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:
parent
b9ab7150bf
commit
8c760f8f05
|
@ -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);
|
||||
}
|
||||
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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,
|
||||
};
|
||||
|
|
|
@ -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,
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
Loading…
Reference in New Issue