void FillSyncPatterns() { IQEncoder Enc = new IQEncoder(BITS_PER_SYMBOL, Constellation.Table_1_to_1, Constellation.ITable_8PSK, Constellation.QTable_8PSK, EncodingType.SCRAMBLE_ADD); SyncScrambler scrambler = new SyncScrambler(); int SyncSymbolCounter = 0; foreach (int BitChanSymb in SyncPreamble) { int[] sequence = ChanSymbToTribit[BitChanSymb]; scrambler.Init(); // repeat sequence 4 times for (int i = 0; i < 4; i++) { foreach (int tribit in sequence) { Enc.Process(tribit, scrambler.DataNext(), SCRAMBLE_MASK, out PreamblePattern[SyncSymbolCounter]); SyncSymbolCounter++; } } } IQ[] symb75 = new IQ[32]; foreach (int[] sequence in ChanSymbToTribit) { SyncSymbolCounter = 0; scrambler.Init(); for (int i = 0; i < 4; i++) { foreach (int tribit in sequence) { Enc.Process(tribit, scrambler.DataNext(), SCRAMBLE_MASK, out symb75[SyncSymbolCounter]); SyncSymbolCounter++; } } SymbDetector.AddTarget(symb75); } }
public void Process(CNTRL_MSG controlParam, IQ inData) { if (controlParam == CNTRL_MSG.DATA_IN) { if (PutIndex < DataSize) { DataBuffer[PutIndex] = inData; } else if ((PutIndex % DecimFactor) == SlicingIndex) { DataOut.Process(inData); } PutIndex++; if (PutIndex == DataSize) { CalculateCorrections(); foreach (IQ IQData in OutputData) { DataOut.Process(IQData); } } } }
public override void Init() { SlicingIndex = 0; PutIndex = new Index(0, DataSize); PutCounter = 0; Array.Clear(DataBuffer, 0, DataSize); OutputData.Clear(); SkipSample = false; FrameEnergy = IQ.ZERO; GNDAI = new float[DecimFactor]; GDDI = new float[DecimFactor];; QAMLDI = new float[DecimFactor]; ZDDI = new float[DecimFactor]; CorrI = new float[DecimFactor]; GNDAQ = new float[DecimFactor]; GDDQ = new float[DecimFactor]; QAMLDQ = new float[DecimFactor]; ZDDQ = new float[DecimFactor]; CorrQ = new float[DecimFactor]; }
/// <summary> /// Process supplied I and Q components and apply them to the current frequency. /// </summary> /// <param name="data">IQ components of Quadrature signal.</param> /// <returns>true - if I and Q were placed and we still can continue. false - if all frequencies are done and we have to read the buffer.</returns> public int Process(IQ data) { PrepareOutputBuffer(OutputBuffer, 0); // encode the I bit fI[CurrFreqIndex].Interpolate(data.I, TempModBuffer); gI[CurrFreqIndex].GenerateAdd(TempModBuffer, OutputBuffer); // Modulate a carrier with symbol // encode the Q bit fQ[CurrFreqIndex].Interpolate(data.Q, TempModBuffer); gQ[CurrFreqIndex].GenerateAdd(TempModBuffer, OutputBuffer); // Modulate a carrier with symbol GeneratorsDone[CurrFreqIndex] = true; // Advance current frequency index and check for wrap-around CurrFreqIndex++; if (CurrFreqIndex >= NFREQ) { CurrFreqIndex = 0; } if (GeneratorsDone[CurrFreqIndex]) { OutputData.AddRange(OutputBuffer); } return(OutputData.Count); }
public float DeltaCosR(IQ prevIQ) { return((prevIQ.R > 0) ? (Q * prevIQ.Q + I * prevIQ.I) / prevIQ.R2 : 0); }
public float DeltaSinR(IQ prevIQ) { return((prevIQ.R > 0) ? (Q * prevIQ.I - I * prevIQ.Q) / prevIQ.R2 : 0); }
public float DeltaCos(IQ prevIQ) { return(I * prevIQ.I + Q * prevIQ.Q); }
public float DeltaSin(IQ prevIQ) { return(Q * prevIQ.I - I * prevIQ.Q); }
static void Combine(ref IQ originalData, IQ newData) { originalData = originalData + newData; }
/// <summary> /// Process I-Q sample in correlator and check if correlation maximum was detected /// </summary> /// <param name="data">IQ sample</param> /// <returns><typeparamref name="true"/> if we should continue to put more data.</returns> public int Process(IQ data) { NumSymbols++; // Save the data Data[CurrentIndex] = data; if (CorrelationMaxFound) { CurrentIndex++; if (CurrentIndex >= DataLength) { CurrentIndex = 0; } CorrelationPosition++; return(CorrelationPosition); } if (CorrelationType == CORR_TYPE.NONE) { CurrentIndex++; if (CurrentIndex >= DataLength) { CurrentIndex = 0; } if (this.NumSymbols >= this.MinNumSymbols) { CorrelationMaxFound = true; CorrelationPosition = this.MinNumSymbols; CalculateCorrections(); } return(CorrelationPosition); } float newVal; float newVal1 = 0; if (CorrelationType == CORR_TYPE.DELTASIN_DIFF) { newVal = data.DeltaSin(PrevIQ); } else if (CorrelationType == CORR_TYPE.DELTACOS_DIFF) { newVal = data.DeltaCos(PrevIQ); } else if (CorrelationType == CORR_TYPE.AMPLITUDE_DIFF) { newVal = (data - PrevIQ).R2; } else if (CorrelationType == CORR_TYPE.AMPLITUDE) { newVal = data.R2; } else if (CorrelationType == CORR_TYPE.I) { newVal = data.I; } else if (CorrelationType == CORR_TYPE.Q) { newVal = data.Q; } else if (CorrelationType == CORR_TYPE.PHASE_DIFF) { newVal = data.Phase - PrevIQ.Phase; } else if (CorrelationType == CORR_TYPE.DELTA_DIFF) { newVal = data.DeltaSin(PrevIQ); newVal1 = data.DeltaCos(PrevIQ); } else if (CorrelationType == CORR_TYPE.IQ) { newVal = data.I; newVal1 = data.Q; } else { newVal = newVal1 = 0; } IQDiff[CurrentIndex] = newVal; IQDiff1[CurrentIndex] = newVal1; PrevIQ = data; CurrentIndex++; if (CurrentIndex >= DataLength) { CurrentIndex = 0; } // Split the correlation calculation in two // to take into account the index wrap-around int Start1, Start2; int End1; Start1 = CurrentIndex - TargetLength; // Start Correlation calculation // N-symbols before End1 = CurrentIndex; // End it at the last sample Start2 = DataLength; // initially disable a second run if (Start1 < 0) // If pointer goes outside array bounds, then... { Start1 += DataLength; // Bring it back... End1 = DataLength; // End first run at the end of the array Start2 = 0; // Start second run from the beginning of the array } float Symbol0 = IQDiff[Start1]; // We use it to get the energy of the first symbol float Symbol1 = IQDiff1[Start1]; // We use it to get the energy of the first symbol DataEnergy += (newVal * newVal) + (newVal1 * newVal1); DataEnergy -= PrevDataEnergy; PrevDataEnergy = Symbol0 * Symbol0 + Symbol1 * Symbol1; // If not enough symbols collected - do not do correlation yet if (this.NumSymbols < this.MinNumSymbols) { return(0); } // Now we can do correlation run Correlation = 0; int targetIdx = 0; // Target array Index for (int i = Start1; i < End1; i++) { Correlation += TargetIQDiff[targetIdx++] * IQDiff[i]; } // Do second calculation loop if wrap-around was detected for (int i = Start2; i < CurrentIndex; i++) { Correlation += TargetIQDiff[targetIdx++] * IQDiff[i]; } if ((CorrelationType == CORR_TYPE.DELTA_DIFF) || (CorrelationType == CORR_TYPE.IQ)) { targetIdx = 0; // Target array Index for (int i = Start1; i < End1; i++) { Correlation += TargetIQDiff1[targetIdx++] * IQDiff1[i]; } // Do second calculation loop if wrap-around was detected for (int i = Start2; i < CurrentIndex; i++) { Correlation += TargetIQDiff1[targetIdx++] * IQDiff1[i]; } } // Check if the newly calculated correlation is the best one... float AbsCorrelation = Math.Abs(Correlation); if (AbsCorrelation > CorrMaxValue) { PrevMaxValue = CorrMaxValue; CorrMaxValue = AbsCorrelation; CorrMaxEnergy = DataEnergy; CorrMaxIndex = Start1; } else { // Adjust the average by adding the new one CorrAverage += Correlation; CorrEnergyAverage += AbsCorrelation; } if (IsMaxCorrelation) { CorrelationMaxFound = true; CorrelationPosition = IndexFromMax; CalculateCorrections(); } return(CorrelationPosition); }
public void Run() { #region "Test of Frequency Detector" { IQModulator iqm = new IQModulator(1200 + 13, 1200 + 13, 1, 7200, 36, null); iqm.Init(); for (int i = 0; i < 243; i++) { iqm.Process(IQ.UNITY); } iqm.Finish(); float[] fa = new float[iqm.Count]; iqm.GetData(fa); IQDetector iqd = new IQDetector(1200, 7200, 36, 0, 1, -10, false); iqd.Init(); iqd.Process(fa, 0, fa.Length); } #endregion #region Test of the FFT Modulator and Demodulator { float BlockSize; BlockSize = ((7200.0f / MILSTD188_110B_39.SYMBOLRATE) + 0.5f); float[] Filter = new float[(int)BlockSize]; for (int i = 0; i < Filter.Length; i++) { Filter[i] = 2.0f / Filter.Length; } OFDMFFTModulator fftm = new OFDMFFTModulator(MILSTD188_110B_39.CARRIER_FREQ_LO, MILSTD188_110B_39.CARRIER_FREQ_HI, 39, 7200, MILSTD188_110B_39.SYMBOLRATE); OFDMFFTDemodulator fftd = new OFDMFFTDemodulator(MILSTD188_110B_39.CARRIER_FREQ_LO, MILSTD188_110B_39.CARRIER_FREQ_HI, 39, 7200, MILSTD188_110B_39.SYMBOLRATE); IQModulator regularm = new IQModulator(MILSTD188_110B_39.CARRIER_FREQ_LO, MILSTD188_110B_39.CARRIER_FREQ_HI, 39, 7200, MILSTD188_110B_39.SYMBOLRATE, null); IQDemodulator regulard = new IQDemodulator(MILSTD188_110B_39.CARRIER_FREQ_LO, MILSTD188_110B_39.CARRIER_FREQ_HI, 39, 7200, MILSTD188_110B_39.SYMBOLRATE, Filter); OFDMDemodulator ofdmd = new OFDMDemodulator(MILSTD188_110B_39.CARRIER_FREQ_LO, MILSTD188_110B_39.CARRIER_FREQ_HI, 39, 7200, MILSTD188_110B_39.SYMBOLRATE, 64f / 81f); IQDetector regdet = new IQDetector(MILSTD188_110B_39.CARRIER_FREQ_LO, 7200, MILSTD188_110B_39.SYMBOLRATE); fftm.Init(); fftd.Init(); ofdmd.Init(); regulard.Init(); fftm[0].Process(new IQ(1, 0)); fftm[1].Process(new IQ(0.7071f, 0.7071f)); fftm[2].Process(new IQ(0, -1)); fftm[3].Process(new IQ(-0.7071f, -0.7071f)); fftm[4].Process(new IQ(0, 1)); fftm[12].Process(new IQ(0, -1)); fftm[22].Process(new IQ(-1, 0)); fftm[0].Process(new IQ(-1, 0)); fftm[1].Process(new IQ(-0.7071f, -0.7071f)); fftm[2].Process(new IQ(0, 1)); fftm[3].Process(new IQ(0.7071f, -0.7071f)); fftm[4].Process(new IQ(0, -1)); fftm[12].Process(new IQ(-1, 0)); fftm[22].Process(new IQ(0, -1)); fftm[0].Process(new IQ(0, -1)); fftm[1].Process(new IQ(-0.7071f, 0.7071f)); fftm[2].Process(new IQ(-0.7071f, -0.7071f)); fftm[3].Process(new IQ(0, 1)); fftm[4].Process(new IQ(0.7071f, 0.7071f)); fftm[12].Process(new IQ(0.7071f, -0.7071f)); fftm[22].Process(new IQ(0, -1)); fftm[0].Process(new IQ(1, 0)); fftm[1].Process(new IQ(0.7071f, 0.7071f)); fftm[2].Process(new IQ(0, -1)); fftm[3].Process(new IQ(-0.7071f, -0.7071f)); fftm[4].Process(new IQ(0, 1)); fftm[12].Process(new IQ(0, -1)); fftm[22].Process(new IQ(-1, 0)); fftm.Finish(); regularm[0].Process(new IQ(1, 0)); regularm[1].Process(new IQ(0.7071f, 0.7071f)); regularm[2].Process(new IQ(0, -1)); regularm[3].Process(new IQ(-0.7071f, -0.7071f)); regularm[4].Process(new IQ(0, 1)); regularm[12].Process(new IQ(0, -1)); regularm[22].Process(new IQ(-1, 0)); regularm.Finish(); float[] ffr = new float[fftm.Count]; OFDMSync os = new OFDMSync((int)BlockSize); fftm.GetData(ffr); fftd.Process(ffr, 0, ffr.Length); regulard.Process(ffr, 0, ffr.Length); ofdmd.Process(ffr, 0, ffr.Length); regdet.Process(ffr, 0, ffr.Length); IQ[] ffriq = new IQ[ffr.Length]; for (int i = 0; i < ffriq.Length; i++) { ffriq[i] = new IQ(ffr[i], 0); } int SymbOffset = 18; os.Process(ffriq, SymbOffset, ffriq.Length - SymbOffset); regularm.GetData(ffr); fftd.Init(); ofdmd.Init(); regulard.Init(); fftd.Process(ffr, 0, ffr.Length); regulard.Process(ffr, 0, ffr.Length); ofdmd.Process(ffr, 0, ffr.Length); } #endregion #region Test of Generator and Quad double delta = (2 * Math.PI * 500) / 8000; double initialphase = 0.123456; // Generator tgSin = new Generator(); // Generator tgCos = new Generator(); // tgSin.Init(500, 8000, (float)(0 + initialphase)); // tgCos.Init(500, 8000, (float)(Math.PI / 2 + initialphase)); Quad tq = new Quad(500, 8000, initialphase); float maxError = 0; float tgdataSin; float tgdataCos; IQ tqData; for (int i = 0; i < 100000; i++) { float idealdataSin = (float)Math.Sin(initialphase + i * delta); float idealdataCos = (float)Math.Cos(initialphase + i * delta); // tqData = tq.Value; tq.Process(1, out tqData); tgdataSin = tqData.I; tgdataCos = tqData.Q; // tgSin.Process(1, out tgdataSin); // tgCos.Process(1, out tgdataCos); float error = Math.Abs(tgdataCos - idealdataCos); error += Math.Abs(tgdataSin - idealdataSin); if (error > maxError) { maxError = error; } } #endregion #region Test of Quad Modulators/Demodulators { IQModulator tm = new IQModulator(1000, 1000, 1, 8000, 250, null); IQEncoder te = new IQEncoder(2, Constellation.BitsToPhase_39, Constellation.IQTable_QPSK45, EncodingType.DIFF_IQ); OFDMDemodulator tt = new OFDMDemodulator(1000, 1000, 1, 8000, 250, 1); IQDecoder td = new IQDecoder(2, Constellation.BitsToPhase_39, Constellation.IQTable_QPSK45, EncodingType.DIFF_IQ); int[] EncData = new int[] { 0, 1, 2, 3, 0, 0, 1, 1, 2, 2, 3, 3, 2, 1, 0 }; IQ IQData; // Send reference signal tm.Process(IQ.UNITY); foreach (int symbol in EncData) { te.Process(symbol, out IQData); tm.Process(IQData); } Samples outputTestSamples = new Samples(@"C:\TestMod.raw", 1.0f); float[] TestSamplesOut = new float[tm.Count]; tm.GetData(TestSamplesOut); outputTestSamples.ToByte(TestSamplesOut); outputTestSamples.Close(); tt.Process(TestSamplesOut, 0, TestSamplesOut.Length); List <int> TestOut = new List <int>(); int Symb; while (tt.Count > 0) { td.Process(tt.GetData(), out Symb); TestOut.Add(Symb); } TestOut.Clear(); } #endregion #region Test SoftConvolutional Encoder { int[] Poly = { 0x7, 0x5, 0x3, 0x6 }; int[] PolyMIL = { 0x5B, 0x79 }; int[] input = { 0xF7, 0x45, 0x12, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0xFF, 0xA5 }; BitArray sba = new BitArray(8); sba.Add(input); ConvEncoder sce = new ConvEncoder(ConvEncoderType.TailBiting_Head, 2, 7, PolyMIL, 0x7, 4); byte[] ddd = new byte[sba.BitsCount]; sba.GetData(ddd); sce.Process(ddd, 0, ddd.Length); sce.Finish(); ddd = new byte[sce.Count]; sce.GetData(ddd); // ddd has all databits VitDecoder svd = new VitDecoder(ConvEncoderType.TailBiting_Head, 2, 7, PolyMIL, 0x7, 4, 3); svd.Process(ddd, 0, ddd.Length); svd.Finish(); ddd = new byte[svd.Count]; svd.GetData(ddd); BitArray res = new BitArray(8); res.Add(ddd); int[] ttt = new int[res.SymbolsCount]; res.GetData(ttt); } #endregion // Test of the 39-tone codec MILSTD188_110B_39 m = new MILSTD188_110B_39(MILSTD_188.Mode.D_2400S, 7200, 7200, null, null); BitArray ba = new BitArray(12); for (int i = 0; i < 800; i++) { ba.Add(i); } byte[] da = new byte[ba.BitsCount]; ba.GetData(da); m.Tx.Start(); m.Tx.Process(da, 0, da.Length); m.Tx.Finish(); Samples outputSamples = new Samples(@"C:\test39.raw", 1.5f); float[] SamplesOut = new float[m.Tx.SampleCount]; m.Tx.GetData(SamplesOut, 0); outputSamples.ToByte(SamplesOut); outputSamples.Close(); string FileName = @"C:\test39"; Samples InputSamples = new Samples(FileName + ".raw"); float[] SamplesIn = new float[100]; List <float> Test39Samples = new List <float>(); int n; do { n = InputSamples.ToFloat(SamplesIn); for (int i = 0; i < n; i++) { Test39Samples.Add(SamplesIn[i]); } } while (n > 0); InputSamples.Close(); m.Rx.pd1.Init(); m.Rx.pd2.Init(0); // foreach (float sample in SamplesOut) // { // m.Rx.pd3.Process(sample); // } foreach (float sample in Test39Samples) { if (!m.Rx.pd1.IsSyncFound) { m.Rx.pd1.Process(sample); if (m.Rx.pd1.IsSyncFound) { m.Rx.pd2.Init(m.Rx.pd1.FrequencyOffset); } } else { if (!m.Rx.pd2.IsSyncFound) { m.Rx.pd2.Process(sample); if (m.Rx.pd2.IsErrorFound) { m.Rx.pd2.Init(0); m.Rx.pd1.Init(); } if (m.Rx.pd2.IsSyncFound) { m.Rx.pd3.Init(m.Rx.pd2.FrequencyOffset); } } else { m.Rx.pd3.Process(sample); } } } List <byte> RegenData = new List <byte>(); System.IO.FileStream File = System.IO.File.Open(FileName + ".asc", System.IO.FileMode.Create); while (m.Rx.pd3.Count > 0) { byte dbyte = m.Rx.pd3.GetData(); RegenData.Add(dbyte); File.WriteByte((byte)(dbyte + 0x30)); } File.Close(); da = new byte[RegenData.Count]; IQ[] iqda = new IQ[m.Rx.pd3.RawCount]; RegenData.CopyTo(da); m.Rx.pd3.GetRawData(iqda); m = new MILSTD188_110B_39(MILSTD_188.Mode.D_2400S, 7200, 7200, null, null); m.Tx.Start(); m.Tx.ProcessRaw(da, 0, da.Length); // m.Tx.ProcessRaw(iqda, 0, iqda.Length); m.Tx.Finish(); outputSamples = new Samples(FileName + "-regen.raw", 1.0f); SamplesOut = new float[m.Tx.SampleCount]; m.Tx.GetData(SamplesOut, 0); outputSamples.ToByte(SamplesOut); outputSamples.Close(); #region Test of Complex data { IQ a = new IQ(1, 2); IQ b = new IQ(3, 4); IQ c = new IQ(5, 6); IQ f = a + b; f = a * c; f = f - a; f = a / b; f -= b; } #endregion #region Test of Serial Class SerialData tx = new SerialData(7, 1, 1, SerialData.Parity.N); SerialData rx = new SerialData(7, 1, 1, SerialData.Parity.N); for (int i = 0; i < 256; i++) { tx.PutSymbol(i); } byte[] rdd = new byte[10000]; int nbits = tx.GetData(rdd); rx.PutData(rdd, 0, nbits); int[] rsymb = new int[256]; rx.GetData(rsymb); #endregion #region Test Convolutional Encoder { int[] Poly = { 0x7, 0x5, 0x3, 0x6 }; int[] PolyMIL = { 0x5B, 0x79 }; // OldConvEncoder ce = new OldConvEncoder(2, 7, PolyMIL, 0x7, 4, ConvEncoderType.TailBiting_Head); byte[] input = { 0xF7, 0x45, 0x12, 0x33, 0x44, 0x55, 0x66, 0x77, 0x88, 0x99, 0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff, 0x00, 0x11, 0xFF, 0xA5 }; byte[] output = new byte[input.Length * 4]; byte[] res = new byte[input.Length]; int iBits = input.Length * 8; // int nBits = ce.Process(input, 0, output, 0, iBits); // Test Convolutional decoder output[0] ^= 0x08; output[2] ^= 0x04; output[5] ^= 0x01; output[7] ^= 0x20; output[10] ^= 0x40; output[13] ^= 0x10; output[15] ^= 0x80; // OldVitDecoder vd = new OldVitDecoder(2, 7, PolyMIL, 0x7, 4, 6, ConvEncoderType.TailBiting_Head); int[] sdd = new int[200]; // int qBits = vd.Quantize(output, sdd, nBits); // int rBits = vd.Process(output, res, nBits); } #endregion #region Test of the IQEncoder and IQDecoder int[] symb = { 0, 1, 2, 3, 4, 5, 6, 7, 0, 1, 1, 2, 2, 3, 3, 4, 4, 5, 5, 6, 6, 7, 7, 0, 3, 5, 7, 4, 3, 2, 1 }; IQEncoder e = new IQEncoder(2, Constellation.Table_1_to_1, Constellation.ITable_QPSK, Constellation.QTable_QPSK, EncodingType.NON_DIFF); IQDecoder d = new IQDecoder(2, Constellation.Table_1_to_1, Constellation.ITable_QPSK, Constellation.QTable_QPSK, EncodingType.NON_DIFF); IQ iqs; int r; for (int i = 0; i < symb.Length; i++) { e.Process(symb[i], out iqs); d.Process(iqs, out r); } #endregion float[] fCoeff = Filters.Fill(Filters.rrc_180, 2); int[] datadecoded = new int[300]; int[] syncseq = { 0, 1, 3, 0, 1, 3, 1, 2, 0, 7, 7, 4, 4, 6, 0, 0, 1, 3, 0, 1, 3, 1, 2, 0, 7, 7, 4, 4, 5, 0, }; IQ[] syncIQ = new IQ[syncseq.Length]; const float SamplingFreq = 24000; const float SymbolFreq = 2400; const float CarrierFreq = 1800; const float FreqOffset = 0; const float PhaseOffset = 0; const int GrpDelay = 0; int DFac = (int)(SamplingFreq / SymbolFreq); // Let's start with the encoder and decoder e = new IQEncoder(3, Constellation.Table_1_to_1, Constellation.IQTable_8PSK, EncodingType.NON_DIFF); d = new IQDecoder(3, Constellation.Table_1_to_1, Constellation.IQTable_8PSK, EncodingType.NON_DIFF); // Create Modulator IQModulator mod = new IQModulator(CarrierFreq + FreqOffset, CarrierFreq + FreqOffset, 1, SamplingFreq, SymbolFreq, fCoeff); // Add offset mod.Phase = PhaseOffset; // Create Demodulator IQDemodulator dem = new IQDemodulator(CarrierFreq, CarrierFreq, 1, SamplingFreq, SymbolFreq, fCoeff); // Now correlator to catch the symbol pattern and sync on it Correlator corr = new Correlator(CORR_TYPE.DELTA_DIFF, 70, 30, 15, 0.5f, 10.0f, 5.0f); e.Init(); // Fill the sync pattern for (int i = 0; i < syncseq.Length; i++) { e.Process(syncseq[i], out syncIQ[i]); } corr.AddTarget(syncIQ); IQ sym; //Encode and Modulate - result goes into incomingData[] array e.Init(); for (int i = 0; i < datastream.Length; i++) { e.Process(datastream[i], out sym); mod.Process(sym, incomingData, i * DFac + GrpDelay); } // Output 20 more ZERO symbols to flush modulator sym = IQ.ZERO; for (int i = datastream.Length; i < datastream.Length + 20; i++) { mod.Process(sym, incomingData, i * DFac + GrpDelay); } //------------------ Now start processing the data on the receiver side IQ[] demodArray = new IQ[300]; // start feeding the data into the demodulator - turn symbolsync search first int startIdx = 0; int outIdx = 0; // feed the data until we get a symbol sync dem.Init(); dem.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, 100); while (!dem.IsSyncReady) { dem.Process(incomingData, startIdx, DFac); startIdx += DFac; } // Feed demodulated data into correlator and search for sync pattern corr.Init(); corr.StartCorrectionProcess(); for (int i = 0; !corr.IsSyncReady; i++, startIdx += DFac) { int nSymb = dem.Process(incomingData, startIdx, DFac); while (nSymb-- > 0) { IQ iqData = dem.GetData(); demodArray[outIdx++] = iqData; corr.Process(iqData); } } dem.RotateCorrection = corr.RotateCorrection; dem.FrequencyCorrection = corr.FrequencyCorrection; corr.GetLastData(corr.CorrelationMaxIndex, demodArray, corr.CorrelationMaxIndex); outIdx = corr.CorrelationMaxIndex; while (startIdx < (incomingData.Length - DFac)) { int nSym = dem.Process(incomingData, startIdx, DFac); while (nSym-- > 0) { demodArray[outIdx++] = dem.GetData(); } startIdx += DFac; } d.Init(); d.StartCorrectionProcess(300); int iSymb; for (int i = 0; i < demodArray.Length; i++) { d.Process(demodArray[i], out iSymb); datadecoded[i] = iSymb; } demodArray.Initialize(); #region Test of Integrate and Dump decoder { int[] teststring = { 0, 4, 0, 4, 0, 4, 0, 4, 4 }; int[] datadecoded1 = new int[300]; const float SYMBOL_TIME = 0.0225f; // Every symbol lasts for 22.5ms const float SYMBOLRATE = 1 / SYMBOL_TIME; // Symbol rate will be 44.44444444 Hz const float SamplingFreq1 = 8000; const float SymbolFreq1 = SYMBOLRATE; const float CarrierFreq1 = 1800; const float FreqOffset1 = 0; const float PhaseOffset1 = 0; const int GrpDelay1 = 0; int DFac1 = (int)(SamplingFreq1 / SymbolFreq1); // Let's start with the encoder and decoder e = new IQEncoder(3, Constellation.Table_1_to_1, Constellation.IQTable_8PSK, EncodingType.NON_DIFF); d = new IQDecoder(3, Constellation.Table_1_to_1, Constellation.IQTable_8PSK, EncodingType.NON_DIFF); // Create Modulator IQModulator mod1 = new IQModulator(CarrierFreq1 + FreqOffset1, CarrierFreq1 + FreqOffset1, 1, SamplingFreq1, SymbolFreq1, null); // Add offset mod1.Phase = PhaseOffset1; // Create Demodulator Quad dem1 = new Quad(CarrierFreq1, SamplingFreq1); e.Init(); IQ sym1; //Encode and Modulate - result goes into incomingData[] array e.Init(); Array.Clear(incomingData, 0, incomingData.Length); for (int i = 0; i < teststring.Length; i++) { e.Process(teststring[i], out sym1); mod1.Process(sym1, incomingData, i * DFac1 + GrpDelay1); } // Output 20 more ZERO symbols to flush modulator //------------------ Now start processing the data on the receiver side IQ[] demodArray1 = new IQ[300]; IntegrateAndDump IandD = new IntegrateAndDump(DFac1); // IandD.Offset = DFac1 / 2; // start feeding the data into the demodulator int[] decodedData = new int[64]; int outIdx1 = 0; foreach (float sample in incomingData) { dem1.Process(sample, out sym1); IandD.Process(sym1); while (IandD.Count > 0) { sym1 = IandD.GetData(); demodArray1[outIdx1] = sym1; d.Process(sym1, out decodedData[outIdx1++]); } } } #endregion #region Decimator Testing /* Testing of the Decimator */ int K = 50; int SAMP = 200; int DEC = 10; float[] Arr = new float[K]; float[] Samp = new float[SAMP]; for (int i = 0; i < Arr.Length; i++) { Arr[i] = 1; } for (int i = 0; i < Samp.Length; i++) { Samp[i] = i / 100.0f; } FIR fff = new FIR(Arr, DEC); float[] rrr = new float[Samp.Length / DEC]; float[] mmm = { 1, 2, 3 }; float[] mmmm = { 1, 2, 3, 4, 5, 6, 7 }; fff.Decimate(mmm, rrr); fff.Decimate(mmm, rrr); fff.Decimate(mmmm, rrr); fff.Decimate(Samp, rrr); fff.Decimate(mmmm, rrr); fff.Decimate(mmm, rrr); fff.Decimate(mmmm, rrr); fff.Decimate(mmm, rrr); fff.Decimate(mmmm, rrr); fff.Decimate(mmmm, rrr); fff.Decimate(mmmm, rrr); #endregion #region // Test EOM detector BitCorrelator bc = new BitCorrelator(); int FlipEOM = MILSTD_188.MSBFirst(MILSTD_188.EOM); bc.AddTarget(FlipEOM, 32); BitArray testBA = new BitArray(8); testBA.Add(0x12); testBA.Add(0x15); testBA.Add((FlipEOM >> 0) & 0x00FF); testBA.Add((FlipEOM >> 8) & 0x00FF); testBA.Add((FlipEOM >> 16) & 0x00FF); testBA.Add((FlipEOM >> 24) & 0x00FF); testBA.Add(0xFF); testBA.Add(0x05); byte[] testArray = new byte[testBA.BitsCount]; testBA.GetData(testArray); bc.Process(testArray, 0, testArray.Length); #endregion // etab [] Tab = new etab[] //{ // {4, 0x13, 1, 1, 4, 8, 10 }, // RS(7,3) on GF(15) // {4, 0x13, 1, 1, 4, 1, 10 }, // RS(14,10) on GF(15) // {4, 0x13, 1, 1, 4, 9, 10 }, // RS(6,2) on GF(15) // {4, 0x13, 1, 1, 4, 10, 10 }, // RS(5,1) on GF(15) // {2, 0x7, 1, 1, 1, 0, 10 }, // {3, 0xb, 1, 1, 2, 0, 10 }, // {4, 0x13, 1, 1, 4, 0, 10 }, // {5, 0x25, 1, 1, 6, 0, 10 }, // {6, 0x43, 1, 1, 8, 0, 10 }, // {7, 0x89, 1, 1, 10, 0, 10 }, // {8, 0x11d, 1, 1, 32, 0, 10 }, // {8, 0x187, 112,11, 32, 0, 10 }, /* Duplicates CCSDS codec */ // {9, 0x211, 1, 1, 32, 0, 10 }, // {10,0x409, 1, 1, 32, 0, 10 }, // {11,0x805, 1, 1, 32, 0, 10 }, // {12,0x1053, 1, 1, 32, 0, 5 }, // {13,0x201b, 1, 1, 32, 0, 2 }, // {14,0x4443, 1, 1, 32, 0, 1 }, // {15,0x8003, 1, 1, 32, 0, 1 }, // {16,0x1100b, 1, 1, 32, 0, 1 }, // {0, 0, 0, 0, 0}, //}; //----------------------------------------------------------------------------------------------------------------------------------- #region Test of the bit rearranger BitGroup[] D2400_old = { new BitGroup(0 * 78, 64) }; BitGroup[] D1200_old = { new BitGroup(0 * 64, 64), new BitGroup(0 * 63, 14) }; BitGroup[] D600_old = { new BitGroup(0 * 32, 32), new BitGroup(0 * 32, 32), new BitGroup(0, 14) }; BitGroup[] D300_old = { new BitGroup(0 * 16, 16), new BitGroup(0 * 16, 16), new BitGroup(0 * 16, 16), new BitGroup(0 * 16, 16), new BitGroup(0 * 0, 14) }; BitGroup[] D150_old = { new BitGroup(0 * 8, 8), new BitGroup(0 * 8, 8), new BitGroup(0 * 8, 8), new BitGroup(0 * 8, 8), new BitGroup(0 * 8, 8), new BitGroup(0 * 8, 8), new BitGroup(0 * 8, 8), new BitGroup(0 * 8, 8), new BitGroup(0 * 0, 8), new BitGroup(0 * 8, 6) }; BitGroup[] D75_old = { new BitGroup(0 * 0, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(0 * 4, 2) }; BitGroup[] D2400_new = { new BitGroup(0 * 78, 64) }; BitGroup[] D1200_new = { new BitGroup(0 * 64, 64), new BitGroup(0 * 63, 14) }; BitGroup[] D600_new = { new BitGroup(0 * 32, 32), new BitGroup(8 * 32, 32), new BitGroup(0, 14) }; BitGroup[] D300_new = { new BitGroup(0 * 16, 16), new BitGroup(4 * 16, 16), new BitGroup(8 * 16, 16), new BitGroup(12 * 16, 16), new BitGroup(0 * 0, 14) }; BitGroup[] D150_new = { new BitGroup(0 * 8, 8), new BitGroup(2 * 8, 8), new BitGroup(4 * 8, 8), new BitGroup(6 * 8, 8), new BitGroup(8 * 8, 8), new BitGroup(10 * 8, 8), new BitGroup(12 * 8, 8), new BitGroup(14 * 8, 8), new BitGroup(0 * 0, 8), new BitGroup(2 * 8, 6) }; BitGroup[] D75_new = { new BitGroup(0 * 0, 4), new BitGroup(1 * 4, 4), new BitGroup(2 * 4, 4), new BitGroup(3 * 4, 4), new BitGroup(4 * 4, 4), new BitGroup(5 * 4, 4), new BitGroup(6 * 4, 4), new BitGroup(7 * 4, 4), new BitGroup(8 * 4, 4), new BitGroup(9 * 4, 4), new BitGroup(10 * 4, 4), new BitGroup(11 * 4, 4), new BitGroup(12 * 4, 4), new BitGroup(13 * 4, 4), new BitGroup(14 * 4, 4), new BitGroup(15 * 4, 4), new BitGroup(0 * 4, 4), new BitGroup(1 * 4, 4), new BitGroup(2 * 4, 4), new BitGroup(3 * 4, 2) }; DataSpreader <byte> dsp = new DataSpreader <byte>(4, D75_new); DataCombiner dcb = new DataCombiner(4, D75_new); dsp.Init(); dcb.Init(); for (int idx = 0; idx < 100; idx++) { dsp.Process((byte)idx); } byte[] od = new byte[dsp.Count]; dsp.GetData(od, 0); foreach (byte b in od) { dcb.Process(b); } #endregion //----------------------------------------------------------------------------------------------------------------------------------- #region Test of the SoftInterleaver // Interleaver_188_110B_39 il = new Interleaver_188_110B_39(18, 12, 4, 7, 3); Interleaver_188_110B_39 il = new Interleaver_188_110B_39(18, 12, 4, 7, 3); il.Init(); int ii = 0; il.Init(); while (!il.IsDataReady) { int Data = ii++; for (int i = 0; (i < 4); i++) { il.ProcessEncode((byte)(Data & 0x0001)); Data >>= 1; } } byte[] OutData = new byte[il.Count]; il.GetData(OutData, 0); Queue <byte> chann = new Queue <byte>(); foreach (byte b in OutData) { chann.Enqueue(b); } il.Init(); while (chann.Count > 0) { il.ProcessDecode(chann.Dequeue()); } while (!il.IsDataReady) { il.ProcessDecode(0); } OutData = new byte[il.Count]; il.GetData(OutData, 0); #endregion ReedSolomon rs = new ReedSolomon(); rs.Init(4, 0x13, 1, 1, 4, 8); int[] data = new int[7]; data[0] = 0x08; data[1] = 0x03; data[2] = 0x04; int[] parity, eras; eras = new int[15]; parity = new int[15]; rs.Encode(data, parity); Array.Copy(parity, 0, data, 3, 4); data[0] = 0x00; data[1] = 0x00; data[2] = 0x00; // data[3] = 0x00; eras[0] = 0; eras[1] = 1; eras[2] = 2; eras[3] = 3; int nerr = rs.Decode(data, eras, 3); LFSR__188_110B_39 lsr = new LFSR__188_110B_39(9, 0x0116); lsr.Init(0x01); int ff = 0; while ((lsr.Value & 0x1FF) != 0x1FF) { ff++; lsr.Shift(); } int rr = (int)lsr.CurrentBit; int[] requiredoffsets = { 252, 256, 260, 264, 267, 268, 272, 280, 288, 300, 308, 340, 356, 376, 384, 385, 392, 396, 400, 408, 416, 420, 432, 440, 444, 448, 464, 480, 484, 497, 504, 512, 520, 528 }; int[] calculatedseeds = new int[requiredoffsets.Length]; int[] mem = new int[511]; int el = 0; int q = 0; el = 0; lsr.Init(0x1FF); do { lsr.Shift(); mem[el++] = lsr.Value & 0x1FF; } while ((lsr.Value & 0x1FF) != 0x1FF); foreach (int req in requiredoffsets) { el = 510 - req; if (el < 0) { el += 511; } calculatedseeds[q++] = mem[el] & 0x1FF; } q = 0; foreach (int load in calculatedseeds) { lsr.Init(load); lsr.Shift(requiredoffsets[q++]); el = (int)lsr.Value; rr = (int)lsr.CurrentBit; } int[] AllValues = new int[512]; lsr.Init(0x1FF); ii = 0; for (ii = 0; ii < 0x200; ii++) { AllValues[ii] = lsr.Value & 0x1FF; lsr.Shift(); } // Now calculate the seed value differently int[] newseeds = new int[requiredoffsets.Length]; ii = 0; foreach (int req in requiredoffsets) { int ShiftVal = 0x200 - req - 1; if (ShiftVal < 0) { ShiftVal += 0x200 - 1; } lsr.Init(0x1FF); lsr.Shift(ShiftVal); newseeds[ii++] = lsr.Value & 0x1FF; } }
public int SendSyncPreamble(bool extendedPreamble, bool useDopplerTone) { int Part1Length = extendedPreamble ? 58: 14; int Part2Length = extendedPreamble ? 27: 8; int Part3Length = extendedPreamble ? 12: 1; int nSamp; IQ Symb; int DataSize = Math.Max(Part1Length, Part2Length); DataSize = Math.Max(DataSize, Part3Length); float[] ModDataBuff = new float[InputBlockSize * DataSize]; float[] PhasesInRads = new float[NUM_FREQ]; for (int i = 0; i < NUM_FREQ; i++) { PhasesInRads[i] = (float)(InitialPhases[i] * (2 * Math.PI / 360)); } //-------------------------------------------------- // Part one of the preamble //-------------------------------------------------- PreambleModulator.Init(); PreambleModulator.FrequencyOffset = FREQ_OFFSET; Array.Clear(ModDataBuff, 0, ModDataBuff.Length); Symb = IQ.UNITY * AMPLITUDE1 * NORM_AMP; for (int i = 0; i < Part1Length; i++) { PreambleModulator[787.5f].Process(Symb, ModDataBuff, i * InputBlockSize); PreambleModulator[1462.5f].Process(Symb, ModDataBuff, i * InputBlockSize); PreambleModulator[2137.5f].Process(Symb, ModDataBuff, i * InputBlockSize); PreambleModulator[2812.5f].Process(Symb, ModDataBuff, i * InputBlockSize); PreambleModulator.Finish(ModDataBuff, i * InputBlockSize); } nSamp = OutputFilter.Decimate(ModDataBuff, 0, ModDataBuff, 0, Part1Length * InputBlockSize); for (int i = 0; i < nSamp; i++) { OutputData.Add(ModDataBuff[i]); } //-------------------------------------------------- // Part two of the preamble //-------------------------------------------------- PreambleModulator.Init(); PreambleModulator.FrequencyOffset = FREQ_OFFSET; Array.Clear(ModDataBuff, 0, ModDataBuff.Length); for (int i = 0; i < Part2Length; i++) { float Sign = (i % 2) == 0 ? 1 : -1; Symb = IQ.UNITY * Sign * AMPLITUDE2 * NORM_AMP; PreambleModulator[1125.0f].Process(Symb * new IQ((float)(0 * (2 * Math.PI / 360))), ModDataBuff, i * InputBlockSize); PreambleModulator[1800.0f].Process(Symb * new IQ((float)(90 * (2 * Math.PI / 360))), ModDataBuff, i * InputBlockSize); PreambleModulator[2475.0f].Process(Symb * new IQ((float)(0 * (2 * Math.PI / 360))), ModDataBuff, i * InputBlockSize); PreambleModulator.Finish(ModDataBuff, i * InputBlockSize); } nSamp = OutputFilter.Decimate(ModDataBuff, 0, ModDataBuff, 0, Part2Length * InputBlockSize); for (int i = 0; i < nSamp; i++) { OutputData.Add(ModDataBuff[i]); } //-------------------------------------------------- // Part three of the preamble //-------------------------------------------------- Array.Clear(ModDataBuff, 0, ModDataBuff.Length); Symb = IQ.UNITY * AMPLITUDE3 * NORM_AMP; for (int i = 0; i < Part3Length; i++) { PreambleModulator.FrequencyOffset = FREQ_OFFSET; Array.Clear(ModDataBuff, 0, ModDataBuff.Length); this.Modulator.Index = 0; for (int k = 0; k < NUM_FREQ; k++) { IQ NewSymb = Symb * new IQ(PhasesInRads[k]); this.Modulator[k].Process(NewSymb, ModDataBuff, i * InputBlockSize); this.Encoder[k].PreviousIQ = NewSymb.N; } // this.Modulator.Finish(ModDataBuff, i * InputBlockSize); } if (useDopplerTone) { this.DopplerTone.GenerateAdd(AMPLITUDEDOPPLER * NORM_AMP, ModDataBuff, Part3Length * InputBlockSize); } nSamp = OutputFilter.Decimate(ModDataBuff, 0, ModDataBuff, 0, Part3Length * InputBlockSize); for (int i = 0; i < nSamp; i++) { OutputData.Add(ModDataBuff[i]); } this.Modulator.Index = 0; return(OutputData.Count); }
public int Process(float inSample) { FFTDemodulator.Process(inSample); Doppler.Process(inSample); if (FFTDemodulator.IsDataReady) { IQ Data; int DataBits; switch (State) { case STATES.FIRST_REF_SYMBOL: IQ RotCorr; for (int i = 0; i < NUMTONES3; i++) { Data = FFTDemodulator.GetData(); RotCorr = (IQ.UNITY / Data) / Data.R2; FFTDemodulator[i].RotateCorrection = RotCorr; OFDMDecoders[i].Init(); OFDMDecoders[i].PreviousIQ = Data * RotCorr; OFDMDecoders[i].StartCorrectionProcess(DOPPLERCORR_INTERVAL); } Doppler.StartCorrectionProcess(DOPPLERCORR_INTERVAL); State = STATES.REGULAR_DATA; break; case STATES.REGULAR_DATA: for (int i = 0; i < NUMTONES3; i++) { Data = FFTDemodulator.GetData(); RawData.Enqueue(Data); OFDMDecoders[i].Process(Data, out DataBits); for (int j = 0; j < BITS_PER_SYMBOL; j++) { OutputData.Enqueue((byte)(DataBits & 0x0001)); DataBits >>= 1; } } if (Doppler.IsCorrectionReady) { IQ DecodeCorr = IQ.UNITY; for (int i = 0; i < NUMTONES3; i++) { // DecodeCorr += OFDMDecoders[i].FrequencyCorrection; OFDMDecoders[i].StartCorrectionProcess(DOPPLERCORR_INTERVAL); } float FreqCorr = Doppler.FrequencyOffset; // +DecodeCorr; FFTDemodulator.FrequencyOffset = FreqCorr; Doppler.FrequencyOffset = FreqCorr; Doppler.StartCorrectionProcess(DOPPLERCORR_INTERVAL); } break; case STATES.FREQ_CORRECTION: break; default: break; } if (FFTDemodulator.Count > 0) { throw new ApplicationException("Extra symbols detected"); } FrameCounter++; } return(0); }
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); }
public void Init() { PrevSymbol = 0; PrevIQ = IQ.UNITY; }
/// <summary> /// Adds corralation target. This target will be used as the matching target for all data in the buffer. /// </summary> /// <param name="targetArray">Array that defines the target IQ components.</param> /// <param name="numberOfTargetSymbols">Number of target symbols in IQ array.</param> public void AddTarget(IQ[] targetArray, int numberOfTargetSymbols) { IQ SavedPrevIQ = PrevIQ; TargetLength = numberOfTargetSymbols; TargetMargin = TargetLength + MinSymbolsAfterMax; Target = new IQ[TargetLength]; TargetIQDiff = new float[TargetLength]; TargetIQDiff1 = new float[TargetLength]; if (TargetMargin > DataLength) { DataLength = TargetMargin; Data = new IQ[DataLength]; IQDiff = new float[DataLength]; IQDiff1 = new float[DataLength]; Init(); } MinNumSymbols = Math.Max(MinNumSymbols, TargetLength); DataLength = Math.Max(DataLength, (MinNumSymbols + MinSymbolsAfterMax)); if (DataLength > Data.Length) { Data = new IQ[DataLength]; IQDiff = new float[DataLength]; IQDiff1 = new float[DataLength]; } targetArray.CopyTo(Target, 0); TargetEnergy = 0; IQ CurrIQ; for (int i = 0; i < TargetLength; i++) { CurrIQ = targetArray[i]; TargetEnergy += CurrIQ.R2; } PrevIQ = IQ.ZERO; TargetAutoCorr = 0; float val; if (CorrelationType == CORR_TYPE.PHASE_DIFF) { for (int i = 0; i < TargetLength; i++) { CurrIQ = targetArray[i]; val = (CurrIQ.Phase - PrevIQ.Phase); TargetAutoCorr += val * val; TargetIQDiff[i] = val; PrevIQ = CurrIQ; } } else if (CorrelationType == CORR_TYPE.DELTASIN_DIFF) { for (int i = 0; i < TargetLength; i++) { CurrIQ = targetArray[i]; val = CurrIQ.DeltaSin(PrevIQ); TargetAutoCorr += val * val; TargetIQDiff[i] = val; PrevIQ = CurrIQ; } } else if (CorrelationType == CORR_TYPE.DELTACOS_DIFF) { for (int i = 0; i < TargetLength; i++) { CurrIQ = targetArray[i]; val = CurrIQ.DeltaCos(PrevIQ); TargetAutoCorr += val * val; TargetIQDiff[i] = val; PrevIQ = CurrIQ; } } else if (CorrelationType == CORR_TYPE.AMPLITUDE_DIFF) { for (int i = 0; i < TargetLength; i++) { CurrIQ = targetArray[i]; val = (CurrIQ - PrevIQ).R2; TargetAutoCorr += val * val; TargetIQDiff[i] = val; PrevIQ = CurrIQ; } } else if (CorrelationType == CORR_TYPE.AMPLITUDE) { for (int i = 0; i < TargetLength; i++) { val = targetArray[i].R2; TargetAutoCorr += val * val; TargetIQDiff[i] = val; } } else if (CorrelationType == CORR_TYPE.DELTA_DIFF) { for (int i = 0; i < TargetLength; i++) { CurrIQ = targetArray[i]; val = CurrIQ.DeltaSin(PrevIQ); TargetAutoCorr += val * val; TargetIQDiff[i] = val; val = CurrIQ.DeltaCos(PrevIQ); TargetAutoCorr += val * val; TargetIQDiff1[i] = val; PrevIQ = CurrIQ; } } else if (CorrelationType == CORR_TYPE.I) { for (int i = 0; i < TargetLength; i++) { val = targetArray[i].I; TargetAutoCorr += val * val; TargetIQDiff[i] = val; } } else if (CorrelationType == CORR_TYPE.Q) { for (int i = 0; i < TargetLength; i++) { val = targetArray[i].Q; TargetAutoCorr += val * val; TargetIQDiff[i] = val; } } else if (CorrelationType == CORR_TYPE.IQ) { for (int i = 0; i < TargetLength; i++) { val = targetArray[i].I; TargetAutoCorr += val * val; TargetIQDiff[i] = val; val = targetArray[i].Q; TargetAutoCorr += val * val; TargetIQDiff1[i] = val; } } else if (CorrelationType == CORR_TYPE.NONE) { } PrevIQ = SavedPrevIQ; }
private bool Equals(IQ other) { return((I == other.I) && (Q == other.Q)); }
public void AddTarget(IQ[] symbolTarget) { IQ[] t = new IQ[symbolTarget.Length]; symbolTarget.CopyTo(t, 0); TargetSymbolsIQ.Add(t); }
public void ProcessIFFT( IQ[] dataIn, IQ[] dataOut) { int i, j, k, n; int BlockSize, BlockEnd; IQ T; // Temporary vriable for swapping /* ** Do simultaneous data copy and bit-reversal ordering into outputs... * For IFFT swap Real and Img parts */ for (i = 0; i < NumSamples; i++) { j = ReverseBits_Table[i]; dataOut[j].I = dataIn[i].Q; dataOut[j].Q = dataIn[i].I; } /* ** Do the FFT itself... */ BlockEnd = 1; int TwiddlesIndex = 0; for (BlockSize = 2; BlockSize <= NumSamples; BlockSize <<= 1) { IQ M1 = T1[TwiddlesIndex]; IQ M2 = T2[TwiddlesIndex]; float w = 2 * fct1[TwiddlesIndex]; IQ A0, A1, A2; for (i = 0; i < NumSamples; i += BlockSize) { A2 = M2; A1 = M1; for (j = i, n = 0, k = i + BlockEnd; n < BlockEnd; j++, n++, k++) { A0 = (w * A1) - A2; A2 = A1; A1 = A0; T = A0 * dataOut[k]; dataOut[k] = dataOut[j] - T; dataOut[j] += T; } } TwiddlesIndex++; BlockEnd = BlockSize; } /* ** Need to normalize if inverse transform... */ float norm = 1.0f / 2.0f; // (float)Math.Sqrt(1.0 / 2); float t; for (i = 0; i < NumSamples; i++) { // Swap Real and Img parts t = dataOut[i].Q; dataOut[i].Q = dataOut[i].I * norm; dataOut[i].I = t * norm; } }