From 13443c3f8c3372b79705698df48ffa3c505a4aa0 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Tue, 22 Dec 2020 11:45:39 +0100 Subject: [PATCH] Added number of DMRS CDM groups without data to NR grant --- lib/include/srslte/phy/phch/pdsch_cfg_nr.h | 4 + lib/include/srslte/phy/ue/ue_dl_nr_data.h | 11 ++ lib/src/phy/ch_estimation/dmrs_pdsch.c | 55 +++++- .../phy/ch_estimation/test/dmrs_pdsch_test.c | 47 +++-- lib/src/phy/phch/pdsch_nr.c | 186 +++++++++++++++--- lib/src/phy/phch/ra_nr.c | 5 + lib/src/phy/phch/test/pdsch_nr_test.c | 15 +- lib/src/phy/ue/ue_dl_nr_data.c | 25 +++ lib/test/phy/phy_dl_nr_test.c | 5 +- 9 files changed, 293 insertions(+), 60 deletions(-) diff --git a/lib/include/srslte/phy/phch/pdsch_cfg_nr.h b/lib/include/srslte/phy/phch/pdsch_cfg_nr.h index 2d7f5050b..a0ec54b04 100644 --- a/lib/include/srslte/phy/phch/pdsch_cfg_nr.h +++ b/lib/include/srslte/phy/phch/pdsch_cfg_nr.h @@ -119,6 +119,10 @@ typedef struct SRSLTE_API { /// Frequency domain resources bool prb_idx[SRSLTE_MAX_PRB_NR]; + /// Number of DMRS groups without data + /// Described in TS 38.214 Section 5.1.6.2 + uint32_t nof_dmrs_cdm_groups_without_data; + /// Spatial resources uint32_t nof_layers; diff --git a/lib/include/srslte/phy/ue/ue_dl_nr_data.h b/lib/include/srslte/phy/ue/ue_dl_nr_data.h index f5cd0ca6c..c70beea80 100644 --- a/lib/include/srslte/phy/ue/ue_dl_nr_data.h +++ b/lib/include/srslte/phy/ue/ue_dl_nr_data.h @@ -58,6 +58,17 @@ SRSLTE_API int srslte_ue_dl_nr_pdsch_time_resource_hl(const srslte_pdsch_allocat SRSLTE_API int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t m, srslte_dmrs_pdsch_typeA_pos_t dmrs_typeA_pos, srslte_pdsch_grant_nr_t* grant); +/** + * @brief Calculates the number of PDSCH-DMRS CDM groups without data for DCI format 1_0 + * + * @remark Defined by TS 38.214 V15.10.0 5.1.6.1.3 CSI-RS for mobility + * + * @param pdsch_cfg PDSCH NR configuration by upper layers + * @param[out] grant Provides grant pointer to fill + * @return Returns SRSLTE_SUCCESS if the provided data is valid, otherwise it returns SRSLTE_ERROR code + */ +SRSLTE_API int srslte_ue_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_pdsch_cfg_nr_t* pdsch_cfg, + srslte_pdsch_grant_nr_t* grant); #ifdef __cplusplus } diff --git a/lib/src/phy/ch_estimation/dmrs_pdsch.c b/lib/src/phy/ch_estimation/dmrs_pdsch.c index a302f6c38..16b652dab 100644 --- a/lib/src/phy/ch_estimation/dmrs_pdsch.c +++ b/lib/src/phy/ch_estimation/dmrs_pdsch.c @@ -201,8 +201,7 @@ static int srslte_dmrs_pdsch_put_symbol(srslte_dmrs_pdsch_t* q, } // Get contiguous pilots - pilot_count += srslte_dmrs_put_pilots( - q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, &symbols[prb_start * SRSLTE_NRE]); + pilot_count += srslte_dmrs_put_pilots(q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols); // Reset counter prb_count = 0; @@ -317,6 +316,12 @@ static int srslte_dmrs_pdsch_get_symbols_idx_mapping_type_A_double(const srslte_ return SRSLTE_ERROR; } + // According to Table 7.4.1.1.2-4, the additional position 3 is invalid. + if (dmrs_cfg->additional_pos == srslte_dmrs_pdsch_add_pos_3) { + ERROR("Invalid additional DMRS (%d)\n", dmrs_cfg->additional_pos); + return SRSLTE_ERROR; + } + // l0 = 3 if the higher-layer parameter dmrs-TypeA-Position is equal to 'pos3' and l0 = 2 otherwise int l0 = (dmrs_cfg->typeA_pos == srslte_dmrs_pdsch_typeA_pos_3) ? 3 : 2; @@ -414,6 +419,19 @@ int srslte_dmrs_pdsch_get_sc_idx(const srslte_pdsch_dmrs_cfg_t* cfg, uint32_t ma int srslte_dmrs_pdsch_get_N_prb(const srslte_pdsch_cfg_nr_t* cfg, const srslte_pdsch_grant_nr_t* grant) { + const srslte_pdsch_dmrs_cfg_t* dmrs_cfg = + grant->mapping == srslte_pdsch_mapping_type_A ? &cfg->dmrs_cfg_typeA : &cfg->dmrs_cfg_typeB; + + if (grant->nof_dmrs_cdm_groups_without_data < 1 || grant->nof_dmrs_cdm_groups_without_data > 3) { + ERROR("Invalid number if DMRS CDM groups without data (%d). Valid values: 1, 2 , 3\n", + grant->nof_dmrs_cdm_groups_without_data); + return SRSLTE_ERROR; + } + + // Get number of frequency domain resource elements used for DMRS + int nof_sc = SRSLTE_MIN( + SRSLTE_NRE, grant->nof_dmrs_cdm_groups_without_data * (dmrs_cfg->type == srslte_dmrs_pdsch_type_1 ? 6 : 4)); + // Get number of symbols used for DMRS uint32_t symbols[SRSLTE_DMRS_PDSCH_MAX_SYMBOLS] = {}; int ret = srslte_dmrs_pdsch_get_symbols_idx(cfg, grant, symbols); @@ -422,7 +440,7 @@ int srslte_dmrs_pdsch_get_N_prb(const srslte_pdsch_cfg_nr_t* cfg, const srslte_p return SRSLTE_ERROR; } - return SRSLTE_NRE * ret; + return nof_sc * ret; } static uint32_t srslte_dmrs_pdsch_seed(const srslte_carrier_nr_t* carrier, @@ -733,11 +751,34 @@ int srslte_dmrs_pdsch_estimate(srslte_dmrs_pdsch_t* q, } if (symbols[symbol_idx] == l) { - continue; + switch (dmrs_cfg->type) { + + case srslte_dmrs_pdsch_type_1: + // Skip if there is no data to read + if (grant->nof_dmrs_cdm_groups_without_data != 1) { + continue; + } + for (uint32_t i = 1; i < nof_re_x_symbol; i += 2) { + chest_res->ce[0][0][count] = ce[i]; + count++; + } + break; + case srslte_dmrs_pdsch_type_2: + // Skip if there is no data to read + if (grant->nof_dmrs_cdm_groups_without_data != 1 && grant->nof_dmrs_cdm_groups_without_data != 2) { + continue; + } + for (uint32_t i = grant->nof_dmrs_cdm_groups_without_data * 2; i < nof_re_x_symbol; i += 6) { + uint32_t nof_re = (3 - grant->nof_dmrs_cdm_groups_without_data) * 2; + srslte_vec_cf_copy(&chest_res->ce[0][0][count], &ce[i], nof_re); + count += nof_re; + } + break; + } + } else { + srslte_vec_cf_copy(&chest_res->ce[0][0][count], ce, nof_re_x_symbol); + count += nof_re_x_symbol; } - - srslte_vec_cf_copy(&chest_res->ce[0][0][count], ce, nof_re_x_symbol); - count += nof_re_x_symbol; } // Set other values in the estimation result chest_res->nof_re = count; diff --git a/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c b/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c index 1e2de636f..4d5460f9d 100644 --- a/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c +++ b/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c @@ -216,9 +216,10 @@ static int run_test(srslte_dmrs_pdsch_t* dmrs_pdsch, srslte_dl_slot_cfg_t slot_cfg = {}; for (slot_cfg.idx = 0; slot_cfg.idx < SRSLTE_NSLOTS_PER_FRAME_NR(dmrs_pdsch->carrier.numerology); slot_cfg.idx++) { - srslte_dmrs_pdsch_put_sf(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols); + TESTASSERT(srslte_dmrs_pdsch_put_sf(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols) == SRSLTE_SUCCESS); - srslte_dmrs_pdsch_estimate(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols, chest_res); + TESTASSERT(srslte_dmrs_pdsch_estimate(dmrs_pdsch, &slot_cfg, pdsch_cfg, grant, sf_symbols, chest_res) == + SRSLTE_SUCCESS); float mse = 0.0f; for (uint32_t i = 0; i < chest_res->nof_re; i++) { @@ -294,6 +295,12 @@ int main(int argc, char** argv) srslte_dmrs_pdsch_len_t max_len_begin = srslte_dmrs_pdsch_len_1; srslte_dmrs_pdsch_len_t max_len_end = srslte_dmrs_pdsch_len_2; + // Only single DMRS symbols can have additional positions 2 and 3 + if (pdsch_cfg.dmrs_cfg_typeA.additional_pos == srslte_dmrs_pdsch_add_pos_2 || + pdsch_cfg.dmrs_cfg_typeA.additional_pos == srslte_dmrs_pdsch_add_pos_3) { + max_len_end = srslte_dmrs_pdsch_len_1; + } + for (pdsch_cfg.dmrs_cfg_typeA.length = max_len_begin; pdsch_cfg.dmrs_cfg_typeA.length <= max_len_end; pdsch_cfg.dmrs_cfg_typeA.length++) { @@ -303,28 +310,32 @@ int main(int argc, char** argv) grant.prb_idx[i] = (i < bw); } - // Load default type A grant - srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &grant); + for (grant.nof_dmrs_cdm_groups_without_data = 1; grant.nof_dmrs_cdm_groups_without_data <= 3; + grant.nof_dmrs_cdm_groups_without_data++) { - // Copy configuration - pdsch_cfg.dmrs_cfg_typeB = pdsch_cfg.dmrs_cfg_typeA; + // Load default type A grant + srslte_ue_dl_nr_pdsch_time_resource_default_A(0, pdsch_cfg.dmrs_cfg_typeA.typeA_pos, &grant); - int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res); + // Copy configuration + pdsch_cfg.dmrs_cfg_typeB = pdsch_cfg.dmrs_cfg_typeA; - if (n == SRSLTE_SUCCESS) { - test_passed++; - } else { - const srslte_pdsch_dmrs_cfg_t* dmrs_cfg = grant.mapping == srslte_pdsch_mapping_type_A - ? &pdsch_cfg.dmrs_cfg_typeA - : &pdsch_cfg.dmrs_cfg_typeB; + int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res); - char str[64] = {}; - srslte_dmrs_pdsch_cfg_to_str(dmrs_cfg, str, 64); + if (n == SRSLTE_SUCCESS) { + test_passed++; + } else { + const srslte_pdsch_dmrs_cfg_t* dmrs_cfg = grant.mapping == srslte_pdsch_mapping_type_A + ? &pdsch_cfg.dmrs_cfg_typeA + : &pdsch_cfg.dmrs_cfg_typeB; - ERROR("Test %d failed. %s.\n", test_counter, str); - } + char str[64] = {}; + srslte_dmrs_pdsch_cfg_to_str(dmrs_cfg, str, 64); - test_counter++; + ERROR("Test %d failed. %s.\n", test_counter, str); + } + + test_counter++; + } } } } diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index ad2058bbb..35501f946 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -168,9 +168,129 @@ void srslte_pdsch_nr_free(srslte_pdsch_nr_t* q) if (q->evm_buffer != NULL) { srslte_evm_free(q->evm_buffer); } +} + +/** + * @brief copies a number of countiguous Resource Elements + * @param sf_symbols slot symbols in frequency domain + * @param symbols resource elements + * @param count number of resource elements to copy + * @param put Direction, symbols are copied into sf_symbols if put is true, otherwise sf_symbols are copied into symbols + */ +static void srslte_pdsch_re_cp(cf_t* sf_symbols, cf_t* symbols, uint32_t count, bool put) +{ + if (put) { + srslte_vec_cf_copy(sf_symbols, symbols, count); + } else { + srslte_vec_cf_copy(symbols, sf_symbols, count); + } +} + +/* + * As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with group 2: + * + * +---+---+---+---+---+---+---+---+---+---+---+---+ + * | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | 1 | 1 | 2 | 2 | + * +---+---+---+---+---+---+---+---+---+---+---+---+ + * -- k --> + * + * If the number of DMRS CDM groups without data is set to: + * - 1, data is mapped in RE marked as 2 + * - Otherwise, no data is mapped in this symbol + */ +static uint32_t srslte_pdsch_nr_cp_dmrs_type1(const srslte_pdsch_nr_t* q, + const srslte_pdsch_grant_nr_t* grant, + cf_t* symbols, + cf_t* sf_symbols, + bool put) +{ + uint32_t count = 0; + uint32_t delta = 0; + + if (grant->nof_dmrs_cdm_groups_without_data != 1) { + return count; + } + + for (uint32_t i = 0; i < q->carrier.nof_prb; i++) { + if (grant->prb_idx[i]) { + for (uint32_t j = 0; j < SRSLTE_NRE; j += 2) { + if (put) { + sf_symbols[i * SRSLTE_NRE + delta + j + 1] = symbols[count++]; + } else { + symbols[count++] = sf_symbols[i * SRSLTE_NRE + delta + j + 1]; + } + } + } + } - // Make sure whole structure is fill with zeros - SRSLTE_MEM_ZERO(q, srslte_pdsch_nr_t, 1); + return count; +} + +/* + * As a RB is 12 RE wide, positions marked as 1 will be used for the 1st CDM group, and the same with groups 2 and 3: + * + * +---+---+---+---+---+---+---+---+---+---+---+---+ + * | 1 | 1 | 2 | 2 | 3 | 3 | 1 | 1 | 2 | 2 | 3 | 3 | + * +---+---+---+---+---+---+---+---+---+---+---+---+ + * -- k --> + * + * If the number of DMRS CDM groups without data is set to: + * - 1, data is mapped in RE marked as 2 and 3 + * - 2, data is mapped in RE marked as 3 + * - otherwise, no data is mapped in this symbol + */ +static uint32_t srslte_pdsch_nr_cp_dmrs_type2(const srslte_pdsch_nr_t* q, + const srslte_pdsch_grant_nr_t* grant, + cf_t* symbols, + cf_t* sf_symbols, + bool put) +{ + uint32_t count = 0; + + if (grant->nof_dmrs_cdm_groups_without_data != 1 && grant->nof_dmrs_cdm_groups_without_data != 2) { + return count; + } + + uint32_t re_offset = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 2 : 4; + uint32_t re_count = (grant->nof_dmrs_cdm_groups_without_data == 1) ? 4 : 2; + + for (uint32_t i = 0; i < q->carrier.nof_prb; i++) { + if (grant->prb_idx[i]) { + // Copy RE between pilot pairs + srslte_pdsch_re_cp(&sf_symbols[i * SRSLTE_NRE + re_offset], &symbols[count], re_count, put); + count += re_count; + + // Copy RE after second pilot + srslte_pdsch_re_cp(&sf_symbols[(i + 1) * SRSLTE_NRE - re_count], &symbols[count], re_count, put); + count += re_count; + } + } + + return count; +} + +static uint32_t srslte_pdsch_nr_cp_dmrs(const srslte_pdsch_nr_t* q, + const srslte_pdsch_cfg_nr_t* cfg, + const srslte_pdsch_grant_nr_t* grant, + cf_t* symbols, + cf_t* sf_symbols, + bool put) +{ + uint32_t count = 0; + + const srslte_pdsch_dmrs_cfg_t* dmrs_cfg = + grant->mapping == srslte_pdsch_mapping_type_A ? &cfg->dmrs_cfg_typeA : &cfg->dmrs_cfg_typeB; + + switch (dmrs_cfg->type) { + case srslte_dmrs_pdsch_type_1: + count = srslte_pdsch_nr_cp_dmrs_type1(q, grant, symbols, sf_symbols, put); + break; + case srslte_dmrs_pdsch_type_2: + count = srslte_pdsch_nr_cp_dmrs_type2(q, grant, symbols, sf_symbols, put); + break; + } + + return count; } static uint32_t srslte_pdsch_nr_cp_clean(const srslte_pdsch_nr_t* q, @@ -236,8 +356,8 @@ static int srslte_pdsch_nr_cp(const srslte_pdsch_nr_t* q, return SRSLTE_ERROR; } - if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { - printf("dmrs_l_idx="); + if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { + DEBUG("dmrs_l_idx="); srslte_vec_fprint_i(stdout, (int32_t*)dmrs_l_idx, nof_dmrs_symbols); } @@ -249,12 +369,13 @@ static int srslte_pdsch_nr_cp(const srslte_pdsch_nr_t* q, dmrs_l_count++; } - // Skip DMRS symbol if (l == dmrs_l_idx[dmrs_l_count]) { - continue; + count += srslte_pdsch_nr_cp_dmrs( + q, cfg, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSLTE_NRE], put); + } else { + count += + srslte_pdsch_nr_cp_clean(q, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSLTE_NRE], put); } - - count += srslte_pdsch_nr_cp_clean(q, grant, &symbols[count], &sf_symbols[l * q->carrier.nof_prb * SRSLTE_NRE], put); } return count; @@ -278,6 +399,20 @@ static int srslte_pdsch_nr_get(const srslte_pdsch_nr_t* q, return srslte_pdsch_nr_cp(q, cfg, grant, symbols, sf_symbols, false); } +static uint32_t +pdsch_nr_cinit(const srslte_carrier_nr_t* carrier, const srslte_pdsch_cfg_nr_t* cfg, uint16_t rnti, uint32_t cw_idx) +{ + uint32_t n_id = carrier->id; + if (cfg->scrambling_id_present && SRSLTE_RNTI_ISUSER(rnti)) { + n_id = cfg->scambling_id; + } + uint32_t cinit = (((uint32_t)rnti) << 15U) + (cw_idx << 14U) + n_id; + + INFO("PDSCH: RNTI=%d (0x%x); nid=%d; cinit=%d (0x%x);\n", rnti, rnti, n_id, cinit, cinit); + + return cinit; +} + static inline int pdsch_nr_encode_codeword(srslte_pdsch_nr_t* q, const srslte_pdsch_cfg_nr_t* cfg, const srslte_sch_tb_t* tb, @@ -307,24 +442,20 @@ static inline int pdsch_nr_encode_codeword(srslte_pdsch_nr_t* q, return SRSLTE_ERROR; } - if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { - INFO("b="); + if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { + DEBUG("b="); srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits); } // 7.3.1.1 Scrambling - uint32_t n_id = q->carrier.id; - if (cfg->scrambling_id_present && SRSLTE_RNTI_ISUSER(rnti)) { - n_id = cfg->scambling_id; - } - uint32_t cinit = ((uint32_t)rnti << 15U) + (tb->cw_idx << 14U) + n_id; + uint32_t cinit = pdsch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx); srslte_sequence_apply_bit(q->b[tb->cw_idx], q->b[tb->cw_idx], tb->nof_bits, cinit); // 7.3.1.2 Modulation srslte_mod_modulate(&q->modem_tables[tb->mod], q->b[tb->cw_idx], q->d[tb->cw_idx], tb->nof_bits); - if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { - INFO("d="); + if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { + DEBUG("d="); srslte_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re); } @@ -422,8 +553,8 @@ static inline int pdsch_nr_decode_codeword(srslte_pdsch_nr_t* q, return SRSLTE_ERROR_OUT_OF_BOUNDS; } - if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { - printf("d="); + if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { + DEBUG("d="); srslte_vec_fprint_c(stdout, q->d[tb->cw_idx], tb->nof_re); } @@ -444,15 +575,10 @@ static inline int pdsch_nr_decode_codeword(srslte_pdsch_nr_t* q, } // Descrambling - uint32_t n_id = q->carrier.id; - if (cfg->scrambling_id_present && SRSLTE_RNTI_ISUSER(rnti)) { - n_id = cfg->scambling_id; - } - uint32_t cinit = ((uint32_t)rnti << 15U) + (tb->cw_idx << 14U) + n_id; - srslte_sequence_apply_c(llr, llr, tb->nof_bits, cinit); + srslte_sequence_apply_c(llr, llr, tb->nof_bits, pdsch_nr_cinit(&q->carrier, cfg, rnti, tb->cw_idx)); - if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { - printf("b="); + if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { + DEBUG("b="); srslte_vec_fprint_b(stdout, q->b[tb->cw_idx], tb->nof_bits); } @@ -501,10 +627,10 @@ int srslte_pdsch_nr_decode(srslte_pdsch_nr_t* q, return SRSLTE_ERROR; } - if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_INFO && !handler_registered) { - INFO("ce="); + if (SRSLTE_DEBUG_ENABLED && srslte_verbose >= SRSLTE_VERBOSE_DEBUG && !handler_registered) { + DEBUG("ce="); srslte_vec_fprint_c(stdout, channel->ce[0][0], nof_re); - INFO("x="); + DEBUG("x="); srslte_vec_fprint_c(stdout, q->x[0], nof_re); } diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 6ca60a900..0fe8a71e6 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -303,6 +303,11 @@ uint32_t srslte_ra_nr_tbs(uint32_t N_re, double S, double R, uint32_t Qm, uint32 S = 1.0; } + if (nof_layers == 0) { + ERROR("Incorrect number of layers (%d). Setting to 1.\n", nof_layers); + nof_layers = 1; + } + // 2) Intermediate number of information bits (N info ) is obtained by N inf o = N RE · R · Q m · υ . uint32_t n_info = (uint32_t)(N_re * S * R * Qm * nof_layers); diff --git a/lib/src/phy/phch/test/pdsch_nr_test.c b/lib/src/phy/phch/test/pdsch_nr_test.c index 1efa496b2..266c98711 100644 --- a/lib/src/phy/phch/test/pdsch_nr_test.c +++ b/lib/src/phy/phch/test/pdsch_nr_test.c @@ -19,7 +19,7 @@ #include static srslte_carrier_nr_t carrier = { - 0, // cell_id + 1, // cell_id 0, // numerology SRSLTE_MAX_PRB_NR, // nof_prb 0, // start @@ -30,6 +30,7 @@ static uint32_t n_prb = 0; // Set to 0 for steering static uint32_t mcs = 30; // Set to 30 for steering static srslte_pdsch_cfg_nr_t pdsch_cfg = {}; static srslte_pdsch_grant_nr_t pdsch_grant = {}; +static uint16_t rnti = 0x1234; void usage(char* prog) { @@ -85,14 +86,14 @@ int main(int argc, char** argv) cf_t* sf_symbols[SRSLTE_MAX_LAYERS_NR] = {}; // Set default PDSCH configuration - pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam; + pdsch_cfg.sch_cfg.mcs_table = srslte_mcs_table_64qam; if (parse_args(argc, argv) < SRSLTE_SUCCESS) { goto clean_exit; } srslte_pdsch_nr_args_t pdsch_args = {}; - pdsch_args.sch.disable_simd = true; + pdsch_args.sch.disable_simd = false; pdsch_args.measure_evm = true; if (srslte_pdsch_nr_init_enb(&pdsch_tx, &pdsch_args) < SRSLTE_SUCCESS) { @@ -155,8 +156,16 @@ int main(int argc, char** argv) ERROR("Error loading default grant\n"); goto clean_exit; } + + // Load number of DMRS CDM groups without data + if (srslte_ue_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&pdsch_cfg, &pdsch_grant) < SRSLTE_SUCCESS) { + ERROR("Error loading number of DMRS CDM groups without data\n"); + goto clean_exit; + } + pdsch_grant.nof_layers = carrier.max_mimo_layers; pdsch_grant.dci_format = srslte_dci_format_nr_1_0; + pdsch_grant.rnti = rnti; uint32_t n_prb_start = 1; uint32_t n_prb_end = carrier.nof_prb + 1; diff --git a/lib/src/phy/ue/ue_dl_nr_data.c b/lib/src/phy/ue/ue_dl_nr_data.c index 53100790a..60ef76b91 100644 --- a/lib/src/phy/ue/ue_dl_nr_data.c +++ b/lib/src/phy/ue/ue_dl_nr_data.c @@ -128,5 +128,30 @@ int srslte_ue_dl_nr_pdsch_time_resource_default_A(uint32_t return SRSLTE_ERROR; } + return SRSLTE_SUCCESS; +} + +int srslte_ue_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_pdsch_cfg_nr_t* pdsch_cfg, + srslte_pdsch_grant_nr_t* grant) +{ + if (pdsch_cfg == NULL || grant == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + const srslte_pdsch_dmrs_cfg_t* dmrs_cfg = + grant->mapping == srslte_pdsch_mapping_type_A ? &pdsch_cfg->dmrs_cfg_typeA : &pdsch_cfg->dmrs_cfg_typeB; + + /* According to TS 38.214 V15.10.0 5.1.6.1.3 CSI-RS for mobility: + * When receiving PDSCH scheduled by DCI format 1_0, the UE shall assume the number of DM-RS CDM groups without data + * is 1 which corresponds to CDM group 0 for the case of PDSCH with allocation duration of 2 symbols, and the UE shall + * assume that the number of DM-RS CDM groups without data is 2 which corresponds to CDM group {0,1} for all other + * cases. + */ + if (dmrs_cfg->length == srslte_dmrs_pdsch_len_2) { + grant->nof_dmrs_cdm_groups_without_data = 1; + } else { + grant->nof_dmrs_cdm_groups_without_data = 2; + } + return SRSLTE_SUCCESS; } \ No newline at end of file diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 316cd8c68..e790788d9 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -259,8 +259,9 @@ int main(int argc, char** argv) ERROR("Error loading default grant\n"); goto clean_exit; } - pdsch_grant.nof_layers = carrier.max_mimo_layers; - pdsch_grant.dci_format = srslte_dci_format_nr_1_0; + pdsch_grant.nof_layers = carrier.max_mimo_layers; + pdsch_grant.dci_format = srslte_dci_format_nr_1_0; + pdsch_grant.nof_dmrs_cdm_groups_without_data = 1; uint32_t n_prb_start = 1; uint32_t n_prb_end = carrier.nof_prb + 1;