⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 fmrda5800_1_5.c

📁 5800C Fm芯片资料和驱动代码 技术特点: *国内首颗采用CMOS工艺的调频收音机芯片; *驱动能力强
💻 C
字号:
//1.0 , 04/16/2007, lilin, RDA
//1.1 , 06/01/2007, lilin, RDA, insert 50ms delay in FmWaitSTC1 subprogram.
//1.2 , 06/22/2007, lilin, RDA, add stopseek and filter false station
//1.3 , 07/29/2007, lilin, RDA, move filter false station function into FmSeek, remove FmSearch, FmWaitSTC1_stopseek
//1.4 , 08/13/2007, lilin, RDA, use seek_singlestep function if want to display incremetal frequency station
//1.5 , 08/27/2007, lilin, RDA, adjust seek time to minimize, use delay 100ms to replace polling STC

#define     	FMRDA5800_GLOBALS

#include "FMRDA5800.h"


//Globals
XWORD FMshadowReg[45];
XWORD FMseekChannels[FMCHANNELSMAX];

CWORD	cwFMDefault[]={
0x0000,
0x0000,	
0xd881,	//0x02
0x6300,
0x4400,	//0x04
0x10ff, //0x13ff, lilin, 06/22, 0x10f8, //0x05
0x0000,
0x00cd,
0x0096,
0x0020,
0x4163,
0x0806,
0x5800,
0x5800,
0x5800,
0x5800,
0x4c17,	//lilin, 08/13, seek_singlestep, 0x4817,
0x20a2,
0x0000,
0x000f,
0x06de,
0xecc0,
0x0200,
0x5383,
0x95a4,
0xe848,
0x0500,	//0x0500, lilin, 06/22, 0x0500,
0x00a4, //0x00a4, lilin, 06/22, 0x00a4,
0x889b,
0x0d84,
0x4f04,
0x8832,
0x7f71,
0x0660,
0x4010,
0x6002,
0x1808,
0x6458,
0x787f,
0x0100,
0xc040,
0xc020,
0x0024,
0x0400,
0x0020,
};

//================================================================
WORD FmChanToFreq(BYTE channel) large
{
	WORD channelSpacing;
	WORD bottomOfBand;
	WORD frequency;

	if ((FMshadowReg[3] & 0x0002) == 0x0000) 
		bottomOfBand = 875;
	else 	
		bottomOfBand = 760;
	if ((FMshadowReg[3] & 0x0001) == 0x0000) 
		channelSpacing = 1;
	else if ((FMshadowReg[5] & 0x0001) == 0x0001) 
		channelSpacing = 2;
	else 
		channelSpacing = 1;

	frequency = (bottomOfBand + channelSpacing * channel);
	return (frequency);
}


//================================================================
WORD FmFreqToChan(WORD frequency) large 
{
	WORD channelSpacing;
	WORD bottomOfBand;
	WORD channel;

	if ((FMshadowReg[3] & 0x0002) == 0x0000) 
		bottomOfBand = 875;
	else 	
		bottomOfBand = 760;
	if ((FMshadowReg[3] & 0x0001) == 0x0000) 
		channelSpacing = 1;
	else if ((FMshadowReg[5] & 0x0001) == 0x0001) 
		channelSpacing = 2;
	else 
		channelSpacing = 1;

	channel = (frequency - bottomOfBand) / channelSpacing;
	return (channel);
}


