fm_philip5767.c
来自「君正早期ucos系统(只有早期的才不没有打包成库),MPLAYER,文件系统,图」· C语言 代码 · 共 603 行
C
603 行
/********************** BEGIN LICENSE BLOCK ************************************
*
* JZ4740 mobile_tv Project V1.0.0
* INGENIC CONFIDENTIAL--NOT FOR DISTRIBUTION IN SOURCE CODE FORM
* Copyright (c) Ingenic Semiconductor Co. Ltd 2005. All rights reserved.
*
* This file, and the files included with this file, is distributed and made
* available on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
* EXPRESS OR IMPLIED, AND REALNETWORKS HEREBY DISCLAIMS ALL SUCH WARRANTIES,
* INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY, FITNESS
* FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
*
* http://www.ingenic.cn
*
********************** END LICENSE BLOCK **************************************
*
* Author: <xyzhang@ingenic.cn>
*
* Create: 2008-06-26, by xyzhang
*
* Maintain:
*
*
*******************************************************************************
*/
#include "FM_Philip5767.h"
#include "jz4740.h"
//------------------------------------------------------------------------------
//// Private globals
#define UP 1
#define DOWN 0
#define TUNE_FOUND 1
#define BAND_LIMIT 0
#define TRUE 1
#define FALSE 0
#define DEVCLK 11200000
#define I2C_READ 1
#define I2C_WRITE 0
#define TIMEOUT 1000
/* error code */
#define ETIMEDOUT 1
#define ENODEV 2
unsigned char ucWritData[5] = {0x00, 0x00, 0x20, 0x17, 0x00};
unsigned char ucReadData[5] = {0x00, 0x00, 0x00, 0x00, 0x00};
unsigned int frequency =87500;//kHZ
unsigned int pll;
//------------------------------------------------------------------------------
/*
* I2C bus protocol basic routines
*/
static int i2c_put_data(unsigned char data)
{
unsigned int timeout = TIMEOUT*10;
__i2c_write(data);
__i2c_set_drf();
while (__i2c_check_drf() != 0);
while (!__i2c_transmit_ended());
while (!__i2c_received_ack() && timeout)
timeout--;
if (timeout)
return 0;
else
return -ETIMEDOUT;
}
static int i2c_get_data(unsigned char *data, int ack)
{
int timeout = TIMEOUT*10;
if (!ack)
__i2c_send_nack();
else
__i2c_send_ack();
while (__i2c_check_drf() == 0 && timeout)
timeout--;
if (timeout) {
if (!ack)
__i2c_send_stop();
*data = __i2c_read();
__i2c_clear_drf();
return 0;
} else
return -ETIMEDOUT;
}
int i2cucs_read(unsigned char device, unsigned char *buf,
int count)
{
unsigned char *ptr = buf;
int cnt = count;
int timeout = 5;
REG_GPIO_PXFUNS(3) = (3 << 23); //GPD23,GPD24
REG_GPIO_PXSELS(3) = (3 << 23);
REG_GPIO_PXTRGC(3) = (3 << 23);
__i2c_set_clk(DEVCLK, 10000); /* default 10 KHz */
__i2c_enable();
L_try_again:
if (timeout < 0)
goto L_timeout;
__i2c_send_start();
if (i2c_put_data( (device << 1) | I2C_READ ) < 0)
goto device_rerr;
__i2c_send_ack(); /* Master sends ACK for continue reading */
while (cnt) {
if (cnt == 1) {
if (i2c_get_data(buf, 0) < 0)
break;
} else {
if (i2c_get_data(buf, 1) < 0)
break;
}
cnt--;
buf++;
}
__i2c_send_stop();
udelay(300); /* wait for STOP goes over. */
__i2c_disable();
return count - cnt;
device_rerr:
device_werr:
offset_err:
timeout --;
__i2c_send_stop();
goto L_try_again;
L_timeout:
printf("Read I2C device 0x%2x failed.\n", device);
__i2c_send_stop();
udelay(300); /* wait for STOP goes over. */
__i2c_disable();
return -ENODEV;
}
int i2cucs_write(unsigned char device, unsigned char *buf,
int count)
{
int cnt = count;
int cnt_in_pg;
int timeout = 5;
unsigned char *tmpbuf;
REG_GPIO_PXFUNS(3) = (3 << 23); //GPD23,GPD24
REG_GPIO_PXSELS(3) = (3 << 23);
REG_GPIO_PXTRGC(3) = (3 << 23);
__i2c_set_clk(DEVCLK, 10000); /* default 10 KHz */
__i2c_enable();
__i2c_send_nack(); /* Master does not send ACK, slave sends it */
W_try_again:
if (timeout < 0)
goto W_timeout;
cnt = count;
tmpbuf = (unsigned char *)buf;
start_write_page:
cnt_in_pg = 0;
__i2c_send_start();
if (i2c_put_data( (device << 1) | I2C_WRITE ) < 0)
goto device_err;
while (cnt) {
if (++cnt_in_pg > 8) {
__i2c_send_stop();
mdelay(1);
goto start_write_page;
}
if (i2c_put_data(*tmpbuf) < 0)
break;
cnt--;
tmpbuf++;
}
__i2c_send_stop();
udelay(300); /* wait for STOP goes over. */
__i2c_disable();
return count - cnt;
device_err:
timeout--;
__i2c_send_stop();
goto W_try_again;
W_timeout:
printf("Write I2C device 0x%2x failed.\n", device);
__i2c_send_stop();
udelay(300); /* wait for STOP goes over. */
__i2c_disable();
return -ENODEV;
}
char i2c_sim_common_read(unsigned char ucSlaveID, unsigned char *pucBuffer, unsigned char ucBytes)
{
return (char)(i2cucs_read(ucSlaveID, pucBuffer,ucBytes));
}
char i2c_sim_common_write(unsigned char ucSlaveID, unsigned char *pucBuffer, unsigned char ucBytes)
{
return (char)(i2cucs_write(ucSlaveID, pucBuffer,ucBytes));
}
//------------------------------------------------------------------------------
void sleep(unsigned int time)
{
//unsigned int i;
//for( i = 0; i < time; i++)
//{}
OSTimeDly(1);
}
static int save_reg[4];
static int aic_init(void )
{
save_reg[0]=REG_AIC_FR;
save_reg[1]=REG_AIC_I2SCR;
save_reg[2]=REG_ICDC_CDCCR1;
save_reg[3]=REG_ICDC_CDCCR2;
REG_AIC_FR |= 0x00000030;
REG_AIC_FR &= 0xFFFFFFF9;
REG_AIC_I2SCR &= 0xFFFFFFFE;
REG_ICDC_CDCCR1 = 0x28002000;
REG_ICDC_CDCCR2 &=0xffe0fffc;
REG_ICDC_CDCCR2 |=0x00130000;
return (TRUE);
}
static void aic_deinit(void )
{
REG_AIC_FR= save_reg[0];
REG_AIC_I2SCR= save_reg[1];
REG_ICDC_CDCCR1=save_reg[2];
REG_ICDC_CDCCR2=save_reg[3];
}
void fm_set_stby(void)
{
ucWritData[3]|=0x40;
fm_write();
return;
}
int fm_deinit(void)
{
aic_deinit();
ucWritData[3]|=0x40;
fm_write();
return (TRUE);
}
//------------------------------------------------------------------------------
int fm_init( void )
{
int bRet = FALSE;
unsigned char i;
if ( !aic_init())
return (FALSE);
i = 0;
ucWritData[3] &=0xBF;
fm_get_pll();
printf("Write1:%x,Write2:%x,Write3:%x,Write4:%x,Write5:%x\n",ucWritData[0],ucWritData[1],ucWritData[2],ucWritData[3],ucWritData[4]);
fm_write();
sleep(500);
fm_read();
printf("Read1:%x,Read2:%x,Read3:%x,Read4:%x,Read5:%x\n",ucReadData[0],ucReadData[1],ucReadData[2],ucReadData[3],ucReadData[4]);
while (i)
{
mul_search ();
i--;
switch(i)
{
case 4:
frequency = 103900;
break;
case 3:
frequency = 97400;
break;
case 2:
frequency = 91500;
break;
case 1:
frequency = 87600;
break;
}
}
//auto_search_save ( UP);
return ( bRet );
}
//-----------------------------------------------------------------------------
int fm_hlsi_optimal(unsigned int freq)
{
unsigned char status;
int temp;
unsigned char levelhigh, levellow;
freq = freq+450;
fm_get_pll(); // Set PLL value High
status = fm_write(); // Send Command
sleep(100);
status = fm_read(); // Read status
levelhigh = ((ucReadData[3] >> 4) & 0x0f); // Get ADC value
freq = freq-450;
fm_get_pll(); // Set PLL value Low
status = fm_write();
sleep(100);
status = fm_read();
levellow = ((ucReadData[3] >> 4) & 0x0f); // Get ADC value
if(levelhigh < levellow)
temp = 1;
else
temp = 0;
return temp;
}
//------------------------------------------------------------------------------
//Calculate PLL from frequency
void fm_get_pll(void)
{
unsigned char hlsi,temp;
unsigned int twpll=0;
hlsi=ucWritData[2]&0x10;
if(ucWritData[3]&0x20)
{
if(frequency >91000)
frequency = 91000;
else if (frequency < 76000)
frequency = 76000;
}
else
{
if(frequency > 108000)
frequency = 108000;
else if (frequency < 87500)
frequency = 87500;
}
if (hlsi)
pll=(unsigned int)((float)((frequency + 225 ) * 4000) / (float)32768); //k
else
pll=(unsigned int)((float)((frequency - 225) * 4000) / (float)32768); //k
temp = (ucWritData[0] & 0xC0);
ucWritData[0] = (unsigned char)(pll/256);//Search mode
ucWritData[0] |= temp;
ucWritData[1] = (unsigned char)(pll%256);
}
//------------------------------------------------------------------------------
void fm_set_volume(int vol_level)
{
if(vol_level==0)
REG_ICDC_CDCCR1 |= 0x00004000;
else
{
REG_ICDC_CDCCR1 &=0xFFFFBFFF;
REG_ICDC_CDCCR2 &=0xffe0fffc;
REG_ICDC_CDCCR2 |=(vol_level<<16);
}
}
int fm_get_volume(void)
{
int vol;
if (REG_ICDC_CDCCR1 & 0x00004000)
{
vol = 0;
return vol;
}
else
{
vol = (REG_ICDC_CDCCR2 & 0x001f0000);
return (vol>>16);
}
}
int fm_get_max_vol(void)
{
return (31);
}
int fm_get_min_vol(void)
{
return (0);
}
//Calculate frequency from PLL
void fm_set_frequency(int freq)
{
frequency = freq;
fm_get_pll();
fm_write();
fm_get_status();
printf("Read1:%x,Read2:%x,Read3:%x,Read4:%x,Read5:%x\n",ucReadData[0],ucReadData[1],ucReadData[2],ucReadData[3],ucReadData[4]);
}
int fm_get_frequency(void)
{
unsigned char hlsi;
unsigned int npll=0;
npll=pll;
hlsi=ucWritData[2]&0x10;
if (hlsi)
frequency=(unsigned int)(((float)(npll * 32768) / 4 - 225000)/1000); //KHz
else
frequency=(unsigned int)(((float)(npll * 32768) / 4 + 225000)/1000); //KHz
return frequency;
}
char fm_is_band_limit( void )
{
if ( ucReadData[0] & 0x40 )
return ( TRUE );
else
return ( FALSE );
}
char fm_is_ready( void )
{
if ( ucReadData[0] & 0x80 )
return ( TRUE );
else
return ( FALSE );
}
//------------------------------------------------------------------------------
unsigned int fm_open (unsigned int dwData, unsigned int dwAccess, unsigned int dwShareMode) {return (4);}
//------------------------------------------------------------------------------
int fm_read(void)
{
int bRet;
unsigned char temp_l,temp_h;
bRet = i2c_sim_common_read(TEA5767_READ_ADDR, ucReadData, 5);
temp_l = ucReadData[1];
temp_h = ucReadData[0];
temp_h &= 0x3f;
pll = ((temp_h << 8 )| temp_l);
fm_get_frequency();
return (bRet);
}
//------------------------------------------------------------------------------
int fm_write(void)
{
int bRet = FALSE;
bRet = i2c_sim_common_write(TEA5767_WRITE_ADDR, ucWritData, 5);
return (bRet);
}
//------------------------------------------------------------------------------
void mul_search (void )
{
unsigned char i;
fm_get_pll();
fm_write();
fm_read();
}
int auto_search ( int direc)
{
unsigned char i;
fm_read();
fm_get_pll();
if(direc)
{
ucWritData[2]=0xC0;
ucWritData[2]&=0xEF;
frequency += 100;
}
else
{
ucWritData[2]=0x40;
ucWritData[2]|=0x10;
frequency -= 100;
}
fm_get_pll();
ucWritData[0]|= 0x40;//Search mode
fm_write();
sleep(2000);
fm_read();
while(!fm_is_ready()) //Flag of search successful
{
fm_read();
}
if ( fm_is_band_limit() )
return (BAND_LIMIT);
else
return (TUNE_FOUND);
}
void auto_search_save( int dir )
{
unsigned char bRet = TRUE;
unsigned int channel[100][2]; //index and frequency
unsigned char i = 0;
if (dir)
{
do
{
sleep(10000);
i++;
bRet = auto_search( UP );
if (bRet && frequency)
{
channel[i][0] =i;
channel[i][1] =frequency;
printf("channel:%d,frequency:%d\r\n",i,channel[i][1] );
}
sleep(100000);
if ( i>100 )
break;
}while (bRet);
}
else
{
i = 0;
do
{
i++;
bRet = auto_search( DOWN );
if (bRet && frequency)
{
channel[i][0] =i;
channel[i][1] =frequency;
printf("channel:%d,frequency:%d\r\n",i,channel[i][1] );
}
if (i==0)
break;
}while (bRet);
}
}
int fm_set_status( int mute, int stereo, int level, int band)
{
if (!mute)
ucWritData[0]|=0x80;//mute
else
ucWritData[0]&=0x7F;//play
if (stereo)
ucWritData[2]|=0x8;
else
ucWritData[2]&=0xF7;
level = (level << 5);
ucWritData[2]&=0x9F;
ucWritData[2]|=level;
if (band)//0--us/e
ucWritData[3]|=0x20;
else
ucWritData[3]&=0xDF;
if(fm_write())
return TRUE;
return FALSE;
}
int fm_get_status( void )
{
//bit[0]--Ready flag,bit[1]--band limit reach,bit[2]--stereo,
//bit[3]--Reserved,bit[4]~bit[5]--level ADC Output(low,mid,high).
int status=0;
int temp_IF=0,temp_LEV=0;
fm_read();
/* if (ucReadData[0]& 1 )
status |=1;//Ready flag
if (ucReadData[0]& 0x2)
status |=(1<<1);//band limit flag
*/
if (ucReadData[2]&0x80)
status |=(1<<2);//stereo flag
temp_LEV=(ucReadData[3]& 0xF0)>>4;
temp_IF=(ucReadData[2]& 0x7F);
printf("LEV=%d,IF =%d\n",temp_LEV,temp_IF);
if ((temp_LEV == 8)&& (temp_IF==0x38 ))
status |= 0x30;//level high,true channel
return status;
}
int fm_set_mute(int mute)
{
if (!mute)
ucWritData[0]|=0x80;//mute
else
ucWritData[0]&=0x7F;//play
if(fm_write())
return TRUE;
return FALSE;
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?