aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/common/power_control.c21
-rw-r--r--tests/power/power_test.c52
-rw-r--r--tests/power/power_test.ok19
3 files changed, 83 insertions, 9 deletions
diff --git a/src/common/power_control.c b/src/common/power_control.c
index d08ed5e5..d2a6c1dd 100644
--- a/src/common/power_control.c
+++ b/src/common/power_control.c
@@ -30,6 +30,11 @@
#include <osmo-bts/measurement.h>
#include <osmo-bts/bts_model.h>
#include <osmo-bts/l1sap.h>
+#include <osmo-bts/power_control.h>
+
+/* how many dB do we raise/lower as maximum (1 ms power level = 2 dB) */
+#define MS_RAISE_MAX_DB 4
+#define MS_LOWER_MAX_DB 8
/*! compute the new MS POWER LEVEL communicated to the MS and store it in lchan.
* \param lchan logical channel for which to compute (and in which to store) new power value.
@@ -51,10 +56,6 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
if (lchan->ms_power_ctrl.fixed)
return 0;
- /* How many dBs measured power should be increased (+) or decreased (-)
- to reach expected power. */
- diff = bts->ul_power_target - rxLevel;
-
current_dbm = ms_pwr_dbm(band, ms_power);
if (current_dbm < 0) {
LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE,
@@ -70,6 +71,18 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan,
return 0;
}
+ /* How many dBs measured power should be increased (+) or decreased (-)
+ to reach expected power. */
+ diff = bts->ul_power_target - rxLevel;
+
+ /* don't ever change more than MS_{LOWER,RAISE}_MAX_DBM during one loop
+ iteration, i.e. reduce the speed at which the MS transmit power can
+ change. A higher value means a lower level (and vice versa) */
+ if (diff > MS_RAISE_MAX_DB)
+ diff = MS_RAISE_MAX_DB;
+ else if (diff < -MS_LOWER_MAX_DB)
+ diff = -MS_LOWER_MAX_DB;
+
new_dbm = current_dbm + diff;
/* Make sure new_dbm is never negative. ms_pwr_ctl_lvl() can later on
diff --git a/tests/power/power_test.c b/tests/power/power_test.c
index 30fbb643..9b1a762b 100644
--- a/tests/power/power_test.c
+++ b/tests/power/power_test.c
@@ -58,22 +58,64 @@ static void test_power_loop(void)
lchan->state = LCHAN_S_NONE;
lchan->ms_power_ctrl.current = ms_pwr_ctl_lvl(GSM_BAND_1800, 0);
OSMO_ASSERT(lchan->ms_power_ctrl.current == 15);
+ lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 26);
+ OSMO_ASSERT(lchan->ms_power_ctrl.max == 2);
/* Simply clamping */
apply_power_test(lchan, -60, 0, 15);
/*
* Now 15 dB too little and we should power it up. Could be a
- * power level of 7 or 8 for 15 dBm
+ * power level of 7 or 8 for 15 dBm. However, since we limit peace at
+ * which we change values, expect several steps of MS_RAISE_MAX_DB/2 levels:
*/
+ apply_power_test(lchan, -90, 1, 13);
+ apply_power_test(lchan, -90, 1, 11);
+ apply_power_test(lchan, -90, 1, 9);
apply_power_test(lchan, -90, 1, 7);
-
- /* It should be clamped to level 0 and 30 dBm */
- apply_power_test(lchan, -100, 1, 0);
+ apply_power_test(lchan, -90, 1, 5);
+
+ /* Check good RSSI value keeps it at same power level: */
+ apply_power_test(lchan, bts.ul_power_target, 0, 5);
+
+ apply_power_test(lchan, -90, 1, 3);
+ apply_power_test(lchan, -90, 1, 2); /* .max is pwr lvl 2 */
+ apply_power_test(lchan, -90, 0, 2); /* .max is pwr lvl 2 */
+
+ lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 30);
+ OSMO_ASSERT(lchan->ms_power_ctrl.max == 0);
+ apply_power_test(lchan, -90, 1, 0); /* .max is pwr lvl 0 */
+ apply_power_test(lchan, -90, 0, 0); /* .max is pwr lvl 0 */
+
+ lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 36);
+ OSMO_ASSERT(lchan->ms_power_ctrl.max == 29);
+ apply_power_test(lchan, -90, 1, 30);
+ apply_power_test(lchan, -90, 1, 29);
+ apply_power_test(lchan, -90, 0, 29);
+
+ /* Check good RSSI value keeps it at same power level: */
+ apply_power_test(lchan, bts.ul_power_target, 0, 29);
+
+ /* Now go down, steps are double size in this direction: */
+ apply_power_test(lchan, -45, 1, 1);
+ apply_power_test(lchan, -45, 1, 5);
+ apply_power_test(lchan, -45, 1, 9);
+
+ /* Go down only one level down and up: */
+ apply_power_test(lchan, bts.ul_power_target + 2, 1, 10);
+ apply_power_test(lchan, bts.ul_power_target - 2, 1, 9);
+
+ /* Check if BSC requesting a low max power is applied after loop calculation: */
+ lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 2);
+ OSMO_ASSERT(lchan->ms_power_ctrl.max == 14);
+ apply_power_test(lchan, bts.ul_power_target + 2, 1, 14);
+ /* Set back a more normal max: */
+ lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 30);
+ OSMO_ASSERT(lchan->ms_power_ctrl.max == 0);
/* Fix it and jump down */
lchan->ms_power_ctrl.fixed = true;
- apply_power_test(lchan, -60, 0, 0);
+ apply_power_test(lchan, -60, 0, 14);
/* And leave it again */
lchan->ms_power_ctrl.fixed = false;
diff --git a/tests/power/power_test.ok b/tests/power/power_test.ok
index cf0a38b4..335a3d3b 100644
--- a/tests/power/power_test.ok
+++ b/tests/power/power_test.ok
@@ -1,7 +1,26 @@
Testing power loop...
power control [0]: MS current power 15
+power control [1]: MS current power 13
+power control [1]: MS current power 11
+power control [1]: MS current power 9
power control [1]: MS current power 7
+power control [1]: MS current power 5
+power control [0]: MS current power 5
+power control [1]: MS current power 3
+power control [1]: MS current power 2
+power control [0]: MS current power 2
power control [1]: MS current power 0
power control [0]: MS current power 0
+power control [1]: MS current power 30
+power control [1]: MS current power 29
+power control [0]: MS current power 29
+power control [0]: MS current power 29
+power control [1]: MS current power 1
+power control [1]: MS current power 5
+power control [1]: MS current power 9
+power control [1]: MS current power 10
+power control [1]: MS current power 9
+power control [1]: MS current power 14
+power control [0]: MS current power 14
power control [1]: MS current power 15
Power loop test OK