#1473 Adds IF AGC Control for RSP tuners and Power Overload indication. Reverts changes to default MacOS library location in API. (#1484)

Co-authored-by: Dennis Sheirer <dsheirer@github.com>
This commit is contained in:
Denny Sheirer
2023-03-11 14:58:58 -05:00
committed by GitHub
parent d69ad46c10
commit bc4e6cb5b0
21 changed files with 464 additions and 59 deletions

View File

@@ -31,6 +31,8 @@ import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.GainReduction;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.IfMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.LoMode;
import io.github.dsheirer.util.ThreadPool;
import java.lang.ref.WeakReference;
import java.util.concurrent.locks.ReentrantLock;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -46,6 +48,7 @@ public abstract class ControlRsp<T extends Device> implements IControlRsp
protected int mGain;
private IDeviceEventListener mDeviceEventListener;
private IStreamListener mStreamListener;
protected WeakReference<IGainOverloadListener> mGainOverloadReference;
//Streaming control lock and boolean status indicator. Access to the boolean indicator is protected by the lock.
protected ReentrantLock mStreamingLock = new ReentrantLock();
@@ -77,8 +80,7 @@ public abstract class ControlRsp<T extends Device> implements IControlRsp
getDevice().getCompositeParameters().getControlAParameters().getDcOffset().setDC(true);
getDevice().getCompositeParameters().getControlAParameters().getDcOffset().setIQ(true);
//Setup IF, LO, and AGC Mode
getDevice().getCompositeParameters().getControlAParameters().getAgc().setAgcMode(AgcMode.DISABLE);
//Setup IF & LO Mode
getDevice().setIfMode(IfMode.IF_ZERO);
getDevice().setLoMode(LoMode.AUTO);
}
@@ -257,6 +259,20 @@ public abstract class ControlRsp<T extends Device> implements IControlRsp
}
}
/**
* Registers the listener to receive gain overload notifications.
* @param listener to register
*/
@Override
public void setGainOverloadListener(IGainOverloadListener listener)
{
if(mGainOverloadReference != null && mGainOverloadReference.get() != null)
{
mGainOverloadReference.clear();
}
mGainOverloadReference = new WeakReference<>(listener);
}
@Override
public void acknowledgePowerOverload(TunerSelect tunerSelect) throws SDRPlayException
@@ -269,6 +285,17 @@ public abstract class ControlRsp<T extends Device> implements IControlRsp
{
throw new SDRPlayException("Device is not initialized");
}
//Notify an optional weakly referenced, registered listener that gain overload has been acknowledged.
if(mGainOverloadReference != null)
{
IGainOverloadListener listener = mGainOverloadReference.get();
if(listener != null)
{
ThreadPool.CACHED.submit(() -> listener.notifyGainOverload(tunerSelect));
}
}
}
@Override
@@ -339,6 +366,27 @@ public abstract class ControlRsp<T extends Device> implements IControlRsp
}
}
/**
* Current IF AGC mode setting.
* @return AGC mode.
*/
@Override
public AgcMode getAgcMode()
{
return getDevice().getCompositeParameters().getControlAParameters().getAgc().getAgcMode();
}
/**
* Sets the IF AGC mode
* @param mode to set.
*/
@Override
public void setAgcMode(AgcMode mode) throws SDRPlayException
{
getDevice().getCompositeParameters().getControlAParameters().getAgc().setAgcMode(mode);
getDevice().update(getTunerSelect(), UpdateReason.CONTROL_AGC);
}
/**
* Registers listeners to receive device events and sample streams.
* @param deviceEventListener to receive device events

View File

@@ -25,6 +25,7 @@ import io.github.dsheirer.source.tuner.sdrplay.api.callback.IDeviceEventListener
import io.github.dsheirer.source.tuner.sdrplay.api.callback.IStreamListener;
import io.github.dsheirer.source.tuner.sdrplay.api.device.Device;
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
/**
* Control interface for base RSP device
@@ -125,4 +126,22 @@ public interface IControlRsp
* @return gain index value (0 - 28)
*/
int getGain();
/**
* Current IF AGC mode setting.
* @return IF agc mode
*/
AgcMode getAgcMode();
/**
* Sets the IF AGC mode
* @param mode to set.
*/
void setAgcMode(AgcMode mode) throws SDRPlayException;
/**
* Registers a listener to receive notifications of gain overload.
* @param listener to register
*/
void setGainOverloadListener(IGainOverloadListener listener);
}

View File

@@ -0,0 +1,30 @@
/*
* *****************************************************************************
* Copyright (C) 2014-2023 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 io.github.dsheirer.source.tuner.sdrplay;
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
/**
* Listener interface to receive notifications of gain overload in the RSP device.
*/
public interface IGainOverloadListener
{
void notifyGainOverload(TunerSelect tunerSelect);
}

