mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
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:
@@ -66,7 +66,8 @@ public enum DecoderType
|
||||
{
|
||||
return EnumSet.of( DecoderType.FLEETSYNC2,
|
||||
DecoderType.MDC1200,
|
||||
DecoderType.MPT1327 );
|
||||
DecoderType.MPT1327,
|
||||
DecoderType.PASSPORT );
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
@@ -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();
|
||||
}
|
||||
}
|
||||
@@ -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 );
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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 );
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user