📄 drx3973d.c
字号:
0, /* ucode size */
TRUE, /* ucode verify switch */
0, /* IF in kHz in case no tuner instance is used */
48000L, /* system clock frequency in kHz */
20000L, /* oscillator frequency kHz*/
0L, /* oscillator deviation in ppm, signed */
FALSE, /* If TRUE mirror frequency spectrum */
/* MPEG output configuration */
TRUE, /* If TRUE, enable MPEG ouput */
TRUE, /* If TRUE, insert RS byte */
TRUE, /* If TRUE, parallel out otherwise serial */
FALSE, /* If TRUE, invert DATA signals */
FALSE, /* If TRUE, invert ERR signal */
FALSE, /* If TRUE, invert STR signals */
FALSE, /* If TRUE, invert VAL signals */
FALSE, /* If TRUE, invert CLK signals */
FALSE, /* isOpened */
/* Scan */
NULL, /* no scan params yet */
0, /* current scan index */
0, /* next scan frequency */
FALSE, /* scan ready flag */
0L, /* max channels to scan */
0L, /* nr of channels scanned */
0, /* millisec to wait for demod lock */
DRX3973D_DEMOD_LOCK, /* desired lock */
FALSE, /* scan routines active or not */
/* Power management */
DRX_POWER_DOWN,
/* Tuner */
1, /* nr of I2C port to wich tuner is */
0L, /* minimum RF input frequency, in kHz */
0L /* maximum RF input frequency, in kHz */
};
/**
* \var DRX3973DDefaultDemod_g
* \brief Default drx3973d demodulator instance.
*/
DRXDemodInstance_t DRX3973DDefaultDemod_g = {
&DRX3973DFunctions_g, /* demod functions */
&DRX3973D_DAP, /* data access protocol functions */
NULL, /* tuner instance */
&DRX3973DDefaultAddr_g, /* i2c address & device id */
&DRX3973DDefaultCommAttr_g, /* demod common attributes */
&DRX3973DData_g /* demod device specific attributes */
};
/*-----------------------------------------------------------------------------
STRUCTURES
----------------------------------------------------------------------------*/
typedef struct {
u16_t cmd;
u16_t param1;
u16_t param2;
u16_t param3;
u16_t param4;
u16_t param5;
} DRX3973DHiCmd_t, *pDRX3973DHiCmd_t;
/*-----------------------------------------------------------------------------
FUNCTIONS
----------------------------------------------------------------------------*/
/* Some prototypes */
static DRXStatus_t CtrlI2CBridge( pDRXDemodInstance_t demod,
pBool_t bridgeClosed );
static DRXStatus_t CtrlUIOWrite( pDRXDemodInstance_t demod,
pDRXUIOData_t UIOData);
static DRXStatus_t CtrlLockStatus( pI2CDeviceAddr_t devAddr,
pDRXLockStatus_t lockStat );
static DRXStatus_t HI_CfgCommand(const pDRXDemodInstance_t demod);
static DRXStatus_t
CtrlSetCfgIfAgc( pDRXDemodInstance_t demod, pDRX3973DCfgAgc_t cfg );
static DRXStatus_t
CtrlSetCfgRfAgc( pDRXDemodInstance_t demod, pDRX3973DCfgAgc_t cfg );
static DRXStatus_t
HI_Command(const pI2CDeviceAddr_t devAddr,
const pDRX3973DHiCmd_t cmd,
pu16_t result);
/*=============================================================================
=============================================================================
===== HELPER FUNCTIONS ======================================================
=============================================================================
===========================================================================*/
/*============================================================================*/
/**
* \fn void WaitMilliSec()
* \brief Wait (loop) at least n millisec
* \param n millisec to wait
*
*/
static DRXStatus_t WaitMilliSec(u16_t n)
{
u32_t start=0;
u32_t current=0;
u32_t delta=0;
start = DRXBSP_HST_Clock();
do{
current = DRXBSP_HST_Clock();
delta = current - start;
} while( delta < n );
return (DRX_STS_OK);
}
/*============================================================================*/
/**
* \fn void Mult32(u32_t a, u32_t b, pu32_t h, pu32_t l)
* \brief 32bitsx32bits signed multiplication
* \param a 32 bits multiplicant
* \param b 32 bits multiplier
* \param h pointer to high part 64 bits result
* \param l pointer to low part 64 bits result
*/
static void Mult32(u32_t a, u32_t b, ps32_t h, pu32_t l)
{
u8_t i = 0;
*l =0;
*h =0;
for ( i=0 ; i<32 ; i++)
{
if ( a & 1)
{
*h += b;
}
/* shift [h:l] one right */
(*l) >>= 1;
if ( (*h) & 1)
{
*l |= 0x80000000UL;
}
(*h) >>=1;
/* shift multiplicant one right */
a >>=1;
}
}
/*============================================================================*/
static u32_t Frac28(u32_t N, u32_t D)
/*
This function is used to avoid floating-point calculations as they may
not be present on the target platform.
Frac28 performs an unsigned 28/28 bits division to 32-bit fixed point
fraction used for setting the Frequency Shifter registers.
N and D can hold numbers up to width: 28-bits.
The 4 bits integer part and the 28 bits fractional part are calculated.
Effectually calculates: (1<<28)*N/D
N: 0...(1<<28)-1 = 268435454
D: 0...(1<<28)-1
Q: 0...(1<<32)-1
*/
{
u8_t i=0;
u32_t Q1=0;
u32_t R0=0;
R0 = (N%D)<<4; /* 32-28 == 4 shifts possible at max */
Q1 = N/D; /* integer part, only the 4 least significant bits
will be visible in the result */
/* division using radix 16, 7 nibbles in the result */
for (i=0; i<7; i++) {
Q1 = (Q1 << 4) | R0/D;
R0 = (R0%D)<<4;
}
/* rounding */
if ((R0>>3) >= D) Q1++;
return Q1;
}
/*============================================================================*/
/**
* \fn u32_t FracTimes1e6( u16_t N, u32_t D)
* \brief Compute: (N/D) * 1000000.
* \param N nominator 16-bits.
* \param D denominator 32-bits.
* \return u32_t
* \retval ((N/D) * 1000000), 32 bits
*
* No check on D=0!
*/
static u32_t
FracTimes1e6( u16_t N, u32_t D)
{
u32_t remainder = 0;
u32_t frac = 0;
/*
frac = (N * 1000000) / D
To let it fit in a 32 bits computation:
frac = (N * (1000000 >> 4)) / (D >> 4)
This would result in a problem in case D < 16 (div by 0).
So we do it more elaborate as shown below.
*/
frac = ( ((u32_t)N) * (1000000UL >> 4) ) / D ;
frac <<= 4 ;
remainder = ( ((u32_t)N) * (1000000UL >> 4) ) % D ;
remainder <<= 4;
frac += remainder / D;
remainder = remainder % D ;
if( (remainder * 2) > D )
{
frac++;
}
return ( frac );
}
/*============================================================================*/
/**
* \fn u32_t Log10Times100( u32_t x)
* \brief Compute: 100*log10(x)
* \param x 32 bits
* \return 100*log10(x)
*
* 100*log10(x)
* = 100*(log2(x)/log2(10)))
* = (100*(2^15)*log2(x))/((2^15)*log2(10))
* = ((200*(2^15)*log2(x))/((2^15)*log2(10)))/2
* = ((200*(2^15)*(log2(x/y)+log2(y)))/((2^15)*log2(10)))/2
* = ((200*(2^15)*log2(x/y))+(200*(2^15)*log2(y)))/((2^15)*log2(10)))/2
*
* where y = 2^k and 1<= (x/y) < 2
*/
u32_t Log10Times100( u32_t x)
{
static const u8_t scale=15;
static const u8_t indexWidth=5;
/*
log2lut[n] = (1<<scale) * 200 * log2( 1.0 + ( (1.0/(1<<INDEXWIDTH)) * n ))
0 <= n < ((1<<INDEXWIDTH)+1)
*/
static const u32_t log2lut[] = {
0, /* 0.000000 */
290941, /* 290941.300628 */
573196, /* 573196.476418 */
847269, /* 847269.179851 */
1113620, /* 1113620.489452 */
1372674, /* 1372673.576986 */
1624818, /* 1624817.752104 */
1870412, /* 1870411.981536 */
2109788, /* 2109787.962654 */
2343253, /* 2343252.817465 */
2571091, /* 2571091.461923 */
2793569, /* 2793568.696416 */
3010931, /* 3010931.055901 */
3223408, /* 3223408.452106 */
3431216, /* 3431215.635215 */
3634553, /* 3634553.498355 */
3833610, /* 3833610.244726 */
4028562, /* 4028562.434393 */
4219576, /* 4219575.925308 */
4406807, /* 4406806.721144 */
4590402, /* 4590401.736809 */
4770499, /* 4770499.491025 */
4947231, /* 4947230.734179 */
5120719, /* 5120719.018555 */
5291081, /* 5291081.217197 */
5458428, /* 5458427.996830 */
5622864, /* 5622864.249668 */
5784489, /* 5784489.488298 */
5943398, /* 5943398.207380 */
6099680, /* 6099680.215452 */
6253421, /* 6253420.939751 */
6404702, /* 6404701.706649 */
6553600, /* 6553600.000000 */
};
u8_t i = 0;
u32_t y = 0;
u32_t d = 0;
u32_t k = 0;
u32_t r = 0;
if (x==0) return (0);
/* Scale x (normalize) */
/* computing y in log(x/y) = log(x) - log(y) */
if ( (x & (((u32_t)(-1))<<(scale+1)) ) == 0 )
{
for (k = scale; k>0 ; k--)
{
if (x & (((u32_t)1)<<scale)) break;
x <<= 1;
}
} else {
for (k = scale; k<31 ; k++)
{
if ((x & (((u32_t)(-1))<<(scale+1)))==0) break;
x >>= 1;
}
}
/*
Now x has binary point between bit[scale] and bit[scale-1]
and 1.0 <= x < 2.0 */
/* correction for divison: log(x) = log(x/y)+log(y) */
y = k * ( ( ((u32_t)1) << scale ) * 200 );
/* remove integer part */
x &= ((((u32_t)1) << scale)-1);
/* get index */
i = (u8_t) (x >> (scale -indexWidth));
/* compute delta (x-a) */
d = x & ((((u32_t)1) << (scale-indexWidth))-1);
/* compute log, multiplication ( d* (.. )) must be within range ! */
y += log2lut[i] + (( d*( log2lut[i+1]-log2lut[i] ))>>(scale-indexWidth));
/* Conver to log10() */
y /= 108853; /* (log2(10) << scale) */
r = (y>>1);
/* rounding */
if (y&((u32_t)1)) r++;
return (r);
}
/*=============================================================================
===== Atomic data access related stuff ======================================
===========================================================================*/
#define HI_TR_FUNC_ADDR HI_IF_RAM_USR_BEGIN__A
static
DRXStatus_t InitAtomicRead ( pI2CDeviceAddr_t devAddr )
{
static u8_t instructions[] =
{
0x26, 0x00, /* 0 -> ring.rdy; */
0x60, 0x04, /* r0rami.dt -> ring.xba; */
0x61, 0x04, /* r0rami.dt -> ring.xad; */
0xE3, 0x07, /* HI_RA_RAM_USR_BEGIN -> ring.iad; */
0x40, 0x00, /* (long immediate) */
0x64, 0x04, /* r0rami.dt -> ring.len; */
0x65, 0x04, /* r0rami.dt -> ring.ctl; */
0x26, 0x00, /* 0 -> ring.rdy; */
0x38, 0x00 /* 0 -> jumps.ad; */
};
WRBLOCK( devAddr, HI_TR_FUNC_ADDR , sizeof(instructions), instructions );
return DRX_STS_OK;
rw_error:
return (DRX_STS_ERROR);
}
/**
* \fn DRXStatus_t AtomicReadBlock()
* \brief Atomic read of n bytes
*
* Flags are ignored for now ...
*/
#define HI_TR_WRITE 0x9
#define HI_TR_READ 0xA
#define HI_TR_READ_WRITE 0xB
#define HI_TR_BROADCAST 0x4
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -