blob: 2d35a606e1134a5ae849ae0d7799179af9afdfb4 [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;
Thomas Tsou85b179d2013-11-15 21:14:33 -050075 bool diversity;
Tom Tsou76764272016-06-24 14:25:39 -070076 bool mcbts;
Thomas Tsou8e17df72014-03-06 14:16:11 -050077 double offset;
Alexander Chemerise8905a02015-06-03 23:47:56 -040078 double rssi_offset;
Alexander Chemeris50747dc2015-06-07 01:07:45 -040079 bool swap_channels;
Tom Tsoub0aefcb2016-03-06 03:44:34 -080080 bool edge;
Thomas Tsou85b179d2013-11-15 21:14:33 -050081};
82
Thomas Tsou4de70be2013-11-17 18:54:52 -050083ConfigurationTable gConfig;
Thomas Tsou85b179d2013-11-15 21:14:33 -050084
85volatile bool gshutdown = false;
86
Thomas Tsou85b179d2013-11-15 21:14:33 -050087/* Setup configuration values
88 * Don't query the existence of the Log.Level because it's a
89 * mandatory value. That is, if it doesn't exist, the configuration
Thomas Tsou4de70be2013-11-17 18:54:52 -050090 * table will crash or will have already crashed. Everything else we
91 * can survive without and use default values if the database entries
Thomas Tsou85b179d2013-11-15 21:14:33 -050092 * are empty.
93 */
94bool trx_setup_config(struct trx_config *config)
95{
Tom Tsou76764272016-06-24 14:25:39 -070096 std::string refstr, fillstr, divstr, mcstr, edgestr;
Thomas Tsou85b179d2013-11-15 21:14:33 -050097
Tom Tsou60317342017-03-30 19:36:41 -070098 if (config->mcbts && config->chans > 5) {
Tom Tsou76764272016-06-24 14:25:39 -070099 std::cout << "Unsupported number of channels" << std::endl;
100 return false;
101 }
102
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800103 edgestr = config->edge ? "Enabled" : "Disabled";
Thomas Tsou85b179d2013-11-15 21:14:33 -0500104 divstr = config->diversity ? "Enabled" : "Disabled";
Tom Tsou76764272016-06-24 14:25:39 -0700105 mcstr = config->mcbts ? "Enabled" : "Disabled";
106
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700107 if (config->extref)
108 refstr = "External";
109 else if (config->gpsref)
110 refstr = "GPS";
111 else
112 refstr = "Internal";
113
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400114 switch (config->filler) {
115 case Transceiver::FILLER_DUMMY:
116 fillstr = "Dummy bursts";
117 break;
118 case Transceiver::FILLER_ZERO:
119 fillstr = "Disabled";
120 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800121 case Transceiver::FILLER_NORM_RAND:
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400122 fillstr = "Normal busrts with random payload";
123 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800124 case Transceiver::FILLER_EDGE_RAND:
125 fillstr = "EDGE busrts with random payload";
126 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300127 case Transceiver::FILLER_ACCESS_RAND:
128 fillstr = "Access busrts with random payload";
129 break;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400130 }
Thomas Tsou85b179d2013-11-15 21:14:33 -0500131
132 std::ostringstream ost("");
133 ost << "Config Settings" << std::endl;
134 ost << " Log Level............... " << config->log_level << std::endl;
135 ost << " Device args............. " << config->dev_args << std::endl;
136 ost << " TRX Base Port........... " << config->port << std::endl;
137 ost << " TRX Address............. " << config->addr << std::endl;
138 ost << " Channels................ " << config->chans << std::endl;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800139 ost << " Tx Samples-per-Symbol... " << config->tx_sps << std::endl;
Alexander Chemeris1ab5e7f2016-04-20 08:44:55 +0300140 ost << " Rx Samples-per-Symbol... " << config->rx_sps << std::endl;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800141 ost << " EDGE support............ " << edgestr << std::endl;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700142 ost << " Reference............... " << refstr << std::endl;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500143 ost << " C0 Filler Table......... " << fillstr << std::endl;
Tom Tsou76764272016-06-24 14:25:39 -0700144 ost << " Multi-Carrier........... " << mcstr << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500145 ost << " Diversity............... " << divstr << std::endl;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500146 ost << " Tuning offset........... " << config->offset << std::endl;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400147 ost << " RSSI to dBm offset...... " << config->rssi_offset << std::endl;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400148 ost << " Swap channels........... " << config->swap_channels << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500149 std::cout << ost << std::endl;
150
151 return true;
152}
153
154/* Create radio interface
155 * The interface consists of sample rate changes, frequency shifts,
156 * channel multiplexing, and other conversions. The transceiver core
157 * accepts input vectors sampled at multiples of the GSM symbol rate.
158 * The radio interface connects the main transceiver with the device
159 * object, which may be operating some other rate.
160 */
161RadioInterface *makeRadioInterface(struct trx_config *config,
162 RadioDevice *usrp, int type)
163{
164 RadioInterface *radio = NULL;
165
166 switch (type) {
167 case RadioDevice::NORMAL:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800168 radio = new RadioInterface(usrp, config->tx_sps,
169 config->rx_sps, config->chans);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500170 break;
171 case RadioDevice::RESAMP_64M:
172 case RadioDevice::RESAMP_100M:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800173 radio = new RadioInterfaceResamp(usrp, config->tx_sps,
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700174 config->rx_sps);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500175 break;
176 case RadioDevice::DIVERSITY:
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700177
178
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800179 radio = new RadioInterfaceDiversity(usrp, config->tx_sps,
180 config->chans);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500181 break;
Tom Tsou76764272016-06-24 14:25:39 -0700182 case RadioDevice::MULTI_ARFCN:
183 radio = new RadioInterfaceMulti(usrp, config->tx_sps,
184 config->rx_sps, config->chans);
185 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500186 default:
187 LOG(ALERT) << "Unsupported radio interface configuration";
188 return NULL;
189 }
190
191 if (!radio->init(type)) {
192 LOG(ALERT) << "Failed to initialize radio interface";
193 return NULL;
194 }
195
196 return radio;
197}
198
199/* Create transceiver core
200 * The multi-threaded modem core operates at multiples of the GSM rate of
201 * 270.8333 ksps and consists of GSM specific modulation, demodulation,
202 * and decoding schemes. Also included are the socket interfaces for
203 * connecting to the upper layer stack.
204 */
205Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
206{
207 Transceiver *trx;
208 VectorFIFO *fifo;
209
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800210 trx = new Transceiver(config->port, config->addr.c_str(),
211 config->tx_sps, config->rx_sps, config->chans,
212 GSM::Time(3,0), radio, config->rssi_offset);
Tom Tsou64464e62016-07-01 03:46:46 -0700213 if (!trx->init(config->filler, config->rtsc,
214 config->rach_delay, config->edge)) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500215 LOG(ALERT) << "Failed to initialize transceiver";
216 delete trx;
217 return NULL;
218 }
219
220 for (size_t i = 0; i < config->chans; i++) {
221 fifo = radio->receiveFIFO(i);
222 if (fifo && trx->receiveFIFO(fifo, i))
223 continue;
224
225 LOG(ALERT) << "Could not attach FIFO to channel " << i;
226 delete trx;
227 return NULL;
228 }
229
230 return trx;
231}
232
233static void sig_handler(int signo)
234{
235 fprintf(stdout, "Received shutdown signal");
236 gshutdown = true;
237}
238
239static void setup_signal_handlers()
240{
241 if (signal(SIGINT, sig_handler) == SIG_ERR) {
242 fprintf(stderr, "Failed to install SIGINT signal handler\n");
243 exit(EXIT_FAILURE);
244 }
245 if (signal(SIGTERM, sig_handler) == SIG_ERR) {
246 fprintf(stderr, "Couldn't install SIGTERM signal handler\n");
247 exit( EXIT_FAILURE);
248 }
249}
250
251static void print_help()
252{
253 fprintf(stdout, "Options:\n"
254 " -h This text\n"
255 " -a UHD device args\n"
256 " -l Logging level (%s)\n"
257 " -i IP address of GSM core\n"
258 " -p Base port number\n"
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800259 " -e Enable EDGE receiver\n"
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700260 " -d Enable dual channel diversity receiver (deprecated)\n"
Tom Tsou76764272016-06-24 14:25:39 -0700261 " -m Enable multi-ARFCN transceiver (default=disabled)\n"
Thomas Tsou85b179d2013-11-15 21:14:33 -0500262 " -x Enable external 10 MHz reference\n"
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700263 " -g Enable GPSDO reference\n"
Tom Tsou2e4ed102016-06-27 15:39:16 -0700264 " -s Tx samples-per-symbol (1 or 4)\n"
265 " -b Rx samples-per-symbol (1 or 4)\n"
Thomas Tsou15d743e2014-01-25 02:34:03 -0500266 " -c Number of ARFCN channels (default=1)\n"
Thomas Tsou8e17df72014-03-06 14:16:11 -0500267 " -f Enable C0 filler table\n"
Tom Tsou64ad7122015-05-19 18:26:31 -0700268 " -o Set baseband frequency offset (default=auto)\n"
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300269 " -r Random Normal Burst test mode with TSC\n"
270 " -A Random Access Burst test mode with delay\n"
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400271 " -R RSSI to dBm offset in dB (default=0)\n"
272 " -S Swap channels (UmTRX only)\n",
Thomas Tsou85b179d2013-11-15 21:14:33 -0500273 "EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
274}
275
276static void handle_options(int argc, char **argv, struct trx_config *config)
277{
278 int option;
279
Tom Tsoude116e92017-03-30 17:00:42 -0700280 config->log_level = "NOTICE";
281 config->addr = DEFAULT_TRX_IP;
282 config->port = DEFAULT_TRX_PORT;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800283 config->tx_sps = DEFAULT_TX_SPS;
284 config->rx_sps = DEFAULT_RX_SPS;
Tom Tsou64ad7122015-05-19 18:26:31 -0700285 config->chans = DEFAULT_CHANS;
286 config->rtsc = 0;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300287 config->rach_delay = 0;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500288 config->extref = false;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700289 config->gpsref = false;
Tom Tsou64ad7122015-05-19 18:26:31 -0700290 config->filler = Transceiver::FILLER_ZERO;
Tom Tsou76764272016-06-24 14:25:39 -0700291 config->mcbts = false;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500292 config->diversity = false;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500293 config->offset = 0.0;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400294 config->rssi_offset = 0.0;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400295 config->swap_channels = false;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800296 config->edge = false;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500297
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700298 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 -0500299 switch (option) {
300 case 'h':
301 print_help();
302 exit(0);
303 break;
304 case 'a':
305 config->dev_args = optarg;
306 break;
307 case 'l':
308 config->log_level = optarg;
309 break;
310 case 'i':
311 config->addr = optarg;
312 break;
313 case 'p':
314 config->port = atoi(optarg);
315 break;
316 case 'c':
317 config->chans = atoi(optarg);
318 break;
Tom Tsou76764272016-06-24 14:25:39 -0700319 case 'm':
320 config->mcbts = true;
321 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500322 case 'd':
323 config->diversity = true;
324 break;
325 case 'x':
326 config->extref = true;
327 break;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700328 case 'g':
329 config->gpsref = true;
330 break;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500331 case 'f':
Tom Tsou64ad7122015-05-19 18:26:31 -0700332 config->filler = Transceiver::FILLER_DUMMY;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500333 break;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500334 case 'o':
335 config->offset = atof(optarg);
336 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500337 case 's':
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800338 config->tx_sps = atoi(optarg);
Tom Tsou64ad7122015-05-19 18:26:31 -0700339 break;
Tom Tsou2e4ed102016-06-27 15:39:16 -0700340 case 'b':
341 config->rx_sps = atoi(optarg);
342 break;
Tom Tsou64ad7122015-05-19 18:26:31 -0700343 case 'r':
344 config->rtsc = atoi(optarg);
Tom Tsouaf717b22016-03-06 22:19:15 -0800345 config->filler = Transceiver::FILLER_NORM_RAND;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500346 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300347 case 'A':
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300348 config->rach_delay = atoi(optarg);
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300349 config->filler = Transceiver::FILLER_ACCESS_RAND;
350 break;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400351 case 'R':
352 config->rssi_offset = atof(optarg);
353 break;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400354 case 'S':
355 config->swap_channels = true;
356 break;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800357 case 'e':
358 config->edge = true;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800359 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500360 default:
361 print_help();
362 exit(0);
363 }
364 }
Tom Tsou64ad7122015-05-19 18:26:31 -0700365
Tom Tsou76764272016-06-24 14:25:39 -0700366 /* Force 4 SPS for EDGE or multi-ARFCN configurations */
367 if ((config->edge) || (config->mcbts)) {
Tom Tsou2e4ed102016-06-27 15:39:16 -0700368 config->tx_sps = 4;
369 config->rx_sps = 4;
370 }
371
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700372 if (config->gpsref && config->extref) {
373 printf("External and GPSDO references unavailable at the same time\n\n");
374 goto bad_config;
375 }
376
377 /* Special restrictions on (deprecated) diversity configuration */
378 if (config->diversity) {
379 if (config->mcbts || config->edge) {
380 std::cout << "Multi-carrier/EDGE diversity unsupported" << std::endl;
381 goto bad_config;
382 }
383
384 if (config->rx_sps != 1) {
385 std::cout << "Diversity only supported with 1 SPS" << std::endl;
386 goto bad_config;
387 }
388
389 if (config->chans != 2) {
390 std::cout << "Diversity only supported with 2 channels" << std::endl;
391 goto bad_config;
392 }
393 }
394
Tom Tsouaf717b22016-03-06 22:19:15 -0800395 if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
396 config->filler = Transceiver::FILLER_EDGE_RAND;
397
Tom Tsou76764272016-06-24 14:25:39 -0700398 if ((config->tx_sps != 1) && (config->tx_sps != 4) &&
399 (config->rx_sps != 1) && (config->rx_sps != 4)) {
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800400 printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700401 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700402 }
403
404 if (config->rtsc > 7) {
405 printf("Invalid training sequence %i\n\n", config->rtsc);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700406 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700407 }
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300408
409 if (config->rach_delay > 68) {
410 printf("RACH delay is too big %i\n\n", config->rach_delay);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700411 goto bad_config;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300412 }
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700413
414 return;
415
416bad_config:
417 print_help();
418 exit(0);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500419}
420
421int main(int argc, char *argv[])
422{
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700423 int type, chans, ref;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500424 RadioDevice *usrp;
425 RadioInterface *radio = NULL;
426 Transceiver *trx = NULL;
Tom Tsou05c6feb2016-06-22 16:09:44 -0700427 RadioDevice::InterfaceType iface = RadioDevice::NORMAL;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500428 struct trx_config config;
429
Philipp Maier7e07cf22017-03-15 18:09:35 +0100430 convolve_init();
431 convert_init();
432
Thomas Tsou85b179d2013-11-15 21:14:33 -0500433 handle_options(argc, argv, &config);
434
435 setup_signal_handlers();
436
437 /* Check database sanity */
438 if (!trx_setup_config(&config)) {
439 std::cerr << "Config: Database failure - exiting" << std::endl;
440 return EXIT_FAILURE;
441 }
442
443 gLogInit("transceiver", config.log_level.c_str(), LOG_LOCAL7);
444
445 srandom(time(NULL));
446
447 /* Create the low level device object */
Tom Tsou76764272016-06-24 14:25:39 -0700448 if (config.mcbts)
449 iface = RadioDevice::MULTI_ARFCN;
450
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700451 if (config.extref)
452 ref = RadioDevice::REF_EXTERNAL;
453 else if (config.gpsref)
454 ref = RadioDevice::REF_GPS;
455 else
456 ref = RadioDevice::REF_INTERNAL;
457
Tom Tsou05c6feb2016-06-22 16:09:44 -0700458 usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
459 config.chans, config.offset);
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700460 type = usrp->open(config.dev_args, ref, config.swap_channels);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500461 if (type < 0) {
462 LOG(ALERT) << "Failed to create radio device" << std::endl;
463 goto shutdown;
464 }
465
466 /* Setup the appropriate device interface */
467 radio = makeRadioInterface(&config, usrp, type);
468 if (!radio)
469 goto shutdown;
470
471 /* Create the transceiver core */
472 trx = makeTransceiver(&config, radio);
473 if (!trx)
474 goto shutdown;
475
Thomas Tsou85b179d2013-11-15 21:14:33 -0500476 chans = trx->numChans();
477 std::cout << "-- Transceiver active with "
478 << chans << " channel(s)" << std::endl;
479
480 while (!gshutdown)
481 sleep(1);
482
483shutdown:
484 std::cout << "Shutting down transceiver..." << std::endl;
485
486 delete trx;
487 delete radio;
488 delete usrp;
489
490 return 0;
491}