aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorVadim Yanitskiy <vyanitskiy@sysmocom.de>2022-04-28 01:35:54 +0300
committerVadim Yanitskiy <vyanitskiy@sysmocom.de>2022-05-10 16:49:16 +0300
commit284f16e7d7797391e40f034d36756a0dbcf6cf71 (patch)
tree2c81e01b084e0f301f9e89953e298a8aa4f29f6f
parent991f3f64d930b249037fb12f63113f727f3666a2 (diff)
measurement: fix matching of SUB frames by TDMA FN
3GPP TS 45.008, section 8.3 defines active TDMA frame subsets for TCH channels, which shall always be transmitted even during the silence periods in DTX mode of operation. Each frame number listed in this section corresponds to a single burst. The Uplink measurements always contain TDMA FN of the *first* burst of a block, so it does not make sense to match the given FN against all FNs in the respective subset. Instead, we should match only specific FNs in accordance with the block mapping rules defined in 3GPP TS 45.002, section 7, table 1. In the active subset for TCH/F there is only one *complete* block starting at FN=52. Incomplete blocks {52, 53, 54, 55} and {56, 57, 58, 59} contain only 50% of the useful bits (partial SID) and thus ~50% BER, so we don't treat them as SUB. In the active subsets for TCH/H there are two *complete* blocks for each sub-slot. Their respective first FNs can be efficiently defined in a lookup table (see ts45008_dtx_tchh_fn_map[]). Note that we can use a single lookup table for both sub-slots of TCH/H because their TDMA FNs do not overlap. This patch fixes unexpected SUB-RxQual values > 0 on TCH channels with DTXu enabled and other than AMR (HR, FR, EFR) codec in use. Change-Id: I8cc3a755a8ad4dc564439aab2298c1e97ac0592d Related: SYS#5853
-rw-r--r--src/common/measurement.c54
-rw-r--r--tests/meas/meas_test.c47
2 files changed, 32 insertions, 69 deletions
diff --git a/src/common/measurement.c b/src/common/measurement.c
index aa1f5ae0..82a1cf40 100644
--- a/src/common/measurement.c
+++ b/src/common/measurement.c
@@ -16,10 +16,17 @@
#include <osmo-bts/power_control.h>
#include <osmo-bts/ta_control.h>
-/* Tables as per TS 45.008 Section 8.3 */
-static const uint8_t ts45008_83_tch_f[] = { 52, 53, 54, 55, 56, 57, 58, 59 };
-static const uint8_t ts45008_83_tch_hs0[] = { 0, 2, 4, 6, 52, 54, 56, 58 };
-static const uint8_t ts45008_83_tch_hs1[] = { 14, 16, 18, 20, 66, 68, 70, 72 };
+/* Active TDMA frame subset for TCH/H in DTX mode (see 3GPP TS 45.008 Section 8.3).
+ * This mapping is used to determine if a L2 block starting at the given TDMA FN
+ * belongs to the SUB set and thus shall always be transmitted in DTX mode. */
+static const uint8_t ts45008_dtx_tchh_fn_map[104] = {
+ /* TCH/H(0): 0, 2, 4, 6, 52, 54, 56, 58 */
+ [0] = 1, /* block { 0, 2, 4, 6} */
+ [52] = 1, /* block {52, 54, 56, 58} */
+ /* TCH/H(1): 14, 16, 18, 20, 66, 68, 70, 72 */
+ [14] = 1, /* block {14, 16, 18, 20} */
+ [66] = 1, /* block {66, 68, 70, 72} */
+};
/* In cases where we less measurements than we expect we must assume that we
* just did not receive the block because it was lost due to bad channel
@@ -36,17 +43,6 @@ static const struct bts_ul_meas measurement_dummy = {
.inv_rssi = MEASUREMENT_DUMMY_IRSSI
};
-/* find out if an array contains a given key as element */
-#define ARRAY_CONTAINS(arr, val) array_contains(arr, ARRAY_SIZE(arr), val)
-static bool array_contains(const uint8_t *arr, unsigned int len, uint8_t val) {
- int i;
- for (i = 0; i < len; i++) {
- if (arr[i] == val)
- return true;
- }
- return false;
-}
-
/* Decide if a given frame number is part of the "-SUB" measurements (true) or not (false)
* (this function is only used internally, it is public to call it from unit-tests) */
bool ts45008_83_is_sub(struct gsm_lchan *lchan, uint32_t fn)
@@ -65,7 +61,11 @@ bool ts45008_83_is_sub(struct gsm_lchan *lchan, uint32_t fn)
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
case GSM48_CMODE_SPEECH_EFR:
- if (ARRAY_CONTAINS(ts45008_83_tch_f, fn104))
+ /* Active TDMA frame subset for TCH/F: 52, 53, 54, 55, 56, 57, 58, 59.
+ * There is only one *complete* block in this subset starting at FN=52.
+ * Incomplete blocks {... 52, 53, 54, 55} and {56, 57, 58, 59 ...}
+ * contain only 50% of the useful bits (partial SID) and thus ~50% BER. */
+ if (fn104 == 52)
return true;
break;
case GSM48_CMODE_SIGN:
@@ -81,18 +81,8 @@ bool ts45008_83_is_sub(struct gsm_lchan *lchan, uint32_t fn)
case GSM_LCHAN_TCH_H:
switch (lchan->tch_mode) {
case GSM48_CMODE_SPEECH_V1:
- switch (lchan->nr) {
- case 0:
- if (ARRAY_CONTAINS(ts45008_83_tch_hs0, fn104))
- return true;
- break;
- case 1:
- if (ARRAY_CONTAINS(ts45008_83_tch_hs1, fn104))
- return true;
- break;
- default:
- OSMO_ASSERT(0);
- }
+ if (ts45008_dtx_tchh_fn_map[fn104])
+ return true;
break;
case GSM48_CMODE_SIGN:
/* No DTX allowed; SUB=FULL, therefore measurements at all frame numbers are
@@ -432,16 +422,16 @@ static unsigned int lchan_meas_sub_num_expected(const struct gsm_lchan *lchan)
/* 1 block SACCH, 24 blocks TCH (see note 1) */
return 25;
} else {
- /* 1 block SACCH, 2 blocks TCH */
- return 3;
+ /* 1 block SACCH, 1 block TCH */
+ return 2;
}
case GSM_PCHAN_TCH_H:
if (lchan->tch_mode == GSM48_CMODE_SIGN) {
/* 1 block SACCH, 12 blocks TCH (see ynote 1) */
return 13;
} else {
- /* 1 block SACCH, 4 blocks TCH */
- return 5;
+ /* 1 block SACCH, 2 blocks TCH */
+ return 3;
}
case GSM_PCHAN_SDCCH8_SACCH8C:
case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:
diff --git a/tests/meas/meas_test.c b/tests/meas/meas_test.c
index a3c514b8..4b8aff81 100644
--- a/tests/meas/meas_test.c
+++ b/tests/meas/meas_test.c
@@ -379,44 +379,17 @@ static bool test_ts45008_83_is_sub_is_sub(const struct gsm_lchan *lchan, uint32_
switch (lchan->type) {
case GSM_LCHAN_TCH_F:
- return (fn >= 52 && fn <= 59);
+ /* block {52, 53, 54, 55, 56, 57, 58, 59} */
+ return fn == 52;
case GSM_LCHAN_TCH_H:
- if (lchan->nr == 0) {
- if (fn == 0)
- return true;
- if (fn == 2)
- return true;
- if (fn == 4)
- return true;
- if (fn == 6)
- return true;
- if (fn == 52)
- return true;
- if (fn == 54)
- return true;
- if (fn == 56)
- return true;
- if (fn == 58)
- return true;
- } else if (lchan->nr == 1) {
- if (fn == 14)
- return true;
- if (fn == 16)
- return true;
- if (fn == 18)
- return true;
- if (fn == 20)
- return true;
- if (fn == 66)
- return true;
- if (fn == 68)
- return true;
- if (fn == 70)
- return true;
- if (fn == 72)
- return true;
- } else
- OSMO_ASSERT(false);
+ if (fn == 0) /* H0 block { 0, 2, 4, 6} */
+ return true;
+ if (fn == 52) /* H0 block {52, 54, 56, 58} */
+ return true;
+ if (fn == 14) /* H1 block {14, 16, 18, 20} */
+ return true;
+ if (fn == 66) /* H1 block {66, 68, 70, 72} */
+ return true;
return false;
default:
return false;