diff --git a/lib/include/srsran/common/interfaces_common.h b/lib/include/srsran/common/interfaces_common.h index 1439b16d1..3c9cb19e6 100644 --- a/lib/include/srsran/common/interfaces_common.h +++ b/lib/include/srsran/common/interfaces_common.h @@ -56,6 +56,9 @@ struct rf_args_t { std::array ch_rx_bands; std::array ch_tx_bands; + + FILE** rx_files; // Array of pre-opened FILE* for rx instead of a real device + FILE** tx_files; // Array of pre-opened FILE* for tx instead of a real device }; class srsran_gw_config_t diff --git a/lib/include/srsran/radio/radio.h b/lib/include/srsran/radio/radio.h index defe4c84c..b0cdf01f7 100644 --- a/lib/include/srsran/radio/radio.h +++ b/lib/include/srsran/radio/radio.h @@ -158,6 +158,19 @@ private: */ bool open_dev(const uint32_t& device_idx, const std::string& device_name, const std::string& devive_args); + /** + * Helper method for opening a file-based RF device abstraction + * + * @param device_idx Device index + * @param rx_files Array of pre-opened FILE* for rx + * @param tx_files Array of pre-opened FILE* for tx + * @param nof_channels Number of elements in each array @p rx_files and @p tx_files + * @param base_srate Sampling rate in Hz + * @return it returns true if the device was opened successful, otherwise it returns false + */ + bool + open_dev(const uint32_t& device_idx, FILE** rx_files, FILE** tx_files, uint32_t nof_channels, uint32_t base_srate); + /** * Helper method for transmitting over a single RF device. This function maps automatically the logical transmit * buffers to the physical RF buffers for the given device. diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index a8694ca02..25b742117 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -103,11 +103,30 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_) rx_channel_mapping.set_config(nof_channels_x_dev, nof_antennas); // Init and start Radios - for (uint32_t device_idx = 0; device_idx < (uint32_t)device_args_list.size(); device_idx++) { - if (not open_dev(device_idx, args.device_name, device_args_list[device_idx])) { - logger.error("Error opening RF device %d", device_idx); + if (args.device_name != "file" || device_args_list[0] != "auto") { + // regular RF device + for (uint32_t device_idx = 0; device_idx < (uint32_t)device_args_list.size(); device_idx++) { + if (not open_dev(device_idx, args.device_name, device_args_list[device_idx])) { + logger.error("Error opening RF device %d", device_idx); + return SRSRAN_ERROR; + } + } + } else { + // file-based RF device abstraction using pre-opened FILE* objects + if (args.rx_files == nullptr && args.tx_files == nullptr) { + logger.error("File-based RF device abstraction requested, but no files provided"); return SRSRAN_ERROR; } + for (uint32_t device_idx = 0; device_idx < (uint32_t)device_args_list.size(); device_idx++) { + if (not open_dev(device_idx, + &args.rx_files[device_idx * nof_channels_x_dev], + &args.tx_files[device_idx * nof_channels_x_dev], + nof_channels_x_dev, + args.srate_hz)) { + logger.error("Error opening RF device %d", device_idx); + return SRSRAN_ERROR; + } + } } is_start_of_burst = true; @@ -473,6 +492,29 @@ bool radio::open_dev(const uint32_t& device_idx, const std::string& device_name, return true; } +bool radio::open_dev(const uint32_t &device_idx, FILE** rx_files, FILE** tx_files, uint32_t nof_channels, uint32_t base_srate) +{ + srsran_rf_t* rf_device = &rf_devices[device_idx]; + + srsran::console("Opening %d channels in RF device abstraction\n"); + + if (srsran_rf_open_file(rf_device, rx_files, tx_files, nof_channels, base_srate)) { + logger.error("Error opening RF device abstraction"); + return false; + } + + // Suppress radio stdout + srsran_rf_suppress_stdout(rf_device); + + // Register handler for processing O/U/L + srsran_rf_register_error_handler(rf_device, rf_msg_callback, this); + + // Get device info + rf_info[device_idx] = *srsran_rf_get_info(rf_device); + + return true; +} + bool radio::tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, const srsran_timestamp_t& tx_time_) { uint32_t nof_samples = buffer.get_nof_samples();