diff --git a/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java b/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java index d5ae5674c..df4b8062a 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java +++ b/src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java @@ -55,9 +55,11 @@ import io.github.dsheirer.source.tuner.rtl.e4k.E4KEmbeddedTuner; import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration; import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerEditor; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TEmbeddedTuner; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerEditor; +import io.github.dsheirer.source.tuner.rtl.r8x.R8xTunerEditor; +import io.github.dsheirer.source.tuner.rtl.r8x.r820t.R820TEmbeddedTuner; +import io.github.dsheirer.source.tuner.rtl.r8x.r820t.R820TTunerConfiguration; +import io.github.dsheirer.source.tuner.rtl.r8x.r828d.R828DEmbeddedTuner; +import io.github.dsheirer.source.tuner.rtl.r8x.r828d.R828DTunerConfiguration; import io.github.dsheirer.source.tuner.sdrplay.DiscoveredRspTuner; import io.github.dsheirer.source.tuner.sdrplay.RspTuner; import io.github.dsheirer.source.tuner.sdrplay.api.DeviceSelectionMode; @@ -367,7 +369,8 @@ public static EmbeddedTuner getRtlEmbeddedTuner(TunerType tunerType, { case ELONICS_E4000 -> new E4KEmbeddedTuner(adapter); case RAFAELMICRO_R820T -> new R820TEmbeddedTuner(adapter); - default -> throw new SourceException("Unsupported/Unrecognized Tuner Type"); + case RAFAELMICRO_R828D -> new R828DEmbeddedTuner(adapter); + default -> throw new SourceException("Unsupported/Unrecognized Tuner Type: " + tunerType); }; } @@ -394,6 +397,8 @@ public static TunerConfiguration getTunerConfiguration(TunerType type, String un return new HackRFTunerConfiguration(uniqueID); case RAFAELMICRO_R820T: return new R820TTunerConfiguration(uniqueID); + case RAFAELMICRO_R828D: + return new R828DTunerConfiguration(uniqueID); case RECORDING: return RecordingTunerConfiguration.create(); case RSP_1: @@ -475,7 +480,8 @@ else if(discoveredRspTuner instanceof DiscoveredRspDuoTuner2 duoTuner2) case ELONICS_E4000: return new E4KTunerEditor(userPreferences, tunerManager, discoveredTuner); case RAFAELMICRO_R820T: - return new R820TTunerEditor(userPreferences, tunerManager, discoveredTuner); + case RAFAELMICRO_R828D: + return new R8xTunerEditor(userPreferences, tunerManager, discoveredTuner); } } return new RTL2832UnknownTunerEditor(userPreferences, tunerManager, discoveredTuner); 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 d45c2ddf9..6de3ee44e 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-2022 Dennis Sheirer + * 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 @@ -31,7 +31,8 @@ import io.github.dsheirer.source.tuner.hackrf.HackRFTunerConfiguration; import io.github.dsheirer.source.tuner.recording.RecordingTunerConfiguration; import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration; +import io.github.dsheirer.source.tuner.rtl.r8x.r820t.R820TTunerConfiguration; +import io.github.dsheirer.source.tuner.rtl.r8x.r828d.R828DTunerConfiguration; import io.github.dsheirer.source.tuner.sdrplay.RspTunerConfiguration; /** @@ -47,6 +48,7 @@ @JsonSubTypes.Type(value = HackRFTunerConfiguration.class, name = "hackRFTunerConfiguration"), @JsonSubTypes.Type(value = RecordingTunerConfiguration.class, name = "recordingTunerConfiguration"), @JsonSubTypes.Type(value = R820TTunerConfiguration.class, name = "r820TTunerConfiguration"), + @JsonSubTypes.Type(value = R828DTunerConfiguration.class, name = "r828DTunerConfiguration"), @JsonSubTypes.Type(value = RspTunerConfiguration.class, name = "rspTunerConfiguration"), }) @JacksonXmlRootElement(localName = "tuner_configuration") 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 d5025ff11..8141240f5 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-2022 Dennis Sheirer + * 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 @@ -24,7 +24,8 @@ import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlRootElement; import io.github.dsheirer.source.tuner.configuration.TunerConfiguration; import io.github.dsheirer.source.tuner.rtl.e4k.E4KTunerConfiguration; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TTunerConfiguration; +import io.github.dsheirer.source.tuner.rtl.r8x.r820t.R820TTunerConfiguration; +import io.github.dsheirer.source.tuner.rtl.r8x.r828d.R828DTunerConfiguration; /** * RTL2832 tuner configuration @@ -33,11 +34,13 @@ @JsonSubTypes({ @JsonSubTypes.Type(value = E4KTunerConfiguration.class, name = "e4KTunerConfiguration"), @JsonSubTypes.Type(value = R820TTunerConfiguration.class, name = "r820TTunerConfiguration"), + @JsonSubTypes.Type(value = R828DTunerConfiguration.class, name = "r828DTunerConfiguration"), }) @JacksonXmlRootElement(localName = "tuner_configuration") public abstract class RTL2832TunerConfiguration extends TunerConfiguration { private RTL2832TunerController.SampleRate mSampleRate = RTL2832TunerController.SampleRate.RATE_2_400MHZ; + private boolean mBiasTEnabled = false; /** * Default constructor to support Jackson @@ -61,4 +64,23 @@ public void setSampleRate(RTL2832TunerController.SampleRate sampleRate) { mSampleRate = sampleRate; } + + /** + * Sets the enabled state of the Bias-T + * @param enabled true to turn-on the bias-T + */ + public void setBiasT(boolean enabled) + { + mBiasTEnabled = enabled; + } + + /** + * Indicates if the Bias-T is enabled. + * @return true if enabled. + */ + @JacksonXmlProperty(isAttribute = true, localName = "bias_t") + public boolean isBiasT() + { + return mBiasTEnabled; + } } diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java index 876ae8a3b..3c4951799 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/RTL2832TunerController.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer + * 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 @@ -66,6 +66,7 @@ public class RTL2832TunerController extends USBTunerController private Descriptor mDescriptor; private EmbeddedTuner mEmbeddedTuner; private long mTunedFrequency = 0; + private boolean mBiasTEnabled = false; private ReentrantLock mLock = new ReentrantLock(); /** @@ -174,7 +175,7 @@ protected void deviceStart() throws SourceException try { - writeRegister(Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1); + writeRegister(Block.USB, Address.USB_SYSCTL, 0x09, 1); } catch(LibUsbException lue) { @@ -195,7 +196,7 @@ protected void deviceStart() throws SourceException try { - writeRegister(Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1); + writeRegister(Block.USB, Address.USB_SYSCTL, 0x09, 1); } catch(LibUsbException lue) { @@ -238,7 +239,7 @@ protected void deviceStart() throws SourceException if(tunerType == TunerType.UNKNOWN) { - throw new SourceException("Unrecognized embedded tuner type for RTL-2832"); + throw new SourceException("Unrecognized RTL-2832 embedded tuner type: " + tunerType); } mEmbeddedTuner = TunerFactory.getRtlEmbeddedTuner(tunerType, new ControllerAdapter(this)); @@ -299,6 +300,26 @@ public Descriptor getDescriptor() return null; } + /** + * Sets the enabled state of the bias-t + * @param enabled true to turn-on the bias-t or false to turn-off the bias-t. + */ + public void setBiasT(boolean enabled) + { + setGPIOOutput((byte)0x01); + setGPIOBit((byte)0x01, enabled); + mBiasTEnabled = enabled; + } + + /** + * Indicates if the bias-t is enabled. + * @return true if enabled. + */ + public boolean isBiasT() + { + return mBiasTEnabled; + } + /** * Overrides updates for measured frequency error so that the updates can also be applied to the * frequency error correction manager for automatic PPM updating. @@ -437,8 +458,8 @@ protected void prepareStreaming() */ public void resetUSBBuffer() throws LibUsbException { - writeRegister(Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2); - writeRegister(Block.USB, Address.USB_EPA_CTL.getAddress(), 0x0000, 2); + writeRegister(Block.USB, Address.USB_EPA_CTL, 0x1002, 2); + writeRegister(Block.USB, Address.USB_EPA_CTL, 0x0000, 2); } /** @@ -448,13 +469,13 @@ public void resetUSBBuffer() throws LibUsbException public void initBaseband() throws LibUsbException { /* Initialize USB */ - writeRegister(Block.USB, Address.USB_SYSCTL.getAddress(), 0x09, 1); - writeRegister(Block.USB, Address.USB_EPA_MAXPKT.getAddress(), 0x0002, 2); - writeRegister(Block.USB, Address.USB_EPA_CTL.getAddress(), 0x1002, 2); + writeRegister(Block.USB, Address.USB_SYSCTL, 0x09, 1); + writeRegister(Block.USB, Address.USB_EPA_MAXPKT, 0x0002, 2); + writeRegister(Block.USB, Address.USB_EPA_CTL, 0x1002, 2); /* Power on demod */ - writeRegister(Block.SYS, Address.DEMOD_CTL_1.getAddress(), 0x22, 1); - writeRegister(Block.SYS, Address.DEMOD_CTL.getAddress(), 0xE8, 1); + writeRegister(Block.SYS, Address.DEMOD_CTL_1, 0x22, 1); + writeRegister(Block.SYS, Address.DEMOD_CTL, 0xE8, 1); /* Reset demod */ writeDemodRegister(Page.ONE, (short) 0x01, 0x14, 1); //Bit 3 = soft reset @@ -513,7 +534,7 @@ public void initBaseband() throws LibUsbException */ private void deinitBaseband() throws IllegalArgumentException, UsbDisconnectedException { - writeRegister(Block.SYS, Address.DEMOD_CTL.getAddress(), 0x20, 1); + writeRegister(Block.SYS, Address.DEMOD_CTL, 0x20, 1); } /** @@ -527,7 +548,7 @@ private void deinitBaseband() throws IllegalArgumentException, UsbDisconnectedEx private void setGPIOBit(byte bitMask, boolean enabled) throws LibUsbException { //Get current register value - int value = readRegister(Block.SYS, Address.GPO.getAddress(), 1); + int value = readRegister(Block.SYS, Address.GPO, 1); //Update the masked bits if(enabled) @@ -540,7 +561,7 @@ private void setGPIOBit(byte bitMask, boolean enabled) throws LibUsbException } //Write the change back to the device - writeRegister(Block.SYS, Address.GPO.getAddress(), value, 1); + writeRegister(Block.SYS, Address.GPO, value, 1); } /** @@ -553,16 +574,16 @@ private void setGPIOBit(byte bitMask, boolean enabled) throws LibUsbException private void setGPIOOutput(byte bitMask) throws LibUsbException { //Get current register value - int value = readRegister(Block.SYS, Address.GPD.getAddress(), 1); + int value = readRegister(Block.SYS, Address.GPD, 1); //Mask the value and rewrite it - writeRegister(Block.SYS, Address.GPO.getAddress(), value & ~bitMask, 1); + writeRegister(Block.SYS, Address.GPO, value & ~bitMask, 1); //Get current register value - value = readRegister(Block.SYS, Address.GPOE.getAddress(), 1); + value = readRegister(Block.SYS, Address.GPOE, 1); //Mask the value and rewrite it - writeRegister(Block.SYS, Address.GPOE.getAddress(), value | bitMask, 1); + writeRegister(Block.SYS, Address.GPOE, value | bitMask, 1); } /** @@ -720,7 +741,7 @@ private int readDemodRegister(Page page, short address, int length) throws LibUs * @param length of value in bytes * @throws LibUsbException on error */ - private void writeRegister(Block block, short address, int value, int length) throws LibUsbException + private void writeRegister(Block block, Address address, int value, int length) throws LibUsbException { ByteBuffer buffer = ByteBuffer.allocateDirect(length); buffer.order(ByteOrder.BIG_ENDIAN); @@ -740,7 +761,7 @@ else if(length == 2) } buffer.rewind(); - write(address, block, buffer); + write(address.getAddress(), block, buffer); } /** @@ -751,10 +772,10 @@ else if(length == 2) * @return value read * @throws LibUsbException on error */ - private int readRegister(Block block, short address, int length) throws LibUsbException + private int readRegister(Block block, Address address, int length) throws LibUsbException { ByteBuffer buffer = ByteBuffer.allocateDirect(2); - read(address, block, buffer); + read(address.getAddress(), block, buffer); buffer.order(ByteOrder.LITTLE_ENDIAN); if(length == 2) @@ -869,11 +890,11 @@ private boolean isTuner(TunerTypeCheck type, boolean controlI2CRepeater) if(type == TunerTypeCheck.FC2580) { - return ((value & 0x7F) == type.getCheckValue()); + return ((value & 0x7F) == (type.getCheckValue() & 0xFF)); } else { - return (value == type.getCheckValue()); + return (value == (type.getCheckValue() & 0xFF)); } } catch(LibUsbException e) @@ -973,7 +994,7 @@ private int getUSBTransferBufferSize(double sampleRate) public void setSampleRateFrequencyCorrection(int ppm) throws SourceException { - int offset = -ppm * TWO_TO_22_POWER / 1000000; + int offset = -ppm * TWO_TO_22_POWER / 1_000_000; writeDemodRegister(Page.ONE, (short) 0x3F, (offset & 0xFF), 1); writeDemodRegister(Page.ONE, (short) 0x3E, (Integer.rotateRight(offset, 8) & 0xFF), 1); /* Test to retune controller to apply frequency correction */ @@ -983,7 +1004,7 @@ public void setSampleRateFrequencyCorrection(int ppm) throws SourceException } catch(Exception e) { - throw new SourceException("couldn't set sample rate frequency correction", e); + throw new SourceException("Couldn't set sample rate frequency correction", e); } } @@ -1027,7 +1048,7 @@ public byte[] readEEPROM(short offset, int length) throws IllegalArgumentExcepti try { /* Tell the RTL-2832 to address the EEPROM */ - writeRegister(Block.I2C, EEPROM_ADDRESS, (byte) offset, 1); + writeRegister(Block.I2C, Address.EEPROM, (byte) offset, 1); } catch(LibUsbException e) { @@ -1068,7 +1089,7 @@ public void writeEEPROMByte(byte offset, byte value) throws IllegalArgumentExcep } int offsetAndValue = Integer.rotateLeft((0xFF & offset), 8) | (0xFF & value); - writeRegister(Block.I2C, EEPROM_ADDRESS, offsetAndValue, 2); + writeRegister(Block.I2C, Address.EEPROM, offsetAndValue, 2); } public enum Address @@ -1093,7 +1114,8 @@ public enum Address SYSINTE_1(0x3009), SYSINTS_1(0x300A), DEMOD_CTL_1(0x300B), - IR_SUSPEND(0x300C); + IR_SUSPEND(0x300C), + EEPROM(0xA0); private int mAddress; @@ -1314,6 +1336,14 @@ public Descriptor(byte[] data) getLabels(); } + /** + * Indicates if this is a rtl-sdr.com V4 R828D dongle with notch filtering. + */ + public boolean isRtlSdrV4() + { + return "RTLSDRBlog".equals(getVendorLabel()) && "Blog V4".equals(getProductLabel()); + } + public boolean isValid() { return mData[0] != (byte)0x0 && mData[1] != (byte)0x0; @@ -1479,6 +1509,15 @@ public boolean isRunning() return mController.isRunning(); } + /** + * Indicates if this is a rtl-sdr.com V4 dongle with support for notch filtering. + * @return true if this is a V4 R828D tuner. + */ + public boolean isV4Dongle() + { + return mController.getDescriptor().isRtlSdrV4(); + } + /** * Device handle for the tuner controller. * @return 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 402e53bf4..f08528439 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 @@ -41,6 +41,7 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JSeparator; +import javax.swing.JToggleButton; import javax.swing.SpinnerNumberModel; import javax.usb.UsbException; @@ -52,6 +53,7 @@ public class E4KTunerEditor extends TunerEditor mSampleRateCombo; private JComboBox mMasterGainCombo; private JComboBox mMixerGainCombo; @@ -95,7 +97,8 @@ private void init() add(getTunerInfoButton()); add(new JLabel("Status:")); - add(getTunerStatusLabel(), "wrap"); + add(getTunerStatusLabel()); + add(getBiasTButton(), "wrap"); add(getButtonPanel(), "span,align left"); @@ -144,6 +147,8 @@ protected void tunerStatusUpdated() if(hasTuner()) { + getBiasTButton().setEnabled(true); + getBiasTButton().setSelected(getConfiguration().isBiasT()); getTunerInfoButton().setEnabled(true); getSampleRateCombo().setEnabled(true); getSampleRateCombo().setSelectedItem(getConfiguration().getSampleRate()); @@ -174,6 +179,8 @@ protected void tunerStatusUpdated() } else { + getBiasTButton().setEnabled(false); + getBiasTButton().setSelected(false); getTunerInfoButton().setEnabled(false); getSampleRateCombo().setEnabled(false); getMasterGainCombo().setEnabled(false); @@ -187,6 +194,28 @@ protected void tunerStatusUpdated() setLoading(false); } + /** + * Bias-T toggle button + * @return + */ + private JToggleButton getBiasTButton() + { + if(mBiasTButton == null) + { + mBiasTButton = new JToggleButton("Bias-T"); + mBiasTButton.setEnabled(false); + mBiasTButton.addActionListener(e -> { + if(!isLoading()) + { + getTuner().getController().setBiasT(mBiasTButton.isSelected()); + save(); + } + }); + } + + return mBiasTButton; + } + private JComboBox getIfGainCombo() { if(mIfGainCombo == null) @@ -459,7 +488,7 @@ public void save() double value = ((SpinnerNumberModel)getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue(); config.setFrequencyCorrection(value); config.setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected()); - + config.setBiasT(getTuner().getController().isBiasT()); config.setSampleRate((SampleRate)getSampleRateCombo().getSelectedItem()); config.setMasterGain((E4KGain)getMasterGainCombo().getSelectedItem()); config.setMixerGain((E4KMixerGain)getMixerGainCombo().getSelectedItem()); diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TEmbeddedTuner.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xEmbeddedTuner.java similarity index 67% rename from src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TEmbeddedTuner.java rename to src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xEmbeddedTuner.java index f43b86c13..3711d12eb 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TEmbeddedTuner.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xEmbeddedTuner.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer + * 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 @@ -16,88 +16,64 @@ * along with this program. If not, see * **************************************************************************** */ -package io.github.dsheirer.source.tuner.rtl.r820t; + +package io.github.dsheirer.source.tuner.rtl.r8x; import io.github.dsheirer.source.SourceException; -import io.github.dsheirer.source.tuner.TunerType; 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.nio.ByteBuffer; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.usb4java.LibUsbException; import javax.usb.UsbException; -import java.nio.ByteBuffer; -public class R820TEmbeddedTuner extends EmbeddedTuner +/** + * Abstract Rafael Micro R8XXX Embedded Tuner base class implementation + */ +public abstract class R8xEmbeddedTuner extends EmbeddedTuner { - private final static Logger mLog = LoggerFactory.getLogger(R820TEmbeddedTuner.class); + 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; private static final double USABLE_BANDWIDTH_PERCENT = 0.98; private static final int DC_SPIKE_AVOID_BUFFER = 5000; - private static final int R820T_IF_FREQUENCY = 3570000; private static final byte VERSION = (byte) 49; - private static final byte I2C_ADDRESS = (byte) 0x34; - 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}; + protected static final int IF_FREQUENCY = 3570000; + private static final Logger mLog = LoggerFactory.getLogger(R8xEmbeddedTuner.class); + private static int mVcoPowerRef = 1; /** * Shadow register is used to keep a cached (in-memory) copy of all registers, so that we don't have to read a * full byte from a register in order to apply a masked value and then re-write the full byte. With the shadow * register, we can apply the masked value to the cached value, and then just write the masked byte, skipping the - * need to read the byte first. + * need to read the byte first and avoid writing the byte value if the value is unchanged. */ - private int[] mShadowRegister = {0x00, 0x00, 0x00, 0x00, 0x00, 0x83, 0x32, 0x75, 0xC0, 0x40, 0xD6, 0x6C, 0xF5, 0x63, - 0x75, 0x68, 0x6C, 0x83, 0x80, 0x00, 0x0F, 0x00, 0xC0, 0x30, 0x48, 0xCC, 0x60, 0x00, 0x54, 0xAE, 0x4A, 0xC0}; - + private byte[] mShadowRegister = {(byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x00, (byte) 0x83, + (byte) 0x32, (byte) 0x75, (byte) 0xC0, (byte) 0x40, (byte) 0xD6, (byte) 0x6C, (byte) 0xF5, (byte) 0x63, + (byte) 0x75, (byte) 0x68, (byte) 0x6C, (byte) 0x83, (byte) 0x80, (byte) 0x00, (byte) 0x0F, (byte) 0x00, + (byte) 0xC0, (byte) 0x30, (byte) 0x48, (byte) 0xCC, (byte) 0x60, (byte) 0x00, (byte) 0x54, (byte) 0xAE, + (byte) 0x4A, (byte) 0xC0}; /** * Constructs an instance - * @param adapter for accessing RTL2832USBController interfaces + * @param adapter to control the RTL2832 interface. + * @param vcoPowerRef power reference. */ - public R820TEmbeddedTuner(RTL2832TunerController.ControllerAdapter adapter) + public R8xEmbeddedTuner(RTL2832TunerController.ControllerAdapter adapter, int vcoPowerRef) { super(adapter); + mVcoPowerRef = vcoPowerRef; } - @Override - public TunerType getTunerType() - { - return TunerType.RAFAELMICRO_R820T; - } - - @Override - public long getMinimumFrequencySupported() - { - return MINIMUM_SUPPORTED_FREQUENCY; - } - - @Override - public long getMaximumFrequencySupported() - { - return MAXIMUM_SUPPORTED_FREQUENCY; - } - - @Override - public int getDcSpikeHalfBandwidth() - { - return DC_SPIKE_AVOID_BUFFER; - } - - @Override - public double getUsableBandwidthPercent() - { - return USABLE_BANDWIDTH_PERCENT; - } - - @Override - public void setSampleRateFilters(int sampleRate) throws SourceException - { - //No-op - } + /** + * I2C Address for the embedded tuner + */ + public abstract byte getI2CAddress(); /** * Applies the tuner configuration values to this embedded tuner @@ -109,14 +85,14 @@ public void apply(TunerConfiguration tunerConfig) throws SourceException { //Invoke super for frequency, frequency correction and autoPPM - if(tunerConfig instanceof R820TTunerConfiguration config) + if(tunerConfig instanceof R8xTunerConfiguration config) { try { - R820TGain masterGain = config.getMasterGain(); + MasterGain masterGain = config.getMasterGain(); setGain(masterGain, true); - if(masterGain == R820TGain.MANUAL) + if(masterGain == MasterGain.MANUAL) { setLNAGain(config.getLNAGain(), true); setMixerGain(config.getMixerGain(), true); @@ -125,83 +101,92 @@ public void apply(TunerConfiguration tunerConfig) throws SourceException } catch(UsbException e) { - throw new SourceException("R820TTunerController - usb error while applying tuner config", e); + throw new SourceException("R8xxxTunerController - usb error while applying tuner config", e); } } } /** - * Sets the center frequency. Setting the frequency is a two-part process - * of setting the multiplexer and then setting the Oscillator (PLL). + * Writes the byte value to the specified register, optionally controlling the I2C repeater as needed. */ - @Override - public synchronized void setTunedFrequency(long frequency) throws SourceException + public synchronized void writeRegister(Register register, byte value, boolean controlI2C) throws UsbException { - getAdapter().getLock().lock(); + byte current = mShadowRegister[register.getRegister()]; - try - { - getAdapter().enableI2CRepeater(); - boolean controlI2C = false; - long offsetFrequency = frequency + R820T_IF_FREQUENCY; - setMux(offsetFrequency, controlI2C); - setPLL(offsetFrequency, controlI2C); - getAdapter().disableI2CRepeater(); - } - catch(UsbException e) + if(register.isMasked()) { - throw new SourceException("R820TTunerController - exception while setting frequency [" + frequency + "] - " + - e.getLocalizedMessage()); + value = (byte) ((current & ~register.getMask()) | (value & register.getMask())); } - finally + + if(value != current) { - getAdapter().getLock().unlock(); + getAdapter().writeI2CRegister(getI2CAddress(), (byte) register.getRegister(), value, controlI2C); + mShadowRegister[register.getRegister()] = value; } } /** - * Overrides the same method from the RTL2832 tuner controller to apply - * settings specific to the R820T tuner. + * Reads the specified register, optionally controlling the I2C repeater */ - public void setSamplingMode(RTL2832TunerController.SampleMode mode) throws LibUsbException + public int readRegister(Register register, boolean controlI2C) throws UsbException { - if(mode == RTL2832TunerController.SampleMode.QUADRATURE) - { - /* Set intermediate frequency to R820T IF frequency */ - getAdapter().setIFFrequency(R820T_IF_FREQUENCY); - - /* Enable spectrum inversion */ - getAdapter().writeDemodRegister(RTL2832TunerController.Page.ONE, (short) 0x15, (short) 0x01, 1); - - /* Set default i/q path */ - getAdapter().writeDemodRegister(RTL2832TunerController.Page.ZERO, (short) 0x06, (short) 0x80, 1); - } + return getAdapter().readI2CRegister(getI2CAddress(), (byte) register.getRegister(), controlI2C); } /** - * Sets the multiplexer for the desired center frequency. + * Assumes value is a byte value and reverses the bits in the byte. */ - private void setMux(long frequency, boolean controlI2C) throws UsbException + private static int bitReverse(int value) { - FrequencyRange range = FrequencyRange.getRangeForFrequency(frequency); + return BIT_REV_LOOKUP_TABLE[value & 0x0F] << 4 | BIT_REV_LOOKUP_TABLE[(value & 0xF0) >> 4]; + } - /* Set open drain */ - writeR820TRegister(Register.DRAIN, range.getOpenDrain(), controlI2C); + @Override + public long getMinimumFrequencySupported() + { + return MINIMUM_SUPPORTED_FREQUENCY; + } - /* RF_MUX, Polymux */ - writeR820TRegister(Register.RF_POLY_MUX, range.getRFMuxPolyMux(), controlI2C); + @Override + public long getMaximumFrequencySupported() + { + return MAXIMUM_SUPPORTED_FREQUENCY; + } - /* TF Band */ - writeR820TRegister(Register.TF_BAND, range.getTFC(), controlI2C); + @Override + public int getDcSpikeHalfBandwidth() + { + return DC_SPIKE_AVOID_BUFFER; + } - /* XTAL CAP & Drive */ - writeR820TRegister(Register.PLL_XTAL_CAPACITOR_AND_DRIVE, range.getXTALHighCap0P(), controlI2C); + @Override + public double getUsableBandwidthPercent() + { + return USABLE_BANDWIDTH_PERCENT; + } - /* Register 8 - what is it? */ - writeR820TRegister(Register.UNKNOWN_REGISTER_8, (byte) 0x00, controlI2C); + @Override + public void setSampleRateFilters(int sampleRate) throws SourceException + { + //No-op + } - /* Register 9 - what is it? */ - writeR820TRegister(Register.UNKNOWN_REGISTER_9, (byte) 0x00, controlI2C); + /** + * Overrides the same method from the RTL2832 tuner controller to apply settings specific to the R8xxx tuner. + */ + public void setSamplingMode(RTL2832TunerController.SampleMode mode) throws LibUsbException + { + if(mode == RTL2832TunerController.SampleMode.QUADRATURE) + { + /* Set intermediate frequency to R820T IF frequency */ + getAdapter().setIFFrequency(IF_FREQUENCY); + + /* Enable spectrum inversion */ + getAdapter().writeDemodRegister(RTL2832TunerController.Page.ONE, (short) 0x15, (short) 0x01, 1); + + /* Set default i/q path */ + getAdapter().writeDemodRegister(RTL2832TunerController.Page.ZERO, (short) 0x06, (short) 0x80, 1); + } } /** @@ -215,8 +200,8 @@ protected void initTuner() throws UsbException /* Only enable in-phase ADC input */ getAdapter().writeDemodRegister(RTL2832TunerController.Page.ZERO, (short) 0x08, (short) 0x4D, 1); - /* Set intermediate frequency to R820T IF frequency (3.57 MHz) */ - getAdapter().setIFFrequency(R820T_IF_FREQUENCY); + /* Set intermediate frequency to IF frequency (3.57 MHz) */ + getAdapter().setIFFrequency(IF_FREQUENCY); /* Enable spectrum inversion */ getAdapter().writeDemodRegister(RTL2832TunerController.Page.ONE, (short) 0x15, (short) 0x01, 1); @@ -225,44 +210,146 @@ protected void initTuner() throws UsbException systemFrequencySelect(0, false); } + /** + * Sets the tuner's Phase-Locked-Loop (PLL) oscillator used for frequency (tuning) control + * + * @param frequency - desired center frequency + * @param controlI2C - control the I2C repeater locally + * @throws UsbException - if unable to set any of the R8xxx registers + */ + protected void setPLL(long frequency, boolean controlI2C) throws UsbException + { + /* Set reference divider to 0 */ + writeRegister(Register.REFERENCE_DIVIDER_2, (byte) 0x00, controlI2C); + /* Set PLL autotune to 128kHz */ + writeRegister(Register.PLL_AUTOTUNE, (byte) 0x00, controlI2C); + /* Set VCO current to 100 */ + writeRegister(Register.VCO_CURRENT, (byte) 0x80, controlI2C); + /* Set the frequency divider - adjust for vco_fine_tune status */ + FrequencyDivider divider = FrequencyDivider.fromFrequency(frequency); + int statusRegister4 = getStatusRegister(4, controlI2C); + int vco_fine_tune = (statusRegister4 & 0x30) >> 4; + int div_num = divider.getDividerNumber(vco_fine_tune); + writeRegister(Register.DIVIDER, (byte) (div_num << 5), controlI2C); + /* Get the integral number for this divider and frequency */ + Integral integral = divider.getIntegral(frequency); + writeRegister(Register.PLL, integral.getRegisterValue(), controlI2C); + /* Calculate the sigma-delta modulator fractional setting. If it's non-zero, power up the sdm and apply the + fractional setting, otherwise turn it off */ + int sdm = divider.getSDM(integral, frequency); + if(sdm != 0) + { + writeRegister(Register.SIGMA_DELTA_MODULATOR_POWER, (byte) 0x00, controlI2C); + writeRegister(Register.SIGMA_DELTA_MODULATOR_MSB, (byte) ((sdm >> 8) & 0xFF), controlI2C); + writeRegister(Register.SIGMA_DELTA_MODULATOR_LSB, (byte) (sdm & 0xFF), controlI2C); + } + else + { + writeRegister(Register.SIGMA_DELTA_MODULATOR_POWER, (byte) 0x08, controlI2C); + } + + /* Check to see if the PLL locked with these divider, integral and sdm + * settings */ + if(!isPLLLocked(controlI2C)) + { + mLog.info("PLL is not locked. Increasing VCO current"); + /* Increase VCO current */ + writeRegister(Register.VCO_CURRENT, (byte) 0x60, controlI2C); + + if(!isPLLLocked(controlI2C)) + { + throw new UsbException("R8xxx Tuner Controller - couldn't achieve PLL lock on frequency [" + frequency + "]"); + } + } + /* set pll autotune to 8kHz */ + writeRegister(Register.PLL_AUTOTUNE_VARIANT, (byte) 0x08, controlI2C); + } + + /** + * Sets the system IF frequency + */ + private void systemFrequencySelect(long frequency, boolean controlI2C) throws UsbException + { + /* LNA top? */ + writeRegister(Register.LNA_TOP2, (byte) 0xE5, controlI2C); + + byte mixer_top; + byte cp_cur; + byte div_buf_cur; + + if(frequency == 506000000 || frequency == 666000000 || frequency == 818000000) + { + mixer_top = (byte) 0x14; + cp_cur = (byte) 0x28; + div_buf_cur = (byte) 0x20; + } + else + { + mixer_top = (byte) 0x24; + cp_cur = (byte) 0x38; + div_buf_cur = (byte) 0x30; + } + + writeRegister(Register.MIXER_TOP, mixer_top, controlI2C); + writeRegister(Register.LNA_VTH_L, (byte) 0x53, controlI2C); + writeRegister(Register.MIXER_VTH_L, (byte) 0x75, controlI2C); + /* Air-In only for Astrometa */ + writeRegister(Register.INPUT_SELECTOR_AIR_AND_CABLE_1, (byte) 0x00, controlI2C); + writeRegister(Register.INPUT_SELECTOR_CABLE_2, (byte) 0x00, controlI2C); + writeRegister(Register.CP_CUR, cp_cur, controlI2C); + writeRegister(Register.DIVIDER_BUFFER_CURRENT, div_buf_cur, controlI2C); + writeRegister(Register.FILTER_CURRENT, (byte) 0x40, controlI2C); + /* if( type != TUNER_ANALOG_TV ) ... */ + writeRegister(Register.LNA_TOP, (byte) 0x00, controlI2C); + writeRegister(Register.MIXER_TOP2, (byte) 0x00, controlI2C); + writeRegister(Register.PRE_DETECT, (byte) 0x00, controlI2C); + writeRegister(Register.AGC_CLOCK, (byte) 0x30, controlI2C); + writeRegister(Register.LNA_TOP, (byte) 0x18, controlI2C); + writeRegister(Register.MIXER_TOP2, mixer_top, controlI2C); + /* LNA discharge current */ + writeRegister(Register.LNA_DISCHARGE_CURRENT, (byte) 0x14, controlI2C); + /* AGC clock 1 khz, external det1 cap 1u */ + writeRegister(Register.AGC_CLOCK, (byte) 0x20, controlI2C); + } + /** * Partially implements the r82xx_set_tv_standard() method from librtlsdr. * Sets standard to digital tv to support sdr operations only. */ - private void setTVStandard(boolean controlI2C) throws UsbException + protected void setTVStandard(boolean controlI2C) throws UsbException { /* Init Flag & Xtal check Result */ - writeR820TRegister(Register.XTAL_CHECK, (byte) 0x00, controlI2C); + writeRegister(Register.XTAL_CHECK, (byte) 0x00, controlI2C); /* Set version */ - writeR820TRegister(Register.VERSION, VERSION, controlI2C); + writeRegister(Register.VERSION, VERSION, controlI2C); /* LT Gain Test */ - writeR820TRegister(Register.LNA_TOP, (byte) 0x00, controlI2C); + writeRegister(Register.LNA_TOP, (byte) 0x00, controlI2C); int calibrationCode = 0; for(int x = 0; x < 2; x++) { /* Set filter cap */ - writeR820TRegister(Register.FILTER_CAPACITOR, (byte) 0x6B, controlI2C); + writeRegister(Register.FILTER_CAPACITOR, (byte) 0x6B, controlI2C); /* Set calibration clock on */ - writeR820TRegister(Register.CALIBRATION_CLOCK, (byte) 0x04, controlI2C); + writeRegister(Register.CALIBRATION_CLOCK, (byte) 0x04, controlI2C); /* XTAL capacitor 0pF for PLL */ - writeR820TRegister(Register.PLL_XTAL_CAPACITOR, (byte) 0x00, controlI2C); + writeRegister(Register.PLL_XTAL_CAPACITOR, (byte) 0x00, controlI2C); setPLL(56000 * 1000, controlI2C); /* Start trigger */ - writeR820TRegister(Register.CALIBRATION_TRIGGER, (byte) 0x10, controlI2C); + writeRegister(Register.CALIBRATION_TRIGGER, (byte) 0x10, controlI2C); /* Stop trigger */ - writeR820TRegister(Register.CALIBRATION_TRIGGER, (byte) 0x00, controlI2C); + writeRegister(Register.CALIBRATION_TRIGGER, (byte) 0x00, controlI2C); /* Set calibration clock off */ - writeR820TRegister(Register.CALIBRATION_CLOCK, (byte) 0x00, controlI2C); + writeRegister(Register.CALIBRATION_CLOCK, (byte) 0x00, controlI2C); calibrationCode = getCalibrationCode(controlI2C); @@ -280,33 +367,31 @@ private void setTVStandard(boolean controlI2C) throws UsbException /* Write calibration code */ byte filt_q = 0x10; - writeR820TRegister(Register.FILTER_CALIBRATION_CODE, - (byte) (calibrationCode | filt_q), controlI2C); + writeRegister(Register.FILTER_CALIBRATION_CODE, (byte) (calibrationCode | filt_q), controlI2C); /* Set BW, Filter gain & HP Corner */ - writeR820TRegister(Register.BANDWIDTH_FILTER_GAIN_HIGHPASS_FILTER_CORNER, - (byte) 0x6B, controlI2C); + writeRegister(Register.BANDWIDTH_FILTER_GAIN_HIGHPASS_FILTER_CORNER, (byte) 0x6B, controlI2C); /* Set Image_R */ - writeR820TRegister(Register.IMAGE_REVERSE, (byte) 0x00, controlI2C); + writeRegister(Register.IMAGE_REVERSE, (byte) 0x00, controlI2C); /* Set filter_3db, V6MHz */ - writeR820TRegister(Register.FILTER_GAIN, (byte) 0x10, controlI2C); + writeRegister(Register.FILTER_GAIN, (byte) 0x10, controlI2C); /* Channel filter extension */ - writeR820TRegister(Register.CHANNEL_FILTER_EXTENSION, (byte) 0x60, controlI2C); + writeRegister(Register.CHANNEL_FILTER_EXTENSION, (byte) 0x60, controlI2C); /* Loop through */ - writeR820TRegister(Register.LOOP_THROUGH, (byte) 0x00, controlI2C); + writeRegister(Register.LOOP_THROUGH, (byte) 0x00, controlI2C); /* Loop through attenuation */ - writeR820TRegister(Register.LOOP_THROUGH_ATTENUATION, (byte) 0x00, controlI2C); + writeRegister(Register.LOOP_THROUGH_ATTENUATION, (byte) 0x00, controlI2C); /* Filter extension widest */ - writeR820TRegister(Register.FILTER_EXTENSION_WIDEST, (byte) 0x00, controlI2C); + writeRegister(Register.FILTER_EXTENSION_WIDEST, (byte) 0x00, controlI2C); /* RF poly filter current */ - writeR820TRegister(Register.RF_POLY_FILTER_CURRENT, (byte) 0x60, controlI2C); + writeRegister(Register.RF_POLY_FILTER_CURRENT, (byte) 0x60, controlI2C); } /** @@ -326,119 +411,43 @@ private int getCalibrationCode(boolean controlI2C) throws UsbException } /** - * Sets the system IF frequency + * Indicates if the Phase Locked Loop (PLL) oscillator is locked following + * a change in the tuned center frequency. Checks status register 2 to see + * if the PLL locked indicator bit is set. */ - private void systemFrequencySelect(long frequency, boolean controlI2C) throws UsbException + protected boolean isPLLLocked(boolean controlI2C) throws UsbException { - /* LNA top? */ - writeR820TRegister(Register.LNA_TOP2, (byte) 0xE5, controlI2C); - - byte mixer_top; - byte cp_cur; - byte div_buf_cur; - - if(frequency == 506000000 || frequency == 666000000 || frequency == 818000000) - { - mixer_top = (byte) 0x14; - cp_cur = (byte) 0x28; - div_buf_cur = (byte) 0x20; - } - else - { - mixer_top = (byte) 0x24; - cp_cur = (byte) 0x38; - div_buf_cur = (byte) 0x30; - } - - writeR820TRegister(Register.MIXER_TOP, mixer_top, controlI2C); - writeR820TRegister(Register.LNA_VTH_L, (byte) 0x53, controlI2C); - writeR820TRegister(Register.MIXER_VTH_L, (byte) 0x75, controlI2C); - /* Air-In only for Astrometa */ - writeR820TRegister(Register.AIR_CABLE1_INPUT_SELECTOR, (byte) 0x00, controlI2C); - writeR820TRegister(Register.CABLE2_INPUT_SELECTOR, (byte) 0x00, controlI2C); - writeR820TRegister(Register.CP_CUR, cp_cur, controlI2C); - writeR820TRegister(Register.DIVIDER_BUFFER_CURRENT, div_buf_cur, controlI2C); - writeR820TRegister(Register.FILTER_CURRENT, (byte) 0x40, controlI2C); - /* if( type != TUNER_ANALOG_TV ) ... */ - writeR820TRegister(Register.LNA_TOP, (byte) 0x00, controlI2C); - writeR820TRegister(Register.MIXER_TOP2, (byte) 0x00, controlI2C); - writeR820TRegister(Register.PRE_DETECT, (byte) 0x00, controlI2C); - writeR820TRegister(Register.AGC_CLOCK, (byte) 0x30, controlI2C); - writeR820TRegister(Register.LNA_TOP, (byte) 0x18, controlI2C); - writeR820TRegister(Register.MIXER_TOP2, mixer_top, controlI2C); - /* LNA discharge current */ - writeR820TRegister(Register.LNA_DISCHARGE_CURRENT, (byte) 0x14, controlI2C); - /* AGC clock 1 khz, external det1 cap 1u */ - writeR820TRegister(Register.AGC_CLOCK, (byte) 0x20, controlI2C); + int register = getStatusRegister(2, controlI2C); + return (register & 0x40) == 0x40; } /** - * Sets the tuner's Phase-Locked-Loop (PLL) oscillator used for frequency (tuning) control - * - * @param frequency - desired center frequency - * @param controlI2C - control the I2C repeater locally - * @throws UsbException - if unable to set any of the R820T registers + * Sets the multiplexer for the desired center frequency. */ - private void setPLL(long frequency, boolean controlI2C) throws UsbException + protected void setMux(long frequency, boolean controlI2C) throws UsbException { - /* Set reference divider to 0 */ - writeR820TRegister(Register.REFERENCE_DIVIDER_2, (byte) 0x00, controlI2C); - /* Set PLL autotune to 128kHz */ - writeR820TRegister(Register.PLL_AUTOTUNE, (byte) 0x00, controlI2C); - /* Set VCO current to 100 */ - writeR820TRegister(Register.VCO_CURRENT, (byte) 0x80, controlI2C); - /* Set the frequency divider - adjust for vco_fine_tune status */ - FrequencyDivider divider = FrequencyDivider.fromFrequency(frequency); - int statusRegister4 = getStatusRegister(4, controlI2C); - int vco_fine_tune = (statusRegister4 & 0x30) >> 4; - int div_num = divider.getDividerNumber(vco_fine_tune); - writeR820TRegister(Register.DIVIDER, (byte) (div_num << 5), controlI2C); - /* Get the integral number for this divider and frequency */ - Integral integral = divider.getIntegral(frequency); - writeR820TRegister(Register.PLL, integral.getRegisterValue(), controlI2C); - /* Calculate the sigma-delta modulator fractional setting. If it's - * non-zero, power up the sdm and apply the fractional setting, - * otherwise turn it off */ - int sdm = divider.getSDM(integral, frequency); - if(sdm != 0) - { - writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_POWER, (byte) 0x00, controlI2C); - writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_MSB, (byte) ((sdm >> 8) & 0xFF), controlI2C); - writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_LSB, (byte) (sdm & 0xFF), controlI2C); - } - else - { - writeR820TRegister(Register.SIGMA_DELTA_MODULATOR_POWER, (byte) 0x08, controlI2C); - } + FrequencyRange range = FrequencyRange.getRangeForFrequency(frequency); - /* Check to see if the PLL locked with these divider, integral and sdm - * settings */ - if(!isPLLLocked(controlI2C)) - { - /* Increase VCO current */ - writeR820TRegister(Register.VCO_CURRENT, (byte) 0x60, controlI2C); + /* Set open drain */ + writeRegister(Register.DRAIN, range.getOpenDrain(), controlI2C); - if(!isPLLLocked(controlI2C)) - { - throw new UsbException("R820T Tuner Controller - couldn't achieve PLL lock on frequency [" + frequency + "]"); - } - } + /* RF_MUX, Polymux */ + writeRegister(Register.RF_POLY_MUX, range.getRFMuxPolyMux(), controlI2C); - /* set pll autotune to 8kHz */ - writeR820TRegister(Register.PLL_AUTOTUNE_VARIANT, (byte) 0x08, controlI2C); - } + /* TF Band */ + writeRegister(Register.TF_BAND, range.getTFC(), controlI2C); - /** - * Indicates if the Phase Locked Loop (PLL) oscillator is locked following - * a change in the tuned center frequency. Checks status register 2 to see - * if the PLL locked indicator bit is set. - */ - private boolean isPLLLocked(boolean controlI2C) throws UsbException - { - int register = getStatusRegister(2, controlI2C); - return (register & 0x40) == 0x40; + /* XTAL CAP & Drive */ + writeRegister(Register.PLL_XTAL_CAPACITOR_AND_DRIVE, range.getXTALHighCap0P(), controlI2C); + + /* Register 8 - what is it? */ + writeRegister(Register.UNKNOWN_REGISTER_8, (byte) 0x00, controlI2C); + + /* Register 9 - what is it? */ + writeRegister(Register.UNKNOWN_REGISTER_9, (byte) 0x00, controlI2C); } + /** * Writes initial starting value of registers 0x05 through 0x1F using the * default value initialized in the shadow register array. This method only @@ -446,77 +455,45 @@ private boolean isPLLLocked(boolean controlI2C) throws UsbException * * @throws UsbException */ - private void initializeRegisters(boolean controlI2C) throws UsbException + protected void initializeRegisters(boolean controlI2C) throws UsbException { for(int x = 5; x < mShadowRegister.length; x++) { - getAdapter().writeI2CRegister(I2C_ADDRESS, (byte) x, (byte) mShadowRegister[x], controlI2C); + getAdapter().writeI2CRegister(getI2CAddress(), (byte) x, mShadowRegister[x], controlI2C); } } /** * Returns the contents of status registers 0 through 4 */ - private int getStatusRegister(int register, boolean controlI2C) throws UsbException + protected int getStatusRegister(int register, boolean controlI2C) throws UsbException { ByteBuffer buffer = ByteBuffer.allocateDirect(5); - getAdapter().read(I2C_ADDRESS, RTL2832TunerController.Block.I2C, buffer); + getAdapter().read(getI2CAddress(), RTL2832TunerController.Block.I2C, buffer); return bitReverse(buffer.get(register) & 0xFF); } - /** - * Assumes value is a byte value and reverses the bits in the byte. - */ - private static int bitReverse(int value) - { - return BIT_REV_LOOKUP_TABLE[value & 0x0F] << 4 | BIT_REV_LOOKUP_TABLE[(value & 0xF0) >> 4]; - } - - /** - * Writes the byte value to the specified register, optionally controlling - * the I2C repeater as needed. - */ - public synchronized void writeR820TRegister(Register register, byte value, boolean controlI2C) throws UsbException - { - if(register.isMasked()) - { - int current = mShadowRegister[register.getRegister()]; - value = (byte) ((current & ~register.getMask()) | (value & register.getMask())); - } - - getAdapter().writeI2CRegister(I2C_ADDRESS, (byte) register.getRegister(), value, controlI2C); - mShadowRegister[register.getRegister()] = value; - } - - /** - * Reads the specified register, optionally controlling the I2C repeater - */ - public int readR820TRegister(Register register, boolean controlI2C) throws UsbException - { - return getAdapter().readI2CRegister(I2C_ADDRESS, (byte) register.getRegister(), controlI2C); - } - /** * Sets master gain by applying gain component values to LNA, Mixer and * VGA gain registers. */ - public void setGain(R820TGain gain, boolean controlI2C) throws UsbException + public void setGain(MasterGain masterGain, boolean controlI2C) throws UsbException { - setLNAGain(gain.getLNAGain(), controlI2C); - setMixerGain(gain.getMixerGain(), controlI2C); - setVGAGain(gain.getVGAGain(), controlI2C); + setLNAGain(masterGain.getLNAGain(), controlI2C); + setMixerGain(masterGain.getMixerGain(), controlI2C); + setVGAGain(masterGain.getVGAGain(), controlI2C); } /** * Sets LNA gain */ - public void setLNAGain(R820TLNAGain gain, boolean controlI2C) throws UsbException + public void setLNAGain(LNAGain gain, boolean controlI2C) throws UsbException { getAdapter().getLock().lock(); try { - writeR820TRegister(Register.LNA_GAIN, gain.getSetting(), controlI2C); + writeRegister(Register.LNA_GAIN, gain.getSetting(), controlI2C); } finally { @@ -527,13 +504,13 @@ public void setLNAGain(R820TLNAGain gain, boolean controlI2C) throws UsbExceptio /** * Sets Mixer gain */ - public void setMixerGain(R820TMixerGain gain, boolean controlI2C) throws UsbException + public void setMixerGain(MixerGain gain, boolean controlI2C) throws UsbException { getAdapter().getLock().lock(); try { - writeR820TRegister(Register.MIXER_GAIN, gain.getSetting(), controlI2C); + writeRegister(Register.MIXER_GAIN, gain.getSetting(), controlI2C); } finally { @@ -544,13 +521,13 @@ public void setMixerGain(R820TMixerGain gain, boolean controlI2C) throws UsbExce /** * Sets VGA gain */ - public void setVGAGain(R820TVGAGain gain, boolean controlI2C) throws UsbException + public void setVGAGain(VGAGain gain, boolean controlI2C) throws UsbException { getAdapter().getLock().lock(); try { - writeR820TRegister(Register.VGA_GAIN, gain.getSetting(), controlI2C); + writeRegister(Register.VGA_GAIN, gain.getSetting(), controlI2C); } finally { @@ -559,9 +536,9 @@ public void setVGAGain(R820TVGAGain gain, boolean controlI2C) throws UsbExceptio } /** - * R820T VGA gain settings + * VGA gain settings */ - public enum R820TVGAGain + public enum VGAGain { GAIN_0("0", 0x00), GAIN_26("26", 0x01), @@ -583,7 +560,7 @@ public enum R820TVGAGain private String mLabel; private int mSetting; - R820TVGAGain(String label, int setting) + VGAGain(String label, int setting) { mLabel = label; mSetting = setting; @@ -601,9 +578,9 @@ public byte getSetting() } /** - * R820T Low Noise Amplifier gain settings + * Low Noise Amplifier gain settings */ - public enum R820TLNAGain + public enum LNAGain { AUTOMATIC("Automatic", 0x00), GAIN_0("0", 0x10), @@ -626,7 +603,7 @@ public enum R820TLNAGain private String mLabel; private int mSetting; - R820TLNAGain(String label, int setting) + LNAGain(String label, int setting) { mLabel = label; mSetting = setting; @@ -644,12 +621,12 @@ public byte getSetting() } /** - * R820T mixer gain settings - * + * Mixer gain settings + *

