Improved LTR FSK decoder for LTR, LTR-Net and Passport decoders. Added IIR DC blocking filter and used improved slicer from the FSK decoder.

Added instrumentation to Passport decoder and updated some of the instrumentation components.
This commit is contained in:
dennis.sheirer
2014-05-01 23:24:51 +00:00
parent d7115f2886
commit da1db8a804
25 changed files with 803 additions and 496 deletions

View File

@@ -66,7 +66,8 @@ public enum DecoderType
{
return EnumSet.of( DecoderType.FLEETSYNC2,
DecoderType.MDC1200,
DecoderType.MPT1327 );
DecoderType.MPT1327,
DecoderType.PASSPORT );
}
/**

View File

@@ -24,8 +24,8 @@ import bits.MessageFramer;
import bits.SyncPattern;
import decode.Decoder;
import decode.DecoderType;
import decode.ltrstandard.LTRFSKDemodulator;
import dsp.filter.DCRemovalFilter2;
import dsp.fsk.LTRFSKDecoder;
import dsp.nbfm.FilteringNBFMDemodulator;
public class LTRNetDecoder extends Decoder
@@ -39,7 +39,7 @@ public class LTRNetDecoder extends Decoder
public static final int sLTR_STANDARD_MESSAGE_LENGTH = 40;
private FilteringNBFMDemodulator mDemodulator;
private DCRemovalFilter2 mDCRemovalFilter;
private LTRFSKDemodulator mLTRFSKDemodulator;
private LTRFSKDecoder mLTRFSKDecoder;
private MessageFramer mLTRMessageFramer;
private LTRNetMessageProcessor mLTRMessageProcessor;
@@ -75,7 +75,7 @@ public class LTRNetDecoder extends Decoder
mDCRemovalFilter.setListener( this.getFloatReceiver() );
}
mLTRFSKDemodulator = new LTRFSKDemodulator();
mLTRFSKDecoder = new LTRFSKDecoder();
/**
* The DC removal filter will impact performance of the LTRFSKDemod,
@@ -83,11 +83,11 @@ public class LTRNetDecoder extends Decoder
*/
if( mSourceSampleType == SampleType.COMPLEX )
{
mDemodulator.addListener( mLTRFSKDemodulator );
mDemodulator.addListener( mLTRFSKDecoder );
}
else
{
mDCRemovalFilter.setListener( mLTRFSKDemodulator );
mDCRemovalFilter.setListener( mLTRFSKDecoder );
}
if( direction == MessageDirection.OSW )
@@ -103,7 +103,7 @@ public class LTRNetDecoder extends Decoder
sLTR_STANDARD_MESSAGE_LENGTH );
}
mLTRFSKDemodulator.addListener( mLTRMessageFramer );
mLTRFSKDecoder.addListener( mLTRMessageFramer );
mLTRMessageProcessor = new LTRNetMessageProcessor( direction, aliasList );
mLTRMessageFramer.addMessageListener( mLTRMessageProcessor );

View File

@@ -1,132 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 decode.ltrstandard;
import sample.Broadcaster;
import sample.Listener;
import dsp.BooleanZeroCrossingDetector;
import dsp.FloatToBinarySlicer;
import dsp.filter.BooleanAveragingFilter;
import dsp.filter.Filters;
import dsp.filter.FloatFIRFilter;
import dsp.filter.FloatHalfBandFilter;
import dsp.filter.FloatHalfBandNoDecimateFilter;
import dsp.filter.SquaringFilter;
public class LTRFSKDemodulator implements Listener<Float>
{
FloatHalfBandFilter mHBFilter1;
FloatHalfBandFilter mHBFilter2;
FloatHalfBandFilter mHBFilter3;
FloatHalfBandFilter mHBFilter4;
FloatHalfBandFilter mHBFilter5;
FloatHalfBandNoDecimateFilter mHBFilter6;
FloatFIRFilter mDCBlocker;
SquaringFilter mSquaringFilter;
BooleanAveragingFilter mAveragingFilter;
BooleanZeroCrossingDetector mZeroCrossingDetector;
FloatToBinarySlicer mSlicer;
Broadcaster<Boolean> mBroadcaster = new Broadcaster<Boolean>();
//debug
// FloatWaveRecorder mRecorder;
/**
* Implements a Logic Trunked Radio sub-audible 300 baud FSK signaling
* decoder. Expects a 48k short-valued sample rate, which is decimated
* to a final 1.5k sample rate via five cascaded decimating half-band
* filters, and applies a sixth, non-decimating half-band filter to bring
* the overall bandwidth down to .75k. Each half band filter requires
* 8 multiply/accumulate (MAC) cycles per input sample, totaling 2560
* MAC filtering cycles per output bit, to get from 48k input to 300-baud
* bit stream output.
*
* Applies a balancer to the demodulated fsk waveform to normalize the
* values about the zero-axis and to offset fluctuations induced by the
* DC correction filter.
*
* Converts filtered, decimated samples to squared bit values and then
* applies a zero crossing detector to make a baud decision every 5 samples.
*
* Outputs the decoded bit stream.
*/
public LTRFSKDemodulator()
{
mHBFilter1 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter2 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter1.setListener( mHBFilter2 );
mHBFilter3 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter2.setListener( mHBFilter3 );
mHBFilter4 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter3.setListener( mHBFilter4 );
mHBFilter5 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter4.setListener( mHBFilter5 );
mHBFilter6 = new FloatHalfBandNoDecimateFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter5.setListener( mHBFilter6 );
// mDCBlocker = new FloatFIRFilter(
// Filters.FIRHP_LTR_DCBLOCK_750FS_50FC.getCoefficients(), 1.0f );
// mHBFilter6.setListener( mDCBlocker );
/**
* Set the slicer's long buffer to a sample length of 14 baud periods
* ( 5 * 14 )since 12 bauds should be the longest string of ones we'll
* encounter
*
* Set the short buffer to two baud periods (5 * 2)
*/
//Set the buffer to 5 samples per baud times 12 bauds. Set the sync
//lock period to 5 samples per baud times 31 bits (155 samples)
mSlicer = new FloatToBinarySlicer( 70, 5 );
mHBFilter6.setListener( mSlicer );
// mDCBlocker.setListener( mSlicer );
mAveragingFilter = new BooleanAveragingFilter( 5 );
mSlicer.setListener( mAveragingFilter );
mZeroCrossingDetector = new BooleanZeroCrossingDetector( 5 );
mAveragingFilter.setListener( mZeroCrossingDetector );
}
@Override
public void receive( Float sample )
{
mHBFilter1.receive( sample );
}
public void addListener( Listener<Boolean> listener )
{
mZeroCrossingDetector.setListener( listener );
}
public void removeListener( Listener<Boolean> listener )
{
mZeroCrossingDetector.removeListener( listener );
}
}

View File

