在线咨询
eetop公众号 创芯大讲堂 创芯人才网
切换到宽版

EETOP 创芯网论坛 (原名:电子顶级开发网)

手机号码,快捷登录

手机号码,快捷登录

找回密码

  登录   注册  

快捷导航
搜帖子
楼主: snowbird13

大家都用的tea5767模块设计原理和layout

[复制链接]
发表于 2007-9-15 15:41:30 | 显示全部楼层
/*以下是FM.h*/
/****************************************************************************/
/* MODULE:                                                                          */
/*
FM.h
*/  
/****************************************************************************/
/*
*   TCC Version 0.0
*   Copyright (c) telechips, Inc.
*   ALL RIGHTS RESERVED
*/
/****************************************************************************/

//dddxxx
#include "tcc760.h"

#ifdef RADIO_MCU
//#define  fm_pwr_off  HwGDATA_D &= ~(1 << 19) // Fm power off
//#define  fm_pwr_on  HwGDATA_D |= (1 << 19) // Fm power on

#define   mcu_slaveaddr    0x54
#define   COM_RADIO_STATE  0x40
#define   COM_RADIO_FREQ  0x41
#define   RADIO_SET_STERO  0x10
#define   RADIO_SET_PWR   0x20
#define  RADIO_SET_SENS_005 0x00
#define  RADIO_SET_SENS_010 0x80
#define  RADIO_SET_SENS_030 0x40
#define  RADIO_SET_SENS_150 0xc0
#define   RADIO_AUTOSCAN_UP 0x01
#define   RADIO_AUTOSCAN_DOWN 0x02
#define   RADIO_MANUSCAN_UP 0x04
#define   RADIO_MANUSCAN_DOWN 0x08
#define   RADIO_FM    0x00
#define   RADIO_AM    0x01

#define   RADIODELAY    100
enum{
PRESET_MODE_OFF,
PRESET_MODE_ON,
NO_MODE,
MANUAL_ADD_CH
};

#define  off    0
#define  on    1
#define  up    1
#define  down   0

#define MAX_PRESET_NUM 20
typedef struct BANKOFRADIO {
unsigned char IsPreset ;
unsigned char IsStereo;
unsigned short LastUseFMHz;
unsigned short Presetbank[MAX_PRESET_NUM] ;
unsigned char LastUsePresetNum;
unsigned char LastBand;
} FMRADIO;

extern unsigned int fm_khz;
extern FMRADIO RadioData;

extern void  delay720(unsigned int count);
extern void  fm_init(void);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern void fmw_stereo_rtn(unsigned char onoff);

extern void mcu_send_state(void);
extern unsigned char mcu_read_radio_state(void);
extern unsigned int  mcu_read_radio_freq(void);
extern void Radio_manual_scan(unsigned char dir);
extern void Radio_auto_scan(unsigned char dir);

#else
#define  fm_slaveaddr 0xc0    // FM modules slave addr
#define  fm_pwr_off  HwGDATA_A |= (1 << 13); // Fm power off
#define  fm_pwr_on  HwGDATA_A &= ~(1 << 13); // Fm power on

enum{
PRESET_MODE_OFF,
PRESET_MODE_ON,
NO_MODE,
MANUAL_ADD_CH
};

#define  off    0
#define  on    1
#define  up    1
#define  down   0
#define  all_level  0
#define  lo_level  1
#define  mid_level  2
#define  hi_level  3
#define  japan   1  // Japan band
#define  us_eu   0  // US/EU band
#define  xtal_32768  1  // set the x-tal to 32.768 KHz
#define  xtal_13m  0  // set the x-tal to 13 MHz
#define  ref_65_en  1  // 6.5 MHz reference for PLL enabled
#define  ref_65_dis  0  // 6.5 MHz reference not enabled
#define  deemph75  1  // deemphasis time constant is 75 us
#define  deemph50  0  // deemphasis time constant is 50 us

#define  hi_side   1  // FM module's high-side injcetion
#define  lo_side   0  // FM module's low-side injection


// when you do not use the autonomous search mode of the FM module, set the scan level and step
#define  scan_level 6  // the available values are 0 ~ 15
#define  scan_step 100  // KHz unit

extern unsigned int fm_khz;
extern void delay720(unsigned int count);
extern void fm_init(void);
extern void LCD_DisplayChannelForFM(int InputHz);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern unsigned char fm_wr_rtn(unsigned char *ptr);

// Struct for Radio data
#define MAX_PRESET_NUM 20
typedef struct BANKOFRADIO {
unsigned char  IsPreset ;
unsigned char IsStereo;
unsigned short LastUseFMHz;
unsigned short Presetbank[MAX_PRESET_NUM] ;
unsigned char LastUsePresetNum;
} FMRADIO;

extern FMRADIO RadioData;
extern unsigned char fm_wr_byte[5];
extern unsigned char fm_hilo_optimal(unsigned int fm_freq);
extern void fmw_pll_rtn(unsigned char hilo, unsigned int fm_freq);
extern void fmw_all_mute_rtn(unsigned char onoff);
extern unsigned char fm_wr_rtn(unsigned char *ptr);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern void fmw_stereo_rtn(unsigned char onoff);
extern void delay720(unsigned int count);
extern unsigned int fm_auto_scan_detect(unsigned char dir);
extern unsigned char fm_auto_scan(unsigned char dir);
extern void fm_manual_scan(unsigned char dir);
#endif

/****************************************************************************/
/* MODULE:                                                                          */
/* FM.c

*/  
/****************************************************************************/
/*
*   TCC Version 0.0
*   Copyright (c) telechips, Inc.
*   ALL RIGHTS RESERVED
*/
/****************************************************************************/

#include "main.h"
#include "fm/FM.h"
#include "kernel/telechips.h"
#include "i2c/i2c.h"

FMRADIO   RadioData;
#ifdef RADIO_INCLUDE
#ifdef RADIO_MCU
unsigned char radio_state = RADIO_SET_STERO|RADIO_SET_SENS_150;
unsigned int radio_freq ;  
unsigned char command_buff[2];
unsigned char receive_data[2];
unsigned int fm_khz;
unsigned char radio_pwron_counter=0;

void delay720(unsigned int count)
{
  for(;count>0;count--) ;
// 1:0.84, 5:1.36, 10:1.96, 20:3.20, 30:4.48, 60:8.04, 80:10.6, 90:11.6, 100:13
}

void fmw_stand_by_rtn(unsigned char onoff)  //radio power onoff
{
// if(onoff)
//  fm_pwr_on;
// else
//  fm_pwr_off;
if(onoff)
  {
  radio_state &= ~RADIO_SET_PWR;
  radio_pwron_counter=1;
  }
else   radio_state |= RADIO_SET_PWR;
mcu_send_state();

}

void fmw_stereo_rtn(unsigned char onoff)
{

//radio_state &= 0xcf;
//if(onoff)
// radio_state |= RADIO_SET_STERO;
//else   radio_state |= RADIO_SET_MONO;
if(onoff)
  radio_state |= RADIO_SET_STERO;
else   radio_state &= ~RADIO_SET_STERO;
mcu_send_state();
}

unsigned char mcu_rd_rtn(unsigned char subadr,unsigned char *ptr, unsigned char bytes)
{
return (unsigned char)(i2c_read((unsigned int)I2C_FM, (unsigned char)mcu_slaveaddr, subadr, ptr, bytes));
}

unsigned char mcu_wr_rtn(unsigned char subadr,unsigned char *ptr, unsigned char bytes)
{
return (unsigned char)(i2c_write((unsigned int)I2C_FM, (unsigned char)mcu_slaveaddr, subadr, ptr, bytes));
}

void mcu_set_state(unsigned char *com)
{
mcu_wr_rtn(COM_RADIO_STATE,com,1);
}

void mcu_set_freq(unsigned char *com)
{
mcu_wr_rtn(COM_RADIO_FREQ,com,2);
}

void mcu_read_state(unsigned char *com)
{
mcu_rd_rtn(COM_RADIO_STATE,com,1);
}

void mcu_read_freq(unsigned char *com)
{
mcu_rd_rtn(COM_RADIO_FREQ,com,2);
}

void mcu_send_state(void)
{
command_buff[0] = radio_state;
mcu_set_state(command_buff);
}
void mcu_manuscan_up(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_MANUSCAN_UP;
mcu_send_state();
}

void mcu_manuscan_down(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_MANUSCAN_DOWN;
mcu_send_state();
}

