blob: 2b0830f2a12c6d2354ac0d7aed681741e71abae5 [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
Pau Espin Pedrol41911d02018-02-01 12:10:33 +010047static inline void dump_ubits(ubit_t *bursts_u, unsigned until)
Max458a6f52017-11-28 17:26:54 +010048{
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
Pau Espin Pedrol41911d02018-02-01 12:10:33 +010060static inline void dump_sbits(uint8_t *bursts_s, unsigned until)
Max458a6f52017-11-28 17:26:54 +010061{
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{
Maxa4785902019-03-05 11:30:39 +0100107 int rc;
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700108 uint8_t result;
109 ubit_t bursts_u[36];
110 sbit_t bursts_s[36];
111
112 /* Encode L2 message */
Maxa4785902019-03-05 11:30:39 +0100113 rc = gsm0503_rach_ext_encode(bursts_u, ra, bsic, false);
114 printf("Encoding: %02x%s\n", ra, (rc != 0) ? " FAIL" : "");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700115
116 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100117 osmo_ubit2sbit(bursts_s, bursts_u, 36);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700118
Max0176b4a2017-11-28 18:04:23 +0100119 printf("U-Bits: %s\n", osmo_ubit_dump(bursts_u, 36));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700120
Max0176b4a2017-11-28 18:04:23 +0100121 printf("S-Bits: %s\n", osmo_hexdump((uint8_t *)bursts_s, 36));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700122
123 /* Destroy some bits */
124 memset(bursts_s + 6, 0, 8);
125
126 /* Decode, correcting errors */
Maxa4785902019-03-05 11:30:39 +0100127 rc = gsm0503_rach_decode_ber(&result, bursts_s, bsic, NULL, NULL);
128 printf("Decoded: %02x%s\n", result, (rc != 0) ? " FAIL" : "");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700129
Max32e56412017-10-16 14:58:00 +0200130 if (ra != result)
131 printf("FAIL [RACH]: encoded %u != %u decoded\n", ra, result);
132
133 printf("\n");
134}
135
136static void test_rach_ext(uint8_t bsic, uint16_t ra)
137{
Maxa4785902019-03-05 11:30:39 +0100138 int rc;
Max32e56412017-10-16 14:58:00 +0200139 uint16_t result = 3000; /* Max ext. RA is 2^11 = 2048 */
140 ubit_t bursts_u[36];
141 sbit_t bursts_s[36];
142
143 /* Encode L2 message */
Maxa4785902019-03-05 11:30:39 +0100144 rc = gsm0503_rach_ext_encode(bursts_u, ra, bsic, true);
145 printf("Encoding: %02x%s\n", ra, (rc != 0) ? " FAIL" : "");
Max32e56412017-10-16 14:58:00 +0200146
147 /* Prepare soft-bits */
148 osmo_ubit2sbit(bursts_s, bursts_u, 36);
149
150 printf("U-Bits: %s\n", osmo_ubit_dump(bursts_u, 36));
151
152 printf("S-Bits: %s\n", osmo_hexdump((uint8_t *)bursts_s, 36));
153
154 /* Destroy some bits */
155 memset(bursts_s + 9, 0, 8);
156
157 /* Decode, correcting errors */
Maxa4785902019-03-05 11:30:39 +0100158 rc = gsm0503_rach_ext_decode_ber(&result, bursts_s, bsic, NULL, NULL);
159 printf("Decoded: %02x%s\n", result, (rc != 0) ? " FAIL" : "");
Max32e56412017-10-16 14:58:00 +0200160
161 if (ra != result)
162 printf("FAIL [RACH ext]: encoded %u != %u decoded\n", ra, result);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700163
Max0176b4a2017-11-28 18:04:23 +0100164 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700165}
166
167static void test_sch(uint8_t *info)
168{
169 uint8_t result[4];
170 ubit_t bursts_u[78];
171 sbit_t bursts_s[78];
172
173 /* Zero bits 25 and above */
174 info[3] &= 1;
175 result[3] = 0;
176
177 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100178 printf("Encoding: %s\n", osmo_hexdump(info, 4));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700179 gsm0503_sch_encode(bursts_u, info);
180
181 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100182 osmo_ubit2sbit(bursts_s, bursts_u, 78);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700183
Max0176b4a2017-11-28 18:04:23 +0100184 printf("U-Bits: %s\n", osmo_ubit_dump(bursts_u, 78));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700185
Max0176b4a2017-11-28 18:04:23 +0100186 printf("S-Bits: %s\n", osmo_hexdump((uint8_t *)bursts_s, 78));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700187
188 /* Destroy some bits */
189 memset(bursts_s + 6, 0, 10);
190
191 /* Decode, correcting errors */
192 gsm0503_sch_decode(result, bursts_s);
Max0176b4a2017-11-28 18:04:23 +0100193 printf("Decoded: %s\n", osmo_hexdump(result, 4));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700194
Max33dbecb2017-11-28 19:49:05 +0100195 OSMO_ASSERT(!memcmp(info, result, 4));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700196
Max0176b4a2017-11-28 18:04:23 +0100197 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700198}
199
200static void test_fr(uint8_t *speech, int len)
201{
202 uint8_t result[33];
203 ubit_t bursts_u[116 * 8];
204 sbit_t bursts_s[116 * 8];
205 int n_errors, n_bits_total;
206 int rc;
207
208 memset(bursts_u, 0x23, sizeof(bursts_u));
209 memset(bursts_s, 0, sizeof(bursts_s));
210
211 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100212 printf("Encoding: %s\n", osmo_hexdump(speech, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700213 gsm0503_tch_fr_encode(bursts_u, speech, len, 1);
214
215 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100216 osmo_ubit2sbit(bursts_s, bursts_u, 116 * 8);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700217
Max458a6f52017-11-28 17:26:54 +0100218 dump_ubits(bursts_u, 812);
219 dump_sbits((uint8_t *)bursts_s, 812);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700220
221 /* Destroy some bits */
222 memset(bursts_s + 6, 0, 20);
223
224 /* Decode, correcting errors */
225 rc = gsm0503_tch_fr_decode(result, bursts_s, 1, len == 31,
226 &n_errors, &n_bits_total);
Max0176b4a2017-11-28 18:04:23 +0100227 printf("Decoded: %s\n", osmo_hexdump(result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700228 printf("tch_fr_decode: n_errors=%d n_bits_total=%d ber=%.2f\n",
229 n_errors, n_bits_total, (float)n_errors/n_bits_total);
230
Max33dbecb2017-11-28 19:49:05 +0100231 OSMO_ASSERT(rc == len);
232 OSMO_ASSERT(!memcmp(speech, result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700233
Max0176b4a2017-11-28 18:04:23 +0100234 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700235}
236
237static void test_hr(uint8_t *speech, int len)
238{
239 uint8_t result[23];
240 ubit_t bursts_u[116 * 6];
241 sbit_t bursts_s[116 * 6];
242 int n_errors, n_bits_total;
243 int rc;
244
245 memset(bursts_u, 0x23, sizeof(bursts_u));
246 memset(bursts_s, 0, sizeof(bursts_s));
247
248 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100249 printf("Encoding: %s\n", osmo_hexdump(speech, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700250 gsm0503_tch_hr_encode(bursts_u, speech, len);
251
252 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100253 osmo_ubit2sbit(bursts_s, bursts_u, 116 * 6);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700254
Max458a6f52017-11-28 17:26:54 +0100255 dump_ubits(bursts_u, 580);
256 dump_sbits((uint8_t *)bursts_s, 580);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700257
258 /* Destroy some bits */
259 memset(bursts_s + 6, 0, 20);
260
261 /* Decode, correcting errors */
262 rc = gsm0503_tch_hr_decode(result, bursts_s, 0,
263 &n_errors, &n_bits_total);
Max0176b4a2017-11-28 18:04:23 +0100264 printf("Decoded: %s\n", osmo_hexdump(result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700265 printf("tch_hr_decode: n_errors=%d n_bits_total=%d ber=%.2f\n",
266 n_errors, n_bits_total, (float)n_errors/n_bits_total);
267
Max33dbecb2017-11-28 19:49:05 +0100268 OSMO_ASSERT(rc == len);
269 OSMO_ASSERT(!memcmp(speech, result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700270
Max0176b4a2017-11-28 18:04:23 +0100271 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700272}
273
274static void test_pdtch(uint8_t *l2, int len)
275{
276 uint8_t result[len];
277 ubit_t bursts_u[116 * 4];
278 sbit_t bursts_s[116 * 4];
279 int n_errors, n_bits_total;
280 int rc;
281
282 /* Zero the not coded tail bits */
283 switch (len) {
284 case 34:
285 case 54:
286 l2[len - 1] &= 0x7f;
287 result[len - 1] &= 0x7f;
288 break;
289 case 40:
290 l2[len - 1] &= 0x07;
291 result[len - 1] &= 0x07;
292 break;
293 }
294
295 /* Encode L2 message */
Max0176b4a2017-11-28 18:04:23 +0100296 printf("Encoding: %s\n", osmo_hexdump(l2, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700297 gsm0503_pdtch_encode(bursts_u, l2, len);
298
299 /* Prepare soft-bits */
Max29d489f2017-11-28 14:54:32 +0100300 osmo_ubit2sbit(bursts_s, bursts_u, 116 * 4);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700301
Max458a6f52017-11-28 17:26:54 +0100302 dump_ubits(bursts_u, 348);
303 dump_sbits((uint8_t *)bursts_s, 348);
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700304
305 /* Decode */
306 rc = gsm0503_pdtch_decode(result, bursts_s, NULL,
307 &n_errors, &n_bits_total);
Max0176b4a2017-11-28 18:04:23 +0100308 printf("Decoded: %s\n", osmo_hexdump(result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700309 printf("pdtch_decode: n_errors=%d n_bits_total=%d ber=%.2f\n",
310 n_errors, n_bits_total, (float)n_errors/n_bits_total);
311
Max33dbecb2017-11-28 19:49:05 +0100312 OSMO_ASSERT(rc == len);
313 OSMO_ASSERT(!memcmp(l2, result, len));
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700314
Max0176b4a2017-11-28 18:04:23 +0100315 printf("\n");
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700316}
317
318uint8_t test_l2[][23] = {
319 /* Dummy frame */
320 { 0x03, 0x03, 0x01, 0x00, 0x00, 0x00, 0x00, 0x00,
321 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
322 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 },
323 /* Random frame */
324 { 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
325 0xd9, 0x6d, 0x7d, 0x62, 0x24, 0xc9, 0xd2, 0x92,
326 0xfa, 0x27, 0x5d, 0x71, 0x7a, 0x59, 0xa8 },
327 /* jolly frame */
328 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
329 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
330 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
331};
332
333uint8_t test_macblock[][54] = {
334 /* Random frame */
335 { 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
336 0xd9, 0x6d, 0x7d, 0x62, 0x24, 0xc9, 0xd2, 0x92,
337 0xfa, 0x27, 0x5d, 0x71, 0x7a, 0x59, 0xa8, 0x42,
338 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
339 0xa3, 0xaf, 0x5f, 0xc6, 0x36, 0x43, 0x44, 0xab,
340 0xd9, 0x6d, 0x7d, 0x62, 0x24, 0xc9, 0xd2, 0x92,
341 0xfa, 0x27, 0x5d, 0x71, 0x7a, 0xa8 },
342 /* jolly frame */
343 { 0x01, 0x02, 0x03, 0x04, 0x05, 0x06, 0x07, 0x08,
344 0x09, 0x0a, 0x0b, 0x0c, 0x0d, 0x0e, 0x0f, 0x10,
345 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17 },
346};
347
348uint8_t test_speech_fr[33];
349uint8_t test_speech_efr[31];
350uint8_t test_speech_hr[15];
351
352int main(int argc, char **argv)
353{
354 int i, len_l2, len_mb;
355
356 len_l2 = sizeof(test_l2) / sizeof(test_l2[0]);
357 len_mb = sizeof(test_macblock) / sizeof(test_macblock[0]);
358
359 for (i = 0; i < len_l2; i++)
360 test_xcch(test_l2[i]);
361
362 for (i = 0; i < 256; i++) {
363 test_rach(0x3f, i);
364 test_rach(0x00, i);
365 test_rach(0x1a, i);
366 }
367
Max32e56412017-10-16 14:58:00 +0200368 for (i = 0; i < 2048; i++) {
369 test_rach_ext(0x3f, i);
370 test_rach_ext(0x00, i);
371 test_rach_ext(0x1a, i);
372 }
373
Vadim Yanitskiy3262f822016-09-23 01:48:59 +0700374 for (i = 0; i < len_l2; i++)
375 test_sch(test_l2[i]);
376
377 for (i = 0; i < sizeof(test_speech_fr); i++)
378 test_speech_fr[i] = i;
379 test_speech_fr[0] = 0xd0;
380 test_fr(test_speech_fr, sizeof(test_speech_fr));
381
382 for (i = 0; i < sizeof(test_speech_efr); i++)
383 test_speech_efr[i] = i;
384 test_speech_efr[0] = 0xc0;
385 test_fr(test_speech_efr, sizeof(test_speech_efr));
386
387 for (i = 0; i < len_l2; i++)
388 test_fr(test_l2[i], sizeof(test_l2[0]));
389
390 for (i = 0; i < sizeof(test_speech_hr); i++)
391 test_speech_hr[i] = i * 17;
392 test_speech_hr[0] = 0x00;
393 test_hr(test_speech_hr, sizeof(test_speech_hr));
394
395 for (i = 0; i < len_l2; i++)
396 test_hr(test_l2[i], sizeof(test_l2[0]));
397
398 for (i = 0; i < len_mb; i++) {
399 test_pdtch(test_macblock[i], 23);
400 test_pdtch(test_macblock[i], 34);
401 test_pdtch(test_macblock[i], 40);
402 test_pdtch(test_macblock[i], 54);
403 }
404
405 printf("Success\n");
406
407 return 0;
408}