phantom_drv.c
来自「QPSK Tuner details, for conexant chipset」· C语言 代码 · 共 1,432 行 · 第 1/3 页
C
1,432 行
} /* PHANTOM_BCD_out() */
/*******************************************************************************************************
* BCD_move_bcd()
* function to move PHANTOM_BCDNO source to PHANTOM_BCDNO dest
*******************************************************************************************************/
static void
BCD_move_bcd(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
PHANTOM_BCDNO *p_bcdsource) /* pointer to bcd struct */
{
int idx;
p_bcd->sign[0] = p_bcdsource->sign[0];
for (idx = 0 ; idx < PHANTOM_MAX_BCDNO ; idx++)
{
p_bcd->digits[idx] = p_bcdsource->digits[idx];
}
return;
} /* BCD_move_bcd() */
/*******************************************************************************************************
* BCD_zero()
* function to set a PHANTOM_BCDNO struct to zero
*******************************************************************************************************/
static BOOL
BCD_zero(PHANTOM_BCDNO *p_bcd) /* pointer to bcd struct */
{
int idx;
/* test bcd for zero */
for (idx = PHANTOM_MAX_BCDNO-1 ; idx > 0 ; idx--) if (p_bcd->digits[idx] != 0)
{
return(False);
}
/* bcd is equal to zero */
return(True);
} /* BCD_zero() */
/*******************************************************************************************************
* BCD_compare()
* function to compare two bcd numbers. returns 0 if equal
*******************************************************************************************************/
static int
BCD_compare(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
PHANTOM_BCDNO *p_bcd2) /* pointer to bcd struct */
{
int idx;
/* test sign for quick result bcd sig == +, return 1 else -1 */
if (BCD_SIGN(p_bcd) != BCD_SIGN(p_bcd2))
{
return(BCD_SIGN(p_bcd));
}
/* compare two bcd numbers, returns positive no., if bcd is higher-than p_bcd2 */
for (idx = 0 ; idx < PHANTOM_MAX_BCDNO ; idx++)
{
if (p_bcd->digits[idx] != p_bcd2->digits[idx] != 0)
{
return((int)(p_bcd->digits[idx]-p_bcd2->digits[idx]));
}
}
/* bcd is equal to p_bcd2 */
return(0);
} /* BCD_compare() */
/*******************************************************************************************************
* BCD_div_ten()
* function to perfrom a bcd div by ten (kill lowest digit)
*******************************************************************************************************/
static void
BCD_div_ten(PHANTOM_BCDNO *p_bcd) /* pointer to bcd struct */
{
int idx;
/* shift bcd rt by one BCD place */
for (idx = PHANTOM_MAX_BCDNO-1 ; idx > 1 ; idx--)
{
p_bcd->digits[idx] = p_bcd->digits[idx-1];
}
p_bcd->digits[0] = 0;
return;
} /* BCD_div_ten() */
/*******************************************************************************************************
* BCD_abs()
* function to perform abs() functionality on a PHANTOM_BCDNO number
*******************************************************************************************************/
static PHANTOM_BCDNO*
BCD_abs(PHANTOM_BCDNO *p_bcd) /* pointer to bcd struct */
{
static PHANTOM_BCDNO bcd_abs;
BCD_move_bcd(&bcd_abs,p_bcd);
BCD_SETSIGN((&bcd_abs),1);
return(&bcd_abs);
} /* BCD_abs() */
/*******************************************************************************************************
* BCD_mult_ten()
* function to multiply a PHANTOM_BCDNO by ten (performs a bcd <<1 op.)
*******************************************************************************************************/
static void
BCD_mult_ten(PHANTOM_BCDNO *p_bcd) /* pointer to bcd struct */
{
int idx;
/* shift bcd lt by one BCD place */
for (idx = 0 ; idx < PHANTOM_MAX_BCDNO-1 ; idx++)
{
p_bcd->digits[idx] = p_bcd->digits[idx+1];
}
p_bcd->digits[PHANTOM_MAX_BCDNO-1] = 0;
return;
} /* BCD_mult_ten() */
////////////////////////////////////////////////////////////////////////////////////////////////////////
/*******************************************************************************************************
* PHANTOM_DRIVER_ValidateNim()
* function to test nim for 0 and inclusion in PHANTOM_NIM_LIST
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_ValidateNim(PHANTOM_NIM *p_nim) /* pointer to nim */
{
/* test for no nim */
if (p_nim == 0)
{
/* invalid nim or already allocated */
PHANTOM_DBG_SET_ERROR(PHANTOM_NIM_NULL);
}
else
{
/* nim was not 0, so test other validity properties */
return(PHANTOM_DRIVER_ValidNim(p_nim));
}
return(False);
} /* PHANTOM_DRIVER_ValidateNim() */
/*******************************************************************************************************
* PHANTOM_DRIVER_ValidNim()
* function to validate a nim pointer
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_ValidNim(PHANTOM_NIM *p_nim) /* pointer to nim */
{
int i;
/* test nims saved via init env for validity */
for (i = 0 ; i < PHANTOM_MAX_NIMS ; i++)
{
if (phantom_nim_list.nim[i] == p_nim)
{
return(True);
}
}
return(False);
} /* PHANTOM_DRIVER_ValidNim() */
/*******************************************************************************************************
* PHANTOM_DRIVER_ResetMicro()
* function to reset the microcontroller module.
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_ResetMicro(PHANTOM_NIM* p_nim)
{
unsigned long status;
/* Test PHANTOM_NIM for validity */
PHANTOM_DBG_VALIDATE_NIM(p_nim);
/* reset Phantom. */
(*p_nim->SBWrite)(p_nim->demod_handle,
PHANTOM_SC_RESET_CNTL,
PHANTOM_UC8051_RESET_HIGH,
&status);
if (status)
{
return(False);
}
/* Release reset. */
(*p_nim->SBWrite)(p_nim->demod_handle,
PHANTOM_SC_RESET_CNTL,
PHANTOM_UC8051_RESET_LOW,
&status);
if (status)
{
return(False);
}
return(True);
}
/*******************************************************************************************************
* PHANTOM_DRIVER_InitTuner()
* function to init the tuner associated with this demod
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_InitTuner(PHANTOM_NIM* p_nim, PHANTOM_TUNER_REF_CLOCKOUT_DIV tuner_ref_clkout_div)
{
unsigned char tuner_select;
unsigned long reg_value = 0;
p_nim->tuner_ref_clkout_div = tuner_ref_clkout_div; /* tuner's ref clk out divider */
tuner_select = (unsigned char)(PHANTOM_GET_TUNER_HANDLE_UNIT(p_nim->demod_handle));
if (PHANTOM_LLF_TunerInit(p_nim, tuner_select, (unsigned char)(p_nim->tuner_ref_clkout_div)) == False)
{
return (False);
}
/* check for error code */
if (PHANTOM_RegisterRead(p_nim, PHANTOM_P0_D0_TUNER_ERR_CODE, ®_value, PHANTOM_USE_DEMOD_HANDLE) == False)
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_READ_ERR);
return (False);
}
switch (reg_value)
{
case 1UL:
PHANTOM_DBG_SET_ERROR(PHANTOM_TUNER_INVALID_I2C_ADDRESS);
return (False);
case 2UL:
PHANTOM_DBG_SET_ERROR(PHANTOM_INVALID_TUNER_SELECTION); /* Single tuner with tunerB selection */
return (False);
default:
break;
}
return (True);
}
/*******************************************************************************************************
* PHANTOM_DRIVER_HWInit()
* function to initialize the Phantom HW.
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_HWInit(PHANTOM_NIM* p_nim)
{
/* Test PHANTOM_NIM for validity */
PHANTOM_DBG_VALIDATE_NIM(p_nim);
/* PLL SPMP */
if (PHANTOM_RegisterWrite (p_nim, PHANTOM_SC_F1_PLL_SPMP, PHANTOM_PLL_SPMP_VALUE, PHANTOM_USE_DEMOD_HANDLE) == False)
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_WRITE_ERR);
return (False);
}
/* PLL SDIV */
if (PHANTOM_RegisterWrite (p_nim, PHANTOM_SC_F2_PLL_SDIV, p_nim->pll_sdiv, PHANTOM_USE_DEMOD_HANDLE) == False)
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_WRITE_ERR);
return (False);
}
/* PLL smooth clock divider */
if (PHANTOM_RegisterWrite (p_nim, PHANTOM_SC_F3_PLL_SMOOTH_CLK_DIV, PHANTOM_PLL_CLOCK_SMOOTH_DIVIDER, PHANTOM_USE_DEMOD_HANDLE) == False)
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_WRITE_ERR);
return (False);
}
/* PLL Main clock divider */
if (PHANTOM_RegisterWrite (p_nim, PHANTOM_SC_F3_PLL_MAIN_CLK_DIV, PHANTOM_PLL_MAIN_CLOCK_DIV6, PHANTOM_USE_DEMOD_HANDLE) == False)
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_WRITE_ERR);
return (False);
}
if (PHANTOM_RegisterWrite (p_nim, PHANTOM_SC_F9_ADC_MODE_SEL, PHANTOM_ADC_MOD_SEL_DIV6, PHANTOM_USE_DEMOD_HANDLE) == False) // /6 clock
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_WRITE_ERR);
return (False);
}
return (True);
}
/*******************************************************************************************************
* PHANTOM_DRIVER_ResetMicro()
* function to reset the microcontroller module.
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_Download(PHANTOM_NIM* p_nim, unsigned long microcode_length, unsigned char *p_microcode)
{
unsigned long length = 0;
unsigned long status;
/* set starting addresses, low 8-bit. */
(*p_nim->SBWrite)(p_nim->demod_handle,
PHANTOM_SC_ADDRESS_LOW,
PHANTOM_DOWNLOAD_DATA_ADDRESS_LOW,
&status);
if (status)
{
return(False);
}
/* set starting addresses, high 8-bit. */
(*p_nim->SBWrite)(p_nim->demod_handle,
PHANTOM_SC_ADDRESS_HIGH,
PHANTOM_DOWNLOAD_DATA_ADDRESS_HIGH,
&status);
if (status)
{
return(False);
}
/* download data. */
if (!(p_nim->SBMultiWrite))
{
length = 0;
while(length < microcode_length) /* The last byte is CRC. */
{
(*p_nim->SBWrite)(p_nim->demod_handle,
PHANTOM_SC_DATA,
p_microcode[length],
&status);
if (status)
{
return(False);
}
length++;
}
}
else
{
(*p_nim->SBMultiWrite)(p_nim->demod_handle,
microcode_length,
PHANTOM_SC_DATA,
p_microcode,
&status);
if (status)
{
return(False);
}
}
/* Return to auto-increment mode and protect the program memory */
(*p_nim->SBWrite)(p_nim->demod_handle,
PHANTOM_SC_DOWNLOAD_CONTROL,
PHANTOM_UC8051_CODE_LOAD_DISABLE,
&status);
if (status)
{
return(False);
}
return (True);
}
/*******************************************************************************************************
* PHANTOM_DRIVER_ResetTunerHandshake()
* function to reset the tuner handshake bit..
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_ResetTunerHandshake(PHANTOM_NIM* p_nim)
{
/* Test NIM for validity */
PHANTOM_DBG_VALIDATE_NIM(p_nim);
if (PHANTOM_RegisterWrite (p_nim, PHANTOM_P0_9D_TUNER_HANDSHAKE, 0x00UL, PHANTOM_USE_DEMOD_HANDLE) == False)
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_WRITE_ERR);
return (False);
}
return (True);
}
/*******************************************************************************************************
* PHANTOM_DRIVER_IsTunerI2CDone()
* function to check if the tuner is no longer accessing I2C
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_IsTunerI2CDone(PHANTOM_NIM* p_nim)
{
unsigned long counter = 0;
unsigned long reg_value;
/* Test NIM for validity */
PHANTOM_DBG_VALIDATE_NIM(p_nim);
do {
if (PHANTOM_RegisterRead (p_nim, PHANTOM_P0_9D_TUNER_HANDSHAKE, ®_value, PHANTOM_USE_DEMOD_HANDLE) == False)
{
PHANTOM_DBG_SET_ERROR(PHANTOM_REG_WRITE_ERR);
return (False);
}
if (reg_value != 0x00UL)
{
return (True);
}
counter++;
} while(counter <= PHANTOM_MAX_TUNER_HANDSHAKE_POLL);
return (False);
}
/*******************************************************************************************************
* PHANTOM_DRIVER_SetInverseVCOFrequency()
* function to program the inverse VCO frequency.
*******************************************************************************************************/
BOOL
PHANTOM_DRIVER_SetVCOFrequency(PHANTOM_NIM* p_nim)
{
unsigned short inverse_vco_frequency;
unsigned long vco_frequency;
PHANTOM_BCDNO bcd1, bcd2;
unsigned long result;
/* Test PHANTOM_NIM for validity */
PHANTOM_DBG_VALIDATE_NIM(p_nim);
/* Get the VCO_frequency_in_kHz = crystal_freq_kHz. x PLL_Multiplier */
p_nim->vco_freq = p_nim->pll_sdiv * p_nim->demod_ref_clock;
vco_frequency = (p_nim->vco_freq/(unsigned long)PHANTOM_ONETHOUSAND);
/* Inverse VCO frequency = 2^34 / (vco_frequency_in_kHz) */
PHANTOM_BCD_set (&bcd1, TWO_POWER_34_OVER_TWO_POWER_3);
PHANTOM_BCD_mult(&bcd1, TWO_POWER_3);
PHANTOM_BCD_div (&bcd1, vco_frequency);
inverse_vco_frequency = (unsigned short)PHANTOM_BCD_out(&bcd1);
/* Improve precision */
// result = 2^34 - (inverse_vco_frequency * vco_frequency)
PHANTOM_BCD_set (&bcd1, TWO_POWER_34_OVER_TWO_POWER_3);
PHANTOM_BCD_mult(&bcd1, TWO_POWER_3);
PHANTOM_BCD_set (&bcd2, inverse_vco_frequency);
PHANTOM_BCD_mult(&bcd2, vco_frequency);
BCD_subt_bcd(&bcd1, &bcd2);
result = PHANTOM_BCD_out(&bcd1);
if (result > (vco_frequency / 2))
{
inverse_vco_frequency++;
}
if (PHANTOM_LLF_SetVCOFrequency(p_nim, vco_frequency, inverse_vco_frequency, (unsigned short)(p_nim->crystal_freq/1000UL)) == False)
{
return (False);
}
return (True);
}
/*******************************************************************************************************
* PHANTOM_DRIVER_ConvertToTwos()
* function to convert to twos-comp number.
*******************************************************************************************************/
long
PHANTOM_DRIVER_ConvertToTwos(unsigned long numeric, /* raw number read from demod */
unsigned long bitslen) /* count of lsb's to perform conversion on */
{
long temp;
if (numeric < (unsigned long)(0x01L<<(bitslen-1))) /* positive */
{
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?