diff --git a/lib/include/srslte/phy/phch/phch_cfg_nr.h b/lib/include/srslte/phy/phch/phch_cfg_nr.h index e9f0f2830..27011170b 100644 --- a/lib/include/srslte/phy/phch/phch_cfg_nr.h +++ b/lib/include/srslte/phy/phch/phch_cfg_nr.h @@ -59,7 +59,7 @@ typedef enum { } srslte_dmrs_sch_add_pos_t; /** - * @brief Provides PDSCH DMRS configuration from higher layers + * @brief Provides PDSCH DMRS configuration * @remark Parameters described in TS 38.331 V15.10.0 */ typedef struct { @@ -122,6 +122,10 @@ typedef struct SRSLTE_API { /// Described in TS 38.214 Section 5.1.6.2 uint32_t nof_dmrs_cdm_groups_without_data; + /// Linear DMRS power offset. Zero means unset and it is equivalent to one. + /// For PUSCH, see TS 38.214 Table 6.2.2-1 for more information + float beta_dmrs; + /// Spatial resources uint32_t nof_layers; diff --git a/lib/include/srslte/phy/phch/ra_ul_nr.h b/lib/include/srslte/phy/phch/ra_ul_nr.h index 3515d9d71..5e882b7b3 100644 --- a/lib/include/srslte/phy/phch/ra_ul_nr.h +++ b/lib/include/srslte/phy/phch/ra_ul_nr.h @@ -66,6 +66,16 @@ srslte_ra_ul_nr_pdsch_time_resource_default_A(uint32_t scs_cfg, uint32_t m, srsl SRSLTE_API int srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch_cfg_nr_t* cfg, srslte_sch_grant_nr_t* grant); +/** + * @brief Calculates the ratio of PUSCH EPRE to DM-RS EPRE + * + * @remark Defined by TS 38.214 V15.10.0 Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE + * + * @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_ra_ul_nr_dmrs_power_offset(srslte_sch_grant_nr_t* grant); + /** * @brief Calculates the minimum number of PRB required for transmitting NR-PUCCH Format 2, 3 or 4 * @remark Based in TS 38.213 9.2.5.1 UE procedure for multiplexing HARQ-ACK or CSI and SR in a PUCCH diff --git a/lib/src/phy/ch_estimation/dmrs_sch.c b/lib/src/phy/ch_estimation/dmrs_sch.c index 22bcf5052..7a6a1e21a 100644 --- a/lib/src/phy/ch_estimation/dmrs_sch.c +++ b/lib/src/phy/ch_estimation/dmrs_sch.c @@ -71,6 +71,7 @@ static uint32_t srslte_dmrs_get_lse(srslte_dmrs_sch_t* q, uint32_t start_prb, uint32_t nof_prb, uint32_t delta, + float amplitude, const cf_t* symbols, cf_t* least_square_estimates) { @@ -88,7 +89,7 @@ static uint32_t srslte_dmrs_get_lse(srslte_dmrs_sch_t* q, } // Generate sequence for the given pilots - srslte_sequence_state_gen_f(sequence_state, M_SQRT1_2, (float*)q->temp, count * 2); + srslte_sequence_state_gen_f(sequence_state, amplitude, (float*)q->temp, count * 2); // Calculate least square estimates srslte_vec_prod_conj_ccc(least_square_estimates, q->temp, least_square_estimates, count); @@ -134,12 +135,13 @@ static uint32_t srslte_dmrs_put_pilots(srslte_dmrs_sch_t* q, uint32_t start_prb, uint32_t nof_prb, uint32_t delta, + float amplitude, cf_t* symbols) { uint32_t count = (dmrs_type == srslte_dmrs_sch_type_1) ? nof_prb * 6 : nof_prb * 4; // Generate sequence for the given pilots - srslte_sequence_state_gen_f(sequence_state, M_SQRT1_2, (float*)q->temp, count * 2); + srslte_sequence_state_gen_f(sequence_state, amplitude, (float*)q->temp, count * 2); switch (dmrs_type) { case srslte_dmrs_sch_type_1: @@ -162,6 +164,12 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q, uint32_t delta, cf_t* symbols) { + // Get signal amplitude + float amplitude = M_SQRT1_2; + if (isnormal(grant->beta_dmrs)) { + amplitude *= grant->beta_dmrs; + } + const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs; uint32_t prb_count = 0; // Counts consecutive used PRB uint32_t prb_start = 0; // Start consecutive used PRB @@ -200,14 +208,16 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q, } // Get contiguous pilots - pilot_count += srslte_dmrs_put_pilots(q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols); + pilot_count += + srslte_dmrs_put_pilots(q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, amplitude, symbols); // Reset counter prb_count = 0; } if (prb_count > 0) { - pilot_count += srslte_dmrs_put_pilots(q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols); + pilot_count += + srslte_dmrs_put_pilots(q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, amplitude, symbols); } return pilot_count; @@ -455,9 +465,8 @@ static uint32_t srslte_dmrs_sch_seed(const srslte_carrier_nr_t* carrier, n_id = dmrs_cfg->scrambling_id1; } - return (uint32_t)(((((SRSLTE_NSYMB_PER_SLOT_NR * slot_idx + symbol_idx + 1UL) * (2UL * n_id + 1UL)) << 17UL) + - (2UL * carrier->id + n_scid)) & - (uint64_t)INT32_MAX); + return SRSLTE_SEQUENCE_MOD((((SRSLTE_NSYMB_PER_SLOT_NR * slot_idx + symbol_idx + 1UL) * (2UL * n_id + 1UL)) << 17UL) + + (2UL * carrier->id + n_scid)); } int srslte_dmrs_sch_init(srslte_dmrs_sch_t* q, bool is_rx) @@ -585,6 +594,12 @@ static int srslte_dmrs_sch_get_symbol(srslte_dmrs_sch_t* q, const cf_t* symbols, cf_t* least_square_estimates) { + // Get signal amplitude + float amplitude = M_SQRT1_2; + if (isnormal(grant->beta_dmrs)) { + amplitude /= grant->beta_dmrs; + } + const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs; uint32_t prb_count = 0; // Counts consecutive used PRB @@ -624,16 +639,30 @@ static int srslte_dmrs_sch_get_symbol(srslte_dmrs_sch_t* q, } // Get contiguous pilots - pilot_count += srslte_dmrs_get_lse( - q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols, &least_square_estimates[pilot_count]); + pilot_count += srslte_dmrs_get_lse(q, + &sequence_state, + dmrs_cfg->type, + prb_start, + prb_count, + delta, + amplitude, + symbols, + &least_square_estimates[pilot_count]); // Reset counter prb_count = 0; } if (prb_count > 0) { - pilot_count += srslte_dmrs_get_lse( - q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols, &least_square_estimates[pilot_count]); + pilot_count += srslte_dmrs_get_lse(q, + &sequence_state, + dmrs_cfg->type, + prb_start, + prb_count, + delta, + amplitude, + symbols, + &least_square_estimates[pilot_count]); } return pilot_count; diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 3b7343148..16edc4f55 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -553,36 +553,41 @@ ra_ul_dmrs(const srslte_sch_hl_cfg_nr_t* pusch_hl_cfg, srslte_sch_grant_nr_t* pu cfg->dmrs.length = srslte_dmrs_sch_len_1; cfg->dmrs.scrambling_id0_present = false; cfg->dmrs.scrambling_id1_present = false; - - if (pusch_grant->dci_format == srslte_dci_format_nr_0_0) { - if (srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(cfg, pusch_grant) < SRSLTE_SUCCESS) { - ERROR("Error loading number of DMRS CDM groups\n"); - return SRSLTE_ERROR; - } - } else { - ERROR("Invalid case\n"); - return SRSLTE_ERROR; - } - - return SRSLTE_SUCCESS; + } else { + ERROR("Unsupported configuration"); + return SRSLTE_ERROR; + } + } else { + if (pusch_grant->mapping == srslte_sch_mapping_type_A) { + cfg->dmrs.additional_pos = pusch_hl_cfg->dmrs_typeA.additional_pos; + cfg->dmrs.type = pusch_hl_cfg->dmrs_typeA.type; + cfg->dmrs.length = pusch_hl_cfg->dmrs_typeA.length; + cfg->dmrs.scrambling_id0_present = false; + cfg->dmrs.scrambling_id1_present = false; + } else { + cfg->dmrs.additional_pos = pusch_hl_cfg->dmrs_typeB.additional_pos; + cfg->dmrs.type = pusch_hl_cfg->dmrs_typeB.type; + cfg->dmrs.length = pusch_hl_cfg->dmrs_typeB.length; + cfg->dmrs.scrambling_id0_present = false; + cfg->dmrs.scrambling_id1_present = false; } + } - ERROR("Unsupported configuration"); + // Set number of DMRS CDM groups without data + if (pusch_grant->dci_format == srslte_dci_format_nr_0_0) { + if (srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(cfg, pusch_grant) < SRSLTE_SUCCESS) { + ERROR("Error loading number of DMRS CDM groups\n"); + return SRSLTE_ERROR; + } + } else { + ERROR("Invalid case\n"); return SRSLTE_ERROR; } - if (pusch_grant->mapping == srslte_sch_mapping_type_A) { - cfg->dmrs.additional_pos = pusch_hl_cfg->dmrs_typeA.additional_pos; - cfg->dmrs.type = pusch_hl_cfg->dmrs_typeA.type; - cfg->dmrs.length = pusch_hl_cfg->dmrs_typeA.length; - cfg->dmrs.scrambling_id0_present = false; - cfg->dmrs.scrambling_id1_present = false; - } else { - cfg->dmrs.additional_pos = pusch_hl_cfg->dmrs_typeB.additional_pos; - cfg->dmrs.type = pusch_hl_cfg->dmrs_typeB.type; - cfg->dmrs.length = pusch_hl_cfg->dmrs_typeB.length; - cfg->dmrs.scrambling_id0_present = false; - cfg->dmrs.scrambling_id1_present = false; + // Set DMRS power offset Table 6.2.2-1: The ratio of PUSCH EPRE to DM-RS EPRE + if (srslte_ra_ul_nr_dmrs_power_offset(pusch_grant) < SRSLTE_SUCCESS) { + ERROR("Error setting DMRS power offset"); + return SRSLTE_ERROR; } return SRSLTE_SUCCESS; diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index ecdf5bab4..df06e34be 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -15,6 +15,7 @@ #include "srslte/phy/ch_estimation/dmrs_pucch.h" #include "srslte/phy/common/phy_common.h" #include "srslte/phy/utils/debug.h" +#include "srslte/phy/utils/vector.h" typedef struct { srslte_sch_mapping_type_t mapping; @@ -216,6 +217,24 @@ int srslte_ra_ul_nr_nof_dmrs_cdm_groups_without_data_format_0_0(const srslte_sch return SRSLTE_SUCCESS; } +int srslte_ra_ul_nr_dmrs_power_offset(srslte_sch_grant_nr_t* grant) +{ + if (grant == NULL) { + return SRSLTE_ERROR_INVALID_INPUTS; + } + + float ratio_dB[3] = {0, -3, -4.77}; + + if (grant->nof_dmrs_cdm_groups_without_data < 1 || grant->nof_dmrs_cdm_groups_without_data > 3) { + ERROR("Invalid number of DMRS CDM groups without data (%d)", grant->nof_dmrs_cdm_groups_without_data); + return SRSLTE_ERROR; + } + + grant->beta_dmrs = srslte_convert_dB_to_amplitude(-ratio_dB[grant->nof_dmrs_cdm_groups_without_data - 1]); + + return SRSLTE_SUCCESS; +} + #define RA_UL_PUCCH_CODE_RATE_N 8 #define RA_UL_PUCCH_CODE_RATE_RESERVED NAN