<p>laforge has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/libosmo-abis/+/18249">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: trau_frame: New API<br><br>Change-Id: I5cf42e6c445d9224be18503cebc7584b3beba08c<br>---<br>M include/osmocom/abis/trau_frame.h<br>M src/trau_frame.c<br>2 files changed, 1,295 insertions(+), 2 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/libosmo-abis refs/changes/49/18249/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmocom/abis/trau_frame.h b/include/osmocom/abis/trau_frame.h</span><br><span>index 0f3d1d2..f14b439 100644</span><br><span>--- a/include/osmocom/abis/trau_frame.h</span><br><span>+++ b/include/osmocom/abis/trau_frame.h</span><br><span>@@ -21,6 +21,7 @@</span><br><span>  */</span><br><span> </span><br><span> #include <stdint.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <stdbool.h></span><br><span> #include <osmocom/core/bits.h></span><br><span> </span><br><span> /*! \defgroup trau_frame TRAU frame handling</span><br><span>@@ -29,6 +30,10 @@</span><br><span>  *  \file trau_frame.h</span><br><span>  */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*********************************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Old API</span><br><span style="color: hsl(120, 100%, 40%);">+ *********************************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /*! \brief Maximum number of C-bits in a TRAU frame:</span><br><span>  * 21 for FR/EFR, 25 for AMR, 15 for OM, 15 for data, 13 for E-data, 21 idle */</span><br><span> #define MAX_C_BITS  25</span><br><span>@@ -41,6 +46,8 @@</span><br><span> #define MAX_S_BITS    6</span><br><span> /*! \brief Maximum number of M-bits in a TRAU frame  for E-data */</span><br><span> #define MAX_M_BITS   2</span><br><span style="color: hsl(120, 100%, 40%);">+/*! \brief Maximum number of XC-bits in a TRAU frame for 8k */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX_XC_BITS  6</span><br><span> </span><br><span> /*! \brief a decoded TRAU frame, extracted C/D/T/S/M bits */</span><br><span> struct decoded_trau_frame {</span><br><span>@@ -51,6 +58,7 @@</span><br><span>     ubit_t m_bits[MAX_M_BITS];</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*! 16k sub-slot types: Bits C1..C5 */</span><br><span> #define TRAU_FT_FR_UP           0x02    /* 0 0 0 1 0 - 3.5.1.1.1 */</span><br><span> #define TRAU_FT_HR_UP            0x03    /* 0 0 0 1 1 - TS 08.61 5.1.4.1.1 */</span><br><span> #define TRAU_FT_FR_DOWN         0x1c    /* 1 1 1 0 0 - 3.5.1.1.1 */</span><br><span>@@ -62,12 +70,19 @@</span><br><span> #define TRAU_FT_DATA_UP            0x08    /* 0 1 0 0 0 - 3.5.3 */</span><br><span> #define TRAU_FT_DATA_UP_HR   0x09    /* 0 1 0 0 1 - TS 08.61 5.1.4.2 */</span><br><span> #define TRAU_FT_DATA_DOWN 0x16    /* 1 0 1 1 0 - 3.5.3 */</span><br><span style="color: hsl(0, 100%, 40%);">-#define TRAU_FT_DATA_DOWN_HR     0x17    /* 0 1 0 0 1 - TS 08.61 5.1.4.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU_FT_DATA_DOWN_HR        0x17    /* 1 0 1 1 1 - TS 08.61 5.1.4.2 */</span><br><span> #define TRAU_FT_D145_SYNC 0x14    /* 1 0 1 0 0 - 3.5.3 */</span><br><span> #define TRAU_FT_EDATA                0x1f    /* 1 1 1 1 1 - 3.5.4 */</span><br><span> #define TRAU_FT_IDLE_UP              0x10    /* 1 0 0 0 0 - 3.5.5 */</span><br><span> #define TRAU_FT_IDLE_DOWN    0x0e    /* 0 1 1 1 0 - 3.5.5 */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* 8k sub-slot types: Bits C1..C5*/</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_SPEECH_UP    0x02    /* 0 0 0 1 P - TS 08.61 5.2.4.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_DATA_UP  0x06    /* 0 0 1 1 P - TS 08.61 5.2.4.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_OM_UP            0x0a    /* 0 1 0 1 P - TS 08.61 5.2.4.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_SPEECH_DOWN      0x00    /* 0 0 0 U P - TS 08.61 5.2.4.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_DATA_DOWN        0x04    /* 0 0 1 U P - TS 08.61 5.2.4.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_OM_DOWN  0x08    /* 0 1 0 U P - TS 08.61 5.2.4.1.2 */</span><br><span> </span><br><span> int decode_trau_frame(struct decoded_trau_frame *fr, const ubit_t *trau_bits);</span><br><span> int encode_trau_frame(ubit_t *trau_bits, const struct decoded_trau_frame *fr);</span><br><span>@@ -75,6 +90,74 @@</span><br><span> </span><br><span> ubit_t *trau_idle_frame(void);</span><br><span> </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%);">+ * New API</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%);">+enum osmo_trau_frame_type {</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_TRAU16_FT_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_TRAU16_FT_FR = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_TRAU16_FT_HR,</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_TRAU16_FT_EFR,</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_TRAU16_FT_AMR,</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_TRAU16_FT_OAM,</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_TRAU16_FT_DATA,</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_TRAU16_FT_EDATA,</span><br><span style="color: hsl(120, 100%, 40%);">+ OSMO_TRAU16_FT_D145_SYNC,</span><br><span style="color: hsl(120, 100%, 40%);">+     OSMO_TRAU16_FT_DATA_HR,</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_TRAU16_FT_IDLE,</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        OSMO_TRAU8_SPEECH,</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_TRAU8_DATA,</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_TRAU8_OAM,</span><br><span style="color: hsl(120, 100%, 40%);">+       OSMO_TRAU8_AMR_LOW,</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_TRAU8_AMR_6k7,</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_TRAU8_AMR_7k4,</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%);">+enum osmo_trau_frame_direction {</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_TRAU_DIR_UL        = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  OSMO_TRAU_DIR_DL        = 1,</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%);">+struct osmo_trau_frame {</span><br><span style="color: hsl(120, 100%, 40%);">+  enum osmo_trau_frame_type type;</span><br><span style="color: hsl(120, 100%, 40%);">+       enum osmo_trau_frame_direction dir;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ ubit_t c_bits[MAX_C_BITS];</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t d_bits[MAX_D_BITS];</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t t_bits[MAX_T_BITS];</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t s_bits[MAX_S_BITS];</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t m_bits[MAX_M_BITS];</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t ufi;                     /*!< Unreliable Frame Indication (HR) */</span><br><span style="color: hsl(120, 100%, 40%);">+   ubit_t crc_bits[3];             /*!< CRC0..CRC2 (HR) */</span><br><span style="color: hsl(120, 100%, 40%);">+    ubit_t xc_bits[MAX_XC_BITS];    /*!< XC1..XC6 (8k) */</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%);">+/*! decode an 8k TRAU frame</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] fr caller-allocated output data structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bits unpacked input bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dir direction</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return 0 on success; negative in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_decode_8k(struct osmo_trau_frame *fr, const ubit_t *bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                        enum osmo_trau_frame_direction dir);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! decode an 16k TRAU frame</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] fr caller-allocated output data structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bits unpacked input bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dir direction</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return 0 on success; negative in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_decode_16k(struct osmo_trau_frame *fr, const ubit_t *bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                         enum osmo_trau_frame_direction dir);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*! encode a TRAU frame</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] bits caller-allocated memory for unpacked output bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] fr input data structure describing TRAU frame</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return number of bits encoded */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_encode(ubit_t *bits, size_t n_bits, const struct osmo_trau_frame *fr);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* }@ */</span><br><span> </span><br><span> #endif /* _TRAU_FRAME_H */</span><br><span>diff --git a/src/trau_frame.c b/src/trau_frame.c</span><br><span>index bc6c5bf..c990c1d 100644</span><br><span>--- a/src/trau_frame.c</span><br><span>+++ b/src/trau_frame.c</span><br><span>@@ -1,4 +1,4 @@</span><br><span style="color: hsl(0, 100%, 40%);">-/* TRAU frame handling according to GSM TS 08.60 */</span><br><span style="color: hsl(120, 100%, 40%);">+/* TRAU frame handling according to GSM TS 08.60 + 08.61 */</span><br><span> </span><br><span> /* (C) 2009,2020 by Harald Welte <laforge@gnumonks.org></span><br><span>  * All Rights Reserved</span><br><span>@@ -37,6 +37,10 @@</span><br><span>  *  \file trau_frame.c</span><br><span>  */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*********************************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * Old API; introduced in 2009 for original bs11_abis/OsmoNITB</span><br><span style="color: hsl(120, 100%, 40%);">+ *********************************************************************************/</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static uint32_t get_bits(const ubit_t *bitbuf, int offset, int num)</span><br><span> {</span><br><span>     int i;</span><br><span>@@ -480,4 +484,1210 @@</span><br><span>      return encoded_idle_frame;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/*********************************************************************************</span><br><span style="color: hsl(120, 100%, 40%);">+ * New API; introduced in 2020 for use by osmo-mgw</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%);">+/* 16k sub-slots */</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_fr_up_bits[5] =         { 0, 0, 0, 1, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_data_up_bits[5] =    { 0, 1, 0, 0, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_idle_up_bits[5] =    { 1, 0, 0, 0, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_efr_bits[5] =                { 1, 1, 0, 1, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_amr_bits[5] =                { 0, 0, 1, 1, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_oam_up_bits[5] =     { 0, 0, 1, 0, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_oam_down_bits[5] =   { 1, 1, 0, 1, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_d145s_bits[5] =              { 1, 0, 1, 0, 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_edata_bits[5] =              { 1, 1, 1, 1, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* 8k sub-slots */</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_hr_up_bits[5] =                { 0, 0, 0, 1, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_hr_down_bits[5] =    { 1, 1, 1, 0, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_data_hr_up_bits[5] = { 0, 1, 0, 0, 1 };</span><br><span style="color: hsl(120, 100%, 40%);">+static const ubit_t ft_data_hr_down_bits[5] =       { 1, 0, 1, 1, 1 };</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%);">+/* generate the sync pattern described in TS 08.60 4.8.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static void encode_sync16(ubit_t *trau_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* 16 '0' bits in  header */</span><br><span style="color: hsl(120, 100%, 40%);">+  memset(trau_bits, 0, 16);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* '1'-bit in regular intervals */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 16; i < 40*8; i += 16)</span><br><span style="color: hsl(120, 100%, 40%);">+            trau_bits[i] = 1;</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%);">+/* TS 08.60 Section 3.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_fr(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  const ubit_t *cbits5;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        int d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      switch (fr->type) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+             if (fr->dir == OSMO_TRAU_DIR_UL)</span><br><span style="color: hsl(120, 100%, 40%);">+                   cbits5 = ft_idle_up_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+             else</span><br><span style="color: hsl(120, 100%, 40%);">+                  cbits5 = ft_idle_down_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+           break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_FR:</span><br><span style="color: hsl(120, 100%, 40%);">+               if (fr->dir == OSMO_TRAU_DIR_UL)</span><br><span style="color: hsl(120, 100%, 40%);">+                   cbits5 = ft_fr_up_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+               else</span><br><span style="color: hsl(120, 100%, 40%);">+                  cbits5 = ft_fr_down_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_EFR:</span><br><span style="color: hsl(120, 100%, 40%);">+              cbits5 = ft_efr_bits;</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%);">+              return -EINVAL;</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%);">+   encode_sync16(trau_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 17, cbits5 + 0, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* C6 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 17 + 5, fr->c_bits + 5, 15 - 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* D1 .. D255 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 32; i < 304; i += 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[i] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             memcpy(trau_bits + i + 1, fr->d_bits + d_idx, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+         d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D256 .. D260 */</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[304] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   memcpy(trau_bits + 305, fr->d_bits + d_idx, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* C16 .. C21 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 310, fr->c_bits + 15, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* FIXME: handle timing adjustment */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* T1 .. T4 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 316, fr->t_bits+0, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        return 40 * 8;</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%);">+/* TS 08.60 Section 3.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode16_fr(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                        enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        int d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* C1 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->c_bits + 0, trau_bits + 17, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* C16 .. C21 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->c_bits + 15, trau_bits + 310, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* T1 .. T4 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->t_bits + 0, trau_bits + 316, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* D1 .. D255 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 32; i < 304; i+= 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+            memcpy(fr->d_bits + d_idx, trau_bits + i + 1, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+         d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D256 .. D260 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(fr->d_bits + d_idx, trau_bits + 305, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</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%);">+/* TS 08.60 Section 3.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_amr(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ const ubit_t *cbits5 = ft_amr_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+   int i, d_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       encode_sync16(trau_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 17, cbits5 + 0, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* C6 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 17 + 5, fr->c_bits + 5, 15 - 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      trau_bits[32] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    /* C16 .. C25 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 33, fr->c_bits + 15, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D1 .. D5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 43, fr->d_bits + 0, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D6 .. D256 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 48, d_idx = 5; i <= 315; i += 16, d_idx += 15) {</span><br><span style="color: hsl(120, 100%, 40%);">+          trau_bits[i] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             memcpy(trau_bits + i + 1, fr->d_bits + d_idx, 15);</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%);">+   /* FIXME: handle timing adjustment */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* T1 .. T4 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 316, fr->t_bits + 0, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return 40 * 8;</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%);">+/* TS 08.60 Section 3.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode16_amr(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                       enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        int d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* C1 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->c_bits + 0, trau_bits + 17, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* C16 .. C25 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->c_bits + 15, trau_bits + 33, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+       /* T1 .. T4 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->t_bits + 0, trau_bits + 316, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* D1 .. D5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits, trau_bits + 43, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+     d_idx += 5;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D6 .. D245 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 48; i < 304; i += 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(fr->d_bits + d_idx, trau_bits + i + 1, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+         d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+  }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D246 .. D256 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(fr->d_bits + d_idx, trau_bits + 305, 11);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</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%);">+/* TS 08.60 Section 3.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_oam(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   const ubit_t *cbits5;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, d_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (fr->dir == OSMO_TRAU_DIR_UL)</span><br><span style="color: hsl(120, 100%, 40%);">+           cbits5 = ft_oam_up_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+      else</span><br><span style="color: hsl(120, 100%, 40%);">+          cbits5 = ft_oam_down_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  encode_sync16(trau_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 17, cbits5, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* C6 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 17 + 5, fr->c_bits, 15 - 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* D1 .. D255 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 32, d_idx = 0; i < 304; i += 16, d_idx += 15) {</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[i] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             memcpy(trau_bits + i + 1, fr->d_bits + d_idx, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D256 .. D264 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(trau_bits + 305, fr->d_bits + 256, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* S1 .. S6 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 314, fr->s_bits, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 40 * 8;</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%);">+/* TS 08.60 Section 3.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode16_oam(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                 enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i, d_idx;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* C1 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->c_bits + 0, trau_bits + 17, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D1 .. D255 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 33, d_idx = 0; i < 312; i+= 16, d_idx += 15)</span><br><span style="color: hsl(120, 100%, 40%);">+              memcpy(fr->d_bits + d_idx, trau_bits + i + 1, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D256 .. D264 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(fr->d_bits+d_idx, trau_bits + 305, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* S1 .. S6 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->s_bits, trau_bits + 314, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  return 0;</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%);">+/* TS 08.61 Section 5.1.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_hr(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        const ubit_t *cbits5;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (fr->dir == OSMO_TRAU_DIR_UL)</span><br><span style="color: hsl(120, 100%, 40%);">+           cbits5 = ft_hr_up_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+       else</span><br><span style="color: hsl(120, 100%, 40%);">+          cbits5 = ft_hr_down_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   encode_sync16(trau_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 17, cbits5, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* C6 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 17 + 5, fr->c_bits + 5, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /*  UFI */</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[33] = fr->ufi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D1 .. D14 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 4 * 8 + 2, fr->d_bits+d_idx, 14); d_idx += 14;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* D15 .. D29 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 6 * 8 + 1, fr->d_bits+d_idx, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* D30 .. D44 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 8 * 8 + 1, fr->d_bits+d_idx, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+  /* CRC */</span><br><span style="color: hsl(120, 100%, 40%);">+     memcpy(trau_bits + 10 * 8 + 1, fr->crc_bits, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D45 .. D56 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 10 * 8 + 4, fr->d_bits+d_idx, 12); d_idx += 12;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D57 .. D71 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 12 * 8 + 1, fr->d_bits+d_idx, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D72 .. D86 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 14 * 8 + 1, fr->d_bits+d_idx, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D87 .. D101 */</span><br><span style="color: hsl(120, 100%, 40%);">+     memcpy(trau_bits + 16 * 8 + 1, fr->d_bits+d_idx, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D102 .. D112 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(trau_bits + 18 * 8 + 1, fr->d_bits+d_idx, 11); d_idx += 11;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       memset(trau_bits + 19 * 8 + 4, 0x01, 4 + 18 * 8 + 6);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* C16 .. C21 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 38 * 8 + 6, fr->c_bits + 15, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* FIXME: handle timing adjustment */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* T1 .. T4 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 39 * 8 + 4, fr->t_bits, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 40 * 8;</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%);">+/* TS 08.61 Section 5.1.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode16_hr(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                      enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* C1 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->c_bits + 0, trau_bits + 17, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* C16 .. C21 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->c_bits + 15, trau_bits + 38 * 8 + 6, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+        /* T1 .. T4 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->t_bits + 0, trau_bits + 39 * 8 + 4, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* UFI */</span><br><span style="color: hsl(120, 100%, 40%);">+     fr->ufi = trau_bits[33];</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D1 .. D14 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->d_bits + d_idx, trau_bits + 4 * 8 + 2, 14); d_idx += 14;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* D15 .. D29 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 6 * 8 + 1, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* D30 .. D44 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 8 * 8 + 1, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+        /* CRC0..2 */</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(fr->crc_bits, trau_bits + 10 * 8 + 1, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D45 .. D56 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 10 * 8 + 4, 12); d_idx += 12;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D57 .. D71 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 12 * 8 + 1, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D72 .. D86 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 14 * 8 + 1, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D87 .. D101 */</span><br><span style="color: hsl(120, 100%, 40%);">+     memcpy(fr->d_bits + d_idx, trau_bits + 16 * 8 + 1, 15); d_idx += 15;</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D102 .. D112 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(fr->d_bits + d_idx, trau_bits + 18 * 8 + 1, 11); d_idx += 11;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     return 0;</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%);">+/* TS 08.60 Section 3.4 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_idle(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  memcpy(trau_bits, trau_idle_frame(), 40*8);</span><br><span style="color: hsl(120, 100%, 40%);">+   return 40 * 8;</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%);">+/* TS 08.60 Section 3.3.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode16_data(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                       enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->c_bits + 0, trau_bits + 17, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D1 .. D63 */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          memcpy(fr->d_bits + d_idx, trau_bits + (4 + i) * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+                d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D64 .. D126 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          memcpy(fr->d_bits + d_idx, trau_bits + (13 + i) * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+               d_idx += 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%);">+   /* D127 .. D189 */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          memcpy(fr->d_bits + d_idx, trau_bits + (22 + i) * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+               d_idx += 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%);">+   /* D190 .. D252 */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          memcpy(fr->d_bits + d_idx, trau_bits + (31 + i) * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+               d_idx += 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%);">+   return 0;</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%);">+/* TS 08.60 Section 3.3.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_data(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        const ubit_t *cbits5;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (fr->dir == OSMO_TRAU_DIR_UL)</span><br><span style="color: hsl(120, 100%, 40%);">+           cbits5 = ft_data_up_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          cbits5 = ft_data_down_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ encode_sync16(trau_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 17, cbits5, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* C6 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 17 + 5, fr->c_bits + 5, 15 - 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D1 .. D63 */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          unsigned int offset = (4 + i) * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+            trau_bits[offset] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   /* D64 .. D126 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          unsigned int offset = (13 + i) * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[offset] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   /* D127 .. D189 */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          unsigned int offset = (22 + i) * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[offset] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   /* D190 .. D252 */</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          unsigned int offset = (31 + i) * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[offset] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   return 40 * 8;</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%);">+/* TS 08.60 3.3.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode16_edata(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                       enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      /* C1 .. C13 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->c_bits, trau_bits + 17, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* M1 .. M2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->m_bits, trau_bits + 30, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D1 .. D288 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits, trau_bits + 4 * 8, 288);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return 0;</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%);">+/* TS 08.60 Section 3.3.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_edata(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       const ubit_t *cbits5;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (fr->type == OSMO_TRAU16_FT_D145_SYNC)</span><br><span style="color: hsl(120, 100%, 40%);">+          cbits5 = ft_d145s_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+       else</span><br><span style="color: hsl(120, 100%, 40%);">+          cbits5 = ft_edata_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 17, cbits5, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* C6 .. C13 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 17 + 5, fr->c_bits + 5, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* M1 .. M2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 30, fr->m_bits, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D1 .. D288 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 4 * 8, fr->d_bits, 288);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      return 40 * 8;</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%);">+/* TS 08.61 Section 5.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode16_data_hr(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                     enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->c_bits+0, trau_bits + 17, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* D1 .. D63 */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          memcpy(fr->d_bits + d_idx, trau_bits + (4 + i) * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+                d_idx += 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%);">+   /* D'1 .. D'63 (mapped to D64..D127) */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          memcpy(fr->d_bits + d_idx, trau_bits + (22 + i) * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+               d_idx += 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%);">+   return 0;</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%);">+/* TS 08.61 Section 5.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode16_data_hr(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const ubit_t *cbits5;</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (fr->dir == OSMO_TRAU_DIR_UL)</span><br><span style="color: hsl(120, 100%, 40%);">+           cbits5 = ft_data_hr_up_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          cbits5 = ft_data_hr_down_bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      encode_sync16(trau_bits);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 17, cbits5, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* C6 .. C15 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 17 + 5, fr->c_bits + 5, 15 - 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D1 .. D63 */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 4; i < 4 + 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              unsigned int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+          trau_bits[offset] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   memset(trau_bits + 13*8, 1, 9*8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D'1 .. D'63 (mapped to D64..D127) */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 22; i < 22 + 9; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+            unsigned int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+          trau_bits[offset] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+                memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   memset(trau_bits + 31*8, 1, 9*8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 40 * 8;</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%);">+/* TS 08.61 Section 5.2.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode8_hr(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                     enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->c_bits, trau_bits + 9, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* XC1 .. XC2 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->xc_bits, trau_bits + 8 + 6, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* XC3 .. XC6 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->xc_bits + 2, trau_bits + 2 * 8 + 2, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D1 .. D2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 2 * 8 + 6, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D1 .. D44 */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 3; i < 3 + 6; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(fr->d_bits + d_idx, trau_bits + offset + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   /* CRC0 .. CRC2 */</span><br><span style="color: hsl(120, 100%, 40%);">+    fr->crc_bits[2] = trau_bits[82];</span><br><span style="color: hsl(120, 100%, 40%);">+   fr->crc_bits[1] = trau_bits[83];</span><br><span style="color: hsl(120, 100%, 40%);">+   fr->crc_bits[0] = trau_bits[84];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D45 .. D48 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 85, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D49 .. D111 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 10; i < 10 + 10; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(fr->d_bits + d_idx, trau_bits + offset + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D112 */</span><br><span style="color: hsl(120, 100%, 40%);">+    fr->d_bits[d_idx++] = trau_bits[19 * 8 + 1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* C6 .. C9 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->c_bits + 5, trau_bits + 19 * 8 + 2, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* FIXME: handle timing adjustment */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* T1 .. T2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        fr->t_bits[0] = trau_bits[19 * 8 + 6];</span><br><span style="color: hsl(120, 100%, 40%);">+     fr->t_bits[1] = trau_bits[19 * 8 + 7];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</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%);">+/* compute the odd parity bit of the given input bit sequence */</span><br><span style="color: hsl(120, 100%, 40%);">+static ubit_t compute_odd_parity(const ubit_t *in, unsigned int num_bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 0; i < num_bits; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (in[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                    sum++;</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%);">+   if (sum % 1)</span><br><span style="color: hsl(120, 100%, 40%);">+          return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          return 1;</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%);">+/* TS 08.61 Section 5.2.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode8_hr(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* sync pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(trau_bits, 0, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      trau_bits[8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[16] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[17] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 3; i < 20; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[i * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        ubit_t *cbits_out = trau_bits + 1 * 8 + 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    if (fr->dir == OSMO_TRAU_DIR_UL) {</span><br><span style="color: hsl(120, 100%, 40%);">+         cbits_out[0] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             cbits_out[1] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             cbits_out[2] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             cbits_out[3] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+             cbits_out[4] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              cbits_out[0] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             cbits_out[1] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             cbits_out[2] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+             cbits_out[3] = fr->c_bits[3];</span><br><span style="color: hsl(120, 100%, 40%);">+              cbits_out[4] = compute_odd_parity(cbits_out, 4);</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%);">+   /* XC1 .. XC2 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 1 * 8 + 6, fr->xc_bits, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* XC3 .. XC6 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 2 * 8 + 2, fr->xc_bits, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D1 ..  D2 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 2 * 8 + 6, fr->d_bits, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D1 .. D44 */</span><br><span style="color: hsl(120, 100%, 40%);">+       for (i = 3; i < 3 + 6; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+              int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+  /* CRC0 .. CRC2 */</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[82] = fr->crc_bits[2];</span><br><span style="color: hsl(120, 100%, 40%);">+   trau_bits[83] = fr->crc_bits[1];</span><br><span style="color: hsl(120, 100%, 40%);">+   trau_bits[84] = fr->crc_bits[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D49 .. D111 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 10; i < 10 + 10; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+           int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D112 */</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[19 * 8 + 1] = fr->d_bits[d_idx++];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     /* C6 .. C9 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 19 * 8 + 2, fr->c_bits + 5, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* FIXME: handle timing adjustment */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* T1 .. T2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        trau_bits[19 * 8 + 6] = fr->t_bits[0];</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[19 * 8 + 7] = fr->t_bits[1];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 20 * 8;</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%);">+/* TS 08.61 Section 5.2.1.2.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode8_amr_low(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                           enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D1 .. D7 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 1 * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->c_bits, trau_bits + 2 * 8 + 1, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D8 .. D9 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 2 * 8 + 6, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D10 .. D15 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 3 * 8 + 2, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D16 .. D120 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 4; i < 19; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(fr->d_bits + d_idx, trau_bits + offset + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D121 .. D126 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(fr->d_bits + d_idx, trau_bits + 19 * 8 + 1, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+     d_idx += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* FIXME: handle timing adjustment */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* T1 */</span><br><span style="color: hsl(120, 100%, 40%);">+      fr->t_bits[0] = trau_bits[19 * 8 + 7];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</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%);">+/* TS 08.61 Section 5.2.1.2.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode8_amr_low(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* sync pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(trau_bits, 0, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      trau_bits[8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[16] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[24] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[25] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+    for (i = 4; i < 20; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[i * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D1 .. D7 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 1 * 8 + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 2 * 8 + 1, fr->c_bits, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D8 .. D9 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 2 * 8 + 6, fr->d_bits + d_idx, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D10 .. D15 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 3 * 8 + 2, fr->d_bits + d_idx, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D16 .. D120 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 4; i < 19; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D121 .. D126 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(trau_bits + 19 * 8 + 1, fr->d_bits + d_idx, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+     d_idx += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* T1 */</span><br><span style="color: hsl(120, 100%, 40%);">+      trau_bits[19 * 8 + 7] = fr->t_bits[0];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 20 * 8;</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%);">+/* TS 08.61 Section 5.2.1.2.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode8_amr_67(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                   enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D1 .. D7 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 1 * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C3 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->c_bits, trau_bits + 2 * 8 + 1, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D8 .. D11 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->d_bits + d_idx, trau_bits + 2 * 8 + 4, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D12 .. D39 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 3; i < 7; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(fr->d_bits + d_idx, trau_bits + offset + 2, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   /* D40 .. D137 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 7; i < 20; i+= 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+               int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(fr->d_bits + d_idx, trau_bits + offset + 1, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+            d_idx += 15;</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 0;</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%);">+/* TS 08.61 Section 5.1.2.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode8_amr_67(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* sync pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(trau_bits, 0, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      trau_bits[1 * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trau_bits[2 * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trau_bits[3 * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trau_bits[4 * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trau_bits[5 * 8] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 5; i < 20; i += 2)</span><br><span style="color: hsl(120, 100%, 40%);">+                trau_bits[i * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* D1 .. D7 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 1 * 8 + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C3 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 2 * 8 + 1, fr->c_bits, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D8 .. D11 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 2 * 8 + 4, fr->d_bits + d_idx, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D12 .. D39 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 3; i < 7; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(trau_bits + offset + 2, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+             d_idx += 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%);">+   /* D40 .. D137 */</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 7; i < 20; i+= 2) {</span><br><span style="color: hsl(120, 100%, 40%);">+               int offset = i * 8;</span><br><span style="color: hsl(120, 100%, 40%);">+           memcpy(trau_bits + offset + 1, fr->d_bits + d_idx, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+            d_idx += 15;</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 20 * 8;</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%);">+/* TS 08.61 Section 5.1.2.3 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode8_amr_74(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                     enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D1 .. D5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 3, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 5;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D6 .. D12 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(fr->d_bits + d_idx, trau_bits + 1 * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1.. C3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(fr->c_bits, trau_bits + 2 * 8 + 1, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D13 .. D16 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 2 * 8 + 4, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D17 .. D23 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->d_bits + d_idx, trau_bits + 3 * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D24 .. D151 */</span><br><span style="color: hsl(120, 100%, 40%);">+     memcpy(fr->d_bits + d_idx, trau_bits + 4 * 8, 16 * 8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 0;</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%);">+/* TS 08.61 Section 5.1.2.3 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode8_amr_74(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     int d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* sync pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+    trau_bits[0] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[1] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[2] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[1*8] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   trau_bits[2*8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   trau_bits[3*8] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D1 .. D5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 3, fr->d_bits + d_idx, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 5;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D6 .. D12 */</span><br><span style="color: hsl(120, 100%, 40%);">+       memcpy(trau_bits + 1 * 8 + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1.. C3 */</span><br><span style="color: hsl(120, 100%, 40%);">+ memcpy(trau_bits + 2 * 8 + 1, fr->c_bits, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D13 .. D16 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 2 * 8 + 4, fr->d_bits + d_idx, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 4;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D17 .. D23 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 3 * 8 + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D24 .. D151 */</span><br><span style="color: hsl(120, 100%, 40%);">+     memcpy(trau_bits + 4 * 8, fr->d_bits + d_idx, 16 * 8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   return 20 * 8;</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%);">+/* TS 08.61 Section 5.2.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode8_data(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                       enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->c_bits, trau_bits + 1 * 8 + 1, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D1 .. D2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 1 * 8 + 6, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D3 .. D8 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 2 * 8 + 2, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D9 .. D57 + D'1 .. D'57 */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 3; i < 20; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         memcpy(fr->d_bits + d_idx, trau_bits + i * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+              d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D'58 .. D'62 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(fr->d_bits + d_idx, trau_bits + 19 * 8 + 1, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+     d_idx += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</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%);">+/* TS 08.61 Section 5.2.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode8_data(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* sync pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(trau_bits, 0, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      trau_bits[1 * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trau_bits[2 * 8] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ trau_bits[2 * 8 + 1] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 3; i < 19; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[i * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+ trau_bits[19 * 8 + 7] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 1 * 8 + 1, fr->c_bits, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D1 .. D2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 1 * 8 + 6, fr->d_bits + d_idx, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D3 .. D8 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 2 * 8 + 2, fr->d_bits + d_idx, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* D9 .. D57 + D'1 .. D'57 */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 3; i < 20; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         memcpy(trau_bits + i * 8 + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+              d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D'58 .. D'62 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(trau_bits + 19 * 8 + 1, fr->d_bits + d_idx, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+     d_idx += 6;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 20 * 8;</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%);">+/* TS 08.61 Section 5.2.3 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int decode8_oam(struct osmo_trau_frame *fr, const ubit_t *trau_bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                       enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->c_bits, trau_bits + 1 * 8 + 1, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* XC1 .. XC2 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->xc_bits, trau_bits + 1 * 8 + 6, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* XC3 .. XC6 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(fr->xc_bits + 2, trau_bits + 2 * 8 + 2, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D1 .. D2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(fr->d_bits + d_idx, trau_bits + 2 * 8 + 6, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D3 .. D114 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 3; i < 19; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         memcpy(fr->d_bits + d_idx, trau_bits + i * 8 + 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+              d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D115 .. D120 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(fr->d_bits + d_idx, trau_bits + 19 * 8 + 1, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+     d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 0;</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%);">+/* TS 08.61 Section 5.2.3 */</span><br><span style="color: hsl(120, 100%, 40%);">+static int encode8_oam(ubit_t *trau_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  int i, d_idx = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* sync pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+    memset(trau_bits, 0, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+      trau_bits[1 * 8 + 0] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[2 * 8 + 0] = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     trau_bits[2 * 8 + 1] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+     for (i = 3; i < 20; i++)</span><br><span style="color: hsl(120, 100%, 40%);">+           trau_bits[i * 8] = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* C1 .. C5 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 1 * 8 + 1, fr->c_bits, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* XC1 .. XC2 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 1 * 8 + 6, fr->xc_bits, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+     /* XC3 .. XC6 */</span><br><span style="color: hsl(120, 100%, 40%);">+      memcpy(trau_bits + 2 * 8 + 2, fr->xc_bits + 2, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+ /* D1 .. D2 */</span><br><span style="color: hsl(120, 100%, 40%);">+        memcpy(trau_bits + 2 * 8 + 6, fr->d_bits + d_idx, 2);</span><br><span style="color: hsl(120, 100%, 40%);">+      d_idx += 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* D3 .. D114 */</span><br><span style="color: hsl(120, 100%, 40%);">+      for (i = 3; i < 19; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         memcpy(trau_bits + i * 8 + 1, fr->d_bits + d_idx, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+              d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* D115 .. D120 */</span><br><span style="color: hsl(120, 100%, 40%);">+    memcpy(trau_bits + 19 * 8 + 1, fr->d_bits + d_idx, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+     d_idx += 7;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+ return 20 * 8;</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%);">+/*! Encode a TRAU frame from its decoded representation to a sequence of unpacked bits.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] bits caller-allocated buffer for unpacked outpud bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] n_bits size of 'bits' oputput buffer in number of unpacked bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] fr decoded representation of TRAU frame to be encoded</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \return 0 number of unpacked output bits generated; negative in case of error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_encode(ubit_t *bits, size_t n_bits, const struct osmo_trau_frame *fr)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+       switch (fr->type) {</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_FR:</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_TRAU16_FT_EFR:</span><br><span style="color: hsl(120, 100%, 40%);">+              return encode16_fr(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+ case OSMO_TRAU16_FT_HR:</span><br><span style="color: hsl(120, 100%, 40%);">+               return encode16_hr(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+ case OSMO_TRAU16_FT_AMR:</span><br><span style="color: hsl(120, 100%, 40%);">+              return encode16_amr(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_OAM:</span><br><span style="color: hsl(120, 100%, 40%);">+              return encode16_oam(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_IDLE:</span><br><span style="color: hsl(120, 100%, 40%);">+             return encode16_idle(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_TRAU16_FT_DATA_HR:</span><br><span style="color: hsl(120, 100%, 40%);">+          return encode16_data_hr(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+    case OSMO_TRAU16_FT_DATA:</span><br><span style="color: hsl(120, 100%, 40%);">+             return encode16_data(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+       case OSMO_TRAU16_FT_D145_SYNC:</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU16_FT_EDATA:</span><br><span style="color: hsl(120, 100%, 40%);">+            return encode16_edata(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+      case OSMO_TRAU8_SPEECH:</span><br><span style="color: hsl(120, 100%, 40%);">+               return encode8_hr(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+  case OSMO_TRAU8_DATA:</span><br><span style="color: hsl(120, 100%, 40%);">+         return encode8_data(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+        case OSMO_TRAU8_OAM:</span><br><span style="color: hsl(120, 100%, 40%);">+          return encode8_oam(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+ case OSMO_TRAU8_AMR_LOW:</span><br><span style="color: hsl(120, 100%, 40%);">+              return encode8_amr_low(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+     case OSMO_TRAU8_AMR_6k7:</span><br><span style="color: hsl(120, 100%, 40%);">+              return encode8_amr_67(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+      case OSMO_TRAU8_AMR_7k4:</span><br><span style="color: hsl(120, 100%, 40%);">+              return encode8_amr_74(bits, fr);</span><br><span style="color: hsl(120, 100%, 40%);">+      case OSMO_TRAU16_FT_NONE:</span><br><span style="color: hsl(120, 100%, 40%);">+     default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return -EINVAL;</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%);">+/*! Decode/parse a 16k TRAU frame from unpacked bits to decoded format.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] fr caller-allocated output data structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bits unpacked bits containing raw TRAU frame; must be aligned</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dir direction (uplink/downlink)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 in case of success; negative on error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_decode_16k(struct osmo_trau_frame *fr, const ubit_t *bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                            enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t cbits5 = get_bits(bits, 17, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     fr->type = OSMO_TRAU16_FT_NONE;</span><br><span style="color: hsl(120, 100%, 40%);">+    fr->dir = dir;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (cbits5) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case TRAU_FT_FR_UP:</span><br><span style="color: hsl(120, 100%, 40%);">+   case TRAU_FT_FR_DOWN:</span><br><span style="color: hsl(120, 100%, 40%);">+         fr->type = OSMO_TRAU16_FT_FR;</span><br><span style="color: hsl(120, 100%, 40%);">+              return decode16_fr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+    case TRAU_FT_IDLE_UP:</span><br><span style="color: hsl(120, 100%, 40%);">+ case TRAU_FT_IDLE_DOWN:</span><br><span style="color: hsl(120, 100%, 40%);">+               fr->type = OSMO_TRAU16_FT_IDLE;</span><br><span style="color: hsl(120, 100%, 40%);">+            return decode16_fr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+    case TRAU_FT_EFR:</span><br><span style="color: hsl(120, 100%, 40%);">+             fr->type = OSMO_TRAU16_FT_EFR;</span><br><span style="color: hsl(120, 100%, 40%);">+             return decode16_fr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+    case TRAU_FT_AMR:</span><br><span style="color: hsl(120, 100%, 40%);">+             fr->type = OSMO_TRAU16_FT_AMR;</span><br><span style="color: hsl(120, 100%, 40%);">+             return decode16_amr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+   case TRAU_FT_OM_UP:</span><br><span style="color: hsl(120, 100%, 40%);">+   case TRAU_FT_OM_DOWN:</span><br><span style="color: hsl(120, 100%, 40%);">+         fr->type = OSMO_TRAU16_FT_OAM;</span><br><span style="color: hsl(120, 100%, 40%);">+             return decode16_oam(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+   case TRAU_FT_DATA_UP:</span><br><span style="color: hsl(120, 100%, 40%);">+ case TRAU_FT_DATA_DOWN:</span><br><span style="color: hsl(120, 100%, 40%);">+               fr->type = OSMO_TRAU16_FT_DATA;</span><br><span style="color: hsl(120, 100%, 40%);">+            return decode16_data(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+  case TRAU_FT_HR_UP:</span><br><span style="color: hsl(120, 100%, 40%);">+   case TRAU_FT_HR_DOWN:</span><br><span style="color: hsl(120, 100%, 40%);">+         fr->type = OSMO_TRAU16_FT_HR;</span><br><span style="color: hsl(120, 100%, 40%);">+              return decode16_hr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+    case TRAU_FT_DATA_UP_HR:</span><br><span style="color: hsl(120, 100%, 40%);">+      case TRAU_FT_DATA_DOWN_HR:</span><br><span style="color: hsl(120, 100%, 40%);">+            fr->type = OSMO_TRAU16_FT_DATA_HR;</span><br><span style="color: hsl(120, 100%, 40%);">+         return decode16_data_hr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+       case TRAU_FT_EDATA:</span><br><span style="color: hsl(120, 100%, 40%);">+           fr->type = OSMO_TRAU16_FT_EDATA;</span><br><span style="color: hsl(120, 100%, 40%);">+           return decode16_edata(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ case TRAU_FT_D145_SYNC:</span><br><span style="color: hsl(120, 100%, 40%);">+               fr->type = OSMO_TRAU16_FT_D145_SYNC;</span><br><span style="color: hsl(120, 100%, 40%);">+               return decode16_edata(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return -EINVAL;</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%);">+#define TRAU8_FT_AMR_NO_SPEECH_CMI      0x10    /* 1, 0, 0, 0, 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_AMR_NO_SPEECH_CMR 0x14    /* 1, 0, 1, 0, 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define TRAU8_FT_AMR_475_515_590   0..7</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+const uint8_t bit8_0[16] = { 0,  };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/*!< check sync pattern for hr/data/oam */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool is_hr(const ubit_t *bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* TS 08.61 Section 6.8.2.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (memcmp(bits, bit8_0, sizeof(bit8_0)))</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[8] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[16] != 0 || bits[17] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+           return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 24; i < 20 * 8; i += 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (bits[i] != 1)</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%);">+     return true;</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%);">+/*!< check sync pattern for AMR No_Speech + low bit rate */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool is_amr_low(const ubit_t *bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+    int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* TS 08.61 Section 6.8.2.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (memcmp(bits, bit8_0, sizeof(bit8_0)))</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[8] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[16] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[24] != 0 || bits[25] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+           return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 32; i < 20 * 8; i += 16) {</span><br><span style="color: hsl(120, 100%, 40%);">+                if (bits[i] != 1)</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%);">+     return true;</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%);">+/*!< check sync pattern for AMR 6.7kBit/s */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool is_amr_67(const ubit_t *bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      int i;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* TS 08.61 Section 6.8.2.1.3 */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (memcmp(bits, bit8_0, sizeof(bit8_0)))</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[8] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[16] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[24] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[32] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[40] != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 48; i < 20 * 8; i+= 16)</span><br><span style="color: hsl(120, 100%, 40%);">+           if (bits[i] != 1)</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%);">+       return true;</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%);">+/*!< check sync pattern for AMR 7.4kBit/s */</span><br><span style="color: hsl(120, 100%, 40%);">+static bool is_amr_74(const ubit_t *bits)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+      if (bits[0] != 0 || bits[1] != 0 || bits[2] != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[8] != 0)</span><br><span style="color: hsl(120, 100%, 40%);">+             return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[16] != 1)</span><br><span style="color: hsl(120, 100%, 40%);">+            return false;</span><br><span style="color: hsl(120, 100%, 40%);">+ if (bits[24] != 0)</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%);">+       return true;</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%);">+/*! Decode/parse a 8k TRAU frame from unpacked bits to decoded format.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[out] fr caller-allocated output data structure</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] bits unpacked bits containing raw TRAU frame; must be aligned</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] dir direction (uplink/downlink)</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \returns 0 in case of success; negative on error */</span><br><span style="color: hsl(120, 100%, 40%);">+int osmo_trau_frame_decode_8k(struct osmo_trau_frame *fr, const ubit_t *bits,</span><br><span style="color: hsl(120, 100%, 40%);">+                          enum osmo_trau_frame_direction dir)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+  fr->dir = dir;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (is_hr(bits)) {</span><br><span style="color: hsl(120, 100%, 40%);">+            /* normal sync pattern */</span><br><span style="color: hsl(120, 100%, 40%);">+             uint8_t cbits5 = get_bits(bits, 9, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+                if (dir == OSMO_TRAU_DIR_UL) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        switch (cbits5) {       /* Section 5.2.4.1.1 */</span><br><span style="color: hsl(120, 100%, 40%);">+                       case 0x02:</span><br><span style="color: hsl(120, 100%, 40%);">+                            return decode8_hr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+                     case 0x07:</span><br><span style="color: hsl(120, 100%, 40%);">+                            return decode8_data(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+                   case 0x13:</span><br><span style="color: hsl(120, 100%, 40%);">+                            return decode8_oam(fr, bits, dir);</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%);">+                      /* Downlink */</span><br><span style="color: hsl(120, 100%, 40%);">+                        switch (cbits5 >> 2) {    /* Section 5.2.4.1.2 */</span><br><span style="color: hsl(120, 100%, 40%);">+                       case 0:</span><br><span style="color: hsl(120, 100%, 40%);">+                               return decode8_hr(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+                     case 1:</span><br><span style="color: hsl(120, 100%, 40%);">+                               return decode8_data(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+                   case 2:</span><br><span style="color: hsl(120, 100%, 40%);">+                               return decode8_oam(fr, bits, dir);</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%);">+     } else if (is_amr_low(bits)) {</span><br><span style="color: hsl(120, 100%, 40%);">+                return decode8_amr_low(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+        } else if (is_amr_67(bits)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return decode8_amr_67(fr, bits, dir);</span><br><span style="color: hsl(120, 100%, 40%);">+ } else if (is_amr_74(bits)) {</span><br><span style="color: hsl(120, 100%, 40%);">+         return decode8_amr_74(fr, bits, dir);</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 -EINVAL;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* }@ */</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/libosmo-abis/+/18249">change 18249</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/libosmo-abis/+/18249"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: libosmo-abis </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I5cf42e6c445d9224be18503cebc7584b3beba08c </div>
<div style="display:none"> Gerrit-Change-Number: 18249 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>