mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Initial commit of redesigned internal processing and audio management.
Note: Several of the decoders are currently non-functioning in this commit. If you want the latest functioning codebase, please checkout the commit prior to this one. All decoders will eventually be updated with this new architecture. Currently broken: - Logging and recording - Aux decoders (Fleetsync/MDC/LoJack/Tait) - LTR/Passport decoders Changes in this commit: - Module architecture for decoders and components with central provisioning by the DecoderFactory - Transition from Complex sample stream processing to float buffer processing for improved memory management - Redesigned filter structures - to support buffers and streams - Resolved several memory leak issues - Universal sharing of the thread pool manager - Added centralized audio management with call/user prioritization and new gui with mute/volume controls - Embedded audio metadata for eventual streaming support - Redesigned ProcessingChain to support independent re-use - Added new TrafficChannelManager to handle traffic channel allocations - Traffic Channel pool size and Call timeout available in P25 and MPT1327 configs - Redesigned channel and decoder gui components
This commit is contained in:
@@ -23,25 +23,25 @@ import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.RejectedExecutionException;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.complex.Complex;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import sample.complex.ComplexSample;
|
||||
import sample.complex.ComplexSampleAssembler;
|
||||
import source.ComplexSource;
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Attribute;
|
||||
import source.tuner.frequency.FrequencyChangeListener;
|
||||
import util.Oscillator;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
import dsp.filter.ComplexPrimeCICDecimate;
|
||||
import dsp.filter.FilterFactory;
|
||||
import dsp.filter.Window.WindowType;
|
||||
import dsp.filter.cic.ComplexPrimeCICDecimate;
|
||||
|
||||
public class TunerChannelSource extends ComplexSource
|
||||
implements FrequencyChangeListener,
|
||||
@@ -57,17 +57,18 @@ public class TunerChannelSource extends ComplexSource
|
||||
new LinkedTransferQueue<ComplexBuffer>();
|
||||
private Tuner mTuner;
|
||||
private TunerChannel mTunerChannel;
|
||||
private Oscillator mSineWaveGenerator;
|
||||
private Oscillator mMixer;
|
||||
private ComplexPrimeCICDecimate mDecimationFilter;
|
||||
|
||||
private ComplexSampleAssembler mBufferAssembler =
|
||||
new ComplexSampleAssembler( 3000 );
|
||||
private long mTunerFrequency = 0;
|
||||
private int mTunerFrequencyError = 0;
|
||||
private int mTunerSampleRate;
|
||||
private Listener<ComplexBuffer> mListener;
|
||||
private FrequencyChangeListener mFrequencyChangeListener;
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
private ScheduledFuture<?> mTaskHandle;
|
||||
|
||||
private long mTunerFrequency = 0;
|
||||
private int mTunerFrequencyError = 0;
|
||||
private int mTunerSampleRate;
|
||||
|
||||
private DecimationProcessor mDecimationProcessor = new DecimationProcessor();
|
||||
|
||||
public TunerChannelSource( ThreadPoolManager threadPoolManager,
|
||||
Tuner tuner,
|
||||
@@ -77,7 +78,6 @@ public class TunerChannelSource extends ComplexSource
|
||||
super( "Tuner Channel Source" );
|
||||
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
|
||||
|
||||
mTuner = tuner;
|
||||
mTuner.addListener( (FrequencyChangeListener)this );
|
||||
@@ -89,7 +89,7 @@ public class TunerChannelSource extends ComplexSource
|
||||
/* Setup the frequency translator to the current source frequency */
|
||||
long frequencyOffset = mTunerFrequency - mTunerChannel.getFrequency();
|
||||
|
||||
mSineWaveGenerator = new Oscillator( frequencyOffset, mTuner.getSampleRate() );
|
||||
mMixer = new Oscillator( frequencyOffset, mTuner.getSampleRate() );
|
||||
|
||||
/* Fire a sample rate change event to get the decimation chain setup */
|
||||
frequencyChanged( new FrequencyChangeEvent(
|
||||
@@ -97,7 +97,7 @@ public class TunerChannelSource extends ComplexSource
|
||||
|
||||
/* Schedule the decimation task to run 50 times a second */
|
||||
mTaskHandle = mThreadPoolManager.scheduleFixedRate( ThreadType.DECIMATION,
|
||||
new DecimationProcessor(), 20, TimeUnit.MILLISECONDS );
|
||||
mDecimationProcessor, 20, TimeUnit.MILLISECONDS );
|
||||
|
||||
/* Finally, register to receive samples from the tuner */
|
||||
mTuner.addListener( (Listener<ComplexBuffer>)this );
|
||||
@@ -106,31 +106,44 @@ public class TunerChannelSource extends ComplexSource
|
||||
@Override
|
||||
public void dispose()
|
||||
{
|
||||
mFrequencyChangeListener = null;
|
||||
|
||||
//Tell the tuner to release our resources
|
||||
/* Tell the tuner to release/unregister our resources */
|
||||
mTuner.removeListener( (FrequencyChangeListener)this );
|
||||
mTuner.releaseChannel( this );
|
||||
mTuner = null;
|
||||
mTunerChannel = null;
|
||||
|
||||
/* Flag the decimation processor to shutdown */
|
||||
if( mDecimationProcessor != null )
|
||||
{
|
||||
mDecimationProcessor.dispose();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Cleanup method to allow the decimation processor to perform final cleanup
|
||||
* once it gracefully shuts itself down
|
||||
*/
|
||||
private void cleanup()
|
||||
{
|
||||
if( mTaskHandle != null )
|
||||
{
|
||||
mThreadPoolManager.cancel( mTaskHandle );
|
||||
mThreadPoolManager = null;
|
||||
mTaskHandle = null;
|
||||
}
|
||||
|
||||
|
||||
|
||||
mBuffer.clear();
|
||||
mBuffer = null;
|
||||
|
||||
// mDecimationFilter.dispose();
|
||||
mFrequencyChangeListener = null;
|
||||
mListener = null;
|
||||
|
||||
mMixer = null;
|
||||
|
||||
mDecimationFilter.dispose();
|
||||
mDecimationFilter = null;
|
||||
|
||||
mBufferAssembler.dispose();
|
||||
|
||||
mTuner = null;
|
||||
|
||||
mTunerChannel = null;
|
||||
|
||||
mTunerChannel = null;
|
||||
mTuner = null;
|
||||
}
|
||||
|
||||
public Tuner getTuner()
|
||||
@@ -144,22 +157,31 @@ public class TunerChannelSource extends ComplexSource
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( ComplexBuffer sampleArray )
|
||||
public void receive( ComplexBuffer buffer )
|
||||
{
|
||||
mBuffer.add( sampleArray );
|
||||
mBuffer.add( buffer );
|
||||
}
|
||||
|
||||
public void setFrequencyChangeListener( FrequencyChangeListener listener )
|
||||
{
|
||||
mFrequencyChangeListener = listener;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setListener( Listener<List<ComplexSample>> listener )
|
||||
{
|
||||
mBufferAssembler.setListener( listener );
|
||||
}
|
||||
|
||||
public void setListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
/* Get a pointer to the listener so that if we have to change the
|
||||
* decimation filter, we can re-add the listener */
|
||||
mListener = listener;
|
||||
|
||||
mDecimationFilter.setListener( listener );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void removeListener( Listener<List<ComplexSample>> listener )
|
||||
{
|
||||
mBufferAssembler.removeListener( listener );
|
||||
}
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mDecimationFilter.removeListener();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void frequencyChanged( FrequencyChangeEvent event )
|
||||
@@ -180,7 +202,7 @@ public class TunerChannelSource extends ComplexSource
|
||||
if( mTunerSampleRate != sampleRate )
|
||||
{
|
||||
/* Set the oscillator to the new frequency */
|
||||
mSineWaveGenerator.setSampleRate( sampleRate );
|
||||
mMixer.setSampleRate( sampleRate );
|
||||
|
||||
/* Get new decimation filter */
|
||||
mDecimationFilter = FilterFactory
|
||||
@@ -192,7 +214,7 @@ public class TunerChannelSource extends ComplexSource
|
||||
WindowType.HAMMING );
|
||||
|
||||
/* re-add the original output listener */
|
||||
mDecimationFilter.setListener( mBufferAssembler );
|
||||
mDecimationFilter.setListener( mListener );
|
||||
|
||||
mTunerSampleRate = sampleRate;
|
||||
}
|
||||
@@ -204,7 +226,7 @@ public class TunerChannelSource extends ComplexSource
|
||||
mTunerChannel.getFrequency() -
|
||||
mTunerFrequencyError;
|
||||
|
||||
mSineWaveGenerator.setFrequency( frequencyErrorOffset );
|
||||
mMixer.setFrequency( frequencyErrorOffset );
|
||||
break;
|
||||
case FREQUENCY:
|
||||
long frequency = event.getValue().longValue();
|
||||
@@ -215,7 +237,7 @@ public class TunerChannelSource extends ComplexSource
|
||||
|
||||
long frequencyOffset = frequency - mTunerChannel.getFrequency();
|
||||
|
||||
mSineWaveGenerator.setFrequency( frequencyOffset );
|
||||
mMixer.setFrequency( frequencyOffset );
|
||||
|
||||
mTunerFrequency = frequency;
|
||||
break;
|
||||
@@ -226,16 +248,27 @@ public class TunerChannelSource extends ComplexSource
|
||||
|
||||
public int getSampleRate() throws SourceException
|
||||
{
|
||||
return mTuner.getSampleRate();
|
||||
return CHANNEL_RATE;
|
||||
}
|
||||
|
||||
public long getFrequency() throws SourceException
|
||||
{
|
||||
return mTuner.getFrequency();
|
||||
return mTunerChannel.getFrequency();
|
||||
}
|
||||
|
||||
/**
|
||||
* Decimates an inbound buffer of I/Q samples from the source down to the
|
||||
* standard 48000 channel sample rate
|
||||
*/
|
||||
public class DecimationProcessor implements Runnable
|
||||
{
|
||||
private AtomicBoolean mDispose = new AtomicBoolean( false );
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
mDispose.set( true );
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
@@ -244,38 +277,59 @@ public class TunerChannelSource extends ComplexSource
|
||||
* run the program out of memory */
|
||||
try
|
||||
{
|
||||
List<ComplexBuffer> sampleBuffers =
|
||||
new ArrayList<ComplexBuffer>();
|
||||
|
||||
if( mBuffer != null )
|
||||
/* Check to see if we've been shutdown */
|
||||
if( mDispose.get() )
|
||||
{
|
||||
/* Limit to 4, so that after a garbage collect we don't
|
||||
* induce wild swings as it tries to take tons of samples
|
||||
* and process them, causing delays and buffer refill */
|
||||
mBuffer.drainTo( sampleBuffers, 4 );
|
||||
|
||||
for( ComplexBuffer buffer: sampleBuffers )
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
List<ComplexBuffer> sampleBuffers =
|
||||
new ArrayList<ComplexBuffer>();
|
||||
|
||||
if( mBuffer != null )
|
||||
{
|
||||
float[] samples = buffer.getSamples();
|
||||
float[] translated = new float[ samples.length ];
|
||||
|
||||
/* Perform frequency translation */
|
||||
for( int x = 0; x < samples.length; x += 2 )
|
||||
mBuffer.drainTo( sampleBuffers, 4 );
|
||||
|
||||
for( ComplexBuffer buffer: sampleBuffers )
|
||||
{
|
||||
ComplexSample multiplier =
|
||||
mSineWaveGenerator.nextComplex();
|
||||
|
||||
translated[ x ] = ( samples[ x ] * multiplier.inphase() ) -
|
||||
( samples[ x + 1 ] * multiplier.quadrature() );
|
||||
|
||||
translated[ x + 1 ] = ( samples[ x + 1 ] * multiplier.inphase() ) +
|
||||
( samples[ x ] * multiplier.quadrature() );
|
||||
/* Check to see if we've been shutdown */
|
||||
if( mDispose.get() )
|
||||
{
|
||||
cleanup();
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
float[] samples = buffer.getSamples();
|
||||
|
||||
/* We make a copy of the buffer so that we don't affect
|
||||
* anyone else that is using the same buffer, like other
|
||||
* channels or the spectral display */
|
||||
float[] translated = new float[ samples.length ];
|
||||
|
||||
/* Perform frequency translation */
|
||||
for( int x = 0; x < samples.length; x += 2 )
|
||||
{
|
||||
mMixer.rotate();
|
||||
|
||||
translated[ x ] = Complex.multiplyInphase(
|
||||
samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() );
|
||||
|
||||
translated[ x + 1 ] = Complex.multiplyQuadrature(
|
||||
samples[ x ], samples[ x + 1 ], mMixer.inphase(), mMixer.quadrature() );
|
||||
}
|
||||
|
||||
if( mDecimationFilter != null )
|
||||
{
|
||||
mDecimationFilter.receive( new ComplexBuffer( translated ) );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
mDecimationFilter.receive( translated );
|
||||
sampleBuffers.clear();
|
||||
}
|
||||
|
||||
sampleBuffers.clear();
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
@@ -284,9 +338,4 @@ public class TunerChannelSource extends ComplexSource
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void addListener( FrequencyChangeListener listener )
|
||||
{
|
||||
mFrequencyChangeListener = listener;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -156,9 +156,8 @@ public abstract class TunerController implements Tunable
|
||||
}
|
||||
|
||||
public TunerChannelSource getChannel( ThreadPoolManager threadPoolManager,
|
||||
Tuner tuner, TunerChannel tunerChannel )
|
||||
throws RejectedExecutionException,
|
||||
SourceException
|
||||
Tuner tuner, TunerChannel tunerChannel )
|
||||
throws RejectedExecutionException, SourceException
|
||||
{
|
||||
TunerChannelSource source = null;
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.usb4java.LibUsb;
|
||||
import source.Source;
|
||||
import source.SourceException;
|
||||
import source.config.SourceConfigTuner;
|
||||
import source.config.SourceConfiguration;
|
||||
import source.mixer.MixerManager;
|
||||
import source.tuner.fcd.FCDTuner;
|
||||
import source.tuner.fcd.proV1.FCD1TunerController;
|
||||
@@ -44,7 +45,6 @@ import source.tuner.rtl.RTL2832TunerController;
|
||||
import source.tuner.rtl.e4k.E4KTunerController;
|
||||
import source.tuner.rtl.r820t.R820TTunerController;
|
||||
import controller.ResourceManager;
|
||||
import controller.channel.ProcessingChain;
|
||||
|
||||
public class TunerManager
|
||||
{
|
||||
@@ -76,15 +76,17 @@ public class TunerManager
|
||||
* Iterates current tuners to get a tuner channel source for the frequency
|
||||
* specified in the channel config's source config object
|
||||
*/
|
||||
public Source getSource( ProcessingChain processingChain )
|
||||
public Source getSource( SourceConfiguration config, int bandwidth )
|
||||
{
|
||||
TunerChannelSource retVal = null;
|
||||
|
||||
|
||||
if( processingChain.getChannel().getSourceConfiguration()
|
||||
instanceof SourceConfigTuner )
|
||||
if( config instanceof SourceConfigTuner )
|
||||
{
|
||||
TunerChannel tunerChannel = processingChain.getChannel().getTunerChannel();
|
||||
SourceConfigTuner tunerConfig = (SourceConfigTuner)config;
|
||||
|
||||
TunerChannel tunerChannel = tunerConfig.getTunerChannel();
|
||||
|
||||
tunerChannel.setBandwidth( bandwidth );
|
||||
|
||||
Iterator<Tuner> it = mTuners.iterator();
|
||||
|
||||
@@ -358,7 +360,8 @@ public class TunerManager
|
||||
try
|
||||
{
|
||||
HackRFTunerController hackRFController =
|
||||
new HackRFTunerController( device, descriptor );
|
||||
new HackRFTunerController( device, descriptor,
|
||||
mResourceManager.getThreadPoolManager() );
|
||||
|
||||
hackRFController.init();
|
||||
|
||||
@@ -409,7 +412,8 @@ public class TunerManager
|
||||
try
|
||||
{
|
||||
E4KTunerController controller =
|
||||
new E4KTunerController( device, deviceDescriptor );
|
||||
new E4KTunerController( device, deviceDescriptor,
|
||||
mResourceManager.getThreadPoolManager() );
|
||||
|
||||
controller.init();
|
||||
|
||||
@@ -432,14 +436,12 @@ public class TunerManager
|
||||
+ "controller - " + se.getLocalizedMessage() );
|
||||
}
|
||||
case RAFAELMICRO_R820T:
|
||||
mLog.debug( "attempting to construct R820T "
|
||||
+ "tuner controller" );
|
||||
try
|
||||
{
|
||||
R820TTunerController controller =
|
||||
new R820TTunerController( device, deviceDescriptor );
|
||||
new R820TTunerController( device, deviceDescriptor,
|
||||
mResourceManager.getThreadPoolManager() );
|
||||
|
||||
mLog.debug( "initializing R820T tuner controller" );
|
||||
controller.init();
|
||||
|
||||
RTL2832Tuner rtlTuner =
|
||||
@@ -450,14 +452,8 @@ public class TunerManager
|
||||
|
||||
if( config != null )
|
||||
{
|
||||
mLog.debug( "applying tuner config to R820T tuner" );
|
||||
rtlTuner.apply( config );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.debug( "R820T tuner config was "
|
||||
+ "null - not applied" );
|
||||
}
|
||||
|
||||
return new TunerInitStatus( rtlTuner, "LOADED" );
|
||||
}
|
||||
|
||||
@@ -25,11 +25,11 @@ import sample.real.RealSampleListener;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Attribute;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
|
||||
public class AutomaticFrequencyControl extends FrequencyCorrectionControl
|
||||
public class AutomaticFrequencyControl_R extends FrequencyCorrectionControl
|
||||
implements RealSampleListener
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AutomaticFrequencyControl.class );
|
||||
LoggerFactory.getLogger( AutomaticFrequencyControl_R.class );
|
||||
|
||||
private static float LARGE_ERROR = 0.300f;
|
||||
private static float MEDIUM_ERROR = 0.150f;
|
||||
@@ -64,7 +64,7 @@ public class AutomaticFrequencyControl extends FrequencyCorrectionControl
|
||||
*
|
||||
* @param maximum - maximum allowable (+/-) frequency correction value.
|
||||
*/
|
||||
public AutomaticFrequencyControl( int maximum )
|
||||
public AutomaticFrequencyControl_R( int maximum )
|
||||
{
|
||||
super( maximum );
|
||||
}
|
||||
197
src/source/tuner/frequency/AutomaticFrequencyControl_RB.java
Normal file
197
src/source/tuner/frequency/AutomaticFrequencyControl_RB.java
Normal file
@@ -0,0 +1,197 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
/*******************************************************************************
|
||||
* SDR Trunk
|
||||
* Copyright (C) 2015 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/>
|
||||
******************************************************************************/
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import sample.Listener;
|
||||
import sample.real.RealBuffer;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Attribute;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
|
||||
public class AutomaticFrequencyControl_RB extends FrequencyCorrectionControl
|
||||
implements Listener<RealBuffer>
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( AutomaticFrequencyControl_RB.class );
|
||||
|
||||
private static float LARGE_ERROR = 0.300f;
|
||||
private static float MEDIUM_ERROR = 0.150f;
|
||||
private static float SMALL_ERROR = 0.030f;
|
||||
private static float FINE_ERROR = 0.015f;
|
||||
|
||||
private static int LARGE_FREQUENCY_CORRECTION = 1500; //Hertz
|
||||
private static int MEDIUM_FREQUENCY_CORRECTION = 500;
|
||||
private static int SMALL_FREQUENCY_CORRECTION = 100;
|
||||
private static int FINE_FREQUENCY_CORRECTION = 50;
|
||||
|
||||
private static int SAMPLE_THRESHOLD = 15000;
|
||||
private Mode mMode = Mode.FAST;
|
||||
|
||||
private FloatAveragingBuffer mBuffer =
|
||||
new FloatAveragingBuffer( SAMPLE_THRESHOLD );
|
||||
|
||||
private int mSampleCounter = 0;
|
||||
private int mSkipCounter = 0;
|
||||
private int mSkipThreshold = 4;
|
||||
private int mErrorCorrection = 0;
|
||||
|
||||
public enum Mode
|
||||
{
|
||||
NORMAL,FAST;
|
||||
}
|
||||
|
||||
/**
|
||||
* Automatic Frequency Control. Monitors DC bias present in an FM
|
||||
* demodulated audio stream and issues automatic frequency corrections to
|
||||
* maintain the DC bias close to zero.
|
||||
*
|
||||
* @param maximum - maximum allowable (+/-) frequency correction value.
|
||||
*/
|
||||
public AutomaticFrequencyControl_RB( int maximum )
|
||||
{
|
||||
super( maximum );
|
||||
}
|
||||
|
||||
public void dispose()
|
||||
{
|
||||
super.dispose();
|
||||
|
||||
mBuffer = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Resets the error correction value to zero and broadcasts a change event
|
||||
*/
|
||||
public void reset()
|
||||
{
|
||||
super.reset();
|
||||
|
||||
mMode = Mode.FAST;
|
||||
dispatch();
|
||||
}
|
||||
|
||||
/**
|
||||
* Broadcasts a frequency correction change event to the registered listener
|
||||
*/
|
||||
private void dispatch()
|
||||
{
|
||||
if( mListener != null )
|
||||
{
|
||||
mListener.frequencyChanged(
|
||||
new FrequencyChangeEvent( Attribute.FREQUENCY_ERROR,
|
||||
mErrorCorrection ) );
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void receive( RealBuffer t )
|
||||
{
|
||||
float average = 0.0f;
|
||||
|
||||
for( float sample: t.getSamples() )
|
||||
{
|
||||
average = mBuffer.get( sample );
|
||||
}
|
||||
|
||||
//TODO: fix this
|
||||
|
||||
// update( average );
|
||||
}
|
||||
|
||||
public void receive( float sample )
|
||||
{
|
||||
if( mMode == Mode.FAST )
|
||||
{
|
||||
float average = mBuffer.get( sample );
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if( mSampleCounter >= SAMPLE_THRESHOLD )
|
||||
{
|
||||
mSampleCounter = 0;
|
||||
|
||||
update( average );
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
mSkipCounter++;
|
||||
|
||||
if( mSkipCounter >= mSkipThreshold )
|
||||
{
|
||||
mSkipCounter = 0;
|
||||
|
||||
float average = mBuffer.get( sample );
|
||||
|
||||
mSampleCounter++;
|
||||
|
||||
if( mSampleCounter >= SAMPLE_THRESHOLD )
|
||||
{
|
||||
mSampleCounter = 0;
|
||||
|
||||
update( average );
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void update( float average )
|
||||
{
|
||||
mMode = Mode.NORMAL;
|
||||
|
||||
if( average > LARGE_ERROR )
|
||||
{
|
||||
adjust( -LARGE_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average > MEDIUM_ERROR )
|
||||
{
|
||||
adjust( -MEDIUM_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average > SMALL_ERROR )
|
||||
{
|
||||
adjust( -SMALL_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average > FINE_ERROR )
|
||||
{
|
||||
adjust( -FINE_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average < -LARGE_ERROR )
|
||||
{
|
||||
adjust( LARGE_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average < -MEDIUM_ERROR )
|
||||
{
|
||||
adjust( MEDIUM_FREQUENCY_CORRECTION );
|
||||
mMode = Mode.FAST;
|
||||
}
|
||||
else if( average < -SMALL_ERROR )
|
||||
{
|
||||
adjust( SMALL_FREQUENCY_CORRECTION );
|
||||
}
|
||||
else if( average < -FINE_ERROR )
|
||||
{
|
||||
adjust( FINE_FREQUENCY_CORRECTION );
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -59,7 +59,7 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener
|
||||
/**
|
||||
* Registers a listener to receive frequency correction events
|
||||
*/
|
||||
public void setListener( FrequencyChangeListener listener )
|
||||
public void setFrequencyChangeListener( FrequencyChangeListener listener )
|
||||
{
|
||||
mListener = listener;
|
||||
}
|
||||
@@ -92,7 +92,7 @@ public class FrequencyCorrectionControl implements FrequencyChangeListener
|
||||
* Resets frequency correction value to zero and notifies any reset
|
||||
* listeners
|
||||
*/
|
||||
protected void reset()
|
||||
public void reset()
|
||||
{
|
||||
setErrorCorrection( 0, false );
|
||||
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
package source.tuner.frequency;
|
||||
|
||||
|
||||
public interface IFrequencyCorrectionController
|
||||
{
|
||||
public boolean hasFrequencyCorrectionControl();
|
||||
public FrequencyCorrectionControl getFrequencyCorrectionControl();
|
||||
}
|
||||
@@ -58,9 +58,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -78,12 +76,15 @@ import org.usb4java.LibUsbException;
|
||||
import org.usb4java.Transfer;
|
||||
import org.usb4java.TransferCallback;
|
||||
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import sample.adapter.ByteSampleAdapter;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerController;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
|
||||
|
||||
public class HackRFTunerController extends TunerController
|
||||
@@ -114,8 +115,7 @@ public class HackRFTunerController extends TunerController
|
||||
private LinkedTransferQueue<byte[]> mFilledBuffers =
|
||||
new LinkedTransferQueue<byte[]>();
|
||||
|
||||
private CopyOnWriteArrayList<Listener<ComplexBuffer>> mSampleListeners =
|
||||
new CopyOnWriteArrayList<Listener<ComplexBuffer>>();
|
||||
private Broadcaster<ComplexBuffer> mComplexBufferBroadcaster = new Broadcaster<>();
|
||||
|
||||
private ByteSampleAdapter mSampleAdapter = new ByteSampleAdapter();
|
||||
private BufferProcessor mBufferProcessor = new BufferProcessor();
|
||||
@@ -127,14 +127,16 @@ public class HackRFTunerController extends TunerController
|
||||
private Device mDevice;
|
||||
private DeviceDescriptor mDeviceDescriptor;
|
||||
private DeviceHandle mDeviceHandle;
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
|
||||
public HackRFTunerController( Device device, DeviceDescriptor descriptor )
|
||||
throws SourceException
|
||||
public HackRFTunerController( Device device, DeviceDescriptor descriptor,
|
||||
ThreadPoolManager threadPoolManager ) throws SourceException
|
||||
{
|
||||
super( MIN_FREQUENCY, MAX_FREQUENCY );
|
||||
|
||||
mDevice = device;
|
||||
mDeviceDescriptor = descriptor;
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
}
|
||||
|
||||
public void init() throws SourceException
|
||||
@@ -870,7 +872,7 @@ public class HackRFTunerController extends TunerController
|
||||
*/
|
||||
public void addListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mSampleListeners.add( listener );
|
||||
mComplexBufferBroadcaster.addListener( listener );
|
||||
|
||||
if( mBufferProcessor == null || !mBufferProcessor.isRunning() )
|
||||
{
|
||||
@@ -890,51 +892,20 @@ public class HackRFTunerController extends TunerController
|
||||
*/
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mSampleListeners.remove( listener );
|
||||
|
||||
if( mSampleListeners.isEmpty() )
|
||||
mComplexBufferBroadcaster.removeListener( listener );
|
||||
|
||||
if( !mComplexBufferBroadcaster.hasListeners() )
|
||||
{
|
||||
mBufferProcessor.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches the sample array to each registered listener. If there is more
|
||||
* than one listener, they receive a copy of the samples. If there is only
|
||||
* one listener, or the last listener, they receive the original sample array.
|
||||
*
|
||||
* This is to facilitate garbage collection of the array when the listener
|
||||
* is done processing the samples.
|
||||
*/
|
||||
public void broadcast( ComplexBuffer samples )
|
||||
{
|
||||
Iterator<Listener<ComplexBuffer>> it = mSampleListeners.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
Listener<ComplexBuffer> next = it.next();
|
||||
|
||||
/* if this is the last (or only) listener, send the original
|
||||
* buffer, otherwise send a copy of the buffer */
|
||||
if( it.hasNext() )
|
||||
{
|
||||
next.receive( samples.copyOf() );
|
||||
}
|
||||
else
|
||||
{
|
||||
next.receive( samples );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer processing thread. Fetches samples from the HackRF Tuner and
|
||||
* dispatches them to all registered listeners
|
||||
*/
|
||||
public class BufferProcessor implements Runnable, TransferCallback
|
||||
{
|
||||
private ScheduledExecutorService mExecutor =
|
||||
Executors.newScheduledThreadPool( 1 );
|
||||
private ScheduledFuture<?> mSampleDispatcherTask;
|
||||
private CopyOnWriteArrayList<Transfer> mTransfers;
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
@@ -960,9 +931,9 @@ public class HackRFTunerController extends TunerController
|
||||
}
|
||||
}
|
||||
|
||||
mSampleDispatcherTask = mExecutor
|
||||
.scheduleAtFixedRate( new BufferDispatcher(),
|
||||
0, 20, TimeUnit.MILLISECONDS );
|
||||
mSampleDispatcherTask = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.SOURCE_SAMPLE_PROCESSING, new BufferDispatcher(),
|
||||
20, TimeUnit.MILLISECONDS );
|
||||
|
||||
while( mRunning.get() )
|
||||
{
|
||||
@@ -1125,7 +1096,7 @@ public class HackRFTunerController extends TunerController
|
||||
{
|
||||
float[] samples = mSampleAdapter.convert( buffer );
|
||||
|
||||
broadcast( new ComplexBuffer( samples ) );
|
||||
mComplexBufferBroadcaster.broadcast( new ComplexBuffer( samples ) );
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
|
||||
@@ -29,9 +29,7 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Iterator;
|
||||
import java.util.concurrent.CopyOnWriteArrayList;
|
||||
import java.util.concurrent.Executors;
|
||||
import java.util.concurrent.LinkedTransferQueue;
|
||||
import java.util.concurrent.ScheduledExecutorService;
|
||||
import java.util.concurrent.ScheduledFuture;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
import java.util.concurrent.atomic.AtomicBoolean;
|
||||
@@ -51,16 +49,20 @@ import org.usb4java.LibUsbException;
|
||||
import org.usb4java.Transfer;
|
||||
import org.usb4java.TransferCallback;
|
||||
|
||||
import sample.Broadcaster;
|
||||
import sample.Listener;
|
||||
import sample.adapter.ByteSampleAdapter;
|
||||
import sample.complex.ComplexBuffer;
|
||||
import sample.complex.Complex;
|
||||
import source.SourceException;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Attribute;
|
||||
import source.tuner.TunerController;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.frequency.FrequencyChangeEvent;
|
||||
import source.tuner.frequency.FrequencyChangeEvent.Attribute;
|
||||
import buffer.FloatAveragingBuffer;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
import controller.ThreadPoolManager.ThreadType;
|
||||
|
||||
public abstract class RTL2832TunerController extends TunerController
|
||||
{
|
||||
@@ -104,12 +106,11 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
|
||||
private SampleRate mSampleRate = DEFAULT_SAMPLE_RATE;
|
||||
|
||||
private BufferProcessor mBufferProcessor = new BufferProcessor();
|
||||
private BufferProcessor mBufferProcessor;
|
||||
|
||||
private ByteSampleAdapter mSampleAdapter = new ByteSampleAdapter();
|
||||
|
||||
private CopyOnWriteArrayList<Listener<ComplexBuffer>> mSampleListeners =
|
||||
new CopyOnWriteArrayList<Listener<ComplexBuffer>>();
|
||||
private Broadcaster<ComplexBuffer> mComplexBufferBroadcaster = new Broadcaster<>();
|
||||
|
||||
private LinkedTransferQueue<byte[]> mFilledBuffers =
|
||||
new LinkedTransferQueue<byte[]>();
|
||||
@@ -127,6 +128,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
public int mBufferSize = 131072;
|
||||
|
||||
protected Descriptor mDescriptor;
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
|
||||
/**
|
||||
* Abstract tuner controller device. Use the static getTunerClass() method
|
||||
@@ -135,11 +137,14 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
*/
|
||||
public RTL2832TunerController( Device device,
|
||||
DeviceDescriptor deviceDescriptor,
|
||||
ThreadPoolManager threadPoolManager,
|
||||
long minTunableFrequency,
|
||||
long maxTunableFrequency ) throws SourceException
|
||||
{
|
||||
super( minTunableFrequency, maxTunableFrequency );
|
||||
|
||||
mThreadPoolManager = threadPoolManager;
|
||||
|
||||
mDevice = device;
|
||||
mDeviceDescriptor = deviceDescriptor;
|
||||
}
|
||||
@@ -1345,12 +1350,15 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
*/
|
||||
public void addListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mSampleListeners.add( listener );
|
||||
mComplexBufferBroadcaster.addListener( listener );
|
||||
|
||||
if( mBufferProcessor == null || !mBufferProcessor.isRunning() )
|
||||
if( mBufferProcessor == null )
|
||||
{
|
||||
mBufferProcessor = new BufferProcessor( mThreadPoolManager );
|
||||
}
|
||||
|
||||
if( !mBufferProcessor.isRunning() )
|
||||
{
|
||||
mBufferProcessor = new BufferProcessor();
|
||||
|
||||
Thread thread = new Thread( mBufferProcessor );
|
||||
thread.setDaemon( true );
|
||||
thread.setName( "RTL2832 Sample Processor" );
|
||||
@@ -1365,59 +1373,35 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
*/
|
||||
public void removeListener( Listener<ComplexBuffer> listener )
|
||||
{
|
||||
mSampleListeners.remove( listener );
|
||||
|
||||
if( mSampleListeners.isEmpty() )
|
||||
mComplexBufferBroadcaster.removeListener( listener );
|
||||
|
||||
if( !mComplexBufferBroadcaster.hasListeners() )
|
||||
{
|
||||
mBufferProcessor.stop();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Dispatches float sample buffers to all registered listeners
|
||||
*/
|
||||
public void broadcast( ComplexBuffer buffer )
|
||||
{
|
||||
Iterator<Listener<ComplexBuffer>> it = mSampleListeners.iterator();
|
||||
|
||||
while( it.hasNext() )
|
||||
{
|
||||
Listener<ComplexBuffer> next = it.next();
|
||||
|
||||
/* if this is the last (or only) listener, send him the original
|
||||
* buffer, otherwise send him a copy of the buffer */
|
||||
if( it.hasNext() )
|
||||
{
|
||||
next.receive( buffer.copyOf() );
|
||||
}
|
||||
else
|
||||
{
|
||||
next.receive( buffer );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Buffer processing thread. Fetches samples from the RTL2832 Tuner and
|
||||
* dispatches them to all registered listeners
|
||||
*/
|
||||
public class BufferProcessor implements Runnable, TransferCallback
|
||||
{
|
||||
private ScheduledExecutorService mExecutor =
|
||||
Executors.newScheduledThreadPool( 2 );
|
||||
private ScheduledFuture<?> mSampleDispatcherTask;
|
||||
private ScheduledFuture<?> mSampleRateCounterTask;
|
||||
private CopyOnWriteArrayList<Transfer> mTransfers;
|
||||
private AtomicBoolean mRunning = new AtomicBoolean();
|
||||
private ThreadPoolManager mThreadPoolManager;
|
||||
|
||||
public BufferProcessor( ThreadPoolManager manager )
|
||||
{
|
||||
mThreadPoolManager = manager;
|
||||
}
|
||||
|
||||
@Override
|
||||
public void run()
|
||||
{
|
||||
if( mRunning.compareAndSet( false, true ) )
|
||||
{
|
||||
mLog.debug( "rtl2832 [" + getUniqueID() +
|
||||
"] - starting sample fetch thread" );
|
||||
|
||||
try
|
||||
{
|
||||
setSampleRate( mSampleRate );
|
||||
@@ -1445,16 +1429,17 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
}
|
||||
}
|
||||
|
||||
mSampleDispatcherTask = mExecutor
|
||||
.scheduleAtFixedRate( new BufferDispatcher(),
|
||||
0, 20, TimeUnit.MILLISECONDS );
|
||||
|
||||
mSampleRateMonitor =
|
||||
new SampleRateMonitor( mSampleRate.getRate() );
|
||||
|
||||
mSampleRateCounterTask = mExecutor
|
||||
.scheduleAtFixedRate( mSampleRateMonitor,
|
||||
10, 10, TimeUnit.SECONDS );
|
||||
try
|
||||
{
|
||||
mSampleDispatcherTask = mThreadPoolManager.scheduleFixedRate(
|
||||
ThreadType.SOURCE_SAMPLE_PROCESSING, new BufferDispatcher(),
|
||||
20, TimeUnit.MILLISECONDS );
|
||||
}
|
||||
catch( NullPointerException npe )
|
||||
{
|
||||
mLog.error( "NPE! = tpm null: " + ( mThreadPoolManager == null ), npe );
|
||||
}
|
||||
|
||||
|
||||
while( mRunning.get() )
|
||||
{
|
||||
@@ -1478,15 +1463,12 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
{
|
||||
if( mRunning.compareAndSet( true, false ) )
|
||||
{
|
||||
mLog.debug( "rtl2832 [" + getUniqueID() +
|
||||
"] - stopping sample fetch thread" );
|
||||
|
||||
cancel();
|
||||
|
||||
if( mSampleDispatcherTask != null )
|
||||
{
|
||||
mSampleDispatcherTask.cancel( true );
|
||||
mSampleRateCounterTask.cancel( true );
|
||||
mThreadPoolManager.cancel( mSampleDispatcherTask );
|
||||
mSampleDispatcherTask = null;
|
||||
mFilledBuffers.clear();
|
||||
}
|
||||
}
|
||||
@@ -1621,7 +1603,7 @@ public abstract class RTL2832TunerController extends TunerController
|
||||
{
|
||||
float[] samples = mSampleAdapter.convert( buffer );
|
||||
|
||||
broadcast( new ComplexBuffer( samples ) );
|
||||
mComplexBufferBroadcaster.broadcast( new ComplexBuffer( samples ) );
|
||||
}
|
||||
}
|
||||
catch( Exception e )
|
||||
|
||||
@@ -34,8 +34,8 @@ import source.SourceException;
|
||||
import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.rtl.RTL2832TunerController;
|
||||
import source.tuner.rtl.RTL2832TunerController.Descriptor;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class E4KTunerController extends RTL2832TunerController
|
||||
{
|
||||
@@ -111,10 +111,12 @@ public class E4KTunerController extends RTL2832TunerController
|
||||
private E4KTunerEditorPanel mEditor;
|
||||
|
||||
public E4KTunerController( Device device,
|
||||
DeviceDescriptor deviceDescriptor )
|
||||
DeviceDescriptor deviceDescriptor,
|
||||
ThreadPoolManager threadPoolManager )
|
||||
throws SourceException
|
||||
{
|
||||
super( device, deviceDescriptor, MIN_FREQUENCY, MAX_FREQUENCY );
|
||||
super( device, deviceDescriptor, threadPoolManager,
|
||||
MIN_FREQUENCY, MAX_FREQUENCY );
|
||||
}
|
||||
|
||||
@Override
|
||||
|
||||
@@ -270,64 +270,64 @@ 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 | LibUsbException 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" );
|
||||
// /**
|
||||
// * 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 | LibUsbException 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
|
||||
|
||||
@@ -38,6 +38,7 @@ import source.tuner.TunerConfiguration;
|
||||
import source.tuner.TunerType;
|
||||
import source.tuner.rtl.RTL2832TunerController;
|
||||
import controller.ResourceManager;
|
||||
import controller.ThreadPoolManager;
|
||||
|
||||
public class R820TTunerController extends RTL2832TunerController
|
||||
{
|
||||
@@ -73,10 +74,12 @@ public class R820TTunerController extends RTL2832TunerController
|
||||
private JPanel mEditor;
|
||||
|
||||
public R820TTunerController( Device device,
|
||||
DeviceDescriptor deviceDescriptor )
|
||||
throws SourceException
|
||||
DeviceDescriptor deviceDescriptor,
|
||||
ThreadPoolManager threadPoolManager )
|
||||
throws SourceException
|
||||
{
|
||||
super( device, deviceDescriptor, MIN_FREQUENCY, MAX_FREQUENCY );
|
||||
super( device, deviceDescriptor, threadPoolManager,
|
||||
MIN_FREQUENCY, MAX_FREQUENCY );
|
||||
}
|
||||
|
||||
@Override
|
||||
@@ -250,21 +253,15 @@ public class R820TTunerController extends RTL2832TunerController
|
||||
|
||||
try
|
||||
{
|
||||
mLog.debug( "initializing RTL2832 tuner baseband" );
|
||||
initBaseband( mDeviceHandle );
|
||||
|
||||
mLog.debug( "enabling I2C repeater" );
|
||||
enableI2CRepeater( mDeviceHandle, true );
|
||||
|
||||
boolean i2CRepeaterControl = false;
|
||||
|
||||
mLog.debug( "initializing R820T tuner" );
|
||||
initTuner( i2CRepeaterControl );
|
||||
|
||||
mLog.debug( "disabling I2C repeater" );
|
||||
enableI2CRepeater( mDeviceHandle, false );
|
||||
|
||||
mLog.debug( "initializing RTL2832 tuner controller super class" );
|
||||
}
|
||||
catch( UsbException e )
|
||||
{
|
||||
|
||||
Reference in New Issue
Block a user