From eb09a63001558d1067bd4cfcd85ece0d73559fa0 Mon Sep 17 00:00:00 2001
From: francescomani <email@francescomani.it>
Date: Thu, 6 Apr 2023 19:02:40 +0200
Subject: [PATCH] separating MAC and PHY procedures for TA

---
 .../telnetsrv/telnetsrv_5Gue_measurements.c   |   5 +-
 executables/nr-ue.c                           |   9 +-
 .../nfapi/public_inc/fapi_nr_ue_constants.h   |   3 +-
 .../nfapi/public_inc/fapi_nr_ue_interface.h   |   6 +
 openair1/PHY/INIT/nr_init_ue.c                |   5 +-
 openair1/PHY/NR_UE_TRANSPORT/csi_rx.c         |   5 +-
 .../PHY/NR_UE_TRANSPORT/nr_initial_sync.c     |   4 +-
 openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c        |   4 +-
 openair1/PHY/defs_nr_UE.h                     |  24 +--
 openair1/SCHED_NR_UE/fapi_nr_ue_l1.c          |  62 +++++-
 openair1/SCHED_NR_UE/phy_procedures_nr_ue.c   | 198 +++---------------
 .../SCHED_NR_UE/phy_sch_processing_time.h     |  12 +-
 .../NR_UE_PHY/unit_tests/src/pucch_uci_test.c |   1 -
 openair2/LAYER2/NR_MAC_UE/mac_defs.h          |  19 +-
 openair2/LAYER2/NR_MAC_UE/mac_proto.h         |   5 +-
 openair2/LAYER2/NR_MAC_UE/main_ue_nr.c        |  12 +-
 openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c  |  53 +++--
 openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c   |  14 ++
 .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c   |   8 +-
 openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c   |  31 ++-
 openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h   |   4 +-
 21 files changed, 201 insertions(+), 283 deletions(-)

diff --git a/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c
index 969521b3c5c..ae04666c95a 100644
--- a/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c
+++ b/common/utils/telnetsrv/telnetsrv_5Gue_measurements.c
@@ -96,10 +96,7 @@ void measurcmd_display_phyta(telnet_printfunc_t prnt)
   PHY_VARS_NR_UE *UE = PHY_vars_UE_g[0][0];
   prnt("%s PHY TA stats\n", HDR);
   prnt("N_TA_offset %d\n", UE->N_TA_offset);
-  for (int i = 0; i < UE->n_connected_gNB; ++i) {
-    NR_UL_TIME_ALIGNMENT_t *ta = &UE->ul_time_alignment[i];
-    prnt("gNB %d TA command %d TA total %d TAG ID %d\n", i, ta->ta_command, ta->ta_total, ta->tag_id);
-  }
+  prnt("TA command %d\n", UE->ta_command);
   prnt("timing_advance %d (samples)\n", UE->timing_advance);
 }
 /*
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index 40240756519..1d96b7aa2eb 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -154,7 +154,6 @@ void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
   int nb_connected_gNB = 1;
 
   ue->Mod_id      = UE_id;
-  ue->mac_enabled = 1;
   ue->if_inst     = nr_ue_if_module_init(0);
   ue->dci_thres   = 0;
   ue->target_Nid_cell = -1;
@@ -259,8 +258,6 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
   reset_queue(&nr_ul_dci_req_queue);
   reset_queue(&nr_ul_tti_req_queue);
 
-  NR_UL_TIME_ALIGNMENT_t ul_time_alignment;
-  memset(&ul_time_alignment, 0, sizeof(ul_time_alignment));
   int last_sfn_slot = -1;
   uint16_t sfn_slot = 0;
 
@@ -305,7 +302,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
 
     if (get_softmodem_params()->sa && mac->mib == NULL) {
       LOG_D(NR_MAC, "We haven't gotten MIB. Lets see if we received it\n");
-      nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment);
+      nr_ue_dl_indication(&mac->dl_info);
       process_queued_nr_nfapi_msgs(mac, sfn_slot);
     }
     if (mac->scc == NULL && mac->scc_SIB == NULL) {
@@ -347,7 +344,7 @@ static void *NRUE_phy_stub_standalone_pnf_task(void *arg)
       mac->dl_info.slot = slot;
       mac->dl_info.dci_ind = NULL;
       mac->dl_info.rx_ind = NULL;
-      nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment);
+      nr_ue_dl_indication(&mac->dl_info);
     }
 
     if (pthread_mutex_unlock(&mac->mutex_dl_info)) abort();
@@ -629,7 +626,7 @@ nr_phy_data_t UE_dl_preprocessing(PHY_VARS_NR_UE *UE, UE_nr_rxtx_proc_t *proc) {
     if(UE->if_inst != NULL && UE->if_inst->dl_indication != NULL) {
       nr_downlink_indication_t dl_indication;
       nr_fill_dl_indication(&dl_indication, NULL, NULL, proc, UE, &phy_data);
-      UE->if_inst->dl_indication(&dl_indication, NULL);
+      UE->if_inst->dl_indication(&dl_indication);
     }
 
     uint64_t a=rdtsc_oai();
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h
index 6d40752a9aa..276f417fbb7 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_constants.h
@@ -50,7 +50,8 @@
 #define FAPI_NR_DL_CONFIG_TYPE_P_DLSCH 0x05
 #define FAPI_NR_DL_CONFIG_TYPE_CSI_RS 0x06
 #define FAPI_NR_DL_CONFIG_TYPE_CSI_IM 0x07
-#define FAPI_NR_DL_CONFIG_TYPES 0x07
+#define FAPI_NR_CONFIG_TA_COMMAND 0x08
+#define FAPI_NR_DL_CONFIG_TYPES 0x08
 
 #define FAPI_NR_CCE_REG_MAPPING_TYPE_INTERLEAVED 0x01
 #define FAPI_NR_CCE_REG_MAPPING_TYPE_NON_INTERLEAVED 0x02
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 87fe5b82bc3..95ae91b4d49 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
@@ -526,6 +526,11 @@ typedef struct {
   fapi_nr_dl_config_csiim_pdu_rel15_t csiim_config_rel15;
 } fapi_nr_dl_config_csiim_pdu;
 
+typedef struct {
+ int ta_frame;
+ int ta_slot;
+ int ta_command;
+} fapi_nr_ta_command_pdu;
 
 typedef struct {
   uint8_t pdu_type;
@@ -534,6 +539,7 @@ typedef struct {
     fapi_nr_dl_config_dlsch_pdu dlsch_config_pdu;
     fapi_nr_dl_config_csirs_pdu csirs_config_pdu;
     fapi_nr_dl_config_csiim_pdu csiim_config_pdu;
+    fapi_nr_ta_command_pdu ta_command_pdu;
   };
 } fapi_nr_dl_config_request_pdu_t;
 
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index 65d3f86f7a7..6c65f6a8035 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -234,9 +234,6 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue, int nb_connected_gNB)
     ue->bitrate[gNB_id] = 0;
     ue->total_received_bits[gNB_id] = 0;
 
-    ue->ul_time_alignment[gNB_id].apply_ta = 0;
-    ue->ul_time_alignment[gNB_id].ta_frame = -1;
-    ue->ul_time_alignment[gNB_id].ta_slot  = -1;
   }
   // init NR modulation lookup tables
   nr_generate_modulation_table();
@@ -691,6 +688,8 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
     }
 
     ue->N_TA_offset = (int)(N_TA_offset * factor);
+    ue->ta_frame = -1;
+    ue->ta_slot = -1;
 
     LOG_I(PHY,"UE %d Setting N_TA_offset to %d samples (factor %f, UL Freq %lu, N_RB %d, mu %d)\n", ue->Mod_id, ue->N_TA_offset, factor, fp->ul_CarrierFreq, fp->N_RB_DL, fp->numerology_index);
   }
diff --git a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c
index 0e5ba62da7a..02f087b2ef2 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/csi_rx.c
@@ -980,9 +980,8 @@ int nr_ue_csi_rs_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, c16_t r
   fapi_nr_rx_indication_t rx_ind = {0};
   nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
   nr_fill_rx_indication(&rx_ind, FAPI_NR_CSIRS_IND, ue, NULL, NULL, 1, proc, (void *)&csirs_measurements, NULL);
-  if (ue->if_inst && ue->if_inst->dl_indication) {
-    ue->if_inst->dl_indication(&dl_indication, NULL);
-  }
+  if (ue->if_inst && ue->if_inst->dl_indication)
+    ue->if_inst->dl_indication(&dl_indication);
 
   return 0;
 }
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
index da99ba7405f..e81f8551c08 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
@@ -515,7 +515,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
   }
 
   // if stand alone and sync on ssb do sib1 detection as part of initial sync
-  if (sa==1 && ret==0) {
+  if (sa == 1 && ret == 0) {
     nr_ue_dlsch_init(phy_data.dlsch, 1, ue->max_ldpc_iterations);
     bool dec = false;
     proc->gNB_id = 0; //FIXME
@@ -524,7 +524,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
     int32_t pdcch_est_size = ((((fp->symbols_per_slot*(fp->ofdm_symbol_size+LTE_CE_FILTER_LENGTH))+15)/16)*16);
     __attribute__ ((aligned(16))) int32_t pdcch_dl_ch_estimates[4*fp->nb_antennas_rx][pdcch_est_size];
 
-    for(int n_ss = 0; n_ss<phy_pdcch_config->nb_search_space; n_ss++) {
+    for(int n_ss = 0; n_ss < phy_pdcch_config->nb_search_space; n_ss++) {
       proc->nr_slot_rx = phy_pdcch_config->slot; // setting PDCCH slot to proc
       uint8_t nb_symb_pdcch = phy_pdcch_config->pdcch_config[n_ss].coreset.duration;
       int start_symb = phy_pdcch_config->pdcch_config[n_ss].coreset.StartSymbolIndex;
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
index 2fa9ca37ef7..8195f6bcb2c 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_pbch.c
@@ -520,7 +520,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
     nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, phy_data);
     nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, NULL, NULL);
     if (ue->if_inst && ue->if_inst->dl_indication)
-      ue->if_inst->dl_indication(&dl_indication, NULL);
+      ue->if_inst->dl_indication(&dl_indication);
     return(decoderState);
   }
   //  printf("polar decoder output 0x%08x\n",pbch_a_prime);
@@ -591,7 +591,7 @@ int nr_rx_pbch(PHY_VARS_NR_UE *ue,
   nr_fill_rx_indication(&rx_ind, FAPI_NR_RX_PDU_TYPE_SSB, ue, NULL, NULL, number_pdus, proc, (void *)result, NULL);
 
   if (ue->if_inst && ue->if_inst->dl_indication)
-    ue->if_inst->dl_indication(&dl_indication, NULL);
+    ue->if_inst->dl_indication(&dl_indication);
 
   return 0;
 }
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index 1543c81e00c..e942ef2e5e0 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -358,18 +358,6 @@ typedef struct UE_NR_SCAN_INFO_s {
   int32_t freq_offset_Hz[3][10];
 } UE_NR_SCAN_INFO_t;
 
-typedef struct NR_UL_TIME_ALIGNMENT {
-  /// flag used by MAC to inform PHY about a TA to be applied
-  unsigned char    apply_ta;
-  /// frame and slot when to apply the TA as stated in TS 38.213 setion 4.2
-  int16_t          ta_frame;
-  char             ta_slot;
-  /// TA command and TAGID received from the gNB
-  uint16_t         ta_command;
-  uint32_t         ta_total;
-  uint8_t          tag_id;
-} NR_UL_TIME_ALIGNMENT_t;
-
 /// Top-level PHY Data Structure for UE
 typedef struct {
   /// \brief Module ID indicator for this instance
@@ -519,7 +507,6 @@ typedef struct {
   int dlsch_mcch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX];
   int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_gNB_MAX];
   int current_dlsch_cqi[NUMBER_OF_CONNECTED_gNB_MAX];
-  unsigned char first_run_timing_advance[NUMBER_OF_CONNECTED_gNB_MAX];
   uint8_t               decode_SIB;
   uint8_t               decode_MIB;
   uint8_t               init_sync_frame;
@@ -533,9 +520,11 @@ typedef struct {
 
   /// Timing Advance updates variables
   /// Timing advance update computed from the TA command signalled from gNB
-  int                      timing_advance;
-  int                      N_TA_offset; ///timing offset used in TDD
-  NR_UL_TIME_ALIGNMENT_t   ul_time_alignment[NUMBER_OF_CONNECTED_gNB_MAX];
+  int timing_advance;
+  int N_TA_offset; ///timing offset used in TDD
+  int ta_frame;
+  int ta_slot;
+  int ta_command;
 
   /// Flag to tell if UE is secondary user (cognitive mode)
   unsigned char    is_secondary_ue;
@@ -546,9 +535,6 @@ typedef struct {
   /// holds the maximum channel/precoder coefficient
   char             log2_maxp;
 
-  /// if ==0 enables phy only test mode
-  int mac_enabled;
-
   /// Flag to initialize averaging of PHY measurements
   int init_averaging;
 
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index 64ec900b2a9..562deb05934 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -40,10 +40,11 @@
 #include "PHY/impl_defs_nr.h"
 #include "utils.h"
 #include "openair2/PHY_INTERFACE/queue_t.h"
+#include "SCHED_NR_UE/phy_sch_processing_time.h"
 
 extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
 
-const char *dl_pdu_type[]={"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM"};
+const char *dl_pdu_type[]={"DCI", "DLSCH", "RA_DLSCH", "SI_DLSCH", "P_DLSCH", "CSI_RS", "CSI_IM", "TA"};
 const char *ul_pdu_type[]={"PRACH", "PUCCH", "PUSCH", "SRS"};
 queue_t nr_rx_ind_queue;
 queue_t nr_crc_ind_queue;
@@ -332,6 +333,62 @@ void configure_dlsch(NR_UE_DLSCH_t *dlsch0,
 }
 
 
+void configure_ta_command(PHY_VARS_NR_UE *ue, fapi_nr_ta_command_pdu *ta_command_pdu)
+{
+
+  /* Time Alignment procedure
+  // - UE processing capability 1
+  // - Setting the TA update to be applied after the reception of the TA command
+  // - Timing adjustment computed according to TS 38.213 section 4.2
+  // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are
+  //   computed according to sections 5.3 and 6.4 of TS 38.214 */
+  const int numerology = ue->frame_parms.numerology_index;
+  const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
+  const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples;
+  const int samples_per_subframe = ue->frame_parms.samples_per_subframe;
+  const int slots_per_frame = ue->frame_parms.slots_per_frame;
+  const int slots_per_subframe = ue->frame_parms.slots_per_subframe;
+
+  const double tc_factor = 1.0 / samples_per_subframe;
+  // convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second
+  //   16 * 64 * T_c            / (2^mu) * samples_per_second
+  // = 16 * T_s                 / (2^mu) * samples_per_second
+  // = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size)
+  // = 16 * 1 /           2048           *                  ofdm_symbol_size
+  // = 16 * ofdm_symbol_size / 2048
+  uint16_t bw_scaling = 16 * ofdm_symbol_size / 2048;
+
+  const int Ta_max = 3846; // Max value of 12 bits TA Command
+  const double N_TA_max = Ta_max * bw_scaling * tc_factor;
+
+  // symbols corresponding to a PDSCH processing time for UE processing capability 1
+  // when additional PDSCH DM-RS is configured
+  int N_1 = pdsch_N_1_capability_1[numerology][3];
+
+  /* PUSCH preapration time N_2 for processing capability 1 */
+  const int N_2 = pusch_N_2_timing_capability_1[numerology][1];
+
+  /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time
+  // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */
+  double N_t_1 = N_1 * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
+  double N_t_2 = N_2 * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
+
+  /* Time alignment procedure */
+  // N_t_1 + N_t_2 + N_TA_max must be in msec
+  const double t_subframe = 1.0; // subframe duration of 1 msec
+  const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe);
+
+  ue->ta_slot = (ta_command_pdu->ta_slot + ul_tx_timing_adjustment) % slots_per_frame;
+  if (ta_command_pdu->ta_slot + ul_tx_timing_adjustment > slots_per_frame)
+    ue->ta_frame = (ta_command_pdu->ta_frame + 1) % 1024;
+  else
+    ue->ta_frame = ta_command_pdu->ta_frame;
+
+  ue->ta_command = ta_command_pdu->ta_command;
+  LOG_D(PHY,"TA command received in Frame.Slot %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);
+}
+
 int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
 
   bool found = false;
