diff options
Diffstat (limited to 'src/osmo-bts-trx')
-rw-r--r-- | src/osmo-bts-trx/l1_if.c | 13 | ||||
-rw-r--r-- | src/osmo-bts-trx/scheduler_trx.c | 73 |
2 files changed, 56 insertions, 30 deletions
diff --git a/src/osmo-bts-trx/l1_if.c b/src/osmo-bts-trx/l1_if.c index 22ef2d73..db53d4c6 100644 --- a/src/osmo-bts-trx/l1_if.c +++ b/src/osmo-bts-trx/l1_if.c @@ -29,6 +29,7 @@ #include <osmocom/core/talloc.h> #include <osmocom/core/bits.h> +#include <osmocom/codec/ecu.h> #include <osmocom/gsm/abis_nm.h> #include <osmo-bts/logging.h> @@ -626,6 +627,9 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) break; } + /* attempt to allocate an Error Concealment Unit instance, if available */ + lchan->ecu_state = osmo_ecu_init(trx, lchan2ecu_codec(lchan)); + /* trx_chan_desc[] in scheduler.c uses the RSL_CHAN_OSMO_PDCH cbits * (0xc0) to indicate the need for PDTCH and PTCCH SAPI activation. * However, 0xc0 is a cbits pattern exclusively used for Osmocom style @@ -671,6 +675,10 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) break; } if (l1sap->u.info.type == PRIM_INFO_MODIFY) { + /* ECU for possibly new codec */ + if (lchan->ecu_state) + osmo_ecu_destroy(lchan->ecu_state); + lchan->ecu_state = osmo_ecu_init(trx, lchan2ecu_codec(lchan)); /* change mode */ trx_sched_set_mode(&l1h->l1s, chan_nr, lchan->rsl_cmode, lchan->tch_mode, @@ -689,6 +697,11 @@ int bts_model_l1sap_down(struct gsm_bts_trx *trx, struct osmo_phsap_prim *l1sap) "chan_nr 0x%02x\n", chan_nr); break; } + /* clear ECU state (if any) */ + if (lchan->ecu_state) { + osmo_ecu_destroy(lchan->ecu_state); + lchan->ecu_state = NULL; + } /* deactivate associated channel */ bts_model_lchan_deactivate_sacch(lchan); if (!l1sap->u.info.u.act_req.sacch_only) { diff --git a/src/osmo-bts-trx/scheduler_trx.c b/src/osmo-bts-trx/scheduler_trx.c index 12490539..45fc7012 100644 --- a/src/osmo-bts-trx/scheduler_trx.c +++ b/src/osmo-bts-trx/scheduler_trx.c @@ -1236,16 +1236,19 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, "Received bad data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); bfi_flag = true; - goto bfi; - } - if (rc < 4) { + } else if (rc < 4) { LOGL1S(DL1P, LOGL_NOTICE, l1t, bi->tn, chan, bi->fn, "Received bad data (%u/%u) with invalid codec mode %d\n", bi->fn % l1ts->mf_period, l1ts->mf_period, rc); bfi_flag = true; - goto bfi; } + if (rc != GSM_MACBLOCK_LEN && lchan->ecu_state) + osmo_ecu_frame_in(lchan->ecu_state, bfi_flag, tch_data, rc); + + if (bfi_flag) + goto bfi; + /* FACCH */ if (rc == GSM_MACBLOCK_LEN) { uint16_t ber10k = compute_ber10k(n_bits_total, n_errors); @@ -1260,21 +1263,22 @@ int rx_tchf_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, bfi: if (rsl_cmode == RSL_CMOD_SPD_SPEECH) { /* indicate bad frame */ - switch (tch_mode) { - case GSM48_CMODE_SPEECH_V1: /* FR */ - if (lchan->tch.dtx.ul_sid) { - /* DTXu: pause in progress. Push empty payload to upper layers */ - rc = 0; - goto compose_l1sap; - } + if (lchan->tch.dtx.ul_sid) { + /* DTXu: pause in progress. Push empty payload to upper layers */ + rc = 0; + goto compose_l1sap; + } - /* Perform error concealment if possible */ - rc = osmo_ecu_fr_conceal(&lchan->ecu_state.fr, tch_data); - if (rc) { - memset(tch_data, 0, GSM_FR_BYTES); - tch_data[0] = 0xd0; - } + /* If there is an ECU active on this channel, use its output */ + if (lchan->ecu_state) { + rc = osmo_ecu_frame_out(lchan->ecu_state, tch_data); + goto compose_l1sap; + } + switch (tch_mode) { + case GSM48_CMODE_SPEECH_V1: /* FR */ + memset(tch_data, 0, GSM_FR_BYTES); + tch_data[0] = 0xd0; rc = GSM_FR_BYTES; break; case GSM48_CMODE_SPEECH_EFR: /* EFR */ @@ -1306,10 +1310,6 @@ bfi: if (rsl_cmode != RSL_CMOD_SPD_SPEECH) return 0; - /* Reset ECU with a good frame */ - if (!bfi_flag && tch_mode == GSM48_CMODE_SPEECH_V1) - osmo_ecu_fr_reset(&lchan->ecu_state.fr, tch_data); - /* TCH or BFI */ compose_l1sap: return _sched_compose_tch_ind(l1t, bi->tn, @@ -1332,6 +1332,7 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, uint8_t tch_data[128]; /* just to be safe */ int rc, amr = 0; int n_errors, n_bits_total; + bool bfi_flag = false; struct gsm_lchan *lchan = get_lchan_by_chan_nr(l1t->trx, trx_chan_desc[chan].chan_nr | bi->tn); /* Note on FN-10: If we are at FN 10, we decoded an even aligned @@ -1444,15 +1445,20 @@ int rx_tchh_fn(struct l1sched_trx *l1t, enum trx_chan_type chan, LOGL1S(DL1P, LOGL_NOTICE, l1t, bi->tn, chan, bi->fn, "Received bad data (%u/%u)\n", bi->fn % l1ts->mf_period, l1ts->mf_period); - goto bfi; - } - if (rc < 4) { + bfi_flag = true; + } else if (rc < 4) { LOGL1S(DL1P, LOGL_NOTICE, l1t, bi->tn, chan, bi->fn, "Received bad data (%u/%u) with invalid codec mode %d\n", bi->fn % l1ts->mf_period, l1ts->mf_period, rc); - goto bfi; + bfi_flag = true; } + if (rc != GSM_MACBLOCK_LEN && lchan->ecu_state) + osmo_ecu_frame_in(lchan->ecu_state, bfi_flag, tch_data, rc); + + if (bfi_flag) + goto bfi; + /* FACCH */ if (rc == GSM_MACBLOCK_LEN) { chan_state->ul_ongoing_facch = 1; @@ -1470,13 +1476,20 @@ bfi: * so we actually need to send two bad frame indications! */ if (rsl_cmode == RSL_CMOD_SPD_SPEECH) { /* indicate bad frame */ + if (lchan->tch.dtx.ul_sid) { + /* DTXu: pause in progress. Push empty payload to upper layers */ + rc = 0; + goto compose_l1sap; + } + + /* If there is an ECU active on this channel, use its output */ + if (lchan->ecu_state) { + rc = osmo_ecu_frame_out(lchan->ecu_state, tch_data); + goto compose_l1sap; + } + switch (tch_mode) { case GSM48_CMODE_SPEECH_V1: /* HR */ - if (lchan->tch.dtx.ul_sid) { - /* DTXu: pause in progress. Push empty payload to upper layers */ - rc = 0; - goto compose_l1sap; - } tch_data[0] = 0x70; /* F = 0, FT = 111 */ memset(tch_data + 1, 0, 14); rc = 15; |