From 338be7d0c2b97421a7fa4374dc3f7200867eb456 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 5 Sep 2017 13:17:33 +0200 Subject: [PATCH 01/10] Refactored grant: removed nof_tb from grant. Use tb_en instead. --- lib/examples/pdsch_enodeb.c | 18 ++-- lib/examples/pdsch_ue.c | 9 +- lib/include/srslte/interfaces/ue_interfaces.h | 2 + lib/include/srslte/phy/phch/ra.h | 4 +- lib/src/phy/phch/pdsch.c | 72 ++++++++------- lib/src/phy/phch/ra.c | 29 +++--- lib/src/phy/phch/sch.c | 4 +- lib/src/phy/phch/test/pdsch_test.c | 39 ++++---- lib/src/phy/ue/ue_dl.c | 61 +++++++------ srsue/hdr/mac/dl_harq.h | 6 +- srsue/hdr/phy/phch_worker.h | 2 +- srsue/src/phy/phch_worker.cc | 89 +++++++++++-------- 12 files changed, 193 insertions(+), 142 deletions(-) diff --git a/lib/examples/pdsch_enodeb.c b/lib/examples/pdsch_enodeb.c index 35f7d3e9f..afbe44b91 100644 --- a/lib/examples/pdsch_enodeb.c +++ b/lib/examples/pdsch_enodeb.c @@ -774,9 +774,11 @@ int main(int argc, char **argv) { } } else { INFO("SF: %d, Generating %d random bits\n", sf_idx, pdsch_cfg.grant.mcs[0].tbs + pdsch_cfg.grant.mcs[1].tbs); - for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) { - for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) { - data[tb][i] = (uint8_t) rand(); + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (pdsch_cfg.grant.tb_en[tb]) { + for (i = 0; i < pdsch_cfg.grant.mcs[tb].tbs / 8; i++) { + data[tb][i] = (uint8_t) rand(); + } } } /* Uncomment this to transmit on sf 0 and 5 only */ @@ -832,10 +834,12 @@ int main(int argc, char **argv) { } if (net_port > 0 && net_packet_ready) { if (null_file_sink) { - for (uint32_t tb = 0; tb < pdsch_cfg.grant.nof_tb; tb++) { - srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs); - if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) { - fprintf(stderr, "Error sending data through UDP socket\n"); + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (pdsch_cfg.grant.tb_en[tb]) { + srslte_bit_pack_vector(data[tb], data_tmp, pdsch_cfg.grant.mcs[tb].tbs); + if (srslte_netsink_write(&net_sink, data_tmp, 1 + (pdsch_cfg.grant.mcs[tb].tbs - 1) / 8) < 0) { + fprintf(stderr, "Error sending data through UDP socket\n"); + } } } } diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index 2ace49d6d..aa3e13257 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -641,9 +641,10 @@ int main(int argc, char **argv) { /* Send data if socket active */ if (prog_args.net_port > 0) { // FIXME: UDP Data transmission does not work - for (uint32_t tb = 0; tb < ue_dl.pdsch_cfg.grant.nof_tb; tb++) { - srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8); - + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (ue_dl.pdsch_cfg.grant.tb_en[tb]) { + srslte_netsink_write(&net_sink, data[tb], 1 + (ue_dl.pdsch_cfg.grant.mcs[tb].tbs - 1) / 8); + } } } @@ -704,7 +705,7 @@ int main(int argc, char **argv) { /* Print basic Parameters */ PRINT_LINE(" nof layers: %d", ue_dl.pdsch_cfg.nof_layers); - PRINT_LINE("nof codewords: %d", ue_dl.pdsch_cfg.grant.nof_tb); + PRINT_LINE("nof codewords: %d", SRSLTE_RA_DL_GRANT_NOF_TB(&ue_dl.pdsch_cfg.grant)); PRINT_LINE(" CFO: %+5.2f kHz", srslte_ue_sync_get_cfo(&ue_sync) / 1000); PRINT_LINE(" SNR: %+5.1f dB | %+5.1f dB", 10 * log10(rsrp0 / noise), 10 * log10(rsrp1 / noise)); PRINT_LINE(" Rb: %6.2f / %6.2f Mbps (net/maximum)", uerate, enodebrate); diff --git a/lib/include/srslte/interfaces/ue_interfaces.h b/lib/include/srslte/interfaces/ue_interfaces.h index 879118021..5907d164b 100644 --- a/lib/include/srslte/interfaces/ue_interfaces.h +++ b/lib/include/srslte/interfaces/ue_interfaces.h @@ -281,6 +281,8 @@ public: bool last_ndi[SRSLTE_MAX_CODEWORDS]; uint32_t n_bytes[SRSLTE_MAX_CODEWORDS]; int rv[SRSLTE_MAX_CODEWORDS]; + bool tb_en[SRSLTE_MAX_CODEWORDS]; + bool tb_cw_swap; uint16_t rnti; bool is_from_rar; bool is_sps_release; diff --git a/lib/include/srslte/phy/phch/ra.h b/lib/include/srslte/phy/phch/ra.h index 9f31a0218..94cc9a084 100644 --- a/lib/include/srslte/phy/phch/ra.h +++ b/lib/include/srslte/phy/phch/ra.h @@ -104,10 +104,12 @@ typedef struct SRSLTE_API { uint32_t nof_prb; uint32_t Qm[SRSLTE_MAX_CODEWORDS]; srslte_ra_mcs_t mcs[SRSLTE_MAX_CODEWORDS]; - uint32_t nof_tb; + bool tb_en[SRSLTE_MAX_CODEWORDS]; uint32_t pinfo; } srslte_ra_dl_grant_t; +#define SRSLTE_RA_DL_GRANT_NOF_TB(G) ((((G)->tb_en[0])?1:0)+(((G)->tb_en[1])?1:0)) + /** Unpacked DCI message for DL grant */ typedef struct SRSLTE_API { diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index bc62df7fd..fe10791d7 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -427,15 +427,17 @@ int srslte_pdsch_cfg(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_g int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type, uint32_t pmi) { - if (cfg) { - if (grant) { - memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); - } + if (cfg && grant) { + uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant); + memcpy(&cfg->grant, grant, sizeof(srslte_ra_dl_grant_t)); - for (int i = 0; i < grant->nof_tb; i++) { - if (srslte_cbsegm(&cfg->cb_segm[i], (uint32_t) cfg->grant.mcs[i].tbs)) { - fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[i].tbs); - return SRSLTE_ERROR; + + for (int cw = 0; cw < SRSLTE_MAX_CODEWORDS; cw++) { + if (grant->tb_en[cw]) { + if (srslte_cbsegm(&cfg->cb_segm[cw], (uint32_t) cfg->grant.mcs[cw].tbs)) { + fprintf(stderr, "Error computing Codeblock (1) segmentation for TBS=%d\n", cfg->grant.mcs[cw].tbs); + return SRSLTE_ERROR; + } } } srslte_ra_dl_grant_to_nbits(&cfg->grant, cfi, cell, sf_idx, cfg->nbits); @@ -447,33 +449,36 @@ int srslte_pdsch_cfg_mimo(srslte_pdsch_cfg_t *cfg, srslte_cell_t cell, srslte_ra /* Check and configure PDSCH transmission modes */ switch(mimo_type) { case SRSLTE_MIMO_TYPE_SINGLE_ANTENNA: - if (grant->nof_tb != 1) { - ERROR("Number of transport blocks is not supported for single transmission mode."); + if (nof_tb != 1) { + ERROR("Wrong number of transport blocks (%d) for single antenna.", nof_tb); return SRSLTE_ERROR; } cfg->nof_layers = 1; break; case SRSLTE_MIMO_TYPE_TX_DIVERSITY: - if (grant->nof_tb != 1) { - ERROR("Number of transport blocks is not supported for transmit diversity mode."); + if (nof_tb != 1) { + ERROR("Wrong number of transport blocks (%d) for transmit diversity.", nof_tb); return SRSLTE_ERROR; } cfg->nof_layers = 2; break; case SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX: - if (grant->nof_tb == 1) { + if (nof_tb == 1) { cfg->codebook_idx = pmi; cfg->nof_layers = 1; - } else { + } else if (nof_tb == 2) { cfg->codebook_idx = pmi + 1; cfg->nof_layers = 2; + } else { + ERROR("Wrong number of transport blocks (%d) for spatial multiplexing.", nof_tb); + return SRSLTE_ERROR; } INFO("PDSCH configured for Spatial Multiplex; nof_codewords=%d; nof_layers=%d; codebook_idx=%d;\n", - grant->nof_tb, cfg->nof_layers, cfg->codebook_idx); + nof_tb, cfg->nof_layers, cfg->codebook_idx); break; case SRSLTE_MIMO_TYPE_CDD: - if (grant->nof_tb != 2) { - ERROR("Number of transport blocks (%d) is not supported for CDD transmission mode.", grant->nof_tb); + if (nof_tb != 2) { + ERROR("Wrong number of transport blocks (%d) for CDD.", nof_tb); return SRSLTE_ERROR; } cfg->nof_layers = 2; @@ -585,9 +590,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, data != NULL && cfg != NULL) { + uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant); INFO("Decoding PDSCH SF: %d, RNTI: 0x%x, NofSymbols: %d, C_prb=%d, mimo_type=%d, nof_layers=%d, nof_tb=%d\n", - cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, cfg->grant.nof_tb); + cfg->sf_idx, rnti, cfg->nbits[0].nof_re, cfg->grant.nof_prb, cfg->nof_layers, nof_tb); // Extract Symbols and Channel Estimates for (int j=0;jnof_rx_antennas;j++) { @@ -608,10 +614,10 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, // Prepare layers int nof_symbols [SRSLTE_MAX_CODEWORDS]; - nof_symbols[0] = cfg->nbits[0].nof_re * cfg->grant.nof_tb / cfg->nof_layers; - nof_symbols[1] = cfg->nbits[1].nof_re * cfg->grant.nof_tb / cfg->nof_layers; + nof_symbols[0] = cfg->nbits[0].nof_re * nof_tb / cfg->nof_layers; + nof_symbols[1] = cfg->nbits[1].nof_re * nof_tb / cfg->nof_layers; - if (cfg->nof_layers == cfg->grant.nof_tb) { + if (cfg->nof_layers == nof_tb) { /* Skip layer demap */ for (i = 0; i < cfg->nof_layers; i++) { x[i] = q->d[i]; @@ -629,15 +635,17 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, cfg->codebook_idx, cfg->nbits[0].nof_re, cfg->mimo_type, noise_estimate); // Layer demapping only if necessary - if (cfg->nof_layers != cfg->grant.nof_tb) { - srslte_layerdemap_type(x, q->d, cfg->nof_layers, cfg->grant.nof_tb, + if (cfg->nof_layers != nof_tb) { + srslte_layerdemap_type(x, q->d, cfg->nof_layers, nof_tb, nof_symbols[0], nof_symbols, cfg->mimo_type); } // Codeword decoding - for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) { - int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb); - acks[tb] = (ret == SRSLTE_SUCCESS); + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) { + if (cfg->grant.tb_en[tb]) { + int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb); + acks[tb] = (ret == SRSLTE_SUCCESS); + } } pdsch_decode_debug(q, cfg, sf_symbols, ce); @@ -689,6 +697,8 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, if (q != NULL && cfg != NULL) { + uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant); + for (i = 0; i < q->cell.nof_ports; i++) { if (sf_symbols[i] == NULL) { @@ -708,15 +718,17 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, return SRSLTE_ERROR_INVALID_INPUTS; } - for (uint32_t tb = 0; tb < cfg->grant.nof_tb; tb ++) { - ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb); + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) { + if (cfg->grant.tb_en[tb]) { + ret |= srslte_pdsch_codeword_encode(q, cfg, softbuffers[tb], rnti, data[tb], tb); + } } // Layer mapping & precode if necessary if (q->cell.nof_ports > 1) { int nof_symbols; /* If number of layers is equal to transport blocks (codewords) skip layer mapping */ - if (cfg->nof_layers == cfg->grant.nof_tb) { + if (cfg->nof_layers == nof_tb) { for (i = 0; i < cfg->nof_layers; i++) { x[i] = q->d[i]; } @@ -728,7 +740,7 @@ int srslte_pdsch_encode(srslte_pdsch_t *q, } memset(&x[cfg->nof_layers], 0, sizeof(cf_t *) * (SRSLTE_MAX_LAYERS - cfg->nof_layers)); - nof_symbols = srslte_layermap_type(q->d, x, cfg->grant.nof_tb, cfg->nof_layers, + nof_symbols = srslte_layermap_type(q->d, x, nof_tb, cfg->nof_layers, (int[SRSLTE_MAX_CODEWORDS]) {cfg->nbits[0].nof_re, cfg->nbits[1].nof_re}, cfg->mimo_type); } diff --git a/lib/src/phy/phch/ra.c b/lib/src/phy/phch/ra.c index 00713e6c1..b85d2ea2f 100644 --- a/lib/src/phy/phch/ra.c +++ b/lib/src/phy/phch/ra.c @@ -521,11 +521,10 @@ static int dl_dci_to_grant_mcs(srslte_ra_dl_dci_t *dci, srslte_ra_dl_grant_t *gr grant->mcs[1].tbs = 0; } } - grant->nof_tb = 0; for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + grant->tb_en[tb] = dci->tb_en[tb]; if (dci->tb_en[tb]) { grant->Qm[tb] = srslte_mod_bits_x_symbol(grant->mcs[tb].mod); - grant->nof_tb++; } } grant->pinfo = dci->pinfo; @@ -541,12 +540,14 @@ void srslte_ra_dl_grant_to_nbits(srslte_ra_dl_grant_t *grant, uint32_t cfi, srsl srslte_ra_nbits_t nbits [SRSLTE_MAX_CODEWORDS]) { // Compute number of RE - for (int i = 0; i < grant->nof_tb; i++) { - /* Compute number of RE for first transport block */ - nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi); - nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi; - nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart; - nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i]; + for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (grant->tb_en[i]) { + /* Compute number of RE for first transport block */ + nbits[i].nof_re = srslte_ra_dl_grant_nof_re(grant, cell, sf_idx, cell.nof_prb < 10 ? (cfi + 1) : cfi); + nbits[i].lstart = cell.nof_prb < 10 ? (cfi + 1) : cfi; + nbits[i].nof_symb = 2 * SRSLTE_CP_NSYMB(cell.cp) - nbits[0].lstart; + nbits[i].nof_bits = nbits[i].nof_re * grant->Qm[i]; + } } } @@ -820,11 +821,13 @@ void srslte_ra_pdsch_fprint(FILE *f, srslte_ra_dl_dci_t *dci, uint32_t nof_prb) void srslte_ra_dl_grant_fprint(FILE *f, srslte_ra_dl_grant_t *grant) { srslte_ra_prb_fprint(f, grant); fprintf(f, " - Number of PRBs:\t\t\t%d\n", grant->nof_prb); - fprintf(f, " - Number of TBs:\t\t\t%d\n", grant->nof_tb); - for (int i = 0; i < grant->nof_tb; i++) { - fprintf(f, " - Transport block:\t\t\t%d\n", i); - fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod)); - fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs); + fprintf(f, " - Number of TBs:\t\t\t%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant)); + for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (grant->tb_en[i]) { + fprintf(f, " - Transport block:\t\t\t%d\n", i); + fprintf(f, " -> Modulation type:\t\t\t%s\n", srslte_mod_string(grant->mcs[i].mod)); + fprintf(f, " -> Transport block size:\t\t%d\n", grant->mcs[i].tbs); + } } } diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index e0002429e..72ee50ee9 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -524,7 +524,7 @@ int srslte_dlsch_decode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu int16_t *e_bits, uint8_t *data, int codeword_idx) { uint32_t Nl = 1; - if (cfg->nof_layers != cfg->grant.nof_tb) { + if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } @@ -553,7 +553,7 @@ int srslte_dlsch_encode2(srslte_sch_t *q, srslte_pdsch_cfg_t *cfg, srslte_softbu uint8_t *data, uint8_t *e_bits, int codeword_idx) { uint32_t Nl = 1; - if (cfg->nof_layers != cfg->grant.nof_tb) { + if (cfg->nof_layers != SRSLTE_RA_DL_GRANT_NOF_TB(&cfg->grant)) { Nl = 2; } diff --git a/lib/src/phy/phch/test/pdsch_test.c b/lib/src/phy/phch/test/pdsch_test.c index b98d75c22..ae0bff64e 100644 --- a/lib/src/phy/phch/test/pdsch_test.c +++ b/lib/src/phy/phch/test/pdsch_test.c @@ -257,8 +257,8 @@ int main(int argc, char **argv) { } - for (int i = 0; i < grant.nof_tb; i++) { - if (grant.mcs[i].tbs) { + for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (grant.tb_en[i]) { data_tx[i] = srslte_vec_malloc(sizeof(uint8_t) * grant.mcs[i].tbs); if (!data_tx[i]) { perror("srslte_vec_malloc"); @@ -303,12 +303,11 @@ int main(int argc, char **argv) { INFO(" cp=%s\n", srslte_cp_string(cell.cp)); INFO(" phich_length=%d\n", (int) cell.phich_length); INFO(" phich_resources=%d\n", (int) cell.phich_resources); - INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb); INFO(" nof_prb=%d\n", pdsch_cfg.grant.nof_prb); INFO(" sf_idx=%d\n", pdsch_cfg.sf_idx); INFO(" mimo_type=%s\n", srslte_mimotype2str(pdsch_cfg.mimo_type)); INFO(" nof_layers=%d\n", pdsch_cfg.nof_layers); - INFO(" nof_tb=%d\n", pdsch_cfg.grant.nof_tb); + INFO(" nof_tb=%d\n", SRSLTE_RA_DL_GRANT_NOF_TB(&pdsch_cfg.grant)); for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { INFO(" Tranport block index %d:\n", i); INFO(" Qm=%d\n", pdsch_cfg.grant.Qm[i]); @@ -372,9 +371,11 @@ int main(int argc, char **argv) { } } - for (int tb = 0; tb < grant.nof_tb; tb++) { - for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { - data_tx[tb][byte] = (uint8_t)(rand() % 256); + for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (grant.tb_en[tb]) { + for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { + data_tx[tb][byte] = (uint8_t) (rand() % 256); + } } } @@ -444,8 +445,8 @@ int main(int argc, char **argv) { srslte_ofdm_rx_sf(&ofdm_rx, tx_sf_symbols[i], rx_slot_symbols[i]); } #endif - for (i = 0; i < grant.nof_tb; i++) { - if (grant.mcs[i].tbs) { + for (i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (grant.tb_en[i]) { srslte_softbuffer_rx_reset_tbs(softbuffers_rx[i], (uint32_t) grant.mcs[i].tbs); } } @@ -464,19 +465,23 @@ int main(int argc, char **argv) { } /* Check Tx and Rx bytes */ - for (int tb = 0; tb < grant.nof_tb; tb++) { - for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { - if (data_tx[tb][byte] != data_rx[tb][byte]) { - ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]); - ret = SRSLTE_ERROR; - goto quit; + for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (grant.tb_en[tb]) { + for (int byte = 0; byte < grant.mcs[tb].tbs / 8; byte++) { + if (data_tx[tb][byte] != data_rx[tb][byte]) { + ERROR("Found BYTE error in TB %d (%02X != %02X), quiting...", tb, data_tx[tb][byte], data_rx[tb][byte]); + ret = SRSLTE_ERROR; + goto quit; + } } } } /* Check all transport blocks have been decoded OK */ - for (int tb = 0; tb < grant.nof_tb; tb++) { - ret |= (acks[tb]) ? SRSLTE_SUCCESS : SRSLTE_ERROR; + for (int tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (grant.tb_en[tb]) { + ret |= (acks[tb]) ? SRSLTE_SUCCESS : SRSLTE_ERROR; + } } ret = SRSLTE_SUCCESS; diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index 888b0d9b3..a67538ff7 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -280,21 +280,22 @@ int srslte_ue_dl_decode_estimate(srslte_ue_dl_t *q, uint32_t sf_idx, uint32_t *c int srslte_ue_dl_cfg_grant(srslte_ue_dl_t *q, srslte_ra_dl_grant_t *grant, uint32_t cfi, uint32_t sf_idx, int rvidx[SRSLTE_MAX_CODEWORDS], srslte_mimo_type_t mimo_type) { uint32_t pmi = 0; + uint32_t nof_tb = SRSLTE_RA_DL_GRANT_NOF_TB(grant); /* Translates Precoding Information (pinfo) to Precoding matrix Index (pmi) as 3GPP 36.212 Table 5.3.3.1.5-4 */ if (mimo_type == SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX) { - if (grant->nof_tb == 1) { + if (nof_tb == 1) { if (grant->pinfo > 0 && grant->pinfo < 5) { pmi = grant->pinfo - 1; } else { - ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, grant->pinfo); + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); return SRSLTE_ERROR; } } else { if (grant->pinfo < 2) { pmi = grant->pinfo; } else { - ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", q->pdsch_cfg.grant.nof_tb, grant->pinfo); + ERROR("Not Implemented (nof_tb=%d, pinfo=%d)", nof_tb, grant->pinfo); return SRSLTE_ERROR; } } @@ -336,29 +337,33 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], /* ===== These lines of code are supposed to be MAC functionality === */ - + int rvidx[SRSLTE_MAX_CODEWORDS] = {1}; if (dci_unpacked.rv_idx < 0) { - uint32_t sfn = tti/10; - uint32_t k = (sfn/2)%4; - for (int i = 0; i < grant.nof_tb; i++) { - rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4; - srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs); + uint32_t sfn = tti / 10; + uint32_t k = (sfn / 2) % 4; + for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (grant.tb_en[i]) { + rvidx[i] = ((uint32_t) ceilf((float) 1.5 * k)) % 4; + srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs); + } } } else { - for (int i = 0; i < grant.nof_tb; i++) { - switch(i) { - case 0: - rvidx[i] = (uint32_t) dci_unpacked.rv_idx; - break; - case 1: - rvidx[i] = (uint32_t) dci_unpacked.rv_idx_1; - break; - default: - ERROR("Wrong number of transport blocks"); - return SRSLTE_ERROR; + for (int i = 0; i < SRSLTE_MAX_CODEWORDS; i++) { + if (grant.tb_en[i]) { + switch (i) { + case 0: + rvidx[i] = (uint32_t) dci_unpacked.rv_idx; + break; + case 1: + rvidx[i] = (uint32_t) dci_unpacked.rv_idx_1; + break; + default: + ERROR("Wrong number of transport blocks"); + return SRSLTE_ERROR; + } + srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs); } - srslte_softbuffer_rx_reset_tbs(q->softbuffers[i], (uint32_t) grant.mcs[i].tbs); } } @@ -372,14 +377,14 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], } break; case SRSLTE_DCI_FORMAT2: - if (grant.nof_tb == 1 && dci_unpacked.pinfo == 0) { + if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) { mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; } else { mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; } break; case SRSLTE_DCI_FORMAT2A: - if (grant.nof_tb == 1 && dci_unpacked.pinfo == 0) { + if (SRSLTE_RA_DL_GRANT_NOF_TB(&grant) == 1 && dci_unpacked.pinfo == 0) { mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; } else { mimo_type = SRSLTE_MIMO_TYPE_CDD; @@ -413,11 +418,13 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], noise_estimate, rnti, data, acks); - for (int tb = 0; tb < q->pdsch_cfg.grant.nof_tb; tb++) { - if (!acks[tb]) { - q->pkt_errors++; + for (int tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (grant.tb_en[tb]) { + if (!acks[tb]) { + q->pkt_errors++; + } + q->pkts_total++; } - q->pkts_total++; } if (ret == SRSLTE_ERROR) { diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index 963551150..a9949cc3a 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -166,8 +166,10 @@ private: } void new_grant_dl(Tgrant grant, Taction *action) { - for (uint32_t tb = 0; tb < grant.phy_grant.dl.nof_tb; tb++) { - subproc[tb].new_grant_dl(grant, action); + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (grant.tb_en[tb]) { + subproc[tb].new_grant_dl(grant, action); + } } } diff --git a/srsue/hdr/phy/phch_worker.h b/srsue/hdr/phy/phch_worker.h index 7b196f948..145f70e46 100644 --- a/srsue/hdr/phy/phch_worker.h +++ b/srsue/hdr/phy/phch_worker.h @@ -95,7 +95,7 @@ private: void set_uci_sr(); void set_uci_periodic_cqi(); void set_uci_aperiodic_cqi(); - void set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb); + void set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS]); bool srs_is_ready_to_send(); float set_power(float tx_power); void setup_tx_gain(); diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 53dc232dc..8f9726a46 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -218,15 +218,17 @@ void phch_worker::work_imp() if (dl_action.generate_ack_callback && dl_action.decode_enabled) { // NOTE: Currently hard-coded to 1st TB only - for (uint32_t tb = 0; tb < 1; tb++) { - phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid); - dl_ack[tb] = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg); - Debug("Calling generate ACK callback for TB %d returned=%d\n", tb, dl_ack[tb]); + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (dl_mac_grant.tb_en[tb]) { + phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid); + dl_ack[tb] = dl_action.generate_ack_callback(dl_action.generate_ack_callback_arg); + Debug("Calling generate ACK callback for TB %d returned=%d\n", tb, dl_ack[tb]); + } } } Debug("dl_ack={%d, %d}, generate_ack=%d\n", dl_ack[0], dl_ack[1], dl_action.generate_ack); if (dl_action.generate_ack) { - set_uci_ack(dl_ack, dl_mac_grant.phy_grant.dl.nof_tb); + set_uci_ack(dl_ack, dl_mac_grant.tb_en); } } } @@ -292,8 +294,10 @@ void phch_worker::work_imp() if (dl_mac_grant.rnti_type == SRSLTE_RNTI_PCH) { phy->mac->pch_decoded_ok(dl_mac_grant.n_bytes[0]); } else { - for (uint32_t tb = 0; tb < dl_mac_grant.phy_grant.dl.nof_tb; tb++) { - phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid); + for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { + if (dl_mac_grant.tb_en[tb]) { + phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid); + } } } } @@ -405,7 +409,15 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) grant->rnti = dl_rnti; grant->rnti_type = type; grant->last_tti = 0; - + grant->tb_en[0] = dci_unpacked.tb_en[0]; + grant->tb_en[1] = dci_unpacked.tb_en[1]; + grant->tb_cw_swap = dci_unpacked.tb_cw_swap; + + if (grant->tb_cw_swap) { + Info("tb_cw_swap = true\n"); + printf("tb_cw_swap = true\n"); + } + last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl); char hexstr[16]; @@ -432,8 +444,8 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL srslte_mimo_type_t mimo_type = SRSLTE_MIMO_TYPE_SINGLE_ANTENNA; int ret = SRSLTE_SUCCESS; - for (uint32_t tb = 0; tb < grant->nof_tb; tb++) { - if (rv[tb] < 0 || rv[tb] > 3) { + for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb++) { + if (grant->tb_en[tb] && (rv[tb] < 0 || rv[tb] > 3)) { valid_config = false; Error("Wrong RV (%d) for TB index %d", rv[tb], tb); } @@ -452,22 +464,22 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL } break; case LIBLTE_RRC_TRANSMISSION_MODE_3: - if (grant->nof_tb == 1) { + if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) { mimo_type = SRSLTE_MIMO_TYPE_TX_DIVERSITY; - } else if (grant->nof_tb == 2) { + } else if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) { mimo_type = SRSLTE_MIMO_TYPE_CDD; } else { - Error("Wrong number of transport blocks (%d) for TM3\n", grant->nof_tb); + Error("Wrong number of transport blocks (%d) for TM3\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant)); valid_config = false; } break; case LIBLTE_RRC_TRANSMISSION_MODE_4: - if (grant->nof_tb == 1) { + if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 1) { mimo_type = (grant->pinfo == 0) ? SRSLTE_MIMO_TYPE_TX_DIVERSITY : SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; - } else if (grant->nof_tb == 2) { + } else if (SRSLTE_RA_DL_GRANT_NOF_TB(grant) == 2) { mimo_type = SRSLTE_MIMO_TYPE_SPATIAL_MULTIPLEX; } else { - Error("Wrong number of transport blocks (%d) for TM4\n", grant->nof_tb); + Error("Wrong number of transport blocks (%d) for TM4\n", SRSLTE_RA_DL_GRANT_NOF_TB(grant)); valid_config = false; } break; @@ -521,13 +533,14 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL snprintf(timestr, 64, ", dec_time=%4d us", (int) t[0].tv_usec); #endif - Info("PDSCH: l_crb=%2d, harq=%d, nof_tb=%d, tbs={%d, %d}, mcs={%d, %d}, rv={%d, %d}, crc={%s, %s}, snr=%.1f dB, n_iter=%d%s\n", - grant->nof_prb, harq_pid, - grant->nof_tb, grant->mcs[0].tbs / 8, grant->mcs[1].tbs / 8, grant->mcs[0].idx, grant->mcs[1].idx, - rv[0], rv[1], acks[0] ? "OK" : "KO", acks[1] ? "OK" : "KO", - 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), - srslte_pdsch_last_noi(&ue_dl.pdsch), - timestr); + Info( + "PDSCH: l_crb=%2d, harq=%d, tb_en={%s, %s}, tbs={%d, %d}, mcs={%d, %d}, rv={%d, %d}, crc={%s, %s}, snr=%.1f dB, n_iter=%d%s\n", + grant->nof_prb, harq_pid, grant->tb_en[0] ? "on" : "off", grant->tb_en[1] ? "on" : "off", + grant->mcs[0].tbs / 8, grant->mcs[1].tbs / 8, grant->mcs[0].idx, + grant->mcs[1].idx, rv[0], rv[1], acks[0] ? "OK" : "KO", acks[1] ? "OK" : "KO", + 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), + srslte_pdsch_last_noi(&ue_dl.pdsch), + timestr); //printf("tti=%d, cfo=%f\n", tti, cfo*15000); //srslte_vec_save_file("pdsch", signal_buffer, sizeof(cf_t)*SRSLTE_SF_LEN_PRB(cell.nof_prb)); @@ -660,23 +673,23 @@ void phch_worker::reset_uci() bzero(&uci_data, sizeof(srslte_uci_data_t)); } - void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], uint32_t nof_tb) { - if (nof_tb > 0) { - uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0); - } - - if (nof_tb > 1) { - uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0); - } - - if (nof_tb > 2) { - Error("Number of transport blocks is not supported"); - } - - uci_data.uci_ack_len = nof_tb; - +void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_MAX_CODEWORDS]) +{ + uint32_t nof_tb = 0; + if (tb_en[0]) { + uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0); + nof_tb++; } + if (tb_en[1]) { + uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0); + nof_tb++; + } + + uci_data.uci_ack_len = nof_tb; + +} + void phch_worker::set_uci_sr() { uci_data.scheduling_request = false; From a8224e8caeca60c5e100cdc43a55c72a00a026f0 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 5 Sep 2017 17:50:20 +0200 Subject: [PATCH 02/10] Removed redundant condition --- srsue/hdr/mac/dl_harq.h | 24 +++++++++++------------- 1 file changed, 11 insertions(+), 13 deletions(-) diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index a9949cc3a..eecf14401 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -297,20 +297,18 @@ private: harq_entity->pcap->write_dl_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid], cur_grant.rnti, ack, cur_grant.tti); } - if (ack) { - if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) { - Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", - cur_grant.n_bytes[tid]); - harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]); - } else { - Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]); - harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], - cur_grant.tti); + if (cur_grant.rnti_type == SRSLTE_RNTI_TEMP) { + Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit (Temporal C-RNTI)\n", + cur_grant.n_bytes[tid]); + harq_entity->demux_unit->push_pdu_temp_crnti(payload_buffer_ptr, cur_grant.n_bytes[tid]); + } else { + Debug("Delivering PDU=%d bytes to Dissassemble and Demux unit\n", cur_grant.n_bytes[tid]); + harq_entity->demux_unit->push_pdu(pid * SRSLTE_MAX_TB + tid, payload_buffer_ptr, cur_grant.n_bytes[tid], + cur_grant.tti); - // Compute average number of retransmissions per packet - harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, - harq_entity->nof_pkts++); - } + // Compute average number of retransmissions per packet + harq_entity->average_retx = SRSLTE_VEC_CMA((float) n_retx, harq_entity->average_retx, + harq_entity->nof_pkts++); } } } else { From 224a54a315e550efbf12eff6e0a68e7664d7ef2d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 5 Sep 2017 17:51:56 +0200 Subject: [PATCH 03/10] Solved bug for plotting srsue contellation and removed trace of tb_cw_swap --- srsue/src/phy/phch_worker.cc | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 8f9726a46..9fd37251c 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -411,12 +411,7 @@ bool phch_worker::decode_pdcch_dl(srsue::mac_interface_phy::mac_grant_t* grant) grant->last_tti = 0; grant->tb_en[0] = dci_unpacked.tb_en[0]; grant->tb_en[1] = dci_unpacked.tb_en[1]; - grant->tb_cw_swap = dci_unpacked.tb_cw_swap; - - if (grant->tb_cw_swap) { - Info("tb_cw_swap = true\n"); - printf("tb_cw_swap = true\n"); - } + grant->tb_cw_swap = dci_unpacked.tb_cw_swap; // FIXME: tb_cw_swap not supported last_dl_pdcch_ncce = srslte_ue_dl_get_ncce(&ue_dl); @@ -1056,7 +1051,7 @@ int phch_worker::read_ce_abs(float *ce_abs) { bzero(ce_abs, sizeof(float)*sz); int g = (sz - 12*cell.nof_prb)/2; for (i = 0; i < 12*cell.nof_prb; i++) { - ce_abs[g+i] = 20 * log10(cabs(ue_dl.ce[0][i])); + ce_abs[g+i] = 20 * log10f(cabsf(ue_dl.ce_m[0][0][i])); if (isinf(ce_abs[g+i])) { ce_abs[g+i] = -80; } @@ -1067,7 +1062,7 @@ int phch_worker::read_ce_abs(float *ce_abs) { int phch_worker::read_pdsch_d(cf_t* pdsch_d) { - memcpy(pdsch_d, ue_dl.pdsch.d, ue_dl.pdsch_cfg.nbits[0].nof_re*sizeof(cf_t)); + memcpy(pdsch_d, ue_dl.pdsch.d[0], ue_dl.pdsch_cfg.nbits[0].nof_re*sizeof(cf_t)); return ue_dl.pdsch_cfg.nbits[0].nof_re; } From 37754f992c8579e5bc26dd392bf5641b62c70040 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 6 Sep 2017 14:45:34 +0200 Subject: [PATCH 04/10] Removed bug in dl_harq for multiple TB --- srsue/hdr/mac/dl_harq.h | 14 ++++++++------ 1 file changed, 8 insertions(+), 6 deletions(-) diff --git a/srsue/hdr/mac/dl_harq.h b/srsue/hdr/mac/dl_harq.h index eecf14401..dec16086b 100644 --- a/srsue/hdr/mac/dl_harq.h +++ b/srsue/hdr/mac/dl_harq.h @@ -166,6 +166,13 @@ private: } void new_grant_dl(Tgrant grant, Taction *action) { + /* Fill action structure */ + bzero(action, sizeof(Taction)); + action->default_ack = false; + action->generate_ack = true; + action->decode_enabled = false; + + /* For each subprocess... */ for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { if (grant.tb_en[tb]) { subproc[tb].new_grant_dl(grant, action); @@ -237,12 +244,6 @@ private: grant.last_tti = cur_grant.tti; memcpy(&cur_grant, &grant, sizeof(Tgrant)); - // Fill action structure - bzero(action, sizeof(Taction)); - action->default_ack = ack; - action->generate_ack = true; - action->decode_enabled = false; - // If data has not yet been successfully decoded if (!ack) { @@ -264,6 +265,7 @@ private: } else { Warning("DL PID %d: Received duplicate TB. Discarting and retransmitting ACK\n", pid); + action->phy_grant.dl.tb_en[tid] = false; } if (pid == HARQ_BCCH_PID || harq_entity->timers_db->get(TIME_ALIGNMENT)->is_expired()) { From 1ab106c127f2dc2c7f3c5f20bb9b51c07e69c4e1 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Wed, 6 Sep 2017 15:25:12 +0200 Subject: [PATCH 05/10] Improved robustness of PDSCH decoder --- lib/src/phy/phch/pdsch.c | 27 +++++++++++++++++++++------ srsue/src/phy/phch_worker.cc | 16 +++++++++------- 2 files changed, 30 insertions(+), 13 deletions(-) diff --git a/lib/src/phy/phch/pdsch.c b/lib/src/phy/phch/pdsch.c index b04b21ea3..fecf50a13 100644 --- a/lib/src/phy/phch/pdsch.c +++ b/lib/src/phy/phch/pdsch.c @@ -537,12 +537,13 @@ static int srslte_pdsch_codeword_encode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_t *cfg, srslte_softbuffer_rx_t *softbuffer, uint16_t rnti, uint8_t *data, - uint32_t codeword_idx) { + uint32_t codeword_idx, bool *ack) { srslte_ra_nbits_t *nbits = &cfg->nbits[codeword_idx]; srslte_ra_mcs_t *mcs = &cfg->grant.mcs[codeword_idx]; uint32_t rv = cfg->rv[codeword_idx]; + int ret = SRSLTE_ERROR_INVALID_INPUTS; - if (nbits->nof_bits) { + if (softbuffer && data && ack) { INFO("Decoding PDSCH SF: %d (TB %d), Mod %s, NofBits: %d, NofSymbols: %d, NofBitsE: %d, rv_idx: %d\n", cfg->sf_idx, codeword_idx, srslte_mod_string(mcs->mod), mcs->tbs, nbits->nof_re, nbits->nof_bits, rv); @@ -566,10 +567,20 @@ static int srslte_pdsch_codeword_decode(srslte_pdsch_t *pdsch, srslte_pdsch_cfg_ srslte_sequence_free(&seq); } - return srslte_dlsch_decode2(&pdsch->dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx); + /* Return */ + ret = srslte_dlsch_decode2(&pdsch->dl_sch, cfg, softbuffer, pdsch->e[codeword_idx], data, codeword_idx); + + if (ret == SRSLTE_SUCCESS) { + *ack = true; + } else if (ret == SRSLTE_ERROR) { + *ack = false; + ret = SRSLTE_SUCCESS; + } + } else { + ERROR("Detected NULL pointer"); } - return SRSLTE_SUCCESS; + return ret; } /** Decodes the PDSCH from the received symbols @@ -643,8 +654,12 @@ int srslte_pdsch_decode(srslte_pdsch_t *q, // Codeword decoding for (uint32_t tb = 0; tb < SRSLTE_MAX_CODEWORDS; tb ++) { if (cfg->grant.tb_en[tb]) { - int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb); - acks[tb] = (ret == SRSLTE_SUCCESS); + int ret = srslte_pdsch_codeword_decode(q, cfg, softbuffers[tb], rnti, data[tb], tb, &acks[tb]); + + /* Check if there has been any execution error */ + if (ret) { + return ret; + } } } diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 9fd37251c..6e77b3a3e 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -216,8 +216,6 @@ void phch_worker::work_imp() dl_mac_grant.pid, dl_ack); } if (dl_action.generate_ack_callback && dl_action.decode_enabled) { - - // NOTE: Currently hard-coded to 1st TB only for (uint32_t tb = 0; tb < SRSLTE_MAX_TB; tb++) { if (dl_mac_grant.tb_en[tb]) { phy->mac->tb_decoded(dl_ack[tb], tb, dl_mac_grant.rnti_type, dl_mac_grant.pid); @@ -520,7 +518,7 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL ret = srslte_pdsch_decode(&ue_dl.pdsch, &ue_dl.pdsch_cfg, softbuffers, ue_dl.sf_symbols_m, ue_dl.ce_m, noise_estimate, rnti, payload, acks); if (ret) { - Error("Decoding PDSCH"); + Error("ERROR: Decoding PDSCH\n"); } #ifdef LOG_EXECTIME gettimeofday(&t[2], NULL); @@ -673,12 +671,14 @@ void phch_worker::set_uci_ack(bool ack[SRSLTE_MAX_CODEWORDS], bool tb_en[SRSLTE_ uint32_t nof_tb = 0; if (tb_en[0]) { uci_data.uci_ack = (uint8_t) ((ack[0]) ? 1 : 0); - nof_tb++; + nof_tb = 1; + } else { + uci_data.uci_ack = 1; } if (tb_en[1]) { uci_data.uci_ack_2 = (uint8_t) ((ack[1]) ? 1 : 0); - nof_tb++; + nof_tb = 2; } uci_data.uci_ack_len = nof_tb; @@ -867,10 +867,12 @@ void phch_worker::encode_pucch() float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len); float gain = set_power(tx_power); - Info("PUCCH: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s, sr=%s, cfo=%.1f Hz%s\n", + Info("PUCCH: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, sr=%s, cfo=%.1f Hz%s\n", tx_power, (tti+4)%10240, last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, - uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no",uci_data.scheduling_request?"yes":"no", + uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", + uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", + uci_data.scheduling_request?"yes":"no", cfo*15000, timestr); } From 6a668ef27fcbc05743cf8a2225ad20b4d06685e7 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 7 Sep 2017 17:46:30 +0200 Subject: [PATCH 06/10] Added PUSCH ACK decoder and test --- lib/include/srslte/phy/phch/uci.h | 3 +- lib/src/phy/phch/sch.c | 5 ++- lib/src/phy/phch/test/pusch_test.c | 15 ++++++-- lib/src/phy/phch/uci.c | 56 +++++++++++++++++++++--------- 4 files changed, 57 insertions(+), 22 deletions(-) diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index bad87866e..c49df67f2 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -130,7 +130,8 @@ SRSLTE_API int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, uint32_t H_prime_total, uint32_t O_cqi, srslte_uci_bit_t *ack_bits, - uint8_t *data); + uint8_t acks[2], + uint32_t nof_acks); SRSLTE_API int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, uint8_t data, diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 72ee50ee9..02ec906ff 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -657,14 +657,17 @@ int srslte_ulsch_uci_decode_ri_ack(srslte_sch_t *q, srslte_pusch_cfg_t *cfg, srs // Deinterleave and decode HARQ bits if (uci_data->uci_ack_len > 0) { + uint8_t acks[2] = {0, 0}; float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack]; if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, &uci_data->uci_ack); + ret = srslte_uci_decode_ack(cfg, q_bits, c_seq, beta, nb_q/Qm, uci_data->uci_cqi_len, q->ack_ri_bits, acks, uci_data->uci_ack_len); if (ret < 0) { return ret; } + uci_data->uci_ack = acks[0]; + uci_data->uci_ack_2 = acks[1]; Q_prime_ack = (uint32_t) ret; // Set zeros to HARQ bits diff --git a/lib/src/phy/phch/test/pusch_test.c b/lib/src/phy/phch/test/pusch_test.c index 0cb2847b7..3434fac72 100644 --- a/lib/src/phy/phch/test/pusch_test.c +++ b/lib/src/phy/phch/test/pusch_test.c @@ -172,14 +172,15 @@ int main(int argc, char **argv) { bzero(&uci_data_tx, sizeof(srslte_uci_data_t)); uci_data_tx.uci_cqi_len = 4; uci_data_tx.uci_ri_len = 0; - uci_data_tx.uci_ack_len = 0; + uci_data_tx.uci_ack_len = 2; memcpy(&uci_data_rx, &uci_data_tx, sizeof(srslte_uci_data_t)); for (uint32_t i=0;i<20;i++) { uci_data_tx.uci_cqi [i] = 1; } - uci_data_tx.uci_ri = 1; - uci_data_tx.uci_ack = 1; + uci_data_tx.uci_ri = 1; + uci_data_tx.uci_ack = 1; + uci_data_tx.uci_ack_2 = 1; uint32_t nof_re = SRSLTE_NRE*cell.nof_prb*2*SRSLTE_CP_NSYMB(cell.cp); sf_symbols = srslte_vec_malloc(sizeof(cf_t) * nof_re); @@ -250,11 +251,19 @@ int main(int argc, char **argv) { if (uci_data_tx.uci_ack_len) { if (uci_data_tx.uci_ack != uci_data_rx.uci_ack) { printf("UCI ACK bit error: %d != %d\n", uci_data_tx.uci_ack, uci_data_rx.uci_ack); + ret = SRSLTE_ERROR; + } + } + if (uci_data_tx.uci_ack_len > 1) { + if (uci_data_tx.uci_ack_2 != uci_data_rx.uci_ack_2) { + printf("UCI ACK 2 bit error: %d != %d\n", uci_data_tx.uci_ack_2, uci_data_rx.uci_ack_2); + ret = SRSLTE_ERROR; } } if (uci_data_tx.uci_ri_len) { if (uci_data_tx.uci_ri != uci_data_rx.uci_ri) { printf("UCI RI bit error: %d != %d\n", uci_data_tx.uci_ri, uci_data_rx.uci_ri); + ret = SRSLTE_ERROR; } } if (uci_data_tx.uci_cqi_len) { diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index 5bf40cc17..cb274bb83 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -545,15 +545,35 @@ static void encode_ri_ack(uint8_t data, srslte_uci_bit_type_t q_encoded_bits[6], } } -static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos) +static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[2], uint32_t nof_data) { - uint32_t p0 = pos[0].position; - uint32_t p1 = pos[1].position; - - uint32_t q0 = c_seq[p0]?q_bits[p0]:-q_bits[p0]; - uint32_t q1 = c_seq[p0]?q_bits[p1]:-q_bits[p1]; + if (nof_data == 1) { + uint32_t p0 = pos[0].position; + uint32_t p1 = pos[1].position; - return -(q0+q1); + int32_t q0 = c_seq[p0] ? q_bits[p0] : -q_bits[p0]; + int32_t q1 = c_seq[p0] ? q_bits[p1] : -q_bits[p1]; + + data[0] -= q0 + q1; + } else { + uint32_t p0 = pos[Qm * 0 + 0].position; + uint32_t p1 = pos[Qm * 0 + 1].position; + uint32_t p2 = pos[Qm * 1 + 6].position; + uint32_t p3 = pos[Qm * 1 + 7].position; + uint32_t p4 = pos[Qm * 2 + 12].position; + uint32_t p5 = pos[Qm * 2 + 13].position; + + int32_t q0 = c_seq[p0] ? q_bits[p0] : -q_bits[p0]; + int32_t q1 = c_seq[p1] ? q_bits[p1] : -q_bits[p1]; + int32_t q2 = c_seq[p2] ? q_bits[p2] : -q_bits[p2]; + int32_t q3 = c_seq[p3] ? q_bits[p3] : -q_bits[p3]; + int32_t q4 = c_seq[p4] ? q_bits[p4] : -q_bits[p4]; + int32_t q5 = c_seq[p5] ? q_bits[p5] : -q_bits[p5]; + + data[0] -= q0 + q3; + data[1] -= q1 + q4; + data[2] -= q2 + q5; + } } @@ -562,25 +582,27 @@ static int32_t decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t * */ int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_seq, float beta, uint32_t H_prime_total, - uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t *data) + uint32_t O_cqi, srslte_uci_bit_t *ack_bits, uint8_t acks[2], uint32_t nof_acks) { - int32_t rx_ack = 0; - + int32_t acks_sum[3] = {0, 0, 0}; + if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); return -1; } - uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); + uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); // Use the same interleaver function to get the HARQ bit position - for (uint32_t i=0;i 1) ? 3 : 1) { uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - rx_ack += (int32_t) decode_ri_ack(q_bits, c_seq, ack_bits); + decode_ri_ack(q_bits, c_seq, ack_bits, cfg->grant.Qm, acks_sum, nof_acks); } - - if (data) { - *data = rx_ack>0; + + if (acks) { + acks[0] = (uint8_t)(acks_sum[0] > 0); + acks[1] = (uint8_t)(acks_sum[1] > 0); + // TODO: Do something with acks_sum[2] } return (int) Qprime; } @@ -629,7 +651,7 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se // Use the same interleaver function to get the HARQ bit position for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); - rx_ri += (int32_t) decode_ri_ack(q_bits, c_seq, ri_bits); + decode_ri_ack(q_bits, c_seq, ri_bits, cfg->grant.Qm, &rx_ri, 1); } if (data) { From c04eadaa6b5c4f08df6d1cd44f1a8db49d702d07 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Thu, 7 Sep 2017 16:30:15 +0200 Subject: [PATCH 07/10] PUSCH supports 2 ACK --- lib/include/srslte/phy/phch/uci.h | 5 +-- lib/src/phy/phch/sch.c | 4 ++- lib/src/phy/phch/uci.c | 54 ++++++++++++++++++++++--------- 3 files changed, 45 insertions(+), 18 deletions(-) diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index c49df67f2..a674e43ea 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -117,8 +117,9 @@ SRSLTE_API int srslte_uci_decode_cqi_pusch(srslte_uci_cqi_pusch_t *q, bool *cqi_ack); SRSLTE_API int srslte_uci_encode_ack(srslte_pusch_cfg_t *cfg, - uint8_t data, - uint32_t O_cqi, + uint8_t acks[2], + uint32_t nof_acks, + uint32_t O_cqi, float beta, uint32_t H_prime_total, srslte_uci_bit_t *ri_bits); diff --git a/lib/src/phy/phch/sch.c b/lib/src/phy/phch/sch.c index 02ec906ff..a44ced2d8 100644 --- a/lib/src/phy/phch/sch.c +++ b/lib/src/phy/phch/sch.c @@ -808,11 +808,13 @@ int srslte_ulsch_uci_encode(srslte_sch_t *q, // Encode (and interleave) ACK if (uci_data.uci_ack_len > 0) { + uint8_t acks [2] = {uci_data.uci_ack, uci_data.uci_ack_2}; float beta = beta_harq_offset[cfg->uci_cfg.I_offset_ack]; if (cfg->cb_segm.tbs == 0) { beta /= beta_cqi_offset[cfg->uci_cfg.I_offset_cqi]; } - ret = srslte_uci_encode_ack(cfg, uci_data.uci_ack, uci_data.uci_cqi_len, beta, nb_q/Qm, &q->ack_ri_bits[Q_prime_ri*Qm]); + ret = srslte_uci_encode_ack(cfg, acks, uci_data.uci_ack_len, uci_data.uci_cqi_len, + beta, nb_q / Qm, &q->ack_ri_bits[Q_prime_ri * Qm]); if (ret < 0) { return ret; } diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index cb274bb83..f649abd1a 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -536,13 +536,35 @@ static uint32_t Q_prime_ri_ack(srslte_pusch_cfg_t *cfg, return Q_prime; } -static void encode_ri_ack(uint8_t data, srslte_uci_bit_type_t q_encoded_bits[6], uint8_t Qm) +static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit_type_t q_encoded_bits[18], uint8_t Qm) { - q_encoded_bits[0] = data?UCI_BIT_1:UCI_BIT_0; - q_encoded_bits[1] = UCI_BIT_REPETITION; - for (uint32_t i=2;igrant.Qm); + uint32_t nof_encoded_bits = encode_ri_ack(acks, nof_acks, q_encoded_bits, cfg->grant.Qm); for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - uci_ulsch_interleave_put(q_encoded_bits, cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]); + uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ack_bits[cfg->grant.Qm*i]); } return (int) Qprime; @@ -666,22 +688,24 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se * Currently only supporting 1-bit RI */ int srslte_uci_encode_ri(srslte_pusch_cfg_t *cfg, - uint8_t data, + uint8_t ri, uint32_t O_cqi, float beta, uint32_t H_prime_total, srslte_uci_bit_t *ri_bits) { + // FIXME: It supports RI of 1 bit only + uint8_t data[2] = {ri, 0}; if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); return -1; } uint32_t Qprime = Q_prime_ri_ack(cfg, 1, O_cqi, beta); - srslte_uci_bit_type_t q_encoded_bits[6]; + srslte_uci_bit_type_t q_encoded_bits[18]; - encode_ri_ack(data, q_encoded_bits, cfg->grant.Qm); + uint32_t nof_encoded_bits = encode_ri_ack(data, 1, q_encoded_bits, cfg->grant.Qm); for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); - uci_ulsch_interleave_put(q_encoded_bits, cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]); + uci_ulsch_interleave_put(&q_encoded_bits[(i*cfg->grant.Qm)%nof_encoded_bits], cfg->grant.Qm, &ri_bits[cfg->grant.Qm*i]); } return (int) Qprime; From 9e4528007cbad2be6eae68dfeb0214fd9406434f Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 8 Sep 2017 10:41:52 +0200 Subject: [PATCH 08/10] Improved ACK and RI in PUSCH decoding --- lib/src/phy/phch/uci.c | 56 +++++++++++++++++++----------------------- 1 file changed, 25 insertions(+), 31 deletions(-) diff --git a/lib/src/phy/phch/uci.c b/lib/src/phy/phch/uci.c index f649abd1a..42d3e6ef2 100644 --- a/lib/src/phy/phch/uci.c +++ b/lib/src/phy/phch/uci.c @@ -567,35 +567,25 @@ static uint32_t encode_ri_ack(uint8_t data[2], uint32_t data_len, srslte_uci_bit return i; } -static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[2], uint32_t nof_data) +static void decode_ri_ack(int16_t *q_bits, uint8_t *c_seq, srslte_uci_bit_t *pos, uint32_t Qm, int32_t data[3]) { - if (nof_data == 1) { - uint32_t p0 = pos[0].position; - uint32_t p1 = pos[1].position; + uint32_t p0 = pos[Qm * 0 + 0].position; + uint32_t p1 = pos[Qm * 0 + 1].position; + uint32_t p2 = pos[Qm * 1 + 0].position; + uint32_t p3 = pos[Qm * 1 + 1].position; + uint32_t p4 = pos[Qm * 2 + 0].position; + uint32_t p5 = pos[Qm * 2 + 1].position; - int32_t q0 = c_seq[p0] ? q_bits[p0] : -q_bits[p0]; - int32_t q1 = c_seq[p0] ? q_bits[p1] : -q_bits[p1]; + int32_t q0 = c_seq[p0] ? q_bits[p0] : -q_bits[p0]; + int32_t q1 = c_seq[p1] ? q_bits[p1] : -q_bits[p1]; + int32_t q2 = c_seq[p2] ? q_bits[p2] : -q_bits[p2]; + int32_t q3 = c_seq[p3] ? q_bits[p3] : -q_bits[p3]; + int32_t q4 = c_seq[p4] ? q_bits[p4] : -q_bits[p4]; + int32_t q5 = c_seq[p5] ? q_bits[p5] : -q_bits[p5]; - data[0] -= q0 + q1; - } else { - uint32_t p0 = pos[Qm * 0 + 0].position; - uint32_t p1 = pos[Qm * 0 + 1].position; - uint32_t p2 = pos[Qm * 1 + 6].position; - uint32_t p3 = pos[Qm * 1 + 7].position; - uint32_t p4 = pos[Qm * 2 + 12].position; - uint32_t p5 = pos[Qm * 2 + 13].position; - - int32_t q0 = c_seq[p0] ? q_bits[p0] : -q_bits[p0]; - int32_t q1 = c_seq[p1] ? q_bits[p1] : -q_bits[p1]; - int32_t q2 = c_seq[p2] ? q_bits[p2] : -q_bits[p2]; - int32_t q3 = c_seq[p3] ? q_bits[p3] : -q_bits[p3]; - int32_t q4 = c_seq[p4] ? q_bits[p4] : -q_bits[p4]; - int32_t q5 = c_seq[p5] ? q_bits[p5] : -q_bits[p5]; - - data[0] -= q0 + q3; - data[1] -= q1 + q4; - data[2] -= q2 + q5; - } + data[0] -= q0 + q3; + data[1] -= q1 + q4; + data[2] -= q2 + q5; } @@ -616,9 +606,11 @@ int srslte_uci_decode_ack(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_s uint32_t Qprime = Q_prime_ri_ack(cfg, nof_acks, O_cqi, beta); // Use the same interleaver function to get the HARQ bit position - for (uint32_t i = 0; i < Qprime; i += (nof_acks > 1) ? 3 : 1) { + for (uint32_t i = 0; i < Qprime; i++) { uci_ulsch_interleave_ack_gen(i, cfg->grant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ack_bits[cfg->grant.Qm*i]); - decode_ri_ack(q_bits, c_seq, ack_bits, cfg->grant.Qm, acks_sum, nof_acks); + if ((i % 3 == 0) && i > 0) { + decode_ri_ack(q_bits, &c_seq[0], &ack_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, acks_sum); + } } if (acks) { @@ -661,7 +653,7 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se float beta, uint32_t H_prime_total, uint32_t O_cqi, srslte_uci_bit_t *ri_bits, uint8_t *data) { - int32_t rx_ri = 0; + int32_t ri_sum[3] = {0, 0, 0}; if (beta < 0) { fprintf(stderr, "Error beta is reserved\n"); @@ -673,11 +665,13 @@ int srslte_uci_decode_ri(srslte_pusch_cfg_t *cfg, int16_t *q_bits, uint8_t *c_se // Use the same interleaver function to get the HARQ bit position for (uint32_t i=0;igrant.Qm, H_prime_total, cfg->nbits.nof_symb, cfg->cp, &ri_bits[cfg->grant.Qm*i]); - decode_ri_ack(q_bits, c_seq, ri_bits, cfg->grant.Qm, &rx_ri, 1); + if ((i % 3 == 0) && i > 0) { + decode_ri_ack(q_bits, &c_seq[0], &ri_bits[cfg->grant.Qm*(i-3)], cfg->grant.Qm, ri_sum); + } } if (data) { - *data = rx_ri>0; + *data = (uint8_t) ((ri_sum[0] + ri_sum[1] + ri_sum[2]) > 0); } return (int) Qprime; From 52bdd9290d39074b9db9eb40cd78924d4241185a Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 8 Sep 2017 11:36:43 +0200 Subject: [PATCH 09/10] Added RI reporting for TM3 and TM4 (no PMI) --- lib/include/srslte/phy/ue/ue_dl.h | 2 +- lib/src/phy/ue/ue_dl.c | 4 ++-- srsue/src/phy/phch_worker.cc | 17 +++++++++++++---- 3 files changed, 16 insertions(+), 7 deletions(-) diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index d0723fae7..0f8b25ece 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -187,7 +187,7 @@ SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, float *current_sinr); SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, - uint32_t *ri, + uint8_t *ri, float *cn); SRSLTE_API bool srslte_ue_dl_decode_phich(srslte_ue_dl_t *q, diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index a67538ff7..dc88685b6 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -516,7 +516,7 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, f /* Compute the Rank Indicator (RI) by computing the condition number, valid for TM3 */ -int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint32_t *ri, float *cn) { +int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint8_t *ri, float *cn) { float _cn; int ret = srslte_pdsch_cn_compute(&q->pdsch, q->ce_m, SRSLTE_SF_LEN_RE(q->cell.nof_prb, q->cell.cp), &_cn); @@ -527,7 +527,7 @@ int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, uint32_t *ri, float *cn) { /* Set rank indicator */ if (!ret && ri) { - *ri = (_cn > 3.0f)? 1:0; + *ri = (uint8_t)((_cn < 17.0f)? 1:0); } return ret; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index 6e77b3a3e..e2c181c98 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -228,6 +228,14 @@ void phch_worker::work_imp() if (dl_action.generate_ack) { set_uci_ack(dl_ack, dl_mac_grant.tb_en); } + + /* Select Rank Indicator by computing Condition Number */ + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 || + phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + float cn = 0.0f; + srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); + uci_data.uci_ri_len = 1; + } } } @@ -527,9 +535,9 @@ int phch_worker::decode_pdsch(srslte_ra_dl_grant_t *grant, uint8_t *payload[SRSL #endif Info( - "PDSCH: l_crb=%2d, harq=%d, tb_en={%s, %s}, tbs={%d, %d}, mcs={%d, %d}, rv={%d, %d}, crc={%s, %s}, snr=%.1f dB, n_iter=%d%s\n", - grant->nof_prb, harq_pid, grant->tb_en[0] ? "on" : "off", grant->tb_en[1] ? "on" : "off", - grant->mcs[0].tbs / 8, grant->mcs[1].tbs / 8, grant->mcs[0].idx, + "PDSCH: l_crb=%2d, harq=%d, scheme=%s, tb_en={%s, %s}, tbs={%d, %d}, mcs={%d, %d}, rv={%d, %d}, crc={%s, %s}, snr=%.1f dB, n_iter=%d, %s\n", + grant->nof_prb, harq_pid, srslte_mimotype2str(mimo_type), grant->tb_en[0] ? "on" : "off", + grant->tb_en[1] ? "on" : "off", grant->mcs[0].tbs / 8, grant->mcs[1].tbs / 8, grant->mcs[0].idx, grant->mcs[1].idx, rv[0], rv[1], acks[0] ? "OK" : "KO", acks[1] ? "OK" : "KO", 10 * log10(srslte_chest_dl_get_snr(&ue_dl.chest)), srslte_pdsch_last_noi(&ue_dl.pdsch), @@ -821,11 +829,12 @@ void phch_worker::encode_pusch(srslte_ra_ul_grant_t *grant, uint8_t *payload, ui snprintf(timestr, 64, ", total_time=%4d us", (int) logtime_start[0].tv_usec); #endif - Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, cfo=%.1f Hz%s\n", + Info("PUSCH: tti_tx=%d, n_prb=%d, rb_start=%d, tbs=%d, mod=%d, mcs=%d, rv_idx=%d, ack=%s, ri=%s, cfo=%.1f Hz%s\n", (tti+4)%10240, grant->L_prb, grant->n_prb[0], grant->mcs.tbs/8, grant->mcs.mod, grant->mcs.idx, rv, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", + uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", cfo*15000, timestr); // Store metrics From 0c31a5cfc1751ae1d133aa6b5510ec393ca28e2d Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 8 Sep 2017 16:24:34 +0200 Subject: [PATCH 10/10] Added periodic RI on PUCCH for TM3 and TM4 --- lib/examples/pdsch_ue.c | 2 +- lib/include/srslte/phy/phch/cqi.h | 3 +++ lib/include/srslte/phy/phch/uci.h | 4 +++ lib/include/srslte/phy/ue/ue_dl.h | 4 +-- lib/src/phy/ue/ue_dl.c | 10 ++++---- lib/src/phy/ue/ue_ul.c | 8 ++++++ srsue/src/phy/phch_worker.cc | 41 ++++++++++++++++++++++++++----- 7 files changed, 58 insertions(+), 14 deletions(-) diff --git a/lib/examples/pdsch_ue.c b/lib/examples/pdsch_ue.c index aa3e13257..71555234a 100644 --- a/lib/examples/pdsch_ue.c +++ b/lib/examples/pdsch_ue.c @@ -518,7 +518,7 @@ int main(int argc, char **argv) { // Variables for measurements uint32_t nframes=0; - uint32_t ri = 0, pmi = 0; + uint8_t ri = 0, pmi = 0; float rsrp0=0.0, rsrp1=0.0, rsrq=0.0, noise=0.0, enodebrate = 0.0, uerate = 0.0, sinr[SRSLTE_MAX_LAYERS][SRSLTE_MAX_CODEBOOKS], cn = 0.0; bool decode_pdsch = false; diff --git a/lib/include/srslte/phy/phch/cqi.h b/lib/include/srslte/phy/phch/cqi.h index 593592f1c..cfc9e92e7 100644 --- a/lib/include/srslte/phy/phch/cqi.h +++ b/lib/include/srslte/phy/phch/cqi.h @@ -41,11 +41,14 @@ #include "srslte/phy/common/phy_common.h" #define SRSLTE_CQI_MAX_BITS 64 +#define SRSLTE_DIF_CQI_MAX_BITS 3 +#define SRSLTE_PMI_MAX_BITS 4 typedef struct { bool configured; uint32_t pmi_idx; uint32_t ri_idx; + bool ri_idx_present; bool simul_cqi_ack; bool format_is_subband; uint32_t subband_size; diff --git a/lib/include/srslte/phy/phch/uci.h b/lib/include/srslte/phy/phch/uci.h index a674e43ea..0c53589e6 100644 --- a/lib/include/srslte/phy/phch/uci.h +++ b/lib/include/srslte/phy/phch/uci.h @@ -64,6 +64,10 @@ typedef struct SRSLTE_API { typedef struct SRSLTE_API { uint8_t uci_cqi[SRSLTE_CQI_MAX_BITS]; uint32_t uci_cqi_len; + uint8_t uci_dif_cqi[SRSLTE_DIF_CQI_MAX_BITS]; + uint32_t uci_dif_cqi_len; + uint8_t uci_pmi[SRSLTE_PMI_MAX_BITS]; + uint8_t uci_pmi_len; uint8_t uci_ri; // Only 1-bit supported for RI uint32_t uci_ri_len; uint8_t uci_ack; // 1st codeword bit for HARQ-ACK diff --git a/lib/include/srslte/phy/ue/ue_dl.h b/lib/include/srslte/phy/ue/ue_dl.h index 0f8b25ece..95523be84 100644 --- a/lib/include/srslte/phy/ue/ue_dl.h +++ b/lib/include/srslte/phy/ue/ue_dl.h @@ -182,8 +182,8 @@ SRSLTE_API int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, bool acks[SRSLTE_MAX_CODEWORDS]); SRSLTE_API int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, - uint32_t *ri, - uint32_t *pmi, + uint8_t *ri, + uint8_t *pmi, float *current_sinr); SRSLTE_API int srslte_ue_dl_ri_select(srslte_ue_dl_t *q, diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index dc88685b6..6d620be9d 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -454,10 +454,10 @@ int srslte_ue_dl_decode_rnti(srslte_ue_dl_t *q, cf_t *input[SRSLTE_MAX_PORTS], /* Compute the Rank Indicator (RI) and Precoder Matrix Indicator (PMI) by computing the Signal to Interference plus * Noise Ratio (SINR), valid for TM4 */ -int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, float *current_sinr) { +int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint8_t *ri, uint8_t *pmi, float *current_sinr) { float noise_estimate = srslte_chest_dl_get_noise_estimate(&q->chest); float best_sinr = -INFINITY; - uint32_t best_pmi = 0, best_ri = 0; + uint8_t best_pmi = 0, best_ri = 0; if (q->cell.nof_ports < 2 || q->nof_rx_antennas < 2) { /* Do nothing */ @@ -471,11 +471,11 @@ int srslte_ue_dl_ri_pmi_select(srslte_ue_dl_t *q, uint32_t *ri, uint32_t *pmi, f /* Select the best Rank indicator (RI) and Precoding Matrix Indicator (PMI) */ for (uint32_t nof_layers = 1; nof_layers <= 2; nof_layers++) { - float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers; + float _sinr = q->sinr[nof_layers - 1][q->pmi[nof_layers - 1]] * nof_layers * nof_layers; if (_sinr > best_sinr + 0.1) { best_sinr = _sinr; - best_pmi = q->pmi[nof_layers - 1]; - best_ri = nof_layers; + best_pmi = (uint8_t) q->pmi[nof_layers - 1]; + best_ri = (uint8_t) (nof_layers - 1); } } diff --git a/lib/src/phy/ue/ue_ul.c b/lib/src/phy/ue/ue_ul.c index 08edcafe0..6c074ea45 100644 --- a/lib/src/phy/ue/ue_ul.c +++ b/lib/src/phy/ue/ue_ul.c @@ -230,6 +230,14 @@ void pucch_encode_bits(srslte_uci_data_t *uci_data, srslte_pucch_format_t format pucch_bits[1] = uci_data->uci_ack_2; // this will be ignored in format 1a } if (format >= SRSLTE_PUCCH_FORMAT_2) { + /* Append Differential CQI */ + memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_dif_cqi, uci_data->uci_dif_cqi_len); + uci_data->uci_cqi_len += uci_data->uci_dif_cqi_len; + + /* Append PMI */ + memcpy(&uci_data->uci_cqi[uci_data->uci_cqi_len], uci_data->uci_pmi, uci_data->uci_pmi_len); + uci_data->uci_cqi_len += uci_data->uci_pmi_len; + srslte_uci_encode_cqi_pucch(uci_data->uci_cqi, uci_data->uci_cqi_len, pucch_bits); if (format > SRSLTE_PUCCH_FORMAT_2) { pucch2_bits[0] = uci_data->uci_ack; diff --git a/srsue/src/phy/phch_worker.cc b/srsue/src/phy/phch_worker.cc index e2c181c98..9ef204cd4 100644 --- a/srsue/src/phy/phch_worker.cc +++ b/srsue/src/phy/phch_worker.cc @@ -230,11 +230,23 @@ void phch_worker::work_imp() } /* Select Rank Indicator by computing Condition Number */ - if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3 || - phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4) { + if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_3) { float cn = 0.0f; srslte_ue_dl_ri_select(&ue_dl, &uci_data.uci_ri, &cn); uci_data.uci_ri_len = 1; + } else if (phy->config->dedicated.antenna_info_explicit_value.tx_mode == LIBLTE_RRC_TRANSMISSION_MODE_4){ + float sinr = 0.0f; + uint8 packed_pmi = 0; + srslte_ue_dl_ri_pmi_select(&ue_dl, &uci_data.uci_ri, &packed_pmi, &sinr); + srslte_bit_unpack_vector(&packed_pmi, uci_data.uci_pmi, 2); + uci_data.uci_ri_len = 1; + if (uci_data.uci_ri == 0) { + uci_data.uci_pmi_len = 2; + uci_data.uci_dif_cqi_len = 0; + } else { + uci_data.uci_pmi_len = 1; + uci_data.uci_dif_cqi_len = 3; + } } } } @@ -714,7 +726,16 @@ void phch_worker::set_uci_periodic_cqi() int cqi_max = phy->args->cqi_max; if (period_cqi.configured && rnti_is_set) { - if (srslte_cqi_send(period_cqi.pmi_idx, (tti+4)%10240)) { + if (period_cqi.ri_idx_present && srslte_ri_send(period_cqi.pmi_idx, period_cqi.ri_idx, (tti+4)%10240)) { + if (uci_data.uci_ri_len) { + uci_data.uci_cqi[0] = uci_data.uci_ri; + uci_data.uci_cqi_len = uci_data.uci_ri_len; + uci_data.uci_ri_len = 0; + uci_data.uci_dif_cqi_len = 0; + uci_data.uci_pmi_len = 0; + Info("PUCCH: Periodic RI=%d\n", uci_data.uci_cqi[0]); + } + } else if (srslte_cqi_send(period_cqi.pmi_idx, (tti+4)%10240)) { srslte_cqi_value_t cqi_report; if (period_cqi.format_is_subband) { // TODO: Implement subband periodic reports @@ -876,11 +897,12 @@ void phch_worker::encode_pucch() float tx_power = srslte_ue_ul_pucch_power(&ue_ul, phy->pathloss, ue_ul.last_pucch_format, uci_data.uci_cqi_len, uci_data.uci_ack_len); float gain = set_power(tx_power); - Info("PUCCH: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, sr=%s, cfo=%.1f Hz%s\n", + Info("PUCCH: power=%.2f dBm, tti_tx=%d, n_cce=%3d, n_pucch=%d, n_prb=%d, ack=%s%s, ri=%s, sr=%s, cfo=%.1f Hz%s\n", tx_power, (tti+4)%10240, last_dl_pdcch_ncce, ue_ul.pucch.last_n_pucch, ue_ul.pucch.last_n_prb, uci_data.uci_ack_len>0?(uci_data.uci_ack?"1":"0"):"no", uci_data.uci_ack_len>1?(uci_data.uci_ack_2?"1":"0"):"", + uci_data.uci_ri_len>0?(uci_data.uci_ri?"1":"0"):"no", uci_data.scheduling_request?"yes":"no", cfo*15000, timestr); } @@ -1011,12 +1033,19 @@ void phch_worker::set_ul_params(bool pregen_disabled) /* CQI configuration */ bzero(&period_cqi, sizeof(srslte_cqi_periodic_cfg_t)); period_cqi.configured = dedicated->cqi_report_cnfg.report_periodic_setup_present; - period_cqi.pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; + period_cqi.pmi_idx = dedicated->cqi_report_cnfg.report_periodic.pmi_cnfg_idx; period_cqi.simul_cqi_ack = dedicated->cqi_report_cnfg.report_periodic.simult_ack_nack_and_cqi; period_cqi.format_is_subband = dedicated->cqi_report_cnfg.report_periodic.format_ind_periodic == LIBLTE_RRC_CQI_FORMAT_INDICATOR_PERIODIC_SUBBAND_CQI; period_cqi.subband_size = dedicated->cqi_report_cnfg.report_periodic.format_ind_periodic_subband_k; - + + if (dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx_present) { + period_cqi.ri_idx = dedicated->cqi_report_cnfg.report_periodic.ri_cnfg_idx; + period_cqi.ri_idx_present = true; + } else { + period_cqi.ri_idx_present = false; + } + /* SR configuration */ I_sr = dedicated->sched_request_cnfg.sr_cnfg_idx;