mirror of https://github.com/PentHertz/srsLTE.git
Made intra frequency cell search and measurment generic
This commit is contained in:
parent
648f0af437
commit
60015e7ceb
|
@ -13,6 +13,7 @@
|
|||
#ifndef SRSRAN_PHY_INTERFACE_TYPES_H
|
||||
#define SRSRAN_PHY_INTERFACE_TYPES_H
|
||||
|
||||
#include "srsran/common/common.h"
|
||||
#include "srsran/srsran.h"
|
||||
|
||||
/// Common types defined by the PHY layer.
|
||||
|
@ -52,11 +53,12 @@ struct phy_meas_nr_t {
|
|||
};
|
||||
|
||||
struct phy_meas_t {
|
||||
float rsrp;
|
||||
float rsrq;
|
||||
float cfo_hz;
|
||||
uint32_t earfcn;
|
||||
uint32_t pci;
|
||||
srsran::srsran_rat_t rat; ///< LTE or NR
|
||||
float rsrp;
|
||||
float rsrq;
|
||||
float cfo_hz;
|
||||
uint32_t earfcn;
|
||||
uint32_t pci;
|
||||
};
|
||||
|
||||
struct phy_cell_t {
|
||||
|
|
|
@ -1,218 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#ifndef SRSUE_INTRA_MEASURE_H
|
||||
#define SRSUE_INTRA_MEASURE_H
|
||||
|
||||
#include <srsran/common/threads.h>
|
||||
#include <srsran/common/tti_sync_cv.h>
|
||||
#include <srsran/srsran.h>
|
||||
|
||||
#include "scell_recv.h"
|
||||
|
||||
namespace srsue {
|
||||
namespace scell {
|
||||
|
||||
// Class to perform intra-frequency measurements
|
||||
class intra_measure : public srsran::thread
|
||||
{
|
||||
/*
|
||||
* The intra-cell measurment has 5 different states:
|
||||
* - idle: it has been initiated and it is waiting to get configured to start capturing samples. From any state
|
||||
* except quit can transition to idle.
|
||||
* - wait: waits for at least intra_freq_meas_period_ms since last receive start and goes to receive.
|
||||
* - receive: captures base-band samples for intra_freq_meas_len_ms and goes to measure.
|
||||
* - measure: enables the inner thread to start the measuring function. The asynchronous buffer will transition to
|
||||
* wait as soon as it has read the data from the buffer.
|
||||
* - quit: stops the inner thread and quits. Transition from any state measure state.
|
||||
*
|
||||
* FSM abstraction:
|
||||
*
|
||||
* +------+ set_cells_to_meas +------+ intra_freq_meas_period_ms +---------+
|
||||
* | Idle | --------------------->| Wait |------------------------------>| Receive |
|
||||
* +------+ +------+ +---------+
|
||||
* ^ ^ | stop +------+
|
||||
* | Read buffer | | ----->| Quit |
|
||||
* init +---------+ intra_freq_meas_len_ms | +------+
|
||||
* meas_stop | Measure |<----------------------------------+
|
||||
* +---------+
|
||||
*/
|
||||
public:
|
||||
// Interface for reporting new cell measurements
|
||||
class meas_itf
|
||||
{
|
||||
public:
|
||||
virtual void cell_meas_reset(uint32_t cc_idx) = 0;
|
||||
virtual void new_cell_meas(uint32_t cc_idx, const std::vector<phy_meas_t>& meas) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* Constructor
|
||||
*/
|
||||
intra_measure(srslog::basic_logger& logger);
|
||||
|
||||
/**
|
||||
* Destructor
|
||||
*/
|
||||
~intra_measure();
|
||||
|
||||
/**
|
||||
* Initiation function, necessary to configure main parameters
|
||||
* @param common SRSUE phy_common instance pointer for providing intra_freq_meas_len_ms and intra_freq_meas_period_ms
|
||||
* @param rrc SRSUE PHY->RRC interface for supplying the RRC with the measurements
|
||||
*/
|
||||
void init(uint32_t cc_idx, phy_common* common, meas_itf* new_cell_itf);
|
||||
|
||||
/**
|
||||
* Stops the operation of this component
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* Sets the primary cell, configures the cell bandwidth and sampling rate
|
||||
* @param earfcn Frequency the component is receiving base-band from. Used only for reporting the EARFCN to the RRC
|
||||
* @param cell Actual cell configuration
|
||||
*/
|
||||
void set_primary_cell(uint32_t earfcn, srsran_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
|
||||
*/
|
||||
void set_cells_to_meas(const std::set<uint32_t>& pci);
|
||||
|
||||
/**
|
||||
* Stops the measurment FSM, setting the inner state to idle.
|
||||
*/
|
||||
void meas_stop();
|
||||
|
||||
/**
|
||||
* Inputs the baseband IQ samples into the component, internal state dictates whether it will be written or not.
|
||||
* @param tti The current physical layer TTI, used for calculating the buffer write
|
||||
* @param data buffer with baseband IQ samples
|
||||
* @param nsamples number of samples to write
|
||||
*/
|
||||
void write(uint32_t tti, cf_t* data, uint32_t nsamples);
|
||||
|
||||
/**
|
||||
* Get EARFCN of this component
|
||||
* @return EARFCN
|
||||
*/
|
||||
uint32_t get_earfcn() { return current_earfcn; };
|
||||
|
||||
/**
|
||||
* Synchronous wait mechanism, blocks the writer thread while it is in measure state. If the asynchonous thread is too
|
||||
* slow, use this method for stalling the writing thread and wait the asynchronous thread to clear the buffer.
|
||||
*/
|
||||
void wait_meas()
|
||||
{ // Only used by scell_search_test
|
||||
state.wait_change(internal_state::measure);
|
||||
}
|
||||
|
||||
private:
|
||||
class internal_state ///< Internal state class, provides thread safe state management
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
idle = 0, ///< Initial state, internal thread runs, it does not capture data
|
||||
wait, ///< Wait for the period time to pass
|
||||
receive, ///< Accumulate samples in ring buffer
|
||||
measure, ///< Module is busy measuring
|
||||
quit ///< Quit thread, no transitions are allowed
|
||||
} state_t;
|
||||
|
||||
private:
|
||||
state_t state = idle;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cvar;
|
||||
|
||||
public:
|
||||
/**
|
||||
* Get the internal state
|
||||
* @return protected state
|
||||
*/
|
||||
state_t get_state() { return state; }
|
||||
|
||||
/**
|
||||
* Transitions to a different state, all transitions are allowed except from quit
|
||||
* @param new_state
|
||||
*/
|
||||
void set_state(state_t new_state)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
// Do not allow transition from quit
|
||||
if (state != quit) {
|
||||
state = new_state;
|
||||
}
|
||||
|
||||
// Notifies to the inner thread about the change of state
|
||||
cvar.notify_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* Waits for a state transition to a state different than the provided, used for blocking the inner thread
|
||||
*/
|
||||
void wait_change(state_t s)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
while (state == s) {
|
||||
cvar.wait(lock);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
internal_state state;
|
||||
|
||||
/**
|
||||
* Measurement process helper method. Encapusulates the neighbour cell measurement functionality
|
||||
*/
|
||||
void measure_proc();
|
||||
|
||||
/**
|
||||
* Internal asynchronous low priority thread, waits for measure internal state to execute the measurement process. It
|
||||
* stops when the internal state transitions to quit.
|
||||
*/
|
||||
void run_thread() override;
|
||||
|
||||
///< Internal Thread priority, low by default
|
||||
const static int INTRA_FREQ_MEAS_PRIO = DEFAULT_PRIORITY + 5;
|
||||
|
||||
scell_recv scell;
|
||||
meas_itf* new_cell_itf = nullptr;
|
||||
srslog::basic_logger& logger;
|
||||
uint32_t cc_idx = 0;
|
||||
uint32_t current_earfcn = 0;
|
||||
uint32_t current_sflen = 0;
|
||||
srsran_cell_t serving_cell = {};
|
||||
std::set<uint32_t> active_pci = {};
|
||||
std::mutex active_pci_mutex = {};
|
||||
uint32_t last_measure_tti = 0;
|
||||
uint32_t intra_freq_meas_len_ms = 20;
|
||||
uint32_t intra_freq_meas_period_ms = 200;
|
||||
uint32_t rx_gain_offset_db = 0;
|
||||
|
||||
cf_t* search_buffer = nullptr;
|
||||
|
||||
srsran_ringbuffer_t ring_buffer = {};
|
||||
|
||||
srsran_refsignal_dl_sync_t refsignal_dl_sync = {};
|
||||
};
|
||||
|
||||
} // namespace scell
|
||||
} // namespace srsue
|
||||
|
||||
#endif // SRSUE_INTRA_MEASURE_H
|
|
@ -0,0 +1,249 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#ifndef SRSUE_INTRA_MEASURE_BASE_H
|
||||
#define SRSUE_INTRA_MEASURE_BASE_H
|
||||
|
||||
#include <srsran/common/common.h>
|
||||
#include <srsran/common/threads.h>
|
||||
#include <srsran/common/tti_sync_cv.h>
|
||||
#include <srsran/srsran.h>
|
||||
|
||||
#include "scell_recv.h"
|
||||
|
||||
namespace srsue {
|
||||
namespace scell {
|
||||
|
||||
/**
|
||||
* @brief Describes a generic base class to perform intra-frequency measurements
|
||||
*/
|
||||
class intra_measure_base : public srsran::thread
|
||||
{
|
||||
/*
|
||||
* The intra-cell measurment has 5 different states:
|
||||
* - idle: it has been initiated and it is waiting to get configured to start capturing samples. From any state
|
||||
* except quit can transition to idle.
|
||||
* - wait: waits for at least intra_freq_meas_period_ms since last receive start and goes to receive.
|
||||
* - receive: captures base-band samples for intra_freq_meas_len_ms and goes to measure.
|
||||
* - measure: enables the inner thread to start the measuring function. The asynchronous buffer will transition to
|
||||
* wait as soon as it has read the data from the buffer.
|
||||
* - quit: stops the inner thread and quits. Transition from any state measure state.
|
||||
*
|
||||
* FSM abstraction:
|
||||
*
|
||||
* +------+ set_cells_to_meas +------+ intra_freq_meas_period_ms +---------+
|
||||
* | Idle | --------------------->| Wait |------------------------------>| Receive |
|
||||
* +------+ +------+ +---------+
|
||||
* ^ ^ | stop +------+
|
||||
* | Read buffer | | ----->| Quit |
|
||||
* init +---------+ intra_freq_meas_len_ms | +------+
|
||||
* meas_stop | Measure |<----------------------------------+
|
||||
* +---------+
|
||||
*/
|
||||
public:
|
||||
/**
|
||||
* @brief Describes an interface for reporting new cell measurements
|
||||
*/
|
||||
class meas_itf
|
||||
{
|
||||
public:
|
||||
virtual void cell_meas_reset(uint32_t cc_idx) = 0;
|
||||
virtual void new_cell_meas(uint32_t cc_idx, const std::vector<phy_meas_t>& meas) = 0;
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Describes the default generic configuration arguments
|
||||
*/
|
||||
struct args_t {
|
||||
double srate_hz = 0.0; ///< Sampling rate in Hz, set to 0.0 for maximum
|
||||
uint32_t len_ms = 20; ///< Amount of time to accumulate
|
||||
uint32_t period_ms = 200; ///< Accumulation trigger period
|
||||
float rx_gain_offset_db = 0.0f; ///< Gain offset, for calibrated measurements
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Stops the operation of this component and it cannot be started again
|
||||
* @note use meas_stop() method to stop measurements temporally
|
||||
*/
|
||||
void stop();
|
||||
|
||||
/**
|
||||
* @brief Updates the 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);
|
||||
|
||||
/**
|
||||
* @brief 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
|
||||
*/
|
||||
void set_cells_to_meas(const std::set<uint32_t>& pci);
|
||||
|
||||
/**
|
||||
* @brief Stops the measurement FSM, setting the inner state to idle.
|
||||
*/
|
||||
void meas_stop();
|
||||
|
||||
/**
|
||||
* @brief Inputs the baseband IQ samples into the component, internal state dictates whether it will be written or
|
||||
* not.
|
||||
* @param tti The current physical layer TTI, used for calculating the buffer write
|
||||
* @param data buffer with baseband IQ samples
|
||||
* @param nsamples number of samples to write
|
||||
*/
|
||||
void write(uint32_t tti, cf_t* data, uint32_t nsamples);
|
||||
|
||||
/**
|
||||
* @brief Get EARFCN of this component
|
||||
* @return EARFCN
|
||||
*/
|
||||
virtual uint32_t get_earfcn() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Synchronous wait mechanism, blocks the writer thread while it is in measure state. If the asynchronous
|
||||
* thread is too slow, use this method for stalling the writing thread and wait the asynchronous thread to clear the
|
||||
* buffer.
|
||||
*/
|
||||
void wait_meas()
|
||||
{ // Only used by scell_search_test
|
||||
state.wait_change(internal_state::measure);
|
||||
}
|
||||
|
||||
protected:
|
||||
struct measure_context_t {
|
||||
uint32_t cc_idx = 0; ///< Component carrier index
|
||||
float rx_gain_offset_db = 0.0f; ///< Current gain offset
|
||||
std::set<uint32_t> active_pci = {}; ///< Set with the active PCIs
|
||||
uint32_t sf_len = 0; ///< Subframe length in samples
|
||||
uint32_t meas_len_ms = 20; ///< Measure length in milliseconds/sub-frames
|
||||
uint32_t meas_period_ms = 200; ///< Measure period in milliseconds/sub-frames
|
||||
meas_itf& new_cell_itf;
|
||||
|
||||
explicit measure_context_t(meas_itf& new_cell_itf_) : new_cell_itf(new_cell_itf_) {}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Generic initialization method, necessary to configure main parameters
|
||||
* @param cc_idx_ Indicates the component carrier index linked to the intra frequency measurement instance
|
||||
* @param args Generic configuration arguments
|
||||
*/
|
||||
void init_generic(uint32_t cc_idx_, const args_t& args);
|
||||
|
||||
/**
|
||||
* @brief Constructor is only accessible through inherited classes
|
||||
*/
|
||||
intra_measure_base(srslog::basic_logger& logger, meas_itf& new_cell_itf_);
|
||||
|
||||
/**
|
||||
* @brief Destructor is only accessible through inherited classes
|
||||
*/
|
||||
~intra_measure_base() override;
|
||||
|
||||
/**
|
||||
* @brief Subframe length setter, the inherited class shall set the subframe length
|
||||
* @param new_sf_len New subframe length
|
||||
*/
|
||||
void set_current_sf_len(uint32_t new_sf_len) { context.sf_len = new_sf_len; }
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Describes the internal state class, provides thread safe state management
|
||||
*/
|
||||
class internal_state
|
||||
{
|
||||
public:
|
||||
typedef enum {
|
||||
idle = 0, ///< Initial state, internal thread runs, it does not capture data
|
||||
wait, ///< Wait for the period time to pass
|
||||
receive, ///< Accumulate samples in ring buffer
|
||||
measure, ///< Module is busy measuring
|
||||
quit ///< Quit thread, no transitions are allowed
|
||||
} state_t;
|
||||
|
||||
private:
|
||||
state_t state = idle;
|
||||
std::mutex mutex;
|
||||
std::condition_variable cvar;
|
||||
|
||||
public:
|
||||
/**
|
||||
* @brief Get the internal state
|
||||
* @return protected state
|
||||
*/
|
||||
state_t get_state() const { return state; }
|
||||
|
||||
/**
|
||||
* @brief Transitions to a different state, all transitions are allowed except from quit
|
||||
* @param new_state
|
||||
*/
|
||||
void set_state(state_t new_state)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
// Do not allow transition from quit
|
||||
if (state != quit) {
|
||||
state = new_state;
|
||||
}
|
||||
|
||||
// Notifies to the inner thread about the change of state
|
||||
cvar.notify_all();
|
||||
}
|
||||
|
||||
/**
|
||||
* @brief Waits for a state transition to a state different than the provided, used for blocking the inner thread
|
||||
*/
|
||||
void wait_change(state_t s)
|
||||
{
|
||||
std::unique_lock<std::mutex> lock(mutex);
|
||||
while (state == s) {
|
||||
cvar.wait(lock);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* @brief Get the Radio Access Technology (RAT) that is being measured
|
||||
* @return The measured RAT
|
||||
*/
|
||||
virtual srsran::srsran_rat_t get_rat() const = 0;
|
||||
|
||||
/**
|
||||
* @brief Pure virtual function to perform measurements
|
||||
*/
|
||||
virtual void measure_rat(const measure_context_t& context, std::vector<cf_t>& buffer) = 0;
|
||||
|
||||
/**
|
||||
* @brief Measurement process helper method. Encapsulates the neighbour cell measurement functionality
|
||||
*/
|
||||
void measure_proc();
|
||||
|
||||
/**
|
||||
* @brief Internal asynchronous low priority thread, waits for measure internal state to execute the measurement
|
||||
* process. It stops when the internal state transitions to quit.
|
||||
*/
|
||||
void run_thread() override;
|
||||
|
||||
///< Internal Thread priority, low by default
|
||||
const static int INTRA_FREQ_MEAS_PRIO = DEFAULT_PRIORITY + 5;
|
||||
|
||||
internal_state state;
|
||||
srslog::basic_logger& logger;
|
||||
mutable std::mutex active_pci_mutex = {};
|
||||
uint32_t last_measure_tti = 0;
|
||||
measure_context_t context;
|
||||
|
||||
std::vector<cf_t> search_buffer;
|
||||
srsran_ringbuffer_t ring_buffer = {};
|
||||
};
|
||||
|
||||
} // namespace scell
|
||||
} // namespace srsue
|
||||
|
||||
#endif // SRSUE_INTRA_MEASURE_BASE_H
|
|
@ -0,0 +1,83 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#ifndef SRSRAN_INTRA_MEASURE_LTE_H
|
||||
#define SRSRAN_INTRA_MEASURE_LTE_H
|
||||
|
||||
#include "intra_measure_base.h"
|
||||
|
||||
namespace srsue {
|
||||
namespace scell {
|
||||
|
||||
/**
|
||||
* @brief Describes a class for performing LTE intra-frequency cell search and measurement
|
||||
*/
|
||||
class intra_measure_lte : public intra_measure_base
|
||||
{
|
||||
public:
|
||||
/**
|
||||
* @brief Constructor
|
||||
* @param logger Logging object
|
||||
* @param new_meas_itf_ Interface to report measurement to higher layers
|
||||
*/
|
||||
intra_measure_lte(srslog::basic_logger& logger, meas_itf& new_meas_itf_);
|
||||
|
||||
/**
|
||||
* @brief Destructor
|
||||
*/
|
||||
~intra_measure_lte() override;
|
||||
|
||||
/**
|
||||
* @brief Initialises LTE specific measurement objects
|
||||
* @param args Configuration arguments
|
||||
*/
|
||||
void init(uint32_t cc_idx, const args_t& args);
|
||||
|
||||
/**
|
||||
* @brief Sets the primary cell and selects LTE operation mode, configures the cell bandwidth and sampling rate
|
||||
* @param earfcn Frequency the component is receiving base-band from. Used only for reporting the EARFCN to the RRC
|
||||
* @param cell Actual cell configuration
|
||||
*/
|
||||
void set_primary_cell(uint32_t earfcn, srsran_cell_t cell);
|
||||
|
||||
/**
|
||||
* @brief Get EARFCN of this component
|
||||
* @return EARFCN
|
||||
*/
|
||||
uint32_t get_earfcn() const override { return current_earfcn; };
|
||||
|
||||
private:
|
||||
/**
|
||||
* @brief Provides with the RAT to the base class
|
||||
* @return The RAT measured by this class which is LTE
|
||||
*/
|
||||
srsran::srsran_rat_t get_rat() const override { return srsran::srsran_rat_t::lte; }
|
||||
|
||||
/**
|
||||
* @brief LTE specific measurement process
|
||||
* @param context Measurement context
|
||||
* @param buffer Provides the baseband buffer to perform the measurements
|
||||
*/
|
||||
void measure_rat(const measure_context_t& context, std::vector<cf_t>& buffer) override;
|
||||
|
||||
srslog::basic_logger& logger;
|
||||
srsran_cell_t serving_cell = {}; ///< Current serving cell in the EARFCN, to avoid reporting it
|
||||
uint32_t current_earfcn; ///< Current EARFCN
|
||||
|
||||
/// LTE-based measuring objects
|
||||
scell_recv scell_rx; ///< Secondary cell searcher
|
||||
srsran_refsignal_dl_sync_t refsignal_dl_sync = {}; ///< Reference signal based measurement
|
||||
};
|
||||
|
||||
} // namespace scell
|
||||
} // namespace srsue
|
||||
|
||||
#endif // SRSRAN_INTRA_MEASURE_LTE_H
|
|
@ -20,7 +20,7 @@
|
|||
|
||||
#include "phy_common.h"
|
||||
#include "prach.h"
|
||||
#include "scell/intra_measure.h"
|
||||
#include "scell/intra_measure_lte.h"
|
||||
#include "scell/scell_sync.h"
|
||||
#include "search.h"
|
||||
#include "sfn_sync.h"
|
||||
|
@ -42,7 +42,7 @@ class sync : public srsran::thread,
|
|||
public rsrp_insync_itf,
|
||||
public search_callback,
|
||||
public scell::sync_callback,
|
||||
public scell::intra_measure::meas_itf
|
||||
public scell::intra_measure_base::meas_itf
|
||||
{
|
||||
public:
|
||||
sync(srslog::basic_logger& phy_logger, srslog::basic_logger& phy_lib_logger) :
|
||||
|
@ -196,9 +196,9 @@ private:
|
|||
bool forced_rx_time_init = true; // Rx time sync after first receive from radio
|
||||
|
||||
// Objects for internal use
|
||||
search search_p;
|
||||
sfn_sync sfn_p;
|
||||
std::vector<std::unique_ptr<scell::intra_measure> > intra_freq_meas;
|
||||
search search_p;
|
||||
sfn_sync sfn_p;
|
||||
std::vector<std::unique_ptr<scell::intra_measure_lte> > intra_freq_meas;
|
||||
|
||||
// Pointers to other classes
|
||||
stack_interface_phy_lte* stack = nullptr;
|
||||
|
|
|
@ -1,248 +0,0 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#include "srsue/hdr/phy/scell/intra_measure.h"
|
||||
|
||||
#define Error(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.error(fmt, ##__VA_ARGS__)
|
||||
#define Warning(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.warning(fmt, ##__VA_ARGS__)
|
||||
#define Info(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.info(fmt, ##__VA_ARGS__)
|
||||
#define Debug(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.debug(fmt, ##__VA_ARGS__)
|
||||
|
||||
namespace srsue {
|
||||
namespace scell {
|
||||
|
||||
intra_measure::intra_measure(srslog::basic_logger& logger) : scell(logger), logger(logger), thread("SYNC_INTRA_MEASURE")
|
||||
{}
|
||||
|
||||
intra_measure::~intra_measure()
|
||||
{
|
||||
srsran_ringbuffer_free(&ring_buffer);
|
||||
scell.deinit();
|
||||
free(search_buffer);
|
||||
}
|
||||
|
||||
void intra_measure::init(uint32_t cc_idx_, phy_common* common, meas_itf* new_cell_itf_)
|
||||
{
|
||||
cc_idx = cc_idx_;
|
||||
new_cell_itf = new_cell_itf_;
|
||||
|
||||
if (common) {
|
||||
intra_freq_meas_len_ms = common->args->intra_freq_meas_len_ms;
|
||||
intra_freq_meas_period_ms = common->args->intra_freq_meas_period_ms;
|
||||
rx_gain_offset_db = common->args->rx_gain_offset;
|
||||
}
|
||||
|
||||
// Initialise Reference signal measurement
|
||||
srsran_refsignal_dl_sync_init(&refsignal_dl_sync);
|
||||
|
||||
// Start scell
|
||||
scell.init(intra_freq_meas_len_ms);
|
||||
|
||||
search_buffer = srsran_vec_cf_malloc(intra_freq_meas_len_ms * SRSRAN_SF_LEN_PRB(SRSRAN_MAX_PRB));
|
||||
|
||||
// Initialise buffer for the maximum number of PRB
|
||||
uint32_t max_required_bytes = (uint32_t)sizeof(cf_t) * intra_freq_meas_len_ms * SRSRAN_SF_LEN_PRB(SRSRAN_MAX_PRB);
|
||||
if (srsran_ringbuffer_init(&ring_buffer, max_required_bytes)) {
|
||||
return;
|
||||
}
|
||||
|
||||
state.set_state(internal_state::idle);
|
||||
start(INTRA_FREQ_MEAS_PRIO);
|
||||
}
|
||||
|
||||
void intra_measure::stop()
|
||||
{
|
||||
// Notify quit to asynchronous thread. If it is measuring, it will first finish the measure, report to stack and
|
||||
// then it will finish
|
||||
state.set_state(internal_state::quit);
|
||||
|
||||
// Wait for the asynchronous thread to finish
|
||||
wait_thread_finish();
|
||||
|
||||
srsran_ringbuffer_stop(&ring_buffer);
|
||||
srsran_refsignal_dl_sync_free(&refsignal_dl_sync);
|
||||
}
|
||||
|
||||
void intra_measure::set_primary_cell(uint32_t earfcn, srsran_cell_t cell)
|
||||
{
|
||||
current_earfcn = earfcn;
|
||||
current_sflen = (uint32_t)SRSRAN_SF_LEN_PRB(cell.nof_prb);
|
||||
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()
|
||||
{
|
||||
// Transition state to idle
|
||||
// Ring-buffer shall not be reset, it will automatically be reset as soon as the FSM transitions to receive
|
||||
state.set_state(internal_state::idle);
|
||||
Info("INTRA: Disabled neighbour cell search for EARFCN %d", get_earfcn());
|
||||
}
|
||||
|
||||
void intra_measure::set_cells_to_meas(const std::set<uint32_t>& pci)
|
||||
{
|
||||
active_pci_mutex.lock();
|
||||
active_pci = pci;
|
||||
active_pci_mutex.unlock();
|
||||
state.set_state(internal_state::receive);
|
||||
logger.info("INTRA: Received list of %zd neighbour cells to measure in EARFCN %d.", pci.size(), current_earfcn);
|
||||
}
|
||||
|
||||
void intra_measure::write(uint32_t tti, cf_t* data, uint32_t nsamples)
|
||||
{
|
||||
int nbytes = (int)(nsamples * sizeof(cf_t));
|
||||
int required_nbytes = (int)(intra_freq_meas_len_ms * current_sflen * sizeof(cf_t));
|
||||
uint32_t elapsed_tti = TTI_SUB(tti, last_measure_tti);
|
||||
|
||||
switch (state.get_state()) {
|
||||
|
||||
case internal_state::idle:
|
||||
case internal_state::measure:
|
||||
case internal_state::quit:
|
||||
// Do nothing
|
||||
break;
|
||||
case internal_state::wait:
|
||||
if (elapsed_tti >= intra_freq_meas_period_ms) {
|
||||
state.set_state(internal_state::receive);
|
||||
last_measure_tti = tti;
|
||||
srsran_ringbuffer_reset(&ring_buffer);
|
||||
}
|
||||
break;
|
||||
case internal_state::receive:
|
||||
// As nbytes might not match the sub-frame size, make sure that buffer does not overflow
|
||||
nbytes = SRSRAN_MIN(srsran_ringbuffer_space(&ring_buffer), nbytes);
|
||||
|
||||
// Try writing in the buffer
|
||||
if (srsran_ringbuffer_write(&ring_buffer, data, nbytes) < nbytes) {
|
||||
Warning("INTRA: Error writing to ringbuffer (EARFCN=%d)", current_earfcn);
|
||||
|
||||
// Transition to wait, so it can keep receiving without stopping the component operation
|
||||
state.set_state(internal_state::wait);
|
||||
} else {
|
||||
// As soon as there are enough samples in the buffer, transition to measure
|
||||
if (srsran_ringbuffer_status(&ring_buffer) >= required_nbytes) {
|
||||
state.set_state(internal_state::measure);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void intra_measure::measure_proc()
|
||||
{
|
||||
std::set<uint32_t> cells_to_measure = {};
|
||||
|
||||
// Load cell list to measure
|
||||
active_pci_mutex.lock();
|
||||
cells_to_measure = active_pci;
|
||||
active_pci_mutex.unlock();
|
||||
|
||||
// Read data from buffer and find cells in it
|
||||
srsran_ringbuffer_read(&ring_buffer, search_buffer, (int)intra_freq_meas_len_ms * current_sflen * sizeof(cf_t));
|
||||
|
||||
// Go to receive before finishing, so new samples can be enqueued before the thread finishes
|
||||
if (state.get_state() == internal_state::measure) {
|
||||
// Prevents transition to wait if state has changed while reading the ring-buffer
|
||||
state.set_state(internal_state::wait);
|
||||
}
|
||||
|
||||
// Detect new cells using PSS/SSS
|
||||
std::set<uint32_t> detected_cells = scell.find_cells(search_buffer, serving_cell, intra_freq_meas_len_ms);
|
||||
|
||||
// Add detected cells to the list of cells to measure
|
||||
for (const uint32_t& c : detected_cells) {
|
||||
cells_to_measure.insert(c);
|
||||
}
|
||||
|
||||
// Initialise empty neighbour cell list
|
||||
std::vector<phy_meas_t> neighbour_cells = {};
|
||||
|
||||
new_cell_itf->cell_meas_reset(cc_idx);
|
||||
|
||||
// Use Cell Reference signal to measure cells in the time domain for all known active PCI
|
||||
for (const uint32_t& id : cells_to_measure) {
|
||||
// Do not measure serving cell here since it's measured by workers
|
||||
if (id == serving_cell.id) {
|
||||
continue;
|
||||
}
|
||||
srsran_cell_t cell = serving_cell;
|
||||
cell.id = id;
|
||||
|
||||
srsran_refsignal_dl_sync_set_cell(&refsignal_dl_sync, cell);
|
||||
srsran_refsignal_dl_sync_run(&refsignal_dl_sync, search_buffer, intra_freq_meas_len_ms * current_sflen);
|
||||
|
||||
if (refsignal_dl_sync.found) {
|
||||
phy_meas_t m = {};
|
||||
m.pci = cell.id;
|
||||
m.earfcn = current_earfcn;
|
||||
m.rsrp = refsignal_dl_sync.rsrp_dBfs - rx_gain_offset_db;
|
||||
m.rsrq = refsignal_dl_sync.rsrq_dB;
|
||||
m.cfo_hz = refsignal_dl_sync.cfo_Hz;
|
||||
neighbour_cells.push_back(m);
|
||||
|
||||
Info("INTRA: Found neighbour cell: EARFCN=%d, PCI=%03d, RSRP=%5.1f dBm, RSRQ=%5.1f, peak_idx=%5d, "
|
||||
"CFO=%+.1fHz",
|
||||
m.earfcn,
|
||||
m.pci,
|
||||
m.rsrp,
|
||||
m.rsrq,
|
||||
refsignal_dl_sync.peak_index,
|
||||
refsignal_dl_sync.cfo_Hz);
|
||||
}
|
||||
}
|
||||
|
||||
// Send measurements to RRC if any cell found
|
||||
if (not neighbour_cells.empty()) {
|
||||
new_cell_itf->new_cell_meas(cc_idx, neighbour_cells);
|
||||
}
|
||||
}
|
||||
|
||||
void intra_measure::run_thread()
|
||||
{
|
||||
bool quit = false;
|
||||
|
||||
do {
|
||||
// Get state
|
||||
internal_state::state_t s = state.get_state();
|
||||
switch (s) {
|
||||
|
||||
case internal_state::idle:
|
||||
case internal_state::wait:
|
||||
case internal_state::receive:
|
||||
// Wait for a different state
|
||||
state.wait_change(s);
|
||||
break;
|
||||
case internal_state::measure:
|
||||
// Run the measurement process
|
||||
measure_proc();
|
||||
break;
|
||||
case internal_state::quit:
|
||||
// Quit loop
|
||||
quit = true;
|
||||
break;
|
||||
}
|
||||
} while (not quit);
|
||||
}
|
||||
|
||||
} // namespace scell
|
||||
} // namespace srsue
|
|
@ -0,0 +1,188 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#include "srsue/hdr/phy/scell/intra_measure_base.h"
|
||||
|
||||
#define Error(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.error("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
#define Warning(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.warning("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
#define Info(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.info("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
#define Debug(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.debug("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
|
||||
namespace srsue {
|
||||
namespace scell {
|
||||
|
||||
intra_measure_base::intra_measure_base(srslog::basic_logger& logger, meas_itf& new_cell_itf_) :
|
||||
logger(logger), context(new_cell_itf_), thread("SYNC_INTRA_MEASURE")
|
||||
{}
|
||||
|
||||
intra_measure_base::~intra_measure_base()
|
||||
{
|
||||
srsran_ringbuffer_free(&ring_buffer);
|
||||
}
|
||||
|
||||
void intra_measure_base::init_generic(uint32_t cc_idx_, const args_t& args)
|
||||
{
|
||||
context.cc_idx = cc_idx_;
|
||||
|
||||
context.meas_len_ms = args.len_ms;
|
||||
context.meas_period_ms = args.period_ms;
|
||||
context.rx_gain_offset_db = args.rx_gain_offset_db;
|
||||
|
||||
context.sf_len = SRSRAN_SF_LEN_PRB(SRSRAN_MAX_PRB);
|
||||
if (isnormal(args.srate_hz)) {
|
||||
context.sf_len = (uint32_t)round(args.srate_hz / 1000.0);
|
||||
}
|
||||
|
||||
// Calculate the new required bytes
|
||||
int max_required_bytes = (int)(sizeof(cf_t) * context.meas_len_ms * context.sf_len);
|
||||
|
||||
// Reallocate only if the required capacity exceds the new requirement
|
||||
if (ring_buffer.capacity < max_required_bytes) {
|
||||
search_buffer.resize(context.meas_len_ms * context.sf_len);
|
||||
|
||||
srsran_ringbuffer_free(&ring_buffer);
|
||||
|
||||
// Initialise buffer for the maximum number of PRB
|
||||
if (srsran_ringbuffer_init(&ring_buffer, max_required_bytes) < SRSRAN_SUCCESS) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
state.set_state(internal_state::idle);
|
||||
start(INTRA_FREQ_MEAS_PRIO);
|
||||
}
|
||||
|
||||
void intra_measure_base::stop()
|
||||
{
|
||||
// Notify quit to asynchronous thread. If it is measuring, it will first finish the measure, report to stack and
|
||||
// then it will finish
|
||||
state.set_state(internal_state::quit);
|
||||
|
||||
// Wait for the asynchronous thread to finish
|
||||
wait_thread_finish();
|
||||
|
||||
srsran_ringbuffer_stop(&ring_buffer);
|
||||
}
|
||||
|
||||
void intra_measure_base::set_rx_gain_offset(float rx_gain_offset_db_)
|
||||
{
|
||||
context.rx_gain_offset_db = rx_gain_offset_db_;
|
||||
}
|
||||
|
||||
void intra_measure_base::meas_stop()
|
||||
{
|
||||
// Transition state to idle
|
||||
// Ring-buffer shall not be reset, it will automatically be reset as soon as the FSM transitions to receive
|
||||
state.set_state(internal_state::idle);
|
||||
Info("Disabled neighbour cell search for EARFCN %d", get_earfcn());
|
||||
}
|
||||
|
||||
void intra_measure_base::set_cells_to_meas(const std::set<uint32_t>& pci)
|
||||
{
|
||||
active_pci_mutex.lock();
|
||||
context.active_pci = pci;
|
||||
active_pci_mutex.unlock();
|
||||
state.set_state(internal_state::receive);
|
||||
Info("Received list of %zd neighbour cells to measure in EARFCN %d.", pci.size(), get_earfcn());
|
||||
}
|
||||
|
||||
void intra_measure_base::write(uint32_t tti, cf_t* data, uint32_t nsamples)
|
||||
{
|
||||
int nbytes = (int)(nsamples * sizeof(cf_t));
|
||||
int required_nbytes = (int)(context.meas_len_ms * context.sf_len * sizeof(cf_t));
|
||||
uint32_t elapsed_tti = TTI_SUB(tti, last_measure_tti);
|
||||
|
||||
switch (state.get_state()) {
|
||||
case internal_state::idle:
|
||||
case internal_state::measure:
|
||||
case internal_state::quit:
|
||||
// Do nothing
|
||||
break;
|
||||
case internal_state::wait:
|
||||
if (elapsed_tti >= context.meas_period_ms) {
|
||||
state.set_state(internal_state::receive);
|
||||
last_measure_tti = tti;
|
||||
srsran_ringbuffer_reset(&ring_buffer);
|
||||
}
|
||||
break;
|
||||
case internal_state::receive:
|
||||
// As nbytes might not match the sub-frame size, make sure that buffer does not overflow
|
||||
nbytes = SRSRAN_MIN(srsran_ringbuffer_space(&ring_buffer), nbytes);
|
||||
|
||||
// Try writing in the buffer
|
||||
if (srsran_ringbuffer_write(&ring_buffer, data, nbytes) < nbytes) {
|
||||
Warning("Error writing to ringbuffer (EARFCN=%d)", get_earfcn());
|
||||
|
||||
// Transition to wait, so it can keep receiving without stopping the component operation
|
||||
state.set_state(internal_state::wait);
|
||||
} else {
|
||||
// As soon as there are enough samples in the buffer, transition to measure
|
||||
if (srsran_ringbuffer_status(&ring_buffer) >= required_nbytes) {
|
||||
state.set_state(internal_state::measure);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
void intra_measure_base::measure_proc()
|
||||
{
|
||||
std::set<uint32_t> cells_to_measure = {};
|
||||
|
||||
// Read data from buffer and find cells in it
|
||||
srsran_ringbuffer_read(&ring_buffer, search_buffer.data(), (int)context.meas_len_ms * context.sf_len * sizeof(cf_t));
|
||||
|
||||
// Go to receive before finishing, so new samples can be enqueued before the thread finishes
|
||||
if (state.get_state() == internal_state::measure) {
|
||||
// Prevents transition to wait if state has changed while reading the ring-buffer
|
||||
state.set_state(internal_state::wait);
|
||||
}
|
||||
|
||||
// Perform measurements for the actual RAT
|
||||
measure_rat(context, search_buffer);
|
||||
}
|
||||
|
||||
void intra_measure_base::run_thread()
|
||||
{
|
||||
bool quit = false;
|
||||
|
||||
do {
|
||||
// Get state
|
||||
internal_state::state_t s = state.get_state();
|
||||
switch (s) {
|
||||
case internal_state::idle:
|
||||
case internal_state::wait:
|
||||
case internal_state::receive:
|
||||
// Wait for a different state
|
||||
state.wait_change(s);
|
||||
break;
|
||||
case internal_state::measure:
|
||||
// Run the measurement process
|
||||
measure_proc();
|
||||
break;
|
||||
case internal_state::quit:
|
||||
// Quit loop
|
||||
quit = true;
|
||||
break;
|
||||
}
|
||||
} while (not quit);
|
||||
}
|
||||
|
||||
} // namespace scell
|
||||
} // namespace srsue
|
|
@ -0,0 +1,115 @@
|
|||
/**
|
||||
*
|
||||
* \section COPYRIGHT
|
||||
*
|
||||
* Copyright 2013-2021 Software Radio Systems Limited
|
||||
*
|
||||
* By using this file, you agree to the terms and conditions set
|
||||
* forth in the LICENSE file which can be found at the top level of
|
||||
* the distribution.
|
||||
*
|
||||
*/
|
||||
#include "srsue/hdr/phy/scell/intra_measure_lte.h"
|
||||
|
||||
namespace srsue {
|
||||
namespace scell {
|
||||
|
||||
#define Error(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.error("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
#define Warning(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.warning("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
#define Info(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.info("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
#define Debug(fmt, ...) \
|
||||
if (SRSRAN_DEBUG_ENABLED) \
|
||||
logger.debug("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__)
|
||||
|
||||
intra_measure_lte::intra_measure_lte(srslog::basic_logger& logger_, meas_itf& new_cell_itf_) :
|
||||
logger(logger_), scell_rx(logger_), intra_measure_base(logger_, new_cell_itf_)
|
||||
{}
|
||||
|
||||
intra_measure_lte::~intra_measure_lte()
|
||||
{
|
||||
scell_rx.deinit();
|
||||
srsran_refsignal_dl_sync_free(&refsignal_dl_sync);
|
||||
}
|
||||
|
||||
void intra_measure_lte::init(uint32_t cc_idx, const args_t& args)
|
||||
{
|
||||
init_generic(cc_idx, args);
|
||||
|
||||
// Initialise Reference signal measurement
|
||||
srsran_refsignal_dl_sync_init(&refsignal_dl_sync);
|
||||
|
||||
// Start scell
|
||||
scell_rx.init(args.len_ms);
|
||||
}
|
||||
|
||||
void intra_measure_lte::set_primary_cell(uint32_t earfcn, srsran_cell_t cell)
|
||||
{
|
||||
current_earfcn = earfcn;
|
||||
serving_cell = cell;
|
||||
set_current_sf_len((uint32_t)SRSRAN_SF_LEN_PRB(cell.nof_prb));
|
||||
}
|
||||
|
||||
void intra_measure_lte::measure_rat(const measure_context_t& context, std::vector<cf_t>& buffer)
|
||||
{
|
||||
std::set<uint32_t> cells_to_measure = context.active_pci;
|
||||
|
||||
// Detect new cells using PSS/SSS
|
||||
std::set<uint32_t> detected_cells = scell_rx.find_cells(buffer.data(), serving_cell, context.meas_len_ms);
|
||||
|
||||
// Add detected cells to the list of cells to measure
|
||||
for (const uint32_t& c : detected_cells) {
|
||||
cells_to_measure.insert(c);
|
||||
}
|
||||
|
||||
// Initialise empty neighbour cell list
|
||||
std::vector<phy_meas_t> neighbour_cells = {};
|
||||
|
||||
context.new_cell_itf.cell_meas_reset(context.cc_idx);
|
||||
|
||||
// Use Cell Reference signal to measure cells in the time domain for all known active PCI
|
||||
for (const uint32_t& id : cells_to_measure) {
|
||||
// Do not measure serving cell here since it's measured by workers
|
||||
if (id == serving_cell.id) {
|
||||
continue;
|
||||
}
|
||||
srsran_cell_t cell = serving_cell;
|
||||
cell.id = id;
|
||||
|
||||
srsran_refsignal_dl_sync_set_cell(&refsignal_dl_sync, cell);
|
||||
srsran_refsignal_dl_sync_run(&refsignal_dl_sync, buffer.data(), context.meas_len_ms * context.sf_len);
|
||||
|
||||
if (refsignal_dl_sync.found) {
|
||||
phy_meas_t m = {};
|
||||
m.rat = srsran::srsran_rat_t::lte;
|
||||
m.pci = cell.id;
|
||||
m.earfcn = current_earfcn;
|
||||
m.rsrp = refsignal_dl_sync.rsrp_dBfs - context.rx_gain_offset_db;
|
||||
m.rsrq = refsignal_dl_sync.rsrq_dB;
|
||||
m.cfo_hz = refsignal_dl_sync.cfo_Hz;
|
||||
neighbour_cells.push_back(m);
|
||||
|
||||
Info("Found neighbour cell: EARFCN=%d, PCI=%03d, RSRP=%5.1f dBm, RSRQ=%5.1f, peak_idx=%5d, "
|
||||
"CFO=%+.1fHz",
|
||||
m.earfcn,
|
||||
m.pci,
|
||||
m.rsrp,
|
||||
m.rsrq,
|
||||
refsignal_dl_sync.peak_index,
|
||||
refsignal_dl_sync.cfo_Hz);
|
||||
}
|
||||
}
|
||||
|
||||
// Send measurements to RRC if any cell found
|
||||
if (not neighbour_cells.empty()) {
|
||||
context.new_cell_itf.new_cell_meas(context.cc_idx, neighbour_cells);
|
||||
}
|
||||
}
|
||||
|
||||
} // namespace scell
|
||||
} // namespace srsue
|
|
@ -88,9 +88,13 @@ void sync::init(srsran::radio_interface_phy* _radio,
|
|||
|
||||
// Start intra-frequency measurement
|
||||
for (uint32_t i = 0; i < worker_com->args->nof_lte_carriers; i++) {
|
||||
scell::intra_measure* q = new scell::intra_measure(phy_logger);
|
||||
q->init(i, worker_com, this);
|
||||
intra_freq_meas.push_back(std::unique_ptr<scell::intra_measure>(q));
|
||||
scell::intra_measure_lte* q = new scell::intra_measure_lte(phy_logger, *this);
|
||||
scell::intra_measure_base::args_t args = {};
|
||||
args.len_ms = worker_com->args->intra_freq_meas_len_ms;
|
||||
args.period_ms = worker_com->args->intra_freq_meas_period_ms;
|
||||
args.rx_gain_offset_db = worker_com->args->rx_gain_offset;
|
||||
q->init(i, args);
|
||||
intra_freq_meas.push_back(std::unique_ptr<scell::intra_measure_lte>(q));
|
||||
}
|
||||
|
||||
// Allocate Secondary serving cell synchronization
|
||||
|
|
|
@ -12,7 +12,7 @@
|
|||
|
||||
#include "srsran/interfaces/phy_interface_types.h"
|
||||
#include "srsran/srslog/srslog.h"
|
||||
#include "srsue/hdr/phy/scell/intra_measure.h"
|
||||
#include "srsue/hdr/phy/scell/intra_measure_lte.h"
|
||||
#include <boost/program_options.hpp>
|
||||
#include <boost/program_options/parsers.hpp>
|
||||
#include <iostream>
|
||||
|
@ -212,7 +212,7 @@ public:
|
|||
}
|
||||
};
|
||||
|
||||
class meas_itf_listener : public srsue::scell::intra_measure::meas_itf
|
||||
class meas_itf_listener : public srsue::scell::intra_measure_base::meas_itf
|
||||
{
|
||||
public:
|
||||
typedef struct {
|
||||
|
@ -396,11 +396,10 @@ int main(int argc, char** argv)
|
|||
srslog::basic_logger& logger = srslog::fetch_basic_logger("intra_measure");
|
||||
srslog::init();
|
||||
|
||||
cf_t* baseband_buffer = srsran_vec_cf_malloc(SRSRAN_SF_LEN_MAX);
|
||||
srsran::rf_timestamp_t ts = {};
|
||||
srsue::scell::intra_measure intra_measure(logger);
|
||||
meas_itf_listener rrc;
|
||||
srsue::phy_common common(logger);
|
||||
cf_t* baseband_buffer = srsran_vec_cf_malloc(SRSRAN_SF_LEN_MAX);
|
||||
srsran::rf_timestamp_t ts = {};
|
||||
meas_itf_listener rrc;
|
||||
srsue::scell::intra_measure_lte intra_measure(logger, rrc);
|
||||
|
||||
// Simulation only
|
||||
std::vector<std::unique_ptr<test_enb> > test_enb_v;
|
||||
|
@ -411,7 +410,6 @@ int main(int argc, char** argv)
|
|||
std::unique_ptr<srsran::radio> radio = nullptr;
|
||||
|
||||
// Set Receiver args
|
||||
common.args = &phy_args;
|
||||
phy_args.estimator_fil_auto = false;
|
||||
phy_args.estimator_fil_order = 4;
|
||||
phy_args.estimator_fil_stddev = 1.0f;
|
||||
|
@ -469,7 +467,12 @@ int main(int argc, char** argv)
|
|||
|
||||
logger.set_level(srslog::str_to_basic_level(intra_meas_log_level));
|
||||
|
||||
intra_measure.init(0, &common, &rrc);
|
||||
srsue::scell::intra_measure_base::args_t args = {};
|
||||
args.len_ms = phy_args.intra_freq_meas_len_ms;
|
||||
args.period_ms = phy_args.intra_freq_meas_period_ms;
|
||||
args.rx_gain_offset_db = phy_args.rx_gain_offset;
|
||||
|
||||
intra_measure.init(0, args);
|
||||
intra_measure.set_primary_cell(SRSRAN_MAX(earfcn_dl, 0), cell_base);
|
||||
|
||||
if (earfcn_dl >= 0) {
|
||||
|
|
|
@ -674,18 +674,18 @@ int meas_obj_test()
|
|||
|
||||
rrc_meas_logger.info("Test7: PHY finds new neighbours in frequency 1 and 2, check RRC instructs to search them");
|
||||
std::vector<phy_meas_t> phy_meas = {};
|
||||
phy_meas.push_back({0, 0, 0.0f, 1, 31});
|
||||
phy_meas.push_back({-1, 0, 0.0f, 1, 32});
|
||||
phy_meas.push_back({-2, 0, 0.0f, 1, 33});
|
||||
phy_meas.push_back({-3, 0, 0.0f, 1, 34});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, 0, 0, 0.0f, 1, 31});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, -1, 0, 0.0f, 1, 32});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, -2, 0, 0.0f, 1, 33});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, -3, 0, 0.0f, 1, 34});
|
||||
rrctest.new_cell_meas(phy_meas);
|
||||
rrctest.run_tti(1);
|
||||
phy_meas = {};
|
||||
phy_meas.push_back({-4, 0, 0.0f, 1, 35});
|
||||
phy_meas.push_back({-5, 0, 0.0f, 1, 36});
|
||||
phy_meas.push_back({-6, 0, 0.0f, 1, 37});
|
||||
phy_meas.push_back({1, 0, 0.0f, 1, 30});
|
||||
phy_meas.push_back({0, 0, 0.0f, 2, 31});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, -4, 0, 0.0f, 1, 35});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, -5, 0, 0.0f, 1, 36});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, -6, 0, 0.0f, 1, 37});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, 1, 0, 0.0f, 1, 30});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, 0, 0, 0.0f, 2, 31});
|
||||
rrctest.new_cell_meas(phy_meas);
|
||||
rrctest.run_tti(1);
|
||||
|
||||
|
@ -806,7 +806,7 @@ void send_report(rrc_test& rrctest,
|
|||
if (earfcn.size() == pci.size()) {
|
||||
e = earfcn[i];
|
||||
}
|
||||
phy_meas.push_back({r, -5, 0.0f, e, pci[i]});
|
||||
phy_meas.push_back({srsran::srsran_rat_t::lte, r, -5, 0.0f, e, pci[i]});
|
||||
}
|
||||
rrctest.new_cell_meas(phy_meas);
|
||||
rrctest.run_tti(1);
|
||||
|
|
Loading…
Reference in New Issue