blob: 3064f9cab76b888891336f13b19e01ff5dec8a70 [file] [log] [blame]
Sylvain Munaut29eb92d2011-11-24 17:48:42 +01001#include <stdio.h>
2#include <stdlib.h>
Jacob Erlbeck3c761c82013-08-14 18:13:46 +02003#include <string.h>
Sylvain Munaut29eb92d2011-11-24 17:48:42 +01004#include <time.h>
5
6#include <osmocom/core/bits.h>
7#include <osmocom/core/conv.h>
8#include <osmocom/core/utils.h>
Max Suraev msuraev@sysmocom.de84da22f2016-04-29 13:17:22 +02009#include <osmocom/gsm/gsm0503.h>
Sylvain Munaut29eb92d2011-11-24 17:48:42 +010010
11#define MAX_LEN_BITS 512
12#define MAX_LEN_BYTES (512/8)
13
14
15/* ------------------------------------------------------------------------ */
16/* Test codes */
17/* ------------------------------------------------------------------------ */
18
Sylvain Munaut29eb92d2011-11-24 17:48:42 +010019/* GMR-1 TCH3 Speech -> Non recursive code, tail-biting, punctured */
20static const uint8_t conv_gmr1_tch3_speech_next_output[][2] = {
21 { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
22 { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
23 { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
24 { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
25 { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
26 { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
27 { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
28 { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
29 { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
30 { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
31 { 3, 0 }, { 2, 1 }, { 0, 3 }, { 1, 2 },
32 { 0, 3 }, { 1, 2 }, { 3, 0 }, { 2, 1 },
33 { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
34 { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
35 { 1, 2 }, { 0, 3 }, { 2, 1 }, { 3, 0 },
36 { 2, 1 }, { 3, 0 }, { 1, 2 }, { 0, 3 },
37};
38
39static const uint8_t conv_gmr1_tch3_speech_next_state[][2] = {
40 { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
41 { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
42 { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
43 { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
44 { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
45 { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
46 { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
47 { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
48 { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
49 { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
50 { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
51 { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
52 { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
53 { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
54 { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
55 { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
56};
57
58static const int conv_gmr1_tch3_speech_puncture[] = {
59 3, 7, 11, 15, 19, 23, 27, 31, 35, 39, 43, 47,
60 51, 55, 59, 63, 67, 71, 75, 79, 83, 87, 91, 95,
61 -1, /* end */
62};
63
64static const struct osmo_conv_code conv_gmr1_tch3_speech = {
65 .N = 2,
66 .K = 7,
67 .len = 48,
68 .term = CONV_TERM_TAIL_BITING,
69 .next_output = conv_gmr1_tch3_speech_next_output,
70 .next_state = conv_gmr1_tch3_speech_next_state,
71 .puncture = conv_gmr1_tch3_speech_puncture,
72};
73
74
75/* WiMax FCH -> Non recursive code, tail-biting, non-punctured */
76static const uint8_t conv_wimax_fch_next_output[][2] = {
77 { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
78 { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
79 { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
80 { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
81 { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
82 { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
83 { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
84 { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
85 { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
86 { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
87 { 3, 0 }, { 1, 2 }, { 0, 3 }, { 2, 1 },
88 { 0, 3 }, { 2, 1 }, { 3, 0 }, { 1, 2 },
89 { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
90 { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
91 { 2, 1 }, { 0, 3 }, { 1, 2 }, { 3, 0 },
92 { 1, 2 }, { 3, 0 }, { 2, 1 }, { 0, 3 },
93};
94
95static const uint8_t conv_wimax_fch_next_state[][2] = {
96 { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
97 { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
98 { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
99 { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
100 { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
101 { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
102 { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
103 { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
104 { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
105 { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
106 { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
107 { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
108 { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
109 { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
110 { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
111 { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
112};
113
114static const struct osmo_conv_code conv_wimax_fch = {
115 .N = 2,
116 .K = 7,
117 .len = 48,
118 .term = CONV_TERM_TAIL_BITING,
119 .next_output = conv_wimax_fch_next_output,
120 .next_state = conv_wimax_fch_next_state,
121};
122
Vadim Yanitskiy12142952017-01-15 12:55:57 +0700123/**
124 * LTE PBCH
125 * Non recursive code, tail-biting, non-punctured
126 */
127static const uint8_t conv_lte_pbch_next_output[][2] = {
128 { 0, 7 }, { 3, 4 }, { 7, 0 }, { 4 , 3 },
129 { 6, 1 }, { 5, 2 }, { 1, 6 }, { 2 , 5 },
130 { 1, 6 }, { 2, 5 }, { 6, 1 }, { 5 , 2 },
131 { 7, 0 }, { 4, 3 }, { 0, 7 }, { 3 , 4 },
132 { 4, 3 }, { 7, 0 }, { 3, 4 }, { 0 , 7 },
133 { 2, 5 }, { 1, 6 }, { 5, 2 }, { 6 , 1 },
134 { 5, 2 }, { 6, 1 }, { 2, 5 }, { 1 , 6 },
135 { 3, 4 }, { 0, 7 }, { 4, 3 }, { 7 , 0 },
136 { 7, 0 }, { 4, 3 }, { 0, 7 }, { 3 , 4 },
137 { 1, 6 }, { 2, 5 }, { 6, 1 }, { 5 , 2 },
138 { 6, 1 }, { 5, 2 }, { 1, 6 }, { 2 , 5 },
139 { 0, 7 }, { 3, 4 }, { 7, 0 }, { 4 , 3 },
140 { 3, 4 }, { 0, 7 }, { 4, 3 }, { 7 , 0 },
141 { 5, 2 }, { 6, 1 }, { 2, 5 }, { 1 , 6 },
142 { 2, 5 }, { 1, 6 }, { 5, 2 }, { 6 , 1 },
143 { 4, 3 }, { 7, 0 }, { 3, 4 }, { 0 , 7 },
144};
145
146static const uint8_t conv_lte_pbch_next_state[][2] = {
147 { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
148 { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
149 { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
150 { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
151 { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
152 { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
153 { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
154 { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
155 { 0, 1 }, { 2, 3 }, { 4, 5 }, { 6, 7 },
156 { 8, 9 }, { 10, 11 }, { 12, 13 }, { 14, 15 },
157 { 16, 17 }, { 18, 19 }, { 20, 21 }, { 22, 23 },
158 { 24, 25 }, { 26, 27 }, { 28, 29 }, { 30, 31 },
159 { 32, 33 }, { 34, 35 }, { 36, 37 }, { 38, 39 },
160 { 40, 41 }, { 42, 43 }, { 44, 45 }, { 46, 47 },
161 { 48, 49 }, { 50, 51 }, { 52, 53 }, { 54, 55 },
162 { 56, 57 }, { 58, 59 }, { 60, 61 }, { 62, 63 },
163};
164
165const struct osmo_conv_code conv_lte_pbch = {
166 .N = 3,
167 .K = 7,
168 .len = 40,
169 .term = CONV_TERM_TAIL_BITING,
170 .next_output = conv_lte_pbch_next_output,
171 .next_state = conv_lte_pbch_next_state,
172};
173
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100174/* ------------------------------------------------------------------------ */
175/* Test vectors */
176/* ------------------------------------------------------------------------ */
177
178struct conv_test_vector {
179 const char *name;
180 const struct osmo_conv_code *code;
181 int in_len;
182 int out_len;
183 int has_vec;
184 pbit_t vec_in[MAX_LEN_BYTES];
185 pbit_t vec_out[MAX_LEN_BYTES];
186};
187
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100188/* ------------------------------------------------------------------------ */
189/* Main */
190/* ------------------------------------------------------------------------ */
191
192static void
193fill_random(ubit_t *b, int n)
194{
195 int i;
196 for (i=0; i<n; i++)
197 b[i] = random() & 1;
198}
199
Jacob Erlbeck3c761c82013-08-14 18:13:46 +0200200int main(int argc, char *argv[])
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100201{
202 const struct conv_test_vector *tst;
203 ubit_t *bu0, *bu1;
204 sbit_t *bs;
205
Max Suraev msuraev@sysmocom.de84da22f2016-04-29 13:17:22 +0200206/* Random code -> Non recursive code, direct truncation, non-punctured */
207 const struct osmo_conv_code conv_trunc = {
208 .N = 2,
209 .K = 5,
210 .len = 224,
211 .term = CONV_TERM_TRUNCATION,
212 .next_output = gsm0503_xcch.next_output,
213 .next_state = gsm0503_xcch.next_state,
214 };
215
216 const struct conv_test_vector tests[] = {
217 {
218 .name = "GSM xCCH (non-recursive, flushed, not punctured)",
219 .code = &gsm0503_xcch,
220 .in_len = 224,
221 .out_len = 456,
222 .has_vec = 1,
223 .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae,
224 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96,
225 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19,
226 0x17, 0xf2, 0x44, 0x99 },
227 .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7,
228 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16,
229 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85,
230 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6,
231 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17,
232 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f,
233 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f,
234 0x8f },
235 },
236 {
237 .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)",
238 .code = &gsm0503_tch_afs_7_95,
239 .in_len = 165,
240 .out_len = 448,
241 .has_vec = 1,
242 .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59,
243 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa,
244 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 },
245 .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f,
246 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41,
247 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91,
248 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1,
249 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c,
250 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e,
251 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c },
252 },
253 {
254 .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)",
255 .code = &conv_gmr1_tch3_speech,
256 .in_len = 48,
257 .out_len = 72,
258 .has_vec = 1,
Vadim Yanitskiyd8494bc2017-01-15 13:00:47 +0700259 .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c },
Max Suraev msuraev@sysmocom.de84da22f2016-04-29 13:17:22 +0200260 .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 },
261 },
262 {
263 .name = "WiMax FCH (non-recursive, tail-biting, not punctured)",
264 .code = &conv_wimax_fch,
265 .in_len = 48,
266 .out_len = 96,
267 .has_vec = 1,
268 .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 },
269 .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42,
270 0x8a, 0xed, 0x21, 0xed },
271 },
272 {
Vadim Yanitskiy12142952017-01-15 12:55:57 +0700273 .name = "LTE PBCH (non-recursive, tail-biting, non-punctured)",
274 .code = &conv_lte_pbch,
275 .in_len = 40,
276 .out_len = 120,
277 .has_vec = 0,
278 .vec_in = { },
279 .vec_out = { },
280 },
281 {
Max Suraev msuraev@sysmocom.de84da22f2016-04-29 13:17:22 +0200282 .name = "??? (non-recursive, direct truncation, not punctured)",
283 .code = &conv_trunc,
284 .in_len = 224,
285 .out_len = 448,
286 .has_vec = 1,
287 .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a,
288 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9,
289 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07,
290 0xac, 0x63, 0xe2, 0x9c,
291 },
292 .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69,
293 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61,
294 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49,
295 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63,
296 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4,
297 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a,
298 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 },
299 },
300 { /* end */ },
301 };
302
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100303 srandom(time(NULL));
304
305 bu0 = malloc(sizeof(ubit_t) * MAX_LEN_BITS);
306 bu1 = malloc(sizeof(ubit_t) * MAX_LEN_BITS);
307 bs = malloc(sizeof(sbit_t) * MAX_LEN_BITS);
308
309 for (tst=tests; tst->name; tst++)
310 {
311 int i,l;
312
313 /* Test name */
314 printf("[+] Testing: %s\n", tst->name);
315
316 /* Check length */
317 l = osmo_conv_get_input_length(tst->code, 0);
318 printf("[.] Input length : ret = %3d exp = %3d -> %s\n",
319 l, tst->in_len, l == tst->in_len ? "OK" : "Bad !");
320
321 if (l != tst->in_len) {
322 fprintf(stderr, "[!] Failure for input length computation\n");
323 return -1;
324 }
325
326 l = osmo_conv_get_output_length(tst->code, 0);
327 printf("[.] Output length : ret = %3d exp = %3d -> %s\n",
328 l, tst->out_len, l == tst->out_len ? "OK" : "Bad !");
329
330 if (l != tst->out_len) {
331 fprintf(stderr, "[!] Failure for output length computation\n");
332 return -1;
333 }
334
335 /* Check pre-computed vector */
336 if (tst->has_vec) {
337 printf("[.] Pre computed vector checks:\n");
338
339 printf("[..] Encoding: ");
340
341 osmo_pbit2ubit(bu0, tst->vec_in, tst->in_len);
342
343 l = osmo_conv_encode(tst->code, bu0, bu1);
344 if (l != tst->out_len) {
345 printf("ERROR !\n");
346 fprintf(stderr, "[!] Failed encoding length check\n");
347 return -1;
348 }
349
350 osmo_pbit2ubit(bu0, tst->vec_out, tst->out_len);
351
352 if (memcmp(bu0, bu1, tst->out_len)) {
353 printf("ERROR !\n");
354 fprintf(stderr, "[!] Failed encoding: Results don't match\n");
355 return -1;
356 };
357
358 printf("OK\n");
359
360
361 printf("[..] Decoding: ");
362
Maxd8fb1422016-04-06 16:13:00 +0200363 osmo_ubit2sbit(bs, bu0, l);
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100364
365 l = osmo_conv_decode(tst->code, bs, bu1);
366 if (l != 0) {
367 printf("ERROR !\n");
368 fprintf(stderr, "[!] Failed decoding: non-zero path (%d)\n", l);
369 return -1;
370 }
371
372 osmo_pbit2ubit(bu0, tst->vec_in, tst->in_len);
373
374 if (memcmp(bu0, bu1, tst->in_len)) {
375 printf("ERROR !\n");
376 fprintf(stderr, "[!] Failed decoding: Results don't match\n");
377 return -1;
378 }
379
380 printf("OK\n");
381 }
382
383 /* Check random vector */
384 printf("[.] Random vector checks:\n");
385
386 for (i=0; i<3; i++) {
387 printf("[..] Encoding / Decoding cycle : ");
388
389 fill_random(bu0, tst->in_len);
390
391 l = osmo_conv_encode(tst->code, bu0, bu1);
392 if (l != tst->out_len) {
393 printf("ERROR !\n");
394 fprintf(stderr, "[!] Failed encoding length check\n");
395 return -1;
396 }
397
Maxd8fb1422016-04-06 16:13:00 +0200398 osmo_ubit2sbit(bs, bu1, l);
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100399
400 l = osmo_conv_decode(tst->code, bs, bu1);
401 if (l != 0) {
402 printf("ERROR !\n");
403 fprintf(stderr, "[!] Failed decoding: non-zero path (%d)\n", l);
404 return -1;
405 }
406
407 if (memcmp(bu0, bu1, tst->in_len)) {
408 printf("ERROR !\n");
409 fprintf(stderr, "[!] Failed decoding: Results don't match\n");
410 return -1;
411 }
412
413 printf("OK\n");
414 }
415
416 /* Spacing */
417 printf("\n");
418 }
419
420 free(bs);
421 free(bu1);
422 free(bu0);
423
424 return 0;
425}