[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
This commit is contained in:
Harald Welte 2008-12-01 10:28:04 +05:30
parent fd405f7994
commit 10f2fcca8d
6 changed files with 473 additions and 290 deletions

View File

@ -1,4 +1,3 @@
/* This file was taken from gsm-tvoid */
#include "system.h"
@ -12,6 +11,7 @@
#include "burst_types.h"
#include "cch.h"
#include "conv.h"
#include "fire_crc.h"
/*
@ -88,251 +88,6 @@ static int parity_check(unsigned char *d) {
return memcmp(buf + DATA_BLOCK_SIZE, parity_remainder, PARITY_SIZE);
}
/*
* Convolutional encoding and Viterbi decoding for the GSM SACCH channel.
*/
/*
* Convolutional encoding:
*
* G_0 = 1 + x^3 + x^4
* G_1 = 1 + x + x^3 + x^4
*
* i.e.,
*
* c_{2k} = u_k + u_{k - 3} + u_{k - 4}
* c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4}
*/
#define K 5
#define MAX_ERROR (2 * CONV_INPUT_SIZE + 1)
/*
* Given the current state and input bit, what are the output bits?
*
* encode[current_state][input_bit]
*/
static const unsigned int encode[1 << (K - 1)][2] = {
{0, 3}, {3, 0}, {3, 0}, {0, 3},
{0, 3}, {3, 0}, {3, 0}, {0, 3},
{1, 2}, {2, 1}, {2, 1}, {1, 2},
{1, 2}, {2, 1}, {2, 1}, {1, 2}
};
/*
* Given the current state and input bit, what is the next state?
*
* next_state[current_state][input_bit]
*/
static const unsigned int next_state[1 << (K - 1)][2] = {
{0, 8}, {0, 8}, {1, 9}, {1, 9},
{2, 10}, {2, 10}, {3, 11}, {3, 11},
{4, 12}, {4, 12}, {5, 13}, {5, 13},
{6, 14}, {6, 14}, {7, 15}, {7, 15}
};
/*
* Given the previous state and the current state, what input bit caused
* the transition? If it is impossible to transition between the two
* states, the value is 2.
*
* prev_next_state[previous_state][current_state]
*/
static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = {
{ 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
{ 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
{ 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
{ 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
{ 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
{ 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
{ 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
{ 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
{ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
{ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
{ 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
{ 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
{ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
{ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
{ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1},
{ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}
};
static inline unsigned int hamming_distance2(unsigned int w) {
return (w & 1) + !!(w & 2);
}
/*
static void conv_encode(unsigned char *data, unsigned char *output) {
unsigned int i, state = 0, o;
// encode data
for(i = 0; i < CONV_INPUT_SIZE; i++) {
o = encode[state][data[i]];
state = next_state[state][data[i]];
*output++ = !!(o & 2);
*output++ = o & 1;
}
}
*/
static int conv_decode(unsigned char *output, unsigned char *data) {
int i, t;
unsigned int rdata, state, nstate, b, o, distance, accumulated_error,
min_state, min_error, cur_state;
unsigned int ae[1 << (K - 1)];
unsigned int nae[1 << (K - 1)]; // next accumulated error
unsigned int state_history[1 << (K - 1)][CONV_INPUT_SIZE + 1];
// initialize accumulated error, assume starting state is 0
for(i = 0; i < (1 << (K - 1)); i++)
ae[i] = nae[i] = MAX_ERROR;
ae[0] = 0;
// build trellis
for(t = 0; t < CONV_INPUT_SIZE; t++) {
// get received data symbol
rdata = (data[2 * t] << 1) | data[2 * t + 1];
// for each state
for(state = 0; state < (1 << (K - 1)); state++) {
// make sure this state is possible
if(ae[state] >= MAX_ERROR)
continue;
// find all states we lead to
for(b = 0; b < 2; b++) {
// get next state given input bit b
nstate = next_state[state][b];
// find output for this transition
o = encode[state][b];
// calculate distance from received data
distance = hamming_distance2(rdata ^ o);
// choose surviving path
accumulated_error = ae[state] + distance;
if(accumulated_error < nae[nstate]) {
// save error for surviving state
nae[nstate] = accumulated_error;
// update state history
state_history[nstate][t + 1] = state;
}
}
}
// get accumulated error ready for next time slice
for(i = 0; i < (1 << (K - 1)); i++) {
ae[i] = nae[i];
nae[i] = MAX_ERROR;
}
}
// the final state is the state with the fewest errors
min_state = (unsigned int)-1;
min_error = MAX_ERROR;
for(i = 0; i < (1 << (K - 1)); i++) {
if(ae[i] < min_error) {
min_state = i;
min_error = ae[i];
}
}
// trace the path
cur_state = min_state;
for(t = CONV_INPUT_SIZE; t >= 1; t--) {
min_state = cur_state;
cur_state = state_history[cur_state][t]; // get previous
output[t - 1] = prev_next_state[cur_state][min_state];
}
// return the number of errors detected (hard-decision)
return min_error;
}
/*
* GSM SACCH interleaving and burst mapping
*
* Interleaving:
*
* Given 456 coded input bits, form 4 blocks of 114 bits:
*
* i(B, j) = c(n, k) k = 0, ..., 455
* n = 0, ..., N, N + 1, ...
* B = B_0 + 4n + (k mod 4)
* j = 2(49k mod 57) + ((k mod 8) div 4)
*
* Mapping on Burst:
*
* e(B, j) = i(B, j)
* e(B, 59 + j) = i(B, 57 + j) j = 0, ..., 56
* e(B, 57) = h_l(B)
* e(B, 58) = h_n(B)
*
* Where h_l(B) and h_n(B) are bits in burst B indicating flags.
*/
/*
static void interleave(unsigned char *data, unsigned char *iBLOCK) {
int j, k, B;
// for each bit in input data
for(k = 0; k < CONV_SIZE; k++) {
B = k % 4;
j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
iBLOCK[B * iBLOCK_SIZE + j] = data[k];
}
}
*/
#if 0
static void decode_interleave(unsigned char *data, unsigned char *iBLOCK) {
int j, k, B;
for(k = 0; k < CONV_SIZE; k++) {
B = k % 4;
j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
data[k] = iBLOCK[B * iBLOCK_SIZE + j];
}
}
#endif
/*
static void burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
unsigned char hl, unsigned char hn) {
int j;
for(j = 0; j < 57; j++) {
eBLOCK[j] = iBLOCK[j];
eBLOCK[j + 59] = iBLOCK[j + 57];
}
eBLOCK[57] = hl;
eBLOCK[58] = hn;
}
*/
static void decode_burstmap(unsigned char *iBLOCK, unsigned char *eBLOCK,
unsigned char *hl, unsigned char *hn) {
@ -380,16 +135,42 @@ int get_ns_l3_len(unsigned char *data, unsigned int datalen) {
#endif
/*
* decode_cch
*
* Decode a "common" control channel. Most control channels use
* the same burst, interleave, Viterbi and parity configuration.
* The documentation for the control channels defines SACCH first
* and then just keeps referring to that.
*
* The current (investigated) list is as follows:
*
* BCCH Norm
* BCCH Ext
* PCH
* AGCH
* CBCH (SDCCH/4)
* CBCH (SDCCH/8)
* SDCCH/4
* SACCH/C4
* SDCCH/8
* SACCH/C8
*
* We provide two functions, one for where all four bursts are
* contiguous, and one where they aren't.
*/
static unsigned char *decode_sacch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) {
static unsigned char *decode_cch(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];
hl, hn, decoded_data[PARITY_OUTPUT_SIZE];
FC_CTX fc_ctx;
data_size = sizeof ctx->msg;
if(datalen)
if (datalen)
*datalen = 0;
// unmap the bursts
@ -400,10 +181,9 @@ static unsigned char *decode_sacch(GS_CTX *ctx, unsigned char *burst, unsigned i
// remove interleave
interleave_decode(&ctx->interleave_ctx, conv_data, (unsigned char *)iBLOCK);
//decode_interleave(conv_data, (unsigned char *)iBLOCK);
// Viterbi decode
errors = conv_decode(decoded_data, conv_data);
errors = conv_decode(decoded_data, conv_data, CONV_INPUT_SIZE_CCH);
if (errors) {
DEBUGF("conv_decode: %d\n", errors);
return NULL;
@ -442,42 +222,3 @@ static unsigned char *decode_sacch(GS_CTX *ctx, unsigned char *burst, unsigned i
*datalen = (unsigned int)len;
return ctx->msg;
}
/*
* decode_cch
*
* Decode a "common" control channel. Most control channels use
* the same burst, interleave, Viterbi and parity configuration.
* The documentation for the control channels defines SACCH first
* and then just keeps referring to that.
*
* The current (investigated) list is as follows:
*
* BCCH Norm
* BCCH Ext
* PCH
* AGCH
* CBCH (SDCCH/4)
* CBCH (SDCCH/8)
* SDCCH/4
* SACCH/C4
* SDCCH/8
* SACCH/C8
*
* We provide two functions, one for where all four bursts are
* contiguous, and one where they aren't.
*/
unsigned char *decode_cch(GS_CTX *ctx, unsigned char *burst, unsigned int *datalen) {
return decode_sacch(ctx, burst, datalen);
}
#if 0
unsigned char *decode_cch(GS_CTX *ctx, unsigned char *e, unsigned int *datalen) {
return decode_sacch(ctx, e, e + eBLOCK_SIZE, e + 2 * eBLOCK_SIZE,
e + 3 * eBLOCK_SIZE, datalen);
}
#endif

206
gsmstack/conv.c Normal file
View File

@ -0,0 +1,206 @@
/* This file was taken from gsm-tvoid */
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <ctype.h>
#include <math.h>
//#include "burst_types.h"
#include "conv.h"
//#include "fire_crc.h"
/*
* Convolutional encoding and Viterbi decoding for the GSM CCH+TCH channel.
*/
/* The class 1 bits are encoded with the 1/2 rate convolutional code defined by
* the polynomials:
* G0 = 1 + D3+ D4
* G1 = 1 + D + D3+ D4
* The coded bits {c(0), c(1),..., c(455)} are then defined by:
* class 1: c(2k) = u(k) + u(k-3) + u(k-4)
* c(2k+1) = u(k) + u(k-1) + u(k-3) + u(k-4) for k = 0,1,...,188
* u(k) = 0 for k < 0
* class 2:c(378+k) = d(182+k) for k = 0,1,....,77
*/
/*
* Convolutional encoding:
*
* G_0 = 1 + x^3 + x^4
* G_1 = 1 + x + x^3 + x^4
*
* i.e.,
*
* c_{2k} = u_k + u_{k - 3} + u_{k - 4}
* c_{2k + 1} = u_k + u_{k - 1} + u_{k - 3} + u_{k - 4}
*/
#define K 5
#define MAX_ERROR(size) (2 * size + 1)
/*
* Given the current state and input bit, what are the output bits?
*
* encode[current_state][input_bit]
*/
static const unsigned int encode[1 << (K - 1)][2] = {
{0, 3}, {3, 0}, {3, 0}, {0, 3},
{0, 3}, {3, 0}, {3, 0}, {0, 3},
{1, 2}, {2, 1}, {2, 1}, {1, 2},
{1, 2}, {2, 1}, {2, 1}, {1, 2}
};
/*
* Given the current state and input bit, what is the next state?
*
* next_state[current_state][input_bit]
*/
static const unsigned int next_state[1 << (K - 1)][2] = {
{0, 8}, {0, 8}, {1, 9}, {1, 9},
{2, 10}, {2, 10}, {3, 11}, {3, 11},
{4, 12}, {4, 12}, {5, 13}, {5, 13},
{6, 14}, {6, 14}, {7, 15}, {7, 15}
};
/*
* Given the previous state and the current state, what input bit caused
* the transition? If it is impossible to transition between the two
* states, the value is 2.
*
* prev_next_state[previous_state][current_state]
*/
static const unsigned int prev_next_state[1 << (K - 1)][1 << (K - 1)] = {
{ 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
{ 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2, 2},
{ 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
{ 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2, 2},
{ 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
{ 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2, 2},
{ 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
{ 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2, 2},
{ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
{ 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2, 2},
{ 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
{ 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2, 2},
{ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
{ 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1, 2},
{ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1},
{ 2, 2, 2, 2, 2, 2, 2, 0, 2, 2, 2, 2, 2, 2, 2, 1}
};
static inline unsigned int hamming_distance2(unsigned int w) {
return (w & 1) + !!(w & 2);
}
/*
static void conv_encode(unsigned char *data, unsigned char *output,
unsigned int input_size) {
unsigned int i, state = 0, o;
// encode data
for(i = 0; i < input_size; i++) {
o = encode[state][data[i]];
state = next_state[state][data[i]];
*output++ = !!(o & 2);
*output++ = o & 1;
}
}
*/
int
conv_decode(unsigned char *output, unsigned char *data,
unsigned int input_size) {
int i, t;
unsigned int rdata, state, nstate, b, o, distance, accumulated_error,
min_state, min_error, cur_state;
unsigned int max_error = MAX_ERROR(input_size);
unsigned int ae[1 << (K - 1)];
unsigned int nae[1 << (K - 1)]; // next accumulated error
unsigned int state_history[1 << (K - 1)][CONV_MAX_INPUT_SIZE + 1];
// initialize accumulated error, assume starting state is 0
for(i = 0; i < (1 << (K - 1)); i++)
ae[i] = nae[i] = max_error;
ae[0] = 0;
// build trellis
for(t = 0; t < input_size; t++) {
// get received data symbol
rdata = (data[2 * t] << 1) | data[2 * t + 1];
// for each state
for(state = 0; state < (1 << (K - 1)); state++) {
// make sure this state is possible
if(ae[state] >= max_error)
continue;
// find all states we lead to
for(b = 0; b < 2; b++) {
// get next state given input bit b
nstate = next_state[state][b];
// find output for this transition
o = encode[state][b];
// calculate distance from received data
distance = hamming_distance2(rdata ^ o);
// choose surviving path
accumulated_error = ae[state] + distance;
if(accumulated_error < nae[nstate]) {
// save error for surviving state
nae[nstate] = accumulated_error;
// update state history
state_history[nstate][t + 1] = state;
}
}
}
// get accumulated error ready for next time slice
for(i = 0; i < (1 << (K - 1)); i++) {
ae[i] = nae[i];
nae[i] = max_error;
}
}
// the final state is the state with the fewest errors
min_state = (unsigned int)-1;
min_error = max_error;
for(i = 0; i < (1 << (K - 1)); i++) {
if(ae[i] < min_error) {
min_state = i;
min_error = ae[i];
}
}
// trace the path
cur_state = min_state;
for(t = input_size; t >= 1; t--) {
min_state = cur_state;
cur_state = state_history[cur_state][t]; // get previous
output[t - 1] = prev_next_state[cur_state][min_state];
}
// return the number of errors detected (hard-decision)
return min_error;
}

24
gsmstack/conv.h Normal file
View File

@ -0,0 +1,24 @@
/* This file was taken from gsm-tvoid */
#ifndef _GSM_CONV_H
#define _GSM_CONV_H
#define DATA_BLOCK_SIZE 184
#define PARITY_SIZE 40
#define FLUSH_BITS_SIZE 4
#define PARITY_OUTPUT_SIZE (DATA_BLOCK_SIZE + PARITY_SIZE + FLUSH_BITS_SIZE)
#define CONV_INPUT_SIZE_TCH_F 189
#define CONV_INPUT_SIZE_CCH PARITY_OUTPUT_SIZE
#define CONV_MAX_INPUT_SIZE PARITY_OUTPUT_SIZE
#define CONV_SIZE (2 * CONV_MAX_INPUT_SIZE)
#define BLOCKS 4
#define iBLOCK_SIZE (CONV_SIZE / BLOCKS)
#define eBLOCK_SIZE (iBLOCK_SIZE + 2)
int conv_decode(unsigned char *output, unsigned char *data,
unsigned int input_size);
int parity_check(unsigned char *data);
int compress_bits(unsigned char *dbuf, int dlen, unsigned char *src, int len);
#endif /* _GSM_CONV_H */

48
gsmstack/interleave.c Normal file
View File

@ -0,0 +1,48 @@
/* This file was taken from gsm-tvoid */
#include <stdlib.h>
#include <stdio.h>
#include "interleave.h"
int
interleave_init(INTERLEAVE_CTX *ictx, int size, int block_size)
{
ictx->trans_size = size;
ictx->trans = (unsigned short *)malloc(size * sizeof *ictx->trans);
// DEBUGF("size: %d\n", size);
// DEBUGF("Block size: %d\n", block_size);
int j, k, B;
for (k = 0; k < size; k++)
{
B = k % 4;
j = 2 * ((49 * k) % 57) + ((k % 8) / 4);
ictx->trans[k] = B * block_size + j;
/* Mapping: pos1 goes to pos2: pos1 -> pos2 */
// DEBUGF("%d -> %d\n", ictx->trans[k], k);
}
// exit(0);
return 0;
}
int
interleave_deinit(INTERLEAVE_CTX *ictx)
{
if (ictx->trans != NULL)
{
free(ictx->trans);
ictx->trans = NULL;
}
return 0;
}
void
interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src)
{
int k;
for (k = 0; k < ictx->trans_size; k++)
dst[k] = src[ictx->trans[k]];
}

19
gsmstack/interleave.h Normal file
View File

@ -0,0 +1,19 @@
/* This file was taken from gsm-tvoid */
/*
* $Id:$
*/
#ifndef __GSMSP_INTERLEAVE_H__
#define __GSMSP_INTERLEAVE_H__ 1
typedef struct _interleave_ctx
{
unsigned short *trans;
int trans_size;
} INTERLEAVE_CTX;
int interleave_init(INTERLEAVE_CTX *ictx, int size, int block_size);
int interleave_deinit(INTERLEAVE_CTX *ictx);
void interleave_decode(INTERLEAVE_CTX *ictx, unsigned char *dst, unsigned char *src);
#endif

145
gsmstack/tch.c Normal file
View File

@ -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;
}