# HG changeset patch # User Mychaela Falconia # Date 1719220854 0 # Node ID 2ee910aa03c3b6dce6407f9ee1254ab7ebd92949 # Parent 5405c157302745df051bfd04f33c974d604f90ca ater: implement TRAU frame filling diff -r 5405c1573027 -r 2ee910aa03c3 ater/Makefile --- a/ater/Makefile Mon Jun 24 08:50:29 2024 +0000 +++ b/ater/Makefile Mon Jun 24 09:20:54 2024 +0000 @@ -1,7 +1,7 @@ PROG= itt-ater-16 -OBJS= main.o read_file.o read_ts.o record_ctrl.o subslot_rx.o tx_func.o \ - user_cmd.o -HDRS= globals.h read_file.h submux.h +OBJS= main.o out_frame.o read_file.o read_ts.o record_ctrl.o subslot_rx.o \ + tx_func.o user_cmd.o +HDRS= globals.h out_frame.h read_file.h submux.h LIBUTIL=../libutil/libutil.a include ../config.defs diff -r 5405c1573027 -r 2ee910aa03c3 ater/out_frame.c --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ater/out_frame.c Mon Jun 24 09:20:54 2024 +0000 @@ -0,0 +1,147 @@ +/* + * Here we implement our TRAU-UL bit filling function. + * + * This code is based on trau_rtp_conv.c in libosmo-abis. + */ + +#include +#include +#include + +#include +#include +#include + +#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 fill_data_efr(const uint8_t *data, struct osmo_trau_frame *tf) +{ + int i, j; + ubit_t check_bits[26]; + + /* 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); +} + +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; +} diff -r 5405c1573027 -r 2ee910aa03c3 ater/out_frame.h --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/ater/out_frame.h Mon Jun 24 09:20:54 2024 +0000 @@ -0,0 +1,15 @@ +/* + * This header file defines the interface to the function that + * fills struct osmo_trau_frame based on a 34-byte binary record + * we read from our ad hoc TRAU testing file format. + */ + +#pragma once + +#include +#include + +#include + +void trau_frame_from_record(const uint8_t *rec, bool is_efr, + struct osmo_trau_frame *fr);