📄 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
***************************************/
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
***************************************/
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_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~10795
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 < 0xff));
if(loop_counter >= 0xff)
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 < 0xfff)); //for loop_counter, when seek, the loop time must > 2s
if(loop_counter >= 0xfff)
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
error_ind = OperationSi47XX_2w(WRITE,&(si4700_channel_seek_stop[0]), 1);
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;
//you can read REG0A&0B for channel number or RSSI here
error_ind = OperationSi47XX_2w(READ,&(si4700_reg_data[0]), 4);
if(error_ind)
return I2C_ERROR;
freq_reg_data = ((Si47XX_reg_data[2] << 8) | Si47XX_reg_data[3])& 0x3ff;
*pChannel_Freq = 8750 + freq_reg_data*(channel_space/10);
return OK;
}
/**************************************
Si4702_FM_Seek()
channel_freq: 8750~10795
channel_space: 50,100,200
***************************************/
T_ERROR_OP Si4702_FM_Seek(T_SEEK_MODE seek_mode,
unsigned char channel_space,
unsigned short *pChannel_Freq,
unsigned char *SeekFail)
{
unsigned char valid_channel;
unsigned short loop_counter = 0;
do
{
if(Si4702_FM_Seek_Start(seek_mode, channel_space, pChannel_Freq, SeekFail, &valid_channel) != OK) return ERROR;
loop_counter++;
}
while((valid_channel == 0) && (loop_counter < 0xff) && (*SeekFail == 0));
if(loop_counter >= 0xff)
return LOOP_EXP_ERROR;
return OK;
}
/**************************************
Si4702_FM_Seek_All()
***************************************/
T_ERROR_OP Si4702_FM_Seek_All(unsigned short *pChannel_All_Array, unsigned char Max_Length, unsigned char *pReturn_Length)
{
unsigned char SeekFail;
unsigned short Channel_Result, Last_Channel = 8750;
*pReturn_Length = 0;
if(Si4702_FM_Tune_Freq(8750, 100) != OK) return ERROR;
while(*pReturn_Length < Max_Length)
{
if(Si4702_FM_Seek(SEEKUP_WRAP, 100, &Channel_Result, &SeekFail) != OK) return ERROR;
if(SeekFail)
{
if(Channel_Result == 8750)
{
if(Si4702_FM_Tune_Freq(10800, 100) != OK) return ERROR;
if(Si4702_FM_Seek(SEEKUP_WRAP, 100, &Channel_Result, &SeekFail) != OK) return ERROR;
if(Channel_Result == 8750)
{
*pChannel_All_Array++ = Channel_Result;
(*pReturn_Length)++;
}
}
return OK;
}
if((Channel_Result) <= Last_Channel)
{
if((Channel_Result) == 8750)
{
*pChannel_All_Array++ = Channel_Result;
(*pReturn_Length)++;
}
return OK;
}
else
{
*pChannel_All_Array++ = Last_Channel = Channel_Result;
(*pReturn_Length)++;
}
}
return OK;
}
/**************************************
Si4702_FM_RDS_ISR()
use standard mode
GPIO2 pull low at least 5ms
RDSR keep high at least 40ms
***************************************/
T_ERROR_OP Si4702_FM_RDS_ISR(void)
{
unsigned char si4700_reg_data[32];
unsigned char error_ind = 0;
//check whether RDSR=1
error_ind = OperationSi47XX_2w(READ, &(si4700_reg_data[0]), 12);
if(error_ind)
return;
if((si4700_reg_data[0]&0x80) != 0)
{
RDS_data_process(&(si4700_reg_data[4]));
}
return OK;
}
/*************************************************
Si4702_FM_Seek_MTK()
only used for MTK search all...
channel_number must from 87.5,87.6,87.7... to 108
if it's invalid station, *Return_RSSI = 0
note: for MTK channel: 875, 876...
*************************************************/
T_ERROR_OP Si4702_FM_Seek_MTK(unsigned short channel_number, unsigned char *Return_RSSI)
{
unsigned char SeekFail;
static unsigned short last_channel_result = 0;
static unsigned char last_channel_rssi;
if(channel_number == 8750)
{
if(Si4702_FM_Tune_Freq(10800, 100) != OK) return ERROR;
last_channel_result = 0;
}
if(last_channel_result > channel_number)
*Return_RSSI = 0;
else if(last_channel_result == channel_number)
*Return_RSSI = last_channel_rssi;
else //if(last_channel_result < channel_number)
{
if(Si4702_FM_Seek(SEEKUP_WRAP, 100, &last_channel_result, &SeekFail) != OK) return ERROR;
if(SeekFail)
{
if(last_channel_result == 10800)
{
if(Si4702_FM_Tune_Freq(10790, 100) != OK) return ERROR;
if(Si4702_FM_Seek(SEEKUP_WRAP, 100, &last_channel_result, &SeekFail) != OK) return ERROR;
if(last_channel_result == 10800)
{
DELAY(1ms);
if(Si4702_FM_Get_RSSI(&last_channel_rssi) != OK) return ERROR;
}
else
last_channel_result = 10810;
}
else
last_channel_result = 10810;
}
else
{
DELAY(1ms);
if(Si4702_FM_Get_RSSI(&last_channel_rssi) != OK) return ERROR;
}
if(last_channel_result > channel_number)
*Return_RSSI = 0;
else if(last_channel_result == channel_number)
*Return_RSSI = last_channel_rssi;
else //if(last_channel_result < channel_number)
{
*Return_RSSI = 0;
last_channel_result = 10810;
}
}
return OK;
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -