Move TA & Power Loops further up the stack, take DTXu flag into account

Only once we receive the Measurement Result on L3 from MS we are able to
find out whether DTXu was used, and hence whether SUB or FULL
measurement set should be used.

Let's move all control loops there to have them in one place together,
and have it at a similar level where it would lay if it was to be
implemented in the BSC.

Related: SYS#4917
Change-Id: Ic152473577ff7c33d30b3f4ee7e321fcb523f723
This commit is contained in:
Pau Espin 2021-09-27 18:44:13 +02:00
parent 3871c1ff0c
commit 0468376c53
2 changed files with 50 additions and 34 deletions

View File

@ -52,8 +52,6 @@
#include <osmo-bts/abis.h>
#include <osmo-bts/bts_model.h>
#include <osmo-bts/handover.h>
#include <osmo-bts/power_control.h>
#include <osmo-bts/ta_control.h>
#include <osmo-bts/msg_utils.h>
#include <osmo-bts/pcuif_proto.h>
#include <osmo-bts/cbch.h>
@ -1533,8 +1531,6 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
uint32_t fn;
enum osmo_ph_pres_info_type pr_info = data_ind->pdch_presence_info;
struct gsm_sacch_l1_hdr *l1_hdr;
int8_t ul_rssi;
int16_t ul_ci_cb;
chan_nr = data_ind->chan_nr;
link_id = data_ind->link_id;
@ -1609,16 +1605,6 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
handle_ms_meas_report(lchan, NULL, 0);
radio_link_timeout(lchan, true);
lchan_ms_ta_ctrl(lchan, lchan->ta_ctrl.current, lchan->meas.ms_toa256);
/* If DTx is active on Downlink, use the '-SUB', otherwise '-FULL': */
if (lchan->tch.dtx.dl_active) {
ul_rssi = rxlev2dbm(lchan->meas.ul_res.sub.rx_lev);
ul_ci_cb = lchan->meas.ul_ci_cb_sub;
} else {
ul_rssi = rxlev2dbm(lchan->meas.ul_res.full.rx_lev);
ul_ci_cb = lchan->meas.ul_ci_cb_full;
}
lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, ul_rssi, ul_ci_cb);
}
return -EINVAL;
}
@ -1645,26 +1631,6 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
lchan->meas.l1_info.srr_sro = l1_hdr->srr_sro;
lchan->meas.l1_info.ta = l1_hdr->ta;
lchan->meas.flags |= LC_UL_M_F_L1_VALID;
/* 3GPP TS 45.008 sec 4.2: UL L1 SACCH Header contains TA and
* MS_PWR used "for the last burst of the previous SACCH
* period". Since MS must use the values provided in DL SACCH
* starting at next meas period, the value of the "last burst"
* is actually the value used in the entire meas period. Since
* it contains info about the previous meas period, we want to
* feed the Control Loop with the measurements for the same
* period (the previous one), which is stored in lchan->meas(.ul_res): */
lchan_ms_ta_ctrl(lchan, l1_hdr->ta, lchan->meas.ms_toa256);
/* If DTx is active on Downlink, use the '-SUB', otherwise '-FULL': */
if (lchan->tch.dtx.dl_active) {
ul_rssi = rxlev2dbm(lchan->meas.ul_res.sub.rx_lev);
ul_ci_cb = lchan->meas.ul_ci_cb_sub;
} else {
ul_rssi = rxlev2dbm(lchan->meas.ul_res.full.rx_lev);
ul_ci_cb = lchan->meas.ul_ci_cb_full;
}
lchan_ms_pwr_ctrl(lchan, l1_hdr->ms_pwr, ul_rssi, ul_ci_cb);
lchan_bs_pwr_ctrl(lchan, (const struct gsm48_hdr *) &data[5]);
} else
le = &lchan->lapdm_ch.lapdm_dcch;

View File

@ -10,6 +10,8 @@
#include <osmo-bts/measurement.h>
#include <osmo-bts/scheduler.h>
#include <osmo-bts/rsl.h>
#include <osmo-bts/power_control.h>
#include <osmo-bts/ta_control.h>
/* Tables as per TS 45.008 Section 8.3 */
static const uint8_t ts45008_83_tch_f[] = { 52, 53, 54, 55, 56, 57, 58, 59 };
@ -793,12 +795,60 @@ int handle_ms_meas_report(struct gsm_lchan *lchan, struct gsm48_hdr *gh, unsigne
{
int timing_offset, rc;
struct lapdm_entity *le;
bool dtxu_used;
uint8_t ms_pwr;
uint8_t ms_ta;
int8_t ul_rssi;
int16_t ul_ci_cb;
le = &lchan->lapdm_ch.lapdm_acch;
timing_offset = ms_to_valid(lchan) ? ms_to2rsl(lchan, le) : -1;
rc = rsl_tx_meas_res(lchan, (uint8_t *)gh, len, timing_offset);
/* Run control loops now that we have all the information: */
/* 3GPP TS 45.008 sec 4.2: UL L1 SACCH Header contains TA and
* MS_PWR used "for the last burst of the previous SACCH
* period". Since MS must use the values provided in DL SACCH
* starting at next meas period, the value of the "last burst"
* is actually the value used in the entire meas period. Since
* it contains info about the previous meas period, we want to
* feed the Control Loop with the measurements for the same
* period (the previous one), which is stored in lchan->meas(.ul_res):
*/
if (len == 0) {
dtxu_used = true;
ms_ta = lchan->ta_ctrl.current;
ms_pwr = lchan->ms_power_ctrl.current;
} else {
/* if len!=0, it means we were able to parse L1Header in UL SACCH: */
OSMO_ASSERT(lchan->meas.flags | LC_UL_M_F_L1_VALID);
ms_ta = lchan->meas.l1_info.ta;
ms_pwr = lchan->meas.l1_info.ms_pwr;
switch (gh->msg_type) {
case GSM48_MT_RR_MEAS_REP:
dtxu_used = (len > sizeof(*gh) + 1) && !!(gh->data[0] & 0x40);
break;
case GSM48_MT_RR_EXT_MEAS_REP:
default:
dtxu_used = true; /* FIXME: not implemented */
break;
}
}
if (dtxu_used) {
ul_rssi = rxlev2dbm(lchan->meas.ul_res.sub.rx_lev);
ul_ci_cb = lchan->meas.ul_ci_cb_sub;
} else {
ul_rssi = rxlev2dbm(lchan->meas.ul_res.full.rx_lev);
ul_ci_cb = lchan->meas.ul_ci_cb_full;
}
lchan_ms_ta_ctrl(lchan, ms_ta, lchan->meas.ms_toa256);
lchan_ms_pwr_ctrl(lchan, ms_pwr, ul_rssi, ul_ci_cb);
if (gh)
lchan_bs_pwr_ctrl(lchan, (const struct gsm48_hdr *) gh);
/* Reset state for next iteration */
lchan->meas.res_nr++;
lchan->tch.dtx.dl_active = false;