Add RF per-channel frequency band constraints (#1026)

master
Ismael Gomez 5 years ago committed by GitHub
parent 2f8643fb97
commit e8b8c9922e
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

@ -34,6 +34,11 @@ typedef struct {
int phy_hex_limit = -1; int phy_hex_limit = -1;
} phy_log_args_t; } phy_log_args_t;
typedef struct {
float min;
float max;
} rf_args_band_t;
// RF/radio args // RF/radio args
typedef struct { typedef struct {
std::string type; std::string type;
@ -52,6 +57,10 @@ typedef struct {
std::string device_args; std::string device_args;
std::string time_adv_nsamples; std::string time_adv_nsamples;
std::string continuous_tx; std::string continuous_tx;
std::array<rf_args_band_t, SRSLTE_MAX_CARRIERS> ch_rx_bands;
std::array<rf_args_band_t, SRSLTE_MAX_CARRIERS> ch_tx_bands;
} rf_args_t; } rf_args_t;
class srslte_gw_config_t class srslte_gw_config_t

@ -49,10 +49,10 @@ namespace srslte {
class rf_buffer_interface class rf_buffer_interface
{ {
public: public:
virtual cf_t* get(uint32_t channel_idx) const = 0; virtual cf_t* get(const uint32_t& channel_idx) const = 0;
virtual void set(uint32_t channel_idx, cf_t* ptr) = 0; virtual void set(const uint32_t& channel_idx, cf_t* ptr) = 0;
virtual cf_t* get(uint32_t cc_idx, uint32_t port_idx, uint32_t nof_antennas) const = 0; virtual cf_t* get(const uint32_t& cc_idx, const uint32_t& port_idx, const uint32_t& nof_antennas) const = 0;
virtual void set(uint32_t cc_idx, uint32_t port_idx, uint32_t nof_antennas, cf_t* ptr) = 0; virtual void set(const uint32_t& cc_idx, const uint32_t& port_idx, const uint32_t& nof_antennas, cf_t* ptr) = 0;
virtual void** to_void() = 0; virtual void** to_void() = 0;
virtual cf_t** to_cf_t() = 0; virtual cf_t** to_cf_t() = 0;
virtual uint32_t size() = 0; virtual uint32_t size() = 0;
@ -121,6 +121,12 @@ public:
*/ */
virtual void set_rx_freq(const uint32_t& carrier_idx, const double& freq) = 0; virtual void set_rx_freq(const uint32_t& carrier_idx, const double& freq) = 0;
/**
* Releases any mapping between frequency and carrier done when calling set_tx_freq() or set_rx_freq()
* @param carrier_idx Index of the carrier to release the mapping
*/
virtual void release_freq(const uint32_t& carrier_idx) = 0;
/** /**
* Sets the transmit gain for all carriers and antennas * Sets the transmit gain for all carriers and antennas
* @param gain Gain in dB * @param gain Gain in dB

@ -28,6 +28,7 @@
#include "srslte/interfaces/radio_interfaces.h" #include "srslte/interfaces/radio_interfaces.h"
#include "srslte/phy/rf/rf.h" #include "srslte/phy/rf/rf.h"
#include "srslte/srslte.h" #include "srslte/srslte.h"
#include <list>
#ifndef SRSLTE_RADIO_H #ifndef SRSLTE_RADIO_H
#define SRSLTE_RADIO_H #define SRSLTE_RADIO_H
@ -112,15 +113,15 @@ public:
} }
return *this; return *this;
} }
cf_t* get(uint32_t channel_idx) const override { return sample_buffer.at(channel_idx); } cf_t* get(const uint32_t& channel_idx) const override { return sample_buffer.at(channel_idx); }
void set(uint32_t channel_idx, cf_t* ptr) override { sample_buffer.at(channel_idx) = ptr; } void set(const uint32_t& channel_idx, cf_t* ptr) override { sample_buffer.at(channel_idx) = ptr; }
cf_t* get(uint32_t cc_idx, uint32_t port_idx, uint32_t nof_antennas) const override cf_t* get(const uint32_t& logical_ch, const uint32_t& port_idx, const uint32_t& nof_antennas) const override
{ {
return sample_buffer.at(cc_idx * nof_antennas + port_idx); return sample_buffer.at(logical_ch * nof_antennas + port_idx);
} }
void set(uint32_t cc_idx, uint32_t port_idx, uint32_t nof_antennas, cf_t* ptr) override void set(const uint32_t& logical_ch, const uint32_t& port_idx, const uint32_t& nof_antennas, cf_t* ptr) override
{ {
sample_buffer.at(cc_idx * nof_antennas + port_idx) = ptr; sample_buffer.at(logical_ch * nof_antennas + port_idx) = ptr;
} }
void** to_void() override { return (void**)sample_buffer.data(); } void** to_void() override { return (void**)sample_buffer.data(); }
cf_t** to_cf_t() override { return sample_buffer.data(); } cf_t** to_cf_t() override { return sample_buffer.data(); }
@ -171,6 +172,7 @@ public:
// setter // setter
void set_tx_freq(const uint32_t& carrier_idx, const double& freq) override; 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 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_tx_gain(const float& gain) override;
void set_rx_gain_th(const float& gain) override; void set_rx_gain_th(const float& gain) override;
@ -219,6 +221,7 @@ private:
double cur_tx_srate = 0.0f; double cur_tx_srate = 0.0f;
uint32_t nof_antennas = 0; uint32_t nof_antennas = 0;
uint32_t nof_channels = 0; uint32_t nof_channels = 0;
uint32_t nof_carriers = 0;
// Define default values for known radios // Define default values for known radios
constexpr static double uhd_default_tx_adv_samples = 98; constexpr static double uhd_default_tx_adv_samples = 98;
@ -227,9 +230,112 @@ private:
constexpr static double blade_default_tx_adv_samples = 27; constexpr static double blade_default_tx_adv_samples = 27;
constexpr static double blade_default_tx_adv_offset_sec = 1e-6; constexpr static double blade_default_tx_adv_offset_sec = 1e-6;
/**
* 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 = {};
};
channel_mapping rx_channel_mapping = {}, tx_channel_mapping = {};
bool map_channels(channel_mapping& map, const rf_buffer_interface& buffer, void* radio_buffers[SRSLTE_MAX_CHANNELS]);
bool start_agc(bool tx_gain_same_rx = false); bool start_agc(bool tx_gain_same_rx = false);
void set_tx_adv(int nsamples); void set_tx_adv(int nsamples);
void set_tx_adv_neg(bool tx_adv_is_neg); void set_tx_adv_neg(bool tx_adv_is_neg);
bool config_rf_channels(const rf_args_t& args);
}; };
} // namespace srslte } // namespace srslte

@ -843,7 +843,7 @@ srslte_sync_find(srslte_sync_t* q, const cf_t* input, uint32_t find_offset, uint
q->threshold, q->threshold,
15 * (srslte_sync_get_cfo(q))); 15 * (srslte_sync_get_cfo(q)));
} else if (srslte_N_id_2_isvalid(q->N_id_2)) { } else if (!srslte_N_id_2_isvalid(q->N_id_2)) {
ERROR("Must call srslte_sync_set_N_id_2() first!\n"); ERROR("Must call srslte_sync_set_N_id_2() first!\n");
} }

@ -25,6 +25,7 @@ extern "C" {
} }
#include "srslte/common/log_filter.h" #include "srslte/common/log_filter.h"
#include "srslte/radio/radio.h" #include "srslte/radio/radio.h"
#include <list>
#include <string.h> #include <string.h>
#include <unistd.h> #include <unistd.h>
@ -76,8 +77,14 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_)
return SRSLTE_ERROR; return SRSLTE_ERROR;
} }
if (!config_rf_channels(args)) {
log_h->console("Error configuring RF channels\n");
return SRSLTE_ERROR;
}
nof_channels = args.nof_antennas * args.nof_carriers; nof_channels = args.nof_antennas * args.nof_carriers;
nof_antennas = args.nof_antennas; nof_antennas = args.nof_antennas;
nof_carriers = args.nof_carriers;
// Init and start Radio // Init and start Radio
char* device_args = nullptr; char* device_args = nullptr;
@ -211,10 +218,13 @@ bool radio::rx_now(rf_buffer_interface& buffer, const uint32_t& nof_samples, srs
time_t* full_secs = rxd_time ? &rxd_time->full_secs : NULL; time_t* full_secs = rxd_time ? &rxd_time->full_secs : NULL;
double* frac_secs = rxd_time ? &rxd_time->frac_secs : NULL; double* frac_secs = rxd_time ? &rxd_time->frac_secs : NULL;
// Conversion from safe C++ std::array to the unsafe C interface. We must ensure that the RF driver implementation void* radio_buffers[SRSLTE_MAX_CHANNELS] = {};
// accepts up to SRSLTE_MAX_CHANNELS buffers if (!map_channels(rx_channel_mapping, buffer, radio_buffers)) {
log_h->error("Mapping logical channels to physical channels for transmission\n");
return false;
}
if (srslte_rf_recv_with_time_multi(&rf_device, buffer.to_void(), nof_samples, true, full_secs, frac_secs) > 0) { if (srslte_rf_recv_with_time_multi(&rf_device, radio_buffers, nof_samples, true, full_secs, frac_secs) > 0) {
ret = true; ret = true;
} else { } else {
ret = false; ret = false;
@ -263,11 +273,14 @@ bool radio::tx(rf_buffer_interface& buffer, const uint32_t& nof_samples, const s
srslte_timestamp_copy(&end_of_burst_time, &tx_time); srslte_timestamp_copy(&end_of_burst_time, &tx_time);
srslte_timestamp_add(&end_of_burst_time, 0, (double)nof_samples / cur_tx_srate); srslte_timestamp_add(&end_of_burst_time, 0, (double)nof_samples / cur_tx_srate);
// Conversion from safe C++ std::array to the unsafe C interface. We must ensure that the RF driver implementation void* radio_buffers[SRSLTE_MAX_CHANNELS] = {};
// accepts up to SRSLTE_MAX_CHANNELS buffers if (!map_channels(rx_channel_mapping, buffer, radio_buffers)) {
log_h->error("Mapping logical channels to physical channels for transmission\n");
return false;
}
int ret = srslte_rf_send_timed_multi( int ret = srslte_rf_send_timed_multi(
&rf_device, buffer.to_void(), nof_samples, tx_time.full_secs, tx_time.frac_secs, true, is_start_of_burst, false); &rf_device, radio_buffers, nof_samples, tx_time.full_secs, tx_time.frac_secs, true, is_start_of_burst, false);
is_start_of_burst = false; is_start_of_burst = false;
if (ret > 0) { if (ret > 0) {
return true; return true;
@ -292,21 +305,41 @@ bool radio::get_is_start_of_burst()
return is_start_of_burst; return is_start_of_burst;
} }
void radio::set_rx_freq(const uint32_t& channel_idx, const double& freq) void radio::release_freq(const uint32_t& carrier_idx)
{
rx_channel_mapping.release_freq(carrier_idx);
tx_channel_mapping.release_freq(carrier_idx);
}
void radio::set_rx_freq(const uint32_t& carrier_idx, const double& freq)
{ {
if (!is_initialized) { if (!is_initialized) {
return; return;
} }
if ((channel_idx + 1) * nof_antennas <= nof_channels) {
// First release mapping
rx_channel_mapping.release_freq(carrier_idx);
// 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);
if ((physical_channel_idx + 1) * nof_antennas <= nof_channels) {
for (uint32_t i = 0; i < nof_antennas; i++) { for (uint32_t i = 0; i < nof_antennas; i++) {
srslte_rf_set_rx_freq(&rf_device, channel_idx * nof_antennas + i, freq + freq_offset); log_h->info("Mapping RF channel %d to logical carrier %d on f_rx=%.1f MHz\n",
physical_channel_idx * nof_antennas + i,
carrier_idx,
freq / 1e6);
srslte_rf_set_rx_freq(&rf_device, physical_channel_idx * nof_antennas + i, freq + freq_offset);
} }
} else { } else {
log_h->error("set_rx_freq: 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",
channel_idx, physical_channel_idx,
nof_antennas, nof_antennas,
nof_channels); nof_channels);
} }
} else {
log_h->error("set_rx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx);
}
} }
void radio::set_rx_gain(const float& gain) void radio::set_rx_gain(const float& gain)
@ -333,21 +366,35 @@ void radio::set_rx_srate(const double& srate)
srslte_rf_set_rx_srate(&rf_device, srate); srslte_rf_set_rx_srate(&rf_device, srate);
} }
void radio::set_tx_freq(const uint32_t& channel_idx, const double& freq) void radio::set_tx_freq(const uint32_t& carrier_idx, const double& freq)
{ {
if (!is_initialized) { if (!is_initialized) {
return; return;
} }
if ((channel_idx + 1) * nof_antennas <= nof_channels) {
// First release mapping
tx_channel_mapping.release_freq(carrier_idx);
// 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);
if ((physical_channel_idx + 1) * nof_antennas <= nof_channels) {
for (uint32_t i = 0; i < nof_antennas; i++) { for (uint32_t i = 0; i < nof_antennas; i++) {
srslte_rf_set_tx_freq(&rf_device, channel_idx * nof_antennas + i, freq + freq_offset); log_h->info("Mapping RF channel %d to logical carrier %d on f_tx=%.1f MHz\n",
physical_channel_idx * nof_antennas + i,
carrier_idx,
freq / 1e6);
srslte_rf_set_tx_freq(&rf_device, physical_channel_idx * nof_antennas + i, freq + freq_offset);
} }
} else { } else {
log_h->error("set_tx_freq: 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",
channel_idx, physical_channel_idx,
nof_antennas, nof_antennas,
nof_channels); nof_channels);
} }
} else {
log_h->error("set_tx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx);
}
} }
void radio::set_tx_gain(const float& gain) void radio::set_tx_gain(const float& gain)
@ -555,4 +602,114 @@ void radio::rf_msg_callback(void* arg, srslte_rf_error_t error)
} }
} }
bool radio::map_channels(channel_mapping& map,
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++) {
if (map.is_allocated(i)) {
uint32_t physical_idx = map.get_carrier_idx(i);
for (uint32_t j = 0; j < nof_antennas; j++) {
if (physical_idx * nof_antennas + j < SRSLTE_MAX_CHANNELS) {
radio_buffers[physical_idx * nof_antennas + j] = buffer.get(i, j, nof_antennas);
} else {
return false;
}
}
}
}
return true;
}
bool radio::config_rf_channels(const rf_args_t& args)
{
// Generate RF-Channel to Carrier map
std::list<channel_mapping::channel_cfg_t> dl_rf_channels = {};
std::list<channel_mapping::channel_cfg_t> ul_rf_channels = {};
for (uint32_t i = 0; i < args.nof_carriers; i++) {
channel_mapping::channel_cfg_t c = {};
c.carrier_idx = i;
// Parse DL band for this channel
c.band.set(args.ch_rx_bands[i].min, args.ch_rx_bands[i].max);
dl_rf_channels.push_back(c);
log_h->info("Configuring physical DL channel %d with band-pass filter (%.1f, %.1f)\n",
i,
c.band.get_low(),
c.band.get_high());
// Parse UL band for this channel
c.band.set(args.ch_tx_bands[i].min, args.ch_tx_bands[i].max);
ul_rf_channels.push_back(c);
log_h->info("Configuring physical UL channel %d with band-pass filter (%.1f, %.1f)\n",
i,
c.band.get_low(),
c.band.get_high());
}
rx_channel_mapping.set_channels(dl_rf_channels);
tx_channel_mapping.set_channels(ul_rf_channels);
return true;
}
/***
* Carrier mapping class
*/
bool radio::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 radio::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 radio::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 radio::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 } // namespace srslte

@ -233,6 +233,7 @@ public:
// Return True if err >= SRSLTE_SUCCESS // Return True if err >= SRSLTE_SUCCESS
return err >= SRSLTE_SUCCESS; return err >= SRSLTE_SUCCESS;
} }
void release_freq(const uint32_t& carrier_idx) override{};
void set_tx_freq(const uint32_t& channel_idx, const double& freq) override {} void set_tx_freq(const uint32_t& channel_idx, const double& freq) override {}
void set_rx_freq(const uint32_t& channel_idx, const double& freq) override {} void set_rx_freq(const uint32_t& channel_idx, const double& freq) override {}
void set_rx_gain_th(const float& gain) override {} void set_rx_gain_th(const float& gain) override {}

@ -85,6 +85,12 @@ public:
*/ */
void set_primary_cell(uint32_t earfcn, srslte_cell_t cell); void set_primary_cell(uint32_t earfcn, srslte_cell_t cell);
/**
* Sets receiver gain offset to convert estimated dBFs to dBm in RSRP
* @param rx_gain_offset Gain offset in dB
*/
void set_rx_gain_offset(float rx_gain_offset_db);
/** /**
* Sets the PCI list of the cells this components needs to measure and starts the FSM for measuring * Sets the PCI list of the cells this components needs to measure and starts the FSM for measuring
* @param pci is the list of PCIs to measure * @param pci is the list of PCIs to measure

@ -92,6 +92,28 @@ static int parse_args(all_args_t* args, int argc, char* argv[])
("rf.time_adv_nsamples", bpo::value<string>(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance") ("rf.time_adv_nsamples", bpo::value<string>(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance")
("rf.continuous_tx", bpo::value<string>(&args->rf.continuous_tx)->default_value("auto"), "Transmit samples continuously to the radio or on bursts (auto/yes/no). Default is auto (yes for UHD, no for rest)") ("rf.continuous_tx", bpo::value<string>(&args->rf.continuous_tx)->default_value("auto"), "Transmit samples continuously to the radio or on bursts (auto/yes/no). Default is auto (yes for UHD, no for rest)")
("rf.bands.rx[0].min", bpo::value<float>(&args->rf.ch_rx_bands[0].min)->default_value(0), "Lower frequency boundary for CH0-RX")
("rf.bands.rx[0].max", bpo::value<float>(&args->rf.ch_rx_bands[0].max)->default_value(0), "Higher frequency boundary for CH0-RX")
("rf.bands.rx[1].min", bpo::value<float>(&args->rf.ch_rx_bands[1].min)->default_value(0), "Lower frequency boundary for CH1-RX")
("rf.bands.rx[1].max", bpo::value<float>(&args->rf.ch_rx_bands[1].max)->default_value(0), "Higher frequency boundary for CH1-RX")
("rf.bands.rx[2].min", bpo::value<float>(&args->rf.ch_rx_bands[2].min)->default_value(0), "Lower frequency boundary for CH2-RX")
("rf.bands.rx[2].max", bpo::value<float>(&args->rf.ch_rx_bands[2].max)->default_value(0), "Higher frequency boundary for CH2-RX")
("rf.bands.rx[3].min", bpo::value<float>(&args->rf.ch_rx_bands[3].min)->default_value(0), "Lower frequency boundary for CH3-RX")
("rf.bands.rx[3].max", bpo::value<float>(&args->rf.ch_rx_bands[3].max)->default_value(0), "Higher frequency boundary for CH3-RX")
("rf.bands.rx[4].min", bpo::value<float>(&args->rf.ch_rx_bands[4].min)->default_value(0), "Lower frequency boundary for CH4-RX")
("rf.bands.rx[4].max", bpo::value<float>(&args->rf.ch_rx_bands[4].max)->default_value(0), "Higher frequency boundary for CH4-RX")
("rf.bands.tx[0].min", bpo::value<float>(&args->rf.ch_tx_bands[0].min)->default_value(0), "Lower frequency boundary for CH1-TX")
("rf.bands.tx[0].max", bpo::value<float>(&args->rf.ch_tx_bands[0].max)->default_value(0), "Higher frequency boundary for CH1-TX")
("rf.bands.tx[1].min", bpo::value<float>(&args->rf.ch_tx_bands[1].min)->default_value(0), "Lower frequency boundary for CH1-TX")
("rf.bands.tx[1].max", bpo::value<float>(&args->rf.ch_tx_bands[1].max)->default_value(0), "Higher frequency boundary for CH1-TX")
("rf.bands.tx[2].min", bpo::value<float>(&args->rf.ch_tx_bands[2].min)->default_value(0), "Lower frequency boundary for CH2-TX")
("rf.bands.tx[2].max", bpo::value<float>(&args->rf.ch_tx_bands[2].max)->default_value(0), "Higher frequency boundary for CH2-TX")
("rf.bands.tx[3].min", bpo::value<float>(&args->rf.ch_tx_bands[3].min)->default_value(0), "Lower frequency boundary for CH3-TX")
("rf.bands.tx[3].max", bpo::value<float>(&args->rf.ch_tx_bands[3].max)->default_value(0), "Higher frequency boundary for CH3-TX")
("rf.bands.tx[4].min", bpo::value<float>(&args->rf.ch_tx_bands[4].min)->default_value(0), "Lower frequency boundary for CH4-TX")
("rf.bands.tx[4].max", bpo::value<float>(&args->rf.ch_tx_bands[4].max)->default_value(0), "Higher frequency boundary for CH4-TX")
("rrc.feature_group", bpo::value<uint32_t>(&args->stack.rrc.feature_group)->default_value(0xe6041000), "Hex value of the featureGroupIndicators field in the" ("rrc.feature_group", bpo::value<uint32_t>(&args->stack.rrc.feature_group)->default_value(0xe6041000), "Hex value of the featureGroupIndicators field in the"
"UECapabilityInformation message. Default 0xe6041000") "UECapabilityInformation message. Default 0xe6041000")
("rrc.ue_category", bpo::value<string>(&args->stack.rrc.ue_category_str)->default_value(SRSLTE_UE_CATEGORY_DEFAULT), "UE Category (1 to 10)") ("rrc.ue_category", bpo::value<string>(&args->stack.rrc.ue_category_str)->default_value(SRSLTE_UE_CATEGORY_DEFAULT), "UE Category (1 to 10)")
@ -116,7 +138,7 @@ static int parse_args(all_args_t* args, int argc, char* argv[])
("gui.enable", bpo::value<bool>(&args->gui.enable)->default_value(false), "Enable GUI plots") ("gui.enable", bpo::value<bool>(&args->gui.enable)->default_value(false), "Enable GUI plots")
("log.rf_level", bpo::value<string>(&args->rf.log_level)->default_value("error"), "RF log level") ("log.rf_level", bpo::value<string>(&args->rf.log_level), "RF log level")
("log.phy_level", bpo::value<string>(&args->phy.log.phy_level), "PHY log level") ("log.phy_level", bpo::value<string>(&args->phy.log.phy_level), "PHY log level")
("log.phy_lib_level", bpo::value<string>(&args->phy.log.phy_lib_level), "PHY lib log level") ("log.phy_lib_level", bpo::value<string>(&args->phy.log.phy_lib_level), "PHY lib log level")
("log.phy_hex_limit", bpo::value<int>(&args->phy.log.phy_hex_limit), "PHY log hex dump limit") ("log.phy_hex_limit", bpo::value<int>(&args->phy.log.phy_hex_limit), "PHY log hex dump limit")

@ -675,6 +675,13 @@ void phy_common::reset()
ZERO_OBJECT(pending_dl_dai); ZERO_OBJECT(pending_dl_dai);
ZERO_OBJECT(pending_ul_ack); ZERO_OBJECT(pending_ul_ack);
ZERO_OBJECT(pending_ul_grant); ZERO_OBJECT(pending_ul_grant);
// Release mapping of secondary cells
if (args != nullptr && radio_h != nullptr) {
for (uint32_t i = 1; i < args->nof_carriers; i++) {
radio_h->release_freq(i);
}
}
} }
/* Convert 6-bit maps to 10-element subframe tables /* Convert 6-bit maps to 10-element subframe tables

@ -87,6 +87,11 @@ void intra_measure::set_primary_cell(uint32_t earfcn, srslte_cell_t cell)
serving_cell = cell; serving_cell = cell;
} }
void intra_measure::set_rx_gain_offset(float rx_gain_offset_db_)
{
rx_gain_offset_db = rx_gain_offset_db_;
}
void intra_measure::meas_stop() void intra_measure::meas_stop()
{ {
state.set_state(internal_state::idle); state.set_state(internal_state::idle);

@ -183,13 +183,12 @@ void sync::reset()
phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte::phy_cell_t* found_cell) phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte::phy_cell_t* found_cell)
{ {
phy_interface_rrc_lte::cell_search_ret_t ret; std::unique_lock<std::mutex> ul(rrc_mutex);
phy_interface_rrc_lte::cell_search_ret_t ret = {};
ret.found = phy_interface_rrc_lte::cell_search_ret_t::ERROR; ret.found = phy_interface_rrc_lte::cell_search_ret_t::ERROR;
ret.last_freq = phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS; ret.last_freq = phy_interface_rrc_lte::cell_search_ret_t::NO_MORE_FREQS;
rrc_mutex.lock();
// Move state to IDLE // Move state to IDLE
Info("Cell Search: Start EARFCN index=%u/%zd\n", cellsearch_earfcn_index, earfcn.size()); Info("Cell Search: Start EARFCN index=%u/%zd\n", cellsearch_earfcn_index, earfcn.size());
phy_state.go_idle(); phy_state.go_idle();
@ -249,7 +248,6 @@ phy_interface_rrc_lte::cell_search_ret_t sync::cell_search(phy_interface_rrc_lte
ret.last_freq = phy_interface_rrc_lte::cell_search_ret_t::MORE_FREQS; ret.last_freq = phy_interface_rrc_lte::cell_search_ret_t::MORE_FREQS;
} }
rrc_mutex.unlock();
return ret; return ret;
} }
@ -526,8 +524,12 @@ void sync::run_thread()
if (srslte_cell_isvalid(&cell)) { if (srslte_cell_isvalid(&cell)) {
for (size_t i = 0; i < intra_freq_meas.size(); i++) { for (size_t i = 0; i < intra_freq_meas.size(); i++) {
intra_freq_meas[i]->write(tti, worker->get_buffer(i, 0), SRSLTE_SF_LEN_PRB(cell.nof_prb)); intra_freq_meas[i]->write(tti, worker->get_buffer(i, 0), SRSLTE_SF_LEN_PRB(cell.nof_prb));
// Update RX gain
intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset);
} }
} }
break; break;
case 0: case 0:
Warning("SYNC: Out-of-sync detected in PSS/SSS\n"); Warning("SYNC: Out-of-sync detected in PSS/SSS\n");
@ -819,11 +821,6 @@ bool sync::set_frequency()
set_dl_freq / 1e6, set_dl_freq / 1e6,
set_ul_freq / 1e6); set_ul_freq / 1e6);
log_h->console("Searching cell in DL EARFCN=%d, f_dl=%.1f MHz, f_ul=%.1f MHz\n",
current_earfcn,
set_dl_freq / 1e6,
set_ul_freq / 1e6);
// Logical channel is 0 // Logical channel is 0
radio_h->set_rx_freq(0, set_dl_freq); radio_h->set_rx_freq(0, set_dl_freq);
radio_h->set_tx_freq(0, set_ul_freq); radio_h->set_tx_freq(0, set_ul_freq);

@ -210,6 +210,7 @@ private:
return ret; return ret;
} }
void release_freq(const uint32_t& carrier_idx) override{};
void tx_end() override {} void tx_end() override {}
bool rx_now(srslte::rf_buffer_interface& buffer, const uint32_t& nof_samples, srslte_timestamp_t* rxd_time) override bool rx_now(srslte::rf_buffer_interface& buffer, const uint32_t& nof_samples, srslte_timestamp_t* rxd_time) override
{ {

Loading…
Cancel
Save