Fixed error in PDSCH mapping. Further API simplification

master
ismagom 11 years ago
parent 0ebb0e7d00
commit ec321f971d

@ -334,13 +334,11 @@ int main(int argc, char **argv) {
data[i] = rand()%2; data[i] = rand()%2;
} }
if (pdcch_encode_msg(&pdcch, &dci_msg, locations[sf_idx][0], 1234)) { if (pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], 1234, sf_symbols, sf_idx, cfi)) {
fprintf(stderr, "Error encoding DCI message\n"); fprintf(stderr, "Error encoding DCI message\n");
exit(-1); exit(-1);
} }
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 */

@ -393,8 +393,7 @@ int cell_id_init(int nof_prb, int cell_id) {
char data[10000]; char data[10000];
int rx_run(cf_t *input, int sf_idx) { int rx_run(cf_t *input, int sf_idx) {
uint32_t cfi, cfi_distance; uint32_t cfi, cfi_distance, i;
int i, nof_dcis;
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;
@ -430,18 +429,19 @@ int rx_run(cf_t *input, int sf_idx) {
/* Search only UE-specific locations */ /* Search only UE-specific locations */
nof_locations = pdcch_ue_locations(&pdcch, locations, 10, sf_idx, cfi, 1234); nof_locations = pdcch_ue_locations(&pdcch, locations, 10, sf_idx, cfi, 1234);
pdcch_extract_llr(&pdcch, fft_buffer, ce, nof_frames, cfi); uint16_t crc_rem = 0;
for (i=0;i<nof_locations && crc_rem != 1234;i++) {
if (pdcch_extract_llr(&pdcch, fft_buffer, ce, locations[i], sf_idx, cfi)) {
nof_dcis = pdcch_decode_msg(&pdcch, &dci_msg, locations, nof_locations, Format1, 1234); fprintf(stderr, "Error extracting LLRs\n");
if (nof_dcis < 0) {
fprintf(stderr, "Error decoding DCI messages\n");
return -1; return -1;
} }
if (pdcch_decode_msg(&pdcch, &dci_msg, Format1A, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return -1;
}
}
INFO("Received %d DCI messages\n", nof_dcis); if (crc_rem == 1234) {
if (nof_dcis == 1) {
dci_msg_type_t type; dci_msg_type_t type;
if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, 1234, 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");
@ -482,7 +482,7 @@ int rx_run(cf_t *input, int sf_idx) {
} }
#ifndef DISABLE_GRAPHICS #ifndef DISABLE_GRAPHICS
if (!disable_plots && nof_dcis > 0) { if (!disable_plots && crc_rem == 1234) {
int n_re = 2 * RE_X_RB * CPNORM_NSYMB * cell.nof_prb; int n_re = 2 * RE_X_RB * CPNORM_NSYMB * cell.nof_prb;
for (i = 0; i < n_re; i++) { for (i = 0; i < n_re; i++) {
tmp_plot[i] = 10 * log10f(cabsf(fft_buffer[i])); tmp_plot[i] = 10 * log10f(cabsf(fft_buffer[i]));

@ -42,18 +42,18 @@ typedef _Complex float cf_t; /* this is only a shortcut */
/* This is common for both directions */ /* This is common for both directions */
typedef struct LIBLTE_API{ typedef struct LIBLTE_API{
dft_plan_t fft_plan; dft_plan_t fft_plan;
int nof_symbols; uint32_t nof_symbols;
int symbol_sz; uint32_t symbol_sz;
int nof_guards; uint32_t nof_guards;
int nof_re; uint32_t nof_re;
int slot_sz; uint32_t slot_sz;
lte_cp_t cp; lte_cp_t cp;
cf_t *tmp; // for removing zero padding cf_t *tmp; // for removing zero padding
}lte_fft_t; }lte_fft_t;
LIBLTE_API int lte_fft_init(lte_fft_t *q, LIBLTE_API int lte_fft_init(lte_fft_t *q,
lte_cp_t cp_type, lte_cp_t cp_type,
int nof_prb); uint32_t nof_prb);
LIBLTE_API void lte_fft_free(lte_fft_t *q); LIBLTE_API void lte_fft_free(lte_fft_t *q);
@ -67,7 +67,7 @@ LIBLTE_API void lte_fft_run_sf(lte_fft_t *q,
LIBLTE_API int lte_ifft_init(lte_fft_t *q, LIBLTE_API int lte_ifft_init(lte_fft_t *q,
lte_cp_t cp_type, lte_cp_t cp_type,
int nof_prb); uint32_t nof_prb);
LIBLTE_API void lte_ifft_free(lte_fft_t *q); LIBLTE_API void lte_ifft_free(lte_fft_t *q);

@ -78,6 +78,8 @@ LIBLTE_API int dci_location_set(dci_location_t *c,
uint32_t L, uint32_t L,
uint32_t nCCE); uint32_t nCCE);
LIBLTE_API bool dci_location_isvalid(dci_location_t *c);
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,

@ -59,8 +59,7 @@ typedef enum LIBLTE_API {
/* PDCCH object */ /* PDCCH object */
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
lte_cell_t cell; lte_cell_t cell;
uint32_t nof_bits; uint32_t e_bits;
uint32_t nof_symbols;
uint32_t nof_regs; uint32_t nof_regs;
uint32_t nof_cce; uint32_t nof_cce;
uint32_t max_bits; uint32_t max_bits;
@ -91,33 +90,27 @@ LIBLTE_API void pdcch_free(pdcch_t *q);
/* Encoding function */ /* Encoding function */
LIBLTE_API void pdcch_reset(pdcch_t *q); LIBLTE_API int pdcch_encode(pdcch_t *q,
LIBLTE_API int pdcch_encode_msg(pdcch_t *q,
dci_msg_t *msg, dci_msg_t *msg,
dci_location_t location, dci_location_t location,
uint16_t rnti); uint16_t rnti,
LIBLTE_API int pdcch_gen_symbols(pdcch_t *q,
cf_t *sf_symbols[MAX_PORTS], cf_t *sf_symbols[MAX_PORTS],
uint32_t nsubframe, uint32_t nsubframe,
uint32_t cfi); uint32_t cfi);
/* Decoding functions: Extract the LLRs and save them in the pdcch_t object */ /* 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 *sf_symbols, cf_t *sf_symbols,
cf_t *ce[MAX_PORTS], cf_t *ce[MAX_PORTS],
dci_location_t location,
uint32_t nsubframe, uint32_t nsubframe,
uint32_t cfi); uint32_t cfi);
/* Decoding functions: Try to decode a DCI message after calling pdcch_extract_llr */ /* Decoding functions: Try to decode a DCI message after calling pdcch_extract_llr */
LIBLTE_API int pdcch_decode_msg(pdcch_t *q, LIBLTE_API int pdcch_decode_msg(pdcch_t *q,
dci_msg_t *msg, dci_msg_t *msg,
dci_location_t *locations,
uint32_t nof_locations,
dci_format_t format, dci_format_t format,
uint16_t rnti); uint16_t *crc_rem);
/* Function for generation of UE-specific search space DCI locations */ /* Function for generation of UE-specific search space DCI locations */
LIBLTE_API uint32_t pdcch_ue_locations(pdcch_t *q, LIBLTE_API uint32_t pdcch_ue_locations(pdcch_t *q,

@ -114,10 +114,22 @@ LIBLTE_API int regs_pdcch_put(regs_t *h,
cf_t *pdcch_symbols, cf_t *pdcch_symbols,
cf_t *slot_symbols); cf_t *slot_symbols);
LIBLTE_API int regs_pdcch_put_offset(regs_t *h,
cf_t *pdcch_symbols,
cf_t *slot_symbols,
uint32_t start_reg,
uint32_t nof_regs);
LIBLTE_API int regs_pdcch_get(regs_t *h, LIBLTE_API int regs_pdcch_get(regs_t *h,
cf_t *slot_symbols, cf_t *slot_symbols,
cf_t *pdcch_symbols); cf_t *pdcch_symbols);
LIBLTE_API int regs_pdcch_get_offset(regs_t *h,
cf_t *slot_symbols,
cf_t *pdcch_symbols,
uint32_t start_reg,
uint32_t nof_regs);
#endif // REGS_H_ #endif // REGS_H_

@ -67,12 +67,12 @@ int refsignal_v(uint32_t port_id, uint32_t ns, uint32_t symbol_id) {
return v; return v;
} }
int refsignal_k(int m, int v, uint32_t cell_id) { uint32_t refsignal_k(uint32_t m, uint32_t v, uint32_t cell_id) {
return 6*m+((v+(cell_id%6))%6); return 6*m+((v+(cell_id%6))%6);
} }
int refsignal_put(refsignal_t *q, cf_t *slot_symbols) { int refsignal_put(refsignal_t *q, cf_t *slot_symbols) {
int i; uint32_t i;
uint32_t fidx, tidx; uint32_t fidx, tidx;
if (q != NULL && if (q != NULL &&
slot_symbols != NULL) slot_symbols != NULL)
@ -96,12 +96,12 @@ int refsignal_init_LTEDL(refsignal_t *q, uint32_t port_id, uint32_t nslot,
uint32_t c_init; uint32_t c_init;
uint32_t ns, l, lp[2]; uint32_t ns, l, lp[2];
int N_cp; uint32_t N_cp;
int i; uint32_t i;
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
sequence_t seq; sequence_t seq;
int v; int v;
int mp; uint32_t mp;
uint32_t nof_refs_x_symbol, nof_ref_symbols; uint32_t nof_refs_x_symbol, nof_ref_symbols;
if (q != NULL && if (q != NULL &&
@ -171,7 +171,7 @@ int refsignal_init_LTEDL(refsignal_t *q, uint32_t port_id, uint32_t nslot,
__imag__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2); __imag__ q->refs[idx(l,i)].simbol = (1 - 2 * (float) seq.c[2 * mp + 1]) / sqrt(2);
/* mapping to resource elements */ /* mapping to resource elements */
q->refs[idx(l,i)].freq_idx = refsignal_k(i, v, cell.id); q->refs[idx(l,i)].freq_idx = refsignal_k(i, (uint32_t) v, cell.id);
q->refs[idx(l,i)].time_idx = lp[l]; q->refs[idx(l,i)].time_idx = lp[l];
} }
} }

@ -35,10 +35,10 @@
#include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/debug.h"
#include "liblte/phy/utils/vector.h" #include "liblte/phy/utils/vector.h"
int lte_fft_init_(lte_fft_t *q, lte_cp_t cp, int nof_prb, dft_dir_t dir) { int lte_fft_init_(lte_fft_t *q, lte_cp_t cp, uint32_t nof_prb, dft_dir_t dir) {
int symbol_sz = lte_symbol_sz(nof_prb); int symbol_sz = lte_symbol_sz(nof_prb);
if (symbol_sz == -1) { if (symbol_sz < 0) {
fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb); fprintf(stderr, "Error: Invalid nof_prb=%d\n", nof_prb);
return -1; return -1;
} }
@ -46,7 +46,7 @@ int lte_fft_init_(lte_fft_t *q, lte_cp_t cp, int nof_prb, dft_dir_t dir) {
fprintf(stderr, "Error: Creating DFT plan\n"); fprintf(stderr, "Error: Creating DFT plan\n");
return -1; return -1;
} }
q->tmp = malloc(symbol_sz * sizeof(cf_t)); q->tmp = malloc((uint32_t) symbol_sz * sizeof(cf_t));
if (!q->tmp) { if (!q->tmp) {
perror("malloc"); perror("malloc");
return -1; return -1;
@ -56,7 +56,7 @@ int lte_fft_init_(lte_fft_t *q, lte_cp_t cp, int nof_prb, dft_dir_t dir) {
dft_plan_set_norm(&q->fft_plan, true); dft_plan_set_norm(&q->fft_plan, true);
dft_plan_set_dc(&q->fft_plan, true); dft_plan_set_dc(&q->fft_plan, true);
q->symbol_sz = symbol_sz; q->symbol_sz = (uint32_t) symbol_sz;
q->nof_symbols = CP_NSYMB(cp); q->nof_symbols = CP_NSYMB(cp);
q->cp = cp; q->cp = cp;
q->nof_re = nof_prb * RE_X_RB; q->nof_re = nof_prb * RE_X_RB;
@ -66,7 +66,8 @@ int lte_fft_init_(lte_fft_t *q, lte_cp_t cp, int nof_prb, dft_dir_t dir) {
DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n", DEBUG("Init %s symbol_sz=%d, nof_symbols=%d, cp=%s, nof_re=%d, nof_guards=%d\n",
dir==FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols, dir==FORWARD?"FFT":"iFFT", q->symbol_sz, q->nof_symbols,
q->cp==CPNORM?"Normal":"Extended", q->nof_re, q->nof_guards); q->cp==CPNORM?"Normal":"Extended", q->nof_re, q->nof_guards);
return 0;
return LIBLTE_SUCCESS;
} }
void lte_fft_free_(lte_fft_t *q) { void lte_fft_free_(lte_fft_t *q) {
@ -77,7 +78,7 @@ void lte_fft_free_(lte_fft_t *q) {
bzero(q, sizeof(lte_fft_t)); bzero(q, sizeof(lte_fft_t));
} }
int lte_fft_init(lte_fft_t *q, lte_cp_t cp, int nof_prb) { int lte_fft_init(lte_fft_t *q, lte_cp_t cp, uint32_t nof_prb) {
return lte_fft_init_(q, cp, nof_prb, FORWARD); return lte_fft_init_(q, cp, nof_prb, FORWARD);
} }
@ -85,17 +86,20 @@ void lte_fft_free(lte_fft_t *q) {
lte_fft_free_(q); lte_fft_free_(q);
} }
int lte_ifft_init(lte_fft_t *q, lte_cp_t cp, int nof_prb) { int lte_ifft_init(lte_fft_t *q, lte_cp_t cp, uint32_t nof_prb) {
int i; uint32_t i;
if (lte_fft_init_(q, cp, nof_prb, BACKWARD)) { int ret;
return -1;
} ret = lte_fft_init_(q, cp, nof_prb, BACKWARD);
if (ret == LIBLTE_SUCCESS) {
/* set now zeros at CP */ /* set now zeros at CP */
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {
bzero(q->tmp, q->nof_guards * sizeof(cf_t)); bzero(q->tmp, q->nof_guards * sizeof(cf_t));
bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t)); bzero(&q->tmp[q->nof_re + q->nof_guards], q->nof_guards * sizeof(cf_t));
} }
return 0; }
return ret;
} }
void lte_ifft_free(lte_fft_t *q) { void lte_ifft_free(lte_fft_t *q) {
@ -106,7 +110,7 @@ void lte_ifft_free(lte_fft_t *q) {
* Performs FFT on a each symbol and removes CP. * Performs FFT on a each symbol and removes CP.
*/ */
void lte_fft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output) { void lte_fft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output) {
int i; uint32_t i;
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {
input += CP_ISNORM(q->cp)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); input += CP_ISNORM(q->cp)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz);
dft_run_c(&q->fft_plan, input, q->tmp); dft_run_c(&q->fft_plan, input, q->tmp);
@ -117,7 +121,7 @@ void lte_fft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output) {
} }
void lte_fft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output) { void lte_fft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output) {
int n; uint32_t n;
for (n=0;n<2;n++) { for (n=0;n<2;n++) {
lte_fft_run_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]); lte_fft_run_slot(q, &input[n*q->slot_sz], &output[n*q->nof_re*q->nof_symbols]);
} }
@ -127,7 +131,7 @@ void lte_fft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output) {
* Performs FFT on a each symbol and adds CP. * Performs FFT on a each symbol and adds CP.
*/ */
void lte_ifft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output) { void lte_ifft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output) {
int i, cp_len; uint32_t i, cp_len;
for (i=0;i<q->nof_symbols;i++) { for (i=0;i<q->nof_symbols;i++) {
cp_len = CP_ISNORM(q->cp)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz); cp_len = CP_ISNORM(q->cp)?CP_NORM(i, q->symbol_sz):CP_EXT(q->symbol_sz);
memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t)); memcpy(&q->tmp[q->nof_guards], input, q->nof_re * sizeof(cf_t));
@ -140,7 +144,7 @@ void lte_ifft_run_slot(lte_fft_t *q, cf_t *input, cf_t *output) {
} }
void lte_ifft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output) { void lte_ifft_run_sf(lte_fft_t *q, cf_t *input, cf_t *output) {
int n; uint32_t n;
for (n=0;n<2;n++) { for (n=0;n<2;n++) {
lte_ifft_run_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]); lte_ifft_run_slot(q, &input[n*q->nof_re*q->nof_symbols], &output[n*q->slot_sz]);
} }

@ -39,6 +39,11 @@ int convcoder_encode(convcoder_t *q, char *input, char *output, uint32_t frame_l
uint32_t i,j; uint32_t i,j;
uint32_t 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 != NULL &&
input != NULL &&
output != NULL &&
frame_length > q->K + 1)
{
if (q->tail_biting) { if (q->tail_biting) {
sr = 0; sr = 0;
for (i=frame_length - q->K + 1; i<frame_length; i++) { for (i=frame_length - q->K + 1; i<frame_length; i++) {
@ -48,14 +53,16 @@ int convcoder_encode(convcoder_t *q, char *input, char *output, uint32_t frame_l
sr = 0; sr = 0;
} }
for (i = 0; i < len; i++) { for (i = 0; i < len; i++) {
int bit = (i < frame_length) ? (input[i] & 1) : 0; char bit = (i < frame_length) ? (input[i] & 1) : 0;
sr = (sr << 1) | bit; sr = (sr << 1) | bit;
for (j=0;j<q->R;j++) { for (j=0;j<q->R;j++) {
output[q->R * i + j] = parity(sr & q->poly[j]); output[q->R * i + j] = parity(sr & q->poly[j]);
} }
} }
return q->R*len; return q->R*len;
} else {
return LIBLTE_ERROR_INVALID_INPUTS;
}
} }

@ -57,6 +57,14 @@ int dci_location_set(dci_location_t *c, uint32_t L, uint32_t nCCE) {
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
} }
bool dci_location_isvalid(dci_location_t *c) {
if (c->L <= 3 && c->ncce <= 87) {
return true;
} else {
return false;
}
}
uint32_t riv_nbits(uint32_t nof_prb) { uint32_t riv_nbits(uint32_t nof_prb) {
return (uint32_t) ceilf(log2f((float) nof_prb * ((float) nof_prb + 1) / 2)); return (uint32_t) ceilf(log2f((float) nof_prb * ((float) nof_prb + 1) / 2));
} }
@ -785,7 +793,9 @@ 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 msg_rnti, uint16_t crnti) { uint16_t msg_rnti, uint16_t crnti)
{
DEBUG("Get message type: nof_bits=%d, msg_rnti=0x%x, crnti=0x%x\n", msg->nof_bits, msg_rnti, crnti);
if (msg->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;

@ -54,8 +54,6 @@ 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;
q->nof_symbols = 4 * q->nof_regs;
q->nof_bits = 2 * q->nof_symbols;
} }
} }
@ -63,7 +61,7 @@ static 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;
int i; uint32_t i;
if (q != NULL && if (q != NULL &&
regs != NULL && regs != NULL &&
@ -74,13 +72,10 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
q->cell = cell; q->cell = cell;
q->regs = regs; q->regs = regs;
/* Now allocate memory for the maximum number of REGs (CFI=3) /* Allocate memory for the largest aggregation level L=3 */
*/ q->max_bits = PDCCH_FORMAT_NOF_BITS(3);
set_cfi(q, 3);
q->max_bits = q->nof_bits;
INFO("Init PDCCH: %d CCEs (%d REGs), %d bits, %d symbols, %d ports\n", INFO("Init PDCCH: %d bits, %d symbols, %d ports\n", q->max_bits, q->max_bits/2, q->cell.nof_ports);
q->nof_cce, q->nof_regs, q->nof_bits, q->nof_symbols, q->cell.nof_ports);
if (modem_table_std(&q->mod, LTE_QPSK, true)) { if (modem_table_std(&q->mod, LTE_QPSK, true)) {
goto clean; goto clean;
@ -94,7 +89,7 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
demod_soft_alg_set(&q->demod, APPROX); demod_soft_alg_set(&q->demod, APPROX);
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell.id, q->nof_bits)) { if (sequence_pdcch(&q->seq_pdcch[i], 2 * i, q->cell.id, q->max_bits)) {
goto clean; goto clean;
} }
} }
@ -104,31 +99,31 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
goto clean; goto clean;
} }
q->pdcch_e = malloc(sizeof(char) * q->nof_bits); q->pdcch_e = malloc(sizeof(char) * q->max_bits);
if (!q->pdcch_e) { if (!q->pdcch_e) {
goto clean; goto clean;
} }
q->pdcch_llr = malloc(sizeof(float) * q->nof_bits); q->pdcch_llr = malloc(sizeof(float) * q->max_bits);
if (!q->pdcch_llr) { if (!q->pdcch_llr) {
goto clean; goto clean;
} }
q->pdcch_d = malloc(sizeof(cf_t) * q->nof_symbols); q->pdcch_d = malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->pdcch_d) { if (!q->pdcch_d) {
goto clean; goto clean;
} }
for (i = 0; i < MAX_PORTS; i++) { for (i = 0; i < MAX_PORTS; i++) {
q->ce[i] = malloc(sizeof(cf_t) * q->nof_symbols); q->ce[i] = malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->ce[i]) { if (!q->ce[i]) {
goto clean; goto clean;
} }
q->pdcch_x[i] = malloc(sizeof(cf_t) * q->nof_symbols); q->pdcch_x[i] = malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->pdcch_x[i]) { if (!q->pdcch_x[i]) {
goto clean; goto clean;
} }
q->pdcch_symbols[i] = malloc(sizeof(cf_t) * q->nof_symbols); q->pdcch_symbols[i] = malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->pdcch_symbols[i]) { if (!q->pdcch_symbols[i]) {
goto clean; goto clean;
} }
@ -277,10 +272,6 @@ static int dci_decode(pdcch_t *q, float *e, char *data, uint32_t E, uint32_t nof
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));
@ -299,7 +290,7 @@ static int dci_decode(pdcch_t *q, float *e, char *data, uint32_t E, uint32_t nof
x = &data[nof_bits]; x = &data[nof_bits];
p_bits = (uint16_t) bit_unpack(&x, 16); p_bits = (uint16_t) bit_unpack(&x, 16);
crc_res = ((uint16_t) crc_checksum(&q->crc, data, nof_bits) & 0xffff); crc_res = ((uint16_t) crc_checksum(&q->crc, data, nof_bits) & 0xffff);
DEBUG("p_bits: 0x%x, crc_res: 0x%x, tot: 0x%x\n", p_bits, crc_res, DEBUG("p_bits: 0x%x, crc_checksum: 0x%x, crc_rem: 0x%x\n", p_bits, crc_res,
p_bits ^ crc_res); p_bits ^ crc_res);
if (crc) { if (crc) {
@ -313,67 +304,57 @@ static int dci_decode(pdcch_t *q, float *e, char *data, uint32_t E, uint32_t nof
/** Tries to decode a DCI message from the LLRs stored in the pdcch_t structure by the function /** 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. * 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 * The decoded message is stored in msg and the CRC remainder in crc_rem pointer
* 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, int pdcch_decode_msg(pdcch_t *q, dci_msg_t *msg, dci_format_t format, uint16_t *crc_rem)
dci_location_t *locations, uint32_t nof_locations,
dci_format_t format, uint16_t rnti)
{ {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
msg != NULL && msg != NULL &&
locations != NULL && crc_rem != NULL)
nof_locations > 0)
{ {
uint16_t crc_res;
uint32_t nof_bits = dci_format_sizeof(format, q->cell.nof_prb); uint32_t nof_bits = dci_format_sizeof(format, q->cell.nof_prb);
uint32_t i;
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, ret = dci_decode(q, q->pdcch_llr, msg->data, q->e_bits, nof_bits, crc_rem);
PDCCH_FORMAT_NOF_BITS(locations[i].L), nof_bits, &crc_res) != LIBLTE_SUCCESS) { if (ret == LIBLTE_SUCCESS) {
return LIBLTE_ERROR;
}
if (crc_res != rnti) {
i++;
}
} while(i < nof_locations && crc_res != rnti);
if (rnti == crc_res) {
msg->nof_bits = nof_bits; 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; return ret;
} }
/** Extracts the LLRs from the subframe symbols (demodulation) and stores them in the pdcch_t structure. /** Extracts the LLRs from dci_location_t location of the subframe and stores them in the pdcch_t structure.
* DCI messages can be extracted calling the function pdcch_decode_msg(). * DCI messages can be extracted from this location calling the function pdcch_decode_msg().
* Every time this function is called, the last demodulated symbols are overwritten. * Every time this function is called (with a different location), the last demodulated symbols are overwritten and
* new messages from other locations can be decoded
*/ */
int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], uint32_t nsubframe, uint32_t cfi) { int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS],
dci_location_t location, uint32_t nsubframe, uint32_t cfi) {
int ret = LIBLTE_ERROR_INVALID_INPUTS;
/* Set pointers for layermapping & precoding */ /* Set pointers for layermapping & precoding */
uint32_t i; uint32_t i, nof_symbols;
cf_t *x[MAX_LAYERS]; cf_t *x[MAX_LAYERS];
if (q != NULL && if (q != NULL &&
nsubframe < 10 && nsubframe < 10 &&
cfi > 0 && cfi > 0 &&
cfi < 4) cfi < 4 &&
dci_location_isvalid(&location))
{ {
set_cfi(q, cfi); set_cfi(q, cfi);
q->e_bits = PDCCH_FORMAT_NOF_BITS(location.L);
nof_symbols = q->e_bits/2;
ret = LIBLTE_ERROR;
if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce) {
INFO("Extracting LLRs: E: %d, nCCE: %d, L: %d\n",
q->e_bits, location.ncce, location.L);
/* number of layers equals number of ports */ /* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->pdcch_x[i]; x[i] = q->pdcch_x[i];
@ -381,55 +362,55 @@ int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], uint32_
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, sf_symbols, q->pdcch_symbols[0]); int n = regs_pdcch_get_offset(q->regs, sf_symbols, q->pdcch_symbols[0],
if (q->nof_symbols != n) { location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L));
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", if (nof_symbols != n) {
q->nof_symbols, n); fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return LIBLTE_ERROR; return ret;
} }
/* extract channel estimates */ /* extract channel estimates */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
n = regs_pdcch_get(q->regs, ce[i], q->ce[i]); n = regs_pdcch_get_offset(q->regs, ce[i], q->ce[i],
if (q->nof_symbols != n) { location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L));
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", if (nof_symbols != n) {
q->nof_symbols, n); fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return LIBLTE_ERROR; return ret;
} }
} }
/* in control channels, only diversity is supported */ /* in control channels, only diversity is supported */
if (q->cell.nof_ports == 1) { if (q->cell.nof_ports == 1) {
/* no need for layer demapping */ /* no need for layer demapping */
predecoding_single_zf(q->pdcch_symbols[0], q->ce[0], q->pdcch_d, predecoding_single_zf(q->pdcch_symbols[0], q->ce[0], q->pdcch_d, nof_symbols);
q->nof_symbols);
} else { } else {
predecoding_diversity_zf(q->pdcch_symbols[0], q->ce, x, q->cell.nof_ports, predecoding_diversity_zf(q->pdcch_symbols[0], q->ce, x, q->cell.nof_ports, nof_symbols);
q->nof_symbols); layerdemap_diversity(x, q->pdcch_d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
layerdemap_diversity(x, q->pdcch_d, q->cell.nof_ports,
q->nof_symbols / q->cell.nof_ports);
} }
DEBUG("pdcch d symbols: ", 0); DEBUG("pdcch d symbols: ", 0);
if (VERBOSE_ISDEBUG()) { if (VERBOSE_ISDEBUG()) {
vec_fprint_c(stdout, q->pdcch_d, q->nof_symbols); vec_fprint_c(stdout, q->pdcch_d, nof_symbols);
} }
/* demodulate symbols */ /* demodulate symbols */
demod_soft_sigma_set(&q->demod, 1.0); demod_soft_sigma_set(&q->demod, 1.0);
demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, q->nof_symbols); demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, nof_symbols);
DEBUG("llr: ", 0); DEBUG("llr: ", 0);
if (VERBOSE_ISDEBUG()) { if (VERBOSE_ISDEBUG()) {
vec_fprint_f(stdout, q->pdcch_llr, q->nof_bits); vec_fprint_f(stdout, q->pdcch_llr, q->e_bits);
} }
/* descramble */ /* descramble */
scrambling_f_offset(&q->seq_pdcch[nsubframe], q->pdcch_llr, 0, q->nof_bits); scrambling_f_offset(&q->seq_pdcch[nsubframe], q->pdcch_llr, 72 * location.ncce, q->e_bits);
return LIBLTE_SUCCESS; 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 LIBLTE_ERROR_INVALID_INPUTS; }
return ret;
} }
@ -487,91 +468,79 @@ static int dci_encode(pdcch_t *q, char *data, char *e, uint32_t nof_bits, uint32
} }
} }
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 /** 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. * 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 * This function can be called multiple times and encoded DCI messages will be allocated to the
* pdcch_t structure. A final call to the function pdcch_gen_symbols() will generate and map the * sf_symbols buffer ready for transmission.
* symbols to the subframe for transmission.
* If the same location is provided in multiple messages, the encoded bits will be overwritten. * 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. * @TODO: Use a bitmask and CFI to ensure message locations are valid and old messages are not overwritten.
*/ */
int pdcch_encode_msg(pdcch_t *q, dci_msg_t *msg, dci_location_t location, uint16_t rnti) { int pdcch_encode(pdcch_t *q, dci_msg_t *msg, dci_location_t location, uint16_t rnti,
cf_t *sf_symbols[MAX_PORTS], uint32_t nsubframe, uint32_t cfi) {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
uint32_t i;
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]; cf_t *x[MAX_LAYERS];
uint32_t nof_symbols;
if (q != NULL && if (q != NULL &&
slot_symbols != NULL && sf_symbols != NULL &&
nsubframe < 10 && nsubframe < 10 &&
cfi > 0 && cfi > 0 &&
cfi < 4) cfi < 4 &&
dci_location_isvalid(&location))
{ {
set_cfi(q, cfi); set_cfi(q, cfi);
q->e_bits = PDCCH_FORMAT_NOF_BITS(location.L);
nof_symbols = q->e_bits/2;
ret = LIBLTE_ERROR;
if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce &&
msg->nof_bits < DCI_MAX_BITS)
{
INFO("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n",
msg->nof_bits, q->e_bits, location.ncce, location.L, rnti);
dci_encode(q, msg->data, q->pdcch_e, msg->nof_bits, q->e_bits, rnti);
/* number of layers equals number of ports */ /* number of layers equals number of ports */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
x[i] = q->pdcch_x[i]; x[i] = q->pdcch_x[i];
} }
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));
scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 0, q->nof_bits); scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 72 * location.ncce, q->e_bits);
DEBUG("Scrambling output: ", 0);
if (VERBOSE_ISDEBUG()) {
vec_fprint_b(stdout, q->pdcch_e, q->e_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->e_bits);
/* layer mapping & precoding */ /* layer mapping & precoding */
if (q->cell.nof_ports > 1) { if (q->cell.nof_ports > 1) {
layermap_diversity(q->pdcch_d, x, q->cell.nof_ports, q->nof_symbols); layermap_diversity(q->pdcch_d, x, q->cell.nof_ports, nof_symbols);
precoding_diversity(x, q->pdcch_symbols, q->cell.nof_ports, precoding_diversity(x, q->pdcch_symbols, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
q->nof_symbols / q->cell.nof_ports);
} else { } else {
memcpy(q->pdcch_symbols[0], q->pdcch_d, q->nof_symbols * sizeof(cf_t)); memcpy(q->pdcch_symbols[0], q->pdcch_d, nof_symbols * sizeof(cf_t));
} }
/* mapping to resource elements */ /* mapping to resource elements */
for (i = 0; i < q->cell.nof_ports; i++) { for (i = 0; i < q->cell.nof_ports; i++) {
regs_pdcch_put(q->regs, q->pdcch_symbols[i], slot_symbols[i]); regs_pdcch_put_offset(q->regs, q->pdcch_symbols[i], sf_symbols[i],
location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L));
} }
return LIBLTE_SUCCESS;
ret = LIBLTE_SUCCESS;
} else { } else {
return LIBLTE_ERROR_INVALID_INPUTS; fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d\n", location.ncce, location.L, q->nof_cce);
}
} }
return ret;
} }

