blob: 511dbb7bbd9b46b7795f9ab66375c037e5c1e624 [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 *
5 * All Rights Reserved
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License as published by
9 * the Free Software Foundation; either version 2 of the License, or
10 * (at your option) any later version.
11 *
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
16 *
17 * You should have received a copy of the GNU General Public License along
18 * with this program; if not, write to the Free Software Foundation, Inc.,
19 * 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
20 */
21
22#include <stdio.h>
23#include <errno.h>
24#include <unistd.h>
25#include <string.h>
26#include <stdlib.h>
27
28#include <osmocom/core/bits.h>
29#include <osmocom/core/utils.h>
30
31#include <osmocom/coding/gsm0503_coding.h>
32
Max458a6f52017-11-28 17:26:54 +010033#define DUMP_U_AT(b, x, u) do { \
34 printf("%s %02x %02x ", osmo_ubit_dump(b + x, 57), b[57 + x], b[58 + x]); \
35 printf("%s\n", osmo_ubit_dump(b + 59 + x, 57)); \
36 if (u <= x) \
37 return; \
38 } while(0)
39
40#define DUMP_S_AT(b, x, u) do { \
41 printf("%s %02x %02x ", osmo_hexdump(b + x, 57), b[57 + x], b[58 + x]); \
42 printf("%s\n", osmo_hexdump(b + 59 + x, 57)); \
43 if (u <= x) \
44 return; \
45 } while(0)
46
47inline void dump_ubits(ubit_t *bursts_u, unsigned until)
48{
49 printf("U-Bits:\n");
50 DUMP_U_AT(bursts_u, 0, until);
51 DUMP_U_AT(bursts_u, 116, until);
52 DUMP_U_AT(bursts_u, 232, until);
53 DUMP_U_AT(bursts_u, 348, until);
54 DUMP_U_AT(bursts_u, 464, until);
55 DUMP_U_AT(bursts_u, 580, until);
56 DUMP_U_AT(bursts_u, 696, until);
57 DUMP_U_AT(bursts_u, 812, until);
58}
59
60inline void dump_sbits(uint8_t *bursts_s, unsigned until)
61{
62 printf("S-Bits:\n");
63 DUMP_S_AT(bursts_s, 0, until);
64 DUMP_S_AT(bursts_s, 116, until);
65 DUMP_S_AT(bursts_s, 232, until);
66 DUMP_S_AT(bursts_s, 348, until);
67 DUMP_S_AT(bursts_s, 464, until);
68 DUMP_S_AT(bursts_s, 580, until);
69 DUMP_S_AT(bursts_s, 696, until);
70 DUMP_S_AT(bursts_s, 812, until);
71}
72
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070073static void test_xcch(uint8_t *l2)
74{
75 uint8_t result[23];
76 ubit_t bursts_u[116 * 4];
77 sbit_t bursts_s[116 * 4];
78 int n_errors, n_bits_total;
79
80 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +010081 printf("Encoding: %s\n", osmo_hexdump(l2, 23));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070082 gsm0503_xcch_encode(bursts_u, l2);
83
84 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +010085 osmo_ubit2sbit(bursts_s, bursts_u, 116 * 4);
Max458a6f52017-11-28 17:26:54 +010086 dump_ubits(bursts_u, 348);
87 dump_sbits((uint8_t *)bursts_s, 348);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070088
89 /* Destroy some bits */
90 memset(bursts_s, 0, 30);
91 memset(bursts_s + 116, 0, 30);
92
93 /* Decode, correcting errors */
94 gsm0503_xcch_decode(result, bursts_s, &n_errors, &n_bits_total);
Max0176b4a2017-11-28 18:04:23 +010095 printf("Decoded: %s\n", osmo_hexdump(result, 23));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +070096 printf("xcch_decode: n_errors=%d n_bits_total=%d ber=%.2f\n",
97 n_errors, n_bits_total, (float) n_errors / n_bits_total);
98
Max33dbecb2017-11-28 19:49:05 +010099 OSMO_ASSERT(n_bits_total == 456);
100 OSMO_ASSERT(!memcmp(l2, result, 23));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700101
Max0176b4a2017-11-28 18:04:23 +0100102 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700103}
104
105static void test_rach(uint8_t bsic, uint8_t ra)
106{
107 uint8_t result;
108 ubit_t bursts_u[36];
109 sbit_t bursts_s[36];
110
111 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100112 printf("Encoding: %02x\n", ra);
Max32e56412017-10-16 14:58:00 +0200113 gsm0503_rach_ext_encode(bursts_u, ra, bsic, false);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700114
115 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100116 osmo_ubit2sbit(bursts_s, bursts_u, 36);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700117
Max0176b4a2017-11-28 18:04:23 +0100118 printf("U-Bits: %s\n", osmo_ubit_dump(bursts_u, 36));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700119
Max0176b4a2017-11-28 18:04:23 +0100120 printf("S-Bits: %s\n", osmo_hexdump((uint8_t *)bursts_s, 36));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700121
122 /* Destroy some bits */
123 memset(bursts_s + 6, 0, 8);
124
125 /* Decode, correcting errors */
126 gsm0503_rach_decode(&result, bursts_s, bsic);
Max0176b4a2017-11-28 18:04:23 +0100127 printf("Decoded: %02x\n", result);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700128
Max32e56412017-10-16 14:58:00 +0200129 if (ra != result)
130 printf("FAIL [RACH]: encoded %u != %u decoded\n", ra, result);
131
132 printf("\n");
133}
134
135static void test_rach_ext(uint8_t bsic, uint16_t ra)
136{
137 uint16_t result = 3000; /* Max ext. RA is 2^11 = 2048 */
138 ubit_t bursts_u[36];
139 sbit_t bursts_s[36];
140
141 /* Encode L2 message */
142 printf("Encoding: %02x\n", ra);
143 gsm0503_rach_ext_encode(bursts_u, ra, bsic, true);
144
145 /* Prepare soft-bits */
146 osmo_ubit2sbit(bursts_s, bursts_u, 36);
147
148 printf("U-Bits: %s\n", osmo_ubit_dump(bursts_u, 36));
149
150 printf("S-Bits: %s\n", osmo_hexdump((uint8_t *)bursts_s, 36));
151
152 /* Destroy some bits */
153 memset(bursts_s + 9, 0, 8);
154
155 /* Decode, correcting errors */
156 gsm0503_rach_ext_decode(&result, bursts_s, bsic);
157 printf("Decoded: %02x\n", result);
158
159 if (ra != result)
160 printf("FAIL [RACH ext]: encoded %u != %u decoded\n", ra, result);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700161
Max0176b4a2017-11-28 18:04:23 +0100162 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700163}
164
165static void test_sch(uint8_t *info)
166{
167 uint8_t result[4];
168 ubit_t bursts_u[78];
169 sbit_t bursts_s[78];
170
171 /* Zero bits 25 and above */
172 info[3] &= 1;
173 result[3] = 0;
174
175 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100176 printf("Encoding: %s\n", osmo_hexdump(info, 4));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700177 gsm0503_sch_encode(bursts_u, info);
178
179 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100180 osmo_ubit2sbit(bursts_s, bursts_u, 78);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700181
Max0176b4a2017-11-28 18:04:23 +0100182 printf("U-Bits: %s\n", osmo_ubit_dump(bursts_u, 78));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700183
Max0176b4a2017-11-28 18:04:23 +0100184 printf("S-Bits: %s\n", osmo_hexdump((uint8_t *)bursts_s, 78));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700185
186 /* Destroy some bits */
187 memset(bursts_s + 6, 0, 10);
188
189 /* Decode, correcting errors */
190 gsm0503_sch_decode(result, bursts_s);
Max0176b4a2017-11-28 18:04:23 +0100191 printf("Decoded: %s\n", osmo_hexdump(result, 4));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700192
Max33dbecb2017-11-28 19:49:05 +0100193 OSMO_ASSERT(!memcmp(info, result, 4));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700194
Max0176b4a2017-11-28 18:04:23 +0100195 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700196}
197
198static void test_fr(uint8_t *speech, int len)
199{
200 uint8_t result[33];
201 ubit_t bursts_u[116 * 8];
202 sbit_t bursts_s[116 * 8];
203 int n_errors, n_bits_total;
204 int rc;
205
206 memset(bursts_u, 0x23, sizeof(bursts_u));
207 memset(bursts_s, 0, sizeof(bursts_s));
208
209 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100210 printf("Encoding: %s\n", osmo_hexdump(speech, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700211 gsm0503_tch_fr_encode(bursts_u, speech, len, 1);
212
213 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100214 osmo_ubit2sbit(bursts_s, bursts_u, 116 * 8);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700215
Max458a6f52017-11-28 17:26:54 +0100216 dump_ubits(bursts_u, 812);
217 dump_sbits((uint8_t *)bursts_s, 812);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700218
219 /* Destroy some bits */
220 memset(bursts_s + 6, 0, 20);
221
222 /* Decode, correcting errors */
223 rc = gsm0503_tch_fr_decode(result, bursts_s, 1, len == 31,
224 &n_errors, &n_bits_total);
Max0176b4a2017-11-28 18:04:23 +0100225 printf("Decoded: %s\n", osmo_hexdump(result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700226 printf("tch_fr_decode: n_errors=%d n_bits_total=%d ber=%.2f\n",
227 n_errors, n_bits_total, (float)n_errors/n_bits_total);
228
Max33dbecb2017-11-28 19:49:05 +0100229 OSMO_ASSERT(rc == len);
230 OSMO_ASSERT(!memcmp(speech, result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700231
Max0176b4a2017-11-28 18:04:23 +0100232 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700233}
234
235static void test_hr(uint8_t *speech, int len)
236{
237 uint8_t result[23];
238 ubit_t bursts_u[116 * 6];
239 sbit_t bursts_s[116 * 6];
240 int n_errors, n_bits_total;
241 int rc;
242
243 memset(bursts_u, 0x23, sizeof(bursts_u));
244 memset(bursts_s, 0, sizeof(bursts_s));
245
246 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100247 printf("Encoding: %s\n", osmo_hexdump(speech, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700248 gsm0503_tch_hr_encode(bursts_u, speech, len);
249
250 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100251 osmo_ubit2sbit(bursts_s, bursts_u, 116 * 6);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700252
Max458a6f52017-11-28 17:26:54 +0100253 dump_ubits(bursts_u, 580);
254 dump_sbits((uint8_t *)bursts_s, 580);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700255
256 /* Destroy some bits */
257 memset(bursts_s + 6, 0, 20);
258
259 /* Decode, correcting errors */
260 rc = gsm0503_tch_hr_decode(result, bursts_s, 0,
261 &n_errors, &n_bits_total);
Max0176b4a2017-11-28 18:04:23 +0100262 printf("Decoded: %s\n", osmo_hexdump(result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700263 printf("tch_hr_decode: n_errors=%d n_bits_total=%d ber=%.2f\n",
264 n_errors, n_bits_total, (float)n_errors/n_bits_total);
265
Max33dbecb2017-11-28 19:49:05 +0100266 OSMO_ASSERT(rc == len);
267 OSMO_ASSERT(!memcmp(speech, result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700268
Max0176b4a2017-11-28 18:04:23 +0100269 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700270}
271
272static void test_pdtch(uint8_t *l2, int len)
273{
274 uint8_t result[len];
275 ubit_t bursts_u[116 * 4];
276 sbit_t bursts_s[116 * 4];
277 int n_errors, n_bits_total;
278 int rc;
279
280 /* Zero the not coded tail bits */
281 switch (len) {
282 case 34:
283 case 54:
284 l2[len - 1] &= 0x7f;
285 result[len - 1] &= 0x7f;
286 break;
287 case 40:
288 l2[len - 1] &= 0x07;
289 result[len - 1] &= 0x07;
290 break;
291 }
292
293 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100294 printf("Encoding: %s\n", osmo_hexdump(l2, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700295 gsm0503_pdtch_encode(bursts_u, l2, len);
296
297 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100298 osmo_ubit2sbit(bursts_s, bursts_u, 116 * 4);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700299
Max458a6f52017-11-28 17:26:54 +0100300 dump_ubits(bursts_u, 348);
301 dump_sbits((uint8_t *)bursts_s, 348);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700302
303 /* Decode */
304 rc = gsm0503_pdtch_decode(result, bursts_s, NULL,
305 &n_errors, &n_bits_total);
Max0176b4a2017-11-28 18:04:23 +0100306 printf("Decoded: %s\n", osmo_hexdump(result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700307 printf("pdtch_decode: n_errors=%d n_bits_total=%d ber=%.2f\n",
308 n_errors, n_bits_total, (float)n_errors/n_bits_total);
309
Max33dbecb2017-11-28 19:49:05 +0100310 OSMO_ASSERT(rc == len);
311 OSMO_ASSERT(!memcmp(l2, result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700312
Max0176b4a2017-11-28 18:04:23 +0100313 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700314}
315
316uint8_t test_l2[][23] = {
317 /* Dummy frame */
318 { 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
319 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
320 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
321 /* Random frame */
322 { 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
323 0xd9, 0x6d, 0x7d, 0x62, 0x24, 0xc9, 0xd2, 0x92,
324 0xfa, 0x27, 0x5d, 0x71, 0x7a, 0x59, 0xa8 },
325 /* jolly frame */
326 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
327 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
328 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
329};
330
331uint8_t test_macblock[][54] = {
332 /* Random frame */
333 { 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
334 0xd9, 0x6d, 0x7d, 0x62, 0x24, 0xc9, 0xd2, 0x92,
335 0xfa, 0x27, 0x5d, 0x71, 0x7a, 0x59, 0xa8, 0x42,
336 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
337 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
338 0xd9, 0x6d, 0x7d, 0x62, 0x24, 0xc9, 0xd2, 0x92,
339 0xfa, 0x27, 0x5d, 0x71, 0x7a, 0xa8 },
340 /* jolly frame */
341 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
342 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
343 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
344};
345
346uint8_t test_speech_fr[33];
347uint8_t test_speech_efr[31];
348uint8_t test_speech_hr[15];
349
350int main(int argc, char **argv)
351{
352 int i, len_l2, len_mb;
353
354 len_l2 = sizeof(test_l2) / sizeof(test_l2[0]);
355 len_mb = sizeof(test_macblock) / sizeof(test_macblock[0]);
356
357 for (i = 0; i < len_l2; i++)
358 test_xcch(test_l2[i]);
359
360 for (i = 0; i < 256; i++) {
361 test_rach(0x3f, i);
362 test_rach(0x00, i);
363 test_rach(0x1a, i);
364 }
365
Max32e56412017-10-16 14:58:00 +0200366 for (i = 0; i < 2048; i++) {
367 test_rach_ext(0x3f, i);
368 test_rach_ext(0x00, i);
369 test_rach_ext(0x1a, i);
370 }
371
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700372 for (i = 0; i < len_l2; i++)
373 test_sch(test_l2[i]);
374
375 for (i = 0; i < sizeof(test_speech_fr); i++)
376 test_speech_fr[i] = i;
377 test_speech_fr[0] = 0xd0;
378 test_fr(test_speech_fr, sizeof(test_speech_fr));
379
380 for (i = 0; i < sizeof(test_speech_efr); i++)
381 test_speech_efr[i] = i;
382 test_speech_efr[0] = 0xc0;
383 test_fr(test_speech_efr, sizeof(test_speech_efr));
384
385 for (i = 0; i < len_l2; i++)
386 test_fr(test_l2[i], sizeof(test_l2[0]));
387
388 for (i = 0; i < sizeof(test_speech_hr); i++)
389 test_speech_hr[i] = i * 17;
390 test_speech_hr[0] = 0x00;
391 test_hr(test_speech_hr, sizeof(test_speech_hr));
392
393 for (i = 0; i < len_l2; i++)
394 test_hr(test_l2[i], sizeof(test_l2[0]));
395
396 for (i = 0; i < len_mb; i++) {
397 test_pdtch(test_macblock[i], 23);
398 test_pdtch(test_macblock[i], 34);
399 test_pdtch(test_macblock[i], 40);
400 test_pdtch(test_macblock[i], 54);
401 }
402
403 printf("Success\n");
404
405 return 0;
406}