468 lines
12 KiB
C
468 lines
12 KiB
C
/*--------------------------------------------------------------------------*/
|
||
/**@file bk1080.c
|
||
@brief BK1080收音底层驱动
|
||
@details
|
||
@author
|
||
@date 2011-3-30
|
||
@note
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
|
||
#include "app_config.h"
|
||
|
||
#include "system/includes.h"
|
||
#include "fm/fm_manage.h"
|
||
#include "BK1080.h"
|
||
|
||
#if(TCFG_FM_BK1080_ENABLE && TCHFG_SOFT_I2C_ENABLE)
|
||
|
||
|
||
extern void delay_2ms(int cnt);
|
||
|
||
#define delay_n10ms(x) \
|
||
delay_2ms(x*5)
|
||
|
||
static struct _fm_dev_info *fm_dev_info;
|
||
|
||
/**
|
||
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 必看 @@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||
*@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@@ 必看 @@@@@@@@@@@@@@@@@@@@@@@@@@@
|
||
*
|
||
*BK1080H可以使用外部晶振
|
||
*
|
||
*BK1080E不能使用外部晶振,因此主控需要提供一个时钟
|
||
*BK1080E需要的时钟范围是:32.768kHz~38.4MHz
|
||
*可以通过以下bk1080e_set_clk函数让主控在PA0输出一个24MHz的时钟
|
||
*该函数使用时加到int fm_dev_init(void *_data)函数的第一行
|
||
*该时钟及输出的IO口可配置,如需要可联系原厂提供帮助
|
||
*
|
||
*/
|
||
/* void bk1080e_set_clk(void){ */
|
||
/* JL_PORTA->DIR &= ~BIT(0); */
|
||
/* JL_CLOCK->CLK_CON0 &=~ BIT(12); */
|
||
|
||
/* JL_CLOCK->CLK_CON0 &=~ BIT(11); */
|
||
/* JL_CLOCK->CLK_CON0 |= BIT(10); */
|
||
/* } */
|
||
|
||
|
||
/*------------BK1080 Initialization Table-----------------*/
|
||
/*
|
||
const u16 HW_Reg[]=
|
||
{
|
||
0x0008,
|
||
0x1080,
|
||
#if XTAL_CLOCK //reg2
|
||
0x1201, //for internal crystal clock
|
||
#else
|
||
0x0201, //for extern clock
|
||
#endif
|
||
0x0000,
|
||
0x40C0,
|
||
0x0A1F, //reg5 RSSI[15:8] BAND[7:6] SPACE[5:4],Europe standar
|
||
0x002E,
|
||
0x02FF,
|
||
0x5B11,
|
||
0x0000,
|
||
0x411E,
|
||
0x0000,
|
||
0xCE00,
|
||
0x0000,
|
||
0x0000,
|
||
0x1000, //reg15
|
||
0x0010,
|
||
0x0000,
|
||
0x13FF,
|
||
0x9852,
|
||
0x0000,
|
||
0x0000,
|
||
0x0008,
|
||
0x0000,
|
||
0x51E1,
|
||
0x28DC,
|
||
0x2645,
|
||
0x00E4,
|
||
0x1CD8,
|
||
0x3A50,
|
||
0xEAF0,
|
||
0x3000, //reg31
|
||
0x0200,
|
||
0x0000,
|
||
};
|
||
*/
|
||
|
||
const u16 HW_Reg[] = {
|
||
0x0800,
|
||
0x8010,
|
||
#if XTAL_CLOCK //reg2
|
||
0x0112, //for internal crystal clock
|
||
#else
|
||
0x0142, //for extern clock, system mute
|
||
#endif
|
||
0x0000,
|
||
0xC040,
|
||
0x1F0A, //reg5 RSSI[15:8] BAND[7:6] SPACE[5:4],Europe standar
|
||
0x2E00,
|
||
0xFF02,
|
||
0x115B,
|
||
0x0000,
|
||
0x1E41,
|
||
0x0000,
|
||
0x00CE,
|
||
0x0000,
|
||
0x0000,
|
||
0x0010, //reg15
|
||
0x1000,
|
||
0x0000,
|
||
0xFF13,
|
||
0x5298,
|
||
0x0000,
|
||
0x0000,
|
||
0x0800,
|
||
0x0000,
|
||
0xE151,
|
||
0xDC38,
|
||
0x4526,
|
||
0xE400,
|
||
0xD81C,
|
||
0x503A,
|
||
0xF0EA,
|
||
0x0030, //reg31
|
||
0x0002,
|
||
0x0000,
|
||
};
|
||
|
||
|
||
u8 bk1080_iic_write(u8 w_chip_id, u8 register_address, u8 *buf, u32 data_len)
|
||
{
|
||
u8 ret = 1;
|
||
iic_start(fm_dev_info->iic_hdl);
|
||
if (0 == iic_tx_byte(fm_dev_info->iic_hdl, w_chip_id)) {
|
||
ret = 0;
|
||
log_e("\n fm iic wr err 0\n");
|
||
goto __gcend;
|
||
}
|
||
|
||
delay(fm_dev_info->iic_delay);
|
||
|
||
if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) {
|
||
ret = 0;
|
||
log_e("\n fm iic wr err 1\n");
|
||
goto __gcend;
|
||
}
|
||
u8 *pbuf = buf;
|
||
|
||
while (data_len--) {
|
||
delay(fm_dev_info->iic_delay);
|
||
|
||
if (0 == iic_tx_byte(fm_dev_info->iic_hdl, *pbuf++)) {
|
||
ret = 0;
|
||
log_e("\n fm iic wr err 2\n");
|
||
goto __gcend;
|
||
}
|
||
}
|
||
|
||
__gcend:
|
||
iic_stop(fm_dev_info->iic_hdl);
|
||
|
||
return ret;
|
||
}
|
||
|
||
u8 bk1080_iic_readn(u8 r_chip_id, u8 register_address, u8 *buf, u8 data_len)
|
||
{
|
||
u8 read_len = 0;
|
||
|
||
iic_start(fm_dev_info->iic_hdl);
|
||
if (0 == iic_tx_byte(fm_dev_info->iic_hdl, (r_chip_id & 0x01) ? (r_chip_id - 1) : (r_chip_id))) {
|
||
log_e("\n fm iic rd err 0\n");
|
||
read_len = 0;
|
||
goto __gdend;
|
||
}
|
||
|
||
|
||
delay(fm_dev_info->iic_delay);
|
||
if (0 == iic_tx_byte(fm_dev_info->iic_hdl, register_address)) {
|
||
log_e("\n fm iic rd err 1\n");
|
||
read_len = 0;
|
||
goto __gdend;
|
||
}
|
||
|
||
/* delay(fm_dev_info->iic_delay); */
|
||
/* iic_start(fm_dev_info->iic_hdl); */
|
||
/* if (0 == iic_tx_byte(fm_dev_info->iic_hdl, r_chip_id)) { */
|
||
/* log_e("\n fm iic rd err 2\n"); */
|
||
/* read_len = 0; */
|
||
/* goto __gdend; */
|
||
/* } */
|
||
|
||
delay(fm_dev_info->iic_delay);
|
||
|
||
for (; data_len > 1; data_len--) {
|
||
*buf++ = iic_rx_byte(fm_dev_info->iic_hdl, 1);
|
||
read_len ++;
|
||
}
|
||
|
||
*buf = iic_rx_byte(fm_dev_info->iic_hdl, 0);
|
||
|
||
__gdend:
|
||
|
||
iic_stop(fm_dev_info->iic_hdl);
|
||
delay(fm_dev_info->iic_delay);
|
||
|
||
return read_len;
|
||
}
|
||
|
||
#define app_IIC_write bk1080_iic_write
|
||
#define app_IIC_readn bk1080_iic_readn
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief BK1080读寄存器函数
|
||
@param num 需要的数目
|
||
@return 无
|
||
@note void BEKEN_I2c_Read(u8 reg,u8 *pBuf,u8 num)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void BEKEN_I2c_Read(u8 reg, u8 *pBuf, u8 num)
|
||
{
|
||
reg = reg << 1;
|
||
reg |= 0x01;
|
||
app_IIC_readn(CHIP_DEV_ID, reg, pBuf, num);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief BK1080读寄存器函数
|
||
@param num 需要的数目
|
||
@return 无
|
||
@note void BEKEN_I2c_Write(u8 reg,u8 *pBuf,u8 num)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
static void BEKEN_I2c_Write(u8 reg, u8 *pBuf, u8 num)
|
||
{
|
||
reg = reg << 1;
|
||
app_IIC_write(CHIP_DEV_ID, reg, pBuf, num);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief BK1080 初始化
|
||
@param 无
|
||
@return 无
|
||
@note void init_BK1080(void)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void bk1080_init(void *priv)
|
||
{
|
||
if (priv != NULL) {
|
||
fm_dev_info = priv;
|
||
}
|
||
u8 temp[2];
|
||
//delay_n10ms(100); //delay 1s,please revise delay time according to your MCU
|
||
|
||
BEKEN_I2c_Write(0, (u8 *)HW_Reg, 68); //start from reg2,total 60 byte
|
||
|
||
delay_n10ms(25); //delay 250ms
|
||
temp[0] = HW_Reg[25];
|
||
temp[1] = HW_Reg[25] >> 8;
|
||
temp[1] &= 0x7f;
|
||
BEKEN_I2c_Write(25, temp, 2);
|
||
|
||
temp[1] |= 0x80;
|
||
BEKEN_I2c_Write(25, temp, 2);
|
||
|
||
/* dac_channel_on(FM_IIC_CHANNEL, FADE_ON); */
|
||
|
||
delay_n10ms(5); //delay 50ms
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 设置一个频点 BK1080
|
||
@param curFreq:设置频点
|
||
@return 无
|
||
@note void bk1080_setfreq(u16 curFreq)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void bk1080_setfreq(u16 curFreq)
|
||
{
|
||
u8 curChan;
|
||
u16 temp;
|
||
|
||
curChan = curFreq - (REAL_FREQ_MIN / 10);
|
||
|
||
temp = curChan << 8;
|
||
BEKEN_I2c_Write(0x03, (u8 *)&temp, 2); //write reg3,with 2 bytes
|
||
|
||
temp |= 0x80;
|
||
BEKEN_I2c_Write(0x03, (u8 *)&temp, 2);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 设置一个频点BK1080
|
||
@param fre 频点 875~1080
|
||
@return 1:当前频点有台,0:当前频点无台
|
||
@note bool bk1080_set_fre(u16 freq)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
bool bk1080_set_fre(void *priv, u16 freq)
|
||
{
|
||
static u16 last_tuned_freq;
|
||
static u16 g_last_freq_deviation_value;
|
||
u8 temp[4];
|
||
u16 cur_freq_deviation;
|
||
|
||
bk1080_setfreq(freq);
|
||
delay_n10ms(4); //延时时间>=30ms
|
||
|
||
///////////////////////////////////////////////////////////////////
|
||
//new added 2009-05-30
|
||
|
||
BEKEN_I2c_Read(0x07, temp, 2); //start from reg 0x7,with 2bytes
|
||
|
||
cur_freq_deviation = (temp[0] << 8) | temp[1];
|
||
cur_freq_deviation = cur_freq_deviation >> 4;
|
||
|
||
BEKEN_I2c_Read(0x0a, &temp[2], 2);
|
||
|
||
/////////////////////////////////////////////////////////////////////
|
||
if (temp[2] & 0x10) { //check AFCRL bit12
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
return 0;
|
||
}
|
||
|
||
if (temp[3] < 8) { //RSSI<10 //搜台较少可减少该值,假台较多可增大该值 //8
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
return 0;
|
||
}
|
||
|
||
if ((temp[1] & 0x0f) < 2) { //SNR<2 //搜台较少可减少该值,假台较多可增大该值
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
return 0;
|
||
}
|
||
/////////////////////////////////////////////////////////////////////////
|
||
//add frequency devation check
|
||
if ((cur_freq_deviation >= 192) && (cur_freq_deviation <= (0xfff - 192))) { //0x64 //搜台较少可减少该值,假台较多可增大该值
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
|
||
return 0;
|
||
}
|
||
|
||
///////////////////////////////////////////////////////////////////////////
|
||
//new added 2009-05-30
|
||
if ((freq > 875) && ((freq - last_tuned_freq) == 1)) { //start_freq)&&( (freq-last_tuned_freq)==1) )
|
||
if (g_last_freq_deviation_value & 0x800) {
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
return 0;
|
||
}
|
||
|
||
if (g_last_freq_deviation_value < 150) { //搜台较少可减少该值,假台较多可增大该值
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
if ((freq >= 875) && ((last_tuned_freq - freq) == 1)) { //start_freq)&&( (last_tuned_freq - freq)==1) )
|
||
if ((g_last_freq_deviation_value & 0x800) == 0) {
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
return 0;
|
||
}
|
||
|
||
if (g_last_freq_deviation_value > (0xfff - 150)) { //搜台较少可减少该值,假台较多可增大该值
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
return 0;
|
||
}
|
||
}
|
||
|
||
last_tuned_freq = freq; //save last tuned freqency
|
||
g_last_freq_deviation_value = cur_freq_deviation;
|
||
|
||
return 1;
|
||
}
|
||
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief 关闭 BK1080的电源
|
||
@param 无
|
||
@return 无
|
||
@note void BK1080_PowerDown(void)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void bk1080_powerdown(void *priv)
|
||
{
|
||
u16 temp = 0x4102;
|
||
//temp[0] = 0x02; //write 0x0241 into reg2
|
||
//temp[1] = 0x41;
|
||
BEKEN_I2c_Write(0x02, (u8 *)&temp, 2);
|
||
|
||
/* dac_channel_off(FM_IIC_CHANNEL, FADE_ON); */
|
||
delay_n10ms(5); //delay 50ms
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief FM 模块静音控制
|
||
@param dir:1-mute 0-unmute
|
||
@return 无
|
||
@note void BK1080_mute(dir)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
void bk1080_mute(void *priv, u8 flag)
|
||
{
|
||
u8 TmpData8[2];
|
||
|
||
BEKEN_I2c_Read(2, TmpData8, 2);
|
||
if (flag) {
|
||
TmpData8[0] |= 0x40; //mute
|
||
} else {
|
||
TmpData8[0] &= 0xbf;
|
||
}
|
||
|
||
BEKEN_I2c_Write(2, TmpData8, 2);
|
||
}
|
||
|
||
/*----------------------------------------------------------------------------*/
|
||
/**@brief FM模块检测,获取BK1080 模块ID
|
||
@param 无
|
||
@return 检测到BK1080模块返回1,否则返回0
|
||
@note bool BK1080_Read_ID(void)
|
||
*/
|
||
/*----------------------------------------------------------------------------*/
|
||
bool bk1080_read_id(void *priv)
|
||
{
|
||
u16 bk_id;
|
||
|
||
if (fm_dev_info == NULL) {
|
||
fm_dev_info = (struct _fm_dev_info *)priv;
|
||
}
|
||
|
||
BEKEN_I2c_Read(0x01, (u8 *)&bk_id, 2); //read reg3,with 2 bytes
|
||
|
||
printf("bk1080_read_id %x", bk_id);
|
||
if (0x8010 == bk_id) {
|
||
return TRUE;
|
||
}
|
||
return FALSE;
|
||
}
|
||
|
||
void bk1080_test(void)
|
||
{
|
||
printf("bk1080 test\n");
|
||
}
|
||
|
||
REGISTER_FM(bk1080) = {
|
||
.logo = "bk1080",
|
||
.init = bk1080_init,
|
||
.close = bk1080_powerdown,
|
||
.set_fre = bk1080_set_fre,
|
||
.mute = bk1080_mute,
|
||
.read_id = bk1080_read_id,
|
||
};
|
||
|
||
|
||
#endif
|