diff --git a/lte/examples/cell_measurement.c b/lte/examples/cell_measurement.c index 82c3dd41d..9449e8c95 100644 --- a/lte/examples/cell_measurement.c +++ b/lte/examples/cell_measurement.c @@ -41,6 +41,12 @@ #include "liblte/cuhd/cuhd.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 ***********************************************************************/ @@ -157,7 +163,7 @@ int main(int argc, char **argv) { cuhd_rx_wait_lo_locked(uhd); 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"); exit(-1); } @@ -191,7 +197,7 @@ int main(int argc, char **argv) { } 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)); /* Main loop */ @@ -201,14 +207,17 @@ int main(int argc, char **argv) { if (ret < 0) { 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) { switch (state) { case DECODE_MIB: if (ue_sync_get_sfidx(&ue_sync) == 0) { 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) { fprintf(stderr, "Error decoding UE MIB\n"); exit(-1); @@ -223,20 +232,17 @@ int main(int argc, char **argv) { break; case DECODE_SIB: sfn=0; - /* If we are looking for SI Blocks, search only in appropiate places */ - if ((sfn % 2) == 0 && (ue_sync_get_sfidx(&ue_sync) == 5)) { + /* We are looking for SI Blocks, search only in appropiate places */ + 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); if (n < 0) { fprintf(stderr, "Error decoding UE DL\n");fflush(stdout); exit(-1); } else if (n == 0) { - // Printf -// 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", + printf("CFO: %+6.4f KHz, SFO: %+6.4f Khz, ExecTime: %5.1f us, NOI: %.2f, PDCCH-Det: %.3f\r", ue_sync_get_cfo(&ue_sync)/1000, ue_sync_get_sfo(&ue_sync)/1000, 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++; } else { printf("\n\nDecoded SIB1 Message Len %d: ",n); diff --git a/lte/examples/cell_search.c b/lte/examples/cell_search.c index 0242457fe..45f570aba 100644 --- a/lte/examples/cell_search.c +++ b/lte/examples/cell_search.c @@ -54,9 +54,8 @@ int band = -1; int earfcn_start=-1, earfcn_end = -1; -int nof_frames_total = 50; -int nof_frames_detected = 10; -float threshold = CS_FIND_THRESHOLD; + +cell_detect_cfg_t config = {50, 10, CS_FIND_THRESHOLD}; float uhd_gain = 60.0; @@ -70,7 +69,7 @@ void usage(char *prog) { printf("\t-e earfcn_end [Default All]\n"); printf("\t-n nof_frames_total [Default 100]\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"); } @@ -91,13 +90,13 @@ void parse_args(int argc, char **argv) { earfcn_end = atoi(argv[optind]); break; case 'n': - nof_frames_total = atoi(argv[optind]); + config.nof_frames_total = atoi(argv[optind]); break; case 'd': - nof_frames_detected = atoi(argv[optind]); + config.nof_frames_detected = atoi(argv[optind]); break; case 't': - threshold = atof(argv[optind]); + config.threshold = atof(argv[optind]); break; case 'g': uhd_gain = atof(argv[optind]); @@ -119,7 +118,6 @@ void parse_args(int argc, char **argv) { int main(int argc, char **argv) { int n; void *uhd; - ue_celldetect_t s; ue_celldetect_result_t found_cells[3]; int nof_freqs; lte_earfcn_t channels[MAX_EARFCN]; @@ -142,21 +140,6 @@ int main(int argc, char **argv) { 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 threshold/2) { - if (decode_pbch(uhd, &found_cells[i], nof_frames_total, bch_payload, &nof_tx_ports, NULL)) { + if (found_cells[i].peak > config.threshold/2) { + if (decode_pbch(uhd, &found_cells[i], config.nof_frames_total, bch_payload, &nof_tx_ports, NULL)) { fprintf(stderr, "Error decoding PBCH\n"); exit(-1); } else { @@ -194,7 +177,6 @@ int main(int argc, char **argv) { printf("\nBye\n"); - ue_celldetect_free(&s); cuhd_close(uhd); exit(0); } diff --git a/lte/examples/cell_search_utils.c b/lte/examples/cell_search_utils.c index 331b4a6ca..fbb6a986a 100644 --- a/lte/examples/cell_search_utils.c +++ b/lte/examples/cell_search_utils.c @@ -37,6 +37,8 @@ #include "liblte/phy/phy.h" #include "liblte/rrc/rrc.h" +#include "cell_search_utils.h" + #ifndef DISABLE_UHD #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) { printf("Realigning frame\n"); + // Receive some randon number of samples to try to resynchronise the frame. if (cuhd_recv(uhd, buffer, 1500, 1)<0) { fprintf(stderr, "Error receiving from USRP\n"); goto free_and_exit; @@ -110,7 +113,7 @@ free_and_exit: 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; 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"); 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); 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; @@ -200,7 +213,7 @@ int find_all_cells(void *uhd, ue_celldetect_result_t found_cell[3]) int nof_detected_cells = 0; 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) { nof_detected_cells++; } 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; } -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; 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]; 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) { - 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 { - ret = find_all_cells(uhd, found_cells); + ret = detect_all_cells(config, uhd, found_cells); } if (ret < 0) { fprintf(stderr, "Error searching cell\n"); diff --git a/lte/examples/cell_search_utils.h b/lte/examples/cell_search_utils.h index a73a52ec5..03a14f36f 100644 --- a/lte/examples/cell_search_utils.h +++ b/lte/examples/cell_search_utils.h @@ -28,6 +28,12 @@ #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, ue_celldetect_result_t *found_cell, uint32_t nof_frames_total, @@ -35,13 +41,16 @@ int decode_pbch(void *uhd, uint32_t *nof_tx_ports, uint32_t *sfn_offset); -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]); -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 cell_search(void *uhd, - int force_N_id_2, - lte_cell_t *cell); \ No newline at end of file +int detect_and_decode_cell(cell_detect_cfg_t *config, + void *uhd, + int force_N_id_2, + lte_cell_t *cell); \ No newline at end of file diff --git a/lte/examples/iodev.c b/lte/examples/iodev.c index 1f1e63b17..c64031783 100644 --- a/lte/examples/iodev.c +++ b/lte/examples/iodev.c @@ -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_rx_wait_lo_locked(q->uhd); 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"); return LIBLTE_ERROR; } diff --git a/lte/phy/include/liblte/phy/phch/dci.h b/lte/phy/include/liblte/phy/phch/dci.h index 66e166571..b21fa7d3a 100644 --- a/lte/phy/include/liblte/phy/phch/dci.h +++ b/lte/phy/include/liblte/phy/phch/dci.h @@ -46,7 +46,7 @@ typedef _Complex float cf_t; #define DCI_MAX_BITS 57 typedef enum { - Format0, Format1, Format1A, Format1C + Format0, Format1, Format1A, Format1C, FormatError } dci_format_t; // 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, 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 int dci_location_set(dci_location_t *c, diff --git a/lte/phy/include/liblte/phy/phch/pdcch.h b/lte/phy/include/liblte/phy/phch/pdcch.h index d9681784b..d061f7d0e 100644 --- a/lte/phy/include/liblte/phy/phch/pdcch.h +++ b/lte/phy/include/liblte/phy/phch/pdcch.h @@ -53,7 +53,6 @@ typedef enum LIBLTE_API { /* PDCCH object */ typedef struct LIBLTE_API { lte_cell_t cell; - uint32_t e_bits; uint32_t nof_regs; uint32_t nof_cce; uint32_t max_bits; @@ -99,13 +98,13 @@ LIBLTE_API 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); /* Decoding functions: Try to decode a DCI message after calling pdcch_extract_llr */ LIBLTE_API int pdcch_decode_msg(pdcch_t *q, dci_msg_t *msg, + dci_location_t *location, dci_format_t format, uint16_t *crc_rem); diff --git a/lte/phy/include/liblte/phy/phch/ra.h b/lte/phy/include/liblte/phy/phch/ra.h index 0d519c031..98e8eca09 100644 --- a/lte/phy/include/liblte/phy/phch/ra.h +++ b/lte/phy/include/liblte/phy/phch/ra.h @@ -39,7 +39,7 @@ typedef struct LIBLTE_API { lte_mod_t mod; - uint32_t tbs; + int tbs; } ra_mcs_t; typedef enum LIBLTE_API { @@ -72,7 +72,7 @@ typedef struct LIBLTE_API { } ra_type2_t; typedef struct LIBLTE_API { - uint32_t prb_idx[MAX_PRB]; + bool prb_idx[MAX_PRB]; uint32_t nof_prb; } ra_prb_slot_t; @@ -123,7 +123,8 @@ typedef struct LIBLTE_API { } ra_pusch_t; 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, ra_pdsch_t *ra, diff --git a/lte/phy/include/liblte/phy/ue/ue_dl.h b/lte/phy/include/liblte/phy/ue/ue_dl.h index 00f5b7f3b..56e7a4dc7 100644 --- a/lte/phy/include/liblte/phy/ue/ue_dl.h +++ b/lte/phy/include/liblte/phy/ue/ue_dl.h @@ -73,6 +73,7 @@ typedef struct LIBLTE_API { uint64_t pkt_errors; uint64_t pkts_total; + uint64_t nof_pdcch_detected; uint16_t user_rnti; }ue_dl_t; diff --git a/lte/phy/lib/ch_estimation/src/refsignal_dl.c b/lte/phy/lib/ch_estimation/src/refsignal_dl.c index 5d3d6d690..168637c3b 100644 --- a/lte/phy/lib/ch_estimation/src/refsignal_dl.c +++ b/lte/phy/lib/ch_estimation/src/refsignal_dl.c @@ -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); 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)]; - 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); + fidx += 6; // 1 reference every 6 RE } } 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); 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)]; - 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 } } diff --git a/lte/phy/lib/fec/src/rm_conv.c b/lte/phy/lib/fec/src/rm_conv.c index e01e81876..876c5d824 100644 --- a/lte/phy/lib/fec/src/rm_conv.c +++ b/lte/phy/lib/fec/src/rm_conv.c @@ -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; float tmp[3 * NCOLS * NROWS_MAX]; - + nrows = (uint32_t) (out_len / 3 - 1) / NCOLS + 1; if (nrows > NROWS_MAX) { fprintf(stderr, "Output too large. Max output length is %d\n", diff --git a/lte/phy/lib/mimo/src/precoding.c b/lte/phy/lib/mimo/src/precoding.c index 2dd39e34d..f3dd41af5 100644 --- a/lte/phy/lib/mimo/src/precoding.c +++ b/lte/phy/lib/mimo/src/precoding.c @@ -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) 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|) vec_prod_conj_ccc(r0,h0,q->tmp1, nof_symbols/2); diff --git a/lte/phy/lib/mimo/test/precoding_test.c b/lte/phy/lib/mimo/test/precoding_test.c index 5528fb8fb..6374175ad 100644 --- a/lte/phy/lib/mimo/test/precoding_test.c +++ b/lte/phy/lib/mimo/test/precoding_test.c @@ -132,7 +132,7 @@ int main(int argc, char **argv) { /* generate random data */ for (i = 0; i < nof_layers; i++) { 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; // assume the channel is time-invariant in nlayer consecutive symbols for (int k=0;k 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++) { free(x[i]); diff --git a/lte/phy/lib/phch/src/dci.c b/lte/phy/lib/phch/src/dci.c index 62542fdb0..86cac5e2e 100644 --- a/lte/phy/lib/phch/src/dci.c +++ b/lte/phy/lib/phch/src/dci.c @@ -61,7 +61,8 @@ int dci_msg_to_ra_dl(dci_msg_t *msg, uint16_t msg_rnti, uint16_t c_rnti, return ret; } - if (VERBOSE_ISDEBUG()) { + if (VERBOSE_ISINFO()) { + INFO("",0); dci_msg_type_fprint(stdout, type); } 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; } - if (VERBOSE_ISDEBUG()) { + if (VERBOSE_ISINFO()) { 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); } +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) { switch (format) { case Format0: diff --git a/lte/phy/lib/phch/src/pdcch.c b/lte/phy/lib/phch/src/pdcch.c index 9a5351f7d..2b0c0af24 100644 --- a/lte/phy/lib/phch/src/pdcch.c +++ b/lte/phy/lib/phch/src/pdcch.c @@ -49,14 +49,6 @@ #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) { if (cfi > 0 && cfi < 4) { 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"); } - /* Allocate memory for the largest aggregation level L=3 */ - q->max_bits = PDCCH_FORMAT_NOF_BITS(3); + /* Allocate memory for the maximum number of PDCCH bits (CFI=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)) { goto clean; @@ -112,31 +105,33 @@ int pdcch_init(pdcch_t *q, regs_t *regs, lte_cell_t cell) { 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) { 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) { 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) { goto clean; } 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]) { 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]) { 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]) { 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 Yk = rnti; - for (m = 0; m < nsubframe; m++) { + for (m = 0; m < nsubframe+1; m++) { 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--) { L = (1 << l); // 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)); if (k < max_candidates && 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].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++; @@ -256,7 +251,7 @@ uint32_t pdcch_common_locations(pdcch_t *q, dci_location_t *c, uint32_t max_cand if (k < max_candidates) { c[k].L = l; c[k].ncce = (L) * (i % (q->nof_cce / (L))); - DEBUG("Common SS Candidate %d: nCCE: %d, L: %d\n", + INFO("Common SS Candidate %d: nCCE: %d, L: %d\n", k, c[k].ncce, c[k].L); 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) { + DEBUG("Rm input: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_f(stdout, e, E); + } + /* unrate matching */ 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]; p_bits = (uint16_t) bit_unpack(&x, 16); 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); 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 * */ -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; - if (q != NULL && - msg != NULL && + if (q != NULL && + msg != NULL && + dci_location_isvalid(location) && 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); - if (ret == LIBLTE_SUCCESS) { - msg->nof_bits = nof_bits; + INFO("Decoding DCI offset %d, e_bits: %d, msg_len %d (nCCE: %d, L: %d)\n", + location->ncce * 72, e_bits, nof_bits, location->ncce, location->L); + + 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; @@ -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 */ 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; @@ -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 && nsubframe < 10 && cfi > 0 && - cfi < 4 && - dci_location_isvalid(&location)) + cfi < 4) { set_cfi(q, cfi); - q->e_bits = PDCCH_FORMAT_NOF_BITS(location.L); - nof_symbols = q->e_bits/2; + uint32_t e_bits = 72*q->nof_cce; + nof_symbols = 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, SF: %d, CFI: %d\n", - q->e_bits, location.ncce, location.L, nsubframe, cfi); + + INFO("Extracting LLRs: E: %d, SF: %d, CFI: %d\n", + e_bits, nsubframe, cfi); - /* number of layers equals number of ports */ - for (i = 0; i < q->cell.nof_ports; i++) { - x[i] = q->pdcch_x[i]; - } - memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); + /* number of layers equals number of ports */ + for (i = 0; i < q->cell.nof_ports; i++) { + x[i] = q->pdcch_x[i]; + } + 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 */ - int n = regs_pdcch_get_offset(q->regs, sf_symbols, q->pdcch_symbols[0], - location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L)); + /* extract channel estimates */ + for (i = 0; i < q->cell.nof_ports; i++) { + n = regs_pdcch_get(q->regs, ce[i], q->ce[i]); if (nof_symbols != n) { fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n); return ret; } + } - /* extract channel estimates */ - for (i = 0; i < q->cell.nof_ports; i++) { - n = regs_pdcch_get_offset(q->regs, ce[i], q->ce[i], - location.ncce * 9, PDCCH_FORMAT_NOF_REGS(location.L)); - if (nof_symbols != n) { - fprintf(stderr, "Expected %d PDCCH symbols but got %d symbols\n", nof_symbols, n); - return ret; - } - } - - /* 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); - } + /* 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); + } - /* demodulate symbols */ - demod_soft_sigma_set(&q->demod, 1.0); - demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, nof_symbols); + DEBUG("pdcch d symbols: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_c(stdout, q->pdcch_d, nof_symbols); + } - DEBUG("llr: ", 0); - if (VERBOSE_ISDEBUG()) { - vec_fprint_f(stdout, q->pdcch_llr, q->e_bits); - } + /* demodulate symbols */ + demod_soft_sigma_set(&q->demod, 1); + demod_soft_demodulate(&q->demod, q->pdcch_d, q->pdcch_llr, nof_symbols); - /* descramble */ - scrambling_f_offset(&q->seq_pdcch[nsubframe], q->pdcch_llr, 72 * location.ncce, q->e_bits); + /* descramble */ + scrambling_f_offset(&q->seq_pdcch[nsubframe], q->pdcch_llr, 0, e_bits); - ret = LIBLTE_SUCCESS; - } else { - fprintf(stderr, "Illegal DCI message nCCE: %d, L: %d, nof_cce: %d\n", location.ncce, location.L, q->nof_cce); + DEBUG("llr: ", 0); + if (VERBOSE_ISDEBUG()) { + vec_fprint_f(stdout, q->pdcch_llr, e_bits); } + + ret = LIBLTE_SUCCESS; } 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); - q->e_bits = PDCCH_FORMAT_NOF_BITS(location.L); - nof_symbols = q->e_bits/2; + uint32_t e_bits = PDCCH_FORMAT_NOF_BITS(location.L); + nof_symbols = 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); + 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 */ 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)); - 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); 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 */ if (q->cell.nof_ports > 1) { diff --git a/lte/phy/lib/phch/src/pdsch.c b/lte/phy/lib/phch/src/pdsch.c index a9d223cf0..8d460db0b 100644 --- a/lte/phy/lib/phch/src/pdsch.c +++ b/lte/phy/lib/phch/src/pdsch.c @@ -49,8 +49,11 @@ const lte_mod_t modulations[4] = { 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, 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", prb_alloc->re_sf[nsubframe], prb_alloc->slot[0].nof_prb); +#ifdef DEBUG_IDX + offset_original = input; +#endif + if (q->cell.nof_ports == 1) { nof_refs = 2; } 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 (l = 0; l < CP_NSYMB(q->cell.cp); l++) { - for (n = 0; n < prb_alloc->slot[s].nof_prb; n++) { - if (s == 0) { - lstart = prb_alloc->lstart; - } else { - lstart = 0; - } - lend = CP_NSYMB(q->cell.cp); - is_pbch = is_sss = false; - - // 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; + for (n = 0; n < q->cell.nof_prb; n++) { + + // If this PRB is assigned + if (prb_alloc->slot[s].prb_idx[n]) { + if (s == 0) { + lstart = prb_alloc->lstart; + } else { + lstart = 0; } - } - // Skip PBCH - if (s == 1 && nsubframe == 0) { - 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) { - lstart = 4; - is_pbch = true; + lend = CP_NSYMB(q->cell.cp); + is_pbch = is_sss = false; + + // Skip PSS/SSS signals + if (s == 0 && (nsubframe == 0 || nsubframe == 5)) { + if (n >= q->cell.nof_prb / 2 - 3 + && n < q->cell.nof_prb / 2 + 3) { + lend = CP_NSYMB(q->cell.cp) - 2; + is_sss = true; + } } - } - lp = l + s * CP_NSYMB(q->cell.cp); - if (put) { - out_ptr = &output[(lp * q->cell.nof_prb + prb_alloc->slot[s].prb_idx[n]) - * RE_X_RB]; - } else { - 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; + // Skip PBCH + if (s == 1 && nsubframe == 0) { + if (n >= q->cell.nof_prb / 2 - 3 + && n < q->cell.nof_prb / 2 + 3) { + lstart = 4; + is_pbch = true; } - 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 { - prb_cp(&in_ptr, &out_ptr, 1); + in_ptr = &input[(lp * q->cell.nof_prb + n) + * RE_X_RB]; } - } - if ((q->cell.nof_prb % 2) && ((is_pbch && l < lstart) || (is_sss && l >= lend))) { - if (prb_alloc->slot[s].prb_idx[n] == q->cell.nof_prb / 2 - 3) { + // This is a symbol in a normal PRB with or without references + if (l >= lstart && l < lend) { 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 { - 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) { - 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); + } + // This is a symbol in a PRB with PBCH or Synch signals (SS). + // If the number or total PRB is odd, half of the the PBCH or SS will fall into the symbol + if ((q->cell.nof_prb % 2) && ((is_pbch && l < lstart) || (is_sss && l >= lend))) { + if (n == q->cell.nof_prb / 2 - 3) { + 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); + } + } 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"); 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 */ 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); do { - tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len); 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); return LIBLTE_ERROR; } - + /* extract channel estimates */ for (i = 0; i < q->cell.nof_ports; i++) { 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; } } - + /* TODO: only diversity is supported */ if (q->cell.nof_ports == 1) { /* 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, nof_symbols / q->cell.nof_ports); } - + + vec_save_file("pdsch_after.dat",q->pdsch_d,sizeof(cf_t)*nof_symbols); + /* demodulate symbols * 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 */ - 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_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols); - - /* - for (int j=0;jpdsch_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 */ 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); } else { return LIBLTE_ERROR_INVALID_INPUTS; diff --git a/lte/phy/lib/phch/src/prb.c b/lte/phy/lib/phch/src/prb.c index 3bd597af6..40bac2014 100644 --- a/lte/phy/lib/phch/src/prb.c +++ b/lte/phy/lib/phch/src/prb.c @@ -32,12 +32,27 @@ #include "prb.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= 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 (slot == 0) { 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++) { prb_dist->re_sf[i] = 0; for (s = 0; s < 2; s++) { - for (j = 0; j < prb_dist->slot[s].nof_prb; j++) { - prb_dist->re_sf[i] += ra_re_x_prb(i, s, prb_dist->slot[s].prb_idx[j], - nof_prb, nof_ports, nof_ctrl_symbols, cp); + for (j = 0; j < nof_prb; j++) { + if (prb_dist->slot[s].prb_idx[j]) { + 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) { - int i, j, nrows; - nrows = (prb->nof_prb - 1) / 25 + 1; - for (j = 0; j < nrows; j++) { - for (i = 0; i < min(25, prb->nof_prb - j * 25); i++) { - fprintf(f, "%3d, ", prb->prb_idx[j * 25 + i]); +void ra_prb_fprint(FILE *f, ra_prb_slot_t *prb, uint32_t nof_prb) { + int i; + if (prb->nof_prb > 0) { + for (i=0;iprb_idx[i]) { + fprintf(f, "%d, ", i); + } } 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 i; 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))) { for (j = 0; j < P; j++) { 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++; } } @@ -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; for (i = 0; i < n_rb_type1; i++) { if (bitmask & (1 << (n_rb_type1 - i - 1))) { - prb_dist->slot[0].prb_idx[prb_dist->slot[0].nof_prb] = ((i + shift) / P) - * P * P + ra->type1_alloc.rbg_subset * P + (i + shift) % P; + prb_dist->slot[0].prb_idx[((i + shift) / P) + * P * P + ra->type1_alloc.rbg_subset * P + (i + shift) % P] = true; 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: if (ra->type2_alloc.mode == t2_loc) { 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++; } 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; int n_tilde_prb_odd, n_tilde_prb_even; 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); } 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_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); 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 { - prb_dist->slot[0].prb_idx[i] = n_tilde_prb_odd + N_gap - - N_tilde_vrb / 2; + prb_dist->slot[0].prb_idx[n_tilde_prb_odd + N_gap + - N_tilde_vrb / 2] = true; } prb_dist->slot[0].nof_prb++; 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 { - prb_dist->slot[1].prb_idx[i] = n_tilde_prb_even + N_gap - - N_tilde_vrb / 2; + prb_dist->slot[1].prb_idx[n_tilde_prb_even + N_gap + - N_tilde_vrb / 2] = true; } 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); for (int s = 0; s < 2; 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)); diff --git a/lte/phy/lib/phch/src/regs.c b/lte/phy/lib/phch/src/regs.c index d752e7d77..e83d7f0b7 100644 --- a/lte/phy/lib/phch/src/regs.c +++ b/lte/phy/lib/phch/src/regs.c @@ -67,11 +67,9 @@ void regs_pdcch_free(regs_t *h) { for (i=0;i<3;i++) { if (h->pdcch[i].regs) { free(h->pdcch[i].regs); + h->pdcch[i].regs = NULL; } } - - bzero(h, sizeof(regs_t)); - } #define PDCCH_NCOLS 32 @@ -114,7 +112,7 @@ int regs_pdcch_init(regs_t *h) { } h->pdcch[cfi].nof_regs = m; - + h->pdcch[cfi].regs = malloc(sizeof(regs_reg_t*) * h->pdcch[cfi].nof_regs); if (!h->pdcch[cfi].regs) { 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; + 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); tmp = NULL; } @@ -348,13 +348,12 @@ void regs_phich_free(regs_t *h) { for (i=0;ingroups_phich;i++) { if (h->phich[i].regs) { free(h->phich[i].regs); + h->phich[i].regs = NULL; } } free(h->phich); + h->phich = NULL; } - - bzero(h, sizeof(regs_t)); - } uint32_t regs_phich_nregs(regs_t *h) { @@ -487,7 +486,7 @@ int regs_pcfich_init(regs_t *h) { k); return LIBLTE_ERROR; } else { - ch->regs[i]->assigned = true; + ch->regs[i]->assigned = true; 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) { if (h->pcfich.regs) { free(h->pcfich.regs); + h->pcfich.regs = NULL; } - - bzero(h, sizeof(regs_t)); - } uint32_t regs_pcfich_nregs(regs_t *h) { diff --git a/lte/phy/lib/phch/test/pdcch_file_test.c b/lte/phy/lib/phch/test/pdcch_file_test.c index ebba943c4..aedd8fb4c 100644 --- a/lte/phy/lib/phch/test/pdcch_file_test.c +++ b/lte/phy/lib/phch/test/pdcch_file_test.c @@ -34,8 +34,8 @@ #include "liblte/phy/phy.h" char *input_file_name = NULL; -char *matlab_file_name = NULL; +#define MAX_CANDIDATES 64 lte_cell_t cell = { 6, // cell.cell.cell.nof_prb @@ -50,8 +50,8 @@ uint32_t cfi = 2; int flen; uint16_t rnti = SIRNTI; int max_frames = 10; -FILE *fmatlab = NULL; +dci_format_t dci_format = Format1A; filesource_t fsrc; pdcch_t pdcch; cf_t *input_buffer, *fft_buffer, *ce[MAX_PORTS]; @@ -61,9 +61,9 @@ chest_dl_t chest; void usage(char *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-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-p cell.nof_ports [Default %d]\n", cell.nof_ports); 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) { int opt; - while ((opt = getopt(argc, argv, "irovfcenmp")) != -1) { + while ((opt = getopt(argc, argv, "irvofcenmp")) != -1) { switch(opt) { case 'i': input_file_name = argv[optind]; @@ -98,7 +98,11 @@ void parse_args(int argc, char **argv) { cell.nof_ports = atoi(argv[optind]); break; 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; case 'v': verbose++; @@ -125,16 +129,6 @@ int base_init() { 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))); input_buffer = malloc(flen * sizeof(cf_t)); @@ -189,9 +183,6 @@ void base_free() { int i; filesource_free(&fsrc); - if (fmatlab) { - fclose(fmatlab); - } free(input_buffer); free(fft_buffer); @@ -210,9 +201,9 @@ void base_free() { int main(int argc, char **argv) { ra_pdsch_t ra_dl; int i; - int nof_frames; + int frame_cnt; int ret; - dci_location_t locations[10]; + dci_location_t locations[MAX_CANDIDATES]; uint32_t nof_locations; dci_msg_t dci_msg; @@ -228,84 +219,72 @@ int main(int argc, char **argv) { 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; - nof_frames = 0; + frame_cnt = 0; do { 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) { - fprintf(fmatlab, "infft%d=", nof_frames); - vec_fprint_c(fmatlab, input_buffer, flen); - fprintf(fmatlab, ";\n"); + lte_fft_run_sf(&fft, input_buffer, fft_buffer); - fprintf(fmatlab, "outfft%d=", nof_frames); - vec_sc_prod_cfc(fft_buffer, 1000.0, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); - vec_fprint_c(fmatlab, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); - fprintf(fmatlab, ";\n"); - vec_sc_prod_cfc(fft_buffer, 0.001, fft_buffer, CP_NSYMB(cell.cp) * cell.nof_prb * RE_X_RB); - } + /* Get channel estimates for each port */ + chest_dl_estimate(&chest, fft_buffer, ce, frame_cnt %10); + + uint16_t crc_rem = 0; + 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 */ - chest_dl_estimate(&chest, fft_buffer, ce, nof_frames); - - uint16_t crc_rem = 0; - for (i=0;i 0) { if (pdsch_harq_setup(&harq_process, ra_dl.mcs, &ra_dl.prb_alloc)) { fprintf(stderr, "Error configuring HARQ process\n"); 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"); goto goout; } else { printf("PDSCH Decoded OK!\n"); } + } else { + printf("Received DCI with no resource allocation\n"); } + sf_idx = (sf_idx+1)%10; } nof_frames++; diff --git a/lte/phy/lib/ue/src/ue_dl.c b/lte/phy/lib/ue/src/ue_dl.c index 2e06a057f..0918c11a0 100644 --- a/lte/phy/lib/ue/src/ue_dl.c +++ b/lte/phy/lib/ue/src/ue_dl.c @@ -36,6 +36,7 @@ #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 MAX_CANDIDATES 64 int ue_dl_init(ue_dl_t *q, lte_cell_t cell, @@ -146,17 +147,24 @@ void ue_dl_free(ue_dl_t *q) { LIBLTE_API float mean_exec_time=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) { uint32_t cfi, cfi_distance, i; ra_pdsch_t ra_dl; - dci_location_t locations[10]; + dci_location_t locations[MAX_CANDIDATES]; dci_msg_t dci_msg; uint32_t nof_locations; uint16_t crc_rem; - dci_format_t format; int ret = LIBLTE_ERROR; struct timeval t[3]; + uint32_t nof_formats; + dci_format_t *formats = NULL; /* Run FFT for all subframe data */ 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); get_time_interval(t); mean_exec_time = (float) VEC_CMA((float) t[0].tv_usec, mean_exec_time, 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 */ if (rnti == SIRNTI) { - nof_locations = pdcch_common_locations(&q->pdcch, locations, 10, cfi); - format = Format1A; + nof_locations = pdcch_common_locations(&q->pdcch, locations, MAX_CANDIDATES, cfi); + formats = common_formats; + nof_formats = nof_common_formats; } else { - nof_locations = pdcch_ue_locations(&q->pdcch, locations, 10, sf_idx, cfi, q->user_rnti); - format = Format1; + nof_locations = pdcch_ue_locations(&q->pdcch, locations, MAX_CANDIDATES, sf_idx, cfi, q->user_rnti); + 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; - for (i=0;ipdcch, q->sf_symbols, q->ce, chest_dl_get_noise_estimate(&q->chest), locations[i], sf_idx, cfi)) { - fprintf(stderr, "Error extracting LLRs\n"); - return LIBLTE_ERROR; - } - if (pdcch_decode_msg(&q->pdcch, &dci_msg, format, &crc_rem)) { - fprintf(stderr, "Error decoding DCI msg\n"); - return LIBLTE_ERROR; + for (int f=0;fpdcch, &dci_msg, &locations[i], formats[f], &crc_rem)) { + fprintf(stderr, "Error decoding DCI msg\n"); + return LIBLTE_ERROR; + } + INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); } - INFO("Decoded DCI message RNTI: 0x%x\n", crc_rem); } 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)) { fprintf(stderr, "Error unpacking PDSCH scheduling DCI message\n"); 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++; } else if (rnti != SIRNTI) { q->pkt_errors++; - } + } } else if (ret == LIBLTE_ERROR_INVALID_INPUTS) { fprintf(stderr, "Error calling pdsch_decode()\n"); return LIBLTE_ERROR; diff --git a/lte/phy/lib/ue/src/ue_mib.c b/lte/phy/lib/ue/src/ue_mib.c index 764429acf..e7075ee08 100644 --- a/lte/phy/lib/ue/src/ue_mib.c +++ b/lte/phy/lib/ue/src/ue_mib.c @@ -161,7 +161,8 @@ int ue_mib_decode_aligned_frame(ue_mib_t * q, cf_t *input, if (ret < 0) { 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 */ if ((q->last_frame_trial && (abs(q->frame_cnt - q->last_frame_trial) > 2)) || q->frame_cnt > 16) @@ -177,7 +178,7 @@ int ue_mib_decode_aligned_frame(ue_mib_t * q, cf_t *input, /* Decode PBCH */ 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); if (ret < 0) { 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) { INFO("Trying to decode MIB\n",0); - printf("caution here should pass begining of frame \n"); - exit(-1); - 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); + ret = ue_mib_decode_aligned_frame(q, + &signal[nf*MIB_FRAME_SIZE_SEARCH+peak_idx-MIB_FRAME_SIZE_SEARCH/10], + q->bch_payload, &q->nof_tx_ports, &q->sfn_offset); counter3++; } else if ((ret == LIBLTE_SUCCESS && peak_idx != 0) || (ret == 1 && nf*MIB_FRAME_SIZE_SEARCH + peak_idx + MIB_FRAME_SIZE_SEARCH/10 > nsamples)) diff --git a/lte/phy/lib/ue/src/ue_sync.c b/lte/phy/lib/ue/src/ue_sync.c index 4943c7dc9..5090f212c 100644 --- a/lte/phy/lib/ue/src/ue_sync.c +++ b/lte/phy/lib/ue/src/ue_sync.c @@ -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); /* FIXME: What should we do in this case? */ q->sf_idx = sync_get_sf_idx(&q->strack); - q->state = SF_TRACK; + q->state = SF_FIND; } else { q->time_offset = ((int) track_idx - (int) CURRENT_FFTSIZE); diff --git a/matlab/tests/test_pdsch_resalloc.m b/matlab/tests/test_pdsch_resalloc.m new file mode 100644 index 000000000..61c9d9740 --- /dev/null +++ b/matlab/tests/test_pdsch_resalloc.m @@ -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); +