P25 LSM decoder work in progress. Adds a CQPSK decoder based on Max's (KA1RBI) scope.py and gardner loop.

The CQPSK decoder is starting to take shape, but needs more tweaking and testing.  It's not keeping a good lock on strong P25 signals.  I have to add some more features to the intrumentation package to allow me to visualize the internals of the CQPSK decoder so that I can get a better sense of what needs fine tuning.

The CQPSK decoder may work for anyone that wants to sync the repo and run the build script.
This commit is contained in:
dennis.sheirer
2015-02-10 00:42:08 +00:00
parent 9310fb0daf
commit a65e821e85
43 changed files with 1996 additions and 413 deletions

View File

@@ -20,7 +20,6 @@ package controller;
import java.awt.BorderLayout;
import javax.swing.BorderFactory;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTree;

View File

@@ -20,6 +20,7 @@ package controller;
import javax.swing.JPanel;
import net.miginfocom.swing.MigLayout;
import controller.channel.ChannelValidationException;
public abstract class Editor extends JPanel
{
@@ -33,4 +34,18 @@ public abstract class Editor extends JPanel
public abstract void save();
public abstract void reset();
/**
* Override this method to allow the editor to inspect the argument for
* valid configuration
*
* @param editor - any editor
*
* @throws ChannelValidationException if the configuration is not compatible
* with this editor's configuration. Supplies a validation text value for
* display to the user
*/
public void validate( Editor editor ) throws ChannelValidationException
{
}
}

View File

@@ -30,11 +30,16 @@ import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JTextField;
import javax.swing.tree.DefaultTreeModel;
import javax.swing.tree.TreePath;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import record.RecordComponentEditor;
import source.SourceComponentEditor;
import alias.AliasList;
@@ -48,7 +53,9 @@ import eventlog.EventLogComponentEditor;
public class ChannelEditor extends Editor implements ActionListener
{
private static final long serialVersionUID = 1L;
private final static Logger mLog = LoggerFactory.getLogger( ChannelEditor.class );
private static final long serialVersionUID = 1L;
private DefaultTreeModel mTreeModel;
private ChannelNode mChannelNode;
@@ -171,32 +178,51 @@ public class ChannelEditor extends Editor implements ActionListener
@Override
public void save()
{
boolean expanded = mChannelNode.getModel().getTree()
.isExpanded( new TreePath( mChannelNode ) );
mSourceEditor.save();
mDecodeEditor.save();
mAuxDecodeEditor.save();
mEventLogEditor.save();
mRecordEditor.save();
mChannelNode.getChannel().setName( mChannelName.getText(), false );
mChannelNode.getChannel().setEnabled( mChannelEnabled.isSelected(), false );
AliasList selected = mComboAliasLists.getItemAt(
mComboAliasLists.getSelectedIndex() );
if( selected != null )
try
{
mChannelNode.getChannel().setAliasListName( selected.getName(), false );
/**
* Validate the source configuration against the other component
* configuration editors
*/
validate( mSourceEditor.getSourceEditor() );
boolean expanded = mChannelNode.getModel().getTree()
.isExpanded( new TreePath( mChannelNode ) );
mSourceEditor.save();
mDecodeEditor.save();
mAuxDecodeEditor.save();
mEventLogEditor.save();
mRecordEditor.save();
mChannelNode.getChannel().setName( mChannelName.getText(), false );
mChannelNode.getChannel().setEnabled( mChannelEnabled.isSelected(), false );
AliasList selected = mComboAliasLists.getItemAt(
mComboAliasLists.getSelectedIndex() );
if( selected != null )
{
mChannelNode.getChannel().setAliasListName( selected.getName(), false );
}
mChannelNode.save();
mChannelNode.show();
if( expanded )
{
mChannelNode.getModel().getTree().expandPath( new TreePath( mChannelNode ) );
}
}
mChannelNode.save();
mChannelNode.show();
if( expanded )
catch ( ChannelValidationException validationException )
{
mChannelNode.getModel().getTree().expandPath( new TreePath( mChannelNode ) );
/* ChannelValidationException can be thrown by any of the component
* editors. Show the validation error text in a popup menu to the
* user */
JOptionPane.showMessageDialog( ChannelEditor.this,
validationException.getMessage(),
"Channel Configuration Error",
JOptionPane.ERROR_MESSAGE );
}
}
@@ -232,4 +258,17 @@ public class ChannelEditor extends Editor implements ActionListener
mEventLogEditor.reset();
mRecordEditor.reset();
}
/**
* Validate the specified editor against each of the component editors
*/
@Override
public void validate( Editor editor ) throws ChannelValidationException
{
mSourceEditor.validate( editor );
mDecodeEditor.validate( editor );
mAuxDecodeEditor.validate( editor );
mEventLogEditor.validate( editor );
mRecordEditor.validate( editor );
}
}

View File

@@ -0,0 +1,11 @@
package controller.channel;
public class ChannelValidationException extends Exception
{
private static final long serialVersionUID = 1L;
public ChannelValidationException( String validationMessage )
{
super( validationMessage );
}
}