View File

@@ -25,16 +25,16 @@ import java.util.EnumSet;
/**
* RSP device Sample Rate, Bandwidth and Decimation enumeration
*
* Note: final effective sample rate must be greater than IF bandwidth setting to avoid aliasing. The available IF
* bandwidth values effectively dictate the available sample rates
*/
public enum RspSampleRate
{
RATE_0_250(8_000_000, 016_000, Bandwidth.BW_0_300, Decimate.X32, "0.250 MHz (0.234 usable)"),
RATE_0_500(8_000_000, 024_000, Bandwidth.BW_0_600, Decimate.X16, "0.500 MHz (0.476 usable)"),
RATE_0_250(8_000_000, 16_000, Bandwidth.BW_0_300, Decimate.X32, "0.250 MHz (0.234 usable)"),
RATE_0_500(8_000_000, 24_000, Bandwidth.BW_0_600, Decimate.X16, "0.500 MHz (0.476 usable)"),
RATE_1_000(8_000_000, 100_000, Bandwidth.BW_1_536, Decimate.X8, "1.000 MHz (0.900 usable)"),
RATE_1_500(6_000_000, 140_000, Bandwidth.BW_1_536, Decimate.X4, "1.500 MHz (1.360 usable)"),
RATE_2_048(8_192_000, 248_000, Bandwidth.BW_1_536, Decimate.X4, "2.048 MHz (1.800 usable)"),
RATE_3_000(6_000_000, 300_000, Bandwidth.BW_5_000, Decimate.X2, "3.000 MHz (2.700 usable)"),
RATE_4_000(8_000_000, 340_000, Bandwidth.BW_5_000, Decimate.X2, "4.000 MHz (3.560 usable)"),
RATE_5_000(5_000_000, 880_000, Bandwidth.BW_5_000, Decimate.X1, "5.000 MHz (4.120 usable)"),
@@ -55,11 +55,11 @@ public enum RspSampleRate
UNDEFINED(0, 0, Bandwidth.UNDEFINED, Decimate.X1, "UNDEFINED");
private long mSampleRate;
private long mUnusable;
private Bandwidth mBandwidth;
private Decimate mDecimation;
private String mDescription;
private final long mSampleRate;
private final long mUnusable;
private final Bandwidth mBandwidth;
private final Decimate mDecimation;
private final String mDescription;
/**
* Constructs an instance
@@ -81,12 +81,12 @@ public enum RspSampleRate
/**
* Single tuner sample rates for all devices operating in single tuner mode
*/
public static EnumSet<RspSampleRate> SINGLE_TUNER_SAMPLE_RATES = EnumSet.range(RATE_0_250, RATE_10_000);
public static final EnumSet<RspSampleRate> SINGLE_TUNER_SAMPLE_RATES = EnumSet.range(RATE_0_250, RATE_10_000);
/**
* RSPduo dual-tuner mode sample rates
*/
public static EnumSet<RspSampleRate> DUAL_TUNER_SAMPLE_RATES = EnumSet.range(DUO_RATE_0_500, DUO_RATE_2_000);
public static final EnumSet<RspSampleRate> DUAL_TUNER_SAMPLE_RATES = EnumSet.range(DUO_RATE_0_500, DUO_RATE_2_000);
/**
* Sample Rate
@@ -137,14 +137,6 @@ public enum RspSampleRate
return mDecimation;
}
/**
* Indicates if this sample rate specifies decimation
*/
public boolean hasDecimation()
{
return getDecimation().isEnabled();
}
/**
* Effective Sample Rate (sample rate / decimation). Note: for RSPduo operating in dual-tuner mode, an
* inherent x4 decimation is applied in the hardware.

View File

@@ -23,6 +23,7 @@ import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.GainReduction;
import io.github.dsheirer.source.tuner.sdrplay.rsp1a.Rsp1aTunerConfiguration;
import io.github.dsheirer.source.tuner.sdrplay.rsp2.Rsp2TunerConfiguration;
@@ -33,7 +34,7 @@ import io.github.dsheirer.source.tuner.sdrplay.rspDx.RspDxTunerConfiguration;
/**
* Abstract RSP tuner configuration
*/
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, include = JsonTypeInfo.As.PROPERTY, property = "type")
@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type")
@JsonSubTypes({
@JsonSubTypes.Type(value = Rsp1aTunerConfiguration.class, name = "rsp1aTunerConfiguration"),
@JsonSubTypes.Type(value = Rsp2TunerConfiguration.class, name = "rsp2TunerConfiguration"),
@@ -47,7 +48,8 @@ public abstract class RspTunerConfiguration extends TunerConfiguration
public static final RspSampleRate DEFAULT_DUAL_TUNER_SAMPLE_RATE = RspSampleRate.DUO_RATE_2_000;
private RspSampleRate mRspSampleRate = DEFAULT_SINGLE_TUNER_SAMPLE_RATE;
private int mGain = 14;
private int mGain = 24;
private AgcMode mAgcMode = AgcMode.ENABLE;
/**
* JAXB Constructor
@@ -103,4 +105,23 @@ public abstract class RspTunerConfiguration extends TunerConfiguration
mGain = gain;
}
}
/**
* IF AGC mode
* @return mode
*/
@JacksonXmlProperty(isAttribute = true, localName = "agcMode")
public AgcMode getAgcMode()
{
return mAgcMode;
}
/**
* Sets the IF AGC mode
* @param mode to set
*/
public void setAgcMode(AgcMode mode)
{
mAgcMode = mode;
}
}

View File

@@ -21,11 +21,21 @@ package io.github.dsheirer.source.tuner.sdrplay;
import io.github.dsheirer.preference.UserPreferences;
import io.github.dsheirer.source.tuner.manager.TunerManager;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.GainReduction;
import io.github.dsheirer.source.tuner.ui.TunerEditor;
import io.github.dsheirer.util.ThreadPool;
import java.awt.Color;
import java.awt.EventQueue;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.atomic.AtomicBoolean;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.JButton;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JOptionPane;
import javax.swing.JSlider;
@@ -33,11 +43,14 @@ import javax.swing.JSlider;
/**
* Abstract RSP tuner editor
*/
public abstract class RspTunerEditor<C extends RspTunerConfiguration> extends TunerEditor<RspTuner,C>
public abstract class RspTunerEditor<C extends RspTunerConfiguration> extends TunerEditor<RspTuner,C> implements IGainOverloadListener
{
private Logger mLog = LoggerFactory.getLogger(RspTunerEditor.class);
private JSlider mGainSlider;
private JLabel mGainValueLabel;
private JComboBox<AgcMode> mAgcModeCombo;
private JButton mGainOverloadButton;
private AtomicBoolean mGainOverloadAlert = new AtomicBoolean();
/**
* Constructs an instance
@@ -105,4 +118,87 @@ public abstract class RspTunerEditor<C extends RspTunerConfiguration> extends Tu
return mGainValueLabel;
}
/**
* IF AGC mode combobox control
*/
protected JComboBox<AgcMode> getAgcModeCombo()
{
if(mAgcModeCombo == null)
{
mAgcModeCombo = new JComboBox<>(AgcMode.values());
mAgcModeCombo.setEnabled(false);
mAgcModeCombo.addActionListener(e -> {
if(hasTuner() && !isLoading())
{
AgcMode selected = (AgcMode)mAgcModeCombo.getSelectedItem();
try
{
getTunerController().getControlRsp().setAgcMode(selected);
save();
}
catch(SDRPlayException se)
{
mLog.error("Error setting AGC mode on RSP device");
}
save();
}
});
}
return mAgcModeCombo;
}
/**
* Gain overload button. Used in a disabled state to indicate (e.g. flashing color) that gain overload is detected.
*/
protected JButton getGainOverloadButton()
{
if(mGainOverloadButton == null)
{
mGainOverloadButton = new JButton("Gain Overload");
mGainOverloadButton.setToolTipText("Notification that manual gain is set too high and causing power overload. Reduce manual gain when this flashes.");
mGainOverloadButton.setEnabled(false);
}
return mGainOverloadButton;
}
@Override
public void notifyGainOverload(TunerSelect tunerSelect)
{
if(hasTuner() && getTuner().getRspTunerController().getTunerSelect() == tunerSelect)
{
//Set overload alert
EventQueue.invokeLater(() -> setGainOverloadAlert(true));
//Schedule a reset to happen 1 second later
ThreadPool.SCHEDULED.schedule((Runnable) () -> setGainOverloadAlert(false), 600, TimeUnit.MILLISECONDS);
}
}
/**
* Toggles the alert styling of the disabled gain overload button to indicate an alert condition or a normal
* operating condition.
* @param alert true to apply alert styling or false to reset.
*/
private void setGainOverloadAlert(boolean alert)
{
if(alert && mGainOverloadAlert.compareAndSet(false, true))
{
getGainOverloadButton().setEnabled(true);
getGainOverloadButton().setForeground(Color.YELLOW);
getGainOverloadButton().setBackground(Color.RED);
}
else if(!alert && mGainOverloadAlert.compareAndSet(true, false))
{
getGainOverloadButton().setEnabled(false);
getGainOverloadButton().setForeground(getForeground());
getGainOverloadButton().setBackground(getBackground());
}
else
{
mLog.info("Ignoring duplicate gain alerting - alert[" + alert + "] atomic [" + mGainOverloadAlert.get() + "]");
}
}
}

View File

@@ -61,7 +61,8 @@ import org.slf4j.LoggerFactory;
public class SDRplay
{
public static final String SDRPLAY_API_LIBRARY_NAME = "sdrplay_api";
public static final String SDRPLAY_API_PATH_LINUX_AND_OSX = "/usr/local/lib/libsdrplay_api.so";
public static final String SDRPLAY_API_PATH_LINUX = "/usr/local/lib/libsdrplay_api.so";
public static final String SDRPLAY_API_PATH_MAC_OS = "/usr/local/lib/libsdrplay_api.dylib";
public static final String SDRPLAY_API_PATH_WINDOWS = System.getenv("ProgramFiles") +
"\\SDRplay\\API\\" + (System.getProperty("sun.arch.data.model").contentEquals("64") ? "x64" : "x86") +
"\\" + SDRPLAY_API_LIBRARY_NAME;
@@ -671,11 +672,11 @@ public class SDRplay
}
else if(SystemUtils.IS_OS_LINUX)
{
return SDRPLAY_API_PATH_LINUX_AND_OSX;
return SDRPLAY_API_PATH_LINUX;
}
else if(SystemUtils.IS_OS_MAC_OSX)
{
return SDRPLAY_API_PATH_LINUX_AND_OSX;
return SDRPLAY_API_PATH_MAC_OS;
}
mLog.error("Unrecognized operating system. Cannot identify sdrplay api library path");

View File

@@ -24,6 +24,7 @@ import io.github.dsheirer.source.tuner.ITunerErrorListener;
import io.github.dsheirer.source.tuner.TunerType;
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
import io.github.dsheirer.source.tuner.sdrplay.RspTunerController;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -54,9 +55,18 @@ public class Rsp1TunerController extends RspTunerController<IControlRsp1>
@Override
public void apply(TunerConfiguration config) throws SourceException
{
if(config instanceof Rsp1TunerConfiguration)
if(config instanceof Rsp1TunerConfiguration rtc)
{
super.apply(config);
try
{
getControlRsp().setAgcMode(rtc.getAgcMode());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSP IF AGC Mode to " + rtc.getAgcMode());
}
}
else
{

View File

@@ -25,12 +25,14 @@ import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SpinnerNumberModel;
@@ -59,7 +61,7 @@ public class Rsp1TunerEditor extends RspTunerEditor<Rsp1TunerConfiguration>
private void init()
{
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
"[][][][][][][][][][][][grow]"));
"[][][][][][][][][][][][][grow]"));
add(new JLabel("Tuner:"));
add(getTunerIdLabel(), "wrap");
@@ -77,6 +79,13 @@ public class Rsp1TunerEditor extends RspTunerEditor<Rsp1TunerConfiguration>
add(new JLabel("Sample Rate:"));
add(getSampleRateCombo(), "wrap");
add(new JLabel("IF AGC Mode:"));
JPanel gainPanel = new JPanel();
gainPanel.setLayout(new MigLayout("insets 0","[grow,fill][]",""));
gainPanel.add(getAgcModeCombo());
gainPanel.add(getGainOverloadButton());
add(gainPanel, "wrap");
add(new JLabel("Gain:"));
add(getGainSlider());
add(getGainValueLabel());
@@ -116,6 +125,14 @@ public class Rsp1TunerEditor extends RspTunerEditor<Rsp1TunerConfiguration>
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
getAgcModeCombo().setEnabled(hasTuner());
if(hasTuner())
{
getAgcModeCombo().setSelectedItem(getTunerController().getControlRsp().getAgcMode());
//Register to receive gain overload notifications
getTunerController().getControlRsp().setGainOverloadListener(this);
}
getGainSlider().setEnabled(hasTuner());
getGainValueLabel().setEnabled(hasTuner());
getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
@@ -134,6 +151,7 @@ public class Rsp1TunerEditor extends RspTunerEditor<Rsp1TunerConfiguration>
getConfiguration().setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected());
getConfiguration().setSampleRate((RspSampleRate)getSampleRateCombo().getSelectedItem());
getConfiguration().setGain(getGainSlider().getValue());
getConfiguration().setAgcMode((AgcMode)getAgcModeCombo().getSelectedItem());
saveConfiguration();
}

