[MERGED] osmo-bts[master]: trx: Enable EGPRS handling through burst lengths

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/.

Harald Welte gerrit-no-reply at lists.osmocom.org
Thu Jul 28 06:18:12 UTC 2016


Harald Welte has submitted this change and it was merged.

Change subject: trx: Enable EGPRS handling through burst lengths
......................................................................


trx: Enable EGPRS handling through burst lengths

Existing interfaces are coded with the implicit expectation of using
a burst sequence length of 148, which is constant with GSM and GPRS.
That changes with EGPRS, where the burst length may be 444 due to
the use of 8-PSK instead of GMSK modulation.

Setup the interface to accept and return a length value with the
burst sequence. This allows 444 length bit vectors to/from the
EGPRS decoder/encoder. Length is explicitly used as a identifier for
8-PSK vs. GMSK modulated sequences.

Change-Id: I90b46b46b11b6ce280e7f8232d5a2fccec2d4f18
Signed-off-by: Tom Tsou <tom.tsou at ettus.com>
---
M include/osmo-bts/scheduler.h
M include/osmo-bts/scheduler_backend.h
M src/common/scheduler.c
M src/osmo-bts-trx/gsm0503_coding.c
M src/osmo-bts-trx/scheduler_trx.c
M src/osmo-bts-trx/trx_if.c
M src/osmo-bts-trx/trx_if.h
7 files changed, 182 insertions(+), 93 deletions(-)

Approvals:
  Harald Welte: Looks good to me, approved
  Jenkins Builder: Verified



diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h
index 090f5a5..b0387db 100644
--- a/include/osmo-bts/scheduler.h
+++ b/include/osmo-bts/scheduler.h
@@ -48,11 +48,21 @@
 	_TRX_CHAN_MAX
 };
 
+#define GSM_BURST_LEN		148
+#define GPRS_BURST_LEN		GSM_BURST_LEN
+#define EGPRS_BURST_LEN		444
+
+enum trx_burst_type {
+	TRX_BURST_GMSK,
+	TRX_BURST_8PSK,
+};
+
 /* States each channel on a multiframe */
 struct l1sched_chan_state {
 	/* scheduler */
 	uint8_t			active;		/* Channel is active */
 	ubit_t			*dl_bursts;	/* burst buffer for TX */
+	enum trx_burst_type	dl_burst_type;  /* GMSK or 8PSK burst type */
 	sbit_t			*ul_bursts;	/* burst buffer for RX */
 	uint32_t		ul_first_fn;	/* fn of first burst */
 	uint8_t			ul_mask;	/* mask of received bursts */
@@ -151,7 +161,7 @@
 
 /*! \brief handle an UL burst received by PHY */
 int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-        sbit_t *bits, int8_t rssi, float toa);
+        sbit_t *bits, uint16_t nbits, int8_t rssi, float toa);
 
 /*! \brief set multiframe scheduler to given physical channel config */
 int trx_sched_set_pchan(struct l1sched_trx *l1t, uint8_t tn,
diff --git a/include/osmo-bts/scheduler_backend.h b/include/osmo-bts/scheduler_backend.h
index 9c0361d..68f0c60 100644
--- a/include/osmo-bts/scheduler_backend.h
+++ b/include/osmo-bts/scheduler_backend.h
@@ -5,12 +5,12 @@
 
 typedef ubit_t *trx_sched_dl_func(struct l1sched_trx *l1t, uint8_t tn,
 				  uint32_t fn, enum trx_chan_type chan,
-				  uint8_t bid);
+				  uint8_t bid, uint16_t *nbits);
 
 typedef int trx_sched_ul_func(struct l1sched_trx *l1t, uint8_t tn,
 			      uint32_t fn, enum trx_chan_type chan,
-			      uint8_t bid, sbit_t *bits, int8_t rssi,
-			      float toa);
+			      uint8_t bid, sbit_t *bits, uint16_t nbits,
+			      int8_t rssi, float toa);
 
 struct trx_chan_desc {
 	/*! \brief Is this on a PDCH (PS) ? */
@@ -49,35 +49,36 @@
 		    enum trx_chan_type chan, uint8_t *tch, uint8_t tch_len);
 
 ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid);
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
 ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid);
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
 ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid);
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
 ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid);
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
 ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid);
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
 ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid);
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
 ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid);
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits);
 int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa);
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa);
 int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa);
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa);
 int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa);
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa);
 int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa);
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa);
 int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa);
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa);
 
-const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
+const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
+			      uint32_t fn, uint16_t *nbits);
 int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn);
 void _sched_act_rach_det(struct l1sched_trx *l1t, uint8_t tn, uint8_t ss, int activate);
diff --git a/src/common/scheduler.c b/src/common/scheduler.c
index 507be78..eeaf2c1 100644
--- a/src/common/scheduler.c
+++ b/src/common/scheduler.c
@@ -47,7 +47,7 @@
 static int rts_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
 	enum trx_chan_type chan);
 /*! \brief Dummy Burst (TS 05.02 Chapter 5.2.6) */
-static const ubit_t dummy_burst[148] = {
+static const ubit_t dummy_burst[GSM_BURST_LEN] = {
 	0,0,0,
 	1,1,1,1,1,0,1,1,0,1,1,1,0,1,1,0,0,0,0,0,1,0,1,0,0,1,0,0,1,1,1,0,
 	0,0,0,0,1,0,0,1,0,0,0,1,0,0,0,0,0,0,0,1,1,1,1,1,0,0,0,1,1,1,0,0,
@@ -58,7 +58,7 @@
 };
 
 /*! \brief FCCH Burst (TS 05.02 Chapter 5.2.4) */
-const ubit_t _sched_fcch_burst[148] = {
+const ubit_t _sched_fcch_burst[GSM_BURST_LEN] = {
 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
 	0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
@@ -1504,7 +1504,8 @@
 }
 
 /* process downlink burst */
-const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn)
+const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn,
+				uint32_t fn, uint16_t *nbits)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct l1sched_chan_state *l1cs;
@@ -1529,11 +1530,14 @@
 	l1cs = &l1ts->chan_state[chan];
 
 	/* check if channel is active */
-	if (!trx_chan_desc[chan].auto_active && !l1cs->active)
-	 	goto no_data;
+	if (!trx_chan_desc[chan].auto_active && !l1cs->active) {
+		if (nbits)
+			*nbits = GSM_BURST_LEN;
+		goto no_data;
+	}
 
 	/* get burst from function */
-	bits = func(l1t, tn, fn, chan, bid);
+	bits = func(l1t, tn, fn, chan, bid, nbits);
 
 	/* encrypt */
 	if (bits && l1cs->dl_encr_algo) {
@@ -1562,7 +1566,7 @@
 
 /* process uplink burst */
 int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t current_fn,
-	sbit_t *bits, int8_t rssi, float toa)
+	sbit_t *bits, uint16_t nbits, int8_t rssi, float toa)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct l1sched_chan_state *l1cs;
@@ -1623,12 +1627,12 @@
 				}
 			}
 
-			func(l1t, tn, fn, chan, bid, bits, rssi, toa);
+			func(l1t, tn, fn, chan, bid, bits, nbits, rssi, toa);
 		} else if (chan != TRXC_RACH && !l1cs->ho_rach_detect) {
-			sbit_t spare[148];
+			sbit_t spare[GSM_BURST_LEN];
 
-			memset(spare, 0, 148);
-			func(l1t, tn, fn, chan, bid, spare, -128, 0);
+			memset(spare, 0, GSM_BURST_LEN);
+			func(l1t, tn, fn, chan, bid, spare, GSM_BURST_LEN, -128, 0);
 		}
 
 next_frame:
diff --git a/src/osmo-bts-trx/gsm0503_coding.c b/src/osmo-bts-trx/gsm0503_coding.c
index fd86385..c601cac 100644
--- a/src/osmo-bts-trx/gsm0503_coding.c
+++ b/src/osmo-bts-trx/gsm0503_coding.c
@@ -1353,7 +1353,7 @@
 		gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
 			hl_hn + i*2, hl_hn + i*2 + 1);
 
-	return 0;
+	return GSM0503_GPRS_BURSTS_NBITS;
 }
 
 
diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c
index d599201..3a6ede3 100644
--- a/src/osmo-bts-trx/scheduler_trx.c
+++ b/src/osmo-bts-trx/scheduler_trx.c
@@ -60,6 +60,8 @@
  * Note that regular phones will not work when using this test! */
 //#define TA_TEST
 
+/* Maximum size of a EGPRS message in bytes */
+#define EGPRS_0503_MAX_BYTES		155
 
 /*
  * TX on downlink
@@ -67,19 +69,25 @@
 
 /* an IDLE burst returns nothing. on C0 it is replaced by dummy burst */
 ubit_t *tx_idle_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid)
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
 {
 	LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr);
+
+	if (nbits)
+		*nbits = GSM_BURST_LEN;
 
 	return NULL;
 }
 
 ubit_t *tx_fcch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid)
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
 {
 	LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr);
+
+	if (nbits)
+		*nbits = GSM_BURST_LEN;
 
 	/* BURST BYPASS */
 
@@ -87,9 +95,9 @@
 }
 
 ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid)
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
 {
-	static ubit_t bits[148], burst[78];
+	static ubit_t bits[GSM_BURST_LEN], burst[78];
 	uint8_t sb_info[4];
 	struct	gsm_time t;
 	uint8_t t3p, bsic;
@@ -125,11 +133,14 @@
 	memcpy(bits + 106, burst + 39, 39);
 	memset(bits + 145, 0, 3);
 
+	if (nbits)
+		*nbits = GSM_BURST_LEN;
+
 	return bits;
 }
 
 ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid)
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
@@ -137,7 +148,7 @@
 	uint8_t chan_nr = trx_chan_desc[chan].chan_nr | tn;
 	struct msgb *msg = NULL; /* make GCC happy */
 	ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts;
-	static ubit_t bits[148];
+	static ubit_t bits[GSM_BURST_LEN];
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
@@ -216,6 +227,9 @@
 	memcpy(bits + 87, burst + 58, 58);
 	memset(bits + 145, 0, 3);
 
+	if (nbits)
+		*nbits = GSM_BURST_LEN;
+
 	LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
 
@@ -223,14 +237,15 @@
 }
 
 ubit_t *tx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid)
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct gsm_bts_trx_ts *ts = &l1t->trx->ts[tn];
 	struct msgb *msg = NULL; /* make GCC happy */
 	ubit_t *burst, **bursts_p = &l1ts->chan_state[chan].dl_bursts;
-	static ubit_t bits[148];
-	int rc;
+	enum trx_burst_type *burst_type = &l1ts->chan_state[chan].dl_burst_type;
+	static ubit_t bits[EGPRS_BURST_LEN];
+	int rc = 0;
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
@@ -261,21 +276,28 @@
 
 	/* alloc burst memory, if not already */
 	if (!*bursts_p) {
-		*bursts_p = talloc_zero_size(tall_bts_ctx, 464);
+		*bursts_p = talloc_zero_size(tall_bts_ctx,
+					     GSM0503_EGPRS_BURSTS_NBITS);
 		if (!*bursts_p)
 			return NULL;
 	}
 
 	/* encode bursts */
-	rc = pdtch_encode(*bursts_p, msg->l2h, msg->tail - msg->l2h);
+	rc = pdtch_egprs_encode(*bursts_p, msg->l2h, msg->tail - msg->l2h);
+	if (rc < 0)
+		rc = pdtch_encode(*bursts_p, msg->l2h, msg->tail - msg->l2h);
 
 	/* check validity of message */
-	if (rc) {
+	if (rc < 0) {
 		LOGP(DL1C, LOGL_FATAL, "Prim invalid length, please FIX! "
-			"(len=%d)\n", rc);
+			"(len=%ld)\n", msg->tail - msg->l2h);
 		/* free message */
 		msgb_free(msg);
 		goto no_msg;
+	} else if (rc == GSM0503_EGPRS_BURSTS_NBITS) {
+		*burst_type = TRX_BURST_8PSK;
+	} else {
+		*burst_type = TRX_BURST_GMSK;
 	}
 
 	/* free message */
@@ -283,12 +305,27 @@
 
 send_burst:
 	/* compose burst */
-	burst = *bursts_p + bid * 116;
-	memset(bits, 0, 3);
-	memcpy(bits + 3, burst, 58);
-	memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
-	memcpy(bits + 87, burst + 58, 58);
-	memset(bits + 145, 0, 3);
+	if (*burst_type == TRX_BURST_8PSK) {
+		burst = *bursts_p + bid * 348;
+		memset(bits, 1, 9);
+		memcpy(bits + 9, burst, 174);
+		memcpy(bits + 183, _sched_egprs_tsc[gsm_ts_tsc(ts)], 78);
+		memcpy(bits + 261, burst + 174, 174);
+		memset(bits + 435, 1, 9);
+
+		if (nbits)
+			*nbits = EGPRS_BURST_LEN;
+	} else {
+		burst = *bursts_p + bid * 116;
+		memset(bits, 0, 3);
+		memcpy(bits + 3, burst, 58);
+		memcpy(bits + 61, _sched_tsc[gsm_ts_tsc(ts)], 26);
+		memcpy(bits + 87, burst + 58, 58);
+		memset(bits + 145, 0, 3);
+
+		if (nbits)
+			*nbits = GSM_BURST_LEN;
+	}
 
 	LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
@@ -528,7 +565,7 @@
 }
 
 ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid)
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
 {
 	struct msgb *msg_tch = NULL, *msg_facch = NULL;
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
@@ -536,7 +573,7 @@
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
 	uint8_t tch_mode = chan_state->tch_mode;
 	ubit_t *burst, **bursts_p = &chan_state->dl_bursts;
-	static ubit_t bits[148];
+	static ubit_t bits[GSM_BURST_LEN];
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
@@ -600,6 +637,9 @@
 	memcpy(bits + 87, burst + 58, 58);
 	memset(bits + 145, 0, 3);
 
+	if (nbits)
+		*nbits = GSM_BURST_LEN;
+
 	LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
 
@@ -607,7 +647,7 @@
 }
 
 ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid)
+	enum trx_chan_type chan, uint8_t bid, uint16_t *nbits)
 {
 	struct msgb *msg_tch = NULL, *msg_facch = NULL;
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
@@ -615,7 +655,7 @@
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
 	uint8_t tch_mode = chan_state->tch_mode;
 	ubit_t *burst, **bursts_p = &chan_state->dl_bursts;
-	static ubit_t bits[148];
+	static ubit_t bits[GSM_BURST_LEN];
 
 	/* send burst, if we already got a frame */
 	if (bid > 0) {
@@ -696,6 +736,9 @@
 	memcpy(bits + 87, burst + 58, 58);
 	memset(bits + 145, 0, 3);
 
+	if (nbits)
+		*nbits = GSM_BURST_LEN;
+
 	LOGP(DL1C, LOGL_DEBUG, "Transmitting %s fn=%u ts=%u trx=%u burst=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
 
@@ -708,8 +751,8 @@
  */
 
 int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa)
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa)
 {
 	uint8_t chan_nr;
 	struct osmo_phsap_prim l1sap;
@@ -751,8 +794,8 @@
 
 /*! \brief a single burst was received by the PHY, process it */
 int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa)
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
@@ -769,7 +812,7 @@
 
 	/* handle rach, if handover rach detection is turned on */
 	if (chan_state->ho_rach_detect == 1)
-		return rx_rach_fn(l1t, tn, fn, chan, bid, bits, rssi, toa);
+		return rx_rach_fn(l1t, tn, fn, chan, bid, bits, GSM_BURST_LEN, rssi, toa);
 
 	LOGP(DL1C, LOGL_DEBUG, "Data received %s fn=%u ts=%u trx=%u bid=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
@@ -848,8 +891,8 @@
 }
 
 int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa)
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
@@ -859,8 +902,8 @@
 	uint8_t *rssi_num = &chan_state->rssi_num;
 	float *toa_sum = &chan_state->toa_sum;
 	uint8_t *toa_num = &chan_state->toa_num;
-	uint8_t l2[54];
-	int n_errors, n_bits_total;
+	uint8_t l2[EGPRS_0503_MAX_BYTES];
+	int n_errors, n_bursts_bits, n_bits_total;
 	int rc;
 
 	LOGP(DL1C, LOGL_DEBUG, "PDTCH received %s fn=%u ts=%u trx=%u bid=%u\n", 
@@ -868,14 +911,15 @@
 
 	/* alloc burst memory, if not already */
 	if (!*bursts_p) {
-		*bursts_p = talloc_zero_size(tall_bts_ctx, 464);
+		*bursts_p = talloc_zero_size(tall_bts_ctx,
+					     GSM0503_EGPRS_BURSTS_NBITS);
 		if (!*bursts_p)
 			return -ENOMEM;
 	}
 
 	/* clear burst */
 	if (bid == 0) {
-		memset(*bursts_p, 0, 464);
+		memset(*bursts_p, 0, GSM0503_EGPRS_BURSTS_NBITS);
 		*mask = 0x0;
 		*rssi_sum = 0;
 		*rssi_num = 0;
@@ -891,9 +935,17 @@
 	(*toa_num)++;
 
 	/* copy burst to buffer of 4 bursts */
-	burst = *bursts_p + bid * 116;
-	memcpy(burst, bits + 3, 58);
-	memcpy(burst + 58, bits + 87, 58);
+	if (nbits == EGPRS_BURST_LEN) {
+		burst = *bursts_p + bid * 348;
+		memcpy(burst, bits + 9, 174);
+		memcpy(burst + 174, bits + 261, 174);
+		n_bursts_bits = GSM0503_EGPRS_BURSTS_NBITS;
+	} else {
+		burst = *bursts_p + bid * 116;
+		memcpy(burst, bits + 3, 58);
+		memcpy(burst + 58, bits + 87, 58);
+		n_bursts_bits = GSM0503_GPRS_BURSTS_NBITS;
+	}
 
 	/* wait until complete set of bursts */
 	if (bid != 3)
@@ -908,8 +960,20 @@
 	}
 	*mask = 0x0;
 
-	/* decode */
-	rc = pdtch_decode(l2, *bursts_p, NULL, &n_errors, &n_bits_total);
+	/*
+	 * Attempt to decode EGPRS bursts first. For 8-PSK EGPRS this is all we
+	 * do. Attempt GPRS decoding on EGPRS failure. If the burst is GPRS,
+	 * then we incur decoding overhead of 31 bits on the Type 3 EGPRS
+	 * header, which is tolerable.
+	 */
+	rc = pdtch_egprs_decode(l2, *bursts_p, n_bursts_bits,
+				NULL, &n_errors, &n_bits_total);
+
+	if ((nbits == GSM_BURST_LEN) && (rc < 0)) {
+		rc = pdtch_decode(l2, *bursts_p, NULL,
+				  &n_errors, &n_bits_total);
+	}
+
 
 	/* Send uplnk measurement information to L2 */
 	l1if_process_meas_res(l1t->trx, tn, fn, trx_chan_desc[chan].chan_nr | tn,
@@ -927,8 +991,8 @@
 }
 
 int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa)
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
@@ -944,7 +1008,7 @@
 
 	/* handle rach, if handover rach detection is turned on */
 	if (chan_state->ho_rach_detect == 1)
-		return rx_rach_fn(l1t, tn, fn, chan, bid, bits, rssi, toa);
+		return rx_rach_fn(l1t, tn, fn, chan, bid, bits, GSM_BURST_LEN, rssi, toa);
 
 	LOGP(DL1C, LOGL_DEBUG, "TCH/F received %s fn=%u ts=%u trx=%u bid=%u\n", 
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
@@ -1083,8 +1147,8 @@
 }
 
 int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
-	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, int8_t rssi,
-	float toa)
+	enum trx_chan_type chan, uint8_t bid, sbit_t *bits, uint16_t nbits,
+	int8_t rssi, float toa)
 {
 	struct l1sched_ts *l1ts = l1sched_trx_get_ts(l1t, tn);
 	struct l1sched_chan_state *chan_state = &l1ts->chan_state[chan];
@@ -1100,7 +1164,7 @@
 
 	/* handle rach, if handover rach detection is turned on */
 	if (chan_state->ho_rach_detect == 1)
-		return rx_rach_fn(l1t, tn, fn, chan, bid, bits, rssi, toa);
+		return rx_rach_fn(l1t, tn, fn, chan, bid, bits, GSM_BURST_LEN, rssi, toa);
 
 	LOGP(DL1C, LOGL_DEBUG, "TCH/H received %s fn=%u ts=%u trx=%u bid=%u\n",
 		trx_chan_desc[chan].name, fn, tn, l1t->trx->nr, bid);
@@ -1263,6 +1327,7 @@
 	uint8_t tn;
 	const ubit_t *bits;
 	uint8_t gain;
+	uint16_t nbits;
 
 	/* send time indication */
 	l1if_mph_time_ind(bts, fn);
@@ -1288,13 +1353,13 @@
 			_sched_rts(l1t, tn,
 				(fn + plink->u.osmotrx.rts_advance) % GSM_HYPERFRAME);
 			/* get burst for FN */
-			bits = _sched_dl_burst(l1t, tn, fn);
+			bits = _sched_dl_burst(l1t, tn, fn, &nbits);
 			if (!bits) {
 				/* if no bits, send no burst */
 				continue;
 			} else
 				gain = 0;
-			trx_if_data(l1h, tn, fn, gain, bits);
+			trx_if_data(l1h, tn, fn, gain, bits, nbits);
 		}
 	}
 
diff --git a/src/osmo-bts-trx/trx_if.c b/src/osmo-bts-trx/trx_if.c
index b2766d0..bef6c09 100644
--- a/src/osmo-bts-trx/trx_if.c
+++ b/src/osmo-bts-trx/trx_if.c
@@ -50,6 +50,8 @@
 int settsc_enabled = 0;
 int setbsic_enabled = 0;
 
+#define TRX_MAX_BURST_LEN	512
+
 /*
  * socket
  */
