From 809c550ca2dd0ebae0e1632abc3330004b2c5e2e Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 13 Mar 2018 19:07:15 +0100 Subject: [PATCH] Use RS power estimation for serving cell RSRP/SNR measurements. Use correlation of RS sequences for neighbour cell verification of Cell ID --- .../srslte/phy/ch_estimation/chest_dl.h | 10 ++- lib/src/phy/ch_estimation/chest_dl.c | 42 +++++++++-- srsue/hdr/phy/phch_recv.h | 3 +- srsue/src/phy/phch_recv.cc | 72 ++++++++++++------- 4 files changed, 96 insertions(+), 31 deletions(-) diff --git a/lib/include/srslte/phy/ch_estimation/chest_dl.h b/lib/include/srslte/phy/ch_estimation/chest_dl.h index c1f5579a1..e7cc28bed 100644 --- a/lib/include/srslte/phy/ch_estimation/chest_dl.h +++ b/lib/include/srslte/phy/ch_estimation/chest_dl.h @@ -82,10 +82,13 @@ typedef struct { srslte_interp_lin_t srslte_interp_lin_3; srslte_interp_lin_t srslte_interp_lin_mbsfn; float rssi[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; - 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 noise_estimate[SRSLTE_MAX_PORTS][SRSLTE_MAX_PORTS]; float cfo; + bool rsrp_neighbour; + bool cfo_estimate_enable; uint32_t cfo_estimate_sf_mask; @@ -158,6 +161,9 @@ SRSLTE_API void srslte_chest_dl_cfo_estimate_enable(srslte_chest_dl_t *q, SRSLTE_API void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, bool enable); +SRSLTE_API void srslte_chest_dl_set_rsrp_neighbour(srslte_chest_dl_t *q, + bool rsrp_for_neighbour); + SRSLTE_API float srslte_chest_dl_get_noise_estimate(srslte_chest_dl_t *q); SRSLTE_API float srslte_chest_dl_get_cfo(srslte_chest_dl_t *q); @@ -185,4 +191,6 @@ SRSLTE_API float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, SRSLTE_API float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q); +SRSLTE_API float srslte_chest_dl_get_rsrp_neighbour(srslte_chest_dl_t *q); + #endif diff --git a/lib/src/phy/ch_estimation/chest_dl.c b/lib/src/phy/ch_estimation/chest_dl.c index ec827ec13..8d9125910 100644 --- a/lib/src/phy/ch_estimation/chest_dl.c +++ b/lib/src/phy/ch_estimation/chest_dl.c @@ -152,7 +152,9 @@ int srslte_chest_dl_init(srslte_chest_dl_t *q, uint32_t max_prb) } q->noise_alg = SRSLTE_NOISE_ALG_REFS; - + + q->rsrp_neighbour = false; + q->smooth_filter_len = 3; srslte_chest_dl_set_smooth_filter3_coeff(q, 0.1); @@ -545,7 +547,7 @@ void chest_interpolate_noise_est(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, ui } } -int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id) +int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id) { uint32_t npilots = SRSLTE_REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); @@ -557,14 +559,18 @@ int srslte_chest_dl_estimate_port(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, u q->pilot_estimates, npilots); /* Compute RSRP for the channel estimates in this port */ - double energy = cabs(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots); - q->rsrp[rxant_id][port_id] = energy*energy; + if (q->rsrp_neighbour) { + double energy = cabs(srslte_vec_acc_cc(q->pilot_estimates, npilots)/npilots); + q->rsrp_corr[rxant_id][port_id] = energy*energy; + } + q->rsrp[rxant_id][port_id] = srslte_vec_avg_power_cf(q->pilot_recv_signal, npilots); q->rssi[rxant_id][port_id] = srslte_chest_dl_rssi(q, input, port_id); chest_interpolate_noise_est(q, input, ce, sf_idx, port_id, rxant_id, SRSLTE_SF_NORM); return 0; } + int srslte_chest_dl_estimate_port_mbsfn(srslte_chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id, uint32_t rxant_id, uint16_t mbsfn_area_id) { @@ -623,6 +629,10 @@ int srslte_chest_dl_estimate_multi_mbsfn(srslte_chest_dl_t *q, cf_t *input[SRSLT return SRSLTE_SUCCESS; } +void srslte_chest_dl_set_rsrp_neighbour(srslte_chest_dl_t *q, bool rsrp_for_neighbour) { + q->rsrp_neighbour = rsrp_for_neighbour; +} + void srslte_chest_dl_average_subframe(srslte_chest_dl_t *q, bool enable) { q->average_subframe = enable; @@ -710,6 +720,19 @@ float srslte_chest_dl_get_rsrp_port(srslte_chest_dl_t *q, uint32_t port) { return sum; } +float srslte_chest_dl_get_rsrp_neighbour_port(srslte_chest_dl_t *q, uint32_t port) { + float sum = 0.0f; + for (int j = 0; j < q->cell.nof_ports; ++j) { + sum +=q->rsrp_corr[port][j]; + } + + if (q->cell.nof_ports) { + sum /= q->cell.nof_ports; + } + + return sum; +} + float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) { float max = -0.0f; for (int i = 0; i < q->last_nof_antennas; ++i) { @@ -720,3 +743,14 @@ float srslte_chest_dl_get_rsrp(srslte_chest_dl_t *q) { } return max; } + +float srslte_chest_dl_get_rsrp_neighbour(srslte_chest_dl_t *q) { + float max = -0.0f; + for (int i = 0; i < q->last_nof_antennas; ++i) { + float v = srslte_chest_dl_get_rsrp_neighbour_port(q, i); + if (v > max) { + max = v; + } + } + return max; +} diff --git a/srsue/hdr/phy/phch_recv.h b/srsue/hdr/phy/phch_recv.h index 7a04e4b10..3d00b631b 100644 --- a/srsue/hdr/phy/phch_recv.h +++ b/srsue/hdr/phy/phch_recv.h @@ -171,6 +171,7 @@ private: ret_code run_multiple_subframes(cf_t *buffer, uint32_t offset, uint32_t sf_idx, uint32_t nof_sf); float rssi(); float rsrp(); + float rsrp_n(); float rsrq(); float snr(); uint32_t frame_st_idx(); @@ -183,7 +184,7 @@ private: uint32_t nof_subframes; uint32_t current_prb; float rx_gain_offset; - float mean_rsrp, mean_rsrq, mean_snr, mean_rssi; + float mean_rsrp, mean_rsrp_n, mean_rsrq, mean_snr, mean_rssi; uint32_t final_offset; const static int RSRP_MEASURE_NOF_FRAMES = 5; }; diff --git a/srsue/src/phy/phch_recv.cc b/srsue/src/phy/phch_recv.cc index 850294175..6ec87d2fa 100644 --- a/srsue/src/phy/phch_recv.cc +++ b/srsue/src/phy/phch_recv.cc @@ -1022,6 +1022,7 @@ void phch_recv::measure::init(cf_t *buffer[SRSLTE_MAX_PORTS], srslte::log *log_h Error("SYNC: Initiating ue_dl_measure\n"); return; } + srslte_chest_dl_set_rsrp_neighbour(&ue_dl.chest, true); reset(); } @@ -1054,6 +1055,10 @@ float phch_recv::measure::rsrp() { return 10*log10(mean_rsrp) + 30 - rx_gain_offset; } +float phch_recv::measure::rsrp_n() { + return 10*log10(mean_rsrp_n) + 30 - rx_gain_offset; +} + float phch_recv::measure::rsrq() { return 10*log10(mean_rsrq); } @@ -1099,12 +1104,13 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in sf_idx ++; } + + // Fine-tune offset using RS +#ifdef FINE_TUNE_OFFSET_WITH_RS float max_rsrp = -200; int best_test_offset = 0; int test_offset = 0; bool found_best = false; - - // Fine-tune offset using RS for (uint32_t n=0;n<5;n++) { test_offset = offset-2+n; @@ -1128,11 +1134,14 @@ phch_recv::measure::ret_code phch_recv::measure::run_multiple_subframes(cf_t *in } } + Debug("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf); + offset = found_best?best_test_offset:offset; +#endif + if (offset >= 0 && offset < sf_len*max_sf) { uint32_t nof_sf = (sf_len*max_sf - offset)/sf_len; - Debug("INTRA: fine-tuning offset: %d, found_best=%d, rem_sf=%d\n", offset, found_best, nof_sf); final_offset = offset; @@ -1161,25 +1170,28 @@ phch_recv::measure::ret_code phch_recv::measure::run_subframe(uint32_t sf_idx) } float rsrp = srslte_chest_dl_get_rsrp(&ue_dl.chest); + float rsrp_n = srslte_chest_dl_get_rsrp_neighbour(&ue_dl.chest); float rsrq = srslte_chest_dl_get_rsrq(&ue_dl.chest); float snr = srslte_chest_dl_get_snr(&ue_dl.chest); float rssi = srslte_vec_avg_power_cf(buffer[0], SRSLTE_SF_LEN_PRB(current_prb)); if (cnt == 0) { - mean_rsrp = rsrp; - mean_rsrq = rsrq; - mean_snr = snr; - mean_rssi = rssi; + mean_rsrp = rsrp; + mean_rsrp_n = rsrp_n; + mean_rsrq = rsrq; + mean_snr = snr; + mean_rssi = rssi; } else { - mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); - mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); - mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); - mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt); + mean_rsrp = SRSLTE_VEC_CMA(rsrp, mean_rsrp, cnt); + mean_rsrp_n = SRSLTE_VEC_CMA(rsrp_n, mean_rsrp_n, cnt); + mean_rsrq = SRSLTE_VEC_CMA(rsrq, mean_rsrq, cnt); + mean_snr = SRSLTE_VEC_CMA(snr, mean_snr, cnt); + mean_rssi = SRSLTE_VEC_CMA(rssi, mean_rssi, cnt); } cnt++; - log_h->debug("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, SNR=%.1f dB\n", - cnt, nof_subframes, sf_idx, rsrp, snr); + log_h->debug("SYNC: Measuring RSRP %d/%d, sf_idx=%d, RSRP=%.1f dBm, corr-RSRP=%.1f dBm, SNR=%.1f dB\n", + cnt, nof_subframes, sf_idx, rsrp, rsrp_n, snr); if (cnt >= nof_subframes) { return MEASURE_OK; @@ -1217,6 +1229,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 fprintf(stderr, "Error initiating sync_find\n"); return; } + srslte_sync_set_sss_algorithm(&sync_find, SSS_FULL); srslte_sync_cp_en(&sync_find, false); srslte_sync_set_cfo_pss_enable(&sync_find, true); srslte_sync_set_threshold(&sync_find, 1.7); @@ -1230,8 +1243,7 @@ void phch_recv::scell_recv::init(srslte::log *log_h, bool sic_pss_enabled, uint3 srslte_sync_set_sss_eq_enable(&sync_find, true); sync_find.pss.chest_on_filter = true; - - sync_find.sss_channel_equalize = true; + sync_find.sss_channel_equalize = false; reset(); } @@ -1336,17 +1348,27 @@ int phch_recv::scell_recv::find_cells(cf_t *input_buffer, float rx_gain_offset, case measure::MEASURE_OK: // Consider a cell to be detectable 8.1.2.2.1.1 from 36.133. Currently only using first condition if (measure_p.rsrp() > ABSOLUTE_RSRP_THRESHOLD_DBM) { - cells[nof_cells].pci = found_cell.id; - cells[nof_cells].rsrp = measure_p.rsrp(); - cells[nof_cells].rsrq = measure_p.rsrq(); - cells[nof_cells].offset = measure_p.frame_st_idx(); - - Info( - "INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", - nof_cells, cell_id, measure_p.rsrp(), measure_p.frame_st_idx(), sync_find.peak_value, - sf_idx, max_sf5, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find)); - nof_cells++; + // Check the cell id has been correctly identified by using the correlation of the RS sequences + // By experimentation, typically the cross-correlation is ~3/4 dB less + if (measure_p.rsrp_n() > measure_p.rsrp() - 6) { + cells[nof_cells].pci = found_cell.id; + cells[nof_cells].rsrp = measure_p.rsrp(); + cells[nof_cells].rsrq = measure_p.rsrq(); + cells[nof_cells].offset = measure_p.frame_st_idx(); + + Info( + "INTRA: Found neighbour cell %d: PCI=%03d, RSRP=%5.1f dBm, corr-RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", + nof_cells, cell_id, measure_p.rsrp(), measure_p.rsrp_n(), measure_p.frame_st_idx(), sync_find.peak_value, + sf_idx, max_sf5, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find)); + + nof_cells++; + } else { + Info( + "INTRA: Found phantom cell %d: PCI=%03d, RSRP=%5.1f dBm, corr-RSRP=%5.1f dBm, peak_idx=%5d, peak_value=%3.2f, sf=%d, max_sf=%d, n_id_2=%d, CFO=%6.1f Hz\n", + nof_cells, cell_id, measure_p.rsrp(), measure_p.rsrp_n(), measure_p.frame_st_idx(), sync_find.peak_value, + sf_idx, max_sf5, n_id_2, 15000 * srslte_sync_get_cfo(&sync_find)); + } /* if (sic_pss_enabled) {