Skip to content

Commit 76741d5

Browse files
committed
Add UHD driver for Ettus radios.
$ ./dump1090 --device-type uhd --gain 30
1 parent e3b3fa8 commit 76741d5

6 files changed

Lines changed: 295 additions & 5 deletions

File tree

Makefile

Lines changed: 12 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -31,12 +31,17 @@ ifeq ($(PKGCONFIG), yes)
3131
ifndef LIMESDR
3232
LIMESDR := $(shell pkg-config --exists LimeSuite && echo "yes" || echo "no")
3333
endif
34+
35+
ifndef UHD
36+
UHD := $(shell pkg-config --exists uhd && echo "yes" || echo "no")
37+
endif
3438
else
3539
# pkg-config not available. Only use explicitly enabled libraries.
3640
RTLSDR ?= no
3741
BLADERF ?= no
3842
HACKRF ?= no
3943
LIMESDR ?= no
44+
UHD ?= no
4045
endif
4146

4247
HOST_UNAME := $(shell uname)
@@ -155,6 +160,12 @@ ifeq ($(LIMESDR), yes)
155160
LIBS_SDR += $(shell pkg-config --libs LimeSuite)
156161
endif
157162

163+
ifeq ($(UHD), yes)
164+
SDR_OBJ += sdr_uhd.o
165+
DUMP1090_CPPFLAGS += -DENABLE_UHD
166+
DUMP1090_CFLAGS += $(shell pkg-config --cflags uhd)
167+
LIBS_SDR += $(shell pkg-config --libs uhd)
168+
endif
158169

159170
##
160171
## starch (runtime DSP code selection) mix, architecture-specific
@@ -201,6 +212,7 @@ showconfig:
201212
@echo " BladeRF support: $(BLADERF)" >&2
202213
@echo " HackRF support: $(HACKRF)" >&2
203214
@echo " LimeSDR support: $(LIMESDR)" >&2
215+
@echo " UHD support : $(UHD)" >&2
204216

205217
%.o: %.c *.h
206218
$(CC) $(ALL_CCFLAGS) -c $< -o $@

README.md

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ many other Linux or Unix-like systems.
1919
## Building under bullseye, buster, or stretch
2020

2121
```bash
22-
$ sudo apt-get install build-essential fakeroot debhelper librtlsdr-dev pkg-config libncurses5-dev libbladerf-dev libhackrf-dev liblimesuite-dev
22+
$ sudo apt-get install build-essential fakeroot debhelper librtlsdr-dev pkg-config libncurses5-dev libbladerf-dev libhackrf-dev liblimesuite-dev libuhd-dev
2323
$ ./prepare-build.sh bullseye # or buster, or stretch
2424
$ cd package-bullseye # or buster, or stretch
2525
$ dpkg-buildpackage -b --no-sign
@@ -35,11 +35,11 @@ limited SDR support only.
3535

3636
Pass `--build-profiles` to `dpkg-buildpackage` with a comma-separated list of
3737
profiles. The list of profiles should include `custom` and zero or more of
38-
`rtlsdr`, `bladerf`, `hackrf`, `limesdr` depending on what you want:
38+
`rtlsdr`, `bladerf`, `hackrf`, `limesdr`, `uhd` depending on what you want:
3939

4040
```bash
4141
$ dpkg-buildpackage -b --no-sign --build-profiles=custom,rtlsdr # builds with rtlsdr support only
42-
$ dpkg-buildpackage -b --no-sign --build-profiles=custom,rtlsdr,bladerf # builds with rtlsdr and bladeRF support
42+
$ dpkg-buildpackage -b --no-sign --build-profiles=custom,rtlsdr # builds with rtlsdr and bladeRF support
4343
$ dpkg-buildpackage -b --no-sign --build-profiles=custom # builds with _no_ SDR support (network support only)
4444
```
4545

@@ -61,6 +61,10 @@ libhackrf.
6161
``make LIMESDR=no`` will disable LimeSDR support and remove the dependency on
6262
libLimeSuite.
6363

64+
``make UHD=no`` will disable UHD support and remove the dependency on
65+
uhd-dev.
66+
67+
6468
## Building on OSX
6569

6670
Minimal testing on Mojave 10.14.6, YMMV.

dump1090.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -299,7 +299,7 @@ typedef enum {
299299
//======================== structure declarations =========================
300300

301301
typedef enum {
302-
SDR_NONE, SDR_IFILE, SDR_RTLSDR, SDR_BLADERF, SDR_HACKRF, SDR_LIMESDR
302+
SDR_NONE, SDR_IFILE, SDR_RTLSDR, SDR_BLADERF, SDR_HACKRF, SDR_LIMESDR, SDR_UHD
303303
} sdr_type_t;
304304

305305
// Program global state

sdr.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,9 @@
3333
#ifdef ENABLE_LIMESDR
3434
# include "sdr_limesdr.h"
3535
#endif
36+
#ifdef ENABLE_UHD
37+
# include "sdr_uhd.h"
38+
#endif
3639

3740
typedef struct {
3841
const char *name;
@@ -128,7 +131,9 @@ static sdr_handler sdr_handlers[] = {
128131
#ifdef ENABLE_LIMESDR
129132
{ "limesdr", SDR_LIMESDR, limesdrInitConfig, limesdrShowHelp, limesdrHandleOption, limesdrOpen, limesdrRun, noStop, limesdrClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain },
130133
#endif
131-
134+
#ifdef ENABLE_UHD
135+
{ "uhd", SDR_UHD, uhdInitConfig, uhdShowHelp, uhdHandleOption, uhdOpen, uhdRun, noStop, uhdClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain },
136+
#endif
132137
{ "none", SDR_NONE, noInitConfig, noShowHelp, noHandleOption, noOpen, noRun, noStop, noClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain },
133138
{ "ifile", SDR_IFILE, ifileInitConfig, ifileShowHelp, ifileHandleOption, ifileOpen, ifileRun, noStop, ifileClose, noGetGain, noGetMaxGain, noGetGainDb, noSetGain },
134139

sdr_uhd.c

Lines changed: 235 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,235 @@
1+
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
2+
//
3+
// sdr_bladerf.h: UHD support (header)
4+
//
5+
// Copyright (c) 2017 FlightAware LLC
6+
//
7+
// This file is free software: you may copy, redistribute and/or modify it
8+
// under the terms of the GNU General Public License as published by the
9+
// Free Software Foundation, either version 2 of the License, or (at your
10+
// option) any later version.
11+
//
12+
// This file is distributed in the hope that it will be useful, but
13+
// WITHOUT ANY WARRANTY; without even the implied warranty of
14+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
// General Public License for more details.
16+
//
17+
// You should have received a copy of the GNU General Public License
18+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
20+
#include "dump1090.h"
21+
#include "sdr_uhd.h"
22+
23+
#include <inttypes.h>
24+
25+
// complex int16
26+
#define SAMPLE_SIZE 4
27+
28+
static struct {
29+
uhd_usrp_handle *usrp;
30+
uhd_rx_metadata_handle *md;
31+
uhd_rx_streamer_handle *rx_streamer;
32+
char *device_args;
33+
size_t channel;
34+
char *sample_data;
35+
36+
iq_convert_fn converter;
37+
struct converter_state *converter_state;
38+
} uhd;
39+
40+
void uhdClose() {
41+
if (uhd.rx_streamer) {
42+
uhd_rx_streamer_free(uhd.rx_streamer);
43+
free(uhd.rx_streamer);
44+
}
45+
if (uhd.md) {
46+
uhd_rx_metadata_free(uhd.md);
47+
free(uhd.md);
48+
}
49+
if (uhd.usrp) {
50+
uhd_usrp_free(uhd.usrp);
51+
free(uhd.usrp);
52+
}
53+
if (uhd.sample_data) {
54+
free(uhd.sample_data);
55+
}
56+
if (uhd.device_args) {
57+
free(uhd.device_args);
58+
}
59+
}
60+
61+
void uhdInitConfig() {
62+
uhd.usrp = NULL;
63+
uhd.md = NULL;
64+
uhd.rx_streamer = NULL;
65+
uhd.device_args = NULL;
66+
uhd.sample_data = NULL;
67+
uhd.channel = 0;
68+
}
69+
70+
void uhdShowHelp() {
71+
printf(" uhd-specific options (use with --device-type uhd)\n");
72+
printf("\n");
73+
printf("--device-args <args> UHD device args\n");
74+
printf("\n");
75+
}
76+
77+
bool uhdHandleOption(int argc, char **argv, int *jptr) {
78+
int j = *jptr;
79+
bool more = (j+1 < argc);
80+
if (!strcmp(argv[j], "--uhd-device-args") && more) {
81+
uhd.device_args = strdup(argv[++j]);
82+
} else {
83+
return false;
84+
}
85+
86+
*jptr = j;
87+
return true;
88+
}
89+
90+
bool uhdOpen() {
91+
uhd_tune_request_t tune_request = {
92+
.target_freq = Modes.freq,
93+
.rf_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
94+
.dsp_freq_policy = UHD_TUNE_REQUEST_POLICY_AUTO,
95+
};
96+
uhd_tune_result_t tune_result;
97+
98+
if (!uhd.device_args) {
99+
uhd.device_args = strdup("");
100+
}
101+
102+
int uhd_error;
103+
104+
uhd.usrp = malloc(sizeof(uhd_usrp_handle));
105+
uhd_error = uhd_usrp_make(uhd.usrp, uhd.device_args);
106+
if (uhd_error) {
107+
fprintf(stderr, "uhd_usrp_make() failed: %x", uhd_error);
108+
goto failed;
109+
}
110+
111+
uhd.md = malloc(sizeof(uhd_rx_metadata_handle));
112+
uhd_error = uhd_rx_metadata_make(uhd.md);
113+
if (uhd_error) {
114+
fprintf(stderr, "uhd_rx_metadata_make() failed: %x", uhd_error);
115+
goto failed;
116+
}
117+
118+
uhd.rx_streamer = malloc(sizeof(uhd_rx_streamer_handle));
119+
uhd_error = uhd_rx_streamer_make(uhd.rx_streamer);
120+
if (uhd_error) {
121+
fprintf(stderr, "uhd_rx_streamer_make() failed: %x", uhd_error);
122+
goto failed;
123+
}
124+
125+
fprintf(stderr, "setting bw, rx rate to %fMsps\n", Modes.sample_rate / 1e6);
126+
uhd_error = uhd_usrp_set_rx_rate(*uhd.usrp, Modes.sample_rate, uhd.channel);
127+
if (uhd_error) {
128+
fprintf(stderr, "uhd_usrp_set_rx_rate() failed: %x", uhd_error);
129+
goto failed;
130+
}
131+
132+
uhd_error = uhd_usrp_set_rx_bandwidth(*uhd.usrp, Modes.sample_rate, uhd.channel);
133+
if (uhd_error) {
134+
fprintf(stderr, "uhd_usrp_set_rx_bandwidth() failed: %x", uhd_error);
135+
goto failed;
136+
}
137+
138+
if (Modes.gain != MODES_DEFAULT_GAIN) {
139+
fprintf(stderr, "setting rx gain to %f\n", Modes.gain);
140+
uhd_error = uhd_usrp_set_rx_gain(*uhd.usrp, Modes.gain, uhd.channel, "");
141+
if (!uhd_error) {
142+
fprintf(stderr, "uhd_usrp_set_rx_gain() failed: %x", uhd_error);
143+
goto failed;
144+
}
145+
}
146+
147+
fprintf(stderr, "setting rx freq to %fMHz\n", Modes.freq / 1e6);
148+
uhd_error = uhd_usrp_set_rx_freq(*uhd.usrp, &tune_request, uhd.channel, &tune_result);
149+
if (uhd_error) {
150+
fprintf(stderr, "uhd_usrp_set_rx_freq() failed: %x", uhd_error);
151+
goto failed;
152+
}
153+
154+
uhd.converter = init_converter(
155+
INPUT_SC16Q11, Modes.sample_rate, Modes.dc_filter, &uhd.converter_state);
156+
157+
return true;
158+
159+
failed:
160+
uhdClose();
161+
return false;
162+
}
163+
164+
void uhdRun() {
165+
uhd_stream_args_t stream_args = {
166+
.cpu_format = "sc16",
167+
.otw_format = "sc16",
168+
.args = "",
169+
.channel_list = &uhd.channel,
170+
.n_channels = 1
171+
};
172+
173+
uhd_stream_cmd_t stream_cmd = {
174+
.stream_mode = UHD_STREAM_MODE_START_CONTINUOUS,
175+
.stream_now = true
176+
};
177+
178+
uhd_stream_cmd_t stop_stream_cmd = {
179+
.stream_mode = UHD_STREAM_MODE_STOP_CONTINUOUS,
180+
};
181+
182+
size_t num_rx_samps = 0;
183+
struct mag_buf *outbuf = NULL;
184+
int uhd_error;
185+
186+
uhd_error = uhd_usrp_get_rx_stream(*uhd.usrp, &stream_args, *uhd.rx_streamer);
187+
if (uhd_error) {
188+
fprintf(stderr, "uhd_usrp_get_rx_stream() failed: %x\n", uhd_error);
189+
return;
190+
}
191+
192+
fprintf(stderr, "streaming...\n");
193+
uhd.sample_data = malloc(MODES_MAG_BUF_SAMPLES * SAMPLE_SIZE);
194+
int64_t full_secs;
195+
double frac_secs;
196+
uhd_rx_metadata_time_spec(*uhd.md, &full_secs, &frac_secs);
197+
double first_recv_time = full_secs + frac_secs;
198+
199+
uhd_error = uhd_rx_streamer_issue_stream_cmd(*uhd.rx_streamer, &stream_cmd);
200+
if (uhd_error) {
201+
fprintf(stderr, "uhd_rx_streamer_issue_stream_cmd() failed: %x\n", uhd_error);
202+
return;
203+
}
204+
205+
for (;;) {
206+
outbuf = fifo_acquire(0);
207+
if (!outbuf) {
208+
if (Modes.exit) {
209+
break;
210+
}
211+
fprintf(stderr, "could not get outbuf\n");
212+
continue;
213+
}
214+
215+
outbuf->sysTimestamp = mstime();
216+
uhd_rx_streamer_recv(*uhd.rx_streamer, (void **) &uhd.sample_data, MODES_MAG_BUF_SAMPLES, uhd.md, 3.0, false, &num_rx_samps);
217+
uhd_rx_metadata_error_code_t error_code;
218+
uhd_rx_metadata_error_code(*uhd.md, &error_code);
219+
if (error_code != UHD_RX_METADATA_ERROR_CODE_NONE) {
220+
fprintf(stderr, "error code while streaming: %x\n", error_code);
221+
break;
222+
}
223+
uhd_rx_metadata_time_spec(*uhd.md, &full_secs, &frac_secs);
224+
double recv_time = full_secs + frac_secs;
225+
outbuf->sampleTimestamp = (recv_time - first_recv_time) * 12e6 / Modes.sample_rate;
226+
227+
uhd.converter(uhd.sample_data, &outbuf->data[outbuf->overlap], num_rx_samps, uhd.converter_state, &outbuf->mean_level, &outbuf->mean_power);
228+
outbuf->validLength = outbuf->overlap + num_rx_samps;
229+
outbuf->flags = 0;
230+
231+
fifo_enqueue(outbuf);
232+
}
233+
234+
uhd_rx_streamer_issue_stream_cmd(*uhd.rx_streamer, &stop_stream_cmd);
235+
}

sdr_uhd.h

Lines changed: 34 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,34 @@
1+
// Part of dump1090, a Mode S message decoder for RTLSDR devices.
2+
//
3+
// sdr_bladerf.h: UHD support (header)
4+
//
5+
// Copyright (c) 2017 FlightAware LLC
6+
//
7+
// This file is free software: you may copy, redistribute and/or modify it
8+
// under the terms of the GNU General Public License as published by the
9+
// Free Software Foundation, either version 2 of the License, or (at your
10+
// option) any later version.
11+
//
12+
// This file is distributed in the hope that it will be useful, but
13+
// WITHOUT ANY WARRANTY; without even the implied warranty of
14+
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15+
// General Public License for more details.
16+
//
17+
// You should have received a copy of the GNU General Public License
18+
// along with this program. If not, see <http://www.gnu.org/licenses/>.
19+
20+
#ifndef UHD_H
21+
#define UHD_H
22+
23+
#include <uhd.h>
24+
25+
// Support for UHD SDR
26+
27+
void uhdInitConfig();
28+
void uhdShowHelp();
29+
bool uhdHandleOption(int argc, char **argv, int *jptr);
30+
bool uhdOpen();
31+
void uhdRun();
32+
void uhdClose();
33+
34+
#endif

0 commit comments

Comments
 (0)