|
@@ -91,7 +91,7 @@ void rtlsdr_set_gpio_bit(rtlsdr_dev_t *dev, uint8_t gpio, int val);
|
|
int e4000_init(void *dev) {
|
|
int e4000_init(void *dev) {
|
|
rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
|
|
rtlsdr_dev_t* devt = (rtlsdr_dev_t*)dev;
|
|
devt->e4k_s.i2c_addr = E4K_I2C_ADDR;
|
|
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;
|
|
devt->e4k_s.rtl_dev = dev;
|
|
return e4k_init(&devt->e4k_s);
|
|
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))
|
|
(rtl_freq < MIN_RTL_XTAL_FREQ || rtl_freq > MAX_RTL_XTAL_FREQ))
|
|
return -2;
|
|
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;
|
|
dev->rtl_xtal = rtl_freq;
|
|
|
|
|
|
/* update xtal-dependent settings */
|
|
/* 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 (dev->tun_xtal != tuner_freq) {
|
|
if (0 == 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 */
|
|
/* update xtal-dependent settings */
|
|
if (dev->freq)
|
|
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)
|
|
if (!dev)
|
|
return -1;
|
|
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;
|
|
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 rtlsdr_set_center_freq(rtlsdr_dev_t *dev, uint32_t freq)
|
|
{
|
|
{
|
|
int r = -1;
|
|
int r = -1;
|
|
- double f = (double) freq;
|
|
|
|
|
|
|
|
if (!dev || !dev->tuner)
|
|
if (!dev || !dev->tuner)
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
if (dev->tuner->set_freq) {
|
|
if (dev->tuner->set_freq) {
|
|
- f *= 1.0 + dev->corr / 1e6;
|
|
|
|
-
|
|
|
|
rtlsdr_set_i2c_repeater(dev, 1);
|
|
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);
|
|
rtlsdr_set_i2c_repeater(dev, 0);
|
|
|
|
|
|
if (!r)
|
|
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)
|
|
uint32_t rtlsdr_get_center_freq(rtlsdr_dev_t *dev)
|
|
{
|
|
{
|
|
- if (!dev || !dev->tuner)
|
|
|
|
|
|
+ if (!dev)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
return dev->freq;
|
|
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 rtlsdr_set_freq_correction(rtlsdr_dev_t *dev, int ppm)
|
|
{
|
|
{
|
|
- int r;
|
|
|
|
|
|
+ int r = 0;
|
|
|
|
|
|
- if (!dev || !dev->tuner)
|
|
|
|
|
|
+ if (!dev)
|
|
return -1;
|
|
return -1;
|
|
|
|
|
|
if (dev->corr == ppm)
|
|
if (dev->corr == ppm)
|
|
- return -1;
|
|
|
|
|
|
+ return -2;
|
|
|
|
|
|
dev->corr = ppm;
|
|
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;
|
|
return r;
|
|
}
|
|
}
|
|
|
|
|
|
int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev)
|
|
int rtlsdr_get_freq_correction(rtlsdr_dev_t *dev)
|
|
{
|
|
{
|
|
- if (!dev || !dev->tuner)
|
|
|
|
|
|
+ if (!dev)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
return dev->corr;
|
|
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)
|
|
int rtlsdr_get_tuner_gain(rtlsdr_dev_t *dev)
|
|
{
|
|
{
|
|
- if (!dev || !dev->tuner)
|
|
|
|
|
|
+ if (!dev)
|
|
return 0;
|
|
return 0;
|
|
|
|
|
|
return dev->gain;
|
|
return dev->gain;
|
|
@@ -796,6 +802,7 @@ int rtlsdr_set_sample_rate(rtlsdr_dev_t *dev, uint32_t samp_rate)
|
|
uint16_t tmp;
|
|
uint16_t tmp;
|
|
uint32_t rsamp_ratio;
|
|
uint32_t rsamp_ratio;
|
|
double real_rate;
|
|
double real_rate;
|
|
|
|
+ uint32_t rtl_freq;
|
|
|
|
|
|
if (!dev)
|
|
if (!dev)
|
|
return -1;
|
|
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)
|
|
if (samp_rate > MAX_SAMP_RATE)
|
|
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;
|
|
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 )
|
|
if ( ((double)samp_rate) != real_rate )
|
|
fprintf(stderr, "Exact sample rate is: %f Hz\n", 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->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)
|
|
if (dev->tuner->init)
|
|
r = dev->tuner->init(dev);
|
|
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 rtlsdr_get_tuner_clock(void *dev)
|
|
{
|
|
{
|
|
|
|
+ uint32_t tuner_freq;
|
|
|
|
+
|
|
if (!dev)
|
|
if (!dev)
|
|
return 0;
|
|
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)
|
|
int rtlsdr_i2c_write_fn(void *dev, uint8_t addr, uint8_t *buf, int len)
|