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_;
high_freq = high_freq_;
}
bool contains(float freq)
bool contains(float freq) const
{
if (low_freq == 0 && high_freq == 0) {
return true;
@ -67,8 +67,8 @@ public:
return freq >= low_freq && freq <= high_freq;
}
}
float get_low() { return low_freq; }
float get_high() { return high_freq; }
float get_low() const { return low_freq; }
float get_high() const { return high_freq; }
private:
float low_freq = 0;
@ -82,6 +82,19 @@ public:
uint32_t carrier_idx;
} 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
* @param channels_
@ -105,14 +118,14 @@ public:
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
* been mapped to
* Obtains the physical information configured in set_channels() in the radio to which the logical channel logical_ch
* has been mapped to
* @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
*/
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()
@ -120,12 +133,20 @@ public:
* @param logical_ch logical channel index
* @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:
std::list<channel_cfg_t> available_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

View File

@ -103,6 +103,8 @@ private:
srslte::logger* logger = nullptr;
phy_interface_radio* phy = 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 = {};
bool is_start_of_burst = false;
@ -191,7 +193,7 @@ private:
* @param radio_buffers Actual physical radio buffer
* @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 sample_offset,
const rf_buffer_interface& buffer,

View File

@ -21,9 +21,16 @@
#include "srslte/radio/channel_mapping.h"
#include "srslte/phy/utils/debug.h"
#include <sstream>
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)
{
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)) {
allocated_channels[logical_ch] = *c;
available_channels.erase(c);
printf("-- Current mapping: %s\n", to_string().c_str());
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;
}
@ -58,19 +66,38 @@ bool channel_mapping::release_freq(const uint32_t& logical_ch)
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);
if (allocated_channels.count(logical_ch)) {
return allocated_channels[logical_ch].carrier_idx;
if (allocated_channels.count(logical_ch) > 0) {
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);
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

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);
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)
{
zeros = srslte_vec_cf_malloc(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()
@ -46,6 +53,13 @@ radio::~radio()
free(zeros);
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_)
@ -115,6 +129,9 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_)
rf_info.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
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])) {
@ -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;
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)) {
log_h->error("Mapping logical channels to physical channels for transmission\n");
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);
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)) {
log_h->error("Mapping logical channels to physical channels for transmission\n");
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
if (rx_channel_mapping.allocate_freq(carrier_idx, freq)) {
uint32_t physical_channel_idx = rx_channel_mapping.get_carrier_idx(carrier_idx);
log_h->info("Mapping RF channel %d to logical carrier %d on f_rx=%.1f MHz\n",
physical_channel_idx * nof_antennas,
channel_mapping::device_mapping_t device_mapping = rx_channel_mapping.get_device_mapping(carrier_idx);
log_h->info("Mapping RF channel %d (device=%d, channel=%d) to logical carrier %d on f_rx=%.1f MHz\n",
device_mapping.carrier_idx,
device_mapping.device_idx,
device_mapping.channel_idx,
carrier_idx,
freq / 1e6);
if (cur_rx_freqs[physical_channel_idx] != freq) {
if ((physical_channel_idx + 1) * nof_antennas <= nof_channels) {
cur_rx_freqs[physical_channel_idx] = freq;
if (cur_rx_freqs[device_mapping.carrier_idx] != freq) {
if ((device_mapping.carrier_idx + 1) * nof_antennas <= nof_channels) {
cur_rx_freqs[device_mapping.carrier_idx] = freq;
for (uint32_t i = 0; i < nof_antennas; i++) {
uint32_t phys_antenna_idx = physical_channel_idx * nof_antennas + i;
// 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);
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);
}
} else {
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_channels);
}
} 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 {
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)
{
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
if (physical_channel_idx < SRSLTE_SUCCESS) {
if (device_idx >= rf_devices.size()) {
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
int main_physical_channel_idx = rx_channel_mapping.get_carrier_idx(0);
uint32_t main_device_idx = (nof_antennas * (uint32_t)main_physical_channel_idx) / nof_channels_x_dev;
uint32_t main_device_idx = rx_channel_mapping.get_device_mapping(0, 0).device_idx;
if (device_idx == main_device_idx) {
return;
}
@ -588,31 +610,29 @@ void radio::set_tx_freq(const uint32_t& carrier_idx, const double& freq)
// Map carrier index to physical channel
if (tx_channel_mapping.allocate_freq(carrier_idx, freq)) {
uint32_t physical_channel_idx = tx_channel_mapping.get_carrier_idx(carrier_idx);
log_h->info("Mapping RF channel %d to logical carrier %d on f_tx=%.1f MHz\n",
physical_channel_idx * nof_antennas,
channel_mapping::device_mapping_t device_mapping = tx_channel_mapping.get_device_mapping(carrier_idx);
log_h->info("Mapping RF channel %d (device=%d, channel=%d) to logical carrier %d on f_tx=%.1f MHz\n",
device_mapping.carrier_idx,
device_mapping.device_idx,
device_mapping.channel_idx,
carrier_idx,
freq / 1e6);
if (cur_tx_freqs[physical_channel_idx] != freq) {
if ((physical_channel_idx + 1) * nof_antennas <= nof_channels) {
cur_tx_freqs[physical_channel_idx] = freq;
if (cur_tx_freqs[device_mapping.carrier_idx] != freq) {
if ((device_mapping.carrier_idx + 1) * nof_antennas <= nof_channels) {
cur_tx_freqs[device_mapping.carrier_idx] = freq;
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
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);
srslte_rf_set_tx_freq(&rf_devices[device_mapping.device_idx], device_mapping.channel_idx, freq + freq_offset);
}
} else {
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_channels);
}
} 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 {
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 sample_offset,
const rf_buffer_interface& buffer,
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
// accepts up to SRSLTE_MAX_CHANNELS buffers
for (uint32_t i = 0; i < nof_carriers; i++) {
@ -853,25 +869,17 @@ bool radio::map_channels(channel_mapping& map,
continue;
}
// Get physical channel
uint32_t physical_idx = map.get_carrier_idx(i);
// Map each antenna
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
if (physical_idx * nof_antennas + j >= SRSLTE_MAX_CHANNELS) {
if (physical_idx.channel_idx >= nof_channels_x_dev) {
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
if (rf_device_idx == device_idx) {
if (physical_idx.device_idx == device_idx) {
cf_t* ptr = buffer.get(i, j, nof_antennas);
// Add sample offset only if it is a valid pointer
@ -879,7 +887,7 @@ bool radio::map_channels(channel_mapping& map,
ptr += sample_offset;
}
radio_buffers[rf_channel_idx] = ptr;
radio_buffers[physical_idx.channel_idx] = ptr;
}
}
}