From fd3d49bbe7e0902f4ae08c025fca01482ac460b7 Mon Sep 17 00:00:00 2001
From: Robert Schmidt <robert.schmidt@eurecom.fr>
Date: Tue, 13 Oct 2020 19:32:19 +0200
Subject: [PATCH] Correctly check and apply the TA in DLSCH scheduler

---
 openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c    | 13 ---------
 .../LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c   | 29 ++++++++++++++++++-
 2 files changed, 28 insertions(+), 14 deletions(-)

diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 4e60bd2ab8..083692e0e3 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -470,18 +470,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
     nr_schedule_reception_msg3(module_idP, 0, frame, slot);
   }
 
-  if (UE_info->active[UE_id]) {
-    // TbD once RACH is available, start ta_timer when UE is connected
-    if (ue_sched_ctl->ta_timer)
-      ue_sched_ctl->ta_timer--;
-    if (ue_sched_ctl->ta_timer == 0) {
-      ue_sched_ctl->ta_apply = true;
-      /* if time is up, then set the timer to not send it for 5 frames
-      // regardless of the TA value */
-      ue_sched_ctl->ta_timer = 100;
-    }
-  }
-
   // This schedules the DCI for Uplink and subsequently PUSCH
   // The decision about whether to schedule is done for each UE independently
   // inside
@@ -499,7 +487,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
     //nr_update_pucch_scheduling(module_idP, UE_id, frame, slot, num_slots_per_tdd,&pucch_sched);
     //nr_schedule_uss_dlsch_phytest(module_idP, frame, slot, &UE_info->UE_sched_ctrl[UE_id].sched_pucch[pucch_sched], NULL);
     nr_schedule_ue_spec(module_idP, frame, slot, num_slots_per_tdd);
-    ue_sched_ctl->ta_apply = false;
   }
 
   if (UE_info->active[UE_id])
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 640068ecae..abd866f9e7 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -500,7 +500,9 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
                                                     0,
                                                     0);
   sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
-  if (sched_ctrl->num_total_bytes == 0 && !get_softmodem_params()->phy_test)
+  if (sched_ctrl->num_total_bytes == 0
+      && !get_softmodem_params()->phy_test
+      && !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */
     return;
   LOG_D(MAC,
         "%d.%d, DTCH%d->DLSCH, RLC status %d bytes\n",
@@ -632,10 +634,26 @@ void nr_schedule_ue_spec(module_id_t module_id,
   NR_UE_info_t *UE_info = &gNB_mac->UE_info;
 
   const int CC_id = 0;
+  /* calculate number of slots since last DL scheduling, since the scheduler is
+   * not called in every slot. */
+  const NR_COMMON_channels_t *cc = gNB_mac->common_channels;
+  const NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
+  const NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
+  const int slot_diff =
+      (slot % num_slots_per_tdd) == 0 ? tdd_pattern->nrofUplinkSlots + 1 : 1;
 
   NR_UE_list_t *UE_list = &UE_info->list;
   for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+
+    /* update TA and set ta_apply upon expiry. If such UE is not scheduled now,
+     * it will be by the preprocessor later. If we add the CE, ta_apply will be
+     * reset */
+    if (sched_ctrl->ta_timer > 0)
+      sched_ctrl->ta_timer -= slot_diff;
+    else
+      sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
+
     if (sched_ctrl->rbSize <= 0 && !get_softmodem_params()->phy_test)
       continue;
 
@@ -733,6 +751,15 @@ void nr_schedule_ue_spec(module_id_t module_id,
       /* reserve space for timing advance of UE if necessary,
        * nr_generate_dlsch_pdu() checks for ta_apply and add TA CE if necessary */
       const int ta_len = (sched_ctrl->ta_apply) ? 2 : 0;
+      if (sched_ctrl->ta_apply) {
+        LOG_I(MAC,
+              "%d.%2d UE %d TA scheduled, resetting timer to 100\n",
+              frame,
+              slot,
+              UE_id);
+        sched_ctrl->ta_apply = false;
+        sched_ctrl->ta_timer = 100;
+      }
 
       /* Get RLC data TODO: remove random data retrieval */
       int header_length_total = 0;
-- 
2.26.2