mirror of
https://gitea.osmocom.org/cellular-infrastructure/osmo-bts.git
synced 2025-10-23 08:22:10 +00:00
csd_v110: handle TCH/F14.4
Thanks to the work done by Mychaela (see the related Change-IDs), we can finally implement handling of TCH/F14.4 (both T and NT modes) for osmo-bts-trx and osmo-bts-virtual. This channel mode is special in a way that it employs a different rate adaptation function RAA' (defined in 3GPP TS 48.020 chapter 11), which converts between between 290-bit blocks used on Um and Abis-E1 interfaces (E-TRAU frames on the latter) and A-TRAU frames spoken over the A interface. The result of function RAA' in the Uplink direction is 320 bits, which is equal to 4 x 80-bit V.110 frames, but actually carrying 8 x 36-bit packed frames. These 320 bits are then fed to the RA2 function, like we do for other CSD channel modes. Change-Id: I3c3bef0bd2f72b8381597b5699e2060165b702a0 Depends: libosmo-abis.git I11fc1529f5be88fa778c7e05cb11eef58a389d40 Depends: libosmo-abis.git I1347a25ce97d5022502ee9112caded66315b09a4 Related: OS#6167
This commit is contained in:
committed by
Vadim Yanitskiy
parent
7b712121b8
commit
5bd8543a5f
@@ -8,3 +8,4 @@
|
|||||||
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
# If any interfaces have been removed or changed since the last public release: c:r:0.
|
||||||
#library what description / commit summary line
|
#library what description / commit summary line
|
||||||
libosmotrau >1.6.0 osmo_csd_ra2_{16k,8k}_{pack,unpack}() API
|
libosmotrau >1.6.0 osmo_csd_ra2_{16k,8k}_{pack,unpack}() API
|
||||||
|
libosmotrau >1.6.0 osmo_csd144_{to,from}_atrau_bits() API
|
||||||
|
@@ -896,8 +896,8 @@ static bool bts_supports_cm_data(const struct gsm_bts *bts,
|
|||||||
switch (bts->variant) {
|
switch (bts->variant) {
|
||||||
case BTS_OSMO_TRX:
|
case BTS_OSMO_TRX:
|
||||||
switch (cm->chan_rate) {
|
switch (cm->chan_rate) {
|
||||||
/* TODO: RSL_CMOD_CSD_NT_14k5 */
|
case RSL_CMOD_CSD_NT_14k5:
|
||||||
/* TODO: RSL_CMOD_CSD_T_14k4 */
|
case RSL_CMOD_CSD_T_14k4:
|
||||||
case RSL_CMOD_CSD_NT_12k0:
|
case RSL_CMOD_CSD_NT_12k0:
|
||||||
case RSL_CMOD_CSD_T_9k6:
|
case RSL_CMOD_CSD_T_9k6:
|
||||||
if (cm->chan_rt != RSL_CMOD_CRT_TCH_Bm)
|
if (cm->chan_rt != RSL_CMOD_CRT_TCH_Bm)
|
||||||
|
@@ -30,13 +30,13 @@
|
|||||||
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
#include <osmocom/gsm/protocol/gsm_04_08.h>
|
||||||
#include <osmocom/isdn/v110.h>
|
#include <osmocom/isdn/v110.h>
|
||||||
#include <osmocom/trau/csd_ra2.h>
|
#include <osmocom/trau/csd_ra2.h>
|
||||||
|
#include <osmocom/trau/csd_raa_prime.h>
|
||||||
|
|
||||||
#include <osmo-bts/csd_v110.h>
|
#include <osmo-bts/csd_v110.h>
|
||||||
#include <osmo-bts/lchan.h>
|
#include <osmo-bts/lchan.h>
|
||||||
|
|
||||||
/* key is enum gsm48_chan_mode, so assuming a value in range 0..255 */
|
/* key is enum gsm48_chan_mode, so assuming a value in range 0..255 */
|
||||||
const struct csd_v110_lchan_desc csd_v110_lchan_desc[256] = {
|
const struct csd_v110_lchan_desc csd_v110_lchan_desc[256] = {
|
||||||
#if 0
|
|
||||||
[GSM48_CMODE_DATA_14k5] = {
|
[GSM48_CMODE_DATA_14k5] = {
|
||||||
/* TCH/F14.4: 8 * 36 + 2 bits every 20 ms (14.5 kbit/s) */
|
/* TCH/F14.4: 8 * 36 + 2 bits every 20 ms (14.5 kbit/s) */
|
||||||
.num_frames = 8,
|
.num_frames = 8,
|
||||||
@@ -44,7 +44,6 @@ const struct csd_v110_lchan_desc csd_v110_lchan_desc[256] = {
|
|||||||
.num_other_bits = 2, /* M-bits */
|
.num_other_bits = 2, /* M-bits */
|
||||||
.ra2_ir = 16,
|
.ra2_ir = 16,
|
||||||
},
|
},
|
||||||
#endif
|
|
||||||
[GSM48_CMODE_DATA_12k0] = {
|
[GSM48_CMODE_DATA_12k0] = {
|
||||||
/* TCH/F9.6: 4 * 60 bits every 20 ms (12.0 kbit/s) */
|
/* TCH/F9.6: 4 * 60 bits every 20 ms (12.0 kbit/s) */
|
||||||
.num_frames = 4,
|
.num_frames = 4,
|
||||||
@@ -92,6 +91,32 @@ int csd_v110_rtp_encode(const struct gsm_lchan *lchan, uint8_t *rtp,
|
|||||||
if (OSMO_UNLIKELY(desc->num_frames == 0))
|
if (OSMO_UNLIKELY(desc->num_frames == 0))
|
||||||
return -ENOTSUP;
|
return -ENOTSUP;
|
||||||
|
|
||||||
|
/* TCH/F14.4 is special: RAA' function is employed */
|
||||||
|
if (lchan->tch_mode == GSM48_CMODE_DATA_14k5) {
|
||||||
|
/* 3GPP TS 44.021, section 10.3 "TCH/F14.4 channel coding"
|
||||||
|
* 3GPP TS 48.020, chapter 11 "THE RAA' FUNCTION" */
|
||||||
|
const ubit_t *m_bits = &data[0]; /* M-bits */
|
||||||
|
const ubit_t *d_bits = &data[2]; /* D-bits */
|
||||||
|
ubit_t c4, c5;
|
||||||
|
|
||||||
|
/* 3GPP TS 48.020, Table 3
|
||||||
|
* | C4 | Date Rate |
|
||||||
|
* | =1 | 14,4 kbit/s |
|
||||||
|
* | =0 | 14.4 kbit/s idle (IWF to BSS only) | */
|
||||||
|
c4 = 1;
|
||||||
|
/* 3GPP TS 48.020, Table 4
|
||||||
|
* | C5 | BSS to IWF FT | IWF to BSS UFE |
|
||||||
|
* | =1 | idle | framing error |
|
||||||
|
* | =0 | data | no framing error | */
|
||||||
|
c5 = 0;
|
||||||
|
|
||||||
|
/* Unless there is a bug, it's highly unlikely */
|
||||||
|
OSMO_ASSERT(data_len == CSD_V110_NUM_BITS(desc));
|
||||||
|
|
||||||
|
osmo_csd144_to_atrau_bits(&ra_bits[0], m_bits, d_bits, c4, c5);
|
||||||
|
goto ra1_ra2;
|
||||||
|
}
|
||||||
|
|
||||||
/* handle empty/incomplete Uplink frames gracefully */
|
/* handle empty/incomplete Uplink frames gracefully */
|
||||||
if (OSMO_UNLIKELY(data_len < CSD_V110_NUM_BITS(desc))) {
|
if (OSMO_UNLIKELY(data_len < CSD_V110_NUM_BITS(desc))) {
|
||||||
/* encode N idle frames as per 3GPP TS 44.021, section 8.1.6 */
|
/* encode N idle frames as per 3GPP TS 44.021, section 8.1.6 */
|
||||||
@@ -178,6 +203,18 @@ int csd_v110_rtp_decode(const struct gsm_lchan *lchan, uint8_t *data,
|
|||||||
else /* desc->ra2_ir == 8 */
|
else /* desc->ra2_ir == 8 */
|
||||||
osmo_csd_ra2_8k_unpack(&ra_bits[0], &rtp[0], RFC4040_RTP_PLEN);
|
osmo_csd_ra2_8k_unpack(&ra_bits[0], &rtp[0], RFC4040_RTP_PLEN);
|
||||||
|
|
||||||
|
/* TCH/F14.4 is special: RAA' function is employed */
|
||||||
|
if (lchan->tch_mode == GSM48_CMODE_DATA_14k5) {
|
||||||
|
/* 3GPP TS 44.021, section 10.3 "TCH/F14.4 channel coding"
|
||||||
|
* 3GPP TS 48.020, chapter 11 "THE RAA' FUNCTION" */
|
||||||
|
ubit_t *m_bits = &data[0]; /* M-bits */
|
||||||
|
ubit_t *d_bits = &data[2]; /* D-bits */
|
||||||
|
int rc;
|
||||||
|
|
||||||
|
rc = osmo_csd144_from_atrau_bits(m_bits, d_bits, NULL, NULL, &ra_bits[0]);
|
||||||
|
return rc == 0 ? CSD_V110_NUM_BITS(desc) : rc;
|
||||||
|
}
|
||||||
|
|
||||||
/* RA1'/RA1: convert from an intermediate rate to radio rate */
|
/* RA1'/RA1: convert from an intermediate rate to radio rate */
|
||||||
for (unsigned int i = 0; i < desc->num_frames; i++) {
|
for (unsigned int i = 0; i < desc->num_frames; i++) {
|
||||||
struct osmo_v110_decoded_frame df;
|
struct osmo_v110_decoded_frame df;
|
||||||
|
@@ -196,9 +196,6 @@ int bts_model_trx_init(struct gsm_bts_trx *trx)
|
|||||||
trx->support.chan_modes = NM_IPAC_MASK_CHANM_SPEECH
|
trx->support.chan_modes = NM_IPAC_MASK_CHANM_SPEECH
|
||||||
| NM_IPAC_MASK_CHANM_CSD_NT
|
| NM_IPAC_MASK_CHANM_CSD_NT
|
||||||
| NM_IPAC_MASK_CHANM_CSD_T;
|
| NM_IPAC_MASK_CHANM_CSD_T;
|
||||||
/* TODO: missing rate adaptation for TCH/F14.4 (see OS#6167) */
|
|
||||||
trx->support.chan_modes &= ~NM_IPAC_F_CHANM_CSD_T_14k4;
|
|
||||||
trx->support.chan_modes &= ~NM_IPAC_F_CHANM_CSD_NT_14k4;
|
|
||||||
|
|
||||||
/* The nominal value for each TRX is later overwritten through VTY cmd
|
/* The nominal value for each TRX is later overwritten through VTY cmd
|
||||||
* 'nominal-tx-power' if present, otherwise through TRXC cmd NOMTXPOWER.
|
* 'nominal-tx-power' if present, otherwise through TRXC cmd NOMTXPOWER.
|
||||||
|
@@ -99,9 +99,6 @@ int bts_model_trx_init(struct gsm_bts_trx *trx)
|
|||||||
trx->support.chan_modes = NM_IPAC_MASK_CHANM_SPEECH
|
trx->support.chan_modes = NM_IPAC_MASK_CHANM_SPEECH
|
||||||
| NM_IPAC_MASK_CHANM_CSD_NT
|
| NM_IPAC_MASK_CHANM_CSD_NT
|
||||||
| NM_IPAC_MASK_CHANM_CSD_T;
|
| NM_IPAC_MASK_CHANM_CSD_T;
|
||||||
/* TODO: missing rate adaptation for TCH/F14.4 (see OS#6167) */
|
|
||||||
trx->support.chan_modes &= ~NM_IPAC_F_CHANM_CSD_T_14k4;
|
|
||||||
trx->support.chan_modes &= ~NM_IPAC_F_CHANM_CSD_NT_14k4;
|
|
||||||
|
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
@@ -145,6 +145,10 @@ static void exec_test_case(const struct test_case *tc)
|
|||||||
i, data_dec[i], data_enc[i]);
|
i, data_dec[i], data_enc[i]);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/* for TCH/F14.4, we always expect a valid block */
|
||||||
|
if (tc->tch_mode == GSM48_CMODE_DATA_14k5)
|
||||||
|
return;
|
||||||
|
|
||||||
fprintf(stderr, "[i] Testing '%s' (IDLE)\n", tc->name);
|
fprintf(stderr, "[i] Testing '%s' (IDLE)\n", tc->name);
|
||||||
|
|
||||||
/* encode an idle RTP frame and print it */
|
/* encode an idle RTP frame and print it */
|
||||||
|
@@ -1,4 +1,16 @@
|
|||||||
[i] Skipping 'TCH/F14.4' (not implemented)
|
[i] Testing 'TCH/F14.4' (bitnum=290)
|
||||||
|
[i] csd_v110_rtp_encode() returns 160
|
||||||
|
3f 3f 3f 3f 3f 3f 3f 3f bf ff bf 7f bf bf bf bf
|
||||||
|
bf bf bf bf bf bf bf bf bf bf bf bf bf bf ff 7f
|
||||||
|
7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f
|
||||||
|
7f bf bf bf bf bf bf bf bf bf bf bf bf bf bf bf
|
||||||
|
bf bf bf ff 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f
|
||||||
|
7f 7f 7f 7f 7f 7f bf bf bf bf bf bf bf bf bf bf
|
||||||
|
bf bf bf bf bf bf bf bf ff 7f 7f 7f 7f 7f 7f 7f
|
||||||
|
7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f bf bf bf bf bf
|
||||||
|
bf bf bf bf bf bf bf bf bf bf bf bf bf ff 7f 7f
|
||||||
|
7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f 7f
|
||||||
|
[i] csd_v110_rtp_decode() returns 290
|
||||||
[i] Testing 'TCH/F9.6' (bitnum=240)
|
[i] Testing 'TCH/F9.6' (bitnum=240)
|
||||||
[i] csd_v110_rtp_encode() returns 160
|
[i] csd_v110_rtp_encode() returns 160
|
||||||
3f 3f 3f 3f bf bf bf bf ff 7f 7f 7f bf bf bf bf
|
3f 3f 3f 3f bf bf bf bf ff 7f 7f 7f bf bf bf bf
|
||||||
|
Reference in New Issue
Block a user