@@ -1,122 +0,0 @@
/*******************************************************************************
* SDR Trunk
* Copyright (C) 2014 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 decode.ltrstandard;
import sample.Listener;
import dsp.BooleanZeroCrossingDetector;
import dsp.FloatToBinarySlicerLTR;
import dsp.SyncDetectListener;
import dsp.filter.BooleanAveragingFilter;
import dsp.filter.Filters;
import dsp.filter.FloatHalfBandFilter;
import dsp.filter.FloatHalfBandNoDecimateFilter;
import dsp.filter.SquaringFilter;
public class LTRFSKDemodulator2 implements Listener<Float>, SyncDetectListener
{
FloatHalfBandFilter mHBFilter1;
FloatHalfBandFilter mHBFilter2;
FloatHalfBandFilter mHBFilter3;
FloatHalfBandFilter mHBFilter4;
FloatHalfBandFilter mHBFilter5;
FloatHalfBandNoDecimateFilter mHBFilter6;
SquaringFilter mSquaringFilter;
BooleanAveragingFilter mAveragingFilter;
BooleanZeroCrossingDetector mZeroCrossingDetector;
FloatToBinarySlicerLTR mSlicer;
/**
* Implements a Logic Trunked Radio sub-audible 300 baud FSK signaling
* decoder. Expects a 48k short-valued sample rate, which is decimated
* to a final 1.5k sample rate via five cascaded decimating half-band
* filters, and applies a sixth, non-decimating half-band filter to bring
* the overall bandwidth down to .75k. Each half band filter requires
* 8 multiply/accumulate (MAC) cycles per input sample, totaling 2560
* MAC filtering cycles per output bit, to get from 48k input to 300-baud
* bit stream output.
*
* Applies a balancer to the demodulated fsk waveform to normalize the
* values about the zero-axis and to offset fluctuations induced by the
* DC correction filter.
*
* Converts filtered, decimated samples to squared bit values and then
* applies a zero crossing detector to make a baud decision every 5 samples.
*
* Outputs the decoded bit stream.
*/
public LTRFSKDemodulator2( int syncLength, int messageLength )
{
mHBFilter1 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter2 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter1.setListener( mHBFilter2 );
mHBFilter3 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter2.setListener( mHBFilter3 );
mHBFilter4 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter3.setListener( mHBFilter4 );
mHBFilter5 = new FloatHalfBandFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter4.setListener( mHBFilter5 );
mHBFilter6 = new FloatHalfBandNoDecimateFilter(
Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO, 1.0002 );
mHBFilter5.setListener( mHBFilter6 );
mSlicer = new FloatToBinarySlicerLTR( syncLength, messageLength, 5 );
mHBFilter6.setListener( mSlicer );
mAveragingFilter = new BooleanAveragingFilter( 5 );
mSlicer.setListener( mAveragingFilter );
mZeroCrossingDetector = new BooleanZeroCrossingDetector( 5 );
mAveragingFilter.setListener( mZeroCrossingDetector );
}
@Override
public void receive( Float sample )
{
mHBFilter1.receive( sample );
}
public void setListener( Listener<Boolean> listener )
{
mZeroCrossingDetector.setListener( listener );
}
public void removeListener( Listener<Boolean> listener )
{
mZeroCrossingDetector.removeListener( listener );
}
/**
* Pass the sync detection down to the slicer
*/
@Override
public void syncDetected()
{
mSlicer.syncDetected();
}
}

View File

@@ -25,6 +25,7 @@ import bits.SyncPattern;
import decode.Decoder;
import decode.DecoderType;
import dsp.filter.DCRemovalFilter2;
import dsp.fsk.LTRFSKDecoder;
import dsp.nbfm.FilteringNBFMDemodulator;
public class LTRStandardDecoder extends Decoder
@@ -38,7 +39,7 @@ public class LTRStandardDecoder extends Decoder
public static final int sLTR_STANDARD_MESSAGE_LENGTH = 40;
private FilteringNBFMDemodulator mDemodulator;
private DCRemovalFilter2 mDCRemovalFilter;
private LTRFSKDemodulator mLTRFSKDemodulator;
private LTRFSKDecoder mLTRFSKDecoder;
private MessageFramer mLTRMessageFramer;
private LTRStandardMessageProcessor mLTRMessageProcessor;
@@ -74,7 +75,7 @@ public class LTRStandardDecoder extends Decoder
mDCRemovalFilter.setListener( this.getFloatReceiver() );
}
mLTRFSKDemodulator = new LTRFSKDemodulator();
mLTRFSKDecoder = new LTRFSKDecoder();
/**
* The DC removal filter will impact performance of the LTRFSKDemod,
@@ -82,11 +83,11 @@ public class LTRStandardDecoder extends Decoder
*/
if( mSourceSampleType == SampleType.COMPLEX )
{
mDemodulator.addListener( mLTRFSKDemodulator );
mDemodulator.addListener( mLTRFSKDecoder );
}
else
{
mDCRemovalFilter.setListener( mLTRFSKDemodulator );
mDCRemovalFilter.setListener( mLTRFSKDecoder );
}
if( direction == MessageDirection.OSW )
@@ -102,7 +103,7 @@ public class LTRStandardDecoder extends Decoder
sLTR_STANDARD_MESSAGE_LENGTH );
}
mLTRFSKDemodulator.addListener( mLTRMessageFramer );
mLTRFSKDecoder.addListener( mLTRMessageFramer );
mLTRMessageProcessor = new LTRStandardMessageProcessor( direction, aliasList );
mLTRMessageFramer.addMessageListener( mLTRMessageProcessor );

