This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/osmocom-sdr@lists.osmocom.org/.
Luigi Tarenga luigi.tarenga at gmail.comhello list, with this patch I try to start adding support for independent gain setting to rtl-sdr. If this will go on (after review of course) I will be able to send a patch for gr-osmosdr to expose those controls to end user applications like gqrx. I see some users wish to experiment with manual tuning like it's possible to do on SDR# with airspy dongle that use R820T tuner. I see some users started their own tree to add this. There will be some complexity added but I think this can be masked with a proper patching of gr-osmosdr to no break compatibility with existing software and let users get the old control layout. In a future patch I wish to add: - single automatic gain control. I ask if it's ok to expose a function like rtlsdr_set_tuner_gain_mode() and internally recycle the function added by this patch but with a new *mode* parameter. - optimized gain for *max sensitivity* and *max linearity* like those found in airspy code. here I ask if is fine to expose gains as just integers instead of tenth of dB. best regards Luigi Signed-off-by: Luigi Tarenga <luigi.tarenga at gmail.com> --- include/rtl-sdr.h | 62 ++++++++++++++++++++++++++ include/tuner_r82xx.h | 3 ++ src/librtlsdr.c | 120 +++++++++++++++++++++++++++++++++++++++++++++++--- src/tuner_r82xx.c | 53 +++++++++++++++++++++- 4 files changed, 230 insertions(+), 8 deletions(-) diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index fe64bea..2eec99c 100644 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -216,6 +216,41 @@ RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains); RTLSDR_API int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain); /*! + * Set the LNA gain for the device. + * + * Valid gain values for the R820T tuner are from 0 to 15. + * + * \param dev the device handle given by rtlsdr_open() + * \param gain between 0 and 15. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_lna_gain(rtlsdr_dev_t *dev, int gain); + +/*! + * Set the Mixer gain for the device. + * Manual gain mode must be enabled for this to work. + * + * Valid gain values for the R820T tuner are from 0 to 15. + * + * \param dev the device handle given by rtlsdr_open() + * \param gain between 0 and 15. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_mix_gain(rtlsdr_dev_t *dev, int gain); + +/*! + * Set the VGA gain for the device. + * Manual gain mode must be enabled for this to work. + * + * Valid gain values for the R820T tuner are from 0 to 15. + * + * \param dev the device handle given by rtlsdr_open() + * \param gain between 0 and 15. + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_tuner_vga_gain(rtlsdr_dev_t *dev, int gain); + +/*! * Set the bandwidth for the device. * * \param dev the device handle given by rtlsdr_open() @@ -233,6 +268,33 @@ RTLSDR_API int rtlsdr_set_tuner_bandwidth(rtlsdr_dev_t *dev, uint32_t bw); RTLSDR_API int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev); /*! + * Get actual LNA gain the device is configured to. + * The LNA gain must have been set with \ref rtlsdr_set_tuner_lna_gain function. + * + * \param dev the device handle given by rtlsdr_open() + * \return -1 on error, LNA gain register value (0 to 15 for R820T). + */ +RTLSDR_API int rtlsdr_get_tuner_lna_gain(rtlsdr_dev_t *dev); + +/*! + * Get actual Mixer gain the device is configured to. + * The Mixer gain must have been set with \ref rtlsdr_set_tuner_mix_gain function. + * + * \param dev the device handle given by rtlsdr_open() + * \return -1 on error, Mixer gain register value (0 to 15 for R820T). + */ +RTLSDR_API int rtlsdr_get_tuner_mix_gain(rtlsdr_dev_t *dev); + +/*! + * Get actual VGA gain the device is configured to. + * The VGA gain must have been set with \ref rtlsdr_set_tuner_vga_gain function. + * + * \param dev the device handle given by rtlsdr_open() + * \return -1 on error, VGA gain register value (0 to 15 for R820T). + */ +RTLSDR_API int rtlsdr_get_tuner_vga_gain(rtlsdr_dev_t *dev); + +/*! * Set the intermediate frequency gain for the device. * * \param dev the device handle given by rtlsdr_open() diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h index f6c206a..3ddb9c6 100644 --- a/include/tuner_r82xx.h +++ b/include/tuner_r82xx.h @@ -115,6 +115,9 @@ int r82xx_standby(struct r82xx_priv *priv); int r82xx_init(struct r82xx_priv *priv); int r82xx_set_freq(struct r82xx_priv *priv, uint32_t freq); int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain); +int r82xx_set_lna_gain(struct r82xx_priv *priv, int gain); +int r82xx_set_mix_gain(struct r82xx_priv *priv, int gain); +int r82xx_set_vga_gain(struct r82xx_priv *priv, int gain); int r82xx_set_bandwidth(struct r82xx_priv *priv, int bandwidth, uint32_t rate); #endif diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 9b7ba52..10556a8 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -62,6 +62,9 @@ typedef struct rtlsdr_tuner_iface { int (*set_freq)(void *, uint32_t freq /* Hz */); int (*set_bw)(void *, int bw /* Hz */); int (*set_gain)(void *, int gain /* tenth dB */); + int (*set_lna_gain)(void *, int gain /* register value */); + int (*set_mix_gain)(void *, int gain /* register value */); + int (*set_vga_gain)(void *, int gain /* register value */); int (*set_if_gain)(void *, int stage, int gain /* tenth dB */); int (*set_gain_mode)(void *, int manual); } rtlsdr_tuner_iface_t; @@ -117,6 +120,9 @@ struct rtlsdr_dev { uint32_t offs_freq; /* Hz */ int corr; /* ppm */ int gain; /* tenth dB */ + int lna_gain; /* register value */ + int mix_gain; /* register value */ + int vga_gain; /* register value */ struct e4k_state e4k_s; struct r82xx_config r82xx_c; struct r82xx_priv r82xx_p; @@ -258,6 +264,18 @@ int r820t_set_gain(void *dev, int gain) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; return r82xx_set_gain(&devt->r82xx_p, 1, gain); } +int r820t_set_lna_gain(void *dev, int gain) { + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; + return r82xx_set_lna_gain(&devt->r82xx_p, gain); +} +int r820t_set_mix_gain(void *dev, int gain) { + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; + return r82xx_set_mix_gain(&devt->r82xx_p, gain); +} +int r820t_set_vga_gain(void *dev, int gain) { + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; + return r82xx_set_vga_gain(&devt->r82xx_p, gain); +} int r820t_set_gain_mode(void *dev, int manual) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; return r82xx_set_gain(&devt->r82xx_p, manual, 0); @@ -266,36 +284,37 @@ int r820t_set_gain_mode(void *dev, int manual) { /* definition order must match enum rtlsdr_tuner */ static rtlsdr_tuner_iface_t tuners[] = { { - NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */ + NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL /* dummy for unknown tuners */ }, { e4000_init, e4000_exit, - e4000_set_freq, e4000_set_bw, e4000_set_gain, e4000_set_if_gain, + e4000_set_freq, e4000_set_bw, e4000_set_gain, NULL, NULL, NULL, e4000_set_if_gain, e4000_set_gain_mode }, { _fc0012_init, fc0012_exit, - fc0012_set_freq, fc0012_set_bw, _fc0012_set_gain, NULL, + fc0012_set_freq, fc0012_set_bw, _fc0012_set_gain, NULL, NULL, NULL, NULL, fc0012_set_gain_mode }, { _fc0013_init, fc0013_exit, - fc0013_set_freq, fc0013_set_bw, _fc0013_set_gain, NULL, + fc0013_set_freq, fc0013_set_bw, _fc0013_set_gain, NULL, NULL, NULL, NULL, fc0013_set_gain_mode }, { fc2580_init, fc2580_exit, - _fc2580_set_freq, fc2580_set_bw, fc2580_set_gain, NULL, + _fc2580_set_freq, fc2580_set_bw, fc2580_set_gain, NULL, NULL, NULL, NULL, fc2580_set_gain_mode }, { r820t_init, r820t_exit, - r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL, + r820t_set_freq, r820t_set_bw, r820t_set_gain, + r820t_set_lna_gain, r820t_set_mix_gain, r820t_set_vga_gain, NULL, r820t_set_gain_mode }, { r820t_init, r820t_exit, - r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL, + r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL, NULL, NULL, NULL, r820t_set_gain_mode }, }; @@ -1049,6 +1068,69 @@ int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain) return r; } +int rtlsdr_set_tuner_lna_gain(rtlsdr_dev_t *dev, int gain) +{ + int r = 0; + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner->set_lna_gain) { + rtlsdr_set_i2c_repeater(dev, 1); + r = dev->tuner->set_lna_gain((void *)dev, gain); + rtlsdr_set_i2c_repeater(dev, 0); + } + + if (!r) + dev->lna_gain = gain; + else + dev->lna_gain = 0; + + return r; +} + +int rtlsdr_set_tuner_mix_gain(rtlsdr_dev_t *dev, int gain) +{ + int r = 0; + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner->set_mix_gain) { + rtlsdr_set_i2c_repeater(dev, 1); + r = dev->tuner->set_mix_gain((void *)dev, gain); + rtlsdr_set_i2c_repeater(dev, 0); + } + + if (!r) + dev->mix_gain = gain; + else + dev->mix_gain = 0; + + return r; +} + +int rtlsdr_set_tuner_vga_gain(rtlsdr_dev_t *dev, int gain) +{ + int r = 0; + + if (!dev || !dev->tuner) + return -1; + + if (dev->tuner->set_vga_gain) { + rtlsdr_set_i2c_repeater(dev, 1); + r = dev->tuner->set_vga_gain((void *)dev, gain); + rtlsdr_set_i2c_repeater(dev, 0); + } + + if (!r) + dev->vga_gain = gain; + else + dev->vga_gain = 0; + + return r; +} + int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev) { if (!dev) @@ -1057,6 +1139,30 @@ int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev) return dev->gain; } +int rtlsdr_get_tuner_lna_gain(rtlsdr_dev_t *dev) +{ + if (!dev) + return -1; + + return dev->lna_gain; +} + +int rtlsdr_get_tuner_mix_gain(rtlsdr_dev_t *dev) +{ + if (!dev) + return -1; + + return dev->mix_gain; +} + +int rtlsdr_get_tuner_vga_gain(rtlsdr_dev_t *dev) +{ + if (!dev) + return -1; + + return dev->vga_gain; +} + int rtlsdr_set_tuner_if_gain(rtlsdr_dev_t *dev, int stage, int gain) { int r = 0; diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c index f620238..64d412b 100644 --- a/src/tuner_r82xx.c +++ b/src/tuner_r82xx.c @@ -1018,7 +1018,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; @@ -1073,6 +1073,57 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain) return 0; } +int r82xx_set_lna_gain(struct r82xx_priv *priv, int gain) +{ + int rc; + + /* LNA auto off */ + rc = r82xx_write_reg_mask(priv, 0x05, 0x10, 0x10); + if (rc < 0) + return rc; + + /* set LNA gain */ + rc = r82xx_write_reg_mask(priv, 0x05, (uint8_t) gain, 0x0f); + if (rc < 0) + return rc; + + return 0; +} + +int r82xx_set_mix_gain(struct r82xx_priv *priv, int gain) +{ + int rc; + + /* Mixer auto off */ + rc = r82xx_write_reg_mask(priv, 0x07, 0, 0x10); + if (rc < 0) + return rc; + + /* set Mixer gain */ + rc = r82xx_write_reg_mask(priv, 0x07, (uint8_t) gain, 0x0f); + if (rc < 0) + return rc; + + return 0; +} + +int r82xx_set_vga_gain(struct r82xx_priv *priv, int gain) +{ + int rc; + + /* VGA auto off */ + rc = r82xx_write_reg_mask(priv, 0x0c, 0, 0x10); + if (rc < 0) + return rc; + + /* set VGA gain */ + rc = r82xx_write_reg_mask(priv, 0x0c, (uint8_t) gain, 0x0f); + if (rc < 0) + return rc; + + return 0; +} + /* Bandwidth contribution by low-pass filter. */ static const int r82xx_if_low_pass_bw_table[] = { 1700000, 1600000, 1550000, 1450000, 1200000, 900000, 700000, 550000, 450000, 350000 -- 2.11.0