blob: 8480240d9260c3d5011ed77ef6b6428ba42b2767 [file] [log] [blame]
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001/*
2 * (C) 2013 by Andreas Eversberg <jolly@eversberg.eu>
3 * (C) 2015 by Alexander Chemeris <Alexander.Chemeris@fairwaves.co>
4 * (C) 2016 by Tom Tsou <tom.tsou@ettus.com>
Harald Weltec6636782017-06-12 14:59:37 +02005 * (C) 2017 by Harald Welte <laforge@gnumonks.org>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07006 *
7 * All Rights Reserved
8 *
Harald Weltee08da972017-11-13 01:00:26 +09009 * SPDX-License-Identifier: GPL-2.0+
10 *
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070011 * This program is free software; you can redistribute it and/or modify
12 * it under the terms of the GNU General Public License as published by
13 * the Free Software Foundation; either version 2 of the License, or
14 * (at your option) any later version.
15 *
16 * This program is distributed in the hope that it will be useful,
17 * but WITHOUT ANY WARRANTY; without even the implied warranty of
18 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
19 * GNU General Public License for more details.
20 *
21 * You should have received a copy of the GNU General Public License along
22 * with this program; if not, write to the Free Software Foundation, Inc.,
23 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
24 */
25
26#include <stdio.h>
27#include <stdint.h>
28#include <string.h>
29#include <stdlib.h>
Maxc8cf8202017-05-22 16:07:04 +020030#include <errno.h>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070031
32#include <osmocom/core/bits.h>
33#include <osmocom/core/conv.h>
34#include <osmocom/core/utils.h>
35#include <osmocom/core/crcgen.h>
36#include <osmocom/core/endian.h>
37
38#include <osmocom/gprs/protocol/gsm_04_60.h>
39#include <osmocom/gprs/gprs_rlc.h>
40
41#include <osmocom/gsm/protocol/gsm_04_08.h>
42#include <osmocom/gsm/gsm0503.h>
43#include <osmocom/codec/codec.h>
44
45#include <osmocom/coding/gsm0503_interleaving.h>
46#include <osmocom/coding/gsm0503_mapping.h>
47#include <osmocom/coding/gsm0503_tables.h>
48#include <osmocom/coding/gsm0503_coding.h>
49#include <osmocom/coding/gsm0503_parity.h>
50
Harald Weltec6636782017-06-12 14:59:37 +020051/*! \mainpage libosmocoding Documentation
52 *
53 * \section sec_intro Introduction
54 * This library is a collection of definitions, tables and functions
55 * implementing the GSM/GPRS/EGPRS channel coding (and decoding) as
56 * specified in 3GPP TS 05.03 / 45.003.
57 *
Vadim Yanitskiy9a232fd2018-01-19 03:05:32 +060058 * libosmocoding is developed as part of the Osmocom (Open Source Mobile
Harald Weltec6636782017-06-12 14:59:37 +020059 * Communications) project, a community-based, collaborative development
60 * project to create Free and Open Source implementations of mobile
61 * communications systems. For more information about Osmocom, please
62 * see https://osmocom.org/
63 *
64 * \section sec_copyright Copyright and License
65 * Copyright © 2013 by Andreas Eversberg\n
66 * Copyright © 2015 by Alexander Chemeris\n
67 * Copyright © 2016 by Tom Tsou\n
68 * Documentation Copyright © 2017 by Harald Welte\n
69 * All rights reserved. \n\n
70 * The source code of libosmocoding is licensed under the terms of the GNU
71 * General Public License as published by the Free Software Foundation;
72 * either version 2 of the License, or (at your option) any later
73 * version.\n
74 * See <http://www.gnu.org/licenses/> or COPYING included in the source
75 * code package istelf.\n
76 * The information detailed here is provided AS IS with NO WARRANTY OF
77 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
78 * FITNESS FOR A PARTICULAR PURPOSE.
79 * \n\n
80 *
81 * \section sec_tracker Homepage + Issue Tracker
82 * libosmocoding is distributed as part of libosmocore and shares its
83 * project page at http://osmocom.org/projects/libosmocore
84 *
85 * An Issue Tracker can be found at
86 * https://osmocom.org/projects/libosmocore/issues
87 *
88 * \section sec_contact Contact and Support
89 * Community-based support is available at the OpenBSC mailing list
90 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
91 * Commercial support options available upon request from
92 * <http://sysmocom.de/>
93 */
94
95
96/*! \addtogroup coding
97 * @{
98 *
Neels Hofmeyr87e45502017-06-20 00:17:59 +020099 * GSM TS 05.03 coding
Harald Weltec6636782017-06-12 14:59:37 +0200100 *
101 * This module is the "master module" of libosmocoding. It uses the
102 * various other modules (mapping, parity, interleaving) in order to
103 * implement the complete channel coding (and decoding) chain for the
104 * various channel types as defined in TS 05.03 / 45.003.
Neels Hofmeyr17518fe2017-06-20 04:35:06 +0200105 *
106 * \file gsm0503_coding.c */
Harald Weltec6636782017-06-12 14:59:37 +0200107
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700108/*
109 * EGPRS coding limits
110 */
111
112/* Max header size with parity bits */
113#define EGPRS_HDR_UPP_MAX 54
114
115/* Max encoded header size */
116#define EGPRS_HDR_C_MAX 162
117
118/* Max punctured header size */
119#define EGPRS_HDR_HC_MAX 160
120
121/* Max data block size with parity bits */
122#define EGPRS_DATA_U_MAX 612
123
124/* Max encoded data block size */
125#define EGPRS_DATA_C_MAX 1836
126
127/* Max single block punctured data size */
128#define EGPRS_DATA_DC_MAX 1248
129
130/* Dual block punctured data size */
131#define EGPRS_DATA_C1 612
132#define EGPRS_DATA_C2 EGPRS_DATA_C1
133
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200134/*! union across the three different EGPRS Uplink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700135union gprs_rlc_ul_hdr_egprs {
136 struct gprs_rlc_ul_header_egprs_1 type1;
137 struct gprs_rlc_ul_header_egprs_2 type2;
138 struct gprs_rlc_ul_header_egprs_3 type3;
139};
140
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200141/*! union across the three different EGPRS Downlink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700142union gprs_rlc_dl_hdr_egprs {
143 struct gprs_rlc_dl_header_egprs_1 type1;
144 struct gprs_rlc_dl_header_egprs_2 type2;
145 struct gprs_rlc_dl_header_egprs_3 type3;
146};
147
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200148/*! Structure describing a Modulation and Coding Scheme */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700149struct gsm0503_mcs_code {
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200150 /*! Modulation and Coding Scheme (MSC) number */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700151 uint8_t mcs;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200152 /*! Length of Uplink Stealing Flag (USF) in bits */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700153 uint8_t usf_len;
154
155 /* Header coding */
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200156 /*! Length of header (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700157 uint8_t hdr_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200158 /*! Length of header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700159 uint8_t hdr_code_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200160 /*! Length of header code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700161 uint8_t hdr_punc_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200162 /*! header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700163 const struct osmo_conv_code *hdr_conv;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200164 /*! header puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700165 const uint8_t *hdr_punc;
166
167 /* Data coding */
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200168 /*! length of data (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700169 uint16_t data_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200170 /*! length of data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700171 uint16_t data_code_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200172 /*! length of data code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700173 uint16_t data_punc_len;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200174 /*! data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700175 const struct osmo_conv_code *data_conv;
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200176 /*! data puncturing sequences */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700177 const uint8_t *data_punc[3];
178};
179
180/*
181 * EGPRS UL coding parameters
182 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200183const struct gsm0503_mcs_code gsm0503_mcs_ul_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700184 {
185 .mcs = EGPRS_MCS0,
186 },
187 {
188 .mcs = EGPRS_MCS1,
189 .hdr_len = 31,
190 .hdr_code_len = 117,
191 .hdr_punc_len = 80,
192 .hdr_conv = &gsm0503_mcs1_ul_hdr,
193 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
194
195 .data_len = 178,
196 .data_code_len = 588,
197 .data_punc_len = 372,
198 .data_conv = &gsm0503_mcs1,
199 .data_punc = {
200 gsm0503_puncture_mcs1_p1,
201 gsm0503_puncture_mcs1_p2,
202 NULL,
203 },
204 },
205 {
206 .mcs = EGPRS_MCS2,
207 .hdr_len = 31,
208 .hdr_code_len = 117,
209 .hdr_punc_len = 80,
210 .hdr_conv = &gsm0503_mcs1_ul_hdr,
211 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
212
213 .data_len = 226,
214 .data_code_len = 732,
215 .data_punc_len = 372,
216 .data_conv = &gsm0503_mcs2,
217 .data_punc = {
218 gsm0503_puncture_mcs2_p1,
219 gsm0503_puncture_mcs2_p2,
220 NULL,
221 },
222 },
223 {
224 .mcs = EGPRS_MCS3,
225 .hdr_len = 31,
226 .hdr_code_len = 117,
227 .hdr_punc_len = 80,
228 .hdr_conv = &gsm0503_mcs1_ul_hdr,
229 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
230
231 .data_len = 298,
232 .data_code_len = 948,
233 .data_punc_len = 372,
234 .data_conv = &gsm0503_mcs3,
235 .data_punc = {
236 gsm0503_puncture_mcs3_p1,
237 gsm0503_puncture_mcs3_p2,
238 gsm0503_puncture_mcs3_p3,
239 },
240 },
241 {
242 .mcs = EGPRS_MCS4,
243 .hdr_len = 31,
244 .hdr_code_len = 117,
245 .hdr_punc_len = 80,
246 .hdr_conv = &gsm0503_mcs1_ul_hdr,
247 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
248
249 .data_len = 354,
250 .data_code_len = 1116,
251 .data_punc_len = 372,
252 .data_conv = &gsm0503_mcs4,
253 .data_punc = {
254 gsm0503_puncture_mcs4_p1,
255 gsm0503_puncture_mcs4_p2,
256 gsm0503_puncture_mcs4_p3,
257 },
258 },
259 {
260 .mcs = EGPRS_MCS5,
261 .hdr_len = 37,
262 .hdr_code_len = 135,
263 .hdr_punc_len = 136,
264 .hdr_conv = &gsm0503_mcs5_ul_hdr,
265 .hdr_punc = NULL,
266
267 .data_len = 450,
268 .data_code_len = 1404,
269 .data_punc_len = 1248,
270 .data_conv = &gsm0503_mcs5,
271 .data_punc = {
272 gsm0503_puncture_mcs5_p1,
273 gsm0503_puncture_mcs5_p2,
274 NULL,
275 },
276 },
277 {
278 .mcs = EGPRS_MCS6,
279 .hdr_len = 37,
280 .hdr_code_len = 135,
281 .hdr_punc_len = 136,
282 .hdr_conv = &gsm0503_mcs5_ul_hdr,
283 .hdr_punc = NULL,
284
285 .data_len = 594,
286 .data_code_len = 1836,
287 .data_punc_len = 1248,
288 .data_conv = &gsm0503_mcs6,
289 .data_punc = {
290 gsm0503_puncture_mcs6_p1,
291 gsm0503_puncture_mcs6_p2,
292 NULL,
293 },
294 },
295 {
296 .mcs = EGPRS_MCS7,
297 .hdr_len = 46,
298 .hdr_code_len = 162,
299 .hdr_punc_len = 160,
300 .hdr_conv = &gsm0503_mcs7_ul_hdr,
301 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
302
303 .data_len = 900,
304 .data_code_len = 1404,
305 .data_punc_len = 612,
306 .data_conv = &gsm0503_mcs7,
307 .data_punc = {
308 gsm0503_puncture_mcs7_p1,
309 gsm0503_puncture_mcs7_p2,
310 gsm0503_puncture_mcs7_p3,
311 }
312 },
313 {
314 .mcs = EGPRS_MCS8,
315 .hdr_len = 46,
316 .hdr_code_len = 162,
317 .hdr_punc_len = 160,
318 .hdr_conv = &gsm0503_mcs7_ul_hdr,
319 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
320
321 .data_len = 1092,
322 .data_code_len = 1692,
323 .data_punc_len = 612,
324 .data_conv = &gsm0503_mcs8,
325 .data_punc = {
326 gsm0503_puncture_mcs8_p1,
327 gsm0503_puncture_mcs8_p2,
328 gsm0503_puncture_mcs8_p3,
329 }
330 },
331 {
332 .mcs = EGPRS_MCS9,
333 .hdr_len = 46,
334 .hdr_code_len = 162,
335 .hdr_punc_len = 160,
336 .hdr_conv = &gsm0503_mcs7_ul_hdr,
337 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
338
339 .data_len = 1188,
340 .data_code_len = 1836,
341 .data_punc_len = 612,
342 .data_conv = &gsm0503_mcs9,
343 .data_punc = {
344 gsm0503_puncture_mcs9_p1,
345 gsm0503_puncture_mcs9_p2,
346 gsm0503_puncture_mcs9_p3,
347 }
348 },
349};
350
351/*
352 * EGPRS DL coding parameters
353 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200354const struct gsm0503_mcs_code gsm0503_mcs_dl_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700355 {
356 .mcs = EGPRS_MCS0,
357 },
358 {
359 .mcs = EGPRS_MCS1,
360 .usf_len = 3,
361 .hdr_len = 28,
362 .hdr_code_len = 108,
363 .hdr_punc_len = 68,
364 .hdr_conv = &gsm0503_mcs1_dl_hdr,
365 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
366
367 .data_len = 178,
368 .data_code_len = 588,
369 .data_punc_len = 372,
370 .data_conv = &gsm0503_mcs1,
371 .data_punc = {
372 gsm0503_puncture_mcs1_p1,
373 gsm0503_puncture_mcs1_p2,
374 NULL,
375 },
376 },
377 {
378 .mcs = EGPRS_MCS2,
379 .usf_len = 3,
380 .hdr_len = 28,
381 .hdr_code_len = 108,
382 .hdr_punc_len = 68,
383 .hdr_conv = &gsm0503_mcs1_dl_hdr,
384 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
385
386 .data_len = 226,
387 .data_code_len = 732,
388 .data_punc_len = 372,
389 .data_conv = &gsm0503_mcs2,
390 .data_punc = {
391 gsm0503_puncture_mcs2_p1,
392 gsm0503_puncture_mcs2_p2,
393 NULL,
394 },
395 },
396 {
397 .mcs = EGPRS_MCS3,
398 .usf_len = 3,
399 .hdr_len = 28,
400 .hdr_code_len = 108,
401 .hdr_punc_len = 68,
402 .hdr_conv = &gsm0503_mcs1_dl_hdr,
403 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
404
405 .data_len = 298,
406 .data_code_len = 948,
407 .data_punc_len = 372,
408 .data_conv = &gsm0503_mcs3,
409 .data_punc = {
410 gsm0503_puncture_mcs3_p1,
411 gsm0503_puncture_mcs3_p2,
412 gsm0503_puncture_mcs3_p3,
413 },
414 },
415 {
416 .mcs = EGPRS_MCS4,
417 .usf_len = 3,
418 .hdr_len = 28,
419 .hdr_code_len = 108,
420 .hdr_punc_len = 68,
421 .hdr_conv = &gsm0503_mcs1_dl_hdr,
422 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
423
424 .data_len = 354,
425 .data_code_len = 1116,
426 .data_punc_len = 372,
427 .data_conv = &gsm0503_mcs4,
428 .data_punc = {
429 gsm0503_puncture_mcs4_p1,
430 gsm0503_puncture_mcs4_p2,
431 gsm0503_puncture_mcs4_p3,
432 },
433 },
434 {
435 .mcs = EGPRS_MCS5,
436 .usf_len = 3,
437 .hdr_len = 25,
438 .hdr_code_len = 99,
439 .hdr_punc_len = 100,
440 .hdr_conv = &gsm0503_mcs5_dl_hdr,
441 .hdr_punc = NULL,
442
443 .data_len = 450,
444 .data_code_len = 1404,
445 .data_punc_len = 1248,
446 .data_conv = &gsm0503_mcs5,
447 .data_punc = {
448 gsm0503_puncture_mcs5_p1,
449 gsm0503_puncture_mcs5_p2,
450 NULL,
451 },
452 },
453 {
454 .mcs = EGPRS_MCS6,
455 .usf_len = 3,
456 .hdr_len = 25,
457 .hdr_code_len = 99,
458 .hdr_punc_len = 100,
459 .hdr_conv = &gsm0503_mcs5_dl_hdr,
460 .hdr_punc = NULL,
461
462 .data_len = 594,
463 .data_code_len = 1836,
464 .data_punc_len = 1248,
465 .data_conv = &gsm0503_mcs6,
466 .data_punc = {
467 gsm0503_puncture_mcs6_p1,
468 gsm0503_puncture_mcs6_p2,
469 NULL,
470 },
471 },
472 {
473 .mcs = EGPRS_MCS7,
474 .usf_len = 3,
475 .hdr_len = 37,
476 .hdr_code_len = 135,
477 .hdr_punc_len = 124,
478 .hdr_conv = &gsm0503_mcs7_dl_hdr,
479 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
480
481 .data_len = 900,
482 .data_code_len = 1404,
483 .data_punc_len = 612,
484 .data_conv = &gsm0503_mcs7,
485 .data_punc = {
486 gsm0503_puncture_mcs7_p1,
487 gsm0503_puncture_mcs7_p2,
488 gsm0503_puncture_mcs7_p3,
489 }
490 },
491 {
492 .mcs = EGPRS_MCS8,
493 .usf_len = 3,
494 .hdr_len = 37,
495 .hdr_code_len = 135,
496 .hdr_punc_len = 124,
497 .hdr_conv = &gsm0503_mcs7_dl_hdr,
498 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
499
500 .data_len = 1092,
501 .data_code_len = 1692,
502 .data_punc_len = 612,
503 .data_conv = &gsm0503_mcs8,
504 .data_punc = {
505 gsm0503_puncture_mcs8_p1,
506 gsm0503_puncture_mcs8_p2,
507 gsm0503_puncture_mcs8_p3,
508 }
509 },
510 {
511 .mcs = EGPRS_MCS9,
512 .usf_len = 3,
513 .hdr_len = 37,
514 .hdr_code_len = 135,
515 .hdr_punc_len = 124,
516 .hdr_conv = &gsm0503_mcs7_dl_hdr,
517 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
518
519 .data_len = 1188,
520 .data_code_len = 1836,
521 .data_punc_len = 612,
522 .data_conv = &gsm0503_mcs9,
523 .data_punc = {
524 gsm0503_puncture_mcs9_p1,
525 gsm0503_puncture_mcs9_p2,
526 gsm0503_puncture_mcs9_p3,
527 }
528 },
529};
530
Alexander Chemeris147051f2018-07-14 21:02:29 +0200531/*! Convolutional Decode + compute BER for punctured codes
Harald Weltec6636782017-06-12 14:59:37 +0200532 * \param[in] code Description of Convolutional Code
533 * \param[in] input Input soft-bits (-127...127)
534 * \param[out] output bits
535 * \param[out] n_errors Number of bit-errors
536 * \param[out] n_bits_total Number of bits
Alexander Chemeris147051f2018-07-14 21:02:29 +0200537 * \param[in] data_punc Puncturing mask array. Can be NULL.
Harald Weltec6636782017-06-12 14:59:37 +0200538 */
Alexander Chemeris147051f2018-07-14 21:02:29 +0200539static int osmo_conv_decode_ber_punctured(const struct osmo_conv_code *code,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700540 const sbit_t *input, ubit_t *output,
Alexander Chemeris147051f2018-07-14 21:02:29 +0200541 int *n_errors, int *n_bits_total,
542 const uint8_t *data_punc)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700543{
544 int res, i, coded_len;
545 ubit_t recoded[EGPRS_DATA_C_MAX];
546
547 res = osmo_conv_decode(code, input, output);
548
549 if (n_bits_total || n_errors) {
550 coded_len = osmo_conv_encode(code, output, recoded);
551 OSMO_ASSERT(sizeof(recoded) / sizeof(recoded[0]) >= coded_len);
552 }
553
554 /* Count bit errors */
555 if (n_errors) {
556 *n_errors = 0;
557 for (i = 0; i < coded_len; i++) {
Alexander Chemeris147051f2018-07-14 21:02:29 +0200558 if (((!data_punc) || (data_punc && !data_punc[i])) &&
559 !((recoded[i] && input[i] < 0) ||
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700560 (!recoded[i] && input[i] > 0)) )
561 *n_errors += 1;
562 }
563 }
564
565 if (n_bits_total)
566 *n_bits_total = coded_len;
567
568 return res;
569}
570
Alexander Chemeris147051f2018-07-14 21:02:29 +0200571/*! Convolutional Decode + compute BER for non-punctured codes
572 * \param[in] code Description of Convolutional Code
573 * \param[in] input Input soft-bits (-127...127)
574 * \param[out] output bits
575 * \param[out] n_errors Number of bit-errors
576 * \param[out] n_bits_total Number of bits
577 */
578static int osmo_conv_decode_ber(const struct osmo_conv_code *code,
579 const sbit_t *input, ubit_t *output,
580 int *n_errors, int *n_bits_total)
581{
582 return osmo_conv_decode_ber_punctured(code, input, output,
583 n_errors, n_bits_total, NULL);
584}
585
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200586/*! convenience wrapper for decoding coded bits
Harald Weltec6636782017-06-12 14:59:37 +0200587 * \param[out] l2_data caller-allocated buffer for L2 Frame
588 * \param[in] cB 456 coded (soft) bits as per TS 05.03 4.1.3
589 * \param[out] n_errors Number of detected errors
590 * \param[out] n_bits_total Number of total coded bits
591 * \returns 0 on success; -1 on CRC error */
Harald Welteb9946d32017-06-12 09:40:16 +0200592static int _xcch_decode_cB(uint8_t *l2_data, const sbit_t *cB,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700593 int *n_errors, int *n_bits_total)
594{
595 ubit_t conv[224];
596 int rv;
597
598 osmo_conv_decode_ber(&gsm0503_xcch, cB,
599 conv, n_errors, n_bits_total);
600
601 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
602 conv, 184, conv + 184);
603 if (rv)
604 return -1;
605
606 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
607
608 return 0;
609}
610
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200611/*! convenience wrapper for encoding to coded bits
Harald Weltec6636782017-06-12 14:59:37 +0200612 * \param[out] cB caller-allocated buffer for 456 coded bits as per TS 05.03 4.1.3
613 * \param[out] l2_data to-be-encoded L2 Frame
614 * \returns 0 */
Harald Welteb9946d32017-06-12 09:40:16 +0200615static int _xcch_encode_cB(ubit_t *cB, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700616{
617 ubit_t conv[224];
618
619 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
620
621 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
622
623 osmo_conv_encode(&gsm0503_xcch, conv, cB);
624
625 return 0;
626}
627
628/*
629 * GSM xCCH block transcoding
630 */
Harald Weltec6636782017-06-12 14:59:37 +0200631
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200632/*! Decoding of xCCH data from bursts to L2 frame
Harald Weltec6636782017-06-12 14:59:37 +0200633 * \param[out] l2_data caller-allocated output data buffer
634 * \param[in] bursts four GSM bursts in soft-bits
635 * \param[out] n_errors Number of detected errors
636 * \param[out] n_bits_total Number of total coded bits
637 */
Harald Welteb9946d32017-06-12 09:40:16 +0200638int gsm0503_xcch_decode(uint8_t *l2_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700639 int *n_errors, int *n_bits_total)
640{
641 sbit_t iB[456], cB[456];
642 int i;
643
644 for (i = 0; i < 4; i++)
645 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116], NULL, NULL);
646
647 gsm0503_xcch_deinterleave(cB, iB);
648
649 return _xcch_decode_cB(l2_data, cB, n_errors, n_bits_total);
650}
651
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200652/*! Encoding of xCCH data from L2 frame to bursts
Harald Weltec6636782017-06-12 14:59:37 +0200653 * \param[out] bursts caller-allocated burst data (unpacked bits)
654 * \param[in] l2_data L2 input data (MAC block)
655 * \returns 0
656 */
Harald Welteb9946d32017-06-12 09:40:16 +0200657int gsm0503_xcch_encode(ubit_t *bursts, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700658{
659 ubit_t iB[456], cB[456], hl = 1, hn = 1;
660 int i;
661
662 _xcch_encode_cB(cB, l2_data);
663
664 gsm0503_xcch_interleave(cB, iB);
665
666 for (i = 0; i < 4; i++)
667 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116], &hl, &hn);
668
669 return 0;
670}
671
672/*
673 * EGPRS PDTCH UL block decoding
674 */
675
676/*
677 * Type 3 - MCS-1,2,3,4
678 * Unmapping and deinterleaving
679 */
680static int egprs_type3_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
681{
682 int i;
683 sbit_t iB[456], q[8];
684
685 for (i = 0; i < 4; i++) {
686 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
687 q + i * 2, q + i * 2 + 1);
688 }
689
690 gsm0503_mcs1_ul_deinterleave(hc, dc, iB);
691
692 return 0;
693}
694
695/*
696 * Type 2 - MCS-5,6
697 * Unmapping and deinterleaving
698 */
699static int egprs_type2_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
700{
701 int i;
702 sbit_t burst[348];
703 sbit_t hi[EGPRS_HDR_HC_MAX];
704 sbit_t di[EGPRS_DATA_DC_MAX];
705
706 for (i = 0; i < 4; i++) {
707 memcpy(burst, &bursts[i * 348], 348);
708
709 gsm0503_mcs5_burst_swap(burst);
710 gsm0503_mcs5_ul_burst_unmap(di, burst, hi, i);
711 }
712
713 gsm0503_mcs5_ul_deinterleave(hc, dc, hi, di);
714
715 return 0;
716}
717
718/*
719 * Type 1 - MCS-7,8,9
720 * Unmapping and deinterleaving - Note that MCS-7 interleaver is unique
721 */
722static int egprs_type1_unmap(const sbit_t *bursts, sbit_t *hc,
723 sbit_t *c1, sbit_t *c2, int msc)
724{
725 int i;
726 sbit_t burst[348];
727 sbit_t hi[EGPRS_HDR_HC_MAX];
728 sbit_t di[EGPRS_DATA_C1 * 2];
729
730 for (i = 0; i < 4; i++) {
731 memcpy(burst, &bursts[i * 348], 348);
732
733 gsm0503_mcs5_burst_swap(burst);
734 gsm0503_mcs7_ul_burst_unmap(di, burst, hi, i);
735 }
736
737 if (msc == EGPRS_MCS7)
738 gsm0503_mcs7_ul_deinterleave(hc, c1, c2, hi, di);
739 else
740 gsm0503_mcs8_ul_deinterleave(hc, c1, c2, hi, di);
741
742 return 0;
743}
744
745/*
746 * Decode EGPRS UL header section
747 *
748 * 1. Depuncture
749 * 2. Convolutional decoding
750 * 3. CRC check
751 */
752static int _egprs_decode_hdr(const sbit_t *hc, int mcs,
753 union gprs_rlc_ul_hdr_egprs *hdr)
754{
755 sbit_t C[EGPRS_HDR_C_MAX];
756 ubit_t upp[EGPRS_HDR_UPP_MAX];
757 int i, j, rc;
Harald Welte2f984ea2017-06-12 15:05:21 +0200758 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700759
760 code = &gsm0503_mcs_ul_codes[mcs];
761
762 /* Skip depuncturing on MCS-5,6 header */
763 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
764 memcpy(C, hc, code->hdr_code_len);
765 goto hdr_conv_decode;
766 }
767
768 if (!code->hdr_punc) {
769 /* Invalid MCS-X header puncture matrix */
770 return -1;
771 }
772
773 i = code->hdr_code_len - 1;
774 j = code->hdr_punc_len - 1;
775
776 for (; i >= 0; i--) {
777 if (!code->hdr_punc[i])
778 C[i] = hc[j--];
779 else
780 C[i] = 0;
781 }
782
783hdr_conv_decode:
784 osmo_conv_decode_ber(code->hdr_conv, C, upp, NULL, NULL);
785 rc = osmo_crc8gen_check_bits(&gsm0503_mcs_crc8_hdr, upp,
786 code->hdr_len, upp + code->hdr_len);
787 if (rc)
788 return -1;
789
790 osmo_ubit2pbit_ext((pbit_t *) hdr, 0, upp, 0, code->hdr_len, 1);
791
792 return 0;
793}
794
795/*
796 * Blind MCS header decoding based on burst length and CRC validation.
797 * Ignore 'q' value coding identification. This approach provides
798 * the strongest chance of header recovery.
799 */
800static int egprs_decode_hdr(union gprs_rlc_ul_hdr_egprs *hdr,
801 const sbit_t *bursts, uint16_t nbits)
802{
803 int rc;
804 sbit_t hc[EGPRS_HDR_HC_MAX];
805
806 if (nbits == GSM0503_GPRS_BURSTS_NBITS) {
807 /* MCS-1,2,3,4 */
808 egprs_type3_unmap(bursts, hc, NULL);
809 rc = _egprs_decode_hdr(hc, EGPRS_MCS1, hdr);
810 if (!rc)
811 return EGPRS_HDR_TYPE3;
812 } else if (nbits == GSM0503_EGPRS_BURSTS_NBITS) {
813 /* MCS-5,6 */
814 egprs_type2_unmap(bursts, hc, NULL);
815 rc = _egprs_decode_hdr(hc, EGPRS_MCS5, hdr);
816 if (!rc)
817 return EGPRS_HDR_TYPE2;
818
819 /* MCS-7,8,9 */
820 egprs_type1_unmap(bursts, hc, NULL, NULL, EGPRS_MCS7);
821 rc = _egprs_decode_hdr(hc, EGPRS_MCS7, hdr);
822 if (!rc)
823 return EGPRS_HDR_TYPE1;
824 }
825
826 return -1;
827}
828
829/*
830 * Parse EGPRS UL header for coding and puncturing scheme (CPS)
831 *
832 * Type 1 - MCS-7,8,9
833 * Type 2 - MCS-5,6
834 * Type 3 - MCS-1,2,3,4
835 */
836static int egprs_parse_ul_cps(struct egprs_cps *cps,
837 union gprs_rlc_ul_hdr_egprs *hdr, int type)
838{
839 uint8_t bits;
840
841 switch (type) {
842 case EGPRS_HDR_TYPE1:
843 bits = hdr->type1.cps;
844 break;
845 case EGPRS_HDR_TYPE2:
846 bits = (hdr->type2.cps_lo << 2) | hdr->type2.cps_hi;
847 break;
848 case EGPRS_HDR_TYPE3:
849 bits = (hdr->type3.cps_lo << 2) | hdr->type3.cps_hi;
850 break;
851 default:
852 return -1;
853 }
854
855 return egprs_get_cps(cps, type, bits);
856}
857
858/*
859 * Decode EGPRS UL data section
860 *
861 * 1. Depuncture
862 * 2. Convolutional decoding
863 * 3. CRC check
864 * 4. Block combining (MCS-7,8,9 only)
865 */
Harald Welteb9946d32017-06-12 09:40:16 +0200866static int egprs_decode_data(uint8_t *l2_data, const sbit_t *c,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700867 int mcs, int p, int blk, int *n_errors, int *n_bits_total)
868{
869 ubit_t u[EGPRS_DATA_U_MAX];
870 sbit_t C[EGPRS_DATA_C_MAX];
871
872 int i, j, rc, data_len;
Harald Welte2f984ea2017-06-12 15:05:21 +0200873 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700874
875 if (blk && mcs < EGPRS_MCS7) {
876 /* Invalid MCS-X block state */
877 return -1;
878 }
879
880 code = &gsm0503_mcs_ul_codes[mcs];
881 if (!code->data_punc[p]) {
882 /* Invalid MCS-X data puncture matrix */
883 return -1;
884 }
885
886 /*
887 * MCS-1,6 - single block processing
888 * MCS-7,9 - dual block processing
889 */
890 if (mcs >= EGPRS_MCS7)
891 data_len = code->data_len / 2;
892 else
893 data_len = code->data_len;
894
895 i = code->data_code_len - 1;
896 j = code->data_punc_len - 1;
897
898 for (; i >= 0; i--) {
899 if (!code->data_punc[p][i])
900 C[i] = c[j--];
901 else
902 C[i] = 0;
903 }
904
Alexander Chemeris147051f2018-07-14 21:02:29 +0200905 osmo_conv_decode_ber_punctured(code->data_conv, C, u,
906 n_errors, n_bits_total, code->data_punc[p]);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700907 rc = osmo_crc16gen_check_bits(&gsm0503_mcs_crc12, u,
908 data_len, u + data_len);
909 if (rc)
910 return -1;
911
912 /* Offsets output pointer on the second block of Type 1 MCS */
913 osmo_ubit2pbit_ext(l2_data, code->hdr_len + blk * data_len,
914 u, 0, data_len, 1);
915
916 /* Return the number of bytes required for the bit message */
Maxdd75bac2017-06-13 15:07:01 +0200917 return OSMO_BYTES_FOR_BITS(code->hdr_len + code->data_len);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700918}
919
Neels Hofmeyr87e45502017-06-20 00:17:59 +0200920/*! Decode EGPRS UL message
Harald Weltec6636782017-06-12 14:59:37 +0200921 * 1. Header section decoding
922 * 2. Extract CPS settings
923 * 3. Burst unmapping and deinterleaving
924 * 4. Data section decoding
925 * \param[out] l2_data caller-allocated buffer for L2 Frame
926 * \param[in] bursts burst input data as soft unpacked bits
927 * \param[in] nbits number of bits in \a bursts
928 * \param usf_p unused argument ?!?
929 * \param[out] n_errors number of detected bit-errors
Alexander Chemerised7d2dd2018-07-14 21:06:27 +0200930 * \param[out] n_bits_total total number of decoded bits
Harald Weltec6636782017-06-12 14:59:37 +0200931 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +0200932int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t nbits,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700933 uint8_t *usf_p, int *n_errors, int *n_bits_total)
934{
935 sbit_t dc[EGPRS_DATA_DC_MAX];
936 sbit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
937 int type, rc;
938 struct egprs_cps cps;
939 union gprs_rlc_ul_hdr_egprs *hdr;
940
Alexander Chemeris50f7d742018-07-14 21:07:27 +0200941 if (n_errors)
942 *n_errors = 0;
943 if (n_bits_total)
944 *n_bits_total = 0;
945
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700946 if ((nbits != GSM0503_GPRS_BURSTS_NBITS) &&
947 (nbits != GSM0503_EGPRS_BURSTS_NBITS)) {
948 /* Invalid EGPRS bit length */
Maxc8cf8202017-05-22 16:07:04 +0200949 return -EOVERFLOW;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700950 }
951
952 hdr = (union gprs_rlc_ul_hdr_egprs *) l2_data;
953 type = egprs_decode_hdr(hdr, bursts, nbits);
954 if (egprs_parse_ul_cps(&cps, hdr, type) < 0)
Maxc8cf8202017-05-22 16:07:04 +0200955 return -EIO;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700956
957 switch (cps.mcs) {
Maxc8cf8202017-05-22 16:07:04 +0200958 case EGPRS_MCS0:
959 return -ENOTSUP;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700960 case EGPRS_MCS1:
961 case EGPRS_MCS2:
962 case EGPRS_MCS3:
963 case EGPRS_MCS4:
964 egprs_type3_unmap(bursts, NULL, dc);
965 break;
966 case EGPRS_MCS5:
967 case EGPRS_MCS6:
968 egprs_type2_unmap(bursts, NULL, dc);
969 break;
970 case EGPRS_MCS7:
971 case EGPRS_MCS8:
972 case EGPRS_MCS9:
973 egprs_type1_unmap(bursts, NULL, c1, c2, cps.mcs);
974 break;
975 default:
976 /* Invalid MCS-X */
Maxc8cf8202017-05-22 16:07:04 +0200977 return -EINVAL;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700978 }
979
980 /* Decode MCS-X block, where X = cps.mcs */
981 if (cps.mcs < EGPRS_MCS7) {
982 rc = egprs_decode_data(l2_data, dc, cps.mcs, cps.p[0],
983 0, n_errors, n_bits_total);
984 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200985 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700986 } else {
Alexander Chemeris94443262018-07-14 21:09:54 +0200987 /* Bit counters for the second block */
988 int n_errors2, n_bits_total2;
989
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700990 /* MCS-7,8,9 block 1 */
991 rc = egprs_decode_data(l2_data, c1, cps.mcs, cps.p[0],
992 0, n_errors, n_bits_total);
993 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200994 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700995
996 /* MCS-7,8,9 block 2 */
997 rc = egprs_decode_data(l2_data, c2, cps.mcs, cps.p[1],
Alexander Chemeris94443262018-07-14 21:09:54 +0200998 1, &n_errors2, &n_bits_total2);
999 if (n_errors)
1000 *n_errors += n_errors2;
1001 if (n_bits_total)
1002 *n_bits_total += n_bits_total2;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001003 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +02001004 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001005 }
1006
1007 return rc;
1008}
1009
1010/*
1011 * GSM PDTCH block transcoding
1012 */
1013
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001014/*! Decode GPRS PDTCH
Harald Weltec6636782017-06-12 14:59:37 +02001015 * \param[out] l2_data caller-allocated buffer for L2 Frame
1016 * \param[in] bursts burst input data as soft unpacked bits
1017 * \param[out] usf_p uplink stealing flag
1018 * \param[out] n_errors number of detected bit-errors
1019 * \param[out] n_bits_total total number of dcoded bits
1020 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001021int gsm0503_pdtch_decode(uint8_t *l2_data, const sbit_t *bursts, uint8_t *usf_p,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001022 int *n_errors, int *n_bits_total)
1023{
1024 sbit_t iB[456], cB[676], hl_hn[8];
1025 ubit_t conv[456];
1026 int i, j, k, rv, best = 0, cs = 0, usf = 0; /* make GCC happy */
1027
1028 for (i = 0; i < 4; i++)
1029 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
1030 hl_hn + i * 2, hl_hn + i * 2 + 1);
1031
1032 for (i = 0; i < 4; i++) {
1033 for (j = 0, k = 0; j < 8; j++)
1034 k += abs(((int)gsm0503_pdtch_hl_hn_sbit[i][j]) - ((int)hl_hn[j]));
1035
1036 if (i == 0 || k < best) {
1037 best = k;
1038 cs = i + 1;
1039 }
1040 }
1041
1042 gsm0503_xcch_deinterleave(cB, iB);
1043
1044 switch (cs) {
1045 case 1:
1046 osmo_conv_decode_ber(&gsm0503_xcch, cB,
1047 conv, n_errors, n_bits_total);
1048
1049 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
1050 conv, 184, conv + 184);
1051 if (rv)
1052 return -1;
1053
1054 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
1055
1056 return 23;
1057 case 2:
1058 for (i = 587, j = 455; i >= 0; i--) {
1059 if (!gsm0503_puncture_cs2[i])
1060 cB[i] = cB[j--];
1061 else
1062 cB[i] = 0;
1063 }
1064
1065 osmo_conv_decode_ber(&gsm0503_cs2_np, cB,
1066 conv, n_errors, n_bits_total);
1067
1068 for (i = 0; i < 8; i++) {
1069 for (j = 0, k = 0; j < 6; j++)
1070 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1071
1072 if (i == 0 || k < best) {
1073 best = k;
1074 usf = i;
1075 }
1076 }
1077
1078 conv[3] = usf & 1;
1079 conv[4] = (usf >> 1) & 1;
1080 conv[5] = (usf >> 2) & 1;
1081 if (usf_p)
1082 *usf_p = usf;
1083
1084 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1085 conv + 3, 271, conv + 3 + 271);
1086 if (rv)
1087 return -1;
1088
1089 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 271, 1);
1090
1091 return 34;
1092 case 3:
1093 for (i = 675, j = 455; i >= 0; i--) {
1094 if (!gsm0503_puncture_cs3[i])
1095 cB[i] = cB[j--];
1096 else
1097 cB[i] = 0;
1098 }
1099
1100 osmo_conv_decode_ber(&gsm0503_cs3_np, cB,
1101 conv, n_errors, n_bits_total);
1102
1103 for (i = 0; i < 8; i++) {
1104 for (j = 0, k = 0; j < 6; j++)
1105 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1106
1107 if (i == 0 || k < best) {
1108 best = k;
1109 usf = i;
1110 }
1111 }
1112
1113 conv[3] = usf & 1;
1114 conv[4] = (usf >> 1) & 1;
1115 conv[5] = (usf >> 2) & 1;
1116 if (usf_p)
1117 *usf_p = usf;
1118
1119 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1120 conv + 3, 315, conv + 3 + 315);
1121 if (rv)
1122 return -1;
1123
1124 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 315, 1);
1125
1126 return 40;
1127 case 4:
1128 for (i = 12; i < 456; i++)
1129 conv[i] = (cB[i] < 0) ? 1 : 0;
1130
1131 for (i = 0; i < 8; i++) {
1132 for (j = 0, k = 0; j < 12; j++)
1133 k += abs(((int)gsm0503_usf2twelve_sbit[i][j]) - ((int)cB[j]));
1134
1135 if (i == 0 || k < best) {
1136 best = k;
1137 usf = i;
1138 }
1139 }
1140
1141 conv[9] = usf & 1;
1142 conv[10] = (usf >> 1) & 1;
1143 conv[11] = (usf >> 2) & 1;
1144 if (usf_p)
1145 *usf_p = usf;
1146
1147 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1148 conv + 9, 431, conv + 9 + 431);
1149 if (rv) {
1150 *n_bits_total = 456 - 12;
1151 *n_errors = *n_bits_total;
1152 return -1;
1153 }
1154
1155 *n_bits_total = 456 - 12;
1156 *n_errors = 0;
1157
1158 osmo_ubit2pbit_ext(l2_data, 0, conv, 9, 431, 1);
1159
1160 return 54;
1161 default:
1162 *n_bits_total = 0;
1163 *n_errors = 0;
1164 break;
1165 }
1166
1167 return -1;
1168}
1169
1170/*
1171 * EGPRS PDTCH UL block encoding
1172 */
Harald Welteb9946d32017-06-12 09:40:16 +02001173static int egprs_type3_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001174{
1175 int i;
1176 ubit_t iB[456];
1177 const ubit_t *hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1178
1179 gsm0503_mcs1_dl_interleave(gsm0503_usf2six[usf], hc, dc, iB);
1180
1181 for (i = 0; i < 4; i++) {
1182 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1183 hl_hn + i * 2, hl_hn + i * 2 + 1);
1184 }
1185
1186 return 0;
1187}
1188
Harald Welteb9946d32017-06-12 09:40:16 +02001189static int egprs_type2_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001190{
1191 int i;
1192 const ubit_t *up;
1193 ubit_t hi[EGPRS_HDR_HC_MAX];
1194 ubit_t di[EGPRS_DATA_DC_MAX];
1195
1196 gsm0503_mcs5_dl_interleave(hc, dc, hi, di);
1197 up = gsm0503_mcs5_usf_precode_table[usf];
1198
1199 for (i = 0; i < 4; i++) {
1200 gsm0503_mcs5_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1201 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1202 }
1203
1204 return 0;
1205}
1206
Harald Welteb9946d32017-06-12 09:40:16 +02001207static int egprs_type1_map(ubit_t *bursts, const ubit_t *hc,
1208 const ubit_t *c1, const ubit_t *c2, int usf, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001209{
1210 int i;
1211 const ubit_t *up;
1212 ubit_t hi[EGPRS_HDR_HC_MAX];
1213 ubit_t di[EGPRS_DATA_C1 * 2];
1214
1215 if (mcs == EGPRS_MCS7)
1216 gsm0503_mcs7_dl_interleave(hc, c1, c2, hi, di);
1217 else
1218 gsm0503_mcs8_dl_interleave(hc, c1, c2, hi, di);
1219
1220 up = gsm0503_mcs5_usf_precode_table[usf];
1221
1222 for (i = 0; i < 4; i++) {
1223 gsm0503_mcs7_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1224 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1225 }
1226
1227 return 0;
1228}
1229
Harald Welteb9946d32017-06-12 09:40:16 +02001230static int egprs_encode_hdr(ubit_t *hc, const uint8_t *l2_data, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001231{
1232 int i, j;
1233 ubit_t upp[EGPRS_HDR_UPP_MAX], C[EGPRS_HDR_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001234 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001235
1236 code = &gsm0503_mcs_dl_codes[mcs];
1237
1238 osmo_pbit2ubit_ext(upp, 0, l2_data, code->usf_len, code->hdr_len, 1);
1239 osmo_crc8gen_set_bits(&gsm0503_mcs_crc8_hdr, upp,
1240 code->hdr_len, upp + code->hdr_len);
1241
1242 osmo_conv_encode(code->hdr_conv, upp, C);
1243
1244 /* MCS-5,6 header direct puncture instead of table */
1245 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
1246 memcpy(hc, C, code->hdr_code_len);
1247 hc[99] = hc[98];
1248 return 0;
1249 }
1250
1251 if (!code->hdr_punc) {
1252 /* Invalid MCS-X header puncture matrix */
1253 return -1;
1254 }
1255
1256 for (i = 0, j = 0; i < code->hdr_code_len; i++) {
1257 if (!code->hdr_punc[i])
1258 hc[j++] = C[i];
1259 }
1260
1261 return 0;
1262}
1263
Harald Welteb9946d32017-06-12 09:40:16 +02001264static int egprs_encode_data(ubit_t *c, const uint8_t *l2_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001265 int mcs, int p, int blk)
1266{
1267 int i, j, data_len;
1268 ubit_t u[EGPRS_DATA_U_MAX], C[EGPRS_DATA_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001269 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001270
1271 code = &gsm0503_mcs_dl_codes[mcs];
1272
1273 /*
1274 * Dual block - MCS-7,8,9
1275 * Single block - MCS-1,2,3,4,5,6
1276 */
1277 if (mcs >= EGPRS_MCS7)
1278 data_len = code->data_len / 2;
1279 else
1280 data_len = code->data_len;
1281
1282 osmo_pbit2ubit_ext(u, 0, l2_data,
1283 code->usf_len + code->hdr_len + blk * data_len, data_len, 1);
1284
1285 osmo_crc16gen_set_bits(&gsm0503_mcs_crc12, u, data_len, u + data_len);
1286
1287 osmo_conv_encode(code->data_conv, u, C);
1288
1289 if (!code->data_punc[p]) {
1290 /* Invalid MCS-X data puncture matrix */
1291 return -1;
1292 }
1293
1294 for (i = 0, j = 0; i < code->data_code_len; i++) {
1295 if (!code->data_punc[p][i])
1296 c[j++] = C[i];
1297 }
1298
1299 return 0;
1300}
1301
1302/*
1303 * Parse EGPRS DL header for coding and puncturing scheme (CPS)
1304 *
1305 * Type 1 - MCS-7,8,9
1306 * Type 2 - MCS-5,6
1307 * Type 3 - MCS-1,2,3,4
1308 */
1309static int egprs_parse_dl_cps(struct egprs_cps *cps,
Harald Welteb9946d32017-06-12 09:40:16 +02001310 const union gprs_rlc_dl_hdr_egprs *hdr, int type)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001311{
1312 uint8_t bits;
1313
1314 switch (type) {
1315 case EGPRS_HDR_TYPE1:
1316 bits = hdr->type1.cps;
1317 break;
1318 case EGPRS_HDR_TYPE2:
1319 bits = hdr->type2.cps;
1320 break;
1321 case EGPRS_HDR_TYPE3:
1322 bits = hdr->type3.cps;
1323 break;
1324 default:
1325 return -1;
1326 }
1327
1328 return egprs_get_cps(cps, type, bits);
1329}
1330
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001331/*! EGPRS DL message encoding
Harald Weltec6636782017-06-12 14:59:37 +02001332 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1333 * \param[in] l2_data L2 (MAC) block to be encoded
1334 * \param[in] l2_len length of l2_data in bytes, used to determine MCS
Vadim Yanitskiy8055cdd2020-03-30 18:16:38 +07001335 * \returns number of bits encoded; negative on error */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001336int gsm0503_pdtch_egprs_encode(ubit_t *bursts,
Harald Welteb9946d32017-06-12 09:40:16 +02001337 const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001338{
1339 ubit_t hc[EGPRS_DATA_C_MAX], dc[EGPRS_DATA_DC_MAX];
1340 ubit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
1341 uint8_t mcs;
1342 struct egprs_cps cps;
1343 union gprs_rlc_dl_hdr_egprs *hdr;
1344
1345 switch (l2_len) {
1346 case 27:
1347 mcs = EGPRS_MCS1;
1348 break;
1349 case 33:
1350 mcs = EGPRS_MCS2;
1351 break;
1352 case 42:
1353 mcs = EGPRS_MCS3;
1354 break;
1355 case 49:
1356 mcs = EGPRS_MCS4;
1357 break;
1358 case 60:
1359 mcs = EGPRS_MCS5;
1360 break;
1361 case 78:
1362 mcs = EGPRS_MCS6;
1363 break;
1364 case 118:
1365 mcs = EGPRS_MCS7;
1366 break;
1367 case 142:
1368 mcs = EGPRS_MCS8;
1369 break;
1370 case 154:
1371 mcs = EGPRS_MCS9;
1372 break;
1373 default:
1374 return -1;
1375 }
1376
1377 /* Read header for USF and puncturing matrix selection. */
1378 hdr = (union gprs_rlc_dl_hdr_egprs *) l2_data;
1379
1380 switch (mcs) {
1381 case EGPRS_MCS1:
1382 case EGPRS_MCS2:
1383 case EGPRS_MCS3:
1384 case EGPRS_MCS4:
1385 /* Check for valid CPS and matching MCS to message size */
1386 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE3) < 0) ||
1387 (cps.mcs != mcs))
1388 goto bad_header;
1389
1390 egprs_encode_hdr(hc, l2_data, mcs);
1391 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1392 egprs_type3_map(bursts, hc, dc, hdr->type3.usf);
1393 break;
1394 case EGPRS_MCS5:
1395 case EGPRS_MCS6:
1396 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE2) < 0) ||
1397 (cps.mcs != mcs))
1398 goto bad_header;
1399
1400 egprs_encode_hdr(hc, l2_data, mcs);
1401 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1402 egprs_type2_map(bursts, hc, dc, hdr->type2.usf);
1403 break;
1404 case EGPRS_MCS7:
1405 case EGPRS_MCS8:
1406 case EGPRS_MCS9:
1407 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE1) < 0) ||
1408 (cps.mcs != mcs))
1409 goto bad_header;
1410
1411 egprs_encode_hdr(hc, l2_data, mcs);
1412 egprs_encode_data(c1, l2_data, mcs, cps.p[0], 0);
1413 egprs_encode_data(c2, l2_data, mcs, cps.p[1], 1);
1414 egprs_type1_map(bursts, hc, c1, c2, hdr->type1.usf, mcs);
1415 break;
1416 }
1417
1418 return mcs >= EGPRS_MCS5 ?
1419 GSM0503_EGPRS_BURSTS_NBITS : GSM0503_GPRS_BURSTS_NBITS;
1420
1421bad_header:
1422 /* Invalid EGPRS MCS-X header */
1423 return -1;
1424}
1425
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001426/*! GPRS DL message encoding
Harald Weltec6636782017-06-12 14:59:37 +02001427 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1428 * \param[in] l2_data L2 (MAC) block to be encoded
1429 * \param[in] l2_len length of l2_data in bytes, used to determine CS
Vadim Yanitskiy8055cdd2020-03-30 18:16:38 +07001430 * \returns number of bits encoded; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001431int gsm0503_pdtch_encode(ubit_t *bursts, const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001432{
1433 ubit_t iB[456], cB[676];
1434 const ubit_t *hl_hn;
1435 ubit_t conv[334];
1436 int i, j, usf;
1437
1438 switch (l2_len) {
1439 case 23:
1440 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
1441
1442 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
1443
1444 osmo_conv_encode(&gsm0503_xcch, conv, cB);
1445
1446 hl_hn = gsm0503_pdtch_hl_hn_ubit[0];
1447
1448 break;
1449 case 34:
1450 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 271, 1);
1451 usf = l2_data[0] & 0x7;
1452
1453 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1454 271, conv + 3 + 271);
1455
1456 memcpy(conv, gsm0503_usf2six[usf], 6);
1457
1458 osmo_conv_encode(&gsm0503_cs2_np, conv, cB);
1459
1460 for (i = 0, j = 0; i < 588; i++)
1461 if (!gsm0503_puncture_cs2[i])
1462 cB[j++] = cB[i];
1463
1464 hl_hn = gsm0503_pdtch_hl_hn_ubit[1];
1465
1466 break;
1467 case 40:
1468 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 315, 1);
1469 usf = l2_data[0] & 0x7;
1470
1471 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1472 315, conv + 3 + 315);
1473
1474 memcpy(conv, gsm0503_usf2six[usf], 6);
1475
1476 osmo_conv_encode(&gsm0503_cs3_np, conv, cB);
1477
1478 for (i = 0, j = 0; i < 676; i++)
1479 if (!gsm0503_puncture_cs3[i])
1480 cB[j++] = cB[i];
1481
1482 hl_hn = gsm0503_pdtch_hl_hn_ubit[2];
1483
1484 break;
1485 case 54:
1486 osmo_pbit2ubit_ext(cB, 9, l2_data, 0, 431, 1);
1487 usf = l2_data[0] & 0x7;
1488
1489 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, cB + 9,
1490 431, cB + 9 + 431);
1491
1492 memcpy(cB, gsm0503_usf2twelve_ubit[usf], 12);
1493
1494 hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1495
1496 break;
1497 default:
1498 return -1;
1499 }
1500
1501 gsm0503_xcch_interleave(cB, iB);
1502
1503 for (i = 0; i < 4; i++) {
1504 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1505 hl_hn + i * 2, hl_hn + i * 2 + 1);
1506 }
1507
1508 return GSM0503_GPRS_BURSTS_NBITS;
1509}
1510
1511/*
1512 * GSM TCH/F FR/EFR transcoding
1513 */
1514
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001515/*! assemble a FR codec frame in format as used inside RTP
Harald Weltec6636782017-06-12 14:59:37 +02001516 * \param[out] tch_data Codec frame in RTP format
1517 * \param[in] b_bits Codec frame in 'native' format
1518 * \param[in] net_order FIXME */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001519static void tch_fr_reassemble(uint8_t *tch_data,
Harald Welteb9946d32017-06-12 09:40:16 +02001520 const ubit_t *b_bits, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001521{
1522 int i, j, k, l, o;
1523
1524 tch_data[0] = 0xd << 4;
1525 memset(tch_data + 1, 0, 32);
1526
1527 if (net_order) {
1528 for (i = 0, j = 4; i < 260; i++, j++)
1529 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1530
1531 return;
1532 }
1533
1534 /* reassemble d-bits */
1535 i = 0; /* counts bits */
1536 j = 4; /* counts output bits */
1537 k = gsm0503_gsm_fr_map[0]-1; /* current number bit in element */
1538 l = 0; /* counts element bits */
1539 o = 0; /* offset input bits */
1540 while (i < 260) {
1541 tch_data[j >> 3] |= (b_bits[k + o] << (7 - (j & 7)));
1542 if (--k < 0) {
1543 o += gsm0503_gsm_fr_map[l];
1544 k = gsm0503_gsm_fr_map[++l]-1;
1545 }
1546 i++;
1547 j++;
1548 }
1549}
1550
1551static void tch_fr_disassemble(ubit_t *b_bits,
Harald Welteb9946d32017-06-12 09:40:16 +02001552 const uint8_t *tch_data, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001553{
1554 int i, j, k, l, o;
1555
1556 if (net_order) {
1557 for (i = 0, j = 4; i < 260; i++, j++)
1558 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1559
1560 return;
1561 }
1562
1563 i = 0; /* counts bits */
1564 j = 4; /* counts input bits */
1565 k = gsm0503_gsm_fr_map[0] - 1; /* current number bit in element */
1566 l = 0; /* counts element bits */
1567 o = 0; /* offset output bits */
1568 while (i < 260) {
1569 b_bits[k + o] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1570 if (--k < 0) {
1571 o += gsm0503_gsm_fr_map[l];
1572 k = gsm0503_gsm_fr_map[++l] - 1;
1573 }
1574 i++;
1575 j++;
1576 }
1577}
1578
Harald Weltec6636782017-06-12 14:59:37 +02001579/* assemble a HR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001580static void tch_hr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001581{
1582 int i, j;
1583
1584 tch_data[0] = 0x00; /* F = 0, FT = 000 */
1585 memset(tch_data + 1, 0, 14);
1586
1587 for (i = 0, j = 8; i < 112; i++, j++)
1588 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1589}
1590
Harald Welteb9946d32017-06-12 09:40:16 +02001591static void tch_hr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001592{
1593 int i, j;
1594
1595 for (i = 0, j = 8; i < 112; i++, j++)
1596 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1597}
1598
Harald Weltec6636782017-06-12 14:59:37 +02001599/* assemble a EFR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001600static void tch_efr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001601{
1602 int i, j;
1603
1604 tch_data[0] = 0xc << 4;
1605 memset(tch_data + 1, 0, 30);
1606
1607 for (i = 0, j = 4; i < 244; i++, j++)
1608 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1609}
1610
Harald Welteb9946d32017-06-12 09:40:16 +02001611static void tch_efr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001612{
1613 int i, j;
1614
1615 for (i = 0, j = 4; i < 244; i++, j++)
1616 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1617}
1618
Harald Weltec6636782017-06-12 14:59:37 +02001619/* assemble a AMR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001620static void tch_amr_reassemble(uint8_t *tch_data, const ubit_t *d_bits, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001621{
1622 int i, j;
1623
1624 memset(tch_data, 0, (len + 7) >> 3);
1625
1626 for (i = 0, j = 0; i < len; i++, j++)
1627 tch_data[j >> 3] |= (d_bits[i] << (7 - (j & 7)));
1628}
1629
Harald Welteb9946d32017-06-12 09:40:16 +02001630static void tch_amr_disassemble(ubit_t *d_bits, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001631{
1632 int i, j;
1633
1634 for (i = 0, j = 0; i < len; i++, j++)
1635 d_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1636}
1637
Harald Weltec6636782017-06-12 14:59:37 +02001638/* re-arrange according to TS 05.03 Table 2 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001639static void tch_fr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001640{
1641 int i;
1642
1643 for (i = 0; i < 260; i++)
1644 b_bits[gsm610_bitorder[i]] = d_bits[i];
1645}
1646
Harald Weltec6636782017-06-12 14:59:37 +02001647/* re-arrange according to TS 05.03 Table 2 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001648static void tch_fr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001649{
1650 int i;
1651
1652 for (i = 0; i < 260; i++)
1653 d_bits[i] = b_bits[gsm610_bitorder[i]];
1654}
1655
Harald Weltec6636782017-06-12 14:59:37 +02001656/* re-arrange according to TS 05.03 Table 3a (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001657static void tch_hr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001658{
1659 int i;
1660
1661 const uint16_t *map;
1662
1663 if (!d_bits[93] && !d_bits[94])
1664 map = gsm620_unvoiced_bitorder;
1665 else
1666 map = gsm620_voiced_bitorder;
1667
1668 for (i = 0; i < 112; i++)
1669 b_bits[map[i]] = d_bits[i];
1670}
1671
Harald Weltec6636782017-06-12 14:59:37 +02001672/* re-arrange according to TS 05.03 Table 3a (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001673static void tch_hr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001674{
1675 int i;
1676 const uint16_t *map;
1677
1678 if (!b_bits[34] && !b_bits[35])
1679 map = gsm620_unvoiced_bitorder;
1680 else
1681 map = gsm620_voiced_bitorder;
1682
1683 for (i = 0; i < 112; i++)
1684 d_bits[i] = b_bits[map[i]];
1685}
1686
Harald Weltec6636782017-06-12 14:59:37 +02001687/* re-arrange according to TS 05.03 Table 6 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001688static void tch_efr_d_to_w(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001689{
1690 int i;
1691
1692 for (i = 0; i < 260; i++)
1693 b_bits[gsm660_bitorder[i]] = d_bits[i];
1694}
1695
Harald Weltec6636782017-06-12 14:59:37 +02001696/* re-arrange according to TS 05.03 Table 6 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001697static void tch_efr_w_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001698{
1699 int i;
1700
1701 for (i = 0; i < 260; i++)
1702 d_bits[i] = b_bits[gsm660_bitorder[i]];
1703}
1704
Harald Weltec6636782017-06-12 14:59:37 +02001705/* extract the 65 protected class1a+1b bits */
Harald Welteb9946d32017-06-12 09:40:16 +02001706static void tch_efr_protected(const ubit_t *s_bits, ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001707{
1708 int i;
1709
1710 for (i = 0; i < 65; i++)
1711 b_bits[i] = s_bits[gsm0503_gsm_efr_protected_bits[i] - 1];
1712}
1713
Harald Welteb9946d32017-06-12 09:40:16 +02001714static void tch_fr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001715{
1716 int i;
1717
1718 for (i = 0; i < 91; i++) {
1719 d[i << 1] = u[i];
1720 d[(i << 1) + 1] = u[184 - i];
1721 }
1722
1723 for (i = 0; i < 3; i++)
1724 p[i] = u[91 + i];
1725}
1726
Harald Welteb9946d32017-06-12 09:40:16 +02001727static void tch_fr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001728{
1729 int i;
1730
1731 for (i = 0; i < 91; i++) {
1732 u[i] = d[i << 1];
1733 u[184 - i] = d[(i << 1) + 1];
1734 }
1735
1736 for (i = 0; i < 3; i++)
1737 u[91 + i] = p[i];
1738}
1739
Harald Welteb9946d32017-06-12 09:40:16 +02001740static void tch_hr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001741{
1742 memcpy(d, u, 95);
1743 memcpy(p, u + 95, 3);
1744}
1745
Harald Welteb9946d32017-06-12 09:40:16 +02001746static void tch_hr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001747{
1748 memcpy(u, d, 95);
1749 memcpy(u + 95, p, 3);
1750}
1751
Harald Welteb9946d32017-06-12 09:40:16 +02001752static void tch_efr_reorder(ubit_t *w, const ubit_t *s, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001753{
1754 memcpy(w, s, 71);
1755 w[71] = w[72] = s[69];
1756 memcpy(w + 73, s + 71, 50);
1757 w[123] = w[124] = s[119];
1758 memcpy(w + 125, s + 121, 53);
1759 w[178] = w[179] = s[172];
1760 memcpy(w + 180, s + 174, 50);
1761 w[230] = w[231] = s[222];
1762 memcpy(w + 232, s + 224, 20);
1763 memcpy(w + 252, p, 8);
1764}
1765
Harald Welteb9946d32017-06-12 09:40:16 +02001766static void tch_efr_unreorder(ubit_t *s, ubit_t *p, const ubit_t *w)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001767{
1768 int sum;
1769
1770 memcpy(s, w, 71);
1771 sum = s[69] + w[71] + w[72];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001772 s[69] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001773 memcpy(s + 71, w + 73, 50);
1774 sum = s[119] + w[123] + w[124];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001775 s[119] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001776 memcpy(s + 121, w + 125, 53);
1777 sum = s[172] + w[178] + w[179];
1778 s[172] = (sum > 2);
1779 memcpy(s + 174, w + 180, 50);
Niro Mahasinghe834e2ac2017-11-03 12:22:34 +01001780 sum = s[222] + w[230] + w[231];
Niro Mahasinghec526dbc2017-11-03 12:24:30 +01001781 s[222] = (sum >= 2);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001782 memcpy(s + 224, w + 232, 20);
1783 memcpy(p, w + 252, 8);
1784}
1785
Harald Welteb9946d32017-06-12 09:40:16 +02001786static 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 +07001787{
1788 memcpy(u, d, prot);
1789 memcpy(u + prot, p, 6);
1790 memcpy(u + prot + 6, d + prot, len - prot);
1791}
1792
Harald Welteb9946d32017-06-12 09:40:16 +02001793static 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 +07001794{
1795 memcpy(d, u, prot);
1796 memcpy(p, u + prot, 6);
1797 memcpy(d + prot, u + prot + 6, len - prot);
1798}
1799
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001800/*! Perform channel decoding of a FR/EFR channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001801 * \param[out] tch_data Codec frame in RTP payload format
1802 * \param[in] bursts buffer containing the symbols of 8 bursts
1803 * \param[in] net_order FIXME
1804 * \param[in] efr Is this channel using EFR (1) or FR (0)
1805 * \param[out] n_errors Number of detected bit errors
1806 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02001807 * \returns length of bytes used in \a tch_data output buffer; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001808int gsm0503_tch_fr_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001809 int net_order, int efr, int *n_errors, int *n_bits_total)
1810{
1811 sbit_t iB[912], cB[456], h;
1812 ubit_t conv[185], s[244], w[260], b[65], d[260], p[8];
1813 int i, rv, len, steal = 0;
1814
Harald Weltec6636782017-06-12 14:59:37 +02001815 /* map from 8 bursts to interleaved data bits (iB) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001816 for (i = 0; i < 8; i++) {
1817 gsm0503_tch_burst_unmap(&iB[i * 114],
1818 &bursts[i * 116], &h, i >> 2);
1819 steal -= h;
1820 }
Harald Weltec6636782017-06-12 14:59:37 +02001821 /* we now have the bits of the four bursts (interface 4 in
1822 * Figure 1a of TS 05.03 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001823
1824 gsm0503_tch_fr_deinterleave(cB, iB);
Harald Weltec6636782017-06-12 14:59:37 +02001825 /* we now have the coded bits c(B): interface 3 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001826
1827 if (steal > 0) {
1828 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
1829 if (rv) {
1830 /* Error decoding FACCH frame */
1831 return -1;
1832 }
1833
1834 return 23;
1835 }
1836
1837 osmo_conv_decode_ber(&gsm0503_tch_fr, cB, conv, n_errors, n_bits_total);
Harald Weltec6636782017-06-12 14:59:37 +02001838 /* we now have the data bits 'u': interface 2 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001839
Harald Weltec6636782017-06-12 14:59:37 +02001840 /* input: 'conv', output: d[ata] + p[arity] */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001841 tch_fr_unreorder(d, p, conv);
1842
1843 for (i = 0; i < 78; i++)
1844 d[i + 182] = (cB[i + 378] < 0) ? 1 : 0;
1845
Harald Weltec6636782017-06-12 14:59:37 +02001846 /* check if parity of first 50 (class 1) 'd'-bits match 'p' */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001847 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1848 if (rv) {
1849 /* Error checking CRC8 for the FR part of an EFR/FR frame */
1850 return -1;
1851 }
1852
1853 if (efr) {
1854 tch_efr_d_to_w(w, d);
Harald Weltec6636782017-06-12 14:59:37 +02001855 /* we now have the preliminary-coded bits w(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001856
1857 tch_efr_unreorder(s, p, w);
Harald Weltec6636782017-06-12 14:59:37 +02001858 /* we now have the data delivered to the preliminary
1859 * channel encoding unit s(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001860
Harald Weltec6636782017-06-12 14:59:37 +02001861 /* extract the 65 most important bits according TS 05.03 3.1.1.1 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001862 tch_efr_protected(s, b);
1863
Harald Weltec6636782017-06-12 14:59:37 +02001864 /* perform CRC-8 on 65 most important bits (50 bits of
1865 * class 1a + 15 bits of class 1b) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001866 rv = osmo_crc8gen_check_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1867 if (rv) {
1868 /* Error checking CRC8 for the EFR part of an EFR frame */
1869 return -1;
1870 }
1871
1872 tch_efr_reassemble(tch_data, s);
1873
1874 len = GSM_EFR_BYTES;
1875 } else {
1876 tch_fr_d_to_b(w, d);
1877
1878 tch_fr_reassemble(tch_data, w, net_order);
1879
1880 len = GSM_FR_BYTES;
1881 }
1882
1883 return len;
1884}
1885
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001886/*! Perform channel encoding on a TCH/FS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001887 * \param[out] bursts caller-allocated output buffer for bursts bits
1888 * \param[in] tch_data Codec input data in RTP payload format
1889 * \param[in] len Length of \a tch_data in bytes
1890 * \param[in] net_order FIXME
1891 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001892int gsm0503_tch_fr_encode(ubit_t *bursts, const uint8_t *tch_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001893 int len, int net_order)
1894{
1895 ubit_t iB[912], cB[456], h;
1896 ubit_t conv[185], w[260], b[65], s[244], d[260], p[8];
1897 int i;
1898
1899 switch (len) {
1900 case GSM_EFR_BYTES: /* TCH EFR */
1901
1902 tch_efr_disassemble(s, tch_data);
1903
1904 tch_efr_protected(s, b);
1905
1906 osmo_crc8gen_set_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1907
1908 tch_efr_reorder(w, s, p);
1909
1910 tch_efr_w_to_d(d, w);
1911
1912 goto coding_efr_fr;
1913 case GSM_FR_BYTES: /* TCH FR */
1914 tch_fr_disassemble(w, tch_data, net_order);
1915
1916 tch_fr_b_to_d(d, w);
1917
1918coding_efr_fr:
1919 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1920
1921 tch_fr_reorder(conv, d, p);
1922
1923 memcpy(cB + 378, d + 182, 78);
1924
1925 osmo_conv_encode(&gsm0503_tch_fr, conv, cB);
1926
1927 h = 0;
1928
1929 break;
1930 case GSM_MACBLOCK_LEN: /* FACCH */
1931 _xcch_encode_cB(cB, tch_data);
1932
1933 h = 1;
1934
1935 break;
1936 default:
1937 return -1;
1938 }
1939
1940 gsm0503_tch_fr_interleave(cB, iB);
1941
1942 for (i = 0; i < 8; i++) {
1943 gsm0503_tch_burst_map(&iB[i * 114],
1944 &bursts[i * 116], &h, i >> 2);
1945 }
1946
1947 return 0;
1948}
1949
Neels Hofmeyr87e45502017-06-20 00:17:59 +02001950/*! Perform channel decoding of a HR(v1) channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02001951 * \param[out] tch_data Codec frame in RTP payload format
1952 * \param[in] bursts buffer containing the symbols of 8 bursts
1953 * \param[in] odd Odd (1) or even (0) frame number
1954 * \param[out] n_errors Number of detected bit errors
1955 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02001956 * \returns length of bytes used in \a tch_data output buffer; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001957int gsm0503_tch_hr_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001958 int *n_errors, int *n_bits_total)
1959{
1960 sbit_t iB[912], cB[456], h;
1961 ubit_t conv[98], b[112], d[112], p[3];
1962 int i, rv, steal = 0;
1963
1964 /* Only unmap the stealing bits */
1965 if (!odd) {
1966 for (i = 0; i < 4; i++) {
1967 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
1968 steal -= h;
1969 }
1970
1971 for (i = 2; i < 5; i++) {
1972 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
1973 steal -= h;
1974 }
1975 }
1976
1977 /* If we found a stole FACCH, but only at correct alignment */
1978 if (steal > 0) {
1979 for (i = 0; i < 6; i++) {
1980 gsm0503_tch_burst_unmap(&iB[i * 114],
1981 &bursts[i * 116], NULL, i >> 2);
1982 }
1983
1984 for (i = 2; i < 4; i++) {
1985 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
1986 &bursts[i * 116], NULL, 1);
1987 }
1988
1989 gsm0503_tch_fr_deinterleave(cB, iB);
1990
1991 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
1992 if (rv) {
1993 /* Error decoding FACCH frame */
1994 return -1;
1995 }
1996
1997 return GSM_MACBLOCK_LEN;
1998 }
1999
2000 for (i = 0; i < 4; i++) {
2001 gsm0503_tch_burst_unmap(&iB[i * 114],
2002 &bursts[i * 116], NULL, i >> 1);
2003 }
2004
2005 gsm0503_tch_hr_deinterleave(cB, iB);
2006
2007 osmo_conv_decode_ber(&gsm0503_tch_hr, cB, conv, n_errors, n_bits_total);
2008
2009 tch_hr_unreorder(d, p, conv);
2010
2011 for (i = 0; i < 17; i++)
2012 d[i + 95] = (cB[i + 211] < 0) ? 1 : 0;
2013
2014 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
2015 if (rv) {
2016 /* Error checking CRC8 for an HR frame */
2017 return -1;
2018 }
2019
2020 tch_hr_d_to_b(b, d);
2021
2022 tch_hr_reassemble(tch_data, b);
2023
2024 return 15;
2025}
2026
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002027/*! Perform channel encoding on a TCH/HS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002028 * \param[out] bursts caller-allocated output buffer for bursts bits
2029 * \param[in] tch_data Codec input data in RTP payload format
2030 * \param[in] len Length of \a tch_data in bytes
2031 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002032int gsm0503_tch_hr_encode(ubit_t *bursts, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002033{
2034 ubit_t iB[912], cB[456], h;
2035 ubit_t conv[98], b[112], d[112], p[3];
2036 int i;
2037
2038 switch (len) {
2039 case 15: /* TCH HR */
2040 tch_hr_disassemble(b, tch_data);
2041
2042 tch_hr_b_to_d(d, b);
2043
2044 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
2045
2046 tch_hr_reorder(conv, d, p);
2047
2048 osmo_conv_encode(&gsm0503_tch_hr, conv, cB);
2049
2050 memcpy(cB + 211, d + 95, 17);
2051
2052 h = 0;
2053
2054 gsm0503_tch_hr_interleave(cB, iB);
2055
2056 for (i = 0; i < 4; i++) {
2057 gsm0503_tch_burst_map(&iB[i * 114],
2058 &bursts[i * 116], &h, i >> 1);
2059 }
2060
2061 break;
2062 case GSM_MACBLOCK_LEN: /* FACCH */
2063 _xcch_encode_cB(cB, tch_data);
2064
2065 h = 1;
2066
2067 gsm0503_tch_fr_interleave(cB, iB);
2068
2069 for (i = 0; i < 6; i++) {
2070 gsm0503_tch_burst_map(&iB[i * 114],
2071 &bursts[i * 116], &h, i >> 2);
2072 }
2073
2074 for (i = 2; i < 4; i++) {
2075 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2076 &bursts[i * 116], &h, 1);
2077 }
2078
2079 break;
2080 default:
2081 return -1;
2082 }
2083
2084 return 0;
2085}
2086
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002087/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002088 * \param[out] tch_data Codec frame in RTP payload format
2089 * \param[in] bursts buffer containing the symbols of 8 bursts
2090 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2091 * \param[in] codec array of active codecs (active codec set)
2092 * \param[in] codecs number of codecs in \a codec
2093 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2094 * \param[out] cmr Output in \a codec_mode_req = 1
2095 * \param[out] n_errors Number of detected bit errors
2096 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02002097 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2098 * codec out of range; negative on error
2099 */
Harald Welteb9946d32017-06-12 09:40:16 +02002100int gsm0503_tch_afs_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002101 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2102 uint8_t *cmr, int *n_errors, int *n_bits_total)
2103{
2104 sbit_t iB[912], cB[456], h;
2105 ubit_t d[244], p[6], conv[250];
2106 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
2107 *n_errors = 0; *n_bits_total = 0;
2108
2109 for (i=0; i<8; i++) {
2110 gsm0503_tch_burst_unmap(&iB[i * 114], &bursts[i * 116], &h, i >> 2);
2111 steal -= h;
2112 }
2113
2114 gsm0503_tch_fr_deinterleave(cB, iB);
2115
2116 if (steal > 0) {
2117 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2118 if (rv) {
2119 /* Error decoding FACCH frame */
2120 return -1;
2121 }
2122
2123 return GSM_MACBLOCK_LEN;
2124 }
2125
2126 for (i = 0; i < 4; i++) {
2127 for (j = 0, k = 0; j < 8; j++)
2128 k += abs(((int)gsm0503_afs_ic_sbit[i][j]) - ((int)cB[j]));
2129
2130 if (i == 0 || k < best) {
2131 best = k;
2132 id = i;
2133 }
2134 }
2135
2136 /* Check if indicated codec fits into range of codecs */
2137 if (id >= codecs) {
2138 /* Codec mode out of range, return id */
2139 return id;
2140 }
2141
2142 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2143 case 7: /* TCH/AFS12.2 */
2144 osmo_conv_decode_ber(&gsm0503_tch_afs_12_2, cB + 8,
2145 conv, n_errors, n_bits_total);
2146
2147 tch_amr_unmerge(d, p, conv, 244, 81);
2148
2149 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 81, p);
2150 if (rv) {
2151 /* Error checking CRC8 for an AMR 12.2 frame */
2152 return -1;
2153 }
2154
2155 tch_amr_reassemble(tch_data, d, 244);
2156
2157 len = 31;
2158
2159 break;
2160 case 6: /* TCH/AFS10.2 */
2161 osmo_conv_decode_ber(&gsm0503_tch_afs_10_2, cB + 8,
2162 conv, n_errors, n_bits_total);
2163
2164 tch_amr_unmerge(d, p, conv, 204, 65);
2165
2166 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 65, p);
2167 if (rv) {
2168 /* Error checking CRC8 for an AMR 10.2 frame */
2169 return -1;
2170 }
2171
2172 tch_amr_reassemble(tch_data, d, 204);
2173
2174 len = 26;
2175
2176 break;
2177 case 5: /* TCH/AFS7.95 */
2178 osmo_conv_decode_ber(&gsm0503_tch_afs_7_95, cB + 8,
2179 conv, n_errors, n_bits_total);
2180
2181 tch_amr_unmerge(d, p, conv, 159, 75);
2182
2183 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 75, p);
2184 if (rv) {
2185 /* Error checking CRC8 for an AMR 7.95 frame */
2186 return -1;
2187 }
2188
2189 tch_amr_reassemble(tch_data, d, 159);
2190
2191 len = 20;
2192
2193 break;
2194 case 4: /* TCH/AFS7.4 */
2195 osmo_conv_decode_ber(&gsm0503_tch_afs_7_4, cB + 8,
2196 conv, n_errors, n_bits_total);
2197
2198 tch_amr_unmerge(d, p, conv, 148, 61);
2199
2200 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2201 if (rv) {
2202 /* Error checking CRC8 for an AMR 7.4 frame */
2203 return -1;
2204 }
2205
2206 tch_amr_reassemble(tch_data, d, 148);
2207
2208 len = 19;
2209
2210 break;
2211 case 3: /* TCH/AFS6.7 */
2212 osmo_conv_decode_ber(&gsm0503_tch_afs_6_7, cB + 8,
2213 conv, n_errors, n_bits_total);
2214
2215 tch_amr_unmerge(d, p, conv, 134, 55);
2216
2217 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2218 if (rv) {
2219 /* Error checking CRC8 for an AMR 6.7 frame */
2220 return -1;
2221 }
2222
2223 tch_amr_reassemble(tch_data, d, 134);
2224
2225 len = 17;
2226
2227 break;
2228 case 2: /* TCH/AFS5.9 */
2229 osmo_conv_decode_ber(&gsm0503_tch_afs_5_9, cB + 8,
2230 conv, n_errors, n_bits_total);
2231
2232 tch_amr_unmerge(d, p, conv, 118, 55);
2233
2234 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2235 if (rv) {
2236 /* Error checking CRC8 for an AMR 5.9 frame */
2237 return -1;
2238 }
2239
2240 tch_amr_reassemble(tch_data, d, 118);
2241
2242 len = 15;
2243
2244 break;
2245 case 1: /* TCH/AFS5.15 */
2246 osmo_conv_decode_ber(&gsm0503_tch_afs_5_15, cB + 8,
2247 conv, n_errors, n_bits_total);
2248
2249 tch_amr_unmerge(d, p, conv, 103, 49);
2250
2251 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2252 if (rv) {
2253 /* Error checking CRC8 for an AMR 5.15 frame */
2254 return -1;
2255 }
2256
2257 tch_amr_reassemble(tch_data, d, 103);
2258
2259 len = 13;
2260
2261 break;
2262 case 0: /* TCH/AFS4.75 */
2263 osmo_conv_decode_ber(&gsm0503_tch_afs_4_75, cB + 8,
2264 conv, n_errors, n_bits_total);
2265
2266 tch_amr_unmerge(d, p, conv, 95, 39);
2267
2268 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2269 if (rv) {
2270 /* Error checking CRC8 for an AMR 4.75 frame */
2271 return -1;
2272 }
2273
2274 tch_amr_reassemble(tch_data, d, 95);
2275
2276 len = 12;
2277
2278 break;
2279 default:
2280 /* Unknown frame type */
2281 *n_bits_total = 448;
2282 *n_errors = *n_bits_total;
2283 return -1;
2284 }
2285
2286 /* Change codec request / indication, if frame is valid */
2287 if (codec_mode_req)
2288 *cmr = id;
2289 else
2290 *ft = id;
2291
2292 return len;
2293}
2294
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002295/*! Perform channel encoding on a TCH/AFS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002296 * \param[out] bursts caller-allocated output buffer for bursts bits
2297 * \param[in] tch_data Codec input data in RTP payload format
2298 * \param[in] len Length of \a tch_data in bytes
2299 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2300 * \param[in] codec Array of codecs (active codec set)
2301 * \param[in] codecs Number of entries in \a codec
2302 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2303 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2304 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002305int gsm0503_tch_afs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002306 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2307 uint8_t cmr)
2308{
2309 ubit_t iB[912], cB[456], h;
2310 ubit_t d[244], p[6], conv[250];
2311 int i;
2312 uint8_t id;
2313
2314 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2315 _xcch_encode_cB(cB, tch_data);
2316
2317 h = 1;
2318
2319 goto facch;
2320 }
2321
2322 h = 0;
2323
2324 if (codec_mode_req) {
2325 if (cmr >= codecs) {
2326 /* FIXME: CMR ID is not in codec list! */
2327 return -1;
2328 }
2329 id = cmr;
2330 } else {
2331 if (ft >= codecs) {
2332 /* FIXME: FT ID is not in codec list! */
2333 return -1;
2334 }
2335 id = ft;
2336 }
2337
2338 switch (codec[ft]) {
2339 case 7: /* TCH/AFS12.2 */
2340 if (len != 31)
2341 goto invalid_length;
2342
2343 tch_amr_disassemble(d, tch_data, 244);
2344
2345 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 81, p);
2346
2347 tch_amr_merge(conv, d, p, 244, 81);
2348
2349 osmo_conv_encode(&gsm0503_tch_afs_12_2, conv, cB + 8);
2350
2351 break;
2352 case 6: /* TCH/AFS10.2 */
2353 if (len != 26)
2354 goto invalid_length;
2355
2356 tch_amr_disassemble(d, tch_data, 204);
2357
2358 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 65, p);
2359
2360 tch_amr_merge(conv, d, p, 204, 65);
2361
2362 osmo_conv_encode(&gsm0503_tch_afs_10_2, conv, cB + 8);
2363
2364 break;
2365 case 5: /* TCH/AFS7.95 */
2366 if (len != 20)
2367 goto invalid_length;
2368
2369 tch_amr_disassemble(d, tch_data, 159);
2370
2371 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 75, p);
2372
2373 tch_amr_merge(conv, d, p, 159, 75);
2374
2375 osmo_conv_encode(&gsm0503_tch_afs_7_95, conv, cB + 8);
2376
2377 break;
2378 case 4: /* TCH/AFS7.4 */
2379 if (len != 19)
2380 goto invalid_length;
2381
2382 tch_amr_disassemble(d, tch_data, 148);
2383
2384 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2385
2386 tch_amr_merge(conv, d, p, 148, 61);
2387
2388 osmo_conv_encode(&gsm0503_tch_afs_7_4, conv, cB + 8);
2389
2390 break;
2391 case 3: /* TCH/AFS6.7 */
2392 if (len != 17)
2393 goto invalid_length;
2394
2395 tch_amr_disassemble(d, tch_data, 134);
2396
2397 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2398
2399 tch_amr_merge(conv, d, p, 134, 55);
2400
2401 osmo_conv_encode(&gsm0503_tch_afs_6_7, conv, cB + 8);
2402
2403 break;
2404 case 2: /* TCH/AFS5.9 */
2405 if (len != 15)
2406 goto invalid_length;
2407
2408 tch_amr_disassemble(d, tch_data, 118);
2409
2410 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2411
2412 tch_amr_merge(conv, d, p, 118, 55);
2413
2414 osmo_conv_encode(&gsm0503_tch_afs_5_9, conv, cB + 8);
2415
2416 break;
2417 case 1: /* TCH/AFS5.15 */
2418 if (len != 13)
2419 goto invalid_length;
2420
2421 tch_amr_disassemble(d, tch_data, 103);
2422
2423 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2424
2425 tch_amr_merge(conv, d, p, 103, 49);
2426
2427 osmo_conv_encode(&gsm0503_tch_afs_5_15, conv, cB + 8);
2428
2429 break;
2430 case 0: /* TCH/AFS4.75 */
2431 if (len != 12)
2432 goto invalid_length;
2433
2434 tch_amr_disassemble(d, tch_data, 95);
2435
2436 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2437
2438 tch_amr_merge(conv, d, p, 95, 39);
2439
2440 osmo_conv_encode(&gsm0503_tch_afs_4_75, conv, cB + 8);
2441
2442 break;
2443 default:
2444 /* FIXME: FT %ft is not supported */
2445 return -1;
2446 }
2447
2448 memcpy(cB, gsm0503_afs_ic_ubit[id], 8);
2449
2450facch:
2451 gsm0503_tch_fr_interleave(cB, iB);
2452
2453 for (i = 0; i < 8; i++) {
2454 gsm0503_tch_burst_map(&iB[i * 114],
2455 &bursts[i * 116], &h, i >> 2);
2456 }
2457
2458 return 0;
2459
2460invalid_length:
2461 /* FIXME: payload length %len does not comply with codec type %ft */
2462 return -1;
2463}
2464
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002465/*! Perform channel decoding of a TCH/AFS channel according TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002466 * \param[out] tch_data Codec frame in RTP payload format
2467 * \param[in] bursts buffer containing the symbols of 8 bursts
2468 * \param[in] odd Is this an odd (1) or even (0) frame number?
2469 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2470 * \param[in] codec array of active codecs (active codec set)
2471 * \param[in] codecs number of codecs in \a codec
2472 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2473 * \param[out] cmr Output in \a codec_mode_req = 1
2474 * \param[out] n_errors Number of detected bit errors
2475 * \param[out] n_bits_total Total number of bits
Pau Espin Pedrolf81d03f2018-07-19 13:49:41 +02002476 * \returns (>=4) length of bytes used in \a tch_data output buffer; ([0,3])
2477 * codec out of range; negative on error
2478 */
Harald Welteb9946d32017-06-12 09:40:16 +02002479int gsm0503_tch_ahs_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002480 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2481 uint8_t *cmr, int *n_errors, int *n_bits_total)
2482{
2483 sbit_t iB[912], cB[456], h;
2484 ubit_t d[244], p[6], conv[135];
2485 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
2486
2487 /* only unmap the stealing bits */
2488 if (!odd) {
2489 for (i = 0; i < 4; i++) {
2490 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
2491 steal -= h;
2492 }
2493 for (i = 2; i < 5; i++) {
2494 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
2495 steal -= h;
2496 }
2497 }
2498
2499 /* if we found a stole FACCH, but only at correct alignment */
2500 if (steal > 0) {
2501 for (i = 0; i < 6; i++) {
2502 gsm0503_tch_burst_unmap(&iB[i * 114],
2503 &bursts[i * 116], NULL, i >> 2);
2504 }
2505
2506 for (i = 2; i < 4; i++) {
2507 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
2508 &bursts[i * 116], NULL, 1);
2509 }
2510
2511 gsm0503_tch_fr_deinterleave(cB, iB);
2512
2513 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2514 if (rv) {
2515 /* Error decoding FACCH frame */
2516 return -1;
2517 }
2518
2519 return GSM_MACBLOCK_LEN;
2520 }
2521
2522 for (i = 0; i < 4; i++) {
2523 gsm0503_tch_burst_unmap(&iB[i * 114],
2524 &bursts[i * 116], NULL, i >> 1);
2525 }
2526
2527 gsm0503_tch_hr_deinterleave(cB, iB);
2528
2529 for (i = 0; i < 4; i++) {
2530 for (j = 0, k = 0; j < 4; j++)
2531 k += abs(((int)gsm0503_ahs_ic_sbit[i][j]) - ((int)cB[j]));
2532
2533 if (i == 0 || k < best) {
2534 best = k;
2535 id = i;
2536 }
2537 }
2538
2539 /* Check if indicated codec fits into range of codecs */
2540 if (id >= codecs) {
2541 /* Codec mode out of range, return id */
2542 return id;
2543 }
2544
2545 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2546 case 5: /* TCH/AHS7.95 */
2547 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_95, cB + 4,
2548 conv, n_errors, n_bits_total);
2549
2550 tch_amr_unmerge(d, p, conv, 123, 67);
2551
2552 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 67, p);
2553 if (rv) {
2554 /* Error checking CRC8 for an AMR 7.95 frame */
2555 return -1;
2556 }
2557
2558 for (i = 0; i < 36; i++)
2559 d[i + 123] = (cB[i + 192] < 0) ? 1 : 0;
2560
2561 tch_amr_reassemble(tch_data, d, 159);
2562
2563 len = 20;
2564
2565 break;
2566 case 4: /* TCH/AHS7.4 */
2567 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_4, cB + 4,
2568 conv, n_errors, n_bits_total);
2569
2570 tch_amr_unmerge(d, p, conv, 120, 61);
2571
2572 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2573 if (rv) {
2574 /* Error checking CRC8 for an AMR 7.4 frame */
2575 return -1;
2576 }
2577
2578 for (i = 0; i < 28; i++)
2579 d[i + 120] = (cB[i + 200] < 0) ? 1 : 0;
2580
2581 tch_amr_reassemble(tch_data, d, 148);
2582
2583 len = 19;
2584
2585 break;
2586 case 3: /* TCH/AHS6.7 */
2587 osmo_conv_decode_ber(&gsm0503_tch_ahs_6_7, cB + 4,
2588 conv, n_errors, n_bits_total);
2589
2590 tch_amr_unmerge(d, p, conv, 110, 55);
2591
2592 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2593 if (rv) {
2594 /* Error checking CRC8 for an AMR 6.7 frame */
2595 return -1;
2596 }
2597
2598 for (i = 0; i < 24; i++)
2599 d[i + 110] = (cB[i + 204] < 0) ? 1 : 0;
2600
2601 tch_amr_reassemble(tch_data, d, 134);
2602
2603 len = 17;
2604
2605 break;
2606 case 2: /* TCH/AHS5.9 */
2607 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_9, cB + 4,
2608 conv, n_errors, n_bits_total);
2609
2610 tch_amr_unmerge(d, p, conv, 102, 55);
2611
2612 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2613 if (rv) {
2614 /* Error checking CRC8 for an AMR 5.9 frame */
2615 return -1;
2616 }
2617
2618 for (i = 0; i < 16; i++)
2619 d[i + 102] = (cB[i + 212] < 0) ? 1 : 0;
2620
2621 tch_amr_reassemble(tch_data, d, 118);
2622
2623 len = 15;
2624
2625 break;
2626 case 1: /* TCH/AHS5.15 */
2627 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_15, cB + 4,
2628 conv, n_errors, n_bits_total);
2629
2630 tch_amr_unmerge(d, p, conv, 91, 49);
2631
2632 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2633 if (rv) {
2634 /* Error checking CRC8 for an AMR 5.15 frame */
2635 return -1;
2636 }
2637
2638 for (i = 0; i < 12; i++)
2639 d[i + 91] = (cB[i + 216] < 0) ? 1 : 0;
2640
2641 tch_amr_reassemble(tch_data, d, 103);
2642
2643 len = 13;
2644
2645 break;
2646 case 0: /* TCH/AHS4.75 */
2647 osmo_conv_decode_ber(&gsm0503_tch_ahs_4_75, cB + 4,
2648 conv, n_errors, n_bits_total);
2649
2650 tch_amr_unmerge(d, p, conv, 83, 39);
2651
2652 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2653 if (rv) {
2654 /* Error checking CRC8 for an AMR 4.75 frame */
2655 return -1;
2656 }
2657
2658 for (i = 0; i < 12; i++)
2659 d[i + 83] = (cB[i + 216] < 0) ? 1 : 0;
2660
2661 tch_amr_reassemble(tch_data, d, 95);
2662
2663 len = 12;
2664
2665 break;
2666 default:
2667 /* Unknown frame type */
2668 *n_bits_total = 159;
2669 *n_errors = *n_bits_total;
2670 return -1;
2671 }
2672
2673 /* Change codec request / indication, if frame is valid */
2674 if (codec_mode_req)
2675 *cmr = id;
2676 else
2677 *ft = id;
2678
2679 return len;
2680}
2681
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002682/*! Perform channel encoding on a TCH/AHS channel according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002683 * \param[out] bursts caller-allocated output buffer for bursts bits
2684 * \param[in] tch_data Codec input data in RTP payload format
2685 * \param[in] len Length of \a tch_data in bytes
2686 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2687 * \param[in] codec Array of codecs (active codec set)
2688 * \param[in] codecs Number of entries in \a codec
2689 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2690 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2691 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002692int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002693 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2694 uint8_t cmr)
2695{
2696 ubit_t iB[912], cB[456], h;
2697 ubit_t d[244], p[6], conv[135];
2698 int i;
2699 uint8_t id;
2700
2701 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2702 _xcch_encode_cB(cB, tch_data);
2703
2704 h = 1;
2705
2706 gsm0503_tch_fr_interleave(cB, iB);
2707
2708 for (i = 0; i < 6; i++)
2709 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116],
2710 &h, i >> 2);
2711 for (i = 2; i < 4; i++)
2712 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2713 &bursts[i * 116], &h, 1);
2714
2715 return 0;
2716 }
2717
2718 h = 0;
2719
2720 if (codec_mode_req) {
2721 if (cmr >= codecs) {
2722 /* FIXME: CMR ID %d not in codec list */
2723 return -1;
2724 }
2725 id = cmr;
2726 } else {
2727 if (ft >= codecs) {
2728 /* FIXME: FT ID %d not in codec list */
2729 return -1;
2730 }
2731 id = ft;
2732 }
2733
2734 switch (codec[ft]) {
2735 case 5: /* TCH/AHS7.95 */
2736 if (len != 20)
2737 goto invalid_length;
2738
2739 tch_amr_disassemble(d, tch_data, 159);
2740
2741 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 67, p);
2742
2743 tch_amr_merge(conv, d, p, 123, 67);
2744
2745 osmo_conv_encode(&gsm0503_tch_ahs_7_95, conv, cB + 4);
2746
2747 memcpy(cB + 192, d + 123, 36);
2748
2749 break;
2750 case 4: /* TCH/AHS7.4 */
2751 if (len != 19)
2752 goto invalid_length;
2753
2754 tch_amr_disassemble(d, tch_data, 148);
2755
2756 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2757
2758 tch_amr_merge(conv, d, p, 120, 61);
2759
2760 osmo_conv_encode(&gsm0503_tch_ahs_7_4, conv, cB + 4);
2761
2762 memcpy(cB + 200, d + 120, 28);
2763
2764 break;
2765 case 3: /* TCH/AHS6.7 */
2766 if (len != 17)
2767 goto invalid_length;
2768
2769 tch_amr_disassemble(d, tch_data, 134);
2770
2771 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2772
2773 tch_amr_merge(conv, d, p, 110, 55);
2774
2775 osmo_conv_encode(&gsm0503_tch_ahs_6_7, conv, cB + 4);
2776
2777 memcpy(cB + 204, d + 110, 24);
2778
2779 break;
2780 case 2: /* TCH/AHS5.9 */
2781 if (len != 15)
2782 goto invalid_length;
2783
2784 tch_amr_disassemble(d, tch_data, 118);
2785
2786 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2787
2788 tch_amr_merge(conv, d, p, 102, 55);
2789
2790 osmo_conv_encode(&gsm0503_tch_ahs_5_9, conv, cB + 4);
2791
2792 memcpy(cB + 212, d + 102, 16);
2793
2794 break;
2795 case 1: /* TCH/AHS5.15 */
2796 if (len != 13)
2797 goto invalid_length;
2798
2799 tch_amr_disassemble(d, tch_data, 103);
2800
2801 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2802
2803 tch_amr_merge(conv, d, p, 91, 49);
2804
2805 osmo_conv_encode(&gsm0503_tch_ahs_5_15, conv, cB + 4);
2806
2807 memcpy(cB + 216, d + 91, 12);
2808
2809 break;
2810 case 0: /* TCH/AHS4.75 */
2811 if (len != 12)
2812 goto invalid_length;
2813
2814 tch_amr_disassemble(d, tch_data, 95);
2815
2816 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2817
2818 tch_amr_merge(conv, d, p, 83, 39);
2819
2820 osmo_conv_encode(&gsm0503_tch_ahs_4_75, conv, cB + 4);
2821
2822 memcpy(cB + 216, d + 83, 12);
2823
2824 break;
2825 default:
2826 /* FIXME: FT %ft is not supported */
2827 return -1;
2828 }
2829
2830 memcpy(cB, gsm0503_afs_ic_ubit[id], 4);
2831
2832 gsm0503_tch_hr_interleave(cB, iB);
2833
2834 for (i = 0; i < 4; i++)
2835 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116], &h, i >> 1);
2836
2837 return 0;
2838
2839invalid_length:
2840 /* FIXME: payload length %len does not comply with codec type %ft */
2841 return -1;
2842}
2843
2844/*
2845 * GSM RACH transcoding
2846 */
2847
2848/*
2849 * GSM RACH apply BSIC to parity
2850 *
2851 * p(j) = p(j) xor b(j) j = 0, ..., 5
2852 * b(0) = MSB of PLMN colour code
2853 * b(5) = LSB of BS colour code
2854 */
Max32e56412017-10-16 14:58:00 +02002855static inline void rach_apply_bsic(ubit_t *d, uint8_t bsic, uint8_t start)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002856{
2857 int i;
2858
2859 /* Apply it */
2860 for (i = 0; i < 6; i++)
Max32e56412017-10-16 14:58:00 +02002861 d[start + i] ^= ((bsic >> (5 - i)) & 1);
2862}
2863
Harald Welte6950b192018-02-26 11:48:00 +01002864static inline int16_t rach_decode_ber(const sbit_t *burst, uint8_t bsic, bool is_11bit,
2865 int *n_errors, int *n_bits_total)
Max32e56412017-10-16 14:58:00 +02002866{
2867 ubit_t conv[17];
2868 uint8_t ra[2] = { 0 }, nbits = is_11bit ? 11 : 8;
2869 int rv;
2870
Harald Welte6950b192018-02-26 11:48:00 +01002871 osmo_conv_decode_ber(is_11bit ? &gsm0503_rach_ext : &gsm0503_rach, burst, conv,
2872 n_errors, n_bits_total);
Max32e56412017-10-16 14:58:00 +02002873
2874 rach_apply_bsic(conv, bsic, nbits);
2875
2876 rv = osmo_crc8gen_check_bits(&gsm0503_rach_crc6, conv, nbits, conv + nbits);
2877 if (rv)
2878 return -1;
2879
2880 osmo_ubit2pbit_ext(ra, 0, conv, 0, nbits, 1);
2881
Vadim Yanitskiy9e713f32020-03-31 19:40:09 +07002882 return is_11bit ? ((ra[0] << 3) | (ra[1] & 0x07)) : ra[0];
Max32e56412017-10-16 14:58:00 +02002883}
2884
2885/*! Decode the Extended (11-bit) RACH according to 3GPP TS 45.003
2886 * \param[out] ra output buffer for RACH data
2887 * \param[in] burst Input burst data
2888 * \param[in] bsic BSIC used in this cell
2889 * \returns 0 on success; negative on error (e.g. CRC error) */
2890int gsm0503_rach_ext_decode(uint16_t *ra, const sbit_t *burst, uint8_t bsic)
2891{
Harald Welte6950b192018-02-26 11:48:00 +01002892 int16_t r = rach_decode_ber(burst, bsic, true, NULL, NULL);
Max32e56412017-10-16 14:58:00 +02002893
2894 if (r < 0)
2895 return r;
2896
2897 *ra = r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002898
2899 return 0;
2900}
2901
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002902/*! Decode the (8-bit) RACH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002903 * \param[out] ra output buffer for RACH data
2904 * \param[in] burst Input burst data
2905 * \param[in] bsic BSIC used in this cell
2906 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02002907int gsm0503_rach_decode(uint8_t *ra, const sbit_t *burst, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002908{
Harald Welte6950b192018-02-26 11:48:00 +01002909 int16_t r = rach_decode_ber(burst, bsic, false, NULL, NULL);
2910 if (r < 0)
2911 return r;
2912
2913 *ra = r;
2914 return 0;
2915}
2916
2917/*! Decode the Extended (11-bit) RACH according to 3GPP TS 45.003
2918 * \param[out] ra output buffer for RACH data
2919 * \param[in] burst Input burst data
2920 * \param[in] bsic BSIC used in this cell
2921 * \param[out] n_errors Number of detected bit errors
2922 * \param[out] n_bits_total Total number of bits
2923 * \returns 0 on success; negative on error (e.g. CRC error) */
2924int gsm0503_rach_ext_decode_ber(uint16_t *ra, const sbit_t *burst, uint8_t bsic,
2925 int *n_errors, int *n_bits_total)
2926{
2927 int16_t r = rach_decode_ber(burst, bsic, true, n_errors, n_bits_total);
2928 if (r < 0)
2929 return r;
2930
2931 *ra = r;
2932 return 0;
2933}
2934
2935/*! Decode the (8-bit) RACH according to TS 05.03
2936 * \param[out] ra output buffer for RACH data
2937 * \param[in] burst Input burst data
2938 * \param[in] bsic BSIC used in this cell
2939 * \param[out] n_errors Number of detected bit errors
2940 * \param[out] n_bits_total Total number of bits
2941 * \returns 0 on success; negative on error (e.g. CRC error) */
2942int gsm0503_rach_decode_ber(uint8_t *ra, const sbit_t *burst, uint8_t bsic,
2943 int *n_errors, int *n_bits_total)
2944{
2945 int16_t r = rach_decode_ber(burst, bsic, false, n_errors, n_bits_total);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002946
Max32e56412017-10-16 14:58:00 +02002947 if (r < 0)
2948 return r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002949
Max32e56412017-10-16 14:58:00 +02002950 *ra = r;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002951
2952 return 0;
2953}
2954
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002955/*! Encode the (8-bit) RACH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002956 * \param[out] burst Caller-allocated output burst buffer
2957 * \param[in] ra Input RACH data
2958 * \param[in] bsic BSIC used in this cell
2959 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002960int gsm0503_rach_encode(ubit_t *burst, const uint8_t *ra, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002961{
Max32e56412017-10-16 14:58:00 +02002962 return gsm0503_rach_ext_encode(burst, *ra, bsic, false);
2963}
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002964
Max32e56412017-10-16 14:58:00 +02002965/*! Encode the Extended (11-bit) or regular (8-bit) RACH according to 3GPP TS 45.003
2966 * \param[out] burst Caller-allocated output burst buffer
2967 * \param[in] ra11 Input RACH data
2968 * \param[in] bsic BSIC used in this cell
2969 * \param[in] is_11bit whether given RA is 11 bit or not
2970 * \returns 0 on success; negative on error */
2971int gsm0503_rach_ext_encode(ubit_t *burst, uint16_t ra11, uint8_t bsic, bool is_11bit)
2972{
2973 ubit_t conv[17];
2974 uint8_t ra[2] = { 0 }, nbits = 8;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002975
Max32e56412017-10-16 14:58:00 +02002976 if (is_11bit) {
Vadim Yanitskiy9e713f32020-03-31 19:40:09 +07002977 ra[0] = (uint8_t) (ra11 >> 3);
2978 ra[1] = (uint8_t) (ra11 & 0x07);
Max32e56412017-10-16 14:58:00 +02002979 nbits = 11;
2980 } else
2981 ra[0] = (uint8_t)ra11;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002982
Max32e56412017-10-16 14:58:00 +02002983 osmo_pbit2ubit_ext(conv, 0, ra, 0, nbits, 1);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002984
Max32e56412017-10-16 14:58:00 +02002985 osmo_crc8gen_set_bits(&gsm0503_rach_crc6, conv, nbits, conv + nbits);
2986
2987 rach_apply_bsic(conv, bsic, nbits);
2988
2989 osmo_conv_encode(is_11bit ? &gsm0503_rach_ext : &gsm0503_rach, conv, burst);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002990
2991 return 0;
2992}
2993
2994/*
2995 * GSM SCH transcoding
2996 */
Harald Weltec6636782017-06-12 14:59:37 +02002997
Neels Hofmeyr87e45502017-06-20 00:17:59 +02002998/*! Decode the SCH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02002999 * \param[out] sb_info output buffer for SCH data
3000 * \param[in] burst Input burst data
3001 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02003002int gsm0503_sch_decode(uint8_t *sb_info, const sbit_t *burst)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003003{
3004 ubit_t conv[35];
3005 int rv;
3006
3007 osmo_conv_decode(&gsm0503_sch, burst, conv);
3008
3009 rv = osmo_crc16gen_check_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
3010 if (rv)
3011 return -1;
3012
3013 osmo_ubit2pbit_ext(sb_info, 0, conv, 0, 25, 1);
3014
3015 return 0;
3016}
3017
Neels Hofmeyr87e45502017-06-20 00:17:59 +02003018/*! Encode the SCH according to TS 05.03
Harald Weltec6636782017-06-12 14:59:37 +02003019 * \param[out] burst Caller-allocated output burst buffer
3020 * \param[in] sb_info Input SCH data
3021 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02003022int gsm0503_sch_encode(ubit_t *burst, const uint8_t *sb_info)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07003023{
3024 ubit_t conv[35];
3025
3026 osmo_pbit2ubit_ext(conv, 0, sb_info, 0, 25, 1);
3027
3028 osmo_crc16gen_set_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
3029
3030 osmo_conv_encode(&gsm0503_sch, conv, burst);
3031
3032 return 0;
3033}
Harald Weltec6636782017-06-12 14:59:37 +02003034
3035/*! @} */