aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorTom Tsou <tom.tsou@ettus.com>2016-07-01 00:10:31 -0700
committerHarald Welte <laforge@gnumonks.org>2016-07-28 06:18:12 +0000
commitdab54b91783d5197e0129de950a705e2da2a4cb9 (patch)
tree12a5bbac7761cfa734c3cd617cc2be347991eb4a
parent9407e644b0246fadec74a45faeedb570a0c04c6b (diff)
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@ettus.com>
-rw-r--r--include/osmo-bts/scheduler.h12
-rw-r--r--include/osmo-bts/scheduler_backend.h43
-rw-r--r--src/common/scheduler.c26
-rw-r--r--src/osmo-bts-trx/gsm0503_coding.c2
-rw-r--r--src/osmo-bts-trx/scheduler_trx.c159
-rw-r--r--src/osmo-bts-trx/trx_if.c31
-rw-r--r--src/osmo-bts-trx/trx_if.h2
7 files changed, 182 insertions, 93 deletions
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 @@ enum trx_chan_type {
_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 @@ int trx_sched_clock(struct gsm_bts *bts, uint32_t fn);
/*! \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 int trx_sched_rts_func(struct l1sched_trx *l1t, uint8_t tn,
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 @@ int _sched_compose_tch_ind(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
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_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
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 @@ static const ubit_t dummy_burst[148] = {
};
/*! \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 @@ int _sched_rts(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn)
}
/* 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 @@ const ubit_t *_sched_dl_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn)
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 @@ if (0) if (chan != TRXC_IDLE) // hack
/* 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 @@ int trx_sched_ul_burst(struct l1sched_trx *l1t, uint8_t tn, uint32_t current_fn,
}
}
- 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 @@ int pdtch_encode(ubit_t *bursts, uint8_t *l2_data, uint8_t l2_len)
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 @@ static struct osmo_timer_list transceiver_clock_timer;
* 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,29 +69,35 @@ static struct osmo_timer_list transceiver_clock_timer;
/* 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 */
return (ubit_t *) _sched_fcch_burst;
}
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 @@ ubit_t *tx_sch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
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 @@ ubit_t *tx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
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 @@ send_burst:
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 @@ send_burst:
}
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 @@ got_msg:
/* 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 @@ got_msg:
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 @@ send_frame:
}
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 @@ ubit_t *tx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
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 @@ send_burst:
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 @@ send_burst:
}
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 @@ ubit_t *tx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
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 @@ send_burst:
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 @@ send_burst:
*/
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 @@ int rx_rach_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/*! \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 @@ int rx_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* 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_data_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
}
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 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
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 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* 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 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
(*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 @@ int rx_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
}
*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_pdtch_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
}
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 @@ int rx_tchf_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* 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 @@ bfi:
}
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 @@ int rx_tchh_fn(struct l1sched_trx *l1t, uint8_t tn, uint32_t fn,
/* 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 @@ static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn)
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 @@ static int trx_sched_fn(struct gsm_bts *bts, uint32_t fn)
_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 transceiver_available = 0;
int settsc_enabled = 0;
int setbsic_enabled = 0;
+#define TRX_MAX_BURST_LEN 512
+
/*
* socket
*/
@@ -406,19 +408,21 @@ rsp_error:
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 @@ static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
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 @@ static int trx_data_read_cb(struct osmo_fd *ofd, unsigned int what)
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 @@ int trx_if_data(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, uint8_t pwr,
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_txtune(struct trx_l1h *l1h, uint16_t arfcn);
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);