#296 APCO25 Phase II Decoder Implementation (#589)

P25 Phase 2 Decoder implementation.
This commit is contained in:
Denny Sheirer
2019-11-17 06:56:52 -05:00
committed by GitHub
parent d5b802e794
commit f934676bd0
561 changed files with 35609 additions and 6215 deletions

View File

@@ -75,6 +75,8 @@ import javax.swing.JOptionPane;
import javax.swing.JSeparator;
import javax.swing.KeyStroke;
import javax.swing.UIManager;
import javax.swing.event.MenuEvent;
import javax.swing.event.MenuListener;
import javax.swing.plaf.metal.MetalLookAndFeel;
import java.awt.AWTException;
import java.awt.Desktop;
@@ -211,7 +213,7 @@ public class SDRTrunk implements Listener<TunerEvent>
mControllerPanel = new ControllerPanel(audioPlaybackManager, aliasModel, mBroadcastModel,
mChannelModel, channelMapModel, mChannelProcessingManager, mIconManager,
mapService, mSettingsManager, mSourceManager, tunerModel, mUserPreferences);
mapService, mSettingsManager, mSourceManager, tunerModel, mUserPreferences, recorderManager);
mSpectralPanel = new SpectralDisplayPanel(mChannelModel,
mChannelProcessingManager, mSettingsManager, tunerModel);
@@ -397,10 +399,11 @@ public class SDRTrunk implements Listener<TunerEvent>
viewMenu.add(new BroadcastStatusVisibleMenuItem(mControllerPanel));
viewMenu.add(new JSeparator());
for(Tuner tuner : mSourceManager.getTunerModel().getTuners())
{
viewMenu.add(new ShowTunerMenuItem(mSourceManager.getTunerModel(), tuner));
}
// for(Tuner tuner : mSourceManager.getTunerModel().getTuners())
// {
// viewMenu.add(new ShowTunerMenuItem(mSourceManager.getTunerModel(), tuner));
// }
viewMenu.add(new TunersMenu());
viewMenu.add(new JSeparator());
viewMenu.add(new ClearTunerMenuItem(mSpectralPanel));
@@ -631,6 +634,34 @@ public class SDRTrunk implements Listener<TunerEvent>
}
}
public class TunersMenu extends JMenu
{
public TunersMenu()
{
super("Tuners");
addMenuListener(new MenuListener()
{
@Override
public void menuSelected(MenuEvent e)
{
removeAll();
for(Tuner tuner : mSourceManager.getTunerModel().getTuners())
{
add(new ShowTunerMenuItem(mSourceManager.getTunerModel(), tuner));
}
}
@Override
public void menuDeselected(MenuEvent e) { }
@Override
public void menuCanceled(MenuEvent e) { }
});
}
}
/**
* Launch the application.
*/

View File

