int ReceiveData(float[] incomingSamples, int startingIndex, int numSamples) { if (numSamples == 0) { this.SymbolsCounter = 0; } int i, nProc; for (i = 0; i < numSamples; i += nProc) { nProc = Math.Min(numSamples - i, DECFACTOR); int nSym = Demodulator.Process(incomingSamples, startingIndex + i, nProc); while (nSym-- > 0) { Decoder.Process(Demodulator.GetData(), DataScrambler.DataNext(), SCRAMBLE_MASK, out DataBlock[SymbolsCounter]); SymbolsCounter++; // Is probe sequence coming ? if (SymbolsCounter >= CurrentMode.UnknownDataSymbols) { NextFunction = ReceiveProbe; numSamples = 0; break; } } } return(i); }
int LookForSyncPreamble(float[] incomingSamples, int startingIndex, int numSamples) { if (numSamples == 0) { SymbolsCounter = 0; } int i = 0; while (i < numSamples) { // Feed the data into demodulator by DFAC chunks int nProc = Math.Min(numSamples - i, DECFACTOR); int nSymb = Demodulator.Process(incomingSamples, startingIndex + i, nProc); while (nSymb-- > 0) { // If we went thru 3 preamble segments and did not catch it - // something is wrong - start from the beginning if (SymbolsCounter++ > (3 * 480)) { NextFunction = Idle; numSamples = 0; // This is how to terminate a loop!!! break; } if (SyncCorr.Process(Demodulator.GetData()) > 0) { NextFunction = SyncDetected; numSamples = 0; // This is how to terminate a loop!!! break; } } i += nProc; } return(i); }
// Initial state - looking for any reasonable amount of energy in signal int Idle(float[] incomingSamples, int startingIndex, int numSamples) { int i = 0; for (i = 0; i < numSamples; i++) { float Sample = incomingSamples[startingIndex + i]; if ((Sample * Sample) > EnergyThreshold) { NextFunction = LookForCarrierEnergy; numSamples = 0; // This is how to terminate a loop!!! } } return(i); }
public void Init() { SyncCorr = new Correlator(CORR_TYPE.DELTA_DIFF, 15 * 32, 9 * 32, 6 * 32, CorrTargetThreshold, CorrAverageThreshold, CorrEnergyThreshold); Demodulator = new IQDemodulator(CARRIER_FREQ - 15, CARRIER_FREQ - 15, NUM_FREQ, ProcessingFrequency, SYMBOLRATE, SymbolFilterCoeffs); ProbeEncoder = new IQEncoder(BITS_PER_SYMBOL, Constellation.Table_1_to_1, Constellation.ITable_8PSK, Constellation.QTable_8PSK, EncodingType.SCRAMBLE_ADD); SymbDetector = new SymbolDetector(); EOMDetector = new BitCorrelator(); FillSyncPatterns(); SyncCorr.AddTarget(PreamblePattern); int FlipEOM = MILSTD_188.MSBFirst(MILSTD_188.EOM); EOMDetector.AddTarget(FlipEOM, 32); OutputData.Clear(); InputFilter.Clear(); PrevFunction = null; NextFunction = Idle; }
// Looking for any energy in carrier frequency int LookForCarrierEnergy(float[] incomingSamples, int startingIndex, int numSamples) { if (numSamples == 0) { Demodulator.Init(); } int i = 0; for (i = 0; i < numSamples; i++) { float Sample = incomingSamples[startingIndex + i]; Demodulator.Process(Sample); if (Demodulator.FrequencyEnergy > Demodulator.SignalEnergy * SignalThreshold) { NextFunction = LookForSymbolSync; numSamples = 0; // This is how to terminate a loop!!! } } return(i); }
void Process(int numSamples) { int Index = 0; int nProcessed; while (numSamples > 0) { // If state function is called the very first time, then // there will be a special call to indicate that. numSamples == 0 to tell that // we are enering the state, so some state initialization can be done while (PrevFunction != NextFunction) { PrevFunction = NextFunction; NextFunction(InterpBuffer, Index, 0); } nProcessed = NextFunction(InterpBuffer, Index, numSamples); Index += nProcessed; numSamples -= nProcessed; } }
// Looking for symbol sync int LookForSymbolSync(float[] incomingSamples, int startingIndex, int numSamples) { if (numSamples == 0) { Demodulator.Init(); Demodulator.StartCorrectionProcess(SYNC_TYPE.GARDNER_DD | SYNC_TYPE.GARDNER_NDA | SYNC_TYPE.QAMLD_NDA | SYNC_TYPE.DIFF_NDA | SYNC_TYPE.ZERODET_NDA | SYNC_TYPE.PEAK_NDA | SYNC_TYPE.CORR_NDA, SYMBOL_SYNC_SIZE); } int i, nProc; for (i = 0; i < numSamples; i += nProc) { nProc = Math.Min(numSamples - i, DECFACTOR); Demodulator.Process(incomingSamples, startingIndex + i, nProc); if (Demodulator.IsSyncReady) { NextFunction = LookForSyncPreamble; numSamples = 0; // This is how to terminate a loop!!! } } return(i); }
int ReceiveProbe(float[] incomingSamples, int startingIndex, int numSamples) { if (numSamples == 0) { LFSRState State = DataScrambler.State; // Save current DataScrambler state Array.Clear(Probe, 0, CurrentMode.ProbeDataSymbols); // The last 2 probes for the interleaver are special - // they are not 0, but D1 and D2 values instead if (ProbeCounter == (TotalPatternsInBlock - 2)) { ChanSymbToTribit[CurrentMode.D1].CopyTo(Probe, 0); // Send 8 tribits ChanSymbToTribit[CurrentMode.D1].CopyTo(Probe, 8); // Send 8 tribits } else if (ProbeCounter == (TotalPatternsInBlock - 1)) { ChanSymbToTribit[CurrentMode.D2].CopyTo(Probe, 0); // Send 8 tribits ChanSymbToTribit[CurrentMode.D2].CopyTo(Probe, 8); // Send 8 tribits } for (int k = 0; k < CurrentMode.ProbeDataSymbols; k++) { ProbeEncoder.Process(Probe[k], DataScrambler.DataNext(), SCRAMBLE_MASK, out ProbeTarget[k]); } ProbeCorr.AddTarget(ProbeTarget); DataScrambler.State = State; // Restore scrambler state ProbeCounter++; if (ProbeCounter >= TotalPatternsInBlock) { ProbeCounter = 0; } Demodulator.RotateCorrection *= Decoder.RotateCorrection; Demodulator.FrequencyCorrection *= (IQ.UNITY + 0.05f * Decoder.FrequencyCorrection) / 1.05f; ProbeCorr.StartCorrectionProcess(); // Demodulator.StartCorrectionProcess(SYNC_TYPE.GARDNER_DD | SYNC_TYPE.GARDNER_NDA | SYNC_TYPE.QAMLD_NDA | // SYNC_TYPE.DIFF_NDA | SYNC_TYPE.ZERODET_NDA | SYNC_TYPE.PEAK_NDA | SYNC_TYPE.CORR_NDA, // CurrentMode.UnknownDataSymbols + CurrentMode.ProbeDataSymbols); Decoder.StartCorrectionProcess(CurrentMode.UnknownDataSymbols + CurrentMode.ProbeDataSymbols); this.SymbolsCounter = 0; } int i, nProc; int Data; IQ Symb; for (i = 0; i < numSamples; i += nProc) { nProc = Math.Min(numSamples - i, DECFACTOR); int nSymb = Demodulator.Process(incomingSamples, startingIndex + i, nProc); while (nSymb-- > 0) { Symb = Demodulator.GetData(); ProbeCorr.Process(Symb); Decoder.Process(Symb, DataScrambler.DataNext(), SCRAMBLE_MASK, out Data); SymbolsCounter++; // Is data sequence coming ? if (SymbolsCounter >= CurrentMode.ProbeDataSymbols) { Demodulator.RotateCorrection *= ProbeCorr.RotateCorrection; Demodulator.FrequencyCorrection *= (IQ.UNITY + 0.05f * ProbeCorr.FrequencyCorrection) / 1.05f; ProcessData(); // Process received data NextFunction = ReceiveData; numSamples = 0; break; } } } return(i); }
int SyncDetected(float[] incomingSamples, int startingIndex, int numSamples) { if (numSamples == 0) { // Adjust demodulator Demodulator.RotateCorrection = SyncCorr.RotateCorrection; // Frequency Correction on receiving the first Sync block // Only apply correction if the accumulated error will be more that 45 degrees if (Math.Abs(SyncCorr.FrequencyCorrection.Degrees * SyncCorr.CorrelationMaxLength) > 45) { Demodulator.FrequencyCorrection = SyncCorr.FrequencyCorrection; } // Get the last 15*32 symbols SyncCorr.GetLastData(SyncCorr.CorrelationMaxIndex, PreambleBlock, 15 * 32); int D1, D2, Z, Cnt; ProcessPreamble(out D1, out D2, out Cnt, out Z); // Check for the reasonable values that we extracted from the preamble // Get the mode from D1 and D2, verify counter ModeInfo mi = MILSTD188_110B.modemModes[D1, D2]; if (Z == 0 && mi != null && Cnt < mi.PreambleSize) { this.CurrentMode = mi; PreambuleCounter = Cnt; if (PreambuleCounter == 0) { InitReceiveData(); NextFunction = ReceiveData; numSamples = 0; } else { PreambleIdx = 0; SyncCorr.StartCorrectionProcess(); } } else { NextFunction = LookForSymbolSync; numSamples = 0; } } int i, nProc; for (i = 0; i < numSamples; i += nProc) { // Decode the preamble chunks nProc = Math.Min(numSamples - i, DECFACTOR); int nSym = Demodulator.Process(incomingSamples, startingIndex + i, nProc); while (nSym-- > 0) { IQ IQData = Demodulator.GetData(); PreambleBlock[PreambleIdx++] = IQData; SyncCorr.Process(IQData); if (PreambleIdx >= PreambleBlock.Length) { // Do demodulator correction Demodulator.RotateCorrection *= SyncCorr.RotateCorrection; Demodulator.FrequencyCorrection *= (IQ.UNITY + 0.05f * SyncCorr.FrequencyCorrection) / 1.05f; int D1, D2, Z, Cnt; ProcessPreamble(out D1, out D2, out Cnt, out Z); // Check the values that we extracted from the preambule // Get the mode from D1 and D2, verify counter if (Z == 0 && D1 == CurrentMode.D1 && D2 == CurrentMode.D2 && Cnt == (PreambuleCounter - 1)) { PreambuleCounter = Cnt; if (PreambuleCounter == 0) { InitReceiveData(); NextFunction = ReceiveData; numSamples = 0; break; } else { PreambleIdx = 0; SyncCorr.StartCorrectionProcess(); } } else { NextFunction = LookForSymbolSync; numSamples = 0; break; } } } } return(i); }