diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 60ff40abeb..c90a5119cd 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -642,7 +642,9 @@ void *UE_thread(void *arg) { readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms); writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH) % nb_slot_frame, &UE->frame_parms); } else { - UE->rx_offset_diff = computeSamplesShift(UE); + //UE->rx_offset_diff = computeSamplesShift(UE); + + readBlockSize=get_readBlockSize(slot_nr, &UE->frame_parms) - UE->rx_offset_diff; writeBlockSize=UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX - NR_RX_NB_TH) % nb_slot_frame, &UE->frame_parms)- UE->rx_offset_diff; diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index b32d48a2e9..e2dd0e456b 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -141,6 +141,8 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain int *eNB_id, int *f_off); +int nr_adjust_pss_synch(PHY_VARS_NR_UE *ue, int *f_off); + #endif #undef EXTERN diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 28b6677b2c..4ee5884afd 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -34,6 +34,7 @@ #include #include #include +#include #include "PHY/defs_nr_UE.h" @@ -975,3 +976,87 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain return(peak_position); } +int nr_adjust_pss_synch(PHY_VARS_NR_UE *ue, int *f_off) { + + int **rxdata = ue->common_vars.rxdata; + NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; + uint8_t Nid2 = GET_NID2(frame_parms->Nid_cell); + + int maxval=0; + for (int i=0;i<2*(frame_parms->ofdm_symbol_size);i++) { + maxval = max(maxval,primary_synchro_time_nr[Nid2][i]); + maxval = max(maxval,-primary_synchro_time_nr[Nid2][i]); + } + int shift = log2_approx(maxval); + + /* Search pss in the received buffer each 4 samples which ensures a memory alignment on 128 bits (32 bits x 4 ) */ + /* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */ + /* Correlation computation is based on a dot product which is realized thank to SIMS extensions */ + int64_t peak_value = 0; + int peak_position = 0; + int64_t result = 0; + int64_t avg=0; + int start = 2*(frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples) + frame_parms->nb_prefix_samples0 - 200; + int length = 2*frame_parms->ofdm_symbol_size + 200; + memset(pss_corr_ue[Nid2],0,(start+length)*sizeof(int64_t)); + for (int n=start; n < start+length; n+=4) { // + for (int ar=0; arnb_antennas_rx; ar++) { + result = dot_product64((short*)primary_synchro_time_nr[Nid2], + (short*) &(rxdata[ar][n]), + frame_parms->ofdm_symbol_size, + shift); + pss_corr_ue[Nid2][n] += abs64(result); + } + avg+=pss_corr_ue[Nid2][n]; + if (pss_corr_ue[Nid2][n] > peak_value) { + peak_value = pss_corr_ue[Nid2][n]; + peak_position = n; + } + } + + avg/=(length/4); + if (peak_value < 5*avg) { + return 0; + } + + int peak_position_diff = peak_position - ( ((frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples)<<1) + frame_parms->nb_prefix_samples0); + + // Fractional frequency offset 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 + int64_t result1 = dot_product64((short*)primary_synchro_time_nr[Nid2], + (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 + int64_t result2 = dot_product64((short*)primary_synchro_time_nr[Nid2]+(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 = ((int*) &result1)[0]; + int64_t re2 = ((int*) &result2)[0]; + int64_t im1 = ((int*) &result1)[1]; + int64_t im2 = ((int*) &result2)[1]; + + // Estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi + double ffo_est = atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI; + + // Computing absolute value of frequency offset + *f_off = ffo_est*frame_parms->subcarrier_spacing; + + /*nr_rf_card_config_freq(&openair0_cfg[ue->rf_map.card], openair0_cfg->tx_freq[0], openair0_cfg->rx_freq[0], ue->common_vars.freq_offset); + + if (ue->mode != loop_through_memory) { + ue->rfdevice.trx_set_freq_func(&ue->rfdevice,&openair0_cfg[0],0); + }*/ + + LOG_I(NR_PHY,"nr_adjust_pss_synch: peak_position %d, peak_position_diff %d, peak_value %d dB, avg %d dB, ffo %lf\n", + peak_position, peak_position_diff, dB_fixed64(peak_value),dB_fixed64(avg),ffo_est); + + return peak_position_diff; +} diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index bb911195c7..fb36b3ee86 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -39,6 +39,7 @@ #include "PHY/phy_extern_nr_ue.h" #include "PHY/MODULATION/modulation_UE.h" #include "PHY/NR_REFSIG/refsig_defs_ue.h" +#include "PHY/NR_REFSIG/pss_nr.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h" #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h" #include "SCHED_NR_UE/defs.h" @@ -1647,10 +1648,12 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, if ((ue->decode_MIB == 1) && slot_pbch) { + int peak_position_diff = nr_adjust_pss_synch(ue, (int *)&ue->common_vars.freq_offset); + LOG_D(PHY," ------ Decode MIB: frame.slot %d.%d ------ \n", frame_rx%1024, nr_slot_rx); nr_ue_pbch_procedures(gNB_id, ue, proc, 0); - if (ue->no_timing_correction==0) { + /* if (ue->no_timing_correction==0) { LOG_D(PHY,"start adjust sync slot = %d no timing %d\n", nr_slot_rx, ue->no_timing_correction); nr_adjust_synch_ue(fp, ue, @@ -1659,7 +1662,11 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, nr_slot_rx, 0, 16384); - } + }*/ + + //ue->rx_offset = peak_position_diff; + + ue->rx_offset_diff = -peak_position_diff; LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__); nr_ue_rrc_measurements(ue, proc, nr_slot_rx); diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf index abc64b6e46..c4b06c1139 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf @@ -35,6 +35,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; pusch_AntennaPorts = 2; + min_rxtxtime_pdsch = 6; ul_prbblacklist = "51,52,53,54" pdcch_ConfigSIB1 = ( diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf index 83b39b85ec..c7531f39ba 100644 --- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf +++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf @@ -35,6 +35,7 @@ gNBs = ssb_SubcarrierOffset = 0; pdsch_AntennaPorts = 1; pusch_AntennaPorts = 1; + min_rxtxtime_pdsch = 6; sib1_tda = 0; pdcch_ConfigSIB1 = (