Added Turbo Decoder

This commit is contained in:
ismagom 2014-05-13 16:03:39 +01:00
parent 2a6d2fbb64
commit bcdf2f0886
11 changed files with 1801 additions and 0 deletions

View file

@ -0,0 +1,41 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#ifndef _PERMUTE_H
#define _PERMUTE_H
typedef struct {
int *forward;
int *reverse;
}tc_interl_t;
int tc_interl_LTE_init(tc_interl_t *h, int long_cb);
int tc_interl_UMTS_init(tc_interl_t *h, int long_cb);
void tc_interl_free(tc_interl_t *h);
#endif

View file

@ -0,0 +1,45 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define NUMREGS 3
#define RATE 3
#define TOTALTAIL 12
typedef struct {
int long_cb;
tc_interl_t interl;
}tcod_t;
int tcod_init(tcod_t *h, int long_cb);
void tcod_free(tcod_t *h);
void tcod_encode(tcod_t *h, char *input, char *output);

View file

@ -0,0 +1,44 @@
#define RATE 3
#define TOTALTAIL 12
#define LOG18 -2.07944
#define NUMSTATES 8
#define NINPUTS 2
#define TAIL 3
#define TOTALTAIL 12
#define INF 9e4
#define ZERO 9e-4
#define MAX_LONG_CB 6114
#define MAX_LONG_CODED (RATE*MAX_LONG_CB+TOTALTAIL)
typedef float llr_t;
typedef struct {
int long_cb;
llr_t *beta;
}map_gen_t;
typedef struct {
int long_cb;
map_gen_t dec;
llr_t *llr1;
llr_t *llr2;
llr_t *w;
llr_t *syst;
llr_t *parity;
tc_interl_t interleaver;
}tdec_t;
int tdec_init(tdec_t *h, int long_cb);
void tdec_free(tdec_t *h);
void tdec_reset(tdec_t *h);
void tdec_iteration(tdec_t *h, llr_t *input);
void tdec_decision(tdec_t *h, char *output);
void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations);

View file

@ -0,0 +1,68 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#define RATE 3
#define TOTALTAIL 12
#define LOG18 -2.07944
#define NUMSTATES 8
#define NINPUTS 2
#define TOTALTAIL 12
#define SCALE 80
#define INF 9e4
#define ZERO 9e-4
#define MAX_LONG_CB 6114
#define MAX_LONG_CODED (RATE*MAX_LONG_CB+TOTALTAIL)
typedef float llr_t;
typedef struct {
int long_cb;
int max_iterations;
int halt_threshold;
enum { HALT_MIN = 2, HALT_MEAN = 1, HALT_NONE = 0} halt_mode;
llr_t alfa[NUMSTATES];
llr_t beta[(MAX_LONG_CB + 1) * NUMSTATES];
llr_t LLR1[MAX_LONG_CB + TOTALTAIL];
llr_t LLR2[MAX_LONG_CB + TOTALTAIL];
llr_t W[MAX_LONG_CB + TOTALTAIL];
llr_t data[RATE*(MAX_LONG_CB + TOTALTAIL)];
llr_t *parity;
struct permute_t permuta;
int iteration;
int HALT_min;
}tdec_t;
int tdec_init(tdec_t *h);
int turbo_decoder(tdec_t *h, llr_t *input, char *output, int *halt);

View file

@ -0,0 +1,117 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "lte/common/base.h"
#include "lte/fec/tc_interl.h"
#include "lte/fec/turbocoder.h"
#include "lte/utils/debug.h"
/************************************************
*
* LTE TURBO CODE INTERLEAVER
*
************************************************/
const int f1_list[NOF_TC_CB_SIZES] = { 3, 7, 19, 7, 7, 11, 5, 11, 7, 41, 103, 15, 9, 17,
9, 21, 101, 21, 57, 23, 13, 27, 11, 27, 85, 29, 33, 15, 17, 33, 103, 19,
19, 37, 19, 21, 21, 115, 193, 21, 133, 81, 45, 23, 243, 151, 155, 25,
51, 47, 91, 29, 29, 247, 29, 89, 91, 157, 55, 31, 17, 35, 227, 65, 19,
37, 41, 39, 185, 43, 21, 155, 79, 139, 23, 217, 25, 17, 127, 25, 239,
17, 137, 215, 29, 15, 147, 29, 59, 65, 55, 31, 17, 171, 67, 35, 19, 39,
19, 199, 21, 211, 21, 43, 149, 45, 49, 71, 13, 17, 25, 183, 55, 127, 27,
29, 29, 57, 45, 31, 59, 185, 113, 31, 17, 171, 209, 253, 367, 265, 181,
39, 27, 127, 143, 43, 29, 45, 157, 47, 13, 111, 443, 51, 51, 451, 257,
57, 313, 271, 179, 331, 363, 375, 127, 31, 33, 43, 33, 477, 35, 233,
357, 337, 37, 71, 71, 37, 39, 127, 39, 39, 31, 113, 41, 251, 43, 21, 43,
45, 45, 161, 89, 323, 47, 23, 47, 263 };
const int f2_list[NOF_TC_CB_SIZES] = { 10, 12, 42, 16, 18, 20, 22, 24, 26, 84, 90, 32,
34, 108, 38, 120, 84, 44, 46, 48, 50, 52, 36, 56, 58, 60, 62, 32, 198,
68, 210, 36, 74, 76, 78, 120, 82, 84, 86, 44, 90, 46, 94, 48, 98, 40,
102, 52, 106, 72, 110, 168, 114, 58, 118, 180, 122, 62, 84, 64, 66, 68,
420, 96, 74, 76, 234, 80, 82, 252, 86, 44, 120, 92, 94, 48, 98, 80, 102,
52, 106, 48, 110, 112, 114, 58, 118, 60, 122, 124, 84, 64, 66, 204, 140,
72, 74, 76, 78, 240, 82, 252, 86, 88, 60, 92, 846, 48, 28, 80, 102, 104,
954, 96, 110, 112, 114, 116, 354, 120, 610, 124, 420, 64, 66, 136, 420,
216, 444, 456, 468, 80, 164, 504, 172, 88, 300, 92, 188, 96, 28, 240,
204, 104, 212, 192, 220, 336, 228, 232, 236, 120, 244, 248, 168, 64,
130, 264, 134, 408, 138, 280, 142, 480, 146, 444, 120, 152, 462, 234,
158, 80, 96, 902, 166, 336, 170, 86, 174, 176, 178, 120, 182, 184, 186,
94, 190, 480 };
int tc_interl_LTE_init(tc_interl_t *h, int long_cb) {
int cb_table_idx, f1, f2;
unsigned long long i, j;
cb_table_idx = lte_find_cb_index(long_cb);
if (cb_table_idx == -1) {
fprintf(stderr, "Can't find long_cb=%d in valid TC CB table\n", long_cb);
return -1;
}
h->forward = h->reverse = NULL;
h->forward = malloc(sizeof(int) * (long_cb));
if (!h->forward) {
return -1;
}
h->reverse = malloc(sizeof(int) * (long_cb));
if (!h->reverse) {
perror("malloc");
free(h->forward);
h->forward = h->reverse = NULL;
return -1;
}
f1 = f1_list[cb_table_idx];
f2 = f2_list[cb_table_idx];
DEBUG("table_idx: %d, f1: %d, f2: %d\n", cb_table_idx, f1, f2);
h->forward[0] = 0;
h->reverse[0] = 0;
for (i = 1; i < long_cb; i++) {
j = (f1*i + f2*i*i) % (long_cb);
h->forward[i] = j;
h->reverse[j] = i;
}
return 0;
}

