<p>Harald Welte <strong>merged</strong> this change.</p><p><a href="https://gerrit.osmocom.org/10476">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  Harald Welte: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">measurement: substitue missing measurements<br><br>At the moment the measurement calculation of osmo-bts works by<br>collecting the measurement reports the phy emits during a measurement<br>interval. Normally one would expect a well defind fixed number here, but<br>some phys will not emit a measurement report for lost blocks. Also<br>blocks and their reports may get lost because of cpu overload etc.<br><br>The computation that is executed at the end of the measurement interval<br>computes over all received measurement. This evenutally means that<br>missing measurements will not taken into account and the result will<br>look better than it is in reality.<br><br>To fix this, the interval must be of a defined size and in cases where<br>less measurements as expected were collected, the algorithm must assume<br>they have been received with a 100%BER and take that into account.<br>However, all RSSI and TA/TOA related computations should continue to<br>rely on actual measurement data.<br><br>- make sure the algorithm works over a fixed interval<br>- replace missing measurements with 100%BER<br>- fix and extend unit-tests<br><br>Change-Id: Idd30fc07603ad7d042c1fb416e247c3bf7d35c8b<br>Related: OS#2987<br>---<br>M src/common/measurement.c<br>M tests/meas/meas_test.c<br>M tests/meas/meas_test.ok<br>M tests/meas/meas_testcases.h<br>4 files changed, 859 insertions(+), 96 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/src/common/measurement.c b/src/common/measurement.c</span><br><span>index d7580e6..59f5d83 100644</span><br><span>--- a/src/common/measurement.c</span><br><span>+++ b/src/common/measurement.c</span><br><span>@@ -16,6 +16,21 @@</span><br><span> static const uint8_t ts45008_83_tch_hs0[] = { 0, 2, 4, 6, 52, 54, 56, 58 };</span><br><span> static const uint8_t ts45008_83_tch_hs1[] = { 14, 16, 18, 20, 66, 68, 70, 72 };</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* In cases where we less measurements than we expect we must assume that we</span><br><span style="color: hsl(120, 100%, 40%);">+ * just did not receive the block because it was lost due to bad channel</span><br><span style="color: hsl(120, 100%, 40%);">+ * conditions. We set up a dummy measurement result here that reflects the</span><br><span style="color: hsl(120, 100%, 40%);">+ * worst possible result. In our* calculation we will use this dummy to replace</span><br><span style="color: hsl(120, 100%, 40%);">+ * the missing measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MEASUREMENT_DUMMY_BER 10000 /* 100% BER */</span><br><span style="color: hsl(120, 100%, 40%);">+#define MEASUREMENT_DUMMY_IRSSI 109 /* noise floor in -dBm */</span><br><span style="color: hsl(120, 100%, 40%);">+static const struct bts_ul_meas measurement_dummy = (struct bts_ul_meas) {</span><br><span style="color: hsl(120, 100%, 40%);">+    .ber10k = MEASUREMENT_DUMMY_BER,</span><br><span style="color: hsl(120, 100%, 40%);">+      .ta_offs_256bits = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+ .c_i = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+     .is_sub = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  .inv_rssi = MEASUREMENT_DUMMY_IRSSI</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> /* find out if an array contains a given key as element */</span><br><span> #define ARRAY_CONTAINS(arr, val) array_contains(arr, ARRAY_SIZE(arr), val)</span><br><span> static bool array_contains(const uint8_t *arr, unsigned int len, uint8_t val) {</span><br><span>@@ -468,6 +483,64 @@</span><br><span>      return 7;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+/* Get the number of measurements that we expect for a specific lchan.</span><br><span style="color: hsl(120, 100%, 40%);">+ * (This is a static number that is defined by the specific slot layout of</span><br><span style="color: hsl(120, 100%, 40%);">+ * the channel) */</span><br><span style="color: hsl(120, 100%, 40%);">+static unsigned int lchan_meas_num_expected(const struct gsm_lchan *lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     enum gsm_phys_chan_config pchan = ts_pchan(lchan->ts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (pchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM_PCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* 24 for TCH + 1 for SACCH */</span><br><span style="color: hsl(120, 100%, 40%);">+                return 25;</span><br><span style="color: hsl(120, 100%, 40%);">+    case GSM_PCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* 24 half-blocks for TCH + 1 for SACCH */</span><br><span style="color: hsl(120, 100%, 40%);">+            return 25;</span><br><span style="color: hsl(120, 100%, 40%);">+    case GSM_PCHAN_SDCCH8_SACCH8C:</span><br><span style="color: hsl(120, 100%, 40%);">+        case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:</span><br><span style="color: hsl(120, 100%, 40%);">+           /* 2 for SDCCH + 1 for SACCH */</span><br><span style="color: hsl(120, 100%, 40%);">+               return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM_PCHAN_CCCH_SDCCH4:</span><br><span style="color: hsl(120, 100%, 40%);">+   case GSM_PCHAN_CCCH_SDCCH4_CBCH:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* 2 for SDCCH + 1 for SACCH */</span><br><span style="color: hsl(120, 100%, 40%);">+               return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     default:</span><br><span style="color: hsl(120, 100%, 40%);">+              return lchan->meas.num_ul_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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* In DTX a subset of blocks must always be transmitted</span><br><span style="color: hsl(120, 100%, 40%);">+ * See also: GSM 05.08, chapter 8.3 Aspects of discontinuous transmission (DTX) */</span><br><span style="color: hsl(120, 100%, 40%);">+static unsigned int lchan_meas_sub_num_expected(const struct gsm_lchan *lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+        enum gsm_phys_chan_config pchan = ts_pchan(lchan->ts);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* AMR is using a more elaborated model with a dymanic amount of</span><br><span style="color: hsl(120, 100%, 40%);">+       * DTX blocks so this function is not applicable to determine the</span><br><span style="color: hsl(120, 100%, 40%);">+      * amount of expected SUB Measurements when AMR is used */</span><br><span style="color: hsl(120, 100%, 40%);">+    OSMO_ASSERT(lchan->tch_mode != GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   switch (pchan) {</span><br><span style="color: hsl(120, 100%, 40%);">+      case GSM_PCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* 1 block SDCCH, 2 blocks TCH */</span><br><span style="color: hsl(120, 100%, 40%);">+             return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM_PCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* 1 block SDCCH, 4 half-blocks TCH */</span><br><span style="color: hsl(120, 100%, 40%);">+                return 5;</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM_PCHAN_SDCCH8_SACCH8C:</span><br><span style="color: hsl(120, 100%, 40%);">+        case GSM_PCHAN_SDCCH8_SACCH8C_CBCH:</span><br><span style="color: hsl(120, 100%, 40%);">+           /* no DTX here, all blocks must be present! */</span><br><span style="color: hsl(120, 100%, 40%);">+                return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM_PCHAN_CCCH_SDCCH4:</span><br><span style="color: hsl(120, 100%, 40%);">+   case GSM_PCHAN_CCCH_SDCCH4_CBCH:</span><br><span style="color: hsl(120, 100%, 40%);">+              /* no DTX here, all blocks must be present! */</span><br><span style="color: hsl(120, 100%, 40%);">+                return 3;</span><br><span style="color: hsl(120, 100%, 40%);">+     default:</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%);">+</span><br><span> /* if we clip the TOA value to 12 bits, i.e. toa256=3200,</span><br><span>  *  -> the maximum deviation can be 2*3200 = 6400</span><br><span>  *  -> the maximum squared deviation can be 6400^2 = 40960000</span><br><span>@@ -482,6 +555,10 @@</span><br><span> /* compute Osmocom extended measurements for the given lchan */</span><br><span> static void lchan_meas_compute_extended(struct gsm_lchan *lchan)</span><br><span> {</span><br><span style="color: hsl(120, 100%, 40%);">+    unsigned int num_ul_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int num_ul_meas_excess = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int num_ul_meas_expect;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>     /* we assume that lchan_meas_check_compute() has already computed the mean value</span><br><span>      * and we can compute the min/max/variance/stddev from this */</span><br><span>       int i;</span><br><span>@@ -489,19 +566,47 @@</span><br><span>       /* each measurement is an int32_t, so the squared difference value must fit in 32bits */</span><br><span>     /* the sum of the squared values (each up to 32bit) can very easily exceed 32 bits */</span><br><span>        u_int64_t sq_diff_sum = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* In case we do not have any measurement values collected there is no</span><br><span style="color: hsl(120, 100%, 40%);">+         * computation possible. We just skip the whole computation here, the</span><br><span style="color: hsl(120, 100%, 40%);">+  * lchan->meas.flags will not get the LC_UL_M_F_OSMO_EXT_VALID flag set</span><br><span style="color: hsl(120, 100%, 40%);">+     * so no extended measurement results will be reported back via RSL.</span><br><span style="color: hsl(120, 100%, 40%);">+   * this is ok, since we have nothing to report anyway and apart of that</span><br><span style="color: hsl(120, 100%, 40%);">+        * we also just lost the signal (otherwise we would have at least some</span><br><span style="color: hsl(120, 100%, 40%);">+         * measurements). */</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!lchan->meas.num_ul_meas)</span><br><span style="color: hsl(120, 100%, 40%);">+              return;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>    /* initialize min/max values with their counterpart */</span><br><span>       lchan->meas.ext.toa256_min = INT16_MAX;</span><br><span>   lchan->meas.ext.toa256_max = INT16_MIN;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  OSMO_ASSERT(lchan->meas.num_ul_meas);</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Determine the number of measurement values we need to take into the</span><br><span style="color: hsl(120, 100%, 40%);">+         * computation. In this case we only compute over the measurements we</span><br><span style="color: hsl(120, 100%, 40%);">+  * have indeed received. Since this computation is about timing</span><br><span style="color: hsl(120, 100%, 40%);">+        * information it does not make sense to approach missing measurement</span><br><span style="color: hsl(120, 100%, 40%);">+  * samples the TOA with 0. This would bend the average towards 0. What</span><br><span style="color: hsl(120, 100%, 40%);">+         * counts is the average TOA of the properly received blocks so that</span><br><span style="color: hsl(120, 100%, 40%);">+   * the TA logic can make a proper decision. */</span><br><span style="color: hsl(120, 100%, 40%);">+        num_ul_meas_expect = lchan_meas_num_expected(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+  if (lchan->meas.num_ul_meas > num_ul_meas_expect) {</span><br><span style="color: hsl(120, 100%, 40%);">+             num_ul_meas = num_ul_meas_expect;</span><br><span style="color: hsl(120, 100%, 40%);">+             num_ul_meas_excess = lchan->meas.num_ul_meas - num_ul_meas_expect;</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+     else</span><br><span style="color: hsl(120, 100%, 40%);">+          num_ul_meas = lchan->meas.num_ul_meas;</span><br><span> </span><br><span>        /* all computations are done on the relative arrival time of the burst, relative to the</span><br><span>       * beginning of its slot. This is of course excluding the TA value that the MS has already</span><br><span>    * compensated/pre-empted its transmission */</span><br><span> </span><br><span>    /* step 1: compute the sum of the squared difference of each value to mean */</span><br><span style="color: hsl(0, 100%, 40%);">-   for (i = 0; i < lchan->meas.num_ul_meas; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-           struct bts_ul_meas *m = &lchan->meas.uplink[i];</span><br><span style="color: hsl(120, 100%, 40%);">+        for (i = 0; i < num_ul_meas; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                const struct bts_ul_meas *m;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                OSMO_ASSERT(i < lchan->meas.num_ul_meas);</span><br><span style="color: hsl(120, 100%, 40%);">+               m = &lchan->meas.uplink[i+num_ul_meas_excess];</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>              int32_t diff = (int32_t)m->ta_offs_256bits - (int32_t)lchan->meas.ms_toa256;</span><br><span>           /* diff can now be any value of +65535 to -65535, so we can safely square it,</span><br><span>                 * but only in unsigned math.  As squaring looses the sign, we can simply drop</span><br><span>@@ -517,7 +622,7 @@</span><br><span>                         lchan->meas.ext.toa256_min = m->ta_offs_256bits;</span><br><span>       }</span><br><span>    /* step 2: compute the variance (mean of sum of squared differences) */</span><br><span style="color: hsl(0, 100%, 40%);">- sq_diff_sum = sq_diff_sum / lchan->meas.num_ul_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+       sq_diff_sum = sq_diff_sum / num_ul_meas;</span><br><span>     /* as the individual summed values can each not exceed 2^32, and we're</span><br><span>    * dividing by the number of summands, the resulting value can also not exceed 2^32 */</span><br><span>       OSMO_ASSERT(sq_diff_sum <= UINT32_MAX);</span><br><span>@@ -535,54 +640,137 @@</span><br><span>  uint32_t irssi_sub_sum = 0;</span><br><span>  int32_t ta256b_sum = 0;</span><br><span>      unsigned int num_meas_sub = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+        unsigned int num_meas_sub_actual = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+ unsigned int num_meas_sub_subst = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int num_meas_sub_expect;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int num_ul_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+     unsigned int num_ul_meas_actual = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+  unsigned int num_ul_meas_subst = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+   unsigned int num_ul_meas_expect;</span><br><span style="color: hsl(120, 100%, 40%);">+      unsigned int num_ul_meas_excess = 0;</span><br><span>         int i;</span><br><span> </span><br><span>   /* if measurement period is not complete, abort */</span><br><span>   if (!is_meas_complete(lchan, fn))</span><br><span>            return 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* if there are no measurements, skip computation */</span><br><span style="color: hsl(0, 100%, 40%);">-    if (lchan->meas.num_ul_meas == 0)</span><br><span style="color: hsl(0, 100%, 40%);">-            return 0;</span><br><span style="color: hsl(120, 100%, 40%);">+     LOGP(DMEAS, LOGL_DEBUG, "%s Calculating measurement results for physical channel:%s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+          gsm_lchan_name(lchan), gsm_pchan_name(ts_pchan(lchan->ts)));</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* compute the actual measurements */</span><br><span style="color: hsl(120, 100%, 40%);">+ /* Note: Some phys will send no measurement indication at all</span><br><span style="color: hsl(120, 100%, 40%);">+  * when a block is lost. Also in DTX mode blocks are left out</span><br><span style="color: hsl(120, 100%, 40%);">+  * intentionally to save energy. It is not necessarly an error</span><br><span style="color: hsl(120, 100%, 40%);">+         * when we get less measurements as we expect. */</span><br><span style="color: hsl(120, 100%, 40%);">+     num_ul_meas_expect = lchan_meas_num_expected(lchan);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        /* step 1: add up */</span><br><span style="color: hsl(0, 100%, 40%);">-    for (i = 0; i < lchan->meas.num_ul_meas; i++) {</span><br><span style="color: hsl(0, 100%, 40%);">-           struct bts_ul_meas *m = &lchan->meas.uplink[i];</span><br><span style="color: hsl(120, 100%, 40%);">+        if (lchan->tch_mode != GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(120, 100%, 40%);">+             num_meas_sub_expect = lchan_meas_sub_num_expected(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+     else {</span><br><span style="color: hsl(120, 100%, 40%);">+                /* FIXME: the amount of SUB Measurements is a dynamic parameter</span><br><span style="color: hsl(120, 100%, 40%);">+                * in AMR and can not be determined by using a lookup table.</span><br><span style="color: hsl(120, 100%, 40%);">+           * See also: OS#2978 */</span><br><span style="color: hsl(120, 100%, 40%);">+               num_meas_sub_expect = 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%);">+   if (lchan->meas.num_ul_meas > num_ul_meas_expect)</span><br><span style="color: hsl(120, 100%, 40%);">+               num_ul_meas_excess = lchan->meas.num_ul_meas - num_ul_meas_expect;</span><br><span style="color: hsl(120, 100%, 40%);">+ num_ul_meas = num_ul_meas_expect;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   LOGP(DMEAS, LOGL_DEBUG, "%s received %u UL measurements, expected %u\n", gsm_lchan_name(lchan),</span><br><span style="color: hsl(120, 100%, 40%);">+          lchan->meas.num_ul_meas, num_ul_meas_expect);</span><br><span style="color: hsl(120, 100%, 40%);">+ if (num_ul_meas_excess)</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGP(DMEAS, LOGL_DEBUG, "%s received %u excess UL measurements\n", gsm_lchan_name(lchan),</span><br><span style="color: hsl(120, 100%, 40%);">+                num_ul_meas_excess);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   /* Measurement computation step 1: add up */</span><br><span style="color: hsl(120, 100%, 40%);">+  for (i = 0; i < num_ul_meas; i++) {</span><br><span style="color: hsl(120, 100%, 40%);">+                const struct bts_ul_meas *m;</span><br><span style="color: hsl(120, 100%, 40%);">+          bool is_sub = false;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                /* Note: We will always compute over a full measurement,</span><br><span style="color: hsl(120, 100%, 40%);">+               * interval even when not enough measurement samples are in</span><br><span style="color: hsl(120, 100%, 40%);">+            * the buffer. As soon as we run out of measurement values</span><br><span style="color: hsl(120, 100%, 40%);">+             * we continue the calculation using dummy values. This works</span><br><span style="color: hsl(120, 100%, 40%);">+          * well for the BER, since there we can safely assume 100%</span><br><span style="color: hsl(120, 100%, 40%);">+             * since a missing measurement means that the data (block)</span><br><span style="color: hsl(120, 100%, 40%);">+             * is lost as well (some phys do not give us measurement</span><br><span style="color: hsl(120, 100%, 40%);">+               * reports for lost blocks or blocks that are spaced out for</span><br><span style="color: hsl(120, 100%, 40%);">+           * DTX). However, for RSSI and TA this does not work since</span><br><span style="color: hsl(120, 100%, 40%);">+             * there we would distort the calculation if we would replace</span><br><span style="color: hsl(120, 100%, 40%);">+          * them with a made up number. This means for those values we</span><br><span style="color: hsl(120, 100%, 40%);">+          * only compute over the data we have actually received. */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         if (i < lchan->meas.num_ul_meas) {</span><br><span style="color: hsl(120, 100%, 40%);">+                      m = &lchan->meas.uplink[i + num_ul_meas_excess];</span><br><span style="color: hsl(120, 100%, 40%);">+                       if (m->is_sub) {</span><br><span style="color: hsl(120, 100%, 40%);">+                           irssi_sub_sum += m->inv_rssi;</span><br><span style="color: hsl(120, 100%, 40%);">+                              num_meas_sub_actual++;</span><br><span style="color: hsl(120, 100%, 40%);">+                                is_sub = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+                     irssi_full_sum += m->inv_rssi;</span><br><span style="color: hsl(120, 100%, 40%);">+                     ta256b_sum += m->ta_offs_256bits;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                        num_ul_meas_actual++;</span><br><span style="color: hsl(120, 100%, 40%);">+         } else {</span><br><span style="color: hsl(120, 100%, 40%);">+                      m = &measurement_dummy;</span><br><span style="color: hsl(120, 100%, 40%);">+                   if (num_ul_meas_expect - i <= num_meas_sub_expect - num_meas_sub) {</span><br><span style="color: hsl(120, 100%, 40%);">+                                num_meas_sub_subst++;</span><br><span style="color: hsl(120, 100%, 40%);">+                         is_sub = true;</span><br><span style="color: hsl(120, 100%, 40%);">+                        }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                   num_ul_meas_subst++;</span><br><span style="color: hsl(120, 100%, 40%);">+          }</span><br><span> </span><br><span>                ber_full_sum += m->ber10k;</span><br><span style="color: hsl(0, 100%, 40%);">-           irssi_full_sum += m->inv_rssi;</span><br><span style="color: hsl(0, 100%, 40%);">-               ta256b_sum += m->ta_offs_256bits;</span><br><span style="color: hsl(0, 100%, 40%);">-</span><br><span style="color: hsl(0, 100%, 40%);">-            if (m->is_sub) {</span><br><span style="color: hsl(120, 100%, 40%);">+           if (is_sub) {</span><br><span>                        num_meas_sub++;</span><br><span>                      ber_sub_sum += m->ber10k;</span><br><span style="color: hsl(0, 100%, 40%);">-                    irssi_sub_sum += m->inv_rssi;</span><br><span>             }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* step 2: divide */</span><br><span style="color: hsl(0, 100%, 40%);">-    ber_full_sum = ber_full_sum / lchan->meas.num_ul_meas;</span><br><span style="color: hsl(0, 100%, 40%);">-       irssi_full_sum = irssi_full_sum / lchan->meas.num_ul_meas;</span><br><span style="color: hsl(0, 100%, 40%);">-   ta256b_sum = ta256b_sum / lchan->meas.num_ul_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ LOGP(DMEAS, LOGL_DEBUG, "%s received UL measurements contain %u SUB measurements, expected %u\n",</span><br><span style="color: hsl(120, 100%, 40%);">+        gsm_lchan_name(lchan), num_meas_sub_actual, num_meas_sub_expect);</span><br><span style="color: hsl(120, 100%, 40%);">+        LOGP(DMEAS, LOGL_DEBUG, "%s replaced %u measurements with dummy values, from which %u were SUB measurements\n",</span><br><span style="color: hsl(120, 100%, 40%);">+          gsm_lchan_name(lchan), num_ul_meas_subst, num_meas_sub_subst);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">- if (num_meas_sub) {</span><br><span style="color: hsl(0, 100%, 40%);">-             ber_sub_sum = ber_sub_sum / num_meas_sub;</span><br><span style="color: hsl(0, 100%, 40%);">-               irssi_sub_sum = irssi_sub_sum / num_meas_sub;</span><br><span style="color: hsl(0, 100%, 40%);">-   } else {</span><br><span style="color: hsl(0, 100%, 40%);">-                LOGP(DMEAS, LOGL_ERROR, "%s No measurements for SUB!!!\n", gsm_lchan_name(lchan));</span><br><span style="color: hsl(0, 100%, 40%);">-            /* The only situation in which this can occur is if the related uplink burst/block was</span><br><span style="color: hsl(0, 100%, 40%);">-           * missing, so let's set BER to 100% and level to lowest possible. */</span><br><span style="color: hsl(0, 100%, 40%);">-               ber_sub_sum = 10000; /* 100% */</span><br><span style="color: hsl(0, 100%, 40%);">-         irssi_sub_sum = 120; /* -120 dBm */</span><br><span style="color: hsl(120, 100%, 40%);">+   if (num_meas_sub != num_meas_sub_expect) {</span><br><span style="color: hsl(120, 100%, 40%);">+            LOGP(DMEAS, LOGL_ERROR, "%s Incorrect number of SUB measurements detected!\n", gsm_lchan_name(lchan));</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Normally the logic above should make sure that there is</span><br><span style="color: hsl(120, 100%, 40%);">+             * always the exact amount of SUB measurements taken into</span><br><span style="color: hsl(120, 100%, 40%);">+              * account. If not then the logic that decides tags the received</span><br><span style="color: hsl(120, 100%, 40%);">+               * measurements as is_sub works incorrectly. Since the logic</span><br><span style="color: hsl(120, 100%, 40%);">+           * above only adds missing measurements during the calculation</span><br><span style="color: hsl(120, 100%, 40%);">+                 * it can not remove excess SUB measurements or add missing SUB</span><br><span style="color: hsl(120, 100%, 40%);">+                * measurements when there is no more room in the interval. */</span><br><span>       }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Measurement computation step 2: divide */</span><br><span style="color: hsl(120, 100%, 40%);">+  ber_full_sum = ber_full_sum / num_ul_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  if (!irssi_full_sum)</span><br><span style="color: hsl(120, 100%, 40%);">+          ber_full_sum = MEASUREMENT_DUMMY_IRSSI;</span><br><span style="color: hsl(120, 100%, 40%);">+       else</span><br><span style="color: hsl(120, 100%, 40%);">+          irssi_full_sum = irssi_full_sum / num_ul_meas_actual;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!num_ul_meas_actual)</span><br><span style="color: hsl(120, 100%, 40%);">+              ta256b_sum = lchan->meas.ms_toa256;</span><br><span style="color: hsl(120, 100%, 40%);">+        else</span><br><span style="color: hsl(120, 100%, 40%);">+          ta256b_sum = ta256b_sum / num_ul_meas_actual;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       if (!num_meas_sub)</span><br><span style="color: hsl(120, 100%, 40%);">+            ber_sub_sum = MEASUREMENT_DUMMY_BER;</span><br><span style="color: hsl(120, 100%, 40%);">+  else</span><br><span style="color: hsl(120, 100%, 40%);">+          ber_sub_sum = ber_sub_sum / num_meas_sub;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+   if (!num_meas_sub_actual)</span><br><span style="color: hsl(120, 100%, 40%);">+             irssi_sub_sum = MEASUREMENT_DUMMY_IRSSI;</span><br><span style="color: hsl(120, 100%, 40%);">+      else</span><br><span style="color: hsl(120, 100%, 40%);">+          irssi_sub_sum = irssi_sub_sum / num_meas_sub_actual;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>       LOGP(DMEAS, LOGL_INFO, "%s Computed TA256(% 4d) BER-FULL(%2u.%02u%%), RSSI-FULL(-%3udBm), "</span><br><span style="color: hsl(0, 100%, 40%);">-           "BER-SUB(%2u.%02u%%), RSSI-SUB(-%3udBm)\n", gsm_lchan_name(lchan),</span><br><span style="color: hsl(0, 100%, 40%);">-            ta256b_sum, ber_full_sum/100,</span><br><span style="color: hsl(0, 100%, 40%);">-           ber_full_sum%100, irssi_full_sum, ber_sub_sum/100, ber_sub_sum%100,</span><br><span style="color: hsl(0, 100%, 40%);">-             irssi_sub_sum);</span><br><span style="color: hsl(120, 100%, 40%);">+            "BER-SUB(%2u.%02u%%), RSSI-SUB(-%3udBm)\n", gsm_lchan_name(lchan),</span><br><span style="color: hsl(120, 100%, 40%);">+          ta256b_sum, ber_full_sum / 100,</span><br><span style="color: hsl(120, 100%, 40%);">+       ber_full_sum % 100, irssi_full_sum, ber_sub_sum / 100, ber_sub_sum % 100, irssi_sub_sum);</span><br><span> </span><br><span>   /* store results */</span><br><span>  mru = &lchan->meas.ul_res;</span><br><span>@@ -593,20 +781,18 @@</span><br><span>    lchan->meas.ms_toa256 = ta256b_sum;</span><br><span> </span><br><span>   LOGP(DMEAS, LOGL_INFO, "%s UL MEAS RXLEV_FULL(%u), RXLEV_SUB(%u),"</span><br><span style="color: hsl(0, 100%, 40%);">-           "RXQUAL_FULL(%u), RXQUAL_SUB(%u), num_meas_sub(%u), num_ul_meas(%u) \n",</span><br><span style="color: hsl(0, 100%, 40%);">-              gsm_lchan_name(lchan),</span><br><span style="color: hsl(0, 100%, 40%);">-          mru->full.rx_lev,</span><br><span style="color: hsl(0, 100%, 40%);">-            mru->sub.rx_lev,</span><br><span style="color: hsl(0, 100%, 40%);">-             mru->full.rx_qual,</span><br><span style="color: hsl(0, 100%, 40%);">-           mru->sub.rx_qual, num_meas_sub, lchan->meas.num_ul_meas);</span><br><span style="color: hsl(120, 100%, 40%);">+             "RXQUAL_FULL(%u), RXQUAL_SUB(%u), num_meas_sub(%u), num_ul_meas(%u) \n",</span><br><span style="color: hsl(120, 100%, 40%);">+            gsm_lchan_name(lchan),</span><br><span style="color: hsl(120, 100%, 40%);">+        mru->full.rx_lev, mru->sub.rx_lev, mru->full.rx_qual, mru->sub.rx_qual, num_meas_sub, num_ul_meas_expect);</span><br><span> </span><br><span>      lchan->meas.flags |= LC_UL_M_F_RES_VALID;</span><br><span> </span><br><span>     lchan_meas_compute_extended(lchan);</span><br><span> </span><br><span>      lchan->meas.num_ul_meas = 0;</span><br><span style="color: hsl(0, 100%, 40%);">- /* send a signal indicating computation is complete */</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+    /* return 1 to indicte that the computation has been done and the next</span><br><span style="color: hsl(120, 100%, 40%);">+         * interval begins. */</span><br><span>       return 1;</span><br><span> }</span><br><span> </span><br><span>diff --git a/tests/meas/meas_test.c b/tests/meas/meas_test.c</span><br><span>index b90227a..c397ddd 100644</span><br><span>--- a/tests/meas/meas_test.c</span><br><span>+++ b/tests/meas/meas_test.c</span><br><span>@@ -24,6 +24,7 @@</span><br><span> #include "sysmobts_fr_samples.h"</span><br><span> #include "meas_testcases.h"</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> void test_fn_sample(struct fn_sample *s, unsigned int len, uint8_t pchan, uint8_t tsmap)</span><br><span> {</span><br><span>    int rc;</span><br><span>@@ -73,13 +74,16 @@</span><br><span> </span><br><span> static void test_meas_compute(const struct meas_testcase *mtc)</span><br><span> {</span><br><span style="color: hsl(0, 100%, 40%);">-        struct gsm_lchan *lchan = &trx->ts[1].lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        struct gsm_lchan *lchan;</span><br><span>     unsigned int i;</span><br><span>      unsigned int fn = 0;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-        printf("\nMeasurement Compute Test %s\n", mtc->name);</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("\n\n");</span><br><span style="color: hsl(120, 100%, 40%);">+     printf("===========================================================\n");</span><br><span style="color: hsl(120, 100%, 40%);">+    printf("Measurement Compute Test: %s\n", mtc->name);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   lchan->ts->pchan = GSM_PCHAN_TCH_F;</span><br><span style="color: hsl(120, 100%, 40%);">+     lchan = &trx->ts[mtc->ts].lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+ lchan->ts->pchan = mtc->pchan;</span><br><span>      reset_lchan_meas(lchan);</span><br><span> </span><br><span>         /* feed uplink measurements into the code */</span><br><span>@@ -94,6 +98,8 @@</span><br><span>             OSMO_ASSERT(!(lchan->meas.flags & LC_UL_M_F_RES_VALID));</span><br><span>      } else {</span><br><span>             OSMO_ASSERT(lchan->meas.flags & (LC_UL_M_F_RES_VALID|LC_UL_M_F_OSMO_EXT_VALID));</span><br><span style="color: hsl(120, 100%, 40%);">+               printf("number of measurements: %u\n",  mtc->ulm_count);</span><br><span style="color: hsl(120, 100%, 40%);">+         printf("parameter                | actual | expected\n");</span><br><span>          printf("meas.ext.toa256_min      | %6d | %6d\n",</span><br><span>                   lchan->meas.ext.toa256_min, mtc->res.toa256_min);</span><br><span>              printf("meas.ext.toa256_max      | %6d | %6d\n",</span><br><span>@@ -113,6 +119,7 @@</span><br><span>                 (lchan->meas.ext.toa256_std_dev != mtc->res.toa256_std_dev) ||</span><br><span>                 (lchan->meas.ul_res.full.rx_lev != mtc->res.rx_lev_full)) {</span><br><span>                        fprintf(stderr, "%s: Unexpected measurement result!\n", mtc->name);</span><br><span style="color: hsl(120, 100%, 40%);">+                      OSMO_ASSERT(false);</span><br><span>          }</span><br><span>    }</span><br><span> </span><br><span>@@ -1121,6 +1128,15 @@</span><br><span>       test_meas_compute(&mtc3);</span><br><span>        test_meas_compute(&mtc4);</span><br><span>        test_meas_compute(&mtc5);</span><br><span style="color: hsl(120, 100%, 40%);">+ test_meas_compute(&mtc_tch_f_complete);</span><br><span style="color: hsl(120, 100%, 40%);">+   test_meas_compute(&mtc_tch_f_dtx_with_lost_subs);</span><br><span style="color: hsl(120, 100%, 40%);">+ test_meas_compute(&mtc_tch_f_dtx);</span><br><span style="color: hsl(120, 100%, 40%);">+        test_meas_compute(&mtc_tch_h_complete);</span><br><span style="color: hsl(120, 100%, 40%);">+   test_meas_compute(&mtc_tch_h_dtx_with_lost_subs);</span><br><span style="color: hsl(120, 100%, 40%);">+ test_meas_compute(&mtc_tch_h_dtx);</span><br><span style="color: hsl(120, 100%, 40%);">+        test_meas_compute(&mtc_overrun);</span><br><span style="color: hsl(120, 100%, 40%);">+  test_meas_compute(&mtc_sdcch4_complete);</span><br><span style="color: hsl(120, 100%, 40%);">+  test_meas_compute(&mtc_sdcch8_complete);</span><br><span> </span><br><span>     printf("\n");</span><br><span>      printf("***************************************************\n");</span><br><span>diff --git a/tests/meas/meas_test.ok b/tests/meas/meas_test.ok</span><br><span>index 58e527a..86d8d87 100644</span><br><span>--- a/tests/meas/meas_test.ok</span><br><span>+++ b/tests/meas/meas_test.ok</span><br><span>@@ -540,33 +540,167 @@</span><br><span> Testing: ts[7]->lchan[0], fn=15170=>015170/11/12/23/14, fn%104=90, rc=1, delta=91</span><br><span> Testing: ts[7]->lchan[1], fn=15183=>015183/11/25/36/27, fn%104=103, rc=1, delta=13</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-Measurement Compute Test TOA256 Min-Max negative/positive</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%);">+Measurement Compute Test: TOA256 Min-Max negative/positive</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 3</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span> meas.ext.toa256_min      |   -256 |   -256</span><br><span> meas.ext.toa256_max      |    256 |    256</span><br><span> meas.ms_toa256           |      0 |      0</span><br><span> meas.ext.toa256_std_dev  |    209 |    209</span><br><span> meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(0, 100%, 40%);">-meas.ul_res.full.rx_qual |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      7 |      0</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-Measurement Compute Test TOA256 small jitter around 256</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%);">+Measurement Compute Test: TOA256 small jitter around 256</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 25</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span> meas.ext.toa256_min      |    254 |    254</span><br><span> meas.ext.toa256_max      |    258 |    258</span><br><span> meas.ms_toa256           |    256 |    256</span><br><span> meas.ext.toa256_std_dev  |      1 |      1</span><br><span> meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(0, 100%, 40%);">-meas.ul_res.full.rx_qual |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      0 |      7</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-Measurement Compute Test RxLEv averaging</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%);">+Measurement Compute Test: RxLEv averaging</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 5</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span> meas.ext.toa256_min      |      0 |      0</span><br><span> meas.ext.toa256_max      |      0 |      0</span><br><span> meas.ms_toa256           |      0 |      0</span><br><span> meas.ext.toa256_std_dev  |      0 |      0</span><br><span> meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      7 |      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%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Empty measurements</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 0</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     63 |     63</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      3 |      3</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: TOA256 26 blocks with max TOA256</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 26</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span> meas.ul_res.full.rx_qual |      0 |      0</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-Measurement Compute Test Empty measurements</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-Measurement Compute Test TOA256 26 blocks with max TOA256</span><br><span style="color: hsl(120, 100%, 40%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Complete TCH/F measurement period (26 measurements, 3 sub-frames)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 25</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      0 |      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%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Incomplete TCH/F measurement period (16 measurements, 1 sub-frame)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 16</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      7 |      7</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Incomplete but normal TCH/F measurement period (16 measurements, 3 sub-frames)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 16</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      7 |      7</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Complete TCH/H measurement period (26 measurements, 5 sub-frames)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 25</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      0 |      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%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Incomplete TCH/H measurement period (14 measurements, 3 sub-frames)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 14</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      7 |      7</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Incomplete but normal TCH/F measurement period (16 measurements, 5 sub-frames)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 16</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      7 |      7</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: TCH/F measurement period with too much measurement values (overrun)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 59</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      0 |      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%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Complete SDCCH4 measurement period (3 measurements)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 3</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_min      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_max      |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ms_toa256           |  16384 |  16384</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ext.toa256_std_dev  |      0 |      0</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_lev  |     20 |     20</span><br><span style="color: hsl(120, 100%, 40%);">+meas.ul_res.full.rx_qual |      0 |      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%);">+===========================================================</span><br><span style="color: hsl(120, 100%, 40%);">+Measurement Compute Test: Complete SDCCH8 measurement period (3 measurements)</span><br><span style="color: hsl(120, 100%, 40%);">+number of measurements: 3</span><br><span style="color: hsl(120, 100%, 40%);">+parameter                | actual | expected</span><br><span> meas.ext.toa256_min      |  16384 |  16384</span><br><span> meas.ext.toa256_max      |  16384 |  16384</span><br><span> meas.ms_toa256           |  16384 |  16384</span><br><span>diff --git a/tests/meas/meas_testcases.h b/tests/meas/meas_testcases.h</span><br><span>index ff74a20..fefa34f 100644</span><br><span>--- a/tests/meas/meas_testcases.h</span><br><span>+++ b/tests/meas/meas_testcases.h</span><br><span>@@ -1,5 +1,5 @@</span><br><span style="color: hsl(0, 100%, 40%);">-#define ULM(ber, ta, neg_rssi) \</span><br><span style="color: hsl(0, 100%, 40%);">-      { .ber10k = (ber), .ta_offs_256bits = (ta), .c_i = 1.0, .is_sub = 0, .inv_rssi = (neg_rssi) }</span><br><span style="color: hsl(120, 100%, 40%);">+#define ULM(ber, ta, sub, neg_rssi) \</span><br><span style="color: hsl(120, 100%, 40%);">+  { .ber10k = (ber), .ta_offs_256bits = (ta), .c_i = 1.0, .is_sub = sub, .inv_rssi = (neg_rssi) }</span><br><span> </span><br><span> struct meas_testcase {</span><br><span>        const char *name;</span><br><span>@@ -7,6 +7,8 @@</span><br><span>  const struct bts_ul_meas *ulm;</span><br><span>       unsigned int ulm_count;</span><br><span>      uint32_t final_fn;</span><br><span style="color: hsl(120, 100%, 40%);">+    uint8_t ts;</span><br><span style="color: hsl(120, 100%, 40%);">+   enum gsm_phys_chan_config pchan;</span><br><span>     /* results */</span><br><span>        struct {</span><br><span>             int success;</span><br><span>@@ -20,15 +22,21 @@</span><br><span> };</span><br><span> </span><br><span> static struct bts_ul_meas ulm1[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-    ULM(0, 0, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-  ULM(0, 256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-        ULM(0, -256, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+     /* Note: The assumptions about the frame number and the subset</span><br><span style="color: hsl(120, 100%, 40%);">+         * allegiance is random since for the calculation only the amount</span><br><span style="color: hsl(120, 100%, 40%);">+      * is of relevance. This is true for all following testcases */</span><br><span style="color: hsl(120, 100%, 40%);">+       ULM(0, 0, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+     ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, -256, 0, 90),</span><br><span> };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct meas_testcase mtc1 = {</span><br><span>   .name = "TOA256 Min-Max negative/positive",</span><br><span>        .ulm = ulm1,</span><br><span>         .ulm_count = ARRAY_SIZE(ulm1),</span><br><span>       .final_fn = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span>    .res = {</span><br><span>             .success = 1,</span><br><span>                .rx_lev_full = 110-90,</span><br><span>@@ -41,22 +49,44 @@</span><br><span> };</span><br><span> </span><br><span> static struct bts_ul_meas ulm2[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-  ULM(0, 256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-        ULM(0, 258, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-        ULM(0, 254, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-        ULM(0, 258, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-        ULM(0, 254, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-        ULM(0, 256, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+      ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 258, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 254, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 256, 0, 90),</span><br><span> };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct meas_testcase mtc2 = {</span><br><span>    .name = "TOA256 small jitter around 256",</span><br><span>  .ulm = ulm2,</span><br><span>         .ulm_count = ARRAY_SIZE(ulm2),</span><br><span>       .final_fn = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span>    .res = {</span><br><span>             .success = 1,</span><br><span>                .rx_lev_full = 110-90,</span><br><span style="color: hsl(0, 100%, 40%);">-          .rx_qual_full = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 7,</span><br><span>           .toa256_mean = 256,</span><br><span>          .toa256_max = 258,</span><br><span>           .toa256_min = 254,</span><br><span>@@ -65,17 +95,20 @@</span><br><span> };</span><br><span> </span><br><span> static struct bts_ul_meas ulm3[] = {</span><br><span style="color: hsl(0, 100%, 40%);">-      ULM(0, 0, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-  ULM(0, 0, 80),</span><br><span style="color: hsl(0, 100%, 40%);">-  ULM(0, 0, 80),</span><br><span style="color: hsl(0, 100%, 40%);">-  ULM(0, 0, 100),</span><br><span style="color: hsl(0, 100%, 40%);">- ULM(0, 0, 100),</span><br><span style="color: hsl(120, 100%, 40%);">+       ULM(0, 0, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+     ULM(0, 0, 0, 80),</span><br><span style="color: hsl(120, 100%, 40%);">+     ULM(0, 0, 0, 80),</span><br><span style="color: hsl(120, 100%, 40%);">+     ULM(0, 0, 0, 100),</span><br><span style="color: hsl(120, 100%, 40%);">+    ULM(0, 0, 0, 100),</span><br><span> };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct meas_testcase mtc3 = {</span><br><span>     .name = "RxLEv averaging",</span><br><span>         .ulm = ulm3,</span><br><span>         .ulm_count = ARRAY_SIZE(ulm3),</span><br><span>       .final_fn = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span>    .res = {</span><br><span>             .success = 1,</span><br><span>                .rx_lev_full = 110-90,</span><br><span>@@ -88,15 +121,18 @@</span><br><span> };</span><br><span> </span><br><span> static struct bts_ul_meas ulm4[] = {};</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct meas_testcase mtc4 = {</span><br><span>    .name = "Empty measurements",</span><br><span>      .ulm = ulm4,</span><br><span>         .ulm_count = ARRAY_SIZE(ulm4),</span><br><span>       .final_fn = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span>    .res = {</span><br><span style="color: hsl(0, 100%, 40%);">-                .success = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-           .rx_lev_full = 0,</span><br><span style="color: hsl(0, 100%, 40%);">-               .rx_qual_full = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 63,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 3,</span><br><span>           .toa256_mean = 0,</span><br><span>            .toa256_max = 0,</span><br><span>             .toa256_min = 0,</span><br><span>@@ -107,38 +143,41 @@</span><br><span> static struct bts_ul_meas ulm5[] = {</span><br><span>     /* one 104 multiframe can at max contain 26 blocks (TCH/F),</span><br><span>   * each of which can at maximum be 64 bits in advance (TA range) */</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(0, 100%, 40%);">-     ULM(0, 64*256, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+   ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span> };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> static const struct meas_testcase mtc5 = {</span><br><span>         .name = "TOA256 26 blocks with max TOA256",</span><br><span>        .ulm = ulm5,</span><br><span>         .ulm_count = ARRAY_SIZE(ulm5),</span><br><span>       .final_fn = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span>    .res = {</span><br><span>             .success = 1,</span><br><span>                .rx_lev_full = 110-90,</span><br><span>@@ -149,3 +188,391 @@</span><br><span>               .toa256_std_dev = 0,</span><br><span>         },</span><br><span> };</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This testcase models a good case as we can see it when all TCH</span><br><span style="color: hsl(120, 100%, 40%);">+ * and SACCH blocks are received */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_tch_f_complete[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</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 const struct meas_testcase mtc_tch_f_complete = {</span><br><span style="color: hsl(120, 100%, 40%);">+        .name = "Complete TCH/F measurement period (26 measurements, 3 sub-frames)",</span><br><span style="color: hsl(120, 100%, 40%);">+        .ulm = ulm_tch_f_complete,</span><br><span style="color: hsl(120, 100%, 40%);">+    .ulm_count = ARRAY_SIZE(ulm_tch_f_complete),</span><br><span style="color: hsl(120, 100%, 40%);">+  .final_fn = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span style="color: hsl(120, 100%, 40%);">+     .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+                .toa256_max = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_min = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This testcase models an error case where two of 3 expected sub measurements</span><br><span style="color: hsl(120, 100%, 40%);">+ * are lost. The calculation logic must detect this and replace those</span><br><span style="color: hsl(120, 100%, 40%);">+ * measurements. Note that this example also lacks some blocks due to DTX,</span><br><span style="color: hsl(120, 100%, 40%);">+ * which is normal. */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_tch_f_dtx_with_lost_subs[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</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 const struct meas_testcase mtc_tch_f_dtx_with_lost_subs = {</span><br><span style="color: hsl(120, 100%, 40%);">+      /* This testcase models a good case as we can see it when all TCH</span><br><span style="color: hsl(120, 100%, 40%);">+      * and SACCH blocks are received */</span><br><span style="color: hsl(120, 100%, 40%);">+   .name = "Incomplete TCH/F measurement period (16 measurements, 1 sub-frame)",</span><br><span style="color: hsl(120, 100%, 40%);">+       .ulm = ulm_tch_f_dtx_with_lost_subs,</span><br><span style="color: hsl(120, 100%, 40%);">+  .ulm_count = ARRAY_SIZE(ulm_tch_f_dtx_with_lost_subs),</span><br><span style="color: hsl(120, 100%, 40%);">+        .final_fn = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span style="color: hsl(120, 100%, 40%);">+     .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_max = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_min = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This testcase models a good-case with DTX. Some measurements are missing</span><br><span style="color: hsl(120, 100%, 40%);">+ * because no block was transmitted, all sub measurements are there. */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_tch_f_dtx[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</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 const struct meas_testcase mtc_tch_f_dtx = {</span><br><span style="color: hsl(120, 100%, 40%);">+     .name = "Incomplete but normal TCH/F measurement period (16 measurements, 3 sub-frames)",</span><br><span style="color: hsl(120, 100%, 40%);">+   .ulm = ulm_tch_f_dtx,</span><br><span style="color: hsl(120, 100%, 40%);">+ .ulm_count = ARRAY_SIZE(ulm_tch_f_dtx),</span><br><span style="color: hsl(120, 100%, 40%);">+       .final_fn = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span style="color: hsl(120, 100%, 40%);">+     .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_max = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_min = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This testcase models a good case as we can see it when all TCH</span><br><span style="color: hsl(120, 100%, 40%);">+ * and SACCH blocks are received */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_tch_h_complete[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+  ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</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 const struct meas_testcase mtc_tch_h_complete = {</span><br><span style="color: hsl(120, 100%, 40%);">+        .name = "Complete TCH/H measurement period (26 measurements, 5 sub-frames)",</span><br><span style="color: hsl(120, 100%, 40%);">+        .ulm = ulm_tch_h_complete,</span><br><span style="color: hsl(120, 100%, 40%);">+    .ulm_count = ARRAY_SIZE(ulm_tch_h_complete),</span><br><span style="color: hsl(120, 100%, 40%);">+  .final_fn = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_H,</span><br><span style="color: hsl(120, 100%, 40%);">+     .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 110 - 90,</span><br><span style="color: hsl(120, 100%, 40%);">+              .rx_qual_full = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+                .toa256_max = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_min = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_tch_h_dtx_with_lost_subs[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</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 const struct meas_testcase mtc_tch_h_dtx_with_lost_subs = {</span><br><span style="color: hsl(120, 100%, 40%);">+      .name = "Incomplete TCH/H measurement period (14 measurements, 3 sub-frames)",</span><br><span style="color: hsl(120, 100%, 40%);">+      .ulm = ulm_tch_h_dtx_with_lost_subs,</span><br><span style="color: hsl(120, 100%, 40%);">+  .ulm_count = ARRAY_SIZE(ulm_tch_h_dtx_with_lost_subs),</span><br><span style="color: hsl(120, 100%, 40%);">+        .final_fn = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_H,</span><br><span style="color: hsl(120, 100%, 40%);">+     .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_max = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_min = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This testcase models a good-case with DTX. Some measurements are missing</span><br><span style="color: hsl(120, 100%, 40%);">+ * because no block was transmitted, all sub measurements are there. */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_tch_h_dtx[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+ ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</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 const struct meas_testcase mtc_tch_h_dtx = {</span><br><span style="color: hsl(120, 100%, 40%);">+     .name = "Incomplete but normal TCH/F measurement period (16 measurements, 5 sub-frames)",</span><br><span style="color: hsl(120, 100%, 40%);">+   .ulm = ulm_tch_h_dtx,</span><br><span style="color: hsl(120, 100%, 40%);">+ .ulm_count = ARRAY_SIZE(ulm_tch_h_dtx),</span><br><span style="color: hsl(120, 100%, 40%);">+       .final_fn = 38,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 2,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_H,</span><br><span style="color: hsl(120, 100%, 40%);">+     .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_max = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_min = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* This testcase assumes that too many measurements were collected. This can</span><br><span style="color: hsl(120, 100%, 40%);">+ * happen when the measurement calculation for a previous cycle were not</span><br><span style="color: hsl(120, 100%, 40%);">+ * executed. In this case the older part of the excess data must be discarded.</span><br><span style="color: hsl(120, 100%, 40%);">+ * the calculation algorithm must make sure that the calculation only takes</span><br><span style="color: hsl(120, 100%, 40%);">+ * place on the last measurement interval */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_overrun[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+      ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        /* All measurements above must be discarded */</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 0, 90),</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 const struct meas_testcase mtc_overrun = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .name = "TCH/F measurement period with too much measurement values (overrun)",</span><br><span style="color: hsl(120, 100%, 40%);">+      .ulm = ulm_overrun,</span><br><span style="color: hsl(120, 100%, 40%);">+   .ulm_count = ARRAY_SIZE(ulm_overrun),</span><br><span style="color: hsl(120, 100%, 40%);">+ .final_fn = 25,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_TCH_F,</span><br><span style="color: hsl(120, 100%, 40%);">+     .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 110 - 90,</span><br><span style="color: hsl(120, 100%, 40%);">+              .rx_qual_full = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+                .toa256_max = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_min = 64*256,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Test SDCCH4 with all frames received */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_sdcch4_complete[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</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 const struct meas_testcase mtc_sdcch4_complete = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .name = "Complete SDCCH4 measurement period (3 measurements)",</span><br><span style="color: hsl(120, 100%, 40%);">+      .ulm = ulm_sdcch4_complete,</span><br><span style="color: hsl(120, 100%, 40%);">+   .ulm_count = ARRAY_SIZE(ulm_sdcch4_complete),</span><br><span style="color: hsl(120, 100%, 40%);">+ .final_fn = 88,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_CCCH_SDCCH4,</span><br><span style="color: hsl(120, 100%, 40%);">+       .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_max = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_min = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_std_dev = 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+/* Test SDCCH8 with all frames received */</span><br><span style="color: hsl(120, 100%, 40%);">+static struct bts_ul_meas ulm_sdcch8_complete[] = {</span><br><span style="color: hsl(120, 100%, 40%);">+     ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</span><br><span style="color: hsl(120, 100%, 40%);">+        ULM(0, 64*256, 1, 90),</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 const struct meas_testcase mtc_sdcch8_complete = {</span><br><span style="color: hsl(120, 100%, 40%);">+       .name = "Complete SDCCH8 measurement period (3 measurements)",</span><br><span style="color: hsl(120, 100%, 40%);">+      .ulm = ulm_sdcch8_complete,</span><br><span style="color: hsl(120, 100%, 40%);">+   .ulm_count = ARRAY_SIZE(ulm_sdcch8_complete),</span><br><span style="color: hsl(120, 100%, 40%);">+ .final_fn = 66,</span><br><span style="color: hsl(120, 100%, 40%);">+       .ts = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+      .pchan = GSM_PCHAN_SDCCH8_SACCH8C,</span><br><span style="color: hsl(120, 100%, 40%);">+    .res = {</span><br><span style="color: hsl(120, 100%, 40%);">+              .success = 1,</span><br><span style="color: hsl(120, 100%, 40%);">+         .rx_lev_full = 20,</span><br><span style="color: hsl(120, 100%, 40%);">+            .rx_qual_full = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+            .toa256_mean = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+         .toa256_max = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_min = 16384,</span><br><span style="color: hsl(120, 100%, 40%);">+          .toa256_std_dev = 0,</span><br><span style="color: hsl(120, 100%, 40%);">+  },</span><br><span style="color: hsl(120, 100%, 40%);">+};</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/10476">change 10476</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/10476"/><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: merged </div>
<div style="display:none"> Gerrit-Change-Id: Idd30fc07603ad7d042c1fb416e247c3bf7d35c8b </div>
<div style="display:none"> Gerrit-Change-Number: 10476 </div>
<div style="display:none"> Gerrit-PatchSet: 7 </div>
<div style="display:none"> Gerrit-Owner: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Harald Welte <laforge@gnumonks.org> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder (1000002) </div>
<div style="display:none"> Gerrit-Reviewer: dexter <pmaier@sysmocom.de> </div>