📄 predet.c
字号:
// When the sum of phase differences is sufficiently large we can say that
// we've found the sync frame since it is coded 180 degrees different from
// the preamble frames.
//
// Revision History:
//==========================================================================================
i16 AlignPhaseCompare(i16 carLen, iCplx *prev, iCplx *curr )
{
int n;
i16 prevdif, prevsum;
i16 bit1, bit0;
i16 dPhase;
i16 phaseError = 0;
i32 acc;
static i16 phasemap[] = {2, -1, 1, 0 };
#if DEBUGIT == DEBUG_PHASE
char prtStr[255];
char numStr[50];
strcpy(prtStr,"phase diff:");
#endif
for( n = 0 ; n < carLen ; n++ )
{
#if DEBUGIT == DEBUG_PHASE
sprintf(numStr, "%5d%5d%5d%5d ", prev->re, prev->im, curr->re, curr->im );
strcat(prtStr, numStr);
#endif
prevdif = prev->re - prev->im;
prevsum = prev->re + prev->im;
acc = (i32)(prevdif) * (i32)(curr->re);
acc += (i32)(prevsum) * (i32)(curr->im);
bit1 = acc > 0;
acc = (i32)(prevsum) * (i32)(curr->re);
acc -= (i32)(prevdif) * (i32)(curr->im);
bit0 = acc > 0;
dPhase = phasemap[ (bit1<<1) + bit0 ]; // decoded phase
phaseError += abs(dPhase); // sum of differences
prev++; // point to next carriers
curr++;
#if DEBUGIT == DEBUG_PHASE
sprintf(numStr, "%3d ", dPhase);
strcat(prtStr, numStr);
#endif
}
#if DEBUGIT == DEBUG_PHASE
strcat(prtStr, "\n");
mexPrintf("%s",prtStr);
#endif
return phaseError;
}
//==========================================================================================
// Function: getFrameStartFromImpulse()
//
// Description: Calculate the impulse response from the averaged frequency values.
// The maximum point in the impulse response corresponds to the beginning
// of the frame.
//
// impulse = received/transmitted = Y/X = [y0 y1...yN] ./ [x0 x1...xN]
// = [y0*conj(x0)...yN*conj(xN)] ./ [x0*conj(x0)...xN*conj(xN)]
// = C*[y0*conj(x0)...yN*conj(xN)]
//
// Uses symbolArray (data passed in) and phaseEqArray as the impulse array
//
// Revision History:
//==========================================================================================
i16 getFrameStartFromImpulse( iCplx *aveCarrier)
{
i16 n; // loop counter, return code
i16 sample; // sample number in frame
u16 impulseSample; // these three variables are used to
u16 maxValue; // find the max in the impulse response
i16 maxSample; // true frame start that is returned
iCplx *fftBuf; // pointer to fft array
iCplx *aveCar; // pointer current and average complex data
iCplx *preamble; // pointer to preamble pattern
iCplx *impulse; // working pointer to complex data
//---- init pointers ---------------------
aveCar = aveCarrier;
fftBuf = fftArray;
preamble = (iCplx *)distanceArray; // get complex phase from txPhase data
impulse = phaseEqArray;
getPrePhases( preamble, PreambleArray );
//---- calc the impulse response and put it in the ifft bins -------
for( n = 0; n < CARRIER_LEN; n++ )
{
impulse->re = (aveCar->re * preamble->re)
+ (aveCar->im * preamble->im);
(impulse++)->im = (aveCar->im * preamble->re)
- (aveCar->re * preamble->im);
aveCar++;
preamble++;
}
//---- Fill the carriers for an IFFT, then invert. Result is a time signal that
//---- looks like a correlation, with a big spike where the frame offset is best.
// Note: When doing IFFT operations, there is scaling on both the fillCarrier() function
// and the cifft() function. Here we will scale up by +2 in fillCarrier(), then down
// by -8 in cifft(). This gives us the least quantization on the input terms without
// rolling over the cifft output.
// ( Shift of +2 works well. +3 seems to work but values are close to rolling over.)
// Contrast this with the transmit function. There the phase terms only have four
// unique, known values, so there we shift down before doing cifft().
fillCarriers( fftArray, phaseEqArray, +2 ); // Fill the carriers in freq domain
DebugDelay(); // Flush C54x if in debug mode.
//diagData(fftArray, FFT_LEN, "impulseF", diagICPLX);
#if COMPILE_MODE == MEX_COMPILE
cifft( (DATA *)(fftArray), FFT_LEN, 0 ); // Invert to get a time-domain "correlation"
#else
cifft( (DATA *)(fftArray), FFT_LEN, 1 ); // Invert to get a time-domain "correlation"
#endif
DebugDelay(); // Flush C54x if in debug mode.
#if DEBUGIT == DEBUG_FRAME
diagData(aveCarrier, CARRIER_LEN, "avecar", diagICPLX);
diagData((iCplx *)distanceArray, CARRIER_LEN, "impulseP", diagICPLX); // preamble
diagData(phaseEqArray, CARRIER_LEN, "impulseF", diagICPLX);
diagData(fftBuf, FFT_LEN, "impulseT", diagICPLX);
#endif
//---- Find biggest sample. Its index indicates offset from beginning of frame --------
fftBuf = fftArray; // point to the real samples
maxValue = 0;
for( sample = 0 ; sample < FFT_LEN ; sample++ )
{
impulseSample = abs(fftBuf->re);
fftBuf++;
if( impulseSample > maxValue ) // find the max sample
{
maxSample = sample;
maxValue = impulseSample;
}
}
#if SAVETRACE == TRUE
SaveTraceData(0xDDDD); //!!!DEBUG Put a marker in the trace buffer
SaveTraceData((u16)maxSample); //!!!DEBUG Put a marker in the trace buffer
SaveTraceData((u16)maxValue); //!!!DEBUG Put a marker in the trace buffer
#endif
return maxSample;
}
#if FEQ_NORM_TYPE == FEQ_NORM_DIV // Use division to calculate freq equalization
//==========================================================================================
// Function: getFreqEq()
//
// Description: Frequency equalization calculation
// EQ = tx/rx = preamble / receive = Preamble / (aveCarrier/N) = N*P/A
//
// complex math:
// EQ = N/(ar*ar + ai*ai) * ((ar*pr + ai*pi) + j*(ar*pi - ai*pr))
// where N is the number of FFT averages
//
// Revision History:
//==========================================================================================
#define FEQ_SHIFT_DIV 9
//#define FEQ_SHIFT_DIV 7
i16 getFreqEq( iCplx *freqEq, iCplx *aveCarrier, i16 numFramesAve )
{
u16 n; // loop counter, return code
iCplx *preamble;
i32 carrierPwr;
static i32 feqNum;
i32 minPwr = 0x7FFFFFFF; // init to a big number
//---- allocate a diagnostic array to pass to Matlab ----------
#if DEBUGIT == DEBUG_GETFEQ
diagArray = mxCreateDoubleMatrix(5, CARRIER_LEN, mxCOMPLEX);
mxSetName(diagArray, "feq_diag");
diag.r = mxGetPr(diagArray);
diag.i = mxGetPi(diagArray);
#endif
//-----------------------------------------------------------------
// Calc the complex freq equalization value that is
// multiplied with each carrier in the data frames.
// Use distance array as a container for cmplex preamble symbols.
//-----------------------------------------------------------------
preamble = (iCplx *)distanceArray; // get complex phase from txPhase data
getPrePhases( preamble, PreambleArray );
for( n = 0; n < CARRIER_LEN; n++ )
{
//------------------------------------------------
// (1.15 * 1.15) >> 12 = 2.30 >> 12 = 14.18 ==> -2.18
// so carrierPwr is 15-PWR_SHIFT bigger than a 1.15 number
//-------------------------------------------------
carrierPwr = iSquare(aveCarrier->re, PWR_SHIFT)
+ iSquare(aveCarrier->im, PWR_SHIFT)
+ 1; // make it at least 1
if( carrierPwr < 0 )
{
PostErrorCode(0xBAE2, "getFreqEq", "preDet.c", "Overflowed carrier power");
}
if( carrierPwr < minPwr )
minPwr = carrierPwr;
if( carrierPwr < WORST_PWR_LIMIT )
{
DebugDelay();
DebugDelay();
}
#if DEBUGIT == DEBUG_GETFEQ
*diag.r++ = (double)preamble->re;
*diag.i++ = (double)preamble->im;
*diag.r++ = (double)aveCarrier->re;
*diag.i++ = (double)aveCarrier->im;
*diag.r++ = (double)carrierPwr;
*diag.i++ = (double)numFramesAve;
#endif
//---------------------------------------------------------
// now multiply FEQ by numFramesAve/carrierPwr.
//---------------------------------------------------------
DebugDelay();
feqNum = ((i32)(aveCarrier->re * preamble->re)) << FEQ_SHIFT_DIV;
DebugDelay();
feqNum += ((i32)(aveCarrier->im * preamble->im)) << FEQ_SHIFT_DIV;
DebugDelay();
freqEq->re = (i16)(numFramesAve * feqNum / carrierPwr);
#if DEBUGIT == DEBUG_GETFEQ
*diag.r++ = (double)freqEq->re;
*diag.r++ = (double)feqNum;
#endif
DebugDelay();
feqNum = ((i32)(aveCarrier->re * preamble->im)) << FEQ_SHIFT_DIV;
DebugDelay();
feqNum -= ((i32)(aveCarrier->im * preamble->re)) << FEQ_SHIFT_DIV;
DebugDelay();
freqEq->im = (i16)(numFramesAve * feqNum / carrierPwr);
#if DEBUGIT == DEBUG_GETFEQ
*diag.i++ = (double)freqEq->im;
*diag.i++ = (double)feqNum;
#endif
aveCarrier++;
freqEq++;
preamble++;
}
#if DEBUGIT == DEBUG_GETFEQ
mexPutArray(diagArray, "caller");
#endif
return (i16)minPwr;
}
#endif
#if FEQ_NORM_TYPE == FEQ_NORM_BIN // Use power-of-2 shifting to approximate freq equalization
//==========================================================================================
// Function: getFreqEq()
//
// Description: Frequency equalization calculation
// EQ = tx/rx = preamble / receive = Preamble / (aveCarrier/N) = N*P/A
//
// complex math:
// EQ = N/(ar*ar + ai*ai) * ((ar*pr + ai*pi) + j*(ar*pi - ai*pr))
// where N is the number of FFT averages
//
// Revision History:
//==========================================================================================
i16 getFreqEq( iCplx *freqEq, iCplx *aveCarrier, i16 numFramesAve )
{
u16 n; // loop counter, return code
iCplx *preamble;
i32 carrierPwr;
i16 minPwr = 0x7FFF; // init to a big number
i16 pwrScaleFactor;
i16 k, shift;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -