blob: 835a18e20b137df19837f4dd9319167d1190eacc [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.
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070020 */
21
22#include <stdio.h>
23#include <stdint.h>
24#include <string.h>
25#include <stdlib.h>
Maxc8cf8202017-05-22 16:07:04 +020026#include <errno.h>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070027
28#include <osmocom/core/bits.h>
29#include <osmocom/core/conv.h>
30#include <osmocom/core/utils.h>
31#include <osmocom/core/crcgen.h>
32#include <osmocom/core/endian.h>
33
34#include <osmocom/gprs/protocol/gsm_04_60.h>
35#include <osmocom/gprs/gprs_rlc.h>
36
37#include <osmocom/gsm/protocol/gsm_04_08.h>
38#include <osmocom/gsm/gsm0503.h>
39#include <osmocom/codec/codec.h>
40
41#include <osmocom/coding/gsm0503_interleaving.h>
42#include <osmocom/coding/gsm0503_mapping.h>
43#include <osmocom/coding/gsm0503_tables.h>
44#include <osmocom/coding/gsm0503_coding.h>
45#include <osmocom/coding/gsm0503_parity.h>
Philipp Maier898c9c62020-02-06 14:25:01 +010046#include <osmocom/coding/gsm0503_amr_dtx.h>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070047
Harald Weltec6636782017-06-12 14:59:37 +020048/*! \mainpage libosmocoding Documentation
49 *
50 * \section sec_intro Introduction
51 * This library is a collection of definitions, tables and functions
52 * implementing the GSM/GPRS/EGPRS channel coding (and decoding) as
53 * specified in 3GPP TS 05.03 / 45.003.
54 *
Vadim Yanitskiy9a232fd2018-01-19 03:05:32 +060055 * libosmocoding is developed as part of the Osmocom (Open Source Mobile
Harald Weltec6636782017-06-12 14:59:37 +020056 * Communications) project, a community-based, collaborative development
57 * project to create Free and Open Source implementations of mobile
58 * communications systems. For more information about Osmocom, please
59 * see https://osmocom.org/
60 *
61 * \section sec_copyright Copyright and License
62 * Copyright © 2013 by Andreas Eversberg\n
63 * Copyright © 2015 by Alexander Chemeris\n
64 * Copyright © 2016 by Tom Tsou\n
65 * Documentation Copyright © 2017 by Harald Welte\n
66 * All rights reserved. \n\n
67 * The source code of libosmocoding is licensed under the terms of the GNU
68 * General Public License as published by the Free Software Foundation;
69 * either version 2 of the License, or (at your option) any later
70 * version.\n
71 * See <http://www.gnu.org/licenses/> or COPYING included in the source
72 * code package istelf.\n
73 * The information detailed here is provided AS IS with NO WARRANTY OF
74 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
75 * FITNESS FOR A PARTICULAR PURPOSE.
76 * \n\n
77 *
78 * \section sec_tracker Homepage + Issue Tracker
79 * libosmocoding is distributed as part of libosmocore and shares its
80 * project page at http://osmocom.org/projects/libosmocore
81 *
82 * An Issue Tracker can be found at
83 * https://osmocom.org/projects/libosmocore/issues
84 *
85 * \section sec_contact Contact and Support
86 * Community-based support is available at the OpenBSC mailing list
87 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
88 * Commercial support options available upon request from
89 * <http://sysmocom.de/>
90 */
91
92
93/*! \addtogroup coding
94 * @{
95 *
Neels Hofmeyr87e45502017-06-20 00:17:59 +020096 * GSM TS 05.03 coding
Harald Weltec6636782017-06-12 14:59:37 +020097 *
98 * This module is the "master module" of libosmocoding. It uses the
99 * various other modules (mapping, parity, interleaving) in order to
100 * implement the complete channel coding (and decoding) chain for the
101 * various channel types as defined in TS 05.03 / 45.003.
Neels Hofmeyr17518fe2017-06-20 04:35:06 +0200102 *
103 * \file gsm0503_coding.c */
Harald Weltec6636782017-06-12 14:59:37 +0200104
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700105/*
106 * EGPRS coding limits
107 */
108
109/* Max header size with parity bits */
110#define EGPRS_HDR_UPP_MAX 54
111
112/* Max encoded header size */
113#define EGPRS_HDR_C_MAX 162
114
115/* Max punctured header size */
116#define EGPRS_HDR_HC_MAX 160
117
118/* Max data block size with parity bits */
119#define EGPRS_DATA_U_MAX 612
120
121/* Max encoded data block size */
122#define EGPRS_DATA_C_MAX 1836
123
124/* Max single block punctured data size */
125#define EGPRS_DATA_DC_MAX 1248
126
127/* Dual block punctured data size */
128#define EGPRS_DATA_C1 612
129#define EGPRS_DATA_C2 EGPRS_DATA_C1
130
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200131/*! union across the three different EGPRS Uplink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700132union gprs_rlc_ul_hdr_egprs {
133 struct gprs_rlc_ul_header_egprs_1 type1;
134 struct gprs_rlc_ul_header_egprs_2 type2;
135 struct gprs_rlc_ul_header_egprs_3 type3;
136};
137
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200138/*! union across the three different EGPRS Downlink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700139union gprs_rlc_dl_hdr_egprs {
140 struct gprs_rlc_dl_header_egprs_1 type1;
141 struct gprs_rlc_dl_header_egprs_2 type2;
142 struct gprs_rlc_dl_header_egprs_3 type3;
143};
144
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200145/*! Structure describing a Modulation and Coding Scheme */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700146struct gsm0503_mcs_code {
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200147 /*! Modulation and Coding Scheme (MSC) number */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700148 uint8_t mcs;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200149 /*! Length of Uplink Stealing Flag (USF) in bits */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700150 uint8_t usf_len;
151
152 /* Header coding */
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200153 /*! Length of header (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700154 uint8_t hdr_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200155 /*! Length of header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700156 uint8_t hdr_code_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200157 /*! Length of header code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700158 uint8_t hdr_punc_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200159 /*! header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700160 const struct osmo_conv_code *hdr_conv;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200161 /*! header puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700162 const uint8_t *hdr_punc;
163
164 /* Data coding */
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200165 /*! length of data (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700166 uint16_t data_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200167 /*! length of data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700168 uint16_t data_code_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200169 /*! length of data code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700170 uint16_t data_punc_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200171 /*! data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700172 const struct osmo_conv_code *data_conv;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200173 /*! data puncturing sequences */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700174 const uint8_t *data_punc[3];
175};
176
177/*
178 * EGPRS UL coding parameters
179 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200180const struct gsm0503_mcs_code gsm0503_mcs_ul_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700181 {
182 .mcs = EGPRS_MCS0,
183 },
184 {
185 .mcs = EGPRS_MCS1,
186 .hdr_len = 31,
187 .hdr_code_len = 117,
188 .hdr_punc_len = 80,
189 .hdr_conv = &gsm0503_mcs1_ul_hdr,
190 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
191
192 .data_len = 178,
193 .data_code_len = 588,
194 .data_punc_len = 372,
195 .data_conv = &gsm0503_mcs1,
196 .data_punc = {
197 gsm0503_puncture_mcs1_p1,
198 gsm0503_puncture_mcs1_p2,
199 NULL,
200 },
201 },
202 {
203 .mcs = EGPRS_MCS2,
204 .hdr_len = 31,
205 .hdr_code_len = 117,
206 .hdr_punc_len = 80,
207 .hdr_conv = &gsm0503_mcs1_ul_hdr,
208 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
209
210 .data_len = 226,
211 .data_code_len = 732,
212 .data_punc_len = 372,
213 .data_conv = &gsm0503_mcs2,
214 .data_punc = {
215 gsm0503_puncture_mcs2_p1,
216 gsm0503_puncture_mcs2_p2,
217 NULL,
218 },
219 },
220 {
221 .mcs = EGPRS_MCS3,
222 .hdr_len = 31,
223 .hdr_code_len = 117,
224 .hdr_punc_len = 80,
225 .hdr_conv = &gsm0503_mcs1_ul_hdr,
226 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
227
228 .data_len = 298,
229 .data_code_len = 948,
230 .data_punc_len = 372,
231 .data_conv = &gsm0503_mcs3,
232 .data_punc = {
233 gsm0503_puncture_mcs3_p1,
234 gsm0503_puncture_mcs3_p2,
235 gsm0503_puncture_mcs3_p3,
236 },
237 },
238 {
239 .mcs = EGPRS_MCS4,
240 .hdr_len = 31,
241 .hdr_code_len = 117,
242 .hdr_punc_len = 80,
243 .hdr_conv = &gsm0503_mcs1_ul_hdr,
244 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
245
246 .data_len = 354,
247 .data_code_len = 1116,
248 .data_punc_len = 372,
249 .data_conv = &gsm0503_mcs4,
250 .data_punc = {
251 gsm0503_puncture_mcs4_p1,
252 gsm0503_puncture_mcs4_p2,
253 gsm0503_puncture_mcs4_p3,
254 },
255 },
256 {
257 .mcs = EGPRS_MCS5,
258 .hdr_len = 37,
259 .hdr_code_len = 135,
260 .hdr_punc_len = 136,
261 .hdr_conv = &gsm0503_mcs5_ul_hdr,
262 .hdr_punc = NULL,
263
264 .data_len = 450,
265 .data_code_len = 1404,
266 .data_punc_len = 1248,
267 .data_conv = &gsm0503_mcs5,
268 .data_punc = {
269 gsm0503_puncture_mcs5_p1,
270 gsm0503_puncture_mcs5_p2,
271 NULL,
272 },
273 },
274 {
275 .mcs = EGPRS_MCS6,
276 .hdr_len = 37,
277 .hdr_code_len = 135,
278 .hdr_punc_len = 136,
279 .hdr_conv = &gsm0503_mcs5_ul_hdr,
280 .hdr_punc = NULL,
281
282 .data_len = 594,
283 .data_code_len = 1836,
284 .data_punc_len = 1248,
285 .data_conv = &gsm0503_mcs6,
286 .data_punc = {
287 gsm0503_puncture_mcs6_p1,
288 gsm0503_puncture_mcs6_p2,
289 NULL,
290 },
291 },
292 {
293 .mcs = EGPRS_MCS7,
294 .hdr_len = 46,
295 .hdr_code_len = 162,
296 .hdr_punc_len = 160,
297 .hdr_conv = &gsm0503_mcs7_ul_hdr,
298 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
299
300 .data_len = 900,
301 .data_code_len = 1404,
302 .data_punc_len = 612,
303 .data_conv = &gsm0503_mcs7,
304 .data_punc = {
305 gsm0503_puncture_mcs7_p1,
306 gsm0503_puncture_mcs7_p2,
307 gsm0503_puncture_mcs7_p3,
308 }
309 },
310 {
311 .mcs = EGPRS_MCS8,
312 .hdr_len = 46,
313 .hdr_code_len = 162,
314 .hdr_punc_len = 160,
315 .hdr_conv = &gsm0503_mcs7_ul_hdr,
316 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
317
318 .data_len = 1092,
319 .data_code_len = 1692,
320 .data_punc_len = 612,
321 .data_conv = &gsm0503_mcs8,
322 .data_punc = {
323 gsm0503_puncture_mcs8_p1,
324 gsm0503_puncture_mcs8_p2,
325 gsm0503_puncture_mcs8_p3,
326 }
327 },
328 {
329 .mcs = EGPRS_MCS9,
330 .hdr_len = 46,
331 .hdr_code_len = 162,
332 .hdr_punc_len = 160,
333 .hdr_conv = &gsm0503_mcs7_ul_hdr,
334 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
335
336 .data_len = 1188,
337 .data_code_len = 1836,
338 .data_punc_len = 612,
339 .data_conv = &gsm0503_mcs9,
340 .data_punc = {
341 gsm0503_puncture_mcs9_p1,
342 gsm0503_puncture_mcs9_p2,
343 gsm0503_puncture_mcs9_p3,
344 }
345 },
346};
347
348/*
349 * EGPRS DL coding parameters
350 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200351const struct gsm0503_mcs_code gsm0503_mcs_dl_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700352 {
353 .mcs = EGPRS_MCS0,
354 },
355 {
356 .mcs = EGPRS_MCS1,
357 .usf_len = 3,
358 .hdr_len = 28,
359 .hdr_code_len = 108,
360 .hdr_punc_len = 68,
361 .hdr_conv = &gsm0503_mcs1_dl_hdr,
362 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
363
364 .data_len = 178,
365 .data_code_len = 588,
366 .data_punc_len = 372,
367 .data_conv = &gsm0503_mcs1,
368 .data_punc = {
369 gsm0503_puncture_mcs1_p1,
370 gsm0503_puncture_mcs1_p2,
371 NULL,
372 },
373 },
374 {
375 .mcs = EGPRS_MCS2,
376 .usf_len = 3,
377 .hdr_len = 28,
378 .hdr_code_len = 108,
379 .hdr_punc_len = 68,
380 .hdr_conv = &gsm0503_mcs1_dl_hdr,
381 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
382
383 .data_len = 226,
384 .data_code_len = 732,
385 .data_punc_len = 372,
386 .data_conv = &gsm0503_mcs2,
387 .data_punc = {
388 gsm0503_puncture_mcs2_p1,
389 gsm0503_puncture_mcs2_p2,
390 NULL,
391 },
392 },
393 {
394 .mcs = EGPRS_MCS3,
395 .usf_len = 3,
396 .hdr_len = 28,
397 .hdr_code_len = 108,
398 .hdr_punc_len = 68,
399 .hdr_conv = &gsm0503_mcs1_dl_hdr,
400 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
401
402 .data_len = 298,
403 .data_code_len = 948,
404 .data_punc_len = 372,
405 .data_conv = &gsm0503_mcs3,
406 .data_punc = {
407 gsm0503_puncture_mcs3_p1,
408 gsm0503_puncture_mcs3_p2,
409 gsm0503_puncture_mcs3_p3,
410 },
411 },
412 {
413 .mcs = EGPRS_MCS4,
414 .usf_len = 3,
415 .hdr_len = 28,
416 .hdr_code_len = 108,
417 .hdr_punc_len = 68,
418 .hdr_conv = &gsm0503_mcs1_dl_hdr,
419 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
420
421 .data_len = 354,
422 .data_code_len = 1116,
423 .data_punc_len = 372,
424 .data_conv = &gsm0503_mcs4,
425 .data_punc = {
426 gsm0503_puncture_mcs4_p1,
427 gsm0503_puncture_mcs4_p2,
428 gsm0503_puncture_mcs4_p3,
429 },
430 },
431 {
432 .mcs = EGPRS_MCS5,
433 .usf_len = 3,
434 .hdr_len = 25,
435 .hdr_code_len = 99,
436 .hdr_punc_len = 100,
437 .hdr_conv = &gsm0503_mcs5_dl_hdr,
438 .hdr_punc = NULL,
439
440 .data_len = 450,
441 .data_code_len = 1404,
442 .data_punc_len = 1248,
443 .data_conv = &gsm0503_mcs5,
444 .data_punc = {
445 gsm0503_puncture_mcs5_p1,
446 gsm0503_puncture_mcs5_p2,
447 NULL,
448 },
449 },
450 {
451 .mcs = EGPRS_MCS6,
452 .usf_len = 3,
453 .hdr_len = 25,
454 .hdr_code_len = 99,
455 .hdr_punc_len = 100,
456 .hdr_conv = &gsm0503_mcs5_dl_hdr,
457 .hdr_punc = NULL,
458
459 .data_len = 594,
460 .data_code_len = 1836,
461 .data_punc_len = 1248,
462 .data_conv = &gsm0503_mcs6,
463 .data_punc = {
464 gsm0503_puncture_mcs6_p1,
465 gsm0503_puncture_mcs6_p2,
466 NULL,
467 },
468 },
469 {
470 .mcs = EGPRS_MCS7,
471 .usf_len = 3,
472 .hdr_len = 37,
473 .hdr_code_len = 135,
474 .hdr_punc_len = 124,
475 .hdr_conv = &gsm0503_mcs7_dl_hdr,
476 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
477
478 .data_len = 900,
479 .data_code_len = 1404,
480 .data_punc_len = 612,
481 .data_conv = &gsm0503_mcs7,
482 .data_punc = {
483 gsm0503_puncture_mcs7_p1,
484 gsm0503_puncture_mcs7_p2,
485 gsm0503_puncture_mcs7_p3,
486 }
487 },
488 {
489 .mcs = EGPRS_MCS8,
490 .usf_len = 3,
491 .hdr_len = 37,
492 .hdr_code_len = 135,
493 .hdr_punc_len = 124,
494 .hdr_conv = &gsm0503_mcs7_dl_hdr,
495 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
496
497 .data_len = 1092,
498 .data_code_len = 1692,
499 .data_punc_len = 612,
500 .data_conv = &gsm0503_mcs8,
501 .data_punc = {
502 gsm0503_puncture_mcs8_p1,
503 gsm0503_puncture_mcs8_p2,
504 gsm0503_puncture_mcs8_p3,
505 }
506 },
507 {
508 .mcs = EGPRS_MCS9,
509 .usf_len = 3,
510 .hdr_len = 37,
511 .hdr_code_len = 135,
512 .hdr_punc_len = 124,
513 .hdr_conv = &gsm0503_mcs7_dl_hdr,
514 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
515
516 .data_len = 1188,
517 .data_code_len = 1836,
518 .data_punc_len = 612,
519 .data_conv = &gsm0503_mcs9,
520 .data_punc = {
521 gsm0503_puncture_mcs9_p1,
522 gsm0503_puncture_mcs9_p2,
523 gsm0503_puncture_mcs9_p3,
524 }
525 },
526};
527
Alexander Chemeris147051f2018-07-14 21:02:29 +0200528/*! Convolutional Decode + compute BER for punctured codes
Harald Weltec6636782017-06-12 14:59:37 +0200529 * \param[in] code Description of Convolutional Code
530 * \param[in] input Input soft-bits (-127...127)
531 * \param[out] output bits
532 * \param[out] n_errors Number of bit-errors
533 * \param[out] n_bits_total Number of bits
Alexander Chemeris147051f2018-07-14 21:02:29 +0200534 * \param[in] data_punc Puncturing mask array. Can be NULL.
Harald Weltec6636782017-06-12 14:59:37 +0200535 */
Alexander Chemeris147051f2018-07-14 21:02:29 +0200536static int osmo_conv_decode_ber_punctured(const struct osmo_conv_code *code,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700537 const sbit_t *input, ubit_t *output,
Alexander Chemeris147051f2018-07-14 21:02:29 +0200538 int *n_errors, int *n_bits_total,
539 const uint8_t *data_punc)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700540{
541 int res, i, coded_len;
542 ubit_t recoded[EGPRS_DATA_C_MAX];
543
544 res = osmo_conv_decode(code, input, output);
545
546 if (n_bits_total || n_errors) {
547 coded_len = osmo_conv_encode(code, output, recoded);
548 OSMO_ASSERT(sizeof(recoded) / sizeof(recoded[0]) >= coded_len);
549 }
550
551 /* Count bit errors */
552 if (n_errors) {
553 *n_errors = 0;
554 for (i = 0; i < coded_len; i++) {
Alexander Chemeris147051f2018-07-14 21:02:29 +0200555 if (((!data_punc) || (data_punc && !data_punc[i])) &&
556 !((recoded[i] && input[i] < 0) ||
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700557 (!recoded[i] && input[i] > 0)) )
558 *n_errors += 1;
559 }
560 }
561
562 if (n_bits_total)
563 *n_bits_total = coded_len;
564
565 return res;
566}
567
Alexander Chemeris147051f2018-07-14 21:02:29 +0200568/*! Convolutional Decode + compute BER for non-punctured codes
569 * \param[in] code Description of Convolutional Code
570 * \param[in] input Input soft-bits (-127...127)
571 * \param[out] output bits
572 * \param[out] n_errors Number of bit-errors
573 * \param[out] n_bits_total Number of bits
574 */
575static int osmo_conv_decode_ber(const struct osmo_conv_code *code,
576 const sbit_t *input, ubit_t *output,
577 int *n_errors, int *n_bits_total)
578{
579 return osmo_conv_decode_ber_punctured(code, input, output,
580 n_errors, n_bits_total, NULL);
581}
582
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200583/*! convenience wrapper for decoding coded bits
Harald Weltec6636782017-06-12 14:59:37 +0200584 * \param[out] l2_data caller-allocated buffer for L2 Frame
585 * \param[in] cB 456 coded (soft) bits as per TS 05.03 4.1.3
586 * \param[out] n_errors Number of detected errors
587 * \param[out] n_bits_total Number of total coded bits
588 * \returns 0 on success; -1 on CRC error */
Harald Welteb9946d32017-06-12 09:40:16 +0200589static int _xcch_decode_cB(uint8_t *l2_data, const sbit_t *cB,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700590 int *n_errors, int *n_bits_total)
591{
592 ubit_t conv[224];
593 int rv;
594
595 osmo_conv_decode_ber(&gsm0503_xcch, cB,
596 conv, n_errors, n_bits_total);
597
598 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
599 conv, 184, conv + 184);
600 if (rv)
601 return -1;
602
603 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
604
605 return 0;
606}
607
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200608/*! convenience wrapper for encoding to coded bits
Harald Weltec6636782017-06-12 14:59:37 +0200609 * \param[out] cB caller-allocated buffer for 456 coded bits as per TS 05.03 4.1.3
610 * \param[out] l2_data to-be-encoded L2 Frame
611 * \returns 0 */
Harald Welteb9946d32017-06-12 09:40:16 +0200612static int _xcch_encode_cB(ubit_t *cB, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700613{
614 ubit_t conv[224];
615
616 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
617
618 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
619
620 osmo_conv_encode(&gsm0503_xcch, conv, cB);
621
622 return 0;
623}
624
625/*
626 * GSM xCCH block transcoding
627 */
Harald Weltec6636782017-06-12 14:59:37 +0200628
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200629/*! Decoding of xCCH data from bursts to L2 frame
Harald Weltec6636782017-06-12 14:59:37 +0200630 * \param[out] l2_data caller-allocated output data buffer
631 * \param[in] bursts four GSM bursts in soft-bits
632 * \param[out] n_errors Number of detected errors
633 * \param[out] n_bits_total Number of total coded bits
634 */
Harald Welteb9946d32017-06-12 09:40:16 +0200635int gsm0503_xcch_decode(uint8_t *l2_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700636 int *n_errors, int *n_bits_total)
637{
638 sbit_t iB[456], cB[456];
639 int i;
640
641 for (i = 0; i < 4; i++)
642 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116], NULL, NULL);
643
644 gsm0503_xcch_deinterleave(cB, iB);
645
646 return _xcch_decode_cB(l2_data, cB, n_errors, n_bits_total);
647}
648
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200649/*! Encoding of xCCH data from L2 frame to bursts
Harald Weltec6636782017-06-12 14:59:37 +0200650 * \param[out] bursts caller-allocated burst data (unpacked bits)
651 * \param[in] l2_data L2 input data (MAC block)
652 * \returns 0
653 */
Harald Welteb9946d32017-06-12 09:40:16 +0200654int gsm0503_xcch_encode(ubit_t *bursts, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700655{
656 ubit_t iB[456], cB[456], hl = 1, hn = 1;
657 int i;
658
659 _xcch_encode_cB(cB, l2_data);
660
661 gsm0503_xcch_interleave(cB, iB);
662
663 for (i = 0; i < 4; i++)
664 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116], &hl, &hn);
665
666 return 0;
667}
668
669/*
670 * EGPRS PDTCH UL block decoding
671 */
672
673/*
674 * Type 3 - MCS-1,2,3,4
675 * Unmapping and deinterleaving
676 */
677static int egprs_type3_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
678{
679 int i;
680 sbit_t iB[456], q[8];
681
682 for (i = 0; i < 4; i++) {
683 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
684 q + i * 2, q + i * 2 + 1);
685 }
686
687 gsm0503_mcs1_ul_deinterleave(hc, dc, iB);
688
689 return 0;
690}
691
692/*
693 * Type 2 - MCS-5,6
694 * Unmapping and deinterleaving
695 */
696static int egprs_type2_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
697{
698 int i;
699 sbit_t burst[348];
700 sbit_t hi[EGPRS_HDR_HC_MAX];
701 sbit_t di[EGPRS_DATA_DC_MAX];
702
703 for (i = 0; i < 4; i++) {
704 memcpy(burst, &bursts[i * 348], 348);
705
706 gsm0503_mcs5_burst_swap(burst);
707 gsm0503_mcs5_ul_burst_unmap(di, burst, hi, i);
708 }
709
710 gsm0503_mcs5_ul_deinterleave(hc, dc, hi, di);
711
712 return 0;
713}
714
715/*
716 * Type 1 - MCS-7,8,9
717 * Unmapping and deinterleaving - Note that MCS-7 interleaver is unique
718 */
719static int egprs_type1_unmap(const sbit_t *bursts, sbit_t *hc,
720 sbit_t *c1, sbit_t *c2, int msc)
721{
722 int i;
723 sbit_t burst[348];
724 sbit_t hi[EGPRS_HDR_HC_MAX];
725 sbit_t di[EGPRS_DATA_C1 * 2];
726
727 for (i = 0; i < 4; i++) {
728 memcpy(burst, &bursts[i * 348], 348);
729
730 gsm0503_mcs5_burst_swap(burst);
731 gsm0503_mcs7_ul_burst_unmap(di, burst, hi, i);
732 }
733
734 if (msc == EGPRS_MCS7)
735 gsm0503_mcs7_ul_deinterleave(hc, c1, c2, hi, di);
736 else
737 gsm0503_mcs8_ul_deinterleave(hc, c1, c2, hi, di);
738
739 return 0;
740}
741
742/*
743 * Decode EGPRS UL header section
744 *
745 * 1. Depuncture
746 * 2. Convolutional decoding
747 * 3. CRC check
748 */
749static int _egprs_decode_hdr(const sbit_t *hc, int mcs,
750 union gprs_rlc_ul_hdr_egprs *hdr)
751{
752 sbit_t C[EGPRS_HDR_C_MAX];
753 ubit_t upp[EGPRS_HDR_UPP_MAX];
754 int i, j, rc;
Harald Welte2f984ea2017-06-12 15:05:21 +0200755 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700756
757 code = &gsm0503_mcs_ul_codes[mcs];
758
759 /* Skip depuncturing on MCS-5,6 header */
760 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
761 memcpy(C, hc, code->hdr_code_len);
762 goto hdr_conv_decode;
763 }
764
765 if (!code->hdr_punc) {
766 /* Invalid MCS-X header puncture matrix */
767 return -1;
768 }
769
770 i = code->hdr_code_len - 1;
771 j = code->hdr_punc_len - 1;
772
773 for (; i >= 0; i--) {
774 if (!code->hdr_punc[i])
775 C[i] = hc[j--];
776 else
777 C[i] = 0;
778 }
779
780hdr_conv_decode:
781 osmo_conv_decode_ber(code->hdr_conv, C, upp, NULL, NULL);
782 rc = osmo_crc8gen_check_bits(&gsm0503_mcs_crc8_hdr, upp,
783 code->hdr_len, upp + code->hdr_len);
784 if (rc)
785 return -1;
786
787 osmo_ubit2pbit_ext((pbit_t *) hdr, 0, upp, 0, code->hdr_len, 1);
788
789 return 0;
790}
791
792/*
793 * Blind MCS header decoding based on burst length and CRC validation.
794 * Ignore 'q' value coding identification. This approach provides
795 * the strongest chance of header recovery.
796 */
797static int egprs_decode_hdr(union gprs_rlc_ul_hdr_egprs *hdr,
798 const sbit_t *bursts, uint16_t nbits)
799{
800 int rc;
801 sbit_t hc[EGPRS_HDR_HC_MAX];
802
803 if (nbits == GSM0503_GPRS_BURSTS_NBITS) {
804 /* MCS-1,2,3,4 */
805 egprs_type3_unmap(bursts, hc, NULL);
806 rc = _egprs_decode_hdr(hc, EGPRS_MCS1, hdr);
807 if (!rc)
808 return EGPRS_HDR_TYPE3;
809 } else if (nbits == GSM0503_EGPRS_BURSTS_NBITS) {
810 /* MCS-5,6 */
811 egprs_type2_unmap(bursts, hc, NULL);
812 rc = _egprs_decode_hdr(hc, EGPRS_MCS5, hdr);
813 if (!rc)
814 return EGPRS_HDR_TYPE2;
815
816 /* MCS-7,8,9 */
817 egprs_type1_unmap(bursts, hc, NULL, NULL, EGPRS_MCS7);
818 rc = _egprs_decode_hdr(hc, EGPRS_MCS7, hdr);
819 if (!rc)
820 return EGPRS_HDR_TYPE1;
821 }
822
823 return -1;
824}
825
826/*
827 * Parse EGPRS UL header for coding and puncturing scheme (CPS)
828 *
829 * Type 1 - MCS-7,8,9
830 * Type 2 - MCS-5,6
831 * Type 3 - MCS-1,2,3,4
832 */
833static int egprs_parse_ul_cps(struct egprs_cps *cps,
834 union gprs_rlc_ul_hdr_egprs *hdr, int type)
835{
836 uint8_t bits;
837
838 switch (type) {
839 case EGPRS_HDR_TYPE1:
840 bits = hdr->type1.cps;
841 break;
842 case EGPRS_HDR_TYPE2:
843 bits = (hdr->type2.cps_lo << 2) | hdr->type2.cps_hi;
844 break;
845 case EGPRS_HDR_TYPE3:
846 bits = (hdr->type3.cps_lo << 2) | hdr->type3.cps_hi;
847 break;
848 default:
849 return -1;
850 }
851
852 return egprs_get_cps(cps, type, bits);
853}
854
855/*
856 * Decode EGPRS UL data section
857 *
858 * 1. Depuncture
859 * 2. Convolutional decoding
860 * 3. CRC check
861 * 4. Block combining (MCS-7,8,9 only)
862 */
Harald Welteb9946d32017-06-12 09:40:16 +0200863static int egprs_decode_data(uint8_t *l2_data, const sbit_t *c,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700864 int mcs, int p, int blk, int *n_errors, int *n_bits_total)
865{
866 ubit_t u[EGPRS_DATA_U_MAX];
867 sbit_t C[EGPRS_DATA_C_MAX];
868
869 int i, j, rc, data_len;
Harald Welte2f984ea2017-06-12 15:05:21 +0200870 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700871
872 if (blk && mcs < EGPRS_MCS7) {
873 /* Invalid MCS-X block state */
874 return -1;
875 }
876
877 code = &gsm0503_mcs_ul_codes[mcs];
878 if (!code->data_punc[p]) {
879 /* Invalid MCS-X data puncture matrix */
880 return -1;
881 }
882
883 /*
884 * MCS-1,6 - single block processing
885 * MCS-7,9 - dual block processing
886 */
887 if (mcs >= EGPRS_MCS7)
888 data_len = code->data_len / 2;
889 else
890 data_len = code->data_len;
891
892 i = code->data_code_len - 1;
893 j = code->data_punc_len - 1;
894
895 for (; i >= 0; i--) {
896 if (!code->data_punc[p][i])
897 C[i] = c[j--];
898 else
899 C[i] = 0;
900 }
901
Alexander Chemeris147051f2018-07-14 21:02:29 +0200902 osmo_conv_decode_ber_punctured(code->data_conv, C, u,
903 n_errors, n_bits_total, code->data_punc[p]);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700904 rc = osmo_crc16gen_check_bits(&gsm0503_mcs_crc12, u,
905 data_len, u + data_len);
906 if (rc)
907 return -1;
908
909 /* Offsets output pointer on the second block of Type 1 MCS */
910 osmo_ubit2pbit_ext(l2_data, code->hdr_len + blk * data_len,
911 u, 0, data_len, 1);
912
913 /* Return the number of bytes required for the bit message */
Maxdd75bac2017-06-13 15:07:01 +0200914 return OSMO_BYTES_FOR_BITS(code->hdr_len + code->data_len);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700915}
916
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200917/*! Decode EGPRS UL message
Harald Weltec6636782017-06-12 14:59:37 +0200918 * 1. Header section decoding
919 * 2. Extract CPS settings
920 * 3. Burst unmapping and deinterleaving
921 * 4. Data section decoding
922 * \param[out] l2_data caller-allocated buffer for L2 Frame
923 * \param[in] bursts burst input data as soft unpacked bits
924 * \param[in] nbits number of bits in \a bursts
925 * \param usf_p unused argument ?!?
926 * \param[out] n_errors number of detected bit-errors
Alexander Chemerised7d2dd2018-07-14 21:06:27 +0200927 * \param[out] n_bits_total total number of decoded bits
Harald Weltec6636782017-06-12 14:59:37 +0200928 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +0200929int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t nbits,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700930 uint8_t *usf_p, int *n_errors, int *n_bits_total)
931{
932 sbit_t dc[EGPRS_DATA_DC_MAX];
933 sbit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
934 int type, rc;
935 struct egprs_cps cps;
936 union gprs_rlc_ul_hdr_egprs *hdr;
937
Alexander Chemeris50f7d742018-07-14 21:07:27 +0200938 if (n_errors)
939 *n_errors = 0;
940 if (n_bits_total)
941 *n_bits_total = 0;
942
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700943 if ((nbits != GSM0503_GPRS_BURSTS_NBITS) &&
944 (nbits != GSM0503_EGPRS_BURSTS_NBITS)) {
945 /* Invalid EGPRS bit length */
Maxc8cf8202017-05-22 16:07:04 +0200946 return -EOVERFLOW;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700947 }
948
949 hdr = (union gprs_rlc_ul_hdr_egprs *) l2_data;
950 type = egprs_decode_hdr(hdr, bursts, nbits);
951 if (egprs_parse_ul_cps(&cps, hdr, type) < 0)
Maxc8cf8202017-05-22 16:07:04 +0200952 return -EIO;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700953
954 switch (cps.mcs) {
Maxc8cf8202017-05-22 16:07:04 +0200955 case EGPRS_MCS0:
956 return -ENOTSUP;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700957 case EGPRS_MCS1:
958 case EGPRS_MCS2:
959 case EGPRS_MCS3:
960 case EGPRS_MCS4:
961 egprs_type3_unmap(bursts, NULL, dc);
962 break;
963 case EGPRS_MCS5:
964 case EGPRS_MCS6:
965 egprs_type2_unmap(bursts, NULL, dc);
966 break;
967 case EGPRS_MCS7:
968 case EGPRS_MCS8:
969 case EGPRS_MCS9:
970 egprs_type1_unmap(bursts, NULL, c1, c2, cps.mcs);
971 break;
972 default:
973 /* Invalid MCS-X */
Maxc8cf8202017-05-22 16:07:04 +0200974 return -EINVAL;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700975 }
976
977 /* Decode MCS-X block, where X = cps.mcs */
978 if (cps.mcs < EGPRS_MCS7) {
979 rc = egprs_decode_data(l2_data, dc, cps.mcs, cps.p[0],
980 0, n_errors, n_bits_total);
981 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200982 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700983 } else {
Alexander Chemeris94443262018-07-14 21:09:54 +0200984 /* Bit counters for the second block */
985 int n_errors2, n_bits_total2;
986
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700987 /* MCS-7,8,9 block 1 */
988 rc = egprs_decode_data(l2_data, c1, cps.mcs, cps.p[0],
989 0, n_errors, n_bits_total);
990 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200991 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700992
993 /* MCS-7,8,9 block 2 */
994 rc = egprs_decode_data(l2_data, c2, cps.mcs, cps.p[1],
Alexander Chemeris94443262018-07-14 21:09:54 +0200995 1, &n_errors2, &n_bits_total2);
996 if (n_errors)
997 *n_errors += n_errors2;
998 if (n_bits_total)
999 *n_bits_total += n_bits_total2;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001000 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +02001001 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001002 }
1003
1004 return rc;
1005}
1006
1007/*
1008 * GSM PDTCH block transcoding
1009 */
1010
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001011/*! Decode GPRS PDTCH
Harald Weltec6636782017-06-12 14:59:37 +02001012 * \param[out] l2_data caller-allocated buffer for L2 Frame
1013 * \param[in] bursts burst input data as soft unpacked bits
1014 * \param[out] usf_p uplink stealing flag
1015 * \param[out] n_errors number of detected bit-errors
1016 * \param[out] n_bits_total total number of dcoded bits
1017 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001018int gsm0503_pdtch_decode(uint8_t *l2_data, const sbit_t *bursts, uint8_t *usf_p,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001019 int *n_errors, int *n_bits_total)
1020{
1021 sbit_t iB[456], cB[676], hl_hn[8];
1022 ubit_t conv[456];
1023 int i, j, k, rv, best = 0, cs = 0, usf = 0; /* make GCC happy */
1024
1025 for (i = 0; i < 4; i++)
1026 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
1027 hl_hn + i * 2, hl_hn + i * 2 + 1);
1028
1029 for (i = 0; i < 4; i++) {
1030 for (j = 0, k = 0; j < 8; j++)
1031 k += abs(((int)gsm0503_pdtch_hl_hn_sbit[i][j]) - ((int)hl_hn[j]));
1032
1033 if (i == 0 || k < best) {
1034 best = k;
1035 cs = i + 1;
1036 }
1037 }
1038
1039 gsm0503_xcch_deinterleave(cB, iB);
1040
1041 switch (cs) {
1042 case 1:
1043 osmo_conv_decode_ber(&gsm0503_xcch, cB,
1044 conv, n_errors, n_bits_total);
1045
1046 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
1047 conv, 184, conv + 184);
1048 if (rv)
1049 return -1;
1050
1051 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
1052
1053 return 23;
1054 case 2:
1055 for (i = 587, j = 455; i >= 0; i--) {
1056 if (!gsm0503_puncture_cs2[i])
1057 cB[i] = cB[j--];
1058 else
1059 cB[i] = 0;
1060 }
1061
1062 osmo_conv_decode_ber(&gsm0503_cs2_np, cB,
1063 conv, n_errors, n_bits_total);
1064
1065 for (i = 0; i < 8; i++) {
1066 for (j = 0, k = 0; j < 6; j++)
1067 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1068
1069 if (i == 0 || k < best) {
1070 best = k;
1071 usf = i;
1072 }
1073 }
1074
1075 conv[3] = usf & 1;
1076 conv[4] = (usf >> 1) & 1;
1077 conv[5] = (usf >> 2) & 1;
1078 if (usf_p)
1079 *usf_p = usf;
1080
1081 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1082 conv + 3, 271, conv + 3 + 271);
1083 if (rv)
1084 return -1;
1085
1086 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 271, 1);
1087
1088 return 34;
1089 case 3:
1090 for (i = 675, j = 455; i >= 0; i--) {
1091 if (!gsm0503_puncture_cs3[i])
1092 cB[i] = cB[j--];
1093 else
1094 cB[i] = 0;
1095 }
1096
1097 osmo_conv_decode_ber(&gsm0503_cs3_np, cB,
1098 conv, n_errors, n_bits_total);
1099
1100 for (i = 0; i < 8; i++) {
1101 for (j = 0, k = 0; j < 6; j++)
1102 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1103
1104 if (i == 0 || k < best) {
1105 best = k;
1106 usf = i;
1107 }
1108 }
1109
1110 conv[3] = usf & 1;
1111 conv[4] = (usf >> 1) & 1;
1112 conv[5] = (usf >> 2) & 1;
1113 if (usf_p)
1114 *usf_p = usf;
1115
1116 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1117 conv + 3, 315, conv + 3 + 315);
1118 if (rv)
1119 return -1;
1120
1121 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 315, 1);
1122
1123 return 40;
1124 case 4:
1125 for (i = 12; i < 456; i++)
1126 conv[i] = (cB[i] < 0) ? 1 : 0;
1127
1128 for (i = 0; i < 8; i++) {
1129 for (j = 0, k = 0; j < 12; j++)
1130 k += abs(((int)gsm0503_usf2twelve_sbit[i][j]) - ((int)cB[j]));
1131
1132 if (i == 0 || k < best) {
1133 best = k;
1134 usf = i;
1135 }
1136 }
1137
1138 conv[9] = usf & 1;
1139 conv[10] = (usf >> 1) & 1;
1140 conv[11] = (usf >> 2) & 1;
1141 if (usf_p)
1142 *usf_p = usf;
1143
1144 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1145 conv + 9, 431, conv + 9 + 431);
1146 if (rv) {
1147 *n_bits_total = 456 - 12;
1148 *n_errors = *n_bits_total;
1149 return -1;
1150 }
1151
1152 *n_bits_total = 456 - 12;
1153 *n_errors = 0;
1154
1155 osmo_ubit2pbit_ext(l2_data, 0, conv, 9, 431, 1);
1156
1157 return 54;
1158 default:
1159 *n_bits_total = 0;
1160 *n_errors = 0;
1161 break;
1162 }
1163
1164 return -1;
1165}
1166
1167/*
Pau Espin Pedrolf62f0732020-04-07 13:12:11 +02001168 * EGPRS PDTCH DL block encoding
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001169 */
Harald Welteb9946d32017-06-12 09:40:16 +02001170static int egprs_type3_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001171{
1172 int i;
1173 ubit_t iB[456];
1174 const ubit_t *hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1175
Pau Espin Pedrol63ebc362020-04-07 13:15:36 +02001176 gsm0503_mcs1_dl_interleave(gsm0503_usf2twelve_ubit[usf], hc, dc, iB);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001177
1178 for (i = 0; i < 4; i++) {
1179 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1180 hl_hn + i * 2, hl_hn + i * 2 + 1);
1181 }
1182
1183 return 0;
1184}
1185
Harald Welteb9946d32017-06-12 09:40:16 +02001186static int egprs_type2_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001187{
1188 int i;
1189 const ubit_t *up;
1190 ubit_t hi[EGPRS_HDR_HC_MAX];
1191 ubit_t di[EGPRS_DATA_DC_MAX];
1192
1193 gsm0503_mcs5_dl_interleave(hc, dc, hi, di);
1194 up = gsm0503_mcs5_usf_precode_table[usf];
1195
1196 for (i = 0; i < 4; i++) {
1197 gsm0503_mcs5_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1198 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1199 }
1200
1201 return 0;
1202}
1203
Harald Welteb9946d32017-06-12 09:40:16 +02001204static int egprs_type1_map(ubit_t *bursts, const ubit_t *hc,
1205 const ubit_t *c1, const ubit_t *c2, int usf, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001206{
1207 int i;
1208 const ubit_t *up;
1209 ubit_t hi[EGPRS_HDR_HC_MAX];
1210 ubit_t di[EGPRS_DATA_C1 * 2];
1211
1212 if (mcs == EGPRS_MCS7)
1213 gsm0503_mcs7_dl_interleave(hc, c1, c2, hi, di);
1214 else
1215 gsm0503_mcs8_dl_interleave(hc, c1, c2, hi, di);
1216
1217 up = gsm0503_mcs5_usf_precode_table[usf];
1218
1219 for (i = 0; i < 4; i++) {
1220 gsm0503_mcs7_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1221 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1222 }
1223
1224 return 0;
1225}
1226
Harald Welteb9946d32017-06-12 09:40:16 +02001227static int egprs_encode_hdr(ubit_t *hc, const uint8_t *l2_data, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001228{
1229 int i, j;
1230 ubit_t upp[EGPRS_HDR_UPP_MAX], C[EGPRS_HDR_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001231 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001232
1233 code = &gsm0503_mcs_dl_codes[mcs];
1234
1235 osmo_pbit2ubit_ext(upp, 0, l2_data, code->usf_len, code->hdr_len, 1);
1236 osmo_crc8gen_set_bits(&gsm0503_mcs_crc8_hdr, upp,
1237 code->hdr_len, upp + code->hdr_len);
1238
1239 osmo_conv_encode(code->hdr_conv, upp, C);
1240
1241 /* MCS-5,6 header direct puncture instead of table */
1242 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
1243 memcpy(hc, C, code->hdr_code_len);
1244 hc[99] = hc[98];
1245 return 0;
1246 }
1247
1248 if (!code->hdr_punc) {
1249 /* Invalid MCS-X header puncture matrix */
1250 return -1;
1251 }
1252
1253 for (i = 0, j = 0; i < code->hdr_code_len; i++) {
1254 if (!code->hdr_punc[i])
1255 hc[j++] = C[i];
1256 }
1257
1258 return 0;
1259}
1260
Harald Welteb9946d32017-06-12 09:40:16 +02001261static int egprs_encode_data(ubit_t *c, const uint8_t *l2_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001262 int mcs, int p, int blk)
1263{
1264 int i, j, data_len;
1265 ubit_t u[EGPRS_DATA_U_MAX], C[EGPRS_DATA_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001266 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001267
1268 code = &gsm0503_mcs_dl_codes[mcs];
1269
1270 /*
1271 * Dual block - MCS-7,8,9
1272 * Single block - MCS-1,2,3,4,5,6
1273 */
1274 if (mcs >= EGPRS_MCS7)
1275 data_len = code->data_len / 2;
1276 else
1277 data_len = code->data_len;
1278
1279 osmo_pbit2ubit_ext(u, 0, l2_data,
1280 code->usf_len + code->hdr_len + blk * data_len, data_len, 1);
1281
1282 osmo_crc16gen_set_bits(&gsm0503_mcs_crc12, u, data_len, u + data_len);
1283
1284 osmo_conv_encode(code->data_conv, u, C);
1285
1286 if (!code->data_punc[p]) {
1287 /* Invalid MCS-X data puncture matrix */
1288 return -1;
1289 }
1290
1291 for (i = 0, j = 0; i < code->data_code_len; i++) {
1292 if (!code->data_punc[p][i])
1293 c[j++] = C[i];
1294 }
1295
1296 return 0;
1297}
1298
1299/*
1300 * Parse EGPRS DL header for coding and puncturing scheme (CPS)
1301 *
1302 * Type 1 - MCS-7,8,9
1303 * Type 2 - MCS-5,6
1304 * Type 3 - MCS-1,2,3,4
1305 */
1306static int egprs_parse_dl_cps(struct egprs_cps *cps,
Harald Welteb9946d32017-06-12 09:40:16 +02001307 const union gprs_rlc_dl_hdr_egprs *hdr, int type)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001308{
1309 uint8_t bits;
1310
1311 switch (type) {
1312 case EGPRS_HDR_TYPE1:
1313 bits = hdr->type1.cps;
1314 break;
1315 case EGPRS_HDR_TYPE2:
1316 bits = hdr->type2.cps;
1317 break;
1318 case EGPRS_HDR_TYPE3:
1319 bits = hdr->type3.cps;
1320 break;
1321 default:
1322 return -1;
1323 }
1324
1325 return egprs_get_cps(cps, type, bits);
1326}
1327
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001328/*! EGPRS DL message encoding
Harald Weltec6636782017-06-12 14:59:37 +02001329 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1330 * \param[in] l2_data L2 (MAC) block to be encoded
1331 * \param[in] l2_len length of l2_data in bytes, used to determine MCS
Vadim Yanitskiy8055cdd2020-03-30 18:16:38 +07001332 * \returns number of bits encoded; negative on error */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001333int gsm0503_pdtch_egprs_encode(ubit_t *bursts,
Harald Welteb9946d32017-06-12 09:40:16 +02001334 const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001335{
1336 ubit_t hc[EGPRS_DATA_C_MAX], dc[EGPRS_DATA_DC_MAX];
1337 ubit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
1338 uint8_t mcs;
1339 struct egprs_cps cps;
1340 union gprs_rlc_dl_hdr_egprs *hdr;
1341
1342 switch (l2_len) {
1343 case 27:
1344 mcs = EGPRS_MCS1;
1345 break;
1346 case 33:
1347 mcs = EGPRS_MCS2;
1348 break;
1349 case 42:
1350 mcs = EGPRS_MCS3;
1351 break;
1352 case 49:
1353 mcs = EGPRS_MCS4;
1354 break;
1355 case 60:
1356 mcs = EGPRS_MCS5;
1357 break;
1358 case 78:
1359 mcs = EGPRS_MCS6;
1360 break;
1361 case 118:
1362 mcs = EGPRS_MCS7;
1363 break;
1364 case 142:
1365 mcs = EGPRS_MCS8;
1366 break;
1367 case 154:
1368 mcs = EGPRS_MCS9;
1369 break;
1370 default:
1371 return -1;
1372 }
1373
1374 /* Read header for USF and puncturing matrix selection. */
1375 hdr = (union gprs_rlc_dl_hdr_egprs *) l2_data;
1376
1377 switch (mcs) {
1378 case EGPRS_MCS1:
1379 case EGPRS_MCS2:
1380 case EGPRS_MCS3:
1381 case EGPRS_MCS4:
1382 /* Check for valid CPS and matching MCS to message size */
1383 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE3) < 0) ||
1384 (cps.mcs != mcs))
1385 goto bad_header;
1386
1387 egprs_encode_hdr(hc, l2_data, mcs);
1388 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1389 egprs_type3_map(bursts, hc, dc, hdr->type3.usf);
1390 break;
1391 case EGPRS_MCS5:
1392 case EGPRS_MCS6:
1393 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE2) < 0) ||
1394 (cps.mcs != mcs))
1395 goto bad_header;
1396
1397 egprs_encode_hdr(hc, l2_data, mcs);
1398 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1399 egprs_type2_map(bursts, hc, dc, hdr->type2.usf);
1400 break;
1401 case EGPRS_MCS7:
1402 case EGPRS_MCS8:
1403 case EGPRS_MCS9:
1404 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE1) < 0) ||
1405 (cps.mcs != mcs))
1406 goto bad_header;
1407
1408 egprs_encode_hdr(hc, l2_data, mcs);
1409 egprs_encode_data(c1, l2_data, mcs, cps.p[0], 0);
1410 egprs_encode_data(c2, l2_data, mcs, cps.p[1], 1);
1411 egprs_type1_map(bursts, hc, c1, c2, hdr->type1.usf, mcs);
1412 break;
1413 }
1414
1415 return mcs >= EGPRS_MCS5 ?
1416 GSM0503_EGPRS_BURSTS_NBITS : GSM0503_GPRS_BURSTS_NBITS;
1417
1418bad_header:
1419 /* Invalid EGPRS MCS-X header */
1420 return -1;
1421}
1422
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001423/*! GPRS DL message encoding
Harald Weltec6636782017-06-12 14:59:37 +02001424 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1425 * \param[in] l2_data L2 (MAC) block to be encoded
1426 * \param[in] l2_len length of l2_data in bytes, used to determine CS
Vadim Yanitskiy8055cdd2020-03-30 18:16:38 +07001427 * \returns number of bits encoded; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001428int gsm0503_pdtch_encode(ubit_t *bursts, const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001429{
1430 ubit_t iB[456], cB[676];
1431 const ubit_t *hl_hn;
1432 ubit_t conv[334];
1433 int i, j, usf;
1434
1435 switch (l2_len) {
1436 case 23:
1437 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
1438
1439 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
1440
1441 osmo_conv_encode(&gsm0503_xcch, conv, cB);
1442
1443 hl_hn = gsm0503_pdtch_hl_hn_ubit[0];
1444
1445 break;
1446 case 34:
1447 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 271, 1);
1448 usf = l2_data[0] & 0x7;
1449
1450 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1451 271, conv + 3 + 271);
1452
1453 memcpy(conv, gsm0503_usf2six[usf], 6);
1454
1455 osmo_conv_encode(&gsm0503_cs2_np, conv, cB);
1456
1457 for (i = 0, j = 0; i < 588; i++)
1458 if (!gsm0503_puncture_cs2[i])
1459 cB[j++] = cB[i];
1460
1461 hl_hn = gsm0503_pdtch_hl_hn_ubit[1];
1462
1463 break;
1464 case 40:
1465 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 315, 1);
1466 usf = l2_data[0] & 0x7;
1467
1468 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1469 315, conv + 3 + 315);
1470
1471 memcpy(conv, gsm0503_usf2six[usf], 6);
1472
1473 osmo_conv_encode(&gsm0503_cs3_np, conv, cB);
1474
1475 for (i = 0, j = 0; i < 676; i++)
1476 if (!gsm0503_puncture_cs3[i])
1477 cB[j++] = cB[i];
1478
1479 hl_hn = gsm0503_pdtch_hl_hn_ubit[2];
1480
1481 break;
1482 case 54:
1483 osmo_pbit2ubit_ext(cB, 9, l2_data, 0, 431, 1);
1484 usf = l2_data[0] & 0x7;
1485
1486 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, cB + 9,
1487 431, cB + 9 + 431);
1488
1489 memcpy(cB, gsm0503_usf2twelve_ubit[usf], 12);
1490
1491 hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1492
1493 break;
1494 default:
1495 return -1;
1496 }
1497
1498 gsm0503_xcch_interleave(cB, iB);
1499
1500 for (i = 0; i < 4; i++) {
1501 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1502 hl_hn + i * 2, hl_hn + i * 2 + 1);
1503 }
1504
1505 return GSM0503_GPRS_BURSTS_NBITS;
1506}
1507
1508/*
1509 * GSM TCH/F FR/EFR transcoding
1510 */
1511
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001512/*! assemble a FR codec frame in format as used inside RTP
Harald Weltec6636782017-06-12 14:59:37 +02001513 * \param[out] tch_data Codec frame in RTP format
1514 * \param[in] b_bits Codec frame in 'native' format
1515 * \param[in] net_order FIXME */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001516static void tch_fr_reassemble(uint8_t *tch_data,
Harald Welteb9946d32017-06-12 09:40:16 +02001517 const ubit_t *b_bits, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001518{
1519 int i, j, k, l, o;
1520
1521 tch_data[0] = 0xd << 4;
1522 memset(tch_data + 1, 0, 32);
1523
1524 if (net_order) {
1525 for (i = 0, j = 4; i < 260; i++, j++)
1526 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1527
1528 return;
1529 }
1530
1531 /* reassemble d-bits */
1532 i = 0; /* counts bits */
1533 j = 4; /* counts output bits */
1534 k = gsm0503_gsm_fr_map[0]-1; /* current number bit in element */
1535 l = 0; /* counts element bits */
1536 o = 0; /* offset input bits */
1537 while (i < 260) {
1538 tch_data[j >> 3] |= (b_bits[k + o] << (7 - (j & 7)));
1539 if (--k < 0) {
1540 o += gsm0503_gsm_fr_map[l];
1541 k = gsm0503_gsm_fr_map[++l]-1;
1542 }
1543 i++;
1544 j++;
1545 }
1546}
1547
1548static void tch_fr_disassemble(ubit_t *b_bits,
Harald Welteb9946d32017-06-12 09:40:16 +02001549 const uint8_t *tch_data, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001550{
1551 int i, j, k, l, o;
1552
1553 if (net_order) {
1554 for (i = 0, j = 4; i < 260; i++, j++)
1555 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1556
1557 return;
1558 }
1559
1560 i = 0; /* counts bits */
1561 j = 4; /* counts input bits */
1562 k = gsm0503_gsm_fr_map[0] - 1; /* current number bit in element */
1563 l = 0; /* counts element bits */
1564 o = 0; /* offset output bits */
1565 while (i < 260) {
1566 b_bits[k + o] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1567 if (--k < 0) {
1568 o += gsm0503_gsm_fr_map[l];
1569 k = gsm0503_gsm_fr_map[++l] - 1;
1570 }
1571 i++;
1572 j++;
1573 }
1574}
1575
Harald Weltec6636782017-06-12 14:59:37 +02001576/* assemble a HR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001577static void tch_hr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001578{
1579 int i, j;
1580
1581 tch_data[0] = 0x00; /* F = 0, FT = 000 */
1582 memset(tch_data + 1, 0, 14);
1583
1584 for (i = 0, j = 8; i < 112; i++, j++)
1585 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1586}
1587
Harald Welteb9946d32017-06-12 09:40:16 +02001588static void tch_hr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001589{
1590 int i, j;
1591
1592 for (i = 0, j = 8; i < 112; i++, j++)
1593 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1594}
1595
Harald Weltec6636782017-06-12 14:59:37 +02001596/* assemble a EFR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001597static void tch_efr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001598{
1599 int i, j;
1600
1601 tch_data[0] = 0xc << 4;
1602 memset(tch_data + 1, 0, 30);
1603
1604 for (i = 0, j = 4; i < 244; i++, j++)
1605 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1606}
1607
Harald Welteb9946d32017-06-12 09:40:16 +02001608static void tch_efr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001609{
1610 int i, j;
1611
1612 for (i = 0, j = 4; i < 244; i++, j++)
1613 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1614}
1615
Harald Weltec6636782017-06-12 14:59:37 +02001616/* assemble a AMR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001617static void tch_amr_reassemble(uint8_t *tch_data, const ubit_t *d_bits, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001618{
1619 int i, j;
1620
1621 memset(tch_data, 0, (len + 7) >> 3);
1622
1623 for (i = 0, j = 0; i < len; i++, j++)
1624 tch_data[j >> 3] |= (d_bits[i] << (7 - (j & 7)));
1625}
1626
Harald Welteb9946d32017-06-12 09:40:16 +02001627static void tch_amr_disassemble(ubit_t *d_bits, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001628{
1629 int i, j;
1630
1631 for (i = 0, j = 0; i < len; i++, j++)
1632 d_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1633}
1634
Philipp Maier898c9c62020-02-06 14:25:01 +01001635/* Append STI and MI bits to the SID_UPDATE frame, see also
1636 * 3GPP TS 26.101, chapter 4.2.3 AMR Core Frame with comfort noise bits */
1637static void tch_amr_sid_update_append(ubit_t *sid_update, uint8_t sti, uint8_t mi)
1638{
1639 /* Zero out the space that had been used by the CRC14 */
1640 memset(sid_update + 35, 0, 14);
1641
1642 /* Append STI and MI parameters */
1643 sid_update[35] = sti & 1;
1644 sid_update[36] = mi & 1;
1645 sid_update[37] = mi >> 1 & 1;
1646 sid_update[38] = mi >> 2 & 1;
1647}
1648
1649/* Extract a SID UPDATE fram the sbits of an FR AMR frame */
1650static void extract_afs_sid_update(sbit_t *sid_update, const sbit_t *sbits)
1651{
1652
1653 unsigned int i;
1654
1655 sbits += 32;
1656
1657 for (i = 0; i < 53; i++) {
1658 sid_update[0] = sbits[0];
1659 sid_update[1] = sbits[1];
1660 sid_update[2] = sbits[2];
1661 sid_update[3] = sbits[3];
1662 sid_update += 4;
1663 sbits += 8;
1664 }
1665
1666}
1667
Harald Weltec6636782017-06-12 14:59:37 +02001668/* re-arrange according to TS 05.03 Table 2 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001669static void tch_fr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001670{
1671 int i;
1672
1673 for (i = 0; i < 260; i++)
1674 b_bits[gsm610_bitorder[i]] = d_bits[i];
1675}
1676
Harald Weltec6636782017-06-12 14:59:37 +02001677/* re-arrange according to TS 05.03 Table 2 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001678static void tch_fr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001679{
1680 int i;
1681
1682 for (i = 0; i < 260; i++)
1683 d_bits[i] = b_bits[gsm610_bitorder[i]];
1684}
1685
Harald Weltec6636782017-06-12 14:59:37 +02001686/* re-arrange according to TS 05.03 Table 3a (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001687static void tch_hr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001688{
1689 int i;
1690
1691 const uint16_t *map;
1692
1693 if (!d_bits[93] && !d_bits[94])
1694 map = gsm620_unvoiced_bitorder;
1695 else
1696 map = gsm620_voiced_bitorder;
1697
1698 for (i = 0; i < 112; i++)
1699 b_bits[map[i]] = d_bits[i];
1700}
1701
Harald Weltec6636782017-06-12 14:59:37 +02001702/* re-arrange according to TS 05.03 Table 3a (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001703static void tch_hr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001704{
1705 int i;
1706 const uint16_t *map;
1707
1708 if (!b_bits[34] && !b_bits[35])
1709 map = gsm620_unvoiced_bitorder;
1710 else
1711 map = gsm620_voiced_bitorder;
1712
1713 for (i = 0; i < 112; i++)
1714 d_bits[i] = b_bits[map[i]];
1715}
1716
Harald Weltec6636782017-06-12 14:59:37 +02001717/* re-arrange according to TS 05.03 Table 6 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001718static void tch_efr_d_to_w(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001719{
1720 int i;
1721
1722 for (i = 0; i < 260; i++)
1723 b_bits[gsm660_bitorder[i]] = d_bits[i];
1724}
1725
Harald Weltec6636782017-06-12 14:59:37 +02001726/* re-arrange according to TS 05.03 Table 6 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001727static void tch_efr_w_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001728{
1729 int i;
1730
1731 for (i = 0; i < 260; i++)
1732 d_bits[i] = b_bits[gsm660_bitorder[i]];
1733}
1734
Harald Weltec6636782017-06-12 14:59:37 +02001735/* extract the 65 protected class1a+1b bits */
Harald Welteb9946d32017-06-12 09:40:16 +02001736static void tch_efr_protected(const ubit_t *s_bits, ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001737{
1738 int i;
1739
1740 for (i = 0; i < 65; i++)
1741 b_bits[i] = s_bits[gsm0503_gsm_efr_protected_bits[i] - 1];
1742}
1743
Harald Welteb9946d32017-06-12 09:40:16 +02001744static void tch_fr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001745{
1746 int i;
1747
1748 for (i = 0; i < 91; i++) {
1749 d[i << 1] = u[i];
1750 d[(i << 1) + 1] = u[184 - i];
1751 }
1752
1753 for (i = 0; i < 3; i++)
1754 p[i] = u[91 + i];
1755}
1756
Harald Welteb9946d32017-06-12 09:40:16 +02001757static void tch_fr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001758{
1759 int i;
1760
1761 for (i = 0; i < 91; i++) {
1762 u[i] = d[i << 1];
1763 u[184 - i] = d[(i << 1) + 1];
1764 }
1765
1766 for (i = 0; i < 3; i++)
1767 u[91 + i] = p[i];
1768}
1769
Harald Welteb9946d32017-06-12 09:40:16 +02001770static void tch_hr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001771{
1772 memcpy(d, u, 95);
1773 memcpy(p, u + 95, 3);
1774}
1775
Harald Welteb9946d32017-06-12 09:40:16 +02001776static void tch_hr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001777{
1778 memcpy(u, d, 95);
1779 memcpy(u + 95, p, 3);
1780}
1781
Harald Welteb9946d32017-06-12 09:40:16 +02001782static void tch_efr_reorder(ubit_t *w, const ubit_t *s, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001783{
1784 memcpy(w, s, 71);
1785 w[71] = w[72] = s[69];
1786 memcpy(w + 73, s + 71, 50);
1787 w[123] = w[124] = s[119];
1788 memcpy(w + 125, s + 121, 53);
1789 w[178] = w[179] = s[172];
1790 memcpy(w + 180, s + 174, 50);
1791 w[230] = w[231] = s[222];
1792 memcpy(w + 232, s + 224, 20);
1793 memcpy(w + 252, p, 8);
1794}
1795
Harald Welteb9946d32017-06-12 09:40:16 +02001796static void tch_efr_unreorder(ubit_t *s, ubit_t *p, const ubit_t *w)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001797{
1798 int sum;
1799
1800 memcpy(s, w, 71);
1801 sum = s[69] + w[71] + w[72];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001802 s[69] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001803 memcpy(s + 71, w + 73, 50);
1804 sum = s[119] + w[123] + w[124];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001805 s[119] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001806 memcpy(s + 121, w + 125, 53);
1807 sum = s[172] + w[178] + w[179];
1808 s[172] = (sum > 2);
1809 memcpy(s + 174, w + 180, 50);
Niro Mahasinghe834e2ac2017-11-03 12:22:34 +01001810 sum = s[222] + w[230] + w[231];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001811 s[222] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001812 memcpy(s + 224, w + 232, 20);
1813 memcpy(p, w + 252, 8);
1814}
1815
Harald Welteb9946d32017-06-12 09:40:16 +02001816static 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 +07001817{
1818 memcpy(u, d, prot);
1819 memcpy(u + prot, p, 6);
1820 memcpy(u + prot + 6, d + prot, len - prot);
1821}
1822
Harald Welteb9946d32017-06-12 09:40:16 +02001823static 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 +07001824{
1825 memcpy(d, u, prot);
1826 memcpy(p, u + prot, 6);
1827 memcpy(d + prot, u + prot + 6, len - prot);
1828}
1829
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001830/*! Perform channel decoding of a FR/EFR channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001831 * \param[out] tch_data Codec frame in RTP payload format
1832 * \param[in] bursts buffer containing the symbols of 8 bursts
1833 * \param[in] net_order FIXME
1834 * \param[in] efr Is this channel using EFR (1) or FR (0)
1835 * \param[out] n_errors Number of detected bit errors
1836 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02001837 * \returns length of bytes used in \a tch_data output buffer; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001838int gsm0503_tch_fr_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001839 int net_order, int efr, int *n_errors, int *n_bits_total)
1840{
1841 sbit_t iB[912], cB[456], h;
1842 ubit_t conv[185], s[244], w[260], b[65], d[260], p[8];
1843 int i, rv, len, steal = 0;
1844
Harald Weltec6636782017-06-12 14:59:37 +02001845 /* map from 8 bursts to interleaved data bits (iB) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001846 for (i = 0; i < 8; i++) {
1847 gsm0503_tch_burst_unmap(&iB[i * 114],
1848 &bursts[i * 116], &h, i >> 2);
1849 steal -= h;
1850 }
Harald Weltec6636782017-06-12 14:59:37 +02001851 /* we now have the bits of the four bursts (interface 4 in
1852 * Figure 1a of TS 05.03 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001853
1854 gsm0503_tch_fr_deinterleave(cB, iB);
Harald Weltec6636782017-06-12 14:59:37 +02001855 /* we now have the coded bits c(B): interface 3 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001856
1857 if (steal > 0) {
1858 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
1859 if (rv) {
1860 /* Error decoding FACCH frame */
1861 return -1;
1862 }
1863
1864 return 23;
1865 }
1866
1867 osmo_conv_decode_ber(&gsm0503_tch_fr, cB, conv, n_errors, n_bits_total);
Harald Weltec6636782017-06-12 14:59:37 +02001868 /* we now have the data bits 'u': interface 2 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001869
Harald Weltec6636782017-06-12 14:59:37 +02001870 /* input: 'conv', output: d[ata] + p[arity] */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001871 tch_fr_unreorder(d, p, conv);
1872
1873 for (i = 0; i < 78; i++)
1874 d[i + 182] = (cB[i + 378] < 0) ? 1 : 0;
1875
Harald Weltec6636782017-06-12 14:59:37 +02001876 /* check if parity of first 50 (class 1) 'd'-bits match 'p' */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001877 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1878 if (rv) {
1879 /* Error checking CRC8 for the FR part of an EFR/FR frame */
1880 return -1;
1881 }
1882
1883 if (efr) {
1884 tch_efr_d_to_w(w, d);
Harald Weltec6636782017-06-12 14:59:37 +02001885 /* we now have the preliminary-coded bits w(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001886
1887 tch_efr_unreorder(s, p, w);
Harald Weltec6636782017-06-12 14:59:37 +02001888 /* we now have the data delivered to the preliminary
1889 * channel encoding unit s(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001890
Harald Weltec6636782017-06-12 14:59:37 +02001891 /* extract the 65 most important bits according TS 05.03 3.1.1.1 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001892 tch_efr_protected(s, b);
1893
Harald Weltec6636782017-06-12 14:59:37 +02001894 /* perform CRC-8 on 65 most important bits (50 bits of
1895 * class 1a + 15 bits of class 1b) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001896 rv = osmo_crc8gen_check_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1897 if (rv) {
1898 /* Error checking CRC8 for the EFR part of an EFR frame */
1899 return -1;
1900 }
1901
1902 tch_efr_reassemble(tch_data, s);
1903
1904 len = GSM_EFR_BYTES;
1905 } else {
1906 tch_fr_d_to_b(w, d);
1907
1908 tch_fr_reassemble(tch_data, w, net_order);
1909
1910 len = GSM_FR_BYTES;
1911 }
1912
1913 return len;
1914}
1915
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001916/*! Perform channel encoding on a TCH/FS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001917 * \param[out] bursts caller-allocated output buffer for bursts bits
1918 * \param[in] tch_data Codec input data in RTP payload format
1919 * \param[in] len Length of \a tch_data in bytes
1920 * \param[in] net_order FIXME
1921 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001922int gsm0503_tch_fr_encode(ubit_t *bursts, const uint8_t *tch_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001923 int len, int net_order)
1924{
1925 ubit_t iB[912], cB[456], h;
1926 ubit_t conv[185], w[260], b[65], s[244], d[260], p[8];
1927 int i;
1928
1929 switch (len) {
1930 case GSM_EFR_BYTES: /* TCH EFR */
1931
1932 tch_efr_disassemble(s, tch_data);
1933
1934 tch_efr_protected(s, b);
1935
1936 osmo_crc8gen_set_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1937
1938 tch_efr_reorder(w, s, p);
1939
1940 tch_efr_w_to_d(d, w);
1941
1942 goto coding_efr_fr;
1943 case GSM_FR_BYTES: /* TCH FR */
1944 tch_fr_disassemble(w, tch_data, net_order);
1945
1946 tch_fr_b_to_d(d, w);
1947
1948coding_efr_fr:
1949 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1950
1951 tch_fr_reorder(conv, d, p);
1952
1953 memcpy(cB + 378, d + 182, 78);
1954
1955 osmo_conv_encode(&gsm0503_tch_fr, conv, cB);
1956
1957 h = 0;
1958
1959 break;
1960 case GSM_MACBLOCK_LEN: /* FACCH */
1961 _xcch_encode_cB(cB, tch_data);
1962
1963 h = 1;
1964
1965 break;
1966 default:
1967 return -1;
1968 }
1969
1970 gsm0503_tch_fr_interleave(cB, iB);
1971
1972 for (i = 0; i < 8; i++) {
1973 gsm0503_tch_burst_map(&iB[i * 114],
1974 &bursts[i * 116], &h, i >> 2);
1975 }
1976
1977 return 0;
1978}
1979
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001980/*! Perform channel decoding of a HR(v1) channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001981 * \param[out] tch_data Codec frame in RTP payload format
1982 * \param[in] bursts buffer containing the symbols of 8 bursts
1983 * \param[in] odd Odd (1) or even (0) frame number
1984 * \param[out] n_errors Number of detected bit errors
1985 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02001986 * \returns length of bytes used in \a tch_data output buffer; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001987int gsm0503_tch_hr_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001988 int *n_errors, int *n_bits_total)
1989{
1990 sbit_t iB[912], cB[456], h;
1991 ubit_t conv[98], b[112], d[112], p[3];
1992 int i, rv, steal = 0;
1993
1994 /* Only unmap the stealing bits */
1995 if (!odd) {
1996 for (i = 0; i < 4; i++) {
1997 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
1998 steal -= h;
1999 }
2000
2001 for (i = 2; i < 5; i++) {
2002 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
2003 steal -= h;
2004 }
2005 }
2006
2007 /* If we found a stole FACCH, but only at correct alignment */
2008 if (steal > 0) {
2009 for (i = 0; i < 6; i++) {
2010 gsm0503_tch_burst_unmap(&iB[i * 114],
2011 &bursts[i * 116], NULL, i >> 2);
2012 }
2013
2014 for (i = 2; i < 4; i++) {
2015 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
2016 &bursts[i * 116], NULL, 1);
2017 }
2018
2019 gsm0503_tch_fr_deinterleave(cB, iB);
2020
2021 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2022 if (rv) {
2023 /* Error decoding FACCH frame */
2024 return -1;
2025 }
2026
2027 return GSM_MACBLOCK_LEN;
2028 }
2029
2030 for (i = 0; i < 4; i++) {
2031 gsm0503_tch_burst_unmap(&iB[i * 114],
2032 &bursts[i * 116], NULL, i >> 1);
2033 }
2034
2035 gsm0503_tch_hr_deinterleave(cB, iB);
2036
2037 osmo_conv_decode_ber(&gsm0503_tch_hr, cB, conv, n_errors, n_bits_total);
2038
2039 tch_hr_unreorder(d, p, conv);
2040
2041 for (i = 0; i < 17; i++)
2042 d[i + 95] = (cB[i + 211] < 0) ? 1 : 0;
2043
2044 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
2045 if (rv) {
2046 /* Error checking CRC8 for an HR frame */
2047 return -1;
2048 }
2049
2050 tch_hr_d_to_b(b, d);
2051
2052 tch_hr_reassemble(tch_data, b);
2053
2054 return 15;
2055}
2056
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002057/*! Perform channel encoding on a TCH/HS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002058 * \param[out] bursts caller-allocated output buffer for bursts bits
2059 * \param[in] tch_data Codec input data in RTP payload format
2060 * \param[in] len Length of \a tch_data in bytes
2061 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002062int gsm0503_tch_hr_encode(ubit_t *bursts, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002063{
2064 ubit_t iB[912], cB[456], h;
2065 ubit_t conv[98], b[112], d[112], p[3];
2066 int i;
2067
2068 switch (len) {
2069 case 15: /* TCH HR */
2070 tch_hr_disassemble(b, tch_data);
2071
2072 tch_hr_b_to_d(d, b);
2073
2074 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
2075
2076 tch_hr_reorder(conv, d, p);
2077
2078 osmo_conv_encode(&gsm0503_tch_hr, conv, cB);
2079
2080 memcpy(cB + 211, d + 95, 17);
2081
2082 h = 0;
2083
2084 gsm0503_tch_hr_interleave(cB, iB);
2085
2086 for (i = 0; i < 4; i++) {
2087 gsm0503_tch_burst_map(&iB[i * 114],
2088 &bursts[i * 116], &h, i >> 1);
2089 }
2090
2091 break;
2092 case GSM_MACBLOCK_LEN: /* FACCH */
2093 _xcch_encode_cB(cB, tch_data);
2094
2095 h = 1;
2096
2097 gsm0503_tch_fr_interleave(cB, iB);
2098
2099 for (i = 0; i < 6; i++) {
2100 gsm0503_tch_burst_map(&iB[i * 114],
2101 &bursts[i * 116], &h, i >> 2);
2102 }
2103
2104 for (i = 2; i < 4; i++) {
2105 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2106 &bursts[i * 116], &h, 1);
2107 }
2108
2109 break;
2110 default:
2111 return -1;
2112 }
2113
2114 return 0;
2115}
2116
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002117/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002118 * \param[out] tch_data Codec frame in RTP payload format
2119 * \param[in] bursts buffer containing the symbols of 8 bursts
2120 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2121 * \param[in] codec array of active codecs (active codec set)
2122 * \param[in] codecs number of codecs in \a codec
2123 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2124 * \param[out] cmr Output in \a codec_mode_req = 1
2125 * \param[out] n_errors Number of detected bit errors
2126 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02002127 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2128 * codec out of range; negative on error
2129 */
Harald Welteb9946d32017-06-12 09:40:16 +02002130int gsm0503_tch_afs_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002131 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2132 uint8_t *cmr, int *n_errors, int *n_bits_total)
2133{
Philipp Maier898c9c62020-02-06 14:25:01 +01002134 return gsm0503_tch_afs_decode_dtx(tch_data, bursts, codec_mode_req,
2135 codec, codecs, ft, cmr, n_errors,
2136 n_bits_total, NULL);
2137}
2138
2139/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
2140 * \param[out] tch_data Codec frame in RTP payload format
2141 * \param[in] bursts buffer containing the symbols of 8 bursts
2142 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2143 * \param[in] codec array of active codecs (active codec set)
2144 * \param[in] codecs number of codecs in \a codec
2145 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2146 * \param[out] cmr Output in \a codec_mode_req = 1
2147 * \param[out] n_errors Number of detected bit errors
2148 * \param[out] n_bits_total Total number of bits
2149 * \param[inout] dtx DTX frame type output, previous DTX frame type input
2150 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2151 * codec out of range; negative on error
2152 */
2153int gsm0503_tch_afs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts,
2154 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2155 uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx)
2156{
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002157 sbit_t iB[912], cB[456], h;
2158 ubit_t d[244], p[6], conv[250];
2159 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
Philipp Maier898c9c62020-02-06 14:25:01 +01002160 ubit_t cBd[456];
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002161 *n_errors = 0; *n_bits_total = 0;
Philipp Maier898c9c62020-02-06 14:25:01 +01002162 static ubit_t sid_first_dummy[64] = { 0 };
2163 sbit_t sid_update_enc[256];
2164 uint8_t dtx_prev;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002165
2166 for (i=0; i<8; i++) {
2167 gsm0503_tch_burst_unmap(&iB[i * 114], &bursts[i * 116], &h, i >> 2);
2168 steal -= h;
2169 }
2170
2171 gsm0503_tch_fr_deinterleave(cB, iB);
2172
2173 if (steal > 0) {
2174 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2175 if (rv) {
2176 /* Error decoding FACCH frame */
2177 return -1;
2178 }
2179
2180 return GSM_MACBLOCK_LEN;
2181 }
2182
Philipp Maier898c9c62020-02-06 14:25:01 +01002183 /* Determine the DTX frame type (SID_UPDATE, ONSET etc...) */
2184 if (dtx) {
2185 osmo_sbit2ubit(cBd, cB, 456);
2186 dtx_prev = *dtx;
2187 *dtx = gsm0503_detect_afs_dtx_frame(n_errors, n_bits_total, cBd);
2188
2189 if (dtx_prev == AFS_SID_UPDATE && *dtx == AMR_OTHER) {
2190 /* NOTE: The AFS_SID_UPDATE frame is splitted into
2191 * two half rate frames. If the id marker frame
2192 * (AFS_SID_UPDATE) is detected the following frame
2193 * contains the actual comfort noised data part of
2194 * (AFS_SID_UPDATE_CN). */
2195 *dtx = AFS_SID_UPDATE_CN;
2196
2197 extract_afs_sid_update(sid_update_enc, cB);
2198 osmo_conv_decode_ber(&gsm0503_tch_axs_sid_update,
2199 sid_update_enc, conv, n_errors,
2200 n_bits_total);
2201 rv = osmo_crc16gen_check_bits(&gsm0503_amr_crc14, conv,
2202 35, conv + 35);
2203 if (rv != 0) {
2204 /* Error checking CRC14 for an AMR SID_UPDATE frame */
2205 return -1;
2206 }
2207
2208 tch_amr_sid_update_append(conv, 1,
2209 (codec_mode_req) ? codec[*ft]
2210 : codec[id]);
2211 tch_amr_reassemble(tch_data, conv, 39);
2212 len = 5;
2213 goto out;
2214 } else if (*dtx == AFS_SID_FIRST) {
2215 tch_amr_sid_update_append(sid_first_dummy, 0,
2216 (codec_mode_req) ? codec[*ft]
2217 : codec[id]);
2218 tch_amr_reassemble(tch_data, conv, 39);
2219 len = 5;
2220 goto out;
2221 } else if (*dtx == AFS_ONSET) {
2222 len = 0;
2223 goto out;
2224 }
2225 }
2226
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002227 for (i = 0; i < 4; i++) {
2228 for (j = 0, k = 0; j < 8; j++)
2229 k += abs(((int)gsm0503_afs_ic_sbit[i][j]) - ((int)cB[j]));
2230
2231 if (i == 0 || k < best) {
2232 best = k;
2233 id = i;
2234 }
2235 }
2236
2237 /* Check if indicated codec fits into range of codecs */
2238 if (id >= codecs) {
2239 /* Codec mode out of range, return id */
2240 return id;
2241 }
2242
2243 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2244 case 7: /* TCH/AFS12.2 */
2245 osmo_conv_decode_ber(&gsm0503_tch_afs_12_2, cB + 8,
2246 conv, n_errors, n_bits_total);
2247
2248 tch_amr_unmerge(d, p, conv, 244, 81);
2249
2250 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 81, p);
2251 if (rv) {
2252 /* Error checking CRC8 for an AMR 12.2 frame */
2253 return -1;
2254 }
2255
2256 tch_amr_reassemble(tch_data, d, 244);
2257
2258 len = 31;
2259
2260 break;
2261 case 6: /* TCH/AFS10.2 */
2262 osmo_conv_decode_ber(&gsm0503_tch_afs_10_2, cB + 8,
2263 conv, n_errors, n_bits_total);
2264
2265 tch_amr_unmerge(d, p, conv, 204, 65);
2266
2267 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 65, p);
2268 if (rv) {
2269 /* Error checking CRC8 for an AMR 10.2 frame */
2270 return -1;
2271 }
2272
2273 tch_amr_reassemble(tch_data, d, 204);
2274
2275 len = 26;
2276
2277 break;
2278 case 5: /* TCH/AFS7.95 */
2279 osmo_conv_decode_ber(&gsm0503_tch_afs_7_95, cB + 8,
2280 conv, n_errors, n_bits_total);
2281
2282 tch_amr_unmerge(d, p, conv, 159, 75);
2283
2284 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 75, p);
2285 if (rv) {
2286 /* Error checking CRC8 for an AMR 7.95 frame */
2287 return -1;
2288 }
2289
2290 tch_amr_reassemble(tch_data, d, 159);
2291
2292 len = 20;
2293
2294 break;
2295 case 4: /* TCH/AFS7.4 */
2296 osmo_conv_decode_ber(&gsm0503_tch_afs_7_4, cB + 8,
2297 conv, n_errors, n_bits_total);
2298
2299 tch_amr_unmerge(d, p, conv, 148, 61);
2300
2301 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2302 if (rv) {
2303 /* Error checking CRC8 for an AMR 7.4 frame */
2304 return -1;
2305 }
2306
2307 tch_amr_reassemble(tch_data, d, 148);
2308
2309 len = 19;
2310
2311 break;
2312 case 3: /* TCH/AFS6.7 */
2313 osmo_conv_decode_ber(&gsm0503_tch_afs_6_7, cB + 8,
2314 conv, n_errors, n_bits_total);
2315
2316 tch_amr_unmerge(d, p, conv, 134, 55);
2317
2318 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2319 if (rv) {
2320 /* Error checking CRC8 for an AMR 6.7 frame */
2321 return -1;
2322 }
2323
2324 tch_amr_reassemble(tch_data, d, 134);
2325
2326 len = 17;
2327
2328 break;
2329 case 2: /* TCH/AFS5.9 */
2330 osmo_conv_decode_ber(&gsm0503_tch_afs_5_9, cB + 8,
2331 conv, n_errors, n_bits_total);
2332
2333 tch_amr_unmerge(d, p, conv, 118, 55);
2334
2335 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2336 if (rv) {
2337 /* Error checking CRC8 for an AMR 5.9 frame */
2338 return -1;
2339 }
2340
2341 tch_amr_reassemble(tch_data, d, 118);
2342
2343 len = 15;
2344
2345 break;
2346 case 1: /* TCH/AFS5.15 */
2347 osmo_conv_decode_ber(&gsm0503_tch_afs_5_15, cB + 8,
2348 conv, n_errors, n_bits_total);
2349
2350 tch_amr_unmerge(d, p, conv, 103, 49);
2351
2352 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2353 if (rv) {
2354 /* Error checking CRC8 for an AMR 5.15 frame */
2355 return -1;
2356 }
2357
2358 tch_amr_reassemble(tch_data, d, 103);
2359
2360 len = 13;
2361
2362 break;
2363 case 0: /* TCH/AFS4.75 */
2364 osmo_conv_decode_ber(&gsm0503_tch_afs_4_75, cB + 8,
2365 conv, n_errors, n_bits_total);
2366
2367 tch_amr_unmerge(d, p, conv, 95, 39);
2368
2369 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2370 if (rv) {
2371 /* Error checking CRC8 for an AMR 4.75 frame */
2372 return -1;
2373 }
2374
2375 tch_amr_reassemble(tch_data, d, 95);
2376
2377 len = 12;
2378
2379 break;
2380 default:
2381 /* Unknown frame type */
2382 *n_bits_total = 448;
2383 *n_errors = *n_bits_total;
2384 return -1;
2385 }
2386
Philipp Maier898c9c62020-02-06 14:25:01 +01002387out:
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002388 /* Change codec request / indication, if frame is valid */
2389 if (codec_mode_req)
2390 *cmr = id;
2391 else
2392 *ft = id;
2393
2394 return len;
2395}
2396
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002397/*! Perform channel encoding on a TCH/AFS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002398 * \param[out] bursts caller-allocated output buffer for bursts bits
2399 * \param[in] tch_data Codec input data in RTP payload format
2400 * \param[in] len Length of \a tch_data in bytes
2401 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2402 * \param[in] codec Array of codecs (active codec set)
2403 * \param[in] codecs Number of entries in \a codec
2404 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2405 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2406 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002407int gsm0503_tch_afs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002408 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2409 uint8_t cmr)
2410{
2411 ubit_t iB[912], cB[456], h;
2412 ubit_t d[244], p[6], conv[250];
2413 int i;
2414 uint8_t id;
2415
2416 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2417 _xcch_encode_cB(cB, tch_data);
2418
2419 h = 1;
2420
2421 goto facch;
2422 }
2423
2424 h = 0;
2425
2426 if (codec_mode_req) {
2427 if (cmr >= codecs) {
2428 /* FIXME: CMR ID is not in codec list! */
2429 return -1;
2430 }
2431 id = cmr;
2432 } else {
2433 if (ft >= codecs) {
2434 /* FIXME: FT ID is not in codec list! */
2435 return -1;
2436 }
2437 id = ft;
2438 }
2439
2440 switch (codec[ft]) {
2441 case 7: /* TCH/AFS12.2 */
2442 if (len != 31)
2443 goto invalid_length;
2444
2445 tch_amr_disassemble(d, tch_data, 244);
2446
2447 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 81, p);
2448
2449 tch_amr_merge(conv, d, p, 244, 81);
2450
2451 osmo_conv_encode(&gsm0503_tch_afs_12_2, conv, cB + 8);
2452
2453 break;
2454 case 6: /* TCH/AFS10.2 */
2455 if (len != 26)
2456 goto invalid_length;
2457
2458 tch_amr_disassemble(d, tch_data, 204);
2459
2460 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 65, p);
2461
2462 tch_amr_merge(conv, d, p, 204, 65);
2463
2464 osmo_conv_encode(&gsm0503_tch_afs_10_2, conv, cB + 8);
2465
2466 break;
2467 case 5: /* TCH/AFS7.95 */
2468 if (len != 20)
2469 goto invalid_length;
2470
2471 tch_amr_disassemble(d, tch_data, 159);
2472
2473 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 75, p);
2474
2475 tch_amr_merge(conv, d, p, 159, 75);
2476
2477 osmo_conv_encode(&gsm0503_tch_afs_7_95, conv, cB + 8);
2478
2479 break;
2480 case 4: /* TCH/AFS7.4 */
2481 if (len != 19)
2482 goto invalid_length;
2483
2484 tch_amr_disassemble(d, tch_data, 148);
2485
2486 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2487
2488 tch_amr_merge(conv, d, p, 148, 61);
2489
2490 osmo_conv_encode(&gsm0503_tch_afs_7_4, conv, cB + 8);
2491
2492 break;
2493 case 3: /* TCH/AFS6.7 */
2494 if (len != 17)
2495 goto invalid_length;
2496
2497 tch_amr_disassemble(d, tch_data, 134);
2498
2499 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2500
2501 tch_amr_merge(conv, d, p, 134, 55);
2502
2503 osmo_conv_encode(&gsm0503_tch_afs_6_7, conv, cB + 8);
2504
2505 break;
2506 case 2: /* TCH/AFS5.9 */
2507 if (len != 15)
2508 goto invalid_length;
2509
2510 tch_amr_disassemble(d, tch_data, 118);
2511
2512 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2513
2514 tch_amr_merge(conv, d, p, 118, 55);
2515
2516 osmo_conv_encode(&gsm0503_tch_afs_5_9, conv, cB + 8);
2517
2518 break;
2519 case 1: /* TCH/AFS5.15 */
2520 if (len != 13)
2521 goto invalid_length;
2522
2523 tch_amr_disassemble(d, tch_data, 103);
2524
2525 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2526
2527 tch_amr_merge(conv, d, p, 103, 49);
2528
2529 osmo_conv_encode(&gsm0503_tch_afs_5_15, conv, cB + 8);
2530
2531 break;
2532 case 0: /* TCH/AFS4.75 */
2533 if (len != 12)
2534 goto invalid_length;
2535
2536 tch_amr_disassemble(d, tch_data, 95);
2537
2538 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2539
2540 tch_amr_merge(conv, d, p, 95, 39);
2541
2542 osmo_conv_encode(&gsm0503_tch_afs_4_75, conv, cB + 8);
2543
2544 break;
2545 default:
2546 /* FIXME: FT %ft is not supported */
2547 return -1;
2548 }
2549
2550 memcpy(cB, gsm0503_afs_ic_ubit[id], 8);
2551
2552facch:
2553 gsm0503_tch_fr_interleave(cB, iB);
2554
2555 for (i = 0; i < 8; i++) {
2556 gsm0503_tch_burst_map(&iB[i * 114],
2557 &bursts[i * 116], &h, i >> 2);
2558 }
2559
2560 return 0;
2561
2562invalid_length:
2563 /* FIXME: payload length %len does not comply with codec type %ft */
2564 return -1;
2565}
2566
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002567/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002568 * \param[out] tch_data Codec frame in RTP payload format
2569 * \param[in] bursts buffer containing the symbols of 8 bursts
2570 * \param[in] odd Is this an odd (1) or even (0) frame number?
2571 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2572 * \param[in] codec array of active codecs (active codec set)
2573 * \param[in] codecs number of codecs in \a codec
2574 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2575 * \param[out] cmr Output in \a codec_mode_req = 1
2576 * \param[out] n_errors Number of detected bit errors
2577 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02002578 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2579 * codec out of range; negative on error
2580 */
Harald Welteb9946d32017-06-12 09:40:16 +02002581int gsm0503_tch_ahs_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002582 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2583 uint8_t *cmr, int *n_errors, int *n_bits_total)
2584{
Philipp Maier898c9c62020-02-06 14:25:01 +01002585 return gsm0503_tch_ahs_decode_dtx(tch_data, bursts, odd, codec_mode_req,
2586 codec, codecs, ft, cmr, n_errors,
2587 n_bits_total, NULL);
2588}
2589
2590/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
2591 * \param[out] tch_data Codec frame in RTP payload format
2592 * \param[in] bursts buffer containing the symbols of 8 bursts
2593 * \param[in] odd Is this an odd (1) or even (0) frame number?
2594 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2595 * \param[in] codec array of active codecs (active codec set)
2596 * \param[in] codecs number of codecs in \a codec
2597 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2598 * \param[out] cmr Output in \a codec_mode_req = 1
2599 * \param[out] n_errors Number of detected bit errors
2600 * \param[out] n_bits_total Total number of bits
2601 * \param[inout] dtx DTX frame type output, previous DTX frame type input
2602 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2603 * codec out of range; negative on error
2604 */
2605int gsm0503_tch_ahs_decode_dtx(uint8_t *tch_data, const sbit_t *bursts, int odd,
2606 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2607 uint8_t *cmr, int *n_errors, int *n_bits_total, uint8_t *dtx)
2608{
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002609 sbit_t iB[912], cB[456], h;
2610 ubit_t d[244], p[6], conv[135];
2611 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
Philipp Maier898c9c62020-02-06 14:25:01 +01002612 ubit_t cBd[456];
2613 static ubit_t sid_first_dummy[64] = { 0 };
2614 uint8_t dtx_prev;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002615
2616 /* only unmap the stealing bits */
2617 if (!odd) {
2618 for (i = 0; i < 4; i++) {
2619 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
2620 steal -= h;
2621 }
2622 for (i = 2; i < 5; i++) {
2623 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
2624 steal -= h;
2625 }
2626 }
2627
2628 /* if we found a stole FACCH, but only at correct alignment */
2629 if (steal > 0) {
2630 for (i = 0; i < 6; i++) {
2631 gsm0503_tch_burst_unmap(&iB[i * 114],
2632 &bursts[i * 116], NULL, i >> 2);
2633 }
2634
2635 for (i = 2; i < 4; i++) {
2636 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
2637 &bursts[i * 116], NULL, 1);
2638 }
2639
2640 gsm0503_tch_fr_deinterleave(cB, iB);
2641
2642 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2643 if (rv) {
2644 /* Error decoding FACCH frame */
2645 return -1;
2646 }
2647
2648 return GSM_MACBLOCK_LEN;
2649 }
2650
2651 for (i = 0; i < 4; i++) {
2652 gsm0503_tch_burst_unmap(&iB[i * 114],
2653 &bursts[i * 116], NULL, i >> 1);
2654 }
2655
2656 gsm0503_tch_hr_deinterleave(cB, iB);
2657
Philipp Maier898c9c62020-02-06 14:25:01 +01002658 /* Determine the DTX frame type (SID_UPDATE, ONSET etc...) */
2659 if (dtx) {
2660 osmo_sbit2ubit(cBd, cB, 456);
2661 dtx_prev = *dtx;
2662 *dtx = gsm0503_detect_ahs_dtx_frame(n_errors, n_bits_total, cBd);
2663
2664 if (dtx_prev == AHS_SID_UPDATE && *dtx == AMR_OTHER) {
2665 /* NOTE: The AHS_SID_UPDATE frame is splitted into
2666 * two half rate frames. If the id marker frame
2667 * (AHS_SID_UPDATE) is detected the following frame
2668 * contains the actual comfort noised data part of
2669 * (AHS_SID_UPDATE_CN). */
2670 *dtx = AHS_SID_UPDATE_CN;
2671
2672 osmo_conv_decode_ber(&gsm0503_tch_axs_sid_update,
2673 cB + 16, conv, n_errors,
2674 n_bits_total);
2675 rv = osmo_crc16gen_check_bits(&gsm0503_amr_crc14, conv,
2676 35, conv + 35);
2677 if (rv != 0) {
2678 /* Error checking CRC14 for an AMR SID_UPDATE frame */
2679 return -1;
2680 }
2681
2682 tch_amr_sid_update_append(conv, 1,
2683 (codec_mode_req) ? codec[*ft]
2684 : codec[id]);
2685 tch_amr_reassemble(tch_data, conv, 39);
2686 len = 5;
2687 goto out;
2688 } else if (*dtx == AHS_SID_FIRST_P2) {
2689 tch_amr_sid_update_append(sid_first_dummy, 0,
2690 (codec_mode_req) ? codec[*ft]
2691 : codec[id]);
2692 tch_amr_reassemble(tch_data, sid_first_dummy, 39);
2693 len = 5;
2694 goto out;
2695 } else if (*dtx == AHS_SID_UPDATE || *dtx == AHS_ONSET
2696 || *dtx == AHS_SID_FIRST_INH
2697 || *dtx == AHS_SID_UPDATE_INH
2698 || *dtx == AHS_SID_FIRST_P1) {
2699 len = 0;
2700 goto out;
2701 }
2702 }
2703
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002704 for (i = 0; i < 4; i++) {
2705 for (j = 0, k = 0; j < 4; j++)
2706 k += abs(((int)gsm0503_ahs_ic_sbit[i][j]) - ((int)cB[j]));
2707
2708 if (i == 0 || k < best) {
2709 best = k;
2710 id = i;
2711 }
2712 }
2713
2714 /* Check if indicated codec fits into range of codecs */
2715 if (id >= codecs) {
2716 /* Codec mode out of range, return id */
2717 return id;
2718 }
2719
2720 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2721 case 5: /* TCH/AHS7.95 */
2722 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_95, cB + 4,
2723 conv, n_errors, n_bits_total);
2724
2725 tch_amr_unmerge(d, p, conv, 123, 67);
2726
2727 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 67, p);
2728 if (rv) {
2729 /* Error checking CRC8 for an AMR 7.95 frame */
2730 return -1;
2731 }
2732
2733 for (i = 0; i < 36; i++)
2734 d[i + 123] = (cB[i + 192] < 0) ? 1 : 0;
2735
2736 tch_amr_reassemble(tch_data, d, 159);
2737
2738 len = 20;
2739
2740 break;
2741 case 4: /* TCH/AHS7.4 */
2742 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_4, cB + 4,
2743 conv, n_errors, n_bits_total);
2744
2745 tch_amr_unmerge(d, p, conv, 120, 61);
2746
2747 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2748 if (rv) {
2749 /* Error checking CRC8 for an AMR 7.4 frame */
2750 return -1;
2751 }
2752
2753 for (i = 0; i < 28; i++)
2754 d[i + 120] = (cB[i + 200] < 0) ? 1 : 0;
2755
2756 tch_amr_reassemble(tch_data, d, 148);
2757
2758 len = 19;
2759
2760 break;
2761 case 3: /* TCH/AHS6.7 */
2762 osmo_conv_decode_ber(&gsm0503_tch_ahs_6_7, cB + 4,
2763 conv, n_errors, n_bits_total);
2764
2765 tch_amr_unmerge(d, p, conv, 110, 55);
2766
2767 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2768 if (rv) {
2769 /* Error checking CRC8 for an AMR 6.7 frame */
2770 return -1;
2771 }
2772
2773 for (i = 0; i < 24; i++)
2774 d[i + 110] = (cB[i + 204] < 0) ? 1 : 0;
2775
2776 tch_amr_reassemble(tch_data, d, 134);
2777
2778 len = 17;
2779
2780 break;
2781 case 2: /* TCH/AHS5.9 */
2782 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_9, cB + 4,
2783 conv, n_errors, n_bits_total);
2784
2785 tch_amr_unmerge(d, p, conv, 102, 55);
2786
2787 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2788 if (rv) {
2789 /* Error checking CRC8 for an AMR 5.9 frame */
2790 return -1;
2791 }
2792
2793 for (i = 0; i < 16; i++)
2794 d[i + 102] = (cB[i + 212] < 0) ? 1 : 0;
2795
2796 tch_amr_reassemble(tch_data, d, 118);
2797
2798 len = 15;
2799
2800 break;
2801 case 1: /* TCH/AHS5.15 */
2802 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_15, cB + 4,
2803 conv, n_errors, n_bits_total);
2804
2805 tch_amr_unmerge(d, p, conv, 91, 49);
2806
2807 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2808 if (rv) {
2809 /* Error checking CRC8 for an AMR 5.15 frame */
2810 return -1;
2811 }
2812
2813 for (i = 0; i < 12; i++)
2814 d[i + 91] = (cB[i + 216] < 0) ? 1 : 0;
2815
2816 tch_amr_reassemble(tch_data, d, 103);
2817
2818 len = 13;
2819
2820 break;
2821 case 0: /* TCH/AHS4.75 */
2822 osmo_conv_decode_ber(&gsm0503_tch_ahs_4_75, cB + 4,
2823 conv, n_errors, n_bits_total);
2824
2825 tch_amr_unmerge(d, p, conv, 83, 39);
2826
2827 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2828 if (rv) {
2829 /* Error checking CRC8 for an AMR 4.75 frame */
2830 return -1;
2831 }
2832
2833 for (i = 0; i < 12; i++)
2834 d[i + 83] = (cB[i + 216] < 0) ? 1 : 0;
2835
2836 tch_amr_reassemble(tch_data, d, 95);
2837
2838 len = 12;
2839
2840 break;
2841 default:
2842 /* Unknown frame type */
2843 *n_bits_total = 159;
2844 *n_errors = *n_bits_total;
2845 return -1;
2846 }
2847
Philipp Maier898c9c62020-02-06 14:25:01 +01002848out:
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002849 /* Change codec request / indication, if frame is valid */
2850 if (codec_mode_req)
2851 *cmr = id;
2852 else
2853 *ft = id;
2854
2855 return len;
2856}
2857
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002858/*! Perform channel encoding on a TCH/AHS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002859 * \param[out] bursts caller-allocated output buffer for bursts bits
2860 * \param[in] tch_data Codec input data in RTP payload format
2861 * \param[in] len Length of \a tch_data in bytes
2862 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2863 * \param[in] codec Array of codecs (active codec set)
2864 * \param[in] codecs Number of entries in \a codec
2865 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2866 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2867 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002868int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002869 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2870 uint8_t cmr)
2871{
2872 ubit_t iB[912], cB[456], h;
2873 ubit_t d[244], p[6], conv[135];
2874 int i;
2875 uint8_t id;
2876
2877 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2878 _xcch_encode_cB(cB, tch_data);
2879
2880 h = 1;
2881
2882 gsm0503_tch_fr_interleave(cB, iB);
2883
2884 for (i = 0; i < 6; i++)
2885 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116],
2886 &h, i >> 2);
2887 for (i = 2; i < 4; i++)
2888 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2889 &bursts[i * 116], &h, 1);
2890
2891 return 0;
2892 }
2893
2894 h = 0;
2895
2896 if (codec_mode_req) {
2897 if (cmr >= codecs) {
2898 /* FIXME: CMR ID %d not in codec list */
2899 return -1;
2900 }
2901 id = cmr;
2902 } else {
2903 if (ft >= codecs) {
2904 /* FIXME: FT ID %d not in codec list */
2905 return -1;
2906 }
2907 id = ft;
2908 }
2909
2910 switch (codec[ft]) {
2911 case 5: /* TCH/AHS7.95 */
2912 if (len != 20)
2913 goto invalid_length;
2914
2915 tch_amr_disassemble(d, tch_data, 159);
2916
2917 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 67, p);
2918
2919 tch_amr_merge(conv, d, p, 123, 67);
2920
2921 osmo_conv_encode(&gsm0503_tch_ahs_7_95, conv, cB + 4);
2922
2923 memcpy(cB + 192, d + 123, 36);
2924
2925 break;
2926 case 4: /* TCH/AHS7.4 */
2927 if (len != 19)
2928 goto invalid_length;
2929
2930 tch_amr_disassemble(d, tch_data, 148);
2931
2932 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2933
2934 tch_amr_merge(conv, d, p, 120, 61);
2935
2936 osmo_conv_encode(&gsm0503_tch_ahs_7_4, conv, cB + 4);
2937
2938 memcpy(cB + 200, d + 120, 28);
2939
2940 break;
2941 case 3: /* TCH/AHS6.7 */
2942 if (len != 17)
2943 goto invalid_length;
2944
2945 tch_amr_disassemble(d, tch_data, 134);
2946
2947 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2948
2949 tch_amr_merge(conv, d, p, 110, 55);
2950
2951 osmo_conv_encode(&gsm0503_tch_ahs_6_7, conv, cB + 4);
2952
2953 memcpy(cB + 204, d + 110, 24);
2954
2955 break;
2956 case 2: /* TCH/AHS5.9 */
2957 if (len != 15)
2958 goto invalid_length;
2959
2960 tch_amr_disassemble(d, tch_data, 118);
2961
2962 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2963
2964 tch_amr_merge(conv, d, p, 102, 55);
2965
2966 osmo_conv_encode(&gsm0503_tch_ahs_5_9, conv, cB + 4);
2967
2968 memcpy(cB + 212, d + 102, 16);
2969
2970 break;
2971 case 1: /* TCH/AHS5.15 */
2972 if (len != 13)
2973 goto invalid_length;
2974
2975 tch_amr_disassemble(d, tch_data, 103);
2976
2977 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2978
2979 tch_amr_merge(conv, d, p, 91, 49);
2980
2981 osmo_conv_encode(&gsm0503_tch_ahs_5_15, conv, cB + 4);
2982
2983 memcpy(cB + 216, d + 91, 12);
2984
2985 break;
2986 case 0: /* TCH/AHS4.75 */
2987 if (len != 12)
2988 goto invalid_length;
2989
2990 tch_amr_disassemble(d, tch_data, 95);
2991
2992 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2993
2994 tch_amr_merge(conv, d, p, 83, 39);
2995
2996 osmo_conv_encode(&gsm0503_tch_ahs_4_75, conv, cB + 4);
2997
2998 memcpy(cB + 216, d + 83, 12);
2999
3000 break;
3001 default:
3002 /* FIXME: FT %ft is not supported */
3003 return -1;
3004 }
3005
Philipp Maiercfea39b2021-08-31 16:02:31 +02003006 memcpy(cB, gsm0503_ahs_ic_ubit[id], 4);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003007
3008 gsm0503_tch_hr_interleave(cB, iB);
3009
3010 for (i = 0; i < 4; i++)
3011 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116], &h, i >> 1);
3012
3013 return 0;
3014
3015invalid_length:
3016 /* FIXME: payload length %len does not comply with codec type %ft */
3017 return -1;
3018}
3019
3020/*
3021 * GSM RACH transcoding
3022 */
3023
3024/*
3025 * GSM RACH apply BSIC to parity
3026 *
3027 * p(j) = p(j) xor b(j) j = 0, ..., 5
3028 * b(0) = MSB of PLMN colour code
3029 * b(5) = LSB of BS colour code
3030 */
Max32e56412017-10-16 14:58:00 +02003031static inline void rach_apply_bsic(ubit_t *d, uint8_t bsic, uint8_t start)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003032{
3033 int i;
3034
3035 /* Apply it */
3036 for (i = 0; i < 6; i++)
Max32e56412017-10-16 14:58:00 +02003037 d[start + i] ^= ((bsic >> (5 - i)) & 1);
3038}
3039
Harald Welte6950b192018-02-26 11:48:00 +01003040static inline int16_t rach_decode_ber(const sbit_t *burst, uint8_t bsic, bool is_11bit,
3041 int *n_errors, int *n_bits_total)
Max32e56412017-10-16 14:58:00 +02003042{
3043 ubit_t conv[17];
3044 uint8_t ra[2] = { 0 }, nbits = is_11bit ? 11 : 8;
3045 int rv;
3046
Harald Welte6950b192018-02-26 11:48:00 +01003047 osmo_conv_decode_ber(is_11bit ? &gsm0503_rach_ext : &gsm0503_rach, burst, conv,
3048 n_errors, n_bits_total);
Max32e56412017-10-16 14:58:00 +02003049
3050 rach_apply_bsic(conv, bsic, nbits);
3051
3052 rv = osmo_crc8gen_check_bits(&gsm0503_rach_crc6, conv, nbits, conv + nbits);
3053 if (rv)
3054 return -1;
3055
3056 osmo_ubit2pbit_ext(ra, 0, conv, 0, nbits, 1);
3057
Vadim Yanitskiy9e713f32020-03-31 19:40:09 +07003058 return is_11bit ? ((ra[0] << 3) | (ra[1] & 0x07)) : ra[0];
Max32e56412017-10-16 14:58:00 +02003059}
3060
3061/*! Decode the Extended (11-bit) RACH according to 3GPP TS 45.003
3062 * \param[out] ra output buffer for RACH data
3063 * \param[in] burst Input burst data
3064 * \param[in] bsic BSIC used in this cell
3065 * \returns 0 on success; negative on error (e.g. CRC error) */
3066int gsm0503_rach_ext_decode(uint16_t *ra, const sbit_t *burst, uint8_t bsic)
3067{
Harald Welte6950b192018-02-26 11:48:00 +01003068 int16_t r = rach_decode_ber(burst, bsic, true, NULL, NULL);
Max32e56412017-10-16 14:58:00 +02003069
3070 if (r < 0)
3071 return r;
3072
3073 *ra = r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003074
3075 return 0;
3076}
3077
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003078/*! Decode the (8-bit) RACH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003079 * \param[out] ra output buffer for RACH data
3080 * \param[in] burst Input burst data
3081 * \param[in] bsic BSIC used in this cell
3082 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02003083int gsm0503_rach_decode(uint8_t *ra, const sbit_t *burst, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003084{
Harald Welte6950b192018-02-26 11:48:00 +01003085 int16_t r = rach_decode_ber(burst, bsic, false, NULL, NULL);
3086 if (r < 0)
3087 return r;
3088
3089 *ra = r;
3090 return 0;
3091}
3092
3093/*! Decode the Extended (11-bit) RACH according to 3GPP TS 45.003
3094 * \param[out] ra output buffer for RACH data
3095 * \param[in] burst Input burst data
3096 * \param[in] bsic BSIC used in this cell
3097 * \param[out] n_errors Number of detected bit errors
3098 * \param[out] n_bits_total Total number of bits
3099 * \returns 0 on success; negative on error (e.g. CRC error) */
3100int gsm0503_rach_ext_decode_ber(uint16_t *ra, const sbit_t *burst, uint8_t bsic,
3101 int *n_errors, int *n_bits_total)
3102{
3103 int16_t r = rach_decode_ber(burst, bsic, true, n_errors, n_bits_total);
3104 if (r < 0)
3105 return r;
3106
3107 *ra = r;
3108 return 0;
3109}
3110
3111/*! Decode the (8-bit) RACH according to TS 05.03
3112 * \param[out] ra output buffer for RACH data
3113 * \param[in] burst Input burst data
3114 * \param[in] bsic BSIC used in this cell
3115 * \param[out] n_errors Number of detected bit errors
3116 * \param[out] n_bits_total Total number of bits
3117 * \returns 0 on success; negative on error (e.g. CRC error) */
3118int gsm0503_rach_decode_ber(uint8_t *ra, const sbit_t *burst, uint8_t bsic,
3119 int *n_errors, int *n_bits_total)
3120{
3121 int16_t r = rach_decode_ber(burst, bsic, false, n_errors, n_bits_total);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003122
Max32e56412017-10-16 14:58:00 +02003123 if (r < 0)
3124 return r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003125
Max32e56412017-10-16 14:58:00 +02003126 *ra = r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003127
3128 return 0;
3129}
3130
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003131/*! Encode the (8-bit) RACH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003132 * \param[out] burst Caller-allocated output burst buffer
3133 * \param[in] ra Input RACH data
3134 * \param[in] bsic BSIC used in this cell
3135 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02003136int gsm0503_rach_encode(ubit_t *burst, const uint8_t *ra, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003137{
Max32e56412017-10-16 14:58:00 +02003138 return gsm0503_rach_ext_encode(burst, *ra, bsic, false);
3139}
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003140
Max32e56412017-10-16 14:58:00 +02003141/*! Encode the Extended (11-bit) or regular (8-bit) RACH according to 3GPP TS 45.003
3142 * \param[out] burst Caller-allocated output burst buffer
3143 * \param[in] ra11 Input RACH data
3144 * \param[in] bsic BSIC used in this cell
3145 * \param[in] is_11bit whether given RA is 11 bit or not
3146 * \returns 0 on success; negative on error */
3147int gsm0503_rach_ext_encode(ubit_t *burst, uint16_t ra11, uint8_t bsic, bool is_11bit)
3148{
3149 ubit_t conv[17];
3150 uint8_t ra[2] = { 0 }, nbits = 8;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003151
Max32e56412017-10-16 14:58:00 +02003152 if (is_11bit) {
Vadim Yanitskiy9e713f32020-03-31 19:40:09 +07003153 ra[0] = (uint8_t) (ra11 >> 3);
3154 ra[1] = (uint8_t) (ra11 & 0x07);
Max32e56412017-10-16 14:58:00 +02003155 nbits = 11;
3156 } else
3157 ra[0] = (uint8_t)ra11;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003158
Max32e56412017-10-16 14:58:00 +02003159 osmo_pbit2ubit_ext(conv, 0, ra, 0, nbits, 1);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003160
Max32e56412017-10-16 14:58:00 +02003161 osmo_crc8gen_set_bits(&gsm0503_rach_crc6, conv, nbits, conv + nbits);
3162
3163 rach_apply_bsic(conv, bsic, nbits);
3164
3165 osmo_conv_encode(is_11bit ? &gsm0503_rach_ext : &gsm0503_rach, conv, burst);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003166
3167 return 0;
3168}
3169
3170/*
3171 * GSM SCH transcoding
3172 */
Harald Weltec6636782017-06-12 14:59:37 +02003173
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003174/*! Decode the SCH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003175 * \param[out] sb_info output buffer for SCH data
3176 * \param[in] burst Input burst data
3177 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02003178int gsm0503_sch_decode(uint8_t *sb_info, const sbit_t *burst)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003179{
3180 ubit_t conv[35];
3181 int rv;
3182
3183 osmo_conv_decode(&gsm0503_sch, burst, conv);
3184
3185 rv = osmo_crc16gen_check_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
3186 if (rv)
3187 return -1;
3188
3189 osmo_ubit2pbit_ext(sb_info, 0, conv, 0, 25, 1);
3190
3191 return 0;
3192}
3193
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003194/*! Encode the SCH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003195 * \param[out] burst Caller-allocated output burst buffer
3196 * \param[in] sb_info Input SCH data
3197 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02003198int gsm0503_sch_encode(ubit_t *burst, const uint8_t *sb_info)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003199{
3200 ubit_t conv[35];
3201
3202 osmo_pbit2ubit_ext(conv, 0, sb_info, 0, 25, 1);
3203
3204 osmo_crc16gen_set_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
3205
3206 osmo_conv_encode(&gsm0503_sch, conv, burst);
3207
3208 return 0;
3209}
Harald Weltec6636782017-06-12 14:59:37 +02003210
3211/*! @} */