View file

@ -0,0 +1,257 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include "lte/fec/tc_interl.h"
#include "lte/fec/turbocoder.h"
#define TURBO_RATE 3
int mcd(int x, int y);
/************************************************
*
* UMTS TURBO CODE INTERLEAVER
*
************************************************/
#define MAX_ROWS 20
#define MAX_COLS 256
const unsigned short table_p[52] = { 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43,
47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97, 101, 103, 107, 109, 113,
127, 131, 137, 139, 149, 151, 157, 163, 167, 173, 179, 181, 191, 193,
197, 199, 211, 223, 227, 229, 233, 239, 241, 251, 257 };
const unsigned char table_v[52] = { 3, 2, 2, 3, 2, 5, 2, 3, 2, 6, 3, 5, 2, 2, 2,
2, 7, 5, 3, 2, 3, 5, 2, 5, 2, 6, 3, 3, 2, 3, 2, 2, 6, 5, 2, 5, 2, 2, 2,
19, 5, 2, 3, 2, 3, 2, 6, 3, 7, 7, 6, 3 };
void tc_interl_free(tc_interl_t *h) {
if (h->forward) {
free(h->forward);
}
if (h->reverse) {
free(h->reverse);
}
h->forward = h->reverse = NULL;
}
int tc_interl_UMTS_init(tc_interl_t *h, int long_cb) {
int i, j;
int res, prim, aux;
int kp, k;
int *per, *desper;
unsigned char v;
unsigned short p;
unsigned short s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS];
unsigned short U[MAX_COLS * MAX_ROWS];
int M_Rows, M_Cols, M_long;
h->forward = h->reverse = NULL;
h->forward = malloc(sizeof(int) * (long_cb));
if (!h->forward) {
return -1;
}
h->reverse = malloc(sizeof(int) * (long_cb));
if (!h->reverse) {
perror("malloc");
free(h->forward);
h->forward = h->reverse = NULL;
return -1;
}
M_long = long_cb;
/* Find R*/
if ((40 <= M_long) && (M_long <= 159))
M_Rows = 5;
else if (((160 <= M_long) && (M_long <= 200))
|| ((481 <= M_long) && (M_long <= 530)))
M_Rows = 10;
else
M_Rows = 20;
/* Find p i v*/
if ((481 <= M_long) && (M_long <= 530)) {
p = 53;
v = 2;
M_Cols = p;
} else {
i = 0;
do {
p = table_p[i];
v = table_v[i];
i++;
} while (M_long > (M_Rows * (p + 1)));
}
/* Find C*/
if ((M_long) <= (M_Rows) * ((p) - 1))
M_Cols = (p) - 1;
else if (((M_Rows) * (p - 1) < M_long) && (M_long <= (M_Rows) * (p)))
M_Cols = p;
else if ((M_Rows) * (p) < M_long)
M_Cols = (p) + 1;
q[0] = 1;
prim = 6;
for (i = 1; i < M_Rows; i++) {
do {
prim++;
res = mcd(prim, p - 1);
} while (res != 1);
q[i] = prim;
}
s[0] = 1;
for (i = 1; i < p - 1; i++) {
s[i] = (v * s[i - 1]) % p;
}
if (M_long <= 159 && M_long >= 40) {
T[0] = 4;
T[1] = 3;
T[2] = 2;
T[3] = 1;
T[4] = 0;
} else if ((M_long <= 200 && M_long >= 160)
|| (M_long <= 530 && M_long >= 481)) {
T[0] = 9;
T[1] = 8;
T[2] = 7;
T[3] = 6;
T[4] = 5;
T[5] = 4;
T[6] = 3;
T[7] = 2;
T[8] = 1;
T[9] = 0;
} else if ((M_long <= 2480 && M_long >= 2281)
|| (M_long <= 3210 && M_long >= 3161)) {
T[0] = 19;
T[1] = 9;
T[2] = 14;
T[3] = 4;
T[4] = 0;
T[5] = 2;
T[6] = 5;
T[7] = 7;
T[8] = 12;
T[9] = 18;
T[10] = 16;
T[11] = 13;
T[12] = 17;
T[13] = 15;
T[14] = 3;
T[15] = 1;
T[16] = 6;
T[17] = 11;
T[18] = 8;
T[19] = 10;
} else {
T[0] = 19;
T[1] = 9;
T[2] = 14;
T[3] = 4;
T[4] = 0;
T[5] = 2;
T[6] = 5;
T[7] = 7;
T[8] = 12;
T[9] = 18;
T[10] = 10;
T[11] = 8;
T[12] = 13;
T[13] = 17;
T[14] = 3;
T[15] = 1;
T[16] = 16;
T[17] = 6;
T[18] = 15;
T[19] = 11;
}
for (i = 0; i < M_Rows; i++) {
r[T[i]] = q[i];
}
for (i = 0; i < M_Rows; i++) {
for (j = 0; j < p - 1; j++) {
U[i * M_Cols + j] = s[(j * r[i]) % (p - 1)];
if (M_Cols == (p - 1))
U[i * M_Cols + j] -= 1;
}
}
if (M_Cols == p) {
for (i = 0; i < M_Rows; i++)
U[i * M_Cols + p - 1] = 0;
} else if (M_Cols == p + 1) {
for (i = 0; i < M_Rows; i++) {
U[i * M_Cols + p - 1] = 0;
U[i * M_Cols + p] = p;
}
if (M_long == M_Cols * M_Rows) {
aux = U[(M_Rows - 1) * M_Cols + p];
U[(M_Rows - 1) * M_Cols + p] = U[(M_Rows - 1) * M_Cols + 0];
U[(M_Rows - 1) * M_Cols + 0] = aux;
}
}
per = h->forward;
desper = h->reverse;
k = 0;
for (j = 0; j < M_Cols; j++) {
for (i = 0; i < M_Rows; i++) {
kp = T[i] * M_Cols + U[i * M_Cols + j];
if (kp < M_long) {
desper[kp] = k;
per[k] = kp;
k++;
}
}
}
return 0;
}
int mcd(int x, int y) {
int r = 1;
while (r) {
r = x % y;
x = y;
y = r;
}
return x;
}

View file

@ -0,0 +1,134 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include "lte/fec/tc_interl.h"
#include "lte/fec/turbocoder.h"
#define NOF_REGS 3
int tcod_init(tcod_t *h, int long_cb) {
if (tc_interl_LTE_init(&h->interl, long_cb)) {
return -1;
}
h->long_cb = long_cb;
return 0;
}
void tcod_free(tcod_t *h) {
tc_interl_free(&h->interl);
h->long_cb = 0;
}
void tcod_encode(tcod_t *h, char *input, char *output) {
char reg1_0,reg1_1,reg1_2, reg2_0,reg2_1,reg2_2;
int i,k=0,j;
char bit;
char in,out;
int *per;
per=h->interl.forward;
reg1_0=0;
reg1_1=0;
reg1_2=0;
reg2_0=0;
reg2_1=0;
reg2_2=0;
k=0;
for (i=0;i<h->long_cb;i++) {
bit=input[i];
output[k]=bit;
k++;
in=bit^(reg1_2^reg1_1);
out=reg1_2^(reg1_0^in);
reg1_2=reg1_1;
reg1_1=reg1_0;
reg1_0=in;
output[k]=out;
k++;
bit=input[per[i]];
in=bit^(reg2_2^reg2_1);
out=reg2_2^(reg2_0^in);
reg2_2=reg2_1;
reg2_1=reg2_0;
reg2_0=in;
output[k]=out;
k++;
}
k=3*h->long_cb;
/* TAILING CODER #1 */
for (j=0;j<NOF_REGS;j++) {
bit=reg1_2^reg1_1;
output[k]=bit;
k++;
in=bit^(reg1_2^reg1_1);
out=reg1_2^(reg1_0^in);
reg1_2=reg1_1;
reg1_1=reg1_0;
reg1_0=in;
output[k]=out;
k++;
}
/* TAILING CODER #2 */
for (j=0;j<NOF_REGS;j++) {
bit=reg2_2^reg2_1;
output[k]=bit;
k++;
in=bit^(reg2_2^reg2_1);
out=reg2_2^(reg2_0^in);
reg2_2=reg2_1;
reg2_1=reg2_0;
reg2_0=in;
output[k]=out;
k++;
}
}

View file

@ -0,0 +1,299 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include "lte/fec/tc_interl.h"
#include "lte/fec/turbodecoder.h"
/************************************************
*
* MAP_GEN is the MAX-LOG-MAP generic implementation of the
* Decoder
*
************************************************/
void map_gen_beta(map_gen_t *s, llr_t *input, llr_t *parity) {
llr_t m_b[8], new[8], old[8];
llr_t x, y, xy;
int k;
int end = s->long_cb + RATE;
llr_t *beta = s->beta;
int i;
for (i=0;i<8;i++) {
old[i] = beta[8 * (end) + i];
}
for (k = end - 1; k >= 0; k--) {
x = input[k];
y = parity[k];
xy = x + y;
m_b[0] = old[4] + xy;
m_b[1] = old[4];
m_b[2] = old[5] + y;
m_b[3] = old[5] + x;
m_b[4] = old[6] + x;
m_b[5] = old[6] + y;
m_b[6] = old[7];
m_b[7] = old[7] + xy;
new[0] = old[0];
new[1] = old[0] + xy;
new[2] = old[1] + x;
new[3] = old[1] + y;
new[4] = old[2] + y;
new[5] = old[2] + x;
new[6] = old[3] + xy;
new[7] = old[3];
for (i=0;i<8;i++) {
if (m_b[i] > new[i])
new[i] = m_b[i];
beta[8 * k + i] = new[i];
old[i] = new[i];
}
}
}
void map_gen_alpha(map_gen_t *s, llr_t *input, llr_t *parity, llr_t *output) {
llr_t m_b[8], new[8], old[8], max1[8], max0[8];
llr_t m1, m0;
llr_t x, y, xy;
llr_t out;
int k;
int end = s->long_cb;
llr_t *beta = s->beta;
int i;
old[0] = 0;
for (i=1;i<8;i++) {
old[i] = -INF;
}
for (k = 1; k < end + 1; k++) {
x = input[k - 1];
y = parity[k - 1];
xy = x + y;
m_b[0] = old[0];
m_b[1] = old[3] + y;
m_b[2] = old[4] + y;
m_b[3] = old[7];
m_b[4] = old[1];
m_b[5] = old[2] + y;
m_b[6] = old[5] + y;
m_b[7] = old[6];
new[0] = old[1] + xy;
new[1] = old[2] + x;
new[2] = old[5] + x;
new[3] = old[6] + xy;
new[4] = old[0] + xy;
new[5] = old[3] + x;
new[6] = old[4] + x;
new[7] = old[7] + xy;
for (i=0;i<8;i++) {
max0[i] = m_b[i] + beta[8 * k + i];
max1[i] = new[i] + beta[8 * k + i];
}
m1 = max1[0];
m0 = max0[0];
for (i=1;i<8;i++) {
if (max1[i] > m1)
m1 = max1[i];
if (max0[i] > m0)
m0 = max0[i];
}
for (i=0;i<8;i++) {
if (m_b[i] > new[i])
new[i] = m_b[i];
old[i] = new[i];
}
out = m1 - m0;
output[k - 1] = out;
}
}
int map_gen_init(map_gen_t *h, int long_cb) {
bzero(h, sizeof(map_gen_t));
h->beta = malloc(sizeof(llr_t) * (long_cb + TOTALTAIL + 1)* NUMSTATES);
if (!h->beta) {
perror("malloc");
return -1;
}
h->long_cb = long_cb;
return 0;
}
void map_gen_free(map_gen_t *h) {
if (h->beta) {
free(h->beta);
}
bzero(h, sizeof(map_gen_t));
}
void map_gen_dec(map_gen_t *h, llr_t *input, llr_t *parity, llr_t *output) {
int k;
h->beta[(h->long_cb + TAIL) * NUMSTATES] = 0;
for (k = 1; k < NUMSTATES; k++)
h->beta[(h->long_cb + TAIL) * NUMSTATES + k] = -INF;
map_gen_beta(h, input, parity);
map_gen_alpha(h, input, parity, output);
}
/************************************************
*
* TURBO DECODER INTERFACE
*
************************************************/
int tdec_init(tdec_t *h, int long_cb) {
int ret = -1;
bzero(h, sizeof(tdec_t));
int len = long_cb + TOTALTAIL;
h->llr1 = malloc(sizeof(llr_t) * len);
if (!h->llr1) {
perror("malloc");
goto clean_and_exit;
}
h->llr2 = malloc(sizeof(llr_t) * len);
if (!h->llr2) {
perror("malloc");
goto clean_and_exit;
}
h->w = malloc(sizeof(llr_t) * len);
if (!h->w) {
perror("malloc");
goto clean_and_exit;
}
h->syst = malloc(sizeof(llr_t) * len);
if (!h->syst) {
perror("malloc");
goto clean_and_exit;
}
h->parity = malloc(sizeof(llr_t) * len);
if (!h->parity) {
perror("malloc");
goto clean_and_exit;
}
if (map_gen_init(&h->dec, long_cb)) {
goto clean_and_exit;
}
h->long_cb = long_cb;
if (tc_interl_LTE_init(&h->interleaver, h->long_cb) < 0) {
goto clean_and_exit;
}
ret = 0;
clean_and_exit:
if (ret == -1) {
tdec_free(h);
}
return ret;
}
void tdec_free(tdec_t *h) {
if (h->llr1) {
free(h->llr1);
}
if (h->llr2) {
free(h->llr2);
}
if (h->w) {
free(h->w);
}
if (h->syst) {
free(h->syst);
}
if (h->parity) {
free(h->parity);
}
map_gen_free(&h->dec);
tc_interl_free(&h->interleaver);
bzero(h, sizeof(tdec_t));
}
void tdec_iteration(tdec_t *h, llr_t *input) {
int i;
// Prepare systematic and parity bits for MAP DEC #1
for (i = 0; i < h->long_cb; i++) {
h->syst[i] = input[RATE * i] + h->w[i];
h->parity[i] = input[RATE * i + 1];
}
for (i=h->long_cb;i<h->long_cb+RATE;i++) {
h->syst[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb)];
h->parity[i] = input[RATE * h->long_cb + NINPUTS * (i - h->long_cb) + 1];
}
// Run MAP DEC #1
map_gen_dec(&h->dec, h->syst, h->parity, h->llr1);
// Prepare systematic and parity bits for MAP DEC #1
for (i = 0; i < h->long_cb; i++) {
h->syst[i] = h->llr1[h->interleaver.forward[i]] - h->w[h->interleaver.forward[i]];
h->parity[i] = input[RATE * i + 2];
}
for (i=h->long_cb;i<h->long_cb+RATE;i++) {
h->syst[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb)];
h->parity[i] = input[RATE * h->long_cb + NINPUTS * RATE + NINPUTS * (i - h->long_cb) + 1];
}
// Run MAP DEC #1
map_gen_dec(&h->dec, h->syst, h->parity, h->llr2);
// Update a-priori LLR from the last iteration
for (i = 0; i < h->long_cb; i++) {
h->w[i] += h->llr2[h->interleaver.reverse[i]] - h->llr1[i];
}
}
void tdec_reset(tdec_t *h) {
memset(h->w, 0, sizeof(llr_t) * h->long_cb);
}
void tdec_decision(tdec_t *h, char *output) {
int i;
for (i = 0; i < h->long_cb; i++) {
output[i] = (h->llr2[h->interleaver.reverse[i]] > 0) ? 1 : 0;
}
}
void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations) {
int iter = 0;
tdec_reset(h);
do {
tdec_iteration(h, input);
iter++;
} while (iter < nof_iterations);
tdec_decision(h, output);
}

View file

@ -0,0 +1,304 @@
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "lte/fec/permute.h"
#include "lte/fec/turbodecoder.h"
void compute_beta(llr_t *beta, llr_t *data, llr_t *parity, int long_cb, int dec) {
llr_t m_b0, m_b1, m_b2, m_b3, m_b4, m_b5, m_b6, m_b7;
llr_t new0, new1, new2, new3, new4, new5, new6, new7;
llr_t old0, old1, old2, old3, old4, old5, old6, old7;
llr_t x, y, xy;
int k;
int end = long_cb + RATE;
old0 = beta[8 * (end) + 0];
old1 = beta[8 * (end) + 1];
old2 = beta[8 * (end) + 2];
old3 = beta[8 * (end) + 3];
old4 = beta[8 * (end) + 4];
old5 = beta[8 * (end) + 5];
old6 = beta[8 * (end) + 6];
old7 = beta[8 * (end) + 7];
for (k = end - 1; k >= 0; k--) {
if (k > long_cb - 1) {
if (dec == 1) {
x = data[RATE * (long_cb ) + NINPUTS * (k - long_cb)];
y = data[RATE * (long_cb ) + NINPUTS * (k - long_cb) + 1];
} else {
x = data[RATE * (long_cb ) + NINPUTS * RATE + NINPUTS * (k - long_cb)];
y = data[RATE * (long_cb ) + NINPUTS * RATE + NINPUTS * (k - long_cb) + 1];
}
} else {
x = data[RATE * k];
y = parity[RATE * k];
}
xy = x + y;
m_b0 = old4 + xy;
m_b1 = old4;
m_b2 = old5 + y;
m_b3 = old5 + x;
m_b4 = old6 + x;
m_b5 = old6 + y;
m_b6 = old7;
m_b7 = old7 + xy;
new0 = old0;
new1 = old0 + xy;
new2 = old1 + x;
new3 = old1 + y;
new4 = old2 + y;
new5 = old2 + x;
new6 = old3 + xy;
new7 = old3;
if (m_b0 > new0) new0 = m_b0;
beta[8 * k + 0] = new0;
old0 = new0;
if (m_b1 > new1) new1 = m_b1;
beta[8 * k + 1] = new1;
old1 = new1;
if (m_b2 > new2) new2 = m_b2;
beta[8 * k + 2] = new2;
old2 = new2;
if (m_b3 > new3) new3 = m_b3;
beta[8 * k + 3] = new3;
old3 = new3;
if (m_b4 > new4) new4 = m_b4;
beta[8 * k + 4] = new4;
old4 = new4;
if (m_b5 > new5) new5 = m_b5;
beta[8 * k + 5] = new5;
old5 = new5;
if (m_b6 > new6) new6 = m_b6;
beta[8 * k + 6] = new6;
old6 = new6;
if (m_b7 > new7) new7 = m_b7;
beta[8 * k + 7] = new7;
old7 = new7;
}
}
void compute_alfa(llr_t *alfa, llr_t *beta, llr_t *data, llr_t *parity, llr_t *output, int long_cb, int dec) {
llr_t m_b0, m_b1, m_b2, m_b3, m_b4, m_b5, m_b6, m_b7;
llr_t new0, new1, new2, new3, new4, new5, new6, new7;
llr_t old0, old1, old2, old3, old4, old5, old6, old7;
llr_t max1_0, max1_1, max1_2, max1_3, max1_4, max1_5, max1_6, max1_7;
llr_t max0_0, max0_1, max0_2, max0_3, max0_4, max0_5, max0_6, max0_7;
llr_t m1, m0;
llr_t x, y, xy;
llr_t out;
int k;
int end = long_cb;
old0 = alfa[0];
old1 = alfa[1];
old2 = alfa[2];
old3 = alfa[3];
old4 = alfa[4];
old5 = alfa[5];
old6 = alfa[6];
old7 = alfa[7];
for (k = 1; k < end + 1; k++) {
x = data[RATE * (k - 1)];
y = parity[RATE * (k - 1)];
xy = x + y;
m_b0 = old0;
m_b1 = old3 + y;
m_b2 = old4 + y;
m_b3 = old7;
m_b4 = old1;
m_b5 = old2 + y;
m_b6 = old5 + y;
m_b7 = old6;
new0 = old1 + xy;
new1 = old2 + x;
new2 = old5 + x;
new3 = old6 + xy;
new4 = old0 + xy;
new5 = old3 + x;
new6 = old4 + x;
new7 = old7 + xy;
max0_0 = m_b0 + beta[8 * k + 0];
max0_1 = m_b1 + beta[8 * k + 1];
max0_2 = m_b2 + beta[8 * k + 2];
max0_3 = m_b3 + beta[8 * k + 3];
max0_4 = m_b4 + beta[8 * k + 4];
max0_5 = m_b5 + beta[8 * k + 5];
max0_6 = m_b6 + beta[8 * k + 6];
max0_7 = m_b7 + beta[8 * k + 7];
max1_0 = new0 + beta[8 * k + 0];
max1_1 = new1 + beta[8 * k + 1];
max1_2 = new2 + beta[8 * k + 2];
max1_3 = new3 + beta[8 * k + 3];
max1_4 = new4 + beta[8 * k + 4];
max1_5 = new5 + beta[8 * k + 5];
max1_6 = new6 + beta[8 * k + 6];
max1_7 = new7 + beta[8 * k + 7];
m1 = max1_0;
if (max1_1 > m1) m1 = max1_1;
if (max1_2 > m1) m1 = max1_2;
if (max1_3 > m1) m1 = max1_3;
if (max1_4 > m1) m1 = max1_4;
if (max1_5 > m1) m1 = max1_5;
if (max1_6 > m1) m1 = max1_6;
if (max1_7 > m1) m1 = max1_7;
m0 = max0_0;
if (max0_1 > m0) m0 = max0_1;
if (max0_2 > m0) m0 = max0_2;
if (max0_3 > m0) m0 = max0_3;
if (max0_4 > m0) m0 = max0_4;
if (max0_5 > m0) m0 = max0_5;
if (max0_6 > m0) m0 = max0_6;
if (max0_7 > m0) m0 = max0_7;
if (m_b0 > new0) new0 = m_b0;
old0 = new0;
if (m_b1 > new1) new1 = m_b1;
old1 = new1;
if (m_b2 > new2) new2 = m_b2;
old2 = new2;
if (m_b3 > new3) new3 = m_b3;
old3 = new3;
if (m_b4 > new4) new4 = m_b4;
old4 = new4;
if (m_b5 > new5) new5 = m_b5;
old5 = new5;
if (m_b6 > new6) new6 = m_b6;
old6 = new6;
if (m_b7 > new7) new7 = m_b7;
old7 = new7;
out = m1 - m0;
/*
if (dec == 2) {
if (abs(out) < HALT_min) {
HALT_min = abs(out);
}
}
*/
output[k - 1] = out;
}
alfa[0] = old0;
alfa[1] = old1;
alfa[2] = old2;
alfa[3] = old3;
alfa[4] = old4;
alfa[5] = old5;
alfa[6] = old6;
alfa[7] = old7;
}
void DEC_RSC(tdec_t *q, llr_t *input, llr_t *output, int *per, int dec) {
int k;
int i;
int last_state = q->long_cb + RATE;
/** Initialize alfa states */
q->alfa[0] = 0;
for (k = 1; k < NUMSTATES; k++) {
q->alfa[k] = -INF;
}
q->beta[last_state * NUMSTATES] = 0;
for (k = 1; k < NUMSTATES; k++)
q->beta[last_state * NUMSTATES + k] = -INF;
/* copy data temporal buffer (to allow fastest loops)*/
memcpy(q->data, input, RATE * last_state * sizeof (llr_t));
q->parity = &input[dec];
if (dec == 1) {
for (i = 0; i < last_state; i++) {
q->data[RATE * i] += q->W[i ];
}
} else {
for (i = 0; i < last_state; i++) {
q->data[RATE * i] = q->LLR1[per[i ]] - q->W[per[i ]];
}
}
compute_beta(q->beta, q->data, &input[dec], q->long_cb, dec);
compute_alfa(q->alfa, q->beta, q->data, &input[dec], output, q->long_cb, dec);
}
void decide(llr_t *LLR2, char *output, int *desper, int long_cb) {
int i;
for (i = 0; i < long_cb; i++)
output[i] = (LLR2[desper[i]] > 0) ? 1 : 0;
}
void update_W(llr_t *W, llr_t *LLR1, llr_t *LLR2, int *desper, int long_cb) {
int i;
for (i = 0; i < long_cb; i++) {
W[i] += LLR2[desper[i]] - LLR1[i];
}
}
int turbo_decoder(tdec_t *q, llr_t *input, char *output, int *halt) {
int i;
long halt_mean=0;
int stop=0;
q->iteration = 0;
if (ComputePermutation(&q->permuta, q->long_cb,PER_UMTS)<0)
return -1;
memset(q->W, 0, sizeof (llr_t) * q->long_cb);
do {
if (q->iteration)
update_W(q->W, q->LLR1, q->LLR2, q->permuta.DESPER, q->long_cb);
DEC_RSC(q, input, q->LLR1, q->permuta.PER, 1);
DEC_RSC(q, input, q->LLR2, q->permuta.PER, 2);
q->iteration++;
} while (q->iteration < q->max_iterations && stop==0);
decide(q->LLR2, output, q->permuta.DESPER, q->long_cb);
return q->iteration;
}

View file

@ -0,0 +1,324 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <strings.h>
#include <unistd.h>
#include <math.h>
#include <time.h>
#include <sys/time.h>
#include <time.h>
#include "lte.h"
#include "turbocoder_test.h"
typedef _Complex float cf_t;
int frame_length = 1000, nof_frames=100;
float ebno_db = 100.0;
unsigned int seed = 0;
int K = -1;
#define MAX_ITERATIONS 4
int nof_iterations = MAX_ITERATIONS;
int test_known_data = 0;
int test_errors = 0;
#define SNR_POINTS 8
#define SNR_MIN 0.0
#define SNR_MAX 4.0
void usage(char *prog) {
printf("Usage: %s [nlesv]\n", prog);
printf("\t-k Test with known data (ignores frame_length) [Default disabled]\n");
printf("\t-i nof_iterations [Default %d]\n", nof_iterations);
printf("\t-n nof_frames [Default %d]\n", nof_frames);
printf("\t-l frame_length [Default %d]\n", frame_length);
printf("\t-e ebno in dB [Default scan]\n");
printf("\t-t test: check errors on exit [Default disabled]\n");
printf("\t-s seed [Default 0=time]\n");
}
void parse_args(int argc, char **argv) {
int opt;
while ((opt = getopt(argc, argv, "inlstvekt")) != -1) {
switch (opt) {
case 'n':
nof_frames = atoi(argv[optind]);
break;
case 'k':
test_known_data = 1;
break;
case 't':
test_errors = 1;
break;
case 'i':
nof_iterations = atoi(argv[optind]);
break;
case 'l':
frame_length = atoi(argv[optind]);
break;
case 'e':
ebno_db = atof(argv[optind]);
break;
case 's':
seed = (unsigned int) strtoul(argv[optind], NULL, 0);
break;
case 'v':
verbose++;
break;
default:
usage(argv[0]);
exit(-1);
}
}
}
void output_matlab(float ber[MAX_ITERATIONS][SNR_POINTS], int snr_points) {
int i, j;
FILE *f = fopen("turbocoder_snr.m", "w");
if (!f) {
perror("fopen");
exit(-1);
}
fprintf(f, "ber=[");
for (j=0;j<MAX_ITERATIONS;j++) {
for (i = 0; i < snr_points; i++) {
fprintf(f, "%g ", ber[j][i]);
}
fprintf(f, ";\n");
}
fprintf(f, "];\n");
fprintf(f, "snr=linspace(%g,%g-%g/%d,%d);\n", SNR_MIN, SNR_MAX, SNR_MAX,
snr_points, snr_points);
fprintf(f, "semilogy(snr,ber,snr,0.5*erfc(sqrt(10.^(snr/10))));\n");
fprintf(f, "legend('1 iter','2 iter', '3 iter', '4 iter', 'theory-uncoded');");
fprintf(f, "grid on;\n");
fclose(f);
}
int main(int argc, char **argv) {
int frame_cnt;
float *llr;
unsigned char *llr_c;
char *data_tx, *data_rx, *symbols;
int i, j;
float var[SNR_POINTS];
int snr_points;
float ber[MAX_ITERATIONS][SNR_POINTS];
unsigned int errors[100];
int coded_length;
struct timeval tdata[3];
float mean_usec;
tdec_t tdec;
tcod_t tcod;
parse_args(argc, argv);
if (!seed) {
seed = time(NULL);
}
srand(seed);
if (test_known_data) {
frame_length = KNOWN_DATA_LEN;
} else {
frame_length = lte_cb_size(lte_find_cb_index(frame_length));
}
coded_length = 3*(frame_length)+TOTALTAIL;
printf(" Frame length: %d\n", frame_length);
if (ebno_db < 100.0) {
printf(" EbNo: %.2f\n", ebno_db);
}
data_tx = malloc(frame_length * sizeof(char));
if (!data_tx) {
perror("malloc");
exit(-1);
}
data_rx = malloc(frame_length * sizeof(char));
if (!data_rx) {
perror("malloc");
exit(-1);
}
symbols = malloc(coded_length * sizeof(char));
if (!symbols) {
perror("malloc");
exit(-1);
}
llr = malloc(coded_length * sizeof(float));
if (!llr) {
perror("malloc");
exit(-1);
}
llr_c = malloc(coded_length * sizeof(char));
if (!llr_c) {
perror("malloc");
exit(-1);
}
if (tcod_init(&tcod, frame_length)) {
fprintf(stderr, "Error initiating Turbo coder\n");
exit(-1);
}
if (tdec_init(&tdec, frame_length)) {
fprintf(stderr, "Error initiating Turbo decoder\n");
exit(-1);
}
float ebno_inc, esno_db;
ebno_inc = (SNR_MAX - SNR_MIN) / SNR_POINTS;
if (ebno_db == 100.0) {
snr_points = SNR_POINTS;
for (i = 0; i < snr_points; i++) {
ebno_db = SNR_MIN + i * ebno_inc;
esno_db = ebno_db + 10 * log10((double) 1 / 3);
var[i] = sqrt(1 / (pow(10, esno_db / 10)));
}
} else {
esno_db = ebno_db + 10 * log10((double) 1 / 3);
var[0] = sqrt(1 / (pow(10, esno_db / 10)));
snr_points = 1;
}
for (i = 0; i < snr_points; i++) {
mean_usec = 0;
frame_cnt = 0;
bzero(errors, sizeof(int) * MAX_ITERATIONS);
while (frame_cnt < nof_frames) {
/* generate data_tx */
for (j = 0; j < frame_length; j++) {
if (test_known_data) {
data_tx[j] = known_data[j];
} else {
data_tx[j] = rand() % 2;
}
}
/* coded BER */
if (test_known_data) {
for (j=0;j<coded_length;j++) {
symbols[j] = known_data_encoded[j];
}
} else {
tcod_encode(&tcod, data_tx, symbols);
}
for (j = 0; j < coded_length; j++) {
llr[j] = symbols[j] ? sqrt(2) : -sqrt(2);
}
ch_awgn_f(llr, llr, var[i], coded_length);
/* decoder */
tdec_reset(&tdec);
int t;
if (nof_iterations == -1) {
t = MAX_ITERATIONS;
} else {
t = nof_iterations;
}
for (j=0;j<t;j++) {
if (!j) gettimeofday(&tdata[1],NULL); // Only measure 1 iteration
tdec_iteration(&tdec, llr);
tdec_decision(&tdec, data_rx);
if (!j) gettimeofday(&tdata[2],NULL);
if (!j) get_time_interval(tdata);
if (!j) mean_usec = (float) mean_usec*0.9+(float) tdata[0].tv_usec*0.1;
/* check errors */
errors[j] += bit_diff(data_tx, data_rx, frame_length);
if (j < MAX_ITERATIONS) {
ber[j][i] = (float) errors[j] /(frame_cnt * frame_length);
}
}
frame_cnt++;
printf("Eb/No: %3.2f %10d/%d ",
SNR_MIN + i * ebno_inc,frame_cnt,nof_frames);
printf("BER: %.2e ",(float) errors[j-1] / (frame_cnt * frame_length));
printf("%3.1f Mbps (%6.2f usec)", (float) frame_length/mean_usec, mean_usec);
printf("\r");
}
printf("\n");
if (snr_points == 1) {
if (test_known_data && seed == KNOWN_DATA_SEED
&& ebno_db == KNOWN_DATA_EBNO
&& frame_cnt == KNOWN_DATA_NFRAMES) {
for (j=0;j<MAX_ITERATIONS;j++) {
if (errors[j] > known_data_errors[j]) {
fprintf(stderr, "Expected %d errors but got %d\n",
known_data_errors[j], errors[j]);
exit(-1);
}else {
printf("Iter %d ok\n", j+1);
}
}
} else {
for (j=0;j<MAX_ITERATIONS;j++) {
printf("BER: %g\t%u errors\n",
(float) errors[j] / (frame_cnt * frame_length), errors[j]);
if (test_errors) {
if (errors[j] > get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db)) {
fprintf(stderr, "Expected %d errors but got %d\n",
get_expected_errors(frame_cnt, seed, j+1, frame_length, ebno_db),
errors[j]);
exit(-1);
} else {
printf("Iter %d ok\n", j+1);
}
}
}
}
}
}
free(data_tx);
free(symbols);
free(llr);
free(llr_c);
free(data_rx);
tdec_free(&tdec);
tcod_free(&tcod);
printf("\n");
output_matlab(ber, snr_points);
printf("Done\n");
exit(0);
}

View file

@ -0,0 +1,168 @@
/**
*
* \section COPYRIGHT
*
* Copyright 2013-2014 The libLTE Developers. See the
* COPYRIGHT file at the top-level directory of this distribution.
*
* \section LICENSE
*
* This file is part of the libLTE library.
*
* libLTE is free software: you can redistribute it and/or modify
* it under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation, either version 3 of
* the License, or (at your option) any later version.
*
* libLTE is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU Lesser General Public License for more details.
*
* A copy of the GNU Lesser General Public License can be found in
* the LICENSE file in the top-level directory of this distribution
* and at http://www.gnu.org/licenses/.
*
*/
#include <stdbool.h>
typedef struct {
int n;
unsigned int s;
int iterations;
int len;
float ebno;
int errors;
} expected_errors_t;
static expected_errors_t expected_errors[] = {
{ 100, 1, 1, 504, 1.0, 3989 },
{ 100, 1, 2, 504, 1.0, 1922 },
{ 100, 1, 3, 504, 1.0, 1096 },
{ 100, 1, 4, 504, 1.0, 957 },
{ 100, 1, 1, 504, 2.0, 803 },
{ 100, 1, 2, 504, 2.0, 47 },
{ 100, 1, 3, 504, 2.0, 7 },
{ 100, 1, 4, 504, 2.0, 0 },
{ 100, 1, 1, 6144, 1.5, 24719 },
{ 100, 1, 2, 6144, 1.5, 897 },
{ 100, 1, 3, 6144, 1.5, 2 },
{ 100, 1, 4, 6144, 1.5, 0 },
{ -1, 0, -1, -1, -1.0, -1}
};
int get_expected_errors(int n, unsigned int s, int iterations, int len, float ebno) {
int i;
i = 0;
while (expected_errors[i].n != -1) {
if (expected_errors[i].n == n
&& expected_errors[i].s == s
&& expected_errors[i].len == len
&& expected_errors[i].iterations == iterations
&& expected_errors[i].ebno == ebno) {
break;
} else {
i++;
}
}
return expected_errors[i].errors;
}
#define KNOWN_DATA_NFRAMES 1
#define KNOWN_DATA_SEED 1
#define KNOWN_DATA_EBNO 0.5
const int known_data_errors[4] = {47, 18, 0, 0};
#define KNOWN_DATA_LEN 504
const char known_data[KNOWN_DATA_LEN] = { 0, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 1,
0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1,
0, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1,
1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0,
0, 0, 1, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 1, 0, 1,
1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 0,
1, 1, 0, 0, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0,
1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0,
1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 0, 1,
0, 0, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0,
0, 1, 1, 0, 1, 1, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 1,
1, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0,
0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0,
0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 1,
1, 0, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 1,
1, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0,
0, 1, 1, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0,
1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 0, 0, 1, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 1,
1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 1, 0, 1, 1, 1, 1, 1 };
const char known_data_encoded[3 * KNOWN_DATA_LEN + 12] = { 0, 0, 0, 0, 0, 1, 1,
1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 1,
1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0,
0, 0, 1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 0,
0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1,
1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1,
1, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1,
0, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 1,
1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0,
1, 0, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1,
0, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0, 1, 0,
1, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1,
0, 0, 1, 0, 1, 1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 1, 0, 0, 1, 1,
0, 1, 0, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0,
0, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0,
0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 0,
0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1,
0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 0, 0,
0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 1, 1,
0, 1, 1, 0, 0, 0, 1, 1, 1, 0, 0, 0, 1, 1, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0,
1, 1, 0, 0, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0,
1, 1, 0, 1, 1, 1, 0, 0, 0, 1, 0, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 1, 0,
1, 0, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 1,
1, 1, 0, 0, 1, 0, 0, 1, 0, 0, 1, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 1, 1,
1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 1, 0, 0, 0, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1,
0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 1, 0, 1, 1,
1, 0, 1, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1,
1, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 1, 0,
0, 0, 1, 0, 0, 0, 1, 0, 1, 1, 1, 0, 1, 1, 0, 0, 1, 1, 0, 0, 1, 1, 0, 0,
1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 0, 0,
0, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1,
1, 0, 0, 1, 0, 1, 0, 1, 1, 1, 0, 1, 1, 1, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0,
0, 1, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 1, 1, 0, 0, 0, 1,
0, 0, 0, 1, 1, 0, 0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 0, 0,
0, 1, 0, 0, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 1,
0, 0, 1, 1, 0, 0, 0, 0, 0, 0, 1, 1, 1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0,
1, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0,
0, 1, 1, 1, 1, 1, 1, 0, 0, 0, 1, 0, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 0, 0, 1, 0, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0,
0, 0, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 1,
1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 0,
0, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 0, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 1,
1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1,
1, 0, 1, 0, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 1, 1, 0, 1, 1,
0, 0, 1, 1, 0, 1, 1, 0, 1, 0, 1, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1,
0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 0, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0,
1, 0, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 0,
1, 1, 1, 0, 1, 0, 1, 0, 0, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 0, 0, 1, 1,
1, 0, 0, 0, 0, 0, 1, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 1, 0, 0, 1,
1, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 1, 1, 0, 1, 0, 1, 0, 1, 1, 1, 1, 1,
1, 1, 0, 1, 0, 0, 1, 0, 1, 0, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 1, 1, 0, 0,
0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 1, 0, 0,
1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1,
1, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1,
1, 1, 1, 1, 0, 0, 0, 0, 0, 1, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 0,
0, 0, 1, 0, 1, 1, 0, 1, 1, 0, 0, 0, 0, 1, 1, 0, 1, 0, 0, 1, 1, 1, 1, 0,
0, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 1, 0, 1, 0, 1, 1, 0,
1, 0, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1, 0, 1, 0, 0,
1, 0, 0, 0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 0, 0, 1, 0, 0, 0, 0, 1, 0, 0, 0,
0, 0, 0, 0, 0, 0, 1, 0, 0, 0, 0, 0, 1, 1, 0, 1, 1, 0, 1, 1, 1, 1, 0, 0,
1, 1, 1, 1, 0, 1, 1, 1, 1, 0, 1, 1, 1, 1, 1, 0, 0, 0, 0, 1, 0, 1, 1, 1,
1, 0, 1, 1, 1 };