diff options
Diffstat (limited to 'include/osmo-bts/scheduler.h')
-rw-r--r-- | include/osmo-bts/scheduler.h | 212 |
1 files changed, 141 insertions, 71 deletions
diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h index e693e3ec..aea55959 100644 --- a/include/osmo-bts/scheduler.h +++ b/include/osmo-bts/scheduler.h @@ -1,18 +1,18 @@ -#ifndef TRX_SCHEDULER_H -#define TRX_SCHEDULER_H +#pragma once #include <osmocom/core/utils.h> +#include <osmocom/core/rate_ctr.h> #include <osmo-bts/gsm_data.h> -/* Whether a logical channel must be activated automatically */ -#define TRX_CHAN_FLAG_AUTO_ACTIVE (1 << 0) -/* Whether a logical channel belongs to PDCH (packet switched data) */ -#define TRX_CHAN_FLAG_PDCH (1 << 1) +#define TRX_GMSK_NB_TSC(br) \ + _sched_train_seq_gmsk_nb[(br)->tsc_set][(br)->tsc] -/* FIXME: we should actually activate 'auto-active' channels */ -#define TRX_CHAN_IS_ACTIVE(state, chan) \ - (trx_chan_desc[chan].flags & TRX_CHAN_FLAG_AUTO_ACTIVE || (state)->active) +#define TRX_8PSK_NB_TSC(br) \ + _sched_train_seq_8psk_nb[(br)->tsc] + +#define TRX_CHAN_IS_DEDIC(chan) \ + (chan >= TRXC_TCHF) /* These types define the different channels on a multiframe. * Each channel has queues and can be activated individually. @@ -24,6 +24,10 @@ enum trx_chan_type { TRXC_BCCH, TRXC_RACH, TRXC_CCCH, + TRXC_CBCH, + TRXC_PDTCH, + TRXC_PTCCH, +/* Dedicated channels start here */ TRXC_TCHF, TRXC_TCHH_0, TRXC_TCHH_1, @@ -54,9 +58,6 @@ enum trx_chan_type { TRXC_SACCH8_5, TRXC_SACCH8_6, TRXC_SACCH8_7, - TRXC_PDTCH, - TRXC_PTCCH, - TRXC_CBCH, _TRX_CHAN_MAX }; @@ -64,31 +65,37 @@ enum trx_chan_type { #define GPRS_BURST_LEN GSM_BURST_LEN #define EGPRS_BURST_LEN 444 -enum trx_burst_type { - TRX_BURST_GMSK, - TRX_BURST_8PSK, +enum trx_mod_type { + TRX_MOD_T_GMSK, + TRX_MOD_T_8PSK, + TRX_MOD_T_AQPSK, +}; + +/* A set of measurements belonging to one Uplink burst */ +struct l1sched_meas_set { + uint32_t fn; /* TDMA frame number */ + int16_t toa256; /* Timing of Arrival (1/256 of a symbol) */ + int16_t ci_cb; /* Carrier-to-Interference (cB) */ + float rssi; /* RSSI (dBm) */ }; /* States each channel on a multiframe */ struct l1sched_chan_state { + /* Pointer to the associated logical channel state from gsm_data_shared. + * Initialized during channel activation, thus may be NULL for inactive + * or auto-active channels. Always check before dereferencing! */ + struct gsm_lchan *lchan; + /* scheduler */ - uint8_t active; /* Channel is active */ + bool active; /* Channel is active */ ubit_t *dl_bursts; /* burst buffer for TX */ - enum trx_burst_type dl_burst_type; /* GMSK or 8PSK burst type */ + enum trx_mod_type dl_mod_type; /* Downlink modulation type */ + uint8_t dl_mask; /* mask of transmitted bursts */ sbit_t *ul_bursts; /* burst buffer for RX */ uint32_t ul_first_fn; /* fn of first burst */ - uint8_t ul_mask; /* mask of received bursts */ - - /* measurements */ - uint8_t rssi_num; /* number of RSSI values */ - float rssi_sum; /* sum of RSSI values */ - uint8_t toa_num; /* number of TOA values */ - int32_t toa256_sum; /* sum of TOA values (1/256 symbol) */ - uint8_t ci_cb_num; /* number of C/I values */ - int32_t ci_cb_sum; /* sum of C/I values (in centiBels) */ + uint32_t ul_mask; /* mask of received bursts */ /* loss detection */ - uint8_t lost_frames; /* how many L2 frames were lost */ uint32_t last_tdma_fn; /* last processed TDMA frame number */ uint32_t proc_tdma_fs; /* how many TDMA frames were processed */ uint32_t lost_tdma_fs; /* how many TDMA frames were lost */ @@ -99,18 +106,20 @@ struct l1sched_chan_state { /* AMR */ uint8_t codec[4]; /* 4 possible codecs for amr */ int codecs; /* number of possible codecs */ - float ber_sum; /* sum of bit error rates */ - int ber_num; /* number of bit error rates */ + int lqual_cb_sum; /* sum of link quality samples (in cB) */ + int lqual_cb_num; /* number of link quality samples */ uint8_t ul_ft; /* current uplink FT index */ uint8_t dl_ft; /* current downlink FT index */ uint8_t ul_cmr; /* current uplink CMR index */ uint8_t dl_cmr; /* current downlink CMR index */ - uint8_t amr_loop; /* if AMR loop is enabled */ + uint8_t amr_last_dtx; /* last received dtx frame type */ /* TCH/H */ uint8_t dl_ongoing_facch; /* FACCH/H on downlink */ uint8_t ul_ongoing_facch; /* FACCH/H on uplink */ + uint8_t dl_facch_bursts; /* number of remaining DL FACCH bursts */ + /* encryption */ int ul_encr_algo; /* A5/x encry algo downlink */ int dl_encr_algo; /* A5/x encry algo uplink */ @@ -119,15 +128,14 @@ struct l1sched_chan_state { uint8_t ul_encr_key[MAX_A5_KEY_LEN]; uint8_t dl_encr_key[MAX_A5_KEY_LEN]; - /* measurements */ + /* Uplink measurements */ struct { - uint8_t clock; /* cyclic clock counter */ - int8_t rssi[32]; /* last RSSI values */ - int rssi_count; /* received RSSI values */ - int rssi_valid_count; /* number of stored value */ - int rssi_got_burst; /* any burst received so far */ - int32_t toa256_sum; /* sum of TOA values (1/256 symbol) */ - int toa_num; /* number of TOA value */ + /* Active channel measurements (simple ring buffer) */ + struct l1sched_meas_set buf[24]; /* up to 24 (BUFMAX) entries */ + unsigned int current; /* current position */ + + /* Interference measurements */ + int interf_avg; /* sliding average */ } meas; /* handover */ @@ -135,67 +143,62 @@ struct l1sched_chan_state { }; struct l1sched_ts { + struct gsm_bts_trx_ts *ts; /* timeslot we belong to */ + uint8_t mf_index; /* selected multiframe index */ uint8_t mf_period; /* period of multiframe */ const struct trx_sched_frame *mf_frames; /* pointer to frame layout */ struct llist_head dl_prims; /* Queue primitives for TX */ + struct rate_ctr_group *ctrs; /* rate counters */ + /* Channel states for all logical channels */ struct l1sched_chan_state chan_state[_TRX_CHAN_MAX]; }; -struct l1sched_trx { - struct gsm_bts_trx *trx; - struct l1sched_ts ts[TRX_NR_TS]; -}; - -struct l1sched_ts *l1sched_trx_get_ts(struct l1sched_trx *l1t, uint8_t tn); - -/*! \brief how many frame numbers in advance we should send bursts to PHY */ -extern uint32_t trx_clock_advance; -/*! \brief advance RTS.ind to L2 by that many clocks */ -extern uint32_t trx_rts_advance; -/*! \brief last frame number as received from PHY */ -extern uint32_t transceiver_last_fn; - /*! \brief Initialize the scheduler data structures */ -int trx_sched_init(struct l1sched_trx *l1t, struct gsm_bts_trx *trx); +void trx_sched_init(struct gsm_bts_trx *trx); /*! \brief De-initialize the scheduler data structures */ -void trx_sched_exit(struct l1sched_trx *l1t); +void trx_sched_clean(struct gsm_bts_trx *trx); /*! \brief Handle a PH-DATA.req from L2 down to L1 */ -int trx_sched_ph_data_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap); +int trx_sched_ph_data_req(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); /*! \brief Handle a PH-TCH.req from L2 down to L1 */ -int trx_sched_tch_req(struct l1sched_trx *l1t, struct osmo_phsap_prim *l1sap); +int trx_sched_tch_req(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap); /*! \brief PHY informs us of new (current) GSM frame number */ int trx_sched_clock(struct gsm_bts *bts, uint32_t fn); +/*! \brief PHY informs us clock indications should start to be received */ +int trx_sched_clock_started(struct gsm_bts *bts); + +/*! \brief PHY informs us no more clock indications should be received anymore */ +int trx_sched_clock_stopped(struct gsm_bts *bts); + /*! \brief set multiframe scheduler to given physical channel config */ -int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn, - enum gsm_phys_chan_config pchan); +int trx_sched_set_pchan(struct gsm_bts_trx_ts *ts, enum gsm_phys_chan_config pchan); /*! \brief set all matching logical channels active/inactive */ -int trx_sched_set_lchan(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t link_id, - int active); +int trx_sched_set_lchan(struct gsm_lchan *lchan, uint8_t chan_nr, uint8_t link_id, bool active); + +/*! \brief set uplink access on given logical channels active/inactive */ +int trx_sched_set_ul_access(struct gsm_lchan *lchan, uint8_t chan_nr, bool active); + +/*! \brief set all logical channels of BCCH/CCCH active/inactive */ +int trx_sched_set_bcch_ccch(struct gsm_lchan *lchan, bool active); /*! \brief set mode of all matching logical channels to given mode(s) */ -int trx_sched_set_mode(struct l1sched_trx *l1t, uint8_t chan_nr, uint8_t rsl_cmode, +int trx_sched_set_mode(struct gsm_bts_trx_ts *ts, uint8_t chan_nr, uint8_t rsl_cmode, uint8_t tch_mode, int codecs, uint8_t codec0, uint8_t codec1, uint8_t codec2, uint8_t codec3, uint8_t initial_codec, uint8_t handover); /*! \brief set ciphering on given logical channels */ -int trx_sched_set_cipher(struct l1sched_trx *l1t, uint8_t chan_nr, int downlink, - int algo, uint8_t *key, int key_len); - -/* \brief close all logical channels and reset timeslots */ -void trx_sched_reset(struct l1sched_trx *l1t); - +int trx_sched_set_cipher(struct gsm_lchan *lchan, uint8_t chan_nr, bool downlink); /* frame structures */ struct trx_sched_frame { @@ -226,13 +229,17 @@ struct trx_sched_multiframe { int find_sched_mframe_idx(enum gsm_phys_chan_config pchan, uint8_t tn); /*! Determine if given frame number contains SACCH (true) or other (false) burst */ -bool trx_sched_is_sacch_fn(struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink); +bool trx_sched_is_sacch_fn(const struct gsm_bts_trx_ts *ts, uint32_t fn, bool uplink); extern const struct trx_sched_multiframe trx_sched_multiframes[]; #define TRX_BI_F_NOPE_IND (1 << 0) #define TRX_BI_F_MOD_TYPE (1 << 1) #define TRX_BI_F_TS_INFO (1 << 2) #define TRX_BI_F_CI_CB (1 << 3) +#define TRX_BI_F_TRX_NUM (1 << 4) +#define TRX_BI_F_BATCH_IND (1 << 5) +#define TRX_BI_F_SHADOW_IND (1 << 6) +#define TRX_BI_F_ACCESS_BURST (1 << 7) /*! UL burst indication with the corresponding meta info */ struct trx_ul_burst_ind { @@ -246,17 +253,80 @@ struct trx_ul_burst_ind { int8_t rssi; /*!< Received Signal Strength Indication */ /* Optional fields (defined by flags) */ - enum trx_burst_type bt; /*!< Modulation type */ + enum trx_mod_type mod; /*!< Modulation type */ uint8_t tsc_set; /*!< Training Sequence Set */ uint8_t tsc; /*!< Training Sequence Code */ int16_t ci_cb; /*!< Carrier-to-Interference ratio (in centiBels) */ + uint8_t trx_num; /*!< TRX (RF channel) number */ + + /* Used internally by the PDU parser */ + uint8_t _num_pdus; /*!< Number of processed PDUs */ + + /* Internally used by the scheduler */ + enum trx_chan_type chan; + uint8_t bid; /*! Burst soft-bits buffer */ sbit_t burst[EGPRS_BURST_LEN]; size_t burst_len; }; +#define TRX_BR_F_FACCH (1 << 0) + +/*! DL burst request with the corresponding meta info */ +struct trx_dl_burst_req { + uint8_t flags; /*!< see TRX_BR_F_* */ + + /* Mandatory fields */ + uint32_t fn; /*!< TDMA frame number */ + uint8_t tn; /*!< TDMA timeslot number */ + uint8_t att; /*!< Tx power attenuation */ + int8_t scpir; /*!< SCPIR (for AQPSK only) */ + uint8_t trx_num; /*!< TRX (RF channel) number */ + + enum trx_mod_type mod; /*!< Modulation type */ + uint8_t tsc_set; /*!< Training Sequence Set */ + uint8_t tsc; /*!< Training Sequence Code */ + + /* Internally used by the scheduler */ + enum trx_chan_type chan; + uint8_t bid; + + /*! Burst hard-bits buffer */ + ubit_t burst[EGPRS_BURST_LEN]; + size_t burst_len; +}; + /*! Handle an UL burst received by PHY */ -int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi); +int trx_sched_route_burst_ind(const struct gsm_bts_trx *trx, struct trx_ul_burst_ind *bi); +int trx_sched_ul_burst(struct l1sched_ts *l1ts, struct trx_ul_burst_ind *bi); + +/* Averaging mode for trx_sched_meas_avg() */ +enum sched_meas_avg_mode { + /* first 22 of last 24 bursts (for TCH/F14.4, TCH/F9.6, TCH/F4.8) */ + SCHED_MEAS_AVG_M_S24N22, + /* last 22 bursts (for TCH/H4.8, TCH/H2.4) */ + SCHED_MEAS_AVG_M_S22N22, + /* last 4 bursts (default for xCCH, PTCCH and PDTCH) */ + SCHED_MEAS_AVG_M_S4N4, + /* last 8 bursts (default for TCH/F and FACCH/F) */ + SCHED_MEAS_AVG_M_S8N8, + /* first 4 of last 6 bursts (default for TCH/H) */ + SCHED_MEAS_AVG_M_S6N4, + /* last 6 bursts (default for FACCH/H) */ + SCHED_MEAS_AVG_M_S6N6, + /* first 4 of last 8 bursts */ + SCHED_MEAS_AVG_M_S8N4, + /* first 2 of last 6 bursts */ + SCHED_MEAS_AVG_M_S6N2, + /* middle 2 of last 6 bursts */ + SCHED_MEAS_AVG_M_S4N2, +}; -#endif /* TRX_SCHEDULER_H */ +void trx_sched_meas_push(struct l1sched_chan_state *chan_state, + const struct trx_ul_burst_ind *bi); +void trx_sched_meas_avg(const struct l1sched_chan_state *chan_state, + struct l1sched_meas_set *avg, + enum sched_meas_avg_mode mode); +uint32_t trx_sched_lookup_fn(const struct l1sched_chan_state *chan_state, + const unsigned int shift); |