📄 agc.c
字号:
//==========================================================================================
// 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 + -