Updates P25 C4FM and LSM decoders to provide demodulated bit streams

for recording using the new binary recorders/format.
This commit is contained in:
Denny
2018-08-18 03:36:17 -04:00
parent 2044c2a2de
commit ade0cef50b
6 changed files with 50 additions and 85 deletions

View File

@@ -16,11 +16,12 @@
package io.github.dsheirer.module.decode.p25; package io.github.dsheirer.module.decode.p25;
import io.github.dsheirer.alias.AliasList; import io.github.dsheirer.alias.AliasList;
import io.github.dsheirer.dsp.symbol.Dibit;
import io.github.dsheirer.dsp.symbol.DibitToByteBufferAssembler; import io.github.dsheirer.dsp.symbol.DibitToByteBufferAssembler;
import io.github.dsheirer.module.decode.Decoder; import io.github.dsheirer.module.decode.Decoder;
import io.github.dsheirer.module.decode.DecoderType; import io.github.dsheirer.module.decode.DecoderType;
import io.github.dsheirer.sample.Broadcaster;
import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.IReusableByteBufferListener;
import io.github.dsheirer.sample.buffer.IReusableByteBufferProvider; import io.github.dsheirer.sample.buffer.IReusableByteBufferProvider;
import io.github.dsheirer.sample.buffer.IReusableComplexBufferListener; import io.github.dsheirer.sample.buffer.IReusableComplexBufferListener;
import io.github.dsheirer.sample.buffer.ReusableByteBuffer; import io.github.dsheirer.sample.buffer.ReusableByteBuffer;
@@ -29,11 +30,11 @@ import io.github.dsheirer.source.ISourceEventListener;
import io.github.dsheirer.source.ISourceEventProvider; import io.github.dsheirer.source.ISourceEventProvider;
import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceEvent;
public abstract class P25Decoder extends Decoder public abstract class P25Decoder extends Decoder implements ISourceEventListener, ISourceEventProvider,
implements ISourceEventListener, ISourceEventProvider, IReusableComplexBufferListener, Listener<ReusableComplexBuffer>, IReusableComplexBufferListener, Listener<ReusableComplexBuffer>, IReusableByteBufferProvider
IReusableByteBufferProvider, IReusableByteBufferListener
{ {
private double mSampleRate; private double mSampleRate;
private Broadcaster<Dibit> mDibitBroadcaster = new Broadcaster<>();
private DibitToByteBufferAssembler mByteBufferAssembler = new DibitToByteBufferAssembler(300); private DibitToByteBufferAssembler mByteBufferAssembler = new DibitToByteBufferAssembler(300);
private P25MessageProcessor mMessageProcessor; private P25MessageProcessor mMessageProcessor;
private AliasList mAliasList; private AliasList mAliasList;
@@ -46,14 +47,15 @@ public abstract class P25Decoder extends Decoder
mAliasList = aliasList; mAliasList = aliasList;
mMessageProcessor = new P25MessageProcessor(mAliasList); mMessageProcessor = new P25MessageProcessor(mAliasList);
mMessageProcessor.setMessageListener(getMessageListener()); mMessageProcessor.setMessageListener(getMessageListener());
mDibitBroadcaster.addListener(mByteBufferAssembler);
} }
/** /**
* Assembler for packaging Dibit stream into reusable byte buffers. * Assembler for packaging Dibit stream into reusable byte buffers.
*/ */
protected DibitToByteBufferAssembler getByteBufferAssembler() protected Broadcaster<Dibit> getDibitBroadcaster()
{ {
return mByteBufferAssembler; return mDibitBroadcaster;
} }
/** /**
@@ -62,7 +64,7 @@ public abstract class P25Decoder extends Decoder
@Override @Override
public void setBufferListener(Listener<ReusableByteBuffer> listener) public void setBufferListener(Listener<ReusableByteBuffer> listener)
{ {
getByteBufferAssembler().setBufferListener(listener); mByteBufferAssembler.setBufferListener(listener);
} }
/** /**
@@ -71,7 +73,7 @@ public abstract class P25Decoder extends Decoder
@Override @Override
public void removeBufferListener(Listener<ReusableByteBuffer> listener) public void removeBufferListener(Listener<ReusableByteBuffer> listener)
{ {
getByteBufferAssembler().removeBufferListener(listener); mByteBufferAssembler.removeBufferListener(listener);
} }
/** /**
@@ -80,7 +82,7 @@ public abstract class P25Decoder extends Decoder
@Override @Override
public boolean hasBufferListeners() public boolean hasBufferListeners()
{ {
return getByteBufferAssembler().hasBufferListeners(); return mByteBufferAssembler.hasBufferListeners();
} }
protected double getSymbolRate() protected double getSymbolRate()

View File

@@ -25,7 +25,6 @@ import io.github.dsheirer.dsp.psk.DQPSKDecisionDirectedDemodulator;
import io.github.dsheirer.dsp.psk.InterpolatingSampleBuffer; import io.github.dsheirer.dsp.psk.InterpolatingSampleBuffer;
import io.github.dsheirer.dsp.psk.pll.AdaptivePLLGainMonitor; import io.github.dsheirer.dsp.psk.pll.AdaptivePLLGainMonitor;
import io.github.dsheirer.dsp.psk.pll.CostasLoop; import io.github.dsheirer.dsp.psk.pll.CostasLoop;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer; import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceEvent;
import org.slf4j.Logger; import org.slf4j.Logger;
@@ -72,20 +71,20 @@ public class P25DecoderC4FM extends P25Decoder
mQPSKDemodulator = new DQPSKDecisionDirectedDemodulator(mCostasLoop, mInterpolatingSampleBuffer); mQPSKDemodulator = new DQPSKDecisionDirectedDemodulator(mCostasLoop, mInterpolatingSampleBuffer);
if(mMessageFramer != null)
{
getDibitBroadcaster().removeListener(mMessageFramer);
mMessageFramer.dispose();
}
//The Costas Loop receives symbol-inversion correction requests when detected. //The Costas Loop receives symbol-inversion correction requests when detected.
//The PLL gain monitor receives sync detect/loss signals from the message framer //The PLL gain monitor receives sync detect/loss signals from the message framer
mMessageFramer = new P25MessageFramer(getAliasList(), mCostasLoop, mPLLGainMonitor); mMessageFramer = new P25MessageFramer(getAliasList(), mCostasLoop, mPLLGainMonitor);
mMessageFramer.setListener(getMessageProcessor()); mMessageFramer.setListener(getMessageProcessor());
mMessageFramer.setSampleRate(sampleRate); mMessageFramer.setSampleRate(sampleRate);
// mQPSKDemodulator.setSymbolListener(mMessageFramer); mQPSKDemodulator.setSymbolListener(getDibitBroadcaster());
mQPSKDemodulator.setSymbolListener(getByteBufferAssembler()); getDibitBroadcaster().addListener(mMessageFramer);
}
@Override
public Listener getReusableByteBufferListener()
{
return mMessageFramer;
} }
/** /**

View File

@@ -78,7 +78,8 @@ public class P25DecoderC4FMInstrumented extends P25DecoderC4FM
instrumented.setPLLFrequencyListener(mPLLFrequencyListener); instrumented.setPLLFrequencyListener(mPLLFrequencyListener);
instrumented.setSymbolDecisionDataListener(mSymbolDecisionDataListener); instrumented.setSymbolDecisionDataListener(mSymbolDecisionDataListener);
instrumented.setSamplesPerSymbolListener(mSamplesPerSymbolListener); instrumented.setSamplesPerSymbolListener(mSamplesPerSymbolListener);
instrumented.setSymbolListener(getByteBufferAssembler()); instrumented.setSymbolListener(getDibitBroadcaster());
getDibitBroadcaster().addListener(mMessageFramer);
} }
public void setComplexSymbolListener(Listener<Complex> listener) public void setComplexSymbolListener(Listener<Complex> listener)

View File

@@ -24,7 +24,6 @@ import io.github.dsheirer.dsp.psk.DQPSKGardnerDemodulator;
import io.github.dsheirer.dsp.psk.InterpolatingSampleBuffer; import io.github.dsheirer.dsp.psk.InterpolatingSampleBuffer;
import io.github.dsheirer.dsp.psk.pll.AdaptivePLLGainMonitor; import io.github.dsheirer.dsp.psk.pll.AdaptivePLLGainMonitor;
import io.github.dsheirer.dsp.psk.pll.CostasLoop; import io.github.dsheirer.dsp.psk.pll.CostasLoop;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableComplexBuffer; import io.github.dsheirer.sample.buffer.ReusableComplexBuffer;
import io.github.dsheirer.source.SourceEvent; import io.github.dsheirer.source.SourceEvent;
@@ -76,17 +75,17 @@ public class P25DecoderLSM extends P25Decoder
//The Costas Loop receives symbol-inversion correction requests when detected. //The Costas Loop receives symbol-inversion correction requests when detected.
//The PLL gain monitor receives sync detect/loss signals from the message framer //The PLL gain monitor receives sync detect/loss signals from the message framer
if(mMessageFramer != null)
{
getDibitBroadcaster().removeListener(mMessageFramer);
mMessageFramer.dispose();
}
mMessageFramer = new P25MessageFramer(getAliasList(), mCostasLoop, mPLLGainMonitor); mMessageFramer = new P25MessageFramer(getAliasList(), mCostasLoop, mPLLGainMonitor);
mMessageFramer.setListener(getMessageProcessor()); mMessageFramer.setListener(getMessageProcessor());
mMessageFramer.setSampleRate(sampleRate); mMessageFramer.setSampleRate(sampleRate);
// mQPSKDemodulator.setSymbolListener(mMessageFramer); mQPSKDemodulator.setSymbolListener(getDibitBroadcaster());
mQPSKDemodulator.setSymbolListener(getByteBufferAssembler()); getDibitBroadcaster().addListener(mMessageFramer);
}
@Override
public Listener getReusableByteBufferListener()
{
return mMessageFramer;
} }
/** /**

View File

@@ -79,7 +79,8 @@ public class P25DecoderLSMInstrumented extends P25DecoderLSM
instrumented.setPLLFrequencyListener(mPLLFrequencyListener); instrumented.setPLLFrequencyListener(mPLLFrequencyListener);
instrumented.setSymbolDecisionDataListener(mSymbolDecisionDataListener); instrumented.setSymbolDecisionDataListener(mSymbolDecisionDataListener);
instrumented.setSamplesPerSymbolListener(mSamplesPerSymbolListener); instrumented.setSamplesPerSymbolListener(mSamplesPerSymbolListener);
instrumented.setSymbolListener(getByteBufferAssembler()); instrumented.setSymbolListener(getDibitBroadcaster());
getDibitBroadcaster().addListener(mMessageFramer);
} }
public void setComplexSymbolListener(Listener<Complex> listener) public void setComplexSymbolListener(Listener<Complex> listener)

View File

@@ -32,14 +32,10 @@ import io.github.dsheirer.module.decode.p25.message.vselp.VSELP1Message;
import io.github.dsheirer.module.decode.p25.message.vselp.VSELP2Message; import io.github.dsheirer.module.decode.p25.message.vselp.VSELP2Message;
import io.github.dsheirer.module.decode.p25.reference.DataUnitID; import io.github.dsheirer.module.decode.p25.reference.DataUnitID;
import io.github.dsheirer.sample.Listener; import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableByteBuffer;
import org.slf4j.Logger; import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.util.ArrayList; public class P25MessageFramer implements Listener<Dibit>
import java.util.List;
public class P25MessageFramer implements Listener<ReusableByteBuffer>
{ {
private final static Logger mLog = LoggerFactory.getLogger(P25MessageFramer.class); private final static Logger mLog = LoggerFactory.getLogger(P25MessageFramer.class);
@@ -78,7 +74,7 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
private PLLPhaseInversionDetector mInversionDetector180; private PLLPhaseInversionDetector mInversionDetector180;
private MultiSyncPatternMatcher mMatcher; private MultiSyncPatternMatcher mMatcher;
private List<P25MessageAssembler> mAssemblers = new ArrayList<P25MessageAssembler>(); private P25MessageAssembler mMessageAssembler = new P25MessageAssembler();
private Listener<Message> mListener; private Listener<Message> mListener;
private AliasList mAliasList; private AliasList mAliasList;
@@ -105,13 +101,9 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
@Override @Override
public void syncDetected() public void syncDetected()
{ {
for(P25MessageAssembler assembler : mAssemblers) if(!mMessageAssembler.isActive())
{ {
if(!assembler.isActive()) mMessageAssembler.setActive(true);
{
assembler.setActive(true);
break;
}
} }
} }
@@ -123,17 +115,6 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
}); });
mMatcher.add(mPrimarySyncDetector); mMatcher.add(mPrimarySyncDetector);
/**
* We use two message assemblers to catch any sync detections, so that
* if we have a false trigger then we still have a chance to catch the
* valid message. If we have two false triggers before the arrival of
* the actual message sync, then the third or subsequent real or false
* sync pattern will produce a debug message indicating no assemblers
* are available..
*/
mAssemblers.add(new P25MessageAssembler());
mAssemblers.add(new P25MessageAssembler());
} }
public P25MessageFramer(AliasList aliasList, IPhaseLockedLoop phaseLockedLoop, ISyncDetectListener syncDetectListener) public P25MessageFramer(AliasList aliasList, IPhaseLockedLoop phaseLockedLoop, ISyncDetectListener syncDetectListener)
@@ -173,12 +154,7 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
public void dispose() public void dispose()
{ {
for(P25MessageAssembler a : mAssemblers) mMessageAssembler.dispose();
{
a.dispose();
}
mAssemblers.clear();
mListener = null; mListener = null;
mAliasList = null; mAliasList = null;
@@ -200,29 +176,20 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
} }
@Override @Override
public void receive(ReusableByteBuffer reusableByteBuffer) public void receive(Dibit symbol)
{ {
//process the buffer received if(mMessageAssembler.isActive())
} {
mMessageAssembler.receive(symbol);
// @Override if(mMessageAssembler.complete())
// public void receive(Dibit symbol) {
// { mMessageAssembler.reset();
// for(P25MessageAssembler assembler : mAssemblers) }
// { }
// if(assembler.isActive())
// { mMatcher.receive(symbol.getBit1(), symbol.getBit2());
// assembler.receive(symbol); }
//
// if(assembler.complete())
// {
// assembler.reset();
// }
// }
// }
//
// mMatcher.receive(symbol.getBit1(), symbol.getBit2());
// }
public void setListener(Listener<Message> listener) public void setListener(Listener<Message> listener)
{ {
@@ -749,13 +716,9 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
mPhaseLockedLoop.correctInversion(mPllCorrection); mPhaseLockedLoop.correctInversion(mPllCorrection);
/* Since we detected a sync pattern, start a message assembler */ /* Since we detected a sync pattern, start a message assembler */
for(P25MessageAssembler assembler : mAssemblers) if(!mMessageAssembler.isActive())
{ {
if(!assembler.isActive()) mMessageAssembler.setActive(true);
{
assembler.setActive(true);
break;
}
} }
} }