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

📄 lv2400x.c

📁 LV24000的单片机DEMO程序
💻 C
📖 第 1 页 / 共 5 页
字号:
/************************************************************************
*
*   Copyright(c) 2004 ItoM BV
*   All Rights Reserved.
*
*   LV2400x evaluation kit: LC24001 specific code
*   File name:	Lv2400x.c
*
*************************************************************************/

#include <stdio.h>
#include "common.h"
#include "Lv24Ekit.h"

// ==============================================================================
#ifdef USE_LV2400x 	// The whole file can be discarded if LV2400x is not used
// ==============================================================================
#include "Lv2400xReg.h"		// For register layout

/*-------------------------------------------------------------------
        Local data
-------------------------------------------------------------------*/
typedef struct	// Register address-value structure (for default register settings)
{
	WORD wRegAddress;
	BYTE byValue;
} I3W_REG_VALUES;

// ----- Default register value list of LV2400x
I3W_REG_VALUES _rom g_Lv2400xDefault[] = 
{
	IR01_MSRC_SEL_REG,	0,			// 0x0102 - Measure source select: nothing selected

	//IR01_FM_OSC_REG,	0,			// 0x0103 - should be tuned
	//IR01_SD_OSC_REG,	0x80,			// 0x0104 - should be tuned
	//IR01_IF_OSC_REG,	0,			// 0x0105 - should be tuned
	//IR01_FM_CAP_REG,	0,			// 0x0109 - should be tuned
	IR01_CNT_CTRL_REG,	IR1_CCTL_SWP_CNT_L,	// 0x0106 - Counter control: select counter 1, no counter swapping
	IR01_IRQ_MSK_REG,	IR1_IRQM_ACT_LOW,	// 0x0108 - Interrupt mask: IRQ active low

	IR01_RADIO_CTRL1_REG,	(IR1_RCTL1_EN_AFC|
				 IR1_RCTL1_NA_H_4|
				 IR1_RCTL1_NA_H_1|
				 IR1_RCTL1_NA_H_0),	// 0x202 - Radio control 1 - Enable AFC as default - keep reserved bit high
	//IR01_IFCEN_OSC_REG,	xx,			// 0x0203 - IF Center Frequency Oscillator: init when setting IF 
	//IR01_IF_BW_REG,	xx,			// 0x0205 - IF Bandwidth: init when setting IF

	IR01_RADIO_CTRL3_REG,	(IR1_RCTL3_SE_FM|
				IR1_RCTL3_AGC_SETLVL),// 0x0207	- Radio Control 3: mute audio, mute tone, select FM source, Set AGC level for FM (V4)

	IR01_STEREO_CTRL_REG,	IR1_DEF_CS_VAL|
				IR1_STCTL_AUTO_SLEWRATE|
				IR1V6_CANCEL_PILOT,	// 0x0208 - Stereo Control: Mono, SD PLL mute off, set default CS value, auto slew rate on
	IR01_AUDIO_CTRL1_REG,	0x77,			// 0x0209 - Audio Control 1: default volume level
	IR01_AUDIO_CTRL2_REG,	IR1_BEEP_HIGH,		// 0x020A - Audio Control 2: treble/bass setting, don't enable the beep output

	IR01_RADIO_CTRL2_REG,	IR1_RCTL2_IF_PM_L|	
		 		IR1_RCTL2_AGC_SPD,	// 0x0206 - Radio Control 2: VREF2/VREF on, IF PLL mute off, Turn on AGC speed for quick fieldstrength measuring
	IR01_PW_SCTRL_REG,	(IR1_PSCTL_PW_RAD|
				IR1_DEF_SOFT_ST|
				IR1_DEF_SOFT_MUTE),	// 0x020B - Power and soft control: turn on FM. Set default soft mute, soft stereo
};
#define LV2400X_DEFAULT_REG_LSIZE (sizeof(g_Lv2400xDefault)/sizeof(g_Lv2400xDefault[0]))

