From 2e7c28a591bc69649de9be11905349fe0d9f2421 Mon Sep 17 00:00:00 2001
From: "Wilson W.K. Thong" <wilsonthong@astri.org>
Date: Fri, 6 Jan 2017 11:55:22 +0800
Subject: [PATCH] fix incorrect PUCCH format causing no SR received by eNB in
 TDD fix incorrect fss_pusch calculation fix the incorrrect HARQ-PID checking
 remove incorrect checking on downlink DCI HARQ PID value fix incorrect
 downlink ACK/NACK feedback procedures in TDD fix no activating PDSCH decoding
 when DL-DCI is indicating a downlink retransmission

see issue #176
---
 openair1/PHY/CODING/TESTBENCH/ltetest.c     |   1 +
 openair1/PHY/LTE_TRANSPORT/dci_tools.c      | 228 ++++++++++++-------
 openair1/PHY/LTE_TRANSPORT/defs.h           |   6 +-
 openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c |  19 ++
 openair1/PHY/LTE_TRANSPORT/group_hopping.c  |   3 +-
 openair1/PHY/LTE_TRANSPORT/phich.c          |  10 +
 openair1/PHY/LTE_TRANSPORT/proto.h          |   5 +-
 openair1/PHY/LTE_TRANSPORT/ulsch_coding.c   |  10 +
 openair1/PHY/impl_defs_lte.h                |   2 +
 openair1/SCHED/defs.h                       |  14 ++
 openair1/SCHED/phy_procedures_lte_common.c  | 174 +++++++++++----
 openair1/SCHED/phy_procedures_lte_ue.c      | 231 +++++++++++++++-----
 openair1/SIMULATION/LTE_PHY/mbmssim.c       |   1 +
 openair1/SIMULATION/LTE_PHY/syncsim.c       |   1 +
 openair2/LAYER2/MAC/proto.h                 |   2 +-
 openair2/LAYER2/MAC/ue_procedures.c         |   3 +-
 openair2/PHY_INTERFACE/defs.h               |   2 +-
 17 files changed, 516 insertions(+), 196 deletions(-)

