From 9c305b0732072163575f8e3090f3ebcf8c7c91c1 Mon Sep 17 00:00:00 2001 From: denny Date: Thu, 31 Dec 2015 09:08:26 -0500 Subject: [PATCH] Resolves issue with AFC and frequency change event handling, specifically for P25 C4FM frequency tracking. -Clarifies frequency change event naming and adds request/notitification events for channel frequency correction type events -Removes DC offset filter from P25 C4FM demodulator which was operating independently of the AFC tracking component within the C4FM symbol filter. -Changed FCD tuner center DC spike buffer size after detecting that the DC center spike was influencing the P25 C4FM filter frequency tracker whenever the tuner's center frequency was changed to bring the channel boundary within 3 kHz of the center spike -- set it to 5 kHz to provide a better buffer. -Updated spectral channel display to provide better indication of automatic frequency control (yellow line) versus channel frequency --- src/gui/control/JFrequencyControl.java | 6 +- src/module/decode/DecoderFactory.java | 2 +- src/module/decode/p25/C4FMSymbolFilter.java | 32 ++++---- src/source/recording/Recording.java | 4 +- src/source/tuner/Tuner.java | 8 +- src/source/tuner/TunerChannelSource.java | 81 +++++++++++-------- src/source/tuner/TunerNode.java | 6 +- .../tuner/airspy/AirspyTunerEditorPanel.java | 4 +- src/source/tuner/fcd/FCDTunerController.java | 2 +- .../tuner/fcd/proV1/FCD1TunerEditorPanel.java | 4 +- .../fcd/proplusV2/FCD2TunerEditorPanel.java | 4 +- .../AutomaticFrequencyControl_R.java | 4 +- .../AutomaticFrequencyControl_RB.java | 4 +- .../tuner/frequency/FrequencyChangeEvent.java | 22 ++--- .../tuner/frequency/FrequencyController.java | 26 +++--- .../frequency/FrequencyCorrectionControl.java | 57 +++++++------ .../tuner/hackrf/HackRFTunerEditorPanel.java | 4 +- .../tuner/rtl/RTL2832TunerController.java | 10 +-- .../tuner/rtl/e4k/E4KTunerEditorPanel.java | 4 +- .../rtl/r820t/R820TTunerEditorPanel.java | 4 +- src/spectrum/ChannelSpectrumPanel.java | 4 +- src/spectrum/DFTProcessor.java | 6 +- src/spectrum/OverlayPanel.java | 53 +++++++----- src/spectrum/SpectralDisplayPanel.java | 6 +- 24 files changed, 191 insertions(+), 166 deletions(-) diff --git a/src/gui/control/JFrequencyControl.java b/src/gui/control/JFrequencyControl.java index 66a7d1c1..a413e11f 100644 --- a/src/gui/control/JFrequencyControl.java +++ b/src/gui/control/JFrequencyControl.java @@ -45,7 +45,7 @@ import org.slf4j.LoggerFactory; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; public class JFrequencyControl extends JPanel implements FrequencyChangeListener { @@ -136,7 +136,7 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { setFrequency( event.getValue().longValue(), false ); } @@ -180,7 +180,7 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener Iterator it = mListeners.iterator(); FrequencyChangeEvent event = - new FrequencyChangeEvent( Attribute.FREQUENCY, mFrequency ); + new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, mFrequency ); while( it.hasNext() ) { diff --git a/src/module/decode/DecoderFactory.java b/src/module/decode/DecoderFactory.java index 8c50153e..59d2f3d3 100644 --- a/src/module/decode/DecoderFactory.java +++ b/src/module/decode/DecoderFactory.java @@ -256,7 +256,7 @@ public class DecoderFactory switch( modulation ) { case C4FM: - modules.add( getFMDemodulator( decodeConfig, 6750, 7500, REMOVE_DC ) ); + modules.add( getFMDemodulator( decodeConfig, 6750, 7500, NO_REMOVE_DC ) ); modules.add( new P25_C4FMDecoder( aliasList ) ); modules.add( new P25DecoderState( aliasList, channelType, Modulation.C4FM, p25Config.getIgnoreDataCalls() ) ); diff --git a/src/module/decode/p25/C4FMSymbolFilter.java b/src/module/decode/p25/C4FMSymbolFilter.java index 17be10ac..7494b2f9 100644 --- a/src/module/decode/p25/C4FMSymbolFilter.java +++ b/src/module/decode/p25/C4FMSymbolFilter.java @@ -188,7 +188,7 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, /* Frequency correction broadcast threshold */ // private static final double COARSE_FREQUENCY_DEADBAND = 1.66; - private static final double COARSE_FREQUENCY_DEADBAND = 1.20; + private static final double COARSE_FREQUENCY_THRESHOLD = 1.20; /* 2.0 symbol spread gives -3, -1, 1, 3 */ private float mSymbolSpread = 2.0f; @@ -201,7 +201,7 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, private float mHistory[] = new float[ NUMBER_FILTER_TAPS ]; private int mHistoryLast = 0; - private boolean mReset = false; + private boolean mResetFrequencyTracker = false; private RealSampleListener mListener; @@ -255,11 +255,16 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, { mFrequencyCorrectionControl.adjust( mFrequencyAdjustmentRequested ); -// mLog.debug( "Adjusting frequency [" + mFrequencyAdjustmentRequested + -// "] correction is now: " + mFrequencyCorrectionControl -// .getErrorCorrection() ); + mLog.debug( "Adjusted frequency [" + mFrequencyAdjustmentRequested + + "] correction is now: " + mFrequencyCorrectionControl + .getErrorCorrection() ); mFrequencyAdjustmentRequested = 0; + + //Reset internal frequency tracking + mLog.debug( "Resetting internal frequency tracking following adjustment" ); + mCoarseFrequencyCorrection = 0.0f; + mFineFrequencyCorrection = 0.0f; } } @@ -267,17 +272,16 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, { sample = mGainController.correct( sample ); - if( mReset ) + if( mResetFrequencyTracker ) { - mGainController.reset(); + mLog.debug( "Resetting internal frequency tracking" ); mCoarseFrequencyCorrection = 0.0f; mFineFrequencyCorrection = 0.0f; - mSymbolSpread = 2.0f; - mSymbolClock = 0.0f; - mSymbolTime = (float)SYMBOL_RATE / (float)SAMPLE_RATE; - mReset = false; + mFrequencyCorrectionControl.setFrequencyCorrection( 0 ); + + mResetFrequencyTracker = false; } mSymbolClock += mSymbolTime; @@ -381,7 +385,7 @@ public class C4FMSymbolFilter implements FrequencyCorrectionResetListener, mFineFrequencyCorrection += ( symbolError * K_FINE_FREQUENCY ); /* Queue a frequency adjustment (once per buffer) as needed */ - if( Math.abs( mCoarseFrequencyCorrection ) > COARSE_FREQUENCY_DEADBAND ) + if( Math.abs( mCoarseFrequencyCorrection ) > COARSE_FREQUENCY_THRESHOLD ) { mFrequencyAdjustmentRequested = 500 * ( mCoarseFrequencyCorrection > 0 ? 1 : -1 ); @@ -403,12 +407,12 @@ 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 or frequency offset. + * has changed frequency (PPM) or sample rate */ @Override public void resetFrequencyCorrection() { - mReset = true; + mResetFrequencyTracker = true; } @Override diff --git a/src/source/recording/Recording.java b/src/source/recording/Recording.java index 48899f8b..90fad405 100644 --- a/src/source/recording/Recording.java +++ b/src/source/recording/Recording.java @@ -10,7 +10,7 @@ import source.tuner.TunerChannelProvider; import source.tuner.TunerChannelSource; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import controller.ResourceManager; import controller.ThreadPoolManager; @@ -90,7 +90,7 @@ public class Recording implements Comparable, @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { long frequency = event.getValue().longValue(); diff --git a/src/source/tuner/Tuner.java b/src/source/tuner/Tuner.java index 98543869..e274c97f 100644 --- a/src/source/tuner/Tuner.java +++ b/src/source/tuner/Tuner.java @@ -31,7 +31,7 @@ import source.SourceException; import source.tuner.frequency.FrequencyChangeBroadcaster; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import controller.ResourceManager; import controller.ThreadPoolManager; @@ -210,7 +210,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, public void broadcastFrequencyChange( long frequency ) { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Attribute.FREQUENCY, frequency ) ); + new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, frequency ) ); } /** @@ -219,7 +219,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, public void broadcastSampleRateChange( int sampleRate ) { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Attribute.SAMPLE_RATE, sampleRate ) ); + new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, sampleRate ) ); } /** @@ -228,7 +228,7 @@ public abstract class Tuner implements FrequencyChangeBroadcaster, public void broadcastActualSampleRateChange( int actualSampleRate ) { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Attribute.SAMPLE_RATE, actualSampleRate ) ); + new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, actualSampleRate ) ); } /** diff --git a/src/source/tuner/TunerChannelSource.java b/src/source/tuner/TunerChannelSource.java index 4d7d3642..ef453e06 100644 --- a/src/source/tuner/TunerChannelSource.java +++ b/src/source/tuner/TunerChannelSource.java @@ -35,7 +35,7 @@ import sample.complex.ComplexBuffer; import source.ComplexSource; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.FrequencyChangeListener; import controller.ThreadPoolManager; import controller.ThreadPoolManager.ThreadType; @@ -66,8 +66,8 @@ public class TunerChannelSource extends ComplexSource private ScheduledFuture mTaskHandle; private long mTunerFrequency = 0; - private int mTunerFrequencyError = 0; private int mTunerSampleRate; + private int mChannelFrequencyCorrection = 0; private DecimationProcessor mDecimationProcessor = new DecimationProcessor(); @@ -92,11 +92,11 @@ public class TunerChannelSource extends ComplexSource mMixer = new Oscillator( frequencyOffset, mTuner.getSampleRate() ); - /* Fire a sample rate change event to get the decimation chain setup */ + /* Fire a sample rate change event to setup the decimation chain */ frequencyChanged( new FrequencyChangeEvent( - Attribute.SAMPLE_RATE, mTuner.getSampleRate() ) ); + Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mTuner.getSampleRate() ) ); - /* Schedule the decimation task to run 50 times a second */ + /* Schedule the decimation task to run every 20 ms (50 iterations/second) */ mTaskHandle = mThreadPoolManager.scheduleFixedRate( ThreadType.DECIMATION, mDecimationProcessor, 20, TimeUnit.MILLISECONDS ); @@ -183,26 +183,44 @@ public class TunerChannelSource extends ComplexSource { mDecimationFilter.removeListener(); } - + + /** + * Handler for frequency change events received from the tuner and channel + * frequency correction events received from the channel consumer/listener + */ @Override public void frequencyChanged( FrequencyChangeEvent event ) { - /* Send change to Automatic Frequency Control if it exists */ + // Echo the event to the registered event listener if( mFrequencyChangeListener != null ) { mFrequencyChangeListener.frequencyChanged( event ); } - switch( event.getAttribute() ) + switch( event.getEvent() ) { - case SAMPLE_RATE_ERROR: + case FREQUENCY_CHANGE_NOTIFICATION: + mTunerFrequency = event.getValue().longValue(); + updateMixerFrequencyOffset(); break; - case SAMPLE_RATE: + case CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST: + mChannelFrequencyCorrection = event.getValue().intValue(); + + updateMixerFrequencyOffset(); + + if( mFrequencyChangeListener != null ) + { + mFrequencyChangeListener.frequencyChanged( + new FrequencyChangeEvent( + Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, + mChannelFrequencyCorrection ) ); + } + break; + case SAMPLE_RATE_CHANGE_NOTIFICATION: int sampleRate = event.getValue().intValue(); if( mTunerSampleRate != sampleRate ) { - /* Set the oscillator to the new frequency */ mMixer.setSampleRate( sampleRate ); /* Get new decimation filter */ @@ -220,33 +238,30 @@ public class TunerChannelSource extends ComplexSource mTunerSampleRate = sampleRate; } break; - case FREQUENCY_ERROR: - mTunerFrequencyError = event.getValue().intValue(); - - long frequencyErrorOffset = mTunerFrequency - - mTunerChannel.getFrequency() - - mTunerFrequencyError; - - mMixer.setFrequency( frequencyErrorOffset ); - break; - case FREQUENCY: - long frequency = event.getValue().longValue(); - - /* If the frequency is updated, the AFC will also get reset, so - * we don't include the frequency error value here */ - mTunerFrequencyError = 0; - - long frequencyOffset = frequency - mTunerChannel.getFrequency(); - - mMixer.setFrequency( frequencyOffset ); - - mTunerFrequency = frequency; - break; default: break; } } + /** + * Calculates the local mixer frequency offset from the tuned frequency, + * channel's requested frequency, and channel frequency correction. + */ + private void updateMixerFrequencyOffset() + { + long offset = mTunerFrequency - + mTunerChannel.getFrequency() - + mChannelFrequencyCorrection; + + mMixer.setFrequency( offset ); + + mLog.debug( "VCO Updated -" + + " Tuner:" + mTunerFrequency + + " Channel:" + mTunerChannel.getFrequency() + + " Correction:" + mChannelFrequencyCorrection + + " Mixer: " + offset ); + } + public int getSampleRate() throws SourceException { return CHANNEL_RATE; diff --git a/src/source/tuner/TunerNode.java b/src/source/tuner/TunerNode.java index db45d1d9..9d2f4d99 100644 --- a/src/source/tuner/TunerNode.java +++ b/src/source/tuner/TunerNode.java @@ -129,9 +129,9 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener @Override public void frequencyChanged( FrequencyChangeEvent event ) { - switch( event.getAttribute() ) + switch( event.getEvent() ) { - case FREQUENCY: + case FREQUENCY_CHANGE_NOTIFICATION: long frequency = event.getValue().longValue(); if( mFrequency != frequency ) @@ -140,7 +140,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener getModel().nodeChanged( TunerNode.this ); } break; - case SAMPLE_RATE: + case SAMPLE_RATE_CHANGE_NOTIFICATION: int sampleRate = event.getValue().intValue(); if( mSampleRate != sampleRate ) diff --git a/src/source/tuner/airspy/AirspyTunerEditorPanel.java b/src/source/tuner/airspy/AirspyTunerEditorPanel.java index 08dec674..d15037f7 100644 --- a/src/source/tuner/airspy/AirspyTunerEditorPanel.java +++ b/src/source/tuner/airspy/AirspyTunerEditorPanel.java @@ -31,7 +31,7 @@ import org.slf4j.LoggerFactory; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.FrequencyChangeListener; import com.jidesoft.swing.JideTabbedPane; @@ -97,7 +97,7 @@ public class AirspyTunerEditorPanel extends JPanel @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { try { diff --git a/src/source/tuner/fcd/FCDTunerController.java b/src/source/tuner/fcd/FCDTunerController.java index cead5092..8e6ff030 100644 --- a/src/source/tuner/fcd/FCDTunerController.java +++ b/src/source/tuner/fcd/FCDTunerController.java @@ -47,7 +47,7 @@ public abstract class FCDTunerController extends TunerController LoggerFactory.getLogger( FCDTunerController.class ); public static final double USABLE_BANDWIDTH_PERCENT = 1.0; - public static final int DC_SPIKE_AVOID_BUFFER = 2000; + public static final int DC_SPIKE_AVOID_BUFFER = 5000; public final static byte FCD_INTERFACE = (byte)0x2; public final static byte FCD_ENDPOINT_IN = (byte)0x82; diff --git a/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java b/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java index e82b7a43..317fcaeb 100644 --- a/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java +++ b/src/source/tuner/fcd/proV1/FCD1TunerEditorPanel.java @@ -34,7 +34,7 @@ import source.tuner.fcd.FCDTuner; import source.tuner.fcd.FCDTunerDetailsPanel; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import com.jidesoft.swing.JideTabbedPane; @@ -95,7 +95,7 @@ public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListe @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { try { diff --git a/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java b/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java index e7dcba54..e372a544 100644 --- a/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java +++ b/src/source/tuner/fcd/proplusV2/FCD2TunerEditorPanel.java @@ -34,7 +34,7 @@ import source.tuner.fcd.FCDTuner; import source.tuner.fcd.FCDTunerDetailsPanel; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import com.jidesoft.swing.JideTabbedPane; @@ -94,7 +94,7 @@ public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListe @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { //Disregard the bandwidth, which shouldn't be changing try diff --git a/src/source/tuner/frequency/AutomaticFrequencyControl_R.java b/src/source/tuner/frequency/AutomaticFrequencyControl_R.java index 4c52f7ef..994ff0c6 100644 --- a/src/source/tuner/frequency/AutomaticFrequencyControl_R.java +++ b/src/source/tuner/frequency/AutomaticFrequencyControl_R.java @@ -22,7 +22,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import sample.real.RealSampleListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import buffer.FloatAveragingBuffer; public class AutomaticFrequencyControl_R extends FrequencyCorrectionControl @@ -94,7 +94,7 @@ public class AutomaticFrequencyControl_R extends FrequencyCorrectionControl if( mListener != null ) { mListener.frequencyChanged( - new FrequencyChangeEvent( Attribute.FREQUENCY_ERROR, + new FrequencyChangeEvent( Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, mErrorCorrection ) ); } } diff --git a/src/source/tuner/frequency/AutomaticFrequencyControl_RB.java b/src/source/tuner/frequency/AutomaticFrequencyControl_RB.java index e51225d3..73970ec2 100644 --- a/src/source/tuner/frequency/AutomaticFrequencyControl_RB.java +++ b/src/source/tuner/frequency/AutomaticFrequencyControl_RB.java @@ -23,7 +23,7 @@ import org.slf4j.LoggerFactory; import sample.Listener; import sample.real.RealBuffer; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import buffer.FloatAveragingBuffer; public class AutomaticFrequencyControl_RB extends FrequencyCorrectionControl @@ -96,7 +96,7 @@ public class AutomaticFrequencyControl_RB extends FrequencyCorrectionControl if( mListener != null ) { mListener.frequencyChanged( - new FrequencyChangeEvent( Attribute.FREQUENCY_ERROR, + new FrequencyChangeEvent( Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, mErrorCorrection ) ); } } diff --git a/src/source/tuner/frequency/FrequencyChangeEvent.java b/src/source/tuner/frequency/FrequencyChangeEvent.java index 0ab125bc..87f82f08 100644 --- a/src/source/tuner/frequency/FrequencyChangeEvent.java +++ b/src/source/tuner/frequency/FrequencyChangeEvent.java @@ -2,27 +2,27 @@ package source.tuner.frequency; public class FrequencyChangeEvent { - public enum Attribute + public enum Event { - SAMPLE_RATE_ERROR, - BANDWIDTH, - FREQUENCY, - FREQUENCY_ERROR, - SAMPLE_RATE; + FREQUENCY_CHANGE_NOTIFICATION, + FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, + CHANNEL_FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, + CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST, + SAMPLE_RATE_CHANGE_NOTIFICATION; } - private Attribute mAttribute; + private Event mEvent; private Number mValue; - public FrequencyChangeEvent( Attribute attribute, Number value ) + public FrequencyChangeEvent( Event event, Number value ) { - mAttribute = attribute; + mEvent = event; mValue = value; } - public Attribute getAttribute() + public Event getEvent() { - return mAttribute; + return mEvent; } public Number getValue() diff --git a/src/source/tuner/frequency/FrequencyController.java b/src/source/tuner/frequency/FrequencyController.java index 009b7467..51bab16f 100644 --- a/src/source/tuner/frequency/FrequencyController.java +++ b/src/source/tuner/frequency/FrequencyController.java @@ -23,7 +23,7 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import source.SourceException; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; public class FrequencyController { @@ -101,6 +101,8 @@ public class FrequencyController if( tunedFrequency < mMinimumFrequency || tunedFrequency > mMaximumFrequency ) { +//TODO: this should throw a frequency limit exception so that the frequency +//controller can update its display to the last tuned frequency throw new SourceException( "Cannot tune frequency ( requested: " + frequency + " actual:" + tunedFrequency + "]" ); } @@ -170,13 +172,10 @@ public class FrequencyController if( mFrequency > 0 ) { - /* Reset the frequency, but don't broadcast a change */ - setFrequency( mFrequency, false ); + setFrequency( mFrequency, true ); } - - broadcastFrequencyChangeEvent( new FrequencyChangeEvent( - Attribute.SAMPLE_RATE_ERROR, mFrequencyCorrection ) ); - + + broadcastFrequencyErrorChange(); } /** @@ -206,16 +205,25 @@ public class FrequencyController protected void broadcastFrequencyChange() { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Attribute.FREQUENCY, mFrequency ) ); + new FrequencyChangeEvent( Event.FREQUENCY_CHANGE_NOTIFICATION, mFrequency ) ); } + /** + * Broadcast a frequency error/correction value change + */ + protected void broadcastFrequencyErrorChange() + { + broadcastFrequencyChangeEvent( + new FrequencyChangeEvent( Event.FREQUENCY_CORRECTION_CHANGE_NOTIFICATION, mFrequencyCorrection ) ); + } + /** * Broadcasts a sample rate change */ protected void broadcastSampleRateChange() { broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( Attribute.SAMPLE_RATE, mSampleRate ) ); + new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mSampleRate ) ); } public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event ) diff --git a/src/source/tuner/frequency/FrequencyCorrectionControl.java b/src/source/tuner/frequency/FrequencyCorrectionControl.java index bf3f6a7c..77255bb0 100644 --- a/src/source/tuner/frequency/FrequencyCorrectionControl.java +++ b/src/source/tuner/frequency/FrequencyCorrectionControl.java @@ -20,10 +20,10 @@ package source.tuner.frequency; import org.slf4j.Logger; import org.slf4j.LoggerFactory; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; /** - * Frequency control for providing frequency error correction to a tuner channel + * Frequency control for providing frequency error correction to a tuned channel */ public class FrequencyCorrectionControl implements FrequencyChangeListener { @@ -33,7 +33,7 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener protected FrequencyChangeListener mListener; protected FrequencyCorrectionResetListener mResetListener; - protected int mErrorCorrection = 0; + protected int mChannelFrequencyCorrection = 0; private int mMaximumCorrection = 3000; /** @@ -79,12 +79,18 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener @Override public void frequencyChanged( FrequencyChangeEvent event ) { - Attribute attribute = event.getAttribute(); + Event attribute = event.getEvent(); - if( attribute == Attribute.FREQUENCY || - attribute == Attribute.SAMPLE_RATE_ERROR ) + switch( attribute ) { - reset(); + //Direct the listener to reset when frequency correction (PPM) or + //sample rate changes + case FREQUENCY_CORRECTION_CHANGE_NOTIFICATION: + case SAMPLE_RATE_CHANGE_NOTIFICATION: + reset(); + break; + default: + break; } } @@ -94,8 +100,6 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener */ public void reset() { - setErrorCorrection( 0, false ); - if( mResetListener != null ) { mResetListener.resetFrequencyCorrection(); @@ -104,35 +108,28 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener /** * Sets frequency correction to the specified value and broadcasts a change + * request */ - public void setErrorCorrection( int correction ) + public void setFrequencyCorrection( int correction ) { - setErrorCorrection( correction, true ); - } - - /** - * Sets frequency correction to the specified value - */ - public void setErrorCorrection( int correction, boolean broadcast ) - { - mErrorCorrection = correction; + mChannelFrequencyCorrection = correction; /* Limit frequency correction to +/- max correction value */ - if( mErrorCorrection > mMaximumCorrection ) + if( mChannelFrequencyCorrection > mMaximumCorrection ) { - mErrorCorrection = mMaximumCorrection; + mChannelFrequencyCorrection = mMaximumCorrection; } - else if( mErrorCorrection < -mMaximumCorrection ) + else if( mChannelFrequencyCorrection < -mMaximumCorrection ) { - mErrorCorrection = -mMaximumCorrection; + mChannelFrequencyCorrection = -mMaximumCorrection; } - /* Broadcast a change event */ - if( broadcast && mListener != null ) + /* Broadcast a change request */ + if( mListener != null ) { - mListener.frequencyChanged( - new FrequencyChangeEvent( Attribute.FREQUENCY_ERROR, - mErrorCorrection ) ); + mListener.frequencyChanged( new FrequencyChangeEvent( + Event.CHANNEL_FREQUENCY_CORRECTION_CHANGE_REQUEST, + mChannelFrequencyCorrection ) ); } } @@ -141,7 +138,7 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener */ public void adjust( int adjustment ) { - setErrorCorrection( getErrorCorrection() + adjustment ); + setFrequencyCorrection( getErrorCorrection() + adjustment ); } /** @@ -150,7 +147,7 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener */ public int getErrorCorrection() { - return mErrorCorrection; + return mChannelFrequencyCorrection; } /** diff --git a/src/source/tuner/hackrf/HackRFTunerEditorPanel.java b/src/source/tuner/hackrf/HackRFTunerEditorPanel.java index a594eab7..9c4d8490 100644 --- a/src/source/tuner/hackrf/HackRFTunerEditorPanel.java +++ b/src/source/tuner/hackrf/HackRFTunerEditorPanel.java @@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.hackrf.HackRFTunerController.BoardID; import com.jidesoft.swing.JideTabbedPane; @@ -110,7 +110,7 @@ public class HackRFTunerEditorPanel extends JPanel @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { try { diff --git a/src/source/tuner/rtl/RTL2832TunerController.java b/src/source/tuner/rtl/RTL2832TunerController.java index c9eb524e..d419c782 100644 --- a/src/source/tuner/rtl/RTL2832TunerController.java +++ b/src/source/tuner/rtl/RTL2832TunerController.java @@ -56,7 +56,7 @@ import source.SourceException; import source.tuner.TunerController; import source.tuner.TunerType; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import buffer.FloatAveragingBuffer; import controller.ResourceManager; import controller.ThreadPoolManager; @@ -1693,14 +1693,6 @@ public abstract class RTL2832TunerController extends TunerController if( mSampleRateMinimum < current && current < mSampleRateMaximum ) { average = mRateErrorBuffer.get( (float)mTargetSampleRate - current ); - - /* broadcast an actual sample rate update */ - if( mFrequencyController != null ) - { - mFrequencyController.broadcastFrequencyChangeEvent( - new FrequencyChangeEvent( - Attribute.SAMPLE_RATE_ERROR, (int)average ) ); - } } else { diff --git a/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java b/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java index fcb6f72c..5c883748 100644 --- a/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java +++ b/src/source/tuner/rtl/e4k/E4KTunerEditorPanel.java @@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.rtl.RTL2832InfoPanel; import com.jidesoft.swing.JideTabbedPane; @@ -98,7 +98,7 @@ public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListen @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { final long frequency = event.getValue().longValue(); diff --git a/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java b/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java index 36bde408..f59d29a7 100644 --- a/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java +++ b/src/source/tuner/rtl/r820t/R820TTunerEditorPanel.java @@ -33,7 +33,7 @@ import org.slf4j.LoggerFactory; import source.SourceException; import source.tuner.frequency.FrequencyChangeEvent; import source.tuner.frequency.FrequencyChangeListener; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.rtl.RTL2832InfoPanel; import com.jidesoft.swing.JideTabbedPane; @@ -97,7 +97,7 @@ public class R820TTunerEditorPanel extends JPanel implements FrequencyChangeList @Override public void frequencyChanged( FrequencyChangeEvent event ) { - if( event.getAttribute() == Attribute.FREQUENCY ) + if( event.getEvent() == Event.FREQUENCY_CHANGE_NOTIFICATION ) { final long frequency = event.getValue().longValue(); diff --git a/src/spectrum/ChannelSpectrumPanel.java b/src/spectrum/ChannelSpectrumPanel.java index 40bd0d99..96cbefa1 100644 --- a/src/spectrum/ChannelSpectrumPanel.java +++ b/src/spectrum/ChannelSpectrumPanel.java @@ -31,7 +31,7 @@ import settings.Setting; import settings.SettingChangeListener; import settings.SettingsManager; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import spectrum.converter.DFTResultsConverter; import spectrum.converter.RealDecibelConverter; import spectrum.menu.AveragingItem; @@ -99,7 +99,7 @@ public class ChannelSpectrumPanel extends JPanel /* Set the DFTProcessor to the decimated 24kHz sample rate */ mDFTProcessor.frequencyChanged( - new FrequencyChangeEvent( Attribute.SAMPLE_RATE, 24000 ) ); + new FrequencyChangeEvent( Event.SAMPLE_RATE_CHANGE_NOTIFICATION, 24000 ) ); initGui(); } diff --git a/src/spectrum/DFTProcessor.java b/src/spectrum/DFTProcessor.java index 3ef75752..45734e9e 100644 --- a/src/spectrum/DFTProcessor.java +++ b/src/spectrum/DFTProcessor.java @@ -476,11 +476,9 @@ public class DFTProcessor implements Listener, @Override public void frequencyChanged( FrequencyChangeEvent event ) { - switch( event.getAttribute() ) + switch( event.getEvent() ) { - case SAMPLE_RATE_ERROR: - break; - case SAMPLE_RATE: + case SAMPLE_RATE_CHANGE_NOTIFICATION: mSampleRate = event.getValue().intValue(); calculateConsumptionRate(); break; diff --git a/src/spectrum/OverlayPanel.java b/src/spectrum/OverlayPanel.java index 1b10bf59..b22896b5 100644 --- a/src/spectrum/OverlayPanel.java +++ b/src/spectrum/OverlayPanel.java @@ -428,24 +428,33 @@ public class OverlayPanel extends JPanel /** * Draws a vertical line at the xaxis */ - private void drawAFC( Graphics2D graphics, double xaxis, boolean isError ) + private void drawChannelCenterLine( Graphics2D graphics, double xaxis ) { double height = getSize().getHeight() - mSpectrumInset; - if( isError ) - { - graphics.setColor( Color.YELLOW ); + graphics.setColor( Color.LIGHT_GRAY ); - graphics.draw( new Line2D.Double( xaxis, height * 0.75d, - xaxis, height - 1.0d ) ); - } - else - { - graphics.setColor( Color.LIGHT_GRAY ); + graphics.draw( new Line2D.Double( xaxis, height * 0.65d, + xaxis, height - 1.0d ) ); + } + + /** + * Draws a vertical line at the xaxis + */ + private void drawAFC( Graphics2D graphics, double frequencyAxis, double errorAxis ) + { + double height = getSize().getHeight() - mSpectrumInset; + double lineHeight = height * 0.75d; - graphics.draw( new Line2D.Double( xaxis, height * 0.65d, - xaxis, height - 1.0d ) ); - } + graphics.setColor( Color.YELLOW ); + + //Vertical frequency error line + graphics.draw( new Line2D.Double( errorAxis, lineHeight, + errorAxis, height - 1.0d ) ); + + //Horizontal line connecting frequency and error lines + graphics.draw( new Line2D.Double( frequencyAxis, lineHeight, + errorAxis, lineHeight ) ); } /** @@ -599,16 +608,18 @@ public class OverlayPanel extends JPanel width ); } + long frequency = tunerChannel.getFrequency(); + + double frequencyAxis = getAxisFromFrequency( frequency ); + + drawChannelCenterLine( graphics, frequencyAxis ); + /* Draw Automatic Frequency Control line */ if( channel.hasFrequencyControl() ) { - long frequency = tunerChannel.getFrequency(); - long error = frequency + channel.getFrequencyCorrection(); - drawAFC( graphics, getAxisFromFrequency( frequency ), false ); - - drawAFC( graphics, getAxisFromFrequency( error ), true ); + drawAFC( graphics, frequencyAxis, getAxisFromFrequency( error ) ); } } } @@ -663,13 +674,13 @@ public class OverlayPanel extends JPanel @Override public void frequencyChanged( FrequencyChangeEvent event ) { - switch( event.getAttribute() ) + switch( event.getEvent() ) { - case SAMPLE_RATE: + case SAMPLE_RATE_CHANGE_NOTIFICATION: mBandwidth = event.getValue().intValue(); mLabelSizeMonitor.update(); break; - case FREQUENCY: + case FREQUENCY_CHANGE_NOTIFICATION: mFrequency = event.getValue().longValue(); mLabelSizeMonitor.update(); break; diff --git a/src/spectrum/SpectralDisplayPanel.java b/src/spectrum/SpectralDisplayPanel.java index dce94b2c..b2cb7dd8 100644 --- a/src/spectrum/SpectralDisplayPanel.java +++ b/src/spectrum/SpectralDisplayPanel.java @@ -65,7 +65,7 @@ import source.SourceException; import source.tuner.Tuner; import source.tuner.TunerSelectionListener; import source.tuner.frequency.FrequencyChangeEvent; -import source.tuner.frequency.FrequencyChangeEvent.Attribute; +import source.tuner.frequency.FrequencyChangeEvent.Event; import source.tuner.frequency.FrequencyChangeListener; import spectrum.OverlayPanel.ChannelDisplay; import spectrum.converter.ComplexDecibelConverter; @@ -434,10 +434,10 @@ public class SpectralDisplayPanel extends JPanel try { frequencyChanged( new FrequencyChangeEvent( - Attribute.FREQUENCY, mTuner.getFrequency() ) ); + Event.FREQUENCY_CHANGE_NOTIFICATION, mTuner.getFrequency() ) ); frequencyChanged( new FrequencyChangeEvent( - Attribute.SAMPLE_RATE, mTuner.getSampleRate() ) ); + Event.SAMPLE_RATE_CHANGE_NOTIFICATION, mTuner.getSampleRate() ) ); } catch ( SourceException e ) {