diff options
Diffstat (limited to 'src/common/ta_control.c')
-rw-r--r-- | src/common/ta_control.c | 90 |
1 files changed, 71 insertions, 19 deletions
diff --git a/src/common/ta_control.c b/src/common/ta_control.c index ccb60e2b..6fe409a2 100644 --- a/src/common/ta_control.c +++ b/src/common/ta_control.c @@ -1,6 +1,7 @@ /* Loop control for Timing Advance */ /* (C) 2013 by Andreas Eversberg <jolly@eversberg.eu> + * (C) 2021 by sysmocom - s.f.m.c. GmbH <info@sysmocom.de> * * All Rights Reserved * @@ -12,39 +13,90 @@ * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. + * GNU Affero General Public License for more details. * * You should have received a copy of the GNU Affero General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. * */ +/* Related specs: 3GPP TS 45.010 sections 5.5, 5.6 */ + #include <osmo-bts/gsm_data.h> +#include <osmo-bts/bts_trx.h> #include <osmo-bts/logging.h> -/* 90% of one bit duration in 1/256 symbols: 256*0.9 */ -#define TOA256_9OPERCENT 230 +/* 3GPP TS 45.010 sec 5.6.3 Delay assessment error: + * 75% of one bit duration in 1/256 symbols: 256*0.75 */ +#define TOA256_THRESH 192 /* rqd_ta value range */ #define TA_MIN 0 #define TA_MAX 63 -void lchan_ms_ta_ctrl(struct gsm_lchan *lchan) +/* TODO: make configurable over osmo-bts VTY? Pass it BSC->BTS? */ +#define TA_MAX_INC_STEP 2 +#define TA_MAX_DEC_STEP 2 + + +/*! 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 toa256 = lchan->meas.ms_toa256; - - 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 + int16_t new_ta; + /* Shall we skip current block based on configured interval? */ + + /* TA control interval: how many blocks do we skip? */ + if (lchan->ta_ctrl.skip_block_num-- > 0) + return; + + /* Reset the number of SACCH blocks to be skipped: + * ctrl_interval=0 => 0 blocks to skip, + * ctrl_interval=1 => 1 blocks to skip, + * ctrl_interval=2 => 3 blocks to skip, + * so basically ctrl_interval * 2 - 1. */ + lchan->ta_ctrl.skip_block_num = lchan->ts->trx->ta_ctrl_interval * 2 - 1; + + int16_t delta_ta = toa256/256; + if (toa256 >= 0) { + if ((toa256 - (256 * delta_ta)) > TOA256_THRESH) + delta_ta++; + if (delta_ta > TA_MAX_INC_STEP) + delta_ta = TA_MAX_INC_STEP; + } else { + if ((toa256 - (256 * delta_ta)) < -TOA256_THRESH) + 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->ta_ctrl.current == (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->ta_ctrl.current, toa256); + return; + } + + LOGPLCHAN(lchan, DLOOP, LOGL_INFO, + "%s TA %u => %u: TOA was too %s (%d)\n", + (uint8_t)new_ta > lchan->ta_ctrl.current ? "Raising" : "Lowering", + lchan->ta_ctrl.current, (uint8_t)new_ta, + (uint8_t)new_ta > lchan->ta_ctrl.current ? "late" : "early", + toa256); + + /* store the resulting new TA in the lchan */ + lchan->ta_ctrl.current = (uint8_t)new_ta; } |