FreeCalypso > hg > ice1-trau-tester
view ater/out_frame.c @ 22:bacc590ec839
ater: implement EFR CRC inversion option
author | Mychaela Falconia <falcon@freecalypso.org> |
---|---|
date | Mon, 24 Jun 2024 09:28:28 +0000 |
parents | 2ee910aa03c3 |
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; }