www.pudn.com > BK1080QB_101018_drv.zip > BK1080QB_101018_drv.c, change:2010-10-18,size:53154b


/***************************************************************************** 
*  Copyright Statement: 
*  -------------------- 
*  This software is protected by Copyright and the information contained 
*  herein is confidential. The software may not be copied and the information 
*  contained herein may not be used or disclosed except with the written 
*  permission of MediaTek Inc. (C) 2005 
* 
*  BY OPENING THIS FILE, BUYER HEREBY UNEQUIVOCALLY ACKNOWLEDGES AND AGREES 
*  THAT THE SOFTWARE/FIRMWARE AND ITS DOCUMENTATIONS ("MEDIATEK SOFTWARE") 
*  RECEIVED FROM MEDIATEK AND/OR ITS REPRESENTATIVES ARE PROVIDED TO BUYER ON 
*  AN "AS-IS" BASIS ONLY. MEDIATEK EXPRESSLY DISCLAIMS ANY AND ALL WARRANTIES, 
*  EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE IMPLIED WARRANTIES OF 
*  MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE OR NONINFRINGEMENT. 
*  NEITHER DOES MEDIATEK PROVIDE ANY WARRANTY WHATSOEVER WITH RESPECT TO THE 
*  SOFTWARE OF ANY THIRD PARTY WHICH MAY BE USED BY, INCORPORATED IN, OR 
*  SUPPLIED WITH THE MEDIATEK SOFTWARE, AND BUYER AGREES TO LOOK ONLY TO SUCH 
*  THIRD PARTY FOR ANY WARRANTY CLAIM RELATING THERETO. MEDIATEK SHALL ALSO 
*  NOT BE RESPONSIBLE FOR ANY MEDIATEK SOFTWARE RELEASES MADE TO BUYER'S 
*  SPECIFICATION OR TO CONFORM TO A PARTICULAR STANDARD OR OPEN FORUM. 
* 
*  BUYER'S SOLE AND EXCLUSIVE REMEDY AND MEDIATEK'S ENTIRE AND CUMULATIVE 
*  LIABILITY WITH RESPECT TO THE MEDIATEK SOFTWARE RELEASED HEREUNDER WILL BE, 
*  AT MEDIATEK'S OPTION, TO REVISE OR REPLACE THE MEDIATEK SOFTWARE AT ISSUE, 
*  OR REFUND ANY SOFTWARE LICENSE FEES OR SERVICE CHARGE PAID BY BUYER TO 
*  MEDIATEK FOR SUCH MEDIATEK SOFTWARE AT ISSUE.  
* 
*  THE TRANSACTION CONTEMPLATED HEREUNDER SHALL BE CONSTRUED IN ACCORDANCE 
*  WITH THE LAWS OF THE STATE OF CALIFORNIA, USA, EXCLUDING ITS CONFLICT OF 
*  LAWS PRINCIPLES.  ANY DISPUTES, CONTROVERSIES OR CLAIMS ARISING THEREOF AND 
*  RELATED THERETO SHALL BE SETTLED BY ARBITRATION IN SAN FRANCISCO, CA, UNDER 
*  THE RULES OF THE INTERNATIONAL CHAMBER OF COMMERCE (ICC). 
* 
*****************************************************************************/ 
 
/******************************************************************************* 
 * 
 * Filename: 
 * --------- 
 * AR1000_drv.c 
 * 
 * Project: 
 * -------- 
 *   MAUI 
 * 
 * Description: 
 * ------------ 
 * 
 *      FM Radio Driver (AR1000) 
 * 
 * Author: 
 * ------- 
 * ------- 
 * 
 *******************************************************************************/ 
#include "l1audio_def.h" 
 
#if (defined(AR1000)) 
 
 
//static int32 freq_rssi_array[2][3]={{0,0,0},{0,0,0}};//for auto search 
//static int8 index_count=0;  
///#define force_mono 
 
#define USE_I2C 
#define AR1000_DEBUG 
#define ext_clk 
//#define AR1000_DEBUG_DUMP_LOG       //Option log file 
//#define AR1000_timing_cal 
#define READ	1 
#define WRITE	0 
 
#if defined AR1000_DEBUG 
static uint8 dbg_cw_readbackM = 0; 
static uint8 dbg_cw_readbackL = 0; 
static uint16 dbg_cw_readdata; 
#endif 
 
#if (defined(MT6205B) || defined(MT6208)) && defined(AR1000_DEBUG_DUMP_LOG) 
#error "No file system on MT6205!" 
#endif 
 
#define UEBAND			0x0000 // US & Europe BAND 87.5MHz to 108MHz 
#define JBAND			0x1000 // Japen BAND 76MHz to 90MHz 
#define JWBAND			0x1800 // Japen BAND (wide) 76 MHz to 108MHz 
 
#define SPACE100K		1 
#define SPACE200K		0 
#define SEEKUP			1 
#define SEEKDOWN 		0 
 
/* General propose constant */ 
#define AR1000_WRITE          	32//192 
#define AR1000_READ           	33//193 
#define ADDR_STATUS		0x13 // the address of status register 
#define MASK_STC 		0x0020  // Seek/Tune/PowerOn complete  D5 in  adress 13H  
#define MASK_SF	 		0x0010  //  Seek Fail D4 in address 13H 
#define MASK_READCHAN 0xFF80 // D7~D15 in address 13H 
#define SHIFT_READCHAN 7 
 
#define ADDR_RSSI		0x12  
#define MASK_RSSI 		0xFE00 
#define SHIFT_RSSI  		9 
 
/// Global variables for current FM status 
static int16 _current_frequency = -1; 
static bool  _is_fm_on = false; 
//static bool  _is_fm_mute = false; 
//static uint8 _rssi_threshold; 
static uint16 Chip_ID = 0; 
static uint16 Device_ID = 0; 
static uint8 HWSearch_flag = 0; 
static uint8 Valid_flag = 0; 
static uint16 FreqKHz = 0; 
static uint8 RSSI_value = 0; 
static uint16 FMChipid = 0; 
 
 
#ifdef AR1000_DEBUG_DUMP_LOG 
extern uint32 video_get_current_time(void); 
extern uint32 video_get_duration_ms(uint32 t1); 
static kal_uint8 _file_name[] = {"D\0:\0\\\0f\0m\0_\0l\0o\0g\0.\0t\0x\0t\0\0\0"}; 
static uint32 _data_written; 
static uint8  _dbg_str[128]; 
static FS_HANDLE  _file_handle = 0; 
 
static kal_uint8 _channel_name[] = {"D\0:\0\\\0l\0i\0s\0_\0l\0o\0g\0.\0t\0x\0t\0\0\0"}; 
static uint32 _list_written; 
static uint8  _list_str[128]; 
static FS_HANDLE  _file_list = 0; 
#endif 
 
bool  BK1080_Intialization(void); 
void  BK1080_SetVolumeLevel(uint8 level); 
uint16 BK1080_FreqToChan(uint16 frequency); 
uint8 BK1080_GetSigLvl( int16 curf ); 
bool  BK1080_IsChipValid(void); 
void  BK1080_Mute(uint8 mute); 
void  BK1080_SetFreq(int16 curFreq); 
uint8 BK1080_ValidStop(int16 freq, int8 signalvl, bool is_step_up); 
uint8 BK1080_ValidStop_2(int16 freq); 
void  BK1080_PowerOnReset(void); 
void  BK1080_PowerOffProc(void); 
uint16 BK1080_GetChipID(void); 
uint16 BK1080_GetCurIF(void); 
unsigned char Operation_Beken_FM_2w(unsigned char operation, unsigned char *data,kal_uint8 start_reg, unsigned char numBytes); 
 
#ifdef BK1080_AUTO_SCAN_BY_CHIP 
uint8 BK1080_FmAutoScan (kal_uint16 *Freqs_buf,uint8 max_len,uint8 b_sort_by_RSSI); 
#endif 
#define FMCHANNELSMAX 30 
 
 
/* Serial communication interfaces */ 
void  SerialCommInit(void); 
void  SerialCommRelease(void); 
void  SerialCommCryClkOn(void); 
void  SerialCommCryClkOff(void); 
void  GPIO_WriteIO(char data,char port); 
 
#if defined USE_I2C 
void  SerialCommStart(void); 
void  SerialCommStop(void); 
uint8 SerialCommTxByte(uint8 data); 
void  SerialCommRxByte(uint8 *data, uint8 ack); 
#elif defined USE_3_WIRE 
uint8 SerialCommTxByte(uint8 cw, uint8 data); 
void  SerialCommRxByte(uint8 cw, uint8 *data); 
#endif 
 
void FMDrv_Mute(uint8 mute); 
void FMDrv_EvaluateRSSIThreshold(void); 
 
// enginner mode struct 
typedef enum group_idx { 
	   mono=0, 
	   stereo, 
	   RSSI_threshold, 
	   IF_count_delta, 
	   GROUP_TOTAL_NUMS 
	} FACTORY_GROUP_ENUM; 
	 
