blob: 9c189cdd90eb4af8e90372bb67c929cb87573cc1 [file] [log] [blame]
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001/*
2 * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
3 * (C) 2015 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
4 * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
Harald Weltec6636782017-06-12 14:59:37 +02005 * (C) 2017 by Harald Welte <laforge@gnumonks.org>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07006 *
7 * All Rights Reserved
8 *
Harald Weltee08da972017-11-13 01:00:26 +09009 * SPDX-License-Identifier: GPL-2.0+
10 *
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#include <stdio.h>
27#include <stdint.h>
28#include <string.h>
29#include <stdlib.h>
Maxc8cf8202017-05-22 16:07:04 +020030#include <errno.h>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070031
32#include <osmocom/core/bits.h>
33#include <osmocom/core/conv.h>
34#include <osmocom/core/utils.h>
35#include <osmocom/core/crcgen.h>
36#include <osmocom/core/endian.h>
37
38#include <osmocom/gprs/protocol/gsm_04_60.h>
39#include <osmocom/gprs/gprs_rlc.h>
40
41#include <osmocom/gsm/protocol/gsm_04_08.h>
42#include <osmocom/gsm/gsm0503.h>
43#include <osmocom/codec/codec.h>
44
45#include <osmocom/coding/gsm0503_interleaving.h>
46#include <osmocom/coding/gsm0503_mapping.h>
47#include <osmocom/coding/gsm0503_tables.h>
48#include <osmocom/coding/gsm0503_coding.h>
49#include <osmocom/coding/gsm0503_parity.h>
Philipp Maier898c9c62020-02-06 14:25:01 +010050#include <osmocom/coding/gsm0503_amr_dtx.h>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070051
Harald Weltec6636782017-06-12 14:59:37 +020052/*! \mainpage libosmocoding Documentation
53 *
54 * \section sec_intro Introduction
55 * This library is a collection of definitions, tables and functions
56 * implementing the GSM/GPRS/EGPRS channel coding (and decoding) as
57 * specified in 3GPP TS 05.03 / 45.003.
58 *
Vadim Yanitskiy9a232fd2018-01-19 03:05:32 +060059 * libosmocoding is developed as part of the Osmocom (Open Source Mobile
Harald Weltec6636782017-06-12 14:59:37 +020060 * Communications) project, a community-based, collaborative development
61 * project to create Free and Open Source implementations of mobile
62 * communications systems. For more information about Osmocom, please
63 * see https://osmocom.org/
64 *
65 * \section sec_copyright Copyright and License
66 * Copyright © 2013 by Andreas Eversberg\n
67 * Copyright © 2015 by Alexander Chemeris\n
68 * Copyright © 2016 by Tom Tsou\n
69 * Documentation Copyright © 2017 by Harald Welte\n
70 * All rights reserved. \n\n
71 * The source code of libosmocoding is licensed under the terms of the GNU
72 * General Public License as published by the Free Software Foundation;
73 * either version 2 of the License, or (at your option) any later
74 * version.\n
75 * See <http://www.gnu.org/licenses/> or COPYING included in the source
76 * code package istelf.\n
77 * The information detailed here is provided AS IS with NO WARRANTY OF
78 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
79 * FITNESS FOR A PARTICULAR PURPOSE.
80 * \n\n
81 *
82 * \section sec_tracker Homepage + Issue Tracker
83 * libosmocoding is distributed as part of libosmocore and shares its
84 * project page at http://osmocom.org/projects/libosmocore
85 *
86 * An Issue Tracker can be found at
87 * https://osmocom.org/projects/libosmocore/issues
88 *
89 * \section sec_contact Contact and Support
90 * Community-based support is available at the OpenBSC mailing list
91 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
92 * Commercial support options available upon request from
93 * <http://sysmocom.de/>
94 */
95
96
97/*! \addtogroup coding
98 * @{
99 *
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200100 * GSM TS 05.03 coding
Harald Weltec6636782017-06-12 14:59:37 +0200101 *
102 * This module is the "master module" of libosmocoding. It uses the
103 * various other modules (mapping, parity, interleaving) in order to
104 * implement the complete channel coding (and decoding) chain for the
105 * various channel types as defined in TS 05.03 / 45.003.
Neels Hofmeyr17518fe2017-06-20 04:35:06 +0200106 *
107 * \file gsm0503_coding.c */
Harald Weltec6636782017-06-12 14:59:37 +0200108
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700109/*
110 * EGPRS coding limits
111 */
112
113/* Max header size with parity bits */
114#define EGPRS_HDR_UPP_MAX 54
115
116/* Max encoded header size */
117#define EGPRS_HDR_C_MAX 162
118
119/* Max punctured header size */
120#define EGPRS_HDR_HC_MAX 160
121
122/* Max data block size with parity bits */
123#define EGPRS_DATA_U_MAX 612
124
125/* Max encoded data block size */
126#define EGPRS_DATA_C_MAX 1836
127
128/* Max single block punctured data size */
129#define EGPRS_DATA_DC_MAX 1248
130
131/* Dual block punctured data size */
132#define EGPRS_DATA_C1 612
133#define EGPRS_DATA_C2 EGPRS_DATA_C1
134
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200135/*! union across the three different EGPRS Uplink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700136union gprs_rlc_ul_hdr_egprs {
137 struct gprs_rlc_ul_header_egprs_1 type1;
138 struct gprs_rlc_ul_header_egprs_2 type2;
139 struct gprs_rlc_ul_header_egprs_3 type3;
140};
141
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200142/*! union across the three different EGPRS Downlink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700143union gprs_rlc_dl_hdr_egprs {
144 struct gprs_rlc_dl_header_egprs_1 type1;
145 struct gprs_rlc_dl_header_egprs_2 type2;
146 struct gprs_rlc_dl_header_egprs_3 type3;
147};
148
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200149/*! Structure describing a Modulation and Coding Scheme */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700150struct gsm0503_mcs_code {
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200151 /*! Modulation and Coding Scheme (MSC) number */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700152 uint8_t mcs;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200153 /*! Length of Uplink Stealing Flag (USF) in bits */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700154 uint8_t usf_len;
155
156 /* Header coding */
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200157 /*! Length of header (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700158 uint8_t hdr_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200159 /*! Length of header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700160 uint8_t hdr_code_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200161 /*! Length of header code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700162 uint8_t hdr_punc_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200163 /*! header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700164 const struct osmo_conv_code *hdr_conv;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200165 /*! header puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700166 const uint8_t *hdr_punc;
167
168 /* Data coding */
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200169 /*! length of data (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700170 uint16_t data_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200171 /*! length of data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700172 uint16_t data_code_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200173 /*! length of data code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700174 uint16_t data_punc_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200175 /*! data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700176 const struct osmo_conv_code *data_conv;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200177 /*! data puncturing sequences */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700178 const uint8_t *data_punc[3];
179};
180
181/*
182 * EGPRS UL coding parameters
183 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200184const struct gsm0503_mcs_code gsm0503_mcs_ul_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700185 {
186 .mcs = EGPRS_MCS0,
187 },
188 {
189 .mcs = EGPRS_MCS1,
190 .hdr_len = 31,
191 .hdr_code_len = 117,
192 .hdr_punc_len = 80,
193 .hdr_conv = &gsm0503_mcs1_ul_hdr,
194 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
195
196 .data_len = 178,
197 .data_code_len = 588,
198 .data_punc_len = 372,
199 .data_conv = &gsm0503_mcs1,
200 .data_punc = {
201 gsm0503_puncture_mcs1_p1,
202 gsm0503_puncture_mcs1_p2,
203 NULL,
204 },
205 },
206 {
207 .mcs = EGPRS_MCS2,
208 .hdr_len = 31,
209 .hdr_code_len = 117,
210 .hdr_punc_len = 80,
211 .hdr_conv = &gsm0503_mcs1_ul_hdr,
212 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
213
214 .data_len = 226,
215 .data_code_len = 732,
216 .data_punc_len = 372,
217 .data_conv = &gsm0503_mcs2,
218 .data_punc = {
219 gsm0503_puncture_mcs2_p1,
220 gsm0503_puncture_mcs2_p2,
221 NULL,
222 },
223 },
224 {
225 .mcs = EGPRS_MCS3,
226 .hdr_len = 31,
227 .hdr_code_len = 117,
228 .hdr_punc_len = 80,
229 .hdr_conv = &gsm0503_mcs1_ul_hdr,
230 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
231
232 .data_len = 298,
233 .data_code_len = 948,
234 .data_punc_len = 372,
235 .data_conv = &gsm0503_mcs3,
236 .data_punc = {
237 gsm0503_puncture_mcs3_p1,
238 gsm0503_puncture_mcs3_p2,
239 gsm0503_puncture_mcs3_p3,
240 },
241 },
242 {
243 .mcs = EGPRS_MCS4,
244 .hdr_len = 31,
245 .hdr_code_len = 117,
246 .hdr_punc_len = 80,
247 .hdr_conv = &gsm0503_mcs1_ul_hdr,
248 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
249
250 .data_len = 354,
251 .data_code_len = 1116,
252 .data_punc_len = 372,
253 .data_conv = &gsm0503_mcs4,
254 .data_punc = {
255 gsm0503_puncture_mcs4_p1,
256 gsm0503_puncture_mcs4_p2,
257 gsm0503_puncture_mcs4_p3,
258 },
259 },
260 {
261 .mcs = EGPRS_MCS5,
262 .hdr_len = 37,
263 .hdr_code_len = 135,
264 .hdr_punc_len = 136,
265 .hdr_conv = &gsm0503_mcs5_ul_hdr,
266 .hdr_punc = NULL,
267
268 .data_len = 450,
269 .data_code_len = 1404,
270 .data_punc_len = 1248,
271 .data_conv = &gsm0503_mcs5,
272 .data_punc = {
273 gsm0503_puncture_mcs5_p1,
274 gsm0503_puncture_mcs5_p2,
275 NULL,
276 },
277 },
278 {
279 .mcs = EGPRS_MCS6,
280 .hdr_len = 37,
281 .hdr_code_len = 135,
282 .hdr_punc_len = 136,
283 .hdr_conv = &gsm0503_mcs5_ul_hdr,
284 .hdr_punc = NULL,
285
286 .data_len = 594,
287 .data_code_len = 1836,
288 .data_punc_len = 1248,
289 .data_conv = &gsm0503_mcs6,
290 .data_punc = {
291 gsm0503_puncture_mcs6_p1,
292 gsm0503_puncture_mcs6_p2,
293 NULL,
294 },
295 },
296 {
297 .mcs = EGPRS_MCS7,
298 .hdr_len = 46,
299 .hdr_code_len = 162,
300 .hdr_punc_len = 160,
301 .hdr_conv = &gsm0503_mcs7_ul_hdr,
302 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
303
304 .data_len = 900,
305 .data_code_len = 1404,
306 .data_punc_len = 612,
307 .data_conv = &gsm0503_mcs7,
308 .data_punc = {
309 gsm0503_puncture_mcs7_p1,
310 gsm0503_puncture_mcs7_p2,
311 gsm0503_puncture_mcs7_p3,
312 }
313 },
314 {
315 .mcs = EGPRS_MCS8,
316 .hdr_len = 46,
317 .hdr_code_len = 162,
318 .hdr_punc_len = 160,
319 .hdr_conv = &gsm0503_mcs7_ul_hdr,
320 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
321
322 .data_len = 1092,
323 .data_code_len = 1692,
324 .data_punc_len = 612,
325 .data_conv = &gsm0503_mcs8,
326 .data_punc = {
327 gsm0503_puncture_mcs8_p1,
328 gsm0503_puncture_mcs8_p2,
329 gsm0503_puncture_mcs8_p3,
330 }
331 },
332 {
333 .mcs = EGPRS_MCS9,
334 .hdr_len = 46,
335 .hdr_code_len = 162,
336 .hdr_punc_len = 160,
337 .hdr_conv = &gsm0503_mcs7_ul_hdr,
338 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
339
340 .data_len = 1188,
341 .data_code_len = 1836,
342 .data_punc_len = 612,
343 .data_conv = &gsm0503_mcs9,
344 .data_punc = {
345 gsm0503_puncture_mcs9_p1,
346 gsm0503_puncture_mcs9_p2,
347 gsm0503_puncture_mcs9_p3,
348 }
349 },
350};
351
352/*
353 * EGPRS DL coding parameters
354 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200355const struct gsm0503_mcs_code gsm0503_mcs_dl_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700356 {
357 .mcs = EGPRS_MCS0,
358 },
359 {
360 .mcs = EGPRS_MCS1,
361 .usf_len = 3,
362 .hdr_len = 28,
363 .hdr_code_len = 108,
364 .hdr_punc_len = 68,
365 .hdr_conv = &gsm0503_mcs1_dl_hdr,
366 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
367
368 .data_len = 178,
369 .data_code_len = 588,
370 .data_punc_len = 372,
371 .data_conv = &gsm0503_mcs1,
372 .data_punc = {
373 gsm0503_puncture_mcs1_p1,
374 gsm0503_puncture_mcs1_p2,
375 NULL,
376 },
377 },
378 {
379 .mcs = EGPRS_MCS2,
380 .usf_len = 3,
381 .hdr_len = 28,
382 .hdr_code_len = 108,
383 .hdr_punc_len = 68,
384 .hdr_conv = &gsm0503_mcs1_dl_hdr,
385 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
386
387 .data_len = 226,
388 .data_code_len = 732,
389 .data_punc_len = 372,
390 .data_conv = &gsm0503_mcs2,
391 .data_punc = {
392 gsm0503_puncture_mcs2_p1,
393 gsm0503_puncture_mcs2_p2,
394 NULL,
395 },
396 },
397 {
398 .mcs = EGPRS_MCS3,
399 .usf_len = 3,
400 .hdr_len = 28,
401 .hdr_code_len = 108,
402 .hdr_punc_len = 68,
403 .hdr_conv = &gsm0503_mcs1_dl_hdr,
404 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
405
406 .data_len = 298,
407 .data_code_len = 948,
408 .data_punc_len = 372,
409 .data_conv = &gsm0503_mcs3,
410 .data_punc = {
411 gsm0503_puncture_mcs3_p1,
412 gsm0503_puncture_mcs3_p2,
413 gsm0503_puncture_mcs3_p3,
414 },
415 },
416 {
417 .mcs = EGPRS_MCS4,
418 .usf_len = 3,
419 .hdr_len = 28,
420 .hdr_code_len = 108,
421 .hdr_punc_len = 68,
422 .hdr_conv = &gsm0503_mcs1_dl_hdr,
423 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
424
425 .data_len = 354,
426 .data_code_len = 1116,
427 .data_punc_len = 372,
428 .data_conv = &gsm0503_mcs4,
429 .data_punc = {
430 gsm0503_puncture_mcs4_p1,
431 gsm0503_puncture_mcs4_p2,
432 gsm0503_puncture_mcs4_p3,
433 },
434 },
435 {
436 .mcs = EGPRS_MCS5,
437 .usf_len = 3,
438 .hdr_len = 25,
439 .hdr_code_len = 99,
440 .hdr_punc_len = 100,
441 .hdr_conv = &gsm0503_mcs5_dl_hdr,
442 .hdr_punc = NULL,
443
444 .data_len = 450,
445 .data_code_len = 1404,
446 .data_punc_len = 1248,
447 .data_conv = &gsm0503_mcs5,
448 .data_punc = {
449 gsm0503_puncture_mcs5_p1,
450 gsm0503_puncture_mcs5_p2,
451 NULL,
452 },
453 },
454 {
455 .mcs = EGPRS_MCS6,
456 .usf_len = 3,
457 .hdr_len = 25,
458 .hdr_code_len = 99,
459 .hdr_punc_len = 100,
460 .hdr_conv = &gsm0503_mcs5_dl_hdr,
461 .hdr_punc = NULL,
462
463 .data_len = 594,
464 .data_code_len = 1836,
465 .data_punc_len = 1248,
466 .data_conv = &gsm0503_mcs6,
467 .data_punc = {
468 gsm0503_puncture_mcs6_p1,
469 gsm0503_puncture_mcs6_p2,
470 NULL,
471 },
472 },
473 {
474 .mcs = EGPRS_MCS7,
475 .usf_len = 3,
476 .hdr_len = 37,
477 .hdr_code_len = 135,
478 .hdr_punc_len = 124,
479 .hdr_conv = &gsm0503_mcs7_dl_hdr,
480 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
481
482 .data_len = 900,
483 .data_code_len = 1404,
484 .data_punc_len = 612,
485 .data_conv = &gsm0503_mcs7,
486 .data_punc = {
487 gsm0503_puncture_mcs7_p1,
488 gsm0503_puncture_mcs7_p2,
489 gsm0503_puncture_mcs7_p3,
490 }
491 },
492 {
493 .mcs = EGPRS_MCS8,
494 .usf_len = 3,
495 .hdr_len = 37,
496 .hdr_code_len = 135,
497 .hdr_punc_len = 124,
498 .hdr_conv = &gsm0503_mcs7_dl_hdr,
499 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
500
501 .data_len = 1092,
502 .data_code_len = 1692,
503 .data_punc_len = 612,
504 .data_conv = &gsm0503_mcs8,
505 .data_punc = {
506 gsm0503_puncture_mcs8_p1,
507 gsm0503_puncture_mcs8_p2,
508 gsm0503_puncture_mcs8_p3,
509 }
510 },
511 {
512 .mcs = EGPRS_MCS9,
513 .usf_len = 3,
514 .hdr_len = 37,
515 .hdr_code_len = 135,
516 .hdr_punc_len = 124,
517 .hdr_conv = &gsm0503_mcs7_dl_hdr,
518 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
519
520 .data_len = 1188,
521 .data_code_len = 1836,
522 .data_punc_len = 612,
523 .data_conv = &gsm0503_mcs9,
524 .data_punc = {
525 gsm0503_puncture_mcs9_p1,
526 gsm0503_puncture_mcs9_p2,
527 gsm0503_puncture_mcs9_p3,
528 }
529 },
530};
531
Alexander Chemeris147051f2018-07-14 21:02:29 +0200532/*! Convolutional Decode + compute BER for punctured codes
Harald Weltec6636782017-06-12 14:59:37 +0200533 * \param[in] code Description of Convolutional Code
534 * \param[in] input Input soft-bits (-127...127)
535 * \param[out] output bits
536 * \param[out] n_errors Number of bit-errors
537 * \param[out] n_bits_total Number of bits
Alexander Chemeris147051f2018-07-14 21:02:29 +0200538 * \param[in] data_punc Puncturing mask array. Can be NULL.
Harald Weltec6636782017-06-12 14:59:37 +0200539 */
Alexander Chemeris147051f2018-07-14 21:02:29 +0200540static int osmo_conv_decode_ber_punctured(const struct osmo_conv_code *code,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700541 const sbit_t *input, ubit_t *output,
Alexander Chemeris147051f2018-07-14 21:02:29 +0200542 int *n_errors, int *n_bits_total,
543 const uint8_t *data_punc)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700544{
545 int res, i, coded_len;
546 ubit_t recoded[EGPRS_DATA_C_MAX];
547
548 res = osmo_conv_decode(code, input, output);
549
550 if (n_bits_total || n_errors) {
551 coded_len = osmo_conv_encode(code, output, recoded);
552 OSMO_ASSERT(sizeof(recoded) / sizeof(recoded[0]) >= coded_len);
553 }
554
555 /* Count bit errors */
556 if (n_errors) {
557 *n_errors = 0;
558 for (i = 0; i < coded_len; i++) {
Alexander Chemeris147051f2018-07-14 21:02:29 +0200559 if (((!data_punc) || (data_punc && !data_punc[i])) &&
560 !((recoded[i] && input[i] < 0) ||
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700561 (!recoded[i] && input[i] > 0)) )
562 *n_errors += 1;
563 }
564 }
565
566 if (n_bits_total)
567 *n_bits_total = coded_len;
568
569 return res;
570}
571
Alexander Chemeris147051f2018-07-14 21:02:29 +0200572/*! Convolutional Decode + compute BER for non-punctured codes
573 * \param[in] code Description of Convolutional Code
574 * \param[in] input Input soft-bits (-127...127)
575 * \param[out] output bits
576 * \param[out] n_errors Number of bit-errors
577 * \param[out] n_bits_total Number of bits
578 */
579static int osmo_conv_decode_ber(const struct osmo_conv_code *code,
580 const sbit_t *input, ubit_t *output,
581 int *n_errors, int *n_bits_total)
582{
583 return osmo_conv_decode_ber_punctured(code, input, output,
584 n_errors, n_bits_total, NULL);
585}
586
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200587/*! convenience wrapper for decoding coded bits
Harald Weltec6636782017-06-12 14:59:37 +0200588 * \param[out] l2_data caller-allocated buffer for L2 Frame
589 * \param[in] cB 456 coded (soft) bits as per TS 05.03 4.1.3
590 * \param[out] n_errors Number of detected errors
591 * \param[out] n_bits_total Number of total coded bits
592 * \returns 0 on success; -1 on CRC error */
Harald Welteb9946d32017-06-12 09:40:16 +0200593static int _xcch_decode_cB(uint8_t *l2_data, const sbit_t *cB,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700594 int *n_errors, int *n_bits_total)
595{
596 ubit_t conv[224];
597 int rv;
598
599 osmo_conv_decode_ber(&gsm0503_xcch, cB,
600 conv, n_errors, n_bits_total);
601
602 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
603 conv, 184, conv + 184);
604 if (rv)
605 return -1;
606
607 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
608
609 return 0;
610}
611
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200612/*! convenience wrapper for encoding to coded bits
Harald Weltec6636782017-06-12 14:59:37 +0200613 * \param[out] cB caller-allocated buffer for 456 coded bits as per TS 05.03 4.1.3
614 * \param[out] l2_data to-be-encoded L2 Frame
615 * \returns 0 */
Harald Welteb9946d32017-06-12 09:40:16 +0200616static int _xcch_encode_cB(ubit_t *cB, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700617{
618 ubit_t conv[224];
619
620 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
621
622 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
623
624 osmo_conv_encode(&gsm0503_xcch, conv, cB);
625
626 return 0;
627}
628
629/*
630 * GSM xCCH block transcoding
631 */
Harald Weltec6636782017-06-12 14:59:37 +0200632
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200633/*! Decoding of xCCH data from bursts to L2 frame
Harald Weltec6636782017-06-12 14:59:37 +0200634 * \param[out] l2_data caller-allocated output data buffer
635 * \param[in] bursts four GSM bursts in soft-bits
636 * \param[out] n_errors Number of detected errors
637 * \param[out] n_bits_total Number of total coded bits
638 */
Harald Welteb9946d32017-06-12 09:40:16 +0200639int gsm0503_xcch_decode(uint8_t *l2_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700640 int *n_errors, int *n_bits_total)
641{
642 sbit_t iB[456], cB[456];
643 int i;
644
645 for (i = 0; i < 4; i++)
646 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116], NULL, NULL);
647
648 gsm0503_xcch_deinterleave(cB, iB);
649
650 return _xcch_decode_cB(l2_data, cB, n_errors, n_bits_total);
651}
652
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200653/*! Encoding of xCCH data from L2 frame to bursts
Harald Weltec6636782017-06-12 14:59:37 +0200654 * \param[out] bursts caller-allocated burst data (unpacked bits)
655 * \param[in] l2_data L2 input data (MAC block)
656 * \returns 0
657 */
Harald Welteb9946d32017-06-12 09:40:16 +0200658int gsm0503_xcch_encode(ubit_t *bursts, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700659{
660 ubit_t iB[456], cB[456], hl = 1, hn = 1;
661 int i;
662
663 _xcch_encode_cB(cB, l2_data);
664
665 gsm0503_xcch_interleave(cB, iB);
666
667 for (i = 0; i < 4; i++)
668 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116], &hl, &hn);
669
670 return 0;
671}
672
673/*
674 * EGPRS PDTCH UL block decoding
675 */
676
677/*
678 * Type 3 - MCS-1,2,3,4
679 * Unmapping and deinterleaving
680 */
681static int egprs_type3_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
682{
683 int i;
684 sbit_t iB[456], q[8];
685
686 for (i = 0; i < 4; i++) {
687 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
688 q + i * 2, q + i * 2 + 1);
689 }
690
691 gsm0503_mcs1_ul_deinterleave(hc, dc, iB);
692
693 return 0;
694}
695
696/*
697 * Type 2 - MCS-5,6
698 * Unmapping and deinterleaving
699 */
700static int egprs_type2_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
701{
702 int i;
703 sbit_t burst[348];
704 sbit_t hi[EGPRS_HDR_HC_MAX];
705 sbit_t di[EGPRS_DATA_DC_MAX];
706
707 for (i = 0; i < 4; i++) {
708 memcpy(burst, &bursts[i * 348], 348);
709
710 gsm0503_mcs5_burst_swap(burst);
711 gsm0503_mcs5_ul_burst_unmap(di, burst, hi, i);
712 }
713
714 gsm0503_mcs5_ul_deinterleave(hc, dc, hi, di);
715
716 return 0;
717}
718
719/*
720 * Type 1 - MCS-7,8,9
721 * Unmapping and deinterleaving - Note that MCS-7 interleaver is unique
722 */
723static int egprs_type1_unmap(const sbit_t *bursts, sbit_t *hc,
724 sbit_t *c1, sbit_t *c2, int msc)
725{
726 int i;
727 sbit_t burst[348];
728 sbit_t hi[EGPRS_HDR_HC_MAX];
729 sbit_t di[EGPRS_DATA_C1 * 2];
730
731 for (i = 0; i < 4; i++) {
732 memcpy(burst, &bursts[i * 348], 348);
733
734 gsm0503_mcs5_burst_swap(burst);
735 gsm0503_mcs7_ul_burst_unmap(di, burst, hi, i);
736 }
737
738 if (msc == EGPRS_MCS7)
739 gsm0503_mcs7_ul_deinterleave(hc, c1, c2, hi, di);
740 else
741 gsm0503_mcs8_ul_deinterleave(hc, c1, c2, hi, di);
742
743 return 0;
744}
745
746/*
747 * Decode EGPRS UL header section
748 *
749 * 1. Depuncture
750 * 2. Convolutional decoding
751 * 3. CRC check
752 */
753static int _egprs_decode_hdr(const sbit_t *hc, int mcs,
754 union gprs_rlc_ul_hdr_egprs *hdr)
755{
756 sbit_t C[EGPRS_HDR_C_MAX];
757 ubit_t upp[EGPRS_HDR_UPP_MAX];
758 int i, j, rc;
Harald Welte2f984ea2017-06-12 15:05:21 +0200759 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700760
761 code = &gsm0503_mcs_ul_codes[mcs];
762
763 /* Skip depuncturing on MCS-5,6 header */
764 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
765 memcpy(C, hc, code->hdr_code_len);
766 goto hdr_conv_decode;
767 }
768
769 if (!code->hdr_punc) {
770 /* Invalid MCS-X header puncture matrix */
771 return -1;
772 }
773
774 i = code->hdr_code_len - 1;
775 j = code->hdr_punc_len - 1;
776
777 for (; i >= 0; i--) {
778 if (!code->hdr_punc[i])
779 C[i] = hc[j--];
780 else
781 C[i] = 0;
782 }
783
784hdr_conv_decode:
785 osmo_conv_decode_ber(code->hdr_conv, C, upp, NULL, NULL);
786 rc = osmo_crc8gen_check_bits(&gsm0503_mcs_crc8_hdr, upp,
787 code->hdr_len, upp + code->hdr_len);
788 if (rc)
789 return -1;
790
791 osmo_ubit2pbit_ext((pbit_t *) hdr, 0, upp, 0, code->hdr_len, 1);
792
793 return 0;
794}
795
796/*
797 * Blind MCS header decoding based on burst length and CRC validation.
798 * Ignore 'q' value coding identification. This approach provides
799 * the strongest chance of header recovery.
800 */
801static int egprs_decode_hdr(union gprs_rlc_ul_hdr_egprs *hdr,
802 const sbit_t *bursts, uint16_t nbits)
803{
804 int rc;
805 sbit_t hc[EGPRS_HDR_HC_MAX];
806
807 if (nbits == GSM0503_GPRS_BURSTS_NBITS) {
808 /* MCS-1,2,3,4 */
809 egprs_type3_unmap(bursts, hc, NULL);
810 rc = _egprs_decode_hdr(hc, EGPRS_MCS1, hdr);
811 if (!rc)
812 return EGPRS_HDR_TYPE3;
813 } else if (nbits == GSM0503_EGPRS_BURSTS_NBITS) {
814 /* MCS-5,6 */
815 egprs_type2_unmap(bursts, hc, NULL);
816 rc = _egprs_decode_hdr(hc, EGPRS_MCS5, hdr);
817 if (!rc)
818 return EGPRS_HDR_TYPE2;
819
820 /* MCS-7,8,9 */
821 egprs_type1_unmap(bursts, hc, NULL, NULL, EGPRS_MCS7);
822 rc = _egprs_decode_hdr(hc, EGPRS_MCS7, hdr);
823 if (!rc)
824 return EGPRS_HDR_TYPE1;
825 }
826
827 return -1;
828}
829
830/*
831 * Parse EGPRS UL header for coding and puncturing scheme (CPS)
832 *
833 * Type 1 - MCS-7,8,9
834 * Type 2 - MCS-5,6
835 * Type 3 - MCS-1,2,3,4
836 */
837static int egprs_parse_ul_cps(struct egprs_cps *cps,
838 union gprs_rlc_ul_hdr_egprs *hdr, int type)
839{
840 uint8_t bits;
841
842 switch (type) {
843 case EGPRS_HDR_TYPE1:
844 bits = hdr->type1.cps;
845 break;
846 case EGPRS_HDR_TYPE2:
847 bits = (hdr->type2.cps_lo << 2) | hdr->type2.cps_hi;
848 break;
849 case EGPRS_HDR_TYPE3:
850 bits = (hdr->type3.cps_lo << 2) | hdr->type3.cps_hi;
851 break;
852 default:
853 return -1;
854 }
855
856 return egprs_get_cps(cps, type, bits);
857}
858
859/*
860 * Decode EGPRS UL data section
861 *
862 * 1. Depuncture
863 * 2. Convolutional decoding
864 * 3. CRC check
865 * 4. Block combining (MCS-7,8,9 only)
866 */
Harald Welteb9946d32017-06-12 09:40:16 +0200867static int egprs_decode_data(uint8_t *l2_data, const sbit_t *c,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700868 int mcs, int p, int blk, int *n_errors, int *n_bits_total)
869{
870 ubit_t u[EGPRS_DATA_U_MAX];
871 sbit_t C[EGPRS_DATA_C_MAX];
872
873 int i, j, rc, data_len;
Harald Welte2f984ea2017-06-12 15:05:21 +0200874 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700875
876 if (blk && mcs < EGPRS_MCS7) {
877 /* Invalid MCS-X block state */
878 return -1;
879 }
880
881 code = &gsm0503_mcs_ul_codes[mcs];
882 if (!code->data_punc[p]) {
883 /* Invalid MCS-X data puncture matrix */
884 return -1;
885 }
886
887 /*
888 * MCS-1,6 - single block processing
889 * MCS-7,9 - dual block processing
890 */
891 if (mcs >= EGPRS_MCS7)
892 data_len = code->data_len / 2;
893 else
894 data_len = code->data_len;
895
896 i = code->data_code_len - 1;
897 j = code->data_punc_len - 1;
898
899 for (; i >= 0; i--) {
900 if (!code->data_punc[p][i])
901 C[i] = c[j--];
902 else
903 C[i] = 0;
904 }
905
Alexander Chemeris147051f2018-07-14 21:02:29 +0200906 osmo_conv_decode_ber_punctured(code->data_conv, C, u,
907 n_errors, n_bits_total, code->data_punc[p]);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700908 rc = osmo_crc16gen_check_bits(&gsm0503_mcs_crc12, u,
909 data_len, u + data_len);
910 if (rc)
911 return -1;
912
913 /* Offsets output pointer on the second block of Type 1 MCS */
914 osmo_ubit2pbit_ext(l2_data, code->hdr_len + blk * data_len,
915 u, 0, data_len, 1);
916
917 /* Return the number of bytes required for the bit message */
Maxdd75bac2017-06-13 15:07:01 +0200918 return OSMO_BYTES_FOR_BITS(code->hdr_len + code->data_len);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700919}
920
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200921/*! Decode EGPRS UL message
Harald Weltec6636782017-06-12 14:59:37 +0200922 * 1. Header section decoding
923 * 2. Extract CPS settings
924 * 3. Burst unmapping and deinterleaving
925 * 4. Data section decoding
926 * \param[out] l2_data caller-allocated buffer for L2 Frame
927 * \param[in] bursts burst input data as soft unpacked bits
928 * \param[in] nbits number of bits in \a bursts
929 * \param usf_p unused argument ?!?
930 * \param[out] n_errors number of detected bit-errors
Alexander Chemerised7d2dd2018-07-14 21:06:27 +0200931 * \param[out] n_bits_total total number of decoded bits
Harald Weltec6636782017-06-12 14:59:37 +0200932 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +0200933int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t nbits,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700934 uint8_t *usf_p, int *n_errors, int *n_bits_total)
935{
936 sbit_t dc[EGPRS_DATA_DC_MAX];
937 sbit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
938 int type, rc;
939 struct egprs_cps cps;
940 union gprs_rlc_ul_hdr_egprs *hdr;
941
Alexander Chemeris50f7d742018-07-14 21:07:27 +0200942 if (n_errors)
943 *n_errors = 0;
944 if (n_bits_total)
945 *n_bits_total = 0;
946
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700947 if ((nbits != GSM0503_GPRS_BURSTS_NBITS) &&
948 (nbits != GSM0503_EGPRS_BURSTS_NBITS)) {
949 /* Invalid EGPRS bit length */
Maxc8cf8202017-05-22 16:07:04 +0200950 return -EOVERFLOW;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700951 }
952
953 hdr = (union gprs_rlc_ul_hdr_egprs *) l2_data;
954 type = egprs_decode_hdr(hdr, bursts, nbits);
955 if (egprs_parse_ul_cps(&cps, hdr, type) < 0)
Maxc8cf8202017-05-22 16:07:04 +0200956 return -EIO;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700957
958 switch (cps.mcs) {
Maxc8cf8202017-05-22 16:07:04 +0200959 case EGPRS_MCS0:
960 return -ENOTSUP;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700961 case EGPRS_MCS1:
962 case EGPRS_MCS2:
963 case EGPRS_MCS3:
964 case EGPRS_MCS4:
965 egprs_type3_unmap(bursts, NULL, dc);
966 break;
967 case EGPRS_MCS5:
968 case EGPRS_MCS6:
969 egprs_type2_unmap(bursts, NULL, dc);
970 break;
971 case EGPRS_MCS7:
972 case EGPRS_MCS8:
973 case EGPRS_MCS9:
974 egprs_type1_unmap(bursts, NULL, c1, c2, cps.mcs);
975 break;
976 default:
977 /* Invalid MCS-X */
Maxc8cf8202017-05-22 16:07:04 +0200978 return -EINVAL;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700979 }
980
981 /* Decode MCS-X block, where X = cps.mcs */
982 if (cps.mcs < EGPRS_MCS7) {
983 rc = egprs_decode_data(l2_data, dc, cps.mcs, cps.p[0],
984 0, n_errors, n_bits_total);
985 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200986 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700987 } else {
Alexander Chemeris94443262018-07-14 21:09:54 +0200988 /* Bit counters for the second block */
989 int n_errors2, n_bits_total2;
990
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700991 /* MCS-7,8,9 block 1 */
992 rc = egprs_decode_data(l2_data, c1, cps.mcs, cps.p[0],
993 0, n_errors, n_bits_total);
994 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200995 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700996
997 /* MCS-7,8,9 block 2 */
998 rc = egprs_decode_data(l2_data, c2, cps.mcs, cps.p[1],
Alexander Chemeris94443262018-07-14 21:09:54 +0200999 1, &n_errors2, &n_bits_total2);
1000 if (n_errors)
1001 *n_errors += n_errors2;
1002 if (n_bits_total)
1003 *n_bits_total += n_bits_total2;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001004 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +02001005 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001006 }
1007
1008 return rc;
1009}
1010
1011/*
1012 * GSM PDTCH block transcoding
1013 */
1014
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001015/*! Decode GPRS PDTCH
Harald Weltec6636782017-06-12 14:59:37 +02001016 * \param[out] l2_data caller-allocated buffer for L2 Frame
1017 * \param[in] bursts burst input data as soft unpacked bits
1018 * \param[out] usf_p uplink stealing flag
1019 * \param[out] n_errors number of detected bit-errors
1020 * \param[out] n_bits_total total number of dcoded bits
1021 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001022int gsm0503_pdtch_decode(uint8_t *l2_data, const sbit_t *bursts, uint8_t *usf_p,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001023 int *n_errors, int *n_bits_total)
1024{
1025 sbit_t iB[456], cB[676], hl_hn[8];
1026 ubit_t conv[456];
1027 int i, j, k, rv, best = 0, cs = 0, usf = 0; /* make GCC happy */
1028
1029 for (i = 0; i < 4; i++)
1030 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
1031 hl_hn + i * 2, hl_hn + i * 2 + 1);
1032
1033 for (i = 0; i < 4; i++) {
1034 for (j = 0, k = 0; j < 8; j++)
1035 k += abs(((int)gsm0503_pdtch_hl_hn_sbit[i][j]) - ((int)hl_hn[j]));
1036
1037 if (i == 0 || k < best) {
1038 best = k;
1039 cs = i + 1;
1040 }
1041 }
1042
1043 gsm0503_xcch_deinterleave(cB, iB);
1044
1045 switch (cs) {
1046 case 1:
1047 osmo_conv_decode_ber(&gsm0503_xcch, cB,
1048 conv, n_errors, n_bits_total);
1049
1050 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
1051 conv, 184, conv + 184);
1052 if (rv)
1053 return -1;
1054
1055 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
1056
1057 return 23;
1058 case 2:
1059 for (i = 587, j = 455; i >= 0; i--) {
1060 if (!gsm0503_puncture_cs2[i])
1061 cB[i] = cB[j--];
1062 else
1063 cB[i] = 0;
1064 }
1065
1066 osmo_conv_decode_ber(&gsm0503_cs2_np, cB,
1067 conv, n_errors, n_bits_total);
1068
1069 for (i = 0; i < 8; i++) {
1070 for (j = 0, k = 0; j < 6; j++)
1071 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1072
1073 if (i == 0 || k < best) {
1074 best = k;
1075 usf = i;
1076 }
1077 }
1078
1079 conv[3] = usf & 1;
1080 conv[4] = (usf >> 1) & 1;
1081 conv[5] = (usf >> 2) & 1;
1082 if (usf_p)
1083 *usf_p = usf;
1084
1085 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1086 conv + 3, 271, conv + 3 + 271);
1087 if (rv)
1088 return -1;
1089
1090 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 271, 1);
1091
1092 return 34;
1093 case 3:
1094 for (i = 675, j = 455; i >= 0; i--) {
1095 if (!gsm0503_puncture_cs3[i])
1096 cB[i] = cB[j--];
1097 else
1098 cB[i] = 0;
1099 }
1100
1101 osmo_conv_decode_ber(&gsm0503_cs3_np, cB,
1102 conv, n_errors, n_bits_total);
1103
1104 for (i = 0; i < 8; i++) {
1105 for (j = 0, k = 0; j < 6; j++)
1106 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1107
1108 if (i == 0 || k < best) {
1109 best = k;
1110 usf = i;
1111 }
1112 }
1113
1114 conv[3] = usf & 1;
1115 conv[4] = (usf >> 1) & 1;
1116 conv[5] = (usf >> 2) & 1;
1117 if (usf_p)
1118 *usf_p = usf;
1119
1120 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1121 conv + 3, 315, conv + 3 + 315);
1122 if (rv)
1123 return -1;
1124
1125 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 315, 1);
1126
1127 return 40;
1128 case 4:
1129 for (i = 12; i < 456; i++)
1130 conv[i] = (cB[i] < 0) ? 1 : 0;
1131
1132 for (i = 0; i < 8; i++) {
1133 for (j = 0, k = 0; j < 12; j++)
1134 k += abs(((int)gsm0503_usf2twelve_sbit[i][j]) - ((int)cB[j]));
1135
1136 if (i == 0 || k < best) {
1137 best = k;
1138 usf = i;
1139 }
1140 }
1141
1142 conv[9] = usf & 1;
1143 conv[10] = (usf >> 1) & 1;
1144 conv[11] = (usf >> 2) & 1;
1145 if (usf_p)
1146 *usf_p = usf;
1147
1148 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1149 conv + 9, 431, conv + 9 + 431);
1150 if (rv) {
1151 *n_bits_total = 456 - 12;
1152 *n_errors = *n_bits_total;
1153 return -1;
1154 }
1155
1156 *n_bits_total = 456 - 12;
1157 *n_errors = 0;
1158
1159 osmo_ubit2pbit_ext(l2_data, 0, conv, 9, 431, 1);
1160
1161 return 54;
1162 default:
1163 *n_bits_total = 0;
1164 *n_errors = 0;
1165 break;
1166 }
1167
1168 return -1;
1169}
1170
1171/*
Pau Espin Pedrolf62f0732020-04-07 13:12:11 +02001172 * EGPRS PDTCH DL block encoding
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001173 */
Harald Welteb9946d32017-06-12 09:40:16 +02001174static int egprs_type3_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001175{
1176 int i;
1177 ubit_t iB[456];
1178 const ubit_t *hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1179
Pau Espin Pedrol63ebc362020-04-07 13:15:36 +02001180 gsm0503_mcs1_dl_interleave(gsm0503_usf2twelve_ubit[usf], hc, dc, iB);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001181
1182 for (i = 0; i < 4; i++) {
1183 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1184 hl_hn + i * 2, hl_hn + i * 2 + 1);
1185 }
1186
1187 return 0;
1188}
1189
Harald Welteb9946d32017-06-12 09:40:16 +02001190static int egprs_type2_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001191{
1192 int i;
1193 const ubit_t *up;
1194 ubit_t hi[EGPRS_HDR_HC_MAX];
1195 ubit_t di[EGPRS_DATA_DC_MAX];
1196
1197 gsm0503_mcs5_dl_interleave(hc, dc, hi, di);
1198 up = gsm0503_mcs5_usf_precode_table[usf];
1199
1200 for (i = 0; i < 4; i++) {
1201 gsm0503_mcs5_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1202 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1203 }
1204
1205 return 0;
1206}
1207
Harald Welteb9946d32017-06-12 09:40:16 +02001208static int egprs_type1_map(ubit_t *bursts, const ubit_t *hc,
1209 const ubit_t *c1, const ubit_t *c2, int usf, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001210{
1211 int i;
1212 const ubit_t *up;
1213 ubit_t hi[EGPRS_HDR_HC_MAX];
1214 ubit_t di[EGPRS_DATA_C1 * 2];
1215
1216 if (mcs == EGPRS_MCS7)
1217 gsm0503_mcs7_dl_interleave(hc, c1, c2, hi, di);
1218 else
1219 gsm0503_mcs8_dl_interleave(hc, c1, c2, hi, di);
1220
1221 up = gsm0503_mcs5_usf_precode_table[usf];
1222
1223 for (i = 0; i < 4; i++) {
1224 gsm0503_mcs7_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1225 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1226 }
1227
1228 return 0;
1229}
1230
Harald Welteb9946d32017-06-12 09:40:16 +02001231static int egprs_encode_hdr(ubit_t *hc, const uint8_t *l2_data, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001232{
1233 int i, j;
1234 ubit_t upp[EGPRS_HDR_UPP_MAX], C[EGPRS_HDR_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001235 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001236
1237 code = &gsm0503_mcs_dl_codes[mcs];
1238
1239 osmo_pbit2ubit_ext(upp, 0, l2_data, code->usf_len, code->hdr_len, 1);
1240 osmo_crc8gen_set_bits(&gsm0503_mcs_crc8_hdr, upp,
1241 code->hdr_len, upp + code->hdr_len);
1242
1243 osmo_conv_encode(code->hdr_conv, upp, C);
1244
1245 /* MCS-5,6 header direct puncture instead of table */
1246 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
1247 memcpy(hc, C, code->hdr_code_len);
1248 hc[99] = hc[98];
1249 return 0;
1250 }
1251
1252 if (!code->hdr_punc) {
1253 /* Invalid MCS-X header puncture matrix */
1254 return -1;
1255 }
1256
1257 for (i = 0, j = 0; i < code->hdr_code_len; i++) {
1258 if (!code->hdr_punc[i])
1259 hc[j++] = C[i];
1260 }
1261
1262 return 0;
1263}
1264
Harald Welteb9946d32017-06-12 09:40:16 +02001265static int egprs_encode_data(ubit_t *c, const uint8_t *l2_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001266 int mcs, int p, int blk)
1267{
1268 int i, j, data_len;
1269 ubit_t u[EGPRS_DATA_U_MAX], C[EGPRS_DATA_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001270 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001271
1272 code = &gsm0503_mcs_dl_codes[mcs];
1273
1274 /*
1275 * Dual block - MCS-7,8,9
1276 * Single block - MCS-1,2,3,4,5,6
1277 */
1278 if (mcs >= EGPRS_MCS7)
1279 data_len = code->data_len / 2;
1280 else
1281 data_len = code->data_len;
1282
1283 osmo_pbit2ubit_ext(u, 0, l2_data,
1284 code->usf_len + code->hdr_len + blk * data_len, data_len, 1);
1285
1286 osmo_crc16gen_set_bits(&gsm0503_mcs_crc12, u, data_len, u + data_len);
1287
1288 osmo_conv_encode(code->data_conv, u, C);
1289
1290 if (!code->data_punc[p]) {
1291 /* Invalid MCS-X data puncture matrix */
1292 return -1;
1293 }
1294
1295 for (i = 0, j = 0; i < code->data_code_len; i++) {
1296 if (!code->data_punc[p][i])
1297 c[j++] = C[i];
1298 }
1299
1300 return 0;
1301}
1302
1303/*
1304 * Parse EGPRS DL header for coding and puncturing scheme (CPS)
1305 *
1306 * Type 1 - MCS-7,8,9
1307 * Type 2 - MCS-5,6
1308 * Type 3 - MCS-1,2,3,4
1309 */
1310static int egprs_parse_dl_cps(struct egprs_cps *cps,
Harald Welteb9946d32017-06-12 09:40:16 +02001311 const union gprs_rlc_dl_hdr_egprs *hdr, int type)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001312{
1313 uint8_t bits;
1314
1315 switch (type) {
1316 case EGPRS_HDR_TYPE1:
1317 bits = hdr->type1.cps;
1318 break;
1319 case EGPRS_HDR_TYPE2:
1320 bits = hdr->type2.cps;
1321 break;
1322 case EGPRS_HDR_TYPE3:
1323 bits = hdr->type3.cps;
1324 break;
1325 default:
1326 return -1;
1327 }
1328
1329 return egprs_get_cps(cps, type, bits);
1330}
1331
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001332/*! EGPRS DL message encoding
Harald Weltec6636782017-06-12 14:59:37 +02001333 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1334 * \param[in] l2_data L2 (MAC) block to be encoded
1335 * \param[in] l2_len length of l2_data in bytes, used to determine MCS
Vadim Yanitskiy8055cdd2020-03-30 18:16:38 +07001336 * \returns number of bits encoded; negative on error */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001337int gsm0503_pdtch_egprs_encode(ubit_t *bursts,
Harald Welteb9946d32017-06-12 09:40:16 +02001338 const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001339{
1340 ubit_t hc[EGPRS_DATA_C_MAX], dc[EGPRS_DATA_DC_MAX];
1341 ubit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
1342 uint8_t mcs;
1343 struct egprs_cps cps;
1344 union gprs_rlc_dl_hdr_egprs *hdr;
1345
1346 switch (l2_len) {
1347 case 27:
1348 mcs = EGPRS_MCS1;
1349 break;
1350 case 33:
1351 mcs = EGPRS_MCS2;
1352 break;
1353 case 42:
1354 mcs = EGPRS_MCS3;
1355 break;
1356 case 49:
1357 mcs = EGPRS_MCS4;
1358 break;
1359 case 60:
1360 mcs = EGPRS_MCS5;
1361 break;
1362 case 78:
1363 mcs = EGPRS_MCS6;
1364 break;
1365 case 118:
1366 mcs = EGPRS_MCS7;
1367 break;
1368 case 142:
1369 mcs = EGPRS_MCS8;
1370 break;
1371 case 154:
1372 mcs = EGPRS_MCS9;
1373 break;
1374 default:
1375 return -1;
1376 }
1377
1378 /* Read header for USF and puncturing matrix selection. */
1379 hdr = (union gprs_rlc_dl_hdr_egprs *) l2_data;
1380
1381 switch (mcs) {
1382 case EGPRS_MCS1:
1383 case EGPRS_MCS2:
1384 case EGPRS_MCS3:
1385 case EGPRS_MCS4:
1386 /* Check for valid CPS and matching MCS to message size */
1387 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE3) < 0) ||
1388 (cps.mcs != mcs))
1389 goto bad_header;
1390
1391 egprs_encode_hdr(hc, l2_data, mcs);
1392 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1393 egprs_type3_map(bursts, hc, dc, hdr->type3.usf);
1394 break;
1395 case EGPRS_MCS5:
1396 case EGPRS_MCS6:
1397 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE2) < 0) ||
1398 (cps.mcs != mcs))
1399 goto bad_header;
1400
1401 egprs_encode_hdr(hc, l2_data, mcs);
1402 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1403 egprs_type2_map(bursts, hc, dc, hdr->type2.usf);
1404 break;
1405 case EGPRS_MCS7:
1406 case EGPRS_MCS8:
1407 case EGPRS_MCS9:
1408 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE1) < 0) ||
1409 (cps.mcs != mcs))
1410 goto bad_header;
1411
1412 egprs_encode_hdr(hc, l2_data, mcs);
1413 egprs_encode_data(c1, l2_data, mcs, cps.p[0], 0);
1414 egprs_encode_data(c2, l2_data, mcs, cps.p[1], 1);
1415 egprs_type1_map(bursts, hc, c1, c2, hdr->type1.usf, mcs);
1416 break;
1417 }
1418
1419 return mcs >= EGPRS_MCS5 ?
1420 GSM0503_EGPRS_BURSTS_NBITS : GSM0503_GPRS_BURSTS_NBITS;
1421
1422bad_header:
1423 /* Invalid EGPRS MCS-X header */
1424 return -1;
1425}
1426
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001427/*! GPRS DL message encoding
Harald Weltec6636782017-06-12 14:59:37 +02001428 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1429 * \param[in] l2_data L2 (MAC) block to be encoded
1430 * \param[in] l2_len length of l2_data in bytes, used to determine CS
Vadim Yanitskiy8055cdd2020-03-30 18:16:38 +07001431 * \returns number of bits encoded; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001432int gsm0503_pdtch_encode(ubit_t *bursts, const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001433{
1434 ubit_t iB[456], cB[676];
1435 const ubit_t *hl_hn;
1436 ubit_t conv[334];
1437 int i, j, usf;
1438
1439 switch (l2_len) {
1440 case 23:
1441 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
1442
1443 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
1444
1445 osmo_conv_encode(&gsm0503_xcch, conv, cB);
1446
1447 hl_hn = gsm0503_pdtch_hl_hn_ubit[0];
1448
1449 break;
1450 case 34:
1451 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 271, 1);
1452 usf = l2_data[0] & 0x7;
1453
1454 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1455 271, conv + 3 + 271);
1456
1457 memcpy(conv, gsm0503_usf2six[usf], 6);
1458
1459 osmo_conv_encode(&gsm0503_cs2_np, conv, cB);
1460
1461 for (i = 0, j = 0; i < 588; i++)
1462 if (!gsm0503_puncture_cs2[i])
1463 cB[j++] = cB[i];
1464
1465 hl_hn = gsm0503_pdtch_hl_hn_ubit[1];
1466
1467 break;
1468 case 40:
1469 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 315, 1);
1470 usf = l2_data[0] & 0x7;
1471
1472 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1473 315, conv + 3 + 315);
1474
1475 memcpy(conv, gsm0503_usf2six[usf], 6);
1476
1477 osmo_conv_encode(&gsm0503_cs3_np, conv, cB);
1478
1479 for (i = 0, j = 0; i < 676; i++)
1480 if (!gsm0503_puncture_cs3[i])
1481 cB[j++] = cB[i];
1482
1483 hl_hn = gsm0503_pdtch_hl_hn_ubit[2];
1484
1485 break;
1486 case 54:
1487 osmo_pbit2ubit_ext(cB, 9, l2_data, 0, 431, 1);
1488 usf = l2_data[0] & 0x7;
1489
1490 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, cB + 9,
1491 431, cB + 9 + 431);
1492
1493 memcpy(cB, gsm0503_usf2twelve_ubit[usf], 12);
1494
1495 hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1496
1497 break;
1498 default:
1499 return -1;
1500 }
1501
1502 gsm0503_xcch_interleave(cB, iB);
1503
1504 for (i = 0; i < 4; i++) {
1505 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1506 hl_hn + i * 2, hl_hn + i * 2 + 1);
1507 }
1508
1509 return GSM0503_GPRS_BURSTS_NBITS;
1510}
1511
1512/*
1513 * GSM TCH/F FR/EFR transcoding
1514 */
1515
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001516/*! assemble a FR codec frame in format as used inside RTP
Harald Weltec6636782017-06-12 14:59:37 +02001517 * \param[out] tch_data Codec frame in RTP format
1518 * \param[in] b_bits Codec frame in 'native' format
1519 * \param[in] net_order FIXME */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001520static void tch_fr_reassemble(uint8_t *tch_data,
Harald Welteb9946d32017-06-12 09:40:16 +02001521 const ubit_t *b_bits, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001522{
1523 int i, j, k, l, o;
1524
1525 tch_data[0] = 0xd << 4;
1526 memset(tch_data + 1, 0, 32);
1527
1528 if (net_order) {
1529 for (i = 0, j = 4; i < 260; i++, j++)
1530 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1531
1532 return;
1533 }
1534
1535 /* reassemble d-bits */
1536 i = 0; /* counts bits */
1537 j = 4; /* counts output bits */
1538 k = gsm0503_gsm_fr_map[0]-1; /* current number bit in element */
1539 l = 0; /* counts element bits */
1540 o = 0; /* offset input bits */
1541 while (i < 260) {
1542 tch_data[j >> 3] |= (b_bits[k + o] << (7 - (j & 7)));
1543 if (--k < 0) {
1544 o += gsm0503_gsm_fr_map[l];
1545 k = gsm0503_gsm_fr_map[++l]-1;
1546 }
1547 i++;
1548 j++;
1549 }
1550}
1551
1552static void tch_fr_disassemble(ubit_t *b_bits,
Harald Welteb9946d32017-06-12 09:40:16 +02001553 const uint8_t *tch_data, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001554{
1555 int i, j, k, l, o;
1556
1557 if (net_order) {
1558 for (i = 0, j = 4; i < 260; i++, j++)
1559 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1560
1561 return;
1562 }
1563
1564 i = 0; /* counts bits */
1565 j = 4; /* counts input bits */
1566 k = gsm0503_gsm_fr_map[0] - 1; /* current number bit in element */
1567 l = 0; /* counts element bits */
1568 o = 0; /* offset output bits */
1569 while (i < 260) {
1570 b_bits[k + o] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1571 if (--k < 0) {
1572 o += gsm0503_gsm_fr_map[l];
1573 k = gsm0503_gsm_fr_map[++l] - 1;
1574 }
1575 i++;
1576 j++;
1577 }
1578}
1579
Harald Weltec6636782017-06-12 14:59:37 +02001580/* assemble a HR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001581static void tch_hr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001582{
1583 int i, j;
1584
1585 tch_data[0] = 0x00; /* F = 0, FT = 000 */
1586 memset(tch_data + 1, 0, 14);
1587
1588 for (i = 0, j = 8; i < 112; i++, j++)
1589 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1590}
1591
Harald Welteb9946d32017-06-12 09:40:16 +02001592static void tch_hr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001593{
1594 int i, j;
1595
1596 for (i = 0, j = 8; i < 112; i++, j++)
1597 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1598}
1599
Harald Weltec6636782017-06-12 14:59:37 +02001600/* assemble a EFR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001601static void tch_efr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001602{
1603 int i, j;
1604
1605 tch_data[0] = 0xc << 4;
1606 memset(tch_data + 1, 0, 30);
1607
1608 for (i = 0, j = 4; i < 244; i++, j++)
1609 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1610}
1611
Harald Welteb9946d32017-06-12 09:40:16 +02001612static void tch_efr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001613{
1614 int i, j;
1615
1616 for (i = 0, j = 4; i < 244; i++, j++)
1617 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1618}
1619
Harald Weltec6636782017-06-12 14:59:37 +02001620/* assemble a AMR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001621static void tch_amr_reassemble(uint8_t *tch_data, const ubit_t *d_bits, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001622{
1623 int i, j;
1624
1625 memset(tch_data, 0, (len + 7) >> 3);
1626
1627 for (i = 0, j = 0; i < len; i++, j++)
1628 tch_data[j >> 3] |= (d_bits[i] << (7 - (j & 7)));
1629}
1630
Harald Welteb9946d32017-06-12 09:40:16 +02001631static void tch_amr_disassemble(ubit_t *d_bits, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001632{
1633 int i, j;
1634
1635 for (i = 0, j = 0; i < len; i++, j++)
1636 d_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1637}
1638
Philipp Maier898c9c62020-02-06 14:25:01 +01001639/* Append STI and MI bits to the SID_UPDATE frame, see also
1640 * 3GPP TS 26.101, chapter 4.2.3 AMR Core Frame with comfort noise bits */
1641static void tch_amr_sid_update_append(ubit_t *sid_update, uint8_t sti, uint8_t mi)
1642{
1643 /* Zero out the space that had been used by the CRC14 */
1644 memset(sid_update + 35, 0, 14);
1645
1646 /* Append STI and MI parameters */
1647 sid_update[35] = sti & 1;
1648 sid_update[36] = mi & 1;
1649 sid_update[37] = mi >> 1 & 1;
1650 sid_update[38] = mi >> 2 & 1;
1651}
1652
1653/* Extract a SID UPDATE fram the sbits of an FR AMR frame */
1654static void extract_afs_sid_update(sbit_t *sid_update, const sbit_t *sbits)
1655{
1656
1657 unsigned int i;
1658
1659 sbits += 32;
1660
1661 for (i = 0; i < 53; i++) {
1662 sid_update[0] = sbits[0];
1663 sid_update[1] = sbits[1];
1664 sid_update[2] = sbits[2];
1665 sid_update[3] = sbits[3];
1666 sid_update += 4;
1667 sbits += 8;
1668 }
1669
1670}
1671
Harald Weltec6636782017-06-12 14:59:37 +02001672/* re-arrange according to TS 05.03 Table 2 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001673static void tch_fr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001674{
1675 int i;
1676
1677 for (i = 0; i < 260; i++)
1678 b_bits[gsm610_bitorder[i]] = d_bits[i];
1679}
1680
Harald Weltec6636782017-06-12 14:59:37 +02001681/* re-arrange according to TS 05.03 Table 2 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001682static void tch_fr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001683{
1684 int i;
1685
1686 for (i = 0; i < 260; i++)
1687 d_bits[i] = b_bits[gsm610_bitorder[i]];
1688}
1689
Harald Weltec6636782017-06-12 14:59:37 +02001690/* re-arrange according to TS 05.03 Table 3a (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001691static void tch_hr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001692{
1693 int i;
1694
1695 const uint16_t *map;
1696
1697 if (!d_bits[93] && !d_bits[94])
1698 map = gsm620_unvoiced_bitorder;
1699 else
1700 map = gsm620_voiced_bitorder;
1701
1702 for (i = 0; i < 112; i++)
1703 b_bits[map[i]] = d_bits[i];
1704}
1705
Harald Weltec6636782017-06-12 14:59:37 +02001706/* re-arrange according to TS 05.03 Table 3a (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001707static void tch_hr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001708{
1709 int i;
1710 const uint16_t *map;
1711
1712 if (!b_bits[34] && !b_bits[35])
1713 map = gsm620_unvoiced_bitorder;
1714 else
1715 map = gsm620_voiced_bitorder;
1716
1717 for (i = 0; i < 112; i++)
1718 d_bits[i] = b_bits[map[i]];
1719}
1720
Harald Weltec6636782017-06-12 14:59:37 +02001721/* re-arrange according to TS 05.03 Table 6 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001722static void tch_efr_d_to_w(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001723{
1724 int i;
1725
1726 for (i = 0; i < 260; i++)
1727 b_bits[gsm660_bitorder[i]] = d_bits[i];
1728}
1729
Harald Weltec6636782017-06-12 14:59:37 +02001730/* re-arrange according to TS 05.03 Table 6 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001731static void tch_efr_w_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001732{
1733 int i;
1734
1735 for (i = 0; i < 260; i++)
1736 d_bits[i] = b_bits[gsm660_bitorder[i]];
1737}
1738
Harald Weltec6636782017-06-12 14:59:37 +02001739/* extract the 65 protected class1a+1b bits */
Harald Welteb9946d32017-06-12 09:40:16 +02001740static void tch_efr_protected(const ubit_t *s_bits, ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001741{
1742 int i;
1743
1744 for (i = 0; i < 65; i++)
1745 b_bits[i] = s_bits[gsm0503_gsm_efr_protected_bits[i] - 1];
1746}
1747
Harald Welteb9946d32017-06-12 09:40:16 +02001748static void tch_fr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001749{
1750 int i;
1751
1752 for (i = 0; i < 91; i++) {
1753 d[i << 1] = u[i];
1754 d[(i << 1) + 1] = u[184 - i];
1755 }
1756
1757 for (i = 0; i < 3; i++)
1758 p[i] = u[91 + i];
1759}
1760
Harald Welteb9946d32017-06-12 09:40:16 +02001761static void tch_fr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001762{
1763 int i;
1764
1765 for (i = 0; i < 91; i++) {
1766 u[i] = d[i << 1];
1767 u[184 - i] = d[(i << 1) + 1];
1768 }
1769
1770 for (i = 0; i < 3; i++)
1771 u[91 + i] = p[i];
1772}
1773
Harald Welteb9946d32017-06-12 09:40:16 +02001774static void tch_hr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001775{
1776 memcpy(d, u, 95);
1777 memcpy(p, u + 95, 3);
1778}
1779
Harald Welteb9946d32017-06-12 09:40:16 +02001780static void tch_hr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001781{
1782 memcpy(u, d, 95);
1783 memcpy(u + 95, p, 3);
1784}
1785
Harald Welteb9946d32017-06-12 09:40:16 +02001786static void tch_efr_reorder(ubit_t *w, const ubit_t *s, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001787{
1788 memcpy(w, s, 71);
1789 w[71] = w[72] = s[69];
1790 memcpy(w + 73, s + 71, 50);
1791 w[123] = w[124] = s[119];
1792 memcpy(w + 125, s + 121, 53);
1793 w[178] = w[179] = s[172];
1794 memcpy(w + 180, s + 174, 50);
1795 w[230] = w[231] = s[222];
1796 memcpy(w + 232, s + 224, 20);
1797 memcpy(w + 252, p, 8);
1798}
1799
Harald Welteb9946d32017-06-12 09:40:16 +02001800static void tch_efr_unreorder(ubit_t *s, ubit_t *p, const ubit_t *w)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001801{
1802 int sum;
1803
1804 memcpy(s, w, 71);
1805 sum = s[69] + w[71] + w[72];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001806 s[69] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001807 memcpy(s + 71, w + 73, 50);
1808 sum = s[119] + w[123] + w[124];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001809 s[119] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001810 memcpy(s + 121, w + 125, 53);
1811 sum = s[172] + w[178] + w[179];
1812 s[172] = (sum > 2);
1813 memcpy(s + 174, w + 180, 50);
Niro Mahasinghe834e2ac2017-11-03 12:22:34 +01001814 sum = s[222] + w[230] + w[231];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001815 s[222] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001816 memcpy(s + 224, w + 232, 20);
1817 memcpy(p, w + 252, 8);
1818}
1819
Harald Welteb9946d32017-06-12 09:40:16 +02001820static void tch_amr_merge(ubit_t *u, const ubit_t *d, const ubit_t *p, int len, int prot)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001821{
1822 memcpy(u, d, prot);
1823 memcpy(u + prot, p, 6);
1824 memcpy(u + prot + 6, d + prot, len - prot);
1825}
1826
Harald Welteb9946d32017-06-12 09:40:16 +02001827static void tch_amr_unmerge(ubit_t *d, ubit_t *p, const ubit_t *u, int len, int prot)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001828{
1829 memcpy(d, u, prot);
1830 memcpy(p, u + prot, 6);
1831 memcpy(d + prot, u + prot + 6, len - prot);
1832}
1833
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001834/*! Perform channel decoding of a FR/EFR channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001835 * \param[out] tch_data Codec frame in RTP payload format
1836 * \param[in] bursts buffer containing the symbols of 8 bursts
1837 * \param[in] net_order FIXME
1838 * \param[in] efr Is this channel using EFR (1) or FR (0)
1839 * \param[out] n_errors Number of detected bit errors
1840 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02001841 * \returns length of bytes used in \a tch_data output buffer; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001842int gsm0503_tch_fr_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001843 int net_order, int efr, int *n_errors, int *n_bits_total)
1844{
1845 sbit_t iB[912], cB[456], h;
1846 ubit_t conv[185], s[244], w[260], b[65], d[260], p[8];
1847 int i, rv, len, steal = 0;
1848
Harald Weltec6636782017-06-12 14:59:37 +02001849 /* map from 8 bursts to interleaved data bits (iB) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001850 for (i = 0; i < 8; i++) {
1851 gsm0503_tch_burst_unmap(&iB[i * 114],
1852 &bursts[i * 116], &h, i >> 2);
1853 steal -= h;
1854 }
Harald Weltec6636782017-06-12 14:59:37 +02001855 /* we now have the bits of the four bursts (interface 4 in
1856 * Figure 1a of TS 05.03 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001857
1858 gsm0503_tch_fr_deinterleave(cB, iB);
Harald Weltec6636782017-06-12 14:59:37 +02001859 /* we now have the coded bits c(B): interface 3 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001860
1861 if (steal > 0) {
1862 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
1863 if (rv) {
1864 /* Error decoding FACCH frame */
1865 return -1;
1866 }
1867
1868 return 23;
1869 }
1870
1871 osmo_conv_decode_ber(&gsm0503_tch_fr, cB, conv, n_errors, n_bits_total);
Harald Weltec6636782017-06-12 14:59:37 +02001872 /* we now have the data bits 'u': interface 2 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001873
Harald Weltec6636782017-06-12 14:59:37 +02001874 /* input: 'conv', output: d[ata] + p[arity] */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001875 tch_fr_unreorder(d, p, conv);
1876
1877 for (i = 0; i < 78; i++)
1878 d[i + 182] = (cB[i + 378] < 0) ? 1 : 0;
1879
Harald Weltec6636782017-06-12 14:59:37 +02001880 /* check if parity of first 50 (class 1) 'd'-bits match 'p' */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001881 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1882 if (rv) {
1883 /* Error checking CRC8 for the FR part of an EFR/FR frame */
1884 return -1;
1885 }
1886
1887 if (efr) {
1888 tch_efr_d_to_w(w, d);
Harald Weltec6636782017-06-12 14:59:37 +02001889 /* we now have the preliminary-coded bits w(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001890
1891 tch_efr_unreorder(s, p, w);
Harald Weltec6636782017-06-12 14:59:37 +02001892 /* we now have the data delivered to the preliminary
1893 * channel encoding unit s(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001894
Harald Weltec6636782017-06-12 14:59:37 +02001895 /* extract the 65 most important bits according TS 05.03 3.1.1.1 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001896 tch_efr_protected(s, b);
1897
Harald Weltec6636782017-06-12 14:59:37 +02001898 /* perform CRC-8 on 65 most important bits (50 bits of
1899 * class 1a + 15 bits of class 1b) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001900 rv = osmo_crc8gen_check_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1901 if (rv) {
1902 /* Error checking CRC8 for the EFR part of an EFR frame */
1903 return -1;
1904 }
1905
1906 tch_efr_reassemble(tch_data, s);
1907
1908 len = GSM_EFR_BYTES;
1909 } else {
1910 tch_fr_d_to_b(w, d);
1911
1912 tch_fr_reassemble(tch_data, w, net_order);
1913
1914 len = GSM_FR_BYTES;
1915 }
1916
1917 return len;
1918}
1919
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001920/*! Perform channel encoding on a TCH/FS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001921 * \param[out] bursts caller-allocated output buffer for bursts bits
1922 * \param[in] tch_data Codec input data in RTP payload format
1923 * \param[in] len Length of \a tch_data in bytes
1924 * \param[in] net_order FIXME
1925 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001926int gsm0503_tch_fr_encode(ubit_t *bursts, const uint8_t *tch_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001927 int len, int net_order)
1928{
1929 ubit_t iB[912], cB[456], h;
1930 ubit_t conv[185], w[260], b[65], s[244], d[260], p[8];
1931 int i;
1932
1933 switch (len) {
1934 case GSM_EFR_BYTES: /* TCH EFR */
1935
1936 tch_efr_disassemble(s, tch_data);
1937
1938 tch_efr_protected(s, b);
1939
1940 osmo_crc8gen_set_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1941
1942 tch_efr_reorder(w, s, p);
1943
1944 tch_efr_w_to_d(d, w);
1945
1946 goto coding_efr_fr;
1947 case GSM_FR_BYTES: /* TCH FR */
1948 tch_fr_disassemble(w, tch_data, net_order);
1949
1950 tch_fr_b_to_d(d, w);
1951
1952coding_efr_fr:
1953 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1954
1955 tch_fr_reorder(conv, d, p);
1956
1957 memcpy(cB + 378, d + 182, 78);
1958
1959 osmo_conv_encode(&gsm0503_tch_fr, conv, cB);
1960
1961 h = 0;
1962
1963 break;
1964 case GSM_MACBLOCK_LEN: /* FACCH */
1965 _xcch_encode_cB(cB, tch_data);
1966
1967 h = 1;
1968
1969 break;
1970 default:
1971 return -1;
1972 }
1973
1974 gsm0503_tch_fr_interleave(cB, iB);
1975
1976 for (i = 0; i < 8; i++) {
1977 gsm0503_tch_burst_map(&iB[i * 114],
1978 &bursts[i * 116], &h, i >> 2);
1979 }
1980
1981 return 0;
1982}
1983
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001984/*! Perform channel decoding of a HR(v1) channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001985 * \param[out] tch_data Codec frame in RTP payload format
1986 * \param[in] bursts buffer containing the symbols of 8 bursts
1987 * \param[in] odd Odd (1) or even (0) frame number
1988 * \param[out] n_errors Number of detected bit errors
1989 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02001990 * \returns length of bytes used in \a tch_data output buffer; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001991int gsm0503_tch_hr_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001992 int *n_errors, int *n_bits_total)
1993{
1994 sbit_t iB[912], cB[456], h;
1995 ubit_t conv[98], b[112], d[112], p[3];
1996 int i, rv, steal = 0;
1997
1998 /* Only unmap the stealing bits */
1999 if (!odd) {
2000 for (i = 0; i < 4; i++) {
2001 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
2002 steal -= h;
2003 }
2004
2005 for (i = 2; i < 5; i++) {
2006 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
2007 steal -= h;
2008 }
2009 }
2010
2011 /* If we found a stole FACCH, but only at correct alignment */
2012 if (steal > 0) {
2013 for (i = 0; i < 6; i++) {
2014 gsm0503_tch_burst_unmap(&iB[i * 114],
2015 &bursts[i * 116], NULL, i >> 2);
2016 }
2017
2018 for (i = 2; i < 4; i++) {
2019 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
2020 &bursts[i * 116], NULL, 1);
2021 }
2022
2023 gsm0503_tch_fr_deinterleave(cB, iB);
2024
2025 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2026 if (rv) {
2027 /* Error decoding FACCH frame */
2028 return -1;
2029 }
2030
2031 return GSM_MACBLOCK_LEN;
2032 }
2033
2034 for (i = 0; i < 4; i++) {
2035 gsm0503_tch_burst_unmap(&iB[i * 114],
2036 &bursts[i * 116], NULL, i >> 1);
2037 }
2038
2039 gsm0503_tch_hr_deinterleave(cB, iB);
2040
2041 osmo_conv_decode_ber(&gsm0503_tch_hr, cB, conv, n_errors, n_bits_total);
2042
2043 tch_hr_unreorder(d, p, conv);
2044
2045 for (i = 0; i < 17; i++)
2046 d[i + 95] = (cB[i + 211] < 0) ? 1 : 0;
2047
2048 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
2049 if (rv) {
2050 /* Error checking CRC8 for an HR frame */
2051 return -1;
2052 }
2053
2054 tch_hr_d_to_b(b, d);
2055
2056 tch_hr_reassemble(tch_data, b);
2057
2058 return 15;
2059}
2060
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002061/*! Perform channel encoding on a TCH/HS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002062 * \param[out] bursts caller-allocated output buffer for bursts bits
2063 * \param[in] tch_data Codec input data in RTP payload format
2064 * \param[in] len Length of \a tch_data in bytes
2065 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002066int gsm0503_tch_hr_encode(ubit_t *bursts, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002067{
2068 ubit_t iB[912], cB[456], h;
2069 ubit_t conv[98], b[112], d[112], p[3];
2070 int i;
2071
2072 switch (len) {
2073 case 15: /* TCH HR */
2074 tch_hr_disassemble(b, tch_data);
2075
2076 tch_hr_b_to_d(d, b);
2077
2078 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
2079
2080 tch_hr_reorder(conv, d, p);
2081
2082 osmo_conv_encode(&gsm0503_tch_hr, conv, cB);
2083
2084 memcpy(cB + 211, d + 95, 17);
2085
2086 h = 0;
2087
2088 gsm0503_tch_hr_interleave(cB, iB);
2089
2090 for (i = 0; i < 4; i++) {
2091 gsm0503_tch_burst_map(&iB[i * 114],
2092 &bursts[i * 116], &h, i >> 1);
2093 }
2094
2095 break;
2096 case GSM_MACBLOCK_LEN: /* FACCH */
2097 _xcch_encode_cB(cB, tch_data);
2098
2099 h = 1;
2100
2101 gsm0503_tch_fr_interleave(cB, iB);
2102
2103 for (i = 0; i < 6; i++) {
2104 gsm0503_tch_burst_map(&iB[i * 114],
2105 &bursts[i * 116], &h, i >> 2);
2106 }
2107
2108 for (i = 2; i < 4; i++) {
2109 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2110 &bursts[i * 116], &h, 1);
2111 }
2112
2113 break;
2114 default:
2115 return -1;
2116 }
2117
2118 return 0;
2119}
2120
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002121/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002122 * \param[out] tch_data Codec frame in RTP payload format
2123 * \param[in] bursts buffer containing the symbols of 8 bursts
2124 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2125 * \param[in] codec array of active codecs (active codec set)
2126 * \param[in] codecs number of codecs in \a codec
2127 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2128 * \param[out] cmr Output in \a codec_mode_req = 1
2129 * \param[out] n_errors Number of detected bit errors
2130 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02002131 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2132 * codec out of range; negative on error
2133 */
Harald Welteb9946d32017-06-12 09:40:16 +02002134int gsm0503_tch_afs_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002135 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2136 uint8_t *cmr, int *n_errors, int *n_bits_total)
2137{
Philipp Maier898c9c62020-02-06 14:25:01 +01002138 return gsm0503_tch_afs_decode_dtx(tch_data, bursts, codec_mode_req,
2139 codec, codecs, ft, cmr, n_errors,
2140 n_bits_total, NULL);
2141}
2142
2143/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
2144 * \param[out] tch_data Codec frame in RTP payload format
2145 * \param[in] bursts buffer containing the symbols of 8 bursts
2146 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2147 * \param[in] codec array of active codecs (active codec set)
2148 * \param[in] codecs number of codecs in \a codec
2149 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2150 * \param[out] cmr Output in \a codec_mode_req = 1
2151 * \param[out] n_errors Number of detected bit errors
2152 * \param[out] n_bits_total Total number of bits
2153 * \param[inout] dtx DTX frame type output, previous DTX frame type input
2154 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2155 * codec out of range; negative on error
2156 */
2157int gsm0503_tch_afs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts,
2158 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2159 uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx)
2160{
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002161 sbit_t iB[912], cB[456], h;
2162 ubit_t d[244], p[6], conv[250];
2163 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
Philipp Maier898c9c62020-02-06 14:25:01 +01002164 ubit_t cBd[456];
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002165 *n_errors = 0; *n_bits_total = 0;
Philipp Maier898c9c62020-02-06 14:25:01 +01002166 static ubit_t sid_first_dummy[64] = { 0 };
2167 sbit_t sid_update_enc[256];
2168 uint8_t dtx_prev;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002169
2170 for (i=0; i<8; i++) {
2171 gsm0503_tch_burst_unmap(&iB[i * 114], &bursts[i * 116], &h, i >> 2);
2172 steal -= h;
2173 }
2174
2175 gsm0503_tch_fr_deinterleave(cB, iB);
2176
2177 if (steal > 0) {
2178 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2179 if (rv) {
2180 /* Error decoding FACCH frame */
2181 return -1;
2182 }
2183
2184 return GSM_MACBLOCK_LEN;
2185 }
2186
Philipp Maier898c9c62020-02-06 14:25:01 +01002187 /* Determine the DTX frame type (SID_UPDATE, ONSET etc...) */
2188 if (dtx) {
2189 osmo_sbit2ubit(cBd, cB, 456);
2190 dtx_prev = *dtx;
2191 *dtx = gsm0503_detect_afs_dtx_frame(n_errors, n_bits_total, cBd);
2192
2193 if (dtx_prev == AFS_SID_UPDATE && *dtx == AMR_OTHER) {
2194 /* NOTE: The AFS_SID_UPDATE frame is splitted into
2195 * two half rate frames. If the id marker frame
2196 * (AFS_SID_UPDATE) is detected the following frame
2197 * contains the actual comfort noised data part of
2198 * (AFS_SID_UPDATE_CN). */
2199 *dtx = AFS_SID_UPDATE_CN;
2200
2201 extract_afs_sid_update(sid_update_enc, cB);
2202 osmo_conv_decode_ber(&gsm0503_tch_axs_sid_update,
2203 sid_update_enc, conv, n_errors,
2204 n_bits_total);
2205 rv = osmo_crc16gen_check_bits(&gsm0503_amr_crc14, conv,
2206 35, conv + 35);
2207 if (rv != 0) {
2208 /* Error checking CRC14 for an AMR SID_UPDATE frame */
2209 return -1;
2210 }
2211
2212 tch_amr_sid_update_append(conv, 1,
2213 (codec_mode_req) ? codec[*ft]
2214 : codec[id]);
2215 tch_amr_reassemble(tch_data, conv, 39);
2216 len = 5;
2217 goto out;
2218 } else if (*dtx == AFS_SID_FIRST) {
2219 tch_amr_sid_update_append(sid_first_dummy, 0,
2220 (codec_mode_req) ? codec[*ft]
2221 : codec[id]);
2222 tch_amr_reassemble(tch_data, conv, 39);
2223 len = 5;
2224 goto out;
2225 } else if (*dtx == AFS_ONSET) {
2226 len = 0;
2227 goto out;
2228 }
2229 }
2230
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002231 for (i = 0; i < 4; i++) {
2232 for (j = 0, k = 0; j < 8; j++)
2233 k += abs(((int)gsm0503_afs_ic_sbit[i][j]) - ((int)cB[j]));
2234
2235 if (i == 0 || k < best) {
2236 best = k;
2237 id = i;
2238 }
2239 }
2240
2241 /* Check if indicated codec fits into range of codecs */
2242 if (id >= codecs) {
2243 /* Codec mode out of range, return id */
2244 return id;
2245 }
2246
2247 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2248 case 7: /* TCH/AFS12.2 */
2249 osmo_conv_decode_ber(&gsm0503_tch_afs_12_2, cB + 8,
2250 conv, n_errors, n_bits_total);
2251
2252 tch_amr_unmerge(d, p, conv, 244, 81);
2253
2254 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 81, p);
2255 if (rv) {
2256 /* Error checking CRC8 for an AMR 12.2 frame */
2257 return -1;
2258 }
2259
2260 tch_amr_reassemble(tch_data, d, 244);
2261
2262 len = 31;
2263
2264 break;
2265 case 6: /* TCH/AFS10.2 */
2266 osmo_conv_decode_ber(&gsm0503_tch_afs_10_2, cB + 8,
2267 conv, n_errors, n_bits_total);
2268
2269 tch_amr_unmerge(d, p, conv, 204, 65);
2270
2271 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 65, p);
2272 if (rv) {
2273 /* Error checking CRC8 for an AMR 10.2 frame */
2274 return -1;
2275 }
2276
2277 tch_amr_reassemble(tch_data, d, 204);
2278
2279 len = 26;
2280
2281 break;
2282 case 5: /* TCH/AFS7.95 */
2283 osmo_conv_decode_ber(&gsm0503_tch_afs_7_95, cB + 8,
2284 conv, n_errors, n_bits_total);
2285
2286 tch_amr_unmerge(d, p, conv, 159, 75);
2287
2288 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 75, p);
2289 if (rv) {
2290 /* Error checking CRC8 for an AMR 7.95 frame */
2291 return -1;
2292 }
2293
2294 tch_amr_reassemble(tch_data, d, 159);
2295
2296 len = 20;
2297
2298 break;
2299 case 4: /* TCH/AFS7.4 */
2300 osmo_conv_decode_ber(&gsm0503_tch_afs_7_4, cB + 8,
2301 conv, n_errors, n_bits_total);
2302
2303 tch_amr_unmerge(d, p, conv, 148, 61);
2304
2305 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2306 if (rv) {
2307 /* Error checking CRC8 for an AMR 7.4 frame */
2308 return -1;
2309 }
2310
2311 tch_amr_reassemble(tch_data, d, 148);
2312
2313 len = 19;
2314
2315 break;
2316 case 3: /* TCH/AFS6.7 */
2317 osmo_conv_decode_ber(&gsm0503_tch_afs_6_7, cB + 8,
2318 conv, n_errors, n_bits_total);
2319
2320 tch_amr_unmerge(d, p, conv, 134, 55);
2321
2322 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2323 if (rv) {
2324 /* Error checking CRC8 for an AMR 6.7 frame */
2325 return -1;
2326 }
2327
2328 tch_amr_reassemble(tch_data, d, 134);
2329
2330 len = 17;
2331
2332 break;
2333 case 2: /* TCH/AFS5.9 */
2334 osmo_conv_decode_ber(&gsm0503_tch_afs_5_9, cB + 8,
2335 conv, n_errors, n_bits_total);
2336
2337 tch_amr_unmerge(d, p, conv, 118, 55);
2338
2339 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2340 if (rv) {
2341 /* Error checking CRC8 for an AMR 5.9 frame */
2342 return -1;
2343 }
2344
2345 tch_amr_reassemble(tch_data, d, 118);
2346
2347 len = 15;
2348
2349 break;
2350 case 1: /* TCH/AFS5.15 */
2351 osmo_conv_decode_ber(&gsm0503_tch_afs_5_15, cB + 8,
2352 conv, n_errors, n_bits_total);
2353
2354 tch_amr_unmerge(d, p, conv, 103, 49);
2355
2356 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2357 if (rv) {
2358 /* Error checking CRC8 for an AMR 5.15 frame */
2359 return -1;
2360 }
2361
2362 tch_amr_reassemble(tch_data, d, 103);
2363
2364 len = 13;
2365
2366 break;
2367 case 0: /* TCH/AFS4.75 */
2368 osmo_conv_decode_ber(&gsm0503_tch_afs_4_75, cB + 8,
2369 conv, n_errors, n_bits_total);
2370
2371 tch_amr_unmerge(d, p, conv, 95, 39);
2372
2373 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2374 if (rv) {
2375 /* Error checking CRC8 for an AMR 4.75 frame */
2376 return -1;
2377 }
2378
2379 tch_amr_reassemble(tch_data, d, 95);
2380
2381 len = 12;
2382
2383 break;
2384 default:
2385 /* Unknown frame type */
2386 *n_bits_total = 448;
2387 *n_errors = *n_bits_total;
2388 return -1;
2389 }
2390
Philipp Maier898c9c62020-02-06 14:25:01 +01002391out:
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002392 /* Change codec request / indication, if frame is valid */
2393 if (codec_mode_req)
2394 *cmr = id;
2395 else
2396 *ft = id;
2397
2398 return len;
2399}
2400
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002401/*! Perform channel encoding on a TCH/AFS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002402 * \param[out] bursts caller-allocated output buffer for bursts bits
2403 * \param[in] tch_data Codec input data in RTP payload format
2404 * \param[in] len Length of \a tch_data in bytes
2405 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2406 * \param[in] codec Array of codecs (active codec set)
2407 * \param[in] codecs Number of entries in \a codec
2408 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2409 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2410 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002411int gsm0503_tch_afs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002412 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2413 uint8_t cmr)
2414{
2415 ubit_t iB[912], cB[456], h;
2416 ubit_t d[244], p[6], conv[250];
2417 int i;
2418 uint8_t id;
2419
2420 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2421 _xcch_encode_cB(cB, tch_data);
2422
2423 h = 1;
2424
2425 goto facch;
2426 }
2427
2428 h = 0;
2429
2430 if (codec_mode_req) {
2431 if (cmr >= codecs) {
2432 /* FIXME: CMR ID is not in codec list! */
2433 return -1;
2434 }
2435 id = cmr;
2436 } else {
2437 if (ft >= codecs) {
2438 /* FIXME: FT ID is not in codec list! */
2439 return -1;
2440 }
2441 id = ft;
2442 }
2443
2444 switch (codec[ft]) {
2445 case 7: /* TCH/AFS12.2 */
2446 if (len != 31)
2447 goto invalid_length;
2448
2449 tch_amr_disassemble(d, tch_data, 244);
2450
2451 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 81, p);
2452
2453 tch_amr_merge(conv, d, p, 244, 81);
2454
2455 osmo_conv_encode(&gsm0503_tch_afs_12_2, conv, cB + 8);
2456
2457 break;
2458 case 6: /* TCH/AFS10.2 */
2459 if (len != 26)
2460 goto invalid_length;
2461
2462 tch_amr_disassemble(d, tch_data, 204);
2463
2464 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 65, p);
2465
2466 tch_amr_merge(conv, d, p, 204, 65);
2467
2468 osmo_conv_encode(&gsm0503_tch_afs_10_2, conv, cB + 8);
2469
2470 break;
2471 case 5: /* TCH/AFS7.95 */
2472 if (len != 20)
2473 goto invalid_length;
2474
2475 tch_amr_disassemble(d, tch_data, 159);
2476
2477 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 75, p);
2478
2479 tch_amr_merge(conv, d, p, 159, 75);
2480
2481 osmo_conv_encode(&gsm0503_tch_afs_7_95, conv, cB + 8);
2482
2483 break;
2484 case 4: /* TCH/AFS7.4 */
2485 if (len != 19)
2486 goto invalid_length;
2487
2488 tch_amr_disassemble(d, tch_data, 148);
2489
2490 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2491
2492 tch_amr_merge(conv, d, p, 148, 61);
2493
2494 osmo_conv_encode(&gsm0503_tch_afs_7_4, conv, cB + 8);
2495
2496 break;
2497 case 3: /* TCH/AFS6.7 */
2498 if (len != 17)
2499 goto invalid_length;
2500
2501 tch_amr_disassemble(d, tch_data, 134);
2502
2503 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2504
2505 tch_amr_merge(conv, d, p, 134, 55);
2506
2507 osmo_conv_encode(&gsm0503_tch_afs_6_7, conv, cB + 8);
2508
2509 break;
2510 case 2: /* TCH/AFS5.9 */
2511 if (len != 15)
2512 goto invalid_length;
2513
2514 tch_amr_disassemble(d, tch_data, 118);
2515
2516 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2517
2518 tch_amr_merge(conv, d, p, 118, 55);
2519
2520 osmo_conv_encode(&gsm0503_tch_afs_5_9, conv, cB + 8);
2521
2522 break;
2523 case 1: /* TCH/AFS5.15 */
2524 if (len != 13)
2525 goto invalid_length;
2526
2527 tch_amr_disassemble(d, tch_data, 103);
2528
2529 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2530
2531 tch_amr_merge(conv, d, p, 103, 49);
2532
2533 osmo_conv_encode(&gsm0503_tch_afs_5_15, conv, cB + 8);
2534
2535 break;
2536 case 0: /* TCH/AFS4.75 */
2537 if (len != 12)
2538 goto invalid_length;
2539
2540 tch_amr_disassemble(d, tch_data, 95);
2541
2542 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2543
2544 tch_amr_merge(conv, d, p, 95, 39);
2545
2546 osmo_conv_encode(&gsm0503_tch_afs_4_75, conv, cB + 8);
2547
2548 break;
2549 default:
2550 /* FIXME: FT %ft is not supported */
2551 return -1;
2552 }
2553
2554 memcpy(cB, gsm0503_afs_ic_ubit[id], 8);
2555
2556facch:
2557 gsm0503_tch_fr_interleave(cB, iB);
2558
2559 for (i = 0; i < 8; i++) {
2560 gsm0503_tch_burst_map(&iB[i * 114],
2561 &bursts[i * 116], &h, i >> 2);
2562 }
2563
2564 return 0;
2565
2566invalid_length:
2567 /* FIXME: payload length %len does not comply with codec type %ft */
2568 return -1;
2569}
2570
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002571/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002572 * \param[out] tch_data Codec frame in RTP payload format
2573 * \param[in] bursts buffer containing the symbols of 8 bursts
2574 * \param[in] odd Is this an odd (1) or even (0) frame number?
2575 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2576 * \param[in] codec array of active codecs (active codec set)
2577 * \param[in] codecs number of codecs in \a codec
2578 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2579 * \param[out] cmr Output in \a codec_mode_req = 1
2580 * \param[out] n_errors Number of detected bit errors
2581 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02002582 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2583 * codec out of range; negative on error
2584 */
Harald Welteb9946d32017-06-12 09:40:16 +02002585int gsm0503_tch_ahs_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002586 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2587 uint8_t *cmr, int *n_errors, int *n_bits_total)
2588{
Philipp Maier898c9c62020-02-06 14:25:01 +01002589 return gsm0503_tch_ahs_decode_dtx(tch_data, bursts, odd, codec_mode_req,
2590 codec, codecs, ft, cmr, n_errors,
2591 n_bits_total, NULL);
2592}
2593
2594/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
2595 * \param[out] tch_data Codec frame in RTP payload format
2596 * \param[in] bursts buffer containing the symbols of 8 bursts
2597 * \param[in] odd Is this an odd (1) or even (0) frame number?
2598 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2599 * \param[in] codec array of active codecs (active codec set)
2600 * \param[in] codecs number of codecs in \a codec
2601 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2602 * \param[out] cmr Output in \a codec_mode_req = 1
2603 * \param[out] n_errors Number of detected bit errors
2604 * \param[out] n_bits_total Total number of bits
2605 * \param[inout] dtx DTX frame type output, previous DTX frame type input
2606 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2607 * codec out of range; negative on error
2608 */
2609int gsm0503_tch_ahs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts, int odd,
2610 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2611 uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx)
2612{
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002613 sbit_t iB[912], cB[456], h;
2614 ubit_t d[244], p[6], conv[135];
2615 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
Philipp Maier898c9c62020-02-06 14:25:01 +01002616 ubit_t cBd[456];
2617 static ubit_t sid_first_dummy[64] = { 0 };
2618 uint8_t dtx_prev;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002619
2620 /* only unmap the stealing bits */
2621 if (!odd) {
2622 for (i = 0; i < 4; i++) {
2623 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
2624 steal -= h;
2625 }
2626 for (i = 2; i < 5; i++) {
2627 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
2628 steal -= h;
2629 }
2630 }
2631
2632 /* if we found a stole FACCH, but only at correct alignment */
2633 if (steal > 0) {
2634 for (i = 0; i < 6; i++) {
2635 gsm0503_tch_burst_unmap(&iB[i * 114],
2636 &bursts[i * 116], NULL, i >> 2);
2637 }
2638
2639 for (i = 2; i < 4; i++) {
2640 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
2641 &bursts[i * 116], NULL, 1);
2642 }
2643
2644 gsm0503_tch_fr_deinterleave(cB, iB);
2645
2646 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2647 if (rv) {
2648 /* Error decoding FACCH frame */
2649 return -1;
2650 }
2651
2652 return GSM_MACBLOCK_LEN;
2653 }
2654
2655 for (i = 0; i < 4; i++) {
2656 gsm0503_tch_burst_unmap(&iB[i * 114],
2657 &bursts[i * 116], NULL, i >> 1);
2658 }
2659
2660 gsm0503_tch_hr_deinterleave(cB, iB);
2661
Philipp Maier898c9c62020-02-06 14:25:01 +01002662 /* Determine the DTX frame type (SID_UPDATE, ONSET etc...) */
2663 if (dtx) {
2664 osmo_sbit2ubit(cBd, cB, 456);
2665 dtx_prev = *dtx;
2666 *dtx = gsm0503_detect_ahs_dtx_frame(n_errors, n_bits_total, cBd);
2667
2668 if (dtx_prev == AHS_SID_UPDATE && *dtx == AMR_OTHER) {
2669 /* NOTE: The AHS_SID_UPDATE frame is splitted into
2670 * two half rate frames. If the id marker frame
2671 * (AHS_SID_UPDATE) is detected the following frame
2672 * contains the actual comfort noised data part of
2673 * (AHS_SID_UPDATE_CN). */
2674 *dtx = AHS_SID_UPDATE_CN;
2675
2676 osmo_conv_decode_ber(&gsm0503_tch_axs_sid_update,
2677 cB + 16, conv, n_errors,
2678 n_bits_total);
2679 rv = osmo_crc16gen_check_bits(&gsm0503_amr_crc14, conv,
2680 35, conv + 35);
2681 if (rv != 0) {
2682 /* Error checking CRC14 for an AMR SID_UPDATE frame */
2683 return -1;
2684 }
2685
2686 tch_amr_sid_update_append(conv, 1,
2687 (codec_mode_req) ? codec[*ft]
2688 : codec[id]);
2689 tch_amr_reassemble(tch_data, conv, 39);
2690 len = 5;
2691 goto out;
2692 } else if (*dtx == AHS_SID_FIRST_P2) {
2693 tch_amr_sid_update_append(sid_first_dummy, 0,
2694 (codec_mode_req) ? codec[*ft]
2695 : codec[id]);
2696 tch_amr_reassemble(tch_data, sid_first_dummy, 39);
2697 len = 5;
2698 goto out;
2699 } else if (*dtx == AHS_SID_UPDATE || *dtx == AHS_ONSET
2700 || *dtx == AHS_SID_FIRST_INH
2701 || *dtx == AHS_SID_UPDATE_INH
2702 || *dtx == AHS_SID_FIRST_P1) {
2703 len = 0;
2704 goto out;
2705 }
2706 }
2707
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002708 for (i = 0; i < 4; i++) {
2709 for (j = 0, k = 0; j < 4; j++)
2710 k += abs(((int)gsm0503_ahs_ic_sbit[i][j]) - ((int)cB[j]));
2711
2712 if (i == 0 || k < best) {
2713 best = k;
2714 id = i;
2715 }
2716 }
2717
2718 /* Check if indicated codec fits into range of codecs */
2719 if (id >= codecs) {
2720 /* Codec mode out of range, return id */
2721 return id;
2722 }
2723
2724 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2725 case 5: /* TCH/AHS7.95 */
2726 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_95, cB + 4,
2727 conv, n_errors, n_bits_total);
2728
2729 tch_amr_unmerge(d, p, conv, 123, 67);
2730
2731 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 67, p);
2732 if (rv) {
2733 /* Error checking CRC8 for an AMR 7.95 frame */
2734 return -1;
2735 }
2736
2737 for (i = 0; i < 36; i++)
2738 d[i + 123] = (cB[i + 192] < 0) ? 1 : 0;
2739
2740 tch_amr_reassemble(tch_data, d, 159);
2741
2742 len = 20;
2743
2744 break;
2745 case 4: /* TCH/AHS7.4 */
2746 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_4, cB + 4,
2747 conv, n_errors, n_bits_total);
2748
2749 tch_amr_unmerge(d, p, conv, 120, 61);
2750
2751 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2752 if (rv) {
2753 /* Error checking CRC8 for an AMR 7.4 frame */
2754 return -1;
2755 }
2756
2757 for (i = 0; i < 28; i++)
2758 d[i + 120] = (cB[i + 200] < 0) ? 1 : 0;
2759
2760 tch_amr_reassemble(tch_data, d, 148);
2761
2762 len = 19;
2763
2764 break;
2765 case 3: /* TCH/AHS6.7 */
2766 osmo_conv_decode_ber(&gsm0503_tch_ahs_6_7, cB + 4,
2767 conv, n_errors, n_bits_total);
2768
2769 tch_amr_unmerge(d, p, conv, 110, 55);
2770
2771 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2772 if (rv) {
2773 /* Error checking CRC8 for an AMR 6.7 frame */
2774 return -1;
2775 }
2776
2777 for (i = 0; i < 24; i++)
2778 d[i + 110] = (cB[i + 204] < 0) ? 1 : 0;
2779
2780 tch_amr_reassemble(tch_data, d, 134);
2781
2782 len = 17;
2783
2784 break;
2785 case 2: /* TCH/AHS5.9 */
2786 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_9, cB + 4,
2787 conv, n_errors, n_bits_total);
2788
2789 tch_amr_unmerge(d, p, conv, 102, 55);
2790
2791 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2792 if (rv) {
2793 /* Error checking CRC8 for an AMR 5.9 frame */
2794 return -1;
2795 }
2796
2797 for (i = 0; i < 16; i++)
2798 d[i + 102] = (cB[i + 212] < 0) ? 1 : 0;
2799
2800 tch_amr_reassemble(tch_data, d, 118);
2801
2802 len = 15;
2803
2804 break;
2805 case 1: /* TCH/AHS5.15 */
2806 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_15, cB + 4,
2807 conv, n_errors, n_bits_total);
2808
2809 tch_amr_unmerge(d, p, conv, 91, 49);
2810
2811 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2812 if (rv) {
2813 /* Error checking CRC8 for an AMR 5.15 frame */
2814 return -1;
2815 }
2816
2817 for (i = 0; i < 12; i++)
2818 d[i + 91] = (cB[i + 216] < 0) ? 1 : 0;
2819
2820 tch_amr_reassemble(tch_data, d, 103);
2821
2822 len = 13;
2823
2824 break;
2825 case 0: /* TCH/AHS4.75 */
2826 osmo_conv_decode_ber(&gsm0503_tch_ahs_4_75, cB + 4,
2827 conv, n_errors, n_bits_total);
2828
2829 tch_amr_unmerge(d, p, conv, 83, 39);
2830
2831 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2832 if (rv) {
2833 /* Error checking CRC8 for an AMR 4.75 frame */
2834 return -1;
2835 }
2836
2837 for (i = 0; i < 12; i++)
2838 d[i + 83] = (cB[i + 216] < 0) ? 1 : 0;
2839
2840 tch_amr_reassemble(tch_data, d, 95);
2841
2842 len = 12;
2843
2844 break;
2845 default:
2846 /* Unknown frame type */
2847 *n_bits_total = 159;
2848 *n_errors = *n_bits_total;
2849 return -1;
2850 }
2851
Philipp Maier898c9c62020-02-06 14:25:01 +01002852out:
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002853 /* Change codec request / indication, if frame is valid */
2854 if (codec_mode_req)
2855 *cmr = id;
2856 else
2857 *ft = id;
2858
2859 return len;
2860}
2861
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002862/*! Perform channel encoding on a TCH/AHS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002863 * \param[out] bursts caller-allocated output buffer for bursts bits
2864 * \param[in] tch_data Codec input data in RTP payload format
2865 * \param[in] len Length of \a tch_data in bytes
2866 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2867 * \param[in] codec Array of codecs (active codec set)
2868 * \param[in] codecs Number of entries in \a codec
2869 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2870 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2871 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002872int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002873 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2874 uint8_t cmr)
2875{
2876 ubit_t iB[912], cB[456], h;
2877 ubit_t d[244], p[6], conv[135];
2878 int i;
2879 uint8_t id;
2880
2881 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2882 _xcch_encode_cB(cB, tch_data);
2883
2884 h = 1;
2885
2886 gsm0503_tch_fr_interleave(cB, iB);
2887
2888 for (i = 0; i < 6; i++)
2889 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116],
2890 &h, i >> 2);
2891 for (i = 2; i < 4; i++)
2892 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2893 &bursts[i * 116], &h, 1);
2894
2895 return 0;
2896 }
2897
2898 h = 0;
2899
2900 if (codec_mode_req) {
2901 if (cmr >= codecs) {
2902 /* FIXME: CMR ID %d not in codec list */
2903 return -1;
2904 }
2905 id = cmr;
2906 } else {
2907 if (ft >= codecs) {
2908 /* FIXME: FT ID %d not in codec list */
2909 return -1;
2910 }
2911 id = ft;
2912 }
2913
2914 switch (codec[ft]) {
2915 case 5: /* TCH/AHS7.95 */
2916 if (len != 20)
2917 goto invalid_length;
2918
2919 tch_amr_disassemble(d, tch_data, 159);
2920
2921 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 67, p);
2922
2923 tch_amr_merge(conv, d, p, 123, 67);
2924
2925 osmo_conv_encode(&gsm0503_tch_ahs_7_95, conv, cB + 4);
2926
2927 memcpy(cB + 192, d + 123, 36);
2928
2929 break;
2930 case 4: /* TCH/AHS7.4 */
2931 if (len != 19)
2932 goto invalid_length;
2933
2934 tch_amr_disassemble(d, tch_data, 148);
2935
2936 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2937
2938 tch_amr_merge(conv, d, p, 120, 61);
2939
2940 osmo_conv_encode(&gsm0503_tch_ahs_7_4, conv, cB + 4);
2941
2942 memcpy(cB + 200, d + 120, 28);
2943
2944 break;
2945 case 3: /* TCH/AHS6.7 */
2946 if (len != 17)
2947 goto invalid_length;
2948
2949 tch_amr_disassemble(d, tch_data, 134);
2950
2951 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2952
2953 tch_amr_merge(conv, d, p, 110, 55);
2954
2955 osmo_conv_encode(&gsm0503_tch_ahs_6_7, conv, cB + 4);
2956
2957 memcpy(cB + 204, d + 110, 24);
2958
2959 break;
2960 case 2: /* TCH/AHS5.9 */
2961 if (len != 15)
2962 goto invalid_length;
2963
2964 tch_amr_disassemble(d, tch_data, 118);
2965
2966 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2967
2968 tch_amr_merge(conv, d, p, 102, 55);
2969
2970 osmo_conv_encode(&gsm0503_tch_ahs_5_9, conv, cB + 4);
2971
2972 memcpy(cB + 212, d + 102, 16);
2973
2974 break;
2975 case 1: /* TCH/AHS5.15 */
2976 if (len != 13)
2977 goto invalid_length;
2978
2979 tch_amr_disassemble(d, tch_data, 103);
2980
2981 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2982
2983 tch_amr_merge(conv, d, p, 91, 49);
2984
2985 osmo_conv_encode(&gsm0503_tch_ahs_5_15, conv, cB + 4);
2986
2987 memcpy(cB + 216, d + 91, 12);
2988
2989 break;
2990 case 0: /* TCH/AHS4.75 */
2991 if (len != 12)
2992 goto invalid_length;
2993
2994 tch_amr_disassemble(d, tch_data, 95);
2995
2996 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2997
2998 tch_amr_merge(conv, d, p, 83, 39);
2999
3000 osmo_conv_encode(&gsm0503_tch_ahs_4_75, conv, cB + 4);
3001
3002 memcpy(cB + 216, d + 83, 12);
3003
3004 break;
3005 default:
3006 /* FIXME: FT %ft is not supported */
3007 return -1;
3008 }
3009
Philipp Maier3a063022021-08-31 16:02:31 +02003010 memcpy(cB, gsm0503_ahs_ic_ubit[id], 4);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003011
3012 gsm0503_tch_hr_interleave(cB, iB);
3013
3014 for (i = 0; i < 4; i++)
3015 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116], &h, i >> 1);
3016
3017 return 0;
3018
3019invalid_length:
3020 /* FIXME: payload length %len does not comply with codec type %ft */
3021 return -1;
3022}
3023
3024/*
3025 * GSM RACH transcoding
3026 */
3027
3028/*
3029 * GSM RACH apply BSIC to parity
3030 *
3031 * p(j) = p(j) xor b(j) j = 0, ..., 5
3032 * b(0) = MSB of PLMN colour code
3033 * b(5) = LSB of BS colour code
3034 */
Max32e56412017-10-16 14:58:00 +02003035static inline void rach_apply_bsic(ubit_t *d, uint8_t bsic, uint8_t start)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003036{
3037 int i;
3038
3039 /* Apply it */
3040 for (i = 0; i < 6; i++)
Max32e56412017-10-16 14:58:00 +02003041 d[start + i] ^= ((bsic >> (5 - i)) & 1);
3042}
3043
Harald Welte6950b192018-02-26 11:48:00 +01003044static inline int16_t rach_decode_ber(const sbit_t *burst, uint8_t bsic, bool is_11bit,
3045 int *n_errors, int *n_bits_total)
Max32e56412017-10-16 14:58:00 +02003046{
3047 ubit_t conv[17];
3048 uint8_t ra[2] = { 0 }, nbits = is_11bit ? 11 : 8;
3049 int rv;
3050
Harald Welte6950b192018-02-26 11:48:00 +01003051 osmo_conv_decode_ber(is_11bit ? &gsm0503_rach_ext : &gsm0503_rach, burst, conv,
3052 n_errors, n_bits_total);
Max32e56412017-10-16 14:58:00 +02003053
3054 rach_apply_bsic(conv, bsic, nbits);
3055
3056 rv = osmo_crc8gen_check_bits(&gsm0503_rach_crc6, conv, nbits, conv + nbits);
3057 if (rv)
3058 return -1;
3059
3060 osmo_ubit2pbit_ext(ra, 0, conv, 0, nbits, 1);
3061
Vadim Yanitskiy9e713f32020-03-31 19:40:09 +07003062 return is_11bit ? ((ra[0] << 3) | (ra[1] & 0x07)) : ra[0];
Max32e56412017-10-16 14:58:00 +02003063}
3064
3065/*! Decode the Extended (11-bit) RACH according to 3GPP TS 45.003
3066 * \param[out] ra output buffer for RACH data
3067 * \param[in] burst Input burst data
3068 * \param[in] bsic BSIC used in this cell
3069 * \returns 0 on success; negative on error (e.g. CRC error) */
3070int gsm0503_rach_ext_decode(uint16_t *ra, const sbit_t *burst, uint8_t bsic)
3071{
Harald Welte6950b192018-02-26 11:48:00 +01003072 int16_t r = rach_decode_ber(burst, bsic, true, NULL, NULL);
Max32e56412017-10-16 14:58:00 +02003073
3074 if (r < 0)
3075 return r;
3076
3077 *ra = r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003078
3079 return 0;
3080}
3081
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003082/*! Decode the (8-bit) RACH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003083 * \param[out] ra output buffer for RACH data
3084 * \param[in] burst Input burst data
3085 * \param[in] bsic BSIC used in this cell
3086 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02003087int gsm0503_rach_decode(uint8_t *ra, const sbit_t *burst, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003088{
Harald Welte6950b192018-02-26 11:48:00 +01003089 int16_t r = rach_decode_ber(burst, bsic, false, NULL, NULL);
3090 if (r < 0)
3091 return r;
3092
3093 *ra = r;
3094 return 0;
3095}
3096
3097/*! Decode the Extended (11-bit) RACH according to 3GPP TS 45.003
3098 * \param[out] ra output buffer for RACH data
3099 * \param[in] burst Input burst data
3100 * \param[in] bsic BSIC used in this cell
3101 * \param[out] n_errors Number of detected bit errors
3102 * \param[out] n_bits_total Total number of bits
3103 * \returns 0 on success; negative on error (e.g. CRC error) */
3104int gsm0503_rach_ext_decode_ber(uint16_t *ra, const sbit_t *burst, uint8_t bsic,
3105 int *n_errors, int *n_bits_total)
3106{
3107 int16_t r = rach_decode_ber(burst, bsic, true, n_errors, n_bits_total);
3108 if (r < 0)
3109 return r;
3110
3111 *ra = r;
3112 return 0;
3113}
3114
3115/*! Decode the (8-bit) RACH according to TS 05.03
3116 * \param[out] ra output buffer for RACH data
3117 * \param[in] burst Input burst data
3118 * \param[in] bsic BSIC used in this cell
3119 * \param[out] n_errors Number of detected bit errors
3120 * \param[out] n_bits_total Total number of bits
3121 * \returns 0 on success; negative on error (e.g. CRC error) */
3122int gsm0503_rach_decode_ber(uint8_t *ra, const sbit_t *burst, uint8_t bsic,
3123 int *n_errors, int *n_bits_total)
3124{
3125 int16_t r = rach_decode_ber(burst, bsic, false, n_errors, n_bits_total);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003126
Max32e56412017-10-16 14:58:00 +02003127 if (r < 0)
3128 return r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003129
Max32e56412017-10-16 14:58:00 +02003130 *ra = r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003131
3132 return 0;
3133}
3134
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003135/*! Encode the (8-bit) RACH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003136 * \param[out] burst Caller-allocated output burst buffer
3137 * \param[in] ra Input RACH data
3138 * \param[in] bsic BSIC used in this cell
3139 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02003140int gsm0503_rach_encode(ubit_t *burst, const uint8_t *ra, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003141{
Max32e56412017-10-16 14:58:00 +02003142 return gsm0503_rach_ext_encode(burst, *ra, bsic, false);
3143}
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003144
Max32e56412017-10-16 14:58:00 +02003145/*! Encode the Extended (11-bit) or regular (8-bit) RACH according to 3GPP TS 45.003
3146 * \param[out] burst Caller-allocated output burst buffer
3147 * \param[in] ra11 Input RACH data
3148 * \param[in] bsic BSIC used in this cell
3149 * \param[in] is_11bit whether given RA is 11 bit or not
3150 * \returns 0 on success; negative on error */
3151int gsm0503_rach_ext_encode(ubit_t *burst, uint16_t ra11, uint8_t bsic, bool is_11bit)
3152{
3153 ubit_t conv[17];
3154 uint8_t ra[2] = { 0 }, nbits = 8;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003155
Max32e56412017-10-16 14:58:00 +02003156 if (is_11bit) {
Vadim Yanitskiy9e713f32020-03-31 19:40:09 +07003157 ra[0] = (uint8_t) (ra11 >> 3);
3158 ra[1] = (uint8_t) (ra11 & 0x07);
Max32e56412017-10-16 14:58:00 +02003159 nbits = 11;
3160 } else
3161 ra[0] = (uint8_t)ra11;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003162
Max32e56412017-10-16 14:58:00 +02003163 osmo_pbit2ubit_ext(conv, 0, ra, 0, nbits, 1);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003164
Max32e56412017-10-16 14:58:00 +02003165 osmo_crc8gen_set_bits(&gsm0503_rach_crc6, conv, nbits, conv + nbits);
3166
3167 rach_apply_bsic(conv, bsic, nbits);
3168
3169 osmo_conv_encode(is_11bit ? &gsm0503_rach_ext : &gsm0503_rach, conv, burst);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003170
3171 return 0;
3172}
3173
3174/*
3175 * GSM SCH transcoding
3176 */
Harald Weltec6636782017-06-12 14:59:37 +02003177
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003178/*! Decode the SCH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003179 * \param[out] sb_info output buffer for SCH data
3180 * \param[in] burst Input burst data
3181 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02003182int gsm0503_sch_decode(uint8_t *sb_info, const sbit_t *burst)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003183{
3184 ubit_t conv[35];
3185 int rv;
3186
3187 osmo_conv_decode(&gsm0503_sch, burst, conv);
3188
3189 rv = osmo_crc16gen_check_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
3190 if (rv)
3191 return -1;
3192
3193 osmo_ubit2pbit_ext(sb_info, 0, conv, 0, 25, 1);
3194
3195 return 0;
3196}
3197
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003198/*! Encode the SCH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003199 * \param[out] burst Caller-allocated output burst buffer
3200 * \param[in] sb_info Input SCH data
3201 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02003202int gsm0503_sch_encode(ubit_t *burst, const uint8_t *sb_info)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003203{
3204 ubit_t conv[35];
3205
3206 osmo_pbit2ubit_ext(conv, 0, sb_info, 0, 25, 1);
3207
3208 osmo_crc16gen_set_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
3209
3210 osmo_conv_encode(&gsm0503_sch, conv, burst);
3211
3212 return 0;
3213}
Harald Weltec6636782017-06-12 14:59:37 +02003214
3215/*! @} */