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

This commit is contained in:
Xavier Arteaga 2021-05-05 15:52:07 +02:00 committed by Xavier Arteaga
parent fd0d804321
commit 1396c2a1e2
11 changed files with 222 additions and 109 deletions

View File

@ -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_

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;
}
}

View File

@ -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) {

View File

@ -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);

View File

@ -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);
}
}

View File

@ -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

View File

@ -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);

View File

@ -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;
}