/*-------------------------------------------------------------------
        Register address list to be shadowed
	(Only save the necessary registers to reduce RAM usage)
-------------------------------------------------------------------*/
WORD _rom g_Lv24ShadowList[] = 
{
	IR01_MSRC_SEL_REG,	// 0x0102 Block 1- Reg02 (W): Measure source select
	IR01_FM_OSC_REG,	// (*) 0x0103 Block 1- Reg03 (W): DAC control for FM-RF oscillator
	IR01_SD_OSC_REG,	// (*) 0x0104 Block 1- Reg04 (W): DAC control for stereo decoder oscillator
	IR01_IF_OSC_REG,	// (*) 0x0105 Block 1- Reg05 (W): DAC control for IF oscillator
	IR01_CNT_CTRL_REG,	// 0x0106 Block 1- Reg06 (W): Counter control
	IR01_IRQ_MSK_REG,	// 0x0108 Block 1- Reg08 (W): Interrupt mask
	IR01_FM_CAP_REG,	// 0x0109 Block 1- Reg09 (W): CAP bank control for RF-frequency

	IR01_RADIO_CTRL1_REG,	// 0x0202 Block 2- Reg02 (W): Radio control 1
	IR01_IFCEN_OSC_REG,	// (*) 0x0203 Block 2- Reg03 (W): IF Center Frequency Oscillator
	IR01_IF_BW_REG,		// (*) 0x0205 Block 1- Reg05 (W): IF Bandwidth
	IR01_RADIO_CTRL2_REG,	// 0x0206 Block 2- Reg06 (W): Radio Control 2
	IR01_RADIO_CTRL3_REG,	// 0x0207 Block 2- Reg07 (W): Radio Control 3
	IR01_STEREO_CTRL_REG,	// 0x0208 Block 2- Reg08 (W): Stereo Control	
	IR01_AUDIO_CTRL1_REG,	// 0x0209 Block 2- Reg09 (W): Audio Control 1
	IR01_AUDIO_CTRL2_REG,	// 0x020A Block 2- Reg0A (W): Audio Control 2
	IR01_PW_SCTRL_REG,	// 0x020B Block 2- Reg0B (W): Power and soft control
				// (*): not required if stand-alone mode only. 
				//      These registers are shadowed for retoring them when switching from USB to stand alone mode
};
#define LVSHADOW_LSIZE (sizeof(g_Lv24ShadowList)/sizeof(g_Lv24ShadowList[0]))

// Global for this module
BYTE g_byaShwRegValue[LVSHADOW_LSIZE];	// array to hold the shadowed value

/*-------------------------------------------------------------------
	Treble/Bass converting table
-------------------------------------------------------------------*/
BYTE _rom g_Lv24001Treble[]=
{
	IR1_ACTL2_TREB_N,	// Logical level 0
	0,			// Logical level 1
	IR1_ACTL2_TREB_P,	// Logical level 2
};
#define IMR1_TREBLE_LSIZE (sizeof(g_Lv24001Treble)/sizeof(g_Lv24001Treble[0]) )

BYTE _rom g_Lv24001Bass[]=
{
	//IR1_ACTL2_BASS_N|IR1_ACTL2_BASS_LVL,	// Logical level 0: invalid combination!
	IR1_ACTL2_BASS_N,			// 0	// Logical level 0
	0,					// 1	// Logical level 1
	IR1_ACTL2_BASS_P,			// 2	// Logical level 2
	IR1_ACTL2_BASS_P|IR1_ACTL2_BASS_LVL,	// 3	// Logical level 3
};
#define IMR1_BASS_LSIZE (sizeof(g_Lv24001Bass)/sizeof(g_Lv24001Bass[0]) )

/*-------------------------------------------------------------------
        LV24001 feature limit
-------------------------------------------------------------------*/
typedef struct
{
	BYTE byFeatureId;
	BYTE byUpperLimit;
} LV_FEAT_LIMIT;

LV_FEAT_LIMIT _rom g_Lv2400xFeatLimit[] = 
{
	IHCAP_TUNERPWR,		1,	// Tuner's power: 0=off, 1= On
	IHCAP_VOLUME,		20, 	// Volume level
	IHCAP_AMUTE,		1,	// Audio mute: 0=audio, 1= muted
	IHCAP_ATREBLE,		(IMR1_TREBLE_LSIZE-1),	// Audio treble
	IHCAP_ABASS,		(IMR1_BASS_LSIZE-1),	// Audio bass
	IHCAP_DYNBASSBOOST,	15, 	// Dynamic bass boost
	IHCAP_SMUTE,		7, 	// Audio soft mute

	IHCAP_STEREO,		1, 	// Stereo: 0=mono, 1=stereo
	IHCAP_SOFT_ST,		7, 	// Soft stereo

	IHCAP_RADIOSOURCE,	1, 	// Radio source: 0=Radio off, 1=FM
	IHCAP_EXTSOURCE,	1, 	// External source: 0=off, 1=on
	IHCAP_BEEPSOURCE,	3, 	// Beep tone: 0=off, 1=Freq1, 2=Freq2, 3=Freq3
	//IHCAP_AFC	       	1,	// Bit 14: AFC (automatic frequency control) supported
	IHCAP_HPA,		1,	// Bit 15: Hardware headphone amplifier presents

	// Software features
	IHCAP_SCANLVL,		7,	// Scan level (0...7)
	IHCAP_SCANWRP,		2,	// 0=no wrap, 1=wrap once, 2=wrap continue
	IHCAP_REGION,		4,	// Region: 0=None, 1=Europe, 2=Japan, 3=USA, 4=JapanWide
	IHCAP_BEEPVOL,		20,	// Beep volume - same limit as IHCAP_VOLUME
#ifdef USE_EXTCLK
	IHCAP_EXTCLK,		1,	// 0= no external clock, 1= 12MHz, 2=32kHz
#endif //USE_EXTCLK
};
#define LV2400X_FEATLIMIT_LSIZE (sizeof(g_Lv2400xFeatLimit)/sizeof(g_Lv2400xFeatLimit[0]))

