FreeCalypso > hg > ice1-trau-tester
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 } |