mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-13 00:57:31 -05:00
Work in progress.
-Started work on new channel editor channel viewer/controller -Removed a number of unused buffer package classes -Moved automatic frequency control to be a module and removed special handling -Added IUnfilteredRealBufferListener & Provider interfaces -Completely removed the ResourceManager class
This commit is contained in:
@@ -16,12 +16,13 @@ import sample.Listener;
|
||||
import sample.real.RealBuffer;
|
||||
import sample.real.RealSampleListener;
|
||||
import sample.real.RealSampleProvider;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl.FrequencyCorrectionResetListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Event;
|
||||
import source.tuner.frequency.IFrequencyChangeListener;
|
||||
import dsp.gain.DirectGainControl;
|
||||
|
||||
public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
Listener<RealBuffer>,
|
||||
public class C4FMSymbolFilter implements Listener<RealBuffer>,
|
||||
IFrequencyChangeListener,
|
||||
RealSampleProvider,
|
||||
Instrumentable
|
||||
{
|
||||
@@ -201,15 +202,17 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
private float mHistory[] = new float[ NUMBER_FILTER_TAPS ];
|
||||
private int mHistoryLast = 0;
|
||||
|
||||
private boolean mResetFrequencyTracker = false;
|
||||
|
||||
private RealSampleListener mListener;
|
||||
|
||||
private DirectGainControl mGainController =
|
||||
new DirectGainControl( 15.0f, 0.1f, 35.0f, 0.3f );
|
||||
|
||||
private FrequencyCorrectionControl mFrequencyCorrectionControl;
|
||||
private int mFrequencyAdjustmentRequested = 0;
|
||||
private int mFrequencyCorrection = 0;
|
||||
private int mFrequencyCorrectionMaximum = 3000;
|
||||
private boolean mResetFrequencyTracker = false;
|
||||
private FrequencyCorrectionProcessor mFrequencyCorrectionProcessor;
|
||||
private Listener<FrequencyChangeEvent> mFrequencyChangeListener;
|
||||
|
||||
/**
|
||||
* C4FM Symbol Filter
|
||||
@@ -224,18 +227,15 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
* setting for this filter is 15.4 and that yields a symbol spread that
|
||||
* is centered on 2.0, ranging 1.92 to 2.08.
|
||||
*/
|
||||
public C4FMSymbolFilter( FrequencyCorrectionControl frequencyControl )
|
||||
public C4FMSymbolFilter( int frequencyCorrectionMaximum )
|
||||
{
|
||||
mFrequencyCorrectionControl = frequencyControl;
|
||||
|
||||
/* Register for reset events, so we can reset internal frequency tracking */
|
||||
mFrequencyCorrectionControl.setListener( this );
|
||||
mFrequencyCorrectionMaximum = frequencyCorrectionMaximum;
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mGainController = null;
|
||||
mFrequencyCorrectionControl = null;
|
||||
// mFrequencyCorrectionControl = null;
|
||||
mListener = null;
|
||||
}
|
||||
|
||||
@@ -253,13 +253,21 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
* the internal frequency correction tracker */
|
||||
if( mFrequencyAdjustmentRequested != 0 )
|
||||
{
|
||||
mFrequencyCorrectionControl.adjust( mFrequencyAdjustmentRequested );
|
||||
int correction = mFrequencyCorrection + mFrequencyAdjustmentRequested;
|
||||
|
||||
if( correction > mFrequencyCorrectionMaximum )
|
||||
{
|
||||
correction = mFrequencyCorrectionMaximum;
|
||||
}
|
||||
else if( correction < -mFrequencyCorrectionMaximum )
|
||||
{
|
||||
correction = -mFrequencyCorrectionMaximum;
|
||||
}
|
||||
|
||||
broadcast( new FrequencyChangeEvent(
|
||||
Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, correction ) );
|
||||
|
||||
mFrequencyAdjustmentRequested = 0;
|
||||
|
||||
//Reset internal frequency tracking
|
||||
mCoarseFrequencyCorrection = 0.0f;
|
||||
mFineFrequencyCorrection = 0.0f;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -272,7 +280,8 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
mCoarseFrequencyCorrection = 0.0f;
|
||||
mFineFrequencyCorrection = 0.0f;
|
||||
|
||||
mFrequencyCorrectionControl.setFrequencyCorrection( 0 );
|
||||
broadcast( new FrequencyChangeEvent(
|
||||
Event.REQUEST_CHANNEL_FREQUENCY_CORRECTION_CHANGE, 0 ));
|
||||
|
||||
mResetFrequencyTracker = false;
|
||||
}
|
||||
@@ -397,17 +406,6 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener interface for frequency correction reset events. We reset the
|
||||
* coarse and fine frequency control values when the tuner channel source
|
||||
* has changed frequency (PPM) or sample rate
|
||||
*/
|
||||
@Override
|
||||
public void resetFrequencyCorrection()
|
||||
{
|
||||
mResetFrequencyTracker = true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener( RealSampleListener listener )
|
||||
{
|
||||
@@ -459,4 +457,56 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener,
|
||||
mSymbolSpreadTap = null;
|
||||
}
|
||||
}
|
||||
|
||||
public void broadcast( FrequencyChangeEvent event )
|
||||
{
|
||||
if( mFrequencyChangeListener != null )
|
||||
{
|
||||
mFrequencyChangeListener.receive( event );
|
||||
}
|
||||
}
|
||||
|
||||
public void setFrequencyChangeListener( Listener<FrequencyChangeEvent> listener )
|
||||
{
|
||||
mFrequencyChangeListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<FrequencyChangeEvent> getFrequencyChangeListener()
|
||||
{
|
||||
if( mFrequencyCorrectionProcessor == null )
|
||||
{
|
||||
mFrequencyCorrectionProcessor = new FrequencyCorrectionProcessor();
|
||||
}
|
||||
|
||||
return mFrequencyCorrectionProcessor;
|
||||
}
|
||||
|
||||
/**
|
||||
* Receives notifications that the channel frequency correction has been
|
||||
* applied and updates internal tracking value.
|
||||
*/
|
||||
public class FrequencyCorrectionProcessor implements Listener<FrequencyChangeEvent>
|
||||
{
|
||||
@Override
|
||||
public void receive( FrequencyChangeEvent event )
|
||||
{
|
||||
switch( event.getEvent() )
|
||||
{
|
||||
case NOTIFICATION_CHANNEL_FREQUENCY_CORRECTION_CHANGE:
|
||||
mFrequencyCorrection = event.getValue().intValue();
|
||||
|
||||
//Reset internal frequency tracking
|
||||
mCoarseFrequencyCorrection = 0.0f;
|
||||
mFineFrequencyCorrection = 0.0f;
|
||||
break;
|
||||
case NOTIFICATION_FREQUENCY_CORRECTION_CHANGE:
|
||||
case NOTIFICATION_SAMPLE_RATE_CHANGE:
|
||||
mResetFrequencyTracker = true;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,8 +34,8 @@ import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceEditor;
|
||||
import source.tuner.TunerEditor;
|
||||
import controller.Editor;
|
||||
import controller.channel.ChannelValidationException;
|
||||
import controller.channel.ChannelConfigurationEditor;
|
||||
import controller.channel.ConfigurationValidationException;
|
||||
|
||||
public class P25DecodeEditor extends DecodeEditor
|
||||
{
|
||||
@@ -101,29 +101,29 @@ public class P25DecodeEditor extends DecodeEditor
|
||||
add( new JLabel( "Ignore Data Calls" ) );
|
||||
add( mIgnoreDataCalls, "wrap,grow" );
|
||||
|
||||
reset();
|
||||
// reset();
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforce source=tuner for CQPSK modulation
|
||||
*/
|
||||
@Override
|
||||
public void validate( Editor editor ) throws ChannelValidationException
|
||||
{
|
||||
if( editor instanceof SourceEditor &&
|
||||
((DecodeConfigP25Phase1)mConfig).getModulation() == Modulation.CQPSK )
|
||||
{
|
||||
if( !( editor instanceof TunerEditor ) )
|
||||
{
|
||||
throw new ChannelValidationException(
|
||||
"<html><body width='175'><h1>LSM Simulcast</h1>"
|
||||
+ "<p>P25 LSM Simulcast decoder can only be used with "
|
||||
+ "a tuner source. Please change the Source to use a tuner"
|
||||
+ " or change the P25 Decoder to C4FM modulation" );
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
// /**
|
||||
// * Enforce source=tuner for CQPSK modulation
|
||||
// */
|
||||
// @Override
|
||||
// public void validate( ChannelConfigurationEditor editor ) throws ConfigurationValidationException
|
||||
// {
|
||||
// if( editor instanceof SourceEditor &&
|
||||
// ((DecodeConfigP25Phase1)mConfig).getModulation() == Modulation.CQPSK )
|
||||
// {
|
||||
// if( !( editor instanceof TunerEditor ) )
|
||||
// {
|
||||
// throw new ConfigurationValidationException(
|
||||
// "<html><body width='175'><h1>LSM Simulcast</h1>"
|
||||
// + "<p>P25 LSM Simulcast decoder can only be used with "
|
||||
// + "a tuner source. Please change the Source to use a tuner"
|
||||
// + " or change the P25 Decoder to C4FM modulation" );
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
|
||||
@Override
|
||||
public void save()
|
||||
@@ -135,13 +135,13 @@ public class P25DecodeEditor extends DecodeEditor
|
||||
config.setTrafficChannelPoolSize( mTrafficChannelPoolSize.getValue() );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void reset()
|
||||
{
|
||||
DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
|
||||
|
||||
mComboModulation.setSelectedItem( config.getModulation() );
|
||||
mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() );
|
||||
mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() );
|
||||
}
|
||||
// @Override
|
||||
// public void reset()
|
||||
// {
|
||||
// DecodeConfigP25Phase1 config = (DecodeConfigP25Phase1)mConfig;
|
||||
//
|
||||
// mComboModulation.setSelectedItem( config.getModulation() );
|
||||
// mIgnoreDataCalls.setSelected( config.getIgnoreDataCalls() );
|
||||
// mTrafficChannelPoolSize.setValue( config.getTrafficChannelPoolSize() );
|
||||
// }
|
||||
}
|
||||
|
||||
@@ -3,11 +3,9 @@ package module.decode.p25;
|
||||
import instrument.Instrumentable;
|
||||
import module.decode.Decoder;
|
||||
import module.decode.DecoderType;
|
||||
import source.tuner.frequency.IFrequencyCorrectionController;
|
||||
import alias.AliasList;
|
||||
|
||||
public abstract class P25Decoder extends Decoder
|
||||
implements IFrequencyCorrectionController, Instrumentable
|
||||
public abstract class P25Decoder extends Decoder implements Instrumentable
|
||||
{
|
||||
private P25MessageProcessor mMessageProcessor;
|
||||
|
||||
|
||||
@@ -24,22 +24,24 @@ import instrument.tap.stream.FloatBufferTap;
|
||||
import instrument.tap.stream.FloatTap;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.real.IRealBufferListener;
|
||||
import sample.real.IFilteredRealBufferListener;
|
||||
import sample.real.RealBuffer;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.IFrequencyChangeListener;
|
||||
import source.tuner.frequency.IFrequencyChangeProvider;
|
||||
import alias.AliasList;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
import dsp.filter.fir.real.RealFIRFilter_RB_RB;
|
||||
|
||||
public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
public class P25_C4FMDecoder extends P25Decoder
|
||||
implements IFrequencyChangeListener, IFrequencyChangeProvider,IFilteredRealBufferListener
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger( P25_C4FMDecoder.class );
|
||||
|
||||
@@ -48,11 +50,8 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
private static final String INSTRUMENT_C4FM_SYMBOL_FILTER_OUTPUT = "Tap Point: Symbol Filter Output";
|
||||
private static final String INSTRUMENT_C4FM_SLICER_OUTPUT = "Tap Point: C4FM Slicer Output";
|
||||
|
||||
private final static int MAXIMUM_FREQUENCY_CORRECTION = 3000; //Hertz, +/-
|
||||
|
||||
private List<TapGroup> mAvailableTaps;
|
||||
private RealFIRFilter_RB_RB mC4FMPreFilter;
|
||||
private FrequencyCorrectionControl mFrequencyCorrectionControl;
|
||||
private C4FMSymbolFilter mSymbolFilter;
|
||||
private C4FMSlicer mC4FMSlicer;
|
||||
private P25MessageFramer mMessageFramer;
|
||||
@@ -70,23 +69,18 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
* infrastructure and subscriber identities that will be included in each
|
||||
* decoded message
|
||||
*/
|
||||
public P25_C4FMDecoder( AliasList aliasList )
|
||||
public P25_C4FMDecoder( AliasList aliasList, int frequencyCorrectionMaximum )
|
||||
{
|
||||
super( aliasList );
|
||||
|
||||
/* Filter demodulated sample buffers */
|
||||
float[] filter = FilterFactory.getLowPass( 48000, 2500, 4000, 80, WindowType.HANNING, true );
|
||||
|
||||
mLog.debug( "Demod Filter tap count:" + filter.length + " coefficients:" + Arrays.toString( filter ) );
|
||||
// mLog.debug( "Demod Filter tap count:" + filter.length + " coefficients:" + Arrays.toString( filter ) );
|
||||
mC4FMPreFilter = new RealFIRFilter_RB_RB( filter, 1.0f );
|
||||
|
||||
/* Issue tuned frequency correction commands, remotely controlled by the
|
||||
* downstream symbol filter */
|
||||
mFrequencyCorrectionControl = new FrequencyCorrectionControl(
|
||||
MAXIMUM_FREQUENCY_CORRECTION );
|
||||
|
||||
/* Shape gain and frequency offsets to optimize sample stream */
|
||||
mSymbolFilter = new C4FMSymbolFilter( mFrequencyCorrectionControl );
|
||||
mSymbolFilter = new C4FMSymbolFilter( frequencyCorrectionMaximum );
|
||||
mC4FMPreFilter.setListener( mSymbolFilter );
|
||||
|
||||
/* Convert samples to symbols */
|
||||
@@ -109,9 +103,6 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
mC4FMPreFilter.dispose();
|
||||
mC4FMPreFilter = null;
|
||||
|
||||
mFrequencyCorrectionControl.dispose();
|
||||
mFrequencyCorrectionControl = null;
|
||||
|
||||
mSymbolFilter.dispose();
|
||||
mSymbolFilter = null;
|
||||
|
||||
@@ -128,19 +119,7 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFrequencyCorrectionControl()
|
||||
{
|
||||
return mFrequencyCorrectionControl != null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrequencyCorrectionControl getFrequencyCorrectionControl()
|
||||
{
|
||||
return mFrequencyCorrectionControl;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<RealBuffer> getRealBufferListener()
|
||||
public Listener<RealBuffer> getFilteredRealBufferListener()
|
||||
{
|
||||
return mC4FMPreFilter;
|
||||
}
|
||||
@@ -262,4 +241,33 @@ public class P25_C4FMDecoder extends P25Decoder implements IRealBufferListener
|
||||
// TODO Auto-generated method stub
|
||||
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setFrequencyChangeListener( Listener<FrequencyChangeEvent> listener )
|
||||
{
|
||||
if( mSymbolFilter != null )
|
||||
{
|
||||
mSymbolFilter.setFrequencyChangeListener( listener );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeFrequencyChangeListener()
|
||||
{
|
||||
if( mSymbolFilter != null )
|
||||
{
|
||||
mSymbolFilter.setFrequencyChangeListener( null );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Listener<FrequencyChangeEvent> getFrequencyChangeListener()
|
||||
{
|
||||
if( mSymbolFilter != null )
|
||||
{
|
||||
return mSymbolFilter.getFrequencyChangeListener();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -34,7 +34,6 @@ import sample.Listener;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import sample.complex.ComplexBufferToStreamConverter;
|
||||
import sample.complex.IComplexBufferListener;
|
||||
import source.tuner.frequency.FrequencyCorrectionControl;
|
||||
import alias.AliasList;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
@@ -119,18 +118,6 @@ public class P25_LSMDecoder extends P25Decoder implements IComplexBufferListener
|
||||
return Modulation.CQPSK;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean hasFrequencyCorrectionControl()
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FrequencyCorrectionControl getFrequencyCorrectionControl()
|
||||
{
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Provides a list of instrumentation taps for monitoring internal processing
|
||||
*/
|
||||
|
||||
Reference in New Issue
Block a user