/*-------------------------------------------------------------------
        LV24001 routines
-------------------------------------------------------------------*/
BYTE InitLv2400xChip(void) 
{
	BYTE byResult;
	BYTE i;

	// Init software
	g_byBlock = 0xFF;		// Mark no block is selected yet
	g_byHwFlag1 = HF1_NEG_IF_PHASE;	// LV2400x has negative IF phase
	g_byRegion = REGION_EUROPE;	// Default region
	g_byStnFlag = STNWRAP_ONCE;	// Default options
	g_byScanLevel = 4;		// Default scan level
	g_byBeepVol = 10;		// Default beep volume
	g_byDynBassBoost = 15;		// Default: dynamic bass boost level is max.

	// 1) Write the default values to the device
	for (i=0; i<LV2400X_DEFAULT_REG_LSIZE; i++)
		WriteReg(g_Lv2400xDefault[i].wRegAddress, g_Lv2400xDefault[i].byValue);

	// 2) Set the prefered IF frequency
	byResult = Set_IF_Freq(DEFAULT_IF_FREQ);

	// 3) Init tuning system
	if (byResult == LVLS_NO_ERROR)
		byResult = InitTuningRfCapOsc(); 

	// 4) Set region to initialise FM band limits
	if (byResult == LVLS_NO_ERROR)
		byResult = SetRegion(g_byRegion);

	// 5) Set the prefered Stereo Decode clock
	Set_SD_Freq(DEFAULT_SD_FREQ);	//  This step can be postboned until stereo is enabled

	// Additional step: read the chip ID to determine chip specific features
	switch (ReadReg(IR01_CHIP_ID_REG))
	{
	case LV24102_ID:	// AM and headphone supported
		g_byHwFlag1 |= HF1_AM;
		// Fall through
	case LV24002_ID:	// Headphone supported
		g_byHwFlag1 |= HF1_HP;
		break;

	case LV24101_ID:	// AM supported
		g_byHwFlag1 |= HF1_AM;
		break;
	//case LV24001_ID:
	default:
		break;
	}

	// The chip is now ready - remember that it's still muted
	return(byResult);
}// End InitLv2400xChip

void DeInitLv2400xChip(void)
{
	// Disable interrupt
	DisableLv2400xIrq();

	// Mute the audio
	SetChipAudioMute(TRUE, MUTESRC_APPLICATION);

	// Turn off the chip power
	//DriveBit(IR01_PW_SCTRL_REG, IR1_PSCTL_PW_RAD, FALSE); // Skip to avoid noise on speaker
} // End DeInitLv2400xChip

