From 400926115e79ad900c1d1e6d1868989ef376e2e7 Mon Sep 17 00:00:00 2001 From: Thomas Schlichter Date: Thu, 3 Apr 2025 13:30:28 +0000 Subject: [PATCH] NR UE: fix reestablishment for NTN During reestablishment the UE goes back to not synchronized state. While the synchronizatin is running, we trash frames using the function readFrame(). And when we successfully synchronize, we skip samples to align with the start of the frame using syncInFrame(). In rfsimulator mode, both of these functions send dummy data using the function dummyWrite(). Unfortunately, the writeTimestamp provided to that function was always assuming a duration from RX to TX of NR_UE_CAPABILITY_SLOT_RX_TO_TX. But in NTN mode, this value is changed when receiving SIB19. Therefore we have to consider this changed value instead of the static one. --- executables/nr-ue.c | 37 +++++++++++++++++++++---------------- 1 file changed, 21 insertions(+), 16 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index d0a8f27a0f..345a12d99a 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -825,7 +825,8 @@ void dummyWrite(PHY_VARS_NR_UE *UE,openair0_timestamp timestamp, int writeBlockS AssertFatal(writeBlockSize == tmp, ""); } -void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) { +void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, bool toTrash) +{ NR_DL_FRAME_PARMS *fp = &UE->frame_parms; // two frames for initial sync int num_frames = 2; @@ -853,7 +854,8 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) AssertFatal(read_block_size == tmp, ""); if (IS_SOFTMODEM_RFSIM) { - const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset; + const openair0_timestamp writeTimestamp = + *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance; dummyWrite(UE, writeTimestamp, fp->get_samples_per_slot(slot, fp)); } } @@ -864,7 +866,7 @@ void readFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, bool toTrash) free(rxp[i]); } -static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, openair0_timestamp rx_offset) +static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, int duration_rx_to_tx, openair0_timestamp rx_offset) { NR_DL_FRAME_PARMS *fp = &UE->frame_parms; if (UE->sl_mode == 2) @@ -879,7 +881,8 @@ static void syncInFrame(PHY_VARS_NR_UE *UE, openair0_timestamp *timestamp, opena const int res = UE->rfdevice.trx_read_func(&UE->rfdevice, timestamp, (void **)UE->common_vars.rxdata, unitTransfer, fp->nb_antennas_rx); DevAssert(unitTransfer == res); if (IS_SOFTMODEM_RFSIM) { - const openair0_timestamp writeTimestamp = *timestamp + fp->get_samples_slot_timestamp(slot, fp, NR_UE_CAPABILITY_SLOT_RX_TO_TX) - UE->N_TA_offset; + const openair0_timestamp writeTimestamp = + *timestamp + fp->get_samples_slot_timestamp(slot, fp, duration_rx_to_tx) - UE->N_TA_offset - UE->timing_advance; dummyWrite(UE, writeTimestamp, unitTransfer); } slot = (slot + 1) % fp->slots_per_subframe; @@ -965,6 +968,10 @@ void *UE_thread(void *arg) notifiedFIFO_t freeBlocks; initNotifiedFIFO_nothreadSafe(&freeBlocks); + double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift; + int ntn_koffset = 0; + + int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX; int timing_advance = UE->timing_advance; UE->N_TA_offset = determine_N_TA_offset(UE); NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id); @@ -988,13 +995,9 @@ void *UE_thread(void *arg) //warm up the RF board int64_t tmp; for (int i = 0; i < 50; i++) - readFrame(UE, &tmp, true); + readFrame(UE, &tmp, duration_rx_to_tx, true); } - double ntn_init_time_drift = get_nrUE_params()->ntn_init_time_drift; - int ntn_koffset = 0; - int duration_rx_to_tx = NR_UE_CAPABILITY_SLOT_RX_TO_TX; - while (!oai_exit) { if (syncRunning) { notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf); @@ -1034,11 +1037,11 @@ void *UE_thread(void *arg) */ const unsigned int sync_in_frames = UE->rfdevice.openair0_cfg->recplay_conf->u_f_sync; while (trashed_frames != sync_in_frames) { - readFrame(UE, &sync_timestamp, true); + readFrame(UE, &sync_timestamp, duration_rx_to_tx, true); trashed_frames += 2; } } else { - readFrame(UE, &sync_timestamp, true); + readFrame(UE, &sync_timestamp, duration_rx_to_tx, true); trashed_frames += ((UE->sl_mode == 2) ? SL_NR_PSBCH_REPETITION_IN_FRAMES : 2); } continue; @@ -1048,7 +1051,7 @@ void *UE_thread(void *arg) AssertFatal(!syncRunning, "At this point synchronization can't be running\n"); if (!UE->is_synchronized) { - readFrame(UE, &sync_timestamp, false); + readFrame(UE, &sync_timestamp, duration_rx_to_tx, false); notifiedFIFO_elt_t *Msg = newNotifiedFIFO_elt(sizeof(syncData_t), 0, &nf, UE_synch); syncData_t *syncMsg = (syncData_t *)NotifiedFifoData(Msg); *syncMsg = (syncData_t){0}; @@ -1065,8 +1068,10 @@ void *UE_thread(void *arg) syncMsg->UE = UE; memset(&syncMsg->proc, 0, sizeof(syncMsg->proc)); pushNotifiedFIFO(&UE->sync_actor.fifo, Msg); - timing_advance = 0; - UE->timing_advance = 0; + if (ntn_koffset == 0) { // reset timing_advance for TN + timing_advance = 0; + UE->timing_advance = 0; + } trashed_frames = 0; syncRunning = true; continue; @@ -1074,7 +1079,7 @@ void *UE_thread(void *arg) if (stream_status == STREAM_STATUS_UNSYNC) { stream_status = STREAM_STATUS_SYNCING; - syncInFrame(UE, &sync_timestamp, intialSyncOffset); + syncInFrame(UE, &sync_timestamp, duration_rx_to_tx, intialSyncOffset); openair0_write_reorder_clear_context(&UE->rfdevice); if (get_nrUE_params()->time_sync_I) // ntn_init_time_drift is in µs/s, max_pos_acc * time_sync_I is in samples/frame @@ -1200,7 +1205,7 @@ void *UE_thread(void *arg) int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply; int new_timing_advance = UE->timing_advance; if (new_timing_advance != timing_advance) { - writeBlockSize -= new_timing_advance- timing_advance; + writeBlockSize -= new_timing_advance - timing_advance; timing_advance = new_timing_advance; } int new_N_TA_offset = determine_N_TA_offset(UE);