From 0d886c272e3c0ca584bc91f4ba5ca84a48445f22 Mon Sep 17 00:00:00 2001 From: Denny Sheirer Date: Sun, 16 Nov 2025 06:52:17 -0500 Subject: [PATCH] #1067 P25 Phase 1 C4FM/LSM decoder redesign. (#2294) C4FM now uses SIMD differential decoding and soft sync detection. LSM updated with soft sync detector and retains original Gardner error detector. Adds new QPSK symbol view in the now playing channel tab. Restores PLL error driven tuner Auto-PPM feature. Deletes the demod viewer GUI application and all instrumented decoders Updates DMR to send soft symbols to new symbol view in Now Playing. Co-authored-by: Dennis Sheirer --- .../github/dsheirer/bits/BinaryMessage.java | 10 + .../io/github/dsheirer/bits/IntField.java | 12 +- .../bits/MultiSyncPatternMatcher.java | 35 +- .../dsheirer/bits/SoftSyncDetector.java | 28 +- .../dsp/filter/design/FilterViewer.java | 22 +- .../psk/DQPSKDecisionDirectedDemodulator.java | 128 -- ...cisionDirectedDemodulatorInstrumented.java | 147 -- .../DQPSKDecisionDirectedSymbolEvaluator.java | 172 --- .../DQPSKGardnerDemodulatorInstrumented.java | 152 --- .../dsheirer/dsp/psk/GardnerDetector.java | 83 -- .../dsheirer/dsp/psk/IQPSKSymbolDecoder.java | 29 - .../dsp/psk/ISymbolPhaseErrorCalculator.java | 28 - ...InterpolatingSampleBufferInstrumented.java | 80 -- .../dsp/psk/LSMConstellationDecoder.java | 28 - .../dsheirer/dsp/psk/QPSKStarSlicer.java | 73 - .../dsheirer/dsp/psk/QPSKSymbolDecoder.java | 91 -- .../psk/QPSKSymbolPhaseErrorCalculator.java | 58 - .../dsheirer/dsp/psk/SymbolDecisionData.java | 115 -- .../dsheirer/dsp/psk/SymbolInversion.java | 37 - .../demod/DifferentialDemodulatorFactory.java | 20 +- ...java => DifferentialDemodulatorFloat.java} | 10 +- ...> DifferentialDemodulatorFloatScalar.java} | 6 +- ...ifferentialDemodulatorFloatVector128.java} | 6 +- ...ifferentialDemodulatorFloatVector256.java} | 4 +- ...ifferentialDemodulatorFloatVector512.java} | 6 +- ...DifferentialDemodulatorFloatVector64.java} | 6 +- .../psk/pll/AdaptivePLLBandwidthMonitor.java | 125 -- .../pll/FrequencyCorrectionSyncMonitor.java | 1 + .../psk/pll/QPSKPhaseInversionCalculator.java | 133 -- .../dsheirer/dsp/squelch/PowerMonitor.java | 41 +- .../io/github/dsheirer/dsp/symbol/Dibit.java | 23 +- .../dsheirer/dsp/symbol/DibitDelayBuffer.java | 260 ---- .../dmr => dsp/symbol}/DibitDelayLine.java | 47 +- .../io/github/dsheirer/edac/BCH_63_16_11.java | 106 -- .../dsheirer/edac/ReedSolomon_63_P25.java | 4 +- .../java/io/github/dsheirer/edac/bch/BCH.java | 7 + .../gui/{instrument => }/RecentFilesMenu.java | 34 +- .../gui/channel/ChannelSpectrumPanel.java | 114 +- .../gui/instrument/DemodulatorViewerFX.java | 257 ---- .../gui/instrument/PlaybackController.java | 423 ------ .../gui/instrument/ViewerDesktop.java | 109 -- .../chart/AFSK1200SampleBufferChart.java | 169 --- ...FSK1200ZeroCrossingErrorDetectorChart.java | 118 -- .../chart/ComplexSampleLineChart.java | 132 -- .../instrument/chart/DecodedSymbolChart.java | 73 - .../gui/instrument/chart/DoubleLineChart.java | 91 -- .../gui/instrument/chart/EyeDiagramChart.java | 149 --- .../chart/IInstrumentedAFSK1200Decoder.java | 30 - .../chart/LTRNetSampleBufferChart.java | 174 --- .../gui/instrument/chart/PhaseLineChart.java | 73 - .../instrument/chart/RealSampleLineChart.java | 85 -- .../gui/instrument/chart/SampleXYChart.java | 87 -- .../chart/SamplesPerSymbolChart.java | 59 - .../gui/instrument/chart/SymbolChart.java | 90 -- .../chart/ZeroCrossingErrorDetectorChart.java | 135 -- .../decoder/AbstractAFSK1200Pane.java | 164 --- .../decoder/ComplexDecoderPane.java | 67 - .../decoder/DecoderPaneFactory.java | 96 -- .../instrument/decoder/Fleetsync2Pane.java | 43 - .../gui/instrument/decoder/LJ1200Pane.java | 78 -- .../gui/instrument/decoder/LTRNetPane.java | 154 --- .../gui/instrument/decoder/MDC1200Pane.java | 64 - .../gui/instrument/decoder/MPT1327Pane.java | 78 -- .../instrument/decoder/P25Phase1C4FMPane.java | 208 --- .../instrument/decoder/P25Phase1LSMPane.java | 210 --- .../decoder/P25Phase2HDQPSKPane.java | 250 ---- .../instrument/decoder/RealDecoderPane.java | 70 - .../gui/instrument/decoder/Tait1200Pane.java | 78 -- .../channel/P25P1ConfigurationEditor.java | 8 +- .../radioreference/FrequencyEditor.java | 9 +- .../playlist/radioreference/SiteEditor.java | 6 +- .../gui/squelch/NoiseSquelchView.java | 15 +- .../dsheirer/gui/symbol/ChannelView.java | 55 + .../dsheirer/gui/symbol/SymbolView.java | 133 ++ .../dsheirer/gui/viewer/P25P1Viewer.java | 14 +- .../symbol/ISymbolResultsListener.java} | 18 +- .../gui/viewer/symbol/SymbolViewPanel.java | 255 ++++ .../gui/viewer/symbol/SymbolViewerFX.java | 104 ++ .../viewer/sync}/ISyncResultsListener.java | 13 +- .../viewer/sync}/SyncResultsViewer.java | 36 +- .../gui/viewer/sync/SyncVisualizer.java | 218 +++ .../message/DroppedSamplesMessage.java | 106 ++ .../dsheirer/module/ProcessingChain.java | 4 +- .../module/decode/FeedbackDecoder.java | 77 +- .../module/decode/PrimaryDecoder.java | 74 +- .../module/decode/SquelchControlDecoder.java | 71 + .../dsheirer/module/decode/am/AMDecoder.java | 4 +- .../module/decode/dmr/DMRDecoder.java | 18 +- .../decode/dmr/DMRHardSymbolProcessor.java | 1 + .../decode/dmr/DMRSoftSymbolProcessor.java | 23 +- .../dmr/sync/visualizer/SyncVisualizer.java | 144 -- .../Fleetsync2DecoderInstrumented.java | 55 - .../lj1200/LJ1200DecoderInstrumented.java | 55 - .../mdc1200/MDCDecoderInstrumented.java | 55 - .../mpt1327/MPT1327DecoderInstrumented.java | 55 - .../module/decode/nbfm/NBFMDecoder.java | 4 +- .../module/decode/p25/phase1/C4FMSlicer.java | 103 -- .../p25/phase1/DecodeConfigP25Phase1.java | 8 +- .../phase1/IP25P1DataUnitDetectListener.java | 44 - ...C4FMFrameListener.java => Modulation.java} | 42 +- .../module/decode/p25/phase1/NACTracker.java | 196 +++ .../p25/phase1/P25P1DataUnitDetector.java | 566 -------- .../decode/p25/phase1/P25P1DataUnitID.java | 130 +- .../decode/p25/phase1/P25P1Decoder.java | 227 ---- .../decode/p25/phase1/P25P1DecoderC4FM.java | 478 +++++-- .../phase1/P25P1DecoderC4FMInstrumented.java | 126 -- .../decode/p25/phase1/P25P1DecoderLSM.java | 457 +++++-- .../phase1/P25P1DecoderLSMInstrumented.java | 127 -- .../decode/p25/phase1/P25P1DecoderState.java | 6 +- .../p25/phase1/P25P1DemodulatorC4FM.java | 1144 ++++++++++++++++ .../p25/phase1/P25P1DemodulatorLSM.java | 393 ++++++ .../p25/phase1/P25P1MessageAssembler.java | 273 ++++ .../decode/p25/phase1/P25P1MessageFramer.java | 1179 ++++++++++------- .../p25/phase1/P25P1MessageProcessor.java | 4 + .../P25P1NetworkConfigurationMonitor.java | 6 +- .../decode/p25/phase1/P25P1SyncDetector.java | 170 --- .../p25/phase1/message/P25MessageFactory.java | 10 +- .../p25/phase1/message/ldu/LDU1Message.java | 51 +- .../p25/phase1/message/ldu/LDU2Message.java | 61 +- .../p25/phase1/message/pdu/PDUHeader.java | 34 +- .../phase1/message/pdu/PDUHeaderFactory.java | 15 +- .../p25/phase1/message/pdu/PDUMessage.java | 4 +- .../phase1/message/pdu/PDUMessageFactory.java | 127 +- .../message/pdu/PDUSequenceMessage.java | 7 +- .../message/pdu/ambtc/AMBTCMessage.java | 4 + .../message/pdu/response/ResponseMessage.java | 4 +- .../p25/phase1/message/tsbk/TSBKMessage.java | 23 +- .../message/tsbk/TSBKMessageFactory.java | 36 +- .../phase1/message/vselp/VSELP1Message.java | 59 - .../phase1/message/vselp/VSELP2Message.java | 59 - .../phase1/sync/P25P1HardSyncDetector.java | 50 + .../phase1/sync/P25P1SoftSyncDetector.java | 71 + .../sync/P25P1SoftSyncDetectorFactory.java | 59 + .../sync/P25P1SoftSyncDetectorScalar.java | 46 + .../sync/P25P1SoftSyncDetectorVector128.java | 51 + .../sync/P25P1SoftSyncDetectorVector256.java | 51 + .../sync/P25P1SoftSyncDetectorVector512.java | 55 + .../sync/P25P1SoftSyncDetectorVector64.java | 51 + .../p25/phase1/sync/P25P1SyncDetector.java | 79 ++ .../decode/p25/phase2/P25P2Decoder.java | 8 +- .../P25P2DecoderHDQPSKInstrumented.java | 141 -- .../tait/Tait1200DecoderInstrumented.java | 55 - .../tuner/TunerFrequencyErrorMonitor.java | 15 +- .../tuner/manager/ChannelSourceManager.java | 3 +- .../vector/calibrate/CalibrationManager.java | 2 + .../vector/calibrate/CalibrationType.java | 1 + .../DifferentialDemodulatorCalibration.java | 22 +- .../sync/P25P1SoftSyncCalibration.java | 292 ++++ src/main/resources/sdrtrunk_style.css | 24 + 149 files changed, 5990 insertions(+), 8984 deletions(-) delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulator.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedDemodulatorInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/DQPSKDecisionDirectedSymbolEvaluator.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/DQPSKGardnerDemodulatorInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/GardnerDetector.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/IQPSKSymbolDecoder.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/ISymbolPhaseErrorCalculator.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/InterpolatingSampleBufferInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/LSMConstellationDecoder.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/QPSKStarSlicer.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolDecoder.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/QPSKSymbolPhaseErrorCalculator.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/SymbolDecisionData.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/SymbolInversion.java rename src/main/java/io/github/dsheirer/dsp/psk/demod/{DifferentialDemodulator.java => DifferentialDemodulatorFloat.java} (87%) rename src/main/java/io/github/dsheirer/dsp/psk/demod/{DifferentialDemodulatorScalar.java => DifferentialDemodulatorFloatScalar.java} (94%) rename src/main/java/io/github/dsheirer/dsp/psk/demod/{DifferentialDemodulatorVector128.java => DifferentialDemodulatorFloatVector128.java} (95%) rename src/main/java/io/github/dsheirer/dsp/psk/demod/{DifferentialDemodulatorVector256.java => DifferentialDemodulatorFloatVector256.java} (96%) rename src/main/java/io/github/dsheirer/dsp/psk/demod/{DifferentialDemodulatorVector512.java => DifferentialDemodulatorFloatVector512.java} (95%) rename src/main/java/io/github/dsheirer/dsp/psk/demod/{DifferentialDemodulatorVector64.java => DifferentialDemodulatorFloatVector64.java} (95%) delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/pll/AdaptivePLLBandwidthMonitor.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/psk/pll/QPSKPhaseInversionCalculator.java delete mode 100644 src/main/java/io/github/dsheirer/dsp/symbol/DibitDelayBuffer.java rename src/main/java/io/github/dsheirer/{module/decode/dmr => dsp/symbol}/DibitDelayLine.java (74%) delete mode 100644 src/main/java/io/github/dsheirer/edac/BCH_63_16_11.java rename src/main/java/io/github/dsheirer/gui/{instrument => }/RecentFilesMenu.java (89%) delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/DemodulatorViewerFX.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/PlaybackController.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/ViewerDesktop.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200SampleBufferChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/AFSK1200ZeroCrossingErrorDetectorChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/ComplexSampleLineChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/DecodedSymbolChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/DoubleLineChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/EyeDiagramChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/IInstrumentedAFSK1200Decoder.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/LTRNetSampleBufferChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/PhaseLineChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/RealSampleLineChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/SampleXYChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/SamplesPerSymbolChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/SymbolChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/chart/ZeroCrossingErrorDetectorChart.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/AbstractAFSK1200Pane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/ComplexDecoderPane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/DecoderPaneFactory.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/Fleetsync2Pane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/LJ1200Pane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/LTRNetPane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/MDC1200Pane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/MPT1327Pane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1C4FMPane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase1LSMPane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/P25Phase2HDQPSKPane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/RealDecoderPane.java delete mode 100644 src/main/java/io/github/dsheirer/gui/instrument/decoder/Tait1200Pane.java create mode 100644 src/main/java/io/github/dsheirer/gui/symbol/ChannelView.java create mode 100644 src/main/java/io/github/dsheirer/gui/symbol/SymbolView.java rename src/main/java/io/github/dsheirer/gui/{instrument/decoder/AbstractDecoderPane.java => viewer/symbol/ISymbolResultsListener.java} (67%) create mode 100644 src/main/java/io/github/dsheirer/gui/viewer/symbol/SymbolViewPanel.java create mode 100644 src/main/java/io/github/dsheirer/gui/viewer/symbol/SymbolViewerFX.java rename src/main/java/io/github/dsheirer/{module/decode/dmr/sync/visualizer => gui/viewer/sync}/ISyncResultsListener.java (78%) rename src/main/java/io/github/dsheirer/{module/decode/dmr/sync/visualizer => gui/viewer/sync}/SyncResultsViewer.java (75%) create mode 100644 src/main/java/io/github/dsheirer/gui/viewer/sync/SyncVisualizer.java create mode 100644 src/main/java/io/github/dsheirer/message/DroppedSamplesMessage.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/SquelchControlDecoder.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/dmr/sync/visualizer/SyncVisualizer.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/fleetsync2/Fleetsync2DecoderInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/lj1200/LJ1200DecoderInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/mdc1200/MDCDecoderInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327DecoderInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/C4FMSlicer.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/IP25P1DataUnitDetectListener.java rename src/main/java/io/github/dsheirer/module/decode/p25/phase1/{C4FMFrameListener.java => Modulation.java} (63%) create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/NACTracker.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1DataUnitDetector.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1Decoder.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1DecoderC4FMInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1DecoderLSMInstrumented.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1DemodulatorC4FM.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1DemodulatorLSM.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1MessageAssembler.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/P25P1SyncDetector.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/message/vselp/VSELP1Message.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/message/vselp/VSELP2Message.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1HardSyncDetector.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SoftSyncDetector.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SoftSyncDetectorFactory.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SoftSyncDetectorScalar.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SoftSyncDetectorVector128.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SoftSyncDetectorVector256.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SoftSyncDetectorVector512.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SoftSyncDetectorVector64.java create mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase1/sync/P25P1SyncDetector.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/p25/phase2/P25P2DecoderHDQPSKInstrumented.java delete mode 100644 src/main/java/io/github/dsheirer/module/decode/tait/Tait1200DecoderInstrumented.java create mode 100644 src/main/java/io/github/dsheirer/vector/calibrate/sync/P25P1SoftSyncCalibration.java create mode 100644 src/main/resources/sdrtrunk_style.css 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