39 - WIP - incorporates the latest P25 C4FM decoder from master and

updates the LSM decoder to follow the same design pattern.  Adds LSM
decoder support to the demodulator viewer application.  The current
symbol timing gain for LSM is set too high -- is using the C4FM gain
and causes too much fluctuation in the timing error.
This commit is contained in:
Denny
2018-03-24 06:59:41 -04:00
parent c3b405a752
commit bfaacb309d
40 changed files with 1817 additions and 1291 deletions

View File

@@ -24,6 +24,7 @@ public class InterpolatingSampleBuffer
private Complex mPrecedingSample = new Complex(0,0);
private Complex mCurrentSample = new Complex(0,0);
private Complex mMiddleSample = new Complex(0,0);
private float[] mDelayLineInphase;
private float[] mDelayLineQuadrature;
@@ -42,8 +43,9 @@ public class InterpolatingSampleBuffer
/**
* Buffer to store complex sample data and produce interpolated samples.
* @param samplesPerSymbol
* @param symbolTimingGain for the symbol timing error adjustments
*/
public InterpolatingSampleBuffer(float samplesPerSymbol)
public InterpolatingSampleBuffer(float samplesPerSymbol, float symbolTimingGain)
{
mSamplingPoint = samplesPerSymbol;
mDetectedSamplesPerSymbol = samplesPerSymbol;
@@ -52,6 +54,7 @@ public class InterpolatingSampleBuffer
mTwiceSamplesPerSymbol = (int)Math.floor(2.0 * samplesPerSymbol);
mDelayLineInphase = new float[2 * mTwiceSamplesPerSymbol];
mDelayLineQuadrature = new float[2 * mTwiceSamplesPerSymbol];
mDetectedSamplesPerSymbolGain = symbolTimingGain * mSampleCounterGain * mSampleCounterGain;
}
/**
@@ -125,18 +128,21 @@ public class InterpolatingSampleBuffer
}
/**
* Un-interpolated sample that precedes the current interpolated sampling point. The current sampling point falls
* somewhere between sample index 3 and index 4, therefore the preceding sample is located at index 3.
* Un-interpolated sample that precedes the current interpolated sampling point. The current interpolated sampling
* point falls somewhere between sample index 3 and index 4 and the sample is interpolated from sample
* indexes 0 - 7, therefore the uninterpolated sample that immediately precedes the current sample is
* located at index 3.
*/
public Complex getPrecedingSample()
{
mPrecedingSample.setValues(mDelayLineInphase[mDelayLinePointer + 4], mDelayLineQuadrature[mDelayLinePointer + 3]);
mPrecedingSample.setValues(mDelayLineInphase[mDelayLinePointer + 3], mDelayLineQuadrature[mDelayLinePointer + 3]);
return mPrecedingSample;
}
/**
* Interpolated middle sample for the symbol. Note: this method should only be invoked after testing for a
* complete symbol with the hasSymbol() method.
* Interpolated current sample for the symbol.
*
* Note: this method should only be invoked after testing for a complete symbol with the hasSymbol() method.
*/
public Complex getCurrentSample()
{
@@ -145,6 +151,21 @@ public class InterpolatingSampleBuffer
return mCurrentSample;
}
/**
* Interpolated sample that is 1/2 symbol away from (after) the current sample.
*
* Note: this method should only be invoked after testing for a complete symbol with the hasSymbol() method.
*/
public Complex getMiddleSample()
{
float halfDetectedSamplesPerSymbol = mDetectedSamplesPerSymbol / 2.0f;
//Interpolated sample that is half a symbol away from (occurred before) the current sample.
mMiddleSample.setValues(getInphase(halfDetectedSamplesPerSymbol),
getQuadrature(halfDetectedSamplesPerSymbol));
return mMiddleSample;
}
/**
* Returns the interpolated inphase value for the specified offset
* @param interpolation into the buffer to calculate the interpolated sample
@@ -152,7 +173,15 @@ public class InterpolatingSampleBuffer
*/
public float getInphase(float interpolation)
{
return mInterpolator.filter(mDelayLineInphase, mDelayLinePointer + 1, interpolation);
if(interpolation < 1.0f)
{
return mInterpolator.filter(mDelayLineInphase, mDelayLinePointer, interpolation);
}
else
{
int offset = (int)Math.floor(interpolation);
return mInterpolator.filter(mDelayLineInphase, mDelayLinePointer + offset, interpolation - offset);
}
}
/**
@@ -162,6 +191,14 @@ public class InterpolatingSampleBuffer
*/
public float getQuadrature(float interpolation)
{
return mInterpolator.filter(mDelayLineQuadrature, mDelayLinePointer + 1, interpolation);
if(interpolation < 1.0f)
{
return mInterpolator.filter(mDelayLineQuadrature, mDelayLinePointer, interpolation);
}
else
{
int offset = (int)Math.floor(interpolation);
return mInterpolator.filter(mDelayLineQuadrature, mDelayLinePointer + offset, interpolation - offset);
}
}
}