diff --git a/lib/include/srsran/interfaces/ue_nr_interfaces.h b/lib/include/srsran/interfaces/ue_nr_interfaces.h index 45603cb62..e78e2655a 100644 --- a/lib/include/srsran/interfaces/ue_nr_interfaces.h +++ b/lib/include/srsran/interfaces/ue_nr_interfaces.h @@ -49,7 +49,11 @@ public: * @brief Describes a cell select result */ struct cell_select_result_t { - bool successful = false; ///< Cell was found and physical layer is synchronised + enum { + ERROR = 0, ///< The cell selection procedure failed due a to an invalid configuration + UNSUCCESFUL, ///< The cell selection failed to find and synchronise the SSB + SUCCESFUL, ///< The cell selection was succesful, resulting in a camping state + } status; }; /** diff --git a/lib/include/srsran/radio/radio_dummy.h b/lib/include/srsran/radio/radio_dummy.h index a723859ba..4d947a41b 100644 --- a/lib/include/srsran/radio/radio_dummy.h +++ b/lib/include/srsran/radio/radio_dummy.h @@ -32,15 +32,10 @@ namespace srsran { /** - * Implementation of the radio interface for the PHY + * Implementation of radio dummy for the PHY testing * - * It uses the rf C library object to access the underlying radio. This implementation uses a flat array to - * transmit/receive samples for all RF channels. The N carriers and P antennas are mapped into M=NP RF channels (M <= - * SRSRAN_MAX_CHANNELS). Note that all carriers must have the same number of antennas. - * - * The underlying radio receives and transmits M RF channels synchronously from possibly multiple radios using the same - * rf driver object. In the current implementation, the mapping between N carriers and P antennas is sequentially, eg: - * [carrier_0_port_0, carrier_0_port_1, carrier_1_port_0, carrier_1_port_1, ..., carrier_N_port_N] + * It uses ringbuffers from srsRAN library to emulate baseband transmission and reception. The current implementation + * does not support dynamic sampling rates, gains and frequencies. */ class radio_dummy : public srsran::radio_base, public srsran::radio_interface_phy { diff --git a/srsue/hdr/stack/ue_stack_nr.h b/srsue/hdr/stack/ue_stack_nr.h index c465a881b..732460dec 100644 --- a/srsue/hdr/stack/ue_stack_nr.h +++ b/srsue/hdr/stack/ue_stack_nr.h @@ -111,6 +111,7 @@ public: void add_eps_bearer(uint8_t eps_bearer_id, srsran::srsran_rat_t rat, uint32_t lcid) final {} void remove_eps_bearer(uint8_t eps_bearer_id) final {} void reset_eps_bearers() final {} + void cell_select_completed(const cell_select_result_t& result) override; private: void run_thread() final; diff --git a/srsue/src/phy/nr/slot_sync.cc b/srsue/src/phy/nr/slot_sync.cc index 1d96a2cd6..aef0a23a1 100644 --- a/srsue/src/phy/nr/slot_sync.cc +++ b/srsue/src/phy/nr/slot_sync.cc @@ -104,27 +104,32 @@ int slot_sync::recv_callback(srsran::rf_buffer_t& data, srsran_timestamp_t* rx_t bool slot_sync::run_sfn_sync() { + // Run UE SYNC process using the temporal SFN process buffer srsran_ue_sync_nr_outcome_t outcome = {}; if (srsran_ue_sync_nr_zerocopy(&ue_sync_nr, sfn_sync_buff.to_cf_t(), &outcome) < SRSRAN_SUCCESS) { logger.error("SYNC: error in zerocopy"); return false; } + // If in sync, update slot index if (outcome.in_sync) { slot_cfg.idx = outcome.sfn * SRSRAN_NSLOTS_PER_FRAME_NR(srsran_subcarrier_spacing_15kHz) + outcome.sf_idx; } + // Return true if the PHY in-sync return outcome.in_sync; } bool slot_sync::run_camping(srsran::rf_buffer_t& buffer, srsran::rf_timestamp_t& timestamp) { + // Run UE SYNC process using an external baseband buffer srsran_ue_sync_nr_outcome_t outcome = {}; if (srsran_ue_sync_nr_zerocopy(&ue_sync_nr, buffer.to_cf_t(), &outcome) < SRSRAN_SUCCESS) { logger.error("SYNC: error in zerocopy"); return false; } + // If in sync, update slot index if (outcome.in_sync) { slot_cfg.idx = outcome.sfn * SRSRAN_NSLOTS_PER_FRAME_NR(srsran_subcarrier_spacing_15kHz) + outcome.sf_idx; } @@ -132,6 +137,7 @@ bool slot_sync::run_camping(srsran::rf_buffer_t& buffer, srsran::rf_timestamp_t& // Set RF timestamp *timestamp.get_ptr(0) = outcome.timestamp; + // Return true if the PHY in-sync return outcome.in_sync; } diff --git a/srsue/src/phy/sync_sa.cc b/srsue/src/phy/sync_sa.cc index 7869ea112..dcb06ca83 100644 --- a/srsue/src/phy/sync_sa.cc +++ b/srsue/src/phy/sync_sa.cc @@ -149,10 +149,16 @@ rrc_interface_phy_nr::cell_select_result_t sync_sa::cell_select_run(const phy_in { std::unique_lock ul(rrc_mutex); + // By default, the result is set to error + rrc_interface_phy_nr::cell_select_result_t result = {}; + result.status = rrc_interface_phy_nr::cell_select_result_t::ERROR; + // Wait the FSM to transition to IDLE if (!wait_idle()) { logger.error("Cell Search: SYNC thread didn't transition to IDLE after 100 ms\n"); - return {}; + + // Return default result with error status + return result; } rrc_proc_state = PROC_SELECT_RUNNING; @@ -170,19 +176,21 @@ rrc_interface_phy_nr::cell_select_result_t sync_sa::cell_select_run(const phy_in cfg.ssb.srate_hz = srate_hz; if (slot_synchronizer.set_sync_cfg(cfg)) { logger.error("Cell Search: Failed setting slot synchronizer configuration"); - return {}; + + // Return default result with error status + return result; } // SFN synchronization phy_state.run_sfn_sync(); - // Determine if the procedure was successful if it is camping - rrc_interface_phy_nr::cell_select_result_t result = {}; - result.successful = phy_state.is_camping(); - if (result.successful) { + // Determine if the procedure was successful if the current state is camping, otherwise it is unsuccessful + if (phy_state.is_camping()) { logger.info("Cell Select: SFN synchronized. CAMPING..."); + result.status = rrc_interface_phy_nr::cell_select_result_t::SUCCESFUL; } else { logger.info("Cell Select: Could not synchronize SFN"); + result.status = rrc_interface_phy_nr::cell_select_result_t::UNSUCCESFUL; } rrc_proc_state = PROC_IDLE; @@ -278,7 +286,7 @@ void sync_sa::run_state_cell_camping() } srsran::phy_common_interface::worker_context_t context; - context.sf_idx = tti; + context.sf_idx = slot_synchronizer.get_slot_cfg().idx; context.worker_ptr = nr_worker; context.last = true; // Set last if standalone last_rx_time.add(FDD_HARQ_DELAY_DL_MS * 1e-3); diff --git a/srsue/src/stack/ue_stack_nr.cc b/srsue/src/stack/ue_stack_nr.cc index 7b7b3358c..695060cce 100644 --- a/srsue/src/stack/ue_stack_nr.cc +++ b/srsue/src/stack/ue_stack_nr.cc @@ -202,4 +202,9 @@ void ue_stack_nr::set_phy_config_complete(bool status) sync_task_queue.push([this, status]() { rrc->set_phy_config_complete(status); }); } +void ue_stack_nr::cell_select_completed(const rrc_interface_phy_nr::cell_select_result_t& result) +{ + sync_task_queue.push([this, result]() { rrc->cell_select_completed(result); }); +} + } // namespace srsue diff --git a/test/phy/nr_phy_test.cc b/test/phy/nr_phy_test.cc index 43b603911..843121ef0 100644 --- a/test/phy/nr_phy_test.cc +++ b/test/phy/nr_phy_test.cc @@ -230,7 +230,8 @@ int main(int argc, char** argv) // Start cell selection procedure srsue::rrc_interface_phy_nr::cell_select_result_t cs_res = tb.run_cell_select(args.phy_cfg.carrier, args.phy_cfg.get_ssb_cfg()); - srsran_assert(cs_res.successful, "Failed to perform cell selection"); + srsran_assert(cs_res.status == srsue::rrc_interface_phy_nr::cell_select_result_t::SUCCESFUL, + "Failed to perform cell selection"); // Run per TTI basis while (tb.run_tti()) {