@@ -406,6 +463,9 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
             configure_dlsch(dlsch0, PHY_vars_UE_g[module_id][cc_id]->dl_harq_processes[0], dlsch_config_pdu, module_id,
                             dl_config->dl_config_list[i].dlsch_config_pdu.rnti);
             break;
+          case FAPI_NR_CONFIG_TA_COMMAND:
+            configure_ta_command(PHY_vars_UE_g[module_id][cc_id], &dl_config->dl_config_list[i].ta_command_pdu);
+            break;
         }
       }
       dl_config->number_pdus = 0;
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index 664cddcfdff..f4debbb4534 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -50,7 +50,6 @@
 #endif
 #include "executables/softmodem-common.h"
 #include "executables/nr-uesoftmodem.h"
-#include "LAYER2/NR_MAC_UE/mac_proto.h"
 #include "SCHED_NR_UE/pucch_uci_ue_nr.h"
 #include <openair1/PHY/TOOLS/phy_scope_interface.h>
 
@@ -87,8 +86,8 @@ void nr_fill_dl_indication(nr_downlink_indication_t *dl_ind,
                            fapi_nr_rx_indication_t *rx_ind,
                            UE_nr_rxtx_proc_t *proc,
                            PHY_VARS_NR_UE *ue,
-                           void *phy_data){
-
+                           void *phy_data)
+{
   memset((void*)dl_ind, 0, sizeof(nr_downlink_indication_t));
 
   dl_ind->gNB_index = proc->gNB_id;
@@ -223,49 +222,37 @@ int get_tx_amp_prach(int power_dBm, int power_max_dBm, int N_RB_UL){
   return (amp_x_100);
 }
 
-// convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second
-//   16 * 64 * T_c            / (2^mu) * samples_per_second
-// = 16 * T_s                 / (2^mu) * samples_per_second
-// = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size)
-// = 16 * 1 /           2048           *                  ofdm_symbol_size
-// = 16 * ofdm_symbol_size / 2048
-static inline
-uint16_t get_bw_scaling(uint16_t ofdm_symbol_size){
-  return 16 * ofdm_symbol_size / 2048;
-}
-
 // UL time alignment procedures:
-// - If the current tx frame and slot match the TA configuration in ul_time_alignment
+// - If the current tx frame and slot match the TA configuration
 //   then timing advance is processed and set to be applied in the next UL transmission
 // - Application of timing adjustment according to TS 38.213 p4.2
 // todo:
 // - handle RAR TA application as per ch 4.2 TS 38.213
-void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx){
-
-  if (ue->mac_enabled == 1) {
-
-    uint8_t gNB_id = 0;
-    NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id];
-
-    if (frame_tx == ul_time_alignment->ta_frame && slot_tx == ul_time_alignment->ta_slot) {
+void ue_ta_procedures(PHY_VARS_NR_UE *ue, int slot_tx, int frame_tx)
+{
+  if (frame_tx == ue->ta_frame && slot_tx == ue->ta_slot) {
 
-      uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
-      uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size);
+    uint16_t ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
 
-      ue->timing_advance += (ul_time_alignment->ta_command - 31) * bw_scaling;
+    // convert time factor "16 * 64 * T_c / (2^mu)" in N_TA calculation in TS38.213 section 4.2 to samples by multiplying with samples per second
+    //   16 * 64 * T_c            / (2^mu) * samples_per_second
+    // = 16 * T_s                 / (2^mu) * samples_per_second
+    // = 16 * 1 / (15 kHz * 2048) / (2^mu) * (15 kHz * 2^mu * ofdm_symbol_size)
+    // = 16 * 1 /           2048           *                  ofdm_symbol_size
+    // = 16 * ofdm_symbol_size / 2048
+    uint16_t bw_scaling = 16 * ofdm_symbol_size / 2048;
 
-      LOG_D(PHY, "In %s: [UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
-        __FUNCTION__,
-        ue->Mod_id,
-        frame_tx,
-        slot_tx,
-        ul_time_alignment->ta_command,
-        ue->timing_advance);
+    ue->timing_advance += (ue->ta_command - 31) * bw_scaling;
 
-      ul_time_alignment->ta_frame = -1;
-      ul_time_alignment->ta_slot = -1;
+    LOG_D(PHY, "[UE %d] [%d.%d] Got timing advance command %u from MAC, new value is %d\n",
+          ue->Mod_id,
+          frame_tx,
+          slot_tx,
+          ue->ta_command,
+          ue->timing_advance);
 
-    }
+    ue->ta_frame = -1;
+    ue->ta_slot = -1;
   }
 }
 
