blob: 31a99cf97b5e46612da91c3725857e14be3b5d25 [file] [log] [blame]
Thomas Tsou85b179d2013-11-15 21:14:33 -05001/*
2 * Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>
3 *
4 * This library is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU Lesser General Public
6 * License as published by the Free Software Foundation; either
7 * version 2.1 of the License, or (at your option) any later version.
8 *
9 * This library is distributed in the hope that it will be useful,
10 * but WITHOUT ANY WARRANTY; without even the implied warranty of
11 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
12 * Lesser General Public License for more details.
13 *
14 * You should have received a copy of the GNU Lesser General Public
15 * License along with this library; if not, write to the Free Software
16 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
17 */
18
19#ifdef HAVE_CONFIG_H
20#include "config.h"
21#endif
22
23#include "Transceiver.h"
24#include "radioDevice.h"
25
26#include <time.h>
27#include <signal.h>
28#include <stdlib.h>
29#include <unistd.h>
30
31#include <GSMCommon.h>
32#include <Logger.h>
33#include <Configuration.h>
34
Philipp Maier7e07cf22017-03-15 18:09:35 +010035extern "C" {
36#include "convolve.h"
37#include "convert.h"
38}
39
Thomas Tsou85b179d2013-11-15 21:14:33 -050040/* Samples-per-symbol for downlink path
41 * 4 - Uses precision modulator (more computation, less distortion)
42 * 1 - Uses minimized modulator (less computation, more distortion)
43 *
44 * Other values are invalid. Receive path (uplink) is always
Tom Tsou0fe41a52016-05-03 15:14:45 -070045 * downsampled to 1 sps. Default to 4 sps for all cases.
Thomas Tsou85b179d2013-11-15 21:14:33 -050046 */
Tom Tsou5cd70dc2016-03-06 01:28:40 -080047#define DEFAULT_TX_SPS 4
Thomas Tsou85b179d2013-11-15 21:14:33 -050048
Tom Tsou5cd70dc2016-03-06 01:28:40 -080049/*
50 * Samples-per-symbol for uplink (receiver) path
51 * Do not modify this value. EDGE configures 4 sps automatically on
52 * B200/B210 devices only. Use of 4 sps on the receive path for other
53 * configurations is not supported.
54 */
55#define DEFAULT_RX_SPS 1
56
Tom Tsoude116e92017-03-30 17:00:42 -070057/* Default configuration parameters */
Thomas Tsou85b179d2013-11-15 21:14:33 -050058#define DEFAULT_TRX_PORT 5700
59#define DEFAULT_TRX_IP "127.0.0.1"
Thomas Tsou85b179d2013-11-15 21:14:33 -050060#define DEFAULT_CHANS 1
61
62struct trx_config {
63 std::string log_level;
64 std::string addr;
65 std::string dev_args;
66 unsigned port;
Tom Tsou5cd70dc2016-03-06 01:28:40 -080067 unsigned tx_sps;
68 unsigned rx_sps;
Thomas Tsou85b179d2013-11-15 21:14:33 -050069 unsigned chans;
Tom Tsou64ad7122015-05-19 18:26:31 -070070 unsigned rtsc;
Alexander Chemeris37c52c72016-03-25 18:28:34 +030071 unsigned rach_delay;
Thomas Tsou85b179d2013-11-15 21:14:33 -050072 bool extref;
Tom Tsou2f3e60b2016-07-17 19:29:08 -070073 bool gpsref;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -040074 Transceiver::FillerType filler;
Tom Tsou76764272016-06-24 14:25:39 -070075 bool mcbts;
Thomas Tsou8e17df72014-03-06 14:16:11 -050076 double offset;
Alexander Chemerise8905a02015-06-03 23:47:56 -040077 double rssi_offset;
Alexander Chemeris50747dc2015-06-07 01:07:45 -040078 bool swap_channels;
Tom Tsoub0aefcb2016-03-06 03:44:34 -080079 bool edge;
Thomas Tsou85b179d2013-11-15 21:14:33 -050080};
81
Thomas Tsou4de70be2013-11-17 18:54:52 -050082ConfigurationTable gConfig;
Thomas Tsou85b179d2013-11-15 21:14:33 -050083
84volatile bool gshutdown = false;
85
Thomas Tsou85b179d2013-11-15 21:14:33 -050086/* Setup configuration values
87 * Don't query the existence of the Log.Level because it's a
88 * mandatory value. That is, if it doesn't exist, the configuration
Thomas Tsou4de70be2013-11-17 18:54:52 -050089 * table will crash or will have already crashed. Everything else we
90 * can survive without and use default values if the database entries
Thomas Tsou85b179d2013-11-15 21:14:33 -050091 * are empty.
92 */
93bool trx_setup_config(struct trx_config *config)
94{
Tom Tsou76764272016-06-24 14:25:39 -070095 std::string refstr, fillstr, divstr, mcstr, edgestr;
Thomas Tsou85b179d2013-11-15 21:14:33 -050096
Tom Tsou60317342017-03-30 19:36:41 -070097 if (config->mcbts && config->chans > 5) {
Tom Tsou76764272016-06-24 14:25:39 -070098 std::cout << "Unsupported number of channels" << std::endl;
99 return false;
100 }
101
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800102 edgestr = config->edge ? "Enabled" : "Disabled";
Tom Tsou76764272016-06-24 14:25:39 -0700103 mcstr = config->mcbts ? "Enabled" : "Disabled";
104
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700105 if (config->extref)
106 refstr = "External";
107 else if (config->gpsref)
108 refstr = "GPS";
109 else
110 refstr = "Internal";
111
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400112 switch (config->filler) {
113 case Transceiver::FILLER_DUMMY:
114 fillstr = "Dummy bursts";
115 break;
116 case Transceiver::FILLER_ZERO:
117 fillstr = "Disabled";
118 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800119 case Transceiver::FILLER_NORM_RAND:
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400120 fillstr = "Normal busrts with random payload";
121 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800122 case Transceiver::FILLER_EDGE_RAND:
123 fillstr = "EDGE busrts with random payload";
124 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300125 case Transceiver::FILLER_ACCESS_RAND:
126 fillstr = "Access busrts with random payload";
127 break;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400128 }
Thomas Tsou85b179d2013-11-15 21:14:33 -0500129
130 std::ostringstream ost("");
131 ost << "Config Settings" << std::endl;
132 ost << " Log Level............... " << config->log_level << std::endl;
133 ost << " Device args............. " << config->dev_args << std::endl;
134 ost << " TRX Base Port........... " << config->port << std::endl;
135 ost << " TRX Address............. " << config->addr << std::endl;
136 ost << " Channels................ " << config->chans << std::endl;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800137 ost << " Tx Samples-per-Symbol... " << config->tx_sps << std::endl;
Alexander Chemeris1ab5e7f2016-04-20 08:44:55 +0300138 ost << " Rx Samples-per-Symbol... " << config->rx_sps << std::endl;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800139 ost << " EDGE support............ " << edgestr << std::endl;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700140 ost << " Reference............... " << refstr << std::endl;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500141 ost << " C0 Filler Table......... " << fillstr << std::endl;
Tom Tsou76764272016-06-24 14:25:39 -0700142 ost << " Multi-Carrier........... " << mcstr << std::endl;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500143 ost << " Tuning offset........... " << config->offset << std::endl;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400144 ost << " RSSI to dBm offset...... " << config->rssi_offset << std::endl;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400145 ost << " Swap channels........... " << config->swap_channels << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500146 std::cout << ost << std::endl;
147
148 return true;
149}
150
151/* Create radio interface
152 * The interface consists of sample rate changes, frequency shifts,
153 * channel multiplexing, and other conversions. The transceiver core
154 * accepts input vectors sampled at multiples of the GSM symbol rate.
155 * The radio interface connects the main transceiver with the device
156 * object, which may be operating some other rate.
157 */
158RadioInterface *makeRadioInterface(struct trx_config *config,
159 RadioDevice *usrp, int type)
160{
161 RadioInterface *radio = NULL;
162
163 switch (type) {
164 case RadioDevice::NORMAL:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800165 radio = new RadioInterface(usrp, config->tx_sps,
166 config->rx_sps, config->chans);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500167 break;
168 case RadioDevice::RESAMP_64M:
169 case RadioDevice::RESAMP_100M:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800170 radio = new RadioInterfaceResamp(usrp, config->tx_sps,
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700171 config->rx_sps);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500172 break;
Tom Tsou76764272016-06-24 14:25:39 -0700173 case RadioDevice::MULTI_ARFCN:
174 radio = new RadioInterfaceMulti(usrp, config->tx_sps,
175 config->rx_sps, config->chans);
176 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500177 default:
178 LOG(ALERT) << "Unsupported radio interface configuration";
179 return NULL;
180 }
181
182 if (!radio->init(type)) {
183 LOG(ALERT) << "Failed to initialize radio interface";
184 return NULL;
185 }
186
187 return radio;
188}
189
190/* Create transceiver core
191 * The multi-threaded modem core operates at multiples of the GSM rate of
192 * 270.8333 ksps and consists of GSM specific modulation, demodulation,
193 * and decoding schemes. Also included are the socket interfaces for
194 * connecting to the upper layer stack.
195 */
196Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
197{
198 Transceiver *trx;
199 VectorFIFO *fifo;
200
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800201 trx = new Transceiver(config->port, config->addr.c_str(),
202 config->tx_sps, config->rx_sps, config->chans,
203 GSM::Time(3,0), radio, config->rssi_offset);
Tom Tsou64464e62016-07-01 03:46:46 -0700204 if (!trx->init(config->filler, config->rtsc,
205 config->rach_delay, config->edge)) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500206 LOG(ALERT) << "Failed to initialize transceiver";
207 delete trx;
208 return NULL;
209 }
210
211 for (size_t i = 0; i < config->chans; i++) {
212 fifo = radio->receiveFIFO(i);
213 if (fifo && trx->receiveFIFO(fifo, i))
214 continue;
215
216 LOG(ALERT) << "Could not attach FIFO to channel " << i;
217 delete trx;
218 return NULL;
219 }
220
221 return trx;
222}
223
224static void sig_handler(int signo)
225{
226 fprintf(stdout, "Received shutdown signal");
227 gshutdown = true;
228}
229
230static void setup_signal_handlers()
231{
232 if (signal(SIGINT, sig_handler) == SIG_ERR) {
233 fprintf(stderr, "Failed to install SIGINT signal handler\n");
234 exit(EXIT_FAILURE);
235 }
236 if (signal(SIGTERM, sig_handler) == SIG_ERR) {
237 fprintf(stderr, "Couldn't install SIGTERM signal handler\n");
238 exit( EXIT_FAILURE);
239 }
240}
241
242static void print_help()
243{
244 fprintf(stdout, "Options:\n"
245 " -h This text\n"
246 " -a UHD device args\n"
247 " -l Logging level (%s)\n"
248 " -i IP address of GSM core\n"
249 " -p Base port number\n"
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800250 " -e Enable EDGE receiver\n"
Tom Tsou76764272016-06-24 14:25:39 -0700251 " -m Enable multi-ARFCN transceiver (default=disabled)\n"
Thomas Tsou85b179d2013-11-15 21:14:33 -0500252 " -x Enable external 10 MHz reference\n"
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700253 " -g Enable GPSDO reference\n"
Tom Tsou2e4ed102016-06-27 15:39:16 -0700254 " -s Tx samples-per-symbol (1 or 4)\n"
255 " -b Rx samples-per-symbol (1 or 4)\n"
Thomas Tsou15d743e2014-01-25 02:34:03 -0500256 " -c Number of ARFCN channels (default=1)\n"
Thomas Tsou8e17df72014-03-06 14:16:11 -0500257 " -f Enable C0 filler table\n"
Tom Tsou64ad7122015-05-19 18:26:31 -0700258 " -o Set baseband frequency offset (default=auto)\n"
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300259 " -r Random Normal Burst test mode with TSC\n"
260 " -A Random Access Burst test mode with delay\n"
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400261 " -R RSSI to dBm offset in dB (default=0)\n"
262 " -S Swap channels (UmTRX only)\n",
Thomas Tsou85b179d2013-11-15 21:14:33 -0500263 "EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
264}
265
266static void handle_options(int argc, char **argv, struct trx_config *config)
267{
268 int option;
269
Tom Tsoude116e92017-03-30 17:00:42 -0700270 config->log_level = "NOTICE";
271 config->addr = DEFAULT_TRX_IP;
272 config->port = DEFAULT_TRX_PORT;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800273 config->tx_sps = DEFAULT_TX_SPS;
274 config->rx_sps = DEFAULT_RX_SPS;
Tom Tsou64ad7122015-05-19 18:26:31 -0700275 config->chans = DEFAULT_CHANS;
276 config->rtsc = 0;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300277 config->rach_delay = 0;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500278 config->extref = false;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700279 config->gpsref = false;
Tom Tsou64ad7122015-05-19 18:26:31 -0700280 config->filler = Transceiver::FILLER_ZERO;
Tom Tsou76764272016-06-24 14:25:39 -0700281 config->mcbts = false;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500282 config->offset = 0.0;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400283 config->rssi_offset = 0.0;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400284 config->swap_channels = false;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800285 config->edge = false;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500286
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700287 while ((option = getopt(argc, argv, "ha:l:i:p:c:dmxgfo:s:b:r:A:R:Se")) != -1) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500288 switch (option) {
289 case 'h':
290 print_help();
291 exit(0);
292 break;
293 case 'a':
294 config->dev_args = optarg;
295 break;
296 case 'l':
297 config->log_level = optarg;
298 break;
299 case 'i':
300 config->addr = optarg;
301 break;
302 case 'p':
303 config->port = atoi(optarg);
304 break;
305 case 'c':
306 config->chans = atoi(optarg);
307 break;
Tom Tsou76764272016-06-24 14:25:39 -0700308 case 'm':
309 config->mcbts = true;
310 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500311 case 'x':
312 config->extref = true;
313 break;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700314 case 'g':
315 config->gpsref = true;
316 break;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500317 case 'f':
Tom Tsou64ad7122015-05-19 18:26:31 -0700318 config->filler = Transceiver::FILLER_DUMMY;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500319 break;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500320 case 'o':
321 config->offset = atof(optarg);
322 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500323 case 's':
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800324 config->tx_sps = atoi(optarg);
Tom Tsou64ad7122015-05-19 18:26:31 -0700325 break;
Tom Tsou2e4ed102016-06-27 15:39:16 -0700326 case 'b':
327 config->rx_sps = atoi(optarg);
328 break;
Tom Tsou64ad7122015-05-19 18:26:31 -0700329 case 'r':
330 config->rtsc = atoi(optarg);
Tom Tsouaf717b22016-03-06 22:19:15 -0800331 config->filler = Transceiver::FILLER_NORM_RAND;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500332 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300333 case 'A':
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300334 config->rach_delay = atoi(optarg);
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300335 config->filler = Transceiver::FILLER_ACCESS_RAND;
336 break;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400337 case 'R':
338 config->rssi_offset = atof(optarg);
339 break;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400340 case 'S':
341 config->swap_channels = true;
342 break;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800343 case 'e':
344 config->edge = true;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800345 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500346 default:
347 print_help();
348 exit(0);
349 }
350 }
Tom Tsou64ad7122015-05-19 18:26:31 -0700351
Tom Tsou76764272016-06-24 14:25:39 -0700352 /* Force 4 SPS for EDGE or multi-ARFCN configurations */
353 if ((config->edge) || (config->mcbts)) {
Tom Tsou2e4ed102016-06-27 15:39:16 -0700354 config->tx_sps = 4;
355 config->rx_sps = 4;
356 }
357
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700358 if (config->gpsref && config->extref) {
359 printf("External and GPSDO references unavailable at the same time\n\n");
360 goto bad_config;
361 }
362
Tom Tsouaf717b22016-03-06 22:19:15 -0800363 if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
364 config->filler = Transceiver::FILLER_EDGE_RAND;
365
Tom Tsou76764272016-06-24 14:25:39 -0700366 if ((config->tx_sps != 1) && (config->tx_sps != 4) &&
367 (config->rx_sps != 1) && (config->rx_sps != 4)) {
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800368 printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700369 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700370 }
371
372 if (config->rtsc > 7) {
373 printf("Invalid training sequence %i\n\n", config->rtsc);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700374 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700375 }
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300376
377 if (config->rach_delay > 68) {
378 printf("RACH delay is too big %i\n\n", config->rach_delay);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700379 goto bad_config;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300380 }
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700381
382 return;
383
384bad_config:
385 print_help();
386 exit(0);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500387}
388
389int main(int argc, char *argv[])
390{
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700391 int type, chans, ref;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500392 RadioDevice *usrp;
393 RadioInterface *radio = NULL;
394 Transceiver *trx = NULL;
Tom Tsou05c6feb2016-06-22 16:09:44 -0700395 RadioDevice::InterfaceType iface = RadioDevice::NORMAL;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500396 struct trx_config config;
397
Philipp Maiere51a8f02017-03-16 12:09:34 +0100398#ifdef HAVE_SSE3
399 printf("Info: SSE3 support compiled in");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300400#ifdef HAVE___BUILTIN_CPU_SUPPORTS
Philipp Maiere51a8f02017-03-16 12:09:34 +0100401 if (__builtin_cpu_supports("sse3"))
402 printf(" and supported by CPU\n");
403 else
404 printf(", but not supported by CPU\n");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300405#else
406 printf(", but runtime SIMD detection disabled\n");
407#endif
Philipp Maiere51a8f02017-03-16 12:09:34 +0100408#endif
409
410#ifdef HAVE_SSE4_1
411 printf("Info: SSE4.1 support compiled in");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300412#ifdef HAVE___BUILTIN_CPU_SUPPORTS
Philipp Maiere51a8f02017-03-16 12:09:34 +0100413 if (__builtin_cpu_supports("sse4.1"))
414 printf(" and supported by CPU\n");
415 else
416 printf(", but not supported by CPU\n");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300417#else
418 printf(", but runtime SIMD detection disabled\n");
419#endif
Philipp Maiere51a8f02017-03-16 12:09:34 +0100420#endif
421
Philipp Maier7e07cf22017-03-15 18:09:35 +0100422 convolve_init();
423 convert_init();
424
Thomas Tsou85b179d2013-11-15 21:14:33 -0500425 handle_options(argc, argv, &config);
426
427 setup_signal_handlers();
428
429 /* Check database sanity */
430 if (!trx_setup_config(&config)) {
431 std::cerr << "Config: Database failure - exiting" << std::endl;
432 return EXIT_FAILURE;
433 }
434
435 gLogInit("transceiver", config.log_level.c_str(), LOG_LOCAL7);
436
437 srandom(time(NULL));
438
439 /* Create the low level device object */
Tom Tsou76764272016-06-24 14:25:39 -0700440 if (config.mcbts)
441 iface = RadioDevice::MULTI_ARFCN;
442
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700443 if (config.extref)
444 ref = RadioDevice::REF_EXTERNAL;
445 else if (config.gpsref)
446 ref = RadioDevice::REF_GPS;
447 else
448 ref = RadioDevice::REF_INTERNAL;
449
Tom Tsou05c6feb2016-06-22 16:09:44 -0700450 usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
451 config.chans, config.offset);
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700452 type = usrp->open(config.dev_args, ref, config.swap_channels);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500453 if (type < 0) {
454 LOG(ALERT) << "Failed to create radio device" << std::endl;
455 goto shutdown;
456 }
457
458 /* Setup the appropriate device interface */
459 radio = makeRadioInterface(&config, usrp, type);
460 if (!radio)
461 goto shutdown;
462
463 /* Create the transceiver core */
464 trx = makeTransceiver(&config, radio);
465 if (!trx)
466 goto shutdown;
467
Thomas Tsou85b179d2013-11-15 21:14:33 -0500468 chans = trx->numChans();
469 std::cout << "-- Transceiver active with "
470 << chans << " channel(s)" << std::endl;
471
472 while (!gshutdown)
473 sleep(1);
474
475shutdown:
476 std::cout << "Shutting down transceiver..." << std::endl;
477
478 delete trx;
479 delete radio;
480 delete usrp;
481
482 return 0;
483}