From a630fc081020b261b86b2da08e54b2c64be35f89 Mon Sep 17 00:00:00 2001 From: Dimitri Stolnikov Date: Wed, 6 Jun 2012 00:44:04 +0200 Subject: implement setting the sample rate --- software/libosmosdr/include/osmosdr.h | 46 ++++++------ software/libosmosdr/src/libosmosdr.c | 131 ++++++++++++---------------------- software/libosmosdr/src/osmo_sdr.c | 13 ++++ 3 files changed, 80 insertions(+), 110 deletions(-) diff --git a/software/libosmosdr/include/osmosdr.h b/software/libosmosdr/include/osmosdr.h index e80a2f8..f28359c 100644 --- a/software/libosmosdr/include/osmosdr.h +++ b/software/libosmosdr/include/osmosdr.h @@ -54,30 +54,6 @@ OSMOSDR_API int osmosdr_close(osmosdr_dev_t *dev); /* configuration functions */ -/*! - * Set clock frequencies used for the ADC and the tuner ICs. - * - * NOTE: Call this function only if you know what you are doing. - * - * \param dev the device handle given by osmosdr_open() - * \param adc_clock frequency value used to clock the ADC in Hz - * \param tun_clock frequency value used to clock the tuner IC in Hz - * \return 0 on success - */ -OSMOSDR_API int osmosdr_set_clock_freq(osmosdr_dev_t *dev, uint32_t adc_clock, - uint32_t tun_clock); - -/*! - * Get clock frequencies used for the ADC and the tuner IC. - * - * \param dev the device handle given by osmosdr_open() - * \param adc_clock frequency value used to clock the ADC in Hz - * \param tun_clock frequency value used to clock the tuner IC in Hz - * \return 0 on success - */ -OSMOSDR_API int osmosdr_get_clock_freq(osmosdr_dev_t *dev, uint32_t *adc_clock, - uint32_t *tun_clock); - /*! * Get USB device strings. * @@ -164,11 +140,29 @@ OSMOSDR_API int osmosdr_set_tuner_mixer_enh(osmosdr_dev_t *dev, int enh); /* set IF stages gain */ OSMOSDR_API int osmosdr_set_tuner_if_gain(osmosdr_dev_t *dev, int stage, int gain); -/* this will select the baseband filters according to the requested sample rate */ +/*! + * Get a list of sample rates supported by the device. + * + * NOTE: The rates argument must be preallocated by the caller. If NULL is + * being given instead, the number of available rate values will be returned. + * + * \param dev the device handle given by osmosdr_open() + * \param rates array of rate values in Hz + * \return <= 0 on error, number of available (returned) rate values otherwise + */ +OSMOSDR_API uint32_t osmosdr_get_sample_rates(osmosdr_dev_t *dev, uint32_t *rates); + +/*! + * Set the sample rate for the device. + * + * \param dev the device handle given by osmosdr_open() + * \param rate the sample rate in Hz + * \return 0 on success + */ OSMOSDR_API int osmosdr_set_sample_rate(osmosdr_dev_t *dev, uint32_t rate); /*! - * Get actual sample rate the device is configured to. + * Get the sample rate the device is configured to. * * \param dev the device handle given by osmosdr_open() * \return 0 on error, sample rate in Hz otherwise diff --git a/software/libosmosdr/src/libosmosdr.c b/software/libosmosdr/src/libosmosdr.c index 485e5a0..1c5a22f 100644 --- a/software/libosmosdr/src/libosmosdr.c +++ b/software/libosmosdr/src/libosmosdr.c @@ -72,7 +72,6 @@ struct osmosdr_dev { uint32_t adc_clock; /* Hz */ /* tuner context */ osmosdr_tuner_t *tuner; - uint32_t tun_clock; /* Hz */ uint32_t freq; /* Hz */ int gain; /* dB */ }; @@ -91,17 +90,7 @@ static osmosdr_dongle_t known_devices[] = { #define DEFAULT_BUF_NUMBER 32 #define DEFAULT_BUF_LENGTH (16 * 32 * 512) -// TODO: change the constants according to the limits imposed by the hardware - -#define DEF_ADC_FREQ 28800000 -#define MIN_ADC_FREQ (DEF_ADC_FREQ - 1000) -#define MAX_ADC_FREQ (DEF_ADC_FREQ + 1000) - -#define DEF_E4K_FREQ 28800000 -#define MIN_E4K_FREQ (DEF_E4K_FREQ - 1000) -#define MAX_E4K_FREQ (DEF_E4K_FREQ + 1000) - -#define MAX_SAMP_RATE 3200000 +#define DEF_ADC_FREQ 4000000 #define CTRL_IN (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_IN) #define CTRL_OUT (LIBUSB_REQUEST_TYPE_VENDOR | LIBUSB_ENDPOINT_OUT) @@ -212,57 +201,6 @@ static osmosdr_tuner_t tuner = { e4k_set_bw, e4k_set_gain, e4k_set_gain_mode }; -int osmosdr_set_xtal_freq(osmosdr_dev_t *dev, uint32_t adc_clock, uint32_t tun_clock) -{ - int r = 0; - - if (!dev) - return -1; - - if (adc_clock > 0 && - (adc_clock < MIN_ADC_FREQ || adc_clock > MAX_ADC_FREQ)) - return -2; - - if (dev->adc_clock != adc_clock) { - if (0 == adc_clock) - adc_clock = DEF_ADC_FREQ; - - dev->adc_clock = adc_clock; - - /* update xtal-dependent settings */ - if (dev->rate) - r = osmosdr_set_sample_rate(dev, dev->rate); - } - - if (dev->tun_clock != tun_clock) { - if (0 == tun_clock) - tun_clock = dev->adc_clock; - - dev->tun_clock = tun_clock; - - /* update xtal-dependent settings */ - if (dev->freq) - r = osmosdr_set_center_freq(dev, dev->freq); - } - - return r; -} - -int osmosdr_get_xtal_freq(osmosdr_dev_t *dev, uint32_t *adc_clock, uint32_t *tun_clock) -{ - if (!dev) - return -1; - - *adc_clock = dev->adc_clock; - - if (!dev->tuner) - return -2; - - *tun_clock = dev->tun_clock; - - return 0; -} - int osmosdr_get_usb_strings(osmosdr_dev_t *dev, char *manufact, char *product, char *serial) { @@ -312,9 +250,8 @@ int osmosdr_set_center_freq(osmosdr_dev_t *dev, uint32_t freq) if (!dev || !dev->tuner) return -1; - if (dev->tuner->set_freq) { + if (dev->tuner->set_freq) r = dev->tuner->set_freq(dev, freq); - } if (!r) dev->freq = freq; @@ -358,9 +295,8 @@ int osmosdr_set_tuner_gain(osmosdr_dev_t *dev, int gain) if (!dev || !dev->tuner) return -1; - if (dev->tuner->set_gain) { + if (dev->tuner->set_gain) r = dev->tuner->set_gain((void *)dev, gain); - } if (!r) dev->gain = gain; @@ -385,9 +321,8 @@ int osmosdr_set_tuner_gain_mode(osmosdr_dev_t *dev, int mode) if (!dev || !dev->tuner) return -1; - if (dev->tuner->set_gain_mode) { + if (dev->tuner->set_gain_mode) r = dev->tuner->set_gain_mode((void *)dev, mode); - } return r; } @@ -451,27 +386,61 @@ int osmosdr_set_tuner_if_gain(osmosdr_dev_t *dev, int stage, int gain) buffer, 5, CTRL_TIMEOUT); } +/* two raised to the power of n */ +#define TWO_POW(n) (1ULL<<(n)) + +uint32_t osmosdr_get_sample_rates(osmosdr_dev_t *dev, uint32_t *rates) +{ + int n; + + if (!dev) + return -1; + + if (!rates) { /* no buffer provided, just return the count */ + return 5; + } else { + for (n = 6; n > 1; n--) /* 64 to 4 */ + *(rates++) = dev->adc_clock / TWO_POW(n); + + return 5; + } + + return 0; +} + int osmosdr_set_sample_rate(osmosdr_dev_t *dev, uint32_t samp_rate) { - uint16_t r = 0; + int n, decim = 3; + int r = 0; + unsigned int req_decim = 0; if (!dev) return -1; - /* check for the maximum rate the resampler supports */ - if (samp_rate > MAX_SAMP_RATE) - samp_rate = MAX_SAMP_RATE; + /* TODO: implement arbitrary rates by steering the master clock */ + + req_decim = dev->adc_clock / samp_rate; - if (dev->tuner && dev->tuner->set_bw) { - dev->tuner->set_bw(dev, samp_rate); + for (n = 2; n <= 6; n++) { /* 4 to 64 */ + if (TWO_POW(n) == req_decim) { + decim = n; + break; + } } - if (!r) + samp_rate = dev->adc_clock / TWO_POW(decim); + + r = osmosdr_set_fpga_decimation(dev, decim); + if (!r) { + if (dev->tuner && dev->tuner->set_bw) + dev->tuner->set_bw(dev, samp_rate); + dev->rate = samp_rate; - else + } else { dev->rate = 0; + } - return 0; + return r; } uint32_t osmosdr_get_sample_rate(osmosdr_dev_t *dev) @@ -739,14 +708,10 @@ int osmosdr_open(osmosdr_dev_t **out_dev, uint32_t index) dev->adc_clock = DEF_ADC_FREQ; - /* TODO: osmosdr_init_baseband(dev); */ - dev->tuner = &tuner; /* so far we support only one tuner */ found: if (dev->tuner) { - dev->tun_clock = dev->adc_clock; - if (dev->tuner->init) { r = dev->tuner->init(dev); } @@ -771,8 +736,6 @@ int osmosdr_close(osmosdr_dev_t *dev) if (!dev) return -1; - /* TODO: osmosdr_deinit_baseband(dev); */ - libusb_release_interface(dev->devh, 0); libusb_close(dev->devh); diff --git a/software/libosmosdr/src/osmo_sdr.c b/software/libosmosdr/src/osmo_sdr.c index f3eb8f6..c9cdd4d 100644 --- a/software/libosmosdr/src/osmo_sdr.c +++ b/software/libosmosdr/src/osmo_sdr.c @@ -110,6 +110,7 @@ int main(int argc, char **argv) char vendor[256] = { 0 }, product[256] = { 0 }, serial[256] = { 0 }; int count; int gains[100]; + uint32_t rates[100]; #ifndef _WIN32 while ((opt = getopt(argc, argv, "d:f:g:s:b:S::")) != -1) { @@ -205,6 +206,14 @@ int main(int argc, char **argv) fprintf(stderr, "%.1f ", gains[i] / 10.0); fprintf(stderr, "\n"); + count = osmosdr_get_sample_rates(dev, NULL); + fprintf(stderr, "Supported sample rates (%d): ", count); + + count = osmosdr_get_sample_rates(dev, rates); + for (i = 0; i < count; i++) + fprintf(stderr, "%u ", rates[i]); + fprintf(stderr, "\n"); + r = osmosdr_get_usb_strings(dev, vendor, product, serial); if (r < 0) fprintf(stderr, "WARNING: Failed to read usb strings.\n"); @@ -215,6 +224,10 @@ int main(int argc, char **argv) r = osmosdr_set_sample_rate(dev, samp_rate); if (r < 0) fprintf(stderr, "WARNING: Failed to set sample rate.\n"); + else { + samp_rate = osmosdr_get_sample_rate(dev); + fprintf(stderr, "Sample rate is set to %u Hz.\n", samp_rate); + } /* Set the frequency */ r = osmosdr_set_center_freq(dev, frequency); -- cgit v1.2.3