P25 - enhancement for LSM demod phase lock errors - adds new sync pattern detectors to detect Costas Loop phase lock errors and apply immediate correction to enable accurate symbol slicing.

This commit is contained in:
dennis.sheirer
2015-04-26 16:58:25 +00:00
parent c12123a81b
commit 2c4b3ab1b5
11 changed files with 376 additions and 72 deletions

View File

@@ -76,6 +76,8 @@ public class CQPSKDemodulator implements Instrumentable,
private GardnerSymbolTiming mGardnerDetector = new GardnerSymbolTiming();
private CostasLoop mCostasLoop = new CostasLoop();
private FrequencyChangeListener mFrequencyChangeListener;
private EyeDiagramDataTap mEyeDiagramDataTap;
@@ -90,6 +92,17 @@ public class CQPSKDemodulator implements Instrumentable,
mGardnerDetector.receive( sample );
}
/**
* Applies a phase correction value to the costas loop to correct when a
* phase lock error is detected in the binary output stream.
*
* @param correction - value in radians
*/
public void correctPhaseError( double correction )
{
mCostasLoop.correctPhaseError( correction );
}
/**
* Constrains value to the range of ( -maximum <> maximum )
*/
@@ -207,7 +220,7 @@ public class CQPSKDemodulator implements Instrumentable,
/* Sampling point */
private float mMu = 10.0f;
private float mGainMu = 0.25f;
private float mGainMu = 0.1f;
/* Samples per symbol */
private float mOmega = 10.0f;
@@ -215,8 +228,6 @@ public class CQPSKDemodulator implements Instrumentable,
private float mOmegaRel = 0.005f;
private float mOmegaMid = 10.0f;
private CostasLoop mCostasLoop = new CostasLoop();
private QPSKInterpolator mInterpolator = new QPSKInterpolator( 1.0f );
private ComplexSample mPreviousSample = new ComplexSample( 0.0f, 0.0f );
@@ -347,7 +358,7 @@ public class CQPSKDemodulator implements Instrumentable,
public static final double TWO_PI = 2.0 * Math.PI;
private static final float MAXIMUM_FREQUENCY =
( 1200.0f * (float)TWO_PI ) / 48000.0f;
( 2400.0f * (float)TWO_PI ) / 48000.0f;
/* http://www.trondeau.com/blog/2011/8/13/control-loop-gain-values.html */
private float mDamping = (float)Math.sqrt( 2.0 ) / 2.0f;
@@ -374,6 +385,33 @@ public class CQPSKDemodulator implements Instrumentable,
{
}
/**
* Applies a phase correction value to the current phasor. Use this
* method to apply correction when a +/- 90, or 180 degree phase error
* is detected in the binary output stream.
*
* If the supplied correction value places the loop frequency outside
* of the max frequency, then the frequency will be corrected 360
* degrees in the opposite direction to maintain within the max
* frequency bounds.
*
* @param correction - correction value in radians
*/
public void correctPhaseError( double correction )
{
mLoopFrequency += correction;
if( mLoopFrequency > MAXIMUM_FREQUENCY )
{
mLoopFrequency -= 2.0d * MAXIMUM_FREQUENCY;
}
if( mLoopFrequency < -MAXIMUM_FREQUENCY )
{
mLoopFrequency += 2.0d * MAXIMUM_FREQUENCY;
}
}
/**
* Increments the phase of the loop
*/

View File

@@ -13,9 +13,9 @@ public class QPSKStarSlicer implements Listener<ComplexSample>
* Slices a ComplexSample representing a phase shifted symbol according to
* the following constellation pattern:
*
* 11 | 01
* 00 | 01
* ---|---
* 10 | 00
* 10 | 11
*/
public QPSKStarSlicer()
{

View File

@@ -2,8 +2,10 @@ package dsp.symbol;
public enum FrameSync
{
P25_PHASE1( 0x5575F5FF77FFl ), //+3 +3 +3 +3 +3 -3 +3 +3 -3 -3 +3 +3 -3 -3 -3 -3 +3 -3 +3 -3 -3 -3 -3 -3
P25_PHASE1_INVERTED( 0xFFDF5F55DD55l );
P25_PHASE1_ERROR_90_CCW( 0xFFEFAFAAEEAAl ),
P25_PHASE1_NORMAL( 0x5575F5FF77FFl ), // +33333 -3 +33 -33 +33 -3333 +3 -3 +3 -33333
P25_PHASE1_ERROR_90_CW( 0x001050551155l ),
P25_PHASE1_ERROR_180( 0xAA8A0A008800l );
private long mSync;