@@ -1,23 +1,29 @@
/*******************************************************************************
* 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.
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
*/
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.P25Decoder;
import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder;
import javafx.application.Application;
import javafx.application.Platform;
import javafx.event.ActionEvent;
@@ -61,7 +67,7 @@ public class DemodulatorViewerFX extends Application
borderPane.setTop(getMenuBar());
borderPane.setCenter(getViewerDesktop());
Scene scene = new Scene(borderPane, 1500, 900);
Scene scene = new Scene(borderPane, 1800, 900);
mStage.setScene(scene);
mStage.show();
@@ -84,7 +90,7 @@ public class DemodulatorViewerFX extends Application
}
}
private void setTitle(P25Decoder.Modulation modulation)
private void setTitle(P25P1Decoder.Modulation modulation)
{
if(modulation != null)
{
@@ -180,7 +186,7 @@ public class DemodulatorViewerFX extends Application
@Override
public void handle(ActionEvent event)
{
getViewerDesktop().setP25Phase1Decoder(P25Decoder.Modulation.C4FM);
getViewerDesktop().setP25Phase1Decoder(P25P1Decoder.Modulation.C4FM);
setTitle(decoderType);
}
});
@@ -194,7 +200,7 @@ public class DemodulatorViewerFX extends Application
@Override
public void handle(ActionEvent event)
{
getViewerDesktop().setP25Phase1Decoder(P25Decoder.Modulation.CQPSK);
getViewerDesktop().setP25Phase1Decoder(P25P1Decoder.Modulation.CQPSK);
setTitle(decoderType);
}
});
@@ -203,7 +209,7 @@ public class DemodulatorViewerFX extends Application
}
else
{
MenuItem decoderMenuItem = new MenuItem(decoderType.getShortDisplayString());
MenuItem decoderMenuItem = new MenuItem(decoderType.getDisplayString());
decoderMenuItem.setOnAction(new EventHandler<ActionEvent>()
{

View File

@@ -1,21 +1,23 @@
/*
* ******************************************************************************
* sdrtrunk
* 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.
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
* 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 <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
package io.github.dsheirer.gui.instrument;
@@ -205,8 +207,10 @@ public class PlaybackController extends HBox implements IFrameLocationListener
getPlaybackPositionText().setDisable(true);
getPlay1Button().setDisable(true);
getPlay10Button().setDisable(true);
getPlay30Button().setDisable(true);
getPlay100Button().setDisable(true);
getPlay1000Button().setDisable(true);
getPlay2000Button().setDisable(true);
}
/**
@@ -218,8 +222,10 @@ public class PlaybackController extends HBox implements IFrameLocationListener
getPlaybackPositionText().setDisable(false);
getPlay1Button().setDisable(false);
getPlay10Button().setDisable(false);
getPlay30Button().setDisable(false);
getPlay100Button().setDisable(false);
getPlay1000Button().setDisable(false);
getPlay2000Button().setDisable(false);
}
private HBox getControlsBox()

View File

@@ -1,24 +1,28 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2018 Dennis Sheirer
/*
* ******************************************************************************
* sdrtrunk
* 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 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
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.module.decode.DecoderType;
import io.github.dsheirer.module.decode.p25.P25Decoder;
import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder;
import javafx.scene.layout.BorderPane;
import java.io.File;
@@ -45,9 +49,9 @@ public class ViewerDesktop extends BorderPane
setDecoderPane(DecoderPaneFactory.getDecoderPane(decoderType));
}
public void setP25Phase1Decoder(P25Decoder.Modulation modulation)
public void setP25Phase1Decoder(P25P1Decoder.Modulation modulation)
{
setDecoderPane(DecoderPaneFactory.getP25DecoderPane(modulation));
setDecoderPane(DecoderPaneFactory.getP25P1DecoderPane(modulation));
}
private void setDecoderPane(AbstractDecoderPane decoderPane)

View File

@@ -1,25 +1,31 @@
/*******************************************************************************
* 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.
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
*/
package io.github.dsheirer.gui.instrument.chart;
import io.github.dsheirer.buffer.ComplexCircularBuffer;
import io.github.dsheirer.dsp.gain.ComplexGain;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
import io.github.dsheirer.sample.complex.Complex;
import io.github.dsheirer.sample.complex.ComplexSampleListener;
import javafx.beans.property.IntegerProperty;
import javafx.beans.property.SimpleIntegerProperty;
import javafx.beans.value.ChangeListener;
@@ -32,20 +38,19 @@ import javafx.scene.chart.XYChart;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
public class ComplexSampleLineChart extends LineChart implements Listener<ReusableComplexBuffer>
public class ComplexSampleLineChart extends LineChart implements Listener<ReusableComplexBuffer>, ComplexSampleListener
{
private final static Logger mLog = LoggerFactory.getLogger(ComplexSampleLineChart.class);
private ComplexCircularBuffer mComplexCircularBuffer;
private ComplexCircularBuffer mDemodulationCircularBuffer;
private ComplexGain mComplexGain = new ComplexGain(500.0f);
private ObservableList<XYChart.Data<Integer,Float>> mISamples = FXCollections.observableArrayList();
private ObservableList<XYChart.Data<Integer,Float>> mQSamples = FXCollections.observableArrayList();
private IntegerProperty mLengthProperty = new SimpleIntegerProperty(40);
public ComplexSampleLineChart(int length, int samplesPerSymbol)
public ComplexSampleLineChart(String label, int length, int samplesPerSymbol)
{
super(new NumberAxis("Differential-Demodulated Samples", 0, length, 10),
super(new NumberAxis(label, 0, length, 10),
new NumberAxis("Value", -1.0, 1.0, 0.25));
LineChart.Series<Integer,Float> iSampleSeries = new LineChart.Series<>("Inphase", mISamples);
@@ -96,24 +101,25 @@ public class ComplexSampleLineChart extends LineChart implements Listener<Reusab
{
float[] samples = complexBuffer.getSamples();
Complex sample = new Complex(0,0);
for(int x = 0; x < samples.length; x += 2)
{
sample.setValues(samples[x], samples[x + 1]);
// mComplexGain.apply(sample);
sample.normalize();
Complex previous = mDemodulationCircularBuffer.get(sample.copy());
sample.multiply(previous.conjugate());
mComplexCircularBuffer.put(sample.copy());
receive(samples[x], samples[x + 1]);
}
updateChart();
complexBuffer.decrementUserCount();
}
@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();

View File

@@ -1,18 +1,24 @@
/*******************************************************************************
* 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.
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
*/
package io.github.dsheirer.gui.instrument.chart;
import io.github.dsheirer.dsp.psk.SymbolDecisionData;
@@ -29,17 +35,17 @@ public class EyeDiagramChart extends LineChart implements Listener<SymbolDecisio
{
private final static Logger mLog = LoggerFactory.getLogger(EyeDiagramChart.class);
private ObservableList<Series<Double,Double>> mData = FXCollections.observableArrayList();
private ObservableList<Series<Double,Float>> mData = FXCollections.observableArrayList();
private int mSeriesCount;
private int mSeriesPointer;
private int mSeriesLength;
public EyeDiagramChart(int seriesCount, String legend)
{
super(new NumberAxis("Symbol Timing (" + legend + ")", 1.0, 10.0, 1.0),
new NumberAxis("Value", -1.25, 1.25, 0.25));
super(new NumberAxis("Sample Point = 3", -1.0, 7.0, 1.0),
new NumberAxis("Radians", -5.0, 5.0, 0.5));
mSeriesCount = seriesCount * 2;
mSeriesCount = seriesCount;
init();
}
@@ -48,15 +54,15 @@ public class EyeDiagramChart extends LineChart implements Listener<SymbolDecisio
for(int x = 0; x < mSeriesCount; x++)
{
ObservableList<Data<Double,Double>> series = FXCollections.observableArrayList();
mData.add(new Series<>(series));
mData.add(new Series(series));
}
setData(mData);
}
private ObservableList<Data<Double,Double>> getSeries(int series, int length)
private ObservableList<Data<Double,Float>> getSeries(int series, int length)
{
ObservableList<Data<Double,Double>> seriesData = mData.get(series).getData();
ObservableList<Data<Double,Float>> seriesData = mData.get(series).getData();
while(seriesData.size() > length)
{
@@ -65,7 +71,7 @@ public class EyeDiagramChart extends LineChart implements Listener<SymbolDecisio
while(seriesData.size() < length)
{
seriesData.add(new Data<Double,Double>(0.0,0.0));
seriesData.add(new Data<>(0.0,0.0f));
}
return seriesData;
@@ -80,42 +86,63 @@ public class EyeDiagramChart extends LineChart implements Listener<SymbolDecisio
}
}
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 && (Math.abs(corrected[x] - corrected[x - 1]) > Math.PI))
{
phaseRolloverIndex = x;
}
}
if(phaseRolloverIndex >= 0)
{
for(int x = 0; x < phaseRolloverIndex; x++)
{
if(corrected[x] > 0)
{
corrected[x] -= 2 * Math.PI;
}
else
{
corrected[x] += 2 * Math.PI;
}
}
}
return corrected;
}
@Override
public void receive(SymbolDecisionData symbolDecisionData)
{
Complex[] demodulated = symbolDecisionData.getDemodulated();
Complex[] samples = symbolDecisionData.getSamples();
int length = samples.length;
int length = demodulated.length;
checkChartLength(length);
ObservableList<Data<Double,Double>> iSeries = getSeries(mSeriesPointer++, length + 1);
ObservableList<Data<Double,Float>> iSeries = getSeries(mSeriesPointer++, length);
// checkChartLength(length);
if(mSeriesPointer >= mSeriesCount)
{
mSeriesPointer = 0;
}
ObservableList<Data<Double,Double>> qSeries = getSeries(mSeriesPointer++, length + 1);
float[] angles = conditionData(samples);
if(mSeriesPointer >= mSeriesCount)
for(int x = 0; x < samples.length; x++)
{
mSeriesPointer = 0;
}
for(int x = 0; x < length; x++)
{
demodulated[x].normalize();
Data<Double,Double> iDataPoint = iSeries.get(x);
iDataPoint.setXValue((double)x + 1 - symbolDecisionData.getSamplingPoint());
double iValue = demodulated[x].inphase();
iDataPoint.setYValue(iValue);
Data<Double,Double> qDataPoint = qSeries.get(x);
qDataPoint.setXValue((double)x + 1 - symbolDecisionData.getSamplingPoint());
double qValue = demodulated[x].quadrature();
qDataPoint.setYValue(qValue);
Data<Double,Float> iDataPoint = iSeries.get(x);
Complex sample = samples[x];
iDataPoint.setXValue((double)x - symbolDecisionData.getSamplingPoint());
iDataPoint.setYValue(angles[x]);
}
}
}

View File

@@ -0,0 +1,96 @@
/*
*
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
*
*/
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.buffer.ReusableComplexBuffer;
import io.github.dsheirer.sample.complex.Complex;
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<XYChartItem> implements Listener<ReusableComplexBuffer>
{
private static ObservableList<XYChartItem> 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(ReusableComplexBuffer buffer)
{
float[] samples = buffer.getSamples();
for(int x = 0; x < samples.length; x += 2)
{
mCircularBuffer.put(new Complex(samples[x], samples[x + 1]));
}
buffer.decrementUserCount();
Complex[] complexSamples = mCircularBuffer.getAll();
XYSeries<XYChartItem> series = getXYPane().getListOfSeries().get(0);
series.setStroke(Color.BLUE);
series.getItems().clear();
for(int x = 0; x < complexSamples.length; x++)
{
Complex sample = complexSamples[x];
series.getItems().add(new XYChartItem(sample.polarAngleDegrees(), sample.magnitude(), Color.BLUE));
}
refresh();
}
}

View File

@@ -1,22 +1,26 @@
/*******************************************************************************
* sdr-trunk
* Copyright (C) 2014-2018 Dennis Sheirer
/*
* ******************************************************************************
* sdrtrunk
* 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 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>
* *****************************************************************************
*/
package io.github.dsheirer.gui.instrument.decoder;
import io.github.dsheirer.module.decode.DecoderType;
import io.github.dsheirer.module.decode.p25.P25Decoder;
import io.github.dsheirer.module.decode.p25.phase1.P25P1Decoder;
import java.util.EnumSet;
@@ -24,6 +28,7 @@ public class DecoderPaneFactory
{
private static final EnumSet<DecoderType> SUPPORTED_DECODER_TYPES = EnumSet.of(
DecoderType.P25_PHASE1,
DecoderType.P25_PHASE2,
DecoderType.FLEETSYNC2,
DecoderType.LJ_1200,
DecoderType.LTR_NET,
@@ -51,7 +56,9 @@ public class DecoderPaneFactory
case TAIT_1200:
return new Tait1200Pane();
case P25_PHASE1:
throw new IllegalArgumentException("Use the getP25DecoderPane() method for P25 decoder type");
throw new IllegalArgumentException("Use the getP25P1DecoderPane() method for P25 decoder type");
case P25_PHASE2:
return new P25Phase2HDQPSKPane();
}
return getDefaultPane();
@@ -60,7 +67,7 @@ public class DecoderPaneFactory
/**
* Creates a decoder pane for the P25 decoder type
*/
public static AbstractDecoderPane getP25DecoderPane(P25Decoder.Modulation modulation)
public static AbstractDecoderPane getP25P1DecoderPane(P25P1Decoder.Modulation modulation)
{
switch(modulation)
{

View File

@@ -1,18 +1,24 @@
/*******************************************************************************
* 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.
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
*/
package io.github.dsheirer.gui.instrument.decoder;
import io.github.dsheirer.gui.instrument.chart.ComplexSampleLineChart;
@@ -22,7 +28,7 @@ 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.P25DecoderC4FMInstrumented;
import io.github.dsheirer.module.decode.p25.phase1.P25P1DecoderC4FMInstrumented;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableBufferBroadcaster;
import javafx.scene.layout.HBox;
@@ -43,7 +49,7 @@ public class P25Phase1C4FMPane extends ComplexDecoderPane
private DoubleLineChart mPLLFrequencyLineChart;
private DoubleLineChart mSamplesPerSymbolLineChart;
private ReusableBufferBroadcaster mFilteredBufferBroadcaster = new ReusableBufferBroadcaster();
private P25DecoderC4FMInstrumented mDecoder = new P25DecoderC4FMInstrumented();
private P25P1DecoderC4FMInstrumented mDecoder = new P25P1DecoderC4FMInstrumented();
public P25Phase1C4FMPane()
{
@@ -89,7 +95,7 @@ public class P25Phase1C4FMPane extends ComplexDecoderPane
getSampleLineChart().setSamplesPerSymbol((int) samplesPerSymbol);
}
private P25DecoderC4FMInstrumented getDecoder()
private P25P1DecoderC4FMInstrumented getDecoder()
{
return mDecoder;
}
@@ -146,7 +152,7 @@ public class P25Phase1C4FMPane extends ComplexDecoderPane
{
if(mSampleLineChart == null)
{
mSampleLineChart = new ComplexSampleLineChart(100, 10);
mSampleLineChart = new ComplexSampleLineChart("Raw Samples", 100, 10);
}
return mSampleLineChart;

View File

@@ -1,18 +1,24 @@
/*******************************************************************************
* 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.
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
* 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 <http://www.gnu.org/licenses/>
*
******************************************************************************/
*/
package io.github.dsheirer.gui.instrument.decoder;
import io.github.dsheirer.gui.instrument.chart.ComplexSampleLineChart;
@@ -23,7 +29,7 @@ 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.P25DecoderLSMInstrumented;
import io.github.dsheirer.module.decode.p25.phase1.P25P1DecoderLSMInstrumented;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableBufferBroadcaster;
import javafx.scene.layout.HBox;
@@ -44,7 +50,7 @@ public class P25Phase1LSMPane extends ComplexDecoderPane
private DoubleLineChart mPLLFrequencyLineChart;
private SamplesPerSymbolChart mSamplesPerSymbolLineChart;
private ReusableBufferBroadcaster mFilteredBufferBroadcaster = new ReusableBufferBroadcaster();
private P25DecoderLSMInstrumented mDecoder = new P25DecoderLSMInstrumented();
private P25P1DecoderLSMInstrumented mDecoder = new P25P1DecoderLSMInstrumented();
public P25Phase1LSMPane()
{
@@ -91,7 +97,7 @@ public class P25Phase1LSMPane extends ComplexDecoderPane
getSamplesPerSymbolLineChart().setSamplesPerSymbol(samplesPerSymbol);
}
private P25DecoderLSMInstrumented getDecoder()
private P25P1DecoderLSMInstrumented getDecoder()
{
return mDecoder;
}
@@ -148,7 +154,7 @@ public class P25Phase1LSMPane extends ComplexDecoderPane
{
if(mDifferentialDemodulatedSamplesChartBox == null)
{
mDifferentialDemodulatedSamplesChartBox = new ComplexSampleLineChart(100, 10);
mDifferentialDemodulatedSamplesChartBox = new ComplexSampleLineChart("Raw Samples", 100, 10);
}
return mDifferentialDemodulatedSamplesChartBox;

View File

@@ -0,0 +1,242 @@
/*
*
* * ******************************************************************************
* * 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 <http://www.gnu.org/licenses/>
* * *****************************************************************************
*
*
*/
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.Listener;
import io.github.dsheirer.sample.buffer.ReusableBufferBroadcaster;
import javafx.scene.layout.HBox;
import javafx.scene.layout.Priority;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
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 ReusableBufferBroadcaster mFilteredBufferBroadcaster = new ReusableBufferBroadcaster();
private P25P2DecoderHDQPSKInstrumented mDecoder = new P25P2DecoderHDQPSKInstrumented(new DecodeConfigP25Phase2());
public P25Phase2HDQPSKPane()
{
super(DecoderType.P25_PHASE2);
init();
}
private void init()
{
addListener(getDecoder());
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<IMessage>()
{
@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;
}
}