Improved PDCCH candidate search interface. Switched FEC modules to uint32_t

master
ismagom 11 years ago
parent 5181b771fd
commit 0ebb0e7d00

@ -229,7 +229,8 @@ int main(int argc, char **argv) {
int i, n; int i, n;
char *data; char *data;
cf_t *sf_symbols[MAX_PORTS]; cf_t *sf_symbols[MAX_PORTS];
dci_t dci_tx; dci_msg_t dci_msg;
dci_location_t locations[NSUBFRAMES_X_FRAME][10];
#ifdef DISABLE_UHD #ifdef DISABLE_UHD
if (argc < 3) { if (argc < 3) {
@ -279,7 +280,6 @@ int main(int argc, char **argv) {
} }
#endif #endif
dci_init(&dci_tx, 1);
bzero(&ra_dl, sizeof(ra_pdsch_t)); bzero(&ra_dl, sizeof(ra_pdsch_t));
ra_dl.harq_process = 0; ra_dl.harq_process = 0;
ra_pdsch_set_mcs(&ra_dl, QPSK, 5); ra_pdsch_set_mcs(&ra_dl, QPSK, 5);
@ -288,10 +288,7 @@ int main(int argc, char **argv) {
ra_dl.alloc_type = alloc_type0; ra_dl.alloc_type = alloc_type0;
ra_dl.type0_alloc.rbg_bitmask = 0xffffffff; ra_dl.type0_alloc.rbg_bitmask = 0xffffffff;
dci_msg_pack_pdsch(&ra_dl, &dci_tx.msg[0], Format1, cell.nof_prb, false); dci_msg_pack_pdsch(&ra_dl, &dci_msg, Format1, cell.nof_prb, false);
dci_tx.nof_dcis++;
pdcch_init_search_ue(&pdcch, 1234, cfi);
ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb); ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb);
ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM); ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM);
@ -299,6 +296,11 @@ int main(int argc, char **argv) {
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
/* Initiate valid DCI locations */
for (i=0;i<NSUBFRAMES_X_FRAME;i++) {
pdcch_ue_locations(&pdcch, locations[i], 10, i, cfi, 1234);
}
data = malloc(sizeof(char) * ra_dl.mcs.tbs); data = malloc(sizeof(char) * ra_dl.mcs.tbs);
if (!data) { if (!data) {
perror("malloc"); perror("malloc");
@ -331,11 +333,14 @@ int main(int argc, char **argv) {
for (i=0;i<ra_dl.mcs.tbs;i++) { for (i=0;i<ra_dl.mcs.tbs;i++) {
data[i] = rand()%2; data[i] = rand()%2;
} }
dci_msg_candidate_set(&dci_tx.msg[0], pdcch.search_mode[2].candidates[0][sf_idx].L,
pdcch.search_mode[2].candidates[0][sf_idx].ncce, 1234); if (pdcch_encode_msg(&pdcch, &dci_msg, locations[sf_idx][0], 1234)) {
INFO("Setting DCI candidate L: %d nCCE: %d\n", pdcch.search_mode[2].candidates[0][sf_idx].L, fprintf(stderr, "Error encoding DCI message\n");
pdcch.search_mode[2].candidates[0][sf_idx].ncce); exit(-1);
pdcch_encode(&pdcch, &dci_tx, sf_symbols, sf_idx, cfi); }
pdcch_gen_symbols(&pdcch, sf_symbols, sf_idx, cfi);
pdsch_encode(&pdsch, data, sf_symbols, sf_idx, ra_dl.mcs, &prb_alloc); pdsch_encode(&pdsch, data, sf_symbols, sf_idx, ra_dl.mcs, &prb_alloc);
/* Transform to OFDM symbols */ /* Transform to OFDM symbols */

@ -88,7 +88,6 @@ float *tmp_plot;
pbch_t pbch; pbch_t pbch;
pcfich_t pcfich; pcfich_t pcfich;
pdcch_t pdcch; pdcch_t pdcch;
dci_t dci_set;
pdsch_t pdsch; pdsch_t pdsch;
regs_t regs; regs_t regs;
lte_fft_t fft; lte_fft_t fft;
@ -286,8 +285,6 @@ int base_init(int nof_prb) {
return -1; return -1;
} }
dci_init(&dci_set, 10);
return 0; return 0;
} }
@ -401,6 +398,9 @@ int rx_run(cf_t *input, int sf_idx) {
cf_t *input_decim; cf_t *input_decim;
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
ra_prb_t prb_alloc; ra_prb_t prb_alloc;
dci_location_t locations[10];
dci_msg_t dci_msg;
uint32_t nof_locations;
/* Downsample if the signal bandwith is shorter */ /* Downsample if the signal bandwith is shorter */
if (sampling_nof_prb > cell.nof_prb) { if (sampling_nof_prb > cell.nof_prb) {
@ -427,25 +427,32 @@ int rx_run(cf_t *input, int sf_idx) {
return -1; return -1;
} }
pdcch_init_search_ue(&pdcch, 1234, cfi); /* Search only UE-specific locations */
nof_locations = pdcch_ue_locations(&pdcch, locations, 10, sf_idx, cfi, 1234);
pdcch_extract_llr(&pdcch, fft_buffer, ce, nof_frames, cfi);
nof_dcis = pdcch_decode_msg(&pdcch, &dci_msg, locations, nof_locations, Format1, 1234);
if (nof_dcis < 0) {
fprintf(stderr, "Error decoding DCI messages\n");
return -1;
}
INFO("Received %d DCI messages\n", nof_dcis);
dci_set.nof_dcis = 0; if (nof_dcis == 1) {
nof_dcis = pdcch_decode(&pdcch, fft_buffer, ce, &dci_set, sf_idx, cfi);
INFO("Received %d DCIs\n", nof_dcis);
for (i=0;i<nof_dcis;i++) {
dci_msg_type_t type; dci_msg_type_t type;
if (dci_msg_get_type(&dci_set.msg[i], &type, cell.nof_prb, 1234)) { if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, 1234, 1234)) {
fprintf(stderr, "Can't get DCI message type\n"); fprintf(stderr, "Can't get DCI message type\n");
} else { } else {
INFO("MSG %d: L: %d nCCE: %d Nbits: %d. ",i,dci_set.msg[i].location.L,
dci_set.msg[i].location.ncce, dci_set.msg[i].location.nof_bits);
if (VERBOSE_ISINFO()) { if (VERBOSE_ISINFO()) {
dci_msg_type_fprint(stdout, type); dci_msg_type_fprint(stdout, type);
} }
switch(type.type) { switch(type.type) {
case PDSCH_SCHED: case PDSCH_SCHED:
bzero(&ra_dl, sizeof(ra_pdsch_t)); bzero(&ra_dl, sizeof(ra_pdsch_t));
if (dci_msg_unpack_pdsch(&dci_set.msg[i], &ra_dl, cell.nof_prb, if (dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb,
false)) { false)) {
fprintf(stderr, "Can't unpack PDSCH message\n"); fprintf(stderr, "Can't unpack PDSCH message\n");
break; break;

@ -34,13 +34,13 @@
#include "liblte/config.h" #include "liblte/config.h"
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
int R; uint32_t R;
int K; uint32_t K;
int poly[3]; uint32_t poly[3];
bool tail_biting; bool tail_biting;
}convcoder_t; }convcoder_t;
LIBLTE_API int convcoder_encode(convcoder_t *q, char *input, char *output, int frame_length); LIBLTE_API int convcoder_encode(convcoder_t *q, char *input, char *output, uint32_t frame_length);
/* High-level API */ /* High-level API */

@ -33,8 +33,15 @@
#define RX_NULL 10000 #define RX_NULL 10000
#define TX_NULL 80 #define TX_NULL 80
LIBLTE_API int rm_conv_tx(char *input, int in_len, char *output, int out_len); LIBLTE_API int rm_conv_tx(char *input,
LIBLTE_API int rm_conv_rx(float *input, int in_len, float *output, int out_len); uint32_t in_len,
char *output,
uint32_t out_len);
LIBLTE_API int rm_conv_rx(float *input,
uint32_t in_len,
float *output,
uint32_t out_len);
/* High-level API */ /* High-level API */
typedef struct typedef struct

@ -45,12 +45,24 @@ typedef struct LIBLTE_API {
char *buffer; char *buffer;
} rm_turbo_t; } rm_turbo_t;
LIBLTE_API int rm_turbo_init(rm_turbo_t *q, int max_codeblock_len); LIBLTE_API int rm_turbo_init(rm_turbo_t *q,
uint32_t max_codeblock_len);
LIBLTE_API void rm_turbo_free(rm_turbo_t *q); LIBLTE_API void rm_turbo_free(rm_turbo_t *q);
LIBLTE_API int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output,
int out_len, int rv_idx); LIBLTE_API int rm_turbo_tx(rm_turbo_t *q,
LIBLTE_API int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, char *input,
float *output, int out_len, int rv_idx); uint32_t in_len,
char *output,
uint32_t out_len,
uint32_t rv_idx);
LIBLTE_API int rm_turbo_rx(rm_turbo_t *q,
float *input,
uint32_t in_len,
float *output,
uint32_t out_len,
uint32_t rv_idx);
/* High-level API */ /* High-level API */
typedef struct LIBLTE_API { typedef struct LIBLTE_API {

@ -31,15 +31,15 @@
#include "liblte/config.h" #include "liblte/config.h"
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
int *forward; uint32_t *forward;
int *reverse; uint32_t *reverse;
int max_long_cb; uint32_t max_long_cb;
} tc_interl_t; } tc_interl_t;
LIBLTE_API int tc_interl_LTE_gen(tc_interl_t *h, int long_cb); LIBLTE_API int tc_interl_LTE_gen(tc_interl_t *h, uint32_t long_cb);
LIBLTE_API int tc_interl_UMTS_gen(tc_interl_t *h, int long_cb); LIBLTE_API int tc_interl_UMTS_gen(tc_interl_t *h, uint32_t long_cb);
LIBLTE_API int tc_interl_init(tc_interl_t *h, int max_long_cb); LIBLTE_API int tc_interl_init(tc_interl_t *h, uint32_t max_long_cb);
LIBLTE_API void tc_interl_free(tc_interl_t *h); LIBLTE_API void tc_interl_free(tc_interl_t *h);
#endif #endif

@ -37,13 +37,13 @@
#define TOTALTAIL 12 #define TOTALTAIL 12
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
int max_long_cb; uint32_t max_long_cb;
tc_interl_t interl; tc_interl_t interl;
} tcod_t; } tcod_t;
LIBLTE_API int tcod_init(tcod_t *h, int max_long_cb); LIBLTE_API int tcod_init(tcod_t *h, uint32_t max_long_cb);
LIBLTE_API void tcod_free(tcod_t *h); LIBLTE_API void tcod_free(tcod_t *h);
LIBLTE_API int tcod_encode(tcod_t *h, char *input, char *output, int long_cb); LIBLTE_API int tcod_encode(tcod_t *h, char *input, char *output, uint32_t long_cb);
#endif #endif

@ -68,13 +68,25 @@ typedef struct LIBLTE_API {
tc_interl_t interleaver; tc_interl_t interleaver;
} tdec_t; } tdec_t;
LIBLTE_API int tdec_init(tdec_t *h, int max_long_cb); LIBLTE_API int tdec_init(tdec_t * h,
LIBLTE_API void tdec_free(tdec_t *h); uint32_t max_long_cb);
LIBLTE_API int tdec_reset(tdec_t *h, int long_cb); LIBLTE_API void tdec_free(tdec_t * h);
LIBLTE_API void tdec_iteration(tdec_t *h, llr_t *input, int long_cb);
LIBLTE_API void tdec_decision(tdec_t *h, char *output, int long_cb); LIBLTE_API int tdec_reset(tdec_t * h, uint32_t long_cb);
LIBLTE_API void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations,
int long_cb); LIBLTE_API void tdec_iteration(tdec_t * h,
llr_t * input,
uint32_t long_cb);
LIBLTE_API void tdec_decision(tdec_t * h,
char *output,
uint32_t long_cb);
LIBLTE_API void tdec_run_all(tdec_t * h,
llr_t * input,
char *output,
uint32_t nof_iterations,
uint32_t long_cb);
#endif #endif

@ -38,21 +38,34 @@ typedef enum {
typedef struct LIBLTE_API{ typedef struct LIBLTE_API{
void *ptr; void *ptr;
int R; uint32_t R;
int K; uint32_t K;
unsigned int framebits; unsigned int framebits;
bool tail_biting; bool tail_biting;
int poly[3]; uint32_t poly[3];
int (*decode) (void*, unsigned char*, char*, int); int (*decode) (void*, uint8_t*, char*, uint32_t);
void (*free) (void*); void (*free) (void*);
unsigned char *tmp; unsigned char *tmp;
unsigned char *symbols_uc; unsigned char *symbols_uc;
}viterbi_t; }viterbi_t;
LIBLTE_API int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int max_frame_length, bool tail_bitting); LIBLTE_API int viterbi_init(viterbi_t *q,
viterbi_type_t type,
uint32_t poly[3],
uint32_t max_frame_length,
bool tail_bitting);
LIBLTE_API void viterbi_free(viterbi_t *q); LIBLTE_API void viterbi_free(viterbi_t *q);
LIBLTE_API int viterbi_decode_f(viterbi_t *q, float *symbols, char *data, int frame_length);
LIBLTE_API int viterbi_decode_uc(viterbi_t *q, unsigned char *symbols, char *data, int frame_length); LIBLTE_API int viterbi_decode_f(viterbi_t *q,
float *symbols,
char *data,
uint32_t frame_length);
LIBLTE_API int viterbi_decode_uc(viterbi_t *q,
uint8_t *symbols,
char *data,
uint32_t frame_length);
/* High-level API */ /* High-level API */

@ -62,41 +62,26 @@ typedef enum {
} dci_spec_t; } dci_spec_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
uint32_t nof_bits; uint32_t L; // Aggregation level
uint32_t L; // Aggregation level
uint32_t ncce; // Position of first CCE of the dci uint32_t ncce; // Position of first CCE of the dci
uint16_t rnti; } dci_location_t;
} dci_candidate_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
char data[DCI_MAX_BITS]; char data[DCI_MAX_BITS];
dci_candidate_t location; uint32_t nof_bits;
} dci_msg_t; } dci_msg_t;
typedef struct LIBLTE_API {
dci_msg_t *msg;
uint32_t nof_dcis;
uint32_t max_dcis;
} dci_t;
LIBLTE_API int dci_init(dci_t *q,
uint32_t max_dci);
LIBLTE_API void dci_free(dci_t *q);
LIBLTE_API char* dci_format_string(dci_format_t format); LIBLTE_API char* dci_format_string(dci_format_t format);
LIBLTE_API int dci_msg_candidate_set(dci_msg_t *msg, LIBLTE_API int dci_location_set(dci_location_t *c,
uint32_t L, uint32_t L,
uint32_t nCCE, uint32_t nCCE);
uint16_t rnti);
LIBLTE_API void dci_candidate_fprint(FILE *f,
dci_candidate_t *q);
LIBLTE_API int dci_msg_get_type(dci_msg_t *msg, LIBLTE_API int dci_msg_get_type(dci_msg_t *msg,
dci_msg_type_t *type, dci_msg_type_t *type,
uint32_t nof_prb, uint32_t nof_prb,
uint16_t msg_rnti,
uint16_t crnti); uint16_t crnti);
LIBLTE_API void dci_msg_type_fprint(FILE *f, LIBLTE_API void dci_msg_type_fprint(FILE *f,

@ -44,21 +44,17 @@
typedef _Complex float cf_t; typedef _Complex float cf_t;
#define PDCCH_NOF_SEARCH_MODES 3 #define NOF_COMMON_FORMATS 2
#define MAX_CANDIDATES 32 const dci_format_t common_formats[NOF_COMMON_FORMATS] = { Format1A, Format1C };
#define NOF_UE_FORMATS 2
const dci_format_t ue_formats[NOF_UE_FORMATS] = { Format0, Format1 }; // 1A has the same payload as 0
typedef enum LIBLTE_API { typedef enum LIBLTE_API {
SEARCH_NONE = 3, SEARCH_SI = 0, SEARCH_RA = 1, SEARCH_UE = 2 SEARCH_UE, SEARCH_COMMON
} pdcch_search_mode_t; } pdcch_search_mode_t;
/*
* A search mode is indicated by higher layers to look for SI/C/RA-RNTI
* DCI messages as defined in Section 7.1 of 36.213
*/
typedef struct LIBLTE_API {
uint32_t nof_candidates;
dci_candidate_t candidates[NSUBFRAMES_X_FRAME][MAX_CANDIDATES];
} pdcch_search_t;
/* PDCCH object */ /* PDCCH object */
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
@ -69,9 +65,6 @@ typedef struct LIBLTE_API {
uint32_t nof_cce; uint32_t nof_cce;
uint32_t max_bits; uint32_t max_bits;
pdcch_search_t search_mode[PDCCH_NOF_SEARCH_MODES];
pdcch_search_mode_t current_search_mode;
regs_t *regs; regs_t *regs;
/* buffers */ /* buffers */
@ -97,62 +90,47 @@ LIBLTE_API int pdcch_init(pdcch_t *q,
LIBLTE_API void pdcch_free(pdcch_t *q); LIBLTE_API void pdcch_free(pdcch_t *q);
/* Encoding functions */ /* Encoding function */
LIBLTE_API int pdcch_encode(pdcch_t *q, LIBLTE_API void pdcch_reset(pdcch_t *q);
dci_t *dci,
cf_t *slot_symbols[MAX_PORTS],
uint32_t nsubframe,
uint32_t cfi);
/* Decoding functions */ LIBLTE_API int pdcch_encode_msg(pdcch_t *q,
dci_msg_t *msg,
dci_location_t location,
uint16_t rnti);
/* There are two ways to decode the DCI messages: LIBLTE_API int pdcch_gen_symbols(pdcch_t *q,
* a) call pdcch_set_search_si/ue/ra and then call pdcch_decode() cf_t *sf_symbols[MAX_PORTS],
* b) call pdcch_extract_llr() and then call pdcch_decode_si/ue/ra uint32_t nsubframe,
*/ uint32_t cfi);
LIBLTE_API int pdcch_decode(pdcch_t *q,
cf_t *slot_symbols,
cf_t *ce[MAX_PORTS],
dci_t *dci,
uint32_t nsubframe,
uint32_t cfi);
/* Decoding functions: Extract the LLRs and save them in the pdcch_t object */
LIBLTE_API int pdcch_extract_llr(pdcch_t *q, LIBLTE_API int pdcch_extract_llr(pdcch_t *q,
cf_t *slot_symbols, cf_t *sf_symbols,
cf_t *ce[MAX_PORTS], cf_t *ce[MAX_PORTS],
float *llr,
uint32_t nsubframe, uint32_t nsubframe,
uint32_t cfi); uint32_t cfi);
LIBLTE_API int pdcch_init_search_si(pdcch_t *q, /* Decoding functions: Try to decode a DCI message after calling pdcch_extract_llr */
uint32_t cfi); LIBLTE_API int pdcch_decode_msg(pdcch_t *q,
dci_msg_t *msg,
LIBLTE_API void pdcch_set_search_si(pdcch_t *q); dci_location_t *locations,
uint32_t nof_locations,
LIBLTE_API int pdcch_decode_si(pdcch_t *q, dci_format_t format,
float *llr, uint16_t rnti);
dci_t *dci);
/* Function for generation of UE-specific search space DCI locations */
LIBLTE_API int pdcch_init_search_ue(pdcch_t *q, LIBLTE_API uint32_t pdcch_ue_locations(pdcch_t *q,
uint16_t c_rnti, dci_location_t *locations,
uint32_t cfi); uint32_t max_locations,
uint32_t nsubframe,
LIBLTE_API void pdcch_set_search_ue(pdcch_t *q); uint32_t cfi,
uint16_t rnti);
LIBLTE_API int pdcch_decode_ue(pdcch_t *q,
float *llr, /* Function for generation of common search space DCI locations */
dci_t *dci, LIBLTE_API uint32_t pdcch_common_locations(pdcch_t *q,
uint32_t nsubframe); dci_location_t *locations,
uint32_t max_locations,
LIBLTE_API int pdcch_init_search_ra(pdcch_t *q, uint32_t cfi);
uint16_t ra_rnti,
uint32_t cfi);
LIBLTE_API void pdcch_set_search_ra(pdcch_t *q);
LIBLTE_API int pdcch_decode_ra(pdcch_t *q,
float *llr,
dci_t *dci);
#endif #endif

@ -28,15 +28,16 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <math.h> #include <math.h>
#include "liblte/phy/fec/convcoder.h" #include "liblte/phy/fec/convcoder.h"
#include "parity.h" #include "parity.h"
int convcoder_encode(convcoder_t *q, char *input, char *output, int frame_length) { int convcoder_encode(convcoder_t *q, char *input, char *output, uint32_t frame_length) {
unsigned int sr; uint32_t sr;
int i,j; uint32_t i,j;
int len = q->tail_biting ? frame_length : (frame_length + q->K - 1); uint32_t len = q->tail_biting ? frame_length : (frame_length + q->K - 1);
if (q->tail_biting) { if (q->tail_biting) {
sr = 0; sr = 0;

@ -4,26 +4,27 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
unsigned char Partab[256]; uint8_t Partab[256];
int P_init; uint32_t P_init;
/* Create 256-entry odd-parity lookup table /* Create 256-entry odd-parity lookup table
* Needed only on non-ia32 machines * Needed only on non-ia32 machines
*/ */
void partab_init(void) { void partab_init(void) {
int i, cnt, ti; uint32_t i, cnt, ti;
/* Initialize parity lookup table */ /* Initialize parity lookup table */
for (i = 0; i < 256; i++) { for (i = 0; i < 256; i++) {
cnt = 0; cnt = 0;
ti = i; ti = i;
while (ti) { while (ti) {
if (ti & 1) if (ti & 1)
cnt++; cnt++;
ti >>= 1; ti >>= 1;
} }
Partab[i] = cnt & 1; Partab[i] = cnt & 1;
} }
P_init = 1; P_init = 1;
} }

@ -10,16 +10,16 @@
/* Determine parity of argument: 1 = odd, 0 = even */ /* Determine parity of argument: 1 = odd, 0 = even */
#ifdef __i386__ #ifdef __i386__
static inline int parityb(unsigned char x){ static inline uint32_t parityb(uint8_t x){
__asm__ __volatile__ ("test %1,%1;setpo %0" : "=qhm" (x) : "qh" (x)); __asm__ __volatile__ ("test %1,%1;setpo %0" : "=qhm" (x) : "qh" (x));
return x; return x;
} }
#else #else
void partab_init(); void partab_init();
static inline int parityb(unsigned char x){ static inline uint32_t parityb(uint8_t x){
extern unsigned char Partab[256]; extern uint8_t Partab[256];
extern int P_init; extern uint32_t P_init;
if(!P_init){ if(!P_init){
partab_init(); partab_init();
} }
@ -28,7 +28,7 @@ static inline int parityb(unsigned char x){
#endif #endif
static inline int parity(int x){ static inline uint32_t parity(int x){
/* Fold down to one byte */ /* Fold down to one byte */
x ^= (x >> 16); x ^= (x >> 16);
x ^= (x >> 8); x ^= (x >> 8);

@ -27,25 +27,27 @@
#include <string.h> #include <string.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include "liblte/phy/fec/rm_conv.h" #include "liblte/phy/fec/rm_conv.h"
#define NCOLS 32 #define NCOLS 32
#define NROWS_MAX NCOLS #define NROWS_MAX NCOLS
unsigned char RM_PERM_CC[NCOLS] = { 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, uint8_t RM_PERM_CC[NCOLS] = { 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27,
7, 23, 15, 31, 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30 }; 7, 23, 15, 31, 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, 6, 22, 14, 30 };
unsigned char RM_PERM_CC_INV[NCOLS] = uint8_t 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, { 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 }; 21, 5, 29, 13, 19, 3, 27, 11, 23, 7, 31, 15 };
int rm_conv_tx(char *input, int in_len, char *output, int out_len) { int rm_conv_tx(char *input, uint32_t in_len, char *output, uint32_t out_len) {
char tmp[3 * NCOLS * NROWS_MAX]; char tmp[3 * NCOLS * NROWS_MAX];
int nrows, ndummy, K_p; int nrows, ndummy, K_p;
int i, j, k, s; int i, j, k, s;
nrows = (int) (in_len / 3 - 1) / NCOLS + 1; nrows = (uint32_t) (in_len / 3 - 1) / NCOLS + 1;
if (nrows > NROWS_MAX) { if (nrows > NROWS_MAX) {
fprintf(stderr, "Input too large. Max input length is %d\n", fprintf(stderr, "Input too large. Max input length is %d\n",
3 * NCOLS * NROWS_MAX); 3 * NCOLS * NROWS_MAX);
@ -89,7 +91,7 @@ int rm_conv_tx(char *input, int in_len, char *output, int out_len) {
/* Undoes Convolutional Code Rate Matching. /* Undoes Convolutional Code Rate Matching.
* 3GPP TS 36.212 v10.1.0 section 5.1.4.2 * 3GPP TS 36.212 v10.1.0 section 5.1.4.2
*/ */
int rm_conv_rx(float *input, int in_len, float *output, int out_len) { int rm_conv_rx(float *input, uint32_t in_len, float *output, uint32_t out_len) {
int nrows, ndummy, K_p; int nrows, ndummy, K_p;
int i, j, k; int i, j, k;
@ -97,7 +99,7 @@ int rm_conv_rx(float *input, int in_len, float *output, int out_len) {
float tmp[3 * NCOLS * NROWS_MAX]; float tmp[3 * NCOLS * NROWS_MAX];
nrows = (int) (out_len / 3 - 1) / NCOLS + 1; nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1;
if (nrows > NROWS_MAX) { if (nrows > NROWS_MAX) {
fprintf(stderr, "Output too large. Max output length is %d\n", fprintf(stderr, "Output too large. Max output length is %d\n",
3 * NCOLS * NROWS_MAX); 3 * NCOLS * NROWS_MAX);

@ -30,16 +30,17 @@
#include <math.h> #include <math.h>
#include <stdbool.h> #include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include "liblte/phy/fec/rm_turbo.h" #include "liblte/phy/fec/rm_turbo.h"
#define NCOLS 32 #define NCOLS 32
#define NROWS_MAX NCOLS #define NROWS_MAX NCOLS
unsigned char RM_PERM_TC[NCOLS] = { 0, 16, 8, 24, 4, 20, 12, 28, 2, 18, 10, 26, uint8_t RM_PERM_TC[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 }; 6, 22, 14, 30, 1, 17, 9, 25, 5, 21, 13, 29, 3, 19, 11, 27, 7, 23, 15, 31 };
int rm_turbo_init(rm_turbo_t *q, int buffer_len) { int rm_turbo_init(rm_turbo_t *q, uint32_t buffer_len) {
q->buffer_len = buffer_len; q->buffer_len = buffer_len;
q->buffer = malloc(buffer_len * sizeof(float)); q->buffer = malloc(buffer_len * sizeof(float));
if (!q->buffer) { if (!q->buffer) {
@ -60,15 +61,16 @@ void rm_turbo_free(rm_turbo_t *q) {
* *
* TODO: Soft buffer size limitation according to UE category * TODO: Soft buffer size limitation according to UE category
*/ */
int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output, int rm_turbo_tx(rm_turbo_t *q, char *input, uint32_t in_len, char *output,
int out_len, int rv_idx) { uint32_t out_len, uint32_t rv_idx) {
char *tmp = (char*) q->buffer; char *tmp = (char*) q->buffer;
int nrows, ndummy, K_p; int ndummy, kidx;
int nrows, K_p;
int i, j, k, s, kidx, N_cb, k0; int i, j, k, s, N_cb, k0;
nrows = (int) (in_len / 3 - 1) / NCOLS + 1; nrows = (uint32_t) (in_len / 3 - 1) / NCOLS + 1;
K_p = nrows * NCOLS; K_p = nrows * NCOLS;
if (3 * K_p > q->buffer_len) { if (3 * K_p > q->buffer_len) {
fprintf(stderr, fprintf(stderr,
@ -113,10 +115,10 @@ int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output,
} }
/* Bit selection and transmission 5.1.4.1.2 */ /* Bit selection and transmission 5.1.4.1.2 */
N_cb = 3 * K_p; // TODO: Soft buffer size limitation N_cb = 3 * K_p; // TODO: Soft buffer size limitation
k0 = nrows k0 = nrows
* (2 * (int) ceilf((float) N_cb / (float) (8 * nrows)) * rv_idx + 2); * (2 * (uint32_t) ceilf((float) N_cb / (float) (8 * nrows)) * rv_idx + 2);
k = 0; k = 0;
j = 0; j = 0;
@ -133,8 +135,8 @@ int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output,
/* Undoes Turbo Code Rate Matching. /* Undoes Turbo Code Rate Matching.
* 3GPP TS 36.212 v10.1.0 section 5.1.4.1 * 3GPP TS 36.212 v10.1.0 section 5.1.4.1
*/ */
int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output, int rm_turbo_rx(rm_turbo_t *q, float *input, uint32_t in_len, float *output,
int out_len, int rv_idx) { uint32_t out_len, uint32_t rv_idx) {
int nrows, ndummy, K_p, k0, N_cb, jp, kidx; int nrows, ndummy, K_p, k0, N_cb, jp, kidx;
int i, j, k; int i, j, k;
@ -143,7 +145,7 @@ int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output,
float *tmp = (float*) q->buffer; float *tmp = (float*) q->buffer;
nrows = (int) (out_len / 3 - 1) / NCOLS + 1; nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1;
K_p = nrows * NCOLS; K_p = nrows * NCOLS;
if (3 * K_p > q->buffer_len) { if (3 * K_p > q->buffer_len) {
fprintf(stderr, fprintf(stderr,
@ -164,7 +166,7 @@ int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output,
/* Undo bit collection. Account for dummy bits */ /* Undo bit collection. Account for dummy bits */
N_cb = 3 * K_p; // TODO: Soft buffer size limitation N_cb = 3 * K_p; // TODO: Soft buffer size limitation
k0 = nrows k0 = nrows
* (2 * (int) ceilf((float) N_cb / (float) (8 * nrows)) * rv_idx + 2); * (2 * (uint32_t) ceilf((float) N_cb / (float) (8 * nrows)) * rv_idx + 2);
k = 0; k = 0;
j = 0; j = 0;
@ -185,7 +187,7 @@ int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output,
isdummy = true; isdummy = true;
} }
} else { } else {
int jpp = (jp - K_p - 1) / 2; uint32_t jpp = (jp - K_p - 1) / 2;
kidx = (RM_PERM_TC[jpp / nrows] + NCOLS * (jpp % nrows) + 1) % K_p; kidx = (RM_PERM_TC[jpp / nrows] + NCOLS * (jpp % nrows) + 1) % K_p;
if ((kidx - ndummy) < 0) { if ((kidx - ndummy) < 0) {
isdummy = true; isdummy = true;

@ -27,6 +27,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include "liblte/phy/common/phy_common.h" #include "liblte/phy/common/phy_common.h"
#include "liblte/phy/fec/tc_interl.h" #include "liblte/phy/fec/tc_interl.h"
@ -39,7 +40,7 @@
* *
************************************************/ ************************************************/
const int f1_list[NOF_TC_CB_SIZES] = { 3, 7, 19, 7, 7, 11, 5, 11, 7, 41, 103, const uint32_t 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, 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, 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, 25, 51, 47, 91, 29, 29, 247, 29, 89, 91, 157, 55, 31, 17, 35, 227, 65, 19,
@ -52,7 +53,7 @@ const int f1_list[NOF_TC_CB_SIZES] = { 3, 7, 19, 7, 7, 11, 5, 11, 7, 41, 103,
39, 127, 39, 39, 31, 113, 41, 251, 43, 21, 43, 45, 45, 161, 89, 323, 47, 23, 39, 127, 39, 39, 31, 113, 41, 251, 43, 21, 43, 45, 45, 161, 89, 323, 47, 23,
47, 263 }; 47, 263 };
const int f2_list[NOF_TC_CB_SIZES] = { 10, 12, 42, 16, 18, 20, 22, 24, 26, 84, const uint32_t 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, 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, 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, 102, 52, 106, 72, 110, 168, 114, 58, 118, 180, 122, 62, 84, 64, 66, 68, 420,
@ -65,9 +66,9 @@ const int f2_list[NOF_TC_CB_SIZES] = { 10, 12, 42, 16, 18, 20, 22, 24, 26, 84,
280, 142, 480, 146, 444, 120, 152, 462, 234, 158, 80, 96, 902, 166, 336, 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 }; 170, 86, 174, 176, 178, 120, 182, 184, 186, 94, 190, 480 };
int tc_interl_LTE_gen(tc_interl_t *h, int long_cb) { int tc_interl_LTE_gen(tc_interl_t *h, uint32_t long_cb) {
int cb_table_idx, f1, f2; uint32_t cb_table_idx, f1, f2;
unsigned long long i, j; uint64_t i, j;
if (long_cb > h->max_long_cb) { if (long_cb > h->max_long_cb) {
fprintf(stderr, "Interleaver initiated for max_long_cb=%d\n", fprintf(stderr, "Interleaver initiated for max_long_cb=%d\n",
@ -90,8 +91,8 @@ int tc_interl_LTE_gen(tc_interl_t *h, int long_cb) {
h->reverse[0] = 0; h->reverse[0] = 0;
for (i = 1; i < long_cb; i++) { for (i = 1; i < long_cb; i++) {
j = (f1 * i + f2 * i * i) % (long_cb); j = (f1 * i + f2 * i * i) % (long_cb);
h->forward[i] = j; h->forward[i] = (uint32_t) j;
h->reverse[j] = i; h->reverse[j] = (uint32_t) i;
} }
return 0; return 0;

@ -28,13 +28,14 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <strings.h> #include <strings.h>
#include <stdint.h>
#include "liblte/phy/fec/tc_interl.h" #include "liblte/phy/fec/tc_interl.h"
#include "liblte/phy/fec/turbocoder.h" #include "liblte/phy/fec/turbocoder.h"
#define TURBO_RATE 3 #define TURBO_RATE 3
int mcd(int x, int y); uint32_t mcd(uint32_t x, uint32_t y);
/************************************************ /************************************************
* *
@ -53,14 +54,14 @@ 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, 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 }; 5, 2, 3, 2, 3, 2, 6, 3, 7, 7, 6, 3 };
int tc_interl_init(tc_interl_t *h, int max_long_cb) { int tc_interl_init(tc_interl_t *h, uint32_t max_long_cb) {
int ret = -1; int ret = -1;
h->forward = malloc(sizeof(int) * max_long_cb); h->forward = malloc(sizeof(uint32_t) * max_long_cb);
if (!h->forward) { if (!h->forward) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
} }
h->reverse = malloc(sizeof(int) * max_long_cb); h->reverse = malloc(sizeof(uint32_t) * max_long_cb);
if (!h->reverse) { if (!h->reverse) {
perror("malloc"); perror("malloc");
goto clean_exit; goto clean_exit;
@ -83,17 +84,17 @@ void tc_interl_free(tc_interl_t *h) {
bzero(h, sizeof(tc_interl_t)); bzero(h, sizeof(tc_interl_t));
} }
int tc_interl_UMTS_gen(tc_interl_t *h, int long_cb) { int tc_interl_UMTS_gen(tc_interl_t *h, uint32_t long_cb) {
int i, j; uint32_t i, j;
int res, prim, aux; uint32_t res, prim, aux;
int kp, k; uint32_t kp, k;
int *per, *desper; uint32_t *per, *desper;
unsigned char v; uint8_t v;
unsigned short p; uint16_t p;
unsigned short s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS]; uint16_t s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS];
unsigned short U[MAX_COLS * MAX_ROWS]; uint16_t U[MAX_COLS * MAX_ROWS];
int M_Rows, M_Cols, M_long; uint32_t M_Rows, M_Cols, M_long;
M_long = long_cb; M_long = long_cb;
@ -260,8 +261,8 @@ int tc_interl_UMTS_gen(tc_interl_t *h, int long_cb) {
} }
int mcd(int x, int y) { uint32_t mcd(uint32_t x, uint32_t y) {
int r = 1; uint32_t r = 1;
while (r) { while (r) {
r = x % y; r = x % y;

@ -26,12 +26,14 @@
*/ */
#include "liblte/phy/fec/turbocoder.h"
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include "liblte/phy/fec/turbocoder.h"
#define NOF_REGS 3 #define NOF_REGS 3
int tcod_init(tcod_t *h, int max_long_cb) { int tcod_init(tcod_t *h, uint32_t max_long_cb) {
if (tc_interl_init(&h->interl, max_long_cb)) { if (tc_interl_init(&h->interl, max_long_cb)) {
return -1; return -1;
@ -45,13 +47,13 @@ void tcod_free(tcod_t *h) {
h->max_long_cb = 0; h->max_long_cb = 0;
} }
int tcod_encode(tcod_t *h, char *input, char *output, int long_cb) { int tcod_encode(tcod_t *h, char *input, char *output, uint32_t long_cb) {
char reg1_0, reg1_1, reg1_2, reg2_0, reg2_1, reg2_2; char reg1_0, reg1_1, reg1_2, reg2_0, reg2_1, reg2_2;
int i, k = 0, j; uint32_t i, k = 0, j;
char bit; char bit;
char in, out; char in, out;
int *per; uint32_t *per;
if (long_cb > h->max_long_cb) { if (long_cb > h->max_long_cb) {
fprintf(stderr, "Turbo coder initiated for max_long_cb=%d\n", fprintf(stderr, "Turbo coder initiated for max_long_cb=%d\n",

@ -27,6 +27,7 @@
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
@ -38,13 +39,13 @@
* Decoder * Decoder
* *
************************************************/ ************************************************/
void map_gen_beta(map_gen_t *s, llr_t *input, llr_t *parity, int long_cb) { void map_gen_beta(map_gen_t *s, llr_t *input, llr_t *parity, uint32_t long_cb) {
llr_t m_b[8], new[8], old[8]; llr_t m_b[8], new[8], old[8];
llr_t x, y, xy; llr_t x, y, xy;
int k; int k;
int end = long_cb + RATE; uint32_t end = long_cb + RATE;
llr_t *beta = s->beta; llr_t *beta = s->beta;
int i; uint32_t i;
for (i = 0; i < 8; i++) { for (i = 0; i < 8; i++) {
old[i] = beta[8 * (end) + i]; old[i] = beta[8 * (end) + i];
@ -84,15 +85,15 @@ void map_gen_beta(map_gen_t *s, llr_t *input, llr_t *parity, int long_cb) {
} }
void map_gen_alpha(map_gen_t *s, llr_t *input, llr_t *parity, llr_t *output, void map_gen_alpha(map_gen_t *s, llr_t *input, llr_t *parity, llr_t *output,
int long_cb) { uint32_t long_cb) {
llr_t m_b[8], new[8], old[8], max1[8], max0[8]; llr_t m_b[8], new[8], old[8], max1[8], max0[8];
llr_t m1, m0; llr_t m1, m0;
llr_t x, y, xy; llr_t x, y, xy;
llr_t out; llr_t out;
int k; uint32_t k;
int end = long_cb; uint32_t end = long_cb;
llr_t *beta = s->beta; llr_t *beta = s->beta;
int i; uint32_t i;
old[0] = 0; old[0] = 0;
for (i = 1; i < 8; i++) { for (i = 1; i < 8; i++) {
@ -168,8 +169,8 @@ void map_gen_free(map_gen_t *h) {
} }
void map_gen_dec(map_gen_t *h, llr_t *input, llr_t *parity, llr_t *output, void map_gen_dec(map_gen_t *h, llr_t *input, llr_t *parity, llr_t *output,
int long_cb) { uint32_t long_cb) {
int k; uint32_t k;
h->beta[(long_cb + TAIL) * NUMSTATES] = 0; h->beta[(long_cb + TAIL) * NUMSTATES] = 0;
for (k = 1; k < NUMSTATES; k++) for (k = 1; k < NUMSTATES; k++)
@ -184,10 +185,10 @@ void map_gen_dec(map_gen_t *h, llr_t *input, llr_t *parity, llr_t *output,
* TURBO DECODER INTERFACE * TURBO DECODER INTERFACE
* *
************************************************/ ************************************************/
int tdec_init(tdec_t *h, int max_long_cb) { int tdec_init(tdec_t *h, uint32_t max_long_cb) {
int ret = -1; int ret = -1;
bzero(h, sizeof(tdec_t)); bzero(h, sizeof(tdec_t));
int len = max_long_cb + TOTALTAIL; uint32_t len = max_long_cb + TOTALTAIL;
h->max_long_cb = max_long_cb; h->max_long_cb = max_long_cb;
@ -256,8 +257,8 @@ void tdec_free(tdec_t *h) {
bzero(h, sizeof(tdec_t)); bzero(h, sizeof(tdec_t));
} }
void tdec_iteration(tdec_t *h, llr_t *input, int long_cb) { void tdec_iteration(tdec_t *h, llr_t *input, uint32_t long_cb) {
int i; uint32_t i;
// Prepare systematic and parity bits for MAP DEC #1 // Prepare systematic and parity bits for MAP DEC #1
for (i = 0; i < long_cb; i++) { for (i = 0; i < long_cb; i++) {
@ -295,7 +296,7 @@ void tdec_iteration(tdec_t *h, llr_t *input, int long_cb) {
} }
int tdec_reset(tdec_t *h, int long_cb) { int tdec_reset(tdec_t *h, uint32_t long_cb) {
memset(h->w, 0, sizeof(llr_t) * long_cb); memset(h->w, 0, sizeof(llr_t) * long_cb);
if (long_cb > h->max_long_cb) { if (long_cb > h->max_long_cb) {
fprintf(stderr, "TDEC was initialized for max_long_cb=%d\n", fprintf(stderr, "TDEC was initialized for max_long_cb=%d\n",
@ -305,16 +306,16 @@ int tdec_reset(tdec_t *h, int long_cb) {
return tc_interl_LTE_gen(&h->interleaver, long_cb); return tc_interl_LTE_gen(&h->interleaver, long_cb);
} }
void tdec_decision(tdec_t *h, char *output, int long_cb) { void tdec_decision(tdec_t *h, char *output, uint32_t long_cb) {
int i; uint32_t i;
for (i = 0; i < long_cb; i++) { for (i = 0; i < long_cb; i++) {
output[i] = (h->llr2[h->interleaver.reverse[i]] > 0) ? 1 : 0; 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, void tdec_run_all(tdec_t *h, llr_t *input, char *output, uint32_t nof_iterations,
int long_cb) { uint32_t long_cb) {
int iter = 0; uint32_t iter = 0;
tdec_reset(h, long_cb); tdec_reset(h, long_cb);

@ -27,6 +27,8 @@
#include <stdlib.h> #include <stdlib.h>
#include <stdio.h> #include <stdio.h>
#include <stdint.h>
#include <math.h> #include <math.h>
#include <string.h> #include <string.h>
@ -38,11 +40,11 @@
#define DEB 0 #define DEB 0
int decode37(void *o, unsigned char *symbols, char *data, int frame_length) { int decode37(void *o, uint8_t *symbols, char *data, uint32_t frame_length) {
viterbi_t *q = o; viterbi_t *q = o;
int i; uint32_t i;
int best_state; uint32_t best_state;
if (frame_length > q->framebits) { if (frame_length > q->framebits) {
fprintf(stderr, "Initialized decoder for max frame length %d bits\n", fprintf(stderr, "Initialized decoder for max frame length %d bits\n",
@ -73,7 +75,7 @@ int decode37(void *o, unsigned char *symbols, char *data, int frame_length) {
return q->framebits; return q->framebits;
} }
int decode39(void *o, unsigned char *symbols, char *data, int frame_length) { int decode39(void *o, uint8_t *symbols, char *data, uint32_t frame_length) {
viterbi_t *q = o; viterbi_t *q = o;
if (frame_length > q->framebits) { if (frame_length > q->framebits) {
@ -113,7 +115,7 @@ void free39(void *o) {
delete_viterbi39_port(q->ptr); delete_viterbi39_port(q->ptr);
} }
int init37(viterbi_t *q, int poly[3], int framebits, bool tail_biting) { int init37(viterbi_t *q, uint32_t poly[3], uint32_t framebits, bool tail_biting) {
q->K = 7; q->K = 7;
q->R = 3; q->R = 3;
q->framebits = framebits; q->framebits = framebits;
@ -145,7 +147,7 @@ int init37(viterbi_t *q, int poly[3], int framebits, bool tail_biting) {
} }
} }
int init39(viterbi_t *q, int poly[3], int framebits, bool tail_biting) { int init39(viterbi_t *q, uint32_t poly[3], uint32_t framebits, bool tail_biting) {
q->K = 9; q->K = 9;
q->R = 3; q->R = 3;
q->framebits = framebits; q->framebits = framebits;
@ -171,8 +173,8 @@ int init39(viterbi_t *q, int poly[3], int framebits, bool tail_biting) {
} }
} }
int viterbi_init(viterbi_t *q, viterbi_type_t type, int poly[3], int viterbi_init(viterbi_t *q, viterbi_type_t type, uint32_t poly[3],
int max_frame_length, bool tail_bitting) { uint32_t max_frame_length, bool tail_bitting) {
switch (type) { switch (type) {
case viterbi_37: case viterbi_37:
return init37(q, poly, max_frame_length, tail_bitting); return init37(q, poly, max_frame_length, tail_bitting);
@ -191,8 +193,8 @@ void viterbi_free(viterbi_t *q) {
} }
/* symbols are real-valued */ /* symbols are real-valued */
int viterbi_decode_f(viterbi_t *q, float *symbols, char *data, int frame_length) { int viterbi_decode_f(viterbi_t *q, float *symbols, char *data, uint32_t frame_length) {
int len; uint32_t len;
if (frame_length > q->framebits) { if (frame_length > q->framebits) {
fprintf(stderr, "Initialized decoder for max frame length %d bits\n", fprintf(stderr, "Initialized decoder for max frame length %d bits\n",
q->framebits); q->framebits);
@ -207,13 +209,13 @@ int viterbi_decode_f(viterbi_t *q, float *symbols, char *data, int frame_length)
return q->decode(q, q->symbols_uc, data, frame_length); return q->decode(q, q->symbols_uc, data, frame_length);
} }
int viterbi_decode_uc(viterbi_t *q, unsigned char *symbols, char *data, int viterbi_decode_uc(viterbi_t *q, uint8_t *symbols, char *data,
int frame_length) { uint32_t frame_length) {
return q->decode(q, symbols, data, frame_length); return q->decode(q, symbols, data, frame_length);
} }
int viterbi_initialize(viterbi_hl* h) { int viterbi_initialize(viterbi_hl* h) {
int poly[3]; uint32_t poly[3];
viterbi_type_t type; viterbi_type_t type;
if (h->init.rate == 2) { if (h->init.rate == 2) {
if (h->init.constraint_length == 7) { if (h->init.constraint_length == 7) {
@ -243,7 +245,7 @@ int viterbi_initialize(viterbi_hl* h) {
poly[0] = h->init.generator_0; poly[0] = h->init.generator_0;
poly[1] = h->init.generator_1; poly[1] = h->init.generator_1;
poly[2] = h->init.generator_2; poly[2] = h->init.generator_2;
return viterbi_init(&h->obj, type, poly, h->init.frame_length, return viterbi_init(&h->obj, type, poly, (uint32_t) h->init.frame_length,
h->init.tail_bitting ? true : false); h->init.tail_bitting ? true : false);
} }

@ -27,8 +27,20 @@
#include <stdbool.h> #include <stdbool.h>
void *create_viterbi37_port(int polys[3], int len); void *create_viterbi37_port(uint32_t polys[3],
int init_viterbi37_port(void *p, int starting_state); uint32_t len);
int chainback_viterbi37_port(void *p, char *data, unsigned int nbits, unsigned int endstate);
int init_viterbi37_port(void *p,
uint32_t starting_state);
int chainback_viterbi37_port(void *p,
char *data,
uint32_t nbits,
uint32_t endstate);
void delete_viterbi37_port(void *p); void delete_viterbi37_port(void *p);
int update_viterbi37_blk_port(void *p, unsigned char *syms, int nbits, int *best_state);
int update_viterbi37_blk_port(void *p,
unsigned char *syms,
uint32_t nbits,
uint32_t *best_state);

@ -4,6 +4,8 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <memory.h> #include <memory.h>
#include "viterbi37.h" #include "viterbi37.h"
#include "parity.h" #include "parity.h"
@ -30,9 +32,9 @@ struct v37 {
}; };
/* Initialize Viterbi decoder for start of new frame */ /* Initialize Viterbi decoder for start of new frame */
int init_viterbi37_port(void *p, int starting_state) { int init_viterbi37_port(void *p, uint32_t starting_state) {
struct v37 *vp = p; struct v37 *vp = p;
int i; uint32_t i;
if (p == NULL) if (p == NULL)
return -1; return -1;
@ -48,8 +50,8 @@ int init_viterbi37_port(void *p, int starting_state) {
return 0; return 0;
} }
void set_viterbi37_polynomial_port(int polys[3]) { void set_viterbi37_polynomial_port(uint32_t polys[3]) {
int state; uint32_t state;
for (state = 0; state < 32; state++) { for (state = 0; state < 32; state++) {
Branchtab37[0].c[state] = Branchtab37[0].c[state] =
@ -62,7 +64,7 @@ void set_viterbi37_polynomial_port(int polys[3]) {
} }
/* Create a new instance of a Viterbi decoder */ /* Create a new instance of a Viterbi decoder */
void *create_viterbi37_port(int polys[3], int len) { void *create_viterbi37_port(uint32_t polys[3], uint32_t len) {
struct v37 *vp; struct v37 *vp;
set_viterbi37_polynomial_port(polys); set_viterbi37_polynomial_port(polys);
@ -82,8 +84,8 @@ void *create_viterbi37_port(int polys[3], int len) {
/* Viterbi chainback */ /* Viterbi chainback */
int chainback_viterbi37_port(void *p, char *data, /* Decoded output data */ int chainback_viterbi37_port(void *p, char *data, /* Decoded output data */
unsigned int nbits, /* Number of data bits */ uint32_t nbits, /* Number of data bits */
unsigned int endstate) { /* Terminal encoder state */ uint32_t endstate) { /* Terminal encoder state */
struct v37 *vp = p; struct v37 *vp = p;
decision_t *d; decision_t *d;
@ -145,18 +147,18 @@ unsigned int metric,m0,m1,decision;\
* of symbols! * of symbols!
*/ */
int update_viterbi37_blk_port(void *p, unsigned char *syms, int nbits, int *best_state) { int update_viterbi37_blk_port(void *p, uint8_t *syms, uint32_t nbits, uint32_t *best_state) {
struct v37 *vp = p; struct v37 *vp = p;
decision_t *d; decision_t *d;
if (p == NULL) if (p == NULL)
return -1; return -1;
int k=0; uint32_t k=0;
d = (decision_t *) vp->dp; d = (decision_t *) vp->dp;
while (nbits--) { while (nbits--) {
void *tmp; void *tmp;
unsigned char sym0, sym1, sym2; uint8_t sym0, sym1, sym2;
int i; uint32_t i;
d->w[0] = d->w[1] = 0; d->w[0] = d->w[1] = 0;
@ -174,8 +176,8 @@ int update_viterbi37_blk_port(void *p, unsigned char *syms, int nbits, int *best
vp->new_metrics = tmp; vp->new_metrics = tmp;
} }
if (best_state) { if (best_state) {
int i, bst=0; uint32_t i, bst=0;
unsigned int minmetric=UINT_MAX; uint32_t minmetric=UINT_MAX;
for (i=0;i<64;i++) { for (i=0;i<64;i++) {
if (vp->old_metrics->w[i] < minmetric) { if (vp->old_metrics->w[i] < minmetric) {
bst = i; bst = i;

@ -27,10 +27,19 @@
#include <stdbool.h> #include <stdbool.h>
void *create_viterbi39_port(int polys[3], int len); void *create_viterbi39_port(uint32_t polys[3],
int init_viterbi39_port(void *p, int starting_state); uint32_t len);
int chainback_viterbi39_port(void *p, char *data, /* Decoded output data */
unsigned int nbits, /* Number of data bits */ int init_viterbi39_port(void *p,
unsigned int endstate); uint32_t starting_state);
int chainback_viterbi39_port(void *p,
char *data, /* Decoded output data */
uint32_t nbits, /* Number of data bits */
uint32_t endstate);
void delete_viterbi39_port(void *p); void delete_viterbi39_port(void *p);
int update_viterbi39_blk_port(void *p, unsigned char *syms, int nbits);
int update_viterbi39_blk_port(void *p,
uint8_t *syms,
uint32_t nbits);

@ -4,6 +4,7 @@
*/ */
#include <stdio.h> #include <stdio.h>
#include <stdlib.h> #include <stdlib.h>
#include <stdint.h>
#include <memory.h> #include <memory.h>
#include "viterbi39.h" #include "viterbi39.h"
#include "parity.h" #include "parity.h"
@ -29,9 +30,9 @@ struct v39 {
}; };
/* Initialize Viterbi decoder for start of new frame */ /* Initialize Viterbi decoder for start of new frame */
int init_viterbi39_port(void *p, int starting_state) { int init_viterbi39_port(void *p, uint32_t starting_state) {
struct v39 *vp = p; struct v39 *vp = p;
int i; uint32_t i;
if (p == NULL) if (p == NULL)
return -1; return -1;
@ -45,8 +46,8 @@ int init_viterbi39_port(void *p, int starting_state) {
return 0; return 0;
} }
void set_viterbi39_polynomial_port(int polys[3]) { void set_viterbi39_polynomial_port(uint32_t polys[3]) {
int state; uint32_t state;
for (state = 0; state < 128; state++) { for (state = 0; state < 128; state++) {
Branchtab39[0].c[state] = Branchtab39[0].c[state] =
@ -59,7 +60,7 @@ void set_viterbi39_polynomial_port(int polys[3]) {
} }
/* Create a new instance of a Viterbi decoder */ /* Create a new instance of a Viterbi decoder */
void *create_viterbi39_port(int polys[3], int len) { void *create_viterbi39_port(uint32_t polys[3], uint32_t len) {
struct v39 *vp; struct v39 *vp;
set_viterbi39_polynomial_port(polys); set_viterbi39_polynomial_port(polys);
@ -79,8 +80,8 @@ void *create_viterbi39_port(int polys[3], int len) {
/* Viterbi chainback */ /* Viterbi chainback */
int chainback_viterbi39_port(void *p, char *data, /* Decoded output data */ int chainback_viterbi39_port(void *p, char *data, /* Decoded output data */
unsigned int nbits, /* Number of data bits */ uint32_t nbits, /* Number of data bits */
unsigned int endstate) { /* Terminal encoder state */ uint32_t endstate) { /* Terminal encoder state */
struct v39 *vp = p; struct v39 *vp = p;
decision_t *d; decision_t *d;
@ -140,7 +141,7 @@ unsigned int metric,m0,m1,decision;\
* of symbols! * of symbols!
*/ */
int update_viterbi39_blk_port(void *p, unsigned char *syms, int nbits) { int update_viterbi39_blk_port(void *p, uint8_t *syms, uint32_t nbits) {
struct v39 *vp = p; struct v39 *vp = p;
decision_t *d; decision_t *d;
@ -150,8 +151,8 @@ int update_viterbi39_blk_port(void *p, unsigned char *syms, int nbits) {
d = (decision_t *) vp->dp; d = (decision_t *) vp->dp;
while (nbits--) { while (nbits--) {
void *tmp; void *tmp;
unsigned char sym0, sym1, sym2; uint8_t sym0, sym1, sym2;
int i; uint32_t i;
for (i = 0; i < 8; i++) for (i = 0; i < 8; i++)
d->w[i] = 0; d->w[i] = 0;

@ -41,9 +41,9 @@
typedef _Complex float cf_t; typedef _Complex float cf_t;
int frame_length = 1000, nof_frames = 100; uint32_t frame_length = 1000, nof_frames = 100;
float ebno_db = 100.0; float ebno_db = 100.0;
unsigned int seed = 0; uint32_t seed = 0;
int K = -1; int K = -1;
#define MAX_ITERATIONS 4 #define MAX_ITERATIONS 4
@ -51,9 +51,9 @@ int nof_iterations = MAX_ITERATIONS;
int test_known_data = 0; int test_known_data = 0;
int test_errors = 0; int test_errors = 0;
#define SNR_POINTS 8 #define SNR_POINTS 8
#define SNR_MIN 0.0 #define SNR_MIN 0.0
#define SNR_MAX 4.0 #define SNR_MAX 4.0
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [nlesv]\n", prog); printf("Usage: %s [nlesv]\n", prog);
@ -127,16 +127,16 @@ void output_matlab(float ber[MAX_ITERATIONS][SNR_POINTS], int snr_points) {
} }
int main(int argc, char **argv) { int main(int argc, char **argv) {
int frame_cnt; uint32_t frame_cnt;
float *llr; float *llr;
unsigned char *llr_c; unsigned char *llr_c;
char *data_tx, *data_rx, *symbols; char *data_tx, *data_rx, *symbols;
int i, j; uint32_t i, j;
float var[SNR_POINTS]; float var[SNR_POINTS];
int snr_points; uint32_t snr_points;
float ber[MAX_ITERATIONS][SNR_POINTS]; float ber[MAX_ITERATIONS][SNR_POINTS];
unsigned int errors[100]; uint32_t errors[100];
int coded_length; uint32_t coded_length;
struct timeval tdata[3]; struct timeval tdata[3];
float mean_usec; float mean_usec;
tdec_t tdec; tdec_t tdec;
@ -247,7 +247,7 @@ int main(int argc, char **argv) {
/* decoder */ /* decoder */
tdec_reset(&tdec, frame_length); tdec_reset(&tdec, frame_length);
int t; uint32_t t;
if (nof_iterations == -1) { if (nof_iterations == -1) {
t = MAX_ITERATIONS; t = MAX_ITERATIONS;
} else { } else {

@ -40,42 +40,20 @@
#include "liblte/phy/utils/vector.h" #include "liblte/phy/utils/vector.h"
#include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/debug.h"
int dci_init(dci_t *q, uint32_t max_dcis) {
q->msg = calloc(sizeof(dci_msg_t), max_dcis);
if (!q->msg) {
perror("malloc");
return LIBLTE_ERROR;
}
q->nof_dcis = 0;
q->max_dcis = max_dcis;
return LIBLTE_SUCCESS;
}
void dci_free(dci_t *q) {
if (q->msg) {
free(q->msg);
}
}
void dci_candidate_fprint(FILE *f, dci_candidate_t *q) {
fprintf(f, "L: %d, nCCE: %d, RNTI: 0x%x, nBits: %d\n", q->L, q->ncce, q->rnti,
q->nof_bits);
}
int dci_msg_candidate_set(dci_msg_t *msg, uint32_t L, uint32_t nCCE, uint16_t rnti) { int dci_location_set(dci_location_t *c, uint32_t L, uint32_t nCCE) {
if (L >= 0 && L <= 3) { if (L <= 3) {
msg->location.L = L; c->L = L;
} else { } else {
fprintf(stderr, "Invalid L %d\n", L); fprintf(stderr, "Invalid L %d\n", L);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
if (nCCE >= 0 && nCCE <= 87) { if (nCCE <= 87) {
msg->location.ncce = nCCE; c->ncce = nCCE;
} else { } else {
fprintf(stderr, "Invalid nCCE %d\n", nCCE); fprintf(stderr, "Invalid nCCE %d\n", nCCE);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
msg->location.rnti = rnti;
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -245,7 +223,7 @@ int dci_format0_pack(ra_pusch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
while (y - msg->data < n) { while (y - msg->data < n) {
*y++ = 0; *y++ = 0;
} }
msg->location.nof_bits = (y - msg->data); msg->nof_bits = (y - msg->data);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
/* Unpacks DCI format 0 data and store result in msg according /* Unpacks DCI format 0 data and store result in msg according
@ -260,7 +238,7 @@ int dci_format0_unpack(dci_msg_t *msg, ra_pusch_t *data, uint32_t nof_prb) {
uint32_t n_ul_hop; uint32_t n_ul_hop;
/* Make sure it's a Format0 message */ /* Make sure it's a Format0 message */
if (msg->location.nof_bits != dci_format_sizeof(Format0, nof_prb)) { if (msg->nof_bits != dci_format_sizeof(Format0, nof_prb)) {
fprintf(stderr, "Invalid message length for format 0\n"); fprintf(stderr, "Invalid message length for format 0\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
@ -385,7 +363,7 @@ int dci_format1_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
while (y - msg->data < n) { while (y - msg->data < n) {
*y++ = 0; *y++ = 0;
} }
msg->location.nof_bits = (y - msg->data); msg->nof_bits = (y - msg->data);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -396,7 +374,7 @@ int dci_format1_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb) {
char *y = msg->data; char *y = msg->data;
/* Make sure it's a Format1 message */ /* Make sure it's a Format1 message */
if (msg->location.nof_bits != dci_format_sizeof(Format1, nof_prb)) { if (msg->nof_bits != dci_format_sizeof(Format1, nof_prb)) {
fprintf(stderr, "Invalid message length for format 1\n"); fprintf(stderr, "Invalid message length for format 1\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
@ -551,7 +529,7 @@ int dci_format1As_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb,
while (y - msg->data < n) { while (y - msg->data < n) {
*y++ = 0; *y++ = 0;
} }
msg->location.nof_bits = (y - msg->data); msg->nof_bits = (y - msg->data);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -566,7 +544,7 @@ int dci_format1As_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
char *y = msg->data; char *y = msg->data;
/* Make sure it's a Format0 message */ /* Make sure it's a Format0 message */
if (msg->location.nof_bits != dci_format_sizeof(Format1A, nof_prb)) { if (msg->nof_bits != dci_format_sizeof(Format1A, nof_prb)) {
fprintf(stderr, "Invalid message length for format 1A\n"); fprintf(stderr, "Invalid message length for format 1A\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
@ -692,7 +670,7 @@ int dci_format1Cs_pack(ra_pdsch_t *data, dci_msg_t *msg, uint32_t nof_prb) {
} }
bit_pack((uint32_t) mcs, &y, 5); bit_pack((uint32_t) mcs, &y, 5);
msg->location.nof_bits = (y - msg->data); msg->nof_bits = (y - msg->data);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -703,7 +681,7 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb) {
/* pack bits */ /* pack bits */
char *y = msg->data; char *y = msg->data;
if (msg->location.nof_bits != dci_format_sizeof(Format1C, nof_prb)) { if (msg->nof_bits != dci_format_sizeof(Format1C, nof_prb)) {
fprintf(stderr, "Invalid message length for format 1C\n"); fprintf(stderr, "Invalid message length for format 1C\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
@ -728,7 +706,7 @@ int dci_format1Cs_unpack(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb) {
data->mcs.tbs = ra_tbs_from_idx_format1c(data->mcs.tbs_idx); data->mcs.tbs = ra_tbs_from_idx_format1c(data->mcs.tbs_idx);
data->mcs.mod = QPSK; data->mcs.mod = QPSK;
msg->location.nof_bits = (y - msg->data); msg->nof_bits = (y - msg->data);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
@ -751,11 +729,11 @@ int dci_msg_pack_pdsch(ra_pdsch_t *data, dci_msg_t *msg, dci_format_t format,
int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb, int dci_msg_unpack_pdsch(dci_msg_t *msg, ra_pdsch_t *data, uint32_t nof_prb,
bool crc_is_crnti) { bool crc_is_crnti) {
if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { if (msg->nof_bits == dci_format_sizeof(Format1, nof_prb)) {
return dci_format1_unpack(msg, data, nof_prb); return dci_format1_unpack(msg, data, nof_prb);
} else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) { } else if (msg->nof_bits == dci_format_sizeof(Format1A, nof_prb)) {
return dci_format1As_unpack(msg, data, nof_prb, crc_is_crnti); return dci_format1As_unpack(msg, data, nof_prb, crc_is_crnti);
} else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { } else if (msg->nof_bits == dci_format_sizeof(Format1C, nof_prb)) {
return dci_format1Cs_unpack(msg, data, nof_prb); return dci_format1Cs_unpack(msg, data, nof_prb);
} else { } else {
return LIBLTE_ERROR; return LIBLTE_ERROR;
@ -807,18 +785,18 @@ void dci_msg_type_fprint(FILE *f, dci_msg_type_t type) {
} }
int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, uint32_t nof_prb, int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, uint32_t nof_prb,
uint16_t crnti) { uint16_t msg_rnti, uint16_t crnti) {
if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb) if (msg->nof_bits == dci_format_sizeof(Format0, nof_prb)
&& !msg->data[0]) { && !msg->data[0]) {
type->type = PUSCH_SCHED; type->type = PUSCH_SCHED;
type->format = Format0; type->format = Format0;
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} else if (msg->location.nof_bits == dci_format_sizeof(Format1, nof_prb)) { } else if (msg->nof_bits == dci_format_sizeof(Format1, nof_prb)) {
type->type = PDSCH_SCHED; // only these 2 types supported type->type = PDSCH_SCHED; // only these 2 types supported
type->format = Format1; type->format = Format1;
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) { } else if (msg->nof_bits == dci_format_sizeof(Format1A, nof_prb)) {
if (msg->location.rnti == crnti) { if (msg_rnti == crnti) {
type->type = RA_PROC_PDCCH; type->type = RA_PROC_PDCCH;
type->format = Format1A; type->format = Format1A;
} else { } else {
@ -826,8 +804,8 @@ int dci_msg_get_type(dci_msg_t *msg, dci_msg_type_t *type, uint32_t nof_prb,
type->format = Format1A; type->format = Format1A;
} }
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) { } else if (msg->nof_bits == dci_format_sizeof(Format1C, nof_prb)) {
if (msg->location.rnti == MRNTI) { if (msg_rnti == MRNTI) {
type->type = MCCH_CHANGE; type->type = MCCH_CHANGE;
type->format = Format1C; type->format = Format1C;
} else { } else {

@ -144,7 +144,7 @@ int pbch_init(pbch_t *q, lte_cell_t cell) {
goto clean; goto clean;
} }
int poly[3] = { 0x6D, 0x4F, 0x57 }; uint32_t poly[3] = { 0x6D, 0x4F, 0x57 };
if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) { if (viterbi_init(&q->decoder, viterbi_37, poly, 40, true)) {
goto clean; goto clean;
} }

@ -46,173 +46,11 @@
#define PDCCH_FORMAT_NOF_REGS(i) ((1<<i)*9) #define PDCCH_FORMAT_NOF_REGS(i) ((1<<i)*9)
#define PDCCH_FORMAT_NOF_BITS(i) ((1<<i)*72) #define PDCCH_FORMAT_NOF_BITS(i) ((1<<i)*72)
#define NOF_COMMON_FORMATS 2
const dci_format_t common_formats[NOF_COMMON_FORMATS] = { Format1A, Format1C };
#define NOF_UE_FORMATS 2
const dci_format_t ue_formats[NOF_UE_FORMATS] = { Format0, Format1 }; // 1A has the same payload as 0
#define MIN(a,b) ((a>b)?b:a) #define MIN(a,b) ((a>b)?b:a)
void set_cfi(pdcch_t *q, uint32_t cfi);
/**
* 36.213 9.1
*/
int gen_common_search(dci_candidate_t *c, uint32_t nof_cce, uint32_t nof_bits,
uint16_t rnti) {
int i, l, L, k;
k = 0;
for (l = 3; l > 1; l--) {
L = (1 << l);
for (i = 0; i < MIN(nof_cce,16) / (L); i++) {
c[k].L = l;
c[k].nof_bits = nof_bits;
c[k].rnti = rnti;
c[k].ncce = (L) * (i % (nof_cce / (L)));
INFO("Common SS Candidate %d: RNTI: 0x%x, nCCE: %d, Nbits: %d, L: %d\n",
k, c[k].rnti, c[k].ncce, c[k].nof_bits, c[k].L);
k++;
}
}
return k;
}
/**
* 36.213 9.1
*/
int gen_ue_search(dci_candidate_t *c, uint32_t nof_cce, uint32_t nof_bits,
uint16_t rnti, uint32_t subframe) {
int i, l, L, k, m;
unsigned int Yk;
const int S[4] = { 6, 12, 8, 16 };
k = 0;
if (VERBOSE_ISDEBUG()) {
printf("NofBits=%d, RNTI: 0x%x, SF=%d (n, L): ", nof_bits, rnti, subframe);
}
for (l = 3; l >= 0; l--) {
L = (1 << l);
for (i = 0; i < MIN(nof_cce / L, 16 / S[l]); i++) {
c[k].L = l;
c[k].nof_bits = nof_bits;
c[k].rnti = rnti;
Yk = rnti;
for (m = 0; m < subframe; m++) {
Yk = (39827 * Yk) % 65537;
}
c[k].ncce = L * ((Yk + i) % (nof_cce / L));
if (VERBOSE_ISDEBUG()) {
printf("(%d, %d), ", c[k].ncce, c[k].L);
}
if (c[k].ncce + PDCCH_FORMAT_NOF_CCE(c[k].L) > nof_cce ||
nof_bits > DCI_MAX_BITS) {
fprintf(stderr, "Illegal DCI message\n");
return LIBLTE_ERROR;
}
k++;
}
}
if (VERBOSE_ISDEBUG()) {
printf("\n");
}
return k;
}
/** 36.213 v9.3 Table 7.1-5
* user-specific search space. Currently supported transmission Mode 1:
* DCI Format 1A and 1 + PUSCH scheduling format 0
*/
int pdcch_init_search_ue(pdcch_t *q, uint16_t c_rnti, uint32_t cfi) {
int k, i, r;
uint32_t n;
set_cfi(q, cfi);
pdcch_search_t *s = &q->search_mode[SEARCH_UE];
for (n = 0; n < NSUBFRAMES_X_FRAME; n++) {
dci_candidate_t *c = s->candidates[n];
if (!n) s->nof_candidates = 0;
// Expect Formats 1, 1A, 0
k = 0;
for (i = 0; i < NOF_UE_FORMATS && k < MAX_CANDIDATES; i++) {
r = gen_ue_search(&c[k], q->nof_cce,
dci_format_sizeof(ue_formats[i], q->cell.nof_prb), c_rnti, n);
if (r < 0) {
fprintf(stderr, "Error generating UE-specific search space\n");
return r;
}
k += r;
}
s->nof_candidates = k;
}
INFO("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x\n",
s->nof_candidates, c_rnti);
q->current_search_mode = SEARCH_UE;
return LIBLTE_SUCCESS;
}
int pdcch_init_common(pdcch_t *q, pdcch_search_t *s, uint16_t rnti) {
int k, r, i;
dci_candidate_t *c = s->candidates[0];
s->nof_candidates = 0;
// Format 1A and 1C L=4 and L=8, 4 and 2 candidates, only if nof_cce > 16
k = 0;
for (i = 0; i < NOF_COMMON_FORMATS && k < MAX_CANDIDATES; i++) {
r = gen_common_search(&c[k], q->nof_cce,
dci_format_sizeof(common_formats[i], q->cell.nof_prb), SIRNTI);
if (r < 0) {
return r;
}
k += r;
}
s->nof_candidates=k;
INFO("Initiated %d candidate(s) in the Common search space for RNTI: 0x%x\n",
s->nof_candidates, rnti);
return LIBLTE_SUCCESS;
}
/** 36.213 v9.3 Table 7.1-1: System Information DCI messages
* Expect DCI formats 1C and 1A in the common search space
*/
int pdcch_init_search_si(pdcch_t *q, uint32_t cfi) {
set_cfi(q, cfi);
int r = pdcch_init_common(q, &q->search_mode[SEARCH_SI], SIRNTI);
if (r >= 0) {
q->current_search_mode = SEARCH_SI;
}
return r;
}
/** 36.213 v9.3 Table 7.1-3
* Expect DCI formats 1C and 1A in the common search space
*/
int pdcch_init_search_ra(pdcch_t *q, uint16_t ra_rnti, uint32_t cfi) {
set_cfi(q, cfi);
int r = pdcch_init_common(q, &q->search_mode[SEARCH_RA], ra_rnti);
if (r >= 0) {
q->current_search_mode = SEARCH_RA;
}
return r;
}
void pdcch_set_search_si(pdcch_t *q) {
q->current_search_mode = SEARCH_SI;
}
void pdcch_set_search_ue(pdcch_t *q) {
q->current_search_mode = SEARCH_UE;
}
void pdcch_set_search_ra(pdcch_t *q) {
q->current_search_mode = SEARCH_RA;
}
void set_cfi(pdcch_t *q, uint32_t cfi) { static void set_cfi(pdcch_t *q, uint32_t cfi) {
if (cfi > 0 && cfi < 4) { if (cfi > 0 && cfi < 4) {
q->nof_regs = (regs_pdcch_nregs(q->regs, cfi) / 9) * 9; q->nof_regs = (regs_pdcch_nregs(q->regs, cfi) / 9) * 9;
q->nof_cce = q->nof_regs / 9; q->nof_cce = q->nof_regs / 9;
@ -221,6 +59,7 @@ void set_cfi(pdcch_t *q, uint32_t cfi) {
} }
} }
/** Initializes the PDCCH transmitter and receiver */ /** Initializes the PDCCH transmitter and receiver */
int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) { int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
@ -234,7 +73,6 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
bzero(q, sizeof(pdcch_t)); bzero(q, sizeof(pdcch_t));
q->cell = cell; q->cell = cell;
q->regs = regs; q->regs = regs;
q->current_search_mode = SEARCH_NONE;
/* Now allocate memory for the maximum number of REGs (CFI=3) /* Now allocate memory for the maximum number of REGs (CFI=3)
*/ */
@ -261,7 +99,7 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
} }
} }
int poly[3] = { 0x6D, 0x4F, 0x57 }; uint32_t poly[3] = { 0x6D, 0x4F, 0x57 };
if (viterbi_init(&q->decoder, viterbi_37, poly, DCI_MAX_BITS + 16, true)) { if (viterbi_init(&q->decoder, viterbi_37, poly, DCI_MAX_BITS + 16, true)) {
goto clean; goto clean;
} }
@ -337,13 +175,97 @@ void pdcch_free(pdcch_t *q) {
viterbi_free(&q->decoder); viterbi_free(&q->decoder);
} }
/** 36.213 v9.1.1
* Computes up to max_candidates UE-specific candidates for DCI messages and saves them
* in the structure pointed by c.
* Returns the number of candidates saved in the array c.
*/
uint32_t pdcch_ue_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidates,
uint32_t nsubframe, uint32_t cfi, uint16_t rnti) {
uint32_t i, k, l, L, m;
uint32_t Yk, ncce;
const int S[4] = { 6, 12, 8, 16 };
set_cfi(q, cfi);
// Compute Yk for this subframe
Yk = rnti;
for (m = 0; m < nsubframe; m++) {
Yk = (39827 * Yk) % 65537;
}
k = 0;
// All aggregation levels from 8 to 1
for (l = 3; l >= 0; l--) {
L = (1 << l);
// For all possible ncce offset
for (i = 0; i < MIN(q->nof_cce / L, 16 / S[l]); i++) {
ncce = L * ((Yk + i) % (q->nof_cce / L));
if (k < max_candidates &&
ncce + PDCCH_FORMAT_NOF_CCE(L) < q->nof_cce)
{
c[k].L = l;
c[k].ncce = ncce;
DEBUG("UE-specific SS Candidate %d: nCCE: %d, L: %d\n",
k, c[k].ncce, c[k].L);
k++;
}
}
}
INFO("Initiated %d candidate(s) in the UE-specific search space for C-RNTI: 0x%x\n", k, rnti);
return k;
}
/**
* 36.213 9.1.1
* Computes up to max_candidates candidates in the common search space
* for DCI messages and saves them in the structure pointed by c.
* Returns the number of candidates saved in the array c.
*/
uint32_t pdcch_common_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidates,
uint32_t cfi) {
uint32_t i, l, L, k;
set_cfi(q, cfi);
k = 0;
for (l = 3; l > 1; l--) {
L = (1 << l);
for (i = 0; i < MIN(q->nof_cce, 16) / (L); i++) {
if (k < max_candidates) {
c[k].L = l;
c[k].ncce = (L) * (i % (q->nof_cce / (L)));
DEBUG("Common SS Candidate %d: nCCE: %d, L: %d\n",
k, c[k].ncce, c[k].L);
k++;
}
}
}
INFO("Initiated %d candidate(s) in the Common search space\n", k);
return k;
}
/** 36.212 5.3.3.2 to 5.3.3.4 /** 36.212 5.3.3.2 to 5.3.3.4
* *
* Returns XOR between parity and remainder bits * Returns XOR between parity and remainder bits
* *
* TODO: UE transmit antenna selection CRC mask * TODO: UE transmit antenna selection CRC mask
*/ */
int dci_decode(pdcch_t *q, float *e, char *data, uint32_t E, uint32_t nof_bits, uint16_t *crc) { static int dci_decode(pdcch_t *q, float *e, char *data, uint32_t E, uint32_t nof_bits, uint16_t *crc) {
float tmp[3 * (DCI_MAX_BITS + 16)]; float tmp[3 * (DCI_MAX_BITS + 16)];
uint16_t p_bits, crc_res; uint16_t p_bits, crc_res;
@ -355,6 +277,10 @@ int dci_decode(pdcch_t *q, float *e, char *data, uint32_t E, uint32_t nof_bits,
nof_bits < DCI_MAX_BITS) nof_bits < DCI_MAX_BITS)
{ {
if (VERBOSE_ISDEBUG()) {
vec_fprint_f(stdout, e, E);
}
/* unrate matching */ /* unrate matching */
rm_conv_rx(e, E, tmp, 3 * (nof_bits + 16)); rm_conv_rx(e, E, tmp, 3 * (nof_bits + 16));
@ -385,36 +311,63 @@ int dci_decode(pdcch_t *q, float *e, char *data, uint32_t E, uint32_t nof_bits,
} }
} }
int pdcch_decode_candidate(pdcch_t *q, float *llr, dci_candidate_t *c, /** Tries to decode a DCI message from the LLRs stored in the pdcch_t structure by the function
dci_msg_t *msg) { * pdcch_extract_llr(). This function can be called multiple times.
uint16_t crc_res; * The decoded message is stored in msg. Up to nof_locations are tried from the array of dci_locations_t
INFO("Trying Candidate: Nbits: %d, E: %3d, nCCE: %d, L: %d, RNTI: 0x%x\n", * pointed by locations. The CRC is checked agains the RNTI parameter.
c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, c->rnti); *
* Returns 1 if the message is correctly decoded, 0 if not and -1 on error.
*/
int pdcch_decode_msg(pdcch_t *q, dci_msg_t *msg,
dci_location_t *locations, uint32_t nof_locations,
dci_format_t format, uint16_t rnti)
{
if (q != NULL &&
msg != NULL &&
locations != NULL &&
nof_locations > 0)
{
uint16_t crc_res;
uint32_t nof_bits = dci_format_sizeof(format, q->cell.nof_prb);
uint32_t i;
if (dci_decode(q, &llr[72 * c->ncce], msg->data, i = 0;
PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits, &crc_res)) { do {
return LIBLTE_ERROR; INFO("Trying Candidate: Nbits: %d, E: %3d, nCCE: %d, L: %d, RNTI: 0x%x\n",
} nof_bits, PDCCH_FORMAT_NOF_BITS(locations[i].L), locations[i].ncce, locations[i].L, rnti);
if (c->rnti == crc_res) { if (dci_decode(q, &q->pdcch_llr[72 * locations[i].ncce], msg->data,
memcpy(&msg->location, c, sizeof(dci_candidate_t)); PDCCH_FORMAT_NOF_BITS(locations[i].L), nof_bits, &crc_res) != LIBLTE_SUCCESS) {
INFO("FOUND Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", return LIBLTE_ERROR;
c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, c->rnti); }
return 1; if (crc_res != rnti) {
i++;
}
} while(i < nof_locations && crc_res != rnti);
if (rnti == crc_res) {
msg->nof_bits = nof_bits;
INFO("FOUND Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n",
nof_bits, PDCCH_FORMAT_NOF_BITS(locations[i].L), locations[i].ncce, locations[i].L, rnti);
return 1;
} else {
return LIBLTE_SUCCESS;
}
} }
return LIBLTE_SUCCESS; return LIBLTE_ERROR_INVALID_INPUTS;
} }
int pdcch_extract_llr(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS], /** Extracts the LLRs from the subframe symbols (demodulation) and stores them in the pdcch_t structure.
float *llr, uint32_t nsubframe, uint32_t cfi) { * DCI messages can be extracted calling the function pdcch_decode_msg().
* Every time this function is called, the last demodulated symbols are overwritten.
*/
int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], uint32_t nsubframe, uint32_t cfi) {
/* Set pointers for layermapping & precoding */ /* Set pointers for layermapping & precoding */
int i; uint32_t i;
cf_t *x[MAX_LAYERS]; cf_t *x[MAX_LAYERS];
if (q != NULL && if (q != NULL &&
llr != NULL &&
slot_symbols != NULL &&
nsubframe < 10 && nsubframe < 10 &&
cfi > 0 && cfi > 0 &&
cfi < 4) cfi < 4)
@ -428,7 +381,7 @@ int pdcch_extract_llr(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS],
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
/* extract symbols */ /* extract symbols */
int n = regs_pdcch_get(q->regs, slot_symbols, q->pdcch_symbols[0]); int n = regs_pdcch_get(q->regs, sf_symbols, q->pdcch_symbols[0]);
if (q->nof_symbols != n) { if (q->nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n",
q->nof_symbols, n); q->nof_symbols, n);
@ -472,84 +425,18 @@ int pdcch_extract_llr(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS],
} }
/* descramble */ /* descramble */
scrambling_f_offset(&q->seq_pdcch[nsubframe], llr, 0, q->nof_bits); scrambling_f_offset(&q->seq_pdcch[nsubframe], q->pdcch_llr, 0, q->nof_bits);
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
} }
return LIBLTE_ERROR_INVALID_INPUTS;
} }
int pdcch_decode_current_mode(pdcch_t *q, float *llr, dci_t *dci, uint32_t subframe) {
int k, i;
int ret;
if (q->current_search_mode == SEARCH_UE) {
k = subframe;
} else {
k = 0;
}
for (i = 0;
i < q->search_mode[q->current_search_mode].nof_candidates
&& dci->nof_dcis < dci->max_dcis; i++) {
ret = pdcch_decode_candidate(q, q->pdcch_llr,
&q->search_mode[q->current_search_mode].candidates[k][i],
&dci->msg[dci->nof_dcis]);
if (ret == 1) {
dci->nof_dcis++;
} else if (ret == -1) {
return LIBLTE_ERROR;
}
}
return dci->nof_dcis;
}
int pdcch_decode_si(pdcch_t *q, float *llr, dci_t *dci) {
pdcch_set_search_si(q);
return pdcch_decode_current_mode(q, llr, dci, 0);
}
int pdcch_decode_ra(pdcch_t *q, float *llr, dci_t *dci) {
pdcch_set_search_ra(q);
return pdcch_decode_current_mode(q, llr, dci, 0);
}
int pdcch_decode_ue(pdcch_t *q, float *llr, dci_t *dci, uint32_t nsubframe) {
pdcch_set_search_ue(q);
return pdcch_decode_current_mode(q, llr, dci, nsubframe);
}
/* Decodes PDCCH channels
*
* dci->nof_dcis is the size of the dci->msg buffer (ie max number of messages)
*
* Returns number of messages stored in dci
*/
int pdcch_decode(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS],
dci_t *dci, uint32_t subframe, uint32_t cfi) {
if (q != NULL &&
dci != NULL &&
slot_symbols != NULL &&
subframe < 10 &&
cfi > 0 &&
cfi < 4)
{
if (pdcch_extract_llr(q, slot_symbols, ce, q->pdcch_llr, subframe, cfi)) {
return LIBLTE_ERROR;
}
if (q->current_search_mode != SEARCH_NONE) {
return pdcch_decode_current_mode(q, q->pdcch_llr, dci, subframe);
}
return LIBLTE_SUCCESS;
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
}
}
void crc_set_mask_rnti(char *crc, uint16_t rnti) { static void crc_set_mask_rnti(char *crc, uint16_t rnti) {
int i; uint32_t i;
char mask[16]; char mask[16];
char *r = mask; char *r = mask;
@ -564,7 +451,7 @@ void crc_set_mask_rnti(char *crc, uint16_t 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
*/ */
int dci_encode(pdcch_t *q, char *data, char *e, uint32_t nof_bits, uint32_t E, static int dci_encode(pdcch_t *q, char *data, char *e, uint32_t nof_bits, uint32_t E,
uint16_t rnti) { uint16_t rnti) {
convcoder_t encoder; convcoder_t encoder;
char tmp[3 * (DCI_MAX_BITS + 16)]; char tmp[3 * (DCI_MAX_BITS + 16)];
@ -600,16 +487,57 @@ int dci_encode(pdcch_t *q, char *data, char *e, uint32_t nof_bits, uint32_t E,
} }
} }
/** Converts the set of DCI messages to symbols mapped to the slot ready for transmission void pdcch_reset(pdcch_t *q) {
/* should add <NIL> elements? Or maybe random bits to facilitate power estimation */
bzero(q->pdcch_e, q->nof_bits);
}
/** Encodes ONE DCI message and allocates the encoded bits to the dci_location_t indicated by
* the parameter location. The CRC is scrambled with the RNTI parameter.
* This function can be called multiple times and encoded DCI messages will be stored in the
* pdcch_t structure. A final call to the function pdcch_gen_symbols() will generate and map the
* symbols to the subframe for transmission.
* If the same location is provided in multiple messages, the encoded bits will be overwritten.
*
* @TODO: Use a bitmask and CFI to ensure message locations are valid and old messages are not overwritten.
*/ */
int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot_symbols[MAX_PORTS], int pdcch_encode_msg(pdcch_t *q, dci_msg_t *msg, dci_location_t location, uint16_t rnti) {
uint32_t nsubframe, uint32_t cfi) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL) {
ret = LIBLTE_ERROR;
if (location.L < 4 &&
msg->nof_bits < DCI_MAX_BITS)
{
INFO("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n",
msg->nof_bits,
PDCCH_FORMAT_NOF_BITS(location.L),
location.ncce, location.L, rnti);
dci_encode(q, msg->data, &q->pdcch_e[72 * location.ncce], msg->nof_bits,
PDCCH_FORMAT_NOF_BITS(location.L), rnti);
ret = LIBLTE_SUCCESS;
} else {
fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d\n",
location.ncce, location.L, q->nof_cce);
}
}
return ret;
}
/** Converts the set of DCI messages encoded using the function pdcch_encode_msg()
* to symbols mapped to the subframe ready for transmission
*/
int pdcch_gen_symbols(pdcch_t *q, cf_t *slot_symbols[MAX_PORTS], uint32_t nsubframe, uint32_t cfi) {
int i; int i;
/* Set pointers for layermapping & precoding */ /* Set pointers for layermapping & precoding */
cf_t *x[MAX_LAYERS]; cf_t *x[MAX_LAYERS];
if (q != NULL && if (q != NULL &&
dci != NULL &&
slot_symbols != NULL && slot_symbols != NULL &&
nsubframe < 10 && nsubframe < 10 &&
cfi > 0 && cfi > 0 &&
@ -623,31 +551,6 @@ int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot_symbols[MAX_PORTS],
} }
memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports));
/* should add <NIL> elements? Or maybe random bits to facilitate power estimation */
bzero(q->pdcch_e, q->nof_bits);
/* Encode DCIs */
for (i = 0; i < dci->nof_dcis; i++) {
/* do some checks */
if (dci->msg[i].location.ncce + PDCCH_FORMAT_NOF_CCE(dci->msg[i].location.L)
> q->nof_cce || dci->msg[i].location.L > 3
|| dci->msg[i].location.nof_bits > DCI_MAX_BITS) {
fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d\n",
dci->msg[i].location.ncce, dci->msg[i].location.L, q->nof_cce);
return LIBLTE_ERROR;
}
INFO("Encoding DCI %d: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", 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(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);
}
scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 0, q->nof_bits); scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 0, q->nof_bits);
mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, q->nof_bits); mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, q->nof_bits);
@ -671,3 +574,4 @@ int pdcch_encode(pdcch_t *q, dci_t *dci, cf_t *slot_symbols[MAX_PORTS],
} }
} }

@ -81,9 +81,8 @@ int main(int argc, char **argv) {
printf("\n"); printf("\n");
dci_msg_type_t dci_type; dci_msg_type_t dci_type;
msg.location.rnti = SIRNTI; msg.nof_bits = len;
msg.location.nof_bits = len; if (dci_msg_get_type(&msg, &dci_type, nof_prb, SIRNTI, 1234)) {
if (dci_msg_get_type(&msg, &dci_type, nof_prb, 1234)) {
fprintf(stderr, "Can't obtain DCI message type\n"); fprintf(stderr, "Can't obtain DCI message type\n");
exit(-1); exit(-1);
} }

@ -56,7 +56,6 @@ cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS];
regs_t regs; regs_t regs;
lte_fft_t fft; lte_fft_t fft;
chest_t chest; chest_t chest;
dci_t dci_rx;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [vcfoe] -i input_file\n", prog); printf("Usage: %s [vcfoe] -i input_file\n", prog);
@ -180,8 +179,6 @@ int base_init() {
exit(-1); exit(-1);
} }
dci_init(&dci_rx, 10);
DEBUG("Memory init OK\n",0); DEBUG("Memory init OK\n",0);
return 0; return 0;
} }
@ -204,7 +201,6 @@ void base_free() {
chest_free(&chest); chest_free(&chest);
lte_fft_free(&fft); lte_fft_free(&fft);
dci_free(&dci_rx);
pdcch_free(&pdcch); pdcch_free(&pdcch);
regs_free(&regs); regs_free(&regs);
} }
@ -215,6 +211,9 @@ int main(int argc, char **argv) {
int nof_dcis; int nof_dcis;
int nof_frames; int nof_frames;
int ret; int ret;
dci_location_t locations[10];
uint32_t nof_locations;
dci_msg_t dci_msg;
if (argc < 3) { if (argc < 3) {
usage(argv[0]); usage(argv[0]);
@ -230,10 +229,11 @@ int main(int argc, char **argv) {
if (rnti == SIRNTI) { if (rnti == SIRNTI) {
INFO("Initializing common search space for SI-RNTI\n",0); INFO("Initializing common search space for SI-RNTI\n",0);
pdcch_init_search_si(&pdcch, cfi); nof_locations = pdcch_common_locations(&pdcch, locations, 10, cfi);
} else { } else {
// For ue-specific, generate locations for subframe 5
INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti); INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti);
pdcch_init_search_ue(&pdcch, rnti, cfi); nof_locations = pdcch_ue_locations(&pdcch, locations, 10, 5, cfi, rnti);
} }
ret = -1; ret = -1;
nof_frames = 0; nof_frames = 0;
@ -264,13 +264,22 @@ int main(int argc, char **argv) {
} }
} }
nof_dcis = pdcch_decode(&pdcch, fft_buffer, ce, &dci_rx, nof_frames%10, cfi); if (pdcch_extract_llr(&pdcch, fft_buffer, ce, nof_frames, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return -1;
}
nof_dcis = pdcch_decode_msg(&pdcch, &dci_msg, locations, nof_locations, Format1A, rnti);
if (nof_dcis < 0) {
fprintf(stderr, "Error decoding DCI messages\n");
return -1;
}
INFO("Received %d DCI messages\n", nof_dcis); INFO("Received %d DCI messages\n", nof_dcis);
for (i=0;i<nof_dcis;i++) { if (nof_dcis == 1) {
dci_msg_type_t type; dci_msg_type_t type;
if (dci_msg_get_type(&dci_rx.msg[i], &type, cell.nof_prb, 1234)) { if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, rnti, 1234)) {
fprintf(stderr, "Can't get DCI message type\n"); fprintf(stderr, "Can't get DCI message type\n");
exit(-1); exit(-1);
} }
@ -279,7 +288,7 @@ int main(int argc, char **argv) {
switch(type.type) { switch(type.type) {
case PDSCH_SCHED: case PDSCH_SCHED:
bzero(&ra_dl, sizeof(ra_pdsch_t)); bzero(&ra_dl, sizeof(ra_pdsch_t));
if (dci_msg_unpack_pdsch(&dci_rx.msg[i], &ra_dl, cell.nof_prb, rnti != SIRNTI)) { if (dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, rnti != SIRNTI)) {
fprintf(stderr, "Can't unpack PDSCH message\n"); fprintf(stderr, "Can't unpack PDSCH message\n");
} else { } else {
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);

@ -105,7 +105,8 @@ int test_dci_payload_size() {
int main(int argc, char **argv) { int main(int argc, char **argv) {
pdcch_t pdcch; pdcch_t pdcch;
dci_t dci_tx, dci_rx; dci_msg_t dci_tx[2], dci_rx[2];
dci_location_t dci_locations[2];
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
regs_t regs; regs_t regs;
int i, j; int i, j;
@ -113,6 +114,7 @@ int main(int argc, char **argv) {
int nof_re; int nof_re;
cf_t *slot_symbols[MAX_PORTS]; cf_t *slot_symbols[MAX_PORTS];
int nof_dcis; int nof_dcis;
int ret = -1; int ret = -1;
parse_args(argc, argv); parse_args(argc, argv);
@ -155,26 +157,32 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
dci_init(&dci_tx, 2); nof_dcis = 2;
bzero(&ra_dl, sizeof(ra_pdsch_t)); bzero(&ra_dl, sizeof(ra_pdsch_t));
ra_dl.harq_process = 0; ra_dl.harq_process = 0;
//ra_pdsch_set_mcs_index(&ra_dl, 6);
ra_pdsch_set_mcs(&ra_dl, QAM16, 5); ra_pdsch_set_mcs(&ra_dl, QAM16, 5);
ra_dl.ndi = 0; ra_dl.ndi = 0;
ra_dl.rv_idx = 0; ra_dl.rv_idx = 0;
ra_dl.alloc_type = alloc_type0; ra_dl.alloc_type = alloc_type0;
ra_dl.type0_alloc.rbg_bitmask = 0x5; ra_dl.type0_alloc.rbg_bitmask = 0x5;
dci_msg_pack_pdsch(&ra_dl, &dci_tx.msg[0], Format1, cell.nof_prb, false); dci_msg_pack_pdsch(&ra_dl, &dci_tx[0], Format1, cell.nof_prb, false);
dci_msg_candidate_set(&dci_tx.msg[0], 0, 0, 1234); dci_location_set(&dci_locations[0], 0, 0);
dci_tx.nof_dcis++;
ra_pdsch_set_mcs(&ra_dl, QAM16, 15); ra_pdsch_set_mcs(&ra_dl, QAM16, 15);
dci_msg_pack_pdsch(&ra_dl, &dci_tx.msg[1], Format1, cell.nof_prb, false); dci_msg_pack_pdsch(&ra_dl, &dci_tx[1], Format1, cell.nof_prb, false);
dci_msg_candidate_set(&dci_tx.msg[1], 0, 1, 1234); dci_location_set(&dci_locations[1], 0, 1);
dci_tx.nof_dcis++;
pdcch_reset(&pdcch);
pdcch_encode(&pdcch, &dci_tx, slot_symbols, 0, cfi); for (i=0;i<nof_dcis;i++) {
if (pdcch_encode_msg(&pdcch, &dci_tx[i], dci_locations[i], 1234+i)) {
goto quit;
}
}
if (pdcch_gen_symbols(&pdcch, slot_symbols, 0, cfi)) {
goto quit;
}
/* combine outputs */ /* combine outputs */
for (i = 1; i < cell.nof_ports; i++) { for (i = 1; i < cell.nof_ports; i++) {
@ -183,39 +191,26 @@ int main(int argc, char **argv) {
} }
} }
pdcch_init_search_ue(&pdcch, 1234, cfi); if (pdcch_extract_llr(&pdcch, slot_symbols[0], ce, 0, cfi)) {
goto quit;
dci_init(&dci_rx, 2); }
nof_dcis = pdcch_decode(&pdcch, slot_symbols[0], ce, &dci_rx, 0, cfi);
if (nof_dcis < 0) {
printf("Error decoding\n");
} else if (nof_dcis == dci_tx.nof_dcis) {
for (i = 0; i < nof_dcis; i++) {
if (dci_tx.msg[i].location.L != dci_rx.msg[i].location.L
|| dci_tx.msg[i].location.ncce != dci_rx.msg[i].location.ncce
|| dci_tx.msg[i].location.nof_bits != dci_rx.msg[i].location.nof_bits
|| dci_tx.msg[i].location.rnti != dci_rx.msg[i].location.rnti) {
printf("Error in DCI %d: Received location does not match\n", i);
dci_candidate_fprint(stdout, &dci_tx.msg[i].location);
dci_candidate_fprint(stdout, &dci_rx.msg[i].location);
goto quit;
}
if (memcmp(dci_tx.msg[i].data, dci_rx.msg[i].data, for (i=0;i<nof_dcis;i++) {
dci_tx.msg[i].location.nof_bits)) { if (pdcch_decode_msg(&pdcch, &dci_rx[i], dci_locations, 2, Format1, 1234+i) < 0) {
printf("Error in DCI %d: Received data does not match\n", i); goto quit;
goto quit; }
} }
for (i = 0; i < nof_dcis; i++) {
if (memcmp(dci_tx[i].data, dci_rx[i].data, dci_tx[i].nof_bits)) {
printf("Error in DCI %d: Received data does not match\n", i);
goto quit;
} }
} else {
printf("Transmitted %d DCIs but got %d\n", dci_tx.nof_dcis, nof_dcis);
goto quit;
} }
ret = 0; ret = 0;
quit: pdcch_free(&pdcch);
quit:
pdcch_free(&pdcch);
regs_free(&regs); regs_free(&regs);
dci_free(&dci_tx);
dci_free(&dci_rx);
for (i = 0; i < MAX_PORTS; i++) { for (i = 0; i < MAX_PORTS; i++) {
free(ce[i]); free(ce[i]);

@ -58,7 +58,6 @@ cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS];
regs_t regs; regs_t regs;
lte_fft_t fft; lte_fft_t fft;
chest_t chest; chest_t chest;
dci_t dci_rx;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [vcfoe] -i input_file\n", prog); printf("Usage: %s [vcfoe] -i input_file\n", prog);
@ -183,8 +182,6 @@ int base_init() {
exit(-1); exit(-1);
} }
dci_init(&dci_rx, 10);
if (pdsch_init(&pdsch, rnti, cell)) { if (pdsch_init(&pdsch, rnti, cell)) {
fprintf(stderr, "Error creating PDSCH object\n"); fprintf(stderr, "Error creating PDSCH object\n");
exit(-1); exit(-1);
@ -212,7 +209,6 @@ void base_free() {
chest_free(&chest); chest_free(&chest);
lte_fft_free(&fft); lte_fft_free(&fft);
dci_free(&dci_rx);
pdcch_free(&pdcch); pdcch_free(&pdcch);
pdsch_free(&pdsch); pdsch_free(&pdsch);
regs_free(&regs); regs_free(&regs);
@ -226,6 +222,9 @@ int main(int argc, char **argv) {
int nof_frames; int nof_frames;
int ret; int ret;
char *data; char *data;
dci_location_t locations[10];
uint32_t nof_locations;
dci_msg_t dci_msg;
data = malloc(10000); data = malloc(10000);
@ -243,11 +242,13 @@ int main(int argc, char **argv) {
if (rnti == SIRNTI) { if (rnti == SIRNTI) {
INFO("Initializing common search space for SI-RNTI\n",0); INFO("Initializing common search space for SI-RNTI\n",0);
pdcch_init_search_si(&pdcch, cfi); nof_locations = pdcch_common_locations(&pdcch, locations, 10, cfi);
} else { } else {
// For ue-specific, generate locations for subframe 5
INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti); INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti);
pdcch_init_search_ue(&pdcch, rnti, cfi); nof_locations = pdcch_ue_locations(&pdcch, locations, 10, 5, cfi, rnti);
} }
ret = -1; ret = -1;
nof_frames = 0; nof_frames = 0;
do { do {
@ -279,13 +280,19 @@ int main(int argc, char **argv) {
} }
} }
nof_dcis = pdcch_decode(&pdcch, fft_buffer, ce, &dci_rx, nof_frames%10, cfi); pdcch_extract_llr(&pdcch, fft_buffer, ce, nof_frames, cfi);
nof_dcis = pdcch_decode_msg(&pdcch, &dci_msg, locations, nof_locations, Format1A, rnti);
if (nof_dcis < 0) {
fprintf(stderr, "Error decoding DCI messages\n");
return -1;
}
INFO("Received %d DCI messages\n", nof_dcis); INFO("Received %d DCI messages\n", nof_dcis);
for (i=0;i<nof_dcis;i++) { if (nof_dcis == 1) {
dci_msg_type_t type; dci_msg_type_t type;
if (dci_msg_get_type(&dci_rx.msg[i], &type, cell.nof_prb, 1234)) { if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, rnti, 1234)) {
fprintf(stderr, "Can't get DCI message type\n"); fprintf(stderr, "Can't get DCI message type\n");
goto goout; goto goout;
} }
@ -294,7 +301,7 @@ int main(int argc, char **argv) {
switch(type.type) { switch(type.type) {
case PDSCH_SCHED: case PDSCH_SCHED:
bzero(&ra_dl, sizeof(ra_pdsch_t)); bzero(&ra_dl, sizeof(ra_pdsch_t));
if (dci_msg_unpack_pdsch(&dci_rx.msg[i], &ra_dl, cell.nof_prb, rnti != SIRNTI)) { if (dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, rnti != SIRNTI)) {
fprintf(stderr, "Can't unpack PDSCH message\n"); fprintf(stderr, "Can't unpack PDSCH message\n");
} else { } else {
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);

Loading…
Cancel
Save