fixeria has uploaded this change for review.

View Change

osmo-bts-trx: detect half burst filling, filter BER10k

According to 3GPP TS 45.002, section A.2.2, in DTXu mode the MS may
use half burst filling, so that only half of the encoded block is
present. In this case we can still decode a valid L2 frame (partial
SID), but as expected the calulated BER would be around 50%.

Half burst filling for TCH/F can be visualized as follows:

7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | | | | | a | b | c | d | Partial SID (BER ~50%)
+---+---+---+---+---+---+---+---+---+---+---+---+
| | | | | a | b | c | d | e | f | g | h | SID (BER 0%)
+---+---+---+---+---+---+---+---+---+---+---+---+
| a | b | c | d | e | f | g | h | | | | | Partial SID (BER ~50%)
+---+---+---+---+---+---+---+---+---+---+---+---+
|<----------------------------->|
Burst buffer

Half burst filling for TCH/H can be visualized as follows:

7 6 5 4 3 2 1 0
+---+---+---+---+---+---+---+---+
| | | | | a | b | c | d | Partial SID (BER ~50%)
+---+---+---+---+---+---+---+---+
| | | a | b | c | d | | | SID (BER 0%)
+---+---+---+---+---+---+---+---+
| a | b | c | d | | | | | Partial SID (BER ~50%)
+---+---+---+---+---+---+---+---+
|<--------------------->|
Burst buffer

In both cases an empty cell corresponds to a NOPE.ind (missing burst).

We need to detect such cases and fliter out the expected BER of 50%.
This can be achieved by checking completeness of the burst buffer,
in particular by maintaining an additional sliding mask of NOPE.ind.

Change-Id: Ia46d68603292b5c5c65f5c6552494223f10ee813
Related: SYS#5853
---
M include/osmo-bts/scheduler.h
M src/osmo-bts-trx/sched_lchan_tchf.c
M src/osmo-bts-trx/sched_lchan_tchh.c
3 files changed, 77 insertions(+), 1 deletion(-)

git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/59/27559/1
diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index e39315f..ff7c36f 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -101,6 +101,7 @@
sbit_t *ul_bursts_prev;/* previous burst buffer for RX (repeated SACCH) */
uint32_t ul_first_fn; /* fn of first burst */
uint8_t ul_mask; /* mask of received bursts */
+ uint16_t nope_mask; /* mask of received NOPE.ind */

/* loss detection */
uint8_t lost_frames; /* how many L2 frames were lost */
diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c
index 6a9a0f0..e1593e4 100644
--- a/src/osmo-bts-trx/sched_lchan_tchf.c
+++ b/src/osmo-bts-trx/sched_lchan_tchf.c
@@ -45,12 +45,33 @@
#include <sched_utils.h>
#include <loops.h>

+static bool is_partial_sid(const struct gsm_lchan *lchan, uint16_t nope_mask)
+{
+ /* 7 6 5 4 3 2 1 0
+ * +---+---+---+---+---+---+---+---+---+---+---+---+
+ * | | | | | | | | | a | b | c | d | Partial SID (BER ~50%)
+ * +---+---+---+---+---+---+---+---+---+---+---+---+
+ * | | | | | a | b | c | d | e | f | g | h | SID (BER 0%)
+ * +---+---+---+---+---+---+---+---+---+---+---+---+
+ * | a | b | c | d | e | f | g | h | | | | | Partial SID (BER ~50%)
+ * +---+---+---+---+---+---+---+---+---+---+---+---+
+ * |<----------------------------->|
+ * Burst buffer
+ */
+ if (!lchan->tch.dtx.ul_sid)
+ return false;
+ if ((~nope_mask & 0xff) == 0xff)
+ return false;
+ return true;
+}
+
/*! \brief a single TCH/F burst was received by the PHY, process it */
int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
{
struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan];
struct gsm_lchan *lchan = chan_state->lchan;
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
+ uint16_t *nope_mask = &chan_state->nope_mask;
uint8_t *mask = &chan_state->ul_mask;
uint8_t rsl_cmode = chan_state->rsl_cmode;
uint8_t tch_mode = chan_state->tch_mode;
@@ -85,11 +106,15 @@
if (bi->bid == 0) {
memcpy(*bursts_p, *bursts_p + 464, 464);
memset(*bursts_p + 464, 0, 464);
+ *nope_mask = *nope_mask << 4;
*mask = *mask << 4;
}

/* update mask */
*mask |= (1 << bi->bid);
+ /* update NOPE.ind mask */
+ if (bi->flags & TRX_BI_F_NOPE_IND)
+ *nope_mask |= (1 << bi->bid);

/* store measurements */
trx_sched_meas_push(chan_state, bi);
@@ -206,6 +231,8 @@
return -EINVAL;
}

