Radio: channel map includes device mapping, unmapped Rx uses dummy buffers

This commit is contained in:
Xavier Arteaga 2020-07-15 13:22:34 +02:00 committed by Xavier Arteaga
parent 74fde5597f
commit 51c6e8d1a6
4 changed files with 128 additions and 70 deletions

View File

@ -59,7 +59,7 @@ public:
low_freq = low_freq_; low_freq = low_freq_;
high_freq = high_freq_; high_freq = high_freq_;
} }
bool contains(float freq) bool contains(float freq) const
{ {
if (low_freq == 0 && high_freq == 0) { if (low_freq == 0 && high_freq == 0) {
return true; return true;
@ -67,8 +67,8 @@ public:
return freq >= low_freq && freq <= high_freq; return freq >= low_freq && freq <= high_freq;
} }
} }
float get_low() { return low_freq; } float get_low() const { return low_freq; }
float get_high() { return high_freq; } float get_high() const { return high_freq; }
private: private:
float low_freq = 0; float low_freq = 0;
@ -82,6 +82,19 @@ public:
uint32_t carrier_idx; uint32_t carrier_idx;
} channel_cfg_t; } channel_cfg_t;
typedef struct {
uint32_t carrier_idx; // Physical channel index of all channels
uint32_t device_idx; // RF Device index
uint32_t channel_idx; // Channel index in the RF Device
} device_mapping_t;
/**
* Sets the number of the RF device channels and antennas per carrier
* @param nof_channels_x_dev_ Number of RF channels per device
* @param nof_antennas_ number of antennas per carrrier
*/
void set_config(const uint32_t& nof_channels_x_dev_, const uint32_t& nof_antennas_);
/** /**
* Sets the channel configuration. If no channels are configured no physical channels can be allocated * Sets the channel configuration. If no channels are configured no physical channels can be allocated
* @param channels_ * @param channels_
@ -105,14 +118,14 @@ public:
bool release_freq(const uint32_t& logical_ch); bool release_freq(const uint32_t& logical_ch);
/** /**
* Obtains the carrier index configured in set_channels() in the radio to which the logical channel logical_ch has * Obtains the physical information configured in set_channels() in the radio to which the logical channel logical_ch
* been mapped to * has been mapped to
* @param logical_ch logical channel index * @param logical_ch logical channel index
* @return <0 if logical_ch is not allocated, true otherwise * @return A device mapping structure carrying the mapping information
* *
* @see channel_cfg_t * @see channel_cfg_t
*/ */
int get_carrier_idx(const uint32_t& logical_ch); device_mapping_t get_device_mapping(const uint32_t& logical_ch, const uint32_t& antenna_idx = 0) const;
/** /**
* Checks if the channel has been allocated using allocate_freq() * Checks if the channel has been allocated using allocate_freq()
@ -120,12 +133,20 @@ public:
* @param logical_ch logical channel index * @param logical_ch logical channel index
* @return true if the channel is allocated, false otherwise * @return true if the channel is allocated, false otherwise
*/ */
bool is_allocated(const uint32_t& logical_ch); bool is_allocated(const uint32_t& logical_ch) const;
/**
* Represents the channel mapping into a string
* @return a string representing the current channel mapping
*/
std::string to_string() const;
private: private:
std::list<channel_cfg_t> available_channels = {}; std::list<channel_cfg_t> available_channels = {};
std::map<uint32_t, channel_cfg_t> allocated_channels = {}; std::map<uint32_t, channel_cfg_t> allocated_channels = {};
std::mutex mutex = {}; mutable std::mutex mutex = {};
uint32_t nof_antennas = 1;
uint32_t nof_channels_x_dev = 1;
}; };
} // namespace srslte } // namespace srslte

View File

@ -103,6 +103,8 @@ private:
srslte::logger* logger = nullptr; srslte::logger* logger = nullptr;
phy_interface_radio* phy = nullptr; phy_interface_radio* phy = nullptr;
cf_t* zeros = nullptr; cf_t* zeros = nullptr;
cf_t* buffer = nullptr;
std::array<cf_t*, SRSLTE_MAX_CHANNELS> dummy_buffers;
rf_timestamp_t end_of_burst_time = {}; rf_timestamp_t end_of_burst_time = {};
bool is_start_of_burst = false; bool is_start_of_burst = false;
@ -191,7 +193,7 @@ private:
* @param radio_buffers Actual physical radio buffer * @param radio_buffers Actual physical radio buffer
* @return It returns true if the mapping was successful, otherwise it returns false. * @return It returns true if the mapping was successful, otherwise it returns false.
*/ */
bool map_channels(channel_mapping& map, bool map_channels(const channel_mapping& map,
uint32_t device_idx, uint32_t device_idx,
uint32_t sample_offset, uint32_t sample_offset,
const rf_buffer_interface& buffer, const rf_buffer_interface& buffer,

View File

@ -21,9 +21,16 @@
#include "srslte/radio/channel_mapping.h" #include "srslte/radio/channel_mapping.h"
#include "srslte/phy/utils/debug.h" #include "srslte/phy/utils/debug.h"
#include <sstream>
namespace srslte { namespace srslte {
void channel_mapping::set_config(const uint32_t& nof_channels_x_dev_, const uint32_t& nof_antennas_)
{
nof_channels_x_dev = nof_channels_x_dev_;
nof_antennas = nof_antennas_;
}
bool channel_mapping::allocate_freq(const uint32_t& logical_ch, const float& freq) bool channel_mapping::allocate_freq(const uint32_t& logical_ch, const float& freq)
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
@ -40,10 +47,11 @@ bool channel_mapping::allocate_freq(const uint32_t& logical_ch, const float& fre
if (c->band.contains(freq)) { if (c->band.contains(freq)) {
allocated_channels[logical_ch] = *c; allocated_channels[logical_ch] = *c;
available_channels.erase(c); available_channels.erase(c);
printf("-- Current mapping: %s\n", to_string().c_str());
return true; return true;
} }
} }
ERROR("allocate_freq: No channels available for frequency=%.1f\n", freq); ERROR("allocate_freq: No channels available for frequency=%.1f %s\n", freq, to_string().c_str());
return false; return false;
} }
@ -58,19 +66,38 @@ bool channel_mapping::release_freq(const uint32_t& logical_ch)
return false; return false;
} }
int channel_mapping::get_carrier_idx(const uint32_t& logical_ch) channel_mapping::device_mapping_t channel_mapping::get_device_mapping(const uint32_t& logical_ch,
const uint32_t& antenna_idx) const
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
if (allocated_channels.count(logical_ch)) { if (allocated_channels.count(logical_ch) > 0) {
return allocated_channels[logical_ch].carrier_idx; uint32_t carrier_idx = allocated_channels.at(logical_ch).carrier_idx;
uint32_t channel_idx = carrier_idx * nof_antennas + antenna_idx;
return {carrier_idx, channel_idx / nof_channels_x_dev, channel_idx % nof_channels_x_dev};
} }
return -1; return {UINT32_MAX, UINT32_MAX, UINT32_MAX};
} }
bool channel_mapping::is_allocated(const uint32_t& logical_ch) bool channel_mapping::is_allocated(const uint32_t& logical_ch) const
{ {
std::lock_guard<std::mutex> lock(mutex); std::lock_guard<std::mutex> lock(mutex);
return allocated_channels.count(logical_ch) > 0; return allocated_channels.count(logical_ch) > 0;
} }
std::string channel_mapping::to_string() const
{
std::stringstream ss;
ss << "[";
for (const auto& c : allocated_channels) {
uint32_t carrier_idx = allocated_channels.at(c.first).carrier_idx;
uint32_t channel_idx = carrier_idx * nof_antennas;
ss << "{carrier: " << c.first << ", device: " << channel_idx / nof_channels_x_dev
<< ", channel: " << channel_idx % nof_channels_x_dev
<< ", center_freq: " << (c.second.band.get_low() + c.second.band.get_high()) / 2e6 << " MHz },";
}
ss << "]";
return ss.str();
}
} // namespace srslte } // namespace srslte

View File

@ -32,12 +32,19 @@ radio::radio(srslte::log_filter* log_h_) : logger(nullptr), log_h(log_h_), zeros
{ {
zeros = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX); zeros = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX);
srslte_vec_cf_zero(zeros, SRSLTE_SF_LEN_MAX); srslte_vec_cf_zero(zeros, SRSLTE_SF_LEN_MAX);
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
dummy_buffers[i] = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX);
srslte_vec_cf_zero(dummy_buffers[i], SRSLTE_SF_LEN_MAX);
}
} }
radio::radio(srslte::logger* logger_) : logger(logger_), log_h(nullptr), zeros(nullptr) radio::radio(srslte::logger* logger_) : logger(logger_), log_h(nullptr), zeros(nullptr)
{ {
zeros = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX); zeros = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX);
srslte_vec_cf_zero(zeros, SRSLTE_SF_LEN_MAX); srslte_vec_cf_zero(zeros, SRSLTE_SF_LEN_MAX);
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
dummy_buffers[i] = srslte_vec_cf_malloc(SRSLTE_SF_LEN_MAX);
}
} }
radio::~radio() radio::~radio()
@ -46,6 +53,13 @@ radio::~radio()
free(zeros); free(zeros);
zeros = nullptr; zeros = nullptr;
} }
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
if (dummy_buffers[i]) {
free(dummy_buffers[i]);
dummy_buffers[i] = nullptr;
}
}
} }
int radio::init(const rf_args_t& args, phy_interface_radio* phy_) int radio::init(const rf_args_t& args, phy_interface_radio* phy_)
@ -115,6 +129,9 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_)
rf_info.resize(device_args_list.size()); rf_info.resize(device_args_list.size());
rx_offset_n.resize(device_args_list.size()); rx_offset_n.resize(device_args_list.size());
tx_channel_mapping.set_config(nof_channels_x_dev, nof_antennas);
rx_channel_mapping.set_config(nof_channels_x_dev, nof_antennas);
// Init and start Radios // Init and start Radios
for (uint32_t device_idx = 0; device_idx < (uint32_t)device_args_list.size(); device_idx++) { 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])) { if (not open_dev(device_idx, args.device_name, device_args_list[device_idx])) {
@ -267,6 +284,12 @@ bool radio::rx_dev(const uint32_t& device_idx, const rf_buffer_interface& buffer
double* frac_secs = rxd_time ? &rxd_time->frac_secs : nullptr; double* frac_secs = rxd_time ? &rxd_time->frac_secs : nullptr;
void* radio_buffers[SRSLTE_MAX_CHANNELS] = {}; void* radio_buffers[SRSLTE_MAX_CHANNELS] = {};
// Discard channels not allocated, need to point to valid buffer
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
radio_buffers[i] = dummy_buffers[i];
}
if (not map_channels(rx_channel_mapping, device_idx, 0, buffer, radio_buffers)) { if (not map_channels(rx_channel_mapping, device_idx, 0, buffer, radio_buffers)) {
log_h->error("Mapping logical channels to physical channels for transmission\n"); log_h->error("Mapping logical channels to physical channels for transmission\n");
return false; return false;
@ -437,6 +460,12 @@ bool radio::tx_dev(const uint32_t& device_idx, rf_buffer_interface& buffer, cons
srslte_timestamp_add(&end_of_burst_time[device_idx], 0, (double)nof_samples / cur_tx_srate); srslte_timestamp_add(&end_of_burst_time[device_idx], 0, (double)nof_samples / cur_tx_srate);
void* radio_buffers[SRSLTE_MAX_CHANNELS] = {}; void* radio_buffers[SRSLTE_MAX_CHANNELS] = {};
// Discard channels not allocated, need to point to valid buffer
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
radio_buffers[i] = zeros;
}
if (not map_channels(tx_channel_mapping, device_idx, sample_offset, buffer, radio_buffers)) { if (not map_channels(tx_channel_mapping, device_idx, sample_offset, buffer, radio_buffers)) {
log_h->error("Mapping logical channels to physical channels for transmission\n"); log_h->error("Mapping logical channels to physical channels for transmission\n");
return false; return false;
@ -484,31 +513,28 @@ void radio::set_rx_freq(const uint32_t& carrier_idx, const double& freq)
// Map carrier index to physical channel // Map carrier index to physical channel
if (rx_channel_mapping.allocate_freq(carrier_idx, freq)) { if (rx_channel_mapping.allocate_freq(carrier_idx, freq)) {
uint32_t physical_channel_idx = rx_channel_mapping.get_carrier_idx(carrier_idx); channel_mapping::device_mapping_t device_mapping = rx_channel_mapping.get_device_mapping(carrier_idx);
log_h->info("Mapping RF channel %d to logical carrier %d on f_rx=%.1f MHz\n", log_h->info("Mapping RF channel %d (device=%d, channel=%d) to logical carrier %d on f_rx=%.1f MHz\n",
physical_channel_idx * nof_antennas, device_mapping.carrier_idx,
device_mapping.device_idx,
device_mapping.channel_idx,
carrier_idx, carrier_idx,
freq / 1e6); freq / 1e6);
if (cur_rx_freqs[physical_channel_idx] != freq) { if (cur_rx_freqs[device_mapping.carrier_idx] != freq) {
if ((physical_channel_idx + 1) * nof_antennas <= nof_channels) { if ((device_mapping.carrier_idx + 1) * nof_antennas <= nof_channels) {
cur_rx_freqs[physical_channel_idx] = freq; cur_rx_freqs[device_mapping.carrier_idx] = freq;
for (uint32_t i = 0; i < nof_antennas; i++) { for (uint32_t i = 0; i < nof_antennas; i++) {
uint32_t phys_antenna_idx = physical_channel_idx * nof_antennas + i; channel_mapping::device_mapping_t dm = rx_channel_mapping.get_device_mapping(carrier_idx, 0);
srslte_rf_set_rx_freq(&rf_devices[dm.device_idx], dm.channel_idx, freq + freq_offset);
// From channel number deduce RF device index and channel
uint32_t rf_device_idx = phys_antenna_idx / nof_channels_x_dev;
uint32_t rf_channel_idx = phys_antenna_idx % nof_channels_x_dev;
srslte_rf_set_rx_freq(&rf_devices[rf_device_idx], rf_channel_idx, freq + freq_offset);
} }
} else { } else {
log_h->error("set_rx_freq: physical_channel_idx=%d for %d antennas exceeds maximum channels (%d)\n", log_h->error("set_rx_freq: physical_channel_idx=%d for %d antennas exceeds maximum channels (%d)\n",
physical_channel_idx, device_mapping.carrier_idx,
nof_antennas, nof_antennas,
nof_channels); nof_channels);
} }
} else { } else {
log_h->info("RF channel %d already on freq\n", physical_channel_idx * nof_antennas); log_h->info("RF Rx channel %d already on freq\n", device_mapping.carrier_idx);
} }
} else { } else {
log_h->error("set_rx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx); log_h->error("set_rx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx);
@ -547,19 +573,15 @@ void radio::set_rx_srate(const double& srate)
void radio::set_channel_rx_offset(uint32_t ch, int32_t offset_samples) void radio::set_channel_rx_offset(uint32_t ch, int32_t offset_samples)
{ {
int physical_channel_idx = rx_channel_mapping.get_carrier_idx(ch); uint32_t device_idx = rx_channel_mapping.get_device_mapping(ch, 0).device_idx;
// Return if invalid index // Return if invalid index
if (physical_channel_idx < SRSLTE_SUCCESS) { if (device_idx >= rf_devices.size()) {
return; return;
} }
// Calculate device index
uint32_t device_idx = (nof_antennas * (uint32_t)physical_channel_idx) / nof_channels_x_dev;
// Skip correction if device matches the first logical channel // Skip correction if device matches the first logical channel
int main_physical_channel_idx = rx_channel_mapping.get_carrier_idx(0); uint32_t main_device_idx = rx_channel_mapping.get_device_mapping(0, 0).device_idx;
uint32_t main_device_idx = (nof_antennas * (uint32_t)main_physical_channel_idx) / nof_channels_x_dev;
if (device_idx == main_device_idx) { if (device_idx == main_device_idx) {
return; return;
} }
@ -588,31 +610,29 @@ void radio::set_tx_freq(const uint32_t& carrier_idx, const double& freq)
// Map carrier index to physical channel // Map carrier index to physical channel
if (tx_channel_mapping.allocate_freq(carrier_idx, freq)) { if (tx_channel_mapping.allocate_freq(carrier_idx, freq)) {
uint32_t physical_channel_idx = tx_channel_mapping.get_carrier_idx(carrier_idx); channel_mapping::device_mapping_t device_mapping = tx_channel_mapping.get_device_mapping(carrier_idx);
log_h->info("Mapping RF channel %d to logical carrier %d on f_tx=%.1f MHz\n", log_h->info("Mapping RF channel %d (device=%d, channel=%d) to logical carrier %d on f_tx=%.1f MHz\n",
physical_channel_idx * nof_antennas, device_mapping.carrier_idx,
device_mapping.device_idx,
device_mapping.channel_idx,
carrier_idx, carrier_idx,
freq / 1e6); freq / 1e6);
if (cur_tx_freqs[physical_channel_idx] != freq) { if (cur_tx_freqs[device_mapping.carrier_idx] != freq) {
if ((physical_channel_idx + 1) * nof_antennas <= nof_channels) { if ((device_mapping.carrier_idx + 1) * nof_antennas <= nof_channels) {
cur_tx_freqs[physical_channel_idx] = freq; cur_tx_freqs[device_mapping.carrier_idx] = freq;
for (uint32_t i = 0; i < nof_antennas; i++) { for (uint32_t i = 0; i < nof_antennas; i++) {
uint32_t phys_antenna_idx = physical_channel_idx * nof_antennas + i; device_mapping = tx_channel_mapping.get_device_mapping(carrier_idx, i);
// From channel number deduce RF device index and channel srslte_rf_set_tx_freq(&rf_devices[device_mapping.device_idx], device_mapping.channel_idx, freq + freq_offset);
uint32_t rf_device_idx = phys_antenna_idx / nof_channels_x_dev;
uint32_t rf_channel_idx = phys_antenna_idx % nof_channels_x_dev;
srslte_rf_set_tx_freq(&rf_devices[rf_device_idx], rf_channel_idx, freq + freq_offset);
} }
} else { } else {
log_h->error("set_tx_freq: physical_channel_idx=%d for %d antennas exceeds maximum channels (%d)\n", log_h->error("set_tx_freq: physical_channel_idx=%d for %d antennas exceeds maximum channels (%d)\n",
physical_channel_idx, device_mapping.carrier_idx,
nof_antennas, nof_antennas,
nof_channels); nof_channels);
} }
} else { } else {
log_h->info("RF channel %d already on freq\n", physical_channel_idx * nof_antennas); log_h->info("RF Tx channel %d already on freq\n", device_mapping.carrier_idx);
} }
} else { } else {
log_h->error("set_tx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx); log_h->error("set_tx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx);
@ -835,16 +855,12 @@ void radio::rf_msg_callback(void* arg, srslte_rf_error_t error)
} }
} }
bool radio::map_channels(channel_mapping& map, bool radio::map_channels(const channel_mapping& map,
uint32_t device_idx, uint32_t device_idx,
uint32_t sample_offset, uint32_t sample_offset,
const rf_buffer_interface& buffer, const rf_buffer_interface& buffer,
void* radio_buffers[SRSLTE_MAX_CHANNELS]) void* radio_buffers[SRSLTE_MAX_CHANNELS])
{ {
// Discard channels not allocated, need to point to valid buffer
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
radio_buffers[i] = zeros;
}
// Conversion from safe C++ std::array to the unsafe C interface. We must ensure that the RF driver implementation // Conversion from safe C++ std::array to the unsafe C interface. We must ensure that the RF driver implementation
// accepts up to SRSLTE_MAX_CHANNELS buffers // accepts up to SRSLTE_MAX_CHANNELS buffers
for (uint32_t i = 0; i < nof_carriers; i++) { for (uint32_t i = 0; i < nof_carriers; i++) {
@ -853,25 +869,17 @@ bool radio::map_channels(channel_mapping& map,
continue; continue;
} }
// Get physical channel
uint32_t physical_idx = map.get_carrier_idx(i);
// Map each antenna // Map each antenna
for (uint32_t j = 0; j < nof_antennas; j++) { for (uint32_t j = 0; j < nof_antennas; j++) {
channel_mapping::device_mapping_t physical_idx = map.get_device_mapping(i, j);
// Detect mapping out-of-bounds // Detect mapping out-of-bounds
if (physical_idx * nof_antennas + j >= SRSLTE_MAX_CHANNELS) { if (physical_idx.channel_idx >= nof_channels_x_dev) {
return false; return false;
} }
// Calculate actual physical port index
uint32_t phys_chan_idx = physical_idx * nof_antennas + j;
// Deduce physical device and port
uint32_t rf_device_idx = phys_chan_idx / nof_channels_x_dev;
uint32_t rf_channel_idx = phys_chan_idx % nof_channels_x_dev;
// Set pointer if device index matches // Set pointer if device index matches
if (rf_device_idx == device_idx) { if (physical_idx.device_idx == device_idx) {
cf_t* ptr = buffer.get(i, j, nof_antennas); cf_t* ptr = buffer.get(i, j, nof_antennas);
// Add sample offset only if it is a valid pointer // Add sample offset only if it is a valid pointer
@ -879,7 +887,7 @@ bool radio::map_channels(channel_mapping& map,
ptr += sample_offset; ptr += sample_offset;
} }
radio_buffers[rf_channel_idx] = ptr; radio_buffers[physical_idx.channel_idx] = ptr;
} }
} }
} }