From 7700ec324d4318765b3b7ef48f6634f855dc23c1 Mon Sep 17 00:00:00 2001 From: rtlsdrblog Date: Fri, 19 May 2023 00:38:05 +1200 Subject: [PATCH] various changes tidy up code, add manufacturer/model test for r828d, tuner hack testing --- include/tuner_r82xx.h | 3 + src/librtlsdr.c | 35 ++++++- src/tuner_r82xx.c | 232 +++++++++++++++++++++--------------------- 3 files changed, 153 insertions(+), 117 deletions(-) diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h index 2dffa28..8e41ec4 100644 --- a/include/tuner_r82xx.h +++ b/include/tuner_r82xx.h @@ -82,6 +82,9 @@ struct r82xx_priv { uint32_t int_freq; uint8_t fil_cal_code; uint8_t input; + int gain; + int gain_manual_mode; + int gain_sensitivity_mode; int has_lock; int init_done; diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 2a0b988..0e76ce9 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -165,6 +165,8 @@ struct rtlsdr_dev { unsigned int xfer_errors; int force_bt; int force_ds; + char manufact[256]; + char product[256]; }; void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val); @@ -1204,7 +1206,16 @@ int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on) if (!dev) return -1; - return rtlsdr_demod_write_reg(dev, 0, 0x19, on ? 0x25 : 0x05, 1); + /* testing: + * replaceme the useless RTL AGC function with a function that + implements max LNA gain for sensitivity when on */ + rtlsdr_set_i2c_repeater(dev, 1); + sensitivity_mode_toggle(&dev->r82xx_p, on); + rtlsdr_set_i2c_repeater(dev, 0); + + return 0; + + //return rtlsdr_demod_write_reg(dev, 0, 0x19, on ? 0x25 : 0x05, 1); } int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on) @@ -1483,6 +1494,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(rtlsdr_dev_t *dev, char* manufact_check, char* product_check) { + if ((strcmp(dev->manufact, manufact_check) == 0 && strcmp(dev->product, product_check) == 0)) + { + return 1; + } + + return 0; +} + int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index) { int r; @@ -1609,6 +1630,12 @@ 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; } @@ -1642,7 +1669,11 @@ found: 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 */ diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c index d7879a0..f69e590 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -33,9 +33,12 @@ #define MHZ(x) ((x)*1000*1000) #define KHZ(x) ((x)*1000) -#define HF 0x10 -#define VHF 0x20 -#define UHF 0x30 +#define HF 1 +#define VHF 2 +#define UHF 3 + +#define NOTCH_FILTERS_OFF 100 +#define NOTCH_FILTERS_ON 200 /* * Static constants @@ -959,10 +962,12 @@ static const int r82xx_mixer_gain_steps[] = { int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain) { int rc; + priv->gain = gain; + priv->gain_manual_mode = set_manual_gain; if (set_manual_gain) { int i, total_gain = 0; - uint8_t mix_index = 0, lna_index = 0; + uint8_t mix_index = 0, lna_index = 0, vga_index = 0; uint8_t data[4]; /* LNA auto off */ @@ -970,7 +975,7 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain) if (rc < 0) return rc; - /* Mixer auto off */ + /* Mixer auto off */ rc = r82xx_write_reg_mask(priv, 0x07, 0, 0x10); if (rc < 0) return rc; @@ -980,24 +985,40 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain) return rc; /* set fixed VGA gain for now (16.3 dB) */ + //rc = r82xx_write_reg_mask(priv, 0x0c, 0x08, 0x9f); rc = r82xx_write_reg_mask(priv, 0x0c, 0x08, 0x9f); //init val 0x08 0x0c works well at 1.7 + if (rc < 0) return rc; - for (i = 0; i < 15; i++) { - if (total_gain >= gain) - break; - - total_gain += r82xx_lna_gain_steps[++lna_index]; - - if (total_gain >= gain) - break; - - total_gain += r82xx_mixer_gain_steps[++mix_index]; + if (priv->gain_sensitivity_mode) + { + mix_index = (int)(gain / 33); + lna_index = 15; } + else + { + for (i = 0; i < 15; i++) { + if (total_gain >= gain) + break; + + total_gain += r82xx_lna_gain_steps[++lna_index]; + //total_gain += r82xx_vga_gain_steps[++vga_index]; + + if (total_gain >= gain) + break; + + total_gain += r82xx_mixer_gain_steps[++mix_index]; + } + } + + fprintf(stdout, "Gain: %i", gain); + fprintf(stdout, "Mix Index: %i", mix_index); + fprintf(stdout, "LNA Index: %i", lna_index); /* set LNA gain */ rc = r82xx_write_reg_mask(priv, 0x05, lna_index, 0x0f); + //rc = r82xx_write_reg_mask(priv, 0x05, 0x0f, 0x0f); if (rc < 0) return rc; @@ -1005,7 +1026,8 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain) rc = r82xx_write_reg_mask(priv, 0x07, mix_index, 0x0f); if (rc < 0) return rc; - } else { + } + else { /* LNA */ rc = r82xx_write_reg_mask(priv, 0x05, 0, 0x10); if (rc < 0) @@ -1101,21 +1123,39 @@ int r82xx_set_bandwidth(struct r82xx_priv *priv, int bw, uint32_t rate) #undef FILT_HP_BW1 #undef FILT_HP_BW2 -// Changes to support new r828d dongle versions +int sensitivity_mode_toggle(struct r82xx_priv *priv, int toggle) +{ + int rc; + + if (toggle) + { + //fprintf(stdout, "TOGGLE ON"); + priv->gain_sensitivity_mode = 1; + r82xx_set_gain(priv, priv->gain_manual_mode, priv->gain); + //rc = r82xx_write_reg_mask(priv, 0x06, 0x10, 0x10); + } + else + { + priv->gain_sensitivity_mode = 0; + //fprintf(stdout, "TOGGLE OFF"); + r82xx_set_gain(priv, priv->gain_manual_mode, priv->gain); + //rc = r82xx_write_reg_mask(priv, 0x06, 0x00, 0x10); + } + + return rc; +} + int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq) { int rc = -1; + int is_rtlsdr_blog_v4 = rtlsdr_check_dongle_model(priv->rtl_dev, "RTLSDRBlog", "Blog V4"); - // Automatically upconvert to 28.8 MHz if we tune to HF so we don't need to set any upconvert offset in the SDR software - uint32_t upconvert_freq = freq; - if (freq < MHZ(28.8)) - { - upconvert_freq = upconvert_freq + MHZ(28.8); - } + /* 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 */ + uint32_t upconvert_freq = is_rtlsdr_blog_v4 ? ((freq < MHZ(28.8)) ? (freq + MHZ(28.8)) : freq) : freq; uint32_t lo_freq = upconvert_freq + priv->int_freq; uint8_t air_cable1_in; - uint8_t cable2_in; rc = r82xx_set_mux(priv, lo_freq); if (rc < 0) @@ -1125,101 +1165,63 @@ int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq) if (rc < 0 || !priv->has_lock) goto err; - - // Set open_d notches automatically - if (freq <= MHZ(2.2) - || (freq >= MHZ(85) && freq <= MHZ(112)) // Notch off until 112 because of roll off - || (freq >= MHZ(172) && freq <= MHZ(242))) + if (is_rtlsdr_blog_v4) { - rc = r82xx_write_reg_mask(priv, 0x17, 0x00, 0x08); // open_d hi_z (notches off) - } - else - { - rc = r82xx_write_reg_mask(priv, 0x17, 0x08, 0x08); // open_d low_z (notches on) - } - if (rc < 0) - goto err; - - // HF -> Cable_2 - // VHF -> Cable_1 - // UHF -> Air_in - - /* 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. - Modded to switch at 300 MHz */ - - - // Only switch if there is a band change (to avoid excessive register writes when tuning rapidly) - int band = 0x00; - if (freq <= MHZ(28.8)) - { - band = HF; // HF - } - else if (freq > MHZ(28.8) && freq < MHZ(300)) // VHF Tuner Input - { - band = VHF; - } - else // UHF Tuner Input - { - band = UHF; - } - - - if ((priv->cfg->rafael_chip == CHIP_R828D) && (band != priv->input)) - { - priv->input = band; - - // Turn LT OFF to save power - rc = r82xx_write_reg_mask(priv, 0x05, 0x80, 0x80); - if (rc < 0) - goto err; - - // Turn open_d off - //rc = r82xx_write_reg_mask(priv, 0x17, 0x00, 0x08); - - - //HF - if (band == HF) //(freq < MHZ(28.8)) - { - // Switch in Cable 2 - rc = r82xx_write_reg_mask(priv, 0x06, 0x08, 0x08); - } - else - { - // Switch out Cable 2 - rc = r82xx_write_reg_mask(priv, 0x06, 0x00, 0x08); - } - - // VHF - // Activate Cable_1 input between 28.8 -> 400 MHz. - if (band == VHF) - { - rc = r82xx_write_reg_mask(priv, 0x05, 0x40, 0x40); - // This register setting appears to enhance Cable 1 input by 2dB - rc = r82xx_write_reg_mask(priv, 0x06, 0x04, 0x04); - } - else - { - rc = r82xx_write_reg_mask(priv, 0x05, 0x00, 0x40); - // Turn off the Cable_1 enhancement (off) - rc = r82xx_write_reg_mask(priv, 0x06, 0x00, 0x04); - } - - if (band == UHF) - { - //Turn air_in LNA ON - rc = r82xx_write_reg_mask(priv, 0x05, 0x00, 0x20); - } - else - { - // Otherwise turn it off to save power (as it uses a lot of power) - rc = r82xx_write_reg_mask(priv, 0x05, 0x20, 0x20); - } + /* 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. + */ + uint8_t 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) - goto err; + 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) */ + uint8_t band = (freq <= MHZ(28.8)) ? HF : ((freq > MHZ(28.8) && freq < MHZ(300)) ? VHF : UHF); + + /* switch between tuner inputs on the RTL-SDR Blog V4 */ + if (band != priv->input) + { + priv->input = band; + + /* activate cable 2 (HF input) */ + uint8_t cable_2_in = (band == HF) ? 0x08 : 0x00; + rc = r82xx_write_reg_mask(priv, 0x06, cable_2_in, 0x08); + + /* activate cable 1 (VHF input) */ + uint8_t cable_1_in = (band == VHF) ? 0x40 : 0x00; + rc = r82xx_write_reg_mask(priv, 0x05, cable_1_in, 0x40); + + /* this register appears to boost cable 1 SNR slightly */ + //uint8_t cable_1_enhance = (band == VHF) ? 0x04 : 0x00; + //rc = r82xx_write_reg_mask(priv, 0x06, cable_1_enhance, 0x04); + + /* activate air_in (UHF input) */ + uint8_t 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: if (rc < 0)