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

📄 fm.c

📁 tea 5767收音 模块源代码
💻 C
字号:
#include "include/FM.h"
#include "include/main.h"

#ifdef  RADIO_INCLUDE
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 delay760(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 ------------------------------------- */
void fm_i2c_comm_s(void)
{	
	
	fm_i2c_wr
	fm_i2c_data_lo
	delay760(fm_i2c_Thold);
	fm_i2c_clk_lo
	delay760(fm_i2c_Thold);
}

void fm_i2c_out_byte(unsigned char *ptr)
{	
	unsigned char i, temp;

	fm_i2c_wr
	for(i=0;i<8;i++)
	{
		temp = *ptr << i;
		temp &= 0x80;
		if(temp) fm_i2c_data_hi
		else	 fm_i2c_data_lo
		delay760(fm_i2c_Tsetup);
		
		fm_i2c_clk_hi
		delay760(fm_i2c_Thold);
		
		fm_i2c_clk_lo
		delay760(fm_i2c_Thold);
	}
}

unsigned char fm_i2c_get_ack(void)
{	
	unsigned int i=0;
	
	fm_i2c_rd

	fm_i2c_clk_hi
	delay760(fm_i2c_Tcatch);
	
	i = (unsigned int)(HwGDATA_B & 0x100);
	delay760(fm_i2c_Tcatch);
	
	fm_i2c_clk_lo
	delay760(fm_i2c_Thold);
	
	return i;
}

void fm_i2c_in_byte(unsigned char *ptr)
{
	unsigned char i, temp=0;
	
	fm_i2c_rd

	for(i=0;i<8;i++)
	{
		fm_i2c_clk_hi
		delay760(fm_i2c_Tcatch);
			
		temp = (unsigned char)((HwGDATA_B & 0x100) >> 8 ); // 
		if(i == 0) *ptr = temp;
		else *ptr = (*ptr << 1) | temp;

		delay760(fm_i2c_Tcatch);
		
		fm_i2c_clk_lo
		delay760(fm_i2c_Thold);
	}
}

void fm_i2c_do_ack(unsigned char bit)
{

	fm_i2c_wr

	if(bit) fm_i2c_data_hi
	else 	fm_i2c_data_lo
	delay760(fm_i2c_Tsetup);
		
	fm_i2c_clk_hi
	delay760(fm_i2c_Thold);
	
	fm_i2c_clk_lo
	delay760(fm_i2c_Thold);
}

void fm_i2c_comm_p(void)
{

	fm_i2c_wr
	fm_i2c_data_lo
	delay760(fm_i2c_Tsetup);
	
	fm_i2c_clk_hi
	delay760(fm_i2c_Thold);
	
	fm_i2c_data_hi
	delay760(fm_i2c_Tbuf);
}

///////////////////////////////////////////////

unsigned char fm_rd_rtn(unsigned char *ptr)
{
	unsigned char i = fm_rd_cmd;
					
	fm_i2c_wr;
	fm_i2c_clk_hi;
	fm_i2c_data_hi;
	delay760(fm_i2c_Tbuf);

	fm_i2c_comm_s();

	fm_i2c_out_byte(&i);
	
	if(fm_i2c_get_ack() != i2c_ack) 
	{
		fm_i2c_comm_p();
		return i2c_err;
	}
	
	for(i=0;i<5;i++)
	{		
		fm_i2c_in_byte(ptr);
		
		if(i < 4) fm_i2c_do_ack(i2c_ack);
		else	  fm_i2c_do_ack(i2c_noack);
		
		ptr++;
	}
	
	fm_i2c_comm_p();
	
	return i2c_ok;
}

unsigned char fm_wr_rtn(unsigned char *ptr)
{
	unsigned char i = fm_wr_cmd;
		
	fm_i2c_wr;
	fm_i2c_clk_hi;
	fm_i2c_data_hi;
	delay760(fm_i2c_Tbuf);

	fm_i2c_comm_s();

	fm_i2c_out_byte(&i);
	
	if(fm_i2c_get_ack() != i2c_ack) 
	{
		fm_i2c_comm_p();
		return i2c_err;
	}
	
	for(i=0;i<5;i++)
	{		
		fm_i2c_out_byte(ptr);
		
		if(fm_i2c_get_ack()) ;
		else		  	  ;
		
		ptr++;
	}
	
	fm_i2c_comm_p();
	
	return i2c_ok;
}

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
	delay760(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);
	delay760(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;

	fm_i2c_wr;
	fm_i2c_clk_hi;
	fm_i2c_data_hi;
//	fm_pwr_on;
	delay760(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_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_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);
								
							
	delay760(20000);					
					
	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 > 2) && (0x33 < curifc) && (curifc < 0x3c)  ) return	1; // scan_level

	else	return	0;
}

//extern unsigned int init_fm_khz;
void 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);
}
/*
unsigned char fm_auto_scan_neon(unsigned char dir)
{
	unsigned char status, curlev, curifc;
	
	if(dir)
	{
		if(fm_khz >= 108000) fm_khz = 78500;
		else				 fm_khz += scan_step;
	}
	else
	{	
		if(fm_khz <= 78500) fm_khz = 108000;
		else				fm_khz -= scan_step;
	}
	
	fmw_all_mute_rtn(on);
	
	status = fm_hilo_optimal(fm_khz);
	fmw_pll_rtn(status, fm_khz);
		
	status = fm_wr_rtn(fm_wr_byte);
									
	LCD_DisplayChannelForFM(fm_khz);
//	LCD_Display_String_Clear(3);
//	lcd_var(0, 3, fm_khz);
														
	delay760(40000);delay760(40000);delay760(40000);delay760(40000);
																																		
	status = fm_rd_rtn(fm_rd_byte);
	curlev = fmr_level_adc_rtn();
	curifc = fmr_if_count_rtn();
		
	if((curlev > scan_level) && (0x33 < curifc) && (curifc < 0x3b)) return	1;
	else															return	0;
}
*/
#endif

⌨️ 快捷键说明

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