void mcu_autoscan_up(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_AUTOSCAN_UP;
mcu_send_state();
}

void mcu_autoscan_down(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_AUTOSCAN_DOWN;
mcu_send_state();
}


void mcu_set_bandfreq(unsigned char band)
{

if(band == RADIO_FM)
  radio_freq = fm_khz/10;
else
  radio_freq = fm_khz | ((unsigned int)(band)<<14);

command_buff[0] = (unsigned char)((radio_freq>>8) & 0xff);
command_buff[1] = (unsigned char)(radio_freq & 0xff);
mcu_set_freq(command_buff);
}

unsigned char mcu_read_radio_state(void)
{
unsigned char temp;

mcu_read_state(receive_data);
temp = receive_data[0];
receive_data[0] = 0;
return temp;
}

unsigned int mcu_read_radio_freq(void)
{
unsigned int temp;
mcu_read_freq(receive_data);
temp = receive_data[0];
temp = (temp<<8) & 0xff00;
temp |= receive_data[1];
receive_data[0] = 0;
receive_data[1] = 0;
return temp;
}

void fm_init(void)
{
//mute fm
fmw_stand_by_rtn(off);
/*
fm_pwr_on;//power on radio
delay720(100);   
fm_khz = 87500;
mcu_set_bandfreq(RADIO_FM);
*/
//unmute fm
}

void fmw_all_mute_rtn(unsigned char onoff)
{
}

void Radio_manual_scan(unsigned char dir)
{
unsigned char status;
unsigned int freq;

if(dir)
  mcu_manuscan_up();
else
  mcu_manuscan_down();

}
void Radio_auto_scan(unsigned char dir)
{
unsigned char status;
unsigned int freq;

if(dir)
  mcu_autoscan_up();
else
  mcu_autoscan_down();
}

#else
unsigned char fm_rd_byte[5] = {0,0,0,0,0}; // Read buf
unsigned char fm_wr_byte[5] = {0,0,0,0,0}; // write but
unsigned int fm_khz;

void delay720(unsigned int count)
{
  for(;count>0;count--) ;
// 1:0.84, 5:1.36, 10:1.96, 20:3.20, 30:4.48, 60:8.04, 80:10.6, 90:11.6, 100:13
}
/* ---------------------------------- Command Function ------------------------------------ */

void fmw_hilo_side_rtn(unsigned char hilo)
{
if(hilo) fm_wr_byte[2] |= 0x10;
else  fm_wr_byte[2] &= 0xef;
}

void fmw_all_mute_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[0] |= 0x80;
else   fm_wr_byte[0] &= 0x7f;
}

void fmw_search_mode_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[0] |= 0x40;
else   fm_wr_byte[0] &= 0xbf;
}

void fmw_search_dir_rtn(unsigned char dir)
{
if(dir) fm_wr_byte[2] |= 0x80;
else fm_wr_byte[2] &= 0x7f;
}

void fmw_search_level_rtn(unsigned char level)
{
switch(level)
{
  case all_level : fm_wr_byte[2] &= 0x9f;
         break;
  case lo_level :  fm_wr_byte[2] &= 0xbf;
         fm_wr_byte[2] |= 0x20;
         break;
  case mid_level : fm_wr_byte[2] |= 0x40;
         fm_wr_byte[2] &= 0xdf;
         break;
  case hi_level  : fm_wr_byte[2] |= 0x60;
         break;
}
}

void fmw_stereo_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] &= 0xf7;
else   fm_wr_byte[2] |= 0x08;
}

void fmw_mute_left_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] |= 0x04;
else   fm_wr_byte[2] &= 0xfb;
}

void fmw_mute_right_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] |= 0x02;
else   fm_wr_byte[2] &= 0xfd;
}

void fmw_stand_by_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x40;
else   fm_wr_byte[3] &= 0xbf;
}

void fmw_band_sel_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x20;
else    fm_wr_byte[3] &= 0xdf;
}

void fmw_xtal_sel_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x10;
else    fm_wr_byte[3] &= 0xef;
}

void fmw_soft_mute_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x08;
else   fm_wr_byte[3] &= 0xf7;
}

void fmw_hcc_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x04;
else   fm_wr_byte[3] &= 0xfb;
}

void fmw_snc_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x02;
else   fm_wr_byte[3] &= 0xfd;
}

void fmw_search_indi_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x01;
else fm_wr_byte[3] &= 0xfe;
}

void fmw_pll_ref_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[4] |= 0x80;
else    fm_wr_byte[4] &= 0x7f;
}

void fmw_deemph_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[4] |= 0x40;
else    fm_wr_byte[4] &= 0xbf;
}

unsigned char fmr_ready_flag_rtn(void)
{
return (unsigned char)((fm_rd_byte[0] >> 7) & 0x01);
}

unsigned char fmr_band_limit_rtn(void)
{
return (unsigned char)((fm_rd_byte[0] >> 6) & 0x01);
}

unsigned short fmr_pll_rtn(void)
{
unsigned short temp = 0;

temp = (unsigned short)((fm_rd_byte[0] & 0x3f) << 8);
temp |= (unsigned short)fm_rd_byte[1];

return temp;
}

unsigned char fmr_stereo_indi_rtn(void)
{
return (unsigned char)((fm_rd_byte[2] >> 7) & 0x01);
}

unsigned char fmr_if_count_rtn(void)
{
return (unsigned char)(fm_rd_byte[2] & 0x7f);
}

unsigned char fmr_level_adc_rtn(void)
{
return (unsigned char)((fm_rd_byte[3] >> 4) & 0x0f);
}

/* ------------------------------ End Command function ------------------------------------- */
unsigned char fm_rd_rtn(unsigned char *ptr)
{
return (unsigned char)(i2c_read((unsigned int)I2C_FM, (unsignedchar)fm_slaveaddr, (char)I2C_SUBADDR_NOUSE, ptr, (unsigned char)5));
}

unsigned char fm_wr_rtn(unsigned char *ptr)
{
return (unsigned char)(i2c_write((unsigned int)I2C_FM, (unsignedchar)fm_slaveaddr, (char)I2C_SUBADDR_NOUSE, ptr, (unsigned char)5));
}

void fmw_pll_rtn(unsigned char hilo, unsigned int fm_freq)
{
unsigned char temp;
unsigned short fm_pll_val = 0;

if(hilo) fm_pll_val = (unsigned short)((4000*(fm_freq+225))/32768); // calc PLL decoder
else  fm_pll_val = (unsigned short)((4000*(fm_freq-225))/32768);

temp = (unsigned char)((fm_pll_val >> 8) & 0x3f);
fm_wr_byte[0] &= 0xc0;
fm_wr_byte[0] |= temp;

temp = (unsigned char)fm_pll_val;
fm_wr_byte[1] = temp;

fmw_hilo_side_rtn(hilo);
}

unsigned char fm_hilo_optimal(unsigned int fm_freq)
{
unsigned char status;
unsigned char temp;
unsigned char levelhigh, levellow;

fmw_pll_rtn(hi_side, fm_freq+450); // Set PLL value High
status = fm_wr_rtn(fm_wr_byte);  // Send Command


        delay720(20000);  
     
status = fm_rd_rtn(fm_rd_byte);  // Read status

levelhigh = fmr_level_adc_rtn(); // Get ADC value
  
fmw_pll_rtn(hi_side, fm_freq-450); // Set PLL value Low
status = fm_wr_rtn(fm_wr_byte);

delay720(20000);  

     
status = fm_rd_rtn(fm_rd_byte);

levellow = fmr_level_adc_rtn();
  
if(levelhigh < levellow) temp = hi_side;
else temp = lo_side;

return temp;
}

