blob: 16db5eb1ebb661f7ce939e03122d3bb65392c970 [file] [log] [blame]
piotrfaacc722014-07-20 23:48:32 +02001//#include "system.h"
2#include <stdio.h>
3#include <stdlib.h>
4#include <unistd.h>
5#include <string.h>
6#include <ctype.h>
7
8//#include <exception>
9//#include <stdexcept>
10#include <math.h>
11//#include "burst_types.h"
12#include "cch.h"
13#include "fire_crc.h"
14
15
16/*
17 * GSM SACCH -- Slow Associated Control Channel
18 *
19 * These messages are encoded exactly the same as on the BCCH.
20 * (Broadcast Control Channel.)
21 *
22 * Input: 184 bits
23 *
24 * 1. Add parity and flushing bits. (Output 184 + 40 + 4 = 228 bit)
25 * 2. Convolutional encode. (Output 228 * 2 = 456 bit)
26 * 3. Interleave. (Output 456 bit)
27 * 4. Map on bursts. (4 x 156 bit bursts with each 2x57 bit content data)
28 */
29
30
31/*
32 * Parity (FIRE) for the GSM SACCH channel.
33 *
34 * g(x) = (x^23 + 1)(x^17 + x^3 + 1)
35 * = x^40 + x^26 + x^23 + x^17 + x^3 + 1
36 */
37
38static const unsigned char parity_polynomial[PARITY_SIZE + 1] = {
39 1, 0, 0, 0, 0, 0, 0, 0,
40 0, 0, 0, 0, 0, 0, 1, 0,
41 0, 1, 0, 0, 0, 0, 0, 1,
42 0, 0, 0, 0, 0, 0, 0, 0,
43 0, 0, 0, 0, 0, 1, 0, 0,
44 1
45};
46
47// remainder after dividing data polynomial by g(x)
48static const unsigned char parity_remainder[PARITY_SIZE] = {
49 1, 1, 1, 1, 1, 1, 1, 1,
50 1, 1, 1, 1, 1, 1, 1, 1,
51 1, 1, 1, 1, 1, 1, 1, 1,
52 1, 1, 1, 1, 1, 1, 1, 1,
53 1, 1, 1, 1, 1, 1, 1, 1
54};
55
56
57/*
58static void parity_encode(unsigned char *d, unsigned char *p) {
59
60 int i;
61 unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
62
63 memcpy(buf, d, DATA_BLOCK_SIZE);
64 memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE);
65
66 for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
67 if(*q)
68 for(i = 0; i < PARITY_SIZE + 1; i++)
69 q[i] ^= parity_polynomial[i];
70 for(i = 0; i < PARITY_SIZE; i++)
71 p[i] = !buf[DATA_BLOCK_SIZE + i];
72}
73 */
74
75
76int parity_check(unsigned char *d) {
77
78 unsigned int i;
79 unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
80
81 memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE);
82
83 for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
84 if(*q)
85 for(i = 0; i < PARITY_SIZE + 1; i++)
86 q[i] ^= parity_polynomial[i];
87 return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE);
88}
89
90
91/*
92 * Convolutional encoding and Viterbi decoding for the GSM SACCH channel.
93 */
94
95/*
96 * Convolutional encoding:
97 *
98 * G_0 = 1 + x^3 + x^4
99 * G_1 = 1 + x + x^3 + x^4
100 *
101 * i.e.,
102 *
103 * c_{2k} = u_k + u_{k - 3} + u_{k - 4}
104 * c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4}
105 */
106#define K 5
107#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1)
108
109
110/*
111 * Given the current state and input bit, what are the output bits?
112 *
113 * encode[current_state][input_bit]
114 */
115static const unsigned int encode[1 << (K - 1)][2] = {
116 {0, 3}, {3, 0}, {3, 0}, {0, 3},
117 {0, 3}, {3, 0}, {3, 0}, {0, 3},
118 {1, 2}, {2, 1}, {2, 1}, {1, 2},
119 {1, 2}, {2, 1}, {2, 1}, {1, 2}
120};
121
122
123/*
124 * Given the current state and input bit, what is the next state?
125 *
126 * next_state[current_state][input_bit]
127 */
128static const unsigned int next_state[1 << (K - 1)][2] = {
129 {0, 8}, {0, 8}, {1, 9}, {1, 9},
130 {2, 10}, {2, 10}, {3, 11}, {3, 11},
131 {4, 12}, {4, 12}, {5, 13}, {5, 13},
132 {6, 14}, {6, 14}, {7, 15}, {7, 15}
133};
134
135
136/*
137 * Given the previous state and the current state, what input bit caused
138 * the transition? If it is impossible to transition between the two
139 * states, the value is 2.
140 *
141 * prev_next_state[previous_state][current_state]
142 */
143static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = {
144 { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
145 { 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
146 { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
147 { 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
148 { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
149 { 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
150 { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
151 { 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
152 { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
153 { 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
154 { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
155 { 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
156 { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
157 { 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
158 { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1},
159 { 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}
160};
161
162
163static inline unsigned int hamming_distance2(unsigned int w) {
164
165 return (w & 1) + !!(w & 2);
166}
167
168
169/*
170static void conv_encode(unsigned char *data, unsigned char *output) {
171
172 unsigned int i, state = 0, o;
173
174 // encode data
175 for(i = 0; i < CONV_INPUT_SIZE; i++) {
176 o = encode[state][data[i]];
177 state = next_state[state][data[i]];
178 *output++ = !!(o & 2);
179 *output++ = o & 1;
180 }
181}
182 */
183
184
185int conv_decode(unsigned char *output, unsigned char *data) {
186
187 int i, t;
188 unsigned int rdata, state, nstate, b, o, distance, accumulated_error,
189 min_state, min_error, cur_state;
190
191 unsigned int ae[1 << (K - 1)]; // accumulated error
192 unsigned int nae[1 << (K - 1)]; // next accumulated error
193 unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1];
194
195 // initialize accumulated error, assume starting state is 0
196 for(i = 0; i < (1 << (K - 1)); i++){
197 ae[i] = nae[i] = MAX_ERROR;
198 }
199
200 ae[0] = 0;
201
202 // build trellis
203 for(t = 0; t < CONV_INPUT_SIZE; t++) {
204
205 // get received data symbol
206 rdata = (data[2 * t] << 1) | data[2 * t + 1];
207
208 // for each state
209 for(state = 0; state < (1 << (K - 1)); state++) {
210
211 // make sure this state is possible
212 if(ae[state] >= MAX_ERROR)
213 continue;
214
215 // find all states we lead to
216 for(b = 0; b < 2; b++) {
217
218 // get next state given input bit b
219 nstate = next_state[state][b];
220
221 // find output for this transition
222 o = encode[state][b];
223
224 // calculate distance from received data
225 distance = hamming_distance2(rdata ^ o);
226
227 // choose surviving path
228 accumulated_error = ae[state] + distance;
229 if(accumulated_error < nae[nstate]) {
230
231 // save error for surviving state
232 nae[nstate] = accumulated_error;
233
234 // update state history
235 state_history[nstate][t + 1] = state;
236 }
237 }
238 }
239
240 // get accumulated error ready for next time slice
241 for(i = 0; i < (1 << (K - 1)); i++) {
242 ae[i] = nae[i];
243 nae[i] = MAX_ERROR;
244 }
245 }
246
247 // the final state is the state with the fewest errors
248 min_state = (unsigned int)-1;
249 min_error = MAX_ERROR;
250 for(i = 0; i < (1 << (K - 1)); i++) {
251 if(ae[i] < min_error) {
252 min_state = i;
253 min_error = ae[i];
254 }
255 }
256
257 // trace the path
258 cur_state = min_state;
259 for(t = CONV_INPUT_SIZE; t >= 1; t--) {
260 min_state = cur_state;
261 cur_state = state_history[cur_state][t]; // get previous
262 output[t - 1] = prev_next_state[cur_state][min_state];
263 }
264
265 // return the number of errors detected (hard-decision)
266 return min_error;
267}
268
269
270/*
271 * GSM SACCH interleaving and burst mapping
272 *
273 * Interleaving:
274 *
275 * Given 456 coded input bits, form 4 blocks of 114 bits:
276 *
277 * i(B, j) = c(n, k) k = 0, ..., 455
278 * n = 0, ..., N, N + 1, ...
279 * B = B_0 + 4n + (k mod 4)
280 * j = 2(49k mod 57) + ((k mod 8) div 4)
281 *
282 * Mapping on Burst:
283 *
284 * e(B, j) = i(B, j)
285 * e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
286 * e(B, 57) = h_l(B)
287 * e(B, 58) = h_n(B)
288 *
289 * Where h_l(B) and h_n(B) are bits in burst B indicating flags.
290 */
291
292/*
293static void interleave(unsigned char *data, unsigned char *iBLOCK) {
294
295 int j, k, B;
296
297 // for each bit in input data
298 for(k = 0; k < CONV_SIZE; k++) {
299 B = k % 4;
300 j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
301 iBLOCK[B * iBLOCK_SIZE + j] = data[k];
302 }
303}
304 */
305
306
307#if 0
308static void decode_interleave(unsigned char *data, unsigned char *iBLOCK) {
309
310 int j, k, B;
311
312 for(k = 0; k < CONV_SIZE; k++) {
313 B = k % 4;
314 j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
315 data[k] = iBLOCK[B * iBLOCK_SIZE + j];
316 }
317}
318
319#endif
320
321/*
322static void burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
323 unsigned char hl, unsigned char hn) {
324
325 int j;
326
327 for(j = 0; j < 57; j++) {
328 eBLOCK[j] = iBLOCK[j];
329 eBLOCK[j + 59] = iBLOCK[j + 57];
330 }
331 eBLOCK[57] = hl;
332 eBLOCK[58] = hn;
333}
334 */
335
336
337static void decode_burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
338 unsigned char *hl, unsigned char *hn) {
339
340 int j;
341
342 for(j = 0; j < 57; j++) {
343 iBLOCK[j] = eBLOCK[j];
344 iBLOCK[j + 57] = eBLOCK[j + 59];
345 }
346 *hl = eBLOCK[57];
347 *hn = eBLOCK[58];
348}
349
350
351/*
352 * Transmitted bits are sent least-significant first.
353 */
354static int compress_bits(unsigned char *dbuf, unsigned int dbuf_len,
355 unsigned char *sbuf, unsigned int sbuf_len) {
356
357 unsigned int i, j, c, pos = 0;
358
359 if(dbuf_len < ((sbuf_len + 7) >> 3))
360 return -1;
361
362 for(i = 0; i < sbuf_len; i += 8) {
363 for(j = 0, c = 0; (j < 8) && (i + j < sbuf_len); j++)
364 c |= (!!sbuf[i + j]) << j;
365 dbuf[pos++] = c & 0xff;
366 }
367 return pos;
368}
369
370
371#if 0
372int get_ns_l3_len(unsigned char *data, unsigned int datalen) {
373
374 if((data[0] & 3) != 1) {
375 fprintf(stderr, "error: get_ns_l3_len: pseudo-length reserved "
376 "bits bad (%2.2x)\n", data[0] & 3);
377 return -1;
378 }
379 return (data[0] >> 2);
380}
381
382#endif
383
384
385/*static unsigned char *decode_sacch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) {*/
386
387/* int errors, len, data_size;*/
388/* unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS][iBLOCK_SIZE],*/
389/* hl, hn, decoded_data[PARITY_OUTPUT_SIZE];*/
390/* FC_CTX fc_ctx;*/
391
392/* data_size = sizeof ctx->msg;*/
393/* if(datalen)*/
394/* *datalen = 0;*/
395
396/* // unmap the bursts*/
397/* decode_burstmap(iBLOCK[0], burst, &hl, &hn); // XXX ignore stealing bits*/
398/* decode_burstmap(iBLOCK[1], burst + 116, &hl, &hn);*/
399/* decode_burstmap(iBLOCK[2], burst + 116 * 2, &hl, &hn);*/
400/* decode_burstmap(iBLOCK[3], burst + 116 * 3, &hl, &hn);*/
401
402/* // remove interleave*/
403/* interleave_decode(&ctx->interleave_ctx, conv_data, (unsigned char *)iBLOCK);*/
404/* //decode_interleave(conv_data, (unsigned char *)iBLOCK);*/
405
406/* // Viterbi decode*/
407/* errors = conv_decode(decoded_data, conv_data);*/
408/* //DEBUGF("conv_decode: %d\n", errors);*/
409
410/* // check parity*/
411/* // If parity check error detected try to fix it.*/
412/* if (parity_check(decoded_data))*/
413/* {*/
414/* unsigned char crc_result[224];*/
415/* if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)*/
416/* {*/
417/* errors = -1;*/
418/* //DEBUGF("error: sacch: parity error (%d fn=%d)\n",*/
419/* // errors, ctx->fn);*/
420/* return NULL;*/
421/* } else {*/
422/* //DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n",*/
423/* // errors, ctx->fn);*/
424/* memcpy(decoded_data, crc_result, sizeof crc_result);*/
425/* errors = 0;*/
426/* }*/
427/* }*/
428
429/* if (errors)*/
430/* printf("WRN: errors=%d fn=%d\n", errors, ctx->fn);*/
431
432/* if((len = compress_bits(ctx->msg, data_size, decoded_data,*/
433/* DATA_BLOCK_SIZE)) < 0) {*/
434/* fprintf(stderr, "error: compress_bits\n");*/
435/* return NULL;*/
436/* }*/
437/* if(len < data_size) {*/
438/* fprintf(stderr, "error: buf too small (%d < %d)\n",*/
439/* sizeof(ctx->msg), len);*/
440/* return NULL;*/
441/* }*/
442
443/* if(datalen)*/
444/* *datalen = (unsigned int)len;*/
445/* return ctx->msg;*/
446/*}*/
447
448
449/*
450 * decode_cch
451 *
452 * Decode a "common" control channel. Most control channels use
453 * the same burst, interleave, Viterbi and parity configuration.
454 * The documentation for the control channels defines SACCH first
455 * and then just keeps referring to that.
456 *
457 * The current (investigated) list is as follows:
458 *
459 * BCCH Norm
460 * BCCH Ext
461 * PCH
462 * AGCH
463 * CBCH (SDCCH/4)
464 * CBCH (SDCCH/8)
465 * SDCCH/4
466 * SACCH/C4
467 * SDCCH/8
468 * SACCH/C8
469 *
470 * We provide two functions, one for where all four bursts are
471 * contiguous, and one where they aren't.
472 */
473/*unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) {*/
474
475/* return decode_sacch(ctx, burst, datalen);*/
476/*}*/
477
478
479#if 0
480unsigned char *decode_cch(GS_CTX *ctx, unsigned char *e, unsigned int *datalen) {
481
482 return decode_sacch(ctx, e, e + eBLOCK_SIZE, e + 2 * eBLOCK_SIZE,
483 e + 3 * eBLOCK_SIZE, datalen);
484}
485#endif
486
487/*unsigned char *decode_facch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen, int offset) {*/
488
489/* int errors, len, data_size;*/
490/* unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS * 2][iBLOCK_SIZE],*/
491/* hl, hn, decoded_data[PARITY_OUTPUT_SIZE];*/
492/* FC_CTX fc_ctx;*/
493
494/* data_size = sizeof ctx->msg;*/
495/* if(datalen)*/
496/* *datalen = 0;*/
497
498/* // unmap the bursts*/
499/* decode_burstmap(iBLOCK[0], burst, &hl, &hn); // XXX ignore stealing bits*/
500/* decode_burstmap(iBLOCK[1], burst + 116, &hl, &hn);*/
501/* decode_burstmap(iBLOCK[2], burst + 116 * 2, &hl, &hn);*/
502/* decode_burstmap(iBLOCK[3], burst + 116 * 3, &hl, &hn);*/
503/* decode_burstmap(iBLOCK[4], burst + 116 * 4, &hl, &hn);*/
504/* decode_burstmap(iBLOCK[5], burst + 116 * 5, &hl, &hn);*/
505/* decode_burstmap(iBLOCK[6], burst + 116 * 6, &hl, &hn);*/
506/* decode_burstmap(iBLOCK[7], burst + 116 * 7, &hl, &hn);*/
507
508/* // remove interleave*/
509/* if (offset == 0)*/
510/* interleave_decode(&ctx->interleave_facch_f1_ctx, conv_data, (unsigned char *)iBLOCK);*/
511/* else*/
512/* interleave_decode(&ctx->interleave_facch_f2_ctx, conv_data, (unsigned char *)iBLOCK);*/
513/* //decode_interleave(conv_data, (unsigned char *)iBLOCK);*/
514
515/* // Viterbi decode*/
516/* errors = conv_decode(decoded_data, conv_data);*/
517/* //DEBUGF("conv_decode: %d\n", errors);*/
518
519/* // check parity*/
520/* // If parity check error detected try to fix it.*/
521/* if (parity_check(decoded_data)) {*/
522/* FC_init(&fc_ctx, 40, 184);*/
523/* unsigned char crc_result[224];*/
524/* if (FC_check_crc(&fc_ctx, decoded_data, crc_result) == 0)*/
525/* {*/
526/* //DEBUGF("error: sacch: parity error (errors=%d fn=%d)\n", errors, ctx->fn);*/
527/* errors = -1;*/
528/* return NULL;*/
529/* } else {*/
530/* //DEBUGF("Successfully corrected parity bits! (errors=%d fn=%d)\n", errors, ctx->fn);*/
531/* memcpy(decoded_data, crc_result, sizeof crc_result);*/
532/* errors = 0;*/
533/* }*/
534/* }*/
535
536/* if (errors)*/
537/* fprintf(stderr, "WRN: errors=%d fn=%d\n", errors, ctx->fn);*/
538
539/* if ((len = compress_bits(ctx->msg, data_size, decoded_data,*/
540/* DATA_BLOCK_SIZE)) < 0) {*/
541/* fprintf(stderr, "error: compress_bits\n");*/
542/* return NULL;*/
543/* }*/
544/* if (len < data_size) {*/
545/* fprintf(stderr, "error: buf too small (%d < %d)\n",*/
546/* sizeof(ctx->msg), len);*/
547/* return NULL;*/
548/* }*/
549
550/* if (datalen)*/
551/* *datalen = (unsigned int)len;*/
552/* return ctx->msg;*/
553/*}*/