View File

@@ -59,6 +59,15 @@ public class Rsp1aTunerController extends RspTunerController<IControlRsp1a>
{
super.apply(config);
try
{
getControlRsp().setAgcMode(rtc.getAgcMode());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSP IF AGC Mode to " + rtc.getAgcMode());
}
try
{
getControlRsp().setBiasT(rtc.isBiasT());

View File

@@ -25,6 +25,7 @@ import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -32,6 +33,7 @@ import org.slf4j.LoggerFactory;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SpinnerNumberModel;
@@ -63,7 +65,7 @@ public class Rsp1aTunerEditor extends RspTunerEditor<Rsp1aTunerConfiguration>
private void init()
{
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
"[][][][][][][][][][][][grow]"));
"[][][][][][][][][][][][][grow]"));
add(new JLabel("Tuner:"));
add(getTunerIdLabel(), "wrap");
@@ -81,6 +83,13 @@ public class Rsp1aTunerEditor extends RspTunerEditor<Rsp1aTunerConfiguration>
add(new JLabel("Sample Rate:"));
add(getSampleRateCombo(), "wrap");
add(new JLabel("IF AGC Mode:"));
JPanel gainPanel = new JPanel();
gainPanel.setLayout(new MigLayout("insets 0","[grow,fill][]",""));
gainPanel.add(getAgcModeCombo());
gainPanel.add(getGainOverloadButton());
add(gainPanel, "wrap");
add(new JLabel("Gain:"));
add(getGainSlider());
add(getGainValueLabel());
@@ -127,6 +136,14 @@ public class Rsp1aTunerEditor extends RspTunerEditor<Rsp1aTunerConfiguration>
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
getAgcModeCombo().setEnabled(hasTuner());
if(hasTuner())
{
getAgcModeCombo().setSelectedItem(getTunerController().getControlRsp().getAgcMode());
//Register to receive gain overload notifications
getTunerController().getControlRsp().setGainOverloadListener(this);
}
getGainSlider().setEnabled(hasTuner());
getGainValueLabel().setEnabled(hasTuner());
getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
@@ -178,6 +195,7 @@ public class Rsp1aTunerEditor extends RspTunerEditor<Rsp1aTunerConfiguration>
getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
getConfiguration().setRfDabNotch(getRfDabNotchCheckBox().isSelected());
getConfiguration().setGain(getGainSlider().getValue());
getConfiguration().setAgcMode((AgcMode)getAgcModeCombo().getSelectedItem());
saveConfiguration();
}

View File

@@ -59,6 +59,15 @@ public class Rsp2TunerController extends RspTunerController<IControlRsp2>
{
super.apply(config);
try
{
getControlRsp().setAgcMode(rtc.getAgcMode());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSP IF AGC Mode to " + rtc.getAgcMode());
}
try
{
getControlRsp().setBiasT(rtc.isBiasT());

View File

@@ -25,6 +25,7 @@ import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.Rsp2AntennaSelection;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
@@ -33,6 +34,7 @@ import org.slf4j.LoggerFactory;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SpinnerNumberModel;
@@ -65,7 +67,7 @@ public class Rsp2TunerEditor extends RspTunerEditor<Rsp2TunerConfiguration>
private void init()
{
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
"[][][][][][][][][][][][grow]"));
"[][][][][][][][][][][][][grow]"));
add(new JLabel("Tuner:"));
add(getTunerIdLabel(), "wrap");
@@ -83,6 +85,13 @@ public class Rsp2TunerEditor extends RspTunerEditor<Rsp2TunerConfiguration>
add(new JLabel("Sample Rate:"));
add(getSampleRateCombo(), "wrap");
add(new JLabel("IF AGC Mode:"));
JPanel gainPanel = new JPanel();
gainPanel.setLayout(new MigLayout("insets 0","[grow,fill][]",""));
gainPanel.add(getAgcModeCombo());
gainPanel.add(getGainOverloadButton());
add(gainPanel, "wrap");
add(new JLabel("Gain:"));
add(getGainSlider());
add(getGainValueLabel());
@@ -131,6 +140,14 @@ public class Rsp2TunerEditor extends RspTunerEditor<Rsp2TunerConfiguration>
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
getAgcModeCombo().setEnabled(hasTuner());
if(hasTuner())
{
getAgcModeCombo().setSelectedItem(getTunerController().getControlRsp().getAgcMode());
//Register to receive gain overload notifications
getTunerController().getControlRsp().setGainOverloadListener(this);
}
getGainSlider().setEnabled(hasTuner());
getGainValueLabel().setEnabled(hasTuner());
getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
@@ -192,6 +209,7 @@ public class Rsp2TunerEditor extends RspTunerEditor<Rsp2TunerConfiguration>
getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
getConfiguration().setAntennaSelection((Rsp2AntennaSelection)getAntennaSelectionCombo().getSelectedItem());
getConfiguration().setGain(getGainSlider().getValue());
getConfiguration().setAgcMode((AgcMode)getAgcModeCombo().getSelectedItem());
saveConfiguration();
}

View File

@@ -20,6 +20,7 @@
package io.github.dsheirer.source.tuner.sdrplay.rspDuo;
import io.github.dsheirer.source.tuner.sdrplay.ControlRsp;
import io.github.dsheirer.source.tuner.sdrplay.IGainOverloadListener;
import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
import io.github.dsheirer.source.tuner.sdrplay.api.DeviceSelectionMode;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
@@ -28,11 +29,11 @@ import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
import io.github.dsheirer.source.tuner.sdrplay.api.device.RspDuoDevice;
import io.github.dsheirer.source.tuner.sdrplay.api.device.RspDuoTuner;
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.IfMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.LoMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.TunerParameters;
import io.github.dsheirer.util.ThreadPool;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
@@ -97,8 +98,7 @@ public abstract class ControlRspDuo<T extends RspDuoTuner> extends ControlRsp<Rs
getControlParameters().getDcOffset().setDC(true);
getControlParameters().getDcOffset().setIQ(true);
//Setup LO and AGC Mode
getControlParameters().getAgc().setAgcMode(AgcMode.DISABLE);
//Setup LO Mode
getTunerParameters().setLoMode(LoMode.AUTO);
//Setup IF mode. In master/slave dual-tuner mode use IF_2048, otherwise use IF_ZERO
@@ -239,6 +239,17 @@ public abstract class ControlRspDuo<T extends RspDuoTuner> extends ControlRsp<Rs
{
throw new SDRPlayException("Device is not initialized");
}
//Notify an optional weakly referenced, registered listener that gain overload has been acknowledged.
if(mGainOverloadReference != null)
{
IGainOverloadListener listener = mGainOverloadReference.get();
if(listener != null)
{
ThreadPool.CACHED.submit(() -> listener.notifyGainOverload(tunerSelect));
}
}
}
@Override

