diff --git a/lib/include/srslte/common/interfaces_common.h b/lib/include/srslte/common/interfaces_common.h index eaf3483bb..bb1cb8798 100644 --- a/lib/include/srslte/common/interfaces_common.h +++ b/lib/include/srslte/common/interfaces_common.h @@ -34,6 +34,11 @@ typedef struct { int phy_hex_limit = -1; } phy_log_args_t; +typedef struct { + float min; + float max; +} rf_args_band_t; + // RF/radio args typedef struct { std::string type; @@ -52,6 +57,10 @@ typedef struct { std::string device_args; std::string time_adv_nsamples; std::string continuous_tx; + + std::array ch_rx_bands; + std::array ch_tx_bands; + } rf_args_t; class srslte_gw_config_t diff --git a/lib/include/srslte/interfaces/radio_interfaces.h b/lib/include/srslte/interfaces/radio_interfaces.h index 46a4eeb70..161b4846e 100644 --- a/lib/include/srslte/interfaces/radio_interfaces.h +++ b/lib/include/srslte/interfaces/radio_interfaces.h @@ -49,13 +49,13 @@ namespace srslte { class rf_buffer_interface { public: - virtual cf_t* get(uint32_t channel_idx) const = 0; - virtual void set(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 void set(uint32_t cc_idx, uint32_t port_idx, uint32_t nof_antennas, cf_t* ptr) = 0; - virtual void** to_void() = 0; - virtual cf_t** to_cf_t() = 0; - virtual uint32_t size() = 0; + virtual cf_t* get(const uint32_t& channel_idx) const = 0; + virtual void set(const uint32_t& channel_idx, cf_t* ptr) = 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(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 cf_t** to_cf_t() = 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; + /** + * 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 * @param gain Gain in dB diff --git a/lib/include/srslte/radio/radio.h b/lib/include/srslte/radio/radio.h index 3c20c4186..f093a094b 100644 --- a/lib/include/srslte/radio/radio.h +++ b/lib/include/srslte/radio/radio.h @@ -28,6 +28,7 @@ #include "srslte/interfaces/radio_interfaces.h" #include "srslte/phy/rf/rf.h" #include "srslte/srslte.h" +#include #ifndef SRSLTE_RADIO_H #define SRSLTE_RADIO_H @@ -112,15 +113,15 @@ public: } return *this; } - cf_t* get(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; } - cf_t* get(uint32_t cc_idx, uint32_t port_idx, uint32_t nof_antennas) const override + 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(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(); } cf_t** to_cf_t() override { return sample_buffer.data(); } @@ -171,6 +172,7 @@ public: // setter 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; @@ -219,6 +221,7 @@ private: double cur_tx_srate = 0.0f; uint32_t nof_antennas = 0; uint32_t nof_channels = 0; + uint32_t nof_carriers = 0; // Define default values for known radios 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_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& 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 available_channels = {}; + std::map 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); void set_tx_adv(int nsamples); void set_tx_adv_neg(bool tx_adv_is_neg); + bool config_rf_channels(const rf_args_t& args); }; } // namespace srslte diff --git a/lib/src/phy/sync/sync.c b/lib/src/phy/sync/sync.c index cc06a11e8..57d2414bf 100644 --- a/lib/src/phy/sync/sync.c +++ b/lib/src/phy/sync/sync.c @@ -843,7 +843,7 @@ srslte_sync_find(srslte_sync_t* q, const cf_t* input, uint32_t find_offset, uint q->threshold, 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"); } diff --git a/lib/src/radio/radio.cc b/lib/src/radio/radio.cc index 15906527a..ce302d082 100644 --- a/lib/src/radio/radio.cc +++ b/lib/src/radio/radio.cc @@ -25,6 +25,7 @@ extern "C" { } #include "srslte/common/log_filter.h" #include "srslte/radio/radio.h" +#include #include #include @@ -76,8 +77,14 @@ int radio::init(const rf_args_t& args, phy_interface_radio* phy_) 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_antennas = args.nof_antennas; + nof_carriers = args.nof_carriers; // Init and start Radio 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; 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 - // accepts up to SRSLTE_MAX_CHANNELS buffers + void* radio_buffers[SRSLTE_MAX_CHANNELS] = {}; + 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; } else { 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_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 - // accepts up to SRSLTE_MAX_CHANNELS buffers + void* radio_buffers[SRSLTE_MAX_CHANNELS] = {}; + 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( - &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; if (ret > 0) { return true; @@ -292,20 +305,40 @@ bool radio::get_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) { return; } - if ((channel_idx + 1) * nof_antennas <= nof_channels) { - for (uint32_t i = 0; i < nof_antennas; i++) { - srslte_rf_set_rx_freq(&rf_device, channel_idx * nof_antennas + i, freq + freq_offset); + + // 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++) { + 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 { + log_h->error("set_rx_freq: physical_channel_idx=%d for %d antennas exceeds maximum channels (%d)\n", + physical_channel_idx, + nof_antennas, + nof_channels); } } else { - log_h->error("set_rx_freq: channel_idx=%d for %d antennas exceeds maximum channels (%d)\n", - channel_idx, - nof_antennas, - nof_channels); + log_h->error("set_rx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx); } } @@ -333,20 +366,34 @@ void radio::set_rx_srate(const double& 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) { return; } - if ((channel_idx + 1) * nof_antennas <= nof_channels) { - for (uint32_t i = 0; i < nof_antennas; i++) { - srslte_rf_set_tx_freq(&rf_device, channel_idx * nof_antennas + i, freq + freq_offset); + + // 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++) { + 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 { + log_h->error("set_tx_freq: physical_channel_idx=%d for %d antennas exceeds maximum channels (%d)\n", + physical_channel_idx, + nof_antennas, + nof_channels); } } else { - log_h->error("set_tx_freq: channel_idx=%d for %d antennas exceeds maximum channels (%d)\n", - channel_idx, - nof_antennas, - nof_channels); + log_h->error("set_tx_freq: Could not allocate frequency %.1f MHz to carrier %d\n", freq / 1e6, carrier_idx); } } @@ -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 dl_rf_channels = {}; + std::list 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 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 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 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 lock(mutex); + return allocated_channels.count(logical_ch) > 0; +} + } // namespace srslte diff --git a/srsenb/test/phy/enb_phy_test.cc b/srsenb/test/phy/enb_phy_test.cc index 6928ed38a..51b36d795 100644 --- a/srsenb/test/phy/enb_phy_test.cc +++ b/srsenb/test/phy/enb_phy_test.cc @@ -233,6 +233,7 @@ public: // Return True if 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_rx_freq(const uint32_t& channel_idx, const double& freq) override {} void set_rx_gain_th(const float& gain) override {} diff --git a/srsue/hdr/phy/scell/intra_measure.h b/srsue/hdr/phy/scell/intra_measure.h index 78f13fa81..3dcbfc5e3 100644 --- a/srsue/hdr/phy/scell/intra_measure.h +++ b/srsue/hdr/phy/scell/intra_measure.h @@ -85,6 +85,12 @@ public: */ 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 * @param pci is the list of PCIs to measure diff --git a/srsue/src/main.cc b/srsue/src/main.cc index 949865cd0..5809656fb 100644 --- a/srsue/src/main.cc +++ b/srsue/src/main.cc @@ -92,6 +92,28 @@ static int parse_args(all_args_t* args, int argc, char* argv[]) ("rf.time_adv_nsamples", bpo::value(&args->rf.time_adv_nsamples)->default_value("auto"), "Transmission time advance") ("rf.continuous_tx", bpo::value(&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(&args->rf.ch_rx_bands[0].min)->default_value(0), "Lower frequency boundary for CH0-RX") + ("rf.bands.rx[0].max", bpo::value(&args->rf.ch_rx_bands[0].max)->default_value(0), "Higher frequency boundary for CH0-RX") + ("rf.bands.rx[1].min", bpo::value(&args->rf.ch_rx_bands[1].min)->default_value(0), "Lower frequency boundary for CH1-RX") + ("rf.bands.rx[1].max", bpo::value(&args->rf.ch_rx_bands[1].max)->default_value(0), "Higher frequency boundary for CH1-RX") + ("rf.bands.rx[2].min", bpo::value(&args->rf.ch_rx_bands[2].min)->default_value(0), "Lower frequency boundary for CH2-RX") + ("rf.bands.rx[2].max", bpo::value(&args->rf.ch_rx_bands[2].max)->default_value(0), "Higher frequency boundary for CH2-RX") + ("rf.bands.rx[3].min", bpo::value(&args->rf.ch_rx_bands[3].min)->default_value(0), "Lower frequency boundary for CH3-RX") + ("rf.bands.rx[3].max", bpo::value(&args->rf.ch_rx_bands[3].max)->default_value(0), "Higher frequency boundary for CH3-RX") + ("rf.bands.rx[4].min", bpo::value(&args->rf.ch_rx_bands[4].min)->default_value(0), "Lower frequency boundary for CH4-RX") + ("rf.bands.rx[4].max", bpo::value(&args->rf.ch_rx_bands[4].max)->default_value(0), "Higher frequency boundary for CH4-RX") + + ("rf.bands.tx[0].min", bpo::value(&args->rf.ch_tx_bands[0].min)->default_value(0), "Lower frequency boundary for CH1-TX") + ("rf.bands.tx[0].max", bpo::value(&args->rf.ch_tx_bands[0].max)->default_value(0), "Higher frequency boundary for CH1-TX") + ("rf.bands.tx[1].min", bpo::value(&args->rf.ch_tx_bands[1].min)->default_value(0), "Lower frequency boundary for CH1-TX") + ("rf.bands.tx[1].max", bpo::value(&args->rf.ch_tx_bands[1].max)->default_value(0), "Higher frequency boundary for CH1-TX") + ("rf.bands.tx[2].min", bpo::value(&args->rf.ch_tx_bands[2].min)->default_value(0), "Lower frequency boundary for CH2-TX") + ("rf.bands.tx[2].max", bpo::value(&args->rf.ch_tx_bands[2].max)->default_value(0), "Higher frequency boundary for CH2-TX") + ("rf.bands.tx[3].min", bpo::value(&args->rf.ch_tx_bands[3].min)->default_value(0), "Lower frequency boundary for CH3-TX") + ("rf.bands.tx[3].max", bpo::value(&args->rf.ch_tx_bands[3].max)->default_value(0), "Higher frequency boundary for CH3-TX") + ("rf.bands.tx[4].min", bpo::value(&args->rf.ch_tx_bands[4].min)->default_value(0), "Lower frequency boundary for CH4-TX") + ("rf.bands.tx[4].max", bpo::value(&args->rf.ch_tx_bands[4].max)->default_value(0), "Higher frequency boundary for CH4-TX") + ("rrc.feature_group", bpo::value(&args->stack.rrc.feature_group)->default_value(0xe6041000), "Hex value of the featureGroupIndicators field in the" "UECapabilityInformation message. Default 0xe6041000") ("rrc.ue_category", bpo::value(&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(&args->gui.enable)->default_value(false), "Enable GUI plots") - ("log.rf_level", bpo::value(&args->rf.log_level)->default_value("error"), "RF log level") + ("log.rf_level", bpo::value(&args->rf.log_level), "RF log level") ("log.phy_level", bpo::value(&args->phy.log.phy_level), "PHY log level") ("log.phy_lib_level", bpo::value(&args->phy.log.phy_lib_level), "PHY lib log level") ("log.phy_hex_limit", bpo::value(&args->phy.log.phy_hex_limit), "PHY log hex dump limit") diff --git a/srsue/src/phy/phy_common.cc b/srsue/src/phy/phy_common.cc index 93a09631f..a743d2a8a 100644 --- a/srsue/src/phy/phy_common.cc +++ b/srsue/src/phy/phy_common.cc @@ -675,6 +675,13 @@ void phy_common::reset() ZERO_OBJECT(pending_dl_dai); ZERO_OBJECT(pending_ul_ack); 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 diff --git a/srsue/src/phy/scell/intra_measure.cc b/srsue/src/phy/scell/intra_measure.cc index 8aa91bed4..f8fbfda1d 100644 --- a/srsue/src/phy/scell/intra_measure.cc +++ b/srsue/src/phy/scell/intra_measure.cc @@ -87,6 +87,11 @@ void intra_measure::set_primary_cell(uint32_t earfcn, srslte_cell_t 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() { state.set_state(internal_state::idle); diff --git a/srsue/src/phy/sync.cc b/srsue/src/phy/sync.cc index e5381047c..af1ddca96 100644 --- a/srsue/src/phy/sync.cc +++ b/srsue/src/phy/sync.cc @@ -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 ret; + std::unique_lock ul(rrc_mutex); + phy_interface_rrc_lte::cell_search_ret_t ret = {}; 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; - rrc_mutex.lock(); - // Move state to IDLE Info("Cell Search: Start EARFCN index=%u/%zd\n", cellsearch_earfcn_index, earfcn.size()); 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; } - rrc_mutex.unlock(); return ret; } @@ -526,8 +524,12 @@ void sync::run_thread() if (srslte_cell_isvalid(&cell)) { 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)); + + // Update RX gain + intra_freq_meas[i]->set_rx_gain_offset(worker_com->rx_gain_offset); } } + break; case 0: Warning("SYNC: Out-of-sync detected in PSS/SSS\n"); @@ -819,11 +821,6 @@ bool sync::set_frequency() set_dl_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 radio_h->set_rx_freq(0, set_dl_freq); radio_h->set_tx_freq(0, set_ul_freq); diff --git a/srsue/test/phy/ue_phy_test.cc b/srsue/test/phy/ue_phy_test.cc index 6b89bdba3..d94a39cb6 100644 --- a/srsue/test/phy/ue_phy_test.cc +++ b/srsue/test/phy/ue_phy_test.cc @@ -210,6 +210,7 @@ private: return ret; } + void release_freq(const uint32_t& carrier_idx) override{}; void tx_end() override {} bool rx_now(srslte::rf_buffer_interface& buffer, const uint32_t& nof_samples, srslte_timestamp_t* rxd_time) override {