osmo-bts-trx: rx_{tchf,tchh}_fn(): get TDMA FN from meas history

Once we have an Uplink speech or FACCH frame decoded, we need to
hand it over to the upper layers indicating TDMA frame number of
the *first* burst corresponding to the beginning of a block.

Currently we use libosmogsm's gsm0502_fn_remap() API to calculate
the first TDMA frame number from the given last frame number.
This API involves iterating over the pre-calculated offset tables
for different channel and payload types, and thus imposes some
additional CPU cycles.  Another downside of the current approach
is that we have to perform such lookups several times for each
decoded L2 frame, e.g. for FACCH on TCH/AHS we do it three times!

In this patch I propose an alternative approach of storing TDMA
frame numbers in the measurement history, together with the
associated samples.  This way we can easily get N-th frame number
from there without performing any additional computations, other
than what we already do during the measurement processing.

Change-Id: Id9a2b7b0f1a1ad7cfbbab862faf521e135c90605
This commit is contained in:
Vadim Yanitskiy 2022-03-20 03:22:14 +03:00 committed by fixeria
parent 333e35439d
commit 12b3921a4a
4 changed files with 38 additions and 36 deletions

View File

@ -80,6 +80,7 @@ enum trx_mod_type {
/* A set of measurements belonging to one Uplink burst */
struct l1sched_meas_set {
uint32_t fn; /* TDMA frame number */
int16_t toa256; /* Timing of Arrival (1/256 of a symbol) */
int16_t ci_cb; /* Carrier-to-Interference (cB) */
float rssi; /* RSSI (dBm) */
@ -325,3 +326,5 @@ void trx_sched_meas_push(struct l1sched_chan_state *chan_state,
void trx_sched_meas_avg(const struct l1sched_chan_state *chan_state,
struct l1sched_meas_set *avg,
enum sched_meas_avg_mode mode);
uint32_t trx_sched_lookup_fn(const struct l1sched_chan_state *chan_state,
const unsigned int shift);

View File

@ -131,7 +131,7 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
* the first FN 4,13,21 defines that CMR is included in frame.
* NOTE: A frame ends 7 FN after start.
*/
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F);
fn_begin = trx_sched_lookup_fn(chan_state, 8);
amr_is_cmr = !ul_amr_fn_is_cmi(fn_begin);
/* The AFS_ONSET frame itself does not result into an RTP frame
@ -209,6 +209,8 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
/* average measurements of the last N (depends on mode) bursts */
trx_sched_meas_avg(chan_state, &meas_avg, meas_avg_mode);
/* meas_avg.fn now contains TDMA frame number of the first burst */
fn_begin = meas_avg.fn;
/* Check if the frame is bad */
if (rc < 0) {
@ -231,7 +233,6 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
/* FACCH */
if (rc == GSM_MACBLOCK_LEN) {
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_F);
_sched_compose_ph_data_ind(l1ts, fn_begin, bi->chan,
tch_data + amr, GSM_MACBLOCK_LEN,
meas_avg.rssi, meas_avg.toa256,
@ -300,7 +301,6 @@ bfi:
/* TCH or BFI */
compose_l1sap:
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F);
return _sched_compose_tch_ind(l1ts, fn_begin, bi->chan, tch_data, rc,
meas_avg.toa256, ber10k, meas_avg.rssi,
meas_avg.ci_cb, is_sub);

View File

@ -67,7 +67,6 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
enum sched_meas_avg_mode meas_avg_mode = SCHED_MEAS_AVG_M_S6N4;
struct l1sched_meas_set meas_avg;
unsigned int fn_begin;
unsigned int fn_tch_end;
uint16_t ber10k = 0;
uint8_t is_sub = 0;
uint8_t ft;
@ -127,6 +126,8 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
/* we have already sent the first BFI when a FACCH/H frame
* was decoded (see below), now send the second one. */
trx_sched_meas_avg(chan_state, &meas_avg, meas_avg_mode);
/* meas_avg.fn now contains TDMA frame number of the first burst */
fn_begin = meas_avg.fn;
goto bfi;
}
@ -164,15 +165,15 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
break;
}
/* Calculate the frame number where the block begins */
if (bi->fn % 13 < 4)
fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 5);
else
fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 4);
if (lchan->nr == 0)
fn_begin = gsm0502_fn_remap(fn_tch_end, FN_REMAP_TCH_H0);
else
fn_begin = gsm0502_fn_remap(fn_tch_end, FN_REMAP_TCH_H1);
/* Calculate the frame number where the block begins. Note that
* we need to traverse the measurement histort back by 6 bursts,
* not by 4 bursts. The reason for this is that the burst shift
* buffer we use for decoding is 6 bursts wide (one SACCH block) but
* TCH/H blocks are only 4 bursts wide. The decoder functions look
* at the beginning of the buffer while we shift into it at the end,
* this means that TCH/H blocks always decoded delayed by two frame
* number positions late. */
fn_begin = trx_sched_lookup_fn(chan_state, 6);
fn_is_cmi = ul_amr_fn_is_cmi(fn_begin);
/* See comment in function rx_tchf_fn() */
@ -243,6 +244,8 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
/* average measurements of the last N (depends on mode) bursts */
trx_sched_meas_avg(chan_state, &meas_avg, meas_avg_mode);
/* meas_avg.fn now contains TDMA frame number of the first burst */
fn_begin = meas_avg.fn;
/* Check if the frame is bad */
if (rc < 0) {
@ -265,10 +268,6 @@ int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
/* FACCH */
if (rc == GSM_MACBLOCK_LEN) {
chan_state->ul_ongoing_facch = 1;
if (lchan->nr == 0)
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_H0);
else
fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_FACCH_H1);
/* In order to provide an even stream of measurement reports, here we
* intentionally invalidate RSSI, so that this report gets dropped in
* process_l1sap_meas_data(). The averaged results will still be sent
@ -329,25 +328,6 @@ bfi:
compose_l1sap:
/* TCH or BFI */
/* The input to gsm0502_fn_remap() needs to get the frame number we
* got two bursts ago. The reason for this is that the burst shift
* buffer we use for decoding is 6 bursts wide (one SACCH block) but
* TCH/H blocks are only 4 bursts wide. The decoder functions look
* at the beginning of the buffer while we shift into it at the end,
* this means that TCH/H blocks always decode delayed by two frame
* number positions late. To calculatue the ending frame number of
* the TCH/H we need to subtract 4 or 5 frames if there was a SACCH
* in between. (Note: this is TCH/H, 4 frames ==> 2 bursts) */
if (bi->fn % 13 < 4)
fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 5);
else
fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 4);
if (lchan->nr == 0)
fn_begin = gsm0502_fn_remap(fn_tch_end, FN_REMAP_TCH_H0);
else
fn_begin = gsm0502_fn_remap(fn_tch_end, FN_REMAP_TCH_H1);
return _sched_compose_tch_ind(l1ts, fn_begin, bi->chan, tch_data, rc,
meas_avg.toa256, ber10k, meas_avg.rssi,
meas_avg.ci_cb, is_sub);

