public void AddNiblesThenReadByte()
        {
            var sink = new BitSink();

            sink.AddBits(0xE, 4);
            sink.AddBits(0xF, 4);
            Assert.AreEqual(0xFE, sink.Read(8));
        }
        public void AddByteThenReadNibble()
        {
            var sink = new BitSink();

            sink.AddByte(0xFE);
            Assert.IsTrue(sink.CanRead(4));
            Assert.AreEqual(0xE, sink.Read(4));
            Assert.IsTrue(sink.CanRead(4));
            Assert.AreEqual(0xF, sink.Read(4));
            Assert.IsFalse(sink.CanRead(4));
        }
Beispiel #3
0
 public void ClockBit(bool state)
 {
     if (CallDepth == 0 && BitSink != null)
     {
         CallDepth++;
         BitSink.ClockBit(state);
         CallDepth--;
     }
     else if (_LuaVm.GetFunction("ClockBit") != null)
     {
         CallFunction("ClockBit", state);
     }
 }
Beispiel #4
0
 public void TransmissionEnd()
 {
     if (CallDepth == 0 && BitSink != null)
     {
         CallDepth++;
         BitSink.TransmissionEnd();
         CallDepth--;
     }
     else if (_LuaVm.GetFunction("TransmissionEnd") != null)
     {
         CallFunction("TransmissionEnd");
     }
 }
Beispiel #5
0
 public void Desynchronized()
 {
     if (CallDepth == 0 && BitSink != null)
     {
         CallDepth++;
         BitSink.Desynchronized();
         CallDepth--;
     }
     else if (_LuaVm.GetFunction("Desynchronized") != null)
     {
         CallFunction("Desynchronized");
     }
 }
        public void AddBytesThenReadBytes()
        {
            var sink = new BitSink();

            sink.AddByte(0xFF);
            sink.AddByte(0x00);
            sink.AddByte(0x0F);
            sink.AddByte(0xF0);
            sink.AddByte(0xFF);

            Assert.AreEqual(0xFF, sink.Read(8));
            Assert.AreEqual(0x00, sink.Read(8));
            Assert.AreEqual(0x0F, sink.Read(8));
            Assert.AreEqual(0xF0, sink.Read(8));
            Assert.AreEqual(0xFF, sink.Read(8));
        }
        public static IEnumerable <byte> UnpackBytes(IEnumerable <byte> sourceBytes, int bits, bool discardRemainder)
        {
            var sink = new BitSink();

            foreach (byte sourceByte in sourceBytes)
            {
                sink.AddByte(sourceByte);

                while (sink.CanRead(bits))
                {
                    yield return(sink.Read(bits));
                }
            }

            if (!(sink.IsEmpty || discardRemainder))
            {
                yield return(sink.ReadRemaining());
            }
        }
        public static IEnumerable <byte> PackBytes(IEnumerable <byte> sourceBytes, int bits)
        {
            var sink = new BitSink();

            foreach (byte sourceByte in sourceBytes)
            {
                sink.AddBits(sourceByte, bits);

                while (sink.CanRead(8))
                {
                    yield return(sink.Read(8));
                }
            }

            if (!sink.IsEmpty)
            {
                yield return(sink.ReadRemaining());
            }
        }
