Closes #71 - frequency controller throws exception when exceeding min/max tuning limits of a tuner.

Updated code to show dialog to user whenever the tuning limit has been exceeded.  Added new InvalidFrequencyException that includes the requested invalid frequency and the valid frequency limit that was exceeded
This commit is contained in:
Denny
2016-06-04 08:21:28 -04:00
parent bf5ded53e2
commit 078a6fddce
14 changed files with 516 additions and 391 deletions

View File

@@ -0,0 +1,57 @@
/*******************************************************************************
* sdrtrunk
* Copyright (C) 2014-2016 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;
public class InvalidFrequencyException extends SourceException
{
private long mInvalidFrequency;
private long mValidFrequency;
/**
* Thrown when the user or the application requests to tune to an invalid frequency. Invalid means that the
* frequency is outside of the tunable range of the current tuner device. This class provides both the requested
* invalid frequency and the suggested valid frequency to use in lieu of the requested invalid frequency.
* @param message optional text
* @param invalidFrequency that was requested
* @param validFrequency that should be used instead
*/
public InvalidFrequencyException( String message, long invalidFrequency, long validFrequency )
{
super( message );
mInvalidFrequency = invalidFrequency;
mValidFrequency = validFrequency;
}
/**
* The invalid requested frequency
*/
public long getInvalidFrequency()
{
return mInvalidFrequency;
}
/**
* The valid frequency that should be used
*/
public long getValidFrequency()
{
return mValidFrequency;
}
}

View File

