SRSUE: Default PHY measurements to NAN

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent 4bfe092a24
commit fc5d069743

@ -168,6 +168,12 @@ public:
*/ */
uint32_t get_ul_earfcn(uint32_t dl_earfcn); uint32_t get_ul_earfcn(uint32_t dl_earfcn);
/**
* @brief Resets measurements from a given CC
* @param cc_idx CC index
*/
void reset_measurements(uint32_t cc_idx);
void update_measurements(uint32_t cc_idx, void update_measurements(uint32_t cc_idx,
const srsran_chest_dl_res_t& chest_res, const srsran_chest_dl_res_t& chest_res,
srsran_dl_sf_cfg_t sf_cfg_dl, srsran_dl_sf_cfg_t sf_cfg_dl,
@ -218,32 +224,26 @@ public:
} }
} }
} }
void reset_neighbour_cells()
{
for (uint32_t i = 0; i < SRSRAN_MAX_CARRIERS; i++) {
avg_rsrp_neigh[i] = NAN;
}
}
private: private:
std::mutex meas_mutex; std::mutex meas_mutex;
float pathloss[SRSRAN_MAX_CARRIERS] = {}; float cur_pathloss = 0.0f;
float cur_pathloss = 0.0f; float cur_pusch_power = 0.0f;
float cur_pusch_power = 0.0f; float rx_gain_offset = 0.0f;
float avg_rsrp[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> pathloss = {};
float avg_rsrp_dbm[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_rsrp = {};
float avg_rsrq_db[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_rsrp_dbm = {};
float avg_rssi_dbm[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_rsrq_db = {};
float avg_cfo_hz[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_rssi_dbm = {};
float rx_gain_offset = 0.0f; std::array<float, SRSRAN_MAX_CARRIERS> avg_cfo_hz = {};
float avg_sinr_db[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_sinr_db = {};
float avg_snr_db[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_snr_db = {};
float avg_noise[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_noise = {};
float avg_rsrp_neigh[SRSRAN_MAX_CARRIERS] = {}; std::array<float, SRSRAN_MAX_CARRIERS> avg_rsrp_neigh = {};
uint32_t pcell_report_period = 0; static constexpr uint32_t pcell_report_period = 20;
uint32_t rssi_read_cnt = 0; uint32_t rssi_read_cnt = 0;
rsrp_insync_itf* insync_itf = nullptr; rsrp_insync_itf* insync_itf = nullptr;

@ -549,6 +549,11 @@ void cc_worker::decode_phich()
void cc_worker::update_measurements(std::vector<phy_meas_t>& serving_cells, cf_t* rssi_power_buffer) void cc_worker::update_measurements(std::vector<phy_meas_t>& serving_cells, cf_t* rssi_power_buffer)
{ {
// Do not update any measurement if the CC is not configured to prevent false or inaccurate data
if (not phy->cell_state.is_configured(cc_idx)) {
return;
}
phy->update_measurements( phy->update_measurements(
cc_idx, ue_dl.chest_res, sf_cfg_dl, ue_dl_cfg.cfg.pdsch.rs_power, serving_cells, rssi_power_buffer); cc_idx, ue_dl.chest_res, sf_cfg_dl, ue_dl_cfg.cfg.pdsch.rs_power, serving_cells, rssi_power_buffer);
} }

@ -529,6 +529,10 @@ bool phy::set_scell(srsran_cell_t cell_info, uint32_t cc_idx, uint32_t earfcn)
} }
} }
// Reset measurements for the given CC after all workers finished processing and have been configured to ensure the
// measurements are not overwritten
common.reset_measurements(cc_idx);
// Change frequency only if the earfcn was modified // Change frequency only if the earfcn was modified
if (earfcn_is_different) { if (earfcn_is_different) {
double dl_freq = srsran_band_fd(earfcn) * 1e6; double dl_freq = srsran_band_fd(earfcn) * 1e6;

@ -611,8 +611,31 @@ void phy_common::update_cfo_measurement(uint32_t cc_idx, float cfo_hz)
{ {
std::unique_lock<std::mutex> lock(meas_mutex); std::unique_lock<std::mutex> lock(meas_mutex);
// use SNR EMA coefficient for averaging // Use SNR EMA coefficient for averaging
avg_cfo_hz[cc_idx] = SRSRAN_VEC_EMA(cfo_hz, avg_cfo_hz[cc_idx], args->snr_ema_coeff); avg_cfo_hz[cc_idx] = SRSRAN_VEC_SAFE_EMA(cfo_hz, avg_cfo_hz[cc_idx], args->snr_ema_coeff);
}
void phy_common::reset_measurements(uint32_t cc_idx)
{
// If the CC index exceeds the maximum number of carriers, reset them all
if (cc_idx >= SRSRAN_MAX_CARRIERS) {
for (uint32_t cc = 0; cc < SRSRAN_MAX_CARRIERS; cc++) {
reset_measurements(cc);
}
}
// Default all metrics to NAN to prevent providing invalid information on traces and other layers
std::unique_lock<std::mutex> lock(meas_mutex);
pathloss[cc_idx] = NAN;
avg_rsrp[cc_idx] = NAN;
avg_rsrp_dbm[cc_idx] = NAN;
avg_rsrq_db[cc_idx] = NAN;
avg_rssi_dbm[cc_idx] = NAN;
avg_cfo_hz[cc_idx] = NAN;
avg_sinr_db[cc_idx] = NAN;
avg_snr_db[cc_idx] = NAN;
avg_noise[cc_idx] = NAN;
avg_rsrp_neigh[cc_idx] = NAN;
} }
void phy_common::update_measurements(uint32_t cc_idx, void phy_common::update_measurements(uint32_t cc_idx,
@ -644,7 +667,7 @@ void phy_common::update_measurements(uint32_t cc_idx,
30) 30)
: 0; : 0;
if (std::isnormal(rssi_dbm)) { if (std::isnormal(rssi_dbm)) {
avg_rssi_dbm[0] = SRSRAN_VEC_EMA(rssi_dbm, avg_rssi_dbm[0], args->snr_ema_coeff); avg_rssi_dbm[0] = SRSRAN_VEC_SAFE_EMA(rssi_dbm, avg_rssi_dbm[0], args->snr_ema_coeff);
} }
rx_gain_offset = get_radio()->get_rx_gain() + args->rx_gain_offset; rx_gain_offset = get_radio()->get_rx_gain() + args->rx_gain_offset;
@ -658,21 +681,17 @@ void phy_common::update_measurements(uint32_t cc_idx,
// Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC // Average RSRQ over DEFAULT_MEAS_PERIOD_MS then sent to RRC
float rsrq_db = chest_res.rsrq_db; float rsrq_db = chest_res.rsrq_db;
if (std::isnormal(rsrq_db)) { if (std::isnormal(rsrq_db)) {
if (!(sf_cfg_dl.tti % pcell_report_period) || !std::isnormal(avg_rsrq_db[cc_idx])) { // Reset average RSRQ measurement
avg_rsrq_db[cc_idx] = rsrq_db; if (sf_cfg_dl.tti % pcell_report_period == 0) {
} else { avg_rsrq_db[cc_idx] = NAN;
avg_rsrq_db[cc_idx] = SRSRAN_VEC_CMA(rsrq_db, avg_rsrq_db[cc_idx], sf_cfg_dl.tti % pcell_report_period);
} }
avg_rsrq_db[cc_idx] = SRSRAN_VEC_SAFE_CMA(rsrq_db, avg_rsrq_db[cc_idx], sf_cfg_dl.tti % pcell_report_period);
} }
// Average RSRP taken from CRS // Average RSRP taken from CRS
float rsrp_lin = chest_res.rsrp; float rsrp_lin = chest_res.rsrp;
if (std::isnormal(rsrp_lin)) { if (std::isnormal(rsrp_lin)) {
if (!std::isnormal(avg_rsrp[cc_idx])) { avg_rsrp[cc_idx] = SRSRAN_VEC_SAFE_EMA(rsrp_lin, avg_rsrp[cc_idx], snr_ema_coeff);
avg_rsrp[cc_idx] = rsrp_lin;
} else {
avg_rsrp[cc_idx] = SRSRAN_VEC_EMA(rsrp_lin, avg_rsrp[cc_idx], snr_ema_coeff);
}
} }
/* Correct absolute power measurements by RX gain offset */ /* Correct absolute power measurements by RX gain offset */
@ -680,11 +699,11 @@ void phy_common::update_measurements(uint32_t cc_idx,
// Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC // Serving cell RSRP measurements are averaged over DEFAULT_MEAS_PERIOD_MS then sent to RRC
if (std::isnormal(rsrp_dbm)) { if (std::isnormal(rsrp_dbm)) {
if (!(sf_cfg_dl.tti % pcell_report_period) || !std::isnormal(avg_rsrp_dbm[cc_idx])) { // Reset average RSRP measurement
avg_rsrp_dbm[cc_idx] = rsrp_dbm; if (sf_cfg_dl.tti % pcell_report_period == 0) {
} else { avg_rsrp_dbm[cc_idx] = NAN;
avg_rsrp_dbm[cc_idx] = SRSRAN_VEC_CMA(rsrp_dbm, avg_rsrp_dbm[cc_idx], sf_cfg_dl.tti % pcell_report_period);
} }
avg_rsrp_dbm[cc_idx] = SRSRAN_VEC_SAFE_CMA(rsrp_dbm, avg_rsrp_dbm[cc_idx], sf_cfg_dl.tti % pcell_report_period);
} }
// Compute PL // Compute PL
@ -693,11 +712,7 @@ void phy_common::update_measurements(uint32_t cc_idx,
// Average noise // Average noise
float cur_noise = chest_res.noise_estimate; float cur_noise = chest_res.noise_estimate;
if (std::isnormal(cur_noise)) { if (std::isnormal(cur_noise)) {
if (!std::isnormal(avg_noise[cc_idx])) { avg_noise[cc_idx] = SRSRAN_VEC_SAFE_EMA(cur_noise, avg_noise[cc_idx], snr_ema_coeff);
avg_noise[cc_idx] = cur_noise;
} else {
avg_noise[cc_idx] = SRSRAN_VEC_EMA(cur_noise, avg_noise[cc_idx], snr_ema_coeff);
}
} }
// Calculate SINR using CRS from neighbours if are detected // Calculate SINR using CRS from neighbours if are detected
@ -714,20 +729,12 @@ void phy_common::update_measurements(uint32_t cc_idx,
// Average sinr in the log domain // Average sinr in the log domain
if (std::isnormal(sinr_db)) { if (std::isnormal(sinr_db)) {
if (!std::isnormal(avg_sinr_db[cc_idx])) { avg_sinr_db[cc_idx] = SRSRAN_VEC_SAFE_EMA(sinr_db, avg_sinr_db[cc_idx], snr_ema_coeff);
avg_sinr_db[cc_idx] = sinr_db;
} else {
avg_sinr_db[cc_idx] = SRSRAN_VEC_EMA(sinr_db, avg_sinr_db[cc_idx], snr_ema_coeff);
}
} }
// Average snr in the log domain // Average snr in the log domain
if (std::isnormal(chest_res.snr_db)) { if (std::isnormal(chest_res.snr_db)) {
if (!std::isnormal(avg_snr_db[cc_idx])) { avg_snr_db[cc_idx] = SRSRAN_VEC_SAFE_EMA(chest_res.snr_db, avg_snr_db[cc_idx], snr_ema_coeff);
avg_snr_db[cc_idx] = chest_res.snr_db;
} else {
avg_snr_db[cc_idx] = SRSRAN_VEC_EMA(chest_res.snr_db, avg_snr_db[cc_idx], snr_ema_coeff);
}
} }
// Store metrics // Store metrics
@ -742,9 +749,9 @@ void phy_common::update_measurements(uint32_t cc_idx,
set_ch_metrics(cc_idx, ch); set_ch_metrics(cc_idx, ch);
// Prepare measurements for serving cells // Prepare measurements for serving cells - skip if any measurement is invalid assuming pure zeros are not possible
bool active = cell_state.is_configured(cc_idx); if (std::isnormal(avg_rsrp_dbm[cc_idx]) and
if (active && ((sf_cfg_dl.tti % pcell_report_period) == pcell_report_period - 1)) { std::isnormal(avg_cfo_hz[cc_idx] and ((sf_cfg_dl.tti % pcell_report_period) == pcell_report_period - 1))) {
phy_meas_t meas = {}; phy_meas_t meas = {};
meas.rsrp = avg_rsrp_dbm[cc_idx]; meas.rsrp = avg_rsrp_dbm[cc_idx];
meas.rsrq = avg_rsrq_db[cc_idx]; meas.rsrq = avg_rsrq_db[cc_idx];
@ -866,25 +873,17 @@ void phy_common::reset()
{ {
reset_radio(); reset_radio();
sr_enabled = false; sr_enabled = false;
cur_pathloss = 0; cur_pathloss = 0;
cur_pusch_power = 0; cur_pusch_power = 0;
sr_last_tx_tti = -1; sr_last_tx_tti = -1;
pcell_report_period = 20; last_ri = 0;
last_ri = 0;
{ // Reset all measurements
std::unique_lock<std::mutex> lock(meas_mutex); reset_measurements(SRSRAN_MAX_CARRIERS);
ZERO_OBJECT(pathloss);
ZERO_OBJECT(avg_sinr_db);
ZERO_OBJECT(avg_snr_db);
ZERO_OBJECT(avg_rsrp);
ZERO_OBJECT(avg_rsrp_dbm);
ZERO_OBJECT(avg_rsrq_db);
}
cell_state.reset();
reset_neighbour_cells(); // Reset all SCell states
cell_state.reset();
// Note: Using memset to reset these members is forbidden because they are real objects, not plain arrays. // Note: Using memset to reset these members is forbidden because they are real objects, not plain arrays.
{ {

Loading…
Cancel
Save