blob: b07ffe83d88dc96bbb8adc744e0e1e977fc39d5a [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
Thomas Tsou85b179d2013-11-15 21:14:33 -050035/* Samples-per-symbol for downlink path
36 * 4 - Uses precision modulator (more computation, less distortion)
37 * 1 - Uses minimized modulator (less computation, more distortion)
38 *
39 * Other values are invalid. Receive path (uplink) is always
Tom Tsou0fe41a52016-05-03 15:14:45 -070040 * downsampled to 1 sps. Default to 4 sps for all cases.
Thomas Tsou85b179d2013-11-15 21:14:33 -050041 */
Tom Tsou5cd70dc2016-03-06 01:28:40 -080042#define DEFAULT_TX_SPS 4
Thomas Tsou85b179d2013-11-15 21:14:33 -050043
Tom Tsou5cd70dc2016-03-06 01:28:40 -080044/*
45 * Samples-per-symbol for uplink (receiver) path
46 * Do not modify this value. EDGE configures 4 sps automatically on
47 * B200/B210 devices only. Use of 4 sps on the receive path for other
48 * configurations is not supported.
49 */
50#define DEFAULT_RX_SPS 1
51
Tom Tsoude116e92017-03-30 17:00:42 -070052/* Default configuration parameters */
Thomas Tsou85b179d2013-11-15 21:14:33 -050053#define DEFAULT_TRX_PORT 5700
54#define DEFAULT_TRX_IP "127.0.0.1"
Thomas Tsou85b179d2013-11-15 21:14:33 -050055#define DEFAULT_CHANS 1
56
57struct trx_config {
58 std::string log_level;
59 std::string addr;
60 std::string dev_args;
61 unsigned port;
Tom Tsou5cd70dc2016-03-06 01:28:40 -080062 unsigned tx_sps;
63 unsigned rx_sps;
Thomas Tsou85b179d2013-11-15 21:14:33 -050064 unsigned chans;
Tom Tsou64ad7122015-05-19 18:26:31 -070065 unsigned rtsc;
Alexander Chemeris37c52c72016-03-25 18:28:34 +030066 unsigned rach_delay;
Thomas Tsou85b179d2013-11-15 21:14:33 -050067 bool extref;
Tom Tsou2f3e60b2016-07-17 19:29:08 -070068 bool gpsref;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -040069 Transceiver::FillerType filler;
Thomas Tsou85b179d2013-11-15 21:14:33 -050070 bool diversity;
Tom Tsou76764272016-06-24 14:25:39 -070071 bool mcbts;
Thomas Tsou8e17df72014-03-06 14:16:11 -050072 double offset;
Alexander Chemerise8905a02015-06-03 23:47:56 -040073 double rssi_offset;
Alexander Chemeris50747dc2015-06-07 01:07:45 -040074 bool swap_channels;
Tom Tsoub0aefcb2016-03-06 03:44:34 -080075 bool edge;
Thomas Tsou85b179d2013-11-15 21:14:33 -050076};
77
Thomas Tsou4de70be2013-11-17 18:54:52 -050078ConfigurationTable gConfig;
Thomas Tsou85b179d2013-11-15 21:14:33 -050079
80volatile bool gshutdown = false;
81
Thomas Tsou85b179d2013-11-15 21:14:33 -050082/* Setup configuration values
83 * Don't query the existence of the Log.Level because it's a
84 * mandatory value. That is, if it doesn't exist, the configuration
Thomas Tsou4de70be2013-11-17 18:54:52 -050085 * table will crash or will have already crashed. Everything else we
86 * can survive without and use default values if the database entries
Thomas Tsou85b179d2013-11-15 21:14:33 -050087 * are empty.
88 */
89bool trx_setup_config(struct trx_config *config)
90{
Tom Tsou76764272016-06-24 14:25:39 -070091 std::string refstr, fillstr, divstr, mcstr, edgestr;
Thomas Tsou85b179d2013-11-15 21:14:33 -050092
Tom Tsou60317342017-03-30 19:36:41 -070093 if (config->mcbts && config->chans > 5) {
Tom Tsou76764272016-06-24 14:25:39 -070094 std::cout << "Unsupported number of channels" << std::endl;
95 return false;
96 }
97
Tom Tsoub0aefcb2016-03-06 03:44:34 -080098 edgestr = config->edge ? "Enabled" : "Disabled";
Thomas Tsou85b179d2013-11-15 21:14:33 -050099 divstr = config->diversity ? "Enabled" : "Disabled";
Tom Tsou76764272016-06-24 14:25:39 -0700100 mcstr = config->mcbts ? "Enabled" : "Disabled";
101
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700102 if (config->extref)
103 refstr = "External";
104 else if (config->gpsref)
105 refstr = "GPS";
106 else
107 refstr = "Internal";
108
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400109 switch (config->filler) {
110 case Transceiver::FILLER_DUMMY:
111 fillstr = "Dummy bursts";
112 break;
113 case Transceiver::FILLER_ZERO:
114 fillstr = "Disabled";
115 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800116 case Transceiver::FILLER_NORM_RAND:
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400117 fillstr = "Normal busrts with random payload";
118 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800119 case Transceiver::FILLER_EDGE_RAND:
120 fillstr = "EDGE busrts with random payload";
121 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300122 case Transceiver::FILLER_ACCESS_RAND:
123 fillstr = "Access busrts with random payload";
124 break;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400125 }
Thomas Tsou85b179d2013-11-15 21:14:33 -0500126
127 std::ostringstream ost("");
128 ost << "Config Settings" << std::endl;
129 ost << " Log Level............... " << config->log_level << std::endl;
130 ost << " Device args............. " << config->dev_args << std::endl;
131 ost << " TRX Base Port........... " << config->port << std::endl;
132 ost << " TRX Address............. " << config->addr << std::endl;
133 ost << " Channels................ " << config->chans << std::endl;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800134 ost << " Tx Samples-per-Symbol... " << config->tx_sps << std::endl;
Alexander Chemeris1ab5e7f2016-04-20 08:44:55 +0300135 ost << " Rx Samples-per-Symbol... " << config->rx_sps << std::endl;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800136 ost << " EDGE support............ " << edgestr << std::endl;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700137 ost << " Reference............... " << refstr << std::endl;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500138 ost << " C0 Filler Table......... " << fillstr << std::endl;
Tom Tsou76764272016-06-24 14:25:39 -0700139 ost << " Multi-Carrier........... " << mcstr << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500140 ost << " Diversity............... " << divstr << std::endl;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500141 ost << " Tuning offset........... " << config->offset << std::endl;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400142 ost << " RSSI to dBm offset...... " << config->rssi_offset << std::endl;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400143 ost << " Swap channels........... " << config->swap_channels << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500144 std::cout << ost << std::endl;
145
146 return true;
147}
148
149/* Create radio interface
150 * The interface consists of sample rate changes, frequency shifts,
151 * channel multiplexing, and other conversions. The transceiver core
152 * accepts input vectors sampled at multiples of the GSM symbol rate.
153 * The radio interface connects the main transceiver with the device
154 * object, which may be operating some other rate.
155 */
156RadioInterface *makeRadioInterface(struct trx_config *config,
157 RadioDevice *usrp, int type)
158{
159 RadioInterface *radio = NULL;
160
161 switch (type) {
162 case RadioDevice::NORMAL:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800163 radio = new RadioInterface(usrp, config->tx_sps,
164 config->rx_sps, config->chans);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500165 break;
166 case RadioDevice::RESAMP_64M:
167 case RadioDevice::RESAMP_100M:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800168 radio = new RadioInterfaceResamp(usrp, config->tx_sps,
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700169 config->rx_sps);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500170 break;
171 case RadioDevice::DIVERSITY:
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700172
173
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800174 radio = new RadioInterfaceDiversity(usrp, config->tx_sps,
175 config->chans);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500176 break;
Tom Tsou76764272016-06-24 14:25:39 -0700177 case RadioDevice::MULTI_ARFCN:
178 radio = new RadioInterfaceMulti(usrp, config->tx_sps,
179 config->rx_sps, config->chans);
180 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500181 default:
182 LOG(ALERT) << "Unsupported radio interface configuration";
183 return NULL;
184 }
185
186 if (!radio->init(type)) {
187 LOG(ALERT) << "Failed to initialize radio interface";
188 return NULL;
189 }
190
191 return radio;
192}
193
194/* Create transceiver core
195 * The multi-threaded modem core operates at multiples of the GSM rate of
196 * 270.8333 ksps and consists of GSM specific modulation, demodulation,
197 * and decoding schemes. Also included are the socket interfaces for
198 * connecting to the upper layer stack.
199 */
200Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
201{
202 Transceiver *trx;
203 VectorFIFO *fifo;
204
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800205 trx = new Transceiver(config->port, config->addr.c_str(),
206 config->tx_sps, config->rx_sps, config->chans,
207 GSM::Time(3,0), radio, config->rssi_offset);
Tom Tsou64464e62016-07-01 03:46:46 -0700208 if (!trx->init(config->filler, config->rtsc,
209 config->rach_delay, config->edge)) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500210 LOG(ALERT) << "Failed to initialize transceiver";
211 delete trx;
212 return NULL;
213 }
214
215 for (size_t i = 0; i < config->chans; i++) {
216 fifo = radio->receiveFIFO(i);
217 if (fifo && trx->receiveFIFO(fifo, i))
218 continue;
219
220 LOG(ALERT) << "Could not attach FIFO to channel " << i;
221 delete trx;
222 return NULL;
223 }
224
225 return trx;
226}
227
228static void sig_handler(int signo)
229{
230 fprintf(stdout, "Received shutdown signal");
231 gshutdown = true;
232}
233
234static void setup_signal_handlers()
235{
236 if (signal(SIGINT, sig_handler) == SIG_ERR) {
237 fprintf(stderr, "Failed to install SIGINT signal handler\n");
238 exit(EXIT_FAILURE);
239 }
240 if (signal(SIGTERM, sig_handler) == SIG_ERR) {
241 fprintf(stderr, "Couldn't install SIGTERM signal handler\n");
242 exit( EXIT_FAILURE);
243 }
244}
245
246static void print_help()
247{
248 fprintf(stdout, "Options:\n"
249 " -h This text\n"
250 " -a UHD device args\n"
251 " -l Logging level (%s)\n"
252 " -i IP address of GSM core\n"
253 " -p Base port number\n"
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800254 " -e Enable EDGE receiver\n"
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700255 " -d Enable dual channel diversity receiver (deprecated)\n"
Tom Tsou76764272016-06-24 14:25:39 -0700256 " -m Enable multi-ARFCN transceiver (default=disabled)\n"
Thomas Tsou85b179d2013-11-15 21:14:33 -0500257 " -x Enable external 10 MHz reference\n"
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700258 " -g Enable GPSDO reference\n"
Tom Tsou2e4ed102016-06-27 15:39:16 -0700259 " -s Tx samples-per-symbol (1 or 4)\n"
260 " -b Rx samples-per-symbol (1 or 4)\n"
Thomas Tsou15d743e2014-01-25 02:34:03 -0500261 " -c Number of ARFCN channels (default=1)\n"
Thomas Tsou8e17df72014-03-06 14:16:11 -0500262 " -f Enable C0 filler table\n"
Tom Tsou64ad7122015-05-19 18:26:31 -0700263 " -o Set baseband frequency offset (default=auto)\n"
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300264 " -r Random Normal Burst test mode with TSC\n"
265 " -A Random Access Burst test mode with delay\n"
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400266 " -R RSSI to dBm offset in dB (default=0)\n"
267 " -S Swap channels (UmTRX only)\n",
Thomas Tsou85b179d2013-11-15 21:14:33 -0500268 "EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
269}
270
271static void handle_options(int argc, char **argv, struct trx_config *config)
272{
273 int option;
274
Tom Tsoude116e92017-03-30 17:00:42 -0700275 config->log_level = "NOTICE";
276 config->addr = DEFAULT_TRX_IP;
277 config->port = DEFAULT_TRX_PORT;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800278 config->tx_sps = DEFAULT_TX_SPS;
279 config->rx_sps = DEFAULT_RX_SPS;
Tom Tsou64ad7122015-05-19 18:26:31 -0700280 config->chans = DEFAULT_CHANS;
281 config->rtsc = 0;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300282 config->rach_delay = 0;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500283 config->extref = false;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700284 config->gpsref = false;
Tom Tsou64ad7122015-05-19 18:26:31 -0700285 config->filler = Transceiver::FILLER_ZERO;
Tom Tsou76764272016-06-24 14:25:39 -0700286 config->mcbts = false;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500287 config->diversity = false;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500288 config->offset = 0.0;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400289 config->rssi_offset = 0.0;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400290 config->swap_channels = false;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800291 config->edge = false;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500292
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700293 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 -0500294 switch (option) {
295 case 'h':
296 print_help();
297 exit(0);
298 break;
299 case 'a':
300 config->dev_args = optarg;
301 break;
302 case 'l':
303 config->log_level = optarg;
304 break;
305 case 'i':
306 config->addr = optarg;
307 break;
308 case 'p':
309 config->port = atoi(optarg);
310 break;
311 case 'c':
312 config->chans = atoi(optarg);
313 break;
Tom Tsou76764272016-06-24 14:25:39 -0700314 case 'm':
315 config->mcbts = true;
316 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500317 case 'd':
318 config->diversity = true;
319 break;
320 case 'x':
321 config->extref = true;
322 break;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700323 case 'g':
324 config->gpsref = true;
325 break;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500326 case 'f':
Tom Tsou64ad7122015-05-19 18:26:31 -0700327 config->filler = Transceiver::FILLER_DUMMY;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500328 break;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500329 case 'o':
330 config->offset = atof(optarg);
331 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500332 case 's':
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800333 config->tx_sps = atoi(optarg);
Tom Tsou64ad7122015-05-19 18:26:31 -0700334 break;
Tom Tsou2e4ed102016-06-27 15:39:16 -0700335 case 'b':
336 config->rx_sps = atoi(optarg);
337 break;
Tom Tsou64ad7122015-05-19 18:26:31 -0700338 case 'r':
339 config->rtsc = atoi(optarg);
Tom Tsouaf717b22016-03-06 22:19:15 -0800340 config->filler = Transceiver::FILLER_NORM_RAND;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500341 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300342 case 'A':
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300343 config->rach_delay = atoi(optarg);
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300344 config->filler = Transceiver::FILLER_ACCESS_RAND;
345 break;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400346 case 'R':
347 config->rssi_offset = atof(optarg);
348 break;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400349 case 'S':
350 config->swap_channels = true;
351 break;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800352 case 'e':
353 config->edge = true;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800354 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500355 default:
356 print_help();
357 exit(0);
358 }
359 }
Tom Tsou64ad7122015-05-19 18:26:31 -0700360
Tom Tsou76764272016-06-24 14:25:39 -0700361 /* Force 4 SPS for EDGE or multi-ARFCN configurations */
362 if ((config->edge) || (config->mcbts)) {
Tom Tsou2e4ed102016-06-27 15:39:16 -0700363 config->tx_sps = 4;
364 config->rx_sps = 4;
365 }
366
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700367 if (config->gpsref && config->extref) {
368 printf("External and GPSDO references unavailable at the same time\n\n");
369 goto bad_config;
370 }
371
372 /* Special restrictions on (deprecated) diversity configuration */
373 if (config->diversity) {
374 if (config->mcbts || config->edge) {
375 std::cout << "Multi-carrier/EDGE diversity unsupported" << std::endl;
376 goto bad_config;
377 }
378
379 if (config->rx_sps != 1) {
380 std::cout << "Diversity only supported with 1 SPS" << std::endl;
381 goto bad_config;
382 }
383
384 if (config->chans != 2) {
385 std::cout << "Diversity only supported with 2 channels" << std::endl;
386 goto bad_config;
387 }
388 }
389
Tom Tsouaf717b22016-03-06 22:19:15 -0800390 if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
391 config->filler = Transceiver::FILLER_EDGE_RAND;
392
Tom Tsou76764272016-06-24 14:25:39 -0700393 if ((config->tx_sps != 1) && (config->tx_sps != 4) &&
394 (config->rx_sps != 1) && (config->rx_sps != 4)) {
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800395 printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700396 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700397 }
398
399 if (config->rtsc > 7) {
400 printf("Invalid training sequence %i\n\n", config->rtsc);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700401 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700402 }
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300403
404 if (config->rach_delay > 68) {
405 printf("RACH delay is too big %i\n\n", config->rach_delay);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700406 goto bad_config;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300407 }
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700408
409 return;
410
411bad_config:
412 print_help();
413 exit(0);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500414}
415
416int main(int argc, char *argv[])
417{
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700418 int type, chans, ref;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500419 RadioDevice *usrp;
420 RadioInterface *radio = NULL;
421 Transceiver *trx = NULL;
Tom Tsou05c6feb2016-06-22 16:09:44 -0700422 RadioDevice::InterfaceType iface = RadioDevice::NORMAL;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500423 struct trx_config config;
424
425 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}