Skip to content

Commit

Permalink
Merge pull request #1679 from DSheirer/1643-r828d-v4-tuner
Browse files Browse the repository at this point in the history
#1643 RTL2832/R828D aka RTL-SDR V4 Dongle & Bias-T Support
  • Loading branch information
DSheirer committed Oct 22, 2023
2 parents 9468fd1 + 0d652b9 commit a27ddbe
Show file tree
Hide file tree
Showing 12 changed files with 874 additions and 466 deletions.
16 changes: 11 additions & 5 deletions src/main/java/io/github/dsheirer/source/tuner/TunerFactory.java
Expand Up @@ -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;
Expand Down Expand Up @@ -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);
};
}

Expand All @@ -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:
Expand Down Expand Up @@ -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);
Expand Down
@@ -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
Expand Down Expand Up @@ -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;

/**
Expand All @@ -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")
Expand Down
@@ -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
Expand All @@ -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
Expand All @@ -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
Expand All @@ -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;
}
}
@@ -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
Expand Down Expand Up @@ -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();

/**
Expand Down Expand Up @@ -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)
{
Expand All @@ -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)
{
Expand Down Expand Up @@ -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));
Expand Down Expand Up @@ -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.
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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
Expand Down Expand Up @@ -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);
}

/**
Expand All @@ -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)
Expand All @@ -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);
}

/**
Expand All @@ -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);
}

/**
Expand Down Expand Up @@ -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);
Expand All @@ -740,7 +761,7 @@ else if(length == 2)
}

buffer.rewind();
write(address, block, buffer);
write(address.getAddress(), block, buffer);
}

/**
Expand All @@ -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)
Expand Down Expand Up @@ -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)
Expand Down Expand Up @@ -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 */
Expand All @@ -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);
}
}

Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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
Expand All @@ -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;

Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit a27ddbe

Please sign in to comment.