diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/common/Makefile.am | 4 | ||||
-rw-r--r-- | src/common/bts.c | 6 | ||||
-rw-r--r-- | src/common/tx_power.c | 273 | ||||
-rw-r--r-- | src/common/vty.c | 82 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/main.c | 6 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/oml.c | 21 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/sysmobts_vty.c | 48 | ||||
-rw-r--r-- | src/osmo-bts-sysmo/utils.c | 84 |
8 files changed, 375 insertions, 149 deletions
diff --git a/src/common/Makefile.am b/src/common/Makefile.am index ea2a742b..77f73b47 100644 --- a/src/common/Makefile.am +++ b/src/common/Makefile.am @@ -5,4 +5,6 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOTRAU_LIBS) noinst_LIBRARIES = libbts.a libbts_a_SOURCES = gsm_data_shared.c sysinfo.c logging.c abis.c oml.c bts.c \ rsl.c vty.c paging.c measurement.c amr.c lchan.c \ - load_indication.c pcu_sock.c handover.c msg_utils.c + load_indication.c pcu_sock.c handover.c msg_utils.c \ + load_indication.c pcu_sock.c handover.c msg_utils.c \ + tx_power.c diff --git a/src/common/bts.c b/src/common/bts.c index 878770af..6cbafd1f 100644 --- a/src/common/bts.c +++ b/src/common/bts.c @@ -120,7 +120,9 @@ int bts_init(struct gsm_bts *bts) /* initialize bts data structure */ llist_for_each_entry(trx, &bts->trx_list, list) { + struct trx_power_params *tpp = &trx->power_params; int i; + for (i = 0; i < ARRAY_SIZE(trx->ts); i++) { struct gsm_bts_trx_ts *ts = &trx->ts[i]; int k; @@ -130,6 +132,10 @@ int bts_init(struct gsm_bts *bts) INIT_LLIST_HEAD(&lchan->dl_tch_queue); } } + /* Default values for the power adjustments */ + tpp->ramp.max_initial_pout_mdBm = to_mdB(23); + tpp->ramp.step_size_mdB = to_mdB(2); + tpp->ramp.step_interval_sec = 1; } osmo_rtp_init(tall_bts_ctx); diff --git a/src/common/tx_power.c b/src/common/tx_power.c new file mode 100644 index 00000000..e2bb9ed7 --- /dev/null +++ b/src/common/tx_power.c @@ -0,0 +1,273 @@ +/* Transmit Power computation */ + +/* (C) 2014 by Harald Welte <laforge@gnumonks.org> + * + * 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 <stdint.h> +#include <limits.h> +#include <errno.h> + +#include <osmocom/core/utils.h> + +#include <osmo-bts/logging.h> +#include <osmo-bts/gsm_data.h> +#include <osmo-bts/bts_model.h> +#include <osmo-bts/tx_power.h> + +static int get_pa_drive_level_mdBm(const struct power_amp *pa, + int desired_p_out_mdBm, unsigned int arfcn) +{ + if (arfcn > ARRAY_SIZE(pa->calib.gain_mdB)) + return INT_MIN; + + /* FIXME: temperature compensation */ + + return desired_p_out_mdBm - pa->calib.gain_mdB[arfcn]; +} + +/* maximum output power of the system */ +int get_p_max_out_mdBm(struct gsm_bts_trx *trx) +{ + struct trx_power_params *tpp = &trx->power_params; + /* Add user gain, internal and external PA gain to TRX output power */ + return tpp->trx_p_max_out_mdBm + tpp->user_gain_mdB + + tpp->pa.nominal_gain_mdB + tpp->user_pa.nominal_gain_mdB; +} + +/* nominal output power, i.e. OML-reduced maximum output power */ +int get_p_nominal_mdBm(struct gsm_bts_trx *trx) +{ + /* P_max_out subtracted by OML maximum power reduction IE */ + return get_p_max_out_mdBm(trx) - to_mdB(trx->max_power_red); +} + +/* calculate the target total output power required, reduced by both + * OML and RSL, but ignoring the attenutation required for power ramping and + * thermal management */ +int get_p_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie) +{ + /* Pn subtracted by RSL BS Power IE (in 2 dB steps) */ + return get_p_nominal_mdBm(trx) - to_mdB(bs_power_ie * 2); +} +int get_p_target_mdBm_lchan(struct gsm_lchan *lchan) +{ + return get_p_target_mdBm(lchan->ts->trx, lchan->bs_power); +} + +/* calculate the actual total output power required, taking into account the + * attenutation required for power ramping but not thermal management */ +int get_p_actual_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm) +{ + struct trx_power_params *tpp = &trx->power_params; + + /* P_target subtracted by ramp attenuation */ + return p_target_mdBm - tpp->ramp.attenuation_mdB; +} + +/* calculate the effective total output power required, taking into account the + * attenutation required for power ramping and thermal management */ +int get_p_eff_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm) +{ + struct trx_power_params *tpp = &trx->power_params; + + /* P_target subtracted by ramp attenuation */ + return p_target_mdBm - tpp->ramp.attenuation_mdB - tpp->thermal_attenuation_mdB; +} + +/* calculate effect TRX output power required, taking into account the + * attenuations required for power ramping and thermal management */ +int get_p_trxout_eff_mdBm(struct gsm_bts_trx *trx, int p_target_mdBm) +{ + struct trx_power_params *tpp = &trx->power_params; + int p_actual_mdBm, user_pa_drvlvl_mdBm, pa_drvlvl_mdBm; + unsigned int arfcn = trx->arfcn; + + /* P_actual subtracted by any bulk gaion added by the user */ + p_actual_mdBm = get_p_eff_mdBm(trx, p_target_mdBm) - tpp->user_gain_mdB; + + /* determine input drive level required at input to user PA */ + user_pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->user_pa, p_actual_mdBm, arfcn); + + /* determine input drive level required at input to internal PA */ + pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->pa, user_pa_drvlvl_mdBm, arfcn); + + /* internal PA input drive level is TRX output power */ + return pa_drvlvl_mdBm; +} + +/* calculate target TRX output power required, ignoring the + * attenuations required for power ramping but not thermal management */ +int get_p_trxout_target_mdBm(struct gsm_bts_trx *trx, uint8_t bs_power_ie) +{ + struct trx_power_params *tpp = &trx->power_params; + int p_target_mdBm, user_pa_drvlvl_mdBm, pa_drvlvl_mdBm; + unsigned int arfcn = trx->arfcn; + + /* P_target subtracted by any bulk gaion added by the user */ + p_target_mdBm = get_p_target_mdBm(trx, bs_power_ie) - tpp->user_gain_mdB; + + /* determine input drive level required at input to user PA */ + user_pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->user_pa, p_target_mdBm, arfcn); + + /* determine input drive level required at input to internal PA */ + pa_drvlvl_mdBm = get_pa_drive_level_mdBm(&tpp->pa, user_pa_drvlvl_mdBm, arfcn); + + /* internal PA input drive level is TRX output power */ + return pa_drvlvl_mdBm; +} +int get_p_trxout_target_mdBm_lchan(struct gsm_lchan *lchan) +{ + return get_p_trxout_target_mdBm(lchan->ts->trx, lchan->bs_power); +} + + +/* output power ramping code */ + +/* The idea here is to avoid a hard switch from 0 to 100, but to actually + * slowly and gradually ramp up or down the power. This is needed on the + * one hand side to avoid very fast dynamic load changes towards the PA power + * supply, but is also needed in order to avoid a DoS by too many subscriber + * attempting to register at the same time. Rather, grow the cell slowly in + * radius than start with the full raduis at once. */ + +static int we_are_ramping_up(struct gsm_bts_trx *trx) +{ + struct trx_power_params *tpp = &trx->power_params; + + if (tpp->p_total_tgt_mdBm > tpp->p_total_cur_mdBm) + return 1; + else + return 0; +} + +static void power_ramp_do_step(struct gsm_bts_trx *trx, int first); + +/* timer call-back for the ramp tumer */ +static void power_ramp_timer_cb(void *_trx) +{ + struct gsm_bts_trx *trx = _trx; + struct trx_power_params *tpp = &trx->power_params; + int p_trxout_eff_mdBm; + + /* compute new actual total output power (= minus ramp attenuation) */ + tpp->p_total_cur_mdBm = get_p_actual_mdBm(trx, tpp->p_total_tgt_mdBm); + + /* compute new effective (= minus ramp and thermal attenuation) TRX output required */ + p_trxout_eff_mdBm = get_p_trxout_eff_mdBm(trx, tpp->p_total_tgt_mdBm); + + LOGP(DL1C, LOGL_DEBUG, "ramp_timer_cb(cur_pout=%d, tgt_pout=%d, " + "ramp_att=%d, therm_att=%d, user_gain=%d)\n", + tpp->p_total_cur_mdBm, tpp->p_total_tgt_mdBm, + tpp->ramp.attenuation_mdB, tpp->thermal_attenuation_mdB, + tpp->user_gain_mdB); + + LOGP(DL1C, LOGL_INFO, + "ramping TRX board output power to %d mdBm.\n", p_trxout_eff_mdBm); + + /* Instruct L1 to apply new effective TRX output power required */ + bts_model_change_power(trx, p_trxout_eff_mdBm); + + /* and do another step... */ + power_ramp_do_step(trx, 0); +} + +static void power_ramp_do_step(struct gsm_bts_trx *trx, int first) +{ + struct trx_power_params *tpp = &trx->power_params; + + /* we had finished in last loop iteration */ + if (!first && tpp->ramp.attenuation_mdB == 0) + return; + + if (we_are_ramping_up(trx)) { + /* ramp up power -> ramp down attenuation */ + tpp->ramp.attenuation_mdB -= tpp->ramp.step_size_mdB; + if (tpp->ramp.attenuation_mdB <= 0) { + /* we are done */ + tpp->ramp.attenuation_mdB = 0; + } + } else { + /* ramp down power -> ramp up attenuation */ + tpp->ramp.attenuation_mdB += tpp->ramp.step_size_mdB; + if (tpp->ramp.attenuation_mdB >= 0) { + /* we are done */ + tpp->ramp.attenuation_mdB = 0; + } + } + + /* schedule timer for the next step */ + tpp->ramp.step_timer.data = trx; + tpp->ramp.step_timer.cb = power_ramp_timer_cb; + osmo_timer_schedule(&tpp->ramp.step_timer, tpp->ramp.step_interval_sec, 0); +} + + +int power_ramp_start(struct gsm_bts_trx *trx, int p_total_tgt_mdBm, int bypass) +{ + struct trx_power_params *tpp = &trx->power_params; + + /* The input to this function is the actual desired output power, i.e. + * the maximum total system power subtracted by OML as well as RSL + * reductions */ + + LOGP(DL1C, LOGL_INFO, "power_ramp_start(cur=%d, tgt=%d)\n", + tpp->p_total_cur_mdBm, p_total_tgt_mdBm); + + if (!bypass && (p_total_tgt_mdBm > get_p_nominal_mdBm(trx))) { + LOGP(DL1C, LOGL_ERROR, "Asked to ramp power up to " + "%d mdBm, which exceeds P_max_out (%d)\n", + p_total_tgt_mdBm, get_p_nominal_mdBm(trx)); + return -ERANGE; + } + + /* Cancel any pending request */ + osmo_timer_del(&tpp->ramp.step_timer); + + /* set the new target */ + tpp->p_total_tgt_mdBm = p_total_tgt_mdBm; + + if (we_are_ramping_up(trx)) { + if (tpp->p_total_tgt_mdBm <= tpp->ramp.max_initial_pout_mdBm) { + LOGP(DL1C, LOGL_INFO, + "target_power(%d) is below max.initial power\n", + tpp->p_total_tgt_mdBm); + /* new setting is below the maximum initial output + * power, so we can directly jump to this level */ + tpp->p_total_cur_mdBm = tpp->p_total_tgt_mdBm; + tpp->ramp.attenuation_mdB = 0; + power_ramp_timer_cb(trx); + } else { + /* We need to step it up. Start from the current value */ + /* Set attenuation to cause no power change right now */ + tpp->ramp.attenuation_mdB = tpp->p_total_tgt_mdBm - tpp->p_total_cur_mdBm; + + /* start with the firsrt step */ + power_ramp_do_step(trx, 1); + } + } else { + /* Set ramp attenuation to negative value, and increse that by + * steps until it reaches 0 */ + tpp->ramp.attenuation_mdB = tpp->p_total_tgt_mdBm - tpp->p_total_cur_mdBm; + + /* start with the firsrt step */ + power_ramp_do_step(trx, 1); + } + + return 0; +} diff --git a/src/common/vty.c b/src/common/vty.c index ea38ac95..a2f2fb37 100644 --- a/src/common/vty.c +++ b/src/common/vty.c @@ -186,7 +186,19 @@ static void config_write_bts_single(struct vty *vty, struct gsm_bts *bts) bts_model_config_write_bts(vty, bts); llist_for_each_entry(trx, &bts->trx_list, list) { + struct trx_power_params *tpp = &trx->power_params; vty_out(vty, " trx %u%s", trx->nr, VTY_NEWLINE); + + if (trx->power_params.user_gain_mdB) + vty_out(vty, " user-gain %u mdB%s", + tpp->user_gain_mdB, VTY_NEWLINE); + vty_out(vty, " power-ramp max-initinal-pout %d mdBm%s", + tpp->ramp.max_initial_pout_mdBm, VTY_NEWLINE); + vty_out(vty, " power-ramp step-size %d mdBm%s", + tpp->ramp.step_size_mdB, VTY_NEWLINE); + vty_out(vty, " power-ramp step-interval %d%s", + tpp->ramp.step_interval_sec, VTY_NEWLINE); + bts_model_config_write_trx(vty, trx); } } @@ -384,6 +396,71 @@ DEFUN(cfg_bts_agch_queue_mgmt_default, return CMD_SUCCESS; } +#define DB_DBM_STR \ + "Unit is dB (decibels)\n" \ + "Unit is mdB (milli-decibels, or rather 1/10000 bel)\n" + +static int parse_mdbm(const char *valstr, const char *unit) +{ + int val = atoi(valstr); + + if (!strcmp(unit, "dB") || !strcmp(unit, "dBm")) + return val * 1000; + else + return val; +} + +DEFUN(cfg_trx_user_gain, + cfg_trx_user_gain_cmd, + "user-gain <-100000-100000> (dB|mdB)", + "Inform BTS about additional, user-provided gain or attenuation at TRX output\n" + "Value of user-provided external gain(+)/attenuation(-)\n" DB_DBM_STR) +{ + struct gsm_bts_trx *trx = vty->index; + + trx->power_params.user_gain_mdB = parse_mdbm(argv[0], argv[1]); + + return CMD_SUCCESS; +} + +#define PR_STR "Power-Ramp settings" +DEFUN(cfg_trx_pr_max_initial, cfg_trx_pr_max_initial_cmd, + "power-ramp max-initial <0-100000> (dBm|mdBm)", + PR_STR "Maximum initial power\n" + "Value\n" DB_DBM_STR) +{ + struct gsm_bts_trx *trx = vty->index; + + trx->power_params.ramp.max_initial_pout_mdBm = + parse_mdbm(argv[0], argv[1]); + + return CMD_SUCCESS; +} + +DEFUN(cfg_trx_pr_step_size, cfg_trx_pr_step_size_cmd, + "power-ramp step-size <1-100000> (dB|mdB)", + PR_STR "Power increase by step\n" + "Step size\n" DB_DBM_STR) +{ + struct gsm_bts_trx *trx = vty->index; + + trx->power_params.ramp.step_size_mdB = + parse_mdbm(argv[0], argv[1]); + return CMD_SUCCESS; +} + +DEFUN(cfg_trx_pr_step_interval, cfg_trx_pr_step_interval_cmd, + "power-ramp step-interval <1-100>", + PR_STR "Power increase by step\n" + "Step time in seconds\n") +{ + struct gsm_bts_trx *trx = vty->index; + + trx->power_params.ramp.step_interval_sec = atoi(argv[0]); + return CMD_SUCCESS; +} + + /* ====================================================================== * SHOW @@ -563,6 +640,11 @@ int bts_vty_init(const struct log_info *cat) install_node(&trx_node, config_write_dummy); install_default(TRX_NODE); + install_element(TRX_NODE, &cfg_trx_user_gain_cmd); + install_element(TRX_NODE, &cfg_trx_pr_max_initial_cmd); + install_element(TRX_NODE, &cfg_trx_pr_step_size_cmd); + install_element(TRX_NODE, &cfg_trx_pr_step_interval_cmd); + install_element(ENABLE_NODE, &bts_t_t_l_jitter_buf_cmd); return 0; diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c index 5a864074..d12421df 100644 --- a/src/osmo-bts-sysmo/main.c +++ b/src/osmo-bts-sysmo/main.c @@ -84,11 +84,7 @@ int bts_model_init(struct gsm_bts *bts) rc = 23; } bts->c0->nominal_power = rc; - - /* Initial values for the power adjustments */ - bts->c0->pa.max_initial_power = 23; - bts->c0->pa.step_size = 2; - bts->c0->pa.step_interval = 1; + bts->c0->power_params.trx_p_max_out_mdBm = to_mdB(rc); bts_model_vty_init(bts); diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c index e5f9260b..207cae89 100644 --- a/src/osmo-bts-sysmo/oml.c +++ b/src/osmo-bts-sysmo/oml.c @@ -272,7 +272,7 @@ static int trx_init_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg) #endif /* Begin to ramp up the power */ - sysmobts_pa_maybe_step(trx); + power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); return opstart_compl(&trx->mo, l1_msg); } @@ -327,9 +327,7 @@ static int trx_init(struct gsm_bts_trx *trx) dev_par->u8NbTsc = trx->bts->bsic & 7; dev_par->fRxPowerLevel = fl1h->ul_power_target; - /* initialize the power */ - sysmobts_pa_pwr_init(trx); - dev_par->fTxPowerLevel = trx->pa.current_power; + dev_par->fTxPowerLevel = 0.0; LOGP(DL1C, LOGL_NOTICE, "Init TRX (ARFCN %u, TSC %u, RxPower % 2f dBm, " "TxPower % 2.2f dBm\n", dev_par->u16Arfcn, dev_par->u8NbTsc, dev_par->fRxPowerLevel, dev_par->fTxPowerLevel); @@ -1074,12 +1072,8 @@ static int chmod_txpower_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg) LOGPC(DL1C, LOGL_INFO, "setTxPower %f dBm\n", cc->cfgParams.setTxPowerLevel.fTxPowerLevel); - trx->pa.current_power = cc->cfgParams.setTxPowerLevel.fTxPowerLevel; msgb_free(l1_msg); - /* Schedule the next step up */ - sysmobts_pa_maybe_step(trx); - return 0; } @@ -1553,10 +1547,8 @@ int bts_model_apply_oml(struct gsm_bts *bts, struct msgb *msg, struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); /* Did we go through MphInit yet? If yes fire and forget */ - if (fl1h->hLayer1) { - sysmobts_pa_pwr_init(trx); - l1if_set_txpower(fl1h, (float) trx->pa.current_power); - } + if (fl1h->hLayer1) + power_ramp_start(trx, get_p_target_mdBm(trx, 0), 0); } /* FIXME: we actaully need to send a ACK or NACK for the OML message */ @@ -1722,3 +1714,8 @@ int bts_model_trx_deact_rf(struct gsm_bts_trx *trx) return l1if_activate_rf(fl1, 0); } + +int bts_model_change_power(struct gsm_bts_trx *trx, int p_trxout_mdBm) +{ + return l1if_set_txpower(trx_femtol1_hdl(trx), ((float) p_trxout_mdBm)/1000.0); +} diff --git a/src/osmo-bts-sysmo/sysmobts_vty.c b/src/osmo-bts-sysmo/sysmobts_vty.c index ed90a234..8b617d78 100644 --- a/src/osmo-bts-sysmo/sysmobts_vty.c +++ b/src/osmo-bts-sysmo/sysmobts_vty.c @@ -254,40 +254,6 @@ DEFUN(cfg_trx_nominal_power, cfg_trx_nominal_power_cmd, return CMD_SUCCESS; } -#define PA_STR "Power-Amplifier settings" -DEFUN(cfg_trx_pa_max_initial, cfg_trx_pa_max_initial_cmd, - "power-amplifier max-initial <0-100>", - PA_STR "Maximum initial power\n" - "Value in dBm\n") -{ - struct gsm_bts_trx *trx = vty->index; - - trx->pa.max_initial_power = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_pa_step_size, cfg_trx_pa_step_size_cmd, - "power-amplifier step-size <1-100>", - PA_STR "Power increase by step\n" - "Step size in dB\n") -{ - struct gsm_bts_trx *trx = vty->index; - - trx->pa.step_size = atoi(argv[0]); - return CMD_SUCCESS; -} - -DEFUN(cfg_trx_pa_step_interval, cfg_trx_pa_step_interval_cmd, - "power-amplifier step-interval <1-100>", - PA_STR "Power increase by step\n" - "Step time in seconds\n") -{ - struct gsm_bts_trx *trx = vty->index; - - trx->pa.step_interval = atoi(argv[0]); - return CMD_SUCCESS; -} - /* runtime */ DEFUN(show_trx_clksrc, show_trx_clksrc_cmd, @@ -452,11 +418,8 @@ DEFUN(set_tx_power, set_tx_power_cmd, int trx_nr = atoi(argv[0]); int power = atoi(argv[1]); struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr); - struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx); - trx->pa.current_power = power; - osmo_timer_del(&trx->pa.step_timer); - l1if_set_txpower(fl1h, (float) trx->pa.current_power); + power_ramp_start(trx, to_mdB(power), 1); return CMD_SUCCESS; } @@ -586,12 +549,6 @@ void bts_model_config_write_trx(struct vty *vty, struct gsm_bts_trx *trx) if (trx->nominal_power != sysmobts_get_nominal_power(trx)) vty_out(vty, " nominal-tx-power %d%s", trx->nominal_power, VTY_NEWLINE); - vty_out(vty, " power-amplifier max-initial %d%s", - trx->pa.max_initial_power, VTY_NEWLINE); - vty_out(vty, " power-amplifier step-size %d%s", - trx->pa.step_size, VTY_NEWLINE); - vty_out(vty, " power-amplifier step-interval %d%s", - trx->pa.step_interval, VTY_NEWLINE); for (i = 0; i < 32; i++) { if (fl1h->gsmtap_sapi_mask & (1 << i)) { @@ -663,9 +620,6 @@ int bts_model_vty_init(struct gsm_bts *bts) install_element(TRX_NODE, &cfg_trx_min_qual_rach_cmd); install_element(TRX_NODE, &cfg_trx_min_qual_norm_cmd); install_element(TRX_NODE, &cfg_trx_nominal_power_cmd); - install_element(TRX_NODE, &cfg_trx_pa_max_initial_cmd); - install_element(TRX_NODE, &cfg_trx_pa_step_size_cmd); - install_element(TRX_NODE, &cfg_trx_pa_step_interval_cmd); return 0; } diff --git a/src/osmo-bts-sysmo/utils.c b/src/osmo-bts-sysmo/utils.c index afca7730..a636ae15 100644 --- a/src/osmo-bts-sysmo/utils.c +++ b/src/osmo-bts-sysmo/utils.c @@ -137,88 +137,4 @@ int sysmobts_get_nominal_power(struct gsm_bts_trx *trx) return -1; } -int sysmobts_get_target_power(struct gsm_bts_trx *trx) -{ - int target_power = trx->nominal_power - trx->max_power_red; - target_power -= trx->power_reduce; - - if (target_power < 0) - target_power = 0; - - return target_power; -} - -void sysmobts_pa_pwr_init(struct gsm_bts_trx *trx) -{ - int target_power = sysmobts_get_target_power(trx); - - /* Cancel any pending request */ - osmo_timer_del(&trx->pa.step_timer); - - /* is this below our initial target */ - if (target_power <= trx->pa.max_initial_power) { - LOGP(DL1C, LOGL_NOTICE, - "PA target_power(%d) is below initial power.\n", - target_power); - trx->pa.current_power = target_power; - return; - } - - /* is this below our current value? */ - if (target_power <= trx->pa.current_power) { - LOGP(DL1C, LOGL_NOTICE, - "PA target_power(%d) is below current_power.\n", - target_power); - trx->pa.current_power = target_power; - return; - } - if (trx->pa.current_power > trx->pa.max_initial_power) { - LOGP(DL1C, LOGL_NOTICE, - "PA target_power(%d) starting from current_power.\n", - target_power); - return; - } - - /* We need to step it up. Start from the initial value */ - trx->pa.current_power = trx->pa.max_initial_power; - LOGP(DL1C, LOGL_NOTICE, - "PA target_power(%d) starting with %d dBm.\n", - target_power, trx->pa.current_power); -} - -static void pa_trx_cb(void *_trx) -{ - struct gsm_bts_trx *trx = _trx; - - LOGP(DL1C, LOGL_NOTICE, - "PA raising power to %d dBm.\n", trx->pa.current_power); - l1if_set_txpower(trx_femtol1_hdl(trx), (float) trx->pa.current_power); -} - -void sysmobts_pa_maybe_step(struct gsm_bts_trx *trx) -{ - /* it can not have changed */ - int target_power = sysmobts_get_target_power(trx); - - /* We are done */ - if (trx->pa.current_power >= target_power) { - LOGP(DL1C, LOGL_NOTICE, - "PA have reached target power: %d dBm.\n", - target_power); - return; - } - - /* Step up the current power but clamp it */ - trx->pa.current_power += trx->pa.step_size; - if (trx->pa.current_power > target_power) - trx->pa.current_power = target_power; - - LOGP(DL1C, LOGL_NOTICE, - "PA scheduling to step to %d dBm.\n", - trx->pa.current_power); - - trx->pa.step_timer.data = trx; - trx->pa.step_timer.cb = pa_trx_cb; - osmo_timer_schedule(&trx->pa.step_timer, trx->pa.step_interval, 0); -} |