diff --git a/bts/BTS_Tests.ttcn b/bts/BTS_Tests.ttcn index aa0618028..9503bec0b 100644 --- a/bts/BTS_Tests.ttcn +++ b/bts/BTS_Tests.ttcn @@ -105,6 +105,7 @@ modulepar { integer mp_bts_tx_pwr_att_exp := 20; /* Expected Tx Power attenuation wrt to Tx Nominal Output Power, in dB */ integer mp_ms_actual_ta_exp := 0; integer mp_timing_offset_256syms_exp := 512; + integer mp_uplink_power_target := -75; /* Time to wait for RSL conn from BTS during startup of test */ float mp_ipa_up_timeout := 15.0; float mp_ipa_up_delay := 0.0; @@ -6809,6 +6810,115 @@ testcase TC_chopped_ipa_payload() runs on test_CT { IPA_Testing.f_run_TC_chopped_ipa_payload(mp_rsl_ip, mp_rsl_port, LISTEN_FOR_CLIENT); } + +/* Callback function to be called by as_TC_ms_pwr_ctrl_constant(). + * Return value: Measurement Report to be sent (encoded octetstring). */ +type function f_TC_ms_pwr_ctrl_cb(inout SacchL1Header l1h, integer num_blocks) + runs on ConnHdlr return octetstring; + +private altstep as_TC_ms_pwr_ctrl(f_TC_ms_pwr_ctrl_cb cb, inout integer num_blocks) +runs on ConnHdlr { + var L1ctlDlMessage l1_dl; + var SacchL1Header l1h; + var octetstring l2; + + [] L1CTL.receive(tr_L1CTL_DATA_IND(g_chan_nr, tr_RslLinkID_SACCH(?))) -> value l1_dl { + /* Parse the L1 SACCH header (MS Power Level & Timing Advance) */ + l1h := dec_SacchL1Header(substr(l1_dl.payload.data_ind.payload, 0, 2)); + log("as_TC_ms_pwr_ctrl(): Rx SACCH L1 header: ", l1h); + + /* Pass it to the user specified call-back function */ + l2 := cb.apply(l1h, num_blocks); + /* Send a Measurement Report generated by the call-back */ + L1CTL.send(ts_L1CTL_DATA_REQ_SACCH(l1_dl.dl_info.chan_nr, + l1_dl.dl_info.link_id, + l1h, l2)); + + /* Shall we keep going? */ + num_blocks := num_blocks - 1; + log("as_TC_ms_pwr_ctrl(): ", num_blocks, " SACCH blocks remaining"); + if (num_blocks > 0) { repeat; } + } + [] L1CTL.receive { repeat; } +} + +private function f_TC_ms_pwr_ctrl_cb_def(inout SacchL1Header l1h, integer num_blocks) +runs on ConnHdlr return octetstring { + /* Command the L1 to apply received parameters */ + f_L1CTL_PARAM(L1CTL, l1h.actual_ta, l1h.ms_power_lvl); + + /* Dummy measurement report (the results are invalid) */ + return f_pad_oct('010349'O & '0615004001C0'O, 21, '00'O); +} + +private function f_TC_ms_pwr_ctrl_cb_const(inout SacchL1Header l1h, integer num_blocks) +runs on ConnHdlr return octetstring { + if (l1h.ms_power_lvl != g_pars.l1_pars.ms_power_level) { + setverdict(fail, "Unexpected MS Power level change: ", + g_pars.l1_pars.ms_power_level, " -> ", + l1h.ms_power_lvl); + } + + return f_TC_ms_pwr_ctrl_cb_def(l1h, num_blocks); +} + +/* Make sure that MS power level remains constant when 'rx-current' equals 'rx-target' */ +private function f_TC_ms_pwr_ctrl_constant(charstring id) +runs on ConnHdlr { + var integer num_blocks := 8; + timer T := int2float(num_blocks); + + f_l1_tune(L1CTL); + RSL.clear; + + /* These IEs are needed for autonomous MS power control */ + var template (value) RSL_IE_List ies := { + t_RSL_IE(RSL_IE_MS_POWER, RSL_IE_Body:{ + ms_power := ts_RSL_IE_MS_Power(g_pars.l1_pars.ms_power_level) + }), + t_RSL_IE(RSL_IE_MS_POWER_PARAM, RSL_IE_Body:{ + ms_power_params := ts_RSL_IE_MS_Power_Parameters(''O) + }) + }; + + /* Ensure that 'rx-current' equals 'rx-target' */ + f_trxc_fake_rssi(mp_uplink_power_target); + + /* Establish a dedicated channel */ + f_est_dchan(more_ies := valueof(ies)); + + L1CTL.clear; + T.start; + alt { + [] as_TC_ms_pwr_ctrl(refers(f_TC_ms_pwr_ctrl_cb_const), num_blocks); + [] T.timeout { + setverdict(fail, "Not all SACCH blocks were processed in time, ", + num_blocks, " were not handled"); + } + } +} +testcase TC_ms_pwr_ctrl_constant() runs on test_CT { + var ConnHdlr vc_conn; + var ConnHdlrPars pars; + + f_init(); + + /* Explicitly configure the Uplink power target (in dBm) */ + f_vty_config(BTSVTY, "bts 0", "uplink-power-target " & int2str(mp_uplink_power_target)); + + for (var integer i := 0; i < sizeof(g_AllChanTypes); i := i + 1) { + pars := valueof(t_Pars(g_AllChanTypes[i], ts_RSL_ChanMode_SIGN)); + log(testcasename(), ": starting on ", pars.chan_nr); + + vc_conn := f_start_handler(refers(f_TC_ms_pwr_ctrl_constant), + pars, trxc_comp := true); + vc_conn.done; + } + + /* No need to reset Uplink power parameters - the IUT restarts anyway */ + Misc_Helpers.f_shutdown(__BFILE__, __LINE__); +} + /* test generation of RLL ERR IND based on Um errors (TS 48.058 3.9) */ /* protocol error as per 44.006 */ /* link layer failure (repetition of I-frame N200 times without ACK */ @@ -6990,6 +7100,8 @@ control { execute( TC_chopped_ipa_ping() ); execute( TC_chopped_ipa_payload() ); + + execute( TC_ms_pwr_ctrl_constant() ); }