trxcon/scheduler: refactor TDMA frame number calculation

Using TDMA frame number of a burst with bid=0 is fine for xCCH,
but not for TCH and FACCH, because they use the block-diagonel
interleaving. A single block on TCH may be interleaved over
8, 4 or even 6 consecutive bursts depending on its type.

Since we now have the measurement history, we can attach TDMA
frame number to each measurement set, and then look up N-th
one when averaging the measurements in sched_trx_meas_avg().

Change-Id: I9221957297a6154edc1767a0e3753f5ee383173f
This commit is contained in:
Vadim Yanitskiy 2020-03-02 19:07:35 +07:00 committed by laforge
parent b9ab7150bf
commit 8c760f8f05
8 changed files with 33 additions and 46 deletions

View File

@ -137,9 +137,11 @@ int sched_send_dt_ind(struct trx_instance *trx, struct trx_ts *ts,
dl_hdr.chan_nr = lchan_desc->chan_nr | ts->index;
dl_hdr.link_id = lchan_desc->link_id;
dl_hdr.band_arfcn = htons(trx->band_arfcn);
dl_hdr.frame_nr = htonl(lchan->rx_first_fn);
dl_hdr.num_biterr = bit_error_count;
/* sched_trx_meas_avg() gives us TDMA frame number of the first burst */
dl_hdr.frame_nr = htonl(meas->fn);
/* RX level: 0 .. 63 in typical GSM notation (dBm + 110) */
dl_hdr.rx_level = dbm2rxlev(meas->rssi);
@ -154,7 +156,7 @@ int sched_send_dt_ind(struct trx_instance *trx, struct trx_ts *ts,
/* Optional GSMTAP logging */
if (l2_len > 0 && (!traffic || lchan_desc->chan_nr == RSL_CHAN_OSMO_PDCH)) {
sched_gsmtap_send(lchan->type, lchan->rx_first_fn, ts->index,
sched_gsmtap_send(lchan->type, meas->fn, ts->index,
trx->band_arfcn, meas->rssi, 0, l2, l2_len);
}

View File

@ -48,12 +48,10 @@ int rx_pdtch_fn(struct trx_instance *trx, struct trx_ts *ts,
uint8_t l2[GPRS_L2_MAX_LEN], *mask;
int n_errors, n_bits_total, rc;
sbit_t *buffer, *offset;
uint32_t *first_fn;
size_t l2_len;
/* Set up pointers */
lchan_desc = &trx_lchan_desc[lchan->type];
first_fn = &lchan->rx_first_fn;
mask = &lchan->rx_burst_mask;
buffer = lchan->rx_bursts;
@ -61,10 +59,8 @@ int rx_pdtch_fn(struct trx_instance *trx, struct trx_ts *ts,
"fn=%u ts=%u bid=%u\n", lchan_desc->name, fn, ts->index, bid);
/* Reset internal state */
if (bid == 0) {
*first_fn = fn;
if (bid == 0)
*mask = 0x0;
}
/* Update mask */
*mask |= (1 << bid);
@ -88,8 +84,8 @@ int rx_pdtch_fn(struct trx_instance *trx, struct trx_ts *ts,
if ((*mask & 0xf) != 0xf) {
LOGP(DSCHD, LOGL_ERROR, "Received incomplete (%s) data frame at "
"fn=%u (%u/%u) for %s\n",
burst_mask2str(mask, 4), *first_fn,
(*first_fn) % ts->mf_layout->period,
burst_mask2str(mask, 4), lchan->meas_avg.fn,
lchan->meas_avg.fn % ts->mf_layout->period,
ts->mf_layout->period,
lchan_desc->name);
@ -101,8 +97,8 @@ int rx_pdtch_fn(struct trx_instance *trx, struct trx_ts *ts,
NULL, &n_errors, &n_bits_total);
if (rc < 0) {
LOGP(DSCHD, LOGL_ERROR, "Received bad packet data frame "
"at fn=%u (%u/%u) for %s\n", *first_fn,
(*first_fn) % ts->mf_layout->period,
"at fn=%u (%u/%u) for %s\n", lchan->meas_avg.fn,
lchan->meas_avg.fn % ts->mf_layout->period,
ts->mf_layout->period,
lchan_desc->name);
}

View File

@ -50,12 +50,10 @@ int rx_tchf_fn(struct trx_instance *trx, struct trx_ts *ts,
int n_errors = -1, n_bits_total, rc;
sbit_t *buffer, *offset;
uint8_t l2[128], *mask;
uint32_t *first_fn;
size_t l2_len;
/* Set up pointers */
lchan_desc = &trx_lchan_desc[lchan->type];
first_fn = &lchan->rx_first_fn;
mask = &lchan->rx_burst_mask;
buffer = lchan->rx_bursts;
@ -63,10 +61,8 @@ int rx_tchf_fn(struct trx_instance *trx, struct trx_ts *ts,
lchan_desc->name, fn, ts->index, bid);
/* Reset internal state */
if (bid == 0) {
*first_fn = fn;
if (bid == 0)
*mask = 0x00;
}
/* Update mask */
*mask |= (1 << bid);
@ -90,8 +86,8 @@ int rx_tchf_fn(struct trx_instance *trx, struct trx_ts *ts,
if ((*mask & 0xf) != 0xf) {
LOGP(DSCHD, LOGL_ERROR, "Received incomplete (%s) traffic frame at "
"fn=%u (%u/%u) for %s\n",
burst_mask2str(mask, 8), *first_fn,
(*first_fn) % ts->mf_layout->period,
burst_mask2str(mask, 8), lchan->meas_avg.fn,
lchan->meas_avg.fn % ts->mf_layout->period,
ts->mf_layout->period,
lchan_desc->name);
@ -152,6 +148,7 @@ bfi:
/* Didn't try to decode, fake measurements */
if (n_errors < 0) {
lchan->meas_avg = (struct trx_meas_set) {
.fn = lchan->meas_avg.fn,
.toa256 = 0,
.rssi = -110,
};

View File

@ -291,23 +291,19 @@ int rx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts,
/* Check decoding result */
if (rc < 4) {
LOGP(DSCHD, LOGL_ERROR, "Received bad TCH frame (%s) ending at "
"fn=%u on %s (rc=%d)\n", burst_mask2str(mask, 6),
fn, lchan_desc->name, rc);
/* Calculate AVG of the measurements (assuming 4 bursts) */
sched_trx_meas_avg(lchan, 4);
LOGP(DSCHD, LOGL_ERROR, "Received bad TCH frame (%s) "
"at fn=%u on %s (rc=%d)\n", burst_mask2str(mask, 6),
lchan->meas_avg.fn, lchan_desc->name, rc);
/* Send BFI */
goto bfi;
} else if (rc == GSM_MACBLOCK_LEN) {
/* Skip decoding of the next 2 stolen bursts */
lchan->dl_ongoing_facch = true;
/* Calculate TDMA frame number of the first burst */
lchan->rx_first_fn = sched_tchh_block_dl_first_fn(lchan->type,
fn, true); /* FACCH/H */
/* Calculate AVG of the measurements (FACCH/H takes 6 bursts) */
sched_trx_meas_avg(lchan, 6);
@ -326,10 +322,6 @@ int rx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts,
sched_trx_meas_avg(lchan, 4);
}
/* Calculate TDMA frame number of the first burst */
lchan->rx_first_fn = sched_tchh_block_dl_first_fn(lchan->type,
fn, false); /* TCH/H */
/* Send a traffic frame to the higher layers */
return sched_send_dt_ind(trx, ts, lchan, l2, l2_len,
n_errors, false, true);
@ -346,6 +338,7 @@ bfi:
/* Didn't try to decode, fake measurements */
if (n_errors < 0) {
lchan->meas_avg = (struct trx_meas_set) {
.fn = sched_tchh_block_dl_first_fn(lchan->type, fn, false),
.toa256 = 0,
.rssi = -110,
};
@ -354,10 +347,6 @@ bfi:
n_errors = 0;
}
/* Calculate TDMA frame number of the first burst */
lchan->rx_first_fn = sched_tchh_block_dl_first_fn(lchan->type,
fn, false); /* TCH/H */
/* BFI is not applicable in signalling mode */
if (lchan->tch_mode == GSM48_CMODE_SIGN)
return sched_send_dt_ind(trx, ts, lchan, NULL, 0,

View File

@ -48,11 +48,9 @@ int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts,
uint8_t l2[GSM_MACBLOCK_LEN], *mask;
int n_errors, n_bits_total, rc;
sbit_t *buffer, *offset;
uint32_t *first_fn;
/* Set up pointers */
lchan_desc = &trx_lchan_desc[lchan->type];
first_fn = &lchan->rx_first_fn;
mask = &lchan->rx_burst_mask;
buffer = lchan->rx_bursts;
@ -60,10 +58,8 @@ int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts,
lchan_desc->name, fn, ts->index, bid);
/* Reset internal state */
if (bid == 0) {
*first_fn = fn;
if (bid == 0)
*mask = 0x0;
}
/* Update mask */
*mask |= (1 << bid);
@ -87,8 +83,8 @@ int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts,
if ((*mask & 0xf) != 0xf) {
LOGP(DSCHD, LOGL_ERROR, "Received incomplete (%s) data frame at "
"fn=%u (%u/%u) for %s\n",
burst_mask2str(mask, 4), *first_fn,
(*first_fn) % ts->mf_layout->period,
burst_mask2str(mask, 4), lchan->meas_avg.fn,
lchan->meas_avg.fn % ts->mf_layout->period,
ts->mf_layout->period,
lchan_desc->name);
/* NOTE: xCCH has an insane amount of redundancy for error
@ -101,8 +97,8 @@ int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts,
rc = gsm0503_xcch_decode(l2, buffer, &n_errors, &n_bits_total);
if (rc) {
LOGP(DSCHD, LOGL_ERROR, "Received bad data frame at fn=%u "
"(%u/%u) for %s\n", *first_fn,
(*first_fn) % ts->mf_layout->period,
"(%u/%u) for %s\n", lchan->meas_avg.fn,
lchan->meas_avg.fn % ts->mf_layout->period,
ts->mf_layout->period,
lchan_desc->name);

View File

@ -464,7 +464,6 @@ static void sched_trx_reset_lchan(struct trx_lchan_state *lchan)
/* Reset internal state variables */
lchan->rx_burst_mask = 0x00;
lchan->tx_burst_mask = 0x00;
lchan->rx_first_fn = 0;
/* Free burst memory */
talloc_free(lchan->rx_bursts);
@ -747,6 +746,10 @@ void sched_trx_meas_avg(struct trx_lchan_state *lchan, unsigned int n)
toa256_sum += meas->toa256;
rssi_sum += meas->rssi;
/* Do not go below the first burst */
if (i + 1 == n)
break;
if (meas == MEAS_HIST_FIRST(hist))
meas = MEAS_HIST_LAST(hist);
else
@ -756,4 +759,7 @@ void sched_trx_meas_avg(struct trx_lchan_state *lchan, unsigned int n)
/* Calculate the AVG */
lchan->meas_avg.toa256 = toa256_sum / n;
lchan->meas_avg.rssi = rssi_sum / n;
/* As a bonus, store TDMA frame number of the first burst */
lchan->meas_avg.fn = meas->fn;
}

View File

@ -159,6 +159,8 @@ struct trx_multiframe {
};
struct trx_meas_set {
/*! \brief TDMA frame number of the first burst this set belongs to */
uint32_t fn;
/*! \brief ToA256 (Timing of Arrival, 1/256 of a symbol) */
int16_t toa256;
/*! \brief RSSI (Received Signal Strength Indication) */
@ -182,8 +184,6 @@ struct trx_lchan_state {
/*! \brief Burst type: GMSK or 8PSK */
enum trx_burst_type burst_type;
/*! \brief Frame number of first burst */
uint32_t rx_first_fn;
/*! \brief Mask of received bursts */
uint8_t rx_burst_mask;
/*! \brief Mask of transmitted bursts */

View File

@ -600,6 +600,7 @@ static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)
meas = (struct trx_meas_set) {
.toa256 = toa256,
.rssi = rssi,
.fn = fn,
};
/* Poke scheduler */