📄 timesync.cpp
字号:
/* If pre-defined number of outliers is exceed, correct */ if (iCorrCounter > NUM_SYM_BEFORE_RESET) { /* If this is the first correction after an initialization was done, reset flag and do not show red light */ if (bInitTimingAcqu == TRUE) { /* Reset flag */ bInitTimingAcqu = FALSE; /* Right after initialization, the first estimate is used for correction */ rStartIndex = (CReal) iNewStartIndexField[i]; } else { /* Correct filter-output */ rStartIndex = (CReal) iAveCorr / (NUM_SYM_BEFORE_RESET + 1); /* GUI message that timing was corrected (red light) */ PostWinMessage(MS_TIME_SYNC, 2); } /* Reset counters */ iCorrCounter = 0; iAveCorr = 0; } else { /* GUI message that timing is yet ok (yellow light). Do not show any light if init was done right before this */ if (bInitTimingAcqu == FALSE) PostWinMessage(MS_TIME_SYNC, 1); } ReceiverParam.ReceptLog.SetSync(FALSE); }#ifdef _DEBUG_/* Save estimated positions of timing (acquisition) */static FILE* pFile = fopen("test/testtime.dat", "w");fprintf(pFile, "%d %d\n", iNewStartIndexField[i], iInputBlockSize);fflush(pFile);#endif } /* Convert result to integer format for cutting out the FFT-window */ iStartIndex = (int) rStartIndex; } else { /* Detect situation when acquisition was deactivated right now */ if (bAcqWasActive == TRUE) { bAcqWasActive = FALSE; /* Reset also the tracking value since the tracking could not get right parameters since the timing was not yet correct */ ReceiverParam.iTimingOffsTrack = 0; } /* In case of tracking only, use final acquisition result "rStartIndex" (which is not updated any more) and add tracking correction */ iStartIndex = (int) rStartIndex + ReceiverParam.iTimingOffsTrack; /* Timing acquisition was successfully finished, show always green light */ PostWinMessage(MS_TIME_SYNC, 0); ReceiverParam.ReceptLog.SetSync(TRUE);#ifdef _DEBUG_/* Save estimated positions of timing (tracking) */static FILE* pFile = fopen("test/testtimetrack.dat", "w");static int iTimeTrackAbs = 0;iTimeTrackAbs += ReceiverParam.iTimingOffsTrack; /* Integration */fprintf(pFile, "%d\n", iTimeTrackAbs);fflush(pFile);#endif } /* ------------------------------------------------------------------------- Cut out the estimated optimal time window and write it to the output vector. Add the acquisition and tracking offset together for the final timing */ /* Check range of "iStartIndex" to prevent from vector overwrites. It must be larger than "0" since then the input block size would be also "0" and than the processing routine of the modul would not be called any more */ const int i2SymBlSize = iSymbolBlockSize + iSymbolBlockSize; if (iStartIndex <= 0) iStartIndex = 1; if (iStartIndex >= i2SymBlSize) iStartIndex = i2SymBlSize; /* Cut out the useful part of the OFDM symbol */ for (k = iStartIndex; k < iStartIndex + iDFTSize; k++) (*pvecOutputData)[k - iStartIndex] = HistoryBuf[k]; /* If synchronized DRM input stream is used, overwrite the detected timing */ if (bSyncInput == TRUE) { /* Set fixed timing position */ iStartIndex = iSymbolBlockSize; /* Cut out guard-interval at right position -> no channel estimation needed when having only one path. No delay introduced in this module */ for (k = iGuardSize; k < iSymbolBlockSize; k++) { (*pvecOutputData)[k - iGuardSize] = HistoryBuf[iTotalBufferSize - iInputBlockSize + k]; } } /* ------------------------------------------------------------------------- Adjust filtered measurement so that it is back in the center of the buffer */ /* Integer part of the difference between filtered measurement and the center of the buffer */ iIntDiffToCenter = iCenterOfBuf - iStartIndex; /* Set input block size for next block and reset filtered measurement. This is equal to a global shift of the observation window by the rearrangement of the filtered measurement */ iInputBlockSize = iSymbolBlockSize - iIntDiffToCenter; /* In acquisition mode, correct start index */ if (bTimingAcqu == TRUE) rStartIndex += (CReal) iIntDiffToCenter; /* ------------------------------------------------------------------------- The channel estimation needs information about timing corrections, because it is using information from the symbol memory. After a timing correction all old symbols must be corrected by a phase rotation as well */ (*pvecOutputData).GetExData().iCurTimeCorr = iIntDiffToCenter;}void CTimeSync::InitInternal(CParameter& ReceiverParam){ int i, j; int iMaxSymbolBlockSize; int iObservedFreqBin; CReal rArgTemp; int iCorrBuffSize; /* Get parameters from info class */ iGuardSize = ReceiverParam.iGuardSize; iDFTSize = ReceiverParam.iFFTSizeN; iSymbolBlockSize = ReceiverParam.iSymbolBlockSize; /* Decimated symbol block size */ iDecSymBS = iSymbolBlockSize / GRDCRR_DEC_FACT; /* Calculate maximum symbol block size (This is Rob. Mode A) */ iMaxSymbolBlockSize = RMA_FFT_SIZE_N + RMA_FFT_SIZE_N * RMA_ENUM_TG_TU / RMA_DENOM_TG_TU; /* We need at least two blocks of data for determining the timing */ iTotalBufferSize = 2 * iSymbolBlockSize + iMaxSymbolBlockSize; iCorrBuffSize = iTotalBufferSize / GRDCRR_DEC_FACT; /* Set step size of the guard-interval correlation */ iStepSizeGuardCorr = STEP_SIZE_GUARD_CORR; /* Size for moving average buffer for guard-interval correlation */ iMovAvBufSize = (int) ((CReal) iGuardSize / GRDCRR_DEC_FACT / iStepSizeGuardCorr); /* Size of buffer, storing the moving-average results for maximum detection */ iMaxDetBufSize = (int) ((CReal) iDecSymBS / iStepSizeGuardCorr); /* Center of maximum detection buffer */ iCenterOfMaxDetBuf = (iMaxDetBufSize - 1) / 2; /* Init Energy calculation after guard-interval correlation (moving average) */ vecrGuardEnMovAv.Init(iMovAvBufSize); /* Start position of this value must be at the end of the observation window because we reset it at the beginning of the loop */ iTimeSyncPos = 2 * iDecSymBS; /* Calculate center of buffer */ iCenterOfBuf = iSymbolBlockSize; /* Init rStartIndex only if acquisition was activated */ if (bTimingAcqu == TRUE) rStartIndex = (CReal) iCenterOfBuf; /* Some inits */ iAveCorr = 0; bInitTimingAcqu = TRUE; /* Flag to show that init was done */ /* Set correction counter so that a non-linear correction is performed right at the beginning */ iCorrCounter = NUM_SYM_BEFORE_RESET; /* Allocate memory for vectors and zero out */ HistoryBuf.Init(iTotalBufferSize, (CReal) 0.0); pMaxDetBuffer.Init(iMaxDetBufSize, (CReal) 0.0); HistoryBufCorr.Init(iCorrBuffSize, (CReal) 0.0); /* Inits for averaging the guard-interval correlation */ vecCorrAvBuf.Init(iMaxDetBufSize, (CReal) 0.0); iCorrAvInd = 0; /* Set the selected robustness mode index */ iSelectedMode = GetIndFromRMode(ReceiverParam.GetWaveMode()); /* Init init count for timing sync (one symbol) */ iTiSyncInitCnt = iDecSymBS / iStepSizeGuardCorr; /* Inits for guard-interval correlation and robustness mode detection --- */ /* Size for robustness mode correlation buffer */ iRMCorrBufSize = (int) ((CReal) NUM_BLOCKS_FOR_RM_CORR * iDecSymBS / STEP_SIZE_GUARD_CORR); /* Init init count for robustness mode detection (do not use the very first block) */ iRobModInitCnt = NUM_BLOCKS_FOR_RM_CORR + 1; for (i = 0; i < NUM_ROBUSTNESS_MODES; i++) { cGuardCorr[i] = (CReal) 0.0; cGuardCorrBlock[i] = (CReal) 0.0; rGuardPow[i] = (CReal) 0.0; rGuardPowBlock[i] = (CReal) 0.0; iPosInIntermCResBuf[i] = 0; /* Set length of the useful part of the symbol and guard size */ switch (i) { case 0: iLenUsefPart[i] = RMA_FFT_SIZE_N / GRDCRR_DEC_FACT; iLenGuardInt[i] = (int) ((CReal) RMA_FFT_SIZE_N * RMA_ENUM_TG_TU / RMA_DENOM_TG_TU / GRDCRR_DEC_FACT); break; case 1: iLenUsefPart[i] = RMB_FFT_SIZE_N / GRDCRR_DEC_FACT; iLenGuardInt[i] = (int) ((CReal) RMB_FFT_SIZE_N * RMB_ENUM_TG_TU / RMB_DENOM_TG_TU / GRDCRR_DEC_FACT); break; case 2: iLenUsefPart[i] = RMC_FFT_SIZE_N / GRDCRR_DEC_FACT; iLenGuardInt[i] = (int) ((CReal) RMC_FFT_SIZE_N * RMC_ENUM_TG_TU / RMC_DENOM_TG_TU / GRDCRR_DEC_FACT); break; case 3: iLenUsefPart[i] = RMD_FFT_SIZE_N / GRDCRR_DEC_FACT; iLenGuardInt[i] = (int) ((CReal) RMD_FFT_SIZE_N * RMD_ENUM_TG_TU / RMD_DENOM_TG_TU / GRDCRR_DEC_FACT); break; } /* Number of correlation result blocks to be stored in a vector. This is the total length of the guard-interval divided by the step size. Since the guard-size must not be a multiple of "iStepSizeGuardCorr", we need to cut-off the fractional part */ iLengthIntermCRes[i] = (int) ((CReal) iLenGuardInt[i] / iStepSizeGuardCorr); /* This length is the start point for the "for"-loop */ iLengthOverlap[i] = iLenGuardInt[i] - iStepSizeGuardCorr; /* Intermediate correlation results vector (init, zero out) */ veccIntermCorrRes[i].Init(iLengthIntermCRes[i], (CReal) 0.0); vecrIntermPowRes[i].Init(iLengthIntermCRes[i], (CReal) 0.0); /* Allocate memory for correlation input buffers */ vecrRMCorrBuffer[i].Init(iRMCorrBufSize); /* Tables for sin and cos function for the desired frequency band */ /* First, allocate memory for vector */ vecrCos[i].Init(iRMCorrBufSize); /* Build table */ for (j = 0; j < iRMCorrBufSize; j++) { /* Calculate frequency bins which has to be observed for each mode. Mode A: f_A = 1 / T_s = 1 / 26.66 ms = 37.5 Hz Mode B: f_B = 1 / T_s = 1 / 26.66 ms = 37.5 Hz Mode C: f_C = 1 / T_s = 1 / 20 ms = 50 Hz Mode D: f_D = 1 / T_s = 1 / 16.66 ms = 60 Hz */ iObservedFreqBin = (int) ((CReal) iRMCorrBufSize * STEP_SIZE_GUARD_CORR / (iLenUsefPart[i] + iLenGuardInt[i])); rArgTemp = (CReal) 2.0 * crPi / iRMCorrBufSize * j; vecrCos[i][j] = cos(rArgTemp * iObservedFreqBin); } }#ifdef USE_FRQOFFS_TRACK_GUARDCORR /* Init vector for averaging the frequency offset estimation */ cFreqOffAv = CComplex((CReal) 0.0, (CReal) 0.0); /* Init time constant for IIR filter for frequency offset estimation */ rLamFreqOff = IIR1Lam(TICONST_FREQ_OFF_EST_GUCORR, (CReal) SOUNDCRD_SAMPLE_RATE / ReceiverParam.iSymbolBlockSize); /* Nomalization constant for frequency offset estimation */ rNormConstFOE = (CReal) 1.0 / ((CReal) 2.0 * crPi * ReceiverParam.iFFTSizeN * GRDCRR_DEC_FACT);#endif /* Define block-sizes for input and output */ iInputBlockSize = iSymbolBlockSize; /* For the first loop */ iOutputBlockSize = iDFTSize;}void CTimeSync::StartAcquisition(){// TODO: check which initialization should be done here and which should be// moved to / from the "InitInternal()" function /* The regular acquisition flags */ bTimingAcqu = TRUE; bRobModAcqu = TRUE; /* Set the init flag so that the "rStartIndex" can be initialized with the center of the buffer and other important settings can be done */ SetInitFlag(); /* This second flag is to determine the moment when the acquisition just finished. In this case, the tracking value must be reset */ bAcqWasActive = TRUE; iCorrCounter = NUM_SYM_BEFORE_RESET; /* Reset the buffers which are storing data for correlation (for robustness mode detection) */ for (int i = 0; i < NUM_ROBUSTNESS_MODES; i++) vecrRMCorrBuffer[i] = Zeros(iRMCorrBufSize); /* Reset lambda for averaging the guard-interval correlation results */ rLambdaCoAv = (CReal) 1.0; iCorrAvInd = 0;}void CTimeSync::SetFilterTaps(const CReal rNewOffsetNorm){#ifndef USE_10_KHZ_HILBFILT /* The filter should be on the right of the DC carrier in 5 kHz mode */ rNewOffsetNorm += (CReal) HILB_FILT_BNDWIDTH / 2 / SOUNDCRD_SAMPLE_RATE;#endif /* Calculate filter taps for complex Hilbert filter */ cvecB.Init(NUM_TAPS_HILB_FILT); for (int i = 0; i < NUM_TAPS_HILB_FILT; i++) cvecB[i] = CComplex( fHilLPProt[i] * Cos((CReal) 2.0 * crPi * rNewOffsetNorm * i), fHilLPProt[i] * Sin((CReal) 2.0 * crPi * rNewOffsetNorm * i)); /* Init state vector for filtering with zeros */ cvecZ.Init(NUM_TAPS_HILB_FILT - 1, (CReal) 0.0);}CTimeSync::CTimeSync() : iTimeSyncPos(0), bSyncInput(FALSE), bTimingAcqu(FALSE), bAcqWasActive(FALSE), bRobModAcqu(FALSE), iLengthIntermCRes(NUM_ROBUSTNESS_MODES), iPosInIntermCResBuf(NUM_ROBUSTNESS_MODES), iLengthOverlap(NUM_ROBUSTNESS_MODES), iLenUsefPart(NUM_ROBUSTNESS_MODES), iLenGuardInt(NUM_ROBUSTNESS_MODES), cGuardCorr(NUM_ROBUSTNESS_MODES), rGuardPow(NUM_ROBUSTNESS_MODES), cGuardCorrBlock(NUM_ROBUSTNESS_MODES), rGuardPowBlock(NUM_ROBUSTNESS_MODES), rLambdaCoAv((CReal) 1.0){ /* Init Hilbert filter. Since the frequency offset correction was done in the previous module, the offset for the filter is always "VIRTUAL_INTERMED_FREQ" */ SetFilterTaps((_REAL) VIRTUAL_INTERMED_FREQ / SOUNDCRD_SAMPLE_RATE);}int CTimeSync::GetIndFromRMode(ERobMode eNewMode){ /* Get the robustness mode index. We define: A: 0, B: 1, C: 2, D: 3 */ switch (eNewMode) { case RM_ROBUSTNESS_MODE_A: return 0; case RM_ROBUSTNESS_MODE_B: return 1; case RM_ROBUSTNESS_MODE_C: return 2; case RM_ROBUSTNESS_MODE_D: return 3; default: return 0; }}ERobMode CTimeSync::GetRModeFromInd(int iNewInd){ /* Get the robustness mode index. We define: A: 0, B: 1, C: 2, D: 3 */ switch (iNewInd) { case 0: return RM_ROBUSTNESS_MODE_A; case 1: return RM_ROBUSTNESS_MODE_B; case 2: return RM_ROBUSTNESS_MODE_C; case 3: return RM_ROBUSTNESS_MODE_D; default: return RM_ROBUSTNESS_MODE_A; }}
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -