Improved PDCCH candidate search interface. Switched FEC modules to uint32_t
This commit is contained in:
parent
5181b771fd
commit
0ebb0e7d00
|
@ -229,7 +229,8 @@ int main(int argc, char **argv) {
|
|||
int i, n;
|
||||
char *data;
|
||||
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
|
||||
if (argc < 3) {
|
||||
|
@ -279,7 +280,6 @@ int main(int argc, char **argv) {
|
|||
}
|
||||
#endif
|
||||
|
||||
dci_init(&dci_tx, 1);
|
||||
bzero(&ra_dl, sizeof(ra_pdsch_t));
|
||||
ra_dl.harq_process = 0;
|
||||
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.type0_alloc.rbg_bitmask = 0xffffffff;
|
||||
|
||||
dci_msg_pack_pdsch(&ra_dl, &dci_tx.msg[0], Format1, cell.nof_prb, false);
|
||||
dci_tx.nof_dcis++;
|
||||
|
||||
pdcch_init_search_ue(&pdcch, 1234, cfi);
|
||||
dci_msg_pack_pdsch(&ra_dl, &dci_msg, Format1, cell.nof_prb, false);
|
||||
|
||||
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);
|
||||
|
@ -299,6 +296,11 @@ int main(int argc, char **argv) {
|
|||
|
||||
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);
|
||||
if (!data) {
|
||||
perror("malloc");
|
||||
|
@ -331,11 +333,14 @@ int main(int argc, char **argv) {
|
|||
for (i=0;i<ra_dl.mcs.tbs;i++) {
|
||||
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);
|
||||
INFO("Setting DCI candidate L: %d nCCE: %d\n", pdcch.search_mode[2].candidates[0][sf_idx].L,
|
||||
pdcch.search_mode[2].candidates[0][sf_idx].ncce);
|
||||
pdcch_encode(&pdcch, &dci_tx, sf_symbols, sf_idx, cfi);
|
||||
|
||||
if (pdcch_encode_msg(&pdcch, &dci_msg, locations[sf_idx][0], 1234)) {
|
||||
fprintf(stderr, "Error encoding DCI message\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
||||
pdcch_gen_symbols(&pdcch, sf_symbols, sf_idx, cfi);
|
||||
|
||||
pdsch_encode(&pdsch, data, sf_symbols, sf_idx, ra_dl.mcs, &prb_alloc);
|
||||
|
||||
/* Transform to OFDM symbols */
|
||||
|
|
|
@ -88,7 +88,6 @@ float *tmp_plot;
|
|||
pbch_t pbch;
|
||||
pcfich_t pcfich;
|
||||
pdcch_t pdcch;
|
||||
dci_t dci_set;
|
||||
pdsch_t pdsch;
|
||||
regs_t regs;
|
||||
lte_fft_t fft;
|
||||
|
@ -286,8 +285,6 @@ int base_init(int nof_prb) {
|
|||
return -1;
|
||||
}
|
||||
|
||||
dci_init(&dci_set, 10);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
@ -401,6 +398,9 @@ int rx_run(cf_t *input, int sf_idx) {
|
|||
cf_t *input_decim;
|
||||
ra_pdsch_t ra_dl;
|
||||
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 */
|
||||
if (sampling_nof_prb > cell.nof_prb) {
|
||||
|
@ -427,25 +427,32 @@ int rx_run(cf_t *input, int sf_idx) {
|
|||
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);
|
||||
|
||||
dci_set.nof_dcis = 0;
|
||||
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++) {
|
||||
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);
|
||||
|
||||
if (nof_dcis == 1) {
|
||||
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");
|
||||
} 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()) {
|
||||
dci_msg_type_fprint(stdout, type);
|
||||
}
|
||||
switch(type.type) {
|
||||
case PDSCH_SCHED:
|
||||
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)) {
|
||||
fprintf(stderr, "Can't unpack PDSCH message\n");
|
||||
break;
|
||||
|
|
|
@ -34,13 +34,13 @@
|
|||
#include "liblte/config.h"
|
||||
|
||||
typedef struct LIBLTE_API {
|
||||
int R;
|
||||
int K;
|
||||
int poly[3];
|
||||
uint32_t R;
|
||||
uint32_t K;
|
||||
uint32_t poly[3];
|
||||
bool tail_biting;
|
||||
}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 */
|
||||
|
|
|
@ -33,8 +33,15 @@
|
|||
#define RX_NULL 10000
|
||||
#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_rx(float *input, int in_len, float *output, int out_len);
|
||||
LIBLTE_API int rm_conv_tx(char *input,
|
||||
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 */
|
||||
typedef struct
|
||||
|
|
|
@ -45,12 +45,24 @@ typedef struct LIBLTE_API {
|
|||
char *buffer;
|
||||
} 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 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_rx(rm_turbo_t *q, float *input, int in_len,
|
||||
float *output, int out_len, int rv_idx);
|
||||
|
||||
LIBLTE_API int rm_turbo_tx(rm_turbo_t *q,
|
||||
char *input,
|
||||
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 */
|
||||
typedef struct LIBLTE_API {
|
||||
|
|
|
@ -31,15 +31,15 @@
|
|||
#include "liblte/config.h"
|
||||
|
||||
typedef struct LIBLTE_API {
|
||||
int *forward;
|
||||
int *reverse;
|
||||
int max_long_cb;
|
||||
uint32_t *forward;
|
||||
uint32_t *reverse;
|
||||
uint32_t max_long_cb;
|
||||
} tc_interl_t;
|
||||
|
||||
LIBLTE_API int tc_interl_LTE_gen(tc_interl_t *h, int long_cb);
|
||||
LIBLTE_API int tc_interl_UMTS_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, 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);
|
||||
|
||||
#endif
|
||||
|
|
|
@ -37,13 +37,13 @@
|
|||
#define TOTALTAIL 12
|
||||
|
||||
typedef struct LIBLTE_API {
|
||||
int max_long_cb;
|
||||
uint32_t max_long_cb;
|
||||
tc_interl_t interl;
|
||||
} 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 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
|
||||
|
||||
|
|
|
@ -68,13 +68,25 @@ typedef struct LIBLTE_API {
|
|||
tc_interl_t interleaver;
|
||||
} tdec_t;
|
||||
|
||||
LIBLTE_API int tdec_init(tdec_t *h, int max_long_cb);
|
||||
LIBLTE_API int tdec_init(tdec_t * h,
|
||||
uint32_t max_long_cb);
|
||||
|
||||
LIBLTE_API void tdec_free(tdec_t * h);
|
||||
|
||||
LIBLTE_API int tdec_reset(tdec_t *h, int long_cb);
|
||||
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 void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations,
|
||||
int long_cb);
|
||||
LIBLTE_API int tdec_reset(tdec_t * h, uint32_t 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
|
||||
|
|
|
@ -38,21 +38,34 @@ typedef enum {
|
|||
|
||||
typedef struct LIBLTE_API{
|
||||
void *ptr;
|
||||
int R;
|
||||
int K;
|
||||
uint32_t R;
|
||||
uint32_t K;
|
||||
unsigned int framebits;
|
||||
bool tail_biting;
|
||||
int poly[3];
|
||||
int (*decode) (void*, unsigned char*, char*, int);
|
||||
uint32_t poly[3];
|
||||
int (*decode) (void*, uint8_t*, char*, uint32_t);
|
||||
void (*free) (void*);
|
||||
unsigned char *tmp;
|
||||
unsigned char *symbols_uc;
|
||||
}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 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 */
|
||||
|
|
|
@ -62,41 +62,26 @@ typedef enum {
|
|||
} dci_spec_t;
|
||||
|
||||
typedef struct LIBLTE_API {
|
||||
uint32_t nof_bits;
|
||||
uint32_t L; // Aggregation level
|
||||
uint32_t ncce; // Position of first CCE of the dci
|
||||
uint16_t rnti;
|
||||
} dci_candidate_t;
|
||||
} dci_location_t;
|
||||
|
||||
typedef struct LIBLTE_API {
|
||||
char data[DCI_MAX_BITS];
|
||||
dci_candidate_t location;
|
||||
uint32_t nof_bits;
|
||||
} 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 int dci_msg_candidate_set(dci_msg_t *msg,
|
||||
LIBLTE_API int dci_location_set(dci_location_t *c,
|
||||
uint32_t L,
|
||||
uint32_t nCCE,
|
||||
uint16_t rnti);
|
||||
|
||||
LIBLTE_API void dci_candidate_fprint(FILE *f,
|
||||
dci_candidate_t *q);
|
||||
uint32_t nCCE);
|
||||
|
||||
LIBLTE_API int dci_msg_get_type(dci_msg_t *msg,
|
||||
dci_msg_type_t *type,
|
||||
uint32_t nof_prb,
|
||||
uint16_t msg_rnti,
|
||||
uint16_t crnti);
|
||||
|
||||
LIBLTE_API void dci_msg_type_fprint(FILE *f,
|
||||
|
|
|
@ -44,21 +44,17 @@
|
|||
|
||||
typedef _Complex float cf_t;
|
||||
|
||||
#define PDCCH_NOF_SEARCH_MODES 3
|
||||
#define MAX_CANDIDATES 32
|
||||
#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
|
||||
|
||||
|
||||
typedef enum LIBLTE_API {
|
||||
SEARCH_NONE = 3, SEARCH_SI = 0, SEARCH_RA = 1, SEARCH_UE = 2
|
||||
SEARCH_UE, SEARCH_COMMON
|
||||
} 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 */
|
||||
typedef struct LIBLTE_API {
|
||||
|
@ -69,9 +65,6 @@ typedef struct LIBLTE_API {
|
|||
uint32_t nof_cce;
|
||||
uint32_t max_bits;
|
||||
|
||||
pdcch_search_t search_mode[PDCCH_NOF_SEARCH_MODES];
|
||||
pdcch_search_mode_t current_search_mode;
|
||||
|
||||
regs_t *regs;
|
||||
|
||||
/* buffers */
|
||||
|
@ -97,62 +90,47 @@ LIBLTE_API int pdcch_init(pdcch_t *q,
|
|||
LIBLTE_API void pdcch_free(pdcch_t *q);
|
||||
|
||||
|
||||
/* Encoding functions */
|
||||
LIBLTE_API int pdcch_encode(pdcch_t *q,
|
||||
dci_t *dci,
|
||||
cf_t *slot_symbols[MAX_PORTS],
|
||||
/* Encoding function */
|
||||
LIBLTE_API void pdcch_reset(pdcch_t *q);
|
||||
|
||||
LIBLTE_API int pdcch_encode_msg(pdcch_t *q,
|
||||
dci_msg_t *msg,
|
||||
dci_location_t location,
|
||||
uint16_t rnti);
|
||||
|
||||
LIBLTE_API int pdcch_gen_symbols(pdcch_t *q,
|
||||
cf_t *sf_symbols[MAX_PORTS],
|
||||
uint32_t nsubframe,
|
||||
uint32_t cfi);
|
||||
|
||||
/* Decoding functions */
|
||||
|
||||
/* There are two ways to decode the DCI messages:
|
||||
* a) call pdcch_set_search_si/ue/ra and then call pdcch_decode()
|
||||
* b) call pdcch_extract_llr() and then call pdcch_decode_si/ue/ra
|
||||
*/
|
||||
|
||||
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,
|
||||
cf_t *slot_symbols,
|
||||
cf_t *sf_symbols,
|
||||
cf_t *ce[MAX_PORTS],
|
||||
float *llr,
|
||||
uint32_t nsubframe,
|
||||
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 */
|
||||
LIBLTE_API 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);
|
||||
|
||||
/* Function for generation of UE-specific search space DCI locations */
|
||||
LIBLTE_API uint32_t pdcch_ue_locations(pdcch_t *q,
|
||||
dci_location_t *locations,
|
||||
uint32_t max_locations,
|
||||
uint32_t nsubframe,
|
||||
uint32_t cfi,
|
||||
uint16_t rnti);
|
||||
|
||||
/* Function for generation of common search space DCI locations */
|
||||
LIBLTE_API uint32_t pdcch_common_locations(pdcch_t *q,
|
||||
dci_location_t *locations,
|
||||
uint32_t max_locations,
|
||||
uint32_t cfi);
|
||||
|
||||
LIBLTE_API void pdcch_set_search_si(pdcch_t *q);
|
||||
|
||||
LIBLTE_API int pdcch_decode_si(pdcch_t *q,
|
||||
float *llr,
|
||||
dci_t *dci);
|
||||
|
||||
LIBLTE_API int pdcch_init_search_ue(pdcch_t *q,
|
||||
uint16_t c_rnti,
|
||||
uint32_t cfi);
|
||||
|
||||
LIBLTE_API void pdcch_set_search_ue(pdcch_t *q);
|
||||
|
||||
LIBLTE_API int pdcch_decode_ue(pdcch_t *q,
|
||||
float *llr,
|
||||
dci_t *dci,
|
||||
uint32_t nsubframe);
|
||||
|
||||
LIBLTE_API int pdcch_init_search_ra(pdcch_t *q,
|
||||
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
|
||||
|
|
|
@ -28,15 +28,16 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include "liblte/phy/fec/convcoder.h"
|
||||
#include "parity.h"
|
||||
|
||||
int convcoder_encode(convcoder_t *q, char *input, char *output, int frame_length) {
|
||||
unsigned int sr;
|
||||
int i,j;
|
||||
int len = q->tail_biting ? frame_length : (frame_length + q->K - 1);
|
||||
int convcoder_encode(convcoder_t *q, char *input, char *output, uint32_t frame_length) {
|
||||
uint32_t sr;
|
||||
uint32_t i,j;
|
||||
uint32_t len = q->tail_biting ? frame_length : (frame_length + q->K - 1);
|
||||
|
||||
if (q->tail_biting) {
|
||||
sr = 0;
|
||||
|
|
|
@ -4,15 +4,16 @@
|
|||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
unsigned char Partab[256];
|
||||
int P_init;
|
||||
uint8_t Partab[256];
|
||||
uint32_t P_init;
|
||||
|
||||
/* Create 256-entry odd-parity lookup table
|
||||
* Needed only on non-ia32 machines
|
||||
*/
|
||||
void partab_init(void) {
|
||||
int i, cnt, ti;
|
||||
uint32_t i, cnt, ti;
|
||||
|
||||
/* Initialize parity lookup table */
|
||||
for (i = 0; i < 256; i++) {
|
||||
|
|
|
@ -10,16 +10,16 @@
|
|||
|
||||
/* Determine parity of argument: 1 = odd, 0 = even */
|
||||
#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));
|
||||
return x;
|
||||
}
|
||||
#else
|
||||
void partab_init();
|
||||
|
||||
static inline int parityb(unsigned char x){
|
||||
extern unsigned char Partab[256];
|
||||
extern int P_init;
|
||||
static inline uint32_t parityb(uint8_t x){
|
||||
extern uint8_t Partab[256];
|
||||
extern uint32_t P_init;
|
||||
if(!P_init){
|
||||
partab_init();
|
||||
}
|
||||
|
@ -28,7 +28,7 @@ static inline int parityb(unsigned char x){
|
|||
#endif
|
||||
|
||||
|
||||
static inline int parity(int x){
|
||||
static inline uint32_t parity(int x){
|
||||
/* Fold down to one byte */
|
||||
x ^= (x >> 16);
|
||||
x ^= (x >> 8);
|
||||
|
|
|
@ -27,25 +27,27 @@
|
|||
|
||||
#include <string.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "liblte/phy/fec/rm_conv.h"
|
||||
|
||||
#define NCOLS 32
|
||||
#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 };
|
||||
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,
|
||||
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];
|
||||
int nrows, ndummy, K_p;
|
||||
|
||||
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) {
|
||||
fprintf(stderr, "Input too large. Max input length is %d\n",
|
||||
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.
|
||||
* 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 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];
|
||||
|
||||
nrows = (int) (out_len / 3 - 1) / NCOLS + 1;
|
||||
nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1;
|
||||
if (nrows > NROWS_MAX) {
|
||||
fprintf(stderr, "Output too large. Max output length is %d\n",
|
||||
3 * NCOLS * NROWS_MAX);
|
||||
|
|
|
@ -30,16 +30,17 @@
|
|||
#include <math.h>
|
||||
#include <stdbool.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "liblte/phy/fec/rm_turbo.h"
|
||||
|
||||
#define NCOLS 32
|
||||
#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 };
|
||||
|
||||
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 = malloc(buffer_len * sizeof(float));
|
||||
if (!q->buffer) {
|
||||
|
@ -60,15 +61,16 @@ void rm_turbo_free(rm_turbo_t *q) {
|
|||
*
|
||||
* 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 out_len, int rv_idx) {
|
||||
int rm_turbo_tx(rm_turbo_t *q, char *input, uint32_t in_len, char *output,
|
||||
uint32_t out_len, uint32_t rv_idx) {
|
||||
|
||||
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;
|
||||
if (3 * K_p > q->buffer_len) {
|
||||
fprintf(stderr,
|
||||
|
@ -116,7 +118,7 @@ int rm_turbo_tx(rm_turbo_t *q, char *input, int in_len, char *output,
|
|||
N_cb = 3 * K_p; // TODO: Soft buffer size limitation
|
||||
|
||||
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;
|
||||
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.
|
||||
* 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 out_len, int rv_idx) {
|
||||
int rm_turbo_rx(rm_turbo_t *q, float *input, uint32_t in_len, float *output,
|
||||
uint32_t out_len, uint32_t rv_idx) {
|
||||
|
||||
int nrows, ndummy, K_p, k0, N_cb, jp, kidx;
|
||||
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;
|
||||
|
||||
nrows = (int) (out_len / 3 - 1) / NCOLS + 1;
|
||||
nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1;
|
||||
K_p = nrows * NCOLS;
|
||||
if (3 * K_p > q->buffer_len) {
|
||||
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 */
|
||||
N_cb = 3 * K_p; // TODO: Soft buffer size limitation
|
||||
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;
|
||||
j = 0;
|
||||
|
@ -185,7 +187,7 @@ int rm_turbo_rx(rm_turbo_t *q, float *input, int in_len, float *output,
|
|||
isdummy = true;
|
||||
}
|
||||
} 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;
|
||||
if ((kidx - ndummy) < 0) {
|
||||
isdummy = true;
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "liblte/phy/common/phy_common.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,
|
||||
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,
|
||||
|
@ -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,
|
||||
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,
|
||||
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,
|
||||
|
@ -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,
|
||||
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 cb_table_idx, f1, f2;
|
||||
unsigned long long i, j;
|
||||
int tc_interl_LTE_gen(tc_interl_t *h, uint32_t long_cb) {
|
||||
uint32_t cb_table_idx, f1, f2;
|
||||
uint64_t i, j;
|
||||
|
||||
if (long_cb > h->max_long_cb) {
|
||||
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;
|
||||
for (i = 1; i < long_cb; i++) {
|
||||
j = (f1 * i + f2 * i * i) % (long_cb);
|
||||
h->forward[i] = j;
|
||||
h->reverse[j] = i;
|
||||
h->forward[i] = (uint32_t) j;
|
||||
h->reverse[j] = (uint32_t) i;
|
||||
}
|
||||
return 0;
|
||||
|
||||
|
|
|
@ -28,13 +28,14 @@
|
|||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <strings.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "liblte/phy/fec/tc_interl.h"
|
||||
#include "liblte/phy/fec/turbocoder.h"
|
||||
|
||||
#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,
|
||||
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;
|
||||
h->forward = malloc(sizeof(int) * max_long_cb);
|
||||
h->forward = malloc(sizeof(uint32_t) * max_long_cb);
|
||||
if (!h->forward) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
}
|
||||
h->reverse = malloc(sizeof(int) * max_long_cb);
|
||||
h->reverse = malloc(sizeof(uint32_t) * max_long_cb);
|
||||
if (!h->reverse) {
|
||||
perror("malloc");
|
||||
goto clean_exit;
|
||||
|
@ -83,17 +84,17 @@ void tc_interl_free(tc_interl_t *h) {
|
|||
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;
|
||||
int res, prim, aux;
|
||||
int kp, k;
|
||||
int *per, *desper;
|
||||
unsigned char v;
|
||||
unsigned short p;
|
||||
unsigned short s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS];
|
||||
unsigned short U[MAX_COLS * MAX_ROWS];
|
||||
int M_Rows, M_Cols, M_long;
|
||||
uint32_t i, j;
|
||||
uint32_t res, prim, aux;
|
||||
uint32_t kp, k;
|
||||
uint32_t *per, *desper;
|
||||
uint8_t v;
|
||||
uint16_t p;
|
||||
uint16_t s[MAX_COLS], q[MAX_ROWS], r[MAX_ROWS], T[MAX_ROWS];
|
||||
uint16_t U[MAX_COLS * MAX_ROWS];
|
||||
uint32_t M_Rows, M_Cols, M_long;
|
||||
|
||||
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) {
|
||||
int r = 1;
|
||||
uint32_t mcd(uint32_t x, uint32_t y) {
|
||||
uint32_t r = 1;
|
||||
|
||||
while (r) {
|
||||
r = x % y;
|
||||
|
|
|
@ -26,12 +26,14 @@
|
|||
*/
|
||||
|
||||
|
||||
#include "liblte/phy/fec/turbocoder.h"
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include "liblte/phy/fec/turbocoder.h"
|
||||
|
||||
#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)) {
|
||||
return -1;
|
||||
|
@ -45,13 +47,13 @@ void tcod_free(tcod_t *h) {
|
|||
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;
|
||||
int i, k = 0, j;
|
||||
uint32_t i, k = 0, j;
|
||||
char bit;
|
||||
char in, out;
|
||||
int *per;
|
||||
uint32_t *per;
|
||||
|
||||
if (long_cb > h->max_long_cb) {
|
||||
fprintf(stderr, "Turbo coder initiated for max_long_cb=%d\n",
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
|
||||
#include <stdio.h>
|
||||
#include <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
#include <strings.h>
|
||||
|
||||
|
@ -38,13 +39,13 @@
|
|||
* 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 x, y, xy;
|
||||
int k;
|
||||
int end = long_cb + RATE;
|
||||
uint32_t end = long_cb + RATE;
|
||||
llr_t *beta = s->beta;
|
||||
int i;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < 8; 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,
|
||||
int long_cb) {
|
||||
uint32_t long_cb) {
|
||||
llr_t m_b[8], new[8], old[8], max1[8], max0[8];
|
||||
llr_t m1, m0;
|
||||
llr_t x, y, xy;
|
||||
llr_t out;
|
||||
int k;
|
||||
int end = long_cb;
|
||||
uint32_t k;
|
||||
uint32_t end = long_cb;
|
||||
llr_t *beta = s->beta;
|
||||
int i;
|
||||
uint32_t i;
|
||||
|
||||
old[0] = 0;
|
||||
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,
|
||||
int long_cb) {
|
||||
int k;
|
||||
uint32_t long_cb) {
|
||||
uint32_t k;
|
||||
|
||||
h->beta[(long_cb + TAIL) * NUMSTATES] = 0;
|
||||
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
|
||||
*
|
||||
************************************************/
|
||||
int tdec_init(tdec_t *h, int max_long_cb) {
|
||||
int tdec_init(tdec_t *h, uint32_t max_long_cb) {
|
||||
int ret = -1;
|
||||
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;
|
||||
|
||||
|
@ -256,8 +257,8 @@ void tdec_free(tdec_t *h) {
|
|||
bzero(h, sizeof(tdec_t));
|
||||
}
|
||||
|
||||
void tdec_iteration(tdec_t *h, llr_t *input, int long_cb) {
|
||||
int i;
|
||||
void tdec_iteration(tdec_t *h, llr_t *input, uint32_t long_cb) {
|
||||
uint32_t i;
|
||||
|
||||
// Prepare systematic and parity bits for MAP DEC #1
|
||||
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);
|
||||
if (long_cb > h->max_long_cb) {
|
||||
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);
|
||||
}
|
||||
|
||||
void tdec_decision(tdec_t *h, char *output, int long_cb) {
|
||||
int i;
|
||||
void tdec_decision(tdec_t *h, char *output, uint32_t long_cb) {
|
||||
uint32_t i;
|
||||
for (i = 0; i < long_cb; i++) {
|
||||
output[i] = (h->llr2[h->interleaver.reverse[i]] > 0) ? 1 : 0;
|
||||
}
|
||||
}
|
||||
|
||||
void tdec_run_all(tdec_t *h, llr_t *input, char *output, int nof_iterations,
|
||||
int long_cb) {
|
||||
int iter = 0;
|
||||
void tdec_run_all(tdec_t *h, llr_t *input, char *output, uint32_t nof_iterations,
|
||||
uint32_t long_cb) {
|
||||
uint32_t iter = 0;
|
||||
|
||||
tdec_reset(h, long_cb);
|
||||
|
||||
|
|
|
@ -27,6 +27,8 @@
|
|||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
|
@ -38,11 +40,11 @@
|
|||
|
||||
#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;
|
||||
int i;
|
||||
uint32_t i;
|
||||
|
||||
int best_state;
|
||||
uint32_t best_state;
|
||||
|
||||
if (frame_length > q->framebits) {
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
if (frame_length > q->framebits) {
|
||||
|
@ -113,7 +115,7 @@ void free39(void *o) {
|
|||
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->R = 3;
|
||||
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->R = 3;
|
||||
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 max_frame_length, bool tail_bitting) {
|
||||
int viterbi_init(viterbi_t *q, viterbi_type_t type, uint32_t poly[3],
|
||||
uint32_t max_frame_length, bool tail_bitting) {
|
||||
switch (type) {
|
||||
case viterbi_37:
|
||||
return init37(q, poly, max_frame_length, tail_bitting);
|
||||
|
@ -191,8 +193,8 @@ void viterbi_free(viterbi_t *q) {
|
|||
}
|
||||
|
||||
/* symbols are real-valued */
|
||||
int viterbi_decode_f(viterbi_t *q, float *symbols, char *data, int frame_length) {
|
||||
int len;
|
||||
int viterbi_decode_f(viterbi_t *q, float *symbols, char *data, uint32_t frame_length) {
|
||||
uint32_t len;
|
||||
if (frame_length > q->framebits) {
|
||||
fprintf(stderr, "Initialized decoder for max frame length %d bits\n",
|
||||
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);
|
||||
}
|
||||
|
||||
int viterbi_decode_uc(viterbi_t *q, unsigned char *symbols, char *data,
|
||||
int frame_length) {
|
||||
int viterbi_decode_uc(viterbi_t *q, uint8_t *symbols, char *data,
|
||||
uint32_t frame_length) {
|
||||
return q->decode(q, symbols, data, frame_length);
|
||||
}
|
||||
|
||||
int viterbi_initialize(viterbi_hl* h) {
|
||||
int poly[3];
|
||||
uint32_t poly[3];
|
||||
viterbi_type_t type;
|
||||
if (h->init.rate == 2) {
|
||||
if (h->init.constraint_length == 7) {
|
||||
|
@ -243,7 +245,7 @@ int viterbi_initialize(viterbi_hl* h) {
|
|||
poly[0] = h->init.generator_0;
|
||||
poly[1] = h->init.generator_1;
|
||||
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);
|
||||
}
|
||||
|
||||
|
|
|
@ -27,8 +27,20 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
void *create_viterbi37_port(int polys[3], int len);
|
||||
int init_viterbi37_port(void *p, int starting_state);
|
||||
int chainback_viterbi37_port(void *p, char *data, unsigned int nbits, unsigned int endstate);
|
||||
void *create_viterbi37_port(uint32_t polys[3],
|
||||
uint32_t len);
|
||||
|
||||
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);
|
||||
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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
|
||||
#include <memory.h>
|
||||
#include "viterbi37.h"
|
||||
#include "parity.h"
|
||||
|
@ -30,9 +32,9 @@ struct v37 {
|
|||
};
|
||||
|
||||
/* 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;
|
||||
int i;
|
||||
uint32_t i;
|
||||
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
@ -48,8 +50,8 @@ int init_viterbi37_port(void *p, int starting_state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void set_viterbi37_polynomial_port(int polys[3]) {
|
||||
int state;
|
||||
void set_viterbi37_polynomial_port(uint32_t polys[3]) {
|
||||
uint32_t state;
|
||||
|
||||
for (state = 0; state < 32; 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 */
|
||||
void *create_viterbi37_port(int polys[3], int len) {
|
||||
void *create_viterbi37_port(uint32_t polys[3], uint32_t len) {
|
||||
struct v37 *vp;
|
||||
|
||||
set_viterbi37_polynomial_port(polys);
|
||||
|
@ -82,8 +84,8 @@ void *create_viterbi37_port(int polys[3], int len) {
|
|||
|
||||
/* Viterbi chainback */
|
||||
int chainback_viterbi37_port(void *p, char *data, /* Decoded output data */
|
||||
unsigned int nbits, /* Number of data bits */
|
||||
unsigned int endstate) { /* Terminal encoder state */
|
||||
uint32_t nbits, /* Number of data bits */
|
||||
uint32_t endstate) { /* Terminal encoder state */
|
||||
struct v37 *vp = p;
|
||||
decision_t *d;
|
||||
|
||||
|
@ -145,18 +147,18 @@ unsigned int metric,m0,m1,decision;\
|
|||
* 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;
|
||||
decision_t *d;
|
||||
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
int k=0;
|
||||
uint32_t k=0;
|
||||
d = (decision_t *) vp->dp;
|
||||
while (nbits--) {
|
||||
void *tmp;
|
||||
unsigned char sym0, sym1, sym2;
|
||||
int i;
|
||||
uint8_t sym0, sym1, sym2;
|
||||
uint32_t i;
|
||||
|
||||
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;
|
||||
}
|
||||
if (best_state) {
|
||||
int i, bst=0;
|
||||
unsigned int minmetric=UINT_MAX;
|
||||
uint32_t i, bst=0;
|
||||
uint32_t minmetric=UINT_MAX;
|
||||
for (i=0;i<64;i++) {
|
||||
if (vp->old_metrics->w[i] < minmetric) {
|
||||
bst = i;
|
||||
|
|
|
@ -27,10 +27,19 @@
|
|||
|
||||
#include <stdbool.h>
|
||||
|
||||
void *create_viterbi39_port(int polys[3], int len);
|
||||
int init_viterbi39_port(void *p, int starting_state);
|
||||
int chainback_viterbi39_port(void *p, char *data, /* Decoded output data */
|
||||
unsigned int nbits, /* Number of data bits */
|
||||
unsigned int endstate);
|
||||
void *create_viterbi39_port(uint32_t polys[3],
|
||||
uint32_t len);
|
||||
|
||||
int init_viterbi39_port(void *p,
|
||||
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);
|
||||
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 <stdlib.h>
|
||||
#include <stdint.h>
|
||||
#include <memory.h>
|
||||
#include "viterbi39.h"
|
||||
#include "parity.h"
|
||||
|
@ -29,9 +30,9 @@ struct v39 {
|
|||
};
|
||||
|
||||
/* 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;
|
||||
int i;
|
||||
uint32_t i;
|
||||
|
||||
if (p == NULL)
|
||||
return -1;
|
||||
|
@ -45,8 +46,8 @@ int init_viterbi39_port(void *p, int starting_state) {
|
|||
return 0;
|
||||
}
|
||||
|
||||
void set_viterbi39_polynomial_port(int polys[3]) {
|
||||
int state;
|
||||
void set_viterbi39_polynomial_port(uint32_t polys[3]) {
|
||||
uint32_t state;
|
||||
|
||||
for (state = 0; state < 128; 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 */
|
||||
void *create_viterbi39_port(int polys[3], int len) {
|
||||
void *create_viterbi39_port(uint32_t polys[3], uint32_t len) {
|
||||
struct v39 *vp;
|
||||
|
||||
set_viterbi39_polynomial_port(polys);
|
||||
|
@ -79,8 +80,8 @@ void *create_viterbi39_port(int polys[3], int len) {
|
|||
|
||||
/* Viterbi chainback */
|
||||
int chainback_viterbi39_port(void *p, char *data, /* Decoded output data */
|
||||
unsigned int nbits, /* Number of data bits */
|
||||
unsigned int endstate) { /* Terminal encoder state */
|
||||
uint32_t nbits, /* Number of data bits */
|
||||
uint32_t endstate) { /* Terminal encoder state */
|
||||
struct v39 *vp = p;
|
||||
decision_t *d;
|
||||
|
||||
|
@ -140,7 +141,7 @@ unsigned int metric,m0,m1,decision;\
|
|||
* 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;
|
||||
decision_t *d;
|
||||
|
||||
|
@ -150,8 +151,8 @@ int update_viterbi39_blk_port(void *p, unsigned char *syms, int nbits) {
|
|||
d = (decision_t *) vp->dp;
|
||||
while (nbits--) {
|
||||
void *tmp;
|
||||
unsigned char sym0, sym1, sym2;
|
||||
int i;
|
||||
uint8_t sym0, sym1, sym2;
|
||||
uint32_t i;
|
||||
|
||||
for (i = 0; i < 8; i++)
|
||||
d->w[i] = 0;
|
||||
|
|
|
@ -41,9 +41,9 @@
|
|||
|
||||
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;
|
||||
unsigned int seed = 0;
|
||||
uint32_t seed = 0;
|
||||
int K = -1;
|
||||
|
||||
#define MAX_ITERATIONS 4
|
||||
|
@ -127,16 +127,16 @@ void output_matlab(float ber[MAX_ITERATIONS][SNR_POINTS], int snr_points) {
|
|||
}
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
int frame_cnt;
|
||||
uint32_t frame_cnt;
|
||||
float *llr;
|
||||
unsigned char *llr_c;
|
||||
char *data_tx, *data_rx, *symbols;
|
||||
int i, j;
|
||||
uint32_t i, j;
|
||||
float var[SNR_POINTS];
|
||||
int snr_points;
|
||||
uint32_t snr_points;
|
||||
float ber[MAX_ITERATIONS][SNR_POINTS];
|
||||
unsigned int errors[100];
|
||||
int coded_length;
|
||||
uint32_t errors[100];
|
||||
uint32_t coded_length;
|
||||
struct timeval tdata[3];
|
||||
float mean_usec;
|
||||
tdec_t tdec;
|
||||
|
@ -247,7 +247,7 @@ int main(int argc, char **argv) {
|
|||
/* decoder */
|
||||
tdec_reset(&tdec, frame_length);
|
||||
|
||||
int t;
|
||||
uint32_t t;
|
||||
if (nof_iterations == -1) {
|
||||
t = MAX_ITERATIONS;
|
||||
} else {
|
||||
|
|
|
@ -40,42 +40,20 @@
|
|||
#include "liblte/phy/utils/vector.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) {
|
||||
if (L >= 0 && L <= 3) {
|
||||
msg->location.L = L;
|
||||
int dci_location_set(dci_location_t *c, uint32_t L, uint32_t nCCE) {
|
||||
if (L <= 3) {
|
||||
c->L = L;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid L %d\n", L);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
if (nCCE >= 0 && nCCE <= 87) {
|
||||
msg->location.ncce = nCCE;
|
||||
if (nCCE <= 87) {
|
||||
c->ncce = nCCE;
|
||||
} else {
|
||||
fprintf(stderr, "Invalid nCCE %d\n", nCCE);
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
msg->location.rnti = rnti;
|
||||
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) {
|
||||
*y++ = 0;
|
||||
}
|
||||
msg->location.nof_bits = (y - msg->data);
|
||||
msg->nof_bits = (y - msg->data);
|
||||
return LIBLTE_SUCCESS;
|
||||
}
|
||||
/* 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;
|
||||
|
||||
/* 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");
|
||||
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) {
|
||||
*y++ = 0;
|
||||
}
|
||||
msg->location.nof_bits = (y - msg->data);
|
||||
msg->nof_bits = (y - msg->data);
|
||||
|
||||
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;
|
||||
|
||||
/* 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");
|
||||
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) {
|
||||
*y++ = 0;
|
||||
}
|
||||
msg->location.nof_bits = (y - msg->data);
|
||||
msg->nof_bits = (y - msg->data);
|
||||
|
||||
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;
|
||||
|
||||
/* 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");
|
||||
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);
|
||||
|
||||
msg->location.nof_bits = (y - msg->data);
|
||||
msg->nof_bits = (y - msg->data);
|
||||
|
||||
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 */
|
||||
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");
|
||||
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.mod = QPSK;
|
||||
|
||||
msg->location.nof_bits = (y - msg->data);
|
||||
msg->nof_bits = (y - msg->data);
|
||||
|
||||
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,
|
||||
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);
|
||||
} 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);
|
||||
} 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);
|
||||
} else {
|
||||
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,
|
||||
uint16_t crnti) {
|
||||
if (msg->location.nof_bits == dci_format_sizeof(Format0, nof_prb)
|
||||
uint16_t msg_rnti, uint16_t crnti) {
|
||||
if (msg->nof_bits == dci_format_sizeof(Format0, nof_prb)
|
||||
&& !msg->data[0]) {
|
||||
type->type = PUSCH_SCHED;
|
||||
type->format = Format0;
|
||||
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->format = Format1;
|
||||
return LIBLTE_SUCCESS;
|
||||
} else if (msg->location.nof_bits == dci_format_sizeof(Format1A, nof_prb)) {
|
||||
if (msg->location.rnti == crnti) {
|
||||
} else if (msg->nof_bits == dci_format_sizeof(Format1A, nof_prb)) {
|
||||
if (msg_rnti == crnti) {
|
||||
type->type = RA_PROC_PDCCH;
|
||||
type->format = Format1A;
|
||||
} 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;
|
||||
}
|
||||
return LIBLTE_SUCCESS;
|
||||
} else if (msg->location.nof_bits == dci_format_sizeof(Format1C, nof_prb)) {
|
||||
if (msg->location.rnti == MRNTI) {
|
||||
} else if (msg->nof_bits == dci_format_sizeof(Format1C, nof_prb)) {
|
||||
if (msg_rnti == MRNTI) {
|
||||
type->type = MCCH_CHANGE;
|
||||
type->format = Format1C;
|
||||
} else {
|
||||
|
|
|
@ -144,7 +144,7 @@ int pbch_init(pbch_t *q, lte_cell_t cell) {
|
|||
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)) {
|
||||
goto clean;
|
||||
}
|
||||
|
|
|
@ -46,173 +46,11 @@
|
|||
#define PDCCH_FORMAT_NOF_REGS(i) ((1<<i)*9)
|
||||
#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)
|
||||
|
||||
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) {
|
||||
q->nof_regs = (regs_pdcch_nregs(q->regs, cfi) / 9) * 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 */
|
||||
int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
|
||||
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));
|
||||
q->cell = cell;
|
||||
q->regs = regs;
|
||||
q->current_search_mode = SEARCH_NONE;
|
||||
|
||||
/* 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)) {
|
||||
goto clean;
|
||||
}
|
||||
|
@ -337,13 +175,97 @@ void pdcch_free(pdcch_t *q) {
|
|||
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
|
||||
*
|
||||
* Returns XOR between parity and remainder bits
|
||||
*
|
||||
* 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)];
|
||||
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)
|
||||
{
|
||||
|
||||
if (VERBOSE_ISDEBUG()) {
|
||||
vec_fprint_f(stdout, e, E);
|
||||
}
|
||||
|
||||
/* unrate matching */
|
||||
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,
|
||||
dci_msg_t *msg) {
|
||||
/** Tries to decode a DCI message from the LLRs stored in the pdcch_t structure by the function
|
||||
* pdcch_extract_llr(). This function can be called multiple times.
|
||||
* The decoded message is stored in msg. Up to nof_locations are tried from the array of dci_locations_t
|
||||
* pointed by locations. The CRC is checked agains the RNTI parameter.
|
||||
*
|
||||
* 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;
|
||||
INFO("Trying Candidate: Nbits: %d, E: %3d, nCCE: %d, L: %d, RNTI: 0x%x\n",
|
||||
c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, c->rnti);
|
||||
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,
|
||||
PDCCH_FORMAT_NOF_BITS(c->L), c->nof_bits, &crc_res)) {
|
||||
i = 0;
|
||||
do {
|
||||
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 (dci_decode(q, &q->pdcch_llr[72 * locations[i].ncce], msg->data,
|
||||
PDCCH_FORMAT_NOF_BITS(locations[i].L), nof_bits, &crc_res) != LIBLTE_SUCCESS) {
|
||||
return LIBLTE_ERROR;
|
||||
}
|
||||
|
||||
if (c->rnti == crc_res) {
|
||||
memcpy(&msg->location, c, sizeof(dci_candidate_t));
|
||||
INFO("FOUND Candidate: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n",
|
||||
c->nof_bits, PDCCH_FORMAT_NOF_BITS(c->L), c->ncce, c->L, c->rnti);
|
||||
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_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
int pdcch_extract_llr(pdcch_t *q, cf_t *slot_symbols, cf_t *ce[MAX_PORTS],
|
||||
float *llr, uint32_t nsubframe, uint32_t cfi) {
|
||||
/** Extracts the LLRs from the subframe symbols (demodulation) and stores them in the pdcch_t structure.
|
||||
* 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 */
|
||||
int i;
|
||||
uint32_t i;
|
||||
cf_t *x[MAX_LAYERS];
|
||||
|
||||
if (q != NULL &&
|
||||
llr != NULL &&
|
||||
slot_symbols != NULL &&
|
||||
nsubframe < 10 &&
|
||||
cfi > 0 &&
|
||||
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));
|
||||
|
||||
/* 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) {
|
||||
fprintf(stderr, "Expected %d PDCCH symbols but got %d 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 */
|
||||
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;
|
||||
} else {
|
||||
}
|
||||
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) {
|
||||
int i;
|
||||
static void crc_set_mask_rnti(char *crc, uint16_t rnti) {
|
||||
uint32_t i;
|
||||
char mask[16];
|
||||
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
|
||||
* 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) {
|
||||
convcoder_t encoder;
|
||||
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],
|
||||
uint32_t nsubframe, uint32_t cfi) {
|
||||
int pdcch_encode_msg(pdcch_t *q, dci_msg_t *msg, dci_location_t location, uint16_t rnti) {
|
||||
|
||||
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;
|
||||
/* Set pointers for layermapping & precoding */
|
||||
cf_t *x[MAX_LAYERS];
|
||||
|
||||
if (q != NULL &&
|
||||
dci != NULL &&
|
||||
slot_symbols != NULL &&
|
||||
nsubframe < 10 &&
|
||||
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));
|
||||
|
||||
/* 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);
|
||||
|
||||
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");
|
||||
|
||||
dci_msg_type_t dci_type;
|
||||
msg.location.rnti = SIRNTI;
|
||||
msg.location.nof_bits = len;
|
||||
if (dci_msg_get_type(&msg, &dci_type, nof_prb, 1234)) {
|
||||
msg.nof_bits = len;
|
||||
if (dci_msg_get_type(&msg, &dci_type, nof_prb, SIRNTI, 1234)) {
|
||||
fprintf(stderr, "Can't obtain DCI message type\n");
|
||||
exit(-1);
|
||||
}
|
||||
|
|
|
@ -56,7 +56,6 @@ cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS];
|
|||
regs_t regs;
|
||||
lte_fft_t fft;
|
||||
chest_t chest;
|
||||
dci_t dci_rx;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [vcfoe] -i input_file\n", prog);
|
||||
|
@ -180,8 +179,6 @@ int base_init() {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
dci_init(&dci_rx, 10);
|
||||
|
||||
DEBUG("Memory init OK\n",0);
|
||||
return 0;
|
||||
}
|
||||
|
@ -204,7 +201,6 @@ void base_free() {
|
|||
chest_free(&chest);
|
||||
lte_fft_free(&fft);
|
||||
|
||||
dci_free(&dci_rx);
|
||||
pdcch_free(&pdcch);
|
||||
regs_free(®s);
|
||||
}
|
||||
|
@ -215,6 +211,9 @@ int main(int argc, char **argv) {
|
|||
int nof_dcis;
|
||||
int nof_frames;
|
||||
int ret;
|
||||
dci_location_t locations[10];
|
||||
uint32_t nof_locations;
|
||||
dci_msg_t dci_msg;
|
||||
|
||||
if (argc < 3) {
|
||||
usage(argv[0]);
|
||||
|
@ -230,10 +229,11 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (rnti == SIRNTI) {
|
||||
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 {
|
||||
// For ue-specific, generate locations for subframe 5
|
||||
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;
|
||||
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);
|
||||
|
||||
for (i=0;i<nof_dcis;i++) {
|
||||
if (nof_dcis == 1) {
|
||||
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");
|
||||
exit(-1);
|
||||
}
|
||||
|
@ -279,7 +288,7 @@ int main(int argc, char **argv) {
|
|||
switch(type.type) {
|
||||
case PDSCH_SCHED:
|
||||
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");
|
||||
} else {
|
||||
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
|
||||
|
|
|
@ -105,7 +105,8 @@ int test_dci_payload_size() {
|
|||
|
||||
int main(int argc, char **argv) {
|
||||
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;
|
||||
regs_t regs;
|
||||
int i, j;
|
||||
|
@ -113,6 +114,7 @@ int main(int argc, char **argv) {
|
|||
int nof_re;
|
||||
cf_t *slot_symbols[MAX_PORTS];
|
||||
int nof_dcis;
|
||||
|
||||
int ret = -1;
|
||||
|
||||
parse_args(argc, argv);
|
||||
|
@ -155,26 +157,32 @@ int main(int argc, char **argv) {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
dci_init(&dci_tx, 2);
|
||||
nof_dcis = 2;
|
||||
bzero(&ra_dl, sizeof(ra_pdsch_t));
|
||||
ra_dl.harq_process = 0;
|
||||
//ra_pdsch_set_mcs_index(&ra_dl, 6);
|
||||
ra_pdsch_set_mcs(&ra_dl, QAM16, 5);
|
||||
ra_dl.ndi = 0;
|
||||
ra_dl.rv_idx = 0;
|
||||
ra_dl.alloc_type = alloc_type0;
|
||||
ra_dl.type0_alloc.rbg_bitmask = 0x5;
|
||||
|
||||
dci_msg_pack_pdsch(&ra_dl, &dci_tx.msg[0], Format1, cell.nof_prb, false);
|
||||
dci_msg_candidate_set(&dci_tx.msg[0], 0, 0, 1234);
|
||||
dci_tx.nof_dcis++;
|
||||
dci_msg_pack_pdsch(&ra_dl, &dci_tx[0], Format1, cell.nof_prb, false);
|
||||
dci_location_set(&dci_locations[0], 0, 0);
|
||||
|
||||
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_candidate_set(&dci_tx.msg[1], 0, 1, 1234);
|
||||
dci_tx.nof_dcis++;
|
||||
dci_msg_pack_pdsch(&ra_dl, &dci_tx[1], Format1, cell.nof_prb, false);
|
||||
dci_location_set(&dci_locations[1], 0, 1);
|
||||
|
||||
pdcch_encode(&pdcch, &dci_tx, slot_symbols, 0, cfi);
|
||||
pdcch_reset(&pdcch);
|
||||
|
||||
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 */
|
||||
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);
|
||||
|
||||
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);
|
||||
if (pdcch_extract_llr(&pdcch, slot_symbols[0], ce, 0, cfi)) {
|
||||
goto quit;
|
||||
}
|
||||
|
||||
if (memcmp(dci_tx.msg[i].data, dci_rx.msg[i].data,
|
||||
dci_tx.msg[i].location.nof_bits)) {
|
||||
for (i=0;i<nof_dcis;i++) {
|
||||
if (pdcch_decode_msg(&pdcch, &dci_rx[i], dci_locations, 2, Format1, 1234+i) < 0) {
|
||||
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;
|
||||
quit: pdcch_free(&pdcch);
|
||||
|
||||
quit:
|
||||
pdcch_free(&pdcch);
|
||||
regs_free(®s);
|
||||
dci_free(&dci_tx);
|
||||
dci_free(&dci_rx);
|
||||
|
||||
for (i = 0; i < MAX_PORTS; i++) {
|
||||
free(ce[i]);
|
||||
|
|
|
@ -58,7 +58,6 @@ cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS];
|
|||
regs_t regs;
|
||||
lte_fft_t fft;
|
||||
chest_t chest;
|
||||
dci_t dci_rx;
|
||||
|
||||
void usage(char *prog) {
|
||||
printf("Usage: %s [vcfoe] -i input_file\n", prog);
|
||||
|
@ -183,8 +182,6 @@ int base_init() {
|
|||
exit(-1);
|
||||
}
|
||||
|
||||
dci_init(&dci_rx, 10);
|
||||
|
||||
if (pdsch_init(&pdsch, rnti, cell)) {
|
||||
fprintf(stderr, "Error creating PDSCH object\n");
|
||||
exit(-1);
|
||||
|
@ -212,7 +209,6 @@ void base_free() {
|
|||
chest_free(&chest);
|
||||
lte_fft_free(&fft);
|
||||
|
||||
dci_free(&dci_rx);
|
||||
pdcch_free(&pdcch);
|
||||
pdsch_free(&pdsch);
|
||||
regs_free(®s);
|
||||
|
@ -226,6 +222,9 @@ int main(int argc, char **argv) {
|
|||
int nof_frames;
|
||||
int ret;
|
||||
char *data;
|
||||
dci_location_t locations[10];
|
||||
uint32_t nof_locations;
|
||||
dci_msg_t dci_msg;
|
||||
|
||||
data = malloc(10000);
|
||||
|
||||
|
@ -243,11 +242,13 @@ int main(int argc, char **argv) {
|
|||
|
||||
if (rnti == SIRNTI) {
|
||||
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 {
|
||||
// For ue-specific, generate locations for subframe 5
|
||||
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;
|
||||
nof_frames = 0;
|
||||
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);
|
||||
|
||||
for (i=0;i<nof_dcis;i++) {
|
||||
if (nof_dcis == 1) {
|
||||
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");
|
||||
goto goout;
|
||||
}
|
||||
|
@ -294,7 +301,7 @@ int main(int argc, char **argv) {
|
|||
switch(type.type) {
|
||||
case PDSCH_SCHED:
|
||||
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");
|
||||
} else {
|
||||
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
|
||||
|
|
Loading…
Reference in New Issue