View File

@ -623,6 +623,7 @@ void trx_sched_meas_push(struct l1sched_chan_state *chan_state,
unsigned int current = chan_state->meas.current;
chan_state->meas.buf[current] = (struct l1sched_meas_set) {
.fn = bi->fn,
.ci_cb = (bi->flags & TRX_BI_F_CI_CB) ? bi->ci_cb : 0,
.toa256 = bi->toa256,
.rssi = bi->rssi,
@ -669,8 +670,13 @@ void trx_sched_meas_avg(const struct l1sched_chan_state *chan_state,
ci_cb_sum += set->ci_cb;
}
/* First sample contains TDMA frame number of the first burst */
pos = (current + hist_size - shift) % hist_size;
set = &chan_state->meas.buf[pos];
/* Calculate the average for each value */
*avg = (struct l1sched_meas_set) {
.fn = set->fn, /* first burst */
.rssi = (rssi_sum / num),
.toa256 = (toa256_sum / num),
.ci_cb = (ci_cb_sum / num),
@ -682,3 +688,16 @@ void trx_sched_meas_avg(const struct l1sched_chan_state *chan_state,
chan_state->lchan ? " " : "",
num, shift, avg->rssi, avg->toa256, avg->ci_cb);
}
/* Lookup TDMA frame number of the N-th sample in the history */
uint32_t trx_sched_lookup_fn(const struct l1sched_chan_state *chan_state,
const unsigned int shift)
{
const unsigned int hist_size = ARRAY_SIZE(chan_state->meas.buf);
const unsigned int current = chan_state->meas.current;
unsigned int pos;
/* First sample contains TDMA frame number of the first burst */
pos = (current + hist_size - shift) % hist_size;
return chan_state->meas.buf[pos].fn;
}