Пример #1
0
            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);
                }
            }
Пример #2
0
 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);
             }
         }
     }
 }
Пример #3
0
        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];
        }
Пример #4
0
        /// <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);
        }
Пример #5
0
 public float DeltaCosR(IQ prevIQ)
 {
     return((prevIQ.R > 0) ? (Q * prevIQ.Q + I * prevIQ.I) / prevIQ.R2 : 0);
 }
Пример #6
0
 public float DeltaSinR(IQ prevIQ)
 {
     return((prevIQ.R > 0) ? (Q * prevIQ.I - I * prevIQ.Q) / prevIQ.R2 : 0);
 }
Пример #7
0
 public float DeltaCos(IQ prevIQ)
 {
     return(I * prevIQ.I + Q * prevIQ.Q);
 }
Пример #8
0
 public float DeltaSin(IQ prevIQ)
 {
     return(Q * prevIQ.I - I * prevIQ.Q);
 }
Пример #9
0
 static void Combine(ref IQ originalData, IQ newData)
 {
     originalData = originalData + newData;
 }
Пример #10
0
        /// <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);
        }
Пример #11
0
        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;
            }
        }
Пример #12
0
            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);
            }
Пример #13
0
                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);
                }
Пример #14
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);
            }
Пример #15
0
 public void Init()
 {
     PrevSymbol = 0;
     PrevIQ     = IQ.UNITY;
 }
Пример #16
0
        /// <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;
        }
Пример #17
0
 private bool Equals(IQ other)
 {
     return((I == other.I) && (Q == other.Q));
 }
Пример #18
0
 public void AddTarget(IQ[] symbolTarget)
 {
     IQ[] t = new IQ[symbolTarget.Length];
     symbolTarget.CopyTo(t, 0);
     TargetSymbolsIQ.Add(t);
 }
Пример #19
0
        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;
            }
        }