|
//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; } |