void fm_init(void)
{
unsigned char i;
#if 0 /* lhm */
i2c_wr
i2c_clk_hi
i2c_data_hi
#endif /* lhm */
// fm_pwr_on // 20050111

delay720(100);   

fm_khz = 89100; //107700;


fmw_all_mute_rtn(on);     // MUTE OFF
fmw_search_mode_rtn(off);    // OFF SearchMode
fmw_search_dir_rtn(up);     // Search direction is up
fmw_search_level_rtn(mid_level);  // search ADC level is middle
// fmw_search_level_rtn(lo_level);  // search ADC level is middle
fmw_stereo_rtn(on);      // Steleo ON
fmw_mute_left_rtn(off);     // Left force mono off
fmw_mute_right_rtn(off);    // Right force mono 0ff
fmw_stand_by_rtn(on);     // Stanby off
// fmw_band_sel_rtn(japan);    // Japan FM zone
fmw_band_sel_rtn(us_eu);    // Japan FM zone
fmw_xtal_sel_rtn(xtal_32768);   // set the x-tal to 32.768 KHz
fmw_soft_mute_rtn(on);
fmw_hcc_rtn(on);      // HCC ON
fmw_snc_rtn(on);      // SNC ON
fmw_search_indi_rtn(on);    // Pin 14 is output for the ready flag
fmw_pll_ref_rtn(ref_65_dis);   // 6.5Mhz ref. not enable
fmw_deemph_rtn(deemph50);    // deemphasis is 50us

i = fm_hilo_optimal(fm_khz);   // HILO algorithm -> find optimize PLL
fmw_pll_rtn(i, fm_khz);
fmw_all_mute_rtn(off);
i = fm_wr_rtn(fm_wr_byte);
}
/*---------------------------------------- Change Hz and Auto Scan ---------------------------------------- */
void fm_manual_scan(unsigned char dir)
{
unsigned char status;


if(dir)
{
  if(fm_khz >= 108000) fm_khz = 87500;
  else     fm_khz += scan_step;
}
else
{
  if(fm_khz <= 87500) fm_khz = 108000;
  else    fm_khz -= scan_step;
}
        
status = fm_hilo_optimal(fm_khz);
      
fmw_pll_rtn(status, fm_khz);
  
//fmw_all_mute_rtn(off); // TEST

status = fm_wr_rtn(fm_wr_byte);
//LCD_DisplayChannelForFM(fm_khz);

}

unsigned char fm_auto_scan(unsigned char dir)
{
unsigned char status, curlev, curifc;

if(dir)
{
  if(fm_khz >= 108000) fm_khz = 87500;
  else     fm_khz += scan_step;
}
else
{
  if(fm_khz <= 87500) fm_khz = 108000;
  else    fm_khz -= scan_step;
}

//fmw_all_mute_rtn(on); // TEST
status = fm_wr_rtn(fm_wr_byte); // Edit By Jim
status = fm_hilo_optimal(fm_khz);
fmw_pll_rtn(status, fm_khz);
status = fm_wr_rtn(fm_wr_byte);
        
// delay720(20000);
delay720(30000);

     
status = fm_rd_rtn(fm_rd_byte);
curlev = fmr_level_adc_rtn();
curifc = fmr_if_count_rtn();

// LCD_DisplayChannelForFM(fm_khz);

/*
if(fm_khz == 88000)
  fm_khz = 88000;
else if(fm_khz == 89100)
  fm_khz = 89100;
else if(fm_khz == 89700)
  fm_khz = 89700;
else if(fm_khz == 91900)
  fm_khz = 91900;
else if(fm_khz == 93100)
  fm_khz = 93100;
else if(fm_khz == 93900)
  fm_khz = 93900;
else if(fm_khz == 95100)
  fm_khz = 95100;
else if(fm_khz == 95700)
  fm_khz = 95700;
else if(fm_khz == 95900)
  fm_khz = 95900;
else if(fm_khz == 97300)
  fm_khz = 97300;
else if(fm_khz == 98100)
  fm_khz = 98100;
else if(fm_khz == 99100)
  fm_khz = 99100;
else if(fm_khz == 99600)
  fm_khz = 99600;
else if(fm_khz == 100000)
  fm_khz = 100000;
else if(fm_khz == 101100)
  fm_khz = 101100;
else if(fm_khz == 101900)
  fm_khz = 101900;
else if(fm_khz == 102700)
  fm_khz = 102700;
else if(fm_khz == 103500)
  fm_khz = 103500;
else if(fm_khz == 105300)
  fm_khz = 105300;
else if(fm_khz == 106100)
  fm_khz = 106100;
else if(fm_khz == 106900)
  fm_khz = 106900;
else if(fm_khz == 107700)
  fm_khz = 107700;
*/
// if((curlev > 3) && (0x30 < curifc) && (curifc < 0x3c)  ) return 1; // scan_level
if((curlev > 3) && (0x30 < curifc) && (curifc < 0x3c)  ) return 1; // scan_level
else
  return 0;
}

unsigned int fm_auto_scan_detect(unsigned char dir)
{
unsigned char status, i;
unsigned char index = 1; // Edit By Jim

unsigned int dumy_fm_khz = fm_khz;


for(i=0;i<10;i++)
{
  if(fm_auto_scan(dir)) index++;
  else break;
}
   
if(index%2)
{
  if(dir) fm_khz = dumy_fm_khz + (unsigned int)((index/2)*100);
  else    fm_khz = dumy_fm_khz - (unsigned int)((index/2)*100);
}
else
{
  if(dir) fm_khz = dumy_fm_khz + (unsigned int)(((index/2)-1)*100);
  else    fm_khz = dumy_fm_khz - (unsigned int)((index/2)*100);
}

status = fm_hilo_optimal(fm_khz);
fmw_pll_rtn(status, fm_khz);
//fmw_all_mute_rtn(off);  TEST

status = fm_wr_rtn(fm_wr_byte);
         
// LCD_ClearOneLine(2);
// lcd_var(0, 2, fm_khz);
// LCD_DisplayChannelForFM(fm_khz);
return fm_khz;
}
#endif
#endif

/*以下是FM.h*/
/****************************************************************************/
/* MODULE:                                                                          */
/*
FM.h
*/  
/****************************************************************************/
/*
*   TCC Version 0.0
*   Copyright (c) telechips, Inc.
*   ALL RIGHTS RESERVED
*/
/****************************************************************************/

//dddxxx
#include "tcc760.h"

#ifdef RADIO_MCU
//#define  fm_pwr_off  HwGDATA_D &= ~(1 << 19) // Fm power off
//#define  fm_pwr_on  HwGDATA_D |= (1 << 19) // Fm power on

#define   mcu_slaveaddr    0x54
#define   COM_RADIO_STATE  0x40
#define   COM_RADIO_FREQ  0x41
#define   RADIO_SET_STERO  0x10
#define   RADIO_SET_PWR   0x20
#define  RADIO_SET_SENS_005 0x00
#define  RADIO_SET_SENS_010 0x80
#define  RADIO_SET_SENS_030 0x40
#define  RADIO_SET_SENS_150 0xc0
#define   RADIO_AUTOSCAN_UP 0x01
#define   RADIO_AUTOSCAN_DOWN 0x02
#define   RADIO_MANUSCAN_UP 0x04
#define   RADIO_MANUSCAN_DOWN 0x08
#define   RADIO_FM    0x00
#define   RADIO_AM    0x01

#define   RADIODELAY    100
enum{
PRESET_MODE_OFF,
PRESET_MODE_ON,
NO_MODE,
MANUAL_ADD_CH
};

#define  off    0
#define  on    1
#define  up    1
#define  down   0

#define MAX_PRESET_NUM 20
typedef struct BANKOFRADIO {
unsigned char IsPreset ;
unsigned char IsStereo;
unsigned short LastUseFMHz;
unsigned short Presetbank[MAX_PRESET_NUM] ;
unsigned char LastUsePresetNum;
unsigned char LastBand;
} FMRADIO;

extern unsigned int fm_khz;
extern FMRADIO RadioData;

extern void  delay720(unsigned int count);
extern void  fm_init(void);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern void fmw_stereo_rtn(unsigned char onoff);

extern void mcu_send_state(void);
extern unsigned char mcu_read_radio_state(void);
extern unsigned int  mcu_read_radio_freq(void);
extern void Radio_manual_scan(unsigned char dir);
extern void Radio_auto_scan(unsigned char dir);

#else
#define  fm_slaveaddr 0xc0    // FM modules slave addr
#define  fm_pwr_off  HwGDATA_A |= (1 << 13); // Fm power off
#define  fm_pwr_on  HwGDATA_A &= ~(1 << 13); // Fm power on

enum{
PRESET_MODE_OFF,
PRESET_MODE_ON,
NO_MODE,
MANUAL_ADD_CH
};

