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:
Vadim Yanitskiy
2024-11-09 18:42:46 +07:00
committed by Vadim Yanitskiy
parent 7b712121b8
commit 5bd8543a5f
7 changed files with 59 additions and 11 deletions

View File

@@ -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

View File

@@ -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)

View File

@@ -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;

View File

@@ -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.

View File

@@ -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;
} }

View File

@@ -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 */

View File

@@ -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