📄 mt_spuravoid.c
字号:
** Description: Choose the best available 1st IF** If f_Desired is not excluded, choose that first.** Otherwise, return the value closest to f_Center that is** not excluded**** Revision History:**** SCR Date Author Description** -------------------------------------------------------------------------** 117 03-29-2007 RSK Ver 1.15: Re-wrote to match search order from** tuner DLL.** 147 07-27-2007 RSK Ver 1.17: Corrected calculation (-) to (+)** Added logic to force f_Center within 1/2 f_Step.*******************************************************************************/UData_t MT_ChooseFirstIF(MT_AvoidSpursData_t* pAS_Info){ /* ** Update "f_Desired" to be the nearest "combinational-multiple" of "f_LO1_Step". ** The resulting number, F_LO1 must be a multiple of f_LO1_Step. And F_LO1 is the arithmetic sum ** of f_in + f_Center. Neither f_in, nor f_Center must be a multiple of f_LO1_Step. ** However, the sum must be. */ const UData_t f_Desired = pAS_Info->f_LO1_Step * ((pAS_Info->f_if1_Request + pAS_Info->f_in + pAS_Info->f_LO1_Step/2) / pAS_Info->f_LO1_Step) - pAS_Info->f_in; const UData_t f_Step = (pAS_Info->f_LO1_Step > pAS_Info->f_LO2_Step) ? pAS_Info->f_LO1_Step : pAS_Info->f_LO2_Step; UData_t f_Center; SData_t i; SData_t j = 0; UData_t bDesiredExcluded = 0; UData_t bZeroExcluded = 0; SData_t tmpMin, tmpMax; SData_t bestDiff; struct MT_ExclZone_t* pNode = pAS_Info->usedZones; struct MT_FIFZone_t zones[MAX_ZONES]; if (pAS_Info->nZones == 0) return f_Desired; /* f_Center needs to be an integer multiple of f_Step away from f_Desired */ if (pAS_Info->f_if1_Center > f_Desired) f_Center = f_Desired + f_Step * ((pAS_Info->f_if1_Center - f_Desired + f_Step/2) / f_Step); else f_Center = f_Desired - f_Step * ((f_Desired - pAS_Info->f_if1_Center + f_Step/2) / f_Step); assert(abs((SData_t) f_Center - (SData_t) pAS_Info->f_if1_Center) <= (SData_t) (f_Step/2)); /* Take MT_ExclZones, center around f_Center and change the resolution to f_Step */ while (pNode != NULL) { /* floor function */ tmpMin = floor((SData_t) (pNode->min_ - f_Center), (SData_t) f_Step); /* ceil function */ tmpMax = ceil((SData_t) (pNode->max_ - f_Center), (SData_t) f_Step); if ((pNode->min_ < f_Desired) && (pNode->max_ > f_Desired)) bDesiredExcluded = 1; if ((tmpMin < 0) && (tmpMax > 0)) bZeroExcluded = 1; /* See if this zone overlaps the previous */ if ((j>0) && (tmpMin < zones[j-1].max_)) zones[j-1].max_ = tmpMax; else { /* Add new zone */ assert(j<MAX_ZONES); zones[j].min_ = tmpMin; zones[j].max_ = tmpMax; j++; } pNode = pNode->next_; } /* ** If the desired is okay, return with it */ if (bDesiredExcluded == 0) return f_Desired; /* ** If the desired is excluded and the center is okay, return with it */ if (bZeroExcluded == 0) return f_Center; /* Find the value closest to 0 (f_Center) */ bestDiff = zones[0].min_; for (i=0; i<j; i++) { if (abs(zones[i].min_) < abs(bestDiff)) bestDiff = zones[i].min_; if (abs(zones[i].max_) < abs(bestDiff)) bestDiff = zones[i].max_; } if (bestDiff < 0) return f_Center - ((UData_t) (-bestDiff) * f_Step); return f_Center + (bestDiff * f_Step);}/******************************************************************************** Name: gcd**** Description: Uses Euclid's algorithm**** Parameters: u, v - unsigned values whose GCD is desired.**** Global: None**** Returns: greatest common divisor of u and v, if either value** is 0, the other value is returned as the result.**** Dependencies: None.**** Revision History:**** SCR Date Author Description** -------------------------------------------------------------------------** N/A 06-01-2004 JWS Original** N/A 08-03-2004 DAD Changed to Euclid's since it can handle** unsigned numbers.******************************************************************************/static UData_t gcd(UData_t u, UData_t v){ UData_t r; while (v != 0) { r = u % v; u = v; v = r; } return u;}/******************************************************************************** Name: umax**** Description: Implements a simple maximum function for unsigned numbers.** Implemented as a function rather than a macro to avoid** multiple evaluation of the calling parameters.**** Parameters: a, b - Values to be compared**** Global: None**** Returns: larger of the input values.**** Dependencies: None.**** Revision History:**** SCR Date Author Description** -------------------------------------------------------------------------** N/A 06-02-2004 JWS Original******************************************************************************/static UData_t umax(UData_t a, UData_t b){ return (a >= b) ? a : b;}#if MT_TUNER_CNT > 1static SData_t RoundAwayFromZero(SData_t n, SData_t d){ return (n<0) ? floor(n, d) : ceil(n, d);}/******************************************************************************** Name: IsSpurInAdjTunerBand**** Description: Checks to see if a spur will be present within the IF's** bandwidth or near the zero IF.** (fIFOut +/- fIFBW/2, -fIFOut +/- fIFBW/2)** and** (0 +/- fZIFBW/2)**** ma mb me mf mc md** <--+-+-+-----------------+-+-+-----------------+-+-+-->** | ^ 0 ^ |** ^ b=-fIFOut+fIFBW/2 -b=+fIFOut-fIFBW/2 ^** a=-fIFOut-fIFBW/2 -a=+fIFOut+fIFBW/2**** Note that some equations are doubled to prevent round-off** problems when calculating fIFBW/2**** The spur frequencies are computed as:**** fSpur = n * f1 - m * f2 - fOffset**** Parameters: f1 - The 1st local oscillator (LO) frequency** of the tuner whose output we are examining** f2 - The 1st local oscillator (LO) frequency** of the adjacent tuner** fOffset - The 2nd local oscillator of the tuner whose** output we are examining** fIFOut - Output IF center frequency** fIFBW - Output IF Bandwidth** nMaxH - max # of LO harmonics to search** fp - If spur, positive distance to spur-free band edge (returned)** fm - If spur, negative distance to spur-free band edge (returned)**** Returns: 1 if an LO spur would be present, otherwise 0.**** Dependencies: None.**** Revision History:**** SCR Date Author Description** -------------------------------------------------------------------------** N/A 01-21-2005 JWS Original, adapted from MT_DoubleConversion.** 115 03-23-2007 DAD Fix declaration of spur due to truncation** errors.** 137 06-18-2007 DAD Ver 1.16: Fix possible divide-by-0 error for** multi-tuners that have** (delta IF1) > (f_out-f_outbw/2).** 177 S 02-26-2008 RSK Ver 1.18: Corrected calculation using LO1 > MAX/2** Type casts added to preserve correct sign.******************************************************************************/static UData_t IsSpurInAdjTunerBand(UData_t bIsMyOutput, UData_t f1, UData_t f2, UData_t fOffset, UData_t fIFOut, UData_t fIFBW, UData_t fZIFBW, UData_t nMaxH, UData_t *fp, UData_t *fm){ UData_t bSpurFound = 0; const UData_t fHalf_IFBW = fIFBW / 2; const UData_t fHalf_ZIFBW = fZIFBW / 2; /* Calculate a scale factor for all frequencies, so that our calculations all stay within 31 bits */ const UData_t f_Scale = ((f1 + (fOffset + fIFOut + fHalf_IFBW) / nMaxH) / (MAX_UDATA/2 / nMaxH)) + 1; /* ** After this scaling, _f1, _f2, and _f3 are guaranteed to fit into ** signed data types (smaller than MAX_UDATA/2) */ const SData_t _f1 = (SData_t) ( f1 / f_Scale); const SData_t _f2 = (SData_t) ( f2 / f_Scale); const SData_t _f3 = (SData_t) (fOffset / f_Scale); const SData_t c = (SData_t) (fIFOut - fHalf_IFBW) / (SData_t) f_Scale; const SData_t d = (SData_t) ((fIFOut + fHalf_IFBW) / f_Scale); const SData_t f = (SData_t) (fHalf_ZIFBW / f_Scale); SData_t ma, mb, mc, md, me, mf; SData_t fp_ = 0; SData_t fm_ = 0; SData_t n; /* ** If the other tuner does not have an LO frequency defined, ** assume that we cannot interfere with it */ if (f2 == 0) return 0; /* Check out all multiples of f1 from -nMaxH to +nMaxH */ for (n = -(SData_t)nMaxH; n <= (SData_t)nMaxH; ++n) { const SData_t nf1 = n*_f1; md = (_f3 + d - nf1) / _f2; /* If # f2 harmonics > nMaxH, then no spurs present */ if (md <= -(SData_t) nMaxH ) break; ma = (_f3 - d - nf1) / _f2; if ((ma == md) || (ma >= (SData_t) (nMaxH))) continue; mc = (_f3 + c - nf1) / _f2; if (mc != md) { const SData_t m = (n<0) ? md : mc; const SData_t fspur = (nf1 + m*_f2 - _f3); const SData_t den = (bIsMyOutput ? n - 1 : n); if (den == 0) { fp_ = (d - fspur)* f_Scale; fm_ = (fspur - c)* f_Scale; } else { fp_ = (SData_t) RoundAwayFromZero((d - fspur)* f_Scale, den); fm_ = (SData_t) RoundAwayFromZero((fspur - c)* f_Scale, den); } if (((UData_t)abs(fm_) >= f_Scale) && ((UData_t)abs(fp_) >= f_Scale)) { bSpurFound = 1; break; } } /* Location of Zero-IF-spur to be checked */ mf = (_f3 + f - nf1) / _f2; me = (_f3 - f - nf1) / _f2; if (me != mf) { const SData_t m = (n<0) ? mf : me; const SData_t fspur = (nf1 + m*_f2 - _f3); const SData_t den = (bIsMyOutput ? n - 1 : n); if (den == 0) { fp_ = (d - fspur)* f_Scale; fm_ = (fspur - c)* f_Scale; } else { fp_ = (SData_t) RoundAwayFromZero((f - fspur)* f_Scale, den); fm_ = (SData_t) RoundAwayFromZero((fspur + f)* f_Scale, den); } if (((UData_t)abs(fm_) >= f_Scale) && ((UData_t)abs(fp_) >= f_Scale)) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -