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

📄 agc.c

📁 DSP 5409 plc应用程序,调试通过,是用在电力线通讯上的演示程序.
💻 C
📖 第 1 页 / 共 2 页
字号:
//==========================================================================================
// Filename:		ofdm_agc.c
//
// Description:		Functions related to the AGC action and preamble detection in 
//					an OFDM power line modem.
//
// Copyright (C) 2001 - 2003 Texas Instruments Incorporated
// Texas Instruments Proprietary Information
// Use subject to terms and conditions of TI Software License Agreement
//
// Revision History:
//==========================================================================================

#include "ofdm_modem.h"


//====================================================================
//	Global var for this module
//=====================================================================
#if COMPILE_MODE == MEX_COMPILE
	u16	  		fakeInteruptCount;		// used to generate a sample_interupt

	u16			pgaGainReg;
#endif


#if COMPILE_MODE == MEX_COMPILE
//==========================================================================================
// Function:		fakeCodecAndDMA()
//
// Description: 	Model getting an ADC sample into the recSignal Buffer.
//
// Revision History:
//==========================================================================================
i16 fakeCodecAndDMA( double **agcrec, double **rec, i16 pgaGainReg )
{
	i32				adcSample;
	i16				overflow = 0;

	//---- amplify current sample ---------------------------
	//		ctrl	gain_dB	gain
	//		 0		 0		 1.0
	//		 1		 3		 1.4
	//		...		...		...
	//		10		30		31.6
	
	//---- get data from Matlab, apply PGA gain to data -------
	#if !defined(DEBUG_ARBWAVE)
		adcSample = (i32)((**rec) * AFE_RXPGA[pgaGainReg]);		// 32bit value
		(*rec)++;
	
		if( adcSample >= ADC_CLIP_LEVEL )	// model clipping in channel ADC
		{
			adcSample = ADC_CLIP_LEVEL-1;
			overflow = 1;
		}
		if( adcSample < -ADC_CLIP_LEVEL )
		{
			adcSample = -ADC_CLIP_LEVEL;
			overflow = 1;
		}

	#else
		adcSample = **rec;					// <=== DEBUG accept data from bench 
		(*rec)++;
	#endif

	if( rxDMApointer == NULL )
		rxDMApointer = recSignalArray;

	*rxDMApointer++ = (i16)adcSample;		// put it in the rx buffer
	
	if( rxDMApointer >= recSignalArray + RX_CIRC_BUFFER_LEN )
		rxDMApointer = recSignalArray;

	if( *agcrec != NULL )
	{
		**agcrec = (double)adcSample;		// put data in Matlab output array 
		(*agcrec)++;
	}

	fakeInteruptCount++;					// used to generate a sample_interupt

	return overflow;
}
#endif


//==========================================================================================
// Function:		sample_interupt()
//
// Description: 	Main sample interrupt routine
//					Called by the DMA engine about every 16 samples.
//					Calculates the AGC control register value and checks AGC related flags.
//
// Modifies:		SNRflag, recSignal, AFEctrl2.
//
// Revision History:
//==========================================================================================
void sample_interupt()
{
	i16					sample;							// compare this to recSignal
	i16*				dmaPtr;							// compare this to recSignal

	i16					adcSample;
	i16					pk;								// indicates thrs crossings
	static i16			agcGaindB = AGC_INIT_GAIN;		// gain ctrl state var
	i16					pgaGain;

	// Fast decay gain (signal is way too high)-------------|
	// Decay gains (signal too high, decr gain)--------|	|
	// Attach gains ( signal too low, incr gain)---|   |	|
	//											   v   v	v
	static const i16	AgcAttackGains[3] =      { 9, -65, -207 };	
//	static const i16	AgcAttackGains[3] =      { 9, -65, -157 };	

#define  AGC_THRS_LO		0x3000		// 37.5% of full-scale
#define  AGC_THRS_HI		0x5000		// 62.5% of full-scale


	if( agcState != AgcHold )
	{
		dmaPtr = ReadRxDMAPointer();					// Read current Rx DMA location.
		DebugDelay();									// Flush C54x if in debug mode.

		// If DMA pointer has wrapped around, ignore little piece at end of buffer.  
		if( recSignal > dmaPtr )						 
			recSignal = recSignalArray;					// Restart at beginning of buffer.

 		#if (AFE_RX_FORMAT == 24) 			
 			// Align the pointer so that we are looking at the real data, not the blank value between them
			if ( ((u16)recSignal & 1) != 0)			// Look for even numbers
			{
				DebugDelay();						// Flush C54x if in debug mode.
				PostErrorCode(0xBADD, "sample_interrupt", "agc.c", "Odd value for recSignal");
				TurnLEDsOn(LED_RX_BUFF_ERR);	// Turn on red LED2
				#if SAVETRACE == TRUE
					SaveTraceData(0xBADD);			//!!!DEBUG  Put a marker in the trace buffer
					SaveTraceData((u16)recSignal); 	//!!!DEBUG  Put a marker in the trace buffer
					SaveTraceData((u16)dmaPtr);		//!!!DEBUG  Put a marker in the trace buffer
				#endif
				DebugDelay();				// Flush C54x if in debug mode.
			}
			else
			{
				TurnLEDsOff(LED_RX_BUFF_ERR); 	//Turn off red LED2
			}

 			// Align the pointer so that we are looking at the real data, not the blank value between them
			if ( *(i16*)( ((u16)recSignal&0xFFFE) | 1) != 0 )
			{
				DebugDelay();				// Flush C54x if in debug mode.
				PostErrorCode(0xBADE, "sample_interrupt", "agc.c", "Odd/Even misalignment in recSignal buffer");
				#if SAVETRACE == TRUE
					SaveTraceData(0xBADE);			//!!!DEBUG  Put a marker in the trace buffer
					SaveTraceData((u16)recSignal); 	//!!!DEBUG  Put a marker in the trace buffer
					SaveTraceData((u16)dmaPtr);		//!!!DEBUG  Put a marker in the trace buffer
				#endif
				DebugDelay();				// Flush C54x if in debug mode.
			}
		#endif

		while( ((u32)recSignal>>1) < ((u32)dmaPtr>>1) )					// AGC update
		{
			adcSample = abs(*recSignal++);			// compare sample
			#if (AFE_RX_FORMAT == 24)
				recSignal++;						// Increment rec pointer to skip blank value
			#endif

			if( ( agcState == AgcIdle ) || (agcState == AgcPreamble) )
			{
				pk =  adcSample >= AGC_THRS_LO;			// compare sample to AGC thresholds
				pk += adcSample >= AGC_THRS_HI;
				agcGaindB += AgcAttackGains[pk];		// update gain
			}
		}			

		#if DEBUGIT == DEBUG_AGC
			*diag.r++ = (double)ReadRxDMAPointer() - recSignalArray;
			*diag.r++ = (double)agcGaindB;
		#endif

		//---- decimate and saturate gain value -------------
		pgaGain  = (agcGaindB + AGC_CTRL_HALF) >> AGC_CTRL_SHIFT;
		if( pgaGain > AGC_CTRL_MAX )
		{
			pgaGain = AGC_CTRL_MAX;
			agcGaindB = pgaGain << AGC_CTRL_SHIFT;
		}
		if( pgaGain < AGC_CTRL_MIN )
		{
			pgaGain = AGC_CTRL_MIN;
			agcGaindB = pgaGain << AGC_CTRL_SHIFT;
		}

		#if COMPILE_MODE == MEX_COMPILE		
			if( pgaGain != pgaGainReg )
			{
				pgaGainReg = pgaGain;
				//mexPrintf("PGA gain set to %d\n",pgaGain);
			}
		#else
			// Calculate new value for AFE control variable
			AFEctrl2 = (AFEctrl2 & (~((0x07)<<3))) | (pgaGain<<3);	// Stuff Rx Gain into hardware control variable
		#endif


		#if DEBUGIT == DEBUG_AGC
			*diag.r++ = (double)pgaGainReg;
		#endif

		if (SNRflag >= 0)	// If SNRflag < 0, then we should not look for packet.
		{
			//---- count to see if time to do SNR calc -----------
			sample = (recSignal - recSignalArray) - prevSnrSample;
			if( sample < 0 )
			{
				sample += (i16)RX_CIRC_BUFFER_LEN;
			}
			
			#if COMPILE_MODE == DSP_COMPILE		
				DebugDelay();				// Flush C54x if in debug mode.
				if(sample >= (SNR_FFT_INTERVAL*RX_SRC_INC*6))	
				{
					// Something's wrong here
					DebugDelay();				// Flush C54x if in debug mode.
					PostErrorCode(0xBADB, "sample_interrupt", "agc.c", "Long delay between SNR Flags");
					#if SAVETRACE == TRUE
						dmaPtr = ReadRxDMAPointer();	// Read current Rx DMA location.
						SaveTraceData(0xBADB);			// trace marker
						SaveTraceData((u16)recSignal); 	// our pointer 
						SaveTraceData((u16)dmaPtr);		// dma pointer

						SaveTraceData(prevSnrSample);	// prevSnrSample is global i16 var
						SaveTraceData(sample); 			// time from last packet det
						SaveTraceData(SNRflag);			// packet detect flag
					#endif
					
					DebugDelay();				// Flush C54x if in debug mode.
					DebugDelay();				// Flush C54x if in debug mode.
				}
			#endif
			
			if( sample >= (SNR_FFT_INTERVAL*RX_SRC_INC) )
			{
				prevSnrSample  = (recSignal - recSignalArray);
				SNRflag = 1;
			}
		}
	}	// done with AGC

	return;
}	


