Mulpiple CSI measurement fixes. Channel and sync metrics from CSI measurements

master
Xavier Arteaga 4 years ago committed by Xavier Arteaga
parent fd0d804321
commit 1396c2a1e2

@ -42,7 +42,7 @@
/** /**
* @brief Describes a measurement for NZP-CSI-RS * @brief Describes a measurement for NZP-CSI-RS
* @note Used for fine tracking RSRP, SNR, CFO, SFO, and so on * @note Used for fine tracking RSRP, SNR, CFO, SFO, and so on
* @note srsran_csi_measurements_t is used for CSI report generation * @note srsran_csi_channel_measurements_t is used for CSI report generation
*/ */
typedef struct SRSRAN_API { typedef struct SRSRAN_API {
float rsrp; ///< Linear scale RSRP float rsrp; ///< Linear scale RSRP
@ -57,7 +57,7 @@ typedef struct SRSRAN_API {
float delay_us; ///< Average measured delay in microseconds float delay_us; ///< Average measured delay in microseconds
uint32_t nof_re; ///< Number of available RE for the measurement, it can be used for weighting among different uint32_t nof_re; ///< Number of available RE for the measurement, it can be used for weighting among different
///< measurements ///< measurements
} srsran_csi_rs_nzp_measure_t; } srsran_csi_trs_measurements_t;
/** /**
* @brief Calculates if the given periodicity implies a CSI-RS transmission in the given slot * @brief Calculates if the given periodicity implies a CSI-RS transmission in the given slot
@ -118,7 +118,7 @@ SRSRAN_API int srsran_csi_rs_nzp_measure(const srsran_carrier_nr_t* car
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_resource_t* resource, const srsran_csi_rs_nzp_resource_t* resource,
const cf_t* grid, const cf_t* grid,
srsran_csi_rs_nzp_measure_t* measure); srsran_csi_trs_measurements_t* measure);
/** /**
* @brief Performs measurements of NZP-CSI-RS resource set flagged as TRS * @brief Performs measurements of NZP-CSI-RS resource set flagged as TRS
@ -150,9 +150,11 @@ SRSRAN_API int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carr
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* set, const srsran_csi_rs_nzp_set_t* set,
const cf_t* grid, const cf_t* grid,
srsran_csi_rs_nzp_measure_t* measure); srsran_csi_trs_measurements_t* measure);
SRSRAN_API uint32_t srsran_csi_rs_measure_info(const srsran_csi_rs_nzp_measure_t* measure, char* str, uint32_t str_len); SRSRAN_API uint32_t srsran_csi_rs_measure_info(const srsran_csi_trs_measurements_t* measure,
char* str,
uint32_t str_len);
/** /**
* @brief Performs channel measurements of NZP-CSI-RS resource set for CSI reports * @brief Performs channel measurements of NZP-CSI-RS resource set for CSI reports
@ -176,7 +178,7 @@ SRSRAN_API int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t*
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* set, const srsran_csi_rs_nzp_set_t* set,
const cf_t* grid, const cf_t* grid,
srsran_csi_measurements_t* measure); srsran_csi_channel_measurements_t* measure);
/** /**
* @brief Performs measurements of ZP-CSI-RS resource set for CSI reports * @brief Performs measurements of ZP-CSI-RS resource set for CSI reports
@ -198,6 +200,6 @@ SRSRAN_API int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* ca
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_zp_set_t* set, const srsran_csi_rs_zp_set_t* set,
const cf_t* grid, const cf_t* grid,
srsran_csi_measurements_t* measure); srsran_csi_channel_measurements_t* measure);
#endif // SRSRAN_CSI_RS_H_ #endif // SRSRAN_CSI_RS_H_

@ -15,10 +15,19 @@
#include "uci_cfg_nr.h" #include "uci_cfg_nr.h"
/**
* @brief Processes a new NZP-CSI-RS channel measurement, it maps the given measurement into the current measurements
* applying an exponential moving average filter
* @param csi_resources CSI Resource configuration, links NZP-CSI-RS resources with CSI Measurements
* @param measurements Current CSI measurements
* @param new_measure New NZP-CSI-RS channel measurement
* @param nzp_csi_rs_id NZP-CSI-RS resource set identifier
* @return SRSLTE_SUCCESS if the provided information is valid, SRSLTE_ERROR code otherwise
*/
SRSRAN_API int SRSRAN_API int
srsran_csi_new_nzp_csi_rs_measurement(const srsran_csi_hl_resource_cfg_t csi_resources[SRSRAN_CSI_MAX_NOF_RESOURCES], srsran_csi_new_nzp_csi_rs_measurement(const srsran_csi_hl_resource_cfg_t csi_resources[SRSRAN_CSI_MAX_NOF_RESOURCES],
srsran_csi_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES], srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
const srsran_csi_measurements_t* new_measure, const srsran_csi_channel_measurements_t* new_measure,
uint32_t nzp_csi_rs_id); uint32_t nzp_csi_rs_id);
/** /**
@ -29,9 +38,10 @@ srsran_csi_new_nzp_csi_rs_measurement(const srsran_csi_hl_resource_cfg_t csi_res
* @param[out] report_cfg Report configuration re * @param[out] report_cfg Report configuration re
* @return The number CSI reports for transmission if the provided data is valid, SRSRAN_ERROR code otherwise * @return The number CSI reports for transmission if the provided data is valid, SRSRAN_ERROR code otherwise
*/ */
SRSRAN_API int srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg, SRSRAN_API int
srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
uint32_t slot_idx, uint32_t slot_idx,
const srsran_csi_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES], const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT], srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT],
srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT]); srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT]);

