//------------------------------------------------------------------------------------
// HS6206.c
//------------------------------------------------------------------------------------
// Copyright 2014, HunterSun Electronics Co., Ltd.
// Yufeng. Yao
// 2014-01-16
//
// Program Description:
//
//
//
#include "uti.h"
#include "HS6220_RF.h"

/* OM6220 模拟SPI(3,4线)接口初始化函数
  已经没有硬件CE的控制脚了，
  IRQ脚根据需要进行配置
*/

void HS6220_SPI_Init(void)
{
  GPIO_InitTypeDef GPIO_InitStruct;            
	
	GPIO_InitStruct.Pin = HS6220_CSN_PIN;           
	GPIO_InitStruct.Mode = MODE_PP_OUT;           
	GPIO_Init(HS6220_CSN_PORT,&GPIO_InitStruct);   
	
	GPIO_InitStruct.Pin = HS6220_SCK_PIN;           
	GPIO_InitStruct.Mode = MODE_PP_OUT;           
	GPIO_Init(HS6220_SCK_PORT,&GPIO_InitStruct);   
		
//	GPIO_InitStruct.Pin = HS6220_MOSI_PIN;           
//	GPIO_InitStruct.Mode = MODE_PP_OUT;           
//	GPIO_Init(HS6220_MOSI_PORT,&GPIO_InitStruct);   

//	GPIO_InitStruct.Pin = HS6220_MISO_PIN;           	
//	GPIO_InitStruct.Mode = MODE_PP_OUT;           	
//	GPIO_Init(HS6220_MISO_PORT,&GPIO_InitStruct);    
	
	GPIO_InitStruct.Pin = HS6220_SDIO_PIN;           	
	GPIO_InitStruct.Mode = MODE_PP_OUT;           	
	GPIO_Init(HS6220_SDIO_PORT,&GPIO_InitStruct);   

	GPIO_InitStruct.Pin = HS6220_IRQ_PIN;            	
	GPIO_InitStruct.Mode = MODE_PU_IN;           	
	GPIO_Init(HS6220_IRQ_PORT,&GPIO_InitStruct);  
	
	HS6220_SDIO_HIGH;
	HS6220_CSN_HIGH;	
	HS6220_SCK_LOW;
}

// 3线SPI写操作函数
void SPI_3wire_sendByte(unsigned char TxData)
{
	unsigned char i;
	unsigned char data_output_bit;
	GPIO_InitTypeDef GPIO_InitStruct;  
	
	GPIO_InitStruct.Pin = HS6220_SDIO_PIN;           	
	GPIO_InitStruct.Mode = MODE_PP_OUT;           	
	GPIO_Init(HS6220_SDIO_PORT,&GPIO_InitStruct); //设置DIO为输出
	
	for(i = 0; i < 8; i ++) 
	{
		data_output_bit = TxData & 0x80 ? 1 : 0;
		HS6220_SCK_LOW;
		if(data_output_bit){
			HS6220_SDIO_HIGH;
		}
		else{
			HS6220_SDIO_LOW;
		}

		HS6220_SCK_HIGH;
//		NOP_DELAY();
		TxData = TxData << 1;
	}

	HS6220_SDIO_LOW;
	HS6220_SCK_LOW;
//	NOP_DELAY();NOP_DELAY();NOP_DELAY();
}

// 3线SPI读操作函数
unsigned char SPI_3wire_readByte(void)
{
	unsigned char bit_ctr;
	unsigned char byte = 0;
	unsigned char temp = 0;
	
	GPIO_InitTypeDef GPIO_InitStruct;  
	
	GPIO_InitStruct.Pin = HS6220_SDIO_PIN;           	
	GPIO_InitStruct.Mode = MODE_FLOATING_IN;           	
	GPIO_Init(HS6220_SDIO_PORT,&GPIO_InitStruct); // 设置DIO为输入
	__NOP;
	__NOP;
	
	for(bit_ctr = 0; bit_ctr < 8; bit_ctr ++) // output 8-bit
	{
		byte = byte << 1;
		HS6220_SCK_HIGH;   
		temp = GPIO_GetBit(HS6220_SDIO_PORT,HS6220_SDIO_PIN);
		byte |= temp;          
		HS6220_SCK_LOW;               
	}

	return (byte); // return read byte
}

// 封装起来的对外可调用的SPI写函数
void SPI_SendByte(unsigned char data)
{
#if (HS6220_SPI_NWIRE == SPI_3_WIRE)
	// 3线SPI写
	SPI_3wire_sendByte(data);
#else
	// 4线SPI读写
	spi_4wire_wrd(data);
#endif
}

// 封装起来的对外可调用的SPI读函数
unsigned char SPI_ReadByte(void)
{
#if (HS6220_SPI_NWIRE == SPI_3_WIRE)
	// 3线SPI读
	return SPI_3wire_readByte();
#else
	// 4线SPI读
	return spi_4wire_wrd(0);
#endif
}

