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.
pull/1/merge
Dimitri Stolnikov 2012-07-08 15:52:59 +02:00
rodzic 7dc15d9fd7
commit f9b5d7b0a6
2 zmienionych plików z 59 dodań i 29 usunięć

Wyświetl plik

@ -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 {

Wyświetl plik

@ -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)