comparison ater/out_frame.c @ 21:2ee910aa03c3

ater: implement TRAU frame filling
author Mychaela Falconia <falcon@freecalypso.org>
date Mon, 24 Jun 2024 09:20:54 +0000
parents
children bacc590ec839
comparison
equal deleted inserted replaced
20:5405c1573027 21:2ee910aa03c3
1 /*
2 * Here we implement our TRAU-UL bit filling function.
3 *
4 * This code is based on trau_rtp_conv.c in libosmo-abis.
5 */
6
7 #include <stdint.h>
8 #include <stdbool.h>
9 #include <string.h>
10
11 #include <osmocom/core/bits.h>
12 #include <osmocom/core/crc8gen.h>
13 #include <osmocom/trau/trau_frame.h>
14
15 #include "out_frame.h"
16
17 /* this corresponds to the bit-lengths of the individual codec
18 * parameters as indicated in Table 1.1 of TS 46.010 */
19 static const uint8_t gsm_fr_map[] = {
20 6, 6, 5, 5, 4, 4, 3, 3,
21 7, 2, 2, 6, 3, 3, 3, 3,
22 3, 3, 3, 3, 3, 3, 3, 3,
23 3, 7, 2, 2, 6, 3, 3, 3,
24 3, 3, 3, 3, 3, 3, 3, 3,
25 3, 3, 7, 2, 2, 6, 3, 3,
26 3, 3, 3, 3, 3, 3, 3, 3,
27 3, 3, 3, 7, 2, 2, 6, 3,
28 3, 3, 3, 3, 3, 3, 3, 3,
29 3, 3, 3, 3
30 };
31
32 /*
33 * EFR TRAU parity
34 *
35 * g(x) = x^3 + x^1 + 1
36 */
37 static const struct osmo_crc8gen_code gsm0860_efr_crc3 = {
38 .bits = 3,
39 .poly = 0x3,
40 .init = 0x0,
41 .remainder = 0x7,
42 };
43
44 /* re-combine EFR parity bits */
45 static inline void efr_parity_bits_1(ubit_t *check_bits, const ubit_t *d_bits)
46 {
47 memcpy(check_bits + 0 , d_bits + 0, 22);
48 memcpy(check_bits + 22 , d_bits + 24, 3);
49 check_bits[25] = d_bits[28];
50 }
51
52 static inline void efr_parity_bits_2(ubit_t *check_bits, const ubit_t *d_bits)
53 {
54 memcpy(check_bits + 0 , d_bits + 42, 10);
55 memcpy(check_bits + 10 , d_bits + 90, 2);
56 }
57
58 static inline void efr_parity_bits_3(ubit_t *check_bits, const ubit_t *d_bits)
59 {
60 memcpy(check_bits + 0 , d_bits + 98, 5);
61 check_bits[5] = d_bits[104];
62 memcpy(check_bits + 6 , d_bits + 143, 2);
63 }
64
65 static inline void efr_parity_bits_4(ubit_t *check_bits, const ubit_t *d_bits)
66 {
67 memcpy(check_bits + 0 , d_bits + 151, 10);
68 memcpy(check_bits + 10 , d_bits + 199, 2);
69 }
70
71 static inline void efr_parity_bits_5(ubit_t *check_bits, const ubit_t *d_bits)
72 {
73 memcpy(check_bits + 0 , d_bits + 207, 5);
74 check_bits[5] = d_bits[213];
75 memcpy(check_bits + 6 , d_bits + 252, 2);
76 }
77
78 static void fill_data_fr(const uint8_t *data, struct osmo_trau_frame *tf)
79 {
80 int i, j, k, l, o;
81
82 /* reassemble d-bits */
83 i = 0; /* counts bits */
84 j = 4; /* counts input bits */
85 k = gsm_fr_map[0]-1; /* current number bit in element */
86 l = 0; /* counts element bits */
87 o = 0; /* offset output bits */
88 while (i < 260) {
89 tf->d_bits[k+o] = (data[j/8] >> (7-(j%8))) & 1;
90 /* to avoid out-of-bounds access in gsm_fr_map[++l] */
91 if (i == 259)
92 break;
93 if (--k < 0) {
94 o += gsm_fr_map[l];
95 k = gsm_fr_map[++l]-1;
96 }
97 i++;
98 j++;
99 }
100 }
101
102 static void fill_data_efr(const uint8_t *data, struct osmo_trau_frame *tf)
103 {
104 int i, j;
105 ubit_t check_bits[26];
106
107 /* reassemble d-bits */
108 tf->d_bits[0] = 1;
109 for (i = 1, j = 4; i < 39; i++, j++)
110 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
111 efr_parity_bits_1(check_bits, tf->d_bits);
112 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 26,
113 tf->d_bits + 39);
114 for (i = 42, j = 42; i < 95; i++, j++)
115 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
116 efr_parity_bits_2(check_bits, tf->d_bits);
117 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
118 tf->d_bits + 95);
119 for (i = 98, j = 95; i < 148; i++, j++)
120 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
121 efr_parity_bits_3(check_bits, tf->d_bits);
122 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
123 tf->d_bits + 148);
124 for (i = 151, j = 145; i < 204; i++, j++)
125 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
126 efr_parity_bits_4(check_bits, tf->d_bits);
127 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 12,
128 tf->d_bits + 204);
129 for (i = 207, j = 198; i < 257; i++, j++)
130 tf->d_bits[i] = (data[j/8] >> (7-(j%8))) & 1;
131 efr_parity_bits_5(check_bits, tf->d_bits);
132 osmo_crc8gen_set_bits(&gsm0860_efr_crc3, check_bits, 8,
133 tf->d_bits + 257);
134 }
135
136 void trau_frame_from_record(const uint8_t *rec, bool is_efr,
137 struct osmo_trau_frame *tf)
138 {
139 if (is_efr)
140 fill_data_efr(rec, tf);
141 else
142 fill_data_fr(rec, tf);
143 /* set BFI and SID flags */
144 tf->c_bits[11] = (rec[33] & 0x80) >> 7;
145 tf->c_bits[12] = (rec[33] & 0x02) >> 1;
146 tf->c_bits[13] = (rec[33] & 0x01) >> 0;
147 }