Fixed a bug with type 2 distributed resource allocation

master
ismagom 10 years ago
parent 68a6169164
commit 8531fb1a0c

@ -41,6 +41,12 @@
#include "liblte/cuhd/cuhd.h" #include "liblte/cuhd/cuhd.h"
#include "cell_search_utils.h" #include "cell_search_utils.h"
cell_detect_cfg_t cell_detect_config = {
500, // nof_frames_total
50, // nof_frames_detected
CS_FIND_THRESHOLD // threshold
};
/********************************************************************** /**********************************************************************
* Program arguments processing * Program arguments processing
***********************************************************************/ ***********************************************************************/
@ -157,7 +163,7 @@ int main(int argc, char **argv) {
cuhd_rx_wait_lo_locked(uhd); cuhd_rx_wait_lo_locked(uhd);
printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000); printf("Tunning receiver to %.3f MHz\n", (double ) prog_args.uhd_freq/1000000);
if (cell_search(uhd, prog_args.force_N_id_2, &cell)) { if (detect_and_decode_cell(&cell_detect_config, uhd, prog_args.force_N_id_2, &cell)) {
fprintf(stderr, "Cell not found\n"); fprintf(stderr, "Cell not found\n");
exit(-1); exit(-1);
} }
@ -191,7 +197,7 @@ int main(int argc, char **argv) {
} }
int sf_re = SF_LEN_RE(cell.nof_prb, cell.cp); int sf_re = SF_LEN_RE(cell.nof_prb, cell.cp);
printf("%d RE allocated\n", sf_re);
cf_t *sf_symbols = vec_malloc(sf_re * sizeof(cf_t)); cf_t *sf_symbols = vec_malloc(sf_re * sizeof(cf_t));
/* Main loop */ /* Main loop */
@ -201,14 +207,17 @@ int main(int argc, char **argv) {
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error calling ue_sync_work()\n"); fprintf(stderr, "Error calling ue_sync_work()\n");
} }
/* iodev_receive returns 1 if successfully read 1 aligned subframe */ /* ue_sync_get_buffer returns 1 if successfully read 1 aligned subframe */
if (ret == 1) { if (ret == 1) {
switch (state) { switch (state) {
case DECODE_MIB: case DECODE_MIB:
if (ue_sync_get_sfidx(&ue_sync) == 0) { if (ue_sync_get_sfidx(&ue_sync) == 0) {
pbch_decode_reset(&ue_mib.pbch); pbch_decode_reset(&ue_mib.pbch);
n = ue_mib_decode_aligned_frame(&ue_mib, &sf_buffer[ue_sync_sf_len(&ue_sync)/2], bch_payload_unpacked, NULL, &sfn_offset); n = ue_mib_decode_aligned_frame(&ue_mib,
sf_buffer, bch_payload_unpacked,
NULL, &sfn_offset);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE MIB\n"); fprintf(stderr, "Error decoding UE MIB\n");
exit(-1); exit(-1);
@ -223,20 +232,17 @@ int main(int argc, char **argv) {
break; break;
case DECODE_SIB: case DECODE_SIB:
sfn=0; sfn=0;
/* If we are looking for SI Blocks, search only in appropiate places */ /* We are looking for SI Blocks, search only in appropiate places */
if ((sfn % 2) == 0 && (ue_sync_get_sfidx(&ue_sync) == 5)) { if ((ue_sync_get_sfidx(&ue_sync) == 5 && (sfn%2)==0)) {
n = ue_dl_decode(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), sfn, SIRNTI); n = ue_dl_decode(&ue_dl, sf_buffer, data, ue_sync_get_sfidx(&ue_sync), sfn, SIRNTI);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); fprintf(stderr, "Error decoding UE DL\n");fflush(stdout);
exit(-1); exit(-1);
} else if (n == 0) { } else if (n == 0) {
// Printf printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, ExecTime: %5.1f us, NOI: %.2f, PDCCH-Det: %.3f\r",
// if (!(sf_cnt%20)) {
printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, ExecTime: %5.1f us, NOI: %.2f, Nof Trials: %4d, Nof Error: %4d\r",
ue_sync_get_cfo(&ue_sync)/1000, ue_sync_get_sfo(&ue_sync)/1000, ue_sync_get_cfo(&ue_sync)/1000, ue_sync_get_sfo(&ue_sync)/1000,
mean_exec_time, pdsch_average_noi(&ue_dl.pdsch), mean_exec_time, pdsch_average_noi(&ue_dl.pdsch),
(int) nof_trials, (int) ue_dl.pkt_errors); (float) ue_dl.nof_pdcch_detected/nof_trials);
// }
nof_trials++; nof_trials++;
} else { } else {
printf("\n\nDecoded SIB1 Message Len %d: ",n); printf("\n\nDecoded SIB1 Message Len %d: ",n);

@ -54,9 +54,8 @@
int band = -1; int band = -1;
int earfcn_start=-1, earfcn_end = -1; int earfcn_start=-1, earfcn_end = -1;
int nof_frames_total = 50;
int nof_frames_detected = 10; cell_detect_cfg_t config = {50, 10, CS_FIND_THRESHOLD};
float threshold = CS_FIND_THRESHOLD;
float uhd_gain = 60.0; float uhd_gain = 60.0;
@ -70,7 +69,7 @@ void usage(char *prog) {
printf("\t-e earfcn_end [Default All]\n"); printf("\t-e earfcn_end [Default All]\n");
printf("\t-n nof_frames_total [Default 100]\n"); printf("\t-n nof_frames_total [Default 100]\n");
printf("\t-d nof_frames_detected [Default 10]\n"); printf("\t-d nof_frames_detected [Default 10]\n");
printf("\t-t threshold [Default %.2f]\n",threshold); printf("\t-t threshold [Default %.2f]\n",config.threshold);
printf("\t-v [set verbose to debug, default none]\n"); printf("\t-v [set verbose to debug, default none]\n");
} }
@ -91,13 +90,13 @@ void parse_args(int argc, char **argv) {
earfcn_end = atoi(argv[optind]); earfcn_end = atoi(argv[optind]);
break; break;
case 'n': case 'n':
nof_frames_total = atoi(argv[optind]); config.nof_frames_total = atoi(argv[optind]);
break; break;
case 'd': case 'd':
nof_frames_detected = atoi(argv[optind]); config.nof_frames_detected = atoi(argv[optind]);
break; break;
case 't': case 't':
threshold = atof(argv[optind]); config.threshold = atof(argv[optind]);
break; break;
case 'g': case 'g':
uhd_gain = atof(argv[optind]); uhd_gain = atof(argv[optind]);
@ -119,7 +118,6 @@ void parse_args(int argc, char **argv) {
int main(int argc, char **argv) { int main(int argc, char **argv) {
int n; int n;
void *uhd; void *uhd;
ue_celldetect_t s;
ue_celldetect_result_t found_cells[3]; ue_celldetect_result_t found_cells[3];
int nof_freqs; int nof_freqs;
lte_earfcn_t channels[MAX_EARFCN]; lte_earfcn_t channels[MAX_EARFCN];
@ -142,21 +140,6 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (ue_celldetect_init(&s)) {
fprintf(stderr, "Error initiating UE sync module\n");
exit(-1);
}
if (threshold > 0) {
ue_celldetect_set_threshold(&s, threshold);
}
if (nof_frames_total > 0) {
ue_celldetect_set_nof_frames_total(&s, nof_frames_total);
}
if (nof_frames_detected > 0) {
ue_celldetect_set_nof_frames_detected(&s, nof_frames_detected);
}
for (freq=0;freq<nof_freqs;freq+=10) { for (freq=0;freq<nof_freqs;freq+=10) {
/* set uhd_freq */ /* set uhd_freq */
@ -172,15 +155,15 @@ int main(int argc, char **argv) {
printf("\n"); printf("\n");
} }
n = find_all_cells(uhd, found_cells); n = detect_all_cells(&config, uhd, found_cells);
if (n < 0) { if (n < 0) {
fprintf(stderr, "Error searching cell\n"); fprintf(stderr, "Error searching cell\n");
exit(-1); exit(-1);
} }
if (n == CS_CELL_DETECTED) { if (n == CS_CELL_DETECTED) {
for (int i=0;i<3;i++) { for (int i=0;i<3;i++) {
if (found_cells[i].peak > threshold/2) { if (found_cells[i].peak > config.threshold/2) {
if (decode_pbch(uhd, &found_cells[i], nof_frames_total, bch_payload, &nof_tx_ports, NULL)) { if (decode_pbch(uhd, &found_cells[i], config.nof_frames_total, bch_payload, &nof_tx_ports, NULL)) {
fprintf(stderr, "Error decoding PBCH\n"); fprintf(stderr, "Error decoding PBCH\n");
exit(-1); exit(-1);
} else { } else {
@ -194,7 +177,6 @@ int main(int argc, char **argv) {
printf("\nBye\n"); printf("\nBye\n");
ue_celldetect_free(&s);
cuhd_close(uhd); cuhd_close(uhd);
exit(0); exit(0);
} }

@ -37,6 +37,8 @@
#include "liblte/phy/phy.h" #include "liblte/phy/phy.h"
#include "liblte/rrc/rrc.h" #include "liblte/rrc/rrc.h"
#include "cell_search_utils.h"
#ifndef DISABLE_UHD #ifndef DISABLE_UHD
#include "liblte/cuhd/cuhd.h" #include "liblte/cuhd/cuhd.h"
@ -82,6 +84,7 @@ int decode_pbch(void *uhd, ue_celldetect_result_t *found_cell, uint32_t nof_fram
} }
if (n == MIB_FRAME_UNALIGNED) { if (n == MIB_FRAME_UNALIGNED) {
printf("Realigning frame\n"); printf("Realigning frame\n");
// Receive some randon number of samples to try to resynchronise the frame.
if (cuhd_recv(uhd, buffer, 1500, 1)<0) { if (cuhd_recv(uhd, buffer, 1500, 1)<0) {
fprintf(stderr, "Error receiving from USRP\n"); fprintf(stderr, "Error receiving from USRP\n");
goto free_and_exit; goto free_and_exit;
@ -110,7 +113,7 @@ free_and_exit:
return ret; return ret;
} }
int find_cell(void *uhd, ue_celldetect_result_t *found_cell, uint32_t N_id_2) int detect_cell(cell_detect_cfg_t *config, void *uhd, ue_celldetect_result_t *found_cell, uint32_t N_id_2)
{ {
int ret = LIBLTE_ERROR; int ret = LIBLTE_ERROR;
ue_celldetect_t cd; ue_celldetect_t cd;
@ -125,6 +128,16 @@ int find_cell(void *uhd, ue_celldetect_result_t *found_cell, uint32_t N_id_2)
fprintf(stderr, "Error initiating UE cell detect\n"); fprintf(stderr, "Error initiating UE cell detect\n");
goto free_and_exit; goto free_and_exit;
} }
if (config->nof_frames_detected) {
ue_celldetect_set_nof_frames_detected(&cd, config->nof_frames_detected);
}
if (config->nof_frames_total) {
ue_celldetect_set_nof_frames_total(&cd, config->nof_frames_total);
}
if (config->threshold) {
ue_celldetect_set_threshold(&cd, config->threshold);
}
INFO("Setting sampling frequency 960 KHz for PSS search\n", 0); INFO("Setting sampling frequency 960 KHz for PSS search\n", 0);
cuhd_set_rx_srate(uhd, 960000.0); cuhd_set_rx_srate(uhd, 960000.0);
@ -192,7 +205,7 @@ free_and_exit:
} }
int find_all_cells(void *uhd, ue_celldetect_result_t found_cell[3]) int detect_all_cells(cell_detect_cfg_t *config, void *uhd, ue_celldetect_result_t found_cell[3])
{ {
uint32_t N_id_2; uint32_t N_id_2;
@ -200,7 +213,7 @@ int find_all_cells(void *uhd, ue_celldetect_result_t found_cell[3])
int nof_detected_cells = 0; int nof_detected_cells = 0;
for (N_id_2=0;N_id_2<3;N_id_2++) { for (N_id_2=0;N_id_2<3;N_id_2++) {
ret = find_cell(uhd, &found_cell[N_id_2], N_id_2); ret = detect_cell(config, uhd, &found_cell[N_id_2], N_id_2);
if (ret == 1) { if (ret == 1) {
nof_detected_cells++; nof_detected_cells++;
} else if (ret == LIBLTE_ERROR) { } else if (ret == LIBLTE_ERROR) {
@ -210,7 +223,7 @@ int find_all_cells(void *uhd, ue_celldetect_result_t found_cell[3])
return nof_detected_cells; return nof_detected_cells;
} }
int cell_search(void *uhd, int force_N_id_2, lte_cell_t *cell) int detect_and_decode_cell(cell_detect_cfg_t *config, void *uhd, int force_N_id_2, lte_cell_t *cell)
{ {
int ret; int ret;
uint32_t nof_tx_ports; uint32_t nof_tx_ports;
@ -219,14 +232,10 @@ int cell_search(void *uhd, int force_N_id_2, lte_cell_t *cell)
ue_celldetect_result_t found_cells[3]; ue_celldetect_result_t found_cells[3];
bzero(found_cells, 3*sizeof(ue_celldetect_result_t)); bzero(found_cells, 3*sizeof(ue_celldetect_result_t));
ue_celldetect_set_nof_frames_detected(&cd, 50);
ue_celldetect_set_nof_frames_total(&cd, 500);
if (force_N_id_2 >= 0) { if (force_N_id_2 >= 0) {
ret = find_cell(uhd, &found_cells[force_N_id_2], force_N_id_2); ret = detect_cell(config, uhd, &found_cells[force_N_id_2], force_N_id_2);
} else { } else {
ret = find_all_cells(uhd, found_cells); ret = detect_all_cells(config, uhd, found_cells);
} }
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error searching cell\n"); fprintf(stderr, "Error searching cell\n");

@ -28,6 +28,12 @@
#include "liblte/phy/phy.h" #include "liblte/phy/phy.h"
typedef struct LIBLTE_API {
uint32_t nof_frames_total;
uint32_t nof_frames_detected;
float threshold;
}cell_detect_cfg_t;
int decode_pbch(void *uhd, int decode_pbch(void *uhd,
ue_celldetect_result_t *found_cell, ue_celldetect_result_t *found_cell,
uint32_t nof_frames_total, uint32_t nof_frames_total,
@ -35,13 +41,16 @@ int decode_pbch(void *uhd,
uint32_t *nof_tx_ports, uint32_t *nof_tx_ports,
uint32_t *sfn_offset); uint32_t *sfn_offset);
int find_all_cells(void *uhd, int detect_all_cells(cell_detect_cfg_t *config,
ue_celldetect_result_t found_cell[3]); void *uhd,
ue_celldetect_result_t found_cell[3]);
int find_cell(void *uhd, int detect_cell(cell_detect_cfg_t *config,
ue_celldetect_result_t *found_cell, void *uhd,
uint32_t N_id_2); ue_celldetect_result_t *found_cell,
uint32_t N_id_2);
int cell_search(void *uhd, int detect_and_decode_cell(cell_detect_cfg_t *config,
int force_N_id_2, void *uhd,
lte_cell_t *cell); int force_N_id_2,
lte_cell_t *cell);

@ -98,8 +98,11 @@ int iodev_init(iodev_t *q, iodev_cfg_t *config, lte_cell_t *cell) {
cuhd_set_rx_freq(q->uhd, (double) config->uhd_freq); cuhd_set_rx_freq(q->uhd, (double) config->uhd_freq);
cuhd_rx_wait_lo_locked(q->uhd); cuhd_rx_wait_lo_locked(q->uhd);
DEBUG("Set uhd_freq to %.3f MHz\n", (double ) config->uhd_freq); DEBUG("Set uhd_freq to %.3f MHz\n", (double ) config->uhd_freq);
cell_detect_cfg_t detect_config;
bzero(&detect_config, sizeof(cell_detect_cfg_t));
if (cell_search(q->uhd, config->force_N_id_2, cell)) { if (detect_and_decode_cell(&detect_config, q->uhd, config->force_N_id_2, cell)) {
fprintf(stderr, "Cell not found\n"); fprintf(stderr, "Cell not found\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }

@ -46,7 +46,7 @@ typedef _Complex float cf_t;
#define DCI_MAX_BITS 57 #define DCI_MAX_BITS 57
typedef enum { typedef enum {
Format0, Format1, Format1A, Format1C Format0, Format1, Format1A, Format1C, FormatError
} dci_format_t; } dci_format_t;
// Each type is for a different interface to packing/unpacking functions // Each type is for a different interface to packing/unpacking functions
@ -89,6 +89,8 @@ LIBLTE_API int dci_msg_to_ra_ul(dci_msg_t *msg,
uint32_t cfi, uint32_t cfi,
ra_pusch_t *ra_ul); ra_pusch_t *ra_ul);
*/ */
LIBLTE_API dci_format_t dci_format_from_string(char *str);
LIBLTE_API char* dci_format_string(dci_format_t format); LIBLTE_API char* dci_format_string(dci_format_t format);
LIBLTE_API int dci_location_set(dci_location_t *c, LIBLTE_API int dci_location_set(dci_location_t *c,

@ -53,7 +53,6 @@ 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 e_bits;
uint32_t nof_regs; uint32_t nof_regs;
uint32_t nof_cce; uint32_t nof_cce;
uint32_t max_bits; uint32_t max_bits;
@ -99,13 +98,13 @@ 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],
float noise_estimate, float noise_estimate,
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 *location,
dci_format_t format, dci_format_t format,
uint16_t *crc_rem); uint16_t *crc_rem);

@ -39,7 +39,7 @@
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
lte_mod_t mod; lte_mod_t mod;
uint32_t tbs; int tbs;
} ra_mcs_t; } ra_mcs_t;
typedef enum LIBLTE_API { typedef enum LIBLTE_API {
@ -72,7 +72,7 @@ typedef struct LIBLTE_API {
} ra_type2_t; } ra_type2_t;
typedef struct LIBLTE_API { typedef struct LIBLTE_API {
uint32_t prb_idx[MAX_PRB]; bool prb_idx[MAX_PRB];
uint32_t nof_prb; uint32_t nof_prb;
} ra_prb_slot_t; } ra_prb_slot_t;
@ -123,7 +123,8 @@ typedef struct LIBLTE_API {
} ra_pusch_t; } ra_pusch_t;
LIBLTE_API void ra_prb_fprint(FILE *f, LIBLTE_API void ra_prb_fprint(FILE *f,
ra_prb_slot_t *prb); ra_prb_slot_t *prb,
uint32_t nof_prb);
LIBLTE_API int ra_prb_get_dl(ra_prb_t *prb, LIBLTE_API int ra_prb_get_dl(ra_prb_t *prb,
ra_pdsch_t *ra, ra_pdsch_t *ra,

@ -73,6 +73,7 @@ typedef struct LIBLTE_API {
uint64_t pkt_errors; uint64_t pkt_errors;
uint64_t pkts_total; uint64_t pkts_total;
uint64_t nof_pdcch_detected;
uint16_t user_rnti; uint16_t user_rnti;
}ue_dl_t; }ue_dl_t;

@ -210,10 +210,7 @@ int refsignal_cs_put_sf(lte_cell_t cell, uint32_t port_id, cf_t *pilots, cf_t *s
fidx = ((refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6); fidx = ((refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6);
for (i = 0; i < 2*cell.nof_prb; i++) { for (i = 0; i < 2*cell.nof_prb; i++) {
sf_symbols[SAMPLE_IDX(cell.nof_prb, nsymbol, fidx)] = pilots[REFSIGNAL_PILOT_IDX(i,l,cell)]; sf_symbols[SAMPLE_IDX(cell.nof_prb, nsymbol, fidx)] = pilots[REFSIGNAL_PILOT_IDX(i,l,cell)];
fidx += 6; // 1 reference every 6 RE fidx += 6; // 1 reference every 6 RE
DEBUG("Putting %d to %d (fidx: %d, lp:%d)\n",
REFSIGNAL_PILOT_IDX(i,l,cell), SAMPLE_IDX(cell.nof_prb, nsymbol, fidx),
fidx, nsymbol);
} }
} }
return LIBLTE_SUCCESS; return LIBLTE_SUCCESS;
@ -242,9 +239,6 @@ int refsignal_cs_get_sf(lte_cell_t cell, uint32_t port_id, cf_t *sf_symbols, cf_
fidx = ((refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6); fidx = ((refsignal_cs_v(port_id, l) + (cell.id % 6)) % 6);
for (i = 0; i < 2*cell.nof_prb; i++) { for (i = 0; i < 2*cell.nof_prb; i++) {
pilots[REFSIGNAL_PILOT_IDX(i,l,cell)] = sf_symbols[SAMPLE_IDX(cell.nof_prb, nsymbol, fidx)]; pilots[REFSIGNAL_PILOT_IDX(i,l,cell)] = sf_symbols[SAMPLE_IDX(cell.nof_prb, nsymbol, fidx)];
DEBUG("Getting %d from %d (fidx: %d, lp:%d)\n",REFSIGNAL_PILOT_IDX(i,l,cell),
SAMPLE_IDX(cell.nof_prb, nsymbol, fidx),
fidx, nsymbol);
fidx += RE_X_RB/2; // 2 references per PRB fidx += RE_X_RB/2; // 2 references per PRB
} }
} }

@ -98,7 +98,7 @@ int rm_conv_rx(float *input, uint32_t in_len, float *output, uint32_t out_len) {
int d_i, d_j; int d_i, d_j;
float tmp[3 * NCOLS * NROWS_MAX]; float tmp[3 * NCOLS * NROWS_MAX];
nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1; nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1;
if (nrows > NROWS_MAX) { if (nrows > NROWS_MAX) {
fprintf(stderr, "Output too large. Max output length is %d\n", fprintf(stderr, "Output too large. Max output length is %d\n",

@ -171,7 +171,7 @@ int predecoding_diversity(precoding_t *q, cf_t *y, cf_t *h[MAX_PORTS], cf_t *x[M
// (H'H + n0) // (H'H + n0)
vec_sc_add_fff(modhh, noise_estimate, modhh, nof_symbols/2); vec_sc_add_fff(modhh, noise_estimate, modhh, nof_symbols/2);
} }
vec_sc_prod_fff(modhh, 1.0/sqrt(2), modhh, nof_symbols/2); //vec_sc_prod_fff(modhh, 1.0/sqrt(2), modhh, nof_symbols/2);
// x[0] = r0·h0*/(|h0|+|h1|)+r1*·h1/(|h0|+|h1|) // x[0] = r0·h0*/(|h0|+|h1|)+r1*·h1/(|h0|+|h1|)
vec_prod_conj_ccc(r0,h0,q->tmp1, nof_symbols/2); vec_prod_conj_ccc(r0,h0,q->tmp1, nof_symbols/2);

@ -132,7 +132,7 @@ int main(int argc, char **argv) {
/* generate random data */ /* generate random data */
for (i = 0; i < nof_layers; i++) { for (i = 0; i < nof_layers; i++) {
for (j = 0; j < nof_symbols; j++) { for (j = 0; j < nof_symbols; j++) {
x[i][j] = (float) rand()/RAND_MAX+((float) rand()/RAND_MAX)*_Complex_I; x[i][j] = (2*(rand()%2)-1+(2*(rand()%2)-1)*_Complex_I)/sqrt(2);
} }
} }
@ -153,7 +153,7 @@ int main(int argc, char **argv) {
h[i][nof_layers*j] = (float) rand()/RAND_MAX+((float) rand()/RAND_MAX)*_Complex_I; h[i][nof_layers*j] = (float) rand()/RAND_MAX+((float) rand()/RAND_MAX)*_Complex_I;
// assume the channel is time-invariant in nlayer consecutive symbols // assume the channel is time-invariant in nlayer consecutive symbols
for (int k=0;k<nof_layers;k++) { for (int k=0;k<nof_layers;k++) {
h[i][nof_layers*j+k] = h[i][nof_layers*j]; h[i][nof_layers*j+k] = h[i][nof_layers*j];
} }
} }
} }
@ -170,34 +170,30 @@ int main(int argc, char **argv) {
} }
} }
float noise_estimate[2] = {0, 0.0000001};
const char *algs[2] = {"ZF", "MMSE"};
/* predecoding / equalization */ /* predecoding / equalization */
struct timeval t[3]; struct timeval t[3];
for (int a=0;a<2;a++) { gettimeofday(&t[1], NULL);
gettimeofday(&t[1], NULL); if (predecoding_type(&precoding, r[0], h, xr, nof_ports, nof_layers,
if (predecoding_type(&precoding, r[0], h, xr, nof_ports, nof_layers, nof_symbols * nof_layers, type, 0) < 0) {
nof_symbols * nof_layers, type, noise_estimate[a]) < 0) { fprintf(stderr, "Error layer mapper encoder\n");
fprintf(stderr, "Error layer mapper encoder\n"); exit(-1);
exit(-1); }
} gettimeofday(&t[2], NULL);
gettimeofday(&t[2], NULL); get_time_interval(t);
get_time_interval(t); printf("Execution Time: %d us\n", t[0].tv_usec);
printf("Execution Time %s: %d us\n", algs[a], t[0].tv_usec);
/* check errors */
/* check errors */ mse = 0;
mse = 0; for (i = 0; i < nof_layers; i++) {
for (i = 0; i < nof_layers; i++) { for (j = 0; j < nof_symbols; j++) {
for (j = 0; j < nof_symbols; j++) { printf("%f - %f\n", crealf(xr[i][j]), crealf(x[i][j]));
mse += cabsf(xr[i][j] - x[i][j]); mse += cabsf(xr[i][j] - x[i][j]);
}
} }
printf("MSE %s: %f\n", algs[a], mse);
if (mse / nof_layers / nof_symbols > MSE_THRESHOLD) {
exit(-1);
}
} }
printf("MSE: %f\n", mse/ nof_layers / nof_symbols );
if (mse / nof_layers / nof_symbols > MSE_THRESHOLD) {
exit(-1);
}
for (i = 0; i < nof_layers; i++) { for (i = 0; i < nof_layers; i++) {
free(x[i]); free(x[i]);

@ -61,7 +61,8 @@ int dci_msg_to_ra_dl(dci_msg_t *msg, uint16_t msg_rnti, uint16_t c_rnti,
return ret; return ret;
} }
if (VERBOSE_ISDEBUG()) { if (VERBOSE_ISINFO()) {
INFO("",0);
dci_msg_type_fprint(stdout, type); dci_msg_type_fprint(stdout, type);
} }
if (type.type == PDSCH_SCHED) { if (type.type == PDSCH_SCHED) {
@ -72,7 +73,7 @@ int dci_msg_to_ra_dl(dci_msg_t *msg, uint16_t msg_rnti, uint16_t c_rnti,
return ret; return ret;
} }
if (VERBOSE_ISDEBUG()) { if (VERBOSE_ISINFO()) {
ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb); ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb);
} }
@ -733,6 +734,20 @@ int dci_msg_unpack_pusch(dci_msg_t *msg, ra_pusch_t *data, uint32_t nof_prb) {
return dci_format0_unpack(msg, data, nof_prb); return dci_format0_unpack(msg, data, nof_prb);
} }
dci_format_t dci_format_from_string(char *str) {
if (!strcmp(str, "Format0")) {
return Format0;
} else if (!strcmp(str, "Format1")) {
return Format1;
} else if (!strcmp(str, "Format1A")) {
return Format1A;
} else if (!strcmp(str, "Format1C")) {
return Format1C;
} else {
return FormatError;
}
}
char* dci_format_string(dci_format_t format) { char* dci_format_string(dci_format_t format) {
switch (format) { switch (format) {
case Format0: case Format0:

@ -49,14 +49,6 @@
#define MIN(a,b) ((a>b)?b:a) #define MIN(a,b) ((a>b)?b:a)
#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
static void set_cfi(pdcch_t *q, uint32_t cfi) { static void set_cfi(pdcch_t *q, uint32_t cfi) {
if (cfi > 0 && cfi < 4) { if (cfi > 0 && cfi < 4) {
q->nof_regs = (regs_pdcch_nregs(q->regs, cfi) / 9) * 9; q->nof_regs = (regs_pdcch_nregs(q->regs, cfi) / 9) * 9;
@ -83,10 +75,11 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
fprintf(stderr, "Error initializing precoding\n"); fprintf(stderr, "Error initializing precoding\n");
} }
/* Allocate memory for the largest aggregation level L=3 */ /* Allocate memory for the maximum number of PDCCH bits (CFI=3) */
q->max_bits = PDCCH_FORMAT_NOF_BITS(3); q->max_bits = (regs_pdcch_nregs(q->regs, 3) / 9) * 72;
INFO("Init PDCCH: %d bits, %d symbols, %d ports\n", q->max_bits, q->max_bits/2, q->cell.nof_ports); INFO("Init PDCCH: Max bits: %d, %d ports.\n",
q->max_bits, q->cell.nof_ports);
if (modem_table_lte(&q->mod, LTE_QPSK, true)) { if (modem_table_lte(&q->mod, LTE_QPSK, true)) {
goto clean; goto clean;
@ -112,31 +105,33 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) {
goto clean; goto clean;
} }
q->pdcch_e = malloc(sizeof(uint8_t) * q->max_bits); q->pdcch_e = vec_malloc(sizeof(uint8_t) * q->max_bits);
if (!q->pdcch_e) { if (!q->pdcch_e) {
goto clean; goto clean;
} }
q->pdcch_llr = malloc(sizeof(float) * q->max_bits); q->pdcch_llr = vec_malloc(sizeof(float) * q->max_bits);
if (!q->pdcch_llr) { if (!q->pdcch_llr) {
goto clean; goto clean;
} }
bzero(q->pdcch_llr, sizeof(float) * q->max_bits);
q->pdcch_d = malloc(sizeof(cf_t) * q->max_bits / 2); q->pdcch_d = vec_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->max_bits / 2); q->ce[i] = vec_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->max_bits / 2); q->pdcch_x[i] = vec_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->max_bits / 2); q->pdcch_symbols[i] = vec_malloc(sizeof(cf_t) * q->max_bits / 2);
if (!q->pdcch_symbols[i]) { if (!q->pdcch_symbols[i]) {
goto clean; goto clean;
} }
@ -204,7 +199,7 @@ uint32_t pdcch_ue_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidat
// Compute Yk for this subframe // Compute Yk for this subframe
Yk = rnti; Yk = rnti;
for (m = 0; m < nsubframe; m++) { for (m = 0; m < nsubframe+1; m++) {
Yk = (39827 * Yk) % 65537; Yk = (39827 * Yk) % 65537;
} }
@ -213,7 +208,7 @@ uint32_t pdcch_ue_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidat
for (l = 3; l >= 0; l--) { for (l = 3; l >= 0; l--) {
L = (1 << l); L = (1 << l);
// For all possible ncce offset // For all possible ncce offset
for (i = 0; i < MIN(q->nof_cce / L, 16 / S[l]); i++) { for (i = 0; i < MIN(q->nof_cce / L, S[l]/PDCCH_FORMAT_NOF_CCE(l)); i++) {
ncce = L * ((Yk + i) % (q->nof_cce / L)); ncce = L * ((Yk + i) % (q->nof_cce / L));
if (k < max_candidates && if (k < max_candidates &&
ncce + PDCCH_FORMAT_NOF_CCE(l) <= q->nof_cce) ncce + PDCCH_FORMAT_NOF_CCE(l) <= q->nof_cce)
@ -221,7 +216,7 @@ uint32_t pdcch_ue_locations(pdcch_t *q, dci_location_t *c, uint32_t max_candidat
c[k].L = l; c[k].L = l;
c[k].ncce = ncce; c[k].ncce = ncce;
DEBUG("UE-specific SS Candidate %d: nCCE: %d, L: %d\n", INFO("UE-specific SS Candidate %d: nCCE: %d, L: %d\n",
k, c[k].ncce, c[k].L); k, c[k].ncce, c[k].L);
k++; k++;
@ -256,7 +251,7 @@ uint32_t pdcch_common_locations(pdcch_t *q, dci_location_t *c, uint32_t max_cand
if (k < max_candidates) { if (k < max_candidates) {
c[k].L = l; c[k].L = l;
c[k].ncce = (L) * (i % (q->nof_cce / (L))); c[k].ncce = (L) * (i % (q->nof_cce / (L)));
DEBUG("Common SS Candidate %d: nCCE: %d, L: %d\n", INFO("Common SS Candidate %d: nCCE: %d, L: %d\n",
k, c[k].ncce, c[k].L); k, c[k].ncce, c[k].L);
k++; k++;
} }
@ -291,6 +286,11 @@ static int dci_decode(pdcch_t *q, float *e, uint8_t *data, uint32_t E, uint32_t
nof_bits <= DCI_MAX_BITS) nof_bits <= DCI_MAX_BITS)
{ {
DEBUG("Rm input: ", 0);
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));
@ -309,7 +309,7 @@ static int dci_decode(pdcch_t *q, float *e, uint8_t *data, uint32_t E, uint32_t
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_checksum: 0x%x, crc_rem: 0x%x\n", p_bits, crc_res, INFO("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) {
@ -327,18 +327,30 @@ static int dci_decode(pdcch_t *q, float *e, uint8_t *data, uint32_t E, uint32_t
* The decoded message is stored in msg and the CRC remainder in crc_rem pointer * The decoded message is stored in msg and the CRC remainder in crc_rem pointer
* *
*/ */
int pdcch_decode_msg(pdcch_t *q, dci_msg_t *msg, dci_format_t format, uint16_t *crc_rem) int pdcch_decode_msg(pdcch_t *q, dci_msg_t *msg, dci_location_t *location, dci_format_t format, uint16_t *crc_rem)
{ {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
if (q != NULL && if (q != NULL &&
msg != NULL && msg != NULL &&
dci_location_isvalid(location) &&
crc_rem != NULL) crc_rem != NULL)
{ {
uint32_t nof_bits = dci_format_sizeof(format, q->cell.nof_prb); if (location->ncce * 72 + PDCCH_FORMAT_NOF_BITS(location->L) >
q->nof_cce*72) {
fprintf(stderr, "Invalid location: nCCE: %d, L: %d, NofCCE: %d\n",
location->ncce, location->L, q->nof_cce);
} else {
uint32_t nof_bits = dci_format_sizeof(format, q->cell.nof_prb);
uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location->L);
ret = dci_decode(q, q->pdcch_llr, msg->data, q->e_bits, nof_bits, crc_rem); INFO("Decoding DCI offset %d, e_bits: %d, msg_len %d (nCCE: %d, L: %d)\n",
if (ret == LIBLTE_SUCCESS) { location->ncce * 72, e_bits, nof_bits, location->ncce, location->L);
msg->nof_bits = nof_bits;
ret = dci_decode(q, &q->pdcch_llr[location->ncce * 72],
msg->data, e_bits, nof_bits, crc_rem);
if (ret == LIBLTE_SUCCESS) {
msg->nof_bits = nof_bits;
}
} }
} }
return ret; return ret;
@ -350,7 +362,7 @@ int pdcch_decode_msg(pdcch_t *q, dci_msg_t *msg, dci_format_t format, uint16_t *
* new messages from other locations can be decoded * new messages from other locations can be decoded
*/ */
int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_estimate, int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_estimate,
dci_location_t location, uint32_t nsubframe, uint32_t cfi) { uint32_t nsubframe, uint32_t cfi) {
int ret = LIBLTE_ERROR_INVALID_INPUTS; int ret = LIBLTE_ERROR_INVALID_INPUTS;
@ -361,74 +373,66 @@ int pdcch_extract_llr(pdcch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float n
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); uint32_t e_bits = 72*q->nof_cce;
nof_symbols = q->e_bits/2; nof_symbols = e_bits/2;
ret = LIBLTE_ERROR; ret = LIBLTE_ERROR;
if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce) { INFO("Extracting LLRs: E: %d, SF: %d, CFI: %d\n",
e_bits, nsubframe, cfi);
INFO("Extracting LLRs: E: %d, nCCE: %d, L: %d, SF: %d, CFI: %d\n",
q->e_bits, location.ncce, location.L, nsubframe, cfi);
/* 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));
/* extract symbols */
int n = regs_pdcch_get(q->regs, sf_symbols, q->pdcch_symbols[0]);
if (nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return ret;
}
/* extract symbols */ /* extract channel estimates */
int n = regs_pdcch_get_offset(q->regs, sf_symbols, q->pdcch_symbols[0], for (i = 0; i < q->cell.nof_ports; i++) {
location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L)); n = regs_pdcch_get(q->regs, ce[i], q->ce[i]);
if (nof_symbols != n) { if (nof_symbols != n) {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n); fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n);
return ret; return ret;
} }
}
/* extract channel estimates */ /* in control channels, only diversity is supported */
for (i = 0; i < q->cell.nof_ports; i++) { if (q->cell.nof_ports == 1) {
n = regs_pdcch_get_offset(q->regs, ce[i], q->ce[i], /* no need for layer demapping */
location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L)); predecoding_single(&q->precoding, q->pdcch_symbols[0], q->ce[0], q->pdcch_d, nof_symbols, noise_estimate);
if (nof_symbols != n) { } else {
fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n); predecoding_diversity(&q->precoding, q->pdcch_symbols[0], q->ce, x, q->cell.nof_ports, nof_symbols, noise_estimate);
return ret; layerdemap_diversity(x, q->pdcch_d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
} }
}
/* in control channels, only diversity is supported */
if (q->cell.nof_ports == 1) {
/* no need for layer demapping */
predecoding_single(&q->precoding, q->pdcch_symbols[0], q->ce[0], q->pdcch_d, nof_symbols, noise_estimate);
} else {
predecoding_diversity(&q->precoding, q->pdcch_symbols[0], q->ce, x, q->cell.nof_ports, nof_symbols, noise_estimate);
layerdemap_diversity(x, q->pdcch_d, q->cell.nof_ports, nof_symbols / q->cell.nof_ports);
}
DEBUG("pdcch d symbols: ", 0);
if (VERBOSE_ISDEBUG()) {
vec_fprint_c(stdout, q->pdcch_d, nof_symbols);
}
/* demodulate symbols */ DEBUG("pdcch d symbols: ", 0);
demod_soft_sigma_set(&q->demod, 1.0); if (VERBOSE_ISDEBUG()) {
demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, nof_symbols); vec_fprint_c(stdout, q->pdcch_d, nof_symbols);
}
DEBUG("llr: ", 0); /* demodulate symbols */
if (VERBOSE_ISDEBUG()) { demod_soft_sigma_set(&q->demod, 1);
vec_fprint_f(stdout, q->pdcch_llr, q->e_bits); demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, nof_symbols);
}
/* descramble */ /* descramble */
scrambling_f_offset(&q->seq_pdcch[nsubframe], q->pdcch_llr, 72 * location.ncce, q->e_bits); scrambling_f_offset(&q->seq_pdcch[nsubframe], q->pdcch_llr, 0, e_bits);
ret = LIBLTE_SUCCESS; DEBUG("llr: ", 0);
} else { if (VERBOSE_ISDEBUG()) {
fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d\n", location.ncce, location.L, q->nof_cce); vec_fprint_f(stdout, q->pdcch_llr, e_bits);
} }
ret = LIBLTE_SUCCESS;
} }
return ret; return ret;
} }
@ -514,17 +518,17 @@ int pdcch_encode(pdcch_t *q, dci_msg_t *msg, dci_location_t location, uint16_t r
set_cfi(q, cfi); set_cfi(q, cfi);
q->e_bits = PDCCH_FORMAT_NOF_BITS(location.L); uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location.L);
nof_symbols = q->e_bits/2; nof_symbols = e_bits/2;
ret = LIBLTE_ERROR; ret = LIBLTE_ERROR;
if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce && if (location.ncce + PDCCH_FORMAT_NOF_CCE(location.L) <= q->nof_cce &&
msg->nof_bits < DCI_MAX_BITS) msg->nof_bits < DCI_MAX_BITS)
{ {
INFO("Encoding DCI: Nbits: %d, E: %d, nCCE: %d, L: %d, RNTI: 0x%x\n", 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); msg->nof_bits, e_bits, location.ncce, location.L, rnti);
dci_encode(q, msg->data, q->pdcch_e, msg->nof_bits, q->e_bits, rnti); dci_encode(q, msg->data, q->pdcch_e, msg->nof_bits, 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++) {
@ -532,14 +536,14 @@ int pdcch_encode(pdcch_t *q, dci_msg_t *msg, dci_location_t location, uint16_t r
} }
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, 72 * location.ncce, q->e_bits); scrambling_b_offset(&q->seq_pdcch[nsubframe], q->pdcch_e, 72 * location.ncce, e_bits);
DEBUG("Scrambling output: ", 0); DEBUG("Scrambling output: ", 0);
if (VERBOSE_ISDEBUG()) { if (VERBOSE_ISDEBUG()) {
vec_fprint_b(stdout, q->pdcch_e, q->e_bits); vec_fprint_b(stdout, q->pdcch_e, e_bits);
} }
mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, q->e_bits); mod_modulate(&q->mod, q->pdcch_e, q->pdcch_d, e_bits);
/* layer mapping & precoding */ /* layer mapping & precoding */
if (q->cell.nof_ports > 1) { if (q->cell.nof_ports > 1) {

@ -49,8 +49,11 @@
const lte_mod_t modulations[4] = const lte_mod_t modulations[4] =
{ LTE_BPSK, LTE_QPSK, LTE_QAM16, LTE_QAM64 }; { LTE_BPSK, LTE_QPSK, LTE_QAM16, LTE_QAM64 };
//#define DEBUG_IDX
#ifdef DEBUG_IDX
cf_t *offset_original=NULL;
#endif
int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc, int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc,
uint32_t nsubframe, bool put) { uint32_t nsubframe, bool put) {
@ -62,6 +65,10 @@ int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc,
INFO("%s %d RE from %d PRB\n", put ? "Putting" : "Getting", INFO("%s %d RE from %d PRB\n", put ? "Putting" : "Getting",
prb_alloc->re_sf[nsubframe], prb_alloc->slot[0].nof_prb); prb_alloc->re_sf[nsubframe], prb_alloc->slot[0].nof_prb);
#ifdef DEBUG_IDX
offset_original = input;
#endif
if (q->cell.nof_ports == 1) { if (q->cell.nof_ports == 1) {
nof_refs = 2; nof_refs = 2;
} else { } else {
@ -70,72 +77,79 @@ int pdsch_cp(pdsch_t *q, cf_t *input, cf_t *output, ra_prb_t *prb_alloc,
for (s = 0; s < 2; s++) { for (s = 0; s < 2; s++) {
for (l = 0; l < CP_NSYMB(q->cell.cp); l++) { for (l = 0; l < CP_NSYMB(q->cell.cp); l++) {
for (n = 0; n < prb_alloc->slot[s].nof_prb; n++) { for (n = 0; n < q->cell.nof_prb; n++) {
if (s == 0) {
lstart = prb_alloc->lstart; // If this PRB is assigned
} else { if (prb_alloc->slot[s].prb_idx[n]) {
lstart = 0; if (s == 0) {
} lstart = prb_alloc->lstart;
lend = CP_NSYMB(q->cell.cp); } else {
is_pbch = is_sss = false; lstart = 0;
// Skip PSS/SSS signals
if (s == 0 && (nsubframe == 0 || nsubframe == 5)) {
if (prb_alloc->slot[s].prb_idx[n] >= q->cell.nof_prb / 2 - 3
&& prb_alloc->slot[s].prb_idx[n] <= q->cell.nof_prb / 2 + 3) {
lend = CP_NSYMB(q->cell.cp) - 2;
is_sss = true;
} }
} lend = CP_NSYMB(q->cell.cp);
// Skip PBCH is_pbch = is_sss = false;
if (s == 1 && nsubframe == 0) {
if (prb_alloc->slot[s].prb_idx[n] >= q->cell.nof_prb / 2 - 3 // Skip PSS/SSS signals
&& prb_alloc->slot[s].prb_idx[n] <= q->cell.nof_prb / 2 + 3) { if (s == 0 && (nsubframe == 0 || nsubframe == 5)) {
lstart = 4; if (n >= q->cell.nof_prb / 2 - 3
is_pbch = true; && n < q->cell.nof_prb / 2 + 3) {
lend = CP_NSYMB(q->cell.cp) - 2;
is_sss = true;
}
} }
} // Skip PBCH
lp = l + s * CP_NSYMB(q->cell.cp); if (s == 1 && nsubframe == 0) {
if (put) { if (n >= q->cell.nof_prb / 2 - 3
out_ptr = &output[(lp * q->cell.nof_prb + prb_alloc->slot[s].prb_idx[n]) && n < q->cell.nof_prb / 2 + 3) {
* RE_X_RB]; lstart = 4;
} else { is_pbch = true;
in_ptr = &input[(lp * q->cell.nof_prb + prb_alloc->slot[s].prb_idx[n])
* RE_X_RB];
}
if (l >= lstart && l < lend) {
if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) {
if (nof_refs == 2 && l != 0) {
offset = q->cell.id % 3 + 3;
} else {
offset = q->cell.id % 3;
} }
prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs, put); }
lp = l + s * CP_NSYMB(q->cell.cp);
if (put) {
out_ptr = &output[(lp * q->cell.nof_prb + n)
* RE_X_RB];
} else { } else {
prb_cp(&in_ptr, &out_ptr, 1); in_ptr = &input[(lp * q->cell.nof_prb + n)
* RE_X_RB];
} }
} // This is a symbol in a normal PRB with or without references
if ((q->cell.nof_prb % 2) && ((is_pbch && l < lstart) || (is_sss && l >= lend))) { if (l >= lstart && l < lend) {
if (prb_alloc->slot[s].prb_idx[n] == q->cell.nof_prb / 2 - 3) {
if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) { if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) {
prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put); if (nof_refs == 2 && l == 0) {
offset = q->cell.id % 3 + 3;
} else {
offset = q->cell.id % 3;
}
prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs, put);
} else { } else {
prb_cp_half(&in_ptr, &out_ptr, 1); prb_cp(&in_ptr, &out_ptr, 1);
} }
} else if (prb_alloc->slot[s].prb_idx[n] == q->cell.nof_prb / 2 + 3) { }
if (put) { // This is a symbol in a PRB with PBCH or Synch signals (SS).
out_ptr += 6; // If the number or total PRB is odd, half of the the PBCH or SS will fall into the symbol
} else { if ((q->cell.nof_prb % 2) && ((is_pbch && l < lstart) || (is_sss && l >= lend))) {
in_ptr += 6; if (n == q->cell.nof_prb / 2 - 3) {
} if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) {
if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) { prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put);
prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put); } else {
} else { prb_cp_half(&in_ptr, &out_ptr, 1);
prb_cp_half(&in_ptr, &out_ptr, 1); }
} else if (n == q->cell.nof_prb / 2 + 3) {
if (put) {
out_ptr += 6;
} else {
in_ptr += 6;
}
if (SYMBOL_HAS_REF(l, q->cell.cp, q->cell.nof_ports)) {
prb_cp_ref(&in_ptr, &out_ptr, offset, nof_refs, nof_refs/2, put);
} else {
prb_cp_half(&in_ptr, &out_ptr, 1);
}
} }
} }
} }
} }
} }
} }
@ -532,6 +546,8 @@ int pdsch_decode_tb(pdsch_t *q, uint8_t *data, uint32_t tbs, uint32_t nb_e,
fprintf(stderr, "Error in rate matching\n"); fprintf(stderr, "Error in rate matching\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
vec_save_file("tdec_in.dat",q->cb_out, sizeof(float) * (3 * cb_len + 12));
/* Turbo Decoding with CRC-based early stopping */ /* Turbo Decoding with CRC-based early stopping */
q->nof_iterations = 0; q->nof_iterations = 0;
@ -542,7 +558,6 @@ int pdsch_decode_tb(pdsch_t *q, uint8_t *data, uint32_t tbs, uint32_t nb_e,
tdec_reset(&q->decoder, cb_len); tdec_reset(&q->decoder, cb_len);
do { do {
tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len); tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len);
q->nof_iterations++; q->nof_iterations++;
@ -651,7 +666,7 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n); fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
/* 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 = pdsch_get(q, ce[i], q->ce[i], &harq_process->prb_alloc, subframe); n = pdsch_get(q, ce[i], q->ce[i], &harq_process->prb_alloc, subframe);
@ -660,7 +675,7 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
} }
/* TODO: only diversity is supported */ /* TODO: 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 */
@ -672,31 +687,22 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_
layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports, layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports,
nof_symbols / q->cell.nof_ports); nof_symbols / q->cell.nof_ports);
} }
vec_save_file("pdsch_after.dat",q->pdsch_d,sizeof(cf_t)*nof_symbols);
/* demodulate symbols /* demodulate symbols
* The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation, * The MAX-log-MAP algorithm used in turbo decoding is unsensitive to SNR estimation,
* thus we don't need tot set it in the LLRs normalization * thus we don't need tot set it in the LLRs normalization
*/ */
demod_soft_sigma_set(&q->demod, 2.0 / q->mod[harq_process->mcs.mod - 1].nbits_x_symbol); demod_soft_sigma_set(&q->demod, 1);//q->mod[harq_process->mcs.mod - 1].nbits_x_symbol);
demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod - 1]); demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod - 1]);
demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols); demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols);
/*
for (int j=0;j<nof_symbols;j++) {
if (isnan(crealf(q->pdsch_d[j])) || isnan(cimagf(q->pdsch_d[j]))) {
printf("\nerror in d[%d]=%f+%f symbols:%f+%f ce0:%f+%f ce1:%f+%f\n",j,
crealf(q->pdsch_d[j]), cimagf(q->pdsch_d[j]),
crealf(q->pdsch_symbols[0][j]), cimagf(q->pdsch_symbols[0][j]),
crealf(q->ce[0][j]), cimagf(q->ce[0][j]),
crealf(q->ce[1][j]), cimagf(q->ce[1][j])
);
}
}
*/
/* descramble */ /* descramble */
scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_e, 0, nof_bits_e); scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_e, 0, nof_bits_e);
vec_save_file("pdsch_llr.dat",q->pdsch_e,sizeof(float)*nof_bits_e);
return pdsch_decode_tb(q, data, nof_bits, nof_bits_e, harq_process, rv_idx); return pdsch_decode_tb(q, data, nof_bits, nof_bits_e, harq_process, rv_idx);
} else { } else {
return LIBLTE_ERROR_INVALID_INPUTS; return LIBLTE_ERROR_INVALID_INPUTS;

@ -32,12 +32,27 @@
#include "prb.h" #include "prb.h"
#include "liblte/phy/common/phy_common.h" #include "liblte/phy/common/phy_common.h"
//#define DEBUG_IDX
#ifdef DEBUG_IDX
extern cf_t *offset_original;
#endif
void print_indexes(cf_t *offset, int len) {
#ifdef DEBUG_IDX
for (int i=0;i<len;i++) {
printf("%d, ",offset-offset_original+i);
}
#endif
}
void prb_cp_ref(cf_t **input, cf_t **output, int offset, int nof_refs, void prb_cp_ref(cf_t **input, cf_t **output, int offset, int nof_refs,
int nof_intervals, bool advance_output) { int nof_intervals, bool advance_output) {
int i; int i;
int ref_interval = ((RE_X_RB / nof_refs) - 1); int ref_interval = ((RE_X_RB / nof_refs) - 1);
memcpy(*output, *input, offset * sizeof(cf_t)); memcpy(*output, *input, offset * sizeof(cf_t));
print_indexes(*input, offset);
*input += offset; *input += offset;
*output += offset; *output += offset;
for (i = 0; i < nof_intervals - 1; i++) { for (i = 0; i < nof_intervals - 1; i++) {
@ -47,6 +62,7 @@ void prb_cp_ref(cf_t **input, cf_t **output, int offset, int nof_refs,
(*input)++; (*input)++;
} }
memcpy(*output, *input, ref_interval * sizeof(cf_t)); memcpy(*output, *input, ref_interval * sizeof(cf_t));
print_indexes(*input, ref_interval);
*output += ref_interval; *output += ref_interval;
*input += ref_interval; *input += ref_interval;
} }
@ -57,6 +73,7 @@ void prb_cp_ref(cf_t **input, cf_t **output, int offset, int nof_refs,
(*input)++; (*input)++;
} }
memcpy(*output, *input, (ref_interval - offset) * sizeof(cf_t)); memcpy(*output, *input, (ref_interval - offset) * sizeof(cf_t));
print_indexes(*input, ref_interval-offset);
*output += (ref_interval - offset); *output += (ref_interval - offset);
*input += (ref_interval - offset); *input += (ref_interval - offset);
} }
@ -64,6 +81,7 @@ void prb_cp_ref(cf_t **input, cf_t **output, int offset, int nof_refs,
void prb_cp(cf_t **input, cf_t **output, int nof_prb) { void prb_cp(cf_t **input, cf_t **output, int nof_prb) {
memcpy(*output, *input, sizeof(cf_t) * RE_X_RB * nof_prb); memcpy(*output, *input, sizeof(cf_t) * RE_X_RB * nof_prb);
print_indexes(*input, RE_X_RB);
*input += nof_prb * RE_X_RB; *input += nof_prb * RE_X_RB;
*output += nof_prb * RE_X_RB; *output += nof_prb * RE_X_RB;
} }
@ -71,6 +89,7 @@ void prb_cp(cf_t **input, cf_t **output, int nof_prb) {
void prb_cp_half(cf_t **input, cf_t **output, int nof_prb) { void prb_cp_half(cf_t **input, cf_t **output, int nof_prb) {
memcpy(*output, *input, sizeof(cf_t) * RE_X_RB * nof_prb / 2); memcpy(*output, *input, sizeof(cf_t) * RE_X_RB * nof_prb / 2);
print_indexes(*input, RE_X_RB/2);
*input += nof_prb * RE_X_RB / 2; *input += nof_prb * RE_X_RB / 2;
*output += nof_prb * RE_X_RB / 2; *output += nof_prb * RE_X_RB / 2;
} }

@ -55,7 +55,7 @@ uint32_t ra_re_x_prb(uint32_t subframe, uint32_t slot, uint32_t prb_idx, uint32_
/* if it's the prb in the middle, there are less RE due to PBCH and PSS/SSS */ /* if it's the prb in the middle, there are less RE due to PBCH and PSS/SSS */
if ((subframe == 0 || subframe == 5) if ((subframe == 0 || subframe == 5)
&& (prb_idx >= nof_prb / 2 - 3 && prb_idx <= nof_prb / 2 + 3)) { && (prb_idx >= nof_prb / 2 - 3 && prb_idx < nof_prb / 2 + 3)) {
if (subframe == 0) { if (subframe == 0) {
if (slot == 0) { if (slot == 0) {
re = (CP_NSYMB(cp) - nof_ctrl_symbols - 2) * RE_X_RB; re = (CP_NSYMB(cp) - nof_ctrl_symbols - 2) * RE_X_RB;
@ -119,26 +119,30 @@ void ra_prb_get_re_dl(ra_prb_t *prb_dist, uint32_t nof_prb, uint32_t nof_ports,
for (i = 0; i < NSUBFRAMES_X_FRAME; i++) { for (i = 0; i < NSUBFRAMES_X_FRAME; i++) {
prb_dist->re_sf[i] = 0; prb_dist->re_sf[i] = 0;
for (s = 0; s < 2; s++) { for (s = 0; s < 2; s++) {
for (j = 0; j < prb_dist->slot[s].nof_prb; j++) { for (j = 0; j < nof_prb; j++) {
prb_dist->re_sf[i] += ra_re_x_prb(i, s, prb_dist->slot[s].prb_idx[j], if (prb_dist->slot[s].prb_idx[j]) {
nof_prb, nof_ports, nof_ctrl_symbols, cp); prb_dist->re_sf[i] += ra_re_x_prb(i, s, j,
nof_prb, nof_ports, nof_ctrl_symbols, cp);
}
} }
} }
} }
} }
void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb) { void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb, uint32_t nof_prb) {
int i, j, nrows; int i;
nrows = (prb->nof_prb - 1) / 25 + 1; if (prb->nof_prb > 0) {
for (j = 0; j < nrows; j++) { for (i=0;i<nof_prb;i++) {
for (i = 0; i < min(25, prb->nof_prb - j * 25); i++) { if (prb->prb_idx[i]) {
fprintf(f, "%3d, ", prb->prb_idx[j * 25 + i]); fprintf(f, "%d, ", i);
}
} }
fprintf(f, "\n"); fprintf(f, "\n");
} }
} }
/** Compute PRB allocation for Downlink as defined in 8.1 of 36.213 */ /** Compute PRB allocation for Uplink as defined in 8.1 of 36.213 */
int ra_prb_get_ul(ra_prb_slot_t *prb, ra_pusch_t *ra, uint32_t nof_prb) { int ra_prb_get_ul(ra_prb_slot_t *prb, ra_pusch_t *ra, uint32_t nof_prb) {
int i; int i;
if (ra->type2_alloc.mode != t2_loc) { if (ra->type2_alloc.mode != t2_loc) {
@ -168,7 +172,7 @@ int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, uint32_t nof_prb) {
if (bitmask & (1 << (nb - i - 1))) { if (bitmask & (1 << (nb - i - 1))) {
for (j = 0; j < P; j++) { for (j = 0; j < P; j++) {
if (i*P+j < nof_prb) { if (i*P+j < nof_prb) {
prb_dist->slot[0].prb_idx[prb_dist->slot[0].nof_prb] = i * P + j; prb_dist->slot[0].prb_idx[i * P + j] = true;
prb_dist->slot[0].nof_prb++; prb_dist->slot[0].nof_prb++;
} }
} }
@ -189,8 +193,8 @@ int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, uint32_t nof_prb) {
bitmask = ra->type1_alloc.vrb_bitmask; bitmask = ra->type1_alloc.vrb_bitmask;
for (i = 0; i < n_rb_type1; i++) { for (i = 0; i < n_rb_type1; i++) {
if (bitmask & (1 << (n_rb_type1 - i - 1))) { if (bitmask & (1 << (n_rb_type1 - i - 1))) {
prb_dist->slot[0].prb_idx[prb_dist->slot[0].nof_prb] = ((i + shift) / P) prb_dist->slot[0].prb_idx[((i + shift) / P)
* P * P + ra->type1_alloc.rbg_subset * P + (i + shift) % P; * P * P + ra->type1_alloc.rbg_subset * P + (i + shift) % P] = true;
prb_dist->slot[0].nof_prb++; prb_dist->slot[0].nof_prb++;
} }
} }
@ -199,7 +203,7 @@ int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, uint32_t nof_prb) {
case alloc_type2: case alloc_type2:
if (ra->type2_alloc.mode == t2_loc) { if (ra->type2_alloc.mode == t2_loc) {
for (i = 0; i < ra->type2_alloc.L_crb; i++) { for (i = 0; i < ra->type2_alloc.L_crb; i++) {
prb_dist->slot[0].prb_idx[i] = i + ra->type2_alloc.RB_start; prb_dist->slot[0].prb_idx[i + ra->type2_alloc.RB_start] = true;
prb_dist->slot[0].nof_prb++; prb_dist->slot[0].nof_prb++;
} }
memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(ra_prb_slot_t)); memcpy(&prb_dist->slot[1], &prb_dist->slot[0], sizeof(ra_prb_slot_t));
@ -211,10 +215,10 @@ int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, uint32_t nof_prb) {
N_row, n_vrb; N_row, n_vrb;
int n_tilde_prb_odd, n_tilde_prb_even; int n_tilde_prb_odd, n_tilde_prb_even;
if (ra->type2_alloc.n_gap == t2_ng1) { if (ra->type2_alloc.n_gap == t2_ng1) {
N_tilde_vrb = nof_prb; N_tilde_vrb = ra_type2_n_vrb_dl(nof_prb, true);
N_gap = ra_type2_ngap(nof_prb, true); N_gap = ra_type2_ngap(nof_prb, true);
} else { } else {
N_tilde_vrb = 2 * nof_prb; N_tilde_vrb = 2 * ra_type2_n_vrb_dl(nof_prb, true);
N_gap = ra_type2_ngap(nof_prb, false); N_gap = ra_type2_ngap(nof_prb, false);
} }
N_row = (int) ceilf((float) N_tilde_vrb / (4 * P)) * P; N_row = (int) ceilf((float) N_tilde_vrb / (4 * P)) * P;
@ -243,17 +247,17 @@ int ra_prb_get_dl(ra_prb_t *prb_dist, ra_pdsch_t *ra, uint32_t nof_prb) {
+ N_tilde_vrb * (n_vrb / N_tilde_vrb); + N_tilde_vrb * (n_vrb / N_tilde_vrb);
if (n_tilde_prb_odd < N_tilde_vrb / 2) { if (n_tilde_prb_odd < N_tilde_vrb / 2) {
prb_dist->slot[0].prb_idx[i] = n_tilde_prb_odd; prb_dist->slot[0].prb_idx[n_tilde_prb_odd] = true;
} else { } else {
prb_dist->slot[0].prb_idx[i] = n_tilde_prb_odd + N_gap prb_dist->slot[0].prb_idx[n_tilde_prb_odd + N_gap
- N_tilde_vrb / 2; - N_tilde_vrb / 2] = true;
} }
prb_dist->slot[0].nof_prb++; prb_dist->slot[0].nof_prb++;
if (n_tilde_prb_even < N_tilde_vrb / 2) { if (n_tilde_prb_even < N_tilde_vrb / 2) {
prb_dist->slot[1].prb_idx[i] = n_tilde_prb_even; prb_dist->slot[1].prb_idx[n_tilde_prb_even] = true;
} else { } else {
prb_dist->slot[1].prb_idx[i] = n_tilde_prb_even + N_gap prb_dist->slot[1].prb_idx[n_tilde_prb_even + N_gap
- N_tilde_vrb / 2; - N_tilde_vrb / 2] = true;
} }
prb_dist->slot[1].nof_prb++; prb_dist->slot[1].nof_prb++;
} }
@ -532,7 +536,7 @@ void ra_pdsch_fprint(FILE *f, ra_pdsch_t *ra, uint32_t nof_prb) {
ra_prb_get_dl(&alloc, ra, nof_prb); ra_prb_get_dl(&alloc, ra, nof_prb);
for (int s = 0; s < 2; s++) { for (int s = 0; s < 2; s++) {
fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", s); fprintf(f, " - PRB Bitmap Assignment %dst slot:\n", s);
ra_prb_fprint(f, &alloc.slot[s]); ra_prb_fprint(f, &alloc.slot[s], nof_prb);
} }
fprintf(f, " - Number of PRBs:\t\t\t%d\n", ra_nprb_dl(ra, nof_prb)); fprintf(f, " - Number of PRBs:\t\t\t%d\n", ra_nprb_dl(ra, nof_prb));

@ -67,11 +67,9 @@ void regs_pdcch_free(regs_t *h) {
for (i=0;i<3;i++) { for (i=0;i<3;i++) {
if (h->pdcch[i].regs) { if (h->pdcch[i].regs) {
free(h->pdcch[i].regs); free(h->pdcch[i].regs);
h->pdcch[i].regs = NULL;
} }
} }
bzero(h, sizeof(regs_t));
} }
#define PDCCH_NCOLS 32 #define PDCCH_NCOLS 32
@ -114,7 +112,7 @@ int regs_pdcch_init(regs_t *h) {
} }
h->pdcch[cfi].nof_regs = m; h->pdcch[cfi].nof_regs = m;
h->pdcch[cfi].regs = malloc(sizeof(regs_reg_t*) * h->pdcch[cfi].nof_regs); h->pdcch[cfi].regs = malloc(sizeof(regs_reg_t*) * h->pdcch[cfi].nof_regs);
if (!h->pdcch[cfi].regs) { if (!h->pdcch[cfi].regs) {
perror("malloc"); perror("malloc");
@ -144,6 +142,8 @@ int regs_pdcch_init(regs_t *h) {
} }
} }
h->pdcch[cfi].nof_regs = (h->pdcch[cfi].nof_regs/9)*9; h->pdcch[cfi].nof_regs = (h->pdcch[cfi].nof_regs/9)*9;
INFO("Init PDCCH REG space CFI %d. %d useful REGs (%d CCEs)\n",cfi+1,
h->pdcch[cfi].nof_regs, h->pdcch[cfi].nof_regs/9);
free(tmp); free(tmp);
tmp = NULL; tmp = NULL;
} }
@ -348,13 +348,12 @@ void regs_phich_free(regs_t *h) {
for (i=0;i<h->ngroups_phich;i++) { for (i=0;i<h->ngroups_phich;i++) {
if (h->phich[i].regs) { if (h->phich[i].regs) {
free(h->phich[i].regs); free(h->phich[i].regs);
h->phich[i].regs = NULL;
} }
} }
free(h->phich); free(h->phich);
h->phich = NULL;
} }
bzero(h, sizeof(regs_t));
} }
uint32_t regs_phich_nregs(regs_t *h) { uint32_t regs_phich_nregs(regs_t *h) {
@ -487,7 +486,7 @@ int regs_pcfich_init(regs_t *h) {
k); k);
return LIBLTE_ERROR; return LIBLTE_ERROR;
} else { } else {
ch->regs[i]->assigned = true; ch->regs[i]->assigned = true;
INFO("Assigned PCFICH REG#%d (%d,0)\n", i, k); INFO("Assigned PCFICH REG#%d (%d,0)\n", i, k);
} }
} }
@ -497,10 +496,8 @@ int regs_pcfich_init(regs_t *h) {
void regs_pcfich_free(regs_t *h) { void regs_pcfich_free(regs_t *h) {
if (h->pcfich.regs) { if (h->pcfich.regs) {
free(h->pcfich.regs); free(h->pcfich.regs);
h->pcfich.regs = NULL;
} }
bzero(h, sizeof(regs_t));
} }
uint32_t regs_pcfich_nregs(regs_t *h) { uint32_t regs_pcfich_nregs(regs_t *h) {

@ -34,8 +34,8 @@
#include "liblte/phy/phy.h" #include "liblte/phy/phy.h"
char *input_file_name = NULL; char *input_file_name = NULL;
char *matlab_file_name = NULL;
#define MAX_CANDIDATES 64
lte_cell_t cell = { lte_cell_t cell = {
6, // cell.cell.cell.nof_prb 6, // cell.cell.cell.nof_prb
@ -50,8 +50,8 @@ uint32_t cfi = 2;
int flen; int flen;
uint16_t rnti = SIRNTI; uint16_t rnti = SIRNTI;
int max_frames = 10; int max_frames = 10;
FILE *fmatlab = NULL;
dci_format_t dci_format = Format1A;
filesource_t fsrc; filesource_t fsrc;
pdcch_t pdcch; pdcch_t pdcch;
cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS]; cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS];
@ -61,9 +61,9 @@ chest_dl_t chest;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [vcfoe] -i input_file\n", prog); printf("Usage: %s [vcfoe] -i input_file\n", prog);
printf("\t-o output matlab file name [Default Disabled]\n");
printf("\t-c cell.id [Default %d]\n", cell.id); printf("\t-c cell.id [Default %d]\n", cell.id);
printf("\t-f cfi [Default %d]\n", cfi); printf("\t-f cfi [Default %d]\n", cfi);
printf("\t-o DCI Format [Default %s]\n", dci_format_string(dci_format));
printf("\t-r rnti [Default SI-RNTI]\n"); printf("\t-r rnti [Default SI-RNTI]\n");
printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports); printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports);
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb); printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
@ -74,7 +74,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "irovfcenmp")) != -1) { while ((opt = getopt(argc, argv, "irvofcenmp")) != -1) {
switch(opt) { switch(opt) {
case 'i': case 'i':
input_file_name = argv[optind]; input_file_name = argv[optind];
@ -98,7 +98,11 @@ void parse_args(int argc, char **argv) {
cell.nof_ports = atoi(argv[optind]); cell.nof_ports = atoi(argv[optind]);
break; break;
case 'o': case 'o':
matlab_file_name = argv[optind]; dci_format = dci_format_from_string(argv[optind]);
if (dci_format == FormatError) {
fprintf(stderr, "Error unsupported format %s\n", argv[optind]);
exit(-1);
}
break; break;
case 'v': case 'v':
verbose++; verbose++;
@ -125,16 +129,6 @@ int base_init() {
exit(-1); exit(-1);
} }
if (matlab_file_name) {
fmatlab = fopen(matlab_file_name, "w");
if (!fmatlab) {
perror("fopen");
return -1;
}
} else {
fmatlab = NULL;
}
flen = 2 * (SLOT_LEN(lte_symbol_sz(cell.nof_prb))); flen = 2 * (SLOT_LEN(lte_symbol_sz(cell.nof_prb)));
input_buffer = malloc(flen * sizeof(cf_t)); input_buffer = malloc(flen * sizeof(cf_t));
@ -189,9 +183,6 @@ void base_free() {
int i; int i;
filesource_free(&fsrc); filesource_free(&fsrc);
if (fmatlab) {
fclose(fmatlab);
}
free(input_buffer); free(input_buffer);
free(fft_buffer); free(fft_buffer);
@ -210,9 +201,9 @@ 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_frames; int frame_cnt;
int ret; int ret;
dci_location_t locations[10]; dci_location_t locations[MAX_CANDIDATES];
uint32_t nof_locations; uint32_t nof_locations;
dci_msg_t dci_msg; dci_msg_t dci_msg;
@ -228,84 +219,72 @@ int main(int argc, char **argv) {
exit(-1); exit(-1);
} }
if (rnti == SIRNTI) {
INFO("Initializing common search space for SI-RNTI\n",0);
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);
nof_locations = pdcch_ue_locations(&pdcch, locations, 10, 5, cfi, rnti);
}
ret = -1; ret = -1;
nof_frames = 0; frame_cnt = 0;
do { do {
filesource_read(&fsrc, input_buffer, flen); filesource_read(&fsrc, input_buffer, flen);
if (nof_frames == 5) {
INFO("Reading %d samples sub-frame %d\n", flen, nof_frames);
lte_fft_run_sf(&fft, input_buffer, fft_buffer); INFO("Reading %d samples sub-frame %d\n", flen, frame_cnt);
if (fmatlab) { lte_fft_run_sf(&fft, input_buffer, fft_buffer);
fprintf(fmatlab, "infft%d=", nof_frames);
vec_fprint_c(fmatlab, input_buffer, flen);
fprintf(fmatlab, ";\n");
fprintf(fmatlab, "outfft%d=", nof_frames); /* Get channel estimates for each port */
vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); chest_dl_estimate(&chest, fft_buffer, ce, frame_cnt %10);
vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB);
fprintf(fmatlab, ";\n"); uint16_t crc_rem = 0;
vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); if (pdcch_extract_llr(&pdcch, fft_buffer,
} ce, chest_dl_get_noise_estimate(&chest),
frame_cnt %10, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return -1;
}
if (rnti == SIRNTI) {
INFO("Initializing common search space for SI-RNTI\n",0);
nof_locations = pdcch_common_locations(&pdcch, locations, MAX_CANDIDATES, cfi);
} else {
INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti);
nof_locations = pdcch_ue_locations(&pdcch, locations, MAX_CANDIDATES, frame_cnt %10, cfi, rnti);
}
/* Get channel estimates for each port */ for (i=0;i<nof_locations && crc_rem != rnti;i++) {
chest_dl_estimate(&chest, fft_buffer, ce, nof_frames); if (pdcch_decode_msg(&pdcch, &dci_msg, &locations[i], dci_format, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
uint16_t crc_rem = 0; return -1;
for (i=0;i<nof_locations && crc_rem != rnti;i++) {
if (pdcch_extract_llr(&pdcch, fft_buffer, ce, chest_dl_get_noise_estimate(&chest), locations[i], nof_frames, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return -1;
}
if (pdcch_decode_msg(&pdcch, &dci_msg, Format1A, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return -1;
}
} }
}
if (crc_rem == rnti) {
dci_msg_type_t type; if (crc_rem == rnti) {
if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, rnti, 1234)) { dci_msg_type_t type;
fprintf(stderr, "Can't get DCI message type\n"); if (dci_msg_get_type(&dci_msg, &type, cell.nof_prb, rnti, 1234)) {
exit(-1); fprintf(stderr, "Can't get DCI message type\n");
} exit(-1);
printf("MSG %d: ",i); }
dci_msg_type_fprint(stdout, type); printf("MSG %d: ",i);
switch(type.type) { dci_msg_type_fprint(stdout, type);
case PDSCH_SCHED: switch(type.type) {
bzero(&ra_dl, sizeof(ra_pdsch_t)); case PDSCH_SCHED:
if (dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, rnti != SIRNTI)) { bzero(&ra_dl, sizeof(ra_pdsch_t));
fprintf(stderr, "Can't unpack PDSCH message\n"); if (dci_msg_unpack_pdsch(&dci_msg, &ra_dl, cell.nof_prb, rnti != SIRNTI)) {
} else { fprintf(stderr, "Can't unpack PDSCH message\n");
ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); } else {
if (ra_dl.alloc_type == alloc_type2 && ra_dl.type2_alloc.mode == t2_loc ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb);
&& ra_dl.type2_alloc.riv == 11 && ra_dl.rv_idx == 0 if (ra_dl.alloc_type == alloc_type2 && ra_dl.type2_alloc.mode == t2_loc
&& ra_dl.harq_process == 0 && ra_dl.mcs_idx == 2) { && ra_dl.type2_alloc.riv == 11 && ra_dl.rv_idx == 0
printf("This is the file signal.1.92M.amar.dat\n"); && ra_dl.harq_process == 0 && ra_dl.mcs_idx == 2) {
ret = 0; printf("This is the file signal.1.92M.amar.dat\n");
} ret = 0;
} }
break;
default:
fprintf(stderr, "Unsupported message type\n");
break;
} }
break;
default:
fprintf(stderr, "Unsupported message type\n");
break;
} }
} }
nof_frames++; frame_cnt++;
} while (nof_frames <= max_frames); } while (frame_cnt <= max_frames);
base_free(); base_free();
exit(ret); exit(ret);

@ -182,6 +182,7 @@ int main(int argc, char **argv) {
} }
} }
vec_fprint_b(stdout, dci_tx[0].data, dci_tx[0].nof_bits);
/* combine outputs */ /* combine outputs */
for (i = 1; i < cell.nof_ports; i++) { for (i = 1; i < cell.nof_ports; i++) {
for (j = 0; j < nof_re; j++) { for (j = 0; j < nof_re; j++) {
@ -190,12 +191,12 @@ int main(int argc, char **argv) {
} }
for (i=0;i<2;i++) { for (i=0;i<2;i++) {
if (pdcch_extract_llr(&pdcch, slot_symbols[0], ce, 0, dci_locations[i], 0, cfi)) { if (pdcch_extract_llr(&pdcch, slot_symbols[0], ce, 0, 0, cfi)) {
fprintf(stderr, "Error extracting LLRs\n"); fprintf(stderr, "Error extracting LLRs\n");
goto quit; goto quit;
} }
uint16_t crc_rem; uint16_t crc_rem;
if (pdcch_decode_msg(&pdcch, &dci_tmp, Format1, &crc_rem)) { if (pdcch_decode_msg(&pdcch, &dci_tmp, &dci_locations[i], Format1, &crc_rem)) {
fprintf(stderr, "Error decoding DCI message\n"); fprintf(stderr, "Error decoding DCI message\n");
goto quit; goto quit;
} }

@ -33,8 +33,9 @@
#include "liblte/phy/phy.h" #include "liblte/phy/phy.h"
#define MAX_CANDIDATES 64
char *input_file_name = NULL; char *input_file_name = NULL;
char *matlab_file_name = NULL;
lte_cell_t cell = { lte_cell_t cell = {
6, // nof_prb 6, // nof_prb
@ -51,8 +52,9 @@ uint32_t cfi = 2;
uint16_t rnti = SIRNTI; uint16_t rnti = SIRNTI;
int max_frames = 10; int max_frames = 10;
FILE *fmatlab = NULL; uint32_t sf_idx = 0;
dci_format_t dci_format = Format1A;
filesource_t fsrc; filesource_t fsrc;
pdcch_t pdcch; pdcch_t pdcch;
pdsch_t pdsch; pdsch_t pdsch;
@ -63,11 +65,12 @@ lte_fft_t fft;
chest_dl_t chest; chest_dl_t chest;
void usage(char *prog) { void usage(char *prog) {
printf("Usage: %s [vcfoe] -i input_file\n", prog); printf("Usage: %s [rovfcenmps] -i input_file\n", prog);
printf("\t-o output matlab file name [Default Disabled]\n"); printf("\t-o DCI format [Default %s]\n", dci_format_string(dci_format));
printf("\t-c cell.id [Default %d]\n", cell.id); printf("\t-c cell.id [Default %d]\n", cell.id);
printf("\t-s Start subframe_idx [Default %d]\n", sf_idx);
printf("\t-f cfi [Default %d]\n", cfi); printf("\t-f cfi [Default %d]\n", cfi);
printf("\t-r rnti [Default SI-RNTI]\n"); printf("\t-r rnti [Default 0x%x]\n",rnti);
printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports); printf("\t-p cell.nof_ports [Default %d]\n", cell.nof_ports);
printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb); printf("\t-n cell.nof_prb [Default %d]\n", cell.nof_prb);
printf("\t-m max_frames [Default %d]\n", max_frames); printf("\t-m max_frames [Default %d]\n", max_frames);
@ -77,7 +80,7 @@ void usage(char *prog) {
void parse_args(int argc, char **argv) { void parse_args(int argc, char **argv) {
int opt; int opt;
while ((opt = getopt(argc, argv, "irovfcenmp")) != -1) { while ((opt = getopt(argc, argv, "irovfcenmps")) != -1) {
switch(opt) { switch(opt) {
case 'i': case 'i':
input_file_name = argv[optind]; input_file_name = argv[optind];
@ -85,6 +88,9 @@ void parse_args(int argc, char **argv) {
case 'c': case 'c':
cell.id = atoi(argv[optind]); cell.id = atoi(argv[optind]);
break; break;
case 's':
sf_idx = atoi(argv[optind]);
break;
case 'r': case 'r':
rnti = strtoul(argv[optind], NULL, 0); rnti = strtoul(argv[optind], NULL, 0);
break; break;
@ -101,7 +107,11 @@ void parse_args(int argc, char **argv) {
cell.nof_ports = atoi(argv[optind]); cell.nof_ports = atoi(argv[optind]);
break; break;
case 'o': case 'o':
matlab_file_name = argv[optind]; dci_format = dci_format_from_string(argv[optind]);
if (dci_format == FormatError) {
fprintf(stderr, "Error unsupported format %s\n", argv[optind]);
exit(-1);
}
break; break;
case 'v': case 'v':
verbose++; verbose++;
@ -128,16 +138,6 @@ int base_init() {
exit(-1); exit(-1);
} }
if (matlab_file_name) {
fmatlab = fopen(matlab_file_name, "w");
if (!fmatlab) {
perror("fopen");
return -1;
}
} else {
fmatlab = NULL;
}
flen = 2 * (SLOT_LEN(lte_symbol_sz(cell.nof_prb))); flen = 2 * (SLOT_LEN(lte_symbol_sz(cell.nof_prb)));
input_buffer = malloc(flen * sizeof(cf_t)); input_buffer = malloc(flen * sizeof(cf_t));
@ -204,9 +204,6 @@ void base_free() {
int i; int i;
filesource_free(&fsrc); filesource_free(&fsrc);
if (fmatlab) {
fclose(fmatlab);
}
free(input_buffer); free(input_buffer);
free(fft_buffer); free(fft_buffer);
@ -225,16 +222,16 @@ 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_frames; int nof_frames;
int ret; int ret;
uint8_t *data; uint8_t *data;
dci_location_t locations[10]; dci_location_t locations[MAX_CANDIDATES];
uint32_t nof_locations; uint32_t nof_locations;
dci_msg_t dci_msg; dci_msg_t dci_msg;
data = malloc(10000); data = malloc(100000);
if (argc < 3) { if (argc < 3) {
usage(argv[0]); usage(argv[0]);
@ -250,65 +247,58 @@ int main(int argc, char **argv) {
if (rnti == SIRNTI) { if (rnti == SIRNTI) {
INFO("Initializing common search space for SI-RNTI\n",0); INFO("Initializing common search space for SI-RNTI\n",0);
nof_locations = pdcch_common_locations(&pdcch, locations, 10, cfi); nof_locations = pdcch_common_locations(&pdcch, locations, MAX_CANDIDATES, cfi);
} else { }
// For ue-specific, generate locations for subframe 5
INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti);
nof_locations = pdcch_ue_locations(&pdcch, locations, 10, 5, cfi, rnti);
}
ret = -1; ret = -1;
nof_frames = 0; nof_frames = 0;
do { do {
filesource_read(&fsrc, input_buffer, flen); filesource_read(&fsrc, input_buffer, flen);
if (nof_frames == 5) { INFO("Reading %d samples sub-frame %d\n", flen, sf_idx);
INFO("Reading %d samples sub-frame %d\n", flen, nof_frames);
lte_fft_run_sf(&fft, input_buffer, fft_buffer);
if (fmatlab) { lte_fft_run_sf(&fft, input_buffer, fft_buffer);
fprintf(fmatlab, "infft%d=", nof_frames);
vec_fprint_c(fmatlab, input_buffer, flen);
fprintf(fmatlab, ";\n");
fprintf(fmatlab, "outfft%d=", nof_frames); /* Get channel estimates for each port */
vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); chest_dl_estimate(&chest, fft_buffer, ce, sf_idx);
vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB);
fprintf(fmatlab, ";\n"); if (rnti != SIRNTI) {
vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); INFO("Initializing user-specific search space for RNTI: 0x%x\n", rnti);
nof_locations = pdcch_ue_locations(&pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, rnti);
}
uint16_t crc_rem = 0;
if (pdcch_extract_llr(&pdcch, fft_buffer, ce, chest_dl_get_noise_estimate(&chest), sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return -1;
}
for (i=0;i<nof_locations && crc_rem != rnti;i++) {
if (pdcch_decode_msg(&pdcch, &dci_msg, &locations[i], dci_format, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return -1;
} }
}
/* Get channel estimates for each port */
chest_dl_estimate(&chest, fft_buffer, ce, nof_frames); if (crc_rem == rnti) {
if (dci_msg_to_ra_dl(&dci_msg, rnti, 1234, cell, cfi, &ra_dl)) {
uint16_t crc_rem = 0; fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
for (i=0;i<nof_locations && crc_rem != rnti;i++) { goto goout;
if (pdcch_extract_llr(&pdcch, fft_buffer, ce, chest_dl_get_noise_estimate(&chest), locations[i], nof_frames, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return -1;
}
if (pdcch_decode_msg(&pdcch, &dci_msg, Format1A, &crc_rem)) {
fprintf(stderr, "Error decoding DCI msg\n");
return -1;
}
} }
if (ra_dl.mcs.tbs > 0) {
if (crc_rem == rnti) {
if (dci_msg_to_ra_dl(&dci_msg, rnti, 1234, cell, cfi, &ra_dl)) {
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
goto goout;
}
if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &ra_dl.prb_alloc)) { if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &ra_dl.prb_alloc)) {
fprintf(stderr, "Error configuring HARQ process\n"); fprintf(stderr, "Error configuring HARQ process\n");
goto goout; goto goout;
} }
if (pdsch_decode(&pdsch, fft_buffer, ce, chest_dl_get_noise_estimate(&chest), data, nof_frames%10, &harq_process, ra_dl.rv_idx)) { if (pdsch_decode(&pdsch, fft_buffer, ce, chest_dl_get_noise_estimate(&chest),
data, sf_idx, &harq_process, ra_dl.rv_idx)) {
fprintf(stderr, "Error decoding PDSCH\n"); fprintf(stderr, "Error decoding PDSCH\n");
goto goout; goto goout;
} else { } else {
printf("PDSCH Decoded OK!\n"); printf("PDSCH Decoded OK!\n");
} }
} else {
printf("Received DCI with no resource allocation\n");
} }
sf_idx = (sf_idx+1)%10;
} }
nof_frames++; nof_frames++;

@ -36,6 +36,7 @@
#define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp)
#define MAX_CANDIDATES 64
int ue_dl_init(ue_dl_t *q, int ue_dl_init(ue_dl_t *q,
lte_cell_t cell, lte_cell_t cell,
@ -146,17 +147,24 @@ void ue_dl_free(ue_dl_t *q) {
LIBLTE_API float mean_exec_time=0; LIBLTE_API float mean_exec_time=0;
int frame_cnt=0; int frame_cnt=0;
dci_format_t ue_formats[] = {Format1A,Format1}; // Format1B should go here also
const uint32_t nof_ue_formats = 2;
dci_format_t common_formats[] = {Format1A,Format1C};
const uint32_t nof_common_formats = 2;
int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32_t sfn, uint16_t rnti) int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32_t sfn, uint16_t rnti)
{ {
uint32_t cfi, cfi_distance, i; uint32_t cfi, cfi_distance, i;
ra_pdsch_t ra_dl; ra_pdsch_t ra_dl;
dci_location_t locations[10]; dci_location_t locations[MAX_CANDIDATES];
dci_msg_t dci_msg; dci_msg_t dci_msg;
uint32_t nof_locations; uint32_t nof_locations;
uint16_t crc_rem; uint16_t crc_rem;
dci_format_t format;
int ret = LIBLTE_ERROR; int ret = LIBLTE_ERROR;
struct timeval t[3]; struct timeval t[3];
uint32_t nof_formats;
dci_format_t *formats = NULL;
/* Run FFT for all subframe data */ /* Run FFT for all subframe data */
lte_fft_run_sf(&q->fft, input, q->sf_symbols); lte_fft_run_sf(&q->fft, input, q->sf_symbols);
@ -169,7 +177,7 @@ int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32
gettimeofday(&t[2], NULL); gettimeofday(&t[2], NULL);
get_time_interval(t); get_time_interval(t);
mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, mean_exec_time, frame_cnt); mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, mean_exec_time, frame_cnt);
frame_cnt++; frame_cnt++;
@ -188,28 +196,34 @@ int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32
/* Generate PDCCH candidates */ /* Generate PDCCH candidates */
if (rnti == SIRNTI) { if (rnti == SIRNTI) {
nof_locations = pdcch_common_locations(&q->pdcch, locations, 10, cfi); nof_locations = pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, cfi);
format = Format1A; formats = common_formats;
nof_formats = nof_common_formats;
} else { } else {
nof_locations = pdcch_ue_locations(&q->pdcch, locations, 10, sf_idx, cfi, q->user_rnti); nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, q->user_rnti);
format = Format1; formats = ue_formats;
nof_formats = nof_ue_formats;
} }
/* Extract all PDCCH symbols and get LLRs */
if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), sf_idx, cfi)) {
fprintf(stderr, "Error extracting LLRs\n");
return LIBLTE_ERROR;
}
/* For all possible locations, try to decode a DCI message */
crc_rem = 0; crc_rem = 0;
for (i=0;i<nof_locations && crc_rem != rnti;i++) { for (int f=0;f<nof_formats;f++) {
if (pdcch_extract_llr(&q->pdcch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), locations[i], sf_idx, cfi)) { for (i=0;i<nof_locations && crc_rem != rnti;i++) {
fprintf(stderr, "Error extracting LLRs\n"); if (pdcch_decode_msg(&q->pdcch, &dci_msg, &locations[i], formats[f], &crc_rem)) {
return LIBLTE_ERROR; fprintf(stderr, "Error decoding DCI msg\n");
} return LIBLTE_ERROR;
if (pdcch_decode_msg(&q->pdcch, &dci_msg, format, &crc_rem)) { }
fprintf(stderr, "Error decoding DCI msg\n"); INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem);
return LIBLTE_ERROR;
} }
INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem);
} }
if (crc_rem == rnti) { if (crc_rem == rnti) {
printf("Hem trobat\n"); q->nof_pdcch_detected++;
if (dci_msg_to_ra_dl(&dci_msg, rnti, q->user_rnti, q->cell, cfi, &ra_dl)) { if (dci_msg_to_ra_dl(&dci_msg, rnti, q->user_rnti, q->cell, cfi, &ra_dl)) {
fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;
@ -249,7 +263,7 @@ int ue_dl_decode(ue_dl_t *q, cf_t *input, uint8_t *data, uint32_t sf_idx, uint32
q->pkt_errors++; q->pkt_errors++;
} else if (rnti != SIRNTI) { } else if (rnti != SIRNTI) {
q->pkt_errors++; q->pkt_errors++;
} }
} else if (ret == LIBLTE_ERROR_INVALID_INPUTS) { } else if (ret == LIBLTE_ERROR_INVALID_INPUTS) {
fprintf(stderr, "Error calling pdsch_decode()\n"); fprintf(stderr, "Error calling pdsch_decode()\n");
return LIBLTE_ERROR; return LIBLTE_ERROR;

@ -161,7 +161,8 @@ int ue_mib_decode_aligned_frame(ue_mib_t * q, cf_t *input,
if (ret < 0) { if (ret < 0) {
return LIBLTE_ERROR; return LIBLTE_ERROR;
} }
INFO("Channel estimated for %d ports, Noise: %f\n", q->chest.cell.nof_ports,
chest_dl_get_noise_estimate(&q->chest));
/* Reset decoder if we missed a frame */ /* Reset decoder if we missed a frame */
if ((q->last_frame_trial && (abs(q->frame_cnt - q->last_frame_trial) > 2)) || if ((q->last_frame_trial && (abs(q->frame_cnt - q->last_frame_trial) > 2)) ||
q->frame_cnt > 16) q->frame_cnt > 16)
@ -177,7 +178,7 @@ int ue_mib_decode_aligned_frame(ue_mib_t * q, cf_t *input,
/* Decode PBCH */ /* Decode PBCH */
ret = pbch_decode(&q->pbch, &q->sf_symbols[SLOT_LEN_RE(q->chest.cell.nof_prb, q->chest.cell.cp)], ret = pbch_decode(&q->pbch, &q->sf_symbols[SLOT_LEN_RE(q->chest.cell.nof_prb, q->chest.cell.cp)],
ce_slot1, chest_dl_get_noise_estimate(&q->chest), ce_slot1, chest_dl_get_noise_estimate(&q->chest),
bch_payload, nof_tx_ports, sfn_offset); bch_payload, nof_tx_ports, sfn_offset);
if (ret < 0) { if (ret < 0) {
fprintf(stderr, "Error decoding PBCH (%d)\n", ret); fprintf(stderr, "Error decoding PBCH (%d)\n", ret);
@ -256,9 +257,9 @@ int ue_mib_sync_and_decode(ue_mib_t * q,
sync_get_sf_idx(&q->sfind) == 0) sync_get_sf_idx(&q->sfind) == 0)
{ {
INFO("Trying to decode MIB\n",0); INFO("Trying to decode MIB\n",0);
printf("caution here should pass begining of frame \n"); ret = ue_mib_decode_aligned_frame(q,
exit(-1); &signal[nf*MIB_FRAME_SIZE_SEARCH+peak_idx-MIB_FRAME_SIZE_SEARCH/10],
ret = ue_mib_decode_aligned_frame(q, &signal[nf*MIB_FRAME_SIZE_SEARCH+peak_idx-960], q->bch_payload, &q->nof_tx_ports, &q->sfn_offset); q->bch_payload, &q->nof_tx_ports, &q->sfn_offset);
counter3++; counter3++;
} else if ((ret == LIBLTE_SUCCESS && peak_idx != 0) || } else if ((ret == LIBLTE_SUCCESS && peak_idx != 0) ||
(ret == 1 && nf*MIB_FRAME_SIZE_SEARCH + peak_idx + MIB_FRAME_SIZE_SEARCH/10 > nsamples)) (ret == 1 && nf*MIB_FRAME_SIZE_SEARCH + peak_idx + MIB_FRAME_SIZE_SEARCH/10 > nsamples))

@ -189,7 +189,7 @@ int track_peak_ok(ue_sync_t *q, uint32_t track_idx) {
q->sf_idx, sync_get_sf_idx(&q->strack), q->strack.m0, q->strack.m0_value, q->strack.m1, q->strack.m1_value); q->sf_idx, sync_get_sf_idx(&q->strack), q->strack.m0, q->strack.m0_value, q->strack.m1, q->strack.m1_value);
/* FIXME: What should we do in this case? */ /* FIXME: What should we do in this case? */
q->sf_idx = sync_get_sf_idx(&q->strack); q->sf_idx = sync_get_sf_idx(&q->strack);
q->state = SF_TRACK; q->state = SF_FIND;
} else { } else {
q->time_offset = ((int) track_idx - (int) CURRENT_FFTSIZE); q->time_offset = ((int) track_idx - (int) CURRENT_FFTSIZE);

@ -0,0 +1,76 @@
filename='../../debug/dist_ra.dat';
enb.NDLRB = 50;
enb.CyclicPrefix = 'Normal';
enb.PHICHDuration = 'Normal';
enb.CFI = 2;
enb.Ng = 'Sixth';
enb.CellRefP = 1;
enb.NCellID = 196;
enb.NSubframe = 5;
enb.NTotalSubframes=1;
enb.DuplexMode = 'FDD';
dci.NDLRB = enb.NDLRB;
dci.DCIFormat = 'Format1C';
dci.AllocationType=1;
%dci.Allocation.Bitmap='01111000011110000';
%dci.Allocation.Subset=3;
dci.Allocation.RIV = 33;
dci.Allocation.Gap = 0;
dci.ModCoding=6;
dci.RV=0;
dci.DuplexMode = enb.DuplexMode;
dci.NTxAnts = enb.CellRefP;
pdcch.RNTI = 65535;
pdcch.PDCCHFormat = 3;
pdsch.Modulation='QPSK';
pdsch.RNTI=pdcch.RNTI;
if (enb.CellRefP == 1)
pdsch.TxScheme='Port0';
else
pdsch.TxScheme='TxDiversity';
end
pdsch.NLayers=enb.CellRefP;
pdsch.trblklen=176;
pdsch.RV=dci.RV;
% Begin frame generation
subframe = lteDLResourceGrid(enb);
%%% Create Reference Signals
rsAnt = lteCellRS(enb);
indAnt = lteCellRSIndices(enb);
subframe(indAnt) = rsAnt;
%%% Create PDCCH
[dciMessage,dciMessageBits] = lteDCI(enb,dci);
codedDciBits = lteDCIEncode(pdcch,dciMessageBits);
pdcchInfo = ltePDCCHInfo(enb);
pdcchBits = -1*ones(1,pdcchInfo.MTot);
candidates = ltePDCCHSpace(enb,pdcch,{'bits','1based'});
pdcchBits (candidates(1,1):candidates(1,2)) = codedDciBits;
pdcchSymbols = ltePDCCH(enb, pdcchBits);
pdcchIndices = ltePDCCHIndices(enb,{'1based'});
subframe(pdcchIndices) = pdcchSymbols;
% Create PDSCH
pdsch.prbset = lteDCIResourceAllocation(enb,dci);
[pdschIndices,pdschInfo] = ltePDSCHIndices(enb,pdsch,pdsch.prbset);
dlschTransportBlk=randi([0 1],pdsch.trblklen,1);
pdschcodeword = lteDLSCH(enb,pdsch,pdschInfo.G,dlschTransportBlk);
%crced = lteCRCEncode(dlschTransportBlk, '24A');
%encoded = lteTurboEncode(crced);
%pdschcodeword2 = lteRateMatchTurbo(encoded,pdschInfo.G,pdsch.RV);
pdschSymbols = ltePDSCH(enb,pdsch,pdschcodeword);
subframe(pdschIndices) = pdschSymbols;
txwaveform = lteOFDMModulate(enb,subframe);
write_complex(filename,sum(txwaveform,2));
fprintf('Written signal to %s\n',filename);
Loading…
Cancel
Save