diff --git a/lte/include/lte.h b/lte/include/lte.h index 7a9c6a15c..d8e7ca567 100644 --- a/lte/include/lte.h +++ b/lte/include/lte.h @@ -57,6 +57,8 @@ #include "lte/fec/tc_interl.h" #include "lte/fec/turbocoder.h" #include "lte/fec/turbodecoder.h" +#include "lte/fec/rm_conv.h" +#include "lte/fec/rm_turbo.h" #include "lte/filter/filter2d.h" @@ -81,8 +83,6 @@ #include "lte/phch/pcfich.h" #include "lte/phch/phich.h" -#include "lte/ratematching/rm_conv.h" - #include "lte/scrambling/scrambling.h" #include "lte/resampling/interp.h" diff --git a/lte/include/lte/common/base.h b/lte/include/lte/common/base.h index 1d8cc5387..22de8bd37 100644 --- a/lte/include/lte/common/base.h +++ b/lte/include/lte/common/base.h @@ -39,6 +39,11 @@ #define MAX_LAYERS 8 #define MAX_CODEWORDS 2 +#define LTE_CRC24A 0x1864CFB +#define LTE_CRC24B 0X1800063 +#define LTE_CRC16 0x11021 +#define LTE_CRC8 0x19B + typedef enum {CPNORM, CPEXT} lte_cp_t; #define SIRNTI 0xFFFF diff --git a/lte/include/lte/fec/crc.h b/lte/include/lte/fec/crc.h index 0844afca4..a08e1568c 100644 --- a/lte/include/lte/fec/crc.h +++ b/lte/include/lte/fec/crc.h @@ -26,42 +26,23 @@ */ - #ifndef CRC_ #define CRC_ -#define LTE_CRC24A 0x1864CFB -#define LTE_CRC24B 0X1800063 -#define LTE_CRC16 0x11021 -#define LTE_CRC8 0x19B - - -#define _WITHMALLOC - -#ifndef _WITHMALLOC -#define MAX_LENGTH 1024*16 -#endif - typedef struct { unsigned long table[256]; -#ifdef _WITHMALLOC - unsigned char *data0; -#else - unsigned char data0[MAX_LENGTH]; -#endif + unsigned char byte; int polynom; int order; unsigned long crcinit; - unsigned long crcxor; unsigned long crcmask; unsigned long crchighbit; unsigned int crc_out; } crc_t; - -int crc_init(crc_t *crc_par); -unsigned int crc_attach(char *bufptr, int len, crc_t *crc_params); -unsigned int crc(unsigned int crc, char *bufptr, int len, - int long_crc,unsigned int poly, int paste_word); +int crc_init(crc_t *h, unsigned int crc_poly, int crc_order); +int crc_set_init(crc_t *h, unsigned long crc_init_value); +void crc_attach(crc_t *h, char *data, int len); +unsigned int crc_checksum(crc_t *h, char *data, int len); #endif diff --git a/lte/include/lte/ratematching/rm_conv.h b/lte/include/lte/fec/rm_conv.h similarity index 100% rename from lte/include/lte/ratematching/rm_conv.h rename to lte/include/lte/fec/rm_conv.h diff --git a/lte/include/lte/fec/turbodecoder.h2 b/lte/include/lte/fec/rm_turbo.h similarity index 51% rename from lte/include/lte/fec/turbodecoder.h2 rename to lte/include/lte/fec/rm_turbo.h index 003cfbbde..96aefadb3 100644 --- a/lte/include/lte/fec/turbodecoder.h2 +++ b/lte/include/lte/fec/rm_turbo.h @@ -1,68 +1,59 @@ -/** - * - * \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); - +/** + * + * \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 RM_CONV_ +#define RM_CONV_ + +#define RX_NULL 10000 +#define TX_NULL 80 + + +int rm_turbo_tx(char *input, char *output, int in_len, int out_len); +int rm_turbo_rx(float *input, float *output, int in_len, int out_len); + + +/* High-level API */ +typedef struct { + struct rm_turbo_init { + int direction; + } init; + void *input; // input type may be char or float depending on hard + int in_len; + struct rm_turbo_ctrl_in { + int E; + int S; + } ctrl_in; + void *output; + int out_len; +}rm_turbo_hl; + +int rm_turbo_initialize(rm_turbo_hl* h); +int rm_turbo_work(rm_turbo_hl* hl); +int rm_turbo_stop(rm_turbo_hl* hl); + +#endif diff --git a/lte/include/lte/phch/pbch.h b/lte/include/lte/phch/pbch.h index 9cb3ae113..877dd6439 100644 --- a/lte/include/lte/phch/pbch.h +++ b/lte/include/lte/phch/pbch.h @@ -35,7 +35,7 @@ #include "lte/modem/mod.h" #include "lte/modem/demod_soft.h" #include "lte/scrambling/scrambling.h" -#include "lte/ratematching/rm_conv.h" +#include "lte/fec/rm_conv.h" #include "lte/fec/convcoder.h" #include "lte/fec/viterbi.h" #include "lte/fec/crc.h" @@ -79,6 +79,7 @@ typedef struct { demod_soft_t demod; sequence_t seq_pbch; viterbi_t decoder; + crc_t crc; convcoder_t encoder; }pbch_t; diff --git a/lte/include/lte/phch/pdcch.h b/lte/include/lte/phch/pdcch.h index 75c8e768c..b7767d0b5 100644 --- a/lte/include/lte/phch/pdcch.h +++ b/lte/include/lte/phch/pdcch.h @@ -35,7 +35,7 @@ #include "lte/modem/mod.h" #include "lte/modem/demod_soft.h" #include "lte/scrambling/scrambling.h" -#include "lte/ratematching/rm_conv.h" +#include "lte/fec/rm_conv.h" #include "lte/fec/convcoder.h" #include "lte/fec/viterbi.h" #include "lte/fec/crc.h" @@ -88,7 +88,7 @@ typedef struct { demod_soft_t demod; sequence_t seq_pdcch[NSUBFRAMES_X_FRAME]; viterbi_t decoder; - + crc_t crc; }pdcch_t; int pdcch_init(pdcch_t *q, regs_t *regs, int nof_prb, int nof_ports, int cell_id, lte_cp_t cp); diff --git a/lte/lib/fec/src/crc.c b/lte/lib/fec/src/crc.c index 8a0cd92bf..e2de27c4f 100644 --- a/lte/lib/fec/src/crc.c +++ b/lte/lib/fec/src/crc.c @@ -25,191 +25,141 @@ * */ - #include #include #include -#include "lte/utils/pack.h" +#include "lte/utils/pack.h" #include "lte/fec/crc.h" +void gen_crc_table(crc_t *h) { -void gen_crc_table(crc_t *crc_params) { - - int i, j, ord=(crc_params->order-8); + int i, j, ord = (h->order - 8); unsigned long bit, crc; - for (i=0; i<256; i++) { - crc = ((unsigned long)i)<crchighbit; - crc<<= 1; - if (bit) crc^= crc_params->polynom; - } - crc_params->table[i]=crc & crc_params->crcmask; + for (i = 0; i < 256; i++) { + crc = ((unsigned long) i) << ord; + for (j = 0; j < 8; j++) { + bit = crc & h->crchighbit; + crc <<= 1; + if (bit) + crc ^= h->polynom; + } + h->table[i] = crc & h->crcmask; } } - -unsigned long crctable (unsigned long length, crc_t *crc_params) { +unsigned long crctable(crc_t *h) { // Polynom order 8, 16, 24 or 32 only. - int ord=crc_params->order-8; - unsigned long crc = crc_params->crcinit; - unsigned char* data = crc_params->data0; + int ord = h->order - 8; + unsigned long crc = h->crcinit; + unsigned char byte = h->byte; - while (length--){ - crc = (crc << 8) ^ crc_params->table[ ((crc >> (ord)) & 0xff) ^ *data++]; - } - return((crc ^ crc_params->crcxor) & crc_params->crcmask); + crc = (crc << 8) ^ h->table[((crc >> (ord)) & 0xff) ^ byte]; + h->crcinit = crc; + return (crc & h->crcmask); } -unsigned long reversecrcbit(unsigned int crc, int nbits, crc_t *crc_params) { +unsigned long reversecrcbit(unsigned int crc, int nbits, crc_t *h) { + + unsigned long m, rmask = 0x1; + + for (m = 0; m < nbits; m++) { + if ((rmask & crc) == 0x01) + crc = (crc ^ h->polynom) >> 1; + else + crc = crc >> 1; + } + return (crc & h->crcmask); +} - unsigned long m, rmask=0x1; +int crc_set_init(crc_t *crc_par, unsigned long crc_init_value) { - for(m=0; mpolynom)>>1; - else crc = crc >> 1; + crc_par->crcinit = crc_init_value; + if (crc_par->crcinit != (crc_par->crcinit & crc_par->crcmask)) { + printf("ERROR, invalid crcinit in crc_set_init().\n"); + return -1; } - return((crc ^ crc_params->crcxor) & crc_params->crcmask); + return 0; } +int crc_init(crc_t *h, unsigned int crc_poly, int crc_order) { -int crc_init(crc_t *crc_par){ + // Set crc working default parameters + h->polynom = crc_poly; + h->order = crc_order; + h->crcinit = 0x00000000; // Compute bit masks for whole CRC and CRC high bit - crc_par->crcmask = ((((unsigned long)1<<(crc_par->order-1))-1)<<1)|1; - crc_par->crchighbit = (unsigned long)1<<(crc_par->order-1); - - printf("crcmask=%x, crchightbit=%x\n", - (unsigned int)crc_par->crcmask, (unsigned int)crc_par->crchighbit); + h->crcmask = ((((unsigned long) 1 << (h->order - 1)) - 1) << 1) + | 1; + h->crchighbit = (unsigned long) 1 << (h->order - 1); // check parameters - if (crc_par->order%8 != 0) { - printf("ERROR, invalid order=%d, it must be 8, 16, 24 or 32.\n", crc_par->order); - return(0); + if (h->order % 8 != 0) { + fprintf(stderr, "ERROR, invalid order=%d, it must be 8, 16, 24 or 32.\n", + h->order); + return -1; } - if (crc_par->crcinit != (crc_par->crcinit & crc_par->crcmask)) { - printf("ERROR, invalid crcinit.\n"); - return(0); - } - if (crc_par->crcxor != (crc_par->crcxor & crc_par->crcmask)) { - printf("ERROR, invalid crcxor.\n"); - return(0); + if (crc_set_init(h, h->crcinit)) { + fprintf(stderr, "Error setting CRC init word\n"); + return -1; } + // generate lookup table - gen_crc_table(crc_par); + gen_crc_table(h); - return(1); + return 0; } - -unsigned int crc_attach(char *bufptr, int len, crc_t *crc_params) { - - int i, len8, res8, a; - unsigned int crc; +unsigned int crc_checksum(crc_t *h, char *data, int len) { + int i, k, len8, res8, a = 0; + unsigned int crc = 0; char *pter; -#ifdef _WITHMALLOC - crc_params->data0 = (unsigned char *)malloc(sizeof(*crc_params->data0) * (len+crc_params->order)*2); - if (!crc_params->data0) { - perror("malloc ERROR: Allocating memory for data pointer in crc() function"); - return(-1); - } -#else - if((((len+crc_params->order)>>3) + 1) > MAX_LENGTH){ - printf("ERROR: Not enough memory allocated\n"); - return(-1); - } -#endif - //# Pack bits into bytes - len8=(len>>3); - res8=8-(len - (len8<<3)); - if(res8>0)a=1; - else a=0; - - // Zeroed additional bits - memset((char *)(bufptr+len),0,(32)*sizeof(char)); - - for(i=0; idata0[i]=(unsigned char)(unpack_bits(&pter, 8)&0xFF); + crc_set_init(h, 0); + + // Pack bits into bytes + len8 = (len >> 3); + res8 = (len - (len8 << 3)); + if (res8 > 0) { + a = 1; } + // Calculate CRC - crc=crctable(len8+a, crc_params); + for (i = 0; i < len8 + a; i++) { + pter = (char *) (data + 8 * i); + if (i == len8) { + h->byte = 0x00; + for (k = 0; k < res8; k++) { + h->byte |= ((unsigned char) *(pter + k)) << (7 - k); + } + } else { + h->byte = (unsigned char) (unpack_bits(&pter, 8) & 0xFF); + } + crc = crctable(h); + } // Reverse CRC res8 positions - if(a==1)crc=reversecrcbit(crc, res8, crc_params); - - // Add CRC - pter=(char *)(bufptr+len); - pack_bits(crc, &pter, crc_params->order); + if (a == 1) { + crc = reversecrcbit(crc, 8 - res8, h); + } -#ifdef _WITHMALLOC - free(crc_params->data0); - crc_params->data0=NULL; -#endif //Return CRC value return crc; -} - - -unsigned int cword; -unsigned int icrc1(unsigned int crc, unsigned short onech,int long_crc, - int left_shift,unsigned int poly) -{ - int i; - unsigned int tmp=(unsigned int) (crc ^ (onech << (long_crc >> 1) )); +} - for (i=0;iorder); } -unsigned int crc(unsigned int crc, char *bufptr, int len, - int long_crc,unsigned int poly, int paste_word) { - - int i,k; - unsigned int data; - int stop; - unsigned int ret; - - cword=crc; - - k=0; - stop=0; - while(!stop) { - data=0; - for (i=0;i>long_crc), - data,long_crc,i,poly)<>long_crc; - } - - ret=cword; - if (paste_word) { - cword<<=32-long_crc; - for (i=0;i>31); - cword<<=1; - } - } - return (ret); -} diff --git a/lte/lib/ratematching/src/rm_conv.c b/lte/lib/fec/src/rm_conv.c similarity index 96% rename from lte/lib/ratematching/src/rm_conv.c rename to lte/lib/fec/src/rm_conv.c index d7b605cb7..ea90b83cf 100644 --- a/lte/lib/ratematching/src/rm_conv.c +++ b/lte/lib/fec/src/rm_conv.c @@ -28,7 +28,7 @@ #include #include -#include "lte/ratematching/rm_conv.h" +#include "lte/fec/rm_conv.h" #define NCOLS 32 #define NROWS_MAX NCOLS @@ -59,6 +59,7 @@ int rm_conv_tx(char *input, char *output, int in_len, int out_len) { if (ndummy < 0) { ndummy = 0; } + /* Sub-block interleaver 5.1.4.2.1 */ k=0; for (s = 0; s < 3; s++) { for (j = 0; j < NCOLS; j++) { @@ -72,6 +73,7 @@ int rm_conv_tx(char *input, char *output, int in_len, int out_len) { } } } + /* Bit collection, selection and transmission 5.1.4.2.2 */ k = 0; j = 0; while (k < out_len) { diff --git a/lte/lib/fec/src/rm_turbo.c b/lte/lib/fec/src/rm_turbo.c new file mode 100644 index 000000000..ee0561f36 --- /dev/null +++ b/lte/lib/fec/src/rm_turbo.c @@ -0,0 +1,180 @@ +/** + * + * \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 +#include +#include "lte/fec/rm_turbo.h" + +#define NCOLS 32 +#define NROWS_MAX NCOLS +#define RATE 3 + +unsigned char RM_PERM_CC[NCOLS] = + { 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30, 1, 17, 9, + 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 }; + +unsigned char RM_PERM_CC_INV[NCOLS] = { 16, 0, 24, 8, 20, 4, 28, 12, 18, 2, 26, + 10, 22, 6, 30, 14, 17, 1, 25, 9, 21, 5, 29, 13, 19, 3, 27, 11, 23, 7, + 31, 15 }; + +int rm_turbo_tx(char *input, char *output, int in_len, int out_len) { + + char tmp[RATE * NCOLS * NROWS_MAX]; + int nrows, ndummy, K_p; + + int i, j, k, s; + + nrows = (int) (in_len / RATE - 1) / NCOLS + 1; + if (nrows > NROWS_MAX) { + fprintf(stderr, "Input too large. Max input length is %d\n", + RATE * NCOLS * NROWS_MAX); + return -1; + } + K_p = nrows * NCOLS; + ndummy = K_p - in_len / RATE; + if (ndummy < 0) { + ndummy = 0; + } + + /* Sub-block interleaver 5.1.4.1.1 */ + k = 0; + for (s = 0; s < 3; s++) { + for (j = 0; j < NCOLS; j++) { + for (i = 0; i < nrows; i++) { + if (i * NCOLS + RM_PERM_CC[j] < ndummy) { + tmp[k] = TX_NULL; + } else { + tmp[k] = input[(i * NCOLS + RM_PERM_CC[j] - ndummy) * 3 + s]; + } + k++; + } + } + } + /* Bit collection, selection and transmission 5.1.4.1.2 */ + k = 0; + j = 0; + while (k < out_len) { + if (tmp[j] != TX_NULL) { + output[k] = tmp[j]; + k++; + } + j++; + if (j == RATE * K_p) { + j = 0; + } + } + return 0; +} + +/* Undoes Convolutional Code Rate Matching. + * 3GPP TS 36.212 v10.1.0 section 5.1.4.2 + */ +int rm_turbo_rx(float *input, float *output, int in_len, int out_len) { + + int nrows, ndummy, K_p; + int i, j, k; + int d_i, d_j; + + float tmp[RATE * NCOLS * NROWS_MAX]; + + nrows = (int) (out_len / RATE - 1) / NCOLS + 1; + if (nrows > NROWS_MAX) { + fprintf(stderr, "Output too large. Max output length is %d\n", + RATE * NCOLS * NROWS_MAX); + return -1; + } + K_p = nrows * NCOLS; + + ndummy = K_p - out_len / RATE; + if (ndummy < 0) { + ndummy = 0; + } + + for (i = 0; i < RATE * K_p; i++) { + tmp[i] = RX_NULL; + } + + /* Undo bit collection. Account for dummy bits */ + k = 0; + j = 0; + while (k < in_len) { + d_i = (j % K_p) / nrows; + d_j = (j % K_p) % nrows; + + if (d_j * NCOLS + RM_PERM_CC[d_i] >= ndummy) { + if (tmp[j] == RX_NULL) { + tmp[j] = input[k]; + } else if (input[k] != RX_NULL) { + tmp[j] += input[k]; /* soft combine LLRs */ + } + k++; + } + j++; + if (j == RATE * K_p) { + j = 0; + } + } + + /* interleaving and bit selection */ + for (i = 0; i < out_len / RATE; i++) { + d_i = (i + ndummy) / NCOLS; + d_j = (i + ndummy) % NCOLS; + for (j = 0; j < RATE; j++) { + float o = tmp[K_p * j + RM_PERM_CC_INV[d_j] * nrows + d_i]; + if (o != RX_NULL) { + output[i * RATE + j] = o; + } else { + output[i * RATE + j] = 0; + } + } + } + return 0; +} + +/** High-level API */ + +int rm_turbo_initialize(rm_turbo_hl* h) { + + return 0; +} + +/** This function can be called in a subframe (1ms) basis */ +int rm_turbo_work(rm_turbo_hl* hl) { + if (hl->init.direction) { + //rm_turbo_tx(hl->input, hl->output, hl->in_len, hl->ctrl_in.S); + hl->out_len = hl->ctrl_in.S; + } else { + rm_turbo_rx(hl->input, hl->output, hl->in_len, hl->ctrl_in.E); + hl->out_len = hl->ctrl_in.E; + } + return 0; +} + +int rm_turbo_stop(rm_turbo_hl* hl) { + return 0; +} + diff --git a/lte/lib/fec/test/CMakeLists.txt b/lte/lib/fec/test/CMakeLists.txt index 1f83b8411..95a9d5974 100644 --- a/lte/lib/fec/test/CMakeLists.txt +++ b/lte/lib/fec/test/CMakeLists.txt @@ -20,6 +20,17 @@ # +######################################################################## +# RATEMATCHING TEST +######################################################################## + +ADD_EXECUTABLE(rm_conv_test rm_conv_test.c) +TARGET_LINK_LIBRARIES(rm_conv_test lte) + +ADD_TEST(rm_conv_test_1 rm_conv_test -t 480 -r 1920) +ADD_TEST(rm_conv_test_2 rm_conv_test -t 1920 -r 480) + + ######################################################################## # Turbo Coder TEST ######################################################################## diff --git a/lte/lib/fec/test/crc_test.c b/lte/lib/fec/test/crc_test.c index 28c389002..e21c89c4d 100644 --- a/lte/lib/fec/test/crc_test.c +++ b/lte/lib/fec/test/crc_test.c @@ -25,7 +25,6 @@ * */ - #include #include #include @@ -37,11 +36,10 @@ #include "lte.h" #include "crc_test.h" -int num_bits = 5000, crc_length = 24; +int num_bits = 5001, crc_length = 24; unsigned int crc_poly = 0x1864CFB; unsigned int seed = 1; - void usage(char *prog) { printf("Usage: %s [nlps]\n", prog); printf("\t-n num_bits [Default %d]\n", num_bits); @@ -81,7 +79,7 @@ int main(int argc, char **argv) { parse_args(argc, argv); - data = malloc(sizeof(char) * (num_bits+crc_length)*2); + data = malloc(sizeof(char) * (num_bits + crc_length * 2)); if (!data) { perror("malloc"); exit(-1); @@ -93,30 +91,23 @@ int main(int argc, char **argv) { srand(seed); // Generate data - for (i=0;i +#include +#include +#include +#include +#include +#include +#include + +#include "lte.h" + +int nof_tx_bits=-1, nof_rx_bits=-1; + +void usage(char *prog) { + printf("Usage: %s -t nof_tx_bits -r nof_rx_bits\n", prog); +} + +void parse_args(int argc, char **argv) { + int opt; + while ((opt = getopt(argc, argv, "tr")) != -1) { + switch (opt) { + case 't': + nof_tx_bits = atoi(argv[optind]); + break; + case 'r': + nof_rx_bits = atoi(argv[optind]); + break; + default: + usage(argv[0]); + exit(-1); + } + } + if (nof_tx_bits == -1) { + usage(argv[0]); + exit(-1); + } + if (nof_rx_bits == -1) { + usage(argv[0]); + exit(-1); + } +} + +int main(int argc, char **argv) { + int i; + char *bits, *rm_bits; + float *rm_symbols, *unrm_symbols; + int nof_errors; + + parse_args(argc, argv); + + bits = malloc(sizeof(char) * nof_tx_bits); + if (!bits) { + perror("malloc"); + exit(-1); + } + rm_bits = malloc(sizeof(char) * nof_rx_bits); + if (!rm_bits) { + perror("malloc"); + exit(-1); + } + rm_symbols = malloc(sizeof(float) * nof_rx_bits); + if (!rm_symbols) { + perror("malloc"); + exit(-1); + } + unrm_symbols = malloc(sizeof(float) * nof_tx_bits); + if (!unrm_symbols) { + perror("malloc"); + exit(-1); + } + + for (i=0;i 0) != bits[i]) { + nof_errors++; + } + } + if (nof_rx_bits > nof_tx_bits) { + if (nof_errors) { + printf("nof_errors=%d\n", nof_errors); + exit(-1); + } + } + + free(bits); + free(rm_bits); + free(rm_symbols); + free(unrm_symbols); + + printf("Ok\n"); + exit(0); +} diff --git a/lte/lib/phch/src/pbch.c b/lte/lib/phch/src/pbch.c index a20684380..e6a413f08 100644 --- a/lte/lib/phch/src/pbch.c +++ b/lte/lib/phch/src/pbch.c @@ -133,6 +133,9 @@ int pbch_init(pbch_t *q, int nof_prb, int cell_id, lte_cp_t cp) { if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) { goto clean; } + if (crc_init(&q->crc, LTE_CRC16, 16)) { + goto clean; + } q->encoder.K = 7; q->encoder.R = 3; q->encoder.tail_biting = true; @@ -356,11 +359,11 @@ void crc_set_mask(char *data, int nof_ports) { * * Returns 0 if the data is correct, -1 otherwise */ -int pbch_crc_check(char *bits, int nof_ports) { +int pbch_crc_check(pbch_t *q, char *bits, int nof_ports) { char data[40]; memcpy(data, bits, 40 * sizeof(char)); crc_set_mask(data, nof_ports); - return crc(0, data, 40, 16, LTE_CRC16, 0); + return crc_checksum(&q->crc, data, 40); } int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n, int nof_bits, int nof_ports) { @@ -399,7 +402,7 @@ int pbch_decode_frame(pbch_t *q, pbch_mib_t *mib, int src, int dst, int n, int n c=1; } - if (!pbch_crc_check(q->data, nof_ports)) { + if (!pbch_crc_check(q, q->data, nof_ports)) { /* unpack MIB */ pbch_mib_unpack(q->data, mib); @@ -523,7 +526,7 @@ void pbch_encode(pbch_t *q, pbch_mib_t *mib, cf_t *slot1_symbols[MAX_PORTS_CTRL] pbch_mib_pack(mib, q->data); /* encode & modulate */ - crc(0, q->data, 24, 16, 0x11021, 1); + crc_attach(&q->crc, q->data, 24); crc_set_mask(q->data, nof_ports); convcoder_encode(&q->encoder, q->data, q->data_enc, 40); diff --git a/lte/lib/phch/src/pdcch.c b/lte/lib/phch/src/pdcch.c index a98b6a47c..0a8fe4e7a 100644 --- a/lte/lib/phch/src/pdcch.c +++ b/lte/lib/phch/src/pdcch.c @@ -221,6 +221,9 @@ int pdcch_init(pdcch_t *q, regs_t *regs, int nof_prb, int nof_ports, if (modem_table_std(&q->mod, LTE_QPSK, true)) { goto clean; } + if (crc_init(&q->crc, LTE_CRC16, 16)) { + goto clean; + } demod_soft_init(&q->demod); demod_soft_table_set(&q->demod, &q->mod); @@ -318,7 +321,7 @@ void pdcch_free(pdcch_t *q) { * * TODO: UE transmit antenna selection CRC mask */ -unsigned short dci_decode(viterbi_t *decoder, float *e, char *data, int E, +unsigned short dci_decode(pdcch_t *q, float *e, char *data, int E, int nof_bits) { float tmp[3 * (DCI_MAX_BITS + 16)]; @@ -343,7 +346,7 @@ unsigned short dci_decode(viterbi_t *decoder, float *e, char *data, int E, } /* viterbi decoder */ - viterbi_decode_f(decoder, tmp, data, nof_bits + 16); + viterbi_decode_f(&q->decoder, tmp, data, nof_bits + 16); if (VERBOSE_ISDEBUG()) { bit_fprint(stdout, data, nof_bits+16); @@ -351,8 +354,7 @@ unsigned short dci_decode(viterbi_t *decoder, float *e, char *data, int E, x = &data[nof_bits]; p_bits = (unsigned short) bit_unpack(&x, 16); - crc_res = ((unsigned short) crc(0, data, nof_bits, 16, LTE_CRC16, 0) - & 0xffff); + crc_res = ((unsigned short) crc_checksum(&q->crc, data, nof_bits) & 0xffff); DEBUG("p_bits: 0x%x, crc_res: 0x%x, tot: 0x%x\n", p_bits, crc_res, p_bits ^ crc_res); return (p_bits ^ crc_res); } @@ -363,7 +365,7 @@ int pdcch_decode_candidate(pdcch_t *q, float *llr, dci_candidate_t *c, DEBUG("Trying Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, c->rnti); - crc_res = dci_decode(&q->decoder, &llr[72 * c->ncce], msg->data, + crc_res = dci_decode(q, &llr[72 * c->ncce], msg->data, PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits); if (c->rnti == crc_res) { @@ -519,7 +521,7 @@ void crc_set_mask_rnti(char *crc, unsigned short rnti) { /** 36.212 5.3.3.2 to 5.3.3.4 * TODO: UE transmit antenna selection CRC mask */ -void dci_encode(char *data, char *e, int nof_bits, int E, unsigned short rnti) { +void dci_encode(pdcch_t *q, char *data, char *e, int nof_bits, int E, unsigned short rnti) { convcoder_t encoder; char tmp[3 * (DCI_MAX_BITS + 16)]; @@ -531,7 +533,7 @@ void dci_encode(char *data, char *e, int nof_bits, int E, unsigned short rnti) { encoder.tail_biting = true; memcpy(encoder.poly, poly, 3 * sizeof(int)); - crc(0, data, nof_bits, 16, LTE_CRC16, 1); + crc_attach(&q->crc, data, nof_bits); crc_set_mask_rnti(&data[nof_bits], rnti); convcoder_encode(&encoder, data, tmp, nof_bits + 16); @@ -579,7 +581,7 @@ int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot1_symbols[MAX_PORTS_CTRL], i, dci->msg[i].location.nof_bits, PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), dci->msg[i].location.ncce, dci->msg[i].location.L, dci->msg[i].location.rnti); - dci_encode(dci->msg[i].data, &q->pdcch_e[72 * dci->msg[i].location.ncce], + dci_encode(q, dci->msg[i].data, &q->pdcch_e[72 * dci->msg[i].location.ncce], dci->msg[i].location.nof_bits, PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L), dci->msg[i].location.rnti); } diff --git a/lte/lib/ratematching/test/CMakeLists.txt b/lte/lib/ratematching/test/CMakeLists.txt deleted file mode 100644 index 1c4ded6df..000000000 --- a/lte/lib/ratematching/test/CMakeLists.txt +++ /dev/null @@ -1,33 +0,0 @@ -# -# Copyright 2012-2013 The libLTE Developers. See the -# COPYRIGHT file at the top-level directory of this distribution. -# -# 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/. -# - -######################################################################## -# RATEMATCHING TEST -######################################################################## - -ADD_EXECUTABLE(rm_conv_test rm_conv_test.c) -TARGET_LINK_LIBRARIES(rm_conv_test lte) - -ADD_TEST(rm_conv_test_1 rm_conv_test -t 480 -r 1920) -ADD_TEST(rm_conv_test_2 rm_conv_test -t 1920 -r 480) - - -