Improved LTR FSK decoder for LTR, LTR-Net and Passport decoders. Added IIR DC blocking filter and used improved slicer from the FSK decoder.

Added instrumentation to Passport decoder and updated some of the instrumentation components.
This commit is contained in:
dennis.sheirer
2014-05-01 23:24:51 +00:00
parent d7115f2886
commit da1db8a804
25 changed files with 803 additions and 496 deletions

View File

@@ -17,84 +17,50 @@
******************************************************************************/
package dsp.filter;
import java.util.Arrays;
import java.util.BitSet;
import sample.Listener;
/**
* Averages (low pass filter) boolean values over the defined length
* Averages (low pass filter) boolean values over the defined size
*/
public class BooleanAveragingFilter implements Listener<Boolean>
{
private boolean[] mBuffer;
private BitSet mBuffer = new BitSet();
private int mBufferPointer;
private int mBufferLength;
private int mThreshold;
private Listener<Boolean> mListener;
public BooleanAveragingFilter( int length )
{
mBuffer = new boolean[ length ];
if( length % 2 == 0 )
mBufferLength = length;
/* Round up */
mThreshold = (int)( length / 2) + ( length % 2 );
}
public void receive( Boolean value )
{
if( value )
{
mThreshold = (int)( length /2 );
mBuffer.set( mBufferPointer );
}
else
{
mThreshold = (int)( ( length + 1 ) / 2 );
mBuffer.clear( mBufferPointer );
}
//Preload the array with false values
Arrays.fill( mBuffer, false );
}
/**
* Loads the newValue into this buffer and adjusts the buffer pointer
* to prepare for the next get/put cycle
*/
public void put( boolean newValue )
{
//Store the new value to the buffer
mBuffer[ mBufferPointer ] = newValue;
//Increment the buffer pointer
mBufferPointer++;
//Wrap the buffer pointer around to 0 when necessary
if( mBufferPointer >= mBuffer.length )
mBufferPointer++;
if( mBufferPointer >= mBufferLength )
{
mBufferPointer = 0;
}
}
/**
* Loads the newValue into the buffer, calculates the average
* and returns that average from this method
*
* This effectively performs low-pass filtering
*/
public void receive( Boolean newValue )
{
//Load the new value into the buffer
put( newValue );
int trueCount = 0;
for( int x = 0; x < mBuffer.length; x++ )
{
if( mBuffer[ x ] )
{
trueCount++;
}
}
/**
* If the number of true values in the buffer is
* more than half, send true, otherwise, false
*/
if( mListener != null )
{
mListener.receive( trueCount >= mThreshold );
mListener.receive( mBuffer.cardinality() >= mThreshold );
}
}
@@ -103,7 +69,7 @@ public class BooleanAveragingFilter implements Listener<Boolean>
mListener = listener;
}
public void clearListener()
public void removeListener( Listener<Boolean> listener )
{
mListener = null;
}

View File

@@ -0,0 +1,45 @@
package dsp.filter;
import sample.Listener;
public class DCRemovalFilter3 implements Listener<Float>
{
private float mAlpha;
private float mPreviousInput = 0.0f;
private float mPreviousOutput = 0.0f;
private Listener<Float> mListener;
/**
* IIR single-pole DC removal filter, as described by J M de Freitas in
* 29Jan2007 paper at:
*
* http://www.mathworks.com/matlabcentral/fileexchange/downloads/72134/download
*
* @param alpha 0.0 - 1.0 float - the closer alpha is to unity, the closer
* the cutoff frequency is to DC.
*/
public DCRemovalFilter3( float alpha )
{
mAlpha = alpha;
}
@Override
public void receive( Float currentInput )
{
float currentOutput = ( currentInput - mPreviousInput ) +
( mAlpha * mPreviousOutput );
if( mListener != null )
{
mListener.receive( currentOutput );
}
mPreviousInput = currentInput;
mPreviousOutput = currentOutput;
}
public void setListener( Listener<Float> listener )
{
mListener = listener;
}
}

View File

@@ -0,0 +1,103 @@
package dsp.filter;
import java.util.BitSet;
import sample.Listener;
public class LTRPulseShapingFilter implements Listener<Boolean>
{
private int[][] mIndexes = { { 0, 1, 2, 3, 4 },
{ 1, 2, 3, 4, 0 },
{ 2, 3, 4, 0, 1 },
{ 3, 4, 0, 1, 2 },
{ 4, 0, 1, 2, 3 } };
private BitSet mBuffer;
private int mBufferPointer = 0;
private Listener<Boolean> mListener;
/**
* Specialized pulse shaping filter that detects a weak 0 or 1 pulse that
* is characterized by two consecutive values, true or false, within a
* sequence of five boolean values where the remainder are the opposite
* value, and elongates that weak pulse to be three consecutive values,
* which is enough to cause the slicer to render a correct value.
*/
public LTRPulseShapingFilter()
{
mBuffer = new BitSet();
mBuffer.clear();
}
@Override
public void receive( Boolean current )
{
boolean previous = mBuffer.get( mBufferPointer );
if( current )
{
mBuffer.set( mBufferPointer );
}
else
{
mBuffer.clear( mBufferPointer );
}
mBufferPointer++;
if( mBufferPointer >= 5 )
{
mBufferPointer = 0;
}
/* Check for weak positive pulse*/
if( mBuffer.cardinality() == 2 )
{
if( mBuffer.get( mIndexes[ mBufferPointer ][ 1 ] ) &&
mBuffer.get( mIndexes[ mBufferPointer ][ 2 ] ) )
{
mBuffer.set( mIndexes[ mBufferPointer][ 3 ] );
}
}
/* Or, a weak negative pulse */
else if( mBuffer.cardinality() == 3 )
{
if( !mBuffer.get( mIndexes[ mBufferPointer][ 1 ] ) &&
!mBuffer.get( mIndexes[ mBufferPointer][ 2 ] ) )
{
mBuffer.clear( mIndexes[ mBufferPointer][ 3 ] );
}
}
if( mListener != null )
{
mListener.receive( previous );
}
}
public String getIndexSet( int pointer )
{
StringBuilder sb = new StringBuilder();
sb.append( "[" );
for( int x = 0; x < 5; x++ )
{
sb.append( mIndexes[ pointer ][ x ] );
sb.append( "," );
}
sb.append( "[" );
return sb.toString();
}
public void setListener( Listener<Boolean> listener )
{
mListener = listener;
}
public void removeListener( Listener<Boolean> listener )
{
mListener = null;
}
}

View File

@@ -35,7 +35,7 @@ public class SquaringFilter implements Listener<Float>
{
if( mListener != null )
{
mListener.receive( ( sample >= 0 ? true : false ) );
mListener.receive( sample >= 0 );
}
}