@@ -516,7 +503,7 @@ int nr_ue_pdcch_procedures(PHY_VARS_NR_UE *ue,
   // fill dl_indication message
   nr_fill_dl_indication(&dl_indication, &dci_ind, NULL, proc, ue, phy_data);
   //  send to mac
-  ue->if_inst->dl_indication(&dl_indication, NULL);
+  ue->if_inst->dl_indication(&dl_indication);
 
 
   stop_meas(&ue->dlsch_rx_pdcch_stats);
@@ -705,13 +692,10 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
   nr_downlink_indication_t dl_indication;
   fapi_nr_rx_indication_t rx_ind = {0};
   uint16_t number_pdus = 1;
-  // params for UL time alignment procedure
-  NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &ue->ul_time_alignment[gNB_id];
 
   uint8_t is_cw0_active = dl_harq0->status;
   uint8_t is_cw1_active = dl_harq1->status;
   uint16_t nb_symb_sch = dlsch[0].dlsch_config.number_symbols;
-  uint16_t start_symbol = dlsch[0].dlsch_config.start_symbol;
   uint8_t dmrs_type = dlsch[0].dlsch_config.dmrsConfigType;
 
   uint8_t nb_re_dmrs;
@@ -805,7 +789,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
   nr_fill_dl_indication(&dl_indication, NULL, &rx_ind, proc, ue, NULL);
   nr_fill_rx_indication(&rx_ind, ind_type, ue, &dlsch[0], NULL, number_pdus, proc, NULL, p_b);
 
-  LOG_D(PHY, "In %s DL PDU length in bits: %d, in bytes: %d \n", __FUNCTION__, dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8);
+  LOG_D(PHY, "DL PDU length in bits: %d, in bytes: %d \n", dlsch[0].dlsch_config.TBS, dlsch[0].dlsch_config.TBS / 8);
 
   stop_meas(&ue->dlsch_decoding_stats);
   if (cpumeas(CPUMEAS_GETSTATE))  {
@@ -857,9 +841,10 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
       }
   LOG_D(PHY, "harq_pid: %d, TBS expected dlsch1: %d \n", harq_pid, dlsch[1].dlsch_config.TBS);
   }
+
   //  send to mac
   if (ue->if_inst && ue->if_inst->dl_indication) {
-    ue->if_inst->dl_indication(&dl_indication, ul_time_alignment);
+    ue->if_inst->dl_indication(&dl_indication);
   }
 
   // DLSCH decoding finished! don't wait anymore
@@ -869,135 +854,6 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
   if (ue->phy_sim_dlsch_b)
     memcpy(ue->phy_sim_dlsch_b, p_b, dlsch_bytes);
 
-  if (ue->mac_enabled == 1) { // TODO: move this from PHY to MAC layer!
-
-    /* Time Alignment procedure
-    // - UE processing capability 1
-    // - Setting the TA update to be applied after the reception of the TA command
-    // - Timing adjustment computed according to TS 38.213 section 4.2
-    // - Durations of N1 and N2 symbols corresponding to PDSCH and PUSCH are
-    //   computed according to sections 5.3 and 6.4 of TS 38.214 */
-    const int numerology = ue->frame_parms.numerology_index;
-    const int ofdm_symbol_size = ue->frame_parms.ofdm_symbol_size;
-    const int nb_prefix_samples = ue->frame_parms.nb_prefix_samples;
-    const int samples_per_subframe = ue->frame_parms.samples_per_subframe;
-    const int slots_per_frame = ue->frame_parms.slots_per_frame;
-    const int slots_per_subframe = ue->frame_parms.slots_per_subframe;
-
-    const double tc_factor = 1.0 / samples_per_subframe;
-    const uint16_t bw_scaling = get_bw_scaling(ofdm_symbol_size);
-
-    const int Ta_max = 3846; // Max value of 12 bits TA Command
-    const double N_TA_max = Ta_max * bw_scaling * tc_factor;
-
-    NR_UE_MAC_INST_t *mac = get_mac_inst(0);
-    NR_BWP_Id_t ul_bwp = mac->current_UL_BWP.bwp_id;
-
-    NR_PUSCH_TimeDomainResourceAllocationList_t *pusch_TimeDomainAllocationList = NULL;
-    if(ul_bwp){
-      if (mac->ULbwp[ul_bwp-1] &&
-          mac->ULbwp[ul_bwp-1]->bwp_Dedicated &&
-          mac->ULbwp[ul_bwp-1]->bwp_Dedicated->pusch_Config &&
-          mac->ULbwp[ul_bwp-1]->bwp_Dedicated->pusch_Config->choice.setup &&
-          mac->ULbwp[ul_bwp-1]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList) {
-        pusch_TimeDomainAllocationList = mac->ULbwp[ul_bwp-1]->bwp_Dedicated->pusch_Config->choice.setup->pusch_TimeDomainAllocationList->choice.setup;
-      }
-      else if (mac->ULbwp[ul_bwp-1] &&
-               mac->ULbwp[ul_bwp-1]->bwp_Common &&
-               mac->ULbwp[ul_bwp-1]->bwp_Common->pusch_ConfigCommon &&
-               mac->ULbwp[ul_bwp-1]->bwp_Common->pusch_ConfigCommon->choice.setup &&
-               mac->ULbwp[ul_bwp-1]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) {
-        pusch_TimeDomainAllocationList = mac->ULbwp[ul_bwp-1]->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
-      }
-    }
-    else if (mac->scc_SIB &&
-             mac->scc_SIB->uplinkConfigCommon &&
-             mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon &&
-             mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup &&
-             mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList) {
-      pusch_TimeDomainAllocationList = mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
-    }
-    long mapping_type_ul = pusch_TimeDomainAllocationList ? pusch_TimeDomainAllocationList->list.array[0]->mappingType : NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeA;
-
-    NR_PDSCH_Config_t *pdsch_Config = mac->current_DL_BWP.pdsch_Config;
-    NR_PDSCH_TimeDomainResourceAllocationList_t *pdsch_TimeDomainAllocationList = mac->current_DL_BWP.tdaList_Common;
-    long mapping_type_dl = pdsch_TimeDomainAllocationList ? pdsch_TimeDomainAllocationList->list.array[0]->mappingType : NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA;
-
-    NR_DMRS_DownlinkConfig_t *NR_DMRS_dlconfig = NULL;
-    if (pdsch_Config) {
-      if (mapping_type_dl == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA)
-        NR_DMRS_dlconfig = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup;
-      else
-        NR_DMRS_dlconfig = (NR_DMRS_DownlinkConfig_t *)pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB->choice.setup;
-    }
-
-    pdsch_dmrs_AdditionalPosition_t add_pos_dl = pdsch_dmrs_pos2;
-    if (NR_DMRS_dlconfig && NR_DMRS_dlconfig->dmrs_AdditionalPosition)
-      add_pos_dl = *NR_DMRS_dlconfig->dmrs_AdditionalPosition;
-
-    /* PDSCH decoding time N_1 for processing capability 1 */
-    int N_1;
-
-    if (add_pos_dl == pdsch_dmrs_pos0)
-      N_1 = pdsch_N_1_capability_1[numerology][1];
-    else if (add_pos_dl == pdsch_dmrs_pos1 || add_pos_dl == pdsch_dmrs_pos2)
-      N_1 = pdsch_N_1_capability_1[numerology][2];
-    else
-      N_1 = pdsch_N_1_capability_1[numerology][3];
-
-    /* PUSCH preapration time N_2 for processing capability 1 */
-    const int N_2 = pusch_N_2_timing_capability_1[numerology][1];
-
-    /* d_1_1 depending on the number of PDSCH symbols allocated */
-    const int d = 0; // TODO number of overlapping symbols of the scheduling PDCCH and the scheduled PDSCH
-    int d_1_1 = 0;
-    if (mapping_type_dl == NR_PDSCH_TimeDomainResourceAllocation__mappingType_typeA)
-     if (nb_symb_sch + start_symbol < 7)
-        d_1_1 = 7 - (nb_symb_sch + start_symbol);
-      else
-        d_1_1 = 0;
-    else // mapping type B
-      switch (nb_symb_sch){
-        case 7: d_1_1 = 0; break;
-        case 4: d_1_1 = 3; break;
-        case 2: d_1_1 = 3 + d; break;
-        default: break;
-      }
-
-    /* d_2_1 */
-    int d_2_1;
-    if (mapping_type_ul == NR_PUSCH_TimeDomainResourceAllocation__mappingType_typeB && start_symbol != 0)
-      d_2_1 = 0;
-    else
-      d_2_1 = 1;
-
-    /* d_2_2 */
-    const double d_2_2 = pusch_d_2_2_timing_capability_1[numerology][1];
-
-    /* N_t_1 time duration in msec of N_1 symbols corresponding to a PDSCH reception time
-    // N_t_2 time duration in msec of N_2 symbols corresponding to a PUSCH preparation time */
-    double N_t_1 = (N_1 + d_1_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
-    double N_t_2 = (N_2 + d_2_1) * (ofdm_symbol_size + nb_prefix_samples) * tc_factor;
-    if (N_t_2 < d_2_2) N_t_2 = d_2_2;
-
-    /* Time alignment procedure */
-    // N_t_1 + N_t_2 + N_TA_max must be in msec
-    const double t_subframe = 1.0; // subframe duration of 1 msec
-    const int ul_tx_timing_adjustment = 1 + (int)ceil(slots_per_subframe*(N_t_1 + N_t_2 + N_TA_max + 0.5)/t_subframe);
-
-    if (ul_time_alignment->apply_ta == 1){
-      ul_time_alignment->ta_slot = (nr_slot_rx + ul_tx_timing_adjustment) % slots_per_frame;
-      if (nr_slot_rx + ul_tx_timing_adjustment > slots_per_frame){
-        ul_time_alignment->ta_frame = (frame_rx + 1) % 1024;
-      } else {
-        ul_time_alignment->ta_frame = frame_rx;
-      }
-      // reset TA flag
-      ul_time_alignment->apply_ta = 0;
-      LOG_D(PHY,"Frame %d slot %d -- Starting UL time alignment procedures. TA update will be applied at frame %d slot %d\n",
-           frame_rx, nr_slot_rx, ul_time_alignment->ta_frame, ul_time_alignment->ta_slot);
-    }
-  }
   return dec;
 }
 
diff --git a/openair1/SCHED_NR_UE/phy_sch_processing_time.h b/openair1/SCHED_NR_UE/phy_sch_processing_time.h
index 81cc4496a26..896c93b9ee4 100644
--- a/openair1/SCHED_NR_UE/phy_sch_processing_time.h
+++ b/openair1/SCHED_NR_UE/phy_sch_processing_time.h
@@ -50,7 +50,7 @@
 //   when PDSCH DM-RS position l1 for the additional DM-RS is != 1,2
 
 */
-int8_t pdsch_N_1_capability_1[4][4] = {
+static const int8_t pdsch_N_1_capability_1[4][4] = {
 /* mu      A            B            C   */
 {  0,      8,           14,          13  },
 {  1,      10,          13,          13  },
@@ -69,7 +69,7 @@ int8_t pdsch_N_1_capability_1[4][4] = {
 //   dmrs-DownlinkForPDSCH-MappingTypeA and dmrs-DownlinkForPDSCH-MappingTypeB
 // mu == 2 is for FR1 only
 */
-float pdsch_N_1_capability_2[3][2] = {
+static const float pdsch_N_1_capability_2[3][2] = {
 /* mu      A */   
 {  0,      3   },
 {  1,      4.5 },
@@ -84,7 +84,7 @@ float pdsch_N_1_capability_2[3][2] = {
 //   carrying the DCI scheduling the PUSCH was transmitted
 //   mu_UL is the SCS of the UL channel with which PUSCH to be transmitted
 */
-int8_t pusch_N_2_timing_capability_1[4][2] = {
+static const int8_t pusch_N_2_timing_capability_1[4][2] = {
 /* mu      N_2   */
 {  0,      10 },
 {  1,      12 },
@@ -101,7 +101,7 @@ int8_t pusch_N_2_timing_capability_1[4][2] = {
 //   mu_UL is the SCS of the UL channel with which PUSCH to be transmitted
 // mu == 2 is for FR1 only
 */
-float pusch_N_2_timing_capability_2[3][2] = {
+static const float pusch_N_2_timing_capability_2[3][2] = {
 /* mu      N_2   */
 {  0,      5   },
 {  1,      5.5 },
@@ -116,7 +116,7 @@ float pusch_N_2_timing_capability_2[3][2] = {
 //   carrying the DCI scheduling the PUSCH was transmitted
 //   mu_UL is the SCS of the UL channel with which PUSCH to be transmitted
 */
-float pusch_d_2_2_timing_capability_1[4][2] = {
+static const float pusch_d_2_2_timing_capability_1[4][2] = {
 /* mu      d_2_2   */
 {  0,      1   },
 {  1,      2   },
@@ -132,7 +132,7 @@ float pusch_d_2_2_timing_capability_1[4][2] = {
 //   carrying the DCI scheduling the PUSCH was transmitted
 //   mu_UL is the SCS of the UL channel with which PUSCH to be transmitted
 */
-float pusch_d_2_2_timing_capability_2[4][2] = {
+static const float pusch_d_2_2_timing_capability_2[4][2] = {
 /* mu      d_2_2   */
 {  0,      3   },
 {  1,      5   },
diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c
index 12d50065fa8..c19680c6d0c 100644
--- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c
+++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/pucch_uci_test.c
@@ -869,7 +869,6 @@ uint32_t tst_ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t e
 *********************************************************************/
 
 void tst_set_sr_config(PHY_VARS_NR_UE *ue, int gNB_id) {
-  ue->mac_enabled = 1;
   ue->scheduling_request_config[gNB_id].sr_ConfigIndex = 0;
   p_nr_ue_get_SR = tst_ue_get_SR;
 }
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index 25063f3141f..2f4b838e2b0 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -380,6 +380,16 @@ typedef struct {
 
 } NR_SSB_meas_t;
 
+typedef struct NR_UL_TIME_ALIGNMENT {
+  /// TA command and TAGID received from the gNB
+  bool ta_apply;
+  int ta_command;
+  int ta_total;
+  uint32_t tag_id;
+  int frame;
+  int slot;
+} NR_UL_TIME_ALIGNMENT_t;
+
 /*!\brief Top level UE MAC structure */
 typedef struct {
   NR_UE_L2_STATE_t state;
@@ -402,11 +412,12 @@ typedef struct {
 
   NR_UE_DL_BWP_t current_DL_BWP;
   NR_UE_UL_BWP_t current_UL_BWP;
+  NR_UL_TIME_ALIGNMENT_t ul_time_alignment;
 
-  NR_BWP_Downlink_t               *DLbwp[MAX_NUM_BWP_UE];
-  NR_BWP_Uplink_t                 *ULbwp[MAX_NUM_BWP_UE];
-  NR_ControlResourceSet_t         *coreset[MAX_NUM_BWP_UE][FAPI_NR_MAX_CORESET_PER_BWP];
-  NR_SearchSpace_t                *SSpace[MAX_NUM_BWP_UE][FAPI_NR_MAX_SS];
+  NR_BWP_Downlink_t *DLbwp[MAX_NUM_BWP_UE];
+  NR_BWP_Uplink_t *ULbwp[MAX_NUM_BWP_UE];
+  NR_ControlResourceSet_t *coreset[MAX_NUM_BWP_UE][FAPI_NR_MAX_CORESET_PER_BWP];
+  NR_SearchSpace_t *SSpace[MAX_NUM_BWP_UE][FAPI_NR_MAX_SS];
 
   bool phy_config_request_sent;
   frame_type_t frame_type;
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index c8eec75d85c..bcb4eefe536 100644
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -235,11 +235,9 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp);
 @returns void
 */
 void nr_ue_send_sdu(nr_downlink_indication_t *dl_info,
-                    NR_UL_TIME_ALIGNMENT_t *ul_time_alignment,
                     int pdu_id);
 
 void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
-                           NR_UL_TIME_ALIGNMENT_t *ul_time_alignment,
                            int pdu_id);
 
 int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
@@ -333,6 +331,7 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
 void nr_ue_pucch_scheduler(module_id_t module_idP, frame_t frameP, int slotP, void *phy_data);
 void nr_schedule_csirs_reception(NR_UE_MAC_INST_t *mac, int frame, int slot);
 void nr_schedule_csi_for_im(NR_UE_MAC_INST_t *mac, int frame, int slot);
+void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment);
 
 /* \brief This function schedules the Msg3 transmission
 @param
@@ -367,7 +366,7 @@ random-access procedure
 @param selected_rar_buffer the output buffer for storing the selected RAR header and RAR payload
 @returns timing advance or 0xffff if preamble doesn't match
 */
-int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id);
+int nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id);
 
 void nr_ue_contention_resolution(module_id_t module_id, int cc_id, frame_t frame, int slot, NR_PRACH_RESOURCES_t *prach_resources);
 
diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
index 31c665524ed..c6e13c412bf 100644
--- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
+++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
@@ -50,16 +50,10 @@ NR_UE_MAC_INST_t * nr_l2_init_ue(NR_UE_RRC_INST_t* rrc_inst) {
     //LOG_I(MAC, "[MAIN] init UE MAC functions \n");
     
     //init mac here
-    nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(sizeof(NR_UE_MAC_INST_t),NB_NR_UE_MAC_INST);
-    nr_ue_mac_inst->first_sync_frame = -1;
-    nr_ue_mac_inst->sib1_decoded = false;
-    nr_ue_mac_inst->phy_config_request_sent = false;
-    nr_ue_mac_inst->state = UE_NOT_SYNC;
-    memset(&nr_ue_mac_inst->ssb_measurements, 0, sizeof(nr_ue_mac_inst->ssb_measurements));
+    nr_ue_mac_inst = (NR_UE_MAC_INST_t *)calloc(sizeof(NR_UE_MAC_INST_t), NB_NR_UE_MAC_INST);
 
-    for (int j=0;j<NB_NR_UE_MAC_INST;j++) {
-	nr_ue_init_mac(j);
-    }
+    for (int j = 0; j < NB_NR_UE_MAC_INST; j++)
+      nr_ue_init_mac(j);
 
     if (rrc_inst && rrc_inst->scell_group_config) {
 
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 9542e19514c..37ff36e05f4 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -131,9 +131,8 @@ const initial_pucch_resource_t initial_pucch_resource[16] = {
 };
 
 
-void nr_ue_init_mac(module_id_t module_idP) {
-  int i;
-
+void nr_ue_init_mac(module_id_t module_idP)
+{
   NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
   // default values as deined in 38.331 sec 9.2.2
   LOG_I(NR_MAC, "[UE%d] Applying default macMainConfig\n", module_idP);
@@ -162,7 +161,7 @@ void nr_ue_init_mac(module_id_t module_idP) {
 //  mac->scheduling_info.PathlossChange_db = nr_get_db_dl_PathlossChange(mac->scheduling_info.PathlossChange);
 //  mac->PHR_reporting_active = 0;
 
-  for (i = 0; i < NR_MAX_NUM_LCID; i++) {
+  for (int i = 0; i < NR_MAX_NUM_LCID; i++) {
     LOG_D(NR_MAC, "[UE%d] Applying default logical channel config for LCGID %d\n",
                  module_idP, i);
     mac->scheduling_info.Bj[i] = -1;
@@ -176,8 +175,16 @@ void nr_ue_init_mac(module_id_t module_idP) {
 
     mac->scheduling_info.LCID_status[i] = LCID_EMPTY;
     mac->scheduling_info.LCID_buffer_remain[i] = 0;
-    for (int i=0;i<NR_MAX_HARQ_PROCESSES;i++) mac->first_ul_tx[i]=1;
+    for (int i = 0; i < NR_MAX_HARQ_PROCESSES; i++)
+      mac->first_ul_tx[i] = 1;
   }
+
+  mac->first_sync_frame = -1;
+  mac->sib1_decoded = false;
+  mac->phy_config_request_sent = false;
+  mac->state = UE_NOT_SYNC;
+  memset(&mac->ssb_measurements, 0, sizeof(mac->ssb_measurements));
+  memset(&mac->ul_time_alignment, 0, sizeof(mac->ul_time_alignment));
 }
 
 NR_BWP_DownlinkCommon_t *get_bwp_downlink_common(NR_UE_MAC_INST_t *mac, NR_BWP_Id_t dl_bwp_id) {
@@ -2380,8 +2387,8 @@ uint8_t get_rsrp_diff_index(int best_rsrp,int current_rsrp) {
 
 }
 
-void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){
-
+void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, int pdu_id)
+{
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
 
   LOG_D(MAC, "In %s [%d.%d] Handling DLSCH PDU...\n", __FUNCTION__, dl_info->frame, dl_info->slot);
@@ -2390,10 +2397,10 @@ void nr_ue_send_sdu(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *u
   // it parses MAC CEs subheaders, MAC CEs, SDU subheaderds and SDUs
   switch (dl_info->rx_ind->rx_indication_body[pdu_id].pdu_type){
     case FAPI_NR_RX_PDU_TYPE_DLSCH:
-    nr_ue_process_mac_pdu(dl_info, ul_time_alignment, pdu_id);
+    nr_ue_process_mac_pdu(dl_info, pdu_id);
     break;
     case FAPI_NR_RX_PDU_TYPE_RAR:
-    nr_ue_process_rar(dl_info, ul_time_alignment, pdu_id);
+    nr_ue_process_rar(dl_info, pdu_id);
     break;
     default:
     break;
@@ -3107,8 +3114,8 @@ static uint8_t nr_extract_dci_info(NR_UE_MAC_INST_t *mac,
 //  R:    Reserved bit, set to zero.
 ////////////////////////////////
 void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
-                           NR_UL_TIME_ALIGNMENT_t *ul_time_alignment,
-                           int pdu_id){
+                           int pdu_id)
+{
 
   module_id_t module_idP = dl_info->module_id;
   frame_t frameP         = dl_info->frame;
@@ -3228,11 +3235,14 @@ void nr_ue_process_mac_pdu(nr_downlink_indication_t *dl_info,
 
         const int ta = ((NR_MAC_CE_TA *)pduP)[1].TA_COMMAND;
         const int tag = ((NR_MAC_CE_TA *)pduP)[1].TAGID;
-        ul_time_alignment->apply_ta = 1;
-        ul_time_alignment->ta_command = ta; //here
+
+        NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
         ul_time_alignment->ta_total += ta - 31;
         ul_time_alignment->tag_id = tag;
-
+        ul_time_alignment->ta_command = ta;
+        ul_time_alignment->frame = frameP;
+        ul_time_alignment->slot = slot;
+        ul_time_alignment->ta_apply = true;
         /*
         #ifdef DEBUG_HEADER_PARSING
         LOG_D(MAC, "[UE] CE %d : UE Timing Advance : %d\n", i, pduP[1]);
@@ -3515,8 +3525,8 @@ int nr_write_ce_ulsch_pdu(uint8_t *mac_ce,
 // - b buffer
 // - ulsch power offset
 // - optimize: mu_pusch, j and table_6_1_2_1_1_2_time_dom_res_alloc_A are already defined in nr_ue_procedures
-int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){
-
+int nr_ue_process_rar(nr_downlink_indication_t *dl_info, int pdu_id)
+{
   module_id_t mod_id       = dl_info->module_id;
   frame_t frame            = dl_info->frame;
   int slot                 = dl_info->slot;
@@ -3601,12 +3611,12 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t
 #endif
 
     // TA command
-    ul_time_alignment->apply_ta = 1;
+    NR_UL_TIME_ALIGNMENT_t *ul_time_alignment = &mac->ul_time_alignment;
     const int ta = rar->TA2 + (rar->TA1 << 5);
     ul_time_alignment->ta_command = 31 + ta;
     ul_time_alignment->ta_total = ta;
-    LOG_W(MAC, "received TA command %d\n", ul_time_alignment->ta_command);
-
+    ul_time_alignment->ta_apply = true;
+    LOG_W(MAC, "received TA command %d\n", 31 + ta);
 #ifdef DEBUG_RAR
     // CSI
     csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01);
@@ -3674,7 +3684,7 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t
       mod_id,
       rar_grant.Msg3_t_alloc,
       rar_grant.Msg3_f_alloc,
-      ul_time_alignment->ta_command,
+      ta_command,
       rar_grant.mcs,
       rar_grant.freq_hopping,
       tpc_command,
@@ -3720,10 +3730,7 @@ int nr_ue_process_rar(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t
     }
 
   } else {
-
     ra->t_crnti = 0;
-    ul_time_alignment->ta_command = (0xffff);
-
   }
 
   return ret;
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index a3f4d06b1c5..8f379726f71 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -1024,6 +1024,8 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info)
     nr_ue_dcireq(&dcireq); //to be replaced with function pointer later
     *dl_config = dcireq.dl_config_req;
 
+    if(mac->ul_time_alignment.ta_apply)
+      schedule_ta_command(dl_config, &mac->ul_time_alignment);
     nr_schedule_csirs_reception(mac, rx_frame, rx_slot);
     nr_schedule_csi_for_im(mac, rx_frame, rx_slot);
     dcireq.dl_config_req = *dl_config;
@@ -1037,6 +1039,8 @@ void nr_ue_dl_scheduler(nr_downlink_indication_t *dl_info)
   else if (mac->state == UE_PERFORMING_RA) {
     // this is for Msg2/Msg4
     if (mac->ra.ra_state >= WAIT_RAR) {
+      if(mac->ul_time_alignment.ta_apply)
+        schedule_ta_command(dl_config, &mac->ul_time_alignment);
       fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &dl_config->dl_config_list[dl_config->number_pdus].dci_config_pdu.dci_config_rel15;
       rel15->num_dci_options = mac->ra.ra_state == WAIT_RAR ? 1 : 2;
       rel15->dci_format_options[0] = NR_DL_DCI_FORMAT_1_0;
@@ -3178,5 +3182,15 @@ uint8_t nr_ue_get_sdu(module_id_t module_idP,
   #endif
 
   return num_sdus > 0 ? 1 : 0;
+}
 
+void schedule_ta_command(fapi_nr_dl_config_request_t *dl_config, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment)
+{
+  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_command = ul_time_alignment->ta_command;
+  dl_config->dl_config_list[dl_config->number_pdus].pdu_type = FAPI_NR_CONFIG_TA_COMMAND;
+  dl_config->number_pdus += 1;
+  ul_time_alignment->ta_apply = false;
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index e6f32b14058..bfa34e977ed 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -108,10 +108,8 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
     AssertFatal(timing_advance_cmd < 64, "timing_advance_cmd %d > 63\n", timing_advance_cmd);
     ((NR_MAC_CE_TA *) ce_ptr)->TA_COMMAND = timing_advance_cmd;    //(timing_advance_cmd+31)&0x3f;
 
-    if (gNB->tag->tag_Id != 0) {
-      tag_id = gNB->tag->tag_Id;
-      ((NR_MAC_CE_TA *) ce_ptr)->TAGID = tag_id;
-    }
+    tag_id = gNB->tag->tag_Id;
+    ((NR_MAC_CE_TA *) ce_ptr)->TAGID = tag_id;
 
     LOG_D(NR_MAC, "NR MAC CE timing advance command = %d (%d) TAG ID = %d\n", timing_advance_cmd, ((NR_MAC_CE_TA *) ce_ptr)->TA_COMMAND, tag_id);
     mac_ce_size = sizeof(NR_MAC_CE_TA);
@@ -1191,7 +1189,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
         T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_INT(harq->round), T_BUFFER(harq->transportBlock, TBS));
       UE->mac_stats.dl.total_rbs_retx += sched_pdsch->rbSize;
     } else { /* initial transmission */
-      LOG_D(NR_MAC, "[%s] Initial HARQ transmission in %d.%d\n", __FUNCTION__, frame, slot);
+      LOG_D(NR_MAC, "Initial HARQ transmission in %d.%d\n", frame, slot);
       uint8_t *buf = (uint8_t *) harq->transportBlock;
       /* first, write all CEs that might be there */
       int written = nr_write_ce_dlsch_pdu(module_id,
diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
index 6aa44194a31..3f44c8c2a61 100644
--- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
@@ -443,9 +443,7 @@ static void copy_dl_tti_req_to_dl_info(nr_downlink_indication_t *dl_info, nfapi_
             rx_ind->sfn = dl_tti_request->SFN;
             rx_ind->slot = dl_tti_request->Slot;
             fill_mib_in_rx_ind(pdu_list, rx_ind, 0, FAPI_NR_RX_PDU_TYPE_SSB);
-            NR_UL_TIME_ALIGNMENT_t ul_time_alignment;
-            memset(&ul_time_alignment, 0, sizeof(ul_time_alignment));
-            nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment);
+            nr_ue_dl_indication(&mac->dl_info);
         }
     }
     dl_info->slot = dl_tti_request->Slot;
@@ -729,15 +727,12 @@ void check_and_process_dci(nfapi_nr_dl_tti_request_t *dl_tti_request,
         return;
     }
 
-
-    NR_UL_TIME_ALIGNMENT_t ul_time_alignment;
-    memset(&ul_time_alignment, 0, sizeof(ul_time_alignment));
     if (dl_tti_request || tx_data_request || ul_dci_request) {
       fapi_nr_dl_config_request_t *dl_config = get_dl_config_request(mac, slot);
       fill_dci_from_dl_config(&mac->dl_info, dl_config);
     }
     nr_ue_dl_scheduler(&mac->dl_info);
-    nr_ue_dl_indication(&mac->dl_info, &ul_time_alignment);
+    nr_ue_dl_indication(&mac->dl_info);
 
     if (pthread_mutex_unlock(&mac->mutex_dl_info)) abort();
 
@@ -1085,7 +1080,8 @@ void handle_ssb_meas(NR_UE_MAC_INST_t *mac, uint8_t ssb_index, int16_t rsrp_dbm)
 
 // L2 Abstraction Layer
 // Note: sdu should always be processed because data and timing advance updates are transmitted by the UE
-int8_t handle_dlsch(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment, int pdu_id){
+int8_t handle_dlsch(nr_downlink_indication_t *dl_info, int pdu_id)
+{
   /* L1 assigns harq_pid, but in emulated L1 mode we need to assign
      the harq_pid based on the saved global g_harq_pid. Because we are
      emulating L1, no antenna measurements are conducted to calculate
@@ -1097,7 +1093,7 @@ int8_t handle_dlsch(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *u
                      dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.harq_pid,
                      dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack);
   if(dl_info->rx_ind->rx_indication_body[pdu_id].pdsch_pdu.ack_nack)
-    nr_ue_send_sdu(dl_info, ul_time_alignment, pdu_id);
+    nr_ue_send_sdu(dl_info, pdu_id);
 
   return 0;
 }
@@ -1142,8 +1138,8 @@ int nr_ue_ul_indication(nr_uplink_indication_t *ul_info)
   return 0;
 }
 
-int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment){
-
+int nr_ue_dl_indication(nr_downlink_indication_t *dl_info)
+{
   pthread_mutex_lock(&mac_IF_mutex);
   uint32_t ret_mask = 0x0;
   module_id_t module_id = dl_info->module_id;
@@ -1193,13 +1189,12 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_
 
     if (dl_info->rx_ind != NULL) {
 
-      for (int i=0; i<dl_info->rx_ind->number_pdus; ++i) {
+      for (int i = 0; i < dl_info->rx_ind->number_pdus; ++i) {
 
         fapi_nr_rx_indication_body_t rx_indication_body = dl_info->rx_ind->rx_indication_body[i];
-        LOG_D(NR_MAC, "In %s sending DL indication to MAC. 1 PDU type %d of %d total number of PDUs \n",
-          __FUNCTION__,
-          rx_indication_body.pdu_type,
-          dl_info->rx_ind->number_pdus);
+        LOG_D(NR_MAC, "Sending DL indication to MAC. 1 PDU type %d of %d total number of PDUs \n",
+              rx_indication_body.pdu_type,
+              dl_info->rx_ind->number_pdus);
 
         switch(rx_indication_body.pdu_type){
           case FAPI_NR_RX_PDU_TYPE_SSB:
@@ -1226,10 +1221,10 @@ int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_
                                            rx_indication_body.pdsch_pdu.pdu_length)) << FAPI_NR_RX_PDU_TYPE_SIB;
             break;
           case FAPI_NR_RX_PDU_TYPE_DLSCH:
-            ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH;
+            ret_mask |= (handle_dlsch(dl_info, i)) << FAPI_NR_RX_PDU_TYPE_DLSCH;
             break;
           case FAPI_NR_RX_PDU_TYPE_RAR:
-            ret_mask |= (handle_dlsch(dl_info, ul_time_alignment, i)) << FAPI_NR_RX_PDU_TYPE_RAR;
+            ret_mask |= (handle_dlsch(dl_info, i)) << FAPI_NR_RX_PDU_TYPE_RAR;
             break;
           case FAPI_NR_CSIRS_IND:
             ret_mask |= (handle_csirs_measurements(dl_info->module_id,
diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h
index 91775794ede..e80459ee5fc 100644
--- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h
+++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.h
@@ -195,7 +195,7 @@ typedef void (nr_ue_synch_request_f)(nr_synch_request_t *synch_request);
  *  -1: Failed to consume bytes. Abort the mission.
  * Non-negative return values indicate success, and ignored.
  */
-typedef int (nr_ue_dl_indication_f)(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment);
+typedef int (nr_ue_dl_indication_f)(nr_downlink_indication_t *dl_info);
 
 /*
  * Generic type of an application-defined callback to return various
@@ -256,7 +256,7 @@ int nr_ue_if_module_kill(uint32_t module_id);
 
 /**\brief interface between L1/L2, indicating the downlink related information, like dci_ind and rx_req
    \param dl_info including dci_ind and rx_request messages*/
-int nr_ue_dl_indication(nr_downlink_indication_t *dl_info, NR_UL_TIME_ALIGNMENT_t *ul_time_alignment);
+int nr_ue_dl_indication(nr_downlink_indication_t *dl_info);
 
 int nr_ue_ul_indication(nr_uplink_indication_t *ul_info);
 
-- 
GitLab