srsgnb,metrics: add ul_pucch_ni metric and refactor rssi/epre nomenclature. Fix bug in rsrp_avg computation in pucch

This commit is contained in:
Ismael Gomez 2022-02-23 22:09:11 +01:00
parent cf647b1fd5
commit 2bbeef6068
11 changed files with 48 additions and 31 deletions

View File

@ -40,7 +40,7 @@ typedef struct SRSRAN_API {
cf_t* ce;
uint32_t nof_re;
float noise_estimate;
float noise_estimate_dbm;
float noise_estimate_dbFs;
float rsrp;
float rsrp_dBfs;
float epre;

View File

@ -75,7 +75,8 @@ typedef struct SRSRAN_API {
srsran_uci_value_t uci_data;
float dmrs_correlation;
float snr_db;
float rsrp_db;
float rssi_dbFs;
float ni_dbFs;
float correlation;
bool detected;

View File

@ -346,19 +346,30 @@ static void chest_ul_estimate(srsran_chest_ul_t* q,
}
}
// Estimate received pilot power
float signal_power = srsran_vec_avg_power_cf(q->pilot_recv_signal, nslots * nrefs_sym);
// Measure reference signal RE average power
cf_t corr = srsran_vec_acc_cc(q->pilot_recv_signal, nslots * nrefs_sym) / (nslots * nrefs_sym);
float rsrp_avg = __real__ corr * __real__ corr + __imag__ corr * __imag__ corr;
// Measure EPRE
float epre = srsran_vec_avg_power_cf(q->pilot_recv_signal, nslots * nrefs_sym);
// RSRP shall not be greater than EPRE
rsrp_avg = SRSRAN_MIN(rsrp_avg, epre);
// Calculate SNR
if (isnormal(res->noise_estimate)) {
res->snr = signal_power / res->noise_estimate;
res->snr = rsrp_avg / res->noise_estimate;
} else {
res->snr = NAN;
}
// Convert measurements in logarithm scale
res->rsrp = signal_power;
res->rsrp_dBfs = srsran_convert_power_to_dB(signal_power);
res->snr_db = srsran_convert_power_to_dB(res->snr);
res->noise_estimate_dbm = srsran_convert_power_to_dBm(res->noise_estimate);
// Set EPRE and RSRP
res->epre = epre;
res->epre_dBfs = srsran_convert_power_to_dB(res->epre);
res->rsrp = rsrp_avg;
res->rsrp_dBfs = srsran_convert_power_to_dB(res->rsrp);
res->snr_db = srsran_convert_power_to_dB(res->snr);
res->noise_estimate_dbFs = srsran_convert_power_to_dBm(res->noise_estimate);
}
int srsran_chest_ul_estimate_pusch(srsran_chest_ul_t* q,
@ -473,15 +484,12 @@ int srsran_chest_ul_estimate_pucch(srsran_chest_ul_t* q,
srsran_vec_prod_conj_ccc(q->pilot_recv_signal, q->pilot_known_signal, q->pilot_estimates, nrefs_sf);
}
// Measure power
float rsrp_avg = 0.0f;
for (int ns = 0; ns < SRSRAN_NOF_SLOTS_PER_SF; ns++) {
for (int i = 0; i < n_rs; i++) {
cf_t corr = srsran_vec_acc_cc(q->pilot_estimates, SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs) / (SRSRAN_NRE);
rsrp_avg += __real__ corr * __real__ corr + __imag__ corr * __imag__ corr;
}
}
rsrp_avg /= SRSRAN_NOF_SLOTS_PER_SF * n_rs;
// Measure reference signal RE average power
cf_t corr = srsran_vec_acc_cc(q->pilot_estimates, SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs) /
(SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs);
float rsrp_avg = __real__ corr * __real__ corr + __imag__ corr * __imag__ corr;
// Measure EPRE
float epre = srsran_vec_avg_power_cf(q->pilot_estimates, SRSRAN_NOF_SLOTS_PER_SF * SRSRAN_NRE * n_rs);
// RSRP shall not be greater than EPRE
@ -556,7 +564,7 @@ int srsran_chest_ul_estimate_pucch(srsran_chest_ul_t* q,
if (fpclassify(res->noise_estimate) == FP_ZERO) {
res->noise_estimate = FLT_MIN;
}
res->noise_estimate_dbm = srsran_convert_power_to_dBm(res->noise_estimate);
res->noise_estimate_dbFs = srsran_convert_power_to_dBm(res->noise_estimate);
// Estimate SINR
if (isnormal(res->noise_estimate)) {

View File

@ -283,7 +283,7 @@ int srsran_dmrs_pucch_format1_estimate(const srsran_pucch_nr_t* q,
res->epre = epre;
res->epre_dBfs = srsran_convert_power_to_dB(epre);
res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f);
res->noise_estimate_dbm = srsran_convert_power_to_dB(res->noise_estimate);
res->noise_estimate_dbFs = srsran_convert_power_to_dB(res->noise_estimate);
res->snr = rsrp / res->noise_estimate;
res->snr_db = srsran_convert_power_to_dB(res->snr);
@ -458,7 +458,7 @@ int srsran_dmrs_pucch_format2_estimate(const srsran_pucch_nr_t* q,
res->epre = epre;
res->epre_dBfs = srsran_convert_power_to_dB(epre);
res->noise_estimate = SRSRAN_MAX(epre - rsrp, 1e-6f);
res->noise_estimate_dbm = srsran_convert_power_to_dB(res->noise_estimate);
res->noise_estimate_dbFs = srsran_convert_power_to_dB(res->noise_estimate);
res->snr = rsrp / res->noise_estimate;
res->snr_db = srsran_convert_power_to_dB(res->snr);

View File

@ -150,12 +150,12 @@ int srs_test_context_run(srs_test_context_t* q)
INFO("RESULTS: tti=%d; snr_db=%+.1f; noise_estimate_dbm=%+.1f; ta_us=%+.1f;",
ul_sf_cfg.tti,
q->chest_ul_res.snr_db,
q->chest_ul_res.noise_estimate_dbm,
q->chest_ul_res.noise_estimate_dbFs,
q->chest_ul_res.ta_us);
// Assert SRS measurements
TESTASSERT(fabsf(q->chest_ul_res.snr_db - snr_db) < CHEST_TEST_SRS_SNR_DB_TOLERANCE);
TESTASSERT(fabsf(q->chest_ul_res.noise_estimate_dbm - n0_dbm) < CHEST_TEST_SRS_SNR_DB_TOLERANCE);
TESTASSERT(fabsf(q->chest_ul_res.noise_estimate_dbFs - n0_dbm) < CHEST_TEST_SRS_SNR_DB_TOLERANCE);
TESTASSERT(fabsf(q->chest_ul_res.ta_us) < CHEST_TEST_SRS_TA_US_TOLERANCE);
return SRSRAN_SUCCESS;

View File

@ -184,8 +184,9 @@ static int get_pucch(srsran_enb_ul_t* q, srsran_ul_sf_cfg_t* ul_sf, srsran_pucch
ERROR("Error estimating PUCCH DMRS");
return SRSRAN_ERROR;
}
pucch_res.snr_db = q->chest_res.snr_db;
pucch_res.rsrp_db = q->chest_res.rsrp_dBfs;
pucch_res.snr_db = q->chest_res.snr_db;
pucch_res.rssi_dbFs = q->chest_res.epre_dBfs;
pucch_res.ni_dbFs = q->chest_res.noise_estimate_dbFs;
ret = srsran_pucch_decode(&q->pucch, ul_sf, cfg, &q->chest_res, q->sf_symbols, &pucch_res);
if (ret < SRSRAN_SUCCESS) {

View File

@ -308,7 +308,7 @@ int srsran_gnb_ul_get_pucch(srsran_gnb_ul_t* q,
meas->epre = q->chest_pucch.epre;
meas->epre_dB = q->chest_pucch.epre_dBfs;
meas->n0 = q->chest_pucch.noise_estimate;
meas->n0_dB = q->chest_pucch.noise_estimate_dbm;
meas->n0_dB = q->chest_pucch.noise_estimate_dbFs;
meas->snr_dB = q->chest_pucch.snr_db;
meas->cfo_hz = q->chest_pucch.cfo_hz;
meas->cfo_hz_max = NAN; // Unavailable

View File

@ -100,7 +100,7 @@ private:
void metrics_read(phy_metrics_t* metrics);
void metrics_dl(uint32_t mcs);
void metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo_iters);
void metrics_ul_pucch(float rssi, float sinr);
void metrics_ul_pucch(float rssi, float ni, float sinr);
uint32_t get_rnti() const { return rnti; }
private:

View File

@ -364,7 +364,7 @@ bool cc_worker::decode_pusch_rnti(stack_interface_phy_lte::ul_sched_grant_t& ul_
if (ul_grant.data != nullptr) {
// Save metrics stats
ue_db[rnti]->metrics_ul(ul_grant.dci.tb.mcs_idx,
enb_ul.chest_res.rsrp_dBfs - phy->params.rx_gain_offset,
enb_ul.chest_res.epre_dBfs - phy->params.rx_gain_offset,
enb_ul.chest_res.snr_db,
pusch_res.avg_iterations_block);
}
@ -455,7 +455,9 @@ int cc_worker::decode_pucch()
// Save metrics
if (pucch_res.detected) {
ue_db[rnti]->metrics_ul_pucch(pucch_res.rsrp_db - phy->params.rx_gain_offset, pucch_res.snr_db);
ue_db[rnti]->metrics_ul_pucch(pucch_res.rssi_dbFs - phy->params.rx_gain_offset,
pucch_res.ni_dbFs - -phy->params.rx_gain_offset,
pucch_res.snr_db);
}
}
}
@ -681,12 +683,13 @@ void cc_worker::ue::metrics_ul(uint32_t mcs, float rssi, float sinr, float turbo
metrics.ul.n_samples++;
}
void cc_worker::ue::metrics_ul_pucch(float rssi, float sinr)
void cc_worker::ue::metrics_ul_pucch(float rssi, float ni, float sinr)
{
if (isnan(rssi)) {
rssi = 0;
}
metrics.ul.pucch_rssi = SRSRAN_VEC_CMA((float)rssi, metrics.ul.pucch_rssi, metrics.ul.n_samples_pucch);
metrics.ul.pucch_ni = SRSRAN_VEC_CMA((float)ni, metrics.ul.pucch_ni, metrics.ul.n_samples_pucch);
metrics.ul.pucch_sinr = SRSRAN_VEC_CMA((float)sinr, metrics.ul.pucch_sinr, metrics.ul.n_samples_pucch);
metrics.ul.n_samples_pucch++;
}

View File

@ -278,6 +278,8 @@ uint32_t sf_worker::get_metrics(std::vector<phy_metrics_t>& metrics)
m->ul.pusch_rssi = SRSRAN_VEC_SAFE_PMA(m->ul.pusch_rssi, m->ul.n_samples, m_->ul.pusch_rssi, m_->ul.n_samples);
m->ul.pucch_rssi =
SRSRAN_VEC_SAFE_PMA(m->ul.pucch_rssi, m->ul.n_samples_pucch, m_->ul.pucch_rssi, m_->ul.n_samples_pucch);
m->ul.pucch_ni =
SRSRAN_VEC_SAFE_PMA(m->ul.pucch_ni, m->ul.n_samples_pucch, m_->ul.pucch_ni, m_->ul.n_samples_pucch);
m->ul.turbo_iters = SRSRAN_VEC_SAFE_PMA(m->ul.turbo_iters, m->ul.n_samples, m_->ul.turbo_iters, m_->ul.n_samples);
m->ul.n_samples += m_->ul.n_samples;
m->ul.n_samples_pucch += m_->ul.n_samples_pucch;

View File

@ -255,6 +255,7 @@ void phy::get_metrics(std::vector<phy_metrics_t>& metrics)
metrics[j].ul.pusch_rssi += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_rssi;
metrics[j].ul.pusch_sinr += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.pusch_sinr;
metrics[j].ul.pucch_rssi += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_rssi;
metrics[j].ul.pucch_ni += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_ni;
metrics[j].ul.pucch_sinr += metrics_tmp[j].ul.n_samples_pucch * metrics_tmp[j].ul.pucch_sinr;
metrics[j].ul.turbo_iters += metrics_tmp[j].ul.n_samples * metrics_tmp[j].ul.turbo_iters;
}
@ -269,6 +270,7 @@ void phy::get_metrics(std::vector<phy_metrics_t>& metrics)
metrics[j].ul.pusch_rssi /= metrics[j].ul.n_samples;
metrics[j].ul.pusch_sinr /= metrics[j].ul.n_samples;
metrics[j].ul.pucch_rssi /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.pucch_ni /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.pucch_sinr /= metrics[j].ul.n_samples_pucch;
metrics[j].ul.turbo_iters /= metrics[j].ul.n_samples;
}