TA loop: Take into account UL SACCH 'Actual Timing advance' field

First step improving and reworking TA loop:
Move trigger of the loop to similar place done by BS/MS Power Control
Loop, that is, upon receivial of UL SACCH block, which contains
information about the TA used to transmit the block encode in L1SACCH
Header. Hence, from computed received TOA and TA used when transmitting
from the MS, we can infer the desired TA to be used by the MS, which
will send back to it later during DL SACCH block.

The values taken are actually the ones calculated for the previous SACCH
block and stored in lchan->meas.ms_toa256. That's because L1SACCH
contains the TA used for the previous reporting period, similarly to
what's specified for MS Power Control loop (TS 45.008 sec 4.2):
"""
The MS shall confirm the power control level that it is currently employing
in the SACCH L1 header on each uplink  channel. The indicated value shall
be the power control level actually used by the mobile for the last burst
of the  previous SACCH period.
"""
(The reader may observe that currently this is not properly done for MS
Power Control loop when calling lchan_ms_pwr_ctrl(): this is a bug.)

This new method also permits changing TA quicker, since we have more
confidence that the TA we request is aligned with the one used to
transmit, and we don't simply increment/decrement based on the value we
request to transmit.

Related: SYS#5371
Change-Id: I2d0f128c8dcac93ee382283a1c91fca76623b8fc
This commit is contained in:
Pau Espin 2021-09-06 19:00:34 +02:00
parent 494b251109
commit f21b9231dd
5 changed files with 74 additions and 28 deletions

View File

@ -2,4 +2,4 @@
#include <osmo-bts/gsm_data.h>
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan);
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan, uint8_t ms_tx_ta, int16_t toa256);

View File

@ -53,6 +53,7 @@
#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>
@ -1604,6 +1605,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
rsl_tx_meas_res(lchan, NULL, 0, le);
radio_link_timeout(lchan, true);
lchan_ms_ta_ctrl(lchan, lchan->rqd_ta, lchan->meas.ms_toa256);
lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, data_ind->rssi, data_ind->lqual_cb);
}
return -EINVAL;
@ -1632,6 +1634,19 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx,
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);
/* FIXME: lchan_ms_pwr_ctrl() is currently being passed data_ind->lqual_cb, which is wrong because:
* 1- It contains measurement data for 1 SACCH block only, not the average over the entire period
* 2- It contains measurement data for *current* meas period, not *previous* one.
*/
lchan_ms_pwr_ctrl(lchan, l1_hdr->ms_pwr, data_ind->rssi, data_ind->lqual_cb);
lchan_bs_pwr_ctrl(lchan, (const struct gsm48_hdr *) &data[5]);
} else

View File

