From 75f04874d18c16c1e8c9341bf7ed98b3ac773978 Mon Sep 17 00:00:00 2001 From: Bartosz Podrygajlo Date: Thu, 6 Mar 2025 11:29:55 +0100 Subject: [PATCH] Handle changing N_TA_offset on the UE correctly in higher layers Send new N_TA_offset in config_request to PHY. Remove N_TA_offset update from ta_command. --- executables/nr-ue.c | 35 ++++++++++++---- .../nfapi/public_inc/fapi_nr_ue_interface.h | 3 +- openair1/PHY/INIT/nr_init_ue.c | 18 --------- openair1/PHY/INIT/nr_phy_init.h | 1 - openair1/SCHED_NR_UE/fapi_nr_ue_l1.c | 9 ----- openair2/LAYER2/NR_MAC_UE/config_ue.c | 40 +++++++++---------- openair2/LAYER2/NR_MAC_UE/mac_defs.h | 1 - openair2/LAYER2/NR_MAC_UE/main_ue_nr.c | 1 - openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c | 1 - 9 files changed, 48 insertions(+), 61 deletions(-) diff --git a/executables/nr-ue.c b/executables/nr-ue.c index e08569e999..4a315f1fc9 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -147,6 +147,24 @@ static void *nrL1_UE_stats_thread(void *param) return NULL; } +static int determine_N_TA_offset(PHY_VARS_NR_UE *ue) { + if (ue->sl_mode == 2) + return 0; + else { + int N_TA_offset = ue->nrUE_config.cell_config.N_TA_offset; + if (N_TA_offset == -1) { + return set_default_nta_offset(ue->frame_parms.freq_range, ue->frame_parms.samples_per_subframe); + } else { + // Return N_TA_offet in samples, as described in 38.211 4.1 and 4.3.1 + // T_c[s] = 1/(Ξ”f_max x N_f) = 1 / (480 * 1000 * 4096) + // N_TA_offset[s] = N_TA_offset x T_c + // N_TA_offset[samples] = samples_per_second x N_TA_offset[s] + // N_TA_offset[samples] = N_TA_offset x samples_per_subframe x 1000 x T_c + return (N_TA_offset * ue->frame_parms.samples_per_subframe) / (4096 * 480); + } + } +} + void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id) { int nb_connected_gNB = 1; @@ -165,8 +183,8 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, uint8_t UE_id) // intialize transport init_nr_ue_transport(ue); - // init N_TA offset - init_N_TA_offset(ue); + ue->ta_frame = -1; + ue->ta_slot = -1; } void init_nrUE_standalone_thread(int ue_idx) @@ -867,7 +885,7 @@ void *UE_thread(void *arg) initNotifiedFIFO_nothreadSafe(&freeBlocks); int timing_advance = UE->timing_advance; - int N_TA_offset = UE->N_TA_offset; + UE->N_TA_offset = determine_N_TA_offset(UE); NR_UE_MAC_INST_t *mac = get_mac_inst(UE->Mod_id); bool syncRunning = false; @@ -1090,7 +1108,7 @@ 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) - - firstSymSamp - N_TA_offset - timing_advance; + - 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; @@ -1099,10 +1117,11 @@ void *UE_thread(void *arg) writeBlockSize -= new_timing_advance- timing_advance; timing_advance = new_timing_advance; } - int new_N_TA_offset = UE->N_TA_offset; - if (new_N_TA_offset != N_TA_offset) { - writeBlockSize -= new_N_TA_offset - N_TA_offset; - N_TA_offset = new_N_TA_offset; + int new_N_TA_offset = determine_N_TA_offset(UE); + if (new_N_TA_offset != UE->N_TA_offset) { + LOG_I(PHY, "N_TA_offset changed from %d to %d\n", UE->N_TA_offset, new_N_TA_offset); + writeBlockSize -= new_N_TA_offset - UE->N_TA_offset; + UE->N_TA_offset = new_N_TA_offset; } if (curMsg.proc.nr_slot_tx == 0) diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h index 881d7fad8e..a5d6087856 100644 --- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h +++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h @@ -551,7 +551,6 @@ typedef struct { int ta_frame; int ta_slot; int ta_command; - int ta_offset; bool is_rar; } fapi_nr_ta_command_pdu; @@ -616,7 +615,7 @@ typedef struct { uint8_t phy_cell_id;//Physical Cell ID, 𝑁_{𝐼𝐷}^{𝑐𝑒𝑙𝑙} [38.211, sec 7.4.2.1] Value: 0 ->1007 uint8_t frame_duplex_type;//Frame duplex type Value: 0 = FDD 1 = TDD - + uint32_t N_TA_offset; } fapi_nr_cell_config_t; typedef struct diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c index 019e386fd0..19816e215f 100644 --- a/openair1/PHY/INIT/nr_init_ue.c +++ b/openair1/PHY/INIT/nr_init_ue.c @@ -492,24 +492,6 @@ void clean_UE_harq(PHY_VARS_NR_UE *UE) } } - -void init_N_TA_offset(PHY_VARS_NR_UE *ue) -{ - NR_DL_FRAME_PARMS *fp = &ue->frame_parms; - - // No timing offset for Sidelink, refer to 3GPP 38.211 Section 8.5 - if (ue->sl_mode == 2) - ue->N_TA_offset = 0; - else - ue->N_TA_offset = set_default_nta_offset(fp->freq_range, fp->samples_per_subframe); - ue->ta_frame = -1; - ue->ta_slot = -1; - - LOG_I(PHY, - "UE %d Setting N_TA_offset to %d samples (UL Freq %lu, N_RB %d, mu %d)\n", - ue->Mod_id, ue->N_TA_offset, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index); -} - void phy_init_nr_top(PHY_VARS_NR_UE *ue) { NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms; init_delay_table(frame_parms->ofdm_symbol_size, MAX_DELAY_COMP, NR_MAX_OFDM_SYMBOL_SIZE, frame_parms->delay_table); diff --git a/openair1/PHY/INIT/nr_phy_init.h b/openair1/PHY/INIT/nr_phy_init.h index d2c65e939f..1b1a0fa1b0 100644 --- a/openair1/PHY/INIT/nr_phy_init.h +++ b/openair1/PHY/INIT/nr_phy_init.h @@ -36,7 +36,6 @@ int nr_init_frame_parms_ue_sl(NR_DL_FRAME_PARMS *fp, int init_nr_ue_signal(PHY_VARS_NR_UE *ue,int nb_connected_eNB); void term_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB); void init_nr_ue_transport(PHY_VARS_NR_UE *ue); -void init_N_TA_offset(PHY_VARS_NR_UE *ue); void nr_dump_frame_parms(NR_DL_FRAME_PARMS *frame_parms); void phy_init_nr_gNB(PHY_VARS_gNB *gNB); int init_codebook_gNB(PHY_VARS_gNB *gNB); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index fbfc9d8389..ba4ad4a0f7 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -419,15 +419,6 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_ LOG_D(PHY, "TA command received in %d.%d Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n", ta_command_pdu->ta_frame, ta_command_pdu->ta_slot, ue->ta_frame, ue->ta_slot); - - if (ta_command_pdu->ta_offset != -1) { - // ta_offset_samples : ta_offset = samples_per_subframe : (Ξ”f_max x N_f / 1000) - // As described in Section 4.3.1 in 38.211 - int ta_offset_samples = (ta_command_pdu->ta_offset * samples_per_subframe) / (4096 * 480); - ue->N_TA_offset = ta_offset_samples; - LOG_D(PHY, "Received N_TA offset %d from upper layers. Corresponds to %d samples.\n", - ta_command_pdu->ta_offset, ta_offset_samples); - } } static void nr_ue_scheduled_response_dl(NR_UE_MAC_INST_t *mac, diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c index dd826efb79..c271f72285 100644 --- a/openair2/LAYER2/NR_MAC_UE/config_ue.c +++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c @@ -44,6 +44,24 @@ #include "oai_asn1.h" #include "executables/position_interface.h" +static int get_ta_offset(long *n_TimingAdvanceOffset) +{ + if (!n_TimingAdvanceOffset) + return -1; + + switch (*n_TimingAdvanceOffset) { + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n0 : + return 0; + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n25600 : + return 25600; + case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n39936 : + return 39936; + default : + AssertFatal(false, "Invalid n-TimingAdvanceOffset\n"); + } + return -1; +} + static void set_tdd_config_nr_ue(fapi_nr_tdd_table_t *tdd_table, const frame_structure_t *fs) { tdd_table->tdd_period_in_slots = fs->numb_slots_period; @@ -143,6 +161,7 @@ static void config_common_ue_sa(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommo // cell config cfg->cell_config.phy_cell_id = mac->physCellId; cfg->cell_config.frame_duplex_type = frame_type; + cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset); // SSB config cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; @@ -345,6 +364,7 @@ static void config_common_ue(NR_UE_MAC_INST_t *mac, NR_ServingCellConfigCommon_t // cell config cfg->cell_config.phy_cell_id = *scc->physCellId; cfg->cell_config.frame_duplex_type = frame_type; + cfg->cell_config.N_TA_offset = get_ta_offset(scc->n_TimingAdvanceOffset); // SSB config cfg->ssb_config.ss_pbch_power = scc->ss_PBCH_BlockPower; @@ -1685,24 +1705,6 @@ void nr_rrc_mac_config_req_reset(module_id_t module_id, NR_UE_MAC_reset_cause_t AssertFatal(!ret, "mutex failed %d\n", ret); } -static int get_ta_offset(long *n_TimingAdvanceOffset) -{ - if (!n_TimingAdvanceOffset) - return -1; - - switch (*n_TimingAdvanceOffset) { - case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n0 : - return 0; - case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n25600 : - return 25600; - case NR_ServingCellConfigCommonSIB__n_TimingAdvanceOffset_n39936 : - return 39936; - default : - AssertFatal(false, "Invalid n-TimingAdvanceOffset\n"); - } - return -1; -} - static void configure_si_schedulingInfo(NR_UE_MAC_INST_t *mac, NR_SI_SchedulingInfo_t *si_SchedulingInfo, NR_SI_SchedulingInfo_v1700_t *si_SchedulingInfo_v1700) @@ -1744,7 +1746,6 @@ void nr_rrc_mac_config_req_sib1(module_id_t module_id, int cc_idP, NR_SIB1_t *si AssertFatal(scc, "SIB1 SCC should not be NULL\n"); UPDATE_IE(mac->tdd_UL_DL_ConfigurationCommon, scc->tdd_UL_DL_ConfigurationCommon, NR_TDD_UL_DL_ConfigCommon_t); configure_si_schedulingInfo(mac, si_SchedulingInfo, si_SchedulingInfo_v1700); - mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset); config_common_ue_sa(mac, scc, cc_idP); configure_common_BWP_dl(mac, @@ -1813,7 +1814,6 @@ static void handle_reconfiguration_with_sync(NR_UE_MAC_INST_t *mac, if (reconfWithSync->spCellConfigCommon) { NR_ServingCellConfigCommon_t *scc = reconfWithSync->spCellConfigCommon; - mac->n_ta_offset = get_ta_offset(scc->n_TimingAdvanceOffset); if (scc->physCellId) mac->physCellId = *scc->physCellId; mac->dmrs_TypeA_Position = scc->dmrs_TypeA_Position; diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h index 2ba5f992d4..d269cc1c0c 100644 --- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h +++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h @@ -633,7 +633,6 @@ typedef struct NR_UE_MAC_INST_s { int dmrs_TypeA_Position; int p_Max; int p_Max_alt; - int n_ta_offset; // -1 not present, otherwise value to be applied ntn_timing_advance_componets_t ntn_ta; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 35167b6173..2c68369638 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -68,7 +68,6 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) mac->uecap_maxMIMO_PUSCH_layers_nocb = 0; mac->p_Max = INT_MIN; mac->p_Max_alt = INT_MIN; - mac->n_ta_offset = -1; mac->ntn_ta.ntn_params_changed = false; reset_mac_inst(mac); diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c index 846d344584..255cb43a5e 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c @@ -3626,7 +3626,6 @@ static void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UE_MA fapi_nr_ta_command_pdu *ta = &dl_config->dl_config_list[dl_config->number_pdus].ta_command_pdu; ta->ta_frame = ul_time_alignment->frame; ta->ta_slot = ul_time_alignment->slot; - ta->ta_offset = mac->n_ta_offset; ta->is_rar = ul_time_alignment->ta_apply == rar_ta; ta->ta_command = ul_time_alignment->ta_command; dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND;