From 35dc0857c4d9bb0a2b2e46cd2765a7da262f0052 Mon Sep 17 00:00:00 2001 From: Francesco Mani Date: Tue, 22 Jan 2019 10:46:45 +0100 Subject: [PATCH] working version of FFO estimation --- openair1/PHY/NR_REFSIG/pss_nr.h | 3 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 5 +- openair1/PHY/NR_UE_TRANSPORT/pss_nr.c | 53 +++++++++++++++---- openair1/PHY/TOOLS/cdot_prod.c | 1 - openair1/SCHED_NR/phy_procedures_nr_gNB.c | 6 +-- openair1/SIMULATION/NR_PHY/pbchsim.c | 3 +- targets/RT/USER/nr-ue.c | 7 +-- 7 files changed, 56 insertions(+), 22 deletions(-) diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index 2f39f26ee4..279f9e417a 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -137,7 +137,8 @@ int set_pss_nr(int ofdm_symbol_size); int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change); int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id); + int *eNB_id, + int *f_off); #endif #undef EXTERN diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 50a283f465..c7c66bc7b5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -244,7 +244,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) ret = -1; } - /* Consider this is a false detection if the offset is > 1000 Hz */ + /* Consider this is a false detection if the offset is > 1000 Hz + Not to be used now that offest estimation is in place if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) ) { ret=-1; @@ -253,7 +254,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode) #else LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset); #endif - } + }*/ if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 43c1de71a2..38beb6f539 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -706,7 +706,9 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) synchro_position = pss_search_time_nr(rxdata, frame_parms, - (int *)&PHY_vars_UE->common_vars.eNb_id); + (int *)&PHY_vars_UE->common_vars.eNb_id, + (int *)&PHY_vars_UE->common_vars.freq_offset); + #if TEST_SYNCHRO_TIMING_PSS @@ -815,11 +817,12 @@ static inline double angle64(int64_t x) int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, - int *eNB_id) + int *eNB_id, + int *f_off) { unsigned int n, ar, peak_position, pss_source; int64_t peak_value; - int64_t result; + int64_t result,result1,result2; int64_t avg[NUMBER_PSS_SEQUENCE]; double ffo_est; @@ -842,7 +845,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain maxval = max(maxval,-primary_synchro_time_nr[1][i]); maxval = max(maxval,primary_synchro_time_nr[2][i]); maxval = max(maxval,-primary_synchro_time_nr[2][i]); - } int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2); @@ -877,27 +879,58 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain } } - + /* calculate the absolute value of sync_corr[n] */ avg[pss_index]+=pss_corr_ue[pss_index][n]; if (pss_corr_ue[pss_index][n] > peak_value) { peak_value = pss_corr_ue[pss_index][n]; peak_position = n; pss_source = pss_index; - ffo_est = angle64(result)/M_PI; -//#ifdef DEBUG_PSS_NR - printf("pss_index %d: n %6d peak_value %15llu ffo %lf\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n],ffo_est); -//#endif +#ifdef DEBUG_PSS_NR + printf("pss_index %d: n %6d peak_value %15llu\n", pss_index, n, (unsigned long long)pss_corr_ue[pss_index][n]); +#endif } } } + + // fractional frequency offser computation according to Cross-correlation Synchronization Algorithm Using PSS + // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012. + + // Computing cross-correlation at peak on half the symbol size for first half of data + result1 = dot_product64((short*)primary_synchro_time_nr[pss_source], + (short*) &(rxdata[0][peak_position]), + frame_parms->ofdm_symbol_size>>1, + shift); + // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size + // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift + result2 = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size), + (short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size), + frame_parms->ofdm_symbol_size>>1, + shift); + + int64_t re1,re2,im1,im2; + re1=((int*) &result1)[0]; + re2=((int*) &result2)[0]; + im1=((int*) &result1)[1]; + im2=((int*) &result2)[1]; + + // estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi + ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI; + +#ifdef DBG_PSS_NR + printf("ffo %lf\n",ffo_est); +#endif + + // computing absolute value of frequency offset + *f_off = ffo_est*frame_parms->subcarrier_spacing; + for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) avg[pss_index]/=(length/4); *eNB_id = pss_source; - LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source])); + LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est); if (peak_value < 5*avg[pss_source]) return(-1); diff --git a/openair1/PHY/TOOLS/cdot_prod.c b/openair1/PHY/TOOLS/cdot_prod.c index 2e23247141..843a9605f1 100644 --- a/openair1/PHY/TOOLS/cdot_prod.c +++ b/openair1/PHY/TOOLS/cdot_prod.c @@ -19,7 +19,6 @@ * contact@openairinterface.org */ -#include #include "tools_defs.h" #include "PHY/sse_intrin.h" diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index a9bc8cd62b..e232a0b5c9 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -139,20 +139,20 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int subframe) { LOG_D(PHY,"SS TX: frame %d, subframe %d, start_symbol %d\n",frame,subframe, ssb_start_symbol); nr_generate_pss(gNB->d_pss, txdataF, AMP, ssb_start_symbol, cfg, fp); - nr_generate_sss(gNB->d_sss, txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp); + nr_generate_sss(gNB->d_sss, txdataF, AMP, ssb_start_symbol, cfg, fp); if (!(frame&7)){ LOG_D(PHY,"%d.%d : pbch_configured %d\n",frame,subframe,gNB->pbch_configured); if (gNB->pbch_configured != 1)return; gNB->pbch_configured = 0; } - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP_OVER_2, ssb_start_symbol, cfg, fp); + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF, AMP, ssb_start_symbol, cfg, fp); nr_generate_pbch(&gNB->pbch, gNB->nrPolar_params, pbch_pdu, gNB->nr_pbch_interleaver, txdataF, - AMP_OVER_2, + AMP, ssb_start_symbol, n_hf,Lmax,ssb_index, frame, cfg, fp); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index a717b820d8..94d1e7dc42 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -120,7 +120,7 @@ int main(int argc, char **argv) double pbch_sinr; int pbch_tx_ant; - int N_RB_DL=106,mu=1; + int N_RB_DL=273,mu=1; unsigned char frame_type = 0; unsigned char pbch_phase = 0; @@ -538,7 +538,6 @@ int main(int argc, char **argv) sigma2_dB = 10*log10((double)txlev)-SNR; sigma2 = pow(10,sigma2_dB/10); // printf("sigma2 %f (%f dB)\n",sigma2,sigma2_dB); - if(eps!=0.0) rf_rx(r_re, // real part of txdata r_im, // imag part of txdata diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c index ed55e15d3c..a81d428992 100644 --- a/targets/RT/USER/nr-ue.c +++ b/targets/RT/USER/nr-ue.c @@ -444,6 +444,7 @@ static void *UE_thread_synch(void *arg) { //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (10*UE->frame_parms.samples_per_subframe), 1, 1); + freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe; printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", hw_slot_offset, @@ -459,13 +460,13 @@ static void *UE_thread_synch(void *arg) { openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET; if (UE->UE_scan_carrier == 1) { if (freq_offset >= 0) - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset); + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset); else - openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset); + openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset); openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i]; downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i]; - freq_offset=0; + //freq_offset=0; } }