SRSUE/SRSENB: UCI bits are carrier by the lowest serving cell index

SRSENB: Fix UCI in lowest serving cell index PUSCH transmission
master
Xavier Arteaga 5 years ago committed by Xavier Arteaga
parent c8b4ba885b
commit 0192130742

@ -1383,6 +1383,7 @@ void srslte_ue_dl_gen_ack(const srslte_cell_t* cell,
const srslte_pdsch_ack_t* ack_info, const srslte_pdsch_ack_t* ack_info,
srslte_uci_data_t* uci_data) srslte_uci_data_t* uci_data)
{ {
uci_data->value.ack.valid = true; //< Always true for UE transmitter
if (cell->frame_type == SRSLTE_FDD) { if (cell->frame_type == SRSLTE_FDD) {
gen_ack_fdd(ack_info, uci_data); gen_ack_fdd(ack_info, uci_data);
} else { } else {

@ -103,8 +103,7 @@ private:
// Do nothing // 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_read(phy_metrics_t* metrics);
void metrics_dl(uint32_t mcs); void metrics_dl(uint32_t mcs);

@ -86,6 +86,7 @@ private:
uint8_t last_ri = 0; ///< Last reported rank indicator uint8_t last_ri = 0; ///< Last reported rank indicator
std::array<srslte_ra_tb_t, SRSLTE_MAX_HARQ_PROC> last_tb = {}; ///< Stores last PUSCH Resource allocation std::array<srslte_ra_tb_t, SRSLTE_MAX_HARQ_PROC> last_tb = {}; ///< Stores last PUSCH Resource allocation
srslte::phy_cfg_t phy_cfg; ///< Configuration, it has a default constructor srslte::phy_cfg_t phy_cfg; ///< Configuration, it has a default constructor
std::array<bool, TTIMOD_SZ> is_grant_available; ///< Indicates whether there is an available grant
} cell_info_t; } cell_info_t;
/** /**
@ -156,6 +157,18 @@ private:
*/ */
inline uint32_t _get_ue_cc_idx(uint16_t rnti, uint32_t enb_cc_idx) const; 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 * Checks if a given RNTI exists in the database
* @param rnti provides UE identifier * @param rnti provides UE identifier
@ -358,7 +371,7 @@ public:
* identifier. * identifier.
* *
* @param rnti the UE temporal ID * @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 pid HARQ process identifier
* @param tb the Resource Allocation for the PUSCH transport block * @param tb the Resource Allocation for the PUSCH transport block
*/ */
@ -375,6 +388,14 @@ public:
* @return the Resource Allocation for the PUSCH transport block * @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; 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 } // namespace srsenb

@ -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; ul_sf = ul_sf_cfg;
log_h->step(ul_sf.tti); log_h->step(ul_sf.tti);
for (auto& ue : ue_db) {
ue.second->is_grant_available = false;
}
// Process UL signal // Process UL signal
srslte_enb_ul_fft(&enb_ul); 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 // Get UE configuration
ul_cfg = phy->ue_db.get_ul_config(rnti, cc_idx); 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 // 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 // Compute UL grant
srslte_pusch_grant_t& grant = ul_cfg.pusch.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 // 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 // Save statistics only if data was provided
if (ul_grant.data != nullptr) { if (ul_grant.data != nullptr) {
@ -393,7 +393,7 @@ int cc_worker::decode_pucch()
uint16_t rnti = iter.first; uint16_t rnti = iter.first;
// If it's a User RNTI and doesn't have PUSCH grant in this TTI // 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); srslte_ul_cfg_t ul_cfg = phy->ue_db.get_ul_config(rnti, cc_idx);
// Check if user needs to receive PUCCH // Check if user needs to receive PUCCH

@ -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_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_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_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; 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; 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 inline int phy_ue_db::_assert_rnti(uint16_t rnti) const
{ {
if (not ue_db.count(rnti)) { 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 // Reset UCI CFG, avoid returning carrying cached information
uci_cfg = {}; uci_cfg = {};
// Assert rnti and cell exits and it is PCell // Assert Cell List configuration
if (_assert_enb_pcell(rnti, enb_cc_idx) != SRSLTE_SUCCESS) { if (_assert_cell_list_cfg() != SRSLTE_SUCCESS) {
return false; return false;
} }
// Assert Cell List configuration // Assert eNb Cell/Carrier for the given RNTI
if (_assert_cell_list_cfg() != SRSLTE_SUCCESS) { 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; return false;
} }
@ -524,8 +556,8 @@ void phy_ue_db::send_uci_data(uint32_t tti,
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
// Assert UE RNTI database entry and eNb cell/carrier must be primary cell // Assert UE RNTI database entry and eNb cell/carrier must be active
if (_assert_enb_pcell(rnti, enb_cc_idx) != SRSLTE_SUCCESS) { if (_assert_active_enb_cc(rnti, enb_cc_idx) != SRSLTE_SUCCESS) {
return; 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 // 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]; 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<std::mutex> 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;
}
}
}
}

@ -203,6 +203,9 @@ void sf_worker::work_imp()
// Configure UL subframe // Configure UL subframe
ul_sf.tti = tti_rx; 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 // Process UL
for (uint32_t cc = 0; cc < cc_workers.size(); cc++) { for (uint32_t cc = 0; cc < cc_workers.size(); cc++) {
cc_workers[cc]->work_ul(ul_sf, ul_grants[cc]); cc_workers[cc]->work_ul(ul_sf, ul_grants[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); srslte::set_phy_cfg_t_scell_config(&scell_phy_rrc_ded.phy_cfg, cell);
scell_phy_rrc_ded.configured = true; 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 // Get corresponding eNB CC index
scell_phy_rrc_ded.enb_cc_idx = cc_cfg->enb_cc_idx; scell_phy_rrc_ded.enb_cc_idx = cc_cfg->enb_cc_idx;

@ -187,8 +187,7 @@ public:
} }
} }
bool tx(srslte::rf_buffer_interface& buffer, bool tx(srslte::rf_buffer_interface& buffer, const srslte::rf_timestamp_interface& tx_time) override
const srslte::rf_timestamp_interface& tx_time) override
{ {
int err = SRSLTE_SUCCESS; int err = SRSLTE_SUCCESS;
@ -209,8 +208,7 @@ public:
return err >= SRSLTE_SUCCESS; return err >= SRSLTE_SUCCESS;
} }
void tx_end() override {} void tx_end() override {}
bool rx_now(srslte::rf_buffer_interface& buffer, bool rx_now(srslte::rf_buffer_interface& buffer, srslte::rf_timestamp_interface& rxd_time) override
srslte::rf_timestamp_interface& rxd_time) override
{ {
int err = SRSLTE_SUCCESS; int err = SRSLTE_SUCCESS;
@ -981,8 +979,32 @@ public:
return SRSLTE_SUCCESS; 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) int work_ul(srslte_pdsch_ack_t& pdsch_ack, srslte_uci_data_t& uci_data)
{ {
bool first_pusch = true;
// Zero all IQ UL buffers // Zero all IQ UL buffers
for (auto& buffer : buffers) { for (auto& buffer : buffers) {
srslte_vec_cf_zero(buffer, SRSLTE_SF_LEN_PRB(ue_ul_v[0]->cell.nof_prb)); 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.ul_cfg.pusch.softbuffers.tx = &softbuffer_tx;
ue_ul_cfg.grant_available = true; ue_ul_cfg.grant_available = true;
pdsch_ack.is_pusch_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 Acknowledgements // Generate UCI data
srslte_ue_dl_gen_ack(&ue_dl_v[cc_idx]->cell, &sf_dl_cfg, &pdsch_ack, &uci_data); if (first_pusch) {
fill_uci(cc_idx, ue_ul_cfg, uci_data, pdsch_ack, pusch_data);
if (uci_data.cfg.cqi.ri_len) { first_pusch = false;
last_ri[uci_data.cfg.cqi.scell_index] = uci_data.value.ri;
} }
} }
// 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 // Work UL
TESTASSERT(srslte_ue_ul_encode(ue_ul_v[cc_idx], &sf_ul_cfg, &ue_ul_cfg, &pusch_data) >= SRSLTE_SUCCESS); 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 // Write eNb Rx
radio->write_rx(buffers, sf_len); 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[2][1] = N_pucch_1 + 5;
dedicated.ul_cfg.pucch.n1_pucch_an_cs[3][1] = N_pucch_1 + 6; 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_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 // Configure UE PHY
std::array<bool, SRSLTE_MAX_CARRIERS> activation = {}; ///< Activation/Deactivation vector std::array<bool, SRSLTE_MAX_CARRIERS> activation = {}; ///< Activation/Deactivation vector

@ -52,6 +52,8 @@ public:
void set_crnti(uint16_t rnti); void set_crnti(uint16_t rnti);
void enable_pregen_signals(bool enabled); void enable_pregen_signals(bool enabled);
void set_uci_periodic_cqi(srslte_uci_data_t* uci_data);
bool work_dl_regular(); bool work_dl_regular();
bool work_dl_mbsfn(srslte_mbsfn_cfg_t mbsfn_cfg); bool work_dl_mbsfn(srslte_mbsfn_cfg_t mbsfn_cfg);
bool work_ul(srslte_uci_data_t* uci_data); bool work_ul(srslte_uci_data_t* uci_data);
@ -84,7 +86,6 @@ private:
/* Methods for UL */ /* Methods for UL */
bool encode_uplink(mac_interface_phy_lte::tb_action_ul_t* action, srslte_uci_data_t* uci_data); 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_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_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); 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(); uint32_t get_wideband_cqi();

@ -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); 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); 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_rar_grant_tti(uint32_t tti);
void set_dl_pending_ack(srslte_dl_sf_cfg_t* sf, void set_dl_pending_ack(srslte_dl_sf_cfg_t* sf,
@ -138,10 +146,7 @@ public:
srslte_pdsch_ack_resource_t resource); 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); 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, void worker_end(void* h, bool tx_enable, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time);
bool tx_enable,
srslte::rf_buffer_t& buffer,
srslte::rf_timestamp_t& tx_time);
void set_cell(const srslte_cell_t& c); void set_cell(const srslte_cell_t& c);
void set_nof_workers(uint32_t nof_workers); void set_nof_workers(uint32_t nof_workers);
@ -184,7 +189,7 @@ private:
std::mutex mtch_mutex; std::mutex mtch_mutex;
std::condition_variable mtch_cvar; std::condition_variable mtch_cvar;
uint32_t nof_workers = 0; uint32_t nof_workers = 0;
bool is_pending_tx_end = false; bool is_pending_tx_end = false;
@ -216,7 +221,7 @@ private:
srslte_dci_ul_t dci; srslte_dci_ul_t dci;
} pending_ul_grant_t; } pending_ul_grant_t;
pending_ul_grant_t pending_ul_grant[TTIMOD_SZ][SRSLTE_MAX_CARRIERS] = {}; 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 { typedef struct {
bool enable; bool enable;

@ -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 phy->set_pdsch_cfg(&pmch_cfg.pdsch_cfg); // set same config in PMCH decoder
// Define MBSFN subframes channel estimation and save default one // Define MBSFN subframes channel estimation and save default one
chest_mbsfn_cfg.filter_type = SRSLTE_CHEST_FILTER_TRIANGLE; chest_mbsfn_cfg.filter_type = SRSLTE_CHEST_FILTER_TRIANGLE;
chest_mbsfn_cfg.filter_coef[0] = 0.1; chest_mbsfn_cfg.filter_coef[0] = 0.1;
chest_mbsfn_cfg.estimator_alg = SRSLTE_ESTIMATOR_ALG_INTERPOLATE; chest_mbsfn_cfg.estimator_alg = SRSLTE_ESTIMATOR_ALG_INTERPOLATE;
chest_mbsfn_cfg.noise_alg = SRSLTE_NOISE_ALG_PSS; chest_mbsfn_cfg.noise_alg = SRSLTE_NOISE_ALG_PSS;
chest_default_cfg = ue_dl_cfg.chest_cfg; 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); 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) */ * Generate aperiodic CQI report if required, note that in case both aperiodic and periodic ones present, only
if (ul_grant_available && dci_ul.cqi_request) { * 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); 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*/ /* 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 // PCell sends SR and ACK
if (cc_idx == 0) { if (uci_data != nullptr) {
set_uci_sr(uci_data); set_uci_sr(uci_data);
// This must be called after set_uci_sr() and set_uci_*_cqi // 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); set_uci_ack(uci_data, ul_grant_available, dci_ul.dai, ul_action.tb.enabled);
} }
// Generate uplink signal, include uci data on only PCell // 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 // Prepare to receive ACK through PHICH
if (ul_action.expect_ack) { 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; ue_dl_cfg.cfg.dci = dci_cfg;
} }

@ -364,6 +364,18 @@ bool phy_common::get_ul_pending_grant(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, u
return ret; return ret;
} }
uint32_t phy_common::get_ul_uci_cc(uint32_t tti_tx) const
{
std::lock_guard<std::mutex> 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 // SF->TTI at which PHICH is received
void phy_common::set_ul_received_ack(srslte_dl_sf_cfg_t* sf, void phy_common::set_ul_received_ack(srslte_dl_sf_cfg_t* sf,
uint32_t cc_idx, uint32_t cc_idx,

@ -245,12 +245,22 @@ void sf_worker::work_imp()
srslte_uci_data_t uci_data; srslte_uci_data_t uci_data;
reset_uci(&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--) { 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 // 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));
} }
} }
} }

Loading…
Cancel
Save