📄 drv0288.c
字号:
/* -------------------------------------------------------------------------
File Name: 288_drv.c
Description: 288 driver LLA
Copyright (C) 2005-2006 STMicroelectronics
author: SD
---------------------------------------------------------------------------- */
/* includes ---------------------------------------------------------------- */
#ifdef ST_OSLINUX
#include "stos.h"
#else
#include "stdlib.h"
#endif
/* common includes */
#include "drv0288.h"
#include "util288.h"
#include "sysdbase.h"
#include "mtuner.h"
#include "tunsdrv.h"
extern TUNSDRV_InstanceData_t *TUNSDRV_GetInstFromHandle(TUNER_Handle_t Handle);
/* Current LLA revision */
static const ST_Revision_t Revision288 = "STX0288-LLA_REL_1.0";
static FE_288_LOOKUP_t FE_288_RF_LookUp = {
22,
{
-101, 127,
-104, 118,
-110, 111,
-130, 100,
-160, 91,
-180, 87,
-200, 84,
-250, 76,
-300, 68,
-350, 63,
-400, 56,
-450, 48,
-500, 40,
-550, 29,
-600, 11,
-650, -22,
-700, -56,
-750, -71,
-800, -82,
-850, -91,
-883, -96,
-888, -128,
}
};
static FE_288_LOOKUP_t FE_288_CN_LookUp = {
30,
{
25, 8680,
30, 8420,
35, 8217,
40, 7897,
50, 7333,
60, 6747,
70, 6162,
80, 5580,
90, 5029,
100,4529,
110,4080,
120,3685,
130,3316,
140,2982,
150,2688,
160,2418,
170,2188,
180,1982,
190,1802,
200,1663,
210,1520,
220,1400,
230,1295,
240,1201,
250,1123,
260,1058,
270,1004,
280,957,
290,920,
300,890
}
};
ST_Revision_t FE_288_GetLLARevision(void)
{
return (Revision288);
}
/*****************************************************
**FUNCTION :: BinaryFloatDiv
**ACTION :: float division (with integer)
**PARAMS IN :: NONE
**PARAMS OUT:: NONE
**RETURN :: Derotator frequency (KHz)
*****************************************************/
long FE_288_BinaryFloatDiv(long n1, long n2, int precision)
{
int i=0;
long result=0;
/* division de N1 par N2 avec N1<N2 */
while(i<=precision) /* n1>0 */
{
if(n1<n2)
{
result<<=1;
n1<<=1;
}
else
{
result=(result<<1)+1;
n1=(n1-n2)<<1;
}
i++;
}
return result;
}
/*****************************************************
**FUNCTION :: FE_288_XtoPowerY
**ACTION :: Compute x^y (where x and y are integers)
**PARAMS IN :: Number -> x
** Power -> y
**PARAMS OUT:: NONE
**RETURN :: 2^n
*****************************************************/
U32 FE_288_XtoPowerY(U32 Number, U32 Power)
{
int i;
long result = 1;
for(i=0;i<Power;i++)
result *= Number;
return (U32)result;
}
/*****************************************************
**FUNCTION :: FE_288_PowOf2
**ACTION :: Compute 2^n (where n is an integer)
**PARAMS IN :: number -> n
**PARAMS OUT:: NONE
**RETURN :: 2^n
*****************************************************/
long FE_288_PowOf2(int number)
{
int i;
long result=1;
for(i=0;i<number;i++)
result*=2;
return result;
}
/*****************************************************
**FUNCTION :: GetPowOf2
**ACTION :: Compute x according to y with y=2^x
**PARAMS IN :: number -> y
**PARAMS OUT:: NONE
**RETURN :: x
*****************************************************/
long FE_288_GetPowOf2(int number)
{
int i=0;
while(FE_288_PowOf2(i)<number) i++;
return i;
}
/*****************************************************
**FUNCTION :: FE_288_GetMclkFreq
**ACTION :: Set the STX0288 master clock frequency
**PARAMS IN :: DeviceMap ==> handle to the chip
** ExtClk ==> External clock frequency (Hz)
**PARAMS OUT:: NONE
**RETURN :: MasterClock frequency (Hz)
*****************************************************/
U32 FE_288_GetMclkFreq(STTUNER_IOREG_DeviceMap_t *DeviceMap, IOARCH_Handle_t IOHandle, U32 ExtClk_Hz)
{
U32 mclk_Hz, /* master clock frequency (Hz) */
pll_divider, /* pll divider */
pll_selratio, /* 4 or 6 ratio */
pll_bypass; /* pll bypass */
pll_divider = STTUNER_IOREG_GetField(DeviceMap, IOHandle, F288_PLL_MDIV)+1;
pll_selratio=(STTUNER_IOREG_GetField(DeviceMap,IOHandle,F288_PLL_SELRATIO)?4:6);
pll_bypass=STTUNER_IOREG_GetField(DeviceMap,IOHandle,F288_BYPASS_PLL);
if(pll_bypass)
mclk_Hz=ExtClk_Hz;
else
mclk_Hz=(ExtClk_Hz*pll_divider)/pll_selratio;
return mclk_Hz;
}
U32 FE_288_SetMclkFreq(STTUNER_IOREG_DeviceMap_t *DeviceMap, IOARCH_Handle_t IOHandle, U32 ExtClk_Hz, U32 MasterClock)
{
U32 /* master clock frequency (Hz) */
pll_divider, /* pll divider */
pll_selratio; /* 4 or 6 ratio */
/* pll bypass */
if(ExtClk_Hz == 4000000)
pll_selratio = 1;
else
pll_selratio = 0;
pll_divider = ((MasterClock/1000000)*(2*(1-pll_selratio) + 4))/(ExtClk_Hz/1000000);
STTUNER_IOREG_SetField(DeviceMap, IOHandle, F288_PLL_MDIV, (pll_divider-1));
STTUNER_IOREG_SetField(DeviceMap, IOHandle, F288_PLL_SELRATIO, pll_selratio);
MasterClock = FE_288_GetMclkFreq(DeviceMap, IOHandle, ExtClk_Hz);
return MasterClock;
}
/*****************************************************
**FUNCTION :: FE_288_AuxClkFreq
**ACTION :: Compute Auxiliary clock frequency
**PARAMS IN :: DigFreq ==> Frequency of the digital synthetizer (Hz)
** Prescaler ==> value of the prescaler
** Divider ==> value of the divider
**PARAMS OUT:: NONE
**RETURN :: Auxiliary Clock frequency
*****************************************************/
U32 FE_288_AuxClkFreq(U32 DigFreq,U32 Prescaler,U32 Divider)
{
U32 aclk,
factor;
switch(Prescaler)
{
case 0:
aclk = 0;
break;
case 1:
if(Divider)
aclk = DigFreq/2/Divider;
else
aclk = DigFreq/2;
break;
default:
factor = (U32)(2048L*FE_288_PowOf2(Prescaler-2));
if(factor)
aclk = DigFreq/factor/(32+Divider);
else
aclk = 0;
break;
}
return aclk;
}
/*****************************************************
**FUNCTION :: FE_288_F22Freq
**ACTION :: Compute F22 frequency
**PARAMS IN :: DigFreq ==> Frequency of the digital synthetizer (Hz)
** F22 ==> Content of the F22 register
**PARAMS OUT:: NONE
**RETURN :: F22 frequency
*****************************************************/
U32 FE_288_F22Freq(U32 DigFreq,U32 F22)
{
return (F22!=0) ? (DigFreq/(32*F22)) : 0;
}
/*****************************************************
**FUNCTION :: FE_288_GetErrorCount
**ACTION :: return the number of error
**PARAMS IN :: Params => Pointer to STTUNER_IOREG_DeviceMap_t
** Counter => Counter to use
**PARAMS OUT:: NONE
**RETURN :: number of errors
*****************************************************/
U32 FE_288_GetErrorCount(STTUNER_IOREG_DeviceMap_t *DeviceMap, IOARCH_Handle_t IOHandle, FE_288_ERRORCOUNTER_t Counter)
{
U32 lsb,msb;
/*Do not modified the read order (lsb first)*/
if(Counter == COUNTER1_288)
{
lsb = STTUNER_IOREG_GetField(DeviceMap, IOHandle,F288_ERROR_COUNT_LSB);
msb = STTUNER_IOREG_GetField(DeviceMap, IOHandle,F288_ERROR_COUNT_MSB);
}
else
{
lsb = STTUNER_IOREG_GetField(DeviceMap, IOHandle,F288_ERROR_COUNT2_LSB);
msb = STTUNER_IOREG_GetField(DeviceMap, IOHandle,F288_ERROR_COUNT2_MSB);
}
return (MAKEWORD_288(msb,lsb));
}
/****************************************************
--FUNCTION :: FE_288_GetPacketErrors
--ACTION :: Set error counter in packet error mode and check for packet errors
--PARAMS IN :: NONE
--PARAMS OUT:: NONE
--RETURN :: Content of error count
--**************************************************/
U32 FE_288_GetDirectErrors(STTUNER_IOREG_DeviceMap_t *DeviceMap, IOARCH_Handle_t IOHandle,FE_288_ERRORCOUNTER_t Counter)
{
U32 BitErrors;
unsigned char CounterMode, i;
switch(Counter)
{
case COUNTER1_288:
CounterMode = STTUNER_IOREG_GetRegister(DeviceMap,IOHandle,R288_ERRCTRL); /* Save error counter mode */
STTUNER_IOREG_SetRegister(DeviceMap,IOHandle,R288_ERRCTRL,0x80); /* Packet Errors --Error counter in Rate mode, packet error, count period 2^12 */
/* Do not remove the for loop : bug work around */
for(i=0;i<2;i++)
BitErrors = FE_288_GetErrorCount(DeviceMap,IOHandle,COUNTER1_288); /* Error counter must be read twice before returning valid value */
STTUNER_IOREG_SetRegister(DeviceMap,IOHandle,R288_ERRCTRL,CounterMode); /* restore error counter mode */
break;
case COUNTER2_288:
CounterMode = STTUNER_IOREG_GetRegister(DeviceMap,IOHandle,R288_ERRCTRL2); /* Save error counter mode */
STTUNER_IOREG_SetRegister(DeviceMap,IOHandle,R288_ERRCTRL2,0xa0); /* Error counter in Rate mode, packet error, count period 2^12 */
for(i=0;i<2;i++)
BitErrors = FE_288_GetErrorCount(DeviceMap,IOHandle,COUNTER2_288); /* Error counter must be read twice before returning valid value */
STTUNER_IOREG_SetRegister(DeviceMap,IOHandle,R288_ERRCTRL2,CounterMode); /* restore error counter mode */
break;
}
return BitErrors;
}
/*****************************************************
--FUNCTION :: FE_288_TimingTimeConstant
--ACTION :: Compute the amount of time needed by the timing loop to lock
--PARAMS IN :: SymbolRate -> symbol rate value
--PARAMS OUT:: NONE
--RETURN :: Timing loop time constant (ms)
--***************************************************/
long FE_288_TimingTimeConstant(long SymbolRate)
{
if(SymbolRate > 0)
return (100000/(SymbolRate/1000));
else
return 0;
}
/*****************************************************
--FUNCTION :: FE_288_DerotTimeConstant
--ACTION :: Compute the amount of time needed by the Derotator to lock
--PARAMS IN :: SymbolRate -> symbol rate value
--PARAMS OUT:: NONE
--RETURN :: Derotator time constant (ms)
--***************************************************/
long FE_288_DerotTimeConstant(long SymbolRate)
{
if(SymbolRate > 0)
return (10000/(SymbolRate/1000));
else
return 0;
}
/*****************************************************
--FUNCTION :: FE_288_DataTimeConstant
--ACTION :: Compute the amount of time needed to capture data
--PARAMS IN :: Er -> Viterbi rror rate
-- Sn -> viterbi averaging period
-- To -> viterbi time out
-- Hy -> viterbi hysteresis
-- SymbolRate -> symbol rate value
--PARAMS OUT:: NONE
--RETURN :: Data time constant
--***************************************************/
long FE_288_DataTimeConstant(STTUNER_IOREG_DeviceMap_t *DeviceMap, IOARCH_Handle_t IOHandle,long SymbolRate)
{
U32 Tviterbi = 0,
TimeOut = 0,
THysteresis = 0,
Tdata = 0,
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -