From 134eea27f86196e886aee9dfa31082131f6c6bde Mon Sep 17 00:00:00 2001 From: ismagom Date: Tue, 30 Dec 2014 10:23:03 -0500 Subject: [PATCH] Finished PDSCH MEX test. Read MCS from STDIN in pdsch_enodeb --- lte/examples/pdsch_enodeb.c | 96 ++++++++++++------ lte/phy/lib/phch/src/pdsch.c | 92 +++++++++-------- lte/phy/lib/phch/test/CMakeLists.txt | 2 + lte/phy/lib/phch/test/pdsch_test.c | 3 +- lte/phy/lib/phch/test/pdsch_test_mex.c | 135 ++++++++++++++++--------- matlab/tests/pdsch_bler.m | 21 ++-- mex/include/liblte/mex/mexutils.h | 3 + mex/lib/mexutils.c | 15 +++ 8 files changed, 239 insertions(+), 128 deletions(-) diff --git a/lte/examples/pdsch_enodeb.c b/lte/examples/pdsch_enodeb.c index 0c8e82215..fa42394ea 100644 --- a/lte/examples/pdsch_enodeb.c +++ b/lte/examples/pdsch_enodeb.c @@ -30,6 +30,7 @@ #include #include #include +#include #include "liblte/phy/phy.h" #include "liblte/rrc/rrc.h" @@ -179,13 +180,6 @@ void base_init() { exit(-1); } - /* - if (udpsource_set_nonblocking(&udp_source)) { - fprintf(stderr, "Error setting non-blocking\n"); - exit(-1); - } - */ - if (udpsource_set_timeout(&udp_source, 5)) { fprintf(stderr, "Error setting UDP socket timeout\n"); exit(-1); @@ -267,6 +261,60 @@ void base_free() { } +int update_radl(ra_pdsch_t *ra_dl) { + ra_prb_t prb_alloc; + + bzero(ra_dl, sizeof(ra_pdsch_t)); + ra_dl->harq_process = 0; + ra_dl->mcs_idx = mcs_idx; + ra_dl->ndi = 0; + ra_dl->rv_idx = 0; + ra_dl->alloc_type = alloc_type0; + ra_dl->type0_alloc.rbg_bitmask = 0xffffffff; + + ra_prb_get_dl(&prb_alloc, ra_dl, cell.nof_prb); + ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM); + ra_mcs_from_idx_dl(mcs_idx, cell.nof_prb, &ra_dl->mcs); + + ra_pdsch_fprint(stdout, ra_dl, cell.nof_prb); + + if (pdsch_harq_setup(&harq_process, ra_dl->mcs, &prb_alloc)) { + fprintf(stderr, "Error configuring HARQ process\n"); + return -1; + } + + return 0; +} + +/* Read new MCS from stdin */ +int update_control(ra_pdsch_t *ra_dl) { + char input[128]; + + fd_set set; + FD_ZERO(&set); + FD_SET(0, &set); + + struct timeval to; + to.tv_sec = 0; + to.tv_usec = 0; + + int n = select(1, &set, NULL, NULL, &to); + if (n == 1) { + // stdin ready + if (fgets(input, sizeof(input), stdin)) { + mcs_idx = atoi(input); + return update_radl(ra_dl); + } + return 0; + } else if (n < 0) { + // error + perror("select"); + return -1; + } else { + return 0; + } +} + uint8_t data[10000], data_unpacked[10000]; int main(int argc, char **argv) { @@ -275,8 +323,7 @@ int main(int argc, char **argv) { float sss_signal0[SSS_LEN]; // for subframe 0 float sss_signal5[SSS_LEN]; // for subframe 5 uint8_t bch_payload[BCH_PAYLOAD_LEN], bch_payload_packed[BCH_PAYLOAD_LEN/8]; - ra_pdsch_t ra_dl; - ra_prb_t prb_alloc; + ra_pdsch_t ra_dl; int i; cf_t *sf_symbols[MAX_PORTS]; cf_t *slot1_symbols[MAX_PORTS]; @@ -330,21 +377,9 @@ int main(int argc, char **argv) { } #endif - bzero(&ra_dl, sizeof(ra_pdsch_t)); - ra_dl.harq_process = 0; - ra_dl.mcs_idx = mcs_idx; - ra_dl.ndi = 0; - ra_dl.rv_idx = 0; - ra_dl.alloc_type = alloc_type0; - ra_dl.type0_alloc.rbg_bitmask = 0xffffffff; - - dci_msg_pack_pdsch(&ra_dl, &dci_msg, Format1, cell.nof_prb, false); - - ra_prb_get_dl(&prb_alloc, &ra_dl, cell.nof_prb); - ra_prb_get_re_dl(&prb_alloc, cell.nof_prb, 1, cell.nof_prb<10?(cfi+1):cfi, CPNORM); - ra_mcs_from_idx_dl(mcs_idx, cell.nof_prb, &ra_dl.mcs); - - ra_pdsch_fprint(stdout, &ra_dl, cell.nof_prb); + if (update_radl(&ra_dl)) { + exit(-1); + } /* Initiate valid DCI locations */ for (i=0;i 0) { @@ -405,6 +440,7 @@ int main(int argc, char **argv) { } if (send_data) { + dci_msg_pack_pdsch(&ra_dl, &dci_msg, Format1, cell.nof_prb, false); INFO("Putting DCI to location: n=%d, L=%d\n", locations[sf_idx][0].ncce, locations[sf_idx][0].L); if (pdcch_encode(&pdcch, &dci_msg, locations[sf_idx][0], 1234, sf_symbols, sf_idx, cfi)) { fprintf(stderr, "Error encoding DCI message\n"); @@ -433,7 +469,7 @@ int main(int argc, char **argv) { nf++; } sfn = (sfn + 1) % 1024; - printf("SFN: %4d\r", sfn); + printf("SFN: %4d\tType new MCS index and press Enter\r", sfn); fflush(stdout); } diff --git a/lte/phy/lib/phch/src/pdsch.c b/lte/phy/lib/phch/src/pdsch.c index 28b9c4a19..d18727fb0 100644 --- a/lte/phy/lib/phch/src/pdsch.c +++ b/lte/phy/lib/phch/src/pdsch.c @@ -675,60 +675,66 @@ int pdsch_decode(pdsch_t *q, cf_t *sf_symbols, cf_t *ce[MAX_PORTS], float noise_ harq_process != NULL) { - nof_bits = harq_process->mcs.tbs; - nof_symbols = harq_process->prb_alloc.re_sf[subframe]; - nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod); + if (q->rnti_is_set) { + nof_bits = harq_process->mcs.tbs; + nof_symbols = harq_process->prb_alloc.re_sf[subframe]; + nof_bits_e = nof_symbols * lte_mod_bits_x_symbol(harq_process->mcs.mod); - INFO("Decoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", - subframe, lte_mod_string(harq_process->mcs.mod), nof_bits, nof_symbols, nof_bits_e, rv_idx); + INFO("Decoding PDSCH SF: %d, Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", + subframe, lte_mod_string(harq_process->mcs.mod), nof_bits, nof_symbols, nof_bits_e, rv_idx); - /* number of layers equals number of ports */ - for (i = 0; i < q->cell.nof_ports; i++) { - x[i] = q->pdsch_x[i]; - } - memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); - - /* extract symbols */ - n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq_process->prb_alloc, subframe); - if (n != nof_symbols) { - 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); + /* number of layers equals number of ports */ + for (i = 0; i < q->cell.nof_ports; i++) { + x[i] = q->pdsch_x[i]; + } + memset(&x[q->cell.nof_ports], 0, sizeof(cf_t*) * (MAX_LAYERS - q->cell.nof_ports)); + + /* extract symbols */ + n = pdsch_get(q, sf_symbols, q->pdsch_symbols[0], &harq_process->prb_alloc, subframe); if (n != nof_symbols) { 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); + if (n != nof_symbols) { + fprintf(stderr, "Error expecting %d symbols but got %d\n", nof_symbols, n); + return LIBLTE_ERROR; + } + } - /* TODO: only diversity is supported */ - if (q->cell.nof_ports == 1) { - /* no need for layer demapping */ - predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d, - nof_symbols, noise_estimate); + /* TODO: only diversity is supported */ + if (q->cell.nof_ports == 1) { + /* no need for layer demapping */ + predecoding_single(&q->precoding, q->pdsch_symbols[0], q->ce[0], q->pdsch_d, + nof_symbols, noise_estimate); + } else { + predecoding_diversity(&q->precoding, q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports, + nof_symbols, noise_estimate); + layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports, + nof_symbols / q->cell.nof_ports); + } + + /* 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, sqrt((float) lte_mod_bits_x_symbol(harq_process->mcs.mod)/2)); + demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod]); + demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols); + + /* descramble */ + scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_e, 0, nof_bits_e); + + return pdsch_decode_tb(q, data, nof_bits, nof_bits_e, harq_process, rv_idx); } else { - predecoding_diversity(&q->precoding, q->pdsch_symbols[0], q->ce, x, q->cell.nof_ports, - nof_symbols, noise_estimate); - layerdemap_diversity(x, q->pdsch_d, q->cell.nof_ports, - nof_symbols / q->cell.nof_ports); + fprintf(stderr, "Must call pdsch_set_rnti() before calling pdsch_decode()\n"); + return LIBLTE_ERROR; } - /* 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, sqrt((float) lte_mod_bits_x_symbol(harq_process->mcs.mod)/2)); - demod_soft_table_set(&q->demod, &q->mod[harq_process->mcs.mod]); - demod_soft_demodulate(&q->demod, q->pdsch_d, q->pdsch_e, nof_symbols); - - /* descramble */ - scrambling_f_offset(&q->seq_pdsch[subframe], q->pdsch_e, 0, 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/test/CMakeLists.txt b/lte/phy/lib/phch/test/CMakeLists.txt index 5022bc63b..7a5c2de0c 100644 --- a/lte/phy/lib/phch/test/CMakeLists.txt +++ b/lte/phy/lib/phch/test/CMakeLists.txt @@ -98,6 +98,8 @@ ADD_TEST(pdsch_test_qpsk pdsch_test -l 1000 -m 2 -n 50 -r 1) ADD_TEST(pdsch_test_qam16 pdsch_test -l 50000 -m 4 -n 110) ADD_TEST(pdsch_test_qam64 pdsch_test -l 5000 -m 6 -n 50 -r 0) +BuildMex(MEXNAME pdsch SOURCES pdsch_test_mex.c LIBRARIES lte_phy liblte_mex) + ######################################################################## # FILE TEST ######################################################################## diff --git a/lte/phy/lib/phch/test/pdsch_test.c b/lte/phy/lib/phch/test/pdsch_test.c index 60b0c1ac4..68b33134e 100644 --- a/lte/phy/lib/phch/test/pdsch_test.c +++ b/lte/phy/lib/phch/test/pdsch_test.c @@ -137,13 +137,14 @@ int main(int argc, char **argv) { mcs.tbs = tbs; mcs.mod = modulation; + prb_alloc.slot[0].nof_prb = cell.nof_prb; for (i=0;i= 1) { - plhs[0] = mxCreateLogicalScalar(crc_rem == rnti); + plhs[0] = mxCreateLogicalScalar(r == 0); } - int nof_bits = (regs_pdcch_nregs(®s, cfi) / 9) * 72; if (nlhs >= 2) { - mexutils_write_f(pdcch.pdcch_llr, &plhs[1], nof_bits, 1); + mexutils_write_uint8(data, &plhs[1], mcs.tbs, 1); } if (nlhs >= 3) { - mexutils_write_cf(pdcch.pdcch_symbols[0], &plhs[2], 36*pdcch.nof_cce, 1); + mexutils_write_cf(pdsch.pdsch_symbols[0], &plhs[2], harq_process.prb_alloc.re_sf[sf_idx], 1); + } + if (nlhs >= 4) { + mexutils_write_cf(pdsch.pdsch_d, &plhs[3], harq_process.prb_alloc.re_sf[sf_idx], 1); } chest_dl_free(&chest); lte_fft_free(&fft); - pdcch_free(&pdcch); - regs_free(®s); + pdsch_free(&pdsch); for (i=0;i 0) + [dec2, llr, pdschRx, pdschSymbols2] = liblte_pdsch(rmccFgOut, rmccFgOut.PDSCH, ... + rmccFgOut.PDSCH.TrBlkSizes(sf_idx+1), ... + subframe_waveform); + else + dec2 = 1; + end + decoded_liblte(snr_idx) = decoded_liblte(snr_idx)+dec2; end end fprintf('SNR: %.1f\n',SNRdB) diff --git a/mex/include/liblte/mex/mexutils.h b/mex/include/liblte/mex/mexutils.h index c3cccda56..4fbf2ca94 100644 --- a/mex/include/liblte/mex/mexutils.h +++ b/mex/include/liblte/mex/mexutils.h @@ -47,6 +47,9 @@ LIBLTE_API bool mexutils_isScalar(const mxArray *ptr); LIBLTE_API int mexutils_read_cell(const mxArray *ptr, lte_cell_t *cell); +LIBLTE_API char *mexutils_get_char_struct(const mxArray *ptr, + const char *field_name); + LIBLTE_API int mexutils_read_uint32_struct(const mxArray *ptr, const char *field_name, uint32_t *value); diff --git a/mex/lib/mexutils.c b/mex/lib/mexutils.c index 6297e4c60..9a533f5d0 100644 --- a/mex/lib/mexutils.c +++ b/mex/lib/mexutils.c @@ -36,6 +36,21 @@ bool mexutils_isScalar(const mxArray *ptr) { return mxGetM(ptr) == 1 && mxGetN(ptr) == 1; } +char *mexutils_get_char_struct(const mxArray *ptr, const char *field_name) { + mxArray *p; + p = mxGetField(ptr, 0, field_name); + if (!p) { + mexPrintf("Error field %s not found\n", field_name); + return NULL; + } + + if (mxIsCell(p)) { + return mxArrayToString(mxGetCell(p,0)); + } else { + return mxArrayToString(p); + } +} + int mexutils_read_uint32_struct(const mxArray *ptr, const char *field_name, uint32_t *value) { mxArray *p;