📄 lv2400x.c
字号:
// Reset counter
DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT1_CLR, TRUE); // Drive Clear counter bit high
DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT1_CLR, FALSE); // Drive Clear counter bit low
// Create the StartPattern (enable LV2400x counter) and StopPattern (disable LV2400x counter)
byTmp = GetSwRegValue(IR01_CNT_CTRL_REG);
byTmp |= IR1_CCTL_CNT_EN; // Enable counter pattern (start pattern)
wStart = MAKEWORD(byTmp, LSB(IR01_CNT_CTRL_REG));
byTmp &= (BYTE)(~IR1_CCTL_CNT_EN); // Disable counter pattern
wStop = MAKEWORD(byTmp, LSB(IR01_CNT_CTRL_REG));
// Start LV2400x counter and Pulse the NRW line
dwMeasureTimeUs = Pulse3wNRW(wStart, wStop, dwMeasureTimeUs);
// Read counter1 of LV2400x
wPulseCnt = ReadReg(IR01_CNT_H_REG); // High byte
wPulseCnt <<=8;
wPulseCnt |= ReadReg(IR01_CNT_L_REG); // Patch low byte
// Calculate measure frequency
*pwFreq = PulseToFrequency1(wPulseCnt, dwMeasureTimeUs);
return(LVLS_NO_ERROR);
} // End CountPulseCnt1
/* ************************************************************************************************
*
* Function: PulseToFrequency1
*
* Authors: Hung van Le
* Purpose: Convert 16 bit pulse count to frequency
* Input:
* wPulseCnt: 16 bit pulse count value
* dwMeasureTimeUs: measured time in us
* Output: The calculated frequency in Hz
* Comments: Use formula f = n * d / t
* where: f: frequency in Hz
* n: pulse count
* d: divider factor (fetched with GetDividerFactor-function)
* t: measured time in us
* This function is meant for measuring with counter 1 (software controlled timing)
* ************************************************************************************************
* Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
/*
WORD PulseToFrequency1(WORD wPulseCnt, DWORD dwMeasureTimeUs)
{
DWORD dwFreqHz;
DWORD dwUnit;
switch ( GetOutputSelect() )
{
case CO_RF_OSC:
dwUnit=10000; // 10 KHz unit for RF
break;
case CO_IF_OSC:
dwUnit=10; // 10 Hz unit for IF
break;
//case CO_SD_OSC:
default:
dwUnit=1; // 1 Hz unit for SD and other freq.
break;
}
dwFreqHz = (DWORD)wPulseCnt * GetDividerFactor();
// Pure unsigned 32 bit variant
{
DWORD dwM, dwK, dwH;
DWORD dwTmp1, dwTmp2;
dwM = dwFreqHz/dwMeasureTimeUs; // First dividing gives MHz because t is in us
dwTmp1 = dwFreqHz%dwMeasureTimeUs; // Remainder of MHz
dwTmp2 = dwTmp1/1000; // Extract KHz
dwK = (dwTmp2 * 1000000)/dwMeasureTimeUs; // KHz
dwH = (dwTmp2 * 1000000)%dwMeasureTimeUs; // Remainder of KHz
dwH = (dwH *1000)/dwMeasureTimeUs; // Hz from KHz
dwTmp2 = dwTmp1%1000; // Hz from MHz
dwH += ((dwTmp2 * 1000000)/dwMeasureTimeUs); // Total Hz
dwFreqHz = dwM*1000000 + dwK*1000 + dwH; // Total frequency
}
// MulDiv variant
//dwFreqHz = MulDiv(dwFreqHz, 1000000, dwMeasureTimeUs);
// Apply unit
dwFreqHz /= dwUnit;
// Shadow the measured frequency to simulates (frequency) read-registers
ShadowMeasuredFrequency(dwFreqHz);
return((WORD)dwFreqHz);
} // End PulseToFrequency1
*/
WORD PulseToFrequency1(WORD wPulseCnt, DWORD dwMeasureTimeUs)
{
DWORD dwFreq;
switch ( GetOutputSelect() )
{
case CO_RF_OSC:
dwFreq = (DWORD)wPulseCnt * IMR01_FM_DIVIDER;
dwFreq *= 100; // 10 KHz unit for RF
dwFreq/= dwMeasureTimeUs;
/*
// Round the measured frequency up to 10 kHz - this must also be done to all RF-usage (example. in FindFmStation)
dwFreq = (DWORD)wPulseCnt * IMR01_FM_DIVIDER;
dwFreq *= 1000; // RF: Calculate in kHz to round it up to 10 KHz unit later
dwFreq/= dwMeasureTimeUs; // RF freq is now in kHz
dwFreq = (dwFreq+5)/10; // 10 KHz unit for RF (with up rouding)
*/
break;
case CO_IF_OSC:
dwFreq = (DWORD)wPulseCnt * 100000; // 10 Hz unit for IF
dwFreq/= dwMeasureTimeUs;
break;
//case CO_SD_OSC:
default:
// 1 Hz unit for SD and other freq.
dwFreq = (DWORD)wPulseCnt;
// Pure unsigned 32 bit variant
{
DWORD dwM, dwK, dwH;
DWORD dwTmp1, dwTmp2;
dwM = dwFreq/dwMeasureTimeUs; // First dividing gives MHz because t is in us
dwTmp1 = dwFreq%dwMeasureTimeUs; // Remainder of MHz
dwTmp2 = dwTmp1/1000; // Extract KHz
dwK = (dwTmp2 * 1000000)/dwMeasureTimeUs; // KHz
dwH = (dwTmp2 * 1000000)%dwMeasureTimeUs; // Remainder of KHz
dwH = (dwH *1000)/dwMeasureTimeUs; // Hz from KHz
dwTmp2 = dwTmp1%1000; // Hz from MHz
dwH += ((dwTmp2 * 1000000)/dwMeasureTimeUs); // Total Hz
dwFreq = dwM*1000000 + dwK*1000 + dwH; // Total frequency
}
// MulDiv variant
//dwFreqHz = MulDiv(dwFreq, 1000000, dwMeasureTimeUs);
break;
}
// Shadow the measured frequency to simulates (frequency) read-registers
ShadowMeasuredFrequency(dwFreq);
return((WORD)dwFreq);
} // End PulseToFrequency1
/* ************************************************************************************************
*
* Function: CountPulseCnt2
*
* Authors: Hung van Le
* Purpose: Counting the pulse (Measure frequencies) of the currently
* selected chip's output. Measuring interval is made with external clock
* Input:
* PWORD pwFreq: buffer to receive the measured frequency (unit depends on chip output)
* Output: Status as defined in LvErr.h
* Comments: See also CountPulseCnt1
* The code is fixed for 12MHz external clock (counter swapping enabled)
* Counter 2 usage
* RF (100 MHz): IR1_CTAB_128, 128 (measuring time 0.66ms - 127ppm)
* RF (100 MHz): IR1_CTAB_512, 512 (measuring time 2.62ms - 32ppm)
*
* IF (45 kHz): IR1_CTAB_128, 128 (overflow !)
* IF (100 kHz): IR1_CTAB_128, 128 (measuring time 2.56ms - 33ppm)
*
* IF (45 kHz): IR1_CTAB_32, 32 (measuring time 1.42ms - 59ppm)
* IF (100 kHz): IR1_CTAB_32, 32 (measuring time 0.64ms - 130ppm)
*
* SD (38 kHz): IR1_CTAB_32, 32 (measuring time 1.68ms - 49ppm)
*
* RDS(57 kHz): IR1_CTAB_32, 32 (measuring time 1.12ms - 74ppm)
*
* Because of short measuring time, this method is not suitable for measuring IF/SD/RDS PLL
* in lock mode.
* In free running mode (calibration mode), this method can be used.
*
* RF is not PLL, so this methode always works
* We use following:
* RF 128
* IF/SD in free running mode: 32
* IF in lock mode: software window
*
* ************************************************************************************************
* Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
#ifdef USE_EXTCLK
BYTE CountPulseCnt2(PWORD pwFreq)
{
BYTE byResult;
WORD wPulseCnt1, wPulseCnt2;
BYTE byTab;
BOOL bSwapState, bCntSelState;
// Return value 0 means no pulses counted (chip removed?)
//*pwFreqHz = 0;
byResult = LVLS_NO_ERROR;
if (GetOutputSelect() == CO_RF_OSC)
{
byTab = IR1_CTAB_128; // Register value
wPulseCnt2 = 128 *IMR01_CNT2_PRESCALER; // Pulses for counter 2
}
else
{
byTab = IR1_CTAB_32; // Register value
wPulseCnt2 = 32 *IMR01_CNT2_PRESCALER; // Pulses for counter 2
}
// Reset counter 1
DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT1_CLR, TRUE); // Drive Clear counter bit of high
DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT1_CLR, FALSE); // Drive Clear counter bit of low
// Program swap counter bit, tab bit, select counter 2
bSwapState = DriveBitNeg(IR01_CNT_CTRL_REG, IR1_CCTL_SWP_CNT_L, TRUE); // Swap counter
bCntSelState = DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT_SEL, TRUE); // Select counter 2
SetRegBits(IR01_CNT_CTRL_REG, IR1_CCTL_CNT_TAB, byTab); // counter Tab setting
// Enable counter to start counting
DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT_EN, TRUE);
// Wait counting done - Poll register for counting done
wPulseCnt1 = 1500; // Temporary use wPulseCnt1 as loop counter
do
{
if (ReadReg(IR01_IRQ_ID_REG) & IR1_IRQID_CNT2) // Counting done bit set
break;
wPulseCnt1--;
DelayUs(DLT_100us);
} while (wPulseCnt1>0);
// Counting done - Disable the counter (also clear IR1_IRQID_CNT2 bit)
DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT_EN, FALSE);
// Check timeout
if (wPulseCnt1 == 0)
{
byResult = LVLS_POLLING_CNT_TIMEOUT;
}
else
{
// Read counter1 of LV2400x
wPulseCnt1 = ReadReg(IR01_CNT_H_REG); // High byte
wPulseCnt1 <<= 8;
wPulseCnt1 |= ReadReg(IR01_CNT_L_REG); // Patch low byte
}
// restore swap bit, counter select bit
DriveBitNeg(IR01_CNT_CTRL_REG, IR1_CCTL_SWP_CNT_L, bSwapState);
DriveBit(IR01_CNT_CTRL_REG, IR1_CCTL_CNT_SEL, bCntSelState);
// Formula to calculate frequency from pulse counts
// if NoSwapping
// f = (N1 * fext * DividerFactor)/N2
// if Swapping
// f = (N2 * fext * DividerFactor)/N1
// (N2 is value of counter 2 = TabValue * CNT2_div_factor)
*pwFreq = PulseToFrequency2(wPulseCnt2, wPulseCnt1);
return(byResult);
} // End CountPulseCnt2
#endif //USE_EXTCLK
#ifdef USE_EXTCLK
WORD PulseToFrequency2(WORD wCntA, WORD wCntB)
{
DWORD dwFreq;
// Avoid dividing by zero
if (wCntB == 0)
{
dwFreq = 0;
}
else
{
switch ( GetOutputSelect() )
{
case CO_RF_OSC:
dwFreq = (DWORD)wCntA * IMR01_FM_DIVIDER;
dwFreq *= (EXT_CLK_12MHZ/10000); // 10 KHz unit for RF
break;
case CO_IF_OSC:
dwFreq = (DWORD)wCntA * (EXT_CLK_12MHZ/10); // 10 Hz unit for IF
break;
//case CO_SD_OSC:
default:
dwFreq = (DWORD)wCntA * (EXT_CLK_12MHZ); // 1 Hz unit for other frequency
break;
}
dwFreq /= wCntB;
}
// Shadow the measured frequency to simulates (frequency) read-registers
ShadowMeasuredFrequency(dwFreq);
return((WORD)dwFreq);
} // End PulseToFrequency2
#endif //USE_EXTCLK
BYTE GetFmFieldStrength(void)
{
BYTE byRegValue;
BYTE byOrgMode;
BYTE byFs;
// Make sure the chip is in measuring mode for measure field strenggth
byOrgMode = DriveBit(IR01_RADIO_CTRL1_REG, IR1_RCTL1_EN_MEAS, TRUE);
// Read Radio status register to determine field strength
byRegValue = ReadReg(IR01_RADIO_STAT_REG);
// Extract FieldStrength
byRegValue &= IR1_RSTAT_FS; // extract field strength bits
byRegValue ^= IR1_RSTAT_FS; // Invert field strength level (0 becomes 1)
byFs = 0; // field strength to be returned
while (byRegValue != 0)
{
if ( byRegValue & 1 )
byFs++;
byRegValue>>=1;
}
// Restore measure mode
DriveBit(IR01_RADIO_CTRL1_REG, IR1_RCTL1_EN_MEAS, byOrgMode);
return(byFs);
} // End GetFmFieldStrength
BYTE GetStereoState(void)
{
// Determine stereo state of LV2400x
// Return: GSS_MONO: mono mode
// GSS_STEREO: stereo is enabled but no stereo recieving
// GSS_STEREO_DET: stereo is enabled and stereo detected
// Determine stereo enable state
if ( (GetSwRegValue(IR01_STEREO_CTRL_REG) & IR1_STCTL_STEREO_L) == 0 ) // Stereo bit = 0: stereo is enabled
{
if (ReadReg(IR01_RADIO_STAT_REG) & IR1_RSTAT_STEREO) // Stereo state bit = 1 (Stereo)
return(GSS_STEREO_DET); // Stereo is detected by the chip
else
return(GSS_STEREO); // Stereo is enabled but not detected
}
else
return(GSS_MONO);
} // End GetStereoState
/* ************************************************************************************************
*
* Function: ShadowMeasuredFrequency
*
* Authors: Hung van Le
* Purpose: Simulates some (frequency) read-registers which are missing in the chip
* Input:
* DWORD dwFreqHz: frequency (in Hz) to be shadowed
* Output: None
* Comments: Use GetOutputSelect to determine the frequency source
*
* ************************************************************************************************
* Copyright (c) 2002-2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
void ShadowMeasuredFrequency(DWORD dwFreqHz)
{
// Only save the RF frequency
if ( GetOutputSelect() == CO_RF_OSC)
{
g_wLastMsrRF = dwFreqHz;
}
} // End ShadowMeasuredFrequency
BYTE SetRfFrequency(WORD wRfFreq)
{
BYTE byResult;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -