This is merely a historical archive of years 2008-2021, before the migration to mailman3.
A maintained and still updated list archive can be found at https://lists.osmocom.org/hyperkitty/list/gerrit-log@lists.osmocom.org/.
pespin gerrit-no-reply at lists.osmocom.orgpespin has submitted this change. ( https://gerrit.osmocom.org/c/osmo-bts/+/25698 ) Change subject: Move lchan,power_control related code from gsm_data.c to their own files ...................................................................... Move lchan,power_control related code from gsm_data.c to their own files We already have similar classification in osmo-bsc. Change-Id: I1493f40d99f88a565f15d3e0943a512fb9b8719a --- M src/common/gsm_data.c M src/common/lchan.c M src/common/power_control.c 3 files changed, 405 insertions(+), 404 deletions(-) Approvals: fixeria: Looks good to me, but someone else must approve pespin: Looks good to me, approved osmith: Looks good to me, but someone else must approve Jenkins Builder: Verified diff --git a/src/common/gsm_data.c b/src/common/gsm_data.c index 89a740d..2edeb4d 100644 --- a/src/common/gsm_data.c +++ b/src/common/gsm_data.c @@ -90,21 +90,6 @@ return get_value_string(gsm_chan_t_names, c); } -static const struct value_string lchan_s_names[] = { - { LCHAN_S_NONE, "NONE" }, - { LCHAN_S_ACT_REQ, "ACTIVATION REQUESTED" }, - { LCHAN_S_ACTIVE, "ACTIVE" }, - { LCHAN_S_REL_REQ, "RELEASE REQUESTED" }, - { LCHAN_S_REL_ERR, "RELEASE DUE ERROR" }, - { LCHAN_S_BROKEN, "BROKEN UNUSABLE" }, - { 0, NULL } -}; - -const char *gsm_lchans_name(enum gsm_lchan_state s) -{ - return get_value_string(lchan_s_names, s); -} - static char ts2str[255]; char *gsm_ts_name(const struct gsm_bts_trx_ts *ts) @@ -162,187 +147,6 @@ return ts2str; } -void gsm_lchan_name_update(struct gsm_lchan *lchan) -{ - const struct gsm_bts_trx_ts *ts = lchan->ts; - const struct gsm_bts_trx *trx = ts->trx; - char *name; - - name = talloc_asprintf(trx, "(" GSM_TS_NAME_FMT ",ss=%u)", - GSM_TS_NAME_ARGS(ts), lchan->nr); - if (lchan->name != NULL) - talloc_free(lchan->name); - lchan->name = name; -} - -/* See Table 10.5.25 of GSM04.08 */ -static uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan, - uint8_t ts_nr, uint8_t lchan_nr) -{ - uint8_t cbits, chan_nr; - - OSMO_ASSERT(pchan != GSM_PCHAN_OSMO_DYN); - OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); - - switch (pchan) { - case GSM_PCHAN_TCH_F: - OSMO_ASSERT(lchan_nr == 0); - cbits = ABIS_RSL_CHAN_NR_CBITS_Bm_ACCHs; - break; - case GSM_PCHAN_PDCH: - OSMO_ASSERT(lchan_nr == 0); - cbits = ABIS_RSL_CHAN_NR_CBITS_OSMO_PDCH; - break; - case GSM_PCHAN_TCH_H: - OSMO_ASSERT(lchan_nr < 2); - cbits = ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(lchan_nr); - break; - case GSM_PCHAN_CCCH_SDCCH4: - case GSM_PCHAN_CCCH_SDCCH4_CBCH: - /* - * As a special hack for BCCH, lchan_nr == 4 may be passed - * here. This should never be sent in an RSL message. - * See osmo-bts-xxx/oml.c:opstart_compl(). - */ - if (lchan_nr == CCCH_LCHAN) - cbits = ABIS_RSL_CHAN_NR_CBITS_BCCH; - else { - OSMO_ASSERT(lchan_nr < 4); - cbits = ABIS_RSL_CHAN_NR_CBITS_SDCCH4_ACCH(lchan_nr); - } - break; - case GSM_PCHAN_SDCCH8_SACCH8C: - case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: - OSMO_ASSERT(lchan_nr < 8); - cbits = ABIS_RSL_CHAN_NR_CBITS_SDCCH8_ACCH(lchan_nr); - break; - case GSM_PCHAN_CCCH: - cbits = ABIS_RSL_CHAN_NR_CBITS_BCCH; - break; - case GSM_PCHAN_NONE: - LOGP(DRSL, LOGL_ERROR, "Physical channel %s not expected!\n", - gsm_pchan_name(pchan)); - cbits = 0x00; - break; - default: - LOGP(DRSL, LOGL_ERROR, "Physical channel %s (0x%02x) not expected!\n", - gsm_pchan_name(pchan), (int)pchan); - /* OSMO_ASSERT(lchan_nr == 0); - * FIXME: On octphy and litecell, we hit above assertion (see - * Max's comment at https://gerrit.osmocom.org/589 ); disabled - * for BTS until this is clarified; remove the #ifdef when it - * is fixed. Tracked in OS#2906. - */ -#pragma message "fix caller that passes lchan_nr != 0" - cbits = 0x10; - break; - } - - chan_nr = (cbits << 3) | (ts_nr & 0x7); - - return chan_nr; -} - -static uint8_t _gsm_lchan2chan_nr(const struct gsm_lchan *lchan, bool rsl) -{ - uint8_t chan_nr; - - switch (lchan->ts->pchan) { - case GSM_PCHAN_OSMO_DYN: - /* Return chan_nr reflecting the current TS pchan, either a standard TCH kind, or the - * nonstandard value reflecting PDCH for Osmocom style dyn TS. */ - chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, lchan->ts->dyn.pchan_is); - break; - case GSM_PCHAN_TCH_F_PDCH: - /* For ip.access style dyn TS, on RSL we want to use the chan_nr as if it was TCH/F. - * We're using custom PDCH ACT and DEACT messages that use the usual chan_nr values. */ - if (rsl) - chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F); - else if (~lchan->ts->flags & TS_F_PDCH_ACTIVE) - chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F); - else - chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_PDCH); - break; - default: - chan_nr = gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr); - break; - } - - /* VAMOS: if this lchan belongs to a shadow timeslot, we must reflect - * this in the channel number. Convert it to Osmocom specific value. */ - if (lchan->ts->vamos.is_shadow) - chan_nr |= RSL_CHAN_OSMO_VAMOS_MASK; - - return chan_nr; -} - -uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan) -{ - return _gsm_lchan2chan_nr(lchan, false); -} - -uint8_t gsm_lchan2chan_nr_rsl(const struct gsm_lchan *lchan) -{ - return _gsm_lchan2chan_nr(lchan, true); -} - -uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan, - enum gsm_phys_chan_config as_pchan) -{ - if (lchan->ts->pchan == GSM_PCHAN_OSMO_DYN - && as_pchan == GSM_PCHAN_PDCH) - return RSL_CHAN_OSMO_PDCH | (lchan->ts->nr & ~RSL_CHAN_NR_MASK); - return gsm_pchan2chan_nr(as_pchan, lchan->ts->nr, lchan->nr); -} - -/* Called by the model specific code every 104 TDMA frames (SACCH period) */ -void gsm_lchan_interf_meas_push(struct gsm_lchan *lchan, int dbm) -{ - const uint8_t meas_num = lchan->meas.interf_meas_num; - - if (meas_num >= ARRAY_SIZE(lchan->meas.interf_meas_dbm)) { - LOGPLCHAN(lchan, DL1C, LOGL_ERROR, "Not enough room " - "to store interference report (%ddBm)\n", dbm); - return; - } - - lchan->meas.interf_meas_dbm[meas_num] = dbm; - lchan->meas.interf_meas_num++; -} - -/* Called by the higher layers every Intave * 104 TDMA frames */ -int gsm_lchan_interf_meas_calc_band(struct gsm_lchan *lchan) -{ - const uint8_t meas_num = lchan->meas.interf_meas_num; - const struct gsm_bts *bts = lchan->ts->trx->bts; - int b, meas_avg, meas_sum = 0; - - /* There must be at least one sample */ - if (meas_num == 0) - return -EAGAIN; - - /* Calculate the sum of all collected samples (in -x dBm) */ - while (lchan->meas.interf_meas_num) { - uint8_t i = --lchan->meas.interf_meas_num; - meas_sum += lchan->meas.interf_meas_dbm[i]; - } - - /* Calculate the average of all collected samples */ - meas_avg = meas_sum / (int) meas_num; - - /* Determine the band using interference boundaries from BSC */ - for (b = 0; b < ARRAY_SIZE(bts->interference.boundary); b++) { - if (meas_avg >= bts->interference.boundary[b]) - break; /* Current 'b' is the band value */ - } - - LOGPLCHAN(lchan, DL1C, LOGL_DEBUG, - "Interference AVG: %ddBm (band %d, samples %u)\n", - meas_avg, b, meas_num); - - return b; -} - /* determine logical channel based on TRX and channel number IE */ struct gsm_lchan *rsl_lchan_lookup(struct gsm_bts_trx *trx, uint8_t chan_nr, int *rc) @@ -486,205 +290,18 @@ return pchan_is_tch(ts_pchan(ts)); } -const struct value_string lchan_ciph_state_names[] = { - { LCHAN_CIPH_NONE, "NONE" }, - { LCHAN_CIPH_RX_REQ, "RX_REQ" }, - { LCHAN_CIPH_RX_CONF, "RX_CONF" }, - { LCHAN_CIPH_RXTX_REQ, "RXTX_REQ" }, - { LCHAN_CIPH_RX_CONF_TX_REQ, "RX_CONF_TX_REQ" }, - { LCHAN_CIPH_RXTX_CONF, "RXTX_CONF" }, - { 0, NULL } -}; - -/* determine the ECU codec constant for the codec used by given lchan */ -int lchan2ecu_codec(const struct gsm_lchan *lchan) +bool ts_is_pdch(const struct gsm_bts_trx_ts *ts) { - const struct gsm_bts_trx_ts *ts = lchan->ts; - - switch (lchan->tch_mode) { - case GSM48_CMODE_SPEECH_V1: - if (ts_pchan(ts) == GSM_PCHAN_TCH_H) - return OSMO_ECU_CODEC_HR; - else - return OSMO_ECU_CODEC_FR; - break; - case GSM48_CMODE_SPEECH_EFR: - return OSMO_ECU_CODEC_EFR; - case GSM48_CMODE_SPEECH_AMR: - return OSMO_ECU_CODEC_AMR; + switch (ts->pchan) { + case GSM_PCHAN_PDCH: + return true; + case GSM_PCHAN_TCH_F_PDCH: + return (ts->flags & TS_F_PDCH_ACTIVE) + && !(ts->flags & TS_F_PDCH_PENDING_MASK); + case GSM_PCHAN_OSMO_DYN: + return ts->dyn.pchan_is == GSM_PCHAN_PDCH + && ts->dyn.pchan_want == ts->dyn.pchan_is; default: - return -1; + return false; } } - -/* Default MS/BS Power Control parameters (see 3GPP TS 45.008, table A.1) */ -const struct gsm_power_ctrl_params power_ctrl_params_def = { - - .ctrl_interval = 1, /* Trigger loop every second SACCH block. TS 45.008 sec 4.7.1 */ - - /* Power increasing/reducing step size (optimal defaults) */ - .inc_step_size_db = 4, /* quickly increase MS/BS power */ - .red_step_size_db = 2, /* slowly decrease MS/BS power */ - - /* RxLev measurement parameters */ - .rxlev_meas = { - /* Thresholds for RxLev (see 3GPP TS 45.008, A.3.2.1) */ - .lower_thresh = 32, /* L_RXLEV_XX_P (-78 dBm) */ - .upper_thresh = 38, /* U_RXLEV_XX_P (-72 dBm) */ - - /* NOTE: only Osmocom specific EWMA is supported */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA, - .ewma.alpha = 50, /* Smoothing factor 50% */ - }, - - /* RxQual measurement parameters */ - .rxqual_meas = { - /* Thresholds for RxQual (see 3GPP TS 45.008, A.3.2.1) */ - .lower_thresh = 3, /* L_RXQUAL_XX_P (0.8% <= BER < 1.6%) */ - .upper_thresh = 0, /* U_RXQUAL_XX_P (BER < 0.2%) */ - - /* No averaging (filtering) by default. - * NOTE: only Osmocom specific EWMA is supported */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, - }, - - /* C/I measurement parameters. - * Target C/I retrieved from "GSM/EDGE: Evolution and Performance" Table 10.3. - * Set lower and upper so that (lower + upper) / 2 is equal or slightly - * above the target. - */ - .ci_fr_meas = { /* FR: Target C/I = 15 dB, Soft blocking threshold = 10 dB */ - .lower_thresh = 13, - .upper_thresh = 17, - - /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages - * out of LOWER_CMP_N averages are lower than L_CI_FR_XX_P */ - .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages - * out of UPPER_CMP_N averages are greater than L_CI_FR_XX_P */ - .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - - /* No averaging (filtering) by default */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, - - /* Hreqave: the period over which an average is produced */ - .h_reqave = 4, /* TODO: investigate a reasonable default value */ - /* Hreqt: the number of averaged results maintained */ - .h_reqt = 6, /* TODO: investigate a reasonable default value */ - }, - .ci_hr_meas = { /* HR: Target C/I = 18 dB, Soft blocking threshold = 13 dB */ - .lower_thresh = 16, - .upper_thresh = 21, - - /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages - * out of LOWER_CMP_N averages are lower than L_CI_HR_XX_P */ - .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages - * out of UPPER_CMP_N averages are greater than L_CI_HR_XX_P */ - .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - - /* No averaging (filtering) by default */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, - - /* Hreqave: the period over which an average is produced */ - .h_reqave = 4, /* TODO: investigate a reasonable default value */ - /* Hreqt: the number of averaged results maintained */ - .h_reqt = 6, /* TODO: investigate a reasonable default value */ - }, - .ci_amr_fr_meas = { /* AMR-FR: Target C/I = 9 dB, Soft blocking threshold = 4 dB */ - .lower_thresh = 7, - .upper_thresh = 11, - - /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages - * out of LOWER_CMP_N averages are lower than L_CI_AMR_FR_XX_P */ - .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages - * out of UPPER_CMP_N averages are greater than L_CI_AMR_FR_XX_P */ - .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - - /* No averaging (filtering) by default */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, - - /* Hreqave: the period over which an average is produced */ - .h_reqave = 4, /* TODO: investigate a reasonable default value */ - /* Hreqt: the number of averaged results maintained */ - .h_reqt = 6, /* TODO: investigate a reasonable default value */ - }, - .ci_amr_hr_meas = { /* AMR-HR: Target C/I = 15 dB, Soft blocking threshold = 10 dB */ - .lower_thresh = 13, - .upper_thresh = 17, - - /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages - * out of LOWER_CMP_N averages are lower than L_CI_AMR_HR_XX_P */ - .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages - * out of UPPER_CMP_N averages are greater than L_CI_AMR_HR_XX_P */ - .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - - /* No averaging (filtering) by default */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, - - /* Hreqave: the period over which an average is produced */ - .h_reqave = 4, /* TODO: investigate a reasonable default value */ - /* Hreqt: the number of averaged results maintained */ - .h_reqt = 6, /* TODO: investigate a reasonable default value */ - }, - .ci_sdcch_meas = { /* SDCCH: Target C/I = 14 dB, Soft blocking threshold = 9 dB */ - .lower_thresh = 12, - .upper_thresh = 16, - - /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages - * out of LOWER_CMP_N averages are lower than L_CI_SDCCH_XX_P */ - .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages - * out of UPPER_CMP_N averages are greater than L_CI_SDCCH_XX_P */ - .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - - /* No averaging (filtering) by default */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, - - /* Hreqave: the period over which an average is produced */ - .h_reqave = 4, /* TODO: investigate a reasonable default value */ - /* Hreqt: the number of averaged results maintained */ - .h_reqt = 6, /* TODO: investigate a reasonable default value */ - }, - .ci_gprs_meas = { /* GPRS: Target C/I = 20 dB, Soft blocking threshold = 15 dB */ - .lower_thresh = 18, - .upper_thresh = 24, - - /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages - * out of LOWER_CMP_N averages are lower than L_CI_GPRS_XX_P */ - .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ - /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages - * out of UPPER_CMP_N averages are greater than L_CI_GPRS_XX_P */ - .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ - - /* No averaging (filtering) by default */ - .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, - - /* Hreqave: the period over which an average is produced */ - .h_reqave = 4, /* TODO: investigate a reasonable default value */ - /* Hreqt: the number of averaged results maintained */ - .h_reqt = 6, /* TODO: investigate a reasonable default value */ - }, -}; - -void power_ctrl_params_def_reset(struct gsm_power_ctrl_params *params, bool is_bs_pwr) -{ - *params = power_ctrl_params_def; - if (!is_bs_pwr) - /* Trigger loop every fourth SACCH block (1.92s). TS 45.008 sec 4.7.1: */ - params->ctrl_interval = 2; -} diff --git a/src/common/lchan.c b/src/common/lchan.c index cd99be7..afcb2c3 100644 --- a/src/common/lchan.c +++ b/src/common/lchan.c @@ -24,6 +24,27 @@ #include <osmo-bts/lchan.h> #include <osmo-bts/bts.h> #include <osmo-bts/rsl.h> +#include <errno.h> + +static const struct value_string lchan_s_names[] = { + { LCHAN_S_NONE, "NONE" }, + { LCHAN_S_ACT_REQ, "ACTIVATION REQUESTED" }, + { LCHAN_S_ACTIVE, "ACTIVE" }, + { LCHAN_S_REL_REQ, "RELEASE REQUESTED" }, + { LCHAN_S_REL_ERR, "RELEASE DUE ERROR" }, + { LCHAN_S_BROKEN, "BROKEN UNUSABLE" }, + { 0, NULL } +}; + +const struct value_string lchan_ciph_state_names[] = { + { LCHAN_CIPH_NONE, "NONE" }, + { LCHAN_CIPH_RX_REQ, "RX_REQ" }, + { LCHAN_CIPH_RX_CONF, "RX_CONF" }, + { LCHAN_CIPH_RXTX_REQ, "RXTX_REQ" }, + { LCHAN_CIPH_RX_CONF_TX_REQ, "RX_CONF_TX_REQ" }, + { LCHAN_CIPH_RXTX_CONF, "RXTX_CONF" }, + { 0, NULL } +}; void gsm_lchan_init(struct gsm_lchan *lchan, struct gsm_bts_trx_ts *ts, unsigned int lchan_nr) { @@ -36,6 +57,24 @@ INIT_LLIST_HEAD(&lchan->dl_tch_queue); } +void gsm_lchan_name_update(struct gsm_lchan *lchan) +{ + const struct gsm_bts_trx_ts *ts = lchan->ts; + const struct gsm_bts_trx *trx = ts->trx; + char *name; + + name = talloc_asprintf(trx, "(" GSM_TS_NAME_FMT ",ss=%u)", + GSM_TS_NAME_ARGS(ts), lchan->nr); + if (lchan->name != NULL) + talloc_free(lchan->name); + lchan->name = name; +} + +const char *gsm_lchans_name(enum gsm_lchan_state s) +{ + return get_value_string(lchan_s_names, s); +} + void early_rr_ia_delay_cb(void *data) { struct gsm_lchan *lchan = data; @@ -98,18 +137,191 @@ } } -bool ts_is_pdch(const struct gsm_bts_trx_ts *ts) +/* See Table 10.5.25 of GSM04.08 */ +static uint8_t gsm_pchan2chan_nr(enum gsm_phys_chan_config pchan, + uint8_t ts_nr, uint8_t lchan_nr) { - switch (ts->pchan) { + uint8_t cbits, chan_nr; + + OSMO_ASSERT(pchan != GSM_PCHAN_OSMO_DYN); + OSMO_ASSERT(pchan != GSM_PCHAN_TCH_F_PDCH); + + switch (pchan) { + case GSM_PCHAN_TCH_F: + OSMO_ASSERT(lchan_nr == 0); + cbits = ABIS_RSL_CHAN_NR_CBITS_Bm_ACCHs; + break; case GSM_PCHAN_PDCH: - return true; - case GSM_PCHAN_TCH_F_PDCH: - return (ts->flags & TS_F_PDCH_ACTIVE) - && !(ts->flags & TS_F_PDCH_PENDING_MASK); - case GSM_PCHAN_OSMO_DYN: - return ts->dyn.pchan_is == GSM_PCHAN_PDCH - && ts->dyn.pchan_want == ts->dyn.pchan_is; + OSMO_ASSERT(lchan_nr == 0); + cbits = ABIS_RSL_CHAN_NR_CBITS_OSMO_PDCH; + break; + case GSM_PCHAN_TCH_H: + OSMO_ASSERT(lchan_nr < 2); + cbits = ABIS_RSL_CHAN_NR_CBITS_Lm_ACCHs(lchan_nr); + break; + case GSM_PCHAN_CCCH_SDCCH4: + case GSM_PCHAN_CCCH_SDCCH4_CBCH: + /* + * As a special hack for BCCH, lchan_nr == 4 may be passed + * here. This should never be sent in an RSL message. + * See osmo-bts-xxx/oml.c:opstart_compl(). + */ + if (lchan_nr == CCCH_LCHAN) + cbits = ABIS_RSL_CHAN_NR_CBITS_BCCH; + else { + OSMO_ASSERT(lchan_nr < 4); + cbits = ABIS_RSL_CHAN_NR_CBITS_SDCCH4_ACCH(lchan_nr); + } + break; + case GSM_PCHAN_SDCCH8_SACCH8C: + case GSM_PCHAN_SDCCH8_SACCH8C_CBCH: + OSMO_ASSERT(lchan_nr < 8); + cbits = ABIS_RSL_CHAN_NR_CBITS_SDCCH8_ACCH(lchan_nr); + break; + case GSM_PCHAN_CCCH: + cbits = ABIS_RSL_CHAN_NR_CBITS_BCCH; + break; + case GSM_PCHAN_NONE: + LOGP(DRSL, LOGL_ERROR, "Physical channel %s not expected!\n", + gsm_pchan_name(pchan)); + cbits = 0x00; + break; default: - return false; + LOGP(DRSL, LOGL_ERROR, "Physical channel %s (0x%02x) not expected!\n", + gsm_pchan_name(pchan), (int)pchan); + /* OSMO_ASSERT(lchan_nr == 0); + * FIXME: On octphy and litecell, we hit above assertion (see + * Max's comment at https://gerrit.osmocom.org/589 ); disabled + * for BTS until this is clarified; remove the #ifdef when it + * is fixed. Tracked in OS#2906. + */ +#pragma message "fix caller that passes lchan_nr != 0" + cbits = 0x10; + break; + } + + chan_nr = (cbits << 3) | (ts_nr & 0x7); + + return chan_nr; +} + +static uint8_t _gsm_lchan2chan_nr(const struct gsm_lchan *lchan, bool rsl) +{ + uint8_t chan_nr; + + switch (lchan->ts->pchan) { + case GSM_PCHAN_OSMO_DYN: + /* Return chan_nr reflecting the current TS pchan, either a standard TCH kind, or the + * nonstandard value reflecting PDCH for Osmocom style dyn TS. */ + chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, lchan->ts->dyn.pchan_is); + break; + case GSM_PCHAN_TCH_F_PDCH: + /* For ip.access style dyn TS, on RSL we want to use the chan_nr as if it was TCH/F. + * We're using custom PDCH ACT and DEACT messages that use the usual chan_nr values. */ + if (rsl) + chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F); + else if (~lchan->ts->flags & TS_F_PDCH_ACTIVE) + chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_TCH_F); + else + chan_nr = gsm_lchan_as_pchan2chan_nr(lchan, GSM_PCHAN_PDCH); + break; + default: + chan_nr = gsm_pchan2chan_nr(lchan->ts->pchan, lchan->ts->nr, lchan->nr); + break; + } + + /* VAMOS: if this lchan belongs to a shadow timeslot, we must reflect + * this in the channel number. Convert it to Osmocom specific value. */ + if (lchan->ts->vamos.is_shadow) + chan_nr |= RSL_CHAN_OSMO_VAMOS_MASK; + + return chan_nr; +} + +uint8_t gsm_lchan2chan_nr(const struct gsm_lchan *lchan) +{ + return _gsm_lchan2chan_nr(lchan, false); +} + +uint8_t gsm_lchan2chan_nr_rsl(const struct gsm_lchan *lchan) +{ + return _gsm_lchan2chan_nr(lchan, true); +} + +uint8_t gsm_lchan_as_pchan2chan_nr(const struct gsm_lchan *lchan, + enum gsm_phys_chan_config as_pchan) +{ + if (lchan->ts->pchan == GSM_PCHAN_OSMO_DYN + && as_pchan == GSM_PCHAN_PDCH) + return RSL_CHAN_OSMO_PDCH | (lchan->ts->nr & ~RSL_CHAN_NR_MASK); + return gsm_pchan2chan_nr(as_pchan, lchan->ts->nr, lchan->nr); +} + +/* Called by the model specific code every 104 TDMA frames (SACCH period) */ +void gsm_lchan_interf_meas_push(struct gsm_lchan *lchan, int dbm) +{ + const uint8_t meas_num = lchan->meas.interf_meas_num; + + if (meas_num >= ARRAY_SIZE(lchan->meas.interf_meas_dbm)) { + LOGPLCHAN(lchan, DL1C, LOGL_ERROR, "Not enough room " + "to store interference report (%ddBm)\n", dbm); + return; + } + + lchan->meas.interf_meas_dbm[meas_num] = dbm; + lchan->meas.interf_meas_num++; +} + +/* Called by the higher layers every Intave * 104 TDMA frames */ +int gsm_lchan_interf_meas_calc_band(struct gsm_lchan *lchan) +{ + const uint8_t meas_num = lchan->meas.interf_meas_num; + const struct gsm_bts *bts = lchan->ts->trx->bts; + int b, meas_avg, meas_sum = 0; + + /* There must be at least one sample */ + if (meas_num == 0) + return -EAGAIN; + + /* Calculate the sum of all collected samples (in -x dBm) */ + while (lchan->meas.interf_meas_num) { + uint8_t i = --lchan->meas.interf_meas_num; + meas_sum += lchan->meas.interf_meas_dbm[i]; + } + + /* Calculate the average of all collected samples */ + meas_avg = meas_sum / (int) meas_num; + + /* Determine the band using interference boundaries from BSC */ + for (b = 0; b < ARRAY_SIZE(bts->interference.boundary); b++) { + if (meas_avg >= bts->interference.boundary[b]) + break; /* Current 'b' is the band value */ + } + + LOGPLCHAN(lchan, DL1C, LOGL_DEBUG, + "Interference AVG: %ddBm (band %d, samples %u)\n", + meas_avg, b, meas_num); + + return b; +} + +/* determine the ECU codec constant for the codec used by given lchan */ +int lchan2ecu_codec(const struct gsm_lchan *lchan) +{ + const struct gsm_bts_trx_ts *ts = lchan->ts; + + switch (lchan->tch_mode) { + case GSM48_CMODE_SPEECH_V1: + if (ts_pchan(ts) == GSM_PCHAN_TCH_H) + return OSMO_ECU_CODEC_HR; + else + return OSMO_ECU_CODEC_FR; + break; + case GSM48_CMODE_SPEECH_EFR: + return OSMO_ECU_CODEC_EFR; + case GSM48_CMODE_SPEECH_AMR: + return OSMO_ECU_CODEC_AMR; + default: + return -1; } } diff --git a/src/common/power_control.c b/src/common/power_control.c index 8f5ce37..a81000e 100644 --- a/src/common/power_control.c +++ b/src/common/power_control.c @@ -421,3 +421,175 @@ state->current = new_att; return 1; } + +/* Default MS/BS Power Control parameters (see 3GPP TS 45.008, table A.1) */ +const struct gsm_power_ctrl_params power_ctrl_params_def = { + + .ctrl_interval = 1, /* Trigger loop every second SACCH block. TS 45.008 sec 4.7.1 */ + + /* Power increasing/reducing step size (optimal defaults) */ + .inc_step_size_db = 4, /* quickly increase MS/BS power */ + .red_step_size_db = 2, /* slowly decrease MS/BS power */ + + /* RxLev measurement parameters */ + .rxlev_meas = { + /* Thresholds for RxLev (see 3GPP TS 45.008, A.3.2.1) */ + .lower_thresh = 32, /* L_RXLEV_XX_P (-78 dBm) */ + .upper_thresh = 38, /* U_RXLEV_XX_P (-72 dBm) */ + + /* NOTE: only Osmocom specific EWMA is supported */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_OSMO_EWMA, + .ewma.alpha = 50, /* Smoothing factor 50% */ + }, + + /* RxQual measurement parameters */ + .rxqual_meas = { + /* Thresholds for RxQual (see 3GPP TS 45.008, A.3.2.1) */ + .lower_thresh = 3, /* L_RXQUAL_XX_P (0.8% <= BER < 1.6%) */ + .upper_thresh = 0, /* U_RXQUAL_XX_P (BER < 0.2%) */ + + /* No averaging (filtering) by default. + * NOTE: only Osmocom specific EWMA is supported */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, + }, + + /* C/I measurement parameters. + * Target C/I retrieved from "GSM/EDGE: Evolution and Performance" Table 10.3. + * Set lower and upper so that (lower + upper) / 2 is equal or slightly + * above the target. + */ + .ci_fr_meas = { /* FR: Target C/I = 15 dB, Soft blocking threshold = 10 dB */ + .lower_thresh = 13, + .upper_thresh = 17, + + /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages + * out of LOWER_CMP_N averages are lower than L_CI_FR_XX_P */ + .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages + * out of UPPER_CMP_N averages are greater than L_CI_FR_XX_P */ + .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + + /* No averaging (filtering) by default */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, + + /* Hreqave: the period over which an average is produced */ + .h_reqave = 4, /* TODO: investigate a reasonable default value */ + /* Hreqt: the number of averaged results maintained */ + .h_reqt = 6, /* TODO: investigate a reasonable default value */ + }, + .ci_hr_meas = { /* HR: Target C/I = 18 dB, Soft blocking threshold = 13 dB */ + .lower_thresh = 16, + .upper_thresh = 21, + + /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages + * out of LOWER_CMP_N averages are lower than L_CI_HR_XX_P */ + .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages + * out of UPPER_CMP_N averages are greater than L_CI_HR_XX_P */ + .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + + /* No averaging (filtering) by default */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, + + /* Hreqave: the period over which an average is produced */ + .h_reqave = 4, /* TODO: investigate a reasonable default value */ + /* Hreqt: the number of averaged results maintained */ + .h_reqt = 6, /* TODO: investigate a reasonable default value */ + }, + .ci_amr_fr_meas = { /* AMR-FR: Target C/I = 9 dB, Soft blocking threshold = 4 dB */ + .lower_thresh = 7, + .upper_thresh = 11, + + /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages + * out of LOWER_CMP_N averages are lower than L_CI_AMR_FR_XX_P */ + .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages + * out of UPPER_CMP_N averages are greater than L_CI_AMR_FR_XX_P */ + .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + + /* No averaging (filtering) by default */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, + + /* Hreqave: the period over which an average is produced */ + .h_reqave = 4, /* TODO: investigate a reasonable default value */ + /* Hreqt: the number of averaged results maintained */ + .h_reqt = 6, /* TODO: investigate a reasonable default value */ + }, + .ci_amr_hr_meas = { /* AMR-HR: Target C/I = 15 dB, Soft blocking threshold = 10 dB */ + .lower_thresh = 13, + .upper_thresh = 17, + + /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages + * out of LOWER_CMP_N averages are lower than L_CI_AMR_HR_XX_P */ + .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages + * out of UPPER_CMP_N averages are greater than L_CI_AMR_HR_XX_P */ + .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + + /* No averaging (filtering) by default */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, + + /* Hreqave: the period over which an average is produced */ + .h_reqave = 4, /* TODO: investigate a reasonable default value */ + /* Hreqt: the number of averaged results maintained */ + .h_reqt = 6, /* TODO: investigate a reasonable default value */ + }, + .ci_sdcch_meas = { /* SDCCH: Target C/I = 14 dB, Soft blocking threshold = 9 dB */ + .lower_thresh = 12, + .upper_thresh = 16, + + /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages + * out of LOWER_CMP_N averages are lower than L_CI_SDCCH_XX_P */ + .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages + * out of UPPER_CMP_N averages are greater than L_CI_SDCCH_XX_P */ + .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + + /* No averaging (filtering) by default */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, + + /* Hreqave: the period over which an average is produced */ + .h_reqave = 4, /* TODO: investigate a reasonable default value */ + /* Hreqt: the number of averaged results maintained */ + .h_reqt = 6, /* TODO: investigate a reasonable default value */ + }, + .ci_gprs_meas = { /* GPRS: Target C/I = 20 dB, Soft blocking threshold = 15 dB */ + .lower_thresh = 18, + .upper_thresh = 24, + + /* Increase {UL,DL}_TXPWR if at least LOWER_CMP_P averages + * out of LOWER_CMP_N averages are lower than L_CI_GPRS_XX_P */ + .lower_cmp_p = 5, /* P3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + .lower_cmp_n = 7, /* N3 as in 3GPP TS 45.008, A.3.2.1 (case c) */ + /* Decrease {UL,DL}_TXPWR if at least UPPER_CMP_P averages + * out of UPPER_CMP_N averages are greater than L_CI_GPRS_XX_P */ + .upper_cmp_p = 15, /* P4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + .upper_cmp_n = 18, /* N4 as in 3GPP TS 45.008, A.3.2.1 (case d) */ + + /* No averaging (filtering) by default */ + .algo = GSM_PWR_CTRL_MEAS_AVG_ALGO_NONE, + + /* Hreqave: the period over which an average is produced */ + .h_reqave = 4, /* TODO: investigate a reasonable default value */ + /* Hreqt: the number of averaged results maintained */ + .h_reqt = 6, /* TODO: investigate a reasonable default value */ + }, +}; + +void power_ctrl_params_def_reset(struct gsm_power_ctrl_params *params, bool is_bs_pwr) +{ + *params = power_ctrl_params_def; + if (!is_bs_pwr) + /* Trigger loop every fourth SACCH block (1.92s). TS 45.008 sec 4.7.1: */ + params->ctrl_interval = 2; +} -- To view, visit https://gerrit.osmocom.org/c/osmo-bts/+/25698 To unsubscribe, or for help writing mail filters, visit https://gerrit.osmocom.org/settings Gerrit-Project: osmo-bts Gerrit-Branch: master Gerrit-Change-Id: I1493f40d99f88a565f15d3e0943a512fb9b8719a Gerrit-Change-Number: 25698 Gerrit-PatchSet: 7 Gerrit-Owner: pespin <pespin at sysmocom.de> Gerrit-Reviewer: Jenkins Builder Gerrit-Reviewer: fixeria <vyanitskiy at sysmocom.de> Gerrit-Reviewer: osmith <osmith at sysmocom.de> Gerrit-Reviewer: pespin <pespin at sysmocom.de> Gerrit-MessageType: merged -------------- next part -------------- An HTML attachment was scrubbed... URL: <http://lists.osmocom.org/pipermail/gerrit-log/attachments/20211007/fa14828c/attachment.htm>