aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-07-25 19:53:21 +0200
committerHolger Hans Peter Freyther <holger@moiji-mobile.com>2014-07-30 18:22:12 +0200
commiteececf5fa96875e93d622299408423766c6e35d0 (patch)
treed74ed74db47e09c84b669fffbb7808784cf99824
parentbc24955e91f050e904851f589400eac4c3443917 (diff)
sysmobts: Make it possible to slowly ramp up the output power
For systems with a bigger PA enabling the full output power at once might draw more current than a power supply can provide. This code will step up the output power in smaller steps to avoid this situation.
-rw-r--r--src/osmo-bts-sysmo/main.c5
-rw-r--r--src/osmo-bts-sysmo/oml.c18
-rw-r--r--src/osmo-bts-sysmo/sysmobts_vty.c46
-rw-r--r--src/osmo-bts-sysmo/utils.c87
-rw-r--r--src/osmo-bts-sysmo/utils.h5
-rw-r--r--tests/stubs.c3
-rw-r--r--tests/sysmobts/Makefile.am3
7 files changed, 155 insertions, 12 deletions
diff --git a/src/osmo-bts-sysmo/main.c b/src/osmo-bts-sysmo/main.c
index bd11472b..fac45d9c 100644
--- a/src/osmo-bts-sysmo/main.c
+++ b/src/osmo-bts-sysmo/main.c
@@ -84,6 +84,11 @@ int bts_model_init(struct gsm_bts *bts)
}
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_model_vty_init(bts);
return 0;
diff --git a/src/osmo-bts-sysmo/oml.c b/src/osmo-bts-sysmo/oml.c
index 4ebf6646..e5f9260b 100644
--- a/src/osmo-bts-sysmo/oml.c
+++ b/src/osmo-bts-sysmo/oml.c
@@ -271,6 +271,9 @@ static int trx_init_compl_cb(struct gsm_bts_trx *trx, struct msgb *l1_msg)
trx_rf_lock(trx, 1, trx_mute_on_init_cb);
#endif
+ /* Begin to ramp up the power */
+ sysmobts_pa_maybe_step(trx);
+
return opstart_compl(&trx->mo, l1_msg);
}
@@ -323,7 +326,10 @@ static int trx_init(struct gsm_bts_trx *trx)
dev_par->u16BcchArfcn = trx->bts->c0->arfcn;
dev_par->u8NbTsc = trx->bts->bsic & 7;
dev_par->fRxPowerLevel = fl1h->ul_power_target;
- dev_par->fTxPowerLevel = sysmobts_get_power_trx(trx);
+
+ /* initialize the power */
+ sysmobts_pa_pwr_init(trx);
+ dev_par->fTxPowerLevel = trx->pa.current_power;
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);
@@ -1068,8 +1074,12 @@ 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;
}
@@ -1543,8 +1553,10 @@ 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)
- l1if_set_txpower(fl1h, sysmobts_get_power_trx(trx));
+ if (fl1h->hLayer1) {
+ sysmobts_pa_pwr_init(trx);
+ l1if_set_txpower(fl1h, (float) trx->pa.current_power);
+ }
}
/* FIXME: we actaully need to send a ACK or NACK for the OML message */
diff --git a/src/osmo-bts-sysmo/sysmobts_vty.c b/src/osmo-bts-sysmo/sysmobts_vty.c
index 690ffed9..ed90a234 100644
--- a/src/osmo-bts-sysmo/sysmobts_vty.c
+++ b/src/osmo-bts-sysmo/sysmobts_vty.c
@@ -254,6 +254,39 @@ 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 */
@@ -421,7 +454,9 @@ DEFUN(set_tx_power, set_tx_power_cmd,
struct gsm_bts_trx *trx = gsm_bts_trx_num(vty_bts, trx_nr);
struct femtol1_hdl *fl1h = trx_femtol1_hdl(trx);
- l1if_set_txpower(fl1h, (float) power);
+ trx->pa.current_power = power;
+ osmo_timer_del(&trx->pa.step_timer);
+ l1if_set_txpower(fl1h, (float) trx->pa.current_power);
return CMD_SUCCESS;
}
@@ -551,6 +586,12 @@ 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)) {
@@ -622,6 +663,9 @@ 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 106d12bd..afca7730 100644
--- a/src/osmo-bts-sysmo/utils.c
+++ b/src/osmo-bts-sysmo/utils.c
@@ -137,13 +137,88 @@ int sysmobts_get_nominal_power(struct gsm_bts_trx *trx)
return -1;
}
-int sysmobts_get_power_trx(struct gsm_bts_trx *trx)
+int sysmobts_get_target_power(struct gsm_bts_trx *trx)
{
- int power_transmitter = trx->nominal_power - trx->max_power_red;
- power_transmitter -= trx->power_reduce;
+ int target_power = trx->nominal_power - trx->max_power_red;
+ target_power -= trx->power_reduce;
- if (power_transmitter < 0)
- power_transmitter = 0;
+ if (target_power < 0)
+ target_power = 0;
- return power_transmitter;
+ 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);
}
diff --git a/src/osmo-bts-sysmo/utils.h b/src/osmo-bts-sysmo/utils.h
index aef774ca..cf5cf7af 100644
--- a/src/osmo-bts-sysmo/utils.h
+++ b/src/osmo-bts-sysmo/utils.h
@@ -12,5 +12,8 @@ int sysmobts_select_femto_band(struct gsm_bts_trx *trx, uint16_t arfcn);
int sysmobts_get_nominal_power(struct gsm_bts_trx *trx);
-int sysmobts_get_power_trx(struct gsm_bts_trx *trx);
+int sysmobts_get_target_power(struct gsm_bts_trx *trx);
+
+void sysmobts_pa_pwr_init(struct gsm_bts_trx *trx);
+void sysmobts_pa_maybe_step(struct gsm_bts_trx *trx);
#endif
diff --git a/tests/stubs.c b/tests/stubs.c
index 99961aad..184ae724 100644
--- a/tests/stubs.c
+++ b/tests/stubs.c
@@ -51,3 +51,6 @@ uint32_t trx_get_hlayer1(struct gsm_bts_trx *trx)
int bts_model_oml_estab(struct gsm_bts *bts)
{ return 0; }
+
+int l1if_set_txpower(struct femtol1_hdl *fl1h, float tx_power)
+{ return 0; }
diff --git a/tests/sysmobts/Makefile.am b/tests/sysmobts/Makefile.am
index d884237b..17160ba5 100644
--- a/tests/sysmobts/Makefile.am
+++ b/tests/sysmobts/Makefile.am
@@ -5,5 +5,6 @@ LDADD = $(LIBOSMOCORE_LIBS) $(LIBOSMOGSM_LIBS) $(LIBOSMOVTY_LIBS) $(LIBOSMOTRAU_
noinst_PROGRAMS = sysmobts_test
EXTRA_DIST = sysmobts_test.ok
-sysmobts_test_SOURCES = sysmobts_test.c $(top_srcdir)/src/osmo-bts-sysmo/utils.c
+sysmobts_test_SOURCES = sysmobts_test.c $(top_srcdir)/src/osmo-bts-sysmo/utils.c \
+ $(srcdir)/../stubs.c
sysmobts_test_LDADD = $(LDADD)