mirror of https://github.com/PentHertz/srsLTE.git
Added UE synchronization error metric (hard-coded disabled by default)
This commit is contained in:
parent
06a9d8eb6f
commit
a1a797589a
|
@ -63,6 +63,7 @@ typedef struct SRSLTE_API {
|
||||||
float rsrq_ant_port_db[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
float rsrq_ant_port_db[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||||
float rssi_dbm;
|
float rssi_dbm;
|
||||||
float cfo;
|
float cfo;
|
||||||
|
float sync_error;
|
||||||
} srslte_chest_dl_res_t;
|
} srslte_chest_dl_res_t;
|
||||||
|
|
||||||
typedef enum SRSLTE_API {
|
typedef enum SRSLTE_API {
|
||||||
|
@ -98,6 +99,7 @@ typedef struct SRSLTE_API {
|
||||||
float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
float rsrp[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||||
float rsrp_corr[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
float rsrp_corr[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||||
float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
float noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||||
|
float sync_err[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS];
|
||||||
float cfo;
|
float cfo;
|
||||||
|
|
||||||
/* Use PSS for noise estimation in LS linear interpolation mode */
|
/* Use PSS for noise estimation in LS linear interpolation mode */
|
||||||
|
@ -118,6 +120,7 @@ typedef struct SRSLTE_API {
|
||||||
bool rsrp_neighbour;
|
bool rsrp_neighbour;
|
||||||
bool cfo_estimate_enable;
|
bool cfo_estimate_enable;
|
||||||
uint32_t cfo_estimate_sf_mask;
|
uint32_t cfo_estimate_sf_mask;
|
||||||
|
bool sync_error_enable;
|
||||||
|
|
||||||
} srslte_chest_dl_cfg_t;
|
} srslte_chest_dl_cfg_t;
|
||||||
|
|
||||||
|
|
|
@ -691,6 +691,19 @@ static int estimate_port(srslte_chest_dl_t* q,
|
||||||
srslte_vec_prod_conj_ccc(
|
srslte_vec_prod_conj_ccc(
|
||||||
q->pilot_recv_signal, q->csr_refs.pilots[port_id / 2][sf->tti % 10], q->pilot_estimates, npilots);
|
q->pilot_recv_signal, q->csr_refs.pilots[port_id / 2][sf->tti % 10], q->pilot_estimates, npilots);
|
||||||
|
|
||||||
|
// Estimate synchronization error
|
||||||
|
if (cfg->sync_error_enable) {
|
||||||
|
uint32_t nsymb = srslte_refsignal_cs_nof_symbols(&q->csr_refs, sf, port_id);
|
||||||
|
float k = (float)srslte_symbol_sz(q->cell.nof_prb) / 6.0f;
|
||||||
|
float sum = 0.0f;
|
||||||
|
for (uint32_t i = 0; i < nsymb; i++) {
|
||||||
|
sum += srslte_vec_estimate_frequency(q->pilot_estimates + i * npilots / nsymb, npilots / nsymb) * k;
|
||||||
|
}
|
||||||
|
q->sync_err[rxant_id][port_id] = sum / nsymb;
|
||||||
|
} else {
|
||||||
|
q->sync_err[rxant_id][port_id] = NAN;
|
||||||
|
}
|
||||||
|
|
||||||
/* Compute RSRP for the channel estimates in this port */
|
/* Compute RSRP for the channel estimates in this port */
|
||||||
if (cfg->rsrp_neighbour) {
|
if (cfg->rsrp_neighbour) {
|
||||||
double energy = cabs(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots);
|
double energy = cabs(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots);
|
||||||
|
@ -843,6 +856,7 @@ static void fill_res(srslte_chest_dl_t* q, srslte_chest_dl_res_t* res)
|
||||||
res->rsrq_db = db(res->rsrq);
|
res->rsrq_db = db(res->rsrq);
|
||||||
res->snr_db = db(get_snr(q));
|
res->snr_db = db(get_snr(q));
|
||||||
res->rssi_dbm = dbm(get_rssi(q));
|
res->rssi_dbm = dbm(get_rssi(q));
|
||||||
|
res->sync_error = q->sync_err[0][0]; // Take only the channel used for synch
|
||||||
|
|
||||||
for (uint32_t port_id = 0; port_id < q->cell.nof_ports; port_id++) {
|
for (uint32_t port_id = 0; port_id < q->cell.nof_ports; port_id++) {
|
||||||
res->rsrp_port_dbm[port_id] = dbm(get_rsrp_port(q, port_id));
|
res->rsrp_port_dbm[port_id] = dbm(get_rsrp_port(q, port_id));
|
||||||
|
|
|
@ -44,6 +44,7 @@ struct dl_metrics_t
|
||||||
float turbo_iters;
|
float turbo_iters;
|
||||||
float mcs;
|
float mcs;
|
||||||
float pathloss;
|
float pathloss;
|
||||||
|
float sync_err;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct ul_metrics_t
|
struct ul_metrics_t
|
||||||
|
|
|
@ -61,6 +61,7 @@ public:
|
||||||
void set_crnti(uint16_t rnti);
|
void set_crnti(uint16_t rnti);
|
||||||
void enable_pregen_signals(bool enabled);
|
void enable_pregen_signals(bool enabled);
|
||||||
|
|
||||||
|
/* Methods for plotting */
|
||||||
int read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna);
|
int read_ce_abs(float* ce_abs, uint32_t tx_antenna, uint32_t rx_antenna);
|
||||||
uint32_t get_cell_nof_ports()
|
uint32_t get_cell_nof_ports()
|
||||||
{
|
{
|
||||||
|
@ -72,6 +73,8 @@ public:
|
||||||
}
|
}
|
||||||
uint32_t get_rx_nof_antennas() { return phy->args->nof_rx_ant; }
|
uint32_t get_rx_nof_antennas() { return phy->args->nof_rx_ant; }
|
||||||
int read_pdsch_d(cf_t* pdsch_d);
|
int read_pdsch_d(cf_t* pdsch_d);
|
||||||
|
float get_sync_error();
|
||||||
|
float get_cfo();
|
||||||
void start_plot();
|
void start_plot();
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
|
|
@ -652,6 +652,7 @@ void cc_worker::update_measurements()
|
||||||
dl_metrics.rssi = phy->avg_rssi_dbm;
|
dl_metrics.rssi = phy->avg_rssi_dbm;
|
||||||
dl_metrics.pathloss = phy->pathloss[cc_idx];
|
dl_metrics.pathloss = phy->pathloss[cc_idx];
|
||||||
dl_metrics.sinr = phy->avg_snr_db_cqi[cc_idx];
|
dl_metrics.sinr = phy->avg_snr_db_cqi[cc_idx];
|
||||||
|
dl_metrics.sync_err = ue_dl.chest_res.sync_error;
|
||||||
|
|
||||||
phy->set_dl_metrics(dl_metrics, cc_idx);
|
phy->set_dl_metrics(dl_metrics, cc_idx);
|
||||||
phy->set_ul_metrics(ul_metrics, cc_idx);
|
phy->set_ul_metrics(ul_metrics, cc_idx);
|
||||||
|
|
|
@ -154,6 +154,7 @@ void phy_common::set_ue_dl_cfg(srslte_ue_dl_cfg_t* ue_dl_cfg)
|
||||||
}
|
}
|
||||||
|
|
||||||
chest_cfg->rsrp_neighbour = false;
|
chest_cfg->rsrp_neighbour = false;
|
||||||
|
chest_cfg->sync_error_enable = false;
|
||||||
chest_cfg->interpolate_subframe = args->interpolate_subframe_enabled;
|
chest_cfg->interpolate_subframe = args->interpolate_subframe_enabled;
|
||||||
chest_cfg->cfo_estimate_enable = args->cfo_ref_mask != 0;
|
chest_cfg->cfo_estimate_enable = args->cfo_ref_mask != 0;
|
||||||
chest_cfg->cfo_estimate_sf_mask = args->cfo_ref_mask;
|
chest_cfg->cfo_estimate_sf_mask = args->cfo_ref_mask;
|
||||||
|
@ -610,6 +611,8 @@ void phy_common::set_dl_metrics(const dl_metrics_t m, uint32_t cc_idx)
|
||||||
dl_metrics[cc_idx].rssi = dl_metrics[cc_idx].rssi + (m.rssi - dl_metrics[cc_idx].rssi) / dl_metrics_count;
|
dl_metrics[cc_idx].rssi = dl_metrics[cc_idx].rssi + (m.rssi - dl_metrics[cc_idx].rssi) / dl_metrics_count;
|
||||||
dl_metrics[cc_idx].rsrp = dl_metrics[cc_idx].rsrp + (m.rsrp - dl_metrics[cc_idx].rsrp) / dl_metrics_count;
|
dl_metrics[cc_idx].rsrp = dl_metrics[cc_idx].rsrp + (m.rsrp - dl_metrics[cc_idx].rsrp) / dl_metrics_count;
|
||||||
dl_metrics[cc_idx].sinr = dl_metrics[cc_idx].sinr + (m.sinr - dl_metrics[cc_idx].sinr) / dl_metrics_count;
|
dl_metrics[cc_idx].sinr = dl_metrics[cc_idx].sinr + (m.sinr - dl_metrics[cc_idx].sinr) / dl_metrics_count;
|
||||||
|
dl_metrics[cc_idx].sync_err =
|
||||||
|
dl_metrics[cc_idx].sync_err + (m.sync_err - dl_metrics[cc_idx].sync_err) / dl_metrics_count;
|
||||||
dl_metrics[cc_idx].pathloss =
|
dl_metrics[cc_idx].pathloss =
|
||||||
dl_metrics[cc_idx].pathloss + (m.pathloss - dl_metrics[cc_idx].pathloss) / dl_metrics_count;
|
dl_metrics[cc_idx].pathloss + (m.pathloss - dl_metrics[cc_idx].pathloss) / dl_metrics_count;
|
||||||
dl_metrics[cc_idx].turbo_iters =
|
dl_metrics[cc_idx].turbo_iters =
|
||||||
|
|
|
@ -395,7 +395,19 @@ int sf_worker::read_pdsch_d(cf_t* pdsch_d)
|
||||||
{
|
{
|
||||||
return cc_workers[0]->read_pdsch_d(pdsch_d);
|
return cc_workers[0]->read_pdsch_d(pdsch_d);
|
||||||
}
|
}
|
||||||
|
float sf_worker::get_sync_error()
|
||||||
|
{
|
||||||
|
dl_metrics_t dl_metrics[SRSLTE_MAX_CARRIERS] = {};
|
||||||
|
phy->get_dl_metrics(dl_metrics);
|
||||||
|
return dl_metrics->sync_err;
|
||||||
|
}
|
||||||
|
|
||||||
|
float sf_worker::get_cfo()
|
||||||
|
{
|
||||||
|
sync_metrics_t sync_metrics = {};
|
||||||
|
phy->get_sync_metrics(sync_metrics);
|
||||||
|
return sync_metrics.cfo;
|
||||||
|
}
|
||||||
} // namespace srsue
|
} // namespace srsue
|
||||||
|
|
||||||
/***********************************************************
|
/***********************************************************
|
||||||
|
@ -419,9 +431,17 @@ static uint32_t icfo = 0;
|
||||||
static float cfo_buffer[CFO_PLOT_LEN];
|
static float cfo_buffer[CFO_PLOT_LEN];
|
||||||
#endif /* CFO_PLOT_LEN > 0 */
|
#endif /* CFO_PLOT_LEN > 0 */
|
||||||
|
|
||||||
|
#define SYNC_PLOT_LEN 0 /* Set to non zero for enabling Sync error plot */
|
||||||
|
#if SYNC_PLOT_LEN > 0
|
||||||
|
static plot_real_t psync;
|
||||||
|
static uint32_t isync = 0;
|
||||||
|
static float sync_buffer[SYNC_PLOT_LEN];
|
||||||
|
#endif /* SYNC_PLOT_LEN > 0 */
|
||||||
|
|
||||||
void* plot_thread_run(void* arg)
|
void* plot_thread_run(void* arg)
|
||||||
{
|
{
|
||||||
srsue::sf_worker* worker = (srsue::sf_worker*)arg;
|
srsue::sf_worker* worker = (srsue::sf_worker*)arg;
|
||||||
|
uint32_t row_count = 0;
|
||||||
|
|
||||||
sdrgui_init();
|
sdrgui_init();
|
||||||
for (uint32_t tx = 0; tx < worker->get_cell_nof_ports(); tx++) {
|
for (uint32_t tx = 0; tx < worker->get_cell_nof_ports(); tx++) {
|
||||||
|
@ -436,13 +456,14 @@ void* plot_thread_run(void* arg)
|
||||||
plot_real_addToWindowGrid(&pce[tx][rx], (char*)"srsue", tx, rx);
|
plot_real_addToWindowGrid(&pce[tx][rx], (char*)"srsue", tx, rx);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
row_count = worker->get_rx_nof_antennas();
|
||||||
|
|
||||||
plot_scatter_init(&pconst);
|
plot_scatter_init(&pconst);
|
||||||
plot_scatter_setTitle(&pconst, (char*)"PDSCH - Equalized Symbols");
|
plot_scatter_setTitle(&pconst, (char*)"PDSCH - Equalized Symbols");
|
||||||
plot_scatter_setXAxisScale(&pconst, -4, 4);
|
plot_scatter_setXAxisScale(&pconst, -4, 4);
|
||||||
plot_scatter_setYAxisScale(&pconst, -4, 4);
|
plot_scatter_setYAxisScale(&pconst, -4, 4);
|
||||||
|
|
||||||
plot_scatter_addToWindowGrid(&pconst, (char*)"srsue", 0, worker->get_rx_nof_antennas());
|
plot_scatter_addToWindowGrid(&pconst, (char*)"srsue", 0, row_count);
|
||||||
|
|
||||||
#if CFO_PLOT_LEN > 0
|
#if CFO_PLOT_LEN > 0
|
||||||
plot_real_init(&pcfo);
|
plot_real_init(&pcfo);
|
||||||
|
@ -450,9 +471,18 @@ void* plot_thread_run(void* arg)
|
||||||
plot_real_setLabels(&pcfo, (char*)"Time", (char*)"Hz");
|
plot_real_setLabels(&pcfo, (char*)"Time", (char*)"Hz");
|
||||||
plot_real_setYAxisScale(&pcfo, -4000, 4000);
|
plot_real_setYAxisScale(&pcfo, -4000, 4000);
|
||||||
|
|
||||||
plot_scatter_addToWindowGrid(&pcfo, (char*)"srsue", 1, worker->get_rx_nof_antennas());
|
plot_scatter_addToWindowGrid(&pcfo, (char*)"srsue", 1, row_count++);
|
||||||
#endif /* CFO_PLOT_LEN > 0 */
|
#endif /* CFO_PLOT_LEN > 0 */
|
||||||
|
|
||||||
|
#if SYNC_PLOT_LEN > 0
|
||||||
|
plot_real_init(&psync);
|
||||||
|
plot_real_setTitle(&psync, (char*)"Sync error (in samples)");
|
||||||
|
plot_real_setLabels(&psync, (char*)"Time", (char*)"Error");
|
||||||
|
plot_real_setYAxisScale(&psync, -2, +2);
|
||||||
|
|
||||||
|
plot_scatter_addToWindowGrid(&psync, (char*)"srsue", 1, row_count++);
|
||||||
|
#endif /* SYNC_PLOT_LEN > 0 */
|
||||||
|
|
||||||
int n;
|
int n;
|
||||||
int readed_pdsch_re = 0;
|
int readed_pdsch_re = 0;
|
||||||
while (1) {
|
while (1) {
|
||||||
|
|
Loading…
Reference in New Issue