diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 993701fb11..7704d59a7d 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -43,6 +43,8 @@ #include "common/utils/threadPool/notified_fifo.h" #include "position_interface.h" +extern unsigned int NTN_UE_Koffset; + /* * NR SLOT PROCESSING SEQUENCE * @@ -156,9 +158,8 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id) ue->if_inst = nr_ue_if_module_init(UE_id); ue->dci_thres = 0; ue->target_Nid_cell = -1; - ue->timing_advance = ue->frame_parms.samples_per_subframe * 2 * get_nrUE_params()->ntn_ta_common; - check_position(UE_id); + config_position_coordinates(UE_id); // initialize all signal buffers init_nr_ue_signal(ue, nb_connected_gNB); @@ -552,7 +553,7 @@ void processSlotTX(void *arg) int slots_per_frame = (UE->sl_mode == 2) ? UE->SL_UE_PHY_PARAMS.sl_frame_params.slots_per_frame : UE->frame_parms.slots_per_frame; - int next_slot = (proc->nr_slot_tx + 1) % slots_per_frame; + int next_slot = (proc->nr_slot_tx + 1 + proc->nr_slot_tx_offset) % slots_per_frame; dynamic_barrier_join(&UE->process_slot_tx_barriers[next_slot]); RU_write(rxtxD, sl_tx_action); free(rxtxD); @@ -827,7 +828,15 @@ void *UE_thread(void *arg) readFrame(UE, &tmp, true); } + double ntn_ta_common = (mac->ntn_ta.N_common_ta_adj + mac->ntn_ta.N_UE_TA_adj) * 2; + int ntn_koffset = mac->ntn_ta.cell_specific_k_offset; + + int duration_rx_to_tx = DURATION_RX_TO_TX; + int nr_slot_tx_offset = 0; + bool update_ntn_system_information = false; + while (!oai_exit) { + nr_slot_tx_offset = 0; if (syncRunning) { notifiedFIFO_elt_t *res = pollNotifiedFIFO(&nf); @@ -935,14 +944,31 @@ void *UE_thread(void *arg) absolute_slot++; TracyCFrameMark; + if (update_ntn_system_information) { + update_ntn_system_information = false; + int ta_offset = + UE->frame_parms.samples_per_subframe * 2 * (mac->ntn_ta.N_common_ta_adj + mac->ntn_ta.N_UE_TA_adj - ntn_ta_common); + + UE->timing_advance += ta_offset; + timing_advance = ntn_koffset * 7680; + ntn_ta_common = mac->ntn_ta.N_common_ta_adj + mac->ntn_ta.N_UE_TA_adj; + } + + if (ntn_koffset != mac->ntn_ta.cell_specific_k_offset && ntn_ta_common != mac->ntn_ta.N_common_ta_adj) { + ntn_koffset = mac->ntn_ta.cell_specific_k_offset; + NTN_UE_Koffset = ntn_koffset; + update_ntn_system_information = true; + nr_slot_tx_offset = mac->ntn_ta.cell_specific_k_offset % nb_slot_frame; + } + int slot_nr = absolute_slot % nb_slot_frame; nr_rxtx_thread_data_t curMsg = {0}; curMsg.UE=UE; // update thread index for received subframe curMsg.proc.nr_slot_rx = slot_nr; - curMsg.proc.nr_slot_tx = (absolute_slot + DURATION_RX_TO_TX) % nb_slot_frame; + curMsg.proc.nr_slot_tx = (absolute_slot + duration_rx_to_tx) % nb_slot_frame; curMsg.proc.frame_rx = (absolute_slot / nb_slot_frame) % MAX_FRAME_NUMBER; - curMsg.proc.frame_tx = ((absolute_slot + DURATION_RX_TO_TX) / nb_slot_frame) % MAX_FRAME_NUMBER; + curMsg.proc.frame_tx = ((absolute_slot + duration_rx_to_tx) / nb_slot_frame) % MAX_FRAME_NUMBER; if (UE->received_config_request) { if (UE->sl_mode) { curMsg.proc.rx_slot_type = sl_nr_ue_slot_select(sl_cfg, curMsg.proc.nr_slot_rx, TDD); @@ -995,11 +1021,11 @@ void *UE_thread(void *arg) } // use previous timing_advance value to compute writeTimestamp - const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, DURATION_RX_TO_TX) + const openair0_timestamp writeTimestamp = rx_timestamp + fp->get_samples_slot_timestamp(slot_nr, fp, duration_rx_to_tx) - firstSymSamp - UE->N_TA_offset - timing_advance; // but use current UE->timing_advance value to compute writeBlockSize - int writeBlockSize = fp->get_samples_per_slot((slot_nr + DURATION_RX_TO_TX) % nb_slot_frame, fp) - iq_shift_to_apply; + int writeBlockSize = fp->get_samples_per_slot((slot_nr + duration_rx_to_tx) % nb_slot_frame, fp) - iq_shift_to_apply; if (UE->timing_advance != timing_advance) { writeBlockSize -= UE->timing_advance - timing_advance; timing_advance = UE->timing_advance; @@ -1025,6 +1051,7 @@ void *UE_thread(void *arg) curMsgTx->proc.timestamp_tx = writeTimestamp; curMsgTx->UE = UE; curMsgTx->stream_status = stream_status; + curMsgTx->proc.nr_slot_tx_offset = nr_slot_tx_offset; int sync_to_previous_thread = stream_status == STREAM_STATUS_SYNCED ? 1 : 0; int slot = curMsgTx->proc.nr_slot_tx; @@ -1034,6 +1061,9 @@ void *UE_thread(void *arg) curMsgTx); stream_status = STREAM_STATUS_SYNCED; tx_wait_for_dlsch[slot] = 0; + if (duration_rx_to_tx != DURATION_RX_TO_TX) { + duration_rx_to_tx = DURATION_RX_TO_TX; + } } return NULL; diff --git a/executables/position_interface.c b/executables/position_interface.c index 3d6bbe3094..c2cd0b09ca 100644 --- a/executables/position_interface.c +++ b/executables/position_interface.c @@ -3,7 +3,7 @@ extern uint16_t NB_UE_INST; static position_t **positionArray = 0; -position_t *check_position(int Mod_id) +void config_position_coordinates(int Mod_id) { AssertFatal(Mod_id < NB_UE_INST, "Mod_id must be less than NB_UE_INST. Mod_id:%d NB_UE_INST:%d", Mod_id, NB_UE_INST); if (positionArray == NULL) { @@ -12,18 +12,17 @@ position_t *check_position(int Mod_id) if (!positionArray[Mod_id]) { char positionName[64]; sprintf(positionName, "position%d", Mod_id); - positionArray[Mod_id] = (void *)init_position(positionName); + positionArray[Mod_id] = (void *) init_position_coordinates(positionName); } - return (position_t *)positionArray[Mod_id]; } -position_t *init_position(char *sectionName) +position_t *init_position_coordinates(char *sectionName) { position_t *position = (position_t *)calloc(sizeof(position_t), 1); paramdef_t position_params[] = POSITION_CONFIG_PARAMS_DEF; int ret = config_get(config_get_if(), position_params, sizeofArray(position_params), sectionName); AssertFatal(ret >= 0, "configuration couldn't be performed for position name: %s", sectionName); - + return position; } diff --git a/executables/position_interface.h b/executables/position_interface.h index a645961f7e..7edda34970 100644 --- a/executables/position_interface.h +++ b/executables/position_interface.h @@ -32,7 +32,7 @@ typedef struct { double positionZ; } position_t; -position_t *check_position(int Mod_id); -position_t *init_position(char *sectionName); +void config_position_coordinates(int Mod_id); +position_t *init_position_coordinates(char *sectionName); position_t *get_position(int Mod_id); #endif \ No newline at end of file diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h index 774309831c..b5ef2b4c85 100644 --- a/openair1/PHY/defs_nr_UE.h +++ b/openair1/PHY/defs_nr_UE.h @@ -394,7 +394,6 @@ typedef struct PHY_VARS_NR_UE_s { uint8_t prs_active_gNBs; NR_DL_UE_HARQ_t dl_harq_processes[2][NR_MAX_DLSCH_HARQ_PROCESSES]; NR_UL_UE_HARQ_t ul_harq_processes[NR_MAX_ULSCH_HARQ_PROCESSES]; - //Paging parameters uint32_t IMSImod1024; uint32_t PF; @@ -540,6 +539,10 @@ typedef struct { int gNB_id; /// NR slot index within frame_tx [0 .. slots_per_frame - 1] to act upon for transmission int nr_slot_tx; + /// NR slot index tx offset to resume + /// in case of NTN, tx_offset can be changed dynamically via SIB19 + /// we need to notify the right tx thread slot based on TX offset change + int nr_slot_tx_offset; int rx_slot_type; /// NR slot index within frame_rx [0 .. slots_per_frame - 1] to act upon for transmission int nr_slot_rx; diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index 7d9a1a40a1..1400548665 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -1777,10 +1777,12 @@ void nr_rrc_mac_config_req_sib19_r17(module_id_t module_id, NR_SIB19_r17_t *sib1 // populate ntn_ta structure from mac // if ephemerisInfo_r17 present in SIB19 - if (mac->sc_info.ntn_Config_r17->ephemerisInfo_r17 && mac->sc_info.ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17 - && (mac->sc_info.ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionX_r17 != 0 - || mac->sc_info.ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionY_r17 != 0 - || mac->sc_info.ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17->positionZ_r17 != 0)) { + struct NR_EphemerisInfo_r17 *ephemeris_info = mac->sc_info.ntn_Config_r17->ephemerisInfo_r17; + struct NR_PositionVelocity_r17 *position_velocity = mac->sc_info.ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17; + + if (ephemeris_info && position_velocity + && (position_velocity->positionX_r17 != 0 || position_velocity->positionY_r17 != 0 + || position_velocity->positionZ_r17 != 0)) { mac->ntn_ta.N_UE_TA_adj = calculate_ue_sat_ta(get_position(module_id), mac->sc_info.ntn_Config_r17->ephemerisInfo_r17->choice.positionVelocity_r17); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index 98f1d7a9e8..e30b69f6be 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -923,7 +923,7 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac) NR_RACH_ConfigCommon_t *setup = mac->current_UL_BWP->rach_ConfigCommon; AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__); - const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17); + const double ta_Common_ms = get_ta_Common_ms(&mac->ntn_ta); const int mu = mac->current_DL_BWP->scs; const int slots_per_ms = nr_slots_per_frame[mu] / 10;