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, &reg_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, &reg_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 + -
显示快捷键?