mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 08:37:25 -05:00
Changed FrequencyChangeListener interface to an event so that I could describe what event was causing the frequency change and to broadcast frequency and sample rate error values.
R820T - added a couple more sample rate settings to the enum and modified the periodic sample rate info logger.
This commit is contained in:
@@ -46,6 +46,7 @@ import source.FloatSource;
|
||||
import source.Source;
|
||||
import source.SourceException;
|
||||
import source.config.SourceConfigMixer;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.Tuner;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import alias.AliasList;
|
||||
@@ -61,7 +62,6 @@ import controller.state.ChannelState.State;
|
||||
import decode.Decoder;
|
||||
import decode.DecoderFactory;
|
||||
import dsp.afc.AutomaticFrequencyControl;
|
||||
import dsp.afc.FrequencyErrorListener;
|
||||
import eventlog.EventLogType;
|
||||
import eventlog.EventLogger;
|
||||
|
||||
@@ -403,16 +403,15 @@ public class ProcessingChain implements Listener<Message>
|
||||
mAFC = null;
|
||||
}
|
||||
|
||||
if( mSource instanceof FrequencyErrorListener &&
|
||||
if( mSource instanceof TunerChannelSource &&
|
||||
mChannel.getDecodeConfiguration().isAFCEnabled() )
|
||||
{
|
||||
FrequencyErrorListener listener =
|
||||
(FrequencyErrorListener)mSource;
|
||||
TunerChannelSource tcs = (TunerChannelSource)mSource;
|
||||
|
||||
mAFC = new AutomaticFrequencyControl( listener );
|
||||
mAFC = new AutomaticFrequencyControl( tcs );
|
||||
|
||||
/* Register AFC to receive frequency change events */
|
||||
listener.addListener( mAFC );
|
||||
tcs.addListener( mAFC );
|
||||
|
||||
/* Add AFC as listener to the decoder */
|
||||
mDecoder.addUnfilteredFloatListener( mAFC );
|
||||
|
||||
@@ -1,7 +1,9 @@
|
||||
package dsp.afc;
|
||||
|
||||
import sample.Listener;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
|
||||
public class AutomaticFrequencyControl implements Listener<Float>,
|
||||
@@ -22,15 +24,14 @@ public class AutomaticFrequencyControl implements Listener<Float>,
|
||||
private int mSkipThreshold = 4;
|
||||
private int mErrorCorrection = 0;
|
||||
private long mCurrentFrequency;
|
||||
private int mCurrentSampleRate;
|
||||
private FrequencyErrorListener mListener;
|
||||
private FrequencyChangeListener mListener;
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
NORMAL,FAST;
|
||||
}
|
||||
|
||||
public AutomaticFrequencyControl( FrequencyErrorListener listener )
|
||||
public AutomaticFrequencyControl( FrequencyChangeListener listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
@@ -57,7 +58,9 @@ public class AutomaticFrequencyControl implements Listener<Float>,
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.setError( mErrorCorrection );
|
||||
mListener.frequencyChanged(
|
||||
new FrequencyChangeEvent( Attribute.FREQUENCY_ERROR,
|
||||
mErrorCorrection ) );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,14 +159,23 @@ public class AutomaticFrequencyControl implements Listener<Float>,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
if( mCurrentFrequency != frequency || mCurrentSampleRate != bandwidth )
|
||||
switch( event.getAttribute() )
|
||||
{
|
||||
mCurrentFrequency = frequency;
|
||||
mCurrentSampleRate = bandwidth;
|
||||
|
||||
reset();
|
||||
case FREQUENCY:
|
||||
int frequency = (int)event.getValue();
|
||||
|
||||
if( mCurrentFrequency != frequency )
|
||||
{
|
||||
mCurrentFrequency = frequency;
|
||||
|
||||
reset();
|
||||
}
|
||||
case SAMPLE_RATE_ERROR:
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,10 +0,0 @@
|
||||
package dsp.afc;
|
||||
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
|
||||
public interface FrequencyErrorListener
|
||||
{
|
||||
public void setError( int error );
|
||||
|
||||
public void addListener( FrequencyChangeListener listener );
|
||||
}
|
||||
@@ -406,7 +406,15 @@ public class FilterFactory
|
||||
|
||||
int decimate = (int)( sampleRate / decimatedRate );
|
||||
|
||||
filters[ 0 ] = new ComplexCICDecimate( decimate, 2, decimatedRate );
|
||||
// if( decimate < 25 )
|
||||
// {
|
||||
filters[ 0 ] = new ComplexCICDecimate( decimate, 1, decimatedRate );
|
||||
// }
|
||||
// else
|
||||
// {
|
||||
// filters[ 0 ] = new ComplexCICDecimate( decimate, 3, decimatedRate );
|
||||
// }
|
||||
|
||||
|
||||
// int finalStopFrequency = decimatedRate - passFrequency;
|
||||
//
|
||||
|
||||
@@ -43,7 +43,9 @@ import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
|
||||
public class JFrequencyControl extends JPanel implements FrequencyChangeListener
|
||||
{
|
||||
@@ -132,9 +134,12 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener
|
||||
* rebroadcast this event, just set the control to indicate the new frequency.
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
setFrequency( frequency, false );
|
||||
if( event.getAttribute() == Attribute.FREQUENCY )
|
||||
{
|
||||
setFrequency( (int)event.getValue(), false );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -174,9 +179,12 @@ public class JFrequencyControl extends JPanel implements FrequencyChangeListener
|
||||
|
||||
Iterator<FrequencyChangeListener> it = mListeners.iterator();
|
||||
|
||||
FrequencyChangeEvent event =
|
||||
new FrequencyChangeEvent( Attribute.FREQUENCY, mFrequency );
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
it.next().frequencyChanged( mFrequency, -1 );
|
||||
it.next().frequencyChanged( event );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,114 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package sample.complex;
|
||||
|
||||
import gui.SDRTrunk;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
|
||||
public class ComplexSampleRateCounter implements Listener<ComplexSample>,
|
||||
ComplexSampleListListener,
|
||||
FrequencyChangeListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( ComplexSampleRateCounter.class );
|
||||
|
||||
private int mCounter;
|
||||
private int mAverageCounter;
|
||||
private int mExpectedSampleRate;
|
||||
private long mLastRun = 0;
|
||||
private int mBufferSize = 100;
|
||||
private FloatAveragingBuffer mAveragingBuffer;
|
||||
|
||||
public ComplexSampleRateCounter( int expectedSampleRate, int bufferSize )
|
||||
{
|
||||
mExpectedSampleRate = expectedSampleRate;
|
||||
mBufferSize = bufferSize;
|
||||
|
||||
mAveragingBuffer = new FloatAveragingBuffer( mBufferSize );
|
||||
|
||||
mLastRun = System.currentTimeMillis();
|
||||
|
||||
mLog.info( "Complex Sample Rate Counter started ...." );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( ComplexSample sample )
|
||||
{
|
||||
mCounter++;
|
||||
|
||||
if( mCounter >= mExpectedSampleRate )
|
||||
{
|
||||
mCounter = 0;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
long elapsed = now - mLastRun;
|
||||
mLastRun = now;
|
||||
|
||||
float average = (float)mExpectedSampleRate * 1000.0f / (float)elapsed;
|
||||
float runningAverage = mAveragingBuffer.get( average );
|
||||
|
||||
mAverageCounter++;
|
||||
|
||||
mLog.info( "Complex Sample Rate Avg " + mAverageCounter +
|
||||
" current [" + elapsed + " ms/" + average +
|
||||
" hz] average [" + runningAverage + " hz] expected [" +
|
||||
mExpectedSampleRate + " hz] over [" +
|
||||
mBufferSize + "] buffer length" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( List<ComplexSample> samples )
|
||||
{
|
||||
mCounter += samples.size();
|
||||
|
||||
if( mCounter >= mExpectedSampleRate )
|
||||
{
|
||||
mCounter -= mExpectedSampleRate;
|
||||
|
||||
long now = System.currentTimeMillis();
|
||||
long elapsed = now - mLastRun;
|
||||
mLastRun = now;
|
||||
|
||||
float average = (float)mExpectedSampleRate * 1000.0f / (float)elapsed;
|
||||
float runningAverage = mAveragingBuffer.get( average );
|
||||
|
||||
mAverageCounter++;
|
||||
|
||||
mLog.info( "Complex Sample Rate Avg " + mAverageCounter +
|
||||
" current [" + elapsed + " ms/" + average +
|
||||
" hz] average [" + runningAverage + " hz] expected [" +
|
||||
mExpectedSampleRate + " hz] over [" +
|
||||
mBufferSize + "] buffer length" );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
{
|
||||
mExpectedSampleRate = bandwidth;
|
||||
}
|
||||
}
|
||||
@@ -5,10 +5,12 @@ import java.util.ArrayList;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.TunerChannel;
|
||||
import source.tuner.TunerChannelProvider;
|
||||
import source.tuner.TunerChannelSource;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
@@ -86,16 +88,22 @@ public class Recording implements Comparable<Recording>,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
mConfiguration.setCenterFrequency( frequency );
|
||||
mResourceManager.getSettingsManager().save();
|
||||
|
||||
mCenterFrequency = frequency;
|
||||
|
||||
for( TunerChannelSource channel: mTunerChannels )
|
||||
if( event.getAttribute() == Attribute.FREQUENCY )
|
||||
{
|
||||
channel.frequencyChanged( frequency, bandwidth );
|
||||
int frequency = (int)event.getValue();
|
||||
|
||||
mConfiguration.setCenterFrequency( frequency );
|
||||
|
||||
mResourceManager.getSettingsManager().save();
|
||||
|
||||
mCenterFrequency = frequency;
|
||||
|
||||
for( TunerChannelSource channel: mTunerChannels )
|
||||
{
|
||||
channel.frequencyChanged( event );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
34
src/source/tuner/FrequencyChangeEvent.java
Normal file
34
src/source/tuner/FrequencyChangeEvent.java
Normal file
@@ -0,0 +1,34 @@
|
||||
package source.tuner;
|
||||
|
||||
public class FrequencyChangeEvent
|
||||
{
|
||||
public enum Attribute
|
||||
{
|
||||
SAMPLE_RATE_ERROR,
|
||||
BANDWIDTH,
|
||||
FREQUENCY,
|
||||
FREQUENCY_ERROR,
|
||||
SAMPLE_RATE;
|
||||
}
|
||||
|
||||
private Attribute mAttribute;
|
||||
private long mValue;
|
||||
|
||||
public FrequencyChangeEvent( Attribute attribute, long value )
|
||||
{
|
||||
mAttribute = attribute;
|
||||
mValue = value;
|
||||
}
|
||||
|
||||
public Attribute getAttribute()
|
||||
{
|
||||
return mAttribute;
|
||||
}
|
||||
|
||||
public long getValue()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -18,8 +18,8 @@
|
||||
package source.tuner;
|
||||
|
||||
/**
|
||||
* Interface for broadcasting changes to frequency and/or bandwidth/sample rate
|
||||
* to all registered listeners.
|
||||
* Interface for broadcasting changes to frequency, bandwidth, sample rate,
|
||||
* and actual sample rate values to all registered listeners.
|
||||
*
|
||||
* Note: broadcasted frequency should be the uncorrected, or displayable
|
||||
* frequency value. All frequency correction aspects should be handled within
|
||||
@@ -27,12 +27,5 @@ package source.tuner;
|
||||
*/
|
||||
public interface FrequencyChangeListener
|
||||
{
|
||||
/**
|
||||
* Broadcasts a change to the (uncorrected) frequency and/or bandwidth
|
||||
* or sample rate.
|
||||
*
|
||||
* @param frequency - uncorrected frequency in hertz
|
||||
* @param bandwidth - bandwidth in hertz
|
||||
*/
|
||||
public void frequencyChanged( long frequency, int bandwidth );
|
||||
public void frequencyChanged( FrequencyChangeEvent event );
|
||||
}
|
||||
|
||||
@@ -20,6 +20,7 @@ package source.tuner;
|
||||
import java.util.ArrayList;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
|
||||
public class FrequencyController
|
||||
{
|
||||
@@ -29,7 +30,7 @@ public class FrequencyController
|
||||
private long mMinimumFrequency;
|
||||
private long mMaximumFrequency;
|
||||
private double mFrequencyCorrection = 0d;
|
||||
private int mBandwidth = 0;
|
||||
private int mSampleRate = 0;
|
||||
|
||||
private ArrayList<FrequencyChangeListener> mListeners =
|
||||
new ArrayList<FrequencyChangeListener>();
|
||||
@@ -50,17 +51,17 @@ public class FrequencyController
|
||||
*/
|
||||
public int getBandwidth()
|
||||
{
|
||||
return mBandwidth;
|
||||
return mSampleRate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set bandwidth/sample rate in hertz
|
||||
* Set sample rate in hertz
|
||||
*/
|
||||
public void setBandwidth( int bandwidth )
|
||||
public void setSampleRate( int sampleRate )
|
||||
{
|
||||
mBandwidth = bandwidth;
|
||||
mSampleRate = sampleRate;
|
||||
|
||||
broadcastFrequencyChange();
|
||||
broadcastSampleRateChange();
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -193,12 +194,28 @@ public class FrequencyController
|
||||
* bandwidth/sample rate value.
|
||||
*/
|
||||
protected void broadcastFrequencyChange()
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Attribute.FREQUENCY, mFrequency ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a sample rate change
|
||||
*/
|
||||
protected void broadcastSampleRateChange()
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, mSampleRate ) );
|
||||
}
|
||||
|
||||
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event )
|
||||
{
|
||||
for( FrequencyChangeListener listener: mListeners )
|
||||
{
|
||||
listener.frequencyChanged( mFrequency, mBandwidth );
|
||||
listener.frequencyChanged( event );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public interface Tunable
|
||||
{
|
||||
|
||||
@@ -1,127 +0,0 @@
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2014 Dennis Sheirer
|
||||
*
|
||||
* This program is free software: you can redistribute it and/or modify
|
||||
* it under the terms of the GNU General Public License as published by
|
||||
* the Free Software Foundation, either version 3 of the License, or
|
||||
* (at your option) any later version.
|
||||
*
|
||||
* This program is distributed in the hope that it will be useful,
|
||||
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
* GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>
|
||||
******************************************************************************/
|
||||
package source.tuner;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.complex.ComplexSample;
|
||||
import sample.complex.ComplexSampleUtils;
|
||||
import util.Oscillator;
|
||||
|
||||
public class NumericallyControlledOscillator implements Listener<ComplexSample>,
|
||||
FrequencyChangeListener
|
||||
{
|
||||
private long mFrequency;
|
||||
private int mSampleRate;
|
||||
private Oscillator mSineWaveGenerator;
|
||||
private Listener<ComplexSample> mListener;
|
||||
/**
|
||||
* Translates (shifts) frequency spectrum up or down, depending on the sign
|
||||
* of the frequency argument, by mixing received complex samples with a
|
||||
* generated sine wave of the frequency argument. Positive frequency shifts
|
||||
* the received spectrum higher in frequency. Negative frequency shifts the
|
||||
* received spectrum lower in frequency. In both cases, spectrum that is
|
||||
* shifted outside of the sampling bandwidth will wrap around, due to the
|
||||
* nature of quadrature sampling.
|
||||
*/
|
||||
public NumericallyControlledOscillator( long frequencyShift, int sampleRate )
|
||||
{
|
||||
mFrequency = frequencyShift;
|
||||
mSampleRate = sampleRate;
|
||||
|
||||
int defaultMixingSignalGain = 10;
|
||||
|
||||
mSineWaveGenerator = new Oscillator( mFrequency, mSampleRate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Listener method for this class to receive samples from a Complex Sample
|
||||
* Provider. This method multiplies the incoming sample by the generated
|
||||
* mixing frequency to translate (ie shift +/-) the incoming signal, and
|
||||
* then send the translated signal on to all registered listeners
|
||||
*/
|
||||
@Override
|
||||
public void receive( ComplexSample sample )
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.receive( ComplexSampleUtils.multiply( sample,
|
||||
mSineWaveGenerator.nextComplex() ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
{
|
||||
if( frequency != mFrequency )
|
||||
{
|
||||
setFrequency( frequency );
|
||||
}
|
||||
|
||||
if( bandwidth != mSampleRate )
|
||||
{
|
||||
setSampleRate( bandwidth );
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the frequency value and resets the sine wave generator, so that
|
||||
* all subsequent samples will be output at the new translated frequency
|
||||
* @param frequency - hertz
|
||||
*/
|
||||
public void setFrequency( long frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
mSineWaveGenerator.setFrequency( frequency );
|
||||
}
|
||||
|
||||
/**
|
||||
* Current frequency shift setting
|
||||
* @return - frequency - hertz
|
||||
*/
|
||||
public long getFrequency()
|
||||
{
|
||||
return mFrequency;
|
||||
}
|
||||
|
||||
/**
|
||||
* Changes the sample rate, so that all new input/output values will be
|
||||
* translated at the new sample rate
|
||||
* @param sampleRate - hertz
|
||||
*/
|
||||
public void setSampleRate( int sampleRate )
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
mSineWaveGenerator.setSampleRate( sampleRate );
|
||||
}
|
||||
|
||||
/**
|
||||
* Add listener to receive frequency translated complex samples
|
||||
*/
|
||||
public void setListener( Listener<ComplexSample> listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
|
||||
/**
|
||||
* Remove listener from receiving frequency translated complex samples.
|
||||
*/
|
||||
public void clearListener()
|
||||
{
|
||||
mListener = null;
|
||||
}
|
||||
}
|
||||
@@ -24,6 +24,7 @@ import javax.swing.JPanel;
|
||||
|
||||
import sample.Listener;
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
@@ -172,11 +173,38 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
/**
|
||||
* Broadcasts a frequency change event to all registered listeners
|
||||
*/
|
||||
public void broadcastFrequencyChange( long frequency, int bandwidth )
|
||||
public void broadcastFrequencyChange( long frequency )
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Attribute.FREQUENCY, frequency ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a sample rate change event to all registered listeners
|
||||
*/
|
||||
public void broadcastSampleRateChange( int sampleRate )
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, sampleRate ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts actual sample rate change event to all registered listeners
|
||||
*/
|
||||
public void broadcastActualSampleRateChange( int actualSampleRate )
|
||||
{
|
||||
broadcastFrequencyChangeEvent(
|
||||
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, actualSampleRate ) );
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a frequency change event to all registered listeners
|
||||
*/
|
||||
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event )
|
||||
{
|
||||
for( FrequencyChangeListener listener: mFrequencyChangeListeners )
|
||||
{
|
||||
listener.frequencyChanged( frequency, bandwidth );
|
||||
listener.frequencyChanged( event );
|
||||
}
|
||||
}
|
||||
|
||||
@@ -184,8 +212,19 @@ public abstract class Tuner implements FrequencyChangeBroadcaster,
|
||||
* Frequency change listener method. We receive change events from the
|
||||
* controller and rebroadcast them to all registered listeners.
|
||||
*/
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
broadcastFrequencyChange( frequency, bandwidth );
|
||||
broadcastFrequencyChangeEvent( event );
|
||||
}
|
||||
|
||||
// /**
|
||||
// * Broadcasts a frequency change event to all registered listeners
|
||||
// */
|
||||
// public void broadcastBandwidthChange( int bandwidth )
|
||||
// {
|
||||
// broadcastFrequencyChangeEvent(
|
||||
// new FrequencyChangeEvent( Attribute.BANDWIDTH, bandwidth ) );
|
||||
// }
|
||||
//
|
||||
|
||||
}
|
||||
|
||||
@@ -29,17 +29,16 @@ import sample.complex.ComplexSample;
|
||||
import sample.complex.ComplexSampleAssembler;
|
||||
import source.ComplexSource;
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import util.Oscillator;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import dsp.afc.FrequencyErrorListener;
|
||||
import dsp.filter.ComplexFilter;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
|
||||
public class TunerChannelSource extends ComplexSource
|
||||
implements FrequencyChangeListener,
|
||||
FrequencyErrorListener,
|
||||
Listener<Float[]>
|
||||
{
|
||||
private static int sCHANNEL_RATE = 48000;
|
||||
@@ -64,32 +63,34 @@ public class TunerChannelSource extends ComplexSource
|
||||
public TunerChannelSource( ThreadPoolManager threadPoolManager,
|
||||
Tuner tuner,
|
||||
TunerChannel tunerChannel )
|
||||
throws RejectedExecutionException
|
||||
throws RejectedExecutionException, SourceException
|
||||
{
|
||||
super( "Tuner Channel Source" );
|
||||
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
|
||||
/* Schedule the decimation task to run 20 times a second */
|
||||
mTaskHandle = mThreadPoolManager.schedule( ThreadType.DECIMATION,
|
||||
new DecimationProcessor(), 50, TimeUnit.MILLISECONDS );
|
||||
|
||||
mTuner = tuner;
|
||||
mTuner.addListener( (FrequencyChangeListener)this );
|
||||
|
||||
mTunerChannel = tunerChannel;
|
||||
|
||||
mTunerFrequency = mTuner.getFrequency();
|
||||
|
||||
/* Setup the frequency translator to the current source frequency */
|
||||
try
|
||||
{
|
||||
frequencyChanged( mTuner.getFrequency(), mTuner.getSampleRate() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
e.printStackTrace();
|
||||
}
|
||||
long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency();
|
||||
|
||||
mSineWaveGenerator = new Oscillator( frequencyOffset, mTuner.getSampleRate() );
|
||||
|
||||
/* Finally, register to receive samples from the tuner */
|
||||
/* Fire a sample rate change event to get the decimation chain setup */
|
||||
frequencyChanged( new FrequencyChangeEvent(
|
||||
Attribute.SAMPLE_RATE, mTuner.getSampleRate() ) );
|
||||
|
||||
/* Schedule the decimation task to run 20 times a second */
|
||||
mTaskHandle = mThreadPoolManager.schedule( ThreadType.DECIMATION,
|
||||
new DecimationProcessor(), 50, TimeUnit.MILLISECONDS );
|
||||
|
||||
/* Finally, register to receive samples from the tuner */
|
||||
mTuner.addListener( (Listener<Float[]>)this );
|
||||
}
|
||||
|
||||
@@ -156,60 +157,73 @@ public class TunerChannelSource extends ComplexSource
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
/* Send change to Automatic Frequency Control */
|
||||
/* Send change to Automatic Frequency Control if it exists */
|
||||
if( mFrequencyChangeListener != null )
|
||||
{
|
||||
mFrequencyChangeListener.frequencyChanged( frequency, bandwidth );
|
||||
mFrequencyChangeListener.frequencyChanged( event );
|
||||
}
|
||||
|
||||
long frequencyOffset = frequency -
|
||||
mTunerChannel.getFrequency() -
|
||||
mTunerFrequencyError;
|
||||
|
||||
if( mSineWaveGenerator == null )
|
||||
switch( event.getAttribute() )
|
||||
{
|
||||
mSineWaveGenerator = new Oscillator( frequencyOffset, bandwidth );
|
||||
}
|
||||
else
|
||||
{
|
||||
mSineWaveGenerator.setFrequency( frequencyOffset );
|
||||
}
|
||||
|
||||
/* Clear the buffer for the frequency to take immediate effect */
|
||||
// mBuffer.clear();
|
||||
|
||||
mTunerFrequency = frequency;
|
||||
|
||||
/* Bandwidth/Sample rate change */
|
||||
if( bandwidth != mTunerSampleRate )
|
||||
{
|
||||
/* Get the original decimation filter output listener */
|
||||
// Listener<ComplexSample> listener = null;
|
||||
|
||||
/* Get new decimation filters */
|
||||
mDecimationFilters = FilterFactory
|
||||
.getDecimationFilters( bandwidth,
|
||||
case SAMPLE_RATE_ERROR:
|
||||
break;
|
||||
case SAMPLE_RATE:
|
||||
int sampleRate = (int)event.getValue();
|
||||
|
||||
if( mTunerSampleRate != sampleRate )
|
||||
{
|
||||
/* Set the oscillator to the new frequency */
|
||||
mSineWaveGenerator.setSampleRate( sampleRate );
|
||||
|
||||
/* Get new decimation filters */
|
||||
mDecimationFilters = FilterFactory
|
||||
.getDecimationFilters( sampleRate,
|
||||
sCHANNEL_RATE,
|
||||
sCHANNEL_PASS_FREQUENCY,
|
||||
48, //dB attenuation
|
||||
WindowType.HAMMING );
|
||||
|
||||
/* wire the filters together */
|
||||
if( mDecimationFilters.length > 1 )
|
||||
{
|
||||
for( int x = 1; x < mDecimationFilters.length; x++ )
|
||||
{
|
||||
mDecimationFilters[ x - 1 ].setListener( mDecimationFilters[ x ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* re-add the original output listener */
|
||||
mDecimationFilters[ mDecimationFilters.length - 1 ]
|
||||
.setListener( mBufferAssembler );
|
||||
|
||||
/* wire the filters together */
|
||||
if( mDecimationFilters.length > 1 )
|
||||
{
|
||||
for( int x = 1; x < mDecimationFilters.length; x++ )
|
||||
{
|
||||
mDecimationFilters[ x - 1 ]
|
||||
.setListener( mDecimationFilters[ x ] );
|
||||
}
|
||||
}
|
||||
|
||||
/* re-add the original output listener */
|
||||
mDecimationFilters[ mDecimationFilters.length - 1 ]
|
||||
.setListener( mBufferAssembler );
|
||||
|
||||
mTunerSampleRate = bandwidth;
|
||||
mTunerSampleRate = sampleRate;
|
||||
}
|
||||
break;
|
||||
case FREQUENCY_ERROR:
|
||||
mTunerFrequencyError = (int)event.getValue();
|
||||
|
||||
long frequencyErrorOffset = mTunerFrequency -
|
||||
mTunerChannel.getFrequency() -
|
||||
mTunerFrequencyError;
|
||||
|
||||
mSineWaveGenerator.setFrequency( frequencyErrorOffset );
|
||||
break;
|
||||
case FREQUENCY:
|
||||
int frequency = (int)event.getValue();
|
||||
|
||||
/* If the frequency is updated, the AFC will also get reset, so
|
||||
* we don't include the frequency error value here */
|
||||
long frequencyOffset = frequency - mTunerChannel.getFrequency();
|
||||
|
||||
mSineWaveGenerator.setFrequency( frequencyOffset );
|
||||
|
||||
mTunerFrequency = frequency;
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -264,20 +278,6 @@ public class TunerChannelSource extends ComplexSource
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic Frequency Control
|
||||
*/
|
||||
@Override
|
||||
public void setError( int error )
|
||||
{
|
||||
if( mTunerFrequencyError != error )
|
||||
{
|
||||
mTunerFrequencyError = error;
|
||||
frequencyChanged( mTunerFrequency, mTunerSampleRate );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void addListener( FrequencyChangeListener listener )
|
||||
{
|
||||
mFrequencyChangeListener = listener;
|
||||
|
||||
@@ -167,7 +167,8 @@ public abstract class TunerController implements Tunable
|
||||
|
||||
updateLOFrequency();
|
||||
|
||||
source = new TunerChannelSource( threadPoolManager, tuner, tunerChannel );
|
||||
source = new TunerChannelSource( threadPoolManager,
|
||||
tuner, tunerChannel );
|
||||
}
|
||||
|
||||
return source;
|
||||
|
||||
@@ -42,7 +42,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
|
||||
private static DecimalFormat SAMPLE_RATE_FORMAT = new DecimalFormat( "0.000" );
|
||||
|
||||
private long mFrequency;
|
||||
private int mBandwidth;
|
||||
private int mSampleRate;
|
||||
|
||||
public TunerNode( Tuner tuner )
|
||||
{
|
||||
@@ -53,7 +53,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
|
||||
try
|
||||
{
|
||||
mFrequency = tuner.getFrequency();
|
||||
mBandwidth = tuner.getSampleRate();
|
||||
mSampleRate = tuner.getSampleRate();
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
@@ -82,7 +82,7 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
|
||||
sb.append( " " );
|
||||
sb.append( FREQUENCY_FORMAT.format( (double)mFrequency / 1E6d ) );
|
||||
sb.append( " [" );
|
||||
sb.append( SAMPLE_RATE_FORMAT.format( (double)mBandwidth / 1E6d ) );
|
||||
sb.append( SAMPLE_RATE_FORMAT.format( (double)mSampleRate / 1E6d ) );
|
||||
sb.append( "] MHz" );
|
||||
|
||||
return sb.toString();
|
||||
@@ -122,11 +122,29 @@ public class TunerNode extends BaseNode implements FrequencyChangeListener
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
mBandwidth = bandwidth;
|
||||
|
||||
getModel().nodeChanged( TunerNode.this );
|
||||
switch( event.getAttribute() )
|
||||
{
|
||||
case FREQUENCY:
|
||||
int frequency = (int)event.getValue();
|
||||
|
||||
if( mFrequency != frequency )
|
||||
{
|
||||
mFrequency = frequency;
|
||||
getModel().nodeChanged( TunerNode.this );
|
||||
}
|
||||
case SAMPLE_RATE:
|
||||
int sampleRate = (int)event.getValue();
|
||||
|
||||
if( mSampleRate != sampleRate )
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
getModel().nodeChanged( TunerNode.this );
|
||||
}
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,7 +60,7 @@ public class FCD1TunerController extends FCDTunerController
|
||||
sMINIMUM_TUNABLE_FREQUENCY,
|
||||
sMAXIMUM_TUNABLE_FREQUENCY );
|
||||
|
||||
mFrequencyController.setBandwidth( sSAMPLE_RATE );
|
||||
mFrequencyController.setSampleRate( sSAMPLE_RATE );
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.FCDTunerDetailsPanel;
|
||||
@@ -91,17 +93,19 @@ public class FCD1TunerEditorPanel extends JPanel implements FrequencyChangeListe
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
//Disregard the bandwidth value, which shouldn't be changing
|
||||
try
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "FCTProController - error setting frequency [" +
|
||||
frequency + "]", e );
|
||||
}
|
||||
if( event.getAttribute() == Attribute.FREQUENCY )
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( event.getValue() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "FCTProController - error setting frequency [" +
|
||||
event.getValue() + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -53,7 +53,7 @@ public class FCD2TunerController extends FCDTunerController
|
||||
sMINIMUM_TUNABLE_FREQUENCY,
|
||||
sMAXIMUM_TUNABLE_FREQUENCY );
|
||||
|
||||
mFrequencyController.setBandwidth( sSAMPLE_RATE );
|
||||
mFrequencyController.setSampleRate( sSAMPLE_RATE );
|
||||
|
||||
try
|
||||
{
|
||||
|
||||
@@ -30,6 +30,8 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.FCDTunerDetailsPanel;
|
||||
@@ -90,17 +92,20 @@ public class FCD2TunerEditorPanel extends JPanel implements FrequencyChangeListe
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
//Disregard the bandwidth, which shouldn't be changing
|
||||
try
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "FCTProController - error setting frequency [" +
|
||||
frequency + "]", e );
|
||||
}
|
||||
if( event.getAttribute() == Attribute.FREQUENCY )
|
||||
{
|
||||
//Disregard the bandwidth, which shouldn't be changing
|
||||
try
|
||||
{
|
||||
mController.setFrequency( event.getValue() );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "FCDProController - error setting frequency [" +
|
||||
event.getValue() + "]", e );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -60,10 +60,13 @@ import org.usb4java.LibUsb;
|
||||
|
||||
import sample.Listener;
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import source.tuner.TunerController;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.usb.USBTunerDevice;
|
||||
import util.TimeStamp;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
import controller.ResourceManager;
|
||||
|
||||
public abstract class RTL2832TunerController extends TunerController
|
||||
@@ -85,7 +88,6 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
(byte)( LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR );
|
||||
public final static byte sREQUEST_ZERO = (byte)0;
|
||||
|
||||
public final static int sUSB_IRP_DATA_SIZE = 65536;
|
||||
public final static int sUSB_IRP_POOL_SIZE = 10;
|
||||
|
||||
public final static byte EEPROM_ADDRESS = (byte)0xA0;
|
||||
@@ -135,7 +137,9 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
};
|
||||
|
||||
private static final DecimalFormat mDecimalFormatter =
|
||||
new DecimalFormat( "###,###,###.#" );
|
||||
new DecimalFormat( "###,###,###.0" );
|
||||
private static final DecimalFormat mPercentFormatter =
|
||||
new DecimalFormat( "###.00" );
|
||||
|
||||
private USBTunerDevice mUSBTunerDevice;
|
||||
protected UsbDevice mUSBDevice;
|
||||
@@ -163,6 +167,9 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
private int mSampleRateAverageCount;
|
||||
protected int mOscillatorFrequency = 28800000; //28.8 MHz
|
||||
|
||||
private SampleRateMonitor mSampleRateMonitor;
|
||||
public int mBufferSize = 16384;
|
||||
|
||||
/**
|
||||
* Abstract tuner controller device. Use the static getTunerClass() method
|
||||
* to determine the tuner type, and construct the corresponding child
|
||||
@@ -1163,7 +1170,17 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
|
||||
mSampleRate = sampleRate;
|
||||
|
||||
mFrequencyController.setBandwidth( sampleRate.getRate() );
|
||||
/**
|
||||
* Adjust the size of the byte array buffers sent over the USB bus
|
||||
*/
|
||||
mBufferSize = mSampleRate.getBufferSize();
|
||||
|
||||
mFrequencyController.setSampleRate( sampleRate.getRate() );
|
||||
|
||||
if( mSampleRateMonitor != null )
|
||||
{
|
||||
mSampleRateMonitor.setSampleRate( mSampleRate.getRate() );
|
||||
}
|
||||
}
|
||||
|
||||
public void setSampleRateFrequencyCorrection( int ppm )
|
||||
@@ -1392,34 +1409,37 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
public enum SampleRate
|
||||
{
|
||||
/* Note: sample rates below 1.0MHz are subject to aliasing */
|
||||
RATE_0_240MHZ( 0x0DFC, 0x0000, 240000, "0.240 MHz" ),
|
||||
RATE_0_288MHZ( 0x08FC, 0x0000, 288000, "0.288 MHz" ),
|
||||
RATE_0_912MHZ( 0x07E6, 0x0000, 912000, "0.912 MHz" ),
|
||||
RATE_0_960MHZ( 0x077A, 0x0000, 960000, "0.960 MHz" ),
|
||||
RATE_1_200MHZ( 0x05F4, 0x0000, 1200000, "1.200 MHz" ),
|
||||
RATE_1_440MHZ( 0x0500, 0x0000, 1440000, "1.440 MHz" ),
|
||||
RATE_1_680MHZ( 0x044A, 0x0000, 1680000, "1.680 MHz" ),
|
||||
RATE_1_824MHZ( 0x03F3, 0x0000, 1824000, "1.824 MHz" ),
|
||||
RATE_2_016MHZ( 0x038F, 0x0000, 2016000, "2.016 MHz" );
|
||||
|
||||
/* Note: usb4java library buffer processing scheme doesn't seem capable
|
||||
* of supporting these rates */
|
||||
//RATE_2_400MHZ( 0x0300, 0x0000, 2400000, "2.400 MHz" ),
|
||||
//RATE_2_880MHZ( 0x0280, 0x0000, 2880000, "2.880 MHz" ),
|
||||
//RATE_3_072MHZ( 0x0258, 0x0000, 3072000, "3.072 MHz" ),
|
||||
//RATE_3_216MHZ( 0x023D, 0x0000, 3216000, "3.216 MHz" );
|
||||
RATE_0_240MHZ( 0x0DFC, 0x0000, 240000, "0.240 MHz", 16384 ),
|
||||
RATE_0_288MHZ( 0x08FC, 0x0000, 288000, "0.288 MHz", 16384 ),
|
||||
RATE_0_912MHZ( 0x07E4, 0x0000, 912000, "0.912 MHz", 32768 ),
|
||||
RATE_0_960MHZ( 0x0778, 0x0000, 960000, "0.960 MHz", 32768 ),
|
||||
RATE_1_200MHZ( 0x05F4, 0x0000, 1200000, "1.200 MHz", 65536 ),
|
||||
RATE_1_440MHZ( 0x04FC, 0x0000, 1440000, "1.440 MHz", 65536 ),
|
||||
RATE_1_680MHZ( 0x0448, 0x0000, 1680000, "1.680 MHz", 65536 ),
|
||||
RATE_1_824MHZ( 0x03F0, 0x0000, 1824000, "1.824 MHz", 65536 ),
|
||||
RATE_2_016MHZ( 0x038C, 0x0000, 2016000, "2.016 MHz", 131072 ),
|
||||
RATE_2_208MHZ( 0x0340, 0x0000, 2208000, "2.208 MHz", 131072 ),
|
||||
RATE_2_400MHZ( 0x02FC, 0x0000, 2400000, "2.400 MHz", 131072 ),
|
||||
RATE_2_640MHZ( 0x02B4, 0x8000, 2640000, "2.640 MHz", 262144 ),
|
||||
RATE_2_880MHZ( 0x027C, 0x0000, 2880000, "2.880 MHz", 262144 );
|
||||
|
||||
private int mRatioHigh;
|
||||
private int mRatioLow;
|
||||
private int mRate;
|
||||
private String mLabel;
|
||||
private int mBufferSize;
|
||||
|
||||
private SampleRate( int ratioHigh, int ratioLow, int rate, String label )
|
||||
private SampleRate( int ratioHigh,
|
||||
int ratioLow,
|
||||
int rate,
|
||||
String label,
|
||||
int bufferSize )
|
||||
{
|
||||
mRatioHigh = ratioHigh;
|
||||
mRatioLow = ratioLow;
|
||||
mRate = rate;
|
||||
mLabel = label;
|
||||
mBufferSize = bufferSize;
|
||||
}
|
||||
|
||||
public int getRatioHighBits()
|
||||
@@ -1447,6 +1467,11 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public int getBufferSize()
|
||||
{
|
||||
return mBufferSize;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the sample rate that is equal to the argument or the next
|
||||
* higher sample rate
|
||||
@@ -1545,7 +1570,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
for( int x = 0; x < sUSB_IRP_POOL_SIZE; x++ )
|
||||
{
|
||||
UsbIrp irp = mUSBPipe.createUsbIrp();
|
||||
irp.setData( new byte[ sUSB_IRP_DATA_SIZE ] );
|
||||
irp.setData( new byte[ mBufferSize ] );
|
||||
irps.add( irp );
|
||||
}
|
||||
|
||||
@@ -1566,12 +1591,15 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
if( mUSBPipe.isOpen() )
|
||||
{
|
||||
mSampleDispatcherTask = mExecutor
|
||||
.scheduleAtFixedRate( new BufferDispatcher(),
|
||||
0, 20, TimeUnit.MILLISECONDS );
|
||||
.scheduleAtFixedRate( new BufferDispatcher(),
|
||||
0, 20, TimeUnit.MILLISECONDS );
|
||||
|
||||
mSampleRateMonitor =
|
||||
new SampleRateMonitor( mSampleRate.getRate() );
|
||||
|
||||
mSampleRateCounterTask = mExecutor
|
||||
.scheduleAtFixedRate( new SampleRateMonitor(),
|
||||
60, 60, TimeUnit.SECONDS );
|
||||
.scheduleAtFixedRate( mSampleRateMonitor,
|
||||
10, 10, TimeUnit.SECONDS );
|
||||
|
||||
mUSBPipe.asyncSubmit( irps );
|
||||
}
|
||||
@@ -1645,7 +1673,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
{
|
||||
try
|
||||
{
|
||||
mUSBPipe.asyncSubmit( new byte[ sUSB_IRP_DATA_SIZE ] );
|
||||
mUSBPipe.asyncSubmit( new byte[ mBufferSize ] );
|
||||
}
|
||||
catch ( UsbNotActiveException | UsbNotOpenException
|
||||
| IllegalArgumentException | UsbDisconnectedException
|
||||
@@ -1707,37 +1735,103 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
*/
|
||||
public class SampleRateMonitor implements Runnable
|
||||
{
|
||||
private static final int BUFFER_SIZE = 5;
|
||||
private int mTargetSampleRate;
|
||||
private int mSampleRateMinimum;
|
||||
private int mSampleRateMaximum;
|
||||
private int mNewTargetSampleRate;
|
||||
private FloatAveragingBuffer mRateErrorBuffer =
|
||||
new FloatAveragingBuffer( BUFFER_SIZE );
|
||||
private AtomicBoolean mRateChanged = new AtomicBoolean();
|
||||
|
||||
public SampleRateMonitor( int sampleRate )
|
||||
{
|
||||
setTargetRate( sampleRate );
|
||||
}
|
||||
|
||||
public void setSampleRate( int sampleRate )
|
||||
{
|
||||
mNewTargetSampleRate = sampleRate;
|
||||
mRateChanged.set( true );
|
||||
}
|
||||
|
||||
private void setTargetRate( int rate )
|
||||
{
|
||||
mTargetSampleRate = rate;
|
||||
mSampleRateMinimum = (int)( (float)mTargetSampleRate * 0.95f );
|
||||
mSampleRateMaximum = (int)( (float)mTargetSampleRate * 1.05f );
|
||||
|
||||
for( int x = 0; x < BUFFER_SIZE; x++ )
|
||||
{
|
||||
mRateErrorBuffer.get( 0 );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
int count = mSampleCounter.getAndSet( 0 );
|
||||
|
||||
double rate = (double)count / 120.0d;
|
||||
|
||||
mSampleRateAverageSum += rate;
|
||||
mSampleRateAverageCount++;
|
||||
|
||||
double average = mSampleRateAverageSum / (double)mSampleRateAverageCount;
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( TimeStamp.getTimeStamp( " " ) );
|
||||
sb.append( " RTL-2832 [" );
|
||||
if( mDescriptor != null )
|
||||
if( mRateChanged.compareAndSet( true, false ) )
|
||||
{
|
||||
sb.append( mDescriptor.getSerial() );
|
||||
setTargetRate( mNewTargetSampleRate );
|
||||
|
||||
/* Reset the sample counter */
|
||||
mSampleCounter.set( 0 );
|
||||
|
||||
mLog.info( "monitor reset for new sample rate [" + mTargetSampleRate + "]" );
|
||||
System.out.println( "monitor reset for new sample rate [" + mTargetSampleRate + "]" );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "DESCRIPTOR IS NULL" );
|
||||
int count = mSampleCounter.getAndSet( 0 );
|
||||
|
||||
float current = (float)count / 20.0f;
|
||||
|
||||
/**
|
||||
* Only accept values +/- 5% of target rate
|
||||
*/
|
||||
float average;
|
||||
|
||||
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
|
||||
{
|
||||
average = mTargetSampleRate;
|
||||
}
|
||||
|
||||
StringBuilder sb = new StringBuilder();
|
||||
sb.append( TimeStamp.getTimeStamp( " " ) );
|
||||
sb.append( " RTL-2832 [" );
|
||||
if( mDescriptor != null )
|
||||
{
|
||||
sb.append( mDescriptor.getSerial() );
|
||||
}
|
||||
else
|
||||
{
|
||||
sb.append( "DESCRIPTOR IS NULL" );
|
||||
}
|
||||
sb.append( "] sample rate current [" );
|
||||
sb.append( mDecimalFormatter.format( current ) );
|
||||
sb.append( " Hz " );
|
||||
sb.append( mPercentFormatter.format( 100.0f * ( current / (float)mTargetSampleRate ) ) );
|
||||
sb.append( "% ] average error [" );
|
||||
sb.append( average );
|
||||
sb.append( " Hz ] target " );
|
||||
sb.append( mTargetSampleRate );
|
||||
|
||||
System.out.println( sb.toString() );
|
||||
|
||||
mLog.info( sb.toString() );
|
||||
}
|
||||
sb.append( "] Sample Rate - current: " );
|
||||
sb.append( mDecimalFormatter.format( rate ) );
|
||||
sb.append( "\taverage: " );
|
||||
sb.append( mDecimalFormatter.format( average ) );
|
||||
sb.append( " count:" );
|
||||
sb.append( mSampleRateAverageCount );
|
||||
|
||||
mLog.info( sb.toString() );
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -31,7 +31,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import source.tuner.rtl.RTL2832InfoPanel;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
@@ -94,23 +96,28 @@ public class E4KTunerEditorPanel extends JPanel implements FrequencyChangeListen
|
||||
* apply end-user requested frequency changes against the tuner
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( final long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
if( event.getAttribute() == Attribute.FREQUENCY )
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "E4KTunerController - error setting frequency [" +
|
||||
frequency + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
final int frequency = (int)event.getValue();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "E4KTunerController - error setting frequency [" +
|
||||
frequency + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -77,6 +77,7 @@ public class R820TTunerConfigurationPanel extends JPanel
|
||||
private JTextField mName;
|
||||
|
||||
private JSpinner mFrequencyCorrection;
|
||||
private JSpinner mSampleRateCorrection;
|
||||
private JComboBox<R820TGain> mComboMasterGain;
|
||||
private JComboBox<R820TMixerGain> mComboMixerGain;
|
||||
private JComboBox<R820TLNAGain> mComboLNAGain;
|
||||
@@ -268,6 +269,65 @@ public class R820TTunerConfigurationPanel extends JPanel
|
||||
add( new JLabel( "Sample Rate:" ) );
|
||||
add( mComboSampleRate, "growx,push" );
|
||||
|
||||
/**
|
||||
* Sample Rate Correction
|
||||
*/
|
||||
SpinnerModel sampleRateCorrectionModel =
|
||||
new SpinnerNumberModel( 0, //initial value
|
||||
-32768, //min
|
||||
32767, //max
|
||||
1 ); //step
|
||||
|
||||
mSampleRateCorrection = new JSpinner( sampleRateCorrectionModel );
|
||||
|
||||
JSpinner.NumberEditor sampleRateCorrectionEditor =
|
||||
(JSpinner.NumberEditor)mSampleRateCorrection.getEditor();
|
||||
|
||||
DecimalFormat sampleRateCorrectionFormat =
|
||||
sampleRateCorrectionEditor.getFormat();
|
||||
|
||||
sampleRateCorrectionFormat.setMinimumFractionDigits( 0 );
|
||||
|
||||
sampleRateCorrectionEditor.getTextField()
|
||||
.setHorizontalAlignment( SwingConstants.CENTER );
|
||||
|
||||
mSampleRateCorrection.addChangeListener( new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged( ChangeEvent e )
|
||||
{
|
||||
final int value = ((SpinnerNumberModel)mSampleRateCorrection
|
||||
.getModel()).getNumber().intValue();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setSampleRateFrequencyCorrection( value );
|
||||
}
|
||||
catch ( SourceException | UsbException e1 )
|
||||
{
|
||||
JOptionPane.showMessageDialog(
|
||||
R820TTunerConfigurationPanel.this,
|
||||
"E4K Tuner Controller - couldn't apply "
|
||||
+ "sample rate correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
|
||||
mLog.error( "E4K Tuner Controller - couldn't apply "
|
||||
+ "sample rate correction value: " + value +
|
||||
e1.getLocalizedMessage() );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
} );
|
||||
|
||||
add( mSampleRateCorrection );
|
||||
add( new JLabel( "Sample Rate Correction (ppm)" ), "grow,push" );
|
||||
|
||||
/**
|
||||
* Gain Controls
|
||||
*/
|
||||
|
||||
@@ -31,7 +31,9 @@ import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import source.tuner.rtl.RTL2832InfoPanel;
|
||||
|
||||
import com.jidesoft.swing.JideTabbedPane;
|
||||
@@ -93,23 +95,28 @@ public class R820TTunerEditorPanel extends JPanel implements FrequencyChangeList
|
||||
* apply end-user requested frequency changes against the tuner
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( final long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
if( event.getAttribute() == Attribute.FREQUENCY )
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "R820T Tuner Controller - error setting frequency [" +
|
||||
frequency + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
final int frequency = (int)event.getValue();
|
||||
|
||||
EventQueue.invokeLater( new Runnable()
|
||||
{
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
try
|
||||
{
|
||||
mController.setFrequency( frequency );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
mLog.error( "R820T Tuner Controller - error setting frequency [" +
|
||||
frequency + "]", e );
|
||||
}
|
||||
}
|
||||
} );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -23,6 +23,8 @@ import settings.Setting;
|
||||
import settings.SettingChangeListener;
|
||||
import settings.SettingsManager;
|
||||
import source.Source.SampleType;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import spectrum.converter.DFTResultsConverter;
|
||||
import spectrum.converter.RealDecibelConverter;
|
||||
import spectrum.menu.AmplificationItem;
|
||||
@@ -86,7 +88,8 @@ public class ChannelSpectrumPanel extends JPanel
|
||||
mDecimatingSampleAssembler = new DecimatingSampleAssembler( mDFTProcessor );
|
||||
|
||||
/* Set the DFTProcessor to the decimated 24kHz sample rate */
|
||||
mDFTProcessor.frequencyChanged( 0, 24000 );
|
||||
mDFTProcessor.frequencyChanged(
|
||||
new FrequencyChangeEvent( Attribute.SAMPLE_RATE, 24000 ) );
|
||||
|
||||
initGui();
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.slf4j.LoggerFactory;
|
||||
import sample.Listener;
|
||||
import source.Source;
|
||||
import source.Source.SampleType;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import spectrum.converter.DFTResultsConverter;
|
||||
import dsp.filter.Window;
|
||||
@@ -443,11 +444,19 @@ public class DFTProcessor implements Listener<Float[]>,
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
mSampleRate = bandwidth;
|
||||
|
||||
calculateConsumptionRate();
|
||||
switch( event.getAttribute() )
|
||||
{
|
||||
case SAMPLE_RATE_ERROR:
|
||||
break;
|
||||
case SAMPLE_RATE:
|
||||
mSampleRate = (int)event.getValue();
|
||||
calculateConsumptionRate();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -36,6 +36,7 @@ import settings.ColorSetting;
|
||||
import settings.ColorSetting.ColorSettingName;
|
||||
import settings.Setting;
|
||||
import settings.SettingChangeListener;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.TunerChannel;
|
||||
import controller.ResourceManager;
|
||||
@@ -523,10 +524,22 @@ public class OverlayPanel extends JPanel
|
||||
* Frequency change event handler
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
mBandwidth = bandwidth;
|
||||
mFrequency = frequency;
|
||||
switch( event.getAttribute() )
|
||||
{
|
||||
case SAMPLE_RATE_ERROR:
|
||||
// System.out.println( "OVerlay panel got a sample rate error update" );
|
||||
break;
|
||||
case SAMPLE_RATE:
|
||||
mBandwidth = (int)event.getValue();
|
||||
break;
|
||||
case FREQUENCY:
|
||||
mFrequency = (int)event.getValue();
|
||||
break;
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reset the visible channel configs list
|
||||
|
||||
@@ -55,9 +55,11 @@ import settings.SettingChangeListener;
|
||||
import settings.SettingsManager;
|
||||
import source.Source.SampleType;
|
||||
import source.SourceException;
|
||||
import source.tuner.FrequencyChangeEvent;
|
||||
import source.tuner.FrequencyChangeListener;
|
||||
import source.tuner.Tuner;
|
||||
import source.tuner.TunerSelectionListener;
|
||||
import source.tuner.FrequencyChangeEvent.Attribute;
|
||||
import spectrum.converter.ComplexDecibelConverter;
|
||||
import spectrum.converter.DFTResultsConverter;
|
||||
import spectrum.menu.AmplificationItem;
|
||||
@@ -340,10 +342,10 @@ public class SpectralDisplayPanel extends JPanel
|
||||
* Receives frequency change events -- primarily from tuner components.
|
||||
*/
|
||||
@Override
|
||||
public void frequencyChanged( long frequency, int bandwidth )
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
{
|
||||
mOverlayPanel.frequencyChanged( frequency, bandwidth );
|
||||
mDFTProcessor.frequencyChanged( frequency, bandwidth );
|
||||
mOverlayPanel.frequencyChanged( event );
|
||||
mDFTProcessor.frequencyChanged( event );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -381,11 +383,15 @@ public class SpectralDisplayPanel extends JPanel
|
||||
//Register the dft processor to receive samples from the tuner
|
||||
mTuner.addListener( (Listener<Float[]>)mDFTProcessor );
|
||||
|
||||
//Fire a frequency change event so that everyone can init
|
||||
//Fire frequency and sample rate change events so that everyone
|
||||
//can init
|
||||
try
|
||||
{
|
||||
frequencyChanged( mTuner.getFrequency(),
|
||||
mTuner.getSampleRate() );
|
||||
frequencyChanged( new FrequencyChangeEvent(
|
||||
Attribute.FREQUENCY, mTuner.getFrequency() ) );
|
||||
|
||||
frequencyChanged( new FrequencyChangeEvent(
|
||||
Attribute.SAMPLE_RATE, mTuner.getSampleRate() ) );
|
||||
}
|
||||
catch ( SourceException e )
|
||||
{
|
||||
|
||||
@@ -42,6 +42,11 @@ public class Oscillator
|
||||
update();
|
||||
}
|
||||
|
||||
public ComplexSample getCurrentAngle()
|
||||
{
|
||||
return mCurrentAngle;
|
||||
}
|
||||
|
||||
private void update()
|
||||
{
|
||||
float anglePerSample =
|
||||
@@ -64,6 +69,7 @@ public class Oscillator
|
||||
*/
|
||||
public void setSampleRate( int sampleRate )
|
||||
{
|
||||
System.out.println( "Oscillator - setting sampleRate to:" + sampleRate );
|
||||
mSampleRate = (double)sampleRate;
|
||||
update();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user