mirror of https://github.com/PentHertz/srsLTE.git
Mulpiple CSI measurement fixes. Channel and sync metrics from CSI measurements
This commit is contained in:
parent
fd0d804321
commit
1396c2a1e2
|
@ -42,7 +42,7 @@
|
|||
/**
|
||||
* @brief Describes a measurement for NZP-CSI-RS
|
||||
* @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 {
|
||||
float rsrp; ///< Linear scale RSRP
|
||||
|
@ -57,7 +57,7 @@ typedef struct SRSRAN_API {
|
|||
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
|
||||
///< 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
|
||||
|
@ -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_csi_rs_nzp_resource_t* resource,
|
||||
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
|
||||
|
@ -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_csi_rs_nzp_set_t* set,
|
||||
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
|
||||
|
@ -172,11 +174,11 @@ SRSRAN_API uint32_t srsran_csi_rs_measure_info(const srsran_csi_rs_nzp_measure_t
|
|||
* @return The number of NZP-CSI-RS resources scheduled for this slot if the configuration is right, SRSLTE_ERROR code
|
||||
* if the configuration is invalid
|
||||
*/
|
||||
SRSRAN_API int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_measurements_t* measure);
|
||||
SRSRAN_API int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_channel_measurements_t* measure);
|
||||
|
||||
/**
|
||||
* @brief Performs measurements of ZP-CSI-RS resource set for CSI reports
|
||||
|
@ -194,10 +196,10 @@ SRSRAN_API int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t*
|
|||
* @return The number of ZP-CSI-RS resources scheduled for this slot if the configuration is right, SRSLTE_ERROR code if
|
||||
* the configuration is invalid
|
||||
*/
|
||||
SRSRAN_API int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_zp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_measurements_t* measure);
|
||||
SRSRAN_API int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_zp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_channel_measurements_t* measure);
|
||||
|
||||
#endif // SRSRAN_CSI_RS_H_
|
||||
|
|
|
@ -15,11 +15,20 @@
|
|||
|
||||
#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_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],
|
||||
const srsran_csi_measurements_t* new_measure,
|
||||
uint32_t nzp_csi_rs_id);
|
||||
srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||
const srsran_csi_channel_measurements_t* new_measure,
|
||||
uint32_t nzp_csi_rs_id);
|
||||
|
||||
/**
|
||||
* @brief Generates CSI report configuration and values from the higher layer configuration and a list of measurements
|
||||
|
@ -29,11 +38,12 @@ srsran_csi_new_nzp_csi_rs_measurement(const srsran_csi_hl_resource_cfg_t csi_res
|
|||
* @param[out] report_cfg Report configuration re
|
||||
* @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,
|
||||
uint32_t slot_idx,
|
||||
const srsran_csi_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||
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_API int
|
||||
srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
|
||||
uint32_t slot_idx,
|
||||
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_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT]);
|
||||
|
||||
/**
|
||||
* @brief Compute number of CSI bits necessary to transmit all the CSI reports for a PUCCH transmission
|
||||
|
|
|
@ -147,7 +147,7 @@ typedef struct SRSRAN_API {
|
|||
} srsran_csi_hl_cfg_t;
|
||||
|
||||
/**
|
||||
* @brief Generic CSI measurement structure
|
||||
* @brief Generic CSI measurement structure, used for generating CSI reports
|
||||
*/
|
||||
typedef struct SRSRAN_API {
|
||||
uint32_t cri; ///< CSI-RS Resource Indicator
|
||||
|
@ -158,7 +158,7 @@ typedef struct SRSRAN_API {
|
|||
// Resource set context
|
||||
uint32_t nof_ports; ///< Number of antenna ports
|
||||
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
|
||||
|
|
|
@ -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
|
||||
int srsran_ue_dl_nr_csi_measure(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_measurements_t* measurement);
|
||||
int srsran_ue_dl_nr_csi_measure_trs(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_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
|
||||
|
|
|
@ -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_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)
|
||||
|
@ -538,16 +538,22 @@ static int csi_rs_nzp_measure_resource(const srsran_carrier_nr_t* carri
|
|||
}
|
||||
|
||||
// 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
|
||||
epre_acc += srsran_vec_avg_power_cf(lse, count_re);
|
||||
|
||||
// Compute correlation
|
||||
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
|
||||
|
@ -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_csi_rs_nzp_resource_t* resource,
|
||||
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) {
|
||||
return SRSRAN_ERROR;
|
||||
|
@ -605,7 +611,7 @@ int srsran_csi_rs_nzp_measure(const srsran_carrier_nr_t* carrier,
|
|||
|
||||
// Copy measurements
|
||||
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->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;
|
||||
}
|
||||
|
||||
// CFo cannot be estimated with a single resource
|
||||
// CFO cannot be estimated with a single resource
|
||||
measure->cfo_hz = 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_csi_rs_nzp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_rs_nzp_measure_t* measure)
|
||||
srsran_csi_trs_measurements_t* measure)
|
||||
{
|
||||
// Verify inputs
|
||||
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;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
epre_sum += measurements[i].epre / (float)count;
|
||||
rsrp_sum += (__real__ measurements[i].corr * __real__ measurements[i].corr +
|
||||
__imag__ measurements[i].corr * __imag__ measurements[i].corr) /
|
||||
(float)count;
|
||||
rsrp_sum += SRSRAN_CSQABS(measurements[i].corr) / (float)count;
|
||||
delay_sum += measurements[i].delay_us / (float)count;
|
||||
nof_re += measurements[i].nof_re;
|
||||
}
|
||||
|
@ -732,11 +736,11 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier,
|
|||
return count;
|
||||
}
|
||||
|
||||
int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_measurements_t* measure)
|
||||
int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_nzp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_channel_measurements_t* measure)
|
||||
{
|
||||
// Verify inputs
|
||||
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;
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
epre_sum += measurements[i].epre / (float)count;
|
||||
rsrp_sum += (__real__ measurements[i].corr * __real__ measurements[i].corr +
|
||||
__imag__ measurements[i].corr * __imag__ measurements[i].corr) /
|
||||
(float)count;
|
||||
rsrp_sum += SRSRAN_CSQABS(measurements[i].corr) / (float)count;
|
||||
}
|
||||
|
||||
// Estimate noise from EPRE and RSPR
|
||||
|
@ -909,11 +911,11 @@ static int csi_rs_zp_measure_set(const srsran_carrier_nr_t* carrier,
|
|||
return count;
|
||||
}
|
||||
|
||||
int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_zp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_measurements_t* measure)
|
||||
int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
|
||||
const srsran_slot_cfg_t* slot_cfg,
|
||||
const srsran_csi_rs_zp_set_t* set,
|
||||
const cf_t* grid,
|
||||
srsran_csi_channel_measurements_t* measure)
|
||||
{
|
||||
// Verify inputs
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
|
||||
|
@ -972,4 +974,4 @@ uint32_t srsran_csi_rs_measure_info(const srsran_csi_rs_nzp_measure_t* measure,
|
|||
}
|
||||
|
||||
return len;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -39,7 +39,7 @@ static int nzp_test_case(const srsran_slot_cfg_t* slot_cfg,
|
|||
srsran_channel_awgn_t* awgn,
|
||||
cf_t* grid)
|
||||
{
|
||||
srsran_csi_rs_nzp_measure_t measure = {};
|
||||
srsran_csi_trs_measurements_t measure = {};
|
||||
|
||||
// Put NZP-CSI-RS
|
||||
TESTASSERT(srsran_csi_rs_nzp_put_resource(&carrier, slot_cfg, resource, grid) == SRSRAN_SUCCESS);
|
||||
|
@ -316,8 +316,8 @@ 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));
|
||||
|
||||
// Measure
|
||||
srsran_csi_rs_nzp_measure_t measure = {};
|
||||
ret = srsran_csi_rs_nzp_measure_trs(&carrier, &slot_cfg, &set, grid, &measure);
|
||||
srsran_csi_trs_measurements_t measure = {};
|
||||
ret = srsran_csi_rs_nzp_measure_trs(&carrier, &slot_cfg, &set, grid, &measure);
|
||||
|
||||
// Check return and assert measurement
|
||||
if (slot_cfg.idx == 11 || slot_cfg.idx == 12) {
|
||||
|
|
|
@ -36,11 +36,11 @@ static bool csi_report_trigger(const srsran_csi_hl_report_cfg_t* cfg, uint32_t s
|
|||
return false;
|
||||
}
|
||||
|
||||
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_measurements_t* interf_meas,
|
||||
srsran_csi_report_cfg_t* report_cfg,
|
||||
srsran_csi_report_value_t* report_value)
|
||||
static void csi_wideband_cri_ri_pmi_cqi_quantify(const srsran_csi_hl_report_cfg_t* cfg,
|
||||
const srsran_csi_channel_measurements_t* channel_meas,
|
||||
const srsran_csi_channel_measurements_t* interf_meas,
|
||||
srsran_csi_report_cfg_t* report_cfg,
|
||||
srsran_csi_report_value_t* report_value)
|
||||
{
|
||||
// Take SNR by default
|
||||
float wideband_sinr_db = channel_meas->wideband_snr_db;
|
||||
|
@ -145,10 +145,10 @@ csi_none_unpack(const srsran_csi_report_cfg_t* cfg, const uint8_t* o_csi1, srsra
|
|||
}
|
||||
|
||||
int 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],
|
||||
const srsran_csi_measurements_t* new_measure,
|
||||
uint32_t nzp_csi_rs_id)
|
||||
const srsran_csi_hl_resource_cfg_t csi_resources[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||
srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||
const srsran_csi_channel_measurements_t* new_measure,
|
||||
uint32_t nzp_csi_rs_id)
|
||||
{
|
||||
if (csi_resources == NULL || measurements == NULL || new_measure == NULL) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
|
@ -190,11 +190,11 @@ int srsran_csi_new_nzp_csi_rs_measurement(
|
|||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
int srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
|
||||
uint32_t slot_idx,
|
||||
const srsran_csi_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT],
|
||||
srsran_csi_report_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT])
|
||||
int srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
|
||||
uint32_t slot_idx,
|
||||
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_value_t report_value[SRSRAN_CSI_MAX_NOF_REPORT])
|
||||
{
|
||||
uint32_t count = 0;
|
||||
|
||||
|
@ -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);
|
||||
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
|
||||
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_id >= SRSRAN_CSI_MAX_NOF_RESOURCES) {
|
||||
ERROR("Interference measurement ID (%d) is out of range", cfg->reports->interf_meas_id);
|
||||
|
|
|
@ -839,14 +839,26 @@ uint32_t srsran_ue_dl_nr_ack_info(const srsran_pdsch_ack_nr_t* ack_info, char* s
|
|||
return len;
|
||||
}
|
||||
|
||||
int srsran_ue_dl_nr_csi_measure(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_measurements_t* measurement)
|
||||
int srsran_ue_dl_nr_csi_measure_trs(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_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) {
|
||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||
}
|
||||
|
||||
return srsran_csi_rs_nzp_measure_channel(&q->carrier, slot_cfg, csi_rs_nzp_set, q->sf_symbols[0], measurement);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -58,11 +58,17 @@ private:
|
|||
void decode_pdcch_ul();
|
||||
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();
|
||||
|
||||
// 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
|
||||
|
|
|
@ -57,8 +57,8 @@ private:
|
|||
mutable std::mutex metrics_mutex;
|
||||
|
||||
/// CSI-RS measurements
|
||||
std::mutex csi_measurements_mutex;
|
||||
std::array<srsran_csi_measurements_t, SRSRAN_CSI_MAX_NOF_RESOURCES> csi_measurements = {};
|
||||
std::mutex csi_measurements_mutex;
|
||||
std::array<srsran_csi_channel_measurements_t, SRSRAN_CSI_MAX_NOF_RESOURCES> csi_measurements = {};
|
||||
|
||||
/**
|
||||
* @brief Resets all metrics (unprotected)
|
||||
|
@ -278,6 +278,7 @@ public:
|
|||
{
|
||||
clear_pending_grants();
|
||||
reset_metrics();
|
||||
reset_measurements();
|
||||
}
|
||||
|
||||
bool has_valid_sr_resource(uint32_t sr_id)
|
||||
|
@ -424,7 +425,22 @@ public:
|
|||
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);
|
||||
|
||||
|
|
|
@ -200,7 +200,7 @@ bool cc_worker::decode_pdsch_dl()
|
|||
srsran_pdsch_ack_resource_nr_t ack_resource = {};
|
||||
if (not phy->get_dl_pending_grant(dl_slot_cfg.idx, pdsch_cfg, ack_resource, pid)) {
|
||||
// Early return if no grant was available
|
||||
return false;
|
||||
return true;
|
||||
}
|
||||
// Notify MAC about PDSCH grant
|
||||
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.evm = pdsch_res.evm[0];
|
||||
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;
|
||||
}
|
||||
|
||||
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++) {
|
||||
// Select NZP-CSI-RS set
|
||||
const srsran_csi_rs_nzp_set_t& nzp_set = phy->cfg.pdsch.nzp_csi_rs_sets[resource_set_id];
|
||||
|
||||
srsran_csi_measurements_t measurements = {};
|
||||
int n = srsran_ue_dl_nr_csi_measure(&ue_dl, &dl_slot_cfg, &nzp_set, &measurements);
|
||||
// Skip set if not set as TRS (it will be processed later)
|
||||
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) {
|
||||
logger.error("Error measuring CSI-RS");
|
||||
return false;
|
||||
}
|
||||
|
||||
// Report new measurement to the PHY state
|
||||
if (n > 0) {
|
||||
phy->new_nzp_csi_rs_channel_measurement(measurements, resource_set_id);
|
||||
// If no measurement performed, skip
|
||||
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);
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
@ -360,8 +419,8 @@ bool cc_worker::work_dl()
|
|||
}
|
||||
|
||||
// Measure CSI-RS
|
||||
if (not measure()) {
|
||||
logger.error("Error measuring CSI-RS, aborting work DL");
|
||||
if (not measure_csi()) {
|
||||
logger.error("Error measuring, aborting work DL");
|
||||
return false;
|
||||
}
|
||||
|
||||
|
|
Loading…
Reference in New Issue