diff --git a/executables/nr-ue.c b/executables/nr-ue.c index 8a73bdd311..447c99182b 100644 --- a/executables/nr-ue.c +++ b/executables/nr-ue.c @@ -149,6 +149,7 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue, 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 * get_nrUE_params()->ntn_ta_common; // initialize all signal buffers init_nr_ue_signal(ue, nb_connected_gNB); diff --git a/executables/nr-uesoftmodem.h b/executables/nr-uesoftmodem.h index c95a6dc98c..8e0650b4e4 100644 --- a/executables/nr-uesoftmodem.h +++ b/executables/nr-uesoftmodem.h @@ -13,6 +13,7 @@ #define CONFIG_HLP_OFFSET_DIV "Divisor for computing OFDM symbol offset in Rx chain (num samples in CP/). Default value is 8. To set the sample offset to 0, set this value ~ 10e6\n" #define CONFIG_HLP_MAX_LDPC_ITERATIONS "Maximum LDPC decoder iterations\n" #define CONFIG_HLP_NTN_KOFFSET "NTN cellSpecificKoffset-r17 (number of slots for a given subcarrier spacing of 15 kHz)\n" +#define CONFIG_HLP_NTN_TA_COMMON "NTN ta-Common, but given in ms\n" /***************************************************************************************************************************************/ /* command line options definitions, CMDLINE_XXXX_DESC macros are used to initialize paramdef_t arrays which are then used as argument @@ -66,6 +67,7 @@ {"SLC", CONFIG_HLP_SLF, 0, .u64ptr=&(sidelink_frequency[0][0]), .defuintval=2600000000,TYPE_UINT64,0}, \ {"num-ues", NULL, 0, .iptr=&(NB_UE_INST), .defuintval=1, TYPE_INT, 0}, \ {"ntn-koffset", CONFIG_HLP_NTN_KOFFSET, 0, .uptr=&(nrUE_params.ntn_koffset), .defuintval=0, TYPE_UINT, 0}, \ + {"ntn-ta-common", CONFIG_HLP_NTN_TA_COMMON, 0, .dblptr=&(nrUE_params.ntn_ta_common), .defdblval=0.0, TYPE_DOUBLE, 0}, \ } // clang-format on @@ -87,6 +89,7 @@ typedef struct { int ssb_start_subcarrier; int ldpc_offload_flag; unsigned int ntn_koffset; + double ntn_ta_common; } nrUE_params_t; extern uint64_t get_nrUE_optmask(void); extern uint64_t set_nrUE_optmask(uint64_t bitmask); diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c index d01f1e3e94..b408b9fed3 100644 --- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c +++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c @@ -373,7 +373,6 @@ static void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_ if (ta_command_pdu->is_rar) { ue->ta_slot = ta_command_pdu->ta_slot; ue->ta_frame = ta_command_pdu->ta_frame; - ue->timing_advance = 0; ue->ta_command = ta_command_pdu->ta_command + 31; // To use TA adjustment algo in ue_ta_procedures() } else { ue->ta_slot = (ta_command_pdu->ta_slot + ul_tx_timing_adjustment) % slots_per_frame; diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c index 2230d92729..501c1022f1 100644 --- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c +++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c @@ -87,7 +87,7 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) // Fake SIB19 reception for NTN // TODO: remove this and implement the actual SIB19 reception instead! - if (get_nrUE_params()->ntn_koffset) { + if (get_nrUE_params()->ntn_koffset || get_nrUE_params()->ntn_ta_common) { NR_SIB19_r17_t *sib19_r17 = calloc(1, sizeof(*sib19_r17)); sib19_r17->ntn_Config_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17)); @@ -96,6 +96,12 @@ void nr_ue_init_mac(NR_UE_MAC_INST_t *mac) asn1cCallocOne(sib19_r17->ntn_Config_r17->cellSpecificKoffset_r17, get_nrUE_params()->ntn_koffset); } + // NTN ta-Common-r17 + if (get_nrUE_params()->ntn_ta_common) { + sib19_r17->ntn_Config_r17->ta_Info_r17 = calloc(1, sizeof(*sib19_r17->ntn_Config_r17->ta_Info_r17)); + sib19_r17->ntn_Config_r17->ta_Info_r17->ta_Common_r17 = get_nrUE_params()->ntn_ta_common / 4.072e-6; // ta-Common-r17 is in units of 4.072e-3 µs, ntn_ta_common is in ms + } + nr_rrc_mac_config_req_sib19_r17(mac->ue_id, sib19_r17); asn1cFreeStruc(asn_DEF_NR_SIB19_r17, sib19_r17); } diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c index ebf3ee2703..11ce2c5c30 100644 --- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c +++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c @@ -41,6 +41,13 @@ #include #include "openair2/LAYER2/RLC/rlc.h" +static double get_ta_Common_ms(NR_NTN_Config_r17_t *ntn_Config_r17) +{ + if (ntn_Config_r17 && ntn_Config_r17->ta_Info_r17) + return ntn_Config_r17->ta_Info_r17->ta_Common_r17 * 4.072e-6; // ta_Common_r17 is in units of 4.072e-3 µs + return 0.0; +} + int16_t get_prach_tx_power(NR_UE_MAC_INST_t *mac) { RA_config_t *ra = &mac->ra; @@ -580,13 +587,17 @@ void nr_Msg3_transmitted(NR_UE_MAC_INST_t *mac, uint8_t CC_id, frame_t frameP, s { RA_config_t *ra = &mac->ra; NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->current_UL_BWP->rach_ConfigCommon; - long mu = mac->current_UL_BWP->scs; - int subframes_per_slot = nr_slots_per_frame[mu] / 10; + const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17); + const int mu = mac->current_UL_BWP->scs; + const int slots_per_ms = nr_slots_per_frame[mu] / 10; // start contention resolution timer - int RA_contention_resolution_timer_subframes = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) << 3; - // timer step 1 slot and timer target given by ra_ContentionResolutionTimer - nr_timer_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_subframes * subframes_per_slot, 1); + const int RA_contention_resolution_timer_ms = (nr_rach_ConfigCommon->ra_ContentionResolutionTimer + 1) << 3; + const int RA_contention_resolution_timer_slots = RA_contention_resolution_timer_ms * slots_per_ms; + const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms); + + // timer step 1 slot and timer target given by ra_ContentionResolutionTimer + ta-Common-r17 + nr_timer_setup(&ra->contention_resolution_timer, RA_contention_resolution_timer_slots + ta_Common_slots, 1); nr_timer_start(&ra->contention_resolution_timer); ra->ra_state = nrRA_WAIT_CONTENTION_RESOLUTION; @@ -788,11 +799,16 @@ 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__); NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric; + const double ta_Common_ms = get_ta_Common_ms(mac->sc_info.ntn_Config_r17); + const int mu = mac->current_DL_BWP->scs; + const int slots_per_ms = nr_slots_per_frame[mu] / 10; - int ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; - int mu = mac->current_DL_BWP->scs; + const int ra_Offset_slots = ra->RA_offset * nr_slots_per_frame[mu]; + const int ta_Common_slots = (int)ceil(ta_Common_ms * slots_per_ms); - ra->RA_window_cnt = ra->RA_offset * nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB + ra->RA_window_cnt = ra_Offset_slots + ta_Common_slots; // taking into account the 2 frames gap introduced by OAI gNB + + int ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow; switch (ra_ResponseWindow) { case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1: