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

📄 lv2410x.c

📁 LV24000的单片机DEMO程序
💻 C
📖 第 1 页 / 共 5 页
字号:
 *		  muted through a chip function like BOOL MuteStereoDecoderPll(BOOL bState) instead of driving the bit 
 *		  directly.
 *		- Function SetHwFeatureValue(IHCAP_BEEPSOURCE, byValue) can also be used to avoid accessing the LV2400x 
 *		  directly. byValue for LV2400x is: 0=beep off, 1=beep 500 Hz, 2=beep 1kHz, 3=beep 2kHz
 *		- Make sure that the LV2400x is in idle state before invoking this function.
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
void AudioFeedback(BYTE byType)
{
// Local equations
#define _AFB_DEMPLL	((BYTE)0x01)
#define _AFB_SDPLL	((BYTE)0x02)
#define _AFB_AUD_MUTE	((BYTE)0x04)
	BYTE byOrgFlag, byCurVolume, byOrgBeep, byOrgBand;

	// Do nothing if beep is not desired
	if (g_byBeepVol==0)
		return;

	// Init local.
	byOrgFlag = 0;

	// Turn off radio band, enable beep source
	byOrgBand = SetRegBits(IR01_RADIO_CTRL3_REG, (IR1_RCTL3_SE_FM|IR3_RCTL3_SE_AM|IR1_RCTL3_SE_BEEP), IR1_RCTL3_SE_BEEP);

	// Turn on the stereo decoder PLL mute for stable beep frequency
	if ( DriveBit(IR01_STEREO_CTRL_REG, IR1_STCTL_SD_PM, TRUE) )
		byOrgFlag |= _AFB_SDPLL;

	// Unmute audio if necessary
	if ( GetHwFeatureValue(IHCAP_AMUTE) )
	{
		SetHwFeatureValue(IHCAP_AMUTE, 0);	// Un-mute audio
		byOrgFlag |= _AFB_AUD_MUTE;
	}

	// Set volume if necessary
	byCurVolume = GetHwFeatureValue(IHCAP_VOLUME); // Determine current volume level
	if (byCurVolume<g_byBeepVol)
		SetHwFeatureValue(IHCAP_VOLUME, g_byBeepVol);

	// turn on demodulator PLL mute to mute the radio
//@@	if (DriveBitNeg(IR01_RADIO_CTRL2_REG, IR1_RCTL2_IF_PM_L, TRUE) )
//		byOrgFlag |= _AFB_DEMPLL;

	if (byType == AUDFB_TYPE1)
	{
		// Beep at 500 Hz
		byOrgBeep = SetRegBits(IR01_AUDIO_CTRL2_REG, IR1_ACTL2_BPFREQ, IR1_BEEP_500Hz);
		DelayUs(DLT_20ms);	
  		DelayUs(DLT_20ms);
	}
	else //if (byType == AUDFB_TYPE2)
	{
		// Beep at 2kHz
		byOrgBeep = SetRegBits(IR01_AUDIO_CTRL2_REG, IR1_ACTL2_BPFREQ, IR1_BEEP_2KHz);
		DelayUs(DLT_20ms);
  		DelayUs(DLT_20ms);
		// Pause
		SetRegBits(IR01_AUDIO_CTRL2_REG, IR1_ACTL2_BPFREQ, IR1_BEEP_OFF);
  		DelayUs(DLT_20ms);
  		DelayUs(DLT_20ms);
		// Beep at 2kHz
		SetRegBits(IR01_AUDIO_CTRL2_REG, IR1_ACTL2_BPFREQ, IR1_BEEP_2KHz);
  		DelayUs(DLT_20ms);
  		DelayUs(DLT_20ms);
	}

	// Restore everything
	if (byCurVolume != g_byBeepVol)		// Restore volume
		SetHwFeatureValue(IHCAP_VOLUME, byCurVolume);

//@@@	if ( (byOrgFlag &_AFB_DEMPLL)==0 )	// Restore demodulator PLL mute
// 		DriveBitNeg(IR01_RADIO_CTRL2_REG, IR1_RCTL2_IF_PM_L, FALSE);

	if ( byOrgFlag & _AFB_AUD_MUTE )	// Restore audio mute
		SetHwFeatureValue(IHCAP_AMUTE, 1);

	if ( (byOrgFlag & _AFB_SDPLL)==0 )	// Restore the stereo decoder PLL mute
		DriveBit(IR01_STEREO_CTRL_REG, IR1_STCTL_SD_PM, FALSE);

	// Restore beep frequency bits
	SetRegBits(IR01_AUDIO_CTRL2_REG, IR1_ACTL2_BPFREQ, byOrgBeep);

	// Restore radio band, beep source setting
	SetRegBits(IR01_RADIO_CTRL3_REG, (IR1_RCTL3_SE_FM|IR3_RCTL3_SE_AM|IR1_RCTL3_SE_BEEP), byOrgBand);

} // End AudioFeedback

