aboutsummaryrefslogtreecommitdiffstats
path: root/include/osmo-bts/scheduler.h
diff options
context:
space:
mode:
Diffstat (limited to 'include/osmo-bts/scheduler.h')
-rw-r--r--include/osmo-bts/scheduler.h212
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);