Added CRC. Changed ratematching to FEC directory

This commit is contained in:
ismagom 2014-06-03 14:59:15 +02:00
parent 887c3a8e80
commit 6fe5a05952
17 changed files with 520 additions and 301 deletions

View File

@ -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"

View File

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

View File

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

View File

@ -25,44 +25,35 @@
*
*/
#define RATE 3
#define TOTALTAIL 12
#define LOG18 -2.07944
#ifndef RM_CONV_
#define RM_CONV_
#define NUMSTATES 8
#define NINPUTS 2
#define TOTALTAIL 12
#define RX_NULL 10000
#define TX_NULL 80
#define SCALE 80
#define INF 9e4
#define ZERO 9e-4
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);
#define MAX_LONG_CB 6114
#define MAX_LONG_CODED (RATE*MAX_LONG_CB+TOTALTAIL)
typedef float llr_t;
/* High-level API */
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;
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;
}tdec_t;
int tdec_init(tdec_t *h);
int turbo_decoder(tdec_t *h, llr_t *input, char *output, int *halt);
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

View File

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

View File

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

View File

@ -25,191 +25,141 @@
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#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)<<ord;
for (j=0; j<8; j++) {
bit = crc & crc_params->crchighbit;
crc<<= 1;
if (bit) crc^= crc_params->polynom;
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;
}
crc_params->table[i]=crc & crc_params->crcmask;
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;
unsigned long m, rmask = 0x1;
for(m=0; m<nbits; m++){
if((rmask & crc) == 0x01 )crc = (crc ^ crc_params->polynom)>>1;
else crc = crc >> 1;
for (m = 0; m < nbits; m++) {
if ((rmask & crc) == 0x01)
crc = (crc ^ h->polynom) >> 1;
else
crc = crc >> 1;
}
return((crc ^ crc_params->crcxor) & crc_params->crcmask);
return (crc & h->crcmask);
}
int crc_set_init(crc_t *crc_par, unsigned long crc_init_value) {
int crc_init(crc_t *crc_par){
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 0;
}
int crc_init(crc_t *h, unsigned int crc_poly, int crc_order) {
// 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;
crc_set_init(h, 0);
// Zeroed additional bits
memset((char *)(bufptr+len),0,(32)*sizeof(char));
for(i=0; i<len8+a; i++){
pter=(char *)(bufptr+8*i);
crc_params->data0[i]=(unsigned char)(unpack_bits(&pter, 8)&0xFF);
// 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);
if (a == 1) {
crc = reversecrcbit(crc, 8 - res8, h);
}
// Add CRC
pter=(char *)(bufptr+len);
pack_bits(crc, &pter, crc_params->order);
#ifdef _WITHMALLOC
free(crc_params->data0);
crc_params->data0=NULL;
#endif
//Return CRC value
return crc;
}
/** Appends crc_order checksum bits to the buffer data.
* The buffer data must be len + crc_order bytes
*/
void crc_attach(crc_t *h, char *data, int len) {
unsigned int checksum = crc_checksum(h, data, len);
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;i<left_shift;i++) {
if (tmp & (0x1<<(long_crc-1)))
tmp=(tmp<<1)^poly;
else
tmp <<= 1;
}
return tmp;
// Add CRC
char *ptr = &data[len];
pack_bits(checksum, &ptr, h->order);
}
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/2;i++) {
if (bufptr[k] && k<len)
data|=(0x1<<(long_crc/2-1-i));
k++;
if (k==len) {
stop=1;
i++;
break;
}
}
cword=(unsigned int) (icrc1((unsigned int) (cword<<long_crc>>long_crc),
data,long_crc,i,poly)<<long_crc)>>long_crc;
}
ret=cword;
if (paste_word) {
cword<<=32-long_crc;
for (i=0;i<long_crc;i++) {
bufptr[i+len]=((cword&(0x1<<31))>>31);
cword<<=1;
}
}
return (ret);
}

View File

@ -28,7 +28,7 @@
#include <string.h>
#include <stdio.h>
#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) {

180
lte/lib/fec/src/rm_turbo.c Normal file
View File

@ -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 <string.h>
#include <stdio.h>
#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;
}

View File

@ -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
########################################################################

View File

@ -25,7 +25,6 @@
*
*/
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
@ -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<num_bits;i++) {
data[i] = rand()%2;
for (i = 0; i < num_bits; i++) {
data[i] = rand() % 2;
}
//Initialize CRC params and tables
crc_p.polynom=crc_poly;
crc_p.order=crc_length;
crc_p.crcinit=0x00000000;
crc_p.crcxor=0x00000000;
if(!crc_init(&crc_p))exit(0);
// generate CRC word
crc_word = crc_attach(data, num_bits, &crc_p);
// check if result is zero
if (crc_attach(data, num_bits + crc_length, &crc_p)) {
printf("CRC check is non-zero\n");
if (crc_init(&crc_p, crc_poly, crc_length)) {
exit(-1);
}
// generate CRC word
crc_word = crc_checksum(&crc_p, data, num_bits);
free(data);
// check if generated word is as expected
if (get_expected_word(num_bits, crc_length, crc_poly, seed, &expected_word)) {
if (get_expected_word(num_bits, crc_length, crc_poly, seed,
&expected_word)) {
fprintf(stderr, "Test parameters not defined in test_results.h\n");
exit(-1);
}

View File

@ -0,0 +1,135 @@
/**
*
* \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 <stdbool.h>
#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<nof_tx_bits;i++) {
bits[i] = rand()%2;
}
if (rm_conv_tx(bits, rm_bits, nof_tx_bits, nof_rx_bits)) {
exit(-1);
}
for (i=0;i<nof_rx_bits;i++) {
rm_symbols[i] = rm_bits[i]?1:-1;
}
if (rm_conv_rx(rm_symbols, unrm_symbols, nof_rx_bits, nof_tx_bits)) {
exit(-1);
}
nof_errors = 0;
for (i=0;i<nof_tx_bits;i++) {
if ((unrm_symbols[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);
}

View File

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

View File

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

View File

@ -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)