Beispiel #9
0
        private void Process(double power)
        {
            switch (State)
            {
            case eLearningState.Init:
                if (SamplingRate == 0)
                {
                    break;
                }
                UpdateBuffers();

                Plot.RealTimeMode = true;
                Plot.MaxSamples   = PreambleSignalBuffer.Length;
                Plot.LabelledHorLines.Clear();
                Plot.LabelledHorLines.AddLast(new LabelledLine("Decision", 0, Color.Red));
                Plot.LabelledVertLines.Clear();

                NoiseFloorInteg = 0;
                SampleNum       = 0;

                Log.AddMessage("PPMDemodulator", "Enter background noise learning mode...");
                State = eLearningState.BackgroundNoise;
                break;

            case eLearningState.BackgroundNoise:
                NoiseFloorInteg += power;
                SampleNum++;

                if (SampleNum > 5 * SamplingRate)
                {
                    NoiseFloor = DBTools.SquaredSampleTodB(NoiseFloorInteg / SampleNum);
                    Log.AddMessage("Learned noise level (" + NoiseFloor.ToString("0.00") + " dB)");
                    State = eLearningState.Synchronizing;
                }
                break;

            case eLearningState.Synchronizing:
                Array.Copy(PreambleSignalBuffer, 1, PreambleSignalBuffer, 0, PreambleSignalBuffer.Length - 1);

                PreambleSignalBuffer[PreambleSignalBuffer.Length - 1] = power * prev * 1000;
                prev = power;

                double match = CalcMatch();

                if (match > DetectionLevel)
                {
                    DetermineLevels();

                    SamplesToSkip = DetectOffset() + SamplesPerBit;
                    Log.AddMessage("Offset: " + SamplesToSkip);

                    IntegratedSignal      = 0;
                    IntegratedSignalCount = 0;
                    DataBitSample         = 0;
                    WholeSignalBufferPos  = 0;

                    SameBits = 0;
                    LastBit  = false;

                    Array.Copy(PreambleSignalBuffer, WholeSignalBuffer, PreambleSignalBuffer.Length);
                    WholeSignalBufferPos = PreambleSignalBuffer.Length;

                    Plot.LabelledVertLines.Clear();
                    Plot.LabelledVertLines.AddLast(new LabelledLine("" + DataBitNumber, WholeSignalBufferPos, Color.Yellow));


                    BitSink.TransmissionStart();
                    State = eLearningState.DataStream;
                }
                break;

            case eLearningState.DataStream:
                if (SamplesToSkip > 0)
                {
                    SamplesToSkip--;
                    break;
                }

                if (WholeSignalBufferPos < WholeSignalBuffer.Length)
                {
                    WholeSignalBuffer[WholeSignalBufferPos++] = power * prev * 1000;
                }

                int prevBit = DataBitNumber;
                IntegratedSignal += power * prev * 1000;
                IntegratedSignalCount++;
                DataBitSample++;

                prev = power;

                /* the current sample is within the next bit already */
                if (DataBitNumber != prevBit)
                {
                    Plot.LabelledVertLines.AddLast(new LabelledLine("" + DataBitNumber, WholeSignalBufferPos, Color.Green));

                    bool   bit   = false;
                    double level = IntegratedSignal / (double)IntegratedSignalCount;


                    if (level > DecisionLevel)
                    {
                        bit = true;
                    }

                    Log.AddMessage("Bit " + DataBitNumber + " Level: " + level.ToString("0.00") + " -> " + bit);
                    if (LastBit == bit)
                    {
                        SameBits++;
                        if (SameBits >= 2)
                        {
                            DumpWholeSignalBuffer();
                            BitSink.TransmissionEnd();
                            SameBits = 0;

                            State = eLearningState.Synchronizing;
                        }
                    }
                    else
                    {
                        SameBits = 0;
                    }

                    BitSink.ClockBit(bit);
                    LastBit = bit;

                    IntegratedSignal      = 0;
                    IntegratedSignalCount = 0;
                }

                if (DataBitNumber >= 2 * 112)
                {
                    DumpWholeSignalBuffer();

                    BitSink.TransmissionEnd();
                    State = eLearningState.Synchronizing;
                }
                break;
            }
        }
Beispiel #10
0
        public void Process(double iValue, double qValue)
        {
            double strength = (iValue * iValue + qValue * qValue);
            double phase;

            phase = UseFastAtan2 ? FastAtan2b(iValue, qValue) : Math.Atan2(iValue, qValue);

            while (phase - LastPhase < -(Math.PI / 2))
            {
                phase += Math.PI;
            }

            while (phase - LastPhase > Math.PI / 2)
            {
                phase -= Math.PI;
            }

            /* catch the case where I and Q are zero */
            if (double.IsNaN(phase))
            {
                phase = LastPhase;
            }

            double diff = phase - LastPhase;

            LastPhase = phase % (2 * Math.PI);


            switch (State)
            {
            case eLearningState.Idle:
                break;

            case eLearningState.Learn:
            case eLearningState.Process:
                /* build a buffer of samples to check the misalignment due to drifting clocks */
                if (!AlignmentCheckDone)
                {
                    AlignmentBuffer[AlignmentBufferPos++] = diff;

                    if (AlignmentBufferPos == AlignmentBuffer.Length)
                    {
                        AlignmentBufferPos = 0;
                        AlignmentCheckDone = true;
                        SampleOffset       = OffsetEstimator.EstimateOffset(AlignmentBuffer, 0, AlignmentBuffer.Length, SamplesPerSymbol);

                        if (State == eLearningState.Learn)
                        {
                            NextSamplePoint = SampleNum + SampleOffset + SamplesPerSymbol / 2;
                            SampleOffset    = 0;
                            State           = eLearningState.Process;
                            Log.AddMessage("GMSKDemodulator", "State: Process");
                        }
                        else
                        {
                            SampleOffset -= SamplesPerSymbol / 2;
                            SampleOffset /= 2;
                        }
                        //Log.AddMessage("SampleOffset:     " + SampleOffset);
                    }
                }

                /* process data only when already learned */
                if (State == eLearningState.Process)
                {
                    if (SampleNum == (long)NextSamplePoint)
                    {
                        if (BitSink != null)
                        {
                            BitSink.ClockBit(diff > 0);
                        }

                        NextSamplePoint += SamplesPerSymbol;

                        if (AlignmentCheckDone)
                        {
                            /* start bit alignment check again */
                            AlignmentCheckDone = false;

                            /* apply offset */
                            NextSamplePoint += SampleOffset;
                        }
                    }
                }
                break;
            }

            SampleNum++;
        }
Beispiel #11
0
        public void Process(double iValue, double qValue)
        {
            if (!Initialized)
            {
                return;
            }

            double sampleValue      = Math.Sqrt(iValue * iValue + qValue * qValue);
            bool   bitStart         = false;
            long   diffToLastActive = SampleNum - LastActiveStart;

            SampleNum++;

            if (EnableAGC)
            {
                NoiseFloor     = (NoiseFloor * NoiseFloorUpdateRate + sampleValue) / (NoiseFloorUpdateRate + 1);
                SignalStrength = (SignalStrength * SignalStrengthUpdateRate) / (SignalStrengthUpdateRate + 1);
            }

            if (Learning)
            {
                if (sampleValue > SignalStrength)
                {
                    SignalStrength = (SignalStrength * 100 + sampleValue) / 101;
                }

                /* reading noise level for 1 second */
                if (SampleNum < SamplingRate)
                {
                    NoiseFloor = Math.Max(sampleValue, NoiseFloor);
                }

                double signalDb = DBTools.SampleTodB(SignalStrength);
                double noiseDb  = DBTools.SampleTodB(NoiseFloor);

                if (signalDb - noiseDb > MinDbDistance)
                {
                    if (LearnBits > 3)
                    {
                        LearnedPower();
                        Learning = false;
                    }
                    else
                    {
                        bool state;

                        if (sampleValue < DecisionValue)
                        {
                            state = false;
                        }
                        else
                        {
                            state = true;
                        }

                        if (LearnTransmitState && !state)
                        {
                            LearnBits++;
                        }

                        LearnTransmitState = state;
                    }
                }
                return;
            }

            if (sampleValue > DecisionValue)
            {
                bitStart = false;

                /* the first sample of the symbol */
                if (TransmittingSamples == 0)
                {
                    long diff = SampleNum - LastActiveStart;

                    if (!BitTimeLocked && (diff < SymbolDistance || SymbolDistance == 0))
                    {
                        SymbolDistance = diff;
                    }

                    if (!Transmission)
                    {
                        if (BitSink != null)
                        {
                            BitSink.TransmissionStart();
                        }
                        //Log.AddMessage("Transmission Start");
                        Transmission      = true;
                        FirstTransmission = true;
                    }

                    LastActiveStart = SampleNum;
                    bitStart        = true;
                }
                TransmittingSamples++;
            }
            else
            {
                /* was active? */
                if (TransmittingSamples != 0)
                {
                    if (!BitTimeLocked)
                    {
                        TransmittingSamplesMax = Math.Max(TransmittingSamplesMax, TransmittingSamples);
                    }
                    TransmittingSamples = 0;
                }
            }

            if (Transmission)
            {
                if (FirstTransmission)
                {
                    FirstTransmission = false;
                }
                else
                {
                    if (diffToLastActive > DelayEnd)
                    {
                        //Log.AddMessage("Transmission STOP");
                        if (BitSink != null)
                        {
                            BitSink.TransmissionEnd();
                        }
                        Transmission = false;
                        DumpBits();
                    }
                    else if (bitStart)
                    {
                        if (diffToLastActive > DelayStartBit)
                        {
                            if (!BitTimeLocked)
                            {
                                BitTimeLocked = true;
                                LearnedTiming();
                                Bits.Clear();
                            }
                            else
                            {
                                DumpBits();
                            }
                            //Log.AddMessage("Transmission START " + diffToLastActive);
                        }
                        else if (diffToLastActive > DelayLongBit)
                        {
                            if (BitSink != null)
                            {
                                BitSink.ClockBit(true);
                            }
                            Bits.Add(true);
                        }
                        else if (diffToLastActive > DelayShortBit)
                        {
                            if (BitSink != null)
                            {
                                BitSink.ClockBit(false);
                            }
                            Bits.Add(false);
                        }
                    }
                }
            }
        }
Beispiel #12
0
        public void Process(double iValue, double qValue)
        {
            SampleNum++;

            double sampleValue = Math.Sqrt(iValue * iValue + qValue * qValue);
            double phase       = UseFastAtan2 ? FastAtan2b(iValue, qValue) : Math.Atan2(iValue, qValue);
            double signalDb    = DBTools.SampleTodB(sampleValue);
            double noiseDb     = DBTools.SampleTodB(NoiseFloor);

            if (Math.Abs(sampleValue) >= 1.0)
            {
                return;
            }

            while (phase - LastPhase < -(Math.PI / 2))
            {
                phase += Math.PI;
            }

            while (phase - LastPhase > Math.PI / 2)
            {
                phase -= Math.PI;
            }

            /* catch the case where I and Q are zero */
            if (double.IsNaN(phase))
            {
                phase = LastPhase;
            }

            double phaseDifference = phase - LastPhase;

            LastPhase = phase % (2 * Math.PI);


            // work with phase difference now
            switch (State)
            {
            case eLearningState.Idle:
                break;

            case eLearningState.Prepare:
                if (SamplingRate != 0)
                {
                    Log.AddMessage("PSKDemodulator", "Waiting for Sampling rate being published.");
                    State = eLearningState.Start;
                }
                break;

            case eLearningState.Start:
                if (SamplingRate != 0)
                {
                    Log.AddMessage("PSKDemodulator", "Learn background noise for " + FrequencyFormatter.TimeToString(NoiseFloorLearnSamples / SamplingRate) + ".");
                    State = eLearningState.BackgroundNoise;
                }
                break;

            case eLearningState.BackgroundNoise:
                NoiseFloor += sampleValue;
                if (SampleNum > NoiseFloorLearnSamples)
                {
                    NoiseFloor /= NoiseFloorLearnSamples;
                    Log.AddMessage("PSKDemodulator", "Learned Noise. Transmission may start now.");
                    State = eLearningState.PhaseDiff;
                }
                break;

            case eLearningState.PhaseDiff:
                PhaseDiffHigh = PhaseShift;
                PhaseDiffLow  = -PhaseShift;
                State         = eLearningState.TransmissionIdle;
                break;

            case eLearningState.TransmissionIdle:
                if (signalDb > noiseDb + MinDbDistance)
                {
                    State = eLearningState.TransmissionStart;
                }
                else
                {
                    State = eLearningState.TransmissionIdle;
                }
                break;

            case eLearningState.TransmissionStart:
                /* wait until quarter of a symbol was sent before using phase information */
                SamplePointStart = SampleNum + SymbolDistance / 4;
                SamplePointEnd   = SamplePointStart + SymbolDistance / 2;
                State            = eLearningState.TransmissionActive;

                if (BitSink != null)
                {
                    BitSink.TransmissionStart();
                }
                break;


            case eLearningState.TransmissionActive:
                if (SampleNum < SamplePointStart || SampleNum > SamplePointEnd)
                {
                    PhaseDifferenceSmooth /= 2;
                    PhaseDifferenceSmooth += phaseDifference;

                    if (PhaseDifferenceSmooth / 1.75f > PhaseDiffHigh)
                    {
                        /* handle a low->high transition */
                        if (!PhasePositive)
                        {
                            PhasePositive    = true;
                            SamplePointStart = (long)(SampleNum + SymbolDistance * 0.15f);
                            SamplePointEnd   = (long)(SamplePointStart + SymbolDistance * 0.7f);
                        }
                    }
                    else if (PhaseDifferenceSmooth / 1.75f < PhaseDiffLow)
                    {
                        /* handle a high->low transition */
                        if (PhasePositive)
                        {
                            PhasePositive    = false;
                            SamplePointStart = (long)(SampleNum + SymbolDistance * 0.15f);
                            SamplePointEnd   = (long)(SamplePointStart + SymbolDistance * 0.7f);
                        }
                    }
                }
                else if (SampleNum == SamplePointStart)
                {
                    PhaseSum = 0;
                }
                else if (SampleNum == SamplePointEnd)
                {
                    PhasePositive = PhaseSum > 0;

                    if (BitSink != null)
                    {
                        BitSink.ClockBit(!PhasePositive);
                    }

                    /* set the next sampling points. will get overriden when phase changes */
                    SamplePointStart += SymbolDistance;
                    SamplePointEnd   += SymbolDistance;
                }
                else
                {
                    /* check whether signal strength has decreased */
                    if (signalDb < noiseDb + MinDbDistance)
                    {
                        State = eLearningState.TransmissionStop;
                    }
                    else
                    {
                        PhaseSum += phaseDifference;
                    }
                }

                break;

            case eLearningState.TransmissionStop:
                if (BitSink != null)
                {
                    BitSink.TransmissionEnd();
                }
                State = eLearningState.TransmissionIdle;
                break;
            }
        }
Beispiel #13
0
        public void Process(double iValue, double qValue)
        {
            if (!Initialized)
            {
                return;
            }

            double sampleValue = Math.Sqrt(iValue * iValue + qValue * qValue);

            SampleNum++;

            if (EnableAGC)
            {
                NoiseFloor     = (NoiseFloor * NoiseFloorUpdateRate + sampleValue) / (NoiseFloorUpdateRate + 1);
                SignalStrength = (SignalStrength * SignalStrengthUpdateRate) / (SignalStrengthUpdateRate + 1);
            }

            switch (State)
            {
            case eLearningState.Idle:
                break;

            case eLearningState.Init:

                if (!NoiseLevelLocked)
                {
                    State = eLearningState.BackgroundNoise;
                    Log.AddMessage("ASKDemodulator", "Enter background noise learning mode...");
                }
                else if (!SignalStrengthLocked)
                {
                    State = eLearningState.SignalStrength;
                    Log.AddMessage("ASKDemodulator", "Enter signal strength learning mode...");
                }
                else
                {
                    State = eLearningState.Done;
                    Log.AddMessage("ASKDemodulator", "Enter processing mode...");
                }
                break;

            case eLearningState.BackgroundNoise:
                NoiseFloor = Math.Max(sampleValue, NoiseFloor);
                if (SampleNum >= BackgroundNoiseSamples)
                {
                    Log.AddMessage("Learned noise level. You may start transmission now.");
                    if (!SignalStrengthLocked)
                    {
                        State = eLearningState.SignalStrength;
                    }
                    else
                    {
                        SignalStrength = DBTools.SampleFromdB(DBTools.SampleTodB(NoiseFloor) + MinDbDistance);
                        State          = eLearningState.BitTiming;
                    }
                }
                break;

            case eLearningState.SignalStrength:
                if (sampleValue > SignalStrength)
                {
                    SignalStrength = (SignalStrength * 99 + sampleValue) / 100;
                }

                double signalDb = DBTools.SampleTodB(SignalStrength);
                double noiseDb  = DBTools.SampleTodB(NoiseFloor);

                if (signalDb - noiseDb > MinDbDistance)
                {
                    if (LearnBits > 3)
                    {
                        LearnedPower();
                        State = eLearningState.BitTiming;
                    }
                    else
                    {
                        bool state;

                        if (sampleValue < DecisionValue)
                        {
                            state = false;
                        }
                        else
                        {
                            state = true;
                        }

                        if (LearnTransmitState && !state)
                        {
                            LearnBits++;
                        }

                        LearnTransmitState = state;
                    }
                }
                break;

            case eLearningState.BitTiming:
                State = eLearningState.Done;
                break;

            case eLearningState.Done:
                bool transmitting = false;
                if (sampleValue > DecisionValue)
                {
                    transmitting = true;

                    /* the first sample of the symbol */
                    if (TransmittingSamples == 0)
                    {
                        long diff = SampleNum - LastActiveEnd;

                        if (!Transmission && SymbolDistance > 0)
                        {
                            //Log.AddMessage("Transmission Start (sync to positive edge)" + " at " + SampleNum);
                            Transmission            = true;
                            TransmissionFirstSample = true;
                            NegativeEdge            = SampleNum;
                        }

                        if (!BitTimeLocked && LastActiveStart != 0 && (diff < SymbolDistance || SymbolDistance == 0))
                        {
                            double sampleTime = (diff / SamplingRate) * 1000;
                            SymbolDistanceDelta = diff - SymbolDistance;

                            Log.AddMessage("SymbolDistance: " + SymbolDistance.ToString() + " (" + sampleTime.ToString() + "ms)" + " at " + SampleNum);
                        }

                        LastActiveStart = SampleNum;
                        NextSamplePoint = SampleNum + SymbolDistance / 2;
                        //Log.AddMessage("Transmission Start (sync to positive edge) at " + SampleNum + " next Sample Point at " + NextSamplePoint);
                    }
                    TransmittingSamples++;
                }
                else
                {
                    /* was active? */
                    if (TransmittingSamples != 0)
                    {
                        NextSamplePoint = SampleNum + SymbolDistance / 2;
                        //Log.AddMessage("Transmission End (sync to negitive edge) at " + SampleNum + " next Sample Point at " + NextSamplePoint);
                        TransmittingSamples = 0;
                        LastActiveEnd       = SampleNum;
                    }
                }

                if (Transmission)
                {
                    if (TransmissionFirstSample)
                    {
                        if (BitSink != null)
                        {
                            BitSink.TransmissionStart();
                        }
                        BitNum = 0;
                        //DumpBits();
                        LastBitSample           = SampleNum;
                        ConsecutiveZeros        = 0;
                        TransmissionFirstSample = false;
                    }
                    else
                    {
                        /* sample in the middle of the bit */
                        if (SampleNum == NextSamplePoint)
                        {
                            NextSamplePoint = SampleNum + SymbolDistance;
                            //Log.AddMessage("Bit #"+ BitNum +" " + (transmitting ? "1" : "0") + " at " + SampleNum);
                            if (BitSink != null)
                            {
                                BitSink.ClockBit(transmitting);
                            }
                            BitNum++;
                            //Bits.Add(transmitting);

                            if (!transmitting)
                            {
                                if (++ConsecutiveZeros > MaxConsecutiveZeros)
                                {
                                    Transmission = false;

                                    if (!BitTimeLocked)
                                    {
                                        BitTimeLocked = true;
                                        LearnedTiming();
                                        //Bits.Clear();
                                    }
                                    else
                                    {
                                        //DumpBits();
                                    }

                                    if (BitSink != null)
                                    {
                                        BitSink.TransmissionEnd();
                                    }
                                    return;
                                }
                            }
                            else
                            {
                                ConsecutiveZeros = 0;
                            }
                        }
                    }
                }
                break;
            }
        }