#define  off    0
#define  on    1
#define  up    1
#define  down   0
#define  all_level  0
#define  lo_level  1
#define  mid_level  2
#define  hi_level  3
#define  japan   1  // Japan band
#define  us_eu   0  // US/EU band
#define  xtal_32768  1  // set the x-tal to 32.768 KHz
#define  xtal_13m  0  // set the x-tal to 13 MHz
#define  ref_65_en  1  // 6.5 MHz reference for PLL enabled
#define  ref_65_dis  0  // 6.5 MHz reference not enabled
#define  deemph75  1  // deemphasis time constant is 75 us
#define  deemph50  0  // deemphasis time constant is 50 us

#define  hi_side   1  // FM module's high-side injcetion
#define  lo_side   0  // FM module's low-side injection


// when you do not use the autonomous search mode of the FM module, set the scan level and step
#define  scan_level 6  // the available values are 0 ~ 15
#define  scan_step 100  // KHz unit

extern unsigned int fm_khz;
extern void delay720(unsigned int count);
extern void fm_init(void);
extern void LCD_DisplayChannelForFM(int InputHz);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern unsigned char fm_wr_rtn(unsigned char *ptr);

// Struct for Radio data
#define MAX_PRESET_NUM 20
typedef struct BANKOFRADIO {
unsigned char  IsPreset ;
unsigned char IsStereo;
unsigned short LastUseFMHz;
unsigned short Presetbank[MAX_PRESET_NUM] ;
unsigned char LastUsePresetNum;
} FMRADIO;

extern FMRADIO RadioData;
extern unsigned char fm_wr_byte[5];
extern unsigned char fm_hilo_optimal(unsigned int fm_freq);
extern void fmw_pll_rtn(unsigned char hilo, unsigned int fm_freq);
extern void fmw_all_mute_rtn(unsigned char onoff);
extern unsigned char fm_wr_rtn(unsigned char *ptr);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern void fmw_stereo_rtn(unsigned char onoff);
extern void delay720(unsigned int count);
extern unsigned int fm_auto_scan_detect(unsigned char dir);
extern unsigned char fm_auto_scan(unsigned char dir);
extern void fm_manual_scan(unsigned char dir);
#endif

/****************************************************************************/
/* MODULE:                                                                          */
/* FM.c

*/  
/****************************************************************************/
/*
*   TCC Version 0.0
*   Copyright (c) telechips, Inc.
*   ALL RIGHTS RESERVED
*/
/****************************************************************************/

#include "main.h"
#include "fm/FM.h"
#include "kernel/telechips.h"
#include "i2c/i2c.h"

FMRADIO   RadioData;
#ifdef RADIO_INCLUDE
#ifdef RADIO_MCU
unsigned char radio_state = RADIO_SET_STERO|RADIO_SET_SENS_150;
unsigned int radio_freq ;  
unsigned char command_buff[2];
unsigned char receive_data[2];
unsigned int fm_khz;
unsigned char radio_pwron_counter=0;

void delay720(unsigned int count)
{
  for(;count>0;count--) ;
// 1:0.84, 5:1.36, 10:1.96, 20:3.20, 30:4.48, 60:8.04, 80:10.6, 90:11.6, 100:13
}

void fmw_stand_by_rtn(unsigned char onoff)  //radio power onoff
{
// if(onoff)
//  fm_pwr_on;
// else
//  fm_pwr_off;
if(onoff)
  {
  radio_state &= ~RADIO_SET_PWR;
  radio_pwron_counter=1;
  }
else   radio_state |= RADIO_SET_PWR;
mcu_send_state();

}

void fmw_stereo_rtn(unsigned char onoff)
{

//radio_state &= 0xcf;
//if(onoff)
// radio_state |= RADIO_SET_STERO;
//else   radio_state |= RADIO_SET_MONO;
if(onoff)
  radio_state |= RADIO_SET_STERO;
else   radio_state &= ~RADIO_SET_STERO;
mcu_send_state();
}

unsigned char mcu_rd_rtn(unsigned char subadr,unsigned char *ptr, unsigned char bytes)
{
return (unsigned char)(i2c_read((unsigned int)I2C_FM, (unsigned char)mcu_slaveaddr, subadr, ptr, bytes));
}

unsigned char mcu_wr_rtn(unsigned char subadr,unsigned char *ptr, unsigned char bytes)
{
return (unsigned char)(i2c_write((unsigned int)I2C_FM, (unsigned char)mcu_slaveaddr, subadr, ptr, bytes));
}

void mcu_set_state(unsigned char *com)
{
mcu_wr_rtn(COM_RADIO_STATE,com,1);
}

void mcu_set_freq(unsigned char *com)
{
mcu_wr_rtn(COM_RADIO_FREQ,com,2);
}

void mcu_read_state(unsigned char *com)
{
mcu_rd_rtn(COM_RADIO_STATE,com,1);
}

void mcu_read_freq(unsigned char *com)
{
mcu_rd_rtn(COM_RADIO_FREQ,com,2);
}

void mcu_send_state(void)
{
command_buff[0] = radio_state;
mcu_set_state(command_buff);
}
void mcu_manuscan_up(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_MANUSCAN_UP;
mcu_send_state();
}

void mcu_manuscan_down(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_MANUSCAN_DOWN;
mcu_send_state();
}

void mcu_autoscan_up(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_AUTOSCAN_UP;
mcu_send_state();
}

void mcu_autoscan_down(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_AUTOSCAN_DOWN;
mcu_send_state();
}


void mcu_set_bandfreq(unsigned char band)
{

if(band == RADIO_FM)
  radio_freq = fm_khz/10;
else
  radio_freq = fm_khz | ((unsigned int)(band)<<14);

command_buff[0] = (unsigned char)((radio_freq>>8) & 0xff);
command_buff[1] = (unsigned char)(radio_freq & 0xff);
mcu_set_freq(command_buff);
}

unsigned char mcu_read_radio_state(void)
{
unsigned char temp;

mcu_read_state(receive_data);
temp = receive_data[0];
receive_data[0] = 0;
return temp;
}

unsigned int mcu_read_radio_freq(void)
{
unsigned int temp;
mcu_read_freq(receive_data);
temp = receive_data[0];
temp = (temp<<8) & 0xff00;
temp |= receive_data[1];
receive_data[0] = 0;
receive_data[1] = 0;
return temp;
}

void fm_init(void)
{
//mute fm
fmw_stand_by_rtn(off);
/*
fm_pwr_on;//power on radio
delay720(100);   
fm_khz = 87500;
mcu_set_bandfreq(RADIO_FM);
*/
//unmute fm
}

void fmw_all_mute_rtn(unsigned char onoff)
{
}

void Radio_manual_scan(unsigned char dir)
{
unsigned char status;
unsigned int freq;

if(dir)
  mcu_manuscan_up();
else
  mcu_manuscan_down();

}
void Radio_auto_scan(unsigned char dir)
{
unsigned char status;
unsigned int freq;

if(dir)
  mcu_autoscan_up();
else
  mcu_autoscan_down();
}

#else
unsigned char fm_rd_byte[5] = {0,0,0,0,0}; // Read buf
unsigned char fm_wr_byte[5] = {0,0,0,0,0}; // write but
unsigned int fm_khz;

void delay720(unsigned int count)
{
  for(;count>0;count--) ;
// 1:0.84, 5:1.36, 10:1.96, 20:3.20, 30:4.48, 60:8.04, 80:10.6, 90:11.6, 100:13
}
/* ---------------------------------- Command Function ------------------------------------ */

void fmw_hilo_side_rtn(unsigned char hilo)
{
if(hilo) fm_wr_byte[2] |= 0x10;
else  fm_wr_byte[2] &= 0xef;
}

void fmw_all_mute_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[0] |= 0x80;
else   fm_wr_byte[0] &= 0x7f;
}

void fmw_search_mode_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[0] |= 0x40;
else   fm_wr_byte[0] &= 0xbf;
}

void fmw_search_dir_rtn(unsigned char dir)
{
if(dir) fm_wr_byte[2] |= 0x80;
else fm_wr_byte[2] &= 0x7f;
}

void fmw_search_level_rtn(unsigned char level)
{
switch(level)
{
  case all_level : fm_wr_byte[2] &= 0x9f;
         break;
  case lo_level :  fm_wr_byte[2] &= 0xbf;
         fm_wr_byte[2] |= 0x20;
         break;
  case mid_level : fm_wr_byte[2] |= 0x40;
         fm_wr_byte[2] &= 0xdf;
         break;
  case hi_level  : fm_wr_byte[2] |= 0x60;
         break;
}
}

void fmw_stereo_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] &= 0xf7;
else   fm_wr_byte[2] |= 0x08;
}