@ -147,7 +147,7 @@ typedef struct SRSRAN_API {
} srsran_csi_hl_cfg_t; } srsran_csi_hl_cfg_t;
/** /**
* @brief Generic CSI measurement structure * @brief Generic CSI measurement structure, used for generating CSI reports
*/ */
typedef struct SRSRAN_API { typedef struct SRSRAN_API {
uint32_t cri; ///< CSI-RS Resource Indicator uint32_t cri; ///< CSI-RS Resource Indicator
@ -158,7 +158,7 @@ typedef struct SRSRAN_API {
// Resource set context // Resource set context
uint32_t nof_ports; ///< Number of antenna ports uint32_t nof_ports; ///< Number of antenna ports
uint32_t K_csi_rs; ///< Number of CSI-RS in the corresponding resource set uint32_t K_csi_rs; ///< Number of CSI-RS in the corresponding resource set
} srsran_csi_measurements_t; } srsran_csi_channel_measurements_t;
/** /**
* @brief CSI report configuration * @brief CSI report configuration

@ -174,9 +174,15 @@ SRSRAN_API int srsran_ue_dl_nr_ack_insert_m(srsran_pdsch_ack_nr_t* ack_info, srs
SRSRAN_API uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len); SRSRAN_API uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* str, uint32_t str_len);
SRSRAN_API SRSRAN_API
int srsran_ue_dl_nr_csi_measure(const srsran_ue_dl_nr_t* q, int srsran_ue_dl_nr_csi_measure_trs(const srsran_ue_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* csi_rs_nzp_set, const srsran_csi_rs_nzp_set_t* csi_rs_nzp_set,
srsran_csi_measurements_t* measurement); srsran_csi_trs_measurements_t* measurement);
SRSRAN_API
int srsran_ue_dl_nr_csi_measure_channel(const srsran_ue_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* csi_rs_nzp_set,
srsran_csi_channel_measurements_t* measurement);
#endif // SRSRAN_UE_DL_NR_H #endif // SRSRAN_UE_DL_NR_H

@ -177,7 +177,7 @@ static uint32_t csi_rs_cinit(const srsran_carrier_nr_t* carrier,
uint32_t n = SRSRAN_SLOT_NR_MOD(carrier->scs, slot_cfg->idx); uint32_t n = SRSRAN_SLOT_NR_MOD(carrier->scs, slot_cfg->idx);
uint32_t n_id = resource->scrambling_id; uint32_t n_id = resource->scrambling_id;
return SRSRAN_SEQUENCE_MOD(((SRSRAN_NSYMB_PER_SLOT_NR * n + l + 1UL) * (2UL * n_id) << 10UL) + n_id); return SRSRAN_SEQUENCE_MOD((((SRSRAN_NSYMB_PER_SLOT_NR * n + l + 1UL) * (2UL * n_id + 1UL)) << 10UL) + n_id);
} }
bool srsran_csi_rs_send(const srsran_csi_rs_period_and_offset_t* periodicity, const srsran_slot_cfg_t* slot_cfg) bool srsran_csi_rs_send(const srsran_csi_rs_period_and_offset_t* periodicity, const srsran_slot_cfg_t* slot_cfg)
@ -538,16 +538,22 @@ static int csi_rs_nzp_measure_resource(const srsran_carrier_nr_t* carri
} }
// Compute LSE // Compute LSE
srsran_sequence_state_apply_f(&sequence_state, (float*)lse, (float*)lse, 2 * count_re); cf_t r[CSI_RS_MAX_SUBC_PRB * SRSRAN_MAX_PRB_NR];
srsran_sequence_state_gen_f(&sequence_state, M_SQRT1_2, (float*)r, 2 * count_re);
srsran_vec_prod_conj_ccc(lse, r, lse, count_re);
// Compute average delay
float delay = srsran_vec_estimate_frequency(lse, (int)count_re);
delay_acc += delay;
// Pre-compensate delay to avoid RSRP measurements get affected by average delay
srsran_vec_apply_cfo(lse, delay, lse, (int)count_re);
// Compute EPRE // Compute EPRE
epre_acc += srsran_vec_avg_power_cf(lse, count_re); epre_acc += srsran_vec_avg_power_cf(lse, count_re);
// Compute correlation // Compute correlation
corr_acc += srsran_vec_acc_cc(lse, count_re) / (float)count_re; corr_acc += srsran_vec_acc_cc(lse, count_re) / (float)count_re;
// Compute average delay
delay_acc += srsran_vec_estimate_frequency(lse, count_re);
} }
// Set measure fields // Set measure fields
@ -591,7 +597,7 @@ int srsran_csi_rs_nzp_measure(const srsran_carrier_nr_t* carrier,
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_resource_t* resource, const srsran_csi_rs_nzp_resource_t* resource,
const cf_t* grid, const cf_t* grid,
srsran_csi_rs_nzp_measure_t* measure) srsran_csi_trs_measurements_t* measure)
{ {
if (carrier == NULL || slot_cfg == NULL || resource == NULL || grid == NULL || measure == NULL) { if (carrier == NULL || slot_cfg == NULL || resource == NULL || grid == NULL || measure == NULL) {
return SRSRAN_ERROR; return SRSRAN_ERROR;
@ -605,7 +611,7 @@ int srsran_csi_rs_nzp_measure(const srsran_carrier_nr_t* carrier,
// Copy measurements // Copy measurements
measure->epre = m.epre; measure->epre = m.epre;
measure->rsrp = (__real__ m.corr * __real__ m.corr + __imag__ m.corr * __imag__ m.corr); measure->rsrp = SRSRAN_CSQABS(m.corr);
measure->delay_us = m.delay_us; measure->delay_us = m.delay_us;
measure->nof_re = m.nof_re; measure->nof_re = m.nof_re;
@ -616,7 +622,7 @@ int srsran_csi_rs_nzp_measure(const srsran_carrier_nr_t* carrier,
measure->n0 = 0.0f; measure->n0 = 0.0f;
} }
// CFo cannot be estimated with a single resource // CFO cannot be estimated with a single resource
measure->cfo_hz = 0.0f; measure->cfo_hz = 0.0f;
measure->cfo_hz_max = 0.0f; measure->cfo_hz_max = 0.0f;
@ -633,7 +639,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier,
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* set, const srsran_csi_rs_nzp_set_t* set,
const cf_t* grid, const cf_t* grid,
srsran_csi_rs_nzp_measure_t* measure) srsran_csi_trs_measurements_t* measure)
{ {
// Verify inputs // Verify inputs
if (carrier == NULL || slot_cfg == NULL || set == NULL || grid == NULL || measure == NULL) { if (carrier == NULL || slot_cfg == NULL || set == NULL || grid == NULL || measure == NULL) {
@ -680,9 +686,7 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier,
uint32_t nof_re = 0; uint32_t nof_re = 0;
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
epre_sum += measurements[i].epre / (float)count; epre_sum += measurements[i].epre / (float)count;
rsrp_sum += (__real__ measurements[i].corr * __real__ measurements[i].corr + rsrp_sum += SRSRAN_CSQABS(measurements[i].corr) / (float)count;
__imag__ measurements[i].corr * __imag__ measurements[i].corr) /
(float)count;
delay_sum += measurements[i].delay_us / (float)count; delay_sum += measurements[i].delay_us / (float)count;
nof_re += measurements[i].nof_re; nof_re += measurements[i].nof_re;
} }
@ -736,7 +740,7 @@ int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* set, const srsran_csi_rs_nzp_set_t* set,
const cf_t* grid, const cf_t* grid,
srsran_csi_measurements_t* measure) srsran_csi_channel_measurements_t* measure)
{ {
// Verify inputs // Verify inputs
if (carrier == NULL || slot_cfg == NULL || set == NULL || grid == NULL || measure == NULL) { if (carrier == NULL || slot_cfg == NULL || set == NULL || grid == NULL || measure == NULL) {
@ -761,9 +765,7 @@ int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
float rsrp_sum = 0.0f; float rsrp_sum = 0.0f;
for (uint32_t i = 0; i < count; i++) { for (uint32_t i = 0; i < count; i++) {
epre_sum += measurements[i].epre / (float)count; epre_sum += measurements[i].epre / (float)count;
rsrp_sum += (__real__ measurements[i].corr * __real__ measurements[i].corr + rsrp_sum += SRSRAN_CSQABS(measurements[i].corr) / (float)count;
__imag__ measurements[i].corr * __imag__ measurements[i].corr) /
(float)count;
} }
// Estimate noise from EPRE and RSPR // Estimate noise from EPRE and RSPR
@ -913,7 +915,7 @@ int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_zp_set_t* set, const srsran_csi_rs_zp_set_t* set,
const cf_t* grid, const cf_t* grid,
srsran_csi_measurements_t* measure) srsran_csi_channel_measurements_t* measure)
{ {
// Verify inputs // Verify inputs
if (carrier == NULL || slot_cfg == NULL || set == NULL || grid == NULL || measure == NULL) { if (carrier == NULL || slot_cfg == NULL || set == NULL || grid == NULL || measure == NULL) {
@ -953,7 +955,7 @@ int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
return count; return count;
} }
uint32_t srsran_csi_rs_measure_info(const srsran_csi_rs_nzp_measure_t* measure, char* str, uint32_t str_len) uint32_t srsran_csi_rs_measure_info(const srsran_csi_trs_measurements_t* measure, char* str, uint32_t str_len)
{ {
uint32_t len = 0; uint32_t len = 0;

@ -39,7 +39,7 @@ static int nzp_test_case(const srsran_slot_cfg_t* slot_cfg,
srsran_channel_awgn_t* awgn, srsran_channel_awgn_t* awgn,
cf_t* grid) cf_t* grid)
{ {
srsran_csi_rs_nzp_measure_t measure = {}; srsran_csi_trs_measurements_t measure = {};
// Put NZP-CSI-RS // Put NZP-CSI-RS
TESTASSERT(srsran_csi_rs_nzp_put_resource(&carrier, slot_cfg, resource, grid) == SRSRAN_SUCCESS); TESTASSERT(srsran_csi_rs_nzp_put_resource(&carrier, slot_cfg, resource, grid) == SRSRAN_SUCCESS);
@ -316,7 +316,7 @@ static int nzp_test_trs(srsran_channel_awgn_t* awgn, cf_t* grid)
srsran_channel_awgn_run_c(awgn, grid, grid, SRSRAN_SLOT_LEN_RE_NR(carrier.nof_prb)); srsran_channel_awgn_run_c(awgn, grid, grid, SRSRAN_SLOT_LEN_RE_NR(carrier.nof_prb));
// Measure // Measure
srsran_csi_rs_nzp_measure_t measure = {}; srsran_csi_trs_measurements_t measure = {};
ret = srsran_csi_rs_nzp_measure_trs(&carrier, &slot_cfg, &set, grid, &measure); ret = srsran_csi_rs_nzp_measure_trs(&carrier, &slot_cfg, &set, grid, &measure);
// Check return and assert measurement // Check return and assert measurement

@ -37,8 +37,8 @@ static bool csi_report_trigger(const srsran_csi_hl_report_cfg_t* cfg, uint32_t s
} }
static void csi_wideband_cri_ri_pmi_cqi_quantify(const srsran_csi_hl_report_cfg_t* cfg, static void csi_wideband_cri_ri_pmi_cqi_quantify(const srsran_csi_hl_report_cfg_t* cfg,
const srsran_csi_measurements_t* channel_meas, const srsran_csi_channel_measurements_t* channel_meas,
const srsran_csi_measurements_t* interf_meas, const srsran_csi_channel_measurements_t* interf_meas,
srsran_csi_report_cfg_t* report_cfg, srsran_csi_report_cfg_t* report_cfg,
srsran_csi_report_value_t* report_value) srsran_csi_report_value_t* report_value)
{ {
@ -146,8 +146,8 @@ csi_none_unpack(const srsran_csi_report_cfg_t* cfg, const uint8_t* o_csi1, srsra
int srsran_csi_new_nzp_csi_rs_measurement( int srsran_csi_new_nzp_csi_rs_measurement(
const srsran_csi_hl_resource_cfg_t csi_resources[SRSRAN_CSI_MAX_NOF_RESOURCES], const srsran_csi_hl_resource_cfg_t csi_resources[SRSRAN_CSI_MAX_NOF_RESOURCES],
srsran_csi_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES], srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
const srsran_csi_measurements_t* new_measure, const srsran_csi_channel_measurements_t* new_measure,
uint32_t nzp_csi_rs_id) uint32_t nzp_csi_rs_id)
{ {
if (csi_resources == NULL || measurements == NULL || new_measure == NULL) { if (csi_resources == NULL || measurements == NULL || new_measure == NULL) {
@ -192,7 +192,7 @@ int srsran_csi_new_nzp_csi_rs_measurement(
int srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg, int srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
uint32_t slot_idx, uint32_t slot_idx,
const srsran_csi_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES], const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT], srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT],
srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT]) srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT])
{ {
@ -215,10 +215,10 @@ int srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
ERROR("Channel measurement ID (%d) is out of range", cfg->reports->channel_meas_id); ERROR("Channel measurement ID (%d) is out of range", cfg->reports->channel_meas_id);
return SRSRAN_ERROR; return SRSRAN_ERROR;
} }
const srsran_csi_measurements_t* channel_meas = &measurements[cfg->reports->channel_meas_id]; const srsran_csi_channel_measurements_t* channel_meas = &measurements[cfg->reports->channel_meas_id];
// Select interference measurement // Select interference measurement
const srsran_csi_measurements_t* interf_meas = NULL; const srsran_csi_channel_measurements_t* interf_meas = NULL;
if (cfg->reports->interf_meas_present) { if (cfg->reports->interf_meas_present) {
if (cfg->reports->interf_meas_id >= SRSRAN_CSI_MAX_NOF_RESOURCES) { if (cfg->reports->interf_meas_id >= SRSRAN_CSI_MAX_NOF_RESOURCES) {
ERROR("Interference measurement ID (%d) is out of range", cfg->reports->interf_meas_id); ERROR("Interference measurement ID (%d) is out of range", cfg->reports->interf_meas_id);

@ -839,10 +839,22 @@ uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* s
return len; return len;
} }
int srsran_ue_dl_nr_csi_measure(const srsran_ue_dl_nr_t* q, int srsran_ue_dl_nr_csi_measure_trs(const srsran_ue_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg, const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* csi_rs_nzp_set, const srsran_csi_rs_nzp_set_t* csi_rs_nzp_set,
srsran_csi_measurements_t* measurement) srsran_csi_trs_measurements_t* measurement)
{
if (q == NULL || slot_cfg == NULL || csi_rs_nzp_set == NULL || measurement == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS;
}
return srsran_csi_rs_nzp_measure_trs(&q->carrier, slot_cfg, csi_rs_nzp_set, q->sf_symbols[0], measurement);
}
int srsran_ue_dl_nr_csi_measure_channel(const srsran_ue_dl_nr_t* q,
const srsran_slot_cfg_t* slot_cfg,
const srsran_csi_rs_nzp_set_t* csi_rs_nzp_set,
srsran_csi_channel_measurements_t* measurement)
{ {
if (q == NULL || slot_cfg == NULL || csi_rs_nzp_set == NULL || measurement == NULL) { if (q == NULL || slot_cfg == NULL || csi_rs_nzp_set == NULL || measurement == NULL) {
return SRSRAN_ERROR_INVALID_INPUTS; return SRSRAN_ERROR_INVALID_INPUTS;

@ -58,11 +58,17 @@ private:
void decode_pdcch_ul(); void decode_pdcch_ul();
void decode_pdcch_dl(); void decode_pdcch_dl();
// Method for decode PDSCH /**
* @brief Decodes PDSCH in the current processing slot
* @return true if current configuration is valid and no error occur, false otherwise
*/
bool decode_pdsch_dl(); bool decode_pdsch_dl();
// Method for measurements /**
bool measure(); * @brief Performs Channel State Information (CSI) measurements
* @return true if current configuration is valid and no error occur, false otherwise
*/
bool measure_csi();
}; };
} // namespace nr } // namespace nr

