<p>pespin <strong>submitted</strong> this change.</p><p><a href="https://gerrit.osmocom.org/c/osmo-bts/+/25268">View Change</a></p><div style="white-space:pre-wrap">Approvals:
  Jenkins Builder: Verified
  osmith: Looks good to me, but someone else must approve
  laforge: Looks good to me, approved

</div><pre style="font-family: monospace,monospace; white-space: pre-wrap;">MS Power Control Loop: Take C/I into account<br><br>This commit extends existing MS Power Control Loop algorithm to take<br>into account computed C/I values on the UL, received from MS. The<br>related C/I parameters used by the algorithm are configured at and<br>provided by the BSC, which transmits them to the BTS similar to already<br>existing parameters.<br><br>Using C/I instead of existing RxQual is preferred due to extended<br>granularity of C/I (bigger range than RxQual's 0-7).<br>Furthermore, existing literature (such as "GSM/EDGE: Evolution and Performance"<br>Table 10.3) provides detailed information about expected target values,<br>even different values for different channel types. Hence, it was decided<br>to support setting different MS Power Parameters for different channel<br>types.<br><br>These MS Power Parameters are Osmocom specific, ie. supported only by<br>newish versions of osmo-bts. Older versions of osmo-bts should ignore<br>the new IEs added just fine. The new IEs containing the MS POwer<br>Parameters are not send for non osmo-bts BTSs, hence this commit is<br>secure with regards to running  osmo-bsc against an ip.access BTS such<br>as nanoBTS.<br><br>Related: SYS#4917<br>Depends: libosmocore.git Change-Id Iffef0611430ad6c90606149c398d80158633bbca<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 src/common/rsl.c<br>M src/common/vty.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>10 files changed, 504 insertions(+), 137 deletions(-)<br><br></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..2da16bb 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,136 @@</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.</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 = { /* FR: 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of LOWER_CMP_N averages are lower than L_CI_FR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+         .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of UPPER_CMP_N averages are greater than L_CI_FR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+               .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* No averaging (filtering) by default */</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%);">+            /* Hreqave: the period over which an average is produced */</span><br><span style="color: hsl(120, 100%, 40%);">+           .h_reqave = 4, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Hreqt: the number of averaged results maintained */</span><br><span style="color: hsl(120, 100%, 40%);">+                .h_reqt = 6, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_hr_meas = { /* HR: 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of LOWER_CMP_N averages are lower than L_CI_HR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+         .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of UPPER_CMP_N averages are greater than L_CI_HR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+               .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* No averaging (filtering) by default */</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%);">+            /* Hreqave: the period over which an average is produced */</span><br><span style="color: hsl(120, 100%, 40%);">+           .h_reqave = 4, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Hreqt: the number of averaged results maintained */</span><br><span style="color: hsl(120, 100%, 40%);">+                .h_reqt = 6, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_amr_fr_meas = { /* AMR-FR: 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of LOWER_CMP_N averages are lower than L_CI_AMR_FR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of UPPER_CMP_N averages are greater than L_CI_AMR_FR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+           .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* No averaging (filtering) by default */</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%);">+            /* Hreqave: the period over which an average is produced */</span><br><span style="color: hsl(120, 100%, 40%);">+           .h_reqave = 4, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Hreqt: the number of averaged results maintained */</span><br><span style="color: hsl(120, 100%, 40%);">+                .h_reqt = 6, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_amr_hr_meas = { /* AMR-HR: 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of LOWER_CMP_N averages are lower than L_CI_AMR_HR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of UPPER_CMP_N averages are greater than L_CI_AMR_HR_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+           .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* No averaging (filtering) by default */</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%);">+            /* Hreqave: the period over which an average is produced */</span><br><span style="color: hsl(120, 100%, 40%);">+           .h_reqave = 4, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Hreqt: the number of averaged results maintained */</span><br><span style="color: hsl(120, 100%, 40%);">+                .h_reqt = 6, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_sdcch_meas = { /* SDCCH: 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of LOWER_CMP_N averages are lower than L_CI_SDCCH_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+              .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of UPPER_CMP_N averages are greater than L_CI_SDCCH_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* No averaging (filtering) by default */</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%);">+            /* Hreqave: the period over which an average is produced */</span><br><span style="color: hsl(120, 100%, 40%);">+           .h_reqave = 4, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Hreqt: the number of averaged results maintained */</span><br><span style="color: hsl(120, 100%, 40%);">+                .h_reqt = 6, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+       },</span><br><span style="color: hsl(120, 100%, 40%);">+    .ci_gprs_meas = { /* GPRS: 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%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of LOWER_CMP_N averages are lower than L_CI_GPRS_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+               .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages</span><br><span style="color: hsl(120, 100%, 40%);">+             * out of UPPER_CMP_N averages are greater than L_CI_GPRS_XX_P */</span><br><span style="color: hsl(120, 100%, 40%);">+             .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+            .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          /* No averaging (filtering) by default */</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%);">+            /* Hreqave: the period over which an average is produced */</span><br><span style="color: hsl(120, 100%, 40%);">+           .h_reqave = 4, /* TODO: investigate a reasonable default value */</span><br><span style="color: hsl(120, 100%, 40%);">+             /* Hreqt: the number of averaged results maintained */</span><br><span style="color: hsl(120, 100%, 40%);">+                .h_reqt = 6, /* TODO: investigate a reasonable default value */</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 3b225c2..9785bfd 100644</span><br><span>--- a/src/common/l1sap.c</span><br><span>+++ b/src/common/l1sap.c</span><br><span>@@ -1604,7 +1604,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>@@ -1632,7 +1632,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..9d874c4 100644</span><br><span>--- a/src/common/power_control.c</span><br><span>+++ b/src/common/power_control.c</span><br><span>@@ -90,7 +90,7 @@</span><br><span> </span><br><span> /* Calculate target RxLev value from lower/upper thresholds */</span><br><span> #define CALC_TARGET(mp) \</span><br><span style="color: hsl(0, 100%, 40%);">-    (mp.lower_thresh + mp.upper_thresh) / 2</span><br><span style="color: hsl(120, 100%, 40%);">+       ((mp).lower_thresh + (mp).upper_thresh) / 2</span><br><span> </span><br><span> /* Calculate a 'delta' value (for the given MS/BS power control state and parameters)</span><br><span>  * to be applied to the current Tx power level to approach the target level. */</span><br><span>@@ -139,14 +139,40 @@</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%);">+         if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(120, 100%, 40%);">+                     return &params->ci_amr_fr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+                else</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%);">+         if (lchan->tch_mode == GSM48_CMODE_SPEECH_AMR)</span><br><span style="color: hsl(120, 100%, 40%);">+                     return &params->ci_amr_hr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+                else</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 +181,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 +214,16 @@</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%);">+       } 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%);">+       } 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>@@ -211,19 +246,21 @@</span><br><span>    int target_dbm = rxlev2dbm(CALC_TARGET(params->rxlev_meas));</span><br><span> </span><br><span>  if (state->current == new_power_lvl) {</span><br><span style="color: hsl(0, 100%, 40%);">-               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%);">+               LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Keeping MS power at control level %d (%d dBm): "</span><br><span style="color: hsl(120, 100%, 40%);">+                          "(rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", RSSI[curr %d, tgt %d] dBm,"</span><br><span style="color: hsl(120, 100%, 40%);">+                      " C/I[curr %d, tgt %d] dB)\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/10, CALC_TARGET(*ci_meas));</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 style="color: hsl(0, 100%, 40%);">-      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%);">+       LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "%s MS power control level %d (%d dBm) => %d (%d dBm): "</span><br><span style="color: hsl(120, 100%, 40%);">+                "rx-ms-pwr-lvl %" PRIu8 ", max-ms-pwr-lvl %" PRIu8 ", RSSI[curr %d, tgt %d] dBm,"</span><br><span style="color: hsl(120, 100%, 40%);">+               " C/I[curr %d, tgt %d] dB\n",</span><br><span>              (new_dbm > current_dbm) ? "Raising" : "Lowering",</span><br><span style="color: hsl(0, 100%, 40%);">-                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%);">+                state->current, current_dbm, new_power_lvl, new_dbm, ms_power_lvl,</span><br><span style="color: hsl(120, 100%, 40%);">+                 state->max, ul_rssi_dbm, target_dbm, ul_lqual_cb/10, CALC_TARGET(*ci_meas));</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/src/common/rsl.c b/src/common/rsl.c</span><br><span>index 4ad807f..f585ec4 100644</span><br><span>--- a/src/common/rsl.c</span><br><span>+++ b/src/common/rsl.c</span><br><span>@@ -938,6 +938,30 @@</span><br><span>               params->rxqual_meas.upper_thresh = thresh->u_rxqual;</span><br><span>   }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Osmocom extension, C/I related thresholds: */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (TLVP_PRES_LEN(&tp[0], RSL_IPAC_EIE_OSMO_MS_PWR_CTL, sizeof(struct osmo_preproc_pc_thresh))) {</span><br><span style="color: hsl(120, 100%, 40%);">+         const struct osmo_preproc_pc_thresh *osmo_thresh;</span><br><span style="color: hsl(120, 100%, 40%);">+             ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_OSMO_MS_PWR_CTL);</span><br><span style="color: hsl(120, 100%, 40%);">+              osmo_thresh = (const struct osmo_preproc_pc_thresh *) ie->val;</span><br><span style="color: hsl(120, 100%, 40%);">+             params->ci_fr_meas.lower_thresh = osmo_thresh->l_ci_fr;</span><br><span style="color: hsl(120, 100%, 40%);">+         params->ci_fr_meas.upper_thresh = osmo_thresh->u_ci_fr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               params->ci_hr_meas.lower_thresh = osmo_thresh->l_ci_hr;</span><br><span style="color: hsl(120, 100%, 40%);">+         params->ci_hr_meas.upper_thresh = osmo_thresh->u_ci_hr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               params->ci_amr_fr_meas.lower_thresh = osmo_thresh->l_ci_amr_fr;</span><br><span style="color: hsl(120, 100%, 40%);">+         params->ci_amr_fr_meas.upper_thresh = osmo_thresh->u_ci_amr_fr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               params->ci_amr_hr_meas.lower_thresh = osmo_thresh->l_ci_amr_hr;</span><br><span style="color: hsl(120, 100%, 40%);">+         params->ci_amr_hr_meas.upper_thresh = osmo_thresh->u_ci_amr_hr;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+               params->ci_sdcch_meas.lower_thresh = osmo_thresh->l_ci_sdcch;</span><br><span style="color: hsl(120, 100%, 40%);">+           params->ci_sdcch_meas.upper_thresh = osmo_thresh->u_ci_sdcch;</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+         params->ci_gprs_meas.lower_thresh = osmo_thresh->l_ci_gprs;</span><br><span style="color: hsl(120, 100%, 40%);">+             params->ci_gprs_meas.upper_thresh = osmo_thresh->u_ci_gprs;</span><br><span style="color: hsl(120, 100%, 40%);">+     }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* (TV) PC Threshold Comparators */</span><br><span>  if ((ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_PC_THRESH_COMP)) != NULL) {</span><br><span>              const struct ipac_preproc_pc_comp *thresh_comp;</span><br><span>@@ -964,6 +988,25 @@</span><br><span>               params->red_step_size_db = thresh_comp->red_step_size;</span><br><span>         }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* Osmocom extension, C/I related thresholds: */</span><br><span style="color: hsl(120, 100%, 40%);">+      if (TLVP_PRES_LEN(&tp[0], RSL_IPAC_EIE_OSMO_PC_THRESH_COMP, sizeof(struct osmo_preproc_pc_thresh))) {</span><br><span style="color: hsl(120, 100%, 40%);">+             const struct osmo_preproc_pc_comp *osmo_thresh_comp;</span><br><span style="color: hsl(120, 100%, 40%);">+          ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_OSMO_PC_THRESH_COMP);</span><br><span style="color: hsl(120, 100%, 40%);">+          osmo_thresh_comp = (const struct osmo_preproc_pc_comp *) ie->val;</span><br><span style="color: hsl(120, 100%, 40%);">+          #define SET_PREPROC_PC(PARAMS, FROM, TYPE) \</span><br><span style="color: hsl(120, 100%, 40%);">+                  (PARAMS)->TYPE##_meas.lower_cmp_p = (FROM)->TYPE.lower_p; \</span><br><span style="color: hsl(120, 100%, 40%);">+                     (PARAMS)->TYPE##_meas.lower_cmp_n = (FROM)->TYPE.lower_n; \</span><br><span style="color: hsl(120, 100%, 40%);">+                     (PARAMS)->TYPE##_meas.upper_cmp_p = (FROM)->TYPE.upper_p; \</span><br><span style="color: hsl(120, 100%, 40%);">+                     (PARAMS)->TYPE##_meas.upper_cmp_n = (FROM)->TYPE.upper_n</span><br><span style="color: hsl(120, 100%, 40%);">+                SET_PREPROC_PC(params, osmo_thresh_comp, ci_fr);</span><br><span style="color: hsl(120, 100%, 40%);">+              SET_PREPROC_PC(params, osmo_thresh_comp, ci_hr);</span><br><span style="color: hsl(120, 100%, 40%);">+              SET_PREPROC_PC(params, osmo_thresh_comp, ci_amr_fr);</span><br><span style="color: hsl(120, 100%, 40%);">+          SET_PREPROC_PC(params, osmo_thresh_comp, ci_amr_hr);</span><br><span style="color: hsl(120, 100%, 40%);">+          SET_PREPROC_PC(params, osmo_thresh_comp, ci_sdcch);</span><br><span style="color: hsl(120, 100%, 40%);">+           SET_PREPROC_PC(params, osmo_thresh_comp, ci_gprs);</span><br><span style="color: hsl(120, 100%, 40%);">+            #undef SET_PREPROC_PC</span><br><span style="color: hsl(120, 100%, 40%);">+ }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  /* (TLV) Measurement Averaging parameters for RxLev/RxQual */</span><br><span>        for (i = 0; i < ARRAY_SIZE(tp); i++) {</span><br><span>            const struct ipac_preproc_ave_cfg *ave_cfg;</span><br><span>@@ -1008,6 +1051,42 @@</span><br><span>                 }</span><br><span>    }</span><br><span> </span><br><span style="color: hsl(120, 100%, 40%);">+ /* (TLV) Measurement Averaging parameters for C/I (Osmocom extension)*/</span><br><span style="color: hsl(120, 100%, 40%);">+       if (TLVP_PRES_LEN(&tp[0], RSL_IPAC_EIE_OSMO_MEAS_AVG_CFG, sizeof(struct osmo_preproc_ave_cfg))) {</span><br><span style="color: hsl(120, 100%, 40%);">+         ie = TLVP_GET(&tp[0], RSL_IPAC_EIE_OSMO_MEAS_AVG_CFG);</span><br><span style="color: hsl(120, 100%, 40%);">+            const struct osmo_preproc_ave_cfg *cfg = (const struct osmo_preproc_ave_cfg *) ie->val;</span><br><span style="color: hsl(120, 100%, 40%);">+            unsigned params_offset = 0;</span><br><span style="color: hsl(120, 100%, 40%);">+           #define SET_AVE_CFG(PARAMS, FROM, TYPE, PARAM_OFFSET) do {\</span><br><span style="color: hsl(120, 100%, 40%);">+                           if ((FROM)->TYPE.ave_enabled) { \</span><br><span style="color: hsl(120, 100%, 40%);">+                                  (PARAMS)->TYPE##_meas.h_reqave = (FROM)->TYPE.h_reqave; \</span><br><span style="color: hsl(120, 100%, 40%);">+                                       (PARAMS)->TYPE##_meas.h_reqt = (FROM)->TYPE.h_reqt; \</span><br><span style="color: hsl(120, 100%, 40%);">+                                   (PARAMS)->TYPE##_meas.algo = (FROM)->TYPE.ave_method + 1; \</span><br><span style="color: hsl(120, 100%, 40%);">+                                     switch ((FROM)->TYPE.ave_method) { \</span><br><span style="color: hsl(120, 100%, 40%);">+                                       case IPAC_OSMO_EWMA_AVE: \</span><br><span style="color: hsl(120, 100%, 40%);">+                                            if (ie->len > sizeof(*cfg) + (PARAM_OFFSET)) {  \</span><br><span style="color: hsl(120, 100%, 40%);">+                                                       (PARAMS)->TYPE##_meas.ewma.alpha = (FROM)->params[PARAM_OFFSET]; \</span><br><span style="color: hsl(120, 100%, 40%);">+                                                      (PARAM_OFFSET)++; \</span><br><span style="color: hsl(120, 100%, 40%);">+                                           } \</span><br><span style="color: hsl(120, 100%, 40%);">+                                           break; \</span><br><span style="color: hsl(120, 100%, 40%);">+                                      /* FIXME: not implemented */ \</span><br><span style="color: hsl(120, 100%, 40%);">+                                        case IPAC_UNWEIGHTED_AVE: \</span><br><span style="color: hsl(120, 100%, 40%);">+                                   case IPAC_WEIGHTED_AVE: \</span><br><span style="color: hsl(120, 100%, 40%);">+                                     case IPAC_MEDIAN_AVE: \</span><br><span style="color: hsl(120, 100%, 40%);">+                                               break; \</span><br><span style="color: hsl(120, 100%, 40%);">+                                      } \</span><br><span style="color: hsl(120, 100%, 40%);">+                           } else { \</span><br><span style="color: hsl(120, 100%, 40%);">+                                    (PARAMS)->TYPE##_meas.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%);">+                   } while(0)</span><br><span style="color: hsl(120, 100%, 40%);">+            SET_AVE_CFG(params, cfg, ci_fr, params_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+               SET_AVE_CFG(params, cfg, ci_hr, params_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+               SET_AVE_CFG(params, cfg, ci_amr_fr, params_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+           SET_AVE_CFG(params, cfg, ci_amr_hr, params_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+           SET_AVE_CFG(params, cfg, ci_sdcch, params_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+            SET_AVE_CFG(params, cfg, ci_gprs, params_offset);</span><br><span style="color: hsl(120, 100%, 40%);">+             #undef SET_AVE_CFG</span><br><span style="color: hsl(120, 100%, 40%);">+    }</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span>  return 0;</span><br><span> }</span><br><span> </span><br><span>diff --git a/src/common/vty.c b/src/common/vty.c</span><br><span>index 4f618d0..62e2d70 100644</span><br><span>--- a/src/common/vty.c</span><br><span>+++ b/src/common/vty.c</span><br><span>@@ -1391,7 +1391,7 @@</span><br><span> }</span><br><span> </span><br><span> static void dump_dpc_params(struct vty *vty, const unsigned int indent,</span><br><span style="color: hsl(0, 100%, 40%);">-                         const struct gsm_power_ctrl_params *cp)</span><br><span style="color: hsl(120, 100%, 40%);">+                       const struct gsm_power_ctrl_params *cp, bool uplink)</span><br><span> {</span><br><span>        cfg_out(vty, "Power control interval: %u ms (every %u SACCH block(s))%s",</span><br><span>          cp->ctrl_interval ? cp->ctrl_interval * 2 * 480 : 480,</span><br><span>@@ -1408,6 +1408,26 @@</span><br><span> </span><br><span>    cfg_out(vty, "RxQual measurement processing:%s", VTY_NEWLINE);</span><br><span>     dump_dpc_meas_params(vty, indent + 2, &cp->rxqual_meas, "RXQUAL", 3);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+      if (uplink) {</span><br><span style="color: hsl(120, 100%, 40%);">+         cfg_out(vty, "C/I measurement processing (FR/EFR):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+                dump_dpc_meas_params(vty, indent + 2, &cp->ci_fr_meas, "CI_FR", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                cfg_out(vty, "C/I measurement processing (HR):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+            dump_dpc_meas_params(vty, indent + 2, &cp->ci_hr_meas, "CI_HR", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                cfg_out(vty, "C/I measurement processing (AMR-FR):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+                dump_dpc_meas_params(vty, indent + 2, &cp->ci_amr_fr_meas, "CI_AMR_FR", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                cfg_out(vty, "C/I measurement processing (AMR-HR):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+                dump_dpc_meas_params(vty, indent + 2, &cp->ci_amr_hr_meas, "CI_AMR_HR", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+                cfg_out(vty, "C/I measurement processing (SDCCH):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+         dump_dpc_meas_params(vty, indent + 2, &cp->ci_sdcch_meas, "CI_SDCCH", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+</span><br><span style="color: hsl(120, 100%, 40%);">+          cfg_out(vty, "C/I measurement processing (GPRS):%s", VTY_NEWLINE);</span><br><span style="color: hsl(120, 100%, 40%);">+          dump_dpc_meas_params(vty, indent + 2, &cp->ci_gprs_meas, "CI_GPRS", 0);</span><br><span style="color: hsl(120, 100%, 40%);">+      }</span><br><span> }</span><br><span> </span><br><span> static void trx_dump_vty(struct vty *vty, const struct gsm_bts_trx *trx)</span><br><span>@@ -1425,13 +1445,13 @@</span><br><span>             trx->bs_dpc_params == &trx->bts->bs_dpc_params ?</span><br><span>                        "fall-back" : "from BSC",</span><br><span>                VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-   dump_dpc_params(vty, 4, trx->bs_dpc_params);</span><br><span style="color: hsl(120, 100%, 40%);">+       dump_dpc_params(vty, 4, trx->bs_dpc_params, false);</span><br><span> </span><br><span>   vty_out(vty, "  MS Power control parameters (%s):%s",</span><br><span>              trx->ms_dpc_params == &trx->bts->ms_dpc_params ?</span><br><span>                        "fall-back" : "from BSC",</span><br><span>                VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-   dump_dpc_params(vty, 4, trx->ms_dpc_params);</span><br><span style="color: hsl(120, 100%, 40%);">+       dump_dpc_params(vty, 4, trx->ms_dpc_params, true);</span><br><span> </span><br><span>    vty_out(vty, "  NM State: ");</span><br><span>      net_dump_nmstate(vty, &trx->mo.nm_state);</span><br><span>@@ -1638,7 +1658,7 @@</span><br><span>             return;</span><br><span> </span><br><span>  cfg_out(vty, "Power Control parameters:%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-     dump_dpc_params(vty, indent + 2, st->dpc_params);</span><br><span style="color: hsl(120, 100%, 40%);">+  dump_dpc_params(vty, indent + 2, st->dpc_params, false);</span><br><span> }</span><br><span> </span><br><span> static void lchan_ms_power_ctrl_state_dump(struct vty *vty, unsigned int indent,</span><br><span>@@ -1664,7 +1684,7 @@</span><br><span>             return;</span><br><span> </span><br><span>  cfg_out(vty, "Power Control parameters:%s", VTY_NEWLINE);</span><br><span style="color: hsl(0, 100%, 40%);">-     dump_dpc_params(vty, indent + 2, st->dpc_params);</span><br><span style="color: hsl(120, 100%, 40%);">+  dump_dpc_params(vty, indent + 2, st->dpc_params, true);</span><br><span> }</span><br><span> </span><br><span> static void lchan_acch_rep_state_dump(struct vty *vty, unsigned int indent,</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..55092db 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,60 @@</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, RSSI[curr -60, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 13 (4 dBm) => 11 (8 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 11 (8 dBm) => 9 (12 dBm): rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 9 (12 dBm) => 7 (16 dBm): rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 7 (16 dBm) => 5 (20 dBm): rx-ms-pwr-lvl 7, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -75, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 5 (20 dBm) => 3 (24 dBm): rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 3 (24 dBm) => 2 (26 dBm): rx-ms-pwr-lvl 3, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 2 (26 dBm) => 0 (30 dBm): rx-ms-pwr-lvl 2, max-ms-pwr-lvl 0, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 0 (30 dBm) => 30 (34 dBm): rx-ms-pwr-lvl 0, max-ms-pwr-lvl 29, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 30 (34 dBm) => 29 (36 dBm): rx-ms-pwr-lvl 30, max-ms-pwr-lvl 29, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</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, RSSI[curr -75, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 29 (36 dBm) => 30 (34 dBm): rx-ms-pwr-lvl 29, max-ms-pwr-lvl 29, RSSI[curr -45, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 30 (34 dBm) => 31 (32 dBm): rx-ms-pwr-lvl 30, max-ms-pwr-lvl 29, RSSI[curr -45, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 31 (32 dBm) => 0 (30 dBm): rx-ms-pwr-lvl 31, max-ms-pwr-lvl 29, RSSI[curr -45, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 0 (30 dBm) => 1 (28 dBm): rx-ms-pwr-lvl 0, max-ms-pwr-lvl 29, RSSI[curr -73, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 1 (28 dBm) => 0 (30 dBm): rx-ms-pwr-lvl 1, max-ms-pwr-lvl 29, RSSI[curr -77, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 0 (30 dBm) => 14 (2 dBm): rx-ms-pwr-lvl 0, max-ms-pwr-lvl 14, RSSI[curr -73, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 14 (2 dBm) => 15 (0 dBm): rx-ms-pwr-lvl 14, max-ms-pwr-lvl 0, RSSI[curr -40, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -75, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (3 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 13 (4 dBm) => 11 (8 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 11 (8 dBm) => 9 (11 dBm): rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, RSSI[curr -70, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -50, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</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, RSSI[curr -50, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -110, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -75, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</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, RSSI[curr -72, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</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, RSSI[curr -78, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</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, RSSI[curr -75, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</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, RSSI[curr -70, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</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, RSSI[curr -80, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -85, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 13 (4 dBm) => 11 (8 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 11 (8 dBm) => 9 (12 dBm): rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 9 (12 dBm) => 7 (16 dBm): rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 7 (16 dBm) => 5 (20 dBm): rx-ms-pwr-lvl 7, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 5 (20 dBm) => 3 (24 dBm): rx-ms-pwr-lvl 5, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 3 (24 dBm) => 2 (26 dBm): rx-ms-pwr-lvl 3, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 13 (4 dBm) => 11 (8 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 11 (8 dBm) => 9 (12 dBm): rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 9 (12 dBm) => 7 (16 dBm): rx-ms-pwr-lvl 9, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 13 (4 dBm) => 11 (8 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -90, tgt -75] dBm, C/I[curr 14, tgt 14] dB</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, RSSI[curr -60, tgt -75] dBm, C/I[curr 14, tgt 14] dB)</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 15 (0 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 15, max-ms-pwr-lvl 2, RSSI[curr -100, tgt -75] dBm, C/I[curr 11, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 13 (4 dBm) => 11 (8 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -100, tgt -75] dBm, C/I[curr 11, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 11 (8 dBm) => 12 (6 dBm): rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, RSSI[curr -60, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 12 (6 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 12, max-ms-pwr-lvl 2, RSSI[curr -60, tgt -75] dBm, C/I[curr 17, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Raising MS power control level 13 (4 dBm) => 11 (8 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -100, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 11 (8 dBm) => 12 (6 dBm): rx-ms-pwr-lvl 11, max-ms-pwr-lvl 2, RSSI[curr -100, tgt -75] dBm, C/I[curr 17, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 12 (6 dBm) => 13 (4 dBm): rx-ms-pwr-lvl 12, max-ms-pwr-lvl 2, RSSI[curr -60, tgt -75] dBm, C/I[curr 14, tgt 14] dB</span><br><span style="color: hsl(120, 100%, 40%);">+(bts=0,trx=0,ts=0,ss=0) Lowering MS power control level 13 (4 dBm) => 14 (2 dBm): rx-ms-pwr-lvl 13, max-ms-pwr-lvl 2, RSSI[curr -60, tgt -75] dBm, C/I[curr 17, tgt 14] dB</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: 7 </div>
<div style="display:none"> Gerrit-Owner: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: Jenkins Builder </div>
<div style="display:none"> Gerrit-Reviewer: fixeria <vyanitskiy@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: laforge <laforge@osmocom.org> </div>
<div style="display:none"> Gerrit-Reviewer: osmith <osmith@sysmocom.de> </div>
<div style="display:none"> Gerrit-Reviewer: pespin <pespin@sysmocom.de> </div>
<div style="display:none"> Gerrit-CC: dexter <pmaier@sysmocom.de> </div>
<div style="display:none"> Gerrit-MessageType: merged </div>