From b34faf6f8ceedcafdb10523a39fe2bcd3d7c1faf Mon Sep 17 00:00:00 2001 From: Harald Welte Date: Wed, 18 Apr 2012 20:03:18 +0200 Subject: TCH: Add support for the L1 RTP mode In L1 RTP mode, the L1 already does all the bit-shifting and re-ordering required for the RTP formats (which have different bit/nibble order than the ETSI/3GPP encodings, for some odd reason). We don't enable it by default yet, as only HR/FR/EFR work with it, but AMR has some yet to be debugged problem. Enabling USE_L1_RTP_MODE would save some CPU cycles on the ARM side. --- src/osmo-bts-sysmo/tch.c | 68 +++++++++++++++++++++++++++++++++++++++--------- 1 file changed, 55 insertions(+), 13 deletions(-) (limited to 'src/osmo-bts-sysmo/tch.c') diff --git a/src/osmo-bts-sysmo/tch.c b/src/osmo-bts-sysmo/tch.c index e9512a92..a63910f8 100644 --- a/src/osmo-bts-sysmo/tch.c +++ b/src/osmo-bts-sysmo/tch.c @@ -1,6 +1,6 @@ /* Traffic channel support for Sysmocom BTS L1 */ -/* (C) 2011 by Harald Welte +/* (C) 2011-2012 by Harald Welte * * All Rights Reserved * @@ -104,6 +104,11 @@ static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len if (!msg) return NULL; +#ifdef USE_L1_RTP_MODE + /* new L1 can deliver bits like we need them */ + cur = msgb_put(msg, GSM_FR_BYTES); + memcpy(cur, l1_payload, GSM_FR_BYTES); +#else /* step1: reverse the bit-order of each payload byte */ osmo_revbytebits_buf(l1_payload, payload_len); @@ -113,6 +118,7 @@ static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len osmo_nibble_shift_right(cur, l1_payload, GSM_FR_BITS/4); cur[0] |= 0xD0; +#endif /* USE_L1_RTP_MODE */ return msg; } @@ -126,16 +132,20 @@ static struct msgb *l1_to_rtppayload_fr(uint8_t *l1_payload, uint8_t payload_len static int rtppayload_to_l1_fr(uint8_t *l1_payload, const uint8_t *rtp_payload, unsigned int payload_len) { +#ifdef USE_L1_RTP_MODE + /* new L1 can deliver bits like we need them */ + memcpy(l1_payload, rtp_payload, GSM_FR_BYTES); +#else /* step2: we need to shift the RTP payload left by one nibble*/ osmo_nibble_shift_left_unal(l1_payload, rtp_payload, GSM_FR_BITS/4); /* step1: reverse the bit-order of each payload byte */ osmo_revbytebits_buf(l1_payload, payload_len); - +#endif /* USE_L1_RTP_MODE */ return GSM_FR_BYTES; } -#ifdef GsmL1_TchPlType_Efr +#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, uint8_t payload_len) { struct msgb *msg; @@ -145,6 +155,11 @@ static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, uint8_t payload_le if (!msg) return NULL; +#ifdef USE_L1_RTP_MODE + /* new L1 can deliver bits like we need them */ + cur = msgb_put(msg, GSM_EFR_BYTES); + memcpy(cur, l1_payload, GSM_EFR_BYTES); +#else /* step1: reverse the bit-order of each payload byte */ osmo_revbytebits_buf(l1_payload, payload_len); @@ -154,12 +169,24 @@ static struct msgb *l1_to_rtppayload_efr(uint8_t *l1_payload, uint8_t payload_le osmo_nibble_shift_right(cur, l1_payload, GSM_EFR_BITS/4); cur[0] |= 0xC0; - +#endif /* USE_L1_RTP_MODE */ return msg; } + +static int rtppayload_to_l1_efr(uint8_t *l1_payload, const uint8_t *rtp_payload, + unsigned int payload_len) +{ +#ifndef USE_L1_RTP_MODE +#error We don't support EFR with L1 that doesn't support RTP mode! #else -#warning No EFR support in L1 + memcpy(l1_payload, rtp_payload, payload_len); + + return payload_len; #endif +} +#else +#warning No EFR support in L1 +#endif /* L1_HAS_EFR */ static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len) { @@ -179,8 +206,10 @@ static struct msgb *l1_to_rtppayload_hr(uint8_t *l1_payload, uint8_t payload_len cur = msgb_put(msg, GSM_HR_BYTES); memcpy(cur, l1_payload, GSM_HR_BYTES); +#ifndef USE_L1_RTP_MODE /* reverse the bit-order of each payload byte */ osmo_revbytebits_buf(cur, GSM_HR_BYTES); +#endif /* USE_L1_RTP_MODE */ return msg; } @@ -203,8 +232,10 @@ static int rtppayload_to_l1_hr(uint8_t *l1_payload, const uint8_t *rtp_payload, memcpy(l1_payload, rtp_payload, GSM_HR_BYTES); +#ifndef USE_L1_RTP_MODE /* reverse the bit-order of each payload byte */ osmo_revbytebits_buf(l1_payload, GSM_HR_BYTES); +#endif /* USE_L1_RTP_MODE */ return GSM_HR_BYTES; } @@ -242,6 +273,10 @@ static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_le cmr = AMR_CMR_NONE; #endif +#ifdef USE_L1_RTP_MODE + cur = msgb_put(msg, amr_if2_len); + memcpy(cur, l1_payload+2, amr_if2_len); +#else /* RFC 3267 4.4.1 Payload Header */ msgb_put_u8(msg, (cmr << 4)); @@ -256,6 +291,8 @@ static struct msgb *l1_to_rtppayload_amr(uint8_t *l1_payload, uint8_t payload_le /* step2: shift everything left by one nibble */ osmo_nibble_shift_left_unal(cur, l1_payload+2, amr_if2_len*2 -1); +#endif /* USE_L1_RTP_MODE */ + return msg; } @@ -292,12 +329,19 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, uint8_t amr_if2_core_len = payload_len - 2; int rc; +#ifdef USE_L1_RTP_MODE + memcpy(l1_payload+2, rtp_payload, payload_len); +#else /* step1: shift everything right one nibble; make space for FT */ osmo_nibble_shift_right(l1_payload+2, rtp_payload+2, amr_if2_core_len*2); /* step2: reverse the bit-order within every byte of the IF2 * core frame contained in the RTP payload */ osmo_revbytebits_buf(l1_payload+2, amr_if2_core_len+1); + /* lower 4 bit of first FR2 byte contains FT */ + l1_payload[2] |= ft; +#endif /* USE_L1_RTP_MODE */ + /* CMI in downlink tells the L1 encoder which encoding function * it will use, so we have to use the frame type */ switch (ft) { @@ -358,9 +402,6 @@ static int rtppayload_to_l1_amr(uint8_t *l1_payload, const uint8_t *rtp_payload, } #endif - /* lower 4 bit of first FR2 byte contains FT */ - l1_payload[2] |= ft; - if (ft == AMR_FT_SID_AMR) { /* store the last SID frame in lchan context */ unsigned int copy_len; @@ -427,10 +468,11 @@ void bts_model_rtp_rx_cb(struct osmo_rtp_socket *rs, const uint8_t *rtp_pl, rtp_pl, rtp_pl_len); } break; -#ifdef GsmL1_TchPlType_Efr +#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) case GSM48_CMODE_SPEECH_EFR: *payload_type = GsmL1_TchPlType_Efr; - rc = FIXME; + rc = rtppayload_to_l1_efr(l1_payload, rtp_pl, + rtp_pl_len); break; #endif case GSM48_CMODE_SPEECH_AMR: @@ -498,7 +540,7 @@ int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg) switch (payload_type) { case GsmL1_TchPlType_Fr: -#ifdef GsmL1_TchPlType_Efr +#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) case GsmL1_TchPlType_Efr: #endif if (lchan->type != GSM_LCHAN_TCH_F) @@ -530,8 +572,8 @@ int l1if_tch_rx(struct gsm_lchan *lchan, struct msgb *l1p_msg) case GsmL1_TchPlType_Hr: rmsg = l1_to_rtppayload_hr(payload, payload_len); break; -#ifdef GsmL1_TchPlType_Efr - case GsmL1_TchPlType_Efr +#if defined(L1_HAS_EFR) && defined(USE_L1_RTP_MODE) + case GsmL1_TchPlType_Efr: rmsg = l1_to_rtppayload_efr(payload, payload_len); break; #endif -- cgit v1.2.3