diff options
Diffstat (limited to 'src/osmo-bts-trx/l1_if.h')
-rw-r--r-- | src/osmo-bts-trx/l1_if.h | 136 |
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 */ |