⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 lv2400x.c

📁 LV24000的单片机DEMO程序
💻 C
📖 第 1 页 / 共 5 页
字号:
	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 + -