@@ -406,19 +408,21 @@
 static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
 {
 	struct trx_l1h *l1h = ofd->data;
-	uint8_t buf[256];
+	uint8_t buf[TRX_MAX_BURST_LEN];
 	int len;
 	uint8_t tn;
 	int8_t rssi;
 	float toa = 0.0;
 	uint32_t fn;
-	sbit_t bits[148];
-	int i;
+	sbit_t bits[EGPRS_BURST_LEN];
+	int i, burst_len = GSM_BURST_LEN;
 
 	len = recv(ofd->fd, buf, sizeof(buf), 0);
-	if (len <= 0)
+	if (len <= 0) {
 		return len;
-	if (len != 158) {
+	} else if (len == EGPRS_BURST_LEN + 10) {
+		burst_len = EGPRS_BURST_LEN;
+	} else if (len != GSM_BURST_LEN + 10) {
 		LOGP(DTRX, LOGL_NOTICE, "Got data message with invalid lenght "
 			"'%d'\n", len);
 		return -EINVAL;
@@ -429,7 +433,7 @@
 	toa = ((int16_t)(buf[6] << 8) | buf[7]) / 256.0F;
 
 	/* copy and convert bits {254..0} to sbits {-127..127} */
-	for (i = 0; i < 148; i++) {
+	for (i = 0; i < burst_len; i++) {
 		if (buf[8 + i] == 255)
 			bits[i] = -127;
 		else
@@ -457,15 +461,20 @@
 	fprintf(stderr, "%s\n", deb);
 #endif
 
-	trx_sched_ul_burst(&l1h->l1s, tn, fn, bits, rssi, toa);
+	trx_sched_ul_burst(&l1h->l1s, tn, fn, bits, burst_len, rssi, toa);
 
 	return 0;
 }
 
 int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
-	const ubit_t *bits)
+	const ubit_t *bits, uint16_t nbits)
 {
-	uint8_t buf[256];
+	uint8_t buf[TRX_MAX_BURST_LEN];
+
+	if ((nbits != GSM_BURST_LEN) && (nbits != EGPRS_BURST_LEN)) {
+		LOGP(DTRX, LOGL_ERROR, "Tx burst length %u invalid\n", nbits);
+		return -1;
+	}
 
 	LOGP(DTRX, LOGL_DEBUG, "TX burst tn=%u fn=%u pwr=%u\n", tn, fn, pwr);
 
@@ -477,12 +486,12 @@
 	buf[5] = pwr;
 
 	/* copy ubits {0,1} */
-	memcpy(buf + 6, bits, 148);
+	memcpy(buf + 6, bits, nbits);
 
 	/* we must be sure that we have clock, and we have sent all control
 	 * data */
 	if (transceiver_available && llist_empty(&l1h->trx_ctrl_list)) {
-		send(l1h->trx_ofd_data.fd, buf, 154, 0);
+		send(l1h->trx_ofd_data.fd, buf, nbits + 6, 0);
 	} else
 		LOGP(DTRX, LOGL_DEBUG, "Ignoring TX data, transceiver "
 			"offline.\n");
diff --git a/src/osmo-bts-trx/trx_if.h b/src/osmo-bts-trx/trx_if.h
index 1ea0da9..8659c4a 100644
--- a/src/osmo-bts-trx/trx_if.h
+++ b/src/osmo-bts-trx/trx_if.h
@@ -28,7 +28,7 @@
 int trx_if_cmd_handover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);
 int trx_if_cmd_nohandover(struct trx_l1h *l1h, uint8_t tn, uint8_t ss);
 int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
-	const ubit_t *bits);
+	const ubit_t *bits, uint16_t nbits);
 int trx_if_open(struct trx_l1h *l1h);
 void trx_if_flush(struct trx_l1h *l1h);
 void trx_if_close(struct trx_l1h *l1h);

-- 
To view, visit https://gerrit.osmocom.org/483
To unsubscribe, visit https://gerrit.osmocom.org/settings

Gerrit-MessageType: merged
Gerrit-Change-Id: I90b46b46b11b6ce280e7f8232d5a2fccec2d4f18
Gerrit-PatchSet: 5
Gerrit-Project: osmo-bts
Gerrit-Branch: master
Gerrit-Owner: Tom Tsou <tom at tsou.cc>
Gerrit-Reviewer: Harald Welte <laforge at gnumonks.org>
Gerrit-Reviewer: Holger Freyther <holger at freyther.de>
Gerrit-Reviewer: Jenkins Builder
Gerrit-Reviewer: Tom Tsou <tom at tsou.cc>
Gerrit-Reviewer: ttsou <tom at tsou.cc>



More information about the gerrit-log mailing list