diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2022-04-12 16:12:41 +0300 |
---|---|---|
committer | fixeria <vyanitskiy@sysmocom.de> | 2022-04-20 12:18:08 +0000 |
commit | 44cb0113cfe5f9002eee868d07c882df8776377a (patch) | |
tree | e5f4aae04a39057b1026155c650c6ece9cc0bb9a | |
parent | cfabf6275e51979526c8b99025c344d3e7be1e8d (diff) |
osmo-bts-trx: use C/I in the AMR link adaptation loop
-rw-r--r-- | include/osmo-bts/scheduler.h | 4 | ||||
-rw-r--r-- | src/common/scheduler.c | 4 | ||||
-rw-r--r-- | src/osmo-bts-trx/amr_loop.c | 81 | ||||
-rw-r--r-- | src/osmo-bts-trx/amr_loop.h | 2 | ||||
-rw-r--r-- | src/osmo-bts-trx/sched_lchan_tchf.c | 5 | ||||
-rw-r--r-- | src/osmo-bts-trx/sched_lchan_tchh.c | 6 |
6 files changed, 53 insertions, 49 deletions
diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h index e39315f4..eab904c8 100644 --- a/include/osmo-bts/scheduler.h +++ b/include/osmo-bts/scheduler.h @@ -114,8 +114,8 @@ 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 */ diff --git a/src/common/scheduler.c b/src/common/scheduler.c index 96189ef2..8ec9ccf0 100644 --- a/src/common/scheduler.c +++ b/src/common/scheduler.c @@ -1185,8 +1185,8 @@ int trx_sched_set_mode(struct gsm_bts_trx_ts *ts, uint8_t chan_nr, uint8_t rsl_c chan_state->dl_ft = initial_id; chan_state->ul_cmr = initial_id; chan_state->dl_cmr = initial_id; - chan_state->ber_sum = 0; - chan_state->ber_num = 0; + chan_state->lqual_cb_sum = 0; + chan_state->lqual_cb_num = 0; } rc = 0; } diff --git a/src/osmo-bts-trx/amr_loop.c b/src/osmo-bts-trx/amr_loop.c index e5c7fec4..5793d03f 100644 --- a/src/osmo-bts-trx/amr_loop.c +++ b/src/osmo-bts-trx/amr_loop.c @@ -1,6 +1,7 @@ /* AMR link adaptation loop (see 3GPP TS 45.009, section 3) */ /* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu> + * (C) 2022 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> * * All Rights Reserved * @@ -32,16 +33,11 @@ #include "amr_loop.h" void trx_loop_amr_input(struct l1sched_chan_state *chan_state, - int n_errors, int n_bits_total) + const struct l1sched_meas_set *meas_set) { - struct gsm_lchan *lchan = chan_state->lchan; - float ber; - - /* calculate BER (Bit Error Ratio) */ - if (n_bits_total == 0) - ber = 1.0; /* 100% BER */ - else - ber = (float) n_errors / (float) n_bits_total; + const struct gsm_lchan *lchan = chan_state->lchan; + const struct amr_multirate_conf *cfg = &lchan->tch.amr_mr; + int lqual_cb = meas_set->ci_cb; /* cB (centibel) */ /* check if loop is enabled */ if (!chan_state->amr_loop) @@ -51,47 +47,54 @@ void trx_loop_amr_input(struct l1sched_chan_state *chan_state, if (chan_state->ul_ft != chan_state->dl_cmr) return; - /* count bit errors */ + /* count per-block C/I samples for further averaging */ if (lchan->type == GSM_LCHAN_TCH_H) { - chan_state->ber_num += 2; - chan_state->ber_sum += (ber + ber); + chan_state->lqual_cb_num += 2; + chan_state->lqual_cb_sum += (lqual_cb + lqual_cb); } else { - chan_state->ber_num++; - chan_state->ber_sum += ber; + chan_state->lqual_cb_num++; + chan_state->lqual_cb_sum += lqual_cb; } /* count frames */ - if (chan_state->ber_num < 48) + if (chan_state->lqual_cb_num < 48) return; - /* calculate average (reuse ber variable) */ - ber = chan_state->ber_sum / chan_state->ber_num; + /* calculate average (reuse lqual_cb variable) */ + lqual_cb = chan_state->lqual_cb_sum / chan_state->lqual_cb_num; - /* reset bit errors */ - chan_state->ber_num = 0; - chan_state->ber_sum = 0; + LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "AMR link quality (C/I) is %d cB, " + "codec mode=%d\n", lqual_cb, chan_state->ul_ft); - LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Current bit error rate (BER) %.6f " - "codec id %d\n", ber, chan_state->ul_ft); + /* reset the link quality measurements */ + chan_state->lqual_cb_num = 0; + chan_state->lqual_cb_sum = 0; - /* degrade */ if (chan_state->dl_cmr > 0) { - /* degrade, if ber is above threshold FIXME: C/I */ - if (ber > - lchan->tch.amr_mr.mode[chan_state->dl_cmr-1].threshold) { - LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Degrading due to BER %.6f " - "from codec id %d to %d\n", ber, chan_state->dl_cmr, - chan_state->dl_cmr - 1); + /* The threshold/hysteresis is in 0.5 dB steps, convert to cB: + * 1dB is 10cB, so 0.5dB is 5cB - this is why we multiply by 5. */ + const int thresh_lower_cb = cfg->mode[chan_state->dl_cmr - 1].threshold * 5; + + /* Degrade if the link quality is below THR_MX_Dn(i - 1) */ + if (lqual_cb < thresh_lower_cb) { + LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Degrading AMR codec mode: " + "%d -> %d due to link quality %d cB < THR_MX_Dn=%d cB\n", + chan_state->dl_cmr, chan_state->dl_cmr - 1, + lqual_cb, thresh_lower_cb); chan_state->dl_cmr--; } } else if (chan_state->dl_cmr < chan_state->codecs - 1) { - /* degrade, if ber is above threshold FIXME: C/I*/ - if (ber < - lchan->tch.amr_mr.mode[chan_state->dl_cmr].threshold - - lchan->tch.amr_mr.mode[chan_state->dl_cmr].hysteresis) { - LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Upgrading due to BER %.6f " - "from codec id %d to %d\n", ber, chan_state->dl_cmr, - chan_state->dl_cmr + 1); + /* The threshold/hysteresis is in 0.5 dB steps, convert to cB: + * 1dB is 10cB, so 0.5dB is 5cB - this is why we multiply by 5. */ + const int thresh_upper_cb = cfg->mode[chan_state->dl_cmr].threshold * 5 \ + + cfg->mode[chan_state->dl_cmr].hysteresis * 5; + + /* Upgrade if the link quality is above THR_MX_Up(i) */ + if (lqual_cb > thresh_upper_cb) { + LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Upgrading AMR codec mode: " + "%d -> %d due to link quality %d cB > THR_MX_Up=%d cB\n", + chan_state->dl_cmr, chan_state->dl_cmr + 1, + lqual_cb, thresh_upper_cb); chan_state->dl_cmr++; } } @@ -102,9 +105,9 @@ void trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop) if (chan_state->amr_loop == loop) return; if (!chan_state->amr_loop) { - /* reset bit errors */ - chan_state->ber_num = 0; - chan_state->ber_sum = 0; + /* reset the link quality measurements */ + chan_state->lqual_cb_num = 0; + chan_state->lqual_cb_sum = 0; } chan_state->amr_loop = loop; diff --git a/src/osmo-bts-trx/amr_loop.h b/src/osmo-bts-trx/amr_loop.h index 85f73fdc..efff76cf 100644 --- a/src/osmo-bts-trx/amr_loop.h +++ b/src/osmo-bts-trx/amr_loop.h @@ -11,6 +11,6 @@ */ void trx_loop_amr_input(struct l1sched_chan_state *chan_state, - int n_errors, int n_bits_total); + const struct l1sched_meas_set *meas_set); void trx_loop_amr_set(struct l1sched_chan_state *chan_state, int loop); diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c index 8ca0961d..fb19dd24 100644 --- a/src/osmo-bts-trx/sched_lchan_tchf.c +++ b/src/osmo-bts-trx/sched_lchan_tchf.c @@ -197,8 +197,6 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) break; } - if (rc) - trx_loop_amr_input(chan_state, n_errors, n_bits_total); /* only good speech frames get rtp header */ if (rc != GSM_MACBLOCK_LEN && rc >= 4) { if (chan_state->amr_last_dtx == AMR_OTHER) { @@ -225,6 +223,9 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) /* meas_avg.fn now contains TDMA frame number of the first burst */ fn_begin = meas_avg.fn; + if (tch_mode == GSM48_CMODE_SPEECH_AMR) + trx_loop_amr_input(chan_state, &meas_avg); + /* Check if the frame is bad */ if (rc < 0) { LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c index e3ce6009..1b4aa40b 100644 --- a/src/osmo-bts-trx/sched_lchan_tchh.c +++ b/src/osmo-bts-trx/sched_lchan_tchh.c @@ -233,9 +233,6 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) break; } - if (rc) - trx_loop_amr_input(chan_state, n_errors, n_bits_total); - /* only good speech frames get rtp header */ if (rc != GSM_MACBLOCK_LEN && rc >= 4) { if (chan_state->amr_last_dtx == AMR_OTHER) { @@ -264,6 +261,9 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi) /* meas_avg.fn now contains TDMA frame number of the first burst */ fn_begin = meas_avg.fn; + if (tch_mode == GSM48_CMODE_SPEECH_AMR) + trx_loop_amr_input(chan_state, &meas_avg); + /* Check if the frame is bad */ if (rc < 0) { LOGL1SB(DL1P, LOGL_NOTICE, l1ts, bi, "Received bad data (%u/%u)\n", |