39 - Adds P25/LSM support to the DemodulatorViewerFX application and

adds Feed forward gain support to the C4FM DQPSK demodulator which seems
to improve output from the interpolating sample buffer at each symbol
period.  Updates the symbol timing gain for C4FM to decrease the gain a
bit since the feed forward gain is providing a better interpolated symbol.
This commit is contained in:
Denny
2018-03-24 11:03:18 -04:00
parent bfaacb309d
commit c36f6901af
16 changed files with 130 additions and 76 deletions

View File

@@ -20,6 +20,7 @@ import io.github.dsheirer.dsp.filter.FilterFactory;
import io.github.dsheirer.dsp.filter.design.FilterDesignException;
import io.github.dsheirer.dsp.filter.fir.FIRFilterSpecification;
import io.github.dsheirer.dsp.filter.fir.complex.ComplexFIRFilter;
import io.github.dsheirer.dsp.gain.ComplexFeedForwardGainControl;
import io.github.dsheirer.dsp.psk.DQPSKDecisionDirectedDemodulator;
import io.github.dsheirer.dsp.psk.InterpolatingSampleBuffer;
import io.github.dsheirer.dsp.psk.pll.CostasLoop;
@@ -34,11 +35,12 @@ import java.util.Map;
public class P25DecoderC4FM extends P25Decoder
{
private final static Logger mLog = LoggerFactory.getLogger(P25DecoderC4FM.class);
protected static final float SYMBOL_TIMING_GAIN = 0.1f;
protected static final float SAMPLE_COUNTER_GAIN = 0.5f;
protected InterpolatingSampleBuffer mInterpolatingSampleBuffer;
protected DQPSKDecisionDirectedDemodulator mQPSKDemodulator;
protected CostasLoop mCostasLoop;
protected P25MessageFramer mMessageFramer;
private ComplexFeedForwardGainControl mAGC = new ComplexFeedForwardGainControl(32);
private Map<Double,float[]> mBasebandFilters = new HashMap<>();
private ComplexFIRFilter mBasebandFilter;
@@ -61,7 +63,7 @@ public class P25DecoderC4FM extends P25Decoder
mBasebandFilter = new ComplexFIRFilter(getBasebandFilter(), 1.0f);
mCostasLoop = new CostasLoop(getSampleRate(), getSymbolRate());
mInterpolatingSampleBuffer = new InterpolatingSampleBuffer(getSamplesPerSymbol(), SYMBOL_TIMING_GAIN);
mInterpolatingSampleBuffer = new InterpolatingSampleBuffer(getSamplesPerSymbol(), SAMPLE_COUNTER_GAIN);
mQPSKDemodulator = new DQPSKDecisionDirectedDemodulator(mCostasLoop, mInterpolatingSampleBuffer);
@@ -79,10 +81,13 @@ public class P25DecoderC4FM extends P25Decoder
public void receive(ReusableComplexBuffer reusableComplexBuffer)
{
//User accounting of the incoming buffer is handled by the filter
ReusableComplexBuffer filtered = filter(reusableComplexBuffer);
ReusableComplexBuffer basebandFiltered = filter(reusableComplexBuffer);
//User accounting of the incoming buffer is handled by the gain filter
ReusableComplexBuffer gainApplied = mAGC.filter(basebandFiltered);
//User accounting of the filtered buffer is handled by the demodulator
mQPSKDemodulator.receive(filtered);
mQPSKDemodulator.receive(gainApplied);
}
/**

View File

@@ -50,9 +50,6 @@ public class P25DecoderC4FMInstrumented extends P25DecoderC4FM
{
ReusableComplexBuffer filtered = super.filter(reusableComplexBuffer);
//Increment user count before we hand to another listener or return from this method
filtered.incrementUserCount();
if(mFilteredSymbolListener != null)
{
filtered.incrementUserCount();
@@ -70,7 +67,7 @@ public class P25DecoderC4FMInstrumented extends P25DecoderC4FM
super.setSampleRate(sampleRate);
InterpolatingSampleBufferInstrumented instrumentedBuffer =
new InterpolatingSampleBufferInstrumented(getSamplesPerSymbol(), SYMBOL_TIMING_GAIN);
new InterpolatingSampleBufferInstrumented(getSamplesPerSymbol(), SAMPLE_COUNTER_GAIN);
mInterpolatingSampleBuffer = instrumentedBuffer;
DQPSKDecisionDirectedDemodulatorInstrumented instrumented = new DQPSKDecisionDirectedDemodulatorInstrumented(mCostasLoop, instrumentedBuffer, getSampleRate());

View File

@@ -34,7 +34,7 @@ import java.util.Map;
public class P25DecoderLSM extends P25Decoder
{
private final static Logger mLog = LoggerFactory.getLogger(P25DecoderLSM.class);
protected static final float SYMBOL_TIMING_GAIN = 0.1f;
protected static final float SAMPLE_COUNTER_GAIN = 0.5f;
private Map<Double,float[]> mBasebandFilters = new HashMap<>();
private ComplexFIRFilter mBasebandFilter;
@@ -67,7 +67,7 @@ public class P25DecoderLSM extends P25Decoder
mBasebandFilter = new ComplexFIRFilter(getBasebandFilter(), 1.0f);
mCostasLoop = new CostasLoop(getSampleRate(), getSymbolRate());
mInterpolatingSampleBuffer = new InterpolatingSampleBuffer(getSamplesPerSymbol(), SYMBOL_TIMING_GAIN);
mInterpolatingSampleBuffer = new InterpolatingSampleBuffer(getSamplesPerSymbol(), SAMPLE_COUNTER_GAIN);
mQPSKDemodulator = new DQPSKGardnerDemodulator(mCostasLoop, mInterpolatingSampleBuffer);

View File

@@ -52,9 +52,6 @@ public class P25DecoderLSMInstrumented extends P25DecoderLSM
{
ReusableComplexBuffer filtered = super.filter(reusableComplexBuffer);
//Increment user count before we hand to another listener or return from this method
filtered.incrementUserCount();
if(mFilteredSymbolListener != null)
{
filtered.incrementUserCount();
@@ -71,7 +68,7 @@ public class P25DecoderLSMInstrumented extends P25DecoderLSM
{
super.setSampleRate(sampleRate);
InterpolatingSampleBufferInstrumented instrumentedBuffer = new InterpolatingSampleBufferInstrumented(getSamplesPerSymbol(), SYMBOL_TIMING_GAIN);
InterpolatingSampleBufferInstrumented instrumentedBuffer = new InterpolatingSampleBufferInstrumented(getSamplesPerSymbol(), SAMPLE_COUNTER_GAIN);
mInterpolatingSampleBuffer = instrumentedBuffer;
DQPSKGardnerDemodulatorInstrumented instrumented = new DQPSKGardnerDemodulatorInstrumented(mCostasLoop, instrumentedBuffer, getSampleRate());