<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/10459">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">trxcon/scheduler: introduce TCH/H TDMA frame mapping helpres<br><br>Unlike xCCH, TCH/H channels are using block diagonal interleaving,<br>so every single burst carries 57 bits of one traffic frame, and 57<br>bits of another one. Moreover, unlike TCH/F where both traffic<br>and FACCH/F frames are interleaved over 8 bursts, a FACCH/H is<br>interleaved over 6 bursts, while a traffic frame is interleaved<br>over 4 bursts.<br><br>This is why a TCH/H burst transmission can't be initiated on<br>an arbitrary TDMA frame number. It shall be aligned as of<br>stated in GSM 05.02, clause 7, table 1.<br><br>This change introduces two basic functions:<br><br>  - sched_tchh_block_map_fn - checks if a TCH/H block transmission<br>    can be initiated / finished on a given frame number<br>    and a given channel type;<br><br>  - sched_tchh_block_dl_first_fn - calculates TDMA frame number of<br>    the first burst using given frame number of the last burst;<br><br>and some auxiliary wrappers to simplify the usage of<br>sched_tchh_block_map_fn().<br><br>Change-Id: Iaf4cb33f1b79df23f8a90c8b14ebe0cd9907fbb9<br>---<br>M src/host/trxcon/Makefile.am<br>A src/host/trxcon/sched_lchan_tchh.c<br>M src/host/trxcon/sched_prim.c<br>M src/host/trxcon/sched_trx.h<br>M src/host/trxcon/scheduler.h<br>5 files changed, 207 insertions(+), 16 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/host/trxcon/Makefile.am b/src/host/trxcon/Makefile.am</span><br><span>index c9cc170..7095cb5 100644</span><br><span>--- a/src/host/trxcon/Makefile.am</span><br><span>+++ b/src/host/trxcon/Makefile.am</span><br><span>@@ -35,6 +35,7 @@</span><br><span>   sched_lchan_desc.c \</span><br><span>         sched_lchan_xcch.c \</span><br><span>         sched_lchan_tchf.c \</span><br><span style="color: hsl(120, 100%, 40%);">+  sched_lchan_tchh.c \</span><br><span>         sched_lchan_rach.c \</span><br><span>         sched_lchan_sch.c \</span><br><span>  sched_mframe.c \</span><br><span>diff --git a/src/host/trxcon/sched_lchan_tchh.c b/src/host/trxcon/sched_lchan_tchh.c</span><br><span>new file mode 100644</span><br><span>index 0000000..316f995</span><br><span>--- /dev/null</span><br><span>+++ b/src/host/trxcon/sched_lchan_tchh.c</span><br><span>@@ -0,0 +1,183 @@</span><br><span style="color: hsl(120, 100%, 40%);">+/*</span><br><span style="color: hsl(120, 100%, 40%);">+ * OsmocomBB <-> SDR connection bridge</span><br><span style="color: hsl(120, 100%, 40%);">+ * TDMA scheduler: handlers for DL / UL bursts on logical channels</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * All Rights Reserved</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is free software; you can redistribute it and/or modify</span><br><span style="color: hsl(120, 100%, 40%);">+ * it under the terms of the GNU General Public License as published by</span><br><span style="color: hsl(120, 100%, 40%);">+ * the Free Software Foundation; either version 2 of the License, or</span><br><span style="color: hsl(120, 100%, 40%);">+ * (at your option) any later version.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * This program is distributed in the hope that it will be useful,</span><br><span style="color: hsl(120, 100%, 40%);">+ * but WITHOUT ANY WARRANTY; without even the implied warranty of</span><br><span style="color: hsl(120, 100%, 40%);">+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the</span><br><span style="color: hsl(120, 100%, 40%);">+ * GNU General Public License for more details.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * You should have received a copy of the GNU General Public License along</span><br><span style="color: hsl(120, 100%, 40%);">+ * with this program; if not, write to the Free Software Foundation, Inc.,</span><br><span style="color: hsl(120, 100%, 40%);">+ * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.</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%);">+#include <errno.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#include "scheduler.h"</span><br><span style="color: hsl(120, 100%, 40%);">+#include "sched_trx.h"</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static const uint8_t tch_h0_traffic_block_map[3][4] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  /* B0(0,2,4,6), B1(4,6,8,10), B2(8,10,0,2) */</span><br><span style="color: hsl(120, 100%, 40%);">+ { 0, 2, 4, 6 },</span><br><span style="color: hsl(120, 100%, 40%);">+       { 4, 6, 8, 10 },</span><br><span style="color: hsl(120, 100%, 40%);">+      { 8, 10, 0, 2 },</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%);">+static const uint8_t tch_h1_traffic_block_map[3][4] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       /* B0(1,3,5,7), B1(5,7,9,11), B2(9,11,1,3) */</span><br><span style="color: hsl(120, 100%, 40%);">+ { 1, 3, 5, 7 },</span><br><span style="color: hsl(120, 100%, 40%);">+       { 5, 7, 9, 11 },</span><br><span style="color: hsl(120, 100%, 40%);">+      { 9, 11, 1, 3 },</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%);">+static const uint8_t tch_h0_dl_facch_block_map[3][6] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* B0(4,6,8,10,13,15), B1(13,15,17,19,21,23), B2(21,23,0,2,4,6) */</span><br><span style="color: hsl(120, 100%, 40%);">+    { 4, 6, 8, 10, 13, 15 },</span><br><span style="color: hsl(120, 100%, 40%);">+      { 13, 15, 17, 19, 21, 23 },</span><br><span style="color: hsl(120, 100%, 40%);">+   { 21, 23, 0, 2, 4, 6 },</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%);">+static const uint8_t tch_h0_ul_facch_block_map[3][6] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       /* B0(0,2,4,6,8,10), B1(8,10,13,15,17,19), B2(17,19,21,23,0,2) */</span><br><span style="color: hsl(120, 100%, 40%);">+     { 0, 2, 4, 6, 8, 10 },</span><br><span style="color: hsl(120, 100%, 40%);">+        { 8, 10, 13, 15, 17, 19 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { 17, 19, 21, 23, 0, 2 },</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%);">+static const uint8_t tch_h1_dl_facch_block_map[3][6] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     /* B0(5,7,9,11,14,16), B1(14,16,18,20,22,24), B2(22,24,1,3,5,7) */</span><br><span style="color: hsl(120, 100%, 40%);">+    { 5, 7, 9, 11, 14, 16 },</span><br><span style="color: hsl(120, 100%, 40%);">+      { 14, 16, 18, 20, 22, 24 },</span><br><span style="color: hsl(120, 100%, 40%);">+   { 22, 24, 1, 3, 5, 7 },</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%);">+const uint8_t tch_h1_ul_facch_block_map[3][6] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* B0(1,3,5,7,9,11), B1(9,11,14,16,18,20), B2(18,20,22,24,1,3) */</span><br><span style="color: hsl(120, 100%, 40%);">+     { 1, 3, 5, 7, 9, 11 },</span><br><span style="color: hsl(120, 100%, 40%);">+        { 9, 11, 14, 16, 18, 20 },</span><br><span style="color: hsl(120, 100%, 40%);">+    { 18, 20, 22, 24, 1, 3 },</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%);">+ * Can a TCH/H block transmission be initiated / finished</span><br><span style="color: hsl(120, 100%, 40%);">+ * on a given frame number and a given channel type?</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See GSM 05.02, clause 7, table 1</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  chan   channel type (TRXC_TCHH_0 or TRXC_TCHH_1)</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  fn     the current frame number</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  ul     Uplink or Downlink?</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  facch  FACCH/H or traffic?</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  start  init or end of transmission?</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return        true (yes) or false (no)</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+bool sched_tchh_block_map_fn(enum trx_lchan_type chan,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t fn, bool ul, bool facch, bool start)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t fn_mf;</span><br><span style="color: hsl(120, 100%, 40%);">+        int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Just to be sure */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(chan == TRXC_TCHH_0 || chan == TRXC_TCHH_1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Calculate a modulo */</span><br><span style="color: hsl(120, 100%, 40%);">+      fn_mf = facch ? (fn % 26) : (fn % 13);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAP_GET_POS(map) \</span><br><span style="color: hsl(120, 100%, 40%);">+  (start ? 0 : ARRAY_SIZE(map[i]) - 1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_MAP_FN(map) \</span><br><span style="color: hsl(120, 100%, 40%);">+   do { \</span><br><span style="color: hsl(120, 100%, 40%);">+                if (map[i][MAP_GET_POS(map)] == fn_mf) \</span><br><span style="color: hsl(120, 100%, 40%);">+                      return true; \</span><br><span style="color: hsl(120, 100%, 40%);">+        } while (++i < ARRAY_SIZE(map))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Choose a proper block map */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (facch) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (ul) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     if (chan == TRXC_TCHH_0)</span><br><span style="color: hsl(120, 100%, 40%);">+                              BLOCK_MAP_FN(tch_h0_ul_facch_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+                      else</span><br><span style="color: hsl(120, 100%, 40%);">+                          BLOCK_MAP_FN(tch_h1_ul_facch_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+              } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      if (chan == TRXC_TCHH_0)</span><br><span style="color: hsl(120, 100%, 40%);">+                              BLOCK_MAP_FN(tch_h0_dl_facch_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+                      else</span><br><span style="color: hsl(120, 100%, 40%);">+                          BLOCK_MAP_FN(tch_h1_dl_facch_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+              }</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (chan == TRXC_TCHH_0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      BLOCK_MAP_FN(tch_h0_traffic_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+               else</span><br><span style="color: hsl(120, 100%, 40%);">+                  BLOCK_MAP_FN(tch_h1_traffic_block_map);</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%);">+   return false;</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%);">+ * Calculates a frame number of the first burst</span><br><span style="color: hsl(120, 100%, 40%);">+ * using given frame number of the last burst.</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * See GSM 05.02, clause 7, table 1</span><br><span style="color: hsl(120, 100%, 40%);">+ *</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  chan      channel type (TRXC_TCHH_0 or TRXC_TCHH_1)</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  last_fn   frame number of the last burst</span><br><span style="color: hsl(120, 100%, 40%);">+ * @param  facch     FACCH/H or traffic?</span><br><span style="color: hsl(120, 100%, 40%);">+ * @return           either frame number of the first burst,</span><br><span style="color: hsl(120, 100%, 40%);">+ *                   or fn=last_fn if calculation failed</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t sched_tchh_block_dl_first_fn(enum trx_lchan_type chan,</span><br><span style="color: hsl(120, 100%, 40%);">+    uint32_t last_fn, bool facch)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      uint8_t fn_mf, fn_diff;</span><br><span style="color: hsl(120, 100%, 40%);">+       int i = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Just to be sure */</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_ASSERT(chan == TRXC_TCHH_0 || chan == TRXC_TCHH_1);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Calculate a modulo */</span><br><span style="color: hsl(120, 100%, 40%);">+      fn_mf = facch ? (last_fn % 26) : (last_fn % 13);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define BLOCK_FIRST_FN(map) \</span><br><span style="color: hsl(120, 100%, 40%);">+     do { \</span><br><span style="color: hsl(120, 100%, 40%);">+                if (map[i][ARRAY_SIZE(map[i]) - 1] == fn_mf) { \</span><br><span style="color: hsl(120, 100%, 40%);">+                      fn_diff = TDMA_FN_DIFF(fn_mf, map[i][0]); \</span><br><span style="color: hsl(120, 100%, 40%);">+                   return TDMA_FN_SUB(last_fn, fn_diff); \</span><br><span style="color: hsl(120, 100%, 40%);">+               } \</span><br><span style="color: hsl(120, 100%, 40%);">+   } while (++i < ARRAY_SIZE(map))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Choose a proper block map */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (facch) {</span><br><span style="color: hsl(120, 100%, 40%);">+          if (chan == TRXC_TCHH_0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      BLOCK_FIRST_FN(tch_h0_dl_facch_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+            else</span><br><span style="color: hsl(120, 100%, 40%);">+                  BLOCK_FIRST_FN(tch_h1_dl_facch_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+    } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              if (chan == TRXC_TCHH_0)</span><br><span style="color: hsl(120, 100%, 40%);">+                      BLOCK_FIRST_FN(tch_h0_traffic_block_map);</span><br><span style="color: hsl(120, 100%, 40%);">+             else</span><br><span style="color: hsl(120, 100%, 40%);">+                  BLOCK_FIRST_FN(tch_h1_traffic_block_map);</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%);">+   LOGP(DSCHD, LOGL_ERROR, "Failed to calculate TDMA "</span><br><span style="color: hsl(120, 100%, 40%);">+         "frame number of the first burst of %s block, "</span><br><span style="color: hsl(120, 100%, 40%);">+             "using the current fn=%u\n", facch ?</span><br><span style="color: hsl(120, 100%, 40%);">+                        "FACCH/H" : "TCH/H", last_fn);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Couldn't calculate the first fn, return the last */</span><br><span style="color: hsl(120, 100%, 40%);">+    return last_fn;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/host/trxcon/sched_prim.c b/src/host/trxcon/sched_prim.c</span><br><span>index e663bc3..6b160d1 100644</span><br><span>--- a/src/host/trxcon/sched_prim.c</span><br><span>+++ b/src/host/trxcon/sched_prim.c</span><br><span>@@ -248,23 +248,10 @@</span><br><span> {</span><br><span>         struct trx_ts_prim *facch;</span><br><span>   struct trx_ts_prim *tch;</span><br><span style="color: hsl(0, 100%, 40%);">-        bool facch_now = false;</span><br><span style="color: hsl(0, 100%, 40%);">- uint32_t fn_mf;</span><br><span style="color: hsl(120, 100%, 40%);">+       bool facch_now;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     /* Traffic multiframe period */</span><br><span style="color: hsl(0, 100%, 40%);">- fn_mf = fn % 26;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-        /* FACCH/H0 frame alignment */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (lchan_type == TRXC_TCHH_0)</span><br><span style="color: hsl(0, 100%, 40%);">-          if (fn_mf == 0 || fn_mf == 8 || fn_mf == 17)</span><br><span style="color: hsl(0, 100%, 40%);">-                    facch_now = true;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* FACCH/H1 frame alignment */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (lchan_type == TRXC_TCHH_1)</span><br><span style="color: hsl(0, 100%, 40%);">-          if (fn_mf == 1 || fn_mf == 9 || fn_mf == 18)</span><br><span style="color: hsl(0, 100%, 40%);">-                    facch_now = true;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-       /* If FACCH/H is not allowed for a given frame number */</span><br><span style="color: hsl(120, 100%, 40%);">+      /* May we initiate an UL FACCH/H frame transmission now? */</span><br><span style="color: hsl(120, 100%, 40%);">+   facch_now = sched_tchh_facch_start(lchan_type, fn, true);</span><br><span>    if (!facch_now) /* Just dequeue a TCH/H prim */</span><br><span>              goto no_facch;</span><br><span> </span><br><span>diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h</span><br><span>index 730923b..2c8b4d8 100644</span><br><span>--- a/src/host/trxcon/sched_trx.h</span><br><span>+++ b/src/host/trxcon/sched_trx.h</span><br><span>@@ -323,3 +323,19 @@</span><br><span>   int bit_error_count, bool dec_failed, bool traffic);</span><br><span> int sched_send_dt_conf(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>  struct trx_lchan_state *lchan, uint32_t fn, bool traffic);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Interleaved TCH/H block TDMA frame mapping */</span><br><span style="color: hsl(120, 100%, 40%);">+uint32_t sched_tchh_block_dl_first_fn(enum trx_lchan_type chan,</span><br><span style="color: hsl(120, 100%, 40%);">+       uint32_t last_fn, bool facch);</span><br><span style="color: hsl(120, 100%, 40%);">+bool sched_tchh_block_map_fn(enum trx_lchan_type chan,</span><br><span style="color: hsl(120, 100%, 40%);">+        uint32_t fn, bool ul, bool facch, bool start);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define sched_tchh_traffic_start(chan, fn, ul) \</span><br><span style="color: hsl(120, 100%, 40%);">+    sched_tchh_block_map_fn(chan, fn, ul, 0, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+#define sched_tchh_traffic_end(chan, fn, ul) \</span><br><span style="color: hsl(120, 100%, 40%);">+   sched_tchh_block_map_fn(chan, fn, ul, 0, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define sched_tchh_facch_start(chan, fn, ul) \</span><br><span style="color: hsl(120, 100%, 40%);">+ sched_tchh_block_map_fn(chan, fn, ul, 1, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+#define sched_tchh_facch_end(chan, fn, ul) \</span><br><span style="color: hsl(120, 100%, 40%);">+     sched_tchh_block_map_fn(chan, fn, ul, 1, 0)</span><br><span>diff --git a/src/host/trxcon/scheduler.h b/src/host/trxcon/scheduler.h</span><br><span>index fccf7d2..7ab17ab 100644</span><br><span>--- a/src/host/trxcon/scheduler.h</span><br><span>+++ b/src/host/trxcon/scheduler.h</span><br><span>@@ -17,6 +17,10 @@</span><br><span>    ((a + GSM_HYPERFRAME - b) % GSM_HYPERFRAME)</span><br><span> #define TDMA_FN_INC(fn) \</span><br><span>     TDMA_FN_SUM(fn, 1)</span><br><span style="color: hsl(120, 100%, 40%);">+#define TDMA_FN_MIN(a, b) \</span><br><span style="color: hsl(120, 100%, 40%);">+       (a < b ? a : b)</span><br><span style="color: hsl(120, 100%, 40%);">+#define TDMA_FN_DIFF(a, b) \</span><br><span style="color: hsl(120, 100%, 40%);">+      TDMA_FN_MIN(TDMA_FN_SUB(a, b), TDMA_FN_SUB(b, a))</span><br><span> </span><br><span> enum tdma_sched_clck_state {</span><br><span>        SCH_CLCK_STATE_WAIT,</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10459">change 10459</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/10459"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: merged </div>
<div style="display:none"> Gerrit-Change-Id: Iaf4cb33f1b79df23f8a90c8b14ebe0cd9907fbb9 </div>
<div style="display:none"> Gerrit-Change-Number: 10459 </div>
<div style="display:none"> Gerrit-PatchSet: 3 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: Vadim Yanitskiy <axilirator@gmail.com> </div>