diff --git a/openair1/PHY/CODING/TESTBENCH/ltetest.c b/openair1/PHY/CODING/TESTBENCH/ltetest.c
index bb4c136af..6bc5e2526 100644
--- a/openair1/PHY/CODING/TESTBENCH/ltetest.c
+++ b/openair1/PHY/CODING/TESTBENCH/ltetest.c
@@ -256,6 +256,7 @@ int test_logmap8(LTE_eNB_DLSCH_t *dlsch_eNB,
                          &PHY_vars_UE->lte_frame_parms,
                          PHY_vars_UE->dlsch_ue[0][0],
                          PHY_vars_UE->dlsch_ue[0][0]->harq_processes[PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid],
+                         frame,
                          subframe,
                          PHY_vars_UE->dlsch_ue[0][0]->current_harq_pid,
                          num_pdcch_symbols,1);
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index 1dfbc9d7d..d4fc7bdf3 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -1061,8 +1061,8 @@ int generate_eNB_dlsch_params_from_dci(int frame,
       // 36-213 sec.7.1.7.2 p.26
       I_mcs     = mcs;
     } else {
-      if (harq_pid>1) {
-        LOG_E(PHY,"ERROR: Format 1A: harq_pid > 1\n");
+      if (harq_pid>=8) {
+        LOG_E(PHY,"ERROR: Format 1A: harq_pid=%d >= 8\n", harq_pid);
         return(-1);
       }
 
@@ -1206,7 +1206,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
     }
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 1: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 1: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -1496,7 +1496,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
 
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -1848,7 +1848,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
 
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -2117,7 +2117,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
 
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -2279,7 +2279,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
 
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -2450,7 +2450,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
 
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -2528,7 +2528,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
     harq_pid  = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->harq_pid;
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 1E_2A_M10PRB: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 1E_2A_M10PRB: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -3818,7 +3818,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
                                       uint16_t si_rnti,
                                       uint16_t ra_rnti,
                                       uint16_t p_rnti,
-                                      uint8_t beamforming_mode)
+                                      uint8_t beamforming_mode,
+                                      uint16_t tc_rnti)
 {
 
   uint8_t harq_pid=0;
@@ -3832,11 +3833,29 @@ int generate_ue_dlsch_params_from_dci(int frame,
   uint8_t TPC=0;
   uint8_t NPRB=0,tbswap=0,tpmi=0;
   uint8_t Ngap;
+  uint8_t dai=0;
   LTE_UE_DLSCH_t *dlsch0=NULL,*dlsch1=NULL;
   LTE_DL_UE_HARQ_t *dlsch0_harq,*dlsch1_harq;
 
 #ifdef DEBUG_DCI
-  LOG_D(PHY,"dci_tools.c: Filling ue dlsch params -> rnti %x, dci_format %d\n",rnti,dci_format);
+  LOG_D(PHY,"dci_tools.c: Filling ue dlsch params -> rnti %x, SFN/SF %d/%d, dci_format %s\n",
+      rnti,
+      frame%1024,
+      subframe,
+      (dci_format==format0?  "Format 0":(
+       dci_format==format1?  "format 1":(
+       dci_format==format1A? "format 1A":(
+       dci_format==format1B? "format 1B":(
+       dci_format==format1C? "format 1C":(
+       dci_format==format1D? "format 1D":(
+       dci_format==format1E_2A_M10PRB? "format 1E_2A_M10PRB":(
+       dci_format==format2?  "format 2":(
+       dci_format==format2A? "format 2A":(
+       dci_format==format2B? "format 2B":(
+       dci_format==format2C? "format 2C":(
+       dci_format==format2D? "format 2D":(
+       dci_format==format3?  "format 3": "UNKNOWN"
+       ))))))))))))));
 #endif
 
   switch (dci_format) {
@@ -3858,6 +3877,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
         ndi      = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->ndi;
         TPC      = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->TPC;
         harq_pid = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid;
+        dai      = ((DCI1A_1_5MHz_TDD_1_6_t *)dci_pdu)->dai;
         //  printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC);
       } else {
         vrb_type = ((DCI1A_1_5MHz_FDD_t *)dci_pdu)->vrb_type;
@@ -3877,8 +3897,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
         NPRB = (TPC&1) + 2;
       } else {
 
-        if (harq_pid>1) {
-          LOG_E(PHY,"Format 1A: harq_pid > 1\n");
+        if (harq_pid>=8) {
+          LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid);
           return(-1);
         }
 
@@ -3914,6 +3934,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
         ndi      = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->ndi;
         TPC      = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->TPC;
         harq_pid = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->harq_pid;
+        dai      = ((DCI1A_5MHz_TDD_1_6_t *)dci_pdu)->dai;
         //printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC);
       } else {
         vrb_type = ((DCI1A_5MHz_FDD_t *)dci_pdu)->vrb_type;
@@ -3933,10 +3954,10 @@ int generate_ue_dlsch_params_from_dci(int frame,
         dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
       } else {
 
-        //if (harq_pid>1) {
-        //  LOG_E(PHY,"Format 1A: harq_pid > 1\n");
-         // return(-1);
-        //}
+        if (harq_pid>=8) {
+          LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid);
+          return(-1);
+        }
 
         dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
         NPRB = RIV2nb_rb_LUT25[rballoc];
@@ -3967,6 +3988,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
         ndi      = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->ndi;
         TPC      = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->TPC;
         harq_pid = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->harq_pid;
+        dai      = ((DCI1A_10MHz_TDD_1_6_t *)dci_pdu)->dai;
         //  printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC);
       } else {
         vrb_type = ((DCI1A_10MHz_FDD_t *)dci_pdu)->vrb_type;
@@ -3986,8 +4008,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
         NPRB = (TPC&1) + 2;
       } else {
 
-        if (harq_pid>1) {
-          LOG_E(PHY,"Format 1A: harq_pid > 1\n");
+        if (harq_pid>=8) {
+          LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid);
           return(-1);
         }
 
@@ -4034,6 +4056,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
         ndi      = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->ndi;
         TPC      = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->TPC;
         harq_pid = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->harq_pid;
+        dai      = ((DCI1A_20MHz_TDD_1_6_t *)dci_pdu)->dai;
         //  printf("TDD 1A: mcs %d, rballoc %x,rv %d, TPC %d\n",mcs,rballoc,rv,TPC);
       } else {
         vrb_type = ((DCI1A_20MHz_FDD_t *)dci_pdu)->vrb_type;
@@ -4053,8 +4076,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
         NPRB = (TPC&1) + 2;
       } else {
 
-        if (harq_pid>1) {
-          LOG_E(PHY,"Format 1A: harq_pid > 1\n");
+        if (harq_pid>=8) {
+          LOG_E(PHY,"Format 1A: harq_pid=%d >= 8\n", harq_pid);
           return(-1);
         }
 
@@ -4139,16 +4162,9 @@ int generate_ue_dlsch_params_from_dci(int frame,
     dlsch0_harq->mimo_mode = frame_parms->mode1_flag == 1 ?SISO : ALAMOUTI;
     dlsch0_harq->dl_power_off = 1; //no power offset
 
-    LOG_D(PHY,"UE (%x/%d): Subframe %d Format1A DCI: ndi %d, old_ndi %d (first tx %d) harq_status %d, round %d\n",
-	  dlsch[0]->rnti,
-	  harq_pid,
-	  subframe,
-	  ndi,
-	  dlsch0_harq->DCINdi,
-	  dlsch0_harq->first_tx,
-	  dlsch0_harq->status,
-	  dlsch0_harq->round);
-    if ((ndi!=dlsch0_harq->DCINdi)||  // DCI has been toggled or this is the first transmission
+    dlsch[0]->active = 1; // fix no DLSCH decoding for downlink retransmission
+
+    if ((ndi!=dlsch0_harq->DCINdi) ||  // DCI has been toggled or this is the first transmission
         (dlsch0_harq->first_tx==1)) {
       dlsch0_harq->round = 0;
 
@@ -4156,10 +4172,41 @@ int generate_ue_dlsch_params_from_dci(int frame,
         //LOG_I(PHY,"[PDSCH %x/%d] Format 1A DCI First TX: Clearing flag\n");
         dlsch0_harq->first_tx = 0;
       }
-    }
+    } else if (dlsch0_harq->round == 0) { // duplicated PDSCH received. possibly eNB missed the previous DL ACK/NACK feedback
 
-    dlsch0_harq->DCINdi = ndi;
+      // skip PDSCH decoding
+      dlsch[0]->active = 0;
+      // report ACK back to eNB for this duplicated PDSCH
+      dlsch0_harq->status = SCH_IDLE;
+      dlsch0_harq->round = 0;
+      dlsch[0]->harq_ack[subframe].ack = 1;
+      dlsch[0]->harq_ack[subframe].harq_id = harq_pid;
+      dlsch[0]->harq_ack[subframe].send_harq_status = 1;
+      LOG_D(PHY,"UE (%x/%d): Format1A DCI: Duplicated PDSCH. Setting ACK for subframe %d (pid %d, round 0)\n",
+          dlsch[0]->rnti,harq_pid, subframe,harq_pid);
+    }
+
+    LOG_D(PHY,"UE (%x/%d): SFN/SF %4d/%1d Format1A DCI: dai %d, ndi %d, old_ndi %d (first tx %d), harq_status %d, round %d\n",
+          rnti,
+          harq_pid,
+          frame % 1024,
+          subframe,
+          dai,
+          ndi,
+          dlsch0_harq->DCINdi,
+          dlsch0_harq->first_tx,
+          dlsch0_harq->status,
+          dlsch0_harq->round);
+
+    if (rnti == tc_rnti) {
+      dlsch0_harq->DCINdi = (uint8_t)-1;
+      LOG_D(PHY,"UE (%x/%d): Format1A DCI: C-RNTI is temporary. Set NDI = %d and to be ignored\n",
+          rnti,harq_pid,dlsch0_harq->DCINdi);
+    } else {
+      dlsch0_harq->DCINdi = ndi;
+    }
 
+    dlsch[0]->harq_ack[subframe].vDAI_DL = dai+1;
     // this a retransmission
     if(dlsch0_harq->round)
     {
@@ -4184,7 +4231,6 @@ int generate_ue_dlsch_params_from_dci(int frame,
       dlsch0_harq->Qm  = get_Qm(mcs);
     }
     dlsch[0]->rnti = rnti;
-    dlsch[0]->active = 1;
     dlsch0 = dlsch[0];
     //printf("Format 1A: harq_pid %d, nb_rb %d, round %d\n",harq_pid,dlsch0_harq->nb_rb,dlsch0_harq->round);
     break;
@@ -4411,7 +4457,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
     }
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"Format 1: harq_pid >= 8\n");
+      LOG_E(PHY,"Format 1: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -4729,7 +4775,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
     }
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"Format 2_2A: harq_pid >= 8\n");
+      LOG_E(PHY,"Format 2_2A: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -5143,7 +5189,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
 
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid >= 8\n");
+      LOG_E(PHY,"ERROR: Format 2_2A: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -5407,7 +5453,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
     harq_pid  = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->harq_pid;
 
     if (harq_pid>=8) {
-      LOG_E(PHY,"Format 1E_2A_M10PRB: harq_pid >= 8\n");
+      LOG_E(PHY,"Format 1E_2A_M10PRB: harq_pid=%d >= 8\n", harq_pid);
       return(-1);
     }
 
@@ -5585,7 +5631,6 @@ int generate_ue_dlsch_params_from_dci(int frame,
   }
 
 #endif
-  dlsch[0]->active=1;
 
   // compute DL power control parameters
   computeRhoA_UE(pdsch_config_dedicated, dlsch[0],dlsch0_harq->dl_power_off);
@@ -6249,7 +6294,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
   uint8_t transmission_mode = ue->transmission_mode[eNB_id];
   ANFBmode_t AckNackFBMode;
   LTE_UE_ULSCH_t *ulsch = ue->ulsch[eNB_id];
-  //  LTE_UE_DLSCH_t **dlsch = ue->dlsch[0];
+  LTE_UE_DLSCH_t **dlsch = ue->dlsch[0];
   PHY_MEASUREMENTS *meas = &ue->measurements;
   LTE_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
   //  uint32_t current_dlsch_cqi = ue->current_dlsch_cqi[eNB_id];
@@ -6264,12 +6309,15 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
   }
 
   uint32_t cqi_req;
-  uint32_t dai=0;
+  uint32_t dai=3;
   uint32_t cshift;
   uint32_t TPC;
   uint32_t ndi;
   uint32_t mcs;
   uint32_t rballoc,RIV_max;
+  uint16_t* RIV2first_rb_LUT;
+  uint16_t* RIV2nb_rb_LUT;
+
   //  uint32_t hopping;
   //  uint32_t type;
 
@@ -6315,8 +6363,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
       }
 
       RIV_max = RIV_max6;
-      ulsch->harq_processes[harq_pid]->first_rb                              = RIV2first_rb_LUT6[rballoc];
-      ulsch->harq_processes[harq_pid]->nb_rb                                 = RIV2nb_rb_LUT6[rballoc];
+      RIV2first_rb_LUT = RIV2first_rb_LUT6;
+      RIV2nb_rb_LUT = RIV2nb_rb_LUT6;
 
       break;
 
@@ -6343,8 +6391,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
       }
 
       RIV_max = RIV_max25;
-      ulsch->harq_processes[harq_pid]->first_rb                              = RIV2first_rb_LUT25[rballoc];
-      ulsch->harq_processes[harq_pid]->nb_rb                                 = RIV2nb_rb_LUT25[rballoc];
+      RIV2first_rb_LUT = RIV2first_rb_LUT25;
+      RIV2nb_rb_LUT = RIV2nb_rb_LUT25;
       //      printf("***********rballoc %d, first_rb %d, nb_rb %d (dci %p)\n",rballoc,ulsch->harq_processes[harq_pid]->first_rb,ulsch->harq_processes[harq_pid]->nb_rb,dci_pdu);
       break;
 
@@ -6371,8 +6419,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
       }
 
       RIV_max = RIV_max50;
-      ulsch->harq_processes[harq_pid]->first_rb = RIV2first_rb_LUT50[rballoc];
-      ulsch->harq_processes[harq_pid]->nb_rb    = RIV2nb_rb_LUT50[rballoc];
+      RIV2first_rb_LUT = RIV2first_rb_LUT50;
+      RIV2nb_rb_LUT = RIV2nb_rb_LUT50;
 
       break;
 
@@ -6399,8 +6447,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
       }
 
       RIV_max = RIV_max100;
-      ulsch->harq_processes[harq_pid]->first_rb                              = RIV2first_rb_LUT100[rballoc];
-      ulsch->harq_processes[harq_pid]->nb_rb                                 = RIV2nb_rb_LUT100[rballoc];
+      RIV2first_rb_LUT = RIV2first_rb_LUT100;
+      RIV2nb_rb_LUT = RIV2nb_rb_LUT100;
 
       //      printf("rb_alloc (20 MHz dci) %d\n",rballoc);
       break;
@@ -6432,6 +6480,8 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
     }
 
     ulsch->harq_processes[harq_pid]->TPC                                   = TPC;
+    ulsch->harq_processes[harq_pid]->first_rb                              = RIV2first_rb_LUT[rballoc];
+    ulsch->harq_processes[harq_pid]->nb_rb                                 = RIV2nb_rb_LUT[rballoc];
 
     if (ue->ul_power_control_dedicated[eNB_id].accumulationEnabled == 1) {
       LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d subframe %d: f_pusch (ACC) %d, adjusting by %d (TPC %d)\n",
@@ -7063,6 +7113,13 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
       //      ulsch->harq_processes[harq_pid]->V_UL_DAI = dai+1;
     }
 
+    dlsch[0]->harq_ack[subframe].vDAI_UL = dai+1;
+
+    LOG_D(PHY, "[PUSCH %d] Format0 DCI %s, CQI_req=%d, cshift=%d, TPC=%d, DAI=%d, vDAI_UL[sf#%d]=%d, NDI=%d, MCS=%d, RBalloc=%d, first_rb=%d, harq_pid=%d, nb_rb=%d, subframe_scheduling_flag=%d\n",
+        harq_pid,
+        (frame_parms->frame_type == TDD? "TDD" : "FDD"),
+        cqi_req, cshift, TPC, dai, subframe, dlsch[0]->harq_ack[subframe].vDAI_UL, ndi, mcs, rballoc, ulsch->harq_processes[harq_pid]->first_rb, harq_pid, ulsch->harq_processes[harq_pid]->nb_rb, ulsch->harq_processes[harq_pid]->subframe_scheduling_flag);
+
     ulsch->beta_offset_cqi_times8                = beta_cqi[ue->pusch_config_dedicated[eNB_id].betaOffset_CQI_Index];//18;
     ulsch->beta_offset_ri_times8                 = beta_ri[ue->pusch_config_dedicated[eNB_id].betaOffset_RI_Index];//10;
     ulsch->beta_offset_harqack_times8            = beta_ack[ue->pusch_config_dedicated[eNB_id].betaOffset_ACK_Index];//16;
@@ -7071,47 +7128,48 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
     ulsch->srs_active                              = use_srs;
     ulsch->bundling = 1-AckNackFBMode;
 
-    if (ulsch->harq_processes[harq_pid]->round == 0) {
-      if ((rnti >= cba_rnti) && (rnti < p_rnti))
-        ulsch->harq_processes[harq_pid]->status = CBA_ACTIVE;
-      else
-        ulsch->harq_processes[harq_pid]->status = ACTIVE;
-
-      ulsch->harq_processes[harq_pid]->rvidx = 0;
-      ulsch->harq_processes[harq_pid]->mcs         = mcs;
-
-      //      ulsch->harq_processes[harq_pid]->calibration_flag =0;
-      if (ulsch->harq_processes[harq_pid]->mcs < 29)
-        ulsch->harq_processes[harq_pid]->TBS         = TBStable[get_I_TBS_UL(ulsch->harq_processes[harq_pid]->mcs)][ulsch->harq_processes[harq_pid]->nb_rb-1];
-      else
-        LOG_E(PHY,"Fatal: mcs > 28!!! and round == 0\n");
+    if ((rnti >= cba_rnti) && (rnti < p_rnti))
+      ulsch->harq_processes[harq_pid]->status = CBA_ACTIVE;
+    else
+      ulsch->harq_processes[harq_pid]->status = ACTIVE;
 
-      /*
-      else if (ulsch->harq_processes[harq_pid]->mcs == 29) {
-      ulsch->harq_processes[harq_pid]->mcs = 4;
-      ulsch->harq_processes[harq_pid]->TBS         = TBStable[get_I_TBS_UL(ulsch->harq_processes[harq_pid]->mcs)][ulsch->harq_processes[harq_pid]->nb_rb-1];
-      // ulsch->harq_processes[harq_pid]->calibration_flag =1;
-      // printf("Auto-Calibration (UE): mcs %d, TBS %d, nb_rb %d\n",ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->TBS,ulsch->harq_processes[harq_pid]->nb_rb);
-      }*/
-      ulsch->harq_processes[harq_pid]->Msc_initial   = 12*ulsch->harq_processes[harq_pid]->nb_rb;
-      ulsch->harq_processes[harq_pid]->Nsymb_initial = ulsch->Nsymb_pusch;
-      ulsch->harq_processes[harq_pid]->round = 0;
+    ulsch->harq_processes[harq_pid]->rvidx = 0;
 
-      // a Ndi=1 automatically acknowledges previous PUSCH transmission
-      if (ue->ulsch_Msg3_active[eNB_id] == 1)
-        ue->ulsch_Msg3_active[eNB_id] = 0;
+    //      ulsch->harq_processes[harq_pid]->calibration_flag =0;
+    if (mcs < 29) {
+      ulsch->harq_processes[harq_pid]->mcs = mcs;
+      // ulsch->harq_processes[harq_pid]->round = 0;
     } else {
-      //      printf("Ndi = 0 : Setting RVidx from mcs %d\n",((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->mcs);
-      if (mcs>28) ulsch->harq_processes[harq_pid]->rvidx = mcs - 28;
-
-      //      ulsch->harq_processes[harq_pid]->round++;
+      ulsch->harq_processes[harq_pid]->rvidx = mcs - 28;
+      if (ulsch->harq_processes[harq_pid]->round == 0) {
+        LOG_W(PHY,"PUSCH::mcs = %d and DCI0::mcs(%d) > 28 and round == %d\n", ulsch->harq_processes[harq_pid]->mcs, mcs, ulsch->harq_processes[harq_pid]->round);
+      } else {
+        LOG_D(PHY,"PUSCH::mcs = %d and DCI0::mcs(%d) > 28 and round == %d\n", ulsch->harq_processes[harq_pid]->mcs, mcs, ulsch->harq_processes[harq_pid]->round);
+      }
+      //LOG_E(PHY,"Fatal: mcs(%d) > 28!!! and round == 0\n", mcs);
     }
+    ulsch->harq_processes[harq_pid]->TBS = TBStable[get_I_TBS_UL(ulsch->harq_processes[harq_pid]->mcs)][ulsch->harq_processes[harq_pid]->nb_rb-1];
 
-    LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d), nb_rb %d, first_rb %d, mcs %d, round %d, rv %d\n",
-          ue->Mod_id,harq_pid,proc->frame_rx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift,ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb,
-          ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->round,ulsch->harq_processes[harq_pid]->rvidx);
-
-    // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift;
+    /*
+       else if (ulsch->harq_processes[harq_pid]->mcs == 29) {
+       ulsch->harq_processes[harq_pid]->mcs = 4;
+       ulsch->harq_processes[harq_pid]->TBS         = TBStable[get_I_TBS_UL(ulsch->harq_processes[harq_pid]->mcs)][ulsch->harq_processes[harq_pid]->nb_rb-1];
+    // ulsch->harq_processes[harq_pid]->calibration_flag =1;
+    // printf("Auto-Calibration (UE): mcs %d, TBS %d, nb_rb %d\n",ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->TBS,ulsch->harq_processes[harq_pid]->nb_rb);
+    }*/
+    ulsch->harq_processes[harq_pid]->Msc_initial   = 12*ulsch->harq_processes[harq_pid]->nb_rb;
+    ulsch->harq_processes[harq_pid]->Nsymb_initial = ulsch->Nsymb_pusch;
+
+    // a Ndi=1 automatically acknowledges previous PUSCH transmission
+    if (ue->ulsch_Msg3_active[eNB_id] == 1)
+      ue->ulsch_Msg3_active[eNB_id] = 0;
+
+    LOG_D(PHY,"[UE %d][PUSCH %d] Frame %d, subframe %d : Programming PUSCH with n_DMRS2 %d (cshift %d), nb_rb %d, first_rb %d, mcs %d, round %d, rv %d, ulsch_ue_Msg3_active %d\n",
+        ue->Mod_id,harq_pid,
+        proc->frame_rx,subframe,ulsch->harq_processes[harq_pid]->n_DMRS2,cshift,ulsch->harq_processes[harq_pid]->nb_rb,ulsch->harq_processes[harq_pid]->first_rb,
+        ulsch->harq_processes[harq_pid]->mcs,ulsch->harq_processes[harq_pid]->round,ulsch->harq_processes[harq_pid]->rvidx, ue->ulsch_Msg3_active[eNB_id]);
+
+  // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift;
 
  #ifdef DEBUG_DCI 
     printf("Format 0 DCI : ulsch (ue): AbsSubframe %d.%d\n",proc->frame_rx,subframe);
diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h
index b6bbe09b3..8e17697ff 100644
--- a/openair1/PHY/LTE_TRANSPORT/defs.h
+++ b/openair1/PHY/LTE_TRANSPORT/defs.h
@@ -675,12 +675,16 @@ typedef struct {
 typedef struct {
   /// HARQ process id
   uint8_t harq_id;
-  /// ACK bits (after decoding)
+  /// ACK bits (after decoding) 0:NACK / 1:ACK / 2:DTX
   uint8_t ack;
   /// send status (for PUCCH)
   uint8_t send_harq_status;
   /// nCCE (for PUCCH)
   uint8_t nCCE;
+  /// DAI value detected from DCI1/1a/1b/1d/2/2a/2b/2c. 0xff indicates not touched
+  uint8_t vDAI_DL;
+  /// DAI value detected from DCI0/4. 0xff indicates not touched
+  uint8_t vDAI_UL;
 } harq_status_t;
 
 typedef struct {
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
index 4a80110b2..01512fde8 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_decoding.c
@@ -159,6 +159,7 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
                          LTE_DL_FRAME_PARMS *frame_parms,
                          LTE_UE_DLSCH_t *dlsch,
                          LTE_DL_UE_HARQ_t *harq_process,
+                         uint8_t frame,
                          uint8_t subframe,
                          uint8_t harq_pid,
                          uint8_t is_crnti,
@@ -241,6 +242,11 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
     return(dlsch->max_turbo_iterations);
   }
 
+  if (dlsch->harq_ack[subframe].ack != 2) {
+    LOG_W(PHY, "[UE %d] DLSCH @ SF%d : ACK bit is %d instead of DTX even before PDSCH is decoded!\n",
+        phy_vars_ue->Mod_id, subframe, dlsch->harq_ack[subframe].ack);
+  }
+
   if (llr8_flag == 0) {
     //#ifdef __AVX2__
 #if 0
@@ -609,10 +615,20 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
       //printf("CRC failed, segment %d\n",r);
       err_flag = 1;
     }
+  }
 
+  int32_t frame_rx_prev = frame;
+  int32_t subframe_rx_prev = subframe - 1;
+  if (subframe_rx_prev < 0) {
+    frame_rx_prev--;
+    subframe_rx_prev += 10;
   }
+  frame_rx_prev = frame_rx_prev%1024;
 
   if (err_flag == 1) {
+    LOG_D(PHY,"[UE %d] DLSCH: Setting NAK for SFN/SF %d/%d (pid %d, round %d, subframe %d)\n",
+        phy_vars_ue->Mod_id, frame_rx_prev, subframe_rx_prev, harq_pid, harq_process->round, subframe);
+
     dlsch->harq_ack[subframe].ack = 0;
     dlsch->harq_ack[subframe].harq_id = harq_pid;
     dlsch->harq_ack[subframe].send_harq_status = 1;
@@ -631,6 +647,9 @@ uint32_t  dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
 
     return((1+dlsch->max_turbo_iterations));
   } else {
+    LOG_D(PHY,"[UE %d] DLSCH: Setting ACK for SFN/SF %d/%d (pid %d, round %d, subframe %d)\n",
+        phy_vars_ue->Mod_id, frame_rx_prev, subframe_rx_prev, harq_pid, harq_process->round, subframe);
+
     harq_process->status = SCH_IDLE;
     harq_process->round  = 0;
     dlsch->harq_ack[subframe].ack = 1;
diff --git a/openair1/PHY/LTE_TRANSPORT/group_hopping.c b/openair1/PHY/LTE_TRANSPORT/group_hopping.c
index bbd908b34..9cbdfad39 100644
--- a/openair1/PHY/LTE_TRANSPORT/group_hopping.c
+++ b/openair1/PHY/LTE_TRANSPORT/group_hopping.c
@@ -118,7 +118,8 @@ void generate_nPRS(LTE_DL_FRAME_PARMS *frame_parms)
   uint16_t next = 0;
   uint8_t ns=0;
 
-  uint32_t fss_pusch = frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH;
+  uint32_t fss_pucch = (frame_parms->Nid_cell) % 30;
+  uint32_t fss_pusch = (fss_pucch + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH) % 30;
 
   x2 = (32*(uint32_t)(frame_parms->Nid_cell/30)) + fss_pusch;
 #ifdef DEBUG_GROUPHOP
diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c
index 989567ca3..36c4f6c55 100644
--- a/openair1/PHY/LTE_TRANSPORT/phich.c
+++ b/openair1/PHY/LTE_TRANSPORT/phich.c
@@ -1110,6 +1110,16 @@ void rx_phich(PHY_VARS_UE *ue,
     nseq_PHICH = ((ulsch->harq_processes[harq_pid]->first_rb/Ngroup_PHICH) +
                   ulsch->harq_processes[harq_pid]->n_DMRS)%(2*NSF_PHICH);
   } else {
+    LOG_D(PHY,"[UE  %d][PUSCH %d] Frame %d subframe %d PHICH RX %s\n",
+        ue->Mod_id,
+        harq_pid,
+        proc->frame_rx,
+        subframe,
+        (ulsch->harq_processes[harq_pid]->status==SCH_IDLE?   "SCH_IDLE"  :
+        (ulsch->harq_processes[harq_pid]->status==ACTIVE?     "ACTIVE"    :
+        (ulsch->harq_processes[harq_pid]->status==CBA_ACTIVE? "CBA_ACTIVE":
+        (ulsch->harq_processes[harq_pid]->status==DISABLED?   "DISABLED"  : "UNKNOWN")))));
+
     return;
   }
 
diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h
index 94aa21c71..4e8a5e62f 100644
--- a/openair1/PHY/LTE_TRANSPORT/proto.h
+++ b/openair1/PHY/LTE_TRANSPORT/proto.h
@@ -1138,6 +1138,7 @@ void dlsch_scale_channel(int32_t **dl_ch_estimates_ext,
     @param dlsch_llr Pointer to LLR values computed by dlsch_demodulation
     @param lte_frame_parms Pointer to frame descriptor
     @param dlsch Pointer to DLSCH descriptor
+    @param frame Frame number
     @param subframe Subframe number
     @param num_pdcch_symbols Number of PDCCH symbols
     @param is_crnti indicates if PDSCH belongs to a CRNTI (necessary for parallelizing decoding threads)
@@ -1149,6 +1150,7 @@ uint32_t dlsch_decoding(PHY_VARS_UE *phy_vars_ue,
                         LTE_DL_FRAME_PARMS *lte_frame_parms,
                         LTE_UE_DLSCH_t *dlsch,
                         LTE_DL_UE_HARQ_t *harq_process,
+                        uint8_t frame,
                         uint8_t subframe,
                         uint8_t harq_pid,
                         uint8_t is_crnti,
@@ -1499,7 +1501,8 @@ int generate_ue_dlsch_params_from_dci(int frame,
                                       uint16_t si_rnti,
                                       uint16_t ra_rnti,
                                       uint16_t p_rnti,
-                                      uint8_t beamforming_mode);
+                                      uint8_t beamforming_mode,
+                                      uint16_t tc_rnti);
 
 int32_t generate_eNB_dlsch_params_from_dci(int frame,
     uint8_t subframe,
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
index 4559aaa32..329fd90ea 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_coding.c
@@ -469,6 +469,16 @@ uint32_t ulsch_encoding(uint8_t *a,
   Q_ACK = Qprime * Q_m;
   Qprime_ACK = Qprime;
 
+  LOG_D(PHY,"UE (%x/%d) O_ACK %d, Mcs_initial %d, Nsymb_initial %d, beta_offset_harqack*8 %d, sum Kr %d, Qprime_ACK %d, Q_ACK %d\n",
+      rnti, harq_pid,
+      ulsch->harq_processes[harq_pid]->O_ACK,
+      ulsch->harq_processes[harq_pid]->Msc_initial,
+      ulsch->harq_processes[harq_pid]->Nsymb_initial,
+      ulsch->beta_offset_harqack_times8,
+      sumKr,
+      Qprime_ACK,
+      Q_ACK);
+
   // Compute Q_cqi, assume O>11, p. 26 36-212
   if (control_only_flag == 0) {
 
diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h
index 7a30bff6a..751de8b64 100644
--- a/openair1/PHY/impl_defs_lte.h
+++ b/openair1/PHY/impl_defs_lte.h
@@ -994,6 +994,8 @@ typedef struct {
   uint8_t num_pdcch_symbols;
   /// Allocated CRNTI for UE
   uint16_t crnti;
+  /// 1: the allocated crnti is Temporary C-RNTI / 0: otherwise
+  uint8_t crnti_is_temporary;
   /// Total number of PDU errors (diagnostic mode)
   uint32_t dci_errors;
   /// Total number of PDU received
diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h
index 2490a4035..ad6791035 100644
--- a/openair1/SCHED/defs.h
+++ b/openair1/SCHED/defs.h
@@ -300,6 +300,18 @@ uint8_t pdcch_alloc2ul_subframe(LTE_DL_FRAME_PARMS *frame_parms,uint8_t n);
 */
 uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,harq_status_t *harq_ack,uint8_t subframe,uint8_t *o_ACK);
 
+/*! \brief Reset ACK/NACK information
+  @param frame_parms Pointer to DL frame parameter descriptor
+  @param harq_ack Pointer to dlsch_ue harq_ack status descriptor
+  @param subframe Subframe for UE transmission (n in 36.213)
+  @param o_ACK Pointer to ACK/NAK payload for PUCCH/PUSCH
+  @returns status indicator for PUCCH/PUSCH transmission
+*/
+uint8_t reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
+                harq_status_t *harq_ack,
+                unsigned char subframe,
+                unsigned char *o_ACK);
+
 /*! \brief Compute UL ACK subframe from DL subframe. This is used to retrieve corresponding DLSCH HARQ pid at eNB upon reception of ACK/NAK information on PUCCH/PUSCH.  Derived from Table 10.1-1 in 36.213 (p. 69 in version 8.6)
   @param frame_parms Pointer to DL frame parameter descriptor
   @param subframe Subframe for UE transmission (n in 36.213)
@@ -366,6 +378,7 @@ subframe n-4 which is acknowledged in subframe n (for FDD) according to n1_pucch
 TDD, this routine computes the complex procedure described in Section 10.1 of 36.213 (through tables 10.1-1,10.1-2)
 @param phy_vars_ue Pointer to UE variables
 @param proc Pointer to RXn-TXnp4 proc information
+@param harq_ack Pointer to dlsch_ue harq_ack status descriptor
 @param eNB_id Index of eNB
 @param b Pointer to PUCCH payload (b[0],b[1])
 @param SR 1 means there's a positive SR in parallel to ACK/NAK
@@ -373,6 +386,7 @@ TDD, this routine computes the complex procedure described in Section 10.1 of 36
 */
 uint16_t get_n1_pucch(PHY_VARS_UE *phy_vars_ue,
 		      UE_rxtx_proc_t *proc,
+                      harq_status_t *harq_ack,
                       uint8_t eNB_id,
                       uint8_t *b,
                       uint8_t SR);
diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c
index 239a5e2f8..2aaab3013 100644
--- a/openair1/SCHED/phy_procedures_lte_common.c
+++ b/openair1/SCHED/phy_procedures_lte_common.c
@@ -320,85 +320,128 @@ unsigned char ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char s
 }
 
 // This function implements table 10.1-1 of 36-213, p. 69
-uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
+// return the number 'Nbundled'
+uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
                 harq_status_t *harq_ack,
                 unsigned char subframe,
-                unsigned char *o_ACK)
+                unsigned char *o_ACK,
+                uint8_t do_reset) // 1 to reset ACK/NACK status : 0 otherwise
 {
-
-
   uint8_t status=0;
-  uint8_t subframe_dl;
+  uint8_t subframe_ul=0xff, subframe_dl0=0xff, subframe_dl1=0xff;
 
   //  printf("get_ack: SF %d\n",subframe);
   if (frame_parms->frame_type == FDD) {
     if (subframe < 4)
-      subframe_dl = subframe + 6;
+      subframe_dl0 = subframe + 6;
     else
-      subframe_dl = subframe - 4;
+      subframe_dl0 = subframe - 4;
 
-    o_ACK[0] = harq_ack[subframe_dl].ack;
-    status = harq_ack[subframe_dl].send_harq_status;
+    o_ACK[0] = harq_ack[subframe_dl0].ack;
+    status = harq_ack[subframe_dl0].send_harq_status;
     //printf("get_ack: Getting ACK/NAK for PDSCH (subframe %d) => %d\n",subframe_dl,o_ACK[0]);
   } else {
     switch (frame_parms->tdd_config) {
     case 1:
-      if (subframe == 2) {  // ACK subframes 5 (forget 6)
-        o_ACK[0] = harq_ack[5].ack;
-        status = harq_ack[5].send_harq_status;
+      if (subframe == 2) {  // ACK subframes 5,6
+        subframe_ul  = 6;
+        subframe_dl0 = 5;
+        subframe_dl1 = 6;
       } else if (subframe == 3) { // ACK subframe 9
-        o_ACK[0] = harq_ack[9].ack;
-        status = harq_ack[9].send_harq_status;
+        subframe_ul  = 9;
+        subframe_dl0 = 9;
+        subframe_dl1 = 0xff;
       } else if (subframe == 4) { // nothing
-        status = 0;
-      } else if (subframe == 7) { // ACK subframes 0 (forget 1)
-        o_ACK[0] = harq_ack[0].ack;
-        status = harq_ack[0].send_harq_status;
+        subframe_ul  = 0xff;
+        subframe_dl0 = 0xff; // invalid subframe number indicates ACK/NACK is not needed
+        subframe_dl1 = 0xff;
+      } else if (subframe == 7) { // ACK subframes 0,1
+        subframe_ul  = 1;
+        subframe_dl0 = 0;
+        subframe_dl1 = 1;
       } else if (subframe == 8) { // ACK subframes 4
-        o_ACK[0] = harq_ack[4].ack;
-        status = harq_ack[4].send_harq_status;
+        subframe_ul  = 4;
+        subframe_dl0 = 4;
+        subframe_dl1 = 0xff;
       } else {
         LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe %d for tdd_config %d\n",
               subframe,frame_parms->tdd_config);
         return(0);
       }
 
+      // report ACK/NACK status
+      o_ACK[0] = 1;
+      status = 0;
+      if ((subframe_dl0 < 10) && (harq_ack[subframe_dl0].send_harq_status)) {
+        o_ACK[0] &= harq_ack[subframe_dl0].ack;
+        status = harq_ack[subframe_dl0].send_harq_status;
+      }
+      if ((subframe_dl1 < 10) && (harq_ack[subframe_dl1].send_harq_status)) {
+        o_ACK[0] &= harq_ack[subframe_dl1].ack;
+        status = harq_ack[subframe_dl1].send_harq_status;
+      }
+      // report status = Nbundled
+      if (!status) {
+        o_ACK[0] = 0;
+      } else {
+        if (harq_ack[subframe_ul].vDAI_UL < 0xff) {
+          status = harq_ack[subframe_ul].vDAI_UL;
+        }
+      }
+
+      if (!do_reset && (subframe_ul < 10)) {
+        if ((subframe_dl0 < 10) && (subframe_dl1 < 10)) {
+          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
+              subframe, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
+              subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL,
+              subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL,
+              o_ACK[0], status);
+        } else if (subframe_dl0 < 10) {
+          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
+              subframe, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
+              subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL,
+              o_ACK[0], status);
+        }else if (subframe_dl1 < 10) {
+          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
+              subframe, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
+              subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL,
+              o_ACK[0], status);
+        }
+      }
+
+      // reset ACK/NACK status
+      if (do_reset) {
+        LOG_D(PHY,"ul-sf#%d ACK/NACK status resetting @ dci0-sf#%d, dci1x/2x-sf#%d, dci1x/2x-sf#%d\n", subframe, subframe_ul, subframe_dl0, subframe_dl1);
+        if (subframe_ul < 10) {
+          harq_ack[subframe_ul].vDAI_UL = 0xff;
+        }
+        if (subframe_dl0 < 10) {
+          harq_ack[subframe_dl0].vDAI_DL = 0xff;
+          harq_ack[subframe_dl0].ack = 2;
+          harq_ack[subframe_dl0].send_harq_status = 0;
+        }
+        if (subframe_dl1 < 10) {
+          harq_ack[subframe_dl1].vDAI_DL = 0xff;
+          harq_ack[subframe_dl1].ack = 2;
+          harq_ack[subframe_dl1].send_harq_status = 0;
+        }
+      }
+
       break;
 
     case 3:
       if (subframe == 2) {  // ACK subframes 5 and 6
-        if (harq_ack[5].send_harq_status == 1) {
-          o_ACK[0] = harq_ack[5].ack;
-
-          if (harq_ack[6].send_harq_status == 1)
-            o_ACK[1] = harq_ack[6].ack;
-        } else if (harq_ack[6].send_harq_status == 1)
-          o_ACK[0] = harq_ack[6].ack;
-
-        status = harq_ack[5].send_harq_status + (harq_ack[6].send_harq_status<<1);
+        subframe_dl0 = 5;
+        subframe_dl1 = 6;
         //printf("Subframe 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status);
       } else if (subframe == 3) { // ACK subframes 7 and 8
-        if (harq_ack[7].send_harq_status == 1) {
-          o_ACK[0] = harq_ack[7].ack;
-
-          if (harq_ack[8].send_harq_status == 1)
-            o_ACK[1] = harq_ack[8].ack;
-        } else if (harq_ack[8].send_harq_status == 1)
-          o_ACK[0] = harq_ack[8].ack;
-
-        status = harq_ack[7].send_harq_status + (harq_ack[8].send_harq_status<<1);
+        subframe_dl0 = 7;
+        subframe_dl1 = 8;
         //printf("Subframe 3, TDD config 3: harq_ack[7] = %d,harq_ack[8] = %d\n",harq_ack[7].ack,harq_ack[8].ack);
         //printf("status %d : o_ACK (%d,%d)\n", status,o_ACK[0],o_ACK[1]);
       } else if (subframe == 4) { // ACK subframes 9 and 0
-        if (harq_ack[9].send_harq_status == 1) {
-          o_ACK[0] = harq_ack[9].ack;
-
-          if (harq_ack[0].send_harq_status == 1)
-            o_ACK[1] = harq_ack[0].ack;
-        } else if (harq_ack[0].send_harq_status == 1)
-          o_ACK[0] = harq_ack[0].ack;
-
-        status = harq_ack[9].send_harq_status + (harq_ack[0].send_harq_status<<1);
+        subframe_dl0 = 9;
+        subframe_dl1 = 0;
         //printf("Subframe 4, TDD config 3: harq_ack[9] = %d,harq_ack[0] = %d\n",harq_ack[9].ack,harq_ack[0].ack);
       } else {
         LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe %d for tdd_config %d\n",
@@ -406,6 +449,25 @@ uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
         return(0);
       }
 
+      // report ACK/NACK status
+      if (harq_ack[subframe_dl0].send_harq_status == 1) {
+        o_ACK[0] = harq_ack[subframe_dl0].ack;
+
+        if (harq_ack[subframe_dl1].send_harq_status == 1)
+          o_ACK[1] = harq_ack[subframe_dl1].ack;
+      } else if (harq_ack[subframe_dl1].send_harq_status == 1)
+        o_ACK[0] = harq_ack[subframe_dl1].ack;
+
+      status = harq_ack[subframe_dl0].send_harq_status + (harq_ack[subframe_dl1].send_harq_status<<1);
+
+      if (do_reset) {
+        // reset ACK/NACK status
+        harq_ack[subframe_dl0].ack = 2;
+        harq_ack[subframe_dl1].ack = 2;
+        harq_ack[subframe_dl0].send_harq_status = 0;
+        harq_ack[subframe_dl1].send_harq_status = 0;
+      }
+
       break;
 
     }
@@ -416,6 +478,24 @@ uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
   return(status);
 }
 
+uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
+                harq_status_t *harq_ack,
+                unsigned char subframe,
+                unsigned char *o_ACK)
+{
+  return get_reset_ack(frame_parms, harq_ack, subframe, o_ACK, 0);
+}
+
+uint8_t reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
+                harq_status_t *harq_ack,
+                unsigned char subframe,
+                unsigned char *o_ACK)
+{
+  return get_reset_ack(frame_parms, harq_ack, subframe, o_ACK, 1);
+}
+
+
+
 uint8_t Np6[4]= {0,1,3,5};
 uint8_t Np15[4]= {0,3,8,13};
 uint8_t Np25[4]= {0,5,13,22};
diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c
index 1c6aa6b20..27ef6119e 100644
--- a/openair1/SCHED/phy_procedures_lte_ue.c
+++ b/openair1/SCHED/phy_procedures_lte_ue.c
@@ -266,7 +266,7 @@ void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
   // This flushes ALL DLSCH and ULSCH harq buffers of ALL connected eNBs...add the eNB_index later
   // for more flexibility
 
-  uint8_t i,j,k;
+  uint8_t i,j,k,s;
   PHY_VARS_UE *ue = PHY_vars_UE_g[Mod_id][CC_id];
 
   //[NUMBER_OF_CONNECTED_eNB_MAX][2];
@@ -276,6 +276,13 @@ void phy_reset_ue(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
       if(ue->dlsch[i][j]) {
         for(k=0; k<NUMBER_OF_HARQ_PID_MAX && ue->dlsch[i][j]->harq_processes[k]; k++) {
           ue->dlsch[i][j]->harq_processes[k]->status = SCH_IDLE;
+          for (s=0; s<10; s++) {
+            // reset ACK/NACK bit to DTX for all subframes s = 0..9
+            ue->dlsch[i][j]->harq_ack[s].ack = 2;
+            ue->dlsch[i][j]->harq_ack[s].send_harq_status = 0;
+            ue->dlsch[i][j]->harq_ack[s].vDAI_UL = 0xff;
+            ue->dlsch[i][j]->harq_ack[s].vDAI_DL = 0xff;
+          }
         }
       }
     }
@@ -301,7 +308,9 @@ void ra_failed(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
 
   // if contention resolution fails, go back to PRACH
   PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PRACH;
-  LOG_E(PHY,"[UE %d] Random-access procedure fails, going back to PRACH, setting SIStatus = 0 and State RRC_IDLE\n",Mod_id);
+  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[eNB_index]->crnti_is_temporary = 0;
+  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[eNB_index]->crnti = 0;
+  LOG_E(PHY,"[UE %d] Random-access procedure fails, going back to PRACH, setting SIStatus = 0, discard temporary C-RNTI and State RRC_IDLE\n",Mod_id);
   //mac_xface->macphy_exit("");
 }
 
@@ -310,8 +319,9 @@ void ra_succeeded(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index)
 
   int i;
 
-  LOG_I(PHY,"[UE %d][RAPROC] Random-access procedure succeeded\n",Mod_id);
+  LOG_I(PHY,"[UE %d][RAPROC] Random-access procedure succeeded. Set C-RNTI = Temporary C-RNTI\n",Mod_id);
 
+  PHY_vars_UE_g[Mod_id][CC_id]->pdcch_vars[eNB_index]->crnti_is_temporary = 0;
   PHY_vars_UE_g[Mod_id][CC_id]->ulsch_Msg3_active[eNB_index] = 0;
   PHY_vars_UE_g[Mod_id][CC_id]->UE_mode[eNB_index] = PUSCH;
 
@@ -728,6 +738,7 @@ void get_cqipmiri_params(PHY_VARS_UE *ue,uint8_t eNB_id)
 
 uint16_t get_n1_pucch(PHY_VARS_UE *ue,
 		      UE_rxtx_proc_t *proc,
+                      harq_status_t *harq_ack,
                       uint8_t eNB_id,
                       uint8_t *b,
                       uint8_t SR)
@@ -737,7 +748,8 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue,
   uint8_t nCCE0,nCCE1,harq_ack1,harq_ack0;
   ANFBmode_t bundling_flag;
   uint16_t n1_pucch0=0,n1_pucch1=0;
-  int subframe_offset;
+  static uint8_t candidate_dl[9]; // which downlink(s) the current ACK/NACK is associating to
+  uint8_t last_dl=0xff; // the last downlink with valid DL-DCI. for calculating the PUCCH resource index
   int sf;
   int M;
   // clear this, important for case where n1_pucch selection is not used
@@ -775,41 +787,71 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue,
       M=1;
 
       // This is the offset for a particular subframe (2,3,4) => (0,2,4)
-      if (subframe == 2) {  // ACK subframes 5 (forget 6)
-        subframe_offset = 5;
+      if (subframe == 2) {  // ACK subframes 5,6
+        candidate_dl[0] = 6;
+        candidate_dl[1] = 5;
         M=2;
       } else if (subframe == 3) { // ACK subframe 9
-        subframe_offset = 9;
-      } else if (subframe == 7) { // ACK subframes 0 (forget 1)
-        subframe_offset = 0;
+        candidate_dl[0] = 9;
+      } else if (subframe == 7) { // ACK subframes 0,1
+        candidate_dl[0] = 1;
+        candidate_dl[1] = 0;
         M=2;
       } else if (subframe == 8) { // ACK subframes 4
-        subframe_offset = 4;
+        candidate_dl[0] = 4;
       } else {
         LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n",
               ue->Mod_id,proc->frame_tx,subframe,frame_parms->tdd_config);
         return(0);
       }
 
+      // checking which downlink candidate is the last downlink with valid DL-DCI
+      int k;
+      for (k=0;k<M;k++) {
+        if (harq_ack[candidate_dl[k]].send_harq_status>0) {
+          last_dl = candidate_dl[k];
+          break;
+        }
+      }
+      if (last_dl >= 10) {
+        LOG_E(PHY,"[UE%d] : Frame %d phy_procedures_lte.c: get_n1pucch, illegal subframe %d for tdd_config %d\n",
+              ue->Mod_id,proc->frame_tx,last_dl,frame_parms->tdd_config);
+        return (0);
+      }
+
+      LOG_D(PHY,"SFN/SF %d/%d calculating n1_pucch0 from last_dl=%d\n",
+          proc->frame_tx%1024,
+          proc->subframe_tx,
+          last_dl);
 
       // i=0
-      nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[subframe_offset];
+      nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[last_dl];
       n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
 
-      // set ACK/NAK to values if not DTX
-      if (ue->dlsch[eNB_id][0]->harq_ack[subframe_offset].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
-        harq_ack0 = ue->dlsch[eNB_id][0]->harq_ack[subframe_offset].ack;
-
+      harq_ack0 = b[0];
 
       if (harq_ack0!=2) {  // DTX
-        if (SR == 0) {  // last paragraph pg 68 from 36.213 (v8.6), m=0
-          b[0]=(M==2) ? 1-harq_ack0 : harq_ack0;
-          b[1]=harq_ack0;   // in case we use pucch format 1b (subframes 2,7)
+        if (frame_parms->frame_type == FDD ) {
+          if (SR == 0) {  // last paragraph pg 68 from 36.213 (v8.6), m=0
+            b[0]=(M==2) ? 1-harq_ack0 : harq_ack0;
+            b[1]=harq_ack0;   // in case we use pucch format 1b (subframes 2,7)
           ue->pucch_sel[subframe] = 0;
-          return(n1_pucch0);
-        } else { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213)
-          b[0]=harq_ack0;
+            return(n1_pucch0);
+          } else { // SR and only 0 or 1 ACKs (first 2 entries in Table 7.3-1 of 36.213)
+            b[0]=harq_ack0;
           return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
+          }
+        } else {
+          if (SR == 0) {
+            b[0] = harq_ack0;
+            b[1] = harq_ack0;
+            ue->pucch_sel[subframe] = 0;
+            return(n1_pucch0);
+          } else {
+            b[0] = harq_ack0;
+            b[1] = harq_ack0;
+            return(ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex);
+          }
         }
       }
 
@@ -823,20 +865,20 @@ uint16_t get_n1_pucch(PHY_VARS_UE *ue,
       harq_ack1 = 2; // DTX
       harq_ack0 = 2; // DTX
       // This is the offset for a particular subframe (2,3,4) => (0,2,4)
-      subframe_offset = (subframe-2)<<1;
+      last_dl = (subframe-2)<<1;
       // i=0
-      nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[5+subframe_offset];
+      nCCE0 = ue->pdcch_vars[eNB_id]->nCCE[5+last_dl];
       n1_pucch0 = get_Np(frame_parms->N_RB_DL,nCCE0,0) + nCCE0+ frame_parms->pucch_config_common.n1PUCCH_AN;
       // i=1
-      nCCE1 = ue->pdcch_vars[eNB_id]->nCCE[(6+subframe_offset)%10];
+      nCCE1 = ue->pdcch_vars[eNB_id]->nCCE[(6+last_dl)%10];
       n1_pucch1 = get_Np(frame_parms->N_RB_DL,nCCE1,1) + nCCE1 + frame_parms->pucch_config_common.n1PUCCH_AN;
 
       // set ACK/NAK to values if not DTX
-      if (ue->dlsch[eNB_id][0]->harq_ack[(6+subframe_offset)%10].send_harq_status>0)  // n-6 // subframe 6 is to be ACK/NAKed
-        harq_ack1 = ue->dlsch[eNB_id][0]->harq_ack[(6+subframe_offset)%10].ack;
+      if (ue->dlsch[eNB_id][0]->harq_ack[(6+last_dl)%10].send_harq_status>0)  // n-6 // subframe 6 is to be ACK/NAKed
+        harq_ack1 = ue->dlsch[eNB_id][0]->harq_ack[(6+last_dl)%10].ack;
 
-      if (ue->dlsch[eNB_id][0]->harq_ack[5+subframe_offset].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
-        harq_ack0 = ue->dlsch[eNB_id][0]->harq_ack[5+subframe_offset].ack;
+      if (ue->dlsch[eNB_id][0]->harq_ack[5+last_dl].send_harq_status>0)  // n-6 // subframe 5 is to be ACK/NAKed
+        harq_ack0 = ue->dlsch[eNB_id][0]->harq_ack[5+last_dl].ack;
 
 
       if (harq_ack1!=2) { // n-6 // subframe 6,8,0 and maybe 5,7,9 is to be ACK/NAKed
@@ -1194,7 +1236,6 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
   int Mod_id = ue->Mod_id;
   int CC_id = ue->CC_id;
   uint8_t Msg3_flag=0;
-  uint8_t ack_status=0;
   uint16_t first_rb, nb_rb;
   unsigned int input_buffer_length;
   int i;
@@ -1202,6 +1243,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
   int tx_amp;
   uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32)));
   uint8_t access_mode;
+  uint8_t Nbundled=0;
+  uint8_t ack_status=0;
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_ULSCH_UESPEC,VCD_FUNCTION_IN);
 
@@ -1245,6 +1288,49 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
     }
   }
   
+  if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) {
+
+    uint8_t isBad = 0;
+    if (ue->frame_parms.N_RB_UL <= ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb) {
+      LOG_D(PHY,"Invalid PUSCH first_RB=%d for N_RB_UL=%d\n",
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb,
+          ue->frame_parms.N_RB_UL);
+      isBad = 1;
+    }
+    if (ue->frame_parms.N_RB_UL < ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb) {
+      LOG_D(PHY,"Invalid PUSCH num_RB=%d for N_RB_UL=%d\n",
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb,
+          ue->frame_parms.N_RB_UL);
+      isBad = 1;
+    }
+    if (0 > ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb) {
+      LOG_D(PHY,"Invalid PUSCH first_RB=%d\n",
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb);
+      isBad = 1;
+    }
+    if (0 >= ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb) {
+      LOG_D(PHY,"Invalid PUSCH num_RB=%d\n",
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb);
+      isBad = 1;
+    }
+    if (ue->frame_parms.N_RB_UL < (ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb + ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb)) {
+      LOG_D(PHY,"Invalid PUSCH num_RB=%d + first_RB=%d for N_RB_UL=%d\n",
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb,
+          ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb,
+          ue->frame_parms.N_RB_UL);
+      isBad = 1;
+    }
+    if ((0 > ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx) ||
+        (3 < ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx)) {
+      LOG_D(PHY,"Invalid PUSCH RV index=%d\n", ue->ulsch[eNB_id]->harq_processes[harq_pid]->rvidx);
+      isBad = 1;
+    }
+
+    if (isBad) {
+      LOG_D(PHY,"Skip PUSCH generation!\n");
+      ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag = 0;
+    }
+  }
   if (ue->ulsch[eNB_id]->harq_processes[harq_pid]->subframe_scheduling_flag == 1) {
     
     ue->generate_ul_signal[eNB_id] = 1;
@@ -1263,7 +1349,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
 			 ue->dlsch[eNB_id][0]->harq_ack,
 			 subframe_tx,
 			 ue->ulsch[eNB_id]->o_ACK);
-    
+    Nbundled = ack_status;
     first_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->first_rb;
     nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb;
     
@@ -1292,8 +1378,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
     }
 
 #ifdef DEBUG_PHY_PROC
-    LOG_D(PHY,
-	  "[UE  %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d\n",
+        LOG_D(PHY,
+              "[UE  %d][PUSCH %d] Frame %d subframe %d Generating PUSCH : first_rb %d, nb_rb %d, round %d, mcs %d, rv %d, cyclic_shift %d (cyclic_shift_common %d,n_DMRS2 %d,n_PRS %d), ACK (%d,%d), O_ACK %d, bundling %d\n",
 	  Mod_id,harq_pid,frame_tx,subframe_tx,
 	  first_rb,nb_rb,
 	  ue->ulsch[eNB_id]->harq_processes[harq_pid]->round,
@@ -1306,7 +1392,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
 	  ue->ulsch[eNB_id]->harq_processes[harq_pid]->n_DMRS2,
 	  ue->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe_tx<<1],
 	  ue->ulsch[eNB_id]->o_ACK[0],ue->ulsch[eNB_id]->o_ACK[1],
-	  ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK);
+	  ue->ulsch[eNB_id]->harq_processes[harq_pid]->O_ACK,
+	  ue->ulsch[eNB_id]->bundling);
 #endif
     
     
@@ -1408,8 +1495,8 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
 			   ue,
 			   harq_pid,
 			   eNB_id,
-			   ue->transmission_mode[eNB_id],0,
-			   0)!=0) {  //  Nbundled, to be updated!!!!
+         ue->transmission_mode[eNB_id],0,
+         Nbundled)!=0) {
 	  LOG_E(PHY,"ulsch_coding.c: FATAL ERROR: returning\n");
 	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT);
 	  stop_meas(&ue->phy_proc_tx);
@@ -1570,6 +1657,7 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
   int CC_id = ue->CC_id;
   int tx_amp;
   int8_t Po_PUCCH;
+  uint8_t ack_status=0;
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PUCCH,VCD_FUNCTION_IN);
   
@@ -1633,18 +1721,24 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
     SR_payload=0;
   }
         	  
