summaryrefslogtreecommitdiff
path: root/gsmstack/tch.c
diff options
context:
space:
mode:
authorHarald Welte <laforge@gnumonks.org>2008-12-01 10:28:04 +0530
committerHarald Welte <laforge@gnumonks.org>2008-12-01 10:28:04 +0530
commit10f2fcca8dd1be2719bccefa16fd9dac9a76c749 (patch)
tree0b521a2ccc7d0d81a89e08b05650dec2421777d2 /gsmstack/tch.c
parentfd405f799425b6832a0c9cc7a56b07f43288b8b1 (diff)
[gsmdecode] import {interleave,conv}.[ch] from gsm-tvoid
* change convolutional decode to cope with TCH * add tch.c file with reordering/decoding for TCH/F
Diffstat (limited to 'gsmstack/tch.c')
-rw-r--r--gsmstack/tch.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/gsmstack/tch.c b/gsmstack/tch.c
new file mode 100644
index 0000000..f8b4329
--- /dev/null
+++ b/gsmstack/tch.c
@@ -0,0 +1,145 @@
+
+/* GSM TCH/F channel coding
+ *
+ * (C) 2008 by Harald Welte <laforge@gnumonks.org>
+ */
+
+#include "system.h"
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <ctype.h>
+#include <math.h>
+
+#include "burst_types.h"
+#include "tch.h"
+//#include "fire_crc.h"
+
+/*
+ * GSM TCH/F -- Traffic Channel (Full Rate)
+ *
+ * Input: 260 bits (182 class-1, 78 class-2 bits)
+ *
+ * 1. Rearrange according to Table 2 (TS 05.03)
+ * 2. Add 3 parity bits for first 50 class-1 bits (d0...49)
+ * 3. Add four tailing bits to class-1. (Output 182 + 3 + 4 = 189 bit)
+ * 4. Convolutional encode of class-1 (Output = 189 * 2 = 378 bit)
+ * 5. Append class-2 bits (Output = 378 + 78 = 456bit)
+ * 3. Interleave. (Output 456 bit)
+ * 4. Map on bursts. (4 x 156 bit bursts with each 2x57 bit content data)
+ */
+
+
+#if 0
+/*
+ * Parity (FIRE) for the GSM SACCH channel.
+ *
+ * g(x) = (x^23 + 1)(x^17 + x^3 + 1)
+ * = x^40 + x^26 + x^23 + x^17 + x^3 + 1
+ */
+
+static const unsigned char parity_polynomial[PARITY_SIZE + 1] = {
+ 1, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 0, 1, 0,
+ 0, 1, 0, 0, 0, 0, 0, 1,
+ 0, 0, 0, 0, 0, 0, 0, 0,
+ 0, 0, 0, 0, 0, 1, 0, 0,
+ 1
+};
+
+// remainder after dividing data polynomial by g(x)
+static const unsigned char parity_remainder[PARITY_SIZE] = {
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1,
+ 1, 1, 1, 1, 1, 1, 1, 1
+};
+
+
+/*
+static void parity_encode(unsigned char *d, unsigned char *p) {
+
+ int i;
+ unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
+
+ memcpy(buf, d, DATA_BLOCK_SIZE);
+ memset(buf + DATA_BLOCK_SIZE, 0, PARITY_SIZE);
+
+ for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
+ if(*q)
+ for(i = 0; i < PARITY_SIZE + 1; i++)
+ q[i] ^= parity_polynomial[i];
+ for(i = 0; i < PARITY_SIZE; i++)
+ p[i] = !buf[DATA_BLOCK_SIZE + i];
+}
+ */
+
+
+static int parity_check(unsigned char *d) {
+
+ unsigned int i;
+ unsigned char buf[DATA_BLOCK_SIZE + PARITY_SIZE], *q;
+
+ memcpy(buf, d, DATA_BLOCK_SIZE + PARITY_SIZE);
+
+ for(q = buf; q < buf + DATA_BLOCK_SIZE; q++)
+ if(*q)
+ for(i = 0; i < PARITY_SIZE + 1; i++)
+ q[i] ^= parity_polynomial[i];
+ return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE);
+}
+#endif
+
+static unsigned char *decode_tch_f(GS_CTX *ctx, unsigned char *burst,
+ unsigned int *datalen)
+{
+ int errors, len, data_size;
+ unsigned char conv_data[CONV_SIZE], iBLOCK[BLOCKS][iBLOCK_SIZE],
+ hl, hn, decoded_data[PARITY_OUTPUT_SIZE];
+ //FC_CTX fc_ctx;
+
+ data_size = sizeof ctx->msg;
+ if (datalen)
+ *datalen = 0;
+
+ // unmap the bursts
+ decode_burstmap(iBLOCK[0], burst, &hl, &hn); // XXX ignore stealing bits
+ decode_burstmap(iBLOCK[1], burst + 116, &hl, &hn);
+ decode_burstmap(iBLOCK[2], burst + 116 * 2, &hl, &hn);
+ decode_burstmap(iBLOCK[3], burst + 116 * 3, &hl, &hn);
+
+ // remove interleave
+ interleave_decode(&ctx->interleave_ctx, conv_data, (unsigned char *)iBLOCK);
+ //decode_interleave(conv_data, (unsigned char *)iBLOCK);
+
+ // Viterbi decode of class-1 bits
+ errors = conv_decode(decoded_data, conv_data, CONV_INPUT_SIZE_TCH_F);
+ if (errors) {
+ DEBUGF("conv_decode: %d\n", errors);
+ return NULL;
+ }
+ // reordering + remove four tailing bits (185..188)
+ for (i = 0; i <= 90; i++) {
+ ctx->msg[2*i] = decoded_data[i];
+ ctx->msg[2*i+1] = decoded_data[184-i];
+ }
+ len = 182;
+ // check 3 bit parity (91,92,93) of class-1 bits
+ /* FIXME */
+ // append class-2 bits
+ memcpy(ctx->msg+185, conv_data+(2*CONV_INPUT_SIZE_TCH_F), 78);
+ len += 78; /* should be 260 bits now */
+
+ if (len < data_size) {
+ fprintf(stderr, "error: buf too small (%d < %d)\n",
+ sizeof(ctx->msg), len);
+ return NULL;
+ }
+
+ if (datalen)
+ *datalen = (unsigned int)len;
+ return ctx->msg;
+}
personal git repositories of Harald Welte. Your mileage may vary