<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 ¶ms->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 ¶ms->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 ¶ms->ci_amr_fr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ return ¶ms->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 ¶ms->ci_amr_hr_meas;</span><br><span style="color: hsl(120, 100%, 40%);">+ else</span><br><span style="color: hsl(120, 100%, 40%);">+ return ¶ms->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>