mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Updates P25 C4FM and LSM decoders to provide demodulated bit streams
for recording using the new binary recorders/format.
This commit is contained in:
@@ -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()
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -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)
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user