View File

@@ -20,9 +20,11 @@
package io.github.dsheirer.source.tuner.sdrplay.rspDuo;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.UpdateReason;
import io.github.dsheirer.source.tuner.sdrplay.api.device.RspDuoDevice;
import io.github.dsheirer.source.tuner.sdrplay.api.device.RspDuoTuner2;
import io.github.dsheirer.source.tuner.sdrplay.api.device.TunerSelect;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.ControlParameters;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.TunerParameters;
import org.slf4j.Logger;
@@ -103,4 +105,25 @@ public abstract class ControlRspDuoTuner2 extends ControlRspDuo<RspDuoTuner2> im
throw new SDRPlayException("Device is not initialized");
}
}
/**
* Current IF AGC mode setting.
* @return AGC mode.
*/
@Override
public AgcMode getAgcMode()
{
return getDevice().getCompositeParameters().getControlBParameters().getAgc().getAgcMode();
}
/**
* Sets the IF AGC mode
* @param mode to set.
*/
@Override
public void setAgcMode(AgcMode mode) throws SDRPlayException
{
getDevice().getCompositeParameters().getControlBParameters().getAgc().setAgcMode(mode);
getDevice().update(getTunerSelect(), UpdateReason.CONTROL_AGC);
}
}

View File

@@ -57,53 +57,62 @@ public class RspDuoTuner1Controller extends RspTunerController<IControlRspDuoTun
@Override
public void apply(TunerConfiguration config) throws SourceException
{
if(config instanceof RspDuoTuner1Configuration duo1)
if(config instanceof RspDuoTuner1Configuration rtc)
{
super.apply(config);
try
{
getControlRsp().setRfNotch(duo1.isRfNotch());
getControlRsp().setAgcMode(rtc.getAgcMode());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 1 RF notch enabled to " + duo1.isRfNotch());
mLog.error("Error setting RSP IF AGC Mode to " + rtc.getAgcMode());
}
try
{
getControlRsp().setRfDabNotch(duo1.isRfDabNotch());
getControlRsp().setRfNotch(rtc.isRfNotch());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 1 RF DAB notch enabled to " + duo1.isRfDabNotch());
mLog.error("Error setting RSPduo tuner 1 RF notch enabled to " + rtc.isRfNotch());
}
try
{
getControlRsp().setAmNotch(duo1.isAmNotch());
getControlRsp().setRfDabNotch(rtc.isRfDabNotch());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 1 AM notch enabled to " + duo1.isAmNotch());
mLog.error("Error setting RSPduo tuner 1 RF DAB notch enabled to " + rtc.isRfDabNotch());
}
try
{
getControlRsp().setAmPort(duo1.getAmPort());
getControlRsp().setAmNotch(rtc.isAmNotch());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 1 AM port to " + duo1.getAmPort());
mLog.error("Error setting RSPduo tuner 1 AM notch enabled to " + rtc.isAmNotch());
}
try
{
getControlRsp().setExternalReferenceOutput(duo1.isExternalReferenceOutput());
getControlRsp().setAmPort(rtc.getAmPort());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 1 external reference output enabled to " + duo1.isExternalReferenceOutput());
mLog.error("Error setting RSPduo tuner 1 AM port to " + rtc.getAmPort());
}
try
{
getControlRsp().setExternalReferenceOutput(rtc.isExternalReferenceOutput());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 1 external reference output enabled to " + rtc.isExternalReferenceOutput());
}
}
else

View File

@@ -28,6 +28,7 @@ import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDuoAmPort;
import java.util.EnumSet;
import net.miginfocom.swing.MigLayout;
@@ -73,7 +74,7 @@ public class RspDuoTuner1Editor extends RspTunerEditor<RspDuoTuner1Configuration
private void init()
{
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
"[][][][][][][][][][][][][][][grow]"));
"[][][][][][][][][][][][][][][][grow]"));
add(new JLabel("Tuner:"));
JPanel labelAndButtonPanel = new JPanel();
@@ -93,6 +94,13 @@ public class RspDuoTuner1Editor extends RspTunerEditor<RspDuoTuner1Configuration
add(new JLabel("Sample Rate:"));
add(getSampleRateCombo(), "wrap");
add(new JLabel("IF AGC Mode:"));
JPanel gainPanel = new JPanel();
gainPanel.setLayout(new MigLayout("insets 0","[grow,fill][]",""));
gainPanel.add(getAgcModeCombo());
gainPanel.add(getGainOverloadButton());
add(gainPanel, "wrap");
add(new JLabel("Gain:"));
add(getGainSlider());
add(getGainValueLabel());
@@ -148,6 +156,14 @@ public class RspDuoTuner1Editor extends RspTunerEditor<RspDuoTuner1Configuration
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
getAgcModeCombo().setEnabled(hasTuner());
if(hasTuner())
{
getAgcModeCombo().setSelectedItem(getTunerController().getControlRsp().getAgcMode());
//Register to receive gain overload notifications
getTunerController().getControlRsp().setGainOverloadListener(this);
}
getGainSlider().setEnabled(hasTuner());
getGainValueLabel().setEnabled(hasTuner());
getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
@@ -222,6 +238,7 @@ public class RspDuoTuner1Editor extends RspTunerEditor<RspDuoTuner1Configuration
getConfiguration().setRfDabNotch(getRfDabNotchCheckBox().isSelected());
getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
getConfiguration().setGain(getGainSlider().getValue());
getConfiguration().setAgcMode((AgcMode)getAgcModeCombo().getSelectedItem());
saveConfiguration();
}