#if COMPILE_MODE == DSP_COMPILE
//==========================================================================================
// Function:		lookForPacket()
//
// Description: 	Look for the start of a packet by comparing power in bins near the top
//					of the transmission band to bins just beyond the transmission band.
//
// Modifies:		SNRflag, agcState
//
// Revision History:
//==========================================================================================
i16* lookForPacket(void)
{
	u16				phError = 0;
	
	TurnLEDsOn(LED_RX_SEARCH);			// Turn on green LED

	backFFT( fftArray, recSignal );		// grab the last FFT_LEN samples and get freq resp

	phError = ddphase(PreambleArray, fftArray + CARRIER_LOW, CARRIER_LEN );

	if( phError  > DDPHASE_HI_LIM  )   	//	decide if this lookes like a packet
	{									//	if so, switch to preamble state
		preambleDetCount = 0;			//	start over
		agcState = AgcIdle;
	}
	else
	{
		if( phError <  DDPHASE_LO_LIM )
		{
			preambleDetCount++;		  	//	and count # of good preamble snrs seen
			agcState = AgcPreamble;
		}
	}

	if( preambleDetCount >= SNR_PRE_DET_COUNT )
	{
		agcState = AgcHold;				// We have seen enough good preamble, so switch modes.
		// The last frame must have been good, so back pointer up one frame and 
		// include it in the equalization data
		// recSignal = WrapRecPtr(recSignal, -FFT_LEN*RX_SRC_INC);
	}

	#if SAVETRACE == TRUE
		//if( ((AFEctrl2>>3) & 7) < 7)	// Save when AGC is not maxed out
		if( preambleDetCount > 0 )		// Save when we think we see a packet
		{								// store 0x8000 + pgaGain + agcState  + preambDetCount			
			SaveTraceData(0x8000 + (((AFEctrl2>>3) & 7)<<8)  + ((u16)agcState<<4) + preambleDetCount);	 
			SaveTraceData((u16)recSignal);
			SaveTraceData(phError);
		}
	#endif

	TurnLEDsOff(LED_RX_SEARCH);	// Turn off green LED

⌨️ 快捷键说明

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