@@ -89,7 +89,7 @@ public class Recording implements Comparable<Recording>,
}
@Override
public void frequencyChanged( FrequencyChangeEvent event )
public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException
{
if( event.getEvent() == Event.NOTIFICATION_FREQUENCY_CHANGE )
{

View File

@@ -82,7 +82,6 @@ public class TunerChannelSource extends ComplexSource
* and thus the tuner might no longer be able to source this channel once it
* has been stopped.
*
* @param threadPoolManager to use for decimation processing task
* @param tuner to obtain wideband IQ samples from
* @param tunerChannel specifying the center frequency for the DDC
* @throws RejectedExecutionException if the thread pool manager cannot
@@ -229,7 +228,7 @@ public class TunerChannelSource extends ComplexSource
* frequency correction events received from the channel consumer/listener
*/
@Override
public void frequencyChanged( FrequencyChangeEvent event )
public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException
{
// Echo the event to the registered event listener
if( mFrequencyChangeProcessor != null )

View File

@@ -51,7 +51,7 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
* @param minimumFrequency minimum uncorrected tunable frequency
* @param maximumFrequency maximum uncorrected tunable frequency
* @param middleUnusable is the +/- value center DC spike to avoid for channels
* @param extantUnusable is the unusable space at the extreme ends of the spectrum
* @param usableBandwidthPercentage is the unusable space at the extreme ends of the spectrum
*
* @throws SourceException - for any issues related to constructing the
* class, tuning a frequency, or setting the bandwidth
@@ -79,18 +79,11 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
* Responds to requests to set the frequency
*/
@Override
public void frequencyChanged( FrequencyChangeEvent event )
public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException
{
if( event.getEvent() == Event.REQUEST_FREQUENCY_CHANGE )
{
try
{
setFrequency( event.getValue().longValue() );
}
catch ( SourceException e )
{
mLog.error( "Error setting frequency from external controller", e );
}
setFrequency( event.getValue().longValue() );
}
}
@@ -212,7 +205,6 @@ public abstract class TunerController implements Tunable, IFrequencyChangeProces
* ensure all of the channels can be accomodated and any defined central DC
* spike avoided.
*
* @param threadPoolManager for the channel to use for runnables
* @param tuner to source the channel from
* @param channel with defined center frequency and bandwidth
*

View File

@@ -405,7 +405,7 @@ public class AirspyTunerController extends TunerController
* Sets the sample rate to the rate specified by the index value in the
* available sample rates map
*
* @param index to a sample rate in the available samples rates map.
* @param rate to a sample rate in the available samples rates map.
*
* @throws IllegalArgumentException if index is not a valid rate index
* @throws LibUsbException if there was a read error or if this operation
@@ -414,7 +414,7 @@ public class AirspyTunerController extends TunerController
* @throws UsbException if there was a USB error
*/
public void setSampleRate( AirspySampleRate rate ) throws
LibUsbException, UsbException
LibUsbException, UsbException, SourceException
{
if( rate.getRate() != mSampleRate )
{

View File

@@ -167,7 +167,7 @@ public class AirspyTunerEditor extends TunerConfigurationEditor
mController.setSampleRate( rate );
save();
}
catch ( LibUsbException | UsbException e1 )
catch ( LibUsbException | UsbException | SourceException e1 )
{
JOptionPane.showMessageDialog( AirspyTunerEditor.this,
"Couldn't set sample rate to " + rate.getLabel() );

View File

@@ -76,9 +76,17 @@ public abstract class FCDTunerController extends TunerController
maxTunableFrequency,
DC_SPIKE_AVOID_BUFFER,
USABLE_BANDWIDTH_PERCENT );
mFrequencyController.setSampleRate( sampleRate );
mDevice = device;
mDeviceDescriptor = descriptor;
try
{
mFrequencyController.setSampleRate( sampleRate );
}
catch( SourceException se )
{
mLog.error("Error setting sample rate to [" + sampleRate + "]", se );
}
}
/**

View File

@@ -1,10 +1,16 @@
package source.tuner.frequency;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import sample.Listener;
import source.SourceException;
import source.tuner.hackrf.HackRFTunerEditor;
public class FrequencyChangeProcessorWrapper
implements IFrequencyChangeListener, Listener<FrequencyChangeEvent>
{
private final static Logger mLog = LoggerFactory.getLogger( FrequencyChangeProcessorWrapper.class );
private IFrequencyChangeProcessor mProcessor;
/**
@@ -26,7 +32,14 @@ public class FrequencyChangeProcessorWrapper
{
if( mProcessor != null )
{
mProcessor.frequencyChanged( event );
try
{
mProcessor.frequencyChanged( event );
}
catch( SourceException se )
{
mLog.error("Error sending frequency change event to embedded processor", se);
}
}
}
}

View File

@@ -22,6 +22,8 @@ import java.util.ArrayList;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import source.InvalidFrequencyException;
import source.Source;
import source.SourceException;
import source.tuner.frequency.FrequencyChangeEvent.Event;
@@ -61,7 +63,7 @@ public class FrequencyController
/**
* Set sample rate in hertz
*/
public void setSampleRate( int sampleRate )
public void setSampleRate( int sampleRate ) throws SourceException
{
mSampleRate = sampleRate;
@@ -92,21 +94,22 @@ public class FrequencyController
* method supports changing the frequency correction value without
* broadcasting a frequency change event.
*/
private void setFrequency( long frequency, boolean broadcastChange )
throws SourceException
private void setFrequency( long frequency, boolean broadcastChange ) throws SourceException
{
long tunedFrequency = getTunedFrequency( frequency );
if( tunedFrequency < mMinimumFrequency ||
tunedFrequency > mMaximumFrequency )
if( tunedFrequency < mMinimumFrequency )
{
//TODO: this should throw a frequency limit exception so that the frequency
//controller can update its display to the last tuned frequency
throw new SourceException( "Cannot tune frequency ( requested: " +
frequency + " actual:" + tunedFrequency + "]" );
throw new InvalidFrequencyException( "Requested frequency not valid", frequency, mMinimumFrequency );
}
if( tunedFrequency > mMaximumFrequency )
{
throw new InvalidFrequencyException( "Requested frequency not valid", frequency, mMaximumFrequency );
}
mFrequency = frequency;
mTunedFrequency = tunedFrequency;
if( mTunable != null )
@@ -164,8 +167,7 @@ public class FrequencyController
return mFrequencyCorrection;
}
public void setFrequencyCorrection( double correction )
throws SourceException
public void setFrequencyCorrection( double correction ) throws SourceException
{
mFrequencyCorrection = correction;
@@ -202,7 +204,7 @@ public class FrequencyController
* Broadcasts a change/update to the current (uncorrected) frequency or the
* bandwidth/sample rate value.
*/
protected void broadcastFrequencyChange()
protected void broadcastFrequencyChange() throws SourceException
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CHANGE, mFrequency ) );
@@ -211,7 +213,7 @@ public class FrequencyController
/**
* Broadcast a frequency error/correction value change
*/
protected void broadcastFrequencyErrorChange()
protected void broadcastFrequencyErrorChange() throws SourceException
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Event.NOTIFICATION_FREQUENCY_CORRECTION_CHANGE, mFrequencyCorrection ) );
@@ -220,13 +222,13 @@ public class FrequencyController
/**
* Broadcasts a sample rate change
*/
protected void broadcastSampleRateChange()
protected void broadcastSampleRateChange() throws SourceException
{
broadcastFrequencyChangeEvent(
new FrequencyChangeEvent( Event.NOTIFICATION_SAMPLE_RATE_CHANGE, mSampleRate ) );
}
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event )
public void broadcastFrequencyChangeEvent( FrequencyChangeEvent event ) throws SourceException
{
for( IFrequencyChangeProcessor processor: mProcessors )
{

View File

@@ -1,6 +1,8 @@
package source.tuner.frequency;
import source.SourceException;
public interface IFrequencyChangeProcessor
{
public void frequencyChanged( FrequencyChangeEvent event );
public void frequencyChanged( FrequencyChangeEvent event ) throws SourceException;
}

View File

@@ -515,7 +515,7 @@ public class HackRFTunerController extends TunerController
* sample rates. However, since we're only using integral sample rates, we
* simply invoke the setSampleRateManual method directly.
*/
public void setSampleRate( HackRFSampleRate rate ) throws UsbException
public void setSampleRate( HackRFSampleRate rate ) throws UsbException, SourceException
{
setSampleRateManual( rate.getRate(), 1 );

View File

@@ -142,7 +142,7 @@ public class HackRFTunerEditor extends TunerConfigurationEditor
mController.setSampleRate( sampleRate );
save();
}
catch ( UsbException e2 )
catch ( SourceException|UsbException e2 )
{
JOptionPane.showMessageDialog( HackRFTunerEditor.this, "HackRF Tuner Controller"
+ " - couldn't apply the sample rate setting [" + sampleRate.getLabel() +