Change in osmo-bts[master]: Move lchan, power_control related code from gsm_data.c to their own files

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.org
Thu Oct 7 12:11:52 UTC 2021


pespin 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>


More information about the gerrit-log mailing list