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/tc_interl.h"
#include "lte/fec/turbocoder.h" #include "lte/fec/turbocoder.h"
#include "lte/fec/turbodecoder.h" #include "lte/fec/turbodecoder.h"
#include "lte/fec/rm_conv.h"
#include "lte/fec/rm_turbo.h"
#include "lte/filter/filter2d.h" #include "lte/filter/filter2d.h"
@ -81,8 +83,6 @@
#include "lte/phch/pcfich.h" #include "lte/phch/pcfich.h"
#include "lte/phch/phich.h" #include "lte/phch/phich.h"
#include "lte/ratematching/rm_conv.h"
#include "lte/scrambling/scrambling.h" #include "lte/scrambling/scrambling.h"
#include "lte/resampling/interp.h" #include "lte/resampling/interp.h"

View File

@ -39,6 +39,11 @@
#define MAX_LAYERS 8 #define MAX_LAYERS 8
#define MAX_CODEWORDS 2 #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; typedef enum {CPNORM, CPEXT} lte_cp_t;
#define SIRNTI 0xFFFF #define SIRNTI 0xFFFF

View File

@ -26,42 +26,23 @@
*/ */
#ifndef CRC_ #ifndef CRC_
#define 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 { typedef struct {
unsigned long table[256]; unsigned long table[256];
#ifdef _WITHMALLOC unsigned char byte;
unsigned char *data0;
#else
unsigned char data0[MAX_LENGTH];
#endif
int polynom; int polynom;
int order; int order;
unsigned long crcinit; unsigned long crcinit;
unsigned long crcxor;
unsigned long crcmask; unsigned long crcmask;
unsigned long crchighbit; unsigned long crchighbit;
unsigned int crc_out; unsigned int crc_out;
} crc_t; } crc_t;
int crc_init(crc_t *h, unsigned int crc_poly, int crc_order);
int crc_init(crc_t *crc_par); int crc_set_init(crc_t *h, unsigned long crc_init_value);
unsigned int crc_attach(char *bufptr, int len, crc_t *crc_params); void crc_attach(crc_t *h, char *data, int len);
unsigned int crc(unsigned int crc, char *bufptr, int len, unsigned int crc_checksum(crc_t *h, char *data, int len);
int long_crc,unsigned int poly, int paste_word);
#endif #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 RX_NULL 10000
#define NINPUTS 2 #define TX_NULL 80
#define TOTALTAIL 12
#define SCALE 80
#define INF 9e4 int rm_turbo_tx(char *input, char *output, int in_len, int out_len);
#define ZERO 9e-4 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 { typedef struct {
int long_cb; struct rm_turbo_init {
int max_iterations; int direction;
int halt_threshold; } init;
enum { HALT_MIN = 2, HALT_MEAN = 1, HALT_NONE = 0} halt_mode; void *input; // input type may be char or float depending on hard
llr_t alfa[NUMSTATES]; int in_len;
llr_t beta[(MAX_LONG_CB + 1) * NUMSTATES]; struct rm_turbo_ctrl_in {
llr_t LLR1[MAX_LONG_CB + TOTALTAIL]; int E;
llr_t LLR2[MAX_LONG_CB + TOTALTAIL]; int S;
llr_t W[MAX_LONG_CB + TOTALTAIL]; } ctrl_in;
llr_t data[RATE*(MAX_LONG_CB + TOTALTAIL)]; void *output;
llr_t *parity; int out_len;
struct permute_t permuta; }rm_turbo_hl;
int iteration;
int HALT_min;
}tdec_t; int rm_turbo_initialize(rm_turbo_hl* h);
int rm_turbo_work(rm_turbo_hl* hl);
int tdec_init(tdec_t *h); int rm_turbo_stop(rm_turbo_hl* hl);
int turbo_decoder(tdec_t *h, llr_t *input, char *output, int *halt);
#endif

View File

@ -35,7 +35,7 @@
#include "lte/modem/mod.h" #include "lte/modem/mod.h"
#include "lte/modem/demod_soft.h" #include "lte/modem/demod_soft.h"
#include "lte/scrambling/scrambling.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/convcoder.h"
#include "lte/fec/viterbi.h" #include "lte/fec/viterbi.h"
#include "lte/fec/crc.h" #include "lte/fec/crc.h"
@ -79,6 +79,7 @@ typedef struct {
demod_soft_t demod; demod_soft_t demod;
sequence_t seq_pbch; sequence_t seq_pbch;
viterbi_t decoder; viterbi_t decoder;
crc_t crc;
convcoder_t encoder; convcoder_t encoder;
}pbch_t; }pbch_t;

View File

