📄 tuner_pal.c
字号:
/******************************************************************************
Copyright (c) 2004 MStar Semiconductor, Inc.
All rights reserved.
[Module Name]: DevTuner.c
[Date]: 30-Mar-2004
[Comment]:
TV tuner subroutines.
[Reversion History]:
*******************************************************************************/
#define TUNER_PAL_C
// System
// Common
#include <stdio.h>
#include <math.h>
#include "board.h"
#include "DataType.h"
#include "Drviic.h"
#include "drvTimer.h"
#include "drvVD.h"
#include "msAPI_VD.h"
#include "Tuner_pal.h"
#include "ZL10353.H"
#define DEBUG_PAL_TUNER 0
#if DEBUG_PAL_TUNER
#define DBG_TN(x) printf x
#define PAL_DBG_MSG(x) x
#else
#define DBG_TN(x)
#define PAL_DBG_MSG(x)
#endif
TunerProgramType g_TunerPara;
U16 g_TuneFreqIF;
#if (FRONTEND_TUNER_TYPE==FRONTEND_IF_MIXER_TYPE==FRONTEND_IF_DEMODE_TYPE==THOMSON_FE6640_TUNER)
#define SETTING_AT_INITIAL 0
void devTunerSet_COFDM_I2C_BypassTable(BOOLEAN ONOFF)
{
//#if(FRONTEND_DEMOD_TYPE==ZARLINK_ZL10353_DEMODE)
#if 1
if(ONOFF==ENABLE)
ZL10353_RepeatControl(ENABLE);
else
ZL10353_RepeatControl(DISABLE);
#endif
}
void devTunerSetTable(void)
{
BOOLEAN bResult;
devTunerSet_COFDM_I2C_BypassTable(ENABLE);
#if (SETTING_AT_INITIAL==1)
MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x00, 0x0000, 0x8000);
MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x03, 0x0000, 0x000C);
#endif
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x1001, 0x0021);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x1010, 0x00CA);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x1012, 0x0008);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x1013, 0x000A);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x1016, 0x01C0);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x10B0, 0x0001);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x100F, 0x05B0);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x100F, 0x0580);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x100E, 0x0000);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x100E, 0x0001);
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x10, 0x1017, 0x0022);
devTunerSet_COFDM_I2C_BypassTable(DISABLE);
}
code U16 tIFBCETable[TUNER_SOUND_NUMS][8][2] =
{
{ // B/G
{0x0020, 0x0103},
{0x1022, 0x013D},
{0x1002, 0x02BC},
{0x1073, 0x012E},
{0x1072, 0x00C5},
{0x1071, 0x0197},
{0x1070, 0x000F},
{0xFFFF, 0xFFFF},
},
{ // I
{0x0020, 0x0103},
{0x1022, 0x0134},
{0x1002, 0x0314},
{0x1073, 0x0192},
{0x1072, 0x0028},
{0x1071, 0x01F6},
{0x1070, 0x0007},
{0xFFFF, 0xFFFF},
},
{ // DK
{0x0020, 0x0004},
{0x1022, 0x0134},
{0x1002, 0x02D0},
#if 1 // China
{0x1073, 0x0192},
{0x1072, 0x0028},
{0x1071, 0x01FA},
{0x1070, 0x0007},
#else // Europe
{0x1073, 0x018E},
{0x1072, 0x00B0},
{0x1071, 0x0198},
{0x1070, 0x0001},
#endif
{0xFFFF, 0xFFFF},
},
{ // L
{0x0020, 0x0009},
{0x1022, 0x0134},
{0x1002, 0x028a},
{0x1073, 0x0192},
{0x1072, 0x0028},
{0x1071, 0x01F6},
{0x1070, 0x0007},
{0xFFFF, 0xFFFF},
},
{ // LL
{0x0020, 0x0109},
{0x1022, 0x0198},
{0x1002, 0x028A},
{0x1073, 0x0192},
{0x1072, 0x0028},
{0x1071, 0x01F6},
{0x1070, 0x0007},
{0xFFFF, 0xFFFF},
},
};
void devTunerSetIF( EnuTunerSoundSystem ucSoundSystem )
{
BOOLEAN bResult;
U8 i, ucTemp;
i = 0;
ucTemp = (ucSoundSystem==TUNER_SOUND_AUTO)?0:ucSoundSystem-1;
devTunerSet_COFDM_I2C_BypassTable(ENABLE);
#if (SETTING_AT_INITIAL==0)
MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x00, 0x0000, 0x8000);
MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR, 0x03, 0x0000, 0x000C);
#endif
while(tIFBCETable[ucTemp][i][0] != 0xFFFF)
{
bResult = MDrv_IIC_WriteGroupBytes(TN_IF_I2C_ADDR,
0x10,
tIFBCETable[ucTemp][i][0],
tIFBCETable[ucTemp][i][1]);
i++;
}
devTunerSet_COFDM_I2C_BypassTable(DISABLE);
#if (SETTING_AT_INITIAL==0)
devTunerSetTable();
#endif
}
void devTunerSetSubSys( EnuTunerSoundSystem ucSoundSystem )
{
devTunerSetIF( ucSoundSystem );
if( TUNER_SOUND_LL == ucSoundSystem )
g_TuneFreqIF = 33.95 * 16;
else
g_TuneFreqIF = 38.9 * 16;
}
U16 devTunerGetIF_Quality(U8 u8Times)
{
U16 u16Data, u16LastData;
devTunerSet_COFDM_I2C_BypassTable(ENABLE);
u16LastData = MDrv_IIC_ReadGroupBytes(TN_IF_I2C_ADDR, 0x11, 0x100C);
do
{
MDrv_Timer_Delayms(5);
u16Data = MDrv_IIC_ReadGroupBytes(TN_IF_I2C_ADDR, 0x11, 0x100C);
if(abs(u16Data-u16LastData)<0x10)
break;
u16LastData = u16Data;
}while(u8Times--);
devTunerSet_COFDM_I2C_BypassTable(DISABLE);
return u16Data;
}
U8 devTunerGetIF_AFC(void)
{
U16 u16Data;
devTunerSet_COFDM_I2C_BypassTable(ENABLE);
u16Data = MDrv_IIC_ReadGroupBytes(TN_IF_I2C_ADDR, 0x11, 0x100B);
devTunerSet_COFDM_I2C_BypassTable(DISABLE);
return (U8)((u16Data>>1)&0xFF);
}
U8 devTunerWrite(TunerProgramType *pProgParam)
{
U8 ucStatus, ucLoop;
ucLoop = 20;
devTunerSet_COFDM_I2C_BypassTable(ENABLE);
MDrv_IIC_WriteBytes(TN_PROG_I2C_ADDR, 0, NULL, sizeof(TunerProgramType), (U8 *)pProgParam);
MDrv_Timer_Delayms(5);
pProgParam->ControlInfo1 = (pProgParam->ControlInfo1&0xC7)|0x18;
pProgParam->ControlInfo2 = 0xA0;
MDrv_IIC_WriteBytes(TN_PROG_I2C_ADDR, 0, NULL, sizeof(TunerProgramType), (U8 *)pProgParam);
MDrv_Timer_Delayms(100);
pProgParam->ControlInfo1 = (pProgParam->ControlInfo1&0xC7)|0x18;
pProgParam->ControlInfo2 = 0x20;
MDrv_IIC_WriteBytes(TN_PROG_I2C_ADDR, 0, NULL, sizeof(TunerProgramType), (U8 *)pProgParam);
devTunerSet_COFDM_I2C_BypassTable(DISABLE);
MDrv_Timer_Delayms(150);
while(--ucLoop)
{
MDrv_Timer_Delayms(5);
ucStatus = devTunerGetStatus(5);
if( (ucStatus&(TN_READ_VIFL|TN_READ_AFCWIN)) == (TN_READ_VIFL|TN_READ_AFCWIN) ) //check PLL is locked
{
MDrv_Timer_Delayms(5);
ucStatus = devTunerGetStatus(5);
if( (ucStatus&(TN_READ_VIFL|TN_READ_AFCWIN)) == (TN_READ_VIFL|TN_READ_AFCWIN) ) //check PLL is locked
break;
}
}
PAL_DBG_MSG(printf("\r\nAfter TunerWirte = 0x%bx",ucStatus));
return ucStatus; // tuner status
}
U8 devTunerSetFreq( U16 wFreq )
{
#if (PATCH_PAL_VTOTAL624SHAKE)
U8 u8Bank;
u8Bank = XBYTE[BK_SELECT_00]; // store bank
XBYTE[BK_SELECT_00] = REG_BANK_COMB;
MDrv_WriteRegBit( BK_COMB_50, ENABLE,_BIT0);//enable H/W auto Htotal
XBYTE[BK_SELECT_00] = u8Bank; // recovery bank
#endif
// Pal tuner:
g_TunerPara.ProgDivide = wFreq + g_TuneFreqIF;
if( wFreq < (136.15 * 16) )
g_TunerPara.ControlInfo1 = 0xF6;
else if( wFreq < (185.15 * 16) )
g_TunerPara.ControlInfo1 = 0xFE;
else if( wFreq < (422.15 * 16) )
g_TunerPara.ControlInfo1 = 0xF6;
else if( wFreq < (465.15 * 16) )
g_TunerPara.ControlInfo1 = 0xFE;
else if( wFreq < (766.15 * 16) )
g_TunerPara.ControlInfo1 = 0xF6;
else if( wFreq < (904.15 * 16) )
g_TunerPara.ControlInfo1 = 0xFE;
else
g_TunerPara.ControlInfo1 = 0xF6;
if( wFreq < (185.15*16) ) // low bank
g_TunerPara.ControlInfo2 = 0x11;
else if( wFreq < (465.15 * 16)) // middle ban
g_TunerPara.ControlInfo2 = 0x12;
else
g_TunerPara.ControlInfo2 = 0x18;
return(devTunerWrite(&g_TunerPara));
}
U8 devTunerSetChannel( EnuTunerSoundSystem ucSoundSystem, U16 wFreq )
{
devTunerSetSubSys( ucSoundSystem );
return (devTunerSetFreq( wFreq ));
}
void devTunerInitialize(void)
{
#if (SETTING_AT_INITIAL==1)
devTunerSetTable();
#endif
}
U8 devTunerGetStatus(U8 ucLoopCount)
{
U8 ucTmp;
U8 ucStatus; // tuner status
ucTmp = 0xFF;
devTunerSet_COFDM_I2C_BypassTable(ENABLE);
do // loop to detect
{
// read tuner status
MDrv_IIC_ReadBytes(TN_PROG_I2C_ADDR, 0, (U8*)NULL, 1, &ucStatus);
if( ucStatus == ucTmp )
break;
else
ucTmp = ucStatus;
if (ucLoopCount-- == 0) break;
//Delay1ms(1); // delay 1ms
}while(1);
if( (ucStatus & 0x70) == 0x70 ) ucStatus = TN_READ_VIFL;
else ucStatus = 0;
MDrv_Timer_Delayms(10);
if( (MDrv_IIC_ReadGroupBytes(TN_IF_I2C_ADDR, 0x11, 0x100B))&0x01 )
ucStatus |= TN_READ_AFCWIN;
devTunerSet_COFDM_I2C_BypassTable(DISABLE);
return ucStatus; // return status
}
#define GOOD_AFC 0x80
#define WEAK_AFC 0x250
#define BAD_AFC 0x700// 0x400
BOOLEAN devTunerFineTuneFreq( U16 wOriFreq, U16* pwResultFreq )
{
U8 ucStatus;
U16 u16AFC;
U16 ucMaxLoopCount;//64; // Protection: don't let program die
U8 u8AFC, u8AFCRange;
U8 u8BestAFC;
U16 u16BestFreq;
ucMaxLoopCount = 8;
u8BestAFC = 0xFF;
u16BestFreq = 0;
u8AFCRange=0x00;
*pwResultFreq=0;
PAL_DBG_MSG(printf( "\r\nStart Finetune %f ==> ", (float)wOriFreq/TN_FREQ_SS_INVERSE ));
while( ucMaxLoopCount-- )
{
//*pwResultFreq=wOriFreq;
PAL_DBG_MSG(printf("\r\nfront wOriFreq = %f",(float)wOriFreq/16));
ucStatus = devTunerSetFreq( wOriFreq );
u8AFCRange = devTunerGetIF_AFC();
//printf("jason=========wOriFreq=%d++++++++++ucMaxLoopCount=%d---------------u8AFCRange=%bx\n",wOriFreq,ucMaxLoopCount,u8AFCRange);
u8AFC = (u8AFCRange&0x80)?((~u8AFCRange)+0x01):(u8AFCRange);
PAL_DBG_MSG(printf("\r\ncAfc= 0x%bx",u8AFCRange));
u16AFC = devTunerGetIF_Quality(5);
if(u16AFC > BAD_AFC)
break;//return FALSE;
if( u8AFC >=0x32 )//>500K break
{
break;
}
else if(u8AFC>0x06)
{
if(u8AFCRange&0x80)
wOriFreq += u8AFC/6;
else
wOriFreq -= u8AFC/6;
}
else if( u8AFC <= 0x06 ) //check AFC is under 60k
{
PAL_DBG_MSG(printf("\r\nFinal quality = %x", u16AFC));
if(u8AFCRange&0x80)
{
if(u8AFCRange <= u8BestAFC)
{
u8BestAFC = u8AFCRange;
u16BestFreq = wOriFreq;
}
else
{
break;
}
wOriFreq += 1;
}
else
{
if(u8AFCRange >= u8BestAFC)
{
u8BestAFC =u8AFCRange/* u8AFC*/;
u16BestFreq = wOriFreq;
}
else
{
break;
}
wOriFreq -= 1;
}
}
}
if(u16BestFreq)
{
*pwResultFreq = u16BestFreq;
return TRUE;
}
return FALSE;
}
#elif (FRONTEND_TUNER_TYPE==PHILIPS_FQD1216_TUNER)
code U8 tIFBCETable[TUNER_SOUND_NUMS][3] =
{
// B C E
{ 0x56, 0x70, 0x49 }, // B/G
{ 0x56, 0x70, 0x4A }, // I
{ 0x56, 0x70, 0x4B }, // D/K
{ 0x46, 0x4E, 0x4B }, // L
{ 0xC6, 0x4E, 0x53 }, // L'
};
void devTunerSetIF( EnuTunerSoundSystem ucSoundSystem )
{
U8 i, ucTemp;
ucTemp = (ucSoundSystem==TUNER_SOUND_AUTO)?0:(ucSoundSystem)-1;
PAL_DBG_MSG(printf("=devTunerSetIF=ucTemp=%bx\n",ucTemp));
if( ucSoundSystem >= TUNER_SOUND_NUMS )
ucSoundSystem = 0;
ZL10353_RepeatControl(ENABLE);
MDrv_Timer_Delayms(5);
for( i = 0; i < 3; ++ i )
{
//printf("IF=%bx \r\n",tIFBCETable[ucTemp][i]);
if(MDrv_IIC_WriteByte(TN_IF_I2C_ADDR, i, tIFBCETable[ucTemp][i])==FALSE)
{
PAL_DBG_MSG(printf("TN_IF_I2C_ADDR write Error\n"));
}
}
ZL10353_RepeatControl(DISABLE);
}
void devTunerSetSubSys( EnuTunerSoundSystem ucSoundSystem )
{
devTunerSetIF( ucSoundSystem );
if( TUNER_SOUND_LL == ucSoundSystem )
g_TuneFreqIF = 33.95 * 16;
else
g_TuneFreqIF = 38.9 * 16;
}
U8 devTunerSetFreq( U16 wFreq )
{
g_TunerPara.ProgDivide = wFreq + g_TuneFreqIF;
g_TunerPara.ControlInfo1 = 0x80 | TN_RSA_RSB ;
if( wFreq < (160*16) )
g_TunerPara.ControlInfo2 = TN_LOW_BAND;
else if( wFreq < (442.00 * 16))
g_TunerPara.ControlInfo2 = TN_MID_BAND;
else
g_TunerPara.ControlInfo2 = TN_HIGH_BAND;
g_TunerPara.AuxilliaryByte=0x60;
return devTunerWrite( &g_TunerPara );
}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -