From 0192130742be5ab2a68bb5abea6ccd25ec3181eb Mon Sep 17 00:00:00 2001 From: Xavier Arteaga Date: Mon, 6 Jul 2020 18:27:03 +0200 Subject: [PATCH] SRSUE/SRSENB: UCI bits are carrier by the lowest serving cell index SRSENB: Fix UCI in lowest serving cell index PUSCH transmission --- lib/src/phy/ue/ue_dl.c | 1 + srsenb/hdr/phy/cc_worker.h | 3 +- srsenb/hdr/phy/phy_ue_db.h | 23 +++++++++- srsenb/src/phy/cc_worker.cc | 20 ++++----- srsenb/src/phy/phy_ue_db.cc | 70 ++++++++++++++++++++++++++--- srsenb/src/phy/sf_worker.cc | 3 ++ srsenb/src/stack/rrc/rrc_ue.cc | 6 +++ srsenb/test/phy/enb_phy_test.cc | 78 ++++++++++++++++++++++++--------- srsue/hdr/phy/cc_worker.h | 3 +- srsue/hdr/phy/phy_common.h | 17 ++++--- srsue/src/phy/cc_worker.cc | 29 +++++------- srsue/src/phy/phy_common.cc | 12 +++++ srsue/src/phy/sf_worker.cc | 16 +++++-- 13 files changed, 214 insertions(+), 67 deletions(-) diff --git a/lib/src/phy/ue/ue_dl.c b/lib/src/phy/ue/ue_dl.c index c2e080102..18de0cf86 100644 --- a/lib/src/phy/ue/ue_dl.c +++ b/lib/src/phy/ue/ue_dl.c @@ -1383,6 +1383,7 @@ void srslte_ue_dl_gen_ack(const srslte_cell_t* cell, const srslte_pdsch_ack_t* ack_info, srslte_uci_data_t* uci_data) { + uci_data->value.ack.valid = true; //< Always true for UE transmitter if (cell->frame_type == SRSLTE_FDD) { gen_ack_fdd(ack_info, uci_data); } else { diff --git a/srsenb/hdr/phy/cc_worker.h b/srsenb/hdr/phy/cc_worker.h index 45ca1ba3b..b9b56e87c 100644 --- a/srsenb/hdr/phy/cc_worker.h +++ b/srsenb/hdr/phy/cc_worker.h @@ -103,8 +103,7 @@ private: // Do nothing } - bool is_grant_available = false; - srslte_phich_grant_t phich_grant = {}; + srslte_phich_grant_t phich_grant = {}; void metrics_read(phy_metrics_t* metrics); void metrics_dl(uint32_t mcs); diff --git a/srsenb/hdr/phy/phy_ue_db.h b/srsenb/hdr/phy/phy_ue_db.h index 8c1bbf810..cccab579b 100644 --- a/srsenb/hdr/phy/phy_ue_db.h +++ b/srsenb/hdr/phy/phy_ue_db.h @@ -86,6 +86,7 @@ private: uint8_t last_ri = 0; ///< Last reported rank indicator std::array last_tb = {}; ///< Stores last PUSCH Resource allocation srslte::phy_cfg_t phy_cfg; ///< Configuration, it has a default constructor + std::array is_grant_available; ///< Indicates whether there is an available grant } cell_info_t; /** @@ -156,6 +157,18 @@ private: */ inline uint32_t _get_ue_cc_idx(uint16_t rnti, uint32_t enb_cc_idx) const; + /** + * Gets the eNb Cell/Carrier index in which the UCI shall be carried. This corresponds to the serving cell with lowest + * index that has an UL grant available. + * + * If no grant is available in the indicated TTI, it returns the number of the eNb Cells/Carriers. + * + * @param tti The UL processing TTI + * @param rnti Temporal UE ID + * @return the eNb Cell/Carrier with lowest serving cell index that has an UL grant + */ + uint32_t _get_uci_enb_cc_idx(uint32_t tti, uint16_t rnti) const; + /** * Checks if a given RNTI exists in the database * @param rnti provides UE identifier @@ -358,7 +371,7 @@ public: * identifier. * * @param rnti the UE temporal ID - * @param cc_idx the cell/carrier origin of the transmission + * @param enb_cc_idx the cell/carrier origin of the transmission * @param pid HARQ process identifier * @param tb the Resource Allocation for the PUSCH transport block */ @@ -375,6 +388,14 @@ public: * @return the Resource Allocation for the PUSCH transport block */ srslte_ra_tb_t get_last_ul_tb(uint16_t rnti, uint32_t enb_cc_idx, uint32_t pid) const; + + /** + * Flags to true the UL grant available for a given TTI, RNTI and eNb cell/carrier index + * @param tti the current TTI + * @param rnti + * @param enb_cc_idx + */ + void set_ul_grant_available(uint32_t tti, const stack_interface_phy_lte::ul_sched_list_t& ul_sched_list); }; } // namespace srsenb diff --git a/srsenb/src/phy/cc_worker.cc b/srsenb/src/phy/cc_worker.cc index 18d475404..cca11e204 100644 --- a/srsenb/src/phy/cc_worker.cc +++ b/srsenb/src/phy/cc_worker.cc @@ -227,10 +227,6 @@ void cc_worker::work_ul(const srslte_ul_sf_cfg_t& ul_sf_cfg, stack_interface_phy ul_sf = ul_sf_cfg; log_h->step(ul_sf.tti); - for (auto& ue : ue_db) { - ue.second->is_grant_available = false; - } - // Process UL signal srslte_enb_ul_fft(&enb_ul); @@ -291,11 +287,13 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_ // Get UE configuration ul_cfg = phy->ue_db.get_ul_config(rnti, cc_idx); - // mark this tti as having an ul dci to avoid pucch - ue_db[rnti]->is_grant_available = true; - // Fill UCI configuration - phy->ue_db.fill_uci_cfg(tti_rx, cc_idx, rnti, ul_grant.dci.cqi_request, true, ul_cfg.pusch.uci_cfg); + bool uci_required = + phy->ue_db.fill_uci_cfg(tti_rx, cc_idx, rnti, ul_grant.dci.cqi_request, true, ul_cfg.pusch.uci_cfg); + + if (ul_cfg.pusch.softbuffers.rx) { + srslte_softbuffer_rx_reset(ul_cfg.pusch.softbuffers.rx); + } // Compute UL grant srslte_pusch_grant_t& grant = ul_cfg.pusch.grant; @@ -347,7 +345,9 @@ void cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_ } // Send UCI data to MAC - phy->ue_db.send_uci_data(tti_rx, rnti, cc_idx, ul_cfg.pusch.uci_cfg, pusch_res.uci); + if (uci_required) { + phy->ue_db.send_uci_data(tti_rx, rnti, cc_idx, ul_cfg.pusch.uci_cfg, pusch_res.uci); + } // Save statistics only if data was provided if (ul_grant.data != nullptr) { @@ -393,7 +393,7 @@ int cc_worker::decode_pucch() uint16_t rnti = iter.first; // If it's a User RNTI and doesn't have PUSCH grant in this TTI - if (SRSLTE_RNTI_ISUSER(rnti) and not ue_db[rnti]->is_grant_available and phy->ue_db.is_pcell(rnti, cc_idx)) { + if (SRSLTE_RNTI_ISUSER(rnti) and phy->ue_db.is_pcell(rnti, cc_idx)) { srslte_ul_cfg_t ul_cfg = phy->ue_db.get_ul_config(rnti, cc_idx); // Check if user needs to receive PUCCH diff --git a/srsenb/src/phy/phy_ue_db.cc b/srsenb/src/phy/phy_ue_db.cc index 0b2b8a28c..9a78d5f6b 100644 --- a/srsenb/src/phy/phy_ue_db.cc +++ b/srsenb/src/phy/phy_ue_db.cc @@ -101,6 +101,7 @@ inline void phy_ue_db::_set_common_config_rnti(uint16_t rnti, srslte::phy_cfg_t& phy_cfg.ul_cfg.pucch.threshold_format1 = SRSLTE_PUCCH_DEFAULT_THRESHOLD_FORMAT1; phy_cfg.ul_cfg.pucch.threshold_data_valid_format1a = SRSLTE_PUCCH_DEFAULT_THRESHOLD_FORMAT1A; phy_cfg.ul_cfg.pucch.threshold_data_valid_format2 = SRSLTE_PUCCH_DEFAULT_THRESHOLD_FORMAT2; + phy_cfg.ul_cfg.pucch.threshold_data_valid_format3 = SRSLTE_PUCCH_DEFAULT_THRESHOLD_FORMAT3; phy_cfg.ul_cfg.pucch.threshold_dmrs_detection = SRSLTE_PUCCH_DEFAULT_THRESHOLD_DMRS; } @@ -119,6 +120,18 @@ inline uint32_t phy_ue_db::_get_ue_cc_idx(uint16_t rnti, uint32_t enb_cc_idx) co return ue_cc_idx; } +uint32_t phy_ue_db::_get_uci_enb_cc_idx(uint32_t tti, uint16_t rnti) const +{ + // Find the lowest index available PUSCH grant + for (const cell_info_t& cell_info : ue_db.at(rnti).cell_info) { + if (cell_info.is_grant_available[TTIMOD(tti)]) { + return cell_info.enb_cc_idx; + } + } + + return (uint32_t)cell_cfg_list->size(); +} + inline int phy_ue_db::_assert_rnti(uint16_t rnti) const { if (not ue_db.count(rnti)) { @@ -456,13 +469,32 @@ bool phy_ue_db::fill_uci_cfg(uint32_t tti, // Reset UCI CFG, avoid returning carrying cached information uci_cfg = {}; - // Assert rnti and cell exits and it is PCell - if (_assert_enb_pcell(rnti, enb_cc_idx) != SRSLTE_SUCCESS) { + // Assert Cell List configuration + if (_assert_cell_list_cfg() != SRSLTE_SUCCESS) { return false; } - // Assert Cell List configuration - if (_assert_cell_list_cfg() != SRSLTE_SUCCESS) { + // Assert eNb Cell/Carrier for the given RNTI + if (_assert_active_enb_cc(rnti, enb_cc_idx) != SRSLTE_SUCCESS) { + return false; + } + + // Get the eNb cell/carrier index with lowest serving cell index (ue_cc_idx) that has an available grant. + uint32_t uci_enb_cc_id = _get_uci_enb_cc_idx(tti, rnti); + bool pusch_grant_available = (uci_enb_cc_id < (uint32_t)cell_cfg_list->size()); + + // There is a PUSCH grant available for the provided RNTI in at least one serving cell and this call is for PUCCH + if (pusch_grant_available and not is_pusch_available) { + return false; + } + + // There is a PUSCH grant and enb_cc_idx with lowest ue_cc_idx with a grant + if (pusch_grant_available and uci_enb_cc_id != enb_cc_idx) { + return false; + } + + // No PUSCH grant for this TTI and cell and no enb_cc_idx is not the PCell + if (not pusch_grant_available and _get_ue_cc_idx(rnti, enb_cc_idx) != 0) { return false; } @@ -524,8 +556,8 @@ void phy_ue_db::send_uci_data(uint32_t tti, { std::lock_guard lock(mutex); - // Assert UE RNTI database entry and eNb cell/carrier must be primary cell - if (_assert_enb_pcell(rnti, enb_cc_idx) != SRSLTE_SUCCESS) { + // Assert UE RNTI database entry and eNb cell/carrier must be active + if (_assert_active_enb_cc(rnti, enb_cc_idx) != SRSLTE_SUCCESS) { return; } @@ -639,3 +671,29 @@ srslte_ra_tb_t phy_ue_db::get_last_ul_tb(uint16_t rnti, uint32_t enb_cc_idx, uin // Returns the latest stored UL transmission grant return ue_db.at(rnti).cell_info[_get_ue_cc_idx(rnti, enb_cc_idx)].last_tb[pid % SRSLTE_FDD_NOF_HARQ]; } + +void phy_ue_db::set_ul_grant_available(uint32_t tti, const stack_interface_phy_lte::ul_sched_list_t& ul_sched_list) +{ + std::lock_guard lock(mutex); + + // Reset all available grants flags for the given TTI + for (auto& ue : ue_db) { + for (cell_info_t& cell_info : ue.second.cell_info) { + cell_info.is_grant_available[TTIMOD(tti)] = false; + } + } + + // For each eNb Cell/Carrier grant set a flag to the corresponding RNTI + for (uint32_t enb_cc_idx = 0; enb_cc_idx < (uint32_t)ul_sched_list.size(); enb_cc_idx++) { + const stack_interface_phy_lte::ul_sched_t& ul_sched = ul_sched_list[enb_cc_idx]; + for (uint32_t i = 0; i < ul_sched.nof_grants; i++) { + const stack_interface_phy_lte::ul_sched_grant_t& ul_sched_grant = ul_sched.pusch[i]; + uint16_t rnti = ul_sched_grant.dci.rnti; + // Check that eNb Cell/Carrier is active for the given RNTI + if (_assert_active_enb_cc(rnti, enb_cc_idx) == SRSLTE_SUCCESS) { + // Rise Grant available flag + ue_db[rnti].cell_info[_get_ue_cc_idx(rnti, enb_cc_idx)].is_grant_available[TTIMOD(tti)] = true; + } + } + } +} diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index bb43a5e12..3bc5109ab 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -203,6 +203,9 @@ void sf_worker::work_imp() // Configure UL subframe ul_sf.tti = tti_rx; + // Set UL grant availability prior to any UL processing + phy->ue_db.set_ul_grant_available(tti_rx, ul_grants); + // Process UL for (uint32_t cc = 0; cc < cc_workers.size(); cc++) { cc_workers[cc]->work_ul(ul_sf, ul_grants[cc]); diff --git a/srsenb/src/stack/rrc/rrc_ue.cc b/srsenb/src/stack/rrc/rrc_ue.cc index 84c22de7d..753e8bdda 100644 --- a/srsenb/src/stack/rrc/rrc_ue.cc +++ b/srsenb/src/stack/rrc/rrc_ue.cc @@ -1127,6 +1127,12 @@ int rrc::ue::fill_scell_to_addmod_list(asn1::rrc::rrc_conn_recfg_r8_ies_s* conn_ srslte::set_phy_cfg_t_scell_config(&scell_phy_rrc_ded.phy_cfg, cell); scell_phy_rrc_ded.configured = true; + // Set PUSCH dedicated configuration following 3GPP TS 36.331 R 10 Section 6.3.2 Radio resource control information + // elements - PUSCH-Config + // One value applies for all serving cells with an uplink (the associated functionality is common i.e. not + // performed independently for each cell). + scell_phy_rrc_ded.phy_cfg.ul_cfg.pusch.uci_offset = phy_rrc_dedicated_list[0].phy_cfg.ul_cfg.pusch.uci_offset; + // Get corresponding eNB CC index scell_phy_rrc_ded.enb_cc_idx = cc_cfg->enb_cc_idx; diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index 346bf0dd5..d27181c5e 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -187,8 +187,7 @@ public: } } - bool tx(srslte::rf_buffer_interface& buffer, - const srslte::rf_timestamp_interface& tx_time) override + bool tx(srslte::rf_buffer_interface& buffer, const srslte::rf_timestamp_interface& tx_time) override { int err = SRSLTE_SUCCESS; @@ -209,8 +208,7 @@ public: return err >= SRSLTE_SUCCESS; } void tx_end() override {} - bool rx_now(srslte::rf_buffer_interface& buffer, - srslte::rf_timestamp_interface& rxd_time) override + bool rx_now(srslte::rf_buffer_interface& buffer, srslte::rf_timestamp_interface& rxd_time) override { int err = SRSLTE_SUCCESS; @@ -981,8 +979,32 @@ public: return SRSLTE_SUCCESS; } + void fill_uci(uint32_t cc_idx, + srslte_ue_ul_cfg_t& ue_ul_cfg, + srslte_uci_data_t& uci_data, + srslte_pdsch_ack_t& pdsch_ack, + srslte_pusch_data_t& pusch_data) + { + // Generate scheduling request + srslte_ue_ul_gen_sr(&ue_ul_cfg, &sf_ul_cfg, &uci_data, (bool)(sf_ul_cfg.tti % 20 == 0)); + + // Generate Acknowledgements + srslte_ue_dl_gen_ack(&ue_dl_v[cc_idx]->cell, &sf_dl_cfg, &pdsch_ack, &uci_data); + + if (uci_data.cfg.cqi.ri_len) { + last_ri[uci_data.cfg.cqi.scell_index] = uci_data.value.ri; + } + + // Set UCI only for lowest serving cell index + pusch_data.uci = uci_data.value; + ue_ul_cfg.ul_cfg.pusch.uci_cfg = uci_data.cfg; + ue_ul_cfg.ul_cfg.pucch.uci_cfg = uci_data.cfg; + } + int work_ul(srslte_pdsch_ack_t& pdsch_ack, srslte_uci_data_t& uci_data) { + bool first_pusch = true; + // Zero all IQ UL buffers for (auto& buffer : buffers) { srslte_vec_cf_zero(buffer, SRSLTE_SF_LEN_PRB(ue_ul_v[0]->cell.nof_prb)); @@ -1022,28 +1044,15 @@ public: ue_ul_cfg.ul_cfg.pusch.softbuffers.tx = &softbuffer_tx; ue_ul_cfg.grant_available = true; pdsch_ack.is_pusch_available = true; - } - // Generate - if (i == 0) { - // Generate scheduling request - srslte_ue_ul_gen_sr(&ue_ul_cfg, &sf_ul_cfg, &uci_data, (bool)(sf_ul_cfg.tti % 20 == 0)); + // Generate UCI data + if (first_pusch) { + fill_uci(cc_idx, ue_ul_cfg, uci_data, pdsch_ack, pusch_data); - // Generate Acknowledgements - srslte_ue_dl_gen_ack(&ue_dl_v[cc_idx]->cell, &sf_dl_cfg, &pdsch_ack, &uci_data); - - if (uci_data.cfg.cqi.ri_len) { - last_ri[uci_data.cfg.cqi.scell_index] = uci_data.value.ri; + first_pusch = false; } } - // Set UCI only for PCel - if (i == 0) { - pusch_data.uci = uci_data.value; - ue_ul_cfg.ul_cfg.pusch.uci_cfg = uci_data.cfg; - ue_ul_cfg.ul_cfg.pucch.uci_cfg = uci_data.cfg; - } - // Work UL TESTASSERT(srslte_ue_ul_encode(ue_ul_v[cc_idx], &sf_ul_cfg, &ue_ul_cfg, &pusch_data) >= SRSLTE_SUCCESS); @@ -1054,6 +1063,31 @@ public: } } + // If no PUSCH, send PUCCH + if (first_pusch) { + uint32_t cc_idx = phy_rrc_cfg[0].enb_cc_idx; + srslte::phy_cfg_t& dedicated = phy_rrc_cfg[0].phy_cfg; + + srslte_ue_ul_cfg_t ue_ul_cfg = {}; + ue_ul_cfg.ul_cfg = dedicated.ul_cfg; + ue_ul_cfg.ul_cfg.pusch.softbuffers.tx = &softbuffer_tx; + ue_ul_cfg.ul_cfg.pucch.rnti = rnti; + ue_ul_cfg.cc_idx = 0; // SCell index + + srslte_pusch_data_t pusch_data = {}; + + fill_uci(cc_idx, ue_ul_cfg, uci_data, pdsch_ack, pusch_data); + + // Work UL PUCCH + TESTASSERT(srslte_ue_ul_encode(ue_ul_v[cc_idx], &sf_ul_cfg, &ue_ul_cfg, &pusch_data) >= SRSLTE_SUCCESS); + + char str[256] = {}; + srslte_ue_ul_info(&ue_ul_cfg, &sf_ul_cfg, &pusch_data.uci, str, sizeof(str)); + if (str[0]) { + log_h.info("[UL INFO %d] %s\n", 0, str); + } + } + // Write eNb Rx radio->write_rx(buffers, sf_len); @@ -1226,6 +1260,8 @@ public: dedicated.ul_cfg.pucch.n1_pucch_an_cs[2][1] = N_pucch_1 + 5; dedicated.ul_cfg.pucch.n1_pucch_an_cs[3][1] = N_pucch_1 + 6; dedicated.ul_cfg.pusch.uci_offset.I_offset_ack = 7; + dedicated.ul_cfg.pusch.uci_offset.I_offset_ri = 7; + dedicated.ul_cfg.pusch.uci_offset.I_offset_cqi = 7; // Configure UE PHY std::array activation = {}; ///< Activation/Deactivation vector diff --git a/srsue/hdr/phy/cc_worker.h b/srsue/hdr/phy/cc_worker.h index 407760436..d1c2515cf 100644 --- a/srsue/hdr/phy/cc_worker.h +++ b/srsue/hdr/phy/cc_worker.h @@ -52,6 +52,8 @@ public: void set_crnti(uint16_t rnti); void enable_pregen_signals(bool enabled); + void set_uci_periodic_cqi(srslte_uci_data_t* uci_data); + bool work_dl_regular(); bool work_dl_mbsfn(srslte_mbsfn_cfg_t mbsfn_cfg); bool work_ul(srslte_uci_data_t* uci_data); @@ -84,7 +86,6 @@ private: /* Methods for UL */ bool encode_uplink(mac_interface_phy_lte::tb_action_ul_t* action, srslte_uci_data_t* uci_data); void set_uci_sr(srslte_uci_data_t* uci_data); - void set_uci_periodic_cqi(srslte_uci_data_t* uci_data); void set_uci_aperiodic_cqi(srslte_uci_data_t* uci_data); void set_uci_ack(srslte_uci_data_t* uci_data, bool is_grant_available, uint32_t dai_ul, bool is_pusch_available); uint32_t get_wideband_cqi(); diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index bef5216e8..0bc7e24fa 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -130,6 +130,14 @@ public: void set_ul_pending_grant(srslte_dl_sf_cfg_t* sf, uint32_t cc_idx, srslte_dci_ul_t* dci); bool get_ul_pending_grant(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, uint32_t* pid, srslte_dci_ul_t* dci); + /** + * If there is a UL Grant it returns the lowest index component carrier that has a grant, otherwise it returns 0. + * + * @param tti_tx TTI in which the transmission is happening + * @return The number of carrier if a grant is available, otherwise 0 + */ + uint32_t get_ul_uci_cc(uint32_t tti_tx) const; + void set_rar_grant_tti(uint32_t tti); void set_dl_pending_ack(srslte_dl_sf_cfg_t* sf, @@ -138,10 +146,7 @@ public: srslte_pdsch_ack_resource_t resource); bool get_dl_pending_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, srslte_pdsch_ack_cc_t* ack); - void worker_end(void* h, - bool tx_enable, - srslte::rf_buffer_t& buffer, - srslte::rf_timestamp_t& tx_time); + void worker_end(void* h, bool tx_enable, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time); void set_cell(const srslte_cell_t& c); void set_nof_workers(uint32_t nof_workers); @@ -184,7 +189,7 @@ private: std::mutex mtch_mutex; std::condition_variable mtch_cvar; - uint32_t nof_workers = 0; + uint32_t nof_workers = 0; bool is_pending_tx_end = false; @@ -216,7 +221,7 @@ private: srslte_dci_ul_t dci; } pending_ul_grant_t; pending_ul_grant_t pending_ul_grant[TTIMOD_SZ][SRSLTE_MAX_CARRIERS] = {}; - std::mutex pending_ul_grant_mutex; + mutable std::mutex pending_ul_grant_mutex; typedef struct { bool enable; diff --git a/srsue/src/phy/cc_worker.cc b/srsue/src/phy/cc_worker.cc index 5ab0c7d03..d661f6621 100644 --- a/srsue/src/phy/cc_worker.cc +++ b/srsue/src/phy/cc_worker.cc @@ -85,10 +85,10 @@ cc_worker::cc_worker(uint32_t cc_idx_, uint32_t max_prb, srsue::phy_common* phy_ phy->set_pdsch_cfg(&pmch_cfg.pdsch_cfg); // set same config in PMCH decoder // Define MBSFN subframes channel estimation and save default one - chest_mbsfn_cfg.filter_type = SRSLTE_CHEST_FILTER_TRIANGLE; - chest_mbsfn_cfg.filter_coef[0] = 0.1; - chest_mbsfn_cfg.estimator_alg = SRSLTE_ESTIMATOR_ALG_INTERPOLATE; - chest_mbsfn_cfg.noise_alg = SRSLTE_NOISE_ALG_PSS; + chest_mbsfn_cfg.filter_type = SRSLTE_CHEST_FILTER_TRIANGLE; + chest_mbsfn_cfg.filter_coef[0] = 0.1; + chest_mbsfn_cfg.estimator_alg = SRSLTE_ESTIMATOR_ALG_INTERPOLATE; + chest_mbsfn_cfg.noise_alg = SRSLTE_NOISE_ALG_PSS; chest_default_cfg = ue_dl_cfg.chest_cfg; @@ -641,17 +641,12 @@ bool cc_worker::work_ul(srslte_uci_data_t* uci_data) pid = phy->ul_pidof(CURRENT_TTI_TX, &sf_cfg_ul.tdd_config); } - /* Generate CQI reports if required, note that in case both aperiodic - * and periodic ones present, only aperiodic is sent (36.213 section 7.2) */ - if (ul_grant_available && dci_ul.cqi_request) { + /* + * Generate aperiodic CQI report if required, note that in case both aperiodic and periodic ones present, only + * aperiodic is sent (36.213 section 7.2) + */ + if (ul_grant_available and dci_ul.cqi_request and uci_data != nullptr) { set_uci_aperiodic_cqi(uci_data); - } else { - /* Check PCell and enabled secondary cells */ - if (cc_idx == 0 || phy->scell_cfg[cc_idx].enabled) { - // 3GPP 36.213 Section 7.2 - // If the UE is configured with more than one serving cell, it transmits CSI for activated serving cell(s) only. - set_uci_periodic_cqi(uci_data); - } } /* Send UL dci or HARQ information (from PHICH) to MAC and receive actions*/ @@ -690,14 +685,14 @@ bool cc_worker::work_ul(srslte_uci_data_t* uci_data) } // PCell sends SR and ACK - if (cc_idx == 0) { + if (uci_data != nullptr) { set_uci_sr(uci_data); // This must be called after set_uci_sr() and set_uci_*_cqi set_uci_ack(uci_data, ul_grant_available, dci_ul.dai, ul_action.tb.enabled); } // Generate uplink signal, include uci data on only PCell - signal_ready = encode_uplink(&ul_action, (cc_idx == 0) ? uci_data : nullptr); + signal_ready = encode_uplink(&ul_action, uci_data); // Prepare to receive ACK through PHICH if (ul_action.expect_ack) { @@ -927,7 +922,7 @@ void cc_worker::set_config(srslte::phy_cfg_t& phy_cfg) } } -void cc_worker::upd_config_dci(srslte_dci_cfg_t &dci_cfg) +void cc_worker::upd_config_dci(srslte_dci_cfg_t& dci_cfg) { ue_dl_cfg.cfg.dci = dci_cfg; } diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index c6c427336..fe543a263 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -364,6 +364,18 @@ bool phy_common::get_ul_pending_grant(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, u return ret; } +uint32_t phy_common::get_ul_uci_cc(uint32_t tti_tx) const +{ + std::lock_guard lock(pending_ul_grant_mutex); + for (uint32_t cc = 0; cc < args->nof_carriers; cc++) { + const pending_ul_grant_t& grant = pending_ul_grant[TTIMOD(tti_tx)][cc]; + if (grant.enable) { + return cc; + } + } + return 0; // Return Primary cell +} + // SF->TTI at which PHICH is received void phy_common::set_ul_received_ack(srslte_dl_sf_cfg_t* sf, uint32_t cc_idx, diff --git a/srsue/src/phy/sf_worker.cc b/srsue/src/phy/sf_worker.cc index c37dd781c..06438f654 100644 --- a/srsue/src/phy/sf_worker.cc +++ b/srsue/src/phy/sf_worker.cc @@ -245,12 +245,22 @@ void sf_worker::work_imp() srslte_uci_data_t uci_data; reset_uci(&uci_data); - // Loop through all carriers. Do in reverse order since control information from SCells is transmitted in PCell + uint32_t uci_cc_idx = phy->get_ul_uci_cc(TTI_TX(tti)); + + // Fill periodic CQI data; In case of periodic CSI report collision, lower carrier index have preference, so + // iterate through all carriers in inverse order. for (int carrier_idx = phy->args->nof_carriers - 1; carrier_idx >= 0; carrier_idx--) { - tx_signal_ready |= cc_workers[carrier_idx]->work_ul(&uci_data); + if (carrier_idx == 0 or phy->scell_cfg[carrier_idx].configured) { + cc_workers[carrier_idx]->set_uci_periodic_cqi(&uci_data); + } + } + + // Loop through all carriers + for (uint32_t carrier_idx = 0; carrier_idx < phy->args->nof_carriers; carrier_idx++) { + tx_signal_ready |= cc_workers[carrier_idx]->work_ul(uci_cc_idx == carrier_idx ? &uci_data : nullptr); // Set signal pointer based on offset - tx_signal_ptr.set((uint32_t)carrier_idx, 0, phy->args->nof_rx_ant, cc_workers[carrier_idx]->get_tx_buffer(0)); + tx_signal_ptr.set(carrier_idx, 0, phy->args->nof_rx_ant, cc_workers[carrier_idx]->get_tx_buffer(0)); } } }