diff --git a/executables/nr-ue.c b/executables/nr-ue.c index bf0dc9809a..d6946f1ac7 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -169,6 +169,7 @@ static void UE_synch(void *arg) { int freq_offset=0; UE->is_synchronized = 0; + if (UE->UE_scan == 0) { get_band(downlink_frequency[CC_id][0], &UE->frame_parms.eutra_band, &uplink_frequency_offset[CC_id][0], &UE->frame_parms.frame_type); LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", @@ -239,7 +240,7 @@ static void UE_synch(void *arg) { case pbch: LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode); - if (nr_initial_sync( &syncD->proc, UE, UE->mode ) == 0) { + if (nr_initial_sync( &syncD->proc, UE, UE->mode,2) == 0) { 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_slot; LOG_I(PHY,"Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n", @@ -348,7 +349,7 @@ static void UE_synch(void *arg) { } } -void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { +void processSlotRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { // Process Rx data for one sub-frame if (slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx) & NR_DOWNLINK_SLOT) { //clean previous FAPI MESSAGE @@ -376,9 +377,9 @@ void processSubframeRX( PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) { phy_procedures_slot_parallelization_nrUE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL ); #else uint64_t a=rdtsc(); - phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode); + phy_procedures_nrUE_RX( UE, proc, 0, 1, UE->mode, UE_mac->phy_config.config_req.pbch_config); LOG_D(PHY,"phy_procedures_nrUE_RX: slot:%d, time %lu\n", proc->nr_tti_rx, (rdtsc()-a)/3500); - // printf(">>> nr_ue_pdcch_procedures ended\n"); + //printf(">>> nr_ue_pdcch_procedures ended\n"); #endif } @@ -413,7 +414,7 @@ void UE_processing(void *arg) { processingData_t *rxtxD=(processingData_t *) arg; UE_nr_rxtx_proc_t *proc = &rxtxD->proc; PHY_VARS_NR_UE *UE = rxtxD->UE; - processSubframeRX(UE, proc); + processSlotRX(UE, proc); //printf(">>> mac ended\n"); // Prepare the future Tx data #if 0 @@ -447,7 +448,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { for (int i=0; iframe_parms.nb_antennas_tx; i++) dummy_tx[i]=malloc16_clear(UE->frame_parms.samples_per_subframe*4); - for(int x=0; x<10; x++) { + for(int x=0; x<20; x++) { // two frames for initial sync for (int i=0; iframe_parms.nb_antennas_rx; i++) rxp[i] = ((void *)&UE->common_vars.rxdata[i][0]) + 4*x*UE->frame_parms.samples_per_subframe; @@ -613,6 +614,7 @@ void *UE_thread(void *arg) { continue; } + absolute_slot++; // whatever means thread_idx // Fix me: will be wrong when slot 1 is slow, as slot 2 finishes diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c index 8300f10675..c8143879b1 100644 --- a/executables/nr-uesoftmodem.c +++ b/executables/nr-uesoftmodem.c @@ -393,7 +393,7 @@ static void get_options(void) { uint32_t online_log_messages; uint32_t glog_level, glog_verbosity; uint32_t start_telnetsrv=0; - paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ; + paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC_UE ; paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ; config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index 078a8066c3..4d45e08722 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -150,7 +150,7 @@ /* command line parameters common to eNodeB and UE */ /* optname helpstr paramflags XXXptr defXXXval type numelt */ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ -#define CMDLINE_PARAMS_DESC { \ +#define CMDLINE_PARAMS_DESC_UE { \ {"rf-config-file", CONFIG_HLP_RFCFGF, 0, strptr:(char **)&rf_config_file, defstrval:NULL, TYPE_STRING, sizeof(rf_config_file)}, \ {"ulsch-max-errors", CONFIG_HLP_ULMAXE, 0, uptr:&ULSCH_max_consecutive_errors, defuintval:0, TYPE_UINT, 0}, \ {"phy-test", CONFIG_HLP_PHYTST, PARAMFLAG_BOOL, iptr:&phy_test, defintval:0, TYPE_INT, 0}, \ diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c index fc2f68016f..c388c4e1e0 100644 --- a/openair1/PHY/INIT/nr_init.c +++ b/openair1/PHY/INIT/nr_init.c @@ -398,6 +398,7 @@ void nr_phy_config_request(NR_PHY_Config_t *phy_config) { gNB_config->sch_config.n_ssb_crb.value = (phy_config->cfg->rf_config.dl_carrier_bandwidth.value-20); gNB_config->sch_config.physical_cell_id.value = phy_config->cfg->sch_config.physical_cell_id.value; gNB_config->sch_config.ssb_scg_position_in_burst.value= phy_config->cfg->sch_config.ssb_scg_position_in_burst.value; + gNB_config->sch_config.ssb_periodicity.value = phy_config->cfg->sch_config.ssb_periodicity.value; if (phy_config->cfg->subframe_config.duplex_mode.value == 0) { gNB_config->subframe_config.duplex_mode.value = TDD; diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 63aeba0480..df52a6f015 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -715,14 +715,13 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, } // init RX buffers - common_vars->rxdata = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); for (th_id=0; th_idcommon_vars_rx_data_per_thread[th_id].rxdataF = (int32_t**)malloc16( fp->nb_antennas_rx*sizeof(int32_t*) ); } for (i=0; inb_antennas_rx; i++) { - common_vars->rxdata[i] = (int32_t*) malloc16_clear( (fp->samples_per_subframe*10+2048)*sizeof(int32_t) ); + common_vars->rxdata[i] = (int32_t*) malloc16_clear( (2*(fp->samples_per_frame)+2048)*sizeof(int32_t) ); for (th_id=0; th_idcommon_vars_rx_data_per_thread[th_id].rxdataF[i] = (int32_t*)malloc16_clear( sizeof(int32_t)*(fp->ofdm_symbol_size*14) ); } @@ -905,6 +904,8 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, ue->decode_MIB = 1; ue->decode_SIB = 1; + ue->ssb_periodicity = 5; // initialization of ssb periodicity to 5ms according to TS38.213 section 4.1 + init_prach_tables(839); diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c index c6a6d93c18..7ff88612a1 100644 --- a/openair1/PHY/MODULATION/slot_fep_nr.c +++ b/openair1/PHY/MODULATION/slot_fep_nr.c @@ -117,8 +117,6 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, return(-1); } - - for (aa=0; aanb_antennas_rx; aa++) { memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int)); @@ -135,13 +133,13 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, if (symbol==0) { if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((short *)&common_vars->rxdata[aa][frame_length_samples], - (short *)&common_vars->rxdata[aa][0], + memcpy((short*) &common_vars->rxdata[aa][frame_length_samples], + (short*) &common_vars->rxdata[aa][0], frame_parms->ofdm_symbol_size*sizeof(int)); if ((rx_offset&7)!=0) { // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs memcpy((void *)tmp_dft_in, - (void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples], + (void *) &common_vars->rxdata[aa][rx_offset % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); dft((int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); @@ -150,19 +148,20 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, start_meas(&ue->rx_dft_stats); #endif - dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); #if UE_TIMING_TRACE stop_meas(&ue->rx_dft_stats); #endif } } else { - rx_offset += (frame_parms->ofdm_symbol_size+nb_prefix_samples)*symbol;// + - // (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1); + + rx_offset += (frame_parms->ofdm_symbol_size+nb_prefix_samples)*symbol; + // + (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1); if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size)) - memcpy((void *)&common_vars->rxdata[aa][frame_length_samples], - (void *)&common_vars->rxdata[aa][0], + memcpy((void *) &common_vars->rxdata[aa][frame_length_samples], + (void *) &common_vars->rxdata[aa][0], frame_parms->ofdm_symbol_size*sizeof(int)); #if UE_TIMING_TRACE start_meas(&ue->rx_dft_stats); @@ -170,13 +169,13 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, if ((rx_offset&7)!=0) { // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs memcpy((void *)tmp_dft_in, - (void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + (void *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], frame_parms->ofdm_symbol_size*sizeof(int)); dft((int16_t *)tmp_dft_in, (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } else { // use dft input from RX buffer directly - dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples], + dft((int16_t *) &common_vars->rxdata[aa][(rx_offset) % frame_length_samples], (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1); } #if UE_TIMING_TRACE @@ -192,6 +191,7 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue, #endif } + #ifdef DEBUG_FEP printf("slot_fep: done\n"); #endif diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h index dc20ab24d7..a2e66d4e11 100644 --- a/openair1/PHY/NR_REFSIG/pss_nr.h +++ b/openair1/PHY/NR_REFSIG/pss_nr.h @@ -134,10 +134,11 @@ void free_context_synchro_nr(void); void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue); void free_context_pss_nr(void); int set_pss_nr(int ofdm_symbol_size); -int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change); +int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change); int pss_search_time_nr(int **rxdata, ///rx data in time domain NR_DL_FRAME_PARMS *frame_parms, int fo_flag, + int is, int *eNB_id, int *f_off); diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c index 0ab83712d8..1728d93b69 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c @@ -65,7 +65,7 @@ int nr_pbch_dmrs_correlation(PHY_VARS_NR_UE *ue, k = nushift; #ifdef DEBUG_CH - printf("PBCH DMRS Correlation : ThreadId %d, eNB_offset %d , OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns>>1], eNB_offset,ue->frame_parms.ofdm_symbol_size, + printf("PBCH DMRS Correlation : ThreadId %d, eNB_offset %d , OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ue->frame_parms.ofdm_symbol_size, ue->frame_parms.Ncp,Ns,k, symbol); #endif @@ -324,6 +324,9 @@ int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue, re_offset = (re_offset+4)&(ue->frame_parms.ofdm_symbol_size-1); rxF = (int16_t *)&rxdataF[aarx][(symbol_offset+k+re_offset)]; + ch[0] = (int16_t)(((int32_t)pil[0]*rxF[0] - (int32_t)pil[1]*rxF[1])>>15); + ch[1] = (int16_t)(((int32_t)pil[0]*rxF[1] + (int32_t)pil[1]*rxF[0])>>15); + #ifdef DEBUG_CH printf("pilot 2 : rxF - > (%d,%d) ch -> (%d,%d), pil -> (%d,%d) \n",rxF[0],rxF[1],ch[0],ch[1],pil[0],pil[1]); #endif @@ -441,8 +444,8 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue, k = coreset_start_subcarrier; #ifdef DEBUG_PDCCH - printf("PDCCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.Ncp,l,Ns,k, symbol); + printf("PDCCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,ue->frame_parms.ofdm_symbol_size, + ue->frame_parms.Ncp,Ns,k, symbol); #endif fl = filt16a_l1; @@ -638,6 +641,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, unsigned short bwp_start_subcarrier, unsigned short nb_rb_pdsch) { + int pilot[1320] __attribute__((aligned(16))); unsigned char aarx; unsigned short k; @@ -665,8 +669,8 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, int re_offset = k; #ifdef DEBUG_CH - printf("PDSCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, l=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,symbol_offset,ue->frame_parms.ofdm_symbol_size, - ue->frame_parms.Ncp,l,Ns,k, symbol); + printf("PDSCH Channel Estimation : ThreadId %d, eNB_offset %d ch_offset %d, symbol_offset %d OFDM size %d, Ncp=%d, Ns=%d, k=%d symbol %d\n",ue->current_thread_id[Ns], eNB_offset,ch_offset,symbol_offset,ue->frame_parms.ofdm_symbol_size, + ue->frame_parms.Ncp,Ns,k, symbol); #endif switch (nushift) { diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 50c7bafbad..fc4fff1c40 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -201,13 +201,14 @@ int nr_pbch_detection(UE_nr_rxtx_proc_t * proc, PHY_VARS_NR_UE *ue, int pbch_ini char duplex_string[2][4] = {"FDD","TDD"}; char prefix_string[2][9] = {"NORMAL","EXTENDED"}; -int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode) +int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode, int n_frames) { int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, int32_t metric_tdd_ncp=0; uint8_t phase_tdd_ncp; double im, re; + int is; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; int ret=-1; @@ -222,10 +223,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode) nr_init_frame_parms_ue(fp,NR_MU_1,NORMAL,fp->N_RB_DL,n_ssb_crb,0); LOG_D(PHY,"nr_initial sync ue RB_DL %d\n", fp->N_RB_DL); - /* - write_output("rxdata0.m","rxd0",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1); - exit(-1); - */ + /* Initial synchronisation * @@ -242,26 +240,27 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode) cnt++; if (1){ // (cnt>100) - cnt =0; + cnt =0; - /* process pss search on received buffer */ - sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE); + // initial sync performed on two successive frames, if pbch passes on first frame, no need to process second frame + // only one frame is used for symulation tools + for(is=0; is= fp->nb_prefix_samples) - ue->ssb_offset = sync_pos - fp->nb_prefix_samples; - else - ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples; + /* process pss search on received buffer */ + sync_pos = pss_synchro_nr(ue, is, NO_RATE_CHANGE); - - //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1); + if (sync_pos >= fp->nb_prefix_samples) + ue->ssb_offset = sync_pos - fp->nb_prefix_samples; + else + ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples; #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n", ue->Mod_id, sync_pos,ue->common_vars.eNb_id); - LOG_I(PHY,"sync_pos %d ssb_offset %d \n",sync_pos,ue->ssb_offset); + LOG_I(PHY,"[UE%d] Initial sync : Estimated PSS position %d, Nid2 %d\n", ue->Mod_id, sync_pos,ue->common_vars.eNb_id); + LOG_I(PHY,"sync_pos %d ssb_offset %d \n",sync_pos,ue->ssb_offset); #endif - // digital compensation of FFO for SSB symbols - if (ue->UE_fo_compensation){ + // digital compensation of FFO for SSB symbols + if (ue->UE_fo_compensation){ double s_time = 1/(1.0e3*fp->samples_per_subframe); // sampling time double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset); // offset rotation angle compensation per sample @@ -276,11 +275,10 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode) ((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle))); } } - } + } - - /* check that SSS/PBCH block is continuous inside the received buffer */ - if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) { + /* check that SSS/PBCH block is continuous inside the received buffer */ + if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) { /* slop_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */ /* for NR this is not the case but slot_fep is still used for computing FFT of samples */ @@ -291,33 +289,33 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode) /* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */ /* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */ - for(int i=0; i<4;i++) - nr_slot_fep(ue, - i, - 0, - ue->ssb_offset, - 0); + for(int i=0; i<4;i++) + nr_slot_fep(ue, + i, + 0, + ue->ssb_offset, + 0); #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"Calling sss detection (normal CP)\n"); + LOG_I(PHY,"Calling sss detection (normal CP)\n"); #endif - rx_sss_nr(ue,&metric_tdd_ncp,&phase_tdd_ncp); + rx_sss_nr(ue,&metric_tdd_ncp,&phase_tdd_ncp); - //FK: why do we need to do this again here? - //nr_init_frame_parms_ue(fp,NR_MU_1,NORMAL,n_ssb_crb,0); + //FK: why do we need to do this again here? + //nr_init_frame_parms_ue(fp,NR_MU_1,NORMAL,n_ssb_crb,0); - nr_gold_pbch(ue); - ret = nr_pbch_detection(proc, ue,1,mode); // start pbch detection at first symbol after pss + nr_gold_pbch(ue); + ret = nr_pbch_detection(proc, ue,1,mode); // start pbch detection at first symbol after pss - if (ret == 0) { - // sync at symbol ue->symbol_offset - // computing the offset wrt the beginning of the frame - sync_pos_frame = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)+((ue->symbol_offset)-1)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); - ue->rx_offset = ue->ssb_offset - sync_pos_frame; - } + if (ret == 0) { + // sync at symbol ue->symbol_offset + // computing the offset wrt the beginning of the frame + sync_pos_frame = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)+((ue->symbol_offset)-1)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); + ue->rx_offset = ue->ssb_offset - sync_pos_frame; + } - nr_gold_pdcch(ue,0, 2); + nr_gold_pdcch(ue,0, 2); /* int nb_prefix_samples0 = fp->nb_prefix_samples0; fp->nb_prefix_samples0 = fp->nb_prefix_samples; @@ -333,16 +331,20 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode) ue->common_vars.freq_offset ); */ + #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"TDD Normal prefix: CellId %d metric %d, phase %d, pbch %d\n", - fp->Nid_cell,metric_tdd_ncp,phase_tdd_ncp,ret); + LOG_I(PHY,"TDD Normal prefix: CellId %d metric %d, phase %d, pbch %d\n", + fp->Nid_cell,metric_tdd_ncp,phase_tdd_ncp,ret); #endif - } - else { + + } + else { #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos); + LOG_I(PHY,"TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos); #endif - } + } + if (ret == 0) break; + } } else { ret = -1; @@ -370,6 +372,8 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, runmode_t mode) #endif //#endif + ue->is_synchronized_on_frame = is; // to notify on which of the two frames sync was successful + if (ue->UE_scan_carrier == 0) { #if UE_AUTOTEST_TRACE diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c index d23f164534..b56573f2b3 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c @@ -417,6 +417,8 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, uint8_t i_ssb, MIMO_mode_t mimo_mode, uint32_t high_speed_flag) { + + int Ns = proc->nr_tti_rx; NR_UE_COMMON *nr_ue_common_vars = &ue->common_vars; int max_h=0; int symbol; @@ -443,19 +445,21 @@ int nr_rx_pbch( PHY_VARS_NR_UE *ue, int symbol_offset=1; if (ue->is_synchronized > 0) - symbol_offset=ue->symbol_offset; + symbol_offset=(ue->symbol_offset)%(frame_parms->symbols_per_slot); else symbol_offset=0; + #ifdef DEBUG_PBCH - //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[proc->subframe_rx]].rxdataF); + //printf("address dataf %p",nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF); write_output("rxdataF0_pbch.m","rxF0pbch", - &nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[proc->subframe_rx]].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1); + &nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF[0][(symbol_offset+1)*frame_parms->ofdm_symbol_size],frame_parms->ofdm_symbol_size*3,1,1); #endif // symbol refers to symbol within SSB. symbol_offset is the offset of the SSB wrt start of slot for (symbol=1; symbol<4; symbol++) { - nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[proc->subframe_rx]].rxdataF, + + nr_pbch_extract(nr_ue_common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns]].rxdataF, nr_ue_pbch_vars->dl_ch_estimates, nr_ue_pbch_vars->rxdataF_ext, nr_ue_pbch_vars->dl_ch_estimates_ext, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h index e7af632327..6e588acd1d 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -1480,7 +1480,9 @@ void generate_RIV_tables(void); @param mode current running mode */ int nr_initial_sync(UE_nr_rxtx_proc_t *proc, - PHY_VARS_NR_UE *phy_vars_ue, runmode_t mode); + PHY_VARS_NR_UE *phy_vars_ue, + runmode_t mode, + int n_frames); /*! diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c index 40945bebef..a880959864 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c +++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c @@ -402,7 +402,7 @@ void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue) assert(0); } - size = NR_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int64_t)*frame_parms_ue->samples_per_subframe; + size = sizeof(int64_t)*(frame_parms_ue->samples_per_frame + (2*ofdm_symbol_size)); q = (int64_t*)malloc16(size); if (q != NULL) { pss_corr_ue[i] = q; @@ -611,7 +611,7 @@ void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_ch void decimation_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change, int **rxdata) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); - int samples_for_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti; + int samples_for_frame = 2*frame_parms->samples_per_frame; AssertFatal(frame_parms->samples_per_tti > 3839,"Illegal samples_per_tti %d\n",frame_parms->samples_per_tti); @@ -658,7 +658,7 @@ void decimation_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change, int **r * *********************************************************************/ -int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) +int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int is, int rate_change) { NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms); int synchro_position; @@ -667,9 +667,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) #ifdef DBG_PSS_NR - int samples_for_frame = frame_parms->samples_per_subframe*NR_NUMBER_OF_SUBFRAMES_PER_FRAME; - - LOG_M("rxdata0_rand.m","rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], samples_for_frame, 1, 1); + LOG_M("rxdata0_rand.m","rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], frame_parms->samples_per_frame, 1, 1); #endif @@ -678,7 +676,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*)); for (int aa=0; aa < frame_parms->nb_antennas_rx; aa++) { - rxdata[aa] = (int32_t*) malloc16_clear( (frame_parms->samples_per_subframe*10+8192)*sizeof(int32_t)); + rxdata[aa] = (int32_t*) malloc16_clear( (frame_parms->samples_per_frame+8192)*sizeof(int32_t)); } #ifdef SYNCHRO_DECIMAT @@ -693,7 +691,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) #ifdef DBG_PSS_NR - LOG_M("rxdata0_des.m","rxd0_des", &rxdata[0][0], samples_for_frame,1,1); + LOG_M("rxdata0_des.m","rxd0_des", &rxdata[0][0], frame_parms->samples_per_frame,1,1); #endif @@ -708,6 +706,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) synchro_position = pss_search_time_nr(rxdata, frame_parms, fo_flag, + is, (int *)&PHY_vars_UE->common_vars.eNb_id, (int *)&PHY_vars_UE->common_vars.freq_offset); @@ -746,6 +745,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change) return synchro_position; } + static inline int abs32(int x) { return (((int)((short*)&x)[0])*((int)((short*)&x)[0]) + ((int)((short*)&x)[1])*((int)((short*)&x)[1])); @@ -820,6 +820,7 @@ 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 fo_flag, + int is, int *eNB_id, int *f_off) { @@ -829,13 +830,17 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain int64_t avg[NUMBER_PSS_SEQUENCE]; double ffo_est=0; - - unsigned int length = (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe); /* 1 frame for now, it should be 2 TODO_NR */ + // performing the correlation on a frame length plus one symbol for the first of the two frame + // to take into account the possibility of PSS in between the two frames + unsigned int length; + if (is==0) + length = frame_parms->samples_per_frame + (2*frame_parms->ofdm_symbol_size); + else + length = frame_parms->samples_per_frame; AssertFatal(length>0,"illegal length %d\n",length); for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) AssertFatal(pss_corr_ue[i] != NULL,"pss_corr_ue[%d] not yet allocated! Exiting.\n", i); - peak_value = 0; peak_position = 0; pss_source = 0; @@ -871,7 +876,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain /* perform correlation of rx data and pss sequence ie it is a dot product */ result = dot_product64((short*)primary_synchro_time_nr[pss_index], - (short*) &(rxdata[ar][n]), + (short*) &(rxdata[ar][n])+(is*frame_parms->samples_per_frame), frame_parms->ofdm_symbol_size, shift); pss_corr_ue[pss_index][n] += abs64(result); @@ -905,13 +910,13 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain int64_t result1,result2; // 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]), + (short*) &(rxdata[0][peak_position])+(is*frame_parms->samples_per_frame), 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), + (short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size+(is*frame_parms->samples_per_frame)), frame_parms->ofdm_symbol_size>>1, shift); @@ -950,7 +955,10 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain LOG_M("pss_corr_ue0.m","pss_corr_ue0",pss_corr_ue[0],length,1,6); LOG_M("pss_corr_ue1.m","pss_corr_ue1",pss_corr_ue[1],length,1,6); LOG_M("pss_corr_ue2.m","pss_corr_ue2",pss_corr_ue[2],length,1,6); - LOG_M("rxdata0.m","rxd0",rxdata[0],length,1,1); + if (is) + LOG_M("rxdata1.m","rxd0",rxdata[frame_parms->samples_per_frame],length,1,1); + else + LOG_M("rxdata0.m","rxd0",rxdata[0],length,1,1); } else { debug_cnt++; } diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 8f463b59b5..cb2200898c 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -292,7 +292,7 @@ typedef struct { /// \brief Holds the received data in time domain. /// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. /// - first index: rx antenna [0..nb_antennas_rx[ - /// - second index: sample [0..FRAME_LENGTH_COMPLEX_SAMPLES+2048[ + /// - second index: sample [0..2*FRAME_LENGTH_COMPLEX_SAMPLES+2048[ int32_t **rxdata; NR_UE_COMMON_PER_THREAD common_vars_rx_data_per_thread[RX_NB_TH_MAX]; @@ -880,8 +880,10 @@ typedef struct { int UE_scan_carrier; /// \brief Indicator that UE should enable estimation and compensation of frequency offset int UE_fo_compensation; - /// \brief Indicator that UE is synchronized to an eNB + /// \brief Indicator that UE is synchronized to a gNB int is_synchronized; + /// \brief Indicates on which frame is synchronized in a two frame synchronization + int is_synchronized_on_frame; /// Data structure for UE process scheduling UE_nr_proc_t proc; /// Flag to indicate the UE shouldn't do timing correction at all @@ -1038,6 +1040,7 @@ typedef struct { // uint8_t prach_timer; uint8_t decode_SIB; uint8_t decode_MIB; + uint8_t ssb_periodicity; /// temporary offset during cell search prior to MIB decoding int ssb_offset; uint16_t symbol_offset; // offset in terms of symbols for detected ssb in sync diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c index fd7ee6e5c9..53c6f3acc0 100644 --- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c +++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c @@ -93,10 +93,18 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) { int ssb_start_symbol, rel_slot; n_hf = cfg->sch_config.half_frame_index.value; + + // if SSB periodicity is 5ms, they are transmitted in both half frames + if ( cfg->sch_config.ssb_periodicity.value == 5) { + if (slot<10) + n_hf=0; + else + n_hf=1; + } + // to set a effective slot number between 0 to 9 in the half frame where the SSB is supposed to be rel_slot = (n_hf)? (slot-10) : slot; - LOG_D(PHY,"common_signal_procedures: frame %d, slot %d\n",frame,slot); if(rel_slot<10 && rel_slot>=0) { @@ -114,7 +122,10 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) { nr_generate_pss(gNB->d_pss, txdataF[0], AMP, ssb_start_symbol, cfg, fp); nr_generate_sss(gNB->d_sss, txdataF[0], AMP, ssb_start_symbol, cfg, fp); - nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp); + if (fp->Lmax == 4) + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp); + else + nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp); nr_generate_pbch(&gNB->pbch, pbch_pdu, @@ -137,6 +148,12 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, NR_DL_FRAME_PARMS *fp=&gNB->frame_parms; nfapi_nr_config_request_t *cfg = &gNB->gNB_config; int offset = gNB->CC_id; + uint8_t ssb_frame_periodicity; // every how many frames SSB are generated + + if (cfg->sch_config.ssb_periodicity.value < 20) + ssb_frame_periodicity = 1; + else + ssb_frame_periodicity = (cfg->sch_config.ssb_periodicity.value)/10 ; // 10ms is the frame length if ((cfg->subframe_config.duplex_mode.value == TDD) && (nr_slot_select(cfg,slot)==SF_UL)) return; @@ -149,10 +166,9 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB, memset(gNB->common_vars.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t)); } - if (nfapi_mode == 0 || nfapi_mode == 1) { - nr_common_signal_procedures(gNB,frame, slot); - //if (frame == 9) - //write_output("txdataF.m","txdataF",gNB->common_vars.txdataF[aa],fp->samples_per_frame_wCP, 1, 1); + if (nfapi_mode == 0 || nfapi_mode == 1) { + if (!(frame%ssb_frame_periodicity)) // generate SSB only for given frames according to SSB periodicity + nr_common_signal_procedures(gNB,frame, slot); } num_dci = gNB->pdcch_vars.num_dci; diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index 5a8dc96fab..ad06543718 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -123,7 +123,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t e @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying @param phy_vars_rn pointer to RN variables */ -int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t do_pdcch_flag,runmode_t mode); +int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t do_pdcch_flag,runmode_t mode,fapi_nr_pbch_config_t pbch_config); int phy_procedures_slot_parallelization_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t abstraction_flag,uint8_t do_pdcch_flag,runmode_t mode,relaying_type_t r_type); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index 0a087d5b8b..72747b03dd 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -2823,6 +2823,7 @@ void nr_ue_pbch_procedures(uint8_t eNB_id, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PBCH_PROCEDURES, VCD_FUNCTION_IN); //LOG_I(PHY,"[UE %d] Frame %d, Trying PBCH %d (NidCell %d, eNB_id %d)\n",ue->Mod_id,frame_rx,pbch_phase,ue->frame_parms.Nid_cell,eNB_id); + ret = nr_rx_pbch(ue, proc, ue->pbch_vars[eNB_id], &ue->frame_parms, @@ -2832,6 +2833,7 @@ void nr_ue_pbch_procedures(uint8_t eNB_id, ue->high_speed_flag); if (ret==0) { + ue->pbch_vars[eNB_id]->pdu_errors_conseq = 0; @@ -4330,21 +4332,45 @@ void *UE_thread_slot1_dl_processing(void *arg) { #endif +int is_pbch_in_slot(fapi_nr_pbch_config_t pbch_config, int frame, int slot, int periodicity, uint16_t slots_per_frame) { -int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, - UE_nr_rxtx_proc_t *proc, - uint8_t eNB_id, - uint8_t do_pdcch_flag, - runmode_t mode) -{ + int ssb_slot_decoded = (pbch_config.ssb_index)/2; + + if (periodicity == 5) { + // check for pbch in corresponding slot each half frame + if (pbch_config.half_frame_bit) + return(slot == ssb_slot_decoded || slot == ssb_slot_decoded - slots_per_frame/2); + else + return(slot == ssb_slot_decoded || slot == ssb_slot_decoded + slots_per_frame/2); + } + else { + // if the current frame is supposed to contain ssb + if (!((frame-(pbch_config.system_frame_number))%(periodicity/10))) + return(slot == ssb_slot_decoded); + else + return 0; + } +} + + +int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id, + uint8_t do_pdcch_flag,runmode_t mode, + fapi_nr_pbch_config_t pbch_config) { + + + + int l,l2; + int pilot1; int frame_rx = proc->frame_rx; int nr_tti_rx = proc->nr_tti_rx; + int slot_pbch; NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][0]; NR_UE_DLSCH_t **dlsch = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id]; uint8_t harq_pid = ue->dlsch[ue->current_thread_id[nr_tti_rx]][eNB_id][0]->current_harq_pid; NR_DL_UE_HARQ_t *dlsch0_harq = dlsch[0]->harq_processes[harq_pid]; uint16_t nb_symb_sch = dlsch0_harq->nb_symbols; uint8_t nb_symb_pdcch = pdcch_vars->coreset[0].duration; + uint8_t ssb_periodicity = 10;// ue->ssb_periodicity; // initialized to 5ms in nr_init_ue for scenarios where UE is not configured (otherwise acquired by cell configuration from gNB or LTE) uint8_t dci_cnt = 0; LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d ****** \n", frame_rx%1024, nr_tti_rx); @@ -4510,18 +4536,17 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT); } + slot_pbch = is_pbch_in_slot(pbch_config, frame_rx, nr_tti_rx, ssb_periodicity, ue->frame_parms.slots_per_frame); - - if ( (nr_tti_rx == 0) && (ue->decode_MIB == 1)) + // looking for pbch only in slot where it is supposed to be + if ((ue->decode_MIB == 1) && slot_pbch) { LOG_D(PHY," ------ PBCH ChannelComp/LLR: frame.slot %d.%d ------ \n", frame_rx%1024, nr_tti_rx); - uint8_t i_ssb = ue->rx_ind.rx_indication_body[0].mib_pdu.ssb_index; - uint8_t n_hf = (((ue->rx_ind.rx_indication_body[0].mib_pdu.additional_bits)>>4)&0x01); - for (int i=1; i<4; i++) { + nr_slot_fep(ue, - (ue->symbol_offset+i), //mu=1 case B + (ue->symbol_offset+i)%(ue->frame_parms.symbols_per_slot), nr_tti_rx, 0, 0); @@ -4529,7 +4554,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue, #if UE_TIMING_TRACE start_meas(&ue->dlsch_channel_estimation_stats); #endif - nr_pbch_channel_estimation(ue,0,0,ue->symbol_offset+i,i-1,i_ssb,n_hf); + nr_pbch_channel_estimation(ue,0,nr_tti_rx,(ue->symbol_offset+i)%(ue->frame_parms.symbols_per_slot),i-1,(pbch_config.ssb_index)&7,pbch_config.half_frame_bit); #if UE_TIMING_TRACE stop_meas(&ue->dlsch_channel_estimation_stats); #endif diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index f4bb3588b2..a968df8da5 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -113,7 +113,8 @@ void config_common(int Mod_idP, int CC_idP, int Nid_cell, int nr_bandP, - uint64_t ssb_pattern, + uint64_t SSB_positions, + uint16_t ssb_periodicity, uint64_t dl_CarrierFreqP, uint32_t dl_BandwidthP ); @@ -166,7 +167,7 @@ int main(int argc, char **argv) //int pbch_tx_ant; int N_RB_DL=273,mu=1; - uint64_t ssb_pattern = 0x01; + uint16_t ssb_periodicity = 10; //unsigned char frame_type = 0; unsigned char pbch_phase = 0; @@ -519,7 +520,7 @@ int main(int argc, char **argv) mac_top_init_gNB(); gNB_mac = RC.nrmac[0]; - config_common(0,0,Nid_cell,78,ssb_pattern,(uint64_t)3640000000L,N_RB_DL); + config_common(0,0,Nid_cell,78,SSB_positions,ssb_periodicity,(uint64_t)3640000000L,N_RB_DL); config_nr_mib(0,0,1,kHz30,0,0,0,0,0); nr_l2_init_ue(); @@ -678,6 +679,10 @@ int main(int argc, char **argv) UE_mac->scheduled_response.frame = frame; UE_mac->scheduled_response.slot = slot; + UE_mac->phy_config.config_req.pbch_config.system_frame_number = frame; + UE_mac->phy_config.config_req.pbch_config.ssb_index = 0; + UE_mac->phy_config.config_req.pbch_config.half_frame_bit = 0; + for (SNR=snr0; SNRis_synchronized == 0) { UE_nr_rxtx_proc_t proc={0}; - ret = nr_initial_sync(&proc, UE, normal_txrx); + ret = nr_initial_sync(&proc, UE, normal_txrx,1); printf("nr_initial_sync1 returns %d\n",ret); if (ret<0) n_errors++; } @@ -728,7 +733,8 @@ int main(int argc, char **argv) &UE_proc, 0, do_pdcch_flag, - normal_txrx); + normal_txrx, + UE_mac->phy_config.config_req.pbch_config); if (n_trials==1) { LOG_M("rxsigF0.m","rxsF0", UE->common_vars.common_vars_rx_data_per_thread[0].rxdataF[0],slot_length_complex_samples_no_prefix,1,1); diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 847fac3213..775710bb60 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -479,8 +479,7 @@ int main(int argc, char **argv) if(eps!=0.0) UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation - if (init_nr_ue_signal(UE, 1, 0) != 0) - { + if (init_nr_ue_signal(UE, 1, 0) != 0) { printf("Error at UE NR initialisation\n"); exit(-1); } @@ -601,25 +600,25 @@ int main(int argc, char **argv) if (UE->is_synchronized == 0) { UE_nr_rxtx_proc_t proc={0}; - ret = nr_initial_sync(&proc, UE, normal_txrx); + ret = nr_initial_sync(&proc, UE, normal_txrx,1); printf("nr_initial_sync1 returns %d\n",ret); if (ret<0) n_errors++; } else { UE->rx_offset=0; - uint8_t ssb_index = 0; while (!((SSB_positions >> ssb_index) & 0x01)) ssb_index++; // to select the first transmitted ssb - UE->symbol_offset = nr_get_ssb_start_symbol(frame_parms, ssb_index, n_hf); + int ssb_slot = (ssb_index/2)+(n_hf*frame_parms->slots_per_frame); for (int i=UE->symbol_offset+1; isymbol_offset+4; i++) { nr_slot_fep(UE, - i, - 0, + i%frame_parms->symbols_per_slot, + ssb_slot, 0, 0); - nr_pbch_channel_estimation(UE,0,0,i,i-(UE->symbol_offset+1),ssb_index%8,n_hf); + nr_pbch_channel_estimation(UE,0,ssb_slot,i%frame_parms->symbols_per_slot,i-(UE->symbol_offset+1),ssb_index%8,n_hf); + } UE_nr_rxtx_proc_t proc={0}; diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c index 6954b9507d..81e59a7dd2 100644 --- a/openair2/LAYER2/NR_MAC_gNB/config.c +++ b/openair2/LAYER2/NR_MAC_gNB/config.c @@ -83,9 +83,9 @@ void config_common(int Mod_idP, int cellid, int nr_bandP, uint64_t ssb_pattern, + uint16_t ssb_periodicity, uint64_t dl_CarrierFreqP, - uint32_t dl_BandwidthP - ){ + uint32_t dl_BandwidthP){ nfapi_nr_config_request_t *cfg = &RC.nrmac[Mod_idP]->config[CC_idP]; @@ -93,6 +93,7 @@ void config_common(int Mod_idP, cfg->sch_config.physical_cell_id.value = cellid; cfg->sch_config.ssb_scg_position_in_burst.value = ssb_pattern; + cfg->sch_config.ssb_periodicity.value = ssb_periodicity; // FDD cfg->subframe_config.duplex_mode.value = 1; @@ -137,6 +138,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, int p_gNB, int nr_bandP, uint64_t ssb_pattern, + uint16_t ssb_enum_periodicity, uint64_t dl_CarrierFreqP, int dl_BandwidthP, NR_BCCH_BCH_Message_t *mib, @@ -144,6 +146,30 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, ){ + uint16_t ssb_periodicity; + + switch (ssb_enum_periodicity) { + case 0: + ssb_periodicity = 5; + break; + case 1: + ssb_periodicity = 10; + break; + case 2: + ssb_periodicity = 20; + break; + case 3: + ssb_periodicity = 40; + break; + case 4: + ssb_periodicity = 80; + break; + case 5: + ssb_periodicity = 160; + break; + + } + if( mib != NULL ){ config_nr_mib(Mod_idP, CC_idP, @@ -168,6 +194,7 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP, cellid, nr_bandP, ssb_pattern, + ssb_periodicity, dl_CarrierFreqP, dl_BandwidthP ); diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h index 9e70ae7025..4f5e3b5938 100644 --- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h +++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h @@ -38,18 +38,20 @@ void mac_top_init_gNB(void); void config_common(int Mod_idP, int CC_idP, - int Nid_cell, + int Nid_cell, int nr_bandP, - uint64_t ssb_pattern, + uint64_t ssb_pattern, + uint16_t ssb_periodicity, uint64_t dl_CarrierFreqP, uint32_t dl_BandwidthP); int rrc_mac_config_req_gNB(module_id_t Mod_idP, int CC_id, - int cellid, + int cellid, int p_gNB, int nr_bandP, uint64_t ssb_pattern, + uint16_t ssb_periodicity, uint64_t dl_CarrierFreqP, int dl_BandwidthP, NR_BCCH_BCH_Message_t *mib, diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c index 92409d96dc..c7b500007d 100644 --- a/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c +++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp_fifo.c @@ -1181,7 +1181,7 @@ void pdcp_fifo_read_input_sdus_from_otg (const protocol_ctxt_t* const ctxt_pP) ctxt_pP->subframe, ctxt_pP->module_id); - for (dst_id = 0; dst_idmodule_id, CC_id, @@ -266,6 +265,7 @@ static void init_NR_SI(const protocol_ctxt_t* const ctxt_pP, RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].p_gNB, configuration->nr_band[CC_id], configuration->ServingCellConfigCommon_ssb_PositionsInBurst_PR[CC_id], + configuration->ServingCellConfigCommon_ssb_periodicityServingCell[CC_id], RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].dl_CarrierFreq, configuration->N_RB_DL[CC_id], (NR_BCCH_BCH_Message_t *)&RC.nrrrc[ctxt_pP->module_id]->carrier[CC_id].mib, diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c index 099e1c190a..b1a6644e5e 100644 --- a/targets/ARCH/rfsimulator/simulator.c +++ b/targets/ARCH/rfsimulator/simulator.c @@ -3,6 +3,12 @@ copyleft: OpenAirInterface Software Alliance and it's licence */ +/* + * Open issues and limitations + * The read and write should be called in the same thread, that is not new USRP UHD design + * When the opposite side switch from passive reading to active R+Write, the synchro is not fully deterministic + */ + #include #include #include @@ -28,7 +34,7 @@ #define sampleToByte(a,b) ((a)*(b)*sizeof(sample_t)) #define byteToSample(a,b) ((a)/(sizeof(sample_t)*(b))) -#define sample_t uint32_t // 2*16 bits complex number +#define sample_t uint32_t //2*16 bits complex number typedef struct buffer_s { int conn_sock; @@ -111,7 +117,7 @@ void setblocking(int sock, enum blocking_t active) { AssertFatal(fcntl(sock, F_SETFL, opts) >= 0, ""); } -static bool flushInput(rfsimulator_state_t *t); +static bool flushInput(rfsimulator_state_t *t, int timeout); void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { if (t->saveIQfile != -1) { @@ -134,7 +140,9 @@ void fullwrite(int fd, void *_buf, ssize_t count, rfsimulator_state_t *t) { continue; if(errno==EAGAIN) { - flushInput(t); + // The opposite side is saturated + // we read incoming sockets meawhile waiting + flushInput(t, 5); continue; } else return; @@ -229,14 +237,17 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi lastW=timestamp; LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n", nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) ); + // Let's verify we don't have incoming data + // This is mandatory when the opposite side don't transmit + flushInput(t, 0); return nsamps; } -static bool flushInput(rfsimulator_state_t *t) { +static bool flushInput(rfsimulator_state_t *t, int timeout) { // Process all incoming events on sockets // store the data in lists struct epoll_event events[FD_SETSIZE]= {0}; - int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, 20); + int nfds = epoll_wait(t->epollfd, events, FD_SETSIZE, timeout); if ( nfds==-1 ) { if ( errno==EINTR || errno==EAGAIN ) @@ -356,7 +367,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo if ( first_sock == FD_SETSIZE ) { // no connected device (we are eNB, no UE is connected) - if (!flushInput(t)) { + if (!flushInput(t, 10)) { for (int x=0; x < nbAnt; x++) memset(samplesVoid[x],0,sampleToByte(nsamps,1)); @@ -385,7 +396,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo ptr->lastReceivedTS, t->nextTimestamp+nsamps); */ - flushInput(t); + flushInput(t, 3); } while (have_to_wait); }