mirror of https://github.com/PentHertz/srsLTE.git
Store PUSCH CSI from PUSCH DMRS
This commit is contained in:
parent
82ae0e6c37
commit
1bdb1bb62d
|
@ -268,7 +268,7 @@ public:
|
|||
srsran::unique_byte_buffer_t pdu = nullptr;
|
||||
|
||||
// PUSCH signal measurements
|
||||
// ...
|
||||
srsran_csi_trs_measurements_t csi; ///< DMRS based signal Channel State Information (CSI)
|
||||
};
|
||||
|
||||
struct rach_info_t {
|
||||
|
|
|
@ -50,6 +50,8 @@ typedef struct {
|
|||
cf_t* temp; /// Temporal data vector of size SRSRAN_NRE * carrier.nof_prb
|
||||
|
||||
float* filter; ///< Smoothing filter
|
||||
|
||||
srsran_csi_trs_measurements_t csi; ///< Last estimated channel state information
|
||||
} srsran_dmrs_sch_t;
|
||||
|
||||
/**
|
||||
|
|
|
@ -808,7 +808,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
|||
sync_err += srsran_vec_estimate_frequency(&q->pilot_estimates[nof_pilots_x_symbol * i], nof_pilots_x_symbol);
|
||||
}
|
||||
sync_err /= (float)nof_symbols;
|
||||
chest_res->sync_error = sync_err / (dmrs_stride * SRSRAN_SUBC_SPACING_NR(q->carrier.scs));
|
||||
float delay_us = sync_err / (dmrs_stride * SRSRAN_SUBC_SPACING_NR(q->carrier.scs));
|
||||
|
||||
#if DMRS_SCH_SYNC_PRECOMPENSATE
|
||||
// Pre-compensate synchronization error
|
||||
|
@ -836,36 +836,52 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
|||
epre /= nof_symbols;
|
||||
rsrp = SRSRAN_MIN(rsrp, epre - epre * 1e-7);
|
||||
|
||||
chest_res->rsrp = rsrp;
|
||||
chest_res->rsrp_dbm = srsran_convert_power_to_dB(chest_res->rsrp);
|
||||
|
||||
chest_res->noise_estimate = epre - rsrp;
|
||||
chest_res->noise_estimate_dbm = srsran_convert_power_to_dB(chest_res->noise_estimate);
|
||||
|
||||
chest_res->snr_db = chest_res->rsrp_dbm - chest_res->noise_estimate_dbm;
|
||||
|
||||
// Measure CFO if more than one symbol is used
|
||||
float cfo_avg = 0.0;
|
||||
float cfo_avg_hz = 0.0;
|
||||
float cfo_hz_max = INFINITY;
|
||||
for (uint32_t i = 0; i < nof_symbols - 1; i++) {
|
||||
float time_diff = srsran_symbol_distance_s(symbols[i], symbols[i + 1], q->carrier.scs);
|
||||
float phase_diff = cargf(corr[i + 1] * conjf(corr[i]));
|
||||
|
||||
if (isnormal(time_diff)) {
|
||||
cfo_avg += phase_diff / (2.0f * M_PI * time_diff * (nof_symbols - 1));
|
||||
cfo_avg_hz += phase_diff / (2.0f * M_PI * time_diff * (nof_symbols - 1));
|
||||
|
||||
// The maximum measured CFO depends on the symbol time difference
|
||||
cfo_hz_max = SRSRAN_MIN(cfo_hz_max, 1 / time_diff);
|
||||
}
|
||||
}
|
||||
chest_res->cfo = cfo_avg;
|
||||
|
||||
// Store internal CSI
|
||||
q->csi.rsrp = rsrp;
|
||||
q->csi.rsrp_dB = srsran_convert_power_to_dB(rsrp);
|
||||
q->csi.epre = epre;
|
||||
q->csi.epre_dB = srsran_convert_power_to_dB(epre);
|
||||
q->csi.n0 = epre - rsrp;
|
||||
q->csi.n0_dB = srsran_convert_power_to_dB(q->csi.n0);
|
||||
q->csi.snr_dB = q->csi.rsrp_dB - q->csi.n0_dB;
|
||||
q->csi.cfo_hz = cfo_avg_hz;
|
||||
q->csi.cfo_hz_max = cfo_hz_max;
|
||||
q->csi.delay_us = delay_us;
|
||||
|
||||
// Write CSI in estimated channel result
|
||||
chest_res->rsrp = q->csi.rsrp;
|
||||
chest_res->rsrp_dbm = q->csi.rsrp_dB;
|
||||
chest_res->noise_estimate = q->csi.n0;
|
||||
chest_res->noise_estimate_dbm = q->csi.n0_dB;
|
||||
chest_res->snr_db = q->csi.snr_dB;
|
||||
chest_res->cfo = q->csi.cfo_hz;
|
||||
chest_res->sync_error = q->csi.delay_us;
|
||||
|
||||
#if DMRS_SCH_CFO_PRECOMPENSATE
|
||||
// Pre-compensate CFO
|
||||
cf_t cfo_correction[SRSRAN_NSYMB_PER_SLOT_NR] = {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1};
|
||||
if (isnormal(cfo_avg)) {
|
||||
if (isnormal(cfo_avg_hz)) {
|
||||
// Calculate phase of the first OFDM symbol (l = 0)
|
||||
float arg0 = cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.scs) * cfo_avg;
|
||||
float arg0 = cargf(corr[0]) - 2.0f * M_PI * srsran_symbol_distance_s(0, symbols[0], q->carrier.scs) * cfo_avg_hz;
|
||||
|
||||
// Calculate CFO corrections
|
||||
for (uint32_t l = 0; l < SRSRAN_NSYMB_PER_SLOT_NR; l++) {
|
||||
float arg = arg0 + 2.0f * M_PI * cfo_avg * srsran_symbol_distance_s(0, l, q->carrier.scs);
|
||||
float arg = arg0 + 2.0f * M_PI * cfo_avg_hz * srsran_symbol_distance_s(0, l, q->carrier.scs);
|
||||
cfo_correction[l] = cexpf(I * arg);
|
||||
}
|
||||
|
||||
|
@ -883,7 +899,7 @@ int srsran_dmrs_sch_estimate(srsran_dmrs_sch_t* q,
|
|||
INFO("PDSCH-DMRS: RSRP=%+.2fdB EPRE=%+.2fdB CFO=%+.0fHz Sync=%.3fus",
|
||||
chest_res->rsrp_dbm,
|
||||
srsran_convert_power_to_dB(epre),
|
||||
cfo_avg,
|
||||
cfo_avg_hz,
|
||||
chest_res->sync_error * 1e6);
|
||||
|
||||
// Average over time, only if more than one DMRS symbol
|
||||
|
|
|
@ -224,6 +224,9 @@ bool slot_worker::work_ul()
|
|||
return false;
|
||||
}
|
||||
|
||||
// Extract DMRS information
|
||||
pusch_info.csi = gnb_ul.dmrs.csi;
|
||||
|
||||
// Inform stack
|
||||
if (stack.pusch_info(ul_slot_cfg, pusch_info) < SRSRAN_SUCCESS) {
|
||||
logger.error("Error pushing PUSCH information to stack");
|
||||
|
|
|
@ -61,6 +61,7 @@ public:
|
|||
uint32_t cqi_count = 0; ///< CQI opportunity counter
|
||||
uint32_t cqi_valid_count = 0; ///< Valid CQI counter
|
||||
pucch_metrics_t pucch = {};
|
||||
pucch_metrics_t pusch = {};
|
||||
};
|
||||
|
||||
private:
|
||||
|
@ -662,6 +663,21 @@ public:
|
|||
metrics.mac.rx_brate += rx_harq_proc[pusch_info.pid].get_tbs();
|
||||
metrics.mac.rx_pkts++;
|
||||
|
||||
// Handle PHY metrics
|
||||
metrics.pusch.epre_db_avg = SRSRAN_VEC_CMA(pusch_info.csi.epre_dB, metrics.pusch.epre_db_avg, metrics.pusch.count);
|
||||
metrics.pusch.epre_db_min = SRSRAN_MIN(metrics.pusch.epre_db_min, pusch_info.csi.epre_dB);
|
||||
metrics.pusch.epre_db_max = SRSRAN_MAX(metrics.pusch.epre_db_max, pusch_info.csi.epre_dB);
|
||||
metrics.pusch.rsrp_db_avg = SRSRAN_VEC_CMA(pusch_info.csi.rsrp_dB, metrics.pusch.rsrp_db_avg, metrics.pusch.count);
|
||||
metrics.pusch.rsrp_db_min = SRSRAN_MIN(metrics.pusch.rsrp_db_min, pusch_info.csi.rsrp_dB);
|
||||
metrics.pusch.rsrp_db_max = SRSRAN_MAX(metrics.pusch.rsrp_db_max, pusch_info.csi.rsrp_dB);
|
||||
metrics.pusch.snr_db_avg = SRSRAN_VEC_CMA(pusch_info.csi.snr_dB, metrics.pusch.snr_db_avg, metrics.pusch.count);
|
||||
metrics.pusch.snr_db_min = SRSRAN_MIN(metrics.pusch.snr_db_min, pusch_info.csi.snr_dB);
|
||||
metrics.pusch.snr_db_max = SRSRAN_MAX(metrics.pusch.snr_db_max, pusch_info.csi.snr_dB);
|
||||
metrics.pusch.ta_us_avg = SRSRAN_VEC_CMA(pusch_info.csi.delay_us, metrics.pusch.ta_us_avg, metrics.pusch.count);
|
||||
metrics.pusch.ta_us_min = SRSRAN_MIN(metrics.pusch.ta_us_min, pusch_info.csi.delay_us);
|
||||
metrics.pusch.ta_us_max = SRSRAN_MAX(metrics.pusch.ta_us_max, pusch_info.csi.delay_us);
|
||||
metrics.pusch.count++;
|
||||
|
||||
return SRSRAN_SUCCESS;
|
||||
}
|
||||
|
||||
|
|
|
@ -194,9 +194,9 @@ int main(int argc, char** argv)
|
|||
test_bench::metrics_t metrics = tb.get_metrics();
|
||||
|
||||
// Print PDSCH metrics if scheduled
|
||||
double pdsch_bler = 0.0;
|
||||
if (metrics.gnb_stack.mac.tx_pkts > 0) {
|
||||
pdsch_bler = (double)metrics.gnb_stack.mac.tx_errors / (double)metrics.gnb_stack.mac.tx_pkts;
|
||||
float pdsch_bler = 0.0f;
|
||||
pdsch_bler = (float)metrics.gnb_stack.mac.tx_errors / (float)metrics.gnb_stack.mac.tx_pkts;
|
||||
|
||||
float pdsch_shed_rate = 0.0f;
|
||||
pdsch_shed_rate = (float)metrics.gnb_stack.mac.tx_brate / (float)metrics.gnb_stack.mac.tx_pkts / 1000.0f;
|
||||
|
@ -215,10 +215,10 @@ int main(int argc, char** argv)
|
|||
}
|
||||
|
||||
// Print PUSCH metrics if scheduled
|
||||
double pusch_bler = 0.0;
|
||||
if (metrics.gnb_stack.mac.rx_pkts > 0) {
|
||||
float pusch_bler = 0.0f;
|
||||
if (metrics.gnb_stack.mac.rx_pkts != 0) {
|
||||
pusch_bler = (double)metrics.gnb_stack.mac.rx_errors / (double)metrics.gnb_stack.mac.rx_pkts;
|
||||
pusch_bler = (float)metrics.gnb_stack.mac.rx_errors / (float)metrics.gnb_stack.mac.rx_pkts;
|
||||
}
|
||||
|
||||
float pusch_shed_rate = 0.0f;
|
||||
|
@ -295,6 +295,73 @@ int main(int argc, char** argv)
|
|||
srsran::console(" +------------+------------+------------+------------+\n");
|
||||
}
|
||||
|
||||
// Print PDSCH metrics if scheduled
|
||||
double pdsch_bler = 0.0;
|
||||
if (metrics.gnb_stack.mac.tx_pkts > 0) {
|
||||
pdsch_bler = (double)metrics.gnb_stack.mac.tx_errors / (double)metrics.gnb_stack.mac.tx_pkts;
|
||||
|
||||
float pdsch_shed_rate = 0.0f;
|
||||
pdsch_shed_rate = (float)metrics.gnb_stack.mac.tx_brate / (float)metrics.gnb_stack.mac.tx_pkts / 1000.0f;
|
||||
|
||||
srsran::console("PDSCH:\n");
|
||||
srsran::console(" Count: %d\n", metrics.gnb_stack.mac.tx_pkts);
|
||||
srsran::console(" BLER: %f\n", pdsch_bler);
|
||||
srsran::console(" Sched Rate: %f Mbps\n", pdsch_shed_rate);
|
||||
srsran::console(" Net Rate: %f Mbps\n", (1.0f - pdsch_bler) * pdsch_shed_rate);
|
||||
srsran::console(" Retx Rate: %f Mbps\n", pdsch_bler * pdsch_shed_rate);
|
||||
srsran::console("\n");
|
||||
}
|
||||
|
||||
// Print PUSCH metrics if scheduled
|
||||
double pusch_bler = 0.0;
|
||||
if (metrics.gnb_stack.mac.rx_pkts > 0) {
|
||||
if (metrics.gnb_stack.mac.rx_pkts != 0) {
|
||||
pusch_bler = (double)metrics.gnb_stack.mac.rx_errors / (double)metrics.gnb_stack.mac.rx_pkts;
|
||||
}
|
||||
|
||||
float pusch_shed_rate = 0.0f;
|
||||
if (metrics.gnb_stack.mac.rx_pkts != 0) {
|
||||
pusch_shed_rate = (float)metrics.gnb_stack.mac.rx_brate / (float)metrics.gnb_stack.mac.rx_pkts / 1000.0f;
|
||||
}
|
||||
|
||||
srsran::console("PUSCH:\n");
|
||||
srsran::console(" Count: %d\n", metrics.gnb_stack.mac.rx_pkts);
|
||||
srsran::console(" BLER: %f\n", pusch_bler);
|
||||
srsran::console(" Sched Rate: %f Mbps\n", pusch_shed_rate);
|
||||
srsran::console(" Net Rate: %f Mbps\n", (1.0f - pusch_bler) * pusch_shed_rate);
|
||||
srsran::console(" Retx Rate: %f Mbps\n", pusch_bler * pusch_shed_rate);
|
||||
srsran::console("\n");
|
||||
}
|
||||
|
||||
// Print PUSCH
|
||||
if (metrics.gnb_stack.pusch.count > 0) {
|
||||
srsran::console("PUSCH DMRS Receiver metrics:\n");
|
||||
srsran::console(" +------------+------------+------------+------------+\n");
|
||||
srsran::console(" | %10s | %10s | %10s | %10s |\n", "Measure", "Average", "Min", "Max");
|
||||
srsran::console(" +------------+------------+------------+------------+\n");
|
||||
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
|
||||
"EPRE (dB)",
|
||||
metrics.gnb_stack.pusch.epre_db_avg,
|
||||
metrics.gnb_stack.pusch.epre_db_min,
|
||||
metrics.gnb_stack.pusch.epre_db_min);
|
||||
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
|
||||
"RSRP (dB)",
|
||||
metrics.gnb_stack.pusch.rsrp_db_avg,
|
||||
metrics.gnb_stack.pusch.rsrp_db_min,
|
||||
metrics.gnb_stack.pusch.rsrp_db_max);
|
||||
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
|
||||
"SINR (dB)",
|
||||
metrics.gnb_stack.pusch.snr_db_avg,
|
||||
metrics.gnb_stack.pusch.snr_db_min,
|
||||
metrics.gnb_stack.pusch.snr_db_max);
|
||||
srsran::console(" | %10s | %+10.2f | %+10.2f | %+10.2f |\n",
|
||||
"TA (us)",
|
||||
metrics.gnb_stack.pusch.ta_us_avg,
|
||||
metrics.gnb_stack.pusch.ta_us_min,
|
||||
metrics.gnb_stack.pusch.ta_us_max);
|
||||
srsran::console(" +------------+------------+------------+------------+\n");
|
||||
}
|
||||
|
||||
srsran::console("UCI stats:\n");
|
||||
srsran::console(" +------------+------------+------------+------------+------------+\n");
|
||||
srsran::console(
|
||||
|
|
Loading…
Reference in New Issue