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

📄 lv2410x.c

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

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

/* ************************************************************************************************
 *
 *  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;
	BYTE byOrgAudioMute, byOrgAudioMode;
	WORD wCfg;
	WORD wCap, wOsc;

	// Check limit
	{
		WORD wRfBandLo, wRfBandHi;

		wRfBandHi = DisplayFreqToRf(g_wDisplayBandHigh);
		wRfBandLo = DisplayFreqToRf(g_wDisplayBandLow);
		byResult = CheckRfLimit(&wRfFreq, wRfBandLo, wRfBandHi, 2);
		if (byResult != LVLS_NO_ERROR)
			return(byResult);
	}

	// No valid station by a frequency set
	g_byStnFlag &= (~STN_VALID);

	// Save the new RF frequency
	g_wLastSetRF = wRfFreq;

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

	// Mute audio and force mono mode
	byOrgAudioMute = SetChipAudioMute(TRUE, MUTESRC_OPERATION);
	byOrgAudioMode = SetChipStereo(FALSE);

	// Quick frequency set
	CalculateRfCapOsc(wRfFreq, &wCap, &wOsc, QSSF_PRECISION_MED);
	//WriteRfCap(wCap); // Will be done in FineTuneRfOsc
	byResult = FineTuneRfOsc(wRfFreq, LV_MSR_TIME_32ms, wOsc, FALSE);
	
	// Do finetuning if frequency is set
	//if ( (dwResult == LVLS_NO_ERROR) && (dwOption & SETSTN_FINETUNE) )
	//	FineTuneFmToIF(&m_bValidStation);

	// Restore chip config
	SetUpChipMode(wCfg);

	// Restore status
	SetChipAudioMute(byOrgAudioMute, MUTESRC_OPERATION);
	SetChipStereo(byOrgAudioMode);

	return(byResult);
} // End SetRfFrequency

BYTE GetHwFeatureLimit(BYTE byFeatureId)
{
	// Return upper limit of a feature (lower limit is always 0)
	// Upper limit 0 means feature is not supported
	BYTE i;

	// Headphone amplifier: depends on hardware capapbility
	if (byFeatureId == IHCAP_HPA)
	{
		if ( (g_byHwFlag1 & HF1_HP)==0 )
			return(0);	// Not supported by hardware
	}

	// Headphone amplifier: depends on hardware capapbility
	if (byFeatureId == IHCAP_RADIOSOURCE)
	{
		if ( (g_byHwFlag1 & HF1_AM)==0 )
			return(1);	// Not supported by hardware - Only Off/FM
	}

	if (byFeatureId == IHCAP_REGION)
	{
		if ( (g_byStnFlag & STN_AM_MODE) == STN_AM_MODE )
			return(3); // Only 0=None, 1=Europe, 2=Japan, 3=USA for AM mode (no JapanWide)
	}

	for (i=0; i<LV2400X_FEATLIMIT_LSIZE; i++)
	{
		if ( g_Lv2400xFeatLimit[i].byFeatureId == byFeatureId)
			return(g_Lv2400xFeatLimit[i].byUpperLimit);
	}
	return(0); // Not support - no upper limit
} // End GetHwFeatureLimit

BYTE GetHwFeatureValue(BYTE byFeatureId)
{
	// Return current value of a feature
	BYTE byTmp, byValue;

	// Default returned value
	byValue=0;

	switch (byFeatureId)
	{
	case IHCAP_TUNERPWR:
		byTmp = GetSwRegValue(IR01_PW_SCTRL_REG);
		if ( byTmp & IR1_PSCTL_PW_RAD )	// FM power on bit = 1: power is on
			byValue = 1;
		break;

	case IHCAP_AMUTE:
		if ( g_bySwFlag1 & MUTESRC_APPLICATION )
			byValue = 1; // Muted
		break;

	case IHCAP_VOLUME:
		byValue = GetChipVolume();
		if ( (g_bySwFlag1 & MUTESRC_VOLUME)==0 )
			byValue++;	// Convert hardware level to logical level (add 1 when we are not muted)
		break;

	case IHCAP_STEREO:
		byTmp = GetSwRegValue(IR01_STEREO_CTRL_REG);
		if ( (byTmp & IR1_STCTL_STEREO_L) == 0)	// Stereo bit = 0: stereo is enabled
			byValue=1;
		break;

//	case IHCAP_DEEMP:
//		wTmp = GetSwRegValue(IR01_AUDIO_CTRL2_REG);
//		if ( wTmp & IR1_ACTL2_DEEMP75 )	// Deemphasis bit = 1: 75us
//			pValue->State.bState = DEEMP_75;
//		else
//			pValue->State.bState = DEEMP_50;
//		break;

	case IHCAP_SMUTE:		// Soft mute
		// Soft mute is in bit [4:2] of IR01_PW_SCTRL_REG
		byTmp = (BYTE)(GetSwRegValue(IR01_PW_SCTRL_REG) & IR1_PSCTL_SOFT_MUTE);
		byValue = byTmp>>2; // Shift to logical level
		break;

	case IHCAP_SOFT_ST:		// Soft stereo
		// Soft stereo is in bit [7:5] of IR01_PW_SCTRL_REG
		byTmp = (BYTE)(GetSwRegValue(IR01_PW_SCTRL_REG) & IR1_PSCTL_SOFT_ST);
		byValue = byTmp>>5; // Shift to logical level
		break;

//	case IHCAP_AFC:			// AFC (automatic frequency control)
//		byTmp = GetSwRegValue(IR01_RADIO_CTRL1_REG);
//		if (byTmp & IR1_RCTL1_EN_AFC)
//			byValue = 1;
//		break;

	case IHCAP_ATREBLE:		// Audio treble
		// Fetch current setting
		byTmp = (BYTE)(GetSwRegValue(IR01_AUDIO_CTRL2_REG) & IR1_ATREBLE_MASK);
		
		// Return the logical level
		byValue = SearchInByteArray(byTmp, g_Lv24001Treble, IMR1_TREBLE_LSIZE);
		break;

	case IHCAP_ABASS:		// Audio bass
		// Fetch current setting
		byTmp = (BYTE)(GetSwRegValue(IR01_AUDIO_CTRL2_REG) & IR1_ABASS_MASK);
		
		// Return the logical level
		byValue = SearchInByteArray(byTmp, g_Lv24001Bass, IMR1_BASS_LSIZE);
		break;

	case IHCAP_RADIOSOURCE:
		// Return: 0: off, 1: FM, 2: AM
		byTmp = GetSwRegValue(IR01_RADIO_CTRL3_REG);
		if (byTmp & IR1_RCTL3_SE_FM)
			byValue = 1;	// FM mode
		else if (byTmp & IR3_RCTL3_SE_AM)	// (LV2410X)
			byValue = 2; 	// AM mode
		break;
		
	case IHCAP_EXTSOURCE:
		// Input: on/off (true/false)
		byTmp = GetSwRegValue(IR01_RADIO_CTRL3_REG);
		if (byTmp & IR1_RCTL3_SE_EXT)

⌨️ 快捷键说明

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