<p>Vadim Yanitskiy has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/13723">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">osmo-bts-trx/scheduler: distinguish synch. sequence of RACH bursts<br><br>WIP/TODO: add detailed description here (please read the code).<br><br>At least it makes both TC_rach_content and TC_rach_count TTCN-3<br>test cases pass again. There were some collisions between the<br>extended (11-bit) RACH bursts and the regular ones, since we<br>used to call gsm0503_rach_ext_decode_ber() first, regardless<br>of the burst type...<br><br>To be 100% sure, we need a similar TTCN-3 test case for the<br>extended (11-bit) RACH. This would require to do some little<br>changes in both trxcon and the L1CTL protocol.<br><br>Change-Id: Ibb6d27c6589965c8b59a6d2598a7c43fd860f284<br>---<br>M src/osmo-bts-trx/scheduler_trx.c<br>1 file changed, 124 insertions(+), 42 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/23/13723/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c</span><br><span>index 32bdb98..81bb48d 100644</span><br><span>--- a/src/osmo-bts-trx/scheduler_trx.c</span><br><span>+++ b/src/osmo-bts-trx/scheduler_trx.c</span><br><span>@@ -709,72 +709,154 @@</span><br><span>  * RX on uplink (indication to upper layer)</span><br><span>  */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* 3GPP TS 05.02, section 5.2.7 */</span><br><span style="color: hsl(120, 100%, 40%);">+#define RACH_EXT_TAIL_LEN        8</span><br><span style="color: hsl(120, 100%, 40%);">+#define RACH_SYNCH_SEQ_LEN   41</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+enum rach_synch_seq_t {</span><br><span style="color: hsl(120, 100%, 40%);">+ RACH_SYNCH_SEQ_UNKNOWN = -1,</span><br><span style="color: hsl(120, 100%, 40%);">+  RACH_SYNCH_SEQ_TS0, /* GSM, GMSK (default) */</span><br><span style="color: hsl(120, 100%, 40%);">+ RACH_SYNCH_SEQ_TS1, /* EGPRS, 8-PSK */</span><br><span style="color: hsl(120, 100%, 40%);">+        RACH_SYNCH_SEQ_TS2, /* EGPRS, GMSK */</span><br><span style="color: hsl(120, 100%, 40%);">+ RACH_SYNCH_SEQ_NUM</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct value_string rach_synch_seq_names[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+       { RACH_SYNCH_SEQ_UNKNOWN,       "UNKNOWN" },</span><br><span style="color: hsl(120, 100%, 40%);">+        { RACH_SYNCH_SEQ_TS0,           "TS0: GSM, GMSK" },</span><br><span style="color: hsl(120, 100%, 40%);">+ { RACH_SYNCH_SEQ_TS1,           "TS1: EGPRS, 8-PSK" },</span><br><span style="color: hsl(120, 100%, 40%);">+      { RACH_SYNCH_SEQ_TS2,           "TS2: EGPRS, GMSK" },</span><br><span style="color: hsl(120, 100%, 40%);">+       { 0, NULL },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static enum rach_synch_seq_t rach_get_synch_seq(sbit_t *bits, float *certitude)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        sbit_t *synch_seq_burst = bits + RACH_EXT_TAIL_LEN;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int score[RACH_SYNCH_SEQ_NUM] = { 0 };</span><br><span style="color: hsl(120, 100%, 40%);">+       unsigned int max_score = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int i, j;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* 3GPP TS 05.02, section 5.2.7 "Access burst (AB)", synch. sequence bits */</span><br><span style="color: hsl(120, 100%, 40%);">+        static const char synch_seq_ref[RACH_SYNCH_SEQ_NUM][RACH_SYNCH_SEQ_LEN] = {</span><br><span style="color: hsl(120, 100%, 40%);">+           [RACH_SYNCH_SEQ_TS0] = "01001011011111111001100110101010001111000",</span><br><span style="color: hsl(120, 100%, 40%);">+         [RACH_SYNCH_SEQ_TS1] = "01010100111110001000011000101111001001101",</span><br><span style="color: hsl(120, 100%, 40%);">+         [RACH_SYNCH_SEQ_TS2] = "11101111001001110101011000001101101110111",</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 RACH_SYNCH_SEQ_MATCH(seq_ref) \</span><br><span style="color: hsl(120, 100%, 40%);">+ (seq_ref[j] == '1' ? synch_seq_burst[j] < 0 : synch_seq_burst[j] >= 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define RACH_SYNCH_SEQ_SCORE(seq_ref) \</span><br><span style="color: hsl(120, 100%, 40%);">+       (RACH_SYNCH_SEQ_MATCH(seq_ref) ? abs(synch_seq_burst[j]) : 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* For each synch. sequence, count the bit match score. Since we deal with</span><br><span style="color: hsl(120, 100%, 40%);">+     * soft-bits (-127...127), we sum the absolute values of matching ones, so</span><br><span style="color: hsl(120, 100%, 40%);">+     * the resulting scores are more accurate than it could be with hard-bits. */</span><br><span style="color: hsl(120, 100%, 40%);">+ for (i = 0; i < RACH_SYNCH_SEQ_NUM; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+         for (j = 0; j < RACH_SYNCH_SEQ_LEN; j++)</span><br><span style="color: hsl(120, 100%, 40%);">+                   score[i] += RACH_SYNCH_SEQ_SCORE(synch_seq_ref[i]);</span><br><span style="color: hsl(120, 100%, 40%);">+           /* Keep the maximum value updated */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (max_score < score[i])</span><br><span style="color: hsl(120, 100%, 40%);">+                  max_score = score[i];</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%);">+   /* Calculate an approximate level of our confidence */</span><br><span style="color: hsl(120, 100%, 40%);">+        if (certitude != NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+                *certitude = max_score * 100 / (RACH_SYNCH_SEQ_LEN * 127);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* At least 1/3 of a synch. sequence shall match */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (max_score < (127 * RACH_SYNCH_SEQ_LEN / 3))</span><br><span style="color: hsl(120, 100%, 40%);">+            return RACH_SYNCH_SEQ_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Which synch. sequence is the best? */</span><br><span style="color: hsl(120, 100%, 40%);">+      else if (max_score == score[RACH_SYNCH_SEQ_TS0])</span><br><span style="color: hsl(120, 100%, 40%);">+              return RACH_SYNCH_SEQ_TS0;</span><br><span style="color: hsl(120, 100%, 40%);">+    else if (max_score == score[RACH_SYNCH_SEQ_TS1])</span><br><span style="color: hsl(120, 100%, 40%);">+              return RACH_SYNCH_SEQ_TS1;</span><br><span style="color: hsl(120, 100%, 40%);">+    else if (max_score == score[RACH_SYNCH_SEQ_TS2])</span><br><span style="color: hsl(120, 100%, 40%);">+              return RACH_SYNCH_SEQ_TS2;</span><br><span style="color: hsl(120, 100%, 40%);">+    else /* Shall not happen in general */</span><br><span style="color: hsl(120, 100%, 40%);">+                return RACH_SYNCH_SEQ_UNKNOWN;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,</span><br><span>      enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,</span><br><span>  int8_t rssi, int16_t toa256)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-       uint8_t chan_nr;</span><br><span>     struct osmo_phsap_prim l1sap;</span><br><span>        int n_errors, n_bits_total;</span><br><span style="color: hsl(0, 100%, 40%);">-     bool is_11bit = true;</span><br><span>        uint16_t ra11;</span><br><span>       uint8_t ra;</span><br><span style="color: hsl(0, 100%, 40%);">-     int rc = 1;</span><br><span style="color: hsl(120, 100%, 40%);">+   int rc;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-     chan_nr = trx_chan_desc[chan].chan_nr | tn;</span><br><span style="color: hsl(120, 100%, 40%);">+   /* It would be great if the transceiver were doing some kind of tagging,</span><br><span style="color: hsl(120, 100%, 40%);">+       * whether it is extended (11-bit) RACH or not. We would not need to guess</span><br><span style="color: hsl(120, 100%, 40%);">+     * it here. For now, let's try to correlate the synch. sequence of a received</span><br><span style="color: hsl(120, 100%, 40%);">+      * Access Burst with the known ones (3GPP TS 05.02, section 5.2.7), and</span><br><span style="color: hsl(120, 100%, 40%);">+        * fall-back to the default TS0 if it fails. This would save some CPU</span><br><span style="color: hsl(120, 100%, 40%);">+  * power, and what is more important - prevent possible collisions. */</span><br><span style="color: hsl(120, 100%, 40%);">+        enum rach_synch_seq_t synch_seq = RACH_SYNCH_SEQ_TS0;</span><br><span style="color: hsl(120, 100%, 40%);">+ float certitude = 100;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received RACH toa=%d\n", toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Handover RACH cannot be extended (11-bit) */</span><br><span style="color: hsl(120, 100%, 40%);">+       if (chan == TRXC_RACH)</span><br><span style="color: hsl(120, 100%, 40%);">+                synch_seq = rach_get_synch_seq(bits, &certitude);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       if (chan == TRXC_RACH) /* Attempt to decode as extended (11-bit) RACH first */</span><br><span style="color: hsl(0, 100%, 40%);">-          rc = gsm0503_rach_ext_decode_ber(&ra11, bits + 8 + 41,</span><br><span style="color: hsl(120, 100%, 40%);">+    LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received RACH (%s; confidence=%.1f%%) toa=%d\n",</span><br><span style="color: hsl(120, 100%, 40%);">+              get_value_string(rach_synch_seq_names, synch_seq), certitude, toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Compose a new L1SAP primitive */</span><br><span style="color: hsl(120, 100%, 40%);">+   memset(&l1sap, 0x00, sizeof(l1sap));</span><br><span style="color: hsl(120, 100%, 40%);">+      osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION, NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+   l1sap.u.rach_ind.chan_nr = trx_chan_desc[chan].chan_nr | tn;</span><br><span style="color: hsl(120, 100%, 40%);">+  l1sap.u.rach_ind.acc_delay = (toa256 >= 0) ? toa256 / 256 : 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     l1sap.u.rach_ind.acc_delay_256bits = toa256;</span><br><span style="color: hsl(120, 100%, 40%);">+  l1sap.u.rach_ind.rssi = rssi;</span><br><span style="color: hsl(120, 100%, 40%);">+ l1sap.u.rach_ind.fn = fn;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Decode RACH depending on its synch. sequence */</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (synch_seq) {</span><br><span style="color: hsl(120, 100%, 40%);">+  case RACH_SYNCH_SEQ_TS1:</span><br><span style="color: hsl(120, 100%, 40%);">+      case RACH_SYNCH_SEQ_TS2:</span><br><span style="color: hsl(120, 100%, 40%);">+              rc = gsm0503_rach_ext_decode_ber(&ra11, bits + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN,</span><br><span>                                            l1t->trx->bts->bsic, &n_errors, &n_bits_total);</span><br><span style="color: hsl(0, 100%, 40%);">-       if (rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-               /* Indicate non-extended RACH */</span><br><span style="color: hsl(0, 100%, 40%);">-                is_11bit = false;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-               /* Fall-back to the normal RACH decoding */</span><br><span style="color: hsl(0, 100%, 40%);">-             rc = gsm0503_rach_decode_ber(&ra, bits + 8 + 41,</span><br><span style="color: hsl(0, 100%, 40%);">-                    l1t->trx->bts->bsic, &n_errors, &n_bits_total);</span><br><span>             if (rc) {</span><br><span style="color: hsl(0, 100%, 40%);">-                       LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad AB frame\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad Access Burst\n");</span><br><span>                        return 0;</span><br><span>            }</span><br><span style="color: hsl(0, 100%, 40%);">-       }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* compose primitive */</span><br><span style="color: hsl(0, 100%, 40%);">- /* generate prim */</span><br><span style="color: hsl(0, 100%, 40%);">-     memset(&l1sap, 0, sizeof(l1sap));</span><br><span style="color: hsl(0, 100%, 40%);">-   osmo_prim_init(&l1sap.oph, SAP_GSM_PH, PRIM_PH_RACH, PRIM_OP_INDICATION,</span><br><span style="color: hsl(0, 100%, 40%);">-            NULL);</span><br><span style="color: hsl(0, 100%, 40%);">-  l1sap.u.rach_ind.chan_nr = chan_nr;</span><br><span style="color: hsl(0, 100%, 40%);">-     l1sap.u.rach_ind.acc_delay = (toa256 >= 0) ? toa256/256 : 0;</span><br><span style="color: hsl(0, 100%, 40%);">- l1sap.u.rach_ind.fn = fn;</span><br><span style="color: hsl(0, 100%, 40%);">-       l1sap.u.rach_ind.rssi = rssi;</span><br><span style="color: hsl(0, 100%, 40%);">-   l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors);</span><br><span style="color: hsl(0, 100%, 40%);">-       l1sap.u.rach_ind.acc_delay_256bits = toa256;</span><br><span style="color: hsl(120, 100%, 40%);">+          if (synch_seq == RACH_SYNCH_SEQ_TS1)</span><br><span style="color: hsl(120, 100%, 40%);">+                  l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_1;</span><br><span style="color: hsl(120, 100%, 40%);">+             else</span><br><span style="color: hsl(120, 100%, 40%);">+                  l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_2;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   if (is_11bit) {</span><br><span>              l1sap.u.rach_ind.is_11bit = 1;</span><br><span>               l1sap.u.rach_ind.ra = ra11;</span><br><span style="color: hsl(0, 100%, 40%);">-             l1sap.u.rach_ind.burst_type = BSIC2BCC(l1t->trx->bts->bsic);</span><br><span style="color: hsl(0, 100%, 40%);">-           switch (l1sap.u.rach_ind.burst_type) {</span><br><span style="color: hsl(0, 100%, 40%);">-          case GSM_L1_BURST_TYPE_ACCESS_0:</span><br><span style="color: hsl(0, 100%, 40%);">-                case GSM_L1_BURST_TYPE_ACCESS_1:</span><br><span style="color: hsl(0, 100%, 40%);">-                case GSM_L1_BURST_TYPE_ACCESS_2:</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%);">-                        LOGL1S(DL1P, LOGL_NOTICE, l1t, tn, chan, fn,</span><br><span style="color: hsl(0, 100%, 40%);">-                           "Received RACH frame with unexpected TSC %u, "</span><br><span style="color: hsl(0, 100%, 40%);">-                        "forcing default %u\n", l1sap.u.rach_ind.burst_type,</span><br><span style="color: hsl(0, 100%, 40%);">-                          GSM_L1_BURST_TYPE_ACCESS_0);</span><br><span style="color: hsl(0, 100%, 40%);">-                     l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      case RACH_SYNCH_SEQ_TS0:</span><br><span style="color: hsl(120, 100%, 40%);">+      default:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Fall-back to the default TS0 if needed */</span><br><span style="color: hsl(120, 100%, 40%);">+          if (synch_seq != RACH_SYNCH_SEQ_TS0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                        LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Falling-back to the default TS0\n");</span><br><span style="color: hsl(120, 100%, 40%);">+                   synch_seq = RACH_SYNCH_SEQ_TS0;</span><br><span>              }</span><br><span style="color: hsl(0, 100%, 40%);">-       } else {</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+            rc = gsm0503_rach_decode_ber(&ra, bits + RACH_EXT_TAIL_LEN + RACH_SYNCH_SEQ_LEN,</span><br><span style="color: hsl(120, 100%, 40%);">+                                       l1t->trx->bts->bsic, &n_errors, &n_bits_total);</span><br><span style="color: hsl(120, 100%, 40%);">+         if (rc) {</span><br><span style="color: hsl(120, 100%, 40%);">+                     LOGL1S(DL1P, LOGL_DEBUG, l1t, tn, chan, fn, "Received bad Access Burst\n");</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%);">+           l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;</span><br><span>            l1sap.u.rach_ind.is_11bit = 0;</span><br><span>               l1sap.u.rach_ind.ra = ra;</span><br><span style="color: hsl(0, 100%, 40%);">-               l1sap.u.rach_ind.burst_type = GSM_L1_BURST_TYPE_ACCESS_0;</span><br><span style="color: hsl(120, 100%, 40%);">+             break;</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ l1sap.u.rach_ind.ber10k = compute_ber10k(n_bits_total, n_errors);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* forward primitive */</span><br><span>      l1sap_up(l1t->trx, &l1sap);</span><br><span> </span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/13723">change 13723</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/13723"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmo-bts </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>
<div style="display:none"> Gerrit-Change-Id: Ibb6d27c6589965c8b59a6d2598a7c43fd860f284 </div>
<div style="display:none"> Gerrit-Change-Number: 13723 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: Vadim Yanitskiy <axilirator@gmail.com> </div>