// OM6220写一个寄存器一个值操作函数
void HS6220_write_byte(unsigned char addr,unsigned char D)
{
	HS6220_CSN_LOW;
	SPI_SendByte(HS6220_W_REGISTER | addr);
	SPI_SendByte(D);
	HS6220_CSN_HIGH;
}

// OM6220写一个寄存器多个数值操作函数
void HS6220_wr_buffer(unsigned char addr,const unsigned char* buf,unsigned char len)
{
	HS6220_CSN_LOW;
	SPI_SendByte(HS6220_W_REGISTER | addr);
	while(len--)
	{
		SPI_SendByte(*buf ++);
	}
	HS6220_CSN_HIGH;
}

// OM6220读一个寄存器一个值操作函数
unsigned char HS6220_read_byte(unsigned char addr)
{
	unsigned char rxdata;
	
	HS6220_CSN_LOW;
	SPI_SendByte(HS6220_R_REGISTER | addr);
	rxdata = SPI_ReadByte();
	HS6220_CSN_HIGH;
	
	return(rxdata);
}

// OM6220读一个寄存器多个值操作函数
void HS6220_read_buffer(unsigned char addr, unsigned char* buf, unsigned char len)
{
	HS6220_CSN_LOW;
	SPI_SendByte(HS6220_R_REGISTER | addr);
	
	while(len --)
	{
		*buf ++ = SPI_ReadByte();
	}
	HS6220_CSN_HIGH;
}

// OM6220直接发命令函数
void HS6220_Operation(unsigned char opt)
{	
	HS6220_CSN_LOW;
	SPI_SendByte(opt);
	HS6220_CSN_HIGH;
}


/* OM6220 初始化函数
第一版的模块，只做测试用，初始化的内容还有点多
改第二版之后，有些值会作为默认值，初始化内容就会少很多
*/
void HS6220_Init(void)
{
	unsigned char temp[5];
	HS6220_SPI_Init();

reset_rf_int:	
	HS6220_write_byte(HS6220_BANK0_FEATURE, SOFT_RST); // soft_reset

#if (HS6220_SPI_NWIRE == SPI_4_WIRE) 
	// 默认是3线SPI的，如果要使用4线SPI，则上电之后要设置一下
	HS6220_write_byte(HS6220_BANK0_DYNPD, 0x08);
#else
	HS6220_write_byte(HS6220_BANK0_DYNPD, 0x00);
#endif

	HS6220_CE_Low();	
	HS6220_write_byte(HS6220_BANK0_CONFIG, 0x8b); // power up
	Delay1ms(3); // wait 3 ms
	HS6220_write_byte(HS6220_BANK0_PMU_CTL, 0xac); // HS6220_PWRDWN = 00
	Delay1ms(2);
    
	HS6220_write_byte(HS6220_BANK0_FEATURE, 0x10); // VCO_AMP_TX_MUX = b'0, A2 don't need config this bit

	HS6220_Bank_Switch(HS6220_Bank1);

	HS6220_write_byte(HS6220_BANK1_TEST_PKDET, 0x20); // pll_vdiv2_sel = 01, A2 don't need config this bit
    

	temp[0] = 0x01;
	HS6220_wr_buffer(HS6220_BANK1_FAGC_CTRL_1, temp, 1);
//************电机动作的时候 HS6220_BANK1_FAGC_CTRL_1按以下配置**********要先拉低CE，切换到Bank1去操作*****	
//*********** 6220为了提高抗干扰能力, 提高了 VCO的增益, 而这样做, 也增强了 本振泄露, 过认证又不好过了. 
//**********一个可行的解决办法:  接收小车在 马达转动的时候才提高VCO, 不转的时候恢复原来的值
 /*
	temp[0] = 0x0c;	
	HS6220_wr_buffer(HS6220_BANK1_FAGC_CTRL_1, temp, 1);
*/	
//************电机动作的时候 HS6220_BANK1_FAGC_CTRL_1按以上配置***************	
	
	temp[1] = 0xb2;
	temp[0] = 0xcf;  
	HS6220_wr_buffer(HS6220_BANK1_AGC_CTRL, temp, 2);
	
	HS6220_Bank_Switch(HS6220_Bank0);

	HS6220_CE_High();
	Delay10us(10);
	HS6220_CE_Low(); // 一定要注意，校准的时候CE是低的

	caldone_time = 0;	
	while(1)   //wait cal done
	{
		if((HS6220_read_byte(HS6220_BANK0_RF_SETUP) & 0x20))
		{
			break;
		}
		caldone_time++;	
		delay_ms(1);
		if(caldone_time > 35)
		{
			goto reset_rf_int;
		}
	}
	
	HS6220_write_byte(HS6220_BANK0_RF_SETUP, 0x40);  // cal_en = 0

	HS6220_Bank_Switch(HS6220_Bank1);	

	temp[2] = 0x75;  //bp_dac =1 bp_rc = 1
	temp[1] = 0x98;  // bp_vco_amp = 1 bp_vco_ldo=1
	temp[0] = 0x20;
	HS6220_wr_buffer(HS6220_BANK1_CAL_CTL, temp, 3);

	HS6220_Bank_Switch(HS6220_Bank0);	

	temp[0] = 0x46;
	temp[1] = 0x0b;
	temp[2] = 0xaf;
	temp[3] = 0x43;
	temp[4] = 0x98;	
	HS6220_wr_buffer(HS6220_BANK0_RX_ADDR_P0, temp, 5); // set address

	temp[0]=0x46;
	temp[1]=0x0b;
	temp[2]=0xaf;
	temp[3]=0x43;
	temp[4]=0x98;
	HS6220_wr_buffer(HS6220_BANK0_TX_ADDR, temp, 5);   //set address


	HS6220_write_byte(HS6220_BANK0_FEATURE, 0x10); 
	HS6220_write_byte(HS6220_BANK0_EN_AA, 0x00);
	HS6220_write_byte(HS6220_BANK0_CONFIG, 0xfa);
	HS6220_write_byte(HS6220_BANK0_RX_PW_P0, rx_lenth);
	HS6220_write_byte(HS6220_BANK0_RF_CH, 45);
	HS6220_write_byte(HS6220_BANK0_EN_RXADDR, 0x03); // scramble_en = 0	
	HS6220_write_byte(HS6220_BANK0_RF_SETUP, 0x47);
	HS6220_write_byte(HS6220_BANK0_DYNPD, 0x07);
	
	HS6220_Clear_All_Irq();
	HS6220_Flush_Tx();	
	HS6220_CE_High();
			
}

/*OM6220 读写寄存器函数
 cmd = code; 
 D = data
 */
void HS6220_wr_cmd(unsigned char cmd,unsigned char D)
{
	HS6220_CSN_LOW;
	SPI_SendByte(cmd);
	SPI_SendByte(D);
	HS6220_CSN_HIGH;
}

// 切换OM6220 BANK
void HS6220_Bank_Switch(HS6220_Bank_TypeDef bank)
{
	unsigned char sta;
	
	sta = HS6220_read_byte(HS6220_BANK0_STATUS);
	
	if(bank != HS6220_Bank0)
	{
		if(!(sta & HS6220_Bank1))
		{
			HS6220_wr_cmd(HS6220_ACTIVATE, HS6220_ACTIVATE_DATA);
		}
	}
	else
	{
		if(sta & HS6220_Bank1)
		{
			HS6220_wr_cmd(HS6220_ACTIVATE, HS6220_ACTIVATE_DATA);
		}
	}
}

// OM6220 切换速率
void HS6220_Change_Rate(HS6220_Rate_TypeDef rate)
{
	unsigned char tmp;
	
	tmp = HS6220_read_byte(HS6220_BANK0_RF_SETUP);

	if(rate == Rate_1M)
	{
		tmp &= 0xf7;
		HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
	}
	else if(rate == Rate_2M)
	{
		tmp |= 0x08;
		HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
	}
}

// OM6220 切换信道
void HS6220_Change_CH(unsigned char chn)
{
	if(chn < 0x80)
		HS6220_write_byte(HS6220_BANK0_RF_CH, chn);
}

// OM6220 切换功率
void HS6220_Change_Pwr(HS6220_Pwr_TypeDef pwr)
{
	unsigned char tmp;

	tmp = HS6220_read_byte(HS6220_BANK0_RF_SETUP);
	tmp &= ~0x47;

	switch (pwr)
	{
		case Pwr_8db:
			tmp |= 0x47;
			HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
		break;

		case Pwr_5db:
			tmp |= 0x40;
			HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
		break;

		case Pwr_4db:
			tmp |= 0x07;
			HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
		break;

		case Pwr_0db:
			tmp |= 0x03;
			HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
		break;

		case Pwr_n6db:
			tmp |= 0x01;
			HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
		break;
	
		default: // 默认就设置成0db
			tmp |= 0x03;
			HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
		break;
	}
}

// OM6220 切换地址
void HS6220_Change_Addr(unsigned char *buf, unsigned char len)
{
	if(len <= 6)
	HS6220_wr_buffer(HS6220_BANK0_RX_ADDR_P0, buf, len); // set address
}


