Project

General

Profile

Bug #2720 » osmo-trx.cpp

missing call to x86 function convert_init() - o8ko8k, 12/11/2017 04:33 PM

 
1
/*
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
#include <sched.h>
31

    
32
#include <GSMCommon.h>
33
#include <Logger.h>
34
#include <Configuration.h>
35

    
36
extern "C" {
37
#include "convolve.h"
38
#include "convert.h"
39
}
40

    
41
/* 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
46
 *     downsampled to 1 sps. Default to 4 sps for all cases.
47
 */
48
#define DEFAULT_TX_SPS		4
49

    
50
/*
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

    
58
/* Default configuration parameters */
59
#define DEFAULT_TRX_PORT	5700
60
#define DEFAULT_TRX_IP		"127.0.0.1"
61
#define DEFAULT_CHANS		1
62

    
63
struct trx_config {
64
	std::string log_level;
65
	std::string local_addr;
66
	std::string remote_addr;
67
	std::string dev_args;
68
	unsigned port;
69
	unsigned tx_sps;
70
	unsigned rx_sps;
71
	unsigned chans;
72
	unsigned rtsc;
73
	unsigned rach_delay;
74
	bool extref;
75
	bool gpsref;
76
	Transceiver::FillerType filler;
77
	bool mcbts;
78
	double offset;
79
	double rssi_offset;
80
	bool swap_channels;
81
	bool edge;
82
	int sched_rr;
83
};
84

    
85
ConfigurationTable gConfig;
86

    
87
volatile bool gshutdown = false;
88

    
89
/* Setup configuration values
90
 *     Don't query the existence of the Log.Level because it's a
91
 *     mandatory value. That is, if it doesn't exist, the configuration
92
 *     table will crash or will have already crashed. Everything else we
93
 *     can survive without and use default values if the database entries
94
 *     are empty.
95
 */
96
bool trx_setup_config(struct trx_config *config)
97
{
98
	std::string refstr, fillstr, divstr, mcstr, edgestr;
99

    
100
	if (config->mcbts && config->chans > 5) {
101
		std::cout << "Unsupported number of channels" << std::endl;
102
		return false;
103
	}
104

    
105
	edgestr = config->edge ? "Enabled" : "Disabled";
106
	mcstr = config->mcbts ? "Enabled" : "Disabled";
107

    
108
	if (config->extref)
109
		refstr = "External";
110
	else if (config->gpsref)
111
		refstr = "GPS";
112
	else
113
		refstr = "Internal";
114

    
115
	switch (config->filler) {
116
	case Transceiver::FILLER_DUMMY:
117
		fillstr = "Dummy bursts";
118
		break;
119
	case Transceiver::FILLER_ZERO:
120
		fillstr = "Disabled";
121
		break;
122
	case Transceiver::FILLER_NORM_RAND:
123
		fillstr = "Normal busrts with random payload";
124
		break;
125
	case Transceiver::FILLER_EDGE_RAND:
126
		fillstr = "EDGE busrts with random payload";
127
		break;
128
	case Transceiver::FILLER_ACCESS_RAND:
129
		fillstr = "Access busrts with random payload";
130
		break;
131
	}
132

    
133
	std::ostringstream ost("");
134
	ost << "Config Settings" << std::endl;
135
	ost << "   Log Level............... " << config->log_level << std::endl;
136
	ost << "   Device args............. " << config->dev_args << std::endl;
137
	ost << "   TRX Base Port........... " << config->port << std::endl;
138
	ost << "   TRX Address............. " << config->local_addr << std::endl;
139
	ost << "   GSM Core Address........." << config->remote_addr << std::endl;
140
	ost << "   Channels................ " << config->chans << std::endl;
141
	ost << "   Tx Samples-per-Symbol... " << config->tx_sps << std::endl;
142
	ost << "   Rx Samples-per-Symbol... " << config->rx_sps << std::endl;
143
	ost << "   EDGE support............ " << edgestr << std::endl;
144
	ost << "   Reference............... " << refstr << std::endl;
145
	ost << "   C0 Filler Table......... " << fillstr << std::endl;
146
	ost << "   Multi-Carrier........... " << mcstr << std::endl;
147
	ost << "   Tuning offset........... " << config->offset << std::endl;
148
	ost << "   RSSI to dBm offset...... " << config->rssi_offset << std::endl;
149
	ost << "   Swap channels........... " << config->swap_channels << std::endl;
150
	std::cout << ost << std::endl;
151

    
152
	return true;
153
}
154

    
155
/* Create radio interface
156
 *     The interface consists of sample rate changes, frequency shifts,
157
 *     channel multiplexing, and other conversions. The transceiver core
158
 *     accepts input vectors sampled at multiples of the GSM symbol rate.
159
 *     The radio interface connects the main transceiver with the device
160
 *     object, which may be operating some other rate.
161
 */
