diff options
-rw-r--r-- | .gitignore | 1 | ||||
-rw-r--r-- | include/osmo-bts/gsm_data.h | 6 | ||||
-rw-r--r-- | include/osmo-bts/power_control.h | 3 | ||||
-rw-r--r-- | src/common/l1sap.c | 1 | ||||
-rw-r--r-- | src/common/power_control.c | 102 | ||||
-rw-r--r-- | src/common/rsl.c | 52 | ||||
-rw-r--r-- | src/common/scheduler.c | 2 | ||||
-rw-r--r-- | src/common/tx_power.c | 4 | ||||
-rw-r--r-- | src/common/vty.c | 4 | ||||
-rw-r--r-- | tests/power/Makefile.am | 8 | ||||
-rw-r--r-- | tests/power/bs_power_loop_test.c | 398 | ||||
-rw-r--r-- | tests/power/bs_power_loop_test.err | 102 | ||||
-rw-r--r-- | tests/power/bs_power_loop_test.ok | 214 | ||||
-rw-r--r-- | tests/testsuite.at | 7 |
14 files changed, 878 insertions, 26 deletions
@@ -64,6 +64,7 @@ tests/handover/handover_test tests/tx_power/tx_power_test tests/ta_control/ta_control_test tests/power/ms_power_loop_test +tests/power/bs_power_loop_test tests/testsuite tests/testsuite.log diff --git a/include/osmo-bts/gsm_data.h b/include/osmo-bts/gsm_data.h index 04c66298..6af96fe9 100644 --- a/include/osmo-bts/gsm_data.h +++ b/include/osmo-bts/gsm_data.h @@ -316,11 +316,9 @@ struct gsm_lchan { /* RTP header Marker bit to indicate beginning of speech after pause */ bool rtp_tx_marker; - /* MS power control */ + /* MS/BS power control */ struct lchan_power_ctrl_state ms_power_ctrl; - - /* BTS power reduction (in dB) */ - uint8_t bs_power_red; + struct lchan_power_ctrl_state bs_power_ctrl; struct msgb *pending_rel_ind_msg; diff --git a/include/osmo-bts/power_control.h b/include/osmo-bts/power_control.h index cb566a8d..f2e14cfe 100644 --- a/include/osmo-bts/power_control.h +++ b/include/osmo-bts/power_control.h @@ -6,3 +6,6 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan, const uint8_t ms_power_lvl, const int8_t ul_rssi_dbm); + +int lchan_bs_pwr_ctrl(struct gsm_lchan *lchan, + const struct gsm48_hdr *gh); diff --git a/src/common/l1sap.c b/src/common/l1sap.c index 2038fbad..33d10a5a 100644 --- a/src/common/l1sap.c +++ b/src/common/l1sap.c @@ -1546,6 +1546,7 @@ static int l1sap_ph_data_ind(struct gsm_bts_trx *trx, lchan->meas.flags |= LC_UL_M_F_L1_VALID; lchan_ms_pwr_ctrl(lchan, data[0] & 0x1f, data_ind->rssi); + lchan_bs_pwr_ctrl(lchan, (const struct gsm48_hdr *) &data[5]); } else le = &lchan->lapdm_ch.lapdm_dcch; diff --git a/src/common/power_control.c b/src/common/power_control.c index 34414392..4c4e2831 100644 --- a/src/common/power_control.c +++ b/src/common/power_control.c @@ -209,3 +209,105 @@ int lchan_ms_pwr_ctrl(struct gsm_lchan *lchan, return 1; } + + /*! compute the new Downlink attenuation value for the given logical channel. + * \param lchan logical channel for which to compute (and in which to store) new power value. + * \param[in] gh pointer to the beginning of (presumably) a Measurement Report. + */ +int lchan_bs_pwr_ctrl(struct gsm_lchan *lchan, + const struct gsm48_hdr *gh) +{ + struct gsm_bts_trx *trx = lchan->ts->trx; + struct gsm_bts *bts = trx->bts; + uint8_t rxqual_full, rxqual_sub; + uint8_t rxlev_full, rxlev_sub; + uint8_t rxqual, rxlev; + int delta, new; + + const struct bts_power_ctrl_params *params = &bts->dl_power_ctrl; + struct lchan_power_ctrl_state *state = &lchan->bs_power_ctrl; + + /* Check if BS Power Control is enabled */ + if (state->fixed) + return 0; + /* Check if this is a Measurement Report */ + if (gh->proto_discr != GSM48_PDISC_RR) + return 0; + if (gh->msg_type != GSM48_MT_RR_MEAS_REP) + return 0; + + /* Check if the measurement results are valid */ + if ((gh->data[1] & 0x40) == 0x40) { + LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, + "The measurement results are not valid\n"); + return 0; + } + + /* See 3GPP TS 44.018, section 10.5.2.20 */ + rxqual_full = (gh->data[2] >> 4) & 0x7; + rxqual_sub = (gh->data[2] >> 1) & 0x7; + + rxlev_full = gh->data[0] & 0x3f; + rxlev_sub = gh->data[1] & 0x3f; + + LOGPLCHAN(lchan, DLOOP, LOGL_DEBUG, "Rx DL Measurement Report: " + "RXLEV-FULL(%02u), RXQUAL-FULL(%u), " + "RXLEV-SUB(%02u), RXQUAL-SUB(%u), " + "DTx is %s => using %s\n", + rxlev_full, rxqual_full, rxlev_sub, rxqual_sub, + lchan->tch.dtx.dl_active ? "enabled" : "disabled", + lchan->tch.dtx.dl_active ? "SUB" : "FULL"); + + /* If DTx is active on Downlink, use the '-SUB' */ + if (lchan->tch.dtx.dl_active) { + rxqual = rxqual_sub; + rxlev = rxlev_sub; + } else { /* ... otherwise use the '-FULL' */ + rxqual = rxqual_full; + rxlev = rxlev_full; + } + + /* Bit Error Rate > 0 => reduce by 2 */ + if (rxqual > 0) { + LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Reducing Downlink attenuation " + "by half: %u -> %u dB due to RXQUAL %u > 0\n", + state->current, state->current / 2, rxqual); + state->current /= 2; + return 1; + } + + /* Calculate a 'delta' for the current attenuation level */ + delta = calc_delta(params, state, rxlev2dbm(rxlev)); + + /* Basic signal transmission / reception formula: + * + * RxLev = TxPwr - (PathLoss + TxAtt) + * + * Here we want to change RxLev at the MS side, so: + * + * RxLev + Delta = TxPwr - (PathLoss + TxAtt) + Delta + * + * The only parameter we can change here is TxAtt, so: + * + * RxLev + Delta = TxPwr - PathLoss - TxAtt + Delta + * RxLev + Delta = TxPwr - PathLoss - (TxAtt - Delta) + */ + new = state->current - delta; + if (new > state->max) + new = state->max; + if (new < 0) + new = 0; + + if (state->current != new) { + LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Changing Downlink attenuation: " + "%u -> %u dB (maximum %u dB, target %d dBm, delta %d dB)\n", + state->current, new, state->max, params->target, delta); + state->current = new; + return 1; + } else { + LOGPLCHAN(lchan, DLOOP, LOGL_INFO, "Keeping Downlink attenuation " + "at %u dB (maximum %u dB, target %d dBm, delta %d dB)\n", + state->current, state->max, params->target, delta); + return 0; + } +} diff --git a/src/common/rsl.c b/src/common/rsl.c index 8760c242..2ebfb323 100644 --- a/src/common/rsl.c +++ b/src/common/rsl.c @@ -1036,8 +1036,8 @@ static void clear_lchan_for_pdch_activ(struct gsm_lchan *lchan) lchan->tch_mode = 0; memset(&lchan->encr, 0, sizeof(lchan->encr)); memset(&lchan->ho, 0, sizeof(lchan->ho)); - lchan->bs_power_red = 0; memset(&lchan->ms_power_ctrl, 0, sizeof(lchan->ms_power_ctrl)); + memset(&lchan->bs_power_ctrl, 0, sizeof(lchan->bs_power_ctrl)); lchan->rqd_ta = 0; copy_sacch_si_to_lchan(lchan); memset(&lchan->tch, 0, sizeof(lchan->tch)); @@ -1153,11 +1153,16 @@ static int rsl_rx_chan_activ(struct msgb *msg) LOGPLCHAN(lchan, DRSL, LOGL_DEBUG, "rx Channel Activation in state: %s.\n", gsm_lchans_name(lchan->state)); - /* Initialize channel defaults */ + /* Initialize MS Power Control defaults */ lchan->ms_power_ctrl.max = ms_pwr_ctl_lvl(lchan->ts->trx->bts->band, 0); lchan->ms_power_ctrl.current = lchan->ms_power_ctrl.max; lchan->ms_power_ctrl.fixed = true; + /* Initialize BS Power Control defaults */ + lchan->bs_power_ctrl.max = 2 * 15; + lchan->bs_power_ctrl.current = 0; + lchan->bs_power_ctrl.fixed = true; + rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); /* 9.3.3 Activation Type */ @@ -1209,9 +1214,11 @@ static int rsl_rx_chan_activ(struct msgb *msg) return rsl_tx_chan_act_nack(lchan, RSL_ERR_SERV_OPT_UNIMPL); } - lchan->bs_power_red = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER)); + lchan->bs_power_ctrl.max = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER)); + lchan->bs_power_ctrl.current = lchan->bs_power_ctrl.max; + LOGPLCHAN(lchan, DRSL, LOGL_DEBUG, "BS Power attenuation %u dB\n", - lchan->bs_power_red); + lchan->bs_power_ctrl.current); } /* 9.3.13 MS Power */ @@ -1224,7 +1231,6 @@ static int rsl_rx_chan_activ(struct msgb *msg) if (TLVP_PRES_LEN(&tp, RSL_IE_TIMING_ADVANCE, 1)) lchan->rqd_ta = *TLVP_VAL(&tp, RSL_IE_TIMING_ADVANCE); - /* 9.3.32 BS Power Parameters */ /* 9.3.31 MS Power Parameters */ if (TLVP_PRESENT(&tp, RSL_IE_MS_POWER_PARAM)) { /* Spec explicitly states BTS should only perform @@ -1232,6 +1238,14 @@ static int rsl_rx_chan_activ(struct msgb *msg) * Parameters' IE is present! */ lchan->ms_power_ctrl.fixed = false; } + + /* 9.3.32 BS Power Parameters */ + if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) { + /* NOTE: it's safer to start from 0 */ + lchan->bs_power_ctrl.current = 0; + lchan->bs_power_ctrl.fixed = false; + } + /* 9.3.16 Physical Context */ /* 9.3.29 SACCH Information */ @@ -1753,7 +1767,7 @@ static int rsl_rx_bs_pwr_ctrl(struct msgb *msg) struct abis_rsl_dchan_hdr *dch = msgb_l2(msg); struct gsm_lchan *lchan = msg->lchan; struct tlv_parsed tp; - uint8_t old_bs_power_red; + uint8_t old, new; rsl_tlv_parse(&tp, msgb_l3(msg), msgb_l3len(msg)); @@ -1766,18 +1780,24 @@ static int rsl_rx_bs_pwr_ctrl(struct msgb *msg) return rsl_tx_error_report(msg->trx, RSL_ERR_SERV_OPT_UNIMPL, &dch->chan_nr, NULL, msg); } - old_bs_power_red = lchan->bs_power_red; - lchan->bs_power_red = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER)); - - LOGPLCHAN(lchan, DRSL, LOGL_INFO, "BS POWER CONTROL Attenuation %d -> %d dB\n", - old_bs_power_red, lchan->bs_power_red); + new = BS_POWER2DB(*TLVP_VAL(&tp, RSL_IE_BS_POWER)); + old = lchan->bs_power_ctrl.current; /* 9.3.31 MS Power Parameters (O) */ if (TLVP_PRESENT(&tp, RSL_IE_BS_POWER_PARAM)) { - /* Spec explicitly states BTS should perform autonomous - * BS power control loop in BTS if 'BS Power Parameters' - * IE is present! WE don't support that. */ - return rsl_tx_error_report(msg->trx, RSL_ERR_OPT_IE_ERROR, &dch->chan_nr, NULL, msg); + /* NOTE: it's safer to start from 0 */ + lchan->bs_power_ctrl.current = 0; + lchan->bs_power_ctrl.max = new; + lchan->bs_power_ctrl.fixed = false; + } else { + lchan->bs_power_ctrl.current = new; + lchan->bs_power_ctrl.fixed = true; + } + + if (lchan->bs_power_ctrl.current != old) { + LOGPLCHAN(lchan, DRSL, LOGL_INFO, "BS POWER CONTROL: " + "attenuation change %u -> %u dB\n", + old, lchan->bs_power_ctrl.current); } return 0; @@ -2975,7 +2995,7 @@ int rsl_tx_meas_res(struct gsm_lchan *lchan, uint8_t *l3, int l3_len, const stru msgb_tlv_put(msg, RSL_IE_UPLINK_MEAS, ie_len, meas_res); lchan->meas.flags &= ~LC_UL_M_F_RES_VALID; } - msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power_red / 2); + msgb_tv_put(msg, RSL_IE_BS_POWER, lchan->bs_power_ctrl.current / 2); if (lchan->meas.flags & LC_UL_M_F_L1_VALID) { msgb_tv_fixed_put(msg, RSL_IE_L1_INFO, 2, lchan->meas.l1_info); lchan->meas.flags &= ~LC_UL_M_F_L1_VALID; diff --git a/src/common/scheduler.c b/src/common/scheduler.c index 84918e31..3d780fdd 100644 --- a/src/common/scheduler.c +++ b/src/common/scheduler.c @@ -1237,7 +1237,7 @@ void _sched_dl_burst(struct l1sched_trx *l1t, struct trx_dl_burst_req *br) /* BS Power reduction (in dB) per logical channel */ if (l1cs->lchan != NULL) - br->att = l1cs->lchan->bs_power_red; + br->att = l1cs->lchan->bs_power_ctrl.current; /* encrypt */ if (br->burst_len && l1cs->dl_encr_algo) { diff --git a/src/common/tx_power.c b/src/common/tx_power.c index 0741429f..348aba5c 100644 --- a/src/common/tx_power.c +++ b/src/common/tx_power.c @@ -68,7 +68,7 @@ int get_p_target_mdBm(const struct gsm_bts_trx *trx, uint8_t bs_power_red) } int get_p_target_mdBm_lchan(const struct gsm_lchan *lchan) { - return get_p_target_mdBm(lchan->ts->trx, lchan->bs_power_red); + return get_p_target_mdBm(lchan->ts->trx, lchan->bs_power_ctrl.current); } /* calculate the actual total output power required, taking into account the @@ -134,7 +134,7 @@ int get_p_trxout_target_mdBm(const struct gsm_bts_trx *trx, uint8_t bs_power_red } int get_p_trxout_target_mdBm_lchan(const struct gsm_lchan *lchan) { - return get_p_trxout_target_mdBm(lchan->ts->trx, lchan->bs_power_red); + return get_p_trxout_target_mdBm(lchan->ts->trx, lchan->bs_power_ctrl.current); } diff --git a/src/common/vty.c b/src/common/vty.c index f32f6cdf..5d21e584 100644 --- a/src/common/vty.c +++ b/src/common/vty.c @@ -1335,10 +1335,13 @@ static void lchan_dump_full_vty(struct vty *vty, const struct gsm_lchan *lchan) lchan->state == LCHAN_S_BROKEN ? " Error reason: " : "", lchan->state == LCHAN_S_BROKEN ? lchan->broken_reason : "", VTY_NEWLINE); +#if 0 + /* TODO: print more info about MS/BS Power Control */ vty_out(vty, " BS Power: %d dBm, MS Power: %u dBm%s", lchan->ts->trx->nominal_power - (lchan->ts->trx->max_power_red + lchan->bs_power_red), ms_pwr_dbm(lchan->ts->trx->bts->band, lchan->ms_power_ctrl.max), VTY_NEWLINE); +#endif vty_out(vty, " Channel Mode / Codec: %s%s", gsm48_chan_mode_name(lchan->tch_mode), VTY_NEWLINE); @@ -1380,7 +1383,6 @@ static void lchan_dump_full_vty(struct vty *vty, const struct gsm_lchan *lchan) if (lchan->loopback) vty_out(vty, " RTP/PDCH Loopback Enabled%s", VTY_NEWLINE); vty_out(vty, " Radio Link Failure Counter 'S': %d%s", lchan->s, VTY_NEWLINE); - /* TODO: MS Power Control */ } static void lchan_dump_short_vty(struct vty *vty, const struct gsm_lchan *lchan) diff --git a/tests/power/Makefile.am b/tests/power/Makefile.am index d6e1a6be..e428178a 100644 --- a/tests/power/Makefile.am +++ b/tests/power/Makefile.am @@ -2,8 +2,12 @@ AM_CPPFLAGS = $(all_includes) -I$(top_srcdir)/include AM_CFLAGS = -Wall $(LIBOSMOCORE_CFLAGS) $(LIBOSMOCODEC_CFLAGS) $(LIBOSMOGSM_CFLAGS) $(LIBOSMOVTY_CFLAGS) $(LIBOSMOTRAU_CFLAGS) LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOCODEC_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_LIBS) -noinst_PROGRAMS = ms_power_loop_test -EXTRA_DIST = ms_power_loop_test.ok ms_power_loop_test.err +noinst_PROGRAMS = ms_power_loop_test bs_power_loop_test +EXTRA_DIST = ms_power_loop_test.ok ms_power_loop_test.err \ + bs_power_loop_test.ok bs_power_loop_test.err ms_power_loop_test_SOURCES = ms_power_loop_test.c $(srcdir)/../stubs.c ms_power_loop_test_LDADD = $(top_builddir)/src/common/libbts.a $(LIBOSMOABIS_LIBS) $(LDADD) + +bs_power_loop_test_SOURCES = bs_power_loop_test.c $(srcdir)/../stubs.c +bs_power_loop_test_LDADD = $(top_builddir)/src/common/libbts.a $(LIBOSMOABIS_LIBS) $(LDADD) diff --git a/tests/power/bs_power_loop_test.c b/tests/power/bs_power_loop_test.c new file mode 100644 index 00000000..bc6b8154 --- /dev/null +++ b/tests/power/bs_power_loop_test.c @@ -0,0 +1,398 @@ +/* + * (C) 2020 by sysmocom - s.m.f.c. GmbH <info@sysmocom.de> + * Author: Vadim Yanitskiy <vyanitskiy@sysmocom.de> + * + * All Rights Reserved + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU Affero General Public License as published by + * the Free Software Foundation; either version 3 of the License, or + * (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU Affero General Public License + * along with this program. If not, see <http://www.gnu.org/licenses/>. + */ + +#include <stdio.h> + +#include <osmocom/core/utils.h> +#include <osmocom/core/talloc.h> +#include <osmocom/core/application.h> + +#include <osmo-bts/bts.h> +#include <osmo-bts/l1sap.h> +#include <osmo-bts/logging.h> +#include <osmo-bts/power_control.h> + +#define PWR_TEST_RXLEV_TARGET 30 + +#define DL_MEAS_FULL(rxqual, rxlev) \ + .rxqual_full = rxqual, \ + .rxlev_full = rxlev + +#define DL_MEAS_SUB(rxqual, rxlev) \ + .rxqual_sub = rxqual, \ + .rxlev_sub = rxlev + +#define DL_MEAS_FULL_SUB(rxqual, rxlev) \ + { DL_MEAS_FULL(rxqual, rxlev), \ + DL_MEAS_SUB(rxqual, rxlev) } + +#define DL_MEAS_FULL_SUB_INV(rxqual, rxlev) \ + { DL_MEAS_FULL(rxqual, rxlev), \ + DL_MEAS_SUB(rxqual, rxlev), \ + .invalid = true } + +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_PARAMS, + PWR_TEST_ST_ENABLE_DTXD, +}; + +struct power_test_step { + /* Instruction to be performed */ + enum power_test_step_type type; + /* Instruction parameters */ + union { + /* Power Control state */ + struct lchan_power_ctrl_state state; + /* Power Control parameters */ + struct bts_power_ctrl_params params; + /* Indicated DL measurements */ + struct { + uint8_t rxqual_full; + uint8_t rxqual_sub; + uint8_t rxlev_full; + uint8_t rxlev_sub; + bool invalid; + } meas; + }; + /* Expected Tx power reduction */ + uint8_t exp_txred; +}; + +static struct gsm_bts *g_bts = NULL; +static struct gsm_bts_trx *g_trx = NULL; + +static void init_test(const char *name) +{ + if (g_trx != NULL) + talloc_free(g_trx); + if (g_bts != NULL) + talloc_free(g_bts); + + g_bts = talloc_zero(tall_bts_ctx, struct gsm_bts); + OSMO_ASSERT(g_bts != NULL); + + INIT_LLIST_HEAD(&g_bts->trx_list); + g_trx = gsm_bts_trx_alloc(g_bts); + OSMO_ASSERT(g_trx != NULL); + + g_bts->dl_power_ctrl.target = rxlev2dbm(PWR_TEST_RXLEV_TARGET); + g_bts->band = GSM_BAND_900; + g_bts->c0 = g_trx; + + printf("\nStarting test case '%s'\n", name); +} + +static void enc_meas_rep(struct gsm48_hdr *gh, + const unsigned int n, + const struct power_test_step *step) +{ + struct gsm48_meas_res *mr = (struct gsm48_meas_res *) gh->data; + + gh->proto_discr = GSM48_PDISC_RR; + gh->msg_type = GSM48_MT_RR_MEAS_REP; + + *mr = (struct gsm48_meas_res) { + .rxlev_full = step->meas.rxlev_full, + .rxlev_sub = step->meas.rxlev_sub, + .rxqual_full = step->meas.rxqual_full, + .rxqual_sub = step->meas.rxqual_sub, + /* NOTE: inversed logic (1 means invalid) */ + .meas_valid = step->meas.invalid, + }; + + printf("#%02u %s() -> Measurement Results (%svalid): " + "RXLEV-FULL(%02u), RXQUAL-FULL(%u), " + "RXLEV-SUB(%02u), RXQUAL-SUB(%u)\n", + n, __func__, step->meas.invalid ? "in" : "", + mr->rxlev_full, mr->rxqual_full, + mr->rxlev_sub, mr->rxqual_sub); +} + +static int exec_power_step(struct gsm_lchan *lchan, + const unsigned int n, + const struct power_test_step *step) +{ + struct gsm48_hdr *gh; + uint8_t old, new; + uint8_t buf[18]; + + gh = (struct gsm48_hdr *) buf; + + switch (step->type) { + case PWR_TEST_ST_SET_STATE: + printf("#%02u %s() <- State (re)set (current %u dB, max %u dB)\n", + n, __func__, step->state.current, step->state.max); + lchan->bs_power_ctrl = step->state; + return 0; /* we're done */ + case PWR_TEST_ST_SET_PARAMS: + printf("#%02u %s() <- Param (re)set (target %d dBm, hysteresis %u dB, " + "filtering is %sabled)\n", + n, __func__, step->params.target, step->params.hysteresis, + step->params.pf_algo != BTS_PF_ALGO_NONE ? "en" : "dis"); + g_bts->dl_power_ctrl = step->params; + return 0; /* we're done */ + case PWR_TEST_ST_ENABLE_DTXD: + printf("#%02u %s() <- Enable DTXd\n", n, __func__); + lchan->tch.dtx.dl_active = true; + return 0; /* we're done */ + case PWR_TEST_ST_IND_DUMMY: + printf("#%02u %s() <- Dummy block\n", n, __func__); + memset(buf, 0x2b, sizeof(buf)); + break; + case PWR_TEST_ST_IND_MEAS: + enc_meas_rep(gh, n, step); + break; + } + + printf("#%02u lchan_bs_pwr_ctrl() <- UL SACCH: %s\n", + n, osmo_hexdump(buf, sizeof(buf))); + + old = lchan->bs_power_ctrl.current; + lchan_bs_pwr_ctrl(lchan, gh); + new = lchan->bs_power_ctrl.current; + + printf("#%02u lchan_bs_pwr_ctrl() -> BS power reduction: " + "%u -> %u (expected %u)\n", + n, old, new, step->exp_txred); + + return new != step->exp_txred; +} + +static void exec_power_test(const struct power_test_step *steps, + unsigned int num_steps, + const char *name) +{ + unsigned int n; + int rc = 0; + + init_test(name); + + struct gsm_lchan *lchan = &g_trx->ts[0].lchan[0]; + for (n = 0; n < num_steps; n++) + rc |= exec_power_step(lchan, n, &steps[n]); + + printf("Test case verdict: %s\n", rc ? "FAIL" : "SUCCESS"); +} + +/* Verify that the power remains constant in fixed mode. */ +static const struct power_test_step TC_fixed_mode[] = { + /* Initial state: 10 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 10, .max = 2 * 10, .fixed = true } }, + + /* MS indicates random RxQual/RxLev values, which must be ignored */ + { .meas = DL_MEAS_FULL_SUB(0, 63), .exp_txred = 10 }, + { .meas = DL_MEAS_FULL_SUB(7, 0), .exp_txred = 10 }, + { .meas = DL_MEAS_FULL_SUB(0, 30), .exp_txred = 10 }, + { .meas = DL_MEAS_FULL_SUB(1, 30), .exp_txred = 10 }, + { .meas = DL_MEAS_FULL_SUB(1, 50), .exp_txred = 10 }, +}; + +/* Verify that the power remains constant if RxLev equals the target level. */ +static const struct power_test_step TC_rxlev_target[] = { + /* Initial state: 0 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 0, .max = 2 * 10 } }, + + /* MS indicates RxLev values that match the target level */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET) }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET) }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET) }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET) }, +}; + +/* Verify that the power is gradually reduced/increased to the + * minimum/maximum if the MS reports high/low RxLev values. */ +static const struct power_test_step TC_rxlev_max_min[] = { + /* Initial state: 0 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 0, .max = 2 * 10 } }, + + /* MS indicates high RxLev values (-50 dBm) */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 4 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 8 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 12 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 16 }, + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 20 }, /* max */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 20 }, /* max */ + { .meas = DL_MEAS_FULL_SUB(0, 60), .exp_txred = 20 }, /* max */ + + /* MS indicates low RxLev values (-100 dBm) */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 12 }, + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 4 }, + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 0 }, /* min */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 0 }, /* min */ + { .meas = DL_MEAS_FULL_SUB(0, 10), .exp_txred = 0 }, /* min */ +}; + +/* Verify that the logic picks the 'SUB' values in DTXd mode. */ +static const struct power_test_step TC_dtxd_mode[] = { + /* Initial state: 0 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 0, .max = 2 * 10 } }, + + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET) }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET) }, + + { .type = PWR_TEST_ST_ENABLE_DTXD }, /* DTXd mode */ + + /* MS indicates target RxLev values as 'SUB', and random as 'FULL' */ + { .meas = { DL_MEAS_FULL(7, 0), DL_MEAS_SUB(0, PWR_TEST_RXLEV_TARGET) } }, + { .meas = { DL_MEAS_FULL(3, 30), DL_MEAS_SUB(0, PWR_TEST_RXLEV_TARGET) } }, + { .meas = { DL_MEAS_FULL(0, 63), DL_MEAS_SUB(0, PWR_TEST_RXLEV_TARGET) } }, +}; + +/* Verify that RxQual > 0 reduces the current attenuation value. */ +static const struct power_test_step TC_rxqual_ber[] = { + /* Initial state: 16 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 16, .max = 2 * 10 } }, + + /* MS indicates target RxLev, and no bit errors */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, + + /* MS indicates target RxLev, but RxQual values > 0 */ + { .meas = DL_MEAS_FULL_SUB(7, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 2 }, + { .meas = DL_MEAS_FULL_SUB(4, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 4 }, + { .meas = DL_MEAS_FULL_SUB(1, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 8 }, + + /* MS indicates target RxLev, and no bit errors anymore */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 8 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 8 }, + + /* Reset state: 16 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 16, .max = 2 * 10 } }, + + /* MS indicates target RxLev, but RxQual values > 0 again */ + { .meas = DL_MEAS_FULL_SUB(7, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 2 }, + { .meas = DL_MEAS_FULL_SUB(7, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 4 }, + { .meas = DL_MEAS_FULL_SUB(7, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 8 }, + { .meas = DL_MEAS_FULL_SUB(7, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 16 }, + { .meas = DL_MEAS_FULL_SUB(7, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 / 32 }, +}; + +/* Verify that invalid and dummy SACCH blocks are ignored. */ +static const struct power_test_step TC_inval_dummy[] = { + /* Initial state: 16 dB, up to 20 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 16, .max = 2 * 10 } }, + + /* MS sends invalid measurement results which must be ignored */ + { .meas = DL_MEAS_FULL_SUB_INV(7, 63), .exp_txred = 16 }, + { .meas = DL_MEAS_FULL_SUB_INV(0, 0), .exp_txred = 16 }, + + /* Let's say SMS (SAPI=3) blocks substitute some of the reports */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, + { .type = PWR_TEST_ST_IND_DUMMY, /* not a report */ .exp_txred = 16 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, + { .type = PWR_TEST_ST_IND_DUMMY, /* not a report */ .exp_txred = 16 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, +}; + +/* 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 */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 12, .max = 2 * 8 } }, + + /* Hysteresis is not enabled, so small deviations trigger oscillations */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET + 1), .exp_txred = 13 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET - 2), .exp_txred = 11 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET + 3), .exp_txred = 14 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET - 2), .exp_txred = 12 }, + + /* Enable hysteresis */ + { .type = PWR_TEST_ST_SET_PARAMS, + .params = { + .target = -110 + PWR_TEST_RXLEV_TARGET, + .hysteresis = 3, + } + }, + + /* Hysteresis is enabled, so small deviations do not trigger any changes */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET + 1), .exp_txred = 12 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET - 2), .exp_txred = 12 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET + 3), .exp_txred = 12 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET - 2), .exp_txred = 12 }, +}; + +/* Verify EWMA based power filtering. */ +static const struct power_test_step TC_rxlev_pf_ewma[] = { + /* Initial state: 20 dB, up to 30 dB */ + { .type = PWR_TEST_ST_SET_STATE, + .state = { .current = 16, .max = 2 * 15 } }, + + /* Enable EWMA based power filtering */ + { .type = PWR_TEST_ST_SET_PARAMS, + .params = { + .target = -110 + PWR_TEST_RXLEV_TARGET, /* RxLev 30 */ + .pf_algo = BTS_PF_ALGO_EWMA, + .pf.ewma.alpha = 50, + } + }, + + /* MS indicates target RxLev, power level remains constant */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET), .exp_txred = 16 }, + + /* Avg[t] = (0.5 * 26) + (0.5 * 30) = 28, so delta is 2 */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET - 4), .exp_txred = 14 }, + /* Avg[t] = (0.5 * 26) + (0.5 * 28) = 27, so delta is 3 */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET - 4), .exp_txred = 11 }, + /* Avg[t] = (0.5 * 35) + (0.5 * 27) = 31, so delta is 1 */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET + 5), .exp_txred = 12 }, + /* Avg[t] = (0.5 * 35) + (0.5 * 31) = 33, so delta is 3 */ + { .meas = DL_MEAS_FULL_SUB(0, PWR_TEST_RXLEV_TARGET + 5), .exp_txred = 15 }, +}; + +int main(int argc, char **argv) +{ + printf("Testing BS Power loop...\n"); + + tall_bts_ctx = talloc_named_const(NULL, 1, "OsmoBTS context"); + msgb_talloc_ctx_init(tall_bts_ctx, 0); + + osmo_init_logging2(tall_bts_ctx, &bts_log_info); + osmo_stderr_target->categories[DLOOP].loglevel = LOGL_DEBUG; + osmo_stderr_target->categories[DL1C].loglevel = LOGL_DEBUG; + log_set_print_filename(osmo_stderr_target, 0); + log_set_use_color(osmo_stderr_target, 0); + +#define exec_test(test) \ + exec_power_test(test, ARRAY_SIZE(test), #test) + + exec_test(TC_fixed_mode); + exec_test(TC_rxlev_target); + exec_test(TC_rxlev_max_min); /* FIXME */ + + exec_test(TC_dtxd_mode); + exec_test(TC_rxqual_ber); + exec_test(TC_inval_dummy); + + exec_test(TC_rxlev_hyst); + exec_test(TC_rxlev_pf_ewma); + + return 0; +} diff --git a/tests/power/bs_power_loop_test.err b/tests/power/bs_power_loop_test.err new file mode 100644 index 00000000..44d996e5 --- /dev/null +++ b/tests/power/bs_power_loop_test.err @@ -0,0 +1,102 @@ +(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 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(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 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(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 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(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 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(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 -> 8 dB (maximum 20 dB, target -80 dBm, delta -8 dB) +(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: 8 -> 16 dB (maximum 20 dB, target -80 dBm, delta -8 dB) +(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: 16 -> 20 dB (maximum 20 dB, target -80 dBm, delta -8 dB) +(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) Keeping Downlink attenuation at 20 dB (maximum 20 dB, target -80 dBm, delta -8 dB) +(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) Keeping Downlink attenuation at 20 dB (maximum 20 dB, target -80 dBm, delta -8 dB) +(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) Keeping Downlink attenuation at 20 dB (maximum 20 dB, target -80 dBm, delta -8 dB) +(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) Keeping Downlink attenuation at 20 dB (maximum 20 dB, target -80 dBm, delta -8 dB) +(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: 20 -> 16 dB (maximum 20 dB, target -80 dBm, delta 4 dB) +(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: 16 -> 12 dB (maximum 20 dB, target -80 dBm, delta 4 dB) +(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: 12 -> 8 dB (maximum 20 dB, target -80 dBm, delta 4 dB) +(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, target -80 dBm, delta 4 dB) +(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, target -80 dBm, delta 4 dB) +(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 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(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 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(00), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(0), DTx is enabled => using SUB +(bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(3), RXLEV-SUB(30), RXQUAL-SUB(0), DTx is enabled => using SUB +(bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(63), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0), DTx is enabled => using SUB +(bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 0 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(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, target -80 dBm, delta 0 dB) +(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, target -80 dBm, delta 0 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 16 -> 8 dB due to RXQUAL 7 > 0 +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(4), RXLEV-SUB(30), RXQUAL-SUB(4), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 8 -> 4 dB due to RXQUAL 4 > 0 +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(1), RXLEV-SUB(30), RXQUAL-SUB(1), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 4 -> 2 dB due to RXQUAL 1 > 0 +(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 2 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(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 2 dB (maximum 20 dB, target -80 dBm, delta 0 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 16 -> 8 dB due to RXQUAL 7 > 0 +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 8 -> 4 dB due to RXQUAL 7 > 0 +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 4 -> 2 dB due to RXQUAL 7 > 0 +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 2 -> 1 dB due to RXQUAL 7 > 0 +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Reducing Downlink attenuation by half: 1 -> 0 dB due to RXQUAL 7 > 0 +(bts=0,trx=0,ts=0,ss=0) The measurement results are not valid +(bts=0,trx=0,ts=0,ss=0) The measurement results are not valid +(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, target -80 dBm, delta 0 dB) +(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, target -80 dBm, delta 0 dB) +(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, target -80 dBm, delta 0 dB) +(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, target -80 dBm, delta -1 dB) +(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 +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 13 -> 11 dB (maximum 16 dB, target -80 dBm, delta 2 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(33), RXQUAL-FULL(0), RXLEV-SUB(33), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 11 -> 14 dB (maximum 16 dB, target -80 dBm, delta -3 dB) +(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 +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 14 -> 12 dB (maximum 16 dB, target -80 dBm, delta 2 dB) +(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) Keeping Downlink attenuation at 12 dB (maximum 16 dB, target -80 dBm, delta 0 dB) +(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 +(bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 12 dB (maximum 16 dB, target -80 dBm, delta 0 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(33), RXQUAL-FULL(0), RXLEV-SUB(33), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 12 dB (maximum 16 dB, target -80 dBm, delta 0 dB) +(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 +(bts=0,trx=0,ts=0,ss=0) Keeping Downlink attenuation at 12 dB (maximum 16 dB, target -80 dBm, delta 0 dB) +(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 30 dB, target -80 dBm, delta 0 dB) +(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 30 dB, target -80 dBm, delta 0 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(26), RXQUAL-FULL(0), RXLEV-SUB(26), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 16 -> 14 dB (maximum 30 dB, target -80 dBm, delta 2 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(26), RXQUAL-FULL(0), RXLEV-SUB(26), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 14 -> 11 dB (maximum 30 dB, target -80 dBm, delta 3 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(35), RXQUAL-FULL(0), RXLEV-SUB(35), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 11 -> 12 dB (maximum 30 dB, target -80 dBm, delta -1 dB) +(bts=0,trx=0,ts=0,ss=0) Rx DL Measurement Report: RXLEV-FULL(35), RXQUAL-FULL(0), RXLEV-SUB(35), RXQUAL-SUB(0), DTx is disabled => using FULL +(bts=0,trx=0,ts=0,ss=0) Changing Downlink attenuation: 12 -> 15 dB (maximum 30 dB, target -80 dBm, delta -3 dB) diff --git a/tests/power/bs_power_loop_test.ok b/tests/power/bs_power_loop_test.ok new file mode 100644 index 00000000..fe2eb78d --- /dev/null +++ b/tests/power/bs_power_loop_test.ok @@ -0,0 +1,214 @@ +Testing BS Power loop... + +Starting test case 'TC_fixed_mode' +#00 exec_power_step() <- State (re)set (current 10 dB, max 20 dB) +#01 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(63), RXQUAL-FULL(0), RXLEV-SUB(63), RXQUAL-SUB(0) +#01 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3f 3f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#01 lchan_bs_pwr_ctrl() -> BS power reduction: 10 -> 10 (expected 10) +#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(00), RXQUAL-FULL(7), RXLEV-SUB(00), RXQUAL-SUB(7) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 00 00 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 10 -> 10 (expected 10) +#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#03 lchan_bs_pwr_ctrl() -> BS power reduction: 10 -> 10 (expected 10) +#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(1), RXLEV-SUB(30), RXQUAL-SUB(1) +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 12 00 00 00 00 00 00 00 00 00 00 00 00 00 +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 10 -> 10 (expected 10) +#05 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(50), RXQUAL-FULL(1), RXLEV-SUB(50), RXQUAL-SUB(1) +#05 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 32 32 12 00 00 00 00 00 00 00 00 00 00 00 00 00 +#05 lchan_bs_pwr_ctrl() -> BS power reduction: 10 -> 10 (expected 10) +Test case verdict: SUCCESS + +Starting test case 'TC_rxlev_target' +#00 exec_power_step() <- State (re)set (current 0 dB, max 20 dB) +#01 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#01 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#01 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#03 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +Test case verdict: SUCCESS + +Starting test case 'TC_rxlev_max_min' +#00 exec_power_step() <- State (re)set (current 0 dB, max 20 dB) +#01 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#01 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#01 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 8 (expected 4) +#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: 8 -> 16 (expected 8) +#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: 16 -> 20 (expected 12) +#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: 20 -> 20 (expected 16) +#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: 20 -> 20 (expected 20) +#06 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#06 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#06 lchan_bs_pwr_ctrl() -> BS power reduction: 20 -> 20 (expected 20) +#07 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(60), RXQUAL-FULL(0), RXLEV-SUB(60), RXQUAL-SUB(0) +#07 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3c 3c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#07 lchan_bs_pwr_ctrl() -> BS power reduction: 20 -> 20 (expected 20) +#08 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#08 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#08 lchan_bs_pwr_ctrl() -> BS power reduction: 20 -> 16 (expected 12) +#09 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#09 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#09 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 12 (expected 4) +#10 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#10 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#10 lchan_bs_pwr_ctrl() -> BS power reduction: 12 -> 8 (expected 0) +#11 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#11 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#11 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 4 (expected 0) +#12 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(10), RXQUAL-FULL(0), RXLEV-SUB(10), RXQUAL-SUB(0) +#12 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 0a 0a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#12 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 0 (expected 0) +Test case verdict: FAIL + +Starting test case 'TC_dtxd_mode' +#00 exec_power_step() <- State (re)set (current 0 dB, max 20 dB) +#01 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#01 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#01 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +#03 exec_power_step() <- Enable DTXd +#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(00), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(0) +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 00 1e 70 00 00 00 00 00 00 00 00 00 00 00 00 00 +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +#05 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(3), RXLEV-SUB(30), RXQUAL-SUB(0) +#05 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 30 00 00 00 00 00 00 00 00 00 00 00 00 00 +#05 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +#06 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(63), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#06 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3f 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#06 lchan_bs_pwr_ctrl() -> BS power reduction: 0 -> 0 (expected 0) +Test case verdict: SUCCESS + +Starting test case 'TC_rxqual_ber' +#00 exec_power_step() <- State (re)set (current 16 dB, max 20 dB) +#01 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#01 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#01 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7) +#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#03 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 8 (expected 8) +#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(4), RXLEV-SUB(30), RXQUAL-SUB(4) +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 48 00 00 00 00 00 00 00 00 00 00 00 00 00 +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 4 (expected 4) +#05 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(1), RXLEV-SUB(30), RXQUAL-SUB(1) +#05 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 12 00 00 00 00 00 00 00 00 00 00 00 00 00 +#05 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 2 (expected 2) +#06 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#06 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#06 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 2 (expected 2) +#07 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#07 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#07 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 2 (expected 2) +#08 exec_power_step() <- State (re)set (current 16 dB, max 20 dB) +#09 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7) +#09 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#09 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 8 (expected 8) +#10 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7) +#10 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#10 lchan_bs_pwr_ctrl() -> BS power reduction: 8 -> 4 (expected 4) +#11 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7) +#11 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#11 lchan_bs_pwr_ctrl() -> BS power reduction: 4 -> 2 (expected 2) +#12 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7) +#12 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#12 lchan_bs_pwr_ctrl() -> BS power reduction: 2 -> 1 (expected 1) +#13 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(7), RXLEV-SUB(30), RXQUAL-SUB(7) +#13 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#13 lchan_bs_pwr_ctrl() -> BS power reduction: 1 -> 0 (expected 0) +Test case verdict: SUCCESS + +Starting test case 'TC_inval_dummy' +#00 exec_power_step() <- State (re)set (current 16 dB, max 20 dB) +#01 enc_meas_rep() -> Measurement Results (invalid): RXLEV-FULL(63), RXQUAL-FULL(7), RXLEV-SUB(63), RXQUAL-SUB(7) +#01 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 3f 7f 7e 00 00 00 00 00 00 00 00 00 00 00 00 00 +#01 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#02 enc_meas_rep() -> Measurement Results (invalid): RXLEV-FULL(00), RXQUAL-FULL(0), RXLEV-SUB(00), RXQUAL-SUB(0) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 00 40 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#03 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#04 exec_power_step() <- Dummy block +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#05 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#05 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#05 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#06 exec_power_step() <- Dummy block +#06 lchan_bs_pwr_ctrl() <- UL SACCH: 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b 2b +#06 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#07 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#07 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#07 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +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) +#01 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1f 1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#01 lchan_bs_pwr_ctrl() -> BS power reduction: 12 -> 13 (expected 13) +#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(28), RXQUAL-FULL(0), RXLEV-SUB(28), RXQUAL-SUB(0) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1c 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 13 -> 11 (expected 11) +#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(33), RXQUAL-FULL(0), RXLEV-SUB(33), RXQUAL-SUB(0) +#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 21 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#03 lchan_bs_pwr_ctrl() -> BS power reduction: 11 -> 14 (expected 14) +#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(28), RXQUAL-FULL(0), RXLEV-SUB(28), RXQUAL-SUB(0) +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1c 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 14 -> 12 (expected 12) +#05 exec_power_step() <- Param (re)set (target -80 dBm, hysteresis 3 dB, filtering is disabled) +#06 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(31), RXQUAL-FULL(0), RXLEV-SUB(31), RXQUAL-SUB(0) +#06 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1f 1f 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#06 lchan_bs_pwr_ctrl() -> BS power reduction: 12 -> 12 (expected 12) +#07 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(28), RXQUAL-FULL(0), RXLEV-SUB(28), RXQUAL-SUB(0) +#07 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1c 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#07 lchan_bs_pwr_ctrl() -> BS power reduction: 12 -> 12 (expected 12) +#08 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(33), RXQUAL-FULL(0), RXLEV-SUB(33), RXQUAL-SUB(0) +#08 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 21 21 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#08 lchan_bs_pwr_ctrl() -> BS power reduction: 12 -> 12 (expected 12) +#09 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(28), RXQUAL-FULL(0), RXLEV-SUB(28), RXQUAL-SUB(0) +#09 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1c 1c 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#09 lchan_bs_pwr_ctrl() -> BS power reduction: 12 -> 12 (expected 12) +Test case verdict: SUCCESS + +Starting test case 'TC_rxlev_pf_ewma' +#00 exec_power_step() <- State (re)set (current 16 dB, max 30 dB) +#01 exec_power_step() <- Param (re)set (target -80 dBm, hysteresis 0 dB, filtering is enabled) +#02 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#02 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#02 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#03 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(30), RXQUAL-FULL(0), RXLEV-SUB(30), RXQUAL-SUB(0) +#03 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1e 1e 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#03 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 16 (expected 16) +#04 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(26), RXQUAL-FULL(0), RXLEV-SUB(26), RXQUAL-SUB(0) +#04 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1a 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#04 lchan_bs_pwr_ctrl() -> BS power reduction: 16 -> 14 (expected 14) +#05 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(26), RXQUAL-FULL(0), RXLEV-SUB(26), RXQUAL-SUB(0) +#05 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 1a 1a 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#05 lchan_bs_pwr_ctrl() -> BS power reduction: 14 -> 11 (expected 11) +#06 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(35), RXQUAL-FULL(0), RXLEV-SUB(35), RXQUAL-SUB(0) +#06 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 23 23 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#06 lchan_bs_pwr_ctrl() -> BS power reduction: 11 -> 12 (expected 12) +#07 enc_meas_rep() -> Measurement Results (valid): RXLEV-FULL(35), RXQUAL-FULL(0), RXLEV-SUB(35), RXQUAL-SUB(0) +#07 lchan_bs_pwr_ctrl() <- UL SACCH: 06 15 23 23 00 00 00 00 00 00 00 00 00 00 00 00 00 00 +#07 lchan_bs_pwr_ctrl() -> BS power reduction: 12 -> 15 (expected 15) +Test case verdict: SUCCESS diff --git a/tests/testsuite.at b/tests/testsuite.at index 0590580f..ba5a409b 100644 --- a/tests/testsuite.at +++ b/tests/testsuite.at @@ -38,6 +38,13 @@ cat $abs_srcdir/power/ms_power_loop_test.err > experr AT_CHECK([$abs_top_builddir/tests/power/ms_power_loop_test], [], [expout], [experr]) AT_CLEANUP +AT_SETUP([bs_power_loop]) +AT_KEYWORDS([power]) +cat $abs_srcdir/power/bs_power_loop_test.ok > expout +cat $abs_srcdir/power/bs_power_loop_test.err > experr +AT_CHECK([$abs_top_builddir/tests/power/bs_power_loop_test], [], [expout], [experr]) +AT_CLEANUP + AT_SETUP([tx_power]) AT_KEYWORDS([tx_power]) cat $abs_srcdir/tx_power/tx_power_test.ok > expout |