//-----------------------------------------------------------------------------
// Helper functions for switch between USB and stand-alone mode
// Placed here because of the shadow list/value array
//-----------------------------------------------------------------------------
#ifdef USE_USB
void RestoreShadowReg()
{
	// Restore shadow register of LV2400x when switching from USB back to stand-alone
	BYTE i;

	g_byBlock = 0xFF; // Mark shadowed block select is dirty to force setting it the 1st time
	for (i=0; i<LVSHADOW_LSIZE; i++)
		WriteReg(g_Lv24ShadowList[i], g_byaShwRegValue[i]);
} // End RestoreShadowReg
#endif //USE_USB

//-----------------------------------------------------------------------------
// Registers shadowing function
//-----------------------------------------------------------------------------
void ShadowReg(WORD wRegAddress, BYTE byValue)
{
	BYTE i;

	for (i=0; i<LVSHADOW_LSIZE; i++)
	{ 
		if ( g_Lv24ShadowList[i] == wRegAddress )
		{
			g_byaShwRegValue[i] = byValue;
			break;
		}
	}
	g_byBlock = MSB(wRegAddress);	//  Save last access block
} // End ShadowReg

BYTE GetSwRegValue(WORD wRegAddress)
{
	BYTE i;

	for (i=0; i<LVSHADOW_LSIZE; i++)
	{ 
		if ( g_Lv24ShadowList[i] == wRegAddress )
			return(g_byaShwRegValue[i]);
	}
	return(0); // not found
} // End GetSwRegValue

void SelRegBlock(BYTE byBlock)
{
	// Skip selecting the block when it's already selected
	if (g_byBlock != byBlock)
	{
		g_byBlock = byBlock; // Save block number for next time
 		IoWrite3W(byBlock, BLK_SEL);	// Write the block number to BLK_SEL register
	}
} // End SelRegBlock

/* ************************************************************************************************
 *
 *  Function:   IsFrequencyOk
 *
 *  Authors:    Hung van Le
 *  Purpose:    Verify if wCurFreq is in range of wExpFreq +/- margin
 *  Input:
 *			wCurFreq: current frequency
 *			wExpFreq: the expected frequency
 *			dwPrecise: precise of the compare (max=1000000, 1000000 is exact comparing)
 *  Output:
 *			0 : wCurFreq within the margin
 *			-1: wCurFreq too low (i.e. wCurFreq < (wExpFreq - margin)
 *			+1: wCurFreq too high (i.e. wCurFreq > (wExpFreq + margin)
 *  Comments:   margin = (1000000 * DividerFactor) / dwPrecise
 *		Divider factor is dependant on current output select of the chip
 *
 * ************************************************************************************************
 * Copyright (c) 2004. Semiconductor Ideas to the Market (ItoM) B.V. All rights reserved.
 * ************************************************************************************************ */
int IsFrequencyOk(WORD wCurFreq, WORD wExpFreq, DWORD dwPrecise)
{
	WORD wMargin;
	DWORD dwFactor;

	if (dwPrecise != 1000000)
	{
		switch ( GetOutputSelect() )
		{
			case CO_RF_OSC:
				// wMargin = (1000000 * (DWORD)GetDividerFactor())/dwPrecise;
				// wMargin /= 10000;	// 10 KHz unit for RF
				dwFactor = 100 * IMR01_FM_DIVIDER;
				break;
			case CO_IF_OSC:
				// wMargin = (1000000 * (DWORD)GetDividerFactor())/dwPrecise;
				// wMargin /= 10;	// 10 Hz unit for IF
				dwFactor = 100000;
				break;
			//case CO_SD_OSC:
			default:
				// wMargin = (1000000 * (DWORD)GetDividerFactor())/dwPrecise;
				// wMargin /= 1;	// 1 Hz unit for other freq
				// 1 Hz unit for SD and other freq.
				dwFactor = 1000000;
				break;
		}
	}
	else
		dwFactor = 0;
	if (dwPrecise < dwFactor)
		wMargin = (WORD)(dwFactor / dwPrecise);
	else
		wMargin = 0;

	if ( wCurFreq < (wExpFreq - wMargin) )
		return(-1);
	else if ( wCurFreq > (wExpFreq + wMargin) )
		return(1);
	else
		return(0);
} // End IsFrequencyOk

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;

	// 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

⌨️ 快捷键说明

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