diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h index 956b62b..0b130bb 100644 --- a/include/rtl-sdr.h +++ b/include/rtl-sdr.h @@ -241,6 +241,16 @@ RTLSDR_API int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on); */ RTLSDR_API int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on); +/*! + * Enable or disable offset tuning for zero-IF tuners, which allows to avoid + * problems caused by the DC offset of the ADCs and 1/f noise. + * + * \param dev the device handle given by rtlsdr_open() + * \param on 0 means disabled, 1 enabled + * \return 0 on success + */ +RTLSDR_API int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on); + /* streaming functions */ RTLSDR_API int rtlsdr_reset_buffer(rtlsdr_dev_t *dev); diff --git a/src/librtlsdr.c b/src/librtlsdr.c index 2008f39..4b3ef07 100644 --- a/src/librtlsdr.c +++ b/src/librtlsdr.c @@ -85,6 +85,7 @@ struct rtlsdr_dev { rtlsdr_tuner_iface_t *tuner; uint32_t tun_xtal; /* Hz */ uint32_t freq; /* Hz */ + uint32_t offs_freq; /* Hz */ int corr; /* ppm */ int gain; /* tenth dB */ struct e4k_state e4k_s; @@ -105,9 +106,18 @@ int e4000_set_freq(void *dev, uint32_t freq) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; return e4k_tune_freq(&devt->e4k_s, freq); } + int e4000_set_bw(void *dev, int bw) { - return 0; + int r = 0; + rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; + + r |= e4k_if_filter_bw_set(&devt->e4k_s, E4K_IF_FILTER_MIX, bw); + r |= e4k_if_filter_bw_set(&devt->e4k_s, E4K_IF_FILTER_RC, bw); + r |= e4k_if_filter_bw_set(&devt->e4k_s, E4K_IF_FILTER_CHAN, bw); + + return r; } + int e4000_set_gain(void *dev, int gain) { rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev; int mixgain = (gain > 340) ? 12 : 4; @@ -708,7 +718,7 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq) r = rtlsdr_set_if_freq(dev, freq); } else if (dev->tuner && dev->tuner->set_freq) { rtlsdr_set_i2c_repeater(dev, 1); - r = dev->tuner->set_freq(dev, freq); + r = dev->tuner->set_freq(dev, freq - dev->offs_freq); rtlsdr_set_i2c_repeater(dev, 0); } @@ -1009,6 +1019,31 @@ int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on) return r; } +int rtlsdr_set_offset_tuning(rtlsdr_dev_t *dev, int on) +{ + int r = 0; + + if (!dev) + return -1; + + if (dev->tuner_type == RTLSDR_TUNER_R820T) + return -2; + + /* based on keenerds 1/f noise measurements */ + dev->offs_freq = on ? ((dev->rate / 2) * 170 / 100) : 0; + r |= rtlsdr_set_if_freq(dev, dev->offs_freq); + + if (dev->tuner && dev->tuner->set_bw) { + rtlsdr_set_i2c_repeater(dev, 1); + dev->tuner->set_bw(dev, on ? (2 * dev->offs_freq) : dev->rate); + rtlsdr_set_i2c_repeater(dev, 0); + } + + r |= rtlsdr_set_center_freq(dev, dev->freq); + + return r; +} + static rtlsdr_dongle_t *find_known_device(uint16_t vid, uint16_t pid) { unsigned int i;