diff --git a/src/main/java/io/github/dsheirer/bits/IBinarySymbolProcessor.java b/src/main/java/io/github/dsheirer/bits/IBinarySymbolProcessor.java
new file mode 100644
index 00000000..a46185ad
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/bits/IBinarySymbolProcessor.java
@@ -0,0 +1,21 @@
+/*******************************************************************************
+ * 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.bits;
+
+public interface IBinarySymbolProcessor
+{
+ void receive(boolean symbol);
+}
diff --git a/src/main/java/io/github/dsheirer/bits/MessageFramer.java b/src/main/java/io/github/dsheirer/bits/MessageFramer.java
index 3a3acc64..27bdcabe 100644
--- a/src/main/java/io/github/dsheirer/bits/MessageFramer.java
+++ b/src/main/java/io/github/dsheirer/bits/MessageFramer.java
@@ -32,7 +32,7 @@ import java.util.List;
* Will extract multiple messages simultaneously, for each sync pattern that is
* encountered within the bitset bit stream.
*/
-public class MessageFramer implements Listener, SyncDetectProvider
+public class MessageFramer implements IBinarySymbolProcessor, Listener, SyncDetectProvider
{
private boolean[] mSyncPattern;
private int mMessageLength;
diff --git a/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200Decoder.java b/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200Decoder.java
index fd022a49..ca72ac66 100644
--- a/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200Decoder.java
+++ b/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200Decoder.java
@@ -15,7 +15,7 @@
******************************************************************************/
package io.github.dsheirer.dsp.afsk;
-import io.github.dsheirer.bits.MessageFramer;
+import io.github.dsheirer.bits.IBinarySymbolProcessor;
import io.github.dsheirer.buffer.FloatAveragingBuffer;
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
@@ -96,7 +96,7 @@ public class AFSK1200Decoder implements Listener
protected AFSKSampleBuffer mSampleBuffer;
protected AFSKTimingErrorDetector mTimingErrorDetector = new AFSKTimingErrorDetector(SAMPLES_PER_SYMBOL);
private RealFIRFilter2 mBandPassFilter = new RealFIRFilter2(sBandPassFilterCoefficients);
- protected MessageFramer mMessageFramer;
+ protected IBinarySymbolProcessor mBinarySymbolProcessor;
private boolean mSampleDecision;
//Resample to an integral of the baud rate 1200 baud * 6 samples per symbol = 7200.0 Hertz
@@ -155,20 +155,20 @@ public class AFSK1200Decoder implements Listener
protected void dispatch(boolean symbol)
{
- if(mMessageFramer != null)
+ if(mBinarySymbolProcessor != null)
{
- mMessageFramer.receive(mNormalOutput ? symbol : !symbol);
+ mBinarySymbolProcessor.receive(mNormalOutput ? symbol : !symbol);
}
}
/**
* Registers a listener to receive decoded LTR symbols.
*
- * @param messageFramer to receive symbols.
+ * @param binarySymbolProcessor to receive symbols.
*/
- public void setMessageFramer(MessageFramer messageFramer)
+ public void setSymbolProcessor(IBinarySymbolProcessor binarySymbolProcessor)
{
- mMessageFramer = messageFramer;
+ mBinarySymbolProcessor = binarySymbolProcessor;
}
/**
@@ -176,7 +176,7 @@ public class AFSK1200Decoder implements Listener
*/
public void removeListener()
{
- mMessageFramer = null;
+ mBinarySymbolProcessor = null;
}
diff --git a/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200DecoderInstrumented.java b/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200DecoderInstrumented.java
index 5aef1105..dd0e444f 100644
--- a/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200DecoderInstrumented.java
+++ b/src/main/java/io/github/dsheirer/dsp/afsk/AFSK1200DecoderInstrumented.java
@@ -40,11 +40,7 @@ public class AFSK1200DecoderInstrumented extends AFSK1200Decoder
protected void dispatch(boolean symbol)
{
- if(mMessageFramer != null)
- {
- mMessageFramer.receive(mNormalOutput ? symbol : !symbol);
- }
-
+ super.dispatch(symbol);
mSymbolBroadcaster.broadcast(symbol);
}
diff --git a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java
index 5a3a3308..f0cfe14e 100644
--- a/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java
+++ b/src/main/java/io/github/dsheirer/module/decode/DecoderFactory.java
@@ -64,10 +64,10 @@ import io.github.dsheirer.module.decode.mdc1200.MDCDecoderState;
import io.github.dsheirer.module.decode.mdc1200.MDCMessageFilter;
import io.github.dsheirer.module.decode.mpt1327.DecodeConfigMPT1327;
import io.github.dsheirer.module.decode.mpt1327.MPT1327Decoder;
-import io.github.dsheirer.module.decode.mpt1327.MPT1327Decoder.Sync;
import io.github.dsheirer.module.decode.mpt1327.MPT1327DecoderEditor;
import io.github.dsheirer.module.decode.mpt1327.MPT1327DecoderState;
import io.github.dsheirer.module.decode.mpt1327.MPT1327MessageFilter;
+import io.github.dsheirer.module.decode.mpt1327.Sync;
import io.github.dsheirer.module.decode.nbfm.DecodeConfigNBFM;
import io.github.dsheirer.module.decode.nbfm.NBFMDecoder;
import io.github.dsheirer.module.decode.nbfm.NBFMDecoderEditor;
@@ -175,15 +175,12 @@ public class DecoderFactory
break;
case MPT1327:
DecodeConfigMPT1327 mptConfig = (DecodeConfigMPT1327) decodeConfig;
-
ChannelMap channelMap = channelMapModel.getChannelMap(mptConfig.getChannelMapName());
-
Sync sync = mptConfig.getSync();
-
modules.add(new MPT1327Decoder(aliasList, sync));
-
-
modules.add(new MPT1327DecoderState(aliasList, channelMap, channelType, mptConfig.getCallTimeout() * 1000));
+ modules.add(new FMDemodulatorModule(CHANNEL_BANDWIDTH, DEMODULATED_AUDIO_SAMPLE_RATE));
+ modules.add(new AudioModule(metadata));
if(channelType == ChannelType.STANDARD)
{
@@ -191,9 +188,6 @@ public class DecoderFactory
channel.getRecordConfiguration(), channel.getSystem(), channel.getSite(),
(aliasList != null ? aliasList.getName() : null), mptConfig.getTrafficChannelPoolSize()));
}
-
- modules.add(new FMDemodulatorModule(CHANNEL_BANDWIDTH, DEMODULATED_AUDIO_SAMPLE_RATE));
- modules.add(new AudioModule(metadata));
break;
case PASSPORT:
modules.add(new PassportDecoder(decodeConfig, aliasList));
diff --git a/src/main/java/io/github/dsheirer/module/decode/fleetsync2/Fleetsync2Decoder.java b/src/main/java/io/github/dsheirer/module/decode/fleetsync2/Fleetsync2Decoder.java
index 5196376f..dc3f52af 100644
--- a/src/main/java/io/github/dsheirer/module/decode/fleetsync2/Fleetsync2Decoder.java
+++ b/src/main/java/io/github/dsheirer/module/decode/fleetsync2/Fleetsync2Decoder.java
@@ -34,21 +34,40 @@ public class Fleetsync2Decoder extends AbstractAFSKDecoder
private MessageFramer mMessageFramer;
private Fleetsync2MessageProcessor mMessageProcessor;
+ /**
+ * Constructs a decoder for Fleetsync II protocol
+ * @param afsk1200Decoder to use for decoding the symbols
+ * @param aliasList to assign aliases to decoded values
+ */
public Fleetsync2Decoder(AFSK1200Decoder afsk1200Decoder, AliasList aliasList)
{
super(afsk1200Decoder);
+ init(aliasList);
+ }
+
+ /**
+ * Constructs a decoder for Fleetsync II protocol
+ * @param aliasList to assign aliases to decoded values
+ */
+ public Fleetsync2Decoder(AliasList aliasList)
+ {
+ super(AFSK1200Decoder.Output.NORMAL);
+ init(aliasList);
+ }
+
+ /**
+ * Initializes the decoding chain.
+ * @param aliasList to assign to the message processor
+ */
+ private void init(AliasList aliasList)
+ {
mMessageFramer = new MessageFramer(SyncPattern.FLEETSYNC2.getPattern(), MESSAGE_LENGTH);
- getDecoder().setMessageFramer(mMessageFramer);
+ getDecoder().setSymbolProcessor(mMessageFramer);
mMessageProcessor = new Fleetsync2MessageProcessor(aliasList);
mMessageFramer.addMessageListener(mMessageProcessor);
mMessageProcessor.setMessageListener(getMessageListener());
}
- public Fleetsync2Decoder(AliasList aliasList)
- {
- this(new AFSK1200Decoder(AFSK1200Decoder.Output.NORMAL), aliasList);
- }
-
@Override
public DecoderType getDecoderType()
{
diff --git a/src/main/java/io/github/dsheirer/module/decode/mpt1327/DecodeConfigMPT1327.java b/src/main/java/io/github/dsheirer/module/decode/mpt1327/DecodeConfigMPT1327.java
index 172ee2e7..40b5a3c6 100644
--- a/src/main/java/io/github/dsheirer/module/decode/mpt1327/DecodeConfigMPT1327.java
+++ b/src/main/java/io/github/dsheirer/module/decode/mpt1327/DecodeConfigMPT1327.java
@@ -20,7 +20,6 @@ package io.github.dsheirer.module.decode.mpt1327;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.module.decode.DecoderType;
import io.github.dsheirer.module.decode.config.DecodeConfiguration;
-import io.github.dsheirer.module.decode.mpt1327.MPT1327Decoder.Sync;
public class DecodeConfigMPT1327 extends DecodeConfiguration
{
diff --git a/src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327Decoder.java b/src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327Decoder.java
index 6dc1fc84..eef7ba35 100644
--- a/src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327Decoder.java
+++ b/src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327Decoder.java
@@ -1,161 +1,65 @@
/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2017 Dennis Sheirer
+ * 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 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.module.decode.mpt1327;
import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.bits.IBinarySymbolProcessor;
import io.github.dsheirer.bits.MessageFramer;
-import io.github.dsheirer.bits.SyncPattern;
-import io.github.dsheirer.dsp.filter.FilterFactory;
-import io.github.dsheirer.dsp.filter.Filters;
-import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
-import io.github.dsheirer.dsp.filter.fir.real.RealFIRFilter_RB_RB;
-import io.github.dsheirer.dsp.filter.halfband.real.HalfBandFilter_RB_RB;
-import io.github.dsheirer.dsp.fsk.FSK2Decoder;
-import io.github.dsheirer.instrument.Instrumentable;
-import io.github.dsheirer.instrument.tap.Tap;
-import io.github.dsheirer.instrument.tap.TapGroup;
-import io.github.dsheirer.instrument.tap.stream.BinaryTap;
-import io.github.dsheirer.instrument.tap.stream.FloatBufferTap;
-import io.github.dsheirer.instrument.tap.stream.FloatTap;
-import io.github.dsheirer.module.decode.Decoder;
+import io.github.dsheirer.dsp.afsk.AFSK1200Decoder;
import io.github.dsheirer.module.decode.DecoderType;
-import io.github.dsheirer.sample.Broadcaster;
-import io.github.dsheirer.sample.Listener;
-import io.github.dsheirer.sample.real.IFilteredRealBufferListener;
-import io.github.dsheirer.sample.real.RealBuffer;
+import io.github.dsheirer.module.decode.afsk.AbstractAFSKDecoder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.ArrayList;
-import java.util.List;
-
-/**
- * MPT1327 Decoder - 1200 baud 2FSK decoder that can process 48k sample rate
- * complex or floating point samples and output fully framed MPT1327 control and
- * traffic messages.
- */
-public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListener, Instrumentable
+public class MPT1327Decoder extends AbstractAFSKDecoder implements IBinarySymbolProcessor
{
private final static Logger mLog = LoggerFactory.getLogger(MPT1327Decoder.class);
- private static final FIRFilterSpecification HIGH_PASS_SPECIFICATION = FIRFilterSpecification.highPassBuilder()
- .sampleRate( 24000 )
- .stopBandCutoff( 800 )
- .stopBandAmplitude( 0.0 )
- .stopBandRipple( 0.03 )
- .passBandStart( 1000 )
- .passBandAmplitude( 1.0 )
- .passBandRipple( 0.08 )
- .build();
-
- private static float[] HIGHPASS_FILTER;
-
- static
- {
- try
- {
- HIGHPASS_FILTER = FilterFactory.getTaps(HIGH_PASS_SPECIFICATION);
- }
- catch(Exception e)
- {
- mLog.error("Couldn't design MPT1327 highpass filter");
- }
- }
-
- /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
- private static final int sDECIMATED_SAMPLE_RATE = 24000;
-
- /* Baud or Symbol Rate */
- private static final int sSYMBOL_RATE = 1200;
-
/* Message length -- longest possible message is:
* 4xREVS + 16xSYNC + 64xADD1 + 64xDCW1 + 64xDCW2 + 64xDCW3 + 64xDCW4 */
- private static final int sMESSAGE_LENGTH = 350;
+ private static final int MESSAGE_LENGTH = 350;
- /* Instrumentation Taps */
- private static final String INSTRUMENT_HB1_FILTER_TO_HIGH_PASS =
- "Tap Point: Half-band Decimation Filter > < Low Pass Filter";
- private static final String INSTRUMENT_HIGH_PASS_TO_DECODER =
- "Tap Point: Low Pass Filter > < Decoder";
- private static final String INSTRUMENT_DECODER_TO_FRAMER =
- "Tap Point: Decoder > < Sync Detect/Message Framer";
- private List mAvailableTaps;
-
- private HalfBandFilter_RB_RB mDecimationFilter;
- private RealFIRFilter_RB_RB mHighPassFilter;
- private FSK2Decoder mFSKDecoder;
- private Broadcaster mSymbolBroadcaster;
private MessageFramer mControlMessageFramer;
private MessageFramer mTrafficMessageFramer;
private MPT1327MessageProcessor mMessageProcessor;
public MPT1327Decoder(AliasList aliasList, Sync sync)
{
- /**
- * Normal: 2FSK Decoder with inverted output
- * French: 2FSK Decoder with normal output
- */
- if(sync == Sync.NORMAL)
- {
- mFSKDecoder = new FSK2Decoder(24000, 1200, FSK2Decoder.Output.INVERTED);
- }
- else if(sync == Sync.FRENCH)
- {
- mFSKDecoder = new FSK2Decoder(24000, 1200, FSK2Decoder.Output.NORMAL);
- }
- else
- {
- throw new IllegalArgumentException("MPT1327 Decoder - unrecognized Sync type");
- }
+ super((sync == Sync.NORMAL ? AFSK1200Decoder.Output.NORMAL : AFSK1200Decoder.Output.INVERTED));
- /* Decimation filter - 48000 / 2 = 24000 output */
- mDecimationFilter = new HalfBandFilter_RB_RB(Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO.getCoefficients(), 1.0002f, true);
+ getDecoder().setSymbolProcessor(this);
- //High-pass filter the audio to remove any DC component or CTCSS tones. The audio has already been low-pass
- //filtered by the AudioDemodulation filter cutoff of 3400 Hz.
- mHighPassFilter = new RealFIRFilter_RB_RB(HIGHPASS_FILTER, 1.0f);
- mDecimationFilter.setListener(mHighPassFilter);
+ //Message framer for control channel messages
+ mControlMessageFramer = new MessageFramer(sync.getControlSyncPattern().getPattern(), MESSAGE_LENGTH);
- mHighPassFilter.setListener(mFSKDecoder);
+ //Message framer for traffic channel massages
+ mTrafficMessageFramer = new MessageFramer(sync.getTrafficSyncPattern().getPattern(), MESSAGE_LENGTH);
- mSymbolBroadcaster = new Broadcaster();
- mFSKDecoder.setListener(mSymbolBroadcaster);
-
- /* Message framer for control channel messages */
- mControlMessageFramer = new MessageFramer(sync.getControlSyncPattern().getPattern(), sMESSAGE_LENGTH);
- mSymbolBroadcaster.addListener(mControlMessageFramer);
-
- /* Message framer for traffic channel massages */
- mTrafficMessageFramer = new MessageFramer(sync.getTrafficSyncPattern().getPattern(), sMESSAGE_LENGTH);
- mSymbolBroadcaster.addListener(mTrafficMessageFramer);
-
- /* Fully decoded and framed messages processor */
+ //Fully decoded and framed messages processor
mMessageProcessor = new MPT1327MessageProcessor(aliasList);
mMessageProcessor.setMessageListener(getMessageListener());
+
mControlMessageFramer.addMessageListener(mMessageProcessor);
mTrafficMessageFramer.addMessageListener(mMessageProcessor);
}
- @Override
- public Listener getFilteredRealBufferListener()
+ public void receive(boolean symbol)
{
- return mDecimationFilter;
+ mControlMessageFramer.receive(symbol);
+ mTrafficMessageFramer.receive(symbol);
}
@Override
@@ -164,6 +68,13 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
return DecoderType.MPT1327;
}
+ @Override
+ public void reset()
+ {
+ mControlMessageFramer.reset();
+ mTrafficMessageFramer.reset();
+ }
+
/**
* Cleanup method
*/
@@ -171,128 +82,9 @@ public class MPT1327Decoder extends Decoder implements IFilteredRealBufferListen
{
super.dispose();
- mSymbolBroadcaster.dispose();
-
- mControlMessageFramer.dispose();
-
- mFSKDecoder.dispose();
-
- mDecimationFilter.dispose();
-
mMessageProcessor.dispose();
-
+ mControlMessageFramer.dispose();
mTrafficMessageFramer.dispose();
}
- /* Instrumentation Taps */
- @Override
- public List getTapGroups()
- {
- if(mAvailableTaps == null)
- {
- mAvailableTaps = new ArrayList();
-
- TapGroup group = new TapGroup("MPT-1327 Decoder");
-
- group.add(new FloatTap(INSTRUMENT_HB1_FILTER_TO_HIGH_PASS, 0, 0.5f));
- group.add(new FloatTap(INSTRUMENT_HIGH_PASS_TO_DECODER, 0, 0.5f));
- group.add(new BinaryTap(INSTRUMENT_DECODER_TO_FRAMER, 0, 0.025f));
-
- mAvailableTaps.add(group);
-
- /* Add the taps from the FSK decoder */
- mAvailableTaps.addAll(mFSKDecoder.getTapGroups());
- }
-
- return mAvailableTaps;
- }
-
- @Override
- public void registerTap(Tap tap)
- {
- /* Send request to decoder */
- mFSKDecoder.registerTap(tap);
-
- switch(tap.getName())
- {
- case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
- FloatBufferTap hb1Tap = (FloatBufferTap) tap;
- mDecimationFilter.setListener(hb1Tap);
- hb1Tap.setListener(mHighPassFilter);
- break;
- case INSTRUMENT_HIGH_PASS_TO_DECODER:
- FloatBufferTap lowTap = (FloatBufferTap) tap;
- mHighPassFilter.setListener(lowTap);
- lowTap.setListener(mFSKDecoder);
- break;
- case INSTRUMENT_DECODER_TO_FRAMER:
- BinaryTap decoderTap = (BinaryTap) tap;
- mFSKDecoder.setListener(decoderTap);
- decoderTap.setListener(mSymbolBroadcaster);
- break;
- }
- }
-
- @Override
- public void unregisterTap(Tap tap)
- {
- mFSKDecoder.unregisterTap(tap);
-
- switch(tap.getName())
- {
- case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
- mDecimationFilter.setListener(mHighPassFilter);
- break;
- case INSTRUMENT_HIGH_PASS_TO_DECODER:
- mHighPassFilter.setListener(mFSKDecoder);
- break;
- case INSTRUMENT_DECODER_TO_FRAMER:
- mFSKDecoder.setListener(mSymbolBroadcaster);
- break;
- }
- }
-
- public enum Sync
- {
- NORMAL("Normal", SyncPattern.MPT1327_CONTROL, SyncPattern.MPT1327_TRAFFIC),
- FRENCH("French", SyncPattern.MPT1327_CONTROL_FRENCH, SyncPattern.MPT1327_TRAFFIC_FRENCH);
-
- private String mLabel;
- private SyncPattern mControlSyncPattern;
- private SyncPattern mTrafficSyncPattern;
-
- private Sync(String label, SyncPattern controlPattern, SyncPattern trafficPattern)
- {
- mLabel = label;
- mControlSyncPattern = controlPattern;
- mTrafficSyncPattern = trafficPattern;
- }
-
- public String getLabel()
- {
- return mLabel;
- }
-
- public SyncPattern getControlSyncPattern()
- {
- return mControlSyncPattern;
- }
-
- public SyncPattern getTrafficSyncPattern()
- {
- return mTrafficSyncPattern;
- }
-
- public String toString()
- {
- return getLabel();
- }
- }
-
- @Override
- public void reset()
- {
- mControlMessageFramer.reset();
- mTrafficMessageFramer.reset();
- }
}
diff --git a/src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327DecoderLegacy.java b/src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327DecoderLegacy.java
new file mode 100644
index 00000000..be8fef25
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/module/decode/mpt1327/MPT1327DecoderLegacy.java
@@ -0,0 +1,253 @@
+/*******************************************************************************
+ * sdrtrunk
+ * Copyright (C) 2014-2017 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.module.decode.mpt1327;
+
+import io.github.dsheirer.alias.AliasList;
+import io.github.dsheirer.bits.MessageFramer;
+import io.github.dsheirer.dsp.filter.FilterFactory;
+import io.github.dsheirer.dsp.filter.Filters;
+import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
+import io.github.dsheirer.dsp.filter.fir.real.RealFIRFilter_RB_RB;
+import io.github.dsheirer.dsp.filter.halfband.real.HalfBandFilter_RB_RB;
+import io.github.dsheirer.dsp.fsk.FSK2Decoder;
+import io.github.dsheirer.instrument.Instrumentable;
+import io.github.dsheirer.instrument.tap.Tap;
+import io.github.dsheirer.instrument.tap.TapGroup;
+import io.github.dsheirer.instrument.tap.stream.BinaryTap;
+import io.github.dsheirer.instrument.tap.stream.FloatBufferTap;
+import io.github.dsheirer.instrument.tap.stream.FloatTap;
+import io.github.dsheirer.module.decode.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.real.IFilteredRealBufferListener;
+import io.github.dsheirer.sample.real.RealBuffer;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * MPT1327 Decoder - 1200 baud 2FSK decoder that can process 48k sample rate
+ * complex or floating point samples and output fully framed MPT1327 control and
+ * traffic messages.
+ */
+public class MPT1327DecoderLegacy extends Decoder implements IFilteredRealBufferListener, Instrumentable
+{
+ private final static Logger mLog = LoggerFactory.getLogger(MPT1327DecoderLegacy.class);
+
+ private static final FIRFilterSpecification HIGH_PASS_SPECIFICATION = FIRFilterSpecification.highPassBuilder()
+ .sampleRate( 24000 )
+ .stopBandCutoff( 800 )
+ .stopBandAmplitude( 0.0 )
+ .stopBandRipple( 0.03 )
+ .passBandStart( 1000 )
+ .passBandAmplitude( 1.0 )
+ .passBandRipple( 0.08 )
+ .build();
+
+ private static float[] HIGHPASS_FILTER;
+
+ static
+ {
+ try
+ {
+ HIGHPASS_FILTER = FilterFactory.getTaps(HIGH_PASS_SPECIFICATION);
+ }
+ catch(Exception e)
+ {
+ mLog.error("Couldn't design MPT1327 highpass filter");
+ }
+ }
+
+ /* Decimated sample rate ( 48,000 / 2 = 24,000 ) feeding the decoder */
+ private static final int sDECIMATED_SAMPLE_RATE = 24000;
+
+ /* Baud or Symbol Rate */
+ private static final int sSYMBOL_RATE = 1200;
+
+ /* Message length -- longest possible message is:
+ * 4xREVS + 16xSYNC + 64xADD1 + 64xDCW1 + 64xDCW2 + 64xDCW3 + 64xDCW4 */
+ private static final int sMESSAGE_LENGTH = 350;
+
+ /* Instrumentation Taps */
+ private static final String INSTRUMENT_HB1_FILTER_TO_HIGH_PASS =
+ "Tap Point: Half-band Decimation Filter > < Low Pass Filter";
+ private static final String INSTRUMENT_HIGH_PASS_TO_DECODER =
+ "Tap Point: Low Pass Filter > < Decoder";
+ private static final String INSTRUMENT_DECODER_TO_FRAMER =
+ "Tap Point: Decoder > < Sync Detect/Message Framer";
+ private List mAvailableTaps;
+
+ private HalfBandFilter_RB_RB mDecimationFilter;
+ private RealFIRFilter_RB_RB mHighPassFilter;
+ private FSK2Decoder mFSKDecoder;
+ private Broadcaster mSymbolBroadcaster;
+ private MessageFramer mControlMessageFramer;
+ private MessageFramer mTrafficMessageFramer;
+ private MPT1327MessageProcessor mMessageProcessor;
+
+ public MPT1327DecoderLegacy(AliasList aliasList, Sync sync)
+ {
+ /**
+ * Normal: 2FSK Decoder with inverted output
+ * French: 2FSK Decoder with normal output
+ */
+ if(sync == Sync.NORMAL)
+ {
+ mFSKDecoder = new FSK2Decoder(24000, 1200, FSK2Decoder.Output.INVERTED);
+ }
+ else if(sync == Sync.FRENCH)
+ {
+ mFSKDecoder = new FSK2Decoder(24000, 1200, FSK2Decoder.Output.NORMAL);
+ }
+ else
+ {
+ throw new IllegalArgumentException("MPT1327 Decoder - unrecognized Sync type");
+ }
+
+ /* Decimation filter - 48000 / 2 = 24000 output */
+ mDecimationFilter = new HalfBandFilter_RB_RB(Filters.FIR_HALF_BAND_31T_ONE_EIGHTH_FCO.getCoefficients(), 1.0002f, true);
+
+ //High-pass filter the audio to remove any DC component or CTCSS tones. The audio has already been low-pass
+ //filtered by the AudioDemodulation filter cutoff of 3400 Hz.
+ mHighPassFilter = new RealFIRFilter_RB_RB(HIGHPASS_FILTER, 1.0f);
+ mDecimationFilter.setListener(mHighPassFilter);
+
+ mHighPassFilter.setListener(mFSKDecoder);
+
+ mSymbolBroadcaster = new Broadcaster();
+ mFSKDecoder.setListener(mSymbolBroadcaster);
+
+ /* Message framer for control channel messages */
+ mControlMessageFramer = new MessageFramer(sync.getControlSyncPattern().getPattern(), sMESSAGE_LENGTH);
+ mSymbolBroadcaster.addListener(mControlMessageFramer);
+
+ /* Message framer for traffic channel massages */
+ mTrafficMessageFramer = new MessageFramer(sync.getTrafficSyncPattern().getPattern(), sMESSAGE_LENGTH);
+ mSymbolBroadcaster.addListener(mTrafficMessageFramer);
+
+ /* Fully decoded and framed messages processor */
+ mMessageProcessor = new MPT1327MessageProcessor(aliasList);
+ mMessageProcessor.setMessageListener(getMessageListener());
+ mControlMessageFramer.addMessageListener(mMessageProcessor);
+ mTrafficMessageFramer.addMessageListener(mMessageProcessor);
+ }
+
+ @Override
+ public Listener getFilteredRealBufferListener()
+ {
+ return mDecimationFilter;
+ }
+
+ @Override
+ public DecoderType getDecoderType()
+ {
+ return DecoderType.MPT1327;
+ }
+
+ /**
+ * Cleanup method
+ */
+ public void dispose()
+ {
+ super.dispose();
+
+ mSymbolBroadcaster.dispose();
+
+ mControlMessageFramer.dispose();
+
+ mFSKDecoder.dispose();
+
+ mDecimationFilter.dispose();
+
+ mMessageProcessor.dispose();
+
+ mTrafficMessageFramer.dispose();
+ }
+
+ /* Instrumentation Taps */
+ @Override
+ public List getTapGroups()
+ {
+ if(mAvailableTaps == null)
+ {
+ mAvailableTaps = new ArrayList();
+
+ TapGroup group = new TapGroup("MPT-1327 Decoder");
+
+ group.add(new FloatTap(INSTRUMENT_HB1_FILTER_TO_HIGH_PASS, 0, 0.5f));
+ group.add(new FloatTap(INSTRUMENT_HIGH_PASS_TO_DECODER, 0, 0.5f));
+ group.add(new BinaryTap(INSTRUMENT_DECODER_TO_FRAMER, 0, 0.025f));
+
+ mAvailableTaps.add(group);
+
+ /* Add the taps from the FSK decoder */
+ mAvailableTaps.addAll(mFSKDecoder.getTapGroups());
+ }
+
+ return mAvailableTaps;
+ }
+
+ @Override
+ public void registerTap(Tap tap)
+ {
+ /* Send request to decoder */
+ mFSKDecoder.registerTap(tap);
+
+ switch(tap.getName())
+ {
+ case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
+ FloatBufferTap hb1Tap = (FloatBufferTap) tap;
+ mDecimationFilter.setListener(hb1Tap);
+ hb1Tap.setListener(mHighPassFilter);
+ break;
+ case INSTRUMENT_HIGH_PASS_TO_DECODER:
+ FloatBufferTap lowTap = (FloatBufferTap) tap;
+ mHighPassFilter.setListener(lowTap);
+ lowTap.setListener(mFSKDecoder);
+ break;
+ case INSTRUMENT_DECODER_TO_FRAMER:
+ BinaryTap decoderTap = (BinaryTap) tap;
+ mFSKDecoder.setListener(decoderTap);
+ decoderTap.setListener(mSymbolBroadcaster);
+ break;
+ }
+ }
+
+ @Override
+ public void unregisterTap(Tap tap)
+ {
+ mFSKDecoder.unregisterTap(tap);
+
+ switch(tap.getName())
+ {
+ case INSTRUMENT_HB1_FILTER_TO_HIGH_PASS:
+ mDecimationFilter.setListener(mHighPassFilter);
+ break;
+ case INSTRUMENT_HIGH_PASS_TO_DECODER:
+ mHighPassFilter.setListener(mFSKDecoder);
+ break;
+ case INSTRUMENT_DECODER_TO_FRAMER:
+ mFSKDecoder.setListener(mSymbolBroadcaster);
+ break;
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/module/decode/mpt1327/Sync.java b/src/main/java/io/github/dsheirer/module/decode/mpt1327/Sync.java
new file mode 100644
index 00000000..33adc048
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/module/decode/mpt1327/Sync.java
@@ -0,0 +1,55 @@
+/*******************************************************************************
+ * 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.module.decode.mpt1327;
+
+import io.github.dsheirer.bits.SyncPattern;
+
+public enum Sync
+{
+ NORMAL("Normal", SyncPattern.MPT1327_CONTROL, SyncPattern.MPT1327_TRAFFIC),
+ FRENCH("French", SyncPattern.MPT1327_CONTROL_FRENCH, SyncPattern.MPT1327_TRAFFIC_FRENCH);
+
+ private String mLabel;
+ private SyncPattern mControlSyncPattern;
+ private SyncPattern mTrafficSyncPattern;
+
+ Sync(String label, SyncPattern controlPattern, SyncPattern trafficPattern)
+ {
+ mLabel = label;
+ mControlSyncPattern = controlPattern;
+ mTrafficSyncPattern = trafficPattern;
+ }
+
+ public String getLabel()
+ {
+ return mLabel;
+ }
+
+ public SyncPattern getControlSyncPattern()
+ {
+ return mControlSyncPattern;
+ }
+
+ public SyncPattern getTrafficSyncPattern()
+ {
+ return mTrafficSyncPattern;
+ }
+
+ public String toString()
+ {
+ return getLabel();
+ }
+}