srsLTE/srsue/src/phy/scell/intra_measure_nr.cc

122 lines
3.9 KiB
C++
Raw Normal View History

/**
*
* \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_nr.h"
#define Log(level, fmt, ...) \
do { \
logger.level("INTRA-%s: " fmt, to_string(get_rat()).c_str(), ##__VA_ARGS__); \
} while (false)
namespace srsue {
namespace scell {
intra_measure_nr::intra_measure_nr(srslog::basic_logger& logger_, meas_itf& new_meas_itf_) :
logger(logger_), intra_measure_base(logger_, new_meas_itf_)
{}
intra_measure_nr::~intra_measure_nr()
{
srsran_ssb_free(&ssb);
}
bool intra_measure_nr::init(uint32_t cc_idx_, const args_t& args)
{
cc_idx = cc_idx_;
thr_snr_db = args.thr_snr_db;
// Initialise generic side
intra_measure_base::args_t base_args = {};
base_args.srate_hz = args.max_srate_hz;
base_args.len_ms = args.max_len_ms;
base_args.period_ms = 20; // Hard-coded, it does not make a difference at this stage
base_args.rx_gain_offset_db = args.rx_gain_offset_dB;
init_generic(cc_idx, base_args);
// Initialise SSB
srsran_ssb_args_t ssb_args = {};
ssb_args.max_srate_hz = args.max_srate_hz;
ssb_args.min_scs = args.min_scs;
ssb_args.enable_search = true;
if (srsran_ssb_init(&ssb, &ssb_args) < SRSRAN_SUCCESS) {
Log(error, "Error initiating SSB");
return false;
}
return true;
}
bool intra_measure_nr::set_config(uint32_t arfcn, const config_t& cfg)
{
// Update ARFCN
current_arfcn = arfcn;
serving_cell_pci = cfg.serving_cell_pci;
// Configure generic side
intra_measure_base::args_t base_cfg = {};
base_cfg.srate_hz = cfg.srate_hz;
base_cfg.len_ms = cfg.len_ms;
base_cfg.period_ms = cfg.periodicity_ms;
base_cfg.rx_gain_offset_db = cfg.rx_gain_offset_db;
init_generic(cc_idx, base_cfg);
// Configure SSB
srsran_ssb_cfg_t ssb_cfg = {};
ssb_cfg.srate_hz = cfg.srate_hz;
ssb_cfg.center_freq_hz = cfg.center_freq_hz;
ssb_cfg.ssb_freq_hz = cfg.ssb_freq_hz;
ssb_cfg.scs = cfg.scs;
if (srsran_ssb_set_cfg(&ssb, &ssb_cfg) < SRSRAN_SUCCESS) {
Log(error, "Error configuring SSB");
return false;
}
return true;
}
void intra_measure_nr::measure_rat(const measure_context_t& context, std::vector<cf_t>& buffer)
{
// Search and measure the best cell
srsran_csi_trs_measurements_t meas = {};
uint32_t N_id = 0;
if (srsran_ssb_csi_search(&ssb, buffer.data(), context.sf_len * context.meas_len_ms, &N_id, &meas) < SRSRAN_SUCCESS) {
Log(error, "Error searching for SSB");
}
// Early return if the found PCI matches with the serving cell ID
if (serving_cell_pci == (int)N_id) {
return;
}
// Check threshold
if (meas.snr_dB >= thr_snr_db) {
// Log finding
if (logger.info.enabled()) {
std::array<char, 512> str_info = {};
srsran_csi_rs_measure_info(&meas, str_info.data(), (uint32_t)str_info.size());
Log(info, "Found neighbour cell: ARFCN=%d PCI=%03d %s", get_earfcn(), N_id, str_info.data());
}
// Prepare found measurements
std::vector<phy_meas_t> meas_list(1);
meas_list[0].rat = get_rat();
meas_list[0].rsrp = meas.rsrp_dB + context.rx_gain_offset_db;
meas_list[0].cfo_hz = meas.cfo_hz;
meas_list[0].earfcn = get_earfcn();
meas_list[0].pci = N_id;
// Push measurements to higher layers
context.new_cell_itf.new_cell_meas(cc_idx, meas_list);
}
}
} // namespace scell
} // namespace srsue