Просмотр исходного кода

add function for offset tuning with zero-IF tuners

Signed-off-by: Steve Markgraf <steve@steve-m.de>
Steve Markgraf лет назад: 12
Родитель
Сommit
b70c7d99f1
2 измененных файлов с 47 добавлено и 2 удалено
  1. 10 0
      include/rtl-sdr.h
  2. 37 2
      src/librtlsdr.c

+ 10 - 0
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);

+ 37 - 2
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;