@ -34,6 +34,9 @@
#include "liblte/phy/phch/regs.h" #include "liblte/phy/phch/regs.h"
#include "liblte/phy/utils/debug.h" #include "liblte/phy/utils/debug.h"
#define REG_IDX(r, i, n) r->k[i]+r->l*n*RE_X_RB
regs_reg_t *regs_find_reg(regs_t *h, uint32_t k, uint32_t l); regs_reg_t *regs_find_reg(regs_t *h, uint32_t k, uint32_t l);
int regs_put_reg(regs_reg_t *reg, int regs_put_reg(regs_reg_t *reg,
cf_t *reg_data, cf_t *reg_data,
@ -79,7 +82,8 @@ const unsigned char PDCCH_PERM[PDCCH_NCOLS] =
int regs_pdcch_init(regs_t *h) { int regs_pdcch_init(regs_t *h) {
int i, m, cfi, nof_ctrl_symbols; int i, m, cfi, nof_ctrl_symbols;
int ret = LIBLTE_ERROR; int ret = LIBLTE_ERROR;
int nrows, ndummy, j, k, kp; int nrows, ndummy, j;
uint32_t k, kp;
regs_reg_t **tmp = NULL; regs_reg_t **tmp = NULL;
bzero(&h->pdcch, sizeof(regs_ch_t)); bzero(&h->pdcch, sizeof(regs_ch_t));
@ -126,9 +130,10 @@ int regs_pdcch_init(regs_t *h) {
for (i = 0; i < nrows; i++) { for (i = 0; i < nrows; i++) {
if (i*PDCCH_NCOLS + PDCCH_PERM[j] >= ndummy) { if (i*PDCCH_NCOLS + PDCCH_PERM[j] >= ndummy) {
m = i*PDCCH_NCOLS + PDCCH_PERM[j]-ndummy; m = i*PDCCH_NCOLS + PDCCH_PERM[j]-ndummy;
if (k < h->cell.id) {
kp = (h->pdcch[cfi].nof_regs + k-h->cell.id)%h->pdcch[cfi].nof_regs;
} else {
kp = (k-h->cell.id)%h->pdcch[cfi].nof_regs; kp = (k-h->cell.id)%h->pdcch[cfi].nof_regs;
if (kp < 0) {
kp += h->pdcch[cfi].nof_regs;
} }
h->pdcch[cfi].regs[m] = tmp[kp]; h->pdcch[cfi].regs[m] = tmp[kp];
k++; k++;
@ -163,28 +168,54 @@ int regs_pdcch_nregs(regs_t *h, uint32_t cfi) {
/** Copy quadruplets to REGs and cyclic shift them, according to the /** Copy quadruplets to REGs and cyclic shift them, according to the
* second part of 6.8.5 in 36.211 * second part of 6.8.5 in 36.211
*/ */
int regs_pdcch_put(regs_t *h, cf_t *pdcch_symbols, cf_t *slot_symbols) {
if (!h->cfi_initiated) { int regs_pdcch_put_offset(regs_t *h, cf_t *pdcch_symbols, cf_t *slot_symbols, uint32_t start_reg, uint32_t nof_regs) {
fprintf(stderr, "Must call regs_set_cfi() first\n"); if (h->cfi_initiated) {
if (start_reg + nof_regs <= h->pdcch[h->cfi].nof_regs) {
uint32_t i, k;
k = 0;
for (i=start_reg;i<start_reg+nof_regs;i++) {
regs_put_reg(h->pdcch[h->cfi].regs[i], &pdcch_symbols[k], slot_symbols, h->cell.nof_prb);
k += 4;
}
return k;
} else {
fprintf(stderr, "Out of range: start_reg + nof_reg must be lower than %d\n", h->pdcch[h->cfi].nof_regs);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
int i; } else {
for (i=0;i<h->pdcch[h->cfi].nof_regs;i++) { fprintf(stderr, "Must call regs_set_cfi() first\n");
regs_put_reg(h->pdcch[h->cfi].regs[i], &pdcch_symbols[i*4], slot_symbols, h->cell.nof_prb); return LIBLTE_ERROR;
} }
return h->pdcch[h->cfi].nof_regs*4;
} }
int regs_pdcch_get(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols) { int regs_pdcch_put(regs_t *h, cf_t *pdcch_symbols, cf_t *slot_symbols) {
if (!h->cfi_initiated) { return regs_pdcch_put_offset(h, pdcch_symbols, slot_symbols, 0, h->pdcch[h->cfi].nof_regs);
fprintf(stderr, "Must call regs_set_cfi() first\n"); }
int regs_pdcch_get_offset(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols, uint32_t start_reg, uint32_t nof_regs) {
if (h->cfi_initiated) {
if (start_reg + nof_regs <= h->pdcch[h->cfi].nof_regs) {
uint32_t i, k;
k = 0;
for (i=start_reg;i<start_reg + nof_regs;i++) {
regs_get_reg(h->pdcch[h->cfi].regs[i], slot_symbols, &pdcch_symbols[k], h->cell.nof_prb);
k += 4;
}
return k;
} else {
fprintf(stderr, "Out of range: start_reg + nof_reg must be lower than %d\n", h->pdcch[h->cfi].nof_regs);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
int i; } else {
for (i=0;i<h->pdcch[h->cfi].nof_regs;i++) { fprintf(stderr, "Must call regs_set_cfi() first\n");
regs_get_reg(h->pdcch[h->cfi].regs[i], slot_symbols, &pdcch_symbols[i*4], h->cell.nof_prb); return LIBLTE_ERROR;
} }
return h->pdcch[h->cfi].nof_regs*4; }
int regs_pdcch_get(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols) {
return regs_pdcch_get_offset(h, slot_symbols, pdcch_symbols, 0, h->pdcch[h->cfi].nof_regs);
} }
@ -201,7 +232,7 @@ int regs_pdcch_get(regs_t *h, cf_t *slot_symbols, cf_t *pdcch_symbols) {
*/ */
int regs_phich_init(regs_t *h) { int regs_phich_init(regs_t *h) {
float ng; float ng;
int i,ni,li,n[3],nreg,mi; uint32_t i, ni, li, n[3], nreg, mi;
regs_reg_t **regs_phich[3]; regs_reg_t **regs_phich[3];
int ret = LIBLTE_ERROR; int ret = LIBLTE_ERROR;
@ -306,7 +337,7 @@ clean_and_exit:
} }
void regs_phich_free(regs_t *h) { void regs_phich_free(regs_t *h) {
int i; uint32_t i;
if (h->phich) { if (h->phich) {
if (CP_ISEXT(h->cell.cp)) { if (CP_ISEXT(h->cell.cp)) {
h->ngroups_phich /= 2; h->ngroups_phich /= 2;
@ -321,7 +352,7 @@ void regs_phich_free(regs_t *h) {
} }
uint32_t regs_phich_nregs(regs_t *h) { uint32_t regs_phich_nregs(regs_t *h) {
int i; uint32_t i;
uint32_t n; uint32_t n;
n=0; n=0;
for (i=0;i<h->ngroups_phich;i++) { for (i=0;i<h->ngroups_phich;i++) {
@ -343,7 +374,7 @@ uint32_t regs_phich_ngroups(regs_t *h) {
* Returns the number of written symbols, or -1 on error * Returns the number of written symbols, or -1 on error
*/ */
int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], uint32_t ngroup, cf_t *slot_symbols) { int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], uint32_t ngroup, cf_t *slot_symbols) {
int i; uint32_t i;
if (ngroup >= h->ngroups_phich) { if (ngroup >= h->ngroups_phich) {
fprintf(stderr, "Error invalid ngroup %d\n", ngroup); fprintf(stderr, "Error invalid ngroup %d\n", ngroup);
return LIBLTE_ERROR_INVALID_INPUTS; return LIBLTE_ERROR_INVALID_INPUTS;
@ -364,7 +395,7 @@ int regs_phich_add(regs_t *h, cf_t phich_symbols[REGS_PHICH_NSYM], uint32_t ngro
* Returns the number of written symbols, or -1 on error * Returns the number of written symbols, or -1 on error
*/ */
int regs_phich_reset(regs_t *h, cf_t *slot_symbols) { int regs_phich_reset(regs_t *h, cf_t *slot_symbols) {
int i; uint32_t i;
uint32_t ngroup, ng; uint32_t ngroup, ng;
for (ngroup = 0;ngroup < h->ngroups_phich;CP_ISEXT(h->cell.cp)?ngroup+=2:ngroup++) { for (ngroup = 0;ngroup < h->ngroups_phich;CP_ISEXT(h->cell.cp)?ngroup+=2:ngroup++) {
if (CP_ISEXT(h->cell.cp)) { if (CP_ISEXT(h->cell.cp)) {
@ -386,7 +417,7 @@ int regs_phich_reset(regs_t *h, cf_t *slot_symbols) {
* Returns the number of written symbols, or -1 on error * Returns the number of written symbols, or -1 on error
*/ */
int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_NSYM], uint32_t ngroup) { int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_NSYM], uint32_t ngroup) {
int i; uint32_t i;
if (ngroup >= h->ngroups_phich) { if (ngroup >= h->ngroups_phich) {
fprintf(stderr, "Error invalid ngroup %d\n", ngroup); fprintf(stderr, "Error invalid ngroup %d\n", ngroup);
return LIBLTE_ERROR_INVALID_INPUTS; return LIBLTE_ERROR_INVALID_INPUTS;
@ -421,7 +452,7 @@ int regs_phich_get(regs_t *h, cf_t *slot_symbols, cf_t phich_symbols[REGS_PHICH_
* 36.211 10.3 section 6.7.4 * 36.211 10.3 section 6.7.4
*/ */
int regs_pcfich_init(regs_t *h) { int regs_pcfich_init(regs_t *h) {
int i; uint32_t i;
uint32_t k_hat, k; uint32_t k_hat, k;
regs_ch_t *ch = &h->pcfich; regs_ch_t *ch = &h->pcfich;
@ -475,7 +506,7 @@ uint32_t regs_pcfich_nregs(regs_t *h) {
int regs_pcfich_put(regs_t *h, cf_t pcfich_symbols[REGS_PCFICH_NSYM], cf_t *slot_symbols) { int regs_pcfich_put(regs_t *h, cf_t pcfich_symbols[REGS_PCFICH_NSYM], cf_t *slot_symbols) {
regs_ch_t *rch = &h->pcfich; regs_ch_t *rch = &h->pcfich;
int i; uint32_t i;
for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) {
regs_put_reg(rch->regs[i], &pcfich_symbols[i*REGS_RE_X_REG], slot_symbols, h->cell.nof_prb); regs_put_reg(rch->regs[i], &pcfich_symbols[i*REGS_RE_X_REG], slot_symbols, h->cell.nof_prb);
} }
@ -489,7 +520,7 @@ int regs_pcfich_put(regs_t *h, cf_t pcfich_symbols[REGS_PCFICH_NSYM], cf_t *slot
*/ */
int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM]) { int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM]) {
regs_ch_t *rch = &h->pcfich; regs_ch_t *rch = &h->pcfich;
int i; uint32_t i;
for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) { for (i = 0; i < rch->nof_regs && i*REGS_RE_X_REG < REGS_PCFICH_NSYM; i++) {
regs_get_reg(rch->regs[i], slot_symbols, &ch_data[i*REGS_RE_X_REG], h->cell.nof_prb); regs_get_reg(rch->regs[i], slot_symbols, &ch_data[i*REGS_RE_X_REG], h->cell.nof_prb);
} }
@ -516,7 +547,7 @@ int regs_pcfich_get(regs_t *h, cf_t *slot_symbols, cf_t ch_data[REGS_PCFICH_NSYM
***************************************************************/ ***************************************************************/
regs_reg_t *regs_find_reg(regs_t *h, uint32_t k, uint32_t l) { regs_reg_t *regs_find_reg(regs_t *h, uint32_t k, uint32_t l) {
int i; uint32_t i;
for (i=0;i<h->nof_regs;i++) { for (i=0;i<h->nof_regs;i++) {
if (h->regs[i].l == l && h->regs[i].k0 == k) { if (h->regs[i].l == l && h->regs[i].k0 == k) {
return &h->regs[i]; return &h->regs[i];
@ -563,7 +594,7 @@ int regs_num_x_symbol(uint32_t symbol, uint32_t nof_port, lte_cp_t cp) {
* 36.211 Section 6.2.4 * 36.211 Section 6.2.4
*/ */
int regs_reg_init(regs_reg_t *reg, uint32_t symbol, uint32_t nreg, uint32_t k0, uint32_t maxreg, uint32_t vo) { int regs_reg_init(regs_reg_t *reg, uint32_t symbol, uint32_t nreg, uint32_t k0, uint32_t maxreg, uint32_t vo) {
int i, j, z; uint32_t i, j, z;
reg->l = symbol; reg->l = symbol;
reg->assigned = false; reg->assigned = false;
@ -643,10 +674,10 @@ int regs_set_cfi(regs_t *h, uint32_t cfi) {
*/ */
int regs_init(regs_t *h, phich_resources_t phich_res, phich_length_t phich_len, lte_cell_t cell) { int regs_init(regs_t *h, phich_resources_t phich_res, phich_length_t phich_len, lte_cell_t cell) {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
int i, k; uint32_t i, k;
uint32_t j[4], jmax, prb; uint32_t j[4], jmax, prb;
uint32_t n[4], vo; uint32_t n[4], vo;
int max_ctrl_symbols; uint32_t max_ctrl_symbols;
if (h != NULL && if (h != NULL &&
lte_cell_isvalid(&cell)) lte_cell_isvalid(&cell))
@ -727,13 +758,11 @@ clean_and_exit:
return ret; return ret;
} }
#define REG_IDX(r, i, n) r->k[i]+r->l*n*RE_X_RB
/** /**
* Puts one REG data (4 symbols) in the slot symbols array * Puts one REG data (4 symbols) in the slot symbols array
*/ */
int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint32_t nof_prb) { int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint32_t nof_prb) {
int i; uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) { for (i = 0; i < REGS_RE_X_REG; i++) {
slot_symbols[REG_IDX(reg, i, nof_prb)] = reg_data[i]; slot_symbols[REG_IDX(reg, i, nof_prb)] = reg_data[i];
} }
@ -745,7 +774,7 @@ int regs_put_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint32_t n
* Used by PHICH * Used by PHICH
*/ */
int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint32_t nof_prb) { int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint32_t nof_prb) {
int i; uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) { for (i = 0; i < REGS_RE_X_REG; i++) {
slot_symbols[REG_IDX(reg, i, nof_prb)] += reg_data[i]; slot_symbols[REG_IDX(reg, i, nof_prb)] += reg_data[i];
} }
@ -757,7 +786,7 @@ int regs_add_reg(regs_reg_t *reg, cf_t *reg_data, cf_t *slot_symbols, uint32_t n
* Reset REG data (4 symbols) in the slot symbols array * Reset REG data (4 symbols) in the slot symbols array
*/ */
int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, uint32_t nof_prb) { int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, uint32_t nof_prb) {
int i; uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) { for (i = 0; i < REGS_RE_X_REG; i++) {
slot_symbols[REG_IDX(reg, i, nof_prb)] = 0; slot_symbols[REG_IDX(reg, i, nof_prb)] = 0;
} }
@ -768,7 +797,7 @@ int regs_reset_reg(regs_reg_t *reg, cf_t *slot_symbols, uint32_t nof_prb) {
* Gets one REG data (4 symbols) from the slot symbols array * Gets one REG data (4 symbols) from the slot symbols array
*/ */
int regs_get_reg(regs_reg_t *reg, cf_t *slot_symbols, cf_t *reg_data, uint32_t nof_prb) { int regs_get_reg(regs_reg_t *reg, cf_t *slot_symbols, cf_t *reg_data, uint32_t nof_prb) {
int i; uint32_t i;
for (i = 0; i < REGS_RE_X_REG; i++) { for (i = 0; i < REGS_RE_X_REG; i++) {
reg_data[i] = slot_symbols[REG_IDX(reg, i, nof_prb)]; reg_data[i] = slot_symbols[REG_IDX(reg, i, nof_prb)];
} }

@ -208,7 +208,6 @@ void base_free() {
int main(int argc, char **argv) { int main(int argc, char **argv) {
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
int i; int i;
int nof_dcis;
int nof_frames; int nof_frames;
int ret; int ret;
dci_location_t locations[10]; dci_location_t locations[10];
@ -264,20 +263,19 @@ int main(int argc, char **argv) {
} }
} }
if (pdcch_extract_llr(&pdcch, fft_buffer, ce, nof_frames, cfi)) { uint16_t crc_rem = 0;
for (i=0;i<nof_locations && crc_rem != rnti;i++) {
if (pdcch_extract_llr(&pdcch, fft_buffer, ce, locations[i], nof_frames, cfi)) {
fprintf(stderr, "Error extracting LLRs\n"); fprintf(stderr, "Error extracting LLRs\n");
return -1; return -1;
} }
if (pdcch_decode_msg(&pdcch, &dci_msg, Format1A, &crc_rem)) {
nof_dcis = pdcch_decode_msg(&pdcch, &dci_msg, locations, nof_locations, Format1A, rnti); fprintf(stderr, "Error decoding DCI msg\n");
if (nof_dcis < 0) {
fprintf(stderr, "Error decoding DCI messages\n");
return -1; return -1;
} }
}
INFO("Received %d DCI messages\n", nof_dcis); if (crc_rem == rnti) {
if (nof_dcis == 1) {
dci_msg_type_t type; dci_msg_type_t type;
if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, rnti, 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");

@ -105,7 +105,7 @@ int test_dci_payload_size() {
int main(int argc, char **argv) { int main(int argc, char **argv) {
pdcch_t pdcch; pdcch_t pdcch;
dci_msg_t dci_tx[2], dci_rx[2]; dci_msg_t dci_tx[2], dci_rx[2], dci_tmp;
dci_location_t dci_locations[2]; dci_location_t dci_locations[2];
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
regs_t regs; regs_t regs;
@ -173,16 +173,12 @@ int main(int argc, char **argv) {
dci_msg_pack_pdsch(&ra_dl, &dci_tx[1], Format1, cell.nof_prb, false); dci_msg_pack_pdsch(&ra_dl, &dci_tx[1], Format1, cell.nof_prb, false);
dci_location_set(&dci_locations[1], 0, 1); dci_location_set(&dci_locations[1], 0, 1);
pdcch_reset(&pdcch);
for (i=0;i<nof_dcis;i++) { for (i=0;i<nof_dcis;i++) {
if (pdcch_encode_msg(&pdcch, &dci_tx[i], dci_locations[i], 1234+i)) { if (pdcch_encode(&pdcch, &dci_tx[i], dci_locations[i], 1234+i, slot_symbols, 0, cfi)) {
fprintf(stderr, "Error encoding DCI message\n");
goto quit; 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++) {
@ -191,12 +187,21 @@ int main(int argc, char **argv) {
} }
} }
if (pdcch_extract_llr(&pdcch, slot_symbols[0], ce, 0, cfi)) { for (i=0;i<2;i++) {
if (pdcch_extract_llr(&pdcch, slot_symbols[0], ce, dci_locations[i], 0, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
goto quit; goto quit;
} }
uint16_t crc_rem;
for (i=0;i<nof_dcis;i++) { if (pdcch_decode_msg(&pdcch, &dci_tmp, Format1, &crc_rem)) {
if (pdcch_decode_msg(&pdcch, &dci_rx[i], dci_locations, 2, Format1, 1234+i) < 0) { fprintf(stderr, "Error decoding DCI message\n");
goto quit;
}
if (crc_rem >= 1234 && crc_rem < 1234 + nof_dcis) {
crc_rem -= 1234;
memcpy(&dci_rx[crc_rem], &dci_tmp, sizeof(dci_msg_t));
} else {
printf("Received invalid DCI CRC 0x%x\n", crc_rem);
goto quit; goto quit;
} }
} }

@ -218,7 +218,6 @@ int main(int argc, char **argv) {
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
ra_prb_t prb_alloc; ra_prb_t prb_alloc;
int i; int i;
int nof_dcis;
int nof_frames; int nof_frames;
int ret; int ret;
char *data; char *data;
@ -280,17 +279,20 @@ int main(int argc, char **argv) {
} }
} }
pdcch_extract_llr(&pdcch, fft_buffer, ce, nof_frames, cfi);
nof_dcis = pdcch_decode_msg(&pdcch, &dci_msg, locations, nof_locations, Format1A, rnti); uint16_t crc_rem = 0;
if (nof_dcis < 0) { for (i=0;i<nof_locations && crc_rem != rnti;i++) {
fprintf(stderr, "Error decoding DCI messages\n"); if (pdcch_extract_llr(&pdcch, fft_buffer, ce, locations[i], nof_frames, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return -1; return -1;
} }
if (pdcch_decode_msg(&pdcch, &dci_msg, Format1A, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return -1;
}
}
INFO("Received %d DCI messages\n", nof_dcis); if (crc_rem == rnti) {
if (nof_dcis == 1) {
dci_msg_type_t type; dci_msg_type_t type;
if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, rnti, 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");

@ -28,6 +28,7 @@
#include <stdlib.h> #include <stdlib.h>
#include <string.h> #include <string.h>
#include <strings.h> #include <strings.h>
#include <assert.h>
#include "liblte/phy/resampling/decim.h" #include "liblte/phy/resampling/decim.h"
#include "liblte/phy/resampling/resample_arb.h" #include "liblte/phy/resampling/resample_arb.h"
@ -120,6 +121,8 @@ void sync_frame_run(sync_frame_t *q, cf_t *input) {
break; break;
} }
assert(q->peak_idx < TRACK_LEN);
track_idx = sync_track(&q->s, &input[q->peak_idx - TRACK_LEN]); track_idx = sync_track(&q->s, &input[q->peak_idx - TRACK_LEN]);
INFO("TRACK %3d: SF=%d. Previous idx is %d New Offset is %d\n", INFO("TRACK %3d: SF=%d. Previous idx is %d New Offset is %d\n",
@ -140,7 +143,7 @@ void sync_frame_run(sync_frame_t *q, cf_t *input) {
q->cur_cfo = (sync_get_cfo(&q->s) + q->frame_cnt * q->cur_cfo) / (q->frame_cnt + 1); q->cur_cfo = (sync_get_cfo(&q->s) + q->frame_cnt * q->cur_cfo) / (q->frame_cnt + 1);
/* compute cumulative moving average time offset */ /* compute cumulative moving average time offset */
q->timeoffset = (float) (track_idx - TRACK_LEN + q->timeoffset * q->frame_cnt) q->timeoffset = (float) ((float) track_idx - TRACK_LEN + q->timeoffset * q->frame_cnt)
/ (q->frame_cnt + 1); / (q->frame_cnt + 1);
q->last_found = q->frame_cnt; q->last_found = q->frame_cnt;

Loading…
Cancel
Save