+ ber10k = compute_ber10k(n_bits_total, n_errors);
+
/* 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 */
@@ -221,12 +248,23 @@
"Received bad data (%u/%u) with invalid codec mode %d\n",
bi->fn % l1ts->mf_period, l1ts->mf_period, rc);
bfi_flag = true;
+ } else if (ber10k > 0 && is_partial_sid(lchan, *nope_mask)) {
+ /* In DTXu mode the MS may use half burst filling (see 3GPP TS 45.002,
+ * section A.2.2), so that only half of the encoded block is present.
+ * In this case we can still decode a valid L2 frame (partial SID),
+ * but as expected the calulated BER would be around 50%. */
+ LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi,
+ "Half burst filling detected: mask=0x%04x, ber10k=%d (%d/%d)\n",
+ *nope_mask, ber10k, n_errors, n_bits_total);
+ /* Filter out the expected 50% of BER (+1% to be sure) */
+ if (ber10k < 5100)
+ ber10k = 0;
+ /* TODO: shall we set is_sub=1 for partial SID frames? */
}

if (rc != GSM_MACBLOCK_LEN && lchan->ecu_state)
osmo_ecu_frame_in(lchan->ecu_state, bfi_flag, tch_data, rc);

- ber10k = compute_ber10k(n_bits_total, n_errors);
if (bfi_flag)
goto bfi;

diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c
index 369e35b..36f8abb 100644
--- a/src/osmo-bts-trx/sched_lchan_tchh.c
+++ b/src/osmo-bts-trx/sched_lchan_tchh.c
@@ -45,12 +45,33 @@
#include <sched_utils.h>
#include <loops.h>

+static bool is_partial_sid(const struct gsm_lchan *lchan, uint16_t nope_mask)
+{
+ /* 7 6 5 4 3 2 1 0
+ * +---+---+---+---+---+---+---+---+
+ * | | | | | a | b | c | d | Partial SID (BER ~50%)
+ * +---+---+---+---+---+---+---+---+
+ * | | | a | b | c | d | | | SID (BER 0%)
+ * +---+---+---+---+---+---+---+---+
+ * | a | b | c | d | | | | | Partial SID (BER ~50%)
+ * +---+---+---+---+---+---+---+---+
+ * |<--------------------->|
+ * Burst buffer
+ */
+ if (!lchan->tch.dtx.ul_sid)
+ return false;
+ if ((~nope_mask & 0x3c) == 0x3c)
+ return false;
+ return true;
+}
+
/*! \brief a single TCH/H burst was received by the PHY, process it */
int rx_tchh_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
{
struct l1sched_chan_state *chan_state = &l1ts->chan_state[bi->chan];
struct gsm_lchan *lchan = chan_state->lchan;
sbit_t *burst, **bursts_p = &chan_state->ul_bursts;
+ uint16_t *nope_mask = &chan_state->nope_mask;
uint8_t *mask = &chan_state->ul_mask;
uint8_t rsl_cmode = chan_state->rsl_cmode;
uint8_t tch_mode = chan_state->tch_mode;
@@ -91,11 +112,15 @@
memcpy(*bursts_p, *bursts_p + 232, 232);
memcpy(*bursts_p + 232, *bursts_p + 464, 232);
memset(*bursts_p + 464, 0, 232);
+ *nope_mask = *nope_mask << 2;
*mask = *mask << 2;
}

/* update mask */
*mask |= (1 << bi->bid);
+ /* update NOPE.ind mask */
+ if (bi->flags & TRX_BI_F_NOPE_IND)
+ *nope_mask |= (1 << bi->bid);

/* store measurements */
trx_sched_meas_push(chan_state, bi);
@@ -248,6 +273,18 @@
"Received bad data (%u/%u) with invalid codec mode %d\n",
bi->fn % l1ts->mf_period, l1ts->mf_period, rc);
bfi_flag = true;
+ } else if (ber10k > 0 && is_partial_sid(lchan, *nope_mask)) {
+ /* In DTXu mode the MS may use half burst filling (see 3GPP TS 45.002,
+ * section A.2.2), so that only half of the encoded block is present.
+ * In this case we can still decode a valid L2 frame (partial SID),
+ * but as expected the calulated BER would be around 50%. */
+ LOGL1SB(DL1P, LOGL_DEBUG, l1ts, bi,
+ "Half burst filling detected: mask=0x%04x, ber10k=%d (%d/%d)\n",
+ *nope_mask, ber10k, n_errors, n_bits_total);
+ /* Filter out the expected 50% of BER (+1% to be sure) */
+ if (ber10k < 5100)
+ ber10k = 0;
+ /* TODO: shall we set is_sub=1 for partial SID frames? */
}

if (rc != GSM_MACBLOCK_LEN && lchan->ecu_state)

To view, visit change 27559. To unsubscribe, or for help writing mail filters, visit settings.

Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Change-Id: Ia46d68603292b5c5c65f5c6552494223f10ee813
Gerrit-Change-Number: 27559
Gerrit-PatchSet: 1
Gerrit-Owner: fixeria <vyanitskiy@sysmocom.de>
Gerrit-MessageType: newchange