View File

@@ -17,17 +17,23 @@
******************************************************************************/
package decode.passport;
import instrument.Instrumentable;
import instrument.tap.Tap;
import java.util.ArrayList;
import java.util.List;
import source.Source.SampleType;
import alias.AliasList;
import bits.MessageFramer;
import bits.SyncPattern;
import decode.Decoder;
import decode.DecoderType;
import decode.ltrstandard.LTRFSKDemodulator;
import dsp.filter.DCRemovalFilter2;
import dsp.fsk.LTRFSKDecoder;
import dsp.nbfm.FilteringNBFMDemodulator;
public class PassportDecoder extends Decoder
public class PassportDecoder extends Decoder implements Instrumentable
{
/**
* This value determines how quickly the DC remove filter responds to
@@ -39,9 +45,11 @@ public class PassportDecoder extends Decoder
public static final int sPASSPORT_SYNC_LENGTH = 9;
private FilteringNBFMDemodulator mNBFMDemodulator;
private DCRemovalFilter2 mDCRemovalFilter;
private LTRFSKDemodulator mPassportFSKDemodulator;
private LTRFSKDecoder mPassportFSKDecoder;
private MessageFramer mPassportMessageFramer;
private PassportMessageProcessor mPassportMessageProcessor;
private List<Tap> mAvailableTaps;
public PassportDecoder( SampleType sampleType, AliasList aliasList )
{
@@ -72,8 +80,8 @@ public class PassportDecoder extends Decoder
mDCRemovalFilter.setListener( this.getFloatReceiver() );
}
mPassportFSKDemodulator =
new LTRFSKDemodulator();
mPassportFSKDecoder =
new LTRFSKDecoder();
/**
* The DC removal filter will impact performance of the LTRFSKDemod,
@@ -81,11 +89,11 @@ public class PassportDecoder extends Decoder
*/
if( mSourceSampleType == SampleType.COMPLEX )
{
mNBFMDemodulator.addListener( mPassportFSKDemodulator );
mNBFMDemodulator.addListener( mPassportFSKDecoder );
}
else
{
addFloatListener( mPassportFSKDemodulator );
addFloatListener( mPassportFSKDecoder );
}
@@ -93,7 +101,7 @@ public class PassportDecoder extends Decoder
new MessageFramer( SyncPattern.PASSPORT.getPattern(),
sPASSPORT_MESSAGE_LENGTH );
mPassportFSKDemodulator.addListener( mPassportMessageFramer );
mPassportFSKDecoder.addListener( mPassportMessageFramer );
mPassportMessageProcessor = new PassportMessageProcessor( aliasList );
mPassportMessageFramer.addMessageListener( mPassportMessageProcessor );
@@ -105,4 +113,29 @@ public class PassportDecoder extends Decoder
{
return DecoderType.PASSPORT;
}
@Override
public List<Tap> getTaps()
{
if( mAvailableTaps == null )
{
mAvailableTaps = new ArrayList<Tap>();
mAvailableTaps.addAll( mPassportFSKDecoder.getTaps() );
}
return mAvailableTaps;
}
@Override
public void addTap( Tap tap )
{
mPassportFSKDecoder.addTap( tap );
}
@Override
public void removeTap( Tap tap )
{
mPassportFSKDecoder.removeTap( tap );
}
}

View File

@@ -175,8 +175,13 @@ public class PassportMessage extends Message
public Alias getTalkgroupIDAlias()
{
int tg = getTalkgroupID();
return mAliasList.getTalkgroupAlias( String.valueOf( tg ) );
if( mAliasList != null )
{
return mAliasList.getTalkgroupAlias( String.valueOf( tg ) );
}
return null;
}
public int getLCN()
@@ -262,7 +267,7 @@ public class PassportMessage extends Message
{
String min = getMobileID();
if( min != null )
if( mAliasList != null && min != null )
{
return mAliasList.getMobileIDNumberAlias( min );
}