aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--include/osmo-bts/scheduler.h38
-rw-r--r--src/osmo-bts-trx/sched_lchan_pdtch.c38
-rw-r--r--src/osmo-bts-trx/sched_lchan_tchf.c33
-rw-r--r--src/osmo-bts-trx/sched_lchan_tchh.c22
-rw-r--r--src/osmo-bts-trx/sched_lchan_xcch.c38
-rw-r--r--src/osmo-bts-trx/scheduler_trx.c70
6 files changed, 151 insertions, 88 deletions
diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index 0d863474..b488b6c4 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -70,6 +70,13 @@ enum trx_burst_type {
TRX_BURST_8PSK,
};
+/* A set of measurements belonging to one Uplink burst */
+struct l1sched_meas_set {
+ 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.
@@ -85,14 +92,6 @@ struct l1sched_chan_state {
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) */
-
/* loss detection */
uint8_t lost_frames; /* how many L2 frames were lost */
uint32_t last_tdma_fn; /* last processed TDMA frame number */
@@ -126,8 +125,11 @@ struct l1sched_chan_state {
uint8_t ul_encr_key[MAX_A5_KEY_LEN];
uint8_t dl_encr_key[MAX_A5_KEY_LEN];
- /* measurements */
- /* TODO: measurement history (ring buffer) will be added here */
+ /* Simple ring buffer (up to 8 unique measurements) */
+ struct {
+ struct l1sched_meas_set buf[8];
+ unsigned int current; /* current position */
+ } meas;
/* handover */
bool ho_rach_detect; /* if rach detection is on */
@@ -266,4 +268,20 @@ struct trx_dl_burst_req {
int trx_sched_route_burst_ind(struct trx_ul_burst_ind *bi, struct l1sched_trx *l1t);
int trx_sched_ul_burst(struct l1sched_trx *l1t, struct trx_ul_burst_ind *bi);
+/* Averaging mode for trx_sched_meas_avg() */
+enum sched_meas_avg_mode {
+ /* last 4 bursts (default for xCCH, TCH/H, PTCCH and PDTCH) */
+ SCHED_MEAS_AVG_M_QUAD,
+ /* last 8 bursts (default for TCH/F and FACCH/F) */
+ SCHED_MEAS_AVG_M_OCTO,
+ /* last 6 bursts (default for FACCH/H) */
+ SCHED_MEAS_AVG_M_SIX,
+};
+
+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);
+
#endif /* TRX_SCHEDULER_H */
diff --git a/src/osmo-bts-trx/sched_lchan_pdtch.c b/src/osmo-bts-trx/sched_lchan_pdtch.c
index 259d3364..28a45f58 100644
--- a/src/osmo-bts-trx/sched_lchan_pdtch.c
+++ b/src/osmo-bts-trx/sched_lchan_pdtch.c
@@ -46,17 +46,11 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
uint32_t *first_fn = &chan_state->ul_first_fn;
uint8_t *mask = &chan_state->ul_mask;
- float *rssi_sum = &chan_state->rssi_sum;
- uint8_t *rssi_num = &chan_state->rssi_num;
- int32_t *toa256_sum = &chan_state->toa256_sum;
- uint8_t *toa_num = &chan_state->toa_num;
- int32_t *ci_cb_sum = &chan_state->ci_cb_sum;
- uint8_t *ci_cb_num = &chan_state->ci_cb_num;
+ struct l1sched_meas_set meas_avg;
uint8_t l2[EGPRS_0503_MAX_BYTES];
int n_errors = 0;
int n_bursts_bits = 0;
int n_bits_total = 0;
- int16_t lqual_cb;
uint16_t ber10k;
int rc;
@@ -76,26 +70,13 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
memset(*bursts_p, 0, GSM0503_EGPRS_BURSTS_NBITS);
*mask = 0x0;
*first_fn = bi->fn;
- *rssi_sum = 0;
- *rssi_num = 0;
- *toa256_sum = 0;
- *toa_num = 0;
- *ci_cb_sum = 0;
- *ci_cb_num = 0;
}
- /* update mask + rssi */
+ /* update mask */
*mask |= (1 << bid);
- *rssi_sum += bi->rssi;
- (*rssi_num)++;
- *toa256_sum += bi->toa256;
- (*toa_num)++;
-
- /* C/I: Carrier-to-Interference ratio (in centiBels) */
- if (bi->flags & TRX_BI_F_CI_CB) {
- *ci_cb_sum += bi->ci_cb;
- (*ci_cb_num)++;
- }
+
+ /* store measurements */
+ trx_sched_meas_push(chan_state, bi);
/* copy burst to buffer of 4 bursts */
if (bi->burst_len == EGPRS_BURST_LEN) {
@@ -114,6 +95,9 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
if (bid != 3)
return 0;
+ /* average measurements of the last 4 bursts */
+ trx_sched_meas_avg(chan_state, &meas_avg, SCHED_MEAS_AVG_M_QUAD);
+
/* check for complete set of bursts */
if ((*mask & 0xf) != 0xf) {
LOGL1S(DL1P, LOGL_DEBUG, l1t, bi->tn, chan, bi->fn,
@@ -143,13 +127,11 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
return 0;
}
- lqual_cb = *ci_cb_num ? (*ci_cb_sum / *ci_cb_num) : 0;
ber10k = compute_ber10k(n_bits_total, n_errors);
return _sched_compose_ph_data_ind(l1t, bi->tn,
*first_fn, chan, l2, rc,
- *rssi_sum / *rssi_num,
- *toa256_sum / *toa_num,
- lqual_cb, ber10k,
+ meas_avg.rssi, meas_avg.toa256,
+ meas_avg.ci_cb, ber10k,
PRES_INFO_BOTH);
}
diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c
index d2896203..e29a47e2 100644
--- a/src/osmo-bts-trx/sched_lchan_tchf.c
+++ b/src/osmo-bts-trx/sched_lchan_tchf.c
@@ -56,6 +56,8 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
uint8_t rsl_cmode = chan_state->rsl_cmode;
uint8_t tch_mode = chan_state->tch_mode;
uint8_t tch_data[128]; /* just to be safe */
+ enum sched_meas_avg_mode meas_avg_mode = SCHED_MEAS_AVG_M_OCTO;
+ struct l1sched_meas_set meas_avg;
int rc, amr = 0;
int n_errors = 0;
int n_bits_total = 0;
@@ -89,6 +91,9 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
/* update mask */
*mask |= (1 << bid);
+ /* store measurements */
+ trx_sched_meas_push(chan_state, bi);
+
/* copy burst to end of buffer of 8 bursts */
burst = *bursts_p + bid * 116 + 464;
if (bi->burst_len > 0) {
@@ -194,6 +199,9 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
}
memcpy(*bursts_p, *bursts_p + 464, 464);
+ /* average measurements of the last N (depends on mode) bursts */
+ trx_sched_meas_avg(chan_state, &meas_avg, meas_avg_mode);
+
/* Check if the frame is bad */
if (rc < 0) {
LOGL1S(DL1P, LOGL_NOTICE, l1t, bi->tn, chan, bi->fn,
@@ -219,10 +227,9 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_F);
_sched_compose_ph_data_ind(l1t, bi->tn, fn_begin, chan,
tch_data + amr, GSM_MACBLOCK_LEN,
- /* FIXME: AVG RSSI and ToA256 */
- bi->rssi, bi->toa256,
- 0 /* FIXME: AVG C/I */,
- ber10k, PRES_INFO_UNKNOWN);
+ meas_avg.rssi, meas_avg.toa256,
+ meas_avg.ci_cb, ber10k,
+ PRES_INFO_UNKNOWN);
bfi:
if (rsl_cmode == RSL_CMOD_SPD_SPEECH) {
/* indicate bad frame */
@@ -277,8 +284,10 @@ bfi:
/* TCH or BFI */
compose_l1sap:
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F);
- return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan,
- tch_data, rc, bi->toa256, ber10k, bi->rssi, is_sub);
+ return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan, tch_data, rc,
+ /* FIXME: what should we use for BFI here? */
+ bfi_flag ? bi->toa256 : meas_avg.toa256, ber10k,
+ bfi_flag ? bi->rssi : meas_avg.rssi, is_sub);
}
/* common section for generation of TCH bursts (TCH/H and TCH/F).
@@ -293,9 +302,6 @@ void tx_tch_common(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
uint8_t rsl_cmode = chan_state->rsl_cmode;
uint8_t tch_mode = chan_state->tch_mode;
struct osmo_phsap_prim *l1sap;
- int32_t *toa256_sum = &chan_state->toa256_sum;
- uint8_t *toa_num = &chan_state->toa_num;
- int16_t toa256;
/* handle loss detection of received TCH frames */
if (rsl_cmode == RSL_CMOD_SPD_SPEECH
@@ -343,14 +349,9 @@ inval_mode1:
}
if (len) {
- if (*toa_num == 0)
- toa256 = 0;
- else
- toa256 = *toa256_sum / *toa_num;
-
- /* Note: RSSI is set to 0 to indicate to the higher
+ /* Note: RSSI/ToA256 is set to 0 to indicate to the higher
* layers that this is a faked tch_ind */
- _sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len, toa256, 10000, 0, 0);
+ _sched_compose_tch_ind(l1t, tn, fn, chan, tch_data, len, 0, 10000, 0, 0);
}
}
diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c
index 0281342c..2a561e1e 100644
--- a/src/osmo-bts-trx/sched_lchan_tchh.c
+++ b/src/osmo-bts-trx/sched_lchan_tchh.c
@@ -65,6 +65,8 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
* Even FN ending at: 10,11,19,20,2,3
*/
int fn_is_odd = (((bi->fn + 26 - 10) % 26) >> 2) & 1;
+ enum sched_meas_avg_mode meas_avg_mode = SCHED_MEAS_AVG_M_QUAD;
+ struct l1sched_meas_set meas_avg;
unsigned int fn_begin;
uint16_t ber10k;
uint8_t is_sub = 0;
@@ -94,6 +96,9 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
/* update mask */
*mask |= (1 << bid);
+ /* store measurements */
+ trx_sched_meas_push(chan_state, bi);
+
/* copy burst to end of buffer of 6 bursts */
burst = *bursts_p + bid * 116 + 464;
if (bi->burst_len > 0) {
@@ -208,6 +213,10 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
memcpy(*bursts_p + 232, *bursts_p + 464, 232);
ber10k = compute_ber10k(n_bits_total, n_errors);
+ /* average measurements of the last N (depends on mode) bursts */
+ if (rc == GSM_MACBLOCK_LEN)
+ meas_avg_mode = SCHED_MEAS_AVG_M_SIX;
+ trx_sched_meas_avg(chan_state, &meas_avg, meas_avg_mode);
/* Check if the frame is bad */
if (rc < 0) {
@@ -238,10 +247,9 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_H1);
_sched_compose_ph_data_ind(l1t, bi->tn, fn_begin, chan,
tch_data + amr, GSM_MACBLOCK_LEN,
- /* FIXME: AVG both RSSI and ToA */
- bi->rssi, bi->toa256,
- 0 /* FIXME: AVG C/I */,
- ber10k, PRES_INFO_UNKNOWN);
+ meas_avg.rssi, meas_avg.toa256,
+ meas_avg.ci_cb, ber10k,
+ PRES_INFO_UNKNOWN);
bfi:
/* FIXME: a FACCH/H frame replaces two speech frames,
* so we actually need to send two bad frame indications! */
@@ -301,8 +309,10 @@ compose_l1sap:
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_H0);
else
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_H1);
- return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan,
- tch_data, rc, bi->toa256, ber10k, bi->rssi, is_sub);
+ return _sched_compose_tch_ind(l1t, bi->tn, fn_begin, chan, tch_data, rc,
+ /* FIXME: what should we use for BFI here? */
+ bfi_flag ? bi->toa256 : meas_avg.toa256, ber10k,
+ bfi_flag ? bi->rssi : meas_avg.rssi, is_sub);
}
/* common section for generation of TCH bursts (TCH/H and TCH/F).
diff --git a/src/osmo-bts-trx/sched_lchan_xcch.c b/src/osmo-bts-trx/sched_lchan_xcch.c
index e2670d80..b96bc0bd 100644
--- a/src/osmo-bts-trx/sched_lchan_xcch.c
+++ b/src/osmo-bts-trx/sched_lchan_xcch.c
@@ -43,16 +43,10 @@ int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
uint32_t *first_fn = &chan_state->ul_first_fn;
uint8_t *mask = &chan_state->ul_mask;
- float *rssi_sum = &chan_state->rssi_sum;
- uint8_t *rssi_num = &chan_state->rssi_num;
- int32_t *toa256_sum = &chan_state->toa256_sum;
- uint8_t *toa_num = &chan_state->toa_num;
- int32_t *ci_cb_sum = &chan_state->ci_cb_sum;
- uint8_t *ci_cb_num = &chan_state->ci_cb_num;
uint8_t l2[GSM_MACBLOCK_LEN], l2_len;
+ struct l1sched_meas_set meas_avg;
int n_errors = 0;
int n_bits_total = 0;
- int16_t lqual_cb;
uint16_t ber10k;
int rc;
@@ -76,26 +70,13 @@ int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
memset(*bursts_p, 0, 464);
*mask = 0x0;
*first_fn = bi->fn;
- *rssi_sum = 0;
- *rssi_num = 0;
- *toa256_sum = 0;
- *toa_num = 0;
- *ci_cb_sum = 0;
- *ci_cb_num = 0;
}
- /* update mask + RSSI */
+ /* update mask */
*mask |= (1 << bid);
- *rssi_sum += bi->rssi;
- (*rssi_num)++;
- *toa256_sum += bi->toa256;
- (*toa_num)++;
-
- /* C/I: Carrier-to-Interference ratio (in centiBels) */
- if (bi->flags & TRX_BI_F_CI_CB) {
- *ci_cb_sum += bi->ci_cb;
- (*ci_cb_num)++;
- }
+
+ /* store measurements */
+ trx_sched_meas_push(chan_state, bi);
/* Copy burst to buffer of 4 bursts. If the burst indication contains
* no data, ensure that the buffer does not stay uninitialized */
@@ -110,6 +91,9 @@ int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
if (bid != 3)
return 0;
+ /* average measurements of the last 4 bursts */
+ trx_sched_meas_avg(chan_state, &meas_avg, SCHED_MEAS_AVG_M_QUAD);
+
/* check for complete set of bursts */
if ((*mask & 0xf) != 0xf) {
LOGL1S(DL1P, LOGL_NOTICE, l1t, bi->tn, chan, bi->fn,
@@ -134,13 +118,11 @@ int rx_data_fn(struct l1sched_trx *l1t, enum trx_chan_type chan,
} else
l2_len = GSM_MACBLOCK_LEN;
- lqual_cb = *ci_cb_num ? (*ci_cb_sum / *ci_cb_num) : 0;
ber10k = compute_ber10k(n_bits_total, n_errors);
return _sched_compose_ph_data_ind(l1t, bi->tn, *first_fn,
chan, l2, l2_len,
- *rssi_sum / *rssi_num,
- *toa256_sum / *toa_num,
- lqual_cb, ber10k,
+ meas_avg.rssi, meas_avg.toa256,
+ meas_avg.ci_cb, ber10k,
PRES_INFO_UNKNOWN);
}
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index e79e674c..3921280b 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -473,3 +473,73 @@ void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int ac
else
trx_if_cmd_nohandover(l1h, tn, ss);
}
+
+/* Add a set of UL burst measurements to the history */
+void trx_sched_meas_push(struct l1sched_chan_state *chan_state,
+ const struct trx_ul_burst_ind *bi)
+{
+ unsigned int hist_size = ARRAY_SIZE(chan_state->meas.buf);
+ unsigned int current = chan_state->meas.current;
+
+ chan_state->meas.buf[current] = (struct l1sched_meas_set) {
+ .ci_cb = (bi->flags & TRX_BI_F_CI_CB) ? bi->ci_cb : 0,
+ .toa256 = bi->toa256,
+ .rssi = bi->rssi,
+ };
+
+ chan_state->meas.current = (current + 1) % hist_size;
+}
+
+/* Calculate the AVG of n measurements from the history */
+void trx_sched_meas_avg(const struct l1sched_chan_state *chan_state,
+ struct l1sched_meas_set *avg,
+ enum sched_meas_avg_mode mode)
+{
+ unsigned int hist_size = ARRAY_SIZE(chan_state->meas.buf);
+ unsigned int current = chan_state->meas.current;
+ const struct l1sched_meas_set *set;
+ unsigned int shift, pos, i, n;
+
+ float rssi_sum = 0;
+ int toa256_sum = 0;
+ int ci_cb_sum = 0;
+
+ switch (mode) {
+ /* last 4 bursts (default for xCCH, TCH/H, PTCCH and PDTCH) */
+ case SCHED_MEAS_AVG_M_QUAD:
+ n = 4; shift = n;
+ break;
+ /* last 8 bursts (default for TCH/F and FACCH/F) */
+ case SCHED_MEAS_AVG_M_OCTO:
+ n = 8; shift = n;
+ break;
+ /* last 6 bursts (default for FACCH/H) */
+ case SCHED_MEAS_AVG_M_SIX:
+ n = 6; shift = n;
+ break;
+ default:
+ /* Shall not happen */
+ OSMO_ASSERT(false);
+ }
+
+ /* Calculate the sum of n entries starting from pos */
+ for (i = 0; i < n; i++) {
+ pos = (current + hist_size - shift + i) % hist_size;
+ set = &chan_state->meas.buf[pos];
+
+ rssi_sum += set->rssi;
+ toa256_sum += set->toa256;
+ ci_cb_sum += set->ci_cb;
+ }
+
+ /* Calculate the average for each value */
+ *avg = (struct l1sched_meas_set) {
+ .rssi = (rssi_sum / n),
+ .toa256 = (toa256_sum / n),
+ .ci_cb = (ci_cb_sum / n),
+ };
+
+ LOGP(DL1C, LOGL_DEBUG, "Measurement AVG (num=%u, shift=%u): "
+ "RSSI %f, ToA256 %d, C/I %d cB\n", n, shift,
+ avg->rssi, avg->toa256, avg->ci_cb);
+}