From 15a13043951a34402c3cc70d56af1c01b3691a64 Mon Sep 17 00:00:00 2001 From: Ismael Gomez Date: Tue, 28 Nov 2017 16:20:40 +0100 Subject: [PATCH] Revert "Add noise reduction in PSS before estimating CFO" This reverts commit 0d7af888222b2c6cd5fed406875ca082b7d457e5. --- lib/include/srslte/phy/sync/pss.h | 16 ++-- lib/src/phy/sync/pss.c | 146 +++++++++++++----------------- 2 files changed, 68 insertions(+), 94 deletions(-) diff --git a/lib/include/srslte/phy/sync/pss.h b/lib/include/srslte/phy/sync/pss.h index d590cf2e6..9760a178c 100644 --- a/lib/include/srslte/phy/sync/pss.h +++ b/lib/include/srslte/phy/sync/pss.h @@ -70,7 +70,9 @@ /* Low-level API */ typedef struct SRSLTE_API { - + + srslte_dft_plan_t dftp_input; + #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_t conv_fft; srslte_filt_cc_t filter; @@ -85,22 +87,16 @@ typedef struct SRSLTE_API { uint32_t N_id_2; uint32_t fft_size; cf_t *pss_signal_freq_full[3]; - + cf_t *pss_signal_time[3]; - + cf_t pss_signal_freq[3][SRSLTE_PSS_LEN]; // One sequence for each N_id_2 cf_t *tmp_input; cf_t *conv_output; float *conv_output_abs; - float ema_alpha; + float ema_alpha; float *conv_output_avg; float peak_value; - - srslte_dft_plan_t dftp_input; - srslte_dft_plan_t idftp_input; - cf_t tmp_fft[SRSLTE_SYMBOL_SZ_MAX]; - cf_t yr[SRSLTE_PSS_LEN]; - }srslte_pss_synch_t; typedef enum { PSS_TX, PSS_RX } pss_direction_t; diff --git a/lib/src/phy/sync/pss.c b/lib/src/phy/sync/pss.c index 9333567ff..f7b35071d 100644 --- a/lib/src/phy/sync/pss.c +++ b/lib/src/phy/sync/pss.c @@ -137,15 +137,9 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } srslte_dft_plan_set_mirror(&q->dftp_input, true); srslte_dft_plan_set_dc(&q->dftp_input, true); + srslte_dft_plan_set_norm(&q->dftp_input, true); - if (srslte_dft_plan(&q->idftp_input, fft_size, SRSLTE_DFT_BACKWARD, SRSLTE_DFT_COMPLEX)) { - fprintf(stderr, "Error creating DFT plan \n"); - goto clean_and_exit; - } - srslte_dft_plan_set_mirror(&q->idftp_input, true); - srslte_dft_plan_set_dc(&q->idftp_input, true); - - q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); + q->tmp_input = srslte_vec_malloc((buffer_size + frame_size*(q->decimate - 1)) * sizeof(cf_t)); if (!q->tmp_input) { fprintf(stderr, "Error allocating memory\n"); goto clean_and_exit; @@ -173,7 +167,7 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, } bzero(q->conv_output_abs, sizeof(float) * buffer_size); #endif - + for (N_id_2=0;N_id_2<3;N_id_2++) { q->pss_signal_time[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (!q->pss_signal_time[N_id_2]) { @@ -184,14 +178,14 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, if (srslte_pss_synch_init_N_id_2(q->pss_signal_freq[N_id_2], q->pss_signal_time[N_id_2], N_id_2, fft_size, offset)) { fprintf(stderr, "Error initiating PSS detector for N_id_2=%d fft_size=%d\n", N_id_2, fft_size); goto clean_and_exit; - } + } bzero(&q->pss_signal_time[N_id_2][q->fft_size], q->frame_size * sizeof(cf_t)); - } + } #ifdef CONVOLUTION_FFT for(N_id_2=0; N_id_2<3; N_id_2++) - q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); + q->pss_signal_freq_full[N_id_2] = srslte_vec_malloc(buffer_size * sizeof(cf_t)); if (srslte_conv_fft_cc_init(&q->conv_fft, frame_size, fft_size)) { fprintf(stderr, "Error initiating convolution FFT\n"); @@ -200,15 +194,15 @@ int srslte_pss_synch_init_fft_offset_decim(srslte_pss_synch_t *q, for(int i=0; i<3; i++) { srslte_dft_run_c(&q->conv_fft.filter_plan, q->pss_signal_time[i], q->pss_signal_freq_full[i]); } - + #endif - + srslte_pss_synch_reset(q); - + ret = SRSLTE_SUCCESS; } -clean_and_exit: +clean_and_exit: if (ret == SRSLTE_ERROR) { srslte_pss_synch_free(q); } @@ -304,7 +298,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } #ifdef CONVOLUTION_FFT srslte_conv_fft_cc_free(&q->conv_fft); - + #endif if (q->tmp_input) { free(q->tmp_input); @@ -318,10 +312,9 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { if (q->conv_output_avg) { free(q->conv_output_avg); } - + srslte_dft_plan_free(&q->dftp_input); - srslte_dft_plan_free(&q->idftp_input); - + if(q->decimate > 1) { srslte_filt_decim_cc_free(&q->filter); @@ -330,7 +323,7 @@ void srslte_pss_synch_free(srslte_pss_synch_t *q) { } - bzero(q, sizeof(srslte_pss_synch_t)); + bzero(q, sizeof(srslte_pss_synch_t)); } } @@ -386,7 +379,7 @@ void srslte_pss_put_slot(cf_t *pss_signal, cf_t *slot, uint32_t nof_prb, srslte_ void srslte_pss_get_slot(cf_t *slot, cf_t *pss_signal, uint32_t nof_prb, srslte_cp_t cp) { int k; k = (SRSLTE_CP_NSYMB(cp) - 1) * nof_prb * SRSLTE_NRE + nof_prb * SRSLTE_NRE / 2 - 31; - memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); + memcpy(pss_signal, &slot[k], SRSLTE_PSS_LEN * sizeof(cf_t)); } @@ -405,34 +398,34 @@ int srslte_pss_synch_set_N_id_2(srslte_pss_synch_t *q, uint32_t N_id_2) { /* Sets the weight factor alpha for the exponential moving average of the PSS correlation output */ void srslte_pss_synch_set_ema_alpha(srslte_pss_synch_t *q, float alpha) { - q->ema_alpha = alpha; + q->ema_alpha = alpha; } -/** Performs time-domain PSS correlation. +/** Performs time-domain PSS correlation. * Returns the index of the PSS correlation peak in a subframe. * The frame starts at corr_peak_pos-subframe_size/2. * The value of the correlation is stored in corr_peak_value. * * Input buffer must be subframe_size long. */ -int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) +int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_peak_value) { int ret = SRSLTE_ERROR_INVALID_INPUTS; - - if (q != NULL && + + if (q != NULL && input != NULL) { uint32_t corr_peak_pos; uint32_t conv_output_len; - + if (!srslte_N_id_2_isvalid(q->N_id_2)) { fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } /* Correlate input with PSS sequence - * + * * We do not reverse time-domain PSS signal because it's conjugate is symmetric. * The conjugate operation on pss_signal_time has been done in srslte_pss_synch_init_N_id_2 * This is why we can use FFT-based convolution @@ -449,7 +442,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe { conv_output_len = srslte_conv_fft_cc_run_opt(&q->conv_fft, q->tmp_input, q->pss_signal_freq_full[q->N_id_2], q->conv_output); } - + #else conv_output_len = srslte_conv_cc(input, q->pss_signal_time[q->N_id_2], q->conv_output, q->frame_size, q->fft_size); #endif @@ -457,19 +450,19 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe for (int i=0;iframe_size;i++) { q->conv_output[i] = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], &input[i], q->fft_size); } - conv_output_len = q->frame_size; + conv_output_len = q->frame_size; } - + #ifdef SRSLTE_PSS_ABS_SQUARE srslte_vec_abs_square_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #else srslte_vec_abs_cf(q->conv_output, q->conv_output_abs, conv_output_len-1); #endif - + if (q->ema_alpha < 1.0 && q->ema_alpha > 0.0) { - srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); - srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_abs, q->ema_alpha, q->conv_output_abs, conv_output_len-1); + srslte_vec_sc_prod_fff(q->conv_output_avg, 1-q->ema_alpha, q->conv_output_avg, conv_output_len-1); srslte_vec_sum_fff(q->conv_output_abs, q->conv_output_avg, q->conv_output_avg, conv_output_len-1); } else { @@ -477,43 +470,43 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe } /* Find maximum of the absolute value of the correlation */ corr_peak_pos = srslte_vec_max_fi(q->conv_output_avg, conv_output_len-1); - - // save absolute value + + // save absolute value q->peak_value = q->conv_output_avg[corr_peak_pos]; - -#ifdef SRSLTE_PSS_RETURN_PSR + +#ifdef SRSLTE_PSS_RETURN_PSR // Find second side lobe - + // Find end of peak lobe to the right int pl_ub = corr_peak_pos+1; while(q->conv_output_avg[pl_ub+1] <= q->conv_output_avg[pl_ub] && pl_ub < conv_output_len) { - pl_ub ++; + pl_ub ++; } // Find end of peak lobe to the left - int pl_lb; + int pl_lb; if (corr_peak_pos > 2) { pl_lb = corr_peak_pos-1; while(q->conv_output_avg[pl_lb-1] <= q->conv_output_avg[pl_lb] && pl_lb > 1) { - pl_lb --; - } + pl_lb --; + } } else { - pl_lb = 0; + pl_lb = 0; } - int sl_distance_right = conv_output_len-1-pl_ub; + int sl_distance_right = conv_output_len-1-pl_ub; if (sl_distance_right < 0) { - sl_distance_right = 0; + sl_distance_right = 0; } - int sl_distance_left = pl_lb; - + int sl_distance_left = pl_lb; + int sl_right = pl_ub+srslte_vec_max_fi(&q->conv_output_avg[pl_ub], sl_distance_right); - int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); - float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); + int sl_left = srslte_vec_max_fi(q->conv_output_avg, sl_distance_left); + float side_lobe_value = SRSLTE_MAX(q->conv_output_avg[sl_right], q->conv_output_avg[sl_left]); if (corr_peak_value) { *corr_peak_value = q->conv_output_avg[corr_peak_pos]/side_lobe_value; - + if (*corr_peak_value < 10) - DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, + DEBUG("peak_pos=%2d, pl_ub=%2d, pl_lb=%2d, sl_right: %2d, sl_left: %2d, PSR: %.2f/%.2f=%.2f\n", corr_peak_pos, pl_ub, pl_lb, sl_right,sl_left, q->conv_output_avg[corr_peak_pos], side_lobe_value,*corr_peak_value); } #else @@ -521,7 +514,7 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe *corr_peak_value = q->conv_output_avg[corr_peak_pos]; } #endif - + if(q->decimate >1) { int decimation_correction = (q->filter.num_taps - 2); @@ -531,23 +524,23 @@ int srslte_pss_synch_find_pss(srslte_pss_synch_t *q, cf_t *input, float *corr_pe if (q->frame_size >= q->fft_size) { - ret = (int) corr_peak_pos; + ret = (int) corr_peak_pos; } else { ret = (int) corr_peak_pos + q->fft_size; } - } + } return ret; } -/* Computes frequency-domain channel estimation of the PSS symbol - * input signal is in the time-domain. - * ce is the returned frequency-domain channel estimates. +/* Computes frequency-domain channel estimation of the PSS symbol + * input signal is in the time-domain. + * ce is the returned frequency-domain channel estimates. */ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PSS_LEN]) { int ret = SRSLTE_ERROR_INVALID_INPUTS; cf_t input_fft[SRSLTE_SYMBOL_SZ_MAX]; - if (q != NULL && + if (q != NULL && input != NULL) { @@ -555,46 +548,31 @@ int srslte_pss_synch_chest(srslte_pss_synch_t *q, cf_t *input, cf_t ce[SRSLTE_PS fprintf(stderr, "Error finding PSS peak, Must set N_id_2 first\n"); return SRSLTE_ERROR; } - + /* Transform to frequency-domain */ srslte_dft_run_c(&q->dftp_input, input, input_fft); - + /* Compute channel estimate taking the PSS sequence as reference */ srslte_vec_prod_conj_ccc(&input_fft[(q->fft_size-SRSLTE_PSS_LEN)/2], q->pss_signal_freq[q->N_id_2], ce, SRSLTE_PSS_LEN); - + ret = SRSLTE_SUCCESS; } - return ret; + return ret; } -#define CLEAN_NOISE_DFT -//#define PSS_CFO_FREQ /* Returns the CFO estimation given a PSS received sequence * * Source: An Efficient CFO Estimation Algorithm for the Downlink of 3GPP-LTE * Feng Wang and Yu Zhu */ float srslte_pss_synch_cfo_compute(srslte_pss_synch_t* q, cf_t *pss_recv) { - cf_t y0, y1; - -#ifdef PSS_CFO_FREQ - - srslte_vec_prod_conj_ccc(&q->tmp_fft[q->fft_size/2-SRSLTE_PSS_LEN/2], q->pss_signal_freq[q->N_id_2], q->yr, SRSLTE_PSS_LEN); - y0 = srslte_vec_acc_cc(q->yr, SRSLTE_PSS_LEN/2); - y1 = srslte_vec_acc_cc(&q->yr[SRSLTE_PSS_LEN/2], SRSLTE_PSS_LEN/2); - -#else -#ifdef CLEAN_NOISE_DFT - // Eliminate noise - srslte_dft_run_c(&q->dftp_input, pss_recv, q->tmp_fft); - bzero(q->tmp_fft, sizeof(cf_t)*(q->fft_size/2-SRSLTE_PSS_LEN/2)); - bzero(&q->tmp_fft[q->fft_size/2+SRSLTE_PSS_LEN/2], sizeof(cf_t)*(q->fft_size/2-SRSLTE_PSS_LEN/2)); - srslte_dft_run_c(&q->idftp_input, q->tmp_fft, pss_recv); -#endif + cf_t y0, y1, yr; y0 = srslte_vec_dot_prod_ccc(q->pss_signal_time[q->N_id_2], pss_recv, q->fft_size/2); y1 = srslte_vec_dot_prod_ccc(&q->pss_signal_time[q->N_id_2][q->fft_size/2], &pss_recv[q->fft_size/2], q->fft_size/2); -#endif - return carg(conjf(y0) * y1)/M_PI; + + yr = conjf(y0) * y1; + + return atan2f(__imag__ yr, __real__ yr) / M_PI; }