/*OM6220 接收数据包函数
buf：读取到的数据存放的地方
return：正常读取之后，返回的是读取到的数据包长度
*/
unsigned char HS6220_ReceivePack(unsigned char *buf)
{
	unsigned char sta;
	unsigned char fifo_sta;
	unsigned char len;

	sta = HS6220_read_byte(HS6220_BANK0_STATUS);

	if(HS6220_STATUS_RX_DR & sta)
	{
		do
		{
			len = HS6220_read_byte(HS6220_R_RX_PL_WID);
			
			if(len <= HS6220_FIFO_MAX_PACK_SIZE)
			{
				HS6220_read_buffer(HS6220_R_RX_PAYLOAD, buf, len);
			}
			else
			{
				HS6220_Flush_Rx();
			}
			
			fifo_sta = HS6220_read_byte(HS6220_BANK0_FIFO_STATUS);
		}while(!(fifo_sta & HS6220_FIFO_STA_RX_EMPTY));/*not empty continue read out*/ 
		
		HS6220_write_byte(HS6220_BANK0_STATUS, sta);/*clear irq*/
		HS6220_Clear_All_Irq();
		HS6220_Flush_Tx();
		HS6220_Flush_Rx();		
		return len;
	}

	if(sta & (HS6220_STATUS_RX_DR | HS6220_STATUS_TX_DS | HS6220_STATUS_MAX_RT))
	{
		HS6220_write_byte(HS6220_BANK0_STATUS, sta);/*clear irq*/
	}
		/* 以下的复位RF和让RF睡眠唤醒的动作是必须的，不可缺少 */	
	if(rf_reset_cnt==0) // 如果300ms都没有收到1包数据，则复位RF重新初始化
	{
		
		HS6220_Init();
		
		rf_reset_cnt=rf_reset_time;		
	}

	if(rf_sleep_cnt==0)// 如果20ms都没有收到1包数据，则让RF睡眠唤醒一次
	{
		
		HS6220_CE_Low();
		HS6220_Flush_Rx();
		HS6220_Clear_All_Irq();
		
		HS6220_write_byte(HS6220_BANK0_PMU_CTL, 0xae);		
		Delay1ms(1);// 这里的1ms延时不可缺少，也不能小 
		HS6220_write_byte(HS6220_BANK0_PMU_CTL, 0xac);
		Delay1ms(1);// 这里的1ms延时不可缺少，也不能小
		HS6220_CE_High(); 
		rf_sleep_cnt=10;
	}
		/* 以上的复位RF和让RF睡眠唤醒的动作是必须的，不可缺少 */	
	return 0;
}


/* OM6220发送数据包函数
  buf:要发送的数据包内容指针 
  len:数据包的长度，从1到32字节 
  cmd: 发送数据包的命令，HS6220_W_TX_PAYLOAD和HS6220_W_TX_PAYLOAD_NOACK
*/
void HS6220_SendPack(unsigned char cmd, unsigned char* buf, unsigned char len)
{
	unsigned char sta;
	
	sta = HS6220_read_byte(HS6220_BANK0_STATUS);
	if(!(sta & HS6220_STATUS_TX_FULL))
	{
		HS6220_wr_buffer(cmd, buf, len);
	}
}

// OM6220 切换RF工作模式函数
void HS6220_ModeSwitch(HS6220_ModeTypeDef mod)
{
	unsigned char tmp;
	
	tmp = HS6220_read_byte(HS6220_BANK0_CONFIG);
	if(mod != HS6220_PRX_Mode)
	{
		tmp &= 0xFE;
	}
	else
	{
		tmp |= 0x01;
	}
	HS6220_write_byte(HS6220_BANK0_CONFIG, tmp);

	if(mod == HS6220_Carrier_Mode)
	{
		tmp = 0Xc7;//0x80 | HS6220_read_byte(HS6220_BANK0_RF_SETUP);
		HS6220_write_byte(HS6220_BANK0_RF_SETUP, tmp);
		/* 注意：最高位为载波使能位，设置了载波模式之后，CE要拉高，载波才会出来；
		   如果不要切换频点，功率等，就不要去在操作RF，否则会看不到载波信号的*/
	}
}

// OM6220 清中断标志
void HS6220_Clear_All_Irq(void)
{
	HS6220_write_byte(HS6220_BANK0_STATUS, 0x70);
}

// OM6220 清空TX FIFO
void HS6220_Flush_Tx(void)
{
	HS6220_Operation(HS6220_FLUSH_TX);
}

// OM6220 清空RX FIFO
void HS6220_Flush_Rx(void)
{
	HS6220_Operation(HS6220_FLUSH_RX);
}

// OM6220 CE拉高
void HS6220_CE_High(void)
{
	HS6220_Operation(HS6220_CMD_CE_HIGH);;
}

// OM6220 CE拉低
void HS6220_CE_Low(void)
{
	HS6220_Operation(HS6220_CMD_CE_LOW);
}

// 读取MO6220接收到的数据包长度的函数
unsigned char HS6220_read_payload_length(void)
{
	return HS6220_read_byte(HS6220_R_RX_PL_WID);
}

