From c5e4bea6b957225da96cdb9f762d3418febffb3c Mon Sep 17 00:00:00 2001 From: Laurent THOMAS Date: Thu, 7 Mar 2024 15:28:22 +0100 Subject: [PATCH] make explicit return of the clock drift to shift the corresponding number of samples remove corresponding global variables --- executables/nr-ue.c | 172 ++++---- .../PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c | 72 +--- openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h | 19 +- .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c | 390 +++++++++--------- .../NR_UE_TRANSPORT/nr_transport_proto_ue.h | 12 +- openair1/PHY/defs_nr_UE.h | 9 +- openair1/SCHED_NR_UE/defs.h | 2 +- openair1/SCHED_NR_UE/phy_procedures_nr_ue.c | 16 +- openair1/SIMULATION/NR_PHY/dlsim.c | 1 - openair1/SIMULATION/NR_PHY/pbchsim.c | 23 +- 10 files changed, 331 insertions(+), 385 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 98c0443422..12d487637b 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -439,11 +439,13 @@ static void UE_synch(void *arg) { uint64_t dl_carrier, ul_carrier; nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier); - - if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa) == 0) { + nr_initial_sync_t ret = nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa); + if (!ret.cell_notdetected) { + syncD->rx_offset = ret.rx_offset; 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 * UE->frame_parms.slots_per_subframe) + - round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0); + hw_slot_offset = + ((ret.rx_offset << 1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) + + round((float)((ret.rx_offset << 1) % UE->frame_parms.samples_per_subframe) / UE->frame_parms.samples_per_slot0); // rerun with new cell parameters and frequency-offset // todo: the freq_offset computed on DL shall be scaled before being applied to UL @@ -462,7 +464,6 @@ static void UE_synch(void *arg) { else UE->is_synchronized = 1; } else { - if (UE->UE_scan_carrier == 1) { if (freq_offset >= 0) @@ -607,8 +608,9 @@ void processSlotTX(void *arg) RU_write(rxtxD); } -static void UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, nr_phy_data_t *phy_data) +static int UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *proc, int *tx_wait_for_dlsch, nr_phy_data_t *phy_data) { + int sampleShift = 0; if (IS_SOFTMODEM_NOS1 || get_softmodem_params()->sa) { // Start synchronization with a target gNB @@ -636,20 +638,16 @@ static void UE_dl_preprocessing(PHY_VARS_NR_UE *UE, const UE_nr_rxtx_proc_t *pro UE->if_inst->dl_indication(&dl_indication); } - uint64_t a=rdtsc_oai(); - pbch_pdcch_processing(UE, proc, phy_data); + sampleShift = pbch_pdcch_processing(UE, proc, phy_data); if (phy_data->dlsch[0].active && phy_data->dlsch[0].rnti_type == TYPE_C_RNTI_) { // indicate to tx thread to wait for DLSCH decoding const int ack_nack_slot = (proc->nr_slot_rx + phy_data->dlsch[0].dlsch_config.k1_feedback) % UE->frame_parms.slots_per_frame; - LOG_D(NR_PHY, "Adding one event to wait after decoding slot %d, for futre tx slot %d\n", proc->nr_slot_rx, ack_nack_slot); tx_wait_for_dlsch[ack_nack_slot]++; } - - LOG_D(PHY, "In %s: slot %d, time %llu\n", __FUNCTION__, proc->nr_slot_rx, (rdtsc_oai()-a)/3500); } ue_ta_procedures(UE, proc->nr_slot_tx, proc->frame_tx); - return; + return sampleShift; } void UE_dl_processing(void *arg) { @@ -710,37 +708,39 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) } -void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp) { - - LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset); - - if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { - // Resynchonize by slot (will work with numerology 1 only) - for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe/2 ) { - int unitTransfer=size>UE->frame_parms.samples_per_subframe/2 ? UE->frame_parms.samples_per_subframe/2 : size ; - AssertFatal(unitTransfer == - UE->rfdevice.trx_read_func(&UE->rfdevice, - timestamp, - (void **)UE->common_vars.rxdata, - unitTransfer, - UE->frame_parms.nb_antennas_rx),""); - } - } else { - *timestamp += UE->frame_parms.get_samples_per_slot(1,&UE->frame_parms); - for ( int size=UE->rx_offset ; size > 0 ; size -= UE->frame_parms.samples_per_subframe ) { - int unitTransfer=size>UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size ; - // we write before read because gNB waits for UE to write and both executions halt - // this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot - if (IS_SOFTMODEM_RFSIM) dummyWrite(UE,*timestamp, unitTransfer); - AssertFatal(unitTransfer == - UE->rfdevice.trx_read_func(&UE->rfdevice, - timestamp, - (void **)UE->common_vars.rxdata, - unitTransfer, - UE->frame_parms.nb_antennas_rx),""); - *timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write - } +static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int rx_offset) +{ + LOG_I(PHY, "Resynchronizing RX by %d samples\n", rx_offset); + if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { + // Resynchonize by slot (will work with numerology 1 only) + for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe / 2) { + int unitTransfer = size > UE->frame_parms.samples_per_subframe / 2 ? UE->frame_parms.samples_per_subframe / 2 : size; + AssertFatal(unitTransfer + == UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx), + ""); } + } else { + *timestamp += UE->frame_parms.get_samples_per_slot(1, &UE->frame_parms); + for (int size = rx_offset; size > 0; size -= UE->frame_parms.samples_per_subframe) { + int unitTransfer = size > UE->frame_parms.samples_per_subframe ? UE->frame_parms.samples_per_subframe : size; + // we write before read because gNB waits for UE to write and both executions halt + // this happens here as the read size is samples_per_subframe which is very much larger than samp_per_slot + if (IS_SOFTMODEM_RFSIM) + dummyWrite(UE, *timestamp, unitTransfer); + AssertFatal(unitTransfer + == UE->rfdevice.trx_read_func(&UE->rfdevice, + timestamp, + (void **)UE->common_vars.rxdata, + unitTransfer, + UE->frame_parms.nb_antennas_rx), + ""); + *timestamp += unitTransfer; // this does not affect the read but needed for RFSIM write + } + } } static inline int get_firstSymSamp(uint16_t slot, NR_DL_FRAME_PARMS *fp) { @@ -764,8 +764,6 @@ void *UE_thread(void *arg) //this thread should be over the processing thread to keep in real time PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg; // int tx_enabled = 0; - openair0_timestamp timestamp = 0; - openair0_timestamp writeTimestamp = 0; void *rxp[NB_ANTENNAS_RX]; int start_rx_stream = 0; fapi_nr_config_request_t *cfg = &UE->nrUE_config; @@ -796,9 +794,10 @@ void *UE_thread(void *arg) for(int i=0; i < num_ind_fifo; i++) { initNotifiedFIFO(UE->tx_resume_ind_fifo + i); } - + int shiftForNextFrame = 0; + int intialSyncOffset = 0; + openair0_timestamp sync_timestamp; while (!oai_exit) { - if (syncRunning) { notifiedFIFO_elt_t *res=tryPullTpool(&nf,&(get_nrUE_params()->Tpool)); @@ -806,25 +805,28 @@ void *UE_thread(void *arg) syncRunning=false; if (UE->is_synchronized) { decoded_frame_rx = mac->mib_frame; - LOG_I(PHY,"UE synchronized decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n", + LOG_A(PHY, + "UE synchronized! decoded_frame_rx=%d UE->init_sync_frame=%d trashed_frames=%d\n", decoded_frame_rx, UE->init_sync_frame, trashed_frames); // shift the frame index with all the frames we trashed meanwhile we perform the synch search decoded_frame_rx = (decoded_frame_rx + UE->init_sync_frame + trashed_frames) % MAX_FRAME_NUMBER; + syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(res); + intialSyncOffset = syncMsg->rx_offset; } delNotifiedFIFO_elt(res); start_rx_stream=0; } else { if (IS_SOFTMODEM_IQPLAYER || IS_SOFTMODEM_IQRECORDER) { - // For IQ recorder/player we force synchronization to happen in 280 ms + // For IQ recorder-player we force synchronization to happen in 280 ms while (trashed_frames != 28) { - readFrame(UE, ×tamp, true); - trashed_frames+=2; + readFrame(UE, &sync_timestamp, true); + trashed_frames += 2; } } else { - readFrame(UE, ×tamp, true); - trashed_frames+=2; + readFrame(UE, &sync_timestamp, true); + trashed_frames += 2; } continue; } @@ -833,7 +835,7 @@ void *UE_thread(void *arg) AssertFatal(!syncRunning, "At this point synchronization can't be running\n"); if (!UE->is_synchronized) { - readFrame(UE, ×tamp, false); + readFrame(UE, &sync_timestamp, false); notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch); syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg); syncMsg->UE = UE; @@ -846,16 +848,16 @@ void *UE_thread(void *arg) if (start_rx_stream == 0) { start_rx_stream=1; - syncInFrame(UE, ×tamp); - UE->rx_offset=0; - UE->time_sync_cell=0; + syncInFrame(UE, &sync_timestamp, intialSyncOffset); + shiftForNextFrame = 0; // will be used to track clock drift // read in first symbol - AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - (void **)UE->common_vars.rxdata, - UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, - UE->frame_parms.nb_antennas_rx),""); + AssertFatal(UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0 + == UE->rfdevice.trx_read_func(&UE->rfdevice, + &sync_timestamp, + (void **)UE->common_vars.rxdata, + UE->frame_parms.ofdm_symbol_size + UE->frame_parms.nb_prefix_samples0, + UE->frame_parms.nb_antennas_rx), + ""); // we have the decoded frame index in the return of the synch process // and we shifted above to the first slot of next frame decoded_frame_rx++; @@ -871,7 +873,7 @@ void *UE_thread(void *arg) continue; } - + // start of normal case, the UE is in sync absolute_slot++; int slot_nr = absolute_slot % nb_slot_frame; @@ -893,26 +895,21 @@ void *UE_thread(void *arg) int firstSymSamp = get_firstSymSamp(slot_nr, &UE->frame_parms); for (int i=0; iframe_parms.nb_antennas_rx; i++) - rxp[i] = (void *)&UE->common_vars.rxdata[i][firstSymSamp+ - UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,0)]; + rxp[i] = (void *)&UE->common_vars + .rxdata[i][firstSymSamp + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, 0)]; - int readBlockSize, writeBlockSize; - - readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms); - writeBlockSize = UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms); - if (UE->apply_timing_offset && (slot_nr == nb_slot_frame - 1)) { - const int sampShift = -(UE->rx_offset>>1); - readBlockSize -= sampShift; - writeBlockSize -= sampShift; - UE->apply_timing_offset = false; + int iq_shift_to_apply = 0; + if (slot_nr == nb_slot_frame - 1) { + // we shift of half of measured drift, at each beginning of frame for both rx and tx + iq_shift_to_apply = shiftForNextFrame; + shiftForNextFrame = 0; // We will get a new measured offset if we decode PBCH } - AssertFatal(readBlockSize == - UE->rfdevice.trx_read_func(&UE->rfdevice, - ×tamp, - rxp, - readBlockSize, - UE->frame_parms.nb_antennas_rx),""); + const int readBlockSize = get_readBlockSize(slot_nr, &UE->frame_parms) - iq_shift_to_apply; + openair0_timestamp rx_timestamp; + AssertFatal(readBlockSize + == UE->rfdevice.trx_read_func(&UE->rfdevice, &rx_timestamp, rxp, readBlockSize, UE->frame_parms.nb_antennas_rx), + ""); if(slot_nr == (nb_slot_frame - 1)) { // read in first symbol of next frame and adjust for timing drift @@ -931,11 +928,13 @@ void *UE_thread(void *arg) } // use previous timing_advance value to compute writeTimestamp - writeTimestamp = timestamp + - UE->frame_parms.get_samples_slot_timestamp(slot_nr,&UE->frame_parms,DURATION_RX_TO_TX) - - firstSymSamp - UE->N_TA_offset - timing_advance; + const openair0_timestamp writeTimestamp = + rx_timestamp + UE->frame_parms.get_samples_slot_timestamp(slot_nr, &UE->frame_parms, DURATION_RX_TO_TX) - firstSymSamp + - UE->N_TA_offset - timing_advance; // but use current UE->timing_advance value to compute writeBlockSize + int writeBlockSize = + UE->frame_parms.get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, &UE->frame_parms) - iq_shift_to_apply; if (UE->timing_advance != timing_advance) { writeBlockSize -= UE->timing_advance - timing_advance; timing_advance = UE->timing_advance; @@ -948,7 +947,12 @@ void *UE_thread(void *arg) notifiedFIFO_elt_t *newRx = newNotifiedFIFO_elt(sizeof(nr_rxtx_thread_data_t), curMsg.proc.nr_slot_rx, NULL, UE_dl_processing); nr_rxtx_thread_data_t *curMsgRx = (nr_rxtx_thread_data_t *)NotifiedFifoData(newRx); *curMsgRx = (nr_rxtx_thread_data_t){.proc = curMsg.proc, .UE = UE}; - UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data); + int ret = UE_dl_preprocessing(UE, &curMsgRx->proc, tx_wait_for_dlsch, &curMsgRx->phy_data); + if (ret) + // if ret is 0, no rx_offset has been computed, + // or the computed value is 0 = no offset to do + // we store it to apply the drift compensation at beginning of next frame + shiftForNextFrame = ret; pushTpool(&(get_nrUE_params()->Tpool), newRx); // Start TX slot processing here. It runs in parallel with RX slot processing diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c index e9d159ff4b..bcac18a60b 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_adjust_synch_ue.c @@ -33,29 +33,22 @@ // The adjustment is performed once per frame based on the // last channel estimate of the receiver -void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, - PHY_VARS_NR_UE *ue, - module_id_t gNB_id, - const int estimateSz, - struct complex16 dl_ch_estimates_time[][estimateSz], - uint8_t frame, - uint8_t subframe, - unsigned char clear, - short coef) +int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, + PHY_VARS_NR_UE *ue, + module_id_t gNB_id, + const int estimateSz, + struct complex16 dl_ch_estimates_time[][estimateSz], + uint8_t frame, + uint8_t slot, + short coef) { - - static int count_max_pos_ok = 0; - static int first_time = 1; int max_val = 0, max_pos = 0; - const int sync_pos = 0; uint8_t sync_offset = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN); short ncoef = 32767 - coef; - LOG_D(PHY,"AbsSubframe %d: rx_offset (before) = %d\n",subframe,ue->rx_offset); - // search for maximum position within the cyclic prefix for (int i = -frame_parms->nb_prefix_samples/2; i < frame_parms->nb_prefix_samples/2; i++) { int temp = 0; @@ -74,53 +67,32 @@ void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, } // filter position to reduce jitter - if (clear == 1) - ue->max_pos_fil = max_pos << 15; - else - ue->max_pos_fil = ((ue->max_pos_fil * coef) >> 15) + (max_pos * ncoef); + ue->max_pos_avg = ((ue->max_pos_avg * coef) >> 15) + (max_pos * ncoef); - // do not filter to have proactive timing adjustment - //ue->max_pos_fil = max_pos << 15; - - int diff = (ue->max_pos_fil >> 15) - sync_pos; + int diff = ue->max_pos_avg >> 15; if (frame_parms->freq_range==nr_FR2) sync_offset = 2; else sync_offset = 0; - if ( abs(diff) < (SYNCH_HYST+sync_offset) ) - ue->rx_offset = 0; - else - ue->rx_offset = diff; + int sampleShift = 0; + if (abs(diff) > (NR_SYNCH_HYST + sync_offset)) + sampleShift = diff; - const int sample_shift = -(ue->rx_offset>>1); + const int sample_shift = -(sampleShift / 2); // reset IIR filter for next offset calculation - ue->max_pos_fil += sample_shift * 32768; + ue->max_pos_avg += sample_shift * 32768; - if(abs(diff)<5) - count_max_pos_ok ++; - else - count_max_pos_ok = 0; - - //printf("adjust sync count_max_pos_ok = %d\n",count_max_pos_ok); - - if(count_max_pos_ok > 10 && first_time == 1) { - first_time = 0; - ue->time_sync_cell = 1; - } - -#ifdef DEBUG_PHY - LOG_I(PHY,"AbsSubframe %d: diff = %i, rx_offset (final) = %i : clear = %d, max_pos = %d, max_pos_fil = %d, max_val = %d, sync_pos %d\n", - subframe, + LOG_D(PHY, + "Slot %d: diff = %i, rx_offset (final) = %i : max_pos = %d, max_pos filtered = %ld, max_power = %d\n", + slot, diff, - ue->rx_offset, - clear, + sampleShift, max_pos, - ue->max_pos_fil, - max_val, - sync_pos); -#endif //DEBUG_PHY + ue->max_pos_avg, + max_val); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT); + return sample_shift; } diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h index 14aa39c0a0..f47d49f877 100644 --- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h +++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h @@ -30,7 +30,7 @@ */ /*!\brief Timing drift hysterisis in samples*/ -#define SYNCH_HYST 2 +#define NR_SYNCH_HYST 1 /* A function to perform the channel estimation of DL PRS signal */ int nr_prs_channel_estimation(uint8_t gNB_id, @@ -91,15 +91,14 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue, int rxdataFsize, c16_t rxdataF[][rxdataFsize]); -void nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, - PHY_VARS_NR_UE *ue, - module_id_t gNB_id, - int estimateSz, - struct complex16 dl_ch_estimates_time [][estimateSz], - uint8_t frame, - uint8_t subframe, - unsigned char clear, - short coef); +int nr_adjust_synch_ue(NR_DL_FRAME_PARMS *frame_parms, + PHY_VARS_NR_UE *ue, + module_id_t gNB_id, + int estimateSz, + struct complex16 dl_ch_estimates_time[][estimateSz], + uint8_t frame, + uint8_t subframe, + short coef); void nr_ue_measurements(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c index 56631c75ea..9e6a8bf7e5 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c @@ -50,7 +50,7 @@ extern openair0_config_t openair0_cfg[]; //static nfapi_nr_config_request_t* config =&config_t; int cnt=0; -#define DEBUG_INITIAL_SYNCH +// #define DEBUG_INITIAL_SYNCH #define DUMP_PBCH_CH_ESTIMATES 0 // create a new node of SSB structure @@ -111,11 +111,6 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, NR_UE_SSB *best_ssb = NULL; NR_UE_SSB *current_ssb; -#ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id, - ue->rx_offset); -#endif - uint8_t N_L = (frame_parms->Lmax == 4)? 4:8; uint8_t N_hf = (frame_parms->Lmax == 4)? 2:1; @@ -129,7 +124,7 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, start_meas(&ue->dlsch_channel_estimation_stats); // computing correlation between received DMRS symbols and transmitted sequence for current i_ssb and n_hf for(int i=pbch_initial_symbol; idlsch_channel_estimation_stats); current_ssb->metric = current_ssb->c_re*current_ssb->c_re + current_ssb->c_im*current_ssb->c_im; @@ -147,7 +142,7 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, while (ret!=0 && temp_ptr != NULL) { start_meas(&ue->dlsch_channel_estimation_stats); - // computing channel estimation for selected best ssb + // computing channel estimation for selected best ssb const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; __attribute__ ((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz]; __attribute__ ((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size]; @@ -178,242 +173,230 @@ int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, free_list(best_ssb); - - if (ret==0) { - - frame_parms->nb_antenna_ports_gNB = 1; //pbch_tx_ant; - - // set initial transmission mode to 1 or 2 depending on number of detected TX antennas - //frame_parms->mode1_flag = (pbch_tx_ant==1); - // openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1; + if (ret == 0) + frame_parms->nb_antenna_ports_gNB = 1; // pbch_tx_ant; + // set initial transmission mode to 1 or 2 depending on number of detected TX antennas + // frame_parms->mode1_flag = (pbch_tx_ant==1); + // openair_daq_vars.dlsch_transmission_mode = (pbch_tx_ant>1) ? 2 : 1; -#ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index); -#endif - return(0); - } else { - return(-1); - } - + LOG_I(PHY, "[UE%d] Initial sync: pbch decoded sucessfully, ssb index %d\n", ue->Mod_id, frame_parms->ssb_index); + return ret; } -int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa) +nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_frames, int sa) { - int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2, - int32_t metric_tdd_ncp=0; + int32_t metric_tdd_ncp = 0; uint8_t phase_tdd_ncp; int frame_id; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - int ret=-1; - int rx_power=0; //aarx, - + nr_initial_sync_t ret = {true, 0}; + VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_IN); - - LOG_D(PHY,"nr_initial sync ue RB_DL %d\n", fp->N_RB_DL); + LOG_D(PHY, "nr_initial sync ue RB_DL %d\n", fp->N_RB_DL); /* Initial synchronisation * - * 1 radio frame = 10 ms - * <---------------------------------------------------------------------------> - * ----------------------------------------------------------------------------- - * | Received UE data buffer | - * ---------------------------------------------------------------------------- - * -------------------------- - * <-------------->| pss | pbch | sss | pbch | - * -------------------------- - * sync_pos SS/PBCH block - */ + * 1 radio frame = 10 ms + * <---------------------------------------------------------------------------> + * ----------------------------------------------------------------------------- + * | Received UE data buffer | + * ---------------------------------------------------------------------------- + * -------------------------- + * <-------------->| pss | pbch | sss | pbch | + * -------------------------- + * sync_pos SS/PBCH block + */ const uint32_t rxdataF_sz = ue->frame_parms.samples_per_slot_wCP; - __attribute__ ((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; + __attribute__((aligned(32))) c16_t rxdataF[ue->frame_parms.nb_antennas_rx][rxdataF_sz]; cnt++; - if (1){ // (cnt>100) - cnt =0; + if (1) { // (cnt>100) + cnt = 0; - // 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 (frame_id = 0; frame_id < n_frames; frame_id++) { - /* process pss search on received buffer */ - sync_pos = pss_synchro_nr(ue, frame_id, NO_RATE_CHANGE); - if (sync_pos < fp->nb_prefix_samples) - continue; + // 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 (frame_id = 0; frame_id < n_frames; frame_id++) { + /* process pss search on received buffer */ + sync_pos = pss_synchro_nr(ue, frame_id, NO_RATE_CHANGE); + if (sync_pos < fp->nb_prefix_samples) + continue; - ue->ssb_offset = sync_pos - fp->nb_prefix_samples; + ue->ssb_offset = sync_pos - 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.nid2); - 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.nid2); + LOG_I(PHY, "sync_pos %d ssb_offset %d \n", sync_pos, ue->ssb_offset); #endif - /* check that SSS/PBCH block is continuous inside the received buffer */ - if (ue->ssb_offset + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples) < fp->samples_per_frame) { + /* check that SSS/PBCH block is continuous inside the received buffer */ + if (ue->ssb_offset + NR_N_SYMBOLS_SSB * (fp->ofdm_symbol_size + fp->nb_prefix_samples) < fp->samples_per_frame) { + // 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 - // 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 + // In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1 + // and we do not know yet in which slot it goes. - // In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1 - // and we do not know yet in which slot it goes. - - for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) { - for (int ar=0; arnb_antennas_rx; ar++) { - const double re = ue->common_vars.rxdata[ar][n].r; - const double im = ue->common_vars.rxdata[ar][n].i; - ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle))); - ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle))); - } - } - } - - /* slot_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 */ - /* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */ - /* symbol number are from beginning of SS/PBCH blocks as below: */ - /* Signal PSS PBCH SSS PBCH */ - /* symbol number 0 1 2 3 */ - /* 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 < NR_N_SYMBOLS_SSB; i++) - nr_slot_fep_init_sync(ue, proc, i, frame_id * fp->samples_per_frame + ue->ssb_offset, false, rxdataF, link_type_dl); - -#ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"Calling sss detection (normal CP)\n"); -#endif - - int freq_offset_sss = 0; - bool ret_sss = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss, rxdataF); - ret = !ret_sss; - // 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*freq_offset_sss; // offset rotation angle compensation per sample - - // In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1 - // and we do not know yet in which slot it goes. - for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) { - for (int ar=0; arnb_antennas_rx; ar++) { - const double re = ue->common_vars.rxdata[ar][n].r; - const double im = ue->common_vars.rxdata[ar][n].i; - ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle))); - ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle))); + for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) { + for (int ar = 0; ar < fp->nb_antennas_rx; ar++) { + const double re = ue->common_vars.rxdata[ar][n].r; + const double im = ue->common_vars.rxdata[ar][n].i; + ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle))); + ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle))); + } } } - ue->common_vars.freq_offset += freq_offset_sss; - } - - if (ret==0) { //we got sss channel - nr_gold_pbch(ue); - ret = nr_pbch_detection(proc, ue, 1, rxdataF); // 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 - int mu = fp->numerology_index; - // number of symbols with different prefix length - // every 7*(1<symbol_offset/(7*(1<ofdm_symbol_size + fp->nb_prefix_samples0)+(ue->symbol_offset-n_symb_prefix0)*(fp->ofdm_symbol_size + fp->nb_prefix_samples); - // for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of the n_frames we got sync - ue->init_sync_frame = n_frames - 1 - frame_id; - - // compute the scramblingID_pdcch and the gold pdcch - ue->scramblingID_pdcch = fp->Nid_cell; - nr_gold_pdcch(ue,fp->Nid_cell); - - // compute the scrambling IDs for PDSCH DMRS - for (int i=0; iscramblingID_dlsch[i]=fp->Nid_cell; - nr_gold_pdsch(ue, i, ue->scramblingID_dlsch[i]); - } - - nr_init_csi_rs(fp, ue->nr_csi_info->nr_gold_csi_rs, fp->Nid_cell); - - // initialize the pusch dmrs - for (int i=0; iscramblingID_ulsch[i]=fp->Nid_cell; - nr_init_pusch_dmrs(ue, ue->scramblingID_ulsch[i], i); - } - - - // we also need to take into account the shift by samples_per_frame in case the if is true - if (ue->ssb_offset < sync_pos_frame){ - ue->rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset; - ue->init_sync_frame += 1; - } - else - ue->rx_offset = ue->ssb_offset - sync_pos_frame; - } - - /* - int nb_prefix_samples0 = fp->nb_prefix_samples0; - fp->nb_prefix_samples0 = fp->nb_prefix_samples; - - nr_slot_fep(ue, proc, 0, 0, ue->ssb_offset, 0, NR_PDCCH_EST); - nr_slot_fep(ue, proc, 1, 0, ue->ssb_offset, 0, NR_PDCCH_EST); - fp->nb_prefix_samples0 = nb_prefix_samples0; - - LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n", - ue->Mod_id, - ue->proc.proc_rxtx[0].frame_rx, - ue->rx_offset, - ue->common_vars.freq_offset ); - */ + /* slot_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 */ + /* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */ + /* symbol number are from beginning of SS/PBCH blocks as below: */ + /* Signal PSS PBCH SSS PBCH */ + /* symbol number 0 1 2 3 */ + /* 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 < NR_N_SYMBOLS_SSB; i++) + nr_slot_fep_init_sync(ue, proc, i, frame_id * fp->samples_per_frame + ue->ssb_offset, false, rxdataF, link_type_dl); #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, "Calling sss detection (normal CP)\n"); #endif - } - else { + int freq_offset_sss = 0; + bool ret_sss = rx_sss_nr(ue, proc, &metric_tdd_ncp, &phase_tdd_ncp, &freq_offset_sss, rxdataF); + ret.cell_notdetected = !ret_sss; // rx_sss_nr returns true if success + // 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 * freq_offset_sss; // offset rotation angle compensation per sample + + // In SA we need to perform frequency offset correction until the end of buffer because we need to decode SIB1 + // and we do not know yet in which slot it goes. + for (int n = frame_id * fp->samples_per_frame; n < (frame_id + 1) * fp->samples_per_frame; n++) { + for (int ar = 0; ar < fp->nb_antennas_rx; ar++) { + const double re = ue->common_vars.rxdata[ar][n].r; + const double im = ue->common_vars.rxdata[ar][n].i; + ue->common_vars.rxdata[ar][n].r = (short)(round(re * cos(n * off_angle) - im * sin(n * off_angle))); + ue->common_vars.rxdata[ar][n].i = (short)(round(re * sin(n * off_angle) + im * cos(n * off_angle))); + } + } + + ue->common_vars.freq_offset += freq_offset_sss; + } + + if (ret.cell_notdetected == 0) { // we got sss channel + nr_gold_pbch(ue); + ret.cell_notdetected = nr_pbch_detection(proc, ue, 1, rxdataF); // start pbch detection at first symbol after pss + } + + if (ret.cell_notdetected == 0) { + // sync at symbol ue->symbol_offset + // computing the offset wrt the beginning of the frame + int mu = fp->numerology_index; + // number of symbols with different prefix length + // every 7*(1<symbol_offset / (7 * (1 << mu))) + 1; + sync_pos_frame = n_symb_prefix0 * (fp->ofdm_symbol_size + fp->nb_prefix_samples0) + + (ue->symbol_offset - n_symb_prefix0) * (fp->ofdm_symbol_size + fp->nb_prefix_samples); + // for a correct computation of frame number to sync with the one decoded at MIB we need to take into account in which of + // the n_frames we got sync + ue->init_sync_frame = n_frames - 1 - frame_id; + + // compute the scramblingID_pdcch and the gold pdcch + ue->scramblingID_pdcch = fp->Nid_cell; + nr_gold_pdcch(ue, fp->Nid_cell); + + // compute the scrambling IDs for PDSCH DMRS + for (int i = 0; i < NR_NB_NSCID; i++) { + ue->scramblingID_dlsch[i] = fp->Nid_cell; + nr_gold_pdsch(ue, i, ue->scramblingID_dlsch[i]); + } + + nr_init_csi_rs(fp, ue->nr_csi_info->nr_gold_csi_rs, fp->Nid_cell); + + // initialize the pusch dmrs + for (int i = 0; i < NR_NB_NSCID; i++) { + ue->scramblingID_ulsch[i] = fp->Nid_cell; + nr_init_pusch_dmrs(ue, ue->scramblingID_ulsch[i], i); + } + + // we also need to take into account the shift by samples_per_frame in case the if is true + if (ue->ssb_offset < sync_pos_frame) { + ret.rx_offset = fp->samples_per_frame - sync_pos_frame + ue->ssb_offset; + ue->init_sync_frame += 1; + } else + ret.rx_offset = ue->ssb_offset - sync_pos_frame; + } + + /* + int nb_prefix_samples0 = fp->nb_prefix_samples0; + fp->nb_prefix_samples0 = fp->nb_prefix_samples; + + nr_slot_fep(ue, proc, 0, 0, ue->ssb_offset, 0, NR_PDCCH_EST); + nr_slot_fep(ue, proc, 1, 0, ue->ssb_offset, 0, NR_PDCCH_EST); + fp->nb_prefix_samples0 = nb_prefix_samples0; + + LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : frame = %d, rx_offset %d, freq_offset %d \n", + ue->Mod_id, + ue->proc.proc_rxtx[0].frame_rx, + ue->rx_offset, + ue->common_vars.freq_offset ); + */ + #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: CellId %d metric %d, phase %d, pbch detected %d, measured offset %d\n", + fp->Nid_cell, + metric_tdd_ncp, + phase_tdd_ncp, + !ret.cell_notdetected, + ret.rx_offset); +#endif + + } else { +#ifdef DEBUG_INITIAL_SYNCH + LOG_I(PHY, "TDD Normal prefix: SSS error condition: sync_pos %d\n", sync_pos); #endif } - if (ret == 0) break; - } - } - else { - ret = -1; + if (ret.cell_notdetected == 0) + break; + } + } else { + ret.cell_notdetected = true; } - /* 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; - LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset); - }*/ + if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) ) + { + ret=-1; + LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset); + }*/ - if (ret==0) { // PBCH found so indicate sync to higher layers and configure frame parameters + if (ret.cell_notdetected == 0) { // PBCH found so indicate sync to higher layers and configure frame parameters //#ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n",ue->Mod_id, ue->rx_offset); + LOG_I(PHY, "[UE%d] In synch, rx_offset %d samples\n", ue->Mod_id, ret.rx_offset); //#endif if (ue->UE_scan_carrier == 0) { +#if UE_AUTOTEST_TRACE + LOG_I(PHY, + "[UE %d] AUTOTEST Cell Sync : rx_offset %d, freq_offset %d \n", + ue->Mod_id, + ue->rx_offset, + ue->common_vars.freq_offset); +#endif - #if UE_AUTOTEST_TRACE - LOG_I(PHY,"[UE %d] AUTOTEST Cell Sync : rx_offset %d, freq_offset %d \n", - ue->Mod_id, - ue->rx_offset, - ue->common_vars.freq_offset ); - #endif - -// send sync status to higher layers later when timing offset converge to target timing - + // send sync status to higher layers later when timing offset converge to target timing } LOG_I(PHY, @@ -428,23 +411,22 @@ int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_fra LOG_I(PHY,"[UE%d] Initial sync : Estimated Nid_cell %d, Frame_type %d\n",ue->Mod_id, frame_parms->Nid_cell,frame_parms->frame_type); #endif - } // gain control - if (ret!=0) { //we are not synched, so we cannot use rssi measurement (which is based on channel estimates) - rx_power = 0; + if (ret.cell_notdetected != 0) { // we are not synched, so we cannot use rssi measurement (which is based on channel estimates) + int rx_power = 0; // do a measurement on the best guess of the PSS - //for (aarx=0; aarxnb_antennas_rx; aarx++) + // for (aarx=0; aarxnb_antennas_rx; aarx++) // rx_power += signal_energy(&ue->common_vars.rxdata[aarx][sync_pos2], - // frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); + // frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples); /* // do a measurement on the full frame for (aarx=0; aarxnb_antennas_rx; aarx++) - rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0], - frame_parms->samples_per_subframe*10); + rx_power += signal_energy(&ue->common_vars.rxdata[aarx][0], + frame_parms->samples_per_subframe*10); */ // we might add a low-pass filter here later @@ -453,12 +435,10 @@ int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *ue, int n_fra ue->measurements.rx_power_avg_dB[0] = dB_fixed(ue->measurements.rx_power_avg[0]); #ifdef DEBUG_INITIAL_SYNCH - LOG_I(PHY,"[UE%d] Initial sync : Estimated power: %d dB\n",ue->Mod_id,ue->measurements.rx_power_avg_dB[0] ); + LOG_I(PHY, "[UE%d] Initial sync : Estimated power: %d dB\n", ue->Mod_id, ue->measurements.rx_power_avg_dB[0]); #endif - } // exit_fun("debug exit"); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_NR_INITIAL_UE_SYNC, VCD_FUNCTION_OUT); return ret; } - 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 69169c1744..6888f36434 100644 --- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h +++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h @@ -287,6 +287,7 @@ int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uin /*! \brief receiver for the PBCH \returns number of tx antennas or -1 if error */ + int nr_rx_pbch(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, const int estimateSz, @@ -297,11 +298,6 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue, fapiPbch_t *result, c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); -int nr_pbch_detection(const UE_nr_rxtx_proc_t *proc, - PHY_VARS_NR_UE *ue, - int pbch_initial_symbol, - c16_t rxdataF[][ue->frame_parms.samples_per_slot_wCP]); - #ifndef modOrder #define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS #endif @@ -323,7 +319,11 @@ int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, @param n_frames @param sa current running mode */ -int nr_initial_sync(const UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, int n_frames, int sa); +typedef struct { + bool cell_notdetected; + int rx_offset; +} nr_initial_sync_t; +nr_initial_sync_t nr_initial_sync(UE_nr_rxtx_proc_t *proc, PHY_VARS_NR_UE *phy_vars_ue, int n_frames, int sa); /*! \brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index bb77dac067..37a6c59854 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -485,12 +485,8 @@ typedef struct PHY_VARS_NR_UE_s { uint8_t init_sync_frame; /// 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 - int rx_offset; /// Timing offset - int rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP - int64_t max_pos_fil; /// Timing offset IIR filter - bool apply_timing_offset; /// Do time sync for current frame - int time_sync_cell; + uint16_t symbol_offset; /// offset in terms of symbols for detected ssb in sync + int64_t max_pos_avg; /// Timing offset IIR filter /// Timing Advance updates variables /// Timing advance update computed from the TA command signalled from gNB @@ -644,6 +640,7 @@ typedef struct nr_rxtx_thread_data_s { int writeBlockSize; nr_phy_data_t phy_data; int tx_wait_for_dlsch; + int rx_offset; } nr_rxtx_thread_data_t; typedef struct LDPCDecode_ue_s { diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h index b3ce6944bb..f6b33359c8 100644 --- a/openair1/SCHED_NR_UE/defs.h +++ b/openair1/SCHED_NR_UE/defs.h @@ -98,7 +98,7 @@ typedef struct { */ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_tx_t *phy_data); -void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); +int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data); diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c index f1c9ce4066..35212ef12d 100644 --- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c +++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c @@ -826,7 +826,7 @@ static bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t * return dec; } -void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) +int pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) { int frame_rx = proc->frame_rx; int nr_slot_rx = proc->nr_slot_rx; @@ -834,6 +834,7 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr fapi_nr_config_request_t *cfg = &ue->nrUE_config; NR_DL_FRAME_PARMS *fp = &ue->frame_parms; NR_UE_PDCCH_CONFIG *phy_pdcch_config = &phy_data->phy_pdcch_config; + int sampleShift = 0; nr_ue_dlsch_init(phy_data->dlsch, NR_MAX_NB_LAYERS>4 ? 2:1, ue->max_ldpc_iterations); VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN); @@ -896,17 +897,9 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr if (ue->no_timing_correction==0 && pbchSuccess == 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, - gNB_id, - fp->ofdm_symbol_size, - dl_ch_estimates_time, - frame_rx, - nr_slot_rx, - 0, - 16384); + sampleShift = + nr_adjust_synch_ue(fp, ue, gNB_id, fp->ofdm_symbol_size, dl_ch_estimates_time, frame_rx, nr_slot_rx, 16384); } - ue->apply_timing_offset = true; } LOG_D(PHY, "Doing N0 measurements in %s\n", __FUNCTION__); nr_ue_rrc_measurements(ue, proc, rxdataF); @@ -996,6 +989,7 @@ void pbch_pdcch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr LOG_D(PHY,"[UE %d] Frame %d, nr_slot_rx %d: found %d DCIs\n", ue->Mod_id, frame_rx, nr_slot_rx, dci_cnt); phy_pdcch_config->nb_search_space = 0; VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP_PDCCH, VCD_FUNCTION_OUT); + return sampleShift; } void pdsch_processing(PHY_VARS_NR_UE *ue, const UE_nr_rxtx_proc_t *proc, nr_phy_data_t *phy_data) diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c index bb0b8cbe6f..e2f1916a5b 100644 --- a/openair1/SIMULATION/NR_PHY/dlsim.c +++ b/openair1/SIMULATION/NR_PHY/dlsim.c @@ -959,7 +959,6 @@ int main(int argc, char **argv) //multipath channel //multipath_channel(gNB2UE,s_re,s_im,r_re,r_im,frame_length_complex_samples,0); - UE->rx_offset=0; UE_proc.frame_rx = frame; UE_proc.nr_slot_rx = slot; UE_proc.gNB_id = 0; diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c index 9f084f190c..bfd23b7ffc 100644 --- a/openair1/SIMULATION/NR_PHY/pbchsim.c +++ b/openair1/SIMULATION/NR_PHY/pbchsim.c @@ -766,21 +766,22 @@ int main(int argc, char **argv) } if (UE->is_synchronized == 0) { UE_nr_rxtx_proc_t proc={0}; - ret = nr_initial_sync(&proc, UE, 1, 0); - printf("nr_initial_sync1 returns %d\n",ret); - if (ret<0) n_errors++; + nr_initial_sync_t ret = nr_initial_sync(&proc, UE, 1, 0); + printf("nr_initial_sync1 returns %d\n", ret.cell_notdetected); + if (ret.cell_notdetected) + n_errors++; } else { UE_nr_rxtx_proc_t proc={0}; - UE->rx_offset=0; - uint8_t ssb_index = 0; - const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; - __attribute__((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz]; - __attribute__((aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size]; - 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); + uint8_t ssb_index = 0; + const int estimateSz = frame_parms->symbols_per_slot * frame_parms->ofdm_symbol_size; + __attribute__((aligned(32))) struct complex16 dl_ch_estimates[frame_parms->nb_antennas_rx][estimateSz]; + __attribute__(( + aligned(32))) struct complex16 dl_ch_estimates_time[frame_parms->nb_antennas_rx][frame_parms->ofdm_symbol_size]; + 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); int ssb_slot = (UE->symbol_offset/14)+(n_hf*(frame_parms->slots_per_frame>>1)); proc.nr_slot_rx = ssb_slot;