void fmw_mute_left_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] |= 0x04;
else   fm_wr_byte[2] &= 0xfb;
}

void fmw_mute_right_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] |= 0x02;
else   fm_wr_byte[2] &= 0xfd;
}

void fmw_stand_by_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x40;
else   fm_wr_byte[3] &= 0xbf;
}

void fmw_band_sel_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x20;
else    fm_wr_byte[3] &= 0xdf;
}

void fmw_xtal_sel_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x10;
else    fm_wr_byte[3] &= 0xef;
}

void fmw_soft_mute_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x08;
else   fm_wr_byte[3] &= 0xf7;
}

void fmw_hcc_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x04;
else   fm_wr_byte[3] &= 0xfb;
}

void fmw_snc_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x02;
else   fm_wr_byte[3] &= 0xfd;
}

void fmw_search_indi_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x01;
else fm_wr_byte[3] &= 0xfe;
}

void fmw_pll_ref_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[4] |= 0x80;
else    fm_wr_byte[4] &= 0x7f;
}

void fmw_deemph_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[4] |= 0x40;
else    fm_wr_byte[4] &= 0xbf;
}

unsigned char fmr_ready_flag_rtn(void)
{
return (unsigned char)((fm_rd_byte[0] >> 7) & 0x01);
}

unsigned char fmr_band_limit_rtn(void)
{
return (unsigned char)((fm_rd_byte[0] >> 6) & 0x01);
}

unsigned short fmr_pll_rtn(void)
{
unsigned short temp = 0;

temp = (unsigned short)((fm_rd_byte[0] & 0x3f) << 8);
temp |= (unsigned short)fm_rd_byte[1];

return temp;
}

unsigned char fmr_stereo_indi_rtn(void)
{
return (unsigned char)((fm_rd_byte[2] >> 7) & 0x01);
}

unsigned char fmr_if_count_rtn(void)
{
return (unsigned char)(fm_rd_byte[2] & 0x7f);
}

unsigned char fmr_level_adc_rtn(void)
{
return (unsigned char)((fm_rd_byte[3] >> 4) & 0x0f);
}

/* ------------------------------ End Command function ------------------------------------- */
unsigned char fm_rd_rtn(unsigned char *ptr)
{
return (unsigned char)(i2c_read((unsigned int)I2C_FM, (unsignedchar)fm_slaveaddr, (char)I2C_SUBADDR_NOUSE, ptr, (unsigned char)5));
}

unsigned char fm_wr_rtn(unsigned char *ptr)
{
return (unsigned char)(i2c_write((unsigned int)I2C_FM, (unsignedchar)fm_slaveaddr, (char)I2C_SUBADDR_NOUSE, ptr, (unsigned char)5));
}

void fmw_pll_rtn(unsigned char hilo, unsigned int fm_freq)
{
unsigned char temp;
unsigned short fm_pll_val = 0;

if(hilo) fm_pll_val = (unsigned short)((4000*(fm_freq+225))/32768); // calc PLL decoder
else  fm_pll_val = (unsigned short)((4000*(fm_freq-225))/32768);

temp = (unsigned char)((fm_pll_val >> 8) & 0x3f);
fm_wr_byte[0] &= 0xc0;
fm_wr_byte[0] |= temp;

temp = (unsigned char)fm_pll_val;
fm_wr_byte[1] = temp;

fmw_hilo_side_rtn(hilo);
}

unsigned char fm_hilo_optimal(unsigned int fm_freq)
{
unsigned char status;
unsigned char temp;
unsigned char levelhigh, levellow;

fmw_pll_rtn(hi_side, fm_freq+450); // Set PLL value High
status = fm_wr_rtn(fm_wr_byte);  // Send Command


        delay720(20000);  
     
status = fm_rd_rtn(fm_rd_byte);  // Read status

levelhigh = fmr_level_adc_rtn(); // Get ADC value
  
fmw_pll_rtn(hi_side, fm_freq-450); // Set PLL value Low
status = fm_wr_rtn(fm_wr_byte);

delay720(20000);  

     
status = fm_rd_rtn(fm_rd_byte);

levellow = fmr_level_adc_rtn();
  
if(levelhigh < levellow) temp = hi_side;
else temp = lo_side;

return temp;
}

void fm_init(void)
{
unsigned char i;
#if 0 /* lhm */
i2c_wr
i2c_clk_hi
i2c_data_hi
#endif /* lhm */
// fm_pwr_on // 20050111

delay720(100);   

fm_khz = 89100; //107700;


fmw_all_mute_rtn(on);     // MUTE OFF
fmw_search_mode_rtn(off);    // OFF SearchMode
fmw_search_dir_rtn(up);     // Search direction is up
fmw_search_level_rtn(mid_level);  // search ADC level is middle
// fmw_search_level_rtn(lo_level);  // search ADC level is middle
fmw_stereo_rtn(on);      // Steleo ON
fmw_mute_left_rtn(off);     // Left force mono off
fmw_mute_right_rtn(off);    // Right force mono 0ff
fmw_stand_by_rtn(on);     // Stanby off
// fmw_band_sel_rtn(japan);    // Japan FM zone
fmw_band_sel_rtn(us_eu);    // Japan FM zone
fmw_xtal_sel_rtn(xtal_32768);   // set the x-tal to 32.768 KHz
fmw_soft_mute_rtn(on);
fmw_hcc_rtn(on);      // HCC ON
fmw_snc_rtn(on);      // SNC ON
fmw_search_indi_rtn(on);    // Pin 14 is output for the ready flag
fmw_pll_ref_rtn(ref_65_dis);   // 6.5Mhz ref. not enable
fmw_deemph_rtn(deemph50);    // deemphasis is 50us

i = fm_hilo_optimal(fm_khz);   // HILO algorithm -> find optimize PLL
fmw_pll_rtn(i, fm_khz);
fmw_all_mute_rtn(off);
i = fm_wr_rtn(fm_wr_byte);
}
/*---------------------------------------- Change Hz and Auto Scan ---------------------------------------- */
void fm_manual_scan(unsigned char dir)
{
unsigned char status;


if(dir)
{
  if(fm_khz >= 108000) fm_khz = 87500;
  else     fm_khz += scan_step;
}
else
{
  if(fm_khz <= 87500) fm_khz = 108000;
  else    fm_khz -= scan_step;
}
        
status = fm_hilo_optimal(fm_khz);
      
fmw_pll_rtn(status, fm_khz);
  
//fmw_all_mute_rtn(off); // TEST

status = fm_wr_rtn(fm_wr_byte);
//LCD_DisplayChannelForFM(fm_khz);

}

unsigned char fm_auto_scan(unsigned char dir)
{
unsigned char status, curlev, curifc;

if(dir)
{
  if(fm_khz >= 108000) fm_khz = 87500;
  else     fm_khz += scan_step;
}
else
{
  if(fm_khz <= 87500) fm_khz = 108000;
  else    fm_khz -= scan_step;
}

//fmw_all_mute_rtn(on); // TEST
status = fm_wr_rtn(fm_wr_byte); // Edit By Jim
status = fm_hilo_optimal(fm_khz);
fmw_pll_rtn(status, fm_khz);
status = fm_wr_rtn(fm_wr_byte);
        
// delay720(20000);
delay720(30000);

     
status = fm_rd_rtn(fm_rd_byte);
curlev = fmr_level_adc_rtn();
curifc = fmr_if_count_rtn();

// LCD_DisplayChannelForFM(fm_khz);

/*
if(fm_khz == 88000)
  fm_khz = 88000;
else if(fm_khz == 89100)
  fm_khz = 89100;
else if(fm_khz == 89700)
  fm_khz = 89700;
else if(fm_khz == 91900)
  fm_khz = 91900;
else if(fm_khz == 93100)
  fm_khz = 93100;
else if(fm_khz == 93900)
  fm_khz = 93900;
else if(fm_khz == 95100)
  fm_khz = 95100;
else if(fm_khz == 95700)
  fm_khz = 95700;
else if(fm_khz == 95900)
  fm_khz = 95900;
else if(fm_khz == 97300)
  fm_khz = 97300;
else if(fm_khz == 98100)
  fm_khz = 98100;
else if(fm_khz == 99100)
  fm_khz = 99100;
else if(fm_khz == 99600)
  fm_khz = 99600;
else if(fm_khz == 100000)
  fm_khz = 100000;
else if(fm_khz == 101100)
  fm_khz = 101100;
else if(fm_khz == 101900)
  fm_khz = 101900;
else if(fm_khz == 102700)
  fm_khz = 102700;
else if(fm_khz == 103500)
  fm_khz = 103500;
else if(fm_khz == 105300)
  fm_khz = 105300;
else if(fm_khz == 106100)
  fm_khz = 106100;
else if(fm_khz == 106900)
  fm_khz = 106900;
else if(fm_khz == 107700)
  fm_khz = 107700;
*/
// if((curlev > 3) && (0x30 < curifc) && (curifc < 0x3c)  ) return 1; // scan_level
if((curlev > 3) && (0x30 < curifc) && (curifc < 0x3c)  ) return 1; // scan_level
else
  return 0;
}