@ -10,7 +10,6 @@
#include <osmo-bts/measurement.h>
#include <osmo-bts/scheduler.h>
#include <osmo-bts/rsl.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 };
@ -739,11 +738,6 @@ int lchan_meas_check_compute(struct gsm_lchan *lchan, uint32_t fn)
lchan_meas_compute_extended(lchan);
/* Compute new ta_req value. This has to be done here since the value
* in lchan->meas.num_ul_meas together with lchan->meas.ms_toa256
* is needed for the computation. */
lchan_ms_ta_ctrl(lchan);
lchan->meas.num_ul_meas = 0;
/* return 1 to indicate that the computation has been done and the next

View File

@ -1,6 +1,7 @@
/* Loop control for Timing Advance */
/* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
* (C) 2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de>
*
* All Rights Reserved
*
@ -19,6 +20,8 @@
*
*/
/* Related specs: 3GPP TS 45.010 sections 5.5, 5.6 */
#include <osmo-bts/gsm_data.h>
#include <osmo-bts/logging.h>
@ -29,22 +32,60 @@
#define TA_MIN 0
#define TA_MAX 63
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan)
{
int16_t toa256 = lchan->meas.ms_toa256;
/* TODO: make configurable over osmo-bts VTY? Pass it BSC->BTS? */
#define TA_MAX_INC_STEP 1
#define TA_MAX_DEC_STEP 1
if (toa256 < -TOA256_9OPERCENT && lchan->rqd_ta > TA_MIN) {
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
"TOA is too early (%d), now lowering TA from %d to %d\n",
toa256, lchan->rqd_ta, lchan->rqd_ta - 1);
lchan->rqd_ta--;
} else if (toa256 > TOA256_9OPERCENT && lchan->rqd_ta < TA_MAX) {
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
"TOA is too late (%d), now raising TA from %d to %d\n",
toa256, lchan->rqd_ta, lchan->rqd_ta + 1);
lchan->rqd_ta++;
} else
/*! compute the new "Ordered Timing Advance" communicated to the MS and store it in lchan.
* \param lchan logical channel for which to compute (and in which to store) new power value.
* \param[in] ms_tx_ta The TA used by the MS and reported in L1SACCH, see struct gsm_sacch_l1_hdr field "ta".
* \param[in] toa256 Time of Arrival (in 1/256th bits) computed at Rx side
*/
void lchan_ms_ta_ctrl(struct gsm_lchan *lchan, uint8_t ms_tx_ta, int16_t toa256)
{
int16_t new_ta;
/* Shall we skip current block based on configured interval? */
/*TODO: implement P_CON_INTERVAL for TA loop */
int16_t delta_ta = toa256/256;
if (toa256 >= 0) {
if ((toa256 - (256 * delta_ta)) > TOA256_9OPERCENT)
delta_ta++;
if (delta_ta > TA_MAX_INC_STEP)
delta_ta = TA_MAX_INC_STEP;
} else {
if ((toa256 - (256 * delta_ta)) < -TOA256_9OPERCENT)
delta_ta--;
if (delta_ta < -TA_MAX_DEC_STEP)
delta_ta = -TA_MAX_DEC_STEP;
}
new_ta = ms_tx_ta + delta_ta;
/* Make sure new_ta is never negative: */
if (new_ta < TA_MIN)
new_ta = TA_MIN;
/* Don't ask for out of range TA: */
if (new_ta > TA_MAX)
new_ta = TA_MAX;
if (lchan->rqd_ta == (uint8_t)new_ta) {
LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG,
"TOA is correct (%d), keeping current TA of %d\n",
toa256, lchan->rqd_ta);
"Keeping current TA at %u: TOA was %d\n",
lchan->rqd_ta, toa256);
return;
}
LOGPLCHAN(lchan, DLOOP, LOGL_INFO,
"%s TA %u => %u: TOA was too %s (%d)\n",
(uint8_t)new_ta > lchan->rqd_ta ? "Raising" : "Lowering",
lchan->rqd_ta, (uint8_t)new_ta,
(uint8_t)new_ta > lchan->rqd_ta ? "late" : "early",
toa256);
/* store the resulting new TA in the lchan */
lchan->rqd_ta = (uint8_t)new_ta;
}

View File

@ -35,9 +35,6 @@ void lchan_ms_ta_ctrl_test(int16_t toa256_start, unsigned int steps)
uint8_t rqd_ta_before;
int16_t toa256 = toa256_start;
/* Arbitrary value, high enough so that a computation can happen. */
lchan.meas.num_ul_meas = 10;
printf("toa256_start = %u / 256 = %u, steps = %u\n", toa256_start,
toa256_start / 256, steps);
@ -49,8 +46,7 @@ void lchan_ms_ta_ctrl_test(int16_t toa256_start, unsigned int steps)
rqd_ta_before = lchan.rqd_ta;
lchan.meas.ms_toa256 = toa256;
lchan_ms_ta_ctrl(&lchan);
lchan_ms_ta_ctrl(&lchan, rqd_ta_before, toa256);
rqd_ta_after = lchan.rqd_ta;
toa256 -= (rqd_ta_after - rqd_ta_before) * 256;