diff --git a/lib/include/srslte/common/string_helpers.h b/lib/include/srslte/common/string_helpers.h index d49580ff6..3f4bd2614 100644 --- a/lib/include/srslte/common/string_helpers.h +++ b/lib/include/srslte/common/string_helpers.h @@ -42,7 +42,7 @@ static inline std::string string_remove_char(const std::string& input, char c) while (p1 != std::string::npos) { ret.erase(p1); - p1 = ret.find(' '); + p1 = ret.find(c); } return ret; diff --git a/lib/include/srslte/interfaces/radio_interfaces.h b/lib/include/srslte/interfaces/radio_interfaces.h index 71b375b34..83660ed49 100644 --- a/lib/include/srslte/interfaces/radio_interfaces.h +++ b/lib/include/srslte/interfaces/radio_interfaces.h @@ -56,6 +56,8 @@ public: virtual void** to_void() = 0; virtual cf_t** to_cf_t() = 0; virtual uint32_t size() = 0; + virtual void set_nof_samples(uint32_t n) = 0; + virtual uint32_t get_nof_samples() const = 0; }; /** @@ -119,22 +121,20 @@ public: * the buffer object. * * @param buffer Is the object that contains the pointers to all RF channels - * @param nof_samples Number of samples to transmit on all carriers and antennas * @param tx_time Time to transmit all signals * @return it returns true if the transmission was successful, otherwise it returns false */ - virtual bool tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const rf_timestamp_interface& tx_time) = 0; + virtual bool tx(rf_buffer_interface& buffer, const rf_timestamp_interface& tx_time) = 0; /** * Indicates the radio to receive from all antennas and carriers synchronously and store the samples * in the buffer object * * @param buffer Is the object where the samples will be stored - * @param nof_samples Number of samples to receive from all carriers and antennas * @param tx_time Time at which the samples were received. Note the time is the same for all carriers * @return */ - virtual bool rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_timestamp_interface& rxd_time) = 0; + virtual bool rx_now(rf_buffer_interface& buffer, rf_timestamp_interface& rxd_time) = 0; /** * Sets the TX frequency for all antennas in the provided carrier index diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index cfeedcede..3bd149d15 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -60,8 +60,8 @@ public: // trx functions void tx_end() override; - bool tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const rf_timestamp_interface& tx_time) override; - bool rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_timestamp_interface& rxd_time) override; + bool tx(rf_buffer_interface& buffer, const rf_timestamp_interface& tx_time) override; + bool rx_now(rf_buffer_interface& buffer, rf_timestamp_interface& rxd_time) override; // setter void set_tx_freq(const uint32_t& carrier_idx, const double& freq) override; @@ -165,7 +165,6 @@ private: */ bool tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, - const uint32_t& nof_samples_, const srslte_timestamp_t& tx_time_); /** @@ -174,13 +173,11 @@ private: * * @param device_idx Device index * @param buffer Common receive buffers - * @param nof_samples Number of samples to receive * @param rxd_time Points at the receive time (write only) * @return it returns true if the reception was successful, otherwise it returns false */ bool rx_dev(const uint32_t& device_idx, const rf_buffer_interface& buffer, - const uint32_t& nof_samples, srslte_timestamp_t* rxd_time); /** diff --git a/lib/include/srslte/radio/rf_buffer.h b/lib/include/srslte/radio/rf_buffer.h index bb0a3b7f3..41c3f6df1 100644 --- a/lib/include/srslte/radio/rf_buffer.h +++ b/lib/include/srslte/radio/rf_buffer.h @@ -57,17 +57,22 @@ public: * contain up to SRSLTE_MAX_CHANNELS pointers * @param data Flat array to use as initializer for the internal buffer pointers */ - explicit rf_buffer_t(cf_t* data[SRSLTE_MAX_CHANNELS]) + explicit rf_buffer_t(cf_t* data[SRSLTE_MAX_CHANNELS], uint32_t nof_samples_) { for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) { sample_buffer[i] = data[i]; } + nof_samples = nof_samples_; } /** * Creates an object from a single array pointer. The rest of the channel pointers will be left to NULL * @param data Flat array to use as initializer for the internal buffer pointers */ - explicit rf_buffer_t(cf_t* data) { sample_buffer[0] = data; } + explicit rf_buffer_t(cf_t* data, uint32_t nof_samples_) + { + sample_buffer[0] = data; + nof_samples = nof_samples_; + } /** * Default constructor leaves the internal pointers to NULL */ @@ -119,11 +124,14 @@ public: void** to_void() override { return (void**)sample_buffer.data(); } cf_t** to_cf_t() override { return sample_buffer.data(); } uint32_t size() override { return nof_subframes * SRSLTE_SF_LEN_MAX; } + void set_nof_samples(uint32_t n) override { nof_samples = n; } + uint32_t get_nof_samples() const override { return nof_samples; } private: std::array sample_buffer = {}; bool allocated = false; uint32_t nof_subframes = 0; + uint32_t nof_samples = 0; void free_all() { for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) { diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 688c5b02a..17278d49c 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -88,7 +88,7 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_) // Split multiple RF channels using `;` delimiter std::vector device_args_list; - string_parse_list(args.device_args, ',', device_args_list); + string_parse_list(args.device_args, ';', device_args_list); // Add auto if list is empty if (device_args_list.empty()) { @@ -211,7 +211,7 @@ bool radio::start_agc(bool tx_gain_same_rx) return true; } -bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_timestamp_interface& rxd_time) +bool radio::rx_now(rf_buffer_interface& buffer, rf_timestamp_interface& rxd_time) { bool ret = true; @@ -223,7 +223,7 @@ bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_ } for (uint32_t device_idx = 0; device_idx < (uint32_t)rf_devices.size(); device_idx++) { - ret &= rx_dev(device_idx, buffer, nof_samples, rxd_time.get_ptr(device_idx)); + ret &= rx_dev(device_idx, buffer, rxd_time.get_ptr(device_idx)); } return ret; @@ -231,7 +231,6 @@ bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, rf_ bool radio::rx_dev(const uint32_t& device_idx, const rf_buffer_interface& buffer, - const uint32_t& nof_samples, srslte_timestamp_t* rxd_time) { if (!is_initialized) { @@ -247,17 +246,17 @@ bool radio::rx_dev(const uint32_t& device_idx, return false; } - int ret = - srslte_rf_recv_with_time_multi(&rf_devices[device_idx], radio_buffers, nof_samples, true, full_secs, frac_secs); + int ret = srslte_rf_recv_with_time_multi( + &rf_devices[device_idx], radio_buffers, buffer.get_nof_samples(), true, full_secs, frac_secs); return ret > 0; } -bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const rf_timestamp_interface& tx_time) +bool radio::tx(rf_buffer_interface& buffer, const rf_timestamp_interface& tx_time) { bool ret = true; for (uint32_t device_idx = 0; device_idx < (uint32_t)rf_devices.size(); device_idx++) { - ret &= tx_dev(device_idx, buffer, nof_samples, tx_time.get(device_idx)); + ret &= tx_dev(device_idx, buffer, tx_time.get(device_idx)); } is_start_of_burst = false; @@ -303,10 +302,9 @@ bool radio::open_dev(const uint32_t& device_idx, const std::string& device_name, bool radio::tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, - const uint32_t& nof_samples_, const srslte_timestamp_t& tx_time_) { - uint32_t nof_samples = nof_samples_; + uint32_t nof_samples = buffer.get_nof_samples(); uint32_t sample_offset = 0; srslte_rf_t* rf_device = &rf_devices[device_idx]; diff --git a/lib/src/radio/test/CMakeLists.txt b/lib/src/radio/test/CMakeLists.txt index 58324584d..02d92e066 100644 --- a/lib/src/radio/test/CMakeLists.txt +++ b/lib/src/radio/test/CMakeLists.txt @@ -25,6 +25,11 @@ if(RF_FOUND) include_directories(${SRSGUI_INCLUDE_DIRS}) target_link_libraries(benchmark_radio ${SRSGUI_LIBRARIES}) endif(SRSGUI_FOUND) + if (ZEROMQ_FOUND) + add_test(benchmark_radio_multi_rf benchmark_radio -d zmq -a + tx_port=tcp://*:2000,rx_port=tcp://localhost:2000\;tx_port=tcp://*:2001,rx_port=tcp://localhost:2001\;tx_port=tcp://*:2002,rx_port=tcp://localhost:2002\;tx_port=tcp://*:2003,rx_port=tcp://localhost:2003\; + -p 4) + endif (ZEROMQ_FOUND) endif(RF_FOUND) diff --git a/lib/src/radio/test/benchmark_radio.cc b/lib/src/radio/test/benchmark_radio.cc index 304e2f02a..1f3b10778 100644 --- a/lib/src/radio/test/benchmark_radio.cc +++ b/lib/src/radio/test/benchmark_radio.cc @@ -39,7 +39,7 @@ using namespace srslte; #define SRSLTE_MAX_RADIOS 3 -static char radios_args[SRSLTE_MAX_RADIOS][64] = {"auto", "auto", "auto"}; +static std::array radios_args = {"auto", "auto", "auto"}; static char radio_device[64]; static log_filter log_h; @@ -77,9 +77,9 @@ void usage(char* prog) printf("Usage: %s [foabcderpstvhmFxw]\n", prog); printf("\t-f Carrier frequency in Hz [Default %f]\n", freq); printf("\t-g RF gain [Default AGC]\n"); - printf("\t-a Arguments for first radio [Default %s]\n", radios_args[0]); - printf("\t-b Arguments for second radio [Default %s]\n", radios_args[1]); - printf("\t-c Arguments for third radio [Default %s]\n", radios_args[2]); + printf("\t-a Arguments for first radio [Default %s]\n", radios_args[0].c_str()); + printf("\t-b Arguments for second radio [Default %s]\n", radios_args[1].c_str()); + printf("\t-c Arguments for third radio [Default %s]\n", radios_args[2].c_str()); printf("\t-d Radio device [Default %s]\n", radio_device); printf("\t-r number of radios 1-%d [Default %d]\n", SRSLTE_MAX_RADIOS, nof_radios); printf("\t-p number of ports 1-%d [Default %d]\n", SRSLTE_MAX_PORTS, nof_ports); @@ -111,16 +111,13 @@ void parse_args(int argc, char** argv) file_pattern = argv[optind]; break; case 'a': - strncpy(radios_args[0], argv[optind], 63); - radios_args[0][63] = '\0'; + radios_args[0] = std::string(argv[optind]); break; case 'b': - strncpy(radios_args[1], argv[optind], 63); - radios_args[1][63] = '\0'; + radios_args[1] = std::string(argv[optind]); break; case 'c': - strncpy(radios_args[2], argv[optind], 63); - radios_args[2][63] = '\0'; + radios_args[2] = std::string(argv[optind]); break; case 'd': strncpy(radio_device, argv[optind], 63); @@ -409,7 +406,8 @@ int main(int argc, char** argv) // receive each radio for (uint32_t r = 0; r < nof_radios; r++) { - radio_h[r]->rx_now(rf_buffers[r], frame_size, ts_rx[r]); + rf_buffers[r].set_nof_samples(frame_size); + radio_h[r]->rx_now(rf_buffers[r], ts_rx[r]); } // run agc @@ -424,7 +422,8 @@ int main(int argc, char** argv) for (uint32_t r = 0; r < nof_radios; r++) { ts_tx.copy(ts_rx[r]); ts_tx.add(0.004); - radio_h[r]->tx(rf_buffers[r], frame_size, ts_tx); + rf_buffers[r].set_nof_samples(frame_size); + radio_h[r]->tx(rf_buffers[r], ts_tx); } } diff --git a/srsenb/hdr/phy/phy_common.h b/srsenb/hdr/phy/phy_common.h index 52ab62089..72bc96eec 100644 --- a/srsenb/hdr/phy/phy_common.h +++ b/srsenb/hdr/phy/phy_common.h @@ -60,10 +60,9 @@ public: * * @param tx_sem_id Semaphore identifier, the worker thread pointer is used * @param buffer baseband IQ sample buffer - * @param nof_samples number of samples to transmit * @param tx_time timestamp to transmit samples */ - void worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, uint32_t nof_samples, srslte::rf_timestamp_t& tx_time); + void worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, srslte::rf_timestamp_t& tx_time); // Common objects phy_args_t params = {}; diff --git a/srsenb/src/phy/phy_common.cc b/srsenb/src/phy/phy_common.cc index 51d3dbbe0..9c2a5d939 100644 --- a/srsenb/src/phy/phy_common.cc +++ b/srsenb/src/phy/phy_common.cc @@ -126,7 +126,6 @@ void phy_common::set_ul_grants(uint32_t tti, const stack_interface_phy_lte::ul_s */ void phy_common::worker_end(void* tx_sem_id, srslte::rf_buffer_t& buffer, - uint32_t nof_samples, srslte::rf_timestamp_t& tx_time) { // Wait for the green light to transmit in the current TTI @@ -134,11 +133,11 @@ void phy_common::worker_end(void* tx_sem_id, // Run DL channel emulator if created if (dl_channel) { - dl_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), nof_samples, tx_time.get(0)); + dl_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), buffer.get_nof_samples(), tx_time.get(0)); } // Always transmit on single radio - radio->tx(buffer, nof_samples, tx_time); + radio->tx(buffer, tx_time); // Trigger MAC clock stack->tti_clock(); diff --git a/srsenb/src/phy/sf_worker.cc b/srsenb/src/phy/sf_worker.cc index 9f6abf5d8..bb43a5e12 100644 --- a/srsenb/src/phy/sf_worker.cc +++ b/srsenb/src/phy/sf_worker.cc @@ -179,7 +179,7 @@ void sf_worker::work_imp() } if (!running) { - phy->worker_end(this, tx_buffer, 0, tx_time); + phy->worker_end(this, tx_buffer, tx_time); return; } @@ -212,14 +212,14 @@ void sf_worker::work_imp() if (sf_type == SRSLTE_SF_NORM) { if (stack->get_dl_sched(tti_tx_dl, dl_grants) < 0) { Error("Getting DL scheduling from MAC\n"); - phy->worker_end(this, tx_buffer, 0, tx_time); + phy->worker_end(this, tx_buffer, tx_time); return; } } else { dl_grants[0].cfi = mbsfn_cfg.non_mbsfn_region_length; if (stack->get_mch_sched(tti_tx_dl, mbsfn_cfg.is_mcch, dl_grants)) { Error("Getting MCH packets from MAC\n"); - phy->worker_end(this, tx_buffer, 0, tx_time); + phy->worker_end(this, tx_buffer, tx_time); return; } } @@ -231,7 +231,7 @@ void sf_worker::work_imp() // Get UL scheduling for the TX TTI from MAC if (stack->get_ul_sched(tti_tx_ul, ul_grants_tx) < 0) { Error("Getting UL scheduling from MAC\n"); - phy->worker_end(this, tx_buffer, 0, tx_time); + phy->worker_end(this, tx_buffer, tx_time); return; } @@ -254,7 +254,8 @@ void sf_worker::work_imp() phy->set_ul_grants(t_rx, ul_grants); Debug("Sending to radio\n"); - phy->worker_end(this, tx_buffer, SRSLTE_SF_LEN_PRB(phy->get_nof_prb(0)), tx_time); + tx_buffer.set_nof_samples(SRSLTE_SF_LEN_PRB(phy->get_nof_prb(0))); + phy->worker_end(this, tx_buffer, tx_time); #ifdef DEBUG_WRITE_FILE fwrite(signal_buffer_tx, SRSLTE_SF_LEN_PRB(phy->cell.nof_prb) * sizeof(cf_t), 1, f); diff --git a/srsenb/src/phy/txrx.cc b/srsenb/src/phy/txrx.cc index e710c949e..dc111e343 100644 --- a/srsenb/src/phy/txrx.cc +++ b/srsenb/src/phy/txrx.cc @@ -133,7 +133,8 @@ void txrx::run_thread() } } - radio_h->rx_now(buffer, sf_len, timestamp); + buffer.set_nof_samples(sf_len); + radio_h->rx_now(buffer, timestamp); if (ul_channel) { ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), sf_len, timestamp.get(0)); diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index 903f01708..91591f766 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -188,15 +188,14 @@ public: } bool tx(srslte::rf_buffer_interface& buffer, - const uint32_t& nof_samples, const srslte::rf_timestamp_interface& tx_time) override { int err = SRSLTE_SUCCESS; // Get number of bytes to write - uint32_t nbytes = static_cast(sizeof(cf_t)) * nof_samples; + uint32_t nbytes = static_cast(sizeof(cf_t)) * buffer.get_nof_samples(); - log_h.debug("tx %d\n", nof_samples); + log_h.debug("tx %d\n", buffer.get_nof_samples()); // Write ring buffer for (uint32_t i = 0; i < ringbuffers_tx.size() and err >= SRSLTE_SUCCESS; i++) { @@ -211,15 +210,14 @@ public: } void tx_end() override {} bool rx_now(srslte::rf_buffer_interface& buffer, - const uint32_t& nof_samples, srslte::rf_timestamp_interface& rxd_time) override { int err = SRSLTE_SUCCESS; - log_h.info("rx_now %d\n", nof_samples); + log_h.info("rx_now %d\n", buffer.get_nof_samples()); // Get number of bytes to read - uint32_t nbytes = static_cast(sizeof(cf_t)) * nof_samples; + uint32_t nbytes = static_cast(sizeof(cf_t)) * buffer.get_nof_samples(); // Write ring buffer for (uint32_t i = 0; i < ringbuffers_rx.size() and err >= SRSLTE_SUCCESS; i++) { @@ -233,7 +231,7 @@ public: // Copy new timestamp if (std::isnormal(rx_srate)) { - ts_rx.add(static_cast(nof_samples) / rx_srate); + ts_rx.add(static_cast(buffer.get_nof_samples()) / rx_srate); } // Notify Rx diff --git a/srsue/hdr/phy/phy_common.h b/srsue/hdr/phy/phy_common.h index 981791c48..bef5216e8 100644 --- a/srsue/hdr/phy/phy_common.h +++ b/srsue/hdr/phy/phy_common.h @@ -141,7 +141,6 @@ public: void worker_end(void* h, bool tx_enable, srslte::rf_buffer_t& buffer, - uint32_t nof_samples, srslte::rf_timestamp_t& tx_time); void set_cell(const srslte_cell_t& c); diff --git a/srsue/hdr/phy/search.h b/srsue/hdr/phy/search.h index b9768d868..9739e5c29 100644 --- a/srsue/hdr/phy/search.h +++ b/srsue/hdr/phy/search.h @@ -31,7 +31,7 @@ namespace srsue { class search_callback { public: - virtual int radio_recv_fnc(srslte::rf_buffer_t&, uint32_t nsamples, srslte_timestamp_t* rx_time) = 0; + virtual int radio_recv_fnc(srslte::rf_buffer_t&, srslte_timestamp_t* rx_time) = 0; virtual void set_ue_sync_opts(srslte_ue_sync_t* q, float cfo) = 0; virtual srslte::radio_interface_phy* get_radio() = 0; virtual void set_rx_gain(float gain) = 0; diff --git a/srsue/hdr/phy/sync.h b/srsue/hdr/phy/sync.h index 44021410b..d7bf8d6d9 100644 --- a/srsue/hdr/phy/sync.h +++ b/srsue/hdr/phy/sync.h @@ -89,7 +89,7 @@ public: // Other functions void set_rx_gain(float gain) override; - int radio_recv_fnc(srslte::rf_buffer_t&, uint32_t nsamples, srslte_timestamp_t* rx_time) override; + int radio_recv_fnc(srslte::rf_buffer_t&, srslte_timestamp_t* rx_time) override; srslte::radio_interface_phy* get_radio() override { return radio_h; } diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index c02312426..c6c427336 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -524,7 +524,6 @@ bool phy_common::get_dl_pending_ack(srslte_ul_sf_cfg_t* sf, uint32_t cc_idx, srs void phy_common::worker_end(void* tx_sem_id, bool tx_enable, srslte::rf_buffer_t& buffer, - uint32_t nof_samples, srslte::rf_timestamp_t& tx_time) { // Wait for the green light to transmit in the current TTI @@ -537,10 +536,10 @@ void phy_common::worker_end(void* tx_sem_id, if (tx_enable) { if (ul_channel) { - ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), nof_samples, tx_time.get(0)); + ul_channel->run(buffer.to_cf_t(), buffer.to_cf_t(), buffer.get_nof_samples(), tx_time.get(0)); } - radio_h->tx(buffer, nof_samples, tx_time); + radio_h->tx(buffer, tx_time); } else { if (radio_h->is_continuous_tx()) { if (is_pending_tx_end) { @@ -550,11 +549,12 @@ void phy_common::worker_end(void* tx_sem_id, if (!radio_h->get_is_start_of_burst()) { if (ul_channel) { - srslte_vec_cf_zero(zeros_multi.get(0), nof_samples); - ul_channel->run(zeros_multi.to_cf_t(), zeros_multi.to_cf_t(), nof_samples, tx_time.get(0)); + srslte_vec_cf_zero(zeros_multi.get(0), buffer.get_nof_samples()); + ul_channel->run(zeros_multi.to_cf_t(), zeros_multi.to_cf_t(), buffer.get_nof_samples(), tx_time.get(0)); } - radio_h->tx(zeros_multi, nof_samples, tx_time); + zeros_multi.set_nof_samples(buffer.get_nof_samples()); + radio_h->tx(zeros_multi, tx_time); } } } else { diff --git a/srsue/src/phy/search.cc b/srsue/src/phy/search.cc index ba5c39d44..642aabfc0 100644 --- a/srsue/src/phy/search.cc +++ b/srsue/src/phy/search.cc @@ -39,8 +39,8 @@ namespace srsue { static int radio_recv_callback(void* obj, cf_t* data[SRSLTE_MAX_CHANNELS], uint32_t nsamples, srslte_timestamp_t* rx_time) { - srslte::rf_buffer_t x(data); - return ((search_callback*)obj)->radio_recv_fnc(x, nsamples, rx_time); + srslte::rf_buffer_t x(data, nsamples); + return ((search_callback*)obj)->radio_recv_fnc(x, rx_time); } static SRSLTE_AGC_CALLBACK(callback_set_rx_gain) diff --git a/srsue/src/phy/sf_worker.cc b/srsue/src/phy/sf_worker.cc index df896a783..c37dd781c 100644 --- a/srsue/src/phy/sf_worker.cc +++ b/srsue/src/phy/sf_worker.cc @@ -202,9 +202,9 @@ void sf_worker::set_config(uint32_t cc_idx, srslte::phy_cfg_t& phy_cfg) void sf_worker::work_imp() { - srslte::rf_buffer_t tx_signal_ptr = {}; + srslte::rf_buffer_t tx_signal_ptr = {}; if (!cell_initiated) { - phy->worker_end(this, false, tx_signal_ptr, 0, tx_time); + phy->worker_end(this, false, tx_signal_ptr, tx_time); } bool rx_signal_ok = false; @@ -255,6 +255,7 @@ void sf_worker::work_imp() } } } + tx_signal_ptr.set_nof_samples(nof_samples); // Set PRACH buffer signal pointer if (prach_ptr) { @@ -264,7 +265,7 @@ void sf_worker::work_imp() } // Call worker_end to transmit the signal - phy->worker_end(this, tx_signal_ready, tx_signal_ptr, nof_samples, tx_time); + phy->worker_end(this, tx_signal_ready, tx_signal_ptr, tx_time); if (rx_signal_ok) { update_measurements(); diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index 0b05a3a53..e8329b559 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -45,8 +45,8 @@ namespace srsue { static int radio_recv_callback(void* obj, cf_t* data[SRSLTE_MAX_CHANNELS], uint32_t nsamples, srslte_timestamp_t* rx_time) { - srslte::rf_buffer_t x(data); - return ((sync*)obj)->radio_recv_fnc(x, nsamples, rx_time); + srslte::rf_buffer_t x(data, nsamples); + return ((sync*)obj)->radio_recv_fnc(x, rx_time); } static SRSLTE_AGC_CALLBACK(callback_set_rx_gain) @@ -501,12 +501,13 @@ void sync::run_idle_state() { if (radio_h->is_init()) { uint32_t nsamples = 1920; - if (current_srate > 0) { + if (std::isnormal(current_srate) and current_srate > 0.0f) { nsamples = current_srate / 1000; } Debug("Discarding %d samples\n", nsamples); srslte_timestamp_t rx_time = {}; - if (radio_recv_fnc(dummy_buffer, nsamples, &rx_time) == SRSLTE_SUCCESS) { + dummy_buffer.set_nof_samples(nsamples); + if (radio_recv_fnc(dummy_buffer, &rx_time) == SRSLTE_SUCCESS) { log_h->console("SYNC: Receiving from radio while in IDLE_RX\n"); } // If radio is in locked state returns immediately. In that case, do a 1 ms sleep @@ -803,7 +804,7 @@ void sync::get_current_cell(srslte_cell_t* cell_, uint32_t* earfcn_) } } -int sync::radio_recv_fnc(srslte::rf_buffer_t& data, uint32_t nsamples, srslte_timestamp_t* rx_time) +int sync::radio_recv_fnc(srslte::rf_buffer_t& data, srslte_timestamp_t* rx_time) { // This function is designed for being called from the UE sync object which will pass a null rx_time in case // receive dummy samples. So, rf_timestamp points at dummy timestamp in case rx_time is not provided @@ -811,70 +812,70 @@ int sync::radio_recv_fnc(srslte::rf_buffer_t& data, uint32_t nsamples, srslte_ti srslte::rf_timestamp_t& rf_timestamp = (rx_time == nullptr) ? dummy_ts : last_rx_time; // Receive - if (radio_h->rx_now(data, nsamples, rf_timestamp)) { - srslte_timestamp_t dummy_flat_ts = {}; - - // Load flat timestamp - if (rx_time == nullptr) { - rx_time = &dummy_flat_ts; - } - *rx_time = rf_timestamp.get(0); - - // check timestamp reset - if (forced_rx_time_init || srslte_timestamp_iszero(&tti_ts) || srslte_timestamp_compare(rx_time, &tti_ts) < 0) { - if (srslte_timestamp_compare(rx_time, &tti_ts) < 0) { - log_h->warning("SYNC: radio time seems to be going backwards (rx_time=%f, tti_ts=%f)\n", - srslte_timestamp_real(rx_time), - srslte_timestamp_real(&tti_ts)); - // time-stamp will be set to rx time below and run_tti() will be called with MIN_TTI_JUMP - } - - // init tti_ts with last rx time - log_h->debug("SYNC: Setting initial TTI time to %f\n", srslte_timestamp_real(rx_time)); - srslte_timestamp_copy(&tti_ts, rx_time); - forced_rx_time_init = false; - } - - // Advance stack in time - if (srslte_timestamp_compare(rx_time, &tti_ts) >= 0) { - srslte_timestamp_t temp = {}; - srslte_timestamp_copy(&temp, rx_time); - srslte_timestamp_sub(&temp, tti_ts.full_secs, tti_ts.frac_secs); - int32_t tti_jump = static_cast(srslte_timestamp_uint64(&temp, 1e3)); - tti_jump = SRSLTE_MAX(tti_jump, MIN_TTI_JUMP); - if (tti_jump > MAX_TTI_JUMP) { - log_h->warning("SYNC: TTI jump of %d limited to %d\n", tti_jump, MAX_TTI_JUMP); - tti_jump = SRSLTE_MIN(tti_jump, MAX_TTI_JUMP); - } - - // Run stack - stack->run_tti(tti, tti_jump); - } - - // update timestamp - srslte_timestamp_copy(&tti_ts, rx_time); - - if (channel_emulator && rx_time) { - channel_emulator->set_srate((uint32_t)current_srate); - channel_emulator->run(data.to_cf_t(), data.to_cf_t(), nsamples, *rx_time); - } - - // Save signal for Intra-frequency measurement - if (srslte_cell_isvalid(&cell)) { - for (uint32_t i = 0; (uint32_t)i < intra_freq_meas.size(); i++) { - intra_freq_meas[i]->write(tti, data.get(i, 0, worker_com->args->nof_rx_ant), SRSLTE_SF_LEN_PRB(cell.nof_prb)); - - // Update RX gain - intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset); - } - } - - log_h->debug("SYNC: received %d samples from radio\n", nsamples); - - return nsamples; - } else { - return -1; + if (not radio_h->rx_now(data, rf_timestamp)) { + return SRSLTE_ERROR; } + + srslte_timestamp_t dummy_flat_ts = {}; + + // Load flat timestamp + if (rx_time == nullptr) { + rx_time = &dummy_flat_ts; + } + *rx_time = rf_timestamp.get(0); + + // check timestamp reset + if (forced_rx_time_init || srslte_timestamp_iszero(&tti_ts) || srslte_timestamp_compare(rx_time, &tti_ts) < 0) { + if (srslte_timestamp_compare(rx_time, &tti_ts) < 0) { + log_h->warning("SYNC: radio time seems to be going backwards (rx_time=%f, tti_ts=%f)\n", + srslte_timestamp_real(rx_time), + srslte_timestamp_real(&tti_ts)); + // time-stamp will be set to rx time below and run_tti() will be called with MIN_TTI_JUMP + } + + // init tti_ts with last rx time + log_h->debug("SYNC: Setting initial TTI time to %f\n", srslte_timestamp_real(rx_time)); + srslte_timestamp_copy(&tti_ts, rx_time); + forced_rx_time_init = false; + } + + // Advance stack in time + if (srslte_timestamp_compare(rx_time, &tti_ts) >= 0) { + srslte_timestamp_t temp = {}; + srslte_timestamp_copy(&temp, rx_time); + srslte_timestamp_sub(&temp, tti_ts.full_secs, tti_ts.frac_secs); + int32_t tti_jump = static_cast(srslte_timestamp_uint64(&temp, 1e3)); + tti_jump = SRSLTE_MAX(tti_jump, MIN_TTI_JUMP); + if (tti_jump > MAX_TTI_JUMP) { + log_h->warning("SYNC: TTI jump of %d limited to %d\n", tti_jump, MAX_TTI_JUMP); + tti_jump = SRSLTE_MIN(tti_jump, MAX_TTI_JUMP); + } + + // Run stack + stack->run_tti(tti, tti_jump); + } + + // update timestamp + srslte_timestamp_copy(&tti_ts, rx_time); + + if (channel_emulator and rx_time) { + channel_emulator->set_srate((uint32_t)current_srate); + channel_emulator->run(data.to_cf_t(), data.to_cf_t(), data.get_nof_samples(), *rx_time); + } + + // Save signal for Intra-frequency measurement + if (srslte_cell_isvalid(&cell)) { + for (uint32_t i = 0; (uint32_t)i < intra_freq_meas.size(); i++) { + intra_freq_meas[i]->write(tti, data.get(i, 0, worker_com->args->nof_rx_ant), SRSLTE_SF_LEN_PRB(cell.nof_prb)); + + // Update RX gain + intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset); + } + } + + log_h->debug("SYNC: received %d samples from radio\n", data.get_nof_samples()); + + return data.get_nof_samples(); } void sync::set_rx_gain(float gain) diff --git a/srsue/test/phy/scell_search_test.cc b/srsue/test/phy/scell_search_test.cc index 32c0dd751..aebc47619 100644 --- a/srsue/test/phy/scell_search_test.cc +++ b/srsue/test/phy/scell_search_test.cc @@ -559,8 +559,8 @@ int main(int argc, char** argv) if (radio) { // Receive radio - srslte::rf_buffer_t radio_buffer(baseband_buffer); - radio->rx_now(radio_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb), ts); + srslte::rf_buffer_t radio_buffer(baseband_buffer, SRSLTE_SF_LEN_PRB(cell_base.nof_prb)); + radio->rx_now(radio_buffer, ts); } else { // Run eNb simulator bool put_pdsch = serving_cell_pdsch_enable; diff --git a/srsue/test/phy/ue_phy_test.cc b/srsue/test/phy/ue_phy_test.cc index de401b89a..021580009 100644 --- a/srsue/test/phy/ue_phy_test.cc +++ b/srsue/test/phy/ue_phy_test.cc @@ -191,9 +191,7 @@ private: uint32_t get_count_late() { return count_late; } - bool tx(srslte::rf_buffer_interface& buffer, - const uint32_t& nof_samples, - const srslte::rf_timestamp_interface& tx_time) override + bool tx(srslte::rf_buffer_interface& buffer, const srslte::rf_timestamp_interface& tx_time) override { bool ret = true; notify_tx(); @@ -207,20 +205,20 @@ private: } tx_last_tx.copy(tx_time); - tx_last_tx.add((double)nof_samples / (double)tx_srate); + if (std::isnormal(tx_srate)) { + tx_last_tx.add((double)buffer.get_nof_samples() / (double)tx_srate); + } return ret; } void release_freq(const uint32_t& carrier_idx) override{}; void tx_end() override {} - bool rx_now(srslte::rf_buffer_interface& buffer, - const uint32_t& nof_samples, - srslte::rf_timestamp_interface& rxd_time) override + bool rx_now(srslte::rf_buffer_interface& buffer, srslte::rf_timestamp_interface& rxd_time) override { notify_rx_now(); std::lock_guard lock(mutex); - auto base_nsamples = (uint32_t)floorf(((float)nof_samples * base_srate) / rx_srate); + uint32_t base_nsamples = (uint32_t)floorf(((float)buffer.get_nof_samples() * base_srate) / rx_srate); for (uint32_t i = 0; i < ring_buffers.size(); i++) { cf_t* buf_ptr = ((buffer.get(i) != nullptr) && (base_srate == rx_srate)) ? buffer.get(i) : temp_buffer; @@ -240,7 +238,7 @@ private: auto decimation = (uint32_t)roundf(base_srate / rx_srate); // Perform decimation - for (uint32_t j = 0, k = 0; j < nof_samples; j++, k += decimation) { + for (uint32_t j = 0, k = 0; j < buffer.get_nof_samples(); j++, k += decimation) { buffer.get(i)[j] = buf_ptr[k]; } } else if (base_srate < rx_srate) { @@ -248,7 +246,7 @@ private: auto interpolation = (uint32_t)roundf(rx_srate / base_srate); // Perform zero order hold interpolation - for (uint32_t j = 0, k = 0; j < nof_samples; k++) { + for (uint32_t j = 0, k = 0; j < buffer.get_nof_samples(); k++) { for (uint32_t c = 0; c < interpolation; c++, j++) { buffer.get(i)[j] = buf_ptr[k]; }