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, I didn't received any feedback on this. Is there any chance my patch get considered to implement single gain tuning? Is this subject of any interest? thanks Luigi On 10/01/17 11:10, Luigi Tarenga wrote: > Hi list, > there is a bug in v2. I didn't put the gain array in the priv structure but used > a global variable so multiple instance would use the same variable. > > v3 fix this by putting a gain[] in the priv structure so every dongle get its > array allocated with a malloc. > > best regards > Luigi > > Signed-off-by: Luigi Tarenga <luigi.tarenga at gmail.com> > --- > include/rtl-sdr.h | 59 +++++++++++++++++++++++++ > include/tuner_r82xx.h | 7 +++ > src/librtlsdr.c | 118 +++++++++++++++++++++++++++++++++++++++++++++++--- > src/tuner_r82xx.c | 81 ++++++++++++++++++++++++++++++++++ > 4 files changed, 258 insertions(+), 7 deletions(-) > > diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h > index fe64bea..3719df4 100644 > --- a/include/rtl-sdr.h > +++ b/include/rtl-sdr.h > @@ -200,6 +200,65 @@ RTLSDR_API enum rtlsdr_tuner rtlsdr_get_tuner_type(rtlsdr_dev_t *dev); > RTLSDR_API int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains); > > /*! > + * Set the gain of a single gain stage for the device. > + * > + * Valid gain values may be queried with \ref rtlsdr_get_tuner_gain_stage_gains function. > + * Usually those are from 0 to a positive integer plus -1 to set the stage in Auto gain mode. > + * > + * \param dev the device handle given by rtlsdr_open() > + * \param stage from 0 to number of gain stages minus 1. > + * \param gain from 0 to maximum supported gain for selected stage or -1 to set Auto gain mode. > + * \return 0 on success > + */ > +RTLSDR_API int rtlsdr_set_tuner_gain_stage(rtlsdr_dev_t *dev, int stage, int gain); > + > + > +/*! > + * Get the gain of a single gain stage for the device. > + * > + * The value returned is a number from 0 to maximum supported gain. or -1 to indicate Auto gain mode. > + * > + * \param dev the device handle given by rtlsdr_open() > + * \param stage from 0 to number of gain stages minus 1. > + * \return the gain value in a range from 0 to maximum supported gain or -1 if Auto gain mode. > + */ > +RTLSDR_API int rtlsdr_get_tuner_gain_stage(rtlsdr_dev_t *dev, int stage); > + > + > +/*! > + * Get the number of gain stages supported by the device. > + * > + * The value returned is a number from 0 to the number of independent gain stages in the device. > + * > + * \param dev the device handle given by rtlsdr_open() > + * \return the number of gain stages in the devices. 0 if none are supported. > + */ > +RTLSDR_API int rtlsdr_get_tuner_gain_stages(rtlsdr_dev_t *dev); > + > +/*! > + * Get the supported values of gains in tenth of dB for a given stage. > + * > + * The value returned is the number of gain steps for the given stage and the maximum supported > + * gain value plus one. The returned value -1 is the maximum value that > + * can be used with \ref rtlsdr_set_tuner_gain_stage function as gain parameter. > + * > + * \param dev the device handle given by rtlsdr_open() > + * \param stage from 0 to number of gain stages minus 1. > + * \param gains a pointer to an array of integer where supported dB steps will be copied. NULL for no copy. > + * \return the number of gain steps for the given stage. > + */ > +RTLSDR_API int rtlsdr_get_tuner_gain_stage_gains(rtlsdr_dev_t *dev, int stage, int *gains); > + > +/*! > + * Get the name of the given gain stage. > + * > + * \param dev the device handle given by rtlsdr_open() > + * \param stage from 0 to number of gain stages minus 1. > + * \return the address of a NULL terminated char array containing a descriptive name of the give gain stage. > + */ > +RTLSDR_API const char* rtlsdr_get_tuner_gain_stage_name(rtlsdr_dev_t *dev, int stage); > + > +/*! > * Set the gain for the device. > * Manual gain mode must be enabled for this to work. > * > diff --git a/include/tuner_r82xx.h b/include/tuner_r82xx.h > index f6c206a..04bb113 100644 > --- a/include/tuner_r82xx.h > +++ b/include/tuner_r82xx.h > @@ -38,6 +38,7 @@ > #define NUM_REGS 30 > #define NUM_IMR 5 > #define IMR_TRIAL 9 > +#define NUM_GAIN_STAGES 3 > > #define VER_NUM 49 > > @@ -90,6 +91,7 @@ struct r82xx_priv { > enum r82xx_tuner_type type; > > uint32_t bw; /* in MHz */ > + int gain[NUM_GAIN_STAGES]; > > void *rtl_dev; > }; > @@ -115,6 +117,11 @@ 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_gain_stage(struct r82xx_priv *priv, int stage, int gain); > +int r82xx_get_gain_stage(struct r82xx_priv *priv, int stage); > +int r82xx_get_gain_stages(struct r82xx_priv *priv); > +int r82xx_get_gain_stage_gains(struct r82xx_priv *priv, int stage, int *gains); > +const char *r82xx_get_gain_stage_name(struct r82xx_priv *priv, int stage); > 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..d0db745 100644 > --- a/src/librtlsdr.c > +++ b/src/librtlsdr.c > @@ -64,6 +64,11 @@ typedef struct rtlsdr_tuner_iface { > int (*set_gain)(void *, int gain /* tenth dB */); > int (*set_if_gain)(void *, int stage, int gain /* tenth dB */); > int (*set_gain_mode)(void *, int manual); > + int (*set_gain_stage)(void *, int stage, int gain); > + int (*get_gain_stage)(void *, int stage); > + int (*get_gain_stages)(void *); > + int (*get_gain_stage_gains)(void *, int stage, int *gains); > + const char * (*get_gain_stage_name)(void *, int stage); > } rtlsdr_tuner_iface_t; > > enum rtlsdr_async_status { > @@ -258,45 +263,76 @@ 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_gain_mode(void *dev, int manual) { > rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; > return r82xx_set_gain(&devt->r82xx_p, manual, 0); > } > > +int r820t_set_gain_stage(void *dev, int stage, int gain) { > + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; > + return r82xx_set_gain_stage(&devt->r82xx_p, stage, gain); > +} > + > +int r820t_get_gain_stage(void *dev, int stage) { > + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; > + return r82xx_get_gain_stage(&devt->r82xx_p, stage); > +} > + > +int r820t_get_gain_stages(void *dev) { > + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; > + return r82xx_get_gain_stages(&devt->r82xx_p); > +} > + > +int r820t_get_gain_stage_gains(void *dev, int stage, int *gains) { > + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; > + return r82xx_get_gain_stage_gains(&devt->r82xx_p, stage, gains); > +} > + > +const char *r820t_get_gain_stage_name(void *dev, int stage) { > + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; > + return r82xx_get_gain_stage_name(&devt->r82xx_p, stage); > +} > + > /* 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, 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_gain_mode > + e4000_set_gain_mode, NULL, NULL, NULL, NULL, NULL > }, > { > _fc0012_init, fc0012_exit, > fc0012_set_freq, fc0012_set_bw, _fc0012_set_gain, NULL, > - fc0012_set_gain_mode > + fc0012_set_gain_mode, NULL, NULL, NULL, NULL, NULL > }, > { > _fc0013_init, fc0013_exit, > fc0013_set_freq, fc0013_set_bw, _fc0013_set_gain, NULL, > - fc0013_set_gain_mode > + fc0013_set_gain_mode, NULL, NULL, NULL, NULL, NULL > }, > { > fc2580_init, fc2580_exit, > _fc2580_set_freq, fc2580_set_bw, fc2580_set_gain, NULL, > - fc2580_set_gain_mode > + fc2580_set_gain_mode, NULL, NULL, NULL, NULL, NULL > }, > { > r820t_init, r820t_exit, > r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL, > - r820t_set_gain_mode > + r820t_set_gain_mode, > + r820t_set_gain_stage, > + r820t_get_gain_stage, > + r820t_get_gain_stages, > + r820t_get_gain_stage_gains, > + r820t_get_gain_stage_name > }, > { > r820t_init, r820t_exit, > r820t_set_freq, r820t_set_bw, r820t_set_gain, NULL, > - r820t_set_gain_mode > + r820t_set_gain_mode, NULL, NULL, NULL, NULL, NULL > }, > }; > > @@ -1089,6 +1125,74 @@ int rtlsdr_set_tuner_gain_mode(rtlsdr_dev_t *dev, int mode) > return r; > } > > +int rtlsdr_set_tuner_gain_stage(rtlsdr_dev_t *dev, int stage, int gain) > +{ > + int r = 0; > + > + if (!dev || !dev->tuner) > + return -1; > + > + if (dev->tuner->set_gain_stage) { > + rtlsdr_set_i2c_repeater(dev, 1); > + r = dev->tuner->set_gain_stage(dev, stage, gain); > + rtlsdr_set_i2c_repeater(dev, 0); > + } > + > + return r; > +} > + > +int rtlsdr_get_tuner_gain_stage(rtlsdr_dev_t *dev, int stage) > +{ > + int r = 0; > + > + if (!dev || !dev->tuner) > + return -1; > + > + if (dev->tuner->get_gain_stage) > + r = dev->tuner->get_gain_stage(dev, stage); > + > + return r; > +} > + > +int rtlsdr_get_tuner_gain_stages(rtlsdr_dev_t *dev) > +{ > + int r = 0; > + > + if (!dev || !dev->tuner) > + return -1; > + > + if (dev->tuner->get_gain_stages) > + r = dev->tuner->get_gain_stages(dev); > + > + return r; > +} > + > +int rtlsdr_get_tuner_gain_stage_gains(rtlsdr_dev_t *dev, int stage, int *gains) > +{ > + int r = 0; > + > + if (!dev || !dev->tuner) > + return -1; > + > + if (dev->tuner->get_gain_stage_gains) > + r = dev->tuner->get_gain_stage_gains(dev, stage, gains); > + > + return r; > +} > + > +const char *rtlsdr_get_tuner_gain_stage_name(rtlsdr_dev_t *dev, int stage) > +{ > + const char *r = ""; > + > + if (!dev || !dev->tuner) > + return ""; > + > + if (dev->tuner->get_gain_stage_name) > + r = dev->tuner->get_gain_stage_name(dev, stage); > + > + return r; > +} > + > int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate) > { > int r = 0; > diff --git a/src/tuner_r82xx.c b/src/tuner_r82xx.c > index f620238..eeb646f 100644 > --- a/src/tuner_r82xx.c > +++ b/src/tuner_r82xx.c > @@ -1073,6 +1073,87 @@ int r82xx_set_gain(struct r82xx_priv *priv, int set_manual_gain, int gain) > return 0; > } > > +typedef struct r82xx_gain_stage { > + const char *name; > + const int *steps; > + const int num; > +} r82xx_gain_stage_t; > + > + > +static r82xx_gain_stage_t gain_stage[NUM_GAIN_STAGES] = { > + { "LNA", (int []) { 0, 9, 13, 40, 38, 13, 31, 22, 26, 31, 26, 14, 19, 5, 35, 13 }, 16 }, > + { "MIX", (int []) { 0, 5, 10, 10, 19, 9, 10, 25, 17, 10, 8, 16, 13, 6, 3, -8 }, 16 }, > + { "VGA", (int []) { 0, 26, 26, 30, 42, 35, 24, 13, 14, 32, 36, 34, 35, 37, 35, 36 }, 16 } > +}; > + > +static const int r82xx_gain_stage_register[NUM_GAIN_STAGES] = { 0x05, 0x07, 0x0c }; > +static const int r82xx_gain_stage_mask[NUM_GAIN_STAGES] = { 0x0f, 0x0f, 0x0f }; > +static const int r82xx_gain_stage_manual[NUM_GAIN_STAGES] = { 0x01, 0x00, 0x00 }; > +static const int r82xx_gain_stage_manual_mask[NUM_GAIN_STAGES] = { 0x10, 0x10, 0x10 }; > + > +int r82xx_set_gain_stage(struct r82xx_priv *priv, int stage, int gain) > +{ > + int rc; > + > + if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage)) > + return -1; > + > + if (gain < -1 || gain >= gain_stage[stage].num) > + return -1; > + > + if (gain >= 0) { > + /* stage auto off */ > + rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], r82xx_gain_stage_manual[stage], r82xx_gain_stage_manual_mask[stage]); > + if (rc < 0) > + return rc; > + > + rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], (uint8_t) gain, r82xx_gain_stage_mask[stage]); > + if (rc < 0) > + return rc; > + > + priv->gain[stage] = gain; > + } else { > + /* stage auto on */ > + rc = r82xx_write_reg_mask(priv, r82xx_gain_stage_register[stage], ~(r82xx_gain_stage_manual[stage]), r82xx_gain_stage_manual_mask[stage]); > + if (rc < 0) > + return rc; > + } > + > + return 0; > +} > + > +int r82xx_get_gain_stage(struct r82xx_priv *priv, int stage) > +{ > + if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage)) > + return 0; > + > + return priv->gain[stage]; > +} > + > +int r82xx_get_gain_stages(struct r82xx_priv *priv) > +{ > + return ARRAY_SIZE(gain_stage); > +} > + > +int r82xx_get_gain_stage_gains(struct r82xx_priv *priv, int stage, int *gains) > +{ > + if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage)) > + return -1; > + > + if (gains) > + memcpy(gains, gain_stage[stage].steps, gain_stage[stage].num * sizeof(int)); > + > + return gain_stage[stage].num; > +} > + > +const char *r82xx_get_gain_stage_name(struct r82xx_priv *priv, int stage) > +{ > + if (stage < 0 || stage >= (int) ARRAY_SIZE(gain_stage)) > + return ""; > + > + return gain_stage[stage].name; > +} > + > /* 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 >