From 3b7960d8516395b2a481028565d2370440f6bcf9 Mon Sep 17 00:00:00 2001
From: Calvin <kai-hsiang.hsu@eurecom.fr>
Date: Fri, 25 May 2018 16:16:22 +0200
Subject: [PATCH] 1. nr_rrc_mac_config_req_ue 2. copy IF module from eNB to new
 folder

---
 openair2/LAYER2/NR_MAC_UE/config_ue.c         |  67 +-
 openair2/LAYER2/NR_MAC_UE/defs.h              |  23 +
 openair2/LAYER2/NR_MAC_UE/main_ue_nr.c        |   6 +
 openair2/LAYER2/NR_MAC_UE/vars.c              |  34 +
 openair2/NR_UE_PHY_INTERFACE/IF_Module.c      | 647 ++++++++++++++++++
 openair2/NR_UE_PHY_INTERFACE/IF_Module.h      | 142 ++++
 openair2/NR_UE_PHY_INTERFACE/defs.h           | 373 ++++++++++
 openair2/NR_UE_PHY_INTERFACE/extern.h         |  27 +
 .../NR_UE_PHY_INTERFACE/mac_phy_primitives.c  | 283 ++++++++
 .../NR_UE_PHY_INTERFACE/mac_phy_primitives.h  | 232 +++++++
 openair2/NR_UE_PHY_INTERFACE/vars.h           |  44 ++
 11 files changed, 1867 insertions(+), 11 deletions(-)
 create mode 100644 openair2/LAYER2/NR_MAC_UE/vars.c
 create mode 100644 openair2/NR_UE_PHY_INTERFACE/IF_Module.c
 create mode 100644 openair2/NR_UE_PHY_INTERFACE/IF_Module.h
 create mode 100644 openair2/NR_UE_PHY_INTERFACE/defs.h
 create mode 100644 openair2/NR_UE_PHY_INTERFACE/extern.h
 create mode 100644 openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c
 create mode 100644 openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h
 create mode 100644 openair2/NR_UE_PHY_INTERFACE/vars.h

diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index 6e75276264..c699ad5232 100644
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -39,43 +39,88 @@ nr_rrc_mac_config_req_ue(
     PhysicalCellGroupConfig_t *phy_cell_group_config,
     SpCellConfig_t *spcell_config){
 
+    NR_UE_MAC_INST *mac = get_mac_inst(Mod_idP);
+
+    ServingCellConfig_t *serving_cell_config = spcell_config->spCellConfigDedicated;
 //  TODO do something FAPI-like P5 L1/L2 config interface in config_si, config_mib, etc.
 
     if(mac_cell_group_config != (MAC_CellGroupConfig_t *)0){
         if(mac_cell_group_config->drx_Config != (drx_Config_t *)0 ){
-            NR_UE_mac_inst->drx_Config = mac_cell_group_config->drx_Config;
+            mac->drx_Config = mac_cell_group_config->drx_Config;
         }
 
         if(mac_cell_group_config->SchedulingRequestConfig != (SchedulingRequestConfig_t *)0 ){
-            NR_UE_mac_inst->SchedulingRequestConfig = mac_cell_group_config->SchedulingRequestConfig;
+            mac->SchedulingRequestConfig = mac_cell_group_config->SchedulingRequestConfig;
         }
 
         if(mac_cell_group_config->BSR_Config != (BSR_Config_t *)0 ){
-            NR_UE_mac_inst->BSR_Config = mac_cell_group_config->BSR_Config;
+            mac->BSR_Config = mac_cell_group_config->BSR_Config;
         }
 
         if(mac_cell_group_config->TAG_Config != (TAG_Config_t *)0 ){
-            NR_UE_mac_inst->TAG_Config = mac_cell_group_config->TAG_Config;
+            mac->TAG_Config = mac_cell_group_config->TAG_Config;
         }
 
         if(mac_cell_group_config->phr_Config != (phr_Config_t *)0 ){
-            NR_UE_mac_inst->phr_Config = mac_cell_group_config->phr_Config;
+            mac->phr_Config = mac_cell_group_config->phr_Config;
         }
 
         if(mac_cell_group_config->cs_RNTI != (cs_RNTI_t *)0 ){
-            NR_UE_mac_inst->cs_RNTI = mac_cell_group_config->cs_RNTI;
+            mac->cs_RNTI = mac_cell_group_config->cs_RNTI;
         }
-
-
     }
     
     if(phy_cell_group_config != (PhysicalCellGroupConfig_t *)0){
-    
+        config_phy(phy_cell_group_config, NULL);
     }
 
-    if(spcell_config != (SpCellConfig_t *)0){
-    
+    if(serving_cell_config_config != (SpCellConfig_t *)0){
+        config_phy(NULL, spcell_config);
+        mac->servCellIndex = spcell_config->servCellIndex;
     }
 
+
+    if(serving_cell_config != (spCellConfigDedicated_t *)0){
+        if(serving_cell_config->tdd_UL_DL_ConfigurationDedicated != (TDD_UL_DL_ConfigDedicated_t *)0){
+            mac->tdd_UL_DL_ConfigurationDedicated = serving_cell_config->tdd_UL_DL_ConfigurationDedicated;
+        }
+        
+        if(spcell_config->initialDownlinkBWP != (BWP_DownlinkDedicated_t *)0){
+            mac->init_DL_BWP = spcell_config->initialDownlinkBWP;
+        }
+        
+        //  storage list of DL BWP config. TODO should be modify to maintain(add/release) a list inside MAC instance, this implementation just use for one-shot RRC configuration setting.
+        if(spcell_config->downlinkBWP_ToAddModList != (struct ServingCellConfig__downlinkBWP_ToAddModList *)0){
+            mac->BWP_Downlink_list = spcell_config->downlinkBWP_ToAddModList->list;
+            mac->BWP_Downlink_count = spcell_config->downlinkBWP_ToAddModList->count;
+        }
+        
+        if(spcell_config->bwp_InactivityTimer != (long *)0){
+            mac->bwp_InactivityTimer = spcell_config->bwp_InactivityTimer;
+        } 
+
+        if(spcell_config->defaultDownlinkBWP_Id != (BWP_Id_t *)0){
+            mac->defaultDownlinkBWP_Id = spcell_config->defaultDownlinkBWP_Id;
+        }
+
+        if(spcell_config->pdsch_ServingCellConfig != (PDSCH_ServingCellConfig_t *)0){
+            mac->pdsch_ServingCellConfig = spcell_config->pdsch_ServingCellConfig;
+        }
+
+        if(spcell_config->csi_MeasConfig != (CSI_MeasConfig_t *)0){
+            mac->csi_MeasConfig = spcell_config->csi_MeasConfig;
+        }
+
+        spcell_config->tag_Id = spcell_config.tag_Id;
+    }
+
+    //scell config not yet
+
+
+
+
+
+
+
     return (0);
 }
diff --git a/openair2/LAYER2/NR_MAC_UE/defs.h b/openair2/LAYER2/NR_MAC_UE/defs.h
index b2a3ec259f..e7329616b7 100644
--- a/openair2/LAYER2/NR_MAC_UE/defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/defs.h
@@ -72,12 +72,35 @@
 /*!\brief Top level UE MAC structure */
 typedef struct {
     
+    ////  MAC config
     drx_Config_t *drx_config;
     SchedulingRequestConfig_t *SchedulingRequestConfig;
     BSR_Config_t *BSR_Config;
     TAG_Config_t *TAG_Config;
     phr_Config_t *phr_Config;
     cs_RNTI_t *cs_RNTI;
+    ServCellIndex_t *servCellIndex;
+
+    ////  Serving cell config
+    TDD_UL_DL_ConfigDedicated_t *tdd_UL_DL_ConfigurationDedicated;
+    //  init DL BWP
+    BWP_DownlinkDedicated_t *init_DL_BWP;
+    //  DL BWP list, not default one
+    BWP_Downlink_t **BWP_Downlink_list;
+    int BWP_Downlink_count;
+    //BWP_Id_t *firstActiveDownlinkBWP_Id;
+    long *bwp_InactivityTimer;
+    BWP_Id_t *defaultDownlinkBWP_Id;
+    //struct UplinkConfig *uplinkConfig;
+    //struct UplinkConfig *supplementaryUplink;
+    PDSCH_ServingCellConfig_t *pdsch_ServingCellConfig;
+    CSI_MeasConfig_t *csi_MeasConfig;
+    //SRS_CarrierSwitching_t *carrierSwitching;
+    //long *sCellDeactivationTimer /* OPTIONAL */;
+    //struct CrossCarrierSchedulingConfig *crossCarrierSchedulingConfig   /* OPTIONAL */;
+    TAG_Id_t tag_Id;
+    //long *ue_BeamLockFunction    /* OPTIONAL */;
+    //long *pathlossReferenceLinking   /* OPTIONAL */;    
 
 } UE_MAC_INST;
 #include "proto.h"
diff --git a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
index d682cf5870..a1c3688fc4 100644
--- a/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
+++ b/openair2/LAYER2/NR_MAC_UE/main_ue_nr.c
@@ -34,6 +34,7 @@
 #include "extern.h"
 #include "assertions.h"
 
+static NR_UE_MAC_INST_t *nr_ue_mac_inst; 
 
 int
 nr_l2_init_ue(void)
@@ -43,7 +44,12 @@ nr_l2_init_ue(void)
     LOG_I(MAC, "[MAIN] init UE MAC functions \n");
     
     //init mac here
+    nr_ue_mac_inst = (NR_UE_MAC_INST_t *)malloc(sizeof(NR_UE_MAC_INST_t)*NB_NR_UE_MAC_INST);
+    
 
     return (1);
 }
 
