Skip to content

Commit

Permalink
add rtl-sdr blog v4 support
Browse files Browse the repository at this point in the history
  • Loading branch information
rtlsdrblog authored and steve-m committed Aug 22, 2023
1 parent 142325a commit 1261fbb
Show file tree
Hide file tree
Showing 3 changed files with 97 additions and 11 deletions.
1 change: 1 addition & 0 deletions include/rtlsdr_i2c.h
Original file line number Diff line number Diff line change
@@ -1,6 +1,7 @@
#ifndef __I2C_H
#define __I2C_H

int rtlsdr_check_dongle_model(void *dev, char *manufact_check, char *product_check);
uint32_t rtlsdr_get_tuner_clock(void *dev);
int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len);
int rtlsdr_i2c_read_fn(void *dev, uint8_t addr, uint8_t *buf, int len);
Expand Down
24 changes: 23 additions & 1 deletion src/librtlsdr.c
Original file line number Diff line number Diff line change
Expand Up @@ -119,6 +119,8 @@ struct rtlsdr_dev {
int dev_lost;
int driver_active;
unsigned int xfer_errors;
char manufact[256];
char product[256];
};

void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val);
Expand Down Expand Up @@ -1430,6 +1432,16 @@ int rtlsdr_get_index_by_serial(const char *serial)
return -3;
}

/* Returns true if the manufact_check and product_check strings match what is in the dongles EEPROM */
int rtlsdr_check_dongle_model(void *dev, char *manufact_check, char *product_check)
{
if ((strcmp(((rtlsdr_dev_t *)dev)->manufact, manufact_check) == 0&& strcmp(((rtlsdr_dev_t *)dev)->product, product_check) == 0))
return 1;

return 0;
}


int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
{
int r;
Expand Down Expand Up @@ -1528,6 +1540,9 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
rtlsdr_init_baseband(dev);
dev->dev_lost = 0;

/* Get device manufacturer and product id */
r = rtlsdr_get_usb_strings(dev, dev->manufact, dev->product, NULL);

/* Probe tuners */
rtlsdr_set_i2c_repeater(dev, 1);

Expand Down Expand Up @@ -1555,6 +1570,10 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
reg = rtlsdr_i2c_read_reg(dev, R828D_I2C_ADDR, R82XX_CHECK_ADDR);
if (reg == R82XX_CHECK_VAL) {
fprintf(stderr, "Found Rafael Micro R828D tuner\n");

if (rtlsdr_check_dongle_model(dev, "RTLSDRBlog", "Blog V4"))
fprintf(stderr, "RTL-SDR Blog V4 Detected\n");

dev->tuner_type = RTLSDR_TUNER_R828D;
goto found;
}
Expand Down Expand Up @@ -1588,7 +1607,10 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)

switch (dev->tuner_type) {
case RTLSDR_TUNER_R828D:
dev->tun_xtal = R828D_XTAL_FREQ;
/* If NOT an RTL-SDR Blog V4, set typical R828D 16 MHz freq. Otherwise, keep at 28.8 MHz. */
if (!(rtlsdr_check_dongle_model(dev, "RTLSDRBlog", "Blog V4"))) {
dev->tun_xtal = R828D_XTAL_FREQ;
}
/* fall-through */
case RTLSDR_TUNER_R820T:
/* disable Zero-IF mode */
Expand Down
83 changes: 73 additions & 10 deletions src/tuner_r82xx.c
Original file line number Diff line number Diff line change
Expand Up @@ -33,6 +33,10 @@
#define MHZ(x) ((x)*1000*1000)
#define KHZ(x) ((x)*1000)

#define HF 1
#define VHF 2
#define UHF 3

/*
* Static constants
*/
Expand Down Expand Up @@ -1098,8 +1102,23 @@ int r82xx_set_bandwidth(struct r82xx_priv *priv, int bw, uint32_t rate)
int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq)
{
int rc = -1;
uint32_t lo_freq = freq + priv->int_freq;
int is_rtlsdr_blog_v4;
uint32_t upconvert_freq;
uint32_t lo_freq;
uint8_t air_cable1_in;
uint8_t open_d;
uint8_t band;
uint8_t cable_2_in;
uint8_t cable_1_in;
uint8_t air_in;

is_rtlsdr_blog_v4 = rtlsdr_check_dongle_model(priv->rtl_dev, "RTLSDRBlog", "Blog V4");

/* if it's an RTL-SDR Blog V4, automatically upconvert by 28.8 MHz if we tune to HF
* so that we don't need to manually set any upconvert offset in the SDR software */
upconvert_freq = is_rtlsdr_blog_v4 ? ((freq < MHZ(28.8)) ? (freq + MHZ(28.8)) : freq) : freq;

lo_freq = upconvert_freq + priv->int_freq;

rc = r82xx_set_mux(priv, lo_freq);
if (rc < 0)
Expand All @@ -1109,16 +1128,60 @@ int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq)
if (rc < 0 || !priv->has_lock)
goto err;

/* switch between 'Cable1' and 'Air-In' inputs on sticks with
* R828D tuner. We switch at 345 MHz, because that's where the
* noise-floor has about the same level with identical LNA
* settings. The original driver used 320 MHz. */
air_cable1_in = (freq > MHZ(345)) ? 0x00 : 0x60;
if (is_rtlsdr_blog_v4) {
/* determine if notch filters should be on or off notches are turned OFF
* when tuned within the notch band and ON when tuned outside the notch band.
*/
open_d = (freq <= MHZ(2.2) || (freq >= MHZ(85) && freq <= MHZ(112)) || (freq >= MHZ(172) && freq <= MHZ(242))) ? 0x00 : 0x08;
rc = r82xx_write_reg_mask(priv, 0x17, open_d, 0x08);

if (rc < 0)
return rc;

/* select tuner band based on frequency and only switch if there is a band change
*(to avoid excessive register writes when tuning rapidly)
*/
band = (freq <= MHZ(28.8)) ? HF : ((freq > MHZ(28.8) && freq < MHZ(250)) ? VHF : UHF);

/* switch between tuner inputs on the RTL-SDR Blog V4 */
if (band != priv->input) {
priv->input = band;

/* activate cable 2 (HF input) */
cable_2_in = (band == HF) ? 0x08 : 0x00;
rc = r82xx_write_reg_mask(priv, 0x06, cable_2_in, 0x08);

if ((priv->cfg->rafael_chip == CHIP_R828D) &&
(air_cable1_in != priv->input)) {
priv->input = air_cable1_in;
rc = r82xx_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);
if (rc < 0)
goto err;

/* activate cable 1 (VHF input) */
cable_1_in = (band == VHF) ? 0x40 : 0x00;
rc = r82xx_write_reg_mask(priv, 0x05, cable_1_in, 0x40);

if (rc < 0)
goto err;

/* activate air_in (UHF input) */
air_in = (band == UHF) ? 0x00 : 0x20;
rc = r82xx_write_reg_mask(priv, 0x05, air_in, 0x20);

if (rc < 0)
goto err;
}
}
else /* Standard R828D dongle*/
{
/* switch between 'Cable1' and 'Air-In' inputs on sticks with
* R828D tuner. We switch at 345 MHz, because that's where the
* noise-floor has about the same level with identical LNA
* settings. The original driver used 320 MHz. */
air_cable1_in = (freq > MHZ(345)) ? 0x00 : 0x60;

if ((priv->cfg->rafael_chip == CHIP_R828D) &&
(air_cable1_in != priv->input)) {
priv->input = air_cable1_in;
rc = r82xx_write_reg_mask(priv, 0x05, air_cable1_in, 0x60);
}
}

err:
Expand Down

0 comments on commit 1261fbb

Please sign in to comment.