📄 si4702_rx_fm.c
字号:
/**************************************
Si47XX FM RX part
***************************************/
#include "Si4702_common.h"
extern void RDS_data_process(unsigned char *group_data); //group_data length is 8 bytes
/**************************************
Si4702_Power_Up()
by following setting, channel space = 100
SEEKTH: 0x0c
SKSNR: 0x04
SKCNT: 0x08
after initialization please make sure(FW/B15):
0x00: 0x1242
0x01: 0x080F/0x0A0F
0x07: 0x3C04/0xBC04(external XO)
0x08: 0x0008/0x0006
0x09: 0x0001
revC19:
0x07: 0x3C04/0xBC04(external XO)
0x08: 0x0002
0x09: 0x0000
· For the Si4702-B16: Register 01h = 0800h before powerup, 0850h after powerup.
· For the SI4703-B16: Register 01h = 0800h before powerup, 0A50h after powerup.
· For the SI4702-C19: Register 01h = 1000h before powerup, 1053h after powerup.
· For the Si4703-C19: Register 01h = 1200h before powerup, 1253h after powerup.
***************************************/
T_ERROR_OP Si4702_Power_Up(void)
{
unsigned char Si47XX_reg_data[32];
unsigned char error_ind = 0;
unsigned char Si47XX_power_up[] = {0x40,0x01,0x00,0x00,0x90,0x04,0x0c,0x1f,0x00,0x48};
ResetSi47XX_2w();
//send CMD
error_ind = OperationSi47XX_2w(WRITE, &(Si47XX_power_up[0]), 10);
if(error_ind)
return I2C_ERROR;
DELAY(POWER_SETTLING);
return OK;
}
/**************************************
Si4702_Power_Up_Internal_Crystal()
by following setting, channel space = 100
SEEKTH: 0x0c
SKSNR: 0x04
SKCNT: 0x08
***************************************/
T_ERROR_OP Si4702_Power_Up_Internal_Crystal(void)
{
unsigned char Si47XX_reg_data[32];
unsigned char error_ind = 0;
unsigned char Si47XX_XO_enable[] = {0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x00,0x81};
unsigned char Si47XX_power_up[] = {0x40,0x01,0x00,0x00,0x90,0x04,0x0c,0x1f,0x00,0x48};
ResetSi47XX_2w();
error_ind = OperationSi47XX_2w(WRITE, &(Si47XX_XO_enable[0]), 11);
if(error_ind)
return I2C_ERROR;
DELAY(XO_SETTLING);
//send CMD
error_ind = OperationSi47XX_2w(WRITE, &(Si47XX_power_up[0]), 10);
if(error_ind)
return I2C_ERROR;
DELAY(POWER_SETTLING);
return OK;
}
/**************************************
Si4702_Power_Down()
***************************************/
T_ERROR_OP Si4702_Power_Down(void)
{
unsigned char Si47XX_reg_data[32];
unsigned char error_ind = 0;
unsigned char Si47XX_power_down[] = {0x00,0x41};
unsigned char Si47XX_disable_RDS[] = {0x40,0x01,0x00,0x00,0x00};
/*following RDS disable is just for Si4703 revC19 errata solution 2: disable RDS before disable the tuner*/
//send CMD
error_ind = OperationSi47XX_2w(WRITE, &(Si47XX_disable_RDS[0]), 5);
if(error_ind)
return I2C_ERROR;
//send CMD
error_ind = OperationSi47XX_2w(WRITE, &(Si47XX_power_down[0]), 2);
if(error_ind)
return I2C_ERROR;
DELAY(POWER_SETTLING/4);
return OK;
}
/**************************************
Si4702_Set_Property_FM_Volume()
FM_Volumn: 0~15
***************************************/
T_ERROR_OP Si4702_Set_Property_FM_Volume(unsigned char FM_Volumn)
{
unsigned char Si47XX_reg_data[32];
unsigned char error_ind = 0;
unsigned char Si47XX_set_property[] = {0x40,0x01,0x00,0x00,0x90,0x04,0x0c,0x1f}; //SNR threshold = 0x0006 = 6dB
Si47XX_set_property[7] = (Si47XX_set_property[7] & 0xf0) | FM_Volumn;
error_ind = OperationSi47XX_2w(WRITE, &(Si47XX_set_property[0]), 8);
if(error_ind)
return I2C_ERROR;
return OK;
}
/**************************************
Si4702_Set_Property_FM_Mute()
Enable_Mute: 0/1
***************************************/
T_ERROR_OP Si4702_Set_Property_FM_Mute(unsigned char Enable_Mute)
{
unsigned char Si47XX_reg_data[32];
unsigned char error_ind = 0;
unsigned char Si47XX_set_property[] = {0x40};
if(Enable_Mute)
Si47XX_set_property[0] = 0x00;
else
Si47XX_set_property[0] = 0x40;
error_ind = OperationSi47XX_2w(WRITE, &(Si47XX_set_property[0]), 1);
if(error_ind)
return I2C_ERROR;
}
return OK;
}
/**************************************
Si4702_FM_Get_RSSI()
***************************************/
T_ERROR_OP Si4702_FM_Get_RSSI(unsigned char *pRSSI)
{
unsigned char Si47XX_reg_data[32];
unsigned char error_ind = 0;
error_ind = OperationSi47XX_2w(READ, &(Si47XX_reg_data[0]), 2);
if(error_ind)
return I2C_ERROR;
*pRSSI = Si47XX_reg_data[1];
return OK;
}
/**************************************
Si4702_FM_Tune_Freq()
channel_freq: 8750~10800
channel_space: 50,100,200
***************************************/
T_ERROR_OP Si4702_FM_Tune_Freq(unsigned short channel_freq, unsigned char channel_space)
{
unsigned short freq_reg_data, loop_counter = 0;
unsigned char si4700_reg_data[32];
unsigned char error_ind = 0;
unsigned char si4700_channel_start_tune[] = {0x40,0x01,0x80,0xCA}; //107.7MHz
unsigned char si4700_channel_stop_tune[] = {0x40,0x01,0x00};
//set tune bit
freq_reg_data = (channel_freq - 8750)/(channel_space/10);
si4700_channel_start_tune[3] = freq_reg_data & 0xff;
si4700_channel_start_tune[2] = (si4700_channel_start_tune[2] & 0xfc) | (freq_reg_data >> 8);
error_ind = OperationSi47XX_2w(WRITE, &(si4700_channel_start_tune[0]), 4);
if(error_ind)
return I2C_ERROR;
//wait STC=1
do
{
error_ind = OperationSi47XX_2w(READ, &(si4700_reg_data[0]), 1);
if(error_ind)
return;
loop_counter++;
}
while(((si4700_reg_data[0]&0x40) == 0) && (loop_counter < 0xffff)); //for loop_counter, when tune, the loop time must > 60ms
if(loop_counter == 0xffff)
return LOOP_EXP_ERROR;
loop_counter = 0;
//clear tune bit
error_ind = OperationSi47XX_2w(WRITE, &(si4700_channel_stop_tune[0]), 3);
if(error_ind)
return I2C_ERROR;
//wait STC=0
do
{
error_ind = OperationSi47XX_2w(READ, &(si4700_reg_data[0]), 1);
if(error_ind)
return I2C_ERROR;
loop_counter++;
}
while(((si4700_reg_data[0]&0x40) != 0) && (loop_counter < 0xff));
if(loop_counter >= 0xff)
return LOOP_EXP_ERROR;
return OK;
}
/**************************************
static Si4702_FM_Seek_Start()
channel_space: 50,100,200
***************************************/
static T_ERROR_OP Si4702_FM_Seek_Start(T_SEEK_MODE seek_mode,
unsigned char channel_space,
unsigned short *pChannel_Freq,
unsigned char *SeekFail,
unsigned char *valid_channel)
{
unsigned short freq_reg_data, loop_counter = 0;
unsigned char Si47XX_reg_data[32];
unsigned char error_ind = 0;
unsigned char si4700_channel_seek_start[] = {0x41};
unsigned char si4700_channel_seek_stop[] = {0x40};
switch(seek_mode)
{
case SEEKDOWN_HALT:
{
si4700_channel_seek_start[0] = 0x45;
break;
}
case SEEKDOWN_WRAP:
{
si4700_channel_seek_start[0] = 0x41;
break;
}
case SEEKUP_HALT:
{
si4700_channel_seek_start[0] = 0x47;
break;
}
case SEEKUP_WRAP:
{
si4700_channel_seek_start[0] = 0x43;
break;
}
}
//set seek bit
error_ind = OperationSi47XX_2w(WRITE,&(si4700_channel_seek_start[0]), 1);
if(error_ind)
return I2C_ERROR;
//wait STC=1
do
{
error_ind = OperationSi47XX_2w(READ,&(si4700_reg_data[0]), 1);
if(error_ind)
return I2C_ERROR;
loop_counter++;
}
while(((si4700_reg_data[0]&0x40) == 0) && (loop_counter < 0xffff)); //for loop_counter, when seek, the loop time must > 12s at the worst case
//60ms*((108-87.5)/0.1+1)= 12s
if(loop_counter == 0xffff)
return LOOP_EXP_ERROR;
loop_counter = 0;
if((si4700_reg_data[0]& 0x20) != 0)
*SeekFail = 1;
else
*SeekFail = 0;
//you can check AFC Rail here
if((si4700_reg_data[0]& 0x10) != 0)
*valid_channel = 0;
else
*valid_channel = 1;
//clear seek bit
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -