FreeCalypso > hg > ice1-trau-tester
view ater/out_frame.c @ 37:26c9535df39e
rm abis subdir: moved to e1-fake-trau repository
The present code repository is meant to contain code for talking
to a TRAU DUT, hence the name ice1-trau-tester. The different and
separate function of talking to an E1 BTS (Abis instead of Ater,
and in the opposite role) was never in scope for this project, but
that code got added here in a haste when the InSite BTS arrived
while the TRAU bring-up was still blocked. Now that we have our
Nokia TCSM2 system working and are doing TRAU experiments, let's
keep the code clean.
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Thu, 29 Aug 2024 19:02:02 +0000 |
parents | bacc590ec839 |
children |
line wrap: on
line source
/* * Here we implement our TRAU-UL bit filling function. * * This code is based on trau_rtp_conv.c in libosmo-abis. */ #include <stdint.h> #include <stdbool.h> #include <string.h> #include <osmocom/core/bits.h> #include <osmocom/core/crc8gen.h> #include <osmocom/trau/trau_frame.h> #include "out_frame.h" /* this corresponds to the bit-lengths of the individual codec * parameters as indicated in Table 1.1 of TS 46.010 */ static const uint8_t gsm_fr_map[] = { 6, 6, 5, 5, 4, 4, 3, 3, 7, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 7, 2, 2, 6, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3, 3 }; /* * EFR TRAU parity * * g(x) = x^3 + x^1 + 1 */ static const struct osmo_crc8gen_code gsm0860_efr_crc3 = { .bits = 3, .poly = 0x3, .init = 0x0, .remainder = 0x7, }; /* re-combine EFR parity bits */ static inline void efr_parity_bits_1(ubit_t *check_bits, const ubit_t *d_bits) { memcpy(check_bits + 0 , d_bits + 0, 22); memcpy(check_bits + 22 , d_bits + 24, 3); check_bits[25] = d_bits[28]; } static inline void efr_parity_bits_2(ubit_t *check_bits, const ubit_t *d_bits) { memcpy(check_bits + 0 , d_bits + 42, 10); memcpy(check_bits + 10 , d_bits + 90, 2); } static inline void efr_parity_bits_3(ubit_t *check_bits, const ubit_t *d_bits) { memcpy(check_bits + 0 , d_bits + 98, 5); check_bits[5] = d_bits[104]; memcpy(check_bits + 6 , d_bits + 143, 2); } static inline void efr_parity_bits_4(ubit_t *check_bits, const ubit_t *d_bits) { memcpy(check_bits + 0 , d_bits + 151, 10); memcpy(check_bits + 10 , d_bits + 199, 2); } static inline void efr_parity_bits_5(ubit_t *check_bits, const ubit_t *d_bits) { memcpy(check_bits + 0 , d_bits + 207, 5); check_bits[5] = d_bits[213]; memcpy(check_bits + 6 , d_bits + 252, 2); } static void fill_data_fr(const uint8_t *data, struct osmo_trau_frame *tf) { int i, j, k, l, o; /* reassemble d-bits */ i = 0; /* counts bits */ j = 4; /* counts input bits */ k = gsm_fr_map[0]-1; /* current number bit in element */ l = 0; /* counts element bits */ o = 0; /* offset output bits */ while (i < 260) { tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1; /* to avoid out-of-bounds access in gsm_fr_map[++l] */ if (i == 259) break; if (--k < 0) { o += gsm_fr_map[l]; k = gsm_fr_map[++l]-1; } i++; j++; } } static void invert_crc3(ubit_t *crc) { crc[0] = !crc[0]; crc[1] = !crc[1]; crc[2] = !crc[2]; } static void fill_data_efr(const uint8_t *data, struct osmo_trau_frame *tf) { int i, j; ubit_t check_bits[26]; uint8_t crc_inv; /* reassemble d-bits */ tf->d_bits[0] = 1; for (i = 1, j = 4; i < 39; i++, j++) tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1; efr_parity_bits_1(check_bits, tf->d_bits); osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 26, tf->d_bits + 39); for (i = 42, j = 42; i < 95; i++, j++) tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1; efr_parity_bits_2(check_bits, tf->d_bits); osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12, tf->d_bits + 95); for (i = 98, j = 95; i < 148; i++, j++) tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1; efr_parity_bits_3(check_bits, tf->d_bits); osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8, tf->d_bits + 148); for (i = 151, j = 145; i < 204; i++, j++) tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1; efr_parity_bits_4(check_bits, tf->d_bits); osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12, tf->d_bits + 204); for (i = 207, j = 198; i < 257; i++, j++) tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1; efr_parity_bits_5(check_bits, tf->d_bits); osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8, tf->d_bits + 257); /* inverted CRC option */ crc_inv = data[31]; if (crc_inv & 0x80) invert_crc3(tf->d_bits + 39); if (crc_inv & 0x40) invert_crc3(tf->d_bits + 95); if (crc_inv & 0x20) invert_crc3(tf->d_bits + 148); if (crc_inv & 0x10) invert_crc3(tf->d_bits + 204); if (crc_inv & 0x08) invert_crc3(tf->d_bits + 257); } void trau_frame_from_record(const uint8_t *rec, bool is_efr, struct osmo_trau_frame *tf) { if (is_efr) fill_data_efr(rec, tf); else fill_data_fr(rec, tf); /* set BFI and SID flags */ tf->c_bits[11] = (rec[33] & 0x80) >> 7; tf->c_bits[12] = (rec[33] & 0x02) >> 1; tf->c_bits[13] = (rec[33] & 0x01) >> 0; }