+NR_UE_MAC_INST_t *get_mac_inst(Module_id_t Mod_idP){
+    return &nr_ue_mac_inst[(int)Mod_idP];
+}
diff --git a/openair2/LAYER2/NR_MAC_UE/vars.c b/openair2/LAYER2/NR_MAC_UE/vars.c
new file mode 100644
index 0000000000..300917b3c1
--- /dev/null
+++ b/openair2/LAYER2/NR_MAC_UE/vars.c
@@ -0,0 +1,34 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file vars.h
+* \brief mac vars
+* \author  Navid Nikaein and Raymond Knopp
+* \date 2010 - 2014
+* \version 1.0
+* \email navid.nikaein@eurecom.fr
+* @ingroup _mac
+
+*/
+
+UE_MAC_INST_t UE_mac_inst;	//[NB_MODULE_MAX];
+
+
diff --git a/openair2/NR_UE_PHY_INTERFACE/IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/IF_Module.c
new file mode 100644
index 0000000000..d0b8e57558
--- /dev/null
+++ b/openair2/NR_UE_PHY_INTERFACE/IF_Module.c
@@ -0,0 +1,647 @@
+#include "openair1/PHY/defs.h"
+#include "openair2/PHY_INTERFACE/IF_Module.h"
+#include "openair1/PHY/extern.h"
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/proto.h"
+#include "common/ran_context.h"
+
+#define MAX_IF_MODULES 100
+
+IF_Module_t *if_inst[MAX_IF_MODULES];
+Sched_Rsp_t Sched_INFO[MAX_IF_MODULES][MAX_NUM_CCs];
+
+extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind);
+extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
+extern int oai_nfapi_cqi_indication(nfapi_cqi_indication_t *cqi_ind);
+extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
+extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
+extern uint8_t nfapi_mode;
+extern uint16_t sf_ahead;
+
+void handle_rach(UL_IND_t *UL_info) {
+  int i;
+
+  if (UL_info->rach_ind.rach_indication_body.number_of_preambles>0) {
+
+    AssertFatal(UL_info->rach_ind.rach_indication_body.number_of_preambles==1,"More than 1 preamble not supported\n");
+    UL_info->rach_ind.rach_indication_body.number_of_preambles=0;
+    LOG_D(MAC,"UL_info[Frame %d, Subframe %d] Calling initiate_ra_proc RACH:SFN/SF:%d\n",UL_info->frame,UL_info->subframe, NFAPI_SFNSF2DEC(UL_info->rach_ind.sfn_sf));
+    initiate_ra_proc(UL_info->module_id,
+		     UL_info->CC_id,
+		     NFAPI_SFNSF2SFN(UL_info->rach_ind.sfn_sf),
+		     NFAPI_SFNSF2SF(UL_info->rach_ind.sfn_sf),
+		     UL_info->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.preamble,
+		     UL_info->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.timing_advance,
+		     UL_info->rach_ind.rach_indication_body.preamble_list[0].preamble_rel8.rnti
+#ifdef Rel14
+		     ,0
+#endif
+		     );
+  }
+
+#ifdef Rel14
+  if (UL_info->rach_ind_br.rach_indication_body.number_of_preambles>0) {
+
+    AssertFatal(UL_info->rach_ind_br.rach_indication_body.number_of_preambles<5,"More than 4 preambles not supported\n");
+    for (i=0;i<UL_info->rach_ind_br.rach_indication_body.number_of_preambles;i++) {
+      AssertFatal(UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel13.rach_resource_type>0,
+		  "Got regular PRACH preamble, not BL/CE\n");
+      LOG_D(MAC,"Frame %d, Subframe %d Calling initiate_ra_proc (CE_level %d)\n",UL_info->frame,UL_info->subframe,
+	    UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel13.rach_resource_type-1);
+      initiate_ra_proc(UL_info->module_id,
+		       UL_info->CC_id,
+		       UL_info->frame,
+		       UL_info->subframe,
+		       UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel8.preamble,
+		       UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel8.timing_advance,
+		       UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel8.rnti,
+		       UL_info->rach_ind_br.rach_indication_body.preamble_list[i].preamble_rel13.rach_resource_type);
+    }
+    UL_info->rach_ind_br.rach_indication_body.number_of_preambles=0;
+  }
+#endif
+}
+
+void handle_sr(UL_IND_t *UL_info) {
+
+  int i;
+
+  if (nfapi_mode == 1)  // PNF
+  {
+    if (UL_info->sr_ind.sr_indication_body.number_of_srs>0)
+    {
+      oai_nfapi_sr_indication(&UL_info->sr_ind);
+    }
+  }
+  else
+  {
+    for (i=0;i<UL_info->sr_ind.sr_indication_body.number_of_srs;i++)
+      SR_indication(UL_info->module_id,
+          UL_info->CC_id,
+          UL_info->frame,
+          UL_info->subframe,
+          UL_info->sr_ind.sr_indication_body.sr_pdu_list[i].rx_ue_information.rnti,
+          UL_info->sr_ind.sr_indication_body.sr_pdu_list[i].ul_cqi_information.ul_cqi);
+  }
+
+  UL_info->sr_ind.sr_indication_body.number_of_srs=0;
+}
+
+void handle_cqi(UL_IND_t *UL_info) {
+
+  int i;
+
+  if (nfapi_mode == 1)
+  {
+    if (UL_info->cqi_ind.number_of_cqis>0)
+    {
+      LOG_D(PHY,"UL_info->cqi_ind.number_of_cqis:%d\n", UL_info->cqi_ind.number_of_cqis);
+      nfapi_cqi_indication_t ind;
+
+      ind.header.message_id = NFAPI_RX_CQI_INDICATION;
+      ind.sfn_sf = UL_info->frame<<4 | UL_info->subframe;
+      ind.cqi_indication_body = UL_info->cqi_ind;
+
+      oai_nfapi_cqi_indication(&ind);
+
+      UL_info->cqi_ind.number_of_cqis=0;
+    }
+  }
+  else
+  {
+    for (i=0;i<UL_info->cqi_ind.number_of_cqis;i++) 
+      cqi_indication(UL_info->module_id,
+          UL_info->CC_id,
+          UL_info->frame,
+          UL_info->subframe,
+          UL_info->cqi_ind.cqi_pdu_list[i].rx_ue_information.rnti,
+          &UL_info->cqi_ind.cqi_pdu_list[i].cqi_indication_rel9,
+          UL_info->cqi_ind.cqi_raw_pdu_list[i].pdu,
+          &UL_info->cqi_ind.cqi_pdu_list[i].ul_cqi_information);
+
+    UL_info->cqi_ind.number_of_cqis=0;
+  }
+}
+
+void handle_harq(UL_IND_t *UL_info) {
+
+  int i;
+
+  if (nfapi_mode == 1 && UL_info->harq_ind.harq_indication_body.number_of_harqs>0) // PNF
+  {
+    //LOG_D(PHY, "UL_info->harq_ind.harq_indication_body.number_of_harqs:%d Send to VNF\n", UL_info->harq_ind.harq_indication_body.number_of_harqs);
+
+    int retval = oai_nfapi_harq_indication(&UL_info->harq_ind);
+
+    if (retval!=0)
+    {
+      LOG_E(PHY, "Failed to encode NFAPI HARQ_IND retval:%d\n", retval);
+    }
+
+    UL_info->harq_ind.harq_indication_body.number_of_harqs = 0;
+  }
+  else
+  {
+    for (i=0;i<UL_info->harq_ind.harq_indication_body.number_of_harqs;i++)
+      harq_indication(UL_info->module_id,
+          UL_info->CC_id,
+          NFAPI_SFNSF2SFN(UL_info->harq_ind.sfn_sf),
+          NFAPI_SFNSF2SF(UL_info->harq_ind.sfn_sf),
+          &UL_info->harq_ind.harq_indication_body.harq_pdu_list[i]);
+
+    UL_info->harq_ind.harq_indication_body.number_of_harqs=0;
+  }
+}
+
+void handle_ulsch(UL_IND_t *UL_info) {
+
+  int i,j;
+
+  if(nfapi_mode == 1)
+  {
+    if (UL_info->crc_ind.crc_indication_body.number_of_crcs>0)
+    {
+      //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf));
+
+      oai_nfapi_crc_indication(&UL_info->crc_ind);
+
+      UL_info->crc_ind.crc_indication_body.number_of_crcs = 0;
+    }
+
+    if (UL_info->rx_ind.rx_indication_body.number_of_pdus>0)
+    {
+      //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf));
+      oai_nfapi_rx_ind(&UL_info->rx_ind);
+      UL_info->rx_ind.rx_indication_body.number_of_pdus = 0;
+    }
+  }
+  else
+  {
+    if (UL_info->rx_ind.rx_indication_body.number_of_pdus>0 && UL_info->crc_ind.crc_indication_body.number_of_crcs>0) {
+      for (i=0;i<UL_info->rx_ind.rx_indication_body.number_of_pdus;i++) {
+        for (j=0;j<UL_info->crc_ind.crc_indication_body.number_of_crcs;j++) {
+          // find crc_indication j corresponding rx_indication i
+          LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].rx_ue_information.rnti:%04x UL_info->rx_ind.rx_indication_body.rx_pdu_list[%d].rx_ue_information.rnti:%04x\n", j, UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti, i, UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti);
+          if (UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].rx_ue_information.rnti ==
+              UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti) {
+            LOG_D(PHY, "UL_info->crc_ind.crc_indication_body.crc_pdu_list[%d].crc_indication_rel8.crc_flag:%d\n", j, UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag);
+            if (UL_info->crc_ind.crc_indication_body.crc_pdu_list[j].crc_indication_rel8.crc_flag == 1) { // CRC error indication
+              LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC error) \n",UL_info->frame,UL_info->subframe);
+              rx_sdu(UL_info->module_id,
+                  UL_info->CC_id,
+                  NFAPI_SFNSF2SFN(UL_info->rx_ind.sfn_sf), //UL_info->frame,
+                  NFAPI_SFNSF2SF(UL_info->rx_ind.sfn_sf), //UL_info->subframe,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti,
+                  (uint8_t *)NULL,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi);
+            }
+            else {
+              LOG_D(MAC,"Frame %d, Subframe %d Calling rx_sdu (CRC ok) \n",UL_info->frame,UL_info->subframe);
+              rx_sdu(UL_info->module_id,
+                  UL_info->CC_id,
+                  NFAPI_SFNSF2SFN(UL_info->rx_ind.sfn_sf), //UL_info->frame,
+                  NFAPI_SFNSF2SF(UL_info->rx_ind.sfn_sf), //UL_info->subframe,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_ue_information.rnti,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].data,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.length,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.timing_advance,
+                  UL_info->rx_ind.rx_indication_body.rx_pdu_list[i].rx_indication_rel8.ul_cqi);
+            }
+            break;
+          } //if (UL_info->crc_ind.crc_pdu_list[j].rx_ue_information.rnti ==
+          //    UL_info->rx_ind.rx_pdu_list[i].rx_ue_information.rnti)
+        } //    for (j=0;j<UL_info->crc_ind.crc_indication_body.number_of_crcs;j++)
+      } //   for (i=0;i<UL_info->rx_ind.number_of_pdus;i++)
+      UL_info->crc_ind.crc_indication_body.number_of_crcs=0;
+      UL_info->rx_ind.rx_indication_body.number_of_pdus = 0;
+    } // UL_info->rx_ind.rx_indication_body.number_of_pdus>0 && UL_info->subframe && UL_info->crc_ind.crc_indication_body.number_of_crcs>0
+    else if (UL_info->rx_ind.rx_indication_body.number_of_pdus!=0 || UL_info->crc_ind.crc_indication_body.number_of_crcs!=0) {
+      LOG_E(PHY,"hoping not to have mis-match between CRC ind and RX ind - hopefully the missing message is coming shortly rx_ind:%d(SFN/SF:%05d) crc_ind:%d(SFN/SF:%05d) UL_info(SFN/SF):%04d%d\n",
+          UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf),
+          UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf),
+          UL_info->frame, UL_info->subframe);
+    }
+  }
+}
+
+/****************************************************************************/
+/* debug utility functions begin                                            */
+/****************************************************************************/
+
+//#define DUMP_FAPI
+
+#ifdef DUMP_FAPI
+
+#define C do { size = 0; put(0); } while (0)
+#define A(...) do { char t[4096]; sprintf(t, __VA_ARGS__); append_string(t); } while (0)
+
+#if 0
+
+/* eats lots of ms at startup, disrupts realtime */
+static char *s;
+static int size;
+static int maxsize;
+
+static void put(char x)
+{
+  if (size == maxsize) {
+    maxsize += 32768;
+    s = realloc(s, maxsize); if (s == NULL) abort();
+  }
+  s[size++] = x;
+}
+
+#else
+
+/* eats nothing at startup, but fixed size */
+#define SMAX 65536
+static char s[SMAX];
+static int size;
+static int maxsize = SMAX;
+
+static void put(char x)
+{
+  if (size == maxsize) { printf("incrase SMAX\n"); exit(1); }
+  s[size++] = x;
+}
+
+#endif
+
+static void append_string(char *t)
+{
+  size--;
+  while (*t) put(*t++);
+  put(0);
+}
+
+static void dump_ul(UL_IND_t *u)
+{
+  int i;
+
+  C;
+  A("XXXX UL  mod %d CC %d f.sf %d.%d\n",
+    u->module_id, u->CC_id, u->frame, u->subframe);
+
+  A("XXXX     harq_ind %d\n", u->harq_ind.harq_indication_body.number_of_harqs);
+      for (i = 0; i < u->harq_ind.harq_indication_body.number_of_harqs; i++) {
+        nfapi_harq_indication_pdu_t *v = &u->harq_ind.harq_indication_body.harq_pdu_list[i];
+  A("XXXX         harq ind %d\n", i);
+  A("XXXX         rnti %d\n", v->rx_ue_information.rnti);
+  A("XXXX         tb1 %d tb2 %d\n", v->harq_indication_fdd_rel8.harq_tb1,
+                                    v->harq_indication_fdd_rel8.harq_tb2);
+  A("XXXX         number_of_ack_nack %d\n",
+                          v->harq_indication_fdd_rel9.number_of_ack_nack);
+  A("XXXX             harq[0] = %d\n",
+                                    v->harq_indication_fdd_rel9.harq_tb_n[0]);
+  A("XXXX harq        ul_cqi %d channel %d\n", v->ul_cqi_information.ul_cqi,
+                                           v->ul_cqi_information.channel);
+      }
+
+  A("XXXX     crc_ind  %d\n", u->crc_ind.crc_indication_body.number_of_crcs);
+
+  A("XXXX     sr_ind   %d\n", u->sr_ind.sr_indication_body.number_of_srs);
+
+  A("XXXX     cqi_ind  %d\n", u->cqi_ind.number_of_cqis);
+      for (i = 0; i < u->cqi_ind.number_of_cqis; i++) {
+        nfapi_cqi_indication_pdu_t *v = &u->cqi_ind.cqi_pdu_list[i];
+  A("XXXX         cqi ind %d\n", i);
+  A("XXXX cqi         ul_cqi %d channel %d\n", v->ul_cqi_information.ul_cqi,
+                                               v->ul_cqi_information.channel);
+      }
+
+  A("XXXX     rach_ind %d\n", u->rach_ind.rach_indication_body.number_of_preambles);
+
+  A("XXXX     rx_ind   %d\n", u->rx_ind.rx_indication_body.number_of_pdus);
+      for (i = 0; i < u->rx_ind.rx_indication_body.number_of_pdus; i++) {
+        nfapi_rx_indication_pdu_t *v = &u->rx_ind.rx_indication_body.rx_pdu_list[i];
+  A("XXXX         rx ind %d\n", i);
+  A("XXXX             timing_advance %d\n",
+                                    v->rx_indication_rel8.timing_advance);
+  A("XXXX rx          ul_cqi %d\n", v->rx_indication_rel8.ul_cqi);
+      }
+
+  LOG_I(PHY, "XXXX UL\nXXXX UL\n%s", s);
+}
+
+static char *DL_PDU_TYPE(int x)
+{
+  switch (x) {
+  case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: return "NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE";
+  case NFAPI_DL_CONFIG_BCH_PDU_TYPE: return "NFAPI_DL_CONFIG_BCH_PDU_TYPE";
+  case NFAPI_DL_CONFIG_MCH_PDU_TYPE: return "NFAPI_DL_CONFIG_MCH_PDU_TYPE";
+  case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: return "NFAPI_DL_CONFIG_DLSCH_PDU_TYPE";
+  case NFAPI_DL_CONFIG_PCH_PDU_TYPE: return "NFAPI_DL_CONFIG_PCH_PDU_TYPE";
+  case NFAPI_DL_CONFIG_PRS_PDU_TYPE: return "NFAPI_DL_CONFIG_PRS_PDU_TYPE";
+  case NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE: return "NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE";
+  case NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE: return "NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE";
+  case NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE: return "NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE";
+  case NFAPI_DL_CONFIG_NBCH_PDU_TYPE: return "NFAPI_DL_CONFIG_NBCH_PDU_TYPE";
+  case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE: return "NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE";
+  case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE: return "NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE";
+  }
+  return "UNKNOWN";
+}
+
+static char *UL_PDU_TYPE(int x)
+{
+  switch (x) {
+  case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_PDU_TYPE";
+  case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE";
+  case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE";
+  case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE";
+  case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE";
+  case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE";
+  case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE";
+  case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE";
+  case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE";
+  case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE";
+  case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE";
+  case NFAPI_UL_CONFIG_SRS_PDU_TYPE: return "NFAPI_UL_CONFIG_SRS_PDU_TYPE";
+  case NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE: return "NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE";
+  case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE";
+  case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE";
+  case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE: return "NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE";
+  case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE: return "NFAPI_UL_CONFIG_NULSCH_PDU_TYPE";
+  case NFAPI_UL_CONFIG_NRACH_PDU_TYPE: return "NFAPI_UL_CONFIG_NRACH_PDU_TYPE";
+  }
+  return "UNKNOWN";
+}
+
+static char *HI_DCI0_PDU_TYPE(int x)
+{
+  switch (x) {
+  case NFAPI_HI_DCI0_HI_PDU_TYPE: return "NFAPI_HI_DCI0_HI_PDU_TYPE";
+  case NFAPI_HI_DCI0_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_DCI_PDU_TYPE";
+  case NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE";
+  case NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE";
+  case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE: return "NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE";
+  }
+  return "UNKNOWN";
+}
+
+static void dump_dl(Sched_Rsp_t *d)
+{
+  int i;
+
+  C;
+  A("XXXX DL  mod %d CC %d f.sf %d.%d\n",
+    d->module_id, d->CC_id, d->frame, d->subframe);
+
+      if (d->DL_req != NULL) {
+        nfapi_dl_config_request_body_t *v=&d->DL_req->dl_config_request_body;
+        nfapi_dl_config_request_pdu_t *p = v->dl_config_pdu_list;
+  A("XXXX     DL_req sfnsf %d\n", d->DL_req->sfn_sf);
+  A("XXXX     PDCCH size   %d\n", v->number_pdcch_ofdm_symbols);
+  A("XXXX     DCIs         %d\n", v->number_dci);
+  A("XXXX     PDUs         %d\n", v->number_pdu);
+  A("XXXX     rntis        %d\n", v->number_pdsch_rnti);
+  A("XXXX     pcfich power %d\n", v->transmission_power_pcfich);
+        for (i = 0; i < v->number_pdu; i++) {
+  A("XXXX         pdu %d\n", i);
+  A("XXXX             type %d %s\n", p[i].pdu_type, DL_PDU_TYPE(p[i].pdu_type));
+          switch (p[i].pdu_type) {
+          case NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE: {
+            nfapi_dl_config_dci_dl_pdu_rel8_t *q =
+                &p[i].dci_dl_pdu.dci_dl_pdu_rel8;
+  A("XXXX                 dci format %d\n", q->dci_format);
+  A("XXXX                 cce idx    %d\n", q->cce_idx);
+  A("XXXX                 agg lvl    %d\n", q->aggregation_level);
+  A("XXXX                 rnti       %d\n", q->rnti);
+  A("XXXX                 rb coding  %8.8x\n", q->resource_block_coding);
+  A("XXXX                 mcs_1      %d\n", q->mcs_1);
+  A("XXXX                 rv_1       %d\n", q->redundancy_version_1);
+  A("XXXX                 ndi_1      %d\n", q->new_data_indicator_1);
+  A("XXXX                 harq pid   %d\n", q->harq_process);
+  A("XXXX                 tpc        %d\n", q->tpc);
+  A("XXXX                 tbs idx    %d\n", q->transport_block_size_index);
+  A("XXXX                 dl pow off %d\n", q->downlink_power_offset);
+  A("XXXX                 rnti type  %d\n", q->rnti_type);
+  A("XXXX                 xmit pow   %d\n", q->transmission_power);
+            break;
+          }
+          case NFAPI_DL_CONFIG_DLSCH_PDU_TYPE: {
+            nfapi_dl_config_dlsch_pdu_rel8_t *q =
+                &p[i].dlsch_pdu.dlsch_pdu_rel8;
+  A("XXXX                 pdu_index %d\n", q->pdu_index);
+  A("XXXX                 rnti      %d\n", q->rnti);
+  A("XXXX                 rv        %d\n", q->redundancy_version);
+  A("XXXX                 mcs       %d\n", q->modulation);
+  A("XXXX                 pa        %d\n", q->pa);
+            break;
+          }}
+        }
+      }
+
+      if (d->HI_DCI0_req != NULL) {
+        nfapi_hi_dci0_request_body_t *v=&d->HI_DCI0_req->hi_dci0_request_body;
+  A("XXXX up  HI_DCI0_req sfnsf %d (%d.%d)\n", d->HI_DCI0_req->sfn_sf,
+    d->HI_DCI0_req->sfn_sf/16, d->HI_DCI0_req->sfn_sf%16);
+  A("XXXX up     sfnsf %d\n", v->sfnsf);
+  A("XXXX up     DCIs  %d\n", v->number_of_dci);
+  A("XXXX up     HIs   %d\n", v->number_of_hi);
+        for (i = 0; i < v->number_of_dci + v->number_of_hi; i++) {
+          nfapi_hi_dci0_request_pdu_t *p = &v->hi_dci0_pdu_list[i];
+  A("XXXX up      pdu %d\n", i);
+  A("XXXX up          type %d %s\n",p->pdu_type,HI_DCI0_PDU_TYPE(p->pdu_type));
+          if (p->pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) {
+            nfapi_hi_dci0_dci_pdu_rel8_t *q = &p->dci_pdu.dci_pdu_rel8;
+  A("XXXX up          dci_format           %d\n", q->dci_format);
+  A("XXXX up          cce_index            %d\n", q->cce_index);
+  A("XXXX up          aggregation_level    %d\n", q->aggregation_level);
+  A("XXXX up          rnti                 %d\n", q->rnti);
+  A("XXXX up          rb start             %d\n", q->resource_block_start);
+  A("XXXX up          # rb                 %d\n", q->number_of_resource_block);
+  A("XXXX up          mcs_1                %d\n", q->mcs_1);
+  A("XXXX up          cshift_2_for_drms    %d\n", q->cyclic_shift_2_for_drms);
+  A("XXXX up          freq hop enabled     %d\n", q->frequency_hopping_enabled_flag);
+  A("XXXX up          fre hop bits         %d\n", q->frequency_hopping_bits);
+  A("XXXX up          NDI_1                %d\n", q->new_data_indication_1);
+  A("XXXX up          tx_antenna_seleciton %d\n", q->ue_tx_antenna_seleciton);
+  A("XXXX up          tpc                  %d\n", q->tpc);
+  A("XXXX up          cqi_csi_request      %d\n", q->cqi_csi_request);
+  A("XXXX up          ul_index             %d\n", q->ul_index);
+  A("XXXX up          dl_assignment_index  %d\n", q->dl_assignment_index);
+  A("XXXX up          tpc_bitmap           %d\n", q->tpc_bitmap);
+  A("XXXX up          transmission_power   %d\n", q->transmission_power);
+          }
+          if (p->pdu_type == NFAPI_HI_DCI0_HI_PDU_TYPE) {
+            nfapi_hi_dci0_hi_pdu_rel8_t *q = &p->hi_pdu.hi_pdu_rel8;
+  A("XXXX up          rb start    %d\n", q->resource_block_start);
+  A("XXXX up          cs2_drms    %d\n", q->cyclic_shift_2_for_drms);
+  A("XXXX up          ack         %d\n", q->hi_value);
+  A("XXXX up          i_phich     %d\n", q->i_phich);
+  A("XXXX up          power       %d\n", q->transmission_power);
+          }
+        }
+      }
+
+      if (d->UL_req != NULL) {
+        nfapi_ul_config_request_body_t *v=&d->UL_req->ul_config_request_body;
+  A("XXXX     UL_req sfnsf %d (%d.%d)\n", d->UL_req->sfn_sf,
+    d->UL_req->sfn_sf/16, d->UL_req->sfn_sf%16);
+  A("XXXX     PDUs         %d\n", v->number_of_pdus);
+  A("XXXX     ra freq      %d\n", v->rach_prach_frequency_resources);
+  A("XXXX     srs?         %d\n", v->srs_present);
+        for (i = 0; i < v->number_of_pdus; i++) {
+          nfapi_ul_config_request_pdu_t *p = &v->ul_config_pdu_list[i];
+  A("XXXX         pdu %d\n", i);
+  A("XXXX             type %d %s\n", p->pdu_type, UL_PDU_TYPE(p->pdu_type));
+          switch(p->pdu_type) {
+          case NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE: {
+            nfapi_ul_config_uci_harq_pdu *q = &p->uci_harq_pdu;
+            nfapi_ul_config_harq_information_rel9_fdd_t *h =
+                &q->harq_information.harq_information_rel9_fdd;
+  A("XXXX                 rnti          %d\n",
+    q->ue_information.ue_information_rel8.rnti);
+  A("XXXX                 harq size     %d\n", h->harq_size);
+  A("XXXX                 ack_nack_mode %d\n", h->ack_nack_mode);
+  A("XXXX                 # pucch res   %d\n", h->number_of_pucch_resources);
+  A("XXXX                 n_pucch_1_0   %d\n", h->n_pucch_1_0);
+  A("XXXX                 n_pucch_1_1   %d\n", h->n_pucch_1_1);
+  A("XXXX                 n_pucch_1_2   %d\n", h->n_pucch_1_2);
+  A("XXXX                 n_pucch_1_3   %d\n", h->n_pucch_1_3);
+            break;
+          }
+          case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE: {
+            nfapi_ul_config_uci_sr_pdu *q = &p->uci_sr_pdu;
+            nfapi_ul_config_sr_information_rel8_t *h =
+                &q->sr_information.sr_information_rel8;
+  A("XXXX                 rnti          %d\n",
+    q->ue_information.ue_information_rel8.rnti);
+  A("XXXX                 pucch_index   %d\n", h->pucch_index);
+          }}
+        }
+      }
+
+  LOG_I(PHY, "XXXX DL\nXXXX DL\n%s", s);
+}
+
+#undef C
+#undef A
+
+#endif /* DUMP_FAPI */
+
+/****************************************************************************/
+/* debug utility functions end                                              */
+/****************************************************************************/
+
+void UL_indication(UL_IND_t *UL_info)
+{
+
+  AssertFatal(UL_info!=NULL,"UL_INFO is null\n");
+
+#ifdef DUMP_FAPI
+  dump_ul(UL_info);
+#endif
+
+  module_id_t  module_id   = UL_info->module_id;
+  int          CC_id       = UL_info->CC_id;
+  Sched_Rsp_t  *sched_info = &Sched_INFO[module_id][CC_id];
+  IF_Module_t  *ifi        = if_inst[module_id];
+  eNB_MAC_INST *mac        = RC.mac[module_id];
+
+  LOG_D(PHY,"SFN/SF:%d%d module_id:%d CC_id:%d UL_info[rx_ind:%d harqs:%d crcs:%d cqis:%d preambles:%d sr_ind:%d]\n",
+        UL_info->frame,UL_info->subframe,
+        module_id,CC_id,
+        UL_info->rx_ind.rx_indication_body.number_of_pdus, UL_info->harq_ind.harq_indication_body.number_of_harqs, UL_info->crc_ind.crc_indication_body.number_of_crcs, UL_info->cqi_ind.number_of_cqis, UL_info->rach_ind.rach_indication_body.number_of_preambles, UL_info->sr_ind.sr_indication_body.number_of_srs);
+
+  if (nfapi_mode != 1)
+  {
+    if (ifi->CC_mask==0) {
+      ifi->current_frame    = UL_info->frame;
+      ifi->current_subframe = UL_info->subframe;
+    }
+    else {
+      AssertFatal(UL_info->frame != ifi->current_frame,"CC_mask %x is not full and frame has changed\n",ifi->CC_mask);
+      AssertFatal(UL_info->subframe != ifi->current_subframe,"CC_mask %x is not full and subframe has changed\n",ifi->CC_mask);
+    }
+    ifi->CC_mask |= (1<<CC_id);
+  }
+
+
+  // clear DL/UL info for new scheduling round
+  clear_nfapi_information(RC.mac[module_id],CC_id,
+			  UL_info->frame,UL_info->subframe);
+
+  handle_rach(UL_info);
+
+  handle_sr(UL_info);
+
+  handle_cqi(UL_info);
+
+  handle_harq(UL_info);
+
+  // clear HI prior to handling ULSCH
+  mac->HI_DCI0_req[CC_id].hi_dci0_request_body.number_of_hi                     = 0;
+  
+  handle_ulsch(UL_info);
+
+  if (nfapi_mode != 1)
+  {
+    if (ifi->CC_mask == ((1<<MAX_NUM_CCs)-1)) {
+
+      eNB_dlsch_ulsch_scheduler(module_id,
+          (UL_info->frame+((UL_info->subframe>(9-sf_ahead))?1:0)) % 1024,
+          (UL_info->subframe+sf_ahead)%10);
+
+      ifi->CC_mask            = 0;
+
+      sched_info->module_id   = module_id;
+      sched_info->CC_id       = CC_id;
+      sched_info->frame       = (UL_info->frame + ((UL_info->subframe>(9-sf_ahead)) ? 1 : 0)) % 1024;
+      sched_info->subframe    = (UL_info->subframe+sf_ahead)%10;
+      sched_info->DL_req      = &mac->DL_req[CC_id];
+      sched_info->HI_DCI0_req = &mac->HI_DCI0_req[CC_id];
+      if ((mac->common_channels[CC_id].tdd_Config==NULL) ||
+          (is_UL_sf(&mac->common_channels[CC_id],(sched_info->subframe+sf_ahead)%10)>0))
+        sched_info->UL_req      = &mac->UL_req[CC_id];
+      else
+        sched_info->UL_req      = NULL;
+
+      sched_info->TX_req      = &mac->TX_req[CC_id];
+
+#ifdef DUMP_FAPI
+      dump_dl(sched_info);
+#endif
+
+      if (ifi->schedule_response)
+      {
+        AssertFatal(ifi->schedule_response!=NULL,
+            "schedule_response is null (mod %d, cc %d)\n",
+            module_id,
+            CC_id);
+        ifi->schedule_response(sched_info);
+      }
+
+      LOG_D(PHY,"Schedule_response: SFN_SF:%d%d dl_pdus:%d\n",sched_info->frame,sched_info->subframe,sched_info->DL_req->dl_config_request_body.number_pdu);
+    }
+  }
+}
+
+IF_Module_t *IF_Module_init(int Mod_id){
+
+  AssertFatal(Mod_id<MAX_MODULES,"Asking for Module %d > %d\n",Mod_id,MAX_IF_MODULES);
+
+  LOG_D(PHY,"Installing callbacks for IF_Module - UL_indication\n");
+
+  if (if_inst[Mod_id]==NULL) {
+    if_inst[Mod_id] = (IF_Module_t*)malloc(sizeof(IF_Module_t));
+    memset((void*)if_inst[Mod_id],0,sizeof(IF_Module_t));
+
+    if_inst[Mod_id]->CC_mask=0;
+    if_inst[Mod_id]->UL_indication = UL_indication;
+
+    AssertFatal(pthread_mutex_init(&if_inst[Mod_id]->if_mutex,NULL)==0,
+        "allocation of if_inst[%d]->if_mutex fails\n",Mod_id);
+  }
+  return if_inst[Mod_id];
+}
+
+void IF_Module_kill(int Mod_id) {
+
+  AssertFatal(Mod_id>MAX_MODULES,"Asking for Module %d > %d\n",Mod_id,MAX_IF_MODULES);
+  if (if_inst[Mod_id]!=NULL) free(if_inst[Mod_id]);
+
+}
diff --git a/openair2/NR_UE_PHY_INTERFACE/IF_Module.h b/openair2/NR_UE_PHY_INTERFACE/IF_Module.h
new file mode 100644
index 0000000000..3b1c88dda0
--- /dev/null
+++ b/openair2/NR_UE_PHY_INTERFACE/IF_Module.h
@@ -0,0 +1,142 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file openair2/PHY_INTERFACE/IF_Module.h
+* \brief data structures for PHY/MAC interface modules
+* \author EURECOM/NTUST
+* \date 2017
+* \version 0.1
+* \company Eurecom
+* \email: raymond.knopp@eurecom.fr
+* \note
+* \warning
+*/
+#ifndef __IF_MODULE__H__
+#define __IF_MODULE__H__
+
+
+#include <stdint.h>
+#include "openair1/PHY/LTE_TRANSPORT/defs.h"
+#include "nfapi_interface.h"
+
+
+#define MAX_NUM_DL_PDU 100
+#define MAX_NUM_UL_PDU 100
+#define MAX_NUM_HI_DCI0_PDU 100
+#define MAX_NUM_TX_REQUEST_PDU 100
+
+#define MAX_NUM_HARQ_IND 100
+#define MAX_NUM_CRC_IND 100
+#define MAX_NUM_SR_IND 100
+#define MAX_NUM_CQI_IND 100
+#define MAX_NUM_RACH_IND 100
+#define MAX_NUM_SRS_IND 100
+
+typedef struct{
+  /// Module ID
+  module_id_t module_id;
+  /// CC ID
+  int CC_id;
+  /// frame 
+  frame_t frame;
+  /// subframe
+  sub_frame_t subframe;
+
+  /// harq indication list
+  nfapi_harq_indication_t harq_ind;
+
+  /// crc indication list
+  nfapi_crc_indication_t crc_ind;
+
+  /// SR indication list
+  nfapi_sr_indication_t sr_ind;
+
+  /// CQI indication list
+  nfapi_cqi_indication_body_t cqi_ind;
+
+  /// RACH indication list
+  nfapi_rach_indication_t rach_ind;
+
+#ifdef Rel14
+  /// RACH indication list for BR UEs
+  nfapi_rach_indication_t rach_ind_br;
+#endif
+
+  /// SRS indication list
+  nfapi_srs_indication_body_t srs_ind;
+
+  /// RX indication
+  nfapi_rx_indication_t rx_ind;
+
+} UL_IND_t;
+
+// Downlink subframe P7
+
+
+typedef struct{
+  /// Module ID
+  module_id_t module_id; 
+  /// CC ID
+  uint8_t CC_id;
+  /// frame
+  frame_t frame;
+  /// subframe
+  sub_frame_t subframe;
+  /// nFAPI DL Config Request
+  nfapi_dl_config_request_t *DL_req;
+  /// nFAPI UL Config Request
+  nfapi_ul_config_request_t *UL_req;
+  /// nFAPI HI_DCI Request
+  nfapi_hi_dci0_request_t *HI_DCI0_req;
+  /// Pointers to DL SDUs
+  nfapi_tx_request_t *TX_req;
+}Sched_Rsp_t;
+
+typedef struct {
+    uint8_t Mod_id;
+    int CC_id;
+    nfapi_config_request_t *cfg;
+}PHY_Config_t;
+
+typedef struct IF_Module_s{
+//define the function pointer
+  void (*UL_indication)(UL_IND_t *UL_INFO);
+  void (*schedule_response)(Sched_Rsp_t *Sched_INFO);
+  void (*PHY_config_req)(PHY_Config_t* config_INFO);
+  uint32_t CC_mask;
+  uint16_t current_frame;
+  uint8_t current_subframe;
+  pthread_mutex_t if_mutex;
+}IF_Module_t;
+
+/*Initial */
+IF_Module_t *IF_Module_init(int Mod_id);
+void IF_Module_kill(int Mod_id);
+
+/*Interface for uplink, transmitting the Preamble(list), ULSCH SDU, NAK, Tick (trigger scheduler)
+ */
+void UL_indication(UL_IND_t *UL_INFO);
+
+/*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/
+void Schedule_Response(Sched_Rsp_t *Sched_INFO);
+
+#endif
+
diff --git a/openair2/NR_UE_PHY_INTERFACE/defs.h b/openair2/NR_UE_PHY_INTERFACE/defs.h
new file mode 100644
index 0000000000..deb07443f1
--- /dev/null
+++ b/openair2/NR_UE_PHY_INTERFACE/defs.h
@@ -0,0 +1,373 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file PHY_INTERFACE/defs.h
+* \brief mac phy interface primitives
+* \author Raymond Knopp and Navid Nikaein
+* \date 2011
+* \version 0.5
+* \mail navid.nikaein@eurecom.fr or openair_tech@eurecom.fr
+*/
+
+#ifndef __MAC_PHY_PRIMITIVES_H__
+#    define __MAC_PHY_PRIMITIVES_H__
+
+#include "LAYER2/MAC/defs.h"
+
+
+#define MAX_NUMBER_OF_MAC_INSTANCES 16
+
+#define NULL_PDU 255
+#define DCI 0
+#define DLSCH 1
+#define ULSCH 2
+
+#define mac_exit_wrapper(sTRING)                                                            \
+do {                                                                                        \
+    char temp[300];                                                                         \
+    snprintf(temp, sizeof(temp), "%s in file "__FILE__" at line %d\n", sTRING, __LINE__);   \
+    mac_xface->macphy_exit(temp);                                                           \
+} while(0)
+
+/** @defgroup _phy_if MAC-PHY interface
+ * @ingroup _oai2
+ * @{
+ */
+/*! \brief MACPHY Interface */
+/*
+typedef struct {
+  /// Pointer function that initializes L2
+  int (*macphy_init)(int eMBMS_active, char *uecap_xer, uint8_t CBA_active,uint8_t HO_active);
+
+  /// Pointer function that stops the low-level scheduler due an exit condition
+  void (*macphy_exit)(const char *);
+
+  // eNB functions
+  /// Invoke dlsch/ulsch scheduling procedure for new subframe
+  void (*eNB_dlsch_ulsch_scheduler)(module_id_t Mod_id,uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP);//, int calibration_flag);
+
+  /// Fill random access response sdu, passing timing advance
+  uint16_t (*fill_rar)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t *dlsch_buffer,uint16_t N_RB_UL, uint8_t input_buffer_length);
+
+  /// Initiate the RA procedure upon reception (hypothetical) of a valid preamble
+  void (*initiate_ra_proc)(module_id_t Mod_id,int CC_id,frame_t frameP,uint16_t preamble,int16_t timing_offset,uint8_t sect_id,sub_frame_t subframe,uint8_t f_id);
+
+  /// cancel an ongoing RA procedure
+  void (*cancel_ra_proc)(module_id_t Mod_id,int CC_id,frame_t frameP,uint16_t preamble);
+
+  /// Inform MAC layer that an uplink is scheduled for Msg3 in given subframe.
+  /// This is used so that the MAC scheduler marks as busy the RBs used by the Msg3.
+  void (*set_msg3_subframe)(module_id_t Mod_id,
+                            int CC_id,
+                            int frame,
+                            int subframe,
+                            int rnti,
+                            int Msg3_frame,
+                            int Msg3_subframe);
+
+  /// Get DCI for current subframe from MAC
+  DCI_PDU* (*get_dci_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP,sub_frame_t subframe);
+
+  /// Get DLSCH sdu for particular RNTI and Transport block index
+  uint8_t* (*get_dlsch_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,uint8_t TB_index);
+
+  /// Send ULSCH sdu to MAC for given rnti
+  void (*rx_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP, sub_frame_t sub_frameP,rnti_t rnti, uint8_t *sdu,uint16_t sdu_len, int harq_pid,uint8_t *msg3_flag);
+
+  /// Indicate failure to synch to external source
+  void (*mrbch_phy_sync_failure) (module_id_t Mod_id,frame_t frameP, uint8_t free_eNB_index);
+
+  /// Indicate Scheduling Request from UE
+  void (*SR_indication)(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,sub_frame_t subframe);
+  /// Indicate UL Failure to eNodeB MAC
+  void (*UL_failure_indication)(module_id_t Mod_id,int CC_id,frame_t frameP,rnti_t rnti,sub_frame_t subframe);
+
+  /// Configure Common PHY parameters from SIB1
+  void (*phy_config_mib_eNB)(module_id_t Mod_id,int CC_id,
+			     int eutra_band,
+			     int N_RB_DL,
+			     PHICH_Config_t *phich_Config,
+			     int Nid_cell,
+			     int Ncp,
+			     int p_eNB,
+			     uint32_t      dl_CarrierFreq,
+			     uint32_t      ul_CarrierFreq);
+
+  /// Configure Common PHY parameters from SIB1
+  void (*phy_config_sib1_eNB)(module_id_t Mod_id,int CC_id,
+                              TDD_Config_t *tdd_config,
+                              uint8_t SIwindowsize,
+                              uint16_t SIperiod);
+
+  /// Configure Common PHY parameters from SIB2
+  void (*phy_config_sib2_eNB)(module_id_t Mod_id, int CC_id,
+                              RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
+                              ARFCN_ValueEUTRA_t *ul_CArrierFreq,
+                              long *ul_Bandwidth,
+                              AdditionalSpectrumEmission_t *additionalSpectrumEmission,
+                              struct MBSFN_SubframeConfigList *mbsfn_SubframeConfigList);
+
+#if defined(Rel10) || defined(Rel14)
+  /// Configure Common PHY parameters from SIB13
+  void (*phy_config_sib13_eNB)(module_id_t Mod_id,int CC_id, int mbsfn_Area_idx,
+                               long mbsfn_AreaId_r9);
+
+  void (*phy_config_dedicated_scell_eNB)(uint8_t Mod_id,
+                                         uint16_t rnti,
+                                         SCellToAddMod_r10_t *sCellToAddMod_r10,
+                                         int CC_id);
+#endif
+
+  /// PHY-Config-Dedicated eNB
+  void (*phy_config_dedicated_eNB)(module_id_t Mod_id,int CC_id,rnti_t rnti,
+                                   struct PhysicalConfigDedicated *physicalConfigDedicated);
+
+#if defined(Rel10) || defined(Rel14)
+  /// Get MCH sdu and corresponding MCS for particular MBSFN subframe
+  MCH_PDU* (*get_mch_sdu)(module_id_t Mod_id, int CC_id, frame_t frameP,sub_frame_t subframe);
+#endif
+  // configure the cba rnti at the physical layer
+  void (*phy_config_cba_rnti)(module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uint8_t index, uint16_t cba_rnti, uint8_t cba_group_id, uint8_t num_active_cba_groups);
+  /// get delta mcs for fast UL AMC
+  int16_t (*estimate_ue_tx_power)(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs);
+
+  int (*mac_phy_remove_ue)(module_id_t Mod_idP,rnti_t rntiP);
+  /// UE functions
+
+  /// reset the ue phy
+  void (*phy_reset_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
+
+  /// Indicate loss of synchronization of PBCH for this eNB to MAC layer
+  void (*out_of_sync_ind)(module_id_t Mod_id,frame_t frameP,uint16_t eNB_index);
+
+  ///  Send a received SI sdu
+  void (*ue_decode_si)(module_id_t Mod_id,int CC_id,frame_t frameP, uint8_t CH_index, void *pdu, uint16_t len);
+
+  ///  Send a received Paging sdu
+  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,sub_frame_t subframe,uint8_t *sdu,uint16_t sdu_len,uint8_t CH_index);
+
+#if defined(Rel10) || defined(Rel14)
+  /// Send a received MCH sdu to MAC
+  void (*ue_send_mch_sdu)(module_id_t Mod_id,uint8_t CC_id, frame_t frameP,uint8_t *sdu,uint16_t sdu_len,uint8_t eNB_index,uint8_t sync_area);
+
+  /// Function to check if UE PHY needs to decode MCH for MAC
+  /// get the sync area id, and return MCS value if need to decode, otherwise -1
+  int (*ue_query_mch)(module_id_t Mod_id, uint8_t CC_id,frame_t frameP,sub_frame_t subframe,uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active);
+#endif
+
+  /// Retrieve ULSCH sdu from MAC
+  void (*ue_get_sdu)(module_id_t Mod_id,int CC_id,frame_t frameP,sub_frame_t subframe, uint8_t CH_index,uint8_t *ulsch_buffer,uint16_t buflen,uint8_t *access_mode);
+
+  /// Retrieve RRCConnectionReq from MAC
+  PRACH_RESOURCES_t* (*ue_get_rach)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t Msg3_flag,sub_frame_t subframe);
+
+  /// Process Random-Access Response
+  uint16_t (*ue_process_rar)(module_id_t Mod_id,int CC_id,frame_t frameP, uint16_t ra_rnti, uint8_t *dlsch_buffer, uint16_t *t_crnti,uint8_t preamble_index, uint8_t* selected_rar_buffer);
+
+  /// Get SR payload (0,1) from UE MAC
+  uint32_t (*ue_get_SR)(module_id_t Mod_id,int CC_id,frame_t frameP,uint8_t eNB_id,rnti_t rnti,sub_frame_t subframe);
+
+  /// Indicate synchronization with valid PBCH
+  void (*dl_phy_sync_success) (module_id_t Mod_id,frame_t frameP, uint8_t CH_index,uint8_t first_sync);
+
+  /// Only calls the PDCP for now
+  UE_L2_STATE_t (*ue_scheduler)(module_id_t Mod_id, frame_t rxFrameP,sub_frame_t rxSubframe, frame_t txFrameP,sub_frame_t txSubframe, lte_subframe_t direction, uint8_t eNB_id, int CC_id);
+
+  /// PHY-Config-Dedicated UE
+  void (*phy_config_dedicated_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+                                  struct PhysicalConfigDedicated *physicalConfigDedicated);
+
+  /// PHY-Config-harq UE
+  void (*phy_config_harq_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+                             uint16_t max_harq_tx);
+  /// Configure Common PHY parameters from SIB1
+  void (*phy_config_sib1_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+                             TDD_Config_t *tdd_config,
+                             uint8_t SIwindowsize,
+                             uint16_t SIperiod);
+
+  /// Configure Common PHY parameters from SIB2
+  void (*phy_config_sib2_ue)(module_id_t Mod_id,int CC_id,uint8_t CH_index,
+                             RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
+                             ARFCN_ValueEUTRA_t *ul_CArrierFreq,
+                             long *ul_Bandwidth,
+                             AdditionalSpectrumEmission_t *additionalSpectrumEmission,
+                             struct MBSFN_SubframeConfigList  *mbsfn_SubframeConfigList);
+
+#if defined(Rel10) || defined(Rel14)
+  /// Configure Common PHY parameters from SIB13
+  void (*phy_config_sib13_ue)(uint8_t Mod_id,int CC_id, uint8_t eNB_index,int mbsfn_Area_idx,
+                              long mbsfn_AreaId_r9);
+
+  void (*phy_config_dedicated_scell_ue)(uint8_t Mod_id,
+                                        uint8_t eNB_index,
+                                        SCellToAddMod_r10_t *sCellToAddMod_r10,
+                                        int CC_id);
+#endif
+  /// Configure Common PHY parameters from mobilityControlInfo
+  void (*phy_config_afterHO_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
+                                MobilityControlInfo_t *mobilityControlInfo,
+                                uint8_t ho_failed);
+
+  /// Function to indicate failure of contention resolution or RA procedure
+  void (*ra_failed)(module_id_t Mod_id, uint8_t CC_id,uint8_t eNB_index);
+
+  /// Function to indicate success of contention resolution or RA procedure
+  void (*ra_succeeded)(module_id_t Mod_id,uint8_t CC_id, uint8_t eNB_index);
+
+  /// Function to indicate the transmission of msg1/rach to MAC
+  void (*Msg1_transmitted)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t eNB_id);
+
+  /// Function to indicate Msg3 transmission/retransmission which initiates/reset Contention Resolution Timer
+  void (*Msg3_transmitted)(module_id_t Mod_id,uint8_t CC_id,frame_t frameP,uint8_t eNB_id);
+
+  /// Function to pass inter-cell measurement parameters to PHY (cell Ids)
+  void (*phy_config_meas_ue)(module_id_t Mod_id,uint8_t CC_id,uint8_t eNB_index,uint8_t n_adj_cells,uint32_t *adj_cell_id);
+
+  // PHY Helper Functions
+
+  /// RIV computation from PHY
+  uint16_t (*computeRIV)(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs);
+
+  /// Downlink TBS table lookup from PHY
+  uint32_t (*get_TBS_DL)(uint8_t mcs, uint16_t nb_rb);
+
+  /// Uplink TBS table lookup from PHY
+  uint32_t (*get_TBS_UL)(uint8_t mcs, uint16_t nb_rb);
+
+  /// Function to retrieve the HARQ round index for a particular UL/DLSCH and harq_pid
+  int (*get_ue_active_harq_pid)(module_id_t Mod_id, uint8_t CC_id,rnti_t rnti, int frame, uint8_t subframe, uint8_t *harq_pid, uint8_t *round, uint8_t ul_flag);
+
+  /// Function to retrieve number of CCE
+  uint16_t (*get_nCCE_max)(module_id_t Mod_id,uint8_t  CC_id,int num_pdcch_symbols,int subframe);
+
+
+  int (*get_nCCE_offset)(int *CCE_table,
+                         const unsigned char L,
+                         const int nCCE,
+                         const int common_dci,
+                         const unsigned short rnti,
+                         const unsigned char subframe);
+
+  /// Function to retrieve number of PRB in an rb_alloc
+  uint32_t (*get_nb_rb)(uint8_t ra_header, uint32_t rb_alloc, int n_rb_dl);
+
+  /// Function to convert VRB to PRB for distributed allocation
+  uint32_t (*get_prb)(int N_RB_DL,int odd_slot,int vrb,int Ngap);
+
+  /// Function to retrieve transmission mode for UE
+  uint8_t (*get_transmission_mode)(module_id_t Mod_id,uint8_t CC_id,rnti_t rnti);
+
+  /// Function to retrieve rb_alloc bitmap from dci rballoc field and VRB type
+  uint32_t (*get_rballoc)(vrb_t vrb_type, uint16_t rb_alloc_dci);
+
+  /// Function for UE MAC to retrieve current PHY connectivity mode (PRACH,RA_RESPONSE,PUSCH)
+  UE_MODE_t (*get_ue_mode)(module_id_t Mod_id, uint8_t CC_id,uint8_t eNB_index);
+
+  /// Function for UE MAC to retrieve measured Path Loss
+  int16_t (*get_PL)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
+
+  /// Function for UE MAC to retrieve the rssi
+  uint32_t (*get_RSSI)(uint8_t Mod_id,uint8_t CC_id);
+
+  /// Function for UE MAC to retrieve the total gain
+  uint32_t (*get_rx_total_gain_dB)(uint8_t Mod_id,uint8_t CC_id);
+
+  /// Function for UE MAC to retrieve the number of adjustent cells
+  uint8_t (*get_n_adj_cells)(uint8_t Mod_id,uint8_t CC_id);
+
+  /// Function for UE MAC to retrieve RSRP/RSRQ measurements
+  uint32_t (*get_RSRP)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
+
+  /// Function for UE MAC to retrieve RSRP/RSRQ measurements
+  uint32_t (*get_RSRQ)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index);
+
+  /// Function for UE MAC to set the layer3 filtered RSRP/RSRQ measurements
+  uint8_t (*set_RSRP_filtered)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp);
+
+  /// Function for UE MAC to set the layer3 filtered RSRP/RSRQ measurements
+  uint8_t (*set_RSRQ_filtered)(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index,float rsrp);
+
+  /// Function for UE/eNB MAC to retrieve number of PRACH in TDD
+  uint8_t (*get_num_prach_tdd)(LTE_DL_FRAME_PARMS *frame_parms);
+
+  /// Function for UE/eNB MAC to retrieve f_id of particular PRACH resource in TDD
+  uint8_t (*get_fid_prach_tdd)(LTE_DL_FRAME_PARMS *frame_parms,uint8_t tdd_map_index);
+
+  /// Function for eNB MAC to retrieve subframe direction
+  lte_subframe_t (*get_subframe_direction)(module_id_t Mod_id, uint8_t CC_id, uint8_t subframe);
+
+  // MAC Helper functions
+  /// Function for UE/PHY to compute PUSCH transmit power in power-control procedure (Po_NOMINAL_PUSCH parameter)
+  int8_t (*get_Po_NOMINAL_PUSCH)(module_id_t Mod_id,uint8_t  CC_id);
+
+  /// Function for UE/PHY to compute PUSCH transmit power in power-control procedure (deltaP_rampup parameter)
+  int8_t (*get_deltaP_rampup)(module_id_t Mod_id,uint8_t CC_id);
+
+  /// Function for UE/PHY to compute PHR
+  int8_t (*get_PHR)(module_id_t Mod_id, uint8_t CC_id,uint8_t eNB_index);
+
+  /// Function for UE to process the timing advance command
+  void (*process_timing_advance)(module_id_t Mod_id,uint8_t CC_id, int16_t timing_advance);
+  
+  /// Function for MAC to get the UE stats from the PHY   
+  LTE_eNB_UE_stats* (*get_eNB_UE_stats)(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti);
+
+  /// get the frame parameters from the PHY
+  LTE_DL_FRAME_PARMS* (*get_lte_frame_parms)(module_id_t Mod_id, uint8_t CC_id);
+  
+  /// get the Multiuser mimo mode
+  MU_MIMO_mode* (*get_mu_mimo_mode) (module_id_t Mod_id, uint8_t CC_id, rnti_t rnti);
+
+  /// get the delta TF for Uplink Power Control Calculation
+  int16_t (*get_hundred_times_delta_TF) (module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid);
+  /// get target PUSCH received power 
+  int16_t (*get_target_pusch_rx_power) (module_id_t module_idP, uint8_t CC_id);
+  /// get target PUSCH received power 
+  int16_t (*get_target_pucch_rx_power) (module_id_t module_idP, uint8_t CC_id);
+
+  unsigned char is_cluster_head;
+  unsigned char is_primary_cluster_head;
+  unsigned char is_secondary_cluster_head;
+  unsigned char cluster_head_index;
+
+  /// PHY Frame Configuration
+  LTE_DL_FRAME_PARMS *frame_parms;
+
+  uint8_t (*get_prach_prb_offset)(LTE_DL_FRAME_PARMS *frame_parms, uint8_t tdd_mapindex, uint16_t Nf); 
+
+  int (*is_prach_subframe)(LTE_DL_FRAME_PARMS *frame_parms,frame_t frame, uint8_t subframe);
+
+  /// ICIC algos
+  uint8_t (*get_SB_size)(uint8_t n_rb_dl);
+  ///end ALU's algo
+
+} MAC_xface;
+
+*/
+
+#endif
+
+
+/** @} */
diff --git a/openair2/NR_UE_PHY_INTERFACE/extern.h b/openair2/NR_UE_PHY_INTERFACE/extern.h
new file mode 100644
index 0000000000..b87fa42fe4
--- /dev/null
+++ b/openair2/NR_UE_PHY_INTERFACE/extern.h
@@ -0,0 +1,27 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef __PHY_INTERFACE_EXTERN_H__
+#define __PHY_INTERFACE_EXTERN_H__
+
+
+
+#endif
diff --git a/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c
new file mode 100644
index 0000000000..06e06d096d
--- /dev/null
+++ b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.c
@@ -0,0 +1,283 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*________________________mac_phy_primitives.c________________________
+
+ Authors : Hicham Anouar, Raymond Knopp
+ Company : EURECOM
+ Emails  : anouar@eurecom.fr,  knopp@eurecom.fr
+________________________________________________________________*/
+
+
+//#include "openair_extern.h"
+
+#ifdef MAC_CONTEXT
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/extern.h"
+//#include "extern.h"
+#include "defs.h"
+#endif //MAC_CONTEXT
+
+
+//#define DEBUG_UE_DECODE_SACH
+//#define DEBUG_NODEB_DECODE_SACH
+
+#ifdef PHY_CONTEXT
+#ifdef PHY_EMUL
+#include "extern.h"
+#include "SIMULATION/simulation_defs.h"
+#else //PHY_EMUL
+#include "MAC_INTERFACE/extern.h"
+#endif //PHY_EMUL
+
+void clear_macphy_data_req(unsigned char Mod_id)
+{
+  //msg("CLEAR DATA_REQ\n");
+  unsigned char i;
+
+  Macphy_req_table[Mod_id].Macphy_req_cnt = 0;
+
+  for (i=0; i<NB_REQ_MAX; i++)
+    Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active = 0;
+}
+
+/*
+unsigned char phy_resources_compare(PHY_RESOURCES *Phy1,PHY_RESOURCES* Phy2 ){
+
+  if(Phy1->Time_alloc==Phy2->Time_alloc && Phy1->Freq_alloc==Phy2->Freq_alloc)// && Phy1->Coding_fmt==Phy2->Coding_fmt && Phy1->Seq_index==Phy2->Seq_index)
+    return 1;
+  else
+    return 0;
+
+}
+*/
+
+MACPHY_DATA_REQ_TABLE_ENTRY* find_data_req_entry(unsigned char Mod_id,MACPHY_REQ_ENTRY_KEY *Search_key)
+{
+
+  unsigned char i;
+
+  //msg("[MAC_PHY]MAC_PHY_REQUEST_CNT=%d\n",Macphy_req_table.Macphy_req_cnt);
+  if (Macphy_req_table[Mod_id].Macphy_req_cnt > 0) {
+#ifdef DEBUG_PHY
+    //    msg("[MACPHY_FIND_REQ] SEARCH KEY=%d\n",Search_key->Key_type);
+#endif //DEBUG_PHY
+    //msg("[MACPHY_FIND_REQ] SEARCH KEY=%d, NB_REQ_MAX=%d\n",Search_key->Key_type,NB_REQ_MAX);
+
+    switch(Search_key->Key_type) {
+    case PDU_TYPE_KEY:
+      for(i=0; i<NB_REQ_MAX; i++) {
+        if ( (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type==Search_key->Key.Pdu_type) &&
+             (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) ) {
+          //msg("[MACPHY_FIND] MACPHY_req_table_entry=%p,idx=%d,Phy_resources %p",       &Macphy_req_table.Macphy_req_table_entry[i],i,Macphy_req_table.Macphy_req_table_entry[i].Macphy_data_req.Phy_Resources_Entry);
+          return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]);
+        }
+      }
+
+      break;
+      /*
+      case LCHAN_KEY:
+      for(i=0;i<NB_REQ_MAX;i++){
+      if ((Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Lchan_id.Index==Search_key->Key.Lchan_id->Index) &&
+      (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) )
+      return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]);
+      }
+      break;
+
+      case PHY_RESOURCES_KEY:
+      for(i=0;i<NB_REQ_MAX;i++){
+      if(Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1)
+      if ( ( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Time_alloc ==
+        Search_key->Key.Phy_resources.Time_alloc )
+         &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc ==
+       Search_key->Key.Phy_resources.Freq_alloc )
+         &&( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.CH_index ==
+      Search_key->CH_index )
+         && ( Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Direction == RX))
+      return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i]);
+      }
+      break;
+      */
+    }
+  }
+
+#ifndef PHY_EMUL
+  //  msg("[PHY][PHY_MAC] Frame %d : No data request\n",mac_xface->frame);
+#endif //PHY_EMUL
+
+
+  return (MACPHY_DATA_REQ_TABLE_ENTRY*)0;
+
+}
+
+
+
+
+
+
+void print_active_requests(unsigned char Mod_id)
+{
+
+  int i;
+  msg("_________________________INST %d , FRAME %d ACTIVE_REQUESTS_________________\n",Mod_id,mac_xface->frame);
+
+  for (i=0; i<NB_REQ_MAX; i++) {
+
+    if (Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Active == 1) {
+      msg("[MACPHY][DATA][REQ] Request %d: Direction %d, Pdu_type %d\n",
+          i,
+          Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Direction,
+          Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type);
+      //    Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Lchan_id.Index);
+      //    Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources,
+      //    Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Time_alloc,
+      //    Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Phy_resources->Freq_alloc);
+      //if(Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Pdu_type==RACH)
+      //msg("[RACH_REQ] Rach_pdu %p, Payload %p\n",Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu,
+      //    Macphy_req_table[Mod_id].Macphy_req_table_entry[i].Macphy_data_req.Dir.Req_rx.Pdu.Rach_pdu->Rach_payload);
+
+    }
+  }
+}
+
+
+/*___________________________________________________________________________________________________*/
+#define RCNT Macphy_req_table[Mod_id].Macphy_req_cnt
+
+MACPHY_DATA_REQ *new_macphy_data_req(unsigned char Mod_id)
+{
+  /*___________________________________________________________________________________________________*/
+  unsigned char i;
+
+
+
+  for (i=0; i<NB_REQ_MAX; i++) {
+    if (Macphy_req_table[Mod_id].Macphy_req_table_entry[(i)%NB_REQ_MAX].Active == 0) {
+      Macphy_req_table[Mod_id].Macphy_req_table_entry[(i)%NB_REQ_MAX].Active = 1;
+      RCNT = (RCNT + 1)%NB_REQ_MAX;
+      //            msg("[MAC_PHY]NEW MAC_REQUEST_CNT=%d,frame %d, Module %d, entry %d \n",Macphy_req_table[Mod_id].Macphy_req_cnt,mac_xface->frame,Mod_id,i);
+      //        Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req.Phy_resources=(PHY_RESOURCES*)malloc16(sizeof(PHY_RESOURCES));
+      return(&Macphy_req_table[Mod_id].Macphy_req_table_entry[i%NB_REQ_MAX].Macphy_data_req);
+    }
+  }
+
+  msg("[OPENAIR][MAC][ERROR] frame %d: No more DATA_REQ !!!!\n",mac_xface->frame);
+
+  print_active_requests(Mod_id);
+  mac_xface->macphy_exit("new_macphy_data_req: no more DATA_REQ");
+  //rt_sleep(nano2count(2000));
+
+  return((MACPHY_DATA_REQ*)0);
+}
+
+
+#endif //PHY_CONTEXT
+
+#ifdef MAC_CONTEXT
+#include "LAYER2/MAC/extern.h"
+
+// Function called by PHY to indicate available data/measurements for MAC
+
+/*___________________________________________________________________________________________________*/
+void macphy_data_ind(unsigned char Mod_id,unsigned char Pdu_type,void *pdu,unsigned short rnti)
+{
+  /*___________________________________________________________________________________________________*/
+  //msg("[OPENAIR][MACPHY] Calling mac_resp In\n");
+
+  int i;
+
+  //  if (Req_rx->crc_status[0]!= -1) {  //CRC_STATUS
+
+  // msg("[OPENAIR][MACPHY] Calling mac_indicate In\n");
+  //     Req_rx->Meas.UL_meas=&UL_meas[Mod_id];
+  //   Req_rx->Meas.DL_meas=&DL_meas[Mod_id];
+
+  switch (Pdu_type) {
+  case ULSCH:
+
+    //        msg("[OPENAIR][MACPHY] Received RACH, Sending to MAC\n");
+    nodeb_decode_ulsch(Mod_id,(ULSCH_PDU *)pdu,rnti);
+
+    break;
+
+  case DLSCH:
+#ifdef DEBUG_UE_DECODE_SACH
+    msg("[MAC][UE][MAC_PHY] TTI %d Inst %d\n",mac_xface->frame,Mod_id);
+#endif
+
+    //      ue_decode_dlsch(Mod_id-NB_CH_INST,
+    //          (DLSCH_PDU *)pdu,rnti);
+
+    break;
+
+  default:
+    break;
+  }
+
+  //    msg("Freeing Req %p\n",Macphy_data_req_table_entry);
+  //  }
+
+}
+
+
+
+
+
+/*PHY_RESOURCES_TABLE_ENTRY *new_phy_resources() {
+
+
+  unsigned char i;
+
+  //msg("[OPENAIR][PHY][MAC Interface] New Phy Resource, cnt %d\n",Phy_resources_table.Phy_resources_cnt);
+
+  for (i=0;i<NB_PHY_RESOURCES_MAX;i++){
+
+    if (Phy_resources_table.Phy_resources_table_entry[(i+Phy_resources_table.Phy_resources_cnt+1)%NB_PHY_RESOURCES_MAX].Active == 0) {
+      Phy_resources_table.Phy_resources_table_entry[(i+Phy_resources_table.Phy_resources_cnt+1)%NB_PHY_RESOURCES_MAX].Active = 1;
+      Phy_resources_table.Phy_resources_cnt = (Phy_resources_table.Phy_resources_cnt + 1)%NB_PHY_RESOURCES_MAX;
+      //  msg("[OPENAIR][PHY][MAC Interface] NEW PHY_RESOURCES: Taking index %d\n\n",(i+Phy_resources_table.Phy_resources_cnt+1)%NB_PHY_RESOURCES_MAX);
+
+      return(&Phy_resources_table.Phy_resources_table_entry[(i+Phy_resources_table.Phy_resources_cnt)%NB_PHY_RESOURCES_MAX]);
+    }
+  }
+  msg("[OPENAIR][MAC][ERROR] No more PHY_RESOURCES !!!!\n");
+  exit(-1);
+}
+*/
+
+#endif //MAC_CONTEXT
+
+
+// Measurements, etc ..
+
+//short phy_resource_cnt = 0, macphy_data_req_cnt = 0, macphy_data_ind_cnt = 0;
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h
new file mode 100644
index 0000000000..889cb503dc
--- /dev/null
+++ b/openair2/NR_UE_PHY_INTERFACE/mac_phy_primitives.h
@@ -0,0 +1,232 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*________________________mac_phy_primitives.h________________________
+
+ Authors : Hicham Anouar, Raymond Knopp
+ Company : EURECOM
+ Emails  : anouar@eurecom.fr,  knopp@eurecom.fr
+________________________________________________________________*/
+
+
+#ifndef __MAC_PHY_PRIMITIVES_H__
+#    define __MAC_PHY_PRIMITIVES_H__
+
+#include "../LAYER2/MAC/defs.h"
+
+
+/**@defgroup _mac_phy_primitives_ MAC Layer Primitives for Communications with PHY
+ *@ingroup w3g4f_mac_layer_
+ *@{
+
+This subclause describes the primitives for communications between the MAC and PHY sub-layers.
+
+The primitives for dynamic MAC-PHY PDU exchange (Transport channel interface) are:
+
+- MACPHY_DATA_REQ: transfers or requests a PDU from PHY.  The data is passed along with the dynamic PHY transmission
+format (coding and modulation, time/freq/space resource allocation)
+
+- MACPHY_DATA_IND: Function call (by PHY) to deliver a new PDU and corresponding measurements to MAC.  This implicitly confirms the MACPHY_DATA_REQ by
+filling the fields of the request (TX or RX) with the data and measurements.
+
+One primitive is used for semi-static configuration (during logical channel establishment)
+relaying the puncturing/repetition patterns for HARQ:
+
+- MACPHY_CONFIG_SACH_HARQ_REQ (still to be defined...)
+
+The primitive for static (re)configuration is:
+- MACPHY_CONFIG_REQ : This primitive transports the initial configuration during the setup phase of equipment, both for CH and UE.
+Static configuration is used during the initialization phase of the equipment.  For a CH, it is done prior to any communication.  For a UE, some
+structures may be set after receiving configuration information from the network via the BCCH/CCCH.
+*/
+
+
+
+
+/*! \brief MACPHY-DATA-REQ_RX structure is used to request transfer a new PDU from PHY corresponding to a particular transport channel*/
+typedef struct {
+  int crc_status[MAX_NUMBER_TB_PER_LCHAN];                   /*!< This field indicates the CRC status of the PDU upon reception from PHY*/
+  unsigned char num_tb;                /*!< This field indicates the number of transport blocks to be received*/
+  unsigned short tb_size_bytes;        /*!< This field indicates the number of bytes per transpor block*/
+  unsigned int Active_process_map;   /*!< HARQ indicator for active processes*/
+  union {
+    CHBCH_PDU   *Chbch_pdu;        /*!< This is a pointer to CHBCH data*/
+    DL_SACH_PDU *DL_sach_pdu;      /*!< This is a pointer to DL_SACH data*/
+    UL_SACH_PDU *UL_sach_pdu;      /*!< This is a pointer to UL_SACH data*/
+    RACH_PDU    *Rach_pdu;         /*!< This is a pointer to RACH data*/
+    MRBCH_PDU   *Mrbch_pdu;        /*!< This is a pointer to MRBCH data*/
+  } Pdu;
+  union {
+    DL_MEAS *DL_meas;   /*!< This is an array of pointers to the current measurements of DL quality at UE (indexed by CH_id) */
+    UL_MEAS *UL_meas;   /*!< This is an array of pointers to the current measurements of UL quality at Node-B (indexed by user_id) */
+  } Meas;
+} MACPHY_DATA_REQ_RX;
+
+
+/*! \brief MACPHY-DATA-REQ_TX structure is used to transfer a new PDU to PHY corresponding to a particular transport channel*/
+typedef struct {
+  unsigned char num_tb;             /*!< This field indicates the number of transport blocks to be received*/
+  unsigned short tb_size_bytes;     /*!< This field indicates the number of bytes per transpor block*/
+  unsigned int Active_process_map;   /*!< HARQ indicator for active processes*/
+  unsigned int New_process_map;      /*!< HARQ indicator for new processes*/
+  //  unsigned char round_indices_tx;
+  union {
+    CHBCH_PDU   *Chbch_pdu;      /*!< pointer to CHBCH data */
+    DL_SACH_PDU DL_sach_pdu;    /*!< pointer to DL_SACH data*/
+    UL_SACH_PDU UL_sach_pdu;    /*!< pointer to UL_SACH data*/
+    RACH_PDU Rach_pdu;  //H.A   /*!< pointer to RACH data */
+    MRBCH_PDU   *Mrbch_pdu;     /*!< pointer to MRBCH data */
+  } Pdu;
+} MACPHY_DATA_REQ_TX;
+
+/*! \brief MACPHY-DATA-REQ primitive is used to transfer a new PDU to PHY corresponding to a particular transport channel*/
+typedef struct {
+  unsigned char Direction;
+  unsigned char Pdu_type;                 /*!< This field indicates the type of PDU requested */
+  LCHAN_ID      Lchan_id;                 /*!< This field indicates the flow id of the PDU */
+  PHY_RESOURCES *Phy_resources;           /*!< This field indicates to PHY the physical resources */
+  unsigned int format_flag;               /*!< This field indicates to PHY something about a SACH, e.g. presense of SACCH*/
+  union {
+    MACPHY_DATA_REQ_RX Req_rx;            /*!< This field contains the request corresponding to an RX resource*/
+    MACPHY_DATA_REQ_TX Req_tx;            /*!< This field contains the request corresponding to a TX resource*/
+  } Dir;
+} MACPHY_DATA_REQ;
+
+/*!\fn void macphy_data_ind(unsigned char Mod_id,MACPHY_DATA_REQ_RX *Req_rx,unsigned char Pdu_type,unsigned short Index);
+\brief MACPHY_DATA_IND function call.  Called by PHY to upload PDU and measurements in response to a MACPHY_DATA_REQ_RX.
+@param Mod_id MAC instance ID (only useful if multiple MAC instances run in the same machine)
+@param Req_rx Pointer to MACPHY_DTA_REQ_RX received previously
+@param Pdu_type Type of PDU (redundant!)
+@param Index CH Index for CH, UEid for UE
+*/
+void macphy_data_ind(unsigned char Mod_id,
+                     MACPHY_DATA_REQ_RX *Req_rx,
+                     unsigned char Pdu_type,
+                     unsigned short Index);
+
+/*! \brief MACPHY-CONFIG-REQ primitive is used to configure a new instance of OpenAirInterface (static configuration) during initialization*/
+typedef struct {
+  PHY_FRAMING Phy_framing;   /*!< Framing Configuration*/
+  PHY_CHSCH Phy_chsch[8];    /*!< CHSCH Static Configuration*/
+  PHY_CHBCH Phy_chbch;       /*!< CHBCH Static Configuration*/
+  PHY_SCH   Phy_sch[8];      /*!< SCH Static Configuration*/
+  PHY_SACH  Phy_sach;        /*!< SACH Statuc Configuration*/
+} MACPHY_CONFIG_REQ;
+
+/*! \brief MACPHY-CONFIG-SACH-HARQ-REQ primitive is used to configure a new SACH transport channel (dynamic configuration) during logical channel establishment*/
+//typedef struct {
+//  LCHAN_ID Lchan_id;             /*!< This is the identifier of the SACH, which should simply be the logical channel id*/
+//  HARQ_PARAMS Harq_params;           /*!< This is the set of HARQ parameters corresponding to the QoS description of the logical channel*/
+//} MACPHY_CONFIG_SACH_HARQ_REQ;
+
+/** @} */
+
+#define MAX_NUMBER_OF_MAC_INSTANCES 16
+
+#define NULL_PDU 255
+#define CHBCH 0
+#define DL_SACH 1
+#define UL_SACH 2
+#define UL_SACCH_SACH 3
+#define RACH 4
+#define MRBCH 5
+
+
+#define NUMBER_OF_SUBBANDS 64
+#define LCHAN_KEY 0
+#define PDU_TYPE_KEY 1
+#define PHY_RESOURCES_KEY 2
+
+typedef struct Macphy_req_entry_key {
+  unsigned char Key_type;
+  union {
+    LCHAN_ID *Lchan_id;  //SACH, EMULATION
+    unsigned char Pdu_type;//CHBCH, RACH, EMULATION
+    PHY_RESOURCES Phy_resources;//REAL PHY
+  } Key;
+} MACPHY_REQ_ENTRY_KEY;
+
+/** @ingroup _PHY_TRANSPORT_CHANNEL_PROCEDURES_
+ * @{
+\var typedef struct Macphy_data_req_table_entry {
+  MACPHY_DATA_REQ Macphy_data_req;
+  unsigned char Active;
+} MACPHY_DATA_REQ_TABLE_ENTRY;
+\brief An entry in the MACPHY_DATA_REQ Table.
+*/
+
+typedef struct Macphy_data_req_table_entry {
+  /// The MACPHY_DATA_REQ Structure itself
+  MACPHY_DATA_REQ Macphy_data_req;
+  /// Active flag.  Active=1 means that the REQ is pending.
+  unsigned char Active;
+} MACPHY_DATA_REQ_TABLE_ENTRY;
+
+/*!\var typedef struct  {
+  MACPHY_DATA_REQ_TABLE_ENTRY *Macphy_req_table_entry;
+  unsigned int Macphy_req_cnt;
+} MACPHY_DATA_REQ_TABLE
+\brief The MACPHY_DATA_REQ interface between MAC and PHY.  This table stores the pending requests from MAC which are serviced by PHY.  The pointer Macphy_req_table_entry points
+to an array of idle reqests allocated during initialization of the MAC-layer.
+*/
+
+typedef struct  {
+  /// Pointer to a MACPHY_DATA_REQ
+  MACPHY_DATA_REQ_TABLE_ENTRY *Macphy_req_table_entry;
+  /// Number of active requests
+  unsigned int Macphy_req_cnt;
+} MACPHY_DATA_REQ_TABLE;
+
+/** @} */
+
+/*typedef struct Tx_Phy_Pdu{                              //H.A
+  PHY_RESOURCES *Phy_resources;
+  MACPHY_DATA_IND *Macphy_data_ind;
+}T_PHY_PDU;
+
+typedef struct Rx_Phy_Pdu{                              //H.A
+  PHY_RESOURCES *Phy_resources;
+  char *Phy_payload;
+  }RX_PHY_PDU;*/
+
+
+typedef struct GRANTED_LCHAN_TABLE_ENTRY {
+  PHY_RESOURCES *Phy_resources;
+  LCHAN_ID Lchan_id;
+} GRANTED_LCHAN_TABLE_ENTRY;
+
+void clear_macphy_data_req(uint8_t);
+//void clean_macphy_interface(void);
+unsigned char phy_resources_compare(PHY_RESOURCES *,PHY_RESOURCES*);
+MACPHY_DATA_REQ_TABLE_ENTRY* find_data_req_entry(uint8_t,MACPHY_REQ_ENTRY_KEY*);
+void print_active_requests(uint8_t);
+void mac_process_meas_ul(uint8_t Mod_id,UL_MEAS *UL_meas, uint16_t Index);
+void mac_process_meas_dl(uint8_t Mod_id,DL_MEAS *DL_meas, uint16_t Index);
+
+
+
+
+MACPHY_DATA_REQ *new_macphy_data_req(uint8_t);
+//PHY_RESOURCES_TABLE_ENTRY *new_phy_resources(void);
+//MACPHY_DATA_IND *new_macphy_data_ind(void);
+#endif
+
+
diff --git a/openair2/NR_UE_PHY_INTERFACE/vars.h b/openair2/NR_UE_PHY_INTERFACE/vars.h
new file mode 100644
index 0000000000..566f4347b6
--- /dev/null
+++ b/openair2/NR_UE_PHY_INTERFACE/vars.h
@@ -0,0 +1,44 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef __PHY_INTERFACE_VARS_H__
+#define __PHY_INTERFACE_VARS_H__
+
+//#include "SIMULATION/PHY_EMULATION/spec_defs.h"
+#include "defs.h"
+
+#ifdef PHY_EMUL
+#include "SIMULATION/PHY_EMULATION/DEVICE_DRIVER/defs.h"
+#include "SIMULATION/simulation_defs.h"
+#endif
+
+
+unsigned int mac_debug;
+
+//MAC_xface *mac_xface;
+
+//MACPHY_PARAMS MACPHY_params;
+
+unsigned int mac_registered;
+
+
+#endif
+
-- 
GitLab