<p>Jan Hrach has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/10271">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">simplify and speed up the burst synchronizer<br><br>Rewrite the burst synchronizer so we simply jump to the next training sequence.<br>I believe the state machine is not needed, the only reason for it - speeding<br>up search for the next frame - has been fixed in ca6a3bc.<br><br>Simplifying the synchronizer allows it to be easily extended to support<br>uplink and direct modes.<br><br>Additionally, we process the entire buffer at once (the previous version used<br>64-byte chunks), so the overhead is much smaller (up to 20 times on sparse<br>channels).<br><br>Change-Id: I74a13ced4c11b6d98afa7916c1f4109875c20101<br>---<br>M src/phy/tetra_burst_sync.c<br>M src/phy/tetra_burst_sync.h<br>M src/tetra-rx.c<br>M src/tetra_common.h<br>4 files changed, 65 insertions(+), 94 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-tetra refs/changes/71/10271/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/phy/tetra_burst_sync.c b/src/phy/tetra_burst_sync.c</span><br><span>index ae210dc..f3b759f 100644</span><br><span>--- a/src/phy/tetra_burst_sync.c</span><br><span>+++ b/src/phy/tetra_burst_sync.c</span><br><span>@@ -21,6 +21,7 @@</span><br><span> #include <stdint.h></span><br><span> #include <stdio.h></span><br><span> #include <string.h></span><br><span style="color: hsl(120, 100%, 40%);">+#include <assert.h></span><br><span> </span><br><span> #include <osmocom/core/utils.h></span><br><span> </span><br><span>@@ -35,7 +36,7 @@</span><br><span> </span><br><span> void tetra_burst_rx_cb(const uint8_t *burst, unsigned int len, enum tetra_train_seq type, void *priv);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static void make_bitbuf_space(struct tetra_rx_state *trs, unsigned int len)</span><br><span style="color: hsl(120, 100%, 40%);">+static unsigned int make_bitbuf_space(struct tetra_rx_state *trs, unsigned int len)</span><br><span> {</span><br><span>  unsigned int bitbuf_space = sizeof(trs->bitbuf) - trs->bits_in_buf;</span><br><span> </span><br><span>@@ -48,9 +49,20 @@</span><br><span>           trs->bitbuf_start_bitnum += delta;</span><br><span>                bitbuf_space = sizeof(trs->bitbuf) - trs->bits_in_buf;</span><br><span>         }</span><br><span style="color: hsl(120, 100%, 40%);">+     return bitbuf_space;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-/* input a raw bitstream into the tetra burst synchronizaer */</span><br><span style="color: hsl(120, 100%, 40%);">+static unsigned int conserve_bits(struct tetra_rx_state *trs, unsigned int howmany)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   assert(howmany < sizeof(trs->bitbuf));</span><br><span style="color: hsl(120, 100%, 40%);">+  return make_bitbuf_space(trs, sizeof(trs->bitbuf) - howmany);</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%);">+/* input a raw bitstream into the tetra burst synchronizer</span><br><span style="color: hsl(120, 100%, 40%);">+ * returns the number which in absolute value is the number of bits</span><br><span style="color: hsl(120, 100%, 40%);">+ *  we can safely consume the next time</span><br><span style="color: hsl(120, 100%, 40%);">+ * if the result is negative, we are done with processing</span><br><span style="color: hsl(120, 100%, 40%);">+ */</span><br><span> int tetra_burst_sync_in(struct tetra_rx_state *trs, uint8_t *bits, unsigned int len)</span><br><span> {</span><br><span>         int rc;</span><br><span>@@ -63,92 +75,35 @@</span><br><span>        memcpy(trs->bitbuf + trs->bits_in_buf, bits, len);</span><br><span>     trs->bits_in_buf += len;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- switch (trs->state) {</span><br><span style="color: hsl(0, 100%, 40%);">-        case RX_S_UNLOCKED:</span><br><span style="color: hsl(0, 100%, 40%);">-             if (trs->bits_in_buf < TETRA_BITS_PER_TS*2) {</span><br><span style="color: hsl(0, 100%, 40%);">-                     /* wait for more bits to arrive */</span><br><span style="color: hsl(0, 100%, 40%);">-                      DEBUGP("-> waiting for more bits to arrive\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                    return len;</span><br><span style="color: hsl(0, 100%, 40%);">-             }</span><br><span style="color: hsl(0, 100%, 40%);">-               DEBUGP("-> trying to find training sequence between bit %u and %u\n",</span><br><span style="color: hsl(0, 100%, 40%);">-                      trs->bitbuf_start_bitnum, trs->bits_in_buf);</span><br><span style="color: hsl(0, 100%, 40%);">-              rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf,</span><br><span style="color: hsl(0, 100%, 40%);">-                                    (1 << TETRA_TRAIN_SYNC), &train_seq_offs);</span><br><span style="color: hsl(0, 100%, 40%);">-          if (rc < 0)</span><br><span style="color: hsl(0, 100%, 40%);">-                  return rc;</span><br><span style="color: hsl(0, 100%, 40%);">-              printf("found SYNC training sequence in bit #%u\n", train_seq_offs);</span><br><span style="color: hsl(0, 100%, 40%);">-          trs->state = RX_S_KNOW_FSTART;</span><br><span style="color: hsl(0, 100%, 40%);">-               trs->next_frame_start_bitnum = trs->bitbuf_start_bitnum + train_seq_offs + 296;</span><br><span style="color: hsl(0, 100%, 40%);">-#if 0</span><br><span style="color: hsl(0, 100%, 40%);">-              if (train_seq_offs < 214) {</span><br><span style="color: hsl(0, 100%, 40%);">-                  /* not enough leading bits for start of burst */</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* we just drop everything that we received so far */</span><br><span style="color: hsl(0, 100%, 40%);">-                   trs->bitbuf_start_bitnum += trs->bits_in_buf;</span><br><span style="color: hsl(0, 100%, 40%);">-                     trs->bits_in_buf = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-                }</span><br><span style="color: hsl(0, 100%, 40%);">-#endif</span><br><span style="color: hsl(120, 100%, 40%);">+       rc = tetra_find_train_seq(trs->bitbuf+214, trs->bits_in_buf,</span><br><span style="color: hsl(120, 100%, 40%);">+                              (1 << TETRA_TRAIN_NORM_1)|</span><br><span style="color: hsl(120, 100%, 40%);">+                              (1 << TETRA_TRAIN_NORM_2)|</span><br><span style="color: hsl(120, 100%, 40%);">+                              (1 << TETRA_TRAIN_SYNC), &train_seq_offs);</span><br><span style="color: hsl(120, 100%, 40%);">+        train_seq_offs += 214;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if ((rc < 0) || (train_seq_offs + TETRA_BITS_PER_TS > trs->bits_in_buf))</span><br><span style="color: hsl(120, 100%, 40%);">+             return -conserve_bits(trs, 2*TETRA_BITS_PER_TS);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    tetra_tdma_time_add_tn(&t_phy_state.time, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("\nBURST @ %u", trs->bitbuf_start_bitnum+train_seq_offs);</span><br><span style="color: hsl(120, 100%, 40%);">+ DEBUGP(": %s", osmo_ubit_dump(trs->bitbuf, TETRA_BITS_PER_TS));</span><br><span style="color: hsl(120, 100%, 40%);">+  printf("\n");</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+     switch (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+ case TETRA_TRAIN_SYNC:</span><br><span style="color: hsl(120, 100%, 40%);">+                if (train_seq_offs >= 214)</span><br><span style="color: hsl(120, 100%, 40%);">+                 tetra_burst_rx_cb(trs->bitbuf+train_seq_offs-214, TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);</span><br><span>          break;</span><br><span style="color: hsl(0, 100%, 40%);">-  case RX_S_KNOW_FSTART:</span><br><span style="color: hsl(0, 100%, 40%);">-          /* we are locked, i.e. already know when the next frame should start */</span><br><span style="color: hsl(0, 100%, 40%);">-         if (trs->bitbuf_start_bitnum + trs->bits_in_buf < trs->next_frame_start_bitnum)</span><br><span style="color: hsl(0, 100%, 40%);">-                     return 0;</span><br><span style="color: hsl(0, 100%, 40%);">-               else {</span><br><span style="color: hsl(0, 100%, 40%);">-                  /* shift start of frame to start of bitbuf */</span><br><span style="color: hsl(0, 100%, 40%);">-                   int offset = trs->next_frame_start_bitnum - trs->bitbuf_start_bitnum;</span><br><span style="color: hsl(0, 100%, 40%);">-                     int bits_remaining = trs->bits_in_buf - offset;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                      memmove(trs->bitbuf, trs->bitbuf+offset, bits_remaining);</span><br><span style="color: hsl(0, 100%, 40%);">-                 trs->bits_in_buf = bits_remaining;</span><br><span style="color: hsl(0, 100%, 40%);">-                   trs->bitbuf_start_bitnum += offset;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                  trs->next_frame_start_bitnum += TETRA_BITS_PER_TS;</span><br><span style="color: hsl(0, 100%, 40%);">-                   trs->state = RX_S_LOCKED;</span><br><span style="color: hsl(0, 100%, 40%);">-            }</span><br><span style="color: hsl(0, 100%, 40%);">-       case RX_S_LOCKED:</span><br><span style="color: hsl(0, 100%, 40%);">-               if (trs->bits_in_buf < TETRA_BITS_PER_TS) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       /* not sufficient data for the full frame yet */</span><br><span style="color: hsl(0, 100%, 40%);">-                        return len;</span><br><span style="color: hsl(0, 100%, 40%);">-             } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                        /* we have successfully received (at least) one frame */</span><br><span style="color: hsl(0, 100%, 40%);">-                        tetra_tdma_time_add_tn(&t_phy_state.time, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-                       printf("\nBURST");</span><br><span style="color: hsl(0, 100%, 40%);">-                    DEBUGP(": %s", osmo_ubit_dump(trs->bitbuf, TETRA_BITS_PER_TS));</span><br><span style="color: hsl(0, 100%, 40%);">-                    printf("\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                 rc = tetra_find_train_seq(trs->bitbuf, trs->bits_in_buf,</span><br><span style="color: hsl(0, 100%, 40%);">-                                            (1 << TETRA_TRAIN_NORM_1)|</span><br><span style="color: hsl(0, 100%, 40%);">-                                                (1 << TETRA_TRAIN_NORM_2)|</span><br><span style="color: hsl(0, 100%, 40%);">-                                                (1 << TETRA_TRAIN_SYNC), &train_seq_offs);</span><br><span style="color: hsl(0, 100%, 40%);">-                  switch (rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                   case TETRA_TRAIN_SYNC:</span><br><span style="color: hsl(0, 100%, 40%);">-                          if (train_seq_offs == 214)</span><br><span style="color: hsl(0, 100%, 40%);">-                                      tetra_burst_rx_cb(trs->bitbuf, TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);</span><br><span style="color: hsl(0, 100%, 40%);">-                                else {</span><br><span style="color: hsl(0, 100%, 40%);">-                                  fprintf(stderr, "#### SYNC burst at offset %u?!?\n", train_seq_offs);</span><br><span style="color: hsl(0, 100%, 40%);">-                                 trs->state = RX_S_UNLOCKED;</span><br><span style="color: hsl(0, 100%, 40%);">-                          }</span><br><span style="color: hsl(0, 100%, 40%);">-                               break;</span><br><span style="color: hsl(0, 100%, 40%);">-                  case TETRA_TRAIN_NORM_1:</span><br><span style="color: hsl(0, 100%, 40%);">-                        case TETRA_TRAIN_NORM_2:</span><br><span style="color: hsl(0, 100%, 40%);">-                        case TETRA_TRAIN_NORM_3:</span><br><span style="color: hsl(0, 100%, 40%);">-                                if (train_seq_offs == 244)</span><br><span style="color: hsl(0, 100%, 40%);">-                                      tetra_burst_rx_cb(trs->bitbuf, TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);</span><br><span style="color: hsl(0, 100%, 40%);">-                                else</span><br><span style="color: hsl(0, 100%, 40%);">-                                    fprintf(stderr, "#### SYNC burst at offset %u?!?\n", train_seq_offs);</span><br><span style="color: hsl(0, 100%, 40%);">-                         break;</span><br><span style="color: hsl(0, 100%, 40%);">-                  default:</span><br><span style="color: hsl(0, 100%, 40%);">-                                fprintf(stderr, "#### could not find successive burst training sequence\n");</span><br><span style="color: hsl(0, 100%, 40%);">-                          trs->state = RX_S_UNLOCKED;</span><br><span style="color: hsl(0, 100%, 40%);">-                          break;</span><br><span style="color: hsl(0, 100%, 40%);">-                  }</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-                       /* move remainder to start of buffer */</span><br><span style="color: hsl(0, 100%, 40%);">-                 trs->bits_in_buf -= TETRA_BITS_PER_TS;</span><br><span style="color: hsl(0, 100%, 40%);">-                       memmove(trs->bitbuf, trs->bitbuf+TETRA_BITS_PER_TS, trs->bits_in_buf);</span><br><span style="color: hsl(0, 100%, 40%);">-                 trs->bitbuf_start_bitnum += TETRA_BITS_PER_TS;</span><br><span style="color: hsl(0, 100%, 40%);">-                       trs->next_frame_start_bitnum += TETRA_BITS_PER_TS;</span><br><span style="color: hsl(0, 100%, 40%);">-           }</span><br><span style="color: hsl(120, 100%, 40%);">+     case TETRA_TRAIN_NORM_1:</span><br><span style="color: hsl(120, 100%, 40%);">+      case TETRA_TRAIN_NORM_2:</span><br><span style="color: hsl(120, 100%, 40%);">+      case TETRA_TRAIN_NORM_3:</span><br><span style="color: hsl(120, 100%, 40%);">+              if (train_seq_offs >= 244)</span><br><span style="color: hsl(120, 100%, 40%);">+                 tetra_burst_rx_cb(trs->bitbuf+train_seq_offs-244, TETRA_BITS_PER_TS, rc, trs->burst_cb_priv);</span><br><span>          break;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(120, 100%, 40%);">+        default:</span><br><span style="color: hsl(120, 100%, 40%);">+              fprintf(stderr, "#### unsupported burst training sequence\n");</span><br><span style="color: hsl(120, 100%, 40%);">+              break;</span><br><span>       }</span><br><span style="color: hsl(0, 100%, 40%);">-       return len;</span><br><span style="color: hsl(120, 100%, 40%);">+   return train_seq_offs+1;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> }</span><br><span>diff --git a/src/phy/tetra_burst_sync.h b/src/phy/tetra_burst_sync.h</span><br><span>index 7862461..4ec8b53 100644</span><br><span>--- a/src/phy/tetra_burst_sync.h</span><br><span>+++ b/src/phy/tetra_burst_sync.h</span><br><span>@@ -3,6 +3,8 @@</span><br><span> </span><br><span> #include <stdint.h></span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define BUFSIZE 4096</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> enum rx_state {</span><br><span>       RX_S_UNLOCKED,          /* we're completely unlocked */</span><br><span>  RX_S_KNOW_FSTART,       /* we know the next frame start */</span><br><span>@@ -12,7 +14,7 @@</span><br><span> struct tetra_rx_state {</span><br><span>    enum rx_state state;</span><br><span>         unsigned int bits_in_buf;               /* how many bits are currently in bitbuf */</span><br><span style="color: hsl(0, 100%, 40%);">-     uint8_t bitbuf[4096];</span><br><span style="color: hsl(120, 100%, 40%);">+ uint8_t bitbuf[BUFSIZE];</span><br><span>     unsigned int bitbuf_start_bitnum;       /* bit number at first element in bitbuf */</span><br><span>  unsigned int next_frame_start_bitnum;   /* frame start expected at this bitnum */</span><br><span> </span><br><span>diff --git a/src/tetra-rx.c b/src/tetra-rx.c</span><br><span>index 8498f8c..78bdfea 100644</span><br><span>--- a/src/tetra-rx.c</span><br><span>+++ b/src/tetra-rx.c</span><br><span>@@ -95,19 +95,29 @@</span><br><span>     if (pcap_file_path)</span><br><span>          tetra_gsmtap_init_file(pcap_file_path);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     while (1) {</span><br><span style="color: hsl(0, 100%, 40%);">-             uint8_t buf[64];</span><br><span style="color: hsl(0, 100%, 40%);">-                int len;</span><br><span style="color: hsl(120, 100%, 40%);">+      int to_consume = BUFSIZE;</span><br><span style="color: hsl(120, 100%, 40%);">+     uint8_t buf[BUFSIZE];</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-               len = read(fd, buf, sizeof(buf));</span><br><span style="color: hsl(120, 100%, 40%);">+     while (1) {</span><br><span style="color: hsl(120, 100%, 40%);">+           int len, rlen;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+              len = read(fd, buf, to_consume);</span><br><span>             if (len < 0) {</span><br><span>                    perror("read");</span><br><span>                    exit(1);</span><br><span style="color: hsl(0, 100%, 40%);">-                } else if (len == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                }</span><br><span style="color: hsl(120, 100%, 40%);">+             rlen = len;</span><br><span style="color: hsl(120, 100%, 40%);">+           if (len == 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                       memset(buf, 0, BUFSIZE);</span><br><span style="color: hsl(120, 100%, 40%);">+                      rlen = to_consume;</span><br><span style="color: hsl(120, 100%, 40%);">+            }</span><br><span style="color: hsl(120, 100%, 40%);">+             int rc = tetra_burst_sync_in(trs, buf, rlen);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               if (len == 0 && rc <= 0) {</span><br><span>                        printf("EOF");</span><br><span>                     break;</span><br><span>               }</span><br><span style="color: hsl(0, 100%, 40%);">-               tetra_burst_sync_in(trs, buf, len);</span><br><span style="color: hsl(120, 100%, 40%);">+           to_consume = MIN(abs(rc), BUFSIZE);</span><br><span>  }</span><br><span> </span><br><span>        free(tms->dumpdir);</span><br><span>diff --git a/src/tetra_common.h b/src/tetra_common.h</span><br><span>index a270a26..c63e6ca 100644</span><br><span>--- a/src/tetra_common.h</span><br><span>+++ b/src/tetra_common.h</span><br><span>@@ -11,6 +11,10 @@</span><br><span> #define DEBUGP(x, args...)  do { } while(0)</span><br><span> #endif</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+#define MIN(a, b)                (((a) < (b))?(a):(b))</span><br><span style="color: hsl(120, 100%, 40%);">+#define MAX(a, b)             (((a) > (b))?(a):(b))</span><br><span style="color: hsl(120, 100%, 40%);">+#define CLAMP(x, lower, upper)        (MIN(upper, MAX(x, lower)))</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> #define TETRA_SYM_PER_TS       255</span><br><span> #define TETRA_BITS_PER_TS        (TETRA_SYM_PER_TS*2)</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10271">change 10271</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/10271"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-tetra </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: I74a13ced4c11b6d98afa7916c1f4109875c20101 </div>
<div style="display:none"> Gerrit-Change-Number: 10271 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Jan Hrach <jenda.2vf9h@hrach.eu> </div>