From 445fc639e825975ba92f213f33a8ce42796ef67f Mon Sep 17 00:00:00 2001 From: ismagom Date: Wed, 26 Nov 2014 17:24:10 +0000 Subject: [PATCH] Improved UE measurements. Calibrated for gain 40 dB --- lte/examples/cell_measurement.c | 22 ++++--- lte/examples/pdsch_ue.c | 2 +- .../liblte/phy/ch_estimation/chest_dl.h | 2 +- lte/phy/include/liblte/phy/utils/vector.h | 4 +- lte/phy/lib/ch_estimation/src/chest_dl.c | 59 +++++++++++-------- lte/phy/lib/sync/src/sync.c | 33 +++++++---- lte/phy/lib/ue/src/ue_sync.c | 16 ++--- lte/phy/lib/utils/src/vector.c | 7 +-- 8 files changed, 82 insertions(+), 63 deletions(-) diff --git a/lte/examples/cell_measurement.c b/lte/examples/cell_measurement.c index 06a136c51..c59020a1a 100644 --- a/lte/examples/cell_measurement.c +++ b/lte/examples/cell_measurement.c @@ -41,6 +41,11 @@ #include "liblte/cuhd/cuhd.h" #include "cell_search_utils.h" +#define B210_DEFAULT_GAIN 40.0 +#define B210_DEFAULT_GAIN_CORREC 76.0 // Gain of the Rx chain when the gain is set to 40 + +float gain_offset = B210_DEFAULT_GAIN_CORREC; + cell_detect_cfg_t cell_detect_config = { 500, // nof_frames_total 50, // nof_frames_detected @@ -64,7 +69,7 @@ void args_default(prog_args_t *args) { args->force_N_id_2 = -1; // Pick the best args->uhd_args = ""; args->uhd_freq = -1.0; - args->uhd_gain = 60.0; + args->uhd_gain = B210_DEFAULT_GAIN; } void usage(prog_args_t *args, char *prog) { @@ -141,7 +146,7 @@ int main(int argc, char **argv) { int n; uint8_t bch_payload[BCH_PAYLOAD_LEN], bch_payload_unpacked[BCH_PAYLOAD_LEN]; uint32_t sfn_offset; - float rssi=0, rsrp=0, rsrq=0, snr=0; + float rssi_utra=0,rssi=0, rsrp=0, rsrq=0, snr=0; cf_t *nullce[MAX_PORTS]; for (int i=0;i2?2:1; +float chest_dl_rssi(chest_dl_t *q, cf_t *input, uint32_t port_id) { + uint32_t l; - for (p=0;pcell.cp, port_id) * q->cell.nof_prb * RE_X_RB]; + rssi += vec_dot_prod_conj_ccc(tmp,tmp,q->cell.nof_prb * RE_X_RB); + } + return rssi/nsymbols; } float chest_dl_rsrp(chest_dl_t *q, uint32_t port_id) { - return crealf(vec_dot_prod_conj_ccc(q->pilot_estimates_average[port_id], - q->pilot_estimates_average[port_id], - REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id))) - / REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id); + return vec_avg_power_cf(q->pilot_recv_signal[port_id], + REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); } int chest_dl_estimate_port(chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx, uint32_t port_id) @@ -307,16 +302,23 @@ int chest_dl_estimate_port(chest_dl_t *q, cf_t *input, cf_t *ce, uint32_t sf_idx /* Get references from the input signal */ refsignal_cs_get_sf(q->cell, port_id, input, q->pilot_recv_signal[port_id]); + /* Compute RSRP for the references in this port */ + if (port_id == 0) { + q->rsrp[port_id] = chest_dl_rsrp(q, port_id); + } + + /* compute rssi */ + if (port_id == 0) { + q->rssi[port_id] = chest_dl_rssi(q, input, port_id); + } + /* Use the known CSR signal to compute Least-squares estimates */ vec_prod_conj_ccc(q->pilot_recv_signal[port_id], q->csr_signal.pilots[port_id/2][sf_idx], q->pilot_estimates[port_id], REFSIGNAL_NUM_SF(q->cell.nof_prb, port_id)); /* Average pilot estimates */ average_pilots(q, port_id); - - /* Compute RSRP for the references in this port */ - q->rsrp[port_id] = chest_dl_rsrp(q, port_id); - + /* Interpolate to create channel estimates for all resource grid */ if (ce != NULL) { interpolate_pilots(q, ce, port_id); @@ -334,8 +336,6 @@ int chest_dl_estimate(chest_dl_t *q, cf_t *input, cf_t *ce[MAX_PORTS], uint32_t for (port_id=0;port_idcell.nof_ports;port_id++) { chest_dl_estimate_port(q, input, ce[port_id], sf_idx, port_id); } - /* compute rssi */ - q->rssi = chest_dl_rssi(q->cell, input); return LIBLTE_SUCCESS; } @@ -346,21 +346,28 @@ float chest_dl_get_noise_estimate(chest_dl_t *q) { float chest_dl_get_snr(chest_dl_t *q) { float noise = chest_dl_get_noise_estimate(q); if (noise) { - return chest_dl_get_rssi(q)/(noise*2*q->cell.nof_ports*lte_symbol_sz(q->cell.nof_prb)); + return chest_dl_get_rssi(q)/(noise);//*2*q->cell.nof_ports*lte_symbol_sz(q->cell.nof_prb)); } else { return 0.0; } } float chest_dl_get_rssi(chest_dl_t *q) { - return q->rssi; + return 4*q->rssi[0]/q->cell.nof_prb/RE_X_RB; } +/* q->rssi[0] is the average power in all RE in all symbol containing references for port 0 . q->rssi[0]/q->cell.nof_prb is the average power per PRB + * q->rsrp[0] is the average power of RE containing references only (for port 0). +*/ float chest_dl_get_rsrq(chest_dl_t *q) { - return (4*q->cell.nof_ports*q->cell.nof_prb) * chest_dl_get_rsrp(q) / q->rssi; + return q->cell.nof_prb*q->rsrp[0] / q->rssi[0]; } float chest_dl_get_rsrp(chest_dl_t *q) { - return vec_acc_ff(q->rsrp, q->cell.nof_ports)/q->cell.nof_ports; + // return linear average from port 0 only + return q->rsrp[0]; + + // return linear average from all ports + //return vec_acc_ff(q->rsrp, q->cell.nof_ports)/q->cell.nof_ports; } diff --git a/lte/phy/lib/sync/src/sync.c b/lte/phy/lib/sync/src/sync.c index 8ec939d3f..710adc7d9 100644 --- a/lte/phy/lib/sync/src/sync.c +++ b/lte/phy/lib/sync/src/sync.c @@ -34,6 +34,9 @@ #include "liblte/phy/sync/sync.h" #include "liblte/phy/utils/vector.h" +#define MEANENERGY_EMA_ALPHA 0.5 +#define MEANPEAK_EMA_ALPHA 0.2 + static bool fft_size_isvalid(uint32_t fft_size) { if (fft_size >= FFT_SIZE_MIN && fft_size <= FFT_SIZE_MAX && (fft_size%64) == 0) { @@ -55,7 +58,8 @@ int sync_init(sync_t *q, uint32_t frame_size, uint32_t fft_size) { bzero(q, sizeof(sync_t)); q->detect_cp = true; q->normalize_en = true; - q->mean_energy = 1.0; + q->mean_energy = 0.0; + q->mean_peak_value = 0.0; q->sss_en = true; q->N_id_2 = 1000; q->N_id_1 = 1000; @@ -261,22 +265,26 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit return LIBLTE_ERROR; } if (q->normalize_en && - peak_pos < q->frame_size && peak_pos + find_offset >= q->fft_size ) { /* Compute the energy of the received PSS sequence to normalize */ energy = sqrtf(vec_avg_power_cf(&input[find_offset+peak_pos-q->fft_size], q->fft_size)); - q->mean_energy = VEC_CMA(energy, q->mean_energy, q->frame_cnt); + q->mean_energy = VEC_EMA(energy, q->mean_energy, MEANENERGY_EMA_ALPHA); } else { if (q->mean_energy == 0.0) { - q->mean_energy = 1.0; + energy = 1.0; + } else { + energy = q->mean_energy; } - energy = q->mean_energy; } /* Normalize and compute mean peak value */ - q->peak_value = peak_unnormalized/energy; - q->mean_peak_value = VEC_CMA(q->peak_value, q->mean_peak_value, q->frame_cnt); + if (q->mean_energy) { + q->peak_value = peak_unnormalized/q->mean_energy; + } else { + q->peak_value = peak_unnormalized/energy; + } + q->mean_peak_value = VEC_EMA(q->peak_value, q->mean_peak_value, MEANPEAK_EMA_ALPHA); q->frame_cnt++; if (peak_position) { @@ -284,7 +292,7 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit } /* If peak is over threshold, compute CFO and SSS */ - if (q->peak_value >= q->threshold) { + if (q->peak_value >= q->threshold) { // Set an invalid N_id_1 indicating SSS is yet to be detected q->N_id_1 = 1000; @@ -296,9 +304,7 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit } } // Make sure we have enough space to estimate CFO - if (peak_pos < q->frame_size && - peak_pos + find_offset >= q->fft_size) - { + if (peak_pos + find_offset >= q->fft_size) { q->cfo = pss_synch_cfo_compute(&q->pss, &input[find_offset+peak_pos-q->fft_size]); } else { INFO("No space for CFO computation. Frame starts at \n",peak_pos); @@ -309,8 +315,9 @@ int sync_find(sync_t *q, cf_t *input, uint32_t find_offset, uint32_t *peak_posit ret = 0; } - INFO("SYNC ret=%d N_id_2=%d pos=%d peak=%.2f/%.2f=%.2f threshold=%.2f sf_idx=%d offset=%d\n", - ret, q->N_id_2, peak_pos, peak_unnormalized,energy,q->peak_value, q->threshold, q->sf_idx, find_offset); + INFO("SYNC ret=%d N_id_2=%d pos=%d peak=%.2f/%.2f=%.2f mean_energy=%.2f threshold=%.2f sf_idx=%d, CFO=%.3f KHz\n", + ret, q->N_id_2, peak_pos, peak_unnormalized*1000,energy*1000,q->peak_value, q->mean_energy*1000, + q->threshold, q->sf_idx, 15*q->cfo); } else if (lte_N_id_2_isvalid(q->N_id_2)) { fprintf(stderr, "Must call sync_set_N_id_2() first!\n"); diff --git a/lte/phy/lib/ue/src/ue_sync.c b/lte/phy/lib/ue/src/ue_sync.c index 408914113..4e207a3d3 100644 --- a/lte/phy/lib/ue/src/ue_sync.c +++ b/lte/phy/lib/ue/src/ue_sync.c @@ -46,10 +46,12 @@ cf_t dummy[MAX_TIME_OFFSET]; #define CURRENT_SLOTLEN_RE SLOT_LEN_RE(q->cell.nof_prb, q->cell.cp) #define CURRENT_SFLEN_RE SF_LEN_RE(q->cell.nof_prb, q->cell.cp) -#define FIND_THRESHOLD 1.4 -#define TRACK_THRESHOLD 0.7 +#define FIND_THRESHOLD 1.5 +#define TRACK_THRESHOLD 0.8 #define TRACK_MAX_LOST 10 +#define CFO_EMA_ALPHA 0.01 + int ue_sync_init(ue_sync_t *q, lte_cell_t cell, @@ -145,7 +147,7 @@ float ue_sync_get_cfo(ue_sync_t *q) { } float ue_sync_get_sfo(ue_sync_t *q) { - return 1000*q->mean_time_offset; + return 5000*q->mean_time_offset; } void ue_sync_decode_sss_on_track(ue_sync_t *q, bool enabled) { @@ -209,9 +211,9 @@ int track_peak_ok(ue_sync_t *q, uint32_t track_idx) { } /* compute cumulative moving average CFO */ - q->cur_cfo = VEC_CMA(sync_get_cfo(&q->strack), q->cur_cfo, q->frame_ok_cnt); + q->cur_cfo = VEC_EMA(sync_get_cfo(&q->strack), q->cur_cfo, CFO_EMA_ALPHA); /* compute cumulative moving average time offset */ - q->mean_time_offset = (float) VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_ok_cnt); + q->mean_time_offset = (float) VEC_CMA((float) q->time_offset, q->mean_time_offset, q->frame_total_cnt); q->peak_idx = CURRENT_SFLEN/2 + q->time_offset; q->frame_ok_cnt++; @@ -356,8 +358,8 @@ void ue_sync_reset(ue_sync_t *q) { q->frame_ok_cnt = 0; q->frame_no_cnt = 0; q->frame_total_cnt = 0; - q->cur_cfo = 0; - q->mean_time_offset = 0; + q->cur_cfo = 0.0; + q->mean_time_offset = 0.0; q->time_offset = 0; #ifdef MEASURE_EXEC_TIME q->mean_exec_time = 0; diff --git a/lte/phy/lib/utils/src/vector.c b/lte/phy/lib/utils/src/vector.c index a807f10bf..d78836b33 100644 --- a/lte/phy/lib/utils/src/vector.c +++ b/lte/phy/lib/utils/src/vector.c @@ -475,12 +475,7 @@ float vec_dot_prod_fff(float *x, float *y, uint32_t len) { float vec_avg_power_cf(cf_t *x, uint32_t len) { - int j; - float power = 0; - for (j=0;j