diff --git a/lib/include/srsran/interfaces/gnb_interfaces.h b/lib/include/srsran/interfaces/gnb_interfaces.h index 9f41130d8..a78c1b50b 100644 --- a/lib/include/srsran/interfaces/gnb_interfaces.h +++ b/lib/include/srsran/interfaces/gnb_interfaces.h @@ -243,10 +243,20 @@ public: std::array data = {}; ///< Data pointer }; + /** + * @brief Describes a possible PUCCH candidate transmission + * @note The physical layer shall try decoding all the possible PUCCH candidates and report back to the stack the + * strongest of the candidates. This is thought to be used in the case of SR opportunities in which the UE could + * transmit HARQ-ACK in two possible resources. + */ + struct pucch_candidate_t { + srsran_uci_cfg_nr_t uci_cfg; ///< UCI configuration for the opportunity + srsran_pucch_nr_resource_t resource; ///< PUCCH resource to use + }; + struct pucch_t { - srsran_uci_cfg_nr_t uci_cfg; ///< UCI configuration - srsran_pucch_nr_common_cfg_t pucch_cfg; ///< UE dedicated PUCCH configuration - srsran_pucch_nr_resource_t resource; ///< PUCCH resource + srsran_pucch_nr_common_cfg_t pucch_cfg; ///< UE dedicated PUCCH configuration + srsran::bounded_vector candidates; ///< PUCCH candidates to decode }; struct ul_sched_t { diff --git a/lib/src/phy/phch/ra_ul_nr.c b/lib/src/phy/phch/ra_ul_nr.c index 1f6a03332..4654d759f 100644 --- a/lib/src/phy/phch/ra_ul_nr.c +++ b/lib/src/phy/phch/ra_ul_nr.c @@ -528,10 +528,9 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, // Use SR PUCCH resource // - At least one positive SR - // - up to 2 HARQ-ACK + // - No HARQ-ACK // - No CSI report - if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && - uci_cfg->nof_csi == 0) { + if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count == 0 && uci_cfg->nof_csi == 0) { uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id; if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) { ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES); @@ -550,6 +549,55 @@ int srsran_ra_ul_nr_pucch_resource(const srsran_pucch_nr_hl_cfg_t* pucch_cfg, return SRSRAN_SUCCESS; } + // Use SR PUCCH resource + // - At least one positive SR + // - up to 2 HARQ-ACK + // - No CSI report + if (uci_cfg->sr_positive_present > 0 && uci_cfg->ack.count <= SRSRAN_PUCCH_NR_FORMAT1_MAX_NOF_BITS && + uci_cfg->nof_csi == 0) { + uint32_t sr_resource_id = uci_cfg->pucch.sr_resource_id; + if (sr_resource_id >= SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES) { + ERROR("SR resource ID (%d) exceeds the maximum ID (%d)", sr_resource_id, SRSRAN_PUCCH_MAX_NOF_SR_RESOURCES); + return SRSRAN_ERROR; + } + + if (!pucch_cfg->sr_resources[sr_resource_id].configured) { + ERROR("SR resource ID (%d) is not configured", sr_resource_id); + return SRSRAN_ERROR; + } + + // Select PUCCH resource for SR + srsran_pucch_nr_resource_t resource_sr = pucch_cfg->sr_resources[sr_resource_id].resource; + + // Select PUCCH resource for HARQ-ACK + srsran_pucch_nr_resource_t resource_harq = {}; + if (ra_ul_nr_pucch_resource_hl(pucch_cfg, O_uci, uci_cfg->pucch.resource_id, &resource_harq) < SRSRAN_SUCCESS) { + return SRSRAN_ERROR; + } + + // If a UE would transmit positive or negative SR in a resource using PUCCH format 0 and HARQ-ACK information bits + // in a resource using PUCCH format 1 in a slot, the UE transmits only a PUCCH with the HARQ-ACK information bits + // in the resource using PUCCH format 1. + if (resource_sr.format == SRSRAN_PUCCH_NR_FORMAT_0 && resource_harq.format == SRSRAN_PUCCH_NR_FORMAT_1) { + *resource = resource_harq; + return SRSRAN_SUCCESS; + } + + // If the UE would transmit positive SR in a first resource using PUCCH format 1 and at most two HARQ-ACK + // information bits in a second resource using PUCCH format 1 in a slot, the UE transmits a PUCCH with HARQ-ACK + // information bits in the first resource using PUCCH format 1 as described in Clause 9.2.3. If a UE would transmit + // negative SR in a resource using PUCCH format 1 and at most two HARQ-ACK information bits in a resource using + // PUCCH format 1 in a slot, the UE transmits a PUCCH in the resource using PUCCH format 1 for HARQ-ACK + // information as described in Clause 9.2.3. + if (resource_sr.format == SRSRAN_PUCCH_NR_FORMAT_1 && resource_harq.format == SRSRAN_PUCCH_NR_FORMAT_1) { + *resource = resource_sr; + return SRSRAN_SUCCESS; + } + + // The impossible happened... + return SRSRAN_ERROR; + } + // Use format 2, 3 or 4 resource from higher layers // - Irrelevant SR opportunities // - More than 2 HARQ-ACK diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index e7323b33f..64bcead67 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -149,13 +149,13 @@ bool slot_worker::work_ul() // For each PUCCH... for (stack_interface_phy_nr::pucch_t& pucch : ul_sched.pucch) { stack_interface_phy_nr::pucch_info_t pucch_info = {}; - pucch_info.uci_data.cfg = pucch.uci_cfg; + pucch_info.uci_data.cfg = pucch.candidates[0].uci_cfg; // Decode PUCCH if (srsran_gnb_ul_get_pucch(&gnb_ul, &ul_slot_cfg, &pucch.pucch_cfg, - &pucch.resource, + &pucch.candidates[0].resource, &pucch_info.uci_data.cfg, &pucch_info.uci_data.value) < SRSRAN_SUCCESS) { logger.error("Error getting PUCCH"); @@ -171,7 +171,8 @@ bool slot_worker::work_ul() // Log PUCCH decoding if (logger.info.enabled()) { std::array str; - srsran_gnb_ul_pucch_info(&gnb_ul, &pucch.resource, &pucch_info.uci_data, str.data(), (uint32_t)str.size()); + srsran_gnb_ul_pucch_info( + &gnb_ul, &pucch.candidates[0].resource, &pucch_info.uci_data, str.data(), (uint32_t)str.size()); logger.info("PUCCH: %s", str.data()); } diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index 828332142..ad2a23fb2 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -475,8 +475,8 @@ public: // If any UCI information is triggered, schedule PUCCH if (uci_cfg.ack.count > 0 || uci_cfg.nof_csi > 0 || uci_cfg.o_sr > 0) { mac_interface_phy_nr::pucch_t pucch = {}; - pucch.uci_cfg = uci_cfg; - if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.resource)) { + pucch.candidates[0].uci_cfg = uci_cfg; + if (not phy_cfg.get_pucch_uci_cfg(slot_cfg, uci_cfg, pucch.pucch_cfg, pucch.candidates[0].resource)) { logger.error("Error getting UCI CFG"); return SRSRAN_ERROR; }