mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
P25 LSM decoder work in progress. Adds a CQPSK decoder based on Max's (KA1RBI) scope.py and gardner loop.
The CQPSK decoder is starting to take shape, but needs more tweaking and testing. It's not keeping a good lock on strong P25 signals. I have to add some more features to the intrumentation package to allow me to visualize the internals of the CQPSK decoder so that I can get a better sense of what needs fine tuning. The CQPSK decoder may work for anyone that wants to sync the repo and run the build script.
This commit is contained in:
@@ -19,13 +19,19 @@ package sample.complex;
|
||||
|
||||
import java.io.Serializable;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* ComplexSample for handling left/right channel audio, or inphase/quadrature
|
||||
* samples, etc.
|
||||
*/
|
||||
public class ComplexSample implements Serializable
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ComplexSample.class );
|
||||
|
||||
private static final long serialVersionUID = 1L;
|
||||
|
||||
private float mLeft;
|
||||
private float mRight;
|
||||
@@ -35,6 +41,11 @@ public class ComplexSample implements Serializable
|
||||
mLeft = left;
|
||||
mRight = right;
|
||||
}
|
||||
|
||||
public ComplexSample()
|
||||
{
|
||||
this( 0.0f, 0.0f );
|
||||
}
|
||||
|
||||
public ComplexSample copy()
|
||||
{
|
||||
@@ -43,7 +54,14 @@ public class ComplexSample implements Serializable
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return "I:" + mLeft + " Q:" + mRight;
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "I:" );
|
||||
sb.append( mLeft );
|
||||
sb.append( " Q:" );
|
||||
sb.append( mRight );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -78,6 +96,9 @@ public class ComplexSample implements Serializable
|
||||
mRight = quadrature;
|
||||
}
|
||||
|
||||
/**
|
||||
* Multiplies both samples returning a new sample with the results
|
||||
*/
|
||||
public static ComplexSample multiply( ComplexSample sample1,
|
||||
ComplexSample sample2 )
|
||||
{
|
||||
@@ -91,16 +112,16 @@ public class ComplexSample implements Serializable
|
||||
}
|
||||
|
||||
public static ComplexSample multiply( ComplexSample sample,
|
||||
Float left, Float right )
|
||||
Float inphase, Float quadrature )
|
||||
{
|
||||
float l = ( sample.left() * left ) - ( sample.right() * right );
|
||||
float r = ( sample.right() * left ) + ( sample.left() * right );
|
||||
float i = ( sample.inphase() * inphase ) - ( sample.quadrature() * quadrature );
|
||||
float q = ( sample.quadrature() * inphase ) + ( sample.inphase() * quadrature );
|
||||
|
||||
return new ComplexSample( l, r );
|
||||
return new ComplexSample( i, q );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the adder sample values to this sample
|
||||
* Adds the adder sample value to this sample
|
||||
*/
|
||||
public void add( ComplexSample adder )
|
||||
{
|
||||
@@ -108,6 +129,24 @@ public class ComplexSample implements Serializable
|
||||
mRight += adder.right();
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the two complex samples returning a new complex sample with the result
|
||||
*/
|
||||
public static ComplexSample add( ComplexSample first, ComplexSample second )
|
||||
{
|
||||
return new ComplexSample( first.left() + second.left(),
|
||||
first.right() + second.right() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds the two complex samples returning a new complex sample with the result
|
||||
*/
|
||||
public static ComplexSample subtract( ComplexSample first, ComplexSample second )
|
||||
{
|
||||
return new ComplexSample( first.left() - second.left(),
|
||||
first.right() - second.right() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Magnitude of this sample
|
||||
*/
|
||||
@@ -130,7 +169,12 @@ public class ComplexSample implements Serializable
|
||||
*/
|
||||
public void normalize()
|
||||
{
|
||||
multiply( (float)( 1.0f / magnitude() ) );
|
||||
float magnitude = magnitude();
|
||||
|
||||
if( magnitude != 0 )
|
||||
{
|
||||
multiply( (float)( 1.0f / magnitude() ) );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -176,12 +220,28 @@ public class ComplexSample implements Serializable
|
||||
{
|
||||
return mLeft;
|
||||
}
|
||||
|
||||
public float imaginery()
|
||||
|
||||
/**
|
||||
* Absolute value of real component
|
||||
*/
|
||||
public float realAbsolute()
|
||||
{
|
||||
return Math.abs( mLeft );
|
||||
}
|
||||
|
||||
public float imaginary()
|
||||
{
|
||||
return mRight;
|
||||
}
|
||||
|
||||
/**
|
||||
* Absolute value of imaginary component
|
||||
*/
|
||||
public float imaginaryAbsolute()
|
||||
{
|
||||
return Math.abs( mRight );
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the greater absolute value between left and right values
|
||||
*/
|
||||
@@ -208,4 +268,18 @@ public class ComplexSample implements Serializable
|
||||
return new ComplexSample( (float)Math.cos( angle ),
|
||||
(float)Math.sin( angle ) );
|
||||
}
|
||||
|
||||
public float angle()
|
||||
{
|
||||
return (float)Math.atan2( y(), x() );
|
||||
}
|
||||
|
||||
public static void main( String[] args )
|
||||
{
|
||||
ComplexSample sample1 = new ComplexSample( .45f, .45f );
|
||||
ComplexSample sample2 = new ComplexSample( .25f, .25f );
|
||||
ComplexSample sample1_2 = ComplexSample.subtract( sample1, sample2 );
|
||||
|
||||
mLog.debug( sample1_2.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user