typedef enum item_idx { 
	   Sblend_OFF=0, 
	   Sblend_ON,   
	   ITEM_TOTAL_NUMS 
	} FACTORY_ITEM_INDEX; 
// enginner mode struct 
 
 
#if 0 
#if defined(ext_clk) 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
#else      
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
/* under construction !*/ 
#endif 
#endif 
 
//- Modified code start 
#if defined(ext_clk) 
static uint16 AR1000reg[18]={ // the initial setting of AR1000 register ( base on ARF_V022_080118_MTK) 
0xFF7B,  // R0 -- the first writable register 0xFF7F 
0x5915,  // R1 0x5B15 
0x10B9,  // R2//F4B9 0xF0B9 
0x8010,  // R3//8012 
0x0780,  // R4 
0x28AB,  // R5//28AA 0x28AA 
0x6400,  // R6 0x4400 
0x1EE7,  // R7 
0x7141,  // R8 
0x007D,  // R9 
0x81C6,  // R10//82CE		//disable wrap by purple 
0x4F65,  // R11//4F55 0x4F55 
0x970C,  // R12//970C 
0xB845,  // R13 
0xFC2D,  // R14//FC2D 
0x8097,  // R15//8097 
0x04A1,  // R16//04A1 
0xE2A7  // R17//7F6A 0x7F6A 
};  
#else      
static uint16 AR1000reg[18]={ // the initial setting of AR1000 register ( base on ARF_V022_080118_MTK) 
0xFFFB,  // R0 -- the first writable register . 0xFFFF 
0x5915,  // R1. 0x5B15 
0x10B9,  // R2. 0xF4B9 
0x8010,  // R3   
0x0780,  // R4   
0x28AB,  // R5  0x28AA 
0x6400,  // R6  0x4400 
0x1EE7,  // R7   
0x7141,  // R8   
0x007D,  // R9   
0x81C6,  // R10 		//disable wrap by purple 
0x4E65,  // R11. <---  0x4E55 
0x970C,  // R12.  
0xB845,  // R13  
0xFC2D,  // R14  
0x8097,  // R15  
0x04A1,  // R16  
0xE2A7  // R17 0xDF6A 
};  
#endif 
//- Modified code end 
 
 
static bool AR1000_ReadByte(uint8 CW, uint8 *dataM, uint8 *dataL) 
{ 
//	uint8 data1, data2; 
   if (CW == 255) { 
      *dataM = 0; 
      *dataL = 0; 
      return true; 
   } 
#if defined USE_I2C 
   SerialCommStart();                /// send the start sequence 
   SerialCommTxByte(AR1000_WRITE);   /// device ID and R/W bit 
   SerialCommTxByte(CW);             /// control word 
   SerialCommStart();                /// resend the start sequence 
   SerialCommTxByte(AR1000_READ);    /// device ID and R/W bit 
   SerialCommRxByte(dataM, 0);        /// read data and send ACK 
   SerialCommRxByte(dataL, 1);        /// read data and send ACK 
   SerialCommStop();                 /// send the stop sequence 
    
#elif defined USE_3_WIRE 
   SerialCommRxByte(CW, dataM); 
#else 
#error "Must define USE_I2C or USE_3_WIRE" 
#endif 
 
   return true; 
} 
 
static bool AR1000_WriteByte(uint8 CW, uint16 data) 
{ 
#if defined USE_I2C 
   SerialCommStart();                /// send the start sequence 
   SerialCommTxByte(AR1000_WRITE);   /// device ID and R/W bit 
   SerialCommTxByte(CW);             /// control word    
   SerialCommTxByte(data>>8);           /// data to be written 
   SerialCommTxByte(data&0xFF);           /// data to be written 
   SerialCommStop();                 /// send the stop sequence 
#elif defined USE_3_WIRE 
   SerialCommTxByte(CW, data); 
#else 
#error "Must define USE_I2C or USE_3_WIRE" 
#endif 
 
#if defined AR1000_DEBUG 
   AR1000_ReadByte(CW, &dbg_cw_readbackM, &dbg_cw_readbackL); 
   dbg_cw_readdata = (uint16)(dbg_cw_readbackM<<8|dbg_cw_readbackL); 
#endif 
   
   return true; 
} 
 
 
/*********************************************************************** 
*  Set radio frequency (internal) 
* 
*  parameter-->CurFreq:set frequency 
*          
***********************************************************************/ 
static bool AR1000_SetFreq(int32 CurFreq) 
{ 
 
	uint32 CHAN = 0x0000; 
	uint8 dataM, dataL; 
	uint16 dataRead, i=0; 
 
 
#ifdef AR1000_DEBUG_DUMP_LOG 
   uint32 start_t, duration_t; 
   kal_sprintf((void*)_dbg_str, "\nAR1000_SetFreq(%d);\n\0", CurFreq); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   start_t = video_get_current_time(); 
#endif    
    
   	//- Modified code start 
      	AR1000_WriteByte(17, AR1000reg[17]); 
      	//- Modified code end 
   	 
   	_current_frequency = CurFreq; 
	CHAN = CurFreq - 690; 
	CHAN = CHAN|0x200;//turn on TUNE 
	AR1000_ReadByte(2, &dataM, &dataL); 
	dataRead = (uint16)(dataM<<8|dataL); 
	AR1000_WriteByte(2, (dataRead&0xFC00)|CHAN); 
	 
	 
	do { 
         	AR1000_ReadByte(ADDR_STATUS, &dataM, &dataL); 
         	dataRead = (uint16)(dataM<<8|dataL); 
          
//         	if (i++ >= 600) { 
//            		return false; 
//         	} 
      	   } while ((dataRead & MASK_STC)==0); 
 
 
   return true; 
 
}//AR1000_SetFreq 
 
/*********************************************************************** 
*  Turn on/off tune (internal) 
* 
*  parameter-->ON_OFF: 1:ON, 0:OFF 
*          
***********************************************************************/ 
void AR1000_TUNE_ON_OFF(uint8 ON_OFF) 
{ 
	uint8 dataM, dataL; 
	uint16 dataRead; 
	 
	AR1000_ReadByte(2, &dataM, &dataL); 
	dataRead = (uint16)(dataM<<8|dataL); 
	if (ON_OFF == 1) 
		AR1000_WriteByte(2, (dataRead&0xFDFF)|0x200); 
	else 
		AR1000_WriteByte(2, (dataRead&0xFDFF)); 
} 
 
/*********************************************************************** 
*  Seek on/off (internal) 
* 
*  parameter-->ON_OFF: 1:ON, 0:OFF 
*          
***********************************************************************/ 
void AR1000_SEEK_ON_OFF(uint8 ON_OFF) 
{ 
	uint8 dataM, dataL; 
	uint16 dataRead; 
	 
	AR1000_ReadByte(3, &dataM, &dataL); 
	dataRead = (uint16)(dataM<<8|dataL); 
	if (ON_OFF == 1) 
		AR1000_WriteByte(3, (dataRead&0xBFFF)|0x4000); 
	else 
		AR1000_WriteByte(3, (dataRead&0xBFFF)); 
} 
 
/*********************************************************************** 
*  HiLo side Tune (internal) 
* 
*  parameter-->Freq: curf:875~1080 
*							 band:range87.5~108.0 
*         		 space:1:100k, 0:200k 
***********************************************************************/ 
void AR1000_TUNE_HiLo(int32 Freq, int16 band, int8 space) 
{ 
	int8 rssi; 
	uint8 dataM, dataL; 
	uint16 dataRead; 
	 
	FMDrv_Mute(1); 
      	SerialCommInit(); 
       
      	AR1000_SEEK_ON_OFF(0); 
      	 
      	AR1000_ReadByte(3, &dataM, &dataL); 
      	dataRead = (uint16)(dataM<<8|dataL); 
      	AR1000_WriteByte(3, ((dataRead&0xC7FF)|(space<<13))|band);//set space(100k/200k)and band(875~1080) 
         
        //Read Low-Side LO Injection 
  	//R11 --> clear  D15,  clear D0/D2,  D3 is the same as default 
  	AR1000_ReadByte(11, &dataM, &dataL); 
  	dataRead = (uint16)(dataM<<8|dataL); 
  	AR1000_WriteByte(11, (dataRead&0x7FFA)); 
  	if (false == AR1000_SetFreq(Freq))  
      	{ 
         	ASSERT(0); 
      	}     
       
       	AR1000_ReadByte(ADDR_RSSI, &dataM, &dataL); 
       	dataRead = (uint16)(dataM<<8|dataL); 
  	rssi = (dataRead & MASK_RSSI); 
  	 
  	//Read Hi-Side LO Injection 
  	// R11-->set D15, set D0/D2,  D3 is the same as default 
  	AR1000_ReadByte(11, &dataM, &dataL); 
  	dataRead = (uint16)(dataM<<8|dataL); 
  	AR1000_WriteByte(11, (dataRead&0x8005)); 
  	if (false == AR1000_SetFreq(Freq))  
      	{ 
         	ASSERT(0); 
      	}   
      	 
      	AR1000_ReadByte(ADDR_RSSI, &dataM, &dataL); 
       	dataRead = (uint16)(dataM<<8|dataL); 
      	rssi = rssi- (dataRead & MASK_RSSI);   
      	 
      	if (rssi < 0) //errata in 0.82 
  	{ 	 
		// LO 
		// R11--> clear D15, set D0/D2, D3 is the same as default 
		AR1000_ReadByte(11, &dataM, &dataL); 
  		dataRead = (uint16)(dataM<<8|dataL); 
  		AR1000_WriteByte(11, (dataRead&0x7FFF)|0x0005); 
  	}else{  
		//HI 
		//R11-->  set D15, clear D0/D2, D3 is the same as default 
		AR1000_ReadByte(11, &dataM, &dataL); 
  		dataRead = (uint16)(dataM<<8|dataL); 
  		AR1000_WriteByte(11, (dataRead|0x8000)&0xFFFA); 
  	} 
  	 
  	//fine-tune !! 
  	//TUNE to FreqKHz with current setting 
  	if (false == AR1000_SetFreq(Freq))  
      	{ 
         	ASSERT(0); 
      	}   
	 
} 
 
/*********************************************************************** 
*  Get RSSI Value (internal) 
* 
*  parameter--> 
***********************************************************************/ 
uint16 AR1000_GetCurRSSI(void) 
{ 
   uint8 TmpRegM, TmpRegL; 
   uint16 TmpReg; 
 
   AR1000_ReadByte(ADDR_RSSI, &TmpRegM, &TmpRegL); 
   TmpReg = (uint16)(TmpRegM<<8|TmpRegL); 
   return ((TmpReg & MASK_RSSI)>>9); 
} 
 
/*********************************************************************** 
*  Get IF_count Value (internal) 
* 
*  parameter--> 
***********************************************************************/ 
uint16 AR1000_GetCurIF(void) 
{ 
   uint8 TmpRegM, TmpRegL; 
   uint16 TmpReg; 
 
   AR1000_ReadByte(ADDR_RSSI, &TmpRegM, &TmpRegL); 
   TmpReg = (uint16)(TmpRegM<<8|TmpRegL); 
   return (TmpReg & 0x1FF); 
} 
 
/*********************************************************************** 
*  Get Search freq (internal) 
* 
*  parameter--> 
***********************************************************************/ 
void AR1000_GetSearchFreq(uint16 *pfreq) 
{ 
	*pfreq = (uint16)FreqKHz; 
} 
 
void FMDrv_ChipInit(void) 
{ 
//   /// power down the chip 
//   int32 i; 
//   uint8 tmp_reg; 
   SerialCommInit(); 
	FMChipid = BK1080_GetChipID(); 
	if (FMChipid == 0x1080) 
	{ 
		BK1080_Intialization();//BK1080 chip 
		BK1080_PowerOffProc(); 
	} 
	else 
	{ 
    
   //- Modified code start 
   AR1000_WriteByte(0, 0xFF7A); //0xFF7E 
   //- Modified code end 
 
   SerialCommCryClkOff(); 
   } 
   SerialCommRelease(); 
//#ifdef USE_AR1000_AMP 
//   ExtSwitchInit(); 
//#endif 
} 
 
 
/*********************************************************************** 
*  Engineer mode function (API) 
* 
*  parameter-->group_idx: mono\stereo\RSSI_threshold\IF_count_delta 
*              item_idx: sub select index 
*              item_value: set parameter value 
***********************************************************************/ 
void FMDrv_radio_item_info(kal_uint16 group_idx, kal_uint16 item_idx, kal_uint32 item_value) 
{ 
	uint8 dataM, dataL; 
   uint16 dataRead; 
   uint8 tmpdata[2]; 
	 
	SerialCommInit(); 
	switch (group_idx) 
	{ 
		case mono: 
			if(item_value == 1) 
  			{ 
  				if (0x1080==FMChipid) 
				{ 
					Operation_Beken_FM_2w(READ, tmpdata, 2, 2); 
					tmpdata[0] |=0x20; 
					Operation_Beken_FM_2w(WRITE, tmpdata, 2, 2); 
				} 
				else 
				{ 
      				AR1000_ReadByte(1, &dataM, &dataL);  
							dataRead = (uint16)(dataM<<8|dataL); 
							AR1000_WriteByte(1, (dataRead&0xFFF7)|0x08); 
				} 
 
      	} 
      	else 
      	{ 
      		if (0x1080==FMChipid) 
			{ 
				Operation_Beken_FM_2w(READ, tmpdata, 2, 2); 
				tmpdata[0] &=0xDF; 
				Operation_Beken_FM_2w(WRITE, tmpdata, 2, 2); 
			} 
			else 
			{ 
      				AR1000_ReadByte(1, &dataM, &dataL);  
							dataRead = (uint16)(dataM<<8|dataL); 
							AR1000_WriteByte(1, (dataRead&0xFFF7)); 
			} 
      	} 
    
		break; 
		case stereo: 
			if(item_value == 0) 
			{ 
				if (0x1080==FMChipid) 
				{ 
					Operation_Beken_FM_2w(READ, tmpdata, 2, 2); 
					tmpdata[0] |=0x20; 
					Operation_Beken_FM_2w(WRITE, tmpdata, 2, 2); 
				} 
				else 
				{ 
				    AR1000_ReadByte(1, &dataM, &dataL);  
						dataRead = (uint16)(dataM<<8|dataL); 
						AR1000_WriteByte(1, (dataRead&0xFFF7)|0x08); 
				} 
			} 
			else 
			{ 
				switch (item_idx) 
				{ 
					case Sblend_ON: 
//								MT6188_ReadByte(CW(14, 0), &TmpReg1); 
//      					TmpReg1&=0x2F; 
//      					MT6188_WriteByte(CW(14, 0),TmpReg1|0xD0); 
//      					mono_flag = 3; 
					break; 
					case Sblend_OFF: 
//								MT6188_ReadByte(CW(14, 0), &TmpReg1); 
//      					TmpReg1&=0x2F; 
//      					MT6188_WriteByte(CW(14, 0),TmpReg1|0x90); 
//      					mono_flag = 4; 
					break; 
				} 
			} 
		break; 
		case RSSI_threshold: 
			if (item_value == 1) 
		        	RSSI_value = 12; 
		    	else if (item_value == 2) 
		        	RSSI_value = 14; 
		    	else if (item_value == 3) 
		        	RSSI_value = 16; 
		    	else if (item_value == 4) 
		        	RSSI_value = 18; 
		    	else if (item_value == 5) 
		        	RSSI_value = 20; 
		    	else if (item_value == 6) 
		        	RSSI_value = 22; 
		    	else 
		    		RSSI_value = 16;//FM_RADIO_INPUT_LEVEL_THRESHOLD; 
//					AR1000_ReadByte(3, &dataM, &dataL);  
//					dataRead = (uint16)(dataM<<8|dataL); 
//					AR1000_WriteByte(3, (dataRead&0xFF80)|RSSI_value); 
		break; 
		case IF_count_delta: 
 
		break; 
		 
	} 
	SerialCommRelease(); 
} 
 
 
 
bool FMDrv_IsChipValid( void ) 
{ 
	/// anything to do? 
	return true; 
} 
 
 
 
/// level ranges from 0 to 12 
void FMDrv_SetVolumeLevel(uint8 level) 
{ 
  #ifdef AR1000_DEBUG_DUMP_LOG 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_SetVolumeLevel(%d);\n\0", level); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
#endif 
//   AR1000_SetVolumeLevel(level); 
} 
 
