📄 cs1100_fm.c
字号:
/*****************************************************************************
* 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 Cresilicon Technology Co.,Ltd (C) 2008
*
*****************************************************************************/
/*******************************************************************************
* Filename: CS1100_FM_Tuner_Driver_Reference_Code_SW-Rev05.2.c
* ------------
* Project:
* ------------
* Description:
* ------------
* Author:
* ------------
* Revision History Rev02.0: 2008-03-14 Add Register Configuration of CS1100's reference clock seletion
* Revision History Rev03.0: 2008-03-21 modified in the functions of CS1100_FMInit and CS1100_FMSeekFromCurrentCh
* Revision History Rev04.0: 2008-03-28 modified the initial value of registers
* Revision History Rev05.1: 2008-04-10 modified the seek function; bool CS1100_FMSeek_TuneMethod(unsigned int TunerFrequency)--->bool CS1100_FMSeek_TuneMethod(unsigned int TunerFrequency, signed short *pryFD )
* Delete function: bool CS1100_FMSeekFromCurrentCh(bool seekUp, unsigned int *TunedFrequency,)
* Add function: void CS1100_FM_SET_volume(unsigned int volume)
* Revision History Rev05.2: 2008-04-11 Add some Judgements to eliminate issue channel which is a interfere frequency just in band [87.5MHZ~108MHZ]
*
*
*
*
* ------------
*******************************************************************************/
/*
********************************************************************************************
* Current Version: Rev05 for CS1100
* Description: the reference driver code describes I2C protocol between FM tuner and MCU
* by GPIO method, and how to implement FM tuner power up/power down/tune/seek functions
********************************************************************************************
*/
/**************************************************************************************
* macro definition for slave address of I2C protocol control, i.e. FM tuner address
**************************************************************************************/
#define CS1100_RD_CTRL 0x0021
#define CS1100_WR_CTRL 0x0020
#define SDA_HIGH SDA=1
#define SDA_LOW SDA=0
#define SCL_HIGH SCL=1
#define SCL_LOW SCL=0
#define SDA_OUT //function to enable SDA pin output
#define SDA_IN //function to enable SDA pin input
#define ISSUE_CHANNEL 10400
unsigned int CS1100ControlData[26];
void SetSDAState(unsigned int state)
{
SDA=(bool)(state);
}
unsigned int GetSDAState(void)
{
return (unsigned int)SDA;
}
/**************************************************************************************
* how to implement I2C protocol control between FM tuner and MCU of main chip by GPIO method
**************************************************************************************/
void DelayXus(unsigned int X)
{
unsigned int i;
for(i = X/2; i >= 1; i--)
delay_nops(CurrCpuFreq);
}
void I2C_Start(void)
{
SCL_HIGH;
SDA_HIGH;
DelayXus(1);
SDA_OUT;
DelayXus(50);
SDA_LOW;
DelayXus(30);
SCL_LOW;
DelayXus(20);
}
void I2C_Stop(void)
{
SCL_LOW;
SDA_LOW;
DelayXus(2);
SDA_OUT;
DelayXus(2);
SCL_LOW;
SDA_LOW;
DelayXus(10);
SCL_HIGH;
DelayXus(20);
SDA_HIGH;
DelayXus(20);
}
void I2C_SendAck(unsigned int ack)
{
SetSDAState(ack);
DelayXus(1);
SDA_OUT;
SCL_HIGH;
DelayXus(20);
SCL_LOW;
DelayXus(20);
}
unsigned int I2C_SendByte(unsigned int byte)
{
int i;
unsigned int ack = 0;
SetSDAState(byte&0x80);
SDA_OUT;
DelayXus(10);
for(i=7;i>=0;i--)
{
SetSDAState(byte&0x80);
byte <<= 1;
DelayXus(20);
SCL_HIGH;
DelayXus(40);
SCL_LOW;
DelayXus(20);
}
SDA_IN;
DelayXus(10);
SCL_HIGH;
DelayXus(40);
ack=GetSDAState();
SCL_LOW;
DelayXus(40);
return ack;
}
unsigned int I2C_ReadByte(void)
{
int i;
unsigned int byte = 0;
SDA_IN;
DelayXus(10);
for(i=7;i>=0;i--)
{
SCL_HIGH;
DelayXus(20);
byte <<= 1;
byte |= GetSDAState();
DelayXus(20);
SCL_LOW;
DelayXus(40);
}
return byte;
}
unsigned int I2C_ReadCS1100Reg(unsigned int *data,unsigned int size) //state=0->success state=1->fail
{
unsigned int i,state = 0;
I2C_Start();
if(I2C_SendByte(CS1100_RD_CTRL))
{
state = 1;
goto I2C_STOP;
}
for(i=0;i<size-1;i++)
{
data[i] = I2C_ReadByte();
I2C_SendAck(0);
}
data[i] = I2C_ReadByte();
I2C_SendAck(1);
I2C_STOP:
I2C_Stop();
return state;
}
unsigned int I2C_WriteCS1100Reg(unsigned int *data,unsigned int size) //state=0->success state=1->fail
{
unsigned int i,state = 0;;
I2C_Start();
if(I2C_SendByte(CS1100_WR_CTRL))
{
state = 1;
goto I2C_STOP;
}
for(i=0;i<size;i++)
{
if(I2C_SendByte(data[i]))
{
state = 1;
break;
}
}
I2C_STOP:
I2C_Stop();
return state;
}
/**************************************************************************************
* how to implement FM tuner initialization/tune/seek/stereo indicator functions
**************************************************************************************/
/**************************************************************************************
* 函数名称:CS1100_FMInit
* 功 能:
* 输入参数:
* 输出参数:
* 说 明:FM power up and initialization operation
**************************************************************************************/
void CS1100_FMInit(void)
{
// initial default value of CS1100 READ/WRITE registers 03h~0Eh
CS1100ControlData[0] = 0xe4;
CS1100ControlData[1] = 0xd8;
CS1100ControlData[2] = 0x3e;
CS1100ControlData[3] = 0x26;
CS1100ControlData[4] = 0x1f;
CS1100ControlData[5] = 0x80;
CS1100ControlData[6] = 0x38;
CS1100ControlData[7] = 0x53;
CS1100ControlData[8] = 0xb3;
CS1100ControlData[9] = 0xb3;
CS1100ControlData[10] = 0xaa;
CS1100ControlData[11] = 0xf0;
CS1100ControlData[12] = 0x8b;
CS1100ControlData[13] = 0xaa;
CS1100ControlData[14] = 0xc0;
CS1100ControlData[15] = 0x04; //
CS1100ControlData[16] = 0x25;
CS1100ControlData[17] = 0x35;
CS1100ControlData[18] = 0xff;
CS1100ControlData[19] = 0xfd;
CS1100ControlData[20] = 0x92;
CS1100ControlData[21] = 0x0f;
CS1100ControlData[22] = 0x44;
CS1100ControlData[23] = 0x00;
CS1100ControlData[24] = 0x84;
CS1100ControlData[25] = 0x50;
//*******************************************************
//Reference clock is from 32.768KHz external clock input: 外灌时钟
CS1100ControlData[6] = 0x28;
CS1100ControlData[15] = 0x00;
//Reference clock is from 13MHz external clock input: 外灌时钟
CS1100ControlData[6] = 0x68;
CS1100ControlData[15] = 0x00;
//Reference clock is from 32.768KHz crystal oscillator : 晶体
CS1100ControlData[6] = 0x38;
CS1100ControlData[15] = 0x04;
//******************************************************
CS1100ControlData[0] &= 0x7f; //power up
I2C_WriteCS1100Reg(CS1100ControlData,26);
Delay1Ms(1000); // wait 1s for crystal oscillate stable
CS1100ControlData[0] &= 0xdf; // mute off
I2C_WriteCS1100Reg(CS1100ControlData,1);
}
/**************************************************************************************
* 函数名称:CS1100_FMTune
* 功 能:
* 输入参数:TunerFrequency, the unit is 10kHz
* 输出参数:
* 说 明:Tune to certain frequency and output audio
**************************************************************************************/
void CS1100_FMTune(unsigned int TunerFrequency) // 频率转换参数 87.5 ==>8750
{
unsigned int ch = 0;
// frequency transfer to channel number, channel=(frequencyMhz-60)/0.05, e.g. 87.5Mhz->550
ch = (TunerFrequency - 6000)/5;
// set channel number
CS1100ControlData[2] &= 0xfc;
CS1100ControlData[2] |= (ch & 0x0300)>>8;
CS1100ControlData[3] = ch & 0xff;
//
// tune function
CS1100ControlData[0] &= 0xdf;// mute off
CS1100ControlData[0] &= 0xfd;// tune=0
I2C_WriteCS1100Reg(CS1100ControlData,4);
CS1100ControlData[0] |= 0x02;//tune=1, begin tune operaton
I2C_WriteCS1100Reg(CS1100ControlData,1);
Delay1Ms(100); // wait for 100ms
}
/**************************************************************************************
* 函数名称:CS1100_FMSeek_TuneMethod
* 功 能:
* 输入参数:unsigned int TunerFrequency, the frequency unit is 10kHz
* 输出参数:bool seekover, return the indicator if the seek operation is completed
* signed short *pryFD,return current channel's fd
* 说 明:seek operation with tune method step by step, judge the threshold by the software
**************************************************************************************/
bool CS1100_FMSeek_TuneMethod(unsigned int TunerFrequency, signed short *pryFD)
{
unsigned int ch = 0;
unsigned int snr,rssi,st,loop;
signed short fd;
bool seekover, stcflag;
unsigned int Temp[27] = { 0x00 };
// frequency transfer to channel number, channel=(frequencyMHz-60)/0.05, e.g. 87.5Mhz->550
ch = (TunerFrequency - 6000)/5;
CS1100ControlData[2] &= 0xfc;
CS1100ControlData[2] |= (ch & 0x0300)>>8;
CS1100ControlData[3] = ch & 0xff;
// seek operation
CS1100ControlData[0] |= 0x20; //mute on
CS1100ControlData[0] &= 0xfd; //tune=0
I2C_WriteCS1100Reg(CS1100ControlData,4);
CS1100ControlData[0] |= 0x02; // TUNE=1, begin tune operation
I2C_WriteCS1100Reg(CS1100ControlData,1);
Delay1Ms(50); // delay 50ms - 100ms
// read STC indicator and judgement of seek threshold
seekover=0;
stcflag=0;
loop=0;
do
{
I2C_ReadCS1100Reg(Temp,6);
stcflag=Temp[0]&0x04; // STC bit
loop++;
Delay1Ms(1); // delay 1ms
}while((!stcflag)&&(loop!=0x1f));
if(stcflag) //STC=1
{
rssi=Temp[1];
snr=Temp[2]/4;
fd=Temp[5];
st=Temp[0]&0x01;
if(fd>127)
{
fd=fd-256;
}
if(rssi>=176 && snr<=38 && ( fd<=10 && fd>=(-10) )) //seek threshold judgement
{
if(*pryFD <= -30) //Note seek direction is seek up
{
if(TunerFrequency == 9600 || TunerFrequency == 10400)
{
if (st==0x01) //Note: now Reg03[6] must be set 0
seekover=1; //a valid frequency
else
seekover=0; //a invalid frequency
}
else
seekover=1;
}
else
seekover=0;
}
else
{
seekover=0;
}
*pryFD = fd; //save current frequency's fd
}
return seekover;
}
/**************************************************************************************
* 函数名称:CS1100_FMPowerdown
* 功 能:
* 输入参数:
* 输出参数:
* 说 明:power down chip
**************************************************************************************/
void CS1100_FMPowerdown(void)
{
CS1100ControlData[0] |= 0x20; // mute on
CS1100ControlData[0] |= 0x80; // power down
I2C_WriteCS1100Reg(CS1100ControlData,1);
}
/**************************************************************************************
* 函数名称:CS1100_FM_PAMode
* 功 能:CS1100从FM Tuner模式进入LINE-IN PA模式
* 说 明:需要先初始化FM Tuner寄存器
**************************************************************************************/
void CS1100_FM_PAMode(void)
{
//旧步骤
// CS1100ControlData[2] |= 0x80; // line-in PA mode on
// CS1100ControlData[14] |= 0x38; // power down not used blocks
// CS1100ControlData[15] |= 0x68; // power down not used blocks
// I2C_WriteCS1100Reg(CS1100ControlData,16);
// 新步骤
CS1100ControlData[2] |= 0x40; //pa off,minimun volume
CS1100ControlData[0] & =0xbf; //Analog Config
I2C_WriteCS1100Reg(CS1100ControlData,3);
CS1100ControlData[0] &= 0x7f; //power on
I2C_WriteCS1100Reg(CS1100ControlData,1);
Delay1Ms(1000);
CS1100ControlData[2] &= 0xbf; //pa on
I2C_WriteCS1100Reg(CS1100ControlData,3);
Delay1Ms(50);
CS1100ControlData[2] |= 0x80; //line in mode
CS1100ControlData[0] |=0x20; //mute on
I2C_WriteCS1100Reg(CS1100ControlData,3);
CS1100ControlData[14] |= 0x39; //cut down the current
CS1100ControlData[15] |= 0xf8;
I2C_WriteCS1100Reg(CS1100ControlData,16);
//CS1100ControlData[0] |= 0xc0; //power off ??
//I2C_WriteCS1100Reg(CS1100ControlData,1);
}
/**************************************************************************************
* 函数名称:CS1100_FM_TunerMode
* 功 能:CS1100从LINE-IN PA模式恢复到FM Tuner模式
* 说 明:需要先初始化FM Tuner寄存器
**************************************************************************************/
void CS1100_FM_TunerMode(void)
{
//旧步骤
// CS1100ControlData[2] &= 0x7f; // line-in PA mode off
// CS1100ControlData[14] &= 0xc7; // power on blocks
// CS1100ControlData[15] &= 0x97; // power on blocks
// I2C_WriteCS1100Reg(CS1100ControlData,16);
//新步骤
CS1100ControlData[2] |= 0x40; //PA off,minimun volume
CS1100ControlData[0] |= 0x40;
CS1100ControlData[14] &= 0xCB; //Power up DSP
CS1100ControlData[15] &= 0x07;
I2C_WriteCS1100Reg(CS1100ControlData,16);
CS1100ControlData[0] &= 0x7f; //power on
I2C_WriteCS1100Reg(CS1100ControlData,1);
Delay1Ms(1000);
CS1100ControlData[2] &= 0xbf; //volume
I2C_WriteCS1100Reg(CS1100ControlData,3);
Delay1Ms(50);
CS1100ControlData[2] &= 0x7f;//fm mode
I2C_WriteCS1100Reg(CS1100ControlData,3);
}
/**************************************************************************************
* 函数名称:CS1100_FM_SET_volume
* 功 能:
* 输入参数:unsigned int volume
* 输出参数:
* 说 明:Set CS1100 FM Volume
**************************************************************************************/
void CS1100_FM_SET_volume(unsigned int volume)
{
unsigned int temp;
if(volume > 0x0f)
{
volume = 0x0f;
}
CS1100ControlData[2]&= 0xc3; //0xc3=11000011
temp = volume<<2;
temp &= 0x3c; //0x3c=00111100
CS1100ControlData[2] |= temp;
I2C_WriteCS1100Reg(CS1100ControlData,3);
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -