public void TransmissionStart() { if (CallDepth == 0 && BitSink != null) { CallDepth++; BitSink.TransmissionStart(); CallDepth--; } else if (_LuaVm.GetFunction("TransmissionStart") != null) { CallFunction("TransmissionStart"); } }
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; } }
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); } } } } }
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; } }
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; } }