unsigned int fm_auto_scan_detect(unsigned char dir)
{
unsigned char status, i;
unsigned char index = 1; // Edit By Jim

unsigned int dumy_fm_khz = fm_khz;


for(i=0;i<10;i++)
{
  if(fm_auto_scan(dir)) index++;
  else break;
}
   
if(index%2)
{
  if(dir) fm_khz = dumy_fm_khz + (unsigned int)((index/2)*100);
  else    fm_khz = dumy_fm_khz - (unsigned int)((index/2)*100);
}
else
{
  if(dir) fm_khz = dumy_fm_khz + (unsigned int)(((index/2)-1)*100);
  else    fm_khz = dumy_fm_khz - (unsigned int)((index/2)*100);
}

status = fm_hilo_optimal(fm_khz);
fmw_pll_rtn(status, fm_khz);
//fmw_all_mute_rtn(off);  TEST

status = fm_wr_rtn(fm_wr_byte);
         
// LCD_ClearOneLine(2);
// lcd_var(0, 2, fm_khz);
// LCD_DisplayChannelForFM(fm_khz);
return fm_khz;
}
#endif
#endif

/*以下是FM.h*/
/****************************************************************************/
/* MODULE:                                                                          */
/*
FM.h
*/  
/****************************************************************************/
/*
*   TCC Version 0.0
*   Copyright (c) telechips, Inc.
*   ALL RIGHTS RESERVED
*/
/****************************************************************************/

//dddxxx
#include "tcc760.h"

#ifdef RADIO_MCU
//#define  fm_pwr_off  HwGDATA_D &= ~(1 << 19) // Fm power off
//#define  fm_pwr_on  HwGDATA_D |= (1 << 19) // Fm power on

#define   mcu_slaveaddr    0x54
#define   COM_RADIO_STATE  0x40
#define   COM_RADIO_FREQ  0x41
#define   RADIO_SET_STERO  0x10
#define   RADIO_SET_PWR   0x20
#define  RADIO_SET_SENS_005 0x00
#define  RADIO_SET_SENS_010 0x80
#define  RADIO_SET_SENS_030 0x40
#define  RADIO_SET_SENS_150 0xc0
#define   RADIO_AUTOSCAN_UP 0x01
#define   RADIO_AUTOSCAN_DOWN 0x02
#define   RADIO_MANUSCAN_UP 0x04
#define   RADIO_MANUSCAN_DOWN 0x08
#define   RADIO_FM    0x00
#define   RADIO_AM    0x01

#define   RADIODELAY    100
enum{
PRESET_MODE_OFF,
PRESET_MODE_ON,
NO_MODE,
MANUAL_ADD_CH
};

#define  off    0
#define  on    1
#define  up    1
#define  down   0

#define MAX_PRESET_NUM 20
typedef struct BANKOFRADIO {
unsigned char IsPreset ;
unsigned char IsStereo;
unsigned short LastUseFMHz;
unsigned short Presetbank[MAX_PRESET_NUM] ;
unsigned char LastUsePresetNum;
unsigned char LastBand;
} FMRADIO;

extern unsigned int fm_khz;
extern FMRADIO RadioData;

extern void  delay720(unsigned int count);
extern void  fm_init(void);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern void fmw_stereo_rtn(unsigned char onoff);

extern void mcu_send_state(void);
extern unsigned char mcu_read_radio_state(void);
extern unsigned int  mcu_read_radio_freq(void);
extern void Radio_manual_scan(unsigned char dir);
extern void Radio_auto_scan(unsigned char dir);

#else
#define  fm_slaveaddr 0xc0    // FM modules slave addr
#define  fm_pwr_off  HwGDATA_A |= (1 << 13); // Fm power off
#define  fm_pwr_on  HwGDATA_A &= ~(1 << 13); // Fm power on

enum{
PRESET_MODE_OFF,
PRESET_MODE_ON,
NO_MODE,
MANUAL_ADD_CH
};

#define  off    0
#define  on    1
#define  up    1
#define  down   0
#define  all_level  0
#define  lo_level  1
#define  mid_level  2
#define  hi_level  3
#define  japan   1  // Japan band
#define  us_eu   0  // US/EU band
#define  xtal_32768  1  // set the x-tal to 32.768 KHz
#define  xtal_13m  0  // set the x-tal to 13 MHz
#define  ref_65_en  1  // 6.5 MHz reference for PLL enabled
#define  ref_65_dis  0  // 6.5 MHz reference not enabled
#define  deemph75  1  // deemphasis time constant is 75 us
#define  deemph50  0  // deemphasis time constant is 50 us

#define  hi_side   1  // FM module's high-side injcetion
#define  lo_side   0  // FM module's low-side injection


// when you do not use the autonomous search mode of the FM module, set the scan level and step
#define  scan_level 6  // the available values are 0 ~ 15
#define  scan_step 100  // KHz unit

extern unsigned int fm_khz;
extern void delay720(unsigned int count);
extern void fm_init(void);
extern void LCD_DisplayChannelForFM(int InputHz);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern unsigned char fm_wr_rtn(unsigned char *ptr);

// Struct for Radio data
#define MAX_PRESET_NUM 20
typedef struct BANKOFRADIO {
unsigned char  IsPreset ;
unsigned char IsStereo;
unsigned short LastUseFMHz;
unsigned short Presetbank[MAX_PRESET_NUM] ;
unsigned char LastUsePresetNum;
} FMRADIO;

extern FMRADIO RadioData;
extern unsigned char fm_wr_byte[5];
extern unsigned char fm_hilo_optimal(unsigned int fm_freq);
extern void fmw_pll_rtn(unsigned char hilo, unsigned int fm_freq);
extern void fmw_all_mute_rtn(unsigned char onoff);
extern unsigned char fm_wr_rtn(unsigned char *ptr);
extern void fmw_stand_by_rtn(unsigned char onoff);
extern void fmw_stereo_rtn(unsigned char onoff);
extern void delay720(unsigned int count);
extern unsigned int fm_auto_scan_detect(unsigned char dir);
extern unsigned char fm_auto_scan(unsigned char dir);
extern void fm_manual_scan(unsigned char dir);
#endif

/****************************************************************************/
/* MODULE:                                                                          */
/* FM.c

*/  
/****************************************************************************/
/*
*   TCC Version 0.0
*   Copyright (c) telechips, Inc.
*   ALL RIGHTS RESERVED
*/
/****************************************************************************/

#include "main.h"
#include "fm/FM.h"
#include "kernel/telechips.h"
#include "i2c/i2c.h"

FMRADIO   RadioData;
#ifdef RADIO_INCLUDE
#ifdef RADIO_MCU
unsigned char radio_state = RADIO_SET_STERO|RADIO_SET_SENS_150;
unsigned int radio_freq ;  
unsigned char command_buff[2];
unsigned char receive_data[2];
unsigned int fm_khz;
unsigned char radio_pwron_counter=0;

void delay720(unsigned int count)
{
  for(;count>0;count--) ;
// 1:0.84, 5:1.36, 10:1.96, 20:3.20, 30:4.48, 60:8.04, 80:10.6, 90:11.6, 100:13
}

void fmw_stand_by_rtn(unsigned char onoff)  //radio power onoff
{
// if(onoff)
//  fm_pwr_on;
// else
//  fm_pwr_off;
if(onoff)
  {
  radio_state &= ~RADIO_SET_PWR;
  radio_pwron_counter=1;
  }
else   radio_state |= RADIO_SET_PWR;
mcu_send_state();

}

void fmw_stereo_rtn(unsigned char onoff)
{

//radio_state &= 0xcf;
//if(onoff)
// radio_state |= RADIO_SET_STERO;
//else   radio_state |= RADIO_SET_MONO;
if(onoff)
  radio_state |= RADIO_SET_STERO;
else   radio_state &= ~RADIO_SET_STERO;
mcu_send_state();
}