@ -58,7 +58,7 @@ private:
/// CSI-RS measurements /// CSI-RS measurements
std::mutex csi_measurements_mutex; std::mutex csi_measurements_mutex;
std::array<srsran_csi_measurements_t, SRSRAN_CSI_MAX_NOF_RESOURCES> csi_measurements = {}; std::array<srsran_csi_channel_measurements_t, SRSRAN_CSI_MAX_NOF_RESOURCES> csi_measurements = {};
/** /**
* @brief Resets all metrics (unprotected) * @brief Resets all metrics (unprotected)
@ -278,6 +278,7 @@ public:
{ {
clear_pending_grants(); clear_pending_grants();
reset_metrics(); reset_metrics();
reset_measurements();
} }
bool has_valid_sr_resource(uint32_t sr_id) bool has_valid_sr_resource(uint32_t sr_id)
@ -424,7 +425,22 @@ public:
reset_metrics_(); reset_metrics_();
} }
void new_nzp_csi_rs_channel_measurement(const srsran_csi_measurements_t& new_measure, uint32_t resource_set_id) /**
* @brief Resets all PHY measurements (protected)
*/
void reset_measurements()
{
std::lock_guard<std::mutex> lock(csi_measurements_mutex);
csi_measurements = {};
}
/**
* @brief Processes a new NZP-CSI-RS channel measurement
* @param new_measure New measurement
* @param resource_set_id NZP-CSI-RS resource set identifier used for the channel measurement
*/
void new_nzp_csi_rs_channel_measurement(const srsran_csi_channel_measurements_t& new_measure,
uint32_t resource_set_id)
{ {
std::lock_guard<std::mutex> lock(csi_measurements_mutex); std::lock_guard<std::mutex> lock(csi_measurements_mutex);

@ -200,7 +200,7 @@ bool cc_worker::decode_pdsch_dl()
srsran_pdsch_ack_resource_nr_t ack_resource = {}; srsran_pdsch_ack_resource_nr_t ack_resource = {};
if (not phy->get_dl_pending_grant(dl_slot_cfg.idx, pdsch_cfg, ack_resource, pid)) { if (not phy->get_dl_pending_grant(dl_slot_cfg.idx, pdsch_cfg, ack_resource, pid)) {
// Early return if no grant was available // Early return if no grant was available
return false; return true;
} }
// Notify MAC about PDSCH grant // Notify MAC about PDSCH grant
mac_interface_phy_nr::tb_action_dl_t dl_action = {}; mac_interface_phy_nr::tb_action_dl_t dl_action = {};
@ -291,42 +291,101 @@ bool cc_worker::decode_pdsch_dl()
dl_m.fec_iters = pdsch_res.tb[0].avg_iter; dl_m.fec_iters = pdsch_res.tb[0].avg_iter;
dl_m.evm = pdsch_res.evm[0]; dl_m.evm = pdsch_res.evm[0];
phy->set_dl_metrics(dl_m); phy->set_dl_metrics(dl_m);
// Generate Synch metrics
sync_metrics_t sync_m = {};
sync_m.cfo = ue_dl.chest.cfo;
phy->set_sync_metrics(sync_m);
// Generate channel metrics
ch_metrics_t ch_m = {};
ch_m.n = ue_dl.chest.noise_estimate;
ch_m.sinr = ue_dl.chest.snr_db;
ch_m.rsrp = ue_dl.chest.rsrp_dbm;
ch_m.sync_err = ue_dl.chest.sync_error;
phy->set_channel_metrics(ch_m);
} }
return true; return true;
} }
bool cc_worker::measure() bool cc_worker::measure_csi()
{ {
// Iterate all NZP-CSI-RS and perform channel measurements // Iterate all NZP-CSI-RS marked as TRS and perform channel measurements
for (uint32_t resource_set_id = 0; resource_set_id < SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS; resource_set_id++) { for (uint32_t resource_set_id = 0; resource_set_id < SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS; resource_set_id++) {
// Select NZP-CSI-RS set // Select NZP-CSI-RS set
const srsran_csi_rs_nzp_set_t& nzp_set = phy->cfg.pdsch.nzp_csi_rs_sets[resource_set_id]; const srsran_csi_rs_nzp_set_t& nzp_set = phy->cfg.pdsch.nzp_csi_rs_sets[resource_set_id];
srsran_csi_measurements_t measurements = {}; // Skip set if not set as TRS (it will be processed later)
int n = srsran_ue_dl_nr_csi_measure(&ue_dl, &dl_slot_cfg, &nzp_set, &measurements); if (not nzp_set.trs_info) {
continue;
}
// Perform measurement, n > 0 is any measurement is performed, n = 0 otherwise
srsran_csi_trs_measurements_t trs_measurements = {};
int n = srsran_ue_dl_nr_csi_measure_trs(&ue_dl, &dl_slot_cfg, &nzp_set, &trs_measurements);
if (n < SRSRAN_SUCCESS) { if (n < SRSRAN_SUCCESS) {
logger.error("Error measuring CSI-RS"); logger.error("Error measuring CSI-RS");
return false; return false;
} }
// Report new measurement to the PHY state // If no measurement performed, skip
if (n > 0) { if (n == 0) {
continue;
}
logger.info("NZP-CSI-RS (TRS): id=%d rsrp=%+.1f epre=%+.1f snr=%+.1f cfo=%+.1f delay=%.1f",
resource_set_id,
trs_measurements.rsrp_dB,
trs_measurements.epre_dB,
trs_measurements.snr_dB,
trs_measurements.cfo_hz,
trs_measurements.delay_us);
// Compute channel metrics and push it
ch_metrics_t ch_metrics = {};
ch_metrics.sinr = trs_measurements.snr_dB;
ch_metrics.rsrp = trs_measurements.rsrp_dB;
ch_metrics.rsrq = 0.0f; // Not supported
ch_metrics.rssi = 0.0f; // Not supported
ch_metrics.sync_err =
trs_measurements.delay_us / (float)(ue_dl.fft->fft_plan.size * SRSRAN_SUBC_SPACING_NR(phy->cfg.carrier.scs));
phy->set_channel_metrics(ch_metrics);
// Compute synch metrics and report it to the PHY state
sync_metrics_t sync_metrics = {};
sync_metrics.cfo = trs_measurements.cfo_hz;
phy->set_sync_metrics(sync_metrics);
// Convert to CSI channel measurement and report new NZP-CSI-RS measurement to the PHY state
srsran_csi_channel_measurements_t measurements = {};
measurements.cri = 0;
measurements.wideband_rsrp_dBm = trs_measurements.rsrp_dB;
measurements.wideband_epre_dBm = trs_measurements.epre_dB;
measurements.wideband_snr_db = trs_measurements.snr_dB;
measurements.nof_ports = 1; // Other values are not supported
measurements.K_csi_rs = (uint32_t)n;
phy->new_nzp_csi_rs_channel_measurement(measurements, resource_set_id); phy->new_nzp_csi_rs_channel_measurement(measurements, resource_set_id);
} }
// Iterate all NZP-CSI-RS not marked as TRS and perform channel measurements
for (uint32_t resource_set_id = 0; resource_set_id < SRSRAN_PHCH_CFG_MAX_NOF_CSI_RS_SETS; resource_set_id++) {
// Select NZP-CSI-RS set
const srsran_csi_rs_nzp_set_t& nzp_set = phy->cfg.pdsch.nzp_csi_rs_sets[resource_set_id];
// Skip set if set as TRS (it was processed previously)
if (nzp_set.trs_info) {
continue;
}
// Perform channel measurement, n > 0 is any measurement is performed, n = 0 otherwise
srsran_csi_channel_measurements_t measurements = {};
int n = srsran_ue_dl_nr_csi_measure_channel(&ue_dl, &dl_slot_cfg, &nzp_set, &measurements);
if (n < SRSRAN_SUCCESS) {
logger.error("Error measuring CSI-RS");
return false;
}
// If no measurement performed, skip
if (n == 0) {
continue;
}
logger.info("NZP-CSI-RS: id=%d, rsrp=%+.1f epre=%+.1f snr=%+.1f",
resource_set_id,
measurements.wideband_rsrp_dBm,
measurements.wideband_epre_dBm,
measurements.wideband_snr_db);
// Report new measurement to the PHY state
phy->new_nzp_csi_rs_channel_measurement(measurements, resource_set_id);
} }
return true; return true;
@ -360,8 +419,8 @@ bool cc_worker::work_dl()
} }
// Measure CSI-RS // Measure CSI-RS
if (not measure()) { if (not measure_csi()) {
logger.error("Error measuring CSI-RS, aborting work DL"); logger.error("Error measuring, aborting work DL");
return false; return false;
} }

Loading…
Cancel
Save