//SP3767和philips的TEA5767一样
/**
* FL-120BC 收音模块 由TENSUN 深圳金图旭昂通讯科技有限公司
* SP3767HN(the same as Philips' TEA5767HN) by SI-POWER 无锡,低功耗立体声收音电路
* 2006 by Yan taosong<taosong.yan@gmail.com>
*/
#define _SP3767_GLOBALS
#i nclude "fia.h"
#i nclude "sp3767.h"
#i nclude "i2c.h"
/*
苏 徐州市 徐州市 中央人民广播电台
苏 徐州市 徐州市 江苏人民广播电台
苏 徐州市 ?? 徐州电台 94.2
苏 徐州市 徐州市 徐州电台新闻综合频道 1269 93.0
苏 徐州市 徐州市 徐州电台经济台 801 91.6
苏 徐州市 徐州市 徐州电台交通台 103.3
苏 徐州市 徐州市 徐州电台文艺之声 1143 89.6 —
苏 徐州市 贾旺区 —
苏 徐州市 铜山县 铜山人民广播电台 — 94.2 —
苏 徐州市 沛县 沛县 徐州 221600 — —
苏 徐州市 丰县 丰县 徐州 221700 — —
苏 徐州市 邳州市 邳州市 徐州 221300 — —
苏 徐州市 新沂市 新沂人民广播电台 — 99.9 —
苏 徐州市 睢宁县 睢宁县 徐州 221200 — —
*/
/* main.c */
extern AT91PS_SYS AT91_SYS;
extern void mdelay(int ms);
int read_sp3767(char *info ,short len);
int write_sp3767(char *info ,short len);
void enable_search(void);
void disable_search(void);
char sp3767_tx[5];
char sp3767_rx[5] = { 0xff, 0xff, 0xff, 0xff, 0xff};
int write_sp3767(char *info ,short len)
{
struct i2c_msg msgs[2];
unsigned char rw_bit = 0;
int ret;
msgs[0].addr = SP3767_I2C_SLAVE_ADDR;
msgs[0].flags = rw_bit;
/* 无内部地址 */
msgs[0].len = 0;
msgs[0].buf = 0;
msgs[1].addr = SP3767_I2C_SLAVE_ADDR;
msgs[1].flags = rw_bit;
msgs[1].len = len;
msgs[1].buf = info;
ret =at91_i2c_transfer(msgs);
return ret;
}
int read_sp3767(char *info ,short len)
{
struct i2c_msg msgs[2];
unsigned char rw_bit = 1;//i2c read
int ret;
msgs[0].addr = SP3767_I2C_SLAVE_ADDR;
msgs[0].flags = rw_bit;
/* 无内部地址 */
msgs[0].len = 0;
msgs[0].buf = 0;
msgs[1].addr = SP3767_I2C_SLAVE_ADDR;
msgs[1].flags = rw_bit;
msgs[1].len = len;
msgs[1].buf = info;
ret = at91_i2c_transfer(msgs);
return ret;
}
/*
* frq(频率)以62.5Hz为单位,如98.0MHz ,frq = 98000000/62.5=1568000
* div与频率的关系:
* f="87".5MHz ,div = (87500 * 4 + 700 + 225 + 25) / 50;
*/
void set_sp3767_freq(unsigned int frq)
{
unsigned div;
//printk("radio freq = %d.%03d MHz\r\n", frq/16000,(frq/16)%1000);
sp3767_tx[2] = SP3767_PORT1_HIGH;
sp3767_tx[3] = SP3767_PORT2_HIGH | SP3767_HIGH_CUT_CTRL |
SP3767_ST_NOISE_CTL;
//sp3767_tx[4] = 0;
// printk("SP3767 set to stereo\r\n");
// printk("SP3767 radio HIGH LO inject xtal @ 32,768 MHz\r\n");
sp3767_tx[2] |= SP3767_HIGH_LO_INJECT;
sp3767_tx[3] |= SP3767_XTAL_32768;
/* const 700=4000*175 kHz - to adjust freq to right value */
/* 锁相环的参考频率为32.768kHz,所以要>>15,即除以32768
* frq*(4000/16)*/
div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
sp3767_tx[0] |= (div >> 8) & 0x3f;
sp3767_tx[1] = div & 0xff;
write_sp3767(sp3767_tx, 5);
}
void set_sp3767_freq_real(unsigned int frq)
{
unsigned div;
static unsigned char count="0";
frq = frq/62.5;
printk("radio freq = %d.%03d MHz , count:%d\r\n", frq/16000,(frq/16)%1000,count++);
sp3767_tx[2] |= SP3767_PORT1_HIGH;
sp3767_tx[3] |= SP3767_PORT2_HIGH | SP3767_HIGH_CUT_CTRL |
SP3767_ST_NOISE_CTL;
sp3767_tx[4] = 0;
// printk("SP3767 set to stereo\r\n");
// printk("SP3767 radio HIGH LO inject xtal @ 32,768 MHz\r\n");
sp3767_tx[2] |= SP3767_HIGH_LO_INJECT;
sp3767_tx[3] |= SP3767_XTAL_32768;
/* const 700=4000*175 kHz - to adjust freq to right value */
/* 锁相环的参考频率为32.768kHz,所以要>>15,即除以32768
* frq*(4000/16)*/
div = ((frq * (4000 / 16) + 700000 + 225000) + 16384) >> 15;
sp3767_tx[0] |= (div >> 8) & 0x3f;
sp3767_tx[1] = div & 0xff;
write_sp3767(sp3767_tx, 5);
}
void sp3767_auto_search(unsigned int from_frq ,unsigned int to_frq)
{
//float step = 62.5;
unsigned int diff;
unsigned int frq = from_frq;//1400000;//87.5MHz
unsigned div;
unsigned char station = 0;
unsigned char completed = 0;
char buf[5];
//set_sp3767_freq_real(100000000);
for (diff = 0 ;diff < 2000 ;diff ++){
set_sp3767_freq_real(87500000+diff*10000);
enable_search();
read_sp3767(buf ,5);
while(!(buf[0]&0x80)&&!completed){
read_sp3767(buf ,5);
mdelay(20);
//if((buf[0]&0x80))printk("locked \r\n");
if((buf[1]&0x7f)>0x31&&(buf[1]&0x7f)<0x3E){
completed = TRUE;
printk("Locked buf[1]:%x \r\n",(buf[1]&0x7f));
}
}
completed = FALSE;
//mdelay(100);
//disable_search();
mdelay(50);
}
#if 0
enable_search();
from_frq = (unsigned int)((float)from_frq/62.5);
to_frq = (unsigned int)((float)to_frq/62.5);
for (diff = 0 ;diff <= (to_frq - from_frq)/100 && !completed;diff++){
//set_sp3767_freq(from_frq + diff*100);
read_sp3767(buf ,5);
/* RF : 1 ,a band is locked
* 0 ,no band is locked */
//div = ((unsigned)(buf[0]&0x3f)<<8)+(unsigned)buf[1];
//frq = ((((unsigned int)div << 15) - 700000 - 225000 - 16384)*16)/4000;
//printk("%d.%03dMHz ,frq=%d\r\n",frq/16000 ,(frq/16)%1000,frq);
mdelay(20);//400
// div = ((unsigned)(buf[0]&0x3f)<<8)+((unsigned)buf[1])&0x00ff;
// frq = (unsigned int)((((float)( ((unsigned int)div * 32768) - 700000 - 225000 - 16384)*16)/4000)*62.5);
// printk("locked! ,diff:%d,station:%d,frq=%d,[0]:%x,[1]:%x,[2]:%x\r\n",diff,station,frq,buf[0],buf[1],buf[2]);
#if 1
if (buf[0] & SP3767_READY_FLAG_MASK){
station++;
enable_search();
div = ((unsigned)(buf[0]&0x3f)<<8)+(((unsigned)buf[1])&0x00ff);
frq = (unsigned int)((((float)( ((unsigned int)div * 32768) - 700000 - 225000 - 16384)*16)/4000)*62.5);
//printk("%d.%03dMHz band is locked , station = %d\r\n",frq/16000 ,(frq/16)%1000 ,station);
//printk("locked!");
//buf[2]:IF
//set_sp3767_freq_real(frq);
printk("locked! ,diff:%d,station:%d,frq=%d,[0]:%x,[1]:%x,[2]:%x\r\n",diff,station,frq,buf[0],buf[1],buf[2]);
mdelay(200);
//station ++;
}
#endif
/* 先自动搜索5个台试试看 */
//if (station >= 5)
//completed = 1;
}
disable_search();
#endif
}
void turn_on_sp3767(void)
{
sp3767_tx[3] &= (~SP3767_STDBY);
sp3767_tx[0] &= (~SP3767_MUTE);
write_sp3767(sp3767_tx, 5);
printk("Turn on radio.\r\n");
}
/* 待机模式,STBY(standby) */
void turn_off_sp3767(void)
{
sp3767_tx[3] |= SP3767_STDBY;
write_sp3767(sp3767_tx, 5);
}
void enable_search(void)
{
/* Enable search mode */
sp3767_tx[0] |= SP3767_SEARCH;
write_sp3767(sp3767_tx, 5);
}
void disable_search(void)
{
/* Disable search mode */
sp3767_tx[0] &= (~SP3767_SEARCH);
write_sp3767(sp3767_tx, 5);
}
int sp3767_detect(void)
{
read_sp3767(sp3767_rx ,5);
printk("rx[0] = %x ,rx[1] = %x ,rx[2] = %x ,rx[3] = %x ,rx[4] = %x \r\n",sp3767_rx[0],sp3767_rx[1],sp3767_rx[2],sp3767_rx[3],sp3767_rx[4]);
/* Status bytes:
* Byte 4: bit 3:1 : CI (Chip Identification) == 0
* bit 0 : internally set to 0
* Byte 5: bit 7:0 : == 0 */
if (((sp3767_rx[3] & 0x0f) != 0x00) || (sp3767_rx[4] != 0x00)) {
printk("Chip ID is not zero. It is not a SP3767\r\n");
return -1;
}
printk("SP3767 detected.\r\n");
return 0;
}
void AT91F_SP3767_CfgPIO(void)
{
/* I2C configuration */
//AT91_SYS->PIOA_PDR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
//AT91_SYS->PIOA_ASR = AT91C_PA25_TWD | AT91C_PA26_TWCK;
}
int sp3767_init(void)
{
/* 对SP3767所需要的PIO进行初始化 */
AT91F_SP3767_CfgPIO();
/* Detect SP3767 */
if(sp3767_detect()){
printk("Can't find SP3767\r\n");
return -1;
}
/* 静音,非搜索模式 */
sp3767_tx[0] = SP3767_MUTE;
sp3767_tx[1] = 0;
/* 搜索停止标准:搜索模式下禁止 , 立体声 ,左右声道正常 */
//sp3767_tx[2] = 0;
//sp3767_tx[2] = SP3767_PORT1_HIGH;
/* 自动搜索时,由高频往低频搜索(搜索方向) */
sp3767_tx[2] = SP3767_PORT1_HIGH/*|SP3767_SEARCH_UP*/|SP3767_SRCH_HIGH_LVL|SP3767_HIGH_LO_INJECT;
sp3767_tx[3] = SP3767_PORT2_HIGH | SP3767_HIGH_CUT_CTRL |
SP3767_ST_NOISE_CTL|SP3767_XTAL_32768|SP3767_STDBY;
/* 初始化处于待机模式 ,XTAL为32.768KHz */
//sp3767_tx[3] = SP3767_STDBY|SP3767_XTAL_32768;
sp3767_tx[4] = 0;
/* Write SP3767 initial status */
//write_sp3767(sp3767_tx, 5);
return 0;
}
连接:http://www.mcublog.com/blog/user1/11414/archives/2006/16753.html
文章评论(0条评论)
登录后参与讨论