//------------------------------------------------------------------------------------
// HS6206.c
//------------------------------------------------------------------------------------
// Copyright 2014, HunterSun Electronics Co., Ltd.
// Yufeng. Yao
// 2014-01-16
//
// Program Description:
//
//
//

#include "gpio.h"
#include "HS6200_RF.h"
#include "uti.h"
#include <intrins.h>



 /*Calibration config infor*/
unsigned char code HS6200_Calibration_Data[] = 
{
   // Register Addr			DataLenth   Data   
	HS6200_BANK0_CONFIG,	1,			0x03,
	HS6200_BANK0_RF_CH,		1,			0x32,
	HS6200_BANK0_RF_SETUP,	1,			0x47,
	0xFF	// Addr=0xFF, Once read this wrong Addr, data transmit must break
};

unsigned char code HS6200_Calibration_Analog[] = 
{
	// Register Addr			DataLenth   Data  
	HS6200_BANK1_PLL_CTL0,		4,			0x40,0x00,0x10,0xE5, 	
	HS6200_BANK1_CAL_CTL,		5,			0x20,0x08,0x50,0x40,0x50,	
	HS6200_BANK1_IF_FREQ,		3,			0x00,0x00,0x1F,
	HS6200_BANK1_FDEV,			1,			0x20,
	HS6200_BANK1_DAC_CAL_HI,	1,			0x7F,
	HS6200_BANK1_RF_IVGEN,		4,			0x1F,0x64,0x00,0x81,
	0xFF	// Addr=0xFF, Once read this wrong Addr, data transmit must break
};


/*config infor*/
unsigned char code HS6200_Analog_Data[]=
{
	// Register Addr			DataLenth   Data  
	HS6200_BANK1_PLL_CTL0,		4,			0x40,0x01,0x30,0xE1,	
	HS6200_BANK1_PLL_CTL1,		4,			0x00,0x42,0x10,0x01, 
	HS6200_BANK1_CAL_CTL,		5,			0x29,0x89,0x65,0x28,0x50,	
	HS6200_BANK1_RX_CTRL,		4,			0x52,0xC2,0x09,0xAC,	
	
	HS6200_BANK1_FAGC_CTRL_1,	4,			0x80,0x14,0x08,0x29,	
	//RF_BANK1_AGC_GAIN,		    4,	        0x02,0xC1,0xCB,0x1C,
	HS6200_BANK1_RF_IVGEN,		4,			0x1f,0x64,0x00,0x01,
	0xFF	// Addr=0xFF, Once read this wrong Addr, data transmit must break
};

code unsigned char  HS6200_Init_Data[]=
{
	// Register Addr			DataLenth   Data  
	HS6200_BANK0_CONFIG,		1,			0x0e,
	HS6200_BANK0_RX_PW_P1,		1,			16,   //P1通道定长接收16bytes,收APP来的数据
	HS6200_BANK0_DYNPD,			1,			0x3c, //P0通道动态接收   , 兼容蓝牙发送时, P0通道不能设置为动态使能
	HS6200_BANK0_FEATURE,		1,			0x07,
	HS6200_BANK0_SETUP_VALUE,	5,			0x40,0x5A,0x80,0x06,0x00,
	HS6200_BANK0_PRE_GURD,		1,			0x77,
	HS6200_BANK0_EN_AA,			1,			0x00, //P0通道自动应答使能, 兼容蓝牙发送时, 不能自动应答使能
	HS6200_BANK0_EN_RXADDR,		1,			0x03, //P0,P1接收使能
	HS6200_BANK0_SETUP_AW,		1,			0x03,	
	HS6200_BANK0_SETUP_RETR,	1,			0x0F, //P0通道自动重发 15 次
	HS6200_BANK0_RF_CH,			1,			2,   //,
	HS6200_BANK0_RF_SETUP,		1,			0x47,
	HS6200_BANK0_RX_ADDR_P0,	5,			0xc0,0x6E,0x54,0x9C,0x52,//0x55,0x42,0x9C,0x8F,0xC9,  //Default_Rx_Addr,
	HS6200_BANK0_RX_ADDR_P1,	1,			0x55,                    //收APP来的数据
	HS6200_BANK0_TX_ADDR,		5,			0x55,0x42,0x9C,0x8F,0xC9,//0x55,0x6E,0x54,0x9C,0x52,  //Default_Tx_Addr,
	//HS6200_BANK0_RX_ADDR_P0,	5,			0x05,0x0b,0xaf,0x43,0x98,//0x55,0x6E,0x54,0x9C,0x52,  //Default_Rx_Addr,
	//HS6200_BANK0_RX_ADDR_P1,	1,			0x46,                    //收APP来的数据
	//HS6200_BANK0_TX_ADDR,		5,			0x46,0x0b,0xaf,0x43,0x98,  //Default_Tx_Addr,
//	HS6200_BANK0_RX_ADDR_P0,	5,			0x46,0x0b,0xaf,0x43,0x98,  //Default_Rx_Addr,
//	HS6200_BANK0_TX_ADDR,		5,			0x46,0x0b,0xaf,0x43,0x98,  //Default_Tx_Addr,	
	0xFF	// Addr=0xFF, Once read this wrong Addr, data transmit must break
};


/*
void HS6200_SPI_CE_Init(void)
{
	RFCON = RF_CLK_EN+RFSPI_CSN;
    SPIRCON |= (RFSPI_MASK_RX_DATA_RDY_INT+RFSPI_MASK_RX_FIFO_FULL_INT+RFSPI_MASK_TX_FIFO_EMPTY_INT+RFSPI_MASK_TX_FIFO_RDY_INT);
    IEN1 &=~ (BIT0+BIT1);  //disable RFRDY and RFIRQ.
}
*/

// 原三雄分离板子
// 
// SPI_CSN  -- P0.6
// SPI_MISO -- P2.2
// SPI_MOSI -- P2.3
// SPI_SCK  -- P2.4
// RF_CE    -- P2.7
// RF_IRQ   -- P1.0
//
#ifdef split_rf
void HS6200_SPI_Init(void)
{
    P0M3 |= IOL_PUSHPULL_OUT;    //P0.6 output
    P2M1 = IOH_PUSHPULL_OUT | IOL_PULLUP_IN;    //P2.2 pull up input, P2.3 output
    P2M2 |= IOL_PUSHPULL_OUT;    //P2.4 output
    P2M3 |= IOH_PUSHPULL_OUT;    //P2.7 output
    P1M0 |= IOL_PULLUP_IN;       //P1.0 input

	  
	RF_SCK_LOW;
	RF_MOSI_HIGH;
	HS6200_CSN_HIGH;
	RF_SPI_CE_LOW; 
	//RF_SPI_CE_HIGH;  
}
#else

// 合封芯片
// SPI_CSN  -- P2.0
// SPI_MISO -- P0.7
// SPI_MOSI -- P1.0
// SPI_SCK  -- P1.1
// RF_CE    -- P0.5
// RF_IRQ   -- P0.6
//
void HS6200_SPI_Init(void)
{
    P2M0 |= IOL_PUSHPULL_OUT;    //P2.0-CSN output
    P0M3 = IOH_PULLUP_IN | IOL_PULLUP_IN;    //P0.6_IRQ pull up input, P0.7_MISO pull up input
    P0M2 |= IOH_PUSHPULL_OUT;    //P0.5_CE output
    P1M0 |= IOH_PUSHPULL_OUT | IOH_PUSHPULL_OUT;    //P1.0_MOSI output, P1.1_SCK output


	  
	RF_SCK_LOW;
	RF_MOSI_HIGH;
	HS6200_CSN_HIGH;
	RF_SPI_CE_LOW; 
	//RF_SPI_CE_HIGH;

#ifdef  HARDWAVE_SPI	//硬件SPI
	MISO_MAP = 0x07;	            				// SPI_MISO 映射到P07口
	MOSI_MAP = 0x10;	            				// SPI_MOSI 映射到P10口
	SCK_MAP  = 0x11;		               			// SPI_SCK  映射到P11口	
	SPDAT    = 0x00;                       			// 数据寄存器写0
	SPSTAT   = 0x00;                     	 		// 状态寄存器清0  
	SPCTL    = 0xD2;                       			// 主机模式,时钟64分频 		250K
	//SPCTL = 0xD3;                       			// 主机模式,时钟128分频 	125K	
#endif	
}

#endif



/*RFSPI write/read 1 Byte to/from RF */
/*
U8 HS6200_spi_wrd(U8 Byte)
{
    while(!(SPIRSTAT & RFSPI_TX_FIFO_RDY));      //Tx Fifo not ready.
    SPIRDAT=Byte;
    while(!(SPIRSTAT & RFSPI_RX_DATA_RDY));      //Rx Fifo has data.
    return SPIRDAT;
}
*/

//
//RFSPI write/read 1 Byte to/from RF 
//
unsigned char HS6200_spi_wrd(unsigned char Data)
{
#ifdef HARDWAVE_SPI
		SPSTAT = 0xC0;
		SPDAT = Data;
		while(!(SPSTAT & 0x80));
		SPSTAT = 0xC0;
		return SPDAT;	
#else
	unsigned char rxd = 0;
	unsigned char i = 0;
	
	for(i=0;i<16;i++)
	{
		if(i%2)
		{
			if(RF_MISO_HIGH)
			{
				rxd |= 0x01;
			}
			else
			{
				rxd &= 0xFE;
			}
			//delay_us(10);
			RF_SCK_LOW;
		}
		else
		{
			if(Data & 0x80)
			{
				RF_MOSI_HIGH;
			}
			else
			{
				RF_MOSI_LOW;
			}
			rxd <<= 1;
			Data <<= 1; 		
			//delay_us(10);
			RF_SCK_HIGH;
		}
	}
	return rxd;	
#endif	
}

void HS6200_write_byte(unsigned char addr,unsigned char D)
{
	HS6200_CSN_LOW;
	HS6200_spi_wrd(HS6200_WR_REG|addr);
	HS6200_spi_wrd(D);
	HS6200_CSN_HIGH;
}

unsigned char HS6200_read_byte(unsigned char addr)
{
	unsigned char rxdata;
	HS6200_CSN_LOW;
	HS6200_spi_wrd(HS6200_RD_REG|addr);
	rxdata = HS6200_spi_wrd(0);
	HS6200_CSN_HIGH;
	return(rxdata);
}

void HS6200_wr_buffer(unsigned char addr,unsigned char* buf,unsigned char len)
{
	HS6200_CSN_LOW;
	HS6200_spi_wrd(HS6200_WR_REG|addr);
	while(len--)
	{
		HS6200_spi_wrd(*buf++);
	}
	HS6200_CSN_HIGH;
}

void HS6200_read_buffer(unsigned char addr,unsigned char* buf,unsigned char len)
{
	HS6200_CSN_LOW;
	HS6200_spi_wrd(HS6200_RD_REG|addr);
	while(len--)
	{
		*buf++ = HS6200_spi_wrd(0);
	}
	HS6200_CSN_HIGH;
}


void HS6200_wr_cmd(unsigned char cmd,unsigned char D)
{
	HS6200_CSN_LOW;
	HS6200_spi_wrd(cmd);
	HS6200_spi_wrd(D);
	HS6200_CSN_HIGH;
}

unsigned char HS6200_Operation(unsigned char opt)
{	
	unsigned char status;
	HS6200_CSN_LOW;
	status = HS6200_spi_wrd(opt);
	HS6200_CSN_HIGH;
	return status;
}


void HS6200_bank_Switch(HS6200_Bank_TypeDef bank)
{
	unsigned char sta;
	sta =HS6200_read_byte(HS6200_BANK0_STATUS);
	sta =HS6200_read_byte(HS6200_BANK0_STATUS);
	if(bank != HS6200_Bank0)
	{
		if(!(sta & HS6200_BANK1))
			HS6200_wr_cmd(HS6200_ACTIVATE,HS6200_ACTIVATE_DATA);
	}
	else
	{
		if(sta & HS6200_BANK1)
			HS6200_wr_cmd(HS6200_ACTIVATE,HS6200_ACTIVATE_DATA);
	}
}

void HS6200_CE_High(void) 
{ 
    //RFCON |=RFSPI_CE;
    RF_SPI_CE_HIGH;
	//unsigned char preGurd_status[2];
	//HS6200_read_buffer(HS6200_BANK0_PRE_GURD,preGurd_status,0x02); 
	//preGurd_status[1] = preGurd_status[1] & 0x7f; /*set bit15 of HS6200_BANK0_PRE_GURD 0*/ 
	//HS6200_wr_buffer(HS6200_BANK0_PRE_GURD, preGurd_status, 2); 
} 

/* set CE low*/
void HS6200_CE_Low(void) 
{	
	//RFCON &=~RFSPI_CE;
	RF_SPI_CE_LOW;
	//unsigned char preGurd_status[2]; 
	//HS6200_read_buffer(HS6200_BANK0_PRE_GURD,preGurd_status,0x02); 
	//preGurd_status[1] = preGurd_status[1] | 0x80; /*set bit15 of HS6200_BANK0_PRE_GURD 1*/ 
	//HS6200_wr_buffer(HS6200_BANK0_PRE_GURD, preGurd_status, 2);
}

void HS6200_RF_CE_High_Pulse(void)
{
	//RFCON |=RFSPI_CE;
	RF_SPI_CE_HIGH;
	Delay10us(8);
	//RFCON &=~RFSPI_CE;	
	RF_SPI_CE_LOW;
}

void HS6200_Clear_All_Irq(void)
{
	HS6200_write_byte(HS6200_BANK0_STATUS,0x70);
}

void HS6200_Flush_Tx(void)
{
	HS6200_Operation(HS6200_FLUSH_TX);
}

void HS6200_Flush_Rx(void)
{
	HS6200_Operation(HS6200_FLUSH_RX);
}

void HS6200_RF_SOFT_Rst(void)
{
	unsigned char temp[4];
	HS6200_bank_Switch(HS6200_Bank1);
	HS6200_read_buffer(HS6200_BANK1_PLL_CTL1, temp, 4);
	temp[3] |= 0x80;
	HS6200_wr_buffer(HS6200_BANK1_PLL_CTL1,temp,4);
}

unsigned char HS6200_Read_Status(void)
{	
	unsigned char status;
	status = HS6200_Operation(HS6200_READ_STATUS);
	return status;
}

unsigned char HS6200_Read_RX_P_No(void)
{	
	unsigned char status;
	status = HS6200_Operation(HS6200_READ_STATUS);
	status = (status>>1)&0x07;
	return status;
}


void HS6200_ChangeAddr_Reg(unsigned char* AddrBuf,unsigned char len)
{
	
//	HS6200_CE_Low();
	HS6200_wr_buffer((HS6200_WR_REG|HS6200_BANK0_RX_ADDR_P0),AddrBuf,len);
	HS6200_wr_buffer((HS6200_WR_REG|HS6200_BANK0_TX_ADDR),AddrBuf,len);
//	HS6200_CE_High();
}

void HS6200_ChangeTxAddr_Reg(unsigned char* AddrBuf,unsigned char len)
{
	
//	HS6200_CE_Low();
	//HS6200_wr_buffer((HS6200_WR_REG|HS6200_BANK0_RX_ADDR_P0),AddrBuf,len);
	HS6200_wr_buffer((HS6200_WR_REG|HS6200_BANK0_TX_ADDR),AddrBuf,len);
//	HS6200_CE_High();
}

//===============================
//Configuration Reg
//The Data organize format as below
//Register Addr	DataLenth   Data
//1byte			1byte       N Byte   
//================================
void HS6200_configure_Reg(unsigned char *Dbuf)
{
	unsigned char cnt=0;
	unsigned char Reg_Addr;	
	unsigned char data_lenth;
	unsigned char *p_data;

	while(1)
	{
		Reg_Addr=Dbuf[cnt];			//Get Reg_Addr
		cnt+=1;
		data_lenth=Dbuf[cnt];		//Get Data_Lenth
		cnt+=1;
		p_data = &Dbuf[cnt];		//Get Data address
		if(Reg_Addr==0xFF)break;	//Register Addr Error. Break
			HS6200_wr_buffer(Reg_Addr,p_data,data_lenth);// Write buffer
		cnt+=data_lenth;
	}
}


void HS6200_Change_CH(unsigned char ch_index)
{
	unsigned char Temp;
			
	Temp = ch_index;	
	HS6200_CE_Low();
	HS6200_wr_buffer(HS6200_BANK0_RF_CH,&Temp,1);	
	HS6200_CE_High();
}

unsigned char HS6200_Get_Chip_ID(void)
{
	unsigned char ReadArr[2];
	
	HS6200_bank_Switch(HS6200_Bank1);
	HS6200_read_buffer(0x00,ReadArr,2);
	return ReadArr[1];
}
/*Mode_Switch*/

void HS6200_ModeSwitch(HS6200_ModeTypeDef mod)
{
	unsigned char sta;
	HS6200_CE_Low();
	sta = HS6200_read_byte(HS6200_BANK0_CONFIG);
	if(mod != Rf_PRX_Mode)
		sta &= 0xFE;
	else	
		sta |= 0x01;
	HS6200_write_byte(HS6200_BANK0_CONFIG,sta);
	if(mod == Rf_Carrier_Mode)
	{
		HS6200_write_byte(HS6200_BANK0_RF_SETUP,0xc7); /* 0xC7:5dbM for B3&B4,0x83:0dBm for b4,0xc0:0dBm for b3*/
		HS6200_CE_High();
                while(1);
	}
	HS6200_CE_High();
}