/* ************************************************************************************************
 *
 *  Function:   Set_IF_Freq
 *  Authors:    Hung van Le
 *  Purpose:    Set the IF frequency to specified dwInputIF
 *  Input:		
 *			DWORD dwInputIF: the IF frequency to be set in Hz
 *  Output:     Status as defined in LvErr.h
 *  Comments:	None
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
BYTE Set_IF_Freq(WORD wInputIF)
{
	BYTE byResult;
	BYTE byOrgDemState;
	WORD wCfg;

	// turn on demodulator PLL mute to set the IF
	byOrgDemState = DriveBitNeg(IR01_RADIO_CTRL2_REG, IR1_RCTL2_IF_PM_L, TRUE);

	// Select correct oscillator output and enable measuring mode
	wCfg = SetUpChipMode(CO_IF_OSC|CHIP_MEASURE_MODE);

	// Do the tuning 
	byResult = LinTuneDac(wInputIF, LV_MSR_TIME_32ms, WriteIfOsc, 50, 150, 1);

	// Tuning done - restore status
	DriveBitNeg(IR01_RADIO_CTRL2_REG, IR1_RCTL2_IF_PM_L, byOrgDemState);

	// Restore chip config
	SetUpChipMode(wCfg);

	return(byResult);
} // End Set_IF_Freq

/* ************************************************************************************************
 *
 *  Function:   Set_SD_Freq
 *  Authors:    Hung van Le
 *  Purpose:    Set the stereo decoder clock frequency to specified dwInputSC
 *  Input:		
 *		DWORD dwInputSC: the stereo decoder clock frequency to be set in Hz
 *  Output:     Status as defined in LvErr.h
 *  Comments:	the set SC will be shadowed in m_dwStereoClock
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
BYTE Set_SD_Freq(WORD wInputSC)
{
	BYTE byResult;
	BOOL bOrgPllState;
	WORD wCfg;
	WORD wCurFreq;

	// turn on the stereo PLL mute measure the stereo decoder clock
	bOrgPllState = DriveBit(IR01_STEREO_CTRL_REG, IR1_STCTL_SD_PM, TRUE);

	// Select correct oscillator output and enable measuring mode
	wCfg = SetUpChipMode(CO_SD_OSC|CHIP_MEASURE_MODE);
		
	// Get current stereo clock
	byResult = CountPulse(LV_MSR_TIME_100ms, &wCurFreq);

	// Skip tuning if the frequency is already good
	if (byResult == LVLS_NO_ERROR)
	{
		if ( IsFrequencyOk(wCurFreq, DEFAULT_SD_FREQ, LV_MSR_TIME_100ms) != 0 )
			byResult = LVLS_NO_ERROR+1;
	}

	// Do the tuning - Some device has dead point below StereoOsc<20, so interpolate between 50-150
	if (byResult != LVLS_NO_ERROR)
		byResult = LinTuneDac(wInputSC, LV_MSR_TIME_100ms, WriteSdOsc, 50, 150, 1);

	// Tuning done - restore status
	DriveBit(IR01_STEREO_CTRL_REG, IR1_STCTL_SD_PM, bOrgPllState);
	SetUpChipMode(wCfg);

	return(byResult);
} // End Set_SD_Freq

/* ************************************************************************************************
 *
 *  Function:   GetOutputSelect
 *
 *  Authors:    Hung van Le
 *  Purpose:    Select an output of IMR01 chip
 *  Input:      Nothing
 *  Output:     The output select
 *  Comments:   The output select is virtualized.
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
BYTE GetOutputSelect(void)
{ 
	BYTE byCurOutputSel;

	// Get current measuring mask
	byCurOutputSel = GetSwRegValue(IR01_MSRC_SEL_REG) & IR1_MSRCS_MSS_MASK;
	if (byCurOutputSel == IR1_MSRCS_MSS_FM)
		return(CO_RF_OSC);	// RF frequency
	else if (byCurOutputSel == IR1_MSRCS_MSS_IF)
		return(CO_IF_OSC);	// IF frequency
	else if (byCurOutputSel == IR1_MSRCS_MSS_SD)
		return(CO_SD_OSC);	// SD frequency
	else // other settings
		return(CO_NONE);
} // End GetOutputSelect

/* ************************************************************************************************
 *
 *  Function:   SetOutputSelect
 *
 *  Authors:    Hung van Le
 *  Purpose:    Select an output of IMR01 chip
 *  Input:      
 *		WORD wOutputCfg: desired output (See SetUpChipMode in Lv24Ekit.h for possible outputs)
 *  Output:     The original output select
 *  Comments:   The output select is virtualized.
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
WORD SetOutputSelect(WORD wOutputCfg)
{
	WORD wCurOutputCfg;

	// Determine current chip output
	wCurOutputCfg = GetOutputSelect();

	// Do nothing if no change
	if (wCurOutputCfg == wOutputCfg)
		return(wCurOutputCfg);		

	// Output select change - update chip
	switch (wOutputCfg)
	{
	case CO_NONE:	// Disable all measurements
		SetRegBits(IR01_MSRC_SEL_REG, IR1_MSRCS_MSS_MASK, 0);
		break;

	case CO_RF_OSC:	// RF frequency
		SetRegBits(IR01_MSRC_SEL_REG, IR1_MSRCS_MSS_MASK, IR1_MSRCS_MSS_FM);
		break;

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -