diff options
Diffstat (limited to 'include')
-rw-r--r-- | include/osmo-bts/Makefile.am | 2 | ||||
-rw-r--r-- | include/osmo-bts/scheduler.h | 175 | ||||
-rw-r--r-- | include/osmo-bts/scheduler_backend.h | 82 |
3 files changed, 258 insertions, 1 deletions
diff --git a/include/osmo-bts/Makefile.am b/include/osmo-bts/Makefile.am index bf037ae3..af88a1ac 100644 --- a/include/osmo-bts/Makefile.am +++ b/include/osmo-bts/Makefile.am @@ -1,4 +1,4 @@ noinst_HEADERS = abis.h bts.h bts_model.h gsm_data.h logging.h measurement.h \ oml.h paging.h rsl.h signal.h vty.h amr.h pcu_if.h pcuif_proto.h \ handover.h msg_utils.h tx_power.h control_if.h cbch.h l1sap.h \ - power_control.h + power_control.h scheduler.h scheduler_backend.h diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h new file mode 100644 index 00000000..13ef0511 --- /dev/null +++ b/include/osmo-bts/scheduler.h @@ -0,0 +1,175 @@ +#ifndef TRX_SCHEDULER_H +#define TRX_SCHEDULER_H + +/* These types define the different channels on a multiframe. + * Each channel has queues and can be activated individually. + */ +enum trx_chan_type { + TRXC_IDLE = 0, + TRXC_FCCH, + TRXC_SCH, + TRXC_BCCH, + TRXC_RACH, + TRXC_CCCH, + TRXC_TCHF, + TRXC_TCHH_0, + TRXC_TCHH_1, + TRXC_SDCCH4_0, + TRXC_SDCCH4_1, + TRXC_SDCCH4_2, + TRXC_SDCCH4_3, + TRXC_SDCCH8_0, + TRXC_SDCCH8_1, + TRXC_SDCCH8_2, + TRXC_SDCCH8_3, + TRXC_SDCCH8_4, + TRXC_SDCCH8_5, + TRXC_SDCCH8_6, + TRXC_SDCCH8_7, + TRXC_SACCHTF, + TRXC_SACCHTH_0, + TRXC_SACCHTH_1, + TRXC_SACCH4_0, + TRXC_SACCH4_1, + TRXC_SACCH4_2, + TRXC_SACCH4_3, + TRXC_SACCH8_0, + TRXC_SACCH8_1, + TRXC_SACCH8_2, + TRXC_SACCH8_3, + TRXC_SACCH8_4, + TRXC_SACCH8_5, + TRXC_SACCH8_6, + TRXC_SACCH8_7, + TRXC_PDTCH, + TRXC_PTCCH, + _TRX_CHAN_MAX +}; + +/* States each channel on a multiframe */ +struct l1sched_chan_state { + /* scheduler */ + uint8_t active; /* Channel is active */ + ubit_t *dl_bursts; /* burst buffer for TX */ + 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 */ + + /* RSSI / TOA */ + uint8_t rssi_num; /* number of RSSI values */ + float rssi_sum; /* sum of RSSI values */ + uint8_t toa_num; /* number of TOA values */ + float toa_sum; /* sum of TOA values */ + + /* loss detection */ + uint8_t lost; /* (SACCH) loss detection */ + + /* mode */ + uint8_t rsl_cmode, tch_mode; /* mode for TCH channels */ + + /* 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 */ + 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 */ + + /* TCH/H */ + uint8_t dl_ongoing_facch; /* FACCH/H on downlink */ + uint8_t ul_ongoing_facch; /* FACCH/H on uplink */ + + /* encryption */ + int ul_encr_algo; /* A5/x encry algo downlink */ + int dl_encr_algo; /* A5/x encry algo uplink */ + int ul_encr_key_len; + int dl_encr_key_len; + uint8_t ul_encr_key[MAX_A5_KEY_LEN]; + uint8_t dl_encr_key[MAX_A5_KEY_LEN]; + + /* 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 */ + float toa_sum; /* sum of TOA values */ + int toa_num; /* number of TOA value */ + } meas; + + /* handover */ + uint8_t ho_rach_detect; /* if rach detection is on */ +}; + +struct l1sched_ts { + uint8_t mf_index; /* selected multiframe index */ + uint32_t mf_last_fn; /* last received frame number */ + uint8_t mf_period; /* period of multiframe */ + const struct trx_sched_frame *mf_frames; /* pointer to frame layout */ + + struct llist_head dl_prims; /* Queue primitves for TX */ + + /* 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 scheudler data structures */ +int trx_sched_init(struct l1sched_trx *l1t); + +/*! \brief De-initialize the scheudler data structures */ +void trx_sched_exit(struct l1sched_trx *l1t); + +/*! \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); + +/*! \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); + +/*! \brief PHY informs us of new (current) GSM freme nunmber */ +int trx_sched_clock(struct gsm_bts *bts, uint32_t fn); + +/*! \brief handle an UL burst received by PHY */ +int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + sbit_t *bits, int8_t rssi, float toa); + +/*! \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); + +/*! \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); + +/*! \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, + 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); + +#endif /* TRX_SCHEDULER_H */ diff --git a/include/osmo-bts/scheduler_backend.h b/include/osmo-bts/scheduler_backend.h new file mode 100644 index 00000000..9f663cdd --- /dev/null +++ b/include/osmo-bts/scheduler_backend.h @@ -0,0 +1,82 @@ +#pragma once + +typedef int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn, + uint32_t fn, enum trx_chan_type chan); + +typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn, + uint32_t fn, enum trx_chan_type chan, + uint8_t bid); + +typedef int trx_sched_ul_func(struct l1sched_trx *l1t, uint8_t tn, + uint32_t fn, enum trx_chan_type chan, + uint8_t bid, sbit_t *bits, int8_t rssi, + float toa); + +struct trx_chan_desc { + /*! \brief Is this on a PDCH (PS) ? */ + int pdch; + /*! \brief TRX Channel Type */ + enum trx_chan_type chan; + /*! \brief Channel Number (like in RSL) */ + uint8_t chan_nr; + /*! \brief Link ID (like in RSL) */ + uint8_t link_id; + /*! \brief Human-readable name */ + const char *name; + /*! \brief function to call when we want to generate RTS.req to L2 */ + trx_sched_rts_func *rts_fn; + /*! \brief function to call when DATA.req received from L2 */ + trx_sched_dl_func *dl_fn; + /*! \brief function to call when burst received from PHY */ + trx_sched_ul_func *ul_fn; + /*! \breif is this channel automatically active at start? */ + int auto_active; +}; +extern const struct trx_chan_desc trx_chan_desc[_TRX_CHAN_MAX]; + +extern const ubit_t _sched_tsc[8][26]; +const ubit_t _sched_fcch_burst[148]; +const ubit_t _sched_sch_train[64]; + +struct msgb *_sched_dequeue_prim(struct l1sched_trx *l1t, int8_t tn, uint32_t fn, + enum trx_chan_type chan); + +int _sched_compose_ph_data_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t *l2, uint8_t l2_len, float rssi); + +int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len); + +ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid); +ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid); +ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid); +ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid); +ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid); +ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid); +ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid); +int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi, + float toa); +int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi, + float toa); +int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi, + float toa); +int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi, + float toa); +int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn, + enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi, + float toa); + +const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn); +int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn); +void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate); |