-  if (get_ack(&ue->frame_parms,
-	      ue->dlsch[eNB_id][0]->harq_ack,
-	      subframe_tx,pucch_ack_payload) > 0) {
+  ack_status = get_ack(&ue->frame_parms,
+      ue->dlsch[eNB_id][0]->harq_ack,
+      subframe_tx,pucch_ack_payload);
+  if (ack_status > 0) {
     // we need to transmit ACK/NAK in this subframe
 	    
     ue->generate_ul_signal[eNB_id] = 1;
 	    
+    if ((frame_parms->frame_type == TDD) && (SR_payload>0)) {
+      format = pucch_format1b;
+    }
+
     n1_pucch = get_n1_pucch(ue,
-			    proc,
-			    eNB_id,
-			    pucch_ack_payload,
-			    SR_payload);
+        proc,
+        ue->dlsch[eNB_id][0]->harq_ack,
+        eNB_id,
+        pucch_ack_payload,
+        SR_payload);
 	    
     if (ue->mac_enabled == 1) {
       Po_PUCCH = pucch_power_cntl(ue,proc,subframe_tx,eNB_id,format);
@@ -1665,21 +1759,25 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 #endif
 	    
     if (SR_payload>0) {
-      LOG_D(PHY,"[UE  %d][SR %x] Frame %d subframe %d Generating PUCCH 1a/1b payload %d,%d (with SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH, amp %d\n",
+      LOG_D(PHY,"[UE  %d][SR %x] Frame %d subframe %d Generating PUCCH %s payload %d,%d (with SR for PUSCH), an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, Po_PUCCH, amp %d\n",
 	    Mod_id,
 	    ue->dlsch[eNB_id][0]->rnti,
-		frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
-	    isShortenPucch,
-	    frame_tx, subframe_tx,
+                  frame_tx % 1024, subframe_tx,
+                  (format == pucch_format1a? "1a": (
+                   format == pucch_format1b? "1b" : "??")),               
 	    pucch_ack_payload[0],pucch_ack_payload[1],
+		frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
+	    isShortenPucch,    	    
 	    ue->scheduling_request_config[eNB_id].sr_PUCCH_ResourceIndex,
 	    Po_PUCCH,
 	    tx_amp);
     } else {
-      LOG_D(PHY,"[UE  %d][PDSCH %x] Frame %d subframe %d Generating PUCCH 1a/1b, an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n",
+      LOG_D(PHY,"[UE  %d][PDSCH %x] Frame %d subframe %d Generating PUCCH %s, an_srs_simultanous %d, shorten_pucch %d, n1_pucch %d, b[0]=%d,b[1]=%d (SR_Payload %d), Po_PUCCH %d, amp %d\n",
 	    Mod_id,
 	    ue->dlsch[eNB_id][0]->rnti,
-	    frame_tx, subframe_tx,
+	                frame_tx, subframe_tx,
+                  (format == pucch_format1a? "1a": (
+                   format == pucch_format1b? "1b" : "??")),
 		frame_parms->soundingrs_ul_config_common.ackNackSRS_SimultaneousTransmission,
 	    isShortenPucch,
 	    n1_pucch,pucch_ack_payload[0],pucch_ack_payload[1],SR_payload,
@@ -1879,7 +1977,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui
   int subframe_tx = proc->subframe_tx;
   int frame_tx = proc->frame_tx;
   unsigned int aa;
-
+  
 
 
 
@@ -2014,6 +2112,17 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui
     ue->generate_prach=0;
   }
     
+  // reset DL ACK/NACK status
+  reset_ack(&ue->frame_parms,
+             ue->dlsch[eNB_id][0]->harq_ack,
+             subframe_tx,
+             ue->ulsch[eNB_id]->o_ACK);
+
+  reset_ack(&ue->frame_parms,
+             ue->dlsch_SI[eNB_id]->harq_ack,
+             subframe_tx,
+             ue->ulsch[eNB_id]->o_ACK);
+
       
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT);
   stop_meas(&ue->phy_proc_tx);
@@ -2600,7 +2709,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 					     SI_RNTI,
 					     0,
 					     P_RNTI,
-					     ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0)) {
+					     ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id],
+					     ue->pdcch_vars[eNB_id]->crnti_is_temporary? ue->pdcch_vars[eNB_id]->crnti: 0)==0)) {
 
 	ue->dlsch_received[eNB_id]++;
 	
@@ -2644,7 +2754,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 					    SI_RNTI,
 					    0,
 					    P_RNTI,
-					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
+					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id],
+              0)==0) {
 
 	ue->dlsch_SI_received[eNB_id]++;
  
@@ -2674,7 +2785,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 					    SI_RNTI,
 					    0,
 					    P_RNTI,
-					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
+					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id],
+                                            0)==0) {
 
 	ue->dlsch_p_received[eNB_id]++;
  
@@ -2709,7 +2821,8 @@ int ue_pdcch_procedures(uint8_t eNB_id,PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint
 					    SI_RNTI,
 					    ue->prach_resources[eNB_id]->ra_RNTI,
 					    P_RNTI,
-					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id])==0) {
+					    ue->transmission_mode[eNB_id]<7?0:ue->transmission_mode[eNB_id],
+                                            0)==0) {
 
 	ue->dlsch_ra_received[eNB_id]++;
 
@@ -2871,6 +2984,7 @@ void ue_pmch_procedures(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc,int eNB_id,int abs
 			     &ue->frame_parms,
 			     ue->dlsch_MCH[0],
 			     ue->dlsch_MCH[0]->harq_processes[0],
+			     frame_rx,
 			     subframe_rx,
 			     0,
 			     0,1);
@@ -3046,6 +3160,9 @@ void process_rar(PHY_VARS_UE *ue, UE_rxtx_proc_t *proc, int eNB_id, runmode_t mo
 	      ue->pdcch_vars[eNB_id]->crnti,
 	      timing_advance);
 	      
+  // remember this c-rnti is still a tc-rnti
+  ue->pdcch_vars[eNB_id]->crnti_is_temporary = 1;	     
+	      
 	//timing_advance = 0;
 	process_timing_advance_rar(ue,proc,timing_advance);
 	      
@@ -3174,6 +3291,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 			   &ue->frame_parms,
 			   dlsch0,
 			   dlsch0->harq_processes[harq_pid],
+			   frame_rx,
 			   subframe_rx,
 			   harq_pid,
 			   pdsch==PDSCH?1:0,
@@ -3233,6 +3351,7 @@ void ue_dlsch_procedures(PHY_VARS_UE *ue,
 	  mac_xface->ue_send_sdu(ue->Mod_id,
 				 CC_id,
 				 frame_rx,
+         subframe_rx,
 				 dlsch0->harq_processes[dlsch0->current_harq_pid]->b,
 				 dlsch0->harq_processes[dlsch0->current_harq_pid]->TBS>>3,
 				 eNB_id);
@@ -3308,7 +3427,7 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
   int frame_rx = proc->frame_rx;
   int subframe_rx = proc->subframe_rx;
 
-
+  
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN);
 
@@ -3528,10 +3647,6 @@ int phy_procedures_UE_RX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC, VCD_FUNCTION_OUT);
 
   }
-  else {
-    //  printf("PDSCH inactive in subframe %d\n",subframe_rx-1);
-    ue->dlsch[eNB_id][0]->harq_ack[subframe_rx].send_harq_status = 0;
-  }
 
   // do procedures for SI-RNTI
   if ((ue->dlsch_SI[eNB_id]) && (ue->dlsch_SI[eNB_id]->active == 1)) {
diff --git a/openair1/SIMULATION/LTE_PHY/mbmssim.c b/openair1/SIMULATION/LTE_PHY/mbmssim.c
index 7849dec1a..2f8fda770 100644
--- a/openair1/SIMULATION/LTE_PHY/mbmssim.c
+++ b/openair1/SIMULATION/LTE_PHY/mbmssim.c
@@ -492,6 +492,7 @@ int main(int argc, char **argv)
                            &UE->frame_parms,
                            UE->dlsch_MCH[0],
                            UE->dlsch_MCH[0]->harq_processes[0],
+                           frame,
                            subframe,
                            0,0,0);
 
diff --git a/openair1/SIMULATION/LTE_PHY/syncsim.c b/openair1/SIMULATION/LTE_PHY/syncsim.c
index 7e94122e6..b18cd7886 100644
--- a/openair1/SIMULATION/LTE_PHY/syncsim.c
+++ b/openair1/SIMULATION/LTE_PHY/syncsim.c
@@ -1651,6 +1651,7 @@ int main(int argc, char **argv)
                                    PHY_vars_UE[UE_idx]->lte_ue_pdsch_vars[0]->llr[0],
                                    &PHY_vars_UE[UE_idx]->lte_frame_parms,
                                    PHY_vars_UE[UE_idx]->dlsch_ue[0][0],
+                                   frame,
                                    subframe,
                                    0,
                                    PHY_vars_UE[UE_idx]->lte_ue_pdcch_vars[0]->num_pdcch_symbols);
diff --git a/openair2/LAYER2/MAC/proto.h b/openair2/LAYER2/MAC/proto.h
index 9454f3da8..5da2367ce 100644
--- a/openair2/LAYER2/MAC/proto.h
+++ b/openair2/LAYER2/MAC/proto.h
@@ -402,7 +402,7 @@ void ue_decode_si(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_in
 void ue_decode_p(module_id_t module_idP, int CC_id,frame_t frame, uint8_t CH_index, void *pdu, uint16_t len);
 
 
-void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frame, uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index);
+void ue_send_sdu(module_id_t module_idP, uint8_t CC_id,frame_t frame, sub_frame_t subframe, uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index);
 
 
 #ifdef Rel10
diff --git a/openair2/LAYER2/MAC/ue_procedures.c b/openair2/LAYER2/MAC/ue_procedures.c
index cdac22c48..85100d14a 100644
--- a/openair2/LAYER2/MAC/ue_procedures.c
+++ b/openair2/LAYER2/MAC/ue_procedures.c
@@ -333,6 +333,7 @@ ue_send_sdu(
   module_id_t module_idP,
 	    uint8_t CC_id,
 	    frame_t frameP,
+        sub_frame_t subframeP,
 	    uint8_t* sdu,
 	    uint16_t sdu_len,
   uint8_t eNB_index
@@ -451,7 +452,7 @@ ue_send_sdu(
 #endif
       mac_rrc_data_ind(module_idP,
                        CC_id,
-                       frameP,0, // unknown subframe
+                       frameP,subframeP,
                        UE_mac_inst[module_idP].crnti,
                        CCCH,
                        (uint8_t*)payload_ptr,
diff --git a/openair2/PHY_INTERFACE/defs.h b/openair2/PHY_INTERFACE/defs.h
index 156b9091b..497325205 100644
--- a/openair2/PHY_INTERFACE/defs.h
+++ b/openair2/PHY_INTERFACE/defs.h
@@ -152,7 +152,7 @@ typedef struct {
   void (*ue_decode_p)(module_id_t Mod_id,int CC_id,frame_t frameP, uint8_t CH_index, void *pdu, uint16_t len);
 
   /// Send a received DLSCH sdu to MAC
-  void (*ue_send_sdu)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index);
+  void (*ue_send_sdu)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,sub_frame_t subframe,uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index);
 
 #ifdef Rel10
   /// Send a received MCH sdu to MAC
-- 
GitLab