diff --git a/lib/include/srsran/asn1/rrc_nr_utils.h b/lib/include/srsran/asn1/rrc_nr_utils.h index bb5ad0326..53939bfd6 100644 --- a/lib/include/srsran/asn1/rrc_nr_utils.h +++ b/lib/include/srsran/asn1/rrc_nr_utils.h @@ -73,7 +73,7 @@ void to_asn1(asn1::rrc_nr::plmn_id_s* asn1_type, const plmn_id_t& cfg); bool make_phy_rach_cfg(const asn1::rrc_nr::rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* prach_cfg); bool make_phy_tdd_cfg(const asn1::rrc_nr::tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, - srsran_tdd_config_nr_t* srsran_tdd_config_nr); + srsran_duplex_config_nr_t* srsran_duplex_config_nr); bool make_phy_harq_ack_cfg(const asn1::rrc_nr::phys_cell_group_cfg_s& phys_cell_group_cfg, srsran_harq_ack_cfg_hl_t* srsran_ue_dl_nr_harq_ack_cfg); bool make_phy_coreset_cfg(const asn1::rrc_nr::ctrl_res_set_s& ctrl_res_set, srsran_coreset_t* srsran_coreset); diff --git a/lib/include/srsran/common/phy_cfg_nr.h b/lib/include/srsran/common/phy_cfg_nr.h index e3985ce21..5a2f3d116 100644 --- a/lib/include/srsran/common/phy_cfg_nr.h +++ b/lib/include/srsran/common/phy_cfg_nr.h @@ -35,16 +35,16 @@ struct phy_cfg_nr_t { srsran_subcarrier_spacing_t scs = srsran_subcarrier_spacing_30kHz; }; - srsran_tdd_config_nr_t tdd = {}; - srsran_sch_hl_cfg_nr_t pdsch = {}; - srsran_sch_hl_cfg_nr_t pusch = {}; - srsran_pucch_nr_hl_cfg_t pucch = {}; - srsran_prach_cfg_t prach = {}; - srsran_pdcch_cfg_nr_t pdcch = {}; - srsran_harq_ack_cfg_hl_t harq_ack = {}; - srsran_csi_hl_cfg_t csi = {}; - srsran_carrier_nr_t carrier = {}; - ssb_cfg_t ssb; + srsran_duplex_config_nr_t duplex = {}; + srsran_sch_hl_cfg_nr_t pdsch = {}; + srsran_sch_hl_cfg_nr_t pusch = {}; + srsran_pucch_nr_hl_cfg_t pucch = {}; + srsran_prach_cfg_t prach = {}; + srsran_pdcch_cfg_nr_t pdcch = {}; + srsran_harq_ack_cfg_hl_t harq_ack = {}; + srsran_csi_hl_cfg_t csi = {}; + srsran_carrier_nr_t carrier = {}; + ssb_cfg_t ssb; phy_cfg_nr_t() {} diff --git a/lib/include/srsran/common/phy_cfg_nr_default.h b/lib/include/srsran/common/phy_cfg_nr_default.h index b5758dd8f..82e9ef7a2 100644 --- a/lib/include/srsran/common/phy_cfg_nr_default.h +++ b/lib/include/srsran/common/phy_cfg_nr_default.h @@ -43,18 +43,23 @@ public: const std::array R_CARRIER_STRING = {{"10MHz", "20MHz"}}; enum { + /** + * @brief FDD, all slots for DL and UL + */ + R_DUPLEX_FDD = 0, + /** * @brief TDD custom reference 5 slot DL and 5 slot UL */ - R_TDD_CUSTOM_6_4 = 0, + R_DUPLEX_TDD_CUSTOM_6_4, /** * @brief TDD pattern FR1.15-1 defined in TS38.101-4 Table A.1.2-1 */ - R_TDD_FR1_15_1, - R_TDD_COUNT, - } tdd = R_TDD_CUSTOM_6_4; - const std::array R_TDD_STRING = {{"6D+4U", "FR1.15-1"}}; + R_DUPLEX_TDD_FR1_15_1, + R_DUPLEX_COUNT, + } duplex = R_DUPLEX_TDD_CUSTOM_6_4; + const std::array R_DUPLEX_STRING = {{"FDD", "6D+4U", "FR1.15-1"}}; enum { /** @@ -144,8 +149,8 @@ private: /** * TDD make helper methods */ - static void make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd); - static void make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd); + static void make_tdd_custom_6_4(srsran_duplex_config_nr_t& duplex); + static void make_tdd_fr1_15_1(srsran_duplex_config_nr_t& duplex); /** * PDCCH make helper methods @@ -171,9 +176,9 @@ private: /** * HARQ make helper methods */ - static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, - const srsran_carrier_nr_t& carrier, - const srsran_tdd_config_nr_t& tdd_cfg); + static void make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_duplex_config_nr_t& duplex_cfg); /** * PRACH make helper methods diff --git a/lib/include/srsran/phy/common/phy_common_nr.h b/lib/include/srsran/phy/common/phy_common_nr.h index 309cbfe92..87a679fbd 100644 --- a/lib/include/srsran/phy/common/phy_common_nr.h +++ b/lib/include/srsran/phy/common/phy_common_nr.h @@ -458,6 +458,17 @@ typedef struct SRSRAN_API { srsran_tdd_pattern_t pattern2; } srsran_tdd_config_nr_t; +/** + * @brief Describes duplex configuration + */ +typedef struct SRSRAN_API { + srsran_duplex_mode_t mode; + union { + srsran_tdd_config_nr_t tdd; ///< TDD configuration + // ... add here other mode parameters + }; +} srsran_duplex_config_nr_t; + /** * @brief Describes a measurement based on NZP-CSI-RS or SSB-CSI * @note Used for tracking RSRP, SNR, CFO, SFO, and so on @@ -593,21 +604,21 @@ SRSRAN_API float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subca /** * @brief Decides whether a given slot is configured as Downlink - * @param cfg Provides TDD configuration + * @param cfg Provides the carrier duplex configuration * @param numerology Provides BWP numerology * @param slot_idx Slot index in the frame for the given numerology * @return true if the provided slot index is configured for Downlink */ -SRSRAN_API bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); +SRSRAN_API bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); /** * @brief Decides whether a given slot is configured as Uplink - * @param cfg Provides TDD configuration + * @param cfg Provides the carrier duplex configuration * @param numerology Provides BWP numerology * @param slot_idx Slot index in the frame for the given numerology * @return true if the provided slot index is configured for Uplink */ -SRSRAN_API bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); +SRSRAN_API bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); SRSRAN_API int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell); diff --git a/lib/src/asn1/rrc_nr_utils.cc b/lib/src/asn1/rrc_nr_utils.cc index 679b38067..6d8e4d82a 100644 --- a/lib/src/asn1/rrc_nr_utils.cc +++ b/lib/src/asn1/rrc_nr_utils.cc @@ -271,21 +271,21 @@ bool make_phy_rach_cfg(const rach_cfg_common_s& asn1_type, srsran_prach_cfg_t* p }; bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, - srsran_tdd_config_nr_t* in_srsran_tdd_config_nr) + srsran_duplex_config_nr_t* in_srsran_duplex_config_nr) { - srsran_tdd_config_nr_t srsran_tdd_config_nr = {}; + srsran_duplex_config_nr_t srsran_duplex_config_nr = {}; switch (tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity) { case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: - srsran_tdd_config_nr.pattern1.period_ms = 1; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 1; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: - srsran_tdd_config_nr.pattern1.period_ms = 2; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 2; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: - srsran_tdd_config_nr.pattern1.period_ms = 5; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 5; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: - srsran_tdd_config_nr.pattern1.period_ms = 10; + srsran_duplex_config_nr.tdd.pattern1.period_ms = 10; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: @@ -297,12 +297,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, tdd_ul_dl_cfg_common.pattern1.dl_ul_tx_periodicity.to_string()); return false; } - srsran_tdd_config_nr.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots; - srsran_tdd_config_nr.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols; - srsran_tdd_config_nr.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots; - srsran_tdd_config_nr.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols; + srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots = tdd_ul_dl_cfg_common.pattern1.nrof_dl_slots; + srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_dl_symbols; + srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots = tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots; + srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols; // Copy and return struct - *in_srsran_tdd_config_nr = srsran_tdd_config_nr; + *in_srsran_duplex_config_nr = srsran_duplex_config_nr; if (not tdd_ul_dl_cfg_common.pattern2_present) { return true; @@ -310,16 +310,16 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, switch (tdd_ul_dl_cfg_common.pattern2.dl_ul_tx_periodicity) { case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1: - srsran_tdd_config_nr.pattern2.period_ms = 1; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 1; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms2: - srsran_tdd_config_nr.pattern2.period_ms = 2; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 2; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms5: - srsran_tdd_config_nr.pattern2.period_ms = 5; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 5; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms10: - srsran_tdd_config_nr.pattern2.period_ms = 10; + srsran_duplex_config_nr.tdd.pattern2.period_ms = 10; break; case tdd_ul_dl_pattern_s::dl_ul_tx_periodicity_opts::ms1p25: @@ -332,12 +332,12 @@ bool make_phy_tdd_cfg(const tdd_ul_dl_cfg_common_s& tdd_ul_dl_cfg_common, return false; } - srsran_tdd_config_nr.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots; - srsran_tdd_config_nr.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols; - srsran_tdd_config_nr.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots; - srsran_tdd_config_nr.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols; + srsran_duplex_config_nr.tdd.pattern2.nof_dl_slots = tdd_ul_dl_cfg_common.pattern2.nrof_dl_slots; + srsran_duplex_config_nr.tdd.pattern2.nof_dl_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_dl_symbols; + srsran_duplex_config_nr.tdd.pattern2.nof_ul_slots = tdd_ul_dl_cfg_common.pattern2.nrof_ul_slots; + srsran_duplex_config_nr.tdd.pattern2.nof_ul_symbols = tdd_ul_dl_cfg_common.pattern2.nrof_ul_symbols; // Copy and return struct - *in_srsran_tdd_config_nr = srsran_tdd_config_nr; + *in_srsran_duplex_config_nr = srsran_duplex_config_nr; return true; } diff --git a/lib/src/common/phy_cfg_nr_default.cc b/lib/src/common/phy_cfg_nr_default.cc index 370e5ca57..487c92e73 100644 --- a/lib/src/common/phy_cfg_nr_default.cc +++ b/lib/src/common/phy_cfg_nr_default.cc @@ -44,13 +44,13 @@ phy_cfg_nr_default_t::reference_cfg_t::reference_cfg_t(const std::string& args) } } srsran_assert(carrier != R_CARRIER_COUNT, "Invalid carrier reference configuration '%s'", param.back().c_str()); - } else if (param.front() == "tdd") { - for (tdd = R_TDD_CUSTOM_6_4; tdd < R_TDD_COUNT; tdd = inc(tdd)) { - if (R_TDD_STRING[tdd] == param.back()) { + } else if (param.front() == "duplex") { + for (duplex = R_DUPLEX_FDD; duplex < R_DUPLEX_COUNT; duplex = inc(duplex)) { + if (R_DUPLEX_STRING[duplex] == param.back()) { break; } } - srsran_assert(tdd != R_TDD_COUNT, "Invalid TDD reference configuration '%s'", param.back().c_str()); + srsran_assert(duplex != R_DUPLEX_COUNT, "Invalid duplex reference configuration '%s'", param.back().c_str()); } else if (param.front() == "pdsch") { for (pdsch = R_PDSCH_DEFAULT; pdsch < R_PDSCH_COUNT; pdsch = inc(pdsch)) { if (R_PDSCH_STRING[pdsch] == param.back()) { @@ -86,8 +86,18 @@ void phy_cfg_nr_default_t::make_carrier_custom_20MHz(srsran_carrier_nr_t& carrie carrier.scs = srsran_subcarrier_spacing_15kHz; } -void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) +void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_duplex_config_nr_t& conf) { + // Set the duplex mode to TDD + conf.mode = SRSRAN_DUPLEX_MODE_TDD; + + // Select TDD config + srsran_tdd_config_nr_t& tdd = conf.tdd; + + // Initialise pattern + tdd = {}; + + // Enable pattern 1 tdd.pattern1.period_ms = 10; tdd.pattern1.nof_dl_slots = 6; tdd.pattern1.nof_dl_symbols = 0; @@ -98,8 +108,17 @@ void phy_cfg_nr_default_t::make_tdd_custom_6_4(srsran_tdd_config_nr_t& tdd) tdd.pattern2.period_ms = 0; } -void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_tdd_config_nr_t& tdd) -{ +void phy_cfg_nr_default_t::make_tdd_fr1_15_1(srsran_duplex_config_nr_t& conf) +{ // Set the duplex mode to TDD + conf.mode = SRSRAN_DUPLEX_MODE_TDD; + + // Select TDD config + srsran_tdd_config_nr_t& tdd = conf.tdd; + + // Initialise pattern + tdd = {}; + + // Enable pattern 1 tdd.pattern1.period_ms = 5; tdd.pattern1.nof_dl_slots = 3; tdd.pattern1.nof_dl_symbols = 10; @@ -319,32 +338,39 @@ void phy_cfg_nr_default_t::make_pucch_custom_one(srsran_pucch_nr_hl_cfg_t& pucch pucch.sr_resources[1].resource = resource_sr; } -void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, - const srsran_carrier_nr_t& carrier, - const srsran_tdd_config_nr_t& tdd_cfg) +void phy_cfg_nr_default_t::make_harq_auto(srsran_harq_ack_cfg_hl_t& harq, + const srsran_carrier_nr_t& carrier, + const srsran_duplex_config_nr_t& duplex_cfg) { - // Generate as many entries as DL slots - harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); - if (tdd_cfg.pattern1.nof_dl_symbols > 0) { - harq.nof_dl_data_to_ul_ack++; - } + if (duplex_cfg.mode == SRSRAN_DUPLEX_MODE_TDD) { + const srsran_tdd_config_nr_t& tdd_cfg = duplex_cfg.tdd; - // Set PDSCH to ACK timing delay to 4 or more - for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { - // Set the first slots into the first UL slot - if (harq.nof_dl_data_to_ul_ack >= 4 and n < (harq.nof_dl_data_to_ul_ack - 4)) { - harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n; - continue; + // Generate as many entries as DL slots + harq.nof_dl_data_to_ul_ack = SRSRAN_MIN(tdd_cfg.pattern1.nof_dl_slots, SRSRAN_MAX_NOF_DL_DATA_TO_UL); + if (tdd_cfg.pattern1.nof_dl_symbols > 0) { + harq.nof_dl_data_to_ul_ack++; } - // After that try if n+4 is UL slot - if (srsran_tdd_nr_is_ul(&tdd_cfg, carrier.scs, n + 4)) { - harq.dl_data_to_ul_ack[n] = 4; - continue; - } + // Set PDSCH to ACK timing delay to 4 or more + for (uint32_t n = 0; n < harq.nof_dl_data_to_ul_ack; n++) { + // Set the first slots into the first UL slot + if (harq.nof_dl_data_to_ul_ack >= 4 and n < (harq.nof_dl_data_to_ul_ack - 4)) { + harq.dl_data_to_ul_ack[n] = harq.nof_dl_data_to_ul_ack - n; + continue; + } + + // After that try if n+4 is UL slot + if (srsran_duplex_nr_is_ul(&duplex_cfg, carrier.scs, n + 4)) { + harq.dl_data_to_ul_ack[n] = 4; + continue; + } - // Otherwise set delay to the first UL slot of the next TDD period - harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n; + // Otherwise set delay to the first UL slot of the next TDD period + harq.dl_data_to_ul_ack[n] = (tdd_cfg.pattern1.period_ms + tdd_cfg.pattern1.nof_dl_slots) - n; + } + } else { + harq.dl_data_to_ul_ack[0] = 4; + harq.nof_dl_data_to_ul_ack = 1; } // Zero the rest @@ -377,14 +403,17 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) srsran_assertion_failure("Invalid carrier reference"); } - switch (reference_cfg.tdd) { - case reference_cfg_t::R_TDD_CUSTOM_6_4: - make_tdd_custom_6_4(tdd); + switch (reference_cfg.duplex) { + case reference_cfg_t::R_DUPLEX_FDD: + duplex.mode = SRSRAN_DUPLEX_MODE_FDD; + break; + case reference_cfg_t::R_DUPLEX_TDD_CUSTOM_6_4: + make_tdd_custom_6_4(duplex); break; - case reference_cfg_t::R_TDD_FR1_15_1: - make_tdd_fr1_15_1(tdd); + case reference_cfg_t::R_DUPLEX_TDD_FR1_15_1: + make_tdd_fr1_15_1(duplex); break; - case reference_cfg_t::R_TDD_COUNT: + case reference_cfg_t::R_DUPLEX_COUNT: srsran_assertion_failure("Invalid TDD reference"); } @@ -419,7 +448,7 @@ phy_cfg_nr_default_t::phy_cfg_nr_default_t(const reference_cfg_t& reference_cfg) switch (reference_cfg.harq) { case reference_cfg_t::R_HARQ_AUTO: - make_harq_auto(harq_ack, carrier, tdd); + make_harq_auto(harq_ack, carrier, duplex); break; } diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 39269ee6d..9a33ac176 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -283,13 +283,8 @@ float srsran_symbol_distance_s(uint32_t l0, uint32_t l1, srsran_subcarrier_spaci return srsran_symbol_offset_s(l1, scs) - srsran_symbol_offset_s(l0, scs); } -bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +static bool tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) { - // Protect NULL pointer access - if (cfg == NULL) { - return false; - } - // Prevent zero division if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { return false; @@ -312,13 +307,24 @@ bool srsran_tdd_nr_is_dl(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, (slot_idx_period == pattern->nof_dl_slots && pattern->nof_dl_symbols != 0)); } -bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +bool srsran_duplex_nr_is_dl(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) + { // Protect NULL pointer access if (cfg == NULL) { return false; } + // In case of TDD + if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) { + return tdd_nr_is_dl(&cfg->tdd, numerology, slot_idx); + } + + return true; +} + +static bool tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ // Prevent zero division if (cfg->pattern1.period_ms == 0 && cfg->pattern2.period_ms == 0) { return false; @@ -343,6 +349,21 @@ bool srsran_tdd_nr_is_ul(const srsran_tdd_config_nr_t* cfg, uint32_t numerology, return (slot_idx_period > start_ul || (slot_idx_period == start_ul && pattern->nof_ul_symbols != 0)); } +bool srsran_duplex_nr_is_ul(const srsran_duplex_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ + // Protect NULL pointer access + if (cfg == NULL) { + return false; + } + + // In case of TDD + if (cfg->mode == SRSRAN_DUPLEX_MODE_TDD) { + return tdd_nr_is_ul(&cfg->tdd, numerology, slot_idx); + } + + return true; +} + int srsran_carrier_to_cell(const srsran_carrier_nr_t* carrier, srsran_cell_t* cell) { // Protect memory access diff --git a/lib/test/asn1/rrc_nr_utils_test.cc b/lib/test/asn1/rrc_nr_utils_test.cc index 6dfc6b234..8f5eb999b 100644 --- a/lib/test/asn1/rrc_nr_utils_test.cc +++ b/lib/test/asn1/rrc_nr_utils_test.cc @@ -88,15 +88,15 @@ int make_phy_tdd_cfg_test() tdd_ul_dl_cfg_common.pattern1.nrof_ul_slots = 2; tdd_ul_dl_cfg_common.pattern1.nrof_ul_symbols = 4; - srsran_tdd_config_nr_t srsran_tdd_config_nr; - TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_tdd_config_nr) == true); - - TESTASSERT(srsran_tdd_config_nr.pattern1.period_ms == 10); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_slots == 7); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_dl_symbols == 6); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_slots == 2); - TESTASSERT(srsran_tdd_config_nr.pattern1.nof_ul_symbols == 4); - TESTASSERT(srsran_tdd_config_nr.pattern2.period_ms == 0); + srsran_duplex_config_nr_t srsran_duplex_config_nr; + TESTASSERT(make_phy_tdd_cfg(tdd_ul_dl_cfg_common, &srsran_duplex_config_nr) == true); + + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.period_ms == 10); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_slots == 7); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_dl_symbols == 6); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_slots == 2); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern1.nof_ul_symbols == 4); + TESTASSERT(srsran_duplex_config_nr.tdd.pattern2.period_ms == 0); return SRSRAN_SUCCESS; } diff --git a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h index 48ea5c197..b8fb7c94a 100644 --- a/srsenb/hdr/stack/mac/nr/sched_nr_interface.h +++ b/srsenb/hdr/stack/mac/nr/sched_nr_interface.h @@ -60,7 +60,7 @@ public: struct cell_cfg_t { srsran_carrier_nr_t carrier = {}; - srsran_tdd_config_nr_t tdd = {}; + srsran_duplex_config_nr_t duplex = {}; srsran::phy_cfg_nr_t::ssb_cfg_t ssb = {}; srsran::bounded_vector bwps{1}; // idx0 for BWP-common }; diff --git a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc index 1b42e8066..04f7ecaa6 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_cfg.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_cfg.cc @@ -37,8 +37,8 @@ bwp_params::bwp_params(const cell_cfg_t& cell, const sched_cfg_t& sched_cfg_, ui uint32_t nof_slots = SRSRAN_NSLOTS_PER_FRAME_NR(cfg.numerology_idx); for (size_t sl = 0; sl < nof_slots; ++sl) { slot_cfg sl_cfg{}; - sl_cfg.is_dl = srsran_tdd_nr_is_dl(&cell_cfg.tdd, cfg.numerology_idx, sl); - sl_cfg.is_ul = srsran_tdd_nr_is_ul(&cell_cfg.tdd, cfg.numerology_idx, sl); + sl_cfg.is_dl = srsran_duplex_nr_is_dl(&cell_cfg.duplex, cfg.numerology_idx, sl); + sl_cfg.is_ul = srsran_duplex_nr_is_ul(&cell_cfg.duplex, cfg.numerology_idx, sl); slots.push_back(sl_cfg); } diff --git a/srsenb/src/stack/mac/nr/sched_nr_ue.cc b/srsenb/src/stack/mac/nr/sched_nr_ue.cc index a0bb2177b..528f2d123 100644 --- a/srsenb/src/stack/mac/nr/sched_nr_ue.cc +++ b/srsenb/src/stack/mac/nr/sched_nr_ue.cc @@ -61,15 +61,15 @@ slot_ue ue_carrier::try_reserve(slot_point pdcch_slot, sfu.dl_pending_bytes = dl_pending_bytes; sfu.ul_pending_bytes = ul_pending_bytes; - const srsran_tdd_config_nr_t& tdd_cfg = cell_params.cell_cfg.tdd; - if (srsran_tdd_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { + const srsran_duplex_config_nr_t& tdd_cfg = cell_params.cell_cfg.duplex; + if (srsran_duplex_nr_is_dl(&tdd_cfg, 0, sfu.pdsch_slot.slot_idx())) { // If DL enabled sfu.h_dl = harq_ent.find_pending_dl_retx(); if (sfu.h_dl == nullptr and sfu.dl_pending_bytes > 0) { sfu.h_dl = harq_ent.find_empty_dl_harq(); } } - if (srsran_tdd_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) { + if (srsran_duplex_nr_is_ul(&tdd_cfg, 0, sfu.pusch_slot.slot_idx())) { // If UL enabled sfu.h_ul = harq_ent.find_pending_ul_retx(); if (sfu.h_ul == nullptr and sfu.ul_pending_bytes > 0) { diff --git a/srsenb/test/mac/nr/sched_nr_cfg_generators.h b/srsenb/test/mac/nr/sched_nr_cfg_generators.h index 310c63a6e..683e0d060 100644 --- a/srsenb/test/mac/nr/sched_nr_cfg_generators.h +++ b/srsenb/test/mac/nr/sched_nr_cfg_generators.h @@ -36,7 +36,7 @@ inline sched_nr_interface::cell_cfg_t get_default_cell_cfg( sched_nr_interface::cell_cfg_t cell_cfg{}; cell_cfg.carrier = phy_cfg.carrier; - cell_cfg.tdd = phy_cfg.tdd; + cell_cfg.duplex = phy_cfg.duplex; cell_cfg.bwps.resize(1); cell_cfg.bwps[0].pdcch = phy_cfg.pdcch; diff --git a/srsenb/test/mac/nr/sched_nr_test.cc b/srsenb/test/mac/nr/sched_nr_test.cc index fccf4ee9e..d793f0c4b 100644 --- a/srsenb/test/mac/nr/sched_nr_test.cc +++ b/srsenb/test/mac/nr/sched_nr_test.cc @@ -82,7 +82,7 @@ void sched_nr_cfg_serialized_test() uint32_t max_nof_ttis = 1000, nof_sectors = 4; task_job_manager tasks; - sched_nr_interface::sched_cfg_t cfg; + sched_nr_interface::sched_cfg_t cfg; cfg.auto_refill_buffer = true; std::vector cells_cfg = get_default_cells_cfg(nof_sectors); @@ -111,7 +111,7 @@ void sched_nr_cfg_serialized_test() sched_nr_cc_output_res_t out{slot_tx, cc, &dl_res, &ul_res}; sched_tester.update(out); tasks.finish_cc(slot_rx, dl_res, ul_res); - TESTASSERT(not srsran_tdd_nr_is_dl(&cells_cfg[cc].tdd, 0, (slot_tx).slot_idx()) or + TESTASSERT(not srsran_duplex_nr_is_dl(&cells_cfg[cc].duplex, 0, (slot_tx).slot_idx()) or dl_res.dl_sched.pdcch_dl.size() == 1); } } diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 1d7d12f75..1abf645d4 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -475,7 +475,7 @@ bool cc_worker::work_dl() } // Check if it is a DL slot, if not skip - if (!srsran_tdd_nr_is_dl(&phy.cfg.tdd, 0, dl_slot_cfg.idx)) { + if (!srsran_duplex_nr_is_dl(&phy.cfg.duplex, 0, dl_slot_cfg.idx)) { return true; } @@ -523,7 +523,7 @@ bool cc_worker::work_ul() bool has_ul_ack = phy.get_pending_ack(ul_slot_cfg.idx, pdsch_ack); // Check if it is a UL slot, if not skip - if (!srsran_tdd_nr_is_ul(&phy.cfg.tdd, 0, ul_slot_cfg.idx)) { + if (!srsran_duplex_nr_is_ul(&phy.cfg.duplex, 0, ul_slot_cfg.idx)) { // No NR signal shall be transmitted srsran_vec_cf_zero(tx_buffer[0], ue_ul.ifft.sf_sz); diff --git a/srsue/src/stack/rrc/rrc_nr.cc b/srsue/src/stack/rrc/rrc_nr.cc index 636534793..cc7d8a14b 100644 --- a/srsue/src/stack/rrc/rrc_nr.cc +++ b/srsue/src/stack/rrc/rrc_nr.cc @@ -1193,11 +1193,11 @@ bool rrc_nr::apply_sp_cell_cfg(const sp_cell_cfg_s& sp_cell_cfg) } if (recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common_present) { - srsran_tdd_config_nr_t tdd; - if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &tdd) == true) { - phy_cfg.tdd = tdd; + srsran_duplex_config_nr_t duplex; + if (make_phy_tdd_cfg(recfg_with_sync.sp_cell_cfg_common.tdd_ul_dl_cfg_common, &duplex) == true) { + phy_cfg.duplex = duplex; } else { - logger.warning("Warning while building tdd structure"); + logger.warning("Warning while building duplex structure"); return false; } } else { diff --git a/test/phy/CMakeLists.txt b/test/phy/CMakeLists.txt index f76226e2e..5644bffb2 100644 --- a/test/phy/CMakeLists.txt +++ b/test/phy/CMakeLists.txt @@ -25,15 +25,18 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ${Boost_LIBRARIES} ${ATOMIC_LIBS}) + # For each supported bandwidth foreach (NR_PHY_TEST_BW "10MHz" "20MHz") - foreach (NR_PHY_TEST_TDD "6D+4U" "FR1.15-1") + # For each supported frame structure + foreach (NR_PHY_TEST_DUPLEX "FDD" "6D+4U" "FR1.15-1") set(NR_PHY_TEST_DURATION_MS 20) + # DL flooding only foreach (NR_PHY_TEST_PDSCH "default" "ts38101/5.2-1") - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD},pdsch=${NR_PHY_TEST_PDSCH} + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_dl_${NR_PHY_TEST_PDSCH} nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX},pdsch=${NR_PHY_TEST_PDSCH} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots + --gnb.stack.pdsch.slots=all --gnb.stack.pdsch.start=0 # Start at RB 0 --gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.mcs=27 # Maximum MCS @@ -43,11 +46,12 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) ) endforeach () - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_ul_only nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} + # UL flooding + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_ul_only nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=6 # No PDSCH - --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots + --gnb.stack.pdsch.slots=none + --gnb.stack.pusch.slots=all --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS @@ -55,14 +59,15 @@ if (RF_FOUND AND ENABLE_SRSUE AND ENABLE_SRSENB) --ue.phy.nof_threads=${NR_PHY_TEST_UE_NOF_THREADS} ) - add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_TDD}_bidir nr_phy_test - --reference=carrier=${NR_PHY_TEST_BW},tdd=${NR_PHY_TEST_TDD} + # DL and UL flooding + add_nr_test(nr_phy_test_${NR_PHY_TEST_BW}_${NR_PHY_TEST_DUPLEX}_bidir nr_phy_test + --reference=carrier=${NR_PHY_TEST_BW},duplex=${NR_PHY_TEST_DUPLEX} --duration=${NR_PHY_TEST_DURATION_MS} - --gnb.stack.pdsch.slots=0,1,2,3,4,5 # All possible DL slots + --gnb.stack.pdsch.slots=all --gnb.stack.pdsch.start=0 # Start at RB 0 --gnb.stack.pdsch.length=52 # Full 10 MHz BW --gnb.stack.pdsch.mcs=28 # Maximum MCS - --gnb.stack.pusch.slots=6,7,8,9 # All possible UL slots + --gnb.stack.pusch.slots=all --gnb.stack.pusch.start=0 # Start at RB 0 --gnb.stack.pusch.length=52 # Full 10 MHz BW --gnb.stack.pusch.mcs=28 # Maximum MCS diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 66ac4636b..d487e8aa4 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -360,10 +360,22 @@ public: ul.mcs = args.pusch.mcs; if (args.pdsch.slots != "none" and not args.pdsch.slots.empty()) { - srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); + if (args.pdsch.slots == "all") { + for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { + dl.slots.insert(n); + } + } else { + srsran::string_parse_list(args.pdsch.slots, ',', dl.slots); + } } if (args.pusch.slots != "none" and not args.pusch.slots.empty()) { - srsran::string_parse_list(args.pusch.slots, ',', ul.slots); + if (args.pusch.slots == "all") { + for (uint32_t n = 0; n < SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); n++) { + ul.slots.insert(n); + } + } else { + srsran::string_parse_list(args.pusch.slots, ',', ul.slots); + } } // Select DCI locations @@ -405,7 +417,11 @@ public: // Setup DL Data to ACK timing for (uint32_t i = 0; i < SRSRAN_NOF_SF_X_FRAME; i++) { - dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.tdd.pattern1.period_ms]; + if (args.phy_cfg.duplex.mode == SRSRAN_DUPLEX_MODE_TDD) { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.duplex.tdd.pattern1.period_ms]; + } else { + dl_data_to_ul_ack[i] = args.phy_cfg.harq_ack.dl_data_to_ul_ack[i % args.phy_cfg.harq_ack.nof_dl_data_to_ul_ack]; + } } // If reached this point the configuration is valid @@ -441,7 +457,7 @@ public: } // Check if it is TDD DL slot and PDSCH mask, if no PDSCH shall be scheduled, do not set any grant and skip - if (not srsran_tdd_nr_is_dl(&phy_cfg.tdd, phy_cfg.carrier.scs, slot_cfg.idx)) { + if (not srsran_duplex_nr_is_dl(&phy_cfg.duplex, phy_cfg.carrier.scs, slot_cfg.idx)) { return SRSRAN_SUCCESS; } @@ -451,7 +467,7 @@ public: } // Check if the UL slot is valid, if not skip UL scheduling - if (not srsran_tdd_nr_is_ul(&phy_cfg.tdd, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { + if (not srsran_duplex_nr_is_ul(&phy_cfg.duplex, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { return SRSRAN_SUCCESS; }