2013-02-05 10:45:28 +00:00
|
|
|
#ifndef L1_IF_H_TRX
|
|
|
|
#define L1_IF_H_TRX
|
|
|
|
|
2020-07-02 12:36:44 +00:00
|
|
|
#include <osmocom/core/rate_ctr.h>
|
|
|
|
|
2016-01-09 22:28:57 +00:00
|
|
|
#include <osmo-bts/scheduler.h>
|
2016-01-09 12:13:37 +00:00
|
|
|
#include <osmo-bts/phy_link.h>
|
2018-01-17 12:45:40 +00:00
|
|
|
#include "trx_if.h"
|
2013-02-05 10:45:28 +00:00
|
|
|
|
2019-09-27 14:44:14 +00:00
|
|
|
/*
|
|
|
|
* TRX frame clock handling
|
|
|
|
*
|
|
|
|
* In a "normal" synchronous PHY layer, we would be polled every time
|
|
|
|
* the PHY needs data for a given frame number. However, the
|
|
|
|
* OpenBTS-inherited TRX protocol works differently: We (L1) must
|
|
|
|
* autonomously send burst data based on our own clock, and every so
|
|
|
|
* often (currently every ~ 216 frames), we get a clock indication from
|
|
|
|
* the TRX.
|
|
|
|
*
|
|
|
|
* We're using a MONOTONIC timerfd interval timer for the 4.615ms frame
|
|
|
|
* intervals, and then compute + send the 8 bursts for that frame.
|
|
|
|
*
|
|
|
|
* Upon receiving a clock indication from the TRX, we compensate
|
|
|
|
* accordingly: If we were transmitting too fast, we're delaying the
|
|
|
|
* next interval timer accordingly. If we were too slow, we immediately
|
|
|
|
* send burst data for the missing frame numbers.
|
|
|
|
*/
|
|
|
|
|
2020-07-02 12:36:44 +00:00
|
|
|
/* bts-trx specific rate counters */
|
|
|
|
enum {
|
|
|
|
BTSTRX_CTR_SCHED_DL_MISS_FN,
|
osmo-bts-trx/scheduler: implement baseband frequency hopping
The idea behind the baseband frequency hopping is quite simple: we
have several RF carriers (transceivers) transmitting and receiving
on fixed frequencies (just like in a regular multi-trx setup), and
an additional burst routing layer between the schedulear and the
transceiver interface (TRXD over UDP).
Speaking in terms of the proposed implementation:
- on Downlink, dlfh_route_br() calculates the ARFCN corresponding
to the current TDMA frame number according to the hopping sequence
parametets, and picks the transceiver with matching ARFCN;
- on Uplink, ulfh_route_bi() iterates over the transceiver list of
of the BTS, calculating hopping ARFCNs for equivalent timeslots,
and picks the one with ARFCN matching the received burst.
In order to avoid frequent transceiver lookups on the Downlink path,
dlfh_route_br() maintains a "cache" in the timeslot state structure.
Unfortunately, this "cache" seems to be useless on the Uplink path,
so ulfh_route_bi() always needs to lookup the matching transceiver
for each burst received over the TRXD interface.
It may also happen that the scheduler will be unable to route an
Uplink or Downlink burst, e.g. due to inconsistent / incorrect
hopping sequence parameters received from the BSC, or in case
if a transceiver gets RF-locked by the BTS operator.
Such events are logged as "FATAL" and aditionally signalled by the
following osmo-bts-trx specific rate counters:
- trx_sched:dl_fh_no_carrier (Downlink), and
- trx_sched:ul_fh_no_carrier (Uplink).
Change-Id: I68f4ae09fd0789ad0d8f1c1e17e17dfc4de8e462
Related: SYS#4868, OS#4546
2020-06-15 10:22:39 +00:00
|
|
|
BTSTRX_CTR_SCHED_DL_FH_NO_CARRIER,
|
2022-03-06 10:10:36 +00:00
|
|
|
BTSTRX_CTR_SCHED_DL_FH_CACHE_MISS,
|
osmo-bts-trx/scheduler: implement baseband frequency hopping
The idea behind the baseband frequency hopping is quite simple: we
have several RF carriers (transceivers) transmitting and receiving
on fixed frequencies (just like in a regular multi-trx setup), and
an additional burst routing layer between the schedulear and the
transceiver interface (TRXD over UDP).
Speaking in terms of the proposed implementation:
- on Downlink, dlfh_route_br() calculates the ARFCN corresponding
to the current TDMA frame number according to the hopping sequence
parametets, and picks the transceiver with matching ARFCN;
- on Uplink, ulfh_route_bi() iterates over the transceiver list of
of the BTS, calculating hopping ARFCNs for equivalent timeslots,
and picks the one with ARFCN matching the received burst.
In order to avoid frequent transceiver lookups on the Downlink path,
dlfh_route_br() maintains a "cache" in the timeslot state structure.
Unfortunately, this "cache" seems to be useless on the Uplink path,
so ulfh_route_bi() always needs to lookup the matching transceiver
for each burst received over the TRXD interface.
It may also happen that the scheduler will be unable to route an
Uplink or Downlink burst, e.g. due to inconsistent / incorrect
hopping sequence parameters received from the BSC, or in case
if a transceiver gets RF-locked by the BTS operator.
Such events are logged as "FATAL" and aditionally signalled by the
following osmo-bts-trx specific rate counters:
- trx_sched:dl_fh_no_carrier (Downlink), and
- trx_sched:ul_fh_no_carrier (Uplink).
Change-Id: I68f4ae09fd0789ad0d8f1c1e17e17dfc4de8e462
Related: SYS#4868, OS#4546
2020-06-15 10:22:39 +00:00
|
|
|
BTSTRX_CTR_SCHED_UL_FH_NO_CARRIER,
|
2020-07-02 12:36:44 +00:00
|
|
|
};
|
|
|
|
|
2019-09-27 14:44:14 +00:00
|
|
|
/*! clock state of a given TRX */
|
|
|
|
struct osmo_trx_clock_state {
|
|
|
|
/*! number of FN periods without TRX clock indication */
|
|
|
|
uint32_t fn_without_clock_ind;
|
|
|
|
struct {
|
|
|
|
/*! last FN we processed based on FN period timer */
|
|
|
|
uint32_t fn;
|
|
|
|
/*! time at which we last processed FN */
|
|
|
|
struct timespec tv;
|
|
|
|
} last_fn_timer;
|
|
|
|
struct {
|
|
|
|
/*! last FN we received a clock indication for */
|
|
|
|
uint32_t fn;
|
|
|
|
/*! time at which we received the last clock indication */
|
|
|
|
struct timespec tv;
|
|
|
|
} last_clk_ind;
|
|
|
|
/*! Osmocom FD wrapper for timerfd */
|
|
|
|
struct osmo_fd fn_timer_ofd;
|
|
|
|
};
|
|
|
|
|
|
|
|
/* gsm_bts->model_priv, specific to osmo-bts-trx */
|
|
|
|
struct bts_trx_priv {
|
|
|
|
struct osmo_trx_clock_state clk_s;
|
2020-07-02 12:36:44 +00:00
|
|
|
struct rate_ctr_group *ctrs; /* bts-trx specific rate counters */
|
2019-09-27 14:44:14 +00:00
|
|
|
};
|
|
|
|
|
2013-02-05 10:45:28 +00:00
|
|
|
struct trx_config {
|
2021-04-14 18:45:49 +00:00
|
|
|
uint8_t trxd_pdu_ver_req; /* requested TRXD PDU version */
|
|
|
|
uint8_t trxd_pdu_ver_use; /* actual TRXD PDU version in use */
|
2020-07-22 12:08:26 +00:00
|
|
|
bool setformat_sent;
|
2020-07-22 16:48:48 +00:00
|
|
|
bool setformat_acked;
|
2019-06-26 19:29:58 +00:00
|
|
|
|
2019-09-27 22:50:51 +00:00
|
|
|
bool enabled;
|
|
|
|
|
2013-02-05 10:45:28 +00:00
|
|
|
|
2020-07-22 12:08:26 +00:00
|
|
|
bool arfcn_valid;
|
2013-02-05 10:45:28 +00:00
|
|
|
uint16_t arfcn;
|
2020-07-22 16:48:48 +00:00
|
|
|
bool rxtune_sent;
|
|
|
|
bool rxtune_acked;
|
|
|
|
bool txtune_sent;
|
|
|
|
bool txtune_acked;
|
2013-02-05 10:45:28 +00:00
|
|
|
|
2020-07-22 12:08:26 +00:00
|
|
|
bool tsc_valid;
|
2013-02-05 10:45:28 +00:00
|
|
|
uint8_t tsc;
|
2020-07-22 12:08:26 +00:00
|
|
|
bool tsc_sent;
|
2020-07-22 16:48:48 +00:00
|
|
|
bool tsc_acked;
|
2013-02-05 10:45:28 +00:00
|
|
|
|
2020-07-22 12:08:26 +00:00
|
|
|
bool bsic_valid;
|
2013-02-05 10:45:28 +00:00
|
|
|
uint8_t bsic;
|
2020-07-22 12:08:26 +00:00
|
|
|
bool bsic_sent;
|
2020-07-22 16:48:48 +00:00
|
|
|
bool bsic_acked;
|
2013-02-05 10:45:28 +00:00
|
|
|
|
2020-07-22 12:08:26 +00:00
|
|
|
bool rxgain_valid;
|
2017-01-26 14:32:37 +00:00
|
|
|
uint8_t rxgain;
|
2020-07-22 12:08:26 +00:00
|
|
|
bool rxgain_sent;
|
2017-01-26 14:32:37 +00:00
|
|
|
|
2020-05-26 17:18:22 +00:00
|
|
|
int forced_max_power_red; /* -1 if not forced by VTY config (default) */
|
2017-01-26 14:32:37 +00:00
|
|
|
|
2020-05-29 11:29:00 +00:00
|
|
|
bool nominal_power_set_by_vty; /* whether nominal trx power was enforced/retreived from VTY config "nominal-tx-power" */
|
2020-07-22 16:48:48 +00:00
|
|
|
bool nomtxpower_sent;
|
|
|
|
bool nomtxpower_acked;
|
2020-05-29 11:29:00 +00:00
|
|
|
|
2020-07-22 12:08:26 +00:00
|
|
|
bool maxdly_valid;
|
2013-02-05 10:45:28 +00:00
|
|
|
int maxdly;
|
2020-07-22 12:08:26 +00:00
|
|
|
bool maxdly_sent;
|
2013-02-05 10:45:28 +00:00
|
|
|
|
2020-07-22 12:08:26 +00:00
|
|
|
bool maxdlynb_valid;
|
2016-11-04 19:30:35 +00:00
|
|
|
int maxdlynb;
|
2020-07-22 12:08:26 +00:00
|
|
|
bool maxdlynb_sent;
|
2016-11-04 19:30:35 +00:00
|
|
|
|
2013-02-05 10:45:28 +00:00
|
|
|
uint8_t slotmask;
|
|
|
|
|
[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
2021-05-24 00:16:50 +00:00
|
|
|
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];
|
2013-02-05 10:45:28 +00:00
|
|
|
};
|
|
|
|
|
|
|
|
struct trx_l1h {
|
|
|
|
struct llist_head trx_ctrl_list;
|
2018-01-17 12:45:40 +00:00
|
|
|
/* Latest RSPed cmd, used to catch duplicate RSPs from sent retransmissions */
|
|
|
|
struct trx_ctrl_msg *last_acked;
|
2013-02-05 10:45:28 +00:00
|
|
|
|
2016-01-09 12:13:37 +00:00
|
|
|
//struct gsm_bts_trx *trx;
|
|
|
|
struct phy_instance *phy_inst;
|
2013-02-05 10:45:28 +00:00
|
|
|
|
|
|
|
struct osmo_fd trx_ofd_ctrl;
|
|
|
|
struct osmo_timer_list trx_ctrl_timer;
|
|
|
|
struct osmo_fd trx_ofd_data;
|
|
|
|
|
2013-04-09 08:55:37 +00:00
|
|
|
/* transceiver config */
|
2013-02-05 10:45:28 +00:00
|
|
|
struct trx_config config;
|
2020-07-06 17:56:08 +00:00
|
|
|
struct osmo_fsm_inst *provision_fi;
|
2013-02-05 10:45:28 +00:00
|
|
|
};
|
|
|
|
|
2018-11-13 18:31:50 +00:00
|
|
|
struct trx_l1h *trx_l1h_alloc(void *tall_ctx, struct phy_instance *pinst);
|
2013-04-09 08:55:37 +00:00
|
|
|
int l1if_provision_transceiver_trx(struct trx_l1h *l1h);
|
2013-02-05 10:45:28 +00:00
|
|
|
int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn);
|
2020-06-19 15:15:57 +00:00
|
|
|
void l1if_trx_set_nominal_power(struct gsm_bts_trx *trx, int nominal_power);
|
2020-07-06 17:56:08 +00:00
|
|
|
int l1if_trx_start_power_ramp(struct gsm_bts_trx *trx, ramp_compl_cb_t ramp_compl_cb);
|
|
|
|
enum gsm_phys_chan_config transceiver_chan_type_2_pchan(uint8_t type);
|
2013-02-05 10:45:28 +00:00
|
|
|
|
|
|
|
#endif /* L1_IF_H_TRX */
|