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