//================================================================
//BYTE FmWaitSTC1(void) large
//{
//#if(WAITGPIO2)
//
//	WORD i;
//	
//	WAIT_FOR_GPIO2();
//
//	//for(i=0x2000;i>0;i--);
//	delay 70ms ;		//lilin, 06/22, change the delay to 70ms 
//	
//	return(1);
//	
//#else
//
//	BYTE readData8[2];
//
//	do
//	{	
//		//!!!!! lilin add, 06/01/2007
//		//for(i=0x2000;i>0;i--) ;	//lilin add, 06/01/2007, insert delay in continous polling STC, 50ms or 100ms is preferable
//		delay 70ms ;		//lilin, 06/22, change the delay to 70ms		
//		if(i2c_rd(I2C_FM,I2C_FM_RD_DATA,2,readData8)==0) return(0);
//		//lilin, 08/13, change to software seek
//		//lilin, 06/22, add to show readchan
//		//READCHAN = readData8[1];
//		
//		//lilin, 08/13, change to software seek
//		//if(STOPSEEK)		//when user press button
//		//  FmStopSeek(seekDirection);
//		  			
//	}while((readData8[0]&0x40)==0); 
//	
//	return(1);
//			
//#endif
//}
//
//
//================================================================
//lilin, 08/13, change to software seek
//lilin, 06/22, set SEEKTH=0 to stop seek operation
/*
BYTE FmStopSeek(BYTE seekDirection)  
{
	BYTE writeData8[8];
	
	//set seek and seekup bit as in FmSeek 		
	if(seekDirection == 0) 
		writeData8[0] = ((FMshadowReg[2]>>8) | 0x01);	// seek down
	else 
		writeData8[0] = ((FMshadowReg[2]>>8) | 0x03); 	// seek up

	writeData8[1] = (FMshadowReg[2]);
	writeData8[2] = (READCHAN);				//Tune to channel that seek operation just on 
	writeData8[3] = (FMshadowReg[3]);
	writeData8[4] = (FMshadowReg[4] >> 8);
	writeData8[5] = (FMshadowReg[4]);
	writeData8[6] = (0x00);					//set SEEKTH=0 to stop seek operation
	writeData8[7] = (FMshadowReg[5]);
		
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,8,writeData8)==0) return(0);
	
	return(1);
}
*/


//================================================================
//BYTE FmWaitSTC0(void) large
//{
//	WORD i;
//	//for(i=0x2000;i>0;i--) ;	//lilin note, 07/03/27, this timer should longer than 50ms
//	delay 70ms ;		//lilin, 06/22, change the delay to 70ms
//	
//	return(1);
//}


//================================================================
BYTE FmInit(void) large
{

	WORD i,j;
	XBYTE writeData8[86],xbTemp;		

	I2C_FM_SEN_1();
	I2C_FM_RST_0();	
	_nop_();
	_nop_();
	_nop_();
	I2C_FM_RST_1();	
	_nop_();
	_nop_();
	_nop_();

	
	for(xbTemp = 0; xbTemp < 45; xbTemp++)
		FMshadowReg[xbTemp] = cwFMDefault[xbTemp];
		
	//lilin, for wait 0.5s after enable RCLK
	writeData8[0] = 0xd8;		//0x02   0xd881
	writeData8[1] = 0x81;		//0x81;		
	
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);

#if(DCXO)	
	//wait 500ms for RCLK stable,
	//for(i=0x500;i>0;i--)	
	//	for(j=0x500;j>0;j--) ; 	//wait 500ms for RCLK stable
	delay 500ms; 			//lilin, 06/22, not specify how to get 500ms delay
#endif		
	
	for(xbTemp = 0; xbTemp < 43; xbTemp++)
	{
		writeData8[xbTemp*2] = (FMshadowReg[xbTemp+2] >> 8);
		writeData8[xbTemp*2+1] = (FMshadowReg[xbTemp+2]);
	}
		
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,86,writeData8)) 
	{
	}
	else
	return (0);
	
	
	//lilin, Tune caused by write REG 03H just now
	//wait STC==1
	//if(FmWaitSTC1()==0) return(0);
	delay 100ms;
	
	//clear STC and lab_mode at the same time, from now only could access register 00H~0FH
	//writeData8[0] = 0xd0;		//0x02   0xd081
	//writeData8[1] = 0x81;		//0x81;		
	
	//if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);
	//guarantee STC=0	
	//if(FmWaitSTC0()==0) return(0);

}


//================================================================
BYTE FmTune(WORD channel) large
{
	BYTE readData8[32];
	BYTE writeData8[4];

 	writeData8[0] = 0xd0;		//0x02   0xd081
	writeData8[1] = 0x81;		
	
	writeData8[2] = channel; 	//0x03	 
	writeData8[3] = 0x00; 
	
	if(i2c_wr(I2C_FM,I2C_FM_WR_DATA,4,writeData8)==0) return(0);				
	
	//wait STC=1
	//if(FmWaitSTC1()==0) return(0);
	delay 100ms;
		
	//read REG0A&0B	
	#if(FMTEST)	
	if (i2c_rd(I2C_FM,I2C_FM_RD_DATA,32,readData8)==0) return(0);
	#else	
	if (i2c_rd(I2C_FM,I2C_FM_RD_DATA,4,readData8)==0) return(0);
	#endif	
	FMshadowReg[10] = readData8[0]*0x100 + readData8[1];
	FMshadowReg[11] = readData8[2]*0x100 + readData8[3];  
	#if(FMTEST)	
	FMshadowReg[12] = readData8[4]*0x100 + readData8[5];
	FMshadowReg[13] = readData8[6]*0x100 + readData8[7]; 
	FMshadowReg[14] = readData8[8]*0x100 + readData8[9];
	FMshadowReg[15] = readData8[10]*0x100 + readData8[11]; 
	FMshadowReg[0] = readData8[12]*0x100 + readData8[13];
	FMshadowReg[1] = readData8[14]*0x100 + readData8[15]; 
	FMshadowReg[2] = readData8[16]*0x100 + readData8[17];
	FMshadowReg[3] = readData8[18]*0x100 + readData8[19]; 
	FMshadowReg[4] = readData8[20]*0x100 + readData8[21];
	FMshadowReg[5] = readData8[22]*0x100 + readData8[23]; 
	FMshadowReg[6] = readData8[24]*0x100 + readData8[25];
	FMshadowReg[7] = readData8[26]*0x100 + readData8[27]; 
	FMshadowReg[8] = readData8[28]*0x100 + readData8[29];
	FMshadowReg[9] = readData8[30]*0x100 + readData8[31];
	#endif
	
	//clear STC
	//writeData8[0] = 0xd0;		//0x02   0xd081
	//writeData8[1] = 0x81;		//0x81;
	
	//if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);
	
	//wait STC=0	
	//if(FmWaitSTC0()==0) return(0);
	
	return(1);
	
}

		
//================================================================
//lilin, 08/13, use seek_singlestep function to easy display frequency station	
BYTE FmSingleSeek(BYTE seekDirection) large
{
	BYTE readData8[4];
	BYTE writeData8[8];
	
	//set seek bit		
	if(seekDirection == 0) 
		writeData8[0] = ((FMshadowReg[2]>>8) | 0x01);	// seek down
	else 
		writeData8[0] = ((FMshadowReg[2]>>8) | 0x03); 	// seek up
		
	writeData8[1] = FMshadowReg[2];
	
	if(i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);
	
	//wait STC=1
	//if(FmWaitSTC1()==0) return(0);
	delay 100ms;	
       			
	//clear STC
	//writeData8[0] = (FMshadowReg[2] >> 8);
	//writeData8[1] = (FMshadowReg[2]);
	//if(i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);
	
	//wait STC=0	
	//if(FmWaitSTC0()==0) return(0);
	
	return(1);
	
}
	
//================================================================	
BYTE FmSeek(BYTE seekDirection) large
{
	BYTE readData8[4];
	BYTE writeData8[8];
	BOOL fStopSeek=0;
	bool falseStation=0;
	
	do{
	        
	        fStopSeek=0;
	        falseStation=0;
	        
		if(FmSingleSeek(seekDirection)==0) return(0);
        	
		//read REG0A&0B	
		if(i2c_rd(I2C_FM,I2C_FM_RD_DATA,4,readData8)==0) return(0);	
		FMshadowReg[10] = readData8[0]*0x100 + readData8[1];
		FMshadowReg[11] = readData8[2]*0x100 + readData8[3];
		
		READCHAN = readData8[1];
		//check whether SF=1
		if((readData8[0]&0x20)!=0) falseStation=1;
		//check station RSSI again, if RSSI<SEEKTH, then falseStation, continue seek
		if(readData8[2] < (FMshadowReg[5]>>8)) falseStation=1;
		
		if(STOPSEEK) fStopSeek=1;	
				
	}while((falseStation==1)&&(fStopSeek==0));	
		
}


//================================================================
BYTE FmEnterSleep(void) large 
{
	BYTE writeData8[2];
	
	FMshadowReg[2] = 0xd080; //ENABLE = 0
	
	writeData8[0] = (FMshadowReg[2] >> 8);
	writeData8[1] = (FMshadowReg[2]);
	
	if(i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);
	
}


//================================================================
BYTE FmExitSleep(void) large
{
	
	BYTE readData8[4];
	BYTE writeData8[4];
	
	writeData8[0] = 0xd0;		//0x02   0xd081
	writeData8[1] = 0x81;		
	
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);

#if(DCXO)	
	//wait 500ms for RCLK stable,
	//for(i=0x500;i>0;i--)	
	//	for(j=0x500;j>0;j--) ; 	//wait 500ms for RCLK stable
	delay 500ms; 			//lilin, 06/22, not specify how to get 500ms delay