unsigned char mcu_rd_rtn(unsigned char subadr,unsigned char *ptr, unsigned char bytes)
{
return (unsigned char)(i2c_read((unsigned int)I2C_FM, (unsigned char)mcu_slaveaddr, subadr, ptr, bytes));
}

unsigned char mcu_wr_rtn(unsigned char subadr,unsigned char *ptr, unsigned char bytes)
{
return (unsigned char)(i2c_write((unsigned int)I2C_FM, (unsigned char)mcu_slaveaddr, subadr, ptr, bytes));
}

void mcu_set_state(unsigned char *com)
{
mcu_wr_rtn(COM_RADIO_STATE,com,1);
}

void mcu_set_freq(unsigned char *com)
{
mcu_wr_rtn(COM_RADIO_FREQ,com,2);
}

void mcu_read_state(unsigned char *com)
{
mcu_rd_rtn(COM_RADIO_STATE,com,1);
}

void mcu_read_freq(unsigned char *com)
{
mcu_rd_rtn(COM_RADIO_FREQ,com,2);
}

void mcu_send_state(void)
{
command_buff[0] = radio_state;
mcu_set_state(command_buff);
}
void mcu_manuscan_up(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_MANUSCAN_UP;
mcu_send_state();
}

void mcu_manuscan_down(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_MANUSCAN_DOWN;
mcu_send_state();
}

void mcu_autoscan_up(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_AUTOSCAN_UP;
mcu_send_state();
}

void mcu_autoscan_down(void)
{
radio_state &= 0xf0;
radio_state |= RADIO_AUTOSCAN_DOWN;
mcu_send_state();
}


void mcu_set_bandfreq(unsigned char band)
{

if(band == RADIO_FM)
  radio_freq = fm_khz/10;
else
  radio_freq = fm_khz | ((unsigned int)(band)<<14);

command_buff[0] = (unsigned char)((radio_freq>>8) & 0xff);
command_buff[1] = (unsigned char)(radio_freq & 0xff);
mcu_set_freq(command_buff);
}

unsigned char mcu_read_radio_state(void)
{
unsigned char temp;

mcu_read_state(receive_data);
temp = receive_data[0];
receive_data[0] = 0;
return temp;
}

unsigned int mcu_read_radio_freq(void)
{
unsigned int temp;
mcu_read_freq(receive_data);
temp = receive_data[0];
temp = (temp<<8) & 0xff00;
temp |= receive_data[1];
receive_data[0] = 0;
receive_data[1] = 0;
return temp;
}

void fm_init(void)
{
//mute fm
fmw_stand_by_rtn(off);
/*
fm_pwr_on;//power on radio
delay720(100);   
fm_khz = 87500;
mcu_set_bandfreq(RADIO_FM);
*/
//unmute fm
}

void fmw_all_mute_rtn(unsigned char onoff)
{
}

void Radio_manual_scan(unsigned char dir)
{
unsigned char status;
unsigned int freq;

if(dir)
  mcu_manuscan_up();
else
  mcu_manuscan_down();

}
void Radio_auto_scan(unsigned char dir)
{
unsigned char status;
unsigned int freq;

if(dir)
  mcu_autoscan_up();
else
  mcu_autoscan_down();
}

#else
unsigned char fm_rd_byte[5] = {0,0,0,0,0}; // Read buf
unsigned char fm_wr_byte[5] = {0,0,0,0,0}; // write but
unsigned int fm_khz;

void delay720(unsigned int count)
{
  for(;count>0;count--) ;
// 1:0.84, 5:1.36, 10:1.96, 20:3.20, 30:4.48, 60:8.04, 80:10.6, 90:11.6, 100:13
}
/* ---------------------------------- Command Function ------------------------------------ */

void fmw_hilo_side_rtn(unsigned char hilo)
{
if(hilo) fm_wr_byte[2] |= 0x10;
else  fm_wr_byte[2] &= 0xef;
}

void fmw_all_mute_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[0] |= 0x80;
else   fm_wr_byte[0] &= 0x7f;
}

void fmw_search_mode_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[0] |= 0x40;
else   fm_wr_byte[0] &= 0xbf;
}

void fmw_search_dir_rtn(unsigned char dir)
{
if(dir) fm_wr_byte[2] |= 0x80;
else fm_wr_byte[2] &= 0x7f;
}

void fmw_search_level_rtn(unsigned char level)
{
switch(level)
{
  case all_level : fm_wr_byte[2] &= 0x9f;
         break;
  case lo_level :  fm_wr_byte[2] &= 0xbf;
         fm_wr_byte[2] |= 0x20;
         break;
  case mid_level : fm_wr_byte[2] |= 0x40;
         fm_wr_byte[2] &= 0xdf;
         break;
  case hi_level  : fm_wr_byte[2] |= 0x60;
         break;
}
}

void fmw_stereo_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] &= 0xf7;
else   fm_wr_byte[2] |= 0x08;
}

void fmw_mute_left_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] |= 0x04;
else   fm_wr_byte[2] &= 0xfb;
}

void fmw_mute_right_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[2] |= 0x02;
else   fm_wr_byte[2] &= 0xfd;
}

void fmw_stand_by_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x40;
else   fm_wr_byte[3] &= 0xbf;
}

void fmw_band_sel_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x20;
else    fm_wr_byte[3] &= 0xdf;
}

void fmw_xtal_sel_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x10;
else    fm_wr_byte[3] &= 0xef;
}

void fmw_soft_mute_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x08;
else   fm_wr_byte[3] &= 0xf7;
}

void fmw_hcc_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x04;
else   fm_wr_byte[3] &= 0xfb;
}

void fmw_snc_rtn(unsigned char onoff)
{
if(onoff) fm_wr_byte[3] |= 0x02;
else   fm_wr_byte[3] &= 0xfd;
}

void fmw_search_indi_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[3] |= 0x01;
else fm_wr_byte[3] &= 0xfe;
}

void fmw_pll_ref_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[4] |= 0x80;
else    fm_wr_byte[4] &= 0x7f;
}

void fmw_deemph_rtn(unsigned char sel)
{
if(sel) fm_wr_byte[4] |= 0x40;
else    fm_wr_byte[4] &= 0xbf;
}

unsigned char fmr_ready_flag_rtn(void)
{
return (unsigned char)((fm_rd_byte[0] >> 7) & 0x01);
}

unsigned char fmr_band_limit_rtn(void)
{
return (unsigned char)((fm_rd_byte[0] >> 6) & 0x01);
}

unsigned short fmr_pll_rtn(void)
{
unsigned short temp = 0;

temp = (unsigned short)((fm_rd_byte[0] & 0x3f) << 8);
temp |= (unsigned short)fm_rd_byte[1];

return temp;
}

unsigned char fmr_stereo_indi_rtn(void)
{
return (unsigned char)((fm_rd_byte[2] >> 7) & 0x01);
}

unsigned char fmr_if_count_rtn(void)
{
return (unsigned char)(fm_rd_byte[2] & 0x7f);
}

unsigned char fmr_level_adc_rtn(void)
{
return (unsigned char)((fm_rd_byte[3] >> 4) & 0x0f);
}

/* ------------------------------ End Command function ------------------------------------- */
unsigned char fm_rd_rtn(unsigned char *ptr)
{
return (unsigned char)(i2c_read((unsigned int)I2C_FM, (unsignedchar)fm_slaveaddr, (char)I2C_SUBADDR_NOUSE, ptr, (unsigned char)5));
}

unsigned char fm_wr_rtn(unsigned char *ptr)
{
return (unsigned char)(i2c_write((unsigned int)I2C_FM, (unsignedchar)fm_slaveaddr, (char)I2C_SUBADDR_NOUSE, ptr, (unsigned char)5));
}

void fmw_pll_rtn(unsigned char hilo, unsigned int fm_freq)
{
unsigned char temp;
unsigned short fm_pll_val = 0;

if(hilo) fm_pll_val = (unsigned short)((4000*(fm_freq+225))/32768); // calc PLL decoder
else  fm_pll_val = (unsigned short)((4000*(fm_freq-225))/32768);

temp = (unsigned char)((fm_pll_val >> 8) & 0x3f);
fm_wr_byte[0] &= 0xc0;
fm_wr_byte[0] |= temp;

temp = (unsigned char)fm_pll_val;
fm_wr_byte[1] = temp;

fmw_hilo_side_rtn(hilo);
}

