📄 channelestimation.cpp
字号:
/******************************************************************************\ * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik * Copyright (c) 2001 * * Author(s): * Volker Fischer * * Description: * Channel estimation and equalization * ****************************************************************************** * * This program is free software; you can redistribute it and/or modify it under * the terms of the GNU General Public License as published by the Free Software * Foundation; either version 2 of the License, or (at your option) any later * version. * * This program is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS * FOR A PARTICULAR PURPOSE. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License along with * this program; if not, write to the Free Software Foundation, Inc., * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA *\******************************************************************************/#include "ChannelEstimation.h"/* Implementation *************************************************************/void CChannelEstimation::ProcessDataInternal(CParameter& ReceiverParam){ int i, j, k; int iModSymNum; _REAL rCurSNREst; _REAL rOffsPDSEst; /* Check if symbol ID index has changed by the synchronization unit. If it has changed, reinit this module */ if ((*pvecInputData).GetExData().bSymbolIDHasChanged == TRUE) {// FIXME: we loose one OFDM symbol by this call -> slower DRM signal acquisition SetInitFlag(); return; } /* Move data in history-buffer (from iLenHistBuff - 1 towards 0) */ for (j = 0; j < iLenHistBuff - 1; j++) { for (i = 0; i < iNumCarrier; i++) matcHistory[j][i] = matcHistory[j + 1][i]; } /* Write new symbol in memory */ for (i = 0; i < iNumCarrier; i++) matcHistory[iLenHistBuff - 1][i] = (*pvecInputData)[i]; /* Time interpolation *****************************************************/ /* Get symbol-counter for next symbol. Use the count from the frame synchronization (in OFDM.cpp). Call estimation routine */ const _REAL rSNRAftTiInt = pTimeInt->Estimate(pvecInputData, veccPilots, ReceiverParam.matiMapTab[(*pvecInputData). GetExData().iSymbolID], ReceiverParam.matcPilotCells[(*pvecInputData). GetExData().iSymbolID], /* The channel estimation is based on the pilots so it needs the SNR on the pilots. Do a correction */ rSNREstimate * rSNRTotToPilCorrFact); /* Debar initialization of channel estimation in time direction */ if (iInitCnt > 0) { iInitCnt--; /* Do not put out data in initialization phase */ iOutputBlockSize = 0; /* Do not continue */ return; } else iOutputBlockSize = iNumCarrier; /* Define DC carrier for robustness mode D because there is no pilot */ if (iDCPos != 0) veccPilots[iDCPos] = (CReal) 0.0; /* ------------------------------------------------------------------------- Use time-interpolated channel estimate for timing synchronization tracking */ TimeSyncTrack.Process(ReceiverParam, veccPilots, (*pvecInputData).GetExData().iCurTimeCorr, rLenPDSEst /* out */, rOffsPDSEst /* out */); /* Store current delay in history */ vecrDelayHist.AddEnd(rLenPDSEst); /* Frequency-interploation ************************************************/ switch (TypeIntFreq) { case FLINEAR: /**********************************************************************\ * Linear interpolation * \**********************************************************************/ /* Set first pilot position */ veccChanEst[0] = veccPilots[0]; for (j = 0, k = 1; j < iNumCarrier - iScatPilFreqInt; j += iScatPilFreqInt, k++) { /* Set values at second time pilot position in cluster */ veccChanEst[j + iScatPilFreqInt] = veccPilots[k]; /* Interpolation cluster */ for (i = 1; i < iScatPilFreqInt; i++) { /* E.g.: c(x) = (c_4 - c_0) / 4 * x + c_0 */ veccChanEst[j + i] = (veccChanEst[j + iScatPilFreqInt] - veccChanEst[j]) / (_REAL) (iScatPilFreqInt) * (_REAL) i + veccChanEst[j]; } } break; case FDFTFILTER: /**********************************************************************\ * DFT based algorithm * \**********************************************************************/ /* --------------------------------------------------------------------- Put all pilots at the beginning of the vector. The "real" length of the vector "pcFFTWInput" is longer than the No of pilots, but we calculate the FFT only over "iNumCarrier / iScatPilFreqInt + 1" values (this is the number of pilot positions) */ /* Weighting pilots with window */ veccPilots *= vecrDFTWindow; /* Transform in time-domain */ veccPilots = Ifft(veccPilots, FftPlanShort); /* Set values outside a defined bound to zero, zero padding (noise filtering). Copy second half of spectrum at the end of the new vector length and zero out samples between the two parts of the spectrum */ veccIntPil.Merge( /* First part of spectrum */ veccPilots(1, iStartZeroPadding), /* Zero padding in the middle, length: Total length minus length of the two parts at the beginning and end */ CComplexVector(Zeros(iLongLenFreq - 2 * iStartZeroPadding), Zeros(iLongLenFreq - 2 * iStartZeroPadding)), /* Set the second part of the actual spectrum at the end of the new vector */ veccPilots(iNumIntpFreqPil - iStartZeroPadding + 1, iNumIntpFreqPil)); /* Transform back in frequency-domain */ veccIntPil = Fft(veccIntPil, FftPlanLong); /* Remove weighting with DFT window by inverse multiplication */ veccChanEst = veccIntPil(1, iNumCarrier) * vecrDFTwindowInv; break; case FWIENER: /**********************************************************************\ * Wiener filter * \**********************************************************************/ /* Wiener filter update --------------------------------------------- */ /* Do not update filter in case of simulation */ if (ReceiverParam.eSimType == CParameter::ST_NONE) { /* Update Wiener filter each OFDM symbol. Use current estimates */ UpdateWienerFiltCoef(rSNRAftTiInt, rLenPDSEst / iNumCarrier, rOffsPDSEst / iNumCarrier); } /* Actual Wiener interpolation (FIR filtering) ---------------------- */ /* FIR filter of the pilots with filter taps. We need to filter the pilot positions as well to improve the SNR estimation (which follows this procedure) */ for (j = 0; j < iNumCarrier; j++) {// TODO: Do only calculate channel estimation for data cells, not for pilot// cells (exeption: if we want to use SNR estimation based on pilots, we also// need Wiener on these cells!) /* Convolution */ veccChanEst[j] = _COMPLEX((_REAL) 0.0, (_REAL) 0.0); for (i = 0; i < iLengthWiener; i++) { veccChanEst[j] += matcFiltFreq[j][i] * veccPilots[veciPilOffTab[j] + i]; } } break; } /* Equalize the output vector ------------------------------------------- */ /* Calculate squared magnitude of channel estimation */ vecrSqMagChanEst = SqMag(veccChanEst); /* Write to output vector. Take oldest symbol of history for output. Also, ship the channel state at a certain cell */ for (i = 0; i < iNumCarrier; i++) { (*pvecOutputData)[i].cSig = matcHistory[0][i] / veccChanEst[i];#ifdef USE_MAX_LOG_MAP /* In case of MAP we need the squared magnitude for the calculation of the metric */ (*pvecOutputData)[i].rChan = vecrSqMagChanEst[i];#else /* In case of hard-desicions, we need the magnitude of the channel for the calculation of the metric */ (*pvecOutputData)[i].rChan = sqrt(vecrSqMagChanEst[i]);#endif } /* ------------------------------------------------------------------------- Calculate symbol ID of the current output block and set parameter */ (*pvecOutputData).GetExData().iSymbolID = (*pvecInputData).GetExData().iSymbolID - iLenHistBuff + 1; /* SNR estimation ------------------------------------------------------- */ /* Modified symbol ID, check range {0, ..., iNumSymPerFrame} */ iModSymNum = (*pvecOutputData).GetExData().iSymbolID; while (iModSymNum < 0) iModSymNum += iNumSymPerFrame; /* Two different types of SNR estimation are available */ switch (TypeSNREst) { case SNR_PIL: /* Use estimated channel and compare it to the received pilots. This estimation works only if the channel estimation was successful */ for (i = 0; i < iNumCarrier; i++) { /* Identify pilot positions. Use MODIFIED "iSymbolID" (See lines above) */ if (_IsScatPil(ReceiverParam.matiMapTab[iModSymNum][i])) { /* We assume that the channel estimation in "veccChanEst" is noise free (e.g., the wiener interpolation does noise reduction). Thus, we have an estimate of the received signal power \hat{r} = s * \hat{h}_{wiener} */ const _COMPLEX cModChanEst = veccChanEst[i] * ReceiverParam.matcPilotCells[iModSymNum][i]; /* Calculate and average noise and signal estimates --------- */ /* The noise estimation is difference between the noise reduced signal and the noisy received signal \tilde{n} = \hat{r} - r */ IIR1(rNoiseEst, SqMag(matcHistory[0][i] - cModChanEst), rLamSNREstFast); /* The received signal power estimation is just \hat{r} */ IIR1(rSignalEst, SqMag(cModChanEst), rLamSNREstFast); /* Calculate final result (signal to noise ratio) */ rCurSNREst = CalAndBoundSNR(rSignalEst, rNoiseEst); /* Average the SNR with a two sided recursion. Apply correction factor, too */ IIR1TwoSided(rSNREstimate, rCurSNREst / rSNRTotToPilCorrFact, rLamSNREstFast, rLamSNREstSlow); } } break; case SNR_FAC: /* SNR estimation based on FAC cells and hard decisions */ /* SNR estimation with initialization */ if (iSNREstInitCnt > 0) { for (i = 0; i < iNumCarrier; i++) { /* Only use the last frame of the initialization phase for initial SNR estimation to debar initialization phase of synchronization and channel estimation units */ if (iSNREstInitCnt < iNumSymPerFrame * iNumCarrier) { const int iCurCellFlag = ReceiverParam.matiMapTab[iModSymNum][i]; /* Initial signal estimate. Use channel estimation from all data and pilot cells. Apply averaging */ if ((_IsData(iCurCellFlag)) || (_IsPilot(iCurCellFlag))) { /* Signal estimation */ rSignalEst += vecrSqMagChanEst[i]; iSNREstIniSigAvCnt++; } /* Noise estimation from all data cells from tentative decisions */ if (_IsFAC(iCurCellFlag)) /* FAC cell */ { rNoiseEst += vecrSqMagChanEst[i] * SqMag(MinDist4QAM((*pvecOutputData)[i].cSig)); iSNREstIniNoiseAvCnt++; } } } iSNREstInitCnt--; } else { /* Only right after initialization phase apply initial SNR value */ if (bSNRInitPhase == TRUE) { /* Normalize average */ rSignalEst /= iSNREstIniSigAvCnt; rNoiseEst /= iSNREstIniNoiseAvCnt; bSNRInitPhase = FALSE; } for (i = 0; i < iNumCarrier; i++) { /* Only use FAC cells for this SNR estimation method */ if (_IsFAC(ReceiverParam.matiMapTab[iModSymNum][i])) { /* Get tentative decision for this FAC QAM symbol. FAC is always 4-QAM. Calculate all distances to the four possible constellation points of a 4-QAM and use the squared result of the returned distance vector */ const CReal rCurErrPow = SqMag(MinDist4QAM((*pvecOutputData)[i].cSig)); /* Use decision together with channel estimate to get estimates for signal and noise */ IIR1(rNoiseEst, rCurErrPow * vecrSqMagChanEst[i], rLamSNREstFast);
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -