📄 lv2400x.c
字号:
case CO_IF_OSC: // IF Osccilator output
SetRegBits(IR01_MSRC_SEL_REG, IR1_MSRCS_MSS_MASK, IR1_MSRCS_MSS_IF);
break;
case CO_SD_OSC: // Stereo decoder clock output
SetRegBits(IR01_MSRC_SEL_REG, IR1_MSRCS_MSS_MASK, IR1_MSRCS_MSS_SD);
break;
default:
// Invalid output select
break;
}
return(wCurOutputCfg);
} // End SetOutputSelect
/* ************************************************************************************************
*
* Function: SetUpChipMode
*
* Authors: Hung van Le
* Purpose: Prepare/Restore chip mode by starting/ending measurement
* Input:
* WORD wCfgIn: desired config (See SetUpChipMode in Lv24Ekit.h for definitions)
* Output: The original config (for restoring chip mode later)
* Comments: Use this routine before measuring chip's frequencies. It manages the measurement mode
* and the AFC state of the hardware
*
* ************************************************************************************************
* Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
WORD SetUpChipMode(WORD wCfgIn)
{
WORD wCfgOut;
// Handle the restore flag first
if (wCfgIn & CHR01_MSR_MODE_FLG ) // Restore chip measure mode flag set
DriveBit(IR01_RADIO_CTRL1_REG, IR1_RCTL1_EN_MEAS, ((wCfgIn & CHR01_MSR_MODE_ON)!=0));
// Select the desired oscillator output to measure
wCfgOut = SetOutputSelect(wCfgIn & CO_SELECT_MASK);
// Enable measuring with the chip
if (wCfgIn & CHIP_MEASURE_MODE)
{
wCfgOut |= CHR01_MSR_MODE_FLG; // Mark that we have to restore it later
if ( DriveBit(IR01_RADIO_CTRL1_REG, IR1_RCTL1_EN_MEAS, TRUE) )
wCfgOut |= CHR01_MSR_MODE_ON; // Remember the state for restoring
}
// Do we have to adjust the AFC state?
if (wCfgIn & CHIP_SET_AFC )
{
// Yes - Set AFC to new state and remember the previous state for retoring it later
if ( SetAFCMode((wCfgIn & CHIP_AFC_STATE)!=0) )
wCfgOut |= CHIP_AFC_ON;
else
wCfgOut |= CHIP_AFC_OFF;
}
return(wCfgOut);
} // End SetUpChipMode
/* ************************************************************************************************
*
* Function: Virtualize register access to the hardware
* WriteIfOsc (adjust the DAC of IF PLL )
* WriteSdOsc (adjust the DAC of Stereo decoder clock)
* WriteRfOsc (adjust the DAC of RF varicap)
* Authors: Hung van Le
* Purpose: These functions provide access to registers of the device which are used for setting frequencies
* Comments: None
*
* ************************************************************************************************
* Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
BYTE WriteIfOsc(WORD wIfOscValue)
{
WORD wTmp;
// Positive IF osc (ie IF frequency increases when the osc value increases)
if (wIfOscValue > 0xFF)
return(LVLS_IFOSC_OUTOFLIMIT_ERR);
WriteReg(IR01_IF_OSC_REG, (BYTE)wIfOscValue);
// Program IF Center Frequency Oscillator and IF bandwidth according to the value of IF_OSC
WriteReg(IR01_IFCEN_OSC_REG, (BYTE)wIfOscValue); // IF center has the same value as IF DAC
// IF BW is 65% of IF DAC value
wTmp = (WORD)wIfOscValue*65;
wTmp /= 100;
WriteReg(IR01_IF_BW_REG, (BYTE)wTmp);
return(LVLS_NO_ERROR);
} // End WriteIfOsc
BYTE WriteSdOsc(WORD wSdOscValue)
{
// Positive Stereo decoder clock (ie SD frequency increases when the osc value increases)
if (wSdOscValue > 0xFF)
return(LVLS_STEREOSC_OUTOFLIMIT_ERR);
WriteReg(IR01_SD_OSC_REG, (BYTE)wSdOscValue);
return(LVLS_NO_ERROR);
} // End WriteSdOsc
BYTE WriteRfOsc(WORD wRfOscValue)
{
// Positive FM osc (ie FM frequency increases when the osc value increases)
if (wRfOscValue > 0xFF)
return(LVLS_RFOSC_OUTOFLIMIT_ERR);
WriteReg(IR01_FM_OSC_REG, (BYTE)wRfOscValue);
return(LVLS_NO_ERROR);
} // End WriteRfOsc
/* ************************************************************************************************
*
* Function: WriteRfCap
* Authors: Hung van Le
* Purpose: Virtualized register access to FM-capacitor bank switch
* Input:
* WORD wCapValue: the logical CAP value (will be converted to hardware value)
* Output: Status as defined in LvErr.h
* Comments:
* Write the CAP bank select - using software logical value to deal with 7.5 bits FM CAP
* Logical value Physical value
* 0...63 255...193
* 64..191 127...0
* Following conversions are used:
* - Hardware to software conversion:
* if hw<128
* sw=~(hw+64)
* else
* sw=~hw
* - Software to hardware conversion:
* if sw<64
* hw=~sw
* else
* hw=~sw-64
*
* ************************************************************************************************
* Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
BYTE WriteRfCap(WORD wCapValue)
{
// Make sure value is valid
if ( wCapValue > QSS_MAX_RFCAP ) // Value exceeds limit
return(LVLS_RFCAP_OUTOFLIMIT_ERR);
// Convert the software value to hardware value before writing it
if (wCapValue < 64)
wCapValue = 255 - wCapValue;
else
wCapValue = 255 - wCapValue - 64;
// Write value to the chip
WriteReg(IR01_FM_CAP_REG, (BYTE)wCapValue);
return(LVLS_NO_ERROR);
} // End WriteRfCap
BYTE GetRfCapValue(void)
{
// The shadow register contains the physical value, software expects logical value as return value.
// so convert the value
BYTE byLogicalCap, byCurCapValue;
byCurCapValue = GetSwRegValue(IR01_FM_CAP_REG);
byLogicalCap = 255 - byCurCapValue;
if ( byCurCapValue < 128 )
byLogicalCap -= 64;
return(byLogicalCap);
} // End GetRfCapValue
BYTE SetAFCMode(BYTE byEnable)
{
// Reset AFC bit = !EnableState
DriveBit(IR01_RADIO_CTRL1_REG, IR1_RCTL1_RST_AFC, !byEnable);
// Set IOSC_ON bit and return it previous state
return(DriveBit(IR01_RADIO_CTRL1_REG, IR1_RCTL1_EN_AFC, byEnable));
} // End SetAFCMode
BYTE SetDeemphasis(BYTE byDeemp)
{
return(DriveBit(IR01_AUDIO_CTRL2_REG, IR1_ACTL2_DEEMP75, byDeemp));
} // End SetDeemphasis
BYTE SetStereoMono(BOOL bStereo)
{
// Input:
// bStereo: TRUE: stereo - FALSE: mono
BYTE byResult;
// No error yet
byResult = LVLS_NO_ERROR;
if (bStereo) // stereo mode request
{
byResult = Set_SD_Freq(DEFAULT_SD_FREQ); // Set the stereo decoder clock
}
// Enable/Disable stereo according to input
if (byResult != LVLS_NO_ERROR)
bStereo = FALSE; // Force mono mode
SetChipStereo(bStereo);
return(byResult);
} // End SetStereoMono
BYTE SetChipStereo(BYTE byStereo)
{
BYTE byOrgValue;
byOrgValue = DriveBitNeg(IR01_STEREO_CTRL_REG, IR1_STCTL_STEREO_L, byStereo);
// Show value
CallBack(CRSN_MS_CHNG);
return(byOrgValue);
} // End SetChipStereo
BYTE GetChipVolume(void)
{
// The LV2400x has 4 bits volume and 1 volume shift bit.
// The logical levels are defined as follow:
// Level Vol[3:0] VolShiftBit Range
// 0...15 0...15 0 3...48 dB
// 16..19 12..15 1 51..60 dB
BYTE byVolLevel;
// Fetch the 4 bits volume
byVolLevel = GetSwRegValue(IR01_AUDIO_CTRL1_REG) & IR1_ACTL1_VOL_LVL;
// Volume bit is inverted @@@@
byVolLevel = 15 - byVolLevel;
// Determine the volume shift bit
if ( GetSwRegValue(IR01_RADIO_CTRL3_REG) & IR1_RCTL3_VOL_SHIFT )
byVolLevel += 4;
return(byVolLevel);
} // End GetChipVolume
void SetChipVolume(BYTE byLevel)
{
// Input: the logical volume level (0..19)
BYTE byRegValue;
BOOL bShiftVol;
if (byLevel<16)
{
bShiftVol = FALSE;
}
else
{
if (byLevel>19)
byLevel = 19; // Make sure we have valid level
byLevel -= 4;
bShiftVol = TRUE;
}
// IR01_AUDIO_CTRL1_REG has bit[7:4] as tone control, [3:0] as volume. We want to keep the tone control
// as same as the volume level until the dynamic bass boost level reached
byRegValue = (15-byLevel); // Volume value is the invertion of logical level (volume bits are inverted)
if (byLevel > g_byDynBassBoost) // Check tone level against dynamic bass boost
byLevel = g_byDynBassBoost; // If exceeds, wrap it back
byLevel = 15-byLevel; // The tone value is the invertion of tone level (tone bits are inverted)
byRegValue |= (byLevel<<4); // Shift tone value to its position and patch into volume value
// Update hardware
DriveBit(IR01_RADIO_CTRL3_REG, IR1_RCTL3_VOL_SHIFT, bShiftVol);
WriteReg(IR01_AUDIO_CTRL1_REG, byRegValue);
} // End SetChipVolume
/* ************************************************************************************************
*
* Function: SetChipAudioMute
*
* Authors: Hung van Le
* Purpose: Handle the sotware audio mute
* Input: BYTE byMute: new mute state
* BYTE byMuteSrc: mute source
* Output: Original (software) audio mute state
* Comments: Mute state: 0=no mute, 1=muted
*
* ************************************************************************************************
* Copyright (c) 2002-2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
BYTE SetChipAudioMute(BYTE byMute, BYTE bySource)
{
BYTE byCurState;
// Determine current state (for returning it later)
if ( (g_bySwFlag1 & bySource)==0 )
byCurState = 0; // unmute
else
byCurState = 1; // mute
if (byMute) // mute request
{
// Mute the chip
DriveBitNeg(IR01_RADIO_CTRL3_REG, IR1_RCTL3_AUDIO_MUTE_L, 1);
g_bySwFlag1 |= bySource; // register mute source
}
else // unmute request
{
g_bySwFlag1 &= (~bySource); // register unmute source
if ( (g_bySwFlag1 & MUTESRC_MASK) == 0) // the chip comes in unmute mode
DriveBitNeg(IR01_RADIO_CTRL3_REG, IR1_RCTL3_AUDIO_MUTE_L, 0);
}
return(byCurState);
} // End SetChipAudioMute
/* ************************************************************************************************
*
* Function: GetDividerFactor
*
* Authors: Hung van Le
* Purpose: Determine the (internal) divider factor by current chip output select
* Input: None
* Output: The divider factor belongs to current chip output
* Comments: For this device: the divider factor is 256 for FM output, 1 for other outputs
*
* ************************************************************************************************
* Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
WORD GetDividerFactor(void)
{
if ( GetOutputSelect() == CO_RF_OSC )
return(IMR01_FM_DIVIDER); // usualy 256
else
return(1);
} // End GetDividerFactor
BYTE CountPulse(DWORD dwMeasureTimeUs, PWORD pwFreq)
{
// Decide counter1/Counter2 usage here
#ifdef USE_EXTCLK
if ( ( g_bySwFlag1 & SF1_EXTCLK) == EXTCLK_12MHz ) // 12MHz is enabled
{
// Don't use counter 2 when measuring IF in lock mode
if ( (GetOutputSelect() != CO_IF_OSC) ||
((GetSwRegValue(IR01_RADIO_CTRL2_REG) & IR1_RCTL2_IF_PM_L) == 0 ) )
return(CountPulseCnt2(pwFreq)); // Use counter 2 (with swapping) for other cases
}
#endif //USE_EXTCLK
return(CountPulseCnt1(dwMeasureTimeUs, pwFreq));
} // End CountPulse
/* ************************************************************************************************
*
* Function: CountPulseCnt1
*
* Authors: Hung van Le
* Purpose: Counting the pulse (Measure frequencies) of the currently
* selected chip's output. Software is responsible for measuring interval
* Input:
* DWORD dwMeasureTimeUs: time to measure in us
* PDWORD pwFreq: buffer to receive the measured frequency (unit depends on chip output)
* Output: Status as defined in LvErr.h
* Comments: Frequencies (depend on current output select) are shadowed when this function is invoked
* This function prepares the chip for counting pulse (reset counter...) and uses timer 0 interrupt
* to do the time critical part (pulse NR_W low for counting).
* Then the counter is disabled and can be read back.
* The interrupt returns the extra overhead time sothat the frequency can be
* calculated.
*
* ************************************************************************************************
* Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
* ************************************************************************************************ */
BYTE CountPulseCnt1(DWORD dwMeasureTimeUs, PWORD pwFreq)
{
WORD wStart, wStop;
WORD wPulseCnt;
BYTE byTmp;
// Return value 0 means no pulses counted (chip removed?)
*pwFreq = 0;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -