aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/rtl-sdr.h12
-rw-r--r--include/tuner_r820t.h2
-rw-r--r--src/librtlsdr.c82
3 files changed, 84 insertions, 12 deletions
diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index 2b9fff0..98c9992 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -229,6 +229,18 @@ RTLSDR_API int rtlsdr_set_testmode(rtlsdr_dev_t *dev, int on);
*/
RTLSDR_API int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on);
+/*!
+ * Enable or disable the direct sampling mode. When enabled, the IF mode
+ * of the RTL2832 is activated, and rtlsdr_set_center_freq() will control
+ * the IF-frequency of the DDC, which can be used to tune from 0 to 28.8 MHz
+ * (xtal frequency of the RTL2832).
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param direct sampling mode, 1 means enabled, 0 disabled
+ * \return 0 on success
+ */
+RTLSDR_API int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on);
+
/* streaming functions */
RTLSDR_API int rtlsdr_reset_buffer(rtlsdr_dev_t *dev);
diff --git a/include/tuner_r820t.h b/include/tuner_r820t.h
index 058a9f2..5d15bfe 100644
--- a/include/tuner_r820t.h
+++ b/include/tuner_r820t.h
@@ -5,6 +5,8 @@
#define R820T_CHECK_ADDR 0x00
#define R820T_CHECK_VAL 0x69
+#define R820T_IF_FREQ 3570000
+
//***************************************************************
//* INCLUDES.H
//***************************************************************
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 87f3ebf..da7191b 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -79,6 +79,7 @@ struct rtlsdr_dev {
/* rtl demod context */
uint32_t rate; /* Hz */
uint32_t rtl_xtal; /* Hz */
+ int direct_sampling;
/* tuner context */
enum rtlsdr_tuner tuner_type;
rtlsdr_tuner_iface_t *tuner;
@@ -562,11 +563,19 @@ int rtlsdr_deinit_baseband(rtlsdr_dev_t *dev)
int rtlsdr_set_if_freq(rtlsdr_dev_t *dev, uint32_t freq)
{
+ uint32_t rtl_xtal;
int32_t if_freq;
uint8_t tmp;
int r;
- if_freq = ((freq * TWO_POW(22)) / dev->rtl_xtal) * (-1);
+ if (!dev)
+ return -1;
+
+ /* read corrected clock value */
+ if (rtlsdr_get_xtal_freq(dev, &rtl_xtal, NULL))
+ return -2;
+
+ if_freq = ((freq * TWO_POW(22)) / rtl_xtal) * (-1);
tmp = (if_freq >> 16) & 0x3f;
r = rtlsdr_demod_write_reg(dev, 1, 0x19, tmp, 1);
@@ -679,17 +688,19 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq)
if (!dev || !dev->tuner)
return -1;
- if (dev->tuner->set_freq) {
+ if (dev->direct_sampling) {
+ 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);
rtlsdr_set_i2c_repeater(dev, 0);
-
- if (!r)
- dev->freq = freq;
- else
- dev->freq = 0;
}
+ if (!r)
+ dev->freq = freq;
+ else
+ dev->freq = 0;
+
return r;
}
@@ -751,6 +762,7 @@ int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains)
const int fc0013_gains[] = { -63, 71, 191, 197 };
const int fc2580_gains[] = { 0 /* no gain values */ };
const int r820t_gains[] = { 0 /* no gain values */ };
+ const int unknown_gains[] = { 0 /* no gain values */ };
int *ptr = NULL;
int len = 0;
@@ -775,7 +787,7 @@ int rtlsdr_get_tuner_gains(rtlsdr_dev_t *dev, int *gains)
ptr = (int *)r820t_gains; len = sizeof(r820t_gains);
break;
default:
- fprintf(stderr, "Invalid tuner type %d\n", dev->tuner_type);
+ ptr = (int *)unknown_gains; len = sizeof(unknown_gains);
break;
}
@@ -923,6 +935,52 @@ int rtlsdr_set_agc_mode(rtlsdr_dev_t *dev, int on)
return rtlsdr_demod_write_reg(dev, 0, 0x19, on ? 0x25 : 0x05, 1);
}
+int rtlsdr_set_direct_sampling(rtlsdr_dev_t *dev, int on)
+{
+ int r = 0;
+
+ if (!dev)
+ return -1;
+
+ if (on) {
+ if (dev->tuner && dev->tuner->exit) {
+ rtlsdr_set_i2c_repeater(dev, 1);
+ r = dev->tuner->exit(dev);
+ rtlsdr_set_i2c_repeater(dev, 0);
+ }
+
+ /* disable Zero-IF mode */
+ r |= rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1a, 1);
+
+ /* disable spectrum inversion */
+ r |= rtlsdr_demod_write_reg(dev, 1, 0x15, 0x00, 1);
+
+ fprintf(stderr, "Enabled direct sampling mode\n");
+ dev->direct_sampling = 1;
+ } else {
+ if (dev->tuner && dev->tuner->init) {
+ rtlsdr_set_i2c_repeater(dev, 1);
+ r |= dev->tuner->init(dev);
+ rtlsdr_set_i2c_repeater(dev, 0);
+ }
+
+ if (dev->tuner_type == RTLSDR_TUNER_R820T) {
+ r |= rtlsdr_set_if_freq(dev, R820T_IF_FREQ);
+
+ /* enable spectrum inversion */
+ r |= rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1);
+ } else {
+ /* Enable Zero-IF mode */
+ rtlsdr_demod_write_reg(dev, 1, 0xb1, 0x1b, 1);
+ }
+
+ fprintf(stderr, "Disabled direct sampling mode\n");
+ dev->direct_sampling = 0;
+ }
+
+ return r;
+}
+
static rtlsdr_dongle_t *find_known_device(uint16_t vid, uint16_t pid)
{
unsigned int i;
@@ -1137,7 +1195,7 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
/* the R820T uses 3.57 MHz IF for the DVB-T 6 MHz mode, and
* 4.57 MHz for the 8 MHz mode */
- rtlsdr_set_if_freq(dev, 3570000);
+ rtlsdr_set_if_freq(dev, R820T_IF_FREQ);
/* enable spectrum inversion */
rtlsdr_demod_write_reg(dev, 1, 0x15, 0x01, 1);
@@ -1169,8 +1227,8 @@ int rtlsdr_open(rtlsdr_dev_t **out_dev, uint32_t index)
found:
if (dev->tuner_type == RTLSDR_TUNER_UNKNOWN) {
- r = -1;
- goto err;
+ fprintf(stderr, "No supported tuner found\n");
+ rtlsdr_set_direct_sampling(dev, 1);
}
dev->tuner = &tuners[dev->tuner_type];
@@ -1204,7 +1262,7 @@ int rtlsdr_close(rtlsdr_dev_t *dev)
while (RTLSDR_INACTIVE != dev->async_status)
usleep(10);
- rtlsdr_deinit_baseband(dev);
+ rtlsdr_deinit_baseband(dev);
libusb_release_interface(dev->devh, 0);
libusb_close(dev->devh);