📄 tlg1100api.c
字号:
/*****************************************************************************
* FILENAME
* tlg1100Api.c
*
*
* ABSTRACT
* This file contains the code for the TLG1100 Ultra Low Power NTSC/PAL
* Tuner/Decoder Front End Application Programmer's Interface library.
*
* $Revision: 1.38 $
*
* (c) 2007 Telegent Systems
*****************************************************************************/
/* INCLUDE SECTION ************************************************************
*******************************************************************************
*******************************************************************************
******************************************************************************/
#include "Tv_Include.h"
#if TLG_CHIP_TYPE == TLG_CHIP_TYPE_TLG1100_1
/* DECLARE SECTION ************************************************************
*******************************************************************************
*******************************************************************************
******************************************************************************/
int TLG_ReadAudioNotchPwr(uint32 base_addr, int read_num);
TLGDLL_API uint32 tlg_cur_fm_ssi = 0;
tlg_avg_filter_t tlg_agc1_filt, tlg_agc2_filt, tlg_lock_filt;
/* FUNCTION SECTION ***********************************************************
*******************************************************************************
*******************************************************************************
******************************************************************************/
/*****************************************************************************
* ceil_log2
*
*
*
*
*****************************************************************************/
/*
* return the integer log2 of the given number.
* ceil==FALSE, truncated value (e.g ceil_log2(3, FALSE) = 1)
* ceil==TRUE, ceiling value (e.g. ceil_log2(3, TRUE) = 2
*/
uint32 ceil_log2(uint32 a, bool ceil) {
uint32 pwr = ((uint32)1)<<31;
int l2 = 31;
if (a == 0) return 0;
/* find the highest power in a, that's its log2() */
while ((a & pwr) == 0)
{
l2--;
pwr >>= 1;
}
/* see if there is a remainder, if so add 1 for ceil() */
if (ceil)
if (a & ~pwr) /* any other bits besides first one? */
l2++;
return(l2);
}
/*****************************************************************************
* TLG_AvgFiltInit
*
*
*
*
*****************************************************************************/
static int TLG_AvgFiltInit(p_tlg_avg_filter_t filter) {
int i;
TLG_NULLPTR_CHECK(filter);
for (i = 0; i < TLG_AVG_FILTER_DEPTH; i++)
filter->taps[i] = 0;
filter->num_sample = 0;
filter->cur_tap = 0;
return TLG_ERR_SUCCESS;
}
/*****************************************************************************
* TLG_AvgFiltGetNext
*
* This procedure keeps a running average of the last TLG_AVG_FILTER_DEPTH
* values supplied to it. It operates in two modes: startup mode and steady
* state mode. Startup mode is when there have been less than the required
* samples entered. When in this mode, totals are kept and averages are
* calculated on the closest power of 2 divisor. Here is an example of the
* tap fill pattern for TLG_AVG_FILTER_DEPTH == 16 (the x's indicate which
* samples are summed in the given tap).
* num_sample
* 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16
* 0 x
* 1 x x
* 2 x x
* 3 x x x x
* 4 x x x x
* 5 x x x x
*t 6 x x x x
*a 7 x x x x x x x x
*p 8 x x x x x x x x
*s 9 x x x x x x x x
* 10 x x x x x x x x
* 11 x x x x x x x x
* 12 x x x x x x x x
* 13 x x x x x x x x
* 14 x x x x x x x x
* 15 x x x x x x x x x x x x x x x x
*
* The procedure returns the sum and the divisor (power of 2) rather than
* performing the averaging directly so additional calculations may be
* combined prior to applying the divide to maximize the precision of
* integer math calculations.
*
*****************************************************************************/
static uint32 TLG_AvgFiltGetNext(p_tlg_avg_filter_t filter, uint32 *val,
uint32 *divisor) {
int bucket_start, bucket_end;
int i;
TLG_NULLPTR_CHECK(filter);
TLG_NULLPTR_CHECK(divisor);
TLG_NULLPTR_CHECK(val);
*divisor = 1; /* 2^0 */
if (filter->num_sample == TLG_AVG_FILTER_DEPTH)
{
/* tap steady state. Keep sum of last TLG_AVG_FILTER_DEPTH values. */
for (i = 0; i < TLG_AVG_FILTER_DEPTH; i++)
{
filter->taps[i] += *val;
}
*divisor = TLG_AVG_FILTER_DEPTH;
} else {
/* tap startup. Fill taps by creating buckets on 2^n boundaries */
filter->num_sample++;
bucket_start = 1; /* 2^0 */
bucket_end = 2; /* 2^1 */
while (bucket_start < TLG_AVG_FILTER_DEPTH*2)
{
if (filter->num_sample < bucket_start)
for (i = bucket_start; i < bucket_start + filter->num_sample; i++)
{
filter->taps[TLG_AVG_FILTER_IDX(i-1)] += *val;
}
else if ((filter->num_sample >= bucket_start) && (filter->num_sample < bucket_end))
{
/*
* found bucket sample is in. Use this as divisor and fill
* taps (including those for next set of tap values)
*/
*divisor = bucket_start;
for (i = filter->num_sample; i < bucket_end; i++)
{
filter->taps[TLG_AVG_FILTER_IDX(i-1)] += *val;
}
}
bucket_start = bucket_end;
bucket_end *= 2;
}
}
/** get current sum, and reset tap */
*val = filter->taps[filter->cur_tap];
filter->taps[filter->cur_tap] = 0;
filter->cur_tap = TLG_AVG_FILTER_IDX(filter->cur_tap + 1);
return TLG_ERR_SUCCESS;
}
#ifdef TLG_USE_SHADOW_REGISTERS
uint16 _TLG_shadow_reg[TLG_MAX_REG_ADDR+1];
uint8 _TLG_shadow_reg_use[TLG_MAX_REG_ADDR+1]={
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0};
#endif /* TLG_SHADOW_REGISTER_SIZE */
#ifdef TLG_SUPPORT_RUNTIME_CHECK
int g_tlg_chip_ver = TLG_NO_VERS;
#endif /* TLG_SUPPORT_RUNTIME_CHECK */
/*****************************************************************************
* TLG_GetVersion
*
*
*
*
*****************************************************************************/
TLGDLL_API int TLG_GetVersion(uint32 base_addr, uint16 *major, uint16 *minor, uint16 *patch) {
TLG_NULLPTR_CHECK(major);
TLG_NULLPTR_CHECK(minor);
TLG_NULLPTR_CHECK(patch);
*major = TLG_VERSION_MAJOR;
*minor = TLG_VERSION_MINOR;
*patch = TLG_VERSION_PATCH;
return(TLG_ERR_SUCCESS);
}
/*****************************************************************************
* TLG_GetChipVersion
*
* 0xffff 1.1
* 0xrfff 1.2 rev r
* 0xr3ff 1.3 rev r
*
*****************************************************************************/
TLGDLL_API int TLG_GetChipVersion(uint32 base_addr, uint32 *chip_vers) {
uint16 reg, rev, ver;
TLG_NULLPTR_CHECK(chip_vers);
#ifdef TLG_SUPPORT_RUNTIME_CHECK
if (g_tlg_chip_ver == TLG_NO_VERS) {
#endif /* TLG_SUPPORT_RUNTIME_CHECK */
TLG_WriteReg(base_addr, REG_018E, 0xffff);
TLG_ReadRegNS(base_addr, REG_018E, ®);
TLGHAL_GET(rev, reg, REG_018E_BIT15_12_SHIFT,
REG_018E_BIT15_12_MASK);
TLGHAL_GET(ver, reg, REG_018E_BIT11_8_SHIFT,
REG_018E_BIT11_8_MASK);
if (rev == REG_018E_NOREV)
*chip_vers = TLG1100_VERS_1_1;
else if (ver == REG_018E_NOREV)
if (base_addr >= 60 && (rev == 0))
*chip_vers = TLG1150_VERS_1_1;
else
*chip_vers = TLG1100_VERS_1_2 | rev;
else
*chip_vers = TLG1100_VERS_1_3 | rev;
#ifdef TLG_SUPPORT_RUNTIME_CHECK
g_tlg_chip_ver = *chip_vers;
TLG_REG_LOG((b,"chip version = 0x%x, rev=%x\n", g_tlg_chip_ver, rev));
} else
*chip_vers = g_tlg_chip_ver;
#endif /* TLG_SUPPORT_RUNTIME_CHECK */
return TLG_ERR_SUCCESS;
}
/*****************************************************************************
* TLG_SoftReset
*
*
*
*
*****************************************************************************/
TLGDLL_API int TLG_SoftReset(uint32 base_addr) {
tlg_statep state;
int ms = 0;
#ifndef TLG_EMBEDDED_TIMERS
return(TLG_ERR_NOT_SUPPORTED);
#else
state[0] = TLG_STATE0;
do {
TLG_SoftResetASYNC(base_addr, state, &ms);
if (ms)
TLG_Delay((uint16)ms);
} while (state[0] != TLG_STATE_FINAL);
return(TLG_ERR_SUCCESS);
#endif /* TLG_EMBEDDED_TIMERS */
}
/*****************************************************************************
* TLG_SoftResetASYNC
*
*
*
*
*****************************************************************************/
TLGDLL_API int TLG_SoftResetASYNC(uint32 base_addr, tlg_statep state, int *ms) {
#if 1
TLG_CHIP_VERS_1_3_BEGIN
#ifdef TLG_CMP_CHIP_1_3
TLG_WriteReg(base_addr, 0x0001,0x0001);
TLG_WriteReg(base_addr, 0x0001,0x0000);
state[0] = TLG_STATE_FINAL;
*ms = 0;
#endif /* TLG_CMP_CHIP_1_3 */
TLG_CHIP_VERS_1_2_ELSE
#else
TLG_CHIP_VERS_1_2_BEGIN
#endif
#ifdef TLG_CMP_CHIP_1_2
uint16 filt_cal_override;
uint16 old_search_limit;
uint16 filt_r_val;
uint16 trkfilt_cal_code;
uint16 *adc_val = &state[1];
uint16 reg;
uint16 force_coef_load;
int i;
switch (state[0]) {
case TLG_STATE0:
/* state[0] - state variable for this function
* state[1..12] - adc_val[]
* state[13] - old_search_limit
*/
TLG_ReadReg(base_addr, REG_0022, ®);
TLGHAL_GET(filt_cal_override, reg, REG_0022_BIT12_SHIFT,
REG_0022_BIT12_MASK);
if (filt_cal_override == 0) {
TLG_ReadReg(base_addr, REG_0111, ®);
TLGHAL_GET(filt_r_val, reg,
REG_0111_BIT7_3_SHIFT,
REG_0111_BIT7_3_MASK);
} else {
TLG_ReadReg(base_addr, REG_0021,®);
TLGHAL_GET(filt_r_val, reg,
REG_0021_BIT14_10_SHIFT,
REG_0021_BIT14_10_MASK);
}
TLG_ReadReg(base_addr, REG_0039, &old_search_limit);
state[13] = old_search_limit;
TLG_ReadRegNS(base_addr, REG_011C,
&trkfilt_cal_code);
TLG_ReadReg(base_addr, REG_000F, &adc_val[11]);
TLGHAL_GET(force_coef_load, adc_val[11],
REG_000F_BIT12_SHIFT,
REG_000F_BIT12_MASK);
if (force_coef_load) {
for(i = 0; i < 11; i++)
TLG_ReadReg(base_addr, REG_0004 + i, &adc_val[i]);
} else {
for(i = 0; i < 10; i++)
TLG_ReadRegNS(base_addr, REG_0100 + i,
&adc_val[i]);
TLGHAL_CLEAR(adc_val[0], REG_0100_BIT11_0_MASK);
TLG_ReadRegNS(base_addr, REG_010B,&adc_val[10]);
}
TLG_WriteReg(base_addr, 0x0001,1);
/** re-calibrate */
TLG_ReadReg(base_addr, REG_0021, ®);
TLGHAL_SET(reg, filt_r_val, REG_0021_BIT14_10_SHIFT,
REG_0021_BIT14_10_MASK);
TLG_WriteReg(base_addr, REG_0021, reg);
TLG_ReadReg(base_addr, REG_0022, ®);
TLGHAL_SET(reg, TLG_ON, REG_0022_BIT12_SHIFT,
REG_0022_BIT12_MASK);
TLG_WriteReg(base_addr, REG_0022, reg);
TLG_WriteReg(base_addr, REG_0039, 0x0000);
TLG_WriteReg(base_addr, REG_0038, trkfilt_cal_code);
*ms = 5;
state[0] = TLG_STATE1;
break;
case TLG_STATE1:
/* state[0] - state variable for this function
* state[1..12] - adc_val[]
* state[13] - old_search_limit
*/
old_search_limit = state[13];
TLG_WriteReg(base_addr, REG_0039, old_search_limit);
for( i= 0; i <11; i++)
TLG_WriteReg(base_addr, REG_0004 + i, adc_val[i]);
TLG_WriteReg(base_addr, REG_000F,
REG_000F_BIT12_MASK);
state[0] = TLG_STATE_FINAL;
*ms = 0;
break;
default:
break;
}
#endif /* TLG_CMP_CHIP_1_2 */
TLG_CHIP_VERS_1_1_ELSE
#ifdef TLG_CMP_CHIP_1_1
TLG_WriteReg(base_addr, 0x0001,0x0001);
state[0] = TLG_STATE_FINAL;
*ms = 0;
#endif /* TLG_CMP_CHIP_1_1 */
TLG_CHIP_VERS_END
return TLG_ERR_SUCCESS;
}
/*****************************************************************************
* TLG_Init
*
*
*
*
*****************************************************************************/
TLGDLL_API int TLG_Init(uint32 base_addr) {
tlg_statep state;
int ms = 0;
#ifndef TLG_EMBEDDED_TIMERS
return(TLG_ERR_NOT_SUPPORTED);
#else
state[0] = TLG_STATE0;
do {
TLG_InitASYNC(base_addr, state, &ms);
if (ms)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -