mirror of https://github.com/pvnis/srsRAN_4G.git
Refactored radio class for acommodating multiple RF devices
parent
e2146e90ad
commit
89b24b54e5
@ -0,0 +1,133 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_CHANNEL_MAPPING_H
|
||||||
|
#define SRSLTE_CHANNEL_MAPPING_H
|
||||||
|
|
||||||
|
#include <cinttypes>
|
||||||
|
#include <list>
|
||||||
|
#include <map>
|
||||||
|
#include <mutex>
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This class manages the mapping between logical and physical channels.
|
||||||
|
* A physical channel in this class is a carrier index in the radio class, which
|
||||||
|
* has multiple antenna ports all tuned to the same frequency.
|
||||||
|
*
|
||||||
|
* Every group of channels tuned associated with a carrier go through the same band-pass filter. This
|
||||||
|
* class then manages the allocation of frequencies to these group of channels.
|
||||||
|
*
|
||||||
|
* The same object is reused for the reception and transmission.
|
||||||
|
*
|
||||||
|
* When the UE wants to tune a logical channel to a new frequency it requests this class
|
||||||
|
* to provide an available channel that supports this frequency. At that point,
|
||||||
|
* that channel can not be used anymore until a call to release().
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class channel_mapping
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/** Configures a band. A band is defined by an upper and lower frequency boundaries.
|
||||||
|
* If the upper and lower frequencies are not configured (default is zero), it means
|
||||||
|
* that they support any frequency
|
||||||
|
*/
|
||||||
|
class band_cfg
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
void set(float low_freq_, float high_freq_)
|
||||||
|
{
|
||||||
|
low_freq = low_freq_;
|
||||||
|
high_freq = high_freq_;
|
||||||
|
}
|
||||||
|
bool contains(float freq)
|
||||||
|
{
|
||||||
|
if (low_freq == 0 && high_freq == 0) {
|
||||||
|
return true;
|
||||||
|
} else {
|
||||||
|
return freq >= low_freq && freq <= high_freq;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
float get_low() { return low_freq; }
|
||||||
|
float get_high() { return high_freq; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
float low_freq = 0;
|
||||||
|
float high_freq = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
/** Each channel is defined by the band it supports and the physical carrier index in the radio
|
||||||
|
*/
|
||||||
|
typedef struct {
|
||||||
|
band_cfg band;
|
||||||
|
uint32_t carrier_idx;
|
||||||
|
} channel_cfg_t;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the channel configuration. If no channels are configured no physical channels can be allocated
|
||||||
|
* @param channels_
|
||||||
|
*/
|
||||||
|
void set_channels(const std::list<channel_cfg_t>& channels_) { available_channels = channels_; }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Finds an unused physical channel that supports the provided frequency and assigns it to logical channel
|
||||||
|
* logical_ch
|
||||||
|
* @param logical_ch logical channel index
|
||||||
|
* @param freq Frequency (in Hz) that we want to receive/transmitt
|
||||||
|
* @return true if a physical channel supporting this frequency was found or false otherwise
|
||||||
|
*/
|
||||||
|
bool allocate_freq(const uint32_t& logical_ch, const float& freq);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Releases the allocation of a logical channel allowing to be used in the next call to allocate_freq
|
||||||
|
* @param logical_ch logical channel index
|
||||||
|
* @return false if logical_ch is not allocated, true otherwise
|
||||||
|
*/
|
||||||
|
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
|
||||||
|
* @param logical_ch logical channel index
|
||||||
|
* @return <0 if logical_ch is not allocated, true otherwise
|
||||||
|
*
|
||||||
|
* @see channel_cfg_t
|
||||||
|
*/
|
||||||
|
int get_carrier_idx(const uint32_t& logical_ch);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Checks if the channel has been allocated using allocate_freq()
|
||||||
|
*
|
||||||
|
* @param logical_ch logical channel index
|
||||||
|
* @return true if the channel is allocated, false otherwise
|
||||||
|
*/
|
||||||
|
bool is_allocated(const uint32_t& logical_ch);
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::list<channel_cfg_t> available_channels = {};
|
||||||
|
std::map<uint32_t, channel_cfg_t> allocated_channels = {};
|
||||||
|
std::mutex mutex = {};
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_CHANNEL_MAPPING_H
|
@ -0,0 +1,139 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_RF_BUFFER_H
|
||||||
|
#define SRSLTE_RF_BUFFER_H
|
||||||
|
|
||||||
|
#include "srslte/interfaces/radio_interfaces.h"
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemenation of the rf_buffer_interface for the current radio implementation which uses flat arrays.
|
||||||
|
* @see rf_buffer_interface
|
||||||
|
* @see radio
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class rf_buffer_t : public rf_buffer_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Creates an object and allocates memory for nof_subframes_ assuming the
|
||||||
|
* largest system bandwidth
|
||||||
|
* @param nof_subframes_ Number of subframes to allocate
|
||||||
|
*/
|
||||||
|
explicit rf_buffer_t(uint32_t nof_subframes_)
|
||||||
|
{
|
||||||
|
if (nof_subframes_ > 0) {
|
||||||
|
// Allocate buffers for an integer number of subframes
|
||||||
|
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
|
||||||
|
sample_buffer[i] = srslte_vec_cf_malloc(nof_subframes_ * SRSLTE_SF_LEN_MAX);
|
||||||
|
srslte_vec_cf_zero(sample_buffer[i], SRSLTE_SF_LEN_MAX);
|
||||||
|
}
|
||||||
|
allocated = true;
|
||||||
|
nof_subframes = nof_subframes_;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Creates an object and sets the buffers to the flat array pointed by data. Note that data must
|
||||||
|
* 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])
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
|
||||||
|
sample_buffer[i] = data[i];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* 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; }
|
||||||
|
/**
|
||||||
|
* Default constructor leaves the internal pointers to NULL
|
||||||
|
*/
|
||||||
|
rf_buffer_t() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The destructor will deallocate memory only if it was allocated passing nof_subframes > 0
|
||||||
|
*/
|
||||||
|
~rf_buffer_t()
|
||||||
|
{
|
||||||
|
if (allocated) {
|
||||||
|
free_all();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
/**
|
||||||
|
* Overrides the = operator such that the lvalue internal buffers point to the pointers inside rvalue.
|
||||||
|
* If memory has already been allocated in the lvalue object, it will free it before pointing the
|
||||||
|
* buffers to the lvalue.
|
||||||
|
* After this operator, when the lvalue is destroyed no memory will be freed.
|
||||||
|
* @param other rvalue
|
||||||
|
* @return lvalue
|
||||||
|
*/
|
||||||
|
rf_buffer_t& operator=(const rf_buffer_t& other)
|
||||||
|
{
|
||||||
|
if (this == &other) {
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
if (this->allocated) {
|
||||||
|
free_all();
|
||||||
|
this->allocated = false;
|
||||||
|
}
|
||||||
|
for (int i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
|
||||||
|
this->sample_buffer[i] = other.sample_buffer[i];
|
||||||
|
}
|
||||||
|
return *this;
|
||||||
|
}
|
||||||
|
|
||||||
|
rf_buffer_t(const rf_buffer_t& other) = delete;
|
||||||
|
cf_t* get(const uint32_t& channel_idx) const override { return sample_buffer.at(channel_idx); }
|
||||||
|
void set(const uint32_t& channel_idx, cf_t* ptr) override { sample_buffer.at(channel_idx) = ptr; }
|
||||||
|
cf_t* get(const uint32_t& logical_ch, const uint32_t& port_idx, const uint32_t& nof_antennas) const override
|
||||||
|
{
|
||||||
|
return sample_buffer.at(logical_ch * nof_antennas + port_idx);
|
||||||
|
}
|
||||||
|
void set(const uint32_t& logical_ch, const uint32_t& port_idx, const uint32_t& nof_antennas, cf_t* ptr) override
|
||||||
|
{
|
||||||
|
sample_buffer.at(logical_ch * nof_antennas + port_idx) = ptr;
|
||||||
|
}
|
||||||
|
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; }
|
||||||
|
|
||||||
|
private:
|
||||||
|
std::array<cf_t*, SRSLTE_MAX_CHANNELS> sample_buffer = {};
|
||||||
|
bool allocated = false;
|
||||||
|
uint32_t nof_subframes = 0;
|
||||||
|
void free_all()
|
||||||
|
{
|
||||||
|
for (uint32_t i = 0; i < SRSLTE_MAX_CHANNELS; i++) {
|
||||||
|
if (sample_buffer[i]) {
|
||||||
|
free(sample_buffer[i]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_RF_BUFFER_H
|
@ -0,0 +1,107 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SRSLTE_RF_TIMESTAMP_H
|
||||||
|
#define SRSLTE_RF_TIMESTAMP_H
|
||||||
|
|
||||||
|
#include "srslte/interfaces/radio_interfaces.h"
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Implemenation of the rf_buffer_interface for the current radio implementation which uses flat arrays.
|
||||||
|
* @see rf_buffer_interface
|
||||||
|
* @see radio
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
class rf_timestamp_t : public rf_timestamp_interface
|
||||||
|
{
|
||||||
|
public:
|
||||||
|
/**
|
||||||
|
* Default constructor, all timestamps are zero by default
|
||||||
|
*/
|
||||||
|
rf_timestamp_t() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copy constructor
|
||||||
|
* @param other the other object to copy
|
||||||
|
*/
|
||||||
|
rf_timestamp_t(const rf_timestamp_t& other) { copy(other); }
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Default destructor
|
||||||
|
*/
|
||||||
|
~rf_timestamp_t() = default;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets a timestamp by reference
|
||||||
|
* @return Given timestamp of the indicated device if the index is bounded, otherwise it returns the default timestamp
|
||||||
|
*/
|
||||||
|
const srslte_timestamp_t& get(uint32_t idx) const override
|
||||||
|
{
|
||||||
|
if (idx >= SRSLTE_MAX_CHANNELS) {
|
||||||
|
return default_ts;
|
||||||
|
}
|
||||||
|
|
||||||
|
return timestamps[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the timestamp array pointer
|
||||||
|
* @return timestamp pointer with the value if the channel index is bounded. Otherwise, returns nullptr
|
||||||
|
*/
|
||||||
|
srslte_timestamp_t* get_ptr(uint32_t idx) override
|
||||||
|
{
|
||||||
|
if (idx >= SRSLTE_MAX_CHANNELS) {
|
||||||
|
return nullptr;
|
||||||
|
}
|
||||||
|
return ×tamps[idx];
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a given amount of seconds to all the timestamps
|
||||||
|
* @param secs number of seconds
|
||||||
|
*/
|
||||||
|
void add(double secs) override
|
||||||
|
{
|
||||||
|
for (srslte_timestamp_t& ts : timestamps) {
|
||||||
|
srslte_timestamp_add(&ts, 0, secs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Subtract a given amount of seconds to all the timestamps
|
||||||
|
* @param secs number of seconds
|
||||||
|
*/
|
||||||
|
void sub(double secs) override
|
||||||
|
{
|
||||||
|
for (srslte_timestamp_t& ts : timestamps) {
|
||||||
|
srslte_timestamp_sub(&ts, 0, secs);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private:
|
||||||
|
const srslte_timestamp_t default_ts = {};
|
||||||
|
std::array<srslte_timestamp_t, SRSLTE_MAX_CHANNELS> timestamps = {};
|
||||||
|
};
|
||||||
|
} // namespace srslte
|
||||||
|
|
||||||
|
#endif // SRSLTE_RF_TIMESTAMP_H
|
@ -0,0 +1,76 @@
|
|||||||
|
/*
|
||||||
|
* Copyright 2013-2020 Software Radio Systems Limited
|
||||||
|
*
|
||||||
|
* This file is part of srsLTE.
|
||||||
|
*
|
||||||
|
* srsLTE is free software: you can redistribute it and/or modify
|
||||||
|
* it under the terms of the GNU Affero General Public License as
|
||||||
|
* published by the Free Software Foundation, either version 3 of
|
||||||
|
* the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* srsLTE is distributed in the hope that it will be useful,
|
||||||
|
* but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
* GNU Affero General Public License for more details.
|
||||||
|
*
|
||||||
|
* A copy of the GNU Affero General Public License can be found in
|
||||||
|
* the LICENSE file in the top-level directory of this distribution
|
||||||
|
* and at http://www.gnu.org/licenses/.
|
||||||
|
*
|
||||||
|
*/
|
||||||
|
|
||||||
|
#include "srslte/radio/channel_mapping.h"
|
||||||
|
#include "srslte/phy/utils/debug.h"
|
||||||
|
|
||||||
|
namespace srslte {
|
||||||
|
|
||||||
|
bool channel_mapping::allocate_freq(const uint32_t& logical_ch, const float& freq)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
|
||||||
|
if (allocated_channels.count(logical_ch)) {
|
||||||
|
ERROR("allocate_freq: Carrier logical_ch=%d already allocated to channel=%d\n",
|
||||||
|
logical_ch,
|
||||||
|
allocated_channels[logical_ch].carrier_idx);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Find first available channel that supports this frequency and allocated it
|
||||||
|
for (auto c = available_channels.begin(); c != available_channels.end(); ++c) {
|
||||||
|
if (c->band.contains(freq)) {
|
||||||
|
allocated_channels[logical_ch] = *c;
|
||||||
|
available_channels.erase(c);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
ERROR("allocate_freq: No channels available for frequency=%.1f\n", freq);
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool channel_mapping::release_freq(const uint32_t& logical_ch)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (allocated_channels.count(logical_ch)) {
|
||||||
|
available_channels.push_back(allocated_channels[logical_ch]);
|
||||||
|
allocated_channels.erase(logical_ch);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
int channel_mapping::get_carrier_idx(const uint32_t& logical_ch)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
if (allocated_channels.count(logical_ch)) {
|
||||||
|
return allocated_channels[logical_ch].carrier_idx;
|
||||||
|
}
|
||||||
|
return -1;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool channel_mapping::is_allocated(const uint32_t& logical_ch)
|
||||||
|
{
|
||||||
|
std::lock_guard<std::mutex> lock(mutex);
|
||||||
|
return allocated_channels.count(logical_ch) > 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
} // namespace srslte
|
Loading…
Reference in New Issue