OpenBTS-UMTS/TransceiverUHD/runTransceiver.cpp

224 lines
5.6 KiB
C++

/*
* OpenBTS provides an open source alternative to legacy telco protocols and
* traditionally complex, proprietary hardware systems.
*
* Copyright 2008, 2009 Free Software Foundation, Inc.
* Copyright 2010 Kestrel Signal Processing, Inc.
* Copyright 2014 Range Networks, Inc.
*
* This software is distributed under the terms of the GNU General Public
* License version 3. See the COPYING and NOTICE files in the current
* directory for licensing information.
*
* This use of this software may be subject to additional restrictions.
* See the LEGAL file in the main directory for details.
*/
#include <stdlib.h>
#include <time.h>
#include <signal.h>
#include <Logger.h>
#include <UMTSCommon.h>
#include <Configuration.h>
#include "Transceiver.h"
#include "UHDDevice.h"
/* Default maximum expected delay spread in symbols */
#define DEFAULT_MAX_DELAY 50
/* Sample rate for all devices */
#define DEVICE_RATE 6.25e6
ConfigurationKeyMap getConfigurationKeys2();
ConfigurationTable gConfig("/etc/OpenBTS/OpenBTS-UMTS.db",
"transceiver", getConfigurationKeys2());
volatile bool gbShutdown = false;
static void shutdown_handler(int signo)
{
std::cout << std::endl << "** Received shutdown signal" << std::endl;
gbShutdown = true;
}
static void register_signal_handlers()
{
if (signal(SIGINT, shutdown_handler) == SIG_ERR) {
std::cerr << "** Failed to install SIGINT signal handler" << std::endl;
exit(1);
}
if (signal(SIGTERM, shutdown_handler) == SIG_ERR) {
std::cerr << "** Failed to install SIGTERM signal handler" << std::endl;
exit(1);
}
}
/* Logging check in the configuration is mandatory */
static bool init_config()
{
try {
std::cout << "** Configuring logger" << std::endl;
gLogInit("transceiver", gConfig.getStr("Log.Level").c_str(), LOG_LOCAL7);
} catch (ConfigurationTableKeyNotFound e) {
LOG(EMERG) << "** Required configuration parameter " << e.key()
<< " not defined, aborting";
return false;
}
return true;
}
/* Optional expected delay spread (default 50 symbols) */
static int init_max_delay()
{
int max_delay;
try {
max_delay = gConfig.getNum("UMTS.Radio.MaxExpectedDelaySpread");
} catch (ConfigurationTableKeyNotFound e) {
max_delay = DEFAULT_MAX_DELAY;
}
return max_delay;
}
/* Optional external reference enable (default off) */
static bool init_extref()
{
int enable;
try {
enable = gConfig.getNum("TRX.Reference");
} catch (ConfigurationTableKeyNotFound e) {
enable = 0;
}
return enable != 0;
}
/* Optional device hint (default none) */
static std::string init_devaddr()
{
std::string addr;
try {
addr = gConfig.getNum("UMTS.Radio.UHD.DeviceAddress");
} catch (ConfigurationTableKeyNotFound e) {
addr = "";
}
return addr;
}
int main(int argc, char *argv[])
{
UHDDevice *usrp = NULL;
RadioDevice *dev = NULL;
Transceiver *trx = NULL;
RadioInterface *radio = NULL;
int max_delay;
bool found, extref;
std::string devaddr;
/* Capture termination signals */
register_signal_handlers();
/* Fail if we don't have logging */
if (!init_config())
goto shutdown;
/* Optional parameters */
max_delay = init_max_delay();
extref = init_extref();
devaddr = init_devaddr();
srandom(time(NULL));
if (extref)
std::cout << "** Using external clock reference" << std::endl;
else
std::cout << "** Using internal clock reference" << std::endl;
std::cout << "** Searching for USRP device " << devaddr << std::endl;
usrp = new UHDDevice(DEVICE_RATE);
found = usrp->open(devaddr, extref);
if (found) {
std::cout << "** Device ready" << std::endl;
dev = (RadioDevice *) usrp;
} else {
std::cout << "** Device not available" << std::endl;
goto shutdown;
}
radio = new RadioInterface(dev, 0);
if (!radio->init()) {
std::cout << "** Radio failed to initialize" << std::endl;
goto shutdown;
}
trx = new Transceiver(5700, "127.0.0.1", UMTS::Time(4, 0), radio);
trx->receiveFIFO(radio->receiveFIFO());
trx->init(max_delay);
while (!gbShutdown)
sleep(1);
shutdown:
delete trx;
delete radio;
delete usrp;
return 0;
}
ConfigurationKeyMap getConfigurationKeys2()
{
extern ConfigurationKeyMap getConfigurationKeys();
ConfigurationKeyMap map = getConfigurationKeys();
ConfigurationKey *tmp;
tmp = new ConfigurationKey("TRX.RadioFrequencyOffset","128",
"~170Hz steps",
ConfigurationKey::FACTORY,
ConfigurationKey::VALRANGE,
"96:160",// educated guess
true,
"Fine-tuning adjustment for the transceiver master clock. "
"Roughly 170 Hz/step. "
"Set at the factory. "
"Do not adjust without proper calibration."
);
map[tmp->getName()] = *tmp;
delete tmp;
tmp = new ConfigurationKey("TRX.TxAttenOffset","0",
"dB of attenuation",
ConfigurationKey::FACTORY,
ConfigurationKey::VALRANGE,
"0:100",// educated guess
true,
"Hardware-specific gain adjustment for transmitter, matched to the power amplifier, expessed as an attenuationi in dB. "
"Set at the factory. "
"Do not adjust without proper calibration."
);
map[tmp->getName()] = *tmp;
delete tmp;
tmp = new ConfigurationKey("TRX.RadioNumber","0",
"",
ConfigurationKey::FACTORY,
ConfigurationKey::VALRANGE,
"0:9", // Not likely to have 10 radios on the same computer. Not likely to have >1
true,
"If non-0, use multiple radios on the same cpu, numbered 1-9. Must change TRX.Port also. Provide a separate config file for each OpenBTS+Radio combination using the environment variable or --config command line option."
);
map[tmp->getName()] = *tmp;
delete(tmp);
return map;
}