diff --git a/lib/include/srslte/interfaces/rrc_nr_interface_types.h b/lib/include/srslte/interfaces/rrc_nr_interface_types.h index 5c916b81c..7bc26936a 100644 --- a/lib/include/srslte/interfaces/rrc_nr_interface_types.h +++ b/lib/include/srslte/interfaces/rrc_nr_interface_types.h @@ -24,6 +24,7 @@ namespace srslte { **************************/ struct phy_cfg_nr_t { + srslte_tdd_config_nr_t tdd = {}; srslte_sch_hl_cfg_nr_t pdsch = {}; srslte_sch_hl_cfg_nr_t pusch = {}; srslte_pucch_nr_hl_cfg_t pucch = {}; @@ -34,9 +35,6 @@ struct phy_cfg_nr_t { phy_cfg_nr_t() { - // Default PDSCH configuration - pdsch.sch_cfg.mcs_table = srslte_mcs_table_256qam; - // Default PRACH configuration prach.is_nr = true; prach.config_idx = 16; @@ -46,6 +44,21 @@ struct phy_cfg_nr_t { prach.num_ra_preambles = 64; prach.hs_flag = false; + // tdd-UL-DL-ConfigurationCommon + // referenceSubcarrierSpacing: kHz15 (0) + // pattern1 + // dl-UL-TransmissionPeriodicity: ms10 (7) + // nrofDownlinkSlots: 7 + // nrofDownlinkSymbols: 6 + // nrofUplinkSlots: 2 + // nrofUplinkSymbols: 4 + tdd.pattern1.period_ms = 10; + tdd.pattern1.nof_dl_slots = 7; + tdd.pattern1.nof_dl_symbols = 6; + tdd.pattern1.nof_ul_slots = 2; + tdd.pattern1.nof_ul_symbols = 4; + tdd.pattern2.period_ms = 0; + // physicalCellGroupConfig // pdsch-HARQ-ACK-Codebook: dynamic (1) harq_ack.pdsch_harq_ack_codebook = srslte_pdsch_harq_ack_codebook_dynamic; diff --git a/lib/include/srslte/phy/common/phy_common_nr.h b/lib/include/srslte/phy/common/phy_common_nr.h index d490fe8a5..a416a9dbf 100644 --- a/lib/include/srslte/phy/common/phy_common_nr.h +++ b/lib/include/srslte/phy/common/phy_common_nr.h @@ -301,6 +301,25 @@ typedef struct SRSLTE_API { uint32_t nof_candidates[SRSLTE_SEARCH_SPACE_NOF_AGGREGATION_LEVELS_NR]; } srslte_search_space_t; +/** + * @brief TDD pattern configuration + */ +typedef struct SRSLTE_API { + uint32_t period_ms; ///< Period in milliseconds, set to 0 if not present + uint32_t nof_dl_slots; ///< Number of consecutive full DL slots at the beginning of each DL-UL pattern + uint32_t nof_dl_symbols; ///< Number of consecutive DL symbols in the beginning of the slot following the last DL slot + uint32_t nof_ul_slots; ///< Number of consecutive full UL slots at the end of each DL-UL pattern + uint32_t nof_ul_symbols; ///< Number of consecutive UL symbols in the end of the slot preceding the first full UL slot +} srslte_tdd_pattern_t; + +/** + * @brief TDD configuration as described in TS 38.331 v15.10.0 TDD-UL-DL-ConfigCommon + */ +typedef struct SRSLTE_API { + srslte_tdd_pattern_t pattern1; + srslte_tdd_pattern_t pattern2; +} srslte_tdd_config_nr_t; + /** * @brief Get the RNTI type name for NR * @param rnti_type RNTI type name @@ -372,6 +391,24 @@ SRSLTE_API uint32_t srslte_min_symbol_sz_rb(uint32_t nof_prb); */ SRSLTE_API float srslte_symbol_distance_s(uint32_t l0, uint32_t l1, uint32_t numerology); +/** + * @brief Decides whether a given slot is configured as Downlink + * @param cfg Provides TDD 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 + */ +SRSLTE_API bool srslte_tdd_nr_is_dl(const srslte_tdd_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 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 + */ +SRSLTE_API bool srslte_tdd_nr_is_ul(const srslte_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx); + #ifdef __cplusplus } #endif diff --git a/lib/src/phy/common/phy_common_nr.c b/lib/src/phy/common/phy_common_nr.c index 7dd120e98..b4f36d4b5 100644 --- a/lib/src/phy/common/phy_common_nr.c +++ b/lib/src/phy/common/phy_common_nr.c @@ -146,3 +146,49 @@ float srslte_symbol_distance_s(uint32_t l0, uint32_t l1, uint32_t numerology) // Return symbol distance in microseconds return (N << numerology) * SRSLTE_LTE_TS; } + +bool srslte_tdd_nr_is_dl(const srslte_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ + if (cfg == NULL) { + return false; + } + + // Calculate slot index within the TDD overall period + uint32_t slot_x_ms = 1U << numerology; // Number of slots per millisecond + uint32_t period_sum = (cfg->pattern1.period_ms + cfg->pattern2.period_ms) * slot_x_ms; // Total perdiod sum + uint32_t slot_idx_period = slot_idx % period_sum; // Slot index within the period + + // Select pattern + const srslte_tdd_pattern_t* pattern = &cfg->pattern1; + if ((slot_idx_period >= cfg->pattern1.period_ms * slot_x_ms)) { + pattern = &cfg->pattern2; + slot_idx_period -= cfg->pattern1.period_ms * slot_x_ms; // Remove pattern 1 offset + } + + return (slot_idx_period < pattern->nof_dl_slots || + (slot_idx_period == pattern->nof_dl_slots && pattern->nof_dl_symbols != 0)); +} + +bool srslte_tdd_nr_is_ul(const srslte_tdd_config_nr_t* cfg, uint32_t numerology, uint32_t slot_idx) +{ + if (cfg == NULL) { + return false; + } + + // Calculate slot index within the TDD overall period + uint32_t slot_x_ms = 1U << numerology; // Number of slots per millisecond + uint32_t period_sum = (cfg->pattern1.period_ms + cfg->pattern2.period_ms) * slot_x_ms; // Total perdiod sum + uint32_t slot_idx_period = slot_idx % period_sum; // Slot index within the period + + // Select pattern + const srslte_tdd_pattern_t* pattern = &cfg->pattern1; + if ((slot_idx_period >= cfg->pattern1.period_ms * slot_x_ms)) { + pattern = &cfg->pattern2; + slot_idx_period -= cfg->pattern1.period_ms * slot_x_ms; // Remove pattern 1 offset + } + + // Calculate slot in which UL starts + uint32_t start_ul = (pattern->period_ms * slot_x_ms - pattern->nof_ul_slots) - 1; + + return (slot_idx_period > start_ul || (slot_idx_period == start_ul && pattern->nof_ul_symbols != 0)); +} diff --git a/srsue/src/phy/nr/cc_worker.cc b/srsue/src/phy/nr/cc_worker.cc index 8d7ea11ee..6dc22c88a 100644 --- a/srsue/src/phy/nr/cc_worker.cc +++ b/srsue/src/phy/nr/cc_worker.cc @@ -181,6 +181,11 @@ void cc_worker::decode_pdcch_ul() bool cc_worker::work_dl() { + // Check if it is a DL slot, if not skip + if (!srslte_tdd_nr_is_dl(&phy->cfg.tdd, 0, dl_slot_cfg.idx)) { + return true; + } + // Run FFT srslte_ue_dl_nr_estimate_fft(&ue_dl, &dl_slot_cfg); @@ -249,6 +254,11 @@ bool cc_worker::work_dl() bool cc_worker::work_ul() { + // Check if it is a DL slot, if not skip + if (!srslte_tdd_nr_is_ul(&phy->cfg.tdd, 0, ul_slot_cfg.idx)) { + return true; + } + srslte_uci_data_nr_t uci_data = {}; uint32_t pid = 0;