@ -35,7 +35,7 @@
#include "lte/modem/mod.h" #include "lte/modem/mod.h"
#include "lte/modem/demod_soft.h" #include "lte/modem/demod_soft.h"
#include "lte/scrambling/scrambling.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/convcoder.h"
#include "lte/fec/viterbi.h" #include "lte/fec/viterbi.h"
#include "lte/fec/crc.h" #include "lte/fec/crc.h"
@ -88,7 +88,7 @@ typedef struct {
demod_soft_t demod; demod_soft_t demod;
sequence_t seq_pdcch[NSUBFRAMES_X_FRAME]; sequence_t seq_pdcch[NSUBFRAMES_X_FRAME];
viterbi_t decoder; viterbi_t decoder;
crc_t crc;
}pdcch_t; }pdcch_t;
int pdcch_init(pdcch_t *q, regs_t *regs, int nof_prb, int nof_ports, int cell_id, lte_cp_t cp); 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 <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include "lte/utils/pack.h"
#include "lte/utils/pack.h"
#include "lte/fec/crc.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 = (h->order - 8);
int i, j, ord=(crc_params->order-8);
unsigned long bit, crc; unsigned long bit, crc;
for (i=0; i<256; i++) { for (i = 0; i < 256; i++) {
crc = ((unsigned long)i)<<ord; crc = ((unsigned long) i) << ord;
for (j=0; j<8; j++) { for (j = 0; j < 8; j++) {
bit = crc & crc_params->crchighbit; bit = crc & h->crchighbit;
crc<<= 1; crc <<= 1;
if (bit) crc^= crc_params->polynom; if (bit)
crc ^= h->polynom;
} }
crc_params->table[i]=crc & crc_params->crcmask; h->table[i] = crc & h->crcmask;
} }
} }
unsigned long crctable(crc_t *h) {
unsigned long crctable (unsigned long length, crc_t *crc_params) {
// Polynom order 8, 16, 24 or 32 only. // Polynom order 8, 16, 24 or 32 only.
int ord=crc_params->order-8; int ord = h->order - 8;
unsigned long crc = crc_params->crcinit; unsigned long crc = h->crcinit;
unsigned char* data = crc_params->data0; unsigned char byte = h->byte;
while (length--){ crc = (crc << 8) ^ h->table[((crc >> (ord)) & 0xff) ^ byte];
crc = (crc << 8) ^ crc_params->table[ ((crc >> (ord)) & 0xff) ^ *data++]; h->crcinit = crc;
} return (crc & h->crcmask);
return((crc ^ crc_params->crcxor) & crc_params->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++){ for (m = 0; m < nbits; m++) {
if((rmask & crc) == 0x01 )crc = (crc ^ crc_params->polynom)>>1; if ((rmask & crc) == 0x01)
else crc = crc >> 1; 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 // Compute bit masks for whole CRC and CRC high bit
crc_par->crcmask = ((((unsigned long)1<<(crc_par->order-1))-1)<<1)|1; h->crcmask = ((((unsigned long) 1 << (h->order - 1)) - 1) << 1)
crc_par->crchighbit = (unsigned long)1<<(crc_par->order-1); | 1;
h->crchighbit = (unsigned long) 1 << (h->order - 1);
printf("crcmask=%x, crchightbit=%x\n",
(unsigned int)crc_par->crcmask, (unsigned int)crc_par->crchighbit);
// check parameters // check parameters
if (crc_par->order%8 != 0) { if (h->order % 8 != 0) {
printf("ERROR, invalid order=%d, it must be 8, 16, 24 or 32.\n", crc_par->order); fprintf(stderr, "ERROR, invalid order=%d, it must be 8, 16, 24 or 32.\n",
return(0); h->order);
return -1;
} }
if (crc_par->crcinit != (crc_par->crcinit & crc_par->crcmask)) { if (crc_set_init(h, h->crcinit)) {
printf("ERROR, invalid crcinit.\n"); fprintf(stderr, "Error setting CRC init word\n");
return(0); return -1;
}
if (crc_par->crcxor != (crc_par->crcxor & crc_par->crcmask)) {
printf("ERROR, invalid crcxor.\n");
return(0);
} }
// generate lookup table // generate lookup table
gen_crc_table(crc_par); gen_crc_table(h);
return(1); return 0;
} }
unsigned int crc_checksum(crc_t *h, char *data, int len) {
unsigned int crc_attach(char *bufptr, int len, crc_t *crc_params) { int i, k, len8, res8, a = 0;
unsigned int crc = 0;
int i, len8, res8, a;
unsigned int crc;
char *pter; char *pter;
#ifdef _WITHMALLOC crc_set_init(h, 0);
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 // Pack bits into bytes
memset((char *)(bufptr+len),0,(32)*sizeof(char)); len8 = (len >> 3);
res8 = (len - (len8 << 3));
for(i=0; i<len8+a; i++){ if (res8 > 0) {
pter=(char *)(bufptr+8*i); a = 1;
crc_params->data0[i]=(unsigned char)(unpack_bits(&pter, 8)&0xFF);
} }
// Calculate CRC // 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 // 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 value
return crc; 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; // Add CRC
char *ptr = &data[len];
unsigned int icrc1(unsigned int crc, unsigned short onech,int long_crc, pack_bits(checksum, &ptr, h->order);
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;
} }
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 <string.h>
#include <stdio.h> #include <stdio.h>
#include "lte/ratematching/rm_conv.h" #include "lte/fec/rm_conv.h"
#define NCOLS 32 #define NCOLS 32
#define NROWS_MAX NCOLS #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) { if (ndummy < 0) {
ndummy = 0; ndummy = 0;
} }
/* Sub-block interleaver 5.1.4.2.1 */
k=0; k=0;
for (s = 0; s < 3; s++) { for (s = 0; s < 3; s++) {
for (j = 0; j < NCOLS; j++) { 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; k = 0;
j = 0; j = 0;
while (k < out_len) { 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 # Turbo Coder TEST
######################################################################## ########################################################################

View File

@ -25,7 +25,6 @@
* *
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
@ -37,11 +36,10 @@
#include "lte.h" #include "lte.h"
#include "crc_test.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 crc_poly = 0x1864CFB;
unsigned int seed = 1; unsigned int seed = 1;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [nlps]\n", prog); printf("Usage: %s [nlps]\n", prog);
printf("\t-n num_bits [Default %d]\n", num_bits); printf("\t-n num_bits [Default %d]\n", num_bits);
@ -81,7 +79,7 @@ int main(int argc, char **argv) {
parse_args(argc, 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) { if (!data) {
perror("malloc"); perror("malloc");
exit(-1); exit(-1);
@ -93,30 +91,23 @@ int main(int argc, char **argv) {
srand(seed); srand(seed);
// Generate data // Generate data
for (i=0;i<num_bits;i++) { for (i = 0; i < num_bits; i++) {
data[i] = rand()%2; data[i] = rand() % 2;
} }
//Initialize CRC params and tables //Initialize CRC params and tables
crc_p.polynom=crc_poly; if (crc_init(&crc_p, crc_poly, crc_length)) {
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");
exit(-1); exit(-1);
} }
// generate CRC word
crc_word = crc_checksum(&crc_p, data, num_bits);
free(data); free(data);
// check if generated word is as expected // 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"); fprintf(stderr, "Test parameters not defined in test_results.h\n");
exit(-1); 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)) { if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) {
goto clean; goto clean;
} }
if (crc_init(&q->crc, LTE_CRC16, 16)) {
goto clean;
}
q->encoder.K = 7; q->encoder.K = 7;
q->encoder.R = 3; q->encoder.R = 3;
q->encoder.tail_biting = true; 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 * 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]; char data[40];
memcpy(data, bits, 40 * sizeof(char)); memcpy(data, bits, 40 * sizeof(char));
crc_set_mask(data, nof_ports); 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) { 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; c=1;
} }
if (!pbch_crc_check(q->data, nof_ports)) { if (!pbch_crc_check(q, q->data, nof_ports)) {
/* unpack MIB */ /* unpack MIB */
pbch_mib_unpack(q->data, 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); pbch_mib_pack(mib, q->data);
/* encode & modulate */ /* encode & modulate */
crc(0, q->data, 24, 16, 0x11021, 1); crc_attach(&q->crc, q->data, 24);
crc_set_mask(q->data, nof_ports); crc_set_mask(q->data, nof_ports);
convcoder_encode(&q->encoder, q->data, q->data_enc, 40); 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)) { if (modem_table_std(&q->mod, LTE_QPSK, true)) {
goto clean; goto clean;
} }
if (crc_init(&q->crc, LTE_CRC16, 16)) {
goto clean;
}
demod_soft_init(&q->demod); demod_soft_init(&q->demod);
demod_soft_table_set(&q->demod, &q->mod); 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 * 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) { int nof_bits) {
float tmp[3 * (DCI_MAX_BITS + 16)]; 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 decoder */
viterbi_decode_f(decoder, tmp, data, nof_bits + 16); viterbi_decode_f(&q->decoder, tmp, data, nof_bits + 16);
if (VERBOSE_ISDEBUG()) { if (VERBOSE_ISDEBUG()) {
bit_fprint(stdout, data, nof_bits+16); 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]; x = &data[nof_bits];
p_bits = (unsigned short) bit_unpack(&x, 16); p_bits = (unsigned short) bit_unpack(&x, 16);
crc_res = ((unsigned short) crc(0, data, nof_bits, 16, LTE_CRC16, 0) crc_res = ((unsigned short) crc_checksum(&q->crc, data, nof_bits) & 0xffff);
& 0xffff);
DEBUG("p_bits: 0x%x, crc_res: 0x%x, tot: 0x%x\n", p_bits, crc_res, p_bits ^ crc_res); 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); 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", 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->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L,
c->rnti); 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); PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits);
if (c->rnti == crc_res) { 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 /** 36.212 5.3.3.2 to 5.3.3.4
* TODO: UE transmit antenna selection CRC mask * 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; convcoder_t encoder;
char tmp[3 * (DCI_MAX_BITS + 16)]; 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; encoder.tail_biting = true;
memcpy(encoder.poly, poly, 3 * sizeof(int)); 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); crc_set_mask_rnti(&data[nof_bits], rnti);
convcoder_encode(&encoder, data, tmp, nof_bits + 16); 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), 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->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.nof_bits, PDCCH_FORMAT_NOF_BITS(dci->msg[i].location.L),
dci->msg[i].location.rnti); 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)