162
RadioInterface *makeRadioInterface(struct trx_config *config,
163
                                   RadioDevice *usrp, int type)
164
{
165
	RadioInterface *radio = NULL;
166

    
167
	switch (type) {
168
	case RadioDevice::NORMAL:
169
		radio = new RadioInterface(usrp, config->tx_sps,
170
					   config->rx_sps, config->chans);
171
		break;
172
	case RadioDevice::RESAMP_64M:
173
	case RadioDevice::RESAMP_100M:
174
		radio = new RadioInterfaceResamp(usrp, config->tx_sps,
175
						 config->rx_sps);
176
		break;
177
	case RadioDevice::MULTI_ARFCN:
178
		radio = new RadioInterfaceMulti(usrp, config->tx_sps,
179
						config->rx_sps, config->chans);
180
		break;
181
	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
 */
200
Transceiver *makeTransceiver(struct trx_config *config, RadioInterface *radio)
201
{
202
	Transceiver *trx;
203
	VectorFIFO *fifo;
204

    
205
	trx = new Transceiver(config->port, config->local_addr.c_str(),
206
			      config->remote_addr.c_str(), config->tx_sps,
207
			      config->rx_sps, config->chans, GSM::Time(3,0),
208
			      radio, config->rssi_offset);
209
	if (!trx->init(config->filler, config->rtsc,
210
		       config->rach_delay, config->edge)) {
211
		LOG(ALERT) << "Failed to initialize transceiver";
212
		delete trx;
213
		return NULL;
214
	}
215

    
216
	for (size_t i = 0; i < config->chans; i++) {
217
		fifo = radio->receiveFIFO(i);
218
		if (fifo && trx->receiveFIFO(fifo, i))
219
			continue;
220

    
221
		LOG(ALERT) << "Could not attach FIFO to channel " << i;
222
		delete trx;
223
		return NULL;
224
	}
225

    
226
	return trx;
227
}
228

    
229
static void sig_handler(int signo)
230
{
231
	fprintf(stdout, "Received shutdown signal");
232
	gshutdown = true;
233
}
234

    
235
static void setup_signal_handlers()
236
{
237
	if (signal(SIGINT, sig_handler) == SIG_ERR) {
238
		fprintf(stderr, "Failed to install SIGINT signal handler\n");
239
		exit(EXIT_FAILURE);
240
	}
241
	if (signal(SIGTERM, sig_handler) == SIG_ERR) {
242
		fprintf(stderr, "Couldn't install SIGTERM signal handler\n");
243
		exit( EXIT_FAILURE);
244
	}
245
}
246

    
247
static void print_help()
248
{
249
	fprintf(stdout, "Options:\n"
250
		"  -h    This text\n"
251
		"  -a    UHD device args\n"
252
		"  -l    Logging level (%s)\n"
253
		"  -i    IP address of GSM core\n"
254
		"  -j    IP address of osmo-trx\n"
255
		"  -p    Base port number\n"
256
		"  -e    Enable EDGE receiver\n"
257
		"  -m    Enable multi-ARFCN transceiver (default=disabled)\n"
258
		"  -x    Enable external 10 MHz reference\n"
259
		"  -g    Enable GPSDO reference\n"
260
		"  -s    Tx samples-per-symbol (1 or 4)\n"
261
		"  -b    Rx samples-per-symbol (1 or 4)\n"
262
		"  -c    Number of ARFCN channels (default=1)\n"
263
		"  -f    Enable C0 filler table\n"
264
		"  -o    Set baseband frequency offset (default=auto)\n"
265
		"  -r    Random Normal Burst test mode with TSC\n"
266
		"  -A    Random Access Burst test mode with delay\n"
267
		"  -R    RSSI to dBm offset in dB (default=0)\n"
268
		"  -S    Swap channels (UmTRX only)\n"
269
		"  -t    SCHED_RR real-time priority (1..32)\n",
270
		"EMERG, ALERT, CRT, ERR, WARNING, NOTICE, INFO, DEBUG");
271
}
272

    
273
static void handle_options(int argc, char **argv, struct trx_config *config)
274
{
275
	int option;
276

    
277
	config->log_level = "NOTICE";
278
	config->local_addr = DEFAULT_TRX_IP;
279
	config->remote_addr = DEFAULT_TRX_IP;
280
	config->port = DEFAULT_TRX_PORT;
281
	config->tx_sps = DEFAULT_TX_SPS;
282
	config->rx_sps = DEFAULT_RX_SPS;
283
	config->chans = DEFAULT_CHANS;
284
	config->rtsc = 0;
285
	config->rach_delay = 0;
286
	config->extref = false;
287
	config->gpsref = false;
288
	config->filler = Transceiver::FILLER_ZERO;
289
	config->mcbts = false;
290
	config->offset = 0.0;
291
	config->rssi_offset = 0.0;
292
	config->swap_channels = false;
293
	config->edge = false;
294
	config->sched_rr = -1;
295

    
296
	while ((option = getopt(argc, argv, "ha:l:i:j:p:c:dmxgfo:s:b:r:A:R:Set:")) != -1) {
297
		switch (option) {
298
		case 'h':
299
			print_help();
300
			exit(0);
301
			break;
302
		case 'a':
303
			config->dev_args = optarg;
304
			break;
305
		case 'l':
306
			config->log_level = optarg;
307
			break;
308
		case 'i':
309
			config->remote_addr = optarg;
310
			break;
311
		case 'j':
312
			config->local_addr = optarg;
313
			break;
314
		case 'p':
315
			config->port = atoi(optarg);
316
			break;
317
		case 'c':
318
			config->chans = atoi(optarg);
319
			break;
320
		case 'm':
321
			config->mcbts = true;
322
			break;
323
		case 'x':
324
			config->extref = true;
325
			break;
326
		case 'g':
327
			config->gpsref = true;
328
			break;
329
		case 'f':
330
			config->filler = Transceiver::FILLER_DUMMY;
331
			break;
332
		case 'o':
333
			config->offset = atof(optarg);
334
			break;
335
		case 's':
336
			config->tx_sps = atoi(optarg);
337
			break;
338
		case 'b':
339
			config->rx_sps = atoi(optarg);
340
			break;
341
		case 'r':
342
			config->rtsc = atoi(optarg);
343
			config->filler = Transceiver::FILLER_NORM_RAND;
344
			break;
345
		case 'A':
346
			config->rach_delay = atoi(optarg);
347
			config->filler = Transceiver::FILLER_ACCESS_RAND;
348
			break;
349
		case 'R':
350
			config->rssi_offset = atof(optarg);
351
			break;
352
		case 'S':
353
			config->swap_channels = true;
354
			break;
355
		case 'e':
356
			config->edge = true;
357
			break;
358
		case 't':
359
			config->sched_rr = atoi(optarg);
360
			break;
361
		default:
362
			print_help();
363
			exit(0);
364
		}
365
	}
366

    
367
	/* Force 4 SPS for EDGE or multi-ARFCN configurations */
368
	if ((config->edge) || (config->mcbts)) {
369
		config->tx_sps = 4;
370
		config->rx_sps = 4;
371
	}
372

    
373
	if (config->gpsref && config->extref) {
374
		printf("External and GPSDO references unavailable at the same time\n\n");
375
		goto bad_config;
376
	}
377

    
378
	if (config->edge && (config->filler == Transceiver::FILLER_NORM_RAND))
379
		config->filler = Transceiver::FILLER_EDGE_RAND;
380

    
381
	if ((config->tx_sps != 1) && (config->tx_sps != 4) &&
382
	    (config->rx_sps != 1) && (config->rx_sps != 4)) {
383
		printf("Unsupported samples-per-symbol %i\n\n", config->tx_sps);
384
		goto bad_config;
385
	}
386

    
387
	if (config->rtsc > 7) {
388
		printf("Invalid training sequence %i\n\n", config->rtsc);
389
		goto bad_config;
390
	}
391

    
392
	if (config->rach_delay > 68) {
393
		printf("RACH delay is too big %i\n\n", config->rach_delay);
394
		goto bad_config;
395
	}
396

    
397
	return;
398

    
399
bad_config:
400
	print_help();
401
	exit(0);
402
}
403

    
404
static int set_sched_rr(int prio)
405
{
406
	struct sched_param param;
407
	int rc;
408
	memset(&param, 0, sizeof(param));
409
	param.sched_priority = prio;
410
	printf("Setting SCHED_RR priority(%d)\n", param.sched_priority);
411
	rc = sched_setscheduler(getpid(), SCHED_RR, &param);
412
	if (rc != 0) {
413
		std::cerr << "Config: Setting SCHED_RR failed" << std::endl;
414
		return -1;
415
	}
416
	return 0;
417
}
418

    
419
int main(int argc, char *argv[])
420
{
421
	int type, chans, ref;
422
	RadioDevice *usrp;
423
	RadioInterface *radio = NULL;
424
	Transceiver *trx = NULL;
425
	RadioDevice::InterfaceType iface = RadioDevice::NORMAL;
426
	struct trx_config config;
427

    
428
#ifdef HAVE_SSE3
429
	printf("Info: SSE3 support compiled in");
430
#ifdef HAVE___BUILTIN_CPU_SUPPORTS
431
	if (__builtin_cpu_supports("sse3"))
432
		printf(" and supported by CPU\n");
433
	else
434
		printf(", but not supported by CPU\n");
435
#else
436
	printf(", but runtime SIMD detection disabled\n");
437
#endif
438
#endif
439

    
440
#ifdef HAVE_SSE4_1
441
	printf("Info: SSE4.1 support compiled in");
442
#ifdef HAVE___BUILTIN_CPU_SUPPORTS
443
	if (__builtin_cpu_supports("sse4.1"))
444
		printf(" and supported by CPU\n");
445
	else
446
		printf(", but not supported by CPU\n");
447
#else
448
	printf(", but runtime SIMD detection disabled\n");
449
#endif
450
#endif
451

    
452
	convolve_init();
453
	//convert_init();
454

    
455
	handle_options(argc, argv, &config);
456

    
457
	if (config.sched_rr != -1) {
458
		if (set_sched_rr(config.sched_rr) < 0)
459
			return EXIT_FAILURE;
460
	}
461

    
462
	setup_signal_handlers();
463

    
464
	/* Check database sanity */
465
	if (!trx_setup_config(&config)) {
466
		std::cerr << "Config: Database failure - exiting" << std::endl;
467
		return EXIT_FAILURE;
468
	}
469

    
470
	gLogInit("transceiver", config.log_level.c_str(), LOG_LOCAL7);
471

    
472
	srandom(time(NULL));
473

    
474
	/* Create the low level device object */
475
	if (config.mcbts)
476
		iface = RadioDevice::MULTI_ARFCN;
477

    
478
	if (config.extref)
479
		ref = RadioDevice::REF_EXTERNAL;
480
	else if (config.gpsref)
481
		ref = RadioDevice::REF_GPS;
482
	else
483
		ref = RadioDevice::REF_INTERNAL;
484

    
485
	usrp = RadioDevice::make(config.tx_sps, config.rx_sps, iface,
486
				 config.chans, config.offset);
487
	type = usrp->open(config.dev_args, ref, config.swap_channels);
488
	if (type < 0) {
489
		LOG(ALERT) << "Failed to create radio device" << std::endl;
490
		goto shutdown;
491
	}
492

    
493
	/* Setup the appropriate device interface */
494
	radio = makeRadioInterface(&config, usrp, type);
495
	if (!radio)
496
		goto shutdown;
497

    
498
	/* Create the transceiver core */
499
	trx = makeTransceiver(&config, radio);
500
	if (!trx)
501
		goto shutdown;
502

    
503
	chans = trx->numChans();
504
	std::cout << "-- Transceiver active with "
505
		  << chans << " channel(s)" << std::endl;
506

    
507
	while (!gshutdown)
508
		sleep(1);
509

    
510
shutdown:
511
	std::cout << "Shutting down transceiver..." << std::endl;
512

    
513
	delete trx;
514
	delete radio;
515
	delete usrp;
516

    
517
	return 0;
518
}
(1-1/2)
Add picture from clipboard (Maximum size: 48.8 MB)