diff options
author | Andreas Eversberg <jolly@eversberg.eu> | 2013-02-15 16:17:43 +0100 |
---|---|---|
committer | Harald Welte <laforge@gnumonks.org> | 2015-09-22 16:41:26 +0200 |
commit | 7451ce29a79a8da6da0ac1dbf155ed4af016dcdc (patch) | |
tree | c7f482f12e0647b8cc3543531271fd565643df2f | |
parent | 450d32919ada7b037b41d89ea8dd181924ed48e9 (diff) |
TRX: Detect missing received bursts and fill them with zero-sbits
-rw-r--r-- | src/osmo-bts-trx/l1_if.h | 1 | ||||
-rw-r--r-- | src/osmo-bts-trx/scheduler.c | 95 |
2 files changed, 60 insertions, 36 deletions
diff --git a/src/osmo-bts-trx/l1_if.h b/src/osmo-bts-trx/l1_if.h index 0ed0991c..8a0a90e6 100644 --- a/src/osmo-bts-trx/l1_if.h +++ b/src/osmo-bts-trx/l1_if.h @@ -106,6 +106,7 @@ struct trx_l1h { struct trx_config config; uint8_t mf_index[8]; /* selected multiframe index */ + uint32_t mf_last_fn[8]; /* last received frame */ uint8_t mf_period[8]; /* period of multiframe */ struct trx_sched_frame *mf_frames[8]; /* pointer to frame layout */ diff --git a/src/osmo-bts-trx/scheduler.c b/src/osmo-bts-trx/scheduler.c index f44df519..31a0fcd4 100644 --- a/src/osmo-bts-trx/scheduler.c +++ b/src/osmo-bts-trx/scheduler.c @@ -207,6 +207,7 @@ int trx_sched_init(struct trx_l1h *l1h) for (tn = 0; tn < 8; tn++) { l1h->mf_index[tn] = 0; + l1h->mf_last_fn[tn] = 0; INIT_LLIST_HEAD(&l1h->dl_prims[tn]); for (i = 0; i < _TRX_CHAN_MAX; i++) { chan_state = &l1h->chan_states[tn][i]; @@ -1035,7 +1036,7 @@ static int rx_pdtch_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, l2[0] = 7; /* valid frame */ - return compose_ph_data_ind(l1h, tn, (fn + 2715648 -3) % 2715648, chan, + return compose_ph_data_ind(l1h, tn, (fn + 2715648 - 3) % 2715648, chan, l2, rc + 1); } @@ -1044,7 +1045,6 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, { struct trx_chan_state *chan_state = &l1h->chan_states[tn][chan]; sbit_t *burst, **bursts_p = &chan_state->ul_bursts; - uint32_t *first_fn = &chan_state->ul_first_fn; uint8_t *mask = &chan_state->ul_mask; uint8_t tch_data[33]; int rc; @@ -1059,11 +1059,10 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, return -ENOMEM; } - /* store frame number of first burst */ + /* clear burst */ if (bid == 0) { memset(*bursts_p + 464, 0, 464); *mask = 0x0; - *first_fn = fn; } /* update mask */ @@ -1082,16 +1081,10 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, /* check for complete set of bursts */ if ((*mask & 0xf) != 0xf) { - LOGP(DL1C, LOGL_NOTICE, "Received incomplete TCH frame at " - "fn=%u (%u/%u) for %s\n", *first_fn, - (*first_fn) % l1h->mf_period[tn], l1h->mf_period[tn], + LOGP(DL1C, LOGL_NOTICE, "Received incomplete TCH frame ending " + "at fn=%u (%u/%u) for %s\n", fn, + fn % l1h->mf_period[tn], l1h->mf_period[tn], trx_chan_desc[chan].name); - /* we require first burst to have correct FN */ - if (!(*mask & 0x1)) { - *mask = 0x0; - rc = 0; - goto bfi; - } } *mask = 0x0; @@ -1100,14 +1093,15 @@ static int rx_tchf_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, rc = tch_fr_decode(tch_data, *bursts_p, 1); memcpy(*bursts_p, *bursts_p + 464, 464); if (rc < 0) { - LOGP(DL1C, LOGL_NOTICE, "Received bad TCH frame at fn=%u " - "for %s\n", *first_fn, trx_chan_desc[chan].name); + LOGP(DL1C, LOGL_NOTICE, "Received bad TCH frame ending at " + "fn=%u for %s\n", fn, trx_chan_desc[chan].name); goto bfi; } /* FACCH */ if (rc == 23) { - compose_ph_data_ind(l1h, tn, *first_fn, chan, tch_data, 23); + compose_ph_data_ind(l1h, tn, (fn + 2715648 - 7) % 2715648, chan, + tch_data, 23); bfi: // FIXME length depends on codec rc = 33; @@ -1116,7 +1110,8 @@ bfi: } /* TCH or BFI */ - return compose_tch_ind(l1h, tn, *first_fn, chan, tch_data, rc); + return compose_tch_ind(l1h, tn, (fn + 2715648 - 7) % 2715648, chan, + tch_data, rc); } static int rx_tchh_fn(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, @@ -2054,40 +2049,68 @@ if (0) if (chan != TRXC_IDLE) // hack } /* process uplink burst */ -int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t fn, +int trx_sched_ul_burst(struct trx_l1h *l1h, uint8_t tn, uint32_t current_fn, sbit_t *bits, int8_t rssi, float toa) { struct trx_sched_frame *frame; uint8_t offset, period, bid; trx_sched_ul_func *func; enum trx_chan_type chan; - int rc; + uint32_t fn, elapsed; if (!l1h->mf_index[tn]) return -EINVAL; - /* get frame from multiframe */ - period = l1h->mf_period[tn]; - offset = fn % period; - frame = l1h->mf_frames[tn] + offset; + /* calculate how many frames have been elapsed */ + elapsed = (current_fn + 2715648 - l1h->mf_last_fn[tn]) % 2715648; - chan = frame->ul_chan; - bid = frame->ul_bid; - func = trx_chan_desc[chan].ul_fn; + /* start counting from last fn + 1, but only if not too many fn have + * been elapsed */ + if (elapsed < 10) + fn = (l1h->mf_last_fn[tn] + 1) % 2715648; + else + fn = current_fn; + + while (42) { + /* get frame from multiframe */ + period = l1h->mf_period[tn]; + offset = fn % period; + frame = l1h->mf_frames[tn] + offset; + + chan = frame->ul_chan; + bid = frame->ul_bid; + func = trx_chan_desc[chan].ul_fn; + + /* check if channel is active */ + if (!trx_chan_desc[chan].auto_active + && !l1h->chan_states[tn][chan].ul_active) + goto next_frame; + + /* omit bursts which have no handler, like IDLE bursts */ + if (!func) + goto next_frame; + + /* put burst to function */ + if (fn == current_fn) + func(l1h, tn, fn, chan, bid, bits, toa); + else { + sbit_t spare[148]; + + memset(spare, 0, 148); + func(l1h, tn, fn, chan, bid, spare, toa); + } - /* check if channel is active */ - if (!trx_chan_desc[chan].auto_active - && !l1h->chan_states[tn][chan].ul_active) - return -EINVAL; +next_frame: + /* reached current fn */ + if (fn == current_fn) + break; - /* omit bursts which have no handler, like IDLE bursts */ - if (!func) - return 0; + fn = (fn + 1) % 2715648; + } - /* put burst to function */ - rc = func(l1h, tn, fn, chan, bid, bits, toa); + l1h->mf_last_fn[tn] = fn; - return rc; + return 0; } /* schedule all frames of all TRX for given FN */ |