From 905a406e58239f432eaec25a752fd36cda174b2c Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Thu, 3 Aug 2023 00:39:37 +0000 Subject: [PATCH 1/2] Add UHD driver for Ettus radios. $ ./dump1090 --device-type uhd --gain 30 --- Makefile | 12 +++ README.md | 8 +- dump1090.h | 2 +- sdr.c | 7 +- sdr_uhd.c | 240 +++++++++++++++++++++++++++++++++++++++++++++++++++++ sdr_uhd.h | 34 ++++++++ 6 files changed, 299 insertions(+), 4 deletions(-) create mode 100644 sdr_uhd.c create mode 100644 sdr_uhd.h diff --git a/Makefile b/Makefile index 8fd50819e..194bd0074 100644 --- a/Makefile +++ b/Makefile @@ -31,12 +31,17 @@ ifeq ($(PKGCONFIG), yes) ifndef LIMESDR LIMESDR := $(shell pkg-config --exists LimeSuite && echo "yes" || echo "no") endif + + ifndef UHD + UHD := $(shell pkg-config --exists uhd && echo "yes" || echo "no") + endif else # pkg-config not available. Only use explicitly enabled libraries. RTLSDR ?= no BLADERF ?= no HACKRF ?= no LIMESDR ?= no + UHD ?= no endif HOST_UNAME := $(shell uname) @@ -155,6 +160,12 @@ ifeq ($(LIMESDR), yes) LIBS_SDR += $(shell pkg-config --libs LimeSuite) endif +ifeq ($(UHD), yes) + SDR_OBJ += sdr_uhd.o + DUMP1090_CPPFLAGS += -DENABLE_UHD + DUMP1090_CFLAGS += $(shell pkg-config --cflags uhd) + LIBS_SDR += $(shell pkg-config --libs uhd) +endif ## ## starch (runtime DSP code selection) mix, architecture-specific @@ -201,6 +212,7 @@ showconfig: @echo " BladeRF support: $(BLADERF)" >&2 @echo " HackRF support: $(HACKRF)" >&2 @echo " LimeSDR support: $(LIMESDR)" >&2 + @echo " UHD support : $(UHD)" >&2 %.o: %.c *.h $(CC) $(ALL_CCFLAGS) -c $< -o $@ diff --git a/README.md b/README.md index b913674db..6a7c8c5a2 100644 --- a/README.md +++ b/README.md @@ -19,7 +19,7 @@ many other Linux or Unix-like systems. ## Building under bullseye, buster, or stretch ```bash -$ sudo apt-get install build-essential fakeroot debhelper librtlsdr-dev pkg-config libncurses5-dev libbladerf-dev libhackrf-dev liblimesuite-dev +$ sudo apt-get install build-essential fakeroot debhelper librtlsdr-dev pkg-config libncurses5-dev libbladerf-dev libhackrf-dev liblimesuite-dev libuhd-dev $ ./prepare-build.sh bullseye # or buster, or stretch $ cd package-bullseye # or buster, or stretch $ dpkg-buildpackage -b --no-sign @@ -35,7 +35,7 @@ limited SDR support only. Pass `--build-profiles` to `dpkg-buildpackage` with a comma-separated list of profiles. The list of profiles should include `custom` and zero or more of -`rtlsdr`, `bladerf`, `hackrf`, `limesdr` depending on what you want: +`rtlsdr`, `bladerf`, `hackrf`, `limesdr`, `uhd` depending on what you want: ```bash $ dpkg-buildpackage -b --no-sign --build-profiles=custom,rtlsdr # builds with rtlsdr support only @@ -61,6 +61,10 @@ libhackrf. ``make LIMESDR=no`` will disable LimeSDR support and remove the dependency on libLimeSuite. +``make UHD=no`` will disable UHD support and remove the dependency on +uhd-dev. + + ## Building on OSX Minimal testing on Mojave 10.14.6, YMMV. diff --git a/dump1090.h b/dump1090.h index 05648c725..5ec9808d8 100644 --- a/dump1090.h +++ b/dump1090.h @@ -299,7 +299,7 @@ typedef enum { //======================== structure declarations ========================= typedef enum { - SDR_NONE, SDR_IFILE, SDR_RTLSDR, SDR_BLADERF, SDR_HACKRF, SDR_LIMESDR + SDR_NONE, SDR_IFILE, SDR_RTLSDR, SDR_BLADERF, SDR_HACKRF, SDR_LIMESDR, SDR_UHD } sdr_type_t; // Program global state diff --git a/sdr.c b/sdr.c index 484302a01..5e86a56c5 100644 --- a/sdr.c +++ b/sdr.c @@ -33,6 +33,9 @@ #ifdef ENABLE_LIMESDR # include "sdr_limesdr.h" #endif +#ifdef ENABLE_UHD +# include "sdr_uhd.h" +#endif typedef struct { const char *name; @@ -128,7 +131,9 @@ static sdr_handler sdr_handlers[] = { #ifdef ENABLE_LIMESDR { "limesdr", SDR_LIMESDR, limesdrInitConfig, limesdrShowHelp, limesdrHandleOption, limesdrOpen, limesdrRun, noStop, limesdrClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain }, #endif - +#ifdef ENABLE_UHD + { "uhd", SDR_UHD, uhdInitConfig, uhdShowHelp, uhdHandleOption, uhdOpen, uhdRun, noStop, uhdClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain }, +#endif { "none", SDR_NONE, noInitConfig, noShowHelp, noHandleOption, noOpen, noRun, noStop, noClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain }, { "ifile", SDR_IFILE, ifileInitConfig, ifileShowHelp, ifileHandleOption, ifileOpen, ifileRun, noStop, ifileClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain }, diff --git a/sdr_uhd.c b/sdr_uhd.c new file mode 100644 index 000000000..0c8aef21d --- /dev/null +++ b/sdr_uhd.c @@ -0,0 +1,240 @@ +// Part of dump1090, a Mode S message decoder for RTLSDR devices. +// +// sdr_bladerf.h: UHD support (header) +// +// Copyright (c) 2017 FlightAware LLC +// +// This file is free software: you may copy, redistribute and/or modify it +// under the terms of the GNU General Public License as published by the +// Free Software Foundation, either version 2 of the License, or (at your +// option) any later version. +// +// This file 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 "dump1090.h" +#include "sdr_uhd.h" + +#include + +// complex int16 +#define SAMPLE_SIZE 4 + +static struct { + uhd_usrp_handle *usrp; + uhd_rx_metadata_handle *md; + uhd_rx_streamer_handle *rx_streamer; + char *device_args; + size_t channel; + char *sample_data; + + iq_convert_fn converter; + struct converter_state *converter_state; +} uhd; + +void uhdClose() { + if (uhd.rx_streamer) { + uhd_rx_streamer_free(uhd.rx_streamer); + free(uhd.rx_streamer); + uhd.rx_streamer = NULL; + } + if (uhd.md) { + uhd_rx_metadata_free(uhd.md); + free(uhd.md); + uhd.md = NULL; + } + if (uhd.usrp) { + uhd_usrp_free(uhd.usrp); + free(uhd.usrp); + uhd.usrp = NULL; + } + if (uhd.sample_data) { + free(uhd.sample_data); + uhd.sample_data = NULL; + } + if (uhd.device_args) { + free(uhd.device_args); + uhd.device_args = NULL; + } +} + +void uhdInitConfig() { + uhd.usrp = NULL; + uhd.md = NULL; + uhd.rx_streamer = NULL; + uhd.device_args = NULL; + uhd.sample_data = NULL; + uhd.channel = 0; +} + +void uhdShowHelp() { + printf(" uhd-specific options (use with --device-type uhd)\n"); + printf("\n"); + printf("--device-args UHD device args\n"); + printf("\n"); +} + +bool uhdHandleOption(int argc, char **argv, int *jptr) { + int j = *jptr; + bool more = (j+1 < argc); + if (!strcmp(argv[j], "--uhd-device-args") && more) { + uhd.device_args = strdup(argv[++j]); + } else { + return false; + } + + *jptr = j; + return true; +} + +bool uhdOpen() { + uhd_tune_request_t tune_request = { + .target_freq = Modes.freq, + .rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, + .dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO, + }; + uhd_tune_result_t tune_result; + + if (!uhd.device_args) { + uhd.device_args = strdup(""); + } + + int uhd_error; + + uhd.usrp = malloc(sizeof(uhd_usrp_handle)); + uhd_error = uhd_usrp_make(uhd.usrp, uhd.device_args); + if (uhd_error) { + fprintf(stderr, "uhd_usrp_make() failed: %x", uhd_error); + goto failed; + } + + uhd.md = malloc(sizeof(uhd_rx_metadata_handle)); + uhd_error = uhd_rx_metadata_make(uhd.md); + if (uhd_error) { + fprintf(stderr, "uhd_rx_metadata_make() failed: %x", uhd_error); + goto failed; + } + + uhd.rx_streamer = malloc(sizeof(uhd_rx_streamer_handle)); + uhd_error = uhd_rx_streamer_make(uhd.rx_streamer); + if (uhd_error) { + fprintf(stderr, "uhd_rx_streamer_make() failed: %x", uhd_error); + goto failed; + } + + fprintf(stderr, "setting bw, rx rate to %fMsps\n", Modes.sample_rate / 1e6); + uhd_error = uhd_usrp_set_rx_rate(*uhd.usrp, Modes.sample_rate, uhd.channel); + if (uhd_error) { + fprintf(stderr, "uhd_usrp_set_rx_rate() failed: %x", uhd_error); + goto failed; + } + + uhd_error = uhd_usrp_set_rx_bandwidth(*uhd.usrp, Modes.sample_rate, uhd.channel); + if (uhd_error) { + fprintf(stderr, "uhd_usrp_set_rx_bandwidth() failed: %x", uhd_error); + goto failed; + } + + if (Modes.gain != MODES_DEFAULT_GAIN) { + fprintf(stderr, "setting rx gain to %f\n", Modes.gain); + uhd_error = uhd_usrp_set_rx_gain(*uhd.usrp, Modes.gain, uhd.channel, ""); + if (!uhd_error) { + fprintf(stderr, "uhd_usrp_set_rx_gain() failed: %x", uhd_error); + goto failed; + } + } + + fprintf(stderr, "setting rx freq to %fMHz\n", Modes.freq / 1e6); + uhd_error = uhd_usrp_set_rx_freq(*uhd.usrp, &tune_request, uhd.channel, &tune_result); + if (uhd_error) { + fprintf(stderr, "uhd_usrp_set_rx_freq() failed: %x", uhd_error); + goto failed; + } + + uhd.converter = init_converter( + INPUT_SC16Q11, Modes.sample_rate, Modes.dc_filter, &uhd.converter_state); + + return true; + + failed: + uhdClose(); + return false; +} + +void uhdRun() { + uhd_stream_args_t stream_args = { + .cpu_format = "sc16", + .otw_format = "sc16", + .args = "", + .channel_list = &uhd.channel, + .n_channels = 1 + }; + + uhd_stream_cmd_t stream_cmd = { + .stream_mode = UHD_STREAM_MODE_START_CONTINUOUS, + .stream_now = true + }; + + uhd_stream_cmd_t stop_stream_cmd = { + .stream_mode = UHD_STREAM_MODE_STOP_CONTINUOUS, + }; + + size_t num_rx_samps = 0; + struct mag_buf *outbuf = NULL; + int uhd_error; + + uhd_error = uhd_usrp_get_rx_stream(*uhd.usrp, &stream_args, *uhd.rx_streamer); + if (uhd_error) { + fprintf(stderr, "uhd_usrp_get_rx_stream() failed: %x\n", uhd_error); + return; + } + + fprintf(stderr, "streaming...\n"); + uhd.sample_data = malloc(MODES_MAG_BUF_SAMPLES * SAMPLE_SIZE); + int64_t full_secs; + double frac_secs; + uhd_rx_metadata_time_spec(*uhd.md, &full_secs, &frac_secs); + double first_recv_time = full_secs + frac_secs; + + uhd_error = uhd_rx_streamer_issue_stream_cmd(*uhd.rx_streamer, &stream_cmd); + if (uhd_error) { + fprintf(stderr, "uhd_rx_streamer_issue_stream_cmd() failed: %x\n", uhd_error); + return; + } + + for (;;) { + outbuf = fifo_acquire(0); + if (!outbuf) { + if (Modes.exit) { + break; + } + fprintf(stderr, "could not get outbuf\n"); + continue; + } + + outbuf->sysTimestamp = mstime(); + uhd_rx_streamer_recv(*uhd.rx_streamer, (void **) &uhd.sample_data, MODES_MAG_BUF_SAMPLES, uhd.md, 3.0, false, &num_rx_samps); + uhd_rx_metadata_error_code_t error_code; + uhd_rx_metadata_error_code(*uhd.md, &error_code); + if (error_code != UHD_RX_METADATA_ERROR_CODE_NONE) { + fprintf(stderr, "error code while streaming: %x\n", error_code); + break; + } + uhd_rx_metadata_time_spec(*uhd.md, &full_secs, &frac_secs); + double recv_time = full_secs + frac_secs; + outbuf->sampleTimestamp = (recv_time - first_recv_time) * 12e6 / Modes.sample_rate; + + uhd.converter(uhd.sample_data, &outbuf->data[outbuf->overlap], num_rx_samps, uhd.converter_state, &outbuf->mean_level, &outbuf->mean_power); + outbuf->validLength = outbuf->overlap + num_rx_samps; + outbuf->flags = 0; + + fifo_enqueue(outbuf); + } + + uhd_rx_streamer_issue_stream_cmd(*uhd.rx_streamer, &stop_stream_cmd); +} diff --git a/sdr_uhd.h b/sdr_uhd.h new file mode 100644 index 000000000..d591bdf96 --- /dev/null +++ b/sdr_uhd.h @@ -0,0 +1,34 @@ +// Part of dump1090, a Mode S message decoder for RTLSDR devices. +// +// sdr_bladerf.h: UHD support (header) +// +// Copyright (c) 2017 FlightAware LLC +// +// This file is free software: you may copy, redistribute and/or modify it +// under the terms of the GNU General Public License as published by the +// Free Software Foundation, either version 2 of the License, or (at your +// option) any later version. +// +// This file 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 . + +#ifndef UHD_H +#define UHD_H + +#include + +// Support for UHD SDR + +void uhdInitConfig(); +void uhdShowHelp(); +bool uhdHandleOption(int argc, char **argv, int *jptr); +bool uhdOpen(); +void uhdRun(); +void uhdClose(); + +#endif From 13c32ad87f74c80a07061580617ae166524c89b3 Mon Sep 17 00:00:00 2001 From: Josh Bailey Date: Mon, 11 Dec 2023 04:12:11 +0000 Subject: [PATCH 2/2] gain. --- sdr_uhd.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/sdr_uhd.c b/sdr_uhd.c index 0c8aef21d..558288cdb 100644 --- a/sdr_uhd.c +++ b/sdr_uhd.c @@ -143,7 +143,7 @@ bool uhdOpen() { if (Modes.gain != MODES_DEFAULT_GAIN) { fprintf(stderr, "setting rx gain to %f\n", Modes.gain); uhd_error = uhd_usrp_set_rx_gain(*uhd.usrp, Modes.gain, uhd.channel, ""); - if (!uhd_error) { + if (uhd_error) { fprintf(stderr, "uhd_usrp_set_rx_gain() failed: %x", uhd_error); goto failed; }