diff options
author | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2021-02-07 20:03:15 +0100 |
---|---|---|
committer | Vadim Yanitskiy <vyanitskiy@sysmocom.de> | 2021-02-07 23:08:57 +0100 |
commit | b1485cd590feaa738b791f7d6835873180d4db02 (patch) | |
tree | 54e37ba654ac1cf68f4edbc0604d8049fa6acfb0 | |
parent | 6b36cce2eac3ee77f930e5c6b3597206d6136084 (diff) |
power_control: implement handling of P_Con_INTERVAL parameter
Change-Id: Ibf9956b2c6d829b38e9fda7d1f29790036219f42
Related: SYS#4918
-rw-r--r-- | include/osmo-bts/gsm_data.h | 5 | ||||
-rw-r--r-- | src/common/power_control.c | 25 | ||||
-rw-r--r-- | src/common/rsl.c | 3 | ||||
-rw-r--r-- | src/common/vty.c | 5 | ||||
-rw-r--r-- | tests/power/bs_power_loop_test.c | 54 | ||||
-rw-r--r-- | tests/power/bs_power_loop_test.err | 31 | ||||
-rw-r--r-- | tests/power/bs_power_loop_test.ok | 64 | ||||
-rw-r--r-- | tests/power/ms_power_loop_test.c | 66 | ||||
-rw-r--r-- | tests/power/ms_power_loop_test.err | 14 | ||||
-rw-r--r-- | tests/power/ms_power_loop_test.ok | 56 |
10 files changed, 320 insertions, 3 deletions
diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h index 8071a28f..05b6cf27 100644 --- a/include/osmo-bts/gsm_data.h +++ b/include/osmo-bts/gsm_data.h @@ -201,6 +201,9 @@ struct gsm_power_ctrl_meas_params { /* MS/BS Power Control parameters */ struct gsm_power_ctrl_params { + /* Minimum interval between power level changes */ + uint8_t ctrl_interval; /* 1 step is 2 SACCH periods */ + /* Power change step size (maximum) */ uint8_t inc_step_size_db; /* increasing direction */ uint8_t red_step_size_db; /* reducing direction */ @@ -231,6 +234,8 @@ struct lchan_power_ctrl_state { const struct gsm_power_ctrl_params *dpc_params; /* Measurement pre-processing state (for dynamic mode) */ struct gsm_power_ctrl_meas_proc_state rxlev_meas_proc; + /* Number of SACCH blocks to skip (for dynamic mode) */ + int skip_block_num; /* Depending on the context (MS or BS power control), fields 'current' and 'max' * reflect either the MS power level (magic numbers), or BS Power reduction level diff --git a/src/common/power_control.c b/src/common/power_control.c index be74a41e..4f5d15e3 100644 --- a/src/common/power_control.c +++ b/src/common/power_control.c @@ -1,7 +1,8 @@ /* MS Power Control Loop L1 */ /* (C) 2014 by Holger Hans Peter Freyther - * Contributions by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2020-2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de> * * All Rights Reserved * @@ -160,6 +161,17 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan, if (params == NULL) return 0; + /* Power control interval: how many blocks do we skip? */ + if (state->skip_block_num-- > 0) + return 0; + + /* Reset the number of SACCH blocks to be skipped: + * ctrl_interval=0 => 0 blocks to skip, + * ctrl_interval=1 => 1 blocks to skip, + * ctrl_interval=2 => 3 blocks to skip, + * so basically ctrl_interval * 2 - 1. */ + state->skip_block_num = params->ctrl_interval * 2 - 1; + ms_dbm = ms_pwr_dbm(band, ms_power_lvl); if (ms_dbm < 0) { LOGPLCHAN(lchan, DLOOP, LOGL_NOTICE, @@ -265,6 +277,17 @@ int lchan_bs_pwr_ctrl(struct gsm_lchan *lchan, lchan->tch.dtx.dl_active ? "enabled" : "disabled", lchan->tch.dtx.dl_active ? "SUB" : "FULL"); + /* Power control interval: how many blocks do we skip? */ + if (state->skip_block_num-- > 0) + return 0; + + /* Reset the number of SACCH blocks to be skipped: + * ctrl_interval=0 => 0 blocks to skip, + * ctrl_interval=1 => 1 blocks to skip, + * ctrl_interval=2 => 3 blocks to skip, + * so basically ctrl_interval * 2 - 1. */ + state->skip_block_num = params->ctrl_interval * 2 - 1; + /* If DTx is active on Downlink, use the '-SUB' */ if (lchan->tch.dtx.dl_active) { rxqual = rxqual_sub; diff --git a/src/common/rsl.c b/src/common/rsl.c index bde53a18..3023ffa1 100644 --- a/src/common/rsl.c +++ b/src/common/rsl.c @@ -763,7 +763,8 @@ static int parse_power_ctrl_params(struct gsm_power_ctrl_params *params, params->rxqual_meas.upper_cmp_p = thresh_comp->p4; params->rxqual_meas.upper_cmp_n = thresh_comp->n4; - /* FIXME: TIMER_PWR_CON_INTERVAL (P_Con_INTERVAL) */ + /* Minimum interval between power level changes (P_Con_INTERVAL) */ + params->ctrl_interval = thresh_comp->pc_interval; /* Power increase / reduce step size: POWER_{INC,RED}_STEP_SIZE */ params->inc_step_size_db = thresh_comp->inc_step_size; diff --git a/src/common/vty.c b/src/common/vty.c index 9dd0c1af..f36c09e5 100644 --- a/src/common/vty.c +++ b/src/common/vty.c @@ -1269,6 +1269,11 @@ static void dump_dpc_meas_params(struct vty *vty, const unsigned int indent, static void dump_dpc_params(struct vty *vty, const unsigned int indent, const struct gsm_power_ctrl_params *cp) { + cfg_out(vty, "Power control interval: %u ms (every %u SACCH block(s))%s", + cp->ctrl_interval ? cp->ctrl_interval * 2 * 480 : 480, + cp->ctrl_interval ? cp->ctrl_interval * 2 : 1, + VTY_NEWLINE); + cfg_out(vty, "Power increase step size: %u%s", cp->inc_step_size_db, VTY_NEWLINE); cfg_out(vty, "Power reduce step size: %u%s", diff --git a/tests/power/bs_power_loop_test.c b/tests/power/bs_power_loop_test.c index 52713243..6f5f2bf1 100644 --- a/tests/power/bs_power_loop_test.c +++ b/tests/power/bs_power_loop_test.c @@ -1,5 +1,5 @@ /* - * (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * (C) 2020-2021 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de> * * All Rights Reserved @@ -56,6 +56,7 @@ enum power_test_step_type { PWR_TEST_ST_IND_MEAS = 0, PWR_TEST_ST_IND_DUMMY, PWR_TEST_ST_SET_STATE, + PWR_TEST_ST_SET_CTRL_INTERVAL, PWR_TEST_ST_SET_STEP_SIZE, PWR_TEST_ST_SET_RXLEV_PARAMS, PWR_TEST_ST_ENABLE_DTXD, @@ -84,6 +85,8 @@ struct power_test_step { uint8_t inc; uint8_t red; } step_size; + /* Power control interval */ + uint8_t ctrl_interval; }; /* Expected Tx power reduction */ uint8_t exp_txred; @@ -159,6 +162,11 @@ static int exec_power_step(struct gsm_lchan *lchan, printf("#%02u %s() <- Dynamic power control is disabled\n", n, __func__); lchan->bs_power_ctrl.dpc_params = NULL; return 0; /* we're done */ + case PWR_TEST_ST_SET_CTRL_INTERVAL: + printf("#%02u %s() <- (Re)set power control interval: %u -> %u\n", + n, __func__, lchan->bs_dpc_params.ctrl_interval, step->ctrl_interval); + lchan->bs_dpc_params.ctrl_interval = step->ctrl_interval; + return 0; /* we're done */ case PWR_TEST_ST_SET_STEP_SIZE: printf("#%02u %s() <- Set step size: inc %u dB, red %u dB\n", n, __func__, step->step_size.inc, step->step_size.red); @@ -411,6 +419,49 @@ static const struct power_test_step TC_inval_dummy[] = { { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, }; +/* Verify handling of optional power control interval (P_Con_INTERVAL). */ +static const struct power_test_step TC_ctrl_interval[] = { + /* Initial state: 0 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 0, .max = 2 * 10 } }, + + /* P_Con_INTERVAL=0 (480 ms): every SACCH block is handled */ + { .type = PWR_TEST_ST_SET_CTRL_INTERVAL, .ctrl_interval = 0 }, + + /* MS indicates high RxLev values (-50 dBm), red step is 2 dB */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 2 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 4 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 6 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 8 }, + + /* MS indicates low RxLev values (-100 dBm), inc step is 4 dB */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 4 }, + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 0 }, + + /* P_Con_INTERVAL=1 (960 ms): 1 out of 2 SACCH blocks is handled */ + { .type = PWR_TEST_ST_SET_CTRL_INTERVAL, .ctrl_interval = 1 }, + + /* MS indicates high RxLev values (-50 dBm), red step is 2 dB */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 2 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 2 }, /* skipped */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 4 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 4 }, /* skipped */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 6 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 6 }, /* skipped */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 8 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 8 }, /* skipped */ + + /* P_Con_INTERVAL=2 (1920 ms): 1 out of 4 SACCH blocks is handled */ + { .type = PWR_TEST_ST_SET_CTRL_INTERVAL, .ctrl_interval = 2 }, + + /* MS indicates low RxLev values (-100 dBm), inc step is 4 dB */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 4 }, + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 4 }, /* skipped */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 4 }, /* skipped */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 4 }, /* skipped */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 0 }, +}; + /* Verify that small deviations from the target do not trigger any changes. */ static const struct power_test_step TC_rxlev_hyst[] = { /* Initial state: 16 dB, up to 20 dB */ @@ -488,6 +539,7 @@ int main(int argc, char **argv) exec_test(TC_dtxd_mode); exec_test(TC_rxqual_ber); exec_test(TC_inval_dummy); + exec_test(TC_ctrl_interval); exec_test(TC_rxlev_hyst); exec_test(TC_rxlev_pf_ewma); diff --git a/tests/power/bs_power_loop_test.err b/tests/power/bs_power_loop_test.err index 7fcfb1e4..c4726b1b 100644 --- a/tests/power/bs_power_loop_test.err +++ b/tests/power/bs_power_loop_test.err @@ -135,6 +135,37 @@ (bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 16 dB (maximum 20 dB, suggested delta 0 dB, RxLev current 30 (-80 dBm), thresholds 30 .. 30) (bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0), DTx is disabled => using FULL (bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 16 dB (maximum 20 dB, suggested delta 0 dB, RxLev current 30 (-80 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 0 -> 2 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 2 -> 4 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 6 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 6 -> 8 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 8 -> 4 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 0 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 0 -> 2 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 2 -> 4 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 6 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 6 -> 8 dB (maximum 20 dB, suggested delta 2 dB, RxLev current 60 (-50 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 8 -> 4 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 4 -> 0 dB (maximum 20 dB, suggested delta -4 dB, RxLev current 10 (-100 dBm), thresholds 30 .. 30) (bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(31), RXQUAL-FULL(0), RXLEV-SUB(31), RXQUAL-SUB(0), DTx is disabled => using FULL (bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 12 -> 13 dB (maximum 16 dB, suggested delta 1 dB, RxLev current 31 (-79 dBm), thresholds 30 .. 30) (bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(28), RXQUAL-FULL(0), RXLEV-SUB(28), RXQUAL-SUB(0), DTx is disabled => using FULL diff --git a/tests/power/bs_power_loop_test.ok b/tests/power/bs_power_loop_test.ok index 4371c9d8..2c123928 100644 --- a/tests/power/bs_power_loop_test.ok +++ b/tests/power/bs_power_loop_test.ok @@ -268,6 +268,70 @@ Starting test case 'TC_inval_dummy' #07 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) Test case verdict: SUCCESS +Starting test case 'TC_ctrl_interval' +#00 exec_power_step() <- State (re)set (current 0 dB, max 20 dB) +#01 exec_power_step() <- (Re)set power control interval: 0 -> 0 +#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 2 (expected 2) +#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#03 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 4 (expected 4) +#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 6 (expected 6) +#05 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#05 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#05 lchan_bs_pwr_ctrl() -> BS power reduction: 6 -> 8 (expected 8) +#06 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#06 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#06 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 4 (expected 4) +#07 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#07 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#07 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 0 (expected 0) +#08 exec_power_step() <- (Re)set power control interval: 0 -> 1 +#09 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#09 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#09 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 2 (expected 2) +#10 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#10 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#10 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 2 (expected 2) +#11 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#11 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#11 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 4 (expected 4) +#12 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#12 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#12 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4) +#13 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#13 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#13 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 6 (expected 6) +#14 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#14 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#14 lchan_bs_pwr_ctrl() -> BS power reduction: 6 -> 6 (expected 6) +#15 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#15 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#15 lchan_bs_pwr_ctrl() -> BS power reduction: 6 -> 8 (expected 8) +#16 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#16 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#16 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 8 (expected 8) +#17 exec_power_step() <- (Re)set power control interval: 1 -> 2 +#18 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#18 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#18 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 4 (expected 4) +#19 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#19 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#19 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4) +#20 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#20 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#20 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4) +#21 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#21 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#21 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 4 (expected 4) +#22 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#22 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#22 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 0 (expected 0) +Test case verdict: SUCCESS + Starting test case 'TC_rxlev_hyst' #00 exec_power_step() <- State (re)set (current 12 dB, max 16 dB) #01 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(31), RXQUAL-FULL(0), RXLEV-SUB(31), RXQUAL-SUB(0) diff --git a/tests/power/ms_power_loop_test.c b/tests/power/ms_power_loop_test.c index eb0e3e9b..c58812b3 100644 --- a/tests/power/ms_power_loop_test.c +++ b/tests/power/ms_power_loop_test.c @@ -248,6 +248,71 @@ static void test_power_hysteresis(void) apply_power_test(lchan, PWR_TEST_RXLEV_TARGET_DBM - 10, 1, 13); } +static void test_power_ctrl_interval(void) +{ + struct gsm_lchan *lchan; + unsigned int i, j; + + init_test(__func__); + lchan = &g_trx->ts[0].lchan[0]; + + lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(GSM_BAND_1800, 26); + OSMO_ASSERT(lchan->ms_power_ctrl.max == 2); + + static const int script[][8][3] = { + { /* P_Con_INTERVAL=0 (480 ms) */ + /* { UL RxLev, expected rc, expected Tx power level } */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 13 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 11 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 9 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 7 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 5 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 3 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 2 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 2 }, + }, + { /* P_Con_INTERVAL=1 (960 ms) */ + /* { UL RxLev, expected rc, expected Tx power level } */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 13 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 13 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 11 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 11 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 9 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 9 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 7 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 7 }, /* skipped */ + }, + { /* P_Con_INTERVAL=2 (1920 ms) */ + /* { UL RxLev, expected rc, expected Tx power level } */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 13 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 13 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 13 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 13 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 1, 11 }, + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 11 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 11 }, /* skipped */ + { PWR_TEST_RXLEV_TARGET_DBM - 15, 0, 11 }, /* skipped */ + }, + }; + + for (i = 0; i < ARRAY_SIZE(script); i++) { + lchan->ms_power_ctrl.current = ms_pwr_ctl_lvl(GSM_BAND_1800, 0); + OSMO_ASSERT(lchan->ms_power_ctrl.current == 15); + + /* Set the corresponding power control interval */ + printf("%s(): power control interval is now %u\n", __func__, i); + lchan->ms_dpc_params.ctrl_interval = i; + + for (j = 0; j < ARRAY_SIZE(script[i]); j++) { + apply_power_test(lchan, script[i][j][0], /* UL RxLev */ + script[i][j][1], /* expected rc */ + script[i][j][2]); /* expected Tx power level */ + } + + printf("\n"); + } +} + int main(int argc, char **argv) { printf("Testing power loop...\n"); @@ -264,6 +329,7 @@ int main(int argc, char **argv) test_power_loop(); test_pf_algo_ewma(); test_power_hysteresis(); + test_power_ctrl_interval(); printf("Power loop test OK\n"); diff --git a/tests/power/ms_power_loop_test.err b/tests/power/ms_power_loop_test.err index 7f8779cb..ae8ad033 100644 --- a/tests/power/ms_power_loop_test.err +++ b/tests/power/ms_power_loop_test.err @@ -35,3 +35,17 @@ (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) (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) (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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) +(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) diff --git a/tests/power/ms_power_loop_test.ok b/tests/power/ms_power_loop_test.ok index 4293d28d..5fea4747 100644 --- a/tests/power/ms_power_loop_test.ok +++ b/tests/power/ms_power_loop_test.ok @@ -88,4 +88,60 @@ lchan_ms_pwr_ctrl(RxLvl=-80 dBm) returns 0 (expected 0) MS current power 15 -> 15 (expected 15) lchan_ms_pwr_ctrl(RxLvl=-85 dBm) returns 1 (expected 1) MS current power 15 -> 13 (expected 13) + +Starting test case 'test_power_ctrl_interval' +test_power_ctrl_interval(): power control interval is now 0 +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 15 -> 13 (expected 13) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 13 -> 11 (expected 11) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 11 -> 9 (expected 9) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 9 -> 7 (expected 7) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 7 -> 5 (expected 5) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 5 -> 3 (expected 3) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 3 -> 2 (expected 2) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 1) + MS current power 2 -> 2 (expected 2) + +test_power_ctrl_interval(): power control interval is now 1 +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 15 -> 13 (expected 13) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 13 -> 13 (expected 13) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 13 -> 11 (expected 11) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 11 -> 11 (expected 11) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 11 -> 9 (expected 9) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 9 -> 9 (expected 9) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 9 -> 7 (expected 7) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 7 -> 7 (expected 7) + +test_power_ctrl_interval(): power control interval is now 2 +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 15 -> 13 (expected 13) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 13 -> 13 (expected 13) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 13 -> 13 (expected 13) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 13 -> 13 (expected 13) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 1 (expected 1) + MS current power 13 -> 11 (expected 11) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 11 -> 11 (expected 11) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 11 -> 11 (expected 11) +lchan_ms_pwr_ctrl(RxLvl=-90 dBm) returns 0 (expected 0) + MS current power 11 -> 11 (expected 11) + Power loop test OK |