diff --git a/src/main/java/io/github/dsheirer/bits/BinaryMessage.java b/src/main/java/io/github/dsheirer/bits/BinaryMessage.java index 68ed5a65..0539f7bd 100644 --- a/src/main/java/io/github/dsheirer/bits/BinaryMessage.java +++ b/src/main/java/io/github/dsheirer/bits/BinaryMessage.java @@ -243,6 +243,16 @@ public class BinaryMessage extends BitSet return mSize; } + /** + * Current size of the message indicating the quantity of bits that have been added to this message. This value + * is less than or equal to the size() value. + * @return current size in bits. + */ + public int currentSize() + { + return mPointer; + } + public void setSize(int size) { mSize = size; diff --git a/src/main/java/io/github/dsheirer/bits/IntField.java b/src/main/java/io/github/dsheirer/bits/IntField.java index 4dc5dc91..3f6239a2 100644 --- a/src/main/java/io/github/dsheirer/bits/IntField.java +++ b/src/main/java/io/github/dsheirer/bits/IntField.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2024 Dennis Sheirer + * Copyright (C) 2014-2025 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -69,6 +69,16 @@ public record IntField(int start, int end) return new IntField(start, (start + 3)); } + /** + * Utility constructor method for a field with one four bits of length. + * @param start index (inclusive) + * @return constructed bit field. + */ + public static IntField length6(int start) + { + return new IntField(start, (start + 5)); + } + /** * Utility constructor method for a field with one octet of length. * @param start index (inclusive) diff --git a/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java b/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java index e3a58008..78671db1 100644 --- a/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java +++ b/src/main/java/io/github/dsheirer/bits/MultiSyncPatternMatcher.java @@ -1,35 +1,31 @@ /* + * ***************************************************************************** + * Copyright (C) 2014-2025 Dennis Sheirer * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * **************************************************************************** */ package io.github.dsheirer.bits; import io.github.dsheirer.dsp.symbol.ISyncDetectListener; +import java.util.ArrayList; +import java.util.List; import org.apache.commons.lang3.Validate; import org.apache.commons.math3.util.FastMath; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.util.ArrayList; -import java.util.List; - /** * Multi-Sync pattern matcher. Accepts multiple sync detector objects for * comparision against the incoming bit stream. @@ -39,6 +35,7 @@ import java.util.List; * of the Long.rotate methods will wrap the MSB around to the LSB and * corrupt the matching value. */ +@Deprecated //remove after P25P2 decoder is updated public class MultiSyncPatternMatcher { private final static Logger mLog = LoggerFactory.getLogger(MultiSyncPatternMatcher.class); diff --git a/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java b/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java index a5abee55..def50c71 100644 --- a/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java +++ b/src/main/java/io/github/dsheirer/bits/SoftSyncDetector.java @@ -1,23 +1,27 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer +/* + * ***************************************************************************** + * Copyright (C) 2014-2025 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * **************************************************************************** + */ package io.github.dsheirer.bits; import io.github.dsheirer.dsp.symbol.ISyncDetectListener; import org.apache.commons.lang3.Validate; +@Deprecated //Remove after P25P2 decoder is updated. public class SoftSyncDetector implements ISyncProcessor { private ISyncDetectListener mListener; diff --git a/src/main/java/io/github/dsheirer/dsp/filter/design/FilterViewer.java b/src/main/java/io/github/dsheirer/dsp/filter/design/FilterViewer.java index 3771675c..698a03ab 100644 --- a/src/main/java/io/github/dsheirer/dsp/filter/design/FilterViewer.java +++ b/src/main/java/io/github/dsheirer/dsp/filter/design/FilterViewer.java @@ -20,6 +20,7 @@ package io.github.dsheirer.dsp.filter.design; import io.github.dsheirer.dsp.filter.FilterFactory; +import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification; import io.github.dsheirer.dsp.window.WindowType; import javafx.application.Application; import javafx.scene.Scene; @@ -61,7 +62,26 @@ public class FilterViewer extends Application int filterLength = 31; WindowType windowType = WindowType.BLACKMAN_HARRIS_7; - float[] taps = FilterFactory.getHighPass(8000, 3000, filterLength, windowType); + FIRFilterSpecification specification = FIRFilterSpecification + .lowPassBuilder() + .sampleRate(12500) + .passBandCutoff(5200) + .passBandAmplitude(1.0).passBandRipple(0.01) //.01 + .stopBandAmplitude(0.0).stopBandStart(6500) //6500 + .stopBandRipple(0.01).build(); + + float[] taps = null; + + try + { + taps = FilterFactory.getTaps(specification); + } + catch(Exception fde) //FilterDesignException + { + System.out.println("Error"); + } + + // float[] taps = FilterFactory.getHighPass(8000, 3000, filterLength, windowType); // float[] taps = FilterFactory.getRootRaisedCosine(50000.0 / 4800.0, 20, 0.2f); // taps = HilbertTransform.HALF_BAND_FILTER_47_TAP; diff --git a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulator.java b/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulator.java deleted file mode 100644 index 08b30d52..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulator.java +++ /dev/null @@ -1,128 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2024 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.filter.interpolator.Interpolator; -import io.github.dsheirer.dsp.filter.interpolator.InterpolatorFactory; -import io.github.dsheirer.dsp.psk.pll.CostasLoop; -import io.github.dsheirer.dsp.psk.pll.IPhaseLockedLoop; -import io.github.dsheirer.dsp.symbol.Dibit; -import io.github.dsheirer.sample.complex.Complex; -import java.text.DecimalFormat; - -public class DQPSKDecisionDirectedDemodulator extends PSKDemodulator -{ - protected DQPSKDecisionDirectedSymbolEvaluator mSymbolEvaluator = new DQPSKDecisionDirectedSymbolEvaluator(); - private Complex mPreviousPrecedingSample = new Complex(0, 0); - private Complex mPreviousCurrentSample = new Complex(0, 0); - private Complex mPrecedingSample = new Complex(0, 0); - private Complex mCurrentSample = new Complex(0, 0); - private Complex mPrecedingSymbol = new Complex(0, 0); - protected Complex mCurrentSymbol = new Complex(0, 0); - - private final Interpolator mInterpolator = InterpolatorFactory.getInterpolator(); - private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("+#0.00000;-#0.00000"); - private float[] mI = new float[15]; - private float[] mQ = new float[15]; - - /** - * Decoder for Differential Quaternary Phase Shift Keying (DQPSK). This decoder uses both a Costas Loop (PLL) and - * a decision-directed DQPSK symbol timing and phase error detector to automatically align to the incoming carrier - * frequency and to adjust for any changes in symbol timing. - * - * This detector is optimized for constant amplitude DQPSK symbols like C4FM. - * - * @param phaseLockedLoop for tracking carrier frequency error - * @param interpolatingSampleBuffer to hold samples for interpolating a symbol - */ - public DQPSKDecisionDirectedDemodulator(IPhaseLockedLoop phaseLockedLoop, InterpolatingSampleBuffer interpolatingSampleBuffer) - { - super(interpolatingSampleBuffer, phaseLockedLoop); - } - - @Override - public void receive(float inphase, float quadrature) - { - super.receive(inphase, quadrature); - - System.arraycopy(mI, 1, mI, 0, mI.length - 1); - System.arraycopy(mQ, 1, mQ, 0, mQ.length - 1); - - //Rotate the sample and add to buffer - Complex current = new Complex(inphase, quadrature); - current.normalizeFast(); - current.multiply(getPLL().getCurrentVector()); - mI[mI.length - 1] = current.inphase(); - mQ[mQ.length - 1] = current.quadrature(); - float iTemp = mInterpolator.filter(mI, 6, .416f); - float qTemp = mInterpolator.filter(mQ, 6, .416f); - float iSymbol = (mI[0] * iTemp) - (-mQ[0] * qTemp); - float qSymbol = (mI[0] * qTemp) + (iTemp * -mQ[0]); - float radians = (float)Math.atan2(iSymbol, qSymbol); - - StringBuilder sb = new StringBuilder(); - sb.append(DECIMAL_FORMAT.format(radians)).append(","); - sb.append(DECIMAL_FORMAT.format(((CostasLoop)getPLL()).getLoopFrequency())); -// System.out.println(sb); - } - - /** - * Calculates a symbol from the interpolating buffer - */ - protected void calculateSymbol() - { - //Get preceding sample and an interpolated current sample from the interpolating buffer - mPrecedingSample = getInterpolatingSampleBuffer().getPrecedingSample(); - mCurrentSample = getInterpolatingSampleBuffer().getCurrentSample(); - - //Differential decode preceding and current symbols by calculating the angular rotation between the previous and - //current samples (current sample x complex conjugate of previous sample). - - //Note: preceding symbol is a preceding measurement of the current symbol that is simply used as a reference - //point to determine vector rotation to the current symbol -- it is not the true predecessor symbol - mPrecedingSymbol.setInphase(Complex.multiplyInphase(mPrecedingSample.inphase(), mPrecedingSample.quadrature(), - mPreviousPrecedingSample.inphase(), -mPreviousPrecedingSample.quadrature())); - mPrecedingSymbol.setQuadrature(Complex.multiplyQuadrature(mPrecedingSample.inphase(), mPrecedingSample.quadrature(), - mPreviousPrecedingSample.inphase(), -mPreviousPrecedingSample.quadrature())); - - mCurrentSymbol.setInphase(Complex.multiplyInphase(mCurrentSample.inphase(), mCurrentSample.quadrature(), - mPreviousCurrentSample.inphase(), -mPreviousCurrentSample.quadrature())); - mCurrentSymbol.setQuadrature(Complex.multiplyQuadrature(mCurrentSample.inphase(), mCurrentSample.quadrature(), - mPreviousCurrentSample.inphase(), -mPreviousCurrentSample.quadrature())); - - //Set gain to unity before we calculate the error value - mPrecedingSymbol.normalize(); - mCurrentSymbol.normalize(); - - //Apply symbols to evaluator to calculate phase and timing error and make a symbol decision - mSymbolEvaluator.setSymbol(mPrecedingSymbol, mCurrentSymbol); - - //Update the symbol timing error - getInterpolatingSampleBuffer().resetAndAdjust(mSymbolEvaluator.getTimingError()); - - //Update the costas loop (PLL) with any measured phase error -// getPLL().adjust(clip(mSymbolEvaluator.getPhaseError(), 0.5f)); - - //Store current samples/symbols to use for the next symbol period - mPreviousPrecedingSample.setValues(mPrecedingSample); - mPreviousCurrentSample.setValues(mCurrentSample); - - broadcast(mSymbolEvaluator.getSymbolDecision()); - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulatorInstrumented.java b/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulatorInstrumented.java deleted file mode 100644 index 21f056f7..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulatorInstrumented.java +++ /dev/null @@ -1,147 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.psk.pll.CostasLoop; -import io.github.dsheirer.dsp.psk.pll.IPhaseLockedLoop; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; -import io.github.dsheirer.sample.complex.ComplexSamples; -import org.apache.commons.math3.util.FastMath; - -public class DQPSKDecisionDirectedDemodulatorInstrumented extends DQPSKDecisionDirectedDemodulator -{ - private Listener mSymbolDecisionDataListener; - private Listener mSamplesPerSymbolListener; - private Listener mComplexSymbolListener; - private Listener mPLLErrorListener; - private Listener mPLLFrequencyListener; - private Listener mFilteredGainAppliedComplexBufferListener; - private double mSampleRate; - - /** - * Decoder for Differential Quaternary Phase Shift Keying (DQPSK). This decoder uses both a Costas Loop (PLL) and - * a custom DQPSK symbol timing error detector to automatically align to the incoming carrier frequency and to - * adjust for any changes in symbol timing. - * - * This detector is optimized for constant amplitude DQPSK symbols like C4FM. - * - * @param phaseLockedLoop for tracking carrier frequency error - * @param interpolatingSampleBuffer - * @param sampleRate of the incoming complex sample stream - */ - public DQPSKDecisionDirectedDemodulatorInstrumented(IPhaseLockedLoop phaseLockedLoop, - InterpolatingSampleBufferInstrumented interpolatingSampleBuffer, - double sampleRate) - { - super(phaseLockedLoop, interpolatingSampleBuffer); - mSampleRate = sampleRate; - } - - @Override - public void receive(ComplexSamples complexSamples) - { - if(mFilteredGainAppliedComplexBufferListener != null) - { - mFilteredGainAppliedComplexBufferListener.receive(complexSamples); - } - - super.receive(complexSamples); - } - - /** - * Overrides the parent class symbol calculation to capture eye diagram data - */ - protected void calculateSymbol() - { - //Eye diagram listener - if(mSymbolDecisionDataListener != null) - { - mSymbolDecisionDataListener.receive( - ((InterpolatingSampleBufferInstrumented)getInterpolatingSampleBuffer()).getSymbolDecisionData()); - } - - super.calculateSymbol(); - - if(mSamplesPerSymbolListener != null) - { - mSamplesPerSymbolListener.receive((double)getInterpolatingSampleBuffer().getSamplingPoint()); - } - - //Send to an external constellation symbol listener when registered - if(mComplexSymbolListener != null) - { - mComplexSymbolListener.receive(mCurrentSymbol); - } - - if(mPLLErrorListener != null) - { - mPLLErrorListener.receive((double)mSymbolEvaluator.getPhaseError()); - } - - if(mPLLFrequencyListener != null) - { - double loopFrequency = ((CostasLoop)getPLL()).getLoopFrequency(); - - loopFrequency *= mSampleRate / (2.0 * FastMath.PI); - - mPLLFrequencyListener.receive(loopFrequency); - } - } - - /** - * Registers a listener to receive symbol decision data to produce an eye diagram. - */ - public void setSymbolDecisionDataListener(Listener listener) - { - mSymbolDecisionDataListener = listener; - } - - /** - * Registers the listener to receive PLL error values - */ - public void setSamplesPerSymbolListener(Listener listener) - { - mSamplesPerSymbolListener = listener; - } - - /** - * Registers the listener to receive decoded QPSK symbols - */ - public void setComplexSymbolListener(Listener listener) - { - mComplexSymbolListener = listener; - } - - /** - * Registers the listener to receive PLL error values - */ - public void setPLLErrorListener(Listener listener) - { - mPLLErrorListener = listener; - } - - /** - * Registers the listener to receive PLL error values - */ - public void setPLLFrequencyListener(Listener listener) - { - mPLLFrequencyListener = listener; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedSymbolEvaluator.java b/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedSymbolEvaluator.java deleted file mode 100644 index 35a08c2d..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedSymbolEvaluator.java +++ /dev/null @@ -1,172 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.symbol.Dibit; -import io.github.dsheirer.sample.complex.Complex; -import org.apache.commons.math3.util.FastMath; - -public class DQPSKDecisionDirectedSymbolEvaluator implements IPSKSymbolEvaluator -{ - private static final Complex ROTATE_FROM_PLUS_135 = Complex.fromAngle(-3.0 * FastMath.PI / 4.0); - private static final Complex ROTATE_FROM_PLUS_45 = Complex.fromAngle(-1.0 * FastMath.PI / 4.0); - private static final Complex ROTATE_FROM_MINUS_45 = Complex.fromAngle(1.0 * FastMath.PI / 4.0); - private static final Complex ROTATE_FROM_MINUS_135 = Complex.fromAngle(3.0 * FastMath.PI / 4.0); - - private Complex mEvaluationSymbol = new Complex(0, 0); - private float mPhaseError = 0.0f; - private float mTimingError = 0.0f; - private float mTimingErrorPolarity = 1.0f; - private Dibit mSymbolDecision = Dibit.D00_PLUS_1; - - /** - * Differential QPSK Decision-directed symbol phase and timing error detector and symbol decision slicer. - * - * Symbol decision is based on the closest reference quadrant for the sampled symbol. - * - * Phase and timing error are calculated as the angular distance of the sampled symbol from the reference - * symbol. Timing error is further corrected to compensate for clock-wise or counter-clock-wise vector rotation - * relative to the immediately preceding symbol. - */ - public DQPSKDecisionDirectedSymbolEvaluator() - { - } - - /** - * Sets the preceding and current symbols to be evaluated for phase and timing errors and to determine the - * transmitted symbol relative to the closest reference symbol. After invoking this method, you can access the - * phase and timing errors and the symbol decision via their respective accessor methods. - * - * Phase and timing error values are calculated by first determining the symbol and then calculating the phase - * and timing errors relative to the reference symbol. The timing error is corrected with the appropriate sign - * relative to the angular vector rotation so that the error value indicates the correct error direction. - * - * @param preceding differential-decoded sample/symbol used to detect rotation - does NOT need to be interpolated - * since it's only a reference - * @param current symbol to be evaluated - interpolated - */ - public void setSymbol(Complex preceding, Complex current) - { - mEvaluationSymbol.setValues(current); - - if(mEvaluationSymbol.quadrature() > 0.0f) - { - if(mEvaluationSymbol.inphase() > 0.0f) - { - mSymbolDecision = Dibit.D00_PLUS_1; - mTimingErrorPolarity = (preceding.quadrature() > current.quadrature() ? 1.0f : -1.0f); - mEvaluationSymbol.multiply(ROTATE_FROM_PLUS_45); - } - else - { - mSymbolDecision = Dibit.D01_PLUS_3; - mTimingErrorPolarity = (preceding.quadrature() < current.quadrature() ? 1.0f : -1.0f); - mEvaluationSymbol.multiply(ROTATE_FROM_PLUS_135); - } - - } - else - { - if(mEvaluationSymbol.inphase() > 0.0f) - { - mSymbolDecision = Dibit.D10_MINUS_1; - mTimingErrorPolarity = (preceding.quadrature() > current.quadrature() ? 1.0f : -1.0f); - mEvaluationSymbol.multiply(ROTATE_FROM_MINUS_45); - } - else - { - mSymbolDecision = Dibit.D11_MINUS_3; - mTimingErrorPolarity = (preceding.quadrature() < current.quadrature() ? 1.0f : -1.0f); - mEvaluationSymbol.multiply(ROTATE_FROM_MINUS_135); - } - } - - //Since we've rotated the error symbol back to 0 radians, the quadrature value closely approximates the - //arctan of the error angle relative to 0 radians and this provides our error value - float errorNormalized = normalize(mEvaluationSymbol.quadrature(), 0.3f); - - mPhaseError = -errorNormalized; - - //Timing error is the same as phase error with the sign corrected according to the vector's angular rotation - mTimingError = errorNormalized * mTimingErrorPolarity; - } - - /** - * Constrains value to the range of ( -maximum <> maximum ) - */ - private static float clip(float value, float maximum) - { - if(value > maximum) - { - return maximum; - } - else if(value < -maximum) - { - return -maximum; - } - - return value; - } - - /** - * Constrains timing error to +/- the maximum value and corrects any - * floating point invalid numbers - */ - private float normalize(float error, float maximum) - { - if(Float.isNaN(error)) - { - return 0.0f; - } - else - { - return clip(error, maximum); - } - } - - /** - * Phase error of the symbol relative to the nearest reference symbol. - * - * @return phase error in radians of distance from the reference symbol. - */ - @Override - public float getPhaseError() - { - return mPhaseError; - } - - /** - * Timing error of the symbol relative to the nearest reference symbol. - * - * @return timing error in radians of angular distance from the reference symbol recognizing that the symbol - * originates at zero radians and rotates toward the intended reference symbol, therefore the error value indicates - * if the symbol was sampled early (-) or late (+) relative to the reference symbol. - */ - @Override - public float getTimingError() - { - return mTimingError; - } - - /** - * Reference symbol that is closest to the transmitted/sampled symbol. - */ - @Override - public Dibit getSymbolDecision() - { - return mSymbolDecision; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKGardnerDemodulatorInstrumented.java b/src/main/java/io/github/dsheirer/dsp/psk/DQPSKGardnerDemodulatorInstrumented.java deleted file mode 100644 index 9f6df37a..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/DQPSKGardnerDemodulatorInstrumented.java +++ /dev/null @@ -1,152 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.psk.pll.CostasLoop; -import io.github.dsheirer.dsp.psk.pll.IPhaseLockedLoop; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; -import io.github.dsheirer.sample.complex.ComplexSamples; -import org.apache.commons.math3.util.FastMath; - -public class DQPSKGardnerDemodulatorInstrumented extends DQPSKGardnerDemodulator -{ - private Listener mSymbolDecisionDataListener; - private Listener mSamplesPerSymbolListener; - private Listener mComplexSymbolListener; - private Listener mPLLErrorListener; - private Listener mPLLFrequencyListener; - private Listener mFilteredGainAppliedComplexBufferListener; - private double mSampleRate; - - /** - * Implements a Differential QPSK demodulator using a Costas Loop (PLL) and a Gardner timing error detector. - * - * This decoder is optimized for P25 Linear Simulcast Modulation (LSM). - * - * @param phaseLockedLoop for tracking carrier frequency error - * @param interpolatingSampleBuffer to hold samples for interpolating a symbol - */ - public DQPSKGardnerDemodulatorInstrumented(IPhaseLockedLoop phaseLockedLoop, - InterpolatingSampleBuffer interpolatingSampleBuffer, - double sampleRate) - { - super(phaseLockedLoop, interpolatingSampleBuffer); - mSampleRate = sampleRate; - } - - @Override - public void receive(ComplexSamples complexSamples) - { - if(mFilteredGainAppliedComplexBufferListener != null) - { - mFilteredGainAppliedComplexBufferListener.receive(complexSamples); - } - - super.receive(complexSamples); - } - - /** - * Overrides the parent class symbol calculation to capture eye diagram data - */ - protected void calculateSymbol() - { - //Eye diagram listener - if(mSymbolDecisionDataListener != null) - { - mSymbolDecisionDataListener.receive( - ((InterpolatingSampleBufferInstrumented)getInterpolatingSampleBuffer()).getSymbolDecisionData()); - } - - super.calculateSymbol(); - - if(mSamplesPerSymbolListener != null) - { - mSamplesPerSymbolListener.receive((double)getInterpolatingSampleBuffer().getSamplingPoint()); - } - - //Send to an external constellation symbol listener when registered - if(mComplexSymbolListener != null) - { - mComplexSymbolListener.receive(mCurrentSymbol); - } - - if(mPLLErrorListener != null) - { - mPLLErrorListener.receive((double)mSymbolEvaluator.getPhaseError()); - } - - if(mPLLFrequencyListener != null) - { - double loopFrequency = ((CostasLoop)getPLL()).getLoopFrequency(); - - loopFrequency *= mSampleRate / (2.0 * FastMath.PI); - - mPLLFrequencyListener.receive(loopFrequency); - } - } - - /** - * Registers a listener to receive symbol decision data to produce an eye diagram. - */ - public void setSymbolDecisionDataListener(Listener listener) - { - mSymbolDecisionDataListener = listener; - } - - /** - * Registers the listener to receive PLL error values - */ - public void setSamplesPerSymbolListener(Listener listener) - { - mSamplesPerSymbolListener = listener; - } - - /** - * Registers the listener to receive decoded QPSK symbols - */ - public void setComplexSymbolListener(Listener listener) - { - mComplexSymbolListener = listener; - } - - /** - * Registers the listener to receive PLL error values - */ - public void setPLLErrorListener(Listener listener) - { - mPLLErrorListener = listener; - } - - /** - * Registers the listener to receive PLL error values - */ - public void setPLLFrequencyListener(Listener listener) - { - mPLLFrequencyListener = listener; - } - - /** - * Registers the listener to receive complex sample buffers that have been filtered with automatic gain control applied - */ - public void setFilteredGainAppliedComplexBufferListener(Listener listener) - { - mFilteredGainAppliedComplexBufferListener = listener; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/GardnerDetector.java b/src/main/java/io/github/dsheirer/dsp/psk/GardnerDetector.java deleted file mode 100644 index af0197de..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/GardnerDetector.java +++ /dev/null @@ -1,83 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.sample.complex.Complex; -import org.apache.commons.math3.util.FastMath; - -public class GardnerDetector -{ - private float mErrorInphase; - private float mErrorQuadrature; - private float mError; - - /** - * Gardner detector for recovering symbol timing error. - */ - public GardnerDetector() - { - } - - - /** - * Calculates the symbol timing error by evaluating the previous, middle and current symbol instants. - * - * @param previous symbol - * @param middle symbol (ie midway between the previous and current) - * @param current symbol - * @return symbol timing error - */ - public float getError(Complex previous, Complex middle, Complex current) - { - mErrorInphase = (FastMath.abs(previous.inphase()) - FastMath.abs(current.inphase())) * FastMath.abs(middle.inphase()); - mErrorQuadrature = (FastMath.abs(previous.quadrature()) - FastMath.abs(current.quadrature())) * FastMath.abs(middle.quadrature()); - mError = normalize(mErrorInphase + mErrorQuadrature, 1.0f); - - return mError; - } - - /** - * Constrains timing error to +/- the maximum value and corrects any floating point invalid numbers - */ - public static float normalize(float error, float maximum) - { - if(Float.isNaN(error)) - { - return 0.0f; - } - else - { - return clip(error, maximum); - } - } - - /** - * Constrains value to the range of ( -maximum <> maximum ) - */ - public static float clip(float value, float maximum) - { - if(value > maximum) - { - return maximum; - } - else if(value < -maximum) - { - return -maximum; - } - - return value; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/IQPSKSymbolDecoder.java b/src/main/java/io/github/dsheirer/dsp/psk/IQPSKSymbolDecoder.java deleted file mode 100644 index 0befad75..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/IQPSKSymbolDecoder.java +++ /dev/null @@ -1,29 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.symbol.Dibit; -import io.github.dsheirer.sample.complex.Complex; - -public interface IQPSKSymbolDecoder -{ - /** - * Decodes the symbol and converts it into a Dibit - * @param symbol to decode - * @return decoded dibit - */ - Dibit decode(Complex symbol); -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/ISymbolPhaseErrorCalculator.java b/src/main/java/io/github/dsheirer/dsp/psk/ISymbolPhaseErrorCalculator.java deleted file mode 100644 index 4e413d88..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/ISymbolPhaseErrorCalculator.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.sample.complex.Complex; - -public interface ISymbolPhaseErrorCalculator -{ - /** - * Calculates the phase error of the symbol relative to an alignment for the constellation - * @param symbol to calculate error - * @return error value - */ - float getPhaseError(Complex symbol); -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/InterpolatingSampleBufferInstrumented.java b/src/main/java/io/github/dsheirer/dsp/psk/InterpolatingSampleBufferInstrumented.java deleted file mode 100644 index ecb08166..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/InterpolatingSampleBufferInstrumented.java +++ /dev/null @@ -1,80 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2019 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.sample.complex.Complex; -import io.github.dsheirer.sample.complex.ComplexSampleListener; -import org.apache.commons.math3.util.FastMath; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class InterpolatingSampleBufferInstrumented extends InterpolatingSampleBuffer -{ - private final static Logger mLog = LoggerFactory.getLogger(InterpolatingSampleBufferInstrumented.class); - private SymbolDecisionData mSymbolDecisionData; - private ComplexSampleListener mSampleListener; - private int mBufferLength; - - public InterpolatingSampleBufferInstrumented(float samplesPerSymbol, float symbolTimingGain) - { - super(samplesPerSymbol, symbolTimingGain); - mBufferLength = (int) FastMath.ceil(samplesPerSymbol); - mSymbolDecisionData = new SymbolDecisionData(mBufferLength); - } - - public void receive(Complex sample) - { - super.receive(sample); - mSymbolDecisionData.receive(sample); - - if(mSampleListener != null) - { - mSampleListener.receive(sample.inphase(), sample.quadrature()); - } - } - - /** - * Contents of the interpolating buffer and the current buffer index and symbol decision offset. This data can - * be used to support an external eye-diagram chart. - * @return symbol decision data. - */ - public SymbolDecisionData getSymbolDecisionData() - { - for(int x = mDelayLinePointer; x < mDelayLinePointer + mBufferLength; x++) - { - mSymbolDecisionData.receive(mDelayLineInphase[x], mDelayLineQuadrature[x]); - } - - mSymbolDecisionData.setSamplingPoint(getSamplingPoint()); - return mSymbolDecisionData; - } - - /** - * Sets the listener to receive samples being sent to this buffer. Note: these samples have - * already been corrected by the PLL, so this provides an ideal tap point for PLL corrected samples. - * @param listener to receive samples. - */ - public void setSampleListener(ComplexSampleListener listener) - { - mSampleListener = listener; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/LSMConstellationDecoder.java b/src/main/java/io/github/dsheirer/dsp/psk/LSMConstellationDecoder.java deleted file mode 100644 index 7c500838..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/LSMConstellationDecoder.java +++ /dev/null @@ -1,28 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.symbol.Dibit; -import io.github.dsheirer.sample.complex.Complex; - -public class LSMConstellationDecoder implements IQPSKSymbolDecoder -{ - @Override - public Dibit decode(Complex symbol) - { - return null; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/QPSKStarSlicer.java b/src/main/java/io/github/dsheirer/dsp/psk/QPSKStarSlicer.java deleted file mode 100644 index b8295145..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/QPSKStarSlicer.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.symbol.Dibit; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; - -public class QPSKStarSlicer implements IQPSKSymbolDecoder, Listener -{ - private Broadcaster mBroadcaster = new Broadcaster(); - - /** - * Slices a Complex sample representing a phase shifted symbol according to the following constellation pattern: - * - * 00 +3 | 01 +1 - * ------|------ - * 10 -1 | 11 -1 - */ - public QPSKStarSlicer() - { - } - - public void dispose() - { - mBroadcaster.dispose(); - mBroadcaster = null; - } - - public void addListener(Listener listener) - { - mBroadcaster.addListener(listener); - } - - public void removeListener(Listener listener) - { - mBroadcaster.removeListener(listener); - } - - @Override - public void receive(Complex sample) - { - mBroadcaster.broadcast(decode(sample)); - } - - @Override - public Dibit decode(Complex sample) - { - if(sample.inphase() > 0) - { - return sample.quadrature() > 0 ? Dibit.D00_PLUS_1 : Dibit.D10_MINUS_1; - } - else - { - return sample.quadrature() > 0 ? Dibit.D01_PLUS_3 : Dibit.D11_MINUS_3; - } - } - -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolDecoder.java b/src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolDecoder.java deleted file mode 100644 index d4dcfa6a..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolDecoder.java +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.dsp.symbol.Dibit; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; -import org.apache.commons.math3.util.FastMath; - -public class QPSKSymbolDecoder implements Listener, IQPSKSymbolDecoder -{ - private Broadcaster mBroadcaster = new Broadcaster(); - - /** - * Slices a ComplexSample representing a phase shifted symbol according to - * the following constellation pattern: - * - * \ 00 / - * \ / - * 01 \/ 10 - * /\ - * / \ - * / 11 \ - */ - public QPSKSymbolDecoder() - { - } - - public void dispose() - { - mBroadcaster.dispose(); - mBroadcaster = null; - } - - public void addListener( Listener listener ) - { - mBroadcaster.addListener( listener ); - } - - public void removeListener( Listener listener ) - { - mBroadcaster.removeListener( listener ); - } - - @Override - public void receive( Complex complex ) - { - mBroadcaster.broadcast( decode( complex ) ); - } - - public Dibit decode(Complex complex ) - { - if( FastMath.abs( complex.inphase() ) > FastMath.abs( complex.quadrature() ) ) - { - if( complex.inphase() > 0 ) - { - return Dibit.D10_MINUS_1; - } - else - { - return Dibit.D01_PLUS_3; - } - } - else - { - if( complex.quadrature() > 0 ) - { - return Dibit.D00_PLUS_1; - } - else - { - return Dibit.D11_MINUS_3; - } - } - } - -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolPhaseErrorCalculator.java b/src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolPhaseErrorCalculator.java deleted file mode 100644 index 0fe1d5f8..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolPhaseErrorCalculator.java +++ /dev/null @@ -1,58 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.sample.complex.Complex; -import org.apache.commons.math3.util.FastMath; - -/** - * Calculates the phase error for a QPSK polar-orientation constellation - */ -public class QPSKSymbolPhaseErrorCalculator implements ISymbolPhaseErrorCalculator -{ - private float mPhaseError; - - @Override - public float getPhaseError(Complex symbol) - { - mPhaseError = 0.0f; - - if(FastMath.abs(symbol.inphase()) > FastMath.abs(symbol.quadrature())) - { - if(symbol.inphase() > 0) - { - mPhaseError = -symbol.quadrature(); - } - else - { - mPhaseError = symbol.quadrature(); - } - } - else - { - if(symbol.quadrature() > 0) - { - mPhaseError = symbol.inphase(); - } - else - { - mPhaseError = -symbol.inphase(); - } - } - - return mPhaseError; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/SymbolDecisionData.java b/src/main/java/io/github/dsheirer/dsp/psk/SymbolDecisionData.java deleted file mode 100644 index 327fde75..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/SymbolDecisionData.java +++ /dev/null @@ -1,115 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2019 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.dsp.psk; - -import io.github.dsheirer.buffer.ComplexCircularBuffer; -import io.github.dsheirer.sample.complex.Complex; -import org.apache.commons.math3.util.FastMath; - -public class SymbolDecisionData -{ - //45 degrees rotation to orient the symbol to a polar axis to make error calculation easy/efficient - public static final Complex DIFFERENTIAL_OFFSET = Complex.fromAngle(FastMath.PI / 4.0d); - - private ComplexCircularBuffer mBuffer; - private float mSamplingPoint; - private float mSamplesPerSymbol; - - /** - * Circular buffer for capturing two symbols worth of sample data for use in instrumentation. - * @param samplesPerSymbol to size the buffer - */ - public SymbolDecisionData(float samplesPerSymbol) - { - mSamplesPerSymbol = samplesPerSymbol; - mBuffer = new ComplexCircularBuffer(8); - } - - /** - * Stores the complex sample in the buffer - */ - public void receive(float inphase, float quadrature) - { - mBuffer.put(new Complex(inphase, quadrature)); - } - - /** - * Stores the complex sample in the buffer - */ - public void receive(Complex complex) - { - mBuffer.put(complex.copy()); - } - - /** - * Sets the fractional sampling point for the current symbol to use in interpolating the current symbol. - */ - public void setSamplingPoint(float samplingPoint) - { - mSamplingPoint = samplingPoint; - } - - /** - * Fractional sampling point - */ - public float getSamplingPoint() - { - return mSamplingPoint; - } - - /** - * Raw samples - */ - public Complex[] getSamples() - { - return mBuffer.getAll(); - } - - public Complex[] getSamples(int length) - { - return mBuffer.get(length); - } - - /** - * Array of (FM) demodulated samples representing the current symbol where each current sample is demodulated against - * the previous symbol's sample to produce the differential demodulated sample. Samples are in time order. - * - * Note: differential decoding is on an integral samples-per-symbol basis and does not use fractional interpolation. - */ - public Complex[] getDemodulated() - { - Complex[] samples = mBuffer.getAll(); - - int length = samples.length / 2; - - Complex[] demodulated = new Complex[length]; - - for(int x = 0; x < samples.length / 2; x++) - { - Complex copy = samples[length + x].copy(); - copy.multiply(samples[x].conjugate()); - demodulated[x] = copy; - } - - return demodulated; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/SymbolInversion.java b/src/main/java/io/github/dsheirer/dsp/psk/SymbolInversion.java deleted file mode 100644 index 22d55f37..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/SymbolInversion.java +++ /dev/null @@ -1,37 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.dsp.psk; - -import org.apache.commons.math3.util.FastMath; - -public enum SymbolInversion -{ - DEGREES_90_PLUS(FastMath.PI / 2.0), - DEGREES_90_MINUS(FastMath.PI / -2.0), - DEGREES_180(FastMath.PI); - - private double mAngleRadians; - - SymbolInversion(double angleRadians) - { - mAngleRadians = angleRadians; - } - - public double getError() - { - return mAngleRadians; - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFactory.java b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFactory.java index d8253de5..22aae9b9 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFactory.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFactory.java @@ -22,34 +22,30 @@ package io.github.dsheirer.dsp.psk.demod; import io.github.dsheirer.vector.calibrate.CalibrationManager; import io.github.dsheirer.vector.calibrate.CalibrationType; import io.github.dsheirer.vector.calibrate.Implementation; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; /** * Factory for creating PSK differential demodulators */ public class DifferentialDemodulatorFactory { - private static final Logger mLog = LoggerFactory.getLogger(DifferentialDemodulatorFactory.class); - /** - * Creates the optimal demodulator using calibration data to select the optimal implementation from scalar and - * vector options, or defaults to the scalar implementation if the calibration wasn't executed. + * Creates the optimal float output demodulator using calibration data to select the optimal implementation from + * scalar and vector options, or defaults to the scalar implementation if the calibration wasn't executed. * @param sampleRate in Hertz * @param symbolRate in Hertz * @return demodulator instance */ - public static DifferentialDemodulator getDemodulator(double sampleRate, int symbolRate) + public static DifferentialDemodulatorFloat getFloatDemodulator(double sampleRate, int symbolRate) { Implementation implementation = CalibrationManager.getInstance().getImplementation(CalibrationType.DIFFERENTIAL_DEMODULATOR); return switch(implementation) { - case VECTOR_SIMD_64 -> new DifferentialDemodulatorVector64(sampleRate, symbolRate); - case VECTOR_SIMD_128 -> new DifferentialDemodulatorVector128(sampleRate, symbolRate); - case VECTOR_SIMD_256 -> new DifferentialDemodulatorVector256(sampleRate, symbolRate); - case VECTOR_SIMD_512 -> new DifferentialDemodulatorVector512(sampleRate, symbolRate); - default -> new DifferentialDemodulatorScalar(sampleRate, symbolRate); //Includes SCALAR case + case VECTOR_SIMD_64 -> new DifferentialDemodulatorFloatVector64(sampleRate, symbolRate); + case VECTOR_SIMD_128 -> new DifferentialDemodulatorFloatVector128(sampleRate, symbolRate); + case VECTOR_SIMD_256 -> new DifferentialDemodulatorFloatVector256(sampleRate, symbolRate); + case VECTOR_SIMD_512 -> new DifferentialDemodulatorFloatVector512(sampleRate, symbolRate); + default -> new DifferentialDemodulatorFloatScalar(sampleRate, symbolRate); //Includes SCALAR case }; } } diff --git a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulator.java b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloat.java similarity index 87% rename from src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulator.java rename to src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloat.java index 53f0ea88..142c6ed4 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulator.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloat.java @@ -26,7 +26,7 @@ import io.github.dsheirer.dsp.fm.IDemodulator; /** * Differential demodulator base class */ -public abstract class DifferentialDemodulator implements IDemodulator +public abstract class DifferentialDemodulatorFloat implements IDemodulator { private int mSymbolRate; private float mSampleRate; @@ -37,14 +37,14 @@ public abstract class DifferentialDemodulator implements IDemodulator protected int mBufferOverlap; protected int mInterpolationOffset; protected final Interpolator mInterpolator = InterpolatorFactory.getInterpolator(); - private DifferentialDemodulatorScalar mScalar; + private DifferentialDemodulatorFloatScalar mScalar; /** * Constructor * @param sampleRate in Hertz * @param symbolRate symbols per second */ - public DifferentialDemodulator(double sampleRate, int symbolRate) + public DifferentialDemodulatorFloat(double sampleRate, int symbolRate) { mSampleRate = (float) sampleRate; mSymbolRate = symbolRate; @@ -64,11 +64,11 @@ public abstract class DifferentialDemodulator implements IDemodulator * Scalar implementation for fallback when the sample buffer size is not compatible with the vector implementation. * @return scalar implementation lazy instantiated when needed. */ - protected DifferentialDemodulatorScalar getScalarImplementation() + protected DifferentialDemodulatorFloatScalar getScalarImplementation() { if(mScalar == null) { - mScalar = new DifferentialDemodulatorScalar(mSampleRate, mSymbolRate); + mScalar = new DifferentialDemodulatorFloatScalar(mSampleRate, mSymbolRate); } return mScalar; diff --git a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorScalar.java b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatScalar.java similarity index 94% rename from src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorScalar.java rename to src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatScalar.java index 0781206a..ea8ad1bb 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorScalar.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatScalar.java @@ -26,16 +26,16 @@ import org.slf4j.LoggerFactory; /** * Differential demodulator that uses scalar calculations for demodulating the sample stream. */ -public class DifferentialDemodulatorScalar extends DifferentialDemodulator +public class DifferentialDemodulatorFloatScalar extends DifferentialDemodulatorFloat { - private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorScalar.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorFloatScalar.class); /** * Constructor * * @param symbolRate symbols per second */ - public DifferentialDemodulatorScalar(double sampleRate, int symbolRate) + public DifferentialDemodulatorFloatScalar(double sampleRate, int symbolRate) { super(sampleRate, symbolRate); } diff --git a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector128.java b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector128.java similarity index 95% rename from src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector128.java rename to src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector128.java index f98829ee..72a2103d 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector128.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector128.java @@ -29,9 +29,9 @@ import org.slf4j.LoggerFactory; /** * Differential demodulator that uses Vector SIMD 128 calculations for demodulating the sample stream. */ -public class DifferentialDemodulatorVector128 extends DifferentialDemodulator +public class DifferentialDemodulatorFloatVector128 extends DifferentialDemodulatorFloat { - private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorVector128.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorFloatVector128.class); private static final VectorSpecies VECTOR_SPECIES = FloatVector.SPECIES_128; /** @@ -40,7 +40,7 @@ public class DifferentialDemodulatorVector128 extends DifferentialDemodulator * @param sampleRate in Hertz * @param symbolRate symbols per second */ - public DifferentialDemodulatorVector128(double sampleRate, int symbolRate) + public DifferentialDemodulatorFloatVector128(double sampleRate, int symbolRate) { super(sampleRate, symbolRate); } diff --git a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector256.java b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector256.java similarity index 96% rename from src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector256.java rename to src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector256.java index ab82190a..ef5bc6af 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector256.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector256.java @@ -27,7 +27,7 @@ import jdk.incubator.vector.VectorSpecies; /** * Differential demodulator that uses Vector SIMD calculations for demodulating the sample stream. */ -public class DifferentialDemodulatorVector256 extends DifferentialDemodulator +public class DifferentialDemodulatorFloatVector256 extends DifferentialDemodulatorFloat { private static final VectorSpecies VECTOR_SPECIES = FloatVector.SPECIES_256; @@ -37,7 +37,7 @@ public class DifferentialDemodulatorVector256 extends DifferentialDemodulator * @param sampleRate in Hertz * @param symbolRate symbols per second */ - public DifferentialDemodulatorVector256(double sampleRate, int symbolRate) + public DifferentialDemodulatorFloatVector256(double sampleRate, int symbolRate) { super(sampleRate, symbolRate); } diff --git a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector512.java b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector512.java similarity index 95% rename from src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector512.java rename to src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector512.java index 8108b8d8..579bdea2 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector512.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector512.java @@ -29,9 +29,9 @@ import org.slf4j.LoggerFactory; /** * Differential demodulator that uses Vector SIMD 512 calculations for demodulating the sample stream. */ -public class DifferentialDemodulatorVector512 extends DifferentialDemodulator +public class DifferentialDemodulatorFloatVector512 extends DifferentialDemodulatorFloat { - private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorVector512.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorFloatVector512.class); private static final VectorSpecies VECTOR_SPECIES = FloatVector.SPECIES_512; /** @@ -39,7 +39,7 @@ public class DifferentialDemodulatorVector512 extends DifferentialDemodulator * * @param symbolRate symbols per second */ - public DifferentialDemodulatorVector512(double sampleRate, int symbolRate) + public DifferentialDemodulatorFloatVector512(double sampleRate, int symbolRate) { super(sampleRate, symbolRate); } diff --git a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector64.java b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector64.java similarity index 95% rename from src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector64.java rename to src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector64.java index 983de06d..00d9e555 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorVector64.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/demod/DifferentialDemodulatorFloatVector64.java @@ -29,9 +29,9 @@ import org.slf4j.LoggerFactory; /** * Differential demodulator that uses Vector SIMD 64 calculations for demodulating the sample stream. */ -public class DifferentialDemodulatorVector64 extends DifferentialDemodulator +public class DifferentialDemodulatorFloatVector64 extends DifferentialDemodulatorFloat { - private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorVector64.class); + private static final Logger LOGGER = LoggerFactory.getLogger(DifferentialDemodulatorFloatVector64.class); private static final VectorSpecies VECTOR_SPECIES = FloatVector.SPECIES_64; /** @@ -40,7 +40,7 @@ public class DifferentialDemodulatorVector64 extends DifferentialDemodulator * @param sampleRate in Hertz * @param symbolRate symbols per second */ - public DifferentialDemodulatorVector64(double sampleRate, int symbolRate) + public DifferentialDemodulatorFloatVector64(double sampleRate, int symbolRate) { super(sampleRate, symbolRate); } diff --git a/src/main/java/io/github/dsheirer/dsp/psk/pll/AdaptivePLLBandwidthMonitor.java b/src/main/java/io/github/dsheirer/dsp/psk/pll/AdaptivePLLBandwidthMonitor.java deleted file mode 100644 index 3e2cd1b9..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/pll/AdaptivePLLBandwidthMonitor.java +++ /dev/null @@ -1,125 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.dsp.psk.pll; - -import io.github.dsheirer.dsp.symbol.ISyncDetectListener; -import io.github.dsheirer.module.decode.FeedbackDecoder; -import io.github.dsheirer.source.SourceEvent; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Monitors decode sync events to adaptively control PLL loop gain. - */ -public class AdaptivePLLBandwidthMonitor implements ISyncDetectListener, IFrequencyErrorProcessor -{ - private final static Logger mLog = LoggerFactory.getLogger(AdaptivePLLBandwidthMonitor.class); - - private static final int MAX_SYNC_COUNT = PLLBandwidth.BW_200.getRangeEnd(); - private CostasLoop mCostasLoop; - private FeedbackDecoder mFeedbackDecoder; - private PLLBandwidth mPLLBandwidth = PLLBandwidth.BW_400; - private int mSyncCount; - - /** - * Constructs an adaptive monitor to monitor the sync state of a decoder and adjust the gain - * level of the costas loop accordingly. - * - * @param costasLoop to receive adaptive gain updates. - * @param feedbackDecoder to rebroadcast frequency error source events - */ - public AdaptivePLLBandwidthMonitor(CostasLoop costasLoop, FeedbackDecoder feedbackDecoder) - { - mCostasLoop = costasLoop; - mCostasLoop.setPLLBandwidth(mPLLBandwidth); - mCostasLoop.setFrequencyErrorProcessor(this); - mFeedbackDecoder = feedbackDecoder; - } - - /** - * Sync detection event. Updates the running sync count and updates the PLL gain level. - */ - @Override - public void syncDetected(int bitErrors) - { - mSyncCount++; - update(); - } - - /** - * Sync loss event. Updates the running sync count and updates the PLL gain level. - */ - @Override - public void syncLost(int bitsProcessed) - { - mSyncCount -= 2; - update(); - } - - /** - * Updates the gain state for a sync detect or sync loss - */ - private void update() - { - if(mSyncCount < 0) - { - mSyncCount = 0; - return; - } - - if(mSyncCount > MAX_SYNC_COUNT) - { - mSyncCount = MAX_SYNC_COUNT; - return; - } - - PLLBandwidth gain = PLLBandwidth.fromSyncCount(mSyncCount); - - //Only update the costas loop if the gain value changes - if(gain != mPLLBandwidth) - { - mPLLBandwidth = gain; - mCostasLoop.setPLLBandwidth(mPLLBandwidth); - } - } - - /** - * Resets the monitor and commands the PLL to use the highest gain level. - */ - public void reset() - { - mSyncCount = 0; - mPLLBandwidth = PLLBandwidth.BW_400; - mCostasLoop.setPLLBandwidth(mPLLBandwidth); - } - - @Override - public void processFrequencyError(long frequencyError) - { - //Only rebroadcast the costas loop frequency error if the gain level has progressed above - //a bandwidth of 300, meaning that we have received at least 4 sync events - if(mPLLBandwidth != PLLBandwidth.BW_400 && mPLLBandwidth != PLLBandwidth.BW_300) - { - mFeedbackDecoder.broadcast(SourceEvent.frequencyErrorMeasurement(frequencyError)); - } - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/psk/pll/FrequencyCorrectionSyncMonitor.java b/src/main/java/io/github/dsheirer/dsp/psk/pll/FrequencyCorrectionSyncMonitor.java index 2cd2358e..b02f04fe 100644 --- a/src/main/java/io/github/dsheirer/dsp/psk/pll/FrequencyCorrectionSyncMonitor.java +++ b/src/main/java/io/github/dsheirer/dsp/psk/pll/FrequencyCorrectionSyncMonitor.java @@ -27,6 +27,7 @@ import org.slf4j.LoggerFactory; /** * Monitors decode sync events to adaptively control frequency correction broadcasts. */ +@Deprecated //Remove after P25P2 decoder gets updated public class FrequencyCorrectionSyncMonitor implements ISyncDetectListener, IFrequencyErrorProcessor { private final static Logger mLog = LoggerFactory.getLogger(FrequencyCorrectionSyncMonitor.class); diff --git a/src/main/java/io/github/dsheirer/dsp/psk/pll/QPSKPhaseInversionCalculator.java b/src/main/java/io/github/dsheirer/dsp/psk/pll/QPSKPhaseInversionCalculator.java deleted file mode 100644 index 58ce1688..00000000 --- a/src/main/java/io/github/dsheirer/dsp/psk/pll/QPSKPhaseInversionCalculator.java +++ /dev/null @@ -1,133 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ - -package io.github.dsheirer.dsp.psk.pll; - -import io.github.dsheirer.dsp.symbol.Dibit; - -/** - * Utility for calculating phase inverted sync pattern derivatives for QPSK constellations - */ -public class QPSKPhaseInversionCalculator -{ - public static void main(String[] args) - { - - //DMR sync patterns -// String[] syncs = {"755FD7DF75F7", "DFF57D75DF5D", "7F7D5DD57DFD", "D5D7F77FD757", "77D55F7DFD77", -// "5D577F7757FF", "F7FDD5DDFD55", "7DFFD5F55D5F", "D7557F5FF7F5", "DD7FF5D757DD"}; - - //P25 Phase 2 sync pattern - String[] syncs = {"575D57F7FF"}; - - //P25 Phase 1 sync pattern -// String[] syncs = {"5575F5FF77FF"}; - - - for(String sync: syncs) - { - StringBuilder sbNorm = new StringBuilder(); - StringBuilder sbP90 = new StringBuilder(); - StringBuilder sbM90 = new StringBuilder(); - StringBuilder sb180 = new StringBuilder(); - - for(char letter: sync.toCharArray()) - { - int value; - - if(Character.isAlphabetic(letter)) - { - value = letter - 55; - } - else - { - value = letter - 48; - } - - sbNorm.append(letter); - sbP90.append(rotate(value, Dibit.Rotation.PLUS90)); - sbM90.append(rotate(value, Dibit.Rotation.MINUS90)); - sb180.append(rotate(value, Dibit.Rotation.INVERT)); - } - - System.out.println("NORMAL: " + sync); - System.out.println(" +90: " + sbP90); - System.out.println(" -90: " + sbM90); - System.out.println(" 180: " + sb180); - } - } - - /** - * Converts the hexadecimal value to an integer, decomposes it into high and low order dibits, rotates the dibits - * in the specified direction, and recombines the rotated dibits into a 4-bit value, returned as a hex character. - * @param value to rotate - * @param direction direction - * @return rotated hex character - */ - public static String rotate(int value, Dibit.Rotation direction) - { - try - { - Dibit dibitHigh = getHighDibit(value); - Dibit dibitLow = getLowDibit(value); - return getHex(dibitHigh.rotate(direction), dibitLow.rotate(direction)); - } - catch(Exception e) - { - //ignore - } - - return "-"; - } - - /** - * Combines the bit values from the two dibits and converts the integer value to a hex character - * @param d1 containing the high order bits - * @param d2 containing the low order bits - * @return string hex character representing the value of these dibits combined - */ - public static String getHex(Dibit d1, Dibit d2) - { - int value = d1.getHighValue() + d2.getLowValue(); - return Integer.toHexString(value).toUpperCase(); - } - - /** - * Calculates the dibit that represents the bits in the 0x8 and 0x4 bit positions of the value - * @param value - * @return a dibit - */ - public static Dibit getHighDibit(int value) - { - return Dibit.fromValue((value >> 2) & 3); - } - - /** - * Calculates the dibit that represents the bits in the 0x2 and 0x1 bit positions of the value - * @param value - * @return a dibit - */ - public static Dibit getLowDibit(int value) - { - return Dibit.fromValue(value & 3); - } -} diff --git a/src/main/java/io/github/dsheirer/dsp/squelch/PowerMonitor.java b/src/main/java/io/github/dsheirer/dsp/squelch/PowerMonitor.java index ca14acef..0f552dfe 100644 --- a/src/main/java/io/github/dsheirer/dsp/squelch/PowerMonitor.java +++ b/src/main/java/io/github/dsheirer/dsp/squelch/PowerMonitor.java @@ -34,14 +34,14 @@ public class PowerMonitor private int mPowerLevelBroadcastCount = 0; private int mPowerLevelBroadcastThreshold; private Listener mSourceEventListener; - private SinglePoleIirFilter mPowerFilter = new SinglePoleIirFilter(0.1f); + private final SinglePoleIirFilter mPowerFilter = new SinglePoleIirFilter(0.1f); /** * Constructs an instance */ public PowerMonitor() { - mPowerLevelBroadcastThreshold = 25000; //Based on a default sample rate of 50 kHz + mPowerLevelBroadcastThreshold = 12500; //Based on a default sample rate of 25 kHz } /** @@ -54,36 +54,25 @@ public class PowerMonitor mPowerLevelBroadcastThreshold = sampleRate / 2; } - /** - * Processes a complex IQ sample and changes squelch state when the signal power is above or below the - * threshold value. - * @param inphase complex sample component - * @param quadrature complex sample component - */ - public void process(float inphase, float quadrature) - { - mPowerLevelBroadcastCount++; - - if(mPowerLevelBroadcastCount > mPowerLevelBroadcastThreshold) - { - mPowerFilter.filter(inphase * inphase + quadrature * quadrature); - } - - if(mPowerLevelBroadcastCount > (mPowerLevelBroadcastThreshold + 10)) - { - mPowerLevelBroadcastCount = 0; - broadcast(SourceEvent.channelPowerLevel(null, 10.0 * Math.log10(mPowerFilter.getValue()))); - } - } - /** * Processes I&Q complex baseband sample buffers. */ public void process(float[] i, float[] q) { - for(int x = 0; x < i.length; x++) + mPowerLevelBroadcastCount += i.length; + + if(mPowerLevelBroadcastCount > mPowerLevelBroadcastThreshold && i.length >= 10) { - process(i[x], q[x]); + double iSquared, qSquared; + for(int x = 0; x < 10; x++) + { + iSquared = Math.pow(i[x], 2.0f); + qSquared = Math.pow(q[x], 2.0f); + mPowerFilter.filter((float)(iSquared + qSquared)); + } + + mPowerLevelBroadcastCount -= mPowerLevelBroadcastThreshold; + broadcast(SourceEvent.channelPowerLevel(null, 10.0 * Math.log10(mPowerFilter.getValue()))); } } diff --git a/src/main/java/io/github/dsheirer/dsp/symbol/Dibit.java b/src/main/java/io/github/dsheirer/dsp/symbol/Dibit.java index 6b9230b5..656a9bb4 100644 --- a/src/main/java/io/github/dsheirer/dsp/symbol/Dibit.java +++ b/src/main/java/io/github/dsheirer/dsp/symbol/Dibit.java @@ -265,15 +265,24 @@ public enum Dibit } } - public static void main(String[] args) + /** + * Number of bit errors between this dibit and the expected dibit argument. + * @param dibit to compare + * @return 0, 1 or 2 bit errors + */ + public int getBitErrorFrom(Dibit dibit) { - byte a = (byte)0x1B; + int xor = getValue() ^ dibit.getValue(); - Dibit d1 = Dibit.parse(a, 0); - Dibit d2 = Dibit.parse(a, 1); - Dibit d3 = Dibit.parse(a, 2); - Dibit d4 = Dibit.parse(a, 3); + if(xor == 0) + { + return 0; + } + else if(xor == 3) + { + return 2; + } - System.out.println("1: " + d1 + " 2:" + d2 + " 3:" + d3 + " 4:" + d4); + return 1; } } diff --git a/src/main/java/io/github/dsheirer/dsp/symbol/DibitDelayBuffer.java b/src/main/java/io/github/dsheirer/dsp/symbol/DibitDelayBuffer.java deleted file mode 100644 index 25131e03..00000000 --- a/src/main/java/io/github/dsheirer/dsp/symbol/DibitDelayBuffer.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2019 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ - -package io.github.dsheirer.dsp.symbol; - -import io.github.dsheirer.bits.BitSetFullException; -import io.github.dsheirer.bits.CorrectedBinaryMessage; -import org.apache.commons.lang3.Validate; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -/** - * Circular buffer for storing and accessing dibits. - */ -public class DibitDelayBuffer -{ - private final static Logger mLog = LoggerFactory.getLogger(DibitDelayBuffer.class); - - protected Dibit[] mBuffer; - protected int mPointer; - - /** - * Constructs a dibit delay buffer of the specified length - */ - public DibitDelayBuffer(int length) - { - Validate.isTrue(length > 0, "Dibit buffer length must be greater than 0"); - mBuffer = new Dibit[length]; - reset(); - } - - /** - * Resets the buffer and preloads the buffer with all zeros - */ - public void reset() - { - for(int x = 0; x < mBuffer.length; x++) - { - mBuffer[x] = Dibit.D00_PLUS_1; - } - } - - /** - * Length of this circular buffer - */ - public int length() - { - return mBuffer.length; - } - - /** - * Returns the dibit at the specified index - * @param index to get - * @return dibit at the specified index - */ - public Dibit get(int index) - { - if(index < 0 || index >= mBuffer.length) - { - throw new IllegalArgumentException("Index argument must be between 0 and buffer length [" + mBuffer.length + "]"); - } - - return mBuffer[index]; - } - - /** - * Sets the dibit at the specified index - * @param index of the dibit - * @param dibit to load at the specified index - */ - public void set(int index, Dibit dibit) - { - if(index < 0 || index >= mBuffer.length) - { - throw new IllegalArgumentException("Index argument must be between 0 and buffer length [" + mBuffer.length + "]"); - } - - mBuffer[index] = dibit; - } - - /** - * Returns an ordered view of the internal circular buffer contents. - */ - public Dibit[] getBuffer() - { - Dibit[] transferBuffer = new Dibit[mBuffer.length]; - - int transferBufferPointer = 0; - int bufferPointer = mPointer; - - while(transferBufferPointer < transferBuffer.length) - { - transferBuffer[transferBufferPointer++] = mBuffer[bufferPointer++]; - - if(bufferPointer >= mBuffer.length) - { - bufferPointer = 0; - } - } - - return transferBuffer; - } - - /** - * Retrieves a view of the buffer from the starting index to the specified length. Note: if the requested - * length exceeds the length of this buffer, the contents will be unwrapped from the circular buffer and repeated. - * @param start of the view where 0 is the first element. - * @param length of the dibit view - * @return an array of dibits - */ - public Dibit[] getBuffer(int start, int length) - { - Dibit[] transferBuffer = new Dibit[length]; - - int transferBufferPointer = 0; - int bufferPointer = (mPointer + start) % mBuffer.length; - - while(transferBufferPointer < transferBuffer.length) - { - transferBuffer[transferBufferPointer++] = mBuffer[bufferPointer++]; - - if(bufferPointer >= mBuffer.length) - { - bufferPointer = 0; - } - } - - return transferBuffer; - } - - /** - * Extracts a corrected binary message from the dibit buffer - * - * @param start dibit index where 0 is the oldest dibit and the newest dibit is buffer length - 1 - * @param dibitLength number of dibits to include in the message, making the message length = dibitLength * 2 - * @return corrected binary message - */ - public CorrectedBinaryMessage getMessage(int start, int dibitLength) - { - CorrectedBinaryMessage message = new CorrectedBinaryMessage(dibitLength * 2); - - int dibitCount = 0; - int bufferPointer = (mPointer + start) % mBuffer.length; - - try - { - while(dibitCount < dibitLength) - { - Dibit dibit = mBuffer[bufferPointer++]; - message.add(dibit.getBit1()); - message.add(dibit.getBit2()); - dibitCount++; - - if(bufferPointer >= mBuffer.length) - { - bufferPointer = 0; - } - } - } - catch(BitSetFullException e) - { - //This shouldn't happen - mLog.error("Bit set full ??", e); - } - - return message; - } - - /** - * Utility method to view the buffer contents with the dibits decoded as an array of zeros and ones. - */ - public int[] getBufferAsArray() - { - Dibit[] dibits = getBuffer(); - - int[] bits = new int[dibits.length * 2]; - - for(int x = 0; x < dibits.length; x++) - { - if(dibits[x].getBit1()) - { - bits[x * 2] = 1; - } - if(dibits[x].getBit2()) - { - bits[x * 2 + 1] = 1; - } - } - - return bits; - } - - /** - * Places the dibit into the internal circular buffer, overwriting the oldest dibit. - */ - public void put(Dibit dibit) - { - mBuffer[mPointer++] = dibit; - - if(mPointer >= mBuffer.length) - { - mPointer = 0; - } - } - - /** - * Places the dibit into the internal circular buffer, overwriting and returning the - * oldest dibit. - */ - public Dibit getAndPut(Dibit dibit) - { - Dibit toReturn = mBuffer[mPointer]; - put(dibit); - return toReturn; - } - - /** - * Logs the contents of the buffer - */ - public void log() - { - StringBuilder sb = new StringBuilder(); - - int counter = 0; - int pointer = mPointer; - - while(counter < mBuffer.length) - { - sb.append(mBuffer[pointer].getBit1() ? "1" : "0"); - sb.append(mBuffer[pointer++].getBit2() ? "1" : "0"); - - if(pointer >= mBuffer.length) - { - pointer = 0; - } - - counter++; - } - mLog.debug("BUFFER: " + sb + " Length:" + mBuffer.length); - } -} diff --git a/src/main/java/io/github/dsheirer/module/decode/dmr/DibitDelayLine.java b/src/main/java/io/github/dsheirer/dsp/symbol/DibitDelayLine.java similarity index 74% rename from src/main/java/io/github/dsheirer/module/decode/dmr/DibitDelayLine.java rename to src/main/java/io/github/dsheirer/dsp/symbol/DibitDelayLine.java index d2b25615..9ad6403a 100644 --- a/src/main/java/io/github/dsheirer/module/decode/dmr/DibitDelayLine.java +++ b/src/main/java/io/github/dsheirer/dsp/symbol/DibitDelayLine.java @@ -17,9 +17,8 @@ * **************************************************************************** */ -package io.github.dsheirer.module.decode.dmr; +package io.github.dsheirer.dsp.symbol; -import io.github.dsheirer.dsp.symbol.Dibit; import java.util.Arrays; /** @@ -27,9 +26,8 @@ import java.util.Arrays; */ public class DibitDelayLine { - private Dibit[] mDelayLine; + protected Dibit[] mDelayLine; public int mPointer; - private int mLength; /** * Constructs an instance @@ -37,7 +35,6 @@ public class DibitDelayLine */ public DibitDelayLine(int length) { - mLength = length; mDelayLine = new Dibit[length]; Arrays.fill(mDelayLine, Dibit.D00_PLUS_1); } @@ -51,7 +48,7 @@ public class DibitDelayLine { Dibit ejected = mDelayLine[mPointer]; mDelayLine[mPointer++] = dibit; - mPointer %= mLength; + mPointer %= mDelayLine.length; return ejected; } @@ -72,10 +69,44 @@ public class DibitDelayLine for(Dibit dibit: dibits) { mDelayLine[mPointer++] = dibit; - mPointer %= mLength; + mPointer %= mDelayLine.length; } } + /** + * Adjusts the pointer to correct a dibit stuff/delete. + * @param offset to adjust. + */ + public void adjustPointer(int offset) + { + mPointer += offset; + + if(mPointer < 0) + { + mPointer += mDelayLine.length; + } + else if(mPointer >= mDelayLine.length) + { + mPointer -= mDelayLine.length; + } + } + + + /** + * Returns the most recently stored Dibit. + */ + public Dibit getLast() + { + int pointer = mPointer - 1; + + if(pointer < 0) + { + pointer += mDelayLine.length; + } + + return mDelayLine[pointer]; + } + public void log() { StringBuilder sb = new StringBuilder(); @@ -89,7 +120,7 @@ public class DibitDelayLine sb.append(" "); pointer++; - pointer = pointer % mLength; + pointer = pointer % mDelayLine.length; } System.out.println(sb); diff --git a/src/main/java/io/github/dsheirer/edac/BCH_63_16_11.java b/src/main/java/io/github/dsheirer/edac/BCH_63_16_11.java deleted file mode 100644 index aac7e24a..00000000 --- a/src/main/java/io/github/dsheirer/edac/BCH_63_16_11.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2020 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ - -package io.github.dsheirer.edac; - -import io.github.dsheirer.bits.BinaryMessage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class BCH_63_16_11 extends ReedSolomon_63_P25 -{ - private final static Logger mLog = LoggerFactory.getLogger(BCH_63_16_11.class); - - /** - * BCH( 63,16,11) decoder - */ - public BCH_63_16_11() - { - super(63, 41); - } - - /** - * Performs error detection and correction on the first 63 bits of the - * message argument. If the message is correctable, only the first 16 bits - * (information bits) are corrected. - * - * @return - true = success, false = failure - */ - public BinaryMessage correctNID(BinaryMessage message) - { - CRC status = CRC.PASSED; - - int[] original = message.toReverseIntegerArray(0, 62); - int[] corrected = new int[63]; - - boolean irrecoverableErrors = decode(original, corrected); - - if(irrecoverableErrors) - { - message.setCRC(CRC.FAILED_CRC); - - return message; - } - else - { - for(int x = 0; x < 16; x++) - { - int index = 63 - x - 1; - - if(corrected[index] != original[index]) - { - status = CRC.CORRECTED; - - if(corrected[index] == 1) - { - message.set(x); - } - else - { - message.clear(x); - } - } - } - } - - message.setCRC(status); - - return message; - } - - public static void main(String[] args) - { - String orig = "0010011000000011010010100000000110000111110011101010001010110000"; - String error = "0001010100000011010010100000000110000111100011001010001010110000"; - - BinaryMessage errorMessage = BinaryMessage.load(error); - - BCH_63_16_11 bch = new BCH_63_16_11(); - - mLog.debug("ORIG:" + orig); - mLog.debug(" ERR:" + errorMessage.toString()); - mLog.debug(" "); - - errorMessage = bch.correctNID(errorMessage); - - mLog.debug(" CRC: " + errorMessage.getCRC().name()); - mLog.debug("CORR:" + errorMessage.toString()); - mLog.debug("ORIG:" + orig); - } -} diff --git a/src/main/java/io/github/dsheirer/edac/ReedSolomon_63_P25.java b/src/main/java/io/github/dsheirer/edac/ReedSolomon_63_P25.java index 38f61142..9edc5c94 100644 --- a/src/main/java/io/github/dsheirer/edac/ReedSolomon_63_P25.java +++ b/src/main/java/io/github/dsheirer/edac/ReedSolomon_63_P25.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2020 Dennis Sheirer + * Copyright (C) 2014-2025 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ public class ReedSolomon_63_P25 extends BerlekempMassey /** * APCO-25 Reed-Solomon code is generated from a Galois Field(2^6) by the polynomial: a6 + a1 + a0. * In binary, this is expressed as: 1000011 which is reversed to big-endian format for this algorithm - * See: TIA 102-BAAA paragraph 5.9 Reed-Solomon Code Generator Matrices + * See: TIA 102-BAAA paragraph 4.9 Reed-Solomon Code Generator Matrices */ public static final int[] P25_GENERATOR_POLYNOMIAL = { 1, 1, 0, 0, 0, 0, 1 }; diff --git a/src/main/java/io/github/dsheirer/edac/bch/BCH.java b/src/main/java/io/github/dsheirer/edac/bch/BCH.java index d2d17d3c..969d8aa9 100644 --- a/src/main/java/io/github/dsheirer/edac/bch/BCH.java +++ b/src/main/java/io/github/dsheirer/edac/bch/BCH.java @@ -324,6 +324,13 @@ public abstract class BCH /* add a^(k*2^i)(z^(2^i) mod f) and compute (z^(2^i) mod f)^2 */ for (j = z.mDegree; j >= 0; j--) { + if(2 * j >= z.mC.length) + { + //Fail ... set degree to 0 to signal fail + outTK.mDegree = 0; + return outTK; + } + outTK.mC[j] ^= z.mC[j]; z.mC[2 * j] = gf_sqr(z.mC[j]); z.mC[2 * j + 1] = 0; diff --git a/src/main/java/io/github/dsheirer/gui/instrument/RecentFilesMenu.java b/src/main/java/io/github/dsheirer/gui/RecentFilesMenu.java similarity index 89% rename from src/main/java/io/github/dsheirer/gui/instrument/RecentFilesMenu.java rename to src/main/java/io/github/dsheirer/gui/RecentFilesMenu.java index 5b8f1d20..02193fd9 100644 --- a/src/main/java/io/github/dsheirer/gui/instrument/RecentFilesMenu.java +++ b/src/main/java/io/github/dsheirer/gui/RecentFilesMenu.java @@ -1,29 +1,31 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer +/* + * ***************************************************************************** + * Copyright (C) 2014-2025 Dennis Sheirer * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument; + * You should have received a copy of the GNU General Public License + * along with this program. If not, see + * **************************************************************************** + */ +package io.github.dsheirer.gui; +import java.io.File; +import java.util.prefs.Preferences; import javafx.event.ActionEvent; import javafx.event.EventHandler; import javafx.scene.control.Menu; import javafx.scene.control.MenuItem; import javafx.scene.control.SeparatorMenuItem; -import java.io.File; -import java.util.prefs.Preferences; - public class RecentFilesMenu extends Menu implements EventHandler { private static final String PREFERENCE_RECENT_FILE = ".recent.file."; diff --git a/src/main/java/io/github/dsheirer/gui/channel/ChannelSpectrumPanel.java b/src/main/java/io/github/dsheirer/gui/channel/ChannelSpectrumPanel.java index b8a23e49..0e8d1e4a 100644 --- a/src/main/java/io/github/dsheirer/gui/channel/ChannelSpectrumPanel.java +++ b/src/main/java/io/github/dsheirer/gui/channel/ChannelSpectrumPanel.java @@ -23,7 +23,9 @@ import io.github.dsheirer.controller.channel.Channel; import io.github.dsheirer.dsp.filter.channelizer.PolyphaseChannelSource; import io.github.dsheirer.gui.power.SignalPowerView; import io.github.dsheirer.gui.squelch.NoiseSquelchView; +import io.github.dsheirer.gui.symbol.SymbolView; import io.github.dsheirer.module.ProcessingChain; +import io.github.dsheirer.module.decode.FeedbackDecoder; import io.github.dsheirer.module.decode.PrimaryDecoder; import io.github.dsheirer.module.decode.am.AMDecoder; import io.github.dsheirer.module.decode.nbfm.NBFMDecoder; @@ -46,13 +48,14 @@ import java.awt.EventQueue; import java.awt.event.ComponentEvent; import java.awt.event.ComponentListener; import java.awt.event.MouseEvent; +import java.net.URL; import java.text.DecimalFormat; -import java.text.NumberFormat; import java.util.List; import javafx.application.Platform; import javafx.embed.swing.JFXPanel; import javafx.scene.Scene; import net.miginfocom.swing.MigLayout; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -70,7 +73,7 @@ import javax.swing.event.MouseInputAdapter; */ public class ChannelSpectrumPanel extends JPanel implements Listener { - private static final Logger mLog = LoggerFactory.getLogger(ChannelSpectrumPanel.class); + private static final Logger LOGGER = LoggerFactory.getLogger(ChannelSpectrumPanel.class); private static final DecimalFormat FREQUENCY_FORMAT = new DecimalFormat("0.00000"); private final PlaylistManager mPlaylistManager; private ProcessingChain mProcessingChain; @@ -80,13 +83,14 @@ public class ChannelSpectrumPanel extends JPanel implements Listener { @@ -144,8 +145,8 @@ public class ChannelSpectrumPanel extends JPanel implements Listener hbtcs) { @@ -153,11 +154,11 @@ public class ChannelSpectrumPanel extends JPanel implements Listener { Scene scene = new Scene(mNoiseSquelchView); mNoiseSquelchPanel.setScene(scene); + Scene scene2 = new Scene(mSymbolView); + URL resource = getClass().getResource("/sdrtrunk_style.css"); + + if(resource != null) + { + scene2.getStylesheets().add(resource.toExternalForm()); + } + else + { + LOGGER.warn("Can't find stylesheet resource for sdrtrunk"); + } + + mSymbolPanel.setScene(scene2); }); mSplitPane = new JSplitPane(JSplitPane.HORIZONTAL_SPLIT); mSplitPane.add(fftPanel, JSplitPane.LEFT); mSplitPane.add(mNoiseSquelchPanel, JSplitPane.RIGHT); - mSplitPane.setDividerLocation(0.5); add(mSplitPane); +// mSplitPane.setDividerLocation(0.5); mSampleStreamTapModule.setListener(mComplexDftProcessor); DFTResultsConverter DFTResultsConverter = new ComplexDecibelConverter(); @@ -214,6 +229,13 @@ public class ChannelSpectrumPanel extends JPanel implements Listener { - String formattedValue = NumberFormat.getInstance().format(carrierOffsetFrequency); - mEstimatedCarrierOffsetFrequencyValueLabel.setText(formattedValue + " Hz"); + mEstimatedCarrierOffsetFrequencyValueLabel.setText(getPaddedCarrierOffsetLabel(carrierOffsetFrequency)); mEstimatedCarrierOffsetFrequencyValueLabel.setEnabled(true); - mEstimatedCarrierOffsetFrequencyLabel.setEnabled(true); }); mFrequencyOverlayPanel.setEstimatedCarrierOffsetFrequency(carrierOffsetFrequency); @@ -306,8 +327,7 @@ public class ChannelSpectrumPanel extends JPanel implements Listener - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.gui.instrument; - -import io.github.dsheirer.gui.instrument.decoder.DecoderPaneFactory; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder; -import javafx.application.Application; -import javafx.application.Platform; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.scene.Scene; -import javafx.scene.control.Menu; -import javafx.scene.control.MenuBar; -import javafx.scene.control.MenuItem; -import javafx.scene.control.SeparatorMenuItem; -import javafx.scene.layout.BorderPane; -import javafx.stage.FileChooser; -import javafx.stage.Stage; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.io.File; -import java.util.prefs.Preferences; - -/** - * Application for viewing and working with demodulators and recording files. - */ -public class DemodulatorViewerFX extends Application -{ - private final static Logger mLog = LoggerFactory.getLogger(DemodulatorViewerFX.class); - - private static final String PREFERENCE_FILE_OPEN_DEFAULT_FOLDER = "default.folder"; - - private Preferences mPreferences = Preferences.userNodeForPackage(DemodulatorViewerFX.class); - private Stage mStage; - private MenuBar mMenuBar; - private RecentFilesMenu mRecentFilesMenu; - private ViewerDesktop mViewerDesktop; - - @Override - public void start(Stage primaryStage) throws Exception - { - mStage = primaryStage; - setTitle(); - - BorderPane borderPane = new BorderPane(); - borderPane.setTop(getMenuBar()); - borderPane.setCenter(getViewerDesktop()); - - Scene scene = new Scene(borderPane, 1800, 900); - - mStage.setScene(scene); - mStage.show(); - } - - private void setTitle() - { - mStage.setTitle("Demodulator Viewer FX"); - } - - private void setTitle(DecoderType decoderType) - { - if(decoderType != null) - { - mStage.setTitle("Demodulator Viewer FX - " + decoderType.getDisplayString()); - } - else - { - setTitle(); - } - } - - private void setTitle(P25P1Decoder.Modulation modulation) - { - if(modulation != null) - { - mStage.setTitle("Demodulator Viewer FX - P25 " + modulation.getLabel()); - } - else - { - setTitle(); - } - } - - private ViewerDesktop getViewerDesktop() - { - if(mViewerDesktop == null) - { - mViewerDesktop = new ViewerDesktop(); - } - - return mViewerDesktop; - } - - private MenuBar getMenuBar() - { - if(mMenuBar == null) - { - mMenuBar = new MenuBar(); - - Menu fileMenu = new Menu("File"); - MenuItem openMenuItem = new MenuItem("Open ..."); - openMenuItem.setOnAction(new EventHandler() - { - @Override - public void handle(ActionEvent event) - { - FileChooser fileChooser = new FileChooser(); - fileChooser.setTitle("Open an I/Q recording file"); - - String directory = mPreferences.get(PREFERENCE_FILE_OPEN_DEFAULT_FOLDER, null); - - if(directory != null) - { - fileChooser.setInitialDirectory(new File(directory)); - } - - File file = fileChooser.showOpenDialog(mStage); - - if(file != null) - { - getViewerDesktop().load(file); - getRecentFilesMenu().add(file); - mPreferences.put(PREFERENCE_FILE_OPEN_DEFAULT_FOLDER, file.getParent()); - } - } - }); - - MenuItem closeMenuItem = new MenuItem("Close"); - closeMenuItem.setOnAction(new EventHandler() - { - @Override - public void handle(ActionEvent event) - { - getViewerDesktop().close(); - } - }); - - MenuItem exitMenuItem = new MenuItem("Exit"); - exitMenuItem.setOnAction(new EventHandler() - { - @Override - public void handle(ActionEvent event) - { - Platform.exit(); - } - }); - - fileMenu.getItems().addAll(openMenuItem, getRecentFilesMenu(), closeMenuItem, new SeparatorMenuItem(), - exitMenuItem); - - mMenuBar.getMenus().add(fileMenu); - - Menu decoderMenu = new Menu("Decoder"); - - for(DecoderType decoderType: DecoderType.values()) - { - if(DecoderPaneFactory.isSupported(decoderType)) - { - if(decoderType == DecoderType.P25_PHASE1) - { - MenuItem c4fmDecoderMenuItem = new MenuItem("P25 Phase 1 C4FM"); - - c4fmDecoderMenuItem.setOnAction(new EventHandler() - { - @Override - public void handle(ActionEvent event) - { - getViewerDesktop().setP25Phase1Decoder(P25P1Decoder.Modulation.C4FM); - setTitle(decoderType); - } - }); - - decoderMenu.getItems().add(c4fmDecoderMenuItem); - - MenuItem lsmDecoderMenuItem = new MenuItem("P25 Phase 1 LSM"); - - lsmDecoderMenuItem.setOnAction(new EventHandler() - { - @Override - public void handle(ActionEvent event) - { - getViewerDesktop().setP25Phase1Decoder(P25P1Decoder.Modulation.CQPSK); - setTitle(decoderType); - } - }); - - decoderMenu.getItems().add(lsmDecoderMenuItem); - } - else - { - MenuItem decoderMenuItem = new MenuItem(decoderType.getDisplayString()); - - decoderMenuItem.setOnAction(new EventHandler() - { - @Override - public void handle(ActionEvent event) - { - getViewerDesktop().setDecoder(decoderType); - setTitle(decoderType); - } - }); - - decoderMenu.getItems().add(decoderMenuItem); - } - } - } - - mMenuBar.getMenus().add(decoderMenu); - } - - return mMenuBar; - } - - private RecentFilesMenu getRecentFilesMenu() - { - if(mRecentFilesMenu == null) - { - mRecentFilesMenu = new RecentFilesMenu("Recent","demodulator.viewer", 5); - mRecentFilesMenu.setFileSelectionListener(new RecentFilesMenu.IFileSelectionListener() - { - @Override - public void fileSelected(File file) - { - getViewerDesktop().load(file); - } - }); - } - - return mRecentFilesMenu; - } - - public static void main(String[] args) - { - launch(args); - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/PlaybackController.java b/src/main/java/io/github/dsheirer/gui/instrument/PlaybackController.java deleted file mode 100644 index 2987b195..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/PlaybackController.java +++ /dev/null @@ -1,423 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument; - -import io.github.dsheirer.buffer.INativeBuffer; -import io.github.dsheirer.gui.instrument.decoder.AbstractDecoderPane; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.source.IControllableFileSource; -import io.github.dsheirer.source.IFrameLocationListener; -import io.github.dsheirer.source.wave.ComplexWaveSource; -import io.github.dsheirer.source.wave.RealWaveSource; -import javafx.event.ActionEvent; -import javafx.event.EventHandler; -import javafx.geometry.Pos; -import javafx.scene.control.Alert; -import javafx.scene.control.Button; -import javafx.scene.control.ButtonType; -import javafx.scene.control.Label; -import javafx.scene.control.TextField; -import javafx.scene.layout.HBox; -import jiconfont.icons.font_awesome.FontAwesome; -import jiconfont.javafx.IconNode; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import javax.sound.sampled.UnsupportedAudioFileException; -import java.io.File; -import java.io.IOException; - -public class PlaybackController extends HBox implements IFrameLocationListener -{ - private final static Logger mLog = LoggerFactory.getLogger(PlaybackController.class); - - private Button mRewindButton; - private TextField mPlaybackPositionText; - private Button mPlay1Button; - private Button mPlay10Button; - private Button mPlay30Button; - private Button mPlay100Button; - private Button mPlay1000Button; - private Button mPlay2000Button; - private HBox mControlsBox; - private Label mFileLabel; - private EventHandler mPlayEventHandler; - private AbstractDecoderPane mSampleRateListener; - - private IControllableFileSource mControllableFileSource; - private Broadcaster mRealBufferBroadcaster = new Broadcaster<>(); - private Broadcaster mNativeBufferBroadcaster = new Broadcaster<>(); - - public PlaybackController() - { - super(10); - - getChildren().addAll(getControlsBox(), getFileLabel()); - - disableControls(); - } - - public void setSampleRateListener(AbstractDecoderPane decoderPane) - { - mSampleRateListener = decoderPane; - - if(mSampleRateListener != null && mControllableFileSource != null) - { - mSampleRateListener.setSampleRate(mControllableFileSource.getSampleRate()); - } - } - - public void load(File file) - { - if(file != null && file.isFile()) - { - if(ComplexWaveSource.supports(file)) - { - try - { - mControllableFileSource = new ComplexWaveSource(file); - mControllableFileSource.setListener(this); - ((ComplexWaveSource)mControllableFileSource).setListener(mNativeBufferBroadcaster); - mControllableFileSource.open(); - - if(mSampleRateListener != null) - { - mSampleRateListener.setSampleRate(mControllableFileSource.getSampleRate()); - } - } - catch(UnsupportedAudioFileException e) - { - mLog.error("Unsupported Audio File Type [" + (file != null ? file.getAbsolutePath() : "null") + "]"); - - Alert alert = new Alert(Alert.AlertType.ERROR, "The file type is unsupported.", ButtonType.OK); - alert.show(); - return; - } - catch(IOException ioe) - { - mLog.error("Error opening file [" + (file != null ? file.getAbsolutePath() : "null") + "]", ioe); - - Alert alert = new Alert(Alert.AlertType.ERROR, "There was an error opening the file", - ButtonType.OK); - alert.show(); - return; - } - - enableControls(); - } - else if(RealWaveSource.supports(file)) - { - try - { - mControllableFileSource = new RealWaveSource(file); - mControllableFileSource.setListener(this); - ((RealWaveSource)mControllableFileSource).setListener(mRealBufferBroadcaster); - mControllableFileSource.open(); - - if(mSampleRateListener != null) - { - mSampleRateListener.setSampleRate(mControllableFileSource.getSampleRate()); - } - } - catch(UnsupportedAudioFileException e) - { - mLog.error("Unsupported Audio File Type [" + (file != null ? file.getAbsolutePath() : "null") + "]"); - - Alert alert = new Alert(Alert.AlertType.ERROR, "The file type is unsupported.", ButtonType.OK); - alert.show(); - return; - } - catch(IOException ioe) - { - mLog.error("Error opening file [" + (file != null ? file.getAbsolutePath() : "null") + "]", ioe); - - Alert alert = new Alert(Alert.AlertType.ERROR, "There was an error opening the file", - ButtonType.OK); - alert.show(); - return; - } - - enableControls(); - } - - getFileLabel().setText(file.getName()); - } - } - - public void close() - { - if(mControllableFileSource != null) - { - try - { - mControllableFileSource.close(); - } - catch(IOException ioe) - { - mLog.error("Error closing file", ioe); - } - } - - disableControls(); - } - - /** - * Adds listener to receive real buffers from this playback - */ - public void addRealListener(Listener listener) - { - mRealBufferBroadcaster.addListener(listener); - } - - /** - * Removes the listener from receiving real buffers from this playback - */ - public void removeRealListener(Listener listener) - { - mRealBufferBroadcaster.removeListener(listener); - } - - /** - * Adds listener to receive complex buffers from this playback - */ - public void addComplexListener(Listener listener) - { - mNativeBufferBroadcaster.addListener(listener); - } - - /** - * Removes the listener from receiving compex buffers from this playback - */ - public void removeComplexListener(Listener listener) - { - mNativeBufferBroadcaster.removeListener(listener); - } - - /** - * Sets all of the playback controls to the specified enabled state. - */ - private void disableControls() - { - getRewindButton().setDisable(true); - getPlaybackPositionText().setDisable(true); - getPlay1Button().setDisable(true); - getPlay10Button().setDisable(true); - getPlay30Button().setDisable(true); - getPlay100Button().setDisable(true); - getPlay1000Button().setDisable(true); - getPlay2000Button().setDisable(true); - } - - /** - * Sets all of the playback controls to the specified enabled state. - */ - private void enableControls() - { - getRewindButton().setDisable(false); - getPlaybackPositionText().setDisable(false); - getPlay1Button().setDisable(false); - getPlay10Button().setDisable(false); - getPlay30Button().setDisable(false); - getPlay100Button().setDisable(false); - getPlay1000Button().setDisable(false); - getPlay2000Button().setDisable(false); - } - - private HBox getControlsBox() - { - if(mControlsBox == null) - { - mControlsBox = new HBox(); - - mControlsBox.getChildren().addAll(getRewindButton(), getPlaybackPositionText(), getPlay1Button(), - getPlay10Button(), getPlay30Button(), getPlay100Button(), getPlay1000Button(), getPlay2000Button()); - } - - return mControlsBox; - } - - - private Button getRewindButton() - { - if(mRewindButton == null) - { - mRewindButton = new Button(); - IconNode iconNode = new IconNode(FontAwesome.FAST_BACKWARD); - iconNode.setIconSize(10); - mRewindButton.setGraphic(iconNode); - } - - return mRewindButton; - } - - private Button getPlay1Button() - { - if(mPlay1Button == null) - { - mPlay1Button = new Button("1"); - mPlay1Button.setUserData(1); - mPlay1Button.setOnAction(getPlaybackEventHandler()); - IconNode iconNode = new IconNode(FontAwesome.PLAY); - iconNode.setIconSize(10); - mPlay1Button.setGraphic(iconNode); - } - - return mPlay1Button; - } - - private Button getPlay10Button() - { - if(mPlay10Button == null) - { - mPlay10Button = new Button("10"); - mPlay10Button.setUserData(10); - mPlay10Button.setOnAction(getPlaybackEventHandler()); - IconNode iconNode = new IconNode(FontAwesome.FAST_FORWARD); - iconNode.setIconSize(10); - mPlay10Button.setGraphic(iconNode); - } - - return mPlay10Button; - } - - private Button getPlay30Button() - { - if(mPlay30Button == null) - { - mPlay30Button = new Button("30"); - mPlay30Button.setUserData(30); - mPlay30Button.setOnAction(getPlaybackEventHandler()); - IconNode iconNode = new IconNode(FontAwesome.FAST_FORWARD); - iconNode.setIconSize(10); - mPlay30Button.setGraphic(iconNode); - } - - return mPlay30Button; - } - - private Button getPlay100Button() - { - if(mPlay100Button == null) - { - mPlay100Button = new Button("100"); - mPlay100Button.setUserData(100); - mPlay100Button.setOnAction(getPlaybackEventHandler()); - IconNode iconNode = new IconNode(FontAwesome.FAST_FORWARD); - iconNode.setIconSize(10); - mPlay100Button.setGraphic(iconNode); - } - - return mPlay100Button; - } - - private Button getPlay1000Button() - { - if(mPlay1000Button == null) - { - mPlay1000Button = new Button("1000"); - mPlay1000Button.setUserData(1000); - mPlay1000Button.setOnAction(getPlaybackEventHandler()); - IconNode iconNode = new IconNode(FontAwesome.FAST_FORWARD); - iconNode.setIconSize(10); - mPlay1000Button.setGraphic(iconNode); - } - - return mPlay1000Button; - } - - private Button getPlay2000Button() - { - if(mPlay2000Button == null) - { - mPlay2000Button = new Button("2000"); - mPlay2000Button.setUserData(2000); - mPlay2000Button.setOnAction(getPlaybackEventHandler()); - IconNode iconNode = new IconNode(FontAwesome.FAST_FORWARD); - iconNode.setIconSize(10); - mPlay2000Button.setGraphic(iconNode); - } - - return mPlay2000Button; - } - - private EventHandler getPlaybackEventHandler() - { - if(mPlayEventHandler == null) - { - mPlayEventHandler = new EventHandler() - { - @Override - public void handle(ActionEvent event) - { - int count = (int)((Button)event.getSource()).getUserData(); - - if(mControllableFileSource != null) - { - try - { - mControllableFileSource.next(count, true); - } - catch(IOException ioe) - { - mLog.error("Error while playing samples"); - } - } - - } - }; - } - - return mPlayEventHandler; - } - - private TextField getPlaybackPositionText() - { - if(mPlaybackPositionText == null) - { - mPlaybackPositionText = new TextField("0"); - mPlaybackPositionText.setAlignment(Pos.CENTER); - mPlaybackPositionText.setPrefWidth(80); - } - - return mPlaybackPositionText; - } - - private Label getFileLabel() - { - if(mFileLabel == null) - { - mFileLabel = new Label(); - } - - return mFileLabel; - } - - @Override - public void frameLocationUpdated(int location) - { - getPlaybackPositionText().setText(String.valueOf(location)); - } - - @Override - public void frameLocationReset() - { - mLog.info("Frame location reset ... ignoring?"); - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/ViewerDesktop.java b/src/main/java/io/github/dsheirer/gui/instrument/ViewerDesktop.java deleted file mode 100644 index d94b2183..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/ViewerDesktop.java +++ /dev/null @@ -1,109 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument; - -import io.github.dsheirer.gui.instrument.decoder.AbstractDecoderPane; -import io.github.dsheirer.gui.instrument.decoder.DecoderPaneFactory; -import io.github.dsheirer.gui.instrument.decoder.RealDecoderPane; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder; -import javafx.scene.layout.BorderPane; - -import java.io.File; - -public class ViewerDesktop extends BorderPane -{ - private PlaybackController mPlaybackController; - private AbstractDecoderPane mDecoderPane = DecoderPaneFactory.getDefaultPane(); - - public ViewerDesktop() - { - setBottom(getPlaybackController()); - setCenter(getDecoderPane()); - } - - public void load(File file) - { - close(); - getPlaybackController().load(file); - } - - public void setDecoder(DecoderType decoderType) - { - setDecoderPane(DecoderPaneFactory.getDecoderPane(decoderType)); - } - - public void setP25Phase1Decoder(P25P1Decoder.Modulation modulation) - { - setDecoderPane(DecoderPaneFactory.getP25P1DecoderPane(modulation)); - } - - private void setDecoderPane(AbstractDecoderPane decoderPane) - { - if(getDecoderPane() instanceof RealDecoderPane) - { - getPlaybackController().removeRealListener(getDecoderPane()); - } - else - { - getPlaybackController().removeComplexListener(getDecoderPane()); - } - getChildren().remove(getDecoderPane()); - mDecoderPane = decoderPane; - setCenter(getDecoderPane()); - - if(getDecoderPane() instanceof RealDecoderPane) - { - getPlaybackController().addRealListener(getDecoderPane()); - } - else - { - getPlaybackController().addComplexListener(getDecoderPane()); - } - getPlaybackController().setSampleRateListener(getDecoderPane()); - } - - /** - * Decoder pane - */ - public AbstractDecoderPane getDecoderPane() - { - if(mDecoderPane == null) - { - mDecoderPane = DecoderPaneFactory.getDefaultPane(); - } - - return mDecoderPane; - } - - public void close() - { - getPlaybackController().close(); - } - - private PlaybackController getPlaybackController() - { - if(mPlaybackController == null) - { - mPlaybackController = new PlaybackController(); - } - - return mPlaybackController; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200SampleBufferChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200SampleBufferChart.java deleted file mode 100644 index 9c861dc0..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200SampleBufferChart.java +++ /dev/null @@ -1,169 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import javafx.scene.layout.StackPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AFSK1200SampleBufferChart extends LineChart -{ - private final static Logger mLog = LoggerFactory.getLogger(AFSK1200SampleBufferChart.class); - private ObservableList> mSamples = FXCollections.observableArrayList(); - private Series mSampleSeries = new Series<>("Samples", mSamples); - - private ObservableList> mSamplePoints = FXCollections.observableArrayList(); - private Series mSamplePointSeries = new Series<>("Pointers", mSamplePoints); - - private ObservableList> mSymbolSamples = FXCollections.observableArrayList(); - private Series mSymbolSamplesSeries = new Series<>("Next Symbol Samples", mSymbolSamples); - - private ObservableList> mPreviousSymbol = FXCollections.observableArrayList(); - private Series mPreviousSymbolSeries = new Series<>("Previous Symbol", mPreviousSymbol); - - private ObservableList> mZeroCrossing = FXCollections.observableArrayList(); - private Series mZeroCrossingSeries = new Series<>("Zero Crossing", mZeroCrossing); - - private IInstrumentedAFSK1200Decoder mIInstrumentedAFSK1200Decoder; - - public AFSK1200SampleBufferChart(IInstrumentedAFSK1200Decoder decoder, int length) - { - super(new NumberAxis("Samples", 0, length, 5), - new NumberAxis("Value", -1.0, 1.0, 0.25)); - - ObservableList observableList = FXCollections.observableArrayList(mSampleSeries, mSamplePointSeries, - mSymbolSamplesSeries, mPreviousSymbolSeries, mZeroCrossingSeries); - - setData(observableList); - - mIInstrumentedAFSK1200Decoder = decoder; - decoder.getBufferCountProperty().addListener(new BufferChangeListener()); - decoder.getAFSK1200Decoder().getErrorDetector().timingError.addListener(new ErrorChangeListener()); - } - - public void setBuffer(boolean[] buffer) - { - while(mSamples.size() < buffer.length) - { - Data sample = new Data<>(mSamples.size(), 0.0f); - mSamples.add(sample); - - //Turn off the data point marker symbols - yes I know this is inefficient - for(Data data: mSampleSeries.getData()) - { - StackPane stackPane = (StackPane)data.getNode(); - stackPane.setVisible(false); - } - } - - for(int x = 0; x < buffer.length; x++) - { - Data sample = mSamples.get(x); - - sample.setYValue(buffer[x] ? 0.5f : -0.5f); - } - } - - public class BufferChangeListener implements ChangeListener - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { - setBuffer(mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getDelayLine()); - - while(mPreviousSymbol.size() < 2) - { - Data sample = new Data<>(0.0, -0.55); - mPreviousSymbol.add(sample); - } - - while(mZeroCrossing.size() < 2) - { - Data sample = new Data<>(0.0, -0.65); - mZeroCrossing.add(sample); - } - - while(mSamplePoints.size() < 2) - { - Data sample = new Data<>(0.0, -0.75); - mSamplePoints.add(sample); - } - - while(mSymbolSamples.size() < 2) - { - Data sample = new Data<>(0.0, -0.85); - mSymbolSamples.add(sample); - } - - int pointer1 = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getDelayLinePointer(); - int pointer2 = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getDelayLineSecondPointer(); - - mSamplePoints.get(0).setXValue(pointer1); - mSamplePoints.get(1).setXValue(pointer2); - - float samplesPerSymbol = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getSamplesPerSymbol(); - - boolean symbol = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getLastSymbol(); - int symbolStart = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getSymbolStart(); - int symbolEnd = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getSymbolEnd(); - - float start = pointer1 + samplesPerSymbol - 1; - float end = symbolEnd; - - mSymbolSamples.get(0).setXValue(start); - mSymbolSamples.get(1).setXValue(end); - - - mPreviousSymbol.get(0).setXValue(symbolStart); - mPreviousSymbol.get(0).setYValue(symbol ? 0.55f : -0.55f); - mPreviousSymbol.get(1).setXValue(symbolEnd); - mPreviousSymbol.get(1).setYValue(symbol ? 0.55f : -0.55f); - } - } - - public class ErrorChangeListener implements ChangeListener - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { - while(mZeroCrossing.size() < 2) - { - Data sample = new Data<>(0.0, -0.65); - mZeroCrossing.add(sample); - } - - int pointer1 = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getDelayLinePointer(); - int pointer2 = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getSampleBuffer().getDelayLineSecondPointer(); - - int detectedZeroCrossing = ((Number)newValue).intValue(); - -// int reference = (zeroCrossingIdeal < pointer1 || detectedZeroCrossing < pointer1 ? pointer2 : pointer1); -// reference--; -// -// float start = reference - zeroCrossingIdeal; -// float end = reference - detectedZeroCrossing; -// -// mZeroCrossing.get(0).setXValue(start); -// mZeroCrossing.get(1).setXValue(end); - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200ZeroCrossingErrorDetectorChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200ZeroCrossingErrorDetectorChart.java deleted file mode 100644 index 0d2b2449..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200ZeroCrossingErrorDetectorChart.java +++ /dev/null @@ -1,118 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class AFSK1200ZeroCrossingErrorDetectorChart extends LineChart -{ - private final static Logger mLog = LoggerFactory.getLogger(AFSK1200ZeroCrossingErrorDetectorChart.class); - - private ObservableList> mCurrentSamples = FXCollections.observableArrayList(); - private Series mCurrentSampleSeries = new Series<>("Samples", mCurrentSamples); - - private ObservableList> mPreviousSamples = FXCollections.observableArrayList(); - private Series mPreviousSampleSeries = new Series<>("Samples", mPreviousSamples); - - private ObservableList> mDetected = FXCollections.observableArrayList(); - private Series mDetectedSeries = new Series<>("Detected", mDetected); - - private IInstrumentedAFSK1200Decoder mIInstrumentedAFSK1200Decoder; - - public AFSK1200ZeroCrossingErrorDetectorChart(IInstrumentedAFSK1200Decoder decoder, int length) - { - super(new NumberAxis("Samples", 0, length, 5), - new NumberAxis("Value", -1.0, 1.0, 0.25)); - - ObservableList observableList = FXCollections.observableArrayList(mCurrentSampleSeries, - mPreviousSampleSeries, mDetectedSeries); - setData(observableList); - - mIInstrumentedAFSK1200Decoder = decoder; - decoder.getAFSK1200Decoder().getErrorDetector().timingError.addListener(new ErrorChangeListener()); - decoder.getBufferCountProperty().addListener(new ChangeListener() - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { - updateBuffer(); - } - }); - - for(int x = 0; x < length; x++) - { - Data sample = new Data<>(x, 0.0f); - mCurrentSamples.add(sample); - Data sample2 = new Data<>(x, 0.0f); - mPreviousSamples.add(sample2); - } - - Data detected1 = new Data<>(5, -0.25f); - mDetected.add(detected1); - Data detected2 = new Data<>(5, -0.75f); - mDetected.add(detected2); - } - - private void updateBuffer() - { - boolean[] samples = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getErrorDetector().getBuffer(); - - for(int x = 0; x < samples.length; x++) - { - Data sample = mCurrentSamples.get(x); - sample.setYValue(samples[x] ? 0.7f : 0.3f); - } - } - - public class ErrorChangeListener implements ChangeListener - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { - float error = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getErrorDetector().getError(); - - boolean[] samples = mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getErrorDetector().getBuffer(); - - for(int x = 0; x < samples.length; x++) - { - Data sample = mPreviousSamples.get(x); - sample.setYValue(samples[x] ? -0.4f : -0.6f); - } - - if(error == 0.0f) - { - Data detected1 = mDetected.get(0); - detected1.setXValue(0.0f); - Data detected2 = mDetected.get(1); - detected2.setXValue(0.0f); - } - else - { - Data detected1 = mDetected.get(0); - detected1.setXValue(mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getErrorDetector().getDetectedZeroCrossing()); - Data detected2 = mDetected.get(1); - detected2.setXValue(mIInstrumentedAFSK1200Decoder.getAFSK1200Decoder().getErrorDetector().getDetectedZeroCrossing()); - } - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/ComplexSampleLineChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/ComplexSampleLineChart.java deleted file mode 100644 index ffe65c67..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/ComplexSampleLineChart.java +++ /dev/null @@ -1,132 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.buffer.ComplexCircularBuffer; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; -import io.github.dsheirer.sample.complex.ComplexSampleListener; -import io.github.dsheirer.sample.complex.ComplexSamples; -import javafx.beans.property.IntegerProperty; -import javafx.beans.property.SimpleIntegerProperty; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import javafx.scene.chart.XYChart; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ComplexSampleLineChart extends LineChart implements Listener, ComplexSampleListener -{ - private final static Logger mLog = LoggerFactory.getLogger(ComplexSampleLineChart.class); - - private ComplexCircularBuffer mComplexCircularBuffer; - private ComplexCircularBuffer mDemodulationCircularBuffer; - private ObservableList> mISamples = FXCollections.observableArrayList(); - private ObservableList> mQSamples = FXCollections.observableArrayList(); - private IntegerProperty mLengthProperty = new SimpleIntegerProperty(40); - - public ComplexSampleLineChart(String label, int length, int samplesPerSymbol) - { - super(new NumberAxis(label, 0, length, 10), - new NumberAxis("Value", -1.0, 1.0, 0.25)); - - LineChart.Series iSampleSeries = new LineChart.Series<>("Inphase", mISamples); - LineChart.Series qSampleSeries = new LineChart.Series<>("Quadrature", mQSamples); - ObservableList> observableList = - FXCollections.observableArrayList(iSampleSeries, qSampleSeries); - - setData(observableList); - init(length, samplesPerSymbol); - } - - public void setSamplesPerSymbol(int samplesPerSymbol) - { - mDemodulationCircularBuffer = new ComplexCircularBuffer(samplesPerSymbol); - } - - private void init(int length, int samplesPerSymbol) - { - mLengthProperty.addListener(new ChangeListener() - { - @Override - public void changed(ObservableValue observable, Number oldValue, Number newValue) - { - mComplexCircularBuffer = new ComplexCircularBuffer(newValue.intValue()); - } - }); - mComplexCircularBuffer = new ComplexCircularBuffer(length); - mDemodulationCircularBuffer = new ComplexCircularBuffer(samplesPerSymbol); - length().setValue(length); - - for(int x = 1; x <= length; x++) - { - mISamples.add(new Data(x, 0.0f)); - mQSamples.add(new Data(x, 0.0f)); - } - } - - /** - * Length of the x-axis for displaying samples - */ - public IntegerProperty length() - { - return mLengthProperty; - } - - @Override - public void receive(ComplexSamples samples) - { - for(int x = 0; x < samples.i().length; x++) - { - receive(samples.i()[x], samples.q()[x]); - } - } - - @Override - public void receive(float i, float q) - { - Complex sample = new Complex(i,q); - sample.normalize(); - Complex previous = mDemodulationCircularBuffer.get(sample.copy()); - sample.multiply(previous.conjugate()); - mComplexCircularBuffer.put(sample); - updateChart(); - } - - private void updateChart() - { - Complex[] samples = mComplexCircularBuffer.getAll(); - - for(int x = 0; x < samples.length; x++) - { - Complex sample = samples[x]; - - if(sample != null) - { - sample.normalize(); - mISamples.get(x).setYValue(sample.inphase()); - mQSamples.get(x).setYValue(sample.quadrature()); - } - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/DecodedSymbolChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/DecodedSymbolChart.java deleted file mode 100644 index 3a416dfc..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/DecodedSymbolChart.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.sample.Listener; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DecodedSymbolChart extends LineChart implements Listener -{ - private final static Logger mLog = LoggerFactory.getLogger(DecodedSymbolChart.class); - - private ObservableList> mSymbols = FXCollections.observableArrayList(); - private Series mSymbolSeries = new Series<>("Samples", mSymbols); - private boolean[] mSymbolBuffer; - private int mSymbolBufferPointer; - - public DecodedSymbolChart(int length) - { - super(new NumberAxis("Symbols", 0, length, 5), - new NumberAxis("Value", -1.0, 1.0, 0.25)); - - ObservableList observableList = FXCollections.observableArrayList(mSymbolSeries); - setData(observableList); - - for(int x = 0; x < length; x++) - { - Data symbol = new Data<>(x, -0.5f); - mSymbols.add(symbol); - } - - mSymbolBuffer = new boolean[length]; - } - - @Override - public void receive(Boolean symbol) - { - mSymbolBuffer[mSymbolBufferPointer++] = symbol; - mSymbolBufferPointer %= mSymbolBuffer.length; - - update(); - } - - private void update() - { - for(int x = 0; x < mSymbolBuffer.length; x++) - { - Data symbol = mSymbols.get(x); - - int offset = x + mSymbolBufferPointer; - offset %= mSymbolBuffer.length; - - symbol.setYValue(mSymbolBuffer[offset] ? 0.5f : -0.5f); - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/DoubleLineChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/DoubleLineChart.java deleted file mode 100644 index ab661f59..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/DoubleLineChart.java +++ /dev/null @@ -1,91 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.buffer.DoubleCircularBuffer; -import io.github.dsheirer.sample.Listener; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import javafx.scene.chart.ValueAxis; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class DoubleLineChart extends LineChart implements Listener -{ - private final static Logger mLog = LoggerFactory.getLogger(DoubleLineChart.class); - - private DoubleCircularBuffer mDoubleCircularBuffer; - private ObservableList> mPhaseValues = FXCollections.observableArrayList(); - - public DoubleLineChart(String seriesLabel, double min, double max, double tick, int length) - { - super(new NumberAxis(1, length, 2), new NumberAxis(min, max, tick)); - - Series phaseSeries = new Series<>(seriesLabel, mPhaseValues); - ObservableList> observableList = FXCollections.observableArrayList(phaseSeries); - - setData(observableList); - init(length); - } - - /** - * Sets the minimum displayable value for the y axis - * @param min - */ - public void setMin(double min) - { - ((ValueAxis)getYAxis()).setLowerBound(min); - } - - /** - * Sets the maximum displayable value for the y axis - * @param max - */ - public void setMax(double max) - { - ((ValueAxis)getYAxis()).setUpperBound(max); - } - - private void init(int length) - { - mDoubleCircularBuffer = new DoubleCircularBuffer(length); - - for(int x = 1; x <= length; x++) - { - mPhaseValues.add(new Data(x, 0.0)); - } - } - - @Override - public void receive(Double phase) - { - mDoubleCircularBuffer.put(phase); - - updateChart(); - } - - private void updateChart() - { - double[] values = mDoubleCircularBuffer.getAll(); - - for(int x = 0; x < values.length; x++) - { - mPhaseValues.get(x).setYValue(values[x]); - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/EyeDiagramChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/EyeDiagramChart.java deleted file mode 100644 index bc12a22b..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/EyeDiagramChart.java +++ /dev/null @@ -1,149 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2019 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.dsp.psk.SymbolDecisionData; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import org.apache.commons.math3.util.FastMath; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class EyeDiagramChart extends LineChart implements Listener -{ - private final static Logger mLog = LoggerFactory.getLogger(EyeDiagramChart.class); - - private ObservableList> mData = FXCollections.observableArrayList(); - private int mSeriesCount; - private int mSeriesPointer; - private int mSeriesLength; - - public EyeDiagramChart(int seriesCount, String legend) - { - super(new NumberAxis("Sample Point = 3", -1.0, 7.0, 1.0), - new NumberAxis("Radians", -5.0, 5.0, 0.5)); - - mSeriesCount = seriesCount; - init(); - } - - private void init() - { - for(int x = 0; x < mSeriesCount; x++) - { - ObservableList> series = FXCollections.observableArrayList(); - mData.add(new Series(series)); - } - - setData(mData); - } - - private ObservableList> getSeries(int series, int length) - { - ObservableList> seriesData = mData.get(series).getData(); - - while(seriesData.size() > length) - { - seriesData.remove(0); - } - - while(seriesData.size() < length) - { - seriesData.add(new Data<>(0.0,0.0f)); - } - - return seriesData; - } - - private void checkChartLength(int length) - { - if(mSeriesLength != length) - { - ((NumberAxis)getXAxis()).setUpperBound(length); - mSeriesLength = length; - } - } - - private float[] conditionData(Complex[] samples) - { - Float previousAngle = null; - float[] corrected = new float[samples.length]; - - int phaseRolloverIndex = -1; - - for(int x = 0; x < samples.length; x++) - { - corrected[x] = samples[x].angle(); - - if(x > 0 && (FastMath.abs(corrected[x] - corrected[x - 1]) > FastMath.PI)) - { - phaseRolloverIndex = x; - } - } - - if(phaseRolloverIndex >= 0) - { - for(int x = 0; x < phaseRolloverIndex; x++) - { - if(corrected[x] > 0) - { - corrected[x] -= 2 * FastMath.PI; - } - else - { - corrected[x] += 2 * FastMath.PI; - } - } - } - - return corrected; - } - - @Override - public void receive(SymbolDecisionData symbolDecisionData) - { - Complex[] samples = symbolDecisionData.getSamples(); - int length = samples.length; - - ObservableList> iSeries = getSeries(mSeriesPointer++, length); -// checkChartLength(length); - - if(mSeriesPointer >= mSeriesCount) - { - mSeriesPointer = 0; - } - - float[] angles = conditionData(samples); - - for(int x = 0; x < samples.length; x++) - { - Data iDataPoint = iSeries.get(x); - Complex sample = samples[x]; - iDataPoint.setXValue((double)x - symbolDecisionData.getSamplingPoint()); - iDataPoint.setYValue(angles[x]); - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/IInstrumentedAFSK1200Decoder.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/IInstrumentedAFSK1200Decoder.java deleted file mode 100644 index 5308cd81..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/IInstrumentedAFSK1200Decoder.java +++ /dev/null @@ -1,30 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.dsp.afsk.AFSK1200DecoderInstrumented; -import io.github.dsheirer.message.IMessage; -import io.github.dsheirer.sample.Listener; -import javafx.beans.property.SimpleIntegerProperty; - -public interface IInstrumentedAFSK1200Decoder -{ - SimpleIntegerProperty getBufferCountProperty(); - - AFSK1200DecoderInstrumented getAFSK1200Decoder(); - - void setMessageListener(Listener listener); -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/LTRNetSampleBufferChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/LTRNetSampleBufferChart.java deleted file mode 100644 index fe898009..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/LTRNetSampleBufferChart.java +++ /dev/null @@ -1,174 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2023 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.module.decode.ltrnet.LTRNetDecoderInstrumented; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import javafx.scene.layout.StackPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LTRNetSampleBufferChart extends LineChart -{ - private final static Logger mLog = LoggerFactory.getLogger(LTRNetSampleBufferChart.class); - private ObservableList> mSamples = FXCollections.observableArrayList(); - private Series mSampleSeries = new Series<>("Samples", mSamples); - - private ObservableList> mSamplePoints = FXCollections.observableArrayList(); - private Series mSamplePointSeries = new Series<>("Pointers", mSamplePoints); - - private ObservableList> mSymbolSamples = FXCollections.observableArrayList(); - private Series mSymbolSamplesSeries = new Series<>("Next Symbol Samples", mSymbolSamples); - - private ObservableList> mSymbol = FXCollections.observableArrayList(); - private Series mSymbolSeries = new Series<>("Previous Symbol", mSymbol); - - private ObservableList> mZeroCrossing = FXCollections.observableArrayList(); - private Series mZeroCrossingSeries = new Series<>("Zero Crossing", mZeroCrossing); - - private LTRNetDecoderInstrumented mLTRNetDecoderInstrumented; - - public LTRNetSampleBufferChart(LTRNetDecoderInstrumented decoder, int length) - { - super(new NumberAxis("Samples", 0, length, 5), - new NumberAxis("Value", -1.0, 1.0, 0.25)); - - ObservableList observableList = FXCollections.observableArrayList(mSampleSeries, mSamplePointSeries, - mSymbolSamplesSeries, mSymbolSeries, mZeroCrossingSeries); - - setData(observableList); - - mLTRNetDecoderInstrumented = decoder; - decoder.bufferCount.addListener(new BufferChangeListener()); -// decoder.getLTRDecoder().getErrorDetector().timingError.addListener(new ErrorChangeListener()); - } - - public void setBuffer(boolean[] buffer) - { - while(mSamples.size() < buffer.length) - { - Data sample = new Data<>(mSamples.size(), 0.0f); - mSamples.add(sample); - - //Turn off the data point marker symbols - yes I know this is inefficient - for(Data data: mSampleSeries.getData()) - { - StackPane stackPane = (StackPane)data.getNode(); - stackPane.setVisible(false); - } - } - - for(int x = 0; x < buffer.length; x++) - { - Data sample = mSamples.get(x); - - sample.setYValue(buffer[x] ? 0.5f : -0.5f); - } - } - - public class BufferChangeListener implements ChangeListener - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { -// setBuffer(mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getDelayLine()); - - while(mSymbol.size() < 2) - { - Data sample = new Data<>(0.0, -0.55); - mSymbol.add(sample); - } - - while(mZeroCrossing.size() < 2) - { - Data sample = new Data<>(0.0, -0.65); - mZeroCrossing.add(sample); - } - - while(mSamplePoints.size() < 2) - { - Data sample = new Data<>(0.0, -0.75); - mSamplePoints.add(sample); - } - - while(mSymbolSamples.size() < 2) - { - Data sample = new Data<>(0.0, -0.85); - mSymbolSamples.add(sample); - } - -// int pointer1 = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getDelayLinePointer(); -// int pointer2 = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getDelayLineSecondPointer(); - -// mSamplePoints.get(0).setXValue(pointer1); -// mSamplePoints.get(1).setXValue(pointer2); - -// float samplesRemaining = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getMidSymbolSamplingPoint(); -// float samplesPerSymbol = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getSamplesPerSymbol(); - -// float start = pointer1 + samplesRemaining; -// float end = start + samplesPerSymbol; - -// mSymbolSamples.get(0).setXValue(start); -// mSymbolSamples.get(1).setXValue(end); - -// boolean symbol = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getLastSymbol(); -// int symbolStart = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getSymbolStart(); -// int symbolEnd = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getSymbolEnd(); - -// mSymbol.get(0).setXValue(symbolStart); -// mSymbol.get(0).setYValue(symbol ? 0.55f : -0.55f); -// mSymbol.get(1).setXValue(symbolEnd); -// mSymbol.get(1).setYValue(symbol ? 0.55f : -0.55f); - } - } - - public class ErrorChangeListener implements ChangeListener - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { - while(mZeroCrossing.size() < 2) - { - Data sample = new Data<>(0.0, -0.65); - mZeroCrossing.add(sample); - } - -// int pointer1 = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getDelayLinePointer(); -// int pointer2 = mLTRNetDecoderInstrumented.getLTRDecoder().getSampleBuffer().getDelayLineSecondPointer(); - -// float zeroCrossingIdeal = mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getZeroCrossingIdeal(); -// float detectedZeroCrossing = zeroCrossingIdeal - ((Number)newValue).floatValue(); -// -// int reference = (zeroCrossingIdeal < pointer1 || detectedZeroCrossing < pointer1 ? pointer2 : pointer1); -// reference--; -// -// float start = reference - zeroCrossingIdeal; -// float end = reference - detectedZeroCrossing; -// -// mZeroCrossing.get(0).setXValue(start); -// mZeroCrossing.get(1).setXValue(end); - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/PhaseLineChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/PhaseLineChart.java deleted file mode 100644 index cdcaf2ad..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/PhaseLineChart.java +++ /dev/null @@ -1,73 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.buffer.DoubleCircularBuffer; -import io.github.dsheirer.sample.Listener; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class PhaseLineChart extends LineChart implements Listener -{ - private final static Logger mLog = LoggerFactory.getLogger(PhaseLineChart.class); - - private DoubleCircularBuffer mDoubleCircularBuffer; - private ObservableList> mPhaseValues = FXCollections.observableArrayList(); - - public PhaseLineChart(int length) - { - super(new NumberAxis("Time", 1, length, 2), - new NumberAxis("Phase", -0.8, 0.8, 0.1)); - - Series phaseSeries = new Series<>("PLL Phase Error", mPhaseValues); - ObservableList> observableList = FXCollections.observableArrayList(phaseSeries); - - setData(observableList); - init(length); - } - - private void init(int length) - { - mDoubleCircularBuffer = new DoubleCircularBuffer(length); - - for(int x = 1; x <= length; x++) - { - mPhaseValues.add(new Data(x, 0.0)); - } - } - - @Override - public void receive(Double phase) - { - mDoubleCircularBuffer.put(phase); - - updateChart(); - } - - private void updateChart() - { - double[] values = mDoubleCircularBuffer.getAll(); - - for(int x = 0; x < values.length; x++) - { - mPhaseValues.get(x).setYValue(values[x]); - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/RealSampleLineChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/RealSampleLineChart.java deleted file mode 100644 index 1f3c2002..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/RealSampleLineChart.java +++ /dev/null @@ -1,85 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.buffer.FloatCircularBuffer; -import io.github.dsheirer.sample.Listener; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import javafx.scene.chart.XYChart; -import javafx.scene.layout.StackPane; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class RealSampleLineChart extends LineChart implements Listener -{ - private final static Logger mLog = LoggerFactory.getLogger(RealSampleLineChart.class); - private ObservableList> mSamples = FXCollections.observableArrayList(); - private Series mSampleSeries = new Series<>("Samples", mSamples); - private FloatCircularBuffer mRealCircularBuffer; - - public RealSampleLineChart(int length, double tickUnit) - { - super(new NumberAxis("Samples", 0, length, tickUnit), - new NumberAxis("Value", -1.0, 1.0, 0.25)); - - ObservableList> observableList = FXCollections.observableArrayList(mSampleSeries); - - setData(observableList); - - init(length); - } - - private void init(int length) - { - mRealCircularBuffer = new FloatCircularBuffer(length); - - for(int x = 0; x < length; x++) - { - Data sample = new Data<>(x, 0.0f); - mSamples.add(sample); - } - - //Turn off the data point marker symbols - for(XYChart.Data data: mSampleSeries.getData()) - { - StackPane stackPane = (StackPane)data.getNode(); - stackPane.setVisible(false); - } - } - - @Override - public void receive(float[] buffer) - { - for(float sample: buffer) - { - mRealCircularBuffer.put(sample); - } - - float[] bufferSamples = mRealCircularBuffer.getAll(); - - for(int x = 0; x < bufferSamples.length; x++) - { - Data sample = mSamples.get(x); - sample.setYValue(bufferSamples[x]); - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/SampleXYChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/SampleXYChart.java deleted file mode 100644 index 83991a71..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/SampleXYChart.java +++ /dev/null @@ -1,87 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.chart; - -import eu.hansolo.fx.charts.ChartType; -import eu.hansolo.fx.charts.PolarChart; -import eu.hansolo.fx.charts.XYPane; -import eu.hansolo.fx.charts.data.XYChartItem; -import eu.hansolo.fx.charts.series.XYSeries; -import io.github.dsheirer.buffer.ComplexCircularBuffer; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; -import io.github.dsheirer.sample.complex.ComplexSamples; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.paint.Color; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SampleXYChart extends PolarChart implements Listener -{ - private static ObservableList sChartItemList = FXCollections.observableArrayList(); - - static - { - sChartItemList.add(new XYChartItem(1, 1)); - sChartItemList.add(new XYChartItem(-1, -1)); - } - - private final static Logger mLog = LoggerFactory.getLogger(SampleXYChart.class); - private ComplexCircularBuffer mCircularBuffer; - private int mSampleCount; - - public SampleXYChart(int sampleCount, String title) - { - super(new XYPane<>(new XYSeries<>(sChartItemList, ChartType.POLAR))); - mSampleCount = sampleCount; - mCircularBuffer = new ComplexCircularBuffer(mSampleCount); - - getXYPane().setLowerBoundX(0); - getXYPane().setUpperBoundX(1.0); - getXYPane().setLowerBoundY(0); - getXYPane().setUpperBoundY(1.0); - } - - private void init() - { - } - - @Override - public void receive(ComplexSamples buffer) - { - for(int x = 0; x < buffer.i().length; x++) - { - mCircularBuffer.put(new Complex(buffer.i()[x], buffer.q()[x])); - } - - Complex[] complexSamples = mCircularBuffer.getAll(); - - XYSeries series = getXYPane().getListOfSeries().get(0); - series.setStroke(Color.BLUE); - - series.getItems().clear(); - - for (Complex sample : complexSamples) { - series.getItems().add(new XYChartItem(sample.polarAngleDegrees(), sample.magnitude(), Color.BLUE)); - } - - refresh(); - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/SamplesPerSymbolChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/SamplesPerSymbolChart.java deleted file mode 100644 index f9b95dd4..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/SamplesPerSymbolChart.java +++ /dev/null @@ -1,59 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import javafx.collections.ObservableList; - -public class SamplesPerSymbolChart extends DoubleLineChart -{ - private double mFractionalSamplesPerSymbol; - private double mPreviousSamplesPerSymbol; - - public SamplesPerSymbolChart(int length, double samplesPerSymbol) - { - super("Samples Per Symbol", -1.0, 1.0, 0.1, length); - setSamplesPerSymbol(samplesPerSymbol); - } - - public void setSamplesPerSymbol(double samplesPerSymbol) - { - mFractionalSamplesPerSymbol = samplesPerSymbol - ((int)samplesPerSymbol); - mPreviousSamplesPerSymbol = samplesPerSymbol; - - ObservableList seriesList = getData(); - seriesList.get(0).setName("Samples Per Symbol:" + samplesPerSymbol); - } - - @Override - public void receive(Double samplesPerSymbol) - { - double delta = samplesPerSymbol - mPreviousSamplesPerSymbol - mFractionalSamplesPerSymbol; - - while(delta < (-1.0 + mFractionalSamplesPerSymbol)) - { - delta++; - } - - while(delta > 1.0) - { - delta--; - } - - super.receive(delta); - - mPreviousSamplesPerSymbol = samplesPerSymbol; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/SymbolChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/SymbolChart.java deleted file mode 100644 index d5ea1567..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/SymbolChart.java +++ /dev/null @@ -1,90 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.Complex; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.NumberAxis; -import javafx.scene.chart.ScatterChart; -import javafx.scene.chart.XYChart; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class SymbolChart extends ScatterChart implements Listener -{ - private final static Logger mLog = LoggerFactory.getLogger(SymbolChart.class); - - private ObservableList mCurrentPoints = FXCollections.observableArrayList(); -// private ObservableList mPreviousPoints = FXCollections.observableArrayList(); -// private ObservableList mOldestPoints = FXCollections.observableArrayList(); - private int mDataPointer; - private int mHistory; - - /** - * Symbol chart for plotting a series of constellation symbols over time. Maintains three history sets for - * current, previous, and oldest symbols. - * - * @param history size for each of the history sets - */ - public SymbolChart(int history) - { - super(new NumberAxis("I", -1.1, 1.1, 0.2), - new NumberAxis("Q", -1.1, 1.1, 0.2)); - - mHistory = history; - - for(int x = 0; x < mHistory; x++) - { - mCurrentPoints.add(new XYChart.Data<>(0.0, 0.0)); -// mPreviousPoints.add(new XYChart.Data<>(0.0, 0.0)); -// mOldestPoints.add(new XYChart.Data<>(0.0, 0.0)); - } - - ObservableList data = FXCollections.observableArrayList(); - data.add(new ScatterChart.Series("Constellation", mCurrentPoints)); -// data.add(new ScatterChart.Series("Previous", mPreviousPoints)); -// data.add(new ScatterChart.Series("Oldest", mOldestPoints)); - - this.setData(data); - } - - @Override - public void receive(Complex complex) - { - //Transfer previous to oldest -// XYChart.Data oldest = mOldestPoints.get(mDataPointer); -// XYChart.Data previous = mPreviousPoints.get(mDataPointer); - XYChart.Data current = mCurrentPoints.get(mDataPointer); - -// oldest.setXValue(previous.getXValue()); -// oldest.setYValue(previous.getYValue()); -// -// previous.setXValue(current.getXValue()); -// previous.setYValue(current.getYValue()); - - current.setXValue(complex.inphase()); - current.setYValue(complex.quadrature()); - - mDataPointer++; - - if(mDataPointer >= mHistory) - { - mDataPointer = 0; - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/chart/ZeroCrossingErrorDetectorChart.java b/src/main/java/io/github/dsheirer/gui/instrument/chart/ZeroCrossingErrorDetectorChart.java deleted file mode 100644 index 1ed84977..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/chart/ZeroCrossingErrorDetectorChart.java +++ /dev/null @@ -1,135 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2023 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.chart; - -import io.github.dsheirer.module.decode.ltrnet.LTRNetDecoderInstrumented; -import javafx.beans.value.ChangeListener; -import javafx.beans.value.ObservableValue; -import javafx.collections.FXCollections; -import javafx.collections.ObservableList; -import javafx.scene.chart.LineChart; -import javafx.scene.chart.NumberAxis; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class ZeroCrossingErrorDetectorChart extends LineChart -{ - private final static Logger mLog = LoggerFactory.getLogger(ZeroCrossingErrorDetectorChart.class); - - private ObservableList> mCurrentSamples = FXCollections.observableArrayList(); - private Series mCurrentSampleSeries = new Series<>("Samples", mCurrentSamples); - - private ObservableList> mPreviousSamples = FXCollections.observableArrayList(); - private Series mPreviousSampleSeries = new Series<>("Samples", mPreviousSamples); - - private ObservableList> mIdeal = FXCollections.observableArrayList(); - private Series mIdealSeries = new Series<>("Ideal", mIdeal); - - private ObservableList> mDetected = FXCollections.observableArrayList(); - private Series mDetectedSeries = new Series<>("Detected", mDetected); - - private LTRNetDecoderInstrumented mLTRNetDecoderInstrumented; - - public ZeroCrossingErrorDetectorChart(LTRNetDecoderInstrumented decoder, int length) - { - super(new NumberAxis("Samples", 0, length, 5), - new NumberAxis("Value", -1.0, 1.0, 0.25)); - - ObservableList observableList = FXCollections.observableArrayList(mCurrentSampleSeries, - mPreviousSampleSeries, mIdealSeries, mDetectedSeries); - setData(observableList); - - mLTRNetDecoderInstrumented = decoder; -// decoder.getLTRDecoder().getErrorDetector().timingError.addListener(new ErrorChangeListener()); - decoder.bufferCount.addListener(new ChangeListener() - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { - updateBuffer(); - } - }); - - for(int x = 0; x < length; x++) - { - Data sample = new Data<>(x, 0.0f); - mCurrentSamples.add(sample); - Data sample2 = new Data<>(x, 0.0f); - mPreviousSamples.add(sample2); - } - - Data ideal1 = new Data<>(5, -0.1f); - mIdeal.add(ideal1); - Data ideal2 = new Data<>(5, -0.9f); - mIdeal.add(ideal2); - - Data detected1 = new Data<>(5, -0.25f); - mDetected.add(detected1); - Data detected2 = new Data<>(5, -0.75f); - mDetected.add(detected2); - } - - private void updateBuffer() - { -// boolean[] samples = mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getBuffer(); -// -// for(int x = 0; x < samples.length; x++) -// { -// Data sample = mCurrentSamples.get(x); -// sample.setYValue(samples[x] ? 0.7f : 0.3f); -// } - } - - public class ErrorChangeListener implements ChangeListener - { - @Override - public void changed(ObservableValue observable, Object oldValue, Object newValue) - { -// float error = mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getError(); -// -// boolean[] samples = mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getBuffer(); -// -// for(int x = 0; x < samples.length; x++) -// { -// Data sample = mPreviousSamples.get(x); -// sample.setYValue(samples[x] ? -0.4f : -0.6f); -// } -// -// Data ideal1 = mIdeal.get(0); -// ideal1.setXValue(mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getZeroCrossingIdeal()); -// Data ideal2 = mIdeal.get(1); -// ideal2.setXValue(mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getZeroCrossingIdeal()); -// -// if(error == 0.0f) -// { -// Data detected1 = mDetected.get(0); -// detected1.setXValue(0.0f); -// Data detected2 = mDetected.get(1); -// detected2.setXValue(0.0f); -// } -// else -// { -// Data detected1 = mDetected.get(0); -// detected1.setXValue(mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getDetectedZeroCrossing()); -// Data detected2 = mDetected.get(1); -// detected2.setXValue(mLTRNetDecoderInstrumented.getLTRDecoder().getErrorDetector().getDetectedZeroCrossing()); -// } - } - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/AbstractAFSK1200Pane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/AbstractAFSK1200Pane.java deleted file mode 100644 index beaf818c..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/AbstractAFSK1200Pane.java +++ /dev/null @@ -1,164 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.gui.instrument.chart.AFSK1200SampleBufferChart; -import io.github.dsheirer.gui.instrument.chart.AFSK1200ZeroCrossingErrorDetectorChart; -import io.github.dsheirer.gui.instrument.chart.DecodedSymbolChart; -import io.github.dsheirer.gui.instrument.chart.IInstrumentedAFSK1200Decoder; -import io.github.dsheirer.gui.instrument.chart.RealSampleLineChart; -import io.github.dsheirer.message.IMessage; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.sample.Listener; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public abstract class AbstractAFSK1200Pane extends RealDecoderPane -{ - private final static Logger mLog = LoggerFactory.getLogger(AbstractAFSK1200Pane.class); - - private HBox mSampleChartBox; - private RealSampleLineChart mRealSampleLineChart; - private HBox mSymbolDecoderBox; - private AFSK1200SampleBufferChart mSampleBufferChart; - private AFSK1200ZeroCrossingErrorDetectorChart mZeroCrossingErrorDetectorChart; - private DecodedSymbolChart mDecodedSymbolChart; - - private IInstrumentedAFSK1200Decoder mDecoder; - - public AbstractAFSK1200Pane(DecoderType decoderType) - { - super(decoderType); - init(); - } - - private void init() - { - //This is force-cast without type checking .... - addListener((Listener) getDecoder()); - - addListener(getSampleLineChart()); - - HBox.setHgrow(getSampleChartBox(), Priority.ALWAYS); - HBox.setHgrow(getSymbolDecoderBox(), Priority.ALWAYS); - - VBox.setVgrow(getSampleChartBox(), Priority.ALWAYS); - VBox.setVgrow(getSymbolDecoderBox(), Priority.ALWAYS); - - getSampleChartBox().setMaxWidth(Double.MAX_VALUE); - getSymbolDecoderBox().setMaxWidth(Double.MAX_VALUE); - - getChildren().addAll(getSampleChartBox(), getSymbolDecoderBox()); - - getDecoder().getAFSK1200Decoder().addListener(getDecodedSymbolChart()); - - getDecoder().setMessageListener(new Listener() - { - @Override - public void receive(IMessage message) - { - mLog.debug((message.isValid() ? "PASS " : "FAIL ") + message.toString()); - } - }); - } - - protected abstract IInstrumentedAFSK1200Decoder getDecoder(); - - private HBox getSampleChartBox() - { - if(mSampleChartBox == null) - { - mSampleChartBox = new HBox(); - mSampleChartBox.setMaxHeight(Double.MAX_VALUE); - - getSampleLineChart().setMaxWidth(Double.MAX_VALUE); - getDecodedSymbolChart().setMaxWidth(Double.MAX_VALUE); - - HBox.setHgrow(getSampleLineChart(), Priority.ALWAYS); - HBox.setHgrow(getDecodedSymbolChart(), Priority.ALWAYS); - - mSampleChartBox.getChildren().addAll(getSampleLineChart(), getDecodedSymbolChart()); - } - - return mSampleChartBox; - } - - private RealSampleLineChart getSampleLineChart() - { - if(mRealSampleLineChart == null) - { - mRealSampleLineChart = new RealSampleLineChart(200, (10.0)); - } - - return mRealSampleLineChart; - } - - private HBox getSymbolDecoderBox() - { - if(mSymbolDecoderBox == null) - { - mSymbolDecoderBox = new HBox(); - mSymbolDecoderBox.setMaxWidth(Double.MAX_VALUE); - - getSampleBufferChart().setMaxWidth(Double.MAX_VALUE); - getZeroCrossingErrorDetectorChart().setMaxWidth(Double.MAX_VALUE); - - HBox.setHgrow(getSampleBufferChart(), Priority.ALWAYS); - HBox.setHgrow(getZeroCrossingErrorDetectorChart(), Priority.ALWAYS); - - mSymbolDecoderBox.getChildren().addAll(getSampleBufferChart(), getZeroCrossingErrorDetectorChart()); - } - - return mSymbolDecoderBox; - } - - private AFSK1200SampleBufferChart getSampleBufferChart() - { - if(mSampleBufferChart == null) - { - mSampleBufferChart = new AFSK1200SampleBufferChart(getDecoder(), 106); - } - - return mSampleBufferChart; - } - - private AFSK1200ZeroCrossingErrorDetectorChart getZeroCrossingErrorDetectorChart() - { - if(mZeroCrossingErrorDetectorChart == null) - { - mZeroCrossingErrorDetectorChart = new AFSK1200ZeroCrossingErrorDetectorChart(getDecoder(), - getDecoder().getAFSK1200Decoder().getErrorDetector().getBuffer().length); - } - - return mZeroCrossingErrorDetectorChart; - } - - private DecodedSymbolChart getDecodedSymbolChart() - { - if(mDecodedSymbolChart == null) - { - mDecodedSymbolChart = new DecodedSymbolChart(50); - } - - return mDecodedSymbolChart; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/ComplexDecoderPane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/ComplexDecoderPane.java deleted file mode 100644 index acf71e4a..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/ComplexDecoderPane.java +++ /dev/null @@ -1,67 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.buffer.INativeBuffer; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.SampleType; -import javafx.scene.text.Text; - -public class ComplexDecoderPane extends AbstractDecoderPane -{ - private Broadcaster mBufferBroadcaster = new Broadcaster(); - private DecoderType mDecoderType; - - public ComplexDecoderPane(DecoderType decoderType) - { - mDecoderType = decoderType; - } - - /** - * Package private - used by factory class to create an empty pane - */ - ComplexDecoderPane() - { - getChildren().add(new Text("Please select a decoder from the menu")); - } - - @Override - SampleType getSampleType() - { - return SampleType.COMPLEX; - } - - @Override - public void receive(INativeBuffer nativeBuffer) - { - mBufferBroadcaster.broadcast(nativeBuffer); - } - - public void addListener(Listener listener) - { - mBufferBroadcaster.addListener(listener); - } - - public void removeListener(Listener listener) - { - mBufferBroadcaster.removeListener(listener); - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/DecoderPaneFactory.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/DecoderPaneFactory.java deleted file mode 100644 index 151b8de7..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/DecoderPaneFactory.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2024 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder; -import java.util.EnumSet; - -public class DecoderPaneFactory -{ - private static final EnumSet SUPPORTED_DECODER_TYPES = EnumSet.of( - DecoderType.P25_PHASE1, - DecoderType.P25_PHASE2, - DecoderType.FLEETSYNC2, - DecoderType.LJ_1200, - DecoderType.LTR_NET, - DecoderType.MDC1200, - DecoderType.MPT1327, - DecoderType.TAIT_1200); - - /** - * Creates a decoder pane for the decoder type - */ - public static AbstractDecoderPane getDecoderPane(DecoderType decoderType) - { - switch(decoderType) - { - case FLEETSYNC2: - return new Fleetsync2Pane(); - case LJ_1200: - return new LJ1200Pane(); - case LTR_NET: - return new LTRNetPane(); - case MDC1200: - return new MDC1200Pane(); - case MPT1327: - return new MPT1327Pane(); - case TAIT_1200: - return new Tait1200Pane(); - case P25_PHASE1: - throw new IllegalArgumentException("Use the getP25P1DecoderPane() method for P25 decoder type"); - case P25_PHASE2: - return new P25Phase2HDQPSKPane(); - } - - return getDefaultPane(); - } - - /** - * Creates a decoder pane for the P25 decoder type - */ - public static AbstractDecoderPane getP25P1DecoderPane(P25P1Decoder.Modulation modulation) - { - switch(modulation) - { - case C4FM: - return new P25Phase1C4FMPane(); - case CQPSK: - return new P25Phase1LSMPane(); - } - - return getDefaultPane(); - } - - /** - * Creates an empty decoder pane - */ - public static AbstractDecoderPane getDefaultPane() - { - return new ComplexDecoderPane(); - } - - /** - * Indicates if the decoder type is supported by this factory - */ - public static boolean isSupported(DecoderType decoderType) - { - return SUPPORTED_DECODER_TYPES.contains(decoderType); - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/Fleetsync2Pane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/Fleetsync2Pane.java deleted file mode 100644 index d37f97fb..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/Fleetsync2Pane.java +++ /dev/null @@ -1,43 +0,0 @@ -/******************************************************************************* - * sdr-trunk - * Copyright (C) 2014-2018 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify it under the terms of the GNU General Public - * License as published by the Free Software Foundation, either version 3 of the License, or (at your option) any - * later version. - * - * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied - * warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License along with this program. - * If not, see - * - ******************************************************************************/ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.fleetsync2.Fleetsync2DecoderInstrumented; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Fleetsync2Pane extends AbstractAFSK1200Pane -{ - private final static Logger mLog = LoggerFactory.getLogger(Fleetsync2Pane.class); - - private Fleetsync2DecoderInstrumented mDecoder; - - public Fleetsync2Pane() - { - super(DecoderType.FLEETSYNC2); - } - - protected Fleetsync2DecoderInstrumented getDecoder() - { - if(mDecoder == null) - { - mDecoder = new Fleetsync2DecoderInstrumented(); - } - - return mDecoder; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/LJ1200Pane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/LJ1200Pane.java deleted file mode 100644 index ddeb01c5..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/LJ1200Pane.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.dsp.symbol.ISyncDetectListener; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.lj1200.LJ1200DecoderInstrumented; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LJ1200Pane extends AbstractAFSK1200Pane -{ - private final static Logger mLog = LoggerFactory.getLogger(LJ1200Pane.class); - - private LJ1200DecoderInstrumented mDecoder; - - public LJ1200Pane() - { - super(DecoderType.LJ_1200); - } - - protected LJ1200DecoderInstrumented getDecoder() - { - if(mDecoder == null) - { - mDecoder = new LJ1200DecoderInstrumented(); - mDecoder.getTowerMessageFramer().setSyncDetectListener(new ISyncDetectListener() - { - @Override - public void syncDetected(int bitErrors) - { - mLog.debug("Tower Sync Detected!"); - } - - @Override - public void syncLost(int bitsProcessed) - { - //no-op - } - }); - mDecoder.getTransponderMessageFramer().setSyncDetectListener(new ISyncDetectListener() - { - @Override - public void syncDetected(int bitErrors) - { - mLog.debug("Transponder Sync Detected!"); - } - - @Override - public void syncLost(int bitsProcessed) - { - //no-op - } - }); - } - - return mDecoder; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/LTRNetPane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/LTRNetPane.java deleted file mode 100644 index 667cc7f0..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/LTRNetPane.java +++ /dev/null @@ -1,154 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2023 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.gui.instrument.chart.LTRNetSampleBufferChart; -import io.github.dsheirer.gui.instrument.chart.RealSampleLineChart; -import io.github.dsheirer.gui.instrument.chart.ZeroCrossingErrorDetectorChart; -import io.github.dsheirer.message.IMessage; -import io.github.dsheirer.message.MessageDirection; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.ltrnet.DecodeConfigLTRNet; -import io.github.dsheirer.module.decode.ltrnet.LTRNetDecoderInstrumented; -import io.github.dsheirer.sample.Listener; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import javafx.scene.layout.VBox; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class LTRNetPane extends RealDecoderPane -{ - private final static Logger mLog = LoggerFactory.getLogger(LTRNetPane.class); - - private HBox mSampleChartBox; - private RealSampleLineChart mRealSampleLineChart; - private HBox mSymbolDecoderBox; - private LTRNetSampleBufferChart mLTRNetSampleBufferChart; - private ZeroCrossingErrorDetectorChart mZeroCrossingErrorDetectorChart; - - private LTRNetDecoderInstrumented mDecoder; - - public LTRNetPane() - { - super(DecoderType.LTR_NET); - init(); - } - - private void init() - { - addListener(getDecoder()); - addListener(getSampleLineChart()); - - HBox.setHgrow(getSampleChartBox(), Priority.ALWAYS); - HBox.setHgrow(getSymbolDecoderBox(), Priority.ALWAYS); - - VBox.setVgrow(getSampleChartBox(), Priority.ALWAYS); - VBox.setVgrow(getSymbolDecoderBox(), Priority.ALWAYS); - - getSampleChartBox().setMaxWidth(Double.MAX_VALUE); - getSymbolDecoderBox().setMaxWidth(Double.MAX_VALUE); - - getChildren().addAll(getSampleChartBox(), getSymbolDecoderBox()); - - } - - private LTRNetDecoderInstrumented getDecoder() - { - if(mDecoder == null) - { - DecodeConfigLTRNet config = new DecodeConfigLTRNet(); - config.setMessageDirection(MessageDirection.OSW); - mDecoder = new LTRNetDecoderInstrumented(config); - mDecoder.setMessageListener(new Listener() - { - @Override - public void receive(IMessage message) - { - mLog.debug(message.toString()); - } - }); - } - - return mDecoder; - } - - private HBox getSampleChartBox() - { - if(mSampleChartBox == null) - { - mSampleChartBox = new HBox(); - mSampleChartBox.setMaxHeight(Double.MAX_VALUE); - - getSampleLineChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getSampleLineChart(), Priority.ALWAYS); - - mSampleChartBox.getChildren().addAll(getSampleLineChart()); - } - - return mSampleChartBox; - } - - private RealSampleLineChart getSampleLineChart() - { - if(mRealSampleLineChart == null) - { - mRealSampleLineChart = new RealSampleLineChart(500, (8000.0 / 300.0)); - } - - return mRealSampleLineChart; - } - - private HBox getSymbolDecoderBox() - { - if(mSymbolDecoderBox == null) - { - mSymbolDecoderBox = new HBox(); - mSymbolDecoderBox.setMaxWidth(Double.MAX_VALUE); - - getSampleBufferChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getSampleBufferChart(), Priority.ALWAYS); - - mSampleChartBox.getChildren().addAll(getSampleBufferChart(), getZeroCrossingErrorDetectorChart()); - } - - return mSymbolDecoderBox; - } - - private LTRNetSampleBufferChart getSampleBufferChart() - { - if(mLTRNetSampleBufferChart == null) - { - mLTRNetSampleBufferChart = new LTRNetSampleBufferChart(getDecoder(), 106); - } - - return mLTRNetSampleBufferChart; - } - - private ZeroCrossingErrorDetectorChart getZeroCrossingErrorDetectorChart() - { - if(mZeroCrossingErrorDetectorChart == null) - { -// mZeroCrossingErrorDetectorChart = new ZeroCrossingErrorDetectorChart(getDecoder(), -// getDecoder().getLTRDecoder().getErrorDetector().getBuffer().length); - } - - return mZeroCrossingErrorDetectorChart; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/MDC1200Pane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/MDC1200Pane.java deleted file mode 100644 index 8de00fc2..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/MDC1200Pane.java +++ /dev/null @@ -1,64 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.dsp.symbol.ISyncDetectListener; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.mdc1200.MDCDecoderInstrumented; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MDC1200Pane extends AbstractAFSK1200Pane -{ - private final static Logger mLog = LoggerFactory.getLogger(MDC1200Pane.class); - - private MDCDecoderInstrumented mDecoder; - - public MDC1200Pane() - { - super(DecoderType.MDC1200); - } - - protected MDCDecoderInstrumented getDecoder() - { - if(mDecoder == null) - { - mDecoder = new MDCDecoderInstrumented(); - mDecoder.getMessageFramer().setSyncDetectListener(new ISyncDetectListener() - { - @Override - public void syncDetected(int bitErrors) - { - mLog.debug("Sync Detected!"); - } - - @Override - public void syncLost(int bitsProcessed) - { - mLog.debug("Sync Lost!"); - } - }); - } - - return mDecoder; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/MPT1327Pane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/MPT1327Pane.java deleted file mode 100644 index b6e1ad1f..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/MPT1327Pane.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.dsp.symbol.ISyncDetectListener; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.mpt1327.MPT1327DecoderInstrumented; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class MPT1327Pane extends AbstractAFSK1200Pane -{ - private final static Logger mLog = LoggerFactory.getLogger(MPT1327Pane.class); - - private MPT1327DecoderInstrumented mDecoder; - - public MPT1327Pane() - { - super(DecoderType.MPT1327); - } - - protected MPT1327DecoderInstrumented getDecoder() - { - if(mDecoder == null) - { - mDecoder = new MPT1327DecoderInstrumented(); - mDecoder.getControlMessageFramer().setSyncDetectListener(new ISyncDetectListener() - { - @Override - public void syncDetected(int bitErrors) - { -// mLog.debug("Control Sync Detected!"); - } - - @Override - public void syncLost(int bitsProcessed) - { - //no-op - } - }); - mDecoder.getTrafficMessageFramer().setSyncDetectListener(new ISyncDetectListener() - { - @Override - public void syncDetected(int bitErrors) - { -// mLog.debug("Traffic Sync Detected!"); - } - - @Override - public void syncLost(int bitsProcessed) - { - //no-op - } - }); - } - - return mDecoder; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1C4FMPane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1C4FMPane.java deleted file mode 100644 index deb7adfe..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1C4FMPane.java +++ /dev/null @@ -1,208 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.gui.instrument.chart.ComplexSampleLineChart; -import io.github.dsheirer.gui.instrument.chart.DoubleLineChart; -import io.github.dsheirer.gui.instrument.chart.EyeDiagramChart; -import io.github.dsheirer.gui.instrument.chart.PhaseLineChart; -import io.github.dsheirer.gui.instrument.chart.SymbolChart; -import io.github.dsheirer.message.IMessage; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.p25.phase1.P25P1DecoderC4FMInstrumented; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.ComplexSamples; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Iterator; - -public class P25Phase1C4FMPane extends ComplexDecoderPane -{ - private final static Logger mLog = LoggerFactory.getLogger(P25Phase1C4FMPane.class); - - private HBox mSampleChartBox; - private ComplexSampleLineChart mSampleLineChart; - private EyeDiagramChart mEyeDiagramChart; - private HBox mDecoderChartBox; - private SymbolChart mSymbolChart; - private PhaseLineChart mPLLPhaseErrorLineChart; - private DoubleLineChart mPLLFrequencyLineChart; - private DoubleLineChart mSamplesPerSymbolLineChart; - private Broadcaster mFilteredBufferBroadcaster = new Broadcaster(); - private P25P1DecoderC4FMInstrumented mDecoder = new P25P1DecoderC4FMInstrumented(); - - public P25Phase1C4FMPane() - { - super(DecoderType.P25_PHASE1); - init(); - } - - private void init() - { - addListener(nativeBuffer -> - { - Iterator iterator = nativeBuffer.iterator(); - - while(iterator.hasNext()) - { - getDecoder().receive(iterator.next()); - } - }); - - getDecoder().setFilteredBufferListener(mFilteredBufferBroadcaster); - getDecoder().setComplexSymbolListener(getSymbolChart()); - getDecoder().setPLLPhaseErrorListener(getPLLPhaseErrorLineChart()); - getDecoder().setPLLFrequencyListener(getPLLFrequencyLineChart()); - getDecoder().setSymbolDecisionDataListener(getEyeDiagramChart()); - getDecoder().setSamplesPerSymbolListener(getSamplesPerSymbolLineChart()); - mFilteredBufferBroadcaster.addListener(getSampleLineChart()); - - HBox.setHgrow(getSampleChartBox(), Priority.ALWAYS); - HBox.setHgrow(getDecoderChartBox(), Priority.ALWAYS); - getChildren().addAll(getSampleChartBox(), getDecoderChartBox()); - - mDecoder.setMessageListener(new Listener() - { - @Override - public void receive(IMessage message) - { - mLog.debug(message.toString()); - } - }); - - } - - @Override - public void setSampleRate(double sampleRate) - { - mLog.debug("Configuring for sample rate: " + sampleRate); - - mDecoder.setSampleRate(sampleRate); - double samplesPerSymbol = sampleRate / 4800.0; - - getSampleLineChart().setSamplesPerSymbol((int) samplesPerSymbol); - } - - private P25P1DecoderC4FMInstrumented getDecoder() - { - return mDecoder; - } - - private SymbolChart getSymbolChart() - { - if(mSymbolChart == null) - { - mSymbolChart = new SymbolChart(10); - } - - return mSymbolChart; - } - - private HBox getDecoderChartBox() - { - if(mDecoderChartBox == null) - { - mDecoderChartBox = new HBox(); - mDecoderChartBox.setMaxHeight(Double.MAX_VALUE); - getSymbolChart().setMaxWidth(Double.MAX_VALUE); - getPLLPhaseErrorLineChart().setMaxWidth(Double.MAX_VALUE); - getPLLFrequencyLineChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getSymbolChart(), Priority.ALWAYS); - HBox.setHgrow(getPLLPhaseErrorLineChart(), Priority.ALWAYS); - HBox.setHgrow(getPLLFrequencyLineChart(), Priority.ALWAYS); - mDecoderChartBox.getChildren().addAll(getSymbolChart(), getPLLPhaseErrorLineChart(), - getPLLFrequencyLineChart()); - } - - return mDecoderChartBox; - } - - private HBox getSampleChartBox() - { - if(mSampleChartBox == null) - { - mSampleChartBox = new HBox(); - mSampleChartBox.setMaxHeight(Double.MAX_VALUE); - getSampleLineChart().setMaxWidth(Double.MAX_VALUE); - getEyeDiagramChart().setMaxWidth(Double.MAX_VALUE); - getSamplesPerSymbolLineChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getSampleLineChart(), Priority.ALWAYS); - HBox.setHgrow(getEyeDiagramChart(), Priority.ALWAYS); - HBox.setHgrow(getSamplesPerSymbolLineChart(), Priority.ALWAYS); - mSampleChartBox.getChildren().addAll(getSampleLineChart(), getEyeDiagramChart(), - getSamplesPerSymbolLineChart()); - } - - return mSampleChartBox; - } - - private ComplexSampleLineChart getSampleLineChart() - { - if(mSampleLineChart == null) - { - mSampleLineChart = new ComplexSampleLineChart("Raw Samples", 100, 10); - } - - return mSampleLineChart; - } - - private EyeDiagramChart getEyeDiagramChart() - { - if(mEyeDiagramChart == null) - { - mEyeDiagramChart = new EyeDiagramChart(10, "Symbol: 3-4"); - } - - return mEyeDiagramChart; - } - - private PhaseLineChart getPLLPhaseErrorLineChart() - { - if(mPLLPhaseErrorLineChart == null) - { - mPLLPhaseErrorLineChart = new PhaseLineChart(40); - } - - return mPLLPhaseErrorLineChart; - } - - private DoubleLineChart getPLLFrequencyLineChart() - { - if(mPLLFrequencyLineChart == null) - { - mPLLFrequencyLineChart = new DoubleLineChart("PLL Frequency", -500, 500, 50, 40); - } - - return mPLLFrequencyLineChart; - } - - private DoubleLineChart getSamplesPerSymbolLineChart() - { - if(mSamplesPerSymbolLineChart == null) - { - mSamplesPerSymbolLineChart = new DoubleLineChart("Sample Point", 9.5, 11.5, 0.1, 40); - } - - return mSamplesPerSymbolLineChart; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1LSMPane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1LSMPane.java deleted file mode 100644 index a5d95169..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1LSMPane.java +++ /dev/null @@ -1,210 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.gui.instrument.chart.ComplexSampleLineChart; -import io.github.dsheirer.gui.instrument.chart.DoubleLineChart; -import io.github.dsheirer.gui.instrument.chart.EyeDiagramChart; -import io.github.dsheirer.gui.instrument.chart.PhaseLineChart; -import io.github.dsheirer.gui.instrument.chart.SamplesPerSymbolChart; -import io.github.dsheirer.gui.instrument.chart.SymbolChart; -import io.github.dsheirer.message.IMessage; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.p25.phase1.P25P1DecoderLSMInstrumented; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.ComplexSamples; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Iterator; - -public class P25Phase1LSMPane extends ComplexDecoderPane -{ - private final static Logger mLog = LoggerFactory.getLogger(P25Phase1LSMPane.class); - - private HBox mTopChartBox; - private ComplexSampleLineChart mDifferentialDemodulatedSamplesChartBox; - private EyeDiagramChart mEyeDiagramChart; - private HBox mBottomChartBox; - private SymbolChart mSymbolConstellationChart; - private PhaseLineChart mPLLPhaseErrorLineChart; - private DoubleLineChart mPLLFrequencyLineChart; - private SamplesPerSymbolChart mSamplesPerSymbolLineChart; - private Broadcaster mFilteredBufferBroadcaster = new Broadcaster(); - private P25P1DecoderLSMInstrumented mDecoder = new P25P1DecoderLSMInstrumented(); - - public P25Phase1LSMPane() - { - super(DecoderType.P25_PHASE1); - init(); - } - - private void init() - { - addListener(nativeBuffer -> - { - Iterator iterator = nativeBuffer.iterator(); - - while(iterator.hasNext()) - { - getDecoder().receive(iterator.next()); - } - }); - - getDecoder().setFilteredBufferListener(mFilteredBufferBroadcaster); - getDecoder().setComplexSymbolListener(getSymbolConstellationChart()); - getDecoder().setPLLPhaseErrorListener(getPLLPhaseErrorLineChart()); - getDecoder().setPLLFrequencyListener(getPLLFrequencyLineChart()); - getDecoder().setSymbolDecisionDataListener(getEyeDiagramChart()); - getDecoder().setSamplesPerSymbolListener(getSamplesPerSymbolLineChart()); - mFilteredBufferBroadcaster.addListener(getDifferentialDemodulatedSamplesChartBox()); - - HBox.setHgrow(getTopChartBox(), Priority.ALWAYS); - HBox.setHgrow(getBottomChartBox(), Priority.ALWAYS); - getChildren().addAll(getTopChartBox(), getBottomChartBox()); - - mDecoder.setMessageListener(new Listener() - { - @Override - public void receive(IMessage message) - { - mLog.debug(message.toString()); - } - }); - - } - - @Override - public void setSampleRate(double sampleRate) - { - mLog.debug("Configuring for sample rate: " + sampleRate); - - mDecoder.setSampleRate(sampleRate); - double samplesPerSymbol = sampleRate / 4800.0; - - getDifferentialDemodulatedSamplesChartBox().setSamplesPerSymbol((int) samplesPerSymbol); - getSamplesPerSymbolLineChart().setSamplesPerSymbol(samplesPerSymbol); - } - - private P25P1DecoderLSMInstrumented getDecoder() - { - return mDecoder; - } - - private SymbolChart getSymbolConstellationChart() - { - if(mSymbolConstellationChart == null) - { - mSymbolConstellationChart = new SymbolChart(10); - } - - return mSymbolConstellationChart; - } - - private HBox getBottomChartBox() - { - if(mBottomChartBox == null) - { - mBottomChartBox = new HBox(); - mBottomChartBox.setMaxHeight(Double.MAX_VALUE); - getSymbolConstellationChart().setMaxWidth(Double.MAX_VALUE); - getPLLPhaseErrorLineChart().setMaxWidth(Double.MAX_VALUE); - getPLLFrequencyLineChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getSymbolConstellationChart(), Priority.ALWAYS); - HBox.setHgrow(getPLLPhaseErrorLineChart(), Priority.ALWAYS); - HBox.setHgrow(getPLLFrequencyLineChart(), Priority.ALWAYS); - mBottomChartBox.getChildren().addAll(getSymbolConstellationChart(), getPLLPhaseErrorLineChart(), - getPLLFrequencyLineChart()); - } - - return mBottomChartBox; - } - - private HBox getTopChartBox() - { - if(mTopChartBox == null) - { - mTopChartBox = new HBox(); - mTopChartBox.setMaxHeight(Double.MAX_VALUE); - getDifferentialDemodulatedSamplesChartBox().setMaxWidth(Double.MAX_VALUE); - getEyeDiagramChart().setMaxWidth(Double.MAX_VALUE); - getSamplesPerSymbolLineChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getDifferentialDemodulatedSamplesChartBox(), Priority.ALWAYS); - HBox.setHgrow(getEyeDiagramChart(), Priority.ALWAYS); - HBox.setHgrow(getSamplesPerSymbolLineChart(), Priority.ALWAYS); - mTopChartBox.getChildren().addAll(getDifferentialDemodulatedSamplesChartBox(), getEyeDiagramChart(), - getSamplesPerSymbolLineChart()); - } - - return mTopChartBox; - } - - private ComplexSampleLineChart getDifferentialDemodulatedSamplesChartBox() - { - if(mDifferentialDemodulatedSamplesChartBox == null) - { - mDifferentialDemodulatedSamplesChartBox = new ComplexSampleLineChart("Raw Samples", 100, 10); - } - - return mDifferentialDemodulatedSamplesChartBox; - } - - private EyeDiagramChart getEyeDiagramChart() - { - if(mEyeDiagramChart == null) - { - mEyeDiagramChart = new EyeDiagramChart(10, "Symbol/Eye Diagram"); - } - - return mEyeDiagramChart; - } - - private PhaseLineChart getPLLPhaseErrorLineChart() - { - if(mPLLPhaseErrorLineChart == null) - { - mPLLPhaseErrorLineChart = new PhaseLineChart(40); - } - - return mPLLPhaseErrorLineChart; - } - - private DoubleLineChart getPLLFrequencyLineChart() - { - if(mPLLFrequencyLineChart == null) - { - mPLLFrequencyLineChart = new DoubleLineChart("PLL Frequency", -2500, 2500, 200, 40); - } - - return mPLLFrequencyLineChart; - } - - private SamplesPerSymbolChart getSamplesPerSymbolLineChart() - { - if(mSamplesPerSymbolLineChart == null) - { - mSamplesPerSymbolLineChart = new SamplesPerSymbolChart(40, 6.25); - } - - return mSamplesPerSymbolLineChart; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase2HDQPSKPane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase2HDQPSKPane.java deleted file mode 100644 index 9a017b02..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase2HDQPSKPane.java +++ /dev/null @@ -1,250 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.gui.instrument.chart.ComplexSampleLineChart; -import io.github.dsheirer.gui.instrument.chart.DoubleLineChart; -import io.github.dsheirer.gui.instrument.chart.EyeDiagramChart; -import io.github.dsheirer.gui.instrument.chart.PhaseLineChart; -import io.github.dsheirer.gui.instrument.chart.SampleXYChart; -import io.github.dsheirer.gui.instrument.chart.SymbolChart; -import io.github.dsheirer.message.IMessage; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2; -import io.github.dsheirer.module.decode.p25.phase2.P25P2DecoderHDQPSKInstrumented; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.complex.ComplexSamples; -import javafx.scene.layout.HBox; -import javafx.scene.layout.Priority; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -import java.util.Iterator; - -public class P25Phase2HDQPSKPane extends ComplexDecoderPane -{ - private final static Logger mLog = LoggerFactory.getLogger(P25Phase2HDQPSKPane.class); - - private HBox mSampleChartBox; - private HBox mDecoderChartBox; - - private ComplexSampleLineChart mSampleLineChartRaw; - private ComplexSampleLineChart mSampleLineChartPllCorrected; - private EyeDiagramChart mEyeDiagramChart; - private DoubleLineChart mSamplesPerSymbolLineChart; - - private SymbolChart mSymbolChart; - private PhaseLineChart mPLLPhaseErrorLineChart; - private DoubleLineChart mPLLFrequencyLineChart; - private SampleXYChart mSampleXYChart; - - - private Broadcaster mFilteredBufferBroadcaster = new Broadcaster(); - private P25P2DecoderHDQPSKInstrumented mDecoder = new P25P2DecoderHDQPSKInstrumented(new DecodeConfigP25Phase2()); - - public P25Phase2HDQPSKPane() - { - super(DecoderType.P25_PHASE2); - init(); - } - - private void init() - { - addListener(nativeBuffer -> - { - Iterator iterator = nativeBuffer.iterator(); - - while(iterator.hasNext()) - { - getDecoder().receive(iterator.next()); - } - }); - - getDecoder().getDemodulator().setFilteredGainAppliedComplexBufferListener(getSampleXYChart()); - - getDecoder().setFilteredBufferListener(mFilteredBufferBroadcaster); - getDecoder().setComplexSymbolListener(getSymbolChart()); - getDecoder().setPLLPhaseErrorListener(getPLLPhaseErrorLineChart()); - getDecoder().setPLLFrequencyListener(getPLLFrequencyLineChart()); - getDecoder().setSymbolDecisionDataListener(getEyeDiagramChart()); - getDecoder().setSamplesPerSymbolListener(getSamplesPerSymbolLineChart()); - - //Listen for raw (uncorrected) samples - mFilteredBufferBroadcaster.addListener(getSampleLineChartRaw()); - - //Listen for PLL corrected samples - getDecoder().getSampleBuffer().setSampleListener(getSampleLineChartPllCorrected()); - - HBox.setHgrow(getSampleChartBox(), Priority.ALWAYS); - HBox.setHgrow(getDecoderChartBox(), Priority.ALWAYS); - getChildren().addAll(getSampleChartBox(), getDecoderChartBox()); - - mDecoder.setMessageListener(new Listener() - { - @Override - public void receive(IMessage message) - { - mLog.debug(message.toString()); - } - }); - - } - - @Override - public void setSampleRate(double sampleRate) - { - mLog.debug("Configuring for sample rate: " + sampleRate); - - mDecoder.setSampleRate(sampleRate); - double samplesPerSymbol = sampleRate / 4800.0; - - getSampleLineChartRaw().setSamplesPerSymbol((int) samplesPerSymbol); - getDecoder().getSampleBuffer().setSampleListener(getSampleLineChartPllCorrected()); - getDecoder().getDemodulator().setFilteredGainAppliedComplexBufferListener(getSampleXYChart()); - } - - private P25P2DecoderHDQPSKInstrumented getDecoder() - { - return mDecoder; - } - - private SymbolChart getSymbolChart() - { - if(mSymbolChart == null) - { - mSymbolChart = new SymbolChart(10); - } - - return mSymbolChart; - } - - private HBox getDecoderChartBox() - { - if(mDecoderChartBox == null) - { - mDecoderChartBox = new HBox(); - mDecoderChartBox.setMaxHeight(Double.MAX_VALUE); - getSymbolChart().setMaxWidth(Double.MAX_VALUE); - getPLLPhaseErrorLineChart().setMaxWidth(Double.MAX_VALUE); - getPLLFrequencyLineChart().setMaxWidth(Double.MAX_VALUE); - getSampleXYChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getSymbolChart(), Priority.ALWAYS); - HBox.setHgrow(getPLLPhaseErrorLineChart(), Priority.ALWAYS); - HBox.setHgrow(getPLLFrequencyLineChart(), Priority.ALWAYS); - HBox.setHgrow(getSampleXYChart(), Priority.ALWAYS); - mDecoderChartBox.getChildren().addAll(getPLLPhaseErrorLineChart(), getPLLFrequencyLineChart(), - getSymbolChart(), getSampleXYChart()); - } - - return mDecoderChartBox; - } - - private HBox getSampleChartBox() - { - if(mSampleChartBox == null) - { - mSampleChartBox = new HBox(); - mSampleChartBox.setMaxHeight(Double.MAX_VALUE); - getSampleLineChartRaw().setMaxWidth(Double.MAX_VALUE); - getSampleLineChartPllCorrected().setMaxWidth(Double.MAX_VALUE); - getEyeDiagramChart().setMaxWidth(Double.MAX_VALUE); - getSamplesPerSymbolLineChart().setMaxWidth(Double.MAX_VALUE); - HBox.setHgrow(getSampleLineChartRaw(), Priority.ALWAYS); - HBox.setHgrow(getSampleLineChartPllCorrected(), Priority.ALWAYS); - HBox.setHgrow(getEyeDiagramChart(), Priority.ALWAYS); - HBox.setHgrow(getSamplesPerSymbolLineChart(), Priority.ALWAYS); - - mSampleChartBox.getChildren().addAll(getSampleLineChartRaw(), getSampleLineChartPllCorrected(), - getEyeDiagramChart(), getSamplesPerSymbolLineChart()); - } - - return mSampleChartBox; - } - - private ComplexSampleLineChart getSampleLineChartRaw() - { - if(mSampleLineChartRaw == null) - { - mSampleLineChartRaw = new ComplexSampleLineChart("Raw Samples", 100, 10); - } - - return mSampleLineChartRaw; - } - - private ComplexSampleLineChart getSampleLineChartPllCorrected() - { - if(mSampleLineChartPllCorrected == null) - { - mSampleLineChartPllCorrected = new ComplexSampleLineChart("PLL Corrected Samples", 100, 10); - } - - return mSampleLineChartPllCorrected; - } - - private EyeDiagramChart getEyeDiagramChart() - { - if(mEyeDiagramChart == null) - { - mEyeDiagramChart = new EyeDiagramChart(10, "Symbol: 3-4"); - } - - return mEyeDiagramChart; - } - - private PhaseLineChart getPLLPhaseErrorLineChart() - { - if(mPLLPhaseErrorLineChart == null) - { - mPLLPhaseErrorLineChart = new PhaseLineChart(40); - } - - return mPLLPhaseErrorLineChart; - } - - private DoubleLineChart getPLLFrequencyLineChart() - { - if(mPLLFrequencyLineChart == null) - { - mPLLFrequencyLineChart = new DoubleLineChart("PLL Frequency", -500, 500, 50, 40); - } - - return mPLLFrequencyLineChart; - } - - private SampleXYChart getSampleXYChart() - { - if(mSampleXYChart == null) - { - mSampleXYChart = new SampleXYChart(100, "Samples"); - } - - return mSampleXYChart; - } - - private DoubleLineChart getSamplesPerSymbolLineChart() - { - if(mSamplesPerSymbolLineChart == null) - { - mSamplesPerSymbolLineChart = new DoubleLineChart("Sample Point", 8.0, 10.0, 0.1, 40); - } - - return mSamplesPerSymbolLineChart; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/RealDecoderPane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/RealDecoderPane.java deleted file mode 100644 index 7bff926c..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/RealDecoderPane.java +++ /dev/null @@ -1,70 +0,0 @@ -/* - * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer - * - * This program is free software: you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation, either version 3 of the License, or - * (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program. If not, see - * **************************************************************************** - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.sample.Broadcaster; -import io.github.dsheirer.sample.Listener; -import io.github.dsheirer.sample.SampleType; -import javafx.scene.text.Text; - -public class RealDecoderPane extends AbstractDecoderPane -{ - private Broadcaster mBufferBroadcaster = new Broadcaster(); - private DecoderType mDecoderType; - - public RealDecoderPane(DecoderType decoderType) - { - mDecoderType = decoderType; - } - - /** - * Package private - used by factory class to create an empty pane - */ - RealDecoderPane() - { - getChildren().add(new Text("Please select a decoder from the menu")); - } - - @Override - SampleType getSampleType() - { - return SampleType.COMPLEX; - } - - @Override - public void receive(float[] buffer) - { - mBufferBroadcaster.broadcast(buffer); - } - - public void addListener(Listener listener) - { - mBufferBroadcaster.addListener(listener); - } - - public void removeListener(Listener listener) - { - mBufferBroadcaster.removeListener(listener); - } - - public void setSampleRate(double sampleRate) - { - } -} diff --git a/src/main/java/io/github/dsheirer/gui/instrument/decoder/Tait1200Pane.java b/src/main/java/io/github/dsheirer/gui/instrument/decoder/Tait1200Pane.java deleted file mode 100644 index 17833acf..00000000 --- a/src/main/java/io/github/dsheirer/gui/instrument/decoder/Tait1200Pane.java +++ /dev/null @@ -1,78 +0,0 @@ -/* - * - * * ****************************************************************************** - * * Copyright (C) 2014-2020 Dennis Sheirer - * * - * * This program is free software: you can redistribute it and/or modify - * * it under the terms of the GNU General Public License as published by - * * the Free Software Foundation, either version 3 of the License, or - * * (at your option) any later version. - * * - * * This program is distributed in the hope that it will be useful, - * * but WITHOUT ANY WARRANTY; without even the implied warranty of - * * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * * GNU General Public License for more details. - * * - * * You should have received a copy of the GNU General Public License - * * along with this program. If not, see - * * ***************************************************************************** - * - * - */ -package io.github.dsheirer.gui.instrument.decoder; - -import io.github.dsheirer.dsp.symbol.ISyncDetectListener; -import io.github.dsheirer.module.decode.DecoderType; -import io.github.dsheirer.module.decode.tait.Tait1200DecoderInstrumented; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - -public class Tait1200Pane extends AbstractAFSK1200Pane -{ - private final static Logger mLog = LoggerFactory.getLogger(Tait1200Pane.class); - - private Tait1200DecoderInstrumented mDecoder; - - public Tait1200Pane() - { - super(DecoderType.TAIT_1200); - } - - protected Tait1200DecoderInstrumented getDecoder() - { - if(mDecoder == null) - { - mDecoder = new Tait1200DecoderInstrumented(); - mDecoder.getANIMessageFramer().setSyncDetectListener(new ISyncDetectListener() - { - @Override - public void syncDetected(int bitErrors) - { - mLog.debug("ANI Sync Detected!"); - } - - @Override - public void syncLost(int bitsProcessed) - { - - } - }); - mDecoder.getGPSMessageFramer().setSyncDetectListener(new ISyncDetectListener() - { - @Override - public void syncDetected(int bitErrors) - { - mLog.debug("GPS Sync Detected!"); - } - - @Override - public void syncLost(int bitsProcessed) - { - - } - }); - } - - return mDecoder; - } -} diff --git a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java index 63218562..c8e97e86 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/channel/P25P1ConfigurationEditor.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2024 Dennis Sheirer + * Copyright (C) 2014-2025 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -27,7 +27,7 @@ import io.github.dsheirer.module.decode.DecoderType; import io.github.dsheirer.module.decode.config.AuxDecodeConfiguration; import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25Phase1; -import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder; +import io.github.dsheirer.module.decode.p25.phase1.Modulation; import io.github.dsheirer.module.log.EventLogType; import io.github.dsheirer.module.log.config.EventLogConfiguration; import io.github.dsheirer.playlist.PlaylistManager; @@ -332,7 +332,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor DecodeConfigP25Phase1 decodeConfig = (DecodeConfigP25Phase1)config; getIgnoreDataCallsButton().setSelected(decodeConfig.getIgnoreDataCalls()); getTrafficChannelPoolSizeSpinner().getValueFactory().setValue(decodeConfig.getTrafficChannelPoolSize()); - if(decodeConfig.getModulation() == P25P1Decoder.Modulation.C4FM) + if(decodeConfig.getModulation() == Modulation.C4FM) { getC4FMToggleButton().setSelected(true); getLSMToggleButton().setSelected(false); @@ -366,7 +366,7 @@ public class P25P1ConfigurationEditor extends ChannelConfigurationEditor config.setIgnoreDataCalls(getIgnoreDataCallsButton().isSelected()); config.setTrafficChannelPoolSize(getTrafficChannelPoolSizeSpinner().getValue()); - config.setModulation(getC4FMToggleButton().isSelected() ? P25P1Decoder.Modulation.C4FM : P25P1Decoder.Modulation.CQPSK); + config.setModulation(getC4FMToggleButton().isSelected() ? Modulation.C4FM : Modulation.CQPSK); getItem().setDecodeConfiguration(config); } diff --git a/src/main/java/io/github/dsheirer/gui/playlist/radioreference/FrequencyEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/radioreference/FrequencyEditor.java index cb48e837..66a5cf6e 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/radioreference/FrequencyEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/radioreference/FrequencyEditor.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer + * Copyright (C) 2014-2025 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -26,7 +26,7 @@ import io.github.dsheirer.module.decode.DecoderFactory; import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM; import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25Phase1; -import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder; +import io.github.dsheirer.module.decode.p25.phase1.Modulation; import io.github.dsheirer.playlist.PlaylistManager; import io.github.dsheirer.preference.UserPreferences; import io.github.dsheirer.rrapi.type.Category; @@ -36,6 +36,7 @@ import io.github.dsheirer.rrapi.type.SubCategory; import io.github.dsheirer.service.radioreference.RadioReference; import io.github.dsheirer.source.config.SourceConfigTuner; import io.github.dsheirer.util.ThreadPool; +import java.text.DecimalFormat; import javafx.animation.FadeTransition; import javafx.application.Platform; import javafx.geometry.HPos; @@ -53,8 +54,6 @@ import javafx.util.Duration; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import java.text.DecimalFormat; - public class FrequencyEditor extends VBox { private static final Logger mLog = LoggerFactory.getLogger(FrequencyEditor.class); @@ -421,7 +420,7 @@ public class FrequencyEditor extends VBox } else if(decodeConfiguration instanceof DecodeConfigP25Phase1) { - ((DecodeConfigP25Phase1)decodeConfiguration).setModulation(P25P1Decoder.Modulation.C4FM); + ((DecodeConfigP25Phase1)decodeConfiguration).setModulation(Modulation.C4FM); } channel.setDecodeConfiguration(decodeConfiguration); return channel; diff --git a/src/main/java/io/github/dsheirer/gui/playlist/radioreference/SiteEditor.java b/src/main/java/io/github/dsheirer/gui/playlist/radioreference/SiteEditor.java index 8119c988..30e01809 100644 --- a/src/main/java/io/github/dsheirer/gui/playlist/radioreference/SiteEditor.java +++ b/src/main/java/io/github/dsheirer/gui/playlist/radioreference/SiteEditor.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2024 Dennis Sheirer + * Copyright (C) 2014-2025 Dennis Sheirer * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by @@ -30,7 +30,7 @@ import io.github.dsheirer.module.decode.config.DecodeConfiguration; import io.github.dsheirer.module.decode.dmr.DecodeConfigDMR; import io.github.dsheirer.module.decode.dmr.channel.TimeslotFrequency; import io.github.dsheirer.module.decode.p25.phase1.DecodeConfigP25Phase1; -import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder; +import io.github.dsheirer.module.decode.p25.phase1.Modulation; import io.github.dsheirer.module.decode.p25.phase2.DecodeConfigP25Phase2; import io.github.dsheirer.module.decode.p25.phase2.enumeration.ScrambleParameters; import io.github.dsheirer.playlist.PlaylistManager; @@ -257,7 +257,7 @@ public class SiteEditor extends GridPane { if(p1config instanceof DecodeConfigP25Phase1) { - ((DecodeConfigP25Phase1)p1config).setModulation(P25P1Decoder.Modulation.CQPSK); + ((DecodeConfigP25Phase1)p1config).setModulation(Modulation.CQPSK); } } return p1config; diff --git a/src/main/java/io/github/dsheirer/gui/squelch/NoiseSquelchView.java b/src/main/java/io/github/dsheirer/gui/squelch/NoiseSquelchView.java index 293a35cc..26ebb088 100644 --- a/src/main/java/io/github/dsheirer/gui/squelch/NoiseSquelchView.java +++ b/src/main/java/io/github/dsheirer/gui/squelch/NoiseSquelchView.java @@ -22,6 +22,7 @@ package io.github.dsheirer.gui.squelch; import io.github.dsheirer.dsp.squelch.INoiseSquelchController; import io.github.dsheirer.dsp.squelch.NoiseSquelch; import io.github.dsheirer.dsp.squelch.NoiseSquelchState; +import io.github.dsheirer.gui.symbol.ChannelView; import io.github.dsheirer.playlist.PlaylistManager; import io.github.dsheirer.sample.Listener; import io.github.dsheirer.util.ThreadPool; @@ -72,7 +73,7 @@ import org.slf4j.LoggerFactory; * 1 for an operating range of 1-6. The close slider uses a range of 0-5 that is combined with the open slider for a * range of (open + 0) to (open + 5). */ -public class NoiseSquelchView extends VBox implements Listener +public class NoiseSquelchView extends ChannelView implements Listener { private static final Logger LOGGER = LoggerFactory.getLogger(NoiseSquelchView.class); private static final DecimalFormat DECIMAL_FORMAT = new DecimalFormat("0.00"); @@ -129,7 +130,6 @@ public class NoiseSquelchView extends VBox implements Listener