From 2421f2cd9935300ea0b697d13dc1fb30710b83b4 Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Fri, 29 Jan 2021 16:43:40 +0100 Subject: [PATCH] Multiple PHY fixes and NR-PHY configuration refactor --- .../srslte/phy/ch_estimation/dmrs_sch.h | 8 +- lib/include/srslte/phy/common/phy_common_nr.h | 36 ++++- lib/include/srslte/phy/phch/dci_nr.h | 12 +- lib/include/srslte/phy/phch/phch_cfg_nr.h | 37 ++++- lib/include/srslte/phy/phch/ra_dl_nr.h | 21 +-- lib/include/srslte/phy/phch/ra_nr.h | 9 +- lib/include/srslte/phy/ue/ue_dl_nr.h | 14 +- lib/src/phy/ch_estimation/dmrs_sch.c | 87 +++++------ .../phy/ch_estimation/test/dmrs_pdcch_test.c | 2 +- .../phy/ch_estimation/test/dmrs_pdsch_test.c | 41 +++-- lib/src/phy/common/phy_common_nr.c | 26 ++++ lib/src/phy/enb/enb_dl_nr.c | 9 +- lib/src/phy/phch/dci_nr.c | 14 +- lib/src/phy/phch/pdsch_nr.c | 20 ++- lib/src/phy/phch/pusch_nr.c | 5 +- lib/src/phy/phch/ra_dl_nr.c | 142 +++++++++++++----- lib/src/phy/phch/ra_nr.c | 77 +++++++--- lib/src/phy/phch/test/pdsch_nr_test.c | 4 +- lib/src/phy/phch/test/sch_nr_test.c | 2 +- lib/src/phy/sync/cfo.c | 2 +- lib/src/phy/ue/ue_dl_nr.c | 39 ++--- lib/test/phy/phy_dl_nr_test.c | 6 +- srsenb/hdr/phy/nr/cc_worker.h | 2 +- srsenb/src/phy/nr/cc_worker.cc | 17 ++- srsenb/src/phy/nr/sf_worker.cc | 9 +- srsue/hdr/phy/nr/cc_worker.h | 56 ++++--- srsue/src/phy/nr/cc_worker.cc | 113 ++++++++------ 27 files changed, 510 insertions(+), 300 deletions(-) diff --git a/lib/include/srslte/phy/ch_estimation/dmrs_sch.h b/lib/include/srslte/phy/ch_estimation/dmrs_sch.h index 6dc7493f6..3726427ff 100644 --- a/lib/include/srslte/phy/ch_estimation/dmrs_sch.h +++ b/lib/include/srslte/phy/ch_estimation/dmrs_sch.h @@ -47,12 +47,12 @@ typedef struct { /** * @brief Computes the symbol indexes carrying DMRS and stores them in symbols_idx - * @param pdsch_cfg PDSCH configuration provided by upper layers + * @param dmrs_cfg DMRS configuration * @param grant PDSCH information provided by a DCI * @param symbols_idx is the destination pointer where the symbols indexes are stored * @return It returns the number of symbols if inputs are valid, otherwise, it returns SRSLTE_ERROR code. */ -SRSLTE_API int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* pdsch_cfg, +SRSLTE_API int srslte_dmrs_sch_get_symbols_idx(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslte_sch_grant_nr_t* grant, uint32_t symbols_idx[SRSLTE_DMRS_SCH_MAX_SYMBOLS]); @@ -69,11 +69,11 @@ SRSLTE_API int srslte_dmrs_sch_get_sc_idx(const srslte_dmrs_sch_cfg_t* cfg, uint /** * @brief Calculates the number of resource elements taken by a PDSCH-DMRS for a given PDSCH transmission - * @param pdsch_cfg PDSCH configuration provided by upper layers + * @param dmrs_cfg PDSCH-DMRS configuration * @param grant PDSCH information provided by a DCI * @return it returns the number of resource elements if the configuration is valid, otherwise it returns SRSLTE_ERROR */ -SRSLTE_API int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant); +SRSLTE_API int srslte_dmrs_sch_get_N_prb(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslte_sch_grant_nr_t* grant); /** * @brief Stringifies the PDSCH DMRS configuration diff --git a/lib/include/srslte/phy/common/phy_common_nr.h b/lib/include/srslte/phy/common/phy_common_nr.h index ff16eecc7..4c02cc13f 100644 --- a/lib/include/srslte/phy/common/phy_common_nr.h +++ b/lib/include/srslte/phy/common/phy_common_nr.h @@ -130,15 +130,26 @@ typedef enum SRSLTE_API { */ typedef enum SRSLTE_API { srslte_sch_mapping_type_A = 0, srslte_sch_mapping_type_B } srslte_sch_mapping_type_t; +/** + * @brief Search spaces + * @remark Described in TS 38.213 V15.10.0 Section 10.1 UE procedure for determining physical downlink control channel + * assignment + */ typedef enum SRSLTE_API { - srslte_search_space_type_common = 0, - srslte_search_space_type_common_0, - srslte_search_space_type_common_0A, - srslte_search_space_type_common_1, - srslte_search_space_type_common_2, - srslte_search_space_type_ue, + srslte_search_space_type_common_0 = 0, ///< configured by pdcch-ConfigSIB1 in MIB or by searchSpaceSIB1 in + ///< PDCCH-ConfigCommon or by searchSpaceZero in PDCCH-ConfigCommon + srslte_search_space_type_common_0A, ///< configured by searchSpaceOtherSystemInformation in PDCCH-ConfigCommon + srslte_search_space_type_common_1, ///< configured by ra-SearchSpace in PDCCH-ConfigCommon + srslte_search_space_type_common_2, ///< configured by pagingSearchSpace in PDCCH-ConfigCommon + srslte_search_space_type_common_3, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = common + srslte_search_space_type_ue, ///< configured by SearchSpace in PDCCH-Config with searchSpaceType = ue-Specific } srslte_search_space_type_t; +/** + * @brief Helper macro to get if a search space type is common or not + */ +#define SRSLTE_SEARCH_SPACE_IS_COMMON(SS_TYPE) ((SS_TYPE) < srslte_search_space_type_ue) + /** * @brief Indicates the MCS table the UE shall use for PDSCH and/or PUSCH without transform precoding */ @@ -160,7 +171,7 @@ typedef enum SRSLTE_API { srslte_rnti_type_tc, srslte_rnti_type_cs, srslte_rnti_type_sp_csi, - srslte_rnti_type_mcs_crnti, + srslte_rnti_type_mcs_c, } srslte_rnti_type_t; /** @@ -321,6 +332,17 @@ SRSLTE_API srslte_mcs_table_t srslte_mcs_table_from_str(const char* str); */ SRSLTE_API uint32_t srslte_min_symbol_sz_rb(uint32_t nof_prb); +/** + * @brief Computes the time in seconds between two symbols in a slot + * @note l0 is expected to be smaller than l1 + * @remark All symbol size reference and values are taken from TS 38.211 section 5.3 OFDM baseband signal generation + * @param l0 First symbol index within the slot + * @param l1 Second symbol index within the slot + * @param numerology NR Carrier numerology + * @return Returns the time in seconds between the two symbols if the condition above is satisfied, 0 seconds otherwise + */ +SRSLTE_API float srslte_symbol_distance_s(uint32_t l0, uint32_t l1, uint32_t numerology); + #ifdef __cplusplus } #endif diff --git a/lib/include/srslte/phy/phch/dci_nr.h b/lib/include/srslte/phy/phch/dci_nr.h index bc66bf066..eeb6c81ad 100644 --- a/lib/include/srslte/phy/phch/dci_nr.h +++ b/lib/include/srslte/phy/phch/dci_nr.h @@ -20,6 +20,7 @@ typedef struct SRSLTE_API { srslte_dci_location_t location; srslte_search_space_type_t search_space; + uint32_t coreset_id; uint8_t payload[50]; srslte_rnti_type_t rnti_type; uint32_t nof_bits; @@ -28,11 +29,12 @@ typedef struct SRSLTE_API { } srslte_dci_msg_nr_t; typedef struct SRSLTE_API { - uint16_t rnti; - srslte_rnti_type_t rnti_type; - srslte_dci_format_nr_t format; - srslte_dci_location_t location; - srslte_search_space_t search_space; + uint16_t rnti; + srslte_rnti_type_t rnti_type; + srslte_dci_format_nr_t format; + srslte_dci_location_t location; + srslte_search_space_type_t search_space; + uint32_t coreset_id; // Common fields uint32_t freq_domain_assigment; ///< Frequency domain resource assignment diff --git a/lib/include/srslte/phy/phch/phch_cfg_nr.h b/lib/include/srslte/phy/phch/phch_cfg_nr.h index aa73c9540..b1a7a0953 100644 --- a/lib/include/srslte/phy/phch/phch_cfg_nr.h +++ b/lib/include/srslte/phy/phch/phch_cfg_nr.h @@ -114,7 +114,7 @@ typedef struct SRSLTE_API { srslte_sch_mapping_type_t mapping; /// Frequency domain resources - bool prb_idx[SRSLTE_MAX_PRB_NR]; + bool prb_idx[SRSLTE_MAX_PRB_NR]; uint32_t nof_prb; /// Number of DMRS groups without data @@ -144,21 +144,48 @@ typedef struct SRSLTE_API { * @remark Described in TS 38.331 V15.10.0 Section PUSCH-Config */ typedef struct SRSLTE_API { + srslte_dmrs_sch_typeA_pos_t typeA_pos; bool scrambling_id_present; uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023) - srslte_dmrs_sch_cfg_t dmrs_typeA; + struct { + srslte_dmrs_sch_type_t type; + srslte_dmrs_sch_add_pos_t additional_pos; + srslte_dmrs_sch_len_t length; + bool scrambling_id0_present; + uint32_t scrambling_id0; + bool scrambling_id1_present; + uint32_t scrambling_id1; + } dmrs_typeA; + + bool dmrs_typeA_present; srslte_dmrs_sch_cfg_t dmrs_typeB; - srslte_sch_grant_nr_t grant; + bool dmrs_typeB_present; + + srslte_pdsch_time_ra_t common_pdsch_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION]; + uint32_t nof_common_pdsch_time_ra; - bool pdsch_time_is_default; ///< Set to true if pdsch_time_ra contains the configuration from pdsch-ConfigCommon or - ///< pdsch-Config srslte_pdsch_time_ra_t pdsch_time_ra[SRSLTE_MAX_NOF_DL_ALLOCATION]; + uint32_t nof_pdsch_time_ra; bool rbg_size_cfg_1; ///< RBG size configuration (1 or 2) srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters +} srslte_pdsch_cfg_nr_t; + +/** + * @brief Common NR-SCH (PDSCH and PUSCH for NR) configuration + */ +typedef struct SRSLTE_API { + + bool scrambling_id_present; + uint32_t scambling_id; // Identifier used to initialize data scrambling (0-1023) + + srslte_dmrs_sch_cfg_t dmrs; + srslte_sch_grant_nr_t grant; + + srslte_sch_cfg_t sch_cfg; ///< Common shared channel parameters /// Uplink params bool enable_transform_precoder; diff --git a/lib/include/srslte/phy/phch/ra_dl_nr.h b/lib/include/srslte/phy/phch/ra_dl_nr.h index 5437aa962..194525b1f 100644 --- a/lib/include/srslte/phy/phch/ra_dl_nr.h +++ b/lib/include/srslte/phy/phch/ra_dl_nr.h @@ -36,13 +36,15 @@ * @param pdsch_cfg Flattened PDSCH configuration provided from higher layers * @param rnti_type Type of the RNTI of the corresponding DCI * @param ss_type Type of the SS for PDCCH + * @param coreset_id CORESET identifier associated with the PDCCH transmission * @param m Time domain resource assignment field value m provided in DCI * @param[out] Provides grant pointer to fill * @return Returns SRSLTE_SUCCESS if the provided allocation is valid, otherwise it returns SRSLTE_ERROR code */ -SRSLTE_API int srslte_ra_dl_nr_time(const srslte_sch_cfg_nr_t* pdsch_cfg, +SRSLTE_API int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg, const srslte_rnti_type_t rnti_type, const srslte_search_space_type_t ss_type, + const uint32_t coreset_id, const uint8_t m, srslte_sch_grant_nr_t* grant); @@ -65,12 +67,12 @@ srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_type * * @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 cfg PDSCH-DMRS 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_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_sch_cfg_nr_t* pdsch_cfg, - srslte_sch_grant_nr_t* grant); +SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_dmrs_sch_cfg_t* cfg, + srslte_sch_grant_nr_t* grant); /** * @brief Calculates the PDSCH frequency resource allocation and stores it in the provided PDSCH NR grant. @@ -80,12 +82,11 @@ SRSLTE_API int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const * @param cfg PDSCH NR configuration by upper layers * @param dci_dl Unpacked DCI used to schedule the PDSCH grant * @param[out] grant Provides grant pointer to fill - * @return + * @return SRSLTE_SUCCESS if the provided data is valid, SRSLTE_ERROR code otherwise */ -SRSLTE_API int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier, - const srslte_sch_cfg_nr_t* cfg, - const srslte_dci_dl_nr_t* dci_dl, - srslte_sch_grant_nr_t* grant); - +SRSLTE_API int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier, + const srslte_pdsch_cfg_nr_t* cfg, + const srslte_dci_dl_nr_t* dci_dl, + srslte_sch_grant_nr_t* grant); #endif // SRSLTE_RA_DL_NR_H diff --git a/lib/include/srslte/phy/phch/ra_nr.h b/lib/include/srslte/phy/phch/ra_nr.h index 5fdc0a944..2f24d861f 100644 --- a/lib/include/srslte/phy/phch/ra_nr.h +++ b/lib/include/srslte/phy/phch/ra_nr.h @@ -95,9 +95,10 @@ SRSLTE_API int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg, * @param pdsch_grant Generated PDSCH grant * @return 0 on success, -1 on error */ -SRSLTE_API int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier, - const srslte_sch_cfg_nr_t* pdsch_cfg, - const srslte_dci_dl_nr_t* dci_dl, - srslte_sch_grant_nr_t* pdsch_grant); +SRSLTE_API int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier, + const srslte_pdsch_cfg_nr_t* pdsch_cfg, + const srslte_dci_dl_nr_t* dci_dl, + srslte_sch_cfg_nr_t* cfg, + srslte_sch_grant_nr_t* pdsch_grant); #endif // SRSLTE_RA_NR_H diff --git a/lib/include/srslte/phy/ue/ue_dl_nr.h b/lib/include/srslte/phy/ue/ue_dl_nr.h index 700d6aa2d..98e429eb5 100644 --- a/lib/include/srslte/phy/ue/ue_dl_nr.h +++ b/lib/include/srslte/phy/ue/ue_dl_nr.h @@ -48,10 +48,10 @@ typedef struct SRSLTE_API { srslte_search_space_t search_space[SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE]; bool search_space_present[SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE]; - uint32_t ra_rnti; ///< Deduced from the PRACH configuration - uint32_t ra_search_space_id; - uint32_t ra_search_space_present; -} srslte_ue_dl_nr_pdcch_cfg_t; + uint16_t ra_rnti; ///< Needs to be deduced from the PRACH configuration + srslte_search_space_t ra_search_space; + bool ra_search_space_present; +} srslte_ue_dl_nr_cfg_t; typedef struct SRSLTE_API { uint32_t max_prb; @@ -59,8 +59,8 @@ typedef struct SRSLTE_API { float pdcch_dmrs_corr_thr; float pdcch_dmrs_epre_thr; - srslte_carrier_nr_t carrier; - srslte_ue_dl_nr_pdcch_cfg_t cfg; + srslte_carrier_nr_t carrier; + srslte_ue_dl_nr_cfg_t cfg; srslte_ofdm_t fft[SRSLTE_MAX_PORTS]; @@ -79,7 +79,7 @@ srslte_ue_dl_nr_init(srslte_ue_dl_nr_t* q, cf_t* input[SRSLTE_MAX_PORTS], const SRSLTE_API int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t* carrier); -SRSLTE_API int srslte_ue_dl_nr_set_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_pdcch_cfg_t* cfg); +SRSLTE_API int srslte_ue_dl_nr_set_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_cfg_t* cfg); SRSLTE_API void srslte_ue_dl_nr_free(srslte_ue_dl_nr_t* q); diff --git a/lib/src/phy/ch_estimation/dmrs_sch.c b/lib/src/phy/ch_estimation/dmrs_sch.c index 6f382d6d5..0ba0a9fcb 100644 --- a/lib/src/phy/ch_estimation/dmrs_sch.c +++ b/lib/src/phy/ch_estimation/dmrs_sch.c @@ -12,6 +12,7 @@ #include "srslte/phy/ch_estimation/dmrs_sch.h" #include "srslte/phy/common/sequence.h" +#include #include #define SRSLTE_DMRS_SCH_TYPEA_SINGLE_DURATION_MIN 3 @@ -163,13 +164,12 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q, uint32_t delta, cf_t* symbols) { - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB; - uint32_t prb_count = 0; // Counts consecutive used PRB - uint32_t prb_start = 0; // Start consecutive used PRB - uint32_t prb_skip = 0; // Number of PRB to skip - uint32_t nof_pilots_x_prb = dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4; - uint32_t pilot_count = 0; + 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 + uint32_t prb_skip = 0; // Number of PRB to skip + uint32_t nof_pilots_x_prb = dmrs_cfg->type == srslte_dmrs_sch_type_1 ? 6 : 4; + uint32_t pilot_count = 0; // Initialise sequence srslte_sequence_state_t sequence_state = {}; @@ -209,8 +209,7 @@ static int srslte_dmrs_sch_put_symbol(srslte_dmrs_sch_t* q, } if (prb_count > 0) { - 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); } return pilot_count; @@ -350,7 +349,7 @@ static int srslte_dmrs_sch_get_symbols_idx_mapping_type_A_double(const srslte_dm return count; } -int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* cfg, +int srslte_dmrs_sch_get_symbols_idx(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslte_sch_grant_nr_t* grant, uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS]) { @@ -363,9 +362,6 @@ int srslte_dmrs_sch_get_symbols_idx(const srslte_sch_cfg_nr_t* cfg, ld = grant->S + grant->L; } - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB; - switch (grant->mapping) { case srslte_sch_mapping_type_A: // The case dmrs-AdditionalPosition equals to 'pos3' is only supported when dmrs-TypeA-Position is equal to 'pos2' @@ -417,11 +413,8 @@ int srslte_dmrs_sch_get_sc_idx(const srslte_dmrs_sch_cfg_t* cfg, uint32_t max_co return count; } -int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_grant_nr_t* grant) +int srslte_dmrs_sch_get_N_prb(const srslte_dmrs_sch_cfg_t* dmrs_cfg, const srslte_sch_grant_nr_t* grant) { - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_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); @@ -434,7 +427,7 @@ int srslte_dmrs_sch_get_N_prb(const srslte_sch_cfg_nr_t* cfg, const srslte_sch_g // Get number of symbols used for DMRS uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; - int ret = srslte_dmrs_sch_get_symbols_idx(cfg, grant, symbols); + int ret = srslte_dmrs_sch_get_symbols_idx(dmrs_cfg, grant, symbols); if (ret < SRSLTE_SUCCESS) { ERROR("Error getting PDSCH DMRS symbol indexes\n"); return SRSLTE_ERROR; @@ -449,8 +442,7 @@ static uint32_t srslte_dmrs_sch_seed(const srslte_carrier_nr_t* carrier, uint32_t slot_idx, uint32_t symbol_idx) { - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB; + const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs; slot_idx = slot_idx % SRSLTE_NSLOTS_PER_FRAME_NR(carrier->numerology); @@ -570,7 +562,7 @@ int srslte_dmrs_sch_put_sf(srslte_dmrs_sch_t* q, // Get symbols indexes uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; - int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols); + int nof_symbols = srslte_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols); if (nof_symbols < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } @@ -595,8 +587,7 @@ static int srslte_dmrs_sch_get_symbol(srslte_dmrs_sch_t* q, const cf_t* symbols, cf_t* least_square_estimates) { - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB; + 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 @@ -635,28 +626,16 @@ 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[prb_start * SRSLTE_NRE], - &least_square_estimates[pilot_count]); + pilot_count += srslte_dmrs_get_lse( + q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, 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[prb_start * SRSLTE_NRE], - &least_square_estimates[pilot_count]); + pilot_count += srslte_dmrs_get_lse( + q, &sequence_state, dmrs_cfg->type, prb_start, prb_count, delta, symbols, &least_square_estimates[pilot_count]); } return pilot_count; @@ -675,15 +654,14 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q, return SRSLTE_ERROR_INVALID_INPUTS; } - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_typeB; + const srslte_dmrs_sch_cfg_t* dmrs_cfg = &pdsch_cfg->dmrs; cf_t* ce = q->temp; uint32_t symbol_sz = q->carrier.nof_prb * SRSLTE_NRE; // Symbol size in resource elements // Get symbols indexes uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; - int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols); + int nof_symbols = srslte_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols); if (nof_symbols <= SRSLTE_SUCCESS) { ERROR("Error getting symbol indexes\n"); return SRSLTE_ERROR; @@ -706,17 +684,19 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q, } } - float rsrp = 0.0f; - float epre = 0.0f; + // Perform Power measurements + float rsrp = 0.0f; + float epre = 0.0f; + cf_t corr[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; for (uint32_t i = 0; i < nof_symbols; i++) { - cf_t corr = + corr[i] = srslte_vec_acc_cc(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol) / nof_pilots_x_symbol; - rsrp += __real__ corr * __real__ corr + __imag__ corr * __imag__ corr; + rsrp += __real__ corr[i] * __real__ corr[i] + __imag__ corr[i] * __imag__ corr[i]; epre += srslte_vec_avg_power_cf(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol); } rsrp /= nof_symbols; epre /= nof_symbols; - rsrp = SRSLTE_MIN(rsrp, epre); + rsrp = SRSLTE_MIN(rsrp, epre - epre * 1e-7); chest_res->rsrp = rsrp; chest_res->rsrp_dbm = srslte_convert_power_to_dB(chest_res->rsrp); @@ -726,8 +706,17 @@ int srslte_dmrs_sch_estimate(srslte_dmrs_sch_t* q, chest_res->snr_db = chest_res->rsrp_dbm - chest_res->noise_estimate_dbm; - // Perform measurements here - // ... + // Measure CFO if more than one symbol is used + float cfo_avg = 0.0; + for (uint32_t i = 0; i < nof_symbols - 1; i++) { + float time_diff = srslte_symbol_distance_s(symbols[i], symbols[i + 1], q->carrier.numerology); + float phase_diff = cargf(corr[i + 1] * conjf(corr[i])); + + if (isnormal(time_diff)) { + cfo_avg += phase_diff / (2.0f * M_PI * time_diff * (nof_symbols - 1)); + } + } + chest_res->cfo = cfo_avg; // Average over time, only if more than one DMRS symbol for (uint32_t i = 1; i < nof_symbols; i++) { diff --git a/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c b/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c index 7789e210a..7aac79286 100644 --- a/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c +++ b/lib/src/phy/ch_estimation/test/dmrs_pdcch_test.c @@ -143,7 +143,7 @@ int main(int argc, char** argv) for (coreset.duration = 1; coreset.duration <= 3; coreset.duration++) { - for (search_space.type = srslte_search_space_type_common; search_space.type <= srslte_search_space_type_ue; + for (search_space.type = srslte_search_space_type_common_0; search_space.type <= srslte_search_space_type_ue; search_space.type++) { for (uint32_t i = 0; i < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; i++) { 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 4d2ceb6b2..7dd0b1079 100644 --- a/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c +++ b/lib/src/phy/ch_estimation/test/dmrs_pdsch_test.c @@ -168,24 +168,24 @@ static int assert_cfg(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_gra continue; } - if (pdsch_cfg->dmrs_typeA.typeA_pos != gold[i].typeA_pos) { + if (pdsch_cfg->dmrs.typeA_pos != gold[i].typeA_pos) { continue; } - if (pdsch_cfg->dmrs_typeA.additional_pos != gold[i].additional_pos) { + if (pdsch_cfg->dmrs.additional_pos != gold[i].additional_pos) { continue; } - if (pdsch_cfg->dmrs_typeA.length != gold[i].max_length) { + if (pdsch_cfg->dmrs.length != gold[i].max_length) { continue; } - if (pdsch_cfg->dmrs_typeA.type != gold[i].type) { + if (pdsch_cfg->dmrs.type != gold[i].type) { continue; } uint32_t symbols[SRSLTE_DMRS_SCH_MAX_SYMBOLS] = {}; - int nof_symbols = srslte_dmrs_sch_get_symbols_idx(pdsch_cfg, grant, symbols); + int nof_symbols = srslte_dmrs_sch_get_symbols_idx(&pdsch_cfg->dmrs, grant, symbols); TESTASSERT(nof_symbols == gold[i].nof_symbols); @@ -194,7 +194,7 @@ static int assert_cfg(const srslte_sch_cfg_nr_t* pdsch_cfg, const srslte_sch_gra } uint32_t sc[SRSLTE_NRE] = {}; - srslte_dmrs_sch_get_sc_idx(&pdsch_cfg->dmrs_typeA, SRSLTE_NRE, sc); + srslte_dmrs_sch_get_sc_idx(&pdsch_cfg->dmrs, SRSLTE_NRE, sc); for (uint32_t j = 0; j < gold[i].nof_sc; j++) { TESTASSERT(sc[j] == gold[i].sc_idx[j]); @@ -274,33 +274,32 @@ int main(int argc, char** argv) srslte_dmrs_sch_type_t type_begin = srslte_dmrs_sch_type_1; srslte_dmrs_sch_type_t type_end = srslte_dmrs_sch_type_2; - for (pdsch_cfg.dmrs_typeA.type = type_begin; pdsch_cfg.dmrs_typeA.type <= type_end; pdsch_cfg.dmrs_typeA.type++) { + for (pdsch_cfg.dmrs.type = type_begin; pdsch_cfg.dmrs.type <= type_end; pdsch_cfg.dmrs.type++) { srslte_dmrs_sch_typeA_pos_t typeA_pos_begin = srslte_dmrs_sch_typeA_pos_2; srslte_dmrs_sch_typeA_pos_t typeA_pos_end = srslte_dmrs_sch_typeA_pos_3; - for (pdsch_cfg.dmrs_typeA.typeA_pos = typeA_pos_begin; pdsch_cfg.dmrs_typeA.typeA_pos <= typeA_pos_end; - pdsch_cfg.dmrs_typeA.typeA_pos++) { + for (pdsch_cfg.dmrs.typeA_pos = typeA_pos_begin; pdsch_cfg.dmrs.typeA_pos <= typeA_pos_end; + pdsch_cfg.dmrs.typeA_pos++) { srslte_dmrs_sch_add_pos_t add_pos_begin = srslte_dmrs_sch_add_pos_2; srslte_dmrs_sch_add_pos_t add_pos_end = srslte_dmrs_sch_add_pos_3; - if (pdsch_cfg.dmrs_typeA.typeA_pos == srslte_dmrs_sch_typeA_pos_3) { + if (pdsch_cfg.dmrs.typeA_pos == srslte_dmrs_sch_typeA_pos_3) { add_pos_end = srslte_dmrs_sch_add_pos_1; } - for (pdsch_cfg.dmrs_typeA.additional_pos = add_pos_begin; pdsch_cfg.dmrs_typeA.additional_pos <= add_pos_end; - pdsch_cfg.dmrs_typeA.additional_pos++) { + for (pdsch_cfg.dmrs.additional_pos = add_pos_begin; pdsch_cfg.dmrs.additional_pos <= add_pos_end; + pdsch_cfg.dmrs.additional_pos++) { srslte_dmrs_sch_len_t max_len_begin = srslte_dmrs_sch_len_1; srslte_dmrs_sch_len_t max_len_end = srslte_dmrs_sch_len_2; // Only single DMRS symbols can have additional positions 2 and 3 - if (pdsch_cfg.dmrs_typeA.additional_pos == srslte_dmrs_sch_add_pos_2 || - pdsch_cfg.dmrs_typeA.additional_pos == srslte_dmrs_sch_add_pos_3) { + if (pdsch_cfg.dmrs.additional_pos == srslte_dmrs_sch_add_pos_2 || + pdsch_cfg.dmrs.additional_pos == srslte_dmrs_sch_add_pos_3) { max_len_end = srslte_dmrs_sch_len_1; } - for (pdsch_cfg.dmrs_typeA.length = max_len_begin; pdsch_cfg.dmrs_typeA.length <= max_len_end; - pdsch_cfg.dmrs_typeA.length++) { + for (pdsch_cfg.dmrs.length = max_len_begin; pdsch_cfg.dmrs.length <= max_len_end; pdsch_cfg.dmrs.length++) { for (uint32_t bw = 1; bw <= carrier.nof_prb; bw++) { @@ -312,21 +311,15 @@ int main(int argc, char** argv) grant.nof_dmrs_cdm_groups_without_data++) { // Load default type A grant - srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &grant); - - // Copy configuration - pdsch_cfg.dmrs_typeB = pdsch_cfg.dmrs_typeA; + srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &grant); int n = run_test(&dmrs_pdsch, &pdsch_cfg, &grant, sf_symbols, &chest_dl_res); if (n == SRSLTE_SUCCESS) { test_passed++; } else { - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant.mapping == srslte_sch_mapping_type_A ? &pdsch_cfg.dmrs_typeA : &pdsch_cfg.dmrs_typeB; - char str[64] = {}; - srslte_dmrs_sch_cfg_to_str(dmrs_cfg, str, 64); + srslte_dmrs_sch_cfg_to_str(&pdsch_cfg.dmrs, str, 64); ERROR("Test %d failed. %s.\n", test_counter, str); } diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 3b3cf498d..abc07dd00 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -96,3 +96,29 @@ uint32_t srslte_min_symbol_sz_rb(uint32_t nof_prb) return 0; } + +float srslte_symbol_distance_s(uint32_t l0, uint32_t l1, uint32_t numerology) +{ + // l0 must be smaller than l1 + if (l0 >= l1) { + return 0.0f; + } + + // Count number of symbols in between + uint32_t count = l1 - l0; + + // Compute at what symbol there is a longer CP + uint32_t cp_boundary = 7U << numerology; + + // Select whether extra CP shall be added + uint32_t extra_cp = 0; + if (l0 < cp_boundary && l1 >= cp_boundary) { + extra_cp = 16; + } + + // Compute reference FFT size + uint32_t N = (2048 + 144) * count + extra_cp; + + // Return symbol distance in microseconds + return (N << numerology) * SRSLTE_LTE_TS; +} diff --git a/lib/src/phy/enb/enb_dl_nr.c b/lib/src/phy/enb/enb_dl_nr.c index 10610ca3e..4c796d966 100644 --- a/lib/src/phy/enb/enb_dl_nr.c +++ b/lib/src/phy/enb/enb_dl_nr.c @@ -57,7 +57,7 @@ int srslte_enb_dl_nr_init(srslte_enb_dl_nr_t* q, cf_t* output[SRSLTE_MAX_PORTS], srslte_ofdm_cfg_t fft_cfg = {}; fft_cfg.nof_prb = args->nof_max_prb; - fft_cfg.symbol_sz = srslte_symbol_sz(args->nof_max_prb); + fft_cfg.symbol_sz = srslte_min_symbol_sz_rb(args->nof_max_prb); fft_cfg.keep_dc = true; for (uint32_t i = 0; i < q->nof_tx_antennas; i++) { @@ -118,8 +118,13 @@ int srslte_enb_dl_nr_set_carrier(srslte_enb_dl_nr_t* q, const srslte_carrier_nr_ } if (carrier->nof_prb != q->carrier.nof_prb) { + srslte_ofdm_cfg_t fft_cfg = {}; + fft_cfg.nof_prb = carrier->nof_prb; + fft_cfg.symbol_sz = srslte_min_symbol_sz_rb(carrier->nof_prb); + for (uint32_t i = 0; i < q->nof_tx_antennas; i++) { - srslte_ofdm_tx_set_prb(&q->fft[i], SRSLTE_CP_NORM, carrier->nof_prb); + fft_cfg.in_buffer = q->sf_symbols[i]; + srslte_ofdm_tx_init_cfg(&q->fft[i], &fft_cfg); } } diff --git a/lib/src/phy/phch/dci_nr.c b/lib/src/phy/phch/dci_nr.c index 355fbd64e..a64d83a97 100644 --- a/lib/src/phy/phch/dci_nr.c +++ b/lib/src/phy/phch/dci_nr.c @@ -42,7 +42,8 @@ int srslte_dci_nr_pack(const srslte_carrier_nr_t* carrier, { // Copy DCI MSG fields msg->location = dci->location; - msg->search_space = dci->search_space.type; + msg->search_space = dci->search_space; + msg->coreset_id = dci->coreset_id; msg->rnti_type = dci->rnti_type; msg->rnti = dci->rnti; msg->format = dci->format; @@ -180,11 +181,12 @@ int srslte_dci_nr_format_1_0_unpack(const srslte_carrier_nr_t* carrier, srslte_rnti_type_t rnti_type = msg->rnti_type; // Copy DCI MSG fields - dci->location = msg->location; - dci->search_space.type = msg->search_space; - dci->rnti_type = msg->rnti_type; - dci->rnti = msg->rnti; - dci->format = msg->format; + dci->location = msg->location; + dci->search_space = msg->search_space; + dci->coreset_id = msg->coreset_id; + dci->rnti_type = msg->rnti_type; + dci->rnti = msg->rnti; + dci->format = msg->format; if (msg->nof_bits != srslte_dci_nr_format_1_0_sizeof(carrier, coreset, rnti_type)) { ERROR("Invalid number of bits %d, expected %d\n", diff --git a/lib/src/phy/phch/pdsch_nr.c b/lib/src/phy/phch/pdsch_nr.c index 5a17af34c..a822b1402 100644 --- a/lib/src/phy/phch/pdsch_nr.c +++ b/lib/src/phy/phch/pdsch_nr.c @@ -282,8 +282,7 @@ static uint32_t srslte_pdsch_nr_cp_dmrs(const srslte_pdsch_nr_t* q, { uint32_t count = 0; - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB; + const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs; switch (dmrs_cfg->type) { case srslte_dmrs_sch_type_1: @@ -355,7 +354,7 @@ static int srslte_pdsch_nr_cp(const srslte_pdsch_nr_t* q, uint32_t dmrs_l_count = 0; // Get symbol indexes carrying DMRS - int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(cfg, grant, dmrs_l_idx); + int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, dmrs_l_idx); if (nof_dmrs_symbols < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } @@ -678,12 +677,23 @@ static uint32_t srslte_pdsch_nr_grant_info(const srslte_sch_cfg_nr_t* cfg, uint32_t len = 0; len = srslte_print_check(str, str_len, len, "rnti=0x%x", grant->rnti); + char freq_str[SRSLTE_MAX_PRB_NR + 1] = {}; + for (uint32_t i = 0, nof_prb = 0; i < SRSLTE_MAX_PRB_NR && nof_prb < grant->nof_prb; i++) { + if (grant->prb_idx[i]) { + freq_str[i] = '1'; + nof_prb++; + } else { + freq_str[i] = '0'; + } + } + // Append time-domain resource mapping len = srslte_print_check(str, str_len, len, - ",k0=%d,S=%d,L=%d,mapping=%s", + ",k0=%d,freq=%s,symb=%d:%d,mapping=%s", grant->k0, + freq_str, grant->S, grant->L, srslte_sch_mapping_type_to_str(grant->mapping)); @@ -748,7 +758,7 @@ uint32_t srslte_pdsch_nr_rx_info(const srslte_pdsch_nr_t* q, } if (q->meas_time_en) { - len = srslte_print_check(str, str_len, len, ", t=%d us\n", q->meas_time_us); + len = srslte_print_check(str, str_len, len, ", t=%d us", q->meas_time_us); } return len; diff --git a/lib/src/phy/phch/pusch_nr.c b/lib/src/phy/phch/pusch_nr.c index d7f146fb0..10e5364db 100644 --- a/lib/src/phy/phch/pusch_nr.c +++ b/lib/src/phy/phch/pusch_nr.c @@ -281,8 +281,7 @@ static uint32_t srslte_pusch_nr_cp_dmrs(const srslte_pusch_nr_t* q, { uint32_t count = 0; - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &cfg->dmrs_typeA : &cfg->dmrs_typeB; + const srslte_dmrs_sch_cfg_t* dmrs_cfg = &cfg->dmrs; switch (dmrs_cfg->type) { case srslte_dmrs_sch_type_1: @@ -354,7 +353,7 @@ static int srslte_pusch_nr_cp(const srslte_pusch_nr_t* q, uint32_t dmrs_l_count = 0; // Get symbol indexes carrying DMRS - int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(cfg, grant, dmrs_l_idx); + int32_t nof_dmrs_symbols = srslte_dmrs_sch_get_symbols_idx(&cfg->dmrs, grant, dmrs_l_idx); if (nof_dmrs_symbols < SRSLTE_SUCCESS) { return SRSLTE_ERROR; } diff --git a/lib/src/phy/phch/ra_dl_nr.c b/lib/src/phy/phch/ra_dl_nr.c index 68b6009a2..de0d2b8ac 100644 --- a/lib/src/phy/phch/ra_dl_nr.c +++ b/lib/src/phy/phch/ra_dl_nr.c @@ -12,16 +12,16 @@ #include "srslte/phy/phch/ra_dl_nr.h" #include "srslte/phy/utils/debug.h" -static void sliv_to_s_and_l(uint32_t sliv, uint32_t* S, uint32_t* L) +static void compute_s_and_l(uint32_t N, uint32_t v, uint32_t* S, uint32_t* L) { - // S values can be 0 to 3 - uint32_t low = sliv % 14; - if (low < 7) { + uint32_t low = v % N; + uint32_t high = v / N; + if (high + 1 + low <= N) { *S = low; - *L = sliv / 14 + 1; + *L = high + 1; } else { - *S = 14 - 1 - low; - *L = 14 - sliv / 14 + 1; + *S = N - 1 - low; + *L = N - high + 1; } } @@ -128,14 +128,16 @@ int srslte_ra_dl_nr_time_default_A(uint32_t m, srslte_dmrs_sch_typeA_pos_t dmrs_ void srslte_ra_dl_nr_time_hl(const srslte_pdsch_time_ra_t* hl_ra_cfg, srslte_sch_grant_nr_t* grant) { // Compute S and L from SLIV from higher layers - sliv_to_s_and_l(hl_ra_cfg->sliv, &grant->S, &grant->L); + compute_s_and_l(SRSLTE_NSYMB_PER_SLOT_NR, hl_ra_cfg->sliv, &grant->S, &grant->L); + grant->k0 = hl_ra_cfg->k0; grant->mapping = hl_ra_cfg->mapping_type; } -int srslte_ra_dl_nr_time(const srslte_sch_cfg_nr_t* cfg, +int srslte_ra_dl_nr_time(const srslte_pdsch_cfg_nr_t* cfg, const srslte_rnti_type_t rnti_type, const srslte_search_space_type_t ss_type, + const uint32_t coreset_id, const uint8_t m, srslte_sch_grant_nr_t* grant) { @@ -149,40 +151,72 @@ int srslte_ra_dl_nr_time(const srslte_sch_cfg_nr_t* cfg, return SRSLTE_ERROR_INVALID_INPUTS; } - // Determine which PDSCH Time domain RA configuration to apply (Table 5.1.2.1.1-1) - if (cfg->pdsch_time_is_default) { - // Note: Only Default A is supported, which corresponds SS/PBCH block and coreset mux pattern 1 - srslte_ra_dl_nr_time_default_A(m, cfg->dmrs_typeA.typeA_pos, grant); + // Determine which PDSCH Time domain RA configuration to apply (TS 38.214 Table 5.1.2.1.1-1) + if (rnti_type == srslte_rnti_type_si && ss_type == srslte_search_space_type_common_0) { + // Row 1 + ERROR("Row not implemented"); + } else if (rnti_type == srslte_rnti_type_si && ss_type == srslte_search_space_type_common_0A) { + // Row 2 + ERROR("Row not implemented"); + } else if ((rnti_type == srslte_rnti_type_ra || rnti_type == srslte_rnti_type_tc) && + ss_type == srslte_search_space_type_common_1) { + // Row 3 + if (cfg->nof_common_pdsch_time_ra > 0) { + srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant); + } else { + // Note: Only Default A is supported, which corresponds SS/PBCH block and coreset mux pattern 1 + srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant); + } + } else if (rnti_type == srslte_rnti_type_p && ss_type == srslte_search_space_type_common_2) { + // Row 4 + ERROR("Row not implemented"); + } else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c || + rnti_type == srslte_rnti_type_cs) && + SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id == 0) { + // Row 5 + if (cfg->nof_common_pdsch_time_ra > 0) { + srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant); + } else { + srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant); + } + } else if ((rnti_type == srslte_rnti_type_c || rnti_type == srslte_rnti_type_mcs_c || + rnti_type == srslte_rnti_type_cs) && + ((SRSLTE_SEARCH_SPACE_IS_COMMON(ss_type) && coreset_id != 0) || ss_type == srslte_search_space_type_ue)) { + // Row 6 + if (cfg->nof_pdsch_time_ra > 0) { + srslte_ra_dl_nr_time_hl(&cfg->pdsch_time_ra[m], grant); + } else if (cfg->nof_common_pdsch_time_ra > 0) { + srslte_ra_dl_nr_time_hl(&cfg->common_pdsch_time_ra[m], grant); + } else { + srslte_ra_dl_nr_time_default_A(m, cfg->typeA_pos, grant); + } } else { - srslte_ra_dl_nr_time_hl(&cfg->pdsch_time_ra[m], grant); + ERROR("Unhandled case"); } // Validate S and L parameters if (!srslte_ra_dl_nr_time_validate(grant)) { - ERROR("Invalid Time RA\n"); + ERROR("Invalid Time RA S=%d; L=%d; m=%d\n", grant->S, grant->L, m); return SRSLTE_ERROR; } return SRSLTE_SUCCESS; } -int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_sch_cfg_nr_t* pdsch_cfg, - srslte_sch_grant_nr_t* grant) +int srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(const srslte_dmrs_sch_cfg_t* cfg, + srslte_sch_grant_nr_t* grant) { - if (pdsch_cfg == NULL || grant == NULL) { + if (cfg == NULL || grant == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } - const srslte_dmrs_sch_cfg_t* dmrs_cfg = - grant->mapping == srslte_sch_mapping_type_A ? &pdsch_cfg->dmrs_typeA : &pdsch_cfg->dmrs_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. + * 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_sch_len_2) { + if (cfg->length == srslte_dmrs_sch_len_2) { grant->nof_dmrs_cdm_groups_without_data = 1; } else { grant->nof_dmrs_cdm_groups_without_data = 2; @@ -205,10 +239,10 @@ uint32_t srslte_ra_dl_nr_type0_P(uint32_t bwp_size, bool config_is_1) } } -static int ra_freq_type0(const srslte_carrier_nr_t* carrier, - const srslte_sch_cfg_nr_t* cfg, - const srslte_dci_dl_nr_t* dci_dl, - srslte_sch_grant_nr_t* grant) +static int ra_freq_type0(const srslte_carrier_nr_t* carrier, + const srslte_pdsch_cfg_nr_t* cfg, + const srslte_dci_dl_nr_t* dci_dl, + srslte_sch_grant_nr_t* grant) { uint32_t P = srslte_ra_dl_nr_type0_P(carrier->nof_prb, cfg->rbg_size_cfg_1); @@ -234,10 +268,42 @@ static int ra_freq_type0(const srslte_carrier_nr_t* carrier, return 0; } -int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier, - const srslte_sch_cfg_nr_t* cfg, - const srslte_dci_dl_nr_t* dci_dl, - srslte_sch_grant_nr_t* grant) +static int +ra_freq_type1(const srslte_carrier_nr_t* carrier, const srslte_dci_dl_nr_t* dci_dl, srslte_sch_grant_nr_t* grant) +{ + + uint32_t riv = dci_dl->freq_domain_assigment; + uint32_t N_bwp_size = carrier->nof_prb; + + uint32_t start = 0; + uint32_t len = 0; + compute_s_and_l(N_bwp_size, riv, &start, &len); + + if (start + len > N_bwp_size) { + ERROR("RIV 0x%x for BWP size %d resulted in freq=%d:%d\n", riv, N_bwp_size, start, len); + return SRSLTE_ERROR; + } + + for (uint32_t i = 0; i < start; i++) { + grant->prb_idx[i] = false; + } + + for (uint32_t i = start; i < start + len; i++) { + grant->prb_idx[i] = true; + } + + for (uint32_t i = start + len; i < SRSLTE_MAX_PRB_NR; i++) { + grant->prb_idx[i] = false; + } + grant->nof_prb = len; + + return SRSLTE_SUCCESS; +} + +int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier, + const srslte_pdsch_cfg_nr_t* cfg, + const srslte_dci_dl_nr_t* dci_dl, + srslte_sch_grant_nr_t* grant) { if (cfg == NULL || grant == NULL || dci_dl == NULL) { @@ -246,11 +312,11 @@ int srslte_ra_dl_nr_freq(const srslte_carrier_nr_t* carrier, // RA scheme if (dci_dl->format == srslte_dci_format_nr_1_0) { - ra_freq_type0(carrier, cfg, dci_dl, grant); - } else { - ERROR("Only DCI Format 1_0 is supported\n"); - return SRSLTE_ERROR; + // when the scheduling grant is received with DCI format 1_0 , then downlink resource allocation type 1 is used. + return ra_freq_type1(carrier, dci_dl, grant); } - return SRSLTE_SUCCESS; + ra_freq_type0(carrier, cfg, dci_dl, grant); + ERROR("Only DCI Format 1_0 is supported\n"); + return SRSLTE_ERROR; } diff --git a/lib/src/phy/phch/ra_nr.c b/lib/src/phy/phch/ra_nr.c index 8125f151d..7be424e03 100644 --- a/lib/src/phy/phch/ra_nr.c +++ b/lib/src/phy/phch/ra_nr.c @@ -139,7 +139,7 @@ static ra_nr_table_t ra_nr_select_table_pusch_noprecoding(srslte_mcs_table_t // - the UE is configured with MCS-C-RNTI, and // - the PUSCH is scheduled by a PDCCH with // - CRC scrambled by MCS-C-RNTI, - if (mcs_c_rnti && dci_format != srslte_dci_format_nr_rar && rnti_type == srslte_rnti_type_mcs_crnti) { + if (mcs_c_rnti && dci_format != srslte_dci_format_nr_rar && rnti_type == srslte_rnti_type_mcs_c) { return ra_nr_table_3; } @@ -275,7 +275,7 @@ int srslte_ra_dl_nr_slot_nof_re(const srslte_sch_cfg_nr_t* pdsch_cfg, const srsl int n_sh_symb = grant->L; // the number of REs for DM-RS per PRB in the scheduled duration - int n_prb_dmrs = srslte_dmrs_sch_get_N_prb(pdsch_cfg, grant); + int n_prb_dmrs = srslte_dmrs_sch_get_N_prb(&pdsch_cfg->dmrs, grant); if (n_prb_dmrs < SRSLTE_SUCCESS) { ERROR("Invalid number of DMRS RE\n"); return SRSLTE_ERROR; @@ -455,40 +455,79 @@ int srslte_ra_nr_fill_tb(const srslte_sch_cfg_nr_t* pdsch_cfg, return SRSLTE_SUCCESS; } -int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier, - const srslte_sch_cfg_nr_t* pdsch_cfg, - const srslte_dci_dl_nr_t* dci_dl, - srslte_sch_grant_nr_t* pdsch_grant) +static int ra_dl_dmrs(const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg, + srslte_sch_grant_nr_t* pdsch_grant, + srslte_dmrs_sch_cfg_t* dmrs_cfg) { - // Time domain resource allocation - if (srslte_ra_dl_nr_time( - pdsch_cfg, dci_dl->rnti_type, dci_dl->search_space.type, dci_dl->time_domain_assigment, pdsch_grant) < - SRSLTE_SUCCESS) { - ERROR("Error computing time domain resource allocation\n"); + const bool dedicated_dmrs_present = (pdsch_grant->mapping == srslte_sch_mapping_type_A) + ? pdsch_hl_cfg->dmrs_typeA_present + : pdsch_hl_cfg->dmrs_typeB_present; + + if (pdsch_grant->dci_format == srslte_dci_format_nr_1_0 || !dedicated_dmrs_present) { + + if (pdsch_grant->mapping == srslte_sch_mapping_type_A) { + // Absent default values are defined is TS 38.331 - DMRS-DownlinkConfig + dmrs_cfg->additional_pos = srslte_dmrs_sch_add_pos_2; + dmrs_cfg->type = srslte_dmrs_sch_type_1; + dmrs_cfg->length = srslte_dmrs_sch_len_1; + dmrs_cfg->scrambling_id0_present = false; + dmrs_cfg->scrambling_id1_present = false; + + if (pdsch_grant->dci_format == srslte_dci_format_nr_1_0) { + if (srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(dmrs_cfg, pdsch_grant) < SRSLTE_SUCCESS) { + ERROR("Error loading number of DMRS CDM groups\n"); + return SRSLTE_ERROR; + } + } + + return SRSLTE_SUCCESS; + } + + ERROR("Unsupported configuration\n"); return SRSLTE_ERROR; } - // Frequency domain resource allocation - if (srslte_ra_dl_nr_freq(carrier, pdsch_cfg, dci_dl, pdsch_grant) < SRSLTE_SUCCESS) { + return SRSLTE_ERROR; +} + +int srslte_ra_dl_dci_to_grant_nr(const srslte_carrier_nr_t* carrier, + const srslte_pdsch_cfg_nr_t* pdsch_hl_cfg, + const srslte_dci_dl_nr_t* dci_dl, + srslte_sch_cfg_nr_t* pdsch_cfg, + srslte_sch_grant_nr_t* pdsch_grant) +{ + // 5.2.1.1 Resource allocation in time domain + if (srslte_ra_dl_nr_time(pdsch_hl_cfg, + dci_dl->rnti_type, + dci_dl->search_space, + dci_dl->coreset_id, + dci_dl->time_domain_assigment, + pdsch_grant) < SRSLTE_SUCCESS) { ERROR("Error computing time domain resource allocation\n"); return SRSLTE_ERROR; } - //??? - if (srslte_ra_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\n"); + // 5.1.2.2 Resource allocation in frequency domain + if (srslte_ra_dl_nr_freq(carrier, pdsch_hl_cfg, dci_dl, pdsch_grant) < SRSLTE_SUCCESS) { + ERROR("Error computing frequency domain resource allocation\n"); return SRSLTE_ERROR; } + // 5.1.2.3 Physical resource block (PRB) bundling + // ... + pdsch_grant->nof_layers = 1; pdsch_grant->dci_format = dci_dl->format; pdsch_grant->rnti = dci_dl->rnti; + pdsch_grant->rnti_type = dci_dl->rnti_type; - for (uint32_t i = 0; i < carrier->nof_prb; i++) { - pdsch_grant->prb_idx[i] = true; + // 5.1.6.2 DM-RS reception procedure + if (ra_dl_dmrs(pdsch_hl_cfg, pdsch_grant, &pdsch_cfg->dmrs) < SRSLTE_SUCCESS) { + ERROR("Error selecting DMRS configuration"); + return SRSLTE_ERROR; } - // Compute TB size + // 5.1.3 Modulation order, target code rate, redundancy version and transport block size determination if (srslte_ra_nr_fill_tb(pdsch_cfg, pdsch_grant, dci_dl->mcs, &pdsch_grant->tb[0]) < SRSLTE_SUCCESS) { ERROR("Error filing tb\n"); return SRSLTE_ERROR; diff --git a/lib/src/phy/phch/test/pdsch_nr_test.c b/lib/src/phy/phch/test/pdsch_nr_test.c index b02921a95..8d8ab2bbf 100644 --- a/lib/src/phy/phch/test/pdsch_nr_test.c +++ b/lib/src/phy/phch/test/pdsch_nr_test.c @@ -153,13 +153,13 @@ int main(int argc, char** argv) } // Use grant default A time resources with m=0 - if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) { + if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) { ERROR("Error loading default grant\n"); goto clean_exit; } // Load number of DMRS CDM groups without data - if (srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&pdsch_cfg, &pdsch_grant) < SRSLTE_SUCCESS) { + if (srslte_ra_dl_nr_nof_dmrs_cdm_groups_without_data_format_1_0(&pdsch_cfg.dmrs, &pdsch_grant) < SRSLTE_SUCCESS) { ERROR("Error loading number of DMRS CDM groups without data\n"); goto clean_exit; } diff --git a/lib/src/phy/phch/test/sch_nr_test.c b/lib/src/phy/phch/test/sch_nr_test.c index 96f6a4589..ff0029eaf 100644 --- a/lib/src/phy/phch/test/sch_nr_test.c +++ b/lib/src/phy/phch/test/sch_nr_test.c @@ -132,7 +132,7 @@ int main(int argc, char** argv) } // Use grant default A time resources with m=0 - if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) { + if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) { ERROR("Error loading default grant\n"); goto clean_exit; } diff --git a/lib/src/phy/sync/cfo.c b/lib/src/phy/sync/cfo.c index a90eb1303..550cc80fa 100644 --- a/lib/src/phy/sync/cfo.c +++ b/lib/src/phy/sync/cfo.c @@ -137,4 +137,4 @@ float srslte_cfo_est_corr_cp(cf_t* input_buffer, uint32_t nof_prb) float cfo = (float)(-1 * carg(cfo_estimated) / (float)(2 * M_PI * tFFT)); srslte_vec_apply_cfo(input_buffer, (float)(1 / (nFFT * 15e3)) * ((-15e3 / 2.0) - cfo), input_buffer, sf_n_samples); return cfo; -} \ No newline at end of file +} diff --git a/lib/src/phy/ue/ue_dl_nr.c b/lib/src/phy/ue/ue_dl_nr.c index 6c34e6b29..93283b321 100644 --- a/lib/src/phy/ue/ue_dl_nr.c +++ b/lib/src/phy/ue/ue_dl_nr.c @@ -163,7 +163,7 @@ int srslte_ue_dl_nr_set_carrier(srslte_ue_dl_nr_t* q, const srslte_carrier_nr_t* return SRSLTE_SUCCESS; } -int srslte_ue_dl_nr_set_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_pdcch_cfg_t* cfg) +int srslte_ue_dl_nr_set_config(srslte_ue_dl_nr_t* q, const srslte_ue_dl_nr_cfg_t* cfg) { if (q == NULL || cfg == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; @@ -259,22 +259,19 @@ static int ue_dl_nr_find_dci_ncce(srslte_ue_dl_nr_t* q, return SRSLTE_SUCCESS; } -static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q, - const srslte_dl_slot_cfg_t* slot_cfg, - uint32_t search_space_id, - uint16_t rnti, - srslte_rnti_type_t rnti_type, - srslte_dci_dl_nr_t* dci_dl_list, - uint32_t nof_dci_msg) +static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q, + const srslte_dl_slot_cfg_t* slot_cfg, + const srslte_search_space_t* search_space, + uint16_t rnti, + srslte_rnti_type_t rnti_type, + srslte_dci_dl_nr_t* dci_dl_list, + uint32_t nof_dci_msg) { // Check inputs if (q == NULL || slot_cfg == NULL || dci_dl_list == NULL) { return SRSLTE_ERROR_INVALID_INPUTS; } - // Select Search space - srslte_search_space_t* search_space = &q->cfg.search_space[search_space_id]; - // Select CORESET uint32_t coreset_id = search_space->coreset_id; if (coreset_id >= SRSLTE_UE_DL_NR_MAX_NOF_CORESET || !q->cfg.coreset_present[coreset_id]) { @@ -317,6 +314,7 @@ static int ue_dl_nr_find_dl_dci_ss(srslte_ue_dl_nr_t* q, dci_msg.location.L = L; dci_msg.location.ncce = candidates[ncce_idx]; dci_msg.search_space = search_space->type; + dci_msg.coreset_id = search_space->coreset_id; dci_msg.rnti_type = rnti_type; dci_msg.rnti = rnti; dci_msg.format = dci_format; @@ -357,16 +355,9 @@ int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q, // If the UE looks for a RAR and RA search space is provided, search for it if (q->cfg.ra_search_space_present && rnti == q->cfg.ra_rnti) { - // Check if the RA search space is valid - uint32_t ra_ss_id = q->cfg.ra_search_space_id; - if (ra_ss_id >= SRSLTE_UE_DL_NR_MAX_NOF_SEARCH_SPACE || !q->cfg.search_space_present[ra_ss_id]) { - ERROR("Invalid RA Search Space ID (%d)", ra_ss_id); - return SRSLTE_ERROR; - } - // Find DCIs in the RA search space return ue_dl_nr_find_dl_dci_ss( - q, slot_cfg, ra_ss_id, rnti, srslte_rnti_type_ra, &dci_dl_list[count], nof_dci_msg - count); + q, slot_cfg, &q->cfg.ra_search_space, rnti, srslte_rnti_type_ra, &dci_dl_list[count], nof_dci_msg - count); } // Iterate all possible search spaces @@ -377,8 +368,8 @@ int srslte_ue_dl_nr_find_dl_dci(srslte_ue_dl_nr_t* q, } // Find DCIs in the selected search space - int ret = - ue_dl_nr_find_dl_dci_ss(q, slot_cfg, i, rnti, srslte_rnti_type_c, &dci_dl_list[count], nof_dci_msg - count); + int ret = ue_dl_nr_find_dl_dci_ss( + q, slot_cfg, &q->cfg.search_space[i], rnti, srslte_rnti_type_c, &dci_dl_list[count], nof_dci_msg - count); if (ret < SRSLTE_SUCCESS) { ERROR("Error searching DCI"); return SRSLTE_ERROR; @@ -422,11 +413,11 @@ int srslte_ue_dl_nr_pdsch_info(const srslte_ue_dl_nr_t* q, { int len = 0; - // Append channel estimator info - // ... - // Append PDSCH info len += srslte_pdsch_nr_rx_info(&q->pdsch, cfg, &cfg->grant, res, &str[len], str_len - len); + // Append channel estimator info + len = srslte_print_check(str, str_len, len, ",SNR=%+.1f", q->chest.snr_db); + return len; } diff --git a/lib/test/phy/phy_dl_nr_test.c b/lib/test/phy/phy_dl_nr_test.c index 6012f7a39..862ad5d8d 100644 --- a/lib/test/phy/phy_dl_nr_test.c +++ b/lib/test/phy/phy_dl_nr_test.c @@ -99,7 +99,7 @@ static int work_gnb_dl(srslte_enb_dl_nr_t* enb_dl, dci_dl->format = srslte_dci_format_nr_1_0; dci_dl->rnti_type = srslte_rnti_type_c; dci_dl->location = *dci_location; - dci_dl->search_space = *search_space; + dci_dl->search_space = search_space->type; dci_dl->rnti = rnti; // Put actual DCI @@ -189,7 +189,7 @@ int main(int argc, char** argv) goto clean_exit; } - srslte_ue_dl_nr_pdcch_cfg_t pdcch_cfg = {}; + srslte_ue_dl_nr_cfg_t pdcch_cfg = {}; // Configure CORESET srslte_coreset_t* coreset = &pdcch_cfg.coreset[0]; @@ -264,7 +264,7 @@ int main(int argc, char** argv) } // Use grant default A time resources with m=0 - if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs_typeA.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) { + if (srslte_ra_dl_nr_time_default_A(0, pdsch_cfg.dmrs.typeA_pos, &pdsch_grant) < SRSLTE_SUCCESS) { ERROR("Error loading default grant\n"); goto clean_exit; } diff --git a/srsenb/hdr/phy/nr/cc_worker.h b/srsenb/hdr/phy/nr/cc_worker.h index 159fd654f..70c634502 100644 --- a/srsenb/hdr/phy/nr/cc_worker.h +++ b/srsenb/hdr/phy/nr/cc_worker.h @@ -38,7 +38,7 @@ typedef struct { } phy_nr_args_t; typedef struct { - srslte_sch_cfg_nr_t pdsch; + srslte_pdsch_cfg_nr_t pdsch; } phy_nr_cfg_t; class phy_nr_state diff --git a/srsenb/src/phy/nr/cc_worker.cc b/srsenb/src/phy/nr/cc_worker.cc index 81248f56f..3d543187e 100644 --- a/srsenb/src/phy/nr/cc_worker.cc +++ b/srsenb/src/phy/nr/cc_worker.cc @@ -24,8 +24,8 @@ namespace srsenb { namespace nr { -cc_worker::cc_worker(uint32_t cc_idx_, srslog::basic_logger& logger, phy_nr_state* phy_state_) : - cc_idx(cc_idx_), phy_state(phy_state_), logger(logger) +cc_worker::cc_worker(uint32_t cc_idx_, srslte::log* log, phy_nr_state* phy_state_) : + cc_idx(cc_idx_), phy_state(phy_state_), log_h(log) { cf_t* buffer_c[SRSLTE_MAX_PORTS] = {}; @@ -118,8 +118,8 @@ int cc_worker::encode_pdcch_dl(stack_interface_phy_nr::dl_sched_grant_t* grants, return SRSLTE_ERROR; } - if (logger.info.enabled()) { - logger.info("PDCCH: cc=%d, ...", cc_idx); + if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) { + log_h->info("PDCCH: cc=%d, ...", cc_idx); } } @@ -132,10 +132,11 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui // Get PHY config for UE // ... - srslte_sch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch; + srslte_pdsch_cfg_nr_t pdsch_hl_cfg = {}; + srslte_sch_cfg_nr_t pdsch_cfg = {}; // Compute DL grant - if (srslte_ra_dl_dci_to_grant_nr(&enb_dl.carrier, &pdsch_cfg, &grants[i].dci, &pdsch_cfg.grant)) { + if (srslte_ra_dl_dci_to_grant_nr(&enb_dl.carrier, &pdsch_hl_cfg, &grants[i].dci, &pdsch_cfg, &pdsch_cfg.grant)) { ERROR("Computing DL grant"); } @@ -150,10 +151,10 @@ int cc_worker::encode_pdsch(stack_interface_phy_nr::dl_sched_grant_t* grants, ui } // Logging - if (logger.info.enabled()) { + if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) { char str[512]; srslte_enb_dl_nr_pdsch_info(&enb_dl, &pdsch_cfg, str, sizeof(str)); - logger.info("PDSCH: cc=%d, %s", cc_idx, str); + log_h->info("PDSCH: cc=%d, %s", cc_idx, str); } } diff --git a/srsenb/src/phy/nr/sf_worker.cc b/srsenb/src/phy/nr/sf_worker.cc index c5e93196a..0d142709f 100644 --- a/srsenb/src/phy/nr/sf_worker.cc +++ b/srsenb/src/phy/nr/sf_worker.cc @@ -98,8 +98,7 @@ void sf_worker::work_imp() } // Configure user - phy_state->cfg.pdsch.rbg_size_cfg_1 = false; - phy_state->cfg.pdsch.pdsch_time_is_default = true; + phy_state->cfg.pdsch.rbg_size_cfg_1 = false; // Fill grant (this comes from the scheduler) srslte_dl_slot_cfg_t dl_cfg = {}; @@ -117,10 +116,8 @@ void sf_worker::work_imp() grants.pdsch[0].dci.time_domain_assigment = 0; grants.pdsch[0].dci.mcs = 27; - grants.pdsch[0].dci.search_space.type = srslte_search_space_type_ue; - for (uint32_t L = 0; L < SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR; L++) { - grants.pdsch[0].dci.search_space.nof_candidates[L] = 1; - } + grants.pdsch[0].dci.search_space = srslte_search_space_type_ue; + grants.pdsch[0].dci.coreset_id = 1; grants.pdsch[0].dci.location.L = 0; grants.pdsch[0].dci.location.ncce = 0; diff --git a/srsue/hdr/phy/nr/cc_worker.h b/srsue/hdr/phy/nr/cc_worker.h index 9496b22e1..8dea39372 100644 --- a/srsue/hdr/phy/nr/cc_worker.h +++ b/srsue/hdr/phy/nr/cc_worker.h @@ -37,17 +37,18 @@ typedef struct { } phy_nr_args_t; typedef struct { - srslte_sch_cfg_nr_t pdsch; - srslte_prach_cfg_t prach; - srslte_ue_dl_nr_pdcch_cfg_t pdcch; + srslte_pdsch_cfg_nr_t pdsch; + srslte_prach_cfg_t prach; + srslte_ue_dl_nr_cfg_t pdcch; } phy_nr_cfg_t; class phy_nr_state { public: - srslte_carrier_nr_t carrier = {}; - phy_nr_args_t args = {}; - phy_nr_cfg_t cfg = {}; + srslte_carrier_nr_t carrier = {}; + phy_nr_args_t args = {}; + phy_nr_cfg_t cfg = {}; + int32_t test_rnti = 0x1234; // Fix PDSCH RNTI for testing phy_nr_state() { @@ -106,20 +107,40 @@ public: // searchSpaceType: common (0) // common // dci-Format0-0-AndFormat1-0 - cfg.pdcch.search_space[1].id = 1; - cfg.pdcch.search_space[1].coreset_id = 1; - cfg.pdcch.search_space[1].nof_candidates[0] = 0; - cfg.pdcch.search_space[1].nof_candidates[1] = 0; - cfg.pdcch.search_space[1].nof_candidates[2] = 1; - cfg.pdcch.search_space[1].nof_candidates[3] = 0; - cfg.pdcch.search_space[1].nof_candidates[4] = 0; - cfg.pdcch.search_space[1].type = srslte_search_space_type_common; - cfg.pdcch.search_space_present[1] = true; + srslte_search_space_t search_space1 = {}; + search_space1.id = 1; + search_space1.coreset_id = 1; + search_space1.nof_candidates[0] = 0; + search_space1.nof_candidates[1] = 0; + search_space1.nof_candidates[2] = 1; + search_space1.nof_candidates[3] = 0; + search_space1.nof_candidates[4] = 0; + search_space1.type = srslte_search_space_type_common_3; + cfg.pdcch.search_space[1] = search_space1; + cfg.pdcch.search_space_present[1] = true; // ra-SearchSpace: 1 cfg.pdcch.ra_rnti = 0x16; //< Supposed to be deduced from PRACH configuration - cfg.pdcch.ra_search_space_id = 1; + cfg.pdcch.ra_search_space = search_space1; + cfg.pdcch.ra_search_space.type = srslte_search_space_type_common_1; cfg.pdcch.ra_search_space_present = true; + + // pdsch-ConfigCommon: setup (1) + // setup + // pdsch-TimeDomainAllocationList: 2 items + // Item 0 + // PDSCH-TimeDomainResourceAllocation + // mappingType: typeA (0) + // startSymbolAndLength: 40 + // Item 1 + // PDSCH-TimeDomainResourceAllocation + // mappingType: typeA (0) + // startSymbolAndLength: 57 + cfg.pdsch.common_pdsch_time_ra[0].mapping_type = srslte_sch_mapping_type_A; + cfg.pdsch.common_pdsch_time_ra[0].sliv = 40; + cfg.pdsch.common_pdsch_time_ra[1].mapping_type = srslte_sch_mapping_type_A; + cfg.pdsch.common_pdsch_time_ra[1].sliv = 57; + cfg.pdsch.nof_common_pdsch_time_ra = 2; } }; @@ -152,9 +173,6 @@ private: // Temporal attributes srslte_softbuffer_rx_t softbuffer_rx = {}; std::vector data; - - // Current rnti - uint16_t rnti = 0; }; } // namespace nr diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index adb1a31b3..9cc0f5bcf 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -79,8 +79,7 @@ bool cc_worker::set_carrier(const srslte_carrier_nr_t* carrier) } // Set default PDSCH config - phy_state->cfg.pdsch.rbg_size_cfg_1 = false; - phy_state->cfg.pdsch.pdsch_time_is_default = true; + phy_state->cfg.pdsch.rbg_size_cfg_1 = false; return true; } @@ -106,64 +105,86 @@ uint32_t cc_worker::get_buffer_len() bool cc_worker::work_dl() { - srslte_dci_dl_nr_t dci_dl = {}; - srslte_sch_cfg_nr_t pdsch_cfg = phy_state->cfg.pdsch; - std::array pdsch_res = {}; + srslte_pdsch_cfg_nr_t pdsch_hl_cfg = phy_state->cfg.pdsch; // Run FFT srslte_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); - // Set rnti - rnti = phy_state->cfg.pdcch.ra_rnti; - - // if (dl_slot_cfg.idx % 10 ==1) { - // printf("a=");srslte_vec_fprint_c(stdout, rx_buffer[0], 512); - // } - - srslte_dci_dl_nr_t dci_dl_rx = {}; - int nof_found_dci = srslte_ue_dl_nr_find_dl_dci(&ue_dl, &dl_slot_cfg, rnti, &dci_dl_rx, 1); - if (nof_found_dci < SRSLTE_SUCCESS) { - ERROR("Error decoding"); - return SRSLTE_ERROR; + // Initialise grants + std::array dci_dl_rx = {}; + uint32_t nof_found_dci = 0; + + // Search for RA DCI + if (phy_state->cfg.pdcch.ra_search_space_present) { + int n_ra = srslte_ue_dl_nr_find_dl_dci(&ue_dl, + &dl_slot_cfg, + phy_state->cfg.pdcch.ra_rnti, + &dci_dl_rx[nof_found_dci], + (uint32_t)dci_dl_rx.size() - nof_found_dci); + if (n_ra < SRSLTE_SUCCESS) { + ERROR("Error decoding"); + return false; + } + nof_found_dci += n_ra; } - if (nof_found_dci < 1) { - // ERROR("Error DCI not found"); - return true; + // Search for test RNTI + if (phy_state->test_rnti > 0) { + int n_test = srslte_ue_dl_nr_find_dl_dci(&ue_dl, + &dl_slot_cfg, + (uint16_t)phy_state->test_rnti, + &dci_dl_rx[nof_found_dci], + (uint32_t)dci_dl_rx.size() - nof_found_dci); + if (n_test < SRSLTE_SUCCESS) { + ERROR("Error decoding"); + return false; + } + nof_found_dci += n_test; } - if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) { - char str[512]; - srslte_dci_nr_to_str(&dci_dl_rx, str, sizeof(str)); - log_h->info("PDCCH: cc=%d, %s", cc_idx, str); - } + // Notify MAC about PDCCH found grants + // ... - dci_dl.rnti = 0x1234; - dci_dl.format = srslte_dci_format_nr_1_0; + // Iterate over all received grants + for (uint32_t i = 0; i < nof_found_dci; i++) { + // Select Received DCI + const srslte_dci_dl_nr_t* dci_dl = &dci_dl_rx[i]; - dci_dl.freq_domain_assigment = 0x1FFF; - dci_dl.time_domain_assigment = 0; - dci_dl.mcs = 27; + // Log found DCI + if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) { + std::array str; + srslte_dci_nr_to_str(dci_dl, str.data(), str.size()); + log_h->info("PDCCH: cc=%d, %s", cc_idx, str.data()); + } - // Compute DL grant - if (srslte_ra_dl_dci_to_grant_nr(&ue_dl.carrier, &pdsch_cfg, &dci_dl, &pdsch_cfg.grant)) { - ERROR("Computing DL grant"); - } + // Compute DL grant + srslte_sch_cfg_nr_t pdsch_cfg = {}; + if (srslte_ra_dl_dci_to_grant_nr(&ue_dl.carrier, &pdsch_hl_cfg, dci_dl, &pdsch_cfg, &pdsch_cfg.grant)) { + ERROR("Computing DL grant"); + return false; + } - pdsch_res[0].payload = data.data(); - pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx; - srslte_softbuffer_rx_reset(pdsch_cfg.grant.tb[0].softbuffer.rx); + // Initialise PDSCH Result + std::array pdsch_res = {}; + pdsch_res[0].payload = data.data(); + pdsch_cfg.grant.tb[0].softbuffer.rx = &softbuffer_rx; + srslte_softbuffer_rx_reset(pdsch_cfg.grant.tb[0].softbuffer.rx); - if (srslte_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, pdsch_res.data()) < SRSLTE_SUCCESS) { - ERROR("Error decoding PDSCH"); - return false; - } + // Decode actual PDSCH transmission + if (srslte_ue_dl_nr_decode_pdsch(&ue_dl, &dl_slot_cfg, &pdsch_cfg, pdsch_res.data()) < SRSLTE_SUCCESS) { + ERROR("Error decoding PDSCH"); + return false; + } + + // Notify MAC about PDSCH decoding result + // ... - // Logging - if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) { - char str[512]; - srslte_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, pdsch_res.data(), str, sizeof(str)); - log_h->info("PDSCH: cc=%d, %s", cc_idx, str); + // Logging + if (log_h->get_level() >= srslte::LOG_LEVEL_INFO) { + std::array str; + srslte_ue_dl_nr_pdsch_info(&ue_dl, &pdsch_cfg, pdsch_res.data(), str.data(), str.size()); + log_h->info("PDSCH: cc=%d, %s", cc_idx, str.data()); + } } return true;