unsigned char fm_hilo_optimal(unsigned int fm_freq)
{
unsigned char status;
unsigned char temp;
unsigned char levelhigh, levellow;

fmw_pll_rtn(hi_side, fm_freq+450); // Set PLL value High
status = fm_wr_rtn(fm_wr_byte);  // Send Command


        delay720(20000);  
     
status = fm_rd_rtn(fm_rd_byte);  // Read status

levelhigh = fmr_level_adc_rtn(); // Get ADC value
  
fmw_pll_rtn(hi_side, fm_freq-450); // Set PLL value Low
status = fm_wr_rtn(fm_wr_byte);

delay720(20000);  

     
status = fm_rd_rtn(fm_rd_byte);

levellow = fmr_level_adc_rtn();
  
if(levelhigh < levellow) temp = hi_side;
else temp = lo_side;

return temp;
}

void fm_init(void)
{
unsigned char i;
#if 0 /* lhm */
i2c_wr
i2c_clk_hi
i2c_data_hi
#endif /* lhm */
// fm_pwr_on // 20050111

delay720(100);   

fm_khz = 89100; //107700;


fmw_all_mute_rtn(on);     // MUTE OFF
fmw_search_mode_rtn(off);    // OFF SearchMode
fmw_search_dir_rtn(up);     // Search direction is up
fmw_search_level_rtn(mid_level);  // search ADC level is middle
// fmw_search_level_rtn(lo_level);  // search ADC level is middle
fmw_stereo_rtn(on);      // Steleo ON
fmw_mute_left_rtn(off);     // Left force mono off
fmw_mute_right_rtn(off);    // Right force mono 0ff
fmw_stand_by_rtn(on);     // Stanby off
// fmw_band_sel_rtn(japan);    // Japan FM zone
fmw_band_sel_rtn(us_eu);    // Japan FM zone
fmw_xtal_sel_rtn(xtal_32768);   // set the x-tal to 32.768 KHz
fmw_soft_mute_rtn(on);
fmw_hcc_rtn(on);      // HCC ON
fmw_snc_rtn(on);      // SNC ON
fmw_search_indi_rtn(on);    // Pin 14 is output for the ready flag
fmw_pll_ref_rtn(ref_65_dis);   // 6.5Mhz ref. not enable
fmw_deemph_rtn(deemph50);    // deemphasis is 50us

i = fm_hilo_optimal(fm_khz);   // HILO algorithm -> find optimize PLL
fmw_pll_rtn(i, fm_khz);
fmw_all_mute_rtn(off);
i = fm_wr_rtn(fm_wr_byte);
}
/*---------------------------------------- Change Hz and Auto Scan ---------------------------------------- */
void fm_manual_scan(unsigned char dir)
{
unsigned char status;


if(dir)
{
  if(fm_khz >= 108000) fm_khz = 87500;
  else     fm_khz += scan_step;
}
else
{
  if(fm_khz <= 87500) fm_khz = 108000;
  else    fm_khz -= scan_step;
}
        
status = fm_hilo_optimal(fm_khz);
      
fmw_pll_rtn(status, fm_khz);
  
//fmw_all_mute_rtn(off); // TEST

status = fm_wr_rtn(fm_wr_byte);
//LCD_DisplayChannelForFM(fm_khz);

}

unsigned char fm_auto_scan(unsigned char dir)
{
unsigned char status, curlev, curifc;

if(dir)
{
  if(fm_khz >= 108000) fm_khz = 87500;
  else     fm_khz += scan_step;
}
else
{
  if(fm_khz <= 87500) fm_khz = 108000;
  else    fm_khz -= scan_step;
}

//fmw_all_mute_rtn(on); // TEST
status = fm_wr_rtn(fm_wr_byte); // Edit By Jim
status = fm_hilo_optimal(fm_khz);
fmw_pll_rtn(status, fm_khz);
status = fm_wr_rtn(fm_wr_byte);
        
// delay720(20000);
delay720(30000);

     
status = fm_rd_rtn(fm_rd_byte);
curlev = fmr_level_adc_rtn();
curifc = fmr_if_count_rtn();

// LCD_DisplayChannelForFM(fm_khz);

/*
if(fm_khz == 88000)
  fm_khz = 88000;
else if(fm_khz == 89100)
  fm_khz = 89100;
else if(fm_khz == 89700)
  fm_khz = 89700;
else if(fm_khz == 91900)
  fm_khz = 91900;
else if(fm_khz == 93100)
  fm_khz = 93100;
else if(fm_khz == 93900)
  fm_khz = 93900;
else if(fm_khz == 95100)
  fm_khz = 95100;
else if(fm_khz == 95700)
  fm_khz = 95700;
else if(fm_khz == 95900)
  fm_khz = 95900;
else if(fm_khz == 97300)
  fm_khz = 97300;
else if(fm_khz == 98100)
  fm_khz = 98100;
else if(fm_khz == 99100)
  fm_khz = 99100;
else if(fm_khz == 99600)
  fm_khz = 99600;
else if(fm_khz == 100000)
  fm_khz = 100000;
else if(fm_khz == 101100)
  fm_khz = 101100;
else if(fm_khz == 101900)
  fm_khz = 101900;
else if(fm_khz == 102700)
  fm_khz = 102700;
else if(fm_khz == 103500)
  fm_khz = 103500;
else if(fm_khz == 105300)
  fm_khz = 105300;
else if(fm_khz == 106100)
  fm_khz = 106100;
else if(fm_khz == 106900)
  fm_khz = 106900;
else if(fm_khz == 107700)
  fm_khz = 107700;
*/
// if((curlev > 3) && (0x30 < curifc) && (curifc < 0x3c)  ) return 1; // scan_level
if((curlev > 3) && (0x30 < curifc) && (curifc < 0x3c)  ) return 1; // scan_level
else
  return 0;
}

unsigned int fm_auto_scan_detect(unsigned char dir)
{
unsigned char status, i;
unsigned char index = 1; // Edit By Jim

unsigned int dumy_fm_khz = fm_khz;


for(i=0;i<10;i++)
{
  if(fm_auto_scan(dir)) index++;
  else break;
}
   
if(index%2)
{
  if(dir) fm_khz = dumy_fm_khz + (unsigned int)((index/2)*100);
  else    fm_khz = dumy_fm_khz - (unsigned int)((index/2)*100);
}
else
{
  if(dir) fm_khz = dumy_fm_khz + (unsigned int)(((index/2)-1)*100);
  else    fm_khz = dumy_fm_khz - (unsigned int)((index/2)*100);
}

status = fm_hilo_optimal(fm_khz);
fmw_pll_rtn(status, fm_khz);
//fmw_all_mute_rtn(off);  TEST

status = fm_wr_rtn(fm_wr_byte);
         
// LCD_ClearOneLine(2);
// lcd_var(0, 2, fm_khz);
// LCD_DisplayChannelForFM(fm_khz);
return fm_khz;
}
#endif
#endif
发表于 2007-9-19 22:06:23 | 显示全部楼层
luoguo
发表于 2007-9-19 22:09:27 | 显示全部楼层
kankan
发表于 2007-9-20 00:43:09 | 显示全部楼层
thanks for your information...............
thanks................
头像被屏蔽
发表于 2007-12-13 13:15:27 | 显示全部楼层
提示: 作者被禁止或删除 内容自动屏蔽
发表于 2007-12-13 14:59:28 | 显示全部楼层
看看先!!
发表于 2007-12-19 14:03:46 | 显示全部楼层
thank you!
发表于 2007-12-30 14:41:09 | 显示全部楼层
xiexie --------------------------!
发表于 2007-12-31 23:42:06 | 显示全部楼层
good, thanks...
发表于 2008-5-16 16:13:59 | 显示全部楼层

支持

謝      謝
您需要登录后才可以回帖 登录 | 注册

本版积分规则

关闭

站长推荐 上一条 /1 下一条

小黑屋| 手机版| 关于我们| 联系我们| 隐私声明| EETOP 创芯网
( 京ICP备:10050787号 京公网安备:11010502037710 )

GMT+8, 2025-2-2 14:59 , Processed in 0.023768 second(s), 6 queries , Gzip On, Redis On.

eetop公众号 创芯大讲堂 创芯人才网
快速回复 返回顶部 返回列表