#endif		

 	writeData8[0] = 0xd0;		//0x02   0xd081
	writeData8[1] = 0x81;		
	
	//tune to orginal channel
	writeData8[2] = channel; 	//0x03	 
	writeData8[3] = 0x00; 
	
	if(i2c_wr(I2C_FM,I2C_FM_WR_DATA,4,writeData8)==0) return(0);				
	
	//wait STC=1
	//if(FmWaitSTC1()==0) return(0);
	delay 100ms;
		
	if (i2c_rd(I2C_FM,I2C_FM_RD_DATA,4,readData8)==0) return(0);
	FMshadowReg[10] = readData8[0]*0x100 + readData8[1];
	FMshadowReg[11] = readData8[2]*0x100 + readData8[3];  
	
	//clear STC
	//writeData8[0] = 0xd0;		//0x02   0xd081
	//writeData8[1] = 0x81;		//0x81;
	//if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);
	
	//wait STC=0	
	//if(FmWaitSTC0()==0) return(0);
	
	return(1);		

}


//================================================================
BYTE FmSetMute(void)
{
	BYTE writeData8[2];

	FMshadowReg[2] = 0x9881; 		// MUTE ENABLE = 1
		
	writeData8[0] = (FMshadowReg[2] >> 8);
	writeData8[1] = (FMshadowReg[2]);
		
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8))
	{	
		return (1);
	}
	else	
		return (0);
	
}


//================================================================
BYTE FmSetNoMute(void)
{
	BYTE writeData8[2];
	
	FMshadowReg[2] = 0xd081; 		// MUTE ENABLE = 0
		
	writeData8[0] = (FMshadowReg[2] >> 8);
	writeData8[1] = (FMshadowReg[2]);
		
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8))
	{	
		return (1);
	}
	else	
		return (0);
		
}


//================================================================
//lilin, 06/22, set tune_freq_diff when set volume, to avoid trigger tune
BYTE FmSetVolume(BYTE volume)
{
	BYTE writeData8[8];
	
	FMshadowReg[2] = 0xd091; 		// set tune_freq_diff, to avoid trigger tune
		
	writeData8[0] = (FMshadowReg[2] >> 8);
	writeData8[1] = (FMshadowReg[2]);
	writeData8[2] = (FMshadowReg[3] >> 8);
	writeData8[3] = (FMshadowReg[3]);
	writeData8[4] = (FMshadowReg[4] >> 8);
	writeData8[5] = (FMshadowReg[4]);
	writeData8[6] = (FMshadowReg[5] >> 8);
	writeData8[7] = (volume);
		
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,8,writeData8)==0) return(0);
	
	FMshadowReg[2] = 0xd081; 		// clear tune_freq_diff, for normal operation
		
	writeData8[0] = (FMshadowReg[2] >> 8);
	writeData8[1] = (FMshadowReg[2]);	
	
	if (i2c_wr(I2C_FM,I2C_FM_WR_DATA,2,writeData8)==0) return(0);

	return (1);
		
}


//================================================================
BYTE FmAutoSeek (BYTE *numChannels) large
{
	BYTE doneSeeking = 0;
	BYTE chanIndex;
	chanIndex = 0;
	
	// tune to the bottom of the band
	if (FmTune(0)==0) return(0);
	
	// seek through the band
	while (!doneSeeking) 
	{
		if (FmSeek(1)==0)
		{
			*numChannels = chanIndex;	
			return (0);
		}
		
		// done seeking if
		// at least one channel has been found previously (chanIndex != 0) and
		// current channel is lower frequency than previous channel
		// (indicating the seek has wrapped the band)
		if ((chanIndex != 0) && ((FMshadowReg[10]&0x00ff) <= (FMseekChannels[chanIndex-1]))) 
			doneSeeking = 1;
		// otherwise store the channel and keep seeking
		else
		{
			if((FMshadowReg[10]&0x2000)==0)
			{
			FMseekChannels[chanIndex] = (FMshadowReg[10]&0x00ff); 	// store chan
			chanIndex++; 					// increment channel index
			if (chanIndex == FMCHANNELSMAX) doneSeeking = 1;// max channels stored
			}
		}
	}
	
	*numChannels = chanIndex;
	if(chanIndex) 	return(1);
	else		return(0);
	
}

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -