mirror of https://github.com/pvnis/srsRAN_4G.git
Added Turbo Decoder
parent
2a6d2fbb64
commit
bcdf2f0886
@ -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
|
@ -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);
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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);
|
@ -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);
|
||||||
|
|
@ -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;
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -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;
|
||||||
|
}
|
@ -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++;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
||||||
|
|
@ -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;
|
||||||
|
}
|
||||||
|
|
@ -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);
|
||||||
|
}
|
@ -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 };
|
Loading…
Reference in New Issue