diff --git a/src/main/java/io/github/dsheirer/gui/control/FrequencyTextField.java b/src/main/java/io/github/dsheirer/gui/control/FrequencyTextField.java
new file mode 100644
index 000000000..e986f6932
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/gui/control/FrequencyTextField.java
@@ -0,0 +1,192 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2024 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
+ * ****************************************************************************
+ */
+
+package io.github.dsheirer.gui.control;
+
+import java.awt.EventQueue;
+import net.miginfocom.swing.MigLayout;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import javax.swing.JFrame;
+import javax.swing.JTextField;
+import javax.swing.text.AttributeSet;
+import javax.swing.text.BadLocationException;
+import javax.swing.text.Document;
+import javax.swing.text.DocumentFilter;
+import javax.swing.text.PlainDocument;
+
+/**
+ * Swing text field control for entering frequency (MHz) values.
+ */
+public class FrequencyTextField extends JTextField
+{
+ private static final Logger LOGGER = LoggerFactory.getLogger(FrequencyTextField.class);
+ private static final String REGEX = "[1-9][0-9]{0,3}(\\.[0-9]{0,6})?";
+ private double mMinimum;
+ private double mMaximum;
+
+ /**
+ * Constructs an instance
+ *
+ * @param minimum allowable frequency value in Hertz
+ * @param maximum allowable frequency value in Hertz
+ * @param current frequency value in Hertz
+ */
+ public FrequencyTextField(long minimum, long maximum, long current)
+ {
+ super(8);
+ mMinimum = minimum / 1E6d;
+ mMaximum = maximum / 1E6d;
+
+ PlainDocument document = (PlainDocument)this.getDocument();
+ document.setDocumentFilter(new FrequencyFilter());
+ setFrequency(current);
+ }
+
+ /**
+ * Current frequency value
+ * @return frequency in Hertz
+ */
+ public long getFrequency()
+ {
+ String value = getText();
+
+ if(value == null || value.isEmpty())
+ {
+ return 0;
+ }
+
+ try
+ {
+ return (long)(Double.parseDouble(getText()) * 1E6d);
+ }
+ catch(Exception e)
+ {
+ LOGGER.error("Unable to parse frequency value from text [" + value + "] " + e.getLocalizedMessage());
+ }
+
+ return 0;
+ }
+
+ /**
+ * Sets the current frequency value
+ * @param frequency in Hertz
+ */
+ public void setFrequency(long frequency)
+ {
+ double frequencyMHz = frequency / 1E6d;
+
+ if(isValid(String.valueOf(frequencyMHz)))
+ {
+ setText(String.valueOf(frequencyMHz));
+ }
+ else
+ {
+ LOGGER.warn("Can't set frequency [" + frequency + "Hz / " + frequencyMHz + "MHz] with current minimum [" + mMinimum + "MHz] and maximum [" + mMaximum + "MHz] limits");
+ }
+ }
+
+ /**
+ * Indicates if the value is a valid double value that is between the minimum and maximum extents.
+ * @param value to test
+ * @return true if it is valid.
+ */
+ private boolean isValid(String value)
+ {
+ if(value == null || value.isEmpty())
+ {
+ return true;
+ }
+
+ if(value.matches(REGEX))
+ {
+ try
+ {
+ double frequency = Double.parseDouble(value);
+ return mMinimum <= frequency && frequency <= mMaximum;
+ }
+ catch(NumberFormatException e)
+ {
+ return false;
+ }
+ }
+
+ return false;
+ }
+
+ /**
+ * Input filter for user entered values.
+ */
+ class FrequencyFilter extends DocumentFilter
+ {
+ @Override
+ public void insertString(FilterBypass fb, int offset, String string, AttributeSet attr) throws BadLocationException
+ {
+ Document doc = fb.getDocument();
+ StringBuilder sb = new StringBuilder();
+ sb.append(doc.getText(0, doc.getLength()));
+ sb.insert(offset, string);
+
+ if(isValid(sb.toString()))
+ {
+ super.insertString(fb, offset, string, attr);
+ }
+ }
+
+ @Override
+ public void replace(FilterBypass fb, int offset, int length, String text, AttributeSet attrs) throws BadLocationException
+ {
+ Document doc = fb.getDocument();
+ StringBuilder sb = new StringBuilder();
+ sb.append(doc.getText(0, doc.getLength()));
+ sb.replace(offset, offset + length, text);
+
+ if(isValid(sb.toString()))
+ {
+ super.replace(fb, offset, length, text, attrs);
+ }
+ }
+
+ @Override
+ public void remove(FilterBypass fb, int offset, int length) throws BadLocationException
+ {
+ Document doc = fb.getDocument();
+ StringBuilder sb = new StringBuilder();
+ sb.append(doc.getText(0, doc.getLength()));
+ sb.delete(offset, offset + length);
+
+ if(isValid(sb.toString()))
+ {
+ super.remove(fb, offset, length);
+ }
+ }
+ }
+
+ public static void main(String[] args)
+ {
+ JFrame frame = new JFrame("Frequency Control Test");
+ frame.setSize(300, 200);
+ FrequencyTextField ftf = new FrequencyTextField(20, 2_000_000_000, 101_100_000);
+ frame.setLayout(new MigLayout());
+ frame.add(ftf);
+
+ EventQueue.invokeLater(() -> frame.setVisible(true));
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/gui/control/IntegerFormatter.java b/src/main/java/io/github/dsheirer/gui/control/IntegerFormatter.java
index 9d522e1dc..1e013e23b 100644
--- a/src/main/java/io/github/dsheirer/gui/control/IntegerFormatter.java
+++ b/src/main/java/io/github/dsheirer/gui/control/IntegerFormatter.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2020 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -19,20 +19,18 @@
package io.github.dsheirer.gui.control;
-import io.github.dsheirer.gui.playlist.alias.AliasItemEditor;
+import java.util.function.UnaryOperator;
import javafx.scene.control.TextFormatter;
import javafx.util.converter.IntegerStringConverter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
-import java.util.function.UnaryOperator;
-
/**
* Text formatter for integer values that constrains values to specified minimum and maximum valid values.
*/
public class IntegerFormatter extends TextFormatter
{
- private static final Logger mLog = LoggerFactory.getLogger(AliasItemEditor.class);
+ private static final Logger mLog = LoggerFactory.getLogger(IntegerFormatter.class);
/**
* Constructs an instance
diff --git a/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java b/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java
index 7e00f8531..cd5bbf770 100644
--- a/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java
+++ b/src/main/java/io/github/dsheirer/gui/control/JFrequencyControl.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -434,8 +434,7 @@ private void set(long amount, boolean fireChangeEvent)
if(se instanceof InvalidFrequencyException ife)
{
- JOptionPane.showMessageDialog(this, "Frequency [" + ife.getInvalidFrequency() +
- "] exceeds the frequency limit [" + ife.getValidFrequency() + "] for this tuner.");
+ JOptionPane.showMessageDialog(this, ife.getMessage() + " for this tuner.");
}
}
}
diff --git a/src/main/java/io/github/dsheirer/gui/control/LongFormatter.java b/src/main/java/io/github/dsheirer/gui/control/LongFormatter.java
new file mode 100644
index 000000000..94171233a
--- /dev/null
+++ b/src/main/java/io/github/dsheirer/gui/control/LongFormatter.java
@@ -0,0 +1,111 @@
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2024 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
+ * ****************************************************************************
+ */
+
+package io.github.dsheirer.gui.control;
+
+import java.util.function.UnaryOperator;
+import javafx.scene.control.TextFormatter;
+import javafx.util.converter.LongStringConverter;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+/**
+ * Text formatter for long values that constrains values to specified minimum and maximum valid values.
+ */
+public class LongFormatter extends TextFormatter
+{
+ private static final Logger mLog = LoggerFactory.getLogger(LongFormatter.class);
+
+ /**
+ * Constructs an instance
+ * @param minimum allowed value
+ * @param maximum allowed value
+ */
+ public LongFormatter(int minimum, int maximum)
+ {
+ super(new LongStringConverter(), null, new LongFilter(minimum, maximum));
+ }
+
+ /**
+ * Formatted text change filter that only allows hexadecimal characters where the converted decimal value
+ * is also constrained within minimum and maximum valid values.
+ */
+ public static class LongFilter implements UnaryOperator
+ {
+ private String DECIMAL_REGEX = "\\-?[0-9].*";
+ private int mMinimum;
+ private int mMaximum;
+
+ /**
+ * Constructs an instance
+ * @param minimum value
+ * @param maximum value
+ */
+ public LongFilter(int minimum, int maximum)
+ {
+ mMinimum = minimum;
+ mMaximum = maximum;
+ }
+
+ /**
+ * Indicates if the value argument is parsable as an integer, or is empty or null.
+ */
+ private boolean isValid(String value)
+ {
+ if(value == null || value.isEmpty())
+ {
+ return true;
+ }
+
+ try
+ {
+ long parsed = Long.parseLong(value);
+ return mMinimum <= parsed && parsed <= mMaximum;
+ }
+ catch(Exception e)
+ {
+ //no-op
+ }
+
+ return false;
+ }
+
+ @Override
+ public Change apply(Change change)
+ {
+ //Only validate if the user added text to the control. Otherwise, allow it to go through
+ if(change.getText() != null)
+ {
+ String updatedText = change.getControlNewText();
+
+ if(updatedText == null || updatedText.isEmpty())
+ {
+ return change;
+ }
+
+ if(!updatedText.matches(DECIMAL_REGEX) || !isValid(updatedText))
+ {
+ return null;
+ }
+ }
+
+ return change;
+ }
+ }
+}
diff --git a/src/main/java/io/github/dsheirer/source/InvalidFrequencyException.java b/src/main/java/io/github/dsheirer/source/InvalidFrequencyException.java
index bc30a29a3..fcaebaa9e 100644
--- a/src/main/java/io/github/dsheirer/source/InvalidFrequencyException.java
+++ b/src/main/java/io/github/dsheirer/source/InvalidFrequencyException.java
@@ -1,6 +1,6 @@
-/*******************************************************************************
- * sdrtrunk
- * Copyright (C) 2014-2016 Dennis Sheirer
+/*
+ * *****************************************************************************
+ * Copyright (C) 2014-2024 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
@@ -14,8 +14,8 @@
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see
- *
- ******************************************************************************/
+ * ****************************************************************************
+ */
package io.github.dsheirer.source;
public class InvalidFrequencyException extends SourceException
@@ -54,11 +54,4 @@ public long getValidFrequency()
{
return mValidFrequency;
}
-
- @Override
- public String getMessage()
- {
- return super.getMessage() + " Invalid Frequency: " + getInvalidFrequency() +
- " - current valid frequency:" + getValidFrequency();
- }
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java
index 46c8dde4c..88816da9a 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/TunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/TunerController.java
@@ -74,6 +74,17 @@ public TunerController(ITunerErrorListener tunerErrorListener)
mFrequencyErrorCorrectionManager = new FrequencyErrorCorrectionManager(this);
}
+ /**
+ * Updates the frequency controller with the new minimum and maximum values.
+ * @param minimum frequency Hertz
+ * @param maximum frequency Hertz
+ */
+ public void setFrequencyExtents(long minimum, long maximum)
+ {
+ mFrequencyController.setMinimumFrequency(minimum);
+ mFrequencyController.setMaximumFrequency(maximum);
+ }
+
/**
* Lock for the frequency controller. This should only be used by the channel source manager to lock access to the
* frequency controller while creating a channel source, to block multi-threaded access to the frequency controller
@@ -175,7 +186,31 @@ public Listener getSourceEventListener()
*/
public void apply(TunerConfiguration config) throws SourceException
{
- setFrequency(config.getFrequency());
+ //Set the frequency from the config. If the config frequency generates an error, try setting the default
+ //frequency before we give up on the tuner as having an error.
+ try
+ {
+ setFrequency(config.getFrequency());
+ }
+ catch(Exception e)
+ {
+ mLog.warn("Unable to restore previous frequency [" + config.getFrequency() + "] trying default frequency");
+ if(config.getFrequency() != TunerConfiguration.DEFAULT_FREQUENCY)
+ {
+ setFrequency(TunerConfiguration.DEFAULT_FREQUENCY);
+ //If we're successful to here, update the config with the default frequency.
+ config.setFrequency(TunerConfiguration.DEFAULT_FREQUENCY);
+ }
+ }
+
+ if(config.getMinimumFrequency() > 0)
+ {
+ setMinimumFrequency(config.getMinimumFrequency());
+ }
+ if(config.getMaximumFrequency() > 0)
+ {
+ setMaximumFrequency(config.getMaximumFrequency());
+ }
setFrequencyCorrection(config.getFrequencyCorrection());
getFrequencyErrorCorrectionManager().setEnabled(config.getAutoPPMCorrectionEnabled());
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerConfiguration.java
index 052480287..2aac26c45 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -38,6 +38,7 @@ public class AirspyTunerConfiguration extends TunerConfiguration
*/
public AirspyTunerConfiguration()
{
+ super(AirspyTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ, AirspyTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
@Override
diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java
index 7c74f9980..0faa1171a 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerController.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -59,8 +59,8 @@ public class AirspyTunerController extends USBTunerController
public static final int IF_GAIN_MIN = 0;
public static final int IF_GAIN_MAX = 15;
public static final int IF_GAIN_DEFAULT = 9;
- public static final long FREQUENCY_MIN = 24000000l;
- public static final long FREQUENCY_MAX = 1800000000l;
+ public static final long MINIMUM_TUNABLE_FREQUENCY_HZ = 24000000l;
+ public static final long MAXIMUM_TUNABLE_FREQUENCY_HZ = 1800000000l;
public static final long FREQUENCY_DEFAULT = 101100000;
public static final double USABLE_BANDWIDTH_PERCENT = 0.90;
private static final long USB_TIMEOUT_MS = 2000l; //milliseconds
@@ -82,7 +82,7 @@ public class AirspyTunerController extends USBTunerController
*/
public AirspyTunerController(int bus, String portAddress, ITunerErrorListener tunerErrorListener)
{
- super(bus, portAddress, FREQUENCY_MIN, FREQUENCY_MAX, 0, USABLE_BANDWIDTH_PERCENT, tunerErrorListener);
+ super(bus, portAddress, MINIMUM_TUNABLE_FREQUENCY_HZ, MAXIMUM_TUNABLE_FREQUENCY_HZ, 0, USABLE_BANDWIDTH_PERCENT, tunerErrorListener);
}
@Override
@@ -233,7 +233,7 @@ public long getTunedFrequency() throws SourceException
@Override
public synchronized void setTunedFrequency(long frequency) throws SourceException
{
- if(FREQUENCY_MIN <= frequency && frequency <= FREQUENCY_MAX)
+ if(MINIMUM_TUNABLE_FREQUENCY_HZ <= frequency && frequency <= MAXIMUM_TUNABLE_FREQUENCY_HZ)
{
ByteBuffer buffer = ByteBuffer.allocateDirect(4);
buffer.order(ByteOrder.LITTLE_ENDIAN);
@@ -252,7 +252,7 @@ public synchronized void setTunedFrequency(long frequency) throws SourceExceptio
}
else
{
- throw new SourceException("Frequency [" + frequency + "] outside " + "of tunable range " + FREQUENCY_MIN + "-" + FREQUENCY_MAX);
+ throw new SourceException("Frequency [" + frequency + "] outside " + "of tunable range " + MINIMUM_TUNABLE_FREQUENCY_HZ + "-" + MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java
index d1f721882..ed32e804e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/AirspyTunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -80,6 +80,18 @@ public AirspyTunerEditor(UserPreferences userPreferences, TunerManager tunerMana
tunerStatusUpdated();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return AirspyTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return AirspyTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
@Override
protected void tunerStatusUpdated()
{
@@ -472,6 +484,10 @@ public void actionPerformed(ActionEvent e)
try
{
getTuner().getController().setSampleRate(rate);
+
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate(rate.getRate());
+
save();
}
catch(Exception e1)
@@ -578,6 +594,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerConfiguration.java
index eb77bdf38..e98f115c6 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -38,6 +38,7 @@ public class AirspyHfTunerConfiguration extends TunerConfiguration
*/
public AirspyHfTunerConfiguration()
{
+ super(AirspyHfTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ, AirspyHfTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
/**
diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerController.java
index 3fbfcb791..5b380d374 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerController.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -46,8 +46,8 @@ public class AirspyHfTunerController extends USBTunerController
private static final AirspyHfSampleRate DEFAULT_SAMPLE_RATE = new AirspyHfSampleRate(0, 768_000, false);
private static final long IF_SHIFT_LIF = 0;
private static final long IF_SHIFT_ZIF = 5_000;
- private static final long MINIMUM_FREQUENCY_HZ = 500_000;
- private static final long MAXIMUM_FREQUENCY_HZ = 260_000_000;
+ public static final long MINIMUM_TUNABLE_FREQUENCY_HZ = 500_000;
+ public static final long MAXIMUM_TUNABLE_FREQUENCY_HZ = 260_000_000;
private static final byte REQUEST_TYPE_IN = LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE;
private static final byte REQUEST_TYPE_OUT = LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE;
private static final int BUFFER_SAMPLE_COUNT = 1024;
@@ -75,8 +75,8 @@ public class AirspyHfTunerController extends USBTunerController
public AirspyHfTunerController(int bus, String portAddress, ITunerErrorListener tunerErrorListener)
{
super(bus, portAddress, tunerErrorListener);
- setMinimumFrequency(MINIMUM_FREQUENCY_HZ);
- setMaximumFrequency(MAXIMUM_FREQUENCY_HZ);
+ setMinimumFrequency(MINIMUM_TUNABLE_FREQUENCY_HZ);
+ setMaximumFrequency(MAXIMUM_TUNABLE_FREQUENCY_HZ);
setUsableBandwidthPercentage(.9); //90% usable after filter rolloff
setMiddleUnusableHalfBandwidth(3000);
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerEditor.java
index 14155350f..850215c07 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/airspy/hf/AirspyHfTunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -62,6 +62,18 @@ public AirspyHfTunerEditor(UserPreferences userPreferences, TunerManager tunerMa
tunerStatusUpdated();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return AirspyHfTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return AirspyHfTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
private void init()
{
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
@@ -102,6 +114,8 @@ protected void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -216,6 +230,10 @@ private JComboBox getSampleRateCombo()
try
{
getTuner().getController().setSampleRate(sampleRate);
+
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate(sampleRate.getSampleRate());
+
save();
}
catch(SourceException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java
index f2fb8fd59..160c5cf6e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/configuration/TunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -56,16 +56,21 @@
@JacksonXmlRootElement(localName = "tuner_configuration")
public abstract class TunerConfiguration
{
+ public static final long DEFAULT_FREQUENCY = 101_100_000;
private String mUniqueID;
- private long mFrequency = 101100000;
+ private long mFrequency = DEFAULT_FREQUENCY;
+ private long mMinimumFrequency;
+ private long mMaximumFrequency;
private double mFrequencyCorrection = 0.0d;
private boolean mAutoPPMCorrection = true;
/**
* Default constructor to support Jackson
*/
- public TunerConfiguration()
+ public TunerConfiguration(long minimumFrequency, long maximumFrequency)
{
+ mMinimumFrequency = minimumFrequency;
+ mMaximumFrequency = maximumFrequency;
}
/**
@@ -123,7 +128,7 @@ public void setFrequencyCorrection(double value)
/**
* Indicates if automatic correction of PPM from measured frequency error is enabled/disabled.
*
- * @return true if auto-correction is enabled.
+ * @return true if autocorrection is enabled.
*/
@JacksonXmlProperty(isAttribute = true, localName = "auto_ppm_correction_enabled")
public boolean getAutoPPMCorrectionEnabled()
@@ -140,4 +145,42 @@ public void setAutoPPMCorrectionEnabled(boolean enabled)
{
mAutoPPMCorrection = enabled;
}
+
+ /**
+ * Minimum tunable frequency.
+ * @return minimum frequency
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "min_frequency")
+ public long getMinimumFrequency()
+ {
+ return mMinimumFrequency;
+ }
+
+ /**
+ * Sets the minimum tunable frequency
+ * @param minimumFrequency to set
+ */
+ public void setMinimumFrequency(long minimumFrequency)
+ {
+ mMinimumFrequency = minimumFrequency;
+ }
+
+ /**
+ * Maximum tunable frequency.
+ * @return maximum frequency
+ */
+ @JacksonXmlProperty(isAttribute = true, localName = "max_frequency")
+ public long getMaximumFrequency()
+ {
+ return mMaximumFrequency;
+ }
+
+ /**
+ * Sets the maximum tunable frequency
+ * @param maximumFrequency to set
+ */
+ public void setMaximumFrequency(long maximumFrequency)
+ {
+ mMaximumFrequency = maximumFrequency;
+ }
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerConfiguration.java
index b6afe8e9b..73927d042 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -41,6 +41,7 @@ public class FCD1TunerConfiguration extends TunerConfiguration
*/
public FCD1TunerConfiguration()
{
+ super(FCD1TunerController.MINIMUM_TUNABLE_FREQUENCY_HZ, FCD1TunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
public FCD1TunerConfiguration(String uniqueID)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java
index 49bde78e9..c5238c24e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerController.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -26,14 +26,14 @@
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.fcd.FCDCommand;
import io.github.dsheirer.source.tuner.fcd.FCDTunerController;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sound.sampled.TargetDataLine;
import javax.usb.UsbClaimException;
import javax.usb.UsbException;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
/**
* Funcube Dongle Pro tuner controller. Combines USB HID control with Audio Mixer data streaming interface.
@@ -41,8 +41,8 @@
public class FCD1TunerController extends FCDTunerController
{
private final static Logger mLog = LoggerFactory.getLogger(FCD1TunerController.class);
- public static final int MINIMUM_TUNABLE_FREQUENCY = 64000000;
- public static final int MAXIMUM_TUNABLE_FREQUENCY = 1700000000;
+ public static final int MINIMUM_TUNABLE_FREQUENCY_HZ = 64000000;
+ public static final int MAXIMUM_TUNABLE_FREQUENCY_HZ = 1700000000;
public static final int SAMPLE_RATE = 96000;
private double mDCCorrectionInPhase = 0.0;
private double mDCCorrectionQuadrature = 0.0;
@@ -61,8 +61,8 @@ public class FCD1TunerController extends FCDTunerController
*/
public FCD1TunerController(TargetDataLine mixerTDL, int bus, String portAddress, ITunerErrorListener tunerErrorListener)
{
- super(MixerTunerType.FUNCUBE_DONGLE_PRO, mixerTDL, bus, portAddress, MINIMUM_TUNABLE_FREQUENCY,
- MAXIMUM_TUNABLE_FREQUENCY, tunerErrorListener);
+ super(MixerTunerType.FUNCUBE_DONGLE_PRO, mixerTDL, bus, portAddress, MINIMUM_TUNABLE_FREQUENCY_HZ,
+ MAXIMUM_TUNABLE_FREQUENCY_HZ, tunerErrorListener);
}
protected void deviceStart() throws SourceException
diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java
index 81da4b684..8b480b5a8 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proV1/FCD1TunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -80,6 +80,18 @@ private FCD1TunerController getController()
return null;
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return FCD1TunerController.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return FCD1TunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
@Override
protected void tunerStatusUpdated()
{
@@ -366,6 +378,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerConfiguration.java
index 5e237ef05..70c0ad703 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -33,6 +33,7 @@ public class FCD2TunerConfiguration extends TunerConfiguration
*/
public FCD2TunerConfiguration()
{
+ super(FCD2TunerController.MINIMUM_TUNABLE_FREQUENCY_HZ, FCD2TunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
@JsonIgnore
diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java
index 2a705fc9a..1fe2bfa1c 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerController.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -26,12 +26,12 @@
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.fcd.FCDCommand;
import io.github.dsheirer.source.tuner.fcd.FCDTunerController;
+import java.nio.ByteBuffer;
+import java.nio.ByteOrder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.sound.sampled.TargetDataLine;
-import java.nio.ByteBuffer;
-import java.nio.ByteOrder;
/**
* Funcube Dongle Pro Plus tuner controller. Combines USB HID control with Audio Mixer for data streaming.
@@ -40,8 +40,8 @@ public class FCD2TunerController extends FCDTunerController
{
private final static Logger mLog = LoggerFactory.getLogger(FCD2TunerController.class);
- public static final int MINIMUM_TUNABLE_FREQUENCY = 150000;
- public static final int MAXIMUM_TUNABLE_FREQUENCY = 2050000000;
+ public static final int MINIMUM_TUNABLE_FREQUENCY_HZ = 150000;
+ public static final int MAXIMUM_TUNABLE_FREQUENCY_HZ = 2050000000;
public static final int SAMPLE_RATE = 192000;
/**
@@ -53,8 +53,8 @@ public class FCD2TunerController extends FCDTunerController
*/
public FCD2TunerController(TargetDataLine mixerTDL, int bus, String portAddress, ITunerErrorListener tunerErrorListener)
{
- super(MixerTunerType.FUNCUBE_DONGLE_PRO_PLUS, mixerTDL, bus, portAddress, MINIMUM_TUNABLE_FREQUENCY,
- MAXIMUM_TUNABLE_FREQUENCY, tunerErrorListener);
+ super(MixerTunerType.FUNCUBE_DONGLE_PRO_PLUS, mixerTDL, bus, portAddress, MINIMUM_TUNABLE_FREQUENCY_HZ,
+ MAXIMUM_TUNABLE_FREQUENCY_HZ, tunerErrorListener);
}
protected void deviceStart() throws SourceException
diff --git a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java
index 39709aa4e..d5616ab18 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/fcd/proplusV2/FCD2TunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -69,6 +69,18 @@ private FCD2TunerController getController()
return null;
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return FCD2TunerController.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return FCD2TunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
@Override
protected void tunerStatusUpdated()
{
@@ -236,6 +248,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
diff --git a/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java b/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java
index 80ef95615..ca539d140 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/frequency/FrequencyController.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -182,21 +182,20 @@ public void setFrequency(long frequency) throws SourceException
*/
private void setFrequency(long frequency, boolean broadcastChange) throws SourceException
{
- long tunedFrequency = getTunedFrequency(frequency);
-
- if(tunedFrequency < mMinimumFrequency)
+ if(frequency < mMinimumFrequency)
{
- throw new InvalidFrequencyException("Requested frequency not valid", frequency, mMinimumFrequency);
+ throw new InvalidFrequencyException("Frequency [" + frequency + "] is below the minimum [" +
+ mMinimumFrequency + "]", frequency, mMinimumFrequency);
}
- if(tunedFrequency > mMaximumFrequency)
+ if(frequency > mMaximumFrequency)
{
- throw new InvalidFrequencyException("Requested frequency not valid", frequency, mMaximumFrequency);
+ throw new InvalidFrequencyException("Frequency [" + frequency + "] is above the maximum [" +
+ mMaximumFrequency + "]", frequency, mMaximumFrequency);
}
mFrequency = frequency;
-
- mTunedFrequency = tunedFrequency;
+ mTunedFrequency = getTunedFrequency(frequency);
if(mTunable != null)
{
@@ -230,7 +229,7 @@ public long getMinimumFrequency()
*/
public void setMinimumFrequency(long minimum)
{
- mMaximumFrequency = minimum;
+ mMinimumFrequency = minimum;
}
/**
@@ -252,15 +251,12 @@ public void setMaximumFrequency(long maximum)
}
/**
- * Calculate the tuned frequency by adding frequency correction to the
- * corrected frequency.
- *
+ * Calculate the tuned frequency by adding frequency correction to the corrected frequency.
* @param correctedFrequency
*/
private long getTunedFrequency(long correctedFrequency)
{
- return (long)((double)correctedFrequency /
- (1.0 + (mFrequencyCorrection / 1000000.0)));
+ return (long)((double)correctedFrequency / (1.0 + (mFrequencyCorrection / 1000000.0)));
}
/**
diff --git a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerConfiguration.java
index a9e328e53..9213577cf 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -39,6 +39,7 @@ public class HackRFTunerConfiguration extends TunerConfiguration
*/
public HackRFTunerConfiguration()
{
+ super(HackRFTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ, HackRFTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
public HackRFTunerConfiguration(String uniqueID)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java
index 3d20b81a6..55e3313d8 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerController.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -47,8 +47,8 @@ public class HackRFTunerController extends USBTunerController
public static final byte REQUEST_TYPE_IN = (byte)(LibUsb.ENDPOINT_IN | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE);
public static final byte REQUEST_TYPE_OUT = (byte)(LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE);
- public static final long MINIMUM_TUNABLE_FREQUENCY = 10000000l;
- public static final long MAXIMUM_TUNABLE_FREQUENCY = 6000000000l;
+ public static final long MINIMUM_TUNABLE_FREQUENCY_HZ = 10000000l;
+ public static final long MAXIMUM_TUNABLE_FREQUENCY_HZ = 6000000000l;
public static final long DEFAULT_FREQUENCY = 101100000;
public static final double USABLE_BANDWIDTH = 0.90;
public static final int DC_HALF_BANDWIDTH = 5000;
@@ -64,7 +64,7 @@ public class HackRFTunerController extends USBTunerController
*/
public HackRFTunerController(int bus, String portAddress, ITunerErrorListener tunerErrorListener)
{
- super(bus, portAddress, MINIMUM_TUNABLE_FREQUENCY, MAXIMUM_TUNABLE_FREQUENCY, DC_HALF_BANDWIDTH, USABLE_BANDWIDTH,
+ super(bus, portAddress, MINIMUM_TUNABLE_FREQUENCY_HZ, MAXIMUM_TUNABLE_FREQUENCY_HZ, DC_HALF_BANDWIDTH, USABLE_BANDWIDTH,
tunerErrorListener);
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java
index 388ff63c7..4190e677c 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/hackrf/HackRFTunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -65,6 +65,18 @@ public HackRFTunerEditor(UserPreferences userPreferences, TunerManager tunerMana
tunerStatusUpdated();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return HackRFTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return HackRFTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
private void init()
{
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
@@ -258,6 +270,8 @@ private JComboBox getSampleRateCombo()
try
{
getTuner().getController().setSampleRate(sampleRate);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate(sampleRate.getRate());
save();
}
catch(SourceException | UsbException e2)
@@ -400,6 +414,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
diff --git a/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java b/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java
index 1cade643e..d7e2bc883 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/manager/DiscoveredTuner.java
@@ -215,7 +215,7 @@ public void setTunerConfiguration(TunerConfiguration tunerConfiguration)
catch(SourceException se)
{
mLog.error("Error applying tuner configuration [" + mTunerConfiguration.getClass() +
- "] to discovered tuner [" + getId() + "}");
+ "] to discovered tuner [" + getId() + "}", se);
}
}
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerConfiguration.java
index a90cb7f09..aaa4f646e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -39,6 +39,7 @@ public class RecordingTunerConfiguration extends TunerConfiguration
*/
public RecordingTunerConfiguration()
{
+ super(0, Long.MAX_VALUE);
}
/**
@@ -47,6 +48,7 @@ public RecordingTunerConfiguration()
*/
public RecordingTunerConfiguration(String uniqueId)
{
+ this();
setUniqueID(uniqueId);
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerEditor.java
index daabf2652..5d0a588d4 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/recording/RecordingTunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -57,6 +57,18 @@ public void setTunerLockState(boolean locked)
getFrequencyPanel().updateControls();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return 0;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return Long.MAX_VALUE;
+ }
+
@Override
protected void tunerStatusUpdated()
{
@@ -125,6 +137,8 @@ public void save()
{
RecordingTunerConfiguration config = getConfiguration();
config.setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
saveConfiguration();
}
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerConfiguration.java
index 587f2064c..e115553e6 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -46,9 +46,12 @@ public abstract class RTL2832TunerConfiguration extends TunerConfiguration
/**
* Default constructor to support Jackson
+ * @param minimumFrequency tunable
+ * @param maximumFrequency tunable
*/
- public RTL2832TunerConfiguration()
+ public RTL2832TunerConfiguration(long minimumFrequency, long maximumFrequency)
{
+ super(minimumFrequency, maximumFrequency);
}
public RTL2832TunerConfiguration(String uniqueID)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832UnknownTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832UnknownTunerEditor.java
index c706c3b66..219958bc2 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832UnknownTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832UnknownTunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -22,6 +22,7 @@
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
import io.github.dsheirer.source.tuner.manager.TunerManager;
+import io.github.dsheirer.source.tuner.rtl.r8x.R8xEmbeddedTuner;
import io.github.dsheirer.source.tuner.ui.TunerEditor;
import net.miginfocom.swing.MigLayout;
@@ -63,13 +64,20 @@ private void init()
add(new JSeparator(), "span,growx,push");
-// add(new JLabel("Frequency (MHz):"));
-// add(getFrequencyPanel(), "wrap");
-//
-// add(new JLabel("Sample Rate:"));
-//// add(getSampleRateCombo(), "wrap");
-//
-// add(new JSeparator(), "span,growx,push");
+ }
+
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ //Bogus value.
+ return R8xEmbeddedTuner.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ //Bogus value.
+ return R8xEmbeddedTuner.MAXIMUM_TUNABLE_FREQUENCY_HZ;
}
@Override
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KEmbeddedTuner.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KEmbeddedTuner.java
index dc235d5c4..5ad54178e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KEmbeddedTuner.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KEmbeddedTuner.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -23,13 +23,13 @@
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.rtl.EmbeddedTuner;
import io.github.dsheirer.source.tuner.rtl.RTL2832TunerController;
+import java.util.EnumSet;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.usb4java.LibUsb;
import org.usb4java.LibUsbException;
import javax.usb.UsbException;
-import java.util.EnumSet;
/**
* Elonic E4000 Tuner
@@ -38,8 +38,8 @@ public class E4KEmbeddedTuner extends EmbeddedTuner
{
private final static Logger mLog = LoggerFactory.getLogger(E4KEmbeddedTuner.class);
- public static final long MINIMUM_SUPPORTED_FREQUENCY = 52000000;
- public static final long MAXIMUM_SUPPORTED_FREQUENCY = 2200000000l;
+ public static final long MINIMUM_TUNABLE_FREQUENCY_HZ = 52000000;
+ public static final long MAXIMUM_TUNABLE_FREQUENCY_HZ = 2200000000l;
public static final double USABLE_BANDWIDTH_PERCENT = 0.95;
public static final int DC_SPIKE_AVOID_BUFFER = 15000;
@@ -99,13 +99,13 @@ public TunerType getTunerType()
@Override
public long getMinimumFrequencySupported()
{
- return MINIMUM_SUPPORTED_FREQUENCY;
+ return MINIMUM_TUNABLE_FREQUENCY_HZ;
}
@Override
public long getMaximumFrequencySupported()
{
- return MAXIMUM_SUPPORTED_FREQUENCY;
+ return MAXIMUM_TUNABLE_FREQUENCY_HZ;
}
@Override
@@ -1039,7 +1039,7 @@ public enum RFFilter
NO_FILTER(0, 0, 0),
//VHF-II Filters (0.0 - 140.0) Optimal (64-108)
- LP268(0, MINIMUM_SUPPORTED_FREQUENCY, 86_000_000), //Values 0 - 7 are all the same
+ LP268(0, MINIMUM_TUNABLE_FREQUENCY_HZ, 86_000_000), //Values 0 - 7 are all the same
LP299(8, 86_000_000, 140_000_000), //Values 8 - 15 are all the same
//VHF-III Filters (140.0 - 350.0) Optimal (170-240)
@@ -1080,7 +1080,7 @@ public enum RFFilter
BP1680(12, 1670000000, 1690000000),
BP1700(13, 1690000000, 1710000000),
BP1720(14, 1710000000, 1735000000),
- BP1750(15, 1735000000, MAXIMUM_SUPPORTED_FREQUENCY);
+ BP1750(15, 1735000000, MAXIMUM_TUNABLE_FREQUENCY_HZ);
private int mValue;
private long mMinFrequency;
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerConfiguration.java
index 74970eab8..0df9dedbf 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2022 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -42,6 +42,7 @@ public class E4KTunerConfiguration extends RTL2832TunerConfiguration
*/
public E4KTunerConfiguration()
{
+ super(E4KEmbeddedTuner.MINIMUM_TUNABLE_FREQUENCY_HZ, E4KEmbeddedTuner.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
@JsonIgnore
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java
index f08528439..35fdb9db6 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/e4k/E4KTunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -73,6 +73,18 @@ public E4KTunerEditor(UserPreferences userPreferences, TunerManager tunerManager
tunerStatusUpdated();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return E4KEmbeddedTuner.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return E4KEmbeddedTuner.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
/**
* Access to the E4000 embedded tuner
* @return E4000 tuner if there is a tuner, or null otherwise
@@ -373,6 +385,8 @@ private JComboBox getSampleRateCombo()
try
{
getTuner().getController().setSampleRate(sampleRate);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate(sampleRate.getRate());
save();
}
catch(SourceException | LibUsbException eSampleRate)
@@ -485,6 +499,8 @@ public void save()
{
E4KTunerConfiguration config = getConfiguration();
config.setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel)getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
config.setFrequencyCorrection(value);
config.setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013EmbeddedTuner.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013EmbeddedTuner.java
index 7afd57cb4..fcc2abfc6 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013EmbeddedTuner.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013EmbeddedTuner.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -61,8 +61,8 @@ public class FC0013EmbeddedTuner extends EmbeddedTuner
{
private final static Logger mLog = LoggerFactory.getLogger(FC0013EmbeddedTuner.class);
private DecimalFormat FREQUENCY_FORMAT = new DecimalFormat("0.000000");
- private static final long MINIMUM_SUPPORTED_FREQUENCY = 13_500_000;
- private static final long MAXIMUM_SUPPORTED_FREQUENCY = 1_907_999_890l;
+ public static final long MINIMUM_TUNABLE_FREQUENCY_HZ = 13_500_000;
+ public static final long MAXIMUM_TUNABLE_FREQUENCY_HZ = 1_907_999_890l;
private static final double USABLE_BANDWIDTH_PERCENT = 0.95;
private static final int DC_SPIKE_AVOID_BUFFER = 15000;
//Hardware I2C address
@@ -74,7 +74,7 @@ public class FC0013EmbeddedTuner extends EmbeddedTuner
private static byte[] REGISTERS = {(byte) 0x00, (byte) 0x09, (byte) 0x16, (byte) 0x00, (byte) 0x00, (byte) 0x17,
(byte) 0x02, (byte) 0x2A, (byte) 0xFF, (byte) 0x6E, (byte) 0xB8, (byte) 0x82, (byte) 0xFE, (byte) 0x01,
(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x50, (byte) 0x01};
- private long mTunedFrequency = MINIMUM_SUPPORTED_FREQUENCY;
+ private long mTunedFrequency = MINIMUM_TUNABLE_FREQUENCY_HZ;
/**
* Constructs an instance
@@ -95,13 +95,13 @@ public TunerType getTunerType()
@Override
public long getMinimumFrequencySupported()
{
- return MINIMUM_SUPPORTED_FREQUENCY;
+ return MINIMUM_TUNABLE_FREQUENCY_HZ;
}
@Override
public long getMaximumFrequencySupported()
{
- return MAXIMUM_SUPPORTED_FREQUENCY;
+ return MAXIMUM_TUNABLE_FREQUENCY_HZ;
}
@Override
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerConfiguration.java
index b08b0609f..c30eabfab 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -36,6 +36,7 @@ public class FC0013TunerConfiguration extends RTL2832TunerConfiguration
*/
public FC0013TunerConfiguration()
{
+ super(FC0013EmbeddedTuner.MINIMUM_TUNABLE_FREQUENCY_HZ, FC0013EmbeddedTuner.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
@JsonIgnore
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerEditor.java
index 187f0f657..1dd0f4886 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/fc0013/FC0013TunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -68,6 +68,18 @@ public FC0013TunerEditor(UserPreferences userPreferences, TunerManager tunerMana
tunerStatusUpdated();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return FC0013EmbeddedTuner.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return FC0013EmbeddedTuner.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
/**
* Access the FC0013 embedded tuner
* @return tuner if there is a tuner, or null otherwise
@@ -263,6 +275,8 @@ private JComboBox getSampleRateCombo()
try
{
getTuner().getController().setSampleRate(sampleRate);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate(sampleRate.getRate());
save();
}
catch(SourceException | LibUsbException eSampleRate)
@@ -390,6 +404,8 @@ public void save()
FC0013TunerConfiguration config = getConfiguration();
config.setBiasT(getTuner().getController().isBiasT());
config.setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel)getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
config.setFrequencyCorrection(value);
config.setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xEmbeddedTuner.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xEmbeddedTuner.java
index 2ff44cf73..ccdd0b0bd 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xEmbeddedTuner.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xEmbeddedTuner.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -38,8 +38,8 @@ public abstract class R8xEmbeddedTuner extends EmbeddedTuner
public static final byte[] BIT_REV_LOOKUP_TABLE = {(byte) 0x0, (byte) 0x8, (byte) 0x4, (byte) 0xC, (byte) 0x2,
(byte) 0xA, (byte) 0x6, (byte) 0xE, (byte) 0x1, (byte) 0x9, (byte) 0x5, (byte) 0xD, (byte) 0x3, (byte) 0xB,
(byte) 0x7, (byte) 0xF};
- private static final long MINIMUM_SUPPORTED_FREQUENCY = 3180000;
- private static final long MAXIMUM_SUPPORTED_FREQUENCY = 1782030000;
+ public static final long MINIMUM_TUNABLE_FREQUENCY_HZ = 3180000;
+ public static final long MAXIMUM_TUNABLE_FREQUENCY_HZ = 1782030000;
private static final double USABLE_BANDWIDTH_PERCENT = 0.98;
private static final int DC_SPIKE_AVOID_BUFFER = 5000;
private static final byte VERSION = (byte) 49;
@@ -147,13 +147,13 @@ private static int bitReverse(int value)
@Override
public long getMinimumFrequencySupported()
{
- return MINIMUM_SUPPORTED_FREQUENCY;
+ return MINIMUM_TUNABLE_FREQUENCY_HZ;
}
@Override
public long getMaximumFrequencySupported()
{
- return MAXIMUM_SUPPORTED_FREQUENCY;
+ return MAXIMUM_TUNABLE_FREQUENCY_HZ;
}
@Override
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerConfiguration.java
index 43ab8b7f9..a81ae8657 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerConfiguration.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -36,6 +36,7 @@ public abstract class R8xTunerConfiguration extends RTL2832TunerConfiguration
*/
public R8xTunerConfiguration()
{
+ super(R8xEmbeddedTuner.MINIMUM_TUNABLE_FREQUENCY_HZ, R8xEmbeddedTuner.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
/**
diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerEditor.java
index 4c48e3ddd..db3713fcb 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -69,6 +69,18 @@ public R8xTunerEditor(UserPreferences userPreferences, TunerManager tunerManager
tunerStatusUpdated();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return R8xEmbeddedTuner.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return R8xEmbeddedTuner.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
/**
* Access the R8xxx embedded tuner
* @return R8xxx tuner if there is a tuner, or null otherwise
@@ -329,6 +341,8 @@ private JComboBox getSampleRateCombo()
try
{
getTuner().getController().setSampleRate(sampleRate);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate(sampleRate.getRate());
save();
}
catch(SourceException | LibUsbException eSampleRate)
@@ -521,6 +535,8 @@ public void save()
R8xTunerConfiguration config = getConfiguration();
config.setBiasT(getTuner().getController().isBiasT());
config.setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel)getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
config.setFrequencyCorrection(value);
config.setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerConfiguration.java
index eb5e4070a..28769c3e5 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerConfiguration.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerConfiguration.java
@@ -60,6 +60,7 @@ public abstract class RspTunerConfiguration extends TunerConfiguration
*/
public RspTunerConfiguration()
{
+ super(RspTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ, RspTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ);
}
/**
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerController.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerController.java
index 79e5ec9eb..db11c8fff 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerController.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerController.java
@@ -45,8 +45,8 @@ public abstract class RspTunerController extends TunerCon
implements IDeviceEventListener, IStreamListener
{
private static final Logger mLog = LoggerFactory.getLogger(RspTunerController.class);
- protected static final long MINIMUM_FREQUENCY = 100_000;
- protected static final long MAXIMUM_FREQUENCY = 2_000_000_000;
+ protected static final long MINIMUM_TUNABLE_FREQUENCY_HZ = 100_000;
+ protected static final long MAXIMUM_TUNABLE_FREQUENCY_HZ = 2_000_000_000;
protected static final int MIDDLE_UNUSABLE_BANDWIDTH = 0;
private I mControlRsp;
private RspNativeBufferFactory mNativeBufferFactory = new RspNativeBufferFactory(RspSampleRate.RATE_8_000);
@@ -66,8 +66,8 @@ public RspTunerController(I controlRsp, ITunerErrorListener tunerErrorListener)
//Register this controller to receive device events and sample streams when startStream() is invoked.
mControlRsp.resister(this, this);
- setMinimumFrequency(MINIMUM_FREQUENCY);
- setMaximumFrequency(MAXIMUM_FREQUENCY);
+ setMinimumFrequency(MINIMUM_TUNABLE_FREQUENCY_HZ);
+ setMaximumFrequency(MAXIMUM_TUNABLE_FREQUENCY_HZ);
setMiddleUnusableHalfBandwidth(MIDDLE_UNUSABLE_BANDWIDTH);
setUsableBandwidthPercentage(1.0); //Initial value
}
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerEditor.java
index 6921d37b1..d70f1393a 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/RspTunerEditor.java
@@ -73,6 +73,18 @@ private RspTunerController getTunerController()
return (RspTunerController) getTuner().getTunerController();
}
+ @Override
+ public long getMinimumTunableFrequency()
+ {
+ return RspTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
+ @Override
+ public long getMaximumTunableFrequency()
+ {
+ return RspTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ;
+ }
+
/**
* Gain controls panel
* @return gain panel
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerEditor.java
index ea3a5093a..b8278f9bf 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1/Rsp1TunerEditor.java
@@ -156,6 +156,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -186,6 +188,8 @@ private JComboBox getSampleRateCombo()
try
{
getTunerController().setSampleRate(selected);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate((int)selected.getSampleRate());
save();
}
catch(SDRPlayException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerEditor.java
index 4650c13a2..6cdeb1d5e 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1a/Rsp1aTunerEditor.java
@@ -197,6 +197,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -230,6 +232,8 @@ private JComboBox getSampleRateCombo()
try
{
getTunerController().setSampleRate(selected);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate((int)selected.getSampleRate());
save();
}
catch(SDRPlayException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1b/Rsp1bTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1b/Rsp1bTunerEditor.java
index 5150db63e..86d8f4494 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1b/Rsp1bTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp1b/Rsp1bTunerEditor.java
@@ -196,6 +196,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -229,6 +231,8 @@ private JComboBox getSampleRateCombo()
try
{
getTunerController().setSampleRate(selected);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate((int)selected.getSampleRate());
save();
}
catch(SDRPlayException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerEditor.java
index 2b483df0c..b5f383a0a 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rsp2/Rsp2TunerEditor.java
@@ -211,6 +211,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -244,6 +246,8 @@ private JComboBox getSampleRateCombo()
try
{
getTunerController().setSampleRate(selected);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate((int)selected.getSampleRate());
save();
}
catch(SDRPlayException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Editor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Editor.java
index a4a757015..8d1d4aa11 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Editor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner1Editor.java
@@ -239,6 +239,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -296,6 +298,8 @@ private JComboBox getSampleRateCombo()
try
{
getTunerController().setSampleRate(selected);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate((int)selected.getSampleRate());
save();
}
catch(SDRPlayException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Editor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Editor.java
index f6dc89ad3..9f1106ad2 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Editor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDuo/RspDuoTuner2Editor.java
@@ -246,6 +246,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -308,6 +310,8 @@ private JComboBox getSampleRateCombo()
try
{
getTunerController().setSampleRate(selected);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate((int)selected.getSampleRate());
save();
}
catch(SDRPlayException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerEditor.java
index f36d725c1..c61e3a85c 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/sdrplay/rspDx/RspDxTunerEditor.java
@@ -230,6 +230,8 @@ public void save()
if(hasConfiguration() && !isLoading())
{
getConfiguration().setFrequency(getFrequencyControl().getFrequency());
+ getConfiguration().setMinimumFrequency(getMinimumFrequencyTextField().getFrequency());
+ getConfiguration().setMaximumFrequency(getMaximumFrequencyTextField().getFrequency());
double value = ((SpinnerNumberModel) getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue();
getConfiguration().setFrequencyCorrection(value);
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
@@ -265,6 +267,8 @@ private JComboBox getSampleRateCombo()
try
{
getTunerController().setSampleRate(selected);
+ //Adjust the min/max values for the sample rate.
+ adjustForSampleRate((int)selected.getSampleRate());
save();
}
catch(SDRPlayException se)
diff --git a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java
index d0d11e654..a09f14367 100644
--- a/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java
+++ b/src/main/java/io/github/dsheirer/source/tuner/ui/TunerEditor.java
@@ -1,6 +1,6 @@
/*
* *****************************************************************************
- * Copyright (C) 2014-2023 Dennis Sheirer
+ * Copyright (C) 2014-2024 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
@@ -18,6 +18,7 @@
*/
package io.github.dsheirer.source.tuner.ui;
+import io.github.dsheirer.gui.control.FrequencyTextField;
import io.github.dsheirer.gui.control.JFrequencyControl;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.properties.SystemProperties;
@@ -37,6 +38,8 @@
import io.github.dsheirer.util.SwingUtils;
import io.github.dsheirer.util.ThreadPool;
import java.awt.EventQueue;
+import java.awt.event.FocusEvent;
+import java.awt.event.FocusListener;
import java.text.CharacterIterator;
import java.text.DecimalFormat;
import java.text.StringCharacterIterator;
@@ -47,6 +50,7 @@
import javax.swing.JButton;
import javax.swing.JCheckBox;
import javax.swing.JLabel;
+import javax.swing.JOptionPane;
import javax.swing.JPanel;
import javax.swing.JSpinner;
import javax.swing.JToggleButton;
@@ -63,6 +67,8 @@ public abstract class TunerEditor
implements IDiscoveredTunerStatusListener, Listener
{
private Logger mLog = LoggerFactory.getLogger(TunerEditor.class);
+ private static final long DEFAULT_MINIMUM_FREQUENCY = 1_000_000;
+ private static final long DEFAULT_MAXIMUM_FREQUENCY = 9_999_999_999l;
private static final String BUTTON_STATUS_ENABLE = "Enable";
private static final String BUTTON_STATUS_DISABLE = "Disable";
private static final long serialVersionUID = 1L;
@@ -86,6 +92,9 @@ public abstract class TunerEditor
private JLabel mRecordingStatusLabel;
private JLabel mTunerStatusLabel;
private JLabel mTunerLockedStatusLabel;
+ private FrequencyTextField mMinimumFrequencyTextField;
+ private FrequencyTextField mMaximumFrequencyTextField;
+ private JButton mResetFrequenciesButton;
private boolean mLoading = false;
/**
@@ -119,6 +128,32 @@ public TunerEditor(UserPreferences userPreferences, TunerManager tunerManager, D
}
}
+ /**
+ * Minimum tunable frequency supported by the tuner.
+ * @return minimum frequency hertz
+ */
+ public abstract long getMinimumTunableFrequency();
+
+ /**
+ * Maximum tunable frequency supported by the tuner.
+ * @return maximum frequency hertz
+ */
+ public abstract long getMaximumTunableFrequency();
+
+ /**
+ * Current sample rate for the tuner.
+ * @return sample rate in hertz.
+ */
+ public int getCurrentSampleRate()
+ {
+ if(hasTuner())
+ {
+ return (int)getTuner().getTunerController().getSampleRate();
+ }
+
+ return 0;
+ }
+
/**r
* Indicates if the controls are currently being loaded with values.
*/
@@ -284,6 +319,235 @@ protected JFrequencyControl getFrequencyControl()
return mFrequencyControl;
}
+ /**
+ * Minimum frequency value text field
+ */
+ protected FrequencyTextField getMinimumFrequencyTextField()
+ {
+ if(mMinimumFrequencyTextField == null)
+ {
+ mMinimumFrequencyTextField = new FrequencyTextField(DEFAULT_MINIMUM_FREQUENCY, DEFAULT_MAXIMUM_FREQUENCY,
+ getMinimumTunableFrequency());
+ mMinimumFrequencyTextField.setToolTipText("Sets or changes the minimum frequency value that this tuner will support.");
+ mMinimumFrequencyTextField.addFocusListener(new FocusListener()
+ {
+ private long mExistingFrequency;
+
+ @Override
+ public void focusGained(FocusEvent e)
+ {
+ mExistingFrequency = getMinimumFrequencyTextField().getFrequency();
+ }
+
+ @Override
+ public void focusLost(FocusEvent e)
+ {
+ if(!isLoading())
+ {
+ setLoading(true);
+
+ long minimum = getMinimumFrequencyTextField().getFrequency();
+ long maximum = getMaximumFrequencyTextField().getFrequency();
+
+ if(minimum < getMinimumTunableFrequency())
+ {
+ JOptionPane.showMessageDialog(TunerEditor.this, "Frequency value [" +
+ getMinimumFrequencyTextField().getText() + "] is below the supported frequency range for this tuner",
+ "Invalid Frequency", JOptionPane.ERROR_MESSAGE);
+ getMinimumFrequencyTextField().setFrequency(mExistingFrequency);
+ return;
+ }
+
+ if((minimum + getCurrentSampleRate()) > maximum)
+ {
+ long newMaximum = minimum + getCurrentSampleRate();
+
+ if(newMaximum <= getMaximumTunableFrequency())
+ {
+ maximum = newMaximum;
+ getMaximumFrequencyTextField().setFrequency(maximum);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(TunerEditor.this, "Frequency value [" +
+ getMinimumFrequencyTextField().getText() + "] is invalid for current sample rate " +
+ "and maximum supported frequency for this tuner", "Invalid Frequency",
+ JOptionPane.ERROR_MESSAGE);
+ getMinimumFrequencyTextField().setFrequency(mExistingFrequency);
+ return;
+ }
+ }
+
+ if(hasTuner())
+ {
+ getTuner().getTunerController().setFrequencyExtents(minimum, maximum);
+ }
+
+ adjustFrequencyControl(minimum, maximum);
+ setLoading(false);
+ save();
+ }
+ }
+ });
+ }
+
+ return mMinimumFrequencyTextField;
+ }
+
+ /**
+ * Adjusts the frequency control to be within the min-max range.
+ * @param minimum frequency value.
+ * @param maximum frequency value.
+ */
+ private void adjustFrequencyControl(long minimum, long maximum)
+ {
+ if(hasTuner())
+ {
+ try
+ {
+ if(getFrequencyControl().getFrequency() < minimum)
+ {
+ getTuner().getTunerController().setFrequency(minimum);
+ }
+ else if(getFrequencyControl().getFrequency() > maximum)
+ {
+ getTuner().getTunerController().setFrequency(maximum);
+ }
+ }
+ catch(SourceException se)
+ {
+ mLog.error("Error adjusting frequency", se);
+ }
+ }
+ }
+
+ /**
+ * Adjusts the minimum and maximum frequency values to ensure the gap is wide enough for the sample rate.
+ * @param sampleRate to adjust for.
+ */
+ protected void adjustForSampleRate(int sampleRate)
+ {
+ long minimum = getMinimumFrequencyTextField().getFrequency();
+ long maximum = getMaximumFrequencyTextField().getFrequency();
+
+ if(maximum - minimum < sampleRate)
+ {
+ long newMaximum = minimum + sampleRate;
+
+ if(newMaximum <= getMaximumTunableFrequency())
+ {
+ getMaximumFrequencyTextField().setFrequency(newMaximum);
+ }
+ else
+ {
+ long newMinimum = maximum - sampleRate;
+
+ if(newMinimum >= getMinimumTunableFrequency())
+ {
+ getMinimumFrequencyTextField().setFrequency(newMinimum);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(TunerEditor.this, "Unable to adjust tuner's " +
+ "minimum and maximum frequency values to accommodate new sample rate [" + sampleRate + "]",
+ "Frequency Error", JOptionPane.ERROR_MESSAGE);
+ }
+ }
+ }
+ }
+
+ /**
+ * Maximum frequency value text field
+ */
+ protected FrequencyTextField getMaximumFrequencyTextField()
+ {
+ if(mMaximumFrequencyTextField == null)
+ {
+ mMaximumFrequencyTextField = new FrequencyTextField(DEFAULT_MINIMUM_FREQUENCY, DEFAULT_MAXIMUM_FREQUENCY,
+ getMaximumTunableFrequency());
+ mMaximumFrequencyTextField.setToolTipText("Sets or changes the maximum frequency value that this tuner will support.");
+ mMaximumFrequencyTextField.addFocusListener(new FocusListener()
+ {
+ private long mExistingFrequency;
+
+ @Override
+ public void focusGained(FocusEvent e)
+ {
+ mExistingFrequency = getMaximumFrequencyTextField().getFrequency();
+ }
+
+ @Override
+ public void focusLost(FocusEvent e)
+ {
+ if(!isLoading())
+ {
+
+ setLoading(true);
+ long minimum = getMinimumFrequencyTextField().getFrequency();
+ long maximum = getMaximumFrequencyTextField().getFrequency();
+
+ if(maximum > getMaximumTunableFrequency())
+ {
+ JOptionPane.showMessageDialog(TunerEditor.this, "Frequency value [" +
+ getMaximumFrequencyTextField().getText() + "] is above the supported frequency " +
+ "range for this tuner", "Invalid Frequency", JOptionPane.ERROR_MESSAGE);
+ getMaximumFrequencyTextField().setFrequency(mExistingFrequency);
+ return;
+ }
+
+ if((maximum - getCurrentSampleRate()) < minimum)
+ {
+ long newMinimum = maximum - getCurrentSampleRate();
+
+ if(newMinimum >= getMinimumTunableFrequency())
+ {
+ minimum = newMinimum;
+ getMinimumFrequencyTextField().setFrequency(minimum);
+ }
+ else
+ {
+ JOptionPane.showMessageDialog(TunerEditor.this, "Frequency value [" +
+ getMaximumFrequencyTextField().getText() + "] is invalid for current sample rate " +
+ "and minimum supported frequency for this tuner", "Invalid Frequency",
+ JOptionPane.ERROR_MESSAGE);
+ getMaximumFrequencyTextField().setFrequency(mExistingFrequency);
+ return;
+ }
+ }
+
+ if(hasTuner())
+ {
+ getTuner().getTunerController().setFrequencyExtents(minimum, maximum);
+ }
+
+ adjustFrequencyControl(minimum, maximum);
+ setLoading(false);
+ save();
+ }
+ }
+ });
+ }
+
+ return mMaximumFrequencyTextField;
+ }
+
+ /**
+ * Resets the minimum and maximum frequency values.
+ */
+ protected JButton getResetFrequenciesButton()
+ {
+ if(mResetFrequenciesButton == null)
+ {
+ mResetFrequenciesButton = new JButton("Reset");
+ mResetFrequenciesButton.addActionListener(e -> {
+ getMinimumFrequencyTextField().setFrequency(getMinimumTunableFrequency());
+ getMaximumFrequencyTextField().setFrequency(getMaximumTunableFrequency());
+ });
+ }
+
+ return mResetFrequenciesButton;
+ }
+
/**
* Button requesting to show tuner in new spectral display
*/
@@ -603,12 +867,22 @@ public class FrequencyPanel extends JPanel
{
public FrequencyPanel()
{
- setLayout(new MigLayout("insets 0,fill", "[][][][][grow,fill]", ""));
+ setLayout(new MigLayout("insets 0,fill", "[][][][grow,fill]", ""));
add(getFrequencyControl(), "spany 2");
add(new JLabel("PPM:"));
add(getFrequencyCorrectionSpinner());
add(getMeasuredPPMLabel(), "wrap");
add(getAutoPPMCheckBox(), "span");
+
+ JPanel minMaxPanel = new JPanel();
+ minMaxPanel.setLayout(new MigLayout("insets 0", "[][][][][][grow,fill]", ""));
+ minMaxPanel.add(new JLabel("Minimum:"));
+ minMaxPanel.add(getMinimumFrequencyTextField());
+ minMaxPanel.add(new JLabel("Maximum:"));
+ minMaxPanel.add(getMaximumFrequencyTextField());
+ minMaxPanel.add(getResetFrequenciesButton());
+ add(minMaxPanel, "span");
+
add(getTunerLockedStatusLabel(), "span");
}
@@ -619,7 +893,11 @@ public void updateControls()
{
getFrequencyControl().clearListeners();
getFrequencyControl().addListener(mFrequencyAndCorrectionChangeListener);
- getFrequencyControl().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
+ boolean hasTunerUnlocked = hasTuner() && !getTuner().getTunerController().isLockedSampleRate();
+ getFrequencyControl().setEnabled(hasTunerUnlocked);
+ getMinimumFrequencyTextField().setEnabled(hasTunerUnlocked);
+ getMaximumFrequencyTextField().setEnabled(hasTunerUnlocked);
+ getResetFrequenciesButton().setEnabled(hasTunerUnlocked);
getTunerLockedStatusLabel().setVisible(hasTuner() && getTuner().getTunerController().isLockedSampleRate());
getFrequencyCorrectionSpinner().setEnabled(hasTuner());
getAutoPPMCheckBox().setEnabled(hasTuner());
@@ -629,6 +907,8 @@ public void updateControls()
if(tuner != null)
{
getFrequencyControl().setFrequency(tuner.getTunerController().getFrequency(), false);
+ getMinimumFrequencyTextField().setFrequency(tuner.getTunerController().getMinimumFrequency());
+ getMaximumFrequencyTextField().setFrequency(tuner.getTunerController().getMaximumFrequency());
getFrequencyCorrectionSpinner().setValue(tuner.getTunerController().getFrequencyCorrection());
getAutoPPMCheckBox().setSelected(tuner.getTunerController().getFrequencyErrorCorrectionManager().isEnabled());
getFrequencyControl().addListener(getTuner().getTunerController());