aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDimitri Stolnikov <horiz0n@gmx.net>2012-07-08 15:52:59 +0200
committerDimitri Stolnikov <horiz0n@gmx.net>2012-07-08 15:52:59 +0200
commitf9b5d7b0a66b39d307334bb84a5ffa6b3171f7b8 (patch)
tree995982c5b16ba07af916d9aa12b09726ff300dd1
parent7dc15d9fd74c870c4528f3d6482b90056f94c43b (diff)
apply frequency correction value on the xtal clock directly
by using this approach both, the tuning frequency and the sample rate should be corrected at the same time.
-rw-r--r--include/rtl-sdr.h17
-rw-r--r--src/librtlsdr.c71
2 files changed, 59 insertions, 29 deletions
diff --git a/include/rtl-sdr.h b/include/rtl-sdr.h
index 7de8455..ec0b4c8 100644
--- a/include/rtl-sdr.h
+++ b/include/rtl-sdr.h
@@ -60,9 +60,9 @@ RTLSDR_API int rtlsdr_close(rtlsdr_dev_t *dev);
*
* Usually both ICs use the same clock. Changing the clock may make sense if
* you are applying an external clock to the tuner or to compensate the
- * frequency (and samplerate) error caused by the original cheap crystal.
+ * frequency (and samplerate) error caused by the original (cheap) crystal.
*
- * NOTE: Call this function only if you know what you are doing.
+ * NOTE: Call this function only if you fully understand the implications.
*
* \param dev the device handle given by rtlsdr_open()
* \param rtl_freq frequency value used to clock the RTL2832 in Hz
@@ -109,8 +109,21 @@ RTLSDR_API int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq);
*/
RTLSDR_API uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev);
+/*!
+ * Set the frequency correction value for the device.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \param ppm correction value in parts per million (ppm)
+ * \return 0 on success
+ */
RTLSDR_API int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm);
+/*!
+ * Get actual frequency correction value of the device.
+ *
+ * \param dev the device handle given by rtlsdr_open()
+ * \return correction value in parts per million (ppm)
+ */
RTLSDR_API int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev);
enum rtlsdr_tuner {
diff --git a/src/librtlsdr.c b/src/librtlsdr.c
index 98cf272..b603ef6 100644
--- a/src/librtlsdr.c
+++ b/src/librtlsdr.c
@@ -91,7 +91,7 @@ void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val);
int e4000_init(void *dev) {
rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
devt->e4k_s.i2c_addr = E4K_I2C_ADDR;
- devt->e4k_s.vco.fosc = devt->tun_xtal;
+ devt->e4k_s.vco.fosc = devt->tun_xtal; /* no need to correct it here */
devt->e4k_s.rtl_dev = dev;
return e4k_init(&devt->e4k_s);
}
@@ -540,10 +540,7 @@ int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, uint32_t tuner_fr
(rtl_freq < MIN_RTL_XTAL_FREQ || rtl_freq > MAX_RTL_XTAL_FREQ))
return -2;
- if (dev->rtl_xtal != rtl_freq) {
- if (0 == rtl_freq)
- rtl_freq = DEF_RTL_XTAL_FREQ;
-
+ if (rtl_freq > 0 && dev->rtl_xtal != rtl_freq) {
dev->rtl_xtal = rtl_freq;
/* update xtal-dependent settings */
@@ -553,9 +550,13 @@ int rtlsdr_set_xtal_freq(rtlsdr_dev_t *dev, uint32_t rtl_freq, uint32_t tuner_fr
if (dev->tun_xtal != tuner_freq) {
if (0 == tuner_freq)
- tuner_freq = dev->rtl_xtal;
+ dev->tun_xtal = dev->rtl_xtal;
+ else
+ dev->tun_xtal = tuner_freq;
- dev->tun_xtal = tuner_freq;
+ /* read corrected clock value into e4k structure */
+ if (rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc))
+ return -3;
/* update xtal-dependent settings */
if (dev->freq)
@@ -570,12 +571,13 @@ int rtlsdr_get_xtal_freq(rtlsdr_dev_t *dev, uint32_t *rtl_freq, uint32_t *tuner_
if (!dev)
return -1;
- *rtl_freq = dev->rtl_xtal;
+ #define APPLY_PPM_CORR(val,ppm) (((val) * (1.0 + (ppm) / 1e6)))
- if (!dev->tuner)
- return -2;
+ if (rtl_freq)
+ *rtl_freq = (uint32_t) APPLY_PPM_CORR(dev->rtl_xtal, dev->corr);
- *tuner_freq = dev->tun_xtal;
+ if (tuner_freq)
+ *tuner_freq = (uint32_t) APPLY_PPM_CORR(dev->tun_xtal, dev->corr);
return 0;
}
@@ -624,16 +626,13 @@ int rtlsdr_get_usb_strings(rtlsdr_dev_t *dev, char *manufact, char *product,
int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq)
{
int r = -1;
- double f = (double) freq;
if (!dev || !dev->tuner)
return -1;
if (dev->tuner->set_freq) {
- f *= 1.0 + dev->corr / 1e6;
-
rtlsdr_set_i2c_repeater(dev, 1);
- r = dev->tuner->set_freq(dev, (uint32_t) f);
+ r = dev->tuner->set_freq(dev, freq);
rtlsdr_set_i2c_repeater(dev, 0);
if (!r)
@@ -647,7 +646,7 @@ int rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq)
uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev)
{
- if (!dev || !dev->tuner)
+ if (!dev)
return 0;
return dev->freq;
@@ -655,25 +654,32 @@ uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev)
int rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm)
{
- int r;
+ int r = 0;
- if (!dev || !dev->tuner)
+ if (!dev)
return -1;
if (dev->corr == ppm)
- return -1;
+ return -2;
dev->corr = ppm;
- /* retune to apply new correction value */
- r = rtlsdr_set_center_freq(dev, dev->freq);
+ /* read corrected clock value into e4k structure */
+ if (rtlsdr_get_xtal_freq(dev, NULL, &dev->e4k_s.vco.fosc))
+ return -3;
+
+ if (dev->rate) /* reset sample rate to apply new correction value */
+ r |= rtlsdr_set_sample_rate(dev, dev->rate);
+
+ if (dev->freq) /* retune to apply new correction value */
+ r |= rtlsdr_set_center_freq(dev, dev->freq);
return r;
}
int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev)
{
- if (!dev || !dev->tuner)
+ if (!dev)
return 0;
return dev->corr;
@@ -752,7 +758,7 @@ int rtlsdr_set_tuner_gain(rtlsdr_dev_t *dev, int gain)
int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev)
{
- if (!dev || !dev->tuner)
+ if (!dev)
return 0;
return dev->gain;
@@ -796,6 +802,7 @@ int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
uint16_t tmp;
uint32_t rsamp_ratio;
double real_rate;
+ uint32_t rtl_freq;
if (!dev)
return -1;
@@ -804,10 +811,14 @@ int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
if (samp_rate > MAX_SAMP_RATE)
samp_rate = MAX_SAMP_RATE;
- rsamp_ratio = (dev->rtl_xtal * TWO_POW(22)) / samp_rate;
+ /* read corrected clock value */
+ if (rtlsdr_get_xtal_freq(dev, &rtl_freq, NULL))
+ return -2;
+
+ rsamp_ratio = (rtl_freq * TWO_POW(22)) / samp_rate;
rsamp_ratio &= ~3;
- real_rate = (dev->rtl_xtal * TWO_POW(22)) / rsamp_ratio;
+ real_rate = (rtl_freq * TWO_POW(22)) / rsamp_ratio;
if ( ((double)samp_rate) != real_rate )
fprintf(stderr, "Exact sample rate is: %f Hz\n", real_rate);
@@ -1089,7 +1100,7 @@ found:
}
dev->tuner = &tuners[dev->tuner_type];
- dev->tun_xtal = dev->rtl_xtal;
+ dev->tun_xtal = dev->rtl_xtal; /* use the rtl clock value by default */
if (dev->tuner->init)
r = dev->tuner->init(dev);
@@ -1313,10 +1324,16 @@ int rtlsdr_cancel_async(rtlsdr_dev_t *dev)
uint32_t rtlsdr_get_tuner_clock(void *dev)
{
+ uint32_t tuner_freq;
+
if (!dev)
return 0;
- return ((rtlsdr_dev_t *)dev)->tun_xtal;
+ /* read corrected clock value */
+ if (rtlsdr_get_xtal_freq((rtlsdr_dev_t *)dev, NULL, &tuner_freq))
+ return 0;
+
+ return tuner_freq;
}
int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len)