diff --git a/lib/include/srsran/radio/radio_dummy.h b/lib/include/srsran/radio/radio_dummy.h index e5a9decb6..a723859ba 100644 --- a/lib/include/srsran/radio/radio_dummy.h +++ b/lib/include/srsran/radio/radio_dummy.h @@ -107,7 +107,7 @@ private: } } - void advance_tx_timestamp(uint64_t ts) + void advance_tx_timestamp(uint64_t ts, bool round_sf = false) { std::lock_guard lock(tx_mutex); @@ -116,9 +116,15 @@ private: return; } - // Calculate transmission gap in samples + // Calculate transmission gap uint32_t tx_gap = (uint32_t)(ts - tx_timestamp); + // Round gap to subframe size + if (round_sf) { + uint64_t sf_sz = (uint64_t)(srate_hz / 1e3); + tx_gap = sf_sz * SRSRAN_CEIL(tx_gap, sf_sz); + } + // Skip zeros if there is no gap if (tx_gap == 0) { return; @@ -128,7 +134,7 @@ private: write_zeros_ring_buffers(tx_ring_buffers, tx_gap); // Update new transmit timestamp - tx_timestamp = ts; + tx_timestamp += tx_gap; } public: @@ -139,6 +145,9 @@ public: for (auto& rb : rx_ring_buffers) { srsran_ringbuffer_free(&rb); } + for (auto& rb : tx_ring_buffers) { + srsran_ringbuffer_free(&rb); + } if (temp_buffer) { free(temp_buffer); } @@ -208,7 +217,7 @@ public: // Check if the transmission is in the past if (tx_time_n < tx_timestamp) { - logger.error("Error transmission in the past"); + logger.error("Error transmission in the past for %d samples", (int)(tx_timestamp - tx_time_n)); return false; } @@ -231,7 +240,7 @@ public: bool rx_now(srsran::rf_buffer_interface& buffer, srsran::rf_timestamp_interface& rxd_time) override { // Advance Tx buffer - advance_tx_timestamp(rx_timestamp + buffer.get_nof_samples()); + advance_tx_timestamp(rx_timestamp + buffer.get_nof_samples(), true); // Read samples read_ring_buffers(rx_ring_buffers, buffer.to_cf_t(), buffer.get_nof_samples()); diff --git a/srsenb/src/phy/nr/slot_worker.cc b/srsenb/src/phy/nr/slot_worker.cc index 6ceb3e43e..0dba28c1b 100644 --- a/srsenb/src/phy/nr/slot_worker.cc +++ b/srsenb/src/phy/nr/slot_worker.cc @@ -18,7 +18,7 @@ #ifdef DEBUG_WRITE_FILE FILE* f; -static uint32_t num_slots = 0; +static uint32_t num_slots = 0; static uint32_t slots_to_dump = 10; #endif @@ -284,9 +284,8 @@ bool slot_worker::work_dl() // Releases synchronization lock and allow next worker to retrieve scheduling results sync.release(); - // Abort if the scheduling failed + // Abort DL processing if the scheduling returned an invalid pointer if (dl_sched_ptr == nullptr) { - logger.error("Error retrieving DL scheduling"); return false; } diff --git a/srsue/src/phy/nr/slot_sync.cc b/srsue/src/phy/nr/slot_sync.cc index 35fc2cc02..1d96a2cd6 100644 --- a/srsue/src/phy/nr/slot_sync.cc +++ b/srsue/src/phy/nr/slot_sync.cc @@ -27,8 +27,12 @@ static int slot_sync_recv_callback(void* ptr, cf_t** buffer, uint32_t nsamples, if (ptr == nullptr) { return SRSRAN_ERROR_INVALID_INPUTS; } - slot_sync* sync = (slot_sync*)ptr; - srsran::rf_buffer_t rf_buffer(buffer, nsamples); + slot_sync* sync = (slot_sync*)ptr; + + cf_t* buffer_ptr[SRSRAN_MAX_CHANNELS] = {}; + buffer_ptr[0] = buffer[0]; + + srsran::rf_buffer_t rf_buffer(buffer_ptr, nsamples); return sync->recv_callback(rf_buffer, ts); } diff --git a/srsue/src/phy/sync_sa.cc b/srsue/src/phy/sync_sa.cc index 17f45104a..7869ea112 100644 --- a/srsue/src/phy/sync_sa.cc +++ b/srsue/src/phy/sync_sa.cc @@ -19,7 +19,12 @@ sync_sa::sync_sa(srslog::basic_logger& logger_, worker_pool& workers_) : logger(logger_), workers(workers_), slot_synchronizer(logger_), searcher(logger_), srsran::thread("SYNC") {} -sync_sa::~sync_sa() {} +sync_sa::~sync_sa() +{ + if (rx_buffer != nullptr) { + free(rx_buffer); + } +} bool sync_sa::init(const args_t& args, stack_interface_phy_nr* stack_, srsran::radio_interface_phy* radio_) { diff --git a/test/phy/dummy_gnb_stack.h b/test/phy/dummy_gnb_stack.h index f31637f6b..304f9a1f6 100644 --- a/test/phy/dummy_gnb_stack.h +++ b/test/phy/dummy_gnb_stack.h @@ -513,6 +513,25 @@ public: return nullptr; } + // Schedule SSB before UL + for (uint32_t ssb_idx = 0; ssb_idx < SRSRAN_SSB_NOF_CANDIDATES; ssb_idx++) { + if (phy_cfg.ssb.position_in_burst[ssb_idx]) { + srsran_mib_nr_t mib = {}; + mib.ssb_idx = ssb_idx; + mib.sfn = slot_cfg.idx / SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); + mib.hrf = (slot_cfg.idx % SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs)) >= + SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs) / 2; + + mac_interface_phy_nr::ssb_t ssb = {}; + if (srsran_pbch_msg_nr_mib_pack(&mib, &ssb.pbch_msg) < SRSRAN_SUCCESS) { + logger.error("Error Packing MIB in slot %d", slot_cfg.idx); + continue; + } + ssb.pbch_msg.ssb_idx = (uint32_t)ssb_idx; + dl_sched.ssb.push_back(ssb); + } + } + // Check if the UL slot is valid, if not skip UL scheduling if (not srsran_duplex_nr_is_ul(&phy_cfg.duplex, phy_cfg.carrier.scs, TTI_TX(slot_cfg.idx))) { return &dl_sched; @@ -537,25 +556,6 @@ public: } } - // Schedule SSB - for (uint32_t ssb_idx = 0; ssb_idx < SRSRAN_SSB_NOF_CANDIDATES; ssb_idx++) { - if (phy_cfg.ssb.position_in_burst[ssb_idx]) { - srsran_mib_nr_t mib = {}; - mib.ssb_idx = ssb_idx; - mib.sfn = slot_cfg.idx / SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs); - mib.hrf = (slot_cfg.idx % SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs)) >= - SRSRAN_NSLOTS_PER_FRAME_NR(phy_cfg.carrier.scs) / 2; - - mac_interface_phy_nr::ssb_t ssb = {}; - if (srsran_pbch_msg_nr_mib_pack(&mib, &ssb.pbch_msg) < SRSRAN_SUCCESS) { - logger.error("Error Packing MIB in slot %d", slot_cfg.idx); - continue; - } - ssb.pbch_msg.ssb_idx = (uint32_t)ssb_idx; - dl_sched.ssb.push_back(ssb); - } - } - return &dl_sched; } diff --git a/test/phy/dummy_ue_stack.h b/test/phy/dummy_ue_stack.h index 8dd740dd9..b8afa0765 100644 --- a/test/phy/dummy_ue_stack.h +++ b/test/phy/dummy_ue_stack.h @@ -66,6 +66,11 @@ private: metrics_t metrics = {}; srsue::phy_interface_stack_nr& phy; + // Atributes to flag configuration PHy complete + bool configuration_complete = false; + std::mutex configuration_complete_mutex; + std::condition_variable configuration_complete_cvar; + // Attributes for throttling PHY and avoiding PHY free-running bool pending_tti = false; std::mutex pending_tti_mutex; @@ -195,7 +200,21 @@ public: metrics.sr_count = 0; } - void set_phy_config_complete(bool status) override {} + void set_phy_config_complete(bool status) override + { + std::unique_lock lock(configuration_complete_mutex); + configuration_complete = true; + configuration_complete_cvar.notify_all(); + } + + void wait_phy_config_complete() + { + std::unique_lock lock(configuration_complete_mutex); + while (not configuration_complete) { + configuration_complete_cvar.wait(lock); + } + configuration_complete = false; + } bool get_cell_search_finished() { diff --git a/test/phy/test_bench.h b/test/phy/test_bench.h index 4097a1eae..5b208c558 100644 --- a/test/phy/test_bench.h +++ b/test/phy/test_bench.h @@ -128,6 +128,9 @@ public: return; } + // Wait for UE to notify stack that the configuration is completed + ue_stack.wait_phy_config_complete(); + // Make sure PHY log is not set by UE or gNb PHY set_handler_enabled(false); if (args.phy_lib_log_level == "info") {