aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--CommonLibs/Logger.h3
-rw-r--r--CommonLibs/debug.c24
-rw-r--r--CommonLibs/debug.h5
-rw-r--r--CommonLibs/trx_vty.c152
-rw-r--r--CommonLibs/trx_vty.h4
-rw-r--r--Transceiver52M/Transceiver.cpp72
-rw-r--r--Transceiver52M/device/common/smpl_buf.cpp6
-rw-r--r--Transceiver52M/device/common/smpl_buf.h2
-rw-r--r--Transceiver52M/device/lms/LMSDevice.cpp180
-rw-r--r--Transceiver52M/device/lms/LMSDevice.h13
-rw-r--r--Transceiver52M/device/uhd/UHDDevice.cpp75
-rw-r--r--Transceiver52M/device/uhd/UHDDevice.h2
-rw-r--r--Transceiver52M/device/usrp1/USRPDevice.cpp4
-rw-r--r--Transceiver52M/device/usrp1/USRPDevice.h2
-rw-r--r--Transceiver52M/osmo-trx.cpp13
-rw-r--r--Transceiver52M/radioInterface.h8
-rw-r--r--Transceiver52M/radioInterfaceMulti.cpp73
-rw-r--r--configure.ac6
-rw-r--r--debian/changelog52
-rw-r--r--debian/control2
-rw-r--r--debian/patches/build-for-debian8.patch2
-rw-r--r--doc/manuals/chapters/configuration.adoc9
-rw-r--r--doc/manuals/vty/trx_vty_reference.xml181
23 files changed, 627 insertions, 263 deletions
diff --git a/CommonLibs/Logger.h b/CommonLibs/Logger.h
index ab72303..b752e51 100644
--- a/CommonLibs/Logger.h
+++ b/CommonLibs/Logger.h
@@ -58,6 +58,9 @@ extern "C" {
#define LOGLV(category, level) \
Log(category, level, __BASE_FILE__, __LINE__).get() << "[tid=" << pthread_self() << "] "
+#define LOGSRC(category, level, file, line) \
+ Log(category, level, file, line).get() << "[tid=" << pthread_self() << "] "
+
#define LOGCHAN(chan, category, level) \
Log(category, LOGL_##level, __BASE_FILE__, __LINE__).get() << "[tid=" << pthread_self() << "][chan=" << chan << "] "
diff --git a/CommonLibs/debug.c b/CommonLibs/debug.c
index 09dab2b..c227435 100644
--- a/CommonLibs/debug.c
+++ b/CommonLibs/debug.c
@@ -35,21 +35,39 @@ static const struct log_info_cat default_categories[] = {
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
+ [DTRXCLK] = {
+ .name = "DTRXCLK",
+ .description = "TRX Master Clock",
+ .color = NULL,
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
[DTRXCTRL] = {
.name = "DTRXCTRL",
.description = "TRX CTRL interface",
.color = "\033[1;33m",
.enabled = 1, .loglevel = LOGL_NOTICE,
},
+ [DTRXDDL] = {
+ .name = "DTRXDDL",
+ .description = "TRX Data interface Downlink",
+ .color = NULL,
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
+ [DTRXDUL] = {
+ .name = "DTRXDUL",
+ .description = "TRX CTRL interface Uplink",
+ .color = NULL,
+ .enabled = 1, .loglevel = LOGL_NOTICE,
+ },
[DDEV] = {
.name = "DDEV",
.description = "Device/Driver specific code",
.color = NULL,
.enabled = 1, .loglevel = LOGL_INFO,
},
- [DLMS] = {
- .name = "DLMS",
- .description = "Logging from within LimeSuite itself",
+ [DDEVDRV] = {
+ .name = "DDEVDRV",
+ .description = "Logging from external device driver library implementing lower level specifics",
.color = NULL,
.enabled = 1, .loglevel = LOGL_NOTICE,
},
diff --git a/CommonLibs/debug.h b/CommonLibs/debug.h
index ad12bb8..0dca2ee 100644
--- a/CommonLibs/debug.h
+++ b/CommonLibs/debug.h
@@ -10,9 +10,12 @@ extern const struct log_info log_info;
/* Debug Areas of the code */
enum {
DMAIN,
+ DTRXCLK,
DTRXCTRL,
+ DTRXDDL,
+ DTRXDUL,
DDEV,
- DLMS,
+ DDEVDRV,
};
#define CLOGC(category, level, fmt, args...) do { \
diff --git a/CommonLibs/trx_vty.c b/CommonLibs/trx_vty.c
index 2c7ecc2..3f875f5 100644
--- a/CommonLibs/trx_vty.c
+++ b/CommonLibs/trx_vty.c
@@ -32,6 +32,7 @@
#include <osmocom/core/rate_ctr.h>
#include <osmocom/vty/command.h>
+#include <osmocom/vty/logging.h>
#include <osmocom/vty/vty.h>
#include <osmocom/vty/misc.h>
@@ -41,22 +42,32 @@
static struct trx_ctx* g_trx_ctx;
-static const struct value_string clock_ref_names[] = {
+const struct value_string clock_ref_names[] = {
{ REF_INTERNAL, "internal" },
{ REF_EXTERNAL, "external" },
{ REF_GPS, "gpsdo" },
{ 0, NULL }
};
-static const struct value_string filler_names[] = {
- { FILLER_DUMMY, "Dummy bursts" },
- { FILLER_ZERO, "Disabled" },
- { FILLER_NORM_RAND, "Normal bursts with random payload" },
- { FILLER_EDGE_RAND, "EDGE bursts with random payload" },
- { FILLER_ACCESS_RAND, "Access bursts with random payload" },
+const struct value_string filler_names[] = {
+ { FILLER_DUMMY, "Dummy bursts (C0 only)" },
+ { FILLER_ZERO, "Empty bursts" },
+ { FILLER_NORM_RAND, "GMSK Normal Bursts with random payload" },
+ { FILLER_EDGE_RAND, "8-PSK Normal Bursts with random payload" },
+ { FILLER_ACCESS_RAND, "Access Bursts with random payload" },
{ 0, NULL }
};
+static const struct value_string filler_types[] = {
+ { FILLER_DUMMY, "dummy" },
+ { FILLER_ZERO, "zero" },
+ { FILLER_NORM_RAND, "random-nb-gmsk" },
+ { FILLER_EDGE_RAND, "random-nb-8psk" },
+ { FILLER_ACCESS_RAND, "random-ab" },
+ { 0, NULL }
+};
+
+
struct trx_ctx *trx_from_vty(struct vty *v)
{
/* It can't hurt to force callers to continue to pass the vty instance
@@ -172,53 +183,6 @@ DEFUN(cfg_rx_sps, cfg_rx_sps_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_test_rtsc, cfg_test_rtsc_cmd,
- "test rtsc <0-7>",
- "Set the Random Normal Burst test mode with TSC\n"
- "TSC\n")
-{
- struct trx_ctx *trx = trx_from_vty(vty);
-
- if (trx->cfg.rach_delay_set) {
- vty_out(vty, "rach-delay and rtsc options are mutual-exclusive%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- trx->cfg.rtsc_set = true;
- trx->cfg.rtsc = atoi(argv[0]);
- if (!trx->cfg.egprs) /* Don't override egprs which sets different filler */
- trx->cfg.filler = FILLER_NORM_RAND;
-
- return CMD_SUCCESS;
-}
-
-DEFUN(cfg_test_rach_delay, cfg_test_rach_delay_cmd,
- "test rach-delay <0-68>",
- "Set the Random Access Burst test mode with delay\n"
- "RACH delay\n")
-{
- struct trx_ctx *trx = trx_from_vty(vty);
-
- if (trx->cfg.rtsc_set) {
- vty_out(vty, "rach-delay and rtsc options are mutual-exclusive%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- if (trx->cfg.egprs) {
- vty_out(vty, "rach-delay and egprs options are mutual-exclusive%s",
- VTY_NEWLINE);
- return CMD_WARNING;
- }
-
- trx->cfg.rach_delay_set = true;
- trx->cfg.rach_delay = atoi(argv[0]);
- trx->cfg.filler = FILLER_ACCESS_RAND;
-
- return CMD_SUCCESS;
-}
-
DEFUN(cfg_clock_ref, cfg_clock_ref_cmd,
"clock-ref (internal|external|gpsdo)",
"Set the Reference Clock\n"
@@ -351,14 +315,57 @@ DEFUN(cfg_stack_size, cfg_stack_size_cmd,
return CMD_SUCCESS;
}
-DEFUN(cfg_filler, cfg_filler_cmd,
- "filler dummy",
- "Enable C0 filler table\n"
- "Dummy method\n")
+DEFUN(cfg_filler, cfg_filler_type_cmd,
+ "filler type (zero|dummy|random-nb-gmsk|random-nb-8psk|random-ab)",
+ "Filler burst settings\n"
+ "Filler burst type (default=zero)\n"
+ "Send an empty burst when there is nothing to send (default)\n"
+ "Send a dummy burst when there is nothing to send on C0 (TRX0) and empty burst on other channels."
+ " Use for OpenBTS compatibility only, don't use with OsmoBTS as it breaks encryption.\n"
+ "Send a GMSK modulated Normal Burst with random bits when there is nothing to send."
+ " Use for spectrum mask testing. Configure 'filler tsc' to set training sequence.\n"
+ "Send an 8-PSK modulated Normal Burst with random bits when there is nothing to send."
+ " Use for spectrum mask testing. Configure 'filler tsc' to set training sequence.\n"
+ "Send an Access Burst with random bits when there is nothing to send. Use for Rx/Tx alignment."
+ " Configure 'filler access-burst-delay' to introduce artificial delay.\n"
+)
{
struct trx_ctx *trx = trx_from_vty(vty);
+ // trx->cfg.filler is unsigned, so we need an interim int var to detect errors
+ int type = get_string_value(filler_types, argv[0]);
- trx->cfg.filler = FILLER_DUMMY;
+ if (type < 0) {
+ trx->cfg.filler = FILLER_ZERO;
+ return CMD_WARNING;
+ }
+ trx->cfg.filler = type;
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_test_rtsc, cfg_filler_tsc_cmd,
+ "filler tsc <0-7>",
+ "Filler burst settings\n"
+ "Set the TSC for GMSK/8-PSK Normal Burst random fillers. Used only with 'random-nb-gmsk' and"
+ " 'random-nb-8psk' filler types. (default=0)\n"
+ "TSC\n")
+{
+ struct trx_ctx *trx = trx_from_vty(vty);
+
+ trx->cfg.rtsc = atoi(argv[0]);
+
+ return CMD_SUCCESS;
+}
+
+DEFUN(cfg_test_rach_delay, cfg_filler_rach_delay_cmd,
+ "filler access-burst-delay <0-68>",
+ "Filler burst settings\n"
+ "Set the delay for Access Burst random fillers. Used only with 'random-ab' filler type. (default=0)\n"
+ "RACH delay in symbols\n")
+{
+ struct trx_ctx *trx = trx_from_vty(vty);
+
+ trx->cfg.rach_delay = atoi(argv[0]);
return CMD_SUCCESS;
}
@@ -546,10 +553,6 @@ static int config_write_trx(struct vty *vty)
vty_out(vty, " tx-sps %u%s", trx->cfg.tx_sps, VTY_NEWLINE);
if (trx->cfg.rx_sps != DEFAULT_RX_SPS)
vty_out(vty, " rx-sps %u%s", trx->cfg.rx_sps, VTY_NEWLINE);
- if (trx->cfg.rtsc_set)
- vty_out(vty, " test rtsc %u%s", trx->cfg.rtsc, VTY_NEWLINE);
- if (trx->cfg.rach_delay_set)
- vty_out(vty, " test rach-delay %u%s", trx->cfg.rach_delay, VTY_NEWLINE);
if (trx->cfg.clock_ref != REF_INTERNAL)
vty_out(vty, " clock-ref %s%s", get_value_string(clock_ref_names, trx->cfg.clock_ref), VTY_NEWLINE);
vty_out(vty, " multi-arfcn %s%s", trx->cfg.multi_arfcn ? "enable" : "disable", VTY_NEWLINE);
@@ -562,6 +565,12 @@ static int config_write_trx(struct vty *vty)
vty_out(vty, " ext-rach %s%s", trx->cfg.ext_rach ? "enable" : "disable", VTY_NEWLINE);
if (trx->cfg.sched_rr != 0)
vty_out(vty, " rt-prio %u%s", trx->cfg.sched_rr, VTY_NEWLINE);
+ if (trx->cfg.filler != FILLER_ZERO)
+ vty_out(vty, " filler type %s%s", get_value_string(filler_types, trx->cfg.filler), VTY_NEWLINE);
+ if (trx->cfg.rtsc > 0)
+ vty_out(vty, " filler tsc %u%s", trx->cfg.rtsc, VTY_NEWLINE);
+ if (trx->cfg.rach_delay > 0)
+ vty_out(vty, " filler access-burst-delay %u%s", trx->cfg.rach_delay, VTY_NEWLINE);
if (trx->cfg.stack_size != 0)
vty_out(vty, " stack-size %u%s", trx->cfg.stack_size, VTY_NEWLINE);
trx_rate_ctr_threshold_write_config(vty, " ");
@@ -589,11 +598,9 @@ static void trx_dump_vty(struct vty *vty, struct trx_ctx *trx)
vty_out(vty, " Device args: %s%s", trx->cfg.dev_args, VTY_NEWLINE);
vty_out(vty, " Tx Samples-per-Symbol: %u%s", trx->cfg.tx_sps, VTY_NEWLINE);
vty_out(vty, " Rx Samples-per-Symbol: %u%s", trx->cfg.rx_sps, VTY_NEWLINE);
- vty_out(vty, " Test Mode: TSC: %u (%s)%s", trx->cfg.rtsc,
- trx->cfg.rtsc_set ? "Enabled" : "Disabled", VTY_NEWLINE);
- vty_out(vty, " Test Mode: RACH Delay: %u (%s)%s", trx->cfg.rach_delay,
- trx->cfg.rach_delay_set ? "Enabled" : "Disabled", VTY_NEWLINE);
- vty_out(vty, " C0 Filler Table: %s%s", get_value_string(filler_names, trx->cfg.filler), VTY_NEWLINE);
+ vty_out(vty, " Filler Burst Type: %s%s", get_value_string(filler_names, trx->cfg.filler), VTY_NEWLINE);
+ vty_out(vty, " Filler Burst TSC: %u%s", trx->cfg.rtsc, VTY_NEWLINE);
+ vty_out(vty, " Filler Burst RACH Delay: %u%s", trx->cfg.rach_delay, VTY_NEWLINE);
vty_out(vty, " Clock Reference: %s%s", get_value_string(clock_ref_names, trx->cfg.clock_ref), VTY_NEWLINE);
vty_out(vty, " Multi-Carrier: %s%s", trx->cfg.multi_arfcn ? "Enabled" : "Disabled", VTY_NEWLINE);
vty_out(vty, " Tuning offset: %f%s", trx->cfg.offset, VTY_NEWLINE);
@@ -662,6 +669,7 @@ static int trx_vty_go_parent(struct vty *vty)
static const char trx_copyright[] =
"Copyright (C) 2007-2014 Free Software Foundation, Inc.\r\n"
"Copyright (C) 2013 Thomas Tsou <tom@tsou.cc>\r\n"
+ "Copyright (C) 2013-2019 Fairwaves, Inc.\r\n"
"Copyright (C) 2015 Ettus Research LLC\r\n"
"Copyright (C) 2017-2018 by sysmocom s.f.m.c. GmbH <info@sysmocom.de>\r\n"
"License AGPLv3+: GNU AGPL version 3 or later <http://gnu.org/licenses/agpl-3.0.html>\r\n"
@@ -704,8 +712,6 @@ int trx_vty_init(struct trx_ctx* trx)
install_element(TRX_NODE, &cfg_dev_args_cmd);
install_element(TRX_NODE, &cfg_tx_sps_cmd);
install_element(TRX_NODE, &cfg_rx_sps_cmd);
- install_element(TRX_NODE, &cfg_test_rtsc_cmd);
- install_element(TRX_NODE, &cfg_test_rach_delay_cmd);
install_element(TRX_NODE, &cfg_clock_ref_cmd);
install_element(TRX_NODE, &cfg_multi_arfcn_cmd);
install_element(TRX_NODE, &cfg_offset_cmd);
@@ -714,7 +720,9 @@ int trx_vty_init(struct trx_ctx* trx)
install_element(TRX_NODE, &cfg_egprs_cmd);
install_element(TRX_NODE, &cfg_ext_rach_cmd);
install_element(TRX_NODE, &cfg_rt_prio_cmd);
- install_element(TRX_NODE, &cfg_filler_cmd);
+ install_element(TRX_NODE, &cfg_filler_type_cmd);
+ install_element(TRX_NODE, &cfg_filler_tsc_cmd);
+ install_element(TRX_NODE, &cfg_filler_rach_delay_cmd);
install_element(TRX_NODE, &cfg_ctr_error_threshold_cmd);
install_element(TRX_NODE, &cfg_no_ctr_error_threshold_cmd);
install_element(TRX_NODE, &cfg_stack_size_cmd);
@@ -724,5 +732,7 @@ int trx_vty_init(struct trx_ctx* trx)
install_element(CHAN_NODE, &cfg_chan_rx_path_cmd);
install_element(CHAN_NODE, &cfg_chan_tx_path_cmd);
+ logging_vty_add_deprecated_subsys(g_trx_ctx, "lms");
+
return 0;
}
diff --git a/CommonLibs/trx_vty.h b/CommonLibs/trx_vty.h
index d939051..c0d54cf 100644
--- a/CommonLibs/trx_vty.h
+++ b/CommonLibs/trx_vty.h
@@ -5,6 +5,8 @@
#include "config_defs.h"
extern struct vty_app_info g_vty_info;
+extern const struct value_string clock_ref_names[];
+extern const struct value_string filler_names[];
/* Maximum number of physical RF channels */
#define TRX_CHAN_MAX 8
@@ -51,9 +53,7 @@ struct trx_ctx {
unsigned int tx_sps;
unsigned int rx_sps;
unsigned int rtsc;
- bool rtsc_set;
unsigned int rach_delay;
- bool rach_delay_set;
enum ReferenceType clock_ref;
enum FillerType filler;
bool multi_arfcn;
diff --git a/Transceiver52M/Transceiver.cpp b/Transceiver52M/Transceiver.cpp
index 9697bb3..dc218d7 100644
--- a/Transceiver52M/Transceiver.cpp
+++ b/Transceiver52M/Transceiver.cpp
@@ -180,12 +180,12 @@ bool Transceiver::init(FillerType filler, size_t rtsc, unsigned rach_delay,
int d_srcport, d_dstport, c_srcport, c_dstport;
if (!mChans) {
- LOG(ALERT) << "No channels assigned";
+ LOG(FATAL) << "No channels assigned";
return false;
}
if (!sigProcLibSetup()) {
- LOG(ALERT) << "Failed to initialize signal processing library";
+ LOG(FATAL) << "Failed to initialize signal processing library";
return false;
}
@@ -285,7 +285,7 @@ bool Transceiver::start()
mLatencyUpdateTime = time;
if (!mRadioInterface->start()) {
- LOG(ALERT) << "Device failed to start";
+ LOG(FATAL) << "Device failed to start";
return false;
}
@@ -371,12 +371,12 @@ void Transceiver::addRadioVector(size_t chan, BitVector &bits,
radioVector *radio_burst;
if (chan >= mTxPriorityQueues.size()) {
- LOG(ALERT) << "Invalid channel " << chan;
+ LOGCHAN(chan, DTRXDDL, FATAL) << "Invalid channel";
return;
}
if (wTime.TN() > 7) {
- LOG(ALERT) << "Received burst with invalid slot " << wTime.TN();
+ LOGCHAN(chan, DTRXDDL, FATAL) << "Received burst with invalid slot " << wTime.TN();
return;
}
@@ -419,7 +419,7 @@ void Transceiver::pushRadioVector(GSM::Time &nowTime)
state = &mStates[i];
while ((burst = mTxPriorityQueues[i].getStaleBurst(nowTime))) {
- LOGCHAN(i, DMAIN, NOTICE) << "dumping STALE burst in TRX->SDR interface ("
+ LOGCHAN(i, DTRXDDL, NOTICE) << "dumping STALE burst in TRX->SDR interface ("
<< burst->getTime() <<" vs " << nowTime << "), retrans=" << state->mRetrans;
if (state->mRetrans)
updateFillerTable(i, burst);
@@ -606,7 +606,7 @@ int Transceiver::pullRadioVector(size_t chan, struct trx_ul_burst_ind *bi)
/* Blocking FIFO read */
radioVector *radio_burst = mReceiveFIFO[chan]->read();
if (!radio_burst) {
- LOGCHAN(chan, DMAIN, ERROR) << "ReceiveFIFO->read() returned no burst";
+ LOGCHAN(chan, DTRXDUL, ERROR) << "ReceiveFIFO->read() returned no burst";
return -EIO;
}
@@ -651,7 +651,7 @@ int Transceiver::pullRadioVector(size_t chan, struct trx_ul_burst_ind *bi)
}
if (max_i < 0) {
- LOG(ALERT) << "Received empty burst";
+ LOGCHAN(chan, DTRXDUL, FATAL) << "Received empty burst";
goto ret_idle;
}
@@ -678,9 +678,9 @@ int Transceiver::pullRadioVector(size_t chan, struct trx_ul_burst_ind *bi)
rc = detectAnyBurst(*burst, mTSC, BURST_THRESH, mSPSRx, type, max_toa, &ebp);
if (rc <= 0) {
if (rc == -SIGERR_CLIP)
- LOG(WARNING) << "Clipping detected on received RACH or Normal Burst";
+ LOGCHAN(chan, DTRXDUL, NOTICE) << "Clipping detected on received RACH or Normal Burst";
else if (rc != SIGERR_NONE)
- LOG(WARNING) << "Unhandled RACH or Normal Burst detection error";
+ LOGCHAN(chan, DTRXDUL, NOTICE) << "Unhandled RACH or Normal Burst detection error";
goto ret_idle;
}
@@ -760,7 +760,7 @@ bool Transceiver::driveControl(size_t chan)
/* Attempt to read from control socket */
msgLen = read(mCtrlSockets[chan], buffer, MAX_PACKET_LENGTH);
if (msgLen <= 0) {
- LOGCHAN(chan, DTRXCTRL, WARNING) << "mCtrlSockets read(" << mCtrlSockets[chan] << ") failed: " << msgLen;
+ LOGCHAN(chan, DTRXCTRL, NOTICE) << "mCtrlSockets read(" << mCtrlSockets[chan] << ") failed: " << msgLen;
return false;
}
@@ -769,7 +769,7 @@ bool Transceiver::driveControl(size_t chan)
/* Verify a command signature */
if (strncmp(buffer, "CMD ", 4)) {
- LOGC(DTRXCTRL, WARNING) << "bogus message on control interface";
+ LOGCHAN(chan, DTRXCTRL, NOTICE) << "bogus message on control interface";
return false;
}
@@ -794,7 +794,7 @@ bool Transceiver::driveControl(size_t chan)
unsigned ts = 0, ss = 0;
sscanf(params, "%u %u", &ts, &ss);
if (ts > 7 || ss > 7) {
- sprintf(response, "RSP NOHANDOVER 1 %u %u", ts, ss);
+ sprintf(response, "RSP HANDOVER 1 %u %u", ts, ss);
} else {
mHandover[ts][ss] = true;
sprintf(response, "RSP HANDOVER 0 %u %u", ts, ss);
@@ -854,7 +854,7 @@ bool Transceiver::driveControl(size_t chan)
sscanf(params, "%d", &freqKhz);
mRxFreq = freqKhz * 1e3;
if (!mRadioInterface->tuneRx(mRxFreq, chan)) {
- LOGC(DTRXCTRL, ALERT) << "RX failed to tune";
+ LOGCHAN(chan, DTRXCTRL, FATAL) << "RX failed to tune";
sprintf(response,"RSP RXTUNE 1 %d",freqKhz);
}
else
@@ -865,7 +865,7 @@ bool Transceiver::driveControl(size_t chan)
sscanf(params, "%d", &freqKhz);
mTxFreq = freqKhz * 1e3;
if (!mRadioInterface->tuneTx(mTxFreq, chan)) {
- LOGC(DTRXCTRL, ALERT) << "TX failed to tune";
+ LOGCHAN(chan, DTRXCTRL, FATAL) << "TX failed to tune";
sprintf(response,"RSP TXTUNE 1 %d",freqKhz);
}
else
@@ -887,7 +887,7 @@ bool Transceiver::driveControl(size_t chan)
int timeslot;
sscanf(params, "%d %d", &timeslot, &corrCode);
if ((timeslot < 0) || (timeslot > 7)) {
- LOGC(DTRXCTRL, WARNING) << "bogus message on control interface";
+ LOGCHAN(chan, DTRXCTRL, NOTICE) << "bogus message on control interface";
sprintf(response,"RSP SETSLOT 1 %d %d",timeslot,corrCode);
return true;
}
@@ -916,14 +916,14 @@ bool Transceiver::driveControl(size_t chan)
mWriteBurstToDiskMask = mask;
sprintf(response,"RSP _SETBURSTTODISKMASK 0 %d",mask);
} else {
- LOGC(DTRXCTRL, WARNING) << "bogus command " << command << " on control interface.";
+ LOGCHAN(chan, DTRXCTRL, NOTICE) << "bogus command " << command << " on control interface.";
sprintf(response,"RSP ERR 1");
}
LOGCHAN(chan, DTRXCTRL, INFO) << "response is '" << response << "'";
msgLen = write(mCtrlSockets[chan], response, strlen(response) + 1);
if (msgLen <= 0) {
- LOGCHAN(chan, DTRXCTRL, WARNING) << "mCtrlSockets write(" << mCtrlSockets[chan] << ") failed: " << msgLen;
+ LOGCHAN(chan, DTRXCTRL, NOTICE) << "mCtrlSockets write(" << mCtrlSockets[chan] << ") failed: " << msgLen;
return false;
}
return true;
@@ -940,7 +940,7 @@ bool Transceiver::driveTxPriorityQueue(size_t chan)
// check data socket
msgLen = read(mDataSockets[chan], buffer, sizeof(buffer));
if (msgLen <= 0) {
- LOGCHAN(chan, DTRXCTRL, WARNING) << "mDataSockets read(" << mCtrlSockets[chan] << ") failed: " << msgLen;
+ LOGCHAN(chan, DTRXDDL, NOTICE) << "mDataSockets read(" << mCtrlSockets[chan] << ") failed: " << msgLen;
return false;
}
@@ -950,13 +950,13 @@ bool Transceiver::driveTxPriorityQueue(size_t chan)
break;
case sizeof(*dl) + EDGE_BURST_NBITS: /* EDGE burst */
if (mSPSTx != 4) {
- LOG(ERR) << "EDGE burst received but SPS is set to " << mSPSTx;
+ LOGCHAN(chan, DTRXDDL, ERROR) << "EDGE burst received but SPS is set to " << mSPSTx;
return false;
}
burstLen = EDGE_BURST_NBITS;
break;
default:
- LOG(ERR) << "badly formatted packet on GSM->TRX interface (len="<< msgLen << ")";
+ LOGCHAN(chan, DTRXDDL, ERROR) << "badly formatted packet on GSM->TRX interface (len="<< msgLen << ")";
return false;
}
@@ -972,13 +972,12 @@ bool Transceiver::driveTxPriorityQueue(size_t chan)
case 1:
break;
default:
- LOG(ERR) << "Rx TRXD message with unknown header version " << unsigned(dl->common.version);
+ LOGCHAN(chan, DTRXDDL, ERROR) << "Rx TRXD message with unknown header version " << unsigned(dl->common.version);
return false;
}
- LOG(DEBUG) << "Rx TRXD message (hdr_ver=" << unsigned(dl->common.version) << "): "
- << "fn=" << fn << ", tn=" << unsigned(dl->common.tn) << ", "
- << "burst_len=" << burstLen;
+ LOGCHAN(chan, DTRXDDL, DEBUG) << "Rx TRXD message (hdr_ver=" << unsigned(dl->common.version)
+ << "): fn=" << fn << ", tn=" << unsigned(dl->common.tn) << ", burst_len=" << burstLen;
BitVector newBurst(burstLen);
BitVector::iterator itr = newBurst.begin();
@@ -1020,7 +1019,7 @@ void Transceiver::logRxBurst(size_t chan, const struct trx_ul_burst_ind *bi)
else os << "-";
}
- LOGCHAN(chan, DMAIN, DEBUG) << std::fixed << std::right
+ LOGCHAN(chan, DTRXDUL, DEBUG) << std::fixed << std::right
<< " time: " << unsigned(bi->tn) << ":" << bi->fn
<< " RSSI: " << std::setw(5) << std::setprecision(1) << (bi->rssi - rssiOffset)
<< "dBFS/" << std::setw(6) << -bi->rssi << "dBm"
@@ -1038,7 +1037,7 @@ bool Transceiver::driveReceiveFIFO(size_t chan)
if ((rc = pullRadioVector(chan, &bi)) < 0) {
if (rc == -ENOENT) { /* timeslot off, continue processing */
- LOGCHAN(chan, DMAIN, DEBUG) << unsigned(bi.tn) << ":" << bi.fn << " timeslot is off";
+ LOGCHAN(chan, DTRXDUL, DEBUG) << unsigned(bi.tn) << ":" << bi.fn << " timeslot is off";
return true;
}
return false; /* other errors: we want to stop the process */
@@ -1075,7 +1074,7 @@ void Transceiver::driveTxFIFO()
if (mOn) {
//radioClock->wait(); // wait until clock updates
- LOG(DEBUG) << "radio clock " << radioClock->get();
+ LOGC(DTRXCLK, DEBUG) << "radio clock " << radioClock->get();
while (radioClock->get() + mTransmitLatency > mTransmitDeadlineClock) {
// if underrun, then we're not providing bursts to radio/USRP fast
// enough. Need to increase latency by one GSM frame.
@@ -1084,8 +1083,9 @@ void Transceiver::driveTxFIFO()
// only update latency at the defined frame interval
if (radioClock->get() > mLatencyUpdateTime + GSM::Time(USB_LATENCY_INTRVL)) {
mTransmitLatency = mTransmitLatency + GSM::Time(1,0);
- LOG(INFO) << "new latency: " << mTransmitLatency << " (underrun "
- << radioClock->get() << " vs " << mLatencyUpdateTime + GSM::Time(USB_LATENCY_INTRVL) << ")";
+ LOGC(DTRXCLK, INFO) << "new latency: " << mTransmitLatency << " (underrun "
+ << radioClock->get() << " vs "
+ << mLatencyUpdateTime + GSM::Time(USB_LATENCY_INTRVL) << ")";
mLatencyUpdateTime = radioClock->get();
}
}
@@ -1095,7 +1095,7 @@ void Transceiver::driveTxFIFO()
if (mTransmitLatency > mRadioInterface->minLatency()) {
if (radioClock->get() > mLatencyUpdateTime + GSM::Time(216,0)) {
mTransmitLatency.decTN();
- LOG(INFO) << "reduced latency: " << mTransmitLatency;
+ LOGC(DTRXCLK, INFO) << "reduced latency: " << mTransmitLatency;
mLatencyUpdateTime = radioClock->get();
}
}
@@ -1119,11 +1119,11 @@ bool Transceiver::writeClockInterface()
// FIXME -- This should be adaptive.
sprintf(command,"IND CLOCK %llu",(unsigned long long) (mTransmitDeadlineClock.FN()+2));
- LOG(INFO) << "ClockInterface: sending " << command;
+ LOGC(DTRXCLK, INFO) << "sending " << command;
msgLen = write(mClockSocket, command, strlen(command) + 1);
if (msgLen <= 0) {
- LOG(ERROR) << "mClockSocket write(" << mClockSocket << ") failed: " << msgLen;
+ LOGC(DTRXCLK, ERROR) << "mClockSocket write(" << mClockSocket << ") failed: " << msgLen;
return false;
}
@@ -1144,7 +1144,7 @@ void *RxUpperLoopAdapter(TrxChanThParams *params)
while (1) {
if (!trx->driveReceiveFIFO(num)) {
- LOGCHAN(num, DMAIN, FATAL) << "Something went wrong in thread " << thread_name << ", requesting stop";
+ LOGCHAN(num, DTRXDUL, FATAL) << "Something went wrong in thread " << thread_name << ", requesting stop";
osmo_signal_dispatch(SS_MAIN, S_MAIN_STOP_REQUIRED, NULL);
break;
}
@@ -1159,7 +1159,7 @@ void *RxLowerLoopAdapter(Transceiver *transceiver)
while (1) {
if (!transceiver->driveReceiveRadio()) {
- LOG(FATAL) << "Something went wrong in thread RxLower, requesting stop";
+ LOGC(DTRXDUL, FATAL) << "Something went wrong in thread RxLower, requesting stop";
osmo_signal_dispatch(SS_MAIN, S_MAIN_STOP_REQUIRED, NULL);
break;
}
@@ -1214,7 +1214,7 @@ void *TxUpperLoopAdapter(TrxChanThParams *params)
while (1) {
if (!trx->driveTxPriorityQueue(num)) {
- LOGCHAN(num, DMAIN, FATAL) << "Something went wrong in thread " << thread_name << ", requesting stop";
+ LOGCHAN(num, DTRXDDL, FATAL) << "Something went wrong in thread " << thread_name << ", requesting stop";
osmo_signal_dispatch(SS_MAIN, S_MAIN_STOP_REQUIRED, NULL);
break;
}
diff --git a/Transceiver52M/device/common/smpl_buf.cpp b/Transceiver52M/device/common/smpl_buf.cpp
index 33161bc..ceca000 100644
--- a/Transceiver52M/device/common/smpl_buf.cpp
+++ b/Transceiver52M/device/common/smpl_buf.cpp
@@ -154,7 +154,7 @@ std::string smpl_buf::str_status(TIMESTAMP timestamp) const
return ost.str();
}
-std::string smpl_buf::str_code(ssize_t code)
+std::string smpl_buf::str_code(int code)
{
switch (code) {
case ERROR_TIMESTAMP:
@@ -166,6 +166,8 @@ std::string smpl_buf::str_code(ssize_t code)
case ERROR_OVERFLOW:
return "Sample buffer: Overrun";
default:
- return "Sample buffer: Unknown error";
+ std::stringstream ss;
+ ss << "Sample buffer: Unknown error " << code;
+ return ss.str();
}
}
diff --git a/Transceiver52M/device/common/smpl_buf.h b/Transceiver52M/device/common/smpl_buf.h
index ab612de..0b49b82 100644
--- a/Transceiver52M/device/common/smpl_buf.h
+++ b/Transceiver52M/device/common/smpl_buf.h
@@ -68,7 +68,7 @@ public:
@param code an error code
@return a formatted error string
*/
- static std::string str_code(ssize_t code);
+ static std::string str_code(int code);
enum err_code {
ERROR_TIMESTAMP = -1,
diff --git a/Transceiver52M/device/lms/LMSDevice.cpp b/Transceiver52M/device/lms/LMSDevice.cpp
index b5993b8..884cc28 100644
--- a/Transceiver52M/device/lms/LMSDevice.cpp
+++ b/Transceiver52M/device/lms/LMSDevice.cpp
@@ -20,6 +20,10 @@
#include <stdint.h>
#include <string.h>
#include <stdlib.h>
+
+#include <map>
+
+#include "trx_vty.h"
#include "Logger.h"
#include "Threads.h"
#include "LMSDevice.h"
@@ -39,17 +43,74 @@ extern "C" {
using namespace std;
#define MAX_ANTENNA_LIST_SIZE 10
-#define LMS_SAMPLE_RATE GSMRATE*32
#define GSM_CARRIER_BW 270000.0 /* 270kHz */
#define LMS_MIN_BW_SUPPORTED 2.5e6 /* 2.5mHz, minimum supported by LMS */
#define LMS_CALIBRATE_BW_HZ OSMO_MAX(GSM_CARRIER_BW, LMS_MIN_BW_SUPPORTED)
#define SAMPLE_BUF_SZ (1 << 20) /* Size of Rx timestamp based Ring buffer, in bytes */
-LMSDevice::LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset,
+
+/* Device Name Prefixes as presented by LimeSuite API LMS_GetDeviceInfo(): */
+#define LMS_DEV_SDR_USB_PREFIX_NAME "LimeSDR-USB"
+#define LMS_DEV_SDR_MINI_PREFIX_NAME "LimeSDR-Mini"
+#define LMS_DEV_NET_MICRO_PREFIX_NAME "LimeNET-Micro"
+
+/* Device parameter descriptor */
+struct dev_desc {
+ /* Does LimeSuite allow switching the clock source for this device?
+ * LimeSDR-Mini does not have switches but needs soldering to select
+ * external/internal clock. Any call to LMS_SetClockFreq() will fail.
+ */
+ bool clock_src_switchable;
+ /* Does LimeSuite allow using REF_INTERNAL for this device?
+ * LimeNET-Micro does not like selecting internal clock
+ */
+ bool clock_src_int_usable;
+ /* Device specific maximum tx levels selected by phasenoise measurements, in dB */
+ double max_tx_gain;
+ /* Sample rate coef (without having TX/RX samples per symbol into account) */
+ double rate;
+ /* Sample rate coef (without having TX/RX samples per symbol into account), if multi-arfcn is enabled */
+ double rate_multiarfcn;
+ /* Coefficient multiplied by TX sample rate in order to shift Tx time */
+ double ts_offset_coef;
+ /* Coefficient multiplied by TX sample rate in order to shift Tx time, if multi-arfcn is enabled */
+ double ts_offset_coef_multiarfcn;
+ /* Device Name Prefix as presented by LimeSuite API LMS_GetDeviceInfo() */
+ std::string name_prefix;
+};
+
+static const std::map<enum lms_dev_type, struct dev_desc> dev_param_map {
+ { LMS_DEV_SDR_USB, { true, true, 73.0, GSMRATE, MCBTS_SPACING, 8.9e-5, 7.9e-5, LMS_DEV_SDR_USB_PREFIX_NAME } },
+ { LMS_DEV_SDR_MINI, { false, true, 66.0, GSMRATE, MCBTS_SPACING, 8.9e-5, 8.2e-5, LMS_DEV_SDR_MINI_PREFIX_NAME } },
+ { LMS_DEV_NET_MICRO, { true, false, 71.0, GSMRATE, MCBTS_SPACING, 8.9e-5, 7.9e-5, LMS_DEV_NET_MICRO_PREFIX_NAME } },
+ { LMS_DEV_UNKNOWN, { true, true, 73.0, GSMRATE, MCBTS_SPACING, 8.9e-5, 7.9e-5, "UNKNOWN" } },
+};
+
+static enum lms_dev_type parse_dev_type(lms_device_t *m_lms_dev)
+{
+ std::map<enum lms_dev_type, struct dev_desc>::const_iterator it = dev_param_map.begin();
+
+ const lms_dev_info_t* device_info = LMS_GetDeviceInfo(m_lms_dev);
+
+ while (it != dev_param_map.end())
+ {
+ enum lms_dev_type dev_type = it->first;
+ struct dev_desc desc = it->second;
+
+ if (strncmp(device_info->deviceName, desc.name_prefix.c_str(), desc.name_prefix.length()) == 0) {
+ LOGC(DDEV, INFO) << "Device identified as " << desc.name_prefix;
+ return dev_type;
+ }
+ it++;
+ }
+ return LMS_DEV_UNKNOWN;
+}
+
+LMSDevice::LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chan_num, double lo_offset,
const std::vector<std::string>& tx_paths,
const std::vector<std::string>& rx_paths):
- RadioDevice(tx_sps, rx_sps, iface, chans, lo_offset, tx_paths, rx_paths),
- m_lms_dev(NULL)
+ RadioDevice(tx_sps, rx_sps, iface, chan_num, lo_offset, tx_paths, rx_paths),
+ m_lms_dev(NULL), started(false), m_dev_type(LMS_DEV_UNKNOWN)
{
LOGC(DDEV, INFO) << "creating LMS device...";
@@ -59,6 +120,11 @@ LMSDevice::LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t c
tx_gains.resize(chans);
rx_buffers.resize(chans);
+
+ /* Set up per-channel Rx timestamp based Ring buffers */
+ for (size_t i = 0; i < rx_buffers.size(); i++)
+ rx_buffers[i] = new smpl_buf(SAMPLE_BUF_SZ / sizeof(uint32_t));
+
}
LMSDevice::~LMSDevice()
@@ -93,7 +159,7 @@ static void lms_log_callback(int lvl, const char *msg)
if ((unsigned int) lvl >= ARRAY_SIZE(lvl_map))
lvl = ARRAY_SIZE(lvl_map)-1;
- LOGLV(DLMS, lvl_map[lvl]) << msg;
+ LOGLV(DDEVDRV, lvl_map[lvl]) << msg;
}
static void print_range(const char* name, lms_range_t *range)
@@ -110,7 +176,7 @@ static void print_range(const char* name, lms_range_t *range)
int info_list_find(lms_info_str_t* info_list, unsigned int count, const std::string &args)
{
unsigned int i, j;
- vector<string> filters;
+ std::vector<string> filters;
filters = comma_delimited_to_vector(args.c_str());
@@ -134,11 +200,11 @@ int info_list_find(lms_info_str_t* info_list, unsigned int count, const std::str
int LMSDevice::open(const std::string &args, int ref, bool swap_channels)
{
lms_info_str_t* info_list;
- const lms_dev_info_t* device_info;
lms_range_t range_sr;
float_type sr_host, sr_rf;
unsigned int i, n;
int rc, dev_id;
+ struct dev_desc dev_desc;
LOGC(DDEV, INFO) << "Opening LMS device..";
@@ -175,19 +241,20 @@ int LMSDevice::open(const std::string &args, int ref, bool swap_channels)
delete [] info_list;
- device_info = LMS_GetDeviceInfo(m_lms_dev);
+ m_dev_type = parse_dev_type(m_lms_dev);
+ dev_desc = dev_param_map.at(m_dev_type);
if ((ref != REF_EXTERNAL) && (ref != REF_INTERNAL)){
LOGC(DDEV, ERROR) << "Invalid reference type";
goto out_close;
}
- /* if reference clock is external setup must happen _before_ calling LMS_Init */
- /* FIXME make external reference frequency configurable */
+ /* if reference clock is external, setup must happen _before_ calling LMS_Init */
if (ref == REF_EXTERNAL) {
LOGC(DDEV, INFO) << "Setting External clock reference to 10MHz";
- /* Assume an external 10 MHz reference clock */
- if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, 10000000.0) < 0)
+ /* FIXME: Assume an external 10 MHz reference clock. make
+ external reference frequency configurable */
+ if (!do_clock_src_freq(REF_EXTERNAL, 10000000.0))
goto out_close;
}
@@ -197,22 +264,13 @@ int LMSDevice::open(const std::string &args, int ref, bool swap_channels)
goto out_close;
}
- /* LimeSDR-Mini does not have switches but needs soldering to select external/internal clock */
- /* LimeNET-Micro also does not like selecting internal clock*/
- /* also set device specific maximum tx levels selected by phasenoise measurements*/
- if (strncmp(device_info->deviceName,"LimeSDR-USB",11) == 0){
- /* if reference clock is internal setup must happen _after_ calling LMS_Init */
- /* according to lms using LMS_CLOCK_EXTREF with a frequency <= 0 is the correct way to set clock to internal reference*/
- if (ref == REF_INTERNAL) {
- LOGC(DDEV, INFO) << "Setting Internal clock reference";
- if (LMS_SetClockFreq(m_lms_dev, LMS_CLOCK_EXTREF, -1) < 0)
- goto out_close;
- }
- maxTxGainClamp = 73.0;
- } else if (strncmp(device_info->deviceName,"LimeSDR-Mini",12) == 0)
- maxTxGainClamp = 66.0;
- else
- maxTxGainClamp = 71.0; /* "LimeNET-Micro", etc FIXME pciE based LMS boards?*/
+ /* if reference clock is internal, setup must happen _after_ calling LMS_Init */
+ if (ref == REF_INTERNAL) {
+ LOGC(DDEV, INFO) << "Setting Internal clock reference";
+ /* Internal freq param is not used */
+ if (!do_clock_src_freq(REF_INTERNAL, 0))
+ goto out_close;
+ }
/* enable all used channels */
for (i=0; i<chans; i++) {
@@ -227,16 +285,22 @@ int LMSDevice::open(const std::string &args, int ref, bool swap_channels)
goto out_close;
print_range("Sample Rate", &range_sr);
- LOGC(DDEV, INFO) << "Setting sample rate to " << GSMRATE*tx_sps << " " << tx_sps;
- if (LMS_SetSampleRate(m_lms_dev, GSMRATE*tx_sps, 32) < 0)
+ if (iface == MULTI_ARFCN)
+ sr_host = dev_desc.rate_multiarfcn * tx_sps;
+ else
+ sr_host = dev_desc.rate * tx_sps;
+ LOGC(DDEV, INFO) << "Setting sample rate to " << sr_host << " " << tx_sps;
+ if (LMS_SetSampleRate(m_lms_dev, sr_host, 32) < 0)
goto out_close;
if (LMS_GetSampleRate(m_lms_dev, LMS_CH_RX, 0, &sr_host, &sr_rf))
goto out_close;
LOGC(DDEV, INFO) << "Sample Rate: Host=" << sr_host << " RF=" << sr_rf;
- /* FIXME: make this device/model dependent, like UHDDevice:dev_param_map! */
- ts_offset = static_cast<TIMESTAMP>(8.9e-5 * GSMRATE * tx_sps); /* time * sample_rate */
+ if (iface == MULTI_ARFCN)
+ ts_offset = static_cast<TIMESTAMP>(dev_desc.ts_offset_coef_multiarfcn * sr_host);
+ else
+ ts_offset = static_cast<TIMESTAMP>(dev_desc.ts_offset_coef * sr_host);
/* configure antennas */
if (!set_antennas()) {
@@ -244,13 +308,7 @@ int LMSDevice::open(const std::string &args, int ref, bool swap_channels)
goto out_close;
}
- /* Set up per-channel Rx timestamp based Ring buffers */
- for (size_t i = 0; i < rx_buffers.size(); i++)
- rx_buffers[i] = new smpl_buf(SAMPLE_BUF_SZ / sizeof(uint32_t));
-
- started = false;
-
- return NORMAL;
+ return iface == MULTI_ARFCN ? MULTI_ARFCN : NORMAL;
out_close:
LOGC(DDEV, FATAL) << "Error in LMS open, closing: " << LMS_GetLastErrorMessage();
@@ -344,6 +402,43 @@ bool LMSDevice::stop()
return true;
}
+bool LMSDevice::do_clock_src_freq(enum ReferenceType ref, double freq)
+{
+ struct dev_desc dev_desc = dev_param_map.at(m_dev_type);
+ size_t lms_clk_id;
+
+ switch (ref) {
+ case REF_EXTERNAL:
+ lms_clk_id = LMS_CLOCK_EXTREF;
+ break;
+ case REF_INTERNAL:
+ if (!dev_desc.clock_src_int_usable) {
+ LOGC(DDEV, ERROR) << "Device type " << dev_desc.name_prefix
+ << " doesn't support internal reference clock";
+ return false;
+ }
+ /* According to lms using LMS_CLOCK_EXTREF with a
+ frequency <= 0 is the correct way to set clock to
+ internal reference */
+ lms_clk_id = LMS_CLOCK_EXTREF;
+ freq = -1;
+ break;
+ default:
+ LOGC(DDEV, ERROR) << "Invalid reference type " << get_value_string(clock_ref_names, ref);
+ return false;
+ }
+
+ if (dev_desc.clock_src_switchable) {
+ if (LMS_SetClockFreq(m_lms_dev, lms_clk_id, freq) < 0)
+ return false;
+ } else {
+ LOGC(DDEV, INFO) << "Device type " << dev_desc.name_prefix
+ << " doesn't support switching clock source through SW";
+ }
+
+ return true;
+}
+
/* do rx/tx calibration - depends on gain, freq and bw */
bool LMSDevice::do_calib(size_t chan)
{
@@ -385,7 +480,7 @@ bool LMSDevice::do_filters(size_t chan)
double LMSDevice::maxTxGain()
{
- return maxTxGainClamp;
+ return dev_param_map.at(m_dev_type).max_tx_gain;
}
double LMSDevice::minTxGain()
@@ -711,8 +806,9 @@ int LMSDevice::readSamples(std::vector < short *>&bufs, int len, bool * overrun,
for (size_t i = 0; i < rx_buffers.size(); i++) {
rc = rx_buffers[i]->read(bufs[i], len, timestamp);
if ((rc < 0) || (rc != len)) {
- LOGC(DDEV, ERROR) << rx_buffers[i]->str_code(rc);
- LOGC(DDEV, ERROR) << rx_buffers[i]->str_status(timestamp);
+ LOGCHAN(i, DDEV, ERROR) << rx_buffers[i]->str_code(rc) << ". "
+ << rx_buffers[i]->str_status(timestamp)
+ << ", (len=" << len << ")";
return 0;
}
}
diff --git a/Transceiver52M/device/lms/LMSDevice.h b/Transceiver52M/device/lms/LMSDevice.h
index 003d064..755f6c4 100644
--- a/Transceiver52M/device/lms/LMSDevice.h
+++ b/Transceiver52M/device/lms/LMSDevice.h
@@ -41,6 +41,13 @@
* A^2 = 1 */
#define LIMESDR_TX_AMPL 0.707
+enum lms_dev_type {
+ LMS_DEV_SDR_USB, /* LimeSDR-USB */
+ LMS_DEV_SDR_MINI, /* LimeSDR-Mini */
+ LMS_DEV_NET_MICRO, /* LimeNet-micro */
+ LMS_DEV_UNKNOWN,
+};
+
/** A class to handle a LimeSuite supported device */
class LMSDevice:public RadioDevice {
@@ -59,7 +66,8 @@ private:
TIMESTAMP ts_initial, ts_offset;
std::vector<double> tx_gains, rx_gains;
- double maxTxGainClamp;
+
+ enum lms_dev_type m_dev_type;
bool do_calib(size_t chan);
bool do_filters(size_t chan);
@@ -68,11 +76,12 @@ private:
bool flush_recv(size_t num_pkts);
void update_stream_stats_rx(size_t chan, bool *overrun);
void update_stream_stats_tx(size_t chan, bool *underrun);
+ bool do_clock_src_freq(enum ReferenceType ref, double freq);
public:
/** Object constructor */
- LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset,
+ LMSDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chan_num, double lo_offset,
const std::vector<std::string>& tx_paths,
const std::vector<std::string>& rx_paths);
~LMSDevice();
diff --git a/Transceiver52M/device/uhd/UHDDevice.cpp b/Transceiver52M/device/uhd/UHDDevice.cpp
index 604bb44..5d267c8 100644
--- a/Transceiver52M/device/uhd/UHDDevice.cpp
+++ b/Transceiver52M/device/uhd/UHDDevice.cpp
@@ -33,11 +33,12 @@
#include "config.h"
#endif
-#ifndef USE_UHD_3_11
+#ifdef USE_UHD_3_11
+#include <uhd/utils/log_add.hpp>
+#include <uhd/utils/thread.hpp>
+#else
#include <uhd/utils/msg.hpp>
#include <uhd/utils/thread_priority.hpp>
-#else
-#include <uhd/utils/thread.hpp>
#endif
#define USRP_TX_AMPL 0.3
@@ -134,23 +135,52 @@ void *async_event_loop(uhd_device *dev)
return NULL;
}
-#ifndef USE_UHD_3_11
+#ifdef USE_UHD_3_11
+static void uhd_log_handler(const uhd::log::logging_info &info)
+{
+ int level;
+
+ switch (info.verbosity)
+ {
+ case uhd::log::trace:
+ case uhd::log::debug:
+ level = LOGL_DEBUG;
+ break;
+ case uhd::log::info:
+ level = LOGL_INFO;
+ break;
+ case uhd::log::warning:
+ level = LOGL_NOTICE;
+ break;
+ case uhd::log::error:
+ level = LOGL_ERROR;
+ break;
+ case uhd::log::fatal:
+ level = LOGL_FATAL;
+ break;
+ default:
+ level = LOGL_NOTICE;
+ }
+
+ LOGSRC(DDEVDRV, level, info.file.c_str(), info.line) << "[" << info.component << "] " << info.message;
+}
+#else
/*
Catch and drop underrun 'U' and overrun 'O' messages from stdout
since we already report using the logging facility. Direct
everything else appropriately.
*/
-void uhd_msg_handler(uhd::msg::type_t type, const std::string &msg)
+static void uhd_msg_handler(uhd::msg::type_t type, const std::string &msg)
{
switch (type) {
case uhd::msg::status:
- LOGC(DDEV, INFO) << msg;
+ LOGC(DDEVDRV, INFO) << msg;
break;
case uhd::msg::warning:
- LOGC(DDEV, WARNING) << msg;
+ LOGC(DDEVDRV, NOTICE) << msg;
break;
case uhd::msg::error:
- LOGC(DDEV, ERROR) << msg;
+ LOGC(DDEVDRV, ERROR) << msg;
break;
case uhd::msg::fastpath:
break;
@@ -159,10 +189,10 @@ void uhd_msg_handler(uhd::msg::type_t type, const std::string &msg)
#endif
uhd_device::uhd_device(size_t tx_sps, size_t rx_sps,
- InterfaceType iface, size_t chans, double lo_offset,
+ InterfaceType iface, size_t chan_num, double lo_offset,
const std::vector<std::string>& tx_paths,
const std::vector<std::string>& rx_paths)
- : RadioDevice(tx_sps, rx_sps, iface, chans, lo_offset, tx_paths, rx_paths),
+ : RadioDevice(tx_sps, rx_sps, iface, chan_num, lo_offset, tx_paths, rx_paths),
tx_gain_min(0.0), tx_gain_max(0.0),
rx_gain_min(0.0), rx_gain_max(0.0),
tx_spp(0), rx_spp(0),
@@ -418,6 +448,16 @@ int uhd_device::open(const std::string &args, int ref, bool swap_channels)
{
const char *refstr;
+ /* Register msg handler. Different APIs depending on UHD version */
+#ifdef USE_UHD_3_11
+ uhd::log::add_logger("OsmoTRX", &uhd_log_handler);
+ uhd::log::set_log_level(uhd::log::debug);
+ uhd::log::set_console_level(uhd::log::off);
+ uhd::log::set_logger_level("OsmoTRX", uhd::log::debug);
+#else
+ uhd::msg::register_handler(&uhd_msg_handler);
+#endif
+
// Find UHD devices
uhd::device_addr_t addr(args);
uhd::device_addrs_t dev_addrs = uhd::device::find(addr);
@@ -526,7 +566,7 @@ int uhd_device::open(const std::string &args, int ref, bool swap_channels)
init_gains();
// Print configuration
- LOGC(DDEV, INFO) << "\n" << usrp_dev->get_pp_string();
+ LOGC(DDEV, INFO) << "Device configuration: " << usrp_dev->get_pp_string();
if (iface == MULTI_ARFCN)
return MULTI_ARFCN;
@@ -604,10 +644,6 @@ bool uhd_device::start()
return false;
}
-#ifndef USE_UHD_3_11
- // Register msg handler
- uhd::msg::register_handler(&uhd_msg_handler);
-#endif
// Start asynchronous event (underrun check) loop
async_event_thrd = new Thread();
async_event_thrd->start((void * (*)(void*))async_event_loop, (void*)this);
@@ -742,7 +778,7 @@ int uhd_device::readSamples(std::vector<short *> &bufs, int len, bool *overrun,
for (size_t i = 0; i < rx_buffers.size(); i++) {
rc = rx_buffers[i]->write((short *) &pkt_bufs[i].front(),
num_smpls,
- metadata.time_spec.to_ticks(rx_rate));
+ ts.to_ticks(rx_rate));
// Continue on local overrun, exit on other errors
if ((rc < 0)) {
@@ -883,15 +919,18 @@ bool uhd_device::set_freq(double freq, size_t chan, bool tx)
std::vector<double> freqs;
uhd::tune_result_t tres;
uhd::tune_request_t treq = select_freq(freq, chan, tx);
+ std::string str_dir;
if (tx) {
tres = usrp_dev->set_tx_freq(treq, chan);
tx_freqs[chan] = usrp_dev->get_tx_freq(chan);
+ str_dir = "Tx";
} else {
tres = usrp_dev->set_rx_freq(treq, chan);
rx_freqs[chan] = usrp_dev->get_rx_freq(chan);
+ str_dir = "Rx";
}
- LOGC(DDEV, INFO) << "\n" << tres.to_pp_string() << std::endl;
+ LOGCHAN(chan, DDEV, INFO) << "set_freq(" << freq << ", " << str_dir << "): " << tres.to_pp_string() << std::endl;
if ((chans == 1) || ((chans == 2) && dev_type == UMTRX))
return true;
@@ -911,7 +950,7 @@ bool uhd_device::set_freq(double freq, size_t chan, bool tx)
rx_freqs[!chan] = usrp_dev->get_rx_freq(!chan);
}
- LOGC(DDEV, INFO) << "\n" << tres.to_pp_string() << std::endl;
+ LOGCHAN(chan, DDEV, INFO) << "set_freq(" << freq << ", " << str_dir << "): " << tres.to_pp_string() << std::endl;
}
return true;
diff --git a/Transceiver52M/device/uhd/UHDDevice.h b/Transceiver52M/device/uhd/UHDDevice.h
index 44f7ebb..d485a8e 100644
--- a/Transceiver52M/device/uhd/UHDDevice.h
+++ b/Transceiver52M/device/uhd/UHDDevice.h
@@ -62,7 +62,7 @@ enum uhd_dev_type {
class uhd_device : public RadioDevice {
public:
uhd_device(size_t tx_sps, size_t rx_sps, InterfaceType type,
- size_t chans, double offset,
+ size_t chan_num, double offset,
const std::vector<std::string>& tx_paths,
const std::vector<std::string>& rx_paths);
~uhd_device();
diff --git a/Transceiver52M/device/usrp1/USRPDevice.cpp b/Transceiver52M/device/usrp1/USRPDevice.cpp
index 03a4f80..766a228 100644
--- a/Transceiver52M/device/usrp1/USRPDevice.cpp
+++ b/Transceiver52M/device/usrp1/USRPDevice.cpp
@@ -61,10 +61,10 @@ const dboardConfigType dboardConfig = TXA_RXB;
const double USRPDevice::masterClockRate = 52.0e6;
USRPDevice::USRPDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface,
- size_t chans, double lo_offset,
+ size_t chan_num, double lo_offset,
const std::vector<std::string>& tx_paths,
const std::vector<std::string>& rx_paths):
- RadioDevice(tx_sps, rx_sps, iface, chans, lo_offset, tx_paths, rx_paths)
+ RadioDevice(tx_sps, rx_sps, iface, chan_num, lo_offset, tx_paths, rx_paths)
{
LOGC(DDEV, INFO) << "creating USRP device...";
diff --git a/Transceiver52M/device/usrp1/USRPDevice.h b/Transceiver52M/device/usrp1/USRPDevice.h
index 6dfa5f0..47f2a43 100644
--- a/Transceiver52M/device/usrp1/USRPDevice.h
+++ b/Transceiver52M/device/usrp1/USRPDevice.h
@@ -95,7 +95,7 @@ private:
public:
/** Object constructor */
- USRPDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chans, double lo_offset,
+ USRPDevice(size_t tx_sps, size_t rx_sps, InterfaceType iface, size_t chan_num, double lo_offset,
const std::vector<std::string>& tx_paths,
const std::vector<std::string>& rx_paths);
diff --git a/Transceiver52M/osmo-trx.cpp b/Transceiver52M/osmo-trx.cpp
index 6b83988..0ad60ef 100644
--- a/Transceiver52M/osmo-trx.cpp
+++ b/Transceiver52M/osmo-trx.cpp
@@ -334,14 +334,12 @@ static void handle_options(int argc, char **argv, struct trx_ctx* trx)
break;
case 'r':
print_deprecated(option);
- trx->cfg.rtsc_set = true;
trx->cfg.rtsc = atoi(optarg);
if (!trx->cfg.egprs) /* Don't override egprs which sets different filler */
trx->cfg.filler = FILLER_NORM_RAND;
break;
case 'A':
print_deprecated(option);
- trx->cfg.rach_delay_set = true;
trx->cfg.rach_delay = atoi(optarg);
trx->cfg.filler = FILLER_ACCESS_RAND;
break;
@@ -383,6 +381,11 @@ static void handle_options(int argc, char **argv, struct trx_ctx* trx)
}
}
+ if (argc > optind) {
+ LOG(ERROR) << "Unsupported positional arguments on command line";
+ goto bad_config;
+ }
+
/* Cmd line option specific validation & setup */
if (trx->cfg.num_chans > TRX_CHAN_MAX) {
@@ -459,7 +462,9 @@ static void print_config(struct trx_ctx *trx)
ost << " EDGE support............ " << trx->cfg.egprs << std::endl;
ost << " Extended RACH support... " << trx->cfg.ext_rach << std::endl;
ost << " Reference............... " << trx->cfg.clock_ref << std::endl;
- ost << " C0 Filler Table......... " << trx->cfg.filler << std::endl;
+ ost << " Filler Burst Type....... " << get_value_string(filler_names, trx->cfg.filler) << std::endl;
+ ost << " Filler Burst TSC........ " << trx->cfg.rtsc << std::endl;
+ ost << " Filler Burst RACH Delay. " << trx->cfg.rach_delay << std::endl;
ost << " Multi-Carrier........... " << trx->cfg.multi_arfcn << std::endl;
ost << " Tuning offset........... " << trx->cfg.offset << std::endl;
ost << " RSSI to dBm offset...... " << trx->cfg.rssi_offset << std::endl;
@@ -583,10 +588,10 @@ int main(int argc, char *argv[])
log_enable_multithread();
osmo_stats_init(tall_trx_ctx);
vty_init(&g_vty_info);
+ logging_vty_add_cmds();
ctrl_vty_init(tall_trx_ctx);
trx_vty_init(g_trx_ctx);
- logging_vty_add_cmds();
osmo_talloc_vty_add_cmds();
osmo_stats_vty_add_cmds();
diff --git a/Transceiver52M/radioInterface.h b/Transceiver52M/radioInterface.h
index d9fa414..c75a983 100644
--- a/Transceiver52M/radioInterface.h
+++ b/Transceiver52M/radioInterface.h
@@ -156,16 +156,24 @@ public:
void close();
};
+struct freq_cfg_state {
+ bool set;
+ double freq_hz;
+};
+
class RadioInterfaceMulti : public RadioInterface {
private:
bool pushBuffer();
int pullBuffer();
+ bool verify_arfcn_consistency(double freq, size_t chan, bool tx);
virtual double setTxGain(double dB, size_t chan);
signalVector *outerSendBuffer;
signalVector *outerRecvBuffer;
std::vector<signalVector *> history;
std::vector<bool> active;
+ std::vector<struct freq_cfg_state> rx_freq_state;
+ std::vector<struct freq_cfg_state> tx_freq_state;
Resampler *dnsampler;
Resampler *upsampler;
diff --git a/Transceiver52M/radioInterfaceMulti.cpp b/Transceiver52M/radioInterfaceMulti.cpp
index 668305c..a0c24b5 100644
--- a/Transceiver52M/radioInterfaceMulti.cpp
+++ b/Transceiver52M/radioInterfaceMulti.cpp
@@ -73,6 +73,8 @@ void RadioInterfaceMulti::close()
powerScaling.resize(0);
history.resize(0);
active.resize(0);
+ rx_freq_state.resize(0);
+ tx_freq_state.resize(0);
RadioInterface::close();
}
@@ -148,6 +150,8 @@ bool RadioInterfaceMulti::init(int type)
mReceiveFIFO.resize(mChans);
powerScaling.resize(mChans);
history.resize(mChans);
+ rx_freq_state.resize(mChans);
+ tx_freq_state.resize(mChans);
active.resize(MCHANS, false);
inchunk = RESAMP_INRATE * 4;
@@ -362,42 +366,67 @@ static bool fltcmp(double a, double b)
return fabs(a - b) < FREQ_DELTA_LIMIT ? true : false;
}
+bool RadioInterfaceMulti::verify_arfcn_consistency(double freq, size_t chan, bool tx)
+{
+ double freq_i;
+ std::string str_dir = tx ? "Tx" : "Rx";
+ std::vector<struct freq_cfg_state> &v = tx ? tx_freq_state : rx_freq_state;
+
+ for (size_t i = 0; i < mChans; i++) {
+ if (i == chan)
+ continue;
+ if (!v[i].set)
+ continue;
+
+ freq_i = v[i].freq_hz + (double) ((int)chan - (int)i) * MCBTS_SPACING;
+ if (!fltcmp(freq, freq_i)) {
+ LOGCHAN(chan, DMAIN, ERROR)
+ << "Setting " << str_dir << " frequency " << freq
+ << " is incompatible: already configured channel "
+ << i << " uses frequency " << v[i].freq_hz
+ << " (expected " << freq_i << ")";
+ return false;
+ }
+ }
+ v[chan].set = true;
+ v[chan].freq_hz = freq;
+ return true;
+}
+
bool RadioInterfaceMulti::tuneTx(double freq, size_t chan)
{
- if (chan >= mChans)
- return false;
+ double shift;
- double shift = (double) getFreqShift(mChans);
+ if (chan >= mChans)
+ return false;
- if (!chan)
- return mDevice->setTxFreq(freq + shift * MCBTS_SPACING);
+ if (!verify_arfcn_consistency(freq, chan, true))
+ return false;
- double center = mDevice->getTxFreq();
- if (!fltcmp(freq, center + (double) (chan - shift) * MCBTS_SPACING)) {
- LOG(NOTICE) << "Channel " << chan << " RF Tx frequency offset is "
- << freq / 1e6 << " MHz";
- }
+ if (chan == 0) {
+ shift = (double) getFreqShift(mChans);
+ return mDevice->setTxFreq(freq + shift * MCBTS_SPACING);
+ }
- return true;
+ return true;
}
bool RadioInterfaceMulti::tuneRx(double freq, size_t chan)
{
- if (chan >= mChans)
- return false;
+ double shift;
- double shift = (double) getFreqShift(mChans);
+ if (chan >= mChans)
+ return false;
- if (!chan)
- return mDevice->setRxFreq(freq + shift * MCBTS_SPACING);
+ if (!verify_arfcn_consistency(freq, chan, false))
+ return false;
- double center = mDevice->getRxFreq();
- if (!fltcmp(freq, center + (double) (chan - shift) * MCBTS_SPACING)) {
- LOG(NOTICE) << "Channel " << chan << " RF Rx frequency offset is "
- << freq / 1e6 << " MHz";
- }
+ if (chan == 0) {
+ shift = (double) getFreqShift(mChans);
+ return mDevice->setRxFreq(freq + shift * MCBTS_SPACING);
+ }
- return true;
+ return true;
}
double RadioInterfaceMulti::setRxGain(double db, size_t chan)
diff --git a/configure.ac b/configure.ac
index d5463e9..b0be728 100644
--- a/configure.ac
+++ b/configure.ac
@@ -75,9 +75,9 @@ AC_TYPE_SIZE_T
AC_HEADER_TIME
AC_C_BIGENDIAN
-PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 0.12.0)
-PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 0.12.0)
-PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 0.12.0)
+PKG_CHECK_MODULES(LIBOSMOCORE, libosmocore >= 1.3.0)
+PKG_CHECK_MODULES(LIBOSMOVTY, libosmovty >= 1.3.0)
+PKG_CHECK_MODULES(LIBOSMOCTRL, libosmoctrl >= 1.3.0)
AC_ARG_ENABLE(sanitize,
[AS_HELP_STRING(
diff --git a/debian/changelog b/debian/changelog
index 96cd208..0ec7b9f 100644
--- a/debian/changelog
+++ b/debian/changelog
@@ -1,3 +1,55 @@
+osmo-trx (1.2.0) unstable; urgency=medium
+
+ [ Pau Espin Pedrol ]
+ * osmo-trx: log to stderr on signal received
+ * Drop old setPriority related code
+ * Transceiver: fix segfault during init if IP addr binding fails
+ * Transceiver: Check return value when binding IP addr for clock socket
+ * Transceiver: Clean up receival of downlink bursts
+ * Transceiver: Fix idle ul burst indications being dropped
+ * Transceiver: exit process when BTS drops connection
+ * Transceiver: Enable EDGE detection only on PDCH timeslots
+ * lms: Log available antennas if requested antenna fails
+ * device: Use LOGCHAN in set_antennas()
+ * Transceiver: Fix logging TN and version
+ * Transceiver: Use LOGCHAN in logRxBurst to unify log format
+ * Transceiver: Log error condition no burst in pullRadioVector()
+ * Transceiver: pullRadioVector(): Fix use of uninitialized value bi->tn
+ * Transceiver: Don't stop TRX if pulling from OFF timeslot
+ * radioInterface: Rename mRadio to mDevice
+ * radioInterfaceMulti: Check equals zero explicitly
+ * USRPDevice: Fix setRxGain return on error and getRxGain() returning always 0
+ * USRPDevice: Return previous txGain if setting value failed
+ * LMSDevice: Return previous txGain/rxGain if setting value failed
+ * radioInterface: Remove unusued getRxGain()
+ * radioDevice: Introduce getTxGain() API
+ * radioInterfaceMulti: Override setTxGain() to avoid chan!=0 calls
+ * UHDDevice: Drop unneeded MULTI_ARFCN checks
+ * radioInterface{Multi,Resamp}: Fix successful writeSamples() masking underrun from readSamples()
+ * radioInterface: Mark setRxGain as virtual
+ * Move multi-ARFCN chan amount modification from UHDDevice to parent class
+ * radioInterface: Atomically fetch and change underrun variable
+ * radioInterfaceMulti: write frequency offset direction (rx/tx) in log line
+ * Use new libosmocore logging lock API
+ * Transceiver: Fix wrong response upon CMD HANDOVER failure
+ * uhd: use value already cached in tmp variable
+ * Transceiver.cpp: Introduce and use new logging categories
+
+ [ Timo Jacobus ]
+ * Transceiver: Fixed copying of history into and from channelizer buffer.
+
+ [ Alexander Chemeris ]
+ * vty: Don't enable random filler bursts automatically with EDGE.
+ * vty: Simplify filler burst settings and improve help and readability.
+
+ [ Martin Hauke ]
+ * Fix common misspellings and typos
+
+ [ Harald Welte ]
+ * trx: exit() on unsupported positional arguments on command line
+
+ -- Pau Espin Pedrol <pespin@sysmocom.de> Fri, 03 Jan 2020 19:54:00 +0100
+
osmo-trx (1.1.1) unstable; urgency=medium
* UNRELEASED
diff --git a/debian/control b/debian/control
index 750f7b9..de4be16 100644
--- a/debian/control
+++ b/debian/control
@@ -14,7 +14,7 @@ Build-Depends: debhelper (>= 9),
libtalloc-dev,
libusrp-dev,
liblimesuite-dev,
- libosmocore-dev (>= 0.12.0),
+ libosmocore-dev (>= 1.3.0),
osmo-gsm-manuals-dev
Standards-Version: 3.9.6
Vcs-Browser: http://cgit.osmocom.org/osmo-trx
diff --git a/debian/patches/build-for-debian8.patch b/debian/patches/build-for-debian8.patch
index cce063c..4bf0207 100644
--- a/debian/patches/build-for-debian8.patch
+++ b/debian/patches/build-for-debian8.patch
@@ -7,7 +7,7 @@ index 8ff59f0..126c16a 100644
libtalloc-dev,
libusrp-dev,
- liblimesuite-dev,
- libosmocore-dev (>= 0.12.0),
+ libosmocore-dev (>= 1.3.0),
osmo-gsm-manuals-dev
Standards-Version: 3.9.6
@@ -30,7 +29,7 @@ Package: osmo-trx-dbg
diff --git a/doc/manuals/chapters/configuration.adoc b/doc/manuals/chapters/configuration.adoc
index 2f4986f..a194537 100644
--- a/doc/manuals/chapters/configuration.adoc
+++ b/doc/manuals/chapters/configuration.adoc
@@ -46,15 +46,16 @@ Multi-ARFCN support is available since osmo-trx release `0.2.0`, and it was
added specifically in commit `76764278169d252980853251daeb9f1ba0c246e1`.
This feature is useful for instance if you want to run more than 1 TRX with an
-Ettus B200 device, or 2 TRX with an Ettus B210 device, since they support only 1
-and 2 physical RF channels respectively. No device from other providers or even
-other devices than B200 and B210 from Ettus are known to support this feature.
+Ettus B200 device, or more than 2 TRXs with an Ettus B210 device, since they
+support only 1 and 2 physical RF channels respectively. No device from other
+providers or even other devices than B200 and B210 from Ettus are known to
+support this feature.
With multi-ARFCN enabled, ARFCN spacing is fixed at 800 kHz or 4 GSM channels.
So if TRX-0 is set to ARFCN 51, TRX-1 _must_ be set to 55, and so on. Up to
three ARFCN's is supported for multi-TRX.
-From BTS and BSC point of view, supporting multiple TRX through multi-ARFCN
+From BTS and BSC point of view, supporting multiple TRXs through multi-ARFCN
feature in OsmoTRX doesn't make any difference from a regular multi-TRX setup,
leaving apart of course the mentioned ARFCN limitations explained above and as a
consequence physical installation and operational differences.
diff --git a/doc/manuals/vty/trx_vty_reference.xml b/doc/manuals/vty/trx_vty_reference.xml
index 8738235..ff44078 100644
--- a/doc/manuals/vty/trx_vty_reference.xml
+++ b/doc/manuals/vty/trx_vty_reference.xml
@@ -18,10 +18,11 @@
<param name='terminal' doc='Write to terminal' />
</params>
</command>
- <command id='write file'>
+ <command id='write file [PATH]'>
<params>
<param name='write' doc='Write running configuration to memory, network, or terminal' />
<param name='file' doc='Write to configuration file' />
+ <param name='[PATH]' doc='Set file path to store the config, or replace if already exists' />
</params>
</command>
<command id='write memory'>
@@ -96,12 +97,6 @@
<param name='history' doc='Display the session command history' />
</params>
</command>
- <command id='show trx'>
- <params>
- <param name='show' doc='Show running system information' />
- <param name='trx' doc='Display information on the TRX' />
- </params>
- </command>
<command id='logging enable'>
<params>
<param name='logging' doc='Configure logging' />
@@ -193,14 +188,17 @@
<param name='MASK' doc='List of logging categories to log, e.g. &apos;abc:mno:xyz&apos;. Available log categories depend on the specific application, refer to the &apos;logging level&apos; command. Optionally add individual log levels like &apos;abc,1:mno,3:xyz,5&apos;, where the level numbers are LOGL_DEBUG=1 LOGL_INFO=3 LOGL_NOTICE=5 LOGL_ERROR=7 LOGL_FATAL=8' />
</params>
</command>
- <command id='logging level (main|trxctrl|dev|lms|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
+ <command id='logging level (main|trxclk|trxctrl|trxddl|trxdul|dev|devdrv|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
<params>
<param name='logging' doc='Configure logging' />
<param name='level' doc='Set the log level for a specified category' />
<param name='main' doc='Main generic category' />
+ <param name='trxclk' doc='TRX Master Clock' />
<param name='trxctrl' doc='TRX CTRL interface' />
+ <param name='trxddl' doc='TRX Data interface Downlink' />
+ <param name='trxdul' doc='TRX CTRL interface Uplink' />
<param name='dev' doc='Device/Driver specific code' />
- <param name='lms' doc='Logging from within LimeSuite itself' />
+ <param name='devdrv' doc='Logging from external device driver library implementing lower level specifics' />
<param name='lglobal' doc='Library-internal global log family' />
<param name='llapd' doc='LAPD in libosmogsm' />
<param name='linp' doc='A-bis Intput Subsystem' />
@@ -259,6 +257,43 @@
<param name='force-all' doc='Release any globally forced log level set with &apos;logging level force-all &lt;level&gt;&apos;' />
</params>
</command>
+ <command id='logp (main|trxclk|trxctrl|trxddl|trxdul|dev|devdrv|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal) .LOGMESSAGE'>
+ <params>
+ <param name='logp' doc='Print a message on all log outputs; useful for placing markers in test logs' />
+ <param name='main' doc='Main generic category' />
+ <param name='trxclk' doc='TRX Master Clock' />
+ <param name='trxctrl' doc='TRX CTRL interface' />
+ <param name='trxddl' doc='TRX Data interface Downlink' />
+ <param name='trxdul' doc='TRX CTRL interface Uplink' />
+ <param name='dev' doc='Device/Driver specific code' />
+ <param name='devdrv' doc='Logging from external device driver library implementing lower level specifics' />
+ <param name='lglobal' doc='Library-internal global log family' />
+ <param name='llapd' doc='LAPD in libosmogsm' />
+ <param name='linp' doc='A-bis Intput Subsystem' />
+ <param name='lmux' doc='A-bis B-Subchannel TRAU Frame Multiplex' />
+ <param name='lmi' doc='A-bis Input Driver for Signalling' />
+ <param name='lmib' doc='A-bis Input Driver for B-Channels (voice)' />
+ <param name='lsms' doc='Layer3 Short Message Service (SMS)' />
+ <param name='lctrl' doc='Control Interface' />
+ <param name='lgtp' doc='GPRS GTP library' />
+ <param name='lstats' doc='Statistics messages and logging' />
+ <param name='lgsup' doc='Generic Subscriber Update Protocol' />
+ <param name='loap' doc='Osmocom Authentication Protocol' />
+ <param name='lss7' doc='libosmo-sigtran Signalling System 7' />
+ <param name='lsccp' doc='libosmo-sigtran SCCP Implementation' />
+ <param name='lsua' doc='libosmo-sigtran SCCP User Adaptation' />
+ <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' />
+ <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' />
+ <param name='ljibuf' doc='libosmo-netif Jitter Buffer' />
+ <param name='lrspro' doc='Remote SIM protocol' />
+ <param name='debug' doc='Log debug messages and higher levels' />
+ <param name='info' doc='Log informational messages and higher levels' />
+ <param name='notice' doc='Log noticeable messages and higher levels' />
+ <param name='error' doc='Log error messages and higher levels' />
+ <param name='fatal' doc='Log only fatal messages' />
+ <param name='.LOGMESSAGE' doc='Arbitrary message to log on given category and log level' />
+ </params>
+ </command>
<command id='show logging vty'>
<params>
<param name='show' doc='Show running system information' />
@@ -272,6 +307,12 @@
<param name='alarms' doc='Show current logging configuration' />
</params>
</command>
+ <command id='show trx'>
+ <params>
+ <param name='show' doc='Show running system information' />
+ <param name='trx' doc='Display information on the TRX' />
+ </params>
+ </command>
<command id='show talloc-context (application|all) (full|brief|DEPTH)'>
<params>
<param name='show' doc='Show running system information' />
@@ -415,12 +456,6 @@
<param name='monitor' doc='Copy debug output to the current terminal line' />
</params>
</command>
- <command id='show trx'>
- <params>
- <param name='show' doc='Show running system information' />
- <param name='trx' doc='Display information on the TRX' />
- </params>
- </command>
<command id='logging enable'>
<params>
<param name='logging' doc='Configure logging' />
@@ -512,14 +547,17 @@
<param name='MASK' doc='List of logging categories to log, e.g. &apos;abc:mno:xyz&apos;. Available log categories depend on the specific application, refer to the &apos;logging level&apos; command. Optionally add individual log levels like &apos;abc,1:mno,3:xyz,5&apos;, where the level numbers are LOGL_DEBUG=1 LOGL_INFO=3 LOGL_NOTICE=5 LOGL_ERROR=7 LOGL_FATAL=8' />
</params>
</command>
- <command id='logging level (main|trxctrl|dev|lms|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
+ <command id='logging level (main|trxclk|trxctrl|trxddl|trxdul|dev|devdrv|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
<params>
<param name='logging' doc='Configure logging' />
<param name='level' doc='Set the log level for a specified category' />
<param name='main' doc='Main generic category' />
+ <param name='trxclk' doc='TRX Master Clock' />
<param name='trxctrl' doc='TRX CTRL interface' />
+ <param name='trxddl' doc='TRX Data interface Downlink' />
+ <param name='trxdul' doc='TRX CTRL interface Uplink' />
<param name='dev' doc='Device/Driver specific code' />
- <param name='lms' doc='Logging from within LimeSuite itself' />
+ <param name='devdrv' doc='Logging from external device driver library implementing lower level specifics' />
<param name='lglobal' doc='Library-internal global log family' />
<param name='llapd' doc='LAPD in libosmogsm' />
<param name='linp' doc='A-bis Intput Subsystem' />
@@ -578,6 +616,43 @@
<param name='force-all' doc='Release any globally forced log level set with &apos;logging level force-all &lt;level&gt;&apos;' />
</params>
</command>
+ <command id='logp (main|trxclk|trxctrl|trxddl|trxdul|dev|devdrv|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal) .LOGMESSAGE'>
+ <params>
+ <param name='logp' doc='Print a message on all log outputs; useful for placing markers in test logs' />
+ <param name='main' doc='Main generic category' />
+ <param name='trxclk' doc='TRX Master Clock' />
+ <param name='trxctrl' doc='TRX CTRL interface' />
+ <param name='trxddl' doc='TRX Data interface Downlink' />
+ <param name='trxdul' doc='TRX CTRL interface Uplink' />
+ <param name='dev' doc='Device/Driver specific code' />
+ <param name='devdrv' doc='Logging from external device driver library implementing lower level specifics' />
+ <param name='lglobal' doc='Library-internal global log family' />
+ <param name='llapd' doc='LAPD in libosmogsm' />
+ <param name='linp' doc='A-bis Intput Subsystem' />
+ <param name='lmux' doc='A-bis B-Subchannel TRAU Frame Multiplex' />
+ <param name='lmi' doc='A-bis Input Driver for Signalling' />
+ <param name='lmib' doc='A-bis Input Driver for B-Channels (voice)' />
+ <param name='lsms' doc='Layer3 Short Message Service (SMS)' />
+ <param name='lctrl' doc='Control Interface' />
+ <param name='lgtp' doc='GPRS GTP library' />
+ <param name='lstats' doc='Statistics messages and logging' />
+ <param name='lgsup' doc='Generic Subscriber Update Protocol' />
+ <param name='loap' doc='Osmocom Authentication Protocol' />
+ <param name='lss7' doc='libosmo-sigtran Signalling System 7' />
+ <param name='lsccp' doc='libosmo-sigtran SCCP Implementation' />
+ <param name='lsua' doc='libosmo-sigtran SCCP User Adaptation' />
+ <param name='lm3ua' doc='libosmo-sigtran MTP3 User Adaptation' />
+ <param name='lmgcp' doc='libosmo-mgcp Media Gateway Control Protocol' />
+ <param name='ljibuf' doc='libosmo-netif Jitter Buffer' />
+ <param name='lrspro' doc='Remote SIM protocol' />
+ <param name='debug' doc='Log debug messages and higher levels' />
+ <param name='info' doc='Log informational messages and higher levels' />
+ <param name='notice' doc='Log noticeable messages and higher levels' />
+ <param name='error' doc='Log error messages and higher levels' />
+ <param name='fatal' doc='Log only fatal messages' />
+ <param name='.LOGMESSAGE' doc='Arbitrary message to log on given category and log level' />
+ </params>
+ </command>
<command id='show logging vty'>
<params>
<param name='show' doc='Show running system information' />
@@ -591,6 +666,12 @@
<param name='alarms' doc='Show current logging configuration' />
</params>
</command>
+ <command id='show trx'>
+ <params>
+ <param name='show' doc='Show running system information' />
+ <param name='trx' doc='Display information on the TRX' />
+ </params>
+ </command>
<command id='show talloc-context (application|all) (full|brief|DEPTH)'>
<params>
<param name='show' doc='Show running system information' />
@@ -772,16 +853,6 @@
<param name='history' doc='Display the session command history' />
</params>
</command>
- <command id='ctrl'>
- <params>
- <param name='ctrl' doc='Configure the Control Interface' />
- </params>
- </command>
- <command id='trx'>
- <params>
- <param name='trx' doc='Configure the TRX' />
- </params>
- </command>
<command id='log stderr'>
<params>
<param name='log' doc='Configure logging sub-system' />
@@ -861,6 +932,16 @@
<param name='[HOSTNAME]' doc='Host name to send the GSMTAP logging to (UDP port 4729)' />
</params>
</command>
+ <command id='ctrl'>
+ <params>
+ <param name='ctrl' doc='Configure the Control Interface' />
+ </params>
+ </command>
+ <command id='trx'>
+ <params>
+ <param name='trx' doc='Configure the TRX' />
+ </params>
+ </command>
<command id='stats reporter statsd'>
<params>
<param name='stats' doc='Configure stats sub-system' />
@@ -973,14 +1054,17 @@
<param name='[last]' doc='Log source file info at the end of a log line. If omitted, log source file info just before the log text.' />
</params>
</command>
- <command id='logging level (main|trxctrl|dev|lms|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
+ <command id='logging level (main|trxclk|trxctrl|trxddl|trxdul|dev|devdrv|lglobal|llapd|linp|lmux|lmi|lmib|lsms|lctrl|lgtp|lstats|lgsup|loap|lss7|lsccp|lsua|lm3ua|lmgcp|ljibuf|lrspro) (debug|info|notice|error|fatal)'>
<params>
<param name='logging' doc='Configure logging' />
<param name='level' doc='Set the log level for a specified category' />
<param name='main' doc='Main generic category' />
+ <param name='trxclk' doc='TRX Master Clock' />
<param name='trxctrl' doc='TRX CTRL interface' />
+ <param name='trxddl' doc='TRX Data interface Downlink' />
+ <param name='trxdul' doc='TRX CTRL interface Uplink' />
<param name='dev' doc='Device/Driver specific code' />
- <param name='lms' doc='Logging from within LimeSuite itself' />
+ <param name='devdrv' doc='Logging from external device driver library implementing lower level specifics' />
<param name='lglobal' doc='Library-internal global log family' />
<param name='llapd' doc='LAPD in libosmogsm' />
<param name='linp' doc='A-bis Intput Subsystem' />
@@ -1179,20 +1263,6 @@
<param name='4' doc='(null)' />
</params>
</command>
- <command id='test rtsc &lt;0-7&gt;'>
- <params>
- <param name='test' doc='Set the Random Normal Burst test mode with TSC' />
- <param name='rtsc' doc='TSC' />
- <param name='&lt;0-7&gt;' doc='(null)' />
- </params>
- </command>
- <command id='test rach-delay &lt;0-68&gt;'>
- <params>
- <param name='test' doc='Set the Random Access Burst test mode with delay' />
- <param name='rach-delay' doc='RACH delay' />
- <param name='&lt;0-68&gt;' doc='(null)' />
- </params>
- </command>
<command id='clock-ref (internal|external|gpsdo)'>
<params>
<param name='clock-ref' doc='Set the Reference Clock' />
@@ -1247,10 +1317,29 @@
<param name='&lt;1-32&gt;' doc='Real time priority' />
</params>
</command>
- <command id='filler dummy'>
+ <command id='filler type (zero|dummy|random-nb-gmsk|random-nb-8psk|random-ab)'>
+ <params>
+ <param name='filler' doc='Filler burst settings' />
+ <param name='type' doc='Filler burst type (default=zero)' />
+ <param name='zero' doc='Send an empty burst when there is nothing to send (default)' />
+ <param name='dummy' doc='Send a dummy burst when there is nothing to send on C0 (TRX0) and empty burst on other channels. Use for OpenBTS compatibility only, don&apos;t use with OsmoBTS as it breaks encryption.' />
+ <param name='random-nb-gmsk' doc='Send a GMSK modulated Normal Burst with random bits when there is nothing to send. Use for spectrum mask testing. Configure &apos;filler tsc&apos; to set training sequence.' />
+ <param name='random-nb-8psk' doc='Send an 8-PSK modulated Normal Burst with random bits when there is nothing to send. Use for spectrum mask testing. Configure &apos;filler tsc&apos; to set training sequence.' />
+ <param name='random-ab' doc='Send an Access Burst with random bits when there is nothing to send. Use for Rx/Tx alignment. Configure &apos;filler access-burst-delay&apos; to introduce artificial delay.' />
+ </params>
+ </command>
+ <command id='filler tsc &lt;0-7&gt;'>
+ <params>
+ <param name='filler' doc='Filler burst settings' />
+ <param name='tsc' doc='Set the TSC for GMSK/8-PSK Normal Burst random fillers. Used only with &apos;random-nb-gmsk&apos; and &apos;random-nb-8psk&apos; filler types. (default=0)' />
+ <param name='&lt;0-7&gt;' doc='TSC' />
+ </params>
+ </command>
+ <command id='filler access-burst-delay &lt;0-68&gt;'>
<params>
- <param name='filler' doc='Enable C0 filler table' />
- <param name='dummy' doc='Dummy method' />
+ <param name='filler' doc='Filler burst settings' />
+ <param name='access-burst-delay' doc='Set the delay for Access Burst random fillers. Used only with &apos;random-ab&apos; filler type. (default=0)' />
+ <param name='&lt;0-68&gt;' doc='RACH delay in symbols' />
</params>
</command>
<command id='ctr-error-threshold (rx_overruns|tx_underruns|rx_drop_events|rx_drop_samples|tx_drop_events|tx_drop_samples) &lt;0-65535&gt; (per-second|per-minute|per-hour|per-day)'>