blob: 61b3098361f2e949af44c0e30578c14917aa238e [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>
Harald Welte81486e02017-06-29 15:35:22 +020030#include <sched.h>
Thomas Tsou85b179d2013-11-15 21:14:33 -050031
32#include <GSMCommon.h>
33#include <Logger.h>
34#include <Configuration.h>
35
Philipp Maier7e07cf22017-03-15 18:09:35 +010036extern "C" {
37#include "convolve.h"
38#include "convert.h"
39}
40
Thomas Tsou85b179d2013-11-15 21:14:33 -050041/* Samples-per-symbol for downlink path
42 * 4 - Uses precision modulator (more computation, less distortion)
43 * 1 - Uses minimized modulator (less computation, more distortion)
44 *
45 * Other values are invalid. Receive path (uplink) is always
Tom Tsou0fe41a52016-05-03 15:14:45 -070046 * downsampled to 1 sps. Default to 4 sps for all cases.
Thomas Tsou85b179d2013-11-15 21:14:33 -050047 */
Tom Tsou5cd70dc2016-03-06 01:28:40 -080048#define DEFAULT_TX_SPS 4
Thomas Tsou85b179d2013-11-15 21:14:33 -050049
Tom Tsou5cd70dc2016-03-06 01:28:40 -080050/*
51 * Samples-per-symbol for uplink (receiver) path
52 * Do not modify this value. EDGE configures 4 sps automatically on
53 * B200/B210 devices only. Use of 4 sps on the receive path for other
54 * configurations is not supported.
55 */
56#define DEFAULT_RX_SPS 1
57
Tom Tsoude116e92017-03-30 17:00:42 -070058/* Default configuration parameters */
Thomas Tsou85b179d2013-11-15 21:14:33 -050059#define DEFAULT_TRX_PORT 5700
60#define DEFAULT_TRX_IP "127.0.0.1"
Thomas Tsou85b179d2013-11-15 21:14:33 -050061#define DEFAULT_CHANS 1
62
63struct trx_config {
64 std::string log_level;
65 std::string addr;
66 std::string dev_args;
67 unsigned port;
Tom Tsou5cd70dc2016-03-06 01:28:40 -080068 unsigned tx_sps;
69 unsigned rx_sps;
Thomas Tsou85b179d2013-11-15 21:14:33 -050070 unsigned chans;
Tom Tsou64ad7122015-05-19 18:26:31 -070071 unsigned rtsc;
Alexander Chemeris37c52c72016-03-25 18:28:34 +030072 unsigned rach_delay;
Thomas Tsou85b179d2013-11-15 21:14:33 -050073 bool extref;
Tom Tsou2f3e60b2016-07-17 19:29:08 -070074 bool gpsref;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -040075 Transceiver::FillerType filler;
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;
Harald Welte81486e02017-06-29 15:35:22 +020081 int sched_rr;
Thomas Tsou85b179d2013-11-15 21:14:33 -050082};
83
Thomas Tsou4de70be2013-11-17 18:54:52 -050084ConfigurationTable gConfig;
Thomas Tsou85b179d2013-11-15 21:14:33 -050085
86volatile bool gshutdown = false;
87
Thomas Tsou85b179d2013-11-15 21:14:33 -050088/* Setup configuration values
89 * Don't query the existence of the Log.Level because it's a
90 * mandatory value. That is, if it doesn't exist, the configuration
Thomas Tsou4de70be2013-11-17 18:54:52 -050091 * table will crash or will have already crashed. Everything else we
92 * can survive without and use default values if the database entries
Thomas Tsou85b179d2013-11-15 21:14:33 -050093 * are empty.
94 */
95bool trx_setup_config(struct trx_config *config)
96{
Tom Tsou76764272016-06-24 14:25:39 -070097 std::string refstr, fillstr, divstr, mcstr, edgestr;
Thomas Tsou85b179d2013-11-15 21:14:33 -050098
Tom Tsou60317342017-03-30 19:36:41 -070099 if (config->mcbts && config->chans > 5) {
Tom Tsou76764272016-06-24 14:25:39 -0700100 std::cout << "Unsupported number of channels" << std::endl;
101 return false;
102 }
103
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800104 edgestr = config->edge ? "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 Tsou8e17df72014-03-06 14:16:11 -0500145 ost << " Tuning offset........... " << config->offset << std::endl;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400146 ost << " RSSI to dBm offset...... " << config->rssi_offset << std::endl;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400147 ost << " Swap channels........... " << config->swap_channels << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500148 std::cout << ost << std::endl;
149
150 return true;
151}
152
153/* Create radio interface
154 * The interface consists of sample rate changes, frequency shifts,
155 * channel multiplexing, and other conversions. The transceiver core
156 * accepts input vectors sampled at multiples of the GSM symbol rate.
157 * The radio interface connects the main transceiver with the device
158 * object, which may be operating some other rate.
159 */
160RadioInterface *makeRadioInterface(struct trx_config *config,
161 RadioDevice *usrp, int type)
162{
163 RadioInterface *radio = NULL;
164
165 switch (type) {
166 case RadioDevice::NORMAL:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800167 radio = new RadioInterface(usrp, config->tx_sps,
168 config->rx_sps, config->chans);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500169 break;
170 case RadioDevice::RESAMP_64M:
171 case RadioDevice::RESAMP_100M:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800172 radio = new RadioInterfaceResamp(usrp, config->tx_sps,
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700173 config->rx_sps);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500174 break;
Tom Tsou76764272016-06-24 14:25:39 -0700175 case RadioDevice::MULTI_ARFCN:
176 radio = new RadioInterfaceMulti(usrp, config->tx_sps,
177 config->rx_sps, config->chans);
178 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500179 default:
180 LOG(ALERT) << "Unsupported radio interface configuration";
181 return NULL;
182 }
183
184 if (!radio->init(type)) {
185 LOG(ALERT) << "Failed to initialize radio interface";
186 return NULL;
187 }
188
189 return radio;
190}
191
192/* Create transceiver core
193 * The multi-threaded modem core operates at multiples of the GSM rate of
194 * 270.8333 ksps and consists of GSM specific modulation, demodulation,
195 * and decoding schemes. Also included are the socket interfaces for
196 * connecting to the upper layer stack.
197 */
198Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
199{
200 Transceiver *trx;
201 VectorFIFO *fifo;
202
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800203 trx = new Transceiver(config->port, config->addr.c_str(),
204 config->tx_sps, config->rx_sps, config->chans,
205 GSM::Time(3,0), radio, config->rssi_offset);
Tom Tsou64464e62016-07-01 03:46:46 -0700206 if (!trx->init(config->filler, config->rtsc,
207 config->rach_delay, config->edge)) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500208 LOG(ALERT) << "Failed to initialize transceiver";
209 delete trx;
210 return NULL;
211 }
212
213 for (size_t i = 0; i < config->chans; i++) {
214 fifo = radio->receiveFIFO(i);
215 if (fifo && trx->receiveFIFO(fifo, i))
216 continue;
217
218 LOG(ALERT) << "Could not attach FIFO to channel " << i;
219 delete trx;
220 return NULL;
221 }
222
223 return trx;
224}
225
226static void sig_handler(int signo)
227{
228 fprintf(stdout, "Received shutdown signal");
229 gshutdown = true;
230}
231
232static void setup_signal_handlers()
233{
234 if (signal(SIGINT, sig_handler) == SIG_ERR) {
235 fprintf(stderr, "Failed to install SIGINT signal handler\n");
236 exit(EXIT_FAILURE);
237 }
238 if (signal(SIGTERM, sig_handler) == SIG_ERR) {
239 fprintf(stderr, "Couldn't install SIGTERM signal handler\n");
240 exit( EXIT_FAILURE);
241 }
242}
243
244static void print_help()
245{
246 fprintf(stdout, "Options:\n"
247 " -h This text\n"
248 " -a UHD device args\n"
249 " -l Logging level (%s)\n"
250 " -i IP address of GSM core\n"
251 " -p Base port number\n"
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800252 " -e Enable EDGE receiver\n"
Tom Tsou76764272016-06-24 14:25:39 -0700253 " -m Enable multi-ARFCN transceiver (default=disabled)\n"
Thomas Tsou85b179d2013-11-15 21:14:33 -0500254 " -x Enable external 10 MHz reference\n"
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700255 " -g Enable GPSDO reference\n"
Tom Tsou2e4ed102016-06-27 15:39:16 -0700256 " -s Tx samples-per-symbol (1 or 4)\n"
257 " -b Rx samples-per-symbol (1 or 4)\n"
Thomas Tsou15d743e2014-01-25 02:34:03 -0500258 " -c Number of ARFCN channels (default=1)\n"
Thomas Tsou8e17df72014-03-06 14:16:11 -0500259 " -f Enable C0 filler table\n"
Tom Tsou64ad7122015-05-19 18:26:31 -0700260 " -o Set baseband frequency offset (default=auto)\n"
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300261 " -r Random Normal Burst test mode with TSC\n"
262 " -A Random Access Burst test mode with delay\n"
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400263 " -R RSSI to dBm offset in dB (default=0)\n"
Harald Welte81486e02017-06-29 15:35:22 +0200264 " -S Swap channels (UmTRX only)\n"
265 " -t SCHED_RR real-time priority (1..32)\n",
Thomas Tsou85b179d2013-11-15 21:14:33 -0500266 "EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
267}
268
269static void handle_options(int argc, char **argv, struct trx_config *config)
270{
271 int option;
272
Tom Tsoude116e92017-03-30 17:00:42 -0700273 config->log_level = "NOTICE";
274 config->addr = DEFAULT_TRX_IP;
275 config->port = DEFAULT_TRX_PORT;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800276 config->tx_sps = DEFAULT_TX_SPS;
277 config->rx_sps = DEFAULT_RX_SPS;
Tom Tsou64ad7122015-05-19 18:26:31 -0700278 config->chans = DEFAULT_CHANS;
279 config->rtsc = 0;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300280 config->rach_delay = 0;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500281 config->extref = false;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700282 config->gpsref = false;
Tom Tsou64ad7122015-05-19 18:26:31 -0700283 config->filler = Transceiver::FILLER_ZERO;
Tom Tsou76764272016-06-24 14:25:39 -0700284 config->mcbts = false;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500285 config->offset = 0.0;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400286 config->rssi_offset = 0.0;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400287 config->swap_channels = false;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800288 config->edge = false;
Harald Welte81486e02017-06-29 15:35:22 +0200289 config->sched_rr = -1;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500290
Harald Welte81486e02017-06-29 15:35:22 +0200291 while ((option = getopt(argc, argv, "ha:l:i:p:c:dmxgfo:s:b:r:A:R:Set:")) != -1) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500292 switch (option) {
293 case 'h':
294 print_help();
295 exit(0);
296 break;
297 case 'a':
298 config->dev_args = optarg;
299 break;
300 case 'l':
301 config->log_level = optarg;
302 break;
303 case 'i':
304 config->addr = optarg;
305 break;
306 case 'p':
307 config->port = atoi(optarg);
308 break;
309 case 'c':
310 config->chans = atoi(optarg);
311 break;
Tom Tsou76764272016-06-24 14:25:39 -0700312 case 'm':
313 config->mcbts = true;
314 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500315 case 'x':
316 config->extref = true;
317 break;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700318 case 'g':
319 config->gpsref = true;
320 break;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500321 case 'f':
Tom Tsou64ad7122015-05-19 18:26:31 -0700322 config->filler = Transceiver::FILLER_DUMMY;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500323 break;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500324 case 'o':
325 config->offset = atof(optarg);
326 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500327 case 's':
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800328 config->tx_sps = atoi(optarg);
Tom Tsou64ad7122015-05-19 18:26:31 -0700329 break;
Tom Tsou2e4ed102016-06-27 15:39:16 -0700330 case 'b':
331 config->rx_sps = atoi(optarg);
332 break;
Tom Tsou64ad7122015-05-19 18:26:31 -0700333 case 'r':
334 config->rtsc = atoi(optarg);
Tom Tsouaf717b22016-03-06 22:19:15 -0800335 config->filler = Transceiver::FILLER_NORM_RAND;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500336 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300337 case 'A':
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300338 config->rach_delay = atoi(optarg);
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300339 config->filler = Transceiver::FILLER_ACCESS_RAND;
340 break;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400341 case 'R':
342 config->rssi_offset = atof(optarg);
343 break;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400344 case 'S':
345 config->swap_channels = true;
346 break;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800347 case 'e':
348 config->edge = true;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800349 break;
Harald Welte81486e02017-06-29 15:35:22 +0200350 case 't':
351 config->sched_rr = atoi(optarg);
352 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500353 default:
354 print_help();
355 exit(0);
356 }
357 }
Tom Tsou64ad7122015-05-19 18:26:31 -0700358
Tom Tsou76764272016-06-24 14:25:39 -0700359 /* Force 4 SPS for EDGE or multi-ARFCN configurations */
360 if ((config->edge) || (config->mcbts)) {
Tom Tsou2e4ed102016-06-27 15:39:16 -0700361 config->tx_sps = 4;
362 config->rx_sps = 4;
363 }
364
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700365 if (config->gpsref && config->extref) {
366 printf("External and GPSDO references unavailable at the same time\n\n");
367 goto bad_config;
368 }
369
Tom Tsouaf717b22016-03-06 22:19:15 -0800370 if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
371 config->filler = Transceiver::FILLER_EDGE_RAND;
372
Tom Tsou76764272016-06-24 14:25:39 -0700373 if ((config->tx_sps != 1) && (config->tx_sps != 4) &&
374 (config->rx_sps != 1) && (config->rx_sps != 4)) {
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800375 printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700376 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700377 }
378
379 if (config->rtsc > 7) {
380 printf("Invalid training sequence %i\n\n", config->rtsc);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700381 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700382 }
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300383
384 if (config->rach_delay > 68) {
385 printf("RACH delay is too big %i\n\n", config->rach_delay);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700386 goto bad_config;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300387 }
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700388
389 return;
390
391bad_config:
392 print_help();
393 exit(0);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500394}
395
Harald Welte81486e02017-06-29 15:35:22 +0200396static int set_sched_rr(int prio)
397{
398 struct sched_param param;
399 int rc;
400 memset(&param, 0, sizeof(param));
401 param.sched_priority = prio;
402 printf("Setting SCHED_RR priority(%d)\n", param.sched_priority);
403 rc = sched_setscheduler(getpid(), SCHED_RR, &param);
404 if (rc != 0) {
405 std::cerr << "Config: Setting SCHED_RR failed" << std::endl;
406 return -1;
407 }
408 return 0;
409}
410
Thomas Tsou85b179d2013-11-15 21:14:33 -0500411int main(int argc, char *argv[])
412{
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700413 int type, chans, ref;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500414 RadioDevice *usrp;
415 RadioInterface *radio = NULL;
416 Transceiver *trx = NULL;
Tom Tsou05c6feb2016-06-22 16:09:44 -0700417 RadioDevice::InterfaceType iface = RadioDevice::NORMAL;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500418 struct trx_config config;
419
Philipp Maiere51a8f02017-03-16 12:09:34 +0100420#ifdef HAVE_SSE3
421 printf("Info: SSE3 support compiled in");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300422#ifdef HAVE___BUILTIN_CPU_SUPPORTS
Philipp Maiere51a8f02017-03-16 12:09:34 +0100423 if (__builtin_cpu_supports("sse3"))
424 printf(" and supported by CPU\n");
425 else
426 printf(", but not supported by CPU\n");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300427#else
428 printf(", but runtime SIMD detection disabled\n");
429#endif
Philipp Maiere51a8f02017-03-16 12:09:34 +0100430#endif
431
432#ifdef HAVE_SSE4_1
433 printf("Info: SSE4.1 support compiled in");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300434#ifdef HAVE___BUILTIN_CPU_SUPPORTS
Philipp Maiere51a8f02017-03-16 12:09:34 +0100435 if (__builtin_cpu_supports("sse4.1"))
436 printf(" and supported by CPU\n");
437 else
438 printf(", but not supported by CPU\n");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300439#else
440 printf(", but runtime SIMD detection disabled\n");
441#endif
Philipp Maiere51a8f02017-03-16 12:09:34 +0100442#endif
443
Philipp Maier7e07cf22017-03-15 18:09:35 +0100444 convolve_init();
445 convert_init();
446
Thomas Tsou85b179d2013-11-15 21:14:33 -0500447 handle_options(argc, argv, &config);
448
Harald Welte81486e02017-06-29 15:35:22 +0200449 if (config.sched_rr != -1) {
450 if (set_sched_rr(config.sched_rr) < 0)
451 return EXIT_FAILURE;
452 }
453
Thomas Tsou85b179d2013-11-15 21:14:33 -0500454 setup_signal_handlers();
455
456 /* Check database sanity */
457 if (!trx_setup_config(&config)) {
458 std::cerr << "Config: Database failure - exiting" << std::endl;
459 return EXIT_FAILURE;
460 }
461
462 gLogInit("transceiver", config.log_level.c_str(), LOG_LOCAL7);
463
464 srandom(time(NULL));
465
466 /* Create the low level device object */
Tom Tsou76764272016-06-24 14:25:39 -0700467 if (config.mcbts)
468 iface = RadioDevice::MULTI_ARFCN;
469
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700470 if (config.extref)
471 ref = RadioDevice::REF_EXTERNAL;
472 else if (config.gpsref)
473 ref = RadioDevice::REF_GPS;
474 else
475 ref = RadioDevice::REF_INTERNAL;
476
Tom Tsou05c6feb2016-06-22 16:09:44 -0700477 usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
478 config.chans, config.offset);
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700479 type = usrp->open(config.dev_args, ref, config.swap_channels);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500480 if (type < 0) {
481 LOG(ALERT) << "Failed to create radio device" << std::endl;
482 goto shutdown;
483 }
484
485 /* Setup the appropriate device interface */
486 radio = makeRadioInterface(&config, usrp, type);
487 if (!radio)
488 goto shutdown;
489
490 /* Create the transceiver core */
491 trx = makeTransceiver(&config, radio);
492 if (!trx)
493 goto shutdown;
494
Thomas Tsou85b179d2013-11-15 21:14:33 -0500495 chans = trx->numChans();
496 std::cout << "-- Transceiver active with "
497 << chans << " channel(s)" << std::endl;
498
499 while (!gshutdown)
500 sleep(1);
501
502shutdown:
503 std::cout << "Shutting down transceiver..." << std::endl;
504
505 delete trx;
506 delete radio;
507 delete usrp;
508
509 return 0;
510}