<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>