View File

@@ -57,44 +57,56 @@ public class RspDuoTuner2Controller extends RspTunerController<IControlRspDuoTun
@Override
public void apply(TunerConfiguration config) throws SourceException
{
if(config instanceof RspDuoTuner2Configuration duo2)
if(config instanceof RspDuoTuner2Configuration rtc)
{
super.apply(config);
try
if(!getControlRsp().isSlaveMode())
{
getControlRsp().setRfNotch(duo2.isRfNotch());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 2 RF notch enabled to " + duo2.isRfNotch());
try
{
getControlRsp().setAgcMode(rtc.getAgcMode());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSP IF AGC Mode to " + rtc.getAgcMode());
}
}
try
{
getControlRsp().setRfDabNotch(duo2.isRfDabNotch());
getControlRsp().setRfNotch(rtc.isRfNotch());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 2 RF DAB notch enabled to " + duo2.isRfDabNotch());
mLog.error("Error setting RSPduo tuner 2 RF notch enabled to " + rtc.isRfNotch());
}
try
{
getControlRsp().setBiasT(duo2.isBiasT());
getControlRsp().setRfDabNotch(rtc.isRfDabNotch());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 2 Bias-T enabled to " + duo2.isBiasT());
mLog.error("Error setting RSPduo tuner 2 RF DAB notch enabled to " + rtc.isRfDabNotch());
}
try
{
getControlRsp().setExternalReferenceOutput(duo2.isExternalReferenceOutput());
getControlRsp().setBiasT(rtc.isBiasT());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 2 external reference output enabled to " + duo2.isExternalReferenceOutput());
mLog.error("Error setting RSPduo tuner 2 Bias-T enabled to " + rtc.isBiasT());
}
try
{
getControlRsp().setExternalReferenceOutput(rtc.isExternalReferenceOutput());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSPduo tuner 2 external reference output enabled to " + rtc.isExternalReferenceOutput());
}
}
else

View File

@@ -28,6 +28,7 @@ import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import java.util.EnumSet;
import net.miginfocom.swing.MigLayout;
import org.slf4j.Logger;
@@ -71,7 +72,7 @@ public class RspDuoTuner2Editor extends RspTunerEditor<RspDuoTuner2Configuration
private void init()
{
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
"[][][][][][][][][][][][][][][grow]"));
"[][][][][][][][][][][][][][][][grow]"));
add(new JLabel("Tuner:"));
JPanel labelAndButtonPanel = new JPanel();
@@ -91,6 +92,13 @@ public class RspDuoTuner2Editor extends RspTunerEditor<RspDuoTuner2Configuration
add(new JLabel("Sample Rate:"));
add(getSampleRateCombo(), "wrap");
add(new JLabel("IF AGC Mode:"));
JPanel gainPanel = new JPanel();
gainPanel.setLayout(new MigLayout("insets 0","[grow,fill][]",""));
gainPanel.add(getAgcModeCombo());
gainPanel.add(getGainOverloadButton());
add(gainPanel, "wrap");
add(new JLabel("Gain:"));
add(getGainSlider());
add(getGainValueLabel());
@@ -165,6 +173,14 @@ public class RspDuoTuner2Editor extends RspTunerEditor<RspDuoTuner2Configuration
getSampleRateCombo().setEnabled(hasTuner() && !isSlaveMode() && !getTuner().getTunerController().isLockedSampleRate());
getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
getAgcModeCombo().setEnabled(hasTuner());
if(hasTuner())
{
getAgcModeCombo().setSelectedItem(getTunerController().getControlRsp().getAgcMode());
//Register to receive gain overload notifications
getTunerController().getControlRsp().setGainOverloadListener(this);
}
getGainSlider().setEnabled(hasTuner());
getGainValueLabel().setEnabled(hasTuner());
getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
@@ -234,6 +250,7 @@ public class RspDuoTuner2Editor extends RspTunerEditor<RspDuoTuner2Configuration
getConfiguration().setRfDabNotch(getRfDabNotchCheckBox().isSelected());
getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
getConfiguration().setGain(getGainSlider().getValue());
getConfiguration().setAgcMode((AgcMode)getAgcModeCombo().getSelectedItem());
saveConfiguration();
}

View File

@@ -59,6 +59,15 @@ public class RspDxTunerController extends RspTunerController<IControlRspDx>
{
super.apply(config);
try
{
getControlRsp().setAgcMode(rtc.getAgcMode());
}
catch(SDRPlayException se)
{
mLog.error("Error setting RSP IF AGC Mode to " + rtc.getAgcMode());
}
try
{
getControlRsp().setAntenna(rtc.getAntenna());

View File

@@ -25,6 +25,7 @@ import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner;
import io.github.dsheirer.source.tuner.sdrplay.RspSampleRate;
import io.github.dsheirer.source.tuner.sdrplay.RspTunerEditor;
import io.github.dsheirer.source.tuner.sdrplay.api.SDRPlayException;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.control.AgcMode;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.HdrModeBandwidth;
import io.github.dsheirer.source.tuner.sdrplay.api.parameter.tuner.RspDxAntenna;
import net.miginfocom.swing.MigLayout;
@@ -34,6 +35,7 @@ import org.slf4j.LoggerFactory;
import javax.swing.JCheckBox;
import javax.swing.JComboBox;
import javax.swing.JLabel;
import javax.swing.JPanel;
import javax.swing.JSeparator;
import javax.swing.SpinnerNumberModel;
@@ -86,6 +88,13 @@ public class RspDxTunerEditor extends RspTunerEditor<RspDxTunerConfiguration>
add(new JLabel("Sample Rate:"));
add(getSampleRateCombo(), "wrap");
add(new JLabel("IF AGC Mode:"));
JPanel gainPanel = new JPanel();
gainPanel.setLayout(new MigLayout("insets 0","[grow,fill][]",""));
gainPanel.add(getAgcModeCombo());
gainPanel.add(getGainOverloadButton());
add(gainPanel, "wrap");
add(new JLabel("Gain:"));
add(getGainSlider());
add(getGainValueLabel());
@@ -140,6 +149,14 @@ public class RspDxTunerEditor extends RspTunerEditor<RspDxTunerConfiguration>
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
getSampleRateCombo().setSelectedItem(hasTuner() ? getTunerController().getControlRsp().getSampleRateEnumeration() : null);
getAgcModeCombo().setEnabled(hasTuner());
if(hasTuner())
{
getAgcModeCombo().setSelectedItem(getTunerController().getControlRsp().getAgcMode());
//Register to receive gain overload notifications
getTunerController().getControlRsp().setGainOverloadListener(this);
}
getGainSlider().setEnabled(hasTuner());
getGainValueLabel().setEnabled(hasTuner());
getGainSlider().setValue(hasTuner() ? getTunerController().getControlRsp().getGain() : 0);
@@ -213,6 +230,7 @@ public class RspDxTunerEditor extends RspTunerEditor<RspDxTunerConfiguration>
getConfiguration().setRfNotch(getRfNotchCheckBox().isSelected());
getConfiguration().setAntenna((RspDxAntenna) getAntennaCombo().getSelectedItem());
getConfiguration().setGain(getGainSlider().getValue());
getConfiguration().setAgcMode((AgcMode)getAgcModeCombo().getSelectedItem());
saveConfiguration();
}