diff --git a/lte/phy/examples/iodev.c b/lte/phy/examples/iodev.c index af6916105..41d6e6a48 100644 --- a/lte/phy/examples/iodev.c +++ b/lte/phy/examples/iodev.c @@ -48,7 +48,7 @@ int cuhd_recv_wrapper(void *h, void *data, uint32_t nsamples) { } /* Setup USRP or input file */ -int iodev_init(iodev_t *q, iodev_cfg_t *config) { +int iodev_init(iodev_t *q, iodev_cfg_t *config, uint32_t file_sf_len) { if (config->input_file_name) { if (filesource_init(&q->fsrc, config->input_file_name, COMPLEX_FLOAT_BIN)) { @@ -61,7 +61,7 @@ int iodev_init(iodev_t *q, iodev_cfg_t *config) { } q->mode = FILESOURCE; - q->sf_len = 1920; + q->sf_len = file_sf_len; } else { #ifndef DISABLE_UHD diff --git a/lte/phy/examples/iodev.h b/lte/phy/examples/iodev.h index 87264eda6..3164f91c5 100644 --- a/lte/phy/examples/iodev.h +++ b/lte/phy/examples/iodev.h @@ -74,7 +74,8 @@ typedef struct LIBLTE_API { LIBLTE_API int iodev_init(iodev_t *q, - iodev_cfg_t *config); + iodev_cfg_t *config, + uint32_t file_sf_len); LIBLTE_API void iodev_free(iodev_t *q); diff --git a/lte/phy/examples/pdsch_enodeb.c b/lte/phy/examples/pdsch_enodeb.c index 88f87864a..f761b043b 100644 --- a/lte/phy/examples/pdsch_enodeb.c +++ b/lte/phy/examples/pdsch_enodeb.c @@ -359,7 +359,10 @@ int main(int argc, char **argv) { exit(-1); } - pdsch_encode(&pdsch, data, sf_symbols, sf_idx, &harq_process, ra_dl.rv_idx); + if (pdsch_encode(&pdsch, data, sf_symbols, sf_idx, &harq_process, ra_dl.rv_idx)) { + fprintf(stderr, "Error encoding PDSCH\n"); + exit(-1); + } /* Transform to OFDM symbols */ lte_ifft_run_sf(&ifft, sf_buffer, output_buffer); diff --git a/lte/phy/examples/pdsch_ue.c b/lte/phy/examples/pdsch_ue.c index 951bc7393..2af627e65 100644 --- a/lte/phy/examples/pdsch_ue.c +++ b/lte/phy/examples/pdsch_ue.c @@ -165,11 +165,18 @@ int main(int argc, char **argv) { pbch_mib_t mib; bool printed_sib = false; int rlen; + int symbol_sz; parse_args(&prog_args, argc, argv); - if (iodev_init(&iodev, &prog_args.io_config)) { - fprintf(stderr, "Error initiating input device\n"); + symbol_sz = lte_symbol_sz(prog_args.nof_prb_file); + if (symbol_sz > 0) { + if (iodev_init(&iodev, &prog_args.io_config, SF_LEN(symbol_sz, CPNORM))) { + fprintf(stderr, "Error initiating input device\n"); + exit(-1); + } + } else { + fprintf(stderr, "Invalid number of PRB %d\n", prog_args.nof_prb_file); exit(-1); } @@ -242,9 +249,10 @@ int main(int argc, char **argv) { printed_sib = true; } if (!(sf_cnt % 10)) { - printf("RSSI: %+.2f dBm, CFO: %+.4f KHz, SFO: %+.4f Khz, TimeOffset: %4d, Errors: %4d/%4d, BLER: %.1e\r", + printf("RSSI: %+.2f dBm, CFO: %+.4f KHz, SFO: %+.4f Khz, NOI: %.2f Errors: %4d/%4d, BLER: %.1e\r", 20*log10f(agc_get_rssi(&iodev.sframe.agc))+30, - ue_sync_get_cfo(&iodev.sframe)/1000, ue_sync_get_sfo(&iodev.sframe)/1000, iodev.sframe.peak_idx, + ue_sync_get_cfo(&iodev.sframe)/1000, ue_sync_get_sfo(&iodev.sframe)/1000, + pdsch_average_noi(&ue_dl.pdsch), (int) ue_dl.pkt_errors, (int) ue_dl.pkts_total, (float) ue_dl.pkt_errors / ue_dl.pkts_total); fflush(stdout); diff --git a/lte/phy/include/liblte/phy/phch/pdsch.h b/lte/phy/include/liblte/phy/phch/pdsch.h index e844ffb8a..173837b98 100644 --- a/lte/phy/include/liblte/phy/phch/pdsch.h +++ b/lte/phy/include/liblte/phy/phch/pdsch.h @@ -43,7 +43,7 @@ #include "liblte/phy/phch/dci.h" #include "liblte/phy/phch/regs.h" -#define TDEC_ITERATIONS 3 +#define TDEC_MAX_ITERATIONS 6 typedef _Complex float cf_t; @@ -75,6 +75,9 @@ typedef struct LIBLTE_API { uint32_t max_symbols; bool rnti_is_set; uint16_t rnti; + uint32_t nof_iterations; + uint64_t average_nof_iterations_n; + float average_nof_iterations; /* buffers */ // void buffers are shared for tx and rx @@ -128,6 +131,10 @@ LIBLTE_API int pdsch_decode(pdsch_t *q, pdsch_harq_t *harq_process, uint32_t rv_idx); +LIBLTE_API float pdsch_average_noi(pdsch_t *q); + +LIBLTE_API uint32_t pdsch_last_noi(pdsch_t *q); + LIBLTE_API int pdsch_get(pdsch_t *q, cf_t *sf_symbols, cf_t *pdsch_symbols, diff --git a/lte/phy/lib/phch/src/pdsch.c b/lte/phy/lib/phch/src/pdsch.c index 0f5a508d4..54892bd72 100644 --- a/lte/phy/lib/phch/src/pdsch.c +++ b/lte/phy/lib/phch/src/pdsch.c @@ -183,7 +183,7 @@ int pdsch_init(pdsch_t *q, lte_cell_t cell) { ret = LIBLTE_ERROR; q->cell = cell; - + q->average_nof_iterations_n = 0; q->max_symbols = q->cell.nof_prb * MAX_PDSCH_RE(q->cell.cp); INFO("Init PDSCH: %d ports %d PRBs, max_symbols: %d\n", q->cell.nof_ports, @@ -459,6 +459,15 @@ int pdsch_harq_setup(pdsch_harq_t *p, ra_mcs_t mcs, ra_prb_t *prb_alloc) { } +float pdsch_average_noi(pdsch_t *q) { + return q->average_nof_iterations; +} + +uint32_t pdsch_last_noi(pdsch_t *q) { + return q->nof_iterations; +} + + /* Decode a transport block according to 36.212 5.3.2 * */ @@ -516,17 +525,42 @@ int pdsch_decode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e, return LIBLTE_ERROR; } - /* Turbo Decoding */ - tdec_run_all(&q->decoder, (float*) q->cb_out, q->cb_in, TDEC_ITERATIONS, - cb_len); - - if (harq_process->cb_segm.C > 1) { + /* Turbo Decoding with CRC-based early stopping */ + q->nof_iterations = 0; + bool early_stop = false; + uint32_t len_crc; + char *cb_in_ptr; + crc_t *crc_ptr; + tdec_reset(&q->decoder, cb_len); + + do { + + tdec_iteration(&q->decoder, (float*) q->cb_out, cb_len); + q->nof_iterations++; + + if (harq_process->cb_segm.C > 1) { + len_crc = cb_len; + cb_in_ptr = q->cb_in; + crc_ptr = &q->crc_cb; + } else { + len_crc = tbs+24; + cb_in_ptr = &q->cb_in[F]; + crc_ptr = &q->crc_tb; + } + /* Check Codeblock CRC and stop early if incorrect */ - if (crc_checksum(&q->crc_cb, q->cb_in, cb_len)) { - INFO("Error in CB#%d\n",i); - return LIBLTE_ERROR; + if (!crc_checksum(crc_ptr, cb_in_ptr, len_crc)) { + early_stop = true; } - } + + } while (q->nof_iterations < TDEC_MAX_ITERATIONS && !early_stop); + + tdec_decision(&q->decoder, q->cb_in, cb_len); + + q->average_nof_iterations = EXPAVERAGE((float) q->nof_iterations, + q->average_nof_iterations, + q->average_nof_iterations_n); + q->average_nof_iterations_n++; /* Copy data to another buffer, removing the Codeblock CRC */ if (i < harq_process->cb_segm.C - 1) { @@ -534,6 +568,7 @@ int pdsch_decode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e, } else { DEBUG("Last CB, appending parity: %d to %d from %d and 24 from %d\n", rlen - F - 24, wp, F, rlen - 24); + /* Append Transport Block parity bits to the last CB */ memcpy(&data[wp], &q->cb_in[F], (rlen - F - 24) * sizeof(char)); memcpy(parity, &q->cb_in[rlen - 24], 24 * sizeof(char)); @@ -553,6 +588,7 @@ int pdsch_decode_tb(pdsch_t *q, char *data, uint32_t tbs, uint32_t nb_e, par_tx = bit_unpack(&p_parity, 24); if (!par_rx) { + vec_fprint_hex(stdout, data, tbs); printf("\n\tCAUTION!! Received all-zero transport block\n\n"); }