blob: 0562dcd92022f7379ecc3d7e5ef4f4844409a16e [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>
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +010031#include <vector>
32#include <string>
33#include <sstream>
34#include <iostream>
Thomas Tsou85b179d2013-11-15 21:14:33 -050035
36#include <GSMCommon.h>
37#include <Logger.h>
Thomas Tsou85b179d2013-11-15 21:14:33 -050038
Philipp Maier7e07cf22017-03-15 18:09:35 +010039extern "C" {
Pau Espin Pedrolab22f4c2018-02-21 20:15:18 +010040#include <osmocom/core/application.h>
Philipp Maier7e07cf22017-03-15 18:09:35 +010041#include "convolve.h"
42#include "convert.h"
43}
44
Thomas Tsou85b179d2013-11-15 21:14:33 -050045/* Samples-per-symbol for downlink path
46 * 4 - Uses precision modulator (more computation, less distortion)
47 * 1 - Uses minimized modulator (less computation, more distortion)
48 *
49 * Other values are invalid. Receive path (uplink) is always
Tom Tsou0fe41a52016-05-03 15:14:45 -070050 * downsampled to 1 sps. Default to 4 sps for all cases.
Thomas Tsou85b179d2013-11-15 21:14:33 -050051 */
Tom Tsou5cd70dc2016-03-06 01:28:40 -080052#define DEFAULT_TX_SPS 4
Thomas Tsou85b179d2013-11-15 21:14:33 -050053
Tom Tsou5cd70dc2016-03-06 01:28:40 -080054/*
55 * Samples-per-symbol for uplink (receiver) path
56 * Do not modify this value. EDGE configures 4 sps automatically on
57 * B200/B210 devices only. Use of 4 sps on the receive path for other
58 * configurations is not supported.
59 */
60#define DEFAULT_RX_SPS 1
61
Tom Tsoude116e92017-03-30 17:00:42 -070062/* Default configuration parameters */
Thomas Tsou85b179d2013-11-15 21:14:33 -050063#define DEFAULT_TRX_PORT 5700
64#define DEFAULT_TRX_IP "127.0.0.1"
Thomas Tsou85b179d2013-11-15 21:14:33 -050065#define DEFAULT_CHANS 1
66
67struct trx_config {
68 std::string log_level;
Pau Espin Pedrol8c800952017-08-16 16:53:23 +020069 std::string local_addr;
70 std::string remote_addr;
Thomas Tsou85b179d2013-11-15 21:14:33 -050071 std::string dev_args;
72 unsigned port;
Tom Tsou5cd70dc2016-03-06 01:28:40 -080073 unsigned tx_sps;
74 unsigned rx_sps;
Thomas Tsou85b179d2013-11-15 21:14:33 -050075 unsigned chans;
Tom Tsou64ad7122015-05-19 18:26:31 -070076 unsigned rtsc;
Alexander Chemeris37c52c72016-03-25 18:28:34 +030077 unsigned rach_delay;
Thomas Tsou85b179d2013-11-15 21:14:33 -050078 bool extref;
Tom Tsou2f3e60b2016-07-17 19:29:08 -070079 bool gpsref;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -040080 Transceiver::FillerType filler;
Tom Tsou76764272016-06-24 14:25:39 -070081 bool mcbts;
Thomas Tsou8e17df72014-03-06 14:16:11 -050082 double offset;
Alexander Chemerise8905a02015-06-03 23:47:56 -040083 double rssi_offset;
Alexander Chemeris50747dc2015-06-07 01:07:45 -040084 bool swap_channels;
Tom Tsoub0aefcb2016-03-06 03:44:34 -080085 bool edge;
Harald Welte81486e02017-06-29 15:35:22 +020086 int sched_rr;
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +010087 std::vector<std::string> rx_paths;
88 std::vector<std::string> tx_paths;
Thomas Tsou85b179d2013-11-15 21:14:33 -050089};
90
Thomas Tsou85b179d2013-11-15 21:14:33 -050091volatile bool gshutdown = false;
92
Thomas Tsou85b179d2013-11-15 21:14:33 -050093/* Setup configuration values
94 * Don't query the existence of the Log.Level because it's a
95 * mandatory value. That is, if it doesn't exist, the configuration
Thomas Tsou4de70be2013-11-17 18:54:52 -050096 * table will crash or will have already crashed. Everything else we
97 * can survive without and use default values if the database entries
Thomas Tsou85b179d2013-11-15 21:14:33 -050098 * are empty.
99 */
100bool trx_setup_config(struct trx_config *config)
101{
Tom Tsou76764272016-06-24 14:25:39 -0700102 std::string refstr, fillstr, divstr, mcstr, edgestr;
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100103 std::vector<std::string>::const_iterator si;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500104
Tom Tsou60317342017-03-30 19:36:41 -0700105 if (config->mcbts && config->chans > 5) {
Tom Tsou76764272016-06-24 14:25:39 -0700106 std::cout << "Unsupported number of channels" << std::endl;
107 return false;
108 }
109
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800110 edgestr = config->edge ? "Enabled" : "Disabled";
Tom Tsou76764272016-06-24 14:25:39 -0700111 mcstr = config->mcbts ? "Enabled" : "Disabled";
112
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700113 if (config->extref)
114 refstr = "External";
115 else if (config->gpsref)
116 refstr = "GPS";
117 else
118 refstr = "Internal";
119
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400120 switch (config->filler) {
121 case Transceiver::FILLER_DUMMY:
122 fillstr = "Dummy bursts";
123 break;
124 case Transceiver::FILLER_ZERO:
125 fillstr = "Disabled";
126 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800127 case Transceiver::FILLER_NORM_RAND:
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400128 fillstr = "Normal busrts with random payload";
129 break;
Tom Tsouaf717b22016-03-06 22:19:15 -0800130 case Transceiver::FILLER_EDGE_RAND:
131 fillstr = "EDGE busrts with random payload";
132 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300133 case Transceiver::FILLER_ACCESS_RAND:
134 fillstr = "Access busrts with random payload";
135 break;
Alexander Chemerisf5fd5782015-05-24 18:56:51 -0400136 }
Thomas Tsou85b179d2013-11-15 21:14:33 -0500137
138 std::ostringstream ost("");
139 ost << "Config Settings" << std::endl;
140 ost << " Log Level............... " << config->log_level << std::endl;
141 ost << " Device args............. " << config->dev_args << std::endl;
142 ost << " TRX Base Port........... " << config->port << std::endl;
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200143 ost << " TRX Address............. " << config->local_addr << std::endl;
144 ost << " GSM Core Address........." << config->remote_addr << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500145 ost << " Channels................ " << config->chans << std::endl;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800146 ost << " Tx Samples-per-Symbol... " << config->tx_sps << std::endl;
Alexander Chemeris1ab5e7f2016-04-20 08:44:55 +0300147 ost << " Rx Samples-per-Symbol... " << config->rx_sps << std::endl;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800148 ost << " EDGE support............ " << edgestr << std::endl;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700149 ost << " Reference............... " << refstr << std::endl;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500150 ost << " C0 Filler Table......... " << fillstr << std::endl;
Tom Tsou76764272016-06-24 14:25:39 -0700151 ost << " Multi-Carrier........... " << mcstr << std::endl;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500152 ost << " Tuning offset........... " << config->offset << std::endl;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400153 ost << " RSSI to dBm offset...... " << config->rssi_offset << std::endl;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400154 ost << " Swap channels........... " << config->swap_channels << std::endl;
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100155 ost << " Tx Antennas.............";
156 for (si = config->tx_paths.begin(); si != config->tx_paths.end(); ++si)
157 ost << " '" << ((*si != "") ? *si : "<default>") << "'";
158 ost << std::endl;
159 ost << " Rx Antennas.............";
160 for (si = config->rx_paths.begin(); si != config->rx_paths.end(); ++si)
161 ost << " '" << ((*si != "") ? *si : "<default>") << "'";
162 ost << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500163
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100164 std::cout << ost << std::endl;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500165 return true;
166}
167
168/* Create radio interface
169 * The interface consists of sample rate changes, frequency shifts,
170 * channel multiplexing, and other conversions. The transceiver core
171 * accepts input vectors sampled at multiples of the GSM symbol rate.
172 * The radio interface connects the main transceiver with the device
173 * object, which may be operating some other rate.
174 */
175RadioInterface *makeRadioInterface(struct trx_config *config,
176 RadioDevice *usrp, int type)
177{
178 RadioInterface *radio = NULL;
179
180 switch (type) {
181 case RadioDevice::NORMAL:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800182 radio = new RadioInterface(usrp, config->tx_sps,
183 config->rx_sps, config->chans);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500184 break;
185 case RadioDevice::RESAMP_64M:
186 case RadioDevice::RESAMP_100M:
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800187 radio = new RadioInterfaceResamp(usrp, config->tx_sps,
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700188 config->rx_sps);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500189 break;
Tom Tsou76764272016-06-24 14:25:39 -0700190 case RadioDevice::MULTI_ARFCN:
191 radio = new RadioInterfaceMulti(usrp, config->tx_sps,
192 config->rx_sps, config->chans);
193 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500194 default:
195 LOG(ALERT) << "Unsupported radio interface configuration";
196 return NULL;
197 }
198
199 if (!radio->init(type)) {
200 LOG(ALERT) << "Failed to initialize radio interface";
201 return NULL;
202 }
203
204 return radio;
205}
206
207/* Create transceiver core
208 * The multi-threaded modem core operates at multiples of the GSM rate of
209 * 270.8333 ksps and consists of GSM specific modulation, demodulation,
210 * and decoding schemes. Also included are the socket interfaces for
211 * connecting to the upper layer stack.
212 */
213Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
214{
215 Transceiver *trx;
216 VectorFIFO *fifo;
217
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200218 trx = new Transceiver(config->port, config->local_addr.c_str(),
219 config->remote_addr.c_str(), config->tx_sps,
220 config->rx_sps, config->chans, GSM::Time(3,0),
221 radio, config->rssi_offset);
Tom Tsou64464e62016-07-01 03:46:46 -0700222 if (!trx->init(config->filler, config->rtsc,
223 config->rach_delay, config->edge)) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500224 LOG(ALERT) << "Failed to initialize transceiver";
225 delete trx;
226 return NULL;
227 }
228
229 for (size_t i = 0; i < config->chans; i++) {
230 fifo = radio->receiveFIFO(i);
231 if (fifo && trx->receiveFIFO(fifo, i))
232 continue;
233
234 LOG(ALERT) << "Could not attach FIFO to channel " << i;
235 delete trx;
236 return NULL;
237 }
238
239 return trx;
240}
241
242static void sig_handler(int signo)
243{
Pau Espin Pedrolab22f4c2018-02-21 20:15:18 +0100244 fprintf(stdout, "signal %d received\n", signo);
245 switch (signo) {
246 case SIGINT:
247 case SIGTERM:
248 fprintf(stdout, "shutting down\n");
249 gshutdown = true;
250 break;
251 default:
252 break;
253 }
Thomas Tsou85b179d2013-11-15 21:14:33 -0500254}
255
256static void setup_signal_handlers()
257{
Pau Espin Pedrolab22f4c2018-02-21 20:15:18 +0100258 /* Handle keyboard interrupt SIGINT */
259 signal(SIGINT, &sig_handler);
260 signal(SIGTERM, &sig_handler);
261 signal(SIGABRT, &sig_handler);
262 signal(SIGUSR1, &sig_handler);
263 signal(SIGUSR2, &sig_handler);
264 osmo_init_ignore_signals();
Thomas Tsou85b179d2013-11-15 21:14:33 -0500265}
266
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100267
268static std::vector<std::string> comma_delimited_to_vector(char* opt) {
269 std::string str = std::string(opt);
270 std::vector<std::string> result;
271 std::stringstream ss(str);
272
273 while( ss.good() )
274 {
275 std::string substr;
276 getline(ss, substr, ',');
277 result.push_back(substr);
278 }
279 return result;
280}
281
Thomas Tsou85b179d2013-11-15 21:14:33 -0500282static void print_help()
283{
284 fprintf(stdout, "Options:\n"
285 " -h This text\n"
286 " -a UHD device args\n"
287 " -l Logging level (%s)\n"
288 " -i IP address of GSM core\n"
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200289 " -j IP address of osmo-trx\n"
Thomas Tsou85b179d2013-11-15 21:14:33 -0500290 " -p Base port number\n"
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800291 " -e Enable EDGE receiver\n"
Tom Tsou76764272016-06-24 14:25:39 -0700292 " -m Enable multi-ARFCN transceiver (default=disabled)\n"
Thomas Tsou85b179d2013-11-15 21:14:33 -0500293 " -x Enable external 10 MHz reference\n"
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700294 " -g Enable GPSDO reference\n"
Tom Tsou2e4ed102016-06-27 15:39:16 -0700295 " -s Tx samples-per-symbol (1 or 4)\n"
296 " -b Rx samples-per-symbol (1 or 4)\n"
Thomas Tsou15d743e2014-01-25 02:34:03 -0500297 " -c Number of ARFCN channels (default=1)\n"
Thomas Tsou8e17df72014-03-06 14:16:11 -0500298 " -f Enable C0 filler table\n"
Tom Tsou64ad7122015-05-19 18:26:31 -0700299 " -o Set baseband frequency offset (default=auto)\n"
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300300 " -r Random Normal Burst test mode with TSC\n"
301 " -A Random Access Burst test mode with delay\n"
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400302 " -R RSSI to dBm offset in dB (default=0)\n"
Harald Welte81486e02017-06-29 15:35:22 +0200303 " -S Swap channels (UmTRX only)\n"
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100304 " -t SCHED_RR real-time priority (1..32)\n"
305 " -y comma-delimited list of Tx paths (num elements matches -c)\n"
306 " -z comma-delimited list of Rx paths (num elements matches -c)\n",
Thomas Tsou85b179d2013-11-15 21:14:33 -0500307 "EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
308}
309
310static void handle_options(int argc, char **argv, struct trx_config *config)
311{
312 int option;
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100313 bool tx_path_set = false, rx_path_set = false;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500314
Tom Tsoude116e92017-03-30 17:00:42 -0700315 config->log_level = "NOTICE";
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200316 config->local_addr = DEFAULT_TRX_IP;
317 config->remote_addr = DEFAULT_TRX_IP;
Tom Tsoude116e92017-03-30 17:00:42 -0700318 config->port = DEFAULT_TRX_PORT;
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800319 config->tx_sps = DEFAULT_TX_SPS;
320 config->rx_sps = DEFAULT_RX_SPS;
Tom Tsou64ad7122015-05-19 18:26:31 -0700321 config->chans = DEFAULT_CHANS;
322 config->rtsc = 0;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300323 config->rach_delay = 0;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500324 config->extref = false;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700325 config->gpsref = false;
Tom Tsou64ad7122015-05-19 18:26:31 -0700326 config->filler = Transceiver::FILLER_ZERO;
Tom Tsou76764272016-06-24 14:25:39 -0700327 config->mcbts = false;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500328 config->offset = 0.0;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400329 config->rssi_offset = 0.0;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400330 config->swap_channels = false;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800331 config->edge = false;
Harald Welte81486e02017-06-29 15:35:22 +0200332 config->sched_rr = -1;
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100333 config->tx_paths = std::vector<std::string>(DEFAULT_CHANS, "");
334 config->rx_paths = std::vector<std::string>(DEFAULT_CHANS, "");
Thomas Tsou85b179d2013-11-15 21:14:33 -0500335
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100336 while ((option = getopt(argc, argv, "ha:l:i:j:p:c:dmxgfo:s:b:r:A:R:Set:y:z:")) != -1) {
Thomas Tsou85b179d2013-11-15 21:14:33 -0500337 switch (option) {
338 case 'h':
339 print_help();
340 exit(0);
341 break;
342 case 'a':
343 config->dev_args = optarg;
344 break;
345 case 'l':
346 config->log_level = optarg;
347 break;
348 case 'i':
Pau Espin Pedrol8c800952017-08-16 16:53:23 +0200349 config->remote_addr = optarg;
350 break;
351 case 'j':
352 config->local_addr = optarg;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500353 break;
354 case 'p':
355 config->port = atoi(optarg);
356 break;
357 case 'c':
358 config->chans = atoi(optarg);
359 break;
Tom Tsou76764272016-06-24 14:25:39 -0700360 case 'm':
361 config->mcbts = true;
362 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500363 case 'x':
364 config->extref = true;
365 break;
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700366 case 'g':
367 config->gpsref = true;
368 break;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500369 case 'f':
Tom Tsou64ad7122015-05-19 18:26:31 -0700370 config->filler = Transceiver::FILLER_DUMMY;
Thomas Tsou15d743e2014-01-25 02:34:03 -0500371 break;
Thomas Tsou8e17df72014-03-06 14:16:11 -0500372 case 'o':
373 config->offset = atof(optarg);
374 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500375 case 's':
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800376 config->tx_sps = atoi(optarg);
Tom Tsou64ad7122015-05-19 18:26:31 -0700377 break;
Tom Tsou2e4ed102016-06-27 15:39:16 -0700378 case 'b':
379 config->rx_sps = atoi(optarg);
380 break;
Tom Tsou64ad7122015-05-19 18:26:31 -0700381 case 'r':
382 config->rtsc = atoi(optarg);
Tom Tsouaf717b22016-03-06 22:19:15 -0800383 config->filler = Transceiver::FILLER_NORM_RAND;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500384 break;
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300385 case 'A':
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300386 config->rach_delay = atoi(optarg);
Alexander Chemeris5efe0502016-03-23 17:06:32 +0300387 config->filler = Transceiver::FILLER_ACCESS_RAND;
388 break;
Alexander Chemerise8905a02015-06-03 23:47:56 -0400389 case 'R':
390 config->rssi_offset = atof(optarg);
391 break;
Alexander Chemeris50747dc2015-06-07 01:07:45 -0400392 case 'S':
393 config->swap_channels = true;
394 break;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800395 case 'e':
396 config->edge = true;
Tom Tsoub0aefcb2016-03-06 03:44:34 -0800397 break;
Harald Welte81486e02017-06-29 15:35:22 +0200398 case 't':
399 config->sched_rr = atoi(optarg);
400 break;
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100401 case 'y':
402 config->tx_paths = comma_delimited_to_vector(optarg);
403 tx_path_set = true;
404 break;
405 case 'z':
406 config->rx_paths = comma_delimited_to_vector(optarg);
407 rx_path_set = true;
408 break;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500409 default:
410 print_help();
411 exit(0);
412 }
413 }
Tom Tsou64ad7122015-05-19 18:26:31 -0700414
Tom Tsou76764272016-06-24 14:25:39 -0700415 /* Force 4 SPS for EDGE or multi-ARFCN configurations */
416 if ((config->edge) || (config->mcbts)) {
Tom Tsou2e4ed102016-06-27 15:39:16 -0700417 config->tx_sps = 4;
418 config->rx_sps = 4;
419 }
420
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700421 if (config->gpsref && config->extref) {
422 printf("External and GPSDO references unavailable at the same time\n\n");
423 goto bad_config;
424 }
425
Tom Tsouaf717b22016-03-06 22:19:15 -0800426 if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
427 config->filler = Transceiver::FILLER_EDGE_RAND;
428
Tom Tsou76764272016-06-24 14:25:39 -0700429 if ((config->tx_sps != 1) && (config->tx_sps != 4) &&
430 (config->rx_sps != 1) && (config->rx_sps != 4)) {
Tom Tsou5cd70dc2016-03-06 01:28:40 -0800431 printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700432 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700433 }
434
435 if (config->rtsc > 7) {
436 printf("Invalid training sequence %i\n\n", config->rtsc);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700437 goto bad_config;
Tom Tsou64ad7122015-05-19 18:26:31 -0700438 }
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300439
440 if (config->rach_delay > 68) {
441 printf("RACH delay is too big %i\n\n", config->rach_delay);
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700442 goto bad_config;
Alexander Chemeris37c52c72016-03-25 18:28:34 +0300443 }
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700444
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100445 if (!tx_path_set) {
446 config->tx_paths = std::vector<std::string>(config->chans, "");
447 } else if (config->tx_paths.size() != config->chans) {
448 printf("Num of channels and num of Tx Antennas doesn't match\n\n");
449 goto bad_config;
450 }
451 if (!rx_path_set) {
452 config->rx_paths = std::vector<std::string>(config->chans, "");
453 } else if (config->rx_paths.size() != config->chans) {
454 printf("Num of channels and num of Rx Antennas doesn't match\n\n");
455 goto bad_config;
456 }
457
Tom Tsou8f0ccf62016-07-20 16:35:03 -0700458 return;
459
460bad_config:
461 print_help();
462 exit(0);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500463}
464
Harald Welte81486e02017-06-29 15:35:22 +0200465static int set_sched_rr(int prio)
466{
467 struct sched_param param;
468 int rc;
469 memset(&param, 0, sizeof(param));
470 param.sched_priority = prio;
471 printf("Setting SCHED_RR priority(%d)\n", param.sched_priority);
472 rc = sched_setscheduler(getpid(), SCHED_RR, &param);
473 if (rc != 0) {
474 std::cerr << "Config: Setting SCHED_RR failed" << std::endl;
475 return -1;
476 }
477 return 0;
478}
479
Thomas Tsou85b179d2013-11-15 21:14:33 -0500480int main(int argc, char *argv[])
481{
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700482 int type, chans, ref;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500483 RadioDevice *usrp;
484 RadioInterface *radio = NULL;
485 Transceiver *trx = NULL;
Tom Tsou05c6feb2016-06-22 16:09:44 -0700486 RadioDevice::InterfaceType iface = RadioDevice::NORMAL;
Thomas Tsou85b179d2013-11-15 21:14:33 -0500487 struct trx_config config;
488
Pau Espin Pedrolab22f4c2018-02-21 20:15:18 +0100489 setup_signal_handlers();
490
Philipp Maiere51a8f02017-03-16 12:09:34 +0100491#ifdef HAVE_SSE3
492 printf("Info: SSE3 support compiled in");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300493#ifdef HAVE___BUILTIN_CPU_SUPPORTS
Philipp Maiere51a8f02017-03-16 12:09:34 +0100494 if (__builtin_cpu_supports("sse3"))
495 printf(" and supported by CPU\n");
496 else
497 printf(", but not supported by CPU\n");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300498#else
499 printf(", but runtime SIMD detection disabled\n");
500#endif
Philipp Maiere51a8f02017-03-16 12:09:34 +0100501#endif
502
503#ifdef HAVE_SSE4_1
504 printf("Info: SSE4.1 support compiled in");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300505#ifdef HAVE___BUILTIN_CPU_SUPPORTS
Philipp Maiere51a8f02017-03-16 12:09:34 +0100506 if (__builtin_cpu_supports("sse4.1"))
507 printf(" and supported by CPU\n");
508 else
509 printf(", but not supported by CPU\n");
Vadim Yanitskiy3bd763d2017-05-20 01:46:51 +0300510#else
511 printf(", but runtime SIMD detection disabled\n");
512#endif
Philipp Maiere51a8f02017-03-16 12:09:34 +0100513#endif
514
Philipp Maier7e07cf22017-03-15 18:09:35 +0100515 convolve_init();
516 convert_init();
517
Thomas Tsou85b179d2013-11-15 21:14:33 -0500518 handle_options(argc, argv, &config);
519
Harald Welte81486e02017-06-29 15:35:22 +0200520 if (config.sched_rr != -1) {
521 if (set_sched_rr(config.sched_rr) < 0)
522 return EXIT_FAILURE;
523 }
524
Thomas Tsou85b179d2013-11-15 21:14:33 -0500525 /* Check database sanity */
526 if (!trx_setup_config(&config)) {
527 std::cerr << "Config: Database failure - exiting" << std::endl;
528 return EXIT_FAILURE;
529 }
530
Pau Espin Pedrol11d50d92018-02-20 17:52:28 +0100531 gLogInit(config.log_level.c_str());
Thomas Tsou85b179d2013-11-15 21:14:33 -0500532
533 srandom(time(NULL));
534
535 /* Create the low level device object */
Tom Tsou76764272016-06-24 14:25:39 -0700536 if (config.mcbts)
537 iface = RadioDevice::MULTI_ARFCN;
538
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700539 if (config.extref)
540 ref = RadioDevice::REF_EXTERNAL;
541 else if (config.gpsref)
542 ref = RadioDevice::REF_GPS;
543 else
544 ref = RadioDevice::REF_INTERNAL;
545
Tom Tsou05c6feb2016-06-22 16:09:44 -0700546 usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
Pau Espin Pedrol77ce99a2018-02-05 13:05:06 +0100547 config.chans, config.offset, config.tx_paths, config.rx_paths);
Tom Tsou2f3e60b2016-07-17 19:29:08 -0700548 type = usrp->open(config.dev_args, ref, config.swap_channels);
Thomas Tsou85b179d2013-11-15 21:14:33 -0500549 if (type < 0) {
550 LOG(ALERT) << "Failed to create radio device" << std::endl;
551 goto shutdown;
552 }
553
554 /* Setup the appropriate device interface */
555 radio = makeRadioInterface(&config, usrp, type);
556 if (!radio)
557 goto shutdown;
558
559 /* Create the transceiver core */
560 trx = makeTransceiver(&config, radio);
561 if (!trx)
562 goto shutdown;
563
Thomas Tsou85b179d2013-11-15 21:14:33 -0500564 chans = trx->numChans();
565 std::cout << "-- Transceiver active with "
566 << chans << " channel(s)" << std::endl;
567
568 while (!gshutdown)
569 sleep(1);
570
571shutdown:
572 std::cout << "Shutting down transceiver..." << std::endl;
573
574 delete trx;
575 delete radio;
576 delete usrp;
577
578 return 0;
579}