* Note: gain labels were changed from measured dB values to simple 1-16 value labels to conform * with the ICD listing the values from 0-15 as minimum to maximum. */ - public enum R820TMixerGain + public enum MixerGain { AUTOMATIC("Automatic", 0x10), GAIN_0("1", 0x00), @@ -672,7 +649,7 @@ public enum R820TMixerGain private String mLabel; private int mSetting; - R820TMixerGain(String label, int setting) + MixerGain(String label, int setting) { mLabel = label; mSetting = setting; @@ -690,49 +667,49 @@ public byte getSetting() } /** - * R820T Master gain settings + * Master gain settings */ - public enum R820TGain + public enum MasterGain { - AUTOMATIC("Automatic", R820TVGAGain.GAIN_312, R820TLNAGain.AUTOMATIC, R820TMixerGain.AUTOMATIC), - MANUAL("Manual", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_123), - GAIN_0("0", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_0, R820TMixerGain.GAIN_0), - GAIN_9("9", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_9, R820TMixerGain.GAIN_0), - GAIN_14("14", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_9, R820TMixerGain.GAIN_5), - GAIN_26("26", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_21, R820TMixerGain.GAIN_5), - GAIN_36("36", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_21, R820TMixerGain.GAIN_15), - GAIN_76("76", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_61, R820TMixerGain.GAIN_15), - GAIN_86("86", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_61, R820TMixerGain.GAIN_25), - GAIN_124("124", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_99, R820TMixerGain.GAIN_25), - GAIN_143("143", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_99, R820TMixerGain.GAIN_44), - GAIN_156("156", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_112, R820TMixerGain.GAIN_44), - GAIN_165("165", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_112, R820TMixerGain.GAIN_53), - GAIN_196("196", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_143, R820TMixerGain.GAIN_53), - GAIN_208("208", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_143, R820TMixerGain.GAIN_63), - GAIN_228("228", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_165, R820TMixerGain.GAIN_63), - GAIN_253("253", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_165, R820TMixerGain.GAIN_88), - GAIN_279("279", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_191, R820TMixerGain.GAIN_88), - GAIN_296("296", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_191, R820TMixerGain.GAIN_105), - GAIN_327("327", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_222, R820TMixerGain.GAIN_105), - GAIN_337("337", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_222, R820TMixerGain.GAIN_115), - GAIN_363("363", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_115), - GAIN_371("371", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_248, R820TMixerGain.GAIN_123), - GAIN_385("385", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_262, R820TMixerGain.GAIN_123), - GAIN_401("401", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_262, R820TMixerGain.GAIN_139), - GAIN_420("420", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_281, R820TMixerGain.GAIN_139), - GAIN_433("433", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_281, R820TMixerGain.GAIN_152), - GAIN_438("438", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_286, R820TMixerGain.GAIN_152), - GAIN_444("444", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_286, R820TMixerGain.GAIN_158), - GAIN_479("479", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_321, R820TMixerGain.GAIN_158), - GAIN_482("482", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_321, R820TMixerGain.GAIN_161), - GAIN_495("495", R820TVGAGain.GAIN_210, R820TLNAGain.GAIN_334, R820TMixerGain.GAIN_161); + AUTOMATIC("Automatic", VGAGain.GAIN_312, LNAGain.AUTOMATIC, MixerGain.AUTOMATIC), + MANUAL("Manual", VGAGain.GAIN_210, LNAGain.GAIN_248, MixerGain.GAIN_123), + GAIN_0("0", VGAGain.GAIN_210, LNAGain.GAIN_0, MixerGain.GAIN_0), + GAIN_9("9", VGAGain.GAIN_210, LNAGain.GAIN_9, MixerGain.GAIN_0), + GAIN_14("14", VGAGain.GAIN_210, LNAGain.GAIN_9, MixerGain.GAIN_5), + GAIN_26("26", VGAGain.GAIN_210, LNAGain.GAIN_21, MixerGain.GAIN_5), + GAIN_36("36", VGAGain.GAIN_210, LNAGain.GAIN_21, MixerGain.GAIN_15), + GAIN_76("76", VGAGain.GAIN_210, LNAGain.GAIN_61, MixerGain.GAIN_15), + GAIN_86("86", VGAGain.GAIN_210, LNAGain.GAIN_61, MixerGain.GAIN_25), + GAIN_124("124", VGAGain.GAIN_210, LNAGain.GAIN_99, MixerGain.GAIN_25), + GAIN_143("143", VGAGain.GAIN_210, LNAGain.GAIN_99, MixerGain.GAIN_44), + GAIN_156("156", VGAGain.GAIN_210, LNAGain.GAIN_112, MixerGain.GAIN_44), + GAIN_165("165", VGAGain.GAIN_210, LNAGain.GAIN_112, MixerGain.GAIN_53), + GAIN_196("196", VGAGain.GAIN_210, LNAGain.GAIN_143, MixerGain.GAIN_53), + GAIN_208("208", VGAGain.GAIN_210, LNAGain.GAIN_143, MixerGain.GAIN_63), + GAIN_228("228", VGAGain.GAIN_210, LNAGain.GAIN_165, MixerGain.GAIN_63), + GAIN_253("253", VGAGain.GAIN_210, LNAGain.GAIN_165, MixerGain.GAIN_88), + GAIN_279("279", VGAGain.GAIN_210, LNAGain.GAIN_191, MixerGain.GAIN_88), + GAIN_296("296", VGAGain.GAIN_210, LNAGain.GAIN_191, MixerGain.GAIN_105), + GAIN_327("327", VGAGain.GAIN_210, LNAGain.GAIN_222, MixerGain.GAIN_105), + GAIN_337("337", VGAGain.GAIN_210, LNAGain.GAIN_222, MixerGain.GAIN_115), + GAIN_363("363", VGAGain.GAIN_210, LNAGain.GAIN_248, MixerGain.GAIN_115), + GAIN_371("371", VGAGain.GAIN_210, LNAGain.GAIN_248, MixerGain.GAIN_123), + GAIN_385("385", VGAGain.GAIN_210, LNAGain.GAIN_262, MixerGain.GAIN_123), + GAIN_401("401", VGAGain.GAIN_210, LNAGain.GAIN_262, MixerGain.GAIN_139), + GAIN_420("420", VGAGain.GAIN_210, LNAGain.GAIN_281, MixerGain.GAIN_139), + GAIN_433("433", VGAGain.GAIN_210, LNAGain.GAIN_281, MixerGain.GAIN_152), + GAIN_438("438", VGAGain.GAIN_210, LNAGain.GAIN_286, MixerGain.GAIN_152), + GAIN_444("444", VGAGain.GAIN_210, LNAGain.GAIN_286, MixerGain.GAIN_158), + GAIN_479("479", VGAGain.GAIN_210, LNAGain.GAIN_321, MixerGain.GAIN_158), + GAIN_482("482", VGAGain.GAIN_210, LNAGain.GAIN_321, MixerGain.GAIN_161), + GAIN_495("495", VGAGain.GAIN_210, LNAGain.GAIN_334, MixerGain.GAIN_161); private String mLabel; - private R820TVGAGain mVGAGain; - private R820TLNAGain mLNAGain; - private R820TMixerGain mMixerGain; + private VGAGain mVGAGain; + private LNAGain mLNAGain; + private MixerGain mMixerGain; - R820TGain(String label, R820TVGAGain vga, R820TLNAGain lna, R820TMixerGain mixer) + MasterGain(String label, VGAGain vga, LNAGain lna, MixerGain mixer) { mLabel = label; mVGAGain = vga; @@ -745,31 +722,33 @@ public String toString() return mLabel; } - public R820TVGAGain getVGAGain() + public VGAGain getVGAGain() { return mVGAGain; } - public R820TLNAGain getLNAGain() + public LNAGain getLNAGain() { return mLNAGain; } - public R820TMixerGain getMixerGain() + public MixerGain getMixerGain() { return mMixerGain; } } /** - * R820T tuner registers and register mask values + * R8xxx tuner registers and register mask values */ public enum Register { LNA_GAIN(0x05, 0x1F), - AIR_CABLE1_INPUT_SELECTOR(0x05, 0x60), + INPUT_SELECTOR_AIR(0x05, 0x20), + INPUT_SELECTOR_CABLE_1(0x05, 0x40), + INPUT_SELECTOR_AIR_AND_CABLE_1(0x05, 0x60), LOOP_THROUGH(0x05, 0x80), - CABLE2_INPUT_SELECTOR(0x06, 0x08), + INPUT_SELECTOR_CABLE_2(0x06, 0x08), FILTER_GAIN(0x06, 0x30), PRE_DETECT(0x06, 0x40), MIXER_GAIN(0x07, 0x1F), @@ -896,6 +875,7 @@ public boolean contains(long frequency) /** * Finds the correct frequency range that contains the frequency + * * @param frequency to lookup * @return frequency range */ @@ -960,9 +940,9 @@ public byte getXTALHighCap0P() /** * Frequency Divider Ranges - * + *

* Actual Tuned Frequency Ranges (after subtracting IF = 3.57 MHz ) - * + *

* Divider 0: 860.43 to 1782.03 MHz * Divider 1: 428.43 to 889.23 MHz * Divider 2: 212.43 to 457.23 MHz @@ -989,7 +969,6 @@ public enum FrequencyDivider private long mMaximumFrequency; private int mRegisterSetting; private int mIntegralValue; - private static final int mVCOPowerReference = 2; FrequencyDivider(int dividerNumber, int mixerDivider, long minimumFrequency, long maximumFrequency, int registerSetting, int integralValue) @@ -1004,15 +983,15 @@ public enum FrequencyDivider public int getDividerNumber(int vcoFineTune) { - if(vcoFineTune == mVCOPowerReference) + if(vcoFineTune == mVcoPowerRef) { return mDividerNumber; } - else if(vcoFineTune < mVCOPowerReference) + else if(vcoFineTune < mVcoPowerRef) { return mDividerNumber - 1; } - else if(vcoFineTune > mVCOPowerReference) + else if(vcoFineTune > mVcoPowerRef) { return mDividerNumber + 1; } @@ -1055,7 +1034,7 @@ public boolean contains(long frequency) */ public static FrequencyDivider fromFrequency(long frequency) { - for(FrequencyDivider divider : FrequencyDivider.values()) + for(FrequencyDivider divider : R8xEmbeddedTuner.FrequencyDivider.values()) { if(divider.contains(frequency)) { @@ -1063,7 +1042,7 @@ public static FrequencyDivider fromFrequency(long frequency) } } - return FrequencyDivider.DIVIDER_5; + return R8xEmbeddedTuner.FrequencyDivider.DIVIDER_5; } /** @@ -1077,7 +1056,7 @@ public Integral getIntegral(long frequency) int integral = (int) ((double) delta / (double) mIntegralValue); - return Integral.fromValue(integral); + return R8xEmbeddedTuner.Integral.fromValue(integral); } throw new IllegalArgumentException("PLL frequency [" + frequency + "] is not valid for this frequency " + @@ -1105,16 +1084,7 @@ public int getSDM(Integral integral, long frequency) } /** - * PLL Integral values. Each value represents one unit of the divided - * crystal frequency as follows: - * - * Divider Value - * 64 I * 0.9 MHz - * 32 I * 1.8 MHz - * 16 I * 3.6 MHz - * 8 I * 7.2 MHz - * 4 I * 14.4 MHz - * 2 I * 28.8 MHz + * PLL Integral values. Each value represents one unit of the divided crystal frequency. */ public enum Integral { @@ -1174,10 +1144,10 @@ public static Integral fromValue(int value) { if(0 <= value && value <= 31) { - return Integral.values()[value]; + return R8xEmbeddedTuner.Integral.values()[value]; } throw new IllegalArgumentException("PLL integral value [" + value + "] must be in the range 0 - 31"); } } -} \ No newline at end of file +} diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerConfiguration.java similarity index 53% rename from src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerConfiguration.java rename to src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerConfiguration.java index cdeb67b79..43ab8b7f9 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerConfiguration.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerConfiguration.java @@ -1,6 +1,6 @@ /* * ***************************************************************************** - * Copyright (C) 2014-2022 Dennis Sheirer + * 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 @@ -16,87 +16,78 @@ * along with this program. If not, see * **************************************************************************** */ -package io.github.dsheirer.source.tuner.rtl.r820t; +package io.github.dsheirer.source.tuner.rtl.r8x; -import com.fasterxml.jackson.annotation.JsonIgnore; import com.fasterxml.jackson.dataformat.xml.annotation.JacksonXmlProperty; -import io.github.dsheirer.source.tuner.TunerType; import io.github.dsheirer.source.tuner.rtl.RTL2832TunerConfiguration; /** - * RTL-2832 with embedded R820T tuner configuration + * RTL-2832 with embedded R8xxx tuner configuration */ -public class R820TTunerConfiguration extends RTL2832TunerConfiguration +public abstract class R8xTunerConfiguration extends RTL2832TunerConfiguration { - private R820TEmbeddedTuner.R820TGain mMasterGain = R820TEmbeddedTuner.R820TGain.GAIN_327; - private R820TEmbeddedTuner.R820TMixerGain mMixerGain = R820TEmbeddedTuner.R820TMixerGain.GAIN_105; - private R820TEmbeddedTuner.R820TLNAGain mLNAGain = R820TEmbeddedTuner.R820TLNAGain.GAIN_222; - private R820TEmbeddedTuner.R820TVGAGain mVGAGain = R820TEmbeddedTuner.R820TVGAGain.GAIN_210; + private R8xEmbeddedTuner.MasterGain mMasterMasterGain = R8xEmbeddedTuner.MasterGain.GAIN_327; + private R8xEmbeddedTuner.MixerGain mMixerGain = R8xEmbeddedTuner.MixerGain.GAIN_105; + private R8xEmbeddedTuner.LNAGain mLNAGain = R8xEmbeddedTuner.LNAGain.GAIN_222; + private R8xEmbeddedTuner.VGAGain mVGAGain = R8xEmbeddedTuner.VGAGain.GAIN_210; /** * Default constructor for JAXB */ - public R820TTunerConfiguration() + public R8xTunerConfiguration() { } - @JsonIgnore - @Override - public TunerType getTunerType() - { - return TunerType.RAFAELMICRO_R820T; - } - /** * Constructs an instance * * @param uniqueID for the tuner */ - public R820TTunerConfiguration(String uniqueID) + public R8xTunerConfiguration(String uniqueID) { super(uniqueID); } @JacksonXmlProperty(isAttribute = true, localName = "master_gain") - public R820TEmbeddedTuner.R820TGain getMasterGain() + public R8xEmbeddedTuner.MasterGain getMasterGain() { - return mMasterGain; + return mMasterMasterGain; } - public void setMasterGain(R820TEmbeddedTuner.R820TGain gain) + public void setMasterGain(R8xEmbeddedTuner.MasterGain masterGain) { - mMasterGain = gain; + mMasterMasterGain = masterGain; } @JacksonXmlProperty(isAttribute = true, localName = "mixer_gain") - public R820TEmbeddedTuner.R820TMixerGain getMixerGain() + public R8xEmbeddedTuner.MixerGain getMixerGain() { return mMixerGain; } - public void setMixerGain(R820TEmbeddedTuner.R820TMixerGain mixerGain) + public void setMixerGain(R8xEmbeddedTuner.MixerGain mixerGain) { mMixerGain = mixerGain; } @JacksonXmlProperty(isAttribute = true, localName = "lna_gain") - public R820TEmbeddedTuner.R820TLNAGain getLNAGain() + public R8xEmbeddedTuner.LNAGain getLNAGain() { return mLNAGain; } - public void setLNAGain(R820TEmbeddedTuner.R820TLNAGain lnaGain) + public void setLNAGain(R8xEmbeddedTuner.LNAGain lnaGain) { mLNAGain = lnaGain; } @JacksonXmlProperty(isAttribute = true, localName = "vga_gain") - public R820TEmbeddedTuner.R820TVGAGain getVGAGain() + public R8xEmbeddedTuner.VGAGain getVGAGain() { return mVGAGain; } - public void setVGAGain(R820TEmbeddedTuner.R820TVGAGain vgaGain) + public void setVGAGain(R8xEmbeddedTuner.VGAGain vgaGain) { mVGAGain = vgaGain; } diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerEditor.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerEditor.java similarity index 75% rename from src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerEditor.java rename to src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerEditor.java index bc9aa49e3..4c48e3ddd 100644 --- a/src/main/java/io/github/dsheirer/source/tuner/rtl/r820t/R820TTunerEditor.java +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/R8xTunerEditor.java @@ -16,7 +16,7 @@ * along with this program. If not, see * **************************************************************************** */ -package io.github.dsheirer.source.tuner.rtl.r820t; +package io.github.dsheirer.source.tuner.rtl.r8x; import io.github.dsheirer.preference.UserPreferences; import io.github.dsheirer.source.SourceException; @@ -25,10 +25,6 @@ import io.github.dsheirer.source.tuner.rtl.RTL2832Tuner; import io.github.dsheirer.source.tuner.rtl.RTL2832TunerController; import io.github.dsheirer.source.tuner.rtl.RTL2832TunerController.SampleRate; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TEmbeddedTuner.R820TGain; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TEmbeddedTuner.R820TLNAGain; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TEmbeddedTuner.R820TMixerGain; -import io.github.dsheirer.source.tuner.rtl.r820t.R820TEmbeddedTuner.R820TVGAGain; import io.github.dsheirer.source.tuner.ui.TunerEditor; import net.miginfocom.swing.MigLayout; import org.slf4j.Logger; @@ -40,20 +36,25 @@ import javax.swing.JLabel; import javax.swing.JOptionPane; import javax.swing.JSeparator; +import javax.swing.JToggleButton; import javax.swing.SpinnerNumberModel; import javax.usb.UsbException; -public class R820TTunerEditor extends TunerEditor +/** + * R8xxx Tuner Editor + */ +public class R8xTunerEditor extends TunerEditor { - private final static Logger mLog = LoggerFactory.getLogger(R820TTunerEditor.class); + private final static Logger mLog = LoggerFactory.getLogger(R8xTunerEditor.class); private static final long serialVersionUID = 1L; - private static final R820TGain DEFAULT_GAIN = R820TGain.GAIN_279; + private static final R8xEmbeddedTuner.MasterGain DEFAULT_GAIN = R8xEmbeddedTuner.MasterGain.GAIN_279; private JButton mTunerInfoButton; + private JToggleButton mBiasTButton; private JComboBox mSampleRateCombo; - private JComboBox mMasterGainCombo; - private JComboBox mMixerGainCombo; - private JComboBox mLNAGainCombo; - private JComboBox mVGAGainCombo; + private JComboBox mMasterGainCombo; + private JComboBox mMixerGainCombo; + private JComboBox mLNAGainCombo; + private JComboBox mVGAGainCombo; /** * Constructs an instance @@ -61,7 +62,7 @@ public class R820TTunerEditor extends TunerEditor { + if(!isLoading()) + { + getTuner().getController().setBiasT(mBiasTButton.isSelected()); + save(); + } + }); + } + + return mBiasTButton; + } + /** * Hyperlink button that provides tuner information */ @@ -200,7 +233,7 @@ private JButton getTunerInfoButton() { mTunerInfoButton = new JButton("Info"); mTunerInfoButton.setEnabled(false); - mTunerInfoButton.addActionListener(e -> JOptionPane.showMessageDialog(R820TTunerEditor.this, + mTunerInfoButton.addActionListener(e -> JOptionPane.showMessageDialog(R8xTunerEditor.this, getTunerInfo(), "Tuner Info", JOptionPane.INFORMATION_MESSAGE)); } @@ -211,13 +244,13 @@ private JComboBox getVGAGainCombo() { if(mVGAGainCombo == null) { - mVGAGainCombo = new JComboBox<>(R820TVGAGain.values()); + mVGAGainCombo = new JComboBox<>(R8xEmbeddedTuner.VGAGain.values()); mVGAGainCombo.setEnabled(false); mVGAGainCombo.addActionListener(arg0 -> { try { - R820TVGAGain vgaGain = (R820TVGAGain) mVGAGainCombo.getSelectedItem(); + R8xEmbeddedTuner.VGAGain vgaGain = (R8xEmbeddedTuner.VGAGain) mVGAGainCombo.getSelectedItem(); if(vgaGain == null) { @@ -233,9 +266,9 @@ private JComboBox getVGAGainCombo() } catch(UsbException e) { - JOptionPane.showMessageDialog(R820TTunerEditor.this, "R820T Tuner Controller - " + + JOptionPane.showMessageDialog(R8xTunerEditor.this, getLogPrefix() + "couldn't apply the VGA gain setting - " + e.getLocalizedMessage()); - mLog.error("R820T Tuner Controller - couldn't apply VGA gain setting", e); + mLog.error(getLogPrefix() + "couldn't apply VGA gain setting", e); } }); mVGAGainCombo.setToolTipText("VGA Gain. Set master gain to MANUAL to enable adjustment"); @@ -248,13 +281,13 @@ private JComboBox getLNAGainCombo() { if(mLNAGainCombo == null) { - mLNAGainCombo = new JComboBox<>(R820TLNAGain.values()); + mLNAGainCombo = new JComboBox<>(R8xEmbeddedTuner.LNAGain.values()); mLNAGainCombo.setEnabled(false); mLNAGainCombo.addActionListener(arg0 -> { try { - R820TLNAGain lnaGain = (R820TLNAGain) mLNAGainCombo.getSelectedItem(); + R8xEmbeddedTuner.LNAGain lnaGain = (R8xEmbeddedTuner.LNAGain) mLNAGainCombo.getSelectedItem(); if(lnaGain == null) { @@ -270,9 +303,9 @@ private JComboBox getLNAGainCombo() } catch(UsbException e) { - JOptionPane.showMessageDialog(R820TTunerEditor.this, "R820T Tuner Controller - " + + JOptionPane.showMessageDialog(R8xTunerEditor.this, getLogPrefix() + "couldn't apply the LNA gain setting - " + e.getLocalizedMessage()); - mLog.error("R820T Tuner Controller - couldn't apply LNA " + "gain setting - ", e); + mLog.error(getLogPrefix() + "couldn't apply LNA " + "gain setting - ", e); } }); mLNAGainCombo.setToolTipText("LNA Gain. Set master gain to MANUAL to enable adjustment"); @@ -300,11 +333,11 @@ private JComboBox getSampleRateCombo() } catch(SourceException | LibUsbException eSampleRate) { - JOptionPane.showMessageDialog(R820TTunerEditor.this, - "R820T Tuner Controller - couldn't apply the sample rate setting [" + + JOptionPane.showMessageDialog(R8xTunerEditor.this, + getLogPrefix() + "couldn't apply the sample rate setting [" + sampleRate.getLabel() + "] " + eSampleRate.getLocalizedMessage()); - mLog.error("R820T Tuner Controller - couldn't apply sample rate setting [" + sampleRate.getLabel() + + mLog.error(getLogPrefix() + "couldn't apply sample rate setting [" + sampleRate.getLabel() + "]", eSampleRate); } } @@ -318,7 +351,7 @@ private JComboBox getMixerGainCombo() { if(mMixerGainCombo == null) { - mMixerGainCombo = new JComboBox<>(R820TMixerGain.values()); + mMixerGainCombo = new JComboBox<>(R8xEmbeddedTuner.MixerGain.values()); mMixerGainCombo.setEnabled(false); mMixerGainCombo.addActionListener(arg0 -> { @@ -326,7 +359,7 @@ private JComboBox getMixerGainCombo() { try { - R820TMixerGain mixerGain = (R820TMixerGain) mMixerGainCombo.getSelectedItem(); + R8xEmbeddedTuner.MixerGain mixerGain = (R8xEmbeddedTuner.MixerGain) mMixerGainCombo.getSelectedItem(); if(mixerGain == null) { @@ -342,10 +375,10 @@ private JComboBox getMixerGainCombo() } catch(UsbException e) { - JOptionPane.showMessageDialog(R820TTunerEditor.this, "R820T Tuner Controller - " + + JOptionPane.showMessageDialog(R8xTunerEditor.this, getLogPrefix() + "couldn't apply the mixer gain setting - " + e.getLocalizedMessage()); - mLog.error("R820T Tuner Controller - couldn't apply mixer gain setting - ", e); + mLog.error(getLogPrefix() + "couldn't apply mixer gain setting - ", e); } } }); @@ -359,7 +392,7 @@ private JComboBox getMasterGainCombo() { if(mMasterGainCombo == null) { - mMasterGainCombo = new JComboBox<>(R820TGain.values()); + mMasterGainCombo = new JComboBox<>(R8xEmbeddedTuner.MasterGain.values()); mMasterGainCombo.setEnabled(false); mMasterGainCombo.addActionListener(arg0 -> { @@ -367,10 +400,10 @@ private JComboBox getMasterGainCombo() { try { - R820TGain gain = (R820TGain)getMasterGainCombo().getSelectedItem(); - getEmbeddedTuner().setGain((R820TGain)getMasterGainCombo().getSelectedItem(), true); + R8xEmbeddedTuner.MasterGain gain = (R8xEmbeddedTuner.MasterGain)getMasterGainCombo().getSelectedItem(); + getEmbeddedTuner().setGain((R8xEmbeddedTuner.MasterGain)getMasterGainCombo().getSelectedItem(), true); - if(gain == R820TGain.MANUAL) + if(gain == R8xEmbeddedTuner.MasterGain.MANUAL) { getMixerGainCombo().setSelectedItem(gain.getMixerGain()); getMixerGainCombo().setEnabled(true); @@ -397,9 +430,9 @@ private JComboBox getMasterGainCombo() } catch(UsbException e) { - JOptionPane.showMessageDialog(R820TTunerEditor.this, "R820T Tuner Controller - " + + JOptionPane.showMessageDialog(R8xTunerEditor.this, getLogPrefix() + "couldn't apply the gain setting - " + e.getLocalizedMessage()); - mLog.error("R820T Tuner Controller - couldn't apply gain setting - ", e); + mLog.error(getLogPrefix() + "couldn't apply gain setting - ", e); } } }); @@ -442,7 +475,7 @@ private String getTunerInfo() { StringBuilder sb = new StringBuilder(); RTL2832TunerController.Descriptor descriptor = getTuner().getController().getDescriptor(); - sb.append("

RTL-2832 with R820T Tuner

"); + sb.append("

RTL-2832 with " + getEmbeddedTuner().getTunerType().getLabel() + " Tuner

"); if(descriptor == null) { @@ -485,21 +518,21 @@ public void save() { if(hasConfiguration() && !isLoading()) { - R820TTunerConfiguration config = getConfiguration(); - + R8xTunerConfiguration config = getConfiguration(); + config.setBiasT(getTuner().getController().isBiasT()); config.setFrequency(getFrequencyControl().getFrequency()); double value = ((SpinnerNumberModel)getFrequencyCorrectionSpinner().getModel()).getNumber().doubleValue(); config.setFrequencyCorrection(value); config.setAutoPPMCorrectionEnabled(getAutoPPMCheckBox().isSelected()); config.setSampleRate((SampleRate)getSampleRateCombo().getSelectedItem()); - R820TGain gain = (R820TGain)getMasterGainCombo().getSelectedItem(); + R8xEmbeddedTuner.MasterGain gain = (R8xEmbeddedTuner.MasterGain)getMasterGainCombo().getSelectedItem(); config.setMasterGain(gain); - R820TMixerGain mixerGain = (R820TMixerGain)getMixerGainCombo().getSelectedItem(); + R8xEmbeddedTuner.MixerGain mixerGain = (R8xEmbeddedTuner.MixerGain)getMixerGainCombo().getSelectedItem(); config.setMixerGain(mixerGain); - R820TLNAGain lnaGain = (R820TLNAGain)getLNAGainCombo().getSelectedItem(); + R8xEmbeddedTuner.LNAGain lnaGain = (R8xEmbeddedTuner.LNAGain)getLNAGainCombo().getSelectedItem(); config.setLNAGain(lnaGain); - R820TVGAGain vgaGain = (R820TVGAGain)getVGAGainCombo().getSelectedItem(); + R8xEmbeddedTuner.VGAGain vgaGain = (R8xEmbeddedTuner.VGAGain)getVGAGainCombo().getSelectedItem(); config.setVGAGain(vgaGain); saveConfiguration(); } diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r820t/R820TEmbeddedTuner.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r820t/R820TEmbeddedTuner.java new file mode 100644 index 000000000..49444e0b1 --- /dev/null +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r820t/R820TEmbeddedTuner.java @@ -0,0 +1,85 @@ +/* + * ***************************************************************************** + * 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 + * **************************************************************************** + */ +package io.github.dsheirer.source.tuner.rtl.r8x.r820t; + +import io.github.dsheirer.source.SourceException; +import io.github.dsheirer.source.tuner.TunerType; +import io.github.dsheirer.source.tuner.rtl.RTL2832TunerController; +import io.github.dsheirer.source.tuner.rtl.r8x.R8xEmbeddedTuner; + +import javax.usb.UsbException; + +/** + * Rafael Micro R820T and R820T2 Embedded Tuner implementation + */ +public class R820TEmbeddedTuner extends R8xEmbeddedTuner +{ + private static final byte I2C_ADDRESS = (byte) 0x34; + private static final int VCO_POWER_REF = 2; + + /** + * Constructs an instance + * @param adapter for accessing RTL2832USBController interfaces + */ + public R820TEmbeddedTuner(RTL2832TunerController.ControllerAdapter adapter) + { + super(adapter, VCO_POWER_REF); + } + + @Override + public TunerType getTunerType() + { + return TunerType.RAFAELMICRO_R820T; + } + + @Override + public byte getI2CAddress() + { + return I2C_ADDRESS; + } + + /** + * Sets the center frequency. Setting the frequency is a two-part process + * of setting the multiplexer and then setting the Oscillator (PLL). + */ + @Override + public synchronized void setTunedFrequency(long frequency) throws SourceException + { + getAdapter().getLock().lock(); + + try + { + getAdapter().enableI2CRepeater(); + boolean controlI2C = false; + long offsetFrequency = frequency + IF_FREQUENCY; + setMux(offsetFrequency, controlI2C); + setPLL(offsetFrequency, controlI2C); + getAdapter().disableI2CRepeater(); + } + catch(UsbException e) + { + throw new SourceException("R820TTunerController - exception while setting frequency [" + frequency + "] - " + + e.getLocalizedMessage()); + } + finally + { + getAdapter().getLock().unlock(); + } + } +} \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r820t/R820TTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r820t/R820TTunerConfiguration.java new file mode 100644 index 000000000..9932c009f --- /dev/null +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r820t/R820TTunerConfiguration.java @@ -0,0 +1,52 @@ +/* + * ***************************************************************************** + * 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 + * **************************************************************************** + */ +package io.github.dsheirer.source.tuner.rtl.r8x.r820t; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.github.dsheirer.source.tuner.TunerType; +import io.github.dsheirer.source.tuner.rtl.r8x.R8xTunerConfiguration; + +/** + * RTL-2832 with embedded R820T tuner configuration + */ +public class R820TTunerConfiguration extends R8xTunerConfiguration +{ + /** + * Empty constructor for Jackson serialization + */ + public R820TTunerConfiguration() + { + } + + /** + * Constructs an instance + * @param uniqueId for the tuner + */ + public R820TTunerConfiguration(String uniqueId) + { + super(uniqueId); + } + + @JsonIgnore + @Override + public TunerType getTunerType() + { + return TunerType.RAFAELMICRO_R820T; + } +} diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r828d/R828DEmbeddedTuner.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r828d/R828DEmbeddedTuner.java new file mode 100644 index 000000000..910c1f04f --- /dev/null +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r828d/R828DEmbeddedTuner.java @@ -0,0 +1,127 @@ +/* + * ***************************************************************************** + * 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 + * **************************************************************************** + */ +package io.github.dsheirer.source.tuner.rtl.r8x.r828d; + +import io.github.dsheirer.source.SourceException; +import io.github.dsheirer.source.tuner.TunerType; +import io.github.dsheirer.source.tuner.rtl.RTL2832TunerController; +import io.github.dsheirer.source.tuner.rtl.r8x.R8xEmbeddedTuner; + +import javax.usb.UsbException; + +/** + * Rafael Micro R828D Embedded Tuner implementation + */ +public class R828DEmbeddedTuner extends R8xEmbeddedTuner +{ + private static final byte I2C_ADDRESS = (byte) 0x74; + private static final int VCO_POWER_REF = 1; + /** + * RTL-SDR.com blog V4 dongle indicator. + */ + private final boolean mIsV4Dongle; + + /** + * Constructs an instance + * @param adapter for accessing RTL2832USBController interfaces + */ + public R828DEmbeddedTuner(RTL2832TunerController.ControllerAdapter adapter) + { + super(adapter, VCO_POWER_REF); + + //Set flag to indicate if this is a V4 dongle that supports notch filtering. + mIsV4Dongle = adapter.isV4Dongle(); + } + + @Override + public TunerType getTunerType() + { + return TunerType.RAFAELMICRO_R828D; + } + + @Override + public byte getI2CAddress() + { + return I2C_ADDRESS; + } + + /** + * Sets the center frequency. Setting the frequency is a two-part process + * of setting the multiplexer and then setting the Oscillator (PLL). + */ + @Override + public synchronized void setTunedFrequency(long frequency) throws SourceException + { + getAdapter().getLock().lock(); + + try + { + getAdapter().enableI2CRepeater(); + boolean controlI2C = false; + long offsetFrequency = frequency + IF_FREQUENCY; + setMux(offsetFrequency, controlI2C); + setPLL(offsetFrequency, controlI2C); + + //Select the RF input + if(mIsV4Dongle) + { + //Disable notch filtering if frequency falls into a notched band, otherwise enable it. + boolean isNotchFilterFrequency = (frequency < 2_200_000) || + (85_000_000 < frequency && frequency < 112_000_000) || + (172_000_000 < frequency && frequency < 242_000_000); + writeRegister(Register.DRAIN, isNotchFilterFrequency ? (byte)0x00 : (byte)0x08, controlI2C); + + if(frequency <= 28_800_000) //Use cable 2 input + { + writeRegister(Register.INPUT_SELECTOR_AIR, (byte)0x20, controlI2C); //disabled + writeRegister(Register.INPUT_SELECTOR_CABLE_1, (byte)0x00, controlI2C); //disabled + writeRegister(Register.INPUT_SELECTOR_CABLE_2, (byte)0x08, controlI2C); //enabled + } + else if(frequency < 250_000_000) + { + writeRegister(Register.INPUT_SELECTOR_AIR, (byte)0x20, controlI2C); //disabled + writeRegister(Register.INPUT_SELECTOR_CABLE_1, (byte)0x40, controlI2C); //enabled + writeRegister(Register.INPUT_SELECTOR_CABLE_2, (byte)0x00, controlI2C); //disabled + } + else + { + writeRegister(Register.INPUT_SELECTOR_AIR, (byte)0x00, controlI2C); //enabled + writeRegister(Register.INPUT_SELECTOR_CABLE_1, (byte)0x00, controlI2C); //disabled + writeRegister(Register.INPUT_SELECTOR_CABLE_2, (byte)0x00, controlI2C); //disabled + } + } + else + { + byte air_cable_in = (frequency > 345_000_000) ? (byte)0x00 : (byte)0x60; + writeRegister(Register.INPUT_SELECTOR_AIR_AND_CABLE_1, air_cable_in, controlI2C); + } + + getAdapter().disableI2CRepeater(); + } + catch(UsbException e) + { + throw new SourceException("R820TTunerController - exception while setting frequency [" + frequency + "] - " + + e.getLocalizedMessage()); + } + finally + { + getAdapter().getLock().unlock(); + } + } +} \ No newline at end of file diff --git a/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r828d/R828DTunerConfiguration.java b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r828d/R828DTunerConfiguration.java new file mode 100644 index 000000000..90710959f --- /dev/null +++ b/src/main/java/io/github/dsheirer/source/tuner/rtl/r8x/r828d/R828DTunerConfiguration.java @@ -0,0 +1,52 @@ +/* + * ***************************************************************************** + * 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 + * **************************************************************************** + */ +package io.github.dsheirer.source.tuner.rtl.r8x.r828d; + +import com.fasterxml.jackson.annotation.JsonIgnore; +import io.github.dsheirer.source.tuner.TunerType; +import io.github.dsheirer.source.tuner.rtl.r8x.R8xTunerConfiguration; + +/** + * RTL-2832 with embedded R828D tuner configuration + */ +public class R828DTunerConfiguration extends R8xTunerConfiguration +{ + /** + * Empty constructor for Jackson serialization + */ + public R828DTunerConfiguration() + { + } + + /** + * Constructs an instance + * @param uniqueId for the tuner + */ + public R828DTunerConfiguration(String uniqueId) + { + super(uniqueId); + } + + @JsonIgnore + @Override + public TunerType getTunerType() + { + return TunerType.RAFAELMICRO_R828D; + } +}