aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSteve Markgraf <steve@steve-m.de>2012-09-13 21:53:51 +0200
committerSteve Markgraf <steve@steve-m.de>2012-09-13 21:53:51 +0200
commitfc5881d4cd6f778b080a3008dbcf4157ae1e13a2 (patch)
treefa0ead2f95c413692285cfa05b873cc312a3bbb8
parent1533422f982b66b340da26357608cb479b3ff7dd (diff)
add support for direct sampling mode
This commit adds the function rtlsdr_set_direct_sampling() which can be used to enable/disable a mode where the RTL2832 acts as a direct sampling receiver. This mode disables the tuner, and by attaching a long wire, or better, a 50Ω to 200Ω transformer and a lowpass- filter to the In-phase ADC input (pin 1 or 2 of the RTL2832, whereas pin 1 is at the molded dot) it is possible to listen to shortwave radio stations. The coupling capacitors can be left in place, but for better results they should be removed. Tuning in this mode is done with the DDC, and since the ADC samples with 28.8 MHz, tuning is possible from 0 to 28.8 MHz. Signed-off-by: Steve Markgraf <steve@steve-m.de>
-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);