blob: 703986323ab64a1bad747685eb0659469dca29fa [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 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License as published by
11 * the Free Software Foundation; either version 2 of the License, or
12 * (at your option) any later version.
13 *
14 * This program is distributed in the hope that it will be useful,
15 * but WITHOUT ANY WARRANTY; without even the implied warranty of
16 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17 * GNU General Public License for more details.
18 *
19 * You should have received a copy of the GNU General Public License along
20 * with this program; if not, write to the Free Software Foundation, Inc.,
21 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
22 */
23
24#include <stdio.h>
25#include <stdint.h>
26#include <string.h>
27#include <stdlib.h>
Maxc8cf8202017-05-22 16:07:04 +020028#include <errno.h>
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070029
30#include <osmocom/core/bits.h>
31#include <osmocom/core/conv.h>
32#include <osmocom/core/utils.h>
33#include <osmocom/core/crcgen.h>
34#include <osmocom/core/endian.h>
35
36#include <osmocom/gprs/protocol/gsm_04_60.h>
37#include <osmocom/gprs/gprs_rlc.h>
38
39#include <osmocom/gsm/protocol/gsm_04_08.h>
40#include <osmocom/gsm/gsm0503.h>
41#include <osmocom/codec/codec.h>
42
43#include <osmocom/coding/gsm0503_interleaving.h>
44#include <osmocom/coding/gsm0503_mapping.h>
45#include <osmocom/coding/gsm0503_tables.h>
46#include <osmocom/coding/gsm0503_coding.h>
47#include <osmocom/coding/gsm0503_parity.h>
48
Harald Weltec6636782017-06-12 14:59:37 +020049/*! \mainpage libosmocoding Documentation
50 *
51 * \section sec_intro Introduction
52 * This library is a collection of definitions, tables and functions
53 * implementing the GSM/GPRS/EGPRS channel coding (and decoding) as
54 * specified in 3GPP TS 05.03 / 45.003.
55 *
56 * libosmocodec is developed as part of the Osmocom (Open Source Mobile
57 * Communications) project, a community-based, collaborative development
58 * project to create Free and Open Source implementations of mobile
59 * communications systems. For more information about Osmocom, please
60 * see https://osmocom.org/
61 *
62 * \section sec_copyright Copyright and License
63 * Copyright © 2013 by Andreas Eversberg\n
64 * Copyright © 2015 by Alexander Chemeris\n
65 * Copyright © 2016 by Tom Tsou\n
66 * Documentation Copyright © 2017 by Harald Welte\n
67 * All rights reserved. \n\n
68 * The source code of libosmocoding is licensed under the terms of the GNU
69 * General Public License as published by the Free Software Foundation;
70 * either version 2 of the License, or (at your option) any later
71 * version.\n
72 * See <http://www.gnu.org/licenses/> or COPYING included in the source
73 * code package istelf.\n
74 * The information detailed here is provided AS IS with NO WARRANTY OF
75 * ANY KIND, INCLUDING THE WARRANTY OF DESIGN, MERCHANTABILITY AND
76 * FITNESS FOR A PARTICULAR PURPOSE.
77 * \n\n
78 *
79 * \section sec_tracker Homepage + Issue Tracker
80 * libosmocoding is distributed as part of libosmocore and shares its
81 * project page at http://osmocom.org/projects/libosmocore
82 *
83 * An Issue Tracker can be found at
84 * https://osmocom.org/projects/libosmocore/issues
85 *
86 * \section sec_contact Contact and Support
87 * Community-based support is available at the OpenBSC mailing list
88 * <http://lists.osmocom.org/mailman/listinfo/openbsc>\n
89 * Commercial support options available upon request from
90 * <http://sysmocom.de/>
91 */
92
93
94/*! \addtogroup coding
95 * @{
96 *
97 * \brief GSM TS 05.03 coding
98 *
99 * This module is the "master module" of libosmocoding. It uses the
100 * various other modules (mapping, parity, interleaving) in order to
101 * implement the complete channel coding (and decoding) chain for the
102 * various channel types as defined in TS 05.03 / 45.003.
103 */
104
105/*! \file gsm0503_coding.c */
106
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700107/*
108 * EGPRS coding limits
109 */
110
111/* Max header size with parity bits */
112#define EGPRS_HDR_UPP_MAX 54
113
114/* Max encoded header size */
115#define EGPRS_HDR_C_MAX 162
116
117/* Max punctured header size */
118#define EGPRS_HDR_HC_MAX 160
119
120/* Max data block size with parity bits */
121#define EGPRS_DATA_U_MAX 612
122
123/* Max encoded data block size */
124#define EGPRS_DATA_C_MAX 1836
125
126/* Max single block punctured data size */
127#define EGPRS_DATA_DC_MAX 1248
128
129/* Dual block punctured data size */
130#define EGPRS_DATA_C1 612
131#define EGPRS_DATA_C2 EGPRS_DATA_C1
132
133/* TS 101318 Chapter 5.1: 260 bits + 4bit sig */
134#define GSM_FR_BYTES 33
135/* TS 101318 Chapter 5.2: 112 bits, no sig */
136#define GSM_HR_BYTES 14
137/* TS 101318 Chapter 5.3: 244 bits + 4bit sig */
138#define GSM_EFR_BYTES 31
139
Harald Weltec6636782017-06-12 14:59:37 +0200140/*! \brief union across the three different EGPRS Uplink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700141union gprs_rlc_ul_hdr_egprs {
142 struct gprs_rlc_ul_header_egprs_1 type1;
143 struct gprs_rlc_ul_header_egprs_2 type2;
144 struct gprs_rlc_ul_header_egprs_3 type3;
145};
146
Harald Weltec6636782017-06-12 14:59:37 +0200147/*! \brief union across the three different EGPRS Downlink header types */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700148union gprs_rlc_dl_hdr_egprs {
149 struct gprs_rlc_dl_header_egprs_1 type1;
150 struct gprs_rlc_dl_header_egprs_2 type2;
151 struct gprs_rlc_dl_header_egprs_3 type3;
152};
153
Harald Weltec6636782017-06-12 14:59:37 +0200154/*! \brief Structure describing a Modulation and Coding Scheme */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700155struct gsm0503_mcs_code {
Harald Weltec6636782017-06-12 14:59:37 +0200156 /*! \brief Modulation and Coding Scheme (MSC) number */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700157 uint8_t mcs;
Harald Weltec6636782017-06-12 14:59:37 +0200158 /*! \brief Length of Uplink Stealing Flag (USF) in bits */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700159 uint8_t usf_len;
160
161 /* Header coding */
Harald Weltec6636782017-06-12 14:59:37 +0200162 /*! \brief Length of header (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700163 uint8_t hdr_len;
Harald Weltec6636782017-06-12 14:59:37 +0200164 /*! \brief Length of header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700165 uint8_t hdr_code_len;
Harald Weltec6636782017-06-12 14:59:37 +0200166 /*! \brief Length of header code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700167 uint8_t hdr_punc_len;
Harald Weltec6636782017-06-12 14:59:37 +0200168 /*! \brief header convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700169 const struct osmo_conv_code *hdr_conv;
Harald Weltec6636782017-06-12 14:59:37 +0200170 /*! \brief header puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700171 const uint8_t *hdr_punc;
172
173 /* Data coding */
Harald Weltec6636782017-06-12 14:59:37 +0200174 /*! \brief length of data (bits) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700175 uint16_t data_len;
Harald Weltec6636782017-06-12 14:59:37 +0200176 /*! \brief length of data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700177 uint16_t data_code_len;
Harald Weltec6636782017-06-12 14:59:37 +0200178 /*! \brief length of data code puncturing sequence */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700179 uint16_t data_punc_len;
Harald Weltec6636782017-06-12 14:59:37 +0200180 /*! \brief data convolutional code */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700181 const struct osmo_conv_code *data_conv;
Harald Weltec6636782017-06-12 14:59:37 +0200182 /*! \brief data puncturing sequences */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700183 const uint8_t *data_punc[3];
184};
185
186/*
187 * EGPRS UL coding parameters
188 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200189const struct gsm0503_mcs_code gsm0503_mcs_ul_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700190 {
191 .mcs = EGPRS_MCS0,
192 },
193 {
194 .mcs = EGPRS_MCS1,
195 .hdr_len = 31,
196 .hdr_code_len = 117,
197 .hdr_punc_len = 80,
198 .hdr_conv = &gsm0503_mcs1_ul_hdr,
199 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
200
201 .data_len = 178,
202 .data_code_len = 588,
203 .data_punc_len = 372,
204 .data_conv = &gsm0503_mcs1,
205 .data_punc = {
206 gsm0503_puncture_mcs1_p1,
207 gsm0503_puncture_mcs1_p2,
208 NULL,
209 },
210 },
211 {
212 .mcs = EGPRS_MCS2,
213 .hdr_len = 31,
214 .hdr_code_len = 117,
215 .hdr_punc_len = 80,
216 .hdr_conv = &gsm0503_mcs1_ul_hdr,
217 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
218
219 .data_len = 226,
220 .data_code_len = 732,
221 .data_punc_len = 372,
222 .data_conv = &gsm0503_mcs2,
223 .data_punc = {
224 gsm0503_puncture_mcs2_p1,
225 gsm0503_puncture_mcs2_p2,
226 NULL,
227 },
228 },
229 {
230 .mcs = EGPRS_MCS3,
231 .hdr_len = 31,
232 .hdr_code_len = 117,
233 .hdr_punc_len = 80,
234 .hdr_conv = &gsm0503_mcs1_ul_hdr,
235 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
236
237 .data_len = 298,
238 .data_code_len = 948,
239 .data_punc_len = 372,
240 .data_conv = &gsm0503_mcs3,
241 .data_punc = {
242 gsm0503_puncture_mcs3_p1,
243 gsm0503_puncture_mcs3_p2,
244 gsm0503_puncture_mcs3_p3,
245 },
246 },
247 {
248 .mcs = EGPRS_MCS4,
249 .hdr_len = 31,
250 .hdr_code_len = 117,
251 .hdr_punc_len = 80,
252 .hdr_conv = &gsm0503_mcs1_ul_hdr,
253 .hdr_punc = gsm0503_puncture_mcs1_ul_hdr,
254
255 .data_len = 354,
256 .data_code_len = 1116,
257 .data_punc_len = 372,
258 .data_conv = &gsm0503_mcs4,
259 .data_punc = {
260 gsm0503_puncture_mcs4_p1,
261 gsm0503_puncture_mcs4_p2,
262 gsm0503_puncture_mcs4_p3,
263 },
264 },
265 {
266 .mcs = EGPRS_MCS5,
267 .hdr_len = 37,
268 .hdr_code_len = 135,
269 .hdr_punc_len = 136,
270 .hdr_conv = &gsm0503_mcs5_ul_hdr,
271 .hdr_punc = NULL,
272
273 .data_len = 450,
274 .data_code_len = 1404,
275 .data_punc_len = 1248,
276 .data_conv = &gsm0503_mcs5,
277 .data_punc = {
278 gsm0503_puncture_mcs5_p1,
279 gsm0503_puncture_mcs5_p2,
280 NULL,
281 },
282 },
283 {
284 .mcs = EGPRS_MCS6,
285 .hdr_len = 37,
286 .hdr_code_len = 135,
287 .hdr_punc_len = 136,
288 .hdr_conv = &gsm0503_mcs5_ul_hdr,
289 .hdr_punc = NULL,
290
291 .data_len = 594,
292 .data_code_len = 1836,
293 .data_punc_len = 1248,
294 .data_conv = &gsm0503_mcs6,
295 .data_punc = {
296 gsm0503_puncture_mcs6_p1,
297 gsm0503_puncture_mcs6_p2,
298 NULL,
299 },
300 },
301 {
302 .mcs = EGPRS_MCS7,
303 .hdr_len = 46,
304 .hdr_code_len = 162,
305 .hdr_punc_len = 160,
306 .hdr_conv = &gsm0503_mcs7_ul_hdr,
307 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
308
309 .data_len = 900,
310 .data_code_len = 1404,
311 .data_punc_len = 612,
312 .data_conv = &gsm0503_mcs7,
313 .data_punc = {
314 gsm0503_puncture_mcs7_p1,
315 gsm0503_puncture_mcs7_p2,
316 gsm0503_puncture_mcs7_p3,
317 }
318 },
319 {
320 .mcs = EGPRS_MCS8,
321 .hdr_len = 46,
322 .hdr_code_len = 162,
323 .hdr_punc_len = 160,
324 .hdr_conv = &gsm0503_mcs7_ul_hdr,
325 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
326
327 .data_len = 1092,
328 .data_code_len = 1692,
329 .data_punc_len = 612,
330 .data_conv = &gsm0503_mcs8,
331 .data_punc = {
332 gsm0503_puncture_mcs8_p1,
333 gsm0503_puncture_mcs8_p2,
334 gsm0503_puncture_mcs8_p3,
335 }
336 },
337 {
338 .mcs = EGPRS_MCS9,
339 .hdr_len = 46,
340 .hdr_code_len = 162,
341 .hdr_punc_len = 160,
342 .hdr_conv = &gsm0503_mcs7_ul_hdr,
343 .hdr_punc = gsm0503_puncture_mcs7_ul_hdr,
344
345 .data_len = 1188,
346 .data_code_len = 1836,
347 .data_punc_len = 612,
348 .data_conv = &gsm0503_mcs9,
349 .data_punc = {
350 gsm0503_puncture_mcs9_p1,
351 gsm0503_puncture_mcs9_p2,
352 gsm0503_puncture_mcs9_p3,
353 }
354 },
355};
356
357/*
358 * EGPRS DL coding parameters
359 */
Harald Welte2f984ea2017-06-12 15:05:21 +0200360const struct gsm0503_mcs_code gsm0503_mcs_dl_codes[EGPRS_NUM_MCS] = {
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700361 {
362 .mcs = EGPRS_MCS0,
363 },
364 {
365 .mcs = EGPRS_MCS1,
366 .usf_len = 3,
367 .hdr_len = 28,
368 .hdr_code_len = 108,
369 .hdr_punc_len = 68,
370 .hdr_conv = &gsm0503_mcs1_dl_hdr,
371 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
372
373 .data_len = 178,
374 .data_code_len = 588,
375 .data_punc_len = 372,
376 .data_conv = &gsm0503_mcs1,
377 .data_punc = {
378 gsm0503_puncture_mcs1_p1,
379 gsm0503_puncture_mcs1_p2,
380 NULL,
381 },
382 },
383 {
384 .mcs = EGPRS_MCS2,
385 .usf_len = 3,
386 .hdr_len = 28,
387 .hdr_code_len = 108,
388 .hdr_punc_len = 68,
389 .hdr_conv = &gsm0503_mcs1_dl_hdr,
390 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
391
392 .data_len = 226,
393 .data_code_len = 732,
394 .data_punc_len = 372,
395 .data_conv = &gsm0503_mcs2,
396 .data_punc = {
397 gsm0503_puncture_mcs2_p1,
398 gsm0503_puncture_mcs2_p2,
399 NULL,
400 },
401 },
402 {
403 .mcs = EGPRS_MCS3,
404 .usf_len = 3,
405 .hdr_len = 28,
406 .hdr_code_len = 108,
407 .hdr_punc_len = 68,
408 .hdr_conv = &gsm0503_mcs1_dl_hdr,
409 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
410
411 .data_len = 298,
412 .data_code_len = 948,
413 .data_punc_len = 372,
414 .data_conv = &gsm0503_mcs3,
415 .data_punc = {
416 gsm0503_puncture_mcs3_p1,
417 gsm0503_puncture_mcs3_p2,
418 gsm0503_puncture_mcs3_p3,
419 },
420 },
421 {
422 .mcs = EGPRS_MCS4,
423 .usf_len = 3,
424 .hdr_len = 28,
425 .hdr_code_len = 108,
426 .hdr_punc_len = 68,
427 .hdr_conv = &gsm0503_mcs1_dl_hdr,
428 .hdr_punc = gsm0503_puncture_mcs1_dl_hdr,
429
430 .data_len = 354,
431 .data_code_len = 1116,
432 .data_punc_len = 372,
433 .data_conv = &gsm0503_mcs4,
434 .data_punc = {
435 gsm0503_puncture_mcs4_p1,
436 gsm0503_puncture_mcs4_p2,
437 gsm0503_puncture_mcs4_p3,
438 },
439 },
440 {
441 .mcs = EGPRS_MCS5,
442 .usf_len = 3,
443 .hdr_len = 25,
444 .hdr_code_len = 99,
445 .hdr_punc_len = 100,
446 .hdr_conv = &gsm0503_mcs5_dl_hdr,
447 .hdr_punc = NULL,
448
449 .data_len = 450,
450 .data_code_len = 1404,
451 .data_punc_len = 1248,
452 .data_conv = &gsm0503_mcs5,
453 .data_punc = {
454 gsm0503_puncture_mcs5_p1,
455 gsm0503_puncture_mcs5_p2,
456 NULL,
457 },
458 },
459 {
460 .mcs = EGPRS_MCS6,
461 .usf_len = 3,
462 .hdr_len = 25,
463 .hdr_code_len = 99,
464 .hdr_punc_len = 100,
465 .hdr_conv = &gsm0503_mcs5_dl_hdr,
466 .hdr_punc = NULL,
467
468 .data_len = 594,
469 .data_code_len = 1836,
470 .data_punc_len = 1248,
471 .data_conv = &gsm0503_mcs6,
472 .data_punc = {
473 gsm0503_puncture_mcs6_p1,
474 gsm0503_puncture_mcs6_p2,
475 NULL,
476 },
477 },
478 {
479 .mcs = EGPRS_MCS7,
480 .usf_len = 3,
481 .hdr_len = 37,
482 .hdr_code_len = 135,
483 .hdr_punc_len = 124,
484 .hdr_conv = &gsm0503_mcs7_dl_hdr,
485 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
486
487 .data_len = 900,
488 .data_code_len = 1404,
489 .data_punc_len = 612,
490 .data_conv = &gsm0503_mcs7,
491 .data_punc = {
492 gsm0503_puncture_mcs7_p1,
493 gsm0503_puncture_mcs7_p2,
494 gsm0503_puncture_mcs7_p3,
495 }
496 },
497 {
498 .mcs = EGPRS_MCS8,
499 .usf_len = 3,
500 .hdr_len = 37,
501 .hdr_code_len = 135,
502 .hdr_punc_len = 124,
503 .hdr_conv = &gsm0503_mcs7_dl_hdr,
504 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
505
506 .data_len = 1092,
507 .data_code_len = 1692,
508 .data_punc_len = 612,
509 .data_conv = &gsm0503_mcs8,
510 .data_punc = {
511 gsm0503_puncture_mcs8_p1,
512 gsm0503_puncture_mcs8_p2,
513 gsm0503_puncture_mcs8_p3,
514 }
515 },
516 {
517 .mcs = EGPRS_MCS9,
518 .usf_len = 3,
519 .hdr_len = 37,
520 .hdr_code_len = 135,
521 .hdr_punc_len = 124,
522 .hdr_conv = &gsm0503_mcs7_dl_hdr,
523 .hdr_punc = gsm0503_puncture_mcs7_dl_hdr,
524
525 .data_len = 1188,
526 .data_code_len = 1836,
527 .data_punc_len = 612,
528 .data_conv = &gsm0503_mcs9,
529 .data_punc = {
530 gsm0503_puncture_mcs9_p1,
531 gsm0503_puncture_mcs9_p2,
532 gsm0503_puncture_mcs9_p3,
533 }
534 },
535};
536
Harald Weltec6636782017-06-12 14:59:37 +0200537/*! \brief Convolutional Decode + compute BER
538 * \param[in] code Description of Convolutional Code
539 * \param[in] input Input soft-bits (-127...127)
540 * \param[out] output bits
541 * \param[out] n_errors Number of bit-errors
542 * \param[out] n_bits_total Number of bits
543 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700544static int osmo_conv_decode_ber(const struct osmo_conv_code *code,
545 const sbit_t *input, ubit_t *output,
546 int *n_errors, int *n_bits_total)
547{
548 int res, i, coded_len;
549 ubit_t recoded[EGPRS_DATA_C_MAX];
550
551 res = osmo_conv_decode(code, input, output);
552
553 if (n_bits_total || n_errors) {
554 coded_len = osmo_conv_encode(code, output, recoded);
555 OSMO_ASSERT(sizeof(recoded) / sizeof(recoded[0]) >= coded_len);
556 }
557
558 /* Count bit errors */
559 if (n_errors) {
560 *n_errors = 0;
561 for (i = 0; i < coded_len; i++) {
562 if (!((recoded[i] && input[i] < 0) ||
563 (!recoded[i] && input[i] > 0)) )
564 *n_errors += 1;
565 }
566 }
567
568 if (n_bits_total)
569 *n_bits_total = coded_len;
570
571 return res;
572}
573
Harald Weltec6636782017-06-12 14:59:37 +0200574/*! \brief convenience wrapper for decoding coded bits
575 * \param[out] l2_data caller-allocated buffer for L2 Frame
576 * \param[in] cB 456 coded (soft) bits as per TS 05.03 4.1.3
577 * \param[out] n_errors Number of detected errors
578 * \param[out] n_bits_total Number of total coded bits
579 * \returns 0 on success; -1 on CRC error */
Harald Welteb9946d32017-06-12 09:40:16 +0200580static int _xcch_decode_cB(uint8_t *l2_data, const sbit_t *cB,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700581 int *n_errors, int *n_bits_total)
582{
583 ubit_t conv[224];
584 int rv;
585
586 osmo_conv_decode_ber(&gsm0503_xcch, cB,
587 conv, n_errors, n_bits_total);
588
589 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
590 conv, 184, conv + 184);
591 if (rv)
592 return -1;
593
594 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
595
596 return 0;
597}
598
Harald Weltec6636782017-06-12 14:59:37 +0200599/*! \brief convenience wrapper for encoding to coded bits
600 * \param[out] cB caller-allocated buffer for 456 coded bits as per TS 05.03 4.1.3
601 * \param[out] l2_data to-be-encoded L2 Frame
602 * \returns 0 */
Harald Welteb9946d32017-06-12 09:40:16 +0200603static int _xcch_encode_cB(ubit_t *cB, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700604{
605 ubit_t conv[224];
606
607 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
608
609 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
610
611 osmo_conv_encode(&gsm0503_xcch, conv, cB);
612
613 return 0;
614}
615
616/*
617 * GSM xCCH block transcoding
618 */
Harald Weltec6636782017-06-12 14:59:37 +0200619
620/*! \brief Decoding of xCCH data from bursts to L2 frame
621 * \param[out] l2_data caller-allocated output data buffer
622 * \param[in] bursts four GSM bursts in soft-bits
623 * \param[out] n_errors Number of detected errors
624 * \param[out] n_bits_total Number of total coded bits
625 */
Harald Welteb9946d32017-06-12 09:40:16 +0200626int gsm0503_xcch_decode(uint8_t *l2_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700627 int *n_errors, int *n_bits_total)
628{
629 sbit_t iB[456], cB[456];
630 int i;
631
632 for (i = 0; i < 4; i++)
633 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116], NULL, NULL);
634
635 gsm0503_xcch_deinterleave(cB, iB);
636
637 return _xcch_decode_cB(l2_data, cB, n_errors, n_bits_total);
638}
639
Harald Weltec6636782017-06-12 14:59:37 +0200640/*! \brief Encoding of xCCH data from L2 frame to bursts
641 * \param[out] bursts caller-allocated burst data (unpacked bits)
642 * \param[in] l2_data L2 input data (MAC block)
643 * \returns 0
644 */
Harald Welteb9946d32017-06-12 09:40:16 +0200645int gsm0503_xcch_encode(ubit_t *bursts, const uint8_t *l2_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700646{
647 ubit_t iB[456], cB[456], hl = 1, hn = 1;
648 int i;
649
650 _xcch_encode_cB(cB, l2_data);
651
652 gsm0503_xcch_interleave(cB, iB);
653
654 for (i = 0; i < 4; i++)
655 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116], &hl, &hn);
656
657 return 0;
658}
659
660/*
661 * EGPRS PDTCH UL block decoding
662 */
663
664/*
665 * Type 3 - MCS-1,2,3,4
666 * Unmapping and deinterleaving
667 */
668static int egprs_type3_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
669{
670 int i;
671 sbit_t iB[456], q[8];
672
673 for (i = 0; i < 4; i++) {
674 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
675 q + i * 2, q + i * 2 + 1);
676 }
677
678 gsm0503_mcs1_ul_deinterleave(hc, dc, iB);
679
680 return 0;
681}
682
683/*
684 * Type 2 - MCS-5,6
685 * Unmapping and deinterleaving
686 */
687static int egprs_type2_unmap(const sbit_t *bursts, sbit_t *hc, sbit_t *dc)
688{
689 int i;
690 sbit_t burst[348];
691 sbit_t hi[EGPRS_HDR_HC_MAX];
692 sbit_t di[EGPRS_DATA_DC_MAX];
693
694 for (i = 0; i < 4; i++) {
695 memcpy(burst, &bursts[i * 348], 348);
696
697 gsm0503_mcs5_burst_swap(burst);
698 gsm0503_mcs5_ul_burst_unmap(di, burst, hi, i);
699 }
700
701 gsm0503_mcs5_ul_deinterleave(hc, dc, hi, di);
702
703 return 0;
704}
705
706/*
707 * Type 1 - MCS-7,8,9
708 * Unmapping and deinterleaving - Note that MCS-7 interleaver is unique
709 */
710static int egprs_type1_unmap(const sbit_t *bursts, sbit_t *hc,
711 sbit_t *c1, sbit_t *c2, int msc)
712{
713 int i;
714 sbit_t burst[348];
715 sbit_t hi[EGPRS_HDR_HC_MAX];
716 sbit_t di[EGPRS_DATA_C1 * 2];
717
718 for (i = 0; i < 4; i++) {
719 memcpy(burst, &bursts[i * 348], 348);
720
721 gsm0503_mcs5_burst_swap(burst);
722 gsm0503_mcs7_ul_burst_unmap(di, burst, hi, i);
723 }
724
725 if (msc == EGPRS_MCS7)
726 gsm0503_mcs7_ul_deinterleave(hc, c1, c2, hi, di);
727 else
728 gsm0503_mcs8_ul_deinterleave(hc, c1, c2, hi, di);
729
730 return 0;
731}
732
733/*
734 * Decode EGPRS UL header section
735 *
736 * 1. Depuncture
737 * 2. Convolutional decoding
738 * 3. CRC check
739 */
740static int _egprs_decode_hdr(const sbit_t *hc, int mcs,
741 union gprs_rlc_ul_hdr_egprs *hdr)
742{
743 sbit_t C[EGPRS_HDR_C_MAX];
744 ubit_t upp[EGPRS_HDR_UPP_MAX];
745 int i, j, rc;
Harald Welte2f984ea2017-06-12 15:05:21 +0200746 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700747
748 code = &gsm0503_mcs_ul_codes[mcs];
749
750 /* Skip depuncturing on MCS-5,6 header */
751 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
752 memcpy(C, hc, code->hdr_code_len);
753 goto hdr_conv_decode;
754 }
755
756 if (!code->hdr_punc) {
757 /* Invalid MCS-X header puncture matrix */
758 return -1;
759 }
760
761 i = code->hdr_code_len - 1;
762 j = code->hdr_punc_len - 1;
763
764 for (; i >= 0; i--) {
765 if (!code->hdr_punc[i])
766 C[i] = hc[j--];
767 else
768 C[i] = 0;
769 }
770
771hdr_conv_decode:
772 osmo_conv_decode_ber(code->hdr_conv, C, upp, NULL, NULL);
773 rc = osmo_crc8gen_check_bits(&gsm0503_mcs_crc8_hdr, upp,
774 code->hdr_len, upp + code->hdr_len);
775 if (rc)
776 return -1;
777
778 osmo_ubit2pbit_ext((pbit_t *) hdr, 0, upp, 0, code->hdr_len, 1);
779
780 return 0;
781}
782
783/*
784 * Blind MCS header decoding based on burst length and CRC validation.
785 * Ignore 'q' value coding identification. This approach provides
786 * the strongest chance of header recovery.
787 */
788static int egprs_decode_hdr(union gprs_rlc_ul_hdr_egprs *hdr,
789 const sbit_t *bursts, uint16_t nbits)
790{
791 int rc;
792 sbit_t hc[EGPRS_HDR_HC_MAX];
793
794 if (nbits == GSM0503_GPRS_BURSTS_NBITS) {
795 /* MCS-1,2,3,4 */
796 egprs_type3_unmap(bursts, hc, NULL);
797 rc = _egprs_decode_hdr(hc, EGPRS_MCS1, hdr);
798 if (!rc)
799 return EGPRS_HDR_TYPE3;
800 } else if (nbits == GSM0503_EGPRS_BURSTS_NBITS) {
801 /* MCS-5,6 */
802 egprs_type2_unmap(bursts, hc, NULL);
803 rc = _egprs_decode_hdr(hc, EGPRS_MCS5, hdr);
804 if (!rc)
805 return EGPRS_HDR_TYPE2;
806
807 /* MCS-7,8,9 */
808 egprs_type1_unmap(bursts, hc, NULL, NULL, EGPRS_MCS7);
809 rc = _egprs_decode_hdr(hc, EGPRS_MCS7, hdr);
810 if (!rc)
811 return EGPRS_HDR_TYPE1;
812 }
813
814 return -1;
815}
816
817/*
818 * Parse EGPRS UL header for coding and puncturing scheme (CPS)
819 *
820 * Type 1 - MCS-7,8,9
821 * Type 2 - MCS-5,6
822 * Type 3 - MCS-1,2,3,4
823 */
824static int egprs_parse_ul_cps(struct egprs_cps *cps,
825 union gprs_rlc_ul_hdr_egprs *hdr, int type)
826{
827 uint8_t bits;
828
829 switch (type) {
830 case EGPRS_HDR_TYPE1:
831 bits = hdr->type1.cps;
832 break;
833 case EGPRS_HDR_TYPE2:
834 bits = (hdr->type2.cps_lo << 2) | hdr->type2.cps_hi;
835 break;
836 case EGPRS_HDR_TYPE3:
837 bits = (hdr->type3.cps_lo << 2) | hdr->type3.cps_hi;
838 break;
839 default:
840 return -1;
841 }
842
843 return egprs_get_cps(cps, type, bits);
844}
845
846/*
847 * Decode EGPRS UL data section
848 *
849 * 1. Depuncture
850 * 2. Convolutional decoding
851 * 3. CRC check
852 * 4. Block combining (MCS-7,8,9 only)
853 */
Harald Welteb9946d32017-06-12 09:40:16 +0200854static int egprs_decode_data(uint8_t *l2_data, const sbit_t *c,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700855 int mcs, int p, int blk, int *n_errors, int *n_bits_total)
856{
857 ubit_t u[EGPRS_DATA_U_MAX];
858 sbit_t C[EGPRS_DATA_C_MAX];
859
860 int i, j, rc, data_len;
Harald Welte2f984ea2017-06-12 15:05:21 +0200861 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700862
863 if (blk && mcs < EGPRS_MCS7) {
864 /* Invalid MCS-X block state */
865 return -1;
866 }
867
868 code = &gsm0503_mcs_ul_codes[mcs];
869 if (!code->data_punc[p]) {
870 /* Invalid MCS-X data puncture matrix */
871 return -1;
872 }
873
874 /*
875 * MCS-1,6 - single block processing
876 * MCS-7,9 - dual block processing
877 */
878 if (mcs >= EGPRS_MCS7)
879 data_len = code->data_len / 2;
880 else
881 data_len = code->data_len;
882
883 i = code->data_code_len - 1;
884 j = code->data_punc_len - 1;
885
886 for (; i >= 0; i--) {
887 if (!code->data_punc[p][i])
888 C[i] = c[j--];
889 else
890 C[i] = 0;
891 }
892
893 osmo_conv_decode_ber(code->data_conv, C, u, n_errors, n_bits_total);
894 rc = osmo_crc16gen_check_bits(&gsm0503_mcs_crc12, u,
895 data_len, u + data_len);
896 if (rc)
897 return -1;
898
899 /* Offsets output pointer on the second block of Type 1 MCS */
900 osmo_ubit2pbit_ext(l2_data, code->hdr_len + blk * data_len,
901 u, 0, data_len, 1);
902
903 /* Return the number of bytes required for the bit message */
904 return NUM_BYTES(code->hdr_len + code->data_len);
905}
906
Harald Weltec6636782017-06-12 14:59:37 +0200907/*! \brief Decode EGPRS UL message
908 * 1. Header section decoding
909 * 2. Extract CPS settings
910 * 3. Burst unmapping and deinterleaving
911 * 4. Data section decoding
912 * \param[out] l2_data caller-allocated buffer for L2 Frame
913 * \param[in] bursts burst input data as soft unpacked bits
914 * \param[in] nbits number of bits in \a bursts
915 * \param usf_p unused argument ?!?
916 * \param[out] n_errors number of detected bit-errors
917 * \param[out] n_bits_total total number of dcoded bits
918 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +0200919int gsm0503_pdtch_egprs_decode(uint8_t *l2_data, const sbit_t *bursts, uint16_t nbits,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700920 uint8_t *usf_p, int *n_errors, int *n_bits_total)
921{
922 sbit_t dc[EGPRS_DATA_DC_MAX];
923 sbit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
924 int type, rc;
925 struct egprs_cps cps;
926 union gprs_rlc_ul_hdr_egprs *hdr;
927
928 if ((nbits != GSM0503_GPRS_BURSTS_NBITS) &&
929 (nbits != GSM0503_EGPRS_BURSTS_NBITS)) {
930 /* Invalid EGPRS bit length */
Maxc8cf8202017-05-22 16:07:04 +0200931 return -EOVERFLOW;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700932 }
933
934 hdr = (union gprs_rlc_ul_hdr_egprs *) l2_data;
935 type = egprs_decode_hdr(hdr, bursts, nbits);
936 if (egprs_parse_ul_cps(&cps, hdr, type) < 0)
Maxc8cf8202017-05-22 16:07:04 +0200937 return -EIO;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700938
939 switch (cps.mcs) {
Maxc8cf8202017-05-22 16:07:04 +0200940 case EGPRS_MCS0:
941 return -ENOTSUP;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700942 case EGPRS_MCS1:
943 case EGPRS_MCS2:
944 case EGPRS_MCS3:
945 case EGPRS_MCS4:
946 egprs_type3_unmap(bursts, NULL, dc);
947 break;
948 case EGPRS_MCS5:
949 case EGPRS_MCS6:
950 egprs_type2_unmap(bursts, NULL, dc);
951 break;
952 case EGPRS_MCS7:
953 case EGPRS_MCS8:
954 case EGPRS_MCS9:
955 egprs_type1_unmap(bursts, NULL, c1, c2, cps.mcs);
956 break;
957 default:
958 /* Invalid MCS-X */
Maxc8cf8202017-05-22 16:07:04 +0200959 return -EINVAL;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700960 }
961
962 /* Decode MCS-X block, where X = cps.mcs */
963 if (cps.mcs < EGPRS_MCS7) {
964 rc = egprs_decode_data(l2_data, dc, cps.mcs, cps.p[0],
965 0, n_errors, n_bits_total);
966 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200967 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700968 } else {
969 /* MCS-7,8,9 block 1 */
970 rc = egprs_decode_data(l2_data, c1, cps.mcs, cps.p[0],
971 0, n_errors, n_bits_total);
972 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200973 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700974
975 /* MCS-7,8,9 block 2 */
976 rc = egprs_decode_data(l2_data, c2, cps.mcs, cps.p[1],
977 1, n_errors, n_bits_total);
978 if (rc < 0)
Maxc8cf8202017-05-22 16:07:04 +0200979 return -EFAULT;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700980 }
981
982 return rc;
983}
984
985/*
986 * GSM PDTCH block transcoding
987 */
988
Harald Weltec6636782017-06-12 14:59:37 +0200989/*! \brief Decode GPRS PDTCH
990 * \param[out] l2_data caller-allocated buffer for L2 Frame
991 * \param[in] bursts burst input data as soft unpacked bits
992 * \param[out] usf_p uplink stealing flag
993 * \param[out] n_errors number of detected bit-errors
994 * \param[out] n_bits_total total number of dcoded bits
995 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +0200996int gsm0503_pdtch_decode(uint8_t *l2_data, const sbit_t *bursts, uint8_t *usf_p,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700997 int *n_errors, int *n_bits_total)
998{
999 sbit_t iB[456], cB[676], hl_hn[8];
1000 ubit_t conv[456];
1001 int i, j, k, rv, best = 0, cs = 0, usf = 0; /* make GCC happy */
1002
1003 for (i = 0; i < 4; i++)
1004 gsm0503_xcch_burst_unmap(&iB[i * 114], &bursts[i * 116],
1005 hl_hn + i * 2, hl_hn + i * 2 + 1);
1006
1007 for (i = 0; i < 4; i++) {
1008 for (j = 0, k = 0; j < 8; j++)
1009 k += abs(((int)gsm0503_pdtch_hl_hn_sbit[i][j]) - ((int)hl_hn[j]));
1010
1011 if (i == 0 || k < best) {
1012 best = k;
1013 cs = i + 1;
1014 }
1015 }
1016
1017 gsm0503_xcch_deinterleave(cB, iB);
1018
1019 switch (cs) {
1020 case 1:
1021 osmo_conv_decode_ber(&gsm0503_xcch, cB,
1022 conv, n_errors, n_bits_total);
1023
1024 rv = osmo_crc64gen_check_bits(&gsm0503_fire_crc40,
1025 conv, 184, conv + 184);
1026 if (rv)
1027 return -1;
1028
1029 osmo_ubit2pbit_ext(l2_data, 0, conv, 0, 184, 1);
1030
1031 return 23;
1032 case 2:
1033 for (i = 587, j = 455; i >= 0; i--) {
1034 if (!gsm0503_puncture_cs2[i])
1035 cB[i] = cB[j--];
1036 else
1037 cB[i] = 0;
1038 }
1039
1040 osmo_conv_decode_ber(&gsm0503_cs2_np, cB,
1041 conv, n_errors, n_bits_total);
1042
1043 for (i = 0; i < 8; i++) {
1044 for (j = 0, k = 0; j < 6; j++)
1045 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1046
1047 if (i == 0 || k < best) {
1048 best = k;
1049 usf = i;
1050 }
1051 }
1052
1053 conv[3] = usf & 1;
1054 conv[4] = (usf >> 1) & 1;
1055 conv[5] = (usf >> 2) & 1;
1056 if (usf_p)
1057 *usf_p = usf;
1058
1059 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1060 conv + 3, 271, conv + 3 + 271);
1061 if (rv)
1062 return -1;
1063
1064 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 271, 1);
1065
1066 return 34;
1067 case 3:
1068 for (i = 675, j = 455; i >= 0; i--) {
1069 if (!gsm0503_puncture_cs3[i])
1070 cB[i] = cB[j--];
1071 else
1072 cB[i] = 0;
1073 }
1074
1075 osmo_conv_decode_ber(&gsm0503_cs3_np, cB,
1076 conv, n_errors, n_bits_total);
1077
1078 for (i = 0; i < 8; i++) {
1079 for (j = 0, k = 0; j < 6; j++)
1080 k += abs(((int)gsm0503_usf2six[i][j]) - ((int)conv[j]));
1081
1082 if (i == 0 || k < best) {
1083 best = k;
1084 usf = i;
1085 }
1086 }
1087
1088 conv[3] = usf & 1;
1089 conv[4] = (usf >> 1) & 1;
1090 conv[5] = (usf >> 2) & 1;
1091 if (usf_p)
1092 *usf_p = usf;
1093
1094 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1095 conv + 3, 315, conv + 3 + 315);
1096 if (rv)
1097 return -1;
1098
1099 osmo_ubit2pbit_ext(l2_data, 0, conv, 3, 315, 1);
1100
1101 return 40;
1102 case 4:
1103 for (i = 12; i < 456; i++)
1104 conv[i] = (cB[i] < 0) ? 1 : 0;
1105
1106 for (i = 0; i < 8; i++) {
1107 for (j = 0, k = 0; j < 12; j++)
1108 k += abs(((int)gsm0503_usf2twelve_sbit[i][j]) - ((int)cB[j]));
1109
1110 if (i == 0 || k < best) {
1111 best = k;
1112 usf = i;
1113 }
1114 }
1115
1116 conv[9] = usf & 1;
1117 conv[10] = (usf >> 1) & 1;
1118 conv[11] = (usf >> 2) & 1;
1119 if (usf_p)
1120 *usf_p = usf;
1121
1122 rv = osmo_crc16gen_check_bits(&gsm0503_cs234_crc16,
1123 conv + 9, 431, conv + 9 + 431);
1124 if (rv) {
1125 *n_bits_total = 456 - 12;
1126 *n_errors = *n_bits_total;
1127 return -1;
1128 }
1129
1130 *n_bits_total = 456 - 12;
1131 *n_errors = 0;
1132
1133 osmo_ubit2pbit_ext(l2_data, 0, conv, 9, 431, 1);
1134
1135 return 54;
1136 default:
1137 *n_bits_total = 0;
1138 *n_errors = 0;
1139 break;
1140 }
1141
1142 return -1;
1143}
1144
1145/*
1146 * EGPRS PDTCH UL block encoding
1147 */
Harald Welteb9946d32017-06-12 09:40:16 +02001148static int egprs_type3_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001149{
1150 int i;
1151 ubit_t iB[456];
1152 const ubit_t *hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1153
1154 gsm0503_mcs1_dl_interleave(gsm0503_usf2six[usf], hc, dc, iB);
1155
1156 for (i = 0; i < 4; i++) {
1157 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1158 hl_hn + i * 2, hl_hn + i * 2 + 1);
1159 }
1160
1161 return 0;
1162}
1163
Harald Welteb9946d32017-06-12 09:40:16 +02001164static int egprs_type2_map(ubit_t *bursts, const ubit_t *hc, const ubit_t *dc, int usf)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001165{
1166 int i;
1167 const ubit_t *up;
1168 ubit_t hi[EGPRS_HDR_HC_MAX];
1169 ubit_t di[EGPRS_DATA_DC_MAX];
1170
1171 gsm0503_mcs5_dl_interleave(hc, dc, hi, di);
1172 up = gsm0503_mcs5_usf_precode_table[usf];
1173
1174 for (i = 0; i < 4; i++) {
1175 gsm0503_mcs5_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1176 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1177 }
1178
1179 return 0;
1180}
1181
Harald Welteb9946d32017-06-12 09:40:16 +02001182static int egprs_type1_map(ubit_t *bursts, const ubit_t *hc,
1183 const ubit_t *c1, const ubit_t *c2, int usf, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001184{
1185 int i;
1186 const ubit_t *up;
1187 ubit_t hi[EGPRS_HDR_HC_MAX];
1188 ubit_t di[EGPRS_DATA_C1 * 2];
1189
1190 if (mcs == EGPRS_MCS7)
1191 gsm0503_mcs7_dl_interleave(hc, c1, c2, hi, di);
1192 else
1193 gsm0503_mcs8_dl_interleave(hc, c1, c2, hi, di);
1194
1195 up = gsm0503_mcs5_usf_precode_table[usf];
1196
1197 for (i = 0; i < 4; i++) {
1198 gsm0503_mcs7_dl_burst_map(di, &bursts[i * 348], hi, up, i);
1199 gsm0503_mcs5_burst_swap((sbit_t *) &bursts[i * 348]);
1200 }
1201
1202 return 0;
1203}
1204
Harald Welteb9946d32017-06-12 09:40:16 +02001205static int egprs_encode_hdr(ubit_t *hc, const uint8_t *l2_data, int mcs)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001206{
1207 int i, j;
1208 ubit_t upp[EGPRS_HDR_UPP_MAX], C[EGPRS_HDR_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001209 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001210
1211 code = &gsm0503_mcs_dl_codes[mcs];
1212
1213 osmo_pbit2ubit_ext(upp, 0, l2_data, code->usf_len, code->hdr_len, 1);
1214 osmo_crc8gen_set_bits(&gsm0503_mcs_crc8_hdr, upp,
1215 code->hdr_len, upp + code->hdr_len);
1216
1217 osmo_conv_encode(code->hdr_conv, upp, C);
1218
1219 /* MCS-5,6 header direct puncture instead of table */
1220 if ((mcs == EGPRS_MCS5) || (mcs == EGPRS_MCS6)) {
1221 memcpy(hc, C, code->hdr_code_len);
1222 hc[99] = hc[98];
1223 return 0;
1224 }
1225
1226 if (!code->hdr_punc) {
1227 /* Invalid MCS-X header puncture matrix */
1228 return -1;
1229 }
1230
1231 for (i = 0, j = 0; i < code->hdr_code_len; i++) {
1232 if (!code->hdr_punc[i])
1233 hc[j++] = C[i];
1234 }
1235
1236 return 0;
1237}
1238
Harald Welteb9946d32017-06-12 09:40:16 +02001239static int egprs_encode_data(ubit_t *c, const uint8_t *l2_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001240 int mcs, int p, int blk)
1241{
1242 int i, j, data_len;
1243 ubit_t u[EGPRS_DATA_U_MAX], C[EGPRS_DATA_C_MAX];
Harald Welte2f984ea2017-06-12 15:05:21 +02001244 const struct gsm0503_mcs_code *code;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001245
1246 code = &gsm0503_mcs_dl_codes[mcs];
1247
1248 /*
1249 * Dual block - MCS-7,8,9
1250 * Single block - MCS-1,2,3,4,5,6
1251 */
1252 if (mcs >= EGPRS_MCS7)
1253 data_len = code->data_len / 2;
1254 else
1255 data_len = code->data_len;
1256
1257 osmo_pbit2ubit_ext(u, 0, l2_data,
1258 code->usf_len + code->hdr_len + blk * data_len, data_len, 1);
1259
1260 osmo_crc16gen_set_bits(&gsm0503_mcs_crc12, u, data_len, u + data_len);
1261
1262 osmo_conv_encode(code->data_conv, u, C);
1263
1264 if (!code->data_punc[p]) {
1265 /* Invalid MCS-X data puncture matrix */
1266 return -1;
1267 }
1268
1269 for (i = 0, j = 0; i < code->data_code_len; i++) {
1270 if (!code->data_punc[p][i])
1271 c[j++] = C[i];
1272 }
1273
1274 return 0;
1275}
1276
1277/*
1278 * Parse EGPRS DL header for coding and puncturing scheme (CPS)
1279 *
1280 * Type 1 - MCS-7,8,9
1281 * Type 2 - MCS-5,6
1282 * Type 3 - MCS-1,2,3,4
1283 */
1284static int egprs_parse_dl_cps(struct egprs_cps *cps,
Harald Welteb9946d32017-06-12 09:40:16 +02001285 const union gprs_rlc_dl_hdr_egprs *hdr, int type)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001286{
1287 uint8_t bits;
1288
1289 switch (type) {
1290 case EGPRS_HDR_TYPE1:
1291 bits = hdr->type1.cps;
1292 break;
1293 case EGPRS_HDR_TYPE2:
1294 bits = hdr->type2.cps;
1295 break;
1296 case EGPRS_HDR_TYPE3:
1297 bits = hdr->type3.cps;
1298 break;
1299 default:
1300 return -1;
1301 }
1302
1303 return egprs_get_cps(cps, type, bits);
1304}
1305
Harald Weltec6636782017-06-12 14:59:37 +02001306/*! \brief EGPRS DL message encoding
1307 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1308 * \param[in] l2_data L2 (MAC) block to be encoded
1309 * \param[in] l2_len length of l2_data in bytes, used to determine MCS
1310 * \returns 0 on success; negative on error */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001311int gsm0503_pdtch_egprs_encode(ubit_t *bursts,
Harald Welteb9946d32017-06-12 09:40:16 +02001312 const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001313{
1314 ubit_t hc[EGPRS_DATA_C_MAX], dc[EGPRS_DATA_DC_MAX];
1315 ubit_t c1[EGPRS_DATA_C1], c2[EGPRS_DATA_C2];
1316 uint8_t mcs;
1317 struct egprs_cps cps;
1318 union gprs_rlc_dl_hdr_egprs *hdr;
1319
1320 switch (l2_len) {
1321 case 27:
1322 mcs = EGPRS_MCS1;
1323 break;
1324 case 33:
1325 mcs = EGPRS_MCS2;
1326 break;
1327 case 42:
1328 mcs = EGPRS_MCS3;
1329 break;
1330 case 49:
1331 mcs = EGPRS_MCS4;
1332 break;
1333 case 60:
1334 mcs = EGPRS_MCS5;
1335 break;
1336 case 78:
1337 mcs = EGPRS_MCS6;
1338 break;
1339 case 118:
1340 mcs = EGPRS_MCS7;
1341 break;
1342 case 142:
1343 mcs = EGPRS_MCS8;
1344 break;
1345 case 154:
1346 mcs = EGPRS_MCS9;
1347 break;
1348 default:
1349 return -1;
1350 }
1351
1352 /* Read header for USF and puncturing matrix selection. */
1353 hdr = (union gprs_rlc_dl_hdr_egprs *) l2_data;
1354
1355 switch (mcs) {
1356 case EGPRS_MCS1:
1357 case EGPRS_MCS2:
1358 case EGPRS_MCS3:
1359 case EGPRS_MCS4:
1360 /* Check for valid CPS and matching MCS to message size */
1361 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE3) < 0) ||
1362 (cps.mcs != mcs))
1363 goto bad_header;
1364
1365 egprs_encode_hdr(hc, l2_data, mcs);
1366 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1367 egprs_type3_map(bursts, hc, dc, hdr->type3.usf);
1368 break;
1369 case EGPRS_MCS5:
1370 case EGPRS_MCS6:
1371 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE2) < 0) ||
1372 (cps.mcs != mcs))
1373 goto bad_header;
1374
1375 egprs_encode_hdr(hc, l2_data, mcs);
1376 egprs_encode_data(dc, l2_data, mcs, cps.p[0], 0);
1377 egprs_type2_map(bursts, hc, dc, hdr->type2.usf);
1378 break;
1379 case EGPRS_MCS7:
1380 case EGPRS_MCS8:
1381 case EGPRS_MCS9:
1382 if ((egprs_parse_dl_cps(&cps, hdr, EGPRS_HDR_TYPE1) < 0) ||
1383 (cps.mcs != mcs))
1384 goto bad_header;
1385
1386 egprs_encode_hdr(hc, l2_data, mcs);
1387 egprs_encode_data(c1, l2_data, mcs, cps.p[0], 0);
1388 egprs_encode_data(c2, l2_data, mcs, cps.p[1], 1);
1389 egprs_type1_map(bursts, hc, c1, c2, hdr->type1.usf, mcs);
1390 break;
1391 }
1392
1393 return mcs >= EGPRS_MCS5 ?
1394 GSM0503_EGPRS_BURSTS_NBITS : GSM0503_GPRS_BURSTS_NBITS;
1395
1396bad_header:
1397 /* Invalid EGPRS MCS-X header */
1398 return -1;
1399}
1400
Harald Weltec6636782017-06-12 14:59:37 +02001401/*! \brief GPRS DL message encoding
1402 * \param[out] bursts caller-allocated buffer for unpacked burst bits
1403 * \param[in] l2_data L2 (MAC) block to be encoded
1404 * \param[in] l2_len length of l2_data in bytes, used to determine CS
1405 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001406int gsm0503_pdtch_encode(ubit_t *bursts, const uint8_t *l2_data, uint8_t l2_len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001407{
1408 ubit_t iB[456], cB[676];
1409 const ubit_t *hl_hn;
1410 ubit_t conv[334];
1411 int i, j, usf;
1412
1413 switch (l2_len) {
1414 case 23:
1415 osmo_pbit2ubit_ext(conv, 0, l2_data, 0, 184, 1);
1416
1417 osmo_crc64gen_set_bits(&gsm0503_fire_crc40, conv, 184, conv + 184);
1418
1419 osmo_conv_encode(&gsm0503_xcch, conv, cB);
1420
1421 hl_hn = gsm0503_pdtch_hl_hn_ubit[0];
1422
1423 break;
1424 case 34:
1425 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 271, 1);
1426 usf = l2_data[0] & 0x7;
1427
1428 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1429 271, conv + 3 + 271);
1430
1431 memcpy(conv, gsm0503_usf2six[usf], 6);
1432
1433 osmo_conv_encode(&gsm0503_cs2_np, conv, cB);
1434
1435 for (i = 0, j = 0; i < 588; i++)
1436 if (!gsm0503_puncture_cs2[i])
1437 cB[j++] = cB[i];
1438
1439 hl_hn = gsm0503_pdtch_hl_hn_ubit[1];
1440
1441 break;
1442 case 40:
1443 osmo_pbit2ubit_ext(conv, 3, l2_data, 0, 315, 1);
1444 usf = l2_data[0] & 0x7;
1445
1446 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, conv + 3,
1447 315, conv + 3 + 315);
1448
1449 memcpy(conv, gsm0503_usf2six[usf], 6);
1450
1451 osmo_conv_encode(&gsm0503_cs3_np, conv, cB);
1452
1453 for (i = 0, j = 0; i < 676; i++)
1454 if (!gsm0503_puncture_cs3[i])
1455 cB[j++] = cB[i];
1456
1457 hl_hn = gsm0503_pdtch_hl_hn_ubit[2];
1458
1459 break;
1460 case 54:
1461 osmo_pbit2ubit_ext(cB, 9, l2_data, 0, 431, 1);
1462 usf = l2_data[0] & 0x7;
1463
1464 osmo_crc16gen_set_bits(&gsm0503_cs234_crc16, cB + 9,
1465 431, cB + 9 + 431);
1466
1467 memcpy(cB, gsm0503_usf2twelve_ubit[usf], 12);
1468
1469 hl_hn = gsm0503_pdtch_hl_hn_ubit[3];
1470
1471 break;
1472 default:
1473 return -1;
1474 }
1475
1476 gsm0503_xcch_interleave(cB, iB);
1477
1478 for (i = 0; i < 4; i++) {
1479 gsm0503_xcch_burst_map(&iB[i * 114], &bursts[i * 116],
1480 hl_hn + i * 2, hl_hn + i * 2 + 1);
1481 }
1482
1483 return GSM0503_GPRS_BURSTS_NBITS;
1484}
1485
1486/*
1487 * GSM TCH/F FR/EFR transcoding
1488 */
1489
Harald Weltec6636782017-06-12 14:59:37 +02001490/*! \brief assemble a FR codec frame in format as used inside RTP
1491 * \param[out] tch_data Codec frame in RTP format
1492 * \param[in] b_bits Codec frame in 'native' format
1493 * \param[in] net_order FIXME */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001494static void tch_fr_reassemble(uint8_t *tch_data,
Harald Welteb9946d32017-06-12 09:40:16 +02001495 const ubit_t *b_bits, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001496{
1497 int i, j, k, l, o;
1498
1499 tch_data[0] = 0xd << 4;
1500 memset(tch_data + 1, 0, 32);
1501
1502 if (net_order) {
1503 for (i = 0, j = 4; i < 260; i++, j++)
1504 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1505
1506 return;
1507 }
1508
1509 /* reassemble d-bits */
1510 i = 0; /* counts bits */
1511 j = 4; /* counts output bits */
1512 k = gsm0503_gsm_fr_map[0]-1; /* current number bit in element */
1513 l = 0; /* counts element bits */
1514 o = 0; /* offset input bits */
1515 while (i < 260) {
1516 tch_data[j >> 3] |= (b_bits[k + o] << (7 - (j & 7)));
1517 if (--k < 0) {
1518 o += gsm0503_gsm_fr_map[l];
1519 k = gsm0503_gsm_fr_map[++l]-1;
1520 }
1521 i++;
1522 j++;
1523 }
1524}
1525
1526static void tch_fr_disassemble(ubit_t *b_bits,
Harald Welteb9946d32017-06-12 09:40:16 +02001527 const uint8_t *tch_data, int net_order)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001528{
1529 int i, j, k, l, o;
1530
1531 if (net_order) {
1532 for (i = 0, j = 4; i < 260; i++, j++)
1533 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1534
1535 return;
1536 }
1537
1538 i = 0; /* counts bits */
1539 j = 4; /* counts input bits */
1540 k = gsm0503_gsm_fr_map[0] - 1; /* current number bit in element */
1541 l = 0; /* counts element bits */
1542 o = 0; /* offset output bits */
1543 while (i < 260) {
1544 b_bits[k + o] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1545 if (--k < 0) {
1546 o += gsm0503_gsm_fr_map[l];
1547 k = gsm0503_gsm_fr_map[++l] - 1;
1548 }
1549 i++;
1550 j++;
1551 }
1552}
1553
Harald Weltec6636782017-06-12 14:59:37 +02001554/* assemble a HR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001555static void tch_hr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001556{
1557 int i, j;
1558
1559 tch_data[0] = 0x00; /* F = 0, FT = 000 */
1560 memset(tch_data + 1, 0, 14);
1561
1562 for (i = 0, j = 8; i < 112; i++, j++)
1563 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1564}
1565
Harald Welteb9946d32017-06-12 09:40:16 +02001566static void tch_hr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001567{
1568 int i, j;
1569
1570 for (i = 0, j = 8; i < 112; i++, j++)
1571 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1572}
1573
Harald Weltec6636782017-06-12 14:59:37 +02001574/* assemble a EFR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001575static void tch_efr_reassemble(uint8_t *tch_data, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001576{
1577 int i, j;
1578
1579 tch_data[0] = 0xc << 4;
1580 memset(tch_data + 1, 0, 30);
1581
1582 for (i = 0, j = 4; i < 244; i++, j++)
1583 tch_data[j >> 3] |= (b_bits[i] << (7 - (j & 7)));
1584}
1585
Harald Welteb9946d32017-06-12 09:40:16 +02001586static void tch_efr_disassemble(ubit_t *b_bits, const uint8_t *tch_data)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001587{
1588 int i, j;
1589
1590 for (i = 0, j = 4; i < 244; i++, j++)
1591 b_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1592}
1593
Harald Weltec6636782017-06-12 14:59:37 +02001594/* assemble a AMR codec frame in format as used inside RTP */
Harald Welteb9946d32017-06-12 09:40:16 +02001595static void tch_amr_reassemble(uint8_t *tch_data, const ubit_t *d_bits, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001596{
1597 int i, j;
1598
1599 memset(tch_data, 0, (len + 7) >> 3);
1600
1601 for (i = 0, j = 0; i < len; i++, j++)
1602 tch_data[j >> 3] |= (d_bits[i] << (7 - (j & 7)));
1603}
1604
Harald Welteb9946d32017-06-12 09:40:16 +02001605static void tch_amr_disassemble(ubit_t *d_bits, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001606{
1607 int i, j;
1608
1609 for (i = 0, j = 0; i < len; i++, j++)
1610 d_bits[i] = (tch_data[j >> 3] >> (7 - (j & 7))) & 1;
1611}
1612
Harald Weltec6636782017-06-12 14:59:37 +02001613/* re-arrange according to TS 05.03 Table 2 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001614static void tch_fr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001615{
1616 int i;
1617
1618 for (i = 0; i < 260; i++)
1619 b_bits[gsm610_bitorder[i]] = d_bits[i];
1620}
1621
Harald Weltec6636782017-06-12 14:59:37 +02001622/* re-arrange according to TS 05.03 Table 2 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001623static void tch_fr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001624{
1625 int i;
1626
1627 for (i = 0; i < 260; i++)
1628 d_bits[i] = b_bits[gsm610_bitorder[i]];
1629}
1630
Harald Weltec6636782017-06-12 14:59:37 +02001631/* re-arrange according to TS 05.03 Table 3a (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001632static void tch_hr_d_to_b(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001633{
1634 int i;
1635
1636 const uint16_t *map;
1637
1638 if (!d_bits[93] && !d_bits[94])
1639 map = gsm620_unvoiced_bitorder;
1640 else
1641 map = gsm620_voiced_bitorder;
1642
1643 for (i = 0; i < 112; i++)
1644 b_bits[map[i]] = d_bits[i];
1645}
1646
Harald Weltec6636782017-06-12 14:59:37 +02001647/* re-arrange according to TS 05.03 Table 3a (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001648static void tch_hr_b_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001649{
1650 int i;
1651 const uint16_t *map;
1652
1653 if (!b_bits[34] && !b_bits[35])
1654 map = gsm620_unvoiced_bitorder;
1655 else
1656 map = gsm620_voiced_bitorder;
1657
1658 for (i = 0; i < 112; i++)
1659 d_bits[i] = b_bits[map[i]];
1660}
1661
Harald Weltec6636782017-06-12 14:59:37 +02001662/* re-arrange according to TS 05.03 Table 6 (receiver) */
Harald Welteb9946d32017-06-12 09:40:16 +02001663static void tch_efr_d_to_w(ubit_t *b_bits, const ubit_t *d_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001664{
1665 int i;
1666
1667 for (i = 0; i < 260; i++)
1668 b_bits[gsm660_bitorder[i]] = d_bits[i];
1669}
1670
Harald Weltec6636782017-06-12 14:59:37 +02001671/* re-arrange according to TS 05.03 Table 6 (transmitter) */
Harald Welteb9946d32017-06-12 09:40:16 +02001672static void tch_efr_w_to_d(ubit_t *d_bits, const ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001673{
1674 int i;
1675
1676 for (i = 0; i < 260; i++)
1677 d_bits[i] = b_bits[gsm660_bitorder[i]];
1678}
1679
Harald Weltec6636782017-06-12 14:59:37 +02001680/* extract the 65 protected class1a+1b bits */
Harald Welteb9946d32017-06-12 09:40:16 +02001681static void tch_efr_protected(const ubit_t *s_bits, ubit_t *b_bits)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001682{
1683 int i;
1684
1685 for (i = 0; i < 65; i++)
1686 b_bits[i] = s_bits[gsm0503_gsm_efr_protected_bits[i] - 1];
1687}
1688
Harald Welteb9946d32017-06-12 09:40:16 +02001689static void tch_fr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001690{
1691 int i;
1692
1693 for (i = 0; i < 91; i++) {
1694 d[i << 1] = u[i];
1695 d[(i << 1) + 1] = u[184 - i];
1696 }
1697
1698 for (i = 0; i < 3; i++)
1699 p[i] = u[91 + i];
1700}
1701
Harald Welteb9946d32017-06-12 09:40:16 +02001702static void tch_fr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001703{
1704 int i;
1705
1706 for (i = 0; i < 91; i++) {
1707 u[i] = d[i << 1];
1708 u[184 - i] = d[(i << 1) + 1];
1709 }
1710
1711 for (i = 0; i < 3; i++)
1712 u[91 + i] = p[i];
1713}
1714
Harald Welteb9946d32017-06-12 09:40:16 +02001715static void tch_hr_unreorder(ubit_t *d, ubit_t *p, const ubit_t *u)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001716{
1717 memcpy(d, u, 95);
1718 memcpy(p, u + 95, 3);
1719}
1720
Harald Welteb9946d32017-06-12 09:40:16 +02001721static void tch_hr_reorder(ubit_t *u, const ubit_t *d, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001722{
1723 memcpy(u, d, 95);
1724 memcpy(u + 95, p, 3);
1725}
1726
Harald Welteb9946d32017-06-12 09:40:16 +02001727static void tch_efr_reorder(ubit_t *w, const ubit_t *s, const ubit_t *p)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001728{
1729 memcpy(w, s, 71);
1730 w[71] = w[72] = s[69];
1731 memcpy(w + 73, s + 71, 50);
1732 w[123] = w[124] = s[119];
1733 memcpy(w + 125, s + 121, 53);
1734 w[178] = w[179] = s[172];
1735 memcpy(w + 180, s + 174, 50);
1736 w[230] = w[231] = s[222];
1737 memcpy(w + 232, s + 224, 20);
1738 memcpy(w + 252, p, 8);
1739}
1740
Harald Welteb9946d32017-06-12 09:40:16 +02001741static void tch_efr_unreorder(ubit_t *s, ubit_t *p, const ubit_t *w)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001742{
1743 int sum;
1744
1745 memcpy(s, w, 71);
1746 sum = s[69] + w[71] + w[72];
1747 s[69] = (sum > 2);
1748 memcpy(s + 71, w + 73, 50);
1749 sum = s[119] + w[123] + w[124];
1750 s[119] = (sum > 2);
1751 memcpy(s + 121, w + 125, 53);
1752 sum = s[172] + w[178] + w[179];
1753 s[172] = (sum > 2);
1754 memcpy(s + 174, w + 180, 50);
1755 sum = s[220] + w[230] + w[231];
1756 s[222] = (sum > 2);
1757 memcpy(s + 224, w + 232, 20);
1758 memcpy(p, w + 252, 8);
1759}
1760
Harald Welteb9946d32017-06-12 09:40:16 +02001761static 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 +07001762{
1763 memcpy(u, d, prot);
1764 memcpy(u + prot, p, 6);
1765 memcpy(u + prot + 6, d + prot, len - prot);
1766}
1767
Harald Welteb9946d32017-06-12 09:40:16 +02001768static 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 +07001769{
1770 memcpy(d, u, prot);
1771 memcpy(p, u + prot, 6);
1772 memcpy(d + prot, u + prot + 6, len - prot);
1773}
1774
Harald Weltec6636782017-06-12 14:59:37 +02001775/*! \brief Perform channel decoding of a FR/EFR channel according TS 05.03
1776 * \param[out] tch_data Codec frame in RTP payload format
1777 * \param[in] bursts buffer containing the symbols of 8 bursts
1778 * \param[in] net_order FIXME
1779 * \param[in] efr Is this channel using EFR (1) or FR (0)
1780 * \param[out] n_errors Number of detected bit errors
1781 * \param[out] n_bits_total Total number of bits
1782 * \returns length of bytes used in \a tch_data output buffer */
Harald Welteb9946d32017-06-12 09:40:16 +02001783int gsm0503_tch_fr_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001784 int net_order, int efr, int *n_errors, int *n_bits_total)
1785{
1786 sbit_t iB[912], cB[456], h;
1787 ubit_t conv[185], s[244], w[260], b[65], d[260], p[8];
1788 int i, rv, len, steal = 0;
1789
Harald Weltec6636782017-06-12 14:59:37 +02001790 /* map from 8 bursts to interleaved data bits (iB) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001791 for (i = 0; i < 8; i++) {
1792 gsm0503_tch_burst_unmap(&iB[i * 114],
1793 &bursts[i * 116], &h, i >> 2);
1794 steal -= h;
1795 }
Harald Weltec6636782017-06-12 14:59:37 +02001796 /* we now have the bits of the four bursts (interface 4 in
1797 * Figure 1a of TS 05.03 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001798
1799 gsm0503_tch_fr_deinterleave(cB, iB);
Harald Weltec6636782017-06-12 14:59:37 +02001800 /* we now have the coded bits c(B): interface 3 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001801
1802 if (steal > 0) {
1803 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
1804 if (rv) {
1805 /* Error decoding FACCH frame */
1806 return -1;
1807 }
1808
1809 return 23;
1810 }
1811
1812 osmo_conv_decode_ber(&gsm0503_tch_fr, cB, conv, n_errors, n_bits_total);
Harald Weltec6636782017-06-12 14:59:37 +02001813 /* we now have the data bits 'u': interface 2 in Fig. 1a */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001814
Harald Weltec6636782017-06-12 14:59:37 +02001815 /* input: 'conv', output: d[ata] + p[arity] */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001816 tch_fr_unreorder(d, p, conv);
1817
1818 for (i = 0; i < 78; i++)
1819 d[i + 182] = (cB[i + 378] < 0) ? 1 : 0;
1820
Harald Weltec6636782017-06-12 14:59:37 +02001821 /* check if parity of first 50 (class 1) 'd'-bits match 'p' */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001822 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1823 if (rv) {
1824 /* Error checking CRC8 for the FR part of an EFR/FR frame */
1825 return -1;
1826 }
1827
1828 if (efr) {
1829 tch_efr_d_to_w(w, d);
Harald Weltec6636782017-06-12 14:59:37 +02001830 /* we now have the preliminary-coded bits w(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001831
1832 tch_efr_unreorder(s, p, w);
Harald Weltec6636782017-06-12 14:59:37 +02001833 /* we now have the data delivered to the preliminary
1834 * channel encoding unit s(k) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001835
Harald Weltec6636782017-06-12 14:59:37 +02001836 /* extract the 65 most important bits according TS 05.03 3.1.1.1 */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001837 tch_efr_protected(s, b);
1838
Harald Weltec6636782017-06-12 14:59:37 +02001839 /* perform CRC-8 on 65 most important bits (50 bits of
1840 * class 1a + 15 bits of class 1b) */
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001841 rv = osmo_crc8gen_check_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1842 if (rv) {
1843 /* Error checking CRC8 for the EFR part of an EFR frame */
1844 return -1;
1845 }
1846
1847 tch_efr_reassemble(tch_data, s);
1848
1849 len = GSM_EFR_BYTES;
1850 } else {
1851 tch_fr_d_to_b(w, d);
1852
1853 tch_fr_reassemble(tch_data, w, net_order);
1854
1855 len = GSM_FR_BYTES;
1856 }
1857
1858 return len;
1859}
1860
Harald Weltec6636782017-06-12 14:59:37 +02001861/*! \brief Perform channel encoding on a TCH/FS channel according to TS 05.03
1862 * \param[out] bursts caller-allocated output buffer for bursts bits
1863 * \param[in] tch_data Codec input data in RTP payload format
1864 * \param[in] len Length of \a tch_data in bytes
1865 * \param[in] net_order FIXME
1866 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02001867int gsm0503_tch_fr_encode(ubit_t *bursts, const uint8_t *tch_data,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001868 int len, int net_order)
1869{
1870 ubit_t iB[912], cB[456], h;
1871 ubit_t conv[185], w[260], b[65], s[244], d[260], p[8];
1872 int i;
1873
1874 switch (len) {
1875 case GSM_EFR_BYTES: /* TCH EFR */
1876
1877 tch_efr_disassemble(s, tch_data);
1878
1879 tch_efr_protected(s, b);
1880
1881 osmo_crc8gen_set_bits(&gsm0503_tch_efr_crc8, b, 65, p);
1882
1883 tch_efr_reorder(w, s, p);
1884
1885 tch_efr_w_to_d(d, w);
1886
1887 goto coding_efr_fr;
1888 case GSM_FR_BYTES: /* TCH FR */
1889 tch_fr_disassemble(w, tch_data, net_order);
1890
1891 tch_fr_b_to_d(d, w);
1892
1893coding_efr_fr:
1894 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d, 50, p);
1895
1896 tch_fr_reorder(conv, d, p);
1897
1898 memcpy(cB + 378, d + 182, 78);
1899
1900 osmo_conv_encode(&gsm0503_tch_fr, conv, cB);
1901
1902 h = 0;
1903
1904 break;
1905 case GSM_MACBLOCK_LEN: /* FACCH */
1906 _xcch_encode_cB(cB, tch_data);
1907
1908 h = 1;
1909
1910 break;
1911 default:
1912 return -1;
1913 }
1914
1915 gsm0503_tch_fr_interleave(cB, iB);
1916
1917 for (i = 0; i < 8; i++) {
1918 gsm0503_tch_burst_map(&iB[i * 114],
1919 &bursts[i * 116], &h, i >> 2);
1920 }
1921
1922 return 0;
1923}
1924
Harald Weltec6636782017-06-12 14:59:37 +02001925/*! \brief Perform channel decoding of a HR(v1) channel according TS 05.03
1926 * \param[out] tch_data Codec frame in RTP payload format
1927 * \param[in] bursts buffer containing the symbols of 8 bursts
1928 * \param[in] odd Odd (1) or even (0) frame number
1929 * \param[out] n_errors Number of detected bit errors
1930 * \param[out] n_bits_total Total number of bits
1931 * \returns length of bytes used in \a tch_data output buffer */
Harald Welteb9946d32017-06-12 09:40:16 +02001932int gsm0503_tch_hr_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07001933 int *n_errors, int *n_bits_total)
1934{
1935 sbit_t iB[912], cB[456], h;
1936 ubit_t conv[98], b[112], d[112], p[3];
1937 int i, rv, steal = 0;
1938
1939 /* Only unmap the stealing bits */
1940 if (!odd) {
1941 for (i = 0; i < 4; i++) {
1942 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
1943 steal -= h;
1944 }
1945
1946 for (i = 2; i < 5; i++) {
1947 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
1948 steal -= h;
1949 }
1950 }
1951
1952 /* If we found a stole FACCH, but only at correct alignment */
1953 if (steal > 0) {
1954 for (i = 0; i < 6; i++) {
1955 gsm0503_tch_burst_unmap(&iB[i * 114],
1956 &bursts[i * 116], NULL, i >> 2);
1957 }
1958
1959 for (i = 2; i < 4; i++) {
1960 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
1961 &bursts[i * 116], NULL, 1);
1962 }
1963
1964 gsm0503_tch_fr_deinterleave(cB, iB);
1965
1966 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
1967 if (rv) {
1968 /* Error decoding FACCH frame */
1969 return -1;
1970 }
1971
1972 return GSM_MACBLOCK_LEN;
1973 }
1974
1975 for (i = 0; i < 4; i++) {
1976 gsm0503_tch_burst_unmap(&iB[i * 114],
1977 &bursts[i * 116], NULL, i >> 1);
1978 }
1979
1980 gsm0503_tch_hr_deinterleave(cB, iB);
1981
1982 osmo_conv_decode_ber(&gsm0503_tch_hr, cB, conv, n_errors, n_bits_total);
1983
1984 tch_hr_unreorder(d, p, conv);
1985
1986 for (i = 0; i < 17; i++)
1987 d[i + 95] = (cB[i + 211] < 0) ? 1 : 0;
1988
1989 rv = osmo_crc8gen_check_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
1990 if (rv) {
1991 /* Error checking CRC8 for an HR frame */
1992 return -1;
1993 }
1994
1995 tch_hr_d_to_b(b, d);
1996
1997 tch_hr_reassemble(tch_data, b);
1998
1999 return 15;
2000}
2001
Harald Weltec6636782017-06-12 14:59:37 +02002002/*! \brief Perform channel encoding on a TCH/HS channel according to TS 05.03
2003 * \param[out] bursts caller-allocated output buffer for bursts bits
2004 * \param[in] tch_data Codec input data in RTP payload format
2005 * \param[in] len Length of \a tch_data in bytes
2006 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002007int gsm0503_tch_hr_encode(ubit_t *bursts, const uint8_t *tch_data, int len)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002008{
2009 ubit_t iB[912], cB[456], h;
2010 ubit_t conv[98], b[112], d[112], p[3];
2011 int i;
2012
2013 switch (len) {
2014 case 15: /* TCH HR */
2015 tch_hr_disassemble(b, tch_data);
2016
2017 tch_hr_b_to_d(d, b);
2018
2019 osmo_crc8gen_set_bits(&gsm0503_tch_fr_crc3, d + 73, 22, p);
2020
2021 tch_hr_reorder(conv, d, p);
2022
2023 osmo_conv_encode(&gsm0503_tch_hr, conv, cB);
2024
2025 memcpy(cB + 211, d + 95, 17);
2026
2027 h = 0;
2028
2029 gsm0503_tch_hr_interleave(cB, iB);
2030
2031 for (i = 0; i < 4; i++) {
2032 gsm0503_tch_burst_map(&iB[i * 114],
2033 &bursts[i * 116], &h, i >> 1);
2034 }
2035
2036 break;
2037 case GSM_MACBLOCK_LEN: /* FACCH */
2038 _xcch_encode_cB(cB, tch_data);
2039
2040 h = 1;
2041
2042 gsm0503_tch_fr_interleave(cB, iB);
2043
2044 for (i = 0; i < 6; i++) {
2045 gsm0503_tch_burst_map(&iB[i * 114],
2046 &bursts[i * 116], &h, i >> 2);
2047 }
2048
2049 for (i = 2; i < 4; i++) {
2050 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2051 &bursts[i * 116], &h, 1);
2052 }
2053
2054 break;
2055 default:
2056 return -1;
2057 }
2058
2059 return 0;
2060}
2061
Harald Weltec6636782017-06-12 14:59:37 +02002062/*! \brief Perform channel decoding of a TCH/AFS channel according TS 05.03
2063 * \param[out] tch_data Codec frame in RTP payload format
2064 * \param[in] bursts buffer containing the symbols of 8 bursts
2065 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2066 * \param[in] codec array of active codecs (active codec set)
2067 * \param[in] codecs number of codecs in \a codec
2068 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2069 * \param[out] cmr Output in \a codec_mode_req = 1
2070 * \param[out] n_errors Number of detected bit errors
2071 * \param[out] n_bits_total Total number of bits
2072 * \returns length of bytes used in \a tch_data output buffer */
Harald Welteb9946d32017-06-12 09:40:16 +02002073int gsm0503_tch_afs_decode(uint8_t *tch_data, const sbit_t *bursts,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002074 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2075 uint8_t *cmr, int *n_errors, int *n_bits_total)
2076{
2077 sbit_t iB[912], cB[456], h;
2078 ubit_t d[244], p[6], conv[250];
2079 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
2080 *n_errors = 0; *n_bits_total = 0;
2081
2082 for (i=0; i<8; i++) {
2083 gsm0503_tch_burst_unmap(&iB[i * 114], &bursts[i * 116], &h, i >> 2);
2084 steal -= h;
2085 }
2086
2087 gsm0503_tch_fr_deinterleave(cB, iB);
2088
2089 if (steal > 0) {
2090 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2091 if (rv) {
2092 /* Error decoding FACCH frame */
2093 return -1;
2094 }
2095
2096 return GSM_MACBLOCK_LEN;
2097 }
2098
2099 for (i = 0; i < 4; i++) {
2100 for (j = 0, k = 0; j < 8; j++)
2101 k += abs(((int)gsm0503_afs_ic_sbit[i][j]) - ((int)cB[j]));
2102
2103 if (i == 0 || k < best) {
2104 best = k;
2105 id = i;
2106 }
2107 }
2108
2109 /* Check if indicated codec fits into range of codecs */
2110 if (id >= codecs) {
2111 /* Codec mode out of range, return id */
2112 return id;
2113 }
2114
2115 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2116 case 7: /* TCH/AFS12.2 */
2117 osmo_conv_decode_ber(&gsm0503_tch_afs_12_2, cB + 8,
2118 conv, n_errors, n_bits_total);
2119
2120 tch_amr_unmerge(d, p, conv, 244, 81);
2121
2122 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 81, p);
2123 if (rv) {
2124 /* Error checking CRC8 for an AMR 12.2 frame */
2125 return -1;
2126 }
2127
2128 tch_amr_reassemble(tch_data, d, 244);
2129
2130 len = 31;
2131
2132 break;
2133 case 6: /* TCH/AFS10.2 */
2134 osmo_conv_decode_ber(&gsm0503_tch_afs_10_2, cB + 8,
2135 conv, n_errors, n_bits_total);
2136
2137 tch_amr_unmerge(d, p, conv, 204, 65);
2138
2139 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 65, p);
2140 if (rv) {
2141 /* Error checking CRC8 for an AMR 10.2 frame */
2142 return -1;
2143 }
2144
2145 tch_amr_reassemble(tch_data, d, 204);
2146
2147 len = 26;
2148
2149 break;
2150 case 5: /* TCH/AFS7.95 */
2151 osmo_conv_decode_ber(&gsm0503_tch_afs_7_95, cB + 8,
2152 conv, n_errors, n_bits_total);
2153
2154 tch_amr_unmerge(d, p, conv, 159, 75);
2155
2156 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 75, p);
2157 if (rv) {
2158 /* Error checking CRC8 for an AMR 7.95 frame */
2159 return -1;
2160 }
2161
2162 tch_amr_reassemble(tch_data, d, 159);
2163
2164 len = 20;
2165
2166 break;
2167 case 4: /* TCH/AFS7.4 */
2168 osmo_conv_decode_ber(&gsm0503_tch_afs_7_4, cB + 8,
2169 conv, n_errors, n_bits_total);
2170
2171 tch_amr_unmerge(d, p, conv, 148, 61);
2172
2173 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2174 if (rv) {
2175 /* Error checking CRC8 for an AMR 7.4 frame */
2176 return -1;
2177 }
2178
2179 tch_amr_reassemble(tch_data, d, 148);
2180
2181 len = 19;
2182
2183 break;
2184 case 3: /* TCH/AFS6.7 */
2185 osmo_conv_decode_ber(&gsm0503_tch_afs_6_7, cB + 8,
2186 conv, n_errors, n_bits_total);
2187
2188 tch_amr_unmerge(d, p, conv, 134, 55);
2189
2190 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2191 if (rv) {
2192 /* Error checking CRC8 for an AMR 6.7 frame */
2193 return -1;
2194 }
2195
2196 tch_amr_reassemble(tch_data, d, 134);
2197
2198 len = 17;
2199
2200 break;
2201 case 2: /* TCH/AFS5.9 */
2202 osmo_conv_decode_ber(&gsm0503_tch_afs_5_9, cB + 8,
2203 conv, n_errors, n_bits_total);
2204
2205 tch_amr_unmerge(d, p, conv, 118, 55);
2206
2207 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2208 if (rv) {
2209 /* Error checking CRC8 for an AMR 5.9 frame */
2210 return -1;
2211 }
2212
2213 tch_amr_reassemble(tch_data, d, 118);
2214
2215 len = 15;
2216
2217 break;
2218 case 1: /* TCH/AFS5.15 */
2219 osmo_conv_decode_ber(&gsm0503_tch_afs_5_15, cB + 8,
2220 conv, n_errors, n_bits_total);
2221
2222 tch_amr_unmerge(d, p, conv, 103, 49);
2223
2224 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2225 if (rv) {
2226 /* Error checking CRC8 for an AMR 5.15 frame */
2227 return -1;
2228 }
2229
2230 tch_amr_reassemble(tch_data, d, 103);
2231
2232 len = 13;
2233
2234 break;
2235 case 0: /* TCH/AFS4.75 */
2236 osmo_conv_decode_ber(&gsm0503_tch_afs_4_75, cB + 8,
2237 conv, n_errors, n_bits_total);
2238
2239 tch_amr_unmerge(d, p, conv, 95, 39);
2240
2241 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2242 if (rv) {
2243 /* Error checking CRC8 for an AMR 4.75 frame */
2244 return -1;
2245 }
2246
2247 tch_amr_reassemble(tch_data, d, 95);
2248
2249 len = 12;
2250
2251 break;
2252 default:
2253 /* Unknown frame type */
2254 *n_bits_total = 448;
2255 *n_errors = *n_bits_total;
2256 return -1;
2257 }
2258
2259 /* Change codec request / indication, if frame is valid */
2260 if (codec_mode_req)
2261 *cmr = id;
2262 else
2263 *ft = id;
2264
2265 return len;
2266}
2267
Harald Weltec6636782017-06-12 14:59:37 +02002268/*! \brief Perform channel encoding on a TCH/AFS channel according to TS 05.03
2269 * \param[out] bursts caller-allocated output buffer for bursts bits
2270 * \param[in] tch_data Codec input data in RTP payload format
2271 * \param[in] len Length of \a tch_data in bytes
2272 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2273 * \param[in] codec Array of codecs (active codec set)
2274 * \param[in] codecs Number of entries in \a codec
2275 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2276 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2277 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002278int gsm0503_tch_afs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002279 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2280 uint8_t cmr)
2281{
2282 ubit_t iB[912], cB[456], h;
2283 ubit_t d[244], p[6], conv[250];
2284 int i;
2285 uint8_t id;
2286
2287 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2288 _xcch_encode_cB(cB, tch_data);
2289
2290 h = 1;
2291
2292 goto facch;
2293 }
2294
2295 h = 0;
2296
2297 if (codec_mode_req) {
2298 if (cmr >= codecs) {
2299 /* FIXME: CMR ID is not in codec list! */
2300 return -1;
2301 }
2302 id = cmr;
2303 } else {
2304 if (ft >= codecs) {
2305 /* FIXME: FT ID is not in codec list! */
2306 return -1;
2307 }
2308 id = ft;
2309 }
2310
2311 switch (codec[ft]) {
2312 case 7: /* TCH/AFS12.2 */
2313 if (len != 31)
2314 goto invalid_length;
2315
2316 tch_amr_disassemble(d, tch_data, 244);
2317
2318 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 81, p);
2319
2320 tch_amr_merge(conv, d, p, 244, 81);
2321
2322 osmo_conv_encode(&gsm0503_tch_afs_12_2, conv, cB + 8);
2323
2324 break;
2325 case 6: /* TCH/AFS10.2 */
2326 if (len != 26)
2327 goto invalid_length;
2328
2329 tch_amr_disassemble(d, tch_data, 204);
2330
2331 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 65, p);
2332
2333 tch_amr_merge(conv, d, p, 204, 65);
2334
2335 osmo_conv_encode(&gsm0503_tch_afs_10_2, conv, cB + 8);
2336
2337 break;
2338 case 5: /* TCH/AFS7.95 */
2339 if (len != 20)
2340 goto invalid_length;
2341
2342 tch_amr_disassemble(d, tch_data, 159);
2343
2344 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 75, p);
2345
2346 tch_amr_merge(conv, d, p, 159, 75);
2347
2348 osmo_conv_encode(&gsm0503_tch_afs_7_95, conv, cB + 8);
2349
2350 break;
2351 case 4: /* TCH/AFS7.4 */
2352 if (len != 19)
2353 goto invalid_length;
2354
2355 tch_amr_disassemble(d, tch_data, 148);
2356
2357 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2358
2359 tch_amr_merge(conv, d, p, 148, 61);
2360
2361 osmo_conv_encode(&gsm0503_tch_afs_7_4, conv, cB + 8);
2362
2363 break;
2364 case 3: /* TCH/AFS6.7 */
2365 if (len != 17)
2366 goto invalid_length;
2367
2368 tch_amr_disassemble(d, tch_data, 134);
2369
2370 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2371
2372 tch_amr_merge(conv, d, p, 134, 55);
2373
2374 osmo_conv_encode(&gsm0503_tch_afs_6_7, conv, cB + 8);
2375
2376 break;
2377 case 2: /* TCH/AFS5.9 */
2378 if (len != 15)
2379 goto invalid_length;
2380
2381 tch_amr_disassemble(d, tch_data, 118);
2382
2383 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2384
2385 tch_amr_merge(conv, d, p, 118, 55);
2386
2387 osmo_conv_encode(&gsm0503_tch_afs_5_9, conv, cB + 8);
2388
2389 break;
2390 case 1: /* TCH/AFS5.15 */
2391 if (len != 13)
2392 goto invalid_length;
2393
2394 tch_amr_disassemble(d, tch_data, 103);
2395
2396 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2397
2398 tch_amr_merge(conv, d, p, 103, 49);
2399
2400 osmo_conv_encode(&gsm0503_tch_afs_5_15, conv, cB + 8);
2401
2402 break;
2403 case 0: /* TCH/AFS4.75 */
2404 if (len != 12)
2405 goto invalid_length;
2406
2407 tch_amr_disassemble(d, tch_data, 95);
2408
2409 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2410
2411 tch_amr_merge(conv, d, p, 95, 39);
2412
2413 osmo_conv_encode(&gsm0503_tch_afs_4_75, conv, cB + 8);
2414
2415 break;
2416 default:
2417 /* FIXME: FT %ft is not supported */
2418 return -1;
2419 }
2420
2421 memcpy(cB, gsm0503_afs_ic_ubit[id], 8);
2422
2423facch:
2424 gsm0503_tch_fr_interleave(cB, iB);
2425
2426 for (i = 0; i < 8; i++) {
2427 gsm0503_tch_burst_map(&iB[i * 114],
2428 &bursts[i * 116], &h, i >> 2);
2429 }
2430
2431 return 0;
2432
2433invalid_length:
2434 /* FIXME: payload length %len does not comply with codec type %ft */
2435 return -1;
2436}
2437
Harald Weltec6636782017-06-12 14:59:37 +02002438/*! \brief Perform channel decoding of a TCH/AFS channel according TS 05.03
2439 * \param[out] tch_data Codec frame in RTP payload format
2440 * \param[in] bursts buffer containing the symbols of 8 bursts
2441 * \param[in] odd Is this an odd (1) or even (0) frame number?
2442 * \param[in] codec_mode_req is this CMR (1) or CMC (0)
2443 * \param[in] codec array of active codecs (active codec set)
2444 * \param[in] codecs number of codecs in \a codec
2445 * \param ft Frame Type; Input if \a codec_mode_req = 1, Output * otherwise
2446 * \param[out] cmr Output in \a codec_mode_req = 1
2447 * \param[out] n_errors Number of detected bit errors
2448 * \param[out] n_bits_total Total number of bits
2449 * \returns length of bytes used in \a tch_data output buffer */
Harald Welteb9946d32017-06-12 09:40:16 +02002450int gsm0503_tch_ahs_decode(uint8_t *tch_data, const sbit_t *bursts, int odd,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002451 int codec_mode_req, uint8_t *codec, int codecs, uint8_t *ft,
2452 uint8_t *cmr, int *n_errors, int *n_bits_total)
2453{
2454 sbit_t iB[912], cB[456], h;
2455 ubit_t d[244], p[6], conv[135];
2456 int i, j, k, best = 0, rv, len, steal = 0, id = 0;
2457
2458 /* only unmap the stealing bits */
2459 if (!odd) {
2460 for (i = 0; i < 4; i++) {
2461 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 0);
2462 steal -= h;
2463 }
2464 for (i = 2; i < 5; i++) {
2465 gsm0503_tch_burst_unmap(NULL, &bursts[i * 116], &h, 1);
2466 steal -= h;
2467 }
2468 }
2469
2470 /* if we found a stole FACCH, but only at correct alignment */
2471 if (steal > 0) {
2472 for (i = 0; i < 6; i++) {
2473 gsm0503_tch_burst_unmap(&iB[i * 114],
2474 &bursts[i * 116], NULL, i >> 2);
2475 }
2476
2477 for (i = 2; i < 4; i++) {
2478 gsm0503_tch_burst_unmap(&iB[i * 114 + 456],
2479 &bursts[i * 116], NULL, 1);
2480 }
2481
2482 gsm0503_tch_fr_deinterleave(cB, iB);
2483
2484 rv = _xcch_decode_cB(tch_data, cB, n_errors, n_bits_total);
2485 if (rv) {
2486 /* Error decoding FACCH frame */
2487 return -1;
2488 }
2489
2490 return GSM_MACBLOCK_LEN;
2491 }
2492
2493 for (i = 0; i < 4; i++) {
2494 gsm0503_tch_burst_unmap(&iB[i * 114],
2495 &bursts[i * 116], NULL, i >> 1);
2496 }
2497
2498 gsm0503_tch_hr_deinterleave(cB, iB);
2499
2500 for (i = 0; i < 4; i++) {
2501 for (j = 0, k = 0; j < 4; j++)
2502 k += abs(((int)gsm0503_ahs_ic_sbit[i][j]) - ((int)cB[j]));
2503
2504 if (i == 0 || k < best) {
2505 best = k;
2506 id = i;
2507 }
2508 }
2509
2510 /* Check if indicated codec fits into range of codecs */
2511 if (id >= codecs) {
2512 /* Codec mode out of range, return id */
2513 return id;
2514 }
2515
2516 switch ((codec_mode_req) ? codec[*ft] : codec[id]) {
2517 case 5: /* TCH/AHS7.95 */
2518 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_95, cB + 4,
2519 conv, n_errors, n_bits_total);
2520
2521 tch_amr_unmerge(d, p, conv, 123, 67);
2522
2523 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 67, p);
2524 if (rv) {
2525 /* Error checking CRC8 for an AMR 7.95 frame */
2526 return -1;
2527 }
2528
2529 for (i = 0; i < 36; i++)
2530 d[i + 123] = (cB[i + 192] < 0) ? 1 : 0;
2531
2532 tch_amr_reassemble(tch_data, d, 159);
2533
2534 len = 20;
2535
2536 break;
2537 case 4: /* TCH/AHS7.4 */
2538 osmo_conv_decode_ber(&gsm0503_tch_ahs_7_4, cB + 4,
2539 conv, n_errors, n_bits_total);
2540
2541 tch_amr_unmerge(d, p, conv, 120, 61);
2542
2543 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 61, p);
2544 if (rv) {
2545 /* Error checking CRC8 for an AMR 7.4 frame */
2546 return -1;
2547 }
2548
2549 for (i = 0; i < 28; i++)
2550 d[i + 120] = (cB[i + 200] < 0) ? 1 : 0;
2551
2552 tch_amr_reassemble(tch_data, d, 148);
2553
2554 len = 19;
2555
2556 break;
2557 case 3: /* TCH/AHS6.7 */
2558 osmo_conv_decode_ber(&gsm0503_tch_ahs_6_7, cB + 4,
2559 conv, n_errors, n_bits_total);
2560
2561 tch_amr_unmerge(d, p, conv, 110, 55);
2562
2563 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2564 if (rv) {
2565 /* Error checking CRC8 for an AMR 6.7 frame */
2566 return -1;
2567 }
2568
2569 for (i = 0; i < 24; i++)
2570 d[i + 110] = (cB[i + 204] < 0) ? 1 : 0;
2571
2572 tch_amr_reassemble(tch_data, d, 134);
2573
2574 len = 17;
2575
2576 break;
2577 case 2: /* TCH/AHS5.9 */
2578 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_9, cB + 4,
2579 conv, n_errors, n_bits_total);
2580
2581 tch_amr_unmerge(d, p, conv, 102, 55);
2582
2583 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 55, p);
2584 if (rv) {
2585 /* Error checking CRC8 for an AMR 5.9 frame */
2586 return -1;
2587 }
2588
2589 for (i = 0; i < 16; i++)
2590 d[i + 102] = (cB[i + 212] < 0) ? 1 : 0;
2591
2592 tch_amr_reassemble(tch_data, d, 118);
2593
2594 len = 15;
2595
2596 break;
2597 case 1: /* TCH/AHS5.15 */
2598 osmo_conv_decode_ber(&gsm0503_tch_ahs_5_15, cB + 4,
2599 conv, n_errors, n_bits_total);
2600
2601 tch_amr_unmerge(d, p, conv, 91, 49);
2602
2603 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 49, p);
2604 if (rv) {
2605 /* Error checking CRC8 for an AMR 5.15 frame */
2606 return -1;
2607 }
2608
2609 for (i = 0; i < 12; i++)
2610 d[i + 91] = (cB[i + 216] < 0) ? 1 : 0;
2611
2612 tch_amr_reassemble(tch_data, d, 103);
2613
2614 len = 13;
2615
2616 break;
2617 case 0: /* TCH/AHS4.75 */
2618 osmo_conv_decode_ber(&gsm0503_tch_ahs_4_75, cB + 4,
2619 conv, n_errors, n_bits_total);
2620
2621 tch_amr_unmerge(d, p, conv, 83, 39);
2622
2623 rv = osmo_crc8gen_check_bits(&gsm0503_amr_crc6, d, 39, p);
2624 if (rv) {
2625 /* Error checking CRC8 for an AMR 4.75 frame */
2626 return -1;
2627 }
2628
2629 for (i = 0; i < 12; i++)
2630 d[i + 83] = (cB[i + 216] < 0) ? 1 : 0;
2631
2632 tch_amr_reassemble(tch_data, d, 95);
2633
2634 len = 12;
2635
2636 break;
2637 default:
2638 /* Unknown frame type */
2639 *n_bits_total = 159;
2640 *n_errors = *n_bits_total;
2641 return -1;
2642 }
2643
2644 /* Change codec request / indication, if frame is valid */
2645 if (codec_mode_req)
2646 *cmr = id;
2647 else
2648 *ft = id;
2649
2650 return len;
2651}
2652
Harald Weltec6636782017-06-12 14:59:37 +02002653/*! \brief Perform channel encoding on a TCH/AHS channel according to TS 05.03
2654 * \param[out] bursts caller-allocated output buffer for bursts bits
2655 * \param[in] tch_data Codec input data in RTP payload format
2656 * \param[in] len Length of \a tch_data in bytes
2657 * \param[in] codec_mode_req Use CMR (1) or FT (0)
2658 * \param[in] codec Array of codecs (active codec set)
2659 * \param[in] codecs Number of entries in \a codec
2660 * \param[in] ft Frame Type to be used for encoding (index to \a codec)
2661 * \param[in] cmr Codec Mode Request (used in codec_mode_req = 1 only)
2662 * \returns 0 in case of success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002663int gsm0503_tch_ahs_encode(ubit_t *bursts, const uint8_t *tch_data, int len,
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002664 int codec_mode_req, uint8_t *codec, int codecs, uint8_t ft,
2665 uint8_t cmr)
2666{
2667 ubit_t iB[912], cB[456], h;
2668 ubit_t d[244], p[6], conv[135];
2669 int i;
2670 uint8_t id;
2671
2672 if (len == GSM_MACBLOCK_LEN) { /* FACCH */
2673 _xcch_encode_cB(cB, tch_data);
2674
2675 h = 1;
2676
2677 gsm0503_tch_fr_interleave(cB, iB);
2678
2679 for (i = 0; i < 6; i++)
2680 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116],
2681 &h, i >> 2);
2682 for (i = 2; i < 4; i++)
2683 gsm0503_tch_burst_map(&iB[i * 114 + 456],
2684 &bursts[i * 116], &h, 1);
2685
2686 return 0;
2687 }
2688
2689 h = 0;
2690
2691 if (codec_mode_req) {
2692 if (cmr >= codecs) {
2693 /* FIXME: CMR ID %d not in codec list */
2694 return -1;
2695 }
2696 id = cmr;
2697 } else {
2698 if (ft >= codecs) {
2699 /* FIXME: FT ID %d not in codec list */
2700 return -1;
2701 }
2702 id = ft;
2703 }
2704
2705 switch (codec[ft]) {
2706 case 5: /* TCH/AHS7.95 */
2707 if (len != 20)
2708 goto invalid_length;
2709
2710 tch_amr_disassemble(d, tch_data, 159);
2711
2712 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 67, p);
2713
2714 tch_amr_merge(conv, d, p, 123, 67);
2715
2716 osmo_conv_encode(&gsm0503_tch_ahs_7_95, conv, cB + 4);
2717
2718 memcpy(cB + 192, d + 123, 36);
2719
2720 break;
2721 case 4: /* TCH/AHS7.4 */
2722 if (len != 19)
2723 goto invalid_length;
2724
2725 tch_amr_disassemble(d, tch_data, 148);
2726
2727 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 61, p);
2728
2729 tch_amr_merge(conv, d, p, 120, 61);
2730
2731 osmo_conv_encode(&gsm0503_tch_ahs_7_4, conv, cB + 4);
2732
2733 memcpy(cB + 200, d + 120, 28);
2734
2735 break;
2736 case 3: /* TCH/AHS6.7 */
2737 if (len != 17)
2738 goto invalid_length;
2739
2740 tch_amr_disassemble(d, tch_data, 134);
2741
2742 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2743
2744 tch_amr_merge(conv, d, p, 110, 55);
2745
2746 osmo_conv_encode(&gsm0503_tch_ahs_6_7, conv, cB + 4);
2747
2748 memcpy(cB + 204, d + 110, 24);
2749
2750 break;
2751 case 2: /* TCH/AHS5.9 */
2752 if (len != 15)
2753 goto invalid_length;
2754
2755 tch_amr_disassemble(d, tch_data, 118);
2756
2757 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 55, p);
2758
2759 tch_amr_merge(conv, d, p, 102, 55);
2760
2761 osmo_conv_encode(&gsm0503_tch_ahs_5_9, conv, cB + 4);
2762
2763 memcpy(cB + 212, d + 102, 16);
2764
2765 break;
2766 case 1: /* TCH/AHS5.15 */
2767 if (len != 13)
2768 goto invalid_length;
2769
2770 tch_amr_disassemble(d, tch_data, 103);
2771
2772 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 49, p);
2773
2774 tch_amr_merge(conv, d, p, 91, 49);
2775
2776 osmo_conv_encode(&gsm0503_tch_ahs_5_15, conv, cB + 4);
2777
2778 memcpy(cB + 216, d + 91, 12);
2779
2780 break;
2781 case 0: /* TCH/AHS4.75 */
2782 if (len != 12)
2783 goto invalid_length;
2784
2785 tch_amr_disassemble(d, tch_data, 95);
2786
2787 osmo_crc8gen_set_bits(&gsm0503_amr_crc6, d, 39, p);
2788
2789 tch_amr_merge(conv, d, p, 83, 39);
2790
2791 osmo_conv_encode(&gsm0503_tch_ahs_4_75, conv, cB + 4);
2792
2793 memcpy(cB + 216, d + 83, 12);
2794
2795 break;
2796 default:
2797 /* FIXME: FT %ft is not supported */
2798 return -1;
2799 }
2800
2801 memcpy(cB, gsm0503_afs_ic_ubit[id], 4);
2802
2803 gsm0503_tch_hr_interleave(cB, iB);
2804
2805 for (i = 0; i < 4; i++)
2806 gsm0503_tch_burst_map(&iB[i * 114], &bursts[i * 116], &h, i >> 1);
2807
2808 return 0;
2809
2810invalid_length:
2811 /* FIXME: payload length %len does not comply with codec type %ft */
2812 return -1;
2813}
2814
2815/*
2816 * GSM RACH transcoding
2817 */
2818
2819/*
2820 * GSM RACH apply BSIC to parity
2821 *
2822 * p(j) = p(j) xor b(j) j = 0, ..., 5
2823 * b(0) = MSB of PLMN colour code
2824 * b(5) = LSB of BS colour code
2825 */
2826static int rach_apply_bsic(ubit_t *d, uint8_t bsic)
2827{
2828 int i;
2829
2830 /* Apply it */
2831 for (i = 0; i < 6; i++)
2832 d[8 + i] ^= ((bsic >> (5 - i)) & 1);
2833
2834 return 0;
2835}
2836
Harald Weltec6636782017-06-12 14:59:37 +02002837/*! \brief Decode the (8-bit) RACH according to TS 05.03
2838 * \param[out] ra output buffer for RACH data
2839 * \param[in] burst Input burst data
2840 * \param[in] bsic BSIC used in this cell
2841 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02002842int gsm0503_rach_decode(uint8_t *ra, const sbit_t *burst, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002843{
2844 ubit_t conv[14];
2845 int rv;
2846
2847 osmo_conv_decode(&gsm0503_rach, burst, conv);
2848
2849 rach_apply_bsic(conv, bsic);
2850
2851 rv = osmo_crc8gen_check_bits(&gsm0503_rach_crc6, conv, 8, conv + 8);
2852 if (rv)
2853 return -1;
2854
2855 osmo_ubit2pbit_ext(ra, 0, conv, 0, 8, 1);
2856
2857 return 0;
2858}
2859
Harald Weltec6636782017-06-12 14:59:37 +02002860/*! \brief Encode the (8-bit) RACH according to TS 05.03
2861 * \param[out] burst Caller-allocated output burst buffer
2862 * \param[in] ra Input RACH data
2863 * \param[in] bsic BSIC used in this cell
2864 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002865int gsm0503_rach_encode(ubit_t *burst, const uint8_t *ra, uint8_t bsic)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002866{
2867 ubit_t conv[14];
2868
2869 osmo_pbit2ubit_ext(conv, 0, ra, 0, 8, 1);
2870
2871 osmo_crc8gen_set_bits(&gsm0503_rach_crc6, conv, 8, conv + 8);
2872
2873 rach_apply_bsic(conv, bsic);
2874
2875 osmo_conv_encode(&gsm0503_rach, conv, burst);
2876
2877 return 0;
2878}
2879
2880/*
2881 * GSM SCH transcoding
2882 */
Harald Weltec6636782017-06-12 14:59:37 +02002883
2884/*! \brief Decode the SCH according to TS 05.03
2885 * \param[out] sb_info output buffer for SCH data
2886 * \param[in] burst Input burst data
2887 * \returns 0 on success; negative on error (e.g. CRC error) */
Harald Welteb9946d32017-06-12 09:40:16 +02002888int gsm0503_sch_decode(uint8_t *sb_info, const sbit_t *burst)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002889{
2890 ubit_t conv[35];
2891 int rv;
2892
2893 osmo_conv_decode(&gsm0503_sch, burst, conv);
2894
2895 rv = osmo_crc16gen_check_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
2896 if (rv)
2897 return -1;
2898
2899 osmo_ubit2pbit_ext(sb_info, 0, conv, 0, 25, 1);
2900
2901 return 0;
2902}
2903
Harald Weltec6636782017-06-12 14:59:37 +02002904/*! \brief Encode the SCH according to TS 05.03
2905 * \param[out] burst Caller-allocated output burst buffer
2906 * \param[in] sb_info Input SCH data
2907 * \returns 0 on success; negative on error */
Harald Welteb9946d32017-06-12 09:40:16 +02002908int gsm0503_sch_encode(ubit_t *burst, const uint8_t *sb_info)
Vadim Yanitskiy3262f822016-09-23 01:48:59 +07002909{
2910 ubit_t conv[35];
2911
2912 osmo_pbit2ubit_ext(conv, 0, sb_info, 0, 25, 1);
2913
2914 osmo_crc16gen_set_bits(&gsm0503_sch_crc10, conv, 25, conv + 25);
2915
2916 osmo_conv_encode(&gsm0503_sch, conv, burst);
2917
2918 return 0;
2919}
Harald Weltec6636782017-06-12 14:59:37 +02002920
2921/*! @} */