<p>dexter has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bts/+/25296">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">sched_lchan_tch_x: use functions to determine AMR tranmssion phase<br><br>The AMR transmission phase directly depends on the frame number. The<br>transmission phase is used to tell if a received AMR frame contains a<br>CMI (frame type that is currently used) or CMR (frame type that the<br>receiver should use). codec idfentifer. The formulas in the present<br>implementation seem to be correct but they do not reflect the numbers in<br>the spec very well, nor do they have unit-tests. Lets replace them with<br>more readble functions and test those functions with unit-tests.<br><br>Change-Id: I94a934a6b3b397b4cd0e9da3577325de58814335<br>Related: SYS#5549<br>---<br>M configure.ac<br>M src/osmo-bts-trx/sched_lchan_tchf.c<br>M src/osmo-bts-trx/sched_lchan_tchh.c<br>M src/osmo-bts-trx/sched_utils.h<br>M tests/Makefile.am<br>M tests/testsuite.at<br>6 files changed, 104 insertions(+), 11 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/96/25296/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/configure.ac b/configure.ac</span><br><span>index 1b4c6e7..4f2e889 100644</span><br><span>--- a/configure.ac</span><br><span>+++ b/configure.ac</span><br><span>@@ -411,6 +411,7 @@</span><br><span> tests/tx_power/Makefile</span><br><span> tests/power/Makefile</span><br><span> tests/meas/Makefile</span><br><span style="color: hsl(120, 100%, 40%);">+ tests/amr/Makefile</span><br><span> doc/Makefile</span><br><span> doc/examples/Makefile</span><br><span> doc/manuals/Makefile</span><br><span>diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c</span><br><span>index 00efcf8..c5d60e4 100644</span><br><span>--- a/src/osmo-bts-trx/sched_lchan_tchf.c</span><br><span>+++ b/src/osmo-bts-trx/sched_lchan_tchf.c</span><br><span>@@ -65,6 +65,7 @@</span><br><span> uint16_t ber10k;</span><br><span> uint8_t is_sub = 0;</span><br><span> uint8_t ft;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool amr_is_cmr;</span><br><span> </span><br><span> /* If handover RACH detection is turned on, treat this burst as an Access Burst.</span><br><span> * Handle NOPE.ind as usually to ensure proper Uplink measurement reporting. */</span><br><span>@@ -129,6 +130,8 @@</span><br><span> * the first FN 4,13,21 defines that CMR is included in frame.</span><br><span> * NOTE: A frame ends 7 FN after start.</span><br><span> */</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F);</span><br><span style="color: hsl(120, 100%, 40%);">+ amr_is_cmr = !ul_amr_fn_is_cmi(fn_begin);</span><br><span> </span><br><span> /* The AFS_ONSET frame itself does not result into an RTP frame</span><br><span> * since it only contains a recognition pattern that marks the</span><br><span>@@ -144,8 +147,7 @@</span><br><span> * know this before we actually decode the frame) */</span><br><span> amr = 2;</span><br><span> rc = gsm0503_tch_afs_decode_dtx(tch_data + amr, *bursts_p,</span><br><span style="color: hsl(0, 100%, 40%);">- (((bi->fn + 26 - 7) % 26) >> 2) & 1, chan_state->codec,</span><br><span style="color: hsl(0, 100%, 40%);">- chan_state->codecs, &chan_state->ul_ft,</span><br><span style="color: hsl(120, 100%, 40%);">+ amr_is_cmr, chan_state->codec, chan_state->codecs, &chan_state->ul_ft,</span><br><span> &chan_state->ul_cmr, &n_errors, &n_bits_total, &chan_state->amr_last_dtx);</span><br><span> </span><br><span> /* Tag all frames that are not regular AMR voice frames as</span><br><span>@@ -419,6 +421,7 @@</span><br><span> enum osmo_amr_type ft_codec;</span><br><span> enum osmo_amr_quality bfi;</span><br><span> int8_t sti, cmi;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool amr_is_cmr = !dl_amr_fn_is_cmi(br->fn);</span><br><span> </span><br><span> if (rsl_cmode != RSL_CMOD_SPD_SPEECH) {</span><br><span> LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Dropping speech frame, "</span><br><span>@@ -463,7 +466,7 @@</span><br><span> "Codec (FT = %d) of RTP frame not in list\n", ft_codec);</span><br><span> goto free_bad_msg;</span><br><span> }</span><br><span style="color: hsl(0, 100%, 40%);">- if (fn_is_codec_mode_request(br->fn) && chan_state->dl_ft != ft) {</span><br><span style="color: hsl(120, 100%, 40%);">+ if (amr_is_cmr && chan_state->dl_ft != ft) {</span><br><span> LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Codec (FT = %d) "</span><br><span> " of RTP cannot be changed now, but in next frame\n", ft_codec);</span><br><span> goto free_bad_msg;</span><br><span>@@ -552,7 +555,7 @@</span><br><span> * the first FN 0,8,17 defines that CMR is included in frame.</span><br><span> */</span><br><span> gsm0503_tch_afs_encode(*bursts_p, msg_tch->l2h + 2,</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(br->fn),</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_l2len(msg_tch) - 2, !dl_amr_fn_is_cmi(br->fn),</span><br><span> chan_state->codec, chan_state->codecs,</span><br><span> chan_state->dl_ft,</span><br><span> chan_state->dl_cmr);</span><br><span>diff --git a/src/osmo-bts-trx/sched_lchan_tchh.c b/src/osmo-bts-trx/sched_lchan_tchh.c</span><br><span>index 9402204..2106a67 100644</span><br><span>--- a/src/osmo-bts-trx/sched_lchan_tchh.c</span><br><span>+++ b/src/osmo-bts-trx/sched_lchan_tchh.c</span><br><span>@@ -72,6 +72,7 @@</span><br><span> uint8_t is_sub = 0;</span><br><span> uint8_t ft;</span><br><span> bool mask_stolen_tch_block = false;</span><br><span style="color: hsl(120, 100%, 40%);">+ bool fn_is_cmi;</span><br><span> </span><br><span> /* If handover RACH detection is turned on, treat this burst as an Access Burst.</span><br><span> * Handle NOPE.ind as usually to ensure proper Uplink measurement reporting. */</span><br><span>@@ -164,10 +165,21 @@</span><br><span> break;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Calculate the frame number where the block begins */</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bi->fn % 13 < 4)</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (lchan->nr == 0)</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_begin = gsm0502_fn_remap(fn_tch_end, FN_REMAP_TCH_H0);</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_begin = gsm0502_fn_remap(fn_tch_end, FN_REMAP_TCH_H1);</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_is_cmi = ul_amr_fn_is_cmi(fn_begin);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* See comment in function rx_tchf_fn() */</span><br><span> amr = 2;</span><br><span> rc = gsm0503_tch_ahs_decode_dtx(tch_data + amr, *bursts_p,</span><br><span style="color: hsl(0, 100%, 40%);">- fn_is_odd, fn_is_odd, chan_state->codec,</span><br><span style="color: hsl(120, 100%, 40%);">+ fn_is_odd, !fn_is_cmi, chan_state->codec,</span><br><span> chan_state->codecs, &chan_state->ul_ft,</span><br><span> &chan_state->ul_cmr, &n_errors, &n_bits_total, &chan_state->amr_last_dtx);</span><br><span> </span><br><span>@@ -343,7 +355,6 @@</span><br><span> fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 5);</span><br><span> else</span><br><span> fn_tch_end = GSM_TDMA_FN_SUB(bi->fn, 4);</span><br><span style="color: hsl(0, 100%, 40%);">- </span><br><span> if (lchan->nr == 0)</span><br><span> fn_begin = gsm0502_fn_remap(fn_tch_end, FN_REMAP_TCH_H0);</span><br><span> else</span><br><span>@@ -441,7 +452,7 @@</span><br><span> * in frame, the first FN 0,8,17 or 1,9,18 defines that CMR is</span><br><span> * included in frame. */</span><br><span> gsm0503_tch_ahs_encode(*bursts_p, msg_tch->l2h + 2,</span><br><span style="color: hsl(0, 100%, 40%);">- msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(br->fn),</span><br><span style="color: hsl(120, 100%, 40%);">+ msgb_l2len(msg_tch) - 2, !dl_amr_fn_is_cmi(br->fn),</span><br><span> chan_state->codec, chan_state->codecs,</span><br><span> chan_state->dl_ft,</span><br><span> chan_state->dl_cmr);</span><br><span>diff --git a/src/osmo-bts-trx/sched_utils.h b/src/osmo-bts-trx/sched_utils.h</span><br><span>index 4a1aaf5..ada6146 100644</span><br><span>--- a/src/osmo-bts-trx/sched_utils.h</span><br><span>+++ b/src/osmo-bts-trx/sched_utils.h</span><br><span>@@ -23,6 +23,8 @@</span><br><span> </span><br><span> #include <stdint.h></span><br><span> #include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <osmo-bts/scheduler.h></span><br><span> </span><br><span> extern void *tall_bts_ctx;</span><br><span> </span><br><span>@@ -35,8 +37,78 @@</span><br><span> return 10000 * n_errors / n_bits_total;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* determine if the FN is transmitting a CMR (1) or not (0) */</span><br><span style="color: hsl(0, 100%, 40%);">-static inline int fn_is_codec_mode_request(uint32_t fn)</span><br><span style="color: hsl(120, 100%, 40%);">+/*! determine the whether an uplink AMR block is CMI according to 3GPP TS 45.009.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] fn_begin frame number of the beginning of the block.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns true in case of CMI; false otherwise. */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool ul_amr_fn_is_cmi(uint32_t fn_begin)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">- return (((fn + 4) % 26) >> 2) & 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t fn_26 = fn_begin % 26;</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (fn_26) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! See also: 3GPP TS 45.009, section 3.2.1.3 Transmitter/Receiver Synchronisation */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 0 and AFS: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 8:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 17:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 1: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 9:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 18:</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Complementary values for sanity check */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 0 and AFS: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 13:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 21:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 1: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 5:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 14:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 22:</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1P, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "uplink frame number fn_begin=%u does not mark the beginning of a voice block!\n", fn_begin);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(false);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! determine the whether a downlink AMR block is CMI according to 3GPP TS 45.009.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \param[in] fn_begin frame number of the beginning of the block.</span><br><span style="color: hsl(120, 100%, 40%);">+ * \returns true in case of CMI; false otherwise. */</span><br><span style="color: hsl(120, 100%, 40%);">+static inline bool dl_amr_fn_is_cmi(uint32_t fn_begin)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint32_t fn_26 = fn_begin % 26;</span><br><span style="color: hsl(120, 100%, 40%);">+ switch (fn_26) {</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! See also: 3GPP TS 45.009, section 3.2.1.3 Transmitter/Receiver Synchronisation */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 0 and AFS: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 4:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 13:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 21:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 1: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 5:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 14:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 22:</span><br><span style="color: hsl(120, 100%, 40%);">+ return true;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Complementary values for sanity check */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 0 and AFS: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 8:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 17:</span><br><span style="color: hsl(120, 100%, 40%);">+ /* valid for AHS subslot 1: */</span><br><span style="color: hsl(120, 100%, 40%);">+ case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 9:</span><br><span style="color: hsl(120, 100%, 40%);">+ case 18:</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ default:</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DL1P, LOGL_DEBUG,</span><br><span style="color: hsl(120, 100%, 40%);">+ "downlink frame number fn_begin=%u does not mark the beginning of a voice block!\n", fn_begin);</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(false);</span><br><span style="color: hsl(120, 100%, 40%);">+ return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ break;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span> }</span><br><span>diff --git a/tests/Makefile.am b/tests/Makefile.am</span><br><span>index 8d19e6e..a1d04a7 100644</span><br><span>--- a/tests/Makefile.am</span><br><span>+++ b/tests/Makefile.am</span><br><span>@@ -1,4 +1,4 @@</span><br><span style="color: hsl(0, 100%, 40%);">-SUBDIRS = paging cipher agch misc handover tx_power power meas ta_control</span><br><span style="color: hsl(120, 100%, 40%);">+SUBDIRS = paging cipher agch misc handover tx_power power meas ta_control amr</span><br><span> </span><br><span> if ENABLE_SYSMOBTS</span><br><span> SUBDIRS += sysmobts</span><br><span>diff --git a/tests/testsuite.at b/tests/testsuite.at</span><br><span>index ba5a409..f2d17fb 100644</span><br><span>--- a/tests/testsuite.at</span><br><span>+++ b/tests/testsuite.at</span><br><span>@@ -63,3 +63,9 @@</span><br><span> cat $abs_srcdir/ta_control/ta_control_test.ok > expout</span><br><span> AT_CHECK([$abs_top_builddir/tests/ta_control/ta_control_test], [], [expout], [ignore])</span><br><span> AT_CLEANUP</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+AT_SETUP([amr])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_KEYWORDS([amr])</span><br><span style="color: hsl(120, 100%, 40%);">+cat $abs_srcdir/amr/amr_test.ok > expout</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CHECK([$abs_top_builddir/tests/amr/amr_test], [], [expout], [ignore])</span><br><span style="color: hsl(120, 100%, 40%);">+AT_CLEANUP</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bts/+/25296">change 25296</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bts/+/25296"/><meta itemprop="name" content="View Change"/></div></div>
<div style="display:none"> Gerrit-Project: osmo-bts </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I94a934a6b3b397b4cd0e9da3577325de58814335 </div>
<div style="display:none"> Gerrit-Change-Number: 25296 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>