aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2021-05-24 02:16:50 +0200
committerlaforge <laforge@osmocom.org>2021-06-04 20:04:13 +0000
commit3c1151f9456bdf0d7348c27c0cabbb41e84fcbbc (patch)
tree55663287acd54f43bab137cc9f4c2a4f346aab36
parent207d56afe5ce3ad1e78b54aa3d5a8cac65382924 (diff)
[VAMOS] osmo-bts-trx: properly handle per-timeslot TSC values
Each timeslot can have its own Training Sequence Code value, which may optionally be included in the NM_MT_SET_CHAN_ATTR message sent over the A-bis/OML. If it's not present, then the TSC value for a timeslot is derived from the BCC part of BSIC, which is always included in the NM_MT_SET_BTS_ATTR message. On the TRXC interface, the BTS global TSC value is indicated to the transceiver using either of the 'SETTSC' or 'SETBSIC' commands. The transceiver then applies this value for all timeslots by default, however it can be redefined for each timeslot individually using additional arguments of the 'SETSLOT' command (see section 25.2.4.1 in the user manual [1] for more details). Currently, trx_set_ts_as_pchan() sends TRX_PROV_EV_CFG_TSC to the transceiver provisioning FSM, together with the per-timeslot TSC value. This event causes the FSM to modify the global TSC value, that is going to be or has already been sent to the transceiver. This is wrong, the global TSC value shall not be overwritten. Remove the TRX_PROV_EV_CFG_TSC, and include per-timeslot Training Sequence Code and Set in the data structure that gets passed together with the TRX_PROV_EV_CFG_TS instead. Implement handling of the optional per-timeslot TSC in trx_if_cmd_setslot(). [1] https://downloads.osmocom.org/docs/latest/osmobts-usermanual.pdf Change-Id: Idc5796151e3e83f42d60c2d4cb7c35890d76a7f5 Related: SYS#4895, OS#4941
-rw-r--r--src/osmo-bts-trx/l1_if.c13
-rw-r--r--src/osmo-bts-trx/l1_if.h11
-rw-r--r--src/osmo-bts-trx/main.c1
-rw-r--r--src/osmo-bts-trx/trx_if.c18
-rw-r--r--src/osmo-bts-trx/trx_if.h2
-rw-r--r--src/osmo-bts-trx/trx_provision_fsm.c73
-rw-r--r--src/osmo-bts-trx/trx_provision_fsm.h7
-rw-r--r--src/osmo-bts-trx/trx_vty.c19
8 files changed, 85 insertions, 59 deletions
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c
index 3f95a696..3be51799 100644
--- a/src/osmo-bts-trx/l1_if.c
+++ b/src/osmo-bts-trx/l1_if.c
@@ -271,15 +271,9 @@ static uint8_t trx_set_ts_as_pchan(struct gsm_bts_trx_ts *ts,
struct phy_instance *pinst = trx_phy_instance(ts->trx);
struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
uint8_t tn = ts->nr;
- uint16_t tsc = ts->tsc;
uint8_t slottype;
int rc;
- /* all TSC of all timeslots must be equal, because transceiver only
- * supports one TSC per TRX */
-
- osmo_fsm_inst_dispatch(l1h->provision_fi, TRX_PROV_EV_CFG_TSC, (void*)(intptr_t)tsc);
-
/* ignore disabled slots */
if (!(l1h->config.slotmask & (1 << tn)))
return NM_NACK_RES_NOTAVAIL;
@@ -303,6 +297,13 @@ static uint8_t trx_set_ts_as_pchan(struct gsm_bts_trx_ts *ts,
struct trx_prov_ev_cfg_ts_data data = { .tn = tn, .slottype = slottype };
+ if (ts->tsc_set != 0 || ts->tsc != BTS_TSC(ts->trx->bts)) {
+ /* On TRXC we use 3GPP compliant numbering, so +1 */
+ data.tsc_set = ts->tsc_set + 1;
+ data.tsc_val = ts->tsc;
+ data.tsc_valid = true;
+ }
+
osmo_fsm_inst_dispatch(l1h->provision_fi, TRX_PROV_EV_CFG_TS, &data);
return 0;
diff --git a/src/osmo-bts-trx/l1_if.h b/src/osmo-bts-trx/l1_if.h
index 864bb691..50369d9d 100644
--- a/src/osmo-bts-trx/l1_if.h
+++ b/src/osmo-bts-trx/l1_if.h
@@ -105,9 +105,14 @@ struct trx_config {
uint8_t slotmask;
- bool slottype_valid[TRX_NR_TS];
- uint8_t slottype[TRX_NR_TS];
- bool slottype_sent[TRX_NR_TS];
+ bool setslot_valid[TRX_NR_TS];
+ struct {
+ uint8_t slottype;
+ uint8_t tsc_set;
+ uint8_t tsc_val;
+ bool tsc_valid;
+ } setslot[TRX_NR_TS];
+ bool setslot_sent[TRX_NR_TS];
};
struct trx_l1h {
diff --git a/src/osmo-bts-trx/main.c b/src/osmo-bts-trx/main.c
index e0a99a5c..6ec8dfc9 100644
--- a/src/osmo-bts-trx/main.c
+++ b/src/osmo-bts-trx/main.c
@@ -145,6 +145,7 @@ int bts_model_init(struct gsm_bts *bts)
osmo_bts_set_feature(bts->features, BTS_FEAT_CBCH);
osmo_bts_set_feature(bts->features, BTS_FEAT_HOPPING);
osmo_bts_set_feature(bts->features, BTS_FEAT_ACCH_REP);
+ osmo_bts_set_feature(bts->features, BTS_FEAT_MULTI_TSC);
bts_internal_flag_set(bts, BTS_INTERNAL_FLAG_MEAS_PAYLOAD_COMB);
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index af1deefd..c10a15fa 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -8,6 +8,7 @@
* Copyright (C) 2013 Andreas Eversberg <jolly@eversberg.eu>
* Copyright (C) 2016-2017 Harald Welte <laforge@gnumonks.org>
* Copyright (C) 2019 Vadim Yanitskiy <axilirator@gmail.com>
+ * Copyright (C) 2021 sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
@@ -326,10 +327,21 @@ int trx_if_cmd_setmaxdlynb(struct trx_l1h *l1h, int dly)
return trx_ctrl_cmd(l1h, 0, "SETMAXDLYNB", "%d", dly);
}
-/*! Send "SETSLOT" command to TRX: Configure Channel Combination for TS */
-int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type, trx_if_cmd_setslot_cb *cb)
+/*! Send "SETSLOT" command to TRX: Configure Channel Combination and TSC for TS */
+int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn,
+ trx_if_cmd_setslot_cb *cb)
{
- return trx_ctrl_cmd_cb(l1h, 1, cb, "SETSLOT", "%d %d", tn, type);
+ const struct trx_config *cfg = &l1h->config;
+
+ if (cfg->setslot[tn].tsc_valid) { /* PHY is instructed to use a custom TSC */
+ return trx_ctrl_cmd_cb(l1h, 1, cb, "SETSLOT", "%u %u C%u/S%u",
+ tn, cfg->setslot[tn].slottype,
+ cfg->setslot[tn].tsc_val,
+ cfg->setslot[tn].tsc_set);
+ } else { /* PHY is instructed to use the default TSC from 'SETTSC' */
+ return trx_ctrl_cmd_cb(l1h, 1, cb, "SETSLOT", "%u %u",
+ tn, cfg->setslot[tn].slottype);
+ }
}
/*! Send "RXTUNE" command to TRX: Tune Receiver to given ARFCN */
diff --git a/src/osmo-bts-trx/trx_if.h b/src/osmo-bts-trx/trx_if.h
index e131d56c..b838b76a 100644
--- a/src/osmo-bts-trx/trx_if.h
+++ b/src/osmo-bts-trx/trx_if.h
@@ -34,7 +34,7 @@ int trx_if_cmd_getnompower(struct trx_l1h *l1h, trx_if_cmd_getnompower_cb *cb);
int trx_if_cmd_setpower_att(struct trx_l1h *l1h, int power_att_db, trx_if_cmd_setpower_att_cb *cb);
int trx_if_cmd_setmaxdly(struct trx_l1h *l1h, int dly);
int trx_if_cmd_setmaxdlynb(struct trx_l1h *l1h, int dly);
-int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, uint8_t type, trx_if_cmd_setslot_cb *cb);
+int trx_if_cmd_setslot(struct trx_l1h *l1h, uint8_t tn, trx_if_cmd_setslot_cb *cb);
int trx_if_cmd_rxtune(struct trx_l1h *l1h, uint16_t arfcn, trx_if_cmd_generic_cb *cb);
int trx_if_cmd_txtune(struct trx_l1h *l1h, uint16_t arfcn, trx_if_cmd_generic_cb *cb);
int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);
diff --git a/src/osmo-bts-trx/trx_provision_fsm.c b/src/osmo-bts-trx/trx_provision_fsm.c
index 070037d0..5beca2ac 100644
--- a/src/osmo-bts-trx/trx_provision_fsm.c
+++ b/src/osmo-bts-trx/trx_provision_fsm.c
@@ -191,17 +191,15 @@ static void l1if_setslot_cb(struct trx_l1h *l1h, uint8_t tn, uint8_t type, int r
cb_ts_connected(ts, rc);
}
-/* Returns true if any TS changed, false otherwise */
-static bool update_ts_data(struct trx_l1h *l1h, struct trx_prov_ev_cfg_ts_data* ts_data) {
-
- if (l1h->config.slottype[ts_data->tn] != ts_data->slottype ||
- !l1h->config.slottype_valid[ts_data->tn]) {
- l1h->config.slottype[ts_data->tn] = ts_data->slottype;
- l1h->config.slottype_valid[ts_data->tn] = true;
- l1h->config.slottype_sent[ts_data->tn] = false;
- return true;
- }
- return false;
+static void update_ts_data(struct trx_l1h *l1h, struct trx_prov_ev_cfg_ts_data *data)
+{
+ l1h->config.setslot[data->tn].slottype = data->slottype;
+ l1h->config.setslot[data->tn].tsc_set = data->tsc_set;
+ l1h->config.setslot[data->tn].tsc_val = data->tsc_val;
+ l1h->config.setslot[data->tn].tsc_valid = data->tsc_valid;
+
+ l1h->config.setslot_valid[data->tn] = true;
+ l1h->config.setslot_sent[data->tn] = false;
}
/* Whether a given TRX is fully configured and can be powered on */
@@ -290,9 +288,7 @@ static void st_open_poweroff(struct osmo_fsm_inst *fi, uint32_t event, void *dat
struct trx_l1h *l1h = (struct trx_l1h *)fi->priv;
struct phy_instance *pinst = l1h->phy_inst;
struct gsm_bts_trx *trx = pinst->trx;
- uint8_t bsic;
uint16_t arfcn;
- uint16_t tsc;
int nominal_power;
int status;
bool others_ready;
@@ -302,11 +298,21 @@ static void st_open_poweroff(struct osmo_fsm_inst *fi, uint32_t event, void *dat
l1h->config.enabled =(bool)data;
break;
case TRX_PROV_EV_CFG_BSIC:
- bsic = (uint8_t)(intptr_t)data;
- if (l1h->config.bsic != bsic || !l1h->config.bsic_valid) {
- l1h->config.bsic = bsic;
- l1h->config.bsic_valid = true;
- l1h->config.bsic_sent = false;
+ /* We always get BSIC from the BSC, TSC can be derived from the BCC */
+ if (!pinst->phy_link->u.osmotrx.use_legacy_setbsic) {
+ const uint8_t tsc = BSIC2BCC((uint8_t)(intptr_t)data);
+ if (l1h->config.tsc != tsc || !l1h->config.tsc_valid) {
+ l1h->config.tsc = tsc;
+ l1h->config.tsc_valid = true;
+ l1h->config.tsc_sent = false;
+ }
+ } else {
+ const uint8_t bsic = (uint8_t)(intptr_t)data;
+ if (l1h->config.bsic != bsic || !l1h->config.bsic_valid) {
+ l1h->config.bsic = bsic;
+ l1h->config.bsic_valid = true;
+ l1h->config.bsic_sent = false;
+ }
}
break;
case TRX_PROV_EV_CFG_ARFCN:
@@ -319,14 +325,6 @@ static void st_open_poweroff(struct osmo_fsm_inst *fi, uint32_t event, void *dat
l1h->config.nomtxpower_sent = false;
}
break;
- case TRX_PROV_EV_CFG_TSC:
- tsc = (uint16_t)(intptr_t)data;
- if (l1h->config.tsc != tsc || !l1h->config.tsc_valid) {
- l1h->config.tsc = tsc;
- l1h->config.tsc_valid = true;
- l1h->config.tsc_sent = false;
- }
- break;
case TRX_PROV_EV_CFG_TS:
update_ts_data(l1h, (struct trx_prov_ev_cfg_ts_data*)data);
break;
@@ -478,11 +476,10 @@ static void st_open_poweron_on_enter(struct osmo_fsm_inst *fi, uint32_t prev_sta
}
for (tn = 0; tn < TRX_NR_TS; tn++) {
- if (l1h->config.slottype_valid[tn]
- && !l1h->config.slottype_sent[tn]) {
- trx_if_cmd_setslot(l1h, tn,
- l1h->config.slottype[tn], l1if_setslot_cb);
- l1h->config.slottype_sent[tn] = true;
+ if (l1h->config.setslot_valid[tn]
+ && !l1h->config.setslot_sent[tn]) {
+ trx_if_cmd_setslot(l1h, tn, l1if_setslot_cb);
+ l1h->config.setslot_sent[tn] = true;
}
}
}
@@ -507,7 +504,7 @@ static void st_open_poweron(struct osmo_fsm_inst *fi, uint32_t event, void *data
l1h->config.maxdly_sent = false;
l1h->config.maxdlynb_sent = false;
for (tn = 0; tn < TRX_NR_TS; tn++)
- l1h->config.slottype_sent[tn] = false;
+ l1h->config.setslot_sent[tn] = false;
} else if (!pinst->phy_link->u.osmotrx.poweronoff_sent) {
bts_model_trx_close_cb(pinst->trx, 0);
} /* else: poweroff in progress, cb will be called upon TRXC RSP */
@@ -519,12 +516,10 @@ static void st_open_poweron(struct osmo_fsm_inst *fi, uint32_t event, void *data
break;
case TRX_PROV_EV_CFG_TS:
ts_data = (struct trx_prov_ev_cfg_ts_data*)data;
- if (update_ts_data(l1h, ts_data)) {
- trx_if_cmd_setslot(l1h, ts_data->tn,
- l1h->config.slottype[ ts_data->tn], l1if_setslot_cb);
- l1h->config.slottype_sent[ts_data->tn] = true;
- }
-
+ update_ts_data(l1h, ts_data);
+ /* While in this state we can send SETSLOT immediately */
+ trx_if_cmd_setslot(l1h, ts_data->tn, l1if_setslot_cb);
+ l1h->config.setslot_sent[ts_data->tn] = true;
break;
default:
OSMO_ASSERT(0);
@@ -571,7 +566,6 @@ static struct osmo_fsm_state trx_prov_fsm_states[] = {
X(TRX_PROV_EV_CFG_ENABLE) |
X(TRX_PROV_EV_CFG_BSIC) |
X(TRX_PROV_EV_CFG_ARFCN) |
- X(TRX_PROV_EV_CFG_TSC) |
X(TRX_PROV_EV_CFG_TS) |
X(TRX_PROV_EV_RXTUNE_CNF) |
X(TRX_PROV_EV_TXTUNE_CNF) |
@@ -623,7 +617,6 @@ const struct value_string trx_prov_fsm_event_names[] = {
OSMO_VALUE_STRING(TRX_PROV_EV_CFG_ENABLE),
OSMO_VALUE_STRING(TRX_PROV_EV_CFG_BSIC),
OSMO_VALUE_STRING(TRX_PROV_EV_CFG_ARFCN),
- OSMO_VALUE_STRING(TRX_PROV_EV_CFG_TSC),
OSMO_VALUE_STRING(TRX_PROV_EV_CFG_TS),
OSMO_VALUE_STRING(TRX_PROV_EV_CFG_RXGAIN),
OSMO_VALUE_STRING(TRX_PROV_EV_CFG_SETMAXDLY),
diff --git a/src/osmo-bts-trx/trx_provision_fsm.h b/src/osmo-bts-trx/trx_provision_fsm.h
index 0f800888..8e6b97bf 100644
--- a/src/osmo-bts-trx/trx_provision_fsm.h
+++ b/src/osmo-bts-trx/trx_provision_fsm.h
@@ -22,6 +22,8 @@
#pragma once
+#include <stdbool.h>
+
#include <osmocom/core/fsm.h>
enum trx_provision_fsm_states {
@@ -35,6 +37,11 @@ enum trx_provision_fsm_states {
struct trx_prov_ev_cfg_ts_data {
uint8_t tn;
uint8_t slottype;
+
+ /* Training Sequence Code and Set */
+ uint8_t tsc_set;
+ uint8_t tsc_val;
+ bool tsc_valid;
};
enum trx_provision_fsm_events {
diff --git a/src/osmo-bts-trx/trx_vty.c b/src/osmo-bts-trx/trx_vty.c
index 2b0913ff..d9d17d03 100644
--- a/src/osmo-bts-trx/trx_vty.c
+++ b/src/osmo-bts-trx/trx_vty.c
@@ -127,16 +127,23 @@ static void show_phy_inst_single(struct vty *vty, struct phy_instance *pinst)
else
vty_out(vty, " maxdlynb : undefined%s", VTY_NEWLINE);
for (tn = 0; tn < TRX_NR_TS; tn++) {
- if (!((1 << tn) & l1h->config.slotmask))
+ if (!((1 << tn) & l1h->config.slotmask)) {
vty_out(vty, " slot #%d: unsupported%s", tn,
VTY_NEWLINE);
- else if (l1h->config.slottype_valid[tn])
- vty_out(vty, " slot #%d: type %d%s", tn,
- l1h->config.slottype[tn],
- VTY_NEWLINE);
- else
+ continue;
+ } else if (!l1h->config.setslot_valid[tn]) {
vty_out(vty, " slot #%d: undefined%s", tn,
VTY_NEWLINE);
+ continue;
+ }
+
+ vty_out(vty, " slot #%d: type %d", tn,
+ l1h->config.setslot[tn].slottype);
+ if (l1h->config.setslot[tn].tsc_valid)
+ vty_out(vty, " TSC-s%dc%d",
+ l1h->config.setslot[tn].tsc_set,
+ l1h->config.setslot[tn].tsc_val);
+ vty_out(vty, "%s", VTY_NEWLINE);
}
}