aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-trx/l1_if.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bts-trx/l1_if.h')
-rw-r--r--src/osmo-bts-trx/l1_if.h136
1 files changed, 99 insertions, 37 deletions
diff --git a/src/osmo-bts-trx/l1_if.h b/src/osmo-bts-trx/l1_if.h
index 87df951b..84fd4b5b 100644
--- a/src/osmo-bts-trx/l1_if.h
+++ b/src/osmo-bts-trx/l1_if.h
@@ -1,58 +1,129 @@
#ifndef L1_IF_H_TRX
#define L1_IF_H_TRX
+#include <osmocom/core/rate_ctr.h>
+
#include <osmo-bts/scheduler.h>
#include <osmo-bts/phy_link.h>
#include "trx_if.h"
+/*
+ * 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.
+ */
+
+/* bts-trx specific rate counters */
+enum {
+ BTSTRX_CTR_SCHED_DL_MISS_FN,
+ BTSTRX_CTR_SCHED_DL_FH_NO_CARRIER,
+ BTSTRX_CTR_SCHED_DL_FH_CACHE_MISS,
+ BTSTRX_CTR_SCHED_UL_FH_NO_CARRIER,
+};
+
+/*! 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;
+ struct rate_ctr_group *ctrs; /* bts-trx specific rate counters */
+};
+
struct trx_config {
- uint8_t trxd_hdr_ver_req; /* requested TRXD header version */
- uint8_t trxd_hdr_ver_use; /* actual TRXD header version in use */
- int setformat_sent;
+ uint8_t trxd_pdu_ver_req; /* requested TRXD PDU version */
+ uint8_t trxd_pdu_ver_use; /* actual TRXD PDU version in use */
+ bool setformat_sent;
+ bool setformat_acked;
+
+ bool enabled;
- uint8_t poweron; /* poweron(1) or poweroff(0) */
- int poweron_sent;
- int arfcn_valid;
+ bool arfcn_valid;
uint16_t arfcn;
- int arfcn_sent;
+ bool rxtune_sent;
+ bool rxtune_acked;
+ bool txtune_sent;
+ bool txtune_acked;
- int tsc_valid;
+ bool tsc_valid;
uint8_t tsc;
- int tsc_sent;
+ bool tsc_sent;
+ bool tsc_acked;
- int bsic_valid;
+ bool bsic_valid;
uint8_t bsic;
- int bsic_sent;
+ bool bsic_sent;
+ bool bsic_acked;
- int rxgain_valid;
+ bool rxgain_valid;
uint8_t rxgain;
- int rxgain_sent;
+ bool rxgain_sent;
- int power_valid;
- uint8_t power;
- int power_oml;
- int power_sent;
+ int forced_max_power_red; /* -1 if not forced by VTY config (default) */
- int maxdly_valid;
+ bool nominal_power_set_by_vty; /* whether nominal trx power was enforced/retreived from VTY config "nominal-tx-power" */
+ bool nomtxpower_sent;
+ bool nomtxpower_acked;
+
+ bool maxdly_valid;
int maxdly;
- int maxdly_sent;
+ bool maxdly_sent;
- int maxdlynb_valid;
+ bool maxdlynb_valid;
int maxdlynb;
- int maxdlynb_sent;
+ bool maxdlynb_sent;
uint8_t slotmask;
- int slottype_valid[TRX_NR_TS];
- uint8_t slottype[TRX_NR_TS];
- int 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 {
struct llist_head trx_ctrl_list;
/* Latest RSPed cmd, used to catch duplicate RSPs from sent retransmissions */
struct trx_ctrl_msg *last_acked;
+ /* Whether the code path is in the middle of handling a received message. */
+ bool in_trx_ctrl_read_cb;
+ /* Whether the l1h->trx_ctrl_list was flushed by the callback handling a received message */
+ bool flushed_while_in_trx_ctrl_read_cb;
//struct gsm_bts_trx *trx;
struct phy_instance *phy_inst;
@@ -63,23 +134,14 @@ struct trx_l1h {
/* transceiver config */
struct trx_config config;
-
- struct l1sched_trx l1s;
+ struct osmo_fsm_inst *provision_fi;
};
struct trx_l1h *trx_l1h_alloc(void *tall_ctx, struct phy_instance *pinst);
-int check_transceiver_availability(struct gsm_bts *bts, int avail);
int l1if_provision_transceiver_trx(struct trx_l1h *l1h);
-int l1if_provision_transceiver(struct gsm_bts *bts);
int l1if_mph_time_ind(struct gsm_bts *bts, uint32_t fn);
-int l1if_process_meas_res(struct gsm_bts_trx *trx, uint8_t tn, uint32_t fn, uint8_t chan_nr,
- int n_errors, int n_bits_total, float rssi, int16_t toa256);
-
-static inline struct l1sched_trx *trx_l1sched_hdl(struct gsm_bts_trx *trx)
-{
- struct phy_instance *pinst = trx->role_bts.l1h;
- struct trx_l1h *l1h = pinst->u.osmotrx.hdl;
- return &l1h->l1s;
-}
+void l1if_trx_set_nominal_power(struct gsm_bts_trx *trx, int nominal_power);
+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);
#endif /* L1_IF_H_TRX */