/*buf:data buffer; len:[1~32] ; cmd: HS6200_W_TX_PAYLOAD/HS6200_W_TX_PAYLOAD_NOACK*/
void HS6200_SendPack(unsigned char cmd, unsigned char* buf, unsigned char len)
{
	unsigned char sta;
	sta = HS6200_Read_Status();
	if(!(sta&HS6200_STATUS_TX_FULL))
	{
		HS6200_wr_buffer(cmd,buf,len);
	}
}

/*buf:data read from rx buffer*/
unsigned int HS6200_RecivePack(unsigned char* buf)
{
	unsigned char sta,fifo_sta,len;
	
	sta = HS6200_Read_Status();
	if(HS6200_STATUS_RX_DR & sta)
	{
		do
		{
			len = HS6200_read_byte(HS6200_R_RX_PL_WID);
			
			if(len <= HS6200_FIFO_MAX_PACK_SIZE)
				HS6200_read_buffer(HS6200_R_RX_PAYLOAD, buf, len);
			else
				HS6200_Flush_Rx();
			fifo_sta = HS6200_read_byte(HS6200_BANK0_FIFO_STATUS);
		}
		while(!(fifo_sta & HS6200_FIFO_STA_RX_EMPTY));/*not empty continue read out*/
		HS6200_write_byte(HS6200_BANK0_STATUS,sta);	  /*clear irq*/
		return (unsigned int)((sta&0x0e)<<7) | len;
	}

	if(sta & (HS6200_STATUS_RX_DR | HS6200_STATUS_TX_DS | HS6200_STATUS_MAX_RT))
	{
		HS6200_write_byte(HS6200_BANK0_STATUS,sta);	/*clear irq*/
	}
	
	return 0;		
}

/*set Auto_ACK msg*/
void HS6200_Write_Ack_Payload(unsigned char PipeNum, unsigned char *pBuf, unsigned char bytes)
{
	unsigned char byte_ctr;
	HS6200_CSN_LOW;
	HS6200_spi_wrd(HS6200_W_ACK_PAYLOAD | PipeNum); 
	for(byte_ctr=0; byte_ctr<bytes; byte_ctr++)	   
	{                          
    	HS6200_spi_wrd(*pBuf++);
	}
    HS6200_CSN_HIGH;
}


void HS6200_Init(void)
{
	unsigned char  temp[5];

	HS6200_SPI_Init(); //初始化相关端口

    HS6200_RF_SOFT_Rst();
    while(HS6200_Get_Chip_ID() !=0x01){} /*id indicate the version of chip*/

	/*Calibration*/
	HS6200_bank_Switch(HS6200_Bank0);
	HS6200_CE_Low();
	HS6200_configure_Reg(HS6200_Calibration_Data);
	HS6200_bank_Switch(HS6200_Bank1);
	HS6200_configure_Reg(HS6200_Calibration_Analog);
	Delay1ms(3);
	HS6200_bank_Switch(HS6200_Bank0);
	HS6200_CE_High();
	Delay1ms(3);	/* 158uS */
	HS6200_CE_Low();
	Delay1ms(40);	/*must > 40mS*/
	HS6200_bank_Switch(HS6200_Bank1);
	HS6200_configure_Reg(HS6200_Analog_Data);
	HS6200_bank_Switch(HS6200_Bank0);
	HS6200_configure_Reg(HS6200_Init_Data);
	HS6200_write_byte(HS6200_BANK0_STATUS,0x70);
	HS6200_Operation(HS6200_FLUSH_TX);
	HS6200_Operation(HS6200_FLUSH_RX);	
	

	HS6200_bank_Switch(HS6200_Bank1);
	HS6200_read_buffer(HS6200_BANK1_CAL_CTL, temp, 5);
	temp[0] |=0xc0;
	HS6200_wr_buffer(HS6200_BANK1_CAL_CTL, temp, 5);
	HS6200_read_buffer(HS6200_BANK1_PLL_CTL0, temp, 5);
	temp[0] |=0x20;
	HS6200_wr_buffer(HS6200_BANK1_PLL_CTL0, temp, 5);
	HS6200_read_buffer(HS6200_BANK1_DAC_RANGE, temp, 1);
	HS6200_wr_buffer(HS6200_BANK1_DAC_RANGE, temp, 1);
	HS6200_bank_Switch(HS6200_Bank0);	

	HS6200_ModeSwitch(Rf_PRX_Mode);
	//HS6200_ModeSwitch(Rf_Carrier_Mode);
	//while(1);
}

