phantom_drv.c
来自「QPSK Tuner details, for conexant chipset」· C语言 代码 · 共 1,432 行 · 第 1/3 页
C
1,432 行
/* phantom_drv.c */
/*+++ *******************************************************************\
*
* Abstract:
*
* Contains internal Phantom Driver functions called by the API and
* other software layers.
*
* Created: 3/30/2004
*
* Author: Amarnath Puttur
*
* Copyright and Disclaimer:
*
* ---------------------------------------------------------------
* This software is provided "AS IS" without warranty of any kind,
* either expressed or implied, including but not limited to the
* implied warranties of noninfringement, merchantability and/or
* fitness for a particular purpose.
* ---------------------------------------------------------------
*
* Copyright (c) 2004 Conexant Systems, Inc.
* All rights reserved.
*
\******************************************************************* ---*/
//#include "CS_assert.h"
#include <string.h> /* ANSI Standard */
#include <stdlib.h> /* ANSI Standard (used for labs() )*/
#define PHANTOM_EXTERN /* forces globals to be static to this function */
#include "phantom.h" /* phantom include files, ordered */
#include "phantom_cmd.h" /* phantom Internal */
/*******************************************************************************************************/
/* BCD Macros */
/*******************************************************************************************************/
#define BCD_ADJUST(b) (BCD_adjust_improved((b),(0)))
#define BCD_CLEAR(a) (PHANTOM_BCD_set((a),0L))
#define BCD_SIGN(a) (BCD_GETSIGN(a))
#define BCD_GETSIGN(a) ((signed int)((a)->sign[0] == '-' ? -1 : 1))
#define BCD_SETSIGN(a,b) ((a)->sign[0] = (signed char)((b) < 0 ? '-' : '+'))
#define BCD_LSD(a) ((a)->digits[PHANTOM_MAX_BCDNO-1]) /* least-significant-digit */
#define BCD_INCR(a) ((BCD_LSD(a) = (signed char)(BCD_LSD(a)+BCD_SIGN(a))),(BCD_ADJUST(a)))
/*******************************************************************************************************
* BCD Functions ***************************************************************************************
*******************************************************************************************************/
static void BCD_mult_bcd(PHANTOM_BCDNO *bcd, PHANTOM_BCDNO *bcdmultby);
static BOOL BCD_zero(PHANTOM_BCDNO *bcd);
static void BCD_adjust_improved(PHANTOM_BCDNO *bcd,int ledge);
static void BCD_move_bcd(PHANTOM_BCDNO *bcd, PHANTOM_BCDNO *bcdsource);
static void BCD_div_ten(PHANTOM_BCDNO *bcd);
static void BCD_mult_ten(PHANTOM_BCDNO *bcd);
static int BCD_compare(PHANTOM_BCDNO *bcd, PHANTOM_BCDNO *bcd2);
static void BCD_subt_bcd(PHANTOM_BCDNO *bcd, PHANTOM_BCDNO *subt);
static PHANTOM_BCDNO* BCD_abs(PHANTOM_BCDNO *p_bcd);
/*******************************************************************************************************
* BCD_add_bcd()
* bcd math function used when LONG might be saturated
*******************************************************************************************************/
static void
BCD_add_bcd(PHANTOM_BCDNO *p_bcd, /* bcd struct */
PHANTOM_BCDNO *p_bcdtoadd) /* bcd struct to be used to add to bcd */
{
int idx;
int result;
/* add two bcd numbers */
if (BCD_GETSIGN(p_bcd) != BCD_GETSIGN(p_bcdtoadd))
{
if (BCD_compare(p_bcd,p_bcdtoadd) < 0)
{
BCD_subt_bcd(p_bcdtoadd,BCD_abs(p_bcd));
BCD_move_bcd(p_bcd,p_bcdtoadd);
}
else
{
BCD_subt_bcd(p_bcd,p_bcdtoadd);
}
return;
}
for (idx = PHANTOM_MAX_BCDNO-1 ; idx > 0 ; idx--)
{
result = (p_bcd->digits[idx] + p_bcdtoadd->digits[idx]);
p_bcd->digits[idx] = (signed char)result;
}
BCD_ADJUST(p_bcd);
return;
} /* BCD_add_bcd() */
/*******************************************************************************************************
* BCD_adjust_improved()
* internal bcd function to adjust bcd struct after computation
*******************************************************************************************************/
static void
BCD_adjust_improved(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
int ledge) /* left edge (highest digit) last melded into bcd (add/subt) */
{
register int idx;
for (idx = PHANTOM_MAX_BCDNO-1 ; idx > ledge ; )
{
if (p_bcd->digits[idx] >= 0 && p_bcd->digits[idx] <= 9)
{
idx--;
}
else
{
if (p_bcd->digits[idx] > 9)
{
p_bcd->digits[idx-1]++;
p_bcd->digits[idx] -= 10;
}
else
{
p_bcd->digits[idx-1]--;
p_bcd->digits[idx] += 10;
}
}
}
return;
} /* BCD_adjust_improved() */
/*******************************************************************************************************
* PHANTOM_BCD_set()
* function to set a value into a PHANTOM_BCDNO struct
*******************************************************************************************************/
void
PHANTOM_BCD_set(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
unsigned long newval) /* no. to convert into a PHANTOM_BCDNO */
{
int idx;
unsigned long ulTemp = (unsigned long)PHANTOM_ONETHOUSAND * (unsigned long)PHANTOM_ONEMILLION;
/* clear the p_bcd storage */
p_bcd->sign[0] = 0;
for (idx = 0 ; idx < PHANTOM_MAX_BCDNO ; idx++)
{
p_bcd->digits[idx] = 0;
}
idx = PHANTOM_MAX_BCDNO-10;
while (ulTemp > 0UL && newval != 0UL)
{
if (newval >= ulTemp)
{
p_bcd->digits[idx]++;
newval -= ulTemp;
}
else
{
idx++;
ulTemp /= 10UL;
}
}
} /* PHANTOM_BCD_set() */
/*******************************************************************************************************
* BCD_subt_bcd() --
* function to subtract a PHANTOM_BCDNO from a PHANTOM_BCDNO
*******************************************************************************************************/
static void
BCD_subt_bcd(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
PHANTOM_BCDNO *p_subt) /* pointer to bcd struct */
{
int idx;
int bstart;
int result;
/* determine the range of bcd digits that must be addressed */
for ( bstart = 0 ; bstart <= PHANTOM_MAX_BCDNO-1 ; bstart++)
{
if (p_subt->digits[bstart] != 0)
{
if (bstart > 0)
{
bstart -= 1;
}
/* subtract from bcd */
for (idx = PHANTOM_MAX_BCDNO-1 ; idx > bstart ; idx--)
{
result = (p_bcd->digits[idx] - p_subt->digits[idx]);
p_bcd->digits[idx] = (signed char)result;
}
BCD_adjust_improved(p_bcd,bstart);
return;
}
}
return;
} /* BCD_subt_bcd() */
/*******************************************************************************************************
* PHANTOM_BCD_mult()
* function to multiply a PHANTOM_BCDNO by a binary number
*******************************************************************************************************/
void
PHANTOM_BCD_mult(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
unsigned long multby) /* binary number to multiply by */
{
static PHANTOM_BCDNO temp_bcd;
/* convert multby to bcd, then proceed */
PHANTOM_BCD_set(&temp_bcd,multby);
BCD_mult_bcd(p_bcd,&temp_bcd);
return;
} /* PHANTOM_BCD_mult() */
/*******************************************************************************************************
* BCD_mult_bcd_ones()
* function to multiply PHANTOM_BCDNO one digit at a time
*******************************************************************************************************/
static void
BCD_mult_bcd_ones(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
signed char digit) /* digit to multiply by */
{
int idx;
/* loop through each temp_bcd low digit until temp_bcd == zero */
for (idx = PHANTOM_MAX_BCDNO-1 ; idx > 0 ; idx--)
{
signed char result;
/* compute result */
result = (signed char)(p_bcd->digits[idx] * digit);
p_bcd->digits[idx] = result;
}
BCD_ADJUST(p_bcd);
return;
} /* BCD_mult_bcd_ones() */
/*******************************************************************************************************
* BCD_mult_bcd()
* function to multiply PHANTOM_BCDNO by a PHANTOM_BCDNO
*******************************************************************************************************/
static void
BCD_mult_bcd(PHANTOM_BCDNO *p_bcd, /* pointer to bcd struct */
PHANTOM_BCDNO *p_bcdmultby) /* pointer to bcd struct */
{
int i;
int cnt;
signed char digit;
signed int sign;
PHANTOM_BCDNO temp_bcd;
PHANTOM_BCDNO result;
PHANTOM_BCDNO result2;
sign = -1;
if (p_bcd->sign[0] == p_bcdmultby->sign[0])
{
sign = 0;
}
/* test for mult by zero */
if (BCD_zero(p_bcd) == True)
{
return;
}
if (BCD_zero(p_bcdmultby) == True)
{
BCD_CLEAR(p_bcd);
return;
}
/* mult two bcd numbers */
BCD_move_bcd(&temp_bcd,p_bcdmultby);
BCD_CLEAR(&result2);
cnt = 0;
while(BCD_zero(&temp_bcd) == False)
{
digit = temp_bcd.digits[PHANTOM_MAX_BCDNO-1];
BCD_div_ten(&temp_bcd);
if (digit != 0)
{
BCD_move_bcd(&result,p_bcd);
BCD_mult_bcd_ones(&result,digit);
if (cnt != 0) for (i = 0 ; i < cnt ; i++)
{
BCD_mult_ten(&result);
}
BCD_add_bcd(&result2,&result);
}
cnt++;
}
/* place computed results and sign back into caller storage */
BCD_move_bcd(p_bcd,&result2);
p_bcd->sign[0] = (signed char)(sign == -1 ? '-' : ' ');
return;
} /* BCD_mult_bcd() */
/*******************************************************************************************************
* BCD_div_bcd()
* function to divide a PHANTOM_BCDNO by a PHANTOM_BCDNO
*******************************************************************************************************/
static void
BCD_div_bcd(PHANTOM_BCDNO *p_numer, /* pointer to bcd struct */
PHANTOM_BCDNO *p_denom) /* pointer to bcd struct */
{
int i;
int lsd;
int done;
int step_numer = 0;
int len_denom = 0;
PHANTOM_BCDNO _numer;
PHANTOM_BCDNO *__numer;
PHANTOM_BCDNO _remainder;
PHANTOM_BCDNO *remainder;
PHANTOM_BCDNO _result;
PHANTOM_BCDNO *result;
__numer = &_numer;
result = &_result;
remainder = &_remainder;
BCD_move_bcd(&_numer,BCD_abs(p_numer));
BCD_CLEAR(result);
/* test if numbers can be divided */
if (BCD_compare(&_numer,BCD_abs(p_denom)) <= 0)
{
BCD_CLEAR(p_numer);
}
else
{
/* find the number of digits in p_denom */
for (len_denom = 0 ; len_denom < PHANTOM_MAX_BCDNO ; len_denom++)
{
if (p_denom->digits[len_denom] != 0)
{
break;
}
}
len_denom = (PHANTOM_MAX_BCDNO) - len_denom;
/* pull-out at-least len_denom digits from numerator */
for (step_numer = 0 ; step_numer < PHANTOM_MAX_BCDNO ; step_numer++)
{
if (p_numer->digits[step_numer] != 0)
{
break;
}
}
BCD_CLEAR(&_numer);
for (i = 0 ; i < len_denom ; i++)
{
BCD_mult_ten(&_numer);
BCD_LSD(__numer) = p_numer->digits[step_numer];
step_numer++;
}
/* subtract denom from nom, until too little remaining */
done = False;
while (done == False)
{
BCD_mult_ten(result);
while (BCD_compare(&_numer,BCD_abs(p_denom)) >= 0)
{
BCD_INCR(result);
BCD_subt_bcd(&_numer,BCD_abs(p_denom));
}
if (step_numer >= PHANTOM_MAX_BCDNO)
{
break;
}
/* save the remainder */
BCD_move_bcd(remainder,&_numer);
BCD_CLEAR(&_numer);
/* add remaining p_numer digits to end-of-result */
do
{
BCD_mult_ten(remainder);
lsd = p_numer->digits[step_numer];
BCD_LSD(remainder) = (signed char)lsd;
step_numer++;
if (step_numer >= PHANTOM_MAX_BCDNO)
{
break;
}
if (BCD_compare(remainder,BCD_abs(p_denom)) >= 0)
{
break;
}
else
{
BCD_mult_ten(result);
}
} while (done == False && step_numer < PHANTOM_MAX_BCDNO);
BCD_move_bcd(&_numer,remainder);
}
}
BCD_move_bcd(p_numer,result);
return;
} /* BCD_div_bcd() */
/*******************************************************************************************************
* PHANTOM_BCD_div()
* function to divide a PHANTOM_BCDNO by a binary number
*******************************************************************************************************/
void
PHANTOM_BCD_div(PHANTOM_BCDNO *p_numer, /* pointer to bcd struct */
unsigned long denom) /* binary demon */
{
PHANTOM_BCDNO _denom;
if (denom != 0UL)
{
/* convert denom to bcd, then divide */
PHANTOM_BCD_set(&_denom, denom);
BCD_div_bcd(p_numer, &_denom);
return;
}
/* if div by zero would have occurred, set result to 0, return */
PHANTOM_BCD_set(p_numer,0L);
return;
} /* PHANTOM_BCD_div() */
/*******************************************************************************************************
* PHANTOM_BCD_out()
* function to convert bcd number in PHANTOM_BCDNO struct to a long
*******************************************************************************************************/
unsigned long
PHANTOM_BCD_out(PHANTOM_BCDNO* p_bcd) /* pointer to bcd struct */
{
unsigned char i;
long lTemp = (long)PHANTOM_ONETHOUSAND *
(long)PHANTOM_ONETHOUSAND *
(long)PHANTOM_ONETHOUSAND;
unsigned long rtn = 0UL;
/* unsigned long will only hold several max 4+ billion, start at billions, and roll BCD out to unsigned long */
for (i = (PHANTOM_MAX_BCDNO-1)-9 ; i < PHANTOM_MAX_BCDNO ; i++)
{
rtn += ((unsigned long)(p_bcd->digits[i] * lTemp));
lTemp = lTemp/10L;
}
return(rtn);
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?