void FMDrv_Mute(uint8 mute) 
{ 
	uint8 dataM, dataL; 
	uint16 dataRead; 
  #ifdef AR1000_DEBUG_DUMP_LOG 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_Mute(%d);\n\0", mute); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
#endif 
 
	SerialCommInit(); 
	if (0x1080==FMChipid) 
	{ 
		BK1080_Mute(mute); 
	}	 
	else 
	{ 
	AR1000_ReadByte(1,&dataM, &dataL); 
	dataRead = (uint16)(dataM<<8|dataL); 
	if (mute == 1) 
		AR1000_WriteByte(1, (dataRead&0xFFFD)|0x02); 
	else 
		AR1000_WriteByte(1, (dataRead&0xFFFD));       
       
	} 
      SerialCommRelease(); 
    
} 
 
 
/************************************************************* 
*  Radio power on Reset 
* 
*************************************************************/ 
void FMDrv_PowerOnReset(void) 
{ 
   uint8 fail_count=0; 
   uint16 dataRead; 
   int16 i; 
   uint8 dataM, dataL; 
    
 
#ifdef AR1000_DEBUG_DUMP_LOG 
   uint32 start_t, duration_t; 
   _file_handle = FS_Open((const WCHAR *)_file_name, FS_CREATE); 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_PowerOnReset();\n\0"); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   start_t = video_get_current_time(); 
#endif 
 
#ifdef AR1000_DEBUG_DUMP_LOG 
    _file_list = FS_Open((const WCHAR *)_channel_name, FS_CREATE); 
   kal_sprintf((void*)_list_str, "\nchannel list;\n\0"); 
   FS_Write(_file_list, _list_str, strlen((void*)_list_str), &_list_written); 
#endif    
    
   SerialCommInit(); 
	if (0x1080==FMChipid) 
	{ 
		BK1080_PowerOnReset(); 
	} 
	else 
	{ 
   SerialCommCryClkOn(); 
 
    AR1000_ReadByte(0x1C, &dataM, &dataL); 
    Chip_ID = (uint16)((dataM<<8)|dataL); 
     
    AR1000_ReadByte(0x1B, &dataM, &dataL); 
    Device_ID = (uint16)((dataM<<8)|dataL); 
/// Power On 
    
   //- Modified code start 
   AR1000_WriteByte(0, 0xFF7A); //0xFF7E 
   //- Modified code end 
    
   if (RSSI_value != 0) 
   	AR1000reg[3] = ((AR1000reg[3]&0xFF80)|RSSI_value); 
   	 	 
   for (i=1; i<18; i++) 
   { 
   	AR1000_WriteByte(i, AR1000reg[i]); 
   } 
   AR1000_WriteByte(0, AR1000reg[0]); 
    
   do { 
         AR1000_ReadByte(ADDR_STATUS, &dataM, &dataL); 
         dataRead = (uint16)(dataM<<8|dataL); 
          
         if (fail_count++ == 400) { 
            ASSERT(0); 
         } 
      } while ((dataRead & MASK_STC)==0); 
    
    
    
    
   SerialCommRelease(); 
   _is_fm_on = true; 
   _current_frequency = -1; 
//   _rssi_threshold = FM_RADIO_INPUT_LEVEL_THRESHOLD; 
//   if(RSSI_offset != 0) 
//    	_rssi_threshold = 6+RSSI_offset;     
//    	_rssi_threshold = 10+RSSI_offset; 
    
#ifdef AR1000_DEBUG_DUMP_LOG 
   duration_t = video_get_duration_ms(start_t); 
   kal_sprintf((void*)_dbg_str, "   time cost: %d ms.\n Chip_ID = %d \n\0", duration_t, Chip_ID); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
#endif 
 
} 
} 
 
/***************************************************************** 
*  Radio power off 
* 
*****************************************************************/ 
void FMDrv_PowerOffProc(void) 
{ 
//   int16 i; 
//   uint8 tmp_reg; 
    
#ifdef AR1000_DEBUG_DUMP_LOG 
   if (_file_handle == 0) 
      ASSERT(0); 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_PowerOffProc();\n\0"); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   FS_Close(_file_handle); 
   _file_handle = 0; 
#endif    
 
#ifdef AR1000_DEBUG_DUMP_LOG 
   if (_file_list == 0) 
      ASSERT(0); 
   kal_sprintf((void*)_list_str, "\nFMDrv_PowerOffProc();\n\0"); 
   FS_Write(_file_list, _list_str, strlen((void*)_list_str), &_list_written); 
   FS_Close(_file_list); 
   _file_list = 0; 
#endif    
    
    
#ifdef USE_AR1000_AMP 
   SwitchExtFMPath(0); 
#endif 
 
   SerialCommInit(); 
   if (0x1080==FMChipid) 
	{ 
		BK1080_PowerOffProc(); 
	} 
   else 
	{ 
   //- Modified code start 
   AR1000_WriteByte(0, 0xFF7A); //0xFF7E 
   //- Modified code end 
    
   SerialCommCryClkOff(); 
	} 
   SerialCommRelease(); 
   _is_fm_on = false; 
   _current_frequency = -1; 
    
} 
 
 
/********************************************************************* 
*  Radio set frquency 
* 
*  parameter-->curf:setting frequency value 
                    input value: 875 - 1080 ( 87.5 MHz - 108.0 MHz) 
*********************************************************************/ 
void FMDrv_SetFreq( int16 curf )  /* input value: 875 - 1080 ( 87.5 MHz - 108.0 MHz)*/ 
{ 
	uint8 dataM, dataL; 
	uint16 dataRead; 
//   if (_current_frequency != curf) { 
//      int16 HiLo; 
//      int32 curFreq = (int32)curf * FM_TUNER_GRID; 
       
#ifdef AR1000_DEBUG_DUMP_LOG 
   uint32 start_t, duration_t; 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_SetFreq(%d);\n\0", curf); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   start_t = video_get_current_time(); 
#endif       
   if (_is_fm_on != true) 
     FMDrv_PowerOnReset(); 
       
   FMDrv_Mute(1); 
   SerialCommInit(); 
       
	  if (0x1080==FMChipid) 
	{ 
		BK1080_SetFreq(curf); 
	} 
	  else 
  	{ 
   AR1000_TUNE_ON_OFF(0); 
   AR1000_SEEK_ON_OFF(0); 
       
   AR1000_ReadByte(3, &dataM, &dataL); 
   dataRead = (uint16)(dataM<<8|dataL); 
   AR1000_WriteByte(3, (dataRead&0xC7FF)|0x2000);//set space(100k/200k)and band(875~1080) 
     
   if (false == AR1000_SetFreq(curf))  
   { 
      ASSERT(0); 
   }      
//      AR1000_TUNE_HiLo(curf, 0, 1); 
  	} 
   SerialCommRelease(); 
   FMDrv_Mute(0); 
   
#ifdef USE_AR1000_AMP 
   SwitchExtFMPath(1); 
#endif 
 
#ifdef AR1000_DEBUG_DUMP_LOG 
   duration_t = video_get_duration_ms(start_t); 
   kal_sprintf((void*)_dbg_str, "   time cost: %d ms.\n\0", duration_t); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
#endif 
 
} 
 
 
/********************************************************************** 
*  Get really signal level in current frequency 
* 
*  parameter-->curf:frequency value of radio now 
**********************************************************************/ 
uint16 FMDrv_GetSigLvl( int16 curf ) 
{ 
   uint16 rssi; 
    
#ifdef AR1000_DEBUG_DUMP_LOG 
   uint32 start_t, duration_t; 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_GetSigLvl(%d);\n\0", curf); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   start_t = video_get_current_time(); 
#endif    
    
   if (curf != _current_frequency) 
   	FMDrv_SetFreq( curf ); 
   SerialCommInit(); 
   if (0x1080==FMChipid) 
	{ 
		rssi=BK1080_GetSigLvl(curf);			 
	} 
   else 
   	{ 
   rssi = AR1000_GetCurRSSI(); 
   	} 
   SerialCommRelease(); 
    
#ifdef AR1000_DEBUG_DUMP_LOG 
   duration_t = video_get_duration_ms(start_t); 
   kal_sprintf((void*)_dbg_str, "   time cost: %d ms.\n   RSSI returned: %d.\n\0", duration_t, rssi); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
#endif 
 
   return rssi; 
} 
 
 
/********************************************************************** 
*  Get really IF count in current frequency 
* 
*  parameter-->curf:frequency value of radio now 
**********************************************************************/ 
uint16 FMDrv_GetIF( int16 curf) 
{ 
   uint16 IF; 
 
#ifdef AR1000_DEBUG_DUMP_LOG 
   uint32 start_t, duration_t; 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_GetIF(%d);\n\0", curf); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   start_t = video_get_current_time(); 
#endif 
 
   if (curf != _current_frequency) 
      FMDrv_SetFreq( curf ); 
   SerialCommInit(); 
   if (0x1080==FMChipid) 
	{ 
		IF = BK1080_GetCurIF(); 
	} 
   else 
   	{ 
   IF = AR1000_GetCurIF(); 
   	} 
   SerialCommRelease(); 
 
#ifdef AR1000_DEBUG_DUMP_LOG 
   duration_t = video_get_duration_ms(start_t); 
   kal_sprintf((void*)_dbg_str, "   time cost: %d ms.\n   IF returned: %d.\n\0", duration_t, IF ); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
#endif 
   return IF; 
} 
 
 
/********************************************************************** 
*  Radio valid station,used in HW auto search frequency to verify  
*  valid positon 
* 
*  parameter-->freq: start frequency 
               is_step_up:1-->forward, 0-->backward 
               space:search step,0:200KHz, 1:100KHz 
**********************************************************************/ 
void FMDrv_HWSearch(int16 freq, bool is_step_up, int16 space, bool is_preset) 
{ 
   int32 targetFreq; 
   uint8 dataM, dataL, UpDown_flag=0; 
   uint16 dataRead; 
   uint8 _step; 
   kal_uint8 TmpData8[8]; 
   uint8 fm_count = 0; 
    
//   int8 pt; 
     
//uint32 save_irq_mask; 
    
#ifdef AR1000_DEBUG_DUMP_LOG 
   uint32 start_t, duration_t; 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_ValidStop(%d, %d, %d);\n\0", freq, signalvl, is_step_up); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   start_t = video_get_current_time(); 
#endif    
	if (0x1080==FMChipid) 
	{ 
		if (_is_fm_on == false) 
		{ 
		HWSearch_flag = 1; 
		Valid_flag = 1; 
		return; 
		} 
 
		//uint32 save_irq_mask; 
 
		//dump_printf("bk1080 hwsearch freq=%d,dir=%d,preset=%d\n",freq,is_step_up,is_preset); 
		kal_prompt_trace(MOD_UEM,"bk1080 hwsearch freq=%d,dir=%d,preset=%d\n",freq,is_step_up,is_preset); 
		if (is_step_up) 
			UpDown_flag = 1; 
		HWSearch_flag = 0; 
		Valid_flag = 0; 
		//calculate starting frequency 
		if( space ) 
		{// 100K 
			_step = 1; 
		}else 
		{ 
		//200K 
			_step = 2; 
		} 
		if (!is_preset) 
		{ 
			if(is_step_up) 
			{// up 
			targetFreq = (int32)(freq+_step); 
			} 
			else 
			{ 
				//down 
				targetFreq = (int32)(freq-_step); 
			} 
		} 
		else 
		{ 
			if(is_step_up) 
			{// up 
				//targetFreq = (int32)(freq-_step); 
				targetFreq = (int32)(freq); 
			} 
			else 
			{ 
				//down 
				//targetFreq = (int32)(freq+_step); 
				targetFreq = (int32)(freq); 
				if( targetFreq > 1080 )	 
					targetFreq = 1080; 
			} 
		} 
		FMDrv_Mute(1); 
		SerialCommInit(); 
		fm_count = 0; 
		HWSearch_flag = 0; 
		Valid_flag = 0; 
		while(fm_count <206) 
		{ 
		fm_count ++; 
 
		if (BK1080_ValidStop_2(targetFreq) == 0) 
		{ 
			HWSearch_flag = 0; 
				Valid_flag = 1; 
			if(is_step_up) 
			{ 
				targetFreq += _step; 
				if (targetFreq > 1080) 
				{ 
					if(!is_preset) 
					{ 
						targetFreq = 875; 
					} 
					else 
					{ 
						FreqKHz = 1080; 
						HWSearch_flag = 1; 
						Valid_flag = 0; 
						break; 
					} 
				} 
			} 
			else 
			{ 
				targetFreq -= _step; 
				if (targetFreq < 875) 
					targetFreq = 1080; 
			} 
		} 
		else 
		{ 
			FreqKHz = targetFreq; 
			HWSearch_flag = 1; 
			Valid_flag = 0; 
			break; 
		} 
 
		//HWSearch_flag = 1; 
		//Valid_flag = 0; 
		} 
		if (fm_count > 205) 
		{ 
			FreqKHz = targetFreq; 
			HWSearch_flag = 1; 
			Valid_flag = 1; 
		} 
		//dump_printf("bk1080 hwsearch search success freq=%d\n",FreqKHz); 
		kal_prompt_trace(MOD_UEM,"bk1080 hwsearch search success freq=%d\n",FreqKHz); 
		FMDrv_Mute(0); 
		SerialCommRelease(); 
	} 
	else 
	{ 
				if (is_step_up) 
					UpDown_flag = 1; 
				HWSearch_flag = 0; 
				Valid_flag = 0; 
//calculate starting frequency 
			 if (!is_preset) 
			{	// this is not a auto_scan function ! 
				targetFreq = (int32)(freq); 
			}else{ 
			 if( space ) 
			 {// 100K 
				_step = 1; 
			 }else{ 
			  //200K 
				_step = 2; 
			 } 
			 if(is_step_up) 
			 {// up 
				targetFreq = (int32)(freq-_step); 
			}else{ 
			  //down 
				targetFreq = (int32)(freq+_step); 
				if( targetFreq > 1080 )	targetFreq = 1080; 
			} 
			} 
    		FMDrv_Mute(1); 
    		SerialCommInit(); 
 
	//- Modified code start   
      	if (false == AR1000_SetFreq(targetFreq))  
      	{ 
      	   ASSERT(0); 
      	}      
       
    		AR1000_TUNE_ON_OFF(0); 
    		AR1000_SEEK_ON_OFF(0); 
    	 
//    		AR1000_ReadByte(3, &dataM, &dataL); 
//      	dataRead = (uint16)(dataM<<8|dataL); 
//      	AR1000_WriteByte(3, (dataRead&0xC7FF)|0x2000);//set space(100k/200k)and band(875~1080) 
      	 
//      	if (false == AR1000_SetFreq(targetFreq))  
//      	{ 
//      	   ASSERT(0); 
//      	}      
 
    		AR1000_ReadByte(3, &dataM, &dataL); 
      	dataRead = (uint16)(dataM<<8|dataL); 
      	AR1000_WriteByte(3, (dataRead&0x47FF)|(UpDown_flag<<15)|(space<<13));//set space(100k/200k)and band(875~1080)and up/down 
 
	// Setting before seek       
	AR1000_ReadByte(17, &dataM, &dataL); 
	dataM = (dataM & 0xC3) | 0x20; 
	dataL =(dataL &  0xFF) | 0x00; 
      	dataRead = (uint16)(dataM<<8|dataL); 
      	AR1000_WriteByte(17, dataRead); 
       
	if (!is_preset) 
  	{	// this is not a auto_scan function ! 
		AR1000_WriteByte(10, AR1000reg[10]|0x0008); //enable wrap , if it is not auto scan function 
    }else{ 
		AR1000_WriteByte(10, AR1000reg[10]&0xFFF7); //disable wrap , if it is auto scan function 
	}	 
    		AR1000_SEEK_ON_OFF(1); 
//    		AR1000_ReadByte(3, &dataM, &dataL); 
//      	dataRead = (uint16)(dataM<<8|dataL); 
//      	AR1000_WriteByte(3, (dataRead&0x47FF)|(UpDown_flag<<15)|(space<<13));//set space(100k/200k)and band(875~1080)and up/down 
   	//- Modified code end 
   			AR1000_ReadByte(ADDR_STATUS, &dataM, &dataL); 
        dataRead = (uint16)(dataM<<8|dataL); 
   			HWSearch_flag = dataRead & MASK_STC; // check STC flag  
  			while( HWSearch_flag == 0) 
  			{ 
					// maybe you can delay for a while 
					// delay ( 100 ms ) 
					AR1000_ReadByte(ADDR_STATUS, &dataM, &dataL); 
         	dataRead = (uint16)(dataM<<8|dataL); 
					HWSearch_flag = dataRead & MASK_STC; // check STC flag  
					Valid_flag = 1; 
  			} 
 			FreqKHz = 690 + ((dataRead & MASK_READCHAN )>> SHIFT_READCHAN );			 
					if (is_preset) 
  			{ 
   					if (FreqKHz == 1080) 
  					{ 
  						HWSearch_flag = 1; 
  						Valid_flag = 0; 
  					} 
  			} 
			if((dataRead & MASK_SF)!=0) 
			{ 
      	 		HWSearch_flag = 1; 
      	 		Valid_flag = 0; 
			}			 
 
      	//- Modified code start 
      	// Restore setting after seek 
      	AR1000_WriteByte(17, AR1000reg[17]); 
      	//- Modified code end 
      		    
 
      	 	 
 
  			FMDrv_Mute(0); 
   			SerialCommRelease(); 
	} 
//   return 1; 
} 
 
uint8 FMDrv_HWSpolling(uint16 *curf, uint8 *is_valid) 
{ 
	 
	if (HWSearch_flag != 0) 
	{ 
		if (0x1080==FMChipid) 
		{ 
			*curf = (uint16)FreqKHz; 
		} 
		else 
		{ 
		AR1000_GetSearchFreq(curf);  
		AR1000_SEEK_ON_OFF(0); 
		} 
		if (Valid_flag == 1) 
			*is_valid = 1; 
		else 
			*is_valid = 0; 
		return 1; 
	} 
	else 
		return 0; 
} 
 
 
 
/********************************************************************** 
*  Radio valid station,used in auto search frequency to verify  
*  valid positon 
* 
*  parameter-->freq: frequency 
               signalv1:signal level range is 0 ~ 15  
               is_step_up:return value(Reserved) 
**********************************************************************/ 
uint8 FMDrv_ValidStop(int16 freq, int8 signalvl, bool is_step_up) 
{ 
   int32 targetFreq; 
   uint8 dataM, dataL; 
   uint16 dataRead, i=0; 
   bool result; 
    
//   int8 pt; 
     
//uint32 save_irq_mask; 
    
#ifdef AR1000_DEBUG_DUMP_LOG 
   uint32 start_t, duration_t; 
   kal_sprintf((void*)_dbg_str, "\nFMDrv_ValidStop(%d, %d, %d);\n\0", freq, signalvl, is_step_up); 
   FS_Write(_file_handle, _dbg_str, strlen((void*)_dbg_str), &_data_written); 
   start_t = video_get_current_time(); 
#endif    
 
	targetFreq = (int32)freq; 
	 
    	FMDrv_Mute(1); 
    	SerialCommInit(); 
		if (0x1080==FMChipid) 
		{ 
			result=BK1080_ValidStop(freq, signalvl, is_step_up); 
		} 
		else 
		{ 
       
    	AR1000_TUNE_ON_OFF(0); 
    	AR1000_SEEK_ON_OFF(0); 
    	 
    	AR1000_ReadByte(3, &dataM, &dataL); 
      	dataRead = (uint16)(dataM<<8|dataL); 
      	AR1000_WriteByte(3, (dataRead&0xC7FF)|0x2000);//set space(100k/200k)and band(875~1080) 
      	 
      	if (false == AR1000_SetFreq(targetFreq))  
      	{ 
      	   ASSERT(0); 
      	}      
       
    	AR1000_SEEK_ON_OFF(1); 
    	AR1000_ReadByte(3, &dataM, &dataL); 
      	dataRead = (uint16)(dataM<<8|dataL); 
      	AR1000_WriteByte(3, (dataRead&0x47FF)|(is_step_up<<15)|0x2000);//set space(100k/200k)and band(875~1080) 
    
   	do { 
         	AR1000_ReadByte(ADDR_STATUS, &dataM, &dataL); 
         	dataRead = (uint16)(dataM<<8|dataL); 
          
         	if (i++ >= 40) { 
            		return 0; 
         	} 
      	   } while ((dataRead & MASK_STC)==0); 
      	    
      	 if((dataRead & MASK_SF)!=0) 
      	 	return 0; 
      	 	 
			} 
  	FMDrv_Mute(0); 
 
 
   SerialCommRelease(); 
 
   return 1; 
} 
 
kal_uint16 BK1080_Digital_Reg[]= 
{ 
0x0008,	//REG0 
0x1080,	//REG1 
0x8201, //REG2          //0x9201 For BK1080XB,0X8201 For BK1080QB	 
0x0000,	//REG3 
0x40C0,	//REG4 
0x0A1F,	//REG5 
0x002E,	//REG6 
0x02FF,	//REG7 
0x5B11,	//REG8 
0x0000,	//REG9 
0x411E,	//REG10 
0x0000,	//REG11 
0xCE00,	//REG12 
0x0000,	//REG13 
0x0000,	//REG14 
0x1000,	//REG15 
0x0010,	//REG16 
0x0000,	//REG17 
0x13FF,	//REG18 
0x9852,	//REG19 
0x0000,	//REG20 
0x0000,	//REG21 
0x0008,	//REG22 
0x0000,	//REG23 
0x51E0,	//REG24 
0x28BC,	//REG25 // 28DC 
0x2645,	//REG26 
0x00E4,	//REG27 
0x1CD8,	//REG28 
0x3A50,	//REG29 
0xEAF0,	//REG30 
0x3000,	//REG31 
0x0000,	//REG32 
0x0000,	//REG33 
}; 
 
#define BK1080_DEV_ADDRESS 0x80 
 
//kal_uint16 bk1080_last_freq=875; 
unsigned char Operation_Beken_FM_2w(unsigned char operation, unsigned char *data,kal_uint8 start_reg, unsigned char numBytes) 
{ 
	unsigned char controlWord,  j, error = 0; 
	int i; 
	int32 acknowledge=0; 
 
/*************************************************** 
 
START: make sure here SDIO_DIR =OUT, SCLK = 1,	SDIO = 1 
 
****************************************************/ 
	SerialCommStart(); 
 
/*************************************************** 
 
WRITE CONTROL DATA: make sure here: SLCK = 0; SDIO = 0 
 
****************************************************/ 
 
/*************************** 
 
CHECK ACK for control word 
 
***************************/ 
 
	acknowledge = SerialCommTxByte(BK1080_DEV_ADDRESS); 
 
	if(operation == READ) 
		acknowledge = SerialCommTxByte((start_reg<<1)|0x01); 
	else 
		acknowledge = SerialCommTxByte((start_reg<<1)); 
 
//kal_prompt_trace(MOD_MED_V,"OperationRda5800_2w   lrjaaaaaa acknowledge =%d ",acknowledge);   
 
 
/*************************************** 
 
WRITE or READ data 
 
****************************************/	 
 
/****************************** 
 
CHECK ACK or SEND ACK=0 
 
*******************************/ 
 
	for(j = 0; j < numBytes; j++, data++) 
	{ 
		if(operation == READ) 
		{ 
			if(j == (numBytes -1)) 
				SerialCommRxByte(data,1);  
			else 
				SerialCommRxByte(data, 0);  
		} 
		else 
			acknowledge = SerialCommTxByte(*data); 
		//kal_prompt_trace(MOD_MED_V,"OperationBekenFM_2w numBytes =%d acknowledge=%d,data=%x",numBytes,acknowledge,*data);  //lrj  add for test 20060522	 
	} 
/**************************** 
 
STOP: make sure here: SCLK = 0 
 
*****************************/ 
	SerialCommStop(); 
    
	return acknowledge; 
 
} 
 
void  BK1080_Mute(uint8 mute) 
{ 
	kal_uint8 TmpData8[2]; 
	Operation_Beken_FM_2w(READ,TmpData8,2,2); 
	if(mute) 
		TmpData8[0]|=0x40; 
	else 
		TmpData8[0]&=0xbf; 
 
	Operation_Beken_FM_2w(WRITE,&(TmpData8[0]),2,2);//write reg2 with 2 bytes 
} 
 
uint16 BK1080_FreqToChan(uint16 frequency) 
{ 
	return (frequency - 875); 
} 
 
 
void  BK1080_SetFreq(int16 curFreq) 
{ 
	uint16 curChan; 
 
	kal_uint8 TmpData8[2]; 
 
	TmpData8[0] =0x0; 
	TmpData8[1]= 0x0; 
	kal_prompt_trace(MOD_UEM,"BK1080_SetFreq curFreq=%d",curFreq); 
	curChan=BK1080_FreqToChan(curFreq); /*stop seek and tune*/ 
 
	TmpData8[0]=(curChan>>8)&0xff; 
	//TmpData8[0] |= 0x80;//start tune 
	TmpData8[1]=curChan&0xff; 
	Operation_Beken_FM_2w(WRITE,TmpData8,3,2); //write reg3,with 2 bytes 
//	kal_sleep_task(6); 
	TmpData8[0] |= 0x80;//start tune 
	Operation_Beken_FM_2w(WRITE,TmpData8,3,2); //write reg3,with 2 bytes 
 
//	kal_prompt_trace(MOD_MED_V,"TmpData8[%d] =0x%x;%x; ",2,TmpData8[0],TmpData8[1]); 
//	kal_prompt_trace(MOD_MED_V,"TmpData8[%d] =0x%x;%x; ",3,TmpData8[2],TmpData8[3]); 
//	kal_sleep_task(6); 
 
	//TmpData8[0] =0x0;//reset tune 
	//TmpData8[1]= 0x0; 
	TmpData8[0] &= 0x7f;//start tune 
	Operation_Beken_FM_2w(WRITE,TmpData8,3,2); //write reg3,with 2 bytes 
	_current_frequency = curFreq; 
 
} 
 
uint16 g_freq_deviation_array[1081-875];  //max length=channel number 
 
uint8 BK1080_ValidStop_2(int16 freq)  /* 自动搜索时,作为判定条件,再从中选择信号最强的9个台*/ 
{ 
	static int16 last_tuned_freq=0; 
	uint16 cur_freq_deviation; 
 
	kal_uint8 TmpData8[8]; 
 
	kal_prompt_trace(MOD_UEM,"BK1080_ValidStop_2 freq=%d\n",freq); 
	BK1080_SetFreq(freq); 
 
	kal_sleep_task(15);//delay 10ms 
 
//////////////////////////////////// 
//new added 2009-05-30 
	Operation_Beken_FM_2w(READ,TmpData8,0x07,2);//start from reg 0x7,with 2bytes 
 
	cur_freq_deviation=TmpData8[0]; 
	cur_freq_deviation<<=8; 
	cur_freq_deviation|=TmpData8[1]; 
	cur_freq_deviation=cur_freq_deviation>>4; 
 
	g_freq_deviation_array[freq-875]=cur_freq_deviation;//save deviation 
 
//////////////////////////////////// 
 
	Operation_Beken_FM_2w(READ,TmpData8,7,8);//start from reg7,with 8bytes 
	 
	if(TmpData8[6]&0x10)    //check AFCRL bit12 
	{ 
		last_tuned_freq=freq;//save last tuned freqency 
		return 0;//false 
	} 
#if defined(__M5070__) 
	if(TmpData8[7]<10) //RSSI<10 
#else 
	if(TmpData8[7]<5) //RSSI<10 
#endif 
	{ 
		last_tuned_freq=freq;//save last tuned freqency 
		return 0;//false 
	} 
 
	if( (TmpData8[1]&0xf) <2) //SNR<2 
	{ 
		last_tuned_freq=freq;//save last tuned freqency 
		return 0;//false 
	} 
#if defined(__M5070__) 
#if 0 
//add frequency devation check 
	if( (cur_freq_deviation>=0x100)&&(cur_freq_deviation<=(0xfff-0x100))) 
	{ 
		last_tuned_freq=freq;//save last tuned freqency 
 
		return 0;		 
	} 
#else  //修改FM搜台有很多重复和空台,更改这个问题请走else. 
//add frequency devation check 
	if( (cur_freq_deviation>=250)&&(cur_freq_deviation<=(0xfff-250)))      //100~280间   搜台少可增大该值,假台多可减小该值。 
	{ 
		last_tuned_freq=freq;//save last tuned freqency 
 
		return 0;		 
	} 
	 
//new added 2009-05-30 
	if( (freq>=876)&&( (freq-last_tuned_freq)==1) ) 
	{ 
		if(g_freq_deviation_array[freq-875-1]&0x800) 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			return 0;		 
		} 
 
		if(g_freq_deviation_array[freq-875-1]<150)      //50~200  搜台较少可减小该值,假台较多可增大该值。 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			return 0; 
		} 
	} 
	 
	if( (freq>=875)&&( (last_tuned_freq-freq)==1) ) 
	{ 
		if( (g_freq_deviation_array[freq-875+1]&0x800)==0) 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			//g_last_freq_deviation_value=cur_freq_deviation; 
			return 0; 
		} 
 
		if(g_freq_deviation_array[freq-875+1]>(0xfff-150) )           //50~200  搜台较少可减小该值,假台较多可增大该值。 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			//g_last_freq_deviation_value=cur_freq_deviation; 
			return 0; 
		} 
 
	} 
#endif 
#else  //__M5070__ 
#if 1 
//add frequency devation check 
	if( (cur_freq_deviation>=0x100)&&(cur_freq_deviation<=(0xfff-0x100))) 
	{ 
		last_tuned_freq=freq;//save last tuned freqency 
 
		return 0;		 
	} 
#else  //修改FM搜台有很多重复和空台,更改这个问题请走else. 
//add frequency devation check 
	if( (cur_freq_deviation>=0x200)&&(cur_freq_deviation<=(0xfff-0x200))) 
	{ 
		last_tuned_freq=freq;//save last tuned freqency 
 
		return 0;		 
	} 
	 
//new added 2009-05-30 
	if( (freq>=876)&&( (freq-last_tuned_freq)==1) ) 
	{ 
		if(g_freq_deviation_array[freq-875-1]&0x800) 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			return 0;		 
		} 
 
		if(g_freq_deviation_array[freq-875-1]<200) 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			return 0; 
		} 
	} 
	 
	if( (freq>=875)&&( (last_tuned_freq-freq)==1) ) 
	{ 
		if( (g_freq_deviation_array[freq-875+1]&0x800)==0) 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			//g_last_freq_deviation_value=cur_freq_deviation; 
			return 0; 
		} 
 
		if(g_freq_deviation_array[freq-875+1]>(0xfff-200) ) 
		{ 
			last_tuned_freq=freq;//save last tuned freqency 
			//g_last_freq_deviation_value=cur_freq_deviation; 
			return 0; 
		} 
 
	} 
#endif 
#endif  //__M5070__ 
	 
	last_tuned_freq=freq;//save last tuned freqency 
	//g_last_freq_deviation_value=cur_freq_deviation; 
 
	return 1; //OK       
} 
 
uint8 BK1080_ValidStop(int16 freq, int8 signalvl, bool is_step_up)  /* 自动搜索时,作为判定条件,再从中选择信号最强的9个台*/ 
{ 
	int32 targetFreq; 
	uint8 fm_count = 0; 
 
	kal_uint8 TmpData8[8]; 
 
	targetFreq = (int32)freq; 
  	FMDrv_Mute(0); 
	SerialCommInit(); 
 
	fm_count = 0; 
 
	while(fm_count <206) 
	{ 
		fm_count ++; 
 
		if (BK1080_ValidStop_2(targetFreq) == 0) 
		{ 
 
			if(is_step_up) 
			{ 
				targetFreq += 1; 
				if (targetFreq > 1080) 
				{ 
 
						targetFreq = 875; 
				} 
			} 
			else 
			{ 
				targetFreq -= 1; 
				if (targetFreq < 875) 
					targetFreq = 1080; 
			} 
		} 
		 
		//HWSearch_flag = 1; 
			//Valid_flag = 0; 
	} 
	if (fm_count > 205) 
	{ 
		FreqKHz = targetFreq; 
		return 0; 
	} 
	//dump_printf("BK1080_ValidStop success freq=%d\n",FreqKHz);		 
	FMDrv_Mute(1); 
 
   SerialCommRelease(); 
 
   return 1; 
} 
 
uint8 BK1080_GetSigLvl( int16 curf )  /*当满足rssi 的条件时,将信号记录,再选最强的9个频段*/ 
{ 
	kal_uint8 TmpData8[2]; 
	 
	if(875==curf) 
		return(1); 
	else 
	{ 
		Operation_Beken_FM_2w(READ,TmpData8,0x0a,2);//start from reg 0xa,with 2bytes 
		 
		return (TmpData8[1]);  /*返回rssi*/ 
	} 
} 
 
uint16 BK1080_GetCurIF(void) 
{ 
	kal_uint8 readdata[2]; 
 
	Operation_Beken_FM_2w(READ,readdata,10,2); 
 
	return (uint16)(readdata[1]); 
 
} 
 
bool  BK1080_IsChipValid(void) 
{ 
//	bool result; 
 
//	SerialCommCryClkOn(); 
//	kal_sleep_task(1); 
//	SerialCommInit(); 
//	result = BK1080_Intialization(); 
//	SerialCommCryClkOff(); 
	return 1; 
} 
 
void  BK1080_SetVolumeLevel(uint8 level)   /*一般不调用,即不用芯片来调节音量。*/ 
{ 
//	if(level) 
//	{ 
//		bk1080_writeData8[7]&=0xf0; 
//		bk1080_writeData8[7]|=level; 
//		Operation_Beken_FM_2w(WRITE,bk1080_writeData8,8,0x0a); 
//	} 
} 
 
bool  BK1080_Intialization(void) 
{ 
	kal_uint8 index = 0; 
	kal_uint8 ret = 0; 
	kal_uint8 ReadData8[2]; 
	kal_uint8 bk1080_writeData8[68]; 
	//kal_uint8 i; 
	 
	for(index=0;index<(1081-875);index++) 
		g_freq_deviation_array[index]=0;  //max length=channel number 
 
 
	//BK1080_EnableWire2(); 
	//kal_sleep_task(50); 
 
	Operation_Beken_FM_2w(READ,ReadData8,1,2);//check device ID 
 
	kal_prompt_trace(MOD_UEM,"bk1080 init id= %x",ReadData8[1]); 
//Write Digital REG 
	for(index = 0; index < 34; index++)//write reg2-reg31 ;reg0->device_id,reg1->chip_id only read ... 
	{ 
		bk1080_writeData8[index*2] = (BK1080_Digital_Reg[index] >> 8)&0xff; 
		bk1080_writeData8[index*2+1] = (BK1080_Digital_Reg[index])&0xff; 
	} 
 
	Operation_Beken_FM_2w(WRITE,&(bk1080_writeData8[0]),0,68);//start from reg2,total 60 byte 
#if 0 
	kal_sleep_task(20); 
	bk1080_writeData8[16*2+1] = ((BK1080_Digital_Reg[16])&0xff)|1; 
	Operation_Beken_FM_2w(WRITE,&(bk1080_writeData8[16*2]),16,2);//write from reg16,total 2 byte 
	kal_sleep_task(20); 
	bk1080_writeData8[16*2+1] = (BK1080_Digital_Reg[16])&0xff; 
	Operation_Beken_FM_2w(WRITE,&(bk1080_writeData8[16*2]),16,2);//write from reg16.total 2 byte 
#endif 
 
//	Operation_Beken_FM_2w(READ,ReadData8,1,2);//check device ID 
 
//	for(i = 0;i < 64 ; i++) 
//		kal_prompt_trace(MOD_MED_V,"OperationRda5800_2w   ReadData8[%d] =%d ",i,ReadData8[i]); 
 
	kal_sleep_task(100);	//delay 250ms 
#if 1 
	bk1080_writeData8[25*2+1] = ((BK1080_Digital_Reg[25])&0x7f); 
	Operation_Beken_FM_2w(WRITE,&(bk1080_writeData8[25*2]),25,2);//write from reg16,total 2 byte 
	//kal_sleep_task(20);	//delay 60ms 
	bk1080_writeData8[25*2+1] = (BK1080_Digital_Reg[25])&0xff; 
	Operation_Beken_FM_2w(WRITE,&(bk1080_writeData8[25*2]),25,2);//write from reg16.total 2 byte 
#endif 
 
	if(ReadData8[1]!=0x80)//device is not BK1080 
	{ 
	//	return 1;//error 
	} 
 
#if 0 
//start seek 
	bk1080_writeData8[2*2]&=0xfe; 
	Operation_Beken_FM_2w(WRITE,&(bk1080_writeData8[2*2]),2,2);//write from reg2,total 2 byte 
 
	bk1080_writeData8[2*2]=(BK1080_Digital_Reg[2] >> 8)&0xff; 
	bk1080_writeData8[2*2+1]=(BK1080_Digital_Reg[2])&0xff;//start seek 
	Operation_Beken_FM_2w(WRITE,&(bk1080_writeData8[2*2]),2,2);//write 
#endif  
 
	kal_sleep_task(50);   //解决收音机power off 之后回到之前的同一个频点 
	BK1080_SetFreq(875); 
	BK1080_Mute(1);  //添加延时 
	return 0; 
} 
 
