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

📄 timesync.cpp

📁 Dream.exe soft source (Visual C++)
💻 CPP
📖 第 1 页 / 共 2 页
字号:
/******************************************************************************\
 * Technische Universitaet Darmstadt, Institut fuer Nachrichtentechnik
 * Copyright (c) 2001
 *
 * Author(s):
 *	Volker Fischer
 *
 * Description:
 *	Time synchronization
 * This module can have different amounts of input data. If two
 * possible FFT-window positions are found, the next time no new block is
 * requested.
 *
 * Robustness-mode detection
 *
 ******************************************************************************
 *
 * 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 "TimeSync.h"


/* Implementation *************************************************************/
void CTimeSync::ProcessDataInternal(CParameter& ReceiverParam)
{
	int				i, j, k;
	int				iMaxIndex;
	int				iNewStIndCount; 
	int				iIntDiffToCenter;
	int				iCurPos;
	int				iDetectedRModeInd;
	int				iDecInpuSize;
	CReal			rMaxValue;
	CReal			rMaxValRMCorr;
	CReal			rSecHighPeak;
	CReal			rFreqOffsetEst;
	CComplexVector	cvecInpTmp;
	CRealVector		rResMode(NUM_ROBUSTNESS_MODES);

	/* Max number of detected peaks ("5" for safety reasons. Could be "2") */
	CVector<int>	iNewStartIndexField(5);

	/* Init start index (in case no timing could be detected or init phase) */
	int iStartIndex = iSymbolBlockSize;

	/* Write new block of data at the end of shift register */
	HistoryBuf.AddEnd(*pvecInputData, iInputBlockSize);

	/* In case the time domain frequency offset estimation method is activated,
	   the hilbert filtering of input signal must always be applied */
#ifndef USE_FRQOFFS_TRACK_GUARDCORR
	if ((bTimingAcqu == TRUE) || (bRobModAcqu == TRUE))
#endif
	{
		/* ---------------------------------------------------------------------
		   Data must be band-pass-filtered before applying the algorithms,
		   because we do not know which mode is active when we synchronize
		   the timing and we must assume the worst-case, therefore use only
		   from DC to 4.5 kHz. If the macro "USE_10_KHZ_HILBFILT" is defined,
		   a bandwith of approx. 10 kHz is used. In this case, we have better
		   performance with the most probable 10 kHz mode but may have worse
		   performance with the 4.5 or 5 kHz modes (for the acquisition) */

		/* The FIR filter intermediate buffer must be adjusted to the new
		   input block size since the size can be vary with time */
		cvecInpTmp.Init(iInputBlockSize);

		/* Copy CVector data in CMatlibVector */
		for (i = 0; i < iInputBlockSize; i++)
			cvecInpTmp[i] = (*pvecInputData)[i];

		/* Complex Hilbert filter. We use the copy constructor for storing
		   the result since the sizes of the output vector varies with time.
		   We decimate the signal with this function, too, because we only
		   analyze a spectrum bandwith of approx. 5 [10] kHz */
		CComplexVector cvecOutTmp(
			FirFiltDec(cvecB, cvecInpTmp, cvecZ, GRDCRR_DEC_FACT));

		/* Get size of new output vector */
		iDecInpuSize = Size(cvecOutTmp);

		/* Copy data from Matlib vector in regular vector for storing in
		   shift register
		   TODO: Make vector types compatible (or maybe only use matlib vectors
		   everywhere) */
		cvecOutTmpInterm.Init(iDecInpuSize);
		for (i = 0; i < iDecInpuSize; i++)
			cvecOutTmpInterm[i] = cvecOutTmp[i];

		/* Write new block of data at the end of shift register */
		HistoryBufCorr.AddEnd(cvecOutTmpInterm, iDecInpuSize);


#ifdef USE_FRQOFFS_TRACK_GUARDCORR
		/* ---------------------------------------------------------------------
		   Frequency offset tracking estimation method based on guard-interval
		   correlation.
		   Problem: The tracking frequency range is "GRDCRR_DEC_FACT"-times
		   smaller than the one in the frequency domain tracking algorithm.
		   Therefore, the acquisition unit must work more precisely
		   (see FreqSyncAcq.h) */

		/* Guard-interval correlation at ML estimated timing position */
		/* Calculate start points for correlation. Consider delay from
		   Hilbert-filter */
		const int iHalHilFilDelDec = NUM_TAPS_HILB_FILT / 2 / GRDCRR_DEC_FACT;
		const int iCorrPosFirst = iDecSymBS + iHalHilFilDelDec;
		const int iCorrPosSec =
			iDecSymBS + iHalHilFilDelDec + iLenUsefPart[iSelectedMode];

		/* Actual correlation over entire guard-interval */
		CComplex cGuardCorrFreqTrack = 0.0;
		for (i = 0; i < iLenGuardInt[iSelectedMode]; i++)
		{
			/* Use start point from ML timing estimation. The input stream is
			   automatically adjusted to have this point at "iDecSymBS" */
			cGuardCorrFreqTrack += HistoryBufCorr[i + iCorrPosFirst] *
				Conj(HistoryBufCorr[i + iCorrPosSec]);
		}

		/* Average vector, real and imaginary part separately */
		IIR1(cFreqOffAv, cGuardCorrFreqTrack, rLamFreqOff);

		/* Calculate argument */
		const CReal rFreqOffsetEst = Angle(cFreqOffAv);

		/* Correct measurement average for actually applied frequency
		   correction */
		cFreqOffAv *= CComplex(Cos(-rFreqOffsetEst), Sin(-rFreqOffsetEst));

		/* Integrate the result for controling the frequency offset, normalize
		   estimate */
		ReceiverParam.rFreqOffsetTrack -= rFreqOffsetEst * rNormConstFOE;
#endif


		if ((bTimingAcqu == TRUE) || (bRobModAcqu == TRUE))
		{
			/* Guard-interval correlation ----------------------------------- */
			/* Set position pointer back for this block */
			iTimeSyncPos -= iDecInpuSize;

			/* Init start-index count */
			iNewStIndCount = 0;

			/* We use the block in the middle of the buffer for observation */
			for (i = iDecSymBS + iDecSymBS - iDecInpuSize;
				i < iDecSymBS + iDecSymBS; i++)
			{
				/* Only every "iStepSizeGuardCorr"'th value is calculated for
				   efficiency reasons */
				if (i == iTimeSyncPos)
				{
					/* Do the following guard interval correlation for all
					   possible robustness modes (this is needed for robustness
					   mode detection) */
					for (j = 0; j < NUM_ROBUSTNESS_MODES; j++)
					{
						/* Guard-interval correlation ----------------------- */
						/* Speed optimized calculation of the guard-interval
						   correlation. We devide the total block, which has to
						   be computed, in parts of length "iStepSizeGuardCorr".
						   The results of these blocks are stored in a vector.
						   Now, only one new part has to be calculated and one
						   old one has to be subtracted from the global result.
						   Special care has to be taken since "iGuardSize" must
						   not be a multiple of "iStepSizeGuardCorr". Therefore
						   the "if"-condition */
						/* First subtract correlation values shifted out */
						cGuardCorr[j] -= 
							veccIntermCorrRes[j][iPosInIntermCResBuf[j]];
						rGuardPow[j] -= 
							vecrIntermPowRes[j][iPosInIntermCResBuf[j]];

						/* Calculate new block and add in memory */
						for (k = iLengthOverlap[j]; k < iLenGuardInt[j]; k++)
						{
							/* Actual correlation */
							iCurPos = iTimeSyncPos + k;
							cGuardCorrBlock[j] += HistoryBufCorr[iCurPos] * 
								Conj(HistoryBufCorr[iCurPos + iLenUsefPart[j]]);

							/* Energy calculation for ML solution */
							rGuardPowBlock[j] +=
								SqMag(HistoryBufCorr[iCurPos]) +
								SqMag(HistoryBufCorr[iCurPos + iLenUsefPart[j]]);

							/* If one complete block is ready -> store it. We
							   need to add "1" to the k, because otherwise
							   "iLengthOverlap" would satisfy the
							   "if"-condition */
							if (((k + 1) % iStepSizeGuardCorr) == 0)
							{
								veccIntermCorrRes[j][iPosInIntermCResBuf[j]] =
									cGuardCorrBlock[j];

								vecrIntermPowRes[j][iPosInIntermCResBuf[j]] =
									rGuardPowBlock[j];

								/* Add the new block to the global result */
								cGuardCorr[j] += cGuardCorrBlock[j];
								rGuardPow[j] += rGuardPowBlock[j];

								/* Reset block result */
								cGuardCorrBlock[j] = (CReal) 0.0;
								rGuardPowBlock[j] = (CReal) 0.0;

								/* Increase position pointer and test if wrap */
								iPosInIntermCResBuf[j]++;
								if (iPosInIntermCResBuf[j] == iLengthIntermCRes[j])
									iPosInIntermCResBuf[j] = 0;
							}
						}

						/* Save correlation results in shift register */
						for (k = 0; k < iRMCorrBufSize - 1; k++)
							vecrRMCorrBuffer[j][k] = vecrRMCorrBuffer[j][k + 1];

						/* ML solution */
						vecrRMCorrBuffer[j][iRMCorrBufSize - 1] =
							abs(cGuardCorr[j] + cGuardCorrBlock[j]) - 
							(rGuardPow[j] + rGuardPowBlock[j]) / 2;
					}

					/* Energy of guard intervall calculation and detection of
					   peak is only needed if timing aquisition is true */
					if (bTimingAcqu == TRUE)
					{
						/* Start timing detection not until initialization phase
						   is finished */
						if (iTiSyncInitCnt > 1)
						{
							/* Decrease counter */
							iTiSyncInitCnt--;
						}
						else
						{
							/* Average the correlation results */
							IIR1(vecCorrAvBuf[iCorrAvInd],
								vecrRMCorrBuffer[iSelectedMode][iRMCorrBufSize - 1],
								1 - rLambdaCoAv);


							/* Energy of guard-interval correlation calculation
							   (this is simply a moving average operation) */
							vecrGuardEnMovAv.Add(vecCorrAvBuf[iCorrAvInd]);


							/* Taking care of correlation average buffer ---- */
							/* We use a "cyclic buffer" structure. This index
							   defines the position in the buffer */
							iCorrAvInd++;
							if (iCorrAvInd == iMaxDetBufSize)
							{
								/* Adaptation of the lambda parameter for
								   guard-interval correlation averaging IIR
								   filter. With this adaptation we achieve
								   better averaging results. A lower bound is
								   defined for this parameter */
								if (rLambdaCoAv <= 0.1)
									rLambdaCoAv = 0.1;
								else
									rLambdaCoAv /= 2;

								iCorrAvInd = 0;
							}


							/* Detection buffer ----------------------------- */
							/* Update buffer for storing the moving average
							   results */
							pMaxDetBuffer.AddEnd(vecrGuardEnMovAv.GetAverage());

							/* Search for maximum */
							iMaxIndex = 0;
							rMaxValue = (CReal) -_MAXREAL; /* Init value */
							for (k = 0; k < iMaxDetBufSize; k++)
							{
								if (pMaxDetBuffer[k] > rMaxValue)
								{
									rMaxValue = pMaxDetBuffer[k];
									iMaxIndex = k;
								}
							}

							/* If maximum is in the middle of the interval, mark
							   position as the beginning of the FFT window */
							if (iMaxIndex == iCenterOfMaxDetBuf)
							{
								/* The optimal start position for the FFT-window
								   is the middle of the "MaxDetBuffer" */
								iNewStartIndexField[iNewStIndCount] = 
									iTimeSyncPos * GRDCRR_DEC_FACT -
									iSymbolBlockSize / 2 -
									/* Compensate for Hilbert-filter delay. The
									   delay is introduced in the downsampled
									   domain, therefore devide it by
									   "GRDCRR_DEC_FACT" */
									NUM_TAPS_HILB_FILT / 2 / GRDCRR_DEC_FACT;

								iNewStIndCount++;
							}
						}
					}

					/* Set position pointer to next step */
					iTimeSyncPos += iStepSizeGuardCorr;
				}
			}


			/* Robustness mode detection ------------------------------------ */
			if (bRobModAcqu == TRUE)
			{
				/* Start robustness mode detection not until the buffer is
				   filled */
				if (iRobModInitCnt > 1)
				{
					/* Decrease counter */
					iRobModInitCnt--;
				}
				else
				{
					/* Correlation of guard-interval correlation with prepared
					   cos-vector. Store highest peak */
					rMaxValRMCorr = (CReal) 0.0;
					for (j = 0; j < NUM_ROBUSTNESS_MODES; j++)
					{
						/* Correlation with symbol rate frequency (Correlations
						   must be normalized to be comparable!
						   ("/ iGuardSizeX")) */
						rResMode[j] =
							Abs(Sum(vecrRMCorrBuffer[j] * vecrCos[j])) /
							iLenGuardInt[j];

						/* Search for maximum */
						if (rResMode[j] > rMaxValRMCorr)
						{
							rMaxValRMCorr = rResMode[j];
							iDetectedRModeInd = j;
						}
					}

					/* Get second highest peak */
					rSecHighPeak = (CReal) 0.0;
					for (j = 0; j < NUM_ROBUSTNESS_MODES; j++)
					{
						if ((rResMode[j] > rSecHighPeak) &&
							(iDetectedRModeInd != j))
						{
							rSecHighPeak = rResMode[j];
						}
					}

					/* Find out if we have a reliable measure
					   (distance to next peak) */
					if ((rMaxValRMCorr / rSecHighPeak) > THRESHOLD_RELI_MEASURE)
					{
						/* Reset aquisition flag for robustness mode detection */
						bRobModAcqu = FALSE;

						/* Set wave mode */
						if (ReceiverParam.
							SetWaveMode(GetRModeFromInd(iDetectedRModeInd)) == TRUE)
						{
							/* Reset output cyclic-buffer because wave mode has
							   changed and the data written in the buffer is not
							   valid anymore */
							SetBufReset1();
						}
					}
				}
			}
		}
	}

	if (bTimingAcqu == TRUE)
	{
		/* Use all measured FFT-window start points for determining the "real"
		   one */	
		for (i = 0; i < iNewStIndCount; i++)
		{
			/* Check if new measurement is in range of predefined bound. This
			   bound shall eliminate outliers for the calculation of the
			   filtered result */
			if (((iNewStartIndexField[i] < (iCenterOfBuf + TIMING_BOUND_ABS)) &&
				(iNewStartIndexField[i] > (iCenterOfBuf - TIMING_BOUND_ABS))))
			{
				/* New measurement is in range -> use it for filtering */
				/* Low-pass filter detected start of frame */
				IIR1(rStartIndex, (CReal) iNewStartIndexField[i],
					LAMBDA_LOW_PASS_START);

				/* Reset counters for non-linear correction algorithm */
				iCorrCounter = 0;
				iAveCorr = 0;

				/* GUI message that timing is ok */
				PostWinMessage(MS_TIME_SYNC, 0);
				ReceiverParam.ReceptLog.SetSync(TRUE);

				/* Acquisition was successful, reset init flag (just in case it
				   was not reset by the non-linear correction unit */
				bInitTimingAcqu = FALSE;
			}
			else
			{
				/* Non-linear correction of the filter-output to ged rid of
				   large differences between current measurement and
				   filter-output */
				iCorrCounter++;

				/* Average the NUM_SYM_BEFORE_RESET measurements for reset
				   rStartIndex */
				iAveCorr += iNewStartIndexField[i];

⌨️ 快捷键说明

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