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
|
* @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
|
||||||
|
@ -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
|
* @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
|
* if the configuration is invalid
|
||||||
*/
|
*/
|
||||||
SRSRAN_API int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
|
SRSRAN_API 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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Performs measurements of ZP-CSI-RS resource set for CSI reports
|
* @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
|
* @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
|
* the configuration is invalid
|
||||||
*/
|
*/
|
||||||
SRSRAN_API int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
|
SRSRAN_API 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);
|
||||||
|
|
||||||
#endif // SRSRAN_CSI_RS_H_
|
#endif // SRSRAN_CSI_RS_H_
|
||||||
|
|
|
@ -15,11 +15,20 @@
|
||||||
|
|
||||||
#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);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Generates CSI report configuration and values from the higher layer configuration and a list of measurements
|
* @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
|
* @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
|
||||||
uint32_t slot_idx,
|
srsran_csi_generate_reports(const srsran_csi_hl_cfg_t* cfg,
|
||||||
const srsran_csi_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
uint32_t slot_idx,
|
||||||
srsran_csi_report_cfg_t report_cfg[SRSRAN_CSI_MAX_NOF_REPORT],
|
const srsran_csi_channel_measurements_t measurements[SRSRAN_CSI_MAX_NOF_RESOURCES],
|
||||||
srsran_csi_report_value_t report_value[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]);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @brief Compute number of CSI bits necessary to transmit all the CSI reports for a PUCCH transmission
|
* @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;
|
} 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;
|
||||||
}
|
}
|
||||||
|
@ -732,11 +736,11 @@ int srsran_csi_rs_nzp_measure_trs(const srsran_carrier_nr_t* carrier,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srsran_csi_rs_nzp_measure_channel(const srsran_carrier_nr_t* carrier,
|
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
|
||||||
|
@ -909,11 +911,11 @@ static int csi_rs_zp_measure_set(const srsran_carrier_nr_t* carrier,
|
||||||
return count;
|
return count;
|
||||||
}
|
}
|
||||||
|
|
||||||
int srsran_csi_rs_zp_measure_channel(const srsran_carrier_nr_t* carrier,
|
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;
|
||||||
|
|
||||||
|
@ -972,4 +974,4 @@ uint32_t srsran_csi_rs_measure_info(const srsran_csi_rs_nzp_measure_t* measure,
|
||||||
}
|
}
|
||||||
|
|
||||||
return len;
|
return len;
|
||||||
}
|
}
|
||||||
|
|
|
@ -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,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));
|
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
|
||||||
if (slot_cfg.idx == 11 || slot_cfg.idx == 12) {
|
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;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
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)
|
||||||
{
|
{
|
||||||
// Take SNR by default
|
// Take SNR by default
|
||||||
float wideband_sinr_db = channel_meas->wideband_snr_db;
|
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(
|
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) {
|
||||||
return SRSRAN_ERROR_INVALID_INPUTS;
|
return SRSRAN_ERROR_INVALID_INPUTS;
|
||||||
|
@ -190,11 +190,11 @@ int srsran_csi_new_nzp_csi_rs_measurement(
|
||||||
return SRSRAN_SUCCESS;
|
return SRSRAN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
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])
|
||||||
{
|
{
|
||||||
uint32_t count = 0;
|
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);
|
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,14 +839,26 @@ 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;
|
||||||
}
|
}
|
||||||
|
|
||||||
return srsran_csi_rs_nzp_measure_channel(&q->carrier, slot_cfg, csi_rs_nzp_set, q->sf_symbols[0], measurement);
|
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_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
|
||||||
|
|
|
@ -57,8 +57,8 @@ private:
|
||||||
mutable std::mutex metrics_mutex;
|
mutable std::mutex metrics_mutex;
|
||||||
|
|
||||||
/// 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) {
|
||||||
phy->new_nzp_csi_rs_channel_measurement(measurements, resource_set_id);
|
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;
|
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…
Reference in New Issue