Fixing and improving SDR support (SoapySDR and UHD)

- Soapy SDR now works.
- Channels can be selected.
- Antennas can be listed and selected.
- Device args, tune args, stream args can be specified.
This commit is contained in:
Andreas Eversberg 2017-07-11 20:26:40 +02:00
parent 538b4a42ec
commit fda224c27f
10 changed files with 395 additions and 114 deletions

View File

@ -37,8 +37,8 @@ AS_IF([test "x$with_soapy" != xno], [PKG_CHECK_MODULES(SOAPY, SoapySDR >= 0.6.0,
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 )], [])
AS_IF([test "x$with_uhd" == "xyes"],[AC_MSG_NOTICE( Compiling with UHD SDR support )], [AC_MSG_NOTICE( UHD SDR not support )])
AS_IF([test "x$with_soapy" == "xyes"],[AC_MSG_NOTICE( Compiling with SoapySDR support )], [AC_MSG_NOTICE( SoapySDR not support )])
AC_OUTPUT(
src/common/Makefile

View File

@ -58,6 +58,7 @@ struct debug_cat {
{ "sms", "\033[1;37m" },
{ "sdr", "\033[1;31m" },
{ "uhd", "\033[1;35m" },
{ "soapy", "\033[1;35m" },
{ NULL, NULL }
};

View File

@ -21,6 +21,7 @@
#define DSMS 14
#define DSDR 15
#define DUHD 16
#define DSOAPY 17
#define PDEBUG(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, -1, fmt, ## arg)
#define PDEBUG_CHAN(cat, level, fmt, arg...) _printdebug(__FILE__, __FUNCTION__, __LINE__, cat, level, CHAN, fmt, ## arg)

View File

@ -59,23 +59,24 @@ int send_patterns = 1;
int release_on_disconnect = 1;
int loopback = 0;
int rt_prio = 0;
const char *write_rx_wave = NULL;
const char *write_tx_wave = NULL;
const char *read_rx_wave = NULL;
const char *write_rx_wave = NULL;
const char *read_tx_wave = NULL;
const char *read_rx_wave = NULL;
int use_sdr = 0;
int sdr_channel = 0;
static const char *sdr_args = "";
static const char *sdr_device_args = "", *sdr_stream_args = "", *sdr_tune_args = "";
static double sdr_bandwidth = 0.0;
#ifdef HAVE_SDR
static int sdr_uhd = 0;
static int sdr_soapy = 0;
#endif
double sdr_rx_gain = 0, sdr_tx_gain = 0;
const char *write_iq_rx_wave = NULL;
double sdr_tx_gain = 0, sdr_rx_gain = 0;
const char *sdr_tx_antenna = "", *sdr_rx_antenna = "";
const char *write_iq_tx_wave = NULL;
const char *read_iq_rx_wave = NULL;
const char *write_iq_rx_wave = NULL;
const char *read_iq_tx_wave = NULL;
const char *read_iq_rx_wave = NULL;
void print_help_common(const char *arg0, const char *ext_usage)
{
printf("Usage: %s -k <kanal/channel> %s[options] [station-id]\n", arg0, ext_usage);
@ -150,11 +151,17 @@ void print_help_common(const char *arg0, const char *ext_usage)
#endif
printf(" --sdr-channel <channel #>\n");
printf(" Give channel number for multi channel SDR device (default = %d)\n", sdr_channel);
printf(" --sdr-args <args>\n");
printf(" --sdr-device-args <args>\n");
printf(" --sdr-stream-args <args>\n");
printf(" --sdr-tune-args <args>\n");
printf(" Optional SDR device arguments, seperated by comma\n");
printf(" e.g. --sdr-args <key>=<value>[,<key>=<value>[,...]]\n");
printf(" e.g. --sdr-device-args <key>=<value>[,<key>=<value>[,...]]\n");
printf(" --sdr-bandwidth <bandwidth>\n");
printf(" Give IF filter bandwidth to use. If not, sample rate is used.\n");
printf(" --sdr-rx-antenna <name>\n");
printf(" SDR device's RX antenna name, use 'list' to get a list\n");
printf(" --sdr-tx-antenna <name>\n");
printf(" SDR device's TX antenna name, use 'list' to get a list\n");
printf(" --sdr-rx-gain <gain>\n");
printf(" SDR device's RX gain in dB (default = %.1f)\n", sdr_rx_gain);
printf(" --sdr-tx-gain <gain>\n");
@ -195,14 +202,18 @@ void print_hotkeys_common(void)
#define OPT_SDR_UHD 1100
#define OPT_SDR_SOAPY 1101
#define OPT_SDR_CHANNEL 1102
#define OPT_SDR_ARGS 1103
#define OPT_SDR_RX_GAIN 1104
#define OPT_SDR_TX_GAIN 1105
#define OPT_SDR_BANDWIDTH 1106
#define OPT_WRITE_IQ_RX_WAVE 1107
#define OPT_WRITE_IQ_TX_WAVE 1108
#define OPT_READ_IQ_RX_WAVE 1109
#define OPT_READ_IQ_TX_WAVE 1110
#define OPT_SDR_DEVICE_ARGS 1103
#define OPT_SDR_STREAM_ARGS 1104
#define OPT_SDR_TUNE_ARGS 1105
#define OPT_SDR_RX_ANTENNA 1106
#define OPT_SDR_TX_ANTENNA 1107
#define OPT_SDR_RX_GAIN 1108
#define OPT_SDR_TX_GAIN 1109
#define OPT_SDR_BANDWIDTH 1110
#define OPT_WRITE_IQ_RX_WAVE 1111
#define OPT_WRITE_IQ_TX_WAVE 1112
#define OPT_READ_IQ_RX_WAVE 1113
#define OPT_READ_IQ_TX_WAVE 1114
static struct option long_options_common[] = {
{"help", 0, 0, 'h'},
@ -230,8 +241,12 @@ static struct option long_options_common[] = {
{"sdr-uhd", 0, 0, OPT_SDR_UHD},
{"sdr-soapy", 0, 0, OPT_SDR_SOAPY},
{"sdr-channel", 1, 0, OPT_SDR_CHANNEL},
{"sdr-args", 1, 0, OPT_SDR_ARGS},
{"sdr-device-args", 1, 0, OPT_SDR_DEVICE_ARGS},
{"sdr-stream-args", 1, 0, OPT_SDR_STREAM_ARGS},
{"sdr-tune-args", 1, 0, OPT_SDR_TUNE_ARGS},
{"sdr-bandwidth", 1, 0, OPT_SDR_BANDWIDTH},
{"sdr-rx-antenna", 1, 0, OPT_SDR_RX_ANTENNA},
{"sdr-tx-antenna", 1, 0, OPT_SDR_TX_ANTENNA},
{"sdr-rx-gain", 1, 0, OPT_SDR_RX_GAIN},
{"sdr-tx-gain", 1, 0, OPT_SDR_TX_GAIN},
{"write-iq-rx-wave", 1, 0, OPT_WRITE_IQ_RX_WAVE},
@ -413,14 +428,30 @@ void opt_switch_common(int c, char *arg0, int *skip_args)
sdr_channel = atoi(optarg);
*skip_args += 2;
break;
case OPT_SDR_ARGS:
sdr_args = strdup(optarg);
case OPT_SDR_DEVICE_ARGS:
sdr_device_args = strdup(optarg);
*skip_args += 2;
break;
case OPT_SDR_STREAM_ARGS:
sdr_stream_args = strdup(optarg);
*skip_args += 2;
break;
case OPT_SDR_TUNE_ARGS:
sdr_tune_args = strdup(optarg);
*skip_args += 2;
break;
case OPT_SDR_BANDWIDTH:
sdr_bandwidth = atof(optarg);
*skip_args += 2;
break;
case OPT_SDR_RX_ANTENNA:
sdr_rx_antenna = strdup(optarg);
*skip_args += 2;
break;
case OPT_SDR_TX_ANTENNA:
sdr_tx_antenna = strdup(optarg);
*skip_args += 2;
break;
case OPT_SDR_RX_GAIN:
sdr_rx_gain = atof(optarg);
*skip_args += 2;
@ -523,7 +554,7 @@ void main_common(int *quit, int latency, int interval, void (*myhandler)(void),
if (sdr_bandwidth == 0.0)
sdr_bandwidth = samplerate;
rc = sdr_init(sdr_uhd, sdr_soapy, sdr_channel, sdr_args, sdr_rx_gain, sdr_tx_gain, sdr_bandwidth, write_iq_rx_wave, write_iq_tx_wave, read_iq_rx_wave, read_iq_tx_wave);
rc = sdr_init(sdr_uhd, sdr_soapy, sdr_channel, sdr_device_args, sdr_stream_args, sdr_tune_args, sdr_tx_antenna, sdr_rx_antenna, sdr_tx_gain, sdr_rx_gain, sdr_bandwidth, write_iq_tx_wave, write_iq_rx_wave, read_iq_tx_wave, read_iq_rx_wave);
if (rc < 0)
return;
#endif

View File

@ -57,24 +57,29 @@ typedef struct sdr {
static int sdr_use_uhd, sdr_use_soapy;
static int sdr_channel;
static const char *sdr_device_args;
static const char *sdr_device_args, *sdr_stream_args, *sdr_tune_args;
static const char *sdr_rx_antenna, *sdr_tx_antenna;
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, *sdr_read_iq_tx_wave;
static double sdr_bandwidth;
int sdr_init(int sdr_uhd, int sdr_soapy, int channel, const char *device_args, double rx_gain, double tx_gain, double bandwidth, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave, const char *read_iq_tx_wave)
int sdr_init(int sdr_uhd, int sdr_soapy, int channel, const char *device_args, const char *stream_args, const char *tune_args, const char *tx_antenna, const char *rx_antenna, double tx_gain, double rx_gain, double bandwidth, const char *write_iq_tx_wave, const char *write_iq_rx_wave, const char *read_iq_tx_wave, const char *read_iq_rx_wave)
{
sdr_use_uhd = sdr_uhd;
sdr_use_soapy = sdr_soapy;
sdr_channel = channel;
sdr_device_args = strdup(device_args);
sdr_rx_gain = rx_gain;
sdr_stream_args = strdup(stream_args);
sdr_tune_args = strdup(tune_args);
sdr_tx_antenna = strdup(tx_antenna);
sdr_rx_antenna = strdup(rx_antenna);
sdr_tx_gain = tx_gain;
sdr_rx_gain = rx_gain;
sdr_bandwidth = bandwidth;
sdr_write_iq_rx_wave = write_iq_rx_wave;
sdr_write_iq_tx_wave = write_iq_tx_wave;
sdr_read_iq_rx_wave = read_iq_rx_wave;
sdr_write_iq_rx_wave = write_iq_rx_wave;
sdr_read_iq_tx_wave = read_iq_tx_wave;
sdr_read_iq_rx_wave = read_iq_rx_wave;
return 0;
}
@ -242,7 +247,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
#ifdef HAVE_UHD
if (sdr_use_uhd) {
rc = uhd_open(sdr_channel, sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain, sdr_bandwidth);
rc = uhd_open(sdr_channel, sdr_device_args, sdr_stream_args, sdr_tune_args, sdr_tx_antenna, sdr_rx_antenna, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_tx_gain, sdr_rx_gain, sdr_bandwidth);
if (rc)
goto error;
}
@ -250,7 +255,7 @@ void *sdr_open(const char __attribute__((__unused__)) *audiodev, double *tx_freq
#ifdef HAVE_SOAPY
if (sdr_use_soapy) {
rc = soapy_open(sdr_channel, sdr_device_args, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_rx_gain, sdr_tx_gain, sdr_bandwidth);
rc = soapy_open(sdr_channel, sdr_device_args, sdr_stream_args, sdr_tune_args, sdr_tx_antenna, sdr_rx_antenna, tx_center_frequency, rx_center_frequency, sdr->samplerate, sdr_tx_gain, sdr_rx_gain, sdr_bandwidth);
if (rc)
goto error;
}

View File

@ -1,5 +1,5 @@
int sdr_init(int sdr_uhd, int sdr_soapy, int channel, const char *device_args, double rx_gain, double tx_gain, double bandwidth, const char *write_iq_rx_wave, const char *write_iq_tx_wave, const char *read_iq_rx_wave, const char *read_iq_tx_wave);
int sdr_init(int sdr_uhd, int sdr_soapy, int channel, const char *device_args, const char *stream_args, const char *tune_args, const char *tx_antenna, const char *rx_antenna, double tx_gain, double rx_gain, double bandwidth, const char *write_iq_tx_wave, const char *write_iq_rx_wave, const char *read_iq_tx_wave, const char *read_iq_rx_wave);
int sdr_start(void *inst);
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);

View File

@ -35,101 +35,171 @@ static double samplerate;
static uint64_t rx_count = 0;
static uint64_t tx_count = 0;
int soapy_open(size_t channel, const char *device_args, double tx_frequency, double rx_frequency, double rate, double rx_gain, double tx_gain, double bandwidth)
static int parse_args(SoapySDRKwargs *args, const char *_args_string)
{
double got_frequency, got_rate, got_gain, got_bandwidth;
char *arg_string = strdup(device_args), *key, *val;
SoapySDRKwargs args;
char *args_string = strdup(_args_string), *key, *val;
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;
memset(args, 0, sizeof(*args));
while (args_string && *args_string) {
key = args_string;
val = strchr(key, '=');
if (!val) {
PDEBUG(DUHD, DEBUG_ERROR, "Error parsing SDR args: No '=' after key\n");
PDEBUG(DSOAPY, DEBUG_ERROR, "Error parsing SDR args: No '=' after key\n");
soapy_close();
return -EIO;
}
*val++ = '\0';
arg_string = strchr(val, ',');
if (arg_string)
*arg_string++ = '\0';
SoapySDRKwargs_set(&args, key, val);
args_string = strchr(val, ',');
if (args_string)
*args_string++ = '\0';
PDEBUG(DSOAPY, DEBUG_DEBUG, "SDR device args: key='%s' value='%s'\n", key, val);
SoapySDRKwargs_set(args, key, val);
}
sdr = SoapySDRDevice_make(&args);
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 rate, double tx_gain, double rx_gain, double bandwidth)
{
double got_frequency, got_rate, got_gain, got_bandwidth;
const char *got_antenna;
size_t num_channels;
SoapySDRKwargs device_args;
SoapySDRKwargs stream_args;
SoapySDRKwargs tune_args;
int rc;
samplerate = rate;
/* parsing ARGS */
PDEBUG(DSOAPY, DEBUG_INFO, "Using device args \"%s\"\n", _device_args);
rc = parse_args(&device_args, _device_args);
if (rc < 0)
return rc;
PDEBUG(DSOAPY, DEBUG_INFO, "Using stream args \"%s\"\n", _stream_args);
rc = parse_args(&stream_args, _stream_args);
if (rc < 0)
return rc;
PDEBUG(DSOAPY, DEBUG_INFO, "Using tune args \"%s\"\n", _tune_args);
rc = parse_args(&tune_args, _tune_args);
if (rc < 0)
return rc;
/* create SoapySDR device */
sdr = SoapySDRDevice_make(&device_args);
if (!sdr) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to create SoapySDR\n");
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to create SoapySDR\n");
soapy_close();
return -EIO;
}
if (tx_frequency) {
/* get number of channels and check if requested channel is in range */
num_channels = SoapySDRDevice_getNumChannels(sdr, SOAPY_SDR_TX);
PDEBUG(DSOAPY, DEBUG_DEBUG, "We have %d TX channel, selecting channel #%d\n", (int)num_channels, (int)channel);
if (channel >= num_channels) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Requested channel #%d (capable of TX) does not exist. Please select channel %d..%d!\n", (int)channel, 0, (int)num_channels - 1);
soapy_close();
return -EIO;
}
/* antenna */
if (tx_antenna && tx_antenna[0]) {
if (!strcasecmp(tx_antenna, "list")) {
char **antennas;
size_t antennas_length;
int i;
antennas = SoapySDRDevice_listAntennas(sdr, SOAPY_SDR_TX, channel, &antennas_length);
if (!antennas) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to request list of TX antennas!\n");
soapy_close();
return -EIO;
}
for (i = 0; i < (int)antennas_length; i++)
PDEBUG(DSOAPY, DEBUG_NOTICE, "TX Antenna: '%s'\n", antennas[i]);
got_antenna = SoapySDRDevice_getAntenna(sdr, SOAPY_SDR_TX, channel);
PDEBUG(DSOAPY, DEBUG_NOTICE, "Default TX Antenna: '%s'\n", got_antenna);
soapy_close();
return 1;
}
if (SoapySDRDevice_setAntenna(sdr, SOAPY_SDR_TX, channel, tx_antenna) != 0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set TX antenna to '%s'\n", tx_antenna);
soapy_close();
return -EIO;
}
got_antenna = SoapySDRDevice_getAntenna(sdr, SOAPY_SDR_TX, channel);
if (!!strcasecmp(tx_antenna, got_antenna)) {
PDEBUG(DSOAPY, DEBUG_NOTICE, "Given TX antenna '%s' was accepted, but driver claims to use '%s'\n", tx_antenna, got_antenna);
soapy_close();
return -EINVAL;
}
}
/* 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);
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set TX 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 (fabs(got_rate - rate) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given TX rate %.0f Hz is not supported, try %0.f Hz\n", rate, got_rate);
if (fabs(got_rate - rate) > 0.01) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Given TX rate %.3f Hz is not supported, try %.3f 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 (tx_gain) {
/* set gain */
if (SoapySDRDevice_setGain(sdr, SOAPY_SDR_TX, channel, tx_gain) != 0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set TX gain to %.0f\n", tx_gain);
soapy_close();
return -EIO;
}
/* see what gain actually is */
got_gain = SoapySDRDevice_getGain(sdr, SOAPY_SDR_TX, channel);
if (fabs(got_gain - tx_gain) > 0.001) {
PDEBUG(DUHD, DEBUG_NOTICE, "Given TX gain %.0f is not supported, we use %0.f\n", tx_gain, got_gain);
tx_gain = got_gain;
/* see what gain actually is */
got_gain = SoapySDRDevice_getGain(sdr, SOAPY_SDR_TX, channel);
if (fabs(got_gain - tx_gain) > 0.001) {
PDEBUG(DSOAPY, DEBUG_NOTICE, "Given TX gain %.3f is not supported, we use %.3f\n", tx_gain, got_gain);
tx_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);
if (SoapySDRDevice_setFrequency(sdr, SOAPY_SDR_TX, channel, tx_frequency, &tune_args) != 0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set TX frequency to %.0f Hz\n", tx_frequency);
soapy_close();
return -EIO;
}
/* see what frequency actually is */
got_frequency = SoapySDRDevice_getFrequency(sdr, SOAPY_SDR_TX, channel);
if (fabs(got_frequency - tx_frequency) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given TX frequency %.0f Hz is not supported, try %0.f Hz\n", tx_frequency, got_frequency);
if (fabs(got_frequency - tx_frequency) > 100.0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Given TX frequency %.0f Hz is not supported, try %.0f Hz\n", tx_frequency, got_frequency);
soapy_close();
return -EINVAL;
}
/* set bandwidth */
if (SoapySDRDevice_setBandwidth(sdr, SOAPY_SDR_TX, channel, bandwidth) != 0) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX bandwidth to %.0f Hz\n", bandwidth);
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set TX bandwidth to %.0f Hz\n", bandwidth);
soapy_close();
return -EIO;
}
/* see what bandwidth actually is */
got_bandwidth = SoapySDRDevice_getBandwidth(sdr, SOAPY_SDR_TX, channel);
if (fabs(got_bandwidth - bandwidth) >= 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given TX bandwidth %.0f Hz is not supported, try %0.f Hz\n", bandwidth, got_bandwidth);
if (fabs(got_bandwidth - bandwidth) > 100.0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Given TX bandwidth %.0f Hz is not supported, try %.0f Hz\n", bandwidth, got_bandwidth);
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");
if (SoapySDRDevice_setupStream(sdr, &txStream, SOAPY_SDR_TX, SOAPY_SDR_CF32, &channel, 1, &stream_args) != 0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set TX streamer args\n");
soapy_close();
return -EIO;
}
@ -137,75 +207,119 @@ int soapy_open(size_t channel, const char *device_args, double tx_frequency, dou
/* 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");
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to get TX streamer sample buffer\n");
soapy_close();
return -EIO;
}
}
if (rx_frequency) {
/* get number of channels and check if requested channel is in range */
num_channels = SoapySDRDevice_getNumChannels(sdr, SOAPY_SDR_RX);
PDEBUG(DSOAPY, DEBUG_DEBUG, "We have %d RX channel, selecting channel #%d\n", (int)num_channels, (int)channel);
if (channel >= num_channels) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Requested channel #%d (capable of RX) does not exist. Please select channel %d..%d!\n", (int)channel, 0, (int)num_channels - 1);
soapy_close();
return -EIO;
}
/* antenna */
if (rx_antenna && rx_antenna[0]) {
if (!strcasecmp(rx_antenna, "list")) {
char **antennas;
size_t antennas_length;
int i;
antennas = SoapySDRDevice_listAntennas(sdr, SOAPY_SDR_RX, channel, &antennas_length);
if (!antennas) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to request list of RX antennas!\n");
soapy_close();
return -EIO;
}
for (i = 0; i < (int)antennas_length; i++)
PDEBUG(DSOAPY, DEBUG_NOTICE, "RX Antenna: '%s'\n", antennas[i]);
got_antenna = SoapySDRDevice_getAntenna(sdr, SOAPY_SDR_RX, channel);
PDEBUG(DSOAPY, DEBUG_NOTICE, "Default RX Antenna: '%s'\n", got_antenna);
soapy_close();
return 1;
}
if (SoapySDRDevice_setAntenna(sdr, SOAPY_SDR_RX, channel, rx_antenna) != 0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set RX antenna to '%s'\n", rx_antenna);
soapy_close();
return -EIO;
}
got_antenna = SoapySDRDevice_getAntenna(sdr, SOAPY_SDR_RX, channel);
if (!!strcasecmp(rx_antenna, got_antenna)) {
PDEBUG(DSOAPY, DEBUG_NOTICE, "Given RX antenna '%s' was accepted, but driver claims to use '%s'\n", rx_antenna, got_antenna);
soapy_close();
return -EINVAL;
}
}
/* set rate */
if (SoapySDRDevice_setSampleRate(sdr, SOAPY_SDR_RX, channel, rate) != 0) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX rate to %.0f Hz\n", rate);
PDEBUG(DSOAPY, 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_RX, channel);
if (fabs(got_rate - rate) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given RX rate %.0f Hz is not supported, try %0.f Hz\n", rate, got_rate);
if (fabs(got_rate - rate) > 0.01) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Given RX rate %.3f Hz is not supported, try %.3f Hz\n", rate, got_rate);
soapy_close();
return -EINVAL;
}
/* set gain */
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;
}
if (rx_gain) {
/* set gain */
if (SoapySDRDevice_setGain(sdr, SOAPY_SDR_RX, channel, rx_gain) != 0) {
PDEBUG(DSOAPY, 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_RX, channel);
if (fabs(got_gain - rx_gain) > 0.001) {
PDEBUG(DUHD, DEBUG_NOTICE, "Given RX gain %.3f is not supported, we use %.3f\n", rx_gain, got_gain);
rx_gain = got_gain;
/* see what gain actually is */
got_gain = SoapySDRDevice_getGain(sdr, SOAPY_SDR_RX, channel);
if (fabs(got_gain - rx_gain) > 0.001) {
PDEBUG(DSOAPY, 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_RX, channel, rx_frequency, NULL) != 0) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX frequency to %.0f Hz\n", rx_frequency);
if (SoapySDRDevice_setFrequency(sdr, SOAPY_SDR_RX, channel, rx_frequency, &tune_args) != 0) {
PDEBUG(DSOAPY, 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_RX, channel);
if (fabs(got_frequency - rx_frequency) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given RX frequency %.0f Hz is not supported, try %0.f Hz\n", rx_frequency, got_frequency);
if (fabs(got_frequency - rx_frequency) > 100.0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Given RX frequency %.0f Hz is not supported, try %.0f Hz\n", rx_frequency, got_frequency);
soapy_close();
return -EINVAL;
}
/* set bandwidth */
if (SoapySDRDevice_setBandwidth(sdr, SOAPY_SDR_RX, channel, bandwidth) != 0) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX bandwidth to %.0f Hz\n", bandwidth);
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set RX bandwidth to %.0f Hz\n", bandwidth);
soapy_close();
return -EIO;
}
/* see what bandwidth actually is */
got_bandwidth = SoapySDRDevice_getBandwidth(sdr, SOAPY_SDR_RX, channel);
if (fabs(got_bandwidth - bandwidth) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given RX bandwidth %.0f Hz is not supported, try %0.f Hz\n", bandwidth, got_bandwidth);
if (fabs(got_bandwidth - bandwidth) > 100.0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Given RX bandwidth %.0f Hz is not supported, try %.0f Hz\n", bandwidth, got_bandwidth);
soapy_close();
return -EINVAL;
}
/* set up streamer */
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");
if (SoapySDRDevice_setupStream(sdr, &rxStream, SOAPY_SDR_RX, SOAPY_SDR_CF32, &channel, 1, &stream_args) != 0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to set RX streamer args\n");
soapy_close();
return -EIO;
}
@ -213,7 +327,7 @@ int soapy_open(size_t channel, const char *device_args, double tx_frequency, dou
/* get buffer sizes */
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");
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to get RX streamer sample buffer\n");
soapy_close();
return -EIO;
}
@ -227,7 +341,13 @@ int soapy_start(void)
{
/* enable rx stream */
if (SoapySDRDevice_activateStream(sdr, rxStream, 0, 0, 0) != 0) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to issue RX stream command\n");
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to issue RX stream command\n");
return -EIO;
}
/* enable tx stream */
if (SoapySDRDevice_activateStream(sdr, txStream, 0, 0, 0) != 0) {
PDEBUG(DSOAPY, DEBUG_ERROR, "Failed to issue TX stream command\n");
return -EIO;
}
return 0;
@ -235,8 +355,9 @@ int soapy_start(void)
void soapy_close(void)
{
PDEBUG(DUHD, DEBUG_DEBUG, "Clean up UHD\n");
PDEBUG(DSOAPY, DEBUG_DEBUG, "Clean up SoapySDR\n");
if (txStream) {
SoapySDRDevice_deactivateStream(sdr, txStream, 0, 0);
SoapySDRDevice_closeStream(sdr, txStream);
txStream = NULL;
}
@ -290,7 +411,7 @@ int soapy_receive(float *buff, int max)
while (1) {
if (max < rx_samps_per_buff) {
/* no more space this time */
PDEBUG(DUHD, DEBUG_ERROR, "SDR RX overflow!\n");
PDEBUG(DSOAPY, DEBUG_ERROR, "SDR RX overflow!\n");
break;
}
/* read RX stream */
@ -329,7 +450,7 @@ int soapy_get_tosend(int latspl)
tosend = latspl - (tx_count - rx_count);
/* in case of underrun: */
if (tosend < 0) {
PDEBUG(DUHD, DEBUG_ERROR, "SDR TX underrun!\n");
PDEBUG(DSOAPY, DEBUG_ERROR, "SDR TX underrun!\n");
tosend = 0;
}

View File

@ -1,5 +1,5 @@
int soapy_open(size_t channel, const char *device_args, double tx_frequency, double rx_frequency, double rate, double rx_gain, double tx_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, double tx_frequency, double rx_frequency, 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);

View File

@ -45,17 +45,22 @@ static time_t tx_time_secs = 0;
static double tx_time_fract_sec = 0.0;
static int rx_gap = 0; /* if we missed samples, we fill our rx data with zeroes */
int uhd_open(size_t channel, const char *device_args, double tx_frequency, double rx_frequency, double rate, double rx_gain, double tx_gain, double bandwidth)
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 rate, double tx_gain, double rx_gain, double bandwidth)
{
uhd_error error;
double got_frequency, got_rate, got_gain, got_bandwidth;
char got_antenna[64];
samplerate = rate;
check_rate = 1;
PDEBUG(DUHD, DEBUG_INFO, "Using device args \"%s\"\n", _device_args);
PDEBUG(DUHD, DEBUG_INFO, "Using stream args \"%s\"\n", _stream_args);
PDEBUG(DUHD, DEBUG_INFO, "Using tune args \"%s\"\n", _tune_args);
/* create USRP */
PDEBUG(DUHD, DEBUG_INFO, "Creating USRP with args \"%s\"...\n", device_args);
error = uhd_usrp_make(&usrp, device_args);
PDEBUG(DUHD, DEBUG_INFO, "Creating USRP with args \"%s\"...\n", _device_args);
error = uhd_usrp_make(&usrp, _device_args);
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to create USRP\n");
uhd_close();
@ -63,6 +68,64 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
}
if (tx_frequency) {
/* antenna */
if (tx_antenna && tx_antenna[0]) {
if (!strcasecmp(tx_antenna, "list")) {
uhd_string_vector_handle antennas;
size_t antennas_length;
int i;
error = uhd_string_vector_make(&antennas);
if (error) {
tx_vector_error:
PDEBUG(DUHD, DEBUG_ERROR, "Failed to hande UHD vector, please fix!\n");
uhd_close();
return -EIO;
}
error = uhd_usrp_get_tx_antennas(usrp, channel, &antennas);
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to request list of TX antennas!\n");
uhd_close();
return -EIO;
}
error = uhd_string_vector_size(antennas, &antennas_length);
if (error)
goto tx_vector_error;
for (i = 0; i < (int)antennas_length; i++) {
error = uhd_string_vector_at(antennas, i, got_antenna, sizeof(got_antenna));
if (error)
goto tx_vector_error;
PDEBUG(DUHD, DEBUG_NOTICE, "TX Antenna: '%s'\n", got_antenna);
}
uhd_string_vector_free(&antennas);
error = uhd_usrp_get_tx_antenna(usrp, channel, got_antenna, sizeof(got_antenna));
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to get TX antenna\n");
uhd_close();
return -EINVAL;
}
PDEBUG(DUHD, DEBUG_NOTICE, "Default TX Antenna: '%s'\n", got_antenna);
uhd_close();
return 1;
}
error = uhd_usrp_set_tx_antenna(usrp, tx_antenna, channel);
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX antenna to '%s'\n", tx_antenna);
uhd_close();
return -EIO;
}
error = uhd_usrp_get_tx_antenna(usrp, channel, got_antenna, sizeof(got_antenna));
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to get TX antenna\n");
uhd_close();
return -EINVAL;
}
if (!!strcasecmp(tx_antenna, got_antenna)) {
PDEBUG(DUHD, DEBUG_NOTICE, "Given TX antenna '%s' was accepted, but driver claims to use '%s'\n", tx_antenna, got_antenna);
uhd_close();
return -EINVAL;
}
}
/* create streamers */
error = uhd_tx_streamer_make(&tx_streamer);
if (error) {
@ -87,7 +150,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
return -EIO;
}
if (fabs(got_rate - rate) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given TX rate %.0f Hz is not supported, try %0.f Hz\n", rate, got_rate);
PDEBUG(DUHD, DEBUG_ERROR, "Given TX rate %.0f Hz is not supported, try %.0f Hz\n", rate, got_rate);
uhd_close();
return -EINVAL;
}
@ -108,7 +171,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
return -EIO;
}
if (fabs(got_gain - tx_gain) > 0.001) {
PDEBUG(DUHD, DEBUG_NOTICE, "Given TX gain %.0f is not supported, we use %0.f\n", tx_gain, got_gain);
PDEBUG(DUHD, DEBUG_NOTICE, "Given TX gain %.0f is not supported, we use %.0f\n", tx_gain, got_gain);
tx_gain = got_gain;
}
@ -117,6 +180,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
tune_request.target_freq = tx_frequency;
tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO;
tune_request.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO;
tune_request.args = strdup(_tune_args);
error = uhd_usrp_set_tx_freq(usrp, &tune_request, channel, &tune_result);
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set TX frequeny to %.0f Hz\n", tx_frequency);
@ -132,7 +196,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
return -EIO;
}
if (fabs(got_frequency - tx_frequency) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given TX frequency %.0f Hz is not supported, try %0.f Hz\n", tx_frequency, got_frequency);
PDEBUG(DUHD, DEBUG_ERROR, "Given TX frequency %.0f Hz is not supported, try %.0f Hz\n", tx_frequency, got_frequency);
uhd_close();
return -EINVAL;
}
@ -152,7 +216,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
return -EIO;
}
if (fabs(got_bandwidth - bandwidth) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given TX bandwidth %.0f Hz is not supported, try %0.f Hz\n", bandwidth, got_bandwidth);
PDEBUG(DUHD, DEBUG_ERROR, "Given TX bandwidth %.0f Hz is not supported, try %.0f Hz\n", bandwidth, got_bandwidth);
uhd_close();
return -EINVAL;
}
@ -161,7 +225,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
memset(&stream_args, 0, sizeof(stream_args));
stream_args.cpu_format = "fc32";
stream_args.otw_format = "sc16";
stream_args.args = "";
stream_args.args = strdup(_stream_args);
stream_args.channel_list = &channel;
stream_args.n_channels = 1;
error = uhd_usrp_get_tx_stream(usrp, &stream_args, tx_streamer);
@ -181,6 +245,63 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
}
if (rx_frequency) {
/* antenna */
if (rx_antenna && rx_antenna[0]) {
if (!strcasecmp(rx_antenna, "list")) {
uhd_string_vector_handle antennas;
size_t antennas_length;
int i;
error = uhd_string_vector_make(&antennas);
if (error) {
rx_vector_error:
PDEBUG(DUHD, DEBUG_ERROR, "Failed to hande UHD vector, please fix!\n");
uhd_close();
return -EIO;
}
error = uhd_usrp_get_rx_antennas(usrp, channel, &antennas);
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to request list of RX antennas!\n");
uhd_close();
return -EIO;
}
error = uhd_string_vector_size(antennas, &antennas_length);
if (error)
goto rx_vector_error;
for (i = 0; i < (int)antennas_length; i++) {
error = uhd_string_vector_at(antennas, i, got_antenna, sizeof(got_antenna));
if (error)
goto rx_vector_error;
PDEBUG(DUHD, DEBUG_NOTICE, "RX Antenna: '%s'\n", got_antenna);
}
uhd_string_vector_free(&antennas);
error = uhd_usrp_get_rx_antenna(usrp, channel, got_antenna, sizeof(got_antenna));
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to get RX antenna\n");
uhd_close();
return -EINVAL;
}
PDEBUG(DUHD, DEBUG_NOTICE, "Default RX Antenna: '%s'\n", got_antenna);
uhd_close();
return 1;
}
error = uhd_usrp_set_rx_antenna(usrp, rx_antenna, channel);
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX antenna to '%s'\n", rx_antenna);
uhd_close();
return -EIO;
}
error = uhd_usrp_get_rx_antenna(usrp, channel, got_antenna, sizeof(got_antenna));
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to get RX antenna\n");
uhd_close();
return -EINVAL;
}
if (!!strcasecmp(rx_antenna, got_antenna)) {
PDEBUG(DUHD, DEBUG_NOTICE, "Given RX antenna '%s' was accepted, but driver claims to use '%s'\n", rx_antenna, got_antenna);
uhd_close();
return -EINVAL;
}
}
/* create streamers */
error = uhd_rx_streamer_make(&rx_streamer);
if (error) {
@ -213,7 +334,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
return -EIO;
}
if (fabs(got_rate - rate) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given RX rate %.0f Hz is not supported, try %0.f Hz\n", rate, got_rate);
PDEBUG(DUHD, DEBUG_ERROR, "Given RX rate %.0f Hz is not supported, try %.0f Hz\n", rate, got_rate);
uhd_close();
return -EINVAL;
}
@ -243,6 +364,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
tune_request.target_freq = rx_frequency;
tune_request.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO;
tune_request.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO;
tune_request.args = strdup(_tune_args);
error = uhd_usrp_set_rx_freq(usrp, &tune_request, channel, &tune_result);
if (error) {
PDEBUG(DUHD, DEBUG_ERROR, "Failed to set RX frequeny to %.0f Hz\n", rx_frequency);
@ -258,7 +380,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
return -EIO;
}
if (fabs(got_frequency - rx_frequency) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given RX frequency %.0f Hz is not supported, try %0.f Hz\n", rx_frequency, got_frequency);
PDEBUG(DUHD, DEBUG_ERROR, "Given RX frequency %.0f Hz is not supported, try %.0f Hz\n", rx_frequency, got_frequency);
uhd_close();
return -EINVAL;
}
@ -278,7 +400,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
return -EIO;
}
if (fabs(got_bandwidth - bandwidth) > 0.001) {
PDEBUG(DUHD, DEBUG_ERROR, "Given RX bandwidth %.0f Hz is not supported, try %0.f Hz\n", bandwidth, got_bandwidth);
PDEBUG(DUHD, DEBUG_ERROR, "Given RX bandwidth %.0f Hz is not supported, try %.0f Hz\n", bandwidth, got_bandwidth);
uhd_close();
return -EINVAL;
}
@ -287,7 +409,7 @@ int uhd_open(size_t channel, const char *device_args, double tx_frequency, doubl
memset(&stream_args, 0, sizeof(stream_args));
stream_args.cpu_format = "fc32";
stream_args.otw_format = "sc16";
stream_args.args = "";
stream_args.args = strdup(_stream_args);
stream_args.channel_list = &channel;
stream_args.n_channels = 1;
error = uhd_usrp_get_rx_stream(usrp, &stream_args, rx_streamer);

View File

@ -1,5 +1,5 @@
int uhd_open(size_t channel, const char *device_args, double tx_frequency, double rx_frequency, double rate, double rx_gain, double tx_gain, double bandwidth);
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 rate, double tx_gain, double rx_gain, double bandwidth);
int uhd_start(void);
void uhd_close(void);
int uhd_send(float *buff, int num);