diff options
author | Tom Tsou <tom.tsou@ettus.com> | 2016-07-01 00:10:31 -0700 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2016-07-28 06:18:12 +0000 |
commit | dab54b91783d5197e0129de950a705e2da2a4cb9 (patch) | |
tree | 12a5bbac7761cfa734c3cd617cc2be347991eb4a | |
parent | 9407e644b0246fadec74a45faeedb570a0c04c6b (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.h | 12 | ||||
-rw-r--r-- | include/osmo-bts/scheduler_backend.h | 43 | ||||
-rw-r--r-- | src/common/scheduler.c | 26 | ||||
-rw-r--r-- | src/osmo-bts-trx/gsm0503_coding.c | 2 | ||||
-rw-r--r-- | src/osmo-bts-trx/scheduler_trx.c | 159 | ||||
-rw-r--r-- | src/osmo-bts-trx/trx_if.c | 31 | ||||
-rw-r--r-- | src/osmo-bts-trx/trx_if.h | 2 |
7 files changed, 182 insertions, 93 deletions
diff --git a/include/osmo-bts/scheduler.h b/include/osmo-bts/scheduler.h index 090f5a52..b0387dbc 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 9c0361d3..68f0c605 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 507be789..eeaf2c13 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 fd863851..c601cac3 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 d599201c..3a6ede37 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 b2766d0e..bef6c097 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 1ea0da91..8659c4a8 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); |