mirror of https://github.com/pvnis/srsRAN_4G.git
Added multi gNb simulation and RF
parent
f5446422bc
commit
58ab8086ff
@ -0,0 +1,108 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_GNB_EMULATOR_H
|
||||
#define SRSRAN_GNB_EMULATOR_H
|
||||
|
||||
#include <srsran/phy/channel/channel.h>
|
||||
#include <srsran/radio/rf_timestamp.h>
|
||||
#include <srsran/srsran.h>
|
||||
#include <srsran/support/srsran_assert.h>
|
||||
|
||||
class gnb_emulator
|
||||
{
|
||||
private:
|
||||
uint32_t sf_len = 0;
|
||||
srsran_carrier_nr_t carrier = {};
|
||||
srsran_ssb_t ssb = {};
|
||||
srsran::channel channel;
|
||||
std::vector<cf_t> buffer;
|
||||
srslog::basic_logger& logger = srslog::fetch_basic_logger("GNB-EMULATOR");
|
||||
|
||||
public:
|
||||
struct args_t {
|
||||
double srate_hz;
|
||||
srsran_carrier_nr_t carrier;
|
||||
srsran_subcarrier_spacing_t ssb_scs;
|
||||
srsran_ssb_patern_t ssb_pattern;
|
||||
uint32_t ssb_periodicity_ms;
|
||||
srsran_duplex_mode_t duplex_mode;
|
||||
srsran::channel::args_t channel;
|
||||
std::string log_level = "warning";
|
||||
};
|
||||
|
||||
gnb_emulator(const args_t& args) : channel(args.channel, 1, srslog::fetch_basic_logger("GNB-EMULATOR"))
|
||||
{
|
||||
logger.set_level(srslog::str_to_basic_level(args.log_level));
|
||||
|
||||
srsran_assert(
|
||||
std::isnormal(args.srate_hz) and args.srate_hz > 0, "Invalid sampling rate (%.2f MHz)", args.srate_hz);
|
||||
|
||||
// Initialise internals
|
||||
sf_len = args.srate_hz / 1000;
|
||||
carrier = args.carrier;
|
||||
buffer.resize(sf_len);
|
||||
|
||||
srsran_ssb_args_t ssb_args = {};
|
||||
ssb_args.enable_encode = true;
|
||||
srsran_assert(srsran_ssb_init(&ssb, &ssb_args) == SRSRAN_SUCCESS, "SSB initialisation failed");
|
||||
|
||||
srsran_ssb_cfg_t ssb_cfg = {};
|
||||
ssb_cfg.srate_hz = args.srate_hz;
|
||||
ssb_cfg.center_freq_hz = args.carrier.dl_center_frequency_hz;
|
||||
ssb_cfg.ssb_freq_hz = args.carrier.ssb_center_freq_hz;
|
||||
ssb_cfg.scs = args.ssb_scs;
|
||||
ssb_cfg.pattern = args.ssb_pattern;
|
||||
ssb_cfg.duplex_mode = args.duplex_mode;
|
||||
ssb_cfg.periodicity_ms = args.ssb_periodicity_ms;
|
||||
srsran_assert(srsran_ssb_set_cfg(&ssb, &ssb_cfg) == SRSRAN_SUCCESS, "SSB set config failed");
|
||||
|
||||
// Configure channel
|
||||
channel.set_srate((uint32_t)args.srate_hz);
|
||||
}
|
||||
|
||||
int work(uint32_t sf_idx, cf_t* baseband_buffer, const srsran::rf_timestamp_t& ts)
|
||||
{
|
||||
logger.set_context(sf_idx);
|
||||
|
||||
// Zero buffer
|
||||
srsran_vec_cf_zero(buffer.data(), sf_len);
|
||||
|
||||
// Check if SSB needs to be sent
|
||||
if (srsran_ssb_send(&ssb, sf_idx)) {
|
||||
// Prepare PBCH message
|
||||
srsran_pbch_msg_nr_t msg = {};
|
||||
|
||||
// Add SSB
|
||||
if (srsran_ssb_add(&ssb, carrier.pci, &msg, buffer.data(), buffer.data()) < SRSRAN_SUCCESS) {
|
||||
logger.error("Error adding SSB");
|
||||
return SRSRAN_ERROR;
|
||||
}
|
||||
}
|
||||
|
||||
// Run channel
|
||||
cf_t* in[SRSRAN_MAX_CHANNELS] = {};
|
||||
cf_t* out[SRSRAN_MAX_CHANNELS] = {};
|
||||
in[0] = buffer.data();
|
||||
out[0] = buffer.data();
|
||||
channel.run(in, out, sf_len, ts.get(0));
|
||||
|
||||
// Add buffer to baseband buffer
|
||||
srsran_vec_sum_ccc(baseband_buffer, buffer.data(), baseband_buffer, sf_len);
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
~gnb_emulator() { srsran_ssb_free(&ssb); }
|
||||
};
|
||||
|
||||
#endif // SRSRAN_GNB_EMULATOR_H
|
@ -0,0 +1,142 @@
|
||||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
|
||||
#ifndef SRSRAN_GNB_RF_EMULATOR_H
|
||||
#define SRSRAN_GNB_RF_EMULATOR_H
|
||||
|
||||
#include "gnb_emulator.h"
|
||||
#include <set>
|
||||
#include <srsran/interfaces/radio_interfaces.h>
|
||||
#include <srsran/srslog/srslog.h>
|
||||
#include <srsran/srsran.h>
|
||||
#include <srsran/support/srsran_assert.h>
|
||||
|
||||
class gnb_rf_emulator final : public srsran::radio_interface_phy
|
||||
{
|
||||
private:
|
||||
const uint32_t BUFFER_SIZE_SF = 10;
|
||||
const std::string LOGNAME = "RF";
|
||||
uint32_t sf_len = 0;
|
||||
srsran_ringbuffer_t ringbuffer = {};
|
||||
uint32_t slot_idx = 0;
|
||||
std::atomic<bool> running = {true};
|
||||
srsran::rf_timestamp_t ts_write = {};
|
||||
std::vector<cf_t> buffer;
|
||||
std::vector<std::shared_ptr<gnb_emulator> > gnb_vector;
|
||||
|
||||
void run_async_slot()
|
||||
{
|
||||
// Early return if not running
|
||||
if (not running) {
|
||||
return;
|
||||
}
|
||||
|
||||
// Zero slot buffer
|
||||
srsran_vec_cf_zero(buffer.data(), sf_len);
|
||||
|
||||
for (std::shared_ptr<gnb_emulator>& gnb : gnb_vector) {
|
||||
srsran_assert(gnb->work(slot_idx, buffer.data(), ts_write) == SRSRAN_SUCCESS, "Failed to run gNb emulator");
|
||||
}
|
||||
|
||||
// Write slot samples in ringbuffer
|
||||
srsran_assert(srsran_ringbuffer_write(&ringbuffer, buffer.data(), (int)sizeof(cf_t) * sf_len) > SRSRAN_SUCCESS,
|
||||
"Error writing in ringbuffer");
|
||||
|
||||
// Increment time
|
||||
ts_write.add(0.001f);
|
||||
}
|
||||
|
||||
public:
|
||||
struct args_t {
|
||||
double srate_hz;
|
||||
srsran_carrier_nr_t base_carrier;
|
||||
srsran_subcarrier_spacing_t ssb_scs;
|
||||
srsran_ssb_patern_t ssb_pattern;
|
||||
uint32_t ssb_periodicity_ms;
|
||||
srsran_duplex_mode_t duplex_mode;
|
||||
std::set<uint32_t> pci_list;
|
||||
};
|
||||
|
||||
gnb_rf_emulator(const args_t& args)
|
||||
{
|
||||
srsran_assert(
|
||||
std::isnormal(args.srate_hz) and args.srate_hz > 0, "Invalid sampling rate (%.2f MHz)", args.srate_hz);
|
||||
|
||||
sf_len = args.srate_hz / 1000;
|
||||
|
||||
for (uint32_t pci : args.pci_list) {
|
||||
gnb_emulator::args_t gnb_args = {};
|
||||
gnb_args.srate_hz = args.srate_hz;
|
||||
gnb_args.carrier = args.base_carrier;
|
||||
gnb_args.carrier.pci = pci;
|
||||
gnb_args.ssb_scs = args.ssb_scs;
|
||||
gnb_args.ssb_pattern = args.ssb_pattern;
|
||||
gnb_args.ssb_periodicity_ms = args.ssb_periodicity_ms;
|
||||
gnb_args.duplex_mode = args.duplex_mode;
|
||||
|
||||
gnb_vector.emplace_back(std::make_shared<gnb_emulator>(gnb_args));
|
||||
}
|
||||
|
||||
srsran_assert(srsran_ringbuffer_init(&ringbuffer, sizeof(cf_t) * BUFFER_SIZE_SF * sf_len) >= SRSRAN_SUCCESS,
|
||||
"Ringbuffer initialisation failed");
|
||||
|
||||
buffer.resize(BUFFER_SIZE_SF * sf_len);
|
||||
}
|
||||
~gnb_rf_emulator() = default;
|
||||
void tx_end() override {}
|
||||
bool tx(srsran::rf_buffer_interface& tx_buffer, const srsran::rf_timestamp_interface& tx_time) override
|
||||
{
|
||||
return false;
|
||||
}
|
||||
bool rx_now(srsran::rf_buffer_interface& rx_buffer, srsran::rf_timestamp_interface& rxd_time) override
|
||||
{
|
||||
int nbytes = (int)(sizeof(cf_t) * rx_buffer.get_nof_samples());
|
||||
cf_t* temp_buffer = rx_buffer.get(0);
|
||||
|
||||
// If the buffer is invalid, use internal temporal buffer
|
||||
if (temp_buffer == nullptr) {
|
||||
temp_buffer = buffer.data();
|
||||
}
|
||||
|
||||
// As long as there are not enough samples
|
||||
while (srsran_ringbuffer_status(&ringbuffer) < nbytes and running) {
|
||||
run_async_slot();
|
||||
}
|
||||
|
||||
if (not running) {
|
||||
return true;
|
||||
}
|
||||
|
||||
srsran_assert(srsran_ringbuffer_read(&ringbuffer, temp_buffer, nbytes) >= SRSRAN_SUCCESS,
|
||||
"Error reading from ringbuffer");
|
||||
|
||||
return true;
|
||||
}
|
||||
void set_tx_freq(const uint32_t& carrier_idx, const double& freq) override {}
|
||||
void set_rx_freq(const uint32_t& carrier_idx, const double& freq) override {}
|
||||
void release_freq(const uint32_t& carrier_idx) override {}
|
||||
void set_tx_gain(const float& gain) override {}
|
||||
void set_rx_gain_th(const float& gain) override {}
|
||||
void set_rx_gain(const float& gain) override {}
|
||||
void set_tx_srate(const double& srate) override {}
|
||||
void set_rx_srate(const double& srate) override {}
|
||||
void set_channel_rx_offset(uint32_t ch, int32_t offset_samples) override {}
|
||||
double get_freq_offset() override { return 0; }
|
||||
float get_rx_gain() override { return 0; }
|
||||
bool is_continuous_tx() override { return false; }
|
||||
bool get_is_start_of_burst() override { return false; }
|
||||
bool is_init() override { return false; }
|
||||
void reset() override { running = false; }
|
||||
srsran_rf_info_t* get_info() override { return nullptr; }
|
||||
};
|
||||
|
||||
#endif // SRSRAN_GNB_RF_EMULATOR_H
|
Loading…
Reference in New Issue