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;
import io.github.dsheirer.alias.AliasList;
import io.github.dsheirer.dsp.symbol.Dibit;
import io.github.dsheirer.dsp.symbol.DibitToByteBufferAssembler;
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.buffer.IReusableByteBufferListener;
import io.github.dsheirer.sample.buffer.IReusableByteBufferProvider;
import io.github.dsheirer.sample.buffer.IReusableComplexBufferListener;
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.SourceEvent;
public abstract class P25Decoder extends Decoder
implements ISourceEventListener, ISourceEventProvider, IReusableComplexBufferListener, Listener<ReusableComplexBuffer>,
IReusableByteBufferProvider, IReusableByteBufferListener
public abstract class P25Decoder extends Decoder implements ISourceEventListener, ISourceEventProvider,
IReusableComplexBufferListener, Listener<ReusableComplexBuffer>, IReusableByteBufferProvider
{
private double mSampleRate;
private Broadcaster<Dibit> mDibitBroadcaster = new Broadcaster<>();
private DibitToByteBufferAssembler mByteBufferAssembler = new DibitToByteBufferAssembler(300);
private P25MessageProcessor mMessageProcessor;
private AliasList mAliasList;
@@ -46,14 +47,15 @@ public abstract class P25Decoder extends Decoder
mAliasList = aliasList;
mMessageProcessor = new P25MessageProcessor(mAliasList);
mMessageProcessor.setMessageListener(getMessageListener());
mDibitBroadcaster.addListener(mByteBufferAssembler);
}
/**
* 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
public void setBufferListener(Listener<ReusableByteBuffer> listener)
{
getByteBufferAssembler().setBufferListener(listener);
mByteBufferAssembler.setBufferListener(listener);
}
/**
@@ -71,7 +73,7 @@ public abstract class P25Decoder extends Decoder
@Override
public void removeBufferListener(Listener<ReusableByteBuffer> listener)
{
getByteBufferAssembler().removeBufferListener(listener);
mByteBufferAssembler.removeBufferListener(listener);
}
/**
@@ -80,7 +82,7 @@ public abstract class P25Decoder extends Decoder
@Override
public boolean hasBufferListeners()
{
return getByteBufferAssembler().hasBufferListeners();
return mByteBufferAssembler.hasBufferListeners();
}
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.pll.AdaptivePLLGainMonitor;
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.source.SourceEvent;
import org.slf4j.Logger;
@@ -72,20 +71,20 @@ public class P25DecoderC4FM extends P25Decoder
mQPSKDemodulator = new DQPSKDecisionDirectedDemodulator(mCostasLoop, mInterpolatingSampleBuffer);
if(mMessageFramer != null)
{
getDibitBroadcaster().removeListener(mMessageFramer);
mMessageFramer.dispose();
}
//The Costas Loop receives symbol-inversion correction requests when detected.
//The PLL gain monitor receives sync detect/loss signals from the message framer
mMessageFramer = new P25MessageFramer(getAliasList(), mCostasLoop, mPLLGainMonitor);
mMessageFramer.setListener(getMessageProcessor());
mMessageFramer.setSampleRate(sampleRate);
// mQPSKDemodulator.setSymbolListener(mMessageFramer);
mQPSKDemodulator.setSymbolListener(getByteBufferAssembler());
}
@Override
public Listener getReusableByteBufferListener()
{
return mMessageFramer;
mQPSKDemodulator.setSymbolListener(getDibitBroadcaster());
getDibitBroadcaster().addListener(mMessageFramer);
}
/**

View File

@@ -78,7 +78,8 @@ public class P25DecoderC4FMInstrumented extends P25DecoderC4FM
instrumented.setPLLFrequencyListener(mPLLFrequencyListener);
instrumented.setSymbolDecisionDataListener(mSymbolDecisionDataListener);
instrumented.setSamplesPerSymbolListener(mSamplesPerSymbolListener);
instrumented.setSymbolListener(getByteBufferAssembler());
instrumented.setSymbolListener(getDibitBroadcaster());
getDibitBroadcaster().addListener(mMessageFramer);
}
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.pll.AdaptivePLLGainMonitor;
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.source.SourceEvent;
@@ -76,17 +75,17 @@ public class P25DecoderLSM extends P25Decoder
//The Costas Loop receives symbol-inversion correction requests when detected.
//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.setListener(getMessageProcessor());
mMessageFramer.setSampleRate(sampleRate);
// mQPSKDemodulator.setSymbolListener(mMessageFramer);
mQPSKDemodulator.setSymbolListener(getByteBufferAssembler());
}
@Override
public Listener getReusableByteBufferListener()
{
return mMessageFramer;
mQPSKDemodulator.setSymbolListener(getDibitBroadcaster());
getDibitBroadcaster().addListener(mMessageFramer);
}
/**

View File

@@ -79,7 +79,8 @@ public class P25DecoderLSMInstrumented extends P25DecoderLSM
instrumented.setPLLFrequencyListener(mPLLFrequencyListener);
instrumented.setSymbolDecisionDataListener(mSymbolDecisionDataListener);
instrumented.setSamplesPerSymbolListener(mSamplesPerSymbolListener);
instrumented.setSymbolListener(getByteBufferAssembler());
instrumented.setSymbolListener(getDibitBroadcaster());
getDibitBroadcaster().addListener(mMessageFramer);
}
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.reference.DataUnitID;
import io.github.dsheirer.sample.Listener;
import io.github.dsheirer.sample.buffer.ReusableByteBuffer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import java.util.ArrayList;
import java.util.List;
public class P25MessageFramer implements Listener<ReusableByteBuffer>
public class P25MessageFramer implements Listener<Dibit>
{
private final static Logger mLog = LoggerFactory.getLogger(P25MessageFramer.class);
@@ -78,7 +74,7 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
private PLLPhaseInversionDetector mInversionDetector180;
private MultiSyncPatternMatcher mMatcher;
private List<P25MessageAssembler> mAssemblers = new ArrayList<P25MessageAssembler>();
private P25MessageAssembler mMessageAssembler = new P25MessageAssembler();
private Listener<Message> mListener;
private AliasList mAliasList;
@@ -105,13 +101,9 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
@Override
public void syncDetected()
{
for(P25MessageAssembler assembler : mAssemblers)
if(!mMessageAssembler.isActive())
{
if(!assembler.isActive())
{
assembler.setActive(true);
break;
}
mMessageAssembler.setActive(true);
}
}
@@ -123,17 +115,6 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
});
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)
@@ -173,12 +154,7 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
public void dispose()
{
for(P25MessageAssembler a : mAssemblers)
{
a.dispose();
}
mAssemblers.clear();
mMessageAssembler.dispose();
mListener = null;
mAliasList = null;
@@ -200,29 +176,20 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
}
@Override
public void receive(ReusableByteBuffer reusableByteBuffer)
public void receive(Dibit symbol)
{
//process the buffer received
}
if(mMessageAssembler.isActive())
{
mMessageAssembler.receive(symbol);
// @Override
// public void receive(Dibit symbol)
// {
// for(P25MessageAssembler assembler : mAssemblers)
// {
// if(assembler.isActive())
// {
// assembler.receive(symbol);
//
// if(assembler.complete())
// {
// assembler.reset();
// }
// }
// }
//
// mMatcher.receive(symbol.getBit1(), symbol.getBit2());
// }
if(mMessageAssembler.complete())
{
mMessageAssembler.reset();
}
}
mMatcher.receive(symbol.getBit1(), symbol.getBit2());
}
public void setListener(Listener<Message> listener)
{
@@ -749,13 +716,9 @@ public class P25MessageFramer implements Listener<ReusableByteBuffer>
mPhaseLockedLoop.correctInversion(mPllCorrection);
/* Since we detected a sync pattern, start a message assembler */
for(P25MessageAssembler assembler : mAssemblers)
if(!mMessageAssembler.isActive())
{
if(!assembler.isActive())
{
assembler.setActive(true);
break;
}
mMessageAssembler.setActive(true);
}
}