I've just released a new R828D based dongle and it needs some code changes to work. It would be great if the osmocom drivers could support it.
The dongle is based on the R828D chip, but unlike prior R828D dongles which use 16 MHz, the V4 uses a 28.8 MHz LO. Also the three RF inputs are used, and connected via a triplexer to separate them into HF, VHF and UHF bands. Finally, the open_d pin is also used to activate some notch filters for common interference bands.
I've written the code so it detects an EEPROM string in the V4, and only applies the new code if that exists. This makes sure that the older R828D based dongles still work.
I'm not too familiar with the patch submission process, so please let me know if something needs to be changed. And if anyone on the team needs/wants some new V4 dongles for testing, please let me know too.
Thanks, Carl
diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 096abae..d624732 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -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); @@ -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(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; @@ -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);
@@ -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; } @@ -1588,7 +1607,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"))) { + fprintf(stdout, "setting 16mhz"); + 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 997abd7..9b831f4 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -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 */ @@ -1098,7 +1102,14 @@ 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 = 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 */ + 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;
rc = r82xx_set_mux(priv, lo_freq); @@ -1109,16 +1120,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. + */ + 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) + 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(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) */ + uint8_t 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) */ + uint8_t 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) */ + 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:
Hi Carl,
On 18.08.23 08:34, Carl Laufer wrote:
I've just released a new R828D based dongle and it needs some code changes to work. It would be great if the osmocom drivers could support it.
The dongle is based on the R828D chip, but unlike prior R828D dongles which use 16 MHz, the V4 uses a 28.8 MHz LO. Also the three RF inputs are used, and connected via a triplexer to separate them into HF, VHF and UHF bands. Finally, the open_d pin is also used to activate some notch filters for common interference bands.
I've written the code so it detects an EEPROM string in the V4, and only applies the new code if that exists. This makes sure that the older R828D based dongles still work.
I'm not too familiar with the patch submission process, so please let me know if something needs to be changed. And if anyone on the team needs/wants some new V4 dongles for testing, please let me know too.
Okay, sounds good, I would like to merge the patch.
Unfortunately your mail seems to have been sent as HTML mail and all intendations are broken, so I cannot amend your patch. Can you please send it again in the git format-patch format or as an attachment?
Regards, Steve
Hi Steve,
Awesome thanks! I've attached the patch file here, hopefully this works. I've made some additional changes to remove the compiler warnings the previous patch was giving too.
If you or anyone at Osmocom needs a V4 unit for testing please send me an email privately with address details.
Regards, Carl
On Tue, Aug 22, 2023 at 12:58 AM Steve Markgraf steve@steve-m.de wrote:
Hi Carl,
On 18.08.23 08:34, Carl Laufer wrote:
I've just released a new R828D based dongle and it needs some code changes to work. It would be great if the osmocom drivers could support
it.
The dongle is based on the R828D chip, but unlike prior R828D dongles which use 16 MHz, the V4 uses a 28.8 MHz LO. Also the three RF inputs are used, and connected via a triplexer to separate them into HF, VHF and UHF bands. Finally, the open_d pin is also used to activate some notch filters for common interference bands.
I've written the code so it detects an EEPROM string in the V4, and only applies the new code if that exists. This makes sure that the older R828D based dongles still work.
I'm not too familiar with the patch submission process, so please let me know if something needs to be changed. And if anyone on the team needs/wants some new V4 dongles for testing, please let me know too.
Okay, sounds good, I would like to merge the patch.
Unfortunately your mail seems to have been sent as HTML mail and all intendations are broken, so I cannot amend your patch. Can you please send it again in the git format-patch format or as an attachment?
Regards, Steve
Hi Carl
On 22.08.23 04:16, Carl Laufer wrote:
Awesome thanks! I've attached the patch file here, hopefully this works. I've made some additional changes to remove the compiler warnings the previous patch was giving too.
I merged the commit, but changed two things:
- Removed a printf to stdout (there are tools aquiring samples through a pipe using rtl_sdr with '-' as filename for stdout output, this would set them off).
- Moved the definition of rtlsdr_check_dongle_model() to the 'tuner api' header rtlsdr_i2c.h - although also not exactly fitting, this is better than having in in tuner_r82xx.h.
Now that I think of it, I probably should have put that in the commit message...
Regards, Steve
Thanks! Yeah those changes are sensible, I wasn't sure what header file to use, and the printf is left over from debugging.
I guess my next question is, can anyone update the old Windows build zip at https://osmocom.org/attachments/2242 as software like SDR# pulls rtlsdr.dll from that via a bat file? I guess they should really pull from the weekly builds, but that probably complicates the bat file a little since it needs to track the latest build date and rename librtlsdr.dll to rtlsdr.dll.
And secondly, how often does the rtl-sdr apt-get package on Linux get updated, and who would need to be informed for that to happen?
Regards, Carl
On Wed, Aug 23, 2023 at 10:42 AM Steve Markgraf steve@steve-m.de wrote:
Hi Carl
On 22.08.23 04:16, Carl Laufer wrote:
Awesome thanks! I've attached the patch file here, hopefully this works. I've made some additional changes to remove the compiler warnings the previous patch was giving too.
I merged the commit, but changed two things:
- Removed a printf to stdout (there are tools aquiring samples through a
pipe using rtl_sdr with '-' as filename for stdout output, this would set them off).
- Moved the definition of rtlsdr_check_dongle_model() to the 'tuner api'
header rtlsdr_i2c.h - although also not exactly fitting, this is better than having in in tuner_r82xx.h.
Now that I think of it, I probably should have put that in the commit message...
Regards, Steve
Hi Carl,
On Wed, Aug 23, 2023 at 02:43:22PM +1200, Carl Laufer wrote:
I guess my next question is, can anyone update the old Windows build zip at https://osmocom.org/attachments/2242 as software like SDR# pulls rtlsdr.dll from that via a bat file? I guess they should really pull from the weekly builds, but that probably complicates the bat file a little since it needs to track the latest build date and rename librtlsdr.dll to rtlsdr.dll.
I'm not really the best person to say anything regarding Windows support. If you register an osmocom.org wiki account, I'm happy to give you wiki editing permissions.
The way how redmine works though is that the attachment 2242 is that one old version that was uploaded. If you remove it and upload a new version, it will have a different attachment number.
What we can do is to have something like a symlink from https://ftp.osmocom.org/binaries/windows/rtl-sdr/rtl-sdr-64bit-weekly.zip and https://ftp.osmocom.org/binaries/windows/rtl-sdr/rtl-sdr-32bit-weekly.zip which then points to whatever is the most current weekly version. This way any 3rd party software should be updated to use those links.
If this sounds like a good idea, feel free to create a related issue on osmocom.org and assign it to user osmith, who is doing most of our CI related work.
And secondly, how often does the rtl-sdr apt-get package on Linux get updated, and who would need to be informed for that to happen?
This depends on where the package originates from. It's usually safe to assume most people use the package from the respective distribution, so the policy of if and when that gets updated relies with Debian, Ubuntu, etc. for the given release (like Debian 10, 11, 12).
In addition, osmocom is publishing its own package feeds for a variety of Linux distributions; one for the latest (released) version, and one for a nightly build, see https://osmocom.org/projects/cellular-infrastructure/wiki/Latest_Builds and https://osmocom.org/projects/cellular-infrastructure/wiki/Nightly_Builds respectively.
For the nightly build, your patch is already included. For the "latest", it depends on when steve-m decides to tag a new version of rtl-sdr. The latest package then gets automatically updated.