blob: 724cf091a159414915db1e5aa94949860b91d939 [file] [log] [blame]
Philipp Maier898c9c62020-02-06 14:25:01 +01001/*
2 * (C) 2020 by sysmocom - s.f.m.c. GmbH, Author: Philipp Maier
3 * All Rights Reserved
4 *
5 * SPDX-License-Identifier: GPL-2.0+
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License
18 * along with this program. If not, see <http://www.gnu.org/licenses/>.
19 *
20 */
21
22#include <stdio.h>
23#include <stdint.h>
24#include <string.h>
25#include <stdlib.h>
26#include <errno.h>
27
28#include <osmocom/core/bits.h>
29#include <osmocom/core/conv.h>
30#include <osmocom/core/utils.h>
31#include <osmocom/coding/gsm0503_amr_dtx.h>
32#include <osmocom/coding/gsm0503_parity.h>
33#include <osmocom/gsm/gsm0503.h>
34
35/* See also: 3GPP TS 05.03, chapter 3.10.1.3, 3.10.5.2 Identification marker */
36static const ubit_t id_marker_1[] = { 1, 0, 1, 1, 0, 0, 0, 0, 1 };
37
38/* See also: 3GPP TS 05.03, chapter 3.9.1.3, 3.10.2.2, 3.10.2.2 Identification marker */
39static const ubit_t id_marker_0[] = { 0, 1, 0, 0, 1, 1, 1, 1, 0 };
40
41/* See also: 3GPP TS 05.03, chapter 3.9 Adaptive multi rate speech channel at full rate (TCH/AFS) */
42static const ubit_t codec_mode_1_sid[] = { 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0 };
43static const ubit_t codec_mode_2_sid[] = { 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0 };
44static const ubit_t codec_mode_3_sid[] = { 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 1 };
45static const ubit_t codec_mode_4_sid[] = { 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1 };
46
47const struct value_string gsm0503_amr_dtx_frame_names[] = {
48 { AFS_SID_FIRST, "AFS_SID_FIRST" },
49 { AFS_SID_UPDATE, "AFS_SID_UPDATE" },
50 { AFS_ONSET, "AFS_ONSET" },
51 { AHS_SID_UPDATE, "AHS_SID_UPDATE" },
52 { AHS_SID_FIRST_P1, "AHS_SID_FIRST_P1" },
53 { AHS_SID_FIRST_P2, "AHS_SID_FIRST_P2" },
54 { AHS_ONSET, "AHS_ONSET" },
55 { AHS_SID_FIRST_INH, "AHS_SID_FIRST_INH" },
56 { AHS_SID_UPDATE_INH, "AHS_SID_UPDATE_INH" },
57 { AMR_OTHER, "NON DTX FRAME (OTHER)" },
58 { 0, NULL }
59};
60
61static bool detect_afs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, uint8_t offset, uint8_t count,
62 const ubit_t * id_marker, uint8_t id_marker_len)
63{
64 unsigned int i, k;
65 unsigned int id_bit_nr = 0;
66 int errors = 0;
67 int bits = 0;
68
69 /* Override coded in-band data */
70 ubits += offset;
71
72 /* Check for identification marker bits */
73 for (i = 0; i < count; i++) {
74 for (k = 0; k < 4; k++) {
75 if (id_marker[id_bit_nr % id_marker_len] != *ubits)
76 errors++;
77 id_bit_nr++;
78 ubits++;
79 bits++;
80 }
81
82 /* Jump to the next block of 4 bits */
83 ubits += 4;
84 }
85
86 *n_errors = errors;
87 *n_bits_total = bits;
88
89 /* Tolerate up to 1/8 errornous bits */
90 return *n_errors < *n_bits_total / 8;
91}
92
93static bool detect_ahs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, const ubit_t * id_marker)
94{
95 unsigned int i, k;
96 int errors = 0;
97 int bits = 0;
98
99 /* Override coded in-band data */
100 ubits += 16;
101
102 /* Check first identification marker bits (23*9 bits) */
103 for (i = 0; i < 23; i++) {
104 for (k = 0; k < 9; k++) {
105 if (id_marker[k] != *ubits)
106 errors++;
107 ubits++;
108 bits++;
109 }
110 }
111
112 /* Check remaining identification marker bits (5 bits) */
113 for (k = 0; k < 5; k++) {
114 if (id_marker[k] != *ubits)
115 errors++;
116 ubits++;
117 bits++;
118 }
119
120 *n_errors = errors;
121 *n_bits_total = bits;
122
123 /* Tolerate up to 1/8 errornous bits */
124 return *n_errors < *n_bits_total / 8;
125}
126
127static bool detect_interleaved_ahs_id_marker(int *n_errors, int *n_bits_total, const ubit_t * ubits, uint8_t offset,
128 uint8_t n_bits, const ubit_t * id_marker, uint8_t id_marker_len)
129{
130 unsigned int i, k;
131 int errors = 0;
132 int bits = 0;
133 uint8_t full_rounds = n_bits / id_marker_len;
134 uint8_t remainder = n_bits % id_marker_len;
135
136 /* Override coded in-band data */
137 ubits += offset;
138
139 /* Check first identification marker bits (23*9 bits) */
140 for (i = 0; i < full_rounds; i++) {
141 for (k = 0; k < id_marker_len; k++) {
142 if (id_marker[k] != *ubits)
143 errors++;
144 ubits += 2;
145 bits++;
146 }
147 }
148
149 /* Check remaining identification marker bits (5 bits) */
150 for (k = 0; k < remainder; k++) {
151 if (id_marker[k] != *ubits)
152 errors++;
153 ubits += 2;
154 bits++;
155 }
156
157 *n_errors = errors;
158 *n_bits_total = bits;
159
160 /* Tolerate up to 1/8 errornous bits */
161 return *n_errors < *n_bits_total / 8;
162}
163
164/* Detect a an FR AMR SID_FIRST frame by its identifcation marker */
165static bool detect_afs_sid_first(int *n_errors, int *n_bits_total, const ubit_t * ubits)
166{
167 return detect_afs_id_marker(n_errors, n_bits_total, ubits, 32, 53, id_marker_0, 9);
168}
169
170/* Detect an FR AMR SID_FIRST frame by its identification marker */
171static bool detect_afs_sid_update(int *n_errors, int *n_bits_total, const ubit_t * ubits)
172{
173 return detect_afs_id_marker(n_errors, n_bits_total, ubits, 36, 53, id_marker_0, 9);
174}
175
176/* Detect an FR AMR SID_FIRST frame by its repeating coded inband data */
177static bool detect_afs_onset(int *n_errors, int *n_bits_total, const ubit_t * ubits)
178{
179 bool rc;
180
181 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_1_sid, 16);
182 if (rc)
183 return true;
184
185 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_2_sid, 16);
186 if (rc)
187 return true;
188
189 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_3_sid, 16);
190 if (rc)
191 return true;
192
193 rc = detect_afs_id_marker(n_errors, n_bits_total, ubits, 4, 57, codec_mode_4_sid, 16);
194 if (rc)
195 return true;
196
197 return false;
198}
199
200/* Detect an HR AMR SID UPDATE frame by its identification marker */
201static bool detect_ahs_sid_update(int *n_errors, int *n_bits_total, const ubit_t * ubits)
202{
203 return detect_ahs_id_marker(n_errors, n_bits_total, ubits, id_marker_1);
204}
205
206/* Detect an HR AMR SID FIRST (part 1) frame by its identification marker */
207static bool detect_ahs_sid_first_p1(int *n_errors, int *n_bits_total, const ubit_t * ubits)
208{
209 return detect_ahs_id_marker(n_errors, n_bits_total, ubits, id_marker_0);
210}
211
212/* Detect an HR AMR SID FIRST (part 2) frame by its repeating coded inband data */
213static bool detect_ahs_sid_first_p2(int *n_errors, int *n_bits_total, const ubit_t * ubits)
214{
215 bool rc;
216
217 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_1_sid, 16);
218 if (rc)
219 return true;
220
221 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_2_sid, 16);
222 if (rc)
223 return true;
224
225 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_3_sid, 16);
226 if (rc)
227 return true;
228
229 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 0, 114, codec_mode_4_sid, 16);
230 if (rc)
231 return true;
232
233 return false;
234}
235
236/* Detect an HR AMR ONSET frame by its repeating coded inband data */
237static bool detect_ahs_onset(int *n_errors, int *n_bits_total, const ubit_t * ubits)
238{
239 bool rc;
240
241 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_1_sid, 16);
242 if (rc)
243 return true;
244
245 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_2_sid, 16);
246 if (rc)
247 return true;
248
249 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_3_sid, 16);
250 if (rc)
251 return true;
252
253 rc = detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 1, 114, codec_mode_4_sid, 16);
254 if (rc)
255 return true;
256
257 return false;
258}
259
260/* Detect an HR AMR SID FIRST INHIBIT frame by its identification marker */
261static bool detect_ahs_sid_first_inh(int *n_errors, int *n_bits_total, const ubit_t * ubits)
262{
263 return detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 33, 212, id_marker_1, 9);
264}
265
266/* Detect an HR AMR SID UPDATE INHIBIT frame by its identification marker */
267static bool detect_ahs_sid_update_inh(int *n_errors, int *n_bits_total, const ubit_t * ubits)
268{
269 return detect_interleaved_ahs_id_marker(n_errors, n_bits_total, ubits, 33, 212, id_marker_0, 9);
270}
271
272/*! Detect FR AMR DTX frame in unmapped, deinterleaved frame bits.
273 * \param[in] ubits input bits (456 bit).
274 * \param[out] n_errors number of errornous bits.
275 * \param[out] n_bits_total number of checked bits.
276 * \returns dtx frame type. */
277enum gsm0503_amr_dtx_frames gsm0503_detect_afs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t * ubits)
278{
279 if (detect_afs_sid_first(n_errors, n_bits_total, ubits))
280 return AFS_SID_FIRST;
281 if (detect_afs_sid_update(n_errors, n_bits_total, ubits))
282 return AFS_SID_UPDATE;
283 if (detect_afs_onset(n_errors, n_bits_total, ubits))
284 return AFS_ONSET;
285
286 *n_errors = 0;
287 *n_bits_total = 0;
288 return AMR_OTHER;
289}
290
291/*! Detect HR AMR DTX frame in unmapped, deinterleaved frame bits.
292 * \param[in] ubits input bits (456 bit).
293 * \param[out] n_errors number of errornous bits.
294 * \param[out] n_bits_total number of checked bits.
295 * \returns dtx frame type, */
296enum gsm0503_amr_dtx_frames gsm0503_detect_ahs_dtx_frame(int *n_errors, int *n_bits_total, const ubit_t * ubits)
297{
298 if (detect_ahs_sid_update(n_errors, n_bits_total, ubits))
299 return AHS_SID_UPDATE;
300 if (detect_ahs_sid_first_inh(n_errors, n_bits_total, ubits))
301 return AHS_SID_FIRST_INH;
302 if (detect_ahs_sid_update_inh(n_errors, n_bits_total, ubits))
303 return AHS_SID_UPDATE_INH;
304 if (detect_ahs_sid_first_p1(n_errors, n_bits_total, ubits))
305 return AHS_SID_FIRST_P1;
306 if (detect_ahs_sid_first_p2(n_errors, n_bits_total, ubits))
307 return AHS_SID_FIRST_P2;
308 if (detect_ahs_onset(n_errors, n_bits_total, ubits))
309 return AHS_ONSET;
310
311 *n_errors = 0;
312 *n_bits_total = 0;
313 return AMR_OTHER;
314}