<p>pespin has uploaded this change for <strong>review</strong>.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bts/+/25268">View Change</a></p><pre style="font-family: monospace,monospace; white-space: pre-wrap;">WIP: MS power loop: Take C/I into account<br><br>Related: SYS#4917<br>Change-Id: I5dfd8ff9ab6b499646498b507624758dcc160fb6<br>---<br>M include/osmo-bts/gsm_data.h<br>M include/osmo-bts/power_control.h<br>M src/common/gsm_data.c<br>M src/common/l1sap.c<br>M src/common/power_control.c<br>M tests/power/ms_power_loop_test.c<br>M tests/power/ms_power_loop_test.err<br>M tests/power/ms_power_loop_test.ok<br>8 files changed, 313 insertions(+), 128 deletions(-)<br><br></pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;">git pull ssh://gerrit.osmocom.org:29418/osmo-bts refs/changes/68/25268/1</pre><pre style="font-family: monospace,monospace; white-space: pre-wrap;"><span>diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h</span><br><span>index 80f1833..979e6d9 100644</span><br><span>--- a/include/osmo-bts/gsm_data.h</span><br><span>+++ b/include/osmo-bts/gsm_data.h</span><br><span>@@ -211,6 +211,14 @@</span><br><span>     /* Measurement averaging parameters for RxLev & RxQual */</span><br><span>        struct gsm_power_ctrl_meas_params rxqual_meas;</span><br><span>       struct gsm_power_ctrl_meas_params rxlev_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Measurement averaging parameters for C/I, per chan type */</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_power_ctrl_meas_params ci_fr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_power_ctrl_meas_params ci_hr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ struct gsm_power_ctrl_meas_params ci_amr_fr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm_power_ctrl_meas_params ci_amr_hr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+     struct gsm_power_ctrl_meas_params ci_sdcch_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+      struct gsm_power_ctrl_meas_params ci_gprs_meas;</span><br><span> };</span><br><span> </span><br><span> /* Default MS/BS Power Control parameters */</span><br><span>diff --git a/include/osmo-bts/power_control.h b/include/osmo-bts/power_control.h</span><br><span>index f2e14cf..ed9f891 100644</span><br><span>--- a/include/osmo-bts/power_control.h</span><br><span>+++ b/include/osmo-bts/power_control.h</span><br><span>@@ -5,7 +5,8 @@</span><br><span> </span><br><span> int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,</span><br><span>                     const uint8_t ms_power_lvl,</span><br><span style="color: hsl(0, 100%, 40%);">-                     const int8_t ul_rssi_dbm);</span><br><span style="color: hsl(120, 100%, 40%);">+                    const int8_t ul_rssi_dbm,</span><br><span style="color: hsl(120, 100%, 40%);">+                     const int16_t ul_lqual_cb);</span><br><span> </span><br><span> int lchan_bs_pwr_ctrl(struct gsm_lchan *lchan,</span><br><span>                    const struct gsm48_hdr *gh);</span><br><span>diff --git a/src/common/gsm_data.c b/src/common/gsm_data.c</span><br><span>index b1f695b..e5a4d38 100644</span><br><span>--- a/src/common/gsm_data.c</span><br><span>+++ b/src/common/gsm_data.c</span><br><span>@@ -527,4 +527,46 @@</span><br><span>           /* FIXME: RxQual averaging is not yet implemented */</span><br><span>                 .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,</span><br><span>     },</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  /* C/I measurement parameters. //TODO: Add ci_*meas here, based on</span><br><span style="color: hsl(120, 100%, 40%);">+     * Target C/I retrieved from "GSM/EDGE: Evolution and Performance" Table 10.3.</span><br><span style="color: hsl(120, 100%, 40%);">+       * Set lower and upper so that (lower + upper) / 2 is equal or slightly</span><br><span style="color: hsl(120, 100%, 40%);">+        * above the target.</span><br><span style="color: hsl(120, 100%, 40%);">+   */</span><br><span style="color: hsl(120, 100%, 40%);">+   .ci_fr_meas = { /* Target C/I = 15 dB, Soft blocking threshold = 10 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_thresh = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+           .upper_thresh = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+           /* FIXME: C/I averaging is not yet implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+             .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_hr_meas = { /* Target C/I = 18 dB, Soft blocking threshold = 13 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_thresh = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+           .upper_thresh = 21,</span><br><span style="color: hsl(120, 100%, 40%);">+           /* FIXME: C/I averaging is not yet implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+             .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_amr_fr_meas = { /* Target C/I = 9 dB, Soft blocking threshold = 4 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+           .lower_thresh = 7,</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_thresh = 11,</span><br><span style="color: hsl(120, 100%, 40%);">+           /* FIXME: C/I averaging is not yet implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+             .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_amr_hr_meas = { /* Target C/I = 15 dB, Soft blocking threshold = 10 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+         .lower_thresh = 13,</span><br><span style="color: hsl(120, 100%, 40%);">+           .upper_thresh = 17,</span><br><span style="color: hsl(120, 100%, 40%);">+           /* FIXME: C/I averaging is not yet implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+             .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_sdcch_meas = { /* Target C/I = 14 dB, Soft blocking threshold = 9 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+           .lower_thresh = 12,</span><br><span style="color: hsl(120, 100%, 40%);">+           .upper_thresh = 16,</span><br><span style="color: hsl(120, 100%, 40%);">+           /* FIXME: C/I averaging is not yet implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+             .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_gprs_meas = { /* Target C/I = 20 dB, Soft blocking threshold = 15 dB */</span><br><span style="color: hsl(120, 100%, 40%);">+           .lower_thresh = 18,</span><br><span style="color: hsl(120, 100%, 40%);">+           .upper_thresh = 24,</span><br><span style="color: hsl(120, 100%, 40%);">+           /* FIXME: C/I averaging is not yet implemented */</span><br><span style="color: hsl(120, 100%, 40%);">+             .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE,</span><br><span style="color: hsl(120, 100%, 40%);">+      },</span><br><span> };</span><br><span>diff --git a/src/common/l1sap.c b/src/common/l1sap.c</span><br><span>index c028a2c..189a814 100644</span><br><span>--- a/src/common/l1sap.c</span><br><span>+++ b/src/common/l1sap.c</span><br><span>@@ -1600,7 +1600,7 @@</span><br><span>                        rsl_tx_meas_res(lchan, NULL, 0, le);</span><br><span> </span><br><span>                     radio_link_timeout(lchan, true);</span><br><span style="color: hsl(0, 100%, 40%);">-                        lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, data_ind->rssi);</span><br><span style="color: hsl(120, 100%, 40%);">+                 lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, data_ind->rssi, data_ind->lqual_cb);</span><br><span>                 }</span><br><span>            return -EINVAL;</span><br><span>      }</span><br><span>@@ -1628,7 +1628,7 @@</span><br><span>            lchan->meas.l1_info.ta = l1_hdr->ta;</span><br><span>           lchan->meas.flags |= LC_UL_M_F_L1_VALID;</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-         lchan_ms_pwr_ctrl(lchan, data[0] & 0x1f, data_ind->rssi);</span><br><span style="color: hsl(120, 100%, 40%);">+              lchan_ms_pwr_ctrl(lchan, data[0] & 0x1f, data_ind->rssi, data_ind->lqual_cb);</span><br><span>              lchan_bs_pwr_ctrl(lchan, (const struct gsm48_hdr *) &data[5]);</span><br><span>   } else</span><br><span>               le = &lchan->lapdm_ch.lapdm_dcch;</span><br><span>diff --git a/src/common/power_control.c b/src/common/power_control.c</span><br><span>index 4f5d15e..1a08fcb 100644</span><br><span>--- a/src/common/power_control.c</span><br><span>+++ b/src/common/power_control.c</span><br><span>@@ -139,14 +139,36 @@</span><br><span>        return delta;</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static const struct gsm_power_ctrl_meas_params *lchan_get_ci_thresholds(const struct gsm_lchan *lchan)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct gsm_power_ctrl_params *params = lchan->ms_power_ctrl.dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    switch (lchan->type) {</span><br><span style="color: hsl(120, 100%, 40%);">+     case GSM_LCHAN_SDCCH:</span><br><span style="color: hsl(120, 100%, 40%);">+         return &params->ci_sdcch_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ case GSM_LCHAN_PDTCH:</span><br><span style="color: hsl(120, 100%, 40%);">+         return &params->ci_gprs_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+  case GSM_LCHAN_TCH_F:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* FIXME: check if need to return ci_amr_fr_meas */</span><br><span style="color: hsl(120, 100%, 40%);">+           return &params->ci_fr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+    case GSM_LCHAN_TCH_H:</span><br><span style="color: hsl(120, 100%, 40%);">+         /* FIXME: check if need to return ci_amr_hr_meas */</span><br><span style="color: hsl(120, 100%, 40%);">+           return &params->ci_hr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+    default:</span><br><span style="color: hsl(120, 100%, 40%);">+              OSMO_ASSERT(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> /*! compute the new MS POWER LEVEL communicated to the MS and store it in lchan.</span><br><span>  *  \param lchan logical channel for which to compute (and in which to store) new power value.</span><br><span>  *  \param[in] ms_power_lvl MS Power Level received from Uplink L1 SACCH Header in SACCH block.</span><br><span>  *  \param[in] ul_rssi_dbm Signal level of the received SACCH block, in dBm.</span><br><span style="color: hsl(120, 100%, 40%);">+ *  \param[in] ul_lqual_cb C/I of the received SACCH block, in dB.</span><br><span>  */</span><br><span> int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,</span><br><span>                       const uint8_t ms_power_lvl,</span><br><span style="color: hsl(0, 100%, 40%);">-                     const int8_t ul_rssi_dbm)</span><br><span style="color: hsl(120, 100%, 40%);">+                     const int8_t ul_rssi_dbm,</span><br><span style="color: hsl(120, 100%, 40%);">+                     const int16_t ul_lqual_cb)</span><br><span> {</span><br><span>        struct lchan_power_ctrl_state *state = &lchan->ms_power_ctrl;</span><br><span>         const struct gsm_power_ctrl_params *params = state->dpc_params;</span><br><span>@@ -155,6 +177,7 @@</span><br><span>     enum gsm_band band = bts->band;</span><br><span>   int8_t new_power_lvl; /* TS 05.05 power level */</span><br><span>     int8_t ms_dbm, new_dbm, current_dbm, bsc_max_dbm;</span><br><span style="color: hsl(120, 100%, 40%);">+     const struct gsm_power_ctrl_meas_params *ci_meas;</span><br><span> </span><br><span>        if (!trx_ms_pwr_ctrl_is_osmo(trx))</span><br><span>           return 0;</span><br><span>@@ -187,8 +210,24 @@</span><br><span>             return 0;</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-   /* Calculate the new Tx power value (in dBm) */</span><br><span style="color: hsl(0, 100%, 40%);">- new_dbm = ms_dbm + calc_delta(params, state, ul_rssi_dbm);</span><br><span style="color: hsl(120, 100%, 40%);">+    /* If computed C/I is out of acceptable thresholds: */</span><br><span style="color: hsl(120, 100%, 40%);">+        ci_meas = lchan_get_ci_thresholds(lchan);</span><br><span style="color: hsl(120, 100%, 40%);">+     if (ul_lqual_cb < ci_meas->lower_thresh * 10) {</span><br><span style="color: hsl(120, 100%, 40%);">+         new_dbm = ms_dbm + params->inc_step_size_db;</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGPLCHAN(lchan, DLOOP, LOGL_ERROR, "Increasing MS Tx power: "</span><br><span style="color: hsl(120, 100%, 40%);">+                        "%d -> %d dB due to C/I %d cB worse than %u cB on %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                         ms_dbm, new_dbm, ul_lqual_cb, ci_meas->lower_thresh * 10,</span><br><span style="color: hsl(120, 100%, 40%);">+                          gsm_lchant_name(lchan->type));</span><br><span style="color: hsl(120, 100%, 40%);">+   } else if (ul_lqual_cb > ci_meas->upper_thresh * 10) {</span><br><span style="color: hsl(120, 100%, 40%);">+          new_dbm = ms_dbm - params->red_step_size_db;</span><br><span style="color: hsl(120, 100%, 40%);">+               LOGPLCHAN(lchan, DLOOP, LOGL_ERROR, "Decreasing MS Tx power: "</span><br><span style="color: hsl(120, 100%, 40%);">+                        "%d -> %d dB due to C/I %d cB better than %u cB on %s\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                        ms_dbm, new_dbm, ul_lqual_cb, ci_meas->upper_thresh * 10,</span><br><span style="color: hsl(120, 100%, 40%);">+                          gsm_lchant_name(lchan->type));</span><br><span style="color: hsl(120, 100%, 40%);">+   } else {</span><br><span style="color: hsl(120, 100%, 40%);">+              /* Calculate the new Tx power value (in dBm) */</span><br><span style="color: hsl(120, 100%, 40%);">+               new_dbm = ms_dbm + calc_delta(params, state, ul_rssi_dbm);</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span> </span><br><span>        /* Make sure new_dbm is never negative. ms_pwr_ctl_lvl() can later on</span><br><span>           cope with any unsigned dbm value, regardless of band minimal value. */</span><br><span>@@ -212,18 +251,18 @@</span><br><span> </span><br><span>        if (state->current == new_power_lvl) {</span><br><span>            LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Keeping MS power at control level %d, %d dBm "</span><br><span style="color: hsl(0, 100%, 40%);">-                      "(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                         "(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm, C/I %d cB)\n",</span><br><span>                     new_power_lvl, new_dbm, ms_power_lvl, state->max,</span><br><span style="color: hsl(0, 100%, 40%);">-                    ul_rssi_dbm, target_dbm);</span><br><span style="color: hsl(120, 100%, 40%);">+                     ul_rssi_dbm, target_dbm, ul_lqual_cb);</span><br><span>             return 0;</span><br><span>    }</span><br><span> </span><br><span>        current_dbm = ms_pwr_dbm(band, state->current);</span><br><span>   LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "%s MS power from control level %d (%d dBm) to %d, %d dBm "</span><br><span style="color: hsl(0, 100%, 40%);">-                  "(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm)\n",</span><br><span style="color: hsl(120, 100%, 40%);">+                 "(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", rx-current %d dBm, rx-target %d dBm, C/I %d cB)\n",</span><br><span>             (new_dbm > current_dbm) ? "Raising" : "Lowering",</span><br><span>             state->current, current_dbm, new_power_lvl, new_dbm,</span><br><span style="color: hsl(0, 100%, 40%);">-                 ms_power_lvl, state->max, ul_rssi_dbm, target_dbm);</span><br><span style="color: hsl(120, 100%, 40%);">+                ms_power_lvl, state->max, ul_rssi_dbm, target_dbm, ul_lqual_cb);</span><br><span> </span><br><span>    /* store the resulting new MS power level in the lchan */</span><br><span>    state->current = new_power_lvl;</span><br><span>diff --git a/tests/power/ms_power_loop_test.c b/tests/power/ms_power_loop_test.c</span><br><span>index 0d86310..f0c0250 100644</span><br><span>--- a/tests/power/ms_power_loop_test.c</span><br><span>+++ b/tests/power/ms_power_loop_test.c</span><br><span>@@ -67,13 +67,13 @@</span><br><span>        printf("\nStarting test case '%s'\n", name);</span><br><span> }</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-static inline void apply_power_test(struct gsm_lchan *lchan, int rxlev, int exp_ret, uint8_t exp_current)</span><br><span style="color: hsl(120, 100%, 40%);">+static inline void apply_power_test(struct gsm_lchan *lchan, int rxlev, int lqual_cb, int exp_ret, uint8_t exp_current)</span><br><span> {</span><br><span>       uint8_t old;</span><br><span>         int ret;</span><br><span> </span><br><span>         old = lchan->ms_power_ctrl.current;</span><br><span style="color: hsl(0, 100%, 40%);">-  ret = lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, rxlev);</span><br><span style="color: hsl(120, 100%, 40%);">+       ret = lchan_ms_pwr_ctrl(lchan, lchan->ms_power_ctrl.current, rxlev, lqual_cb);</span><br><span> </span><br><span>        /* Keep the measurement counter updated */</span><br><span>   lchan->meas.res_nr++;</span><br><span>@@ -87,9 +87,14 @@</span><br><span> static void test_power_loop(void)</span><br><span> {</span><br><span>      struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct gsm_power_ctrl_params *params;</span><br><span style="color: hsl(120, 100%, 40%);">+   int16_t good_lqual;</span><br><span> </span><br><span>      init_test(__func__);</span><br><span>         lchan = &g_trx->ts[0].lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        params = lchan->ms_power_ctrl.dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+  lchan->type = GSM_LCHAN_SDCCH;</span><br><span style="color: hsl(120, 100%, 40%);">+     good_lqual = (params->ci_sdcch_meas.lower_thresh + 2) * 10;</span><br><span> </span><br><span>   lchan->ms_power_ctrl.current = ms_pwr_ctl_lvl(GSM_BAND_1800, 0);</span><br><span>  OSMO_ASSERT(lchan->ms_power_ctrl.current == 15);</span><br><span>@@ -97,73 +102,78 @@</span><br><span>   OSMO_ASSERT(lchan->ms_power_ctrl.max == 2);</span><br><span> </span><br><span>   /* Simply clamping */</span><br><span style="color: hsl(0, 100%, 40%);">-   apply_power_test(lchan, -60, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -60, good_lqual, 0, 15);</span><br><span> </span><br><span>         /*</span><br><span>    * Now 15 dB too little and we should power it up. Could be a</span><br><span>         * power level of 7 or 8 for 15 dBm. However, since we limit peace at</span><br><span>         * which we change values, expect several steps of MS_RAISE_MAX_DB/2 levels:</span><br><span>          */</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -90, 1, 13);</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -90, 1, 11);</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -90, 1, 9);</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -90, 1, 7);</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -90, 1, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+   apply_power_test(lchan, -90, good_lqual, 1, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+      apply_power_test(lchan, -90, good_lqual, 1, 11);</span><br><span style="color: hsl(120, 100%, 40%);">+      apply_power_test(lchan, -90, good_lqual, 1, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -90, good_lqual, 1, 7);</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -90, good_lqual, 1, 5);</span><br><span> </span><br><span>  /* Check good RSSI value keeps it at same power level: */</span><br><span style="color: hsl(0, 100%, 40%);">-       apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, 0, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+     apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, good_lqual, 0, 5);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-       apply_power_test(lchan, -90, 1, 3);</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -90, 1, 2); /* .max is pwr lvl 2 */</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -90, 0, 2); /* .max is pwr lvl 2 */</span><br><span style="color: hsl(120, 100%, 40%);">+   apply_power_test(lchan, -90, good_lqual, 1, 3);</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -90, good_lqual, 1, 2); /* .max is pwr lvl 2 */</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -90, good_lqual, 0, 2); /* .max is pwr lvl 2 */</span><br><span> </span><br><span>  lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 30);</span><br><span>     OSMO_ASSERT(lchan->ms_power_ctrl.max == 0);</span><br><span style="color: hsl(0, 100%, 40%);">-  apply_power_test(lchan, -90, 1, 0); /* .max is pwr lvl 0 */</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -90, 0, 0); /* .max is pwr lvl 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+   apply_power_test(lchan, -90, good_lqual, 1, 0); /* .max is pwr lvl 0 */</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -90, good_lqual, 0, 0); /* .max is pwr lvl 0 */</span><br><span> </span><br><span>  lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 36);</span><br><span>     OSMO_ASSERT(lchan->ms_power_ctrl.max == 29);</span><br><span style="color: hsl(0, 100%, 40%);">- apply_power_test(lchan, -90, 1, 30);</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -90, 1, 29);</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -90, 0, 29);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -90, good_lqual, 1, 30);</span><br><span style="color: hsl(120, 100%, 40%);">+      apply_power_test(lchan, -90, good_lqual, 1, 29);</span><br><span style="color: hsl(120, 100%, 40%);">+      apply_power_test(lchan, -90, good_lqual, 0, 29);</span><br><span> </span><br><span>         /* Check good RSSI value keeps it at same power level: */</span><br><span style="color: hsl(0, 100%, 40%);">-       apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, 0, 29);</span><br><span style="color: hsl(120, 100%, 40%);">+    apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, good_lqual, 0, 29);</span><br><span> </span><br><span>   /* Now go down, steps are double size in this direction: */</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -45, 1, 1);</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -45, 1, 5);</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -45, 1, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+   apply_power_test(lchan, -45, good_lqual, 1, 1);</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -45, good_lqual, 1, 5);</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -45, good_lqual, 1, 9);</span><br><span> </span><br><span>  /* Go down only one level down and up: */</span><br><span style="color: hsl(0, 100%, 40%);">-       apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 2, 1, 10);</span><br><span style="color: hsl(0, 100%, 40%);">-  apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 2, 1, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+ apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 2, good_lqual, 1, 10);</span><br><span style="color: hsl(120, 100%, 40%);">+    apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 2, good_lqual, 1, 9);</span><br><span> </span><br><span>        /* Check if BSC requesting a low max power is applied after loop calculation: */</span><br><span>     lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 2);</span><br><span>      OSMO_ASSERT(lchan->ms_power_ctrl.max == 14);</span><br><span style="color: hsl(0, 100%, 40%);">- apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 2, 1, 14);</span><br><span style="color: hsl(120, 100%, 40%);">+        apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 2, good_lqual, 1, 14);</span><br><span>   /* Set back a more normal max: */</span><br><span>    lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 30);</span><br><span>     OSMO_ASSERT(lchan->ms_power_ctrl.max == 0);</span><br><span> </span><br><span>   /* Disable dynamic power control and jump down */</span><br><span>    lchan->ms_power_ctrl.dpc_params = NULL;</span><br><span style="color: hsl(0, 100%, 40%);">-      apply_power_test(lchan, -60, 0, 14);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -60, good_lqual, 0, 14);</span><br><span> </span><br><span>         /* Enable and leave it again */</span><br><span>      lchan->ms_power_ctrl.dpc_params = &lchan->ms_dpc_params;</span><br><span style="color: hsl(0, 100%, 40%);">-      apply_power_test(lchan, -40, 1, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -40, good_lqual, 1, 15);</span><br><span> }</span><br><span> </span><br><span> static void test_pf_algo_ewma(void)</span><br><span> {</span><br><span>        struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct gsm_power_ctrl_params *params;</span><br><span style="color: hsl(120, 100%, 40%);">+   int16_t good_lqual;</span><br><span>  const int *avg100;</span><br><span> </span><br><span>       init_test(__func__);</span><br><span>         lchan = &g_trx->ts[0].lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        lchan->type = GSM_LCHAN_SDCCH;</span><br><span style="color: hsl(120, 100%, 40%);">+     params = lchan->ms_power_ctrl.dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+  good_lqual = (params->ci_sdcch_meas.lower_thresh + 2) * 10;</span><br><span>       avg100 = &lchan->ms_power_ctrl.rxlev_meas_proc.ewma.Avg100;</span><br><span> </span><br><span>       struct gsm_power_ctrl_meas_params *mp = &lchan->ms_dpc_params.rxlev_meas;</span><br><span>@@ -180,15 +190,15 @@</span><br><span>            ((float) *avg100) / 100, exp);</span><br><span> </span><br><span>    /* UL RSSI remains constant => no UL power change */</span><br><span style="color: hsl(0, 100%, 40%);">- apply_power_test(lchan, -75, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -75, good_lqual, 0, 15);</span><br><span>     CHECK_UL_RSSI_AVG100(-75.00);</span><br><span> </span><br><span>    /* Avg[t] = (0.2 * -90) + (0.8 * -75) = -78.0 dBm */</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -90, 1, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -90, good_lqual, 1, 13);</span><br><span>     CHECK_UL_RSSI_AVG100(-78.00);</span><br><span> </span><br><span>    /* Avg[t] = (0.2 * -90) + (0.8 * -78) = -80.4 dBm */</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -90, 1, 11);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -90, good_lqual, 1, 11);</span><br><span>     CHECK_UL_RSSI_AVG100(-80.40);</span><br><span> </span><br><span>    /* Avg[t] = (0.2 * -70) + (0.8 * -80.4) = -78.32 dBm,</span><br><span>@@ -199,7 +209,7 @@</span><br><span>   *   Avg100[t] = -8040 + 20 * (-70 + 80)</span><br><span>      *   Avg100[t] = -8040 + 200 = -7840</span><br><span>          *   Avg[t] = -7840 / 100 = -78.4 */</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -70, 1, 9);</span><br><span style="color: hsl(120, 100%, 40%);">+   apply_power_test(lchan, -70, good_lqual, 1, 9);</span><br><span>      CHECK_UL_RSSI_AVG100(-78.40);</span><br><span> </span><br><span>    mp->ewma.alpha = 70; /* 30% smoothing */</span><br><span>@@ -208,25 +218,30 @@</span><br><span>          (struct gsm_power_ctrl_meas_proc_state) { 0 };</span><br><span> </span><br><span>   /* This is the first sample, the filter outputs it as-is */</span><br><span style="color: hsl(0, 100%, 40%);">-     apply_power_test(lchan, -50, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -50, good_lqual, 0, 15);</span><br><span>     CHECK_UL_RSSI_AVG100(-50.00);</span><br><span> </span><br><span>    /* Avg[t] = (0.7 * -50) + (0.3 * -50) = -50.0 dBm */</span><br><span style="color: hsl(0, 100%, 40%);">-    apply_power_test(lchan, -50, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -50, good_lqual, 0, 15);</span><br><span>     CHECK_UL_RSSI_AVG100(-50.0);</span><br><span> </span><br><span>     /* Simulate SACCH block loss (-110 dBm):</span><br><span>      * Avg[t] = (0.7 * -110) + (0.3 * -50) = -92.0 dBm */</span><br><span style="color: hsl(0, 100%, 40%);">-   apply_power_test(lchan, -110, 1, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+ apply_power_test(lchan, -110, good_lqual, 1, 13);</span><br><span>    CHECK_UL_RSSI_AVG100(-92.0);</span><br><span> }</span><br><span> </span><br><span> static void test_power_hysteresis(void)</span><br><span> {</span><br><span>        struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct gsm_power_ctrl_params *params;</span><br><span style="color: hsl(120, 100%, 40%);">+   int16_t good_lqual;</span><br><span> </span><br><span>      init_test(__func__);</span><br><span>         lchan = &g_trx->ts[0].lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        lchan->type = GSM_LCHAN_SDCCH;</span><br><span style="color: hsl(120, 100%, 40%);">+     params = lchan->ms_power_ctrl.dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+  good_lqual = (params->ci_sdcch_meas.lower_thresh + 2) * 10;</span><br><span> </span><br><span>   /* Tolerate power deviations in range -80 .. -70 */</span><br><span>  lchan->ms_dpc_params.rxlev_meas.lower_thresh = 30;</span><br><span>@@ -237,61 +252,66 @@</span><br><span>        lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 26);</span><br><span>     OSMO_ASSERT(lchan->ms_power_ctrl.max == 2);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, 0, 15);</span><br><span style="color: hsl(0, 100%, 40%);">-      apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 3, 0, 15);</span><br><span style="color: hsl(0, 100%, 40%);">-  apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 3, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+        apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, good_lqual, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+        apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 3, good_lqual, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+    apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 3, good_lqual, 0, 15);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, 0, 15);</span><br><span style="color: hsl(0, 100%, 40%);">-      apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 5, 0, 15);</span><br><span style="color: hsl(0, 100%, 40%);">-  apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 5, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+        apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM, good_lqual, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+        apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM + 5, good_lqual, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+    apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 5, good_lqual, 0, 15);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-  apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 10, 1, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 10, good_lqual, 1, 13);</span><br><span> }</span><br><span> </span><br><span> static void test_power_ctrl_interval(void)</span><br><span> {</span><br><span>      struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct gsm_power_ctrl_params *params;</span><br><span style="color: hsl(120, 100%, 40%);">+   int16_t good_lqual;</span><br><span>  unsigned int i, j;</span><br><span> </span><br><span>       init_test(__func__);</span><br><span>         lchan = &g_trx->ts[0].lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        lchan->type = GSM_LCHAN_SDCCH;</span><br><span style="color: hsl(120, 100%, 40%);">+     params = lchan->ms_power_ctrl.dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+  good_lqual = (params->ci_sdcch_meas.lower_thresh + 2) * 10;</span><br><span> </span><br><span>   lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 26);</span><br><span>     OSMO_ASSERT(lchan->ms_power_ctrl.max == 2);</span><br><span> </span><br><span style="color: hsl(0, 100%, 40%);">-      static const int script[][8][3] = {</span><br><span style="color: hsl(120, 100%, 40%);">+   const int script[][8][4] = {</span><br><span>                 { /* P_Con_INTERVAL=0 (480 ms) */</span><br><span>                    /* { UL RxLev, expected rc, expected Tx power level } */</span><br><span style="color: hsl(0, 100%, 40%);">-                        { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,      13 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,      11 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       9 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       7 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       5 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       3 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       2 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       2 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,      13 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,      11 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       9 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       7 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       5 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       3 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       2 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       2 },</span><br><span>                },</span><br><span>           { /* P_Con_INTERVAL=1 (960 ms) */</span><br><span>                    /* { UL RxLev, expected rc, expected Tx power level } */</span><br><span style="color: hsl(0, 100%, 40%);">-                        { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,      13 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      13 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,      11 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      11 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       9 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,       9 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,       7 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,       7 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,      13 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      13 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,      11 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      11 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       9 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,       9 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,       7 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,       7 }, /* skipped */</span><br><span>          },</span><br><span>           { /* P_Con_INTERVAL=2 (1920 ms) */</span><br><span>                   /* { UL RxLev, expected rc, expected Tx power level } */</span><br><span style="color: hsl(0, 100%, 40%);">-                        { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,      13 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      13 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      13 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      13 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       1,      11 },</span><br><span style="color: hsl(0, 100%, 40%);">-                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      11 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      11 }, /* skipped */</span><br><span style="color: hsl(0, 100%, 40%);">-                     { PWR_TEST_RXLEV_TARGET_DBM - 15,       0,      11 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,      13 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      13 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      13 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      13 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     1,      11 },</span><br><span style="color: hsl(120, 100%, 40%);">+                 { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      11 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      11 }, /* skipped */</span><br><span style="color: hsl(120, 100%, 40%);">+                   { PWR_TEST_RXLEV_TARGET_DBM - 15,       good_lqual,     0,      11 }, /* skipped */</span><br><span>          },</span><br><span>   };</span><br><span> </span><br><span>@@ -305,14 +325,54 @@</span><br><span> </span><br><span>           for (j = 0; j < ARRAY_SIZE(script[i]); j++) {</span><br><span>                     apply_power_test(lchan, script[i][j][0],  /* UL RxLev */</span><br><span style="color: hsl(0, 100%, 40%);">-                                                script[i][j][1],  /* expected rc */</span><br><span style="color: hsl(0, 100%, 40%);">-                                             script[i][j][2]); /* expected Tx power level */</span><br><span style="color: hsl(120, 100%, 40%);">+                                               script[i][j][1],  /* UL C/I */</span><br><span style="color: hsl(120, 100%, 40%);">+                                                script[i][j][2],  /* expected rc */</span><br><span style="color: hsl(120, 100%, 40%);">+                                           script[i][j][3]); /* expected Tx power level */</span><br><span>              }</span><br><span> </span><br><span>                printf("\n");</span><br><span>      }</span><br><span> }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+static void test_power_loop_ci(void)</span><br><span style="color: hsl(120, 100%, 40%);">+{</span><br><span style="color: hsl(120, 100%, 40%);">+   struct gsm_lchan *lchan;</span><br><span style="color: hsl(120, 100%, 40%);">+      const struct gsm_power_ctrl_params *params;</span><br><span style="color: hsl(120, 100%, 40%);">+   int16_t good_lqual, too_low_lqual, too_high_lqual;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  init_test(__func__);</span><br><span style="color: hsl(120, 100%, 40%);">+  lchan = &g_trx->ts[0].lchan[0];</span><br><span style="color: hsl(120, 100%, 40%);">+        params = lchan->ms_power_ctrl.dpc_params;</span><br><span style="color: hsl(120, 100%, 40%);">+  lchan->type = GSM_LCHAN_SDCCH;</span><br><span style="color: hsl(120, 100%, 40%);">+     good_lqual = (params->ci_sdcch_meas.lower_thresh + 2) * 10;</span><br><span style="color: hsl(120, 100%, 40%);">+        too_low_lqual = (params->ci_sdcch_meas.lower_thresh - 1) * 10;</span><br><span style="color: hsl(120, 100%, 40%);">+     too_high_lqual = (params->ci_sdcch_meas.upper_thresh + 1) * 10;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+  lchan->ms_power_ctrl.current = ms_pwr_ctl_lvl(GSM_BAND_1800, 0);</span><br><span style="color: hsl(120, 100%, 40%);">+   OSMO_ASSERT(lchan->ms_power_ctrl.current == 15);</span><br><span style="color: hsl(120, 100%, 40%);">+   lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 26);</span><br><span style="color: hsl(120, 100%, 40%);">+      OSMO_ASSERT(lchan->ms_power_ctrl.max == 2);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      /* Simply clamping */</span><br><span style="color: hsl(120, 100%, 40%);">+ apply_power_test(lchan, -60, good_lqual, 0, 15);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+    /* Now UL C/I is too bad as well as RSSI: */</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -100, too_low_lqual, 1, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+  apply_power_test(lchan, -100, too_low_lqual, 1, 11);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Now UL C/I is good again while RSSI is good: */</span><br><span style="color: hsl(120, 100%, 40%);">+    apply_power_test(lchan, -60, good_lqual, 1, 12);</span><br><span style="color: hsl(120, 100%, 40%);">+      apply_power_test(lchan, -60, too_high_lqual, 1, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+        /* Now UL C/I is good while RSSI is bad, C/I mandates: */</span><br><span style="color: hsl(120, 100%, 40%);">+     apply_power_test(lchan, -100, good_lqual, 1, 11);</span><br><span style="color: hsl(120, 100%, 40%);">+     apply_power_test(lchan, -100, too_high_lqual, 1, 12);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+       /* Now UL C/I is bad again while RSSI is good, C/I mandates: */</span><br><span style="color: hsl(120, 100%, 40%);">+       apply_power_test(lchan, -60, good_lqual, 1, 13);</span><br><span style="color: hsl(120, 100%, 40%);">+      apply_power_test(lchan, -60, too_high_lqual, 1, 14);</span><br><span style="color: hsl(120, 100%, 40%);">+}</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span> int main(int argc, char **argv)</span><br><span> {</span><br><span>    printf("Testing power loop...\n");</span><br><span>@@ -332,6 +392,7 @@</span><br><span>   test_pf_algo_ewma();</span><br><span>         test_power_hysteresis();</span><br><span>     test_power_ctrl_interval();</span><br><span style="color: hsl(120, 100%, 40%);">+   test_power_loop_ci();</span><br><span> </span><br><span>    printf("Power loop test OK\n");</span><br><span> </span><br><span>diff --git a/tests/power/ms_power_loop_test.err b/tests/power/ms_power_loop_test.err</span><br><span>index ae8ad03..f7ebaed 100644</span><br><span>--- a/tests/power/ms_power_loop_test.err</span><br><span>+++ b/tests/power/ms_power_loop_test.err</span><br><span>@@ -1,51 +1,65 @@</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -60 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 7 (16 dBm) to 5, 20 dBm (rx-ms-pwr-lvl 7, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 5, 20 dBm (rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 5 (20 dBm) to 3, 24 dBm (rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 3 (24 dBm) to 2, 26 dBm (rx-ms-pwr-lvl 3, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 2, 26 dBm (rx-ms-pwr-lvl 2, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 2 (26 dBm) to 0, 30 dBm (rx-ms-pwr-lvl 2, max-ms-pwr-lvl 0, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 0, 30 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 0, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 0 (30 dBm) to 30, 34 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 29, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 30 (34 dBm) to 29, 36 dBm (rx-ms-pwr-lvl 30, max-ms-pwr-lvl 29, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 29, 36 dBm (rx-ms-pwr-lvl 29, max-ms-pwr-lvl 29, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 29, 36 dBm (rx-ms-pwr-lvl 29, max-ms-pwr-lvl 29, rx-current -75 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 29 (36 dBm) to 30, 34 dBm (rx-ms-pwr-lvl 29, max-ms-pwr-lvl 29, rx-current -45 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 30 (34 dBm) to 31, 32 dBm (rx-ms-pwr-lvl 30, max-ms-pwr-lvl 29, rx-current -45 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 31 (32 dBm) to 0, 30 dBm (rx-ms-pwr-lvl 31, max-ms-pwr-lvl 29, rx-current -45 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 0 (30 dBm) to 1, 28 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 29, rx-current -73 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 1 (28 dBm) to 0, 30 dBm (rx-ms-pwr-lvl 1, max-ms-pwr-lvl 29, rx-current -77 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 0 (30 dBm) to 14, 2 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 14, rx-current -73 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 14 (2 dBm) to 15, 0 dBm (rx-ms-pwr-lvl 14, max-ms-pwr-lvl 0, rx-current -40 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 3 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 11 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -70 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -50 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -50 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -110 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -72 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -78 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -70 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -80 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -85 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 7 (16 dBm) to 5, 20 dBm (rx-ms-pwr-lvl 7, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 5 (20 dBm) to 3, 24 dBm (rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 3 (24 dBm) to 2, 26 dBm (rx-ms-pwr-lvl 3, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 2, 26 dBm (rx-ms-pwr-lvl 2, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(0, 100%, 40%);">-(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -60 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 7 (16 dBm) to 5, 20 dBm (rx-ms-pwr-lvl 7, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 5, 20 dBm (rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 5 (20 dBm) to 3, 24 dBm (rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 3 (24 dBm) to 2, 26 dBm (rx-ms-pwr-lvl 3, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 2, 26 dBm (rx-ms-pwr-lvl 2, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 2 (26 dBm) to 0, 30 dBm (rx-ms-pwr-lvl 2, max-ms-pwr-lvl 0, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 0, 30 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 0, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 0 (30 dBm) to 30, 34 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 29, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 30 (34 dBm) to 29, 36 dBm (rx-ms-pwr-lvl 30, max-ms-pwr-lvl 29, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 29, 36 dBm (rx-ms-pwr-lvl 29, max-ms-pwr-lvl 29, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 29, 36 dBm (rx-ms-pwr-lvl 29, max-ms-pwr-lvl 29, rx-current -75 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 29 (36 dBm) to 30, 34 dBm (rx-ms-pwr-lvl 29, max-ms-pwr-lvl 29, rx-current -45 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 30 (34 dBm) to 31, 32 dBm (rx-ms-pwr-lvl 30, max-ms-pwr-lvl 29, rx-current -45 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 31 (32 dBm) to 0, 30 dBm (rx-ms-pwr-lvl 31, max-ms-pwr-lvl 29, rx-current -45 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 0 (30 dBm) to 1, 28 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 29, rx-current -73 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 1 (28 dBm) to 0, 30 dBm (rx-ms-pwr-lvl 1, max-ms-pwr-lvl 29, rx-current -77 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 0 (30 dBm) to 14, 2 dBm (rx-ms-pwr-lvl 0, max-ms-pwr-lvl 14, rx-current -73 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 14 (2 dBm) to 15, 0 dBm (rx-ms-pwr-lvl 14, max-ms-pwr-lvl 0, rx-current -40 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 3 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 11 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -70 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -50 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -50 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -110 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -72 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -78 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -75 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -70 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -80 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -85 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 7 (16 dBm) to 5, 20 dBm (rx-ms-pwr-lvl 7, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 5 (20 dBm) to 3, 24 dBm (rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 3 (24 dBm) to 2, 26 dBm (rx-ms-pwr-lvl 3, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 2, 26 dBm (rx-ms-pwr-lvl 2, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 11 (8 dBm) to 9, 12 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 9 (12 dBm) to 7, 16 dBm (rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -90 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Keeping MS power at control level 15, 0 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -60 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Increasing MS Tx power: 0 -> 4 dB due to C/I 110 cB worse than 120 cB on SDCCH</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 15 (0 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, rx-current -100 dBm, rx-target -75 dBm, C/I 110 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Increasing MS Tx power: 4 -> 8 dB due to C/I 110 cB worse than 120 cB on SDCCH</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -100 dBm, rx-target -75 dBm, C/I 110 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 11 (8 dBm) to 12, 6 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -60 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Decreasing MS Tx power: 6 -> 4 dB due to C/I 170 cB better than 160 cB on SDCCH</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 12 (6 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 12, max-ms-pwr-lvl 2, rx-current -60 dBm, rx-target -75 dBm, C/I 170 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power from control level 13 (4 dBm) to 11, 8 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -100 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Decreasing MS Tx power: 8 -> 6 dB due to C/I 170 cB better than 160 cB on SDCCH</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 11 (8 dBm) to 12, 6 dBm (rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, rx-current -100 dBm, rx-target -75 dBm, C/I 170 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 12 (6 dBm) to 13, 4 dBm (rx-ms-pwr-lvl 12, max-ms-pwr-lvl 2, rx-current -60 dBm, rx-target -75 dBm, C/I 140 cB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Decreasing MS Tx power: 4 -> 2 dB due to C/I 170 cB better than 160 cB on SDCCH</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power from control level 13 (4 dBm) to 14, 2 dBm (rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, rx-current -60 dBm, rx-target -75 dBm, C/I 170 cB)</span><br><span>diff --git a/tests/power/ms_power_loop_test.ok b/tests/power/ms_power_loop_test.ok</span><br><span>index 5fea474..ccf2ddc 100644</span><br><span>--- a/tests/power/ms_power_loop_test.ok</span><br><span>+++ b/tests/power/ms_power_loop_test.ok</span><br><span>@@ -144,4 +144,24 @@</span><br><span> lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0)</span><br><span>      MS current power 11 -> 11 (expected 11)</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+Starting test case 'test_power_loop_ci'</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-60 dBm) returns 0 (expected 0)</span><br><span style="color: hsl(120, 100%, 40%);">+    MS current power 15 -> 15 (expected 15)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-100 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+  MS current power 15 -> 13 (expected 13)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-100 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+  MS current power 13 -> 11 (expected 11)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-60 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+   MS current power 11 -> 12 (expected 12)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-60 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+   MS current power 12 -> 13 (expected 13)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-100 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+  MS current power 13 -> 11 (expected 11)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-100 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+  MS current power 11 -> 12 (expected 12)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-60 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+   MS current power 12 -> 13 (expected 13)</span><br><span style="color: hsl(120, 100%, 40%);">+lchan_ms_pwr_ctrl(RxLvl=-60 dBm) returns 1 (expected 1)</span><br><span style="color: hsl(120, 100%, 40%);">+   MS current power 13 -> 14 (expected 14)</span><br><span> Power loop test OK</span><br><span></span><br></pre><p>To view, visit <a href="https://gerrit.osmocom.org/c/osmo-bts/+/25268">change 25268</a>. To unsubscribe, or for help writing mail filters, visit <a href="https://gerrit.osmocom.org/settings">settings</a>.</p><div itemscope itemtype="http://schema.org/EmailMessage"><div itemscope itemprop="action" itemtype="http://schema.org/ViewAction"><link itemprop="url" href="https://gerrit.osmocom.org/c/osmo-bts/+/25268"/><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-Change-Id: I5dfd8ff9ab6b499646498b507624758dcc160fb6 </div>
<div style="display:none"> Gerrit-Change-Number: 25268 </div>
<div style="display:none"> Gerrit-PatchSet: 1 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: newchange </div>