void  BK1080_PowerOnReset(void) 
{ 
	kal_uint8 TmpData8[2]; 
 
	kal_prompt_trace(MOD_UEM,"BK1080_PowerOnReset"); 
 
	SerialCommCryClkOn(); 
	kal_sleep_task(10); 
	SerialCommInit(); 
	//kal_sleep_task(10); 
	BK1080_Intialization(); 
	kal_sleep_task(50); 
	_is_fm_on = true; 
	//Operation_Beken_FM_2w(READ,TmpData8,2,2); //read reg2,with 2 bytes 
	//TmpData8[1]=TmpData8[1]&0xbe; 
	//Operation_Beken_FM_2w(WRITE,TmpData8,2,2); 
} 
 
void  BK1080_PowerOffProc(void) 
{ 
	kal_uint8 TmpData8[2]; 
 
	kal_prompt_trace(MOD_UEM,"BK1080_PowerOffProc"); 
 
	Operation_Beken_FM_2w(READ,TmpData8,2,2); //read reg2,with 2 bytes 
 
	TmpData8[1]=TmpData8[1]|0x41; 
	Operation_Beken_FM_2w(WRITE, TmpData8, 2,2); 
	kal_sleep_task(5); 
	SerialCommCryClkOff(); 
	_is_fm_on = false; 
} 
 
uint16 BK1080_GetChipID(void) 
{ 
	kal_uint8 ReadData8[2]; 
	uint16 chipid; 
	 
	Operation_Beken_FM_2w(READ,ReadData8,1,2);//check device ID 
	 
	chipid = ((uint16)ReadData8[0] << 8) + (uint16)ReadData8[1]; 
	 
	kal_prompt_trace(MOD_UEM,"bk1080 chip id=%x, reg1=%x%x",chipid,ReadData8[0],ReadData8[1]); 
	return chipid; 
} 
#elif defined(QN8035) 
#include "l1audio_def.h" 
#include "qndriver.h" 
#include "qnio.h" 
 
#define FM_32K	              75// Base band 32k clock output	 
#define FM_32K_MOD 		 2// 3  
 
 
 
extern void SerialCommInit(void); 
extern void SerialCommRelease(void); 
extern void SerialCommCryClkOn(void); 
extern void SerialCommCryClkOff(void); 
/* 
void SerialCommInit(void) 
{ 
	GPIO_ModeSetup(SCL,0); 
	GPIO_ModeSetup(SDA,0); 
	GPIO_InitIO(1,SCL); 
	GPIO_InitIO(1,SDA); 
	GPIO_WriteIO(1,SCL); 
 	GPIO_WriteIO(1,SDA);  
} 
 
void SerialCommRelease(void) 
{ 
	GPIO_WriteIO(0,SCL); 
	GPIO_WriteIO(0,SDA); 
} 
 
extern kal_uint8 FM_SetClk_32K(kal_uint8 numLpo,kal_bool enable); 
 
void SerialCommCryClkOn(void) 
{ 
       
	GPIO_ModeSetup(FM_32K, FM_32K_MOD);	 
	//GPIO_SetClkOut(FM_32K, FM_32K_MOD); 
	 //GPIO_SetClkOut(FM_32K_MOD, 4); 
	 FM_SetClk_32K(FM_32K,KAL_TRUE); 
	Msdelay(10); 
} 
void SerialCommCryClkOff(void) 
{ 
	GPIO_ModeSetup(FM_32K,0); 
	//GPIO_SetClkOut(FM_32K_MOD, 0); 
	FM_SetClk_32K(FM_32K,KAL_FALSE); 
	Msdelay(10); 
} 
*/ 
 
 
void FMDrv_radio_item_info(kal_uint16 group_idx, kal_uint16 item_idx, kal_uint32 item_value) 
{ 
 
} 
 
void FMDrv_SetVolumeLevel(UINT8 level) 
{ 
    QND_RXConfigAudio(QND_CONFIG_VOLUME,level); 
} 
void FMDrv_Mute(UINT8 mute) 
{ 
	SerialCommInit(); 
 
	if (mute == 1) 
		QND_RXConfigAudio(QND_CONFIG_MUTE, 1 ); 
	else 
		QND_RXConfigAudio(QND_CONFIG_MUTE, 0 ); 
 
	SerialCommRelease(); 
} 
void FMDrv_PowerOnReset(void) 
{ 
      sys_print(0,"FMDrv_PowerOnReset start"); 
	SerialCommCryClkOn(); 
	SerialCommInit();	 
	QND_Init(); 
	QND_SetSysMode(QND_MODE_FM|QND_MODE_RX); 
	//QND_RXConfigAudio(QND_CONFIG_MUTE, 1 ); 
	//QND_RXConfigAudio(QND_CONFIG_VOLUME,40); 
	//QND_RXConfigAudio(QND_CONFIG_MUTE, 0 ); 
	//SerialCommRelease(); 
	sys_print(0,"FMDrv_PowerOnReset end"); 
} 
 
void FMDrv_PowerOffProc(void) 
{ 
	//SerialCommInit(); 
	QND_SetSysMode(QND_MODE_SLEEP); 
	SerialCommCryClkOff(); 
	//SerialCommRelease(); 
} 
void FMDrv_SetFreq( int16 curf ) 
{ 
	UINT16 ch; 
      sys_print(0,"FMDrv_SetFreq"); 
	SerialCommInit(); 
 
	ch = (UINT16)(curf*10); 
	QND_TuneToCH(ch); 
 
	SerialCommRelease(); 
} 
 
uint16 FMDrv_GetSigLvl( int16 curf ) 
{ 
	UINT16 ch; 
	UINT16 rssi; 
       sys_print(0,"FMDrv_GetSigLvl"); 
	SerialCommInit(); 
 
	ch = (UINT16)(curf*10); 
	rssi=QND_GetRSSI(ch); 
 
	SerialCommRelease(); 
 
	return rssi; 
	 
} 
uint16 FMDrv_GetIF( int16 curf) 
{ 
    //	return 120; 
} 
 
void FMDrv_EvaluateRSSIThreshold(void) 
{ 
	//kal_prompt_trace(MOD_MMI,"FMDrv_EvaluateRSSIThreshold"); 
} 
 
uint8 FMDrv_ValidStop(int16 freq, int8 signalvl, bool is_step_up) 
 
{ 
	UINT16 temp; 
	sys_print(0,"FMDrv_ValidStop"); 
	#if defined(__D252_INA__) 
	QND_RXSetTH(2);  //actually,for saving time of automatic scan channel,only need call once when enter to automatic seeking mode before. 
	#else 
	QND_RXSetTH(3);  //actually,for saving time of automatic scan channel,only need call once when enter to automatic seeking mode before. 
	#endif 
    temp = QND_RXValidCH((UINT16)(freq * 10), QND_FSTEP_100KHZ); 
	if(temp) 
		return 1; 
	else 
		return 0; 
} 
 
void FMDrv_ChipInit(void) 
{ 
    /* uint16 reg; 
	 sys_print(0,"start to write"); 
      QND_WriteReg(0x07,0xaa); 
	reg = QND_ReadReg(0x07);  
	sys_print(0,"reg = %x",reg); 
	//kal_prompt_trace(MOD_MMI,"FMDrv_ChipInit"); 
	*/ 
	uint16  FMChipid; 
	 
	FMChipid =QND_ReadReg(0x06); 
	sys_print(0,"QN8035 chip id=%x",FMChipid); 
	if(FMChipid == 0x84) 
	{	   
	  //SerialCommInit();	 
	  //QND_Init(); 
	  sys_print(0,"FMDrv_ChipInit");	 
	  //SerialCommCryClkOff(); 
	}	 
	 
} 
 
bool FMDrv_IsChipValid( void ) 
{ 
	return true; 
} 
 
 
 
void FMDrv_HWSearch(int16 freq, bool is_step_up, int16 space, bool is_preset) 
{ 
    
 
		 
} 
 
uint8 FMDrv_HWSpolling(uint16 *curf, uint8 *is_valid) 
{ 
 
 
  
} 
#endif // defined(AR1000A1)