blob: 608f829bf8f0c53442e94cd0201c51de759c567f [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
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100123/* ------------------------------------------------------------------------ */
124/* Test vectors */
125/* ------------------------------------------------------------------------ */
126
127struct conv_test_vector {
128 const char *name;
129 const struct osmo_conv_code *code;
130 int in_len;
131 int out_len;
132 int has_vec;
133 pbit_t vec_in[MAX_LEN_BYTES];
134 pbit_t vec_out[MAX_LEN_BYTES];
135};
136
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100137/* ------------------------------------------------------------------------ */
138/* Main */
139/* ------------------------------------------------------------------------ */
140
141static void
142fill_random(ubit_t *b, int n)
143{
144 int i;
145 for (i=0; i<n; i++)
146 b[i] = random() & 1;
147}
148
Jacob Erlbeck3c761c82013-08-14 18:13:46 +0200149int main(int argc, char *argv[])
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100150{
151 const struct conv_test_vector *tst;
152 ubit_t *bu0, *bu1;
153 sbit_t *bs;
154
Max Suraev msuraev@sysmocom.de84da22f2016-04-29 13:17:22 +0200155/* Random code -> Non recursive code, direct truncation, non-punctured */
156 const struct osmo_conv_code conv_trunc = {
157 .N = 2,
158 .K = 5,
159 .len = 224,
160 .term = CONV_TERM_TRUNCATION,
161 .next_output = gsm0503_xcch.next_output,
162 .next_state = gsm0503_xcch.next_state,
163 };
164
165 const struct conv_test_vector tests[] = {
166 {
167 .name = "GSM xCCH (non-recursive, flushed, not punctured)",
168 .code = &gsm0503_xcch,
169 .in_len = 224,
170 .out_len = 456,
171 .has_vec = 1,
172 .vec_in = { 0xf3, 0x1d, 0xb4, 0x0c, 0x4d, 0x1d, 0x9d, 0xae,
173 0xc0, 0x0a, 0x42, 0x57, 0x13, 0x60, 0x80, 0x96,
174 0xef, 0x23, 0x7e, 0x4c, 0x1d, 0x96, 0x24, 0x19,
175 0x17, 0xf2, 0x44, 0x99 },
176 .vec_out = { 0xe9, 0x4d, 0x70, 0xab, 0xa2, 0x87, 0xf0, 0xe7,
177 0x04, 0x14, 0x7c, 0xab, 0xaf, 0x6b, 0xa1, 0x16,
178 0xeb, 0x30, 0x00, 0xde, 0xc8, 0xfd, 0x0b, 0x85,
179 0x80, 0x41, 0x4a, 0xcc, 0xd3, 0xc0, 0xd0, 0xb6,
180 0x26, 0xe5, 0x4e, 0x32, 0x49, 0x69, 0x38, 0x17,
181 0x33, 0xab, 0xaf, 0xb6, 0xc1, 0x08, 0xf3, 0x9f,
182 0x8c, 0x75, 0x6a, 0x4e, 0x08, 0xc4, 0x20, 0x5f,
183 0x8f },
184 },
185 {
186 .name = "GSM TCH/AFS 7.95 (recursive, flushed, punctured)",
187 .code = &gsm0503_tch_afs_7_95,
188 .in_len = 165,
189 .out_len = 448,
190 .has_vec = 1,
191 .vec_in = { 0x87, 0x66, 0xc3, 0x58, 0x09, 0xd4, 0x06, 0x59,
192 0x10, 0xbf, 0x6b, 0x7f, 0xc8, 0xed, 0x72, 0xaa,
193 0xc1, 0x3d, 0xf3, 0x1e, 0xb0 },
194 .vec_out = { 0x92, 0xbc, 0xde, 0xa0, 0xde, 0xbe, 0x01, 0x2f,
195 0xbe, 0xe4, 0x61, 0x32, 0x4d, 0x4f, 0xdc, 0x41,
196 0x43, 0x0d, 0x15, 0xe0, 0x23, 0xdd, 0x18, 0x91,
197 0xe5, 0x36, 0x2d, 0xb7, 0xd9, 0x78, 0xb8, 0xb1,
198 0xb7, 0xcb, 0x2f, 0xc0, 0x52, 0x8f, 0xe2, 0x8c,
199 0x6f, 0xa6, 0x79, 0x88, 0xed, 0x0c, 0x2e, 0x9e,
200 0xa1, 0x5f, 0x45, 0x4a, 0xfb, 0xe6, 0x5a, 0x9c },
201 },
202 {
203 .name = "GMR-1 TCH3 Speech (non-recursive, tail-biting, punctured)",
204 .code = &conv_gmr1_tch3_speech,
205 .in_len = 48,
206 .out_len = 72,
207 .has_vec = 1,
208 .vec_in = { 0x4d, 0xcb, 0xfc, 0x72, 0xf4, 0x8c },
209 .vec_out = { 0xc0, 0x86, 0x63, 0x4b, 0x8b, 0xd4, 0x6a, 0x76, 0xb2 },
210 },
211 {
212 .name = "WiMax FCH (non-recursive, tail-biting, not punctured)",
213 .code = &conv_wimax_fch,
214 .in_len = 48,
215 .out_len = 96,
216 .has_vec = 1,
217 .vec_in = { 0xfc, 0xa0, 0xa0, 0xfc, 0xa0, 0xa0 },
218 .vec_out = { 0x19, 0x42, 0x8a, 0xed, 0x21, 0xed, 0x19, 0x42,
219 0x8a, 0xed, 0x21, 0xed },
220 },
221 {
222 .name = "??? (non-recursive, direct truncation, not punctured)",
223 .code = &conv_trunc,
224 .in_len = 224,
225 .out_len = 448,
226 .has_vec = 1,
227 .vec_in = { 0xe5, 0xe0, 0x85, 0x7e, 0xf7, 0x08, 0x19, 0x5a,
228 0xb9, 0xad, 0x82, 0x37, 0x98, 0x8b, 0x26, 0xb9,
229 0x81, 0x26, 0x9c, 0x75, 0xaf, 0xf3, 0xcb, 0x07,
230 0xac, 0x63, 0xe2, 0x9c,
231 },
232 .vec_out = { 0xea, 0x3b, 0x55, 0x0c, 0xd3, 0xf7, 0x85, 0x69,
233 0xe5, 0x79, 0x83, 0xd3, 0xc3, 0x9f, 0xb8, 0x61,
234 0x21, 0x63, 0x51, 0x18, 0xac, 0xcd, 0x32, 0x49,
235 0x53, 0x5c, 0x13, 0x1d, 0xbe, 0x05, 0x11, 0x63,
236 0x5c, 0xc3, 0x42, 0x05, 0x1c, 0x68, 0x0a, 0xb4,
237 0x61, 0x15, 0xaa, 0x4d, 0x94, 0xed, 0xb3, 0x3a,
238 0x5d, 0x1b, 0x09, 0xc2, 0x99, 0x01, 0xec, 0x68 },
239 },
240 { /* end */ },
241 };
242
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100243 srandom(time(NULL));
244
245 bu0 = malloc(sizeof(ubit_t) * MAX_LEN_BITS);
246 bu1 = malloc(sizeof(ubit_t) * MAX_LEN_BITS);
247 bs = malloc(sizeof(sbit_t) * MAX_LEN_BITS);
248
249 for (tst=tests; tst->name; tst++)
250 {
251 int i,l;
252
253 /* Test name */
254 printf("[+] Testing: %s\n", tst->name);
255
256 /* Check length */
257 l = osmo_conv_get_input_length(tst->code, 0);
258 printf("[.] Input length : ret = %3d exp = %3d -> %s\n",
259 l, tst->in_len, l == tst->in_len ? "OK" : "Bad !");
260
261 if (l != tst->in_len) {
262 fprintf(stderr, "[!] Failure for input length computation\n");
263 return -1;
264 }
265
266 l = osmo_conv_get_output_length(tst->code, 0);
267 printf("[.] Output length : ret = %3d exp = %3d -> %s\n",
268 l, tst->out_len, l == tst->out_len ? "OK" : "Bad !");
269
270 if (l != tst->out_len) {
271 fprintf(stderr, "[!] Failure for output length computation\n");
272 return -1;
273 }
274
275 /* Check pre-computed vector */
276 if (tst->has_vec) {
277 printf("[.] Pre computed vector checks:\n");
278
279 printf("[..] Encoding: ");
280
281 osmo_pbit2ubit(bu0, tst->vec_in, tst->in_len);
282
283 l = osmo_conv_encode(tst->code, bu0, bu1);
284 if (l != tst->out_len) {
285 printf("ERROR !\n");
286 fprintf(stderr, "[!] Failed encoding length check\n");
287 return -1;
288 }
289
290 osmo_pbit2ubit(bu0, tst->vec_out, tst->out_len);
291
292 if (memcmp(bu0, bu1, tst->out_len)) {
293 printf("ERROR !\n");
294 fprintf(stderr, "[!] Failed encoding: Results don't match\n");
295 return -1;
296 };
297
298 printf("OK\n");
299
300
301 printf("[..] Decoding: ");
302
Maxd8fb1422016-04-06 16:13:00 +0200303 osmo_ubit2sbit(bs, bu0, l);
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100304
305 l = osmo_conv_decode(tst->code, bs, bu1);
306 if (l != 0) {
307 printf("ERROR !\n");
308 fprintf(stderr, "[!] Failed decoding: non-zero path (%d)\n", l);
309 return -1;
310 }
311
312 osmo_pbit2ubit(bu0, tst->vec_in, tst->in_len);
313
314 if (memcmp(bu0, bu1, tst->in_len)) {
315 printf("ERROR !\n");
316 fprintf(stderr, "[!] Failed decoding: Results don't match\n");
317 return -1;
318 }
319
320 printf("OK\n");
321 }
322
323 /* Check random vector */
324 printf("[.] Random vector checks:\n");
325
326 for (i=0; i<3; i++) {
327 printf("[..] Encoding / Decoding cycle : ");
328
329 fill_random(bu0, tst->in_len);
330
331 l = osmo_conv_encode(tst->code, bu0, bu1);
332 if (l != tst->out_len) {
333 printf("ERROR !\n");
334 fprintf(stderr, "[!] Failed encoding length check\n");
335 return -1;
336 }
337
Maxd8fb1422016-04-06 16:13:00 +0200338 osmo_ubit2sbit(bs, bu1, l);
Sylvain Munaut29eb92d2011-11-24 17:48:42 +0100339
340 l = osmo_conv_decode(tst->code, bs, bu1);
341 if (l != 0) {
342 printf("ERROR !\n");
343 fprintf(stderr, "[!] Failed decoding: non-zero path (%d)\n", l);
344 return -1;
345 }
346
347 if (memcmp(bu0, bu1, tst->in_len)) {
348 printf("ERROR !\n");
349 fprintf(stderr, "[!] Failed decoding: Results don't match\n");
350 return -1;
351 }
352
353 printf("OK\n");
354 }
355
356 /* Spacing */
357 printf("\n");
358 }
359
360 free(bs);
361 free(bu1);
362 free(bu0);
363
364 return 0;
365}