<p>laforge <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmocom-bb/+/17350">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  laforge: Looks good to me, approved
  Jenkins Builder: Verified

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">trxcon/scheduler: refactor Downlink measurement processing<br><br>So far we used to store the sums of ToA and RSSI measurements in the<br>logical channel state, and after decoding of a block, we did calculate<br>the average. This approach works fine for xCCH and PDTCH, but when it<br>comes to block-diagonal interleaving (which is used on TCH/F and TCH/H<br>channels), the results are incorrect. The problem is that a burst on<br>TCH may carry 57 bits of one encoded frame and 57 bits of another.<br><br>Instead of calculating the sum of measurements on the fly, let's push<br>them into a circular buffer (the measurement history), and keep them<br>there even after decoding of a block. This would allow us to calculate<br>the average of N last measurements depending on the interleaving type.<br><br>A single circular buffer can hold up to 8 unique measurements, so the<br>recent measurements would basically override the oldest ones.<br><br>Change-Id: I211ee3314f0a284112a4deddc0e93028f4a27cef<br>---<br>M src/host/trxcon/sched_lchan_common.c<br>M src/host/trxcon/sched_lchan_desc.c<br>M src/host/trxcon/sched_lchan_pdtch.c<br>M src/host/trxcon/sched_lchan_sch.c<br>M src/host/trxcon/sched_lchan_tchf.c<br>M src/host/trxcon/sched_lchan_tchh.c<br>M src/host/trxcon/sched_lchan_xcch.c<br>M src/host/trxcon/sched_trx.c<br>M src/host/trxcon/sched_trx.h<br>M src/host/trxcon/trx_if.c<br>10 files changed, 140 insertions(+), 74 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/host/trxcon/sched_lchan_common.c b/src/host/trxcon/sched_lchan_common.c</span><br><span>index 813f315..55ec7e9 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_common.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_common.c</span><br><span>@@ -126,9 +126,9 @@</span><br><span>  struct trx_lchan_state *lchan, uint8_t *l2, size_t l2_len,</span><br><span>   int bit_error_count, bool dec_failed, bool traffic)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct trx_meas_set *meas = &lchan->meas_avg;</span><br><span>   const struct trx_lchan_desc *lchan_desc;</span><br><span>     struct l1ctl_info_dl dl_hdr;</span><br><span style="color: hsl(0, 100%, 40%);">-    int dbm_avg = 0;</span><br><span> </span><br><span>         /* Set up pointers */</span><br><span>        lchan_desc = &trx_lchan_desc[lchan->type];</span><br><span>@@ -140,15 +140,8 @@</span><br><span>     dl_hdr.frame_nr = htonl(lchan->rx_first_fn);</span><br><span>      dl_hdr.num_biterr = bit_error_count;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* Convert average RSSI to RX level */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (lchan->meas.num) {</span><br><span style="color: hsl(0, 100%, 40%);">-               /* RX level: 0 .. 63 in typical GSM notation (dBm + 110) */</span><br><span style="color: hsl(0, 100%, 40%);">-             dbm_avg = lchan->meas.rssi_sum / lchan->meas.num;</span><br><span style="color: hsl(0, 100%, 40%);">-         dl_hdr.rx_level = dbm2rxlev(dbm_avg);</span><br><span style="color: hsl(0, 100%, 40%);">-   } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                /* No measurements, assuming the worst */</span><br><span style="color: hsl(0, 100%, 40%);">-               dl_hdr.rx_level = 0;</span><br><span style="color: hsl(0, 100%, 40%);">-    }</span><br><span style="color: hsl(120, 100%, 40%);">+     /* RX level: 0 .. 63 in typical GSM notation (dBm + 110) */</span><br><span style="color: hsl(120, 100%, 40%);">+   dl_hdr.rx_level = dbm2rxlev(meas->rssi);</span><br><span> </span><br><span>      /* FIXME: set proper values */</span><br><span>       dl_hdr.snr = 0;</span><br><span>@@ -162,7 +155,7 @@</span><br><span>        /* Optional GSMTAP logging */</span><br><span>        if (l2_len > 0 && (!traffic || lchan_desc->chan_nr == RSL_CHAN_OSMO_PDCH)) {</span><br><span>           sched_gsmtap_send(lchan->type, lchan->rx_first_fn, ts->index,</span><br><span style="color: hsl(0, 100%, 40%);">-                            trx->band_arfcn, dbm_avg, 0, l2, l2_len);</span><br><span style="color: hsl(120, 100%, 40%);">+                                  trx->band_arfcn, meas->rssi, 0, l2, l2_len);</span><br><span>         }</span><br><span> </span><br><span>        return 0;</span><br><span>diff --git a/src/host/trxcon/sched_lchan_desc.c b/src/host/trxcon/sched_lchan_desc.c</span><br><span>index b22a18b..1184e5b 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_desc.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_desc.c</span><br><span>@@ -31,35 +31,35 @@</span><br><span> /* Forward declaration of handlers */</span><br><span> int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>         struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+   sbit_t *bits, const struct trx_meas_set *meas);</span><br><span> </span><br><span> int tx_data_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>   struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid);</span><br><span> </span><br><span> int rx_sch_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>  struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+   sbit_t *bits, const struct trx_meas_set *meas);</span><br><span> </span><br><span> int tx_rach_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>   struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid);</span><br><span> </span><br><span> int rx_tchf_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>         struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+   sbit_t *bits, const struct trx_meas_set *meas);</span><br><span> </span><br><span> int tx_tchf_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>   struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid);</span><br><span> </span><br><span> int rx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>         struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+   sbit_t *bits, const struct trx_meas_set *meas);</span><br><span> </span><br><span> int tx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>   struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid);</span><br><span> </span><br><span> int rx_pdtch_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>        struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+   sbit_t *bits, const struct trx_meas_set *meas);</span><br><span> </span><br><span> int tx_pdtch_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>  struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid);</span><br><span>diff --git a/src/host/trxcon/sched_lchan_pdtch.c b/src/host/trxcon/sched_lchan_pdtch.c</span><br><span>index 83a6f53..4fd7d35 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_pdtch.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_pdtch.c</span><br><span>@@ -2,7 +2,7 @@</span><br><span>  * OsmocomBB <-> SDR connection bridge</span><br><span>  * TDMA scheduler: handlers for DL / UL bursts on logical channels</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>  *</span><br><span>@@ -42,7 +42,7 @@</span><br><span> </span><br><span> int rx_pdtch_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>  struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256)</span><br><span style="color: hsl(120, 100%, 40%);">+    sbit_t *bits, const struct trx_meas_set *meas)</span><br><span> {</span><br><span>  const struct trx_lchan_desc *lchan_desc;</span><br><span>     uint8_t l2[GPRS_L2_MAX_LEN], *mask;</span><br><span>@@ -62,9 +62,6 @@</span><br><span> </span><br><span>  /* Reset internal state */</span><br><span>   if (bid == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         /* Clean up old measurements */</span><br><span style="color: hsl(0, 100%, 40%);">-         memset(&lchan->meas, 0x00, sizeof(lchan->meas));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>           *first_fn = fn;</span><br><span>              *mask = 0x0;</span><br><span>         }</span><br><span>@@ -72,10 +69,8 @@</span><br><span>       /* Update mask */</span><br><span>    *mask |= (1 << bid);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /* Update measurements */</span><br><span style="color: hsl(0, 100%, 40%);">-       lchan->meas.toa256_sum += toa256;</span><br><span style="color: hsl(0, 100%, 40%);">-    lchan->meas.rssi_sum += rssi;</span><br><span style="color: hsl(0, 100%, 40%);">-        lchan->meas.num++;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Store the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+  sched_trx_meas_push(lchan, meas);</span><br><span> </span><br><span>        /* Copy burst to buffer of 4 bursts */</span><br><span>       offset = buffer + bid * 116;</span><br><span>@@ -86,6 +81,9 @@</span><br><span>     if (bid != 3)</span><br><span>                return 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Calculate AVG of the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+       sched_trx_meas_avg(lchan, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /* Check for complete set of bursts */</span><br><span>       if ((*mask & 0xf) != 0xf) {</span><br><span>              LOGP(DSCHD, LOGL_ERROR, "Received incomplete (%s) data frame at "</span><br><span>diff --git a/src/host/trxcon/sched_lchan_sch.c b/src/host/trxcon/sched_lchan_sch.c</span><br><span>index 9eed506..17f68b0 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_sch.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_sch.c</span><br><span>@@ -70,7 +70,7 @@</span><br><span> </span><br><span> int rx_sch_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>   struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256)</span><br><span style="color: hsl(120, 100%, 40%);">+    sbit_t *bits, const struct trx_meas_set *meas)</span><br><span> {</span><br><span>  sbit_t payload[2 * 39];</span><br><span>      struct gsm_time time;</span><br><span>@@ -117,7 +117,7 @@</span><br><span>  data->link_id = trx_lchan_desc[lchan->type].link_id;</span><br><span>   data->band_arfcn = htons(trx->band_arfcn);</span><br><span>     data->frame_nr = htonl(fn);</span><br><span style="color: hsl(0, 100%, 40%);">-  data->rx_level = -rssi;</span><br><span style="color: hsl(120, 100%, 40%);">+    data->rx_level = -(meas->rssi);</span><br><span> </span><br><span>    /* FIXME: set proper values */</span><br><span>       data->num_biterr = 0;</span><br><span>diff --git a/src/host/trxcon/sched_lchan_tchf.c b/src/host/trxcon/sched_lchan_tchf.c</span><br><span>index 0109280..d2cf030 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_tchf.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_tchf.c</span><br><span>@@ -2,7 +2,7 @@</span><br><span>  * OsmocomBB <-> SDR connection bridge</span><br><span>  * TDMA scheduler: handlers for DL / UL bursts on logical channels</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2017 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2017-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>  *</span><br><span>@@ -44,7 +44,7 @@</span><br><span> </span><br><span> int rx_tchf_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>        struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256)</span><br><span style="color: hsl(120, 100%, 40%);">+    sbit_t *bits, const struct trx_meas_set *meas)</span><br><span> {</span><br><span>  const struct trx_lchan_desc *lchan_desc;</span><br><span>     int n_errors = -1, n_bits_total, rc;</span><br><span>@@ -64,9 +64,6 @@</span><br><span> </span><br><span>         /* Reset internal state */</span><br><span>   if (bid == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         /* Clean up old measurements */</span><br><span style="color: hsl(0, 100%, 40%);">-         memset(&lchan->meas, 0x00, sizeof(lchan->meas));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>           *first_fn = fn;</span><br><span>              *mask = 0x00;</span><br><span>        }</span><br><span>@@ -74,10 +71,8 @@</span><br><span>       /* Update mask */</span><br><span>    *mask |= (1 << bid);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /* Update mask and RSSI */</span><br><span style="color: hsl(0, 100%, 40%);">-      lchan->meas.rssi_sum += rssi;</span><br><span style="color: hsl(0, 100%, 40%);">-        lchan->meas.toa256_sum += toa256;</span><br><span style="color: hsl(0, 100%, 40%);">-    lchan->meas.num++;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Store the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+  sched_trx_meas_push(lchan, meas);</span><br><span> </span><br><span>        /* Copy burst to end of buffer of 8 bursts */</span><br><span>        offset = buffer + bid * 116 + 464;</span><br><span>@@ -88,6 +83,9 @@</span><br><span>       if (bid != 3)</span><br><span>                return 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Calculate AVG of the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+       sched_trx_meas_avg(lchan, 8);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /* Check for complete set of bursts */</span><br><span>       if ((*mask & 0xf) != 0xf) {</span><br><span>              LOGP(DSCHD, LOGL_ERROR, "Received incomplete (%s) traffic frame at "</span><br><span>@@ -150,9 +148,14 @@</span><br><span>                n_errors, false, true);</span><br><span> </span><br><span> bfi:</span><br><span style="color: hsl(0, 100%, 40%);">-     /* Didn't try to decode */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (n_errors < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Didn't try to decode, fake measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (n_errors < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->meas_avg = (struct trx_meas_set) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  .toa256 = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                  .rssi = -110,</span><br><span style="color: hsl(120, 100%, 40%);">+         };</span><br><span>           n_errors = 116 * 4;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span> </span><br><span>        /* BFI is not applicable in signalling mode */</span><br><span>       if (lchan->tch_mode == GSM48_CMODE_SIGN)</span><br><span>diff --git a/src/host/trxcon/sched_lchan_tchh.c b/src/host/trxcon/sched_lchan_tchh.c</span><br><span>index 8288670..599dd20 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_tchh.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_tchh.c</span><br><span>@@ -2,7 +2,7 @@</span><br><span>  * OsmocomBB <-> SDR connection bridge</span><br><span>  * TDMA scheduler: handlers for DL / UL bursts on logical channels</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2018 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2018-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span>  * (C) 2018 by Harald Welte <laforge@gnumonks.org></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>@@ -200,7 +200,7 @@</span><br><span> </span><br><span> int rx_tchh_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>     struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256)</span><br><span style="color: hsl(120, 100%, 40%);">+    sbit_t *bits, const struct trx_meas_set *meas)</span><br><span> {</span><br><span>  const struct trx_lchan_desc *lchan_desc;</span><br><span>     int n_errors = -1, n_bits_total, rc;</span><br><span>@@ -234,16 +234,8 @@</span><br><span>  /* Update mask */</span><br><span>    *mask |= (1 << bid);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /**</span><br><span style="color: hsl(0, 100%, 40%);">-      * FIXME: properly update measurements</span><br><span style="color: hsl(0, 100%, 40%);">-   *</span><br><span style="color: hsl(0, 100%, 40%);">-       * Since TCH/H channel is using block-diagonal interleaving,</span><br><span style="color: hsl(0, 100%, 40%);">-     * a single burst may carry 57 bits of one encoded frame,</span><br><span style="color: hsl(0, 100%, 40%);">-        * and 57 bits of another. This should be taken into account.</span><br><span style="color: hsl(0, 100%, 40%);">-    */</span><br><span style="color: hsl(0, 100%, 40%);">-     lchan->meas.rssi_sum += rssi;</span><br><span style="color: hsl(0, 100%, 40%);">-        lchan->meas.toa256_sum += toa256;</span><br><span style="color: hsl(0, 100%, 40%);">-    lchan->meas.num++;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Store the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+  sched_trx_meas_push(lchan, meas);</span><br><span> </span><br><span>        /* Copy burst to the end of buffer of 6 bursts */</span><br><span>    offset = buffer + bid * 116 + 464;</span><br><span>@@ -303,6 +295,9 @@</span><br><span>                     "fn=%u on %s (rc=%d)\n", burst_mask2str(mask, 6),</span><br><span>                  fn, lchan_desc->name, rc);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+             /* Calculate AVG of the measurements (assuming 4 bursts) */</span><br><span style="color: hsl(120, 100%, 40%);">+           sched_trx_meas_avg(lchan, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>              /* Send BFI */</span><br><span>               goto bfi;</span><br><span>    } else if (rc == GSM_MACBLOCK_LEN) {</span><br><span>@@ -313,6 +308,9 @@</span><br><span>           lchan->rx_first_fn = sched_tchh_block_dl_first_fn(lchan->type,</span><br><span>                         fn, true); /* FACCH/H */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+          /* Calculate AVG of the measurements (FACCH/H takes 6 bursts) */</span><br><span style="color: hsl(120, 100%, 40%);">+              sched_trx_meas_avg(lchan, 6);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>              /* FACCH/H received, forward to the higher layers */</span><br><span>                 sched_send_dt_ind(trx, ts, lchan, l2, GSM_MACBLOCK_LEN,</span><br><span>                      n_errors, false, false);</span><br><span>@@ -322,6 +320,9 @@</span><br><span>       } else {</span><br><span>             /* A good TCH frame received */</span><br><span>              l2_len = rc;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Calculate AVG of the measurements (traffic takes 4 bursts) */</span><br><span style="color: hsl(120, 100%, 40%);">+              sched_trx_meas_avg(lchan, 4);</span><br><span>        }</span><br><span> </span><br><span>        /* Calculate TDMA frame number of the first burst */</span><br><span>@@ -341,9 +342,14 @@</span><br><span>  *mask = *mask << 2;</span><br><span> </span><br><span> bfi:</span><br><span style="color: hsl(0, 100%, 40%);">-   /* Didn't try to decode */</span><br><span style="color: hsl(0, 100%, 40%);">-  if (n_errors < 0)</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Didn't try to decode, fake measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (n_errors < 0) {</span><br><span style="color: hsl(120, 100%, 40%);">+                lchan->meas_avg = (struct trx_meas_set) {</span><br><span style="color: hsl(120, 100%, 40%);">+                  .toa256 = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+                  .rssi = -110,</span><br><span style="color: hsl(120, 100%, 40%);">+         };</span><br><span>           n_errors = 116 * 2;</span><br><span style="color: hsl(120, 100%, 40%);">+   }</span><br><span> </span><br><span>        /* Calculate TDMA frame number of the first burst */</span><br><span>         lchan->rx_first_fn = sched_tchh_block_dl_first_fn(lchan->type,</span><br><span>diff --git a/src/host/trxcon/sched_lchan_xcch.c b/src/host/trxcon/sched_lchan_xcch.c</span><br><span>index 34fe5ce..aa8d4dd 100644</span><br><span>--- a/src/host/trxcon/sched_lchan_xcch.c</span><br><span>+++ b/src/host/trxcon/sched_lchan_xcch.c</span><br><span>@@ -2,7 +2,7 @@</span><br><span>  * OsmocomBB <-> SDR connection bridge</span><br><span>  * TDMA scheduler: handlers for DL / UL bursts on logical channels</span><br><span>  *</span><br><span style="color: hsl(0, 100%, 40%);">- * (C) 2017 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span style="color: hsl(120, 100%, 40%);">+ * (C) 2017-2020 by Vadim Yanitskiy <axilirator@gmail.com></span><br><span>  *</span><br><span>  * All Rights Reserved</span><br><span>  *</span><br><span>@@ -42,7 +42,7 @@</span><br><span> </span><br><span> int rx_data_fn(struct trx_instance *trx, struct trx_ts *ts,</span><br><span>    struct trx_lchan_state *lchan, uint32_t fn, uint8_t bid,</span><br><span style="color: hsl(0, 100%, 40%);">-        sbit_t *bits, int8_t rssi, int16_t toa256)</span><br><span style="color: hsl(120, 100%, 40%);">+    sbit_t *bits, const struct trx_meas_set *meas)</span><br><span> {</span><br><span>  const struct trx_lchan_desc *lchan_desc;</span><br><span>     uint8_t l2[GSM_MACBLOCK_LEN], *mask;</span><br><span>@@ -61,9 +61,6 @@</span><br><span> </span><br><span>         /* Reset internal state */</span><br><span>   if (bid == 0) {</span><br><span style="color: hsl(0, 100%, 40%);">-         /* Clean up old measurements */</span><br><span style="color: hsl(0, 100%, 40%);">-         memset(&lchan->meas, 0x00, sizeof(lchan->meas));</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span>           *first_fn = fn;</span><br><span>              *mask = 0x0;</span><br><span>         }</span><br><span>@@ -71,10 +68,8 @@</span><br><span>       /* Update mask */</span><br><span>    *mask |= (1 << bid);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  /* Update measurements */</span><br><span style="color: hsl(0, 100%, 40%);">-       lchan->meas.rssi_sum += rssi;</span><br><span style="color: hsl(0, 100%, 40%);">-        lchan->meas.toa256_sum += toa256;</span><br><span style="color: hsl(0, 100%, 40%);">-    lchan->meas.num++;</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Store the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+  sched_trx_meas_push(lchan, meas);</span><br><span> </span><br><span>        /* Copy burst to buffer of 4 bursts */</span><br><span>       offset = buffer + bid * 116;</span><br><span>@@ -85,6 +80,9 @@</span><br><span>     if (bid != 3)</span><br><span>                return 0;</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Calculate AVG of the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+       sched_trx_meas_avg(lchan, 4);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>      /* Check for complete set of bursts */</span><br><span>       if ((*mask & 0xf) != 0xf) {</span><br><span>              LOGP(DSCHD, LOGL_ERROR, "Received incomplete (%s) data frame at "</span><br><span>diff --git a/src/host/trxcon/sched_trx.c b/src/host/trxcon/sched_trx.c</span><br><span>index b7914b6..081e3ca 100644</span><br><span>--- a/src/host/trxcon/sched_trx.c</span><br><span>+++ b/src/host/trxcon/sched_trx.c</span><br><span>@@ -613,7 +613,7 @@</span><br><span> </span><br><span> int sched_trx_handle_rx_burst(struct trx_instance *trx, uint8_t tn,</span><br><span>        uint32_t burst_fn, sbit_t *bits, uint16_t nbits,</span><br><span style="color: hsl(0, 100%, 40%);">-        int8_t rssi, int16_t toa256)</span><br><span style="color: hsl(120, 100%, 40%);">+  const struct trx_meas_set *meas)</span><br><span> {</span><br><span>        struct trx_lchan_state *lchan;</span><br><span>       const struct trx_frame *frame;</span><br><span>@@ -674,7 +674,7 @@</span><br><span>                                 sched_trx_a5_burst_dec(lchan, fn, bits);</span><br><span> </span><br><span>                         /* Put burst to handler */</span><br><span style="color: hsl(0, 100%, 40%);">-                      handler(trx, ts, lchan, fn, bid, bits, rssi, toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+                 handler(trx, ts, lchan, fn, bid, bits, meas);</span><br><span>                }</span><br><span> </span><br><span> next_frame:</span><br><span>@@ -710,3 +710,50 @@</span><br><span> </span><br><span>      return 0;</span><br><span> }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+#define MEAS_HIST_FIRST(hist) \</span><br><span style="color: hsl(120, 100%, 40%);">+     (&hist->buf[0])</span><br><span style="color: hsl(120, 100%, 40%);">+#define MEAS_HIST_LAST(hist) \</span><br><span style="color: hsl(120, 100%, 40%);">+        (MEAS_HIST_FIRST(hist) + ARRAY_SIZE(hist->buf) - 1)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Add a new set of measurements to the history */</span><br><span style="color: hsl(120, 100%, 40%);">+void sched_trx_meas_push(struct trx_lchan_state *lchan, const struct trx_meas_set *meas)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     struct trx_lchan_meas_hist *hist = &lchan->meas_hist;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Find a new position where to store the measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+     if (hist->head == MEAS_HIST_LAST(hist) || hist->head == NULL)</span><br><span style="color: hsl(120, 100%, 40%);">+           hist->head = MEAS_HIST_FIRST(hist);</span><br><span style="color: hsl(120, 100%, 40%);">+        else</span><br><span style="color: hsl(120, 100%, 40%);">+          hist->head++;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    *hist->head = *meas;</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 the AVG of n measurements from the history */</span><br><span style="color: hsl(120, 100%, 40%);">+void sched_trx_meas_avg(struct trx_lchan_state *lchan, unsigned int n)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct trx_lchan_meas_hist *hist = &lchan->meas_hist;</span><br><span style="color: hsl(120, 100%, 40%);">+  struct trx_meas_set *meas = hist->head;</span><br><span style="color: hsl(120, 100%, 40%);">+    int toa256_sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   int rssi_sum = 0;</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%);">+      OSMO_ASSERT(n > 0 && n <= ARRAY_SIZE(hist->buf));</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(meas != NULL);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* Traverse backwards up to n entries, calculate the sum */</span><br><span style="color: hsl(120, 100%, 40%);">+   for (i = 0; i < n; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+          toa256_sum += meas->toa256;</span><br><span style="color: hsl(120, 100%, 40%);">+                rssi_sum += meas->rssi;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          if (meas == MEAS_HIST_FIRST(hist))</span><br><span style="color: hsl(120, 100%, 40%);">+                    meas = MEAS_HIST_LAST(hist);</span><br><span style="color: hsl(120, 100%, 40%);">+          else</span><br><span style="color: hsl(120, 100%, 40%);">+                  meas--;</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 the AVG */</span><br><span style="color: hsl(120, 100%, 40%);">+       lchan->meas_avg.toa256 = toa256_sum / n;</span><br><span style="color: hsl(120, 100%, 40%);">+   lchan->meas_avg.rssi = rssi_sum / n;</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span>diff --git a/src/host/trxcon/sched_trx.h b/src/host/trxcon/sched_trx.h</span><br><span>index 13fc678..a4fc90f 100644</span><br><span>--- a/src/host/trxcon/sched_trx.h</span><br><span>+++ b/src/host/trxcon/sched_trx.h</span><br><span>@@ -40,6 +40,7 @@</span><br><span> </span><br><span> /* Forward declaration to avoid mutual include */</span><br><span> struct trx_lchan_state;</span><br><span style="color: hsl(120, 100%, 40%);">+struct trx_meas_set;</span><br><span> struct trx_instance;</span><br><span> struct trx_ts;</span><br><span> </span><br><span>@@ -99,7 +100,7 @@</span><br><span> typedef int trx_lchan_rx_func(struct trx_instance *trx,</span><br><span>      struct trx_ts *ts, struct trx_lchan_state *lchan,</span><br><span>    uint32_t fn, uint8_t bid, sbit_t *bits,</span><br><span style="color: hsl(0, 100%, 40%);">- int8_t rssi, int16_t toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct trx_meas_set *meas);</span><br><span> </span><br><span> typedef int trx_lchan_tx_func(struct trx_instance *trx,</span><br><span>     struct trx_ts *ts, struct trx_lchan_state *lchan,</span><br><span>@@ -157,6 +158,19 @@</span><br><span>     const struct trx_frame *frames;</span><br><span> };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+struct trx_meas_set {</span><br><span style="color: hsl(120, 100%, 40%);">+      /*! \brief ToA256 (Timing of Arrival, 1/256 of a symbol) */</span><br><span style="color: hsl(120, 100%, 40%);">+   int16_t toa256;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! \brief RSSI (Received Signal Strength Indication) */</span><br><span style="color: hsl(120, 100%, 40%);">+      int8_t rssi;</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%);">+/* Simple ring buffer (up to 8 unique measurements) */</span><br><span style="color: hsl(120, 100%, 40%);">+struct trx_lchan_meas_hist {</span><br><span style="color: hsl(120, 100%, 40%);">+      struct trx_meas_set buf[8];</span><br><span style="color: hsl(120, 100%, 40%);">+   struct trx_meas_set *head;</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* States each channel on a multiframe */</span><br><span> struct trx_lchan_state {</span><br><span>    /*! \brief Channel type */</span><br><span>@@ -190,14 +204,10 @@</span><br><span>   /*! \brief pending FACCH/H blocks on Uplink */</span><br><span>       uint8_t ul_facch_blocks;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-    struct {</span><br><span style="color: hsl(0, 100%, 40%);">-                /*! \brief Number of measurements */</span><br><span style="color: hsl(0, 100%, 40%);">-            unsigned int num;</span><br><span style="color: hsl(0, 100%, 40%);">-               /*! \brief Sum of RSSI values */</span><br><span style="color: hsl(0, 100%, 40%);">-                float rssi_sum;</span><br><span style="color: hsl(0, 100%, 40%);">-         /*! \brief Sum of TOA values */</span><br><span style="color: hsl(0, 100%, 40%);">-         int32_t toa256_sum;</span><br><span style="color: hsl(0, 100%, 40%);">-     } meas;</span><br><span style="color: hsl(120, 100%, 40%);">+       /*! \brief Downlink measurements history */</span><br><span style="color: hsl(120, 100%, 40%);">+   struct trx_lchan_meas_hist meas_hist;</span><br><span style="color: hsl(120, 100%, 40%);">+ /*! \brief AVG measurements of the last received block */</span><br><span style="color: hsl(120, 100%, 40%);">+     struct trx_meas_set meas_avg;</span><br><span> </span><br><span>    /*! \brief SACCH state */</span><br><span>    struct {</span><br><span>@@ -347,7 +357,7 @@</span><br><span> </span><br><span> int sched_trx_handle_rx_burst(struct trx_instance *trx, uint8_t tn,</span><br><span>    uint32_t burst_fn, sbit_t *bits, uint16_t nbits,</span><br><span style="color: hsl(0, 100%, 40%);">-        int8_t rssi, int16_t toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+ const struct trx_meas_set *meas);</span><br><span> int sched_trx_handle_tx_burst(struct trx_instance *trx,</span><br><span>         struct trx_ts *ts, struct trx_lchan_state *lchan,</span><br><span>    uint32_t fn, ubit_t *bits);</span><br><span>@@ -381,3 +391,7 @@</span><br><span>    sched_tchh_block_map_fn(chan, fn, ul, 1, 1)</span><br><span> #define sched_tchh_facch_end(chan, fn, ul) \</span><br><span>  sched_tchh_block_map_fn(chan, fn, ul, 1, 0)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Measurement history */</span><br><span style="color: hsl(120, 100%, 40%);">+void sched_trx_meas_push(struct trx_lchan_state *lchan, const struct trx_meas_set *meas);</span><br><span style="color: hsl(120, 100%, 40%);">+void sched_trx_meas_avg(struct trx_lchan_state *lchan, unsigned int n);</span><br><span>diff --git a/src/host/trxcon/trx_if.c b/src/host/trxcon/trx_if.c</span><br><span>index 55d7034..343c6ca 100644</span><br><span>--- a/src/host/trxcon/trx_if.c</span><br><span>+++ b/src/host/trxcon/trx_if.c</span><br><span>@@ -555,6 +555,7 @@</span><br><span> static int trx_data_rx_cb(struct osmo_fd *ofd, unsigned int what)</span><br><span> {</span><br><span>    struct trx_instance *trx = ofd->data;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct trx_meas_set meas;</span><br><span>    uint8_t buf[256];</span><br><span>    sbit_t bits[148];</span><br><span>    int8_t rssi, tn;</span><br><span>@@ -595,8 +596,14 @@</span><br><span>      LOGP(DTRXD, LOGL_DEBUG, "RX burst tn=%u fn=%u rssi=%d toa=%d\n",</span><br><span>           tn, fn, rssi, toa256);</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    /* Group the measurements together */</span><br><span style="color: hsl(120, 100%, 40%);">+ meas = (struct trx_meas_set) {</span><br><span style="color: hsl(120, 100%, 40%);">+                .toa256 = toa256,</span><br><span style="color: hsl(120, 100%, 40%);">+             .rssi = rssi,</span><br><span style="color: hsl(120, 100%, 40%);">+ };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>         /* Poke scheduler */</span><br><span style="color: hsl(0, 100%, 40%);">-    sched_trx_handle_rx_burst(trx, tn, fn, bits, 148, rssi, toa256);</span><br><span style="color: hsl(120, 100%, 40%);">+      sched_trx_handle_rx_burst(trx, tn, fn, bits, 148, &meas);</span><br><span> </span><br><span>    /* Correct local clock counter */</span><br><span>    if (fn % 51 == 0)</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmocom-bb/+/17350">change 17350</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/osmocom-bb/+/17350"/><meta itemprop="name" content="View Change"/></div></div>

<div style="display:none"> Gerrit-Project: osmocom-bb </div>
<div style="display:none"> Gerrit-Branch: master </div>
<div style="display:none"> Gerrit-Change-Id: I211ee3314f0a284112a4deddc0e93028f4a27cef </div>
<div style="display:none"> Gerrit-Change-Number: 17350 </div>
<div style="display:none"> Gerrit-PatchSet: 4 </div>
<div style="display:none"> Gerrit-Owner: fixeria <axilirator@gmail.com> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>