diff --git a/configure.ac b/configure.ac index 58543f3..63175a7 100644 --- a/configure.ac +++ b/configure.ac @@ -26,10 +26,17 @@ AC_CANONICAL_HOST PKG_CHECK_MODULES(ALSA, alsa >= 1.0) -have_sdr=no -PKG_CHECK_MODULES(UHD, uhd >= 3.0.0, have_sdr=yes have_uhd=yes, have_uhd=no) -AM_CONDITIONAL(HAVE_UHD, test "x$have_uhd" == "xyes" ) -AM_CONDITIONAL(HAVE_SDR, test "x$have_sdr" == "xyes" ) + +with_sdr=no +AC_ARG_WITH([uhd], [AS_HELP_STRING([--with-uhd], [compile with UHD driver @<:@default=check@:>@]) ], [], [with_uhd="check"]) +AC_ARG_WITH([soapy], [AS_HELP_STRING([--with-soapy], [compile with SoapySDR driver @<:@default=check@:>@]) ], [], [with_soapy="check"]) +AS_IF([test "x$with_uhd" != xno], [PKG_CHECK_MODULES(UHD, uhd >= 3.0.0, with_sdr=yes with_uhd=yes, with_uhd=no)]) +AS_IF([test "x$with_soapy" != xno], [PKG_CHECK_MODULES(SOAPY, SoapySDR >= 0.6.0, with_sdr=yes with_soapy=yes, with_soapy=no)]) +AM_CONDITIONAL(HAVE_UHD, test "x$with_uhd" == "xyes" ) +AM_CONDITIONAL(HAVE_SOAPY, test "x$with_soapy" == "xyes" ) +AM_CONDITIONAL(HAVE_SDR, test "x$with_sdr" == "xyes" ) +AS_IF([test "x$with_uhd" == "xyes"],[AC_MSG_NOTICE( Compiling with UHD SDR support )], []) +AS_IF([test "x$with_soapy" == "xyes"],[AC_MSG_NOTICE( Compiling with SoapySDR support )], []) AC_OUTPUT( src/common/Makefile diff --git a/src/amps/Makefile.am b/src/amps/Makefile.am index eb86101..20af5ac 100644 --- a/src/amps/Makefile.am +++ b/src/amps/Makefile.am @@ -22,5 +22,6 @@ amps_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm diff --git a/src/anetz/Makefile.am b/src/anetz/Makefile.am index 47bbbcf..4fa79b0 100644 --- a/src/anetz/Makefile.am +++ b/src/anetz/Makefile.am @@ -14,5 +14,6 @@ anetz_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm diff --git a/src/bnetz/Makefile.am b/src/bnetz/Makefile.am index 6249bc8..b19e595 100644 --- a/src/bnetz/Makefile.am +++ b/src/bnetz/Makefile.am @@ -16,5 +16,6 @@ bnetz_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm diff --git a/src/cnetz/Makefile.am b/src/cnetz/Makefile.am index 7fe7b2c..79d008f 100644 --- a/src/cnetz/Makefile.am +++ b/src/cnetz/Makefile.am @@ -20,5 +20,6 @@ cnetz_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm diff --git a/src/common/Makefile.am b/src/common/Makefile.am index 4ac6c67..fb7968a 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -45,3 +45,10 @@ libcommon_a_SOURCES += \ ../common/uhd.c endif +if HAVE_SOAPY +AM_CPPFLAGS += -DHAVE_SOAPY + +libcommon_a_SOURCES += \ + ../common/soapy.c +endif + diff --git a/src/common/main_common.c b/src/common/main_common.c index 13fb5d6..76fcd63 100644 --- a/src/common/main_common.c +++ b/src/common/main_common.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "sample.h" #include "main.h" #include "debug.h" @@ -61,6 +62,8 @@ const char *write_rx_wave = NULL; const char *write_tx_wave = NULL; const char *read_rx_wave = NULL; static const char *sdr_args = ""; +static int sdr_uhd = 0; +static int sdr_soapy = 0; double sdr_rx_gain = 0, sdr_tx_gain = 0; const char *write_iq_rx_wave = NULL; const char *write_iq_tx_wave = NULL; @@ -124,8 +127,17 @@ void print_help_common(const char *arg0, const char *ext_usage) printf(" Replace received audio by given wave file.\n"); #ifdef HAVE_SDR printf("\nSDR options:\n"); +#ifdef HAVE_UHD + printf(" --sdr-uhd\n"); + printf(" Force UHD driver\n"); +#endif +#ifdef HAVE_SOAPY + printf(" --sdr-soapy\n"); + printf(" Force SoapySDR driver\n"); +#endif printf(" --sdr-args \n"); - printf(" Optional SDR device arguments\n"); + printf(" Optional SDR device arguments, seperated by comma\n"); + printf(" e.g. --sdr-args =[,=[,...]]\n"); printf(" --sdr-rx-gain \n"); printf(" SDR device's RX gain in dB (default = %.1f)\n", sdr_rx_gain); printf(" --sdr-tx-gain \n"); @@ -154,12 +166,14 @@ void print_hotkeys_common(void) #define OPT_READ_RX_WAVE 1003 #define OPT_CALL_SAMPLERATE 1004 -#define OPT_SDR_ARGS 1100 -#define OPT_SDR_RX_GAIN 1101 -#define OPT_SDR_TX_GAIN 1102 -#define OPT_WRITE_IQ_RX_WAVE 1103 -#define OPT_WRITE_IQ_TX_WAVE 1104 -#define OPT_READ_IQ_RX_WAVE 1105 +#define OPT_SDR_UHD 1100 +#define OPT_SDR_SOAPY 1101 +#define OPT_SDR_ARGS 1102 +#define OPT_SDR_RX_GAIN 1103 +#define OPT_SDR_TX_GAIN 1104 +#define OPT_WRITE_IQ_RX_WAVE 1105 +#define OPT_WRITE_IQ_TX_WAVE 1106 +#define OPT_READ_IQ_RX_WAVE 1107 static struct option long_options_common[] = { {"help", 0, 0, 'h'}, @@ -172,7 +186,7 @@ static struct option long_options_common[] = { {"buffer", 1, 0, 'b'}, {"pre-emphasis", 0, 0, 'p'}, {"de-emphasis", 0, 0, 'd'}, - {"rx-gain", 0, 0, 'g'}, + {"rx-gain", 1, 0, 'g'}, {"mncc-sock", 0, 0, 'm'}, {"call-device", 1, 0, 'c'}, {"call-samplerate", 1, 0, OPT_CALL_SAMPLERATE}, @@ -182,6 +196,8 @@ static struct option long_options_common[] = { {"write-rx-wave", 1, 0, OPT_WRITE_RX_WAVE}, {"write-tx-wave", 1, 0, OPT_WRITE_TX_WAVE}, {"read-rx-wave", 1, 0, OPT_READ_RX_WAVE}, + {"sdr-uhd", 0, 0, OPT_SDR_UHD}, + {"sdr-soapy", 0, 0, OPT_SDR_SOAPY}, {"sdr-args", 1, 0, OPT_SDR_ARGS}, {"sdr-rx-gain", 1, 0, OPT_SDR_RX_GAIN}, {"sdr-tx-gain", 1, 0, OPT_SDR_TX_GAIN}, @@ -331,6 +347,14 @@ void opt_switch_common(int c, char *arg0, int *skip_args) read_rx_wave = strdup(optarg); *skip_args += 2; break; + case OPT_SDR_UHD: + sdr_uhd = 1; + *skip_args += 1; + break; + case OPT_SDR_SOAPY: + sdr_soapy = 1; + *skip_args += 1; + break; case OPT_SDR_ARGS: sdr_args = strdup(optarg); *skip_args += 2; @@ -413,8 +437,25 @@ int init_common(const char *station_id, int station_id_digits) return rc; } +#ifdef HAVE_UHD + #ifdef HAVE_SOAPY + if ((sdr_uhd == 1 && sdr_soapy == 1) || (sdr_uhd == 0 && sdr_soapy == 0)) { + fprintf(stderr, "UHD and SoapySDR drivers are compiled in. You must choose which one you want: --sdr-uhd or --sdr-soapy\n"); + return -EINVAL; + } + #else + sdr_uhd = 1; + sdr_soapy = 0; + #endif +#else + #ifdef HAVE_SOAPY + sdr_uhd = 0; + sdr_soapy = 1; + #endif +#endif + #ifdef HAVE_SDR - rc = sdr_init(sdr_args, sdr_rx_gain, sdr_tx_gain, write_iq_rx_wave, write_iq_tx_wave, read_iq_rx_wave); + rc = sdr_init(sdr_uhd, sdr_soapy, sdr_args, sdr_rx_gain, sdr_tx_gain, write_iq_rx_wave, write_iq_tx_wave, read_iq_rx_wave); if (rc < 0) return rc; #endif diff --git a/src/common/sdr.c b/src/common/sdr.c index 0d0a595..bf158cf 100644 --- a/src/common/sdr.c +++ b/src/common/sdr.c @@ -29,6 +29,9 @@ #ifdef HAVE_UHD #include "uhd.h" #endif +#ifdef HAVE_SOAPY +#include "soapy.h" +#endif #include "debug.h" typedef struct sdr_chan { @@ -50,12 +53,15 @@ typedef struct sdr { wave_play_t wave_rx_play; } sdr_t; +static int sdr_use_uhd, sdr_use_soapy; static const char *sdr_device_args; static double sdr_rx_gain, sdr_tx_gain; const char *sdr_write_iq_rx_wave, *sdr_write_iq_tx_wave, *sdr_read_iq_rx_wave; -int sdr_init(const char *device_args, double rx_gain, double tx_gain, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave) +int sdr_init(int sdr_uhd, int sdr_soapy, const char *device_args, double rx_gain, double tx_gain, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave) { + sdr_use_uhd = sdr_uhd; + sdr_use_soapy = sdr_soapy; sdr_device_args = strdup(device_args); sdr_rx_gain = rx_gain; sdr_tx_gain = tx_gain; @@ -199,9 +205,19 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq } #ifdef HAVE_UHD - rc = uhd_open(sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain); - if (rc) - goto error; + if (sdr_use_uhd) { + rc = uhd_open(sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain); + if (rc) + goto error; + } +#endif + +#ifdef HAVE_SOAPY + if (sdr_use_soapy) { + rc = soapy_open(sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain); + if (rc) + goto error; + } #endif return sdr; @@ -216,7 +232,13 @@ void sdr_close(void *inst) sdr_t *sdr = (sdr_t *)inst; #ifdef HAVE_UHD - uhd_close(); + if (sdr_use_uhd) + uhd_close(); +#endif + +#ifdef HAVE_SOAPY + if (sdr_use_soapy) + soapy_close(); #endif if (sdr) { @@ -234,7 +256,7 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr sdr_t *sdr = (sdr_t *)inst; float buff[num * 2]; int c, s, ss; - int sent; + int sent = 0; if (channels != sdr->channels) { PDEBUG(DSDR, DEBUG_ERROR, "Invalid number of channels, please fix!\n"); @@ -261,7 +283,12 @@ int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal __attr } #ifdef HAVE_UHD - sent = uhd_send(buff, num); + if (sdr_use_uhd) + sent = uhd_send(buff, num); +#endif +#ifdef HAVE_SOAPY + if (sdr_use_soapy) + sent = soapy_send(buff, num); #endif if (sent < 0) return sent; @@ -273,11 +300,16 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels) { sdr_t *sdr = (sdr_t *)inst; float buff[num * 2]; - int count; + int count = 0; int c, s, ss; #ifdef HAVE_UHD - count = uhd_receive(buff, num); + if (sdr_use_uhd) + count = uhd_receive(buff, num); +#endif +#ifdef HAVE_SOAPY + if (sdr_use_soapy) + count = soapy_receive(buff, num); #endif if (count <= 0) return count; @@ -312,10 +344,15 @@ int sdr_read(void *inst, sample_t **samples, int num, int channels) int sdr_get_inbuffer(void __attribute__((__unused__)) *inst) { // sdr_t *sdr = (sdr_t *)inst; - int count; + int count = 0; #ifdef HAVE_UHD - count = uhd_get_inbuffer(); + if (sdr_use_uhd) + count = uhd_get_inbuffer(); +#endif +#ifdef HAVE_SOAPY + if (sdr_use_soapy) + count = soapy_get_inbuffer(); #endif if (count < 0) return count; diff --git a/src/common/sdr.h b/src/common/sdr.h index 5495de6..ac00a2d 100644 --- a/src/common/sdr.h +++ b/src/common/sdr.h @@ -1,5 +1,5 @@ -int sdr_init(const char *device_args, double rx_gain, double tx_gain, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave); +int sdr_init(int sdr_uhd, int sdr_soapy, const char *device_args, double rx_gain, double tx_gain, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave); void *sdr_open(const char *audiodev, double *tx_frequency, double *rx_frequency, int channels, double paging_frequency, int samplerate, double bandwidth, double sample_deviation); void sdr_close(void *inst); int sdr_write(void *inst, sample_t **samples, int num, enum paging_signal *paging_signal, int *on, int channels); diff --git a/src/common/soapy.c b/src/common/soapy.c new file mode 100644 index 0000000..c31e29f --- /dev/null +++ b/src/common/soapy.c @@ -0,0 +1,281 @@ +/* SoapySDR device access + * + * (C) 2017 by Andreas Eversberg + * All Rights Reserved + * + * This program is free software: you can redistribute it and/or modify + * it under the terms of the GNU General Public License as published by + * the Free Software Foundation, either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + */ + +#include +#include +#include +#include +#include +#include +#include +#include "soapy.h" +#include "debug.h" + +static SoapySDRDevice *sdr = NULL; +SoapySDRStream *rxStream = NULL; +SoapySDRStream *txStream = NULL; +static int tx_samps_per_buff, rx_samps_per_buff; +static double samplerate; +static long long rx_count = 0; +static long long tx_count = 0; + +int soapy_open(const char *device_args, double tx_frequency, double rx_frequency, double rate, double rx_gain, double tx_gain) +{ + double got_frequency, got_rate, got_gain; + size_t channel = 0; + char *arg_string = strdup(device_args), *key, *val; + SoapySDRKwargs args; + + samplerate = rate; + + /* create SoapySDR device */ + PDEBUG(DUHD, DEBUG_INFO, "Creating SoapySDR with args \"%s\"...\n", arg_string); + memset(&args, 0, sizeof(args)); + while (arg_string && *arg_string) { + key = arg_string; + val = strchr(key, '='); + if (!val) { + PDEBUG(DUHD, DEBUG_ERROR, "Error parsing SDR args: No '=' after key\n"); + soapy_close(); + return -EIO; + } + val++; + arg_string = strchr(val, ','); + if (arg_string) + *arg_string++ = '\0'; + SoapySDRKwargs_set(&args, key, val); + } + sdr = SoapySDRDevice_make(&args); + if (!sdr) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to create SoapySDR\n"); + soapy_close(); + return -EIO; + } + + /* set rate */ + if (SoapySDRDevice_setSampleRate(sdr, SOAPY_SDR_TX, channel, rate) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX rate to %.0f Hz\n", rate); + soapy_close(); + return -EIO; + } + if (SoapySDRDevice_setSampleRate(sdr, SOAPY_SDR_RX, channel, rate) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX rate to %.0f Hz\n", rate); + soapy_close(); + return -EIO; + } + + /* see what rate actually is */ + got_rate = SoapySDRDevice_getSampleRate(sdr, SOAPY_SDR_TX, channel); + if (got_rate != rate) { + PDEBUG(DUHD, DEBUG_ERROR, "Given TX rate %.0f Hz is not supported, try %0.f Hz\n", rate, got_rate); + soapy_close(); + return -EINVAL; + } + got_rate = SoapySDRDevice_getSampleRate(sdr, SOAPY_SDR_RX, channel); + if (got_rate != rate) { + PDEBUG(DUHD, DEBUG_ERROR, "Given RX rate %.0f Hz is not supported, try %0.f Hz\n", rate, got_rate); + soapy_close(); + return -EINVAL; + } + + /* set gain */ + if (SoapySDRDevice_setGain(sdr, SOAPY_SDR_TX, channel, tx_gain) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX gain to %.0f\n", tx_gain); + soapy_close(); + return -EIO; + } + if (SoapySDRDevice_setGain(sdr, SOAPY_SDR_RX, channel, rx_gain) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX gain to %.0f\n", rx_gain); + soapy_close(); + return -EIO; + } + + /* see what gain actually is */ + got_gain = SoapySDRDevice_getGain(sdr, SOAPY_SDR_TX, channel); + if (got_gain != tx_gain) { + PDEBUG(DUHD, DEBUG_NOTICE, "Given TX gain %.0f is not supported, we use %0.f\n", tx_gain, got_gain); + tx_gain = got_gain; + } + got_gain = SoapySDRDevice_getGain(sdr, SOAPY_SDR_RX, channel); + if (got_gain != rx_gain) { + PDEBUG(DUHD, DEBUG_NOTICE, "Given RX gain %.3f is not supported, we use %.3f\n", rx_gain, got_gain); + rx_gain = got_gain; + } + + /* set frequency */ + if (SoapySDRDevice_setFrequency(sdr, SOAPY_SDR_TX, channel, tx_frequency, NULL) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX frequency to %.0f Hz\n", tx_frequency); + soapy_close(); + return -EIO; + } + if (SoapySDRDevice_setFrequency(sdr, SOAPY_SDR_RX, channel, rx_frequency, NULL) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX frequency to %.0f Hz\n", rx_frequency); + soapy_close(); + return -EIO; + } + + /* see what frequency actually is */ + got_frequency = SoapySDRDevice_getFrequency(sdr, SOAPY_SDR_TX, channel); + if (got_frequency != tx_frequency) { + PDEBUG(DUHD, DEBUG_ERROR, "Given TX frequency %.0f Hz is not supported, try %0.f Hz\n", tx_frequency, got_frequency); + soapy_close(); + return -EINVAL; + } + got_frequency = SoapySDRDevice_getFrequency(sdr, SOAPY_SDR_RX, channel); + if (got_frequency != rx_frequency) { + PDEBUG(DUHD, DEBUG_ERROR, "Given RX frequency %.0f Hz is not supported, try %0.f Hz\n", rx_frequency, got_frequency); + soapy_close(); + return -EINVAL; + } + + /* set up streamer */ + if (SoapySDRDevice_setupStream(sdr, &txStream, SOAPY_SDR_TX, SOAPY_SDR_CF32, &channel, 1, NULL) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX streamer args\n"); + soapy_close(); + return -EIO; + } + if (SoapySDRDevice_setupStream(sdr, &rxStream, SOAPY_SDR_RX, SOAPY_SDR_CF32, &channel, 1, NULL) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX streamer args\n"); + soapy_close(); + return -EIO; + } + + /* get buffer sizes */ + tx_samps_per_buff = SoapySDRDevice_getStreamMTU(sdr, txStream); + if (tx_samps_per_buff == 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to get TX streamer sample buffer\n"); + soapy_close(); + return -EIO; + } + rx_samps_per_buff = SoapySDRDevice_getStreamMTU(sdr, rxStream); + if (rx_samps_per_buff == 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to get RX streamer sample buffer\n"); + soapy_close(); + return -EIO; + } + + /* enable rx stream */ + if (SoapySDRDevice_activateStream(sdr, rxStream, 0, 0, 0) != 0) { + PDEBUG(DUHD, DEBUG_ERROR, "Failed to issue RX stream command\n"); + soapy_close(); + return -EIO; + } + return 0; +} + +void soapy_close(void) +{ + PDEBUG(DUHD, DEBUG_DEBUG, "Clean up UHD\n"); + if (txStream) { + SoapySDRDevice_closeStream(sdr, txStream); + txStream = NULL; + } + if (rxStream) { + SoapySDRDevice_deactivateStream(sdr, rxStream, 0, 0); + SoapySDRDevice_closeStream(sdr, rxStream); + rxStream = NULL; + } + if (sdr) { + SoapySDRDevice_unmake(sdr); + sdr = NULL; + } +} + +int soapy_send(float *buff, int num) +{ + const void *buffs_ptr[1]; + int chunk; + int sent = 0, count; + int flags = 0; + + while (num) { + chunk = num; + if (chunk > tx_samps_per_buff) + chunk = tx_samps_per_buff; + /* create tx metadata */ + buffs_ptr[0] = buff; + count = SoapySDRDevice_writeStream(sdr, txStream, buffs_ptr, chunk, &flags, 0, 0); + if (count <= 0) + break; + + /* increment tx counter */ + tx_count += count; + + sent += count; + buff += count * 2; + num -= count; + } + + return sent; +} + +/* read what we got, return 0, if buffer is empty, otherwise return the number of samples */ +int soapy_receive(float *buff, int max) +{ + void *buffs_ptr[1]; + int got = 0, count; + long long timeNs; + int flags = 0; + + while (1) { + if (max < rx_samps_per_buff) { + PDEBUG(DUHD, DEBUG_ERROR, "SDR rx buffer overflow!\n"); + break; + } + /* read RX stream */ + buffs_ptr[0] = buff; + count = SoapySDRDevice_readStream(sdr, rxStream, buffs_ptr, rx_samps_per_buff, &flags, &timeNs, 0); + if (count > 0) { + /* update current rx time */ + rx_count += count; + /* commit received data to buffer */ + got += count; + buff += count * 2; + max -= count; + } else { + /* got nothing this time */ + break; + } + } + + return got; +} + +/* estimate current unsent number of samples */ +int soapy_get_inbuffer(void) +{ + long long advance; + + /* we need the rx time stamp to determine how much data is already sent in advance */ + if (rx_count == 0) + return -EAGAIN; + + /* if we have not yet sent any data, we set initial tx time stamp */ + if (tx_count == 0) + tx_count = rx_count; + + /* we check how advance our transmitted time stamp is */ + advance = tx_count - rx_count; + /* in case of underrun: */ + if (advance < 0) + advance = 0; + + return advance; +} + diff --git a/src/common/soapy.h b/src/common/soapy.h new file mode 100644 index 0000000..ee7c59a --- /dev/null +++ b/src/common/soapy.h @@ -0,0 +1,7 @@ + +int soapy_open(const char *device_args, double tx_frequency, double rx_frequency, double rate, double rx_gain, double tx_gain); +void soapy_close(void); +int soapy_send(float *buff, int num); +int soapy_receive(float *buff, int max); +int soapy_get_inbuffer(void); + diff --git a/src/common/uhd.c b/src/common/uhd.c index 8437e3b..f79d851 100644 --- a/src/common/uhd.c +++ b/src/common/uhd.c @@ -166,14 +166,14 @@ int uhd_open(const char *device_args, double tx_frequency, double rx_frequency, tune_request.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO; error = uhd_usrp_set_tx_freq(usrp, &tune_request, channel, &tune_result); if (error) { - PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX rate to %.0f Hz\n", tx_frequency); + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX frequeny to %.0f Hz\n", tx_frequency); uhd_close(); return -EIO; } tune_request.target_freq = rx_frequency; error = uhd_usrp_set_rx_freq(usrp, &tune_request, channel, &tune_result); if (error) { - PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX rate to %.0f Hz\n", rx_frequency); + PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX frequeny to %.0f Hz\n", rx_frequency); uhd_close(); return -EIO; } @@ -327,7 +327,7 @@ int uhd_receive(float *buff, int max) while (1) { if (max < (int)rx_samps_per_buff) { PDEBUG(DUHD, DEBUG_ERROR, "SDR rx buffer overflow!\n"); - return 0; + break; } /* read RX stream */ buffs_ptr[0] = buff; @@ -362,7 +362,7 @@ int uhd_receive(float *buff, int max) } check_rate = 0; rx_gap = diff_time * (double)samplerate + 0.5; - PDEBUG(DUHD, DEBUG_ERROR, "Lost rx frame(s): A gap of %.6f secods (%d samples), \n", diff_time, rx_gap); + PDEBUG(DUHD, DEBUG_ERROR, "Lost rx frame(s): A gap of %.6f seconds (%d samples), \n", diff_time, rx_gap); } } break; diff --git a/src/nmt/Makefile.am b/src/nmt/Makefile.am index cd45ef5..f76311c 100644 --- a/src/nmt/Makefile.am +++ b/src/nmt/Makefile.am @@ -19,5 +19,6 @@ nmt_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm diff --git a/src/test/Makefile.am b/src/test/Makefile.am index eb50f7d..393a0b5 100644 --- a/src/test/Makefile.am +++ b/src/test/Makefile.am @@ -16,6 +16,7 @@ test_filter_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm test_compandor_SOURCES = test_compandor.c @@ -32,6 +33,7 @@ test_emphasis_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm test_dms_SOURCES = \ @@ -44,6 +46,7 @@ test_dms_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm test_sms_SOURCES = \ @@ -56,6 +59,7 @@ test_sms_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm test_performance_SOURCES = dummy.c test_performance.c @@ -65,5 +69,6 @@ test_performance_LDADD = \ $(top_builddir)/src/common/libcommon.a \ $(ALSA_LIBS) \ $(UHD_LIBS) \ + $(SOAPY_LIBS) \ -lm