mirror of
https://github.com/DSheirer/sdrtrunk.git
synced 2026-11-12 16:47:31 -05:00
Hydrasdr Tuner Support (#2339)
HydraSDR tuner support * Adds Bias-T option * Update nightly.yml * Fix BoardID * Consolidated calibrations and sample converters and removed logging. --------- Co-authored-by: Benjamin Vernoux <bvernoux@gmail.com> Co-authored-by: denny <dennis.sheirer@gmail.com>
This commit is contained in:
@@ -30,6 +30,7 @@ public enum TunerClass
|
||||
FUNCUBE_DONGLE_PRO("Funcube Dongle Pro" ),
|
||||
FUNCUBE_DONGLE_PRO_PLUS("Funcube Dongle Pro+" ),
|
||||
HACKRF("HackRF" ),
|
||||
HYDRASDR("HydraSDR"),
|
||||
RTL2832("RTL-2832"),
|
||||
RSP("RSP"),
|
||||
TEST_TUNER("Test"),
|
||||
@@ -53,8 +54,8 @@ public enum TunerClass
|
||||
return mDescription;
|
||||
}
|
||||
|
||||
public static final EnumSet<TunerClass> SUPPORTED_USB_TUNERS = EnumSet.of(AIRSPY, AIRSPY_HF, HACKRF, RTL2832,
|
||||
FUNCUBE_DONGLE_PRO, FUNCUBE_DONGLE_PRO_PLUS);
|
||||
public static final EnumSet<TunerClass> SUPPORTED_USB_TUNERS = EnumSet.of(AIRSPY, AIRSPY_HF, HACKRF, HYDRASDR,
|
||||
RTL2832, FUNCUBE_DONGLE_PRO, FUNCUBE_DONGLE_PRO_PLUS);
|
||||
|
||||
public static final EnumSet<TunerClass> FUNCUBE_TUNERS = EnumSet.of(FUNCUBE_DONGLE_PRO, FUNCUBE_DONGLE_PRO_PLUS);
|
||||
|
||||
@@ -121,6 +122,8 @@ public enum TunerClass
|
||||
case 0x1D50CC15: //HACKRF ONE
|
||||
case 0x1D50604B: //HACKRF JAWBREAKER
|
||||
return HACKRF;
|
||||
case 0x38AF0001: //HYDRASDR RFONE (official VID 38af, PID 0001)
|
||||
return HYDRASDR;
|
||||
case 0x1D5060A1:
|
||||
return AIRSPY;
|
||||
case 0x03EB800C:
|
||||
|
||||
@@ -44,6 +44,10 @@ import io.github.dsheirer.source.tuner.hackrf.HackRFTuner;
|
||||
import io.github.dsheirer.source.tuner.hackrf.HackRFTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.hackrf.HackRFTunerController;
|
||||
import io.github.dsheirer.source.tuner.hackrf.HackRFTunerEditor;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTuner;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerController;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerEditor;
|
||||
import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration;
|
||||
@@ -375,6 +379,8 @@ public class TunerFactory
|
||||
throw new SourceException("Unable to find matching tuner sound card mixer");
|
||||
case HACKRF:
|
||||
return new HackRFTuner(new HackRFTunerController(bus, portAddress, tunerErrorListener), tunerErrorListener, channelizerType);
|
||||
case HYDRASDR:
|
||||
return new HydraSdrTuner(new HydraSdrTunerController(bus, portAddress, tunerErrorListener), tunerErrorListener, channelizerType);
|
||||
case RTL2832:
|
||||
return new RTL2832Tuner(new RTL2832TunerController(bus, portAddress, tunerErrorListener), tunerErrorListener, channelizerType);
|
||||
default:
|
||||
@@ -424,6 +430,8 @@ public class TunerFactory
|
||||
case HACKRF_ONE:
|
||||
case HACKRF_RAD1O:
|
||||
return new HackRFTunerConfiguration(uniqueID);
|
||||
case HYDRASDR_R828D:
|
||||
return new HydraSdrTunerConfiguration(uniqueID);
|
||||
case RAFAELMICRO_R820T:
|
||||
return new R820TTunerConfiguration(uniqueID);
|
||||
case RAFAELMICRO_R828D:
|
||||
@@ -467,6 +475,8 @@ public class TunerFactory
|
||||
return new FCD2TunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case HACKRF:
|
||||
return new HackRFTunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case HYDRASDR:
|
||||
return new HydraSdrTunerEditor(userPreferences, tunerManager, discoveredTuner);
|
||||
case RSP:
|
||||
if(discoveredTuner instanceof DiscoveredRspTuner discoveredRspTuner)
|
||||
{
|
||||
|
||||
@@ -36,6 +36,7 @@ public enum TunerType
|
||||
HACKRF_ONE("ONE"),
|
||||
HACKRF_JAWBREAKER("Jawbreaker"),
|
||||
HACKRF_RAD1O("RAD1O"),
|
||||
HYDRASDR_R828D("R828D"),
|
||||
RAFAELMICRO_R820T("R820T"),
|
||||
RAFAELMICRO_R828D("R828D"),
|
||||
RSP_1("RSP1"),
|
||||
@@ -73,7 +74,7 @@ public enum TunerType
|
||||
* Supported USB tuner types
|
||||
*/
|
||||
public static EnumSet<TunerType> SUPPORTED_USB_TUNERS = EnumSet.of(AIRSPY_R820T, ELONICS_E4000, FITIPOWER_FC0012,
|
||||
HACKRF_JAWBREAKER, HACKRF_RAD1O, HACKRF_ONE, RAFAELMICRO_R820T);
|
||||
HACKRF_JAWBREAKER, HACKRF_RAD1O, HACKRF_ONE, HYDRASDR_R828D, RAFAELMICRO_R820T);
|
||||
|
||||
/**
|
||||
* Supported sound card tuner types
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 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
|
||||
@@ -20,7 +20,7 @@
|
||||
package io.github.dsheirer.source.tuner.airspy;
|
||||
|
||||
import io.github.dsheirer.buffer.INativeBufferFactory;
|
||||
import io.github.dsheirer.buffer.airspy.AirspyNativeBufferFactory;
|
||||
import io.github.dsheirer.buffer.sample.SampleNativeBufferFactory;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
import io.github.dsheirer.source.tuner.ITunerErrorListener;
|
||||
import io.github.dsheirer.source.tuner.TunerType;
|
||||
@@ -69,7 +69,7 @@ public class AirspyTunerController extends USBTunerController
|
||||
private static final byte USB_REQUEST_OUT = (byte) (LibUsb.ENDPOINT_OUT | LibUsb.REQUEST_TYPE_VENDOR | LibUsb.RECIPIENT_DEVICE);
|
||||
public static final DecimalFormat MHZ_FORMATTER = new DecimalFormat("#.00 MHz");
|
||||
public static final AirspySampleRate DEFAULT_SAMPLE_RATE = new AirspySampleRate(0, 10000000, "10.00 MHz");
|
||||
private AirspyNativeBufferFactory mNativeBufferFactory = new AirspyNativeBufferFactory();
|
||||
private SampleNativeBufferFactory mNativeBufferFactory = new SampleNativeBufferFactory();
|
||||
private AirspyDeviceInformation mDeviceInfo;
|
||||
private List<AirspySampleRate> mSampleRates = new ArrayList<>();
|
||||
private int mSampleRate = 0;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2024 Dennis Sheirer
|
||||
* Copyright (C) 2014-2025 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
|
||||
@@ -20,7 +20,7 @@
|
||||
package io.github.dsheirer.source.tuner.airspy.hf;
|
||||
|
||||
import io.github.dsheirer.buffer.INativeBufferFactory;
|
||||
import io.github.dsheirer.buffer.airspy.hf.AirspyHfNativeBufferFactory;
|
||||
import io.github.dsheirer.buffer.airspy.AirspyHfNativeBufferFactory;
|
||||
import io.github.dsheirer.source.SourceException;
|
||||
import io.github.dsheirer.source.tuner.ITunerErrorListener;
|
||||
import io.github.dsheirer.source.tuner.TunerType;
|
||||
|
||||
@@ -29,6 +29,7 @@ import io.github.dsheirer.source.tuner.airspy.hf.AirspyHfTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.fcd.proV1.FCD1TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.fcd.proplusV2.FCD2TunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.hackrf.HackRFTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration;
|
||||
import io.github.dsheirer.source.tuner.rtl.fc0013.FC0013TunerConfiguration;
|
||||
@@ -48,6 +49,7 @@ import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration;
|
||||
@JsonSubTypes.Type(value = FCD1TunerConfiguration.class, name = "fcd1TunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = FCD2TunerConfiguration.class, name = "fcd2TunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = HackRFTunerConfiguration.class, name = "hackRFTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = HydraSdrTunerConfiguration.class, name = "hydraSdrTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = RecordingTunerConfiguration.class, name = "recordingTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = R820TTunerConfiguration.class, name = "r820TTunerConfiguration"),
|
||||
@JsonSubTypes.Type(value = R828DTunerConfiguration.class, name = "r828DTunerConfiguration"),
|
||||
|
||||
@@ -0,0 +1,157 @@
|
||||
package io.github.dsheirer.source.tuner.hydrasdr;
|
||||
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import java.util.Arrays;
|
||||
|
||||
public class HydraSdrDeviceInformation
|
||||
{
|
||||
private final static Logger mLog =
|
||||
LoggerFactory.getLogger( HydraSdrDeviceInformation.class );
|
||||
|
||||
private HydraSdrTunerController.BoardID mBoardID = HydraSdrTunerController.BoardID.UNKNOWN;
|
||||
private String mFirmwareVersion = "Unknown";
|
||||
private String mPartNumber = "Unknown";
|
||||
private String mSerialNumber = "Unknown";
|
||||
|
||||
/**
|
||||
* HydraSDR Device Information - provides parsing and access to device
|
||||
* information components.
|
||||
*/
|
||||
public HydraSdrDeviceInformation()
|
||||
{
|
||||
}
|
||||
|
||||
public void setBoardID( int boardID )
|
||||
{
|
||||
mBoardID = HydraSdrTunerController.BoardID.fromValue( boardID );
|
||||
}
|
||||
|
||||
public HydraSdrTunerController.BoardID getBoardID()
|
||||
{
|
||||
return mBoardID;
|
||||
}
|
||||
|
||||
public void setVersion( byte[] data )
|
||||
{
|
||||
if( data != null && data.length > 0 )
|
||||
{
|
||||
/* Truncate the version string if we have a line break - ASCII 10 */
|
||||
for( int x = 0; x < data.length; x++ )
|
||||
{
|
||||
if( data[ x ] == (byte)10 )
|
||||
{
|
||||
mFirmwareVersion = new String( Arrays.copyOf( data, x ) );
|
||||
mFirmwareVersion = mFirmwareVersion.replace( "HydraSDR ", "" );
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
mFirmwareVersion = new String( data );
|
||||
mFirmwareVersion = mFirmwareVersion.replace( "HydraSDR ", "" );
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "Error setting HydraSDR version byte data - null:" +
|
||||
( data == null ? " TRUE" : " FALSE length:" + data.length ) );
|
||||
}
|
||||
}
|
||||
|
||||
public String getVersion()
|
||||
{
|
||||
return mFirmwareVersion;
|
||||
}
|
||||
|
||||
public void setPartAndSerialNumber( byte[] data )
|
||||
{
|
||||
if( data != null && data.length == 24 )
|
||||
{
|
||||
//Note: values are byte-reversed (big-endian) 32-bit chunks
|
||||
StringBuilder part = new StringBuilder();
|
||||
|
||||
part.append( format( data[ 3 ] ) );
|
||||
part.append( format( data[ 2 ] ) );
|
||||
part.append( format( data[ 1 ] ) );
|
||||
part.append( format( data[ 0 ] ) );
|
||||
part.append( format( data[ 7 ] ) );
|
||||
part.append( format( data[ 6 ] ) );
|
||||
part.append( format( data[ 5 ] ) );
|
||||
part.append( format( data[ 4 ] ) );
|
||||
|
||||
mPartNumber = part.toString();
|
||||
|
||||
StringBuilder serial = new StringBuilder();
|
||||
|
||||
//Note: current library only exposes 64-bits of serial number
|
||||
//address space, but appears to have room for 128-bits. We won't
|
||||
//add the first 64 bits if it's zeros
|
||||
if( !( data[ 8 ] == 0 && data[ 9 ] == 0 && data[ 10 ] == 0 && data[ 11 ] == 0 ) )
|
||||
{
|
||||
serial.append( format( data[ 11 ] ) );
|
||||
serial.append( format( data[ 10 ] ) );
|
||||
serial.append( format( data[ 9 ] ) );
|
||||
serial.append( format( data[ 8 ] ) );
|
||||
serial.append( "-" );
|
||||
}
|
||||
|
||||
if( !( data[ 12 ] == 0 && data[ 13 ] == 0 && data[ 14 ] == 0 && data[ 15 ] == 0 ) )
|
||||
{
|
||||
serial.append( format( data[ 15 ] ) );
|
||||
serial.append( format( data[ 14 ] ) );
|
||||
serial.append( format( data[ 13 ] ) );
|
||||
serial.append( format( data[ 12 ] ) );
|
||||
serial.append( "-" );
|
||||
}
|
||||
|
||||
serial.append( format( data[ 19 ] ) );
|
||||
serial.append( format( data[ 18 ] ) );
|
||||
serial.append( format( data[ 17 ] ) );
|
||||
serial.append( format( data[ 16 ] ) );
|
||||
serial.append( "-" );
|
||||
serial.append( format( data[ 23 ] ) );
|
||||
serial.append( format( data[ 22 ] ) );
|
||||
serial.append( format( data[ 21 ] ) );
|
||||
serial.append( format( data[ 20 ] ) );
|
||||
|
||||
mSerialNumber = serial.toString();
|
||||
}
|
||||
else
|
||||
{
|
||||
mLog.error( "Error setting HydraSDR part and serial byte data - null:" +
|
||||
( data == null ? " TRUE" : " FALSE length:" + data.length ) );
|
||||
}
|
||||
}
|
||||
|
||||
private String format( byte value )
|
||||
{
|
||||
return String.format( "%02X", value );
|
||||
}
|
||||
|
||||
public String getSerialNumber()
|
||||
{
|
||||
return mSerialNumber;
|
||||
}
|
||||
|
||||
public String getPartNumber()
|
||||
{
|
||||
return mPartNumber;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
sb.append( "HydraSDR Device Information\n" );
|
||||
sb.append( "Board: " );
|
||||
sb.append( getBoardID().getLabel() );
|
||||
sb.append( "\nPart Number: " );
|
||||
sb.append( getPartNumber() );
|
||||
sb.append( "\nSerial Number: " );
|
||||
sb.append( getSerialNumber() );
|
||||
sb.append( "\nFirmware: " );
|
||||
sb.append( getVersion() );
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,35 @@
|
||||
package io.github.dsheirer.source.tuner.hydrasdr;
|
||||
|
||||
public class HydraSdrSampleRate
|
||||
{
|
||||
private int mIndex;
|
||||
private int mValue;
|
||||
private String mLabel;
|
||||
|
||||
public HydraSdrSampleRate( int index, int value, String label )
|
||||
{
|
||||
mIndex = index;
|
||||
mValue = value;
|
||||
mLabel = label;
|
||||
}
|
||||
|
||||
public int getIndex()
|
||||
{
|
||||
return mIndex;
|
||||
}
|
||||
|
||||
public int getRate()
|
||||
{
|
||||
return mValue;
|
||||
}
|
||||
|
||||
public String getLabel()
|
||||
{
|
||||
return mLabel;
|
||||
}
|
||||
|
||||
public String toString()
|
||||
{
|
||||
return getLabel();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,95 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* Copyright (C) 2014-2022 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.hydrasdr;
|
||||
|
||||
import io.github.dsheirer.preference.source.ChannelizerType;
|
||||
import io.github.dsheirer.source.tuner.ITunerErrorListener;
|
||||
import io.github.dsheirer.source.tuner.Tuner;
|
||||
import io.github.dsheirer.source.tuner.TunerClass;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerController.BoardID;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
/**
|
||||
* HydraSDR Tuner
|
||||
*/
|
||||
public class HydraSdrTuner extends Tuner
|
||||
{
|
||||
private final static Logger mLog = LoggerFactory.getLogger(HydraSdrTuner.class);
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param controller for the HydraSDR
|
||||
* @param tunerErrorListener to listen for errors from this tuner
|
||||
* @param channelizerType for the channelizer
|
||||
*/
|
||||
public HydraSdrTuner(HydraSdrTunerController controller, ITunerErrorListener tunerErrorListener,
|
||||
ChannelizerType channelizerType)
|
||||
{
|
||||
super(controller, tunerErrorListener, channelizerType);
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getPreferredName()
|
||||
{
|
||||
return "HydraSDR " + getController().getDeviceInfo().getSerialNumber();
|
||||
}
|
||||
|
||||
/**
|
||||
* HydraSDR tuner controller
|
||||
*/
|
||||
public HydraSdrTunerController getController()
|
||||
{
|
||||
return (HydraSdrTunerController)getTunerController();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getUniqueID()
|
||||
{
|
||||
try
|
||||
{
|
||||
return getController().getDeviceInfo().getSerialNumber();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("error getting serial number", e);
|
||||
}
|
||||
|
||||
return BoardID.HYDRASDR_RFONE.getLabel();
|
||||
}
|
||||
|
||||
@Override
|
||||
public TunerClass getTunerClass()
|
||||
{
|
||||
return TunerClass.HYDRASDR;
|
||||
}
|
||||
|
||||
@Override
|
||||
public double getSampleSize()
|
||||
{
|
||||
return 13.0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getMaximumUSBBitsPerSecond()
|
||||
{
|
||||
//4-bytes per sample = 32 bits times 10 MSps = 320,000,000 bits per second
|
||||
return 320000000;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,144 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.source.tuner.hydrasdr;
|
||||
|
||||
import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty;
|
||||
import io.github.dsheirer.source.tuner.TunerType;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerController.Gain;
|
||||
import io.github.dsheirer.source.tuner.configuration.TunerConfiguration;
|
||||
|
||||
public class HydraSdrTunerConfiguration extends TunerConfiguration
|
||||
{
|
||||
private Gain mGain = HydraSdrTunerController.LINEARITY_GAIN_DEFAULT;
|
||||
private int mSampleRate = HydraSdrTunerController.DEFAULT_SAMPLE_RATE.getRate();
|
||||
private int mIFGain = HydraSdrTunerController.IF_GAIN_DEFAULT;
|
||||
private int mMixerGain = HydraSdrTunerController.MIXER_GAIN_DEFAULT;
|
||||
private int mLNAGain = HydraSdrTunerController.LNA_GAIN_DEFAULT;
|
||||
private boolean mMixerAGC = false;
|
||||
private boolean mLNAAGC = false;
|
||||
private boolean mBiasT = false;
|
||||
|
||||
/**
|
||||
* Default constructor for JAXB
|
||||
*/
|
||||
public HydraSdrTunerConfiguration()
|
||||
{
|
||||
super(HydraSdrTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ, HydraSdrTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ);
|
||||
}
|
||||
|
||||
@Override
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "type", namespace = "http://www.w3.org/2001/XMLSchema-instance")
|
||||
public TunerType getTunerType()
|
||||
{
|
||||
return TunerType.HYDRASDR_R828D;
|
||||
}
|
||||
|
||||
public HydraSdrTunerConfiguration(String uniqueID)
|
||||
{
|
||||
super(uniqueID);
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "sample_rate")
|
||||
public int getSampleRate()
|
||||
{
|
||||
return mSampleRate;
|
||||
}
|
||||
|
||||
public void setSampleRate(int sampleRate)
|
||||
{
|
||||
mSampleRate = sampleRate;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "gain")
|
||||
public Gain getGain()
|
||||
{
|
||||
return mGain;
|
||||
}
|
||||
|
||||
public void setGain(Gain gain)
|
||||
{
|
||||
mGain = gain;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "if_gain")
|
||||
public int getIFGain()
|
||||
{
|
||||
return mIFGain;
|
||||
}
|
||||
|
||||
public void setIFGain(int gain)
|
||||
{
|
||||
mIFGain = gain;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "mixer_gain")
|
||||
public int getMixerGain()
|
||||
{
|
||||
return mMixerGain;
|
||||
}
|
||||
|
||||
public void setMixerGain(int gain)
|
||||
{
|
||||
mMixerGain = gain;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "lna_gain")
|
||||
public int getLNAGain()
|
||||
{
|
||||
return mLNAGain;
|
||||
}
|
||||
|
||||
public void setLNAGain(int gain)
|
||||
{
|
||||
mLNAGain = gain;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "mixer_agc")
|
||||
public boolean isMixerAGC()
|
||||
{
|
||||
return mMixerAGC;
|
||||
}
|
||||
|
||||
public void setMixerAGC(boolean enabled)
|
||||
{
|
||||
mMixerAGC = enabled;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "lna_agc")
|
||||
public boolean isLNAAGC()
|
||||
{
|
||||
return mLNAAGC;
|
||||
}
|
||||
|
||||
public void setLNAAGC(boolean enabled)
|
||||
{
|
||||
mLNAAGC = enabled;
|
||||
}
|
||||
|
||||
@JacksonXmlProperty(isAttribute = true, localName = "bias_t")
|
||||
public boolean isBiasT()
|
||||
{
|
||||
return mBiasT;
|
||||
}
|
||||
|
||||
public void setBiasT(boolean enabled)
|
||||
{
|
||||
mBiasT = enabled;
|
||||
}
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,742 @@
|
||||
/*
|
||||
* *****************************************************************************
|
||||
* 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 <http://www.gnu.org/licenses/>
|
||||
* ****************************************************************************
|
||||
*/
|
||||
package io.github.dsheirer.source.tuner.hydrasdr;
|
||||
|
||||
import io.github.dsheirer.preference.UserPreferences;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerController.Gain;
|
||||
import io.github.dsheirer.source.tuner.hydrasdr.HydraSdrTunerController.GainMode;
|
||||
import io.github.dsheirer.source.tuner.manager.DiscoveredTuner;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerManager;
|
||||
import io.github.dsheirer.source.tuner.manager.TunerStatus;
|
||||
import io.github.dsheirer.source.tuner.ui.TunerEditor;
|
||||
import java.awt.event.ActionEvent;
|
||||
import java.awt.event.ActionListener;
|
||||
import java.util.List;
|
||||
import net.miginfocom.swing.MigLayout;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
|
||||
import javax.swing.DefaultComboBoxModel;
|
||||
import javax.swing.JButton;
|
||||
import javax.swing.JCheckBox;
|
||||
import javax.swing.JComboBox;
|
||||
import javax.swing.JLabel;
|
||||
import javax.swing.JOptionPane;
|
||||
import javax.swing.JSeparator;
|
||||
import javax.swing.JSlider;
|
||||
import javax.swing.SpinnerNumberModel;
|
||||
import javax.swing.event.ChangeEvent;
|
||||
import javax.swing.event.ChangeListener;
|
||||
|
||||
/**
|
||||
* HydraSDR tuner editor/controller
|
||||
*/
|
||||
public class HydraSdrTunerEditor extends TunerEditor<HydraSdrTuner, HydraSdrTunerConfiguration>
|
||||
{
|
||||
private static final long serialVersionUID = 1L;
|
||||
private final static Logger mLog = LoggerFactory.getLogger(HydraSdrTunerEditor.class);
|
||||
private JButton mTunerInfoButton;
|
||||
private JComboBox<HydraSdrSampleRate> mSampleRateCombo;
|
||||
private JComboBox<GainMode> mGainModeCombo;
|
||||
private JSlider mMasterGainSlider;
|
||||
private JLabel mMasterGainLabel;
|
||||
private JLabel mMasterGainValueLabel;
|
||||
private JSlider mIFGainSlider;
|
||||
private JLabel mIFGainLabel;
|
||||
private JLabel mIFGainValueLabel;
|
||||
private JSlider mLNAGainSlider;
|
||||
private JLabel mLNAGainValueLabel;
|
||||
private JSlider mMixerGainSlider;
|
||||
private JLabel mMixerGainValueLabel;
|
||||
private JCheckBox mLNAAGCCheckBox;
|
||||
private JCheckBox mMixerAGCCheckBox;
|
||||
private JCheckBox mBiasTCheckBox;
|
||||
|
||||
/**
|
||||
* Constructs an instance
|
||||
* @param userPreferences for wide-band recordings
|
||||
* @param tunerManager for saving tuner configuration
|
||||
* @param discoveredTuner for the optionally usable HydraSDR tuner and controller
|
||||
*/
|
||||
public HydraSdrTunerEditor(UserPreferences userPreferences, TunerManager tunerManager, DiscoveredTuner discoveredTuner)
|
||||
{
|
||||
super(userPreferences, tunerManager, discoveredTuner);
|
||||
init();
|
||||
tunerStatusUpdated();
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMinimumTunableFrequency()
|
||||
{
|
||||
return HydraSdrTunerController.MINIMUM_TUNABLE_FREQUENCY_HZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getMaximumTunableFrequency()
|
||||
{
|
||||
return HydraSdrTunerController.MAXIMUM_TUNABLE_FREQUENCY_HZ;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void tunerStatusUpdated()
|
||||
{
|
||||
setLoading(true);
|
||||
|
||||
if(hasTuner())
|
||||
{
|
||||
getTunerIdLabel().setText(getTuner().getPreferredName());
|
||||
}
|
||||
else
|
||||
{
|
||||
getTunerIdLabel().setText(getDiscoveredTuner().getId());
|
||||
}
|
||||
|
||||
String status = getDiscoveredTuner().getTunerStatus().toString();
|
||||
if(getDiscoveredTuner().hasErrorMessage())
|
||||
{
|
||||
status += " - " + getDiscoveredTuner().getErrorMessage();
|
||||
}
|
||||
getTunerStatusLabel().setText(status);
|
||||
getButtonPanel().updateControls();
|
||||
getFrequencyPanel().updateControls();
|
||||
getSampleRateCombo().setEnabled(hasTuner() && !getTuner().getTunerController().isLockedSampleRate());
|
||||
getTunerInfoButton().setEnabled(hasTuner());
|
||||
getBiasTCheckBox().setEnabled(hasTuner());
|
||||
if(hasTuner() && hasConfiguration())
|
||||
{
|
||||
getBiasTCheckBox().setSelected(getConfiguration().isBiasT());
|
||||
}
|
||||
updateGainComponents((hasTuner() && hasConfiguration()) ? getConfiguration().getGain() : null);
|
||||
|
||||
if(hasTuner())
|
||||
{
|
||||
List<HydraSdrSampleRate> rates = getTuner().getController().getSampleRates();
|
||||
getSampleRateCombo().setModel(new DefaultComboBoxModel<>(rates.toArray(new HydraSdrSampleRate[rates.size()])));
|
||||
|
||||
if(hasConfiguration())
|
||||
{
|
||||
HydraSdrSampleRate sampleRate = getSampleRate(getConfiguration().getSampleRate());
|
||||
getSampleRateCombo().setSelectedItem(sampleRate);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getSampleRateCombo().setModel(new DefaultComboBoxModel<>());
|
||||
}
|
||||
|
||||
setLoading(false);
|
||||
}
|
||||
|
||||
private void init()
|
||||
{
|
||||
setLayout(new MigLayout("fill,wrap 3", "[right][grow,fill][fill]",
|
||||
"[][][][][][][][][][][][][][][][grow]"));
|
||||
|
||||
add(new JLabel("Tuner:"));
|
||||
add(getTunerIdLabel());
|
||||
add(getTunerInfoButton());
|
||||
|
||||
add(new JLabel("Status:"));
|
||||
add(getTunerStatusLabel(), "wrap");
|
||||
|
||||
add(getButtonPanel(), "span,align left");
|
||||
|
||||
add(new JSeparator(), "span,growx,push");
|
||||
|
||||
add(new JLabel("Frequency (MHz):"));
|
||||
add(getFrequencyPanel(), "wrap");
|
||||
|
||||
add(new JLabel("Sample Rate:"));
|
||||
add(getSampleRateCombo(), "wrap");
|
||||
|
||||
add(new JLabel());
|
||||
add(getBiasTCheckBox(), "wrap");
|
||||
|
||||
add(new JSeparator(), "span,growx,push");
|
||||
add(new JLabel("Gain Control"), "wrap");
|
||||
|
||||
add(new JLabel("Mode:"));
|
||||
add(getGainModeCombo(), "wrap");
|
||||
|
||||
add(getMasterGainLabel());
|
||||
add(getMasterGainSlider());
|
||||
add(getMasterGainValueLabel());
|
||||
|
||||
add(getIFGainLabel());
|
||||
add(getIFGainSlider());
|
||||
add(getIFGainValueLabel());
|
||||
|
||||
add(getMixerAGCCheckBox());
|
||||
add(getMixerGainSlider());
|
||||
add(getMixerGainValueLabel());
|
||||
|
||||
add(getLNAAGCCheckBox());
|
||||
add(getLNAGainSlider());
|
||||
add(getLNAGainValueLabel());
|
||||
}
|
||||
|
||||
private JCheckBox getLNAAGCCheckBox()
|
||||
{
|
||||
if(mLNAAGCCheckBox == null)
|
||||
{
|
||||
mLNAAGCCheckBox = new JCheckBox("AGC LNA:");
|
||||
mLNAAGCCheckBox.setEnabled(false);
|
||||
mLNAAGCCheckBox.addActionListener(e ->
|
||||
{
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTuner().getController().setLNAAGC(getLNAAGCCheckBox().isSelected());
|
||||
getLNAGainSlider().setEnabled(!getLNAAGCCheckBox().isSelected());
|
||||
save();
|
||||
}
|
||||
catch(Exception e1)
|
||||
{
|
||||
mLog.error("Error setting LNA AGC Enabled");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mLNAAGCCheckBox;
|
||||
}
|
||||
|
||||
private JCheckBox getMixerAGCCheckBox()
|
||||
{
|
||||
if(mMixerAGCCheckBox == null)
|
||||
{
|
||||
mMixerAGCCheckBox = new JCheckBox("AGC Mixer:");
|
||||
mMixerAGCCheckBox.setEnabled(false);
|
||||
mMixerAGCCheckBox.addActionListener(e ->
|
||||
{
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTuner().getController().setMixerAGC(getMixerAGCCheckBox().isSelected());
|
||||
getMixerGainSlider().setEnabled(!getMixerAGCCheckBox().isSelected());
|
||||
save();
|
||||
}
|
||||
catch(Exception e1)
|
||||
{
|
||||
mLog.error("Error setting Mixer AGC Enabled");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mMixerAGCCheckBox;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checkbox to enable/disable Bias-T power for active antennas
|
||||
*/
|
||||
private JCheckBox getBiasTCheckBox()
|
||||
{
|
||||
if(mBiasTCheckBox == null)
|
||||
{
|
||||
mBiasTCheckBox = new JCheckBox("Bias-T");
|
||||
mBiasTCheckBox.setEnabled(false);
|
||||
mBiasTCheckBox.setToolTipText("Enable Bias-T power output for active antennas");
|
||||
mBiasTCheckBox.addActionListener(e ->
|
||||
{
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTuner().getController().setBiasT(mBiasTCheckBox.isSelected());
|
||||
save();
|
||||
}
|
||||
catch(Exception e1)
|
||||
{
|
||||
mLog.error("Error setting Bias-T", e1);
|
||||
JOptionPane.showMessageDialog(mBiasTCheckBox, "Couldn't set Bias-T: " + e1.getMessage());
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mBiasTCheckBox;
|
||||
}
|
||||
|
||||
private JLabel getLNAGainValueLabel()
|
||||
{
|
||||
if(mLNAGainValueLabel == null)
|
||||
{
|
||||
mLNAGainValueLabel = new JLabel("0");
|
||||
mLNAGainValueLabel.setEnabled(false);
|
||||
}
|
||||
|
||||
return mLNAGainValueLabel;
|
||||
}
|
||||
|
||||
private JSlider getLNAGainSlider()
|
||||
{
|
||||
if(mLNAGainSlider == null)
|
||||
{
|
||||
mLNAGainSlider = new JSlider(JSlider.HORIZONTAL, HydraSdrTunerController.LNA_GAIN_MIN,
|
||||
HydraSdrTunerController.LNA_GAIN_MAX, HydraSdrTunerController.LNA_GAIN_MIN);
|
||||
mLNAGainSlider.setEnabled(false);
|
||||
mLNAGainSlider.setMajorTickSpacing(1);
|
||||
mLNAGainSlider.setPaintTicks(true);
|
||||
mLNAGainSlider.addChangeListener(event ->
|
||||
{
|
||||
int gain = mLNAGainSlider.getValue();
|
||||
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTuner().getController().setLNAGain(gain);
|
||||
save();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't set HydraSDR LNA gain to:" + gain, e);
|
||||
JOptionPane.showMessageDialog(mLNAGainSlider, "Couldn't set LNA gain value to " + gain);
|
||||
}
|
||||
}
|
||||
|
||||
getLNAGainValueLabel().setText(String.valueOf(gain));
|
||||
});
|
||||
}
|
||||
|
||||
return mLNAGainSlider;
|
||||
}
|
||||
|
||||
private JLabel getMixerGainValueLabel()
|
||||
{
|
||||
if(mMixerGainValueLabel == null)
|
||||
{
|
||||
mMixerGainValueLabel = new JLabel("0");
|
||||
mMixerGainValueLabel.setEnabled(false);
|
||||
}
|
||||
|
||||
return mMixerGainValueLabel;
|
||||
}
|
||||
|
||||
private JSlider getMixerGainSlider()
|
||||
{
|
||||
if(mMixerGainSlider == null)
|
||||
{
|
||||
mMixerGainSlider = new JSlider(JSlider.HORIZONTAL, HydraSdrTunerController.MIXER_GAIN_MIN,
|
||||
HydraSdrTunerController.MIXER_GAIN_MAX, HydraSdrTunerController.MIXER_GAIN_MIN);
|
||||
mMixerGainSlider.setEnabled(false);
|
||||
mMixerGainSlider.setMajorTickSpacing(1);
|
||||
mMixerGainSlider.setPaintTicks(true);
|
||||
mMixerGainSlider.addChangeListener(new ChangeListener()
|
||||
{
|
||||
@Override
|
||||
public void stateChanged(ChangeEvent event)
|
||||
{
|
||||
int gain = mMixerGainSlider.getValue();
|
||||
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTuner().getController().setMixerGain(gain);
|
||||
save();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't set HydraSDR Mixer gain to:" + gain, e);
|
||||
JOptionPane.showMessageDialog(mMixerGainSlider, "Couldn't set Mixer gain value to " + gain);
|
||||
}
|
||||
}
|
||||
|
||||
getMixerGainValueLabel().setText(String.valueOf(gain));
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mMixerGainSlider;
|
||||
}
|
||||
|
||||
private JLabel getIFGainLabel()
|
||||
{
|
||||
if(mIFGainLabel == null)
|
||||
{
|
||||
mIFGainLabel = new JLabel("IF:");
|
||||
}
|
||||
|
||||
return mIFGainLabel;
|
||||
}
|
||||
|
||||
private JLabel getIFGainValueLabel()
|
||||
{
|
||||
if(mIFGainValueLabel == null)
|
||||
{
|
||||
mIFGainValueLabel = new JLabel("0");
|
||||
mIFGainValueLabel.setEnabled(false);
|
||||
}
|
||||
|
||||
return mIFGainValueLabel;
|
||||
}
|
||||
|
||||
private JSlider getIFGainSlider()
|
||||
{
|
||||
if(mIFGainSlider == null)
|
||||
{
|
||||
mIFGainSlider = new JSlider(JSlider.HORIZONTAL, HydraSdrTunerController.IF_GAIN_MIN,
|
||||
HydraSdrTunerController.IF_GAIN_MAX, HydraSdrTunerController.IF_GAIN_MIN);
|
||||
mIFGainSlider.setEnabled(false);
|
||||
mIFGainSlider.setMajorTickSpacing(1);
|
||||
mIFGainSlider.setPaintTicks(true);
|
||||
mIFGainSlider.addChangeListener(event ->
|
||||
{
|
||||
int gain = mIFGainSlider.getValue();
|
||||
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTuner().getController().setIFGain(gain);
|
||||
save();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't set HydraSDR IF gain to:" + gain, e);
|
||||
JOptionPane.showMessageDialog(mIFGainSlider, "Couldn't set IF gain value to " + gain);
|
||||
}
|
||||
}
|
||||
|
||||
getIFGainValueLabel().setText(String.valueOf(gain));
|
||||
});
|
||||
}
|
||||
|
||||
return mIFGainSlider;
|
||||
}
|
||||
|
||||
private JLabel getMasterGainLabel()
|
||||
{
|
||||
if(mMasterGainLabel == null)
|
||||
{
|
||||
mMasterGainLabel = new JLabel("Master:");
|
||||
}
|
||||
|
||||
return mMasterGainLabel;
|
||||
}
|
||||
|
||||
private JLabel getMasterGainValueLabel()
|
||||
{
|
||||
if(mMasterGainValueLabel == null)
|
||||
{
|
||||
mMasterGainValueLabel = new JLabel("0");
|
||||
mMasterGainValueLabel.setEnabled(false);
|
||||
}
|
||||
|
||||
return mMasterGainValueLabel;
|
||||
}
|
||||
|
||||
private JSlider getMasterGainSlider()
|
||||
{
|
||||
if(mMasterGainSlider == null)
|
||||
{
|
||||
mMasterGainSlider = new JSlider(JSlider.HORIZONTAL, HydraSdrTunerController.GAIN_MIN,
|
||||
HydraSdrTunerController.GAIN_MAX, HydraSdrTunerController.GAIN_MIN);
|
||||
mMasterGainSlider.setEnabled(false);
|
||||
mMasterGainSlider.setMajorTickSpacing(1);
|
||||
mMasterGainSlider.setPaintTicks(true);
|
||||
|
||||
mMasterGainSlider.addChangeListener(event ->
|
||||
{
|
||||
GainMode mode = (GainMode)mGainModeCombo.getSelectedItem();
|
||||
int value = mMasterGainSlider.getValue();
|
||||
Gain gain = Gain.getGain(mode, value);
|
||||
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
try
|
||||
{
|
||||
getTuner().getController().setGain(gain);
|
||||
save();
|
||||
}
|
||||
catch(Exception e)
|
||||
{
|
||||
mLog.error("Couldn't set HydraSDR gain to:" + gain.name(), e);
|
||||
JOptionPane.showMessageDialog(mMasterGainSlider, "Couldn't set gain value to " +
|
||||
gain.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
getMasterGainValueLabel().setText(String.valueOf(value));
|
||||
});
|
||||
}
|
||||
|
||||
return mMasterGainSlider;
|
||||
}
|
||||
|
||||
private JComboBox<GainMode> getGainModeCombo()
|
||||
{
|
||||
if(mGainModeCombo == null)
|
||||
{
|
||||
mGainModeCombo = new JComboBox<>(GainMode.values());
|
||||
mGainModeCombo.setEnabled(false);
|
||||
mGainModeCombo.addActionListener(e ->
|
||||
{
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
GainMode mode = (GainMode)mGainModeCombo.getSelectedItem();
|
||||
int value = getMasterGainSlider().getValue();
|
||||
Gain gain = Gain.getGain(mode, value);
|
||||
updateGainComponents(gain);
|
||||
save();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mGainModeCombo;
|
||||
}
|
||||
|
||||
private JComboBox<HydraSdrSampleRate> getSampleRateCombo()
|
||||
{
|
||||
if(mSampleRateCombo == null)
|
||||
{
|
||||
mSampleRateCombo = new JComboBox<>();
|
||||
mSampleRateCombo.setEnabled(false);
|
||||
mSampleRateCombo.addActionListener(new ActionListener()
|
||||
{
|
||||
@Override
|
||||
public void actionPerformed(ActionEvent e)
|
||||
{
|
||||
if(hasTuner() && !isLoading())
|
||||
{
|
||||
HydraSdrSampleRate rate = (HydraSdrSampleRate)mSampleRateCombo.getSelectedItem();
|
||||
|
||||
try
|
||||
{
|
||||
getTuner().getController().setSampleRate(rate);
|
||||
|
||||
//Adjust the min/max values for the sample rate.
|
||||
adjustForSampleRate(rate.getRate());
|
||||
|
||||
save();
|
||||
}
|
||||
catch(Exception e1)
|
||||
{
|
||||
JOptionPane.showMessageDialog(HydraSdrTunerEditor.this,
|
||||
"Couldn't set sample rate to " + rate.getLabel());
|
||||
mLog.error("Error setting HydraSDR sample rate", e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return mSampleRateCombo;
|
||||
}
|
||||
|
||||
/**
|
||||
* Hyperlink button that provides tuner information
|
||||
*/
|
||||
private JButton getTunerInfoButton()
|
||||
{
|
||||
if(mTunerInfoButton == null)
|
||||
{
|
||||
mTunerInfoButton = new JButton("Info");
|
||||
mTunerInfoButton.setEnabled(false);
|
||||
mTunerInfoButton.addActionListener(e -> JOptionPane.showMessageDialog(HydraSdrTunerEditor.this,
|
||||
getTunerInfo(), "Tuner Info", JOptionPane.INFORMATION_MESSAGE));
|
||||
}
|
||||
|
||||
return mTunerInfoButton;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the enabled state of each of the gain controls according to the
|
||||
* specified gain mode. The master gain control is enabled for linearity
|
||||
* and sensitivity and the individual gain controls are disabled, and
|
||||
* vice-versa for custom mode.
|
||||
*/
|
||||
private void updateGainComponents(Gain gain)
|
||||
{
|
||||
if(hasTuner() && gain != null)
|
||||
{
|
||||
boolean isCustom = gain.equals(Gain.CUSTOM);
|
||||
|
||||
getGainModeCombo().setEnabled(true);
|
||||
getGainModeCombo().setSelectedItem(gain.getGainMode());
|
||||
getMasterGainLabel().setEnabled(!isCustom);
|
||||
getMasterGainSlider().setEnabled(!isCustom);
|
||||
getMasterGainSlider().setValue(gain.getValue());
|
||||
getMasterGainValueLabel().setEnabled(!isCustom);
|
||||
getIFGainLabel().setEnabled(isCustom);
|
||||
getIFGainSlider().setEnabled(isCustom);
|
||||
getIFGainValueLabel().setEnabled(isCustom);
|
||||
getLNAAGCCheckBox().setEnabled(isCustom);
|
||||
getLNAGainSlider().setEnabled(isCustom && !getConfiguration().isLNAAGC());
|
||||
getLNAGainValueLabel().setEnabled(isCustom);
|
||||
getMixerAGCCheckBox().setEnabled(isCustom);
|
||||
getMixerGainSlider().setEnabled(isCustom && !getConfiguration().isMixerAGC());
|
||||
getMixerGainValueLabel().setEnabled(isCustom);
|
||||
if(isCustom)
|
||||
{
|
||||
getIFGainSlider().setValue(getConfiguration().getIFGain());
|
||||
getLNAGainSlider().setValue(getConfiguration().getLNAGain());
|
||||
getMixerGainSlider().setValue(getConfiguration().getMixerGain());
|
||||
getMixerAGCCheckBox().setSelected(getConfiguration().isMixerAGC());
|
||||
getLNAAGCCheckBox().setSelected(getConfiguration().isLNAAGC());
|
||||
}
|
||||
else
|
||||
{
|
||||
getIFGainSlider().setValue(0);
|
||||
getLNAGainSlider().setValue(0);
|
||||
getMixerGainSlider().setValue(0);
|
||||
getMixerAGCCheckBox().setSelected(false);
|
||||
getLNAAGCCheckBox().setSelected(false);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
getGainModeCombo().setEnabled(false);
|
||||
getMasterGainLabel().setEnabled(false);
|
||||
getMasterGainSlider().setEnabled(false);
|
||||
getMasterGainSlider().setValue(0);
|
||||
getMasterGainValueLabel().setEnabled(false);
|
||||
getIFGainLabel().setEnabled(false);
|
||||
getIFGainSlider().setEnabled(false);
|
||||
getIFGainSlider().setValue(0);
|
||||
getIFGainValueLabel().setEnabled(false);
|
||||
getLNAAGCCheckBox().setEnabled(false);
|
||||
getLNAAGCCheckBox().setSelected(false);
|
||||
getLNAGainSlider().setEnabled(false);
|
||||
getLNAGainSlider().setValue(0);
|
||||
getLNAGainValueLabel().setEnabled(false);
|
||||
getMixerAGCCheckBox().setEnabled(false);
|
||||
getMixerAGCCheckBox().setSelected(false);
|
||||
getMixerGainSlider().setEnabled(false);
|
||||
getMixerGainSlider().setValue(0);
|
||||
getMixerGainValueLabel().setEnabled(false);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
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());
|
||||
getConfiguration().setSampleRate(((HydraSdrSampleRate)getSampleRateCombo().getSelectedItem()).getRate());
|
||||
Gain gain = Gain.getGain((GainMode)mGainModeCombo.getSelectedItem(), getMasterGainSlider().getValue());
|
||||
getConfiguration().setGain(gain);
|
||||
getConfiguration().setIFGain(getIFGainSlider().getValue());
|
||||
getConfiguration().setMixerGain(getMixerGainSlider().getValue());
|
||||
getConfiguration().setLNAGain(getLNAGainSlider().getValue());
|
||||
getConfiguration().setMixerAGC(getMixerAGCCheckBox().isSelected());
|
||||
getConfiguration().setLNAAGC(getLNAAGCCheckBox().isSelected());
|
||||
getConfiguration().setBiasT(getBiasTCheckBox().isSelected());
|
||||
saveConfiguration();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Finds the HydraSDR sample rate entry that matches the value.
|
||||
* @param value in Hertz
|
||||
* @return the matching rate entry or null.
|
||||
*/
|
||||
private HydraSdrSampleRate getSampleRate(int value)
|
||||
{
|
||||
if(hasTuner())
|
||||
{
|
||||
List<HydraSdrSampleRate> rates = getTuner().getController().getSampleRates();
|
||||
|
||||
for(HydraSdrSampleRate rate : rates)
|
||||
{
|
||||
if(rate.getRate() == value)
|
||||
{
|
||||
return rate;
|
||||
}
|
||||
}
|
||||
|
||||
if(rates.size() > 0)
|
||||
{
|
||||
return rates.get(0);
|
||||
}
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Updates the sample rate tooltip according to the tuner controller's lock state.
|
||||
*/
|
||||
private void updateSampleRateToolTip()
|
||||
{
|
||||
if(hasTuner() && getTuner().getController().isLockedSampleRate())
|
||||
{
|
||||
getSampleRateCombo().setToolTipText("Sample Rate is locked. Disable decoding channels to unlock.");
|
||||
}
|
||||
else
|
||||
{
|
||||
getSampleRateCombo().setToolTipText("Select a sample rate for the tuner");
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setTunerLockState(boolean locked)
|
||||
{
|
||||
getFrequencyPanel().updateControls();
|
||||
getSampleRateCombo().setEnabled(!locked);
|
||||
updateSampleRateToolTip();
|
||||
}
|
||||
|
||||
private String getTunerInfo()
|
||||
{
|
||||
if(getDiscoveredTuner().getTunerStatus() == TunerStatus.ERROR)
|
||||
{
|
||||
return getDiscoveredTuner().getErrorMessage();
|
||||
}
|
||||
|
||||
if(hasTuner())
|
||||
{
|
||||
StringBuilder sb = new StringBuilder();
|
||||
|
||||
HydraSdrDeviceInformation info = getTuner().getController().getDeviceInfo();
|
||||
|
||||
sb.append("<html><h3>HydraSDR Tuner</h3>");
|
||||
sb.append("<b>Serial: </b>");
|
||||
sb.append(info.getSerialNumber());
|
||||
sb.append("<br>");
|
||||
|
||||
sb.append("<b>Firmware: </b>");
|
||||
String[] firmware = info.getVersion().split(" ");
|
||||
sb.append(firmware.length > 1 ? firmware[0] : info.getVersion());
|
||||
sb.append("<br>");
|
||||
|
||||
sb.append("<b>Part: </b>");
|
||||
sb.append(info.getPartNumber());
|
||||
sb.append("<br>");
|
||||
|
||||
sb.append("<b>Board ID: </b>");
|
||||
sb.append(info.getBoardID().getLabel());
|
||||
sb.append("<br>");
|
||||
|
||||
return sb.toString();
|
||||
}
|
||||
|
||||
return null;
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user