aboutsummaryrefslogtreecommitdiffstats
path: root/src/osmo-bts-trx/sched_lchan_tchf.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/osmo-bts-trx/sched_lchan_tchf.c')
-rw-r--r--src/osmo-bts-trx/sched_lchan_tchf.c44
1 files changed, 31 insertions, 13 deletions
diff --git a/src/osmo-bts-trx/sched_lchan_tchf.c b/src/osmo-bts-trx/sched_lchan_tchf.c
index 689925fb..20a40770 100644
--- a/src/osmo-bts-trx/sched_lchan_tchf.c
+++ b/src/osmo-bts-trx/sched_lchan_tchf.c
@@ -65,6 +65,7 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
uint16_t ber10k;
uint8_t is_sub = 0;
uint8_t ft;
+ bool amr_is_cmr;
/* If handover RACH detection is turned on, treat this burst as an Access Burst.
* Handle NOPE.ind as usually to ensure proper Uplink measurement reporting. */
@@ -129,6 +130,8 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
* the first FN 4,13,21 defines that CMR is included in frame.
* NOTE: A frame ends 7 FN after start.
*/
+ fn_begin = gsm0502_fn_remap(bi->fn, FN_REMAP_TCH_F);
+ amr_is_cmr = !ul_amr_fn_is_cmi(fn_begin);
/* The AFS_ONSET frame itself does not result into an RTP frame
* since it only contains a recognition pattern that marks the
@@ -144,8 +147,7 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
* know this before we actually decode the frame) */
amr = 2;
rc = gsm0503_tch_afs_decode_dtx(tch_data + amr, *bursts_p,
- (((bi->fn + 26 - 7) % 26) >> 2) & 1, chan_state->codec,
- chan_state->codecs, &chan_state->ul_ft,
+ amr_is_cmr, chan_state->codec, chan_state->codecs, &chan_state->ul_ft,
&chan_state->ul_cmr, &n_errors, &n_bits_total, &chan_state->amr_last_dtx);
/* Tag all frames that are not regular AMR voice frames as
@@ -186,7 +188,7 @@ int rx_tchf_fn(struct l1sched_ts *l1ts, const struct trx_ul_burst_ind *bi)
/* only good speech frames get rtp header */
if (rc != GSM_MACBLOCK_LEN && rc >= 4) {
if (chan_state->amr_last_dtx == AMR_OTHER) {
- ft = chan_state->codec[chan_state->ul_cmr];
+ ft = chan_state->codec[chan_state->ul_ft];
} else {
/* SID frames will always get Frame Type Index 8 (AMR_SID) */
ft = AMR_SID;
@@ -274,8 +276,8 @@ bfi:
break;
case GSM48_CMODE_SPEECH_AMR: /* AMR */
rc = osmo_amr_rtp_enc(tch_data,
- chan_state->codec[chan_state->dl_cmr],
- chan_state->codec[chan_state->dl_ft],
+ chan_state->codec[chan_state->ul_cmr],
+ chan_state->codec[chan_state->ul_ft],
AMR_BAD);
if (rc < 2) {
LOGL1SB(DL1P, LOGL_ERROR, l1ts, bi,
@@ -302,7 +304,9 @@ compose_l1sap:
return _sched_compose_tch_ind(l1ts, fn_begin, bi->chan, tch_data, rc,
/* FIXME: what should we use for BFI here? */
bfi_flag ? bi->toa256 : meas_avg.toa256, ber10k,
- bfi_flag ? bi->rssi : meas_avg.rssi, is_sub);
+ bfi_flag ? bi->rssi : meas_avg.rssi,
+ bfi_flag ? bi->ci_cb : meas_avg.ci_cb,
+ is_sub);
}
/* common section for generation of TCH bursts (TCH/H and TCH/F).
@@ -364,7 +368,7 @@ inval_mode1:
/* Note: RSSI/ToA256 is set to 0 to indicate to the higher
* layers that this is a faked tch_ind */
_sched_compose_tch_ind(l1ts, br->fn, br->chan,
- tch_data, len, 0, 10000, 0, 0);
+ tch_data, len, 0, 10000, 0, 0, 0);
}
}
@@ -419,6 +423,7 @@ inval_mode1:
enum osmo_amr_type ft_codec;
enum osmo_amr_quality bfi;
int8_t sti, cmi;
+ bool amr_is_cmr = !dl_amr_fn_is_cmi(br->fn);
if (rsl_cmode != RSL_CMOD_SPD_SPEECH) {
LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Dropping speech frame, "
@@ -463,7 +468,7 @@ inval_mode1:
"Codec (FT = %d) of RTP frame not in list\n", ft_codec);
goto free_bad_msg;
}
- if (fn_is_codec_mode_request(br->fn) && chan_state->dl_ft != ft) {
+ if (amr_is_cmr && chan_state->dl_ft != ft) {
LOGL1SB(DL1P, LOGL_NOTICE, l1ts, br, "Codec (FT = %d) "
" of RTP cannot be changed now, but in next frame\n", ft_codec);
goto free_bad_msg;
@@ -511,7 +516,7 @@ int tx_tchf_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br)
/* send burst, if we already got a frame */
if (br->bid > 0) {
if (!*bursts_p)
- return 0;
+ return -ENODEV;
goto send_burst;
}
@@ -530,22 +535,30 @@ int tx_tchf_fn(struct l1sched_ts *l1ts, struct trx_dl_burst_req *br)
memset(*bursts_p + 464, 0, 464);
}
- /* no message at all */
+ /* no message at all, send a dummy L2 frame on FACCH */
if (!msg_tch && !msg_facch) {
+ static const uint8_t dummy[GSM_MACBLOCK_LEN] = {
+ 0x03, 0x03, 0x01, /* TODO: use randomized padding */
+ 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
+ 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b, 0x2b,
+ };
+
LOGL1SB(DL1P, LOGL_INFO, l1ts, br, "No TCH or FACCH prim for transmit.\n");
+ gsm0503_tch_fr_encode(*bursts_p, dummy, sizeof(dummy), 1);
goto send_burst;
}
/* encode bursts (prioritize FACCH) */
- if (msg_facch)
+ if (msg_facch) {
gsm0503_tch_fr_encode(*bursts_p, msg_facch->l2h, msgb_l2len(msg_facch),
1);
- else if (tch_mode == GSM48_CMODE_SPEECH_AMR)
+ chan_state->dl_facch_bursts = 8;
+ } else if (tch_mode == GSM48_CMODE_SPEECH_AMR)
/* the first FN 4,13,21 defines that CMI is included in frame,
* the first FN 0,8,17 defines that CMR is included in frame.
*/
gsm0503_tch_afs_encode(*bursts_p, msg_tch->l2h + 2,
- msgb_l2len(msg_tch) - 2, fn_is_codec_mode_request(br->fn),
+ msgb_l2len(msg_tch) - 2, !dl_amr_fn_is_cmi(br->fn),
chan_state->codec, chan_state->codecs,
chan_state->dl_ft,
chan_state->dl_cmr);
@@ -567,6 +580,11 @@ send_burst:
br->burst_len = GSM_BURST_LEN;
+ if (chan_state->dl_facch_bursts > 0) {
+ chan_state->dl_facch_bursts--;
+ br->flags |= TRX_BR_F_FACCH;
+ }
+
LOGL1SB(DL1P, LOGL_DEBUG, l1ts, br, "Transmitting burst=%u.\n", br->bid);
return 0;