diff --git a/src/libsdr/sdr.c b/src/libsdr/sdr.c index e7221cf..a316d95 100644 --- a/src/libsdr/sdr.c +++ b/src/libsdr/sdr.c @@ -374,7 +374,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq #ifdef HAVE_UHD if (sdr_config->uhd) { - rc = uhd_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, tx_center_frequency, rx_center_frequency, sdr_config->lo_offset, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth, sdr_config->uhd_tx_timestamps); + rc = uhd_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, sdr_config->clock_source, tx_center_frequency, rx_center_frequency, sdr_config->lo_offset, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth, sdr_config->uhd_tx_timestamps); if (rc) goto error; } @@ -382,7 +382,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq #ifdef HAVE_SOAPY if (sdr_config->soapy) { - rc = soapy_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, tx_center_frequency, rx_center_frequency, sdr_config->lo_offset, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth); + rc = soapy_open(sdr_config->channel, sdr_config->device_args, sdr_config->stream_args, sdr_config->tune_args, sdr_config->tx_antenna, sdr_config->rx_antenna, sdr_config->clock_source, tx_center_frequency, rx_center_frequency, sdr_config->lo_offset, sdr_config->samplerate, sdr_config->tx_gain, sdr_config->rx_gain, sdr_config->bandwidth); if (rc) goto error; } diff --git a/src/libsdr/sdr_config.c b/src/libsdr/sdr_config.c index dfbada7..0ff021d 100644 --- a/src/libsdr/sdr_config.c +++ b/src/libsdr/sdr_config.c @@ -76,6 +76,8 @@ void sdr_config_print_help(void) printf(" SDR device's RX antenna name, use 'list' to get a list\n"); printf(" --sdr-tx-antenna \n"); printf(" SDR device's TX antenna name, use 'list' to get a list\n"); + printf(" --sdr-clock-source \n"); + printf(" SDR device's clock sourc name, use 'list' to get a list\n"); printf(" --sdr-rx-gain \n"); printf(" SDR device's RX gain in dB (default = %.1f)\n", sdr_config->rx_gain); printf(" --sdr-tx-gain \n"); @@ -111,17 +113,18 @@ void sdr_config_print_hotkeys(void) #define OPT_SDR_TUNE_ARGS 1505 #define OPT_SDR_RX_ANTENNA 1506 #define OPT_SDR_TX_ANTENNA 1507 -#define OPT_SDR_RX_GAIN 1508 -#define OPT_SDR_TX_GAIN 1509 -#define OPT_SDR_SAMPLERATE 1510 -#define OPT_SDR_LO_OFFSET 1511 -#define OPT_SDR_BANDWIDTH 1512 -#define OPT_WRITE_IQ_RX_WAVE 1513 -#define OPT_WRITE_IQ_TX_WAVE 1514 -#define OPT_READ_IQ_RX_WAVE 1515 -#define OPT_READ_IQ_TX_WAVE 1516 -#define OPT_SDR_SWAP_LINKS 1517 -#define OPT_SDR_UHD_TX_TS 1518 +#define OPT_SDR_CLOCK_SOURCE 1508 +#define OPT_SDR_RX_GAIN 1509 +#define OPT_SDR_TX_GAIN 1510 +#define OPT_SDR_SAMPLERATE 1511 +#define OPT_SDR_LO_OFFSET 1512 +#define OPT_SDR_BANDWIDTH 1513 +#define OPT_WRITE_IQ_RX_WAVE 1514 +#define OPT_WRITE_IQ_TX_WAVE 1515 +#define OPT_READ_IQ_RX_WAVE 1516 +#define OPT_READ_IQ_TX_WAVE 1517 +#define OPT_SDR_SWAP_LINKS 1518 +#define OPT_SDR_UHD_TX_TS 1519 void sdr_config_add_options(void) { @@ -136,6 +139,7 @@ void sdr_config_add_options(void) option_add(OPT_SDR_BANDWIDTH, "sdr-bandwidth", 1); option_add(OPT_SDR_RX_ANTENNA, "sdr-rx-antenna", 1); option_add(OPT_SDR_TX_ANTENNA, "sdr-tx-antenna", 1); + option_add(OPT_SDR_CLOCK_SOURCE, "sdr-clock-source", 1); option_add(OPT_SDR_RX_GAIN, "sdr-rx-gain", 1); option_add(OPT_SDR_TX_GAIN, "sdr-tx-gain", 1); option_add(OPT_WRITE_IQ_RX_WAVE, "write-iq-rx-wave", 1); @@ -194,6 +198,9 @@ int sdr_config_handle_options(int short_option, int argi, char **argv) case OPT_SDR_TX_ANTENNA: sdr_config->tx_antenna = strdup(argv[argi]); break; + case OPT_SDR_CLOCK_SOURCE: + sdr_config->clock_source = strdup(argv[argi]); + break; case OPT_SDR_RX_GAIN: sdr_config->rx_gain = atof(argv[argi]); break; diff --git a/src/libsdr/sdr_config.h b/src/libsdr/sdr_config.h index 1feb323..37f3643 100644 --- a/src/libsdr/sdr_config.h +++ b/src/libsdr/sdr_config.h @@ -13,6 +13,7 @@ typedef struct sdr_config { rx_gain; const char *tx_antenna, /* list/override antennas */ *rx_antenna; + const char *clock_source; /* list/override clock source */ const char *write_iq_tx_wave; /* wave recording and playback */ const char *write_iq_rx_wave; const char *read_iq_tx_wave; diff --git a/src/libsdr/soapy.c b/src/libsdr/soapy.c index 9c33dfb..0919060 100644 --- a/src/libsdr/soapy.c +++ b/src/libsdr/soapy.c @@ -62,10 +62,10 @@ static int parse_args(SoapySDRKwargs *args, const char *_args_string) return 0; } -int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth) +int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, const char *clock_source, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth) { double got_frequency, got_rate, got_gain, got_bandwidth; - const char *got_antenna; + const char *got_antenna, *got_clock; size_t num_channels; SoapySDRKwargs device_args; SoapySDRKwargs stream_args; @@ -103,6 +103,42 @@ int soapy_open(size_t channel, const char *_device_args, const char *_stream_arg return -EIO; } + /* clock source */ + if (clock_source && clock_source[0]) { + if (!strcasecmp(clock_source, "list")) { + char **clocks; + size_t clocks_length; + int i; + clocks = SoapySDRDevice_listClockSources(sdr, &clocks_length); + if (!clocks) { + PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to request list of clock sources!\n"); + soapy_close(); + return -EIO; + } + if (clocks_length) { + for (i = 0; i < (int)clocks_length; i++) + PDEBUG(DSOAPY, DEBUG_NOTICE, "Clock source: '%s'\n", clocks[i]); + got_clock = SoapySDRDevice_getClockSource(sdr); + PDEBUG(DSOAPY, DEBUG_NOTICE, "Default clock source: '%s'\n", got_clock); + } else + PDEBUG(DSOAPY, DEBUG_NOTICE, "There are no clock sources configurable for this device.\n"); + soapy_close(); + return 1; + } + + if (SoapySDRDevice_setClockSource(sdr, clock_source) != 0) { + PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set clock source to '%s'\n", clock_source); + soapy_close(); + return -EIO; + } + got_clock = SoapySDRDevice_getClockSource(sdr); + if (!!strcasecmp(clock_source, got_clock)) { + PDEBUG(DSOAPY, DEBUG_NOTICE, "Given clock source '%s' was accepted, but driver claims to use '%s'\n", clock_source, got_clock); + soapy_close(); + return -EINVAL; + } + } + if (rx_frequency) { /* get number of channels and check if requested channel is in range */ num_channels = SoapySDRDevice_getNumChannels(sdr, SOAPY_SDR_RX); diff --git a/src/libsdr/soapy.h b/src/libsdr/soapy.h index 755d0ca..c411b5b 100644 --- a/src/libsdr/soapy.h +++ b/src/libsdr/soapy.h @@ -1,5 +1,5 @@ -int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth); +int soapy_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, const char *clock_source, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth); int soapy_start(void); void soapy_close(void); int soapy_send(float *buff, int num); diff --git a/src/libsdr/uhd.c b/src/libsdr/uhd.c index 624146f..dc99125 100644 --- a/src/libsdr/uhd.c +++ b/src/libsdr/uhd.c @@ -49,11 +49,11 @@ static time_t tx_time_secs = 0; static double tx_time_fract_sec = 0.0; static int tx_timestamps; -int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps) +int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, const char *clock_source, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps) { uhd_error error; double got_frequency, got_rate, got_gain, got_bandwidth; - char got_antenna[64]; + char got_antenna[64], got_clock[64]; samplerate = rate; tx_timestamps = _tx_timestamps; @@ -71,6 +71,64 @@ int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, return -EIO; } + /* clock source */ + if (clock_source && clock_source[0]) { + if (!strcasecmp(clock_source, "list")) { + uhd_string_vector_handle clocks; + size_t clocks_length; + int i; + error = uhd_string_vector_make(&clocks); + if (error) { + clock_vector_error: + PDEBUG(DUHD, DEBUG_ERROR, "Failed to hande UHD vector, please fix!\n"); + uhd_close(); + return -EIO; + } + error = uhd_usrp_get_clock_sources(usrp, 0, &clocks); + if (error) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to request list of clock sources!\n"); + uhd_close(); + return -EIO; + } + error = uhd_string_vector_size(clocks, &clocks_length); + if (error) + goto clock_vector_error; + for (i = 0; i < (int)clocks_length; i++) { + error = uhd_string_vector_at(clocks, i, got_clock, sizeof(got_clock)); + if (error) + goto clock_vector_error; + PDEBUG(DUHD, DEBUG_NOTICE, "Clock source: '%s'\n", got_clock); + } + uhd_string_vector_free(&clocks); + error = uhd_usrp_get_clock_source(usrp, 0, got_clock, sizeof(got_clock)); + if (error) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to get clock source\n"); + uhd_close(); + return -EINVAL; + } + PDEBUG(DUHD, DEBUG_NOTICE, "Default clock source: '%s'\n", got_clock); + uhd_close(); + return 1; + } + error = uhd_usrp_set_clock_source(usrp, clock_source, 0); + if (error) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set clock source to '%s'\n", clock_source); + uhd_close(); + return -EIO; + } + error = uhd_usrp_get_clock_source(usrp, 0, got_clock, sizeof(got_clock)); + if (error) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to get clock source\n"); + uhd_close(); + return -EINVAL; + } + if (!!strcasecmp(clock_source, got_clock)) { + PDEBUG(DUHD, DEBUG_NOTICE, "Given clock source '%s' was accepted, but driver claims to use '%s'\n", clock_source, got_clock); + uhd_close(); + return -EINVAL; + } + } + if (tx_frequency) { /* antenna */ if (tx_antenna && tx_antenna[0]) { diff --git a/src/libsdr/uhd.h b/src/libsdr/uhd.h index 36ce1ba..ad80e57 100644 --- a/src/libsdr/uhd.h +++ b/src/libsdr/uhd.h @@ -1,5 +1,5 @@ -int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps); +int uhd_open(size_t channel, const char *_device_args, const char *_stream_args, const char *_tune_args, const char *tx_antenna, const char *rx_antenna, const char *clock_source, double tx_frequency, double rx_frequency, double lo_offset, double rate, double tx_gain, double rx_gain, double bandwidth, int _tx_timestamps); int uhd_start(void); void uhd_close(void); int uhd_send(float *buff, int num);