diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 56f1fe2d5b7e86b10974af95cf929c62e895a513..783d89a7e82ffb57ca63689f272e7b2b01b6c6bb 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -311,7 +311,7 @@ if (NOT ${ret} STREQUAL 0)
 endif (NOT ${ret} STREQUAL 0)
 file(GLOB rrc_source ${RRC_FULL_DIR}/*.c)
 set(rrc_source  ${rrc_source} ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1_msg.c)
-set(rrc_source  ${rrc_source} ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1_msg_nb_iot.c)
+set(rrc_source  ${rrc_source} ${OPENAIR2_DIR}/RRC/LITE/MESSAGES/asn1_msg_NB_IoT.c)
 file(GLOB rrc_h ${RRC_FULL_DIR}/*.h)
 set(rrc_h ${rrc_h} ${RRC_FULL_DIR}/asn1_constants.h)
 set_source_files_properties(${rrc_source} PROPERTIES COMPILE_FLAGS -w) # suppress warnings from generated code
@@ -567,6 +567,12 @@ add_boolean_option(MESSAGE_CHART_GENERATOR_PHY     False "trace some PHY exchang
 
 add_boolean_option(FLEXRAN_AGENT_SB_IF             False         "enable FlexRAN agent to inteface with a SDN controller")
 
+################################################################
+# NB-IOT
+################################################################
+add_boolean_option(NB_IOT True "Enabling NB-IoT code")
+
+
 ########################
 # Include order
 ##########################
@@ -959,12 +965,15 @@ add_library(SECU_CN ${SECU_CN_SRC})
 ################################"
 set(SCHED_SRC
   ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_eNb.c
-  ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_eNb_nb_iot.c
+  ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_eNb_NB_IoT.c
   ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_ue.c
   ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common.c
+  ${OPENAIR1_DIR}/SCHED/phy_procedures_lte_common_NB_IoT.c
   ${OPENAIR1_DIR}/SCHED/phy_mac_stub.c
+  ${OPENAIR1_DIR}/SCHED/IF_Module_L1_primitives_NB_IoT.c
   ${OPENAIR1_DIR}/SCHED/pucch_pc.c
   ${OPENAIR1_DIR}/SCHED/pusch_pc.c
+  ${OPENAIR1_DIR}/SCHED/pusch_pc_NB_IoT.c
   ${OPENAIR1_DIR}/SCHED/srs_pc.c
 )
 add_library(SCHED_LIB ${SCHED_SRC})
@@ -976,34 +985,50 @@ set(PHY_SRC
   ${RRC_FULL_DIR}/asn1_constants.h
   # actual source
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pss.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/npss_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/sss.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/nsss_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pilots_mbsfn.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_coding.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_coding_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_modulation.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_modulation_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_demodulation.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_llr_computation.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/power_control.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_decoding.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_scrambling.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dlsch_scrambling_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_tools_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/uci_tools.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/uci_tools_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_mcs_NB_IoT.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/lte_Isc_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pbch.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/npbch_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/dci_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/phich.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pcfich.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pucch.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/prach.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/nprach_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pmch.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/pch.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/group_hopping_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/srs_modulation.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/drs_modulation.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_modulation.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_coding.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_decoding.c
+  ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/ulsch_decoding_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/rar_tools.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/print_stats.c
   ${OPENAIR1_DIR}/PHY/LTE_TRANSPORT/initial_sync.c
@@ -1017,37 +1042,48 @@ set(PHY_SRC
   ${OPENAIR1_DIR}/PHY/MODULATION/beamforming.c
   ${OPENAIR1_DIR}/PHY/MODULATION/compute_bf_weights.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization.c
+  ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/freq_equalization_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_time.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_sync_timefreq.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync.c
+  ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_adjust_sync_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_channel_estimation.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_bf_channel_estimation.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_dl_mbsfn_channel_estimation.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation.c
+  ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ul_channel_estimation_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_est_freq_offset.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_ue_measurements.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/lte_eNB_measurements.c
   ${OPENAIR1_DIR}/PHY/LTE_ESTIMATION/adjust_gain.c
   ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_cell_spec.c
-  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_uespec.c
-  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold.c
+  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_cell_spec_NB_IoT.c
+  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_uespec.c   
+  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold.c   
+  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold_NB_IoT.c   
   ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_gold_mbsfn.c
   ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_dl_mbsfn.c
   ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_ul_ref.c
+  ${OPENAIR1_DIR}/PHY/LTE_REFSIG/lte_ul_ref_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/CODING/lte_segmentation.c
+  ${OPENAIR1_DIR}/PHY/CODING/lte_segmentation_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte.c
+  ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/CODING/ccoding_byte_lte.c
   ${OPENAIR1_DIR}/PHY/CODING/3gpplte_sse.c
   ${OPENAIR1_DIR}/PHY/CODING/crc_byte.c
+  ${OPENAIR1_DIR}/PHY/CODING/crc_byte_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_8bit.c
   ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_sse_16bit.c
   ${OPENAIR1_DIR}/PHY/CODING/3gpplte_turbo_decoder_avx2_16bit.c
   ${OPENAIR1_DIR}/PHY/CODING/lte_rate_matching.c
+  ${OPENAIR1_DIR}/PHY/CODING/lte_rate_matching_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/CODING/rate_matching.c
   ${OPENAIR1_DIR}/PHY/CODING/viterbi.c
   ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte.c
+  ${OPENAIR1_DIR}/PHY/CODING/viterbi_lte_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/INIT/lte_init.c
-  ${OPENAIR1_DIR}/PHY/INIT/lte_init_nb_iot.c
+  ${OPENAIR1_DIR}/PHY/INIT/lte_init_NB_IoT.c
   ${OPENAIR1_DIR}/PHY/INIT/lte_parms.c
   ${OPENAIR1_DIR}/PHY/INIT/lte_param_init.c
   ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
@@ -1077,12 +1113,15 @@ add_library(PHY ${PHY_SRC})
 #####################
 set(MAC_DIR ${OPENAIR2_DIR}/LAYER2/MAC)
 set(RLC_DIR ${OPENAIR2_DIR}/LAYER2/RLC)
+set(PHY_INTERFACE_DIR ${OPENAIR2_DIR}/PHY_INTERFACE)
 set(RLC_UM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/UM_v9.3.0)
 set(RLC_AM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/AM_v9.3.0)
 set(RLC_TM_DIR ${OPENAIR2_DIR}/LAYER2/RLC/TM_v9.3.0)
 set(RRC_DIR ${OPENAIR2_DIR}/RRC/LITE)
 set(PDCP_DIR  ${OPENAIR2_DIR}/LAYER2/PDCP_v10.1.0)
 set(L2_SRC
+  ${PHY_INTERFACE_DIR}/IF_Module_NB_IoT.c
+  ${PHY_INTERFACE_DIR}/IF_Module_L2_primitives_NB_IoT.c
   ${OPENAIR2_DIR}/LAYER2/openair2_proc.c
   ${PDCP_DIR}/pdcp.c
   ${PDCP_DIR}/pdcp_fifo.c
@@ -1118,38 +1157,42 @@ set(L2_SRC
   ${RLC_DIR}/rlc.c
   ${RLC_DIR}/rlc_rrc.c
   ${RLC_DIR}/rlc_mpls.c
-  ${RRC_DIR}/vars_nb_iot.c
   ${RRC_DIR}/rrc_UE.c
   ${RRC_DIR}/rrc_eNB.c
-  ${RRC_DIR}/rrc_eNB_nb_iot.c
+  ${RRC_DIR}/rrc_eNB_NB_IoT.c
   ${RRC_DIR}/rrc_eNB_S1AP.c
   ${RRC_DIR}/rrc_eNB_UE_context.c
+  ${RRC_DIR}/rrc_eNB_UE_context_NB_IoT.c
   ${RRC_DIR}/rrc_common.c
-  ${RRC_DIR}/rrc_common_nb_iot.c
+  ${RRC_DIR}/rrc_common_NB_IoT.c
   ${RRC_DIR}/L2_interface.c
-  ${RRC_DIR}/L2_interface_nb_iot.c
+  ${RRC_DIR}/L2_interface_NB_IoT.c
   )
 set (MAC_SRC
   ${MAC_DIR}/lte_transport_init.c
   ${MAC_DIR}/main.c
-  ${MAC_DIR}/IF_Module_nb_iot.c
+  ${MAC_DIR}/main_NB_IoT.c
   ${MAC_DIR}/ue_procedures.c
   ${MAC_DIR}/ra_procedures.c
   ${MAC_DIR}/l1_helpers.c
   ${MAC_DIR}/rar_tools.c
   ${MAC_DIR}/eNB_scheduler.c
+  ${MAC_DIR}/eNB_scheduler_NB_IoT.c
   ${MAC_DIR}/eNB_scheduler_dlsch.c
-  ${MAC_DIR}/eNB_scheduler_dlsch_nb_iot.c
+  ${MAC_DIR}/eNB_scheduler_dlsch_NB_IoT.c
   ${MAC_DIR}/eNB_scheduler_ulsch.c
-  ${MAC_DIR}/eNB_scheduler_ulsch_nb_iot.c
+  ${MAC_DIR}/eNB_scheduler_ulsch_NB_IoT.c
   ${MAC_DIR}/eNB_scheduler_mch.c
   ${MAC_DIR}/eNB_scheduler_bch.c
+  ${MAC_DIR}/eNB_scheduler_bch_NB_IoT.c
   ${MAC_DIR}/eNB_scheduler_primitives.c
-  ${MAC_DIR}/eNB_scheduler_primitives_nb_iot.c
+  ${MAC_DIR}/output_handler_NB_IoT.c
   ${MAC_DIR}/eNB_scheduler_RA.c
-  ${MAC_DIR}/eNB_scheduler_RA_nb_iot.c
+  ${MAC_DIR}/eNB_scheduler_RA_NB_IoT.c
   ${MAC_DIR}/pre_processor.c
   ${MAC_DIR}/config.c
+  ${MAC_DIR}/config_NB_IoT.c
+  ${MAC_DIR}/schedule_tool_NB_IoT.c
  )
 
 if (FLEXRAN_AGENT_SB_IF)
diff --git a/cmake_targets/oaisim_noS1_build_oai/CMakeLists.txt b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.txt
new file mode 100644
index 0000000000000000000000000000000000000000..d600a25f2c74011f030a3dd310879287990311d2
--- /dev/null
+++ b/cmake_targets/oaisim_noS1_build_oai/CMakeLists.txt
@@ -0,0 +1,92 @@
+cmake_minimum_required(VERSION 2.8)
+
+set (  ADDR_CONF False )
+set (  DEBUG_OMG False )
+set (  DISABLE_XER_PRINT False )
+set (  DRIVER2013 True )
+set (  EMOS False )
+set (  ENABLE_FXP True )
+set (  ENABLE_ITTI True )
+set (  ENABLE_NAS_UE_LOGGING False )
+set (  ENABLE_NEW_MULTICAST True )
+set (  ENABLE_PGM_TRANSPORT True )
+set (  ENABLE_RAL False )
+set (  ENABLE_SECURITY False )
+set (  ENABLE_STANDALONE_EPC False)
+set (  ENABLE_USE_CPU_EXECUTION_TIME True )
+set (  ENABLE_USE_MME False )
+set (  ENABLE_USE_RAW_SOCKET_FOR_SGI False)
+set (  ENABLE_VCD_FIFO False )
+set (  ENB_MODE True )
+set (  EXMIMO_IOT True )
+set (  HARD_RT False )
+set (  JUMBO_FRAME True )
+set (  LARGE_SCALE False )
+set (  LINK_ENB_PDCP_TO_GTPV1U False)
+set (  LINUX_LIST False )
+set (  LINUX True )
+set (  LOCALIZATION False )
+set (  LOG_NO_THREAD 1 )
+set (  DEADLINE_SCHEDULER False )
+set (  MAC_CONTEXT 1 )
+set (  MAX_NUM_CCs 1 )
+set (  MESSAGE_CHART_GENERATOR         False )
+set (  MESSAGE_CHART_GENERATOR_RLC_MAC False )
+set (  MESSAGE_CHART_GENERATOR_PHY     False )
+set (  MIH_C_MEDIEVAL_EXTENSIONS False )
+set (  MSG_PRINT False )
+set (  MU_RECEIVER False )
+set (  NAS_ADDRESS_FIX True )
+set (  NAS_BUILT_IN_UE False)
+set (  NAS_MME False )
+set (  NAS_UE False )
+set (  NB_ANTENNAS_RX "2" )
+set (  NB_ANTENNAS_TX "2" )
+set (  NB_ANTENNAS_TXRX "2" )
+set (  NEW_FFT True )
+set (  NO_RRM True )
+set (  OAI_EMU True )
+set (  OAISIM True )
+set (  OAI_NW_DRIVER_TYPE_ETHERNET False )
+set (  OAI_NW_DRIVER_USE_NETLINK True )
+set (  OPENAIR1 True )
+set (  OPENAIR2 True )
+set (  OPENAIR_EMU False )
+set (  OPENAIR_LTE True )
+set (  PACKAGE_NAME "oaisim" )
+set (  PBS_SIM False )
+set (  PDCP_USE_NETLINK True )
+set (  PC_DSP True )
+set (  PC_TARGET True )
+set (  PDCP_MSG_PRINT False )
+set (  PERFECT_CE False )
+set (  PHY_ABSTRACTION True )
+set (  PHY_CONTEXT False )
+set (  PHY_EMUL False )
+set (  PHYSIM True )
+set (  PUCCH True )
+set (  RANDOM_BF False )
+set (  RF_BOARD "False" )
+set (  RRC_ASN1_VERSION "Rel10" )
+set (  RLC_STOP_ON_LOST_PDU False )
+set (  RRC_MSG_PRINT False )
+set (  RTAI False )
+set (  SECU False )
+set (  SMBV False )
+set (  SPECTRA False )
+set (  TEST_OMG False )
+set (  USE_3GPP_ADDR_AS_LINK_ADDR False )
+set (  USE_MME "R10" )
+set (  USER_MODE True )
+set (  XER_PRINT False )
+set (  DEBUG_PHY False )
+set (  DEBUG_PHY_PROC False)
+set (  DEBUG_DLSCH False)
+set ( CMAKE_BUILD_TYPE  )
+set ( CFLAGS_PROCESSOR_USER "" )
+set ( XFORMS True )
+set ( PRINT_STATS True )
+set ( RRC_ASN1_VERSION "Rel14")
+set ( ENABLE_VCD_FIFO False )
+set ( T_TRACER False )
+include(${CMAKE_CURRENT_SOURCE_DIR}/../CMakeLists.txt)
diff --git a/openair1/PHY/CODING/ccoding_byte_NB_IoT.c b/openair1/PHY/CODING/ccoding_byte_NB_IoT.c
index 83c5d49d70b1cbb0f40f20d3abc1902121da2fa0..5b291c9864dfa8861585074f675aefa835a12305 100644
--- a/openair1/PHY/CODING/ccoding_byte_NB_IoT.c
+++ b/openair1/PHY/CODING/ccoding_byte_NB_IoT.c
@@ -12,12 +12,10 @@
 * \warning
 */
 
-#include "defs.h"
-
-#include "defs_NB_IoT.h"
+#include "PHY/CODING/defs_NB_IoT.h"
 
 unsigned char  ccodelte_table_NB_IoT[128];      // for transmitter
-//unsigned char  ccodelte_table_rev[128];  // for receiver
+unsigned short glte_NB_IoT[] = { 0133, 0171, 0165 }; // {A,B} //renaimed but is exactly the same as the one in the old implementation
 
 /*************************************************************************
   Encodes for an arbitrary convolutional code of rate 1/3
@@ -26,15 +24,15 @@ unsigned char  ccodelte_table_NB_IoT[128];      // for transmitter
   An optional 8-bit CRC (3GPP) can be added.
   Trellis tail-biting is included here
 *************************************************************************/
-void ccode_encode_NB_IoT (int32_t numbits,
-						  uint8_t add_crc,
-						  uint8_t *inPtr,
-						  uint8_t *outPtr,
-						  uint16_t rnti)
+void ccode_encode_NB_IoT (int32_t  numbits,
+						              uint8_t  add_crc,
+						              uint8_t  *inPtr,
+						              uint8_t  *outPtr,
+						              uint16_t rnti)
 {
-  uint32_t  state;
+  uint32_t state;
   uint8_t  c, out, first_bit;
-  int8_t shiftbit=0;
+  int8_t   shiftbit=0;
   uint16_t c16;
   uint16_t next_last_byte=0;
   uint32_t crc=0;
@@ -44,23 +42,27 @@ void ccode_encode_NB_IoT (int32_t numbits,
   state = 0;
 
   if (add_crc == 2) {
-    crc = crc16(inPtr,numbits);     // crc is 2 bytes
-    // scramble with RNTI
-    crc ^= (((uint32_t)rnti)<<16);  // XOR with crc
-    first_bit = 2;
-    c = (uint8_t)((crc>>16)&0xff);
+
+      crc = crc16_NB_IoT(inPtr,numbits);     // crc is 2 bytes
+      // scramble with RNTI
+      crc ^= (((uint32_t)rnti)<<16);  // XOR with crc
+      first_bit = 2;
+      c = (uint8_t)((crc>>16)&0xff);
+
   } else {
-    next_last_byte = numbits>>3;
-    first_bit      = (numbits-6)&7;
-    c = inPtr[next_last_byte-1];
+
+      next_last_byte = numbits>>3;
+      first_bit      = (numbits-6)&7;
+      c = inPtr[next_last_byte-1];
   }
 
   // Perform Tail-biting
   // get bits from last byte of input (or crc)
   
   for (shiftbit = 0 ; shiftbit <(8-first_bit) ; shiftbit++) {
-    if ((c&(1<<(7-first_bit-shiftbit))) != 0)
-      state |= (1<<shiftbit);
+
+      if ((c&(1<<(7-first_bit-shiftbit))) != 0)
+          state |= (1<<shiftbit);
   }
 
   state = state & 0x3f;   // true initial state of Tail-biting CCode
@@ -71,20 +73,19 @@ void ccode_encode_NB_IoT (int32_t numbits,
     c = *inPtr++;
 
     for (shiftbit = 7; (shiftbit>=0) && (numbits>0); shiftbit--,numbits--) {
-      state >>= 1;
 
-      if ((c&(1<<shiftbit)) != 0) {
-        state |= 64;
-      }
+        state >>= 1;
 
-      out = ccodelte_table_NB_IoT[state];
+        if ((c&(1<<shiftbit)) != 0) {
+            state |= 64;
+        }
 
-      *outPtr++ = out  & 1;
-      *outPtr++ = (out>>1)&1;
-      *outPtr++ = (out>>2)&1;
+        out = ccodelte_table_NB_IoT[state];
 
+        *outPtr++ = out  & 1;
+        *outPtr++ = (out>>1)&1;
+        *outPtr++ = (out>>2)&1;
     }
-
   }
   
   // now code 16-bit CRC for DCI 						// Tail-biting is applied to CRC bits , input 16 bits , output 48 bits
@@ -93,18 +94,18 @@ void ccode_encode_NB_IoT (int32_t numbits,
     c16 = (uint16_t)(crc>>16);
 	
     for (shiftbit = 15; (shiftbit>=0); shiftbit--) {
-      state >>= 1;
 
-      if ((c16&(1<<shiftbit)) != 0) {
-        state |= 64;
-      }
+        state >>= 1;
 
-      out = ccodelte_table_NB_IoT[state];
+        if ((c16&(1<<shiftbit)) != 0) {
+            state |= 64;
+        }
 
-      *outPtr++ = out  & 1;
-      *outPtr++ = (out>>1)&1;
-      *outPtr++ = (out>>2)&1;  
+        out = ccodelte_table_NB_IoT[state];
 
+        *outPtr++ = out  & 1;
+        *outPtr++ = (out>>1)&1;
+        *outPtr++ = (out>>2)&1;  
     }
   }
 }
@@ -121,6 +122,7 @@ void ccodelte_init_NB_IoT(void)
   unsigned int  i, j, k, sum;
 
   for (i = 0; i < 128; i++) {
+
     ccodelte_table_NB_IoT[i] = 0;
 
     /* Compute 3 output bits */
@@ -128,7 +130,7 @@ void ccodelte_init_NB_IoT(void)
       sum = 0;
 
       for (k = 0; k < 7; k++)
-        if ((i & glte[j]) & (1 << k))
+        if ((i & glte_NB_IoT[j]) & (1 << k))
           sum++;
 
       /* Write the sum modulo 2 in bit j */
diff --git a/openair1/PHY/CODING/crc_byte_NB_IoT.c b/openair1/PHY/CODING/crc_byte_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..bceadfb5afcbdec94b265b95d7aed29af71d6b5e
--- /dev/null
+++ b/openair1/PHY/CODING/crc_byte_NB_IoT.c
@@ -0,0 +1,211 @@
+/*
+ * 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.0  (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: crc_byte.c
+   purpose: generate 3GPP LTE CRCs. Byte-oriented implementation of CRC's
+   author: raymond.knopp@eurecom.fr, matthieu.kanj@b-com.com
+   date: 07/2017
+
+*/
+
+
+#ifndef USER_MODE
+#define __NO_VERSION__
+
+#endif
+
+//#include "PHY/types.h"
+
+//#include "defs.h"   // to delete in final code version
+
+#include "PHY/CODING/defs_NB_IoT.h"  //
+/*ref 36-212 v8.6.0 , pp 8-9 */
+/* the highest degree is set by default */
+unsigned int     poly24a_NB_IoT = 0x864cfb00;   //1000 0110 0100 1100 1111 1011  D^24 + D^23 + D^18 + D^17 + D^14 + D^11 + D^10 + D^7 + D^6 + D^5 + D^4 + D^3 + D + 1
+unsigned int     poly24b_NB_IoT = 0x80006300;    // 1000 0000 0000 0000 0110 0011  D^24 + D^23 + D^6 + D^5 + D + 1
+unsigned int     poly16_NB_IoT = 0x10210000;    // 0001 0000 0010 0001            D^16 + D^12 + D^5 + 1
+unsigned int     poly12_NB_IoT = 0x80F00000;    // 1000 0000 1111                 D^12 + D^11 + D^3 + D^2 + D + 1
+unsigned int     poly8_NB_IoT = 0x9B000000;     // 1001 1011                      D^8  + D^7  + D^4 + D^3 + D + 1
+/*********************************************************
+
+For initialization && verification purposes,
+   bit by bit implementation with any polynomial
+
+The first bit is in the MSB of each byte
+
+*********************************************************/
+unsigned int crcbit_NB_IoT (unsigned char * inputptr, int octetlen, unsigned int poly)
+{
+  unsigned int i, crc = 0, c;
+
+  while (octetlen-- > 0) {
+      
+      c = (*inputptr++) << 24;
+
+      for (i = 8; i != 0; i--) {
+
+          if ((1 << 31) & (c ^ crc))
+
+              crc = (crc << 1) ^ poly;
+
+          else
+        
+              crc <<= 1;
+
+          c <<= 1;
+      }
+  }
+
+  return crc;
+}
+
+/*********************************************************
+
+crc table initialization
+
+*********************************************************/
+static unsigned int        crc24aTable_NB_IoT[256];
+static unsigned int        crc24bTable_NB_IoT[256];
+static unsigned short      crc16Table_NB_IoT[256];
+static unsigned short      crc12Table_NB_IoT[256];
+static unsigned char       crc8Table_NB_IoT[256];
+
+void crcTableInit_NB_IoT (void)
+{
+  unsigned char c = 0;
+
+  do {
+       crc24aTable_NB_IoT[c] = crcbit_NB_IoT (&c, 1, poly24a_NB_IoT);
+       crc24bTable_NB_IoT[c] = crcbit_NB_IoT (&c, 1, poly24b_NB_IoT);
+       crc16Table_NB_IoT[c] = (unsigned short) (crcbit_NB_IoT (&c, 1, poly16_NB_IoT) >> 16);
+       crc12Table_NB_IoT[c] = (unsigned short) (crcbit_NB_IoT (&c, 1, poly12_NB_IoT) >> 16);
+       crc8Table_NB_IoT[c] = (unsigned char) (crcbit_NB_IoT (&c, 1, poly8_NB_IoT) >> 24);
+  } while (++c);
+
+}
+/*********************************************************
+
+Byte by byte implementations,
+assuming initial byte is 0 padded (in MSB) if necessary
+
+*********************************************************/
+unsigned int crc24a_NB_IoT (unsigned char * inptr, int bitlen)
+{
+
+  int            octetlen, resbit;
+  unsigned int   crc = 0;
+  
+  octetlen = bitlen / 8;        /* Change in octets */
+  resbit = (bitlen % 8);
+
+  while (octetlen-- > 0) {
+    
+      crc = (crc << 8) ^ crc24aTable_NB_IoT[(*inptr++) ^ (crc >> 24)];
+
+  }
+
+  if (resbit > 0)
+
+      crc = (crc << resbit) ^ crc24aTable_NB_IoT[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))];
+
+  return crc;
+}
+
+unsigned int crc24b_NB_IoT (unsigned char * inptr, int bitlen)
+{
+
+  int             octetlen, resbit;
+  unsigned int    crc = 0;
+  
+  octetlen = bitlen / 8;        /* Change in octets */
+  resbit = (bitlen % 8);
+
+  while (octetlen-- > 0) {
+
+      crc = (crc << 8) ^ crc24bTable_NB_IoT[(*inptr++) ^ (crc >> 24)];
+
+  }
+
+  if (resbit > 0)
+
+      crc = (crc << resbit) ^ crc24bTable_NB_IoT[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))];
+
+  return crc;
+}
+
+unsigned int crc16_NB_IoT (unsigned char * inptr, int bitlen)
+{
+  int             octetlen, resbit;
+  unsigned int    crc = 0;
+  
+  octetlen = bitlen / 8;        /* Change in octets */
+  resbit = (bitlen % 8);
+
+  while (octetlen-- > 0) {
+
+    crc = (crc << 8) ^ (crc16Table_NB_IoT[(*inptr++) ^ (crc >> 24)] << 16);
+
+  }
+
+  if (resbit > 0)
+
+    crc = (crc << resbit) ^ (crc16Table_NB_IoT[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 16);
+
+  return crc;
+}
+
+unsigned int crc8_NB_IoT (unsigned char * inptr, int bitlen)
+{
+  int             octetlen, resbit;
+  unsigned int             crc = 0;
+  octetlen = bitlen / 8;        /* Change in octets */
+  resbit = (bitlen % 8);
+
+  while (octetlen-- > 0) {
+    crc = crc8Table_NB_IoT[(*inptr++) ^ (crc >> 24)] << 24;
+  }
+
+  if (resbit > 0)
+    crc = (crc << resbit) ^ (crc8Table_NB_IoT[((*inptr) >> (8 - resbit)) ^ (crc >> (32 - resbit))] << 24);
+
+  return crc;
+}
+
+
+//#ifdef DEBUG_CRC
+/*******************************************************************/
+/**
+   Test code
+********************************************************************/
+
+// #include <stdio.h>
+
+// main()
+// {
+//   unsigned char test[] = "Thebigredfox";
+//   crcTableInit();
+//   printf("%x\n", crcbit(test, sizeof(test) - 1, poly24));
+//   printf("%x\n", crc24(test, (sizeof(test) - 1)*8));
+//   printf("%x\n", crcbit(test, sizeof(test) - 1, poly8));
+//   printf("%x\n", crc8(test, (sizeof(test) - 1)*8));
+// }
+//#endif
+
diff --git a/openair1/PHY/CODING/defs_NB_IoT.h b/openair1/PHY/CODING/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..17670ec8bc040dcd03bf73d0438c1fa09b4d1226
--- /dev/null
+++ b/openair1/PHY/CODING/defs_NB_IoT.h
@@ -0,0 +1,275 @@
+/*
+ * 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.0  (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/CODING/defs_NB_IoT.h
+   purpose: Top-level definitions, data types and function prototypes for openairinterface coding blocks for NB-IoT
+   author: matthieu.kanj@b-com.com, raymond.knopp@eurecom.fr, michele.paffetti@studio.unibo.it
+   date: 29.06.2017
+*/
+
+#ifndef OPENAIR1_PHY_CODING_DEFS_NB_IOT_H_
+#define OPENAIR1_PHY_CODING_DEFS_NB_IOT_H_
+
+#include <stdint.h>  // for uint8/16/32_t
+
+/* check if this ifndef is required for NB-IoT ?!
+//#ifndef NO_OPENAIR1
+//#include "PHY/defs_NB_IoT.h"
+//#else
+//#include "PHY/TOOLS/time_meas.h"
+//#endif
+*/
+
+#define CRC24_A_NB_IoT 0
+#define CRC24_B_NB_IoT 1
+#define CRC16_NB_IoT 2
+#define CRC8_NB_IoT 3
+
+//#define MAX_TURBO_ITERATIONS_MBSFN 8  // no MBSFN
+#define MAX_TURBO_ITERATIONS_NB_IoT 4
+
+#define LTE_NULL_NB_IoT 2  // defined also in PHY/LTE_TRANSPORT/defs_NB_IoT.h
+
+/** \fn uint32_t sub_block_interleaving_cc(uint32_t D, uint8_t *d,uint8_t *w)
+\brief This is the subblock interleaving algorithm for convolutionally coded blocks from 36-212 (Release 13.4, 2017).
+This function takes the d-sequence and generates the w-sequence.  The nu-sequence from 36-212 is implicit.
+\param D Number of input bits
+\param d Pointer to input (d-sequence, convolutional code output)
+\param w Pointer to output (w-sequence, interleaver output)
+\returns Interleaving matrix cardinality (\f$K_{\pi}\f$  from 36-212)
+*/
+uint32_t sub_block_interleaving_cc_NB_IoT(uint32_t D, uint8_t *d,uint8_t *w);
+
+/**
+\brief This is the NB-IoT rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI).  It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
+\param RCC R^CC_subblock from subblock interleaver (number of rows in interleaving matrix) for up to 8 segments
+\param E Number of coded channel bits
+\param w This is a pointer to the w-sequence (second interleaver output)
+\param e This is a pointer to the e-sequence (rate matching output, channel input/output bits)
+\returns \f$E\f$, the number of coded bits per segment */
+
+uint32_t lte_rate_matching_cc_NB_IoT(uint32_t RCC,      // RRC = 2
+				     				 uint16_t E,        // E = 1600
+				     				 uint8_t *w,	// length
+				    				 uint8_t *e);	// length 1600
+
+/** \fn void ccodelte_encode(int32_t numbits,uint8_t add_crc, uint8_t *inPtr,uint8_t *outPtr,uint16_t rnti)
+\brief This function implements the LTE convolutional code of rate 1/3
+  with a constraint length of 7 bits. The inputs are bit packed in octets
+(from MSB to LSB). Trellis tail-biting is included here.
+@param numbits Number of bits to encode
+@param add_crc crc to be appended (8 bits) if add_crc = 1
+@param inPtr Pointer to input buffer
+@param outPtr Pointer to output buffer
+@param rnti RNTI for CRC scrambling
+*/
+
+void ccode_encode_NB_IoT (int32_t numbits,
+						  uint8_t add_crc,
+						  uint8_t *inPtr,
+						  uint8_t *outPtr,
+						  uint16_t rnti);
+
+/*!\fn void ccodelte_init(void)
+\brief This function initializes the generator polynomials for an LTE convolutional code.*/
+void ccodelte_init_NB_IoT(void);
+
+/*!\fn void crcTableInit(void)
+\brief This function initializes the different crc tables.*/
+void crcTableInit_NB_IoT (void);
+
+
+/*!\fn uint32_t crc24a(uint8_t *inPtr, int32_t bitlen)
+\brief This computes a 24-bit crc ('a' variant for overall transport block)
+based on 3GPP UMTS/LTE specifications.
+@param inPtr Pointer to input byte stream
+@param bitlen length of inputs in bits
+*/
+uint32_t crc24a_NB_IoT (uint8_t *inPtr, int32_t bitlen);
+
+/*!\fn uint32_t crc24b(uint8_t *inPtr, int32_t bitlen)
+\brief This computes a 24-bit crc ('b' variant for transport-block segments)
+based on 3GPP UMTS/LTE specifications.
+@param inPtr Pointer to input byte stream
+@param bitlen length of inputs in bits
+*/
+uint32_t crc24b_NB_IoT (uint8_t *inPtr, int32_t bitlen);
+
+/*!\fn uint32_t crc16(uint8_t *inPtr, int32_t bitlen)
+\brief This computes a 16-bit crc based on 3GPP UMTS specifications.
+@param inPtr Pointer to input byte stream
+@param bitlen length of inputs in bits*/
+uint32_t crc16_NB_IoT (uint8_t *inPtr, int32_t bitlen);
+
+/*!\fn uint32_t crc8(uint8_t *inPtr, int32_t bitlen)
+\brief This computes a 8-bit crc based on 3GPP UMTS specifications.
+@param inPtr Pointer to input byte stream
+@param bitlen length of inputs in bits*/
+uint32_t crc8_NB_IoT  (uint8_t *inPtr, int32_t bitlen);
+
+
+
+
+
+
+uint32_t crcbit_NB_IoT (uint8_t * ,
+                 		int32_t,
+                 		uint32_t);
+
+
+/*!\fn void phy_viterbi_lte_sse2(int8_t *y, uint8_t *decoded_bytes, uint16_t n)
+\brief This routine performs a SIMD optmized Viterbi decoder for the LTE 64-state tail-biting convolutional code.
+@param y Pointer to soft input (coded on 8-bits but should be limited to 4-bit precision to avoid overflow)
+@param decoded_bytes Pointer to decoded output
+@param n Length of input/trellis depth in bits*/
+//void phy_viterbi_lte_sse2(int8_t *y,uint8_t *decoded_bytes,uint16_t n);
+void phy_viterbi_lte_sse2_NB_IoT(int8_t *y,uint8_t *decoded_bytes,uint16_t n);
+
+/** \fn void sub_block_deinterleaving_cc(uint32_t D, int8_t *d,int8_t *w)
+\brief This is the subblock deinterleaving algorithm for convolutionally-coded data from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
+This function takes the w-sequence and generates the d-sequence.  The nu-sequence from 36-212 is implicit.
+\param D Number of input bits
+\param d Pointer to output (d-sequence, turbo code output)
+\param w Pointer to input (w-sequence, interleaver output)
+*/
+void sub_block_deinterleaving_cc_NB_IoT(uint32_t D,int8_t *d,int8_t *w);
+
+
+/*
+\brief This is the LTE rate matching algorithm for Convolutionally-coded channels (e.g. BCH,DCI,UCI).  It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
+\param RCC R^CC_subblock from subblock interleaver (number of rows in interleaving matrix)
+\param E This the number of coded bits allocated for channel
+\param w This is a pointer to the soft w-sequence (second interleaver output) with soft-combined outputs from successive HARQ rounds
+\param dummy_w This is the first row of the interleaver matrix for identifying/discarding the "LTE-NULL" positions
+\param soft_input This is a pointer to the soft channel output
+\returns \f$E\f$, the number of coded bits per segment
+*/
+void lte_rate_matching_cc_rx_NB_IoT(uint32_t RCC,
+                             		uint16_t E,
+                             		int8_t *w,
+                             		uint8_t *dummy_w,
+                             		int8_t *soft_input);
+
+/** \fn generate_dummy_w_cc(uint32_t D, uint8_t *w)
+\brief This function generates a dummy interleaved sequence (first row) for receiver (convolutionally-coded data), in order to identify the NULL positions used to make the matrix complete.
+\param D Number of systematic bits plus 4 (plus 4 for termination)
+\param w This is the dummy sequence (first row), it will contain zeros and at most 31 "LTE_NULL" values
+\returns Interleaving matrix cardinality (\f$K_{\pi}\f$ from 36-212)
+*/
+uint32_t generate_dummy_w_cc_NB_IoT(uint32_t D, uint8_t *w);
+
+/** \fn lte_segmentation(uint8_t *input_buffer,
+              uint8_t **output_buffers,
+            uint32_t B,
+            uint32_t *C,
+            uint32_t *Cplus,
+            uint32_t *Cminus,
+            uint32_t *Kplus,
+            uint32_t *Kminus,
+            uint32_t *F)
+\brief This function implements the LTE transport block segmentation algorithm from 36-212, V8.6 2009-03.
+@param input_buffer
+@param output_buffers
+@param B
+@param C
+@param Cplus
+@param Cminus
+@param Kplus
+@param Kminus
+@param F
+*/
+int32_t lte_segmentation_NB_IoT(uint8_t *input_buffer,
+                         		uint8_t **output_buffers,
+                         		uint32_t B,
+                         		uint32_t *C,
+                         		uint32_t *Cplus,
+                         		uint32_t *Cminus,
+                         		uint32_t *Kplus,
+                         		uint32_t *Kminus,
+                         		uint32_t *F);
+
+/** \fn void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d,int16_t *w)
+\brief This is the subblock deinterleaving algorithm from 36-212 (Release 8, 8.6 2009-03), pages 15-16.
+This function takes the w-sequence and generates the d-sequence.  The nu-sequence from 36-212 is implicit.
+\param D Number of systematic bits plus 4 (plus 4 for termination)
+\param d Pointer to output (d-sequence, turbo code output)
+\param w Pointer to input (w-sequence, interleaver output)
+*/
+//*****************void sub_block_deinterleaving_turbo(uint32_t D, int16_t *d,int16_t *w);
+
+/**
+\brief This is the LTE rate matching algorithm for Turbo-coded channels (e.g. DLSCH,ULSCH).  It is taken directly from 36-212 (Rel 8 8.6, 2009-03), pages 16-18 )
+\param RTC R^TC_subblock from subblock interleaver (number of rows in interleaving matrix)
+\param G This the number of coded transport bits allocated in sub-frame
+\param w This is a pointer to the soft w-sequence (second interleaver output) with soft-combined outputs from successive HARQ rounds
+\param dummy_w This is the first row of the interleaver matrix for identifying/discarding the "LTE-NULL" positions
+\param soft_input This is a pointer to the soft channel output
+\param C Number of segments (codewords) in the sub-frame
+\param Nsoft Total number of soft bits (from UE capabilities in 36-306)
+\param Mdlharq Number of HARQ rounds
+\param Kmimo MIMO capability for this DLSCH (0 = no MIMO)
+\param rvidx round index (0-3)
+\param clear 1 means clear soft buffer (start of HARQ round)
+\param Qm modulation order (2,4,6)
+\param Nl number of layers (1,2)
+\param r segment number
+\param E_out the number of coded bits per segment
+\returns 0 on success, -1 on failure
+*/
+
+// int lte_rate_matching_turbo_rx(uint32_t RTC,
+//                                uint32_t G,
+//                                int16_t *w,
+//                                uint8_t *dummy_w,
+//                                int16_t *soft_input,
+//                                uint8_t C,
+//                                uint32_t Nsoft,
+//                                uint8_t Mdlharq,
+//                                uint8_t Kmimo,
+//                                uint8_t rvidx,
+//                                uint8_t clear,
+//                                uint8_t Qm,
+//                                uint8_t Nl,
+//                                uint8_t r,
+//                                uint32_t *E_out);
+
+// uint32_t lte_rate_matching_turbo_rx_abs(uint32_t RTC,
+//                                         uint32_t G,
+//                                         double *w,
+//                                         uint8_t *dummy_w,
+//                                         double *soft_input,
+//                                         uint8_t C,
+//                                         uint32_t Nsoft,
+//                                         uint8_t Mdlharq,
+//                                         uint8_t Kmimo,
+//                                         uint8_t rvidx,
+//                                         uint8_t clear,
+//                                         uint8_t Qm,
+//                                         uint8_t Nl,
+//                                         uint8_t r,
+//                                         uint32_t *E_out);
+
+void ccode_encode_npdsch_NB_IoT (int32_t   numbits,
+								 uint8_t   *inPtr,
+								 uint8_t   *outPtr,
+								 uint32_t  crc);
+
+#endif /* OPENAIR1_PHY_CODING_DEFS_NB_IOT_H_ */
diff --git a/openair1/PHY/CODING/lte_rate_matching_NB_IoT.c b/openair1/PHY/CODING/lte_rate_matching_NB_IoT.c
index 37aa3a2ee867914a9c54f26ef3a4ed14d5dacc54..e680e6d090f59123aa9b75136a57131d0ca59088 100644
--- a/openair1/PHY/CODING/lte_rate_matching_NB_IoT.c
+++ b/openair1/PHY/CODING/lte_rate_matching_NB_IoT.c
@@ -12,62 +12,149 @@
 * \warning
 */
 
+/* // check if this ifdef MAIN is required for NB-IoT
 #ifdef MAIN
 #include <stdio.h>
 #include <stdlib.h>
 #endif
-#include "PHY/defs.h"
-#include "assertions.h"
+*/
 
+//#include "PHY/CODING/defs_NB_IoT.h"
 #include "PHY/defs_NB_IoT.h"
+//#include "assertions.h"
+
+//#include "PHY/LTE_REFSIG/defs_NB_IoT.h"   // does this file is needed ?
 
-static uint32_t bitrev_cc[32] = {1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31,0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30};
+static uint32_t bitrev_cc_NB_IoT[32] = {1,17,9,25,5,21,13,29,3,19,11,27,7,23,15,31,0,16,8,24,4,20,12,28,2,18,10,26,6,22,14,30};
 
 uint32_t sub_block_interleaving_cc_NB_IoT(uint32_t D, uint8_t *d,uint8_t *w)
 {
-  uint32_t RCC = (D>>5), ND, ND3;   // D = 50 ,  
+    uint32_t RCC = (D>>5), ND, ND3;   // D = 50 ,  
+    uint32_t row,col,Kpi,index;
+    uint32_t index3,k;
+
+    if ((D&0x1f) > 0)
+        RCC++;
+
+    Kpi = (RCC<<5); 					// Kpi = 32
+    ND = Kpi - D;
+    ND3 = ND*3;   					  // ND3 = ND*3 = 18 *3 = 54
+    k=0;
+
+    for (col=0; col<32; col++) {
+
+      index = bitrev_cc_NB_IoT[col];
+      index3 = 3*index;
+
+        for (row=0; row<RCC; row++) {
+
+          w[k]          =   d[(int32_t)index3-(int32_t)ND3];
+          w[Kpi+k]      =   d[(int32_t)index3-(int32_t)ND3+1];
+          w[(Kpi<<1)+k] =   d[(int32_t)index3-(int32_t)ND3+2];
+
+          index3+=96;
+          index+=32;
+          k++;
+        }
+    }
+    return(RCC);
+}
+
+
+uint32_t lte_rate_matching_cc_NB_IoT(uint32_t  RCC,      // RRC = 2
+				                             uint16_t  E,        // E = 1600
+				                             uint8_t   *w,	     // length
+				                             uint8_t   *e)	     // length 1600
+{
+  uint32_t ind=0,k;
+  uint16_t Kw = 3*(RCC<<5);   				  // 3*64 = 192
+
+  for (k=0; k<E; k++) {
+
+    while(w[ind] == LTE_NULL_NB_IoT) {
+
+      ind++;
+
+      if (ind==Kw)
+        ind=0;
+    }
+
+    e[k] = w[ind];
+    ind++;
+
+    if (ind==Kw)
+      ind=0;
+  }
+
+  return(E);
+}
+
+//******************* below functions related to uplink transmission , to be reviwed *********
+// this function should be adapted to NB-IoT , this deinterleaving is for LTE
+void sub_block_deinterleaving_cc_NB_IoT(uint32_t D,int8_t *d,int8_t *w)
+{
+
+  //WANG_Hao uint32_t RCC = (D>>5), ND, ND3;
+  uint32_t RCC = (D>>5);
+  ptrdiff_t   ND, ND3;
   uint32_t row,col,Kpi,index;
-  uint32_t index3,k;
+  //WANG_Hao uint32_t index3,k;
+  ptrdiff_t index3;
+  uint32_t k;
 
   if ((D&0x1f) > 0)
     RCC++;
 
-  Kpi = (RCC<<5); 					// Kpi = 32
+  Kpi = (RCC<<5);
+  //  Kpi3 = Kpi*3;
   ND = Kpi - D;
-  ND3 = ND*3;   					// ND3 = ND*3 = 18 *3 = 54
+
+  ND3 = ND*3;
+
   k=0;
 
   for (col=0; col<32; col++) {
 
-    index = bitrev_cc[col];
+    index = bitrev_cc_NB_IoT[col];
     index3 = 3*index;
 
     for (row=0; row<RCC; row++) {
-      w[k]          =   d[(int32_t)index3-(int32_t)ND3];
-      w[Kpi+k]      =   d[(int32_t)index3-(int32_t)ND3+1];
-      w[(Kpi<<1)+k] =   d[(int32_t)index3-(int32_t)ND3+2];
+
+      d[index3-ND3]   = w[k];
+      d[index3-ND3+1] = w[Kpi+k];
+      d[index3-ND3+2] = w[(Kpi<<1)+k];
 
       index3+=96;
       index+=32;
       k++;
     }
   }
-  return(RCC);
+
 }
 
 
-uint32_t lte_rate_matching_cc_NB_IoT(uint32_t RCC,      // RRC = 2
-				     uint16_t E,        // E = 1600
-				     uint8_t *w,	// length
-				     uint8_t *e)	// length 1600
+
+void lte_rate_matching_cc_rx_NB_IoT(uint32_t RCC,
+                                    uint16_t E,
+                                    int8_t *w,
+                                    uint8_t *dummy_w,
+                                    int8_t *soft_input)
 {
+
+
+
   uint32_t ind=0,k;
+  uint16_t Kw = 3*(RCC<<5);
+  uint32_t acc=1;
+  int16_t w16[Kw];
 
-  uint16_t Kw = 3*(RCC<<5);   				  // 3*64 = 192
+  memset(w,0,Kw);
+  memset(w16,0,Kw*sizeof(int16_t));
 
   for (k=0; k<E; k++) {
 
-    while(w[ind] == LTE_NULL) {
+
+    while(dummy_w[ind] == LTE_NULL_NB_IoT) {
 
       ind++;
 
@@ -75,12 +162,62 @@ uint32_t lte_rate_matching_cc_NB_IoT(uint32_t RCC,      // RRC = 2
         ind=0;
     }
 
-    e[k] = w[ind];
+ 
+    w16[ind] += soft_input[k];
+
     ind++;
 
-    if (ind==Kw)
+    if (ind==Kw) {
       ind=0;
+      acc++;
+    }
   }
 
-  return(E);
+  // rescale
+  for (ind=0; ind<Kw; ind++) {
+    //    w16[ind]=(w16[ind]/acc);
+    if (w16[ind]>7)
+      w[ind]=7;
+    else if (w16[ind]<-8)
+      w[ind]=-8;
+    else
+      w[ind]=(int8_t)w16[ind];
+  }
+
+}
+
+
+uint32_t generate_dummy_w_cc_NB_IoT(uint32_t D, uint8_t *w)
+{
+
+  uint32_t RCC = (D>>5), ND;
+  uint32_t col,Kpi,index;
+  int32_t k;
+
+  if ((D&0x1f) > 0)
+    RCC++;
+
+  Kpi = (RCC<<5);
+  //  Kpi3 = Kpi*3;
+  ND = Kpi - D;
+
+  // copy d02 to dD2 (for mod Kpi operation from clause (4), p.16 of 36.212
+  k=0;
+
+  for (col=0; col<32; col++) {
+
+    index = bitrev_cc_NB_IoT[col];
+
+    if (index<ND) {
+      w[k]          = LTE_NULL_NB_IoT;
+      w[Kpi+k]      = LTE_NULL_NB_IoT;
+      w[(Kpi<<1)+k] = LTE_NULL_NB_IoT;
+
+    }
+
+
+    k+=RCC;
+  }
+
+  return(RCC);
 }
diff --git a/openair1/PHY/CODING/lte_segmentation_NB_IoT.c b/openair1/PHY/CODING/lte_segmentation_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..6620a66d557ec090e192aeddb4851cb67ee1562f
--- /dev/null
+++ b/openair1/PHY/CODING/lte_segmentation_NB_IoT.c
@@ -0,0 +1,152 @@
+/*
+ * 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.0  (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: lte_segmentation.c
+   purpose: Procedures for transport block segmentation for LTE (turbo-coded transport channels)
+   author: raymond.knopp@eurecom.fr
+   date: 21.10.2009
+*/
+#include "PHY/defs_NB_IoT.h"
+#include "SCHED/extern_NB_IoT.h"
+
+//#define DEBUG_SEGMENTATION
+
+int lte_segmentation_NB_IoT(unsigned char *input_buffer,
+                            unsigned char **output_buffers,
+                            unsigned int B,
+                            unsigned int *C,
+                            unsigned int *Cplus,
+                            unsigned int *Cminus,
+                            unsigned int *Kplus,
+                            unsigned int *Kminus,
+                            unsigned int *F)
+{
+
+  unsigned int L,Bprime,Bprime_by_C,r,Kr,k,s,crc;
+
+  if (B<=6144) {
+    L=0;
+    *C=1;
+    Bprime=B;
+  } else {
+    L=24;
+    *C = B/(6144-L);
+
+    if ((6144-L)*(*C) < B)
+      *C=*C+1;
+
+    Bprime = B+((*C)*L);
+  }
+
+  if ((*C)>MAX_NUM_DLSCH_SEGMENTS_NB_IoT) {
+      LOG_E(PHY,"lte_segmentation.c: too many segments %d, B %d, L %d, Bprime %d\n",*C,B,L,Bprime);
+    return(-1);
+  }
+
+  // Find K+
+  Bprime_by_C  = Bprime/(*C);
+
+  if (Bprime_by_C <= 40) {
+    *Kplus = 40;
+    *Kminus = 0;
+  } else if (Bprime_by_C<=512) { // increase by 1 byte til here
+    *Kplus = (Bprime_by_C>>3)<<3;
+    *Kminus = Bprime_by_C-8;
+  } else if (Bprime_by_C <=1024) { // increase by 2 bytes til here
+    *Kplus = (Bprime_by_C>>4)<<4;
+
+    if (*Kplus < Bprime_by_C)
+      *Kplus = *Kplus + 16;
+
+    *Kminus = (*Kplus - 16);
+  } else if (Bprime_by_C <= 2048) { // increase by 4 bytes til here
+    *Kplus = (Bprime_by_C>>5)<<5;
+
+    if (*Kplus < Bprime_by_C)
+      *Kplus = *Kplus + 32;
+
+    *Kminus = (*Kplus - 32);
+  } else if (Bprime_by_C <=6144 ) { // increase by 8 bytes til here
+
+    *Kplus = (Bprime_by_C>>6)<<6;
+
+
+    if (*Kplus < Bprime_by_C)
+      *Kplus = *Kplus + 64;
+
+    *Kminus = (*Kplus - 64);
+  } else {
+    msg("lte_segmentation.c: Illegal codeword size !!!\n");
+    return(-1);
+  }
+
+  if (*C == 1) {
+    *Cplus = *C;
+    *Kminus = 0;
+    *Cminus = 0;
+  } else {
+
+    //    printf("More than one segment (%d), exiting \n",*C);
+    //    exit(-1);
+    *Cminus = ((*C)*(*Kplus) - (Bprime))/((*Kplus) - (*Kminus));
+    *Cplus  = (*C) - (*Cminus);
+  }
+
+  *F = ((*Cplus)*(*Kplus) + (*Cminus)*(*Kminus) - (Bprime));
+
+  if ((input_buffer) && (output_buffers)) {
+
+    for (k=0; k<*F>>3; k++) {
+      output_buffers[0][k] = 0;
+    }
+
+    s=0;
+
+    for (r=0; r<*C; r++) {
+
+      if (r<*Cminus)
+        Kr = *Kminus;
+      else
+        Kr = *Kplus;
+
+      while (k<((Kr - L)>>3)) {
+        output_buffers[r][k] = input_buffer[s];
+	//	printf("encoding segment %d : byte %d (%d) => %d\n",r,k,Kr>>3,input_buffer[s]);
+        k++;
+        s++;
+      }
+
+      if (*C > 1) { // add CRC
+        crc = crc24b_NB_IoT(output_buffers[r],Kr-24)>>8;
+        output_buffers[r][(Kr-24)>>3] = ((uint8_t*)&crc)[2];
+        output_buffers[r][1+((Kr-24)>>3)] = ((uint8_t*)&crc)[1];
+        output_buffers[r][2+((Kr-24)>>3)] = ((uint8_t*)&crc)[0];
+
+      }
+
+      k=0;
+    }
+  }
+
+  return(0);
+}
+
+
diff --git a/openair1/PHY/CODING/viterbi_lte_NB_IoT.c b/openair1/PHY/CODING/viterbi_lte_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..9f67381c441a2f24718c68e1d6264e86c7ba5425
--- /dev/null
+++ b/openair1/PHY/CODING/viterbi_lte_NB_IoT.c
@@ -0,0 +1,336 @@
+/*
+ * 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.0  (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: viterbit_lte.c
+   purpose: SIMD optimized LTE Viterbi Decoder for rate 1/3 Tail-biting convolutional code.  Performs two iterations
+            of code.  First pass does Viterbi with all initial partial metrics set to zero.  Second pass does Viterbi
+            with initial partial metrics set to values from final state values after first pass. Max is selected at
+      end to do trace-back.
+   author: raymond.knopp@eurecom.fr
+   date: 21.10.2009
+*/
+
+#ifdef USER_MODE
+#include <stdio.h>
+#endif
+
+#ifndef TEST_DEBUG
+#include "PHY/defs.h"
+#include "PHY/extern.h"
+#else
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#define msg printf
+#endif
+
+
+#include "PHY/sse_intrin.h"
+
+//extern uint8_t ccodelte_table[128],ccodelte_table_rev[128];
+
+
+
+
+static int8_t m0_table[64*16*16*16] __attribute__ ((aligned(16)));
+static int8_t m1_table[64*16*16*16] __attribute__ ((aligned(16)));
+
+
+
+void phy_viterbi_lte_sse2_NB_IoT(int8_t *y,uint8_t *decoded_bytes,uint16_t n)
+{
+
+
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i  TB[4*8192];
+  __m128i *m0_ptr,*m1_ptr,*TB_ptr = &TB[0];
+  
+  __m128i metrics0_15,metrics16_31,metrics32_47,metrics48_63,even0_30a,even0_30b,even32_62a,even32_62b,odd1_31a,odd1_31b,odd33_63a,odd33_63b,TBeven0_30,TBeven32_62,TBodd1_31,
+    TBodd33_63;
+  
+  __m128i min_state,min_state2;
+
+#elif defined(__arm__)
+  uint8x16x2_t TB[2*8192];  // 2 int8x16_t per input bit, 8 bits / byte, 8192 is largest packet size in bits
+
+  uint8x16_t even0_30a,even0_30b,even32_62a,even32_62b,odd1_31a,odd1_31b,odd33_63a,odd33_63b,TBeven0_30,TBeven32_62,TBodd1_31,TBodd33_63;
+  uint8x16x2_t metrics0_31,metrics32_63;
+
+  uint8x16_t min_state;
+
+  uint8x16_t *m0_ptr,*m1_ptr;
+  uint8x16x2_t *TB_ptr = &TB[0];
+
+
+#endif
+  int8_t *in = y;
+  uint8_t prev_state0,maxm,s;
+  static uint8_t *TB_ptr2;
+  uint32_t table_offset;
+  uint8_t iter;
+  int16_t position;
+
+  // set initial metrics
+  //debug_msg("Doing viterbi\n");
+
+#if defined(__x86_64__) || defined(__i386__)
+
+  metrics0_15  = _mm_setzero_si128();
+  metrics16_31 = _mm_setzero_si128();
+  metrics32_47 = _mm_setzero_si128();
+  metrics48_63 = _mm_setzero_si128();
+#elif defined(__arm__)
+    metrics0_31.val[0]  = vdupq_n_u8(0); 
+    metrics0_31.val[1]  = vdupq_n_u8(0);
+    metrics32_63.val[0] = vdupq_n_u8(0);
+    metrics32_63.val[1] = vdupq_n_u8(0);
+#endif
+
+  for (iter=0; iter<2; iter++) {
+    in = y;
+    TB_ptr=&TB[0];
+
+    for (position=0; position<n; position++) {
+
+
+      // get branch metric offsets for the 64 states
+      table_offset = (in[0]+8 + ((in[1]+8)<<4) + ((in[2]+8)<<8))<<6;
+
+#if defined(__x86_64__) || defined(__i386__)
+      m0_ptr = (__m128i *)&m0_table[table_offset];
+      m1_ptr = (__m128i *)&m1_table[table_offset];
+
+      // even states
+      even0_30a  = _mm_adds_epu8(metrics0_15,m0_ptr[0]);
+      even32_62a = _mm_adds_epu8(metrics16_31,m0_ptr[1]);
+      even0_30b  = _mm_adds_epu8(metrics32_47,m0_ptr[2]);
+      even32_62b = _mm_adds_epu8(metrics48_63,m0_ptr[3]);
+
+
+      // odd states
+      odd1_31a   = _mm_adds_epu8(metrics0_15,m1_ptr[0]);
+      odd33_63a  = _mm_adds_epu8(metrics16_31,m1_ptr[1]);
+      odd1_31b   = _mm_adds_epu8(metrics32_47,m1_ptr[2]);
+      odd33_63b  = _mm_adds_epu8(metrics48_63,m1_ptr[3]);
+
+      // select maxima
+
+      even0_30a  = _mm_max_epu8(even0_30a,even0_30b);
+      even32_62a = _mm_max_epu8(even32_62a,even32_62b);
+      odd1_31a   = _mm_max_epu8(odd1_31a,odd1_31b);
+      odd33_63a  = _mm_max_epu8(odd33_63a,odd33_63b);
+
+      // Traceback information
+
+      TBeven0_30  = _mm_cmpeq_epi8(even0_30a,even0_30b);
+      TBeven32_62 = _mm_cmpeq_epi8(even32_62a,even32_62b);
+      TBodd1_31   = _mm_cmpeq_epi8(odd1_31a,odd1_31b);
+      TBodd33_63  = _mm_cmpeq_epi8(odd33_63a,odd33_63b);
+
+      metrics0_15        = _mm_unpacklo_epi8(even0_30a ,odd1_31a);
+      metrics16_31       = _mm_unpackhi_epi8(even0_30a ,odd1_31a);
+      metrics32_47       = _mm_unpacklo_epi8(even32_62a,odd33_63a);
+      metrics48_63       = _mm_unpackhi_epi8(even32_62a,odd33_63a);
+
+      TB_ptr[0]  = _mm_unpacklo_epi8(TBeven0_30,TBodd1_31);
+      TB_ptr[1] = _mm_unpackhi_epi8(TBeven0_30,TBodd1_31);
+      TB_ptr[2] = _mm_unpacklo_epi8(TBeven32_62,TBodd33_63);
+      TB_ptr[3] = _mm_unpackhi_epi8(TBeven32_62,TBodd33_63);
+
+
+      in+=3;
+      TB_ptr += 4;
+
+      // rescale by subtracting minimum
+      /****************************************************
+      USE SSSE instruction phminpos!!!!!!!
+      ****************************************************/
+      min_state =_mm_min_epu8(metrics0_15,metrics16_31);
+      min_state =_mm_min_epu8(min_state,metrics32_47);
+      min_state =_mm_min_epu8(min_state,metrics48_63);
+
+      min_state2 = min_state;
+      min_state  = _mm_unpacklo_epi8(min_state,min_state);
+      min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
+      min_state  = _mm_min_epu8(min_state,min_state2);
+
+      min_state2 = min_state;
+      min_state  = _mm_unpacklo_epi8(min_state,min_state);
+      min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
+      min_state  = _mm_min_epu8(min_state,min_state2);
+
+      min_state2 = min_state;
+      min_state  = _mm_unpacklo_epi8(min_state,min_state);
+      min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
+      min_state  = _mm_min_epu8(min_state,min_state2);
+
+      min_state2 = min_state;
+      min_state  = _mm_unpacklo_epi8(min_state,min_state);
+      min_state2 = _mm_unpackhi_epi8(min_state2,min_state2);
+      min_state  = _mm_min_epu8(min_state,min_state2);
+
+      metrics0_15  = _mm_subs_epu8(metrics0_15,min_state);
+      metrics16_31 = _mm_subs_epu8(metrics16_31,min_state);
+      metrics32_47 = _mm_subs_epu8(metrics32_47,min_state);
+      metrics48_63 = _mm_subs_epu8(metrics48_63,min_state);
+#elif defined(__arm__)
+    m0_ptr = (uint8x16_t *)&m0_table[table_offset];
+    m1_ptr = (uint8x16_t *)&m1_table[table_offset];
+
+
+    // even states
+    even0_30a  = vqaddq_u8(metrics0_31.val[0],m0_ptr[0]);
+    even32_62a = vqaddq_u8(metrics0_31.val[1],m0_ptr[1]);
+    even0_30b  = vqaddq_u8(metrics32_63.val[0],m0_ptr[2]);
+    even32_62b = vqaddq_u8(metrics32_63.val[1],m0_ptr[3]);
+
+    // odd states
+    odd1_31a   = vqaddq_u8(metrics0_31.val[0],m1_ptr[0]);
+    odd33_63a  = vqaddq_u8(metrics0_31.val[1],m1_ptr[1]);
+    odd1_31b   = vqaddq_u8(metrics32_63.val[0],m1_ptr[2]);
+    odd33_63b  = vqaddq_u8(metrics32_63.val[1],m1_ptr[3]);
+    // select maxima
+    even0_30a  = vmaxq_u8(even0_30a,even0_30b);
+    even32_62a = vmaxq_u8(even32_62a,even32_62b);
+    odd1_31a   = vmaxq_u8(odd1_31a,odd1_31b);
+    odd33_63a  = vmaxq_u8(odd33_63a,odd33_63b);
+
+    // Traceback information
+    TBeven0_30  = vceqq_u8(even0_30a,even0_30b);
+    TBeven32_62 = vceqq_u8(even32_62a,even32_62b);
+    TBodd1_31   = vceqq_u8(odd1_31a,odd1_31b);
+    TBodd33_63  = vceqq_u8(odd33_63a,odd33_63b);
+
+    metrics0_31  = vzipq_u8(even0_30a,odd1_31a);
+    metrics32_63 = vzipq_u8(even32_62a,odd33_63a);
+
+    TB_ptr[0] = vzipq_u8(TBeven0_30,TBodd1_31);
+    TB_ptr[1] = vzipq_u8(TBeven32_62,TBodd33_63);
+
+    in+=2;
+    TB_ptr += 2;
+
+    // rescale by subtracting minimum
+    /****************************************************
+    USE SSSE instruction phminpos!!!!!!!
+    ****************************************************/
+    min_state =vminq_u8(metrics0_31.val[0],metrics0_31.val[1]);
+    min_state =vminq_u8(min_state,metrics32_63.val[0]);
+    min_state =vminq_u8(min_state,metrics32_63.val[1]);
+    // here we have 16 maximum metrics from the 64 states
+    uint8x8_t min_state2 = vpmin_u8(((uint8x8_t*)&min_state)[0],((uint8x8_t*)&min_state)[0]);
+    // now the 8 maximum in min_state2
+    min_state2 = vpmin_u8(min_state2,min_state2);
+    // now the 4 maximum in min_state2, repeated twice
+    min_state2 = vpmin_u8(min_state2,min_state2);
+    // now the 2 maximum in min_state2, repeated 4 times
+    min_state2 = vpmin_u8(min_state2,min_state2);
+    // now the 1 maximum in min_state2, repeated 8 times
+    min_state  = vcombine_u8(min_state2,min_state2);
+    // now the 1 maximum in min_state, repeated 16 times
+    metrics0_31.val[0]  = vqsubq_u8(metrics0_31.val[0],min_state);
+    metrics0_31.val[1]  = vqsubq_u8(metrics0_31.val[1],min_state);
+    metrics32_63.val[0] = vqsubq_u8(metrics32_63.val[0],min_state);
+    metrics32_63.val[1] = vqsubq_u8(metrics32_63.val[1],min_state);
+#endif
+    }
+
+  } // iteration
+
+  // Traceback
+  prev_state0 = 0;
+  maxm = 0;
+
+#if defined(__x86_64__) || defined(__i386__)
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics0_15)[s] > maxm) {
+      maxm = ((uint8_t *)&metrics0_15)[s];
+      prev_state0 = s;
+    }
+
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics16_31)[s] > maxm) {
+      maxm = ((uint8_t *)&metrics16_31)[s];
+      prev_state0 = s+16;
+    }
+
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics32_47)[s] > maxm) {
+      maxm = ((uint8_t *)&metrics32_47)[s];
+      prev_state0 = s+32;
+    }
+
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics48_63)[s] > maxm) {
+      maxm = ((uint8_t *)&metrics48_63)[s];
+      prev_state0 = s+48;
+    }
+
+
+#elif defined(__arm__)
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics0_31.val[0])[s] > maxm) {
+      maxm = ((uint8_t *)&metrics0_31.val[0])[s];
+      prev_state0 = s;
+    }
+
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics0_31.val[1])[s] > maxm) {
+      maxm = ((uint8_t *)&metrics0_31.val[1])[s];
+      prev_state0 = s+16;
+    }
+
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics32_63.val[0])[s] > maxm) {
+      maxm = ((uint8_t *)&metrics32_63.val[0])[s];
+      prev_state0 = s+32;
+    }
+
+  for (s=0; s<16; s++)
+    if (((uint8_t *)&metrics32_63.val[1])[s] > maxm) {
+      maxm = ((uint8_t *)&metrics32_63.val[1])[s];
+      prev_state0 = s+48;
+    }
+#endif
+
+  TB_ptr2 = (uint8_t *)&TB[(n-1)*4];
+
+  for (position = n-1 ; position>-1; position--) {
+
+    decoded_bytes[(position)>>3] += (prev_state0 & 0x1)<<(7-(position & 0x7));
+
+
+    if (TB_ptr2[prev_state0] == 0)
+      prev_state0 = (prev_state0 >> 1);
+    else
+      prev_state0 = 32 + (prev_state0>>1);
+
+    TB_ptr2-=64;
+  }
+
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+}
+
+
diff --git a/openair1/PHY/INIT/defs_NB_IoT.h b/openair1/PHY/INIT/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..06c5aad35e4957fb644a93eb0560cd0588b81b6c
--- /dev/null
+++ b/openair1/PHY/INIT/defs_NB_IoT.h
@@ -0,0 +1,80 @@
+/*
+ * 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.0  (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 __INIT_DEFS_NB_IOT__H__
+#define __INIT_DEFS_NB_IOT__H__
+
+//#include "PHY/defs_NB_IoT.h"
+#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"  
+// nfapi_interface.h is required here, it is called through IF_Module_NB_IoT.h
+
+//#include "SystemInformationBlockType2.h"
+//#include "RadioResourceConfigCommonSIB.h"
+//#include "RadioResourceConfigDedicated.h"
+//#include "TDD-Config.h"
+//#include "MBSFN-SubframeConfigList.h"
+//#include "MobilityControlInfo.h"
+//#if defined(Rel10) || defined(Rel14)
+//#include "SCellToAddMod-r10.h"
+//#endif
+
+/*brief Configure LTE_DL_FRAME_PARMS with components derived after initial synchronization (MIB-NB decoding + primary/secondary synch).*/
+void phy_config_mib_eNB_NB_IoT(int  		Mod_id,
+						   	   int      	CC_id,
+						   	   int          eutra_band,
+						       int          Nid_cell,
+						       int          Ncp,
+						       int			Ncp_UL,
+						       int          p_eNB,
+						       uint16_t		EARFCN,
+						       uint16_t		prb_index, // NB_IoT_RB_ID,
+						       uint16_t 	operating_mode,
+						       uint16_t		control_region_size,
+						       uint16_t		eutra_NumCRS_ports);
+
+/*NB_phy_config_sib1_eNB is not needed since NB-IoT use only FDD mode*/
+
+/*brief Configure LTE_DL_FRAME_PARMS with components of SIB2-NB (at eNB).*/
+
+//void NB_phy_config_sib2_eNB(module_id_t                            Mod_id,
+//                         int                                		CC_id,
+//                         RadioResourceConfigCommonSIB_NB_r13_t      *radioResourceConfigCommon
+//                         );
+
+void phy_config_sib2_eNB_NB_IoT(uint8_t Mod_id,
+                         		int CC_id,
+                         		nfapi_config_NB_IoT_t *config,
+						 		nfapi_rf_config_t *rf_config,
+								nfapi_uplink_reference_signal_config_t* ul_nrs_config,
+								extra_phyConfig_t* extra_phy_parms);
+
+void phy_config_dedicated_eNB_NB_IoT(module_id_t Mod_id,
+                              	 	 int CC_id,
+                              	 	 rnti_t rnti,
+							     	 extra_phyConfig_t* extra_phy_parms); 
+
+// void phy_init_lte_top_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms); 
+
+
+
+#endif
+
diff --git a/openair1/PHY/INIT/defs_nb_iot.h b/openair1/PHY/INIT/defs_nb_iot.h
deleted file mode 100644
index 059d802a71551f63f51c875ac94764ec409c1c45..0000000000000000000000000000000000000000
--- a/openair1/PHY/INIT/defs_nb_iot.h
+++ /dev/null
@@ -1,384 +0,0 @@
-/*
- * 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.0  (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 __INIT_DEFS__H__
-#define __INIT_DEFS__H__
-
-#include "PHY/defs.h"
-
-
-#include "SystemInformationBlockType2.h"
-//#include "RadioResourceConfigCommonSIB.h"
-#include "RadioResourceConfigDedicated.h"
-#include "TDD-Config.h"
-#include "MBSFN-SubframeConfigList.h"
-#include "MobilityControlInfo.h"
-#if defined(Rel10) || defined(Rel14)
-#include "SCellToAddMod-r10.h"
-#endif
-/** @addtogroup _PHY_STRUCTURES_
- * @{
- */
-
-/*!
-\fn int phy_init_top(LTE_DL_FRAME_PARMS *frame_parms)
-\brief Allocate and Initialize the PHY variables after receiving static configuration
-@param frame_parms Pointer to LTE_DL_FRAME_PARMS (common configuration)
-@returns 0 on success
- */
-int phy_init_top(LTE_DL_FRAME_PARMS *frame_parms);
-
-
-/*!
-\brief Allocate and Initialize the PHY variables relevant to the LTE implementation.
-\details Only a subset of phy_vars_ue is initialized.
-@param[out] phy_vars_ue Pointer to UE Variables
-@param nb_connected_eNB Number of eNB that UE can process in one PDSCH demodulation subframe
-@param abstraction_flag 1 indicates memory should be allocated for abstracted MODEM
-@returns 0 on success
-@returns -1 if any memory allocation failed
-@note The current implementation will never return -1, but segfault.
- */
-int phy_init_lte_ue(PHY_VARS_UE *phy_vars_ue,
-                    int          nb_connected_eNB,
-                    uint8_t         abstraction_flag);
-
-/*!
-\brief Allocate and initialize the PHY variables relevant to the LTE implementation (eNB).
-\details Only a subset of phy_vars_eNb is initialized.
-@param[out] phy_vars_eNb Pointer to eNB Variables
-@param is_secondary_eNb Flag to indicate this eNB gets synch from another
-@param abstraction_flag 1 indicates memory should be allocated for abstracted MODEM
-@returns 0 on success
-@returns -1 if any memory allocation failed
-@note The current implementation will never return -1, but segfault.
- */
-int phy_init_lte_eNB(PHY_VARS_eNB *phy_vars_eNb,
-                     unsigned char is_secondary_eNb,
-                     unsigned char abstraction_flag);
-
-/** \brief Configure LTE_DL_FRAME_PARMS with components derived after initial synchronization (MIB decoding + primary/secondary synch).
-\details The basically allows configuration of \f$N_{\mathrm{RB}}^{\mathrm{DL}}\f$, the cell id  \f$N_{\mathrm{ID}}^{\mathrm{cell}}\f$, the normal/extended prefix mode, the frame type (FDD/TDD), \f$N_{\mathrm{cp}}\f$, the number of TX antennas at eNB (\f$p\f$) and the number of PHICH groups, \f$N_{\mathrm{group}}^{\mathrm{PHICH}}\f$
-@param lte_frame_parms pointer to LTE parameter structure
-@param N_RB_DL Number of DL resource blocks
-@param Nid_cell Cell ID
-@param Ncp Normal/Extended Prefix flag
-@param frame_type FDD/TDD framing
-@param p_eNB Number of eNB TX antennas
-@param phich_config Pointer to PHICH_CONFIG_COMMON
- */
-void phy_config_mib(LTE_DL_FRAME_PARMS *lte_frame_parms,
-                    uint8_t                N_RB_DL,
-                    uint8_t                Nid_cell,
-                    uint8_t                Ncp,
-                    uint8_t                frame_type,
-                    uint8_t                p_eNB,
-                    PHICH_CONFIG_COMMON *phich_config);
-
-
-/** \brief Configure LTE_DL_FRAME_PARMS with components derived after reception of SIB1.
-\details From a PHY perspective this allows configuration of TDD framing parameters and SI reception.
-@param Mod_id Instance ID of eNB
-@param CC_id Component Carrier index
-@param tdd_Config TDD UL/DL and S-subframe configurations
-@param SIwindowsize Size of a SI window in frames where repetitions of a unique System Information message block is repeated
-@param SIperiod Periodicity of System Information Messages (in multiples of a frame)*/
-void phy_config_sib1_eNB(module_id_t    Mod_id,
-                         int CC_id,
-                         TDD_Config_t  *tdd_Config,
-                         uint8_t           SIwindowsize,
-                         uint16_t            SIperiod);
-
-/** \brief Configure LTE_DL_FRAME_PARMS with components derived after reception of SIB1.
-\details From a PHY perspective this allows configuration of TDD framing parameters and SI reception.
-@param Mod_id Instance ID of UE
-@param CC_id Component Carrier index
-@param CH_index Index of eNB for this configuration
-@param tdd_Config TDD UL/DL and S-subframe configurations
-@param SIwindowsize Size of a SI window in frames where repetitions of a unique System Information message block is repeated
-@param SIperiod Periodicity of System Information Messages (in multiples of a frame)*/
-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);
-
-
-/*!
-  \fn void phy_config_sib2_ue(module_id_t Mod_id,uint8_t 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)
-  \brief Configure LTE_DL_FRAME_PARMS with components derived after reception of SIB2 (at UE).
-  @param Mod_id Instance id
-  @param CC_id
-  @param CH_index Index of CH to which UE is connected
-  @param CC_id Component Carrier Index
-  @param radioResourceConfigCommon Radio Configuration from SIB2
-  @param ul_CarrierFreq UL carrier ARFCN, null if optional (i.e. implicit from DL)
-  @param ul_Bandwidth UL bandwidth, null if optional (i.e. same as DL)
-  @param additionalSpectrumEmission UL parameter (see 36.101)
-  @param mbsfn_SubframeConfigList MBSFN subframe configuration
- */
-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);
-
-
-/*!
-  \fn phy_config_afterHO_ue
-  \brief Configure Common PHY parameters from mobilityControlInfo
-  @param Mod_id
-  @param CC_id
-  @param eNB_index
-  @param mobilityControlInfo pointer to the mobility control information for handover
-  @param ho_failed flag to indicated whether the ho was successful or not
- */
-void phy_config_afterHO_ue(module_id_t Mod_id,
-                           uint8_t CC_id,
-                           uint8_t eNB_index,
-                           MobilityControlInfo_t *mobilityControlInfo,
-                           uint8_t ho_failed);
-/*!
-  \fn void phy_config_sib2_eNB(module_id_t Mod_id,
-                               RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
-             ARFCN_ValueEUTRA_t *ul_CArrierFreq,
-             long *ul_Bandwidth,
-             AdditionalSpectrumEmission_t additionalSpectrumEmission,
-             struct MBSFN_SubframeConfigList  *mbsfn_SubframeConfigList)
-  \brief Configure LTE_DL_FRAME_PARMS with components of SIB2 (at eNB).
-  @param Mod_id Instance id
-  @param Mod_id Component Carrier index
-  @param radioResourceConfigCommon Radio Configuration from SIB2
-  @param ul_CarrierFreq UL carrier ARFCN, null if optional (i.e. implicit from DL)
-  @param ul_Bandwidth UL bandwidth, null if optional (i.e. same as DL)
-  @param additionalSpectrumEmission UL parameter (see 36.101)
-  @param mbsfn_SubframeConfigList MBSFN subframe configuration
- */
-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);
-
-
-/*!
-\fn void phy_config_dedicated_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
-               struct PhysicalConfigDedicated *physicalConfigDedicated)
-\brief Configure UE dedicated parameters.
-\details Invoked upon reception of RRCConnectionSetup or RRCConnectionReconfiguration from eNB.
-@param Mod_id Instance ID for eNB
-@param CC_id Component Carrier index
-@param CH_index Index of eNB for this configuration
-@param physicalConfigDedicated PHY Configuration information
-
- */
-void phy_config_dedicated_ue(module_id_t Mod_id,
-                             int CC_id,
-                             uint8_t CH_index,
-                             struct PhysicalConfigDedicated *physicalConfigDedicated);
-
-/*!
-\fn void phy_config_harq_ue(module_id_t Mod_id,uint8_t CC_id,uint8_t CH_index,
-               uint16_t max_harq_tx)
-\brief Configure UE UL max harq Tx.
-\details Invoked upon reception of RRCConnectionSetup or RRCConnectionReconfiguration from eNB.
-@param Mod_id Instance ID for eNB
-@param CC_id Component Carrier index
-@param CH_index Index of eNB for this configuration
-@param max_harq_tx max harq tx information
-
- */
-void phy_config_harq_ue(module_id_t Mod_id,int CC_id,uint8_t CH_index,
-                           uint16_t max_harq_tx);
-/**
-\brief Configure UE MBSFN common parameters.
-\details Invoked upon reception of SIB13 from eNB.
-@param Mod_id Instance ID for UE
-@param CC_id Component Carrier Index
-@param CH_index eNB id (for multiple eNB reception)
-@param mbsfn_Area_idx Index of MBSFN-Area for which this command operates
-@param mbsfn_AreaId_r9 MBSFN-Area Id
- */
-
-void phy_config_sib13_ue(module_id_t Mod_id,
-                         int CC_id,uint8_t CH_index,int mbsfn_Area_idx,
-                         long mbsfn_AreaId_r9);
-
-/**
-\brief Configure eNB MBSFN common parameters.
-\details Invoked upon transmission of SIB13 from eNB.
-@param Mod_id Instance ID for eNB
-@param CC_id Component Carrier index
-@param mbsfn_Area_idx Index of MBSFN-Area for which this command operates
-@param mbsfn_AreaId_r9 MBSFN-Area Id
- */
-void phy_config_sib13_eNB(module_id_t Mod_id,
-                          int CC_id,
-                          int mbsfn_Area_idx,
-                          long mbsfn_AreaId_r9);
-
-/**
-\brief Configure cba rnti for .
-@param Mod_id Instance ID for eNB
-@param CC_id Component Carrier Index
-@param eNB_flag flag indicating whether the nodeis eNB (1) or UE (0)
-@param index index of the node
-@param cba_rnti rnti for the cba transmission
-@param num_active_cba_groups num active cba group
- */
-void  phy_config_cba_rnti (module_id_t Mod_id,int CC_id,eNB_flag_t eNB_flag, uint8_t index, rnti_t cba_rnti, uint8_t cba_group_id, uint8_t num_active_cba_groups);
-
-/** \brief Configure RRC inter-cell measurements procedures
-@param Mod_id Index of UE
-@param CC_id
-@param eNB_index Index of corresponding eNB
-@param n_adj_cells Number of adjacent cells on which to perform the measuremnts
-@param adj_cell_id Array of cell ids of adjacent cells
- */
-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);
-
-/*!
-\fn void phy_config_dedicated_eNB(module_id_t Mod_id,uint16_t rnti,
-                                  struct PhysicalConfigDedicated *physicalConfigDedicated)
-\brief Prepare for configuration of PHY with dedicated parameters.
-\details Invoked just prior to transmission of RRCConnectionSetup or RRCConnectionReconfiguration at eNB.
-@param Mod_id Instance ID for eNB
-@param CC_id Component Carrier index
-@param rnti rnti for UE context
-@param physicalConfigDedicated PHY Configuration information
- */
-void phy_config_dedicated_eNB(module_id_t Mod_id,
-                              int CC_id,
-                              rnti_t rnti,
-                              struct PhysicalConfigDedicated *physicalConfigDedicated);
-
-/*!
-\fn void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *phy_vars_eNB)
-\brief Configure PHY with dedicated parameters between configuration of DLSCH (n) and ULSCH (n+4) in current subframe (n).
-@param phy_vars_eNB Pointer to PHY_VARS_eNB structure
- */
-void phy_config_dedicated_eNB_step2(PHY_VARS_eNB *phy_vars_eNB);
-
-/*
-  \fn int phy_init_secsys_eNB(PHY_VARS_eNB *phy_vars_eNb)
-\brief Allocate and Initialize the PHY variables relevant to the LTE implementation.
-@param phy_vars_eNb pointer to LTE parameter structure for the eNb
- */
-int phy_init_secsys_eNB(PHY_VARS_eNB *phy_vars_eNb);
-
-
-void phy_init_lte_top(LTE_DL_FRAME_PARMS *lte_frame_parms);
-
-//void copy_lte_parms_to_phy_framing(LTE_DL_FRAME_PARMS *frame_parm, PHY_FRAMING *phy_framing);
-
-void lte_param_init(unsigned char N_tx_port_eNB,
-		    unsigned char N_tx, 
-		    unsigned char N_rx,
-		    unsigned char transmission_mode,
-		    uint8_t extended_prefix_flag,
-		    frame_t frame_type, 
-		    uint16_t Nid_cell,
-		    uint8_t tdd_config,
-		    uint8_t N_RB_DL,
-		    uint8_t threequarter_fs,
-                    uint8_t osf,
-		    uint32_t perfect_ce);
-
-#if defined(Rel10) || defined(Rel14)
-void phy_config_dedicated_scell_ue(uint8_t Mod_id,
-                                   uint8_t eNB_index,
-                                   SCellToAddMod_r10_t *sCellToAddMod_r10,
-                                   int CC_id);
-
-void phy_config_dedicated_scell_eNB(uint8_t Mod_id,
-                                    uint16_t rnti,
-                                    SCellToAddMod_r10_t *sCellToAddMod_r10,
-                                    int CC_id);
-
-#endif
-
-/*brief Configure LTE_DL_FRAME_PARMS with components derived after initial synchronization (MIB-NB decoding + primary/secondary synch).*/
-void NB_phy_config_mib_eNB(int                    Mod_id,
-			int                    CC_id,
-			int                    eutra_band,
-			int                    Nid_cell,
-			int                    Ncp,
-			int                    p_eNB,
-			uint32_t               dl_CarrierFreq,
-			uint32_t               ul_CarrierFreq,
-			struct MasterInformationBlock_NB__operationModeInfo_r13_u operationModeInfo);
-
-/*NB_phy_config_sib1_eNB is not needed since NB-IoT use only FDD mode*/
-
-/*brief Configure LTE_DL_FRAME_PARMS with components of SIB2-NB (at eNB).*/
-void NB_phy_config_sib2_eNB(module_id_t                            Mod_id,
-                         int                                CC_id,
-                         RadioResourceConfigCommonSIB_NB_r13         *radioResourceConfigCommon,
-                         ARFCN_ValueEUTRA_r9_t                     *ul_CArrierFreq,,
-                         );
-
-void NB_phy_config_dedicated_eNB(module_id_t Mod_id,
-                              int CC_id,
-                              rnti_t rnti,
-                              struct PhysicalConfigDedicated_NB_r13 *physicalConfigDedicated);
-
-
-
-
-
-/*! !\fn void phy_cleanup(void)
-\brief Cleanup the PHY variables*/
-void phy_cleanup(void);
-
-
-int init_frame_parms(LTE_DL_FRAME_PARMS *frame_parms,uint8_t osf);
-void dump_frame_parms(LTE_DL_FRAME_PARMS *frame_parms);
-
-void lte_param_init(unsigned char N_tx_port_eNB, 
-                    unsigned char N_tx_phy,
-		    unsigned char N_rx,
-		    unsigned char transmission_mode,
-		    uint8_t extended_prefix_flag,
-		    frame_t frame_type, 
-		    uint16_t Nid_cell,
-		    uint8_t tdd_config,
-		    uint8_t N_RB_DL,
-		    uint8_t threequarter_fs,
-                    uint8_t osf,
-		    uint32_t perfect_ce);
-/** @} */
-#endif
-
diff --git a/openair1/PHY/INIT/init_top.c b/openair1/PHY/INIT/init_top.c
index 33ff141203f351fb8549b5ecd026072f99af2706..1156cbecc8e866c4b510862341fe527d078e3ac4 100644
--- a/openair1/PHY/INIT/init_top.c
+++ b/openair1/PHY/INIT/init_top.c
@@ -37,7 +37,7 @@
 
 */
 
-//#define DEBUG_PHY
+//#define DEBUG_PHY 
 t
 
 
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index 241ace9d3caf2a449df597b20bc4516e8a7a98e9..0b14a03ce26ec6e4f068d311a74518f40ffad574 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -32,76 +32,13 @@
 #define DEBUG_PHY
 #include "assertions.h"
 #include <math.h>
+#include "PHY/LTE_REFSIG/defs.h"
 
 extern uint16_t prach_root_sequence_map0_3[838];
 extern uint16_t prach_root_sequence_map4[138];
 uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10};
 
-#if defined(NB_IoT)
 
-void NB_phy_config_mib_eNB(int                 Mod_id,
-			int                 CC_id,
-			int                 eutra_band,
-			int                 Nid_cell,
-			int                 Ncp,
-			int                 p_eNB,
-			uint32_t            dl_CarrierFreq,
-			uint32_t            ul_CarrierFreq) {
-
-  
-  LTE_DL_FRAME_PARMS *fp;
-
-  LOG_I(PHY,"Configuring MIB for instance %d, CCid %d : (band %d,N_RB_DL %d,Nid_cell %d,p %d,DL freq %u)\n",
-	Mod_id, CC_id, eutra_band, N_RB_DL_array[dl_Bandwidth], Nid_cell, p_eNB,dl_CarrierFreq);
-
-  /*if (RC.eNB == NULL) {
-    RC.eNB                               = (PHY_VARS_eNB ***)malloc((1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
-    LOG_I(PHY,"RC.eNB = %p\n",RC.eNB);
-    memset(RC.eNB,0,(1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
-  }
-  if (RC.eNB[Mod_id] == NULL) {
-    RC.eNB[Mod_id]                       = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB**));
-    LOG_I(PHY,"RC.eNB[%d] = %p\n",Mod_id,RC.eNB[Mod_id]);
-    memset(RC.eNB[Mod_id],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB***));
-  }
-  if (RC.eNB[Mod_id][CC_id] == NULL) {
-    RC.eNB[Mod_id][CC_id] = (PHY_VARS_eNB *)malloc(sizeof(PHY_VARS_eNB));
-    LOG_I(PHY,"RC.eNB[%d][%d] = %p\n",Mod_id,CC_id,RC.eNB[Mod_id][CC_id]);
-    RC.eNB[Mod_id][CC_id]->Mod_id        = Mod_id;
-    RC.eNB[Mod_id][CC_id]->CC_id         = CC_id;
-  }
-
-  RC.eNB[Mod_id][CC_id]->mac_enabled     = 1;
-
-  fp = &RC.eNB[Mod_id][CC_id]->frame_parms; */
-
-  fp->Nid_cell                           = Nid_cell;
-  fp->nushift                            = Nid_cell%6;
-  fp->eutra_band                         = eutra_band;
-  fp->Ncp                                = Ncp;
-  fp->nb_antenna_ports_eNB               = p_eNB;
-  fp->dl_CarrierFreq                     = dl_CarrierFreq;
-  fp->ul_CarrierFreq                     = ul_CarrierFreq;
-  
-
-  init_frame_parms(fp,1);
-  init_lte_top(fp);
-
-}
-
-void NB_phy_config_sib2_eNB(uint8_t Mod_id,
-                         int CC_id,
-                         RadioResourceConfigCommonSIB_t *radioResourceConfigCommon,
-                         ARFCN_ValueEUTRA_t *ul_CArrierFreq,
-                         AdditionalSpectrumEmission_t *additionalSpectrumEmission,
-                         )
-{
-
-}
-
-#endif
-
-// FIXME not used anywhere
 void phy_config_mib(LTE_DL_FRAME_PARMS *fp,
                     uint8_t N_RB_DL,
                     uint8_t Nid_cell,
diff --git a/openair1/PHY/INIT/lte_init_NB_IoT.c b/openair1/PHY/INIT/lte_init_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..efa05472d94b20a8be149ab4e8b87de639526b66
--- /dev/null
+++ b/openair1/PHY/INIT/lte_init_NB_IoT.c
@@ -0,0 +1,422 @@
+/*
+ * 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.0  (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
+ */
+
+//#include "defs.h"
+#include "SCHED/defs_NB_IoT.h"
+//#include "PHY/extern.h"
+#include "PHY/extern_NB_IoT.h"   	// PHY/defs_NB_IoT.h is called here , log.h & LTE_TRANSPORT/defs_NB_IoT.h are included through PHY/defs_NB_IoT.h
+#include "openair2/LAYER2/MAC/proto_NB_IoT.h"	// for functions: from_earfcn_NB_IoT, get_uldl_offset_NB_IoT
+//#include "SIMULATION/TOOLS/defs.h"
+//#include "RadioResourceConfigCommonSIB.h"
+//#include "RadioResourceConfigDedicated.h"
+//#include "TDD-Config.h"
+//#include "LAYER2/MAC/extern.h"
+//#include "MBSFN-SubframeConfigList.h"
+//#include "UTIL/LOG/vcd_signal_dumper.h"
+//#define DEBUG_PHY
+#include "assertions.h"
+//#include <math.h>
+
+//NB-IoT
+#include "PHY/INIT/defs_NB_IoT.h"   // nfapi_interface.h & IF_Module_NB_IoT.h are included here
+//#include "RadioResourceConfigCommonSIB-NB-r13.h"
+//#include "RadioResourceConfigDedicated-NB-r13.h"
+//#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
+//#include "openair2/RRC/LITE/proto_NB_IoT.h"
+
+//extern uint16_t prach_root_sequence_map0_3[838];
+//extern uint16_t prach_root_sequence_map4[138];
+//uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10};
+
+
+void phy_config_mib_eNB_NB_IoT(int  			Mod_id,
+							   int              CC_id,
+							   int              eutra_band,
+							   int              Nid_cell,
+							   int              Ncp,
+							   int				Ncp_UL,
+							   int              p_eNB,
+							   uint16_t			EARFCN,
+							   uint16_t			prb_index, // NB_IoT_RB_ID,
+							   uint16_t 		operating_mode,
+							   uint16_t			control_region_size,
+							   uint16_t			eutra_NumCRS_ports)
+{
+
+
+  AssertFatal(PHY_vars_eNB_NB_IoT_g != NULL, "PHY_vars_eNB_NB_IoT_g instance pointer doesn't exist\n");
+  AssertFatal(PHY_vars_eNB_NB_IoT_g[Mod_id] != NULL, "PHY_vars_eNB_NB_IoT_g instance %d doesn't exist\n",Mod_id);
+  AssertFatal(PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id] != NULL, "PHY_vars_eNB_NB_IoT_g instance %d, CCid %d doesn't exist\n",Mod_id,CC_id);
+
+  NB_IoT_DL_FRAME_PARMS *fp = &PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->frame_parms_NB_IoT;
+
+   LOG_I(PHY,"Configuring MIB-NB for instance %d, CCid %d : (band %d,Nid_cell %d,p %d,EARFCN %u)\n",Mod_id, CC_id, eutra_band, Nid_cell, p_eNB,EARFCN);
+
+//  fp->N_RB_DL
+//  fp->N_RB_UL						also this two values need to be known when we are dealing with in-band and guard-band operating mode
+  fp->Nid_cell                           = Nid_cell;
+  fp->nushift                            = Nid_cell%6;
+  fp->eutra_band                         = eutra_band;
+  fp->Ncp                             	 = Ncp;
+  fp->Ncp_UL							 = Ncp_UL;
+  fp->nb_antenna_ports_eNB               = p_eNB; //tx antenna port
+  fp->dl_CarrierFreq                     = from_earfcn_NB_IoT(eutra_band,EARFCN,0);
+  fp->ul_CarrierFreq                     = fp->dl_CarrierFreq - get_uldl_offset_NB_IoT(eutra_band);
+  fp->operating_mode					 = operating_mode; //see how are defined by FAPI structure
+  fp->NB_IoT_RB_ID						 = prb_index; //XXX to be better understand how should be managed
+  //fp->nb_rx_antenna_ports_eNB
+  fp->control_region_size			 	 = control_region_size; //(assume that this value is negative if not used)
+  fp->eutra_NumCRS_ports				 = eutra_NumCRS_ports; //(valid only for in-band operating mode with different PCI)
+  
+
+  //TODO  (new Raymond implementation) in the classic implementation seems to be used only by oaisim
+  //init_frame_parms(fp,1);
+  //init_lte_top(fp);
+
+}
+
+//Before FAPI implementation
+//void NB_phy_config_sib2_eNB(uint8_t Mod_id,
+//                         int CC_id,
+//                         RadioResourceConfigCommonSIB_NB_r13_t *radioResourceConfigCommon
+//                         )
+//{
+//	NB_IoT_DL_FRAME_PARMS *fp = &PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->frame_parms;
+//	  //LTE_eNB_UE_stats *eNB_UE_stats		= PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->eNB_UE_stats;
+//	  //int32_t rx_total_gain_eNB_dB		= PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->rx_total_gain_eNB_dB;
+//	  uint8_t MAX_NPRACH = 4;
+//          NPRACH_Parameters_NB_r13_t *np;
+//
+//	  LOG_D(PHY,"[eNB%d] CCid %d: Applying radioResourceConfigCommon_NB\n",Mod_id,CC_id);
+//
+//      /*NPRACH configCommon*/
+//	  fp->nprach_config_common.nprach_CP_Length                                     =radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_CP_Length = %d\n",fp->nprach_config_common.nprach_CP_Length);
+//	  //fp->nprach_config_common.rsrp_ThresholdsPrachInfoList.list                    =radioResourceConfigCommon->nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13.list;
+//	  //LOG_D(PHY,"nprach_config_common.rsrp_ThresholdsPrachInfoList = %d\n",fp->nprach_config_common.rsrp_ThresholdsPrachInfoList);
+//
+//	  /*Loop over the configuration according to the maxNPRACH_Resources*/
+//      for (fp->CE=1; fp->CE <= MAX_NPRACH;fp->CE++){
+//      np = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[fp->CE];
+//      /*fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->maxNumPreambleAttemptCE           =np->maxNumPreambleAttemptCE_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.maxNumPreambleAttemptCE = %d\n",fp->nprach_config_common.nprach_ParametersList.list.maxNumPreambleAttemptCE);
+//      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_NumRepetitions_RA          =np->npdcch_NumRepetitions_RA_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_NumRepetitions_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.npdcch_NumRepetitions_RA);
+//      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_Periodicity                =np->nprach_Periodicity_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_Periodicity = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_Periodicity);
+//      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_StartTime                  =np->nprach_StartTime_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_StartTime = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_StartTime);
+//      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_SubcarrierOffset           =np->nprach_SubcarrierOffset_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierOffset = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierOffset);
+//      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_SubcarrierMSG3_RangeStart  =np->nprach_SubcarrierMSG3_RangeStart_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierMSG3_RangeStart = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierMSG3_RangeStart);
+//      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_Offset_RA                  =np->npdcch_Offset_RA_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_Offset_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.npdcch_Offset_RA);
+//      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_StartSF_CSS_RA             =np->npdcch_StartSF_CSS_RA_r13;
+//	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_StartSF_CSS_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_StartSF_CSS_RA);
+//      */
+//      }
+//
+//	  /*Should modify to compute_nprach_seq*/
+//	  //compute_prach_seq(&fp->prach_config_common,fp->frame_type,PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->X_u);
+//
+//	  /*NPDSCH ConfigCommon*/
+//	  fp->npdsch_config_common.nrs_Power           = radioResourceConfigCommon->npdsch_ConfigCommon_r13.nrs_Power_r13;
+//
+//	  /*NPUSCH ConfigCommon*/
+//	  /*A list (1-3) should be loop for ack_NACK_NumRepetitions_Msg4*/
+//	  for (fp->CE=1; fp->CE <= MAX_NPRACH;fp->CE++){
+//	  fp->npusch_config_common.ack_NACK_NumRepetitions_Msg4[fp->CE]        = radioResourceConfigCommon->npusch_ConfigCommon_r13.ack_NACK_NumRepetitions_Msg4_r13.list.array[fp->CE];
+//          //LOG_D(PHY,"npusch_config_common.ack_NACK_NumRepetitions_Msg4 = %d]n",fp->npusch_config_common.ack_NACK_NumRepetitions_Msg4);
+//	  }
+//	  fp->npusch_config_common.srs_SubframeConfig                          = radioResourceConfigCommon->npusch_ConfigCommon_r13.srs_SubframeConfig_r13;
+//	  LOG_D(PHY,"npusch_config_common.srs_SubframeConfig = %d]n",fp->npusch_config_common.srs_SubframeConfig);
+//	  fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence          = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_BaseSequence_r13;
+//	  LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence);
+//	  fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence            = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_BaseSequence_r13;
+//	  LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence);
+//	  fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift           = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13;
+//	  LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_CyclicShift = %d]n",fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift);
+//	  fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift             = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13;
+//	  LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_CyclicShift = %d]n",fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift);
+//	  fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence         = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->twelveTone_BaseSequence_r13;
+//	  LOG_D(PHY,"npusch_config_common.dmrs_Config.twelveTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence);
+//
+//	  fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH  = radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13;
+//	  LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH = %d]n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH);
+//	  fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled    = radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13;
+//	  LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled = %d]n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled);
+//
+//      /*should change the part that implement the ul hopping in NB-IoT*/
+//	  //init_ul_hopping(fp);
+//
+//	  /*UL Power Control Config Common*/
+//
+//	  fp->ul_power_control_config_common.p0_NominalNPUSCH      = radioResourceConfigCommon->uplinkPowerControlCommon_r13.p0_NominalNPUSCH_r13;
+//	  fp->ul_power_control_config_common.alpha				   = radioResourceConfigCommon->uplinkPowerControlCommon_r13.alpha_r13;
+//      fp->ul_power_control_config_common.deltaPreambleMsg3     = radioResourceConfigCommon->uplinkPowerControlCommon_r13.deltaPreambleMsg3_r13;
+//
+//	  /*DL gap*/
+//
+//      fp->DL_gap_config.dl_GapDurationCoeff                        = radioResourceConfigCommon->dl_Gap_r13->dl_GapDurationCoeff_r13;
+//	  fp->DL_gap_config.dl_GapPeriodicity                      = radioResourceConfigCommon->dl_Gap_r13->dl_GapPeriodicity_r13;
+//	  fp->DL_gap_config.dl_GapThreshold                        = radioResourceConfigCommon->dl_Gap_r13->dl_GapThreshold_r13;
+//
+//	  /*PUCCH stuff in LTE*/
+//	  //init_ncs_cell(fp,PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->ncs_cell);
+//
+//	  //init_ul_hopping(fp);
+//
+//
+//
+//}
+
+void phy_config_sib2_eNB_NB_IoT(uint8_t 								  Mod_id,
+                         		int 									  CC_id,
+                         		nfapi_config_NB_IoT_t 					  *config,
+						 		nfapi_rf_config_t 						  *rf_config,
+						 		nfapi_uplink_reference_signal_config_t	  *ul_nrs_config,
+						 		extra_phyConfig_t						  *extra_phy_parms)
+{
+	NB_IoT_DL_FRAME_PARMS *fp = &PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->frame_parms;
+	LOG_D(PHY,"[eNB%d] CCid %d: Applying config_NB_IoT from sib2_NB\n",Mod_id,CC_id);
+	  
+	/*NPRACH_ConfigSIB_NB_r13----------------------------------------------------------*/
+
+	//MP: FAPI style approach: instead of a list they consider the 3 possible configuration separately
+
+	  if(config->nprach_config_0_enabled.value == 1){
+		  LOG_D(PHY, "NPRACH Config #0 enabled\n");
+
+		  fp->nprach_config_common.nprach_CP_Length = config->nprach_config_0_cp_length.value; //NPRACH_ConfigSIB_NB_r13__nprach_CP_Length_r13_us66dot7
+		  LOG_D(PHY," config#0: nprach_CP_Length = %d\n",fp->nprach_config_common.nprach_CP_Length);
+		  //FIXME: MP: memory for the list should be allocated? initialization??
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_Periodicity = config->nprach_config_0_sf_periodicity.value;
+		  LOG_D(PHY,"config#0: nprach_Periodicity = %d\n", fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_Periodicity);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_StartTime = config->nprach_config_0_start_time.value;
+		  LOG_D(PHY,"config#0: nprach_StartTime = %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_StartTime);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_SubcarrierOffset = config->nprach_config_0_subcarrier_offset.value;
+		  LOG_D(PHY,"config#0: nprach_SubcarrierOffset= %d\n", fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_SubcarrierOffset);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_NumSubcarriers = config->nprach_config_0_number_of_subcarriers.value;
+		  LOG_D(PHY,"config#0: nprach_NumSubcarriers= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_NumSubcarriers);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->numRepetitionsPerPreambleAttempt = config->nprach_config_0_number_of_repetitions_per_attempt.value;
+		  LOG_D(PHY,"config#0: numRepetitionsPerPreambleAttempt= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[0]->numRepetitionsPerPreambleAttempt);
+
+		  //missed configuration in FAPI config_request (TS 36.331 pag 610) (may not needed)
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->nprach_SubcarrierMSG3_RangeStart = extra_phy_parms->nprach_config_0_subcarrier_MSG3_range_start;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->npdcch_StartSF_CSS_RA = extra_phy_parms->nprach_config_0_npdcch_startSF_CSS_RA;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->npdcch_NumRepetitions_RA = extra_phy_parms->nprach_config_0_npdcch_num_repetitions_RA;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->npdcch_Offset_RA = extra_phy_parms->nprach_config_0_npdcch_offset_RA;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[0]->maxNumPreambleAttemptCE = extra_phy_parms->nprach_config_0_max_num_preamble_attempt_CE;
+		  //fp->nprach_config_common.rsrp_ThresholdsPrachInfoList.list /*OPTIONAL*/
+
+	  }
+
+	  if(config->nprach_config_1_enabled.value == 1){
+		  LOG_D(PHY, "NPRACH Config #1 enabled\n");
+
+		  fp->nprach_config_common.nprach_CP_Length = config->nprach_config_1_cp_length.value; //NPRACH_ConfigSIB_NB_r13__nprach_CP_Length_r13_us66dot7
+		  LOG_D(PHY," config#1: nprach_CP_Length = %d\n",fp->nprach_config_common.nprach_CP_Length);
+		  //FIXME: MP: memory for the list should be allocated? initialization??
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_Periodicity = config->nprach_config_1_sf_periodicity.value;
+		  LOG_D(PHY,"config#1: nprach_Periodicity = %d\n", fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_Periodicity);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_StartTime = config->nprach_config_1_start_time.value;
+		  LOG_D(PHY,"config#1: nprach_StartTime = %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_StartTime);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_SubcarrierOffset = config->nprach_config_1_subcarrier_offset.value;
+		  LOG_D(PHY,"config#1: nprach_SubcarrierOffset= %d\n", fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_SubcarrierOffset);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_NumSubcarriers = config->nprach_config_1_number_of_subcarriers.value;
+		  LOG_D(PHY,"config#1: nprach_NumSubcarriers= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_NumSubcarriers);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->numRepetitionsPerPreambleAttempt = config->nprach_config_1_number_of_repetitions_per_attempt.value;
+		  LOG_D(PHY,"config#1: numRepetitionsPerPreambleAttempt= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[1]->numRepetitionsPerPreambleAttempt);
+
+		  //missed configuration in FAPI config_request (TS 36.331 pag 610) (may not needed)
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->nprach_SubcarrierMSG3_RangeStart = extra_phy_parms->nprach_config_1_subcarrier_MSG3_range_start;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->npdcch_StartSF_CSS_RA = extra_phy_parms->nprach_config_1_npdcch_startSF_CSS_RA;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->npdcch_NumRepetitions_RA = extra_phy_parms->nprach_config_1_npdcch_num_repetitions_RA;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->npdcch_Offset_RA = extra_phy_parms->nprach_config_1_npdcch_offset_RA;
+		  fp->nprach_config_common.nprach_ParametersList.list.array[1]->maxNumPreambleAttemptCE = extra_phy_parms->nprach_config_1_max_num_preamble_attempt_CE;
+		  //fp->nprach_config_common.rsrp_ThresholdsPrachInfoList.list /*OPTIONAL*/
+
+	  }
+
+	  if(config->nprach_config_2_enabled.value == 1){
+		  LOG_D(PHY, "NPRACH Config #2 enabled\n");
+
+		  fp->nprach_config_common.nprach_CP_Length = config->nprach_config_2_cp_length.value; //NPRACH_ConfigSIB_NB_r13__nprach_CP_Length_r13_us66dot7
+		  LOG_D(PHY," config#2: nprach_CP_Length = %d\n",fp->nprach_config_common.nprach_CP_Length);
+		  //FIXME: MP: memory for the list should be allocated? initialization?? where??
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_Periodicity = config->nprach_config_2_sf_periodicity.value;
+		  LOG_D(PHY,"config#2: nprach_Periodicity = %d\n", fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_Periodicity);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_StartTime = config->nprach_config_2_start_time.value;
+		  LOG_D(PHY,"config#2: nprach_StartTime = %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_StartTime);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_SubcarrierOffset = config->nprach_config_2_subcarrier_offset.value;
+		  LOG_D(PHY,"config#2: nprach_SubcarrierOffset= %d\n", fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_SubcarrierOffset);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_NumSubcarriers = config->nprach_config_2_number_of_subcarriers.value;
+		  LOG_D(PHY,"config#2: nprach_NumSubcarriers= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_NumSubcarriers);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->numRepetitionsPerPreambleAttempt = config->nprach_config_2_number_of_repetitions_per_attempt.value;
+		  LOG_D(PHY,"config#2: numRepetitionsPerPreambleAttempt= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->numRepetitionsPerPreambleAttempt);
+
+		  //missed configuration in FAPI config_request (TS 36.331 pag 610) (may not needed)
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_SubcarrierMSG3_RangeStart = extra_phy_parms->nprach_config_2_subcarrier_MSG3_range_start;
+		  LOG_D(PHY,"config#2: nprach_SubcarrierMSG3_RangeStart= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->nprach_SubcarrierMSG3_RangeStart);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->npdcch_StartSF_CSS_RA = extra_phy_parms->nprach_config_2_npdcch_startSF_CSS_RA;
+		  LOG_D(PHY,"config#2: npdcch_StartSF_CSS_RA= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->npdcch_StartSF_CSS_RA);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->npdcch_NumRepetitions_RA = extra_phy_parms->nprach_config_2_npdcch_num_repetitions_RA;
+		  LOG_D(PHY,"config#2: npdcch_NumRepetitions_RA= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->npdcch_NumRepetitions_RA);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->npdcch_Offset_RA = extra_phy_parms->nprach_config_2_npdcch_offset_RA;
+		  LOG_D(PHY,"config#2: npdcch_Offset_RA= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->npdcch_Offset_RA);
+		  fp->nprach_config_common.nprach_ParametersList.list.array[2]->maxNumPreambleAttemptCE = extra_phy_parms->nprach_config_2_max_num_preamble_attempt_CE;
+		  LOG_D(PHY,"config#2: maxNumPreambleAttemptCE= %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[2]->maxNumPreambleAttemptCE);
+		  //fp->nprach_config_common.rsrp_ThresholdsPrachInfoList.list /*OPTIONAL*/
+
+	  }
+
+	  //TODO: Should modify to compute_nprach_seq --> nprach.
+	  //compute_prach_seq(&fp->prach_config_common,fp->frame_type,PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->X_u);
+	  
+
+	  /*NPDSCH ConfigCommon-------------------------------------------------------------------*/
+	  //NPDSCH_ConfigCommon_NB_r13_t b;
+
+	  //FIXME: the FAPI specs pag 140 fix a range of value (0->255) but i don't find any similar correspondence in the 3GPP specs (TS 36.331 pag 608 and TS 36.213 ch 16.2.2)
+	  fp->npdsch_config_common.nrs_Power = rf_config->reference_signal_power.value;
+	
+	  /*NPUSCH ConfigCommon-------------------------------------------------------------------*/
+	  //NPUSCH_ConfigCommon_NB_r13_t c;
+
+	  fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence = config->three_tone_base_sequence.value;
+	  LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_BaseSequence = %d\n",fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence);
+	  fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence = config->six_tone_base_sequence.value;
+	  LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_BaseSequence = %d\n",fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence);
+	  fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift = config->three_tone_cyclic_shift.value;
+	  LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_CyclicShift = %d\n",fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift);
+	  fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift = config->six_tone_cyclic_shift.value;
+	  LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_CyclicShift = %d\n",fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift);
+	  fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence= config->twelve_tone_base_sequence.value;
+	  LOG_D(PHY,"npusch_config_common.dmrs_Config.twelveTone_BaseSequence = %d\n",fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence);
+
+
+	  fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled = ul_nrs_config->uplink_rs_hopping.value;
+	  LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled = %d\n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled);
+	  LOG_D(PHY,"**%s**\n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled == 1 ? "RS_GROUP_HOPPING" : "RS_NO_HOPPING");
+	  fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH = ul_nrs_config->group_assignment.value;
+	  LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH = %d]n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH);
+
+
+
+	  //MP: FAPI missed parameters (may not needed at eNB side and some of them are optional by the 3GPP specs)
+	  //fp->npusch_config_common.ack_NACK_NumRepetitions_Msg4 --> list of size maxNPRACH_Resources_NB_r13 (3 elements)
+	  //fp->npusch_config_common.srs_SubframeConfig /*OPTIONAL*/
+
+
+	  //No Frequency hopping in NULSCH for NB-IoT and not init_ncs_cell used for PUCCH
+
+
+	  /*UL Power Control Config Common---------------------------------------------------------*/
+	  //F nothing has been defined in FAPI specs for this (may because are only UE stuffs)
+	  fp->ul_power_control_config_common.p0_NominalNPUSCH = extra_phy_parms->p0_nominal_npusch;
+	  fp->ul_power_control_config_common.alpha = extra_phy_parms->alpha;
+	  fp->ul_power_control_config_common.deltaPreambleMsg3 = extra_phy_parms->delta_preamle_MSG3;
+
+	  /*DL gap Config - OPTIONAL----------------------------------------------------------------*/
+	  //DL_GapConfig_NB_r13_t a;
+	  if(config->dl_gap_config_enable.value == 1){
+		  fp->DL_gap_config.dl_GapDurationCoeff= config->dl_gap_periodicity.value;
+		  fp->DL_gap_config.dl_GapPeriodicity = config->dl_gap_periodicity.value;
+		  fp->DL_gap_config.dl_GapThreshold = config->dl_gap_threshold.value;
+	  }
+
+
+}
+
+
+
+void phy_config_dedicated_eNB_NB_IoT(uint8_t 			Mod_id,
+                              		 int 				CC_id,
+                             		 uint16_t 			rnti,
+							 		 extra_phyConfig_t  *extra_parms)
+{
+	PHY_VARS_eNB_NB_IoT *eNB = PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id];
+	NB_IoT_eNB_NPDCCH_t *npdcch;
+	uint8_t UE_id = find_ue_NB_IoT(rnti,eNB);
+	
+	if (UE_id == -1) {
+
+		LOG_E( PHY, "[eNB %"PRIu8"] find_ue() returns -1\n", Mod_id);
+		return;
+	}
+	
+	//configure UE specific parameters for NPDCCH Search Space
+
+	if (eNB->npdcch[UE_id]) {
+		npdcch = eNB->npdcch[UE_id];
+		npdcch->rnti = rnti;
+		npdcch->npdcch_NumRepetitions = extra_parms->npdcch_NumRepetitions; //Rmax maybe is the only one needed
+		//npdcch->npdcch_Offset_USS = extra_parms->npdcch_Offset_USS;
+		//npdcch->npdcch_StartSF_USS = extra_parms->npdcch_StartSF_USS;
+
+		LOG_I(PHY,"phy_config_dedicated_eNB_NB_IoT: npdcch_NumRepetitions = %d\n",npdcch->npdcch_NumRepetitions);
+	
+	} else {
+		LOG_E(PHY,"[eNB %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, UE_id);
+		return;
+	}
+	
+}
+
+// void phy_init_lte_top_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms)
+// {
+
+// //   crcTableInit();
+
+// //   ccodedot11_init();
+// //   ccodedot11_init_inv();
+
+// //   ccodelte_init();
+// //   ccodelte_init_inv();
+
+// //   treillis_table_init();
+
+// //   phy_generate_viterbi_tables();
+// //   phy_generate_viterbi_tables_lte();
+
+// //   init_td8();
+// //   init_td16();
+// // #ifdef __AVX2__
+// //   init_td16avx2();
+// // #endif
+
+// //   lte_sync_time_init(frame_parms);
+
+// //   generate_ul_ref_sigs();
+//   generate_ul_ref_sigs_rx_NB_IoT();
+
+//   // generate_64qam_table();
+//   // generate_16qam_table();
+//   // generate_RIV_tables();
+
+//   // init_unscrambling_lut();
+//   // init_scrambling_lut();
+//   // //set_taus_seed(1328);
+
+// }
+
+
diff --git a/openair1/PHY/INIT/lte_init_nb_iot.c b/openair1/PHY/INIT/lte_init_nb_iot.c
deleted file mode 100644
index 835c3aa3828f3bf90f688d8962d211b81d9f556b..0000000000000000000000000000000000000000
--- a/openair1/PHY/INIT/lte_init_nb_iot.c
+++ /dev/null
@@ -1,219 +0,0 @@
-/*
- * 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.0  (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
- */
-
-#include "defs.h"
-#include "SCHED/defs.h"
-#include "PHY/extern.h"
-#include "SIMULATION/TOOLS/defs.h"
-#include "RadioResourceConfigCommonSIB.h"
-#include "RadioResourceConfigDedicated.h"
-#include "TDD-Config.h"
-#include "LAYER2/MAC/extern.h"
-#include "MBSFN-SubframeConfigList.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-#define DEBUG_PHY
-#include "assertions.h"
-#include <math.h>
-
-//NB-IoT
-#include "defs_nb_iot.h"
-#include "RadioResourceConfigCommonSIB-NB-r13.h"
-#include "PHY/impl_defs_lte_nb_iot.h"
-#include "RadioResourceConfigDedicated-NB-r13.h"
-
-extern uint16_t prach_root_sequence_map0_3[838];
-extern uint16_t prach_root_sequence_map4[138];
-uint8_t dmrs1_tab[8] = {0,2,3,4,6,8,9,10};
-
-
-void NB_phy_config_mib_eNB(int                 Mod_id,
-			int                 CC_id,
-			int                 eutra_band,
-			int                 Nid_cell,
-			int                 Ncp,
-			int                 p_eNB,
-			uint32_t            dl_CarrierFreq,
-			uint32_t            ul_CarrierFreq) {
-
-  /*Not sure if phy parameters should be initial here or not*/
-  /*the phy_config_mib_eNB as the entry point to allocate the context for L1.  The RC contains the context for L1,L2. If RC.eNB is NULL, it hasn't been allocated earlier so we allocate it there.*/
-  /*if (RC.eNB == NULL) {
-    RC.eNB                               = (PHY_VARS_eNB ***)malloc((1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
-    LOG_I(PHY,"RC.eNB = %p\n",RC.eNB);
-    memset(RC.eNB,0,(1+NUMBER_OF_eNB_MAX)*sizeof(PHY_VARS_eNB***));
-  }
-  if (RC.eNB[Mod_id] == NULL) {
-    RC.eNB[Mod_id]                       = (PHY_VARS_eNB **)malloc((1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB**));
-    LOG_I(PHY,"RC.eNB[%d] = %p\n",Mod_id,RC.eNB[Mod_id]);
-    memset(RC.eNB[Mod_id],0,(1+MAX_NUM_CCs)*sizeof(PHY_VARS_eNB***));
-  }
-  if (RC.eNB[Mod_id][CC_id] == NULL) {
-    RC.eNB[Mod_id][CC_id] = (PHY_VARS_eNB *)malloc(sizeof(PHY_VARS_eNB));
-    LOG_I(PHY,"RC.eNB[%d][%d] = %p\n",Mod_id,CC_id,RC.eNB[Mod_id][CC_id]);
-    RC.eNB[Mod_id][CC_id]->Mod_id        = Mod_id;
-    RC.eNB[Mod_id][CC_id]->CC_id         = CC_id;
-  }
-
-  RC.eNB[Mod_id][CC_id]->mac_enabled     = 1;
-
-  fp = &RC.eNB[Mod_id][CC_id]->frame_parms; */
-
-  NB_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms;
-
-   //LOG_I(PHY,"Configuring MIB-NB for instance %d, CCid %d : (band %d,N_RB_DL %d,Nid_cell %d,p %d,DL freq %u)\n",
-	//Mod_id, CC_id, eutra_band, N_RB_DL_array[dl_Bandwidth], Nid_cell, p_eNB,dl_CarrierFreq);
-
-  fp->Nid_cell                           = Nid_cell;
-  fp->nushift                            = Nid_cell%6;
-  fp->eutra_band                         = eutra_band;
-  fp->Ncp                                = Ncp;
-  fp->nb_antenna_ports_eNB               = p_eNB;
-  fp->dl_CarrierFreq                     = dl_CarrierFreq;
-  fp->ul_CarrierFreq                     = ul_CarrierFreq;
-  
-
-  //init_frame_parms(fp,1);
-  //init_lte_top(fp);
-
-}
-
-void NB_phy_config_sib2_eNB(uint8_t Mod_id,
-                         int CC_id,
-                         RadioResourceConfigCommonSIB_NB_r13_t *radioResourceConfigCommon,
-                         ARFCN_ValueEUTRA_r9_t *ul_CArrierFreq
-                         )
-{
-	NB_DL_FRAME_PARMS *fp = &PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms;
-	  //LTE_eNB_UE_stats *eNB_UE_stats		= PHY_vars_eNB_g[Mod_id][CC_id]->eNB_UE_stats;
-	  //int32_t rx_total_gain_eNB_dB		= PHY_vars_eNB_g[Mod_id][CC_id]->rx_total_gain_eNB_dB;
-	  uint8_t MAX_NPRACH = 4;
-          NPRACH_Parameters_NB_r13_t *np;
-	  
-	  LOG_D(PHY,"[eNB%d] CCid %d: Applying radioResourceConfigCommon_NB\n",Mod_id,CC_id);
-	  
-      /*NPRACH configCommon*/
-	  fp->nprach_config_common.nprach_CP_Length                                     =radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_CP_Length = %d\n",fp->nprach_config_common.nprach_CP_Length);
-	  //fp->nprach_config_common.rsrp_ThresholdsPrachInfoList.list                    =radioResourceConfigCommon->nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13.list;
-	  //LOG_D(PHY,"nprach_config_common.rsrp_ThresholdsPrachInfoList = %d\n",fp->nprach_config_common.rsrp_ThresholdsPrachInfoList);
-
-	  /*Loop over the configuration according to the maxNPRACH_Resources*/
-      for (fp->CE=1; fp->CE <= MAX_NPRACH;fp->CE++){
-      np = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[fp->CE];	  	
-      /*fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->maxNumPreambleAttemptCE           =np->maxNumPreambleAttemptCE_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.maxNumPreambleAttemptCE = %d\n",fp->nprach_config_common.nprach_ParametersList.list.maxNumPreambleAttemptCE);
-      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_NumRepetitions_RA          =np->npdcch_NumRepetitions_RA_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_NumRepetitions_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.npdcch_NumRepetitions_RA);
-      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_Periodicity                =np->nprach_Periodicity_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_Periodicity = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_Periodicity);
-      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_StartTime                  =np->nprach_StartTime_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_StartTime = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_StartTime);
-      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_SubcarrierOffset           =np->nprach_SubcarrierOffset_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierOffset = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierOffset);
-      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->nprach_SubcarrierMSG3_RangeStart  =np->nprach_SubcarrierMSG3_RangeStart_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierMSG3_RangeStart = %d\n",fp->nprach_config_common.nprach_ParametersList.list.nprach_SubcarrierMSG3_RangeStart);
-      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_Offset_RA                  =np->npdcch_Offset_RA_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_Offset_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.npdcch_Offset_RA);
-      fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_StartSF_CSS_RA             =np->npdcch_StartSF_CSS_RA_r13;
-	  //LOG_D(PHY,"nprach_config_common.nprach_ParametersList.list.npdcch_StartSF_CSS_RA = %d\n",fp->nprach_config_common.nprach_ParametersList.list.array[fp->CE]->npdcch_StartSF_CSS_RA);
-      */	  
-      }
-
-	  /*Should modify to compute_nprach_seq*/
-	  //compute_prach_seq(&fp->prach_config_common,fp->frame_type,PHY_vars_eNB_g[Mod_id][CC_id]->X_u);
-	  
-	  /*NPDSCH ConfigCommon*/
-	  fp->npdsch_config_common.nrs_Power           = radioResourceConfigCommon->npdsch_ConfigCommon_r13.nrs_Power_r13;
-	
-	  /*NPUSCH ConfigCommon*/
-	  /*A list (1-3) should be loop for ack_NACK_NumRepetitions_Msg4*/
-	  for (fp->CE=1; fp->CE <= MAX_NPRACH;fp->CE++){
-	  fp->npusch_config_common.ack_NACK_NumRepetitions_Msg4[fp->CE]        = radioResourceConfigCommon->npusch_ConfigCommon_r13.ack_NACK_NumRepetitions_Msg4_r13.list.array[fp->CE];
-          //LOG_D(PHY,"npusch_config_common.ack_NACK_NumRepetitions_Msg4 = %d]n",fp->npusch_config_common.ack_NACK_NumRepetitions_Msg4);
-	  }
-	  fp->npusch_config_common.srs_SubframeConfig                          = radioResourceConfigCommon->npusch_ConfigCommon_r13.srs_SubframeConfig_r13;
-	  LOG_D(PHY,"npusch_config_common.srs_SubframeConfig = %d]n",fp->npusch_config_common.srs_SubframeConfig);
-	  fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence          = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_BaseSequence_r13;
-	  LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.threeTone_BaseSequence);
-	  fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence            = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_BaseSequence_r13;
-	  LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.sixTone_BaseSequence);
-	  fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift           = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13;
-	  LOG_D(PHY,"npusch_config_common.dmrs_Config.threeTone_CyclicShift = %d]n",fp->npusch_config_common.dmrs_Config.threeTone_CyclicShift);
-	  fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift             = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13;
-	  LOG_D(PHY,"npusch_config_common.dmrs_Config.sixTone_CyclicShift = %d]n",fp->npusch_config_common.dmrs_Config.sixTone_CyclicShift);
-	  fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence         = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->twelveTone_BaseSequence_r13;
-	  LOG_D(PHY,"npusch_config_common.dmrs_Config.twelveTone_BaseSequence = %d]n",fp->npusch_config_common.dmrs_Config.twelveTone_BaseSequence);
-
-	  fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH  = radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13;
-	  LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH = %d]n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH);
-	  fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled    = radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13;
-	  LOG_D(PHY,"npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled = %d]n",fp->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled);
-
-      /*should change the part that implement the ul hopping in NB-IoT*/
-	  //init_ul_hopping(fp);
-
-	  /*UL Power Control Config Common*/
-	
-	  fp->ul_power_control_config_common.p0_NominalNPUSCH      = radioResourceConfigCommon->uplinkPowerControlCommon_r13.p0_NominalNPUSCH_r13;
-	  fp->ul_power_control_config_common.alpha				   = radioResourceConfigCommon->uplinkPowerControlCommon_r13.alpha_r13;
-      fp->ul_power_control_config_common.deltaPreambleMsg3     = radioResourceConfigCommon->uplinkPowerControlCommon_r13.deltaPreambleMsg3_r13;
-
-	  /*DL gap*/
-                                                                                                    
-      fp->DL_gap_config.dl_GapDurationCoeff                        = radioResourceConfigCommon->dl_Gap_r13->dl_GapDurationCoeff_r13;
-	  fp->DL_gap_config.dl_GapPeriodicity                      = radioResourceConfigCommon->dl_Gap_r13->dl_GapPeriodicity_r13;
-	  fp->DL_gap_config.dl_GapThreshold                        = radioResourceConfigCommon->dl_Gap_r13->dl_GapThreshold_r13;
-	  
-	  /*PUCCH stuff in LTE*/
-	  //init_ncs_cell(fp,PHY_vars_eNB_g[Mod_id][CC_id]->ncs_cell);
-	
-	  //init_ul_hopping(fp);
-	
-	
-	  
-}
-
-void NB_phy_config_dedicated_eNB(uint8_t Mod_id,
-                              int CC_id,
-                              uint16_t rnti,
-                              struct PhysicalConfigDedicated_NB_r13 *physicalConfigDedicated)
-{
-	  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[Mod_id][CC_id];
-	  int8_t UE_id = find_ue(rnti,eNB);
-	
-	  if (UE_id == -1) {
-		LOG_E( PHY, "[eNB %"PRIu8"] find_ue() returns -1\n", Mod_id);
-		return;
-	  }
-	
-	/*physicalconfigDedicated is defined in PHY_VARS_eNB in defs.h in PHY layer*/
-	  if (physicalConfigDedicated) {
-		eNB->physicalConfigDedicated[UE_id] = physicalConfigDedicated;
-		LOG_I(PHY,"phy_config_dedicated_eNB: physicalConfigDedicated=%p\n",physicalConfigDedicated);
-	
-	  } else {
-		LOG_E(PHY,"[eNB %d] Received NULL radioResourceConfigDedicated from eNB %d\n",Mod_id, UE_id);
-		return;
-	  }
-	
-}
-
-
diff --git a/openair1/PHY/LTE_ESTIMATION/defs_NB_IoT.h b/openair1/PHY/LTE_ESTIMATION/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..c786e6341c93ed470524ee0f650f42b833649ca0
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/defs_NB_IoT.h
@@ -0,0 +1,61 @@
+/*
+ * 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.0  (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 __LTE_ESTIMATION_DEFS_NB_IOT__H__
+#define __LTE_ESTIMATION_DEFS_NB_IOT__H__
+
+#include "PHY/defs_NB_IoT.h"
+
+/*
+int lte_est_timing_advance(NB_IoT_DL_FRAME_PARMS *frame_parms,
+                           NB_IoT_eNB_SRS *lte_eNb_srs,
+                           unsigned int *eNb_id,
+                           unsigned char clear,
+                           unsigned char number_of_cards,
+                           short coef);
+*/
+
+int NB_IoT_est_timing_advance_pusch(PHY_VARS_eNB_NB_IoT* phy_vars_eNB,module_id_t UE_id);
+
+
+
+int lte_ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT      *phy_vars_eNB,
+			      					 eNB_rxtx_proc_NB_IoT_t   *proc,
+                              		 module_id_t              eNB_id,
+                              		 module_id_t              UE_id,
+                              		 uint8_t                  l,
+                              		 uint8_t                  Ns,
+                              		 uint8_t                  cooperation_flag);
+
+int16_t lte_ul_freq_offset_estimation_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
+                                      		 int32_t *ul_ch_estimates,
+                                      		 uint16_t nb_rb);
+
+void freq_equalization_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
+                       		  int **rxdataF_comp,
+                       		  int **ul_ch_mag,
+                       		  int **ul_ch_mag_b,
+                       		  unsigned char symbol,
+                       	      unsigned short Msc_RS,
+                              unsigned char Qm);
+
+/** @} */
+#endif
diff --git a/openair1/PHY/LTE_ESTIMATION/freq_equalization_NB_IoT.c b/openair1/PHY/LTE_ESTIMATION/freq_equalization_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..cbc02afaafc4a13c0cf6ebcadd05852a37a0fe40
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/freq_equalization_NB_IoT.c
@@ -0,0 +1,337 @@
+/*
+ * 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.0  (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
+ */
+
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/extern_NB_IoT.h"
+//#include "PHY/sse_intrin.h"
+
+// This is 512/(1:256) in __m128i format
+int16_t inv_ch_NB_IoT[256*8] = {512,512,512,512,512,512,512,512,
+                         256,256,256,256,256,256,256,256,
+                         170,170,170,170,170,170,170,170,
+                         128,128,128,128,128,128,128,128,
+                         102,102,102,102,102,102,102,102,
+                         85,85,85,85,85,85,85,85,
+                         73,73,73,73,73,73,73,73,
+                         64,64,64,64,64,64,64,64,
+                         56,56,56,56,56,56,56,56,
+                         51,51,51,51,51,51,51,51,
+                         46,46,46,46,46,46,46,46,
+                         42,42,42,42,42,42,42,42,
+                         39,39,39,39,39,39,39,39,
+                         36,36,36,36,36,36,36,36,
+                         34,34,34,34,34,34,34,34,
+                         32,32,32,32,32,32,32,32,
+                         30,30,30,30,30,30,30,30,
+                         28,28,28,28,28,28,28,28,
+                         26,26,26,26,26,26,26,26,
+                         25,25,25,25,25,25,25,25,
+                         24,24,24,24,24,24,24,24,
+                         23,23,23,23,23,23,23,23,
+                         22,22,22,22,22,22,22,22,
+                         21,21,21,21,21,21,21,21,
+                         20,20,20,20,20,20,20,20,
+                         19,19,19,19,19,19,19,19,
+                         18,18,18,18,18,18,18,18,
+                         18,18,18,18,18,18,18,18,
+                         17,17,17,17,17,17,17,17,
+                         17,17,17,17,17,17,17,17,
+                         16,16,16,16,16,16,16,16,
+                         16,16,16,16,16,16,16,16,
+                         15,15,15,15,15,15,15,15,
+                         15,15,15,15,15,15,15,15,
+                         14,14,14,14,14,14,14,14,
+                         14,14,14,14,14,14,14,14,
+                         13,13,13,13,13,13,13,13,
+                         13,13,13,13,13,13,13,13,
+                         13,13,13,13,13,13,13,13,
+                         12,12,12,12,12,12,12,12,
+                         12,12,12,12,12,12,12,12,
+                         12,12,12,12,12,12,12,12,
+                         11,11,11,11,11,11,11,11,
+                         11,11,11,11,11,11,11,11,
+                         11,11,11,11,11,11,11,11,
+                         11,11,11,11,11,11,11,11,
+                         10,10,10,10,10,10,10,10,
+                         10,10,10,10,10,10,10,10,
+                         10,10,10,10,10,10,10,10,
+                         10,10,10,10,10,10,10,10,
+                         10,10,10,10,10,10,10,10,
+                         9,9,9,9,9,9,9,9,
+                         9,9,9,9,9,9,9,9,
+                         9,9,9,9,9,9,9,9,
+                         9,9,9,9,9,9,9,9,
+                         9,9,9,9,9,9,9,9,
+                         8,8,8,8,8,8,8,8,
+                         8,8,8,8,8,8,8,8,
+                         8,8,8,8,8,8,8,8,
+                         8,8,8,8,8,8,8,8,
+                         8,8,8,8,8,8,8,8,
+                         8,8,8,8,8,8,8,8,
+                         8,8,8,8,8,8,8,8,
+                         8,8,8,8,8,8,8,8,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         7,7,7,7,7,7,7,7,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         6,6,6,6,6,6,6,6,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         5,5,5,5,5,5,5,5,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         4,4,4,4,4,4,4,4,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         3,3,3,3,3,3,3,3,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                         2,2,2,2,2,2,2,2,
+                        };
+
+void freq_equalization_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
+                              int32_t **rxdataF_comp,
+                              int32_t **ul_ch_mag,
+                              int32_t **ul_ch_magb,
+                              uint8_t symbol,
+                              uint16_t Msc_RS,
+                              uint8_t Qm)
+{
+  uint16_t re;
+  int16_t amp;
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i *ul_ch_mag128,*ul_ch_magb128,*rxdataF_comp128;
+  rxdataF_comp128   = (__m128i *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12];
+  ul_ch_mag128      = (__m128i *)&ul_ch_mag[0][symbol*frame_parms->N_RB_DL*12];
+  ul_ch_magb128      = (__m128i *)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12];
+#elif defined(__arm__)
+  int16x8_t *ul_ch_mag128,*ul_ch_magb128,*rxdataF_comp128;
+  rxdataF_comp128   = (int16x8_t*)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12];
+  ul_ch_mag128      = (int16x8_t*)&ul_ch_mag[0][symbol*frame_parms->N_RB_DL*12];
+  ul_ch_magb128     = (int16x8_t*)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12];
+#endif
+
+  for (re=0; re<(Msc_RS>>2); re++) {
+
+    amp=(*((int16_t*)&ul_ch_mag128[re]));
+
+    if (amp>255)
+      amp=255;
+
+    //     printf("freq_eq: symbol %d re %d => %d,%d,%d, (%d) (%d,%d) => ",symbol,re,*((int16_t*)(&ul_ch_mag128[re])),amp,inv_ch[8*amp],*((int16_t*)(&ul_ch_mag128[re]))*inv_ch[8*amp],*(int16_t*)&(rxdataF_comp128[re]),*(1+(int16_t*)&(rxdataF_comp128[re])));
+#if defined(__x86_64__) || defined(__i386__)
+    rxdataF_comp128[re] = _mm_mullo_epi16(rxdataF_comp128[re],*((__m128i *)&inv_ch_NB_IoT[8*amp]));
+
+    if (Qm==4)
+      ul_ch_mag128[re]  = _mm_set1_epi16(324);  // this is 512*2/sqrt(10)
+   // else {
+    //  ul_ch_mag128[re]  = _mm_set1_epi16(316);  // this is 512*4/sqrt(42)
+    //  ul_ch_magb128[re] = _mm_set1_epi16(158);  // this is 512*2/sqrt(42)
+   // }
+#elif defined(__arm__)
+    rxdataF_comp128[re] = vmulq_s16(rxdataF_comp128[re],*((int16x8_t *)&inv_ch_NB_IoT[8*amp]));
+
+    if (Qm==4)
+      ul_ch_mag128[re]  = vdupq_n_s16(324);  // this is 512*2/sqrt(10)
+    //else {
+    //  ul_ch_mag128[re]  = vdupq_n_s16(316);  // this is 512*4/sqrt(42)
+    //  ul_ch_magb128[re] = vdupq_n_s16(158);  // this is 512*2/sqrt(42)
+    //}
+#endif
+    //            printf("(%d,%d)\n",*(int16_t*)&(rxdataF_comp128[re]),*(1+(int16_t*)&(rxdataF_comp128[re])));
+
+  }
+}
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_NB_IoT.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..dad3d564833ed6bb7cac057c19b469d1ea23dd50
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync_NB_IoT.c
@@ -0,0 +1,75 @@
+/*
+ * 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.0  (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
+ */
+
+//#include "PHY/types.h"
+#include "PHY/defs_NB_IoT.h"
+//#include "PHY/extern.h"
+
+//#include "UTIL/LOG/vcd_signal_dumper.h"
+
+#define DEBUG_PHY
+
+int NB_IoT_est_timing_advance_pusch(PHY_VARS_eNB_NB_IoT* eNB,uint8_t UE_id)
+{
+  static int first_run=1;
+  static int max_pos_fil2=0;
+  int temp, i, aa, max_pos=0, max_val=0;
+  short Re,Im,coef=24576;
+  short ncoef = 32768 - coef;
+
+  NB_IoT_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
+  NB_IoT_eNB_PUSCH *eNB_pusch_vars = eNB->pusch_vars[UE_id];
+  int32_t **ul_ch_estimates_time=  eNB_pusch_vars->drs_ch_estimates_time[0];
+  uint8_t cyclic_shift = 0;
+  int sync_pos = (frame_parms->ofdm_symbol_size-cyclic_shift*frame_parms->ofdm_symbol_size/12)%(frame_parms->ofdm_symbol_size);
+
+
+  for (i = 0; i < frame_parms->ofdm_symbol_size; i++) {
+    temp = 0;
+
+    for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
+      Re = ((int16_t*)ul_ch_estimates_time[aa])[(i<<1)];
+      Im = ((int16_t*)ul_ch_estimates_time[aa])[1+(i<<1)];
+      temp += (Re*Re/2) + (Im*Im/2);
+    }
+
+    if (temp > max_val) {
+      max_pos = i;
+      max_val = temp;
+    }
+  }
+
+  if (max_pos>frame_parms->ofdm_symbol_size/2)
+    max_pos = max_pos-frame_parms->ofdm_symbol_size;
+
+  // filter position to reduce jitter
+  if (first_run == 1) {
+    first_run=0;
+    max_pos_fil2 = max_pos;
+  } else
+    max_pos_fil2 = ((max_pos_fil2 * coef) + (max_pos * ncoef)) >> 15;
+
+#ifdef DEBUG_PHY
+  LOG_D(PHY,"frame %d: max_pos = %d, max_pos_fil = %d, sync_pos=%d\n",eNB->proc.frame_rx,max_pos,max_pos_fil2,sync_pos);
+#endif //DEBUG_PHY
+
+  return(max_pos_fil2-sync_pos);
+}
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation_NB_IoT.c b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..75599f6206110a68c873332c675579cfe317651b
--- /dev/null
+++ b/openair1/PHY/LTE_ESTIMATION/lte_ul_channel_estimation_NB_IoT.c
@@ -0,0 +1,848 @@
+/*
+ * 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.0  (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
+ */
+
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/extern_NB_IoT.h"
+//#include "PHY/sse_intrin.h"
+#include <math.h>
+
+#include "PHY/LTE_ESTIMATION/defs_NB_IoT.h"
+#include "PHY/LTE_TRANSPORT/extern_NB_IoT.h"
+//#define DEBUG_CH
+
+#include "T.h"
+
+// For Channel Estimation in Distributed Alamouti Scheme
+//static int16_t temp_out_ifft[2048*4] __attribute__((aligned(16)));
+/*
+static int16_t temp_out_fft_0[2048*4] __attribute__((aligned(16)));
+static int16_t temp_out_fft_1[2048*4] __attribute__((aligned(16)));
+static int16_t temp_out_ifft_0[2048*4] __attribute__((aligned(16)));
+static int16_t temp_out_ifft_1[2048*4] __attribute__((aligned(16)));
+*/
+
+static int32_t temp_in_ifft_0[2048*2] __attribute__((aligned(32)));
+//static int32_t temp_in_ifft_1[2048*2] __attribute__((aligned(32)));
+//static int32_t temp_in_fft_0[2048*2] __attribute__((aligned(16)));
+static int32_t temp_in_fft_1[2048*2] __attribute__((aligned(16)));
+
+// round(exp(sqrt(-1)*(pi/2)*[0:1:N-1]/N)*pow2(15))
+static int16_t ru_90[2*128] = {32767, 0,32766, 402,32758, 804,32746, 1206,32729, 1608,32706, 2009,32679, 2411,32647, 2811,32610, 3212,32568, 3612,32522, 4011,32470, 4410,32413, 4808,32352, 5205,32286, 5602,32214, 5998,32138, 6393,32058, 6787,31972, 7180,31881, 7571,31786, 7962,31686, 8351,31581, 8740,31471, 9127,31357, 9512,31238, 9896,31114, 10279,30986, 10660,30853, 11039,30715, 11417,30572, 11793,30425, 12167,30274, 12540,30118, 12910,29957, 13279,29792, 13646,29622, 14010,29448, 14373,29269, 14733,29086, 15091,28899, 15447,28707, 15800,28511, 16151,28311, 16500,28106, 16846,27897, 17190,27684, 17531,27467, 17869,27246, 18205,27020, 18538,26791, 18868,26557, 19195,26320, 19520,26078, 19841,25833, 20160,25583, 20475,25330, 20788,25073, 21097,24812, 21403,24548, 21706,24279, 22006,24008, 22302,23732, 22595,23453, 22884,23170, 23170,22884, 23453,22595, 23732,22302, 24008,22006, 24279,21706, 24548,21403, 24812,21097, 25073,20788, 25330,20475, 25583,20160, 25833,19841, 26078,19520, 26320,19195, 26557,18868, 26791,18538, 27020,18205, 27246,17869, 27467,17531, 27684,17190, 27897,16846, 28106,16500, 28311,16151, 28511,15800, 28707,15447, 28899,15091, 29086,14733, 29269,14373, 29448,14010, 29622,13646, 29792,13279, 29957,12910, 30118,12540, 30274,12167, 30425,11793, 30572,11417, 30715,11039, 30853,10660, 30986,10279, 31114,9896, 31238,9512, 31357,9127, 31471,8740, 31581,8351, 31686,7962, 31786,7571, 31881,7180, 31972,6787, 32058,6393, 32138,5998, 32214,5602, 32286,5205, 32352,4808, 32413,4410, 32470,4011, 32522,3612, 32568,3212, 32610,2811, 32647,2411, 32679,2009, 32706,1608, 32729,1206, 32746,804, 32758,402, 32766};
+
+static int16_t ru_90c[2*128] = {32767, 0,32766, -402,32758, -804,32746, -1206,32729, -1608,32706, -2009,32679, -2411,32647, -2811,32610, -3212,32568, -3612,32522, -4011,32470, -4410,32413, -4808,32352, -5205,32286, -5602,32214, -5998,32138, -6393,32058, -6787,31972, -7180,31881, -7571,31786, -7962,31686, -8351,31581, -8740,31471, -9127,31357, -9512,31238, -9896,31114, -10279,30986, -10660,30853, -11039,30715, -11417,30572, -11793,30425, -12167,30274, -12540,30118, -12910,29957, -13279,29792, -13646,29622, -14010,29448, -14373,29269, -14733,29086, -15091,28899, -15447,28707, -15800,28511, -16151,28311, -16500,28106, -16846,27897, -17190,27684, -17531,27467, -17869,27246, -18205,27020, -18538,26791, -18868,26557, -19195,26320, -19520,26078, -19841,25833, -20160,25583, -20475,25330, -20788,25073, -21097,24812, -21403,24548, -21706,24279, -22006,24008, -22302,23732, -22595,23453, -22884,23170, -23170,22884, -23453,22595, -23732,22302, -24008,22006, -24279,21706, -24548,21403, -24812,21097, -25073,20788, -25330,20475, -25583,20160, -25833,19841, -26078,19520, -26320,19195, -26557,18868, -26791,18538, -27020,18205, -27246,17869, -27467,17531, -27684,17190, -27897,16846, -28106,16500, -28311,16151, -28511,15800, -28707,15447, -28899,15091, -29086,14733, -29269,14373, -29448,14010, -29622,13646, -29792,13279, -29957,12910, -30118,12540, -30274,12167, -30425,11793, -30572,11417, -30715,11039, -30853,10660, -30986,10279, -31114,9896, -31238,9512, -31357,9127, -31471,8740, -31581,8351, -31686,7962, -31786,7571, -31881,7180, -31972,6787, -32058,6393, -32138,5998, -32214,5602, -32286,5205, -32352,4808, -32413,4410, -32470,4011, -32522,3612, -32568,3212, -32610,2811, -32647,2411, -32679,2009, -32706,1608, -32729,1206, -32746,804, -32758,402, -32766};
+
+#define SCALE 0x3FFF
+
+int32_t lte_ul_channel_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT      *eNB,
+				                                 eNB_rxtx_proc_NB_IoT_t   *proc,
+                                         uint8_t                  eNB_id,
+                                         uint8_t                  UE_id,
+                                         unsigned char            l,
+                                         unsigned char            Ns,
+                                         uint8_t                  cooperation_flag)
+{
+
+  NB_IoT_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
+  NB_IoT_eNB_PUSCH *pusch_vars = eNB->pusch_vars[UE_id];
+  int32_t **ul_ch_estimates=pusch_vars->drs_ch_estimates[eNB_id];
+  int32_t **ul_ch_estimates_time=  pusch_vars->drs_ch_estimates_time[eNB_id];
+  //int32_t **ul_ch_estimates_0=  pusch_vars->drs_ch_estimates_0[eNB_id];
+  //int32_t **ul_ch_estimates_1=  pusch_vars->drs_ch_estimates_1[eNB_id];
+  int32_t **rxdataF_ext=  pusch_vars->rxdataF_ext[eNB_id];
+  int subframe = proc->subframe_rx;
+  //uint8_t harq_pid = subframe2harq_pid_NB_IoT(frame_parms,proc->frame_rx,subframe);
+  int16_t delta_phase = 0;
+  int16_t *ru1 = ru_90;
+  int16_t *ru2 = ru_90;
+  int16_t current_phase1,current_phase2;
+  uint16_t N_rb_alloc = eNB->ulsch[UE_id]->harq_process->nb_rb;
+  uint16_t aa,Msc_RS,Msc_RS_idx;
+  uint16_t * Msc_idx_ptr;
+  int k,pilot_pos1 = 3 - frame_parms->Ncp, pilot_pos2 = 10 - 2*frame_parms->Ncp;
+  int16_t alpha, beta;
+  int32_t *ul_ch1=NULL, *ul_ch2=NULL;
+  //int32_t *ul_ch1_0=NULL,*ul_ch2_0=NULL,*ul_ch1_1=NULL,*ul_ch2_1=NULL;
+  int16_t ul_ch_estimates_re,ul_ch_estimates_im;
+  int32_t rx_power_correction;
+
+  //uint8_t nb_antennas_rx = frame_parms->nb_antenna_ports_eNB;
+  uint8_t nb_antennas_rx = frame_parms->nb_antennas_rx;
+  uint8_t cyclic_shift;
+
+  uint32_t alpha_ind;
+  uint32_t u;//=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[Ns+(subframe<<1)];
+  //uint32_t v=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.seqhop[Ns+(subframe<<1)];
+  int32_t tmp_estimates[N_rb_alloc*12] __attribute__((aligned(16)));
+
+  int symbol_offset,i;
+  //int j;
+
+  //debug_msg("lte_ul_channel_estimation: cyclic shift %d\n",cyclicShift);
+
+
+  int16_t alpha_re[12] = {32767, 28377, 16383,     0,-16384,  -28378,-32768,-28378,-16384,    -1, 16383, 28377};
+  int16_t alpha_im[12] = {0,     16383, 28377, 32767, 28377,   16383,     0,-16384,-28378,-32768,-28378,-16384}; 
+
+  ////// NB-IoT specific //////
+
+  uint32_t I_sc = eNB->ulsch[UE_id]->harq_process->I_sc;  // NB_IoT: subcarrier indication field: must be defined in higher layer
+  uint16_t ul_sc_start; // subcarrier start index into UL RB 
+
+  // 36.211, Section 10.1.4.1.2, Table 10.1.4.1.2-3 
+  double alpha3[3] = {0 , M_PI*2/3, M_PI*4/3}; 
+  double alpha6[4] = {0 , M_PI*2/6, M_PI*4/6, M_PI*8/6}; 
+  uint8_t threetnecyclicshift=0, sixtonecyclichift=0; // NB-IoT: to be defined from higher layer, see 36.211 Section 10.1.4.1.2
+  uint16_t Nsc_RU; // Vincent: number of sc 1,3,6,12 
+  unsigned int index_Nsc_RU; // Vincent: index_Nsc_RU 0,1,2,3 ---> number of sc 1,3,6,12 
+
+
+ /* 
+      int32_t *in_fft_ptr_0 = (int32_t*)0,*in_fft_ptr_1 = (int32_t*)0,
+           *temp_out_fft_0_ptr = (int32_t*)0,*out_fft_ptr_0 = (int32_t*)0,
+            *temp_out_fft_1_ptr = (int32_t*)0,*out_fft_ptr_1 = (int32_t*)0,
+             *temp_in_ifft_ptr = (int32_t*)0; 
+*/
+
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i *rxdataF128,*ul_ref128,*ul_ch128;
+  __m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3;
+#elif defined(__arm__)
+  int16x8_t *rxdataF128,*ul_ref128,*ul_ch128;
+  int32x4_t mmtmp0,mmtmp1,mmtmp_re,mmtmp_im;
+#endif
+  Msc_RS = N_rb_alloc*12;
+
+  cyclic_shift = (frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.cyclicShift +
+                  eNB->ulsch[UE_id]->harq_process->n_DMRS2 +
+                  frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.nPRS[(subframe<<1)+Ns]) % 12;
+
+#if defined(USER_MODE)
+  Msc_idx_ptr = (uint16_t*) bsearch(&Msc_RS, dftsizes, 33, sizeof(uint16_t), compareints);
+
+  if (Msc_idx_ptr)
+    Msc_RS_idx = Msc_idx_ptr - dftsizes;
+  else {
+    msg("lte_ul_channel_estimation: index for Msc_RS=%d not found\n",Msc_RS);
+    return(-1);
+  }
+
+#else
+  uint8_t b;
+
+  for (b=0; b<33; b++)
+    if (Msc_RS==dftsizes[b])
+      Msc_RS_idx = b;
+
+#endif
+
+  //  LOG_I(PHY,"subframe %d, Ns %d, l %d, Msc_RS = %d, Msc_RS_idx = %d, u %d, v %d, cyclic_shift %d\n",subframe,Ns,l,Msc_RS, Msc_RS_idx,u,v,cyclic_shift);
+#ifdef DEBUG_CH
+
+#ifdef USER_MODE
+
+  if (Ns==0)
+    write_output("drs_seq0.m","drsseq0",ul_ref_sigs_rx[u][Msc_RS_idx],2*Msc_RS,2,1);
+  else
+    write_output("drs_seq1.m","drsseq1",ul_ref_sigs_rx[u][Msc_RS_idx],2*Msc_RS,2,1);
+
+#endif
+#endif
+
+  rx_power_correction = 1;
+  ul_sc_start = get_UL_sc_start_NB_IoT(I_sc); // NB-IoT: get the used subcarrier in RB
+  u=frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[Ns+(subframe<<1)][index_Nsc_RU]; // Vincent: may be adapted for Nsc_RU, see 36.211, Section 10.1.4.1.3
+
+  if (l == (3 - frame_parms->Ncp)) { 
+
+    // symbol_offset = frame_parms->N_RB_UL*12*(l+((7-frame_parms->Ncp)*(Ns&1))); 
+    symbol_offset = frame_parms->N_RB_UL*12*(l+(7*(Ns&1)));
+
+    for (aa=0; aa<nb_antennas_rx; aa++) {
+      //           msg("Componentwise prod aa %d, symbol_offset %d,ul_ch_estimates %p,ul_ch_estimates[aa] %p,ul_ref_sigs_rx[0][0][Msc_RS_idx] %p\n",aa,symbol_offset,ul_ch_estimates,ul_ch_estimates[aa],ul_ref_sigs_rx[0][0][Msc_RS_idx]);
+
+#if defined(__x86_64__) || defined(__i386__)
+      rxdataF128 = (__m128i *)&rxdataF_ext[aa][symbol_offset];
+      ul_ch128   = (__m128i *)&ul_ch_estimates[aa][symbol_offset];
+      if (index_Nsc_RU){
+        ul_ref128  = (__m128i *)ul_ref_sigs_rx[u][index_Nsc_RU][24-(ul_sc_start<<1)]; // pilot values are the same every slots
+        }else{
+        ul_ref128  = (__m128i *)ul_ref_sigs_rx[u][index_Nsc_RU][24 + 12*(subframe<<1)-(ul_sc_start<<1)]; // pilot values depends on the slots
+      }
+#elif defined(__arm__)
+      rxdataF128 = (int16x8_t *)&rxdataF_ext[aa][symbol_offset];
+      ul_ch128   = (int16x8_t *)&ul_ch_estimates[aa][symbol_offset]; 
+      if (index_Nsc_RU){
+        ul_ref128  = (int16x8_t *)ul_ref_sigs_rx[u][index_Nsc_RU][24-(ul_sc_start<<1)]; 
+      }else{
+        ul_ref128  = (int16x8_t *)ul_ref_sigs_rx[u][index_Nsc_RU][24 + 12*(subframe<<1)-(ul_sc_start<<1)]; 
+      }
+#endif
+
+      for (i=0; i<Msc_RS/12; i++) {
+#if defined(__x86_64__) || defined(__i386__)
+        // multiply by conjugated channel
+        mmtmpU0 = _mm_madd_epi16(ul_ref128[0],rxdataF128[0]);
+        // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+        mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[0],_MM_SHUFFLE(2,3,0,1));
+        mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+        mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)&conjugate[0]);
+        mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]);
+        // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+        mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
+        mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
+        mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+        mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+        ul_ch128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+        //  printf("rb %d ch: %d %d\n",i,((int16_t*)ul_ch128)[0],((int16_t*)ul_ch128)[1]);
+        // multiply by conjugated channel
+        mmtmpU0 = _mm_madd_epi16(ul_ref128[1],rxdataF128[1]);
+        // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+        mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[1],_MM_SHUFFLE(2,3,0,1));
+        mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+        mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+        mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]);
+        // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+        mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
+        mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
+        mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+        mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+        ul_ch128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+
+        mmtmpU0 = _mm_madd_epi16(ul_ref128[2],rxdataF128[2]);
+        // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+        mmtmpU1 = _mm_shufflelo_epi16(ul_ref128[2],_MM_SHUFFLE(2,3,0,1));
+        mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+        mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+        mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]);
+        // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+        mmtmpU0 = _mm_srai_epi32(mmtmpU0,15);
+        mmtmpU1 = _mm_srai_epi32(mmtmpU1,15);
+        mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+        mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+        ul_ch128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+#elif defined(__arm__)
+      mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]);
+      mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]);
+      mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
+                              vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
+      mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]);
+      mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]);
+      mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
+                              vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
+
+      ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
+      ul_ch128++;
+      ul_ref128++;
+      rxdataF128++;
+      mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]);
+      mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]);
+      mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
+                              vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
+      mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]);
+      mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]);
+      mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
+                              vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
+
+      ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
+      ul_ch128++;
+      ul_ref128++;
+      rxdataF128++;
+
+      mmtmp0 = vmull_s16(((int16x4_t*)ul_ref128)[0],((int16x4_t*)rxdataF128)[0]);
+      mmtmp1 = vmull_s16(((int16x4_t*)ul_ref128)[1],((int16x4_t*)rxdataF128)[1]);
+      mmtmp_re = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
+                              vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
+      mmtmp0 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[0],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[0]);
+      mmtmp1 = vmull_s16(vrev32_s16(vmul_s16(((int16x4_t*)ul_ref128)[1],*(int16x4_t*)conjugate)), ((int16x4_t*)rxdataF128)[1]);
+      mmtmp_im = vcombine_s32(vpadd_s32(vget_low_s32(mmtmp0),vget_high_s32(mmtmp0)),
+                              vpadd_s32(vget_low_s32(mmtmp1),vget_high_s32(mmtmp1)));
+
+      ul_ch128[0] = vcombine_s16(vmovn_s32(mmtmp_re),vmovn_s32(mmtmp_im));
+      ul_ch128++;
+      ul_ref128++;
+      rxdataF128++;
+
+
+#endif
+        ul_ch128+=3;
+        ul_ref128+=3;
+        rxdataF128+=3;
+      }
+
+      alpha_ind = 0;
+
+      if((cyclic_shift != 0) && Msc_RS != 12) {
+      // if(Nsc_RU != 1 && Nsc_RU != 12) {
+        // Compensating for the phase shift introduced at the transmitter
+        // In NB-IoT, phase alpha is zero when 12 subcarriers are allocated
+#ifdef DEBUG_CH
+        write_output("drs_est_pre.m","drsest_pre",ul_ch_estimates[0],300*12,1,1);
+#endif
+
+        for(i=symbol_offset; i<symbol_offset+Msc_RS; i++) {
+          ul_ch_estimates_re = ((int16_t*) ul_ch_estimates[aa])[i<<1];
+          ul_ch_estimates_im = ((int16_t*) ul_ch_estimates[aa])[(i<<1)+1];
+          //    ((int16_t*) ul_ch_estimates[aa])[i<<1] =  (i%2 == 1? 1:-1) * ul_ch_estimates_re;
+          ((int16_t*) ul_ch_estimates[aa])[i<<1] =
+            (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_re) +
+                        (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_im))>>15);
+
+          //((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] =  (i%2 == 1? 1:-1) * ul_ch_estimates_im;
+          ((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] =
+            (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_im) -
+                        (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_re))>>15);
+
+          alpha_ind+=cyclic_shift;
+
+          if (alpha_ind>11)
+            alpha_ind-=12;
+        }
+
+#ifdef DEBUG_CH
+        write_output("drs_est_post.m","drsest_post",ul_ch_estimates[0],300*12,1,1);
+#endif
+      }
+
+      //copy MIMO channel estimates to temporary buffer for EMOS
+      //memcpy(&ul_ch_estimates_0[aa][symbol_offset],&ul_ch_estimates[aa][symbol_offset],frame_parms->ofdm_symbol_size*sizeof(int32_t)*2);
+
+      memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t));
+
+      // Convert to time domain for visualization
+      for(i=0; i<Msc_RS; i++)
+        ((int32_t*)temp_in_ifft_0)[i] = ul_ch_estimates[aa][symbol_offset+i];
+      switch(frame_parms->N_RB_DL) {
+      case 6:
+	
+	idft128((int16_t*) temp_in_ifft_0,
+	       (int16_t*) ul_ch_estimates_time[aa],
+	       1);
+	break;
+      case 25:
+	
+	idft512((int16_t*) temp_in_ifft_0,
+	       (int16_t*) ul_ch_estimates_time[aa],
+	       1);
+	break;
+      case 50:
+	
+	idft1024((int16_t*) temp_in_ifft_0,
+	       (int16_t*) ul_ch_estimates_time[aa],
+	       1);
+	break;
+      case 100:
+	
+	idft2048((int16_t*) temp_in_ifft_0,
+	       (int16_t*) ul_ch_estimates_time[aa],
+	       1);
+	break;
+      }
+
+#if T_TRACER
+      if (aa == 0)
+        T(T_ENB_PHY_UL_CHANNEL_ESTIMATE, T_INT(eNB_id), T_INT(UE_id),
+          T_INT(proc->frame_rx), T_INT(subframe),
+          T_INT(0), T_BUFFER(ul_ch_estimates_time[0], 512  * 4));
+#endif
+
+#ifdef DEBUG_CH
+
+      if (aa==0) {
+        if (Ns == 0) {
+          write_output("rxdataF_ext.m","rxF_ext",&rxdataF_ext[aa][symbol_offset],512*2,2,1);
+          write_output("tmpin_ifft.m","drs_in",temp_in_ifft_0,512,1,1);
+          write_output("drs_est0.m","drs0",ul_ch_estimates_time[aa],512,1,1);
+        } else
+          write_output("drs_est1.m","drs1",ul_ch_estimates_time[aa],512,1,1);
+      }
+
+#endif
+
+
+//       if(cooperation_flag == 2) {
+//         memset(temp_in_ifft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t*)*2);
+//         memset(temp_in_ifft_1,0,frame_parms->ofdm_symbol_size*sizeof(int32_t*)*2);
+//         memset(temp_in_fft_0,0,frame_parms->ofdm_symbol_size*sizeof(int32_t*)*2);
+//         memset(temp_in_fft_1,0,frame_parms->ofdm_symbol_size*sizeof(int32_t*)*2);
+
+//         temp_in_ifft_ptr = &temp_in_ifft_0[0];
+
+//         i = symbol_offset;
+
+//         for(j=0; j<(frame_parms->N_RB_UL*12); j++) {
+//           temp_in_ifft_ptr[j] = ul_ch_estimates[aa][i];
+//           i++;
+//         }
+
+//         alpha_ind = 0;
+
+//         // Compensating for the phase shift introduced at the transmitter
+//         for(i=symbol_offset; i<symbol_offset+Msc_RS; i++) {
+//           ul_ch_estimates_re = ((int16_t*) ul_ch_estimates[aa])[i<<1];
+//           ul_ch_estimates_im = ((int16_t*) ul_ch_estimates[aa])[(i<<1)+1];
+//           //    ((int16_t*) ul_ch_estimates[aa])[i<<1] =  (i%2 == 1? 1:-1) * ul_ch_estimates_re;
+//           ((int16_t*) ul_ch_estimates[aa])[i<<1] =
+//             (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_re) +
+//                         (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_im))>>15);
+
+//           //((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] =  (i%2 == 1? 1:-1) * ul_ch_estimates_im;
+//           ((int16_t*) ul_ch_estimates[aa])[(i<<1)+1] =
+//             (int16_t) (((int32_t) (alpha_re[alpha_ind]) * (int32_t) (ul_ch_estimates_im) -
+//                         (int32_t) (alpha_im[alpha_ind]) * (int32_t) (ul_ch_estimates_re))>>15);
+
+//           alpha_ind+=10;
+
+//           if (alpha_ind>11)
+//             alpha_ind-=12;
+//         }
+
+//         //Extracting Channel Estimates for Distributed Alamouti Receiver Combining
+
+//         temp_in_ifft_ptr = &temp_in_ifft_1[0];
+
+//         i = symbol_offset;
+
+//         for(j=0; j<(frame_parms->N_RB_UL*12); j++) {
+//           temp_in_ifft_ptr[j] = ul_ch_estimates[aa][i];
+//           i++;
+//         }
+
+// 	switch (frame_parms->N_RB_DL) {
+// 	case 6:
+// 	  idft128((int16_t*) &temp_in_ifft_0[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_0,
+// 		  1);
+// 	  idft128((int16_t*) &temp_in_ifft_1[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_1,
+// 		  1);
+// 	  break;
+// 	case 25:
+// 	  idft512((int16_t*) &temp_in_ifft_0[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_0,
+// 		  1);
+// 	  idft512((int16_t*) &temp_in_ifft_1[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_1,
+// 		  1);
+// 	  break;
+// 	case 50:
+// 	  idft1024((int16_t*) &temp_in_ifft_0[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_0,
+// 		  1);
+// 	  idft1024((int16_t*) &temp_in_ifft_1[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_1,
+// 		  1);
+// 	  break;
+// 	case 100:
+// 	  idft2048((int16_t*) &temp_in_ifft_0[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_0,
+// 		  1);
+// 	  idft2048((int16_t*) &temp_in_ifft_1[0],                          // Performing IFFT on Combined Channel Estimates
+// 		  temp_out_ifft_1,
+// 		  1);
+// 	  break;
+// 	}
+
+//         // because the ifft is not power preserving, we should apply the factor sqrt(power_correction) here, but we rather apply power_correction here and nothing after the next fft
+//         in_fft_ptr_0 = &temp_in_fft_0[0];
+//         in_fft_ptr_1 = &temp_in_fft_1[0];
+
+//         for(j=0; j<(frame_parms->ofdm_symbol_size)/12; j++) {
+//           if (j>19) {
+//             ((int16_t*)in_fft_ptr_0)[-40+(2*j)] = ((int16_t*)temp_out_ifft_0)[-80+(2*j)]*rx_power_correction;
+//             ((int16_t*)in_fft_ptr_0)[-40+(2*j)+1] = ((int16_t*)temp_out_ifft_0)[-80+(2*j+1)]*rx_power_correction;
+//             ((int16_t*)in_fft_ptr_1)[-40+(2*j)] = ((int16_t*)temp_out_ifft_1)[-80+(2*j)]*rx_power_correction;
+//             ((int16_t*)in_fft_ptr_1)[-40+(2*j)+1] = ((int16_t*)temp_out_ifft_1)[-80+(2*j)+1]*rx_power_correction;
+//           } else {
+//             ((int16_t*)in_fft_ptr_0)[2*(frame_parms->ofdm_symbol_size-20+j)] = ((int16_t*)temp_out_ifft_0)[2*(frame_parms->ofdm_symbol_size-20+j)]*rx_power_correction;
+//             ((int16_t*)in_fft_ptr_0)[2*(frame_parms->ofdm_symbol_size-20+j)+1] = ((int16_t*)temp_out_ifft_0)[2*(frame_parms->ofdm_symbol_size-20+j)+1]*rx_power_correction;
+//             ((int16_t*)in_fft_ptr_1)[2*(frame_parms->ofdm_symbol_size-20+j)] = ((int16_t*)temp_out_ifft_1)[2*(frame_parms->ofdm_symbol_size-20+j)]*rx_power_correction;
+//             ((int16_t*)in_fft_ptr_1)[2*(frame_parms->ofdm_symbol_size-20+j)+1] = ((int16_t*)temp_out_ifft_1)[2*(frame_parms->ofdm_symbol_size-20+j)+1]*rx_power_correction;
+//           }
+//         }
+
+// 	switch (frame_parms->N_RB_DL) {
+//         case 6:
+// 	  dft128((int16_t*) &temp_in_fft_0[0],     
+// 		 // Performing FFT to obtain the Channel Estimates for UE0 to eNB1
+// 		 temp_out_fft_0,
+// 		 1);
+// 	  break;
+//         case 25:
+// 	  dft512((int16_t*) &temp_in_fft_0[0],     
+// 		 // Performing FFT to obtain the Channel Estimates for UE0 to eNB1
+// 		 temp_out_fft_0,
+// 		 1);
+// 	  break;
+//         case 50:
+// 	  dft1024((int16_t*) &temp_in_fft_0[0],     
+// 		 // Performing FFT to obtain the Channel Estimates for UE0 to eNB1
+// 		 temp_out_fft_0,
+// 		 1);
+// 	  break;
+//         case 100:
+// 	  dft2048((int16_t*) &temp_in_fft_0[0],     
+// 		 // Performing FFT to obtain the Channel Estimates for UE0 to eNB1
+// 		 temp_out_fft_0,
+// 		 1);
+// 	  break;
+// 	}
+
+//         out_fft_ptr_0 = &ul_ch_estimates_0[aa][symbol_offset]; // CHANNEL ESTIMATES FOR UE0 TO eNB1
+//         temp_out_fft_0_ptr = (int32_t*) temp_out_fft_0;
+
+//         i=0;
+
+//         for(j=0; j<frame_parms->N_RB_UL*12; j++) {
+//           out_fft_ptr_0[i] = temp_out_fft_0_ptr[j];
+//           i++;
+//         }
+// 	switch (frame_parms->N_RB_DL) {
+// 	case 6:
+// 	  dft128((int16_t*) &temp_in_fft_1[0],                          // Performing FFT to obtain the Channel Estimates for UE1 to eNB1
+// 		 temp_out_fft_1,
+// 		 1);
+// 	  break;
+// 	case 25:
+// 	  dft512((int16_t*) &temp_in_fft_1[0],                          // Performing FFT to obtain the Channel Estimates for UE1 to eNB1
+// 		 temp_out_fft_1,
+// 		 1);
+// 	  break;
+// 	case 50:
+// 	  dft1024((int16_t*) &temp_in_fft_1[0],                          // Performing FFT to obtain the Channel Estimates for UE1 to eNB1
+// 		 temp_out_fft_1,
+// 		 1);
+// 	  break;
+// 	case 100:
+// 	  dft2048((int16_t*) &temp_in_fft_1[0],                          // Performing FFT to obtain the Channel Estimates for UE1 to eNB1
+// 		 temp_out_fft_1,
+// 		 1);
+// 	  break;
+// 	}
+
+//         out_fft_ptr_1 = &ul_ch_estimates_1[aa][symbol_offset];   // CHANNEL ESTIMATES FOR UE1 TO eNB1
+//         temp_out_fft_1_ptr = (int32_t*) temp_out_fft_1;
+
+//         i=0;
+
+//         for(j=0; j<frame_parms->N_RB_UL*12; j++) {
+//           out_fft_ptr_1[i] = temp_out_fft_1_ptr[j];
+//           i++;
+//         }
+
+// #ifdef DEBUG_CH
+// #ifdef USER_MODE
+
+//         if((aa == 0)&& (cooperation_flag == 2)) {
+//           write_output("test1.m","t1",temp_in_ifft_0,512,1,1);
+//           write_output("test2.m","t2",temp_out_ifft_0,512*2,2,1);
+//           write_output("test3.m","t3",temp_in_fft_0,512,1,1);
+//           write_output("test4.m","t4",temp_out_fft_0,512,1,1);
+//           write_output("test5.m","t5",temp_in_fft_1,512,1,1);
+//           write_output("test6.m","t6",temp_out_fft_1,512,1,1);
+//         }
+
+// #endif
+// #endif
+
+//       }//cooperation_flag == 2
+
+      if (Ns&1) {//we are in the second slot of the sub-frame, so do the interpolation
+
+        ul_ch1 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos1];
+        ul_ch2 = &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*pilot_pos2];
+
+
+        // if(cooperation_flag == 2) { // For Distributed Alamouti
+        //   ul_ch1_0 = &ul_ch_estimates_0[aa][frame_parms->N_RB_UL*12*pilot_pos1];
+        //   ul_ch2_0 = &ul_ch_estimates_0[aa][frame_parms->N_RB_UL*12*pilot_pos2];
+
+        //   ul_ch1_1 = &ul_ch_estimates_1[aa][frame_parms->N_RB_UL*12*pilot_pos1];
+        //   ul_ch2_1 = &ul_ch_estimates_1[aa][frame_parms->N_RB_UL*12*pilot_pos2];
+        // }
+
+        // Estimation of phase difference between the 2 channel estimates
+        delta_phase = lte_ul_freq_offset_estimation_NB_IoT(frame_parms,
+                      ul_ch_estimates[aa],
+                      N_rb_alloc);
+        // negative phase index indicates negative Im of ru
+        //    msg("delta_phase: %d\n",delta_phase);
+
+#ifdef DEBUG_CH
+        msg("lte_ul_channel_estimation: ul_ch1 = %p, ul_ch2 = %p, pilot_pos1=%d, pilot_pos2=%d\n",ul_ch1, ul_ch2, pilot_pos1,pilot_pos2);
+#endif
+
+        for (k=0; k<frame_parms->symbols_per_tti; k++) {
+
+          // we scale alpha and beta by SCALE (instead of 0x7FFF) to avoid overflows
+          alpha = (int16_t) (((int32_t) SCALE * (int32_t) (pilot_pos2-k))/(pilot_pos2-pilot_pos1));
+          beta  = (int16_t) (((int32_t) SCALE * (int32_t) (k-pilot_pos1))/(pilot_pos2-pilot_pos1));
+
+
+#ifdef DEBUG_CH
+          msg("lte_ul_channel_estimation: k=%d, alpha = %d, beta = %d\n",k,alpha,beta);
+#endif
+          //symbol_offset_subframe = frame_parms->N_RB_UL*12*k;
+
+          // interpolate between estimates
+          if ((k != pilot_pos1) && (k != pilot_pos2))  {
+            //          multadd_complex_vector_real_scalar((int16_t*) ul_ch1,alpha,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+            //          multadd_complex_vector_real_scalar((int16_t*) ul_ch2,beta ,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+
+            //          multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+            //          multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+            //          msg("phase = %d\n",ru[2*cmax(((delta_phase/7)*(k-3)),0)]);
+
+            // the phase is linearly interpolated
+            current_phase1 = (delta_phase/7)*(k-pilot_pos1);
+            current_phase2 = (delta_phase/7)*(k-pilot_pos2);
+            //          msg("sym: %d, current_phase1: %d, current_phase2: %d\n",k,current_phase1,current_phase2);
+            // set the right quadrant
+            (current_phase1 > 0) ? (ru1 = ru_90) : (ru1 = ru_90c);
+            (current_phase2 > 0) ? (ru2 = ru_90) : (ru2 = ru_90c);
+            // take absolute value and clip
+            current_phase1 = cmin(abs(current_phase1),127);
+            current_phase2 = cmin(abs(current_phase2),127);
+
+            //          msg("sym: %d, current_phase1: %d, ru: %d + j%d, current_phase2: %d, ru: %d + j%d\n",k,current_phase1,ru1[2*current_phase1],ru1[2*current_phase1+1],current_phase2,ru2[2*current_phase2],ru2[2*current_phase2+1]);
+
+            // rotate channel estimates by estimated phase
+            rotate_cpx_vector((int16_t*) ul_ch1,
+                              &ru1[2*current_phase1],
+                              (int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],
+                              Msc_RS,
+                              15);
+
+            rotate_cpx_vector((int16_t*) ul_ch2,
+                              &ru2[2*current_phase2],
+                              (int16_t*) &tmp_estimates[0],
+                              Msc_RS,
+                              15);
+
+            // Combine the two rotated estimates
+            multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+            multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+
+            /*
+            if ((k<pilot_pos1) || ((k>pilot_pos2))) {
+
+                multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+
+                multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+
+            } else {
+
+                multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+
+                multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],SCALE>>1,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+
+                //              multadd_complex_vector_real_scalar((int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],alpha,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+
+                //              multadd_complex_vector_real_scalar((int16_t*) &tmp_estimates[0],beta ,(int16_t*) &ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+
+            }
+            */
+
+            //      memcpy(&ul_ch_estimates[aa][frame_parms->N_RB_UL*12*k],ul_ch1,Msc_RS*sizeof(int32_t));
+            // if(cooperation_flag == 2) { // For Distributed Alamouti
+            //   multadd_complex_vector_real_scalar((int16_t*) ul_ch1_0,beta ,(int16_t*) &ul_ch_estimates_0[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+            //   multadd_complex_vector_real_scalar((int16_t*) ul_ch2_0,alpha,(int16_t*) &ul_ch_estimates_0[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+
+            //   multadd_complex_vector_real_scalar((int16_t*) ul_ch1_1,beta ,(int16_t*) &ul_ch_estimates_1[aa][frame_parms->N_RB_UL*12*k],1,Msc_RS);
+            //   multadd_complex_vector_real_scalar((int16_t*) ul_ch2_1,alpha,(int16_t*) &ul_ch_estimates_1[aa][frame_parms->N_RB_UL*12*k],0,Msc_RS);
+            // }
+
+          }
+        } //for(k=...
+
+        // because of the scaling of alpha and beta we also need to scale the final channel estimate at the pilot positions
+
+        //    multadd_complex_vector_real_scalar((int16_t*) ul_ch1,SCALE,(int16_t*) ul_ch1,1,Msc_RS);
+        //    multadd_complex_vector_real_scalar((int16_t*) ul_ch2,SCALE,(int16_t*) ul_ch2,1,Msc_RS);
+
+        // if(cooperation_flag == 2) { // For Distributed Alamouti
+        //   multadd_complex_vector_real_scalar((int16_t*) ul_ch1_0,SCALE,(int16_t*) ul_ch1_0,1,Msc_RS);
+        //   multadd_complex_vector_real_scalar((int16_t*) ul_ch2_0,SCALE,(int16_t*) ul_ch2_0,1,Msc_RS);
+
+        //   multadd_complex_vector_real_scalar((int16_t*) ul_ch1_1,SCALE,(int16_t*) ul_ch1_1,1,Msc_RS);
+        //   multadd_complex_vector_real_scalar((int16_t*) ul_ch2_1,SCALE,(int16_t*) ul_ch2_1,1,Msc_RS);
+        // }
+
+
+      } //if (Ns&1)
+
+    } //for(aa=...
+
+  } //if(l==...
+
+
+
+  return(0);
+}
+
+
+int16_t lte_ul_freq_offset_estimation_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
+                                             int32_t *ul_ch_estimates,
+                                             uint16_t nb_rb)
+{
+
+#if defined(__x86_64__) || defined(__i386__)
+  int k, rb;
+  int a_idx = 64;
+  uint8_t conj_flag = 0;
+  uint8_t output_shift;
+  int pilot_pos1 = 3 - frame_parms->Ncp;
+  int pilot_pos2 = 10 - 2*frame_parms->Ncp;
+  __m128i *ul_ch1 = (__m128i*)&ul_ch_estimates[pilot_pos1*frame_parms->N_RB_UL*12];
+  __m128i *ul_ch2 = (__m128i*)&ul_ch_estimates[pilot_pos2*frame_parms->N_RB_UL*12];
+  int32_t avg[2];
+  int16_t Ravg[2];
+  Ravg[0]=0;
+  Ravg[1]=0;
+  int16_t iv, rv, phase_idx;
+  __m128i avg128U1, avg128U2, R[3], mmtmpD0,mmtmpD1,mmtmpD2,mmtmpD3;
+
+  // round(tan((pi/4)*[1:1:N]/N)*pow2(15))
+  int16_t alpha[128] = {201, 402, 603, 804, 1006, 1207, 1408, 1610, 1811, 2013, 2215, 2417, 2619, 2822, 3024, 3227, 3431, 3634, 3838, 4042, 4246, 4450, 4655, 4861, 5066, 5272, 5479, 5686, 5893, 6101, 6309, 6518, 6727, 6937, 7147, 7358, 7570, 7782, 7995, 8208, 8422, 8637, 8852, 9068, 9285, 9503, 9721, 9940, 10160, 10381, 10603, 10825, 11049, 11273, 11498, 11725, 11952, 12180, 12410, 12640, 12872, 13104, 13338, 13573, 13809, 14046, 14285, 14525, 14766, 15009, 15253, 15498, 15745, 15993, 16243, 16494, 16747, 17001, 17257, 17515, 17774, 18035, 18298, 18563, 18829, 19098, 19368, 19640, 19915, 20191, 20470, 20750, 21033, 21318, 21605, 21895, 22187, 22481, 22778, 23078, 23380, 23685, 23992, 24302, 24615, 24931, 25250, 25572, 25897, 26226, 26557, 26892, 27230, 27572, 27917, 28266, 28618, 28975, 29335, 29699, 30067, 30440, 30817, 31198, 31583, 31973, 32368, 32767};
+
+  // compute log2_maxh (output_shift)
+  avg128U1 = _mm_setzero_si128();
+  avg128U2 = _mm_setzero_si128();
+
+  for (rb=0; rb<nb_rb; rb++) {
+    avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[0],ul_ch1[0]));
+    avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[1],ul_ch1[1]));
+    avg128U1 = _mm_add_epi32(avg128U1,_mm_madd_epi16(ul_ch1[2],ul_ch1[2]));
+
+    avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[0],ul_ch2[0]));
+    avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[1],ul_ch2[1]));
+    avg128U2 = _mm_add_epi32(avg128U2,_mm_madd_epi16(ul_ch2[2],ul_ch2[2]));
+
+    ul_ch1+=3;
+    ul_ch2+=3;
+  }
+
+  avg[0] = (((int*)&avg128U1)[0] +
+            ((int*)&avg128U1)[1] +
+            ((int*)&avg128U1)[2] +
+            ((int*)&avg128U1)[3])/(nb_rb*12);
+
+  avg[1] = (((int*)&avg128U2)[0] +
+            ((int*)&avg128U2)[1] +
+            ((int*)&avg128U2)[2] +
+            ((int*)&avg128U2)[3])/(nb_rb*12);
+
+  //    msg("avg0 = %d, avg1 = %d\n",avg[0],avg[1]);
+  avg[0] = cmax(avg[0],avg[1]);
+  avg[1] = log2_approx(avg[0]);
+  output_shift = cmax(0,avg[1]-10);
+  //output_shift  = (log2_approx(avg[0])/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+1;
+  //    msg("avg= %d, shift = %d\n",avg[0],output_shift);
+
+  ul_ch1 = (__m128i*)&ul_ch_estimates[pilot_pos1*frame_parms->N_RB_UL*12];
+  ul_ch2 = (__m128i*)&ul_ch_estimates[pilot_pos2*frame_parms->N_RB_UL*12];
+
+  // correlate and average the 2 channel estimates ul_ch1*ul_ch2
+  for (rb=0; rb<nb_rb; rb++) {
+    mmtmpD0 = _mm_madd_epi16(ul_ch1[0],ul_ch2[0]);
+    mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[0],_MM_SHUFFLE(2,3,0,1));
+    mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
+    mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate);
+    mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[0]);
+    mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
+    mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
+    mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
+    mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
+    R[0] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
+
+    mmtmpD0 = _mm_madd_epi16(ul_ch1[1],ul_ch2[1]);
+    mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[1],_MM_SHUFFLE(2,3,0,1));
+    mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
+    mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate);
+    mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[1]);
+    mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
+    mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
+    mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
+    mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
+    R[1] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
+
+    mmtmpD0 = _mm_madd_epi16(ul_ch1[2],ul_ch2[2]);
+    mmtmpD1 = _mm_shufflelo_epi16(ul_ch1[2],_MM_SHUFFLE(2,3,0,1));
+    mmtmpD1 = _mm_shufflehi_epi16(mmtmpD1,_MM_SHUFFLE(2,3,0,1));
+    mmtmpD1 = _mm_sign_epi16(mmtmpD1,*(__m128i*)&conjugate);
+    mmtmpD1 = _mm_madd_epi16(mmtmpD1,ul_ch2[2]);
+    mmtmpD0 = _mm_srai_epi32(mmtmpD0,output_shift);
+    mmtmpD1 = _mm_srai_epi32(mmtmpD1,output_shift);
+    mmtmpD2 = _mm_unpacklo_epi32(mmtmpD0,mmtmpD1);
+    mmtmpD3 = _mm_unpackhi_epi32(mmtmpD0,mmtmpD1);
+    R[2] = _mm_packs_epi32(mmtmpD2,mmtmpD3);
+
+    R[0] = _mm_add_epi16(_mm_srai_epi16(R[0],1),_mm_srai_epi16(R[1],1));
+    R[0] = _mm_add_epi16(_mm_srai_epi16(R[0],1),_mm_srai_epi16(R[2],1));
+
+    Ravg[0] += (((short*)&R)[0] +
+                ((short*)&R)[2] +
+                ((short*)&R)[4] +
+                ((short*)&R)[6])/(nb_rb*4);
+
+    Ravg[1] += (((short*)&R)[1] +
+                ((short*)&R)[3] +
+                ((short*)&R)[5] +
+                ((short*)&R)[7])/(nb_rb*4);
+
+    ul_ch1+=3;
+    ul_ch2+=3;
+  }
+
+  // phase estimation on Ravg
+  //   Ravg[0] = 56;
+  //   Ravg[1] = 0;
+  rv = Ravg[0];
+  iv = Ravg[1];
+
+  if (iv<0)
+    iv = -Ravg[1];
+
+  if (rv<iv) {
+    rv = iv;
+    iv = Ravg[0];
+    conj_flag = 1;
+  }
+
+  //   msg("rv = %d, iv = %d\n",rv,iv);
+  //   msg("max_avg = %d, log2_approx = %d, shift = %d\n",avg[0], avg[1], output_shift);
+
+  for (k=0; k<6; k++) {
+    (iv<(((int32_t)(alpha[a_idx]*rv))>>15)) ? (a_idx -= 32>>k) : (a_idx += 32>>k);
+  }
+
+  (conj_flag==1) ? (phase_idx = 127-(a_idx>>1)) : (phase_idx = (a_idx>>1));
+
+  if (Ravg[1]<0)
+    phase_idx = -phase_idx;
+
+  return(phase_idx);
+#elif defined(__arm__)
+  return(0);
+#endif
+}
diff --git a/openair1/PHY/LTE_REFSIG/defs_NB_IoT.h b/openair1/PHY/LTE_REFSIG/defs_NB_IoT.h
index 4bfb9a36a3a8983c40c7e1afd65e62d608bdbbe8..9c6e20b9208de3c9e79cede4df1b1058d9f1573e 100644
--- a/openair1/PHY/LTE_REFSIG/defs_NB_IoT.h
+++ b/openair1/PHY/LTE_REFSIG/defs_NB_IoT.h
@@ -16,7 +16,7 @@
 
 #ifndef __LTE_REFSIG_DEFS_NB_IOT__H__
 #define __LTE_REFSIG_DEFS_NB_IOT__H__
-#include "PHY/defs.h"
+
 #include "PHY/defs_NB_IoT.h"
 
 /** @ingroup _PHY_REF_SIG
@@ -27,7 +27,9 @@
 @param lte_gold_table pointer to table where sequences are stored
 @param Nid_cell Cell Id for NB_IoT (to compute sequences for local and adjacent cells) */
 
-void lte_gold_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table[20][2][14],uint16_t Nid_cell);
+void lte_gold_NB_IoT(NB_IoT_DL_FRAME_PARMS  *frame_parms,
+					 uint32_t 				lte_gold_table_NB_IoT[20][2][14],
+					 uint16_t 				Nid_cell);
 
 /*! \brief This function generates the Narrowband reference signal (NRS) sequence (36-211, Sec 6.10.1.1)
 @param phy_vars_eNB Pointer to eNB variables
@@ -38,12 +40,21 @@ void lte_gold_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table[20]
 @param p antenna index
 @param RB_IoT_ID the ID of the RB dedicated for NB_IoT
 */
-int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
-                     int32_t *output,
-                     short amp,
-                     unsigned char Ns,
-                     unsigned char l,
-                     unsigned char p
-					 unsigned short RB_IoT_ID); 
-					 
+int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB_NB_IoT  *phy_vars_eNB,
+                     		int32_t 			 *output,
+                     		short 				 amp,
+                     		unsigned char 		 Ns,
+                     		unsigned char 		 l,
+                     		unsigned char 		 p,
+					 		unsigned short 		 RB_IoT_ID); 
+
+
+unsigned int lte_gold_generic_NB_IoT(unsigned int  *x1,
+									 unsigned int  *x2,
+									 unsigned char reset);
+		
+void generate_ul_ref_sigs_rx_NB_IoT(void);
+
+void free_ul_ref_sigs_NB_IoT(void);
+			 
 #endif
diff --git a/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec_NB_IoT.c b/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec_NB_IoT.c
index f8a6b29c5a0a76355e825fb025ebc1cb89b71725..cf8818f0b6bd2666b1c211b7c53f9473f9a1c8c1 100644
--- a/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec_NB_IoT.c
+++ b/openair1/PHY/LTE_REFSIG/lte_dl_cell_spec_NB_IoT.c
@@ -12,31 +12,29 @@
 * \warning
 */
 
+/* check if this is required for NB-IoT
 #ifdef USER_MODE
 #include <stdio.h>
 #include <stdlib.h>
 #endif
-
-#include "defs.h"
-#include "PHY/defs.h"
-
-#include "defs_NB_IoT.h"
+*/
+#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
 #include "PHY/defs_NB_IoT.h"
 
-int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
-                     int32_t *output,
-                     short amp,
-                     unsigned char Ns,
-                     unsigned char l,
-                     unsigned char p,
-					 unsigned short RB_IoT_ID) 			// the ID of the RB dedicated for NB_IoT
+int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB_NB_IoT   *phy_vars_eNB,
+                            int32_t               *output,
+                            short                 amp,
+                            unsigned char         Ns,
+                            unsigned char         l,
+                            unsigned char         p,
+					                  unsigned short        RB_IoT_ID) 			// the ID of the RB dedicated for NB_IoT
 {
-  unsigned char nu,mprime,mprime_dword,mprime_qpsk_symb,m;
-  unsigned short k,a;
-  unsigned short NB_IoT_start,bandwidth_even_odd;
-  int32_t qpsk[4];
+  unsigned char   nu,m;
+  unsigned short  k,a;
+  unsigned short  NB_IoT_start,bandwidth_even_odd;
+  int32_t         qpsk[4];
 
-  a = (amp*ONE_OVER_SQRT2_Q15)>>15;
+  a = (amp*ONE_OVER_SQRT2_Q15_NB_IoT)>>15;
   ((short *)&qpsk[0])[0] = a;
   ((short *)&qpsk[0])[1] = a;
   ((short *)&qpsk[1])[0] = -a;
@@ -55,21 +53,22 @@ int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
   else if ((p==1) && (l>0))
     nu = 0;
   else {
-    printf("lte_dl_cell_spec: p %d, l %d -> ERROR\n",p,l);
+    printf("lte_dl_cell_spec_NB_IoT: p %d, l %d -> ERROR\n",p,l);
     return(-1);
   }
 
   // testing if the total number of RBs is even or odd 
-  bandwidth_even_odd = frame_parms->N_RB_DL % 2;    // 0 even, 1 odd
+  bandwidth_even_odd = phy_vars_eNB->frame_parms.N_RB_DL % 2;    // 0 even, 1 odd
   
-  mprime = 0; 										// mprime = 0,1 for NB_IoT //  for LTE , maximum number of resources blocks (110) - the total number of RB in the selected bandwidth (.... 15 , 25 , 50, 100)
-  k = (nu + phy_vars_eNB->lte_frame_parms.nushift)%6;
+  //mprime = 0; 										// mprime = 0,1 for NB_IoT //  for LTE , maximum number of resources blocks (110) - the total number of RB in the selected bandwidth (.... 15 , 25 , 50, 100)
+  k = (nu + phy_vars_eNB->frame_parms.nushift)%6;
 
-  if(RB_IoT_ID < (phy_vars_eNB->lte_frame_parms.N_RB_DL/2))
-  {
-		NB_IoT_start = phy_vars_eNB->lte_frame_parms.ofdm_symbol_size - 12*(phy_vars_eNB->lte_frame_parms.N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(phy_vars_eNB->lte_frame_parms.N_RB_DL/(float)2)));
+  if(RB_IoT_ID < (phy_vars_eNB->frame_parms.N_RB_DL/2))
+  {																																//XXX this mod operation is not valid since the second member is not an integer but double (for the moment i put a cast)
+		NB_IoT_start = phy_vars_eNB->frame_parms.ofdm_symbol_size - 12*(phy_vars_eNB->frame_parms.N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%((int)(ceil(phy_vars_eNB->frame_parms.N_RB_DL/(float)2))));
   } else {
-		NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(phy_vars_eNB->lte_frame_parms.N_RB_DL/(float)2)));
+	  	  	  	  	  	  	  	  	  	  	  	  	 //XXX invalid mod operation (put a cast for the moment)
+		NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%((int)(ceil(phy_vars_eNB->frame_parms.N_RB_DL/(float)2))));
   }
    
   k+=NB_IoT_start;
@@ -78,7 +77,7 @@ int lte_dl_cell_spec_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
   DevAssert( l < 2 );
 
   for (m=0; m<2; m++) {
-    output[k] = qpsk[(phy_vars_eNB->lte_gold_table_NB_IoT[Ns][l][0]) & 3];
+    output[k] = qpsk[(phy_vars_eNB->lte_gold_table_NB_IoT[Ns][l][0]) & 3]; //TODO should be defined one for NB-IoT
     k+=6;
   }
 
diff --git a/openair1/PHY/LTE_REFSIG/lte_gold_NB_IoT.c b/openair1/PHY/LTE_REFSIG/lte_gold_NB_IoT.c
index e66a4884f8da1740f24ebbbe755d198d303d6166..23edfc80983585a97d2194340e6040b04a238ca1 100644
--- a/openair1/PHY/LTE_REFSIG/lte_gold_NB_IoT.c
+++ b/openair1/PHY/LTE_REFSIG/lte_gold_NB_IoT.c
@@ -12,21 +12,19 @@
 * \warning
 */
 
-#include "defs.h"
-#include "defs_NB_IoT.h"
+//#include "defs.h"
+#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
 
-void lte_gold_NB_IoT(LTE_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table_NB_IoT[20][2][14],uint16_t Nid_cell)  //  Nid_cell = Nid_cell_NB_IoT
+void lte_gold_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,uint32_t lte_gold_table_NB_IoT[20][2][14],uint16_t Nid_cell)  //  Nid_cell = Nid_cell_NB_IoT
 {
   unsigned char ns,l,Ncp=1;
-  unsigned int n,x1,x2;
+  unsigned int  n,x1,x2;
 
   for (ns=0; ns<20; ns++) {
 
     for (l=0; l<2; l++) {
 
-      x2 = Ncp +
-           (Nid_cell<<1) +
-		   (((1+(Nid_cell<<1))*(1 + (l+5) + (7*(1+ns))))<<10); //cinit
+      x2 = Ncp + (Nid_cell<<1) + (((1+(Nid_cell<<1))*(1 + (l+5) + (7*(1+ns))))<<10); //cinit
      
       x1 = 1+ (1<<31);
       x2 = x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
diff --git a/openair1/PHY/LTE_REFSIG/lte_ul_ref_NB_IoT.c b/openair1/PHY/LTE_REFSIG/lte_ul_ref_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..1cbea408892278cbcfb1c5228627581b6d33fc3a
--- /dev/null
+++ b/openair1/PHY/LTE_REFSIG/lte_ul_ref_NB_IoT.c
@@ -0,0 +1,258 @@
+/*
+ * 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.0  (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/LTE_REFSIG/lte_ul_ref_NB_IoT.c
+* \function called by lte_dl_cell_spec_NB_IoT.c ,  TS 36-211, V13.4.0 2017-02
+* \author: Vincent Savaux
+* \date 2017
+* \version 0.0
+* \company b<>com
+* \email: vincent.savaux@b-com.com
+* \note
+* \warning
+*/
+
+#ifdef MAIN
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#endif
+// #include "defs.h"
+#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
+#include "PHY/defs_NB_IoT.h"
+
+uint16_t dftsizes[33] = {12,24,36,48,60,72,96,108,120,144,180,192,216,240,288,300,324,360,384,432,480,540,576,600,648,720,864,900,960,972,1080,1152,1200};
+
+uint16_t ref_primes[33] = {11,23,31,47,59,71,89,107,113,139,179,191,211,239,283,293,317,359,383,431,479,523,571,599,647,719,863,887,953,971,1069,1151,1193};
+
+uint16_t sequence_length[4] = {2048,3,6,12}; //the "32" value corresponds to the max gold sequence length 
+
+// int16_t *ul_ref_sigs[30][33];
+int16_t *ul_ref_sigs_rx[30][4]; //these contain the sequences in repeated format and quantized to QPSK ifdef IFFT_FPGA
+uint16_t u_max[4] = {16,12,14,30}; // maximum u value, see 36.211, Section 10.1.4
+
+/* 36.211 table 5.5.1.2-1 */
+char ref12[360] = {-1,1,3,-3,3,3,1,1,3,1,-3,3,1,1,3,3,3,-1,1,-3,-3,1,-3,3,1,1,-3,-3,-3,-1,-3,-3,1,-3,1,-1,-1,1,1,1,1,-1,-3,-3,1,-3,3,-1,-1,3,1,-1,1,-1,-3,-1,1,-1,1,3,1,-3,3,-1,-1,1,1,-1,-1,3,-3,1,-1,3,-3,-3,-3,3,1,-1,3,3,-3,1,-3,-1,-1,-1,1,-3,3,-1,1,-3,3,1,1,-3,3,1,-1,-1,-1,1,1,3,-1,1,1,-3,-1,3,3,-1,-3,1,1,1,1,1,-1,3,-1,1,1,-3,-3,-1,-3,-3,3,-1,3,1,-1,-1,3,3,-3,1,3,1,3,3,1,-3,1,1,-3,1,1,1,-3,-3,-3,1,3,3,-3,3,-3,1,1,3,-1,-3,3,3,-3,1,-1,-3,-1,3,1,3,3,3,-1,1,3,-1,1,-3,-1,-1,1,1,3,1,-1,-3,1,3,1,-1,1,3,3,3,-1,-1,3,-1,-3,1,1,3,-3,3,-3,-3,3,1,3,-1,-3,3,1,1,-3,1,-3,-3,-1,-1,1,-3,-1,3,1,3,1,-1,-1,3,-3,-1,-3,-1,-1,-3,1,1,1,1,3,1,-1,1,-3,-1,-1,3,-1,1,-3,-3,-3,-3,-3,1,-1,-3,1,1,-3,-3,-3,-3,-1,3,-3,1,-3,3,1,1,-1,-3,-1,-3,1,-1,1,3,-1,1,1,1,3,1,3,3,-1,1,-1,-3,-3,1,1,-3,3,3,1,3,3,1,-3,-1,-1,3,1,3,-3,-3,3,-3,1,-1,-1,3,-1,-3,-3,-1,-3,-1,-3,3,1,-1,1,3,-3,-3,-1,3,-3,3,-1,3,3,-3,3,3,-1,-1,3,-3,-3,-1,-1,-3,-1,3,-3,3,1,-1};
+
+/* 36.211 table 5.5.1.2-2 */
+// char ref24[720] = {
+//   -1,3,1,-3,3,-1,1,3,-3,3,1,3,-3,3,1,1,-1,1,3,-3,3,-3,-1,-3,-3,3,-3,-3,-3,1,-3,-3,3,-1,1,1,1,3,1,-1,3,-3,-3,1,3,1,1,-3,3,-1,3,3,1,1,-3,3,3,3,3,1,-1,3,-1,1,1,-1,-3,-1,-1,1,3,3,-1,-3,1,1,3,-3,1,1,-3,-1,-1,1,3,1,3,1,-1,3,1,1,-3,-1,-3,-1,-1,-1,-1,-3,-3,-1,1,1,3,3,-1,3,-1,1,-1,-3,1,-1,-3,-3,1,-3,-1,-1,-3,1,1,3,-1,1,3,1,-3,1,-3,1,1,-1,-1,3,-1,-3,3,-3,-3,-3,1,1,1,1,-1,-1,3,-3,-3,3,-3,1,-1,-1,1,-1,1,1,-1,-3,-1,1,-1,3,-1,-3,-3,3,3,-1,-1,-3,-1,3,1,3,1,3,1,1,-1,3,1,-1,1,3,-3,-1,-1,1,-3,1,3,-3,1,-1,-3,3,-3,3,-1,-1,-1,-1,1,-3,-3,-3,1,-3,-3,-3,1,-3,1,1,-3,3,3,-1,-3,-1,3,-3,3,3,3,-1,1,1,-3,1,-1,1,1,-3,1,1,-1,1,-3,-3,3,-1,3,-1,-1,-3,-3,-3,-1,-3,-3,1,-1,1,3,3,-1,1,-1,3,1,3,3,-3,-3,1,3,1,-1,-3,-3,-3,3,3,-3,3,3,-1,-3,3,-1,1,-3,1,1,3,3,1,1,1,-1,-1,1,-3,3,-1,1,1,-3,3,3,-1,-3,3,-3,-1,-3,-1,3,-1,-1,-1,-1,-3,-1,3,3,1,-1,1,3,3,3,-1,1,1,-3,1,3,-1,-3,3,-3,-3,3,1,3,1,-3,3,1,3,1,1,3,3,-1,-1,-3,1,-3,-1,3,1,1,3,-1,-1,1,-3,1,3,-3,1,-1,-3,-1,3,1,3,1,-1,-3,-3,-1,-1,-3,-3,-3,-1,-1,-3,3,-1,-1,-1,-1,1,1,-3,3,1,3,3,1,-1,1,-3,1,-3,1,1,-3,-1,1,3,-1,3,3,-1,-3,1,-1,-3,3,3,3,-1,1,1,3,-1,-3,-1,3,-1,-1,-1,1,1,1,1,1,-1,3,-1,-3,1,1,3,-3,1,-3,-1,1,1,-3,-3,3,1,1,-3,1,3,3,1,-1,-3,3,-1,3,3,3,-3,1,-1,1,-1,-3,-1,1,3,-1,3,-3,-3,-1,-3,3,-3,-3,-3,-1,-1,-3,-1,-3,3,1,3,-3,-1,3,-1,1,-1,3,-3,1,-1,-3,-3,1,1,-1,1,-1,1,-1,3,1,-3,-1,1,-1,1,-1,-1,3,3,-3,-1,1,-3,-3,-1,-3,3,1,-1,-3,-1,-3,-3,3,-3,3,-3,-1,1,3,1,-3,1,3,3,-1,-3,-1,-1,-1,-1,3,3,3,1,3,3,-3,1,3,-1,3,-1,3,3,-3,3,1,-1,3,3,1,-1,3,3,-1,-3,3,-3,-1,-1,3,-1,3,-1,-1,1,1,1,1,-1,-1,-3,-1,3,1,-1,1,-1,3,-1,3,1,1,-1,-1,-3,1,1,-3,1,3,-3,1,1,-3,-3,-1,-1,-3,-1,1,3,1,1,-3,-1,-1,-3,3,-3,3,1,-3,3,-3,1,-1,1,-3,1,1,1,-1,-3,3,3,1,1,3,-1,-3,-1,-1,-1,3,1,-3,-3,-1,3,-3,-1,-3,-1,-3,-1,-1,-3,-1,-1,1,-3,-1,-1,1,-1,-3,1,1,-3,1,-3,-3,3,1,1,-1,3,-1,-1,1,1,-1,-1,-3,-1,3,-1,3,-1,1,3,1,-1,3,1,3,-3,-3,1,-1,-1,1,3
+// }; 
+
+// 36.211, Section 10.1.4.1.2, Table 10.1.4.1.2-1 
+char ref3[36] = {1,  -3,  -3, 1, -3,  -1, 1, -3,  3, 1, -1,  -1, 1, -1,  1, 1, -1,  3, 1, 1, -3, 1, 1, -1, 1, 1, 3, 1, 3, -1, 1, 3, 1, 1, 3, 3 }; 
+
+// 36.211, Section 10.1.4.1.2, Table 10.1.4.1.2-2 
+char ref6[84] = {1,  1, 1, 1, 3, -3, 1, 1, 3, 1, -3,  3, 1, -1,  -1,  -1,  1, -3, 1, -1,  3, -3,  -1,  -1, 1, 3, 1, -1,  -1,  3, 1, -3,  -3,  1, 3, 1, -1,  -1,  1, -3,  -3,  -1, 
+                -1,  -1,  -1,  3, -3,  -1, 3, -1,  1, -3,  -3,  3, 3, -1,  3, -3,  -1,  1, 3, -3,  3, -1,  3, 3, -3,  1, 3, 1, -3,  -1, -3,  1, -3,  3, -3,  -1, -3,  3, -3,  1, 1, -3};
+
+// NB-IoT: 36.211, Section 10.1.4.1.1, Table 10.1.4.1.1-1
+int16_t w_n[256] = {
+  1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,
+  1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1, 1,-1,
+  1, 1,-1,-1, 1, 1,-1,-1, 1, 1,-1,-1, 1, 1,-1,-1,
+  1,-1,-1, 1, 1,-1,-1, 1, 1,-1,-1, 1, 1,-1,-1, 1,
+  1, 1, 1, 1,-1,-1,-1,-1, 1, 1, 1, 1,-1,-1,-1,-1,
+  1,-1, 1,-1,-1, 1,-1, 1, 1,-1, 1,-1,-1, 1,-1, 1,
+  1, 1,-1,-1,-1,-1, 1, 1, 1, 1,-1,-1,-1,-1, 1, 1,
+  1,-1,-1, 1,-1, 1, 1,-1, 1,-1,-1, 1,-1, 1, 1,-1,
+  1, 1, 1, 1, 1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1,
+  1,-1, 1,-1, 1,-1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1,
+  1, 1,-1,-1, 1, 1,-1,-1,-1,-1, 1, 1,-1,-1, 1, 1,
+  1,-1,-1, 1, 1,-1,-1, 1,-1, 1, 1,-1,-1, 1, 1,-1,
+  1, 1, 1, 1,-1,-1,-1,-1,-1,-1,-1,-1, 1, 1, 1, 1,
+  1,-1, 1,-1,-1, 1,-1, 1,-1, 1,-1, 1, 1,-1, 1,-1,
+  1, 1,-1,-1,-1,-1, 1, 1,-1,-1, 1, 1, 1, 1,-1,-1,
+  1,-1,-1, 1,-1, 1, 1,-1,-1, 1, 1,-1, 1,-1,-1, 1
+}; 
+
+// void generate_ul_ref_sigs(void)
+// {
+//   double qbar,phase;
+//   unsigned int u,v,Msc_RS,q,m,n;
+
+//   // These are the Zadoff-Chu sequences (for RB 3-100)
+//   for (Msc_RS=2; Msc_RS<33; Msc_RS++) {
+//     for (u=0; u<30; u++) {
+//       for (v=0; v<2; v++) {
+//         qbar = ref_primes[Msc_RS] * (u+1)/(double)31;
+//         ul_ref_sigs[u][v][Msc_RS] = (int16_t*)malloc16(2*sizeof(int16_t)*dftsizes[Msc_RS]);
+
+//         if ((((int)floor(2*qbar))&1) == 0)
+//           q = (int)(floor(qbar+.5)) - v;
+//         else
+//           q = (int)(floor(qbar+.5)) + v;
+
+// #ifdef MAIN
+//         printf("Msc_RS %d (%d), u %d, v %d -> q %d (qbar %f)\n",Msc_RS,dftsizes[Msc_RS],u,v,q,qbar);
+// #endif
+
+//         for (n=0; n<dftsizes[Msc_RS]; n++) {
+//           m=n%ref_primes[Msc_RS];
+//           phase = (double)q*m*(m+1)/ref_primes[Msc_RS];
+//           ul_ref_sigs[u][v][Msc_RS][n<<1]     =(int16_t)(floor(32767*cos(M_PI*phase)));
+//           ul_ref_sigs[u][v][Msc_RS][1+(n<<1)] =-(int16_t)(floor(32767*sin(M_PI*phase)));
+// #ifdef MAIN
+
+//           if (Msc_RS<5)
+//             printf("(%d,%d) ",ul_ref_sigs[u][v][Msc_RS][n<<1],ul_ref_sigs[u][v][Msc_RS][1+(n<<1)]);
+
+// #endif
+//         }
+
+// #ifdef MAIN
+
+//         if (Msc_RS<5)
+//           printf("\n");
+
+// #endif
+//       }
+//     }
+//   }
+
+//   // These are the sequences for RB 1
+//   for (u=0; u<30; u++) {
+//     ul_ref_sigs[u][0][0] = (int16_t*)malloc16(2*sizeof(int16_t)*dftsizes[0]);
+
+//     for (n=0; n<dftsizes[0]; n++) {
+//       ul_ref_sigs[u][0][0][n<<1]    =(int16_t)(floor(32767*cos(M_PI*ref12[(u*12) + n]/4)));
+//       ul_ref_sigs[u][0][0][1+(n<<1)]=(int16_t)(floor(32767*sin(M_PI*ref12[(u*12) + n]/4)));
+//     }
+
+//   }
+
+//   // These are the sequences for RB 2
+//   for (u=0; u<30; u++) {
+//     ul_ref_sigs[u][0][1] = (int16_t*)malloc16(2*sizeof(int16_t)*dftsizes[1]);
+
+//     for (n=0; n<dftsizes[1]; n++) {
+//       ul_ref_sigs[u][0][1][n<<1]    =(int16_t)(floor(32767*cos(M_PI*ref24[(u*24) + n]/4)));
+//       ul_ref_sigs[u][0][1][1+(n<<1)]=(int16_t)(floor(32767*sin(M_PI*ref24[(u*24) + n]/4)));
+//     }
+//   }
+// }
+
+void generate_ul_ref_sigs_rx_NB_IoT(void)
+{
+
+  unsigned int u,index_Nsc_RU,n; // Vincent: index_Nsc_RU 0,1,2,3 ---> number of sc 1,3,6,12 
+  uint8_t npusch_format = 1; // NB-IoT: format 1 (data), or 2: ack. Should be defined in higher layer 
+  int16_t  a;
+  int16_t   qpsk[2]; 
+  unsigned int x1, x2=35; // NB-IoT: defined in 36.211, Section 10.1.4.1.1
+  int16_t ref_sigs_sc1[2*sequence_length[0]]; 
+  uint32_t s; 
+
+  a = (ONE_OVER_SQRT2_Q15_NB_IoT)>>15;
+  qpsk[0] = a; 
+  qpsk[1] = -a;
+  s = lte_gold_generic_NB_IoT(&x1, &x2, 1);
+
+  for (index_Nsc_RU=0; index_Nsc_RU<4; index_Nsc_RU++) {
+    for (u=0; u<u_max[index_Nsc_RU]; u++) { 
+      // ul_ref_sigs_rx[u][index_Nsc_RU] = (int16_t*)malloc16(2*sizeof(int16_t)*sequence_length[index_Nsc_RU]); 
+      switch (index_Nsc_RU){
+        case 0: // 36.211, Section 10.1.4.1.1
+          ul_ref_sigs_rx[u][index_Nsc_RU] = (int16_t*)malloc16(sizeof(int16_t)*(2*sequence_length[index_Nsc_RU]*12+24)); // *12 is mandatory to fit channel estimation functions
+          // NB-IoT: for same reason, +24 is added in order to fit the possible subcarrier start shift when index_Nsc_RU = 0, 1, 2 --> see ul_sc_start in channel estimation function
+          for (n=0; n<sequence_length[index_Nsc_RU]; n++) {
+            ref_sigs_sc1[n<<1]    = qpsk[(s>>n)&1]*w_n[16*u+n%16]; 
+            // ref_sigs_sc1[1+(n<<1)] = qpsk[(s>>n)&1]*w_n[16*u+n%16];
+            ref_sigs_sc1[1+(n<<1)] = ref_sigs_sc1[n<<1];  
+          }
+          if (npusch_format==1){
+            for (n=0; n<sequence_length[index_Nsc_RU]; n++) {
+              // ul_ref_sigs_rx[u][index_Nsc_RU][n<<1]    = ref_sigs_sc1[n<<1];
+              // ul_ref_sigs_rx[u][index_Nsc_RU][1+(n<<1)]= ref_sigs_sc1[1+(n<<1)];
+              ul_ref_sigs_rx[u][index_Nsc_RU][12*n<<1+24]    = ref_sigs_sc1[n<<1]; // ul_ref_sigs_rx is filled every 12 RE, real part
+              ul_ref_sigs_rx[u][index_Nsc_RU][1+12*(n<<1)+24]= ref_sigs_sc1[1+(n<<1)]; // ul_ref_sigs_rx is filled every 12 RE, imaginary part    
+            }
+          }
+          if (npusch_format==2){// NB-IoT: to be implemented
+            printf("Not coded yet\n"); 
+          }
+          break; 
+        case 1: // 36.211, Section 10.1.4.1.2
+          ul_ref_sigs_rx[u][index_Nsc_RU] = (int16_t*)malloc16(sizeof(int16_t)*(2*12+24)); // *12 is mandatory to fit channel estimation functions
+          for (n=0; n<sequence_length[index_Nsc_RU]; n++) {
+            // ul_ref_sigs_rx[u][index_Nsc_RU][n<<1]    = (int16_t)(floor(32767*cos(M_PI*ref3[(u*3) + n]/4 + alpha3[threetnecyclicshift])));
+            // ul_ref_sigs_rx[u][index_Nsc_RU][1+(n<<1)]= (int16_t)(floor(32767*sin(M_PI*ref3[(u*3) + n]/4 + alpha3[threetnecyclicshift]))); 
+            ul_ref_sigs_rx[u][index_Nsc_RU][n<<1+24]    = (int16_t)(floor(32767*cos(M_PI*ref3[(u*3) + n]/4 )));
+            ul_ref_sigs_rx[u][index_Nsc_RU][1+(n<<1)+24]= (int16_t)(floor(32767*sin(M_PI*ref3[(u*3) + n]/4 )));
+          }
+          break; 
+        case 2:
+          ul_ref_sigs_rx[u][index_Nsc_RU] = (int16_t*)malloc16(sizeof(int16_t)*(2*12+24)); // *12 is mandatory to fit channel estimation functions
+          for (n=0; n<sequence_length[index_Nsc_RU]; n++) {
+            // ul_ref_sigs_rx[u][index_Nsc_RU][n<<1]    = (int16_t)(floor(32767*cos(M_PI*ref6[(u*6) + n]/4 + alpha6[sixtonecyclichift])));
+            // ul_ref_sigs_rx[u][index_Nsc_RU][1+(n<<1)]= (int16_t)(floor(32767*sin(M_PI*ref6[(u*6) + n]/4 + alpha6[sixtonecyclichift])));
+            ul_ref_sigs_rx[u][index_Nsc_RU][n<<1+24]    = (int16_t)(floor(32767*cos(M_PI*ref6[(u*6) + n]/4 )));
+            ul_ref_sigs_rx[u][index_Nsc_RU][1+(n<<1)+24]= (int16_t)(floor(32767*sin(M_PI*ref6[(u*6) + n]/4 )));
+          }
+          break; 
+        case 3:
+          ul_ref_sigs_rx[u][index_Nsc_RU] = (int16_t*)malloc16(sizeof(int16_t)*(2*12+24)); // *12 is mandatory to fit channel estimation functions
+          for (n=0; n<sequence_length[index_Nsc_RU]; n++) {
+            ul_ref_sigs_rx[u][index_Nsc_RU][n<<1]    = (int16_t)(floor(32767*cos(M_PI*ref12[(u*12) + n]/4)));
+            ul_ref_sigs_rx[u][index_Nsc_RU][1+(n<<1)]= (int16_t)(floor(32767*sin(M_PI*ref12[(u*12) + n]/4)));
+          }
+          break; 
+      }
+    }
+  }
+
+
+}
+
+void free_ul_ref_sigs_NB_IoT(void)
+{
+
+  unsigned int u,index_Nsc_RU;
+
+  for (index_Nsc_RU=0; index_Nsc_RU<4; index_Nsc_RU++) {
+    for (u=0; u<30; u++) {
+        if (ul_ref_sigs_rx[u][index_Nsc_RU])
+          free16(ul_ref_sigs_rx[u][index_Nsc_RU],4*sizeof(int16_t)*sequence_length[index_Nsc_RU]);
+    }
+  }
+}
+
+// void free_ul_ref_sigs(void)
+// {
+
+//   unsigned int u,index_Nsc_RU;
+
+//   for (index_Nsc_RU=0; index_Nsc_RU<4; index_Nsc_RU++) {
+//     for (u=0; u<30; u++) {
+//         if (ul_ref_sigs_rx[u][index_Nsc_RU])
+//           free16(ul_ref_sigs_rx[u][index_Nsc_RU],4*sizeof(int16_t)*sequence_length[index_Nsc_RU]);
+//     }
+//   }
+// }
+
+#ifdef MAIN
+main()
+{
+
+  //generate_ul_ref_sigs();
+  generate_ul_ref_sigs_rx();
+  free_ul_ref_sigs();
+}
+#endif
diff --git a/openair1/PHY/LTE_TRANSPORT/dci.c b/openair1/PHY/LTE_TRANSPORT/dci.c
index 41180b6e61c4c5ec88b404e98438575e4f3a4f31..65f36247fc2f297aa0415ab293e903655b3f3adc 100755
--- a/openair1/PHY/LTE_TRANSPORT/dci.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci.c
@@ -2120,6 +2120,8 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
   // generate DCIs in order of decreasing aggregation level, then common/ue spec
   // MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization
   for (L=3; L>=0; L--) {
+
+	  //first common DCI
     for (i=0; i<num_common_dci; i++) {
 
       if (dci_alloc[i].L == (uint8_t)L) {
@@ -2140,6 +2142,7 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
       }
     }
 
+    //start the second loop from the end of the previous one for ue specific DCI
     for (; i<num_ue_spec_dci + num_common_dci; i++) {
 
       if (dci_alloc[i].L == (uint8_t)L) {
@@ -2157,9 +2160,9 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
                                 dci_alloc[i].L,
                                 dci_alloc[i].rnti);
         }
-	else {
-	  
-	}
+  else {
+    
+  }
       }
     }
   }
@@ -2368,7 +2371,6 @@ uint8_t generate_dci_top(uint8_t num_ue_spec_dci,
 
   return(num_pdcch_symbols);
 }
-
 #ifdef PHY_ABSTRACTION
 uint8_t generate_dci_top_emul(PHY_VARS_eNB *phy_vars_eNB,
                               uint8_t num_ue_spec_dci,
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.c
new file mode 100755
index 0000000000000000000000000000000000000000..56097ec55a2c7ef77b348c4479c8bfffd9e5ca94
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.c
@@ -0,0 +1,599 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/dci.c
+* \brief Implements PDCCH physical channel TX/RX procedures (36.211) and DCI encoding/decoding (36.212/36.213). Current LTE compliance V8.6 2009-03.
+* \author R. Knopp
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: knopp@eurecom.fr
+* \note
+* \warning
+*/
+#ifdef USER_MODE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+//#include "PHY/defs.h"
+//#include "PHY/LTE_TRANSPORT/dci_NB_IoT.h"
+//#include "PHY/CODING/defs_NB_IoT.h"
+#include "PHY/defs_NB_IoT.h"  // /LTE_TRANSPORT/defs_NB_IoT.h
+//#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
+//#include "PHY/extern.h"
+//////////#include "PHY/extern_NB_IoT.h"
+//#include "SCHED/defs.h"
+/////////////////////////////#include "SCHED/defs_nb_iot.h"
+//#include "SIMULATION/TOOLS/defs.h" // for taus 
+//#include "PHY/sse_intrin.h"
+
+//#include "assertions.h" 
+//#include "T.h"
+
+
+//------------------------------------------------
+// BCOM code functions npdcch start
+// (TODO solve some error in compilation)
+//------------------------------------------------
+static uint8_t d[2][3*(MAX_DCI_SIZE_BITS_NB_IoT + 16) + 96];
+static uint8_t w[2][3*3*(MAX_DCI_SIZE_BITS_NB_IoT+16)];
+
+
+
+void dci_encoding_NB_IoT(uint8_t    *a[2],				// Array of two DCI pdus, even if one DCI is to transmit , the number of DCI is indicated in dci_number
+						 uint8_t    A,					// Length of array a (in number of bytes)(es 4 bytes = 32 bits) is a parameter fixed
+						 uint16_t   E,					// E should equals to G (number of available bits in one RB)
+						 uint8_t    *e[2],				// *e should be e[2][G]
+						 uint16_t   rnti[2],			// RNTI for UE specific or common search space
+						 uint8_t    dci_number,			// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
+						 uint8_t    agr_level)			// Aggregation level
+{
+	uint8_t  D = (A + 16);
+	uint32_t RCC;
+	uint8_t  occupation_size=1;
+	// encode dci
+	if(dci_number == 1)
+	{
+		if(agr_level == 2)
+		{
+			occupation_size=1;
+		}else{
+			occupation_size=2;
+		}
+		memset((void *)d[0],LTE_NULL_NB_IoT,96);
+
+		ccode_encode_NB_IoT(A,2,a[0],d[0]+96,rnti[0]);    					// CRC attachement & Tail-biting convolutional coding
+		RCC = sub_block_interleaving_cc_NB_IoT(D,d[0]+96,w[0]);				// Interleaving
+		lte_rate_matching_cc_NB_IoT(RCC,(E/occupation_size),w[0],e[0]);		// Rate Matching
+
+	}else if (dci_number == 2) {
+
+		memset((void *)d[0],LTE_NULL_NB_IoT,96);
+		memset((void *)d[1],LTE_NULL_NB_IoT,96);
+		// first DCI encoding
+		ccode_encode_NB_IoT(A,2,a[0],d[0]+96,rnti[0]);    					// CRC attachement & Tail-biting convolutional coding
+		RCC = sub_block_interleaving_cc_NB_IoT(D,d[0]+96,w[0]);				// interleaving
+		lte_rate_matching_cc_NB_IoT(RCC,E/2,w[0],e[0]);						// Rate Matching , E/2 ,  NCCE0
+		// second DCI encoding
+		ccode_encode_NB_IoT(A,2,a[1],d[1]+96,rnti[1]);    					// CRC attachement & Tail-biting convolutional coding
+		RCC = sub_block_interleaving_cc_NB_IoT(D,d[1]+96,w[1]);				// Interleaving
+		lte_rate_matching_cc_NB_IoT(RCC,E/2,w[1],e[1]);						// Rate Matching, E/2 , NCCE1
+
+	}
+}
+
+///The scrambling sequence shall be initialised at the start of the search space and after every 4th NPDCCH subframes.
+///
+///
+void npdcch_scrambling_NB_IoT(NB_IoT_DL_FRAME_PARMS    *frame_parms,
+							  uint8_t                  *e[2],			// Input data
+							  int                      length,        	// Total number of bits to transmit in one subframe(case of DCI = G)
+							  uint8_t 				   Ns,				//XXX we pass the subframe	// Slot number (0..19)
+							  uint8_t 				   dci_number,		// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
+							  uint8_t 				   agr_level)		// Aggregation level
+{
+	int 	  i,k=0;
+	uint32_t  x1, x2, s=0;
+	uint8_t   reset;
+	uint8_t   occupation_size=1;
+
+	reset = 1;
+
+	if(agr_level == 2)
+	{
+		occupation_size=1;
+	}else{
+		occupation_size=2;
+	}
+
+	if(dci_number == 1)														// Case of one DCI
+	{
+		x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell;                          // This is c_init in 36.211 Sec 10.2.3.1
+
+		for (i=0; i<length/occupation_size; i++) {
+			if ((i&0x1f)==0) {
+				s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
+				reset = 0;
+			}
+			e[0][k] = (e[0][k]&1) ^ ((s>>(i&0x1f))&1);
+		}
+
+	}else if(dci_number == 2 && occupation_size == 2) {						// Case of two DCI
+
+		// Scrambling the first DCI
+		//
+		x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell;                          // This is c_init in 36.211 Sec 10.2.3.1
+
+		for (i=0; i<length/occupation_size; i++) {
+			if ((i&0x1f)==0) {
+				s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
+				reset = 0;
+			}
+			e[0][k] = (e[0][k]&1) ^ ((s>>(i&0x1f))&1);
+		}
+		// reset of the scrambling function
+		reset = 1;
+		// Scrambling the second DCI
+		//
+		x2 = ((Ns>>1)<<9) + frame_parms->Nid_cell;                          //this is c_init in 36.211 Sec 10.2.3.1
+
+		for (i=0; i<length/occupation_size; i++) {
+			if ((i&0x1f)==0) {
+				s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
+				reset = 0;
+			}
+			e[1][k] = (e[1][k]&1) ^ ((s>>(i&0x1f))&1);
+		}
+	}
+}
+
+
+int dci_allocate_REs_in_RB_NB_IoT(NB_IoT_DL_FRAME_PARMS 	*frame_parms,
+                                  int32_t 					**txdataF,
+                                  uint32_t 					*jj,
+                                  uint32_t 					symbol_offset,
+                                  uint8_t 					*x0[2],
+                                  uint8_t 					pilots,
+                                  int16_t 					amp,
+						  	      unsigned short 			id_offset,
+                                  uint32_t 					*re_allocated, 	//  not used variable ??!!
+								  uint8_t 					dci_number,		// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
+								  uint8_t 					agr_level)
+{
+	MIMO_mode_NB_IoT_t mimo_mode = (frame_parms->mode1_flag==1)?SISO_NB_IoT:ALAMOUTI_NB_IoT;
+
+	uint32_t  tti_offset,aa;
+	uint8_t   re;
+	int16_t   gain_lin_QPSK;
+	uint8_t   first_re,last_re;
+	int32_t   tmp_sample1,tmp_sample2,tmp_sample3,tmp_sample4;
+
+	gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+	first_re=0;
+	last_re=12;
+
+	if(agr_level == 2 && dci_number == 1)
+	{
+		for (re=first_re; re<last_re; re++) {      	// re varies between 0 and 12 sub-carriers
+
+			tti_offset = symbol_offset + re;				// symbol_offset = 512 * L ,  re_offset = 512 - 3*12  , re
+
+			if (pilots != 1 || re%3 != id_offset)  			// if re is not a pilot
+			{
+															//	diff_re = re%3 - id_offset;
+				if (mimo_mode == SISO_NB_IoT) {  					//SISO mapping
+					*re_allocated = *re_allocated + 1;				// variable incremented but never used
+
+					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+						((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
+					}
+					*jj = *jj + 1;
+					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+						((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+					}
+					*jj = *jj + 1;
+
+				} else if (mimo_mode == ALAMOUTI_NB_IoT) {
+
+					*re_allocated = *re_allocated + 1;
+
+					((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+					((int16_t*)&tmp_sample1)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+
+					// second antenna position n -> -x1*
+
+					((int16_t*)&tmp_sample2)[0] = (x0[0][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
+					*jj=*jj+1;
+					((int16_t*)&tmp_sample2)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+
+					// normalization for 2 tx antennas
+					((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+
+					// fill in the rest of the ALAMOUTI precoding
+					if ( pilots != 1 || (re+1)%3 != id_offset) {
+						((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
+						((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
+					} else {
+						((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
+						((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
+
+						re++;														// skip pilots
+						*re_allocated = *re_allocated + 1;
+					}
+					re++;  															// adjacent carriers are taken care of by precoding
+					*re_allocated = *re_allocated + 1;   							// incremented variable but never used
+				}
+			}
+		}
+  	}else if(agr_level == 1 && dci_number == 1){
+
+		for (re=first_re; re<6; re++) {      		// re varies between 0 and 6 sub-carriers
+
+    		tti_offset = symbol_offset + re;				// symbol_offset = 512 * L ,  re_offset = 512 - 3*12  , re
+
+			if (pilots != 1 || re%3 != id_offset)  			// if re is not a pilot
+			{
+													//	diff_re = re%3 - id_offset;
+				if (mimo_mode == SISO_NB_IoT) {  								//SISO mapping
+					*re_allocated = *re_allocated + 1;						// variable incremented but never used
+
+					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+						((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
+					}
+					*jj = *jj + 1;
+					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+						((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+					}
+					*jj = *jj + 1;
+
+				} else if (mimo_mode == ALAMOUTI_NB_IoT) {
+
+					*re_allocated = *re_allocated + 1;
+
+					((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+					((int16_t*)&tmp_sample1)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+
+					// second antenna position n -> -x1*
+
+					((int16_t*)&tmp_sample2)[0] = (x0[0][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
+					*jj=*jj+1;
+					((int16_t*)&tmp_sample2)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+
+					// normalization for 2 tx antennas
+					((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+
+					// fill in the rest of the ALAMOUTI precoding
+					if ( pilots != 1 || (re+1)%3 != id_offset) {
+						((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
+						((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
+					} else {
+						((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
+						((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
+
+						re++;														// skip pilots
+						*re_allocated = *re_allocated + 1;
+					}
+					re++;  															// adjacent carriers are taken care of by precoding
+					*re_allocated = *re_allocated + 1;   							// incremented variable but never used
+		 		}
+     		}
+   		}
+ 	} else {
+
+		// allocate first DCI
+		for (re=first_re; re<6; re++) {      		// re varies between 0 and 12 sub-carriers
+
+    		tti_offset = symbol_offset + re;				// symbol_offset = 512 * L ,  re_offset = 512 - 3*12  , re
+
+			if (pilots != 1 || re%3 != id_offset) { 			// if re is not a pilot
+			
+													//	diff_re = re%3 - id_offset;
+     			if (mimo_mode == SISO_NB_IoT) {  								//SISO mapping
+					*re_allocated = *re_allocated + 1;						// variable incremented but never used
+
+					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+						((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
+						((int16_t*)&txdataF[aa][tti_offset+6])[0] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
+					}
+					*jj = *jj + 1;
+					for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+						((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+						((int16_t*)&txdataF[aa][tti_offset+6])[1] += (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+					}
+					*jj = *jj + 1;
+
+     			} else if (mimo_mode == ALAMOUTI_NB_IoT) {
+
+					*re_allocated = *re_allocated + 1;
+
+					((int16_t*)&tmp_sample1)[0] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					((int16_t*)&tmp_sample3)[0] = (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+					((int16_t*)&tmp_sample1)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					((int16_t*)&tmp_sample3)[1] = (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+
+					// second antenna position n -> -x1*
+
+					((int16_t*)&tmp_sample2)[0] = (x0[0][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
+					((int16_t*)&tmp_sample4)[0] = (x0[1][*jj]==1) ? (gain_lin_QPSK) : -gain_lin_QPSK;
+					*jj=*jj+1;
+					((int16_t*)&tmp_sample2)[1] = (x0[0][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					((int16_t*)&tmp_sample4)[1] = (x0[1][*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
+					*jj=*jj+1;
+
+					// normalization for 2 tx antennas
+					((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+
+					((int16_t*)&txdataF[0][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample3)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[0][tti_offset+6])[1] += (int16_t)((((int16_t*)&tmp_sample3)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset+6])[0] += (int16_t)((((int16_t*)&tmp_sample4)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+					((int16_t*)&txdataF[1][tti_offset+6])[1] += (int16_t)((((int16_t*)&tmp_sample4)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+
+					// fill in the rest of the ALAMOUTI precoding
+					if ( pilots != 1 || (re+1)%3 != id_offset) {
+						((int16_t *)&txdataF[0][tti_offset+1])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+1])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
+						((int16_t *)&txdataF[1][tti_offset+1])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+1])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
+
+						((int16_t *)&txdataF[0][tti_offset+6+1])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+6+1])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1];
+						((int16_t *)&txdataF[1][tti_offset+6+1])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+6+1])[1] += -((int16_t *)&txdataF[0][tti_offset+6])[1];
+					} else {
+						((int16_t *)&txdataF[0][tti_offset+2])[0] += -((int16_t *)&txdataF[1][tti_offset])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+2])[1] += ((int16_t *)&txdataF[1][tti_offset])[1];
+						((int16_t *)&txdataF[1][tti_offset+2])[0] += ((int16_t *)&txdataF[0][tti_offset])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+2])[1] += -((int16_t *)&txdataF[0][tti_offset])[1];
+
+						((int16_t *)&txdataF[0][tti_offset+6+2])[0] += -((int16_t *)&txdataF[1][tti_offset+6])[0]; //x1
+						((int16_t *)&txdataF[0][tti_offset+6+2])[1] += ((int16_t *)&txdataF[1][tti_offset+6])[1];
+						((int16_t *)&txdataF[1][tti_offset+6+2])[0] += ((int16_t *)&txdataF[0][tti_offset+6])[0];  //x0*
+						((int16_t *)&txdataF[1][tti_offset+6+2])[1] += -((int16_t *)&txdataF[0][tti_offset+6])[1];
+
+						re++;														// skip pilots
+						*re_allocated = *re_allocated + 1;
+					}
+					re++;  															// adjacent carriers are taken care of by precoding
+					*re_allocated = *re_allocated + 1;   							// incremented variable but never used
+				}
+      		}
+    	}
+  	}
+  	return(0);
+}
+
+
+int dci_modulation_NB_IoT(int32_t 					**txdataF,
+						  int16_t 					amp,
+						  NB_IoT_DL_FRAME_PARMS 	*frame_parms,
+						  uint8_t 					control_region_size,    //XXX we pass the npdcch_start_symbol // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
+						  uint8_t 					*e[2],					// Input data
+						  int 						G,						// number of bits per subframe
+						  uint8_t 					dci_number,				// This variable should takes the 1 or 2 (1 for in case of one DCI, 2 in case of two DCI)
+						  uint8_t 					agr_level)				// Aggregation level
+{
+    uint32_t 		jj=0;
+	uint32_t 		re_allocated,symbol_offset;
+    uint16_t 		l;
+    uint8_t 		id_offset,pilots=0;
+	unsigned short  bandwidth_even_odd;
+    unsigned short  NB_IoT_start, RB_IoT_ID;
+
+    re_allocated=0;
+	id_offset=0;
+	// testing if the total number of RBs is even or odd
+	bandwidth_even_odd = frame_parms->N_RB_DL % 2; 	 		// 0 even, 1 odd
+	RB_IoT_ID = frame_parms->NB_IoT_RB_ID;
+	// step  5, 6, 7   									 	// modulation and mapping (slot 1, symbols 0..3)
+	for (l=control_region_size; l<14; l++) { 				// loop on OFDM symbols
+		if((l>=4 && l<=8) || (l>=11 && l<=13))
+		{
+			pilots =1;
+		} else {
+			pilots=0;
+		}
+		id_offset = frame_parms->Nid_cell % 3;    			// Cell_ID_NB_IoT % 3
+		if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
+		{
+			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID% (int)(ceil(frame_parms->N_RB_DL/(float)2)));
+		} else {
+			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID % (int)(ceil(frame_parms->N_RB_DL/(float)2)));
+		}
+		symbol_offset = frame_parms->ofdm_symbol_size*l + NB_IoT_start;  						// symbol_offset = 512 * L + NB_IOT_RB start
+		dci_allocate_REs_in_RB_NB_IoT(frame_parms,
+								      txdataF,
+							    	  &jj,
+									  symbol_offset,
+									  e,
+									  pilots,
+									  amp,
+									  id_offset,
+									  &re_allocated,
+									  dci_number,
+									  agr_level);
+	}
+
+    // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
+  return (re_allocated);
+}
+
+//------------------------------------------------
+// BCOM code functions npdcch end
+//------------------------------------------------
+
+
+
+
+uint8_t generate_dci_top_NB_IoT(NB_IoT_eNB_NPDCCH_t		*npdcch,
+						 		uint8_t 				Num_dci,
+                         		DCI_ALLOC_NB_IoT_t 		*dci_alloc,
+                         		int16_t 				amp,
+                         		NB_IoT_DL_FRAME_PARMS 	*fp,
+                         		int32_t 				**txdataF,
+                         		uint32_t 				subframe,
+						 		uint8_t 				npdcch_start_symbol)
+{
+
+
+  int      i, G;
+  //temporary variable
+  uint16_t rnti[2];
+  uint8_t  L = 0;
+
+
+  /* PARAMETERS may not needed
+  **e_ptr : store the encoding result, and as a input to modulation
+  *num_pdcch_symbols : to calculate the resource allocation for pdcch
+  *L = aggregation level (there is 2 (at most) in NB-IoT) (Note this is not the real value but the index)
+  *lprime,kprime,kprime_mod12,mprime,nsymb,symbol_offset,tti_offset,re_offset : used in the REG allocation
+  *gain_lin_QPSK,yseq0[Msymb],yseq1[Msymb],*y[2] : used in the modulation
+  *mi = used in interleaving
+  *e = used to store the taus sequence (taus sequence is used to generate the first sequence for DCI) Turbo coding
+  *wbar used in the interleaving and also REG allocation
+  */
+
+  // MAC is assumed to have ordered the UE spec DCI according to the RNTI-based randomization???
+
+  // Value of aggregation level (FAPI/NFAPI specs v.9.0 pag 221 value 1,2)
+  /*
+   * in NB-IoT we can have at most 2 aggregation level since we have only 2 NCCE (Narrowband control channel element)
+   * if only 1 DCI transmitted:
+   * 	- Aggregation level could be 1 or 2
+   * if 2 DCI transmitted:
+   * 	- Aggregation level should be 1
+   *
+   */
+
+  //First take all the DCI pdu and their corrispondent rnti
+  for(i = 0; i<Num_dci;i++)
+  {
+	  npdcch->a[i]=dci_alloc[i].dci_pdu;
+	  rnti[i]=dci_alloc[i].rnti;
+	  L = dci_alloc[i].L;
+
+  }
+
+  if(Num_dci == 2 && L == 1)
+	  LOG_E(PHY,"generate_dci_top_NB_IoT: Aggregation level not compatible with Num_dci\n" );
+
+
+  //Second, evaluate the G variable based of the npdcch_start_sysmbol
+
+  /*
+   * TS 36.213 ch 16.6.1
+   * npdcch_start_symbol  indicate the starting OFDM symbol for NPDCCH in the first slot of a subframe k ad is determined as follow:
+   * - if eutracontrolregionsize is present (defined for in-band operating mode (mode 0,1 for FAPI specs))
+   * 	npdcch_start_symbol = eutracontrolregionsize (value 1,2,3) [units in number of OFDM symbol]
+   * -otherwise
+   * 	npdcch_start_symbol = 0
+   *
+   *XXX npdcch_start symbol should be the same for every DCI once is decided since depends on the parameters
+   *(the setting of this npdcch_start_symbol parameter should be done in the MAC)
+   *Depending on npdcch_start_symbol then we define different values for G
+   *
+   */
+
+
+  switch(npdcch_start_symbol) //mail Bcom matthieu
+  {
+	  	  case 0:
+	  		  G = 304;
+		 	break;
+	  	  case 1:
+	  		  G = 240;
+	  		  break;
+	  	  case 2:
+	  		  G = 224;
+	  		  break;
+	  	  case 3:
+	  		  G =200;
+	  		  break;
+	  	  default:
+	  		  LOG_E (PHY,"npdcch_start_symbol has unwanted value\n");
+	  		  break;
+  }
+
+   //NB-IoT encoding
+//  dci_encoding_NB_IoT(
+//		  	  	  	  a,
+//					  4, // total length (in byte) of a [assume max 2 pdus of  ??]
+//					  G,
+//					  npdcch->e,
+//					  rnti,
+//					  Num_dci,
+//					  L
+//		  	  	  	  );
+
+
+
+  //NB-IoT scrambling
+//  npdcch_scrambling_NB_IoT(
+//		  	  	  	  	  fp,
+//						  npdcch->e,
+//						  G,
+//						  subframe,
+//						  Num_dci,
+//						  L
+//		  	  	  	  	   );
+
+
+  //NB-IoT Modulation
+//  dci_modulation_NB_IoT(
+//		  	  	  	  txdataF,
+//					  amp,
+//					  fp,
+//					  npdcch_start_symbol,
+//					  npdcch->e,
+//					  G,
+//					  Num_dci,
+//					  L
+//		  	  	  	  );
+
+
+
+  return 0;
+}
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h b/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h
similarity index 57%
rename from openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h
rename to openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h
index ce3737e6b5ed82a4e3f494df5e7fcc89d446e9c1..ea84f66de42e1e69fb765af2606c3c296d0aabbf 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h
+++ b/openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h
@@ -29,21 +29,25 @@
 * \note
 * \warning
 */
-#ifndef USER_MODE
-#include "PHY/types.h"
-#else
+#ifndef __DCI_NB_IOT_H__
+#define __DCI_NB_IOT_H__
+
+//#ifndef USER_MODE
+//#include "PHY/types.h"
+//#else
 #include <stdint.h>
-#endif
+//#endif
 
-typedef enum DCI_format_NB
+typedef enum 
 {
   DCIFormatN0 = 0,
   DCIFormatN1,
-  DCIFormatN1_RA,
+  DCIFormatN1_RA,//is for initial RA procedure (semi-static information) so maybe is not needed
   DCIFormatN1_RAR,
+  DCIFormatN2,
   DCIFormatN2_Ind,
   DCIFormatN2_Pag,
-}e_DCI_format_NB;
+}DCI_format_NB_IoT_t;
 
 ///  DCI Format Type 0 (180 kHz, 23 bits)
 struct DCIFormatN0{
@@ -68,7 +72,6 @@ struct DCIFormatN0{
 };
 
 typedef struct DCIFormatN0 DCIFormatN0_t;
-#define sizeof_DDCIFormatN0_t 23
 
 ///  DCI Format Type N1 for User data
 struct DCIFormatN1{
@@ -94,7 +97,6 @@ struct DCIFormatN1{
 
 
 typedef struct DCIFormatN1 DCIFormatN1_t;
-#define sizeof_DCIFormatN1_t 23
 
 ///  DCI Format Type N1 for initial RA
 struct DCIFormatN1_RA{
@@ -111,30 +113,30 @@ struct DCIFormatN1_RA{
 };
 
 typedef struct DCIFormatN1_RA DCIFormatN1_RA_t;
-#define sizeof_DCIFormatN1_RA_t 23
 
-///  DCI Format Type N1 for RAR
+///  DCI Format Type N1 for User data
 struct DCIFormatN1_RAR{
-  /// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
+  /// type = 0 => DCI Format N0, type = 1 => DCI Format N1,1bits
   uint8_t type;
-  //NPDCCH order indicator (set to 0),1 bits
+  //NPDCCH order indicator (set to 0), 1 bits
   uint8_t orderIndicator;
-  // Scheduling Delay, 3 bits
+  // Scheduling Delay,3 bits
   uint8_t Scheddly;
-  // Resourse Assignment (RU Assignment), 3 bits
+  // Resourse Assignment (RU Assignment),3 bits
   uint8_t ResAssign;
-  // Modulation and Coding Scheme, 4 bits
+  // Modulation and Coding Scheme,4 bits
   uint8_t mcs;
-  // Repetition Number, 4 bits
+  // Repetition Number,4 bits
   uint8_t RepNum;
-  // Reserved 5 bits
-  uint8_t Reserved;
-  // DCI subframe repetition Number, 2 bits
+  // New Data Indicator,1 bits,reserved in the RAR
+  uint8_t ndi;
+  // HARQ-ACK resource,4 bits,reserved in the RAR
+  uint8_t HARQackRes;
+  // DCI subframe repetition Number,2 bits
   uint8_t DCIRep;
 };
 
 typedef struct DCIFormatN1_RAR DCIFormatN1_RAR_t;
-#define sizeof_DCIFormatN1_RAR_t 23
 
 //  DCI Format Type N2 for direct indication, 15 bits
 struct DCIFormatN2_Ind{
@@ -147,7 +149,6 @@ struct DCIFormatN2_Ind{
 };
 
 typedef struct DCIFormatN2_Ind DCIFormatN2_Ind_t;
-#define sizeof_DCIFormatN2_Ind_t 15
 
 //  DCI Format Type N2 for Paging, 15 bits
 struct DCIFormatN2_Pag{
@@ -164,9 +165,8 @@ struct DCIFormatN2_Pag{
 };
 
 typedef struct DCIFormatN2_Pag DCIFormatN2_Pag_t;
-#define sizeof_DCIFormatN2_Pag_t 15
 
- typedef union DCI_CONTENT {
+typedef union DCI_CONTENT {
  // 
  DCIFormatN0_t DCIN0;
  //
@@ -180,4 +180,113 @@ typedef struct DCIFormatN2_Pag DCIFormatN2_Pag_t;
  //
  DCIFormatN2_Pag_t DCIN2_Pag;
 
- }DCI_CONTENT;
\ No newline at end of file
+ }DCI_CONTENT;
+
+ /*Structure for packing*/
+
+ struct DCIN0{
+  /// DCI subframe repetition Number, 2 bits
+  uint8_t DCIRep:2;
+  /// New Data Indicator, 1 bits
+  uint8_t ndi:1;
+  /// Repetition Number, 3 bits
+  uint8_t RepNum:3;
+  /// Redundancy version for HARQ (only use 0 and 2), 1 bits
+  uint8_t rv:1;
+  /// Modulation and Coding Scheme, 4 bits
+  uint8_t mcs:4;
+  /// Scheduling Delay, 2 bits
+  uint8_t Scheddly:2;
+  /// Resourse Assignment (RU Assignment), 3 bits
+  uint8_t ResAssign:3;
+  /// Subcarrier indication, 6 bits
+  uint8_t scind:6;
+  /// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
+  uint8_t type:1;
+ } __attribute__ ((__packed__));
+
+ typedef struct DCIN0 DCIN0_t;
+#define sizeof_DCIN0_t 23
+
+struct DCIN1_RAR{
+  // DCI subframe repetition Number, 2 bits
+  uint8_t DCIRep:2;
+  // HARQ-ACK resource,4 bits
+  uint8_t HARQackRes:4; 
+  // New Data Indicator,1 bits
+  uint8_t ndi:1;
+  // Repetition Number, 4 bits
+  uint8_t RepNum:4;
+  // Modulation and Coding Scheme, 4 bits
+  uint8_t mcs:4;
+  // Resourse Assignment (RU Assignment), 3 bits
+  uint8_t ResAssign:3;
+  // Scheduling Delay, 3 bits
+  uint8_t Scheddly:3;
+  //NPDCCH order indicator (set to 0),1 bits
+  uint8_t orderIndicator:1;
+  /// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
+  uint8_t type:1;
+ } __attribute__ ((__packed__));
+
+ typedef struct DCIN1_RAR DCIN1_RAR_t;
+#define sizeof_DCIN1_RAR_t 23
+
+struct DCIN1{
+  // DCI subframe repetition Number, 2 bits
+  uint8_t DCIRep:2;
+  // HARQ-ACK resource,4 bits
+  uint8_t HARQackRes:4; 
+  // New Data Indicator,1 bits
+  uint8_t ndi:1;
+  // Repetition Number, 4 bits
+  uint8_t RepNum:4;
+  // Modulation and Coding Scheme, 4 bits
+  uint8_t mcs:4;
+  // Resourse Assignment (RU Assignment), 3 bits
+  uint8_t ResAssign:3;
+  // Scheduling Delay, 3 bits
+  uint8_t Scheddly:3;
+  //NPDCCH order indicator (set to 0),1 bits
+  uint8_t orderIndicator:1;
+  /// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
+  uint8_t type:1;
+ } __attribute__ ((__packed__));
+
+ typedef struct DCIN1 DCIN1_t;
+#define sizeof_DCIN1_t 23
+
+//  DCI Format Type N2 for direct indication, 15 bits
+struct DCIN2_Ind{
+  // Reserved information bits, 6 bits
+  uint8_t resInfoBits:6;
+  //Direct indication information, 8 bits
+  uint8_t directIndInf:8;
+  //Flag for paging(1)/direct indication(0), set to 0,1 bits
+  uint8_t type:1;
+} __attribute__ ((__packed__));;
+
+typedef struct DCIN2_Ind DCIN2_Ind_t;
+#define sizeof_DCIN2_Ind_t 15
+
+//  DCI Format Type N2 for Paging, 15 bits
+struct DCIN2_Pag{
+  // Reserved 3 bits
+  uint8_t DCIRep:3;
+  // Repetition Number, 4 bits
+  uint8_t RepNum:4;
+  // Modulation and Coding Scheme, 4 bits
+  uint8_t mcs:4;
+  // Resourse Assignment (RU Assignment), 3 bits
+  uint8_t ResAssign:3;
+  //Flag for paging(1)/direct indication(0), set to 1,1 bits
+  uint8_t type:1;
+} __attribute__ ((__packed__));;
+
+typedef struct DCIN2_Pag DCIN2_Pag_t;
+
+#define sizeof_DCIN2_Pag_t 15
+
+#define MAX_DCI_SIZE_BITS_NB_IoT 23
+
+#endif
diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/dci_tools_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..525c174cb854d87b1d1a3784ea19b31837373b33
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools_NB_IoT.c
@@ -0,0 +1,475 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/dci_tools.c
+ * \brief PHY Support routines (eNB/UE) for filling PDSCH/PUSCH/DLSCH/ULSCH data structures based on DCI PDUs generated by eNB MAC scheduler.
+ * \author R. Knopp
+ * \date 2011
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+//#include "PHY/defs.h"
+#include "PHY/impl_defs_lte_NB_IoT.h"
+#include "openair1/PHY/extern_NB_IoT.h"
+//#include "PHY/LTE_TRANSPORT/extern_NB_IoT.h"
+//#include "SCHED/defs_NB_IoT.h"
+/*
+#ifdef DEBUG_DCI_TOOLS
+#include "PHY/vars_NB_IoT.h"
+#endif
+*/
+//#include "assertions.h"
+//#include "dlsch_tbs_full.h"
+#include "PHY/LTE_TRANSPORT/dlsch_tbs_full_NB_IoT.h"
+
+//#define DEBUG_HARQ
+
+//#include "LAYER2/MAC/extern_NB_IoT.h"
+//#include "LAYER2/MAC/defs_NB_IoT.h"
+#include "PHY/defs_NB_IoT.h"
+
+//#define DEBUG_DCI
+
+void add_dci_NB_IoT(DCI_PDU_NB_IoT *DCI_pdu,void *pdu,rnti_t rnti,unsigned char dci_size_bytes,unsigned char aggregation,unsigned char dci_size_bits,unsigned char dci_fmt, uint8_t npdcch_start_symbol)
+{
+	//put the pdu
+  memcpy(&DCI_pdu->dci_alloc[DCI_pdu->Num_dci].dci_pdu[0],pdu,dci_size_bytes);
+  //configure the dci alloc
+  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].dci_length      = dci_size_bits;
+  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].L               = aggregation;
+  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].rnti            = rnti;
+  DCI_pdu->dci_alloc[DCI_pdu->Num_dci].format          = dci_fmt;
+  DCI_pdu->npdcch_start_symbol                         = npdcch_start_symbol;
+
+  DCI_pdu->Num_dci++;
+
+  LOG_D(MAC,"add ue specific dci format %d for rnti %x \n",dci_fmt,rnti);
+}
+
+
+int generate_eNB_ulsch_params_from_dci_NB_IoT(PHY_VARS_eNB_NB_IoT        *eNB,
+                                              eNB_rxtx_proc_NB_IoT_t     *proc,
+                                              DCI_CONTENT                *DCI_Content,
+                                              uint16_t                   rnti,
+                                              DCI_format_NB_IoT_t        dci_format,
+                                              uint8_t                    UE_id,
+                                              uint8_t                    aggregation,
+									                            uint8_t                    npdcch_start_symbol)
+{
+
+  void *ULSCH_DCI_NB_IoT = NULL;
+
+  eNB->DCI_pdu = (DCI_PDU_NB_IoT*) malloc(sizeof(DCI_PDU_NB_IoT));
+
+  /// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
+  uint8_t type;
+  /// Subcarrier indication, 6 bits
+  uint8_t scind;
+  /// Resourse Assignment (RU Assignment), 3 bits
+  uint8_t ResAssign;
+  /// Modulation and Coding Scheme, 4 bits
+  uint8_t mcs;
+  /// New Data Indicator, 1 bits
+  uint8_t ndi;
+  /// Scheduling Delay, 2 bits
+  uint8_t Scheddly;
+  /// Repetition Number, 3 bits
+  uint8_t RepNum;
+  /// Redundancy version for HARQ (only use 0 and 2), 1 bits
+  uint8_t rv;
+  /// DCI subframe repetition Number, 2 bits
+  uint8_t DCIRep;
+  
+  if (dci_format == DCIFormatN0) 
+    {
+      
+      type        = DCI_Content->DCIN0.type;
+      scind       = DCI_Content->DCIN0.scind;
+      ResAssign   = DCI_Content->DCIN0.ResAssign;
+      mcs         = DCI_Content->DCIN0.mcs;
+      ndi         = DCI_Content->DCIN0.ndi;
+      Scheddly    = DCI_Content->DCIN0.Scheddly;
+      RepNum      = DCI_Content->DCIN0.RepNum;
+      rv          = DCI_Content->DCIN0.rv;
+      DCIRep      = DCI_Content->DCIN0.DCIRep;
+
+      /*Packed DCI here*/
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->type      =type;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->scind     =scind;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->ResAssign =ResAssign;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->Scheddly  =Scheddly;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->mcs       =mcs;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->rv        =rv;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->RepNum    =RepNum;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->ndi       =ndi;
+      ((DCIN0_t *)ULSCH_DCI_NB_IoT)->DCIRep    =DCIRep;
+
+
+      add_dci_NB_IoT(eNB->DCI_pdu,ULSCH_DCI_NB_IoT,rnti,sizeof(DCIN0_t),aggregation,sizeof_DCIN0_t,DCIFormatN0, npdcch_start_symbol);
+
+      // use this value to configure PHY both harq_processes and resource mapping.
+
+
+      
+      return(0);
+    } 
+  else 
+    {
+        LOG_E(PHY,"generate_eNB_ulsch_params_from_dci, Illegal dci_format %d\n",dci_format);
+        return(-1);
+    }
+}
+
+//map the Isf (DCI param) to the number of subframes (Nsf)
+int resource_to_subframe[8] = {1,2,3,4,5,6,8,10};
+
+int generate_eNB_dlsch_params_from_dci_NB_IoT(PHY_VARS_eNB_NB_IoT      *eNB,
+                                              int                      frame,
+                                              uint8_t                  subframe,
+                                              DCI_CONTENT              *DCI_Content,
+                                              uint16_t                 rnti,
+                                              DCI_format_NB_IoT_t      dci_format,
+                                              NB_IoT_eNB_NDLSCH_t      *ndlsch,
+                                              NB_IoT_DL_FRAME_PARMS    *frame_parms,
+                                              uint8_t                  aggregation,
+									                            uint8_t                  npdcch_start_symbol)
+{
+
+  NB_IoT_DL_eNB_HARQ_t  *ndlsch_harq      = ndlsch->harq_process;
+  void                  *DLSCH_DCI_NB_IoT = NULL;
+
+  eNB->DCI_pdu = (DCI_PDU_NB_IoT*) malloc(sizeof(DCI_PDU_NB_IoT));
+
+
+
+  //N1 parameters
+
+  /// type = 0 => DCI Format N0, type = 1 => DCI Format N1, 1 bits
+  uint8_t type = 0;
+  //NPDCCH order indicator (set to 0),1 bits
+  uint8_t orderIndicator = 0;
+  // Scheduling Delay, 3 bits
+  uint8_t Sched_delay = 0;
+  // Resourse Assignment (RU Assignment), 3 bits
+  uint8_t ResAssign = 0;//Isf
+  // Modulation and Coding Scheme, 4 bits
+  uint8_t mcs = 0;
+  // Repetition Number, 4 bits
+  uint8_t RepNum = 0;
+  // DCI subframe repetition Number, 2 bits
+  uint8_t DCIRep = 0;
+  // New Data Indicator,1 bits
+  uint8_t ndi = 0;
+  // HARQ-ACK resource,4 bits
+  uint8_t HARQackRes = 0;
+
+  //N2 parameters
+
+  //Direct indication information, 8 bits
+  uint8_t directIndInf= 0;
+  // Reserved information bits, 6 bits
+  uint8_t resInfoBits =0;
+
+  //   printf("Generate eNB DCI, format %d, rnti %x (pdu %p)\n",dci_format,rnti,dci_pdu);
+
+  switch (dci_format) {
+
+  // Impossible to have a DCI N0, we have condition before
+  case DCIFormatN0:
+    return(-1);
+    break;
+
+  case DCIFormatN1_RAR:  // This is DLSCH allocation for control traffic (no NDI and no ACK/NACK resource for RAR DCI)
+
+
+	/*Packed DCI here-------------------------------------------*/
+    type               = DCI_Content->DCIN1_RAR.type;
+    orderIndicator     = DCI_Content->DCIN1_RAR.orderIndicator; 
+    Sched_delay        = DCI_Content->DCIN1_RAR.Scheddly;
+    ResAssign          = DCI_Content->DCIN1_RAR.ResAssign; 
+    mcs                = DCI_Content->DCIN1_RAR.mcs; 
+    RepNum             = DCI_Content->DCIN1_RAR.RepNum; 
+    ndi                = DCI_Content->DCIN1_RAR.ndi;
+    HARQackRes         = DCI_Content->DCIN1_RAR.HARQackRes; 
+    DCIRep             = DCI_Content->DCIN1_RAR.DCIRep;
+    
+    //DCI pdu content
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->type           =type;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->orderIndicator =orderIndicator;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->Scheddly       =Sched_delay;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->ResAssign      =ResAssign;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->mcs            =mcs;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->RepNum         =RepNum;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->ndi            =ndi;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->HARQackRes     =HARQackRes;
+    ((DCIN1_RAR_t *)DLSCH_DCI_NB_IoT)->DCIRep         =DCIRep;
+
+
+    add_dci_NB_IoT(eNB->DCI_pdu,DLSCH_DCI_NB_IoT,rnti,sizeof(DCIN1_RAR_t),aggregation,sizeof_DCIN1_RAR_t,DCIFormatN1_RAR, npdcch_start_symbol);
+
+
+    /*Now configure the ndlsch structure*/
+
+    ndlsch->subframe_tx[subframe] = 1; // check if it's OK
+    ndlsch->rnti = rnti; //we store the RNTI (e.g. for RNTI will be used later)
+    ndlsch->active = 0; //will be activated by the corresponding NDSLCH pdu
+
+    // use this value to configure PHY both harq_processes and resource mapping.
+    ndlsch_harq->scheduling_delay         = Sched_delay;
+    ndlsch_harq->resource_assignment      = resource_to_subframe[ResAssign];  //from Isf of DCI to the number of subframe
+    ndlsch_harq->repetition_number        = RepNum;
+    ndlsch_harq->dci_subframe_repetitions = DCIRep;
+    ndlsch_harq->modulation               = 2; //QPSK
+    if(ndlsch_harq->round == 0) //this should be set from initialization (init-lte)
+
+    	ndlsch_harq->status = ACTIVE_NB_IoT;
+      ndlsch_harq->mcs    = mcs;
+
+    /*
+     * TS 36.213 ch 16.4.1.5
+     * ITBS is always set equivalent to IMCS for data
+     * ISF = ResAssign
+     */
+
+      ndlsch_harq->TBS      = TBStable_NB_IoT[mcs][ResAssign];
+      ndlsch_harq->subframe = subframe;
+
+    //ndlsch_harq->B; we don-t have now my is given when we receive the dlsch data
+    //ndlsch->error_treshold
+    //ndlsch->G??
+    //ndlsc->nsoft?? //set in new_eNB_dlsch (initialization)
+    //ndlsch-> sqrt_rho_a?? set in dlsch_modulation
+    //ndlsch-> sqrt_rho_b??? set in dlsch_modulation
+
+    //set in new_eNB_dlsch (initialization)
+    /*
+     * Mlimit
+     * nsoft
+     * round
+     */
+
+
+    break;
+
+  case DCIFormatN1: // for user data
+    
+
+    type               = DCI_Content->DCIN1.type;
+    orderIndicator     = DCI_Content->DCIN1.orderIndicator; 
+    Sched_delay        = DCI_Content->DCIN1.Scheddly;
+    ResAssign          = DCI_Content->DCIN1.ResAssign; 
+    mcs                = DCI_Content->DCIN1.mcs; 
+    RepNum             = DCI_Content->DCIN1.RepNum; 
+    ndi                = DCI_Content->DCIN1.ndi;
+    HARQackRes         = DCI_Content->DCIN1.HARQackRes; 
+    DCIRep             = DCI_Content->DCIN1.DCIRep;
+    
+    /*Packed DCI here*/
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->type           =type;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->orderIndicator =orderIndicator;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->Scheddly       =Sched_delay;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->ResAssign      =ResAssign;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->mcs            =mcs;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->RepNum         =RepNum;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->ndi            =ndi;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->HARQackRes     =HARQackRes;
+    ((DCIN1_t *)DLSCH_DCI_NB_IoT)->DCIRep         =DCIRep;
+
+
+    add_dci_NB_IoT(eNB->DCI_pdu,DLSCH_DCI_NB_IoT,rnti,sizeof(DCIN1_t),aggregation,sizeof_DCIN1_t,DCIFormatN1,npdcch_start_symbol);
+
+    /*Now configure the ndlsch structure*/
+
+    ndlsch->subframe_tx[subframe] = 1; // check if it's OK
+    ndlsch->rnti                  = rnti; //we store the RNTI (e.g. for RNTI will be used later)
+    ndlsch->active                = 0;//will be activated by the corresponding NDSLCH pdu
+
+    // use this value to configure PHY both harq_processes and resource mapping.
+        ndlsch_harq->scheduling_delay         = Sched_delay;
+        ndlsch_harq->resource_assignment      = resource_to_subframe[ResAssign]; //from Isf of DCI to the number of subframe
+        ndlsch_harq->repetition_number        = RepNum;
+        ndlsch_harq->dci_subframe_repetitions = DCIRep;
+        ndlsch_harq->modulation               = 2; //QPSK
+        if(ndlsch_harq->round == 0){ //this should be set from initialization (init-lte)
+
+        	ndlsch_harq->status  = ACTIVE_NB_IoT;
+        	ndlsch_harq->mcs     = mcs;
+        	ndlsch_harq->TBS     = TBStable_NB_IoT[mcs][ResAssign]; // this table should be rewritten for nb-iot
+        }
+        ndlsch_harq->frame    = frame;
+        ndlsch_harq->subframe = subframe;
+
+
+
+    break;
+
+  case DCIFormatN2_Ind: //MP: for the moment is not implemented
+
+    type               = DCI_Content->DCIN2_Ind.type;
+    directIndInf       = DCI_Content->DCIN2_Ind.directIndInf; 
+    resInfoBits        = DCI_Content->DCIN2_Ind.resInfoBits; 
+
+    /*Packed DCI here*/
+    ((DCIN2_Ind_t *)DLSCH_DCI_NB_IoT)->type           =type;
+    ((DCIN2_Ind_t *)DLSCH_DCI_NB_IoT)->directIndInf   =directIndInf;
+    ((DCIN2_Ind_t *)DLSCH_DCI_NB_IoT)->resInfoBits    =resInfoBits;
+
+
+    add_dci_NB_IoT(eNB->DCI_pdu,DLSCH_DCI_NB_IoT,rnti,sizeof(DCIN2_Ind_t),aggregation,sizeof_DCIN2_Ind_t,DCIFormatN2_Ind,npdcch_start_symbol);
+
+    // use this value to configure PHY both harq_processes and resource mapping.
+    break;
+
+    
+  case DCIFormatN2_Pag:  //MP: for the moment is not implemented
+
+    type               = DCI_Content->DCIN2_Pag.type;
+    ResAssign          = DCI_Content->DCIN2_Pag.ResAssign; 
+    mcs                = DCI_Content->DCIN2_Pag.mcs; 
+    RepNum             = DCI_Content->DCIN2_Pag.RepNum; 
+    DCIRep             = DCI_Content->DCIN2_Pag.DCIRep; 
+
+    /*Packed DCI here*/
+    ((DCIN2_Pag_t *)DLSCH_DCI_NB_IoT)->type      =type;
+    ((DCIN2_Pag_t *)DLSCH_DCI_NB_IoT)->ResAssign =ResAssign;
+    ((DCIN2_Pag_t *)DLSCH_DCI_NB_IoT)->mcs       =mcs;
+    ((DCIN2_Pag_t *)DLSCH_DCI_NB_IoT)->RepNum    =RepNum;
+    ((DCIN2_Pag_t *)DLSCH_DCI_NB_IoT)->DCIRep    =DCIRep;
+
+
+    add_dci_NB_IoT(eNB->DCI_pdu,DLSCH_DCI_NB_IoT,rnti,sizeof(DCIN2_Pag_t),aggregation,sizeof_DCIN2_Pag_t,DCIFormatN2_Pag,npdcch_start_symbol);
+
+    // use this value to configure PHY both harq_processes and resource mapping.
+    break;
+
+
+  default:
+    LOG_E(PHY,"Unknown DCI format\n");
+    return(-1);
+    break;
+  }
+
+  // compute DL power control parameters
+
+
+
+  return(0);
+}
+
+
+uint8_t subframe2harq_pid_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe)
+{
+  //MAC_xface_NB_IoT *mac_xface_NB_IoT; //test_xface
+  /*
+    #ifdef DEBUG_DCI
+    if (frame_parms->frame_type == TDD)
+    printf("dci_tools.c: subframe2_harq_pid, subframe %d for TDD configuration %d\n",subframe,frame_parms->tdd_config);
+    else
+    printf("dci_tools.c: subframe2_harq_pid, subframe %d for FDD \n",subframe);
+    #endif
+  */
+
+  uint8_t ret = 255;
+
+  if (frame_parms->frame_type == FDD_NB_IoT) {
+    ret = (((frame<<1)+subframe)&7);
+  } else {
+
+    switch (frame_parms->tdd_config) {
+
+    case 1:
+      if ((subframe==2) ||
+          (subframe==3) ||
+          (subframe==7) ||
+          (subframe==8))
+        switch (subframe) {
+        case 2:
+        case 3:
+          ret = (subframe-2);
+          break;
+
+        case 7:
+        case 8:
+          ret = (subframe-5);
+          break;
+
+        default:
+          LOG_E(PHY,"subframe2_harq_pid_NB_IoT, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+          ret = (255);
+          break;
+        }
+
+      break;
+
+    case 2:
+      if ((subframe!=2) && (subframe!=7)) {
+        LOG_E(PHY,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+        //mac_xface_NB_IoT->macphy_exit("subframe2_harq_pid_NB_IoT, Illegal subframe");
+        ret = (255);
+      }
+
+      ret = (subframe/7);
+      break;
+
+    case 3:
+      if ((subframe<2) || (subframe>4)) {
+        LOG_E(PHY,"subframe2_harq_pid_NB_IoT, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+        ret = (255);
+      }
+
+      ret = (subframe-2);
+      break;
+
+    case 4:
+      if ((subframe<2) || (subframe>3)) {
+        LOG_E(PHY,"subframe2_harq_pid_NB_IoT, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+        ret = (255);
+      }
+
+      ret = (subframe-2);
+      break;
+
+    case 5:
+      if (subframe!=2) {
+        LOG_E(PHY,"subframe2_harq_pid_NB_IoT, Illegal subframe %d for TDD mode %d\n",subframe,frame_parms->tdd_config);
+        ret = (255);
+      }
+
+      ret = (subframe-2);
+      break;
+
+    default:
+      LOG_E(PHY,"subframe2_harq_pid_NB_IoT, Unsupported TDD mode %d\n",frame_parms->tdd_config);
+      ret = (255);
+
+    }
+  }
+
+  if (ret == 255) {
+    LOG_E(PHY, "invalid harq_pid(%d) at SFN/SF = %d/%d\n", ret, frame, subframe);
+    //mac_xface_NB_IoT->macphy_exit("invalid harq_pid");
+  }
+  return ret;
+}
+
diff --git a/openair1/PHY/LTE_TRANSPORT/defs.h b/openair1/PHY/LTE_TRANSPORT/defs.h
index dced65fa2cbe84432a11a6bf5611ae36da28068c..53239b71b118c8d63ac151100ea64aaccc8bac2c 100644
--- a/openair1/PHY/LTE_TRANSPORT/defs.h
+++ b/openair1/PHY/LTE_TRANSPORT/defs.h
@@ -168,6 +168,7 @@ typedef struct {
   uint8_t codeword;
 } LTE_DL_eNB_HARQ_t;
 
+
 typedef struct {
   /// Indicator of first transmission
   uint8_t first_tx;
@@ -800,5 +801,9 @@ typedef struct {
 } DCI_ALLOC_t;
 
 
+
+
+//---------------------------------------------------------------------------------------
+
 /**@}*/
 #endif
diff --git a/openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..3574ba67405c271fefe0a43d01936fb49010efd6
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h
@@ -0,0 +1,787 @@
+/*******************************************************************************
+ 
+ *******************************************************************************/
+/*! \file PHY/LTE_TRANSPORT/defs_NB_IoT.h
+* \brief data structures for NPDSCH/NDLSCH/NPUSCH/NULSCH physical and transport channel descriptors (TX/RX) of NB-IoT
+* \author M. KANJ
+* \date 2017
+* \version 0.0
+* \company bcom
+* \email: matthieu.kanj@b-com.com
+* \note
+* \warning
+*/
+#ifndef __LTE_TRANSPORT_DEFS_NB_IOT__H__
+#define __LTE_TRANSPORT_DEFS_NB_IOT__H__
+////#include "PHY/defs.h"
+//#include "PHY/defs_nb_iot.h"
+#include "PHY/LTE_TRANSPORT/dci_NB_IoT.h"
+#include "PHY/impl_defs_lte_NB_IoT.h"
+#include "openair2/COMMON/platform_types.h"
+//#include "dci.h"
+#include "PHY/LTE_TRANSPORT/uci_NB_IoT.h"
+//#include "dci.h"
+//#include "uci.h"
+//#ifndef STANDALONE_COMPILE
+//#include "UTIL/LISTS/list.h"
+//#endif
+ 
+//#include "dci_nb_iot.h"
+
+//#define MOD_TABLE_QPSK_OFFSET 1
+//#define MOD_TABLE_16QAM_OFFSET 5
+//#define MOD_TABLE_64QAM_OFFSET 21
+//#define MOD_TABLE_PSS_OFFSET 85
+//
+//// structures below implement 36-211 and 36-212
+//
+//#define NSOFT 1827072
+#define LTE_NULL_NB_IoT 2
+//
+//// maximum of 3 segments before each coding block if data length exceeds 6144 bits.
+//
+#define MAX_NUM_DLSCH_SEGMENTS_NB_IoT 16
+//#define MAX_NUM_ULSCH_SEGMENTS MAX_NUM_DLSCH_SEGMENTS
+//#define MAX_DLSCH_PAYLOAD_BYTES (MAX_NUM_DLSCH_SEGMENTS*768)
+//#define MAX_ULSCH_PAYLOAD_BYTES (MAX_NUM_ULSCH_SEGMENTS*768)
+//
+//#define MAX_NUM_CHANNEL_BITS_NB_IOT (14*1200*6)  // 14 symbols, 1200 REs, 12 bits/RE
+//#define MAX_NUM_RE (14*1200)
+//
+//#if !defined(SI_RNTI)
+//#define SI_RNTI  (rnti_t)0xffff
+//#endif
+//#if !defined(M_RNTI)
+//#define M_RNTI   (rnti_t)0xfffd
+//#endif
+//#if !defined(P_RNTI)
+//#define P_RNTI   (rnti_t)0xfffe
+//#endif
+//#if !defined(CBA_RNTI)
+//#define CBA_RNTI (rnti_t)0xfff4
+//#endif
+//#if !defined(C_RNTI)
+//#define C_RNTI   (rnti_t)0x1234
+//#endif
+//
+//#define PMI_2A_11 0
+//#define PMI_2A_1m1 1
+//#define PMI_2A_1j 2
+//#define PMI_2A_1mj 3
+//
+//// for NB-IoT
+#define MAX_NUM_CHANNEL_BITS_NB_IoT 3360 			//14 symbols * 12 sub-carriers * 10 SF * 2bits/RE  // to check during real tests
+#define MAX_DL_SIZE_BITS_NB_IoT 680 				// in release 13 // in release 14 = 2048      // ??? **** not sure
+////#define MAX_NUM_CHANNEL_BITS_NB_IOT 3*680  			/// ??? ****not sure
+//
+//// to be created LTE_eNB_DLSCH_t --> is duplicated for each number of UE and then indexed in the table
+//
+//typedef struct {                              // LTE_DL_eNB_HARQ_t
+//  /// Status Flag indicating for this DLSCH (idle,active,disabled)
+//  SCH_status_t status;
+//  /// Transport block size
+//  uint32_t TBS;
+//  /// The payload + CRC size in bits, "B" from 36-212
+//  uint32_t B;        // keep this parameter
+//  /// Pointer to the payload
+//  uint8_t *b;   // keep this parameter
+//  /// Pointers to transport block segments
+//  //uint8_t *c[MAX_NUM_DLSCH_SEGMENTS];
+//  /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
+// // uint32_t RTC[MAX_NUM_DLSCH_SEGMENTS];
+//  /// Frame where current HARQ round was sent
+//  uint32_t frame;
+//  /// Subframe where current HARQ round was sent
+//  uint32_t subframe;
+//  /// Index of current HARQ round for this DLSCH
+//  uint8_t round;
+//  /// MCS format for this DLSCH
+//  uint8_t mcs;
+//  /// Redundancy-version of the current sub-frame
+//  uint8_t rvidx;
+//  /// MIMO mode for this DLSCH
+//  MIMO_mode_t mimo_mode;
+//  /// Current RB allocation
+//  uint32_t rb_alloc[4];
+//  /// distributed/localized flag
+//  vrb_t vrb_type;
+//  /// Current subband PMI allocation
+//  uint16_t pmi_alloc;
+//  /// Current subband RI allocation
+//  uint32_t ri_alloc;
+//  /// Current subband CQI1 allocation
+//  uint32_t cqi_alloc1;
+//  /// Current subband CQI2 allocation
+//  uint32_t cqi_alloc2;
+//  /// Current Number of RBs
+//  uint16_t nb_rb;
+//  /// downlink power offset field
+//  uint8_t dl_power_off;
+//  /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
+//  uint8_t e[MAX_NUM_CHANNEL_BITS_NB_IOT];
+//  /// data after scrambling
+//  uint8_t s_e[MAX_NUM_CHANNEL_BITS_NB_IOT];
+//  /// length of the table e
+//  uint16_t length_e                 // new parameter
+//  /// Tail-biting convolutional coding outputs
+//  uint8_t d[96+(3*(24+MAX_DL_SIZE_BITS_NB_IOT))];  // new parameter
+//  /// Sub-block interleaver outputs
+//  uint8_t w[3*3*(MAX_DL_SIZE_BITS_NB_IOT+24)];      // new parameter
+//  /// Number of MIMO layers (streams) (for definition see 36-212 V8.6 2009-03, p.17, TM3-4)
+//  uint8_t Nl;
+//  /// Number of layers for this PDSCH transmission (TM8-10)
+//  uint8_t Nlayers;
+//  /// First layer for this PSCH transmission
+//  uint8_t first_layer;
+//} NB_IoT_DL_eNB_HARQ_t;
+
+typedef enum {
+
+  SCH_IDLE_NB_IoT,
+  ACTIVE_NB_IoT,
+  CBA_ACTIVE_NB_IoT,
+  DISABLED_NB_IoT
+
+} SCH_status_NB_IoT_t;
+
+
+typedef struct {
+  /// NB-IoT
+  SCH_status_NB_IoT_t   status;
+  /// The scheduling the NPDCCH and the NPDSCH transmission TS 36.213 Table 16.4.1-1
+  uint8_t               scheduling_delay;
+  /// The number of the subframe to transmit the NPDSCH Table TS 36.213 Table 16.4.1.3-1  (Nsf) (NB. in this case is not the index Isf)
+  uint8_t               resource_assignment;
+  /// is the index that determined the repeat number of NPDSCH through table TS 36.213 Table 16.4.1.3-2 / for SIB1-NB Table 16.4.1.3-3
+  uint8_t               repetition_number;
+  /// Determined the ACK/NACK delay and the subcarrier allocation TS 36.213 Table 16.4.2
+  uint8_t               HARQ_ACK_resource;
+  /// Determined the repetition number value 0-3 (2 biut carried by the FAPI NPDCCH)
+  uint8_t               dci_subframe_repetitions;
+  /// modulation always QPSK Qm = 2 
+  uint8_t               modulation;
+  /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
+  uint8_t               e[MAX_NUM_CHANNEL_BITS_NB_IoT];
+  /// data after scrambling
+  uint8_t               s_e[MAX_NUM_CHANNEL_BITS_NB_IoT];
+  //length of the table e
+  uint16_t              length_e;                // new parameter
+  /// Tail-biting convolutional coding outputs
+  uint8_t               d[96+(3*(24+MAX_DL_SIZE_BITS_NB_IoT))];  // new parameter
+  /// Sub-block interleaver outputs
+  uint8_t               w[3*3*(MAX_DL_SIZE_BITS_NB_IoT+24)];      // new parameter
+
+  /// Status Flag indicating for this DLSCH (idle,active,disabled)
+  //SCH_status_t status;
+  /// Transport block size
+  uint32_t              TBS;
+  /// The payload + CRC size in bits, "B" from 36-212
+  uint32_t              B;
+  /// Pointer to the payload
+  uint8_t               *b;
+  ///pdu of the ndlsch message
+  uint8_t               *pdu;
+  /// Frame where current HARQ round was sent
+  uint32_t              frame;
+  /// Subframe where current HARQ round was sent
+  uint32_t              subframe;
+  /// Index of current HARQ round for this DLSCH
+  uint8_t               round;
+  /// MCS format for this NDLSCH , TS 36.213 Table 16.4.1.5
+  uint8_t               mcs;
+  // we don't have code block segmentation / crc attachment / concatenation in NB-IoT R13 36.212 6.4.2
+  // we don't have beamforming in NB-IoT
+  //this index will be used mainly for SI message buffer
+   uint8_t               pdu_buffer_index;
+
+} NB_IoT_DL_eNB_HARQ_t;
+
+
+typedef struct {                                        // LTE_eNB_DLSCH_t
+ /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
+ uint32_t               *txdataF[8];
+ /// Allocated RNTI (0 means DLSCH_t is not currently used)
+ uint16_t               rnti;
+ /// Active flag for baseband transmitter processing
+ uint8_t                active;
+ /// Indicator of TX activation per subframe.  Used during PUCCH detection for ACK/NAK.
+ uint8_t                subframe_tx[10];
+ /// First CCE of last PDSCH scheduling per subframe.  Again used during PUCCH detection for ACK/NAK.
+ uint8_t                nCCE[10];
+ /// Current HARQ process id
+ uint8_t                current_harq_pid;
+ /// Process ID's per subframe.  Used to associate received ACKs on PUSCH/PUCCH to DLSCH harq process ids
+ uint8_t                harq_ids[10];
+ /// Window size (in outgoing transport blocks) for fine-grain rate adaptation
+ uint8_t                ra_window_size;
+ /// First-round error threshold for fine-grain rate adaptation
+ uint8_t                error_threshold;
+ /// Pointers to 8 HARQ processes for the DLSCH
+ NB_IoT_DL_eNB_HARQ_t   harq_process;
+ /// circular list of free harq PIDs (the oldest come first)
+ /// (10 is arbitrary value, must be > to max number of DL HARQ processes in LTE)
+ int                    harq_pid_freelist[10];
+ /// the head position of the free list (if list is free then head=tail)
+ int                    head_freelist;
+ /// the tail position of the free list
+ int                    tail_freelist;
+ /// Number of soft channel bits
+ uint32_t               G;
+ /// Codebook index for this dlsch (0,1,2,3)
+ uint8_t                codebook_index;
+ /// Maximum number of HARQ processes (for definition see 36-212 V8.6 2009-03, p.17)
+ uint8_t                Mdlharq;
+ /// Maximum number of HARQ rounds
+ uint8_t                Mlimit;
+ /// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17)
+ uint8_t                Kmimo;
+ /// Nsoft parameter related to UE Category
+ uint32_t               Nsoft;
+ /// amplitude of PDSCH (compared to RS) in symbols without pilots
+ int16_t                sqrt_rho_a;
+ /// amplitude of PDSCH (compared to RS) in symbols containing pilots
+ int16_t                sqrt_rho_b;
+
+} NB_IoT_eNB_DLSCH_t;
+
+
+typedef struct {
+  /// HARQ process id
+  uint8_t   harq_id;
+  /// 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_NB_IoT_t;
+
+typedef struct {
+  /// UL RSSI per receive antenna
+  int32_t             UL_rssi[NB_ANTENNAS_RX];
+  /// PUCCH1a/b power (digital linear)
+  uint32_t            Po_PUCCH;
+  /// PUCCH1a/b power (dBm)
+  int32_t             Po_PUCCH_dBm;
+  /// PUCCH1 power (digital linear), conditioned on below threshold
+  uint32_t            Po_PUCCH1_below;
+  /// PUCCH1 power (digital linear), conditioned on above threshold
+  uint32_t            Po_PUCCH1_above;
+  /// Indicator that Po_PUCCH has been updated by PHY
+  int32_t             Po_PUCCH_update;
+  /// DL Wideband CQI index (2 TBs)
+  uint8_t             DL_cqi[2];
+  /// DL Subband CQI index (from HLC feedback)
+  uint8_t             DL_subband_cqi[2][13];
+  /// DL PMI Single Stream
+  uint16_t            DL_pmi_single;
+  /// DL PMI Dual Stream
+  uint16_t            DL_pmi_dual;
+  /// Current RI
+  uint8_t             rank;
+  /// CRNTI of UE
+  uint16_t            crnti; ///user id (rnti) of connected UEs
+  /// Initial timing offset estimate from PRACH for RAR
+  int32_t             UE_timing_offset;
+  /// Timing advance estimate from PUSCH for MAC timing advance signalling
+  int32_t             timing_advance_update;
+  /// Current mode of UE (NOT SYCHED, RAR, PUSCH)
+  UE_MODE_NB_IoT_t    mode;
+  /// Current sector where UE is attached
+  uint8_t             sector;
+
+  /// dlsch l2 errors
+  uint32_t            dlsch_l2_errors[8];
+  /// dlsch trials per harq and round
+  uint32_t            dlsch_trials[8][8];
+  /// dlsch ACK/NACK per hard_pid and round
+  uint32_t            dlsch_ACK[8][8];
+  uint32_t            dlsch_NAK[8][8];
+
+  /// ulsch l2 errors per harq_pid
+  uint32_t            ulsch_errors[8];
+  /// ulsch l2 consecutive errors per harq_pid
+  uint32_t            ulsch_consecutive_errors; //[8];
+  /// ulsch trials/errors/fer per harq and round
+  uint32_t            nulsch_decoding_attempts[8][8];
+  uint32_t            ulsch_round_errors[8][8];
+  uint32_t            ulsch_decoding_attempts_last[8][8];
+  uint32_t            ulsch_round_errors_last[8][8];
+  uint32_t            ulsch_round_fer[8][8];
+  uint32_t            sr_received;
+  uint32_t            sr_total;
+
+  /// dlsch sliding count and total errors in round 0 are used to compute the dlsch_mcs_offset
+  uint32_t            dlsch_sliding_cnt;
+  uint32_t            dlsch_NAK_round0;
+  int8_t              dlsch_mcs_offset;
+
+  /// Target mcs1 after rate-adaptation (used by MAC layer scheduler)
+  uint8_t             dlsch_mcs1;
+  /// Target mcs2 after rate-adaptation (used by MAC layer scheduler)
+  uint8_t             dlsch_mcs2;
+  /// Total bits received from MAC on PDSCH
+  int                 total_TBS_MAC;
+  /// Total bits acknowledged on PDSCH
+  int                 total_TBS;
+  /// Total bits acknowledged on PDSCH (last interval)
+  int                 total_TBS_last;
+  /// Bitrate on the PDSCH [bps]
+  unsigned int        dlsch_bitrate;
+  //  unsigned int total_transmitted_bits;
+
+} NB_IoT_eNB_UE_stats;
+
+typedef struct {
+  /// Indicator of first transmission
+  uint8_t     first_tx;
+  /// Last Ndi received for this process on DCI (used for C-RNTI only)
+  uint8_t     DCINdi;
+  /// DLSCH status flag indicating
+  //SCH_status_t status;
+  /// Transport block size
+  uint32_t    TBS;
+  /// The payload + CRC size in bits
+  uint32_t    B;
+  /// Pointer to the payload
+  uint8_t     *b;
+  /// Pointers to transport block segments
+  uint8_t     *c[MAX_NUM_DLSCH_SEGMENTS_NB_IoT];
+  /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
+  uint32_t    RTC[MAX_NUM_DLSCH_SEGMENTS_NB_IoT];
+  /// Index of current HARQ round for this DLSCH
+  uint8_t     round;
+  /// MCS format for this DLSCH
+  uint8_t     mcs;
+  /// Qm (modulation order) for this DLSCH
+  uint8_t     Qm;
+  /// Redundancy-version of the current sub-frame
+  uint8_t     rvidx;
+  /// MIMO mode for this DLSCH
+ // MIMO_mode_t mimo_mode;
+  /// soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
+  int16_t     w[MAX_NUM_DLSCH_SEGMENTS_NB_IoT][3*(6144+64)];
+  /// for abstraction soft bits for each received segment ("w"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
+  double      w_abs[MAX_NUM_DLSCH_SEGMENTS_NB_IoT][3*(6144+64)];
+  /// soft bits for each received segment ("d"-sequence)(for definition see 36-212 V8.6 2009-03, p.15)
+  int16_t     *d[MAX_NUM_DLSCH_SEGMENTS_NB_IoT];
+  /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9)
+  uint32_t    C;
+  /// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t    Cminus;
+  /// Number of "large" code segments (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t    Cplus;
+  /// Number of bits in "small" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t    Kminus;
+  /// Number of bits in "large" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t    Kplus;
+  /// Number of "Filler" bits (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t    F;
+  /// Number of MIMO layers (streams) (for definition see 36-212 V8.6 2009-03, p.17)
+  uint8_t     Nl;
+  /// current delta_pucch
+  int8_t      delta_PUCCH;
+  /// Number of soft channel bits
+  uint32_t    G;
+  /// Current Number of RBs
+  uint16_t    nb_rb;
+  /// Current subband PMI allocation
+  uint16_t    pmi_alloc;
+  /// Current RB allocation (even slots)
+  uint32_t    rb_alloc_even[4];
+  /// Current RB allocation (odd slots)
+  uint32_t    rb_alloc_odd[4];
+  /// distributed/localized flag
+  //vrb_t vrb_type;
+  /// downlink power offset field
+  uint8_t     dl_power_off;
+  /// trials per round statistics
+  uint32_t    trials[8];
+  /// error statistics per round
+  uint32_t    errors[8];
+  /// codeword this transport block is mapped to
+  uint8_t     codeword;
+
+} NB_IoT_DL_UE_HARQ_t;
+
+typedef struct {
+  /// RNTI
+  uint16_t              rnti;
+  /// Active flag for DLSCH demodulation
+  uint8_t               active;
+  /// Transmission mode
+  uint8_t               mode1_flag;
+  /// amplitude of PDSCH (compared to RS) in symbols without pilots
+  int16_t               sqrt_rho_a;
+  /// amplitude of PDSCH (compared to RS) in symbols containing pilots
+  int16_t               sqrt_rho_b;
+  /// Current HARQ process id threadRx Odd and threadRx Even
+  uint8_t               current_harq_pid;
+  /// Current subband antenna selection
+  uint32_t              antenna_alloc;
+  /// Current subband RI allocation
+  uint32_t              ri_alloc;
+  /// Current subband CQI1 allocation
+  uint32_t              cqi_alloc1;
+  /// Current subband CQI2 allocation
+  uint32_t              cqi_alloc2;
+  /// saved subband PMI allocation from last PUSCH/PUCCH report
+  uint16_t              pmi_alloc;
+  /// HARQ-ACKs
+  harq_status_NB_IoT_t  harq_ack;
+  /// Pointers to up to 8 HARQ processes
+  NB_IoT_DL_UE_HARQ_t   *harq_process;
+  /// Maximum number of HARQ processes(for definition see 36-212 V8.6 2009-03, p.17
+  uint8_t               Mdlharq;
+  /// MIMO transmission mode indicator for this sub-frame (for definition see 36-212 V8.6 2009-03, p.17)
+  uint8_t               Kmimo;
+  /// Nsoft parameter related to UE Category
+  uint32_t              Nsoft;
+  /// Maximum number of Turbo iterations
+  uint8_t               max_turbo_iterations;
+  /// number of iterations used in last turbo decoding
+  uint8_t               last_iteration_cnt;
+  /// accumulated tx power adjustment for PUCCH
+  int8_t                g_pucch;
+
+} NB_IoT_UE_DLSCH_t;
+
+//----------------------------------------------------------------------------------------------------------
+// NB-IoT
+//----------------------------------------------------------------------------------------------------
+
+//enum for distinguish the different type of ndlsch (may in the future will be not needed)
+typedef enum
+{
+
+  SIB1,
+  SI_Message,
+  RAR,
+  UE_Data
+
+}ndlsch_flag_t;
+
+
+
+typedef struct {
+  rnti_t          rnti;
+  //array containing the pdus of DCI
+  uint8_t         *a[2];
+  //Array containing encoded DCI data
+  uint8_t         *e[2];
+
+  //UE specific parameters
+  uint16_t        npdcch_NumRepetitions;
+
+  uint16_t        repetition_number;
+  //indicate the corresponding subframe within the repetition (set to 0 when a new NPDCCH pdu is received)
+  uint16_t        repetition_idx;
+
+  //  uint16_t npdcch_Offset_USS;
+  //  uint16_t npdcch_StartSF_USS;
+
+
+}NB_IoT_eNB_NPDCCH_t;
+
+
+typedef struct{
+
+  //Number of repetitions (R) for common search space (RAR and PAGING)
+  uint16_t    number_repetition_RA;
+  uint16_t    number_repetition_PAg;
+  //index of the current subframe among the repetition (set to 0 when we receive the new NPDCCH)
+  uint16_t    repetition_idx_RA;
+  uint16_t    repetition_idx_Pag;
+
+}NB_IoT_eNB_COMMON_NPDCCH_t;
+
+
+typedef struct {
+
+  /// Length of DCI in bits
+  uint8_t               dci_length;
+  /// Aggregation level only 1,2 in NB-IoT
+  uint8_t               L;
+  /// Position of first CCE of the dci
+  int                   firstCCE;
+  /// flag to indicate that this is a RA response
+  boolean_t      ra_flag;
+  /// rnti
+  rnti_t                rnti;
+  /// Format
+  DCI_format_NB_IoT_t   format;
+  /// DCI pdu
+  uint8_t               dci_pdu[8];
+
+} DCI_ALLOC_NB_IoT_t;
+
+
+typedef struct {
+  //delete the count for the DCI numbers,NUM_DCI_MAX should set to 2
+  uint32_t              num_npdcch_symbols;
+  ///indicates the starting OFDM symbol in the first slot of a subframe k for the NPDCCH transmission
+  /// see FAPI/NFAPI specs Table 4-45
+  uint8_t               npdcch_start_symbol;
+  uint8_t               Num_dci;
+  DCI_ALLOC_NB_IoT_t    dci_alloc[2] ;
+
+} DCI_PDU_NB_IoT;
+
+
+
+
+typedef struct {
+  /// TX buffers for UE-spec transmission (antenna ports 5 or 7..14, prior to precoding)
+  int32_t                 *txdataF[8];
+  /// dl channel estimates (estimated from ul channel estimates)
+  int32_t                 **calib_dl_ch_estimates;
+  /// Allocated RNTI (0 means DLSCH_t is not currently used)
+  uint16_t                rnti;
+  /// Active flag for baseband transmitter processing
+  uint8_t                 active;
+  /// Indicator of TX activation per subframe.  Used during PUCCH detection for ACK/NAK.
+  uint8_t                 subframe_tx[10];
+  /// First CCE of last PDSCH scheduling per subframe.  Again used during PUCCH detection for ACK/NAK.
+  uint8_t                 nCCE[10];
+  /*in NB-IoT there is only 1 HARQ process for each UE therefore no pid is required*/
+  /// The only HARQ process for the DLSCH
+  NB_IoT_DL_eNB_HARQ_t    *harq_process;
+  /// Number of soft channel bits
+  uint32_t                G;
+  /// Maximum number of HARQ rounds
+  uint8_t                 Mlimit;
+  /// Nsoft parameter related to UE Category
+  uint32_t                Nsoft;
+  /// amplitude of PDSCH (compared to RS) in symbols without pilots
+  int16_t                 sqrt_rho_a;
+  /// amplitude of PDSCH (compared to RS) in symbols containing pilots
+  int16_t                 sqrt_rho_b;
+  ///NB-IoT
+  /// may use in the npdsch_procedures
+  uint16_t                scrambling_sequence_intialization;
+  /// number of cell specific TX antenna ports assumed by the UE
+  uint8_t                 nrs_antenna_ports;
+
+  //This indicate the current subframe within the subframe interval between the NPDSCH transmission (Nsf*Nrep)
+  uint16_t                sf_index;
+  ///indicates the starting OFDM symbol in the first slot of a subframe k for the NPDSCH transmission
+  /// see FAPI/NFAPI specs Table 4-47
+  uint8_t                 npdsch_start_symbol;
+  /*SIB1-NB related parameters*/
+  ///flag for indicate if the current frame is the start of a new SIB1-NB repetition within the SIB1-NB period (0 = FALSE, 1 = TRUE)
+  uint8_t                 sib1_rep_start;
+  ///the number of the frame within the 16 continuous frame in which sib1-NB is transmitted (1-8 = 1st, 2nd ecc..) (0 = not foresees a transmission)
+  uint8_t                 relative_sib1_frame;
+  //Flag  used to discern among different NDLSCH structures (SIB1,SI,RA,UE-spec)
+  //(used inside the ndlsch procedure for distinguish the different type of data to manage also in term of repetitions and transmission over more subframes
+  ndlsch_flag_t           ndlsch_type;
+
+} NB_IoT_eNB_NDLSCH_t;
+
+typedef struct {
+  /// Length of CQI data under RI=1 assumption(bits)
+  uint8_t               Or1;
+  /// Rank information
+  uint8_t               o_RI[2];
+  /// Format of CQI data
+  UCI_format_NB_IoT_t   uci_format;
+  /// The value of DAI in DCI format 0
+  uint8_t               V_UL_DAI;
+  /// Pointer to CQI data
+  uint8_t               o[MAX_CQI_BYTES_NB_IoT];
+  /// CQI CRC status
+  uint8_t               cqi_crc_status;
+  /// PHICH active flag
+  uint8_t               phich_active;
+  /// PHICH ACK
+  uint8_t               phich_ACK;
+  /// Length of rank information (bits)
+  uint8_t               O_RI;
+  /// First Allocated RB
+  uint16_t              first_rb;
+  /// Current Number of RBs
+  uint16_t              nb_rb;
+  /// Determined the subcarrier allocation for the NPUSCH.(15, 3.75 KHz)
+  uint8_t               subcarrier_indication;
+  /// Determined the number of resource unit for the NPUSCH
+  uint8_t               resource_assignment;
+  /// Determined the scheduling delay for NPUSCH
+  uint8_t               scheduling_delay;
+  /// The number of the repetition number for NPUSCH Transport block
+  uint8_t               repetition_number;
+  /// Determined the repetition number value 0-3
+  uint8_t               dci_subframe_repetitions;
+  /// Flag indicating that this ULSCH has been allocated by a DCI (otherwise it is a retransmission based on PHICH NAK)
+  uint8_t               dci_alloc;
+  /// Flag indicating that this ULSCH has been allocated by a RAR (otherwise it is a retransmission based on PHICH NAK or DCI)
+  uint8_t               rar_alloc;
+  /// Status Flag indicating for this ULSCH (idle,active,disabled)
+  SCH_status_NB_IoT_t   status;
+  /// Subframe scheduling indicator (i.e. Transmission opportunity indicator)
+  uint8_t               subframe_scheduling_flag;
+  /// Transport block size
+  uint32_t              TBS;
+  /// The payload + CRC size in bits
+  uint32_t              B;
+  /// Number of soft channel bits
+  uint32_t              G;
+  /// Pointer to ACK
+  uint8_t               o_ACK[4];
+  /// Length of ACK information (bits)
+  uint8_t               O_ACK;
+  /// coded ACK bits
+  int16_t               q_ACK[MAX_ACK_PAYLOAD_NB_IoT];
+  /// Number of code segments (for definition see 36-212 V8.6 2009-03, p.9)
+  /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
+  int16_t               e[MAX_NUM_CHANNEL_BITS_NB_IoT] __attribute__((aligned(32)));
+  /// coded RI bits
+  int16_t               q_RI[MAX_RI_PAYLOAD_NB_IoT];
+  /// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27)
+  int8_t                q[MAX_CQI_PAYLOAD_NB_IoT];
+  /// number of coded CQI bits after interleaving
+  uint8_t               o_RCC;
+  /// coded and interleaved CQI bits
+  int8_t                o_w[(MAX_CQI_BITS_NB_IoT+8)*3];
+  /// coded CQI bits
+  int8_t                o_d[96+((MAX_CQI_BITS_NB_IoT+8)*3)];
+  ///
+  uint32_t              C;
+  /// Number of "small" code segments (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t              Cminus;
+  /// Number of "large" code segments (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t              Cplus;
+  /// Number of bits in "small" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t              Kminus;
+  /// Number of bits in "large" code segments (<6144) (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t              Kplus;
+  /// Number of "Filler" bits (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t              F;
+  /// Temporary h sequence to flag PUSCH_x/PUSCH_y symbols which are not scrambled
+  //uint8_t h[MAX_NUM_CHANNEL_BITS];
+  /// SRS active flag
+  uint8_t               srs_active;
+  /// Pointer to the payload
+  uint8_t               *b;
+  /// Current Number of Symbols
+  uint8_t               Nsymb_pusch;
+  /// Index of current HARQ round for this ULSCH
+  uint8_t               round;
+  /// MCS format for this ULSCH
+  uint8_t               mcs;
+  /// Redundancy-version of the current sub-frame (value 0->RV0,value 1 ->RV2)
+  uint8_t               rvidx;
+  /// Msc_initial, Initial number of subcarriers for ULSCH (36-212, v8.6 2009-03, p.26-27)
+  uint16_t              Msc_initial;
+  /// Nsymb_initial, Initial number of symbols for ULSCH (36-212, v8.6 2009-03, p.26-27)
+  uint8_t               Nsymb_initial;
+  /// n_DMRS  for cyclic shift of DMRS (36.213 Table 9.1.2-2)
+  uint8_t               n_DMRS;
+  /// n_DMRS  for cyclic shift of DMRS (36.213 Table 9.1.2-2) - previous scheduling
+  /// This is needed for PHICH generation which
+  /// is done after a new scheduling
+  uint8_t               previous_n_DMRS;
+  /// n_DMRS 2 for cyclic shift of DMRS (36.211 Table 5.5.1.1.-1)
+  uint8_t               n_DMRS2;
+  /// Flag to indicate that this ULSCH is for calibration information sent from UE (i.e. no MAC SDU to pass up)
+  //  int calibration_flag;
+  /// delta_TF for power control
+  int32_t               delta_TF;
+  ///////////////////////////////////////////// 4 parameter added by vincent ///////////////////////////////////////////////
+  // NB_IoT: Nsymb_UL and Nslot_UL are defined in 36.211, Section 10.1.2.3, Table 10.1.2.3-1
+  // The number of symbol in a resource unit is given by Nsymb_UL*Nslot_UL
+  uint8_t               Nsymb_UL; 
+  // Number of NPUSCH slots
+  uint8_t               Nslot_UL; 
+  // Number of subcarrier for NPUSH, can be 1, 3, 6, 12
+  uint8_t               N_sc_RU; 
+  // Index of UL NB_IoT resource block
+  uint32_t              UL_RB_ID_NB_IoT; 
+  // Subcarrier indication fields, obtained through DCI, Section 16.5.1.1 in 36.213
+  uint16_t              I_sc; 
+  //////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+
+} NB_IoT_UL_eNB_HARQ_t;
+
+
+typedef struct {
+  /// Pointers to the HARQ processes for the NULSCH
+  NB_IoT_UL_eNB_HARQ_t    *harq_process;
+  /// Maximum number of HARQ rounds
+  uint8_t                 Mlimit;
+  /// Value 0 = npush format 1 (data) value 1 = npusch format 2 (ACK/NAK)
+  uint8_t                 npusch_format;
+  /// Flag to indicate that eNB awaits UE Msg3
+  uint8_t                 Msg3_active;
+  /// Flag to indicate that eNB should decode UE Msg3
+  uint8_t                 Msg3_flag;
+  /// Subframe for Msg3
+  uint8_t                 Msg3_subframe;
+  /// Frame for Msg3
+  uint32_t                Msg3_frame;
+  /// RNTI attributed to this ULSCH
+  uint16_t                rnti;
+  /// cyclic shift for DM RS
+  uint8_t                 cyclicShift;
+  /// cooperation flag
+  uint8_t                 cooperation_flag;
+  /// (only in-band mode), indicate the resource block overlap the SRS configuration of LTE
+  uint8_t                 N_srs;
+  ///
+  uint8_t                 scrambling_re_intialization_batch_index;
+  /// number of cell specific TX antenna ports assumed by the UE
+  uint8_t                 nrs_antenna_ports;
+  ///
+  uint16_t                scrambling_sequence_intialization;
+  ///
+  uint16_t                sf_index;
+  /// Determined the ACK/NACK delay and the subcarrier allocation TS 36.213 Table 16.4.2
+  uint8_t                 HARQ_ACK_resource;
+
+  ///////////// kept from LTE ///////////////////////////////////////////////////
+
+  /// Maximum number of iterations used in eNB turbo decoder
+  uint8_t                 max_turbo_iterations;
+  /// ACK/NAK Bundling flag
+  uint8_t                 bundling;
+  /// beta_offset_cqi times 8
+  uint16_t                beta_offset_cqi_times8;
+  /// beta_offset_ri times 8
+  uint16_t                beta_offset_ri_times8;
+  /// beta_offset_harqack times 8
+  uint16_t                beta_offset_harqack_times8;
+  /// num active cba group
+  uint8_t                 num_active_cba_groups;
+  /// allocated CBA RNTI for this ulsch
+  uint16_t                cba_rnti[4];//NUM_MAX_CBA_GROUP];
+  #ifdef LOCALIZATION
+  /// epoch timestamp in millisecond
+  int32_t                 reference_timestamp_ms;
+  /// aggregate physical states every n millisecond
+  int32_t                 aggregation_period_ms;
+  /// a set of lists used for localization
+  struct                  list loc_rss_list[10], loc_rssi_list[10], loc_subcarrier_rss_list[10], loc_timing_advance_list[10], loc_timing_update_list[10];
+  struct                  list tot_loc_rss_list, tot_loc_rssi_list, tot_loc_subcarrier_rss_list, tot_loc_timing_advance_list, tot_loc_timing_update_list;
+  #endif
+
+} NB_IoT_eNB_NULSCH_t;
+
+#define NPBCH_A 34
+
+typedef struct {
+  //the 2 LSB of the hsfn (the MSB are indicated by the SIB1-NB)
+  uint16_t  h_sfn_lsb;
+
+  uint8_t   npbch_d[96+(3*(16+NPBCH_A))];
+  uint8_t   npbch_w[3*3*(16+NPBCH_A)];
+  uint8_t   npbch_e[1600];
+  ///pdu of the npbch message
+  uint8_t   *pdu;
+
+} NB_IoT_eNB_NPBCH_t;
+
+
+#endif
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
index 7d4bfc05930d520b793a115a88beccaf8d7d9a75..97e659d93b3516c8c99476e1adafce03c94b63f3 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding.c
@@ -234,6 +234,136 @@ LTE_eNB_DLSCH_t *new_eNB_dlsch(unsigned char Kmimo,unsigned char Mdlharq,uint32_
 
 
 }
+/*
+NB_IoT_eNB_NDLSCH_t *new_eNB_dlsch_NB_IoT(//unsigned char Kmimo,
+									//unsigned char Mdlharq,
+									uint32_t Nsoft,
+									//unsigned char N_RB_DL,
+									uint8_t abstraction_flag,
+									NB_IoT_DL_FRAME_PARMS* frame_parms)
+{
+
+  NB_IoT_eNB_NDLSCH_t *dlsch;
+  unsigned char exit_flag = 0,i,j,r,aa,layer;
+  int re;
+  unsigned char bw_scaling =1;
+
+//  switch (N_RB_DL) {
+//  case 6:
+//    bw_scaling =16;
+//    break;
+//
+//  case 25:
+//    bw_scaling =4;
+//    break;
+//
+//  case 50:
+//    bw_scaling =2;
+//    break;
+//
+//  default:
+//    bw_scaling =1;
+//    break;
+//  }
+
+  dlsch = (NB_IoT_eNB_NDLSCH_t *)malloc16(sizeof(NB_IoT_eNB_NDLSCH_t));
+
+  if (dlsch) {
+    bzero(dlsch,sizeof(NB_IoT_eNB_NDLSCH_t));
+
+    dlsch->Mlimit = 4;//max number of retransmission
+    dlsch->Nsoft = Nsoft;
+
+    for (layer=0; layer<4; layer++) {
+      dlsch->ue_spec_bf_weights[layer] = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+
+       for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+         dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
+         for (re=0;re<OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES; re++) {
+           dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
+         }
+       }
+     }
+
+     dlsch->calib_dl_ch_estimates = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+     for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
+       dlsch->calib_dl_ch_estimates[aa] = (int32_t *)malloc16(OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES*sizeof(int32_t));
+
+     }
+
+
+
+
+    //In NB-IoT we have only 1 HARQ process for each User-------------
+ 
+      dlsch->harq_process = (LTE_DL_eNB_HARQ_t *)malloc16(sizeof(LTE_DL_eNB_HARQ_t));
+      LOG_T(PHY, "[NB-IoT] Required mem size %d (bw scaling %d), dlsch->harq_process %p\n",
+            MAX_DLSCH_PAYLOAD_BYTES/bw_scaling,bw_scaling,dlsch->harq_process);
+
+      if (dlsch->harq_process) {
+        bzero(dlsch->harq_process,sizeof(LTE_DL_eNB_HARQ_t));
+        //    dlsch->harq_processes[i]->first_tx=1;
+        dlsch->harq_process->b = (unsigned char*)malloc16(MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);
+
+        if (dlsch->harq_process->b) {
+          bzero(dlsch->harq_process->b,MAX_DLSCH_PAYLOAD_BYTES/bw_scaling);
+        } else {
+          printf("Can't get b\n");
+          exit_flag=1;
+        }
+
+        if (abstraction_flag==0) {
+
+        //XXX MAX_NUM_DLSCH_SEGMENTS may should be changed for NB-IoT
+          for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
+            // account for filler in first segment and CRCs for multiple segment case
+            dlsch->harq_process->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+ 768);
+            dlsch->harq_process->d[r] = (uint8_t*)malloc16((96+12+3+(3*6144)));
+            if (dlsch->harq_process->c[r]) {
+              bzero(dlsch->harq_process->c[r],((r==0)?8:0) + 3+ 768);
+            } else {
+              printf("Can't get c\n");
+              exit_flag=2;
+            }
+            if (dlsch->harq_process->d[r]) {
+              bzero(dlsch->harq_process->d[r],(96+12+3+(3*6144)));
+            } else {
+              printf("Can't get d\n");
+              exit_flag=2;
+            }
+          }
+        }
+      } else {
+        printf("Can't get harq_p %d\n",i);
+        exit_flag=3;
+      }
+    //---------------------------------------------
+
+    if (exit_flag==0) {
+
+      dlsch->harq_process->round=0;
+
+      for (j=0; j<96; j++)
+    	  for (r=0; r<MAX_NUM_DLSCH_SEGMENTS/bw_scaling; r++) {
+    		  //      printf("dlsch->harq_processes[%d]->d[%d] %p\n",i,r,dlsch->harq_processes[i]->d[r]);
+    		  if (dlsch->harq_process->d[r])
+    			  dlsch->harq_process->d[r][j] = LTE_NULL;
+    	  }
+      return(dlsch);
+    }
+  }
+
+ // memory allocation failed for ndlsch
+
+  LOG_D(PHY,"new_eNB_ndlsch exit flag %d, size of  %ld\n",
+	exit_flag, sizeof(LTE_eNB_DLSCH_t));
+  free_eNB_dlsch(dlsch);
+  return(NULL);
+
+
+}
+
+*/
 
 void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
 {
@@ -265,7 +395,7 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch)
   }
 }
 
-
+/*
 int dlsch_encoding_2threads0(te_params *tep) {
 
   LTE_eNB_DLSCH_t *dlsch          = tep->dlsch;
@@ -556,6 +686,7 @@ int dlsch_encoding_2threads(PHY_VARS_eNB *eNB,
 
   return(0);
 }
+*/
 
 int dlsch_encoding(PHY_VARS_eNB *eNB,
 		   unsigned char *a,
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_coding_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/dlsch_coding_NB_IoT.c
index aa54ae11057c851e9046a5ba3058613d6cf94360..58a14bb7c3862bfc45025f84ee08b4f86735eb08 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_coding_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_coding_NB_IoT.c
@@ -11,43 +11,43 @@
 * \note
 * \warning
 */
+#include <string.h>
+//#include "PHY/defs.h"
+//#include "PHY/defs_NB_IoT.h"
+//#include "PHY/extern_NB_IoT.h"
+#include "PHY/CODING/defs_NB_IoT.h"
+//#include "PHY/CODING/extern.h"
+//#include "PHY/CODING/lte_interleaver_inline.h"
+#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+//#include "PHY/LTE_TRANSPORT/proto_NB_IoT.h"
+//#include "SCHED/defs_NB_IoT.h"
+//#include "defs_nb_iot.h"
+//#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "PHY/TOOLS/time_meas_NB_IoT.h" 
 
-#include "PHY/defs.h"
-#include "PHY/extern.h"
-#include "PHY/CODING/defs.h"
-#include "PHY/CODING/extern.h"
-#include "PHY/CODING/lte_interleaver_inline.h"
-#include "PHY/LTE_TRANSPORT/defs.h"
-#include "PHY/LTE_TRANSPORT/proto.h"
-#include "SCHED/defs.h"
-#include "defs.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
+unsigned char  ccodelte_table2_NB_IoT[128];
 
-#define is_not_pilot(pilots,first_pilot,re) (1)
-
-#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h" // newly added for NB_IoT
-
-void ccode_encode_npdsch_NB_IoT (int32_t numbits,
-								 uint8_t *inPtr,
-								 uint8_t *outPtr,
-								 uint32_t crc)
+void ccode_encode_npdsch_NB_IoT (int32_t   numbits,
+								 uint8_t   *inPtr,
+								 uint8_t   *outPtr,
+								 uint32_t  crc)
 {
-	uint32_t  state;
-	uint8_t  c, out, first_bit;
-	int8_t shiftbit=0;
-  /* The input bit is shifted in position 8 of the state.
+	uint32_t  	state;
+	uint8_t  	c, out, first_bit;
+	int8_t 		shiftbit = 0;
+    /* The input bit is shifted in position 8 of the state.
 	Shiftbit will take values between 1 and 8 */
-	state = 0;
-	first_bit = 2;
-	c = ((uint8_t*)&crc)[0];
+	state 		= 0;
+	first_bit   = 2;
+	c 			= ((uint8_t*)&crc)[0];
 	// Perform Tail-biting
 	// get bits from last byte of input (or crc)
 	for (shiftbit = 0 ; shiftbit <(8-first_bit) ; shiftbit++) {
 		if ((c&(1<<(7-first_bit-shiftbit))) != 0)
-		state |= (1<<shiftbit);
+			state |= (1<<shiftbit);
 	}
-	state = state & 0x3f;   // true initial state of Tail-biting CCode
-	state<<=1;              // because of loop structure in CCode
+	state = state & 0x3f;   			  // true initial state of Tail-biting CCode
+	state<<=1;            				  // because of loop structure in CCode
 		while (numbits > 0) {											// Tail-biting is applied to input bits , input 34 bits , output 102 bits
 			c = *inPtr++;
 			for (shiftbit = 7; (shiftbit>=0) && (numbits>0); shiftbit--,numbits--) {
@@ -55,7 +55,7 @@ void ccode_encode_npdsch_NB_IoT (int32_t numbits,
 				if ((c&(1<<shiftbit)) != 0) {
 					state |= 64;
 				}
-				out = ccodelte_table_NB_IoT[state];
+				out = ccodelte_table2_NB_IoT[state];
 
 				*outPtr++ = out  & 1;
 				*outPtr++ = (out>>1)&1;
@@ -65,46 +65,48 @@ void ccode_encode_npdsch_NB_IoT (int32_t numbits,
 }
 
 
-int dlsch_encoding_NB_IoT(unsigned char *a,
-						  NB_IoT_eNB_DLSCH_t *dlsch,
-						  uint8_t Nsf,					// number of subframes required for npdsch pdu transmission calculated from Isf (3GPP spec table)
-						  unsigned int G; 				// G (number of available RE) is implicitly multiplied by 2 (since only QPSK modulation)
-						  time_stats_t *rm_stats,
-						  time_stats_t *te_stats,
-						  time_stats_t *i_stats)
+int dlsch_encoding_NB_IoT(unsigned char      			*a,
+						  NB_IoT_eNB_DLSCH_t 			*dlsch,
+						  uint8_t 			 			Nsf,		// number of subframes required for npdsch pdu transmission calculated from Isf (3GPP spec table)
+						  unsigned int 		 			G, 		    // G (number of available RE) is implicitly multiplied by 2 (since only QPSK modulation)
+						  time_stats_t_NB_IoT 		 	*rm_stats,
+						  time_stats_t_NB_IoT 		 	*te_stats,
+						  time_stats_t_NB_IoT 		 	*i_stats)
 {
-	unsigned int crc=1;
+	unsigned int  crc = 1;
 	//unsigned char harq_pid = dlsch->current_harq_pid;  			// to check during implementation if harq_pid is required in the NB_IoT_eNB_DLSCH_t structure  in defs_NB_IoT.h
-	unsigned int A;
-	uint8_t RCC;
-	A = dlsch->harq_processe->TBS;  				// 680
-	dlsch->harq_processe->length_e = G*Nsf			// G*Nsf (number_of_subframes) = total number of bits to transmit 
+	unsigned int  A;
+	uint8_t 	  RCC;
+
+	A 							 = dlsch->harq_process.TBS;  				// 680
+	dlsch->harq_process.length_e = G*Nsf;									// G*Nsf (number_of_subframes) = total number of bits to transmit
+
 	int32_t numbits = A+24;
 	
-	if (dlsch->harq_processe->round == 0) { 	    // This is a new packet
+	if (dlsch->harq_process.round == 0) { 	    // This is a new packet
 
-		crc = crc24a(a,A)>>8;						// CRC calculation (24 bits CRC)
-												// CRC attachment to payload
-		a[A>>3] = ((uint8_t*)&crc)[2];
+		crc = crc24a_NB_IoT(a,A)>>8;						// CRC calculation (24 bits CRC)
+												    // CRC attachment to payload
+		a[A>>3]     = ((uint8_t*)&crc)[2];
 		a[1+(A>>3)] = ((uint8_t*)&crc)[1];
 		a[2+(A>>3)] = ((uint8_t*)&crc)[0];
 		
-		dlsch->harq_processe->B = numbits;			// The length of table b in bits
+		dlsch->harq_process.B = numbits;			// The length of table b in bits
 		
-		memcpy(dlsch->harq_processe->b,a,numbits/8); 
-		memset(dlsch->harq_processe->d,LTE_NULL,96);
+		memcpy(dlsch->harq_process.b,a,numbits/8); 
+		memset(dlsch->harq_process.d,LTE_NULL_NB_IoT,96);
 		
-		start_meas(te_stats);
-		ccode_encode_npdsch_NB_IoT(numbits, dlsch->harq_processe->b, dlsch->harq_processe->d+96, crc);  					//   step 1 Tail-biting convolutional coding
-		stop_meas(te_stats);
+		start_meas_NB_IoT(te_stats);
+		ccode_encode_npdsch_NB_IoT(numbits, dlsch->harq_process.b, dlsch->harq_process.d+96, crc);  					//   step 1 Tail-biting convolutional coding
+		stop_meas_NB_IoT(te_stats);
 		
-		start_meas(i_stats);
-		RCC = sub_block_interleaving_cc_NB_IoT(numbits,dlsch->harq_processe->d+96,dlsch->harq_processe->w);					//   step 2 interleaving
-		stop_meas(i_stats);
+		start_meas_NB_IoT(i_stats);
+		RCC = sub_block_interleaving_cc_NB_IoT(numbits,dlsch->harq_process.d+96,dlsch->harq_process.w);					//   step 2 interleaving
+		stop_meas_NB_IoT(i_stats);
 		
-		start_meas(rm_stats);
-		lte_rate_matching_cc_NB_IoT(RCC,dlsch->harq_processe->length_e,dlsch->harq_processe->w,dlsch->harq_processe->e);    // step 3 Rate Matching
-		stop_meas(rm_stats);		
+		start_meas_NB_IoT(rm_stats);
+		lte_rate_matching_cc_NB_IoT(RCC,dlsch->harq_process.length_e,dlsch->harq_process.w,dlsch->harq_process.e);    // step 3 Rate Matching
+		stop_meas_NB_IoT(rm_stats);		
     }
   return(0);
 }
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation_NB_IoT.c
index d8f6c5428a3eac21846509f64ad2878162ad6692..bef91bd60647848ac852ef44ee189bfec5876b5f 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_modulation_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_modulation_NB_IoT.c
@@ -11,35 +11,40 @@
 * \note
 * \warning
 */
+#include <math.h>
+//#include "PHY/defs.h"
+//#include "PHY/defs_NB_IoT.h"
+//#include "PHY/extern_NB_IoT.h"
+//#include "PHY/CODING/defs_nb_iot.h"
+//#include "PHY/CODING/extern.h"
+//#include "PHY/CODING/lte_interleaver_inline.h"
+#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+#include "PHY/impl_defs_lte_NB_IoT.h"
+#include "PHY/impl_defs_top_NB_IoT.h"
+//#include "defs.h"
+//#include "UTIL/LOG/vcd_signal_dumper.h"
 
-#include "PHY/defs.h"
-#include "PHY/extern.h"
-#include "PHY/CODING/defs.h"
-#include "PHY/CODING/extern.h"
-#include "PHY/CODING/lte_interleaver_inline.h"
-#include "PHY/LTE_TRANSPORT/defs.h"
-#include "defs.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-
-int allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
-                              int32_t **txdataF,
-                              uint32_t *jj,
-                              uint32_t symbol_offset,
-                              uint8_t *x0,
-                              uint8_t pilots,
-                              int16_t amp,
-						  	  unsigned short id_offset,
-                              uint32_t *re_allocated)  //  not used variable ??!!
+int allocate_REs_in_RB_NB_IoT(NB_IoT_DL_FRAME_PARMS 	*frame_parms,
+                              int32_t 					**txdataF,
+                              uint32_t 					*jj,
+                              uint32_t 					symbol_offset,
+                              uint8_t 					*x0,
+                              uint8_t 					pilots,
+                              int16_t 					amp,
+						  	  unsigned short 			id_offset,
+                              uint32_t 					*re_allocated)  //  not used variable ??!!
 {
-  MIMO_mode_t mimo_mode = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI;
-  uint32_t tti_offset,aa;
-  uint8_t re, diff_re;
-  int16_t gain_lin_QPSK;
-  uint8_t first_re,last_re;
-  int32_t tmp_sample1,tmp_sample2;
-  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
-  first_re=0;
-  last_re=12;
+  MIMO_mode_NB_IoT_t 	mimo_mode = (frame_parms->mode1_flag==1)? SISO_NB_IoT:ALAMOUTI_NB_IoT;
+
+  uint32_t  tti_offset,aa;
+  uint8_t   re;
+  int16_t   gain_lin_QPSK;
+  uint8_t   first_re,last_re;
+  int32_t   tmp_sample1,tmp_sample2;
+
+  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+  first_re      = 0;
+  last_re       = 12;
 
   for (re=first_re; re<last_re; re++) {      		// re varies between 0 and 12 sub-carriers
 
@@ -47,8 +52,8 @@ int allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
 	
 	if (pilots != 1 || re%3 != id_offset)  			// if re is not a pilot
 	{
-													//	diff_re = re%3 - id_offset;  
-      if (mimo_mode == SISO) {  								//SISO mapping
+													 
+      if (mimo_mode == SISO_NB_IoT) {  								//SISO mapping
 			*re_allocated = *re_allocated + 1;						// variable incremented but never used
 			
 			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
@@ -56,11 +61,11 @@ int allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
 			}
 			*jj = *jj + 1;
 			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
-				((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
+					((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
 			}
 			*jj = *jj + 1;	
 			
-      } else if (mimo_mode == ALAMOUTI) {
+      } else if (mimo_mode == ALAMOUTI_NB_IoT) {
 	  
 			*re_allocated = *re_allocated + 1;
 
@@ -77,10 +82,10 @@ int allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
 			*jj=*jj+1;
 
 			// normalization for 2 tx antennas
-			((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
-			((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
-			((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
-			((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
+			((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+			((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+			((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+			((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
 
 			// fill in the rest of the ALAMOUTI precoding
 			if ( pilots != 1 || (re+1)%3 != id_offset) {
@@ -107,53 +112,55 @@ int allocate_REs_in_RB_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
 }
 
 
-int dlsch_modulation_NB_IoT(int32_t **txdataF,
-							int16_t amp,
-							NB_IOT_DL_FRAME_PARMS *frame_parms,
-							uint8_t control_region_size,                          // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
-							NB_IoT_eNB_DLSCH_t *dlsch0,
-							int G,												// number of bits per subframe
-							unsigned npdsch_data_subframe,							// subframe index of the data table of npdsch channel (G*Nsf)  , values are between 0..Nsf  			
-							unsigned short NB_IoT_RB_ID)
+int dlsch_modulation_NB_IoT(int32_t 				**txdataF,
+							int16_t 				amp,
+							NB_IoT_DL_FRAME_PARMS 	*frame_parms,
+							uint8_t 				control_region_size,      // control region size for LTE , values between 0..3, (0 for stand-alone / 1, 2 or 3 for in-band)
+							NB_IoT_eNB_DLSCH_t 		*dlsch0,
+							int 					G,						  // number of bits per subframe
+							unsigned 				npdsch_data_subframe,     // subframe index of the data table of npdsch channel (G*Nsf)  , values are between 0..Nsf  			
+							unsigned short 			NB_IoT_RB_ID)
 {
     //uint8_t harq_pid = dlsch0->current_harq_pid;
     //NB_IoT_DL_eNB_HARQ_t *dlsch0_harq = dlsch0->harq_processes[harq_pid];
-    uint32_t jj=0;
-	uint32_t re_allocated,symbol_offset;
-    uint16_t l;
-    uint8_t id_offset,pilots=0; 
-	unsigned short bandwidth_even_odd;
-    unsigned short NB_IoT_start, RB_IoT_ID;
-    re_allocated=0;
-	id_offset=0;
+    uint32_t 		jj = 0;
+	uint32_t 		re_allocated,symbol_offset;
+    uint16_t 		l;
+    uint8_t 		id_offset,pilots = 0; 
+	unsigned short 	bandwidth_even_odd;
+    unsigned short 	NB_IoT_start, RB_IoT_ID;
+
+    re_allocated = 0;
+	id_offset    = 0;
 	// testing if the total number of RBs is even or odd 
-		bandwidth_even_odd = frame_parms->N_RB_DL % 2; 	 	// 0 even, 1 odd
-		RB_IoT_ID = NB_IoT_RB_ID;
+	bandwidth_even_odd  =  frame_parms->N_RB_DL % 2; 	 	// 0 even, 1 odd
+	RB_IoT_ID 			=  NB_IoT_RB_ID;
 	// step  5, 6, 7   									 	// modulation and mapping (slot 1, symbols 0..3)
 	for (l=control_region_size; l<14; l++) { 								 	// loop on OFDM symbols	
 		if((l>=4 && l<=8) || (l>=11 && l<=13))
 		{
-			pilots =1;
+			pilots = 1;
 		} else {
-			pilots=0;
+			pilots = 0;
 		}
 		id_offset = frame_parms->Nid_cell % 3;    			// Cell_ID_NB_IoT % 3
 		if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
 		{
-			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID % (int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		} else {
-			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID % (int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		}
 		symbol_offset = frame_parms->ofdm_symbol_size*l + NB_IoT_start;  						// symbol_offset = 512 * L + NB_IOT_RB start
+
 		allocate_REs_in_RB_NB_IoT(frame_parms,
-								txdataF,
-								&jj,
-								symbol_offset,
-								&dlsch0->harq_processes->s_e[G*npdsch_data_subframe],
-								pilots,
-								amp,
-								id_offset,
-								&re_allocated);
+								  txdataF,
+								  &jj,
+								  symbol_offset,
+								  &dlsch0->harq_process.s_e[G*npdsch_data_subframe],
+								  pilots,
+								  amp,
+								  id_offset,
+								  &re_allocated);
 	}
 	
  // VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_MODULATION, VCD_FUNCTION_OUT);
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling_NB_IoT.c
index edc2f9b88dfcad58224f1a5836d084812f49c31b..f925c13712876f591e89ed67934053b2f9e3268e 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_scrambling_NB_IoT.c
@@ -14,27 +14,30 @@
 
 //#define DEBUG_SCRAMBLING 1
 
-#include "PHY/defs.h"
-#include "PHY/CODING/extern.h"
-#include "PHY/CODING/lte_interleaver_inline.h"
-#include "defs.h"
-#include "extern.h"
-#include "PHY/extern.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-
-#include "defs_NB_IoT.h"
-
-void dlsch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
-							 NB_IoT_eNB_DLSCH_t *dlsch,
-							 int G,        							// total number of bits to transmit
-							 uint8_t Nf,   							// Nf is the frame number (0..9)
-							 uint8_t Ns)							// slot number (0..19)
+//#include "PHY/defs.h"
+//#include "PHY/defs_NB_IoT.h"
+//#include "PHY/CODING/extern.h"
+//#include "PHY/CODING/lte_interleaver_inline.h"
+//#include "defs.h"
+//#include "extern_NB_IoT.h"
+//#include "PHY/extern_NB_IoT.h"
+//#include "UTIL/LOG/vcd_signal_dumper.h"
+
+#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+#include "PHY/impl_defs_lte_NB_IoT.h"
+#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
+
+void dlsch_scrambling_NB_IoT(NB_IoT_DL_FRAME_PARMS  *frame_parms,
+							               NB_IoT_eNB_DLSCH_t     *dlsch,
+							               int                    G,        				// total number of bits to transmit
+							               uint8_t                Nf,   						// Nf is the frame number (0..9)
+							               uint8_t                Ns)							  // slot number (0..19)
 {
-  int i,j,k=0;
-  uint32_t x1, x2, s=0;
-  uint8_t *e=dlsch->harq_processes->e; 															//uint8_t *e=dlsch->harq_processes[dlsch->current_harq_pid]->e;
+  int         i,j,k=0;
+  uint32_t    x1,x2, s=0;
+  uint8_t     *e = dlsch->harq_process.e; 															//uint8_t *e=dlsch->harq_processes[dlsch->current_harq_pid]->e;
 
-  x2 = (dlsch->rnti<<14) + ((Nf%2)<<13) + ((Ns>>1)<<9) + frame_parms->Nid_cell;                    //this is c_init in 36.211 Sec 10.2.3.1
+  x2 = (dlsch->rnti<<14) + ((Nf%2)<<13) + ((Ns>>1)<<9) + frame_parms->Nid_cell;   //this is c_init in 36.211 Sec 10.2.3.1
   
   s = lte_gold_generic_NB_IoT(&x1, &x2, 1);
 
@@ -42,7 +45,7 @@ void dlsch_scrambling_NB_IoT(NB_IOT_DL_FRAME_PARMS *frame_parms,
 
     for (j=0; j<32; j++,k++) {
 
-      dlsch->s_e[k] = (e[k]&1) ^ ((s>>j)&1);
+      dlsch->harq_process.s_e[k] = (e[k]&1) ^ ((s>>j)&1);
 
     }
     s = lte_gold_generic_NB_IoT(&x1, &x2, 0);
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_tbs_full.h b/openair1/PHY/LTE_TRANSPORT/dlsch_tbs_full.h
index 10ac5f866b60c173ae48c22b79a42c371b47dae4..c2d1bed9ba94666d17305b635769adb28726526f 100644
--- a/openair1/PHY/LTE_TRANSPORT/dlsch_tbs_full.h
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_tbs_full.h
@@ -19,6 +19,10 @@
  *      contact@openairinterface.org
  */
 
+
+#ifndef __DLSCH_TBS_FULL_H__
+#define __DLSCH_TBS_FULL_H__
+
 #define TBStable_rowCnt 27
 
 /** \brief "Transport block size table"
@@ -54,3 +58,10 @@ unsigned int TBStable[TBStable_rowCnt][110] = {{16,32,56,88,120,152,176,208,224,
 };
 
 unsigned int TBStable1C[32] = {40, 56, 72, 120, 136, 144, 176, 208, 224, 256, 280, 296, 328, 336, 392, 488, 552, 600, 632, 696, 776, 840, 904, 1000, 1064, 1128, 1224, 1288, 1384, 1480, 1608, 1736};
+
+
+
+#endif
+
+
+
diff --git a/openair1/PHY/LTE_TRANSPORT/dlsch_tbs_full_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/dlsch_tbs_full_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..73a3e381fc1e643412f71eeb811d559cc6c06873
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/dlsch_tbs_full_NB_IoT.h
@@ -0,0 +1,56 @@
+
+/*
+ * 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.0  (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 __DLSCH_TBS_FULL_NB_IOT_H__
+#define __DLSCH_TBS_FULL_NB_IOT_H__
+
+/** \brief "Transport block size table"
+ *  (Table 7.1.7.2.1-1 in 3GPP TS 36.213 V8.6.0)
+ */
+
+
+// NB-IoT------------------
+
+// TBS table for the case not containing SIB1-NB, Table 16.4.1.5.1-1 in TS 36.213 v14.2 
+unsigned int TBStable_NB_IoT[14][8] ={ //[ITBS][ISF]
+  {16,32,56,88,120.152,208,256},
+  {24,56,88,144,176,208,256,344},
+  {32,72,144,176,208,256,328,424},
+  {40,104,176,208,256,328,440,568},
+  {56,120,208,256,328,408,552,680},
+  {72,144,244,328,424,504,680,872},
+  {88,176,256,392,504,600,808,1032},
+  {104,224,328,472,584,680,968,1224},
+  {120,256,392,536,680,808,1096,1352},
+  {136,296,456,616,776,936,1256,1544},
+  {144,328,504,680,872,1032,1384,1736},
+  {176,376,584,776,1000,1192,1608,2024},
+  {208,440,680,904,1128,1352,1800,2280},
+  {224,488,744,1128,1256,1544,2024,2536}
+};
+
+//TBS table for the case containing S1B1-NB, Table 16.4.1.5.2-1 in TS 36.213 v14.2 (Itbs = 12 ~ 15 is reserved field
+//mapping ITBS to SIB1-NB
+unsigned int TBStable_NB_IoT_SIB1[16] = {208,208,208,328,328,328,440,440,440,680,680,680};
+
+#endif
\ No newline at end of file
diff --git a/openair1/PHY/LTE_TRANSPORT/extern.h b/openair1/PHY/LTE_TRANSPORT/extern.h
index af4dc20df611b1bff4d66b9e575ccb70411c6f93..379b3a31f637d96e12d863912ef164057adc791c 100644
--- a/openair1/PHY/LTE_TRANSPORT/extern.h
+++ b/openair1/PHY/LTE_TRANSPORT/extern.h
@@ -20,6 +20,7 @@
  */
 
 extern unsigned int dlsch_tbs25[27][25],TBStable[27][110],TBStable1C[32];
+
 extern unsigned short lte_cqi_eff1024[16];
 extern char lte_cqi_snr_dB[15];
 extern short conjugate[8],conjugate2[8];
diff --git a/openair1/PHY/LTE_TRANSPORT/extern_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/extern_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..066b6d51eae86ea9dd54d1b996eabc0fe5e03bf7
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/extern_NB_IoT.h
@@ -0,0 +1,41 @@
+/*
+ * 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.0  (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_LTE_TRANSPORT_EXTERN_NB_IOT__H__
+#define __PHY_LTE_TRANSPORT_EXTERN_NB_IOT__H__
+
+
+extern unsigned int TBStable_NB_IoT[14][8];
+
+extern unsigned char cs_ri_normal_NB_IoT[4];
+extern unsigned char cs_ri_extended_NB_IoT[4];
+extern unsigned char cs_ack_normal_NB_IoT[4];
+extern unsigned char cs_ack_extended_NB_IoT[4];
+extern int8_t wACK_RX_NB_IoT[5][4];
+
+
+extern short conjugate[8],conjugate2[8];
+extern short *ul_ref_sigs_rx[30][4]; // NB-IoT: format 1 pilots
+// extern short *ul_ref_sigs_rx_format2[30][3]; // NB-IoT: format 2 pilots
+extern unsigned short dftsizes[33];
+
+#endif
\ No newline at end of file
diff --git a/openair1/PHY/LTE_TRANSPORT/group_hopping_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/group_hopping_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..3e34f7b1c8224b7f8b33900b70052d2f30ba7f7f
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/group_hopping_NB_IoT.c
@@ -0,0 +1,173 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/group_hopping.c
+* \brief Top-level routines for group hopping for DMRS from 36.211 R14, Section 10.1.4.1.3
+* \author Vincent Savaux
+* \date 2017
+* \version 0.1
+* \company b<>com
+* \email: vincent.savaux@b<>com.com
+* \note
+* \warning
+*/
+
+#include "PHY/defs_NB_IoT.h"
+#include <math.h> 
+
+//#define DEBUG_GROUPHOP 1
+
+void generate_grouphop_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms)
+{
+
+  uint8_t ns; 
+  uint8_t reset=1; 
+  uint32_t x1, x2, s=0;
+  uint16_t Nseq_RU[4] = {16,12,14,30}; // Table 10.1.4.1.3-1
+  // This is from Section 10.1.4.1.3
+  uint32_t fss_npusch_nn = frame_parms->Nid_cell + frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH;
+  uint32_t fss_npusch; 
+  int k; 
+
+  if (frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled){
+
+    for (k=0;k<4;k++){ // all four possible sucarrier configurations
+      fss_npusch = fss_npusch_nn % Nseq_RU[k]; 
+      x2 = (uint32_t) floor(frame_parms->Nid_cell/Nseq_RU[k]); 
+
+      // x2 = frame_parms->Nid_cell/30;
+    #ifdef DEBUG_GROUPHOP
+      printf("[PHY] GroupHop:");
+    #endif
+
+      for (ns=0; ns<20; ns++) { // slot number
+        // if (k==0){ // 1 subcarrier --> initialize at the beginning of the sequence 
+        if ((ns&3) == 0) {
+          s = lte_gold_generic_NB_IoT(&x1,&x2,reset);
+          reset = 0;
+        }
+        // }else{ // 3, 6, 12 subcarriers --> initialize at every even slot number
+        //   if ((ns%2) == 0) {
+        //     s = lte_gold_generic_NB_IoT(&x1,&x2,reset);
+        //     reset = 1;
+        //   }         
+        // }
+
+        frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[ns][k] = (((uint8_t*)&s)[ns&3]%Nseq_RU[k]+fss_npusch)%Nseq_RU[k]; 
+
+    #ifdef DEBUG_GROUPHOP
+        printf("%d.",frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[ns]);
+    #endif
+      }
+    }
+  }else{
+    for (ns=0; ns<20; ns++) {
+      for (k=0;k<4;k++){
+        frame_parms->npusch_config_common.ul_ReferenceSignalsNPUSCH.grouphop[ns][k] = frame_parms->Nid_cell % Nseq_RU[k]; 
+      }
+    }
+  }
+
+#ifdef DEBUG_GROUPHOP
+  printf("\n");
+#endif
+}
+
+// void generate_seqhop(LTE_DL_FRAME_PARMS *frame_parms)
+// {
+
+//   uint8_t ns,reset=1;
+//   uint32_t x1, x2, s=0;
+//   // This is from Section 5.5.1.3
+//   uint32_t fss_pusch = frame_parms->Nid_cell + frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH;
+
+//   x2 = (32*(frame_parms->Nid_cell/30) + fss_pusch)%30;
+
+//   s = lte_gold_generic(&x1,&x2,reset);
+// #ifdef DEBUG_GROUPHOP
+//   printf("[PHY] SeqHop:");
+// #endif
+
+//   for (ns=0; ns<20; ns++) {
+//     if ((frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled == 0) &&
+//         (frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled == 1))
+//       frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[ns] = (s>>(ns&0x1f))&1;
+//     else
+//       frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[ns] = 0;
+
+// #ifdef DEBUG_GROUPHOP
+//     printf("%d.",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.seqhop[ns]);
+// #endif
+//   }
+
+// #ifdef DEBUG_GROUPHOP
+//   printf("\n");
+// #endif
+// }
+
+// void generate_nPRS(LTE_DL_FRAME_PARMS *frame_parms)
+// {
+
+//   uint16_t n=0;
+//   uint8_t reset=1;
+//   uint32_t x1, x2, s=0;
+//   // This is from Section 5.5.1.3
+//   uint8_t Nsymb_UL = (frame_parms->Ncp_UL == NORMAL) ? 7 : 6;
+//   uint16_t next = 0;
+//   uint8_t ns=0;
+
+//   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
+//   printf("[PHY] nPRS:");
+// #endif
+
+//   for (n=0; n<(20*Nsymb_UL); n++) { //loop over total number of bytes to generate
+//     if ((n&3) == 0) {
+//       s = lte_gold_generic(&x1,&x2,reset);
+//       reset = 0;
+//       //      printf("n %d : s (%d,%d,%d,%d)\n",n,((uint8_t*)&s)[0],((uint8_t*)&s)[1],((uint8_t*)&s)[2],((uint8_t*)&s)[3]);
+//     }
+
+//     if (n == next) {
+//       frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[ns] = ((uint8_t*)&s)[next&3];
+// #ifdef DEBUG_GROUPHOP
+//       printf("%d.",frame_parms->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[ns]);
+// #endif
+//       ns++;
+//       next+=Nsymb_UL;
+//     }
+//   }
+
+// #ifdef DEBUG_GROUPHOP
+//   printf("\n");
+// #endif
+// }
+
+void init_ul_hopping_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms)
+{
+
+  generate_grouphop(frame_parms);
+  // generate_seqhop(frame_parms);
+  // generate_nPRS(frame_parms);
+}
diff --git a/openair1/PHY/LTE_TRANSPORT/initial_sync.c b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
index 19b01529464e58b775fda85f8fc4bcec2f782dbb..930a8280e212b1308af2f61c178dc53cfa16e930 100644
--- a/openair1/PHY/LTE_TRANSPORT/initial_sync.c
+++ b/openair1/PHY/LTE_TRANSPORT/initial_sync.c
@@ -36,6 +36,7 @@
 #include "SCHED/extern.h"
 #include "defs.h"
 #include "extern.h"
+#include "PHY/LTE_REFSIG/defs.h"
 
 
 #include "common_lib.h"
diff --git a/openair1/PHY/LTE_TRANSPORT/lte_Isc_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/lte_Isc_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..40c4f0aca832a35c50ff310b93cd4bdd2ef73914
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/lte_Isc_NB_IoT.c
@@ -0,0 +1,58 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/lte_mcs_NB_IoT.c
+* \brief Some support routines for subcarrier start into UL RB for ULSCH
+* \author V. Savaux
+* \date 2017
+* \version 0.1
+* \company b<>com
+* \email: 
+* \note
+* \warning
+*/
+
+//#include "PHY/defs.h"
+//#include "PHY/extern.h"
+#include "PHY/LTE_TRANSPORT/proto_NB_IoT.h"
+
+// Section 16.5.1.1 in 36.213
+uint16_t get_UL_sc_start_NB_IoT(uint16_t I_sc)
+{
+
+	if (0<=I_sc && I_sc<=11){
+		return I_sc; 
+	}
+	if (12<=I_sc && I_sc<=15){
+		return 3*(I_sc-12); 
+	}
+	if (16<=I_sc && I_sc<=17){
+		return 6*(I_sc-16); 
+	}
+	if (I_sc==18){
+		return 0; 
+	}
+	if (I_sc>18){
+		return -1; 
+	}
+
+}
+
diff --git a/openair1/PHY/LTE_TRANSPORT/lte_mcs_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/lte_mcs_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..162641baa00f6f9fab14752caa949b329cb7c648
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/lte_mcs_NB_IoT.c
@@ -0,0 +1,57 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/lte_mcs_NB_IoT.c
+* \brief Some support routines for MCS computations
+* \author V. Savaux
+* \date 2017
+* \version 0.1
+* \company b<>com
+* \email: 
+* \note
+* \warning
+*/
+
+//#include "PHY/defs.h"
+//#include "PHY/extern.h"
+#include "PHY/LTE_TRANSPORT/proto_NB_IoT.h"
+
+// 36213 Section 16.5.1.2, Table 
+unsigned char get_Qm_ul_NB_IoT(unsigned char I_MCS, uint8_t N_sc_RU)
+{
+
+	if (N_sc_RU)
+		return(2);
+	else
+		if (I_MCS<2)
+			return(1); 
+		else
+			return(2);
+		
+  // if (I_MCS < 11)
+  //   return(2);
+  // else if (I_MCS < 21)
+  //   return(4);
+  // else
+  //   return(6);
+
+}
+
diff --git a/openair1/PHY/LTE_TRANSPORT/npbch_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/npbch_NB_IoT.c
index a9cc1240d940a24a4e970172c92f8ac23fb9ebb1..59e0d22ccbaac07dfe2e0401c41e42ebfc40b3c4 100644
--- a/openair1/PHY/LTE_TRANSPORT/npbch_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/npbch_NB_IoT.c
@@ -12,43 +12,50 @@
 * \warning
 */
 
-#include "PHY/defs.h"
-#include "PHY/CODING/extern.h"
-#include "PHY/CODING/lte_interleaver_inline.h"
-#include "defs.h"
-#include "extern.h"
-#include "PHY/extern.h"
-#include "PHY/sse_intrin.h"
-
-#ifdef PHY_ABSTRACTION
-#include "SIMULATION/TOOLS/defs.h"
-#endif
-
-#ifdef OPENAIR2
-#include "PHY_INTERFACE/defs.h"
-#endif
+//#include "PHY/defs.h"
+//#include "PHY/defs_NB_IoT.h"
+//#include "PHY/CODING/extern.h"
+//#include "PHY/CODING/lte_interleaver_inline.h"
+//#include "extern_NB_IoT.h"
+//#include "PHY/extern_NB_IoT.h"
+//#include "PHY/sse_intrin.h"
+#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+#include "PHY/CODING/defs_NB_IoT.h"
+#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
+#include "PHY/impl_defs_lte_NB_IoT.h"
+#include "PHY/impl_defs_top_NB_IoT.h"
+
+//#ifdef PHY_ABSTRACTION
+//#include "SIMULATION/TOOLS/defs.h"
+//#endif
+
+//#ifdef OPENAIR2
+//#include "PHY_INTERFACE/defs.h"
+//#endif
 
 #define NPBCH_A 34                             // 34 for NB-IoT and 24 for LTE
 
-int allocate_npbch_REs_in_RB(NB_IOT_DL_FRAME_PARMS *frame_parms,
-                            int32_t **txdataF,
-                            uint32_t *jj,
-                            uint32_t symbol_offset,
-                            uint8_t *x0,
-                            uint8_t pilots,
-                            int16_t amp,
-			    unsigned short id_offset,
-                            uint32_t *re_allocated)  //  not used variable ??!!
+int allocate_npbch_REs_in_RB(NB_IoT_DL_FRAME_PARMS 	*frame_parms,
+                             int32_t 				**txdataF,
+                             uint32_t 				*jj,
+                             uint32_t 				symbol_offset,
+                             uint8_t 				*x0,
+                             uint8_t 				pilots,
+                             int16_t 				amp,
+			     unsigned short 		id_offset,
+                             uint32_t 				*re_allocated)  //  not used variable ??!!
 {
-  MIMO_mode_t mimo_mode = (frame_parms->mode1_flag==1)?SISO:ALAMOUTI;
-  uint32_t tti_offset,aa;
-  uint8_t re, diff_re;
-  int16_t gain_lin_QPSK;
-  uint8_t first_re,last_re;
-  int32_t tmp_sample1,tmp_sample2;
-  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15)>>15);
-  first_re=0;
-  last_re=12;
+  MIMO_mode_NB_IoT_t mimo_mode = (frame_parms->mode1_flag==1)?SISO_NB_IoT:ALAMOUTI_NB_IoT;
+
+  uint32_t  tti_offset,aa;
+  uint8_t   re;
+  int16_t   gain_lin_QPSK;
+  uint8_t   first_re,last_re;
+  int32_t   tmp_sample1,tmp_sample2;
+
+  gain_lin_QPSK = (int16_t)((amp*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+  first_re      = 0;
+  last_re       = 12;
 
   for (re=first_re; re<last_re; re++) {      		// re varies between 0 and 12 sub-carriers
 
@@ -57,7 +64,7 @@ int allocate_npbch_REs_in_RB(NB_IOT_DL_FRAME_PARMS *frame_parms,
 	if (pilots != 1 || re%3 != id_offset)  			// if re is not a pilot
 	{
 													//	diff_re = re%3 - id_offset;  
-      if (mimo_mode == SISO) {  								//SISO mapping
+      if (mimo_mode == SISO_NB_IoT) {  								//SISO mapping
         *re_allocated = *re_allocated + 1;						// variable incremented but never used
 			for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
 					((int16_t*)&txdataF[aa][tti_offset])[0] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //I //b_i
@@ -67,7 +74,7 @@ int allocate_npbch_REs_in_RB(NB_IOT_DL_FRAME_PARMS *frame_parms,
 				((int16_t*)&txdataF[aa][tti_offset])[1] += (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK; //Q //b_{i+1}
 			}
 			*jj = *jj + 1;	
-      } else if (mimo_mode == ALAMOUTI) {
+      } else if (mimo_mode == ALAMOUTI_NB_IoT) {
 			*re_allocated = *re_allocated + 1;
 
 			((int16_t*)&tmp_sample1)[0] = (x0[*jj]==1) ? (-gain_lin_QPSK) : gain_lin_QPSK;
@@ -83,10 +90,10 @@ int allocate_npbch_REs_in_RB(NB_IOT_DL_FRAME_PARMS *frame_parms,
 			*jj=*jj+1;
 
 			// normalization for 2 tx antennas
-			((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15)>>15);
-			((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15)>>15);
-			((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15)>>15);
-			((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15)>>15);
+			((int16_t*)&txdataF[0][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample1)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+			((int16_t*)&txdataF[0][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample1)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+			((int16_t*)&txdataF[1][tti_offset])[0] += (int16_t)((((int16_t*)&tmp_sample2)[0]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
+			((int16_t*)&txdataF[1][tti_offset])[1] += (int16_t)((((int16_t*)&tmp_sample2)[1]*ONE_OVER_SQRT2_Q15_NB_IoT)>>15);
 
 			// fill in the rest of the ALAMOUTI precoding
 			if ( pilots != 1 || (re+1)%3 != id_offset) {
@@ -113,44 +120,49 @@ int allocate_npbch_REs_in_RB(NB_IOT_DL_FRAME_PARMS *frame_parms,
 }
 /**********************************************************
 **********************************************************/
-int generate_npbch(NB_IoT_eNB_NPBCH *eNB_npbch,
-                  int32_t **txdataF,
-                  int amp,
-                  NB_IOT_DL_FRAME_PARMS *frame_parms,
-                  uint8_t *npbch_pdu,
-                  uint8_t frame_mod64
-				  unsigned short NB_IoT_RB_ID)
+int generate_npbch(NB_IoT_eNB_NPBCH_t 		*eNB_npbch,
+                   int32_t 					**txdataF,
+                   int 						amp,
+                   NB_IoT_DL_FRAME_PARMS 	*frame_parms,
+                   uint8_t 					*npbch_pdu,
+                   uint8_t 					frame_mod64,
+				   unsigned short 			NB_IoT_RB_ID)
 {
-  int i, l;
-  uint32_t npbch_D,npbch_E;
-  uint8_t npbch_a[5];   							// 34/8 =4.25 => 4 bytes and 2 bits
-  uint8_t RCC,id_offset=0;
-  unsigned short bandwidth_even_odd;
-  unsigned short NB_IoT_start, RB_IoT_ID;
-  uint32_t nsymb = 14;
-  uint32_t pilots;
-  uint32_t second_pilot = 4;
-  uint32_t jj=0;
-  uint32_t re_allocated=0;
-  uint32_t rb, symbol_offset;
-  uint16_t amask=0;
-  npbch_D  = 16+NPBCH_A;
+  int 			  i, l;
+  int 			  id_offset;
+  uint32_t 		  npbch_D,npbch_E;
+  uint8_t 		  npbch_a[5];   							// 34/8 =4.25 => 4 bytes and 2 bits
+  uint8_t 		  RCC;
+  unsigned short  bandwidth_even_odd;
+  unsigned short  NB_IoT_start, RB_IoT_ID;
+  uint32_t 		  pilots;
+  uint32_t 		  jj=0;
+  uint32_t 		  re_allocated=0;
+  uint32_t 		  symbol_offset;
+  uint16_t 		  amask=0;
+
+  npbch_D  = 16 + NPBCH_A;
   npbch_E  = 1600; 									
 									
 	if (frame_mod64==0) {
 		bzero(npbch_a,5);      									// initializing input data stream , filling with zeros
-		bzero(eNB_npbch->npbch_e,pbch_E);						// filling with "0" the table pbch_e[1600]
-		memset(eNB_npbch->npbch_d,LTE_NULL,96);					// filling with "2" the first 96 elements of table pbch_d[216]
+		bzero(eNB_npbch->npbch_e,npbch_E);						// filling with "0" the table pbch_e[1600]
+		memset(eNB_npbch->npbch_d,LTE_NULL_NB_IoT,96);					// filling with "2" the first 96 elements of table pbch_d[216]
 		
 		for (i=0; i<5; i++) 									// set input bits stream
 		{	
-			npbch_a[5-i-1] = npbch_pdu[i];        				// & 0xc0   //??/** in LTE 24 bits with 3 bytes, but in NB_IoT 34 bits will require 4 bytes+2 bits !! to check
+			if (i != 4)
+			{
+				npbch_a[5-i-1] = npbch_pdu[i];            		// ????????/*****?? in LTE 24 bits with 3 bytes, but in NB_IoT 34 bits will require 4 bytes+2 bits !! to verify
+			} else {
+				npbch_a[5-i-1]= npbch_pdu[i] & 0x03;
+			}
 		}
 	
 		if (frame_parms->mode1_flag == 1)						// setting CRC mask depending on the number of used eNB antennas 
 			amask = 0x0000;
 		else {
-			switch (frame_parms->nb_antennas_tx_eNB) {			// *****???? better replacing nb_antennas_tx_eNB by nb_antennas_tx_eNB_NB_IoT
+			switch (frame_parms->nb_antennas_tx) {			// *****???? better replacing nb_antennas_tx_eNB by nb_antennas_tx_eNB_NB_IoT
 				case 1:
 					amask = 0x0000;
 				break;
@@ -164,13 +176,13 @@ int generate_npbch(NB_IoT_eNB_NPBCH *eNB_npbch,
 		RCC = sub_block_interleaving_cc_NB_IoT(npbch_D,eNB_npbch->npbch_d+96,eNB_npbch->npbch_w);   	// step 2 Channel Coding
 		lte_rate_matching_cc_NB_IoT(RCC,npbch_E,eNB_npbch->npbch_w,eNB_npbch->npbch_e);				// step 3 Rate Matching
 		npbch_scrambling(frame_parms,															// step 4 Scrambling
-						eNB_npbch->npbch_e,
-						npbch_E);
+						 eNB_npbch->npbch_e,
+						 npbch_E);
 
 	}
 	// testing if the total number of RBs is even or odd 
-		bandwidth_even_odd = frame_parms->N_RB_DL % 2; 	 	// 0 even, 1 odd
-		RB_IoT_ID = NB_IoT_RB_ID;
+	bandwidth_even_odd = frame_parms->N_RB_DL % 2; 	 	// 0 even, 1 odd
+	RB_IoT_ID = NB_IoT_RB_ID;
 	// step  5, 6, 7   									 	// modulation and mapping (slot 1, symbols 0..3)
 	for (l=3; l<14; l++) { 								 	// loop on OFDM symbols
 			
@@ -185,22 +197,22 @@ int generate_npbch(NB_IoT_eNB_NPBCH *eNB_npbch,
 		
 		if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
 		{
-			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		} else {
-			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		}
 		
 		symbol_offset = frame_parms->ofdm_symbol_size*l + NB_IoT_start;  						// symbol_offset = 512 * L + NB_IOT_RB start
 		
 		allocate_npbch_REs_in_RB(frame_parms,
-								txdataF,
-								&jj,
-								symbol_offset,
-								&eNB_npbch->npbch_e[(frame_mod64/8)*(npbch_E>>3)],
-								pilots,
-								amp,
-								id_offset,
-								&re_allocated);
+								 txdataF,
+								 &jj,
+								 symbol_offset,
+								 &eNB_npbch->npbch_e[(frame_mod64/8)*(npbch_E>>3)],
+								 pilots,
+								 amp,
+								 id_offset,
+								 &re_allocated);
 			
 	
 	}
@@ -208,18 +220,21 @@ return(0);
 }
 /**********************************************************
 **********************************************************/
-void npbch_scrambling(NB_IOT_DL_FRAME_PARMS *frame_parms,
-                     uint8_t *npbch_e,
-                     uint32_t length)  // 1600
+void npbch_scrambling(NB_IoT_DL_FRAME_PARMS 	*frame_parms,
+                      uint8_t 					*npbch_e,
+                      uint32_t 					length)  // 1600
 {
-  int i;
-  uint8_t reset;
-  uint32_t x1, x2, s=0;
+  int 		i;
+  uint8_t 	reset;
+  uint32_t 	x1, x2, s=0;
+
   reset = 1;
-  x2 = frame_parms->Nid_cell;
+  x2 	= frame_parms->Nid_cell;
+
   for (i=0; i<length; i++) {
     if ((i&0x1f)==0) {
-      s = lte_gold_generic_NB_IoT(&x1, &x2, reset);
+
+      s 	= lte_gold_generic_NB_IoT(&x1, &x2, reset);
       reset = 0;
     }
     npbch_e[i] = (npbch_e[i]&1) ^ ((s>>(i&0x1f))&1);
diff --git a/openair1/PHY/LTE_TRANSPORT/nprach_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/nprach_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..5ee0b62ef03ddd5009f7d12d831dcf6a3dd193df
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/nprach_NB_IoT.c
@@ -0,0 +1,406 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/nprach_eNb_NB_IoT.c
+ * function for NPRACH signal detection and Timing Advance estimation
+ * \author V. Savaux
+ * \date 2017
+ * \version 0.1
+ * \company b<>com
+ * \email: vincent.savaux@b-com.com
+ * \note
+ * \warning
+ */
+
+//#include "PHY/sse_intrin.h"
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/TOOLS/defs.h" // to take into account the dft functions
+//#include "PHY/extern.h"
+//#include "prach.h"
+//#include "PHY/LTE_TRANSPORT/if4_tools.h"
+//#include "SCHED/defs.h"
+//#include "SCHED/extern.h"
+//#include "UTIL/LOG/vcd_signal_dumper.h"
+
+uint8_t NPRACH_detection_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, 
+								int16_t *Rx_sub_sampled_buffer, 
+								uint16_t sub_sampling_rate, 
+								uint32_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES){
+
+	uint32_t P_noise ; // needs to be defined or calculated
+	uint16_t FFT_size; 
+	uint16_t delta_t; // size, in samples, between 2 successive FFTs
+	uint16_t Nb_packets,n_subcarriers; 
+	uint16_t N_sample_per_sc; // number of samples per subcarrier
+	int16_t **mat_from_buffer,**mat_to_detector; 
+	uint32_t **mat_energy;  
+	uint64_t energy_per_subcarrier;  
+	uint32_t threshold_gamma; // threshold for signal detection
+	int k,n,m; 
+	uint8_t is_NPRACH_present = 0; 
+
+	switch (sub_sampling_rate){
+		case 16: // fs = 1.92 MHz
+			FFT_size = 16384; 
+			//dft_size = dft16384; 
+			delta_t = 80; 
+			N_sample_per_sc = 256; 
+		break; 
+		case 32: // fs = 960 kHz 
+			FFT_size = 8192; 
+			//dft_size = dft8192; 
+			delta_t = 40; 
+			N_sample_per_sc = 128;  
+		break; 
+		case 64: // fs = 480 kHz 
+			FFT_size = 4096; 
+			//dft_size = dft4096; 
+			delta_t = 20; 
+			N_sample_per_sc = 64; 
+		break;
+		case 128: // fs = 240 kHz 
+			FFT_size = 2048; 
+			//dft_size = dft2048; 
+			delta_t = 10; 
+			N_sample_per_sc = 32; 
+		break; 
+	}
+
+	Nb_packets = (uint16_t)(FRAME_LENGTH_COMPLEX_SUB_SAMPLES-FFT_size)/delta_t + 1; // Number of sections of FFT_size complex samples
+	n_subcarriers = FFT_size/N_sample_per_sc; // number of subcarriers on which the energy is calculated
+
+	// Create matrices where lines correspond to one sample, columns are fft of inputs
+	mat_to_detector = (int16_t **)malloc(Nb_packets*sizeof(int16_t *)); 
+	mat_from_buffer = (int16_t **)malloc(Nb_packets*sizeof(int16_t *)); 
+	mat_energy = (uint32_t **)malloc(Nb_packets*sizeof(uint32_t *)); 
+	 
+	for (k=0;k<Nb_packets;k++){
+		mat_to_detector[k] = (int16_t *)malloc(2*FFT_size*sizeof(int16_t)); 
+		mat_from_buffer[k] = (int16_t *)malloc(2*FFT_size*sizeof(int16_t)); 
+		mat_energy[k] = (uint32_t *)malloc(n_subcarriers*sizeof(uint32_t)); 
+	}
+	for (k=0;k<Nb_packets;k++){
+		for (n=0;n<FFT_size;n++){
+			mat_from_buffer[k][2*n] = Rx_sub_sampled_buffer[k*delta_t+2*n]; // Real part
+			mat_from_buffer[k][2*n+1] = Rx_sub_sampled_buffer[k*delta_t+2*n+1]; // Imag part
+		}
+		// dft_size(int16_t mat_from_buffer[k],int16_t mat_to_detector[k],int scale=1); 	
+		switch (sub_sampling_rate){
+			case 16: // fs = 1.92 MHz
+				printf("dft16384 not yet implemented\n");
+				//dft16384(int16_t mat_from_buffer[k],int16_t mat_to_detector[k],int scale=1); 
+			break; 
+			case 32: // fs = 960 kHz 
+				dft8192( mat_from_buffer[k], mat_to_detector[k],1);   
+			break; 
+			case 64: // fs = 480 kHz 
+				dft4096( mat_from_buffer[k], mat_to_detector[k],1);  
+			break;
+			case 128: // fs = 240 kHz 
+				dft2048( mat_from_buffer[k], mat_to_detector[k],1);
+			break; 
+		}
+	}
+
+	// Calculate the energy of the samples of mat_to_detector 
+	// and concatenate by N_sample_per_sc samples 
+
+	for (k=0;k<Nb_packets;k++){
+		for (n=0;n<n_subcarriers;n++){
+			energy_per_subcarrier = 0; 
+			for (m=0;m<N_sample_per_sc;m++){
+				energy_per_subcarrier += (uint64_t)mat_to_detector[k][2*n*N_sample_per_sc+2*m]*mat_to_detector[k][2*n*N_sample_per_sc+2*m] 
+										+ (uint64_t)mat_to_detector[k][2*n*N_sample_per_sc+2*m+1]*mat_to_detector[k][2*n*N_sample_per_sc+2*m+1];
+			}	
+			mat_energy[k][n] = energy_per_subcarrier/N_sample_per_sc; 
+
+			if (energy_per_subcarrier >= threshold_gamma){
+				is_NPRACH_present = 1; 
+			}
+		}		
+	} 
+
+	for (k=0;k<Nb_packets;k++){
+		free(mat_to_detector[k]); 
+		free(mat_from_buffer[k]); 
+		free(mat_energy[k]);
+	}
+	free(mat_to_detector); 
+	free(mat_from_buffer); 
+	free(mat_energy); 
+
+	return is_NPRACH_present; 
+
+}
+
+uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, 
+							  int16_t *Rx_sub_sampled_buffer, 
+							  uint16_t sub_sampling_rate, 
+							  uint16_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES, 
+							  uint32_t estimated_TA_coarse, 
+							  char coarse){
+
+	uint16_t length_seq_NPRACH,length_CP,length_symbol; // in number of samples, per NPRACH preamble: 4 sequences ; length of CP in number of samples 
+	uint16_t length_CP_0 = eNB->frame_parms.nprach_config_common.nprach_CP_Length; //NB-IoT: 0: short, 1: long 
+	uint32_t fs; //NB-IoT: sampling frequency of Rx_buffer, must be defined somewhere
+	uint32_t fs_sub_sampled; 
+	uint16_t length_correl_window,base_length; 
+	int64_t *vec_correlation; 
+	double max_correlation = 0; 
+	int16_t **matrix_received_signal_re, **matrix_received_signal_im; 
+	uint16_t offset_estimation, offset_start; // offset due to first coarse estimation
+	// double *** mat_to_phase_estimation_re, *** mat_to_phase_estimation_im; 
+	double average_mat_to_phase_re, average_mat_to_phase_im; 
+	double estimated_phase, estimated_CFO; 
+	// int16_t *vec_CFO_compensation_re, *vec_CFO_compensation_im; 
+	// int16_t *vec_received_signal_re, *vec_received_signal_im; 
+	int32_t *signal_CFO_compensed_re, *signal_CFO_compensed_im; 
+	int32_t **sub_sequence_reference_re, **sub_sequence_reference_im; 
+	int32_t *sequence_reference_re, *sequence_reference_im; 
+	uint32_t TA_sample_estimated = 0; 
+	int n,k,m,o; 
+
+	length_seq_NPRACH = (length_CP_0+5*8192)/sub_sampling_rate; 
+	length_CP = length_CP_0/sub_sampling_rate; 
+
+	length_symbol = 8192/sub_sampling_rate;  
+
+	if (coarse){ // coarse = 1: first estimation 
+
+		offset_start = 0; 
+		length_correl_window = 20512/sub_sampling_rate; // corresponds to the max TA, i.e. 667.66 micro s //FRAME_LENGTH_COMPLEX_SUB_SAMPLES - 4*length_seq_NPRACH+1; 
+
+	}else{
+
+		offset_estimation = 8 * estimated_TA_coarse; 
+		base_length = 32; 
+		// we arbitrarily define the length of correl window as base_length samples. 
+		// Check if offset_estimation is close to zero or 1282 (max lentgh of delays) 
+
+		if (offset_estimation-base_length/2 <0){
+			offset_start = 0; 
+			length_correl_window = offset_estimation + base_length/2; 
+		}
+		if (offset_estimation+base_length/2 >1281){
+			offset_start = offset_estimation-base_length/2; 
+			length_correl_window = base_length;// 512 - (1282-offset_estimation); 
+		}
+		if ((offset_estimation-base_length/2 >=0) && (offset_estimation+base_length/2 <=1281)){
+			offset_start = offset_estimation-base_length/2; 
+			length_correl_window = base_length; 
+		}
+		
+	}
+
+	fs_sub_sampled = (uint32_t)fs/sub_sampling_rate; 
+
+	// Method: MMSE (sub-optimal) CFO estimation -> CFO compensation -> ML (sub-optimal) TA estimation /============================================================/
+
+		matrix_received_signal_re = (int16_t **)malloc(4*sizeof(int16_t *)); 
+		matrix_received_signal_im = (int16_t **)malloc(4*sizeof(int16_t *)); 
+		for (k=0;k<4;k++){ // # sequence
+			matrix_received_signal_re[k] = (int16_t *)malloc((length_seq_NPRACH-length_CP)*sizeof(int16_t)); // avoid CP in this process
+			matrix_received_signal_im[k] = (int16_t *)malloc((length_seq_NPRACH-length_CP)*sizeof(int16_t)); // avoid CP in this process
+		}
+		signal_CFO_compensed_re = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); 
+		signal_CFO_compensed_im = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); 
+		sub_sequence_reference_re = (int32_t **)malloc(4*sizeof(int32_t *));  
+		sub_sequence_reference_im = (int32_t **)malloc(4*sizeof(int32_t *)); 
+		for (k=0;k<4;k++){
+			sub_sequence_reference_re[k] = (int32_t *)calloc(length_symbol,sizeof(int32_t)); 
+			sub_sequence_reference_im[k] = (int32_t *)calloc(length_symbol,sizeof(int32_t)); 
+		} 
+		sequence_reference_re = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); 
+		sequence_reference_im = (int32_t *)malloc(4*length_seq_NPRACH*sizeof(int32_t)); 		
+		vec_correlation = (int64_t *)malloc(length_correl_window*sizeof(int64_t));  
+
+	for (n=0;n<length_correl_window;n++){ // loops over samples %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
+
+		// MMSE (sub-optimal) CFO estimation /============================================================/ 
+
+		// for (k=0;k<4;k++){ // # sequence
+		// 	for (m=0;m<(length_seq_NPRACH-length_CP);m++){
+		// 		matrix_received_signal_re[k][m] = Rx_sub_sampled_buffer[2*(n+k*length_seq_NPRACH+length_CP+m)]; // avoid CP for CFO estimation
+		// 		matrix_received_signal_im[k][m] = Rx_sub_sampled_buffer[2*(n+k*length_seq_NPRACH+length_CP+m)+1]; 
+		// 	} 
+		// } 
+		average_mat_to_phase_re = 0; 
+		average_mat_to_phase_im = 0; 
+		for (k=0;k<4;k++){ // # sequence
+			for (o=0;o<4;o++){ // # symbol in sequence
+				for (m=0;m<length_symbol;m++){
+					// average_mat_to_phase_re = average_mat_to_phase_re 
+					// 						- (double)matrix_received_signal_re[k][o*length_symbol+m] * matrix_received_signal_re[k][(o+1)*length_symbol+m]
+					// 						- (double)matrix_received_signal_im[k][o*length_symbol+m] * matrix_received_signal_im[k][(o+1)*length_symbol+m]; 
+					// average_mat_to_phase_im = average_mat_to_phase_im
+					// 						-	(double)matrix_received_signal_im[k][o*length_symbol+m]	* matrix_received_signal_re[k][(o+1)*length_symbol+m] 
+					// 						+ (double)matrix_received_signal_re[k][o*length_symbol+m] * matrix_received_signal_im[k][(o+1)*length_symbol+m]; 
+
+					average_mat_to_phase_re = average_mat_to_phase_re 
+												- (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)]
+												* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)]
+												- (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)+1]
+												* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)+1];
+												// - (double)matrix_received_signal_re[k][o*length_symbol+m] * matrix_received_signal_re[k][(o+1)*length_symbol+m]
+												// - (double)matrix_received_signal_im[k][o*length_symbol+m] * matrix_received_signal_im[k][(o+1)*length_symbol+m]; 
+					average_mat_to_phase_im = average_mat_to_phase_im
+												- (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)+1]
+												* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)]
+												+ (double)Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+o*length_symbol+m)]
+												* Rx_sub_sampled_buffer[2*(n+offset_start+k*length_seq_NPRACH+length_CP+(o+1)*length_symbol+m)+1];
+				}
+			} 
+		} 
+
+		average_mat_to_phase_re = average_mat_to_phase_re/(16*length_symbol); 
+		average_mat_to_phase_im = average_mat_to_phase_im/(16*length_symbol); 
+		estimated_phase = atan2(average_mat_to_phase_im,average_mat_to_phase_re); 
+		estimated_CFO = ((double)fs*estimated_phase)/(8192*2*M_PI); 
+
+		// CFO compensation /============================================================/ 
+
+		for (k=0;k<4*length_seq_NPRACH;k++){
+			signal_CFO_compensed_re[k] = Rx_sub_sampled_buffer[2*(n+k)] * (int16_t)((double)cos(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767) 
+										- Rx_sub_sampled_buffer[2*(n+k)+1] * (int16_t)((double)sin(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767); 
+			signal_CFO_compensed_im[k] = Rx_sub_sampled_buffer[2*(n+k)] * (int16_t)((double)sin(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767) 
+										+ Rx_sub_sampled_buffer[2*(n+k)+1] * (int16_t)((double)cos(2*M_PI*estimated_CFO*k/fs_sub_sampled)*32767); 
+		} 
+
+		// sub-optimal ML TA estimation /============================================================/ 
+ 
+		for (k=0;k<4;k++){ // loop over the 4 sequence of a preamble 
+			for (o=0;o<5;o++){ // loop over the symbols of a sequence 
+				for (m=0;m<length_symbol;m++){
+					sub_sequence_reference_re[k][m] = sub_sequence_reference_re[k][m] + (int32_t)pow(-1,o) * signal_CFO_compensed_re[k*length_seq_NPRACH + o*length_symbol + length_CP + m] / 5; // average over the 5 symbols of a group
+					sub_sequence_reference_im[k][m] = sub_sequence_reference_im[k][m] + (int32_t)pow(-1,o) * signal_CFO_compensed_im [k*length_seq_NPRACH + o*length_symbol + length_CP + m]/ 5; // average over the 5 symbols of a group
+				}
+			}
+		} 
+		for (k=0;k<4;k++){ // re-initialize sub_sequence_reference matrices
+			for (m=0;m<length_symbol;m++){ 
+				sub_sequence_reference_re[k][m] = 0; 
+				sub_sequence_reference_im[k][m] = 0; 
+			}
+		} 
+
+		for (m=0;m<length_seq_NPRACH;m++){
+			vec_correlation[n] = vec_correlation[n] + (double)signal_CFO_compensed_re[m] * sequence_reference_re[m] + (double)signal_CFO_compensed_im[m] * sequence_reference_im[m];  
+		}
+
+	} 
+	for (n=0;n<length_correl_window;n++){ 
+		if(vec_correlation[n]>=max_correlation){ 
+			max_correlation = vec_correlation[n]; 
+			TA_sample_estimated = n; 
+		}
+	}
+
+	free(vec_correlation); 
+	for (k=0;k<4;k++){ // # sequence
+		free(matrix_received_signal_re[k]); 
+		free(matrix_received_signal_im[k]); 
+		free(sub_sequence_reference_re[k]); 
+		free(sub_sequence_reference_im[k]); 
+	} 
+	free(matrix_received_signal_re); 
+	free(matrix_received_signal_im); 
+	free(signal_CFO_compensed_re); 
+	free(signal_CFO_compensed_im); 
+	free(sub_sequence_reference_re); 
+	free(sub_sequence_reference_im); 
+
+	return TA_sample_estimated; 
+
+} 
+
+int16_t* sub_sampling_NB_IoT(int16_t *input_buffer, uint32_t length_input, uint32_t *length_ouput, uint16_t sub_sampling_rate){
+
+	int k; 
+	uint32_t L; 
+	int16_t *output_buffer; 
+
+	L = (uint32_t)((double)length_input / sub_sampling_rate); 
+	*length_ouput = L; 
+
+	output_buffer = (int16_t *)malloc(2*L*sizeof(int16_t)); 
+
+	for (k=0;k<L;k++){
+		output_buffer[2*k] = input_buffer[sub_sampling_rate*(2*k)]; 
+		output_buffer[2*k+1] = input_buffer[sub_sampling_rate*(2*k)+1]; 
+	} 
+	// for (k=0;k<2*L;k++){
+	// 	 printf("%i\n",output_buffer[k]); 
+	// }
+
+	return output_buffer;
+
+}
+
+void RX_NPRACH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int16_t *Rx_buffer){ 
+
+	uint32_t estimated_TA, estimated_TA_coarse; 
+	int16_t *Rx_sub_sampled_buffer_128,*Rx_sub_sampled_buffer_16; 
+	uint16_t sub_sampling_rate; //NB-IoT: to be defined somewhere
+	uint32_t FRAME_LENGTH_COMPLEX_SAMPLES; // NB-IoT: length of input buffer, to be defined somewhere 
+	uint32_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES; // Length of buffer after sub-sampling
+	uint32_t *length_ouput; // Length of buffer after sub-sampling 
+	char coarse=1; // flag that indicate the level of TA estimation
+
+	/* 1. Coarse TA estimation using sub sampling rate = 128, i.e. fs = 240 kHz  */
+
+	// Sub-sampling stage /============================================================/ 
+
+	sub_sampling_rate = 128; 
+	length_ouput = &FRAME_LENGTH_COMPLEX_SUB_SAMPLES; 
+	Rx_sub_sampled_buffer_128 = sub_sampling_NB_IoT(Rx_buffer,FRAME_LENGTH_COMPLEX_SAMPLES,length_ouput, sub_sampling_rate); 
+
+	// Detection and TA estimation stage  /============================================================/ 
+
+	if (NPRACH_detection_NB_IoT(eNB, Rx_sub_sampled_buffer_128, sub_sampling_rate,FRAME_LENGTH_COMPLEX_SUB_SAMPLES)){
+
+		estimated_TA_coarse = TA_estimation_NB_IoT(eNB, 
+												   Rx_sub_sampled_buffer_128, 
+												   sub_sampling_rate, 
+												   FRAME_LENGTH_COMPLEX_SUB_SAMPLES, 
+												   estimated_TA_coarse, 
+												   coarse); 
+
+		/* 2. Fine TA estimation using sub sampling rate = 16, i.e. fs = 240 MHz */ 
+	
+		// Sub-sampling stage /============================================================/
+		sub_sampling_rate = 16; 
+		Rx_sub_sampled_buffer_16 = sub_sampling_NB_IoT(Rx_buffer,FRAME_LENGTH_COMPLEX_SAMPLES,length_ouput, sub_sampling_rate); 
+
+
+		// Fine TA estimation stage  /============================================================/ 
+		// start1 = clock();
+		coarse = 0;
+		estimated_TA = TA_estimation_NB_IoT(eNB, 
+											Rx_sub_sampled_buffer_16, 
+											sub_sampling_rate, 
+											FRAME_LENGTH_COMPLEX_SUB_SAMPLES, 
+											estimated_TA_coarse, 
+											coarse); 
+		// Needs to be stored in a variable in PHY_VARS_eNB_NB_IoT structure
+	}
+
+
+}
+
diff --git a/openair1/PHY/LTE_TRANSPORT/npss_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/npss_NB_IoT.c
index 75e4f926169d79e8a12d7271eadb20663b51985a..3f16b3f13ed8be891fc42909e94304c5e6ad67b3 100644
--- a/openair1/PHY/LTE_TRANSPORT/npss_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/npss_NB_IoT.c
@@ -12,27 +12,33 @@
 * \warning
 */
 
-#include "PHY/defs.h"
-#include "PHY/extern.h"
+//#include "PHY/defs.h"
+///////////////#include "PHY/defs_nb_iot.h"
+//#include "PHY/extern.h"
+#include <math.h>
+#include "PHY/impl_defs_lte_NB_IoT.h"
+#include "PHY/impl_defs_top_NB_IoT.h"
+//or #include "PHY/defs_nb_iot.h"
+#include "PHY/LTE_REFSIG/primary_synch_NB_IoT.h"
 
-int generate_npss_NB_IoT(int32_t **txdataF,
-						short amp,
-						LTE_DL_FRAME_PARMS *frame_parms,
-						unsigned short symbol_offset,				// symbol_offset should equal to 3 for NB-IoT 
-						unsigned short slot_offset,
-						unsigned short RB_IoT_ID)					// new attribute (values are between 0.. Max_RB_number-1), it does not exist for LTE
+int generate_npss_NB_IoT(int32_t 				**txdataF,
+						short 					amp,
+						NB_IoT_DL_FRAME_PARMS   *frame_parms,
+						unsigned short 			symbol_offset,				// symbol_offset should equal to 3 for NB-IoT 
+						unsigned short 			slot_offset,
+						unsigned short 			RB_IoT_ID)					// new attribute (values are between 0.. Max_RB_number-1), it does not exist for LTE
 {
-   unsigned short c,aa,a,s;
-   unsigned short slot_id;
-   short *primary_sync;
-   unsigned short NB_IoT_start; 			// Index of the first RE in the RB dedicated for NB-IoT
-   unsigned short bandwidth_even_odd;
+   unsigned short  c,aa,a,s;
+   unsigned short  slot_id;
+   short 		   *primary_sync;
+   unsigned short  NB_IoT_start; 			// Index of the first RE in the RB dedicated for NB-IoT
+   unsigned short  bandwidth_even_odd;
 
-   slot_id = slot_offset;  							// The id(0..19) of the slot including the NPSS signal // For NB-IoT, slod_id should be 10 (SF5)
+   slot_id 		= slot_offset;  					// The id(0..19) of the slot including the NPSS signal // For NB-IoT, slod_id should be 10 (SF5)
    primary_sync = primary_synch_NB_IoT;     		// primary_synch_NB_IoT[264] of primary_synch_NB_IoT.h
 
    // Signal amplitude
-   a = (frame_parms->nb_antennas_tx == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15)>>15;
+   a = (frame_parms->nb_antennas_tx == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15_NB_IoT)>>15;
 
    // Testing if the total number of RBs is even or odd (i.e. Identification of the bandwidth: 1.4, 3, 5, 10, ... MHz)
    bandwidth_even_odd = frame_parms->N_RB_DL % 2;  		// 0 for even, 1 for odd
@@ -41,9 +47,9 @@ int generate_npss_NB_IoT(int32_t **txdataF,
 	
 		if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
 		{
-			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		} else {
-			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		}
 		// For the In-band or Stand-alone case the REs of NPSS signal have the same positions
 		for (s=0; s<11; s++ )   				// loop on OFDM symbols
@@ -65,7 +71,7 @@ int generate_npss_NB_IoT(int32_t **txdataF,
 }
 
 /* (for LTE)
-int generate_pss_emul(PHY_VARS_eNB *phy_vars_eNb,uint8_t sect_id)
+int generate_pss_emul(PHY_VARS_eNB_NB_IoT *phy_vars_eNb,uint8_t sect_id)
 {
 
   msg("[PHY] EMUL eNB generate_pss_emul eNB %d, sect_id %d\n",phy_vars_eNb->Mod_id,sect_id);
diff --git a/openair1/PHY/LTE_TRANSPORT/nsss_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/nsss_NB_IoT.c
index 16088af4e9e0a1dfbc2e14a95a58e5048b69bab8..f65ef2934e2d1e468ba977055279474892e88902 100644
--- a/openair1/PHY/LTE_TRANSPORT/nsss_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/nsss_NB_IoT.c
@@ -12,29 +12,32 @@
 * \warning
 */
 
+//#include <math.h>
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h" // not can be replaced by impl_defs_lte_NB_IoT & impl_defs_top_NB_IoT if "msg" function is not used
+//#include "defs.h"
+//#include "PHY/extern_NB_IoT.h"
+//#include "PHY/impl_defs_lte_NB_IoT.h"
+//#include "PHY/impl_defs_top_NB_IoT.h"
+#include "nsss_NB_IoT.h"
 
-#include "PHY/defs.h"
-#include "defs.h"
-#include "PHY/extern.h"
-
-int generate_sss_NB_IoT(int32_t **txdataF,
-						int16_t amp,
-						LTE_DL_FRAME_PARMS *frame_parms, 
-						uint16_t symbol_offset, 				// symbol_offset = 3 for NB-IoT 
-						uint16_t slot_offset, 
-						unsigned short frame_number, 			// new attribute (Get value from higher layer), it does not exist for LTE
-						unsigned short RB_IoT_ID)				// new attribute (values are between 0.. Max_RB_number-1), it does not exist for LTE
+int generate_sss_NB_IoT(int32_t 				**txdataF,
+						int16_t 				amp,
+						NB_IoT_DL_FRAME_PARMS   *frame_parms, 
+						uint16_t 				symbol_offset, 	// symbol_offset = 3 for NB-IoT 
+						uint16_t 				slot_offset, 
+						unsigned short 			frame_number, 	// new attribute (Get value from higher layer), it does not exist for LTE
+						unsigned short 			RB_IoT_ID)		// new attribute (values are between 0.. Max_RB_number-1), it does not exist for LTE
 {
-	uint8_t aa,Nid_NB_IoT,Nid2,f,q,s,c,u;
-	int16_t *d;
-	uint8_t Nid2;
-	uint16_t n_f;
-	unsigned short a;
-	uint16_t slot_id;  						// slot_id = 17 in NB_IoT
-	unsigned short bandwidth_even_odd;
-	unsigned short NB_IoT_start;
+	uint8_t  	    aa,Nid_NB_IoT,Nid2,f,q,s,c,u;
+	int16_t 		*d;
+	uint16_t 		n_f;
+	unsigned short  a;
+	uint16_t 		slot_id;  						// slot_id = 17 in NB_IoT
+	unsigned short  bandwidth_even_odd;
+	unsigned short  NB_IoT_start;
   
-	n_f = frame_number;
+	n_f 	   = frame_number;
 	Nid_NB_IoT = frame_parms->Nid_cell;     // supposing Cell_Id of LTE = Cell_Id of NB-IoT  // if different , NB_IOT_DL_FRAME_PARMS should be includes as attribute
   
 	f = (n_f/2) % 4;   						// f = 0, 1, 2, 3
@@ -100,7 +103,7 @@ int generate_sss_NB_IoT(int32_t **txdataF,
 	slot_id = slot_offset;
    
 	//  Signal amplitude
-	a = (frame_parms->nb_antennas_tx == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15)>>15;
+	a = (frame_parms->nb_antennas_tx == 1) ? amp: (amp*ONE_OVER_SQRT2_Q15_NB_IoT)>>15;
    
 	// Testing if the total number of RBs is even or odd (i.e. Identification of the bandwidth: 1.4, 3, 5, 10, ... MHz)
 	bandwidth_even_odd = frame_parms->N_RB_DL % 2;  		// 0 even, 1 odd
@@ -109,9 +112,9 @@ int generate_sss_NB_IoT(int32_t **txdataF,
 
 		if(RB_IoT_ID < (frame_parms->N_RB_DL/2))
 		{
-			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = frame_parms->ofdm_symbol_size - 12*(frame_parms->N_RB_DL/2) - (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		} else {
-			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(ceil(frame_parms->N_RB_DL/(float)2)));
+			NB_IoT_start = (bandwidth_even_odd*6) + 12*(RB_IoT_ID%(int)(ceil(frame_parms->N_RB_DL/(float)2)));
 		}
 		// For the In-band or Stand-alone case the REs of NPSS signal have the same positions
 		for (s=0; s<11; s++ ) 								// loop on OFDM symbols
diff --git a/openair1/PHY/LTE_TRANSPORT/pbch.c b/openair1/PHY/LTE_TRANSPORT/pbch.c
index e28e179b07a3b21bee4b60e6005d5d19a1617312..33b259e9348cdc0d45d4909da17559f8d8c3be41 100644
--- a/openair1/PHY/LTE_TRANSPORT/pbch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pbch.c
@@ -37,6 +37,7 @@
 #include "PHY/extern.h"
 #include "PHY/sse_intrin.h"
 
+
 #ifdef PHY_ABSTRACTION
 #include "SIMULATION/TOOLS/defs.h"
 #endif
@@ -50,6 +51,8 @@
 #include "PHY_INTERFACE/defs.h"
 #endif
 
+#include "PHY/LTE_REFSIG/defs.h"
+
 #define PBCH_A 24
 
 int allocate_pbch_REs_in_RB(LTE_DL_FRAME_PARMS *frame_parms,
diff --git a/openair1/PHY/LTE_TRANSPORT/pilots_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/pilots_NB_IoT.c
index 20d0663db3004a215bf6340bd1b9b04d4a784cff..96ecd44117d2e17b87605570249423d2f8b70207 100644
--- a/openair1/PHY/LTE_TRANSPORT/pilots_NB_IoT.c
+++ b/openair1/PHY/LTE_TRANSPORT/pilots_NB_IoT.c
@@ -12,99 +12,103 @@
 * \warning
 */
 
-#include "PHY/defs.h"
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
 
-void generate_pilots_NB_IoT(PHY_VARS_eNB *phy_vars_eNB,
-                     int32_t **txdataF,
-                     int16_t amp,
-                     uint16_t Ntti, 					// Ntti = 10
-					 unsigned short RB_IoT_ID,			// RB reserved for NB-IoT
-					 unsigned short With_NSSS;) 		// With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
+void generate_pilots_NB_IoT(PHY_VARS_eNB_NB_IoT  *phy_vars_eNB,
+                            int32_t              **txdataF,
+                            int16_t              amp,
+                            uint16_t             Ntti, 				// Ntti = 10
+					        unsigned short       RB_IoT_ID,			// RB reserved for NB-IoT
+					        unsigned short       With_NSSS) 		// With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
 {
 
-  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;
+  NB_IoT_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->frame_parms_NB_IoT;
 
   uint32_t tti,tti_offset,slot_offset,Nsymb,samples_per_symbol;
-  uint8_t first_pilot,second_pilot;
-  Nsymb = 14;
-  first_pilot = 5;      // first pilot position
+  uint8_t  first_pilot,second_pilot;
+
+  Nsymb        = 14;
+  first_pilot  = 5;     // first pilot position
   second_pilot = 6;		// second pilot position
   
   for (tti=0; tti<Ntti; tti++) { 										// loop on sub-frames    
 
-    tti_offset = tti*frame_parms->ofdm_symbol_size*Nsymb; 				// begins with 0
+    tti_offset         = tti*frame_parms->ofdm_symbol_size*Nsymb; 				// begins with 0
     samples_per_symbol = frame_parms->ofdm_symbol_size;  				// ex. 512
-    slot_offset = (tti*2)%20; 											// 0, 2, 4, ....... 18 
+    slot_offset        = (tti*2)%20; 											// 0, 2, 4, ....... 18 
 	
 	if((slot_offset != 10) && ((With_NSSS*slot_offset) != 18)) {   		//  condition to avoid NPSS and NSSS signals
 	
 		//Generate Pilots for slot 0 and 1
 		
-			//antenna 0 symbol 5 slot 0
-		lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (first_pilot*samples_per_symbol)], 			// tti_offset 512 x 32 bits
-                     amp,
-					 RB_IoT_ID,
-                     slot_offset,
-                     0,
-                     0);
+		//antenna 0 symbol 5 slot 0
+		lte_dl_cell_spec_NB_IoT(phy_vars_eNB,
+					            &txdataF[0][tti_offset + (first_pilot*samples_per_symbol)], 			// tti_offset 512 x 32 bits
+                                amp,
+					            RB_IoT_ID,
+                                slot_offset,
+                                0, //p
+                                0);
 					 
-			//antenna 0 symbol 6 slot 0
+		//antenna 0 symbol 6 slot 0
 		lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (second_pilot*samples_per_symbol)],
-                     amp,
-					 RB_IoT_ID,
-                     slot_offset,
-                     1,
-                     0);
+                                amp,
+					            RB_IoT_ID,
+                                slot_offset,
+                                1,
+                                0);
 
-			//antenna 0 symbol 5 slot 1
+		//antenna 0 symbol 5 slot 1
 		lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (7*samples_per_symbol) + (first_pilot*samples_per_symbol)],
-                     amp,
-					 RB_IoT_ID,
-                     1+slot_offset,
-                     0,
-                     0);
+                                amp,
+					            RB_IoT_ID,
+                                1+slot_offset,
+                                0,
+                                0);
 
-			//antenna 0 symbol 6 slot 1
+		//antenna 0 symbol 6 slot 1
 		lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[0][tti_offset + (7*samples_per_symbol) + (second_pilot*samples_per_symbol)],
-                     amp,
-					 RB_IoT_ID,
-                     1+slot_offset,
-                     1,
-                     0);
+                                amp,
+					            RB_IoT_ID,
+                                1+slot_offset,
+                                1,
+                                0);
 
 		if (frame_parms->nb_antennas_tx > 1) {  																// Pilots generation with two antennas
 
-				// antenna 1 symbol 5 slot 0
+			// antenna 1 symbol 5 slot 0
 			lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (first_pilot*samples_per_symbol)],
-                         amp,
-						 RB_IoT_ID,
-                         slot_offset,
-                         0,
-                         1);
+                                    amp,
+						            RB_IoT_ID,
+                                    slot_offset,
+                                    0,
+                                    1);
 
-				// antenna 1 symbol 6 slot 0
+			// antenna 1 symbol 6 slot 0
 			lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (second_pilot*samples_per_symbol)],
-                         amp,
-						 RB_IoT_ID,
-                         slot_offset,
-                         1,
-                         1);
+                                    amp,
+						            RB_IoT_ID,
+                                    slot_offset,
+                                    1,
+                                    1);
 
-				//antenna 1 symbol 5 slot 1
+			//antenna 1 symbol 5 slot 1
 			lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (7*samples_per_symbol) + (first_pilot*samples_per_symbol)],
-                         amp,
-						 RB_IoT_ID,
-                         1+slot_offset,
-                         0,
-                         1);
+                                    amp,
+						            RB_IoT_ID,
+                                    1+slot_offset,
+                                    0,
+                                    1);
 
-				// antenna 1 symbol 6 slot 1
+			// antenna 1 symbol 6 slot 1
 			lte_dl_cell_spec_NB_IoT(phy_vars_eNB,&txdataF[1][tti_offset + (7*samples_per_symbol) + (second_pilot*samples_per_symbol)],
-                         amp,
-						 RB_IoT_ID,
-                         1+slot_offset,
-                         1,
-                         1);
+                                    amp,
+						            RB_IoT_ID,
+                                    1+slot_offset,
+                                    1,
+                                    1);
 		}
 	}
   }
diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h
index 54054ed90f765dee7d478b07cad642b7b0f81984..d8b3ea8b9ab179c8b3da1e2c78d1e98d52dd7ff3 100644
--- a/openair1/PHY/LTE_TRANSPORT/proto.h
+++ b/openair1/PHY/LTE_TRANSPORT/proto.h
@@ -60,6 +60,7 @@ void clean_eNb_dlsch(LTE_eNB_DLSCH_t *dlsch);
 */
 LTE_eNB_DLSCH_t *new_eNB_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t N_RB_DL, uint8_t abstraction_flag, LTE_DL_FRAME_PARMS* frame_parms);
 
+
 /** \fn free_ue_dlsch(LTE_UE_DLSCH_t *dlsch)
     \brief This function frees memory allocated for a particular DLSCH at UE
     @param dlsch Pointer to DLSCH to be removed
@@ -84,6 +85,7 @@ void free_ue_ulsch(LTE_UE_ULSCH_t *ulsch);
 
 LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag);
 
+
 LTE_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag);
 
 /** \fn dlsch_encoding(PHY_VARS_eNB *eNB,
@@ -122,14 +124,14 @@ int32_t dlsch_encoding(PHY_VARS_eNB *eNB,
                        time_stats_t *i_stats);
 
 int32_t dlsch_encoding_SIC(PHY_VARS_UE *ue,
-                       uint8_t *a,
-                       uint8_t num_pdcch_symbols,
-                       LTE_eNB_DLSCH_t *dlsch,
-                       int frame,
-                       uint8_t subframe,
-                       time_stats_t *rm_stats,
-                       time_stats_t *te_stats,
-                       time_stats_t *i_stats);
+                           uint8_t *a,
+                           uint8_t num_pdcch_symbols,
+                           LTE_eNB_DLSCH_t *dlsch,
+                           int frame,
+                           uint8_t subframe,
+                           time_stats_t *rm_stats,
+                           time_stats_t *te_stats,
+                           time_stats_t *i_stats);
 
 
 
@@ -269,7 +271,6 @@ int32_t allocate_REs_in_RB(PHY_VARS_eNB* phy_vars_eNB,
                            int *P1_SHIFT,
                            int *P2_SHIFT);
 
-
 /** \fn int32_t dlsch_modulation(int32_t **txdataF,
     int16_t amp,
     uint32_t sub_frame_offset,
@@ -295,11 +296,11 @@ int32_t dlsch_modulation(PHY_VARS_eNB* phy_vars_eNB,
                          LTE_eNB_DLSCH_t *dlsch1);
 
 int32_t dlsch_modulation_SIC(int32_t **sic_buffer,
-                         uint32_t sub_frame_offset,
-                         LTE_DL_FRAME_PARMS *frame_parms,
-                         uint8_t num_pdcch_symbols,
-                         LTE_eNB_DLSCH_t *dlsch0,
-                         int G);
+                             uint32_t sub_frame_offset,
+                             LTE_DL_FRAME_PARMS *frame_parms,
+                             uint8_t num_pdcch_symbols,
+                             LTE_eNB_DLSCH_t *dlsch0,
+                             int G);
 /*
   \brief This function is the top-level routine for generation of the sub-frame signal (frequency-domain) for MCH.
   @param txdataF Table of pointers for frequency-domain TX signals
@@ -396,7 +397,6 @@ void generate_ue_spec_pilots(PHY_VARS_eNB *phy_vars_eNB,
                              int16_t amp,
                              uint16_t Ntti,
                              uint8_t beamforming_mode);
-
 int32_t generate_pss(int32_t **txdataF,
                      int16_t amp,
                      LTE_DL_FRAME_PARMS *frame_parms,
@@ -1742,7 +1742,7 @@ int32_t generate_ue_ulsch_params_from_rar(PHY_VARS_UE *phy_vars_ue,
                                           uint8_t eNB_id);
 double sinr_eff_cqi_calc(PHY_VARS_UE *phy_vars_ue,
                          uint8_t eNB_id,
-                                                 uint8_t subframe);
+                         uint8_t subframe);
 
 uint8_t sinr2cqi(double sinr,uint8_t trans_mode);
 
diff --git a/openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..a06656c2fb6537d14bef8f5236bbd17a50530c03
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/proto_NB_IoT.h
@@ -0,0 +1,255 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/proto.h
+ * \brief Function prototypes for PHY physical/transport channel processing and generation V8.6 2009-03
+ * \author R. Knopp, F. Kaltenberger
+ * \date 2011
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+#ifndef __LTE_TRANSPORT_PROTO_NB_IOT__H__
+#define __LTE_TRANSPORT_PROTO_NB_IOT__H__
+#include "PHY/defs_NB_IoT.h"
+//#include <math.h>
+
+//NPSS
+
+int generate_npss_NB_IoT(int32_t                **txdataF,
+                         short                  amp,
+                         NB_IoT_DL_FRAME_PARMS  *frame_parms,
+                         unsigned short         symbol_offset,          // symbol_offset should equal to 3 for NB-IoT 
+                         unsigned short         slot_offset,
+                         unsigned short         RB_IoT_ID);             // new attribute (values are between 0.. Max_RB_number-1), it does not exist for LTE
+
+//NSSS
+
+int generate_sss_NB_IoT(int32_t                **txdataF,
+                        int16_t                amp,
+                        NB_IoT_DL_FRAME_PARMS  *frame_parms, 
+                        uint16_t               symbol_offset,             // symbol_offset = 3 for NB-IoT 
+                        uint16_t               slot_offset, 
+                        unsigned short         frame_number,        // new attribute (Get value from higher layer), it does not exist for LTE
+                        unsigned short         RB_IoT_ID);          // new attribute (values are between 0.. Max_RB_number-1), it does not exist for LTE
+
+//NRS
+
+void generate_pilots_NB_IoT(PHY_VARS_eNB_NB_IoT  *phy_vars_eNB,
+                            int32_t              **txdataF,
+                            int16_t              amp,
+                            uint16_t             Ntti,                // Ntti = 10
+                            unsigned short       RB_IoT_ID,       // RB reserved for NB-IoT
+                            unsigned short       With_NSSS);      // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
+
+
+//NPBCH
+
+int allocate_npbch_REs_in_RB(NB_IoT_DL_FRAME_PARMS  *frame_parms,
+                             int32_t                **txdataF,
+                             uint32_t               *jj,
+                             uint32_t               symbol_offset,
+                             uint8_t                *x0,
+                             uint8_t                pilots,
+                             int16_t                amp,
+                             unsigned short         id_offset,
+                             uint32_t               *re_allocated);
+
+
+int generate_npbch(NB_IoT_eNB_NPBCH_t     *eNB_npbch,
+                   int32_t                **txdataF,
+                   int                    amp,
+                   NB_IoT_DL_FRAME_PARMS  *frame_parms,
+                   uint8_t                *npbch_pdu,
+                   uint8_t                frame_mod64,
+                   unsigned short         NB_IoT_RB_ID);
+
+
+void npbch_scrambling(NB_IoT_DL_FRAME_PARMS  *frame_parms,
+                      uint8_t                *npbch_e,
+                      uint32_t               length);
+
+// Functions below implement 36-211 and 36-212
+
+/*Function to pack the DCI*/ 
+// newly added function for NB-IoT , does not exist for LTE
+void add_dci_NB_IoT(DCI_PDU_NB_IoT    *DCI_pdu,
+                    void              *pdu,
+                    rnti_t            rnti,
+                    unsigned char     dci_size_bytes,
+                    unsigned char     aggregation, 
+                    unsigned char     dci_size_bits,
+                    unsigned char     dci_fmt,
+                    uint8_t           npdcch_start_symbol);
+
+
+/*Use the UL DCI Information to configure PHY and also Pack the DCI*/
+int generate_eNB_ulsch_params_from_dci_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
+                                              eNB_rxtx_proc_NB_IoT_t  *proc,
+                                              DCI_CONTENT             *DCI_Content,
+                                              uint16_t                rnti,
+                                              DCI_format_NB_IoT_t     dci_format,
+                                              uint8_t                 UE_id,
+                                              uint8_t                 aggregation,
+									                            uint8_t                 npdcch_start_symbol);
+
+
+/*Use the DL DCI Information to configure PHY and also Pack the DCI*/
+int generate_eNB_dlsch_params_from_dci_NB_IoT(PHY_VARS_eNB_NB_IoT    *eNB,
+                                              int                    frame,
+                                              uint8_t                subframe,
+                                              DCI_CONTENT            *DCI_Content,
+                                              uint16_t               rnti,
+                                              DCI_format_NB_IoT_t    dci_format,
+                                              NB_IoT_eNB_NDLSCH_t    *ndlsch,
+                                              NB_IoT_DL_FRAME_PARMS  *frame_parms,
+                                              uint8_t                aggregation,
+									                            uint8_t                npdcch_start_symbol);
+
+
+/*Function for DCI encoding, scrambling, modulation*/
+uint8_t generate_dci_top_NB_IoT(NB_IoT_eNB_NPDCCH_t     *npdcch,
+						                    uint8_t                 Num_dci,
+                                DCI_ALLOC_NB_IoT_t      *dci_alloc,
+                                int16_t                 amp,
+                                NB_IoT_DL_FRAME_PARMS   *fp,
+                                int32_t                 **txdataF,
+                                uint32_t                subframe,
+						                    uint8_t                 npdcch_start_symbol);
+
+/*!
+  \brief Decoding of PUSCH/ACK/RI/ACK from 36-212.
+  @param phy_vars_eNB Pointer to eNB top-level descriptor
+  @param proc Pointer to RXTX proc variables
+  @param UE_id ID of UE transmitting this PUSCH
+  @param subframe Index of subframe for PUSCH
+  @param control_only_flag Receive PUSCH with control information only
+  @param Nbundled Nbundled parameter for ACK/NAK scrambling from 36-212/36-213
+  @param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used
+  @returns 0 on success
+*/
+unsigned int  ulsch_decoding_NB_IoT(PHY_VARS_eNB_NB_IoT     *phy_vars_eNB,
+                                    eNB_rxtx_proc_NB_IoT_t  *proc,
+                                    uint8_t                 UE_id,
+                                    uint8_t                 control_only_flag,
+                                    uint8_t                 Nbundled,
+                                    uint8_t                 llr8_flag);
+
+//NB-IoT version
+NB_IoT_eNB_NDLSCH_t *new_eNB_dlsch_NB_IoT(//unsigned char Kmimo,
+                                          //unsigned char Mdlharq,
+                                          uint32_t Nsoft,
+                                          //unsigned char N_RB_DL,
+                                          uint8_t abstraction_flag,
+                                          NB_IoT_DL_FRAME_PARMS* frame_parms);
+
+
+NB_IoT_eNB_NULSCH_t *new_eNB_ulsch_NB_IoT(uint8_t abstraction_flag);
+
+
+uint8_t subframe2harq_pid_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe);
+
+
+/** \brief Compute Q (modulation order) based on I_MCS for PUSCH.  Implements table 8.6.1-1 from 36.213.
+    @param I_MCS */
+
+//uint8_t get_Qm_ul_NB_IoT(uint8_t I_MCS);
+unsigned char get_Qm_ul_NB_IoT(unsigned char I_MCS, uint8_t N_sc_RU);
+
+/** \fn dlsch_encoding(PHY_VARS_eNB *eNB,
+    uint8_t *input_buffer,
+    LTE_DL_FRAME_PARMS *frame_parms,
+    uint8_t num_pdcch_symbols,
+    LTE_eNB_DLSCH_t *dlsch,
+    int frame,
+    uint8_t subframe)
+    \brief This function performs a subset of the bit-coding functions for LTE as described in 36-212, Release 8.Support is limited to turbo-coded channels (DLSCH/ULSCH). The implemented functions are:
+    - CRC computation and addition
+    - Code block segmentation and sub-block CRC addition
+    - Channel coding (Turbo coding)
+    - Rate matching (sub-block interleaving, bit collection, selection and transmission
+    - Code block concatenation
+    @param eNB Pointer to eNB PHY context
+    @param input_buffer Pointer to input buffer for sub-frame
+    @param frame_parms Pointer to frame descriptor structure
+    @param num_pdcch_symbols Number of PDCCH symbols in this subframe
+    @param dlsch Pointer to dlsch to be encoded
+    @param frame Frame number
+    @param subframe Subframe number
+    @param rm_stats Time statistics for rate-matching
+    @param te_stats Time statistics for turbo-encoding
+    @param i_stats Time statistics for interleaving
+    @returns status
+*/
+
+int32_t dlsch_encoding_NB_IoT(unsigned char              *a,
+                              NB_IoT_eNB_DLSCH_t         *dlsch,
+                              uint8_t                    Nsf,        // number of subframes required for npdsch pdu transmission calculated from Isf (3GPP spec table)
+                              unsigned int               G,          // G (number of available RE) is implicitly multiplied by 2 (since only QPSK modulation)
+                              time_stats_t_NB_IoT        *rm_stats,
+                              time_stats_t_NB_IoT        *te_stats,
+                              time_stats_t_NB_IoT        *i_stats);
+
+
+void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT      *phy_vars_eNB,
+                     eNB_rxtx_proc_NB_IoT_t   *proc,
+                     uint8_t                  eNB_id,               // this is the effective sector id
+                     uint8_t                  UE_id,
+                     NB_IoT_eNB_NULSCH_t      **ulsch,
+                     uint8_t                  cooperation_flag);
+
+void ulsch_extract_rbs_single_NB_IoT(int32_t                **rxdataF,
+                                     int32_t                **rxdataF_ext,
+                                     // uint32_t               first_rb, 
+                                     uint32_t               UL_RB_ID_NB_IoT, // index of UL NB_IoT resource block 
+                                     uint8_t                N_sc_RU, // number of subcarriers in UL
+				     uint32_t               I_sc, // subcarrier indication field
+                                     uint32_t               nb_rb,
+                                     uint8_t                l,
+                                     uint8_t                Ns,
+                                     NB_IoT_DL_FRAME_PARMS  *frame_parms);
+
+void extract_CQI_NB_IoT(void *o,UCI_format_NB_IoT_t uci_format,NB_IoT_eNB_UE_stats *stats,uint8_t N_RB_DL, uint16_t * crnti, uint8_t * access_mode);
+
+//*****************Vincent part for nprach ******************//
+void RX_NPRACH_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int16_t *Rx_buffer); 
+
+uint32_t TA_estimation_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, 
+                              int16_t *Rx_sub_sampled_buffer, 
+                              uint16_t sub_sampling_rate, 
+                              uint16_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES, 
+                              uint32_t estimated_TA_coarse, 
+                              char coarse); 
+
+uint8_t NPRACH_detection_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB, int16_t *Rx_sub_sampled_buffer, uint16_t sub_sampling_rate, uint32_t FRAME_LENGTH_COMPLEX_SUB_SAMPLES); 
+
+int16_t* sub_sampling_NB_IoT(int16_t *input_buffer, uint32_t length_input, uint32_t *length_ouput, uint16_t sub_sampling_rate);
+//************************************************************//
+//*****************Vincent part for ULSCH demodulation ******************//
+uint16_t get_UL_sc_start_NB_IoT(uint16_t I_sc); 
+
+void generate_grouphop_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms); 
+
+void init_ul_hopping_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms); 
+//************************************************************//
+#endif
diff --git a/openair1/PHY/LTE_TRANSPORT/pucch.c b/openair1/PHY/LTE_TRANSPORT/pucch.c
index 8adc693b31c7d668785ea011da34c21ed581ad5b..5d27d6b4a35f68b557acf345be17dd3dbc227dc4 100644
--- a/openair1/PHY/LTE_TRANSPORT/pucch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pucch.c
@@ -1263,7 +1263,7 @@ uint16_t pucchfmt3_ChannelEstimation( int16_t SubCarrierDeMapData[NB_ANTENNAS_RX
     int32_t         IP_CsData_allsfavg[NB_ANTENNAS_RX][14][4][2];
     int32_t         IP_allavg[D_NPUCCH_SF5];
     //int16_t         temp_ch[2];
-	int16_t         m[NUMBER_OF_UE_MAX], m_self, same_m_number;
+	int16_t         m[NUMBER_OF_UE_MAX], m_self=0, same_m_number;
 	uint16_t        n3_pucch_sameRB[NUMBER_OF_UE_MAX];
 	int16_t         n_oc0[NUMBER_OF_UE_MAX];
 	int16_t         n_oc1[NUMBER_OF_UE_MAX];
diff --git a/openair1/PHY/LTE_TRANSPORT/uci_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/uci_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..b20635360d0b977b497fb60a7dab4ca76489901b
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/uci_NB_IoT.h
@@ -0,0 +1,324 @@
+/*
+ * 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.0  (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 __UCI_NB_IOT__H__
+#define __UCI_NB_IOT__H__
+//#include "PHY/types_NB_IoT.h"
+
+
+
+typedef enum {
+  ue_selected_NB_IoT,
+  wideband_cqi_rank1_2A_NB_IoT, //wideband_cqi_rank1_2A,
+  wideband_cqi_rank2_2A_NB_IoT, //wideband_cqi_rank2_2A,
+  HLC_subband_cqi_nopmi_NB_IoT, //HLC_subband_cqi_nopmi,
+  HLC_subband_cqi_rank1_2A_NB_IoT, //HLC_subband_cqi_rank1_2A,
+  HLC_subband_cqi_rank2_2A_NB_IoT, //HLC_subband_cqi_rank2_2A,
+  HLC_subband_cqi_modes123_NB_IoT, //HLC_subband_cqi_modes123
+  HLC_subband_cqi_mcs_CBA_NB_IoT, // MCS and RNTI, for contention-based acces
+  unknown_cqi_NB_IoT//
+} UCI_format_NB_IoT_t;
+
+// **********************************************1.5 MHz***************************************************************************
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:16;
+  uint32_t pmi:12;
+  uint32_t cqi1:4;
+}
+wideband_cqi_rank1_2A_1_5MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank1_2A_1_5MHz_NB_IoT 16
+
+typedef struct __attribute__((packed))
+{
+  uint16_t padding:2;
+  uint16_t pmi:6;
+  uint16_t cqi2:4;
+  uint16_t cqi1:4;
+}
+wideband_cqi_rank2_2A_1_5MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank2_2A_1_5MHz_NB_IoT 14
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:16;
+  uint32_t diffcqi1:12;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_nopmi_1_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_nopmi_1_5MHz_NB_IoT 16
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:14;
+  uint32_t pmi:2;
+  uint32_t diffcqi1:12;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_rank1_2A_1_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank1_2A_1_5MHz_NB_IoT 18
+
+typedef struct __attribute__((packed))
+{
+  uint64_t padding:31;
+  uint64_t pmi:1;
+  uint64_t diffcqi2:12;
+  uint64_t cqi2:4;
+  uint64_t diffcqi1:12;
+  uint64_t cqi1:4;
+}
+HLC_subband_cqi_rank2_2A_1_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank2_2A_1_5MHz_NB_IoT 33
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:16;
+  uint32_t diffcqi1:12;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_modes123_1_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_modes123_1_5MHz_NB_IoT 16
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:11;
+  uint32_t crnti:16;
+  uint32_t mcs:5;
+}
+HLC_subband_cqi_mcs_CBA_1_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_mcs_CBA_1_5MHz_NB_IoT 21
+
+
+// **********************************************5 MHz***************************************************************************
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:14;
+  uint32_t pmi:14;
+  uint32_t cqi1:4;
+}
+wideband_cqi_rank1_2A_5MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank1_2A_5MHz_NB_IoT 18
+
+typedef struct __attribute__((packed))
+{
+  uint16_t padding:1;
+  uint16_t pmi:7;
+  uint16_t cqi2:4;
+  uint16_t cqi1:4;
+}
+wideband_cqi_rank2_2A_5MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank2_2A_5MHz_NB_IoT 15
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:14;
+  uint32_t diffcqi1:14;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_nopmi_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_nopmi_5MHz_NB_IoT 18
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:12;
+  uint32_t pmi:2;
+  uint32_t diffcqi1:14;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_rank1_2A_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank1_2A_5MHz_NB_IoT 20
+
+typedef struct __attribute__((packed))
+{
+  uint64_t padding:27;
+  uint64_t pmi:1;
+  uint64_t diffcqi2:14;
+  uint64_t cqi2:4;
+  uint64_t diffcqi1:14;
+  uint64_t cqi1:4;
+}
+HLC_subband_cqi_rank2_2A_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank2_2A_5MHz_NB_IoT 37
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:14;
+  uint32_t diffcqi1:14;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_modes123_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_modes123_5MHz_NB_IoT 18
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:11;
+  uint32_t crnti:16;
+  uint32_t mcs:5;
+}
+HLC_subband_cqi_mcs_CBA_5MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_mcs_CBA_5MHz_NB_IoT 21
+
+// **********************************************10 MHz***************************************************************************
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:10;
+  uint32_t pmi:18;
+  uint32_t cqi1:4;
+}
+wideband_cqi_rank1_2A_10MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank1_2A_10MHz_NB_IoT 22
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:15;
+  uint32_t pmi:9;
+  uint32_t cqi2:4;
+  uint32_t cqi1:4;
+}
+wideband_cqi_rank2_2A_10MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank2_2A_10MHz_NB_IoT 17
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:10;
+  uint32_t diffcqi1:18;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_nopmi_10MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_nopmi_10MHz_NB_IoT 22
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:8;
+  uint32_t pmi:2;
+  uint32_t diffcqi1:18;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_rank1_2A_10MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank1_2A_10MHz_NB_IoT 24
+
+typedef struct __attribute__((packed))
+{
+  uint64_t padding:19;
+  uint64_t pmi:1;
+  uint64_t diffcqi2:18;
+  uint64_t cqi2:4;
+  uint64_t diffcqi1:18;
+  uint64_t cqi1:4;
+}
+HLC_subband_cqi_rank2_2A_10MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank2_2A_10MHz_NB_IoT 45
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:10;
+  uint32_t diffcqi1:18;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_modes123_10MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_modes123_10MHz_NB_IoT 22
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:11;
+  uint32_t crnti:16;
+  uint32_t mcs:5;
+}
+HLC_subband_cqi_mcs_CBA_10MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_mcs_CBA_10MHz_NB_IoT 21
+
+// **********************************************20 MHz***************************************************************************
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:2;
+  uint32_t pmi:26;
+  uint32_t cqi1:4;
+}
+wideband_cqi_rank1_2A_20MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank1_2A_20MHz_NB_IoT 20
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:11;
+  uint32_t pmi:13;
+  uint32_t cqi2:4;
+  uint32_t cqi1:4;
+}
+wideband_cqi_rank2_2A_20MHz_NB_IoT ;
+#define sizeof_wideband_cqi_rank2_2A_20MHz_NB_IoT 21
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:2;
+  uint32_t diffcqi1:26;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_nopmi_20MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_nopmi_20MHz_NB_IoT 30
+
+typedef struct __attribute__((packed))
+{
+  //  uint32_t padding:12;
+  uint32_t pmi:2;
+  uint32_t diffcqi1:26;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_rank1_2A_20MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank1_2A_20MHz_NB_IoT 32
+
+typedef struct __attribute__((packed))
+{
+  uint64_t padding:3;
+  uint64_t pmi:1;
+  uint64_t diffcqi2:26;
+  uint64_t cqi2:4;
+  uint64_t diffcqi1:26;
+  uint64_t cqi1:4;
+}
+HLC_subband_cqi_rank2_2A_20MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_rank2_2A_20MHz_NB_IoT 61
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:2;
+  uint32_t diffcqi1:26;
+  uint32_t cqi1:4;
+}
+HLC_subband_cqi_modes123_20MHz_NB_IoT;
+#define sizeof_HLC_subband_cqi_modes123_20MHz_NB_IoT 30
+
+typedef struct __attribute__((packed))
+{
+  uint32_t padding:11;
+  uint32_t crnti:16;
+  uint32_t mcs:5;
+}
+HLC_subband_cqi_mcs_CBA_20MHz_NB_IoT;
+
+#define sizeof_HLC_subband_cqi_mcs_CBA_20MHz_NB_IoT 21
+
+#define MAX_CQI_PAYLOAD_NB_IoT (sizeof(HLC_subband_cqi_rank2_2A_20MHz_NB_IoT)*8*20)
+#define MAX_CQI_BITS_NB_IoT (sizeof(HLC_subband_cqi_rank2_2A_20MHz_NB_IoT)*8)
+#define MAX_CQI_BYTES_NB_IoT (sizeof(HLC_subband_cqi_rank2_2A_20MHz_NB_IoT))
+#define MAX_ACK_PAYLOAD_NB_IoT 18
+#define MAX_RI_PAYLOAD_NB_IoT 6
+
+#endif
\ No newline at end of file
diff --git a/openair1/PHY/LTE_TRANSPORT/uci_tools_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/uci_tools_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..6266ae38de1e1e59042b2d3fafc06214213c03fc
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/uci_tools_NB_IoT.c
@@ -0,0 +1,431 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/phich.c
+* \brief Routines for generation of and computations regarding the uplink control information (UCI) for PUSCH. V8.6 2009-03
+* \author R. Knopp, F. Kaltenberger, A. Bhamri
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: knopp@eurecom.fr, florian.kaltenberger@eurecom.fr, ankit.bhamri@eurecom.fr
+* \note
+* \warning
+*/
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/extern_NB_IoT.h"
+#ifdef DEBUG_UCI_TOOLS
+#include "PHY/vars_NB_IoT.h"
+#endif
+
+
+void do_diff_cqi_NB_IoT(uint8_t N_RB_DL,
+                        uint8_t *DL_subband_cqi,
+                        uint8_t DL_cqi,
+                        uint32_t diffcqi1)
+{
+
+  uint8_t nb_sb,i,offset;
+
+  // This is table 7.2.1-3 from 36.213 (with k replaced by the number of subbands, nb_sb)
+  switch (N_RB_DL) {
+  case 6:
+    nb_sb=1;
+    break;
+
+  case 15:
+    nb_sb = 4;
+    break;
+
+  case 25:
+    nb_sb = 7;
+    break;
+
+  case 50:
+    nb_sb = 9;
+    break;
+
+  case 75:
+    nb_sb = 10;
+    break;
+
+  case 100:
+    nb_sb = 13;
+    break;
+
+  default:
+    nb_sb=0;
+    break;
+  }
+
+  memset(DL_subband_cqi,0,13);
+
+  for (i=0; i<nb_sb; i++) {
+    offset = (diffcqi1>>(2*i))&3;
+
+    if (offset == 3)
+      DL_subband_cqi[i] = DL_cqi - 1;
+    else
+      DL_subband_cqi[i] = DL_cqi + offset;
+  }
+}
+
+void extract_CQI_NB_IoT(void *o,UCI_format_NB_IoT_t uci_format,NB_IoT_eNB_UE_stats *stats, uint8_t N_RB_DL, uint16_t * crnti, uint8_t * access_mode)
+{
+
+  
+  uint8_t i;
+  LOG_D(PHY,"[eNB][UCI] N_RB_DL %d uci format %d\n", N_RB_DL,uci_format);
+
+  switch(N_RB_DL) {
+  case 6:
+    switch(uci_format) {
+    case wideband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank1_2A_1_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_pmi_single = ((wideband_cqi_rank1_2A_1_5MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case wideband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank2_2A_1_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((wideband_cqi_rank2_2A_1_5MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      stats->DL_pmi_dual   = ((wideband_cqi_rank2_2A_1_5MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_nopmi_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_nopmi_1_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],((HLC_subband_cqi_nopmi_1_5MHz_NB_IoT *)o)->diffcqi1);
+      break;
+
+    case HLC_subband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank1_2A_1_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank1_2A_1_5MHz_NB_IoT *)o)->diffcqi1));
+      stats->DL_pmi_single = ((HLC_subband_cqi_rank1_2A_1_5MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank2_2A_1_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((HLC_subband_cqi_rank2_2A_1_5MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank2_2A_1_5MHz *)o)->diffcqi1));
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[1],stats->DL_cqi[1],(((HLC_subband_cqi_rank2_2A_1_5MHz *)o)->diffcqi2));
+      stats->DL_pmi_dual   = ((HLC_subband_cqi_rank2_2A_1_5MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_mcs_CBA_NB_IoT:
+      if ((*crnti == ((HLC_subband_cqi_mcs_CBA_1_5MHz_NB_IoT *)o)->crnti) && (*crnti !=0)) {
+        *access_mode=CBA_ACCESS;
+        LOG_N(PHY,"[eNB] UCI for CBA : mcs %d  crnti %x\n",
+              ((HLC_subband_cqi_mcs_CBA_1_5MHz_NB_IoT *)o)->mcs, ((HLC_subband_cqi_mcs_CBA_1_5MHz_NB_IoT *)o)->crnti);
+      } else {
+        LOG_D(PHY,"[eNB] UCI for CBA : rnti (enb context %x, rx uci %x) invalid, unknown access\n",
+              *crnti, ((HLC_subband_cqi_mcs_CBA_1_5MHz_NB_IoT *)o)->crnti);
+      }
+
+      break;
+
+    case unknown_cqi:
+    default:
+      LOG_N(PHY,"[eNB][UCI] received unknown uci (rb %d)\n",N_RB_DL);
+      break;
+    }
+
+    break;
+
+  case 25:
+
+    switch(uci_format) {
+    case wideband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank1_2A_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_pmi_single = ((wideband_cqi_rank1_2A_5MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case wideband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank2_2A_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((wideband_cqi_rank2_2A_5MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      stats->DL_pmi_dual   = ((wideband_cqi_rank2_2A_5MHz_NB_IoT *)o)->pmi;
+      //this translates the 2-layer PMI into a single layer PMI for the first codeword
+      //the PMI for the second codeword will be stats->DL_pmi_single^0x1555
+      stats->DL_pmi_single = 0;
+      for (i=0;i<7;i++)
+	stats->DL_pmi_single = stats->DL_pmi_single | (((stats->DL_pmi_dual&(1<i))>>i)*2)<<2*i;  
+      break;
+
+    case HLC_subband_cqi_nopmi_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_nopmi_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],((HLC_subband_cqi_nopmi_5MHz_NB_IoT *)o)->diffcqi1);
+      break;
+
+    case HLC_subband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank1_2A_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank1_2A_5MHz_NB_IoT *)o)->diffcqi1));
+      stats->DL_pmi_single = ((HLC_subband_cqi_rank1_2A_5MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank2_2A_5MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((HLC_subband_cqi_rank2_2A_5MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank2_2A_5MHz_NB_IoT *)o)->diffcqi1));
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[1],stats->DL_cqi[1],(((HLC_subband_cqi_rank2_2A_5MHz_NB_IoT *)o)->diffcqi2));
+      stats->DL_pmi_dual   = ((HLC_subband_cqi_rank2_2A_5MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_mcs_CBA_NB_IoT:
+      if ((*crnti == ((HLC_subband_cqi_mcs_CBA_5MHz_NB_IoT *)o)->crnti) && (*crnti !=0)) {
+        *access_mode=CBA_ACCESS;
+        LOG_N(PHY,"[eNB] UCI for CBA : mcs %d  crnti %x\n",
+              ((HLC_subband_cqi_mcs_CBA_5MHz_NB_IoT *)o)->mcs, ((HLC_subband_cqi_mcs_CBA_5MHz_NB_IoT *)o)->crnti);
+      } else {
+        LOG_D(PHY,"[eNB] UCI for CBA : rnti (enb context %x, rx uci %x) invalid, unknown access\n",
+              *crnti, ((HLC_subband_cqi_mcs_CBA_5MHz_NB_IoT *)o)->crnti);
+      }
+
+      break;
+
+    case unknown_cqi_NB_IoT:
+    default:
+      LOG_N(PHY,"[eNB][UCI] received unknown uci (rb %d)\n",N_RB_DL);
+      break;
+    }
+
+    break;
+
+  case 50:
+    switch(uci_format) {
+    case wideband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank1_2A_10MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_pmi_single = ((wideband_cqi_rank1_2A_10MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case wideband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank2_2A_10MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((wideband_cqi_rank2_2A_10MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      stats->DL_pmi_dual   = ((wideband_cqi_rank2_2A_10MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_nopmi_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_nopmi_10MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],((HLC_subband_cqi_nopmi_10MHz_NB_IoT *)o)->diffcqi1);
+      break;
+
+    case HLC_subband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank1_2A_10MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank1_2A_10MHz_NB_IoT *)o)->diffcqi1));
+      stats->DL_pmi_single = ((HLC_subband_cqi_rank1_2A_10MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank2_2A_10MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((HLC_subband_cqi_rank2_2A_10MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank2_2A_10MHz_NB_IoT *)o)->diffcqi1));
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[1],stats->DL_cqi[1],(((HLC_subband_cqi_rank2_2A_10MHz_NB_IoT *)o)->diffcqi2));
+      stats->DL_pmi_dual   = ((HLC_subband_cqi_rank2_2A_10MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_mcs_CBA_NB_IoT:
+      if ((*crnti == ((HLC_subband_cqi_mcs_CBA_10MHz_NB_IoT *)o)->crnti) && (*crnti !=0)) {
+        *access_mode=CBA_ACCESS;
+        LOG_N(PHY,"[eNB] UCI for CBA : mcs %d  crnti %x\n",
+              ((HLC_subband_cqi_mcs_CBA_10MHz_NB_IoT *)o)->mcs, ((HLC_subband_cqi_mcs_CBA_10MHz_NB_IoT *)o)->crnti);
+      } else {
+        LOG_D(PHY,"[eNB] UCI for CBA : rnti (enb context %x, rx uci %x) invalid, unknown access\n",
+              *crnti, ((HLC_subband_cqi_mcs_CBA_10MHz_NB_IoT *)o)->crnti);
+      }
+
+      break;
+
+    case unknown_cqi_NB_IoT:
+    default:
+      LOG_N(PHY,"[eNB][UCI] received unknown uci (RB %d)\n",N_RB_DL);
+      break;
+    }
+
+    break;
+
+  case 100:
+    switch(uci_format) {
+    case wideband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank1_2A_20MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_pmi_single = ((wideband_cqi_rank1_2A_20MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case wideband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((wideband_cqi_rank2_2A_20MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((wideband_cqi_rank2_2A_20MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      stats->DL_pmi_dual   = ((wideband_cqi_rank2_2A_20MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_nopmi_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_nopmi_20MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],((HLC_subband_cqi_nopmi_20MHz_NB_IoT *)o)->diffcqi1);
+      break;
+
+    case HLC_subband_cqi_rank1_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank1_2A_20MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank1_2A_20MHz_NB_IoT *)o)->diffcqi1));
+      stats->DL_pmi_single = ((HLC_subband_cqi_rank1_2A_20MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_rank2_2A_NB_IoT:
+      stats->DL_cqi[0]     = (((HLC_subband_cqi_rank2_2A_20MHz_NB_IoT *)o)->cqi1);
+
+      if (stats->DL_cqi[0] > 24)
+        stats->DL_cqi[0] = 24;
+
+      stats->DL_cqi[1]     = (((HLC_subband_cqi_rank2_2A_20MHz_NB_IoT *)o)->cqi2);
+
+      if (stats->DL_cqi[1] > 24)
+        stats->DL_cqi[1] = 24;
+
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[0],stats->DL_cqi[0],(((HLC_subband_cqi_rank2_2A_20MHz_NB_IoT *)o)->diffcqi1));
+      do_diff_cqi_NB_IoT(N_RB_DL,stats->DL_subband_cqi[1],stats->DL_cqi[1],(((HLC_subband_cqi_rank2_2A_20MHz_NB_IoT *)o)->diffcqi2));
+      stats->DL_pmi_dual   = ((HLC_subband_cqi_rank2_2A_20MHz_NB_IoT *)o)->pmi;
+      break;
+
+    case HLC_subband_cqi_mcs_CBA_NB_IoT:
+      if ((*crnti == ((HLC_subband_cqi_mcs_CBA_20MHz_NB_IoT *)o)->crnti) && (*crnti !=0)) {
+        *access_mode=CBA_ACCESS;
+        LOG_N(PHY,"[eNB] UCI for CBA : mcs %d  crnti %x\n",
+              ((HLC_subband_cqi_mcs_CBA_20MHz_NB_IoT *)o)->mcs, ((HLC_subband_cqi_mcs_CBA_20MHz_NB_IoT *)o)->crnti);
+      } else {
+        LOG_D(PHY,"[eNB] UCI for CBA : rnti (enb context %x, rx uci %x) invalid, unknown access\n",
+              *crnti, ((HLC_subband_cqi_mcs_CBA_20MHz_NB_IoT *)o)->crnti);
+      }
+
+      break;
+
+    case unknown_cqi_NB_IoT:
+    default:
+      LOG_N(PHY,"[eNB][UCI] received unknown uci (RB %d)\n",N_RB_DL);
+      break;
+    }
+
+    break;
+
+  default:
+    LOG_N(PHY,"[eNB][UCI] unknown RB %d\n",N_RB_DL);
+    break;
+  }
+
+
+}
+
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
index 51a9d1e9469d8862088c2d17fb9fe32640d2e8a1..2b6e5b46202e8846894a898aaa53670fa91d2758 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding.c
@@ -164,6 +164,86 @@ LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uin
   return(NULL);
 }
 
+/*
+NB_IoT_eNB_NULSCH_t *new_eNB_ulsch_NB(uint8_t abstraction_flag)
+{
+
+	NB_IoT_eNB_NULSCH_t *ulsch;
+  uint8_t exit_flag = 0,i,r;
+  unsigned char bw_scaling =1;
+
+//  switch (N_RB_UL) {
+//  case 6:
+//    bw_scaling =16;
+//    break;
+//
+//  case 25:
+//    bw_scaling =4;
+//    break;
+//
+//  case 50:
+//    bw_scaling =2;
+//    break;
+//
+//  default:
+//    bw_scaling =1;
+//    break;
+//  }
+
+  ulsch = (NB_IoT_eNB_NULSCH_t *)malloc16(sizeof(NB_IoT_eNB_NULSCH_t));
+
+  if (ulsch) {
+    memset(ulsch,0,sizeof(LTE_eNB_ULSCH_t));
+    //MP: add some parameters in npusch structure for convolutional coding to be set
+    ulsch->Mlimit = 4;
+
+
+      ulsch->harq_process = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t));
+
+      if (ulsch->harq_process) {
+        memset(ulsch->harq_process,0,sizeof(LTE_UL_eNB_HARQ_t));
+        ulsch->harq_process->b = (uint8_t*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
+
+        if (ulsch->harq_process->b)
+          memset(ulsch->harq_process->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
+        else
+          exit_flag=3;
+
+        if (abstraction_flag==0) {
+          for (r=0; r<MAX_NUM_ULSCH_SEGMENTS/bw_scaling; r++) {
+            ulsch->harq_process->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+768);
+            if (ulsch->harq_process->c[r])
+              memset(ulsch->harq_process->c[r],0,((r==0)?8:0) + 3+768);
+            else
+              exit_flag=2;
+
+            ulsch->harq_process->d[r] = (short*)malloc16(((3*8*6144)+12+96)*sizeof(short));
+
+            if (ulsch->harq_process->d[r])
+              memset(ulsch->harq_process->d[r],0,((3*8*6144)+12+96)*sizeof(short));
+            else
+              exit_flag=2;
+          }
+
+          ulsch->harq_process->subframe_scheduling_flag = 0;
+        }
+      } else {
+        exit_flag=1;
+      }
+
+
+    if (exit_flag==0)
+      return(ulsch);
+  }
+
+  LOG_E(PHY,"new_ue_ulsch: exit_flag = %d\n",exit_flag);
+  free_eNB_ulsch(ulsch);
+
+  return(NULL);
+}
+
+*/
+
 void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch)
 {
 
@@ -212,7 +292,7 @@ uint8_t extract_cqi_crc(uint8_t *cqi,uint8_t CQI_LENGTH)
 
 
 
-
+/*
 int ulsch_decoding_data_2thread0(td_params* tdp) {
 
   PHY_VARS_eNB *eNB = tdp->eNB;
@@ -648,6 +728,7 @@ int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr
 
   return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret );
 }
+*/
 
 int ulsch_decoding_data(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) {
 
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_decoding_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..271bd51ff68a2055dc5e43488d6226332435b4b5
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_decoding_NB_IoT.c
@@ -0,0 +1,2193 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/ulsch_decoding.c
+* \brief Top-level routines for decoding  the ULSCH transport channel from 36.212 V8.6 2009-03
+* \author R. Knopp
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: knopp@eurecom.fr
+* \note
+* \warning
+*/
+
+//#include "defs.h"
+
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/extern_NB_IoT.h"
+#include "PHY/LTE_TRANSPORT/vars_NB_IoT.h"
+#include "PHY/CODING/defs_NB_IoT.h"
+//#include "PHY/CODING/extern.h"
+//#include "extern_NB_IoT.h"
+//#include "SCHED/extern.h"
+/*
+#ifdef OPENAIR2
+#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/extern_NB_IoT.h"
+#include "RRC/LITE/extern.h"
+#include "PHY_INTERFACE/extern.h"
+#endif
+
+#ifdef PHY_ABSTRACTION
+#include "UTIL/OCG/OCG.h"
+#include "UTIL/OCG/OCG_extern.h"
+#endif
+*/
+#include "UTIL/LOG/vcd_signal_dumper.h"
+//#define DEBUG_ULSCH_DECODING
+/*
+void free_eNB_ulsch(LTE_eNB_ULSCH_t *ulsch)
+{
+
+  int i,r;
+
+  if (ulsch) {
+    for (i=0; i<8; i++) {
+      if (ulsch->harq_processes[i]) {
+        if (ulsch->harq_processes[i]->b) {
+          free16(ulsch->harq_processes[i]->b,MAX_ULSCH_PAYLOAD_BYTES);
+          ulsch->harq_processes[i]->b = NULL;
+        }
+
+        for (r=0; r<MAX_NUM_ULSCH_SEGMENTS; r++) {
+          free16(ulsch->harq_processes[i]->c[r],((r==0)?8:0) + 768);
+          ulsch->harq_processes[i]->c[r] = NULL;
+        }
+
+        for (r=0; r<MAX_NUM_ULSCH_SEGMENTS; r++)
+          if (ulsch->harq_processes[i]->d[r]) {
+            free16(ulsch->harq_processes[i]->d[r],((3*8*6144)+12+96)*sizeof(short));
+            ulsch->harq_processes[i]->d[r] = NULL;
+          }
+
+        free16(ulsch->harq_processes[i],sizeof(LTE_UL_eNB_HARQ_t));
+        ulsch->harq_processes[i] = NULL;
+      }
+    }
+
+    free16(ulsch,sizeof(LTE_eNB_ULSCH_t));
+    ulsch = NULL;
+  }
+}
+
+LTE_eNB_ULSCH_t *new_eNB_ulsch(uint8_t max_turbo_iterations,uint8_t N_RB_UL, uint8_t abstraction_flag)
+{
+
+  LTE_eNB_ULSCH_t *ulsch;
+  uint8_t exit_flag = 0,i,r;
+  unsigned char bw_scaling =1;
+
+  switch (N_RB_UL) {
+  case 6:
+    bw_scaling =16;
+    break;
+
+  case 25:
+    bw_scaling =4;
+    break;
+
+  case 50:
+    bw_scaling =2;
+    break;
+
+  default:
+    bw_scaling =1;
+    break;
+  }
+
+  ulsch = (LTE_eNB_ULSCH_t *)malloc16(sizeof(LTE_eNB_ULSCH_t));
+
+  if (ulsch) {
+    memset(ulsch,0,sizeof(LTE_eNB_ULSCH_t));
+    ulsch->max_turbo_iterations = max_turbo_iterations;
+    ulsch->Mlimit = 4;
+
+    for (i=0; i<8; i++) {
+      //      printf("new_ue_ulsch: Harq process %d\n",i);
+      ulsch->harq_processes[i] = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t));
+
+      if (ulsch->harq_processes[i]) {
+        memset(ulsch->harq_processes[i],0,sizeof(LTE_UL_eNB_HARQ_t));
+        ulsch->harq_processes[i]->b = (uint8_t*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
+
+        if (ulsch->harq_processes[i]->b)
+          memset(ulsch->harq_processes[i]->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
+        else
+          exit_flag=3;
+
+        if (abstraction_flag==0) {
+          for (r=0; r<MAX_NUM_ULSCH_SEGMENTS/bw_scaling; r++) {
+            ulsch->harq_processes[i]->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+768);
+            if (ulsch->harq_processes[i]->c[r])
+              memset(ulsch->harq_processes[i]->c[r],0,((r==0)?8:0) + 3+768);
+            else
+              exit_flag=2;
+
+            ulsch->harq_processes[i]->d[r] = (short*)malloc16(((3*8*6144)+12+96)*sizeof(short));
+
+            if (ulsch->harq_processes[i]->d[r])
+              memset(ulsch->harq_processes[i]->d[r],0,((3*8*6144)+12+96)*sizeof(short));
+            else
+              exit_flag=2;
+          }
+
+          ulsch->harq_processes[i]->subframe_scheduling_flag = 0;
+        }
+      } else {
+        exit_flag=1;
+      }
+    }
+
+    if (exit_flag==0)
+      return(ulsch);
+  }
+
+  LOG_E(PHY,"new_ue_ulsch: exit_flag = %d\n",exit_flag);
+  free_eNB_ulsch(ulsch);
+
+  return(NULL);
+}
+
+///
+NB_IoT_eNB_NULSCH_t *new_eNB_ulsch_NB(uint8_t abstraction_flag)
+{
+
+	NB_IoT_eNB_NULSCH_t *ulsch;
+  uint8_t exit_flag = 0,i,r;
+  unsigned char bw_scaling =1;
+
+//  switch (N_RB_UL) {
+//  case 6:
+//    bw_scaling =16;
+//    break;
+//
+//  case 25:
+//    bw_scaling =4;
+//    break;
+//
+//  case 50:
+//    bw_scaling =2;
+//    break;
+//
+//  default:
+//    bw_scaling =1;
+//    break;
+//  }
+
+  ulsch = (NB_IoT_eNB_NULSCH_t *)malloc16(sizeof(NB_IoT_eNB_NULSCH_t));
+
+  if (ulsch) {
+    memset(ulsch,0,sizeof(LTE_eNB_ULSCH_t));
+    //MP: add some parameters in npusch structure for convolutional coding to be set
+    ulsch->Mlimit = 4;
+
+
+      ulsch->harq_process = (LTE_UL_eNB_HARQ_t *)malloc16(sizeof(LTE_UL_eNB_HARQ_t));
+
+      if (ulsch->harq_process) {
+        memset(ulsch->harq_process,0,sizeof(LTE_UL_eNB_HARQ_t));
+        ulsch->harq_process->b = (uint8_t*)malloc16(MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
+
+        if (ulsch->harq_process->b)
+          memset(ulsch->harq_process->b,0,MAX_ULSCH_PAYLOAD_BYTES/bw_scaling);
+        else
+          exit_flag=3;
+
+        if (abstraction_flag==0) {
+          for (r=0; r<MAX_NUM_ULSCH_SEGMENTS/bw_scaling; r++) {
+            ulsch->harq_process->c[r] = (uint8_t*)malloc16(((r==0)?8:0) + 3+768);
+            if (ulsch->harq_process->c[r])
+              memset(ulsch->harq_process->c[r],0,((r==0)?8:0) + 3+768);
+            else
+              exit_flag=2;
+
+            ulsch->harq_process->d[r] = (short*)malloc16(((3*8*6144)+12+96)*sizeof(short));
+
+            if (ulsch->harq_process->d[r])
+              memset(ulsch->harq_process->d[r],0,((3*8*6144)+12+96)*sizeof(short));
+            else
+              exit_flag=2;
+          }
+
+          ulsch->harq_process->subframe_scheduling_flag = 0;
+        }
+      } else {
+        exit_flag=1;
+      }
+
+
+    if (exit_flag==0)
+      return(ulsch);
+  }
+
+  LOG_E(PHY,"new_ue_ulsch: exit_flag = %d\n",exit_flag);
+  free_eNB_ulsch(ulsch);
+
+  return(NULL);
+}
+
+
+
+void clean_eNb_ulsch(LTE_eNB_ULSCH_t *ulsch)
+{
+
+  unsigned char i;
+
+  //ulsch = (LTE_eNB_ULSCH_t *)malloc16(sizeof(LTE_eNB_ULSCH_t));
+  if (ulsch) {
+    ulsch->rnti = 0;
+
+    for (i=0; i<8; i++) {
+      if (ulsch->harq_processes[i]) {
+        //    ulsch->harq_processes[i]->Ndi = 0;
+        ulsch->harq_processes[i]->status = 0;
+        ulsch->harq_processes[i]->subframe_scheduling_flag = 0;
+        //ulsch->harq_processes[i]->phich_active = 0; //this will be done later after transmission of PHICH
+        ulsch->harq_processes[i]->phich_ACK = 0;
+        ulsch->harq_processes[i]->round = 0;
+      }
+    }
+
+  }
+}
+*/
+
+uint8_t extract_cqi_crc_NB_IoT(uint8_t *cqi,uint8_t CQI_LENGTH)
+{
+
+  uint8_t crc;
+
+  crc = cqi[CQI_LENGTH>>3];
+  //  printf("crc1: %x, shift %d\n",crc,CQI_LENGTH&0x7);
+  crc = (crc<<(CQI_LENGTH&0x7));
+  // clear crc bits
+  //  ((char *)cqi)[CQI_LENGTH>>3] &= 0xff>>(8-(CQI_LENGTH&0x7));
+  //  printf("crc2: %x, cqi0 %x\n",crc,cqi[1+(CQI_LENGTH>>3)]);
+  crc |= (cqi[1+(CQI_LENGTH>>3)])>>(8-(CQI_LENGTH&0x7));
+  // clear crc bits
+  //(((char *)cqi)[1+(CQI_LENGTH>>3)]) = 0;
+
+  //  printf("crc : %x\n",crc);
+  return(crc);
+
+}
+
+/*
+
+
+
+
+int ulsch_decoding_data_2thread0(td_params* tdp) {
+
+  PHY_VARS_eNB *eNB = tdp->eNB;
+  int UE_id         = tdp->UE_id;
+  int harq_pid      = tdp->harq_pid;
+  int llr8_flag     = tdp->llr8_flag;
+
+  unsigned int r,r_offset=0,Kr,Kr_bytes,iind;
+  uint8_t crc_type;
+  int offset = 0;
+  int ret = 1;
+  int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
+  LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
+  LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
+  int Q_m = get_Qm_ul(ulsch_harq->mcs);
+  int G = ulsch_harq->G;
+  uint32_t E;
+  uint32_t Gp,GpmodC,Nl=1;
+  uint32_t C = ulsch_harq->C;
+
+  uint8_t (*tc)(int16_t *y,
+                uint8_t *,
+                uint16_t,
+                uint16_t,
+                uint16_t,
+                uint8_t,
+                uint8_t,
+                uint8_t,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *);
+
+  if (llr8_flag == 0)
+    tc = phy_threegpplte_turbo_decoder16;
+  else
+    tc = phy_threegpplte_turbo_decoder8;
+
+
+
+  // go through first half of segments to get r_offset
+  for (r=0; r<(ulsch_harq->C/2); r++) {
+
+    // Get Turbo interleaver parameters
+    if (r<ulsch_harq->Cminus)
+      Kr = ulsch_harq->Kminus;
+    else
+      Kr = ulsch_harq->Kplus;
+
+    Kr_bytes = Kr>>3;
+
+    if (Kr_bytes<=64)
+      iind = (Kr_bytes-5);
+    else if (Kr_bytes <=128)
+      iind = 59 + ((Kr_bytes-64)>>1);
+    else if (Kr_bytes <= 256)
+      iind = 91 + ((Kr_bytes-128)>>2);
+    else if (Kr_bytes <= 768)
+      iind = 123 + ((Kr_bytes-256)>>3);
+    else {
+      LOG_E(PHY,"ulsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
+      return(-1);
+    }
+
+    // This is stolen from rate-matching algorithm to get the value of E
+    
+    Gp = G/Nl/Q_m;
+    GpmodC = Gp%C;
+    
+    if (r < (C-(GpmodC)))
+      E = Nl*Q_m * (Gp/C);
+    else
+      E = Nl*Q_m * ((GpmodC==0?0:1) + (Gp/C));
+    
+    r_offset += E;
+
+    if (r==0) {
+      offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0);
+    } else {
+      offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
+    }
+  }
+
+  // go through second half of segments
+  for (; r<(ulsch_harq->C); r++) {
+
+
+    //    printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]);
+    // Get Turbo interleaver parameters
+    if (r<ulsch_harq->Cminus)
+      Kr = ulsch_harq->Kminus;
+    else
+      Kr = ulsch_harq->Kplus;
+
+    Kr_bytes = Kr>>3;
+
+    if (Kr_bytes<=64)
+      iind = (Kr_bytes-5);
+    else if (Kr_bytes <=128)
+      iind = 59 + ((Kr_bytes-64)>>1);
+    else if (Kr_bytes <= 256)
+      iind = 91 + ((Kr_bytes-128)>>2);
+    else if (Kr_bytes <= 768)
+      iind = 123 + ((Kr_bytes-256)>>3);
+    else {
+      LOG_E(PHY,"ulsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
+      return(-1);
+    }
+
+#ifdef DEBUG_ULSCH_DECODING
+    printf("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0);
+#endif
+
+    memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
+    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
+                                          (uint8_t*)&dummy_w[r][0],
+                                          (r==0) ? ulsch_harq->F : 0);
+
+#ifdef DEBUG_ULSCH_DECODING
+    printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n",
+        r, G,
+        Kr*3,
+        Q_m,
+        nb_rb,
+        ulsch_harq->Nl);
+#endif
+
+
+    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
+                                   G,
+                                   ulsch_harq->w[r],
+                                   (uint8_t*) &dummy_w[r][0],
+                                   ulsch_harq->e+r_offset,
+                                   ulsch_harq->C,
+                                   NSOFT,
+                                   0,   //Uplink
+                                   1,
+                                   ulsch_harq->rvidx,
+                                   (ulsch_harq->round==0)?1:0,  // clear
+                                   get_Qm_ul(ulsch_harq->mcs),
+                                   1,
+                                   r,
+                                   &E)==-1) {
+      LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
+      return(-1);
+    }
+
+    r_offset += E;
+
+    sub_block_deinterleaving_turbo(4+Kr,
+                                   &ulsch_harq->d[r][96],
+                                   ulsch_harq->w[r]);
+
+    if (ulsch_harq->C == 1)
+      crc_type = CRC24_A;
+    else
+      crc_type = CRC24_B;
+    
+    
+    ret = tc(&ulsch_harq->d[r][96],
+	     ulsch_harq->c[r],
+	     Kr,
+	     f1f2mat_old[iind*2],
+	     f1f2mat_old[(iind*2)+1],
+	     ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS,
+	     crc_type,
+	     (r==0) ? ulsch_harq->F : 0,
+	     &eNB->ulsch_tc_init_stats,
+	     &eNB->ulsch_tc_alpha_stats,
+	     &eNB->ulsch_tc_beta_stats,
+	     &eNB->ulsch_tc_gamma_stats,
+	     &eNB->ulsch_tc_ext_stats,
+	     &eNB->ulsch_tc_intl1_stats,
+	     &eNB->ulsch_tc_intl2_stats);
+    
+    // Reassembly of Transport block here
+
+    if (ret != (1+ulsch->max_turbo_iterations)) {
+      if (r<ulsch_harq->Cminus)
+	Kr = ulsch_harq->Kminus;
+      else
+	Kr = ulsch_harq->Kplus;
+      
+      Kr_bytes = Kr>>3;
+      
+      memcpy(ulsch_harq->b+offset,
+	     ulsch_harq->c[r],
+	     Kr_bytes - ((ulsch_harq->C>1)?3:0));
+      offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
+      
+      
+    } else {
+      break;
+    }
+    
+  }
+
+  return(ret);
+}
+
+extern int oai_exit;
+void *td_thread(void *param) {
+  pthread_setname_np( pthread_self(), "td processing");
+  PHY_VARS_eNB *eNB = ((td_params*)param)->eNB;
+  eNB_proc_t *proc  = &eNB->proc;
+
+  while (!oai_exit) {
+
+    if (wait_on_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread")<0) break;  
+
+    ((td_params*)param)->ret = ulsch_decoding_data_2thread0((td_params*)param);
+
+    if (release_thread(&proc->mutex_td,&proc->instance_cnt_td,"td thread")<0) break;
+
+    if (pthread_cond_signal(&proc->cond_td) != 0) {
+      printf("[eNB] ERROR pthread_cond_signal for td thread exit\n");
+      exit_fun( "ERROR pthread_cond_signal" );
+      return(NULL);
+    }
+  }
+
+  return(NULL);
+}
+
+int ulsch_decoding_data_2thread(PHY_VARS_eNB *eNB,int UE_id,int harq_pid,int llr8_flag) {
+
+  eNB_proc_t *proc = &eNB->proc;
+  unsigned int r,r_offset=0,Kr,Kr_bytes,iind;
+  uint8_t crc_type;
+  int offset = 0;
+  int ret = 1;
+  int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
+  LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
+  LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
+  //int Q_m = get_Qm_ul(ulsch_harq->mcs);
+  int G = ulsch_harq->G;
+  unsigned int E;
+  int Cby2;
+
+  uint8_t (*tc)(int16_t *y,
+                uint8_t *,
+                uint16_t,
+                uint16_t,
+                uint16_t,
+                uint8_t,
+                uint8_t,
+                uint8_t,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *);
+
+  struct timespec wait;
+
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+
+  if (llr8_flag == 0)
+    tc = phy_threegpplte_turbo_decoder16;
+  else
+    tc = phy_threegpplte_turbo_decoder8;
+
+  if (ulsch_harq->C>1) { // wakeup worker if more than 1 segment
+    if (pthread_mutex_timedlock(&proc->mutex_td,&wait) != 0) {
+      printf("[eNB] ERROR pthread_mutex_lock for TD thread (IC %d)\n", proc->instance_cnt_td);
+      exit_fun( "error locking mutex_fep" );
+      return -1;
+    }
+    
+    if (proc->instance_cnt_td==0) {
+      printf("[eNB] TD thread busy\n");
+      exit_fun("TD thread busy");
+      pthread_mutex_unlock( &proc->mutex_td );
+      return -1;
+    }
+    
+    ++proc->instance_cnt_td;
+    
+    proc->tdp.eNB       = eNB;
+    proc->tdp.UE_id     = UE_id;
+    proc->tdp.harq_pid  = harq_pid;
+    proc->tdp.llr8_flag = llr8_flag;
+    
+    
+    // wakeup worker to do second half segments 
+    if (pthread_cond_signal(&proc->cond_td) != 0) {
+      printf("[eNB] ERROR pthread_cond_signal for td thread exit\n");
+      exit_fun( "ERROR pthread_cond_signal" );
+      return (1+ulsch->max_turbo_iterations);
+    }
+
+    pthread_mutex_unlock( &proc->mutex_td );
+    Cby2 = ulsch_harq->C/2;
+  }
+  else {
+    Cby2 = 1;
+  }
+
+  // go through first half of segments in main thread
+  for (r=0; r<Cby2; r++) {
+
+    //    printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]);
+    // Get Turbo interleaver parameters
+    if (r<ulsch_harq->Cminus)
+      Kr = ulsch_harq->Kminus;
+    else
+      Kr = ulsch_harq->Kplus;
+
+    Kr_bytes = Kr>>3;
+
+    if (Kr_bytes<=64)
+      iind = (Kr_bytes-5);
+    else if (Kr_bytes <=128)
+      iind = 59 + ((Kr_bytes-64)>>1);
+    else if (Kr_bytes <= 256)
+      iind = 91 + ((Kr_bytes-128)>>2);
+    else if (Kr_bytes <= 768)
+      iind = 123 + ((Kr_bytes-256)>>3);
+    else {
+      LOG_E(PHY,"ulsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
+      return(-1);
+    }
+
+#ifdef DEBUG_ULSCH_DECODING
+    printf("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0);
+#endif
+
+    memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
+    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
+                                          (uint8_t*)&dummy_w[r][0],
+                                          (r==0) ? ulsch_harq->F : 0);
+
+#ifdef DEBUG_ULSCH_DECODING
+    printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n",
+        r, G,
+        Kr*3,
+        Q_m,
+        nb_rb,
+        ulsch_harq->Nl);
+#endif
+
+    start_meas(&eNB->ulsch_rate_unmatching_stats);
+
+    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
+                                   G,
+                                   ulsch_harq->w[r],
+                                   (uint8_t*) &dummy_w[r][0],
+                                   ulsch_harq->e+r_offset,
+                                   ulsch_harq->C,
+                                   NSOFT,
+                                   0,   //Uplink
+                                   1,
+                                   ulsch_harq->rvidx,
+                                   (ulsch_harq->round==0)?1:0,  // clear
+                                   get_Qm_ul(ulsch_harq->mcs),
+                                   1,
+                                   r,
+                                   &E)==-1) {
+      LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
+      return(-1);
+    }
+
+    stop_meas(&eNB->ulsch_rate_unmatching_stats);
+    r_offset += E;
+
+    start_meas(&eNB->ulsch_deinterleaving_stats);
+    sub_block_deinterleaving_turbo(4+Kr,
+                                   &ulsch_harq->d[r][96],
+                                   ulsch_harq->w[r]);
+    stop_meas(&eNB->ulsch_deinterleaving_stats);
+
+    if (ulsch_harq->C == 1)
+      crc_type = CRC24_A;
+    else
+      crc_type = CRC24_B;
+
+    start_meas(&eNB->ulsch_turbo_decoding_stats);
+    
+    ret = tc(&ulsch_harq->d[r][96],
+	     ulsch_harq->c[r],
+	     Kr,
+	     f1f2mat_old[iind*2],
+	     f1f2mat_old[(iind*2)+1],
+	     ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS,
+	     crc_type,
+	     (r==0) ? ulsch_harq->F : 0,
+	     &eNB->ulsch_tc_init_stats,
+	     &eNB->ulsch_tc_alpha_stats,
+	     &eNB->ulsch_tc_beta_stats,
+	     &eNB->ulsch_tc_gamma_stats,
+	     &eNB->ulsch_tc_ext_stats,
+	     &eNB->ulsch_tc_intl1_stats,
+	     &eNB->ulsch_tc_intl2_stats);
+
+  // Reassembly of Transport block here
+
+    if (ret != (1+ulsch->max_turbo_iterations)) {
+      if (r<ulsch_harq->Cminus)
+	Kr = ulsch_harq->Kminus;
+      else
+	Kr = ulsch_harq->Kplus;
+      
+      Kr_bytes = Kr>>3;
+      
+      if (r==0) {
+	memcpy(ulsch_harq->b,
+	       &ulsch_harq->c[0][(ulsch_harq->F>>3)],
+	       Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0));
+	offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0);
+      } else {
+	memcpy(ulsch_harq->b+offset,
+	       ulsch_harq->c[r],
+	       Kr_bytes - ((ulsch_harq->C>1)?3:0));
+	offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
+      }
+      
+    } else {
+      break;
+    }
+    stop_meas(&eNB->ulsch_turbo_decoding_stats);    
+  }
+
+   // wait for worker to finish
+
+  wait_on_busy_condition(&proc->mutex_td,&proc->cond_td,&proc->instance_cnt_td,"td thread");  
+
+  return( (ret>proc->tdp.ret) ? ret : proc->tdp.ret );
+}
+*/
+/*
+// NB_IoT: functions in ulsch_decoding_data_NB_IoT must be defined
+
+int ulsch_decoding_data_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,int UE_id,int harq_pid,int llr8_flag) {
+
+  unsigned int r,r_offset=0,Kr,Kr_bytes,iind;
+  uint8_t crc_type;
+  int offset = 0;
+  int ret = 1;
+  int16_t dummy_w[MAX_NUM_ULSCH_SEGMENTS][3*(6144+64)];
+  LTE_eNB_ULSCH_t *ulsch = eNB->ulsch[UE_id];
+  LTE_UL_eNB_HARQ_t *ulsch_harq = ulsch->harq_processes[harq_pid];
+  //int Q_m = get_Qm_ul(ulsch_harq->mcs);
+  int G = ulsch_harq->G;
+  unsigned int E;
+
+  uint8_t (*tc)(int16_t *y,
+                uint8_t *,
+                uint16_t,
+                uint16_t,
+                uint16_t,
+                uint8_t,
+                uint8_t,
+                uint8_t,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *,
+                time_stats_t *);
+
+  if (llr8_flag == 0)
+    tc = phy_threegpplte_turbo_decoder16;
+  else
+    tc = phy_threegpplte_turbo_decoder8;
+
+
+  for (r=0; r<ulsch_harq->C; r++) {
+
+    //    printf("before subblock deinterleaving c[%d] = %p\n",r,ulsch_harq->c[r]);
+    // Get Turbo interleaver parameters
+    if (r<ulsch_harq->Cminus)
+      Kr = ulsch_harq->Kminus;
+    else
+      Kr = ulsch_harq->Kplus;
+
+    Kr_bytes = Kr>>3;
+
+    if (Kr_bytes<=64)
+      iind = (Kr_bytes-5);
+    else if (Kr_bytes <=128)
+      iind = 59 + ((Kr_bytes-64)>>1);
+    else if (Kr_bytes <= 256)
+      iind = 91 + ((Kr_bytes-128)>>2);
+    else if (Kr_bytes <= 768)
+      iind = 123 + ((Kr_bytes-256)>>3);
+    else {
+      LOG_E(PHY,"ulsch_decoding: Illegal codeword size %d!!!\n",Kr_bytes);
+      return(-1);
+    }
+
+#ifdef DEBUG_ULSCH_DECODING
+    printf("f1 %d, f2 %d, F %d\n",f1f2mat_old[2*iind],f1f2mat_old[1+(2*iind)],(r==0) ? ulsch_harq->F : 0);
+#endif
+
+    memset(&dummy_w[r][0],0,3*(6144+64)*sizeof(short));
+    ulsch_harq->RTC[r] = generate_dummy_w(4+(Kr_bytes*8),
+                                          (uint8_t*)&dummy_w[r][0],
+                                          (r==0) ? ulsch_harq->F : 0);
+
+#ifdef DEBUG_ULSCH_DECODING
+    printf("Rate Matching Segment %d (coded bits (G) %d,unpunctured/repeated bits %d, Q_m %d, nb_rb %d, Nl %d)...\n",
+        r, G,
+        Kr*3,
+        Q_m,
+        nb_rb,
+        ulsch_harq->Nl);
+#endif
+
+    start_meas(&eNB->ulsch_rate_unmatching_stats);
+
+    if (lte_rate_matching_turbo_rx(ulsch_harq->RTC[r],
+                                   G,
+                                   ulsch_harq->w[r],
+                                   (uint8_t*) &dummy_w[r][0],
+                                   ulsch_harq->e+r_offset,
+                                   ulsch_harq->C,
+                                   NSOFT,
+                                   0,   //Uplink
+                                   1,
+                                   ulsch_harq->rvidx,
+                                   (ulsch_harq->round==0)?1:0,  // clear
+                                   get_Qm_ul(ulsch_harq->mcs),
+                                   1,
+                                   r,
+                                   &E)==-1) {
+      LOG_E(PHY,"ulsch_decoding.c: Problem in rate matching\n");
+      return(-1);
+    }
+
+    stop_meas(&eNB->ulsch_rate_unmatching_stats);
+    r_offset += E;
+
+    start_meas(&eNB->ulsch_deinterleaving_stats);
+    sub_block_deinterleaving_turbo(4+Kr,
+                                   &ulsch_harq->d[r][96],
+                                   ulsch_harq->w[r]);
+    stop_meas(&eNB->ulsch_deinterleaving_stats);
+
+    if (ulsch_harq->C == 1)
+      crc_type = CRC24_A;
+    else
+      crc_type = CRC24_B;
+   
+    start_meas(&eNB->ulsch_turbo_decoding_stats);
+    
+    ret = tc(&ulsch_harq->d[r][96],
+	     ulsch_harq->c[r],
+	     Kr,
+	     f1f2mat_old[iind*2],
+	     f1f2mat_old[(iind*2)+1],
+	     ulsch->max_turbo_iterations,//MAX_TURBO_ITERATIONS,
+	     crc_type,
+	     (r==0) ? ulsch_harq->F : 0,
+	     &eNB->ulsch_tc_init_stats,
+	     &eNB->ulsch_tc_alpha_stats,
+	     &eNB->ulsch_tc_beta_stats,
+	     &eNB->ulsch_tc_gamma_stats,
+	     &eNB->ulsch_tc_ext_stats,
+	     &eNB->ulsch_tc_intl1_stats,
+	     &eNB->ulsch_tc_intl2_stats);
+    
+    stop_meas(&eNB->ulsch_turbo_decoding_stats);
+    
+  // Reassembly of Transport block here
+
+    if (ret != (1+ulsch->max_turbo_iterations)) {
+      if (r<ulsch_harq->Cminus)
+	Kr = ulsch_harq->Kminus;
+      else
+	Kr = ulsch_harq->Kplus;
+      
+      Kr_bytes = Kr>>3;
+      
+      if (r==0) {
+	memcpy(ulsch_harq->b,
+	       &ulsch_harq->c[0][(ulsch_harq->F>>3)],
+	       Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0));
+	offset = Kr_bytes - (ulsch_harq->F>>3) - ((ulsch_harq->C>1)?3:0);
+      } else {
+	memcpy(ulsch_harq->b+offset,
+	       ulsch_harq->c[r],
+	       Kr_bytes - ((ulsch_harq->C>1)?3:0));
+	offset += (Kr_bytes- ((ulsch_harq->C>1)?3:0));
+      }
+      
+    } else {
+      break;
+    }
+    
+  }
+
+  return(ret);
+}
+
+*/
+
+// NB_IoT: functions in ulsch_decoding_data_NB_IoT must be defined :ulsch_decoding_data_NB_IoT (defined in this file)
+
+static inline unsigned int lte_gold_unscram_NB_IoT(unsigned int *x1, unsigned int *x2, unsigned char reset) __attribute__((always_inline));
+static inline unsigned int lte_gold_unscram_NB_IoT(unsigned int *x1, unsigned int *x2, unsigned char reset)
+{
+  int n;
+
+  if (reset) {
+    *x1 = 1+ (1<<31);
+    *x2=*x2 ^ ((*x2 ^ (*x2>>1) ^ (*x2>>2) ^ (*x2>>3))<<31);
+
+    // skip first 50 double words (1600 bits)
+    //      printf("n=0 : x1 %x, x2 %x\n",x1,x2);
+    for (n=1; n<50; n++) {
+      *x1 = (*x1>>1) ^ (*x1>>4);
+      *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
+      *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
+      *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
+    }
+  }
+
+  *x1 = (*x1>>1) ^ (*x1>>4);
+  *x1 = *x1 ^ (*x1<<31) ^ (*x1<<28);
+  *x2 = (*x2>>1) ^ (*x2>>2) ^ (*x2>>3) ^ (*x2>>4);
+  *x2 = *x2 ^ (*x2<<31) ^ (*x2<<30) ^ (*x2<<29) ^ (*x2<<28);
+  return(*x1^*x2);
+  //  printf("n=%d : c %x\n",n,x1^x2);
+
+}
+
+
+unsigned int  ulsch_decoding_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
+                                    eNB_rxtx_proc_NB_IoT_t  *proc,
+                                    uint8_t                 UE_id,
+                                    uint8_t                 control_only_flag,
+                                    uint8_t                 Nbundled,
+                                    uint8_t                 llr8_flag)
+{
+  //MAC_xface_NB_IoT *mac_xface_NB_IoT;  //test_xface
+
+  int16_t                 *ulsch_llr    = eNB->pusch_vars[UE_id]->llr;
+  NB_IoT_DL_FRAME_PARMS   *frame_parms  = &eNB->frame_parms;
+  NB_IoT_eNB_NULSCH_t     *ulsch        = eNB->ulsch[UE_id];
+  NB_IoT_UL_eNB_HARQ_t    *ulsch_harq;
+
+  uint8_t         harq_pid;
+  unsigned short  nb_rb;
+  unsigned int    A;
+  uint8_t         Q_m;
+  unsigned int    i,i2,j,j2;
+ // unsigned int    q;
+  int             iprime;
+  unsigned int    ret = 0;
+  int             r,Kr;
+
+ // uint8_t         *columnset;
+  unsigned int    sumKr=0;
+  //unsigned int    Qprime,L,O_RCC;
+  unsigned int    G,Q_CQI,Q_RI,H,Hprime,Hpp,Cmux,Rmux_prime;
+  
+  //unsigned int    Qprime_ACK,Qprime_RI,len_ACK=0,len_RI=0;
+
+ // int             metric,metric_new;
+  //uint8_t         o_flip[8];
+  uint32_t        x1, x2, s=0;
+  //int16_t         ys;
+  int16_t           c;
+  //uint32_t        wACK_idx;
+  //uint8_t         dummy_w_cc[3*(MAX_CQI_BITS+8+32)];
+  int16_t         y[6*14*1200] __attribute__((aligned(32)));
+  uint8_t         ytag[14*1200];
+  int16_t         cseq[6*14*1200];
+  //int             off;
+  int             subframe = proc->subframe_rx;
+
+  harq_pid = subframe2harq_pid_NB_IoT(frame_parms,proc->frame_rx,subframe);
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,1);
+
+  // x1 is set in lte_gold_generic
+  // x2 should not reinitialized each subframe
+  // x2 should be reinitialized according to 36.211 Sections 10.1.3.1 and 10.1.3.6
+  x2         =  ((uint32_t)ulsch->rnti<<14) + ((uint32_t)subframe<<9) + (((uint32_t)proc->frame_rx%2)<<13) + frame_parms->Nid_cell; //this is c_init in 36.211 Sec 6.3.1
+  ulsch_harq =  ulsch->harq_process;
+
+  if (harq_pid==255) {
+    LOG_E(PHY, "FATAL ERROR: illegal harq_pid, returning\n");
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0);
+    return -1;
+  }
+
+  if (ulsch_harq->Nsymb_pusch == 0) {
+      LOG_E(PHY, "FATAL ERROR: harq_pid %d, Nsymb 0!\n",harq_pid);
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0); 
+      return 1+ulsch->max_turbo_iterations;
+  }
+
+/* ----------------------- Segmentation */
+
+  nb_rb = ulsch_harq->nb_rb;  // nb_rb set but not used ??
+  A     = ulsch_harq->TBS;
+  Q_m   = get_Qm_ul_NB_IoT(ulsch_harq->mcs,ulsch_harq->N_sc_RU);
+  //G     = nb_rb * (12 * Q_m) * ulsch_harq->Nsymb_pusch;
+  G     = (ulsch_harq->N_sc_RU * Q_m) * ulsch_harq->Nsymb_UL * ulsch_harq->Nslot_UL;
+
+#ifdef DEBUG_ULSCH_DECODING
+  printf("ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n",
+      frame_parms->Nid_cell,ulsch->rnti,x2,
+      ulsch_harq->round,
+      ulsch_harq->rvidx,
+      ulsch_harq->mcs,
+      ulsch_harq->O_RI,
+      ulsch_harq->O_ACK,
+      G,
+      subframe);
+#endif
+
+  if (ulsch_harq->round == 0) {
+    // This is a new packet, so compute quantities regarding segmentation
+    ulsch_harq->B = A+24;
+    lte_segmentation_NB_IoT(NULL,
+                            NULL,
+                            ulsch_harq->B,
+                            &ulsch_harq->C,
+                            &ulsch_harq->Cplus,
+                            &ulsch_harq->Cminus,
+                            &ulsch_harq->Kplus,
+                            &ulsch_harq->Kminus,
+                            &ulsch_harq->F);
+    //  CLEAR LLR's HERE for first packet in process
+  }
+
+  //  printf("after segmentation c[%d] = %p\n",0,ulsch_harq->c[0]);
+
+  sumKr = 0;
+
+  for (r=0; r<ulsch_harq->C; r++) {
+    if (r<ulsch_harq->Cminus)
+      Kr = ulsch_harq->Kminus;
+    else
+      Kr = ulsch_harq->Kplus;
+
+    sumKr += Kr;
+  }
+
+  if (sumKr==0) {
+    LOG_N(PHY,"[eNB %d] ulsch_decoding.c: FATAL sumKr is 0!\n",eNB->Mod_id);
+    LOG_D(PHY,"ulsch_decoding (Nid_cell %d, rnti %x, x2 %x): harq_pid %d round %d, RV %d, mcs %d, O_RI %d, O_ACK %d, G %d, subframe %d\n",
+          frame_parms->Nid_cell,ulsch->rnti,x2,
+          harq_pid,
+          ulsch_harq->round,
+          ulsch_harq->rvidx,
+          ulsch_harq->mcs,
+          ulsch_harq->O_RI,
+          ulsch_harq->O_ACK,
+          G,
+          subframe);
+       //mac_xface_NB_IoT->macphy_exit("ulsch_decoding.c: FATAL sumKr is 0!");
+    return(-1);
+  }
+
+  // No control information in NB-IoT
+  // Compute Q_ri
+//   Qprime = ulsch_harq->O_RI*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_ri_times8;
+
+//   if (Qprime > 0 ) {
+//     if ((Qprime % (8*sumKr)) > 0)
+//       Qprime = 1+(Qprime/(8*sumKr));
+//     else
+//       Qprime = Qprime/(8*sumKr);
+
+//     if (Qprime > 4*nb_rb * 12)
+//       Qprime = 4*nb_rb * 12;
+//   }
+
+//   Q_RI      = Q_m*Qprime;
+//   Qprime_RI = Qprime;
+//   // Compute Q_ack
+//   Qprime = ulsch_harq->O_ACK*ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_harqack_times8;
+
+//   if (Qprime > 0) {
+//     if ((Qprime % (8*sumKr)) > 0)
+//       Qprime = 1+(Qprime/(8*sumKr));
+//     else
+//       Qprime = Qprime/(8*sumKr);
+
+//     if (Qprime > (4*nb_rb * 12))
+//       Qprime = 4*nb_rb * 12;
+//   }
+//   //  Q_ACK = Qprime * Q_m;
+//   Qprime_ACK = Qprime;
+// #ifdef DEBUG_ULSCH_DECODING
+//   printf("ulsch_decoding.c: Qprime_ACK %d, Msc_initial %d, Nsymb_initial %d, sumKr %d\n",
+//       Qprime_ACK,ulsch_harq->Msc_initial,ulsch_harq->Nsymb_initial,sumKr);
+// #endif
+
+//   // Compute Q_cqi
+//   if (ulsch_harq->Or1 < 12)
+//     L=0;
+//   else
+//     L=8;
+
+//   // NOTE: we have to handle the case where we have a very small number of bits (condition on pg. 26 36.212)
+//   if (ulsch_harq->Or1 > 0)
+//     Qprime = (ulsch_harq->Or1 + L) * ulsch_harq->Msc_initial*ulsch_harq->Nsymb_initial * ulsch->beta_offset_cqi_times8;
+//   else
+//     Qprime=0;
+
+//   if (Qprime > 0) {  // check if ceiling is larger than floor in Q' expression
+//     if ((Qprime % (8*sumKr)) > 0)
+//       Qprime = 1+(Qprime/(8*sumKr));
+//     else
+//       Qprime = Qprime/(8*sumKr);
+//   }
+
+//   G = nb_rb * (12 * Q_m) * (ulsch_harq->Nsymb_pusch);
+
+
+
+//   Q_CQI = Q_m * Qprime;
+// #ifdef DEBUG_ULSCH_DECODING
+//   printf("ulsch_decoding: G %d, Q_RI %d, Q_CQI %d (L %d, Or1 %d) O_ACK %d\n",G,Q_RI,Q_CQI,L,ulsch_harq->Or1,ulsch_harq->O_ACK);
+// #endif
+
+//   G             = G - Q_RI - Q_CQI;
+  ulsch_harq->G = G;
+
+  if ((int)G < 0) {
+    LOG_E(PHY,"FATAL: ulsch_decoding.c G < 0 (%d) : Q_RI %d, Q_CQI %d\n",G,Q_RI,Q_CQI);
+    return(-1);
+  }
+
+  //H      = G + Q_CQI;
+  H      = G ;
+  Hprime = H/Q_m;
+  // Demultiplexing/Deinterleaving of PUSCH/ACK/RI/CQI
+  //start_meas_NB_IoT(&eNB->ulsch_demultiplexing_stats);
+  //Hpp        = Hprime + Qprime_RI;
+  Hpp        = Hprime;
+  // Cmux       = ulsch_harq->Nsymb_pusch;
+  // unsigned int Nsymb_UL, Nslot_UL; // NB_IoT: these parameters should included in ulsch_harq
+  // Cmux       = (Nsymb_UL-1)*Nslot_UL; 
+  Cmux       = (ulsch_harq->Nsymb_UL-1)*ulsch_harq->Nslot_UL;
+
+  Rmux_prime = Hpp/Cmux;
+
+  // Clear "tag" interleaving matrix to allow for CQI/DATA identification
+  memset(ytag,0,Cmux*Rmux_prime);
+  i = 0;
+  memset(y,LTE_NULL_NB_IoT,Q_m*Hpp);
+  // read in buffer and unscramble llrs for everything but placeholder bits
+  // llrs stored per symbol correspond to columns of interleaving matrix
+  s  = lte_gold_unscram_NB_IoT(&x1, &x2, 1);
+  i2 = 0;
+
+  for (i=0; i<((Hpp*Q_m)>>5); i++) {
+    /*
+    for (j=0; j<32; j++) {
+      cseq[i2++] = (int16_t)((((s>>j)&1)<<1)-1);
+    }
+    */
+    #if defined(__x86_64__) || defined(__i386__)
+    #ifndef __AVX2__
+        ((__m128i*)cseq)[i2++] = ((__m128i*)unscrambling_lut_NB_IoT)[(s&65535)<<1];
+        ((__m128i*)cseq)[i2++] = ((__m128i*)unscrambling_lut_NB_IoT)[1+((s&65535)<<1)];
+        s>>=16;
+        ((__m128i*)cseq)[i2++] = ((__m128i*)unscrambling_lut_NB_IoT)[(s&65535)<<1];
+        ((__m128i*)cseq)[i2++] = ((__m128i*)unscrambling_lut_NB_IoT)[1+((s&65535)<<1)];
+    #else
+        ((__m256i*)cseq)[i2++] = ((__m256i*)unscrambling_lut_NB_IoT)[s&65535];
+        ((__m256i*)cseq)[i2++] = ((__m256i*)unscrambling_lut_NB_IoT)[(s>>16)&65535];
+    #endif
+    #elif defined(__arm__)
+        ((int16x8_t*)cseq)[i2++] = ((int16x8_t*)unscrambling_lut_NB_IoT)[(s&65535)<<1];
+        ((int16x8_t*)cseq)[i2++] = ((int16x8_t*)unscrambling_lut_NB_IoT)[1+((s&65535)<<1)];
+        s>>=16;
+        ((int16x8_t*)cseq)[i2++] = ((int16x8_t*)unscrambling_lut_NB_IoT)[(s&65535)<<1];
+        ((int16x8_t*)cseq)[i2++] = ((int16x8_t*)unscrambling_lut_NB_IoT)[1+((s&65535)<<1)];
+    #endif
+    s = lte_gold_unscram_NB_IoT(&x1, &x2, 0);
+  }
+
+
+  //  printf("after unscrambling c[%d] = %p\n",0,ulsch_harq->c[0]);
+
+  // if (frame_parms->Ncp == 0)
+  //   columnset = cs_ri_normal_NB_IoT;
+  // else
+  //   columnset = cs_ri_extended_NB_IoT;
+
+  // j = 0;
+
+  // for (i=0; i<Qprime_RI; i++) {
+
+  //   r           = Rmux_prime - 1 - (i>>2);
+  //   /*
+  //   for (q=0;q<Q_m;q++)
+  //     ytag2[q+(Q_m*((r*Cmux) + columnset[j]))]  = q_RI[(q+(Q_m*i))%len_RI];
+  //   */
+  //   off         =((Rmux_prime*Q_m*columnset[j])+(r*Q_m));
+  //   cseq[off+1] = cseq[off];  // PUSCH_y
+
+  //   for (q=2; q<Q_m; q++)
+  //     cseq[off+q] = -1;    // PUSCH_x
+
+  //   j = (j+3)&3;
+
+  // }
+
+  // //  printf("after RI c[%d] = %p\n",0,ulsch_harq->c[0]);
+
+  // // HARQ-ACK Bits (Note these overwrite some bits)
+  // if (frame_parms->Ncp == 0)
+  //   columnset = cs_ack_normal_NB_IoT;
+  // else
+  //   columnset = cs_ack_extended_NB_IoT;
+
+  // j = 0;
+
+  // for (i=0; i<Qprime_ACK; i++) {
+  //   r = Rmux_prime - 1 - (i>>2);
+  //   off =((Rmux_prime*Q_m*columnset[j])+(r*Q_m));
+
+  //   if (ulsch_harq->O_ACK == 1) {
+  //     if (ulsch->bundling==0)
+  //       cseq[off+1] = cseq[off];  // PUSCH_y
+
+  //     for (q=2; q<Q_m; q++)
+  //       cseq[off+q] = -1;    // PUSCH_x
+  //   } else if (ulsch_harq->O_ACK == 2) {
+  //     for (q=2; q<Q_m; q++)
+  //       cseq[off+q] = -1;    // PUSCH_x
+  //   }
+
+  //   #ifdef DEBUG_ULSCH_DECODING
+  //   printf("ulsch_decoding.c: ACK i %d, r %d, j %d, ColumnSet[j] %d\n",i,r,j,columnset[j]);
+  //   #endif
+  //   j=(j+3)&3;
+  // }
+
+  i = 0;
+
+  switch (Q_m) {
+
+    // why the case 1 ??????????????????
+  case 1: 
+    break; 
+  case 2:
+    for (j=0; j<Cmux; j++) {
+
+      i2 = j<<1;
+
+      for (r=0; r<Rmux_prime; r++) {
+
+        c       = cseq[i];
+        //  printf("ulsch %d: %d * ",i,c);
+        y[i2++] = c*ulsch_llr[i++];
+        //  printf("%d\n",ulsch_llr[i-1]);
+        c       = cseq[i];
+        //  printf("ulsch %d: %d * ",i,c);
+        y[i2]   = c*ulsch_llr[i++];
+        //  printf("%d\n",ulsch_llr[i-1]);
+        i2      =(i2+(Cmux<<1)-1);
+      }
+    }
+
+    break;
+
+  // case 4:
+  //   for (j=0; j<Cmux; j++) {
+
+  //     i2 = j<<2;
+
+  //     for (r=0; r<Rmux_prime; r++) {
+	 //      /*
+  //       c = cseq[i];
+  //       y[i2++] = c*ulsch_llr[i++];
+  //       c = cseq[i];
+  //       y[i2++] = c*ulsch_llr[i++];
+  //       c = cseq[i];
+  //       y[i2++] = c*ulsch_llr[i++];
+  //       c = cseq[i];
+  //       y[i2] = c*ulsch_llr[i++];
+  //       i2=(i2+(Cmux<<2)-3);
+	 //      */
+	 //      // slightly more optimized version (equivalent to above) for 16QAM to improve computational performance
+	 //      *(__m64 *)&y[i2] = _mm_sign_pi16(*(__m64*)&ulsch_llr[i],*(__m64*)&cseq[i]);i+=4;i2+=(Cmux<<2);
+
+  //     }
+  //   }
+
+  //   break;
+
+  // case 6:
+  //   for (j=0; j<Cmux; j++) {
+
+  //     i2 = j*6;
+
+  //     for (r=0; r<Rmux_prime; r++) {
+  //       c           = cseq[i];
+  //       y[i2++]     = c*ulsch_llr[i++];
+  //       c           = cseq[i];
+  //       y[i2++]     = c*ulsch_llr[i++];
+  //       c           = cseq[i];
+  //       y[i2++]     = c*ulsch_llr[i++];
+  //       c           = cseq[i];
+  //       y[i2++]     = c*ulsch_llr[i++];
+  //       c           = cseq[i];
+  //       y[i2++]     = c*ulsch_llr[i++];
+  //       c           = cseq[i];
+  //       y[i2]       = c*ulsch_llr[i++];
+  //       i2          =(i2+(Cmux*6)-5);
+  //     }
+  //   }
+
+  //   break;
+  }
+
+
+
+
+  // if (i!=(H+Q_RI))
+  if (i!=(H))
+    LOG_D(PHY,"ulsch_decoding.c: Error in input buffer length (j %d, H+Q_RI %d)\n",i,H+Q_RI);
+
+  // HARQ-ACK Bits (LLRs are nulled in overwritten bits after copying HARQ-ACK LLR)
+
+  // if (frame_parms->Ncp == 0)
+  //   columnset = cs_ack_normal_NB_IoT;
+  // else
+  //   columnset = cs_ack_extended_NB_IoT;
+
+  // j=0;
+
+  // if (ulsch_harq->O_ACK == 1) {
+  //   switch (Q_m) {
+  //   case 2:
+  //     len_ACK = 2;
+  //     break;
+
+  //   case 4:
+  //     len_ACK = 4;
+  //     break;
+
+  //   case 6:
+  //     len_ACK = 6;
+  //     break;
+  //   }
+  // }
+
+  // if (ulsch_harq->O_ACK == 2) {
+  //   switch (Q_m) {
+  //   case 2:
+  //     len_ACK = 6;
+  //     break;
+
+  //   case 4:
+  //     len_ACK = 12;
+  //     break;
+
+  //   case 6:
+  //     len_ACK = 18;
+  //     break;
+  //   }
+  // }
+
+  // if (ulsch_harq->O_ACK > 2) {
+  //   LOG_E(PHY,"ulsch_decoding: FATAL, ACK cannot be more than 2 bits yet\n");
+  //   return(-1);
+  // }
+
+  // for (i=0; i<len_ACK; i++)
+  //   ulsch_harq->q_ACK[i] = 0;
+
+
+  // for (i=0; i<Qprime_ACK; i++) {
+  //   r = Rmux_prime -1 - (i>>2);
+
+  //   for (q=0; q<Q_m; q++) {
+
+  //     if (y[q+(Q_m*((r*Cmux) + columnset[j]))]!=0)
+  //       ulsch_harq->q_ACK[(q+(Q_m*i))%len_ACK] += y[q+(Q_m*((r*Cmux) + columnset[j]))];
+
+  //     y[q+(Q_m*((r*Cmux) + columnset[j]))] = 0;  // NULL LLRs in ACK positions
+  //   }
+
+  //   j = (j+3)&3;
+  // }
+
+  // //  printf("after ACKNAK c[%d] = %p\n",0,ulsch_harq->c[0]);
+
+  // // RI BITS
+
+  // if (ulsch_harq->O_RI == 1) {
+  //   switch (Q_m) {
+  //   case 2:
+  //     len_RI = 2;
+  //     break;
+
+  //   case 4:
+  //     len_RI = 4;
+  //     break;
+
+  //   case 6:
+  //     len_RI = 6;
+  //     break;
+  //   }
+  // }
+
+  // if (ulsch_harq->O_RI > 1) {
+  //   LOG_E(PHY,"ulsch_decoding: FATAL, RI cannot be more than 1 bit yet\n");
+  //   return(-1);
+  // }
+
+  // for (i=0; i<len_RI; i++)
+  //   ulsch_harq->q_RI[i] = 0;
+
+  // if (frame_parms->Ncp == 0)
+  //   columnset = cs_ri_normal_NB_IoT;
+  // else
+  //   columnset = cs_ri_extended_NB_IoT;
+
+  // j=0;
+
+  // for (i=0; i<Qprime_RI; i++) {
+  //   r = Rmux_prime -1 - (i>>2);
+
+  //   for (q=0; q<Q_m; q++)
+  //     ulsch_harq->q_RI[(q+(Q_m*i))%len_RI] += y[q+(Q_m*((r*Cmux) + columnset[j]))];
+
+  //   ytag[(r*Cmux) + columnset[j]] = LTE_NULL_NB_IoT;
+  //   j                             = (j+3)&3;
+  // }
+
+  //  printf("after RI2 c[%d] = %p\n",0,ulsch_harq->c[0]);
+
+  // CQI and Data bits
+  j  = 0;
+  j2 = 0;
+
+  //  r=0;
+  // if (Q_RI>0) {
+  //   for (i=0; i<(Q_CQI/Q_m); i++) {
+      
+  //       while (ytag[j]==LTE_NULL_NB_IoT) {
+	 //         j++;
+	 //         j2+=Q_m;
+  //       }
+      
+  //       for (q=0; q<Q_m; q++) {
+	       
+	 //         ys = y[q+j2];
+	
+	 //         if (ys>127)
+	 //            ulsch_harq->q[q+(Q_m*i)] = 127;
+	 //         else if (ys<-128)
+	 //            ulsch_harq->q[q+(Q_m*i)] = -128;
+	 //         else
+	 //            ulsch_harq->q[q+(Q_m*i)] = ys;
+  //       }
+  //       j2+=Q_m;
+  //   }
+    
+        
+  //   switch (Q_m) {
+  //       case 2:
+  //           for (iprime=0; iprime<G;) {
+	 //             while (ytag[j]==LTE_NULL_NB_IoT) {
+	 //                j++;
+	 //                j2+=2;
+	 //             }
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+  //           } 
+  //       break;
+      
+  //       case 4:
+  //           for (iprime=0; iprime<G;) {
+	 //             while (ytag[j]==LTE_NULL_NB_IoT) {
+	 //                 j++;
+	 //                 j2+=4;
+	 //             }
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+  //           }
+  //       break;
+      
+  //       case 6:
+  //           for (iprime=0; iprime<G;) {
+	 //             while (ytag[j]==LTE_NULL_NB_IoT) {
+	 //                 j++;
+	 //                 j2+=6;
+	 //             }
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+	 //             ulsch_harq->e[iprime++] = y[j2++];
+  //           }
+  //       break;
+  //   }
+  // } // Q_RI>0
+  // else {
+
+  //   for (i=0; i<(Q_CQI/Q_m); i++) {
+      
+  //     for (q=0; q<Q_m; q++) {
+	 //       ys = y[q+j2];
+	 //       if (ys>127)
+	 //           ulsch_harq->q[q+(Q_m*i)] = 127;
+	 //       else if (ys<-128)
+	 //           ulsch_harq->q[q+(Q_m*i)] = -128;
+	 //       else
+	 //           ulsch_harq->q[q+(Q_m*i)] = ys;
+  //     }
+  //     j2+=Q_m;
+  //   }
+    /* To be improved according to alignment of j2
+    #if defined(__x86_64__)||defined(__i386__)
+    #ifndef __AVX2__
+    for (iprime=0; iprime<G;iprime+=8,j2+=8)
+      *((__m128i *)&ulsch_harq->e[iprime]) = *((__m128i *)&y[j2]);
+    #else
+    for (iprime=0; iprime<G;iprime+=16,j2+=16)
+      *((__m256i *)&ulsch_harq->e[iprime]) = *((__m256i *)&y[j2]);
+    #endif
+    #elif defined(__arm__)
+    for (iprime=0; iprime<G;iprime+=8,j2+=8)
+      *((int16x8_t *)&ulsch_harq->e[iprime]) = *((int16x8_t *)&y[j2]);
+    #endif
+    */
+    int16_t *yp,*ep;
+
+    for (iprime=0,yp=&y[j2],ep=&ulsch_harq->e[0]; 
+	     iprime<G;
+	     iprime+=8,j2+=8,ep+=8,yp+=8) {
+       ep[0] = yp[0];
+       ep[1] = yp[1];
+       ep[2] = yp[2];
+       ep[3] = yp[3];
+       ep[4] = yp[4];
+       ep[5] = yp[5];
+       ep[6] = yp[6];
+       ep[7] = yp[7];
+    }
+  
+    
+   
+  //stop_meas_NB_IoT(&eNB->ulsch_demultiplexing_stats);
+
+  //  printf("after ACKNAK2 c[%d] = %p (iprime %d, G %d)\n",0,ulsch_harq->c[0],iprime,G);
+
+  // Do CQI/RI/HARQ-ACK Decoding first and pass to MAC
+/*
+  // HARQ-ACK
+  wACK_idx = (ulsch->bundling==0) ? 4 : ((Nbundled-1)&3);
+
+  if (ulsch_harq->O_ACK == 1) {
+    ulsch_harq->q_ACK[0] *= wACK_RX_NB_IoT[wACK_idx][0];
+    ulsch_harq->q_ACK[0] += (ulsch->bundling==0) ? ulsch_harq->q_ACK[1]*wACK_RX_NB_IoT[wACK_idx][0] : ulsch_harq->q_ACK[1]*wACK_RX_NB_IoT[wACK_idx][1];
+
+    if (ulsch_harq->q_ACK[0] < 0)
+      ulsch_harq->o_ACK[0] = 0;
+    else
+      ulsch_harq->o_ACK[0] = 1;
+  }
+
+  if (ulsch_harq->O_ACK == 2) {
+    switch (Q_m) {
+
+    case 2:
+      ulsch_harq->q_ACK[0] = ulsch_harq->q_ACK[0]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[3]*wACK_RX_NB_IoT[wACK_idx][1];
+      ulsch_harq->q_ACK[1] = ulsch_harq->q_ACK[1]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[4]*wACK_RX_NB_IoT[wACK_idx][1];
+      ulsch_harq->q_ACK[2] = ulsch_harq->q_ACK[2]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[5]*wACK_RX_NB_IoT[wACK_idx][1];
+      break;
+    // case 4:
+    //   ulsch_harq->q_ACK[0] = ulsch_harq->q_ACK[0]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[5]*wACK_RX_NB_IoT[wACK_idx][1];
+    //   ulsch_harq->q_ACK[1] = ulsch_harq->q_ACK[1]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[8]*wACK_RX_NB_IoT[wACK_idx][1];
+    //   ulsch_harq->q_ACK[2] = ulsch_harq->q_ACK[4]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[9]*wACK_RX_NB_IoT[wACK_idx][1];
+    //   break;
+    // case 6:
+    //   ulsch_harq->q_ACK[0] =  ulsch_harq->q_ACK[0]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[7]*wACK_RX_NB_IoT[wACK_idx][1];
+    //   ulsch_harq->q_ACK[1] =  ulsch_harq->q_ACK[1]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[12]*wACK_RX_NB_IoT[wACK_idx][1];
+    //   ulsch_harq->q_ACK[2] =  ulsch_harq->q_ACK[6]*wACK_RX_NB_IoT[wACK_idx][0] + ulsch_harq->q_ACK[13]*wACK_RX_NB_IoT[wACK_idx][1];
+    //   break;
+    }
+
+    ulsch_harq->o_ACK[0] = 1;
+    ulsch_harq->o_ACK[1] = 1;
+    metric     = ulsch_harq->q_ACK[0]+ulsch_harq->q_ACK[1]-ulsch_harq->q_ACK[2];
+    metric_new = -ulsch_harq->q_ACK[0]+ulsch_harq->q_ACK[1]+ulsch_harq->q_ACK[2];
+
+    if (metric_new > metric) {
+      ulsch_harq->o_ACK[0]=0;
+      ulsch_harq->o_ACK[1]=1;
+      metric = metric_new;
+    }
+
+    metric_new = ulsch_harq->q_ACK[0]-ulsch_harq->q_ACK[1]+ulsch_harq->q_ACK[2];
+
+
+    if (metric_new > metric) {
+      ulsch_harq->o_ACK[0] = 1;
+      ulsch_harq->o_ACK[1] = 0;
+      metric = metric_new;
+    }
+
+    metric_new = -ulsch_harq->q_ACK[0]-ulsch_harq->q_ACK[1]-ulsch_harq->q_ACK[2];
+
+    if (metric_new > metric) {
+      ulsch_harq->o_ACK[0] = 0;
+      ulsch_harq->o_ACK[1] = 0;
+      metric = metric_new;
+    }
+  }
+
+  // RI
+
+  // rank 1
+  if ((ulsch_harq->O_RI == 1) && (Qprime_RI > 0)) {
+    ulsch_harq->o_RI[0] = ((ulsch_harq->q_RI[0] + ulsch_harq->q_RI[Q_m/2]) > 0) ? 0 : 1;
+  }
+
+  // CQI
+
+  //  printf("before cqi c[%d] = %p\n",0,ulsch_harq->c[0]);
+  ulsch_harq->cqi_crc_status = 0;
+  if (Q_CQI>0) {
+    memset((void *)&dummy_w_cc[0],0,3*(ulsch_harq->Or1+8+32));
+
+    O_RCC = generate_dummy_w_cc_NB_IoT(ulsch_harq->Or1+8,
+                                       &dummy_w_cc[0]);
+
+    lte_rate_matching_cc_rx_NB_IoT(O_RCC,
+                                   Q_CQI,
+                                   ulsch_harq->o_w,
+                                   dummy_w_cc,
+                                   ulsch_harq->q);
+
+    sub_block_deinterleaving_cc_NB_IoT((unsigned int)(ulsch_harq->Or1+8),
+                                        &ulsch_harq->o_d[96],
+                                        &ulsch_harq->o_w[0]);
+
+    memset(o_flip,0,1+((8+ulsch_harq->Or1)/8));
+
+    phy_viterbi_lte_sse2_NB_IoT(ulsch_harq->o_d+96,o_flip,8+ulsch_harq->Or1);
+
+    if (extract_cqi_crc_NB_IoT(o_flip,ulsch_harq->Or1) == (crc8_NB_IoT(o_flip,ulsch_harq->Or1)>>24))
+      ulsch_harq->cqi_crc_status = 1;
+
+    if (ulsch->harq_process->Or1<=32) {
+      ulsch_harq->o[3] = o_flip[0] ;
+      ulsch_harq->o[2] = o_flip[1] ;
+      ulsch_harq->o[1] = o_flip[2] ;
+      ulsch_harq->o[0] = o_flip[3] ;
+    } else {
+      ulsch_harq->o[7] = o_flip[0] ;
+      ulsch_harq->o[6] = o_flip[1] ;
+      ulsch_harq->o[5] = o_flip[2] ;
+      ulsch_harq->o[4] = o_flip[3] ;
+      ulsch_harq->o[3] = o_flip[4] ;
+      ulsch_harq->o[2] = o_flip[5] ;
+      ulsch_harq->o[1] = o_flip[6] ;
+      ulsch_harq->o[0] = o_flip[7] ;
+
+    }
+
+    #ifdef DEBUG_ULSCH_DECODING
+    printf("ulsch_decoding: Or1=%d\n",ulsch_harq->Or1);
+
+    for (i=0; i<1+((8+ulsch_harq->Or1)/8); i++)
+      printf("ulsch_decoding: O[%d] %d\n",i,ulsch_harq->o[i]);
+
+    if (ulsch_harq->cqi_crc_status == 1)
+      printf("RX CQI CRC OK (%x)\n",extract_cqi_crc_NB_IoT(o_flip,ulsch_harq->Or1));
+    else
+      printf("RX CQI CRC NOT OK (%x)\n",extract_cqi_crc_NB_IoT(o_flip,ulsch_harq->Or1));
+
+    #endif
+  }
+
+*/
+  // Do ULSCH Decoding for data portion
+
+  ret = eNB->td(eNB,UE_id,harq_pid,llr8_flag);
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_DECODING0+harq_pid,0);
+
+  return(ret);
+}
+
+
+/*
+#ifdef PHY_ABSTRACTION
+
+#ifdef PHY_ABSTRACTION_UL
+int ulsch_abstraction(double* sinr_dB, uint8_t TM, uint8_t mcs,uint16_t nrb, uint16_t frb)
+{
+
+  int index,ii;
+  double sinr_eff = 0;
+  int rb_count = 0;
+  int offset;
+  double bler = 0;
+  TM = TM-1;
+  sinr_eff = sinr_dB[frb]; //the single sinr_eff value we calculated with MMSE FDE formula in init_snr_up function
+
+
+  sinr_eff *= 10;
+  sinr_eff = floor(sinr_eff);
+  sinr_eff /= 10;
+
+  LOG_D(PHY,"[ABSTRACTION] sinr_eff after rounding = %f\n",sinr_eff);
+
+  for (index = 0; index < 16; index++) {
+    if(index == 0) {
+      if (sinr_eff < sinr_bler_map_up[mcs][0][index]) {
+        bler = 1;
+        break;
+      }
+    }
+
+    if (sinr_eff == sinr_bler_map_up[mcs][0][index]) {
+      bler = sinr_bler_map_up[mcs][1][index];
+    }
+  }
+
+#ifdef USER_MODE // need to be adapted for the emulation in the kernel space 
+
+  if (uniformrandom() < bler) {
+    LOG_I(OCM,"abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
+    return(0);
+  } else {
+    LOG_I(OCM,"abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
+    return(1);
+  }
+
+#endif
+}
+
+
+
+
+
+
+
+int ulsch_abstraction_MIESM(double* sinr_dB,uint8_t TM, uint8_t mcs,uint16_t nrb, uint16_t frb)
+{
+  int index;
+  double sinr_eff = 0;
+  double sinr_db1 = 0;
+  double sinr_db2 = 0;
+  double SI=0;
+  double RBIR=0;
+  int rb_count = 0;
+  int offset, M=0;
+  double bler = 0;
+  int start,middle,end;
+  TM = TM-1;
+
+  for (offset = frb; offset <= (frb + nrb -1); offset++) {
+
+    rb_count++;
+
+    //we need to do the table lookups here for the mutual information corresponding to the certain sinr_dB.
+
+    sinr_db1 = sinr_dB[offset*2];
+    sinr_db2 = sinr_dB[offset*2+1];
+
+    printf("sinr_db1=%f\n,sinr_db2=%f\n",sinr_db1,sinr_db2);
+
+    //rounding up for the table lookup
+    sinr_db1 *= 10;
+    sinr_db2 *= 10;
+
+    sinr_db1 = floor(sinr_db1);
+    sinr_db2 = floor(sinr_db2);
+
+    if ((int)sinr_db1%2) {
+      sinr_db1 += 1;
+    }
+
+    if ((int)sinr_db2%2) {
+      sinr_db2 += 1;
+    }
+
+    sinr_db1 /= 10;
+    sinr_db2 /= 10;
+
+    if(mcs<10) {
+      //for sinr_db1
+      for (index = 0; index < 162; index++) {
+        if (sinr_db1 < MI_map_4qam[0][0]) {
+          SI += (MI_map_4qam[1][0]/beta1_dlsch_MI[TM][mcs]);
+          M +=2;
+          break;
+        }
+
+        if (sinr_db1 > MI_map_4qam[0][161]) {
+          SI += (MI_map_4qam[1][161]/beta1_dlsch_MI[TM][mcs]);
+          M +=2;
+          break;
+        }
+
+        if (sinr_db1 == MI_map_4qam[0][index]) {
+          SI += (MI_map_4qam[1][index]/beta1_dlsch_MI[TM][mcs]);
+          M +=2;
+          break;
+        }
+      }
+
+      //for sinr_db2
+      for (index = 0; index < 162; index++) {
+        if (sinr_db2 < MI_map_4qam[0][0]) {
+          SI += (MI_map_4qam[1][0]/beta1_dlsch_MI[TM][mcs]);
+          M +=2;
+          break;
+        }
+
+        if (sinr_db2 > MI_map_4qam[0][161]) {
+          SI += (MI_map_4qam[1][161]/beta1_dlsch_MI[TM][mcs]);
+          M +=2;
+          break;
+        }
+
+        if (sinr_db2 == MI_map_4qam[0][index]) {
+          SI += (MI_map_4qam[1][index]/beta1_dlsch_MI[TM][mcs]);
+          M +=2;
+          break;
+        }
+      }
+
+    } else if(mcs>9 && mcs<17) {
+      //for sinr_db1
+      for (index = 0; index < 197; index++) {
+        if (sinr_db1 < MI_map_16qam[0][0]) {
+          SI += (MI_map_16qam[1][0]/beta1_dlsch_MI[TM][mcs]);
+          M +=4;
+          break;
+        }
+
+        if (sinr_db1 > MI_map_16qam[0][196]) {
+          SI += (MI_map_16qam[1][196]/beta1_dlsch_MI[TM][mcs]);
+          M +=4;
+          break;
+        }
+
+        if (sinr_db1 == MI_map_16qam[0][index]) {
+          SI += (MI_map_16qam[1][index]/beta1_dlsch_MI[TM][mcs]);
+          M +=4;
+          break;
+        }
+      }
+
+      //for sinr_db2
+      for (index = 0; index < 197; index++) {
+        if (sinr_db2 < MI_map_16qam[0][0]) {
+          SI += (MI_map_16qam[1][0]/beta1_dlsch_MI[TM][mcs]);
+          M +=4;
+          break;
+        }
+
+        if (sinr_db2 > MI_map_16qam[0][196]) {
+          SI += (MI_map_16qam[1][196]/beta1_dlsch_MI[TM][mcs]);
+          M +=4;
+          break;
+        }
+
+        if (sinr_db2 == MI_map_16qam[0][index]) {
+          SI += (MI_map_16qam[1][index]/beta1_dlsch_MI[TM][mcs]);
+          M +=4;
+          break;
+        }
+      }
+
+    } else if(mcs>16 && mcs<22) {
+      //for sinr_db1
+      for (index = 0; index < 227; index++) {
+        if (sinr_db1 < MI_map_64qam[0][0]) {
+          SI += (MI_map_64qam[1][0]/beta1_dlsch_MI[TM][mcs]);
+          M +=6;
+          break;
+        }
+
+        if (sinr_db1 > MI_map_64qam[0][226]) {
+          SI += (MI_map_64qam[1][226]/beta1_dlsch_MI[TM][mcs]);
+          M +=6;
+          break;
+        }
+
+        if (sinr_db1 == MI_map_64qam[0][index]) {
+          SI += (MI_map_64qam[1][index]/beta1_dlsch_MI[TM][mcs]);
+          M +=6;
+          break;
+        }
+      }
+
+      //for sinr_db2
+      for (index = 0; index < 227; index++) {
+        if (sinr_db2 < MI_map_64qam[0][0]) {
+          SI += (MI_map_64qam[1][0]/beta1_dlsch_MI[TM][mcs]);
+          M +=6;
+          break;
+        }
+
+        if (sinr_db2 > MI_map_64qam[0][226]) {
+          SI += (MI_map_64qam[1][226]/beta1_dlsch_MI[TM][mcs]);
+          M +=6;
+          break;
+        }
+
+        if (sinr_db2 == MI_map_64qam[0][index]) {
+          SI += (MI_map_64qam[1][index]/beta1_dlsch_MI[TM][mcs]);
+          M +=6;
+          break;
+        }
+      }
+    }
+  }
+
+  // }
+
+  RBIR = SI/M;
+
+  //Now RBIR->SINR_effective Mapping
+  //binary search method is performed here
+  if(mcs<10) {
+    start = 0;
+    end = 161;
+    middle = end/2;
+
+    if (RBIR <= MI_map_4qam[2][start]) {
+      sinr_eff =  MI_map_4qam[0][start];
+    } else {
+      if (RBIR >= MI_map_4qam[2][end])
+        sinr_eff =  MI_map_4qam[0][end];
+      else {
+        //while((end-start > 1) && (RBIR >= MI_map_4qam[2]))
+        if (RBIR < MI_map_4qam[2][middle]) {
+          end = middle;
+          middle = end/2;
+        } else {
+          start = middle;
+          middle = (end-middle)/2;
+        }
+      }
+
+      for (; end>start; end--) {
+        if ((RBIR < MI_map_4qam[2][end]) && (RBIR >  MI_map_4qam[2][end-2])) {
+          sinr_eff = MI_map_4qam[0][end-1];
+          break;
+        }
+      }
+    }
+
+    sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs];
+  }
+
+
+
+  else if (mcs>9 && mcs<17) {
+
+    start = 0;
+    end = 196;
+    middle = end/2;
+
+    if (RBIR <= MI_map_16qam[2][start]) {
+      sinr_eff =  MI_map_16qam[0][start];
+    } else {
+      if (RBIR >= MI_map_16qam[2][end])
+        sinr_eff =  MI_map_16qam[0][end];
+      else {
+        //while((end-start > 1) && (RBIR >= MI_map_4qam[2]))
+        if (RBIR < MI_map_16qam[2][middle]) {
+          end = middle;
+          middle = end/2;
+        } else {
+          start = middle;
+          middle = (end-middle)/2;
+        }
+      }
+
+      for (; end>start; end--) {
+        if ((RBIR < MI_map_16qam[2][end]) && (RBIR >  MI_map_16qam[2][end-2])) {
+          sinr_eff = MI_map_16qam[0][end-1];
+          break;
+        }
+      }
+    }
+
+    sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs];
+  } else if (mcs>16) {
+    start = 0;
+    end = 226;
+    middle = end/2;
+
+    if (RBIR <= MI_map_64qam[2][start]) {
+      sinr_eff =  MI_map_64qam[0][start];
+    } else {
+      if (RBIR >= MI_map_64qam[2][end])
+        sinr_eff =  MI_map_64qam[0][end];
+      else {
+        //while((end-start > 1) && (RBIR >= MI_map_4qam[2]))
+        if (RBIR < MI_map_64qam[2][middle]) {
+          end = middle;
+          middle = end/2;
+        } else {
+          start = middle;
+          middle = (end-middle)/2;
+        }
+      }
+
+      for (; end>start; end--) {
+        if ((RBIR < MI_map_64qam[2][end]) && (RBIR >  MI_map_64qam[2][end-2])) {
+          sinr_eff = MI_map_64qam[0][end-1];
+          break;
+        }
+      }
+    }
+
+    sinr_eff = sinr_eff * beta2_dlsch_MI[TM][mcs];
+  }
+
+  printf("SINR_Eff = %e\n",sinr_eff);
+
+  sinr_eff *= 10;
+  sinr_eff = floor(sinr_eff);
+  // if ((int)sinr_eff%2) {
+  //   sinr_eff += 1;
+  // }
+  sinr_eff /= 10;
+  printf("sinr_eff after rounding = %f\n",sinr_eff);
+
+  for (index = 0; index < 16; index++) {
+    if(index == 0) {
+      if (sinr_eff < sinr_bler_map_up[mcs][0][index]) {
+        bler = 1;
+        break;
+      }
+    }
+
+    if (sinr_eff == sinr_bler_map_up[mcs][0][index]) {
+      bler = sinr_bler_map_up[mcs][1][index];
+    }
+  }
+
+#ifdef USER_MODE // need to be adapted for the emulation in the kernel space 
+
+  if (uniformrandom() < bler) {
+    printf("abstraction_decoding failed (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
+    return(0);
+  } else {
+    printf("abstraction_decoding successful (mcs=%d, sinr_eff=%f, bler=%f)\n",mcs,sinr_eff,bler);
+    return(1);
+  }
+
+#endif
+
+}
+
+#endif
+
+uint32_t ulsch_decoding_emul(PHY_VARS_eNB *eNB, eNB_rxtx_proc_t *proc,
+                             uint8_t UE_index,
+                             uint16_t *crnti)
+{
+
+  uint8_t UE_id;
+  uint16_t rnti;
+  int subframe = proc->subframe_rx;
+  uint8_t harq_pid;
+  uint8_t CC_id = eNB->CC_id;
+
+  harq_pid = subframe2harq_pid(&eNB->frame_parms,proc->frame_rx,subframe);
+
+  rnti = eNB->ulsch[UE_index]->rnti;
+#ifdef DEBUG_PHY
+  LOG_D(PHY,"[eNB %d] ulsch_decoding_emul : subframe %d UE_index %d harq_pid %d rnti %x\n",eNB->Mod_id,subframe,UE_index,harq_pid,rnti);
+#endif
+
+  for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
+    if (rnti == PHY_vars_UE_g[UE_id][CC_id]->pdcch_vars[subframe & 0x1][0]->crnti)
+      break;
+
+  }
+
+  if (UE_id==NB_UE_INST) {
+    LOG_W(PHY,"[eNB %d] ulsch_decoding_emul: FATAL, didn't find UE with rnti %x (UE index %d)\n",
+          eNB->Mod_id, rnti, UE_index);
+    return(1+eNB->ulsch[UE_id]->max_turbo_iterations);
+  } else {
+    LOG_D(PHY,"[eNB %d] Found UE with rnti %x => UE_id %d\n",eNB->Mod_id, rnti, UE_id);
+  }
+
+  if (PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->harq_processes[harq_pid]->status == CBA_ACTIVE) {
+    *crnti = rnti;
+    PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->harq_processes[harq_pid]->status=IDLE;
+  } else
+    *crnti = 0x0;
+
+  // Do abstraction here to determine if packet it in error
+  /// if (ulsch_abstraction_MIESM(eNB->sinr_dB_eNB,1, eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, eNB->ulsch[UE_id]->harq_processes[harq_pid]->first_rb) == 1)
+   flag = 1;
+   else flag = 0;///
+
+
+  
+  //SINRdbPost = eNB->sinr_dB_eNB;
+  mcsPost = eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,
+  nrbPost = eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb;
+  frbPost = eNB->ulsch[UE_id]->harq_processes[harq_pid]->first_rb;
+
+
+  if(nrbPost > 0)
+  {
+  SINRdbPost = eNB->sinr_dB_eNB;
+  ULflag1 = 1;
+  }
+  else
+  {
+   SINRdbPost = NULL  ;
+   ULflag1 = 0 ;
+  }//
+
+  //
+  // write_output("postprocSINR.m","SINReNB",eNB->sinr_dB,301,1,7);
+
+
+  //Yazdir buraya her frame icin 300 eNb
+  // fprintf(SINRrx,"%e,%e,%e,%e;\n",SINRdbPost);
+  //fprintf(SINRrx,"%e\n",SINRdbPost);
+
+  // fprintf(csv_fd,"%e+i*(%e),",channelx,channely);
+
+  // if (ulsch_abstraction(eNB->sinr_dB,1, eNB->ulsch[UE_id]->harq_processes[harq_pid]->mcs,eNB->ulsch[UE_id]->harq_processes[harq_pid]->nb_rb, eNB->ulsch[UE_id]->harq_processes[harq_pid]->first_rb) == 1) {
+  if (1) {
+    LOG_D(PHY,"ulsch_decoding_emul abstraction successful\n");
+
+    memcpy(eNB->ulsch[UE_index]->harq_processes[harq_pid]->b,
+           PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->harq_processes[harq_pid]->b,
+           eNB->ulsch[UE_index]->harq_processes[harq_pid]->TBS>>3);
+
+    // get local ue's ack
+    if ((UE_index >= oai_emulation.info.first_ue_local) ||(UE_index <(oai_emulation.info.first_ue_local+oai_emulation.info.nb_ue_local))) {
+      get_ack(&eNB->frame_parms,
+              PHY_vars_UE_g[UE_id][CC_id]->dlsch[0][0][0]->harq_ack,
+              proc->subframe_tx,
+              proc->subframe_rx,
+              eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK,0);
+    } else { // get remote UEs' ack
+      eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[0] = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_ACK[0];
+      eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[1] = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_ACK[1];
+    }
+
+    // Do abstraction of PUSCH feedback
+#ifdef DEBUG_PHY
+    LOG_D(PHY,"[eNB %d][EMUL] ue index %d UE_id %d: subframe %d : o_ACK (%d %d), cqi (val %d, len %d)\n",
+          eNB->Mod_id,UE_index, UE_id, subframe,eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[0],
+          eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_ACK[1],
+          ((HLC_subband_cqi_rank1_2A_5MHz *)PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o)->cqi1,
+          PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->O);
+#endif
+
+    eNB->ulsch[UE_index]->harq_processes[harq_pid]->Or1 = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->O;
+    eNB->ulsch[UE_index]->harq_processes[harq_pid]->Or2 = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->O;
+
+    eNB->ulsch[UE_index]->harq_processes[harq_pid]->uci_format = PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->uci_format;
+    memcpy(eNB->ulsch[UE_index]->harq_processes[harq_pid]->o,PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o,MAX_CQI_BYTES);
+    memcpy(eNB->ulsch[UE_index]->harq_processes[harq_pid]->o_RI,PHY_vars_UE_g[UE_id][CC_id]->ulsch[0]->o_RI,2);
+
+    eNB->ulsch[UE_index]->harq_processes[harq_pid]->cqi_crc_status = 1;
+
+    return(1);
+  } else {
+    LOG_W(PHY,"[eNB %d] ulsch_decoding_emul abstraction failed for UE %d\n",eNB->Mod_id,UE_index);
+
+    eNB->ulsch[UE_index]->harq_processes[harq_pid]->cqi_crc_status = 0;
+
+    // retransmission
+    return(1+eNB->ulsch[UE_index]->max_turbo_iterations);
+  }
+
+}
+
+
+#endif
+*/
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..74b1133ac65a26f89270a0508db6713e8457ae0c
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation_NB_IoT.c
@@ -0,0 +1,1686 @@
+/*
+ * 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.0  (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/LTE_TRANSPORT/ulsch_demodulation.c
+* \brief Top-level routines for demodulating the PUSCH physical channel from 36.211 V8.6 2009-03
+* \author R. Knopp
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: knopp@eurecom.fr, florian.kaltenberger@eurecom.fr, ankit.bhamri@eurecom.fr
+* \note
+* \warning
+*/
+
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/extern_NB_IoT.h"
+#include "defs_NB_IoT.h"
+#include "extern_NB_IoT.h"
+//#define DEBUG_ULSCH
+//#include "PHY/sse_intrin.h"
+#include "PHY/LTE_ESTIMATION/defs_NB_IoT.h"
+#include "T.h"
+
+//extern char* namepointer_chMag ;
+//eren
+//extern int **ulchmag_eren;
+//eren
+
+static short jitter[8]  __attribute__ ((aligned(16))) = {1,0,0,1,0,1,1,0};
+static short jitterc[8] __attribute__ ((aligned(16))) = {0,1,1,0,1,0,0,1};
+
+#ifndef OFDMA_ULSCH
+void lte_idft_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,uint32_t *z, uint16_t Msc_PUSCH)
+{
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i idft_in128[3][1200],idft_out128[3][1200];
+  __m128i norm128;
+#elif defined(__arm__)
+  int16x8_t idft_in128[3][1200],idft_out128[3][1200];
+  int16x8_t norm128;
+#endif
+  int16_t *idft_in0=(int16_t*)idft_in128[0],*idft_out0=(int16_t*)idft_out128[0];
+  int16_t *idft_in1=(int16_t*)idft_in128[1],*idft_out1=(int16_t*)idft_out128[1];
+  int16_t *idft_in2=(int16_t*)idft_in128[2],*idft_out2=(int16_t*)idft_out128[2];
+
+  uint32_t *z0,*z1,*z2,*z3,*z4,*z5,*z6,*z7,*z8,*z9,*z10=NULL,*z11=NULL;
+  int i,ip;
+
+
+
+  //  printf("Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH);
+
+   // Normal prefix
+    z0 = z;
+    z1 = z0+(frame_parms->N_RB_DL*12);
+    z2 = z1+(frame_parms->N_RB_DL*12);
+    //pilot
+    z3 = z2+(2*frame_parms->N_RB_DL*12);
+    z4 = z3+(frame_parms->N_RB_DL*12);
+    z5 = z4+(frame_parms->N_RB_DL*12);
+
+    z6 = z5+(frame_parms->N_RB_DL*12);
+    z7 = z6+(frame_parms->N_RB_DL*12);
+    z8 = z7+(frame_parms->N_RB_DL*12);
+    //pilot
+    z9 = z8+(2*frame_parms->N_RB_DL*12);
+    z10 = z9+(frame_parms->N_RB_DL*12);
+    // srs
+    z11 = z10+(frame_parms->N_RB_DL*12);
+  
+  // conjugate input
+  for (i=0; i<(Msc_PUSCH>>2); i++) {
+#if defined(__x86_64__)||defined(__i386__)
+    *&(((__m128i*)z0)[i])=_mm_sign_epi16(*&(((__m128i*)z0)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z1)[i])=_mm_sign_epi16(*&(((__m128i*)z1)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z2)[i])=_mm_sign_epi16(*&(((__m128i*)z2)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z3)[i])=_mm_sign_epi16(*&(((__m128i*)z3)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z4)[i])=_mm_sign_epi16(*&(((__m128i*)z4)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z5)[i])=_mm_sign_epi16(*&(((__m128i*)z5)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z6)[i])=_mm_sign_epi16(*&(((__m128i*)z6)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z7)[i])=_mm_sign_epi16(*&(((__m128i*)z7)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z8)[i])=_mm_sign_epi16(*&(((__m128i*)z8)[i]),*(__m128i*)&conjugate2[0]);
+    *&(((__m128i*)z9)[i])=_mm_sign_epi16(*&(((__m128i*)z9)[i]),*(__m128i*)&conjugate2[0]);
+
+    if (frame_parms->Ncp==NORMAL_NB_IoT) {
+      *&(((__m128i*)z10)[i])=_mm_sign_epi16(*&(((__m128i*)z10)[i]),*(__m128i*)&conjugate2[0]);
+      *&(((__m128i*)z11)[i])=_mm_sign_epi16(*&(((__m128i*)z11)[i]),*(__m128i*)&conjugate2[0]);
+    }
+#elif defined(__arm__)
+    *&(((int16x8_t*)z0)[i])=vmulq_s16(*&(((int16x8_t*)z0)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z1)[i])=vmulq_s16(*&(((int16x8_t*)z1)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z2)[i])=vmulq_s16(*&(((int16x8_t*)z2)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z3)[i])=vmulq_s16(*&(((int16x8_t*)z3)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z4)[i])=vmulq_s16(*&(((int16x8_t*)z4)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z5)[i])=vmulq_s16(*&(((int16x8_t*)z5)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z6)[i])=vmulq_s16(*&(((int16x8_t*)z6)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z7)[i])=vmulq_s16(*&(((int16x8_t*)z7)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z8)[i])=vmulq_s16(*&(((int16x8_t*)z8)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z9)[i])=vmulq_s16(*&(((int16x8_t*)z9)[i]),*(int16x8_t*)&conjugate2[0]);
+
+
+    if (frame_parms->Ncp==NORMAL_NB_IoT) {
+      *&(((int16x8_t*)z10)[i])=vmulq_s16(*&(((int16x8_t*)z10)[i]),*(int16x8_t*)&conjugate2[0]);
+      *&(((int16x8_t*)z11)[i])=vmulq_s16(*&(((int16x8_t*)z11)[i]),*(int16x8_t*)&conjugate2[0]);
+    }
+
+#endif
+  }
+
+  for (i=0,ip=0; i<Msc_PUSCH; i++,ip+=4) {
+    ((uint32_t*)idft_in0)[ip+0] =  z0[i];
+    ((uint32_t*)idft_in0)[ip+1] =  z1[i];
+    ((uint32_t*)idft_in0)[ip+2] =  z2[i];
+    ((uint32_t*)idft_in0)[ip+3] =  z3[i];
+    ((uint32_t*)idft_in1)[ip+0] =  z4[i];
+    ((uint32_t*)idft_in1)[ip+1] =  z5[i];
+    ((uint32_t*)idft_in1)[ip+2] =  z6[i];
+    ((uint32_t*)idft_in1)[ip+3] =  z7[i];
+    ((uint32_t*)idft_in2)[ip+0] =  z8[i];
+    ((uint32_t*)idft_in2)[ip+1] =  z9[i];
+
+    if (frame_parms->Ncp==0) {
+      ((uint32_t*)idft_in2)[ip+2] =  z10[i];
+      ((uint32_t*)idft_in2)[ip+3] =  z11[i];
+    }
+  }
+
+
+  switch (Msc_PUSCH) {
+  case 12:
+    dft12((int16_t *)idft_in0,(int16_t *)idft_out0);
+    dft12((int16_t *)idft_in1,(int16_t *)idft_out1);
+    dft12((int16_t *)idft_in2,(int16_t *)idft_out2);
+
+#if defined(__x86_64__)||defined(__i386__)
+    norm128 = _mm_set1_epi16(9459);
+#elif defined(__arm__)
+    norm128 = vdupq_n_s16(9459);
+#endif
+    for (i=0; i<12; i++) {
+#if defined(__x86_64__)||defined(__i386__)
+      ((__m128i*)idft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out0)[i],norm128),1);
+      ((__m128i*)idft_out1)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out1)[i],norm128),1);
+      ((__m128i*)idft_out2)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out2)[i],norm128),1);
+#elif defined(__arm__)
+      ((int16x8_t*)idft_out0)[i] = vqdmulhq_s16(((int16x8_t*)idft_out0)[i],norm128);
+      ((int16x8_t*)idft_out1)[i] = vqdmulhq_s16(((int16x8_t*)idft_out1)[i],norm128);
+      ((int16x8_t*)idft_out2)[i] = vqdmulhq_s16(((int16x8_t*)idft_out2)[i],norm128);
+#endif
+    }
+
+    break;
+
+  // case 24:
+  //   dft24(idft_in0,idft_out0,1);
+  //   dft24(idft_in1,idft_out1,1);
+  //   dft24(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 36:
+  //   dft36(idft_in0,idft_out0,1);
+  //   dft36(idft_in1,idft_out1,1);
+  //   dft36(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 48:
+  //   dft48(idft_in0,idft_out0,1);
+  //   dft48(idft_in1,idft_out1,1);
+  //   dft48(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 60:
+  //   dft60(idft_in0,idft_out0,1);
+  //   dft60(idft_in1,idft_out1,1);
+  //   dft60(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 72:
+  //   dft72(idft_in0,idft_out0,1);
+  //   dft72(idft_in1,idft_out1,1);
+  //   dft72(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 96:
+  //   dft96(idft_in0,idft_out0,1);
+  //   dft96(idft_in1,idft_out1,1);
+  //   dft96(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 108:
+  //   dft108(idft_in0,idft_out0,1);
+  //   dft108(idft_in1,idft_out1,1);
+  //   dft108(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 120:
+  //   dft120(idft_in0,idft_out0,1);
+  //   dft120(idft_in1,idft_out1,1);
+  //   dft120(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 144:
+  //   dft144(idft_in0,idft_out0,1);
+  //   dft144(idft_in1,idft_out1,1);
+  //   dft144(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 180:
+  //   dft180(idft_in0,idft_out0,1);
+  //   dft180(idft_in1,idft_out1,1);
+  //   dft180(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 192:
+  //   dft192(idft_in0,idft_out0,1);
+  //   dft192(idft_in1,idft_out1,1);
+  //   dft192(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 216:
+  //   dft216(idft_in0,idft_out0,1);
+  //   dft216(idft_in1,idft_out1,1);
+  //   dft216(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 240:
+  //   dft240(idft_in0,idft_out0,1);
+  //   dft240(idft_in1,idft_out1,1);
+  //   dft240(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 288:
+  //   dft288(idft_in0,idft_out0,1);
+  //   dft288(idft_in1,idft_out1,1);
+  //   dft288(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 300:
+  //   dft300(idft_in0,idft_out0,1);
+  //   dft300(idft_in1,idft_out1,1);
+  //   dft300(idft_in2,idft_out2,1);
+  //   break;
+
+  // case 324:
+  //   dft324((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft324((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft324((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 360:
+  //   dft360((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft360((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft360((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 384:
+  //   dft384((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft384((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft384((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 432:
+  //   dft432((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft432((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft432((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 480:
+  //   dft480((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft480((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft480((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 540:
+  //   dft540((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft540((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft540((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 576:
+  //   dft576((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft576((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft576((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 600:
+  //   dft600((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft600((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft600((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 648:
+  //   dft648((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft648((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft648((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 720:
+  //   dft720((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft720((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft720((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 864:
+  //   dft864((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft864((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft864((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 900:
+  //   dft900((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft900((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft900((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 960:
+  //   dft960((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft960((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft960((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 972:
+  //   dft972((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft972((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft972((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 1080:
+  //   dft1080((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft1080((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft1080((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 1152:
+  //   dft1152((int16_t*)idft_in0,(int16_t*)idft_out0,1);
+  //   dft1152((int16_t*)idft_in1,(int16_t*)idft_out1,1);
+  //   dft1152((int16_t*)idft_in2,(int16_t*)idft_out2,1);
+  //   break;
+
+  // case 1200:
+  //   dft1200(idft_in0,idft_out0,1);
+  //   dft1200(idft_in1,idft_out1,1);
+  //   dft1200(idft_in2,idft_out2,1);
+  //   break;
+
+  default:
+    // should not be reached
+    LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH );
+    return;
+  }
+
+
+
+  for (i=0,ip=0; i<Msc_PUSCH; i++,ip+=4) {
+    z0[i]     = ((uint32_t*)idft_out0)[ip];
+    /*
+      printf("out0 (%d,%d),(%d,%d),(%d,%d),(%d,%d)\n",
+      ((int16_t*)&idft_out0[ip])[0],((int16_t*)&idft_out0[ip])[1],
+      ((int16_t*)&idft_out0[ip+1])[0],((int16_t*)&idft_out0[ip+1])[1],
+      ((int16_t*)&idft_out0[ip+2])[0],((int16_t*)&idft_out0[ip+2])[1],
+      ((int16_t*)&idft_out0[ip+3])[0],((int16_t*)&idft_out0[ip+3])[1]);
+    */
+    z1[i]     = ((uint32_t*)idft_out0)[ip+1];
+    z2[i]     = ((uint32_t*)idft_out0)[ip+2];
+    z3[i]     = ((uint32_t*)idft_out0)[ip+3];
+    z4[i]     = ((uint32_t*)idft_out1)[ip+0];
+    z5[i]     = ((uint32_t*)idft_out1)[ip+1];
+    z6[i]     = ((uint32_t*)idft_out1)[ip+2];
+    z7[i]     = ((uint32_t*)idft_out1)[ip+3];
+    z8[i]     = ((uint32_t*)idft_out2)[ip];
+    z9[i]     = ((uint32_t*)idft_out2)[ip+1];
+
+    if (frame_parms->Ncp==0) {
+      z10[i]    = ((uint32_t*)idft_out2)[ip+2];
+      z11[i]    = ((uint32_t*)idft_out2)[ip+3];
+    }
+  }
+
+  // conjugate output
+  for (i=0; i<(Msc_PUSCH>>2); i++) {
+#if defined(__x86_64__) || defined(__i386__)
+    ((__m128i*)z0)[i]=_mm_sign_epi16(((__m128i*)z0)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z1)[i]=_mm_sign_epi16(((__m128i*)z1)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z2)[i]=_mm_sign_epi16(((__m128i*)z2)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z3)[i]=_mm_sign_epi16(((__m128i*)z3)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z4)[i]=_mm_sign_epi16(((__m128i*)z4)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z5)[i]=_mm_sign_epi16(((__m128i*)z5)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z6)[i]=_mm_sign_epi16(((__m128i*)z6)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z7)[i]=_mm_sign_epi16(((__m128i*)z7)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z8)[i]=_mm_sign_epi16(((__m128i*)z8)[i],*(__m128i*)&conjugate2[0]);
+    ((__m128i*)z9)[i]=_mm_sign_epi16(((__m128i*)z9)[i],*(__m128i*)&conjugate2[0]);
+
+    if (frame_parms->Ncp==NORMAL_NB_IoT) {
+      ((__m128i*)z10)[i]=_mm_sign_epi16(((__m128i*)z10)[i],*(__m128i*)&conjugate2[0]);
+      ((__m128i*)z11)[i]=_mm_sign_epi16(((__m128i*)z11)[i],*(__m128i*)&conjugate2[0]);
+    }
+#elif defined(__arm__)
+    *&(((int16x8_t*)z0)[i])=vmulq_s16(*&(((int16x8_t*)z0)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z1)[i])=vmulq_s16(*&(((int16x8_t*)z1)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z2)[i])=vmulq_s16(*&(((int16x8_t*)z2)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z3)[i])=vmulq_s16(*&(((int16x8_t*)z3)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z4)[i])=vmulq_s16(*&(((int16x8_t*)z4)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z5)[i])=vmulq_s16(*&(((int16x8_t*)z5)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z6)[i])=vmulq_s16(*&(((int16x8_t*)z6)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z7)[i])=vmulq_s16(*&(((int16x8_t*)z7)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z8)[i])=vmulq_s16(*&(((int16x8_t*)z8)[i]),*(int16x8_t*)&conjugate2[0]);
+    *&(((int16x8_t*)z9)[i])=vmulq_s16(*&(((int16x8_t*)z9)[i]),*(int16x8_t*)&conjugate2[0]);
+
+
+    if (frame_parms->Ncp==NORMAL_NB_IoT) {
+      *&(((int16x8_t*)z10)[i])=vmulq_s16(*&(((int16x8_t*)z10)[i]),*(int16x8_t*)&conjugate2[0]);
+      *&(((int16x8_t*)z11)[i])=vmulq_s16(*&(((int16x8_t*)z11)[i]),*(int16x8_t*)&conjugate2[0]);
+    }
+
+#endif
+  }
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+
+}
+#endif
+
+
+
+
+
+int32_t ulsch_qpsk_llr_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
+                              int32_t **rxdataF_comp,
+                              int16_t *ulsch_llr,
+                              uint8_t symbol,
+                              uint16_t nb_rb,
+                              int16_t **llrp)
+{
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i *rxF=(__m128i*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
+  __m128i **llrp128 = (__m128i **)llrp;
+#elif defined(__arm__)
+  int16x8_t *rxF= (int16x8_t*)&rxdataF_comp[0][(symbol*frame_parms->N_RB_DL*12)];
+  int16x8_t **llrp128 = (int16x8_t **)llrp;
+#endif
+
+  int i;
+
+  //  printf("qpsk llr for symbol %d (pos %d), llr offset %d\n",symbol,(symbol*frame_parms->N_RB_DL*12),llr128U-(__m128i*)ulsch_llr);
+
+  for (i=0; i<(nb_rb*3); i++) {
+    //printf("%d,%d,%d,%d,%d,%d,%d,%d\n",((int16_t *)rxF)[0],((int16_t *)rxF)[1],((int16_t *)rxF)[2],((int16_t *)rxF)[3],((int16_t *)rxF)[4],((int16_t *)rxF)[5],((int16_t *)rxF)[6],((int16_t *)rxF)[7]);
+    *(*llrp128) = *rxF;
+    rxF++;
+    (*llrp128)++;
+  }
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+
+  return(0);
+
+}
+
+
+void ulsch_detection_mrc_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,
+                         int32_t **rxdataF_comp,
+                         int32_t **ul_ch_mag,
+                         int32_t **ul_ch_magb,
+                         uint8_t symbol,
+                         uint16_t nb_rb)
+{
+
+
+#if defined(__x86_64__) || defined(__i386__)
+
+  __m128i *rxdataF_comp128_0,*ul_ch_mag128_0,*ul_ch_mag128_0b;
+  __m128i *rxdataF_comp128_1,*ul_ch_mag128_1,*ul_ch_mag128_1b;
+#elif defined(__arm__)
+
+  int16x8_t *rxdataF_comp128_0,*ul_ch_mag128_0,*ul_ch_mag128_0b;
+  int16x8_t *rxdataF_comp128_1,*ul_ch_mag128_1,*ul_ch_mag128_1b;
+
+#endif
+  int32_t i;
+
+  if (frame_parms->nb_antennas_rx>1) {
+#if defined(__x86_64__) || defined(__i386__)
+    rxdataF_comp128_0   = (__m128i *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12];
+    rxdataF_comp128_1   = (__m128i *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_0      = (__m128i *)&ul_ch_mag[0][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_1      = (__m128i *)&ul_ch_mag[1][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_0b     = (__m128i *)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_1b     = (__m128i *)&ul_ch_magb[1][symbol*frame_parms->N_RB_DL*12];
+
+    // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
+    for (i=0; i<nb_rb*3; i++) {
+      rxdataF_comp128_0[i] = _mm_adds_epi16(_mm_srai_epi16(rxdataF_comp128_0[i],1),_mm_srai_epi16(rxdataF_comp128_1[i],1));
+      ul_ch_mag128_0[i]    = _mm_adds_epi16(_mm_srai_epi16(ul_ch_mag128_0[i],1),_mm_srai_epi16(ul_ch_mag128_1[i],1));
+      ul_ch_mag128_0b[i]   = _mm_adds_epi16(_mm_srai_epi16(ul_ch_mag128_0b[i],1),_mm_srai_epi16(ul_ch_mag128_1b[i],1));
+      rxdataF_comp128_0[i] = _mm_add_epi16(rxdataF_comp128_0[i],(*(__m128i*)&jitterc[0]));
+
+#elif defined(__arm__)
+    rxdataF_comp128_0   = (int16x8_t *)&rxdataF_comp[0][symbol*frame_parms->N_RB_DL*12];
+    rxdataF_comp128_1   = (int16x8_t *)&rxdataF_comp[1][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_0      = (int16x8_t *)&ul_ch_mag[0][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_1      = (int16x8_t *)&ul_ch_mag[1][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_0b     = (int16x8_t *)&ul_ch_magb[0][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128_1b     = (int16x8_t *)&ul_ch_magb[1][symbol*frame_parms->N_RB_DL*12];
+
+    // MRC on each re of rb, both on MF output and magnitude (for 16QAM/64QAM llr computation)
+    for (i=0; i<nb_rb*3; i++) {
+      rxdataF_comp128_0[i] = vhaddq_s16(rxdataF_comp128_0[i],rxdataF_comp128_1[i]);
+      ul_ch_mag128_0[i]    = vhaddq_s16(ul_ch_mag128_0[i],ul_ch_mag128_1[i]);
+      ul_ch_mag128_0b[i]   = vhaddq_s16(ul_ch_mag128_0b[i],ul_ch_mag128_1b[i]);
+      rxdataF_comp128_0[i] = vqaddq_s16(rxdataF_comp128_0[i],(*(int16x8_t*)&jitterc[0]));
+
+
+#endif
+    }
+  }
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+}
+
+void ulsch_extract_rbs_single_NB_IoT(int32_t **rxdataF,
+                                     int32_t **rxdataF_ext,
+                                     // uint32_t first_rb, 
+                                     uint32_t UL_RB_ID_NB_IoT, // index of UL NB_IoT resource block 
+                                     uint8_t N_sc_RU, // number of subcarriers in UL 
+                                     uint32_t I_sc, // NB_IoT: subcarrier indication field: must be defined in higher layer
+                                     uint32_t nb_rb,
+                                     uint8_t l,
+                                     uint8_t Ns,
+                                     NB_IoT_DL_FRAME_PARMS *frame_parms)
+{
+  uint16_t  nb_rb1; 
+  // uint16_t  nb_rb2; 
+  uint8_t   aarx,n;
+  // int32_t   *rxF,*rxF_ext;
+  //uint8_t symbol = l+Ns*frame_parms->symbols_per_tti/2;
+  uint8_t   symbol = l+((7-frame_parms->Ncp)*(Ns&1)); ///symbol within sub-frame 
+  uint16_t ul_sc_start; // subcarrier start index into UL RB 
+
+  ul_sc_start = get_UL_sc_start_NB_IoT(I_sc); 
+
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+    nb_rb1 = cmin(cmax((int)(frame_parms->N_RB_UL) - (int)(2*UL_RB_ID_NB_IoT),(int)0),(int)(2));    // 2 times no. RBs before the DC
+                                 // 2 times no. RBs after the DC
+
+    // rxF_ext   = &rxdataF_ext[aarx][(symbol*frame_parms->N_RB_UL*12)];
+
+    if (nb_rb1) { // RB NB-IoT is in the first half
+
+      for (n=0;n<N_sc_RU;n++){
+        // Note that FFT splits the RBs 
+        rxdataF_ext[aarx][symbol*frame_parms->N_RB_UL*12 + n] = rxdataF[aarx][UL_RB_ID_NB_IoT*12 + ul_sc_start + frame_parms->first_carrier_offset + symbol*frame_parms->ofdm_symbol_size + n];
+      
+      }
+
+      // rxF = &rxdataF[aarx][(first_rb*12 + frame_parms->first_carrier_offset + symbol*frame_parms->ofdm_symbol_size)];
+      // memcpy(rxF_ext, rxF, nb_rb1*6*sizeof(int));
+      // rxF_ext += nb_rb1*6;
+
+      // if (nb_rb2)  {
+      //   //#ifdef OFDMA_ULSCH
+      //   //  rxF = &rxdataF[aarx][(1 + symbol*frame_parms->ofdm_symbol_size)*2];
+      //   //#else
+      //   rxF = &rxdataF[aarx][(symbol*frame_parms->ofdm_symbol_size)];
+      //   //#endif
+      //   memcpy(rxF_ext, rxF, nb_rb2*6*sizeof(int));
+      //   rxF_ext += nb_rb2*6;
+      // }
+    } else { // RB NB-IoT is in the second half 
+
+      for (n=0;n<N_sc_RU;n++){
+        // Note that FFT splits the RBs 
+        rxdataF_ext[aarx][symbol*frame_parms->N_RB_UL*12 + n] = rxdataF[aarx][6*(2*UL_RB_ID_NB_IoT - frame_parms->N_RB_UL) +  ul_sc_start + symbol*frame_parms->ofdm_symbol_size + n];
+      
+      }
+
+      //#ifdef OFDMA_ULSCH
+      //      rxF = &rxdataF[aarx][(1 + 6*(2*first_rb - frame_parms->N_RB_UL) + symbol*frame_parms->ofdm_symbol_size)*2];
+      //#else
+      // rxF = &rxdataF[aarx][(6*(2*first_rb - frame_parms->N_RB_UL) + symbol*frame_parms->ofdm_symbol_size)]; 
+      // //#endif
+      // memcpy(rxF_ext, rxF, nb_rb2*6*sizeof(int));
+      // rxF_ext += nb_rb2*6;
+    }
+  }
+
+}
+
+
+void ulsch_channel_compensation_NB_IoT(int32_t **rxdataF_ext,
+                                int32_t **ul_ch_estimates_ext,
+                                int32_t **ul_ch_mag,
+                                int32_t **ul_ch_magb,
+                                int32_t **rxdataF_comp,
+                                NB_IoT_DL_FRAME_PARMS *frame_parms,
+                                uint8_t symbol,
+                                uint8_t Qm,
+                                uint16_t nb_rb,
+                                uint8_t output_shift)
+{
+
+  uint16_t rb;
+
+#if defined(__x86_64__) || defined(__i386__)
+
+  __m128i *ul_ch128,*ul_ch_mag128,*ul_ch_mag128b,*rxdataF128,*rxdataF_comp128;
+  uint8_t aarx;//,symbol_mod;
+  __m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3;
+#ifdef OFDMA_ULSCH
+  __m128i QAM_amp128U,QAM_amp128bU;
+#endif
+
+#elif defined(__arm__)
+
+  int16x4_t *ul_ch128,*rxdataF128;
+  int16x8_t *ul_ch_mag128,*ul_ch_mag128b,*rxdataF_comp128;
+
+  uint8_t aarx;//,symbol_mod;
+  int32x4_t mmtmpU0,mmtmpU1,mmtmpU0b,mmtmpU1b;
+#ifdef OFDMA_ULSCH
+  int16x8_t mmtmpU2,mmtmpU3;
+  int16x8_t QAM_amp128U,QAM_amp128bU;
+#endif
+  int16_t conj[4]__attribute__((aligned(16))) = {1,-1,1,-1};
+  int32x4_t output_shift128 = vmovq_n_s32(-(int32_t)output_shift);
+
+
+
+#endif
+
+#ifdef OFDMA_ULSCH
+
+#if defined(__x86_64__) || defined(__i386__)
+  if (Qm == 4)
+    QAM_amp128U = _mm_set1_epi16(QAM16_n1);
+  else if (Qm == 6) {
+    QAM_amp128U  = _mm_set1_epi16(QAM64_n1);
+    QAM_amp128bU = _mm_set1_epi16(QAM64_n2);
+  }
+#elif defined(__arm__)
+  if (Qm == 4)
+    QAM_amp128U = vdupq_n_s16(QAM16_n1);
+  else if (Qm == 6) {
+    QAM_amp128U  = vdupq_n_s16(QAM64_n1);
+    QAM_amp128bU = vdupq_n_s16(QAM64_n2);
+  }
+
+#endif
+#endif
+
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+#if defined(__x86_64__) || defined(__i386__)
+
+    ul_ch128          = (__m128i *)&ul_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128      = (__m128i *)&ul_ch_mag[aarx][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128b     = (__m128i *)&ul_ch_magb[aarx][symbol*frame_parms->N_RB_DL*12];
+    rxdataF128        = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12];
+    rxdataF_comp128   = (__m128i *)&rxdataF_comp[aarx][symbol*frame_parms->N_RB_DL*12];
+
+#elif defined(__arm__)
+
+
+    ul_ch128          = (int16x4_t *)&ul_ch_estimates_ext[aarx][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128      = (int16x8_t *)&ul_ch_mag[aarx][symbol*frame_parms->N_RB_DL*12];
+    ul_ch_mag128b     = (int16x8_t *)&ul_ch_magb[aarx][symbol*frame_parms->N_RB_DL*12];
+    rxdataF128        = (int16x4_t *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12];
+    rxdataF_comp128   = (int16x8_t *)&rxdataF_comp[aarx][symbol*frame_parms->N_RB_DL*12];
+
+#endif
+    for (rb=0; rb<nb_rb; rb++) {
+      //            printf("comp: symbol %d rb %d\n",symbol,rb);
+#ifdef OFDMA_ULSCH
+      if (Qm>2) {
+        // get channel amplitude if not QPSK
+
+#if defined(__x86_64__) || defined(__i386__)
+        mmtmpU0 = _mm_madd_epi16(ul_ch128[0],ul_ch128[0]);
+
+        mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+
+        mmtmpU1 = _mm_madd_epi16(ul_ch128[1],ul_ch128[1]);
+        mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+        mmtmpU0 = _mm_packs_epi32(mmtmpU0,mmtmpU1);
+
+        ul_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpU0,mmtmpU0);
+        ul_ch_mag128b[0] = ul_ch_mag128[0];
+        ul_ch_mag128[0] = _mm_mulhi_epi16(ul_ch_mag128[0],QAM_amp128U);
+        ul_ch_mag128[0] = _mm_slli_epi16(ul_ch_mag128[0],2);  // 2 to compensate the scale channel estimate
+        ul_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpU0,mmtmpU0);
+        ul_ch_mag128b[1] = ul_ch_mag128[1];
+        ul_ch_mag128[1] = _mm_mulhi_epi16(ul_ch_mag128[1],QAM_amp128U);
+        ul_ch_mag128[1] = _mm_slli_epi16(ul_ch_mag128[1],2);  // 2 to compensate the scale channel estimate
+
+        mmtmpU0 = _mm_madd_epi16(ul_ch128[2],ul_ch128[2]);
+        mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+        mmtmpU1 = _mm_packs_epi32(mmtmpU0,mmtmpU0);
+
+        ul_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpU1,mmtmpU1);
+        ul_ch_mag128b[2] = ul_ch_mag128[2];
+
+        ul_ch_mag128[2] = _mm_mulhi_epi16(ul_ch_mag128[2],QAM_amp128U);
+        ul_ch_mag128[2] = _mm_slli_epi16(ul_ch_mag128[2],2); // 2 to compensate the scale channel estimate
+
+
+        ul_ch_mag128b[0] = _mm_mulhi_epi16(ul_ch_mag128b[0],QAM_amp128bU);
+        ul_ch_mag128b[0] = _mm_slli_epi16(ul_ch_mag128b[0],2); // 2 to compensate the scale channel estimate
+
+
+        ul_ch_mag128b[1] = _mm_mulhi_epi16(ul_ch_mag128b[1],QAM_amp128bU);
+        ul_ch_mag128b[1] = _mm_slli_epi16(ul_ch_mag128b[1],2); // 2 to compensate the scale channel estimate
+
+        ul_ch_mag128b[2] = _mm_mulhi_epi16(ul_ch_mag128b[2],QAM_amp128bU);
+        ul_ch_mag128b[2] = _mm_slli_epi16(ul_ch_mag128b[2],2);// 2 to compensate the scale channel estimate
+
+#elif defined(__arm__)
+          mmtmpU0 = vmull_s16(ul_ch128[0], ul_ch128[0]);
+          mmtmpU0 = vqshlq_s32(vqaddq_s32(mmtmpU0,vrev64q_s32(mmtmpU0)),-output_shift128);
+          mmtmpU1 = vmull_s16(ul_ch128[1], ul_ch128[1]);
+          mmtmpU1 = vqshlq_s32(vqaddq_s32(mmtmpU1,vrev64q_s32(mmtmpU1)),-output_shift128);
+          mmtmpU2 = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+          mmtmpU0 = vmull_s16(ul_ch128[2], ul_ch128[2]);
+          mmtmpU0 = vqshlq_s32(vqaddq_s32(mmtmpU0,vrev64q_s32(mmtmpU0)),-output_shift128);
+          mmtmpU1 = vmull_s16(ul_ch128[3], ul_ch128[3]);
+          mmtmpU1 = vqshlq_s32(vqaddq_s32(mmtmpU1,vrev64q_s32(mmtmpU1)),-output_shift128);
+          mmtmpU3 = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+          mmtmpU0 = vmull_s16(ul_ch128[4], ul_ch128[4]);
+          mmtmpU0 = vqshlq_s32(vqaddq_s32(mmtmpU0,vrev64q_s32(mmtmpU0)),-output_shift128);
+          mmtmpU1 = vmull_s16(ul_ch128[5], ul_ch128[5]);
+          mmtmpU1 = vqshlq_s32(vqaddq_s32(mmtmpU1,vrev64q_s32(mmtmpU1)),-output_shift128);
+          mmtmpU4 = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+
+          ul_ch_mag128b[0] = vqdmulhq_s16(mmtmpU2,QAM_amp128b);
+          ul_ch_mag128b[1] = vqdmulhq_s16(mmtmpU3,QAM_amp128b);
+          ul_ch_mag128[0] = vqdmulhq_s16(mmtmpU2,QAM_amp128);
+          ul_ch_mag128[1] = vqdmulhq_s16(mmtmpU3,QAM_amp128);
+          ul_ch_mag128b[2] = vqdmulhq_s16(mmtmpU4,QAM_amp128b);
+          ul_ch_mag128[2]  = vqdmulhq_s16(mmtmpU4,QAM_amp128);
+#endif
+      }
+
+#else // SC-FDMA
+// just compute channel magnitude without scaling, this is done after equalization for SC-FDMA
+
+#if defined(__x86_64__) || defined(__i386__)
+      mmtmpU0 = _mm_madd_epi16(ul_ch128[0],ul_ch128[0]);
+
+      mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+      mmtmpU1 = _mm_madd_epi16(ul_ch128[1],ul_ch128[1]);
+
+      mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+
+      mmtmpU0 = _mm_packs_epi32(mmtmpU0,mmtmpU1);
+
+      ul_ch_mag128[0] = _mm_unpacklo_epi16(mmtmpU0,mmtmpU0);
+      ul_ch_mag128[1] = _mm_unpackhi_epi16(mmtmpU0,mmtmpU0);
+
+      mmtmpU0 = _mm_madd_epi16(ul_ch128[2],ul_ch128[2]);
+
+      mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+      mmtmpU1 = _mm_packs_epi32(mmtmpU0,mmtmpU0);
+      ul_ch_mag128[2] = _mm_unpacklo_epi16(mmtmpU1,mmtmpU1);
+
+      // printf("comp: symbol %d rb %d => %d,%d,%d (output_shift %d)\n",symbol,rb,*((int16_t*)&ul_ch_mag128[0]),*((int16_t*)&ul_ch_mag128[1]),*((int16_t*)&ul_ch_mag128[2]),output_shift);
+
+
+#elif defined(__arm__)
+          mmtmpU0 = vmull_s16(ul_ch128[0], ul_ch128[0]);
+          mmtmpU0 = vqshlq_s32(vqaddq_s32(mmtmpU0,vrev64q_s32(mmtmpU0)),-output_shift128);
+          mmtmpU1 = vmull_s16(ul_ch128[1], ul_ch128[1]);
+          mmtmpU1 = vqshlq_s32(vqaddq_s32(mmtmpU1,vrev64q_s32(mmtmpU1)),-output_shift128);
+          ul_ch_mag128[0] = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+          mmtmpU0 = vmull_s16(ul_ch128[2], ul_ch128[2]);
+          mmtmpU0 = vqshlq_s32(vqaddq_s32(mmtmpU0,vrev64q_s32(mmtmpU0)),-output_shift128);
+          mmtmpU1 = vmull_s16(ul_ch128[3], ul_ch128[3]);
+          mmtmpU1 = vqshlq_s32(vqaddq_s32(mmtmpU1,vrev64q_s32(mmtmpU1)),-output_shift128);
+          ul_ch_mag128[1] = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+          mmtmpU0 = vmull_s16(ul_ch128[4], ul_ch128[4]);
+          mmtmpU0 = vqshlq_s32(vqaddq_s32(mmtmpU0,vrev64q_s32(mmtmpU0)),-output_shift128);
+          mmtmpU1 = vmull_s16(ul_ch128[5], ul_ch128[5]);
+          mmtmpU1 = vqshlq_s32(vqaddq_s32(mmtmpU1,vrev64q_s32(mmtmpU1)),-output_shift128);
+          ul_ch_mag128[2] = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+
+#endif
+#endif
+
+#if defined(__x86_64__) || defined(__i386__)
+      // multiply by conjugated channel
+      mmtmpU0 = _mm_madd_epi16(ul_ch128[0],rxdataF128[0]);
+      //        print_ints("re",&mmtmpU0);
+
+      // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+      mmtmpU1 = _mm_shufflelo_epi16(ul_ch128[0],_MM_SHUFFLE(2,3,0,1));
+      mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+      mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)&conjugate[0]);
+
+      mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]);
+      //      print_ints("im",&mmtmpU1);
+      // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+      mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+      //  print_ints("re(shift)",&mmtmpU0);
+      mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+      //  print_ints("im(shift)",&mmtmpU1);
+      mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+      mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+      //        print_ints("c0",&mmtmpU2);
+      //  print_ints("c1",&mmtmpU3);
+      rxdataF_comp128[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+      /*
+              print_shorts("rx:",&rxdataF128[0]);
+              print_shorts("ch:",&ul_ch128[0]);
+              print_shorts("pack:",&rxdataF_comp128[0]);
+      */
+      // multiply by conjugated channel
+      mmtmpU0 = _mm_madd_epi16(ul_ch128[1],rxdataF128[1]);
+      // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+      mmtmpU1 = _mm_shufflelo_epi16(ul_ch128[1],_MM_SHUFFLE(2,3,0,1));
+      mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+      mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+      mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]);
+      // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+      mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+      mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+      mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+      mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+      rxdataF_comp128[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+      //        print_shorts("rx:",rxdataF128[1]);
+      //        print_shorts("ch:",ul_ch128[1]);
+      //        print_shorts("pack:",rxdataF_comp128[1]);
+      //       multiply by conjugated channel
+      mmtmpU0 = _mm_madd_epi16(ul_ch128[2],rxdataF128[2]);
+      // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+      mmtmpU1 = _mm_shufflelo_epi16(ul_ch128[2],_MM_SHUFFLE(2,3,0,1));
+      mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+      mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+      mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]);
+      // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+      mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+      mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+      mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+      mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+      rxdataF_comp128[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+      //        print_shorts("rx:",rxdataF128[2]);
+      //        print_shorts("ch:",ul_ch128[2]);
+      //        print_shorts("pack:",rxdataF_comp128[2]);
+
+      // Add a jitter to compensate for the saturation in "packs" resulting in a bias on the DC after IDFT
+      rxdataF_comp128[0] = _mm_add_epi16(rxdataF_comp128[0],(*(__m128i*)&jitter[0]));
+      rxdataF_comp128[1] = _mm_add_epi16(rxdataF_comp128[1],(*(__m128i*)&jitter[0]));
+      rxdataF_comp128[2] = _mm_add_epi16(rxdataF_comp128[2],(*(__m128i*)&jitter[0]));
+
+      ul_ch128+=3;
+      ul_ch_mag128+=3;
+      ul_ch_mag128b+=3;
+      rxdataF128+=3;
+      rxdataF_comp128+=3;
+#elif defined(__arm__)
+        mmtmpU0 = vmull_s16(ul_ch128[0], rxdataF128[0]);
+        //mmtmpU0 = [Re(ch[0])Re(rx[0]) Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1]) Im(ch[1])Im(ch[1])] 
+        mmtmpU1 = vmull_s16(ul_ch128[1], rxdataF128[1]);
+        //mmtmpU1 = [Re(ch[2])Re(rx[2]) Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3]) Im(ch[3])Im(ch[3])] 
+        mmtmpU0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpU0),vget_high_s32(mmtmpU0)),
+                               vpadd_s32(vget_low_s32(mmtmpU1),vget_high_s32(mmtmpU1)));
+        //mmtmpU0 = [Re(ch[0])Re(rx[0])+Im(ch[0])Im(ch[0]) Re(ch[1])Re(rx[1])+Im(ch[1])Im(ch[1]) Re(ch[2])Re(rx[2])+Im(ch[2])Im(ch[2]) Re(ch[3])Re(rx[3])+Im(ch[3])Im(ch[3])] 
+
+        mmtmpU0b = vmull_s16(vrev32_s16(vmul_s16(ul_ch128[0],*(int16x4_t*)conj)), rxdataF128[0]);
+        //mmtmpU0 = [-Im(ch[0])Re(rx[0]) Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1]) Re(ch[1])Im(rx[1])]
+        mmtmpU1b = vmull_s16(vrev32_s16(vmul_s16(ul_ch128[1],*(int16x4_t*)conj)), rxdataF128[1]);
+        //mmtmpU0 = [-Im(ch[2])Re(rx[2]) Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3]) Re(ch[3])Im(rx[3])]
+        mmtmpU1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpU0b),vget_high_s32(mmtmpU0b)),
+                               vpadd_s32(vget_low_s32(mmtmpU1b),vget_high_s32(mmtmpU1b)));
+        //mmtmpU1 = [-Im(ch[0])Re(rx[0])+Re(ch[0])Im(rx[0]) -Im(ch[1])Re(rx[1])+Re(ch[1])Im(rx[1]) -Im(ch[2])Re(rx[2])+Re(ch[2])Im(rx[2]) -Im(ch[3])Re(rx[3])+Re(ch[3])Im(rx[3])]
+
+        mmtmpU0 = vqshlq_s32(mmtmpU0,-output_shift128);
+        mmtmpU1 = vqshlq_s32(mmtmpU1,-output_shift128);
+        rxdataF_comp128[0] = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+        mmtmpU0 = vmull_s16(ul_ch128[2], rxdataF128[2]);
+        mmtmpU1 = vmull_s16(ul_ch128[3], rxdataF128[3]);
+        mmtmpU0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpU0),vget_high_s32(mmtmpU0)),
+                               vpadd_s32(vget_low_s32(mmtmpU1),vget_high_s32(mmtmpU1)));
+        mmtmpU0b = vmull_s16(vrev32_s16(vmul_s16(ul_ch128[2],*(int16x4_t*)conj)), rxdataF128[2]);
+        mmtmpU1b = vmull_s16(vrev32_s16(vmul_s16(ul_ch128[3],*(int16x4_t*)conj)), rxdataF128[3]);
+        mmtmpU1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpU0b),vget_high_s32(mmtmpU0b)),
+                               vpadd_s32(vget_low_s32(mmtmpU1b),vget_high_s32(mmtmpU1b)));
+        mmtmpU0 = vqshlq_s32(mmtmpU0,-output_shift128);
+        mmtmpU1 = vqshlq_s32(mmtmpU1,-output_shift128);
+        rxdataF_comp128[1] = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+
+        mmtmpU0 = vmull_s16(ul_ch128[4], rxdataF128[4]);
+        mmtmpU1 = vmull_s16(ul_ch128[5], rxdataF128[5]);
+        mmtmpU0 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpU0),vget_high_s32(mmtmpU0)),
+                               vpadd_s32(vget_low_s32(mmtmpU1),vget_high_s32(mmtmpU1)));
+
+        mmtmpU0b = vmull_s16(vrev32_s16(vmul_s16(ul_ch128[4],*(int16x4_t*)conj)), rxdataF128[4]);
+        mmtmpU1b = vmull_s16(vrev32_s16(vmul_s16(ul_ch128[5],*(int16x4_t*)conj)), rxdataF128[5]);
+        mmtmpU1 = vcombine_s32(vpadd_s32(vget_low_s32(mmtmpU0b),vget_high_s32(mmtmpU0b)),
+                               vpadd_s32(vget_low_s32(mmtmpU1b),vget_high_s32(mmtmpU1b)));
+
+              
+        mmtmpU0 = vqshlq_s32(mmtmpU0,-output_shift128);
+        mmtmpU1 = vqshlq_s32(mmtmpU1,-output_shift128);
+        rxdataF_comp128[2] = vcombine_s16(vmovn_s32(mmtmpU0),vmovn_s32(mmtmpU1));
+              
+              // Add a jitter to compensate for the saturation in "packs" resulting in a bias on the DC after IDFT
+        rxdataF_comp128[0] = vqaddq_s16(rxdataF_comp128[0],(*(int16x8_t*)&jitter[0]));
+        rxdataF_comp128[1] = vqaddq_s16(rxdataF_comp128[1],(*(int16x8_t*)&jitter[0]));
+        rxdataF_comp128[2] = vqaddq_s16(rxdataF_comp128[2],(*(int16x8_t*)&jitter[0]));
+
+      
+        ul_ch128+=6;
+        ul_ch_mag128+=3;
+        ul_ch_mag128b+=3;
+        rxdataF128+=6;
+        rxdataF_comp128+=3;
+              
+#endif
+    }
+  }
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+}
+
+
+
+
+// #if defined(__x86_64__) || defined(__i386__)
+// __m128i QAM_amp128U_0,QAM_amp128bU_0,QAM_amp128U_1,QAM_amp128bU_1;
+// #endif
+
+// void ulsch_channel_compensation_alamouti_NB_IoT(int32_t **rxdataF_ext,                 // For Distributed Alamouti Combining
+//     int32_t **ul_ch_estimates_ext_0,
+//     int32_t **ul_ch_estimates_ext_1,
+//     int32_t **ul_ch_mag_0,
+//     int32_t **ul_ch_magb_0,
+//     int32_t **ul_ch_mag_1,
+//     int32_t **ul_ch_magb_1,
+//     int32_t **rxdataF_comp_0,
+//     int32_t **rxdataF_comp_1,
+//     NB_IoT_DL_FRAME_PARMS *frame_parms,
+//     uint8_t symbol,
+//     uint8_t Qm,
+//     uint16_t nb_rb,
+//     uint8_t output_shift)
+// {
+// #if defined(__x86_64__) || defined(__i386__)
+//   uint16_t rb;
+//   __m128i *ul_ch128_0,*ul_ch128_1,*ul_ch_mag128_0,*ul_ch_mag128_1,*ul_ch_mag128b_0,*ul_ch_mag128b_1,*rxdataF128,*rxdataF_comp128_0,*rxdataF_comp128_1;
+//   uint8_t aarx;//,symbol_mod;
+//   __m128i mmtmpU0,mmtmpU1,mmtmpU2,mmtmpU3;
+
+//   //  symbol_mod = (symbol>=(7-frame_parms->Ncp)) ? symbol-(7-frame_parms->Ncp) : symbol;
+
+//   //    printf("comp: symbol %d\n",symbol);
+
+
+//   if (Qm == 4) {
+//     QAM_amp128U_0 = _mm_set1_epi16(QAM16_n1);
+//     QAM_amp128U_1 = _mm_set1_epi16(QAM16_n1);
+//   } else if (Qm == 6) {
+//     QAM_amp128U_0  = _mm_set1_epi16(QAM64_n1);
+//     QAM_amp128bU_0 = _mm_set1_epi16(QAM64_n2);
+
+//     QAM_amp128U_1  = _mm_set1_epi16(QAM64_n1);
+//     QAM_amp128bU_1 = _mm_set1_epi16(QAM64_n2);
+//   }
+
+//   for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+//     ul_ch128_0          = (__m128i *)&ul_ch_estimates_ext_0[aarx][symbol*frame_parms->N_RB_DL*12];
+//     ul_ch_mag128_0      = (__m128i *)&ul_ch_mag_0[aarx][symbol*frame_parms->N_RB_DL*12];
+//     ul_ch_mag128b_0     = (__m128i *)&ul_ch_magb_0[aarx][symbol*frame_parms->N_RB_DL*12];
+//     ul_ch128_1          = (__m128i *)&ul_ch_estimates_ext_1[aarx][symbol*frame_parms->N_RB_DL*12];
+//     ul_ch_mag128_1      = (__m128i *)&ul_ch_mag_1[aarx][symbol*frame_parms->N_RB_DL*12];
+//     ul_ch_mag128b_1     = (__m128i *)&ul_ch_magb_1[aarx][symbol*frame_parms->N_RB_DL*12];
+//     rxdataF128        = (__m128i *)&rxdataF_ext[aarx][symbol*frame_parms->N_RB_DL*12];
+//     rxdataF_comp128_0   = (__m128i *)&rxdataF_comp_0[aarx][symbol*frame_parms->N_RB_DL*12];
+//     rxdataF_comp128_1   = (__m128i *)&rxdataF_comp_1[aarx][symbol*frame_parms->N_RB_DL*12];
+
+
+//     for (rb=0; rb<nb_rb; rb++) {
+//       //      printf("comp: symbol %d rb %d\n",symbol,rb);
+//       if (Qm>2) {
+//         // get channel amplitude if not QPSK
+
+//         mmtmpU0 = _mm_madd_epi16(ul_ch128_0[0],ul_ch128_0[0]);
+
+//         mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+
+//         mmtmpU1 = _mm_madd_epi16(ul_ch128_0[1],ul_ch128_0[1]);
+//         mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//         mmtmpU0 = _mm_packs_epi32(mmtmpU0,mmtmpU1);
+
+//         ul_ch_mag128_0[0] = _mm_unpacklo_epi16(mmtmpU0,mmtmpU0);
+//         ul_ch_mag128b_0[0] = ul_ch_mag128_0[0];
+//         ul_ch_mag128_0[0] = _mm_mulhi_epi16(ul_ch_mag128_0[0],QAM_amp128U_0);
+//         ul_ch_mag128_0[0] = _mm_slli_epi16(ul_ch_mag128_0[0],2); // 2 to compensate the scale channel estimate
+
+//         ul_ch_mag128_0[1] = _mm_unpackhi_epi16(mmtmpU0,mmtmpU0);
+//         ul_ch_mag128b_0[1] = ul_ch_mag128_0[1];
+//         ul_ch_mag128_0[1] = _mm_mulhi_epi16(ul_ch_mag128_0[1],QAM_amp128U_0);
+//         ul_ch_mag128_0[1] = _mm_slli_epi16(ul_ch_mag128_0[1],2); // 2 to scale compensate the scale channel estimate
+
+//         mmtmpU0 = _mm_madd_epi16(ul_ch128_0[2],ul_ch128_0[2]);
+//         mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//         mmtmpU1 = _mm_packs_epi32(mmtmpU0,mmtmpU0);
+
+//         ul_ch_mag128_0[2] = _mm_unpacklo_epi16(mmtmpU1,mmtmpU1);
+//         ul_ch_mag128b_0[2] = ul_ch_mag128_0[2];
+
+//         ul_ch_mag128_0[2] = _mm_mulhi_epi16(ul_ch_mag128_0[2],QAM_amp128U_0);
+//         ul_ch_mag128_0[2] = _mm_slli_epi16(ul_ch_mag128_0[2],2);  //  2 to scale compensate the scale channel estimat
+
+
+//         ul_ch_mag128b_0[0] = _mm_mulhi_epi16(ul_ch_mag128b_0[0],QAM_amp128bU_0);
+//         ul_ch_mag128b_0[0] = _mm_slli_epi16(ul_ch_mag128b_0[0],2);  //  2 to scale compensate the scale channel estima
+
+
+//         ul_ch_mag128b_0[1] = _mm_mulhi_epi16(ul_ch_mag128b_0[1],QAM_amp128bU_0);
+//         ul_ch_mag128b_0[1] = _mm_slli_epi16(ul_ch_mag128b_0[1],2);   //  2 to scale compensate the scale channel estima
+
+//         ul_ch_mag128b_0[2] = _mm_mulhi_epi16(ul_ch_mag128b_0[2],QAM_amp128bU_0);
+//         ul_ch_mag128b_0[2] = _mm_slli_epi16(ul_ch_mag128b_0[2],2);   //  2 to scale compensate the scale channel estima
+
+
+
+
+//         mmtmpU0 = _mm_madd_epi16(ul_ch128_1[0],ul_ch128_1[0]);
+
+//         mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+
+//         mmtmpU1 = _mm_madd_epi16(ul_ch128_1[1],ul_ch128_1[1]);
+//         mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//         mmtmpU0 = _mm_packs_epi32(mmtmpU0,mmtmpU1);
+
+//         ul_ch_mag128_1[0] = _mm_unpacklo_epi16(mmtmpU0,mmtmpU0);
+//         ul_ch_mag128b_1[0] = ul_ch_mag128_1[0];
+//         ul_ch_mag128_1[0] = _mm_mulhi_epi16(ul_ch_mag128_1[0],QAM_amp128U_1);
+//         ul_ch_mag128_1[0] = _mm_slli_epi16(ul_ch_mag128_1[0],2); // 2 to compensate the scale channel estimate
+
+//         ul_ch_mag128_1[1] = _mm_unpackhi_epi16(mmtmpU0,mmtmpU0);
+//         ul_ch_mag128b_1[1] = ul_ch_mag128_1[1];
+//         ul_ch_mag128_1[1] = _mm_mulhi_epi16(ul_ch_mag128_1[1],QAM_amp128U_1);
+//         ul_ch_mag128_1[1] = _mm_slli_epi16(ul_ch_mag128_1[1],2); // 2 to scale compensate the scale channel estimate
+
+//         mmtmpU0 = _mm_madd_epi16(ul_ch128_1[2],ul_ch128_1[2]);
+//         mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//         mmtmpU1 = _mm_packs_epi32(mmtmpU0,mmtmpU0);
+
+//         ul_ch_mag128_1[2] = _mm_unpacklo_epi16(mmtmpU1,mmtmpU1);
+//         ul_ch_mag128b_1[2] = ul_ch_mag128_1[2];
+
+//         ul_ch_mag128_1[2] = _mm_mulhi_epi16(ul_ch_mag128_1[2],QAM_amp128U_0);
+//         ul_ch_mag128_1[2] = _mm_slli_epi16(ul_ch_mag128_1[2],2);  //  2 to scale compensate the scale channel estimat
+
+
+//         ul_ch_mag128b_1[0] = _mm_mulhi_epi16(ul_ch_mag128b_1[0],QAM_amp128bU_1);
+//         ul_ch_mag128b_1[0] = _mm_slli_epi16(ul_ch_mag128b_1[0],2);  //  2 to scale compensate the scale channel estima
+
+
+//         ul_ch_mag128b_1[1] = _mm_mulhi_epi16(ul_ch_mag128b_1[1],QAM_amp128bU_1);
+//         ul_ch_mag128b_1[1] = _mm_slli_epi16(ul_ch_mag128b_1[1],2);   //  2 to scale compensate the scale channel estima
+
+//         ul_ch_mag128b_1[2] = _mm_mulhi_epi16(ul_ch_mag128b_1[2],QAM_amp128bU_1);
+//         ul_ch_mag128b_1[2] = _mm_slli_epi16(ul_ch_mag128b_1[2],2);   //  2 to scale compensate the scale channel estima
+//       }
+
+
+//       /************************For Computing (y)*(h0*)********************************************/
+
+//       // multiply by conjugated channel
+//       mmtmpU0 = _mm_madd_epi16(ul_ch128_0[0],rxdataF128[0]);
+//       //  print_ints("re",&mmtmpU0);
+
+//       // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+//       mmtmpU1 = _mm_shufflelo_epi16(ul_ch128_0[0],_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)&conjugate[0]);
+//       //  print_ints("im",&mmtmpU1);
+//       mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[0]);
+//       // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+//       mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//       //  print_ints("re(shift)",&mmtmpU0);
+//       mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//       //  print_ints("im(shift)",&mmtmpU1);
+//       mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+//       mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+//       //        print_ints("c0",&mmtmpU2);
+//       //  print_ints("c1",&mmtmpU3);
+//       rxdataF_comp128_0[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+//       //        print_shorts("rx:",rxdataF128[0]);
+//       //        print_shorts("ch:",ul_ch128_0[0]);
+//       //        print_shorts("pack:",rxdataF_comp128_0[0]);
+
+//       // multiply by conjugated channel
+//       mmtmpU0 = _mm_madd_epi16(ul_ch128_0[1],rxdataF128[1]);
+//       // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+//       mmtmpU1 = _mm_shufflelo_epi16(ul_ch128_0[1],_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+//       mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[1]);
+//       // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+//       mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//       mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//       mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+//       mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+//       rxdataF_comp128_0[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+//       //        print_shorts("rx:",rxdataF128[1]);
+//       //        print_shorts("ch:",ul_ch128_0[1]);
+//       //        print_shorts("pack:",rxdataF_comp128_0[1]);
+//       //       multiply by conjugated channel
+//       mmtmpU0 = _mm_madd_epi16(ul_ch128_0[2],rxdataF128[2]);
+//       // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+//       mmtmpU1 = _mm_shufflelo_epi16(ul_ch128_0[2],_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+//       mmtmpU1 = _mm_madd_epi16(mmtmpU1,rxdataF128[2]);
+//       // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+//       mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//       mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//       mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+//       mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+//       rxdataF_comp128_0[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+//       //        print_shorts("rx:",rxdataF128[2]);
+//       //        print_shorts("ch:",ul_ch128_0[2]);
+//       //        print_shorts("pack:",rxdataF_comp128_0[2]);
+
+
+
+
+//       /*************************For Computing (y*)*(h1)************************************/
+//       // multiply by conjugated signal
+//       mmtmpU0 = _mm_madd_epi16(ul_ch128_1[0],rxdataF128[0]);
+//       //  print_ints("re",&mmtmpU0);
+
+//       // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+//       mmtmpU1 = _mm_shufflelo_epi16(rxdataF128[0],_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)&conjugate[0]);
+//       //  print_ints("im",&mmtmpU1);
+//       mmtmpU1 = _mm_madd_epi16(mmtmpU1,ul_ch128_1[0]);
+//       // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+//       mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//       //  print_ints("re(shift)",&mmtmpU0);
+//       mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//       //  print_ints("im(shift)",&mmtmpU1);
+//       mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+//       mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+//       //        print_ints("c0",&mmtmpU2);
+//       //  print_ints("c1",&mmtmpU3);
+//       rxdataF_comp128_1[0] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+//       //        print_shorts("rx:",rxdataF128[0]);
+//       //        print_shorts("ch_conjugate:",ul_ch128_1[0]);
+//       //        print_shorts("pack:",rxdataF_comp128_1[0]);
+
+
+//       // multiply by conjugated signal
+//       mmtmpU0 = _mm_madd_epi16(ul_ch128_1[1],rxdataF128[1]);
+//       // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+//       mmtmpU1 = _mm_shufflelo_epi16(rxdataF128[1],_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+//       mmtmpU1 = _mm_madd_epi16(mmtmpU1,ul_ch128_1[1]);
+//       // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+//       mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//       mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//       mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+//       mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+//       rxdataF_comp128_1[1] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+//       //        print_shorts("rx:",rxdataF128[1]);
+//       //        print_shorts("ch_conjugate:",ul_ch128_1[1]);
+//       //        print_shorts("pack:",rxdataF_comp128_1[1]);
+
+
+//       //       multiply by conjugated signal
+//       mmtmpU0 = _mm_madd_epi16(ul_ch128_1[2],rxdataF128[2]);
+//       // mmtmpU0 contains real part of 4 consecutive outputs (32-bit)
+//       mmtmpU1 = _mm_shufflelo_epi16(rxdataF128[2],_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_shufflehi_epi16(mmtmpU1,_MM_SHUFFLE(2,3,0,1));
+//       mmtmpU1 = _mm_sign_epi16(mmtmpU1,*(__m128i*)conjugate);
+//       mmtmpU1 = _mm_madd_epi16(mmtmpU1,ul_ch128_1[2]);
+//       // mmtmpU1 contains imag part of 4 consecutive outputs (32-bit)
+//       mmtmpU0 = _mm_srai_epi32(mmtmpU0,output_shift);
+//       mmtmpU1 = _mm_srai_epi32(mmtmpU1,output_shift);
+//       mmtmpU2 = _mm_unpacklo_epi32(mmtmpU0,mmtmpU1);
+//       mmtmpU3 = _mm_unpackhi_epi32(mmtmpU0,mmtmpU1);
+
+//       rxdataF_comp128_1[2] = _mm_packs_epi32(mmtmpU2,mmtmpU3);
+//       //        print_shorts("rx:",rxdataF128[2]);
+//       //        print_shorts("ch_conjugate:",ul_ch128_0[2]);
+//       //        print_shorts("pack:",rxdataF_comp128_1[2]);
+
+
+
+//       ul_ch128_0+=3;
+//       ul_ch_mag128_0+=3;
+//       ul_ch_mag128b_0+=3;
+//       ul_ch128_1+=3;
+//       ul_ch_mag128_1+=3;
+//       ul_ch_mag128b_1+=3;
+//       rxdataF128+=3;
+//       rxdataF_comp128_0+=3;
+//       rxdataF_comp128_1+=3;
+
+//     }
+//   }
+
+
+//   _mm_empty();
+//   _m_empty();
+// #endif
+// }
+
+
+
+/*
+void ulsch_alamouti_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms,// For Distributed Alamouti Receiver Combining
+                    int32_t **rxdataF_comp,
+                    int32_t **rxdataF_comp_0,
+                    int32_t **rxdataF_comp_1,
+                    int32_t **ul_ch_mag,
+                    int32_t **ul_ch_magb,
+                    int32_t **ul_ch_mag_0,
+                    int32_t **ul_ch_magb_0,
+                    int32_t **ul_ch_mag_1,
+                    int32_t **ul_ch_magb_1,
+                    uint8_t symbol,
+                    uint16_t nb_rb)
+{
+
+#if defined(__x86_64__) || defined(__i386__)
+  int16_t *rxF,*rxF0,*rxF1;
+  __m128i *ch_mag,*ch_magb,*ch_mag0,*ch_mag1,*ch_mag0b,*ch_mag1b;
+  uint8_t rb,re,aarx;
+  int32_t jj=(symbol*frame_parms->N_RB_DL*12);
+
+
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+    rxF      = (int16_t*)&rxdataF_comp[aarx][jj];
+    rxF0     = (int16_t*)&rxdataF_comp_0[aarx][jj];   // Contains (y)*(h0*)
+    rxF1     = (int16_t*)&rxdataF_comp_1[aarx][jj];   // Contains (y*)*(h1)
+    ch_mag   = (__m128i *)&ul_ch_mag[aarx][jj];
+    ch_mag0 = (__m128i *)&ul_ch_mag_0[aarx][jj];
+    ch_mag1 = (__m128i *)&ul_ch_mag_1[aarx][jj];
+    ch_magb = (__m128i *)&ul_ch_magb[aarx][jj];
+    ch_mag0b = (__m128i *)&ul_ch_magb_0[aarx][jj];
+    ch_mag1b = (__m128i *)&ul_ch_magb_1[aarx][jj];
+
+    for (rb=0; rb<nb_rb; rb++) {
+
+      for (re=0; re<12; re+=2) {
+
+        // Alamouti RX combining
+
+        rxF[0] = rxF0[0] + rxF1[2];                   // re((y0)*(h0*))+ re((y1*)*(h1)) = re(x0)
+        rxF[1] = rxF0[1] + rxF1[3];                   // im((y0)*(h0*))+ im((y1*)*(h1)) = im(x0)
+
+        rxF[2] = rxF0[2] - rxF1[0];                   // re((y1)*(h0*))- re((y0*)*(h1)) = re(x1)
+        rxF[3] = rxF0[3] - rxF1[1];                   // im((y1)*(h0*))- im((y0*)*(h1)) = im(x1)
+
+        rxF+=4;
+        rxF0+=4;
+        rxF1+=4;
+      }
+
+      // compute levels for 16QAM or 64 QAM llr unit
+      ch_mag[0] = _mm_adds_epi16(ch_mag0[0],ch_mag1[0]);
+      ch_mag[1] = _mm_adds_epi16(ch_mag0[1],ch_mag1[1]);
+      ch_mag[2] = _mm_adds_epi16(ch_mag0[2],ch_mag1[2]);
+      ch_magb[0] = _mm_adds_epi16(ch_mag0b[0],ch_mag1b[0]);
+      ch_magb[1] = _mm_adds_epi16(ch_mag0b[1],ch_mag1b[1]);
+      ch_magb[2] = _mm_adds_epi16(ch_mag0b[2],ch_mag1b[2]);
+
+      ch_mag+=3;
+      ch_mag0+=3;
+      ch_mag1+=3;
+      ch_magb+=3;
+      ch_mag0b+=3;
+      ch_mag1b+=3;
+    }
+  }
+
+  _mm_empty();
+  _m_empty();
+
+#endif
+}
+
+*/
+
+
+
+#if defined(__x86_64__) || defined(__i386__)
+__m128i avg128U;
+#elif defined(__arm__)
+int32x4_t avg128U;
+#endif
+
+void ulsch_channel_level_NB_IoT(int32_t **drs_ch_estimates_ext,
+                                NB_IoT_DL_FRAME_PARMS *frame_parms,
+                                int32_t *avg,
+                                uint16_t nb_rb)
+{
+
+  int16_t rb;
+  uint8_t aarx;
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i *ul_ch128;
+#elif defined(__arm__)
+  int16x4_t *ul_ch128;
+#endif
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+    //clear average level
+#if defined(__x86_64__) || defined(__i386__)
+    avg128U = _mm_setzero_si128();
+    ul_ch128=(__m128i *)drs_ch_estimates_ext[aarx];
+
+    for (rb=0; rb<nb_rb; rb++) {
+
+      avg128U = _mm_add_epi32(avg128U,_mm_madd_epi16(ul_ch128[0],ul_ch128[0]));
+      avg128U = _mm_add_epi32(avg128U,_mm_madd_epi16(ul_ch128[1],ul_ch128[1]));
+      avg128U = _mm_add_epi32(avg128U,_mm_madd_epi16(ul_ch128[2],ul_ch128[2]));
+
+      ul_ch128+=3;
+
+
+    }
+
+#elif defined(__arm__)
+    avg128U = vdupq_n_s32(0);
+    ul_ch128=(int16x4_t *)drs_ch_estimates_ext[aarx];
+
+    for (rb=0; rb<nb_rb; rb++) {
+
+       avg128U = vqaddq_s32(avg128U,vmull_s16(ul_ch128[0],ul_ch128[0]));
+       avg128U = vqaddq_s32(avg128U,vmull_s16(ul_ch128[1],ul_ch128[1]));
+       avg128U = vqaddq_s32(avg128U,vmull_s16(ul_ch128[2],ul_ch128[2]));
+       avg128U = vqaddq_s32(avg128U,vmull_s16(ul_ch128[3],ul_ch128[3]));
+       avg128U = vqaddq_s32(avg128U,vmull_s16(ul_ch128[4],ul_ch128[4]));
+       avg128U = vqaddq_s32(avg128U,vmull_s16(ul_ch128[5],ul_ch128[5]));
+       ul_ch128+=6;
+
+
+    }
+
+#endif
+
+    DevAssert( nb_rb );
+    avg[aarx] = (((int*)&avg128U)[0] +
+                 ((int*)&avg128U)[1] +
+                 ((int*)&avg128U)[2] +
+                 ((int*)&avg128U)[3])/(nb_rb*12);
+
+  }
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+}
+
+int32_t avgU[2];
+int32_t avgU_0[2],avgU_1[2]; // For the Distributed Alamouti Scheme
+
+void rx_ulsch_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
+	                   eNB_rxtx_proc_NB_IoT_t  *proc,
+                     uint8_t                 eNB_id,  // this is the effective sector id
+                     uint8_t                 UE_id,
+                     NB_IoT_eNB_NULSCH_t     **ulsch,
+                     uint8_t                 cooperation_flag)
+{
+  // flagMag = 0;
+  NB_IoT_eNB_COMMON      *common_vars  =  &eNB->common_vars;
+  NB_IoT_eNB_PUSCH       *pusch_vars   =  eNB->pusch_vars[UE_id];
+  NB_IoT_DL_FRAME_PARMS  *frame_parms  =  &eNB->frame_parms;
+
+  uint32_t   l,i;
+  int32_t    avgs;
+  uint8_t    log2_maxh = 0,aarx;
+
+ // int32_t    avgs_0,avgs_1;
+ // uint32_t   log2_maxh_0 = 0,log2_maxh_1 = 0;
+
+  uint8_t    harq_pid;
+  uint8_t    Qm;
+  uint16_t   rx_power_correction;
+  int16_t    *llrp;
+  int        subframe = proc->subframe_rx;
+
+  harq_pid = subframe2harq_pid_NB_IoT(frame_parms,proc->frame_rx,subframe);
+  Qm       = get_Qm_ul_NB_IoT(ulsch[UE_id]->harq_process->mcs,ulsch[UE_id]->harq_process->N_sc_RU);
+
+  rx_power_correction = 1;
+
+  if (ulsch[UE_id]->harq_process->nb_rb == 0) {
+    LOG_E(PHY,"PUSCH (%d/%x) nb_rb=0!\n", harq_pid,ulsch[UE_id]->rnti);
+    return;
+  }
+
+  for (l=0; l<frame_parms->symbols_per_tti; l++) { 
+
+    ulsch_extract_rbs_single_NB_IoT(common_vars->rxdataF[eNB_id],
+                                    pusch_vars->rxdataF_ext[eNB_id],
+                                    // ulsch[UE_id]->harq_process->first_rb, 
+                                    ulsch[UE_id]->harq_process->UL_RB_ID_NB_IoT, // index of UL NB_IoT resource block 
+                                    ulsch[UE_id]->harq_process->N_sc_RU, // number of subcarriers in UL
+                                    ulsch[UE_id]->harq_process->I_sc, // subcarrier indication field
+                                    ulsch[UE_id]->harq_process->nb_rb,
+                                    l%(frame_parms->symbols_per_tti/2),
+                                    l/(frame_parms->symbols_per_tti/2),
+                                    frame_parms);
+
+    lte_ul_channel_estimation_NB_IoT(eNB,proc,
+                                     eNB_id,
+                                     UE_id,
+                                     l%(frame_parms->symbols_per_tti/2),
+                                     l/(frame_parms->symbols_per_tti/2),
+                                     cooperation_flag);
+  }
+
+  // if(cooperation_flag == 2) {
+  //   for (i=0; i<frame_parms->nb_antennas_rx; i++) {
+  //     pusch_vars->ulsch_power_0[i] = signal_energy(pusch_vars->drs_ch_estimates_0[eNB_id][i],
+  //                                        ulsch[UE_id]->harq_process->nb_rb*12)*rx_power_correction;
+  //     pusch_vars->ulsch_power_1[i] = signal_energy(pusch_vars->drs_ch_estimates_1[eNB_id][i],
+  //                                        ulsch[UE_id]->harq_process->nb_rb*12)*rx_power_correction;
+  //   }
+  // } else {
+    for (i=0; i<frame_parms->nb_antennas_rx; i++) {
+      /*
+      pusch_vars->ulsch_power[i] = signal_energy_nodc(pusch_vars->drs_ch_estimates[eNB_id][i],
+                                       ulsch[UE_id]->harq_processes[harq_pid]->nb_rb*12)*rx_power_correction;
+
+      */
+      //////////////////////// NB_IoT: maybe, should be defined for NB-IoT
+      pusch_vars->ulsch_power[i] = signal_energy_nodc(pusch_vars->drs_ch_estimates[eNB_id][i],
+							  ulsch[UE_id]->harq_process->nb_rb*12);
+      
+#ifdef LOCALIZATION
+      pusch_vars->subcarrier_power = (int32_t *)malloc(ulsch[UE_id]->harq_process->nb_rb*12*sizeof(int32_t));
+      pusch_vars->active_subcarrier = subcarrier_energy(pusch_vars->drs_ch_estimates[eNB_id][i],
+                                          ulsch[UE_id]->harq_process->nb_rb*12, pusch_vars->subcarrier_power, rx_power_correction);
+#endif
+    }
+ // }
+
+  //write_output("rxdataF_ext.m","rxF_ext",pusch_vars->rxdataF_ext[eNB_id][0],300*(frame_parms->symbols_per_tti-ulsch[UE_id]->srs_active),1,1);
+  //write_output("ulsch_chest.m","drs_est",pusch_vars->drs_ch_estimates[eNB_id][0],300*(frame_parms->symbols_per_tti-ulsch[UE_id]->srs_active),1,1);
+
+
+//   if(cooperation_flag == 2) {
+//     ulsch_channel_level_NB_IoT(pusch_vars->drs_ch_estimates_0[eNB_id],
+//                                frame_parms,
+//                                avgU_0,
+//                                ulsch[UE_id]->harq_process->nb_rb);
+
+//     //  printf("[ULSCH] avg_0[0] %d\n",avgU_0[0]);
+
+
+//     avgs_0 = 0;
+
+//     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
+//       avgs_0 = cmax(avgs_0,avgU_0[(aarx<<1)]);
+
+//     log2_maxh_0 = (log2_approx(avgs_0)/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+3;
+// #ifdef DEBUG_ULSCH
+//     printf("[ULSCH] log2_maxh_0 = %d (%d,%d)\n",log2_maxh_0,avgU_0[0],avgs_0);
+// #endif
+
+//     ulsch_channel_level_NB_IoT(pusch_vars->drs_ch_estimates_1[eNB_id],
+//                               frame_parms,
+//                               avgU_1,
+//                               ulsch[UE_id]->harq_process->nb_rb);
+
+//     //  printf("[ULSCH] avg_1[0] %d\n",avgU_1[0]);
+
+
+//     avgs_1 = 0;
+
+//     for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
+//       avgs_1 = cmax(avgs_1,avgU_1[(aarx<<1)]);
+
+//     log2_maxh_1 = (log2_approx(avgs_1)/2) + log2_approx(frame_parms->nb_antennas_rx-1)+3;
+// #ifdef DEBUG_ULSCH
+//     printf("[ULSCH] log2_maxh_1 = %d (%d,%d)\n",log2_maxh_1,avgU_1[0],avgs_1);
+// #endif
+//     log2_maxh = max(log2_maxh_0,log2_maxh_1);
+//   } else {
+    ulsch_channel_level_NB_IoT(pusch_vars->drs_ch_estimates[eNB_id],
+                               frame_parms,
+                               avgU,
+                               ulsch[UE_id]->harq_process->nb_rb);
+
+    //  printf("[ULSCH] avg[0] %d\n",avgU[0]);
+
+
+    avgs = 0;
+
+    for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++)
+      avgs = cmax(avgs,avgU[(aarx<<1)]);
+
+    //      log2_maxh = 4+(log2_approx(avgs)/2);
+
+    log2_maxh = (log2_approx(avgs)/2)+ log2_approx(frame_parms->nb_antennas_rx-1)+4;
+
+#ifdef DEBUG_ULSCH
+    printf("[ULSCH] log2_maxh = %d (%d,%d)\n",log2_maxh,avgU[0],avgs);
+#endif
+  //}
+
+  for (l=0; l<frame_parms->symbols_per_tti; l++) {
+
+    if (((frame_parms->Ncp == 0) && ((l==3) || (l==10)))||   // skip pilots
+        ((frame_parms->Ncp == 1) && ((l==2) || (l==8)))) {
+      l++;
+    }
+
+    // if(cooperation_flag == 2) {
+
+    //   ulsch_channel_compensation_alamouti_NB_IoT(
+    //     pusch_vars->rxdataF_ext[eNB_id],
+    //     pusch_vars->drs_ch_estimates_0[eNB_id],
+    //     pusch_vars->drs_ch_estimates_1[eNB_id],
+    //     pusch_vars->ul_ch_mag_0[eNB_id],
+    //     pusch_vars->ul_ch_magb_0[eNB_id],
+    //     pusch_vars->ul_ch_mag_1[eNB_id],
+    //     pusch_vars->ul_ch_magb_1[eNB_id],
+    //     pusch_vars->rxdataF_comp_0[eNB_id],
+    //     pusch_vars->rxdataF_comp_1[eNB_id],
+    //     frame_parms,
+    //     l,
+    //     Qm,
+    //     ulsch[UE_id]->harq_process->nb_rb,
+    //     log2_maxh);
+
+    //   ulsch_alamouti_NB_IoT(frame_parms,
+    //                  pusch_vars->rxdataF_comp[eNB_id],
+    //                  pusch_vars->rxdataF_comp_0[eNB_id],
+    //                  pusch_vars->rxdataF_comp_1[eNB_id],
+    //                  pusch_vars->ul_ch_mag[eNB_id],
+    //                  pusch_vars->ul_ch_magb[eNB_id],
+    //                  pusch_vars->ul_ch_mag_0[eNB_id],
+    //                  pusch_vars->ul_ch_magb_0[eNB_id],
+    //                  pusch_vars->ul_ch_mag_1[eNB_id],
+    //                  pusch_vars->ul_ch_magb_1[eNB_id],
+    //                  l,
+    //                  ulsch[UE_id]->harq_process->nb_rb);
+    // } else {
+      ulsch_channel_compensation_NB_IoT(
+        pusch_vars->rxdataF_ext[eNB_id],
+        pusch_vars->drs_ch_estimates[eNB_id],
+        pusch_vars->ul_ch_mag[eNB_id],
+        pusch_vars->ul_ch_magb[eNB_id],
+        pusch_vars->rxdataF_comp[eNB_id],
+        frame_parms,
+        l,
+        Qm,
+        ulsch[UE_id]->harq_process->nb_rb,
+        log2_maxh); // log2_maxh+I0_shift
+
+   // }
+
+
+    //eren
+    /* if(flagMag == 0){
+    //writing for the first time
+    write_output(namepointer_log2,"xxx",log2_maxh,1,1,12);
+
+    write_output(namepointer_chMag,"xxx",pusch_vars->ul_ch_mag[eNB_id][0],300,1,11);
+
+    //namepointer_chMag = NULL;
+    flagMag=1;
+    }*/
+
+    if (frame_parms->nb_antennas_rx > 1)
+      ulsch_detection_mrc_NB_IoT(frame_parms,
+                          pusch_vars->rxdataF_comp[eNB_id],
+                          pusch_vars->ul_ch_mag[eNB_id],
+                          pusch_vars->ul_ch_magb[eNB_id],
+                          l,
+                          ulsch[UE_id]->harq_process->nb_rb);
+
+#ifndef OFDMA_ULSCH
+
+    if ((eNB->measurements->n0_power_dB[0]+3)<pusch_vars->ulsch_power[0]) {
+
+      freq_equalization_NB_IoT(frame_parms,
+                               pusch_vars->rxdataF_comp[eNB_id],
+                               pusch_vars->ul_ch_mag[eNB_id],
+                               pusch_vars->ul_ch_magb[eNB_id],
+                               l,
+                               ulsch[UE_id]->harq_process->nb_rb*12,
+                               Qm);
+    }
+
+#endif
+  }
+
+#ifndef OFDMA_ULSCH
+
+  //#ifdef DEBUG_ULSCH
+  // Inverse-Transform equalized outputs
+  //  printf("Doing IDFTs\n");
+  lte_idft_NB_IoT(frame_parms,
+                  (uint32_t*)pusch_vars->rxdataF_comp[eNB_id][0],
+                  ulsch[UE_id]->harq_process->nb_rb*12);
+  //  printf("Done\n");
+  //#endif //DEBUG_ULSCH
+
+#endif
+
+
+
+  llrp = (int16_t*)&pusch_vars->llr[0];
+
+  T(T_ENB_PHY_PUSCH_IQ, T_INT(eNB_id), T_INT(UE_id), T_INT(proc->frame_rx),
+    T_INT(subframe), T_INT(ulsch[UE_id]->harq_process->nb_rb),
+    T_INT(frame_parms->N_RB_UL), T_INT(frame_parms->symbols_per_tti),
+    T_BUFFER(pusch_vars->rxdataF_comp[eNB_id][0],
+             2 * /* ulsch[UE_id]->harq_processes[harq_pid]->nb_rb */ frame_parms->N_RB_UL *12*frame_parms->symbols_per_tti*2));
+
+  for (l=0; l<frame_parms->symbols_per_tti; l++) {
+
+    if (((frame_parms->Ncp == 0) && ((l==3) || (l==10)))||   // skip pilots
+        ((frame_parms->Ncp == 1) && ((l==2) || (l==8)))) {
+      l++;
+    }
+
+    switch (Qm) {
+    case 1: 
+      printf("To be developped\n");
+    break; 
+    case 2 :
+      ulsch_qpsk_llr_NB_IoT(frame_parms,
+                            pusch_vars->rxdataF_comp[eNB_id],
+                            pusch_vars->llr,
+                            l,
+                            ulsch[UE_id]->harq_process->nb_rb,
+                            &llrp);
+      break;
+
+    default:
+#ifdef DEBUG_ULSCH
+      printf("ulsch_demodulation.c (rx_ulsch): Unknown Qm!!!!\n");
+#endif //DEBUG_ULSCH
+      break;
+    }
+  }
+
+}
+
diff --git a/openair1/PHY/LTE_TRANSPORT/vars_NB_IoT.h b/openair1/PHY/LTE_TRANSPORT/vars_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..0e5ff67e0dd9948576d0e108525749c969f4f5c2
--- /dev/null
+++ b/openair1/PHY/LTE_TRANSPORT/vars_NB_IoT.h
@@ -0,0 +1,36 @@
+/*
+ * 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.0  (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
+ */
+
+//#include "dlsch_tbs.h"
+//#include "dlsch_tbs_full.h"
+//#include "sss.h"
+#ifndef __PHY_LTE_TRANSPORT_VARS_NB_IOT__H__
+#define __PHY_LTE_TRANSPORT_VARS_NB_IOT__H__
+
+unsigned char cs_ri_normal_NB_IoT[4]    = {1,4,7,10};
+unsigned char cs_ri_extended_NB_IoT[4]  = {0,3,5,8};
+unsigned char cs_ack_normal_NB_IoT[4]   = {2,3,8,9};
+unsigned char cs_ack_extended_NB_IoT[4] = {1,2,6,7};
+
+
+int8_t wACK_RX_NB_IoT[5][4] = {{-1,-1,-1,-1},{-1,1,-1,1},{-1,-1,1,1},{-1,1,1,-1},{1,1,1,1}};
+
+#endif
diff --git a/openair1/PHY/TOOLS/time_meas_NB_IoT.c b/openair1/PHY/TOOLS/time_meas_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..8236a16ad587b4427609204a0513bbd2c6ae27dc
--- /dev/null
+++ b/openair1/PHY/TOOLS/time_meas_NB_IoT.c
@@ -0,0 +1,117 @@
+/*
+ * 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.0  (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
+ */
+
+#include <stdio.h>
+#include "time_meas_NB_IoT.h"
+#include <math.h>
+#include <unistd.h>
+
+// global var for openair performance profiler
+int opp_enabled = 0;
+
+
+double get_cpu_freq_GHz(void) {
+
+  time_stats_t ts = {0};
+  reset_meas(&ts);
+  ts.trials++;
+  ts.in = rdtsc_oai();
+  sleep(1);
+  ts.diff = (rdtsc_oai()-ts.in);
+  cpu_freq_GHz = (double)ts.diff/1000000000;
+  printf("CPU Freq is %f \n", cpu_freq_GHz);
+  return cpu_freq_GHz; 
+}
+
+void print_meas_now(time_stats_t *ts, const char* name, FILE* file_name){
+
+  if (opp_enabled) {
+
+    //static double cpu_freq_GHz = 3.2;
+
+    //if (cpu_freq_GHz == 0.0)
+      //cpu_freq_GHz = get_cpu_freq_GHz(); // super slow
+
+    if (ts->trials>0) {
+
+      //fprintf(file_name,"Name %25s: Processing %15.3f ms for SF %d, diff_now %15.3f \n", name,(ts->diff_now/(cpu_freq_GHz*1000000.0)),subframe,ts->diff_now);
+      fprintf(file_name,"%15.3f ms, diff_now %15.3f \n",(ts->diff_now/(cpu_freq_GHz*1000000.0)),(double)ts->diff_now);
+      
+    }
+  }
+}
+
+void print_meas(time_stats_t *ts, const char* name, time_stats_t * total_exec_time, time_stats_t * sf_exec_time)
+{
+
+  if (opp_enabled) {
+
+    static int first_time = 0;
+    static double cpu_freq_GHz = 0.0;
+
+    if (cpu_freq_GHz == 0.0)
+      cpu_freq_GHz = get_cpu_freq_GHz();
+
+    if (first_time == 0) {
+      first_time=1;
+
+      if ((total_exec_time == NULL) || (sf_exec_time== NULL))
+        fprintf(stderr, "%25s  %25s  %25s  %25s %25s %6f\n","Name","Total","Per Trials",   "Num Trials","CPU_F_GHz", cpu_freq_GHz);
+      else
+        fprintf(stderr, "%25s  %25s  %25s  %20s %15s %6f\n","Name","Total","Average/Frame","Trials",    "CPU_F_GHz", cpu_freq_GHz);
+    }
+
+    if (ts->trials>0) {
+      //printf("%20s: total: %10.3f ms, average: %10.3f us (%10d trials)\n", name, ts->diff/cpu_freq_GHz/1000000.0, ts->diff/ts->trials/cpu_freq_GHz/1000.0, ts->trials);
+
+      if ((total_exec_time == NULL) || (sf_exec_time== NULL)) {
+        fprintf(stderr, "%25s:  %15.3f ms ;  %15.3f us; %15d;\n",
+                name,
+                (ts->diff/cpu_freq_GHz/1000000.0),
+                (ts->diff/ts->trials/cpu_freq_GHz/1000.0),
+                ts->trials);
+      } else {
+        fprintf(stderr, "%25s:  %15.3f ms (%5.2f%%); %15.3f us (%5.2f%%); %15d;\n",
+                name,
+                (ts->diff/cpu_freq_GHz/1000000.0),
+                ((ts->diff/cpu_freq_GHz/1000000.0)/(total_exec_time->diff/cpu_freq_GHz/1000000.0))*100,  // percentage
+                (ts->diff/ts->trials/cpu_freq_GHz/1000.0),
+                ((ts->diff/ts->trials/cpu_freq_GHz/1000.0)/(sf_exec_time->diff/sf_exec_time->trials/cpu_freq_GHz/1000.0))*100,  // percentage
+                ts->trials);
+      }
+    }
+  }
+
+}
+
+double get_time_meas_us(time_stats_t *ts)
+{
+
+  static double cpu_freq_GHz = 0.0;
+
+  if (cpu_freq_GHz == 0.0)
+    cpu_freq_GHz = get_cpu_freq_GHz();
+
+  if (ts->trials>0)
+    return  (ts->diff/ts->trials/cpu_freq_GHz/1000.0);
+
+  return 0;
+}
diff --git a/openair1/PHY/TOOLS/time_meas_NB_IoT.h b/openair1/PHY/TOOLS/time_meas_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d3a55879bac8aa072f0cff0aedbb54974a15dca
--- /dev/null
+++ b/openair1/PHY/TOOLS/time_meas_NB_IoT.h
@@ -0,0 +1,158 @@
+/*
+ * 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.0  (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 __TIME_MEAS_DEFS_NB_IoT__H__
+#define __TIME_MEAS_DEFS_NB_IoT__H__
+
+#include <unistd.h>
+#include <math.h>
+#include <stdint.h>
+#include <time.h>
+#include <errno.h>
+#include <stdio.h>
+#include <pthread.h>
+#include <linux/kernel.h>
+#include <linux/types.h>
+// global var to enable openair performance profiler
+
+extern int opp_enabled_NB_IoT;
+
+double cpu_freq_GHz;
+#if defined(__x86_64__) || defined(__i386__)
+
+typedef struct {
+
+  long long in;
+  long long diff;
+  long long diff_now;
+  long long p_time; /*!< \brief absolute process duration */
+  long long diff_square; /*!< \brief process duration square */
+  long long max;
+  int trials;
+  int meas_flag;
+} time_stats_t_NB_IoT;
+#elif defined(__arm__)
+typedef struct {
+  uint32_t in;
+  uint32_t diff_now;
+  uint32_t diff;
+  uint32_t p_time; /*!< \brief absolute process duration */
+  uint32_t diff_square; /*!< \brief process duration square */
+  uint32_t max;
+  int trials;
+} time_stats_t_NB_IoT;
+
+#endif
+static inline void start_meas_NB_IoT(time_stats_t_NB_IoT *ts) __attribute__((always_inline));
+static inline void stop_meas_NB_IoT(time_stats_t_NB_IoT *ts) __attribute__((always_inline));
+
+/*
+void print_meas_now(time_stats_t *ts, const char* name, FILE* file_name);
+void print_meas(time_stats_t *ts, const char* name, time_stats_t * total_exec_time, time_stats_t * sf_exec_time);
+double get_time_meas_us(time_stats_t *ts);
+double get_cpu_freq_GHz(void);
+*/
+#if defined(__i386__)
+static inline unsigned long long rdtsc_oai_NB_IoT(void) __attribute__((always_inline));
+static inline unsigned long long rdtsc_oai_NB_IoT(void)
+{
+  unsigned long long int x;
+  __asm__ volatile (".byte 0x0f, 0x31" : "=A" (x));
+  return x;
+}
+#elif defined(__x86_64__)
+static inline unsigned long long rdtsc_oai_NB_IoT(void) __attribute__((always_inline));
+static inline unsigned long long rdtsc_oai_NB_IoT(void)
+{
+  unsigned long long a, d;
+  __asm__ volatile ("rdtsc" : "=a" (a), "=d" (d));
+  return (d<<32) | a;
+}
+
+#elif defined(__arm__)
+static inline uint32_t rdtsc_oai_NB_IoT(void) __attribute__((always_inline));
+static inline uint32_t rdtsc_oai_NB_IoT(void)
+{
+  uint32_t r = 0;
+  asm volatile("mrc p15, 0, %0, c9, c13, 0" : "=r"(r) );
+  return r;
+}
+#endif
+
+
+static inline void start_meas_NB_IoT(time_stats_t_NB_IoT *ts)
+{
+
+  if (opp_enabled_NB_IoT) {
+    if (ts->meas_flag==0) {
+      ts->trials++;
+      ts->in = rdtsc_oai_NB_IoT();
+      ts->meas_flag=1;
+    }
+    else {
+      ts->in = rdtsc_oai_NB_IoT();
+    }
+  }
+}
+
+static inline void stop_meas_NB_IoT(time_stats_t_NB_IoT *ts)
+{
+
+  if (opp_enabled_NB_IoT) {
+    long long out = rdtsc_oai_NB_IoT();
+    
+    ts->diff_now = (out-ts->in);
+    
+    ts->diff_now = (out-ts->in);
+    ts->diff += (out-ts->in);
+    /// process duration is the difference between two clock points
+    ts->p_time = (out-ts->in);
+    ts->diff_square += (out-ts->in)*(out-ts->in);
+    
+    if ((out-ts->in) > ts->max)
+      ts->max = out-ts->in;
+
+    ts->meas_flag=0;    
+  }
+}
+
+static inline void reset_meas_NB_IoT(time_stats_t_NB_IoT *ts) {
+
+  ts->trials=0;
+  ts->diff=0;
+  ts->diff_now=0;
+  ts->p_time=0;
+  ts->diff_square=0;
+  ts->max=0;
+  ts->meas_flag=0;
+  
+}
+
+static inline void copy_meas_NB_IoT(time_stats_t_NB_IoT *dst_ts,time_stats_t_NB_IoT *src_ts)
+{
+
+  if (opp_enabled_NB_IoT) {
+    dst_ts->trials=src_ts->trials;
+    dst_ts->diff=src_ts->diff;
+    dst_ts->max=src_ts->max;
+  }
+}
+#endif
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 272051000664a4dc4917c5917e9f90b286df2389..513ed9c56d059f3356c5c42148a0b0f8c24f037f 100644
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -128,6 +128,7 @@ static inline void* malloc16_clear( size_t size )
 #ifdef OPENAIR_LTE
 
 #include "PHY/LTE_TRANSPORT/defs.h"
+
 #include <pthread.h>
 
 #include "targets/ARCH/COMMON/common_lib.h"
@@ -138,6 +139,8 @@ static inline void* malloc16_clear( size_t size )
 
 #define NB_BANDS_MAX 8
 
+#include "defs_common.h"
+
 #ifdef OCP_FRAMEWORK
 #include <enums.h>
 #else
@@ -187,34 +190,7 @@ typedef struct {
 
 } PHY_VARS_RN;
 
-/// Context data structure for RX/TX portion of subframe processing
-typedef struct {
-  /// Component Carrier index
-  uint8_t              CC_id;
-  /// timestamp transmitted to HW
-  openair0_timestamp timestamp_tx;
-  /// subframe to act upon for transmission
-  int subframe_tx;
-  /// subframe to act upon for reception
-  int subframe_rx;
-  /// frame to act upon for transmission
-  int frame_tx;
-  /// frame to act upon for reception
-  int frame_rx;
-  /// \brief Instance count for RXn-TXnp4 processing thread.
-  /// \internal This variable is protected by \ref mutex_rxtx.
-  int instance_cnt_rxtx;
-  /// pthread structure for RXn-TXnp4 processing thread
-  pthread_t pthread_rxtx;
-  /// pthread attributes for RXn-TXnp4 processing thread
-  pthread_attr_t attr_rxtx;
-  /// condition variable for tx processing thread
-  pthread_cond_t cond_rxtx;
-  /// mutex for RXn-TXnp4 processing thread
-  pthread_mutex_t mutex_rxtx;
-  /// scheduling parameters for RXn-TXnp4 thread
-  struct sched_param sched_param_rxtx;
-} eNB_rxtx_proc_t;
+
 
 typedef struct {
   struct PHY_VARS_eNB_s *eNB;
@@ -230,137 +206,7 @@ typedef struct {
   int G;
 } te_params;
 
-/// Context data structure for eNB subframe processing
-typedef struct eNB_proc_t_s {
-  /// Component Carrier index
-  uint8_t              CC_id;
-  /// thread index
-  int thread_index;
-  /// timestamp received from HW
-  openair0_timestamp timestamp_rx;
-  /// timestamp to send to "slave rru"
-  openair0_timestamp timestamp_tx;
-  /// subframe to act upon for reception
-  int subframe_rx;
-  /// symbol mask for IF4p5 reception per subframe
-  uint32_t symbol_mask[10];
-  /// subframe to act upon for PRACH
-  int subframe_prach;
-  /// frame to act upon for reception
-  int frame_rx;
-  /// frame to act upon for transmission
-  int frame_tx;
-  /// frame offset for secondary eNBs (to correct for frame asynchronism at startup)
-  int frame_offset;
-  /// frame to act upon for PRACH
-  int frame_prach;
-  /// \internal This variable is protected by \ref mutex_fep.
-  int instance_cnt_fep;
-  /// \internal This variable is protected by \ref mutex_td.
-  int instance_cnt_td;
-  /// \internal This variable is protected by \ref mutex_te.
-  int instance_cnt_te;
-  /// \brief Instance count for FH processing thread.
-  /// \internal This variable is protected by \ref mutex_FH.
-  int instance_cnt_FH;
-  /// \brief Instance count for rx processing thread.
-  /// \internal This variable is protected by \ref mutex_prach.
-  int instance_cnt_prach;
-  // instance count for over-the-air eNB synchronization
-  int instance_cnt_synch;
-  /// \internal This variable is protected by \ref mutex_asynch_rxtx.
-  int instance_cnt_asynch_rxtx;
-  /// pthread structure for FH processing thread
-  pthread_t pthread_FH;
-  /// pthread structure for eNB single processing thread
-  pthread_t pthread_single;
-  /// pthread structure for asychronous RX/TX processing thread
-  pthread_t pthread_asynch_rxtx;
-  /// flag to indicate first RX acquisition
-  int first_rx;
-  /// flag to indicate first TX transmission
-  int first_tx;
-  /// pthread attributes for parallel fep thread
-  pthread_attr_t attr_fep;
-  /// pthread attributes for parallel turbo-decoder thread
-  pthread_attr_t attr_td;
-  /// pthread attributes for parallel turbo-encoder thread
-  pthread_attr_t attr_te;
-  /// pthread attributes for FH processing thread
-  pthread_attr_t attr_FH;
-  /// pthread attributes for single eNB processing thread
-  pthread_attr_t attr_single;
-  /// pthread attributes for prach processing thread
-  pthread_attr_t attr_prach;
-  /// pthread attributes for over-the-air synch thread
-  pthread_attr_t attr_synch;
-  /// pthread attributes for asynchronous RX thread
-  pthread_attr_t attr_asynch_rxtx;
-  /// scheduling parameters for parallel fep thread
-  struct sched_param sched_param_fep;
-  /// scheduling parameters for parallel turbo-decoder thread
-  struct sched_param sched_param_td;
-  /// scheduling parameters for parallel turbo-encoder thread
-  struct sched_param sched_param_te;
-  /// scheduling parameters for FH thread
-  struct sched_param sched_param_FH;
-  /// scheduling parameters for single eNB thread
-  struct sched_param sched_param_single;
-  /// scheduling parameters for prach thread
-  struct sched_param sched_param_prach;
-  /// scheduling parameters for over-the-air synchronization thread
-  struct sched_param sched_param_synch;
-  /// scheduling parameters for asynch_rxtx thread
-  struct sched_param sched_param_asynch_rxtx;
-  /// pthread structure for parallel fep thread
-  pthread_t pthread_fep;
-  /// pthread structure for parallel turbo-decoder thread
-  pthread_t pthread_td;
-  /// pthread structure for parallel turbo-encoder thread
-  pthread_t pthread_te;
-  /// pthread structure for PRACH thread
-  pthread_t pthread_prach;
-  /// pthread structure for eNB synch thread
-  pthread_t pthread_synch;
-  /// condition variable for parallel fep thread
-  pthread_cond_t cond_fep;
-  /// condition variable for parallel turbo-decoder thread
-  pthread_cond_t cond_td;
-  /// condition variable for parallel turbo-encoder thread
-  pthread_cond_t cond_te;
-  /// condition variable for FH thread
-  pthread_cond_t cond_FH;
-  /// condition variable for PRACH processing thread;
-  pthread_cond_t cond_prach;
-  // condition variable for over-the-air eNB synchronization
-  pthread_cond_t cond_synch;
-  /// condition variable for asynch RX/TX thread
-  pthread_cond_t cond_asynch_rxtx;
-  /// mutex for parallel fep thread
-  pthread_mutex_t mutex_fep;
-  /// mutex for parallel turbo-decoder thread
-  pthread_mutex_t mutex_td;
-  /// mutex for parallel turbo-encoder thread
-  pthread_mutex_t mutex_te;
-  /// mutex for FH
-  pthread_mutex_t mutex_FH;
-  /// mutex for PRACH thread
-  pthread_mutex_t mutex_prach;
-  // mutex for over-the-air eNB synchronization
-  pthread_mutex_t mutex_synch;
-  /// mutex for asynch RX/TX thread
-  pthread_mutex_t mutex_asynch_rxtx;
-  /// parameters for turbo-decoding worker thread
-  td_params tdp;
-  /// parameters for turbo-encoding worker thread
-  te_params tep;
-  /// set of scheduling variables RXn-TXnp4 threads
-  eNB_rxtx_proc_t proc_rxtx[2];
-  /// number of slave threads
-  int                  num_slaves;
-  /// array of pointers to slaves
-  struct eNB_proc_t_s           **slave_proc;
-} eNB_proc_t;
+
 
 
 /// Context data structure for RX/TX portion of subframe processing
@@ -426,6 +272,8 @@ typedef struct {
   UE_rxtx_proc_t proc_rxtx[2];
 } UE_proc_t;
 
+
+
 /// Top-level PHY Data Structure for eNB
 typedef struct PHY_VARS_eNB_s {
   /// Module ID indicator for this instance
@@ -466,12 +314,13 @@ typedef struct PHY_VARS_eNB_s {
   LTE_eNB_PUSCH       *pusch_vars[NUMBER_OF_UE_MAX];
   LTE_eNB_PRACH        prach_vars;
   LTE_eNB_DLSCH_t     *dlsch[NUMBER_OF_UE_MAX][2];   // Nusers times two spatial streams
-  LTE_eNB_ULSCH_t     *ulsch[NUMBER_OF_UE_MAX+1];      // Nusers + number of RA
+  LTE_eNB_ULSCH_t     *ulsch[NUMBER_OF_UE_MAX+1];      // Nusers + number of RA (the ulsch[0] contains RAR)
   LTE_eNB_DLSCH_t     *dlsch_SI,*dlsch_ra;
   LTE_eNB_DLSCH_t     *dlsch_MCH;
   LTE_eNB_UE_stats     UE_stats[NUMBER_OF_UE_MAX];
   LTE_eNB_UE_stats    *UE_stats_ptr[NUMBER_OF_UE_MAX];
 
+
   /// cell-specific reference symbols
   uint32_t         lte_gold_table[20][2][14];
 
@@ -563,7 +412,6 @@ typedef struct PHY_VARS_eNB_s {
   // Pointers for active physicalConfigDedicated to be applied in current subframe
   struct PhysicalConfigDedicated *physicalConfigDedicated[NUMBER_OF_UE_MAX];
 
-
   uint32_t rb_mask_ul[4];
 
   /// Information regarding TM5
@@ -935,6 +783,7 @@ void exit_fun(const char* s);
 
 static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
 
+  // lock the mutex, if lock successfully, it would return the 0, the other value means failed
   if (pthread_mutex_lock(mutex) != 0) {
     LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
     exit_fun("nothing to add");
diff --git a/openair1/PHY/defs_NB_IoT.h b/openair1/PHY/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..fc5811a960966ee7f40fb4e1e53a15a4e4144e5a
--- /dev/null
+++ b/openair1/PHY/defs_NB_IoT.h
@@ -0,0 +1,1110 @@
+/*
+ * 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.0  (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/defs.h
+ \brief Top-level defines and structure definitions
+ \author R. Knopp, F. Kaltenberger
+ \date 2011
+ \version 0.1
+ \company Eurecom
+ \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
+ \note
+ \warning
+*/
+#ifndef __PHY_DEFS_NB_IOT__H__
+#define __PHY_DEFS_NB_IOT__H__
+
+#define _GNU_SOURCE 
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <math.h>
+#include "common_lib.h"
+
+//#include <complex.h>
+#include "assertions.h"
+#ifdef MEX
+# define msg mexPrintf
+#else
+# ifdef OPENAIR2
+#   if ENABLE_RAL
+#     include "collection/hashtable/hashtable.h"
+#     include "COMMON/ral_messages_types.h"
+#     include "UTIL/queue.h"
+#   endif
+#   include "log.h"
+#   define msg(aRGS...) LOG_D(PHY, ##aRGS)
+# else
+#   define msg printf
+# endif
+#endif
+//use msg in the real-time thread context
+#define msg_nrt printf
+//use msg_nrt in the non real-time context (for initialization, ...)
+#ifndef malloc16
+#  ifdef __AVX2__
+#    define malloc16(x) memalign(32,x)
+#  else
+#    define malloc16(x) memalign(16,x)
+#  endif
+#endif
+#define free16(y,x) free(y)
+#define bigmalloc malloc
+#define bigmalloc16 malloc16
+#define openair_free(y,x) free((y))
+#define PAGE_SIZE 4096
+
+//#ifdef SHRLIBDEV
+//extern int rxrescale;
+//#define RX_IQRESCALELEN rxrescale
+//#else
+//#define RX_IQRESCALELEN 15
+//#endif
+
+//! \brief Allocate \c size bytes of memory on the heap with alignment 16 and zero it afterwards.
+//! If no more memory is available, this function will terminate the program with an assertion error.
+//******************************************************************************************************
+/*
+static inline void* malloc16_clear( size_t size )
+{
+#ifdef __AVX2__
+  void* ptr = memalign(32, size);
+#else
+  void* ptr = memalign(16, size);
+#endif
+  DevAssert(ptr);
+  memset( ptr, 0, size );
+  return ptr;
+}
+
+*/
+
+
+// #define PAGE_MASK 0xfffff000
+// #define virt_to_phys(x) (x)
+
+// #define openair_sched_exit() exit(-1)
+
+
+// #define max(a,b)  ((a)>(b) ? (a) : (b))
+// #define min(a,b)  ((a)<(b) ? (a) : (b))
+
+
+// #define bzero(s,n) (memset((s),0,(n)))
+
+// #define cmax(a,b)  ((a>b) ? (a) : (b))
+// #define cmin(a,b)  ((a<b) ? (a) : (b))
+
+// #define cmax3(a,b,c) ((cmax(a,b)>c) ? (cmax(a,b)) : (c))
+
+// /// suppress compiler warning for unused arguments
+// #define UNUSED(x) (void)x;
+
+
+#include "PHY/impl_defs_top_NB_IoT.h"
+//#include "impl_defs_top.h"
+//#include "impl_defs_lte.h"
+#include "PHY/impl_defs_lte_NB_IoT.h"
+
+#include "PHY/TOOLS/time_meas_NB_IoT.h"
+//#include "PHY/CODING/defs.h"
+#include "PHY/CODING/defs_NB_IoT.h"
+//#include "PHY/TOOLS/defs.h"
+//#include "platform_types.h"
+///#include "openair1/PHY/LTE_TRANSPORT/defs_nb_iot.h"
+
+////////////////////////////////////////////////////////////////////#ifdef OPENAIR_LTE    (check if this is required)
+
+//#include "PHY/LTE_TRANSPORT/defs.h"
+#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+#include <pthread.h>
+
+#include "targets/ARCH/COMMON/common_lib.h"
+
+#define NUM_DCI_MAX_NB_IoT 32
+
+#define NUMBER_OF_eNB_SECTORS_MAX_NB_IoT 3
+
+#define NB_BANDS_MAX_NB_IoT 8
+
+#include "defs_common.h"
+
+#ifdef OCP_FRAMEWORK
+#include <enums.h>
+#else
+typedef enum {normal_txrx_NB_IoT=0,rx_calib_ue_NB_IoT=1,rx_calib_ue_med_NB_IoT=2,rx_calib_ue_byp_NB_IoT=3,debug_prach_NB_IoT=4,no_L2_connect_NB_IoT=5,calib_prach_tx_NB_IoT=6,rx_dump_frame_NB_IoT=7,loop_through_memory_NB_IoT=8} runmode_NB_IoT_t;
+#endif
+/*
+enum transmission_access_mode {
+  NO_ACCESS=0,
+  POSTPONED_ACCESS,
+  CANCELED_ACCESS,
+  UNKNOWN_ACCESS,
+  SCHEDULED_ACCESS,
+  CBA_ACCESS};
+
+typedef enum  {
+  eNodeB_3GPP=0,   // classical eNodeB function
+  eNodeB_3GPP_BBU, // eNodeB with NGFI IF5
+  NGFI_RCC_IF4p5,  // NGFI_RCC (NGFI radio cloud center)
+  NGFI_RAU_IF4p5,
+  NGFI_RRU_IF5,    // NGFI_RRU (NGFI remote radio-unit,IF5)
+  NGFI_RRU_IF4p5   // NGFI_RRU (NGFI remote radio-unit,IF4p5)
+} eNB_func_t;
+
+typedef enum {
+  synch_to_ext_device=0,  // synch to RF or Ethernet device
+  synch_to_other          // synch to another source (timer, other CC_id)
+} eNB_timing_t;
+#endif
+*/
+typedef struct UE_SCAN_INFO_NB_IoT_s {
+  /// 10 best amplitudes (linear) for each pss signals
+  int32_t             amp[3][10];
+  /// 10 frequency offsets (kHz) corresponding to best amplitudes, with respect do minimum DL frequency in the band
+  int32_t             freq_offset_Hz[3][10];
+
+} UE_SCAN_INFO_NB_IoT_t;
+
+/// Top-level PHY Data Structure for RN
+typedef struct {
+  /// Module ID indicator for this instance
+  uint8_t             Mod_id;
+  uint32_t            frame;
+  // phy_vars_eNB_NB_IoT
+  // phy_vars ue
+  // cuurently only used to store and forward the PMCH
+  uint8_t             mch_avtive[10];
+  uint8_t             sync_area[10]; // num SF
+  NB_IoT_UE_DLSCH_t   *dlsch_rn_MCH[10];
+
+} PHY_VARS_RN_NB_IoT;
+/*
+#ifdef OCP_FRAMEWORK
+#include <enums.h>
+#else
+//typedef enum {normal_txrx=0,rx_calib_ue=1,rx_calib_ue_med=2,rx_calib_ue_byp=3,debug_prach=4,no_L2_connect=5,calib_prach_tx=6,rx_dump_frame=7,loop_through_memory=8} runmode_t;
+*/
+// enum transmission_access_mode {
+//   NO_ACCESS=0,
+//   POSTPONED_ACCESS,
+//   CANCELED_ACCESS,
+//   UNKNOWN_ACCESS,
+//   SCHEDULED_ACCESS,
+//   CBA_ACCESS};
+
+typedef enum  {
+  eNodeB_3GPP_NB_IoT=0,   // classical eNodeB function
+  eNodeB_3GPP_BBU_NB_IoT, // eNodeB with NGFI IF5
+  NGFI_RCC_IF4p5_NB_IoT,  // NGFI_RCC (NGFI radio cloud center)
+  NGFI_RAU_IF4p5_NB_IoT,
+  NGFI_RRU_IF5_Nb_IoT,    // NGFI_RRU (NGFI remote radio-unit,IF5)
+  NGFI_RRU_IF4p5_NB_IoT   // NGFI_RRU (NGFI remote radio-unit,IF4p5)
+} eNB_func_NB_IoT_t;
+
+typedef enum {
+
+  synch_to_ext_device_NB_IoT=0,  // synch to RF or Ethernet device
+  synch_to_other_NB_IoT          // synch to another source (timer, other CC_id)
+
+} eNB_timing_NB_IoT_t;
+////////////////////////////////////////////////////////////////////#endif
+
+
+typedef struct {
+
+  struct                        PHY_VARS_eNB_NB_IoT_s       *eNB;
+  NB_IoT_eNB_NDLSCH_t           *dlsch;
+  int                           G;
+
+} te_params_NB_IoT;
+
+
+typedef struct {
+
+  struct                        PHY_VARS_eNB_NB_IoT_s       *eNB;
+  int                           UE_id;
+  int                           harq_pid;
+  int                           llr8_flag;
+  int                           ret;
+
+} td_params_NB_IoT;
+
+
+/// Context data structure for RX/TX portion of subframe processing
+typedef struct {
+  /// Component Carrier index
+  uint8_t               CC_id;
+  /// timestamp transmitted to HW
+  openair0_timestamp    timestamp_tx;
+  /// subframe to act upon for transmission
+  int                   subframe_tx;
+  /// subframe to act upon for reception
+  int                   subframe_rx;
+  /// frame to act upon for transmission
+  int                   frame_tx;
+  /// frame to act upon for reception
+  int                   frame_rx;
+  /// \brief Instance count for RXn-TXnp4 processing thread.
+  /// \internal This variable is protected by \ref mutex_rxtx.
+  int                   instance_cnt_rxtx;
+  /// pthread structure for RXn-TXnp4 processing thread
+  pthread_t             pthread_rxtx;
+  /// pthread attributes for RXn-TXnp4 processing thread
+  pthread_attr_t        attr_rxtx;
+  /// condition variable for tx processing thread
+  pthread_cond_t        cond_rxtx;
+  /// mutex for RXn-TXnp4 processing thread
+  pthread_mutex_t       mutex_rxtx;
+  /// scheduling parameters for RXn-TXnp4 thread
+  struct                sched_param sched_param_rxtx;
+  /// NB-IoT for IF_Module
+  pthread_t             pthread_l2;
+  pthread_cond_t        cond_l2;
+  pthread_mutex_t       mutex_l2;
+  int                   instance_cnt_l2;
+  pthread_attr_t        attr_l2;
+
+} eNB_rxtx_proc_NB_IoT_t;
+/*
+typedef struct {
+  struct PHY_VARS_eNB_NB_IoT_s *eNB;
+  int UE_id;
+  int harq_pid;
+  int llr8_flag;
+  int ret;
+} td_params;
+
+typedef struct {
+  struct PHY_VARS_eNB_NB_IoT_s *eNB;
+  LTE_eNB_DLSCH_t *dlsch;
+  int G;
+} te_params;
+*/
+
+/// Context data structure for eNB subframe processing
+typedef struct eNB_proc_NB_IoT_t_s {
+  /// Component Carrier index
+  uint8_t                 CC_id;
+  /// thread index
+  int                     thread_index;
+  /// timestamp received from HW
+  openair0_timestamp      timestamp_rx;
+  /// timestamp to send to "slave rru"
+  openair0_timestamp      timestamp_tx;
+  /// subframe to act upon for reception
+  int                     subframe_rx;
+  /// symbol mask for IF4p5 reception per subframe
+  uint32_t                symbol_mask[10];
+  /// subframe to act upon for PRACH
+  int                     subframe_prach;
+  /// frame to act upon for reception
+  int                     frame_rx;
+  /// frame to act upon for transmission
+  int                     frame_tx;
+  /// frame offset for secondary eNBs (to correct for frame asynchronism at startup)
+  int                     frame_offset;
+  /// frame to act upon for PRACH
+  int                     frame_prach;
+  /// \internal This variable is protected by \ref mutex_fep.
+  int                     instance_cnt_fep;
+  /// \internal This variable is protected by \ref mutex_td.
+  int                     instance_cnt_td;
+  /// \internal This variable is protected by \ref mutex_te.
+  int                     instance_cnt_te;
+  /// \brief Instance count for FH processing thread.
+  /// \internal This variable is protected by \ref mutex_FH.
+  int                     instance_cnt_FH;
+  /// \brief Instance count for rx processing thread.
+  /// \internal This variable is protected by \ref mutex_prach.
+  int                     instance_cnt_prach;
+  // instance count for over-the-air eNB synchronization
+  int                     instance_cnt_synch;
+  /// \internal This variable is protected by \ref mutex_asynch_rxtx.
+  int                     instance_cnt_asynch_rxtx;
+  /// pthread structure for FH processing thread
+  pthread_t               pthread_FH;
+  /// pthread structure for eNB single processing thread
+  pthread_t               pthread_single;
+  /// pthread structure for asychronous RX/TX processing thread
+  pthread_t               pthread_asynch_rxtx;
+  /// flag to indicate first RX acquisition
+  int                     first_rx;
+  /// flag to indicate first TX transmission
+  int                     first_tx;
+  /// pthread attributes for parallel fep thread
+  pthread_attr_t          attr_fep;
+  /// pthread attributes for parallel turbo-decoder thread
+  pthread_attr_t          attr_td;
+  /// pthread attributes for parallel turbo-encoder thread
+  pthread_attr_t          attr_te;
+  /// pthread attributes for FH processing thread
+  pthread_attr_t          attr_FH;
+  /// pthread attributes for single eNB processing thread
+  pthread_attr_t          attr_single;
+  /// pthread attributes for prach processing thread
+  pthread_attr_t          attr_prach;
+  /// pthread attributes for over-the-air synch thread
+  pthread_attr_t          attr_synch;
+  /// pthread attributes for asynchronous RX thread
+  pthread_attr_t          attr_asynch_rxtx;
+  /// scheduling parameters for parallel fep thread
+  struct                  sched_param sched_param_fep;
+  /// scheduling parameters for parallel turbo-decoder thread
+  struct                  sched_param sched_param_td;
+  /// scheduling parameters for parallel turbo-encoder thread
+  struct                  sched_param sched_param_te;
+  /// scheduling parameters for FH thread
+  struct                  sched_param sched_param_FH;
+  /// scheduling parameters for single eNB thread
+  struct                  sched_param sched_param_single;
+  /// scheduling parameters for prach thread
+  struct                  sched_param sched_param_prach;
+  /// scheduling parameters for over-the-air synchronization thread
+  struct                  sched_param sched_param_synch;
+  /// scheduling parameters for asynch_rxtx thread
+  struct                  sched_param sched_param_asynch_rxtx;
+  /// pthread structure for parallel fep thread
+  pthread_t               pthread_fep;
+  /// pthread structure for parallel turbo-decoder thread
+  pthread_t               pthread_td;
+  /// pthread structure for parallel turbo-encoder thread
+  pthread_t               pthread_te;
+  /// pthread structure for PRACH thread
+  pthread_t               pthread_prach;
+  /// pthread structure for eNB synch thread
+  pthread_t               pthread_synch;
+  /// condition variable for parallel fep thread
+  pthread_cond_t          cond_fep;
+  /// condition variable for parallel turbo-decoder thread
+  pthread_cond_t          cond_td;
+  /// condition variable for parallel turbo-encoder thread
+  pthread_cond_t          cond_te;
+  /// condition variable for FH thread
+  pthread_cond_t          cond_FH;
+  /// condition variable for PRACH processing thread;
+  pthread_cond_t          cond_prach;
+  // condition variable for over-the-air eNB synchronization
+  pthread_cond_t          cond_synch;
+  /// condition variable for asynch RX/TX thread
+  pthread_cond_t          cond_asynch_rxtx;
+  /// mutex for parallel fep thread
+  pthread_mutex_t         mutex_fep;
+  /// mutex for parallel turbo-decoder thread
+  pthread_mutex_t         mutex_td;
+  /// mutex for parallel turbo-encoder thread
+  pthread_mutex_t         mutex_te;
+  /// mutex for FH
+  pthread_mutex_t         mutex_FH;
+  /// mutex for PRACH thread
+  pthread_mutex_t         mutex_prach;
+  // mutex for over-the-air eNB synchronization
+  pthread_mutex_t         mutex_synch;
+  /// mutex for asynch RX/TX thread
+  pthread_mutex_t         mutex_asynch_rxtx;
+  /// parameters for turbo-decoding worker thread
+  td_params_NB_IoT        tdp;
+  /// parameters for turbo-encoding worker thread
+  te_params_NB_IoT        tep;
+  /// number of slave threads
+  int                     num_slaves;
+  /// array of pointers to slaves
+  struct                  eNB_proc_NB_IoT_t_s           **slave_proc;
+  /// set of scheduling variables RXn-TXnp4 threads
+  // newly added for NB_IoT
+  eNB_rxtx_proc_NB_IoT_t  proc_rxtx[2];
+
+} eNB_proc_NB_IoT_t;
+
+
+/// Context data structure for RX/TX portion of subframe processing
+typedef struct {
+  /// index of the current UE RX/TX proc
+  int                   proc_id;
+  /// Component Carrier index
+  uint8_t               CC_id;
+  /// timestamp transmitted to HW
+  openair0_timestamp    timestamp_tx;
+  /// subframe to act upon for transmission
+  int                   subframe_tx;
+  /// subframe to act upon for reception
+  int                   subframe_rx;
+  /// frame to act upon for transmission
+  int                   frame_tx;
+  /// frame to act upon for reception
+  int                   frame_rx;
+  /// \brief Instance count for RXn-TXnp4 processing thread.
+  /// \internal This variable is protected by \ref mutex_rxtx.
+  int                   instance_cnt_rxtx;
+  /// pthread structure for RXn-TXnp4 processing thread
+  pthread_t             pthread_rxtx;
+  /// pthread attributes for RXn-TXnp4 processing thread
+  pthread_attr_t        attr_rxtx;
+  /// condition variable for tx processing thread
+  pthread_cond_t        cond_rxtx;
+  /// mutex for RXn-TXnp4 processing thread
+  pthread_mutex_t       mutex_rxtx;
+  /// scheduling parameters for RXn-TXnp4 thread
+  struct                sched_param sched_param_rxtx;
+  /// 
+  int                   sub_frame_start;
+  ///
+  int                   sub_frame_step;
+  ///
+  unsigned long long    gotIQs;
+
+} UE_rxtx_proc_NB_IoT_t;
+
+/// Context data structure for eNB subframe processing
+typedef struct {
+  /// Component Carrier index
+  uint8_t                 CC_id;
+  /// Last RX timestamp
+  openair0_timestamp      timestamp_rx;
+  /// pthread attributes for main UE thread
+  pthread_attr_t          attr_ue;
+  /// scheduling parameters for main UE thread
+  struct                  sched_param sched_param_ue;
+  /// pthread descriptor main UE thread
+  pthread_t               pthread_ue;
+  /// \brief Instance count for synch thread.
+  /// \internal This variable is protected by \ref mutex_synch.
+  int                     instance_cnt_synch;
+  /// pthread attributes for synch processing thread
+  pthread_attr_t          attr_synch;
+  /// scheduling parameters for synch thread
+  struct                  sched_param sched_param_synch;
+  /// pthread descriptor synch thread
+  pthread_t               pthread_synch;
+  /// condition variable for UE synch thread;
+  pthread_cond_t          cond_synch;
+  /// mutex for UE synch thread
+  pthread_mutex_t         mutex_synch;
+  /// set of scheduling variables RXn-TXnp4 threads
+  UE_rxtx_proc_NB_IoT_t   proc_rxtx[2];
+
+} UE_proc_NB_IoT_t;
+
+
+
+/// Top-level PHY Data Structure for eNB
+typedef struct PHY_VARS_eNB_NB_IoT_s {
+  /// Module ID indicator for this instance
+  module_id_t                   Mod_id;
+  uint8_t                       CC_id;
+  eNB_proc_NB_IoT_t             proc;
+  eNB_func_NB_IoT_t             node_function;
+  eNB_timing_NB_IoT_t           node_timing;
+  eth_params_t                  *eth_params;
+  int                           single_thread_flag;
+  openair0_rf_map               rf_map;
+  int                           abstraction_flag;
+  openair0_timestamp            ts_offset;
+  // indicator for synchronization state of eNB
+  int                           in_synch;
+  // indicator for master/slave (RRU)
+  int                           is_slave;
+  // indicator for precoding function (eNB,3GPP_eNB_BBU)
+  int                           do_precoding;
+  void                          (*do_prach)(struct PHY_VARS_eNB_NB_IoT_s *eNB,int frame,int subframe);
+  void                          (*fep)(struct PHY_VARS_eNB_NB_IoT_s *eNB,eNB_rxtx_proc_NB_IoT_t *proc);
+  int                           (*td)(struct PHY_VARS_eNB_NB_IoT_s *eNB,int UE_id,int harq_pid,int llr8_flag);
+  int                           (*te)(struct PHY_VARS_eNB_NB_IoT_s *,uint8_t *,uint8_t,NB_IoT_eNB_DLSCH_t *,int,uint8_t,time_stats_t_NB_IoT *,time_stats_t_NB_IoT *,time_stats_t_NB_IoT *);
+  void                          (*proc_uespec_rx)(struct PHY_VARS_eNB_NB_IoT_s *eNB,eNB_rxtx_proc_NB_IoT_t *proc,const relaying_type_t_NB_IoT r_type);
+  void                          (*proc_tx)(struct PHY_VARS_eNB_NB_IoT_s *eNB,eNB_rxtx_proc_NB_IoT_t *proc,relaying_type_t_NB_IoT r_type,PHY_VARS_RN_NB_IoT *rn);
+  void                          (*tx_fh)(struct PHY_VARS_eNB_NB_IoT_s *eNB,eNB_rxtx_proc_NB_IoT_t *proc);
+  void                          (*rx_fh)(struct PHY_VARS_eNB_NB_IoT_s *eNB,int *frame, int *subframe);
+  int                           (*start_rf)(struct PHY_VARS_eNB_NB_IoT_s *eNB);
+  int                           (*start_if)(struct PHY_VARS_eNB_NB_IoT_s *eNB);
+  void                          (*fh_asynch)(struct PHY_VARS_eNB_NB_IoT_s *eNB,int *frame, int *subframe);
+  uint8_t                       local_flag;
+  uint32_t                      rx_total_gain_dB;
+  NB_IoT_DL_FRAME_PARMS         frame_parms;
+  PHY_MEASUREMENTS_eNB_NB_IoT   measurements[NUMBER_OF_eNB_SECTORS_MAX_NB_IoT]; /// Measurement variables
+  NB_IoT_eNB_COMMON             common_vars;
+  NB_IoT_eNB_SRS                srs_vars[NUMBER_OF_UE_MAX_NB_IoT];
+  NB_IoT_eNB_PBCH               pbch;
+  NB_IoT_eNB_PUSCH              *pusch_vars[NUMBER_OF_UE_MAX_NB_IoT];
+  NB_IoT_eNB_PRACH              prach_vars;
+  //LTE_eNB_DLSCH_t             *dlsch[NUMBER_OF_UE_MAX_NB_IoT][2];             // Nusers times two spatial streams
+  NB_IoT_eNB_NULSCH_t            *ulsch[NUMBER_OF_UE_MAX_NB_IoT+1];              // Nusers + number of RA (the ulsch[0] contains RAR)
+  //LTE_eNB_DLSCH_t             *dlsch_SI,*dlsch_ra;
+  //LTE_eNB_DLSCH_t             *dlsch_MCH;
+  NB_IoT_eNB_UE_stats           UE_stats[NUMBER_OF_UE_MAX_NB_IoT];
+  //LTE_eNB_UE_stats            *UE_stats_ptr[NUMBER_OF_UE_MAX_NB_IoT];
+  /// cell-specific reference symbols
+  uint32_t                      lte_gold_table_NB_IoT[20][2][14];
+  /// UE-specific reference symbols (p=5), TM 7
+  uint32_t                      lte_gold_uespec_port5_table[NUMBER_OF_UE_MAX_NB_IoT][20][38];
+  /// UE-specific reference symbols (p=7...14), TM 8/9/10
+  uint32_t                      lte_gold_uespec_table[2][20][2][21];
+  /// mbsfn reference symbols
+  uint32_t                      lte_gold_mbsfn_table[10][3][42];
+  ///
+  uint32_t                      X_u[64][839];
+  ///
+  uint8_t                       pbch_pdu[4];                                      //PBCH_PDU_SIZE
+  ///
+  char                          eNB_generate_rar;
+  /// Indicator set to 0 after first SR
+  uint8_t                       first_sr[NUMBER_OF_UE_MAX_NB_IoT];
+
+  uint32_t                      max_peak_val;
+  ///
+  int                           max_eNB_id, max_sync_pos;
+  ///
+  int                           N_TA_offset;                        ///timing offset used in TDD
+  /// \brief sinr for all subcarriers of the current link (used only for abstraction).
+  /// first index: ? [0..N_RB_DL*12[
+  double                        *sinr_dB;
+  /// N0 (used for abstraction)
+  double                        N0;
+  ///
+  unsigned char                 first_run_timing_advance[NUMBER_OF_UE_MAX_NB_IoT];
+  unsigned char                 first_run_I0_measurements;
+
+  unsigned char                 cooperation_flag;                   // for cooperative communication
+
+  unsigned char                 is_secondary_eNB;                   // primary by default
+  unsigned char                 is_init_sync;                       /// Flag to tell if initial synchronization is performed. This affects how often the secondary eNB will listen to the PSS from the primary system.
+  unsigned char                 has_valid_precoder;                 /// Flag to tell if secondary eNB has channel estimates to create NULL-beams from, and this B/F vector is created.
+  unsigned char                 PeNB_id;                            /// id of Primary eNB
+  int                           rx_offset;                          /// Timing offset (used if is_secondary_eNB)
+
+  /// hold the precoder for NULL beam to the primary user
+  int                           **dl_precoder_SeNB[3];
+  ///
+  char                          log2_maxp;                          /// holds the maximum channel/precoder coefficient
+  /// if ==0 enables phy only test mode
+  int                           mac_enabled;
+  /// For emulation only (used by UE abstraction to retrieve DCI)
+  uint8_t                       num_common_dci[2];                  // num_dci in even/odd subframes
+  ///
+  uint8_t                       num_ue_spec_dci[2];                 // num_dci in even/odd subframes
+  ///
+  DCI_ALLOC_NB_IoT_t            dci_alloc[2][NUM_DCI_MAX_NB_IoT];   // dci_alloc from even/odd subframes
+  /////////////
+  // PDSCH Varaibles
+  PDSCH_CONFIG_DEDICATED_NB_IoT             pdsch_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT];
+  // PUSCH Varaibles
+  PUSCH_CONFIG_DEDICATED_NB_IoT             pusch_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT];
+  // PUCCH variables
+  PUCCH_CONFIG_DEDICATED_NB_IoT             pucch_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT];
+  // UL-POWER-Control
+  UL_POWER_CONTROL_DEDICATED_NB_IoT         ul_power_control_dedicated[NUMBER_OF_UE_MAX_NB_IoT];
+  // TPC
+  TPC_PDCCH_CONFIG_NB_IoT                   tpc_pdcch_config_pucch[NUMBER_OF_UE_MAX_NB_IoT];
+  ///
+  TPC_PDCCH_CONFIG_NB_IoT                   tpc_pdcch_config_pusch[NUMBER_OF_UE_MAX_NB_IoT];
+  // CQI reporting
+  CQI_REPORT_CONFIG_NB_IoT                  cqi_report_config[NUMBER_OF_UE_MAX_NB_IoT];
+  // SRS Variables
+  SOUNDINGRS_UL_CONFIG_DEDICATED_NB_IoT     soundingrs_ul_config_dedicated[NUMBER_OF_UE_MAX_NB_IoT];
+  ///
+  uint8_t                                   ncs_cell[20][7];
+  // Scheduling Request Config
+  SCHEDULING_REQUEST_CONFIG_NB_IoT          scheduling_request_config[NUMBER_OF_UE_MAX_NB_IoT];
+  // Transmission mode per UE
+  uint8_t                                   transmission_mode[NUMBER_OF_UE_MAX_NB_IoT];
+  /// cba_last successful reception for each group, used for collision detection
+  uint8_t                                   cba_last_reception[4];
+  // Pointers for active physicalConfigDedicated to be applied in current subframe
+  struct                                    PhysicalConfigDedicated                         *physicalConfigDedicated[NUMBER_OF_UE_MAX_NB_IoT];
+  //Pointers for actve physicalConfigDedicated for NB-IoT to be applied in current subframe
+  struct                                    PhysicalConfigDedicated_NB_r13                  *phy_config_dedicated_NB_IoT[NUMBER_OF_UE_MAX_NB_IoT];
+  ///
+  uint32_t                                  rb_mask_ul[4];
+  /// Information regarding TM5
+  MU_MIMO_mode_NB_IoT                       mu_mimo_mode[NUMBER_OF_UE_MAX_NB_IoT];
+  /// target_ue_dl_mcs : only for debug purposes
+  uint32_t                                  target_ue_dl_mcs;
+  /// target_ue_ul_mcs : only for debug purposes
+  uint32_t                                  target_ue_ul_mcs;
+  /// target_ue_dl_rballoc : only for debug purposes
+  uint32_t                                  ue_dl_rb_alloc;
+  /// target ul PRBs : only for debug
+  uint32_t                                  ue_ul_nb_rb;
+  ///check for Total Transmissions
+  uint32_t                                  check_for_total_transmissions;
+  ///check for MU-MIMO Transmissions
+  uint32_t                                  check_for_MUMIMO_transmissions;
+  ///check for SU-MIMO Transmissions
+  uint32_t                                  check_for_SUMIMO_transmissions;
+  ///check for FULL MU-MIMO Transmissions
+  uint32_t                                  FULL_MUMIMO_transmissions;
+  /// Counter for total bitrate, bits and throughput in downlink
+  uint32_t                                  total_dlsch_bitrate;
+  ///
+  uint32_t                                  total_transmitted_bits;
+  ///
+  uint32_t                                  total_system_throughput;
+  ///
+  int                                       hw_timing_advance;
+  ///
+  time_stats_t_NB_IoT                       phy_proc;
+  time_stats_t_NB_IoT                       phy_proc_tx;
+  time_stats_t_NB_IoT                       phy_proc_rx;
+  time_stats_t_NB_IoT                       rx_prach;
+
+  time_stats_t_NB_IoT                       ofdm_mod_stats;
+  time_stats_t_NB_IoT                       dlsch_encoding_stats;
+  time_stats_t_NB_IoT                       dlsch_modulation_stats;
+  time_stats_t_NB_IoT                       dlsch_scrambling_stats;
+  time_stats_t_NB_IoT                       dlsch_rate_matching_stats;
+  time_stats_t_NB_IoT                       dlsch_turbo_encoding_stats;
+  time_stats_t_NB_IoT                       dlsch_interleaving_stats;
+
+  time_stats_t_NB_IoT                       ofdm_demod_stats;
+  time_stats_t_NB_IoT                       rx_dft_stats;
+  time_stats_t_NB_IoT                       ulsch_channel_estimation_stats;
+  time_stats_t_NB_IoT                       ulsch_freq_offset_estimation_stats;
+  time_stats_t_NB_IoT                       ulsch_decoding_stats;
+  time_stats_t_NB_IoT                       ulsch_demodulation_stats;
+  time_stats_t_NB_IoT                       ulsch_rate_unmatching_stats;
+  time_stats_t_NB_IoT                       ulsch_turbo_decoding_stats;
+  time_stats_t_NB_IoT                       ulsch_deinterleaving_stats;
+  time_stats_t_NB_IoT                       ulsch_demultiplexing_stats;
+  time_stats_t_NB_IoT                       ulsch_llr_stats;
+  time_stats_t_NB_IoT                       ulsch_tc_init_stats;
+  time_stats_t_NB_IoT                       ulsch_tc_alpha_stats;
+  time_stats_t_NB_IoT                       ulsch_tc_beta_stats;
+  time_stats_t_NB_IoT                       ulsch_tc_gamma_stats;
+  time_stats_t_NB_IoT                       ulsch_tc_ext_stats;
+  time_stats_t_NB_IoT                       ulsch_tc_intl1_stats;
+  time_stats_t_NB_IoT                       ulsch_tc_intl2_stats;
+
+  #ifdef LOCALIZATION
+  /// time state for localization
+  time_stats_t_NB_IoT                       localization_stats;
+  #endif
+
+  int32_t                                   pucch1_stats_cnt[NUMBER_OF_UE_MAX_NB_IoT][10];
+  int32_t                                   pucch1_stats[NUMBER_OF_UE_MAX_NB_IoT][10*1024];
+  int32_t                                   pucch1_stats_thres[NUMBER_OF_UE_MAX_NB_IoT][10*1024];
+  int32_t                                   pucch1ab_stats_cnt[NUMBER_OF_UE_MAX_NB_IoT][10];
+  int32_t                                   pucch1ab_stats[NUMBER_OF_UE_MAX_NB_IoT][2*10*1024];
+  int32_t                                   pusch_stats_rb[NUMBER_OF_UE_MAX_NB_IoT][10240];
+  int32_t                                   pusch_stats_round[NUMBER_OF_UE_MAX_NB_IoT][10240];
+  int32_t                                   pusch_stats_mcs[NUMBER_OF_UE_MAX_NB_IoT][10240];
+  int32_t                                   pusch_stats_bsr[NUMBER_OF_UE_MAX_NB_IoT][10240];
+  int32_t                                   pusch_stats_BO[NUMBER_OF_UE_MAX_NB_IoT][10240];
+
+  /// RF and Interface devices per CC
+  openair0_device                           rfdevice;
+  openair0_device                           ifdevice;
+  /// Pointer for ifdevice buffer struct
+  if_buffer_t                               ifbuffer;
+
+  //------------------------
+  // NB-IoT
+  //------------------------
+
+  /*
+   * NUMBER_OF_UE_MAX_NB_IoT maybe in the future should be dynamic because could be very large and the memory may explode
+   * (is almost the indication of the number of UE context that we are storing at PHY layer)
+   *
+   * reasoning: the following data structure (ndlsch, nulsch ecc..) are used to store the context that should be transmitted in at least n+4 subframe later
+   * (the minimum interval between NPUSCH and the ACK for this)
+   * the problem is that in NB_IoT the ACK for the UPLINK is contained in the DCI through the NDI field (if this value change from the previous one then it means ACK)
+   * but may we could schedule this DCI long time later so may lots of contents shuld be stored (there is no concept of phich channel in NB-IoT)
+   * For the DL transmission the UE send a proper ACK/NACK message
+   *
+   * *the HARQ process should be killed when the NDI change
+   *
+   * *In the Structure for nulsch we should also store the information related to the subframe (because each time we should read it and understand what should be done
+   * in that subframe)
+   *
+   */
+
+
+  /*
+   * TIMING
+   * the entire transmission and scheduling are done for the "subframe" concept but the subframe = proc->subframe_tx (that in reality is the subframe_rx +4)
+   * (see USER/lte-enb/wakeup_rxtx )
+   *
+   * Related to FAPI:
+   * DCI and  DL_CONFIG.request (also more that 1) and MAC_PDU are transmitted in the same subframe (our assumption) so will be all contained in the schedule_response getting from the scheduler
+   * DCI0 and UL_CONFIG.request are transmitted in the same subframe (our assumption) so contained in the schedule_response
+   *
+   */
+
+  //TODO: check what should be NUMBER_OF_UE_MAX_NB_IoT value
+  NB_IoT_eNB_NPBCH_t        *npbch;
+  NB_IoT_eNB_NPDCCH_t       *npdcch[NUMBER_OF_UE_MAX_NB_IoT];
+  NB_IoT_eNB_NDLSCH_t       *ndlsch[NUMBER_OF_UE_MAX_NB_IoT];
+  NB_IoT_eNB_NULSCH_t       *nulsch[NUMBER_OF_UE_MAX_NB_IoT+1]; //nulsch[0] contains the RAR
+  NB_IoT_eNB_NDLSCH_t       *ndlsch_SI,*ndlsch_ra, *ndlsch_SIB1;
+
+  NB_IoT_DL_FRAME_PARMS     frame_parms_NB_IoT;
+  // DCI for at most 2 DCI pdus
+  DCI_PDU_NB_IoT            *DCI_pdu;
+
+
+
+} PHY_VARS_eNB_NB_IoT;
+
+//#define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg
+
+/// Top-level PHY Data Structure for UE
+typedef struct {
+  /// \brief Module ID indicator for this instance
+  uint8_t                       Mod_id;
+  /// \brief Component carrier ID for this PHY instance
+  uint8_t                       CC_id;
+  /// \brief Mapping of CC_id antennas to cards
+  openair0_rf_map               rf_map;
+  //uint8_t local_flag;
+  /// \brief Indicator of current run mode of UE (normal_txrx, rx_calib_ue, no_L2_connect, debug_prach)
+  runmode_NB_IoT_t              mode;
+  /// \brief Indicator that UE should perform band scanning
+  int                           UE_scan;
+  /// \brief Indicator that UE should perform coarse scanning around carrier
+  int                           UE_scan_carrier;
+  /// \brief Indicator that UE is synchronized to an eNB
+  int                           is_synchronized;
+  /// Data structure for UE process scheduling
+  UE_proc_NB_IoT_t              proc;
+  /// Flag to indicate the UE shouldn't do timing correction at all
+  int                           no_timing_correction;
+  /// \brief Total gain of the TX chain (16-bit baseband I/Q to antenna)
+  uint32_t                      tx_total_gain_dB;
+  /// \brief Total gain of the RX chain (antenna to baseband I/Q) This is a function of rx_gain_mode (and the corresponding gain) and the rx_gain of the card.
+  uint32_t                      rx_total_gain_dB;
+  /// \brief Total gains with maximum RF gain stage (ExpressMIMO2/Lime)
+  uint32_t                      rx_gain_max[4];
+  /// \brief Total gains with medium RF gain stage (ExpressMIMO2/Lime)
+  uint32_t                      rx_gain_med[4];
+  /// \brief Total gains with bypassed RF gain stage (ExpressMIMO2/Lime)
+  uint32_t                      rx_gain_byp[4];
+  /// \brief Current transmit power
+  int16_t                       tx_power_dBm[10];
+  /// \brief Total number of REs in current transmission
+  int                           tx_total_RE[10];
+  /// \brief Maximum transmit power
+  int8_t                        tx_power_max_dBm;
+  /// \brief Number of eNB seen by UE
+  uint8_t                       n_connected_eNB;
+  /// \brief indicator that Handover procedure has been initiated
+  uint8_t                       ho_initiated;
+  /// \brief indicator that Handover procedure has been triggered
+  uint8_t                       ho_triggered;
+  /// \brief Measurement variables.
+  PHY_MEASUREMENTS_NB_IoT       measurements;
+  NB_IoT_DL_FRAME_PARMS         frame_parms;
+  /// \brief Frame parame before ho used to recover if ho fails.
+  NB_IoT_DL_FRAME_PARMS         frame_parms_before_ho;
+  NB_IoT_UE_COMMON              common_vars;
+/*
+  LTE_UE_PDSCH     *pdsch_vars[2][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads
+  LTE_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  LTE_UE_PDSCH     *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  LTE_UE_PDSCH     *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  LTE_UE_PDSCH     *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  LTE_UE_PDSCH     *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_PBCH      *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_PDCCH     *pdcch_vars[2][NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_PRACH     *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_DLSCH_t   *dlsch[2][NUMBER_OF_CONNECTED_eNB_MAX][2]; // two RxTx Threads
+  LTE_UE_ULSCH_t   *ulsch[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_DLSCH_t   *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_DLSCH_t   *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_DLSCH_t   *dlsch_p[NUMBER_OF_CONNECTED_eNB_MAX];
+  LTE_UE_DLSCH_t   *dlsch_MCH[NUMBER_OF_CONNECTED_eNB_MAX];
+  // This is for SIC in the UE, to store the reencoded data
+  LTE_eNB_DLSCH_t  *dlsch_eNB[NUMBER_OF_CONNECTED_eNB_MAX];
+*/
+  //Paging parameters
+  uint32_t                        IMSImod1024;
+  uint32_t                        PF;
+  uint32_t                        PO;
+  // For abstraction-purposes only
+  uint8_t                         sr[10];
+  uint8_t                         pucch_sel[10];
+  uint8_t                         pucch_payload[22];
+  //UE_MODE_t                     UE_mode[NUMBER_OF_CONNECTED_eNB_MAX];
+  //cell-specific reference symbols
+  uint32_t                        lte_gold_table[7][20][2][14];
+  //UE-specific reference symbols (p=5), TM 7
+  uint32_t                        lte_gold_uespec_port5_table[20][38];
+  //ue-specific reference symbols
+  uint32_t                        lte_gold_uespec_table[2][20][2][21];
+  //mbsfn reference symbols
+  uint32_t                        lte_gold_mbsfn_table[10][3][42];
+  ///
+  uint32_t                        X_u[64][839];
+  /// 
+  uint32_t                        high_speed_flag;
+  uint32_t                        perfect_ce;
+  int16_t                         ch_est_alpha;
+  int                             generate_ul_signal[NUMBER_OF_CONNECTED_eNB_MAX];
+  ///
+  UE_SCAN_INFO_NB_IoT_t           scan_info[NB_BANDS_MAX_NB_IoT];
+  ///
+  char                            ulsch_no_allocation_counter[NUMBER_OF_CONNECTED_eNB_MAX];
+
+/*
+
+  unsigned char ulsch_Msg3_active[NUMBER_OF_CONNECTED_eNB_MAX];
+  uint32_t  ulsch_Msg3_frame[NUMBER_OF_CONNECTED_eNB_MAX];
+  unsigned char ulsch_Msg3_subframe[NUMBER_OF_CONNECTED_eNB_MAX];
+  PRACH_RESOURCES_t *prach_resources[NUMBER_OF_CONNECTED_eNB_MAX];
+  int turbo_iterations, turbo_cntl_iterations;
+  /// \brief ?.
+  /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded)
+  uint32_t total_TBS[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// \brief ?.
+  /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded)
+  uint32_t total_TBS_last[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// \brief ?.
+  /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded)
+  uint32_t bitrate[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// \brief ?.
+  /// - first index: eNB [0..NUMBER_OF_CONNECTED_eNB_MAX[ (hard coded)
+  uint32_t total_received_bits[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_errors[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_errors_last[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_received[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_received_last[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_fer[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_SI_received[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_SI_errors[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_ra_received[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_ra_errors[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_p_received[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_p_errors[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mch_received_sf[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mch_received[NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mcch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mtch_received[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mcch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mtch_errors[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mcch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
+  int dlsch_mtch_trials[MAX_MBSFN_AREA][NUMBER_OF_CONNECTED_eNB_MAX];
+  int current_dlsch_cqi[NUMBER_OF_CONNECTED_eNB_MAX];
+  unsigned char first_run_timing_advance[NUMBER_OF_CONNECTED_eNB_MAX];
+  uint8_t               generate_prach;
+  uint8_t               prach_cnt;
+  uint8_t               prach_PreambleIndex;
+  //  uint8_t               prach_timer;
+  uint8_t               decode_SIB;
+  uint8_t               decode_MIB;
+  int              rx_offset; /// Timing offset
+  int              rx_offset_diff; /// Timing adjustment for ofdm symbol0 on HW USRP
+  int              timing_advance; ///timing advance signalled from eNB
+  int              hw_timing_advance;
+  int              N_TA_offset; ///timing offset used in TDD
+  /// Flag to tell if UE is secondary user (cognitive mode)
+  unsigned char    is_secondary_ue;
+  /// Flag to tell if secondary eNB has channel estimates to create NULL-beams from.
+  unsigned char    has_valid_precoder;
+  /// hold the precoder for NULL beam to the primary eNB
+  int              **ul_precoder_S_UE;
+  /// holds the maximum channel/precoder coefficient
+  char             log2_maxp;
+*/
+  /// if ==0 enables phy only test mode
+  int              mac_enabled;
+  /// Flag to initialize averaging of PHY measurements
+  int              init_averaging;
+  /// \brief sinr for all subcarriers of the current link (used only for abstraction).
+  /// - first index: ? [0..12*N_RB_DL[
+  double           *sinr_dB;
+  /// \brief sinr for all subcarriers of first symbol for the CQI Calculation.
+  /// - first index: ? [0..12*N_RB_DL[
+  double           *sinr_CQI_dB;
+  /// sinr_effective used for CQI calulcation
+  double           sinr_eff;
+  /// N0 (used for abstraction)
+  double           N0;
+/*
+  /// PDSCH Varaibles
+  PDSCH_CONFIG_DEDICATED pdsch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// PUSCH Varaibles
+  PUSCH_CONFIG_DEDICATED pusch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// PUSCH contention-based access vars
+  PUSCH_CA_CONFIG_DEDICATED  pusch_ca_config_dedicated[NUMBER_OF_eNB_MAX]; // lola
+
+  /// PUCCH variables
+
+  PUCCH_CONFIG_DEDICATED pucch_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  uint8_t ncs_cell[20][7];
+
+  /// UL-POWER-Control
+  UL_POWER_CONTROL_DEDICATED ul_power_control_dedicated[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// TPC
+  TPC_PDCCH_CONFIG tpc_pdcch_config_pucch[NUMBER_OF_CONNECTED_eNB_MAX];
+  TPC_PDCCH_CONFIG tpc_pdcch_config_pusch[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// CQI reporting
+  CQI_REPORT_CONFIG cqi_report_config[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// SRS Variables
+  SOUNDINGRS_UL_CONFIG_DEDICATED soundingrs_ul_config_dedicated[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// Scheduling Request Config
+  SCHEDULING_REQUEST_CONFIG scheduling_request_config[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// Transmission mode per eNB
+  uint8_t transmission_mode[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  time_stats_t phy_proc;
+  time_stats_t phy_proc_tx;
+  time_stats_t phy_proc_rx[2];
+
+  uint32_t use_ia_receiver;
+
+  time_stats_t ofdm_mod_stats;
+  time_stats_t ulsch_encoding_stats;
+  time_stats_t ulsch_modulation_stats;
+  time_stats_t ulsch_segmentation_stats;
+  time_stats_t ulsch_rate_matching_stats;
+  time_stats_t ulsch_turbo_encoding_stats;
+  time_stats_t ulsch_interleaving_stats;
+  time_stats_t ulsch_multiplexing_stats;
+
+  time_stats_t generic_stat;
+  time_stats_t pdsch_procedures_stat;
+  time_stats_t dlsch_procedures_stat;
+
+  time_stats_t ofdm_demod_stats;
+  time_stats_t dlsch_rx_pdcch_stats;
+  time_stats_t rx_dft_stats;
+  time_stats_t dlsch_channel_estimation_stats;
+  time_stats_t dlsch_freq_offset_estimation_stats;
+  time_stats_t dlsch_decoding_stats[2];
+  time_stats_t dlsch_demodulation_stats;
+  time_stats_t dlsch_rate_unmatching_stats;
+  time_stats_t dlsch_turbo_decoding_stats;
+  time_stats_t dlsch_deinterleaving_stats;
+  time_stats_t dlsch_llr_stats;
+  time_stats_t dlsch_unscrambling_stats;
+  time_stats_t dlsch_rate_matching_stats;
+  time_stats_t dlsch_turbo_encoding_stats;
+  time_stats_t dlsch_interleaving_stats;
+  time_stats_t dlsch_tc_init_stats;
+  time_stats_t dlsch_tc_alpha_stats;
+  time_stats_t dlsch_tc_beta_stats;
+  time_stats_t dlsch_tc_gamma_stats;
+  time_stats_t dlsch_tc_ext_stats;
+  time_stats_t dlsch_tc_intl1_stats;
+  time_stats_t dlsch_tc_intl2_stats;
+  time_stats_t tx_prach;
+
+  /// RF and Interface devices per CC
+  openair0_device rfdevice;
+  time_stats_t dlsch_encoding_SIC_stats;
+  time_stats_t dlsch_scrambling_SIC_stats;
+  time_stats_t dlsch_modulation_SIC_stats;
+  time_stats_t dlsch_llr_stripping_unit_SIC_stats;
+  time_stats_t dlsch_unscrambling_SIC_stats;
+
+#if ENABLE_RAL
+  hash_table_t    *ral_thresholds_timed;
+  SLIST_HEAD(ral_thresholds_gen_poll_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX];
+  SLIST_HEAD(ral_thresholds_lte_poll_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX];
+#endif
+*/
+} PHY_VARS_UE_NB_IoT;
+
+
+/*
+void exit_fun(const char* s);
+
+static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
+
+  // lock the mutex, if lock successfully, it would return the 0, the other value means failed
+  if (pthread_mutex_lock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+
+  while (*instance_cnt < 0) {
+    // most of the time the thread is waiting here
+    // proc->instance_cnt_rxtx is -1
+    pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
+  }
+
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
+
+static inline int wait_on_busy_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
+
+  if (pthread_mutex_lock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+
+  while (*instance_cnt == 0) {
+    // most of the time the thread will skip this
+    // waits only if proc->instance_cnt_rxtx is 0
+    pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
+  }
+
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
+
+static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {
+
+  if (pthread_mutex_lock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+
+  *instance_cnt=*instance_cnt-1;
+
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
+
+*/
+
+#include "PHY/INIT/defs_NB_IoT.h"
+#include "PHY/LTE_REFSIG/defs_NB_IoT.h"
+//#include "PHY/MODULATION/defs.h"
+//#include "PHY/LTE_TRANSPORT/proto.h"
+#include "PHY/LTE_TRANSPORT/proto_NB_IoT.h"
+//#include "PHY/LTE_ESTIMATION/defs.h"
+
+//#include "SIMULATION/ETH_TRANSPORT/defs.h"
+//#endif
+#endif //  __PHY_DEFS__H__
diff --git a/openair1/PHY/extern_NB_IoT.h b/openair1/PHY/extern_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..7a640d7d63f9c71662e43486e06af17655e9fde9
--- /dev/null
+++ b/openair1/PHY/extern_NB_IoT.h
@@ -0,0 +1,139 @@
+/*
+ * 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.0  (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_EXTERN_NB_IOT_H__
+#define __PHY_EXTERN_NB_IOT_H__
+
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+#include "openair2/PHY_INTERFACE/defs_NB_IoT.h"
+//#include "PHY_INTERFACE/IF_Module_NB_IoT.h"
+/*
+extern  char* namepointer_chMag ;
+extern char* namepointer_log2;
+extern  char fmageren_name2[512];
+
+extern unsigned int RX_DMA_BUFFER[4][NB_ANTENNAS_RX];
+extern unsigned int TX_DMA_BUFFER[4][NB_ANTENNAS_TX];
+*/
+//#include "PHY/LTE_TRANSPORT/extern.h"
+//#include "SIMULATION/ETH_TRANSPORT/extern.h"
+
+extern unsigned int DAQ_MBOX_NB_IoT;
+extern int number_of_cards_NB_IoT;
+
+//extern PHY_CONFIG *PHY_config;
+//extern PHY_VARS *PHY_vars;
+#ifndef OCP_FRAMEWORK
+extern PHY_VARS_UE_NB_IoT ***PHY_vars_UE_NB_IoT_g;
+extern PHY_VARS_eNB_NB_IoT ***PHY_vars_eNB_NB_IoT_g;
+extern PHY_VARS_RN_NB_IoT **PHY_vars_RN_NB_IoT_g;
+extern NB_IoT_DL_FRAME_PARMS *nb_iot_frame_parms_g;
+#else
+#define MAX_UE 10
+#define MAX_eNB_NB_IoT 20
+extern PHY_VARS_UE_NB_IoT * PHY_vars_UE_NB_IoT_g[MAX_UE][MAX_NUM_CCs];
+extern PHY_VARS_eNB_NB_IoT * PHY_vars_eNB_NB_IoT_g[MAX_eNB_NB_IoT][MAX_NUM_CCs];
+#endif
+
+
+//extern MAC_xface_NB_IoT *mac_xface_NB_IoT;
+
+extern IF_Module_t *if_inst;
+/*
+
+extern short primary_synch0[144];
+extern short primary_synch1[144];
+extern short primary_synch2[144];
+extern unsigned char primary_synch0_tab[72];
+extern unsigned char primary_synch1_tab[72];
+extern unsigned char primary_synch2_tab[72];
+extern int16_t *primary_synch0_time; //!< index: [0..ofdm_symbol_size*2[
+extern int16_t *primary_synch1_time; //!< index: [0..ofdm_symbol_size*2[
+extern int16_t *primary_synch2_time; //!< index: [0..ofdm_symbol_size*2[
+extern int *sync_corr_ue0; //!< index [0..10*samples_per_tti[
+extern int *sync_corr_ue1; //!< index [0..10*samples_per_tti[
+extern int *sync_corr_ue2; //!< index [0..10*samples_per_tti[
+
+extern int flagMag;
+//extern short **txdataF_rep_tmp;
+
+extern char mode_string[4][20];
+*/
+
+
+/*
+#ifndef OPENAIR2
+extern unsigned char NB_eNB_INST;
+extern unsigned char NB_UE_INST;
+extern unsigned char NB_RN_INST;
+#endif
+
+extern unsigned int ULSCH_max_consecutive_errors;
+extern int flag_LA;
+extern double sinr_bler_map[MCS_COUNT][2][MCS_TABLE_LENGTH_MAX];
+extern double sinr_bler_map_up[MCS_COUNT][2][16];
+extern int table_length[MCS_COUNT];
+extern double sinr_to_cqi[4][16];
+extern int cqi_to_mcs[16];
+
+//for MU-MIMO abstraction using MIESM
+//this 2D arrarays contains SINR, MI and RBIR in rows 1, 2, and 3 respectively
+extern double MI_map_4qam[3][162];
+extern double MI_map_16qam[3][197];
+extern double MI_map_64qam[3][227];
+
+extern double beta1_dlsch_MI[6][MCS_COUNT];
+extern double beta2_dlsch_MI[6][MCS_COUNT];
+
+extern double q_qpsk[8];
+extern double q_qam16[8];
+extern double q_qam64[8];
+
+extern double p_qpsk[8];
+extern double p_qam16[8];
+extern double p_qam64[8];
+
+extern double beta1_dlsch[6][MCS_COUNT];
+extern double beta2_dlsch[6][MCS_COUNT];
+
+extern char eNB_functions[6][20];
+extern char eNB_timing[2][20];
+
+*/
+extern int16_t unscrambling_lut_NB_IoT[65536*16];
+/*
+extern uint8_t scrambling_lut[65536*16];
+
+extern unsigned short msrsb_6_40[8][4];
+extern unsigned short msrsb_41_60[8][4];
+extern unsigned short msrsb_61_80[8][4];
+extern unsigned short msrsb_81_110[8][4];
+extern unsigned short Nb_6_40[8][4];
+extern unsigned short Nb_41_60[8][4];
+extern unsigned short Nb_61_80[8][4];
+extern unsigned short Nb_81_110[8][4];
+
+extern uint16_t hundred_times_log10_NPRB[100];
+extern uint8_t alpha_lut[8];
+*/
+#endif /*__PHY_EXTERN_H__ */
+
diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h
index 5707aedd27ccdff32b079a7ce142d77522dddd5e..b710e943eda511da6ca4c1f8ff430ecf2e313ea5 100644
--- a/openair1/PHY/impl_defs_lte.h
+++ b/openair1/PHY/impl_defs_lte.h
@@ -587,6 +587,7 @@ typedef struct {
 
   struct MBSFN_SubframeConfig *mbsfn_SubframeConfig[MAX_MBSFN_AREA];
 
+
 } LTE_DL_FRAME_PARMS;
 
 typedef enum {
diff --git a/openair1/PHY/impl_defs_lte_NB_IoT.h b/openair1/PHY/impl_defs_lte_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..4284169c995a4d7907d9b7c6ec1282cca8b101f3
--- /dev/null
+++ b/openair1/PHY/impl_defs_lte_NB_IoT.h
@@ -0,0 +1,732 @@
+/*
+ * 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.0  (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/impl_defs_lte.h
+* \brief LTE Physical channel configuration and variable structure definitions
+* \author R. Knopp, F. Kaltenberger
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
+* \note
+* \warning
+*/
+
+#ifndef __PHY_IMPL_DEFS_NB_IOT__H__
+#define __PHY_IMPL_DEFS_NB_IOT__H__
+
+#include "types_NB_IoT.h"
+//#include "defs.h"
+
+typedef enum {TDD_NB_IoT=1,FDD_NB_IoT=0} NB_IoT_frame_type_t;
+typedef enum {EXTENDED_NB_IoT=1,NORMAL_NB_IoT=0} NB_IoT_prefix_type_t;
+typedef enum {SF_DL_NB_IoT, SF_UL_NB_IoT, SF_S_NB_IoT} NB_IoT_subframe_t;
+
+#define	A_SEQUENCE_OF(type)	A_SET_OF(type)
+
+#define	A_SET_OF(type)					\
+	struct {					\
+		type **array;				\
+		int count;	/* Meaningful size */	\
+		int size;	/* Allocated size */	\
+		void (*free)(type *);			\
+	}
+
+
+/////////////////////////
+  /// Union for \ref TPC_PDCCH_CONFIG::tpc_Index.
+typedef union {
+  /// Index of N when DCI format 3 is used. See TS 36.212 (5.3.3.1.6). \vr{[1..15]}
+  uint8_t indexOfFormat3;
+  /// Index of M when DCI format 3A is used. See TS 36.212 (5.3.3.1.7). \vr{[1..31]}
+  uint8_t indexOfFormat3A;
+} TPC_INDEX_NB_IoT_t;
+
+/// TPC-PDCCH-Config Information Element from 36.331 RRC spec
+typedef struct {
+  /// RNTI for power control using DCI format 3/3A, see TS 36.212. \vr{[0..65535]}
+  uint16_t rnti;
+  /// Index of N or M, see TS 36.212 (5.3.3.1.6 and 5.3.3.1.7), where N or M is dependent on the used DCI format (i.e. format 3 or 3a).
+  TPC_INDEX_NB_IoT_t tpc_Index;
+} TPC_PDCCH_CONFIG_NB_IoT;
+  /// Enumeration for parameter \f$N_\text{ANRep}\f$ \ref PUCCH_CONFIG_DEDICATED::repetitionFactor.
+typedef enum {
+  //n2=0,
+  n4_n,
+  n6_n
+} ACKNAKREP_NB_IoT_t;
+
+/// Enumeration for \ref PUCCH_CONFIG_DEDICATED::tdd_AckNackFeedbackMode.
+typedef enum {
+  bundling_N=0,
+  multiplexing_N
+} ANFBmode_NB_IoT_t;
+
+/// PUCCH-ConfigDedicated from 36.331 RRC spec
+typedef struct {
+  /// Flag to indicate ACK NAK repetition activation, see TS 36.213 (10.1). \vr{[0..1]}
+  uint8_t ackNackRepetition;
+  /// Parameter: \f$N_\text{ANRep}\f$, see TS 36.213 (10.1).
+  ACKNAKREP_NB_IoT_t repetitionFactor;
+  /// Parameter: \f$n^{(1)}_\text{PUCCH,ANRep}\f$, see TS 36.213 (10.1). \vr{[0..2047]}
+  uint16_t n1PUCCH_AN_Rep;
+  /// Feedback mode, see TS 36.213 (7.3). \details Applied to both PUCCH and PUSCH feedback. For TDD, should always be set to bundling.
+  ANFBmode_NB_IoT_t tdd_AckNackFeedbackMode;
+} PUCCH_CONFIG_DEDICATED_NB_IoT;
+  // UE specific PUSCH configuration.
+typedef struct {
+  /// Parameter: \f$I^\text{HARQ-ACK}_\text{offset}\f$, see TS 36.213 (Table 8.6.3-1). \vr{[0..15]}
+  uint16_t betaOffset_ACK_Index;
+  /// Parameter: \f$I^{RI}_\text{offset}\f$, see TS 36.213 (Table 8.6.3-2). \vr{[0..15]}
+  uint16_t betaOffset_RI_Index;
+  /// Parameter: \f$I^{CQI}_\text{offset}\f$, see TS 36.213 (Table 8.6.3-3). \vr{[0..15]}
+  uint16_t betaOffset_CQI_Index;
+} PUSCH_CONFIG_DEDICATED_NB_IoT;
+/// Enumeration for Parameter \f$P_A\f$ \ref PDSCH_CONFIG_DEDICATED::p_a.
+typedef enum {
+  //dBm6=0, ///< (dB-6) corresponds to -6 dB
+ // dBm477, ///< (dB-4dot77) corresponds to -4.77 dB
+ // dBm3,   ///< (dB-3) corresponds to -3 dB
+  //dBm177, ///< (dB-1dot77) corresponds to -1.77 dB
+  //dB0,    ///< corresponds to 0 dB
+ // dB1,    ///< corresponds to 1 dB
+  dB2_NB,    ///< corresponds to 2 dB
+  dB3_NB     ///< corresponds to 3 dB
+} PA_NB_IoT_t;
+
+/// PDSCH-ConfigDedicated from 36.331 RRC spec
+typedef struct {
+  /// Parameter: \f$P_A\f$, see TS 36.213 (5.2).
+  PA_NB_IoT_t p_a;
+} PDSCH_CONFIG_DEDICATED_NB_IoT;
+
+/// UplinkPowerControlDedicated Information Element from 36.331 RRC spec
+typedef struct {
+  /// Parameter: \f$P_\text{0\_UE\_PUSCH}(1)\f$, see TS 36.213 (5.1.1.1), unit dB. \vr{[-8..7]}\n This field is applicable for non-persistent scheduling, only.
+  int8_t p0_UE_PUSCH;
+  /// Parameter: Ks, see TS 36.213 (5.1.1.1). \vr{[0..1]}\n en0 corresponds to value 0 corresponding to state “disabled”. en1 corresponds to value 1.25 corresponding to “enabled”. \note the specification sais it is an enumerated value. \warning the enumeration values do not correspond to the given values in the specification (en1 should be 1.25).
+  uint8_t deltaMCS_Enabled;
+  /// Parameter: Accumulation-enabled, see TS 36.213 (5.1.1.1). \vr{[0..1]} 1 corresponds to "enabled" whereas 0 corresponds to "disabled".
+  uint8_t accumulationEnabled;
+  /// Parameter: \f$P_\text{0\_UE\_PUCCH}(1)\f$, see TS 36.213 (5.1.2.1), unit dB. \vr{[-8..7]}
+  int8_t p0_UE_PUCCH;
+  /// Parameter: \f$P_\text{SRS\_OFFSET}\f$, see TS 36.213 (5.1.3.1). \vr{[0..15]}\n For Ks=1.25 (\ref deltaMCS_Enabled), the actual parameter value is pSRS_Offset value - 3. For Ks=0, the actual parameter value is -10.5 + 1.5*pSRS_Offset value.
+  int8_t pSRS_Offset;
+  /// Specifies the filtering coefficient for RSRP measurements used to calculate path loss, as specified in TS 36.213 (5.1.1.1).\details The same filtering mechanism applies as for quantityConfig described in 5.5.3.2. \note the specification sais it is an enumerated value.
+  uint8_t filterCoefficient;
+} UL_POWER_CONTROL_DEDICATED_NB_IoT;
+
+/// Union for \ref TPC_PDCCH_CONFIG::tpc_Index.
+//typedef union {
+  /// Index of N when DCI format 3 is used. See TS 36.212 (5.3.3.1.6). \vr{[1..15]}
+ // uint8_t indexOfFormat3;
+  /// Index of M when DCI format 3A is used. See TS 36.212 (5.3.3.1.7). \vr{[1..31]}
+ // uint8_t indexOfFormat3A;
+//} TPC_INDEX_NB_IoT_t;
+
+/// CQI-ReportPeriodic
+typedef struct {
+  /// Parameter: \f$n^{(2)}_\text{PUCCH}\f$, see TS 36.213 (7.2). \vr{[0..1185]}, -1 indicates inactivity
+  int16_t cqi_PUCCH_ResourceIndex;
+  /// Parameter: CQI/PMI Periodicity and Offset Configuration Index \f$I_\text{CQI/PMI}\f$, see TS 36.213 (tables 7.2.2-1A and 7.2.2-1C). \vr{[0..1023]}
+  int16_t cqi_PMI_ConfigIndex;
+  /// Parameter: K, see 36.213 (4.2.2). \vr{[1..4]}
+  uint8_t K;
+  /// Parameter: RI Config Index \f$I_\text{RI}\f$, see TS 36.213 (7.2.2-1B). \vr{[0..1023]}, -1 indicates inactivity
+  int16_t ri_ConfigIndex;
+  /// Parameter: Simultaneous-AN-and-CQI, see TS 36.213 (10.1). \vr{[0..1]} 1 indicates that simultaneous transmission of ACK/NACK and CQI is allowed.
+  uint8_t simultaneousAckNackAndCQI;
+  /// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
+  uint16_t Npd;
+  /// parameter computed from Tables 7.2.2-1A and 7.2.2-1C
+  uint16_t N_OFFSET_CQI;
+} CQI_REPORTPERIODIC_NB_IoT;
+
+/// Enumeration for parameter reporting mode \ref CQI_REPORT_CONFIG::cqi_ReportModeAperiodic.
+typedef enum {
+  //rm12=0,
+  //rm20=1,
+  //rm22=2,
+  rm30_N=3,
+  rm31_N=4
+} CQI_REPORTMODEAPERIODIC_NB_IoT;
+
+/// CQI-ReportConfig Information Element from 36.331 RRC spec
+typedef struct {
+  /// Parameter: reporting mode. Value rm12 corresponds to Mode 1-2, rm20 corresponds to Mode 2-0, rm22 corresponds to Mode 2-2 etc. PUSCH reporting modes are described in TS 36.213 [23, 7.2.1].
+  CQI_REPORTMODEAPERIODIC_NB_IoT cqi_ReportModeAperiodic;
+  /// Parameter: \f$\Delta_\text{offset}\f$, see TS 36.213 (7.2.3). \vr{[-1..6]}\n Actual value = IE value * 2 [dB].
+  int8_t nomPDSCH_RS_EPRE_Offset;
+  CQI_REPORTPERIODIC_NB_IoT CQI_ReportPeriodic;
+} CQI_REPORT_CONFIG_NB_IoT;
+
+/// SoundingRS-UL-ConfigDedicated Information Element from 36.331 RRC spec
+typedef struct {
+  /// Parameter: \f$B_\text{SRS}\f$, see TS 36.211 (table 5.5.3.2-1, 5.5.3.2-2, 5.5.3.2-3 and 5.5.3.2-4). \vr{[0..3]} \note the specification sais it is an enumerated value.
+  uint8_t srs_Bandwidth;
+  /// Parameter: SRS hopping bandwidth \f$b_\text{hop}\in\{0,1,2,3\}\f$, see TS 36.211 (5.5.3.2) \vr{[0..3]} \note the specification sais it is an enumerated value.
+  uint8_t srs_HoppingBandwidth;
+  /// Parameter: \f$n_\text{RRC}\f$, see TS 36.211 (5.5.3.2). \vr{[0..23]}
+  uint8_t freqDomainPosition;
+  /// Parameter: Duration, see TS 36.213 (8.2). \vr{[0..1]} 0 corresponds to "single" and 1 to "indefinite".
+  uint8_t duration;
+  /// Parameter: \f$k_\text{TC}\in\{0,1\}\f$, see TS 36.211 (5.5.3.2). \vr{[0..1]}
+  uint8_t transmissionComb;
+  /// Parameter: \f$I_\text{SRS}\f$, see TS 36.213 (table 8.2-1). \vr{[0..1023]}
+  uint16_t srs_ConfigIndex;
+  /// Parameter: \f$n^\text{CS}_\text{SRS}\f$. See TS 36.211 (5.5.3.1). \vr{[0..7]} \note the specification sais it is an enumerated value.
+  uint8_t cyclicShift;
+  // Parameter: internal implementation: UE SRS configured
+  uint8_t srsConfigDedicatedSetup;
+  // Parameter: cell srs subframe for internal implementation
+  uint8_t srsCellSubframe;
+  // Parameter: ue srs subframe for internal implementation
+  uint8_t srsUeSubframe;
+} SOUNDINGRS_UL_CONFIG_DEDICATED_NB_IoT;
+
+
+/// Enumeration for parameter SR transmission \ref SCHEDULING_REQUEST_CONFIG::dsr_TransMax.
+typedef enum {
+  //sr_n4=0,
+ // sr_n8=1,
+ // sr_n16=2,
+  sr_n32_N=3,
+  sr_n64_N=4
+} DSR_TRANSMAX_NB_IoT_t;
+
+/// SchedulingRequestConfig Information Element from 36.331 RRC spec
+typedef struct {
+  /// Parameter: \f$n^{(1)}_\text{PUCCH,SRI}\f$, see TS 36.213 (10.1). \vr{[0..2047]}
+  uint16_t sr_PUCCH_ResourceIndex;
+  /// Parameter: \f$I_\text{SR}\f$, see TS 36.213 (10.1). \vr{[0..155]}
+  uint8_t sr_ConfigIndex;
+  /// Parameter for SR transmission in TS 36.321 (5.4.4). \details The value n4 corresponds to 4 transmissions, n8 corresponds to 8 transmissions and so on.
+  DSR_TRANSMAX_NB_IoT_t dsr_TransMax;
+} SCHEDULING_REQUEST_CONFIG_NB_IoT;
+
+typedef struct {
+  /// Downlink Power offset field
+  uint8_t dl_pow_off;
+  ///Subband resource allocation field
+  uint8_t rballoc_sub[50];
+  ///Total number of PRBs indicator
+  uint8_t pre_nb_available_rbs;
+} MU_MIMO_mode_NB_IoT;
+////////////////////////
+
+typedef struct {
+
+    /// \brief Holds the received data in the frequency domain.
+    /// - first index: rx antenna [0..nb_antennas_rx[
+    /// - second index: symbol [0..28*ofdm_symbol_size[
+    int32_t **rxdataF;
+
+    /// \brief Hold the channel estimates in frequency domain.
+    /// - first index: eNB id [0..6] (hard coded)
+    /// - second index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+    /// - third index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[
+    int32_t **dl_ch_estimates[7];
+
+    /// \brief Hold the channel estimates in time domain (used for tracking).
+    /// - first index: eNB id [0..6] (hard coded)
+    /// - second index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+    /// - third index: samples? [0..2*ofdm_symbol_size[
+    int32_t **dl_ch_estimates_time[7];
+}NB_IoT_UE_COMMON_PER_THREAD;
+
+typedef struct {
+  /// \brief Holds the transmit data in time domain.
+  /// For IFFT_FPGA this points to the same memory as PHY_vars->tx_vars[a].TX_DMA_BUFFER.
+  /// - first index: tx antenna [0..nb_antennas_tx[
+  /// - second index: sample [0..FRAME_LENGTH_COMPLEX_SAMPLES[
+  int32_t **txdata;
+  /// \brief Holds the transmit data in the frequency domain.
+  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
+  /// - first index: tx antenna [0..nb_antennas_tx[
+  /// - second index: sample [0..FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX[
+  int32_t **txdataF;
+
+  /// \brief Holds the received data in time domain.
+  /// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: sample [0..FRAME_LENGTH_COMPLEX_SAMPLES+2048[
+  int32_t **rxdata;
+
+  NB_IoT_UE_COMMON_PER_THREAD common_vars_rx_data_per_thread[2];
+
+  /// holds output of the sync correlator
+  int32_t *sync_corr;
+  /// estimated frequency offset (in radians) for all subcarriers
+  int32_t freq_offset;
+  /// eNb_id user is synched to
+  int32_t eNb_id;
+} NB_IoT_UE_COMMON;
+
+/// NPRACH-ParametersList-NB-r13 from 36.331 RRC spec
+typedef struct NPRACH_Parameters_NB_IoT{
+  /// the period time for nprach
+  uint16_t nprach_Periodicity;
+  /// for the start time for the NPRACH resource from 40ms-2560ms
+  uint16_t nprach_StartTime;
+  /// for the subcarrier of set to the NPRACH preamble from n0 - n34
+  uint16_t nprach_SubcarrierOffset;
+  ///number of subcarriers in a NPRACH resource allowed values (n12,n24,n36,n48)
+  uint16_t nprach_NumSubcarriers;
+  /// where is the region that in NPRACH resource to indicate if this UE support MSG3 for multi-tone or not. from 0 - 1
+  uint16_t nprach_SubcarrierMSG3_RangeStart;
+  /// The max preamble transmission attempt for the CE level from 1 - 128
+  uint16_t maxNumPreambleAttemptCE;
+  /// Number of NPRACH repetitions per attempt for each NPRACH resource
+  uint16_t numRepetitionsPerPreambleAttempt;
+  /// The number of the repetition for DCI use in RAR/MSG3/MSG4 from 1 - 2048 (Rmax)
+  uint16_t npdcch_NumRepetitions_RA;
+  /// Starting subframe for NPDCCH Common searching space for (RAR/MSG3/MSG4)
+  uint16_t npdcch_StartSF_CSS_RA;
+  /// Fractional period offset of starting subframe for NPDCCH common search space
+  uint16_t npdcch_Offset_RA;
+} nprach_parameters_NB_IoT_t;
+
+typedef struct{
+  A_SEQUENCE_OF(nprach_parameters_NB_IoT_t) list;
+}NPRACH_List_NB_IoT_t;
+
+typedef long RSRP_Range_t;
+
+typedef struct {
+  A_SEQUENCE_OF(RSRP_Range_t) list;
+}rsrp_ThresholdsNPrachInfoList;
+
+
+/// NPRACH_ConfigSIB-NB from 36.331 RRC spec
+typedef struct {
+  /// nprach_CP_Length_r13, for the CP length(unit us) only 66.7 and 266.7 is implemented
+  uint16_t nprach_CP_Length;
+  /// The criterion for UEs to select a NPRACH resource. Up to 2 RSRP threshold values can be signalled.  \vr{[1..2]}
+  struct rsrp_ThresholdsNPrachInfoList *rsrp_ThresholdsPrachInfoList;
+  /// NPRACH Parameters List
+  NPRACH_List_NB_IoT_t nprach_ParametersList;
+
+} NPRACH_CONFIG_COMMON;
+
+/// NPDSCH-ConfigCommon from 36.331 RRC spec
+typedef struct {
+  ///see TS 36.213 (16.2). \vr{[-60..50]}\n Provides the downlink reference-signal EPRE. The actual value in dBm.
+  uint16_t nrs_Power;
+} NPDSCH_CONFIG_COMMON;
+
+typedef struct{
+  /// The base sequence of DMRS sequence in a cell for 3 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 12. Value 12 is not used.
+  uint16_t threeTone_BaseSequence;
+  /// Define 3 cyclic shifts for the 3-tone case, see TS 36.211 [21, 10.1.4.1.2].
+  uint16_t threeTone_CyclicShift;
+  /// The base sequence of DMRS sequence in a cell for 6 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 14. Value 14 is not used.
+  uint16_t sixTone_BaseSequence;
+  /// Define 4 cyclic shifts for the 6-tone case, see TS 36.211 [21, 10.1.4.1.2].
+  uint16_t sixTone_CyclicShift;
+  /// The base sequence of DMRS sequence in a cell for 12 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 30. Value 30 is not used.
+  uint16_t twelveTone_BaseSequence;
+
+}DMRS_CONFIG_t;
+
+/// UL-ReferenceSignalsNPUSCH from 36.331 RRC spec
+typedef struct {
+  /// Parameter: Group-hopping-enabled, see TS 36.211 (5.5.1.3). \vr{[0..1]}
+  uint8_t groupHoppingEnabled;
+  /// , see TS 36.211 (5.5.1.3). \vr{[0..29]}
+  uint8_t groupAssignmentNPUSCH;
+  /// Parameter: cyclicShift, see TS 36.211 (Table 5.5.2.1.1-2). \vr{[0..7]}
+  uint8_t cyclicShift;
+  /// nPRS for cyclic shift of DRS \note not part of offical UL-ReferenceSignalsPUSCH ASN1 specification.
+  uint8_t nPRS[20];
+  /// group hopping sequence for DMRS, 36.211, Section 10.1.4.1.3. Second index corresponds to the four possible subcarrier configurations
+  uint8_t grouphop[20][4];
+  /// sequence hopping sequence for DRS \note not part of offical UL-ReferenceSignalsPUSCH ASN1 specification.
+  uint8_t seqhop[20];
+} UL_REFERENCE_SIGNALS_NPUSCH_t;
+
+
+/// PUSCH-ConfigCommon from 36.331 RRC spec.
+typedef struct {
+  /// Number of repetitions for ACK/NACK HARQ response to NPDSCH containing Msg4 per NPRACH resource, see TS 36.213 [23, 16.4.2].
+  uint8_t ack_NACK_NumRepetitions_Msg4[3];
+  /// SRS SubframeConfiguration. See TS 36.211 [21, table 5.5.3.3-1]. Value sc0 corresponds to value 0, sc1 to value 1 and so on.
+  uint8_t srs_SubframeConfig;
+  /// Parameter: \f$N^{HO}_{RB}\f$, see TS 36.211 (5.3.4). \vr{[0..98]}
+  DMRS_CONFIG_t dmrs_Config;
+  /// Ref signals configuration
+  UL_REFERENCE_SIGNALS_NPUSCH_t ul_ReferenceSignalsNPUSCH;
+
+} NPUSCH_CONFIG_COMMON;
+
+
+typedef struct{
+  /// See TS 36.213 [23, 16.2.1.1], unit dBm.
+  uint8_t p0_NominalNPUSCH;
+  /// See TS 36.213 [23, 16.2.1.1] where al0 corresponds to 0, al04 corresponds to value 0.4, al05 to 0.5, al06 to 0.6, al07 to 0.7, al08 to 0.8, al09 to 0.9 and al1 corresponds to 1. 
+  uint8_t alpha;
+  /// See TS 36.213 [23, 16.2.1.1]. Actual value = IE value * 2 [dB].
+  uint8_t deltaPreambleMsg3;
+}UplinkPowerControlCommon_NB_IoT;
+
+
+/* DL-GapConfig-NB-r13 */
+typedef struct {
+	uint16_t	 dl_GapThreshold;
+	uint16_t	 dl_GapPeriodicity;
+	uint16_t	 dl_GapDurationCoeff;
+} DL_GapConfig_NB_IoT;
+
+
+typedef struct {
+
+  /// Frame type (0 FDD, 1 TDD)
+  NB_IoT_frame_type_t frame_type;
+  /// Number of resource blocks (RB) in DL of the LTE (for knowing the bandwidth)
+  uint8_t N_RB_DL;
+  /// Number of resource blocks (RB) in UL of the LTE ((for knowing the bandwidth)
+  uint8_t N_RB_UL;
+  /// TDD subframe assignment (0-7) (default = 3) (254=RX only, 255=TX only)
+  uint8_t tdd_config;
+  /// Cell ID
+  uint16_t Nid_cell;
+  /// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
+  NB_IoT_prefix_type_t Ncp;
+  /// Cyclic Prefix for UL (0=Normal CP, 1=Extended CP)
+  NB_IoT_prefix_type_t Ncp_UL;
+  /// shift of pilot position in one RB
+  uint8_t nushift;
+  /// indicates if node is a UE (NODE=2) or eNB (PRIMARY_CH=0).
+  uint8_t node_id;
+  /// Frequency index of CBMIMO1 card
+  uint8_t freq_idx;
+  /// RX Frequency for ExpressMIMO/LIME
+  uint32_t carrier_freq[4];
+  /// TX Frequency for ExpressMIMO/LIME
+  uint32_t carrier_freqtx[4];
+  /// RX gain for ExpressMIMO/LIME
+  uint32_t rxgain[4];
+  /// TX gain for ExpressMIMO/LIME
+  uint32_t txgain[4];
+  /// RF mode for ExpressMIMO/LIME
+  uint32_t rfmode[4];
+  /// RF RX DC Calibration for ExpressMIMO/LIME
+  uint32_t rxdc[4];
+  /// RF TX DC Calibration for ExpressMIMO/LIME
+  uint32_t rflocal[4];
+  /// RF VCO calibration for ExpressMIMO/LIME
+  uint32_t rfvcolocal[4];
+  /// Turns on second TX of CBMIMO1 card
+  uint8_t dual_tx;
+  /// flag to indicate SISO transmission
+  uint8_t mode1_flag;
+  /// Indicator that 20 MHz channel uses 3/4 sampling frequency
+  //uint8_t threequarter_fs;
+  /// Size of FFT
+  uint16_t ofdm_symbol_size;
+  /// Number of prefix samples in all but first symbol of slot
+  uint16_t nb_prefix_samples;
+  /// Number of prefix samples in first symbol of slot
+  uint16_t nb_prefix_samples0;
+  /// Carrier offset in FFT buffer for first RE in PRB0
+  uint16_t first_carrier_offset;
+  /// Number of samples in a subframe
+  uint32_t samples_per_tti;
+  /// Number of OFDM/SC-FDMA symbols in one subframe (to be modified to account for potential different in UL/DL)
+  uint16_t symbols_per_tti;
+  /// Number of Physical transmit antennas in node
+  uint8_t nb_antennas_tx;
+  /// Number of Receive antennas in node
+  uint8_t nb_antennas_rx;
+  /// Number of common transmit antenna ports in eNodeB (1 or 2)
+  uint8_t nb_antenna_ports_eNB;
+  /// Number of common receiving antenna ports in eNodeB (1 or 2)
+  uint8_t nb_antenna_ports_rx_eNB;
+  /// NPRACH Config Common (from 36-331 RRC spec)
+  NPRACH_CONFIG_COMMON nprach_config_common;
+  /// NPDSCH Config Common (from 36-331 RRC spec)
+  NPDSCH_CONFIG_COMMON npdsch_config_common;
+  /// PUSCH Config Common (from 36-331 RRC spec)
+  NPUSCH_CONFIG_COMMON npusch_config_common;
+  /// UL Power Control (from 36-331 RRC spec)
+  UplinkPowerControlCommon_NB_IoT ul_power_control_config_common;
+  /// DL Gap
+  DL_GapConfig_NB_IoT DL_gap_config;
+  /// Size of SI windows used for repetition of one SI message (in frames)
+  uint8_t SIwindowsize;
+  /// Period of SI windows used for repetition of one SI message (in frames)
+  uint16_t SIPeriod;
+  int                 eutra_band;
+  uint32_t            dl_CarrierFreq;
+  uint32_t            ul_CarrierFreq;
+  // CE level to determine the NPRACH Configuration (one CE for each NPRACH config.)
+  uint8_t             CE;
+
+  /*
+   * index of the PRB assigned to NB-IoT carrier in in-band/guard-band operating mode
+   */
+  unsigned short NB_IoT_RB_ID;
+
+
+  /*Following FAPI approach:
+   * 0 = in-band with same PCI
+   * 1 = in-band with diff PCI
+   * 2 = guard band
+   * 3 =stand alone
+   */
+  uint16_t operating_mode;
+
+  /*
+   * Only for In-band operating mode with same PCI
+   * its measured in number of OFDM symbols
+   * allowed values:
+   * 1, 2, 3, 4(this value is written in FAPI specs but not exist in TS 36.331 v14.2.1 pag 587)
+   * -1 (we put this value when is not defined - other operating mode)
+   */
+  uint16_t control_region_size;
+
+  /*Number of EUTRA CRS antenna ports (AP)
+   * valid only for in-band different PCI mode
+   * value 0 = indicates the same number of AP as NRS APs
+   * value 1 = four CRS APs
+   */
+  uint16_t eutra_NumCRS_ports;
+
+
+} NB_IoT_DL_FRAME_PARMS;
+
+typedef struct {
+  /// \brief Holds the transmit data in time domain.
+  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: tx antenna [0..nb_antennas_tx[
+  /// - third index:
+  int32_t **txdata[3];
+  /// \brief holds the transmit data in the frequency domain.
+  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //?
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: tx antenna [0..14[ where 14 is the total supported antenna ports.
+  /// - third index: sample [0..]
+  int32_t **txdataF[3];
+  /// \brief holds the transmit data after beamforming in the frequency domain.
+  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER. //?
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: tx antenna [0..nb_antennas_tx[
+  /// - third index: sample [0..]
+  int32_t **txdataF_BF[3];
+  /// \brief Holds the received data in time domain.
+  /// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna [0..nb_antennas_rx[
+  /// - third index: sample [0..]
+  int32_t **rxdata[3];
+  /// \brief Holds the last subframe of received data in time domain after removal of 7.5kHz frequency offset.
+  /// - first index: secotr id [0..2] (hard coded)
+  /// - second index: rx antenna [0..nb_antennas_rx[
+  /// - third index: sample [0..samples_per_tti[
+  int32_t **rxdata_7_5kHz[3];
+  /// \brief Holds the received data in the frequency domain.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna [0..nb_antennas_rx[
+  /// - third index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[
+  int32_t **rxdataF[3];
+  /// \brief Holds output of the sync correlator.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: sample [0..samples_per_tti*10[
+  uint32_t *sync_corr[3];
+  /// \brief Holds the beamforming weights
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: eNB antenna port index (hard coded)
+  /// - third index: tx antenna [0..nb_antennas_tx[
+  /// - fourth index: sample [0..]
+  int32_t **beam_weights[3][15];
+  /// \brief Holds the tdd reciprocity calibration coefficients
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: tx antenna [0..nb_antennas_tx[
+  /// - third index: frequency [0..]
+  int32_t **tdd_calib_coeffs[3];
+} NB_IoT_eNB_COMMON;
+
+typedef struct {
+  /// \brief Hold the channel estimates in frequency domain based on SRS.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..ofdm_symbol_size[
+  int32_t **srs_ch_estimates[3];
+  /// \brief Hold the channel estimates in time domain based on SRS.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..2*ofdm_symbol_size[
+  int32_t **srs_ch_estimates_time[3];
+  /// \brief Holds the SRS for channel estimation at the RX.
+  /// - first index: ? [0..ofdm_symbol_size[
+  int32_t *srs;
+} NB_IoT_eNB_SRS;
+
+typedef struct {
+  /// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..2*ofdm_symbol_size[
+  /// - third index (definition from phy_init_lte_eNB()): ? [0..24*N_RB_UL*frame_parms->symbols_per_tti[
+  /// \warning inconsistent third index definition
+  int32_t **rxdataF_ext[3];
+  /// \brief Holds the received data in the frequency domain for the allocated RBs in normal format.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **rxdataF_ext2[3];
+  /// \brief Hold the channel estimates in time domain based on DRS.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..4*ofdm_symbol_size[
+  int32_t **drs_ch_estimates_time[3];
+  /// \brief Hold the channel estimates in frequency domain based on DRS.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **drs_ch_estimates[3];
+  /// \brief Hold the channel estimates for UE0 in case of Distributed Alamouti Scheme.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **drs_ch_estimates_0[3];
+  /// \brief Hold the channel estimates for UE1 in case of Distributed Almouti Scheme.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **drs_ch_estimates_1[3];
+  /// \brief Holds the compensated signal.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **rxdataF_comp[3];
+  /// \brief Hold the compensated data (y)*(h0*) in case of Distributed Alamouti Scheme.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **rxdataF_comp_0[3];
+  /// \brief Hold the compensated data (y*)*(h1) in case of Distributed Alamouti Scheme.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **rxdataF_comp_1[3];
+  /// \brief ?.
+  /// - first index: sector id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_mag[3];
+  /// \brief ?.
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_magb[3];
+  /// \brief Hold the channel mag for UE0 in case of Distributed Alamouti Scheme.
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_mag_0[3];
+  /// \brief Hold the channel magb for UE0 in case of Distributed Alamouti Scheme.
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_magb_0[3];
+  /// \brief Hold the channel mag for UE1 in case of Distributed Alamouti Scheme.
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_mag_1[3];
+  /// \brief Hold the channel magb for UE1 in case of Distributed Alamouti Scheme.
+  /// - first index: eNB id [0..2] (hard coded)
+  /// - second index: rx antenna id [0..nb_antennas_rx[
+  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_magb_1[3];
+  /// measured RX power based on DRS
+  int ulsch_power[2];
+  /// measured RX power based on DRS for UE0 in case of Distributed Alamouti Scheme
+  int ulsch_power_0[2];
+  /// measured RX power based on DRS for UE0 in case of Distributed Alamouti Scheme
+  int ulsch_power_1[2];
+  /// \brief llr values.
+  /// - first index: ? [0..1179743] (hard coded)
+  int16_t *llr;
+#ifdef LOCALIZATION
+  /// number of active subcarrier for a specific UE
+  int32_t active_subcarrier;
+  /// subcarrier power in dBm
+  int32_t *subcarrier_power;
+#endif
+} NB_IoT_eNB_PUSCH;
+
+#define PBCH_A_NB_IoT 24
+typedef struct {
+  uint8_t pbch_d[96+(3*(16+PBCH_A_NB_IoT))];
+  uint8_t pbch_w[3*3*(16+PBCH_A_NB_IoT)];
+  uint8_t pbch_e[1920];
+} NB_IoT_eNB_PBCH;
+
+
+typedef enum {
+  /// TM1
+  SISO_NB_IoT=0,
+  /// TM2
+  ALAMOUTI_NB_IoT=1,
+  /// TM3
+  LARGE_CDD_NB_IoT=2,
+  /// the next 6 entries are for TM5
+  UNIFORM_PRECODING11_NB_IoT=3,
+  UNIFORM_PRECODING1m1_NB_IoT=4,
+  UNIFORM_PRECODING1j_NB_IoT=5,
+  UNIFORM_PRECODING1mj_NB_IoT=6,
+  PUSCH_PRECODING0_NB_IoT=7,
+  PUSCH_PRECODING1_NB_IoT=8,
+  /// the next 3 entries are for TM4
+  DUALSTREAM_UNIFORM_PRECODING1_NB_IoT=9,
+  DUALSTREAM_UNIFORM_PRECODINGj_NB_IoT=10,
+  DUALSTREAM_PUSCH_PRECODING_NB_IoT=11,
+  TM7_NB_IoT=12,
+  TM8_NB_IoT=13,
+  TM9_10_NB_IoT=14
+} MIMO_mode_NB_IoT_t;
+
+typedef struct {
+  /// \brief ?.
+  /// first index: ? [0..1023] (hard coded)
+  int16_t *prachF;
+  /// \brief ?.
+  /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
+  /// second index: ? [0..ofdm_symbol_size*12[
+  int16_t *rxsigF[64];
+  /// \brief local buffer to compute prach_ifft (necessary in case of multiple CCs)
+  /// first index: rx antenna [0..63] (hard coded) \note Hard coded array size indexed by \c nb_antennas_rx.
+  /// second index: ? [0..2047] (hard coded)
+  int16_t *prach_ifft[64];
+} NB_IoT_eNB_PRACH;
+
+typedef enum {
+  NOT_SYNCHED_NB_IoT=0,
+  PRACH_NB_IoT=1,
+  RA_RESPONSE_NB_IoT=2,
+  PUSCH_NB_IoT=3,
+  RESYNCH_NB_IoT=4
+} UE_MODE_NB_IoT_t;
+
+
+#endif
diff --git a/openair1/PHY/impl_defs_lte_nb_iot.h b/openair1/PHY/impl_defs_lte_nb_iot.h
deleted file mode 100644
index a252b86b26f9cf2d15b1d39ece74b4b478677cb5..0000000000000000000000000000000000000000
--- a/openair1/PHY/impl_defs_lte_nb_iot.h
+++ /dev/null
@@ -1,235 +0,0 @@
-/*
- * 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.0  (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/impl_defs_lte.h
-* \brief LTE Physical channel configuration and variable structure definitions
-* \author R. Knopp, F. Kaltenberger
-* \date 2011
-* \version 0.1
-* \company Eurecom
-* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
-* \note
-* \warning
-*/
-
-
-#ifndef __PHY_IMPL_DEFS_NB_IOT__H__
-#define __PHY_IMPL_DEFS_NB_IOT__H__
-
-#include "types.h"
-//#include "defs.h"
-
-#define	A_SEQUENCE_OF(type)	A_SET_OF(type)
-
-#define	A_SET_OF(type)					\
-	struct {					\
-		type **array;				\
-		int count;	/* Meaningful size */	\
-		int size;	/* Allocated size */	\
-		void (*free)(type *);			\
-	}
-
-
-/// NPRACH-ParametersList-NB-r13 from 36.331 RRC spec
-typedef struct {
-  /// the period time for nprach
-  uint8_t nprach_Periodicity;
-  /// for the start time for the NPRACH resource from 40ms-2560ms
-  uint8_t nprach_StartTime;	
-  /// for the subcarrier of set to the NPRACH preamble from n0 - n34
-  uint8_t nprach_SubcarrierOffset;
-  /// where is the region that in NPRACH resource to indicate if this UE support MSG3 for multi-tone or not. from 0 - 1
-  uint8_t nprach_SubcarrierMSG3_RangeStart;
-  /// The max preamble transmission attempt for the CE level from 1 - 128
-  uint8_t maxNumPreambleAttemptCE;
-  /// The number of the repetition for DCI use in RAR/MSG3/MSG4 from 1 - 2048
-  uint8_t npdcch_NumRepetitions_RA;
-  /// Starting subframe for NPDCCH Common searching space for (RAR/MSG3/MSG4)
-  uint8_t npdcch_StartSF_CSS_RA;
-  /// Fractional period offset of starting subframe for NPDCCH common search space
-  uint8_t npdcch_Offset_RA;
-} nprach_parameters_NB_t;
-
-typedef struct{
-  A_SEQUENCE_OF(struct NPRACH_Parameters_NB) list;
-}NPRACH_List_NB_t;
-
-typedef long RSRP_Range_t;
-
-typedef struct {
-  A_SEQUENCE_OF(RSRP_Range_t) list;
-}rsrp_ThresholdsNPrachInfoList;
-
-
-/// NPRACH_ConfigSIB-NB from 36.331 RRC spec
-typedef struct {
-  /// nprach_CP_Length_r13, for the CP length(unit us) only 66.7 and 266.7 is implemented
-  uint8_t nprach_CP_Length;
-  /// The criterion for UEs to select a NPRACH resource. Up to 2 RSRP threshold values can be signalled.  \vr{[1..2]}
-  struct rsrp_ThresholdsNPrachInfoList *rsrp_ThresholdsPrachInfoList;
-  /// NPRACH Parameters List
-  NPRACH_List_NB_t nprach_ParametersList;
-} NPRACH_CONFIG_COMMON;
-
-/// NPDSCH-ConfigCommon from 36.331 RRC spec
-typedef struct {
-  ///see TS 36.213 (16.2). \vr{[-60..50]}\n Provides the downlink reference-signal EPRE. The actual value in dBm.
-  int8_t nrs_Power;
-} NPDSCH_CONFIG_COMMON;
-
-typedef struct{
-  /// The base sequence of DMRS sequence in a cell for 3 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 12. Value 12 is not used.
-  uint8_t threeTone_BaseSequence;
-  /// Define 3 cyclic shifts for the 3-tone case, see TS 36.211 [21, 10.1.4.1.2].
-  uint8_t threeTone_CyclicShift;
-  /// The base sequence of DMRS sequence in a cell for 6 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 14. Value 14 is not used.
-  uint8_t sixTone_BaseSequence;
-  /// Define 4 cyclic shifts for the 6-tone case, see TS 36.211 [21, 10.1.4.1.2].
-  uint8_t sixTone_CyclicShift;
-  /// The base sequence of DMRS sequence in a cell for 12 tones transmission; see TS 36.211 [21, 10.1.4.1.2]. If absent, it is given by NB-IoT CellID mod 30. Value 30 is not used.
-  uint8_t twelveTone_BaseSequence;
-
-}DMRS_CONFIG_t;
-
-/// UL-ReferenceSignalsNPUSCH from 36.331 RRC spec
-typedef struct {
-  /// Parameter: Group-hopping-enabled, see TS 36.211 (5.5.1.3). \vr{[0..1]}
-  uint8_t groupHoppingEnabled;
-  /// , see TS 36.211 (5.5.1.3). \vr{[0..29]}
-  uint8_t groupAssignmentNPUSCH;
-} UL_REFERENCE_SIGNALS_NPUSCH_t;
-
-
-/// PUSCH-ConfigCommon from 36.331 RRC spec.
-typedef struct {
-  /// Number of repetitions for ACK/NACK HARQ response to NPDSCH containing Msg4 per NPRACH resource, see TS 36.213 [23, 16.4.2].
-  uint8_t ack_NACK_NumRepetitions_Msg4[3];
-  /// SRS SubframeConfiguration. See TS 36.211 [21, table 5.5.3.3-1]. Value sc0 corresponds to value 0, sc1 to value 1 and so on.
-  uint8_t srs_SubframeConfig;
-  /// Parameter: \f$N^{HO}_{RB}\f$, see TS 36.211 (5.3.4). \vr{[0..98]}
-  DMRS_CONFIG_t dmrs_Config;
-  /// Ref signals configuration
-  UL_REFERENCE_SIGNALS_NPUSCH_t ul_ReferenceSignalsNPUSCH;
-} NPUSCH_CONFIG_COMMON;
-
-
-typedef struct{
-  /// See TS 36.213 [23, 16.2.1.1], unit dBm.
-  uint8_t p0_NominalNPUSCH;
-  /// See TS 36.213 [23, 16.2.1.1] where al0 corresponds to 0, al04 corresponds to value 0.4, al05 to 0.5, al06 to 0.6, al07 to 0.7, al08 to 0.8, al09 to 0.9 and al1 corresponds to 1. 
-  uint8_t alpha;
-  /// See TS 36.213 [23, 16.2.1.1]. Actual value = IE value * 2 [dB].
-  uint8_t deltaPreambleMsg3;
-}UplinkPowerControlCommon_NB;
-
-
-/* DL-GapConfig-NB-r13 */
-typedef struct {
-	uint8_t	 dl_GapThreshold;
-	uint8_t	 dl_GapPeriodicity;
-	uint8_t	 dl_GapDurationCoeff;
-} DL_GapConfig_NB;
-
-typedef struct {
-  /// Cell ID
-  uint16_t Nid_cell;
-  /// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
-  lte_prefix_type_t Ncp;
-  /// Cyclic Prefix for UL (0=Normal CP, 1=Extended CP)
-  lte_prefix_type_t Ncp_UL;
-  /// shift of pilot position in one RB
-  uint8_t nushift;
-  /// indicates if node is a UE (NODE=2) or eNB (PRIMARY_CH=0).
-  uint8_t node_id;
-  /// Frequency index of CBMIMO1 card
-  uint8_t freq_idx;
-  /// RX Frequency for ExpressMIMO/LIME
-  uint32_t carrier_freq[4];
-  /// TX Frequency for ExpressMIMO/LIME
-  uint32_t carrier_freqtx[4];
-  /// RX gain for ExpressMIMO/LIME
-  uint32_t rxgain[4];
-  /// TX gain for ExpressMIMO/LIME
-  uint32_t txgain[4];
-  /// RF mode for ExpressMIMO/LIME
-  uint32_t rfmode[4];
-  /// RF RX DC Calibration for ExpressMIMO/LIME
-  uint32_t rxdc[4];
-  /// RF TX DC Calibration for ExpressMIMO/LIME
-  uint32_t rflocal[4];
-  /// RF VCO calibration for ExpressMIMO/LIME
-  uint32_t rfvcolocal[4];
-  /// Turns on second TX of CBMIMO1 card
-  uint8_t dual_tx;
-  /// flag to indicate SISO transmission
-  uint8_t mode1_flag;
-  /// Indicator that 20 MHz channel uses 3/4 sampling frequency
-  //uint8_t threequarter_fs;
-  /// Size of FFT
-  uint16_t ofdm_symbol_size;
-  /// Number of prefix samples in all but first symbol of slot
-  uint16_t nb_prefix_samples;
-  /// Number of prefix samples in first symbol of slot
-  uint16_t nb_prefix_samples0;
-  /// Carrier offset in FFT buffer for first RE in PRB0
-  uint16_t first_carrier_offset;
-  /// Number of samples in a subframe
-  uint32_t samples_per_tti;
-  /// Number of OFDM/SC-FDMA symbols in one subframe (to be modified to account for potential different in UL/DL)
-  uint16_t symbols_per_tti;
-  /// Number of Physical transmit antennas in node
-  uint8_t nb_antennas_tx;
-  /// Number of Receive antennas in node
-  uint8_t nb_antennas_rx;
-  /// Number of common transmit antenna ports in eNodeB (1 or 2)
-  uint8_t nb_antenna_ports_eNB;
-  /// NPRACH Config Common (from 36-331 RRC spec)
-  NPRACH_CONFIG_COMMON nprach_config_common;
-  /// NPDSCH Config Common (from 36-331 RRC spec)
-  NPDSCH_CONFIG_COMMON npdsch_config_common;
-  /// PUSCH Config Common (from 36-331 RRC spec)
-  NPUSCH_CONFIG_COMMON npusch_config_common;
-  /// UL Power Control (from 36-331 RRC spec)
-  UplinkPowerControlCommon_NB ul_power_control_config_common;
-  /// DL Gap
-  DL_GapConfig_NB DL_gap_config;
-  /// Size of SI windows used for repetition of one SI message (in frames)
-  uint8_t SIwindowsize;
-  /// Period of SI windows used for repetition of one SI message (in frames)
-  uint16_t SIPeriod;
-  int                 eutra_band;
-  uint32_t            dl_CarrierFreq;
-  uint32_t            ul_CarrierFreq;
-  uint8_t             CE;// CE level to determine the NPRACH Configuration
-
-} NB_DL_FRAME_PARMS;
-
-#define NPBCH_A 34 
-
-typedef struct {
-  uint8_t npbch_d[96+(3*(16+NPBCH_A))];
-  uint8_t npbch_w[3*3*(16+NPBCH_A)];
-  uint8_t npbch_e[1600];
-} NB_IoT_eNB_NPBCH;
-
-
-#endif
-
diff --git a/openair1/PHY/impl_defs_top_NB_IoT.h b/openair1/PHY/impl_defs_top_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..e512ec02155c8e7780856ab6dd677d638043e1f0
--- /dev/null
+++ b/openair1/PHY/impl_defs_top_NB_IoT.h
@@ -0,0 +1,541 @@
+/*
+ * 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.0  (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/impl_defs_top.h
+* \brief More defines and structure definitions
+* \author R. Knopp, F. Kaltenberger
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
+* \note
+* \warning
+*/
+
+#ifndef __PHY_IMPLEMENTATION_DEFS_NB_IOT_H__
+#define __PHY_IMPLEMENTATION_DEFS_NB_IOT_H__
+
+
+#include "openairinterface5g_limits.h"
+/** @defgroup _ref_implementation_ OpenAirInterface LTE Implementation
+ * @{
+
+ * @defgroup _PHY_RF_INTERFACE_ PHY - RF Interface
+ * @ingroup _PHY_RF_INTERFACE_
+ * @{
+ * @defgroup _GENERIC_PHY_RF_INTERFACE_ Generic PHY - RF Interface
+ * @defgroup _USRP_PHY_RF_INTERFACE_    PHY - USRP RF Interface
+ * @defgroup _BLADERF_PHY_RF_INTERFACE_    PHY - BLADERF RF Interface
+ * @defgroup _LMSSDR_PHY_RF_INTERFACE_    PHY - LMSSDR RF Interface
+ * @}
+ *
+ * @ingroup _ref_implementation_
+ * @{
+ * This module is responsible for defining the generic interface between PHY and RF Target
+ * @}
+ 
+ * @defgroup _openair1_ openair1 Reference Implementation 
+ * @ingroup _ref_implementation_
+ * @{
+
+
+ * @defgroup _physical_layer_ref_implementation_ Physical Layer Reference Implementation
+ * @ingroup _openair1_
+ * @{
+
+
+ * @defgroup _PHY_STRUCTURES_ Basic Structures and Memory Initialization
+ * @ingroup _physical_layer_ref_implementation_
+ * @{
+ * This module is responsible for defining and initializing the PHY variables during static configuration of OpenAirInterface.
+ * @}
+
+ * @defgroup _PHY_DSP_TOOLS_ DSP Tools
+ * @ingroup _physical_layer_ref_implementation_
+ * @{
+ * This module is responsible for basic signal processing related to inner-MODEM processing.
+ * @}
+
+ * @defgroup _PHY_MODULATION_ Modulation and Demodulation
+ * @ingroup _physical_layer_ref_implementation_
+ * @{
+ * This module is responsible for procedures related to OFDMA modulation and demodulation.
+ * @}
+
+ * @defgroup _PHY_PARAMETER_ESTIMATION_BLOCKS_ Parameter Estimation
+ * @ingroup _physical_layer_ref_implementation_
+ * @{
+ * This module is responsible for procedures related to OFDMA frequency-domain channel estimation for LTE Downlink Channels.
+ * @}
+
+ * @defgroup _PHY_CODING_BLOCKS_ Channel Coding/Decoding Functions
+ * @ingroup _physical_layer_ref_implementation_
+ * @{
+ * This module is responsible for procedures related to channel coding/decoding, rate-matching, segementation and interleaving.
+ * @}
+
+ * @defgroup _PHY_TRANSPORT_ Transport/Physical Channel Processing
+ * @ingroup _physical_layer_ref_implementation_
+ * @{
+ * This module is responsible for defining and processing the PHY procedures (TX/RX) related to transport and physical channels.
+ * @}
+
+ * @defgroup _PHY_PROCEDURES_ Physical Layer Procedures
+ * @ingroup _physical_layer_ref_implementation_
+ * @{
+ * This module is responsible for defining and processing the PHY procedures (TX/RX) related to transport and physical channels.
+ * @}
+
+ * @}
+ * @}
+ * @}
+ */
+
+//#include "types.h"
+
+/*
+
+
+#define NUMBER_OF_OFDM_CARRIERS (frame_parms->ofdm_symbol_size)
+#define NUMBER_OF_SYMBOLS_PER_FRAME (frame_parms->symbols_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)
+#define NUMBER_OF_USEFUL_CARRIERS (12*frame_parms->N_RB_DL)
+#define NUMBER_OF_ZERO_CARRIERS (NUMBER_OF_OFDM_CARRIERS-NUMBER_OF_USEFUL_CARRIERS)
+#define NUMBER_OF_USEFUL_CARRIERS_BYTES (NUMBER_OF_USEFUL_CARRIERS>>2)
+#define HALF_NUMBER_OF_USEFUL_CARRIERS (NUMBER_OF_USEFUL_CARRIERS>>1)
+#define HALF_NUMBER_OF_USEFUL_CARRIERS_BYTES (HALF_NUMBER_OF_USEFUL_CARRIERS>>2)
+#define FIRST_CARRIER_OFFSET (HALF_NUMBER_OF_USEFUL_CARRIERS+NUMBER_OF_ZERO_CARRIERS)
+#define NUMBER_OF_OFDM_SYMBOLS_PER_SLOT (NUMBER_OF_SYMBOLS_PER_FRAME/LTE_SLOTS_PER_FRAME)
+
+#ifdef EMOS
+#define EMOS_SCH_INDEX 1
+#endif //EMOS
+
+#define EXTENSION_TYPE (PHY_config->PHY_framing.Extension_type)
+
+#define NUMBER_OF_OFDM_CARRIERS_BYTES   NUMBER_OF_OFDM_CARRIERS*4
+//#define NUMBER_OF_USEFUL_CARRIERS_BYTES NUMBER_OF_USEFUL_CARRIERS*4
+#define HALF_NUMBER_OF_USER_CARRIERS_BYTES NUMBER_OF_USEFUL_CARRIERS/2
+
+#define CYCLIC_PREFIX_LENGTH (frame_parms->nb_prefix_samples)
+#define CYCLIC_PREFIX_LENGTH_SAMPLES (CYCLIC_PREFIX_LENGTH*2)
+#define CYCLIC_PREFIX_LENGTH_BYTES (CYCLIC_PREFIX_LENGTH*4)
+#define CYCLIC_PREFIX_LENGTH0 (frame_parms->nb_prefix_samples0)
+#define CYCLIC_PREFIX_LENGTH_SAMPLES0 (CYCLIC_PREFIX_LENGTH0*2)
+#define CYCLIC_PREFIX_LENGTH_BYTES0 (CYCLIC_PREFIX_LENGTH0*4)
+
+#define OFDM_SYMBOL_SIZE_SAMPLES ((NUMBER_OF_OFDM_CARRIERS + CYCLIC_PREFIX_LENGTH)*2)   // 16-bit units (i.e. real samples)
+#define OFDM_SYMBOL_SIZE_SAMPLES0 ((NUMBER_OF_OFDM_CARRIERS + CYCLIC_PREFIX_LENGTH0)*2)   // 16-bit units (i.e. real samples)
+#define OFDM_SYMBOL_SIZE_SAMPLES_MAX 4096   // 16-bit units (i.e. real samples)
+#define OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES (OFDM_SYMBOL_SIZE_SAMPLES/2)                   // 32-bit units (i.e. complex samples)
+#define OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES0 (OFDM_SYMBOL_SIZE_SAMPLES0/2)                   // 32-bit units (i.e. complex samples)
+#define OFDM_SYMBOL_SIZE_SAMPLES_NO_PREFIX ((NUMBER_OF_OFDM_CARRIERS)*2)
+#define OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX (OFDM_SYMBOL_SIZE_SAMPLES_NO_PREFIX/2)
+#define OFDM_SYMBOL_SIZE_BYTES (OFDM_SYMBOL_SIZE_SAMPLES*2)
+#define OFDM_SYMBOL_SIZE_BYTES0 (OFDM_SYMBOL_SIZE_SAMPLES0*2)
+#define OFDM_SYMBOL_SIZE_BYTES_NO_PREFIX (OFDM_SYMBOL_SIZE_SAMPLES_NO_PREFIX*2)
+
+#define SLOT_LENGTH_BYTES (frame_parms->samples_per_tti<<1) // 4 bytes * samples_per_tti/2
+#define SLOT_LENGTH_BYTES_NO_PREFIX (OFDM_SYMBOL_SIZE_BYTES_NO_PREFIX * NUMBER_OF_OFDM_SYMBOLS_PER_SLOT)
+
+#define FRAME_LENGTH_COMPLEX_SAMPLES (frame_parms->samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME)
+#define FRAME_LENGTH_SAMPLES (FRAME_LENGTH_COMPLEX_SAMPLES*2)
+#define FRAME_LENGTH_SAMPLES_NO_PREFIX (NUMBER_OF_SYMBOLS_PER_FRAME*OFDM_SYMBOL_SIZE_SAMPLES_NO_PREFIX)
+#define FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX (FRAME_LENGTH_SAMPLES_NO_PREFIX/2)
+
+#define NUMBER_OF_CARRIERS_PER_GROUP (NUMBER_OF_USEFUL_CARRIERS/NUMBER_OF_FREQUENCY_GROUPS)
+
+#define RX_PRECISION (16)
+#define LOG2_RX_PRECISION (4)
+#define RX_OUTPUT_SHIFT (4)
+
+
+#define SAMPLE_SIZE_BYTES    2                                           // 2 bytes/real sample
+
+#define FRAME_LENGTH_BYTES   (FRAME_LENGTH_SAMPLES * SAMPLE_SIZE_BYTES)  // frame size in bytes
+#define FRAME_LENGTH_BYTES_NO_PREFIX   (FRAME_LENGTH_SAMPLES_NO_PREFIX * SAMPLE_SIZE_BYTES)  // frame size in bytes
+
+
+#define FFT_SCALE_FACTOR     8                                           // Internal Scaling for FFT
+#define DMA_BLKS_PER_SLOT    (SLOT_LENGTH_BYTES/2048)                    // Number of DMA blocks per slot
+#define SLOT_TIME_NS         (SLOT_LENGTH_SAMPLES*(1e3)/7.68)            // slot time in ns
+
+#define NB_ANTENNA_PORTS_ENB  6                                         // total number of eNB antenna ports
+
+#ifdef EXMIMO
+#define TARGET_RX_POWER 55    // Target digital power for the AGC
+#define TARGET_RX_POWER_MAX 55    // Maximum digital power, such that signal does not saturate (value found by simulation)
+#define TARGET_RX_POWER_MIN 50    // Minimum digital power, anything below will be discarded (value found by simulation)
+#else
+#define TARGET_RX_POWER 50    // Target digital power for the AGC
+#define TARGET_RX_POWER_MAX 65    // Maximum digital power, such that signal does not saturate (value found by simulation)
+#define TARGET_RX_POWER_MIN 35    // Minimum digital power, anything below will be discarded (value found by simulation)
+#endif
+
+//the min and max gains have to match the calibrated gain table
+//#define MAX_RF_GAIN 160
+//#define MIN_RF_GAIN 96
+#define MAX_RF_GAIN 200
+#define MIN_RF_GAIN 80
+
+#define PHY_SYNCH_OFFSET ((OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES)-1)  // OFFSET of BEACON SYNCH
+#define PHY_SYNCH_MIN_POWER 1000
+#define PHY_SYNCH_THRESHOLD 100
+
+*/
+
+#define ONE_OVER_SQRT2_Q15_NB_IoT 23170
+
+/*
+#define ONE_OVER_2_Q15 16384
+
+// QAM amplitude definitions
+
+/// First Amplitude for QAM16 (\f$ 2^{15} \times 2/\sqrt{10}\f$)
+#define QAM16_n1 20724
+/// Second Amplitude for QAM16 (\f$ 2^{15} \times 1/\sqrt{10}\f$)
+#define QAM16_n2 10362
+
+///First Amplitude for QAM64 (\f$ 2^{15} \times 4/\sqrt{42}\f$)
+#define QAM64_n1 20225
+///Second Amplitude for QAM64 (\f$ 2^{15} \times 2/\sqrt{42}\f$)
+#define QAM64_n2 10112
+///Third Amplitude for QAM64 (\f$ 2^{15} \times 1/\sqrt{42}\f$)
+#define QAM64_n3 5056
+
+/// First Amplitude for QAM16 for TM5 (\f$ 2^{15} \times 2/sqrt(20)\f$)
+#define QAM16_TM5_n1 14654
+/// Second Amplitude for QAM16 for TM5 Receiver (\f$ 2^{15} \times 1/\sqrt{20}\f$)
+#define QAM16_TM5_n2 7327
+
+///First Amplitude for QAM64 (\f$ 2^{15} \times 4/\sqrt{84}\f$)
+#define QAM64_TM5_n1 14301
+///Second Amplitude for QAM64 (\f$ 2^{15} \times 2/\sqrt{84}\f$)
+#define QAM64_TM5_n2 7150
+///Third Amplitude for QAM64 for TM5 Receiver (\f$ 2^{15} \times 1/\sqrt{84}\f$)
+#define QAM64_TM5_n3 3575
+
+
+#ifdef BIT8_RXMUX
+#define PERROR_SHIFT 0
+#else
+#define PERROR_SHIFT 10
+#endif
+
+#define BIT8_TX_SHIFT 2
+#define BIT8_TX_SHIFT_DB 12
+
+//#define CHBCH_RSSI_MIN -75
+
+#ifdef BIT8_TX
+#define AMP 128
+#else
+#define AMP 512//1024 //4096
+#endif
+
+#define AMP_OVER_SQRT2 ((AMP*ONE_OVER_SQRT2_Q15)>>15)
+#define AMP_OVER_2 (AMP>>1)
+
+/// Threshold for PUCCH Format 1 detection
+#define PUCCH1_THRES 0
+/// Threshold for PUCCH Format 1a/1b detection
+#define PUCCH1a_THRES 4
+
+/// Data structure for transmission.
+typedef struct {
+  /// RAW TX sample buffer
+  char *TX_DMA_BUFFER[2];
+} TX_VARS ;
+
+/// Data structure for reception.
+typedef struct {
+  /// RAW TX sample buffer
+  char *TX_DMA_BUFFER[2];
+  /// RAW RX sample buffer
+  int *RX_DMA_BUFFER[2];
+} TX_RX_VARS;
+
+//! \brief Extension Type /
+typedef enum {
+  CYCLIC_PREFIX,
+  CYCLIC_SUFFIX,
+  ZEROS,
+  NONE
+} Extension_t;
+	
+/// Measurement Variables
+*/
+#define NUMBER_OF_SUBBANDS_MAX_NB_IoT 13
+/*
+#define NUMBER_OF_HARQ_PID_MAX 8
+
+#define MAX_FRAME_NUMBER 0x400
+#include "openairinterface5g_limits.h"
+
+#define NUMBER_OF_RN_MAX 3
+typedef enum {no_relay=1,unicast_relay_type1,unicast_relay_type2, multicast_relay} relaying_type_t;
+
+typedef struct {
+  //unsigned int   rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];     //! estimated received signal power (linear)
+  //unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];  //! estimated received signal power (dB)
+  //unsigned short rx_avg_power_dB[NUMBER_OF_CONNECTED_eNB_MAX];              //! estimated avg received signal power (dB)
+
+  // RRC measurements
+  uint32_t rssi;
+  int n_adj_cells;
+  unsigned int adj_cell_id[6];
+  uint32_t rsrq[7];
+  uint32_t rsrp[7];
+  float rsrp_filtered[7]; // after layer 3 filtering
+  float rsrq_filtered[7];
+  // common measurements
+  //! estimated noise power (linear)
+  unsigned int   n0_power[NB_ANTENNAS_RX];
+  //! estimated noise power (dB)
+  unsigned short n0_power_dB[NB_ANTENNAS_RX];
+  //! total estimated noise power (linear)
+  unsigned int   n0_power_tot;
+  //! total estimated noise power (dB)
+  unsigned short n0_power_tot_dB;
+  //! average estimated noise power (linear)
+  unsigned int   n0_power_avg;
+  //! average estimated noise power (dB)
+  unsigned short n0_power_avg_dB;
+  //! total estimated noise power (dBm)
+  short n0_power_tot_dBm;
+
+  // UE measurements
+  //! estimated received spatial signal power (linear)
+  int            rx_spatial_power[NUMBER_OF_CONNECTED_eNB_MAX][2][2];
+  //! estimated received spatial signal power (dB)
+  unsigned short rx_spatial_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][2][2];
+
+  /// estimated received signal power (sum over all TX antennas)
+  //int            wideband_cqi[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  int            rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  /// estimated received signal power (sum over all TX antennas)
+  //int            wideband_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+
+  /// estimated received signal power (sum over all TX/RX antennas)
+  int            rx_power_tot[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW
+  /// estimated received signal power (sum over all TX/RX antennas)
+  unsigned short rx_power_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW
+
+  //! estimated received signal power (sum of all TX/RX antennas, time average)
+  int            rx_power_avg[NUMBER_OF_CONNECTED_eNB_MAX];
+  //! estimated received signal power (sum of all TX/RX antennas, time average, in dB)
+  unsigned short rx_power_avg_dB[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// SINR (sum of all TX/RX antennas, in dB)
+  int            wideband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// SINR (sum of all TX/RX antennas, time average, in dB)
+  int            wideband_cqi_avg[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  //! estimated rssi (dBm)
+  short          rx_rssi_dBm[NUMBER_OF_CONNECTED_eNB_MAX];
+  //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation)
+  int            rx_correlation[NUMBER_OF_CONNECTED_eNB_MAX][2];
+  //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation)
+  int            rx_correlation_dB[NUMBER_OF_CONNECTED_eNB_MAX][2];
+
+  /// Wideband CQI (sum of all RX antennas, in dB, for precoded transmission modes (3,4,5,6), up to 4 spatial streams)
+  int            precoded_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX+1][4];
+  /// Subband CQI per RX antenna (= SINR)
+  int            subband_cqi[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX];
+  /// Total Subband CQI  (= SINR)
+  int            subband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX];
+  /// Subband CQI in dB (= SINR dB)
+  int            subband_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX];
+  /// Total Subband CQI
+  int            subband_cqi_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX];
+  /// Wideband PMI for each RX antenna
+  int            wideband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  /// Wideband PMI for each RX antenna
+  int            wideband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  ///Subband PMI for each RX antenna
+  int            subband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX];
+  ///Subband PMI for each RX antenna
+  int            subband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX][NB_ANTENNAS_RX];
+  /// chosen RX antennas (1=Rx antenna 1, 2=Rx antenna 2, 3=both Rx antennas)
+  unsigned char           selected_rx_antennas[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX];
+  /// Wideband Rank indication
+  unsigned char  rank[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// Number of RX Antennas
+  unsigned char  nb_antennas_rx;
+  /// DLSCH error counter
+  // short          dlsch_errors;
+
+} PHY_MEASUREMENTS;
+*/
+typedef enum {no_relay_NB_IoT=1,unicast_relay_type1_NB_IoT,unicast_relay_type2_NB_IoT, multicast_relay_NB_IoT} relaying_type_t_NB_IoT;
+typedef struct {
+  //unsigned int   rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];     //! estimated received signal power (linear)
+  //unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];  //! estimated received signal power (dB)
+  //unsigned short rx_avg_power_dB[NUMBER_OF_CONNECTED_eNB_MAX];              //! estimated avg received signal power (dB)
+
+  // RRC measurements
+  uint32_t rssi;
+  int n_adj_cells;
+  unsigned int adj_cell_id[6];
+  uint32_t rsrq[7];
+  uint32_t rsrp[7];
+  float rsrp_filtered[7]; // after layer 3 filtering
+  float rsrq_filtered[7];
+  // common measurements
+  //! estimated noise power (linear)
+  unsigned int   n0_power[NB_ANTENNAS_RX];
+  //! estimated noise power (dB)
+  unsigned short n0_power_dB[NB_ANTENNAS_RX];
+  //! total estimated noise power (linear)
+  unsigned int   n0_power_tot;
+  //! total estimated noise power (dB)
+  unsigned short n0_power_tot_dB;
+  //! average estimated noise power (linear)
+  unsigned int   n0_power_avg;
+  //! average estimated noise power (dB)
+  unsigned short n0_power_avg_dB;
+  //! total estimated noise power (dBm)
+  short n0_power_tot_dBm;
+
+  // UE measurements
+  //! estimated received spatial signal power (linear)
+  int            rx_spatial_power[NUMBER_OF_CONNECTED_eNB_MAX][2][2];
+  //! estimated received spatial signal power (dB)
+  unsigned short rx_spatial_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][2][2];
+
+  /// estimated received signal power (sum over all TX antennas)
+  //int            wideband_cqi[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  int            rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  /// estimated received signal power (sum over all TX antennas)
+  //int            wideband_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+
+  /// estimated received signal power (sum over all TX/RX antennas)
+  int            rx_power_tot[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW
+  /// estimated received signal power (sum over all TX/RX antennas)
+  unsigned short rx_power_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX]; //NEW
+
+  //! estimated received signal power (sum of all TX/RX antennas, time average)
+  int            rx_power_avg[NUMBER_OF_CONNECTED_eNB_MAX];
+  //! estimated received signal power (sum of all TX/RX antennas, time average, in dB)
+  unsigned short rx_power_avg_dB[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  /// SINR (sum of all TX/RX antennas, in dB)
+  int            wideband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// SINR (sum of all TX/RX antennas, time average, in dB)
+  int            wideband_cqi_avg[NUMBER_OF_CONNECTED_eNB_MAX];
+
+  //! estimated rssi (dBm)
+  short          rx_rssi_dBm[NUMBER_OF_CONNECTED_eNB_MAX];
+  //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation)
+  int            rx_correlation[NUMBER_OF_CONNECTED_eNB_MAX][2];
+  //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation)
+  int            rx_correlation_dB[NUMBER_OF_CONNECTED_eNB_MAX][2];
+
+  /// Wideband CQI (sum of all RX antennas, in dB, for precoded transmission modes (3,4,5,6), up to 4 spatial streams)
+  int            precoded_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX+1][4];
+  /// Subband CQI per RX antenna (= SINR)
+  int            subband_cqi[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX_NB_IoT];
+  /// Total Subband CQI  (= SINR)
+  int            subband_cqi_tot[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX_NB_IoT];
+  /// Subband CQI in dB (= SINR dB)
+  int            subband_cqi_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX][NUMBER_OF_SUBBANDS_MAX_NB_IoT];
+  /// Total Subband CQI
+  int            subband_cqi_tot_dB[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX_NB_IoT];
+  /// Wideband PMI for each RX antenna
+  int            wideband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  /// Wideband PMI for each RX antenna
+  int            wideband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];
+  ///Subband PMI for each RX antenna
+  int            subband_pmi_re[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX_NB_IoT][NB_ANTENNAS_RX];
+  ///Subband PMI for each RX antenna
+  int            subband_pmi_im[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX_NB_IoT][NB_ANTENNAS_RX];
+  /// chosen RX antennas (1=Rx antenna 1, 2=Rx antenna 2, 3=both Rx antennas)
+  unsigned char           selected_rx_antennas[NUMBER_OF_CONNECTED_eNB_MAX][NUMBER_OF_SUBBANDS_MAX_NB_IoT];
+  /// Wideband Rank indication
+  unsigned char  rank[NUMBER_OF_CONNECTED_eNB_MAX];
+  /// Number of RX Antennas
+  unsigned char  nb_antennas_rx;
+  /// DLSCH error counter
+  // short          dlsch_errors;
+
+} PHY_MEASUREMENTS_NB_IoT;
+
+
+typedef struct {
+  //unsigned int   rx_power[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];     //! estimated received signal power (linear)
+  //unsigned short rx_power_dB[NUMBER_OF_CONNECTED_eNB_MAX][NB_ANTENNAS_RX];  //! estimated received signal power (dB)
+  //unsigned short rx_avg_power_dB[NUMBER_OF_CONNECTED_eNB_MAX];              //! estimated avg received signal power (dB)
+
+  // common measurements
+  //! estimated noise power (linear)
+  unsigned int   n0_power[NB_ANTENNAS_RX];
+  //! estimated noise power (dB)
+  unsigned short n0_power_dB[NB_ANTENNAS_RX];
+  //! total estimated noise power (linear)
+  unsigned int   n0_power_tot;
+  //! estimated avg noise power (dB)
+  unsigned short n0_power_tot_dB;
+  //! estimated avg noise power (dB)
+  short n0_power_tot_dBm;
+  //! estimated avg noise power per RB per RX ant (lin)
+  unsigned short n0_subband_power[NB_ANTENNAS_RX][100];
+  //! estimated avg noise power per RB per RX ant (dB)
+  unsigned short n0_subband_power_dB[NB_ANTENNAS_RX][100];
+  //! estimated avg noise power per RB (dB)
+  short n0_subband_power_tot_dB[100];
+  //! estimated avg noise power per RB (dBm)
+  short n0_subband_power_tot_dBm[100];
+  // eNB measurements (per user)
+  //! estimated received spatial signal power (linear)
+  unsigned int   rx_spatial_power[NUMBER_OF_UE_MAX_NB_IoT][2][2];
+  //! estimated received spatial signal power (dB)
+  unsigned short rx_spatial_power_dB[NUMBER_OF_UE_MAX_NB_IoT][2][2];
+  //! estimated rssi (dBm)
+  short          rx_rssi_dBm[NUMBER_OF_UE_MAX_NB_IoT];
+  //! estimated correlation (wideband linear) between spatial channels (computed in dlsch_demodulation)
+  int            rx_correlation[NUMBER_OF_UE_MAX_NB_IoT][2];
+  //! estimated correlation (wideband dB) between spatial channels (computed in dlsch_demodulation)
+  int            rx_correlation_dB[NUMBER_OF_UE_MAX_NB_IoT][2];
+
+  /// Wideband CQI (= SINR)
+  int            wideband_cqi[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX];
+  /// Wideband CQI in dB (= SINR dB)
+  int            wideband_cqi_dB[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX];
+  /// Wideband CQI (sum of all RX antennas, in dB)
+  char           wideband_cqi_tot[NUMBER_OF_UE_MAX_NB_IoT];
+  /// Subband CQI per RX antenna and RB (= SINR)
+  int            subband_cqi[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX][100];
+  /// Total Subband CQI and RB (= SINR)
+  int            subband_cqi_tot[NUMBER_OF_UE_MAX_NB_IoT][100];
+  /// Subband CQI in dB and RB (= SINR dB)
+  int            subband_cqi_dB[NUMBER_OF_UE_MAX_NB_IoT][NB_ANTENNAS_RX][100];
+  /// Total Subband CQI and RB
+  int            subband_cqi_tot_dB[NUMBER_OF_UE_MAX_NB_IoT][100];
+
+} PHY_MEASUREMENTS_eNB_NB_IoT;
+/*
+#define MCS_COUNT 28
+#define MCS_TABLE_LENGTH_MAX 64
+*/
+#endif //__PHY_IMPLEMENTATION_DEFS_H__ 
+/**@} 
+*/
diff --git a/openair1/PHY/types_NB_IoT.h b/openair1/PHY/types_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..e8a6ea501e7170a031143840bed37a85552a09ad
--- /dev/null
+++ b/openair1/PHY/types_NB_IoT.h
@@ -0,0 +1,32 @@
+/*
+ * 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.0  (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 __openair_TYPES_NB_IOT_H__
+#define __openair_TYPES_NB_IOT_H__
+
+#ifdef USER_MODE
+#include <stdint.h>
+#else
+#include <linux/types.h>
+#endif
+
+
+#endif /*__openair_TYPES_NB_IOT_H__ */
diff --git a/openair1/PHY/vars.h b/openair1/PHY/vars.h
index bb570f0ecd7b9732198915d34063d29990f34afc..c4b81ffaac50f9eae56e30d6cf9671201c6c86f0 100644
--- a/openair1/PHY/vars.h
+++ b/openair1/PHY/vars.h
@@ -150,4 +150,7 @@ int16_t unscrambling_lut[65536*16] __attribute__((aligned(32)));
 uint8_t scrambling_lut[65536*16] __attribute__((aligned(32)));
 
 
+
+
+
 #endif /*__PHY_VARS_H__ */
diff --git a/openair1/PHY/vars_NB_IoT.h b/openair1/PHY/vars_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..7f076f9a0029f87ef20d0dec55b2244eb6efc040
--- /dev/null
+++ b/openair1/PHY/vars_NB_IoT.h
@@ -0,0 +1,162 @@
+/*
+ * 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.0  (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_VARS_NB_IOT_H__
+#define __PHY_VARS_NB_IOT_H__
+
+#include "PHY/types_NB_IoT.h"
+#include "PHY/defs_NB_IoT.h"
+
+/*
+#ifndef USER_MODE
+unsigned int RX_DMA_BUFFER[4][NB_ANTENNAS_RX];
+unsigned int TX_DMA_BUFFER[4][NB_ANTENNAS_TX];
+unsigned int DAQ_MBOX;
+#endif
+char* namepointer_chMag ;
+char fmageren_name2[512];
+char* namepointer_log2;
+//PHY_CONFIG *PHY_config;
+*/
+
+/*
+#include "PHY/LTE_REFSIG/primary_synch.h"
+int16_t *primary_synch0_time;
+int16_t *primary_synch1_time;
+int16_t *primary_synch2_time;
+*/
+
+//#include "PHY/CODING/vars.h"
+
+//PHY_VARS *PHY_vars;
+#ifndef OCP_FRAMEWORK
+PHY_VARS_UE_NB_IoT ***PHY_vars_UE_NB_IoT_g;
+PHY_VARS_eNB_NB_IoT ***PHY_vars_eNB_NB_IoT_g;
+PHY_VARS_RN_NB_IoT **PHY_vars_RN_NB_IoT_g;
+NB_IoT_DL_FRAME_PARMS *lte_frame_parms_g;
+#else
+PHY_VARS_UE_NB_IoT * PHY_vars_UE_NB_IoT_g[MAX_UE][MAX_NUM_CCs]={NULL};
+PHY_vars_eNB_NB_IoT * PHY_vars_eNB_NB_IoT_g[MAX_eNB_NB_IoT][MAX_NUM_CCs]={NULL};
+#endif
+
+///*
+//unsigned short rev[2048],rev_times4[8192],rev_half[1024];
+//unsigned short rev256[256],rev512[512],rev1024[1024],rev4096[4096],rev2048[2048],rev8192[8192];
+//*/
+/*
+char mode_string[4][20] = {"NOT SYNCHED","PRACH","RAR","PUSCH"};
+#include "PHY/LTE_TRANSPORT/vars.h"
+
+
+
+#include "SIMULATION/ETH_TRANSPORT/vars.h"
+
+
+#ifndef OPENAIR2
+unsigned char NB_eNB_INST=0;
+unsigned char NB_UE_INST=0;
+unsigned char NB_RN_INST=0;
+unsigned char NB_INST=0;
+#endif
+*/
+
+/*
+unsigned int ULSCH_max_consecutive_errors = 20;
+
+int number_of_cards;
+
+int flag_LA=0;
+int flagMag;
+//extern  channel_desc_t *eNB2UE[NUMBER_OF_eNB_MAX][NUMBER_OF_UE_MAX];
+//extern  double ABS_SINR_eff_BLER_table[MCS_COUNT][9][9];
+//extern  double ABS_beta[MCS_COUNT];odi
+double sinr_bler_map[MCS_COUNT][2][MCS_TABLE_LENGTH_MAX];
+int table_length[MCS_COUNT];
+//double sinr_bler_map_up[MCS_COUNT][2][16];
+
+//for MU-MIMO abstraction using MIESM
+//this 2D arrarays contains SINR, MI and RBIR in rows 1, 2, and 3 respectively
+double MI_map_4qam[3][162];
+double MI_map_16qam[3][197];
+double MI_map_64qam[3][227];
+
+// here the first index is for transmission mode 1, 2, 5 and 6 whereas the second index is for the 16 sinr vaues corresponding to 16 CQIs
+double sinr_to_cqi[4][16]= { {-2.5051, -2.5051, -1.7451, -0.3655, 1.0812, 2.4012, 3.6849, 6.6754, 8.3885, 8.7970, 12.0437, 14.4709, 15.7281,  17.2424,  17.2424, 17.2424},
+  {-2.2360, -2.2360, -1.3919, -0.0218, 1.5319,  2.9574,  4.3234, 6.3387, 8.9879, 9.5096, 12.6609, 14.0116, 16.4984, 18.1572, 18.1572, 18.1572},
+  {-1, -1.0000, -0.4198, -0.0140, 1.0362,  2.3520, 3.5793, 6.1136, 8.4836, 9.0858, 12.4723, 13.9128, 16.2054, 17.7392, 17.7392, 17.7392},
+  { -4.1057, -4.1057, -3.3768, -2.2916, -1.1392, 0.1236, 1.2849, 3.1933, 5.9298, 6.4052, 9.6245, 10.9414, 13.5166, 14.9545, 14.9545, 14.9545}
+};
+
+//int cqi_to_mcs[16]={0, 0, 1, 3, 5, 7, 9, 13, 15, 16, 20, 23, 25, 27, 27, 27};
+int cqi_to_mcs[16]= {0, 0, 1, 2, 4, 6, 8, 11, 13, 16, 18, 20, 23, 25, 27, 28};
+
+//for SNR to MI conversion 7 th order Polynomial coeff
+double q_qam16[8]= {3.21151853033897e-10,5.55435952230651e-09,-2.30760065362117e-07,-6.25587743817859e-06,4.62251036452795e-06,0.00224150813158937,0.0393723140344367,0.245486379182639};
+double q_qpsk[8]= {1.94491167814437e-09,8.40494123817774e-08,4.75527131198034e-07,-2.48946285301621e-05,-0.000347614016158364,0.00209252225437100,0.0742986115462510,0.488297879889425};
+double q_qam64[8]= {2.25934026232206e-11,-1.45992206328306e-10,-3.70861183071900e-08,-1.22206071019319e-06,6.49115500399637e-06,0.00129828997837433,0.0259669554914859,0.166602901214898};
+
+//for MI to SNR conversion 7 th order Polynomial coeff
+double p_qpsk[8]= {5982.42405670359,-21568.1135917693,31293.9987036905,-23394.6795043871,9608.34750585489,-2158.15802349899,267.731968719036,-20.6145324295965};
+double p_qam16[8]= {7862.12690694170,-28510.3207048338,41542.2150287122,-31088.3036957379,12690.1982361016,-2785.66604739984,326.595462489375,-18.9911849872089};
+double p_qam64[8]= {8832.57933013696,-32119.1802555952,46914.2578990397,-35163.8150557183,14343.7419388853,-3126.61025510092,360.954930562237,-18.0358548533343};
+
+// ideal CE MIESM
+
+double beta1_dlsch_MI[6][MCS_COUNT] = { {1.1188, 0.3720, 0.3755, 0.9453, 0.5799, 0.5256, 0.5485, 0.5340, 0.5165, 0.5300, 0.6594, 0.5962, 0.4884, 0.4927, 0.3687, 0.4614, 0.4081, 0.2639,0.2935,0.2520,0.3709,0.2906,0.2612,0.2390}, {0.7138, 0.5533, 0.5533, 0.4828, 0.4998, 0.4843, 0.4942, 0.5323, 0.5142, 0.4756, 0.5792, 0.4167, 0.4445, 0.3942, 0.3789, 0.2756, 0.4456, 0.1650, 0.2254, 0.2353, 0.2097,0.2517,0.3242,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1},  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1},{1.808065416202085, 1.754544945430673,1.902272019362616, 1.790054645392961, 1.563204092967629, 1.585258289348813, 1.579349443720310, 1.570650121437345, 1.545055626608596, 1.362229442426877, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33, 1,1,1,1,1,1,1},{0.7146, 0.4789, 0.5392, 0.5556, 0.4975, 0.4847, 0.4691, 0.5261, 0.5278, 0.4962, 0.4468, 0.4113, 0.4622, 0.4609, 0.3946, 0.3991, 0.3532, 0.2439, 0.1898, 0.2929, 0.2712, 0.3367, 0.3591, 0.2571}};
+double beta2_dlsch_MI[6][MCS_COUNT] = { {1.1293, 0.3707, 0.3722, 0.9310, 0.5808, 0.5265, 0.5404, 0.5279, 0.5210, 0.5226, 0.6438, 0.5827, 0.4804, 0.4830, 0.3638, 0.4506, 0.4107, 0.2547, 0.2797, 0.2413, 0.3351, 0.2750, 0.2568, 0.2273}, {0.7028, 0.5503, 0.5503, 0.4815, 0.5006, 0.4764, 0.4810, 0.5124, 0.4964, 0.4485, 0.5497, 0.3971, 0.4239, 0.3701, 0.3494, 0.2630, 0.4053, 0.1505, 0.2001,0.2024,0.1788,0.2124,0.2668,1}, {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1},  {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1},{1.079518113138858, 1.105622953570353, 1.031337449900606, 1.073342032668810, 1.242636589110353, 1.255054927783647, 1.291463834317768, 1.317048698347491, 1.354485054187984, 0.338534029291017, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33,1, 1,1,1,1,1,1},{0.6980, 0.4694, 0.5379, 0.5483, 0.4982, 0.4737, 0.4611, 0.5051, 0.5020, 0.4672, 0.4357, 0.3957, 0.4389, 0.4344, 0.3645, 0.3661, 0.3301, 0.2179, 0.1730, 0.2536, 0.2389,0.2884,0.2936,0.2226}};
+
+//real CE MIESM
+////////
+double beta1_dlsch_MI[6][MCS_COUNT] = { {1.32955, 0.59522, 0.54024, 0.98698, 0.81305, 0.76976, 0.69258, 0.69713, 0.70546, 0.69111, 0.81904, 0.72664, 0.79491, 0.72562, 0.53980, 0.33134, 0.50550, 0.40602,0.40281,0.47012,0.50510,0.23540,0.32045,1}, {0.59632, 1.08475, 1.02431, 1.07020, 0.90170, 0.97719, 0.95464, 0.92764, 0.86721, 0.85986, 0.64558, 0.80631, 0.82673, 0.82888, 0.87122, 0.77245, 0.29771, 0.43477, 0.55321, 0.61027, 0.56111, 0.57292, 0.39737,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1},  {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1},{1.808065416202085, 1.754544945430673,1.902272019362616, 1.790054645392961, 1.563204092967629, 1.585258289348813, 1.579349443720310, 1.570650121437345, 1.545055626608596, 1.362229442426877, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33, 1,1,1,1,1,1,1},{0.77532, 1.07544, 1.10571, 1.04099, 0.91638, 0.88644, 0.96405, 0.86709, 0.94066, 0.84430, 1.24478, 1.09665, 1.42604, 0.79541, 0.71847, 0.71604, 0.74561, 0.36431, 0.41536, 0.52175, 0.47096, 0.49977, 0.59728,1}};
+double beta2_dlsch_MI[6][MCS_COUNT] = { {1.36875, 0.59304, 0.53870, 0.98239, 0.81637, 0.76847, 0.69842, 0.69885, 0.69967, 0.69826, 0.82660, 0.70559, 0.78404, 0.70670, 0.55393, 0.36893, 0.52225, 0.39752, 0.40494, 0.46239, 0.49247,0.26900,0.34504,1}, {0.43775, 0.78208, 0.72875, 0.77458, 0.64485, 0.69174, 0.66097, 0.63289, 0.59652, 0.61175, 0.44551, 0.56047, 0.57314, 0.57553, 0.58849, 0.52159, 0.21241, 0.30139, 0.37373, 0.32029, 0.37067, 0.36706, 0.27118,1}, {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1},  {1,1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1},{1.079518113138858, 1.105622953570353, 1.031337449900606, 1.073342032668810, 1.242636589110353, 1.255054927783647, 1.291463834317768, 1.317048698347491, 1.354485054187984, 0.338534029291017, 1.85, 1.79, 1.65, 1.54, 1.46, 1.39, 1.33,1, 1,1,1,1,1,1},{0.54448, 0.73731, 0.79165, 0.74407, 0.68042, 0.64906, 0.71349, 0.62109, 0.65815, 0.60940, 0.90549, 0.78708, 1.03176, 0.58431, 0.53379, 0.51224, 0.52767, 0.26848, 0.29642, 0.36879, 0.34148, 0.35279,0.40633,1}};
+////////
+//ideal channel estimation values
+//double beta1_dlsch[6][MCS_COUNT] = { {2.3814, 0.4956, 0.5273, 1.1708, 0.8014, 0.7889, 0.8111, 0.8139, 0.8124, 0.8479, 1.9280, 1.9664, 2.3857, 2.5147, 2.4511, 3.0158, 2.8643, 5.3013, 5.8594, 6.5372, 7.8073, 7.8030, 7.5295, 7.1320}, {0.5146, 0.5549, 0.7405, 0.6913, 0.7349, 0.7000, 0.7539, 0.7955, 0.8074, 0.7760, 1.8150, 1.6561, 1.9280, 2.3563, 2.6699, 2.3086, 3.1601, 4.5316, 5.2870, 6.0983, 6.5635, 7.7024, 9.9592, 6.6173}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1.79358, 1.17908, 2.02600, 1.72040, 1.58618, 1.59039, 1.68111, 1.67062, 1.64911, 1.33274, 4.87800, 3.58797, 3.72338, 5.35700, 2.81752, 1.93472, 2.23259, 1,1,1,1,1,1,1}, {0.4445, 0.5918, 0.7118, 0.7115, 0.7284, 0.7202, 0.7117, 0.8111, 0.8239, 0.7907, 1.8456, 1.8144, 2.3830, 2.6634, 2.6129, 2.8127, 2.7372, 4.9424, 4.8763, 6.8413, 7.1493, 9.4180, 10.1230, 8.9613}};
+//double beta2_dlsch[6][MCS_COUNT] = { {2.3639, 0.4952, 0.5207, 1.1572, 0.8026, 0.7864, 0.7996, 0.8034, 0.8200, 0.8367, 1.8701, 1.9212, 2.2947, 2.4472, 2.4091, 2.9479, 2.8973, 5.0591, 5.5134, 6.1483, 7.2166, 7.5177, 7.5704, 7.2248}, {0.5113, 0.5600, 0.7359, 0.6860, 0.7344, 0.6902, 0.7315, 0.7660, 0.7817, 0.7315, 1.7268, 1.5912, 1.8519, 2.2115, 2.4580, 2.1879, 2.9015, 4.1543, 4.6986, 5.3193, 5.6319, 6.5640, 8.2421, 5.6393}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {0.79479, 0.52872, 0.90005, 0.77170, 0.73220, 0.72060, 0.75433, 0.75451, 0.75989, 0.67655, 1.68525, 1.31100, 1.46573, 1.99843, 1.57293, 1.62852, 2.10636, 1,1,1,1,1,1,1}, {0.4398, 0.5823, 0.7094, 0.7043, 0.7282, 0.7041, 0.6979, 0.7762, 0.7871, 0.7469, 1.7752, 1.7443, 2.2266, 2.4767, 2.4146, 2.6040, 2.5708, 4.4488, 4.4944, 5.9630, 6.3740, 8.1097, 8.4210, 7.8027}};
+/////////double beta1_dlsch[6][MCS_COUNT] = { {1.199175, 1.085656, 0.983872, 0.843789, 0.816093, 0.853078, 0.899236, 0.919665, 0.888673, 0.924181, 0.814176, 0.794108, 0.770653, 0.826266, 0.982043, 0.979621, 0.985176, 0.901741, 0.870311, 0.911303, 0.898923, 1.003359, 0.988535, 1.030639, 1.151038, 1.116939, 1.214118, 1.219148}, {0.5146, 0.5549, 0.7405, 0.6913, 0.7349, 0.7000, 0.7539, 0.7955, 0.8074, 0.7760, 1.8150, 1.6561, 1.9280, 2.3563, 2.6699, 2.3086, 3.1601, 4.5316, 5.2870, 6.0983, 6.5635, 7.7024, 9.9592, 6.6173}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1.79358, 1.17908, 2.02600, 1.72040, 1.58618, 1.59039, 1.68111, 1.67062, 1.64911, 1.33274, 4.87800, 3.58797, 3.72338, 5.35700, 2.81752, 1.93472, 2.23259, 1,1,1,1,1,1,1}, {0.4445, 0.5918, 0.7118, 0.7115, 0.7284, 0.7202, 0.7117, 0.8111, 0.8239, 0.7907, 1.8456, 1.8144, 2.3830, 2.6634, 2.6129, 2.8127, 2.7372, 4.9424, 4.8763, 6.8413, 7.1493, 9.4180, 10.1230, 8.9613}};
+/////////double beta2_dlsch[6][MCS_COUNT] = { {0.534622, 0.596561, 0.500838, 0.471721, 0.548218, 0.547974, 0.924245, 0.836484, 0.776917, 0.879691, 0.875722, 0.666933, 0.666393, 0.755377, 1.074985, 1.080290, 1.010914, 0.790892, 0.793435, 0.860249, 0.901508, 0.967060, 0.951372, 1.011493, 1.106151, 1.117076, 1.209397, 1.227790}, {0.5113, 0.5600, 0.7359, 0.6860, 0.7344, 0.6902, 0.7315, 0.7660, 0.7817, 0.7315, 1.7268, 1.5912, 1.8519, 2.2115, 2.4580, 2.1879, 2.9015, 4.1543, 4.6986, 5.3193, 5.6319, 6.5640, 8.2421, 5.6393}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {0.79479, 0.52872, 0.90005, 0.77170, 0.73220, 0.72060, 0.75433, 0.75451, 0.75989, 0.67655, 1.68525, 1.31100, 1.46573, 1.99843, 1.57293, 1.62852, 2.10636, 1,1,1,1,1,1,1}, {0.4398, 0.5823, 0.7094, 0.7043, 0.7282, 0.7041, 0.6979, 0.7762, 0.7871, 0.7469, 1.7752, 1.7443, 2.2266, 2.4767, 2.4146, 2.6040, 2.5708, 4.4488, 4.4944, 5.9630, 6.3740, 8.1097, 8.4210, 7.8027}};
+
+//real channel estimation valus
+///
+double beta1_dlsch[6][MCS_COUNT] = { {2.50200, 0.84047, 0.78195, 1.37929, 1.16871, 1.11906, 1.06303, 1.07447, 1.11403, 1.09223, 2.82502, 2.87556, 3.51254, 3.62920, 3.53638, 2.35980, 3.74126, 8.66532, 7.31772, 9.86882, 10.64939, 6.75208, 9.50664, 13.63057}, {0.92257, 1, 1.80445, 1.43175, 1.42093, 1.37381, 1.45392, 1.47255, 1.47451, 1.41235, 3.9079, 3.38557, 4.13059, 4.93355, 4.97277, 6.04951, 5.88896, 8.68076, 10.23746, 12.37069, 5.50538, 17.29612, 17.95050, 13.27095}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {1.79255, 1.88213, 4.44226, 2.25150, 1.93710, 2.18504, 2.57389, 1.94322, 1.78515, 2.09265, 2.37459, 1.74442, 1.74346, 1.19705, 1.56149, 1.59604, 1.6, 1,1,1,1,1,1,1}, {0.93374, 1.40389, 1.36670, 1.38679, 1.35707, 1.26353, 1.32360, 1.40164, 1.51843, 1.34863, 3.45839, 3.13726, 3.94768, 4.21966, 4.60750, 4.97894, 5.40755, 8.12814, 10.59221, 12.96427, 13.37323, 14.27206, 16.61779, 17.19656}};
+double beta2_dlsch[6][MCS_COUNT] = { {2.52163, 0.83231, 0.77472, 1.36536, 1.16829, 1.11186, 1.06287, 1.07292, 1.09946, 1.10650, 2.79174, 2.75655, 3.36651, 3.49011, 3.60903, 2.73517, 3.84009, 8.20312, 7.41739, 9.64081, 10.40911, 8.11765, 10.41923, 9.34300}, {0.67252, 0.8600, 1.28633, 1.01624, 1.03066, 0.97590, 1.02560, 1.01840, 1.00547, 0.97093, 2.72573, 2.33283, 2.86181, 3.40452, 3.47957, 4.08916, 3.97628, 6.14541, 7.11017, 8.42369, 4.04812, 11.42082, 11.57171, 9.28462}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1,1}, {1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1,1,1,1,1,1}, {0.85784, 0.90361, 2.09766, 1.08385, 0.96300, 1.04432, 1.22763, 0.99249, 0.95544, 1.12333, 1.37924, 1.12913, 1.30644, 1.19253, 1.75488, 2.13813, 2.10636, 1,1,1,1,1,1,1}, {0.66288, 0.96402, 0.98545, 0.99386, 0.99981, 0.92678, 0.98978, 0.99600, 1.05538, 0.97777, 2.52504, 2.29338, 2.89631, 3.10812, 3.41916, 3.58671, 3.84166, 6.05254, 7.45821, 9.15812, 9.66330, 10.17852, 11.50519, 11.16299}};
+
+///
+
+#ifdef OCP_FRAMEWORK
+#include <enums.h>
+#else
+char eNB_functions[6][20]={"eNodeB_3GPP","eNodeB_3GPP_BBU","NGFI_RCC_IF4p5","NGFI_RAI_IF4p5","NGFI_RRU_IF5","NGFI_RRU_IF4p5",};
+char eNB_timing[2][20]={"synch_to_ext_device","synch_to_other"};
+#endif
+*/
+/// lookup table for unscrambling in RX
+int16_t unscrambling_lut_NB_IoT[65536*16] __attribute__((aligned(32)));
+
+/*
+/// lookup table for scrambling in TX
+uint8_t scrambling_lut[65536*16] __attribute__((aligned(32)));
+
+
+*/
+
+
+#endif /*__PHY_VARS_H__ */
diff --git a/openair1/SCHED/IF_Module_L1_primitives_NB_IoT.c b/openair1/SCHED/IF_Module_L1_primitives_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..688e06a08a413b4762abf1e82726ef6217445fb0
--- /dev/null
+++ b/openair1/SCHED/IF_Module_L1_primitives_NB_IoT.c
@@ -0,0 +1,363 @@
+
+
+
+#include "../SCHED/IF_Module_L1_primitives_NB_IoT.h"
+//#include "../SCHED/defs.h"
+#include "../SCHED/defs_NB_IoT.h"
+#include "assertions.h"
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+//#include "PHY/extern.h"
+#include "PHY/extern_NB_IoT.h"
+//#include "PHY/vars.h"
+#include "PHY/vars_NB_IoT.h"
+#include "PHY/INIT/defs_NB_IoT.h"
+
+
+void handle_nfapi_dlsch_pdu_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
+						  		   eNB_rxtx_proc_NB_IoT_t *proc,
+		       	   	   	           nfapi_dl_config_request_pdu_t *dl_config_pdu,
+						   		   uint8_t *sdu)
+{
+
+	NB_IoT_eNB_NDLSCH_t *ndlsch;
+	NB_IoT_DL_eNB_HARQ_t *ndlsch_harq;
+	nfapi_dl_config_ndlsch_pdu_rel13_t *rel13 = &dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13;
+	int UE_id= -1;
+
+  //Check for SI PDU since in NB-IoT there is no DCI for that
+  //SIB1 (type 0), other DLSCH data (type 1) (include the SI messages) based on our ASSUMPTIONs
+
+	//is SIB1-NB
+  if(rel13->rnti_type == 0 && rel13->rnti == 65535)
+  {
+
+	  /*
+	   * the configuration of the NDLSCH PDU for the SIB1-NB shoudl be the following:
+	   * -RNTI type = 0; (BCCH)
+	   * -RNTI = OxFFFF (65535)
+	   * -Repetition number = 0-15 and should be mapped to 4,8,16 as reported in Table 16.4.1.3-3 TS 36.213 (is the schedulingInoSIB1 of the MIB)
+	   * -Number of subframe for resource assignment = may is not neded to know since the scheduling is fixed
+	   *  (Spec TS 36.331 "SIB1-NB transmission occur in subframe #4 of every other frame in 16 continuous frame"
+	   *  meaning that from the starting point we should transmit the SIB1-NB in 8 subframes  among the 16 available (every other))
+	   *
+	   * From spec. TS 36.321 v14.2.o pag 31 --> there is an HARQ process for all the broadcast (so we consider it also for SIB1-NB)
+	   *
+	   */
+
+	  	ndlsch= eNB->ndlsch_SIB1;
+	  	ndlsch->ndlsch_type = SIB1;
+
+		ndlsch->npdsch_start_symbol = rel13->start_symbol; //start symbol for the ndlsch transmission
+		ndlsch_harq = ndlsch->harq_process;
+		ndlsch_harq->pdu = sdu;
+		//should be from 1 to 8
+		ndlsch_harq->resource_assignment = rel13->number_of_subframes_for_resource_assignment;//maybe we don't care about it since a fixed schedule
+		ndlsch_harq->repetition_number = rel13->repetition_number; //is the schedulingInfoSIB1 (value 1-15) of MIB that is mapped into value 4-8-16 (see NDLSCH fapi specs Table 4-47)
+		ndlsch_harq->modulation = rel13->modulation;
+		ndlsch_harq->status = ACTIVE_NB_IoT;
+
+		//SI information in reality have no feedback (so there is no retransmission from the HARQ view point since no ack and nack)
+//        ndlsch_harq->frame = frame;
+//        ndlsch_harq->subframe = subframe;
+
+        ndlsch->nrs_antenna_ports = rel13->nrs_antenna_ports_assumed_by_the_ue;
+        ndlsch->scrambling_sequence_intialization = rel13->scrambling_sequence_initialization_cinit;
+
+
+
+
+  }
+  //is SI message (this is an NDLSCH that will be transmitted very frequently)
+  else if(rel13->rnti_type == 1 && rel13->rnti == 65535)
+  {
+	  /*
+	   *
+	   * the configuration of the NDLSCH PDU for the SIB1-NB should be the following:
+	   * RNTI type = 1;
+	   * RNTI = OxFFFF (65535)
+	   * Repetition number = 0 and should be mapped to 1 through Table 16.4.1.3-2 TS 36.213
+	   * Number of subframe for resource assignment = will be evaluated by the MAC based on the value of the "si-TB" field inside the SIB1-NB (value 2 or 8)
+	   *
+	   * From spec. TS 36.321 v14.2.o pag 31 --> there is an HARQ process for all the broadcast
+	   *
+	   * XXX for the moment we are not able to prevent the problem of Error: first transmission but sdu = NULL.
+	   * anyway, the PHY layer if have finished the transmission it will not transmit anything and will generate the error
+	   *
+	   */
+
+	  	ndlsch= eNB->ndlsch_SI;
+	  	ndlsch_harq = ndlsch->harq_process;
+
+		//new SI starting transmission (should enter here only the first time for a new transmission)
+		if(sdu != NULL)
+		{
+
+		  	ndlsch->ndlsch_type = SI_Message;
+			ndlsch->npdsch_start_symbol = rel13->start_symbol; //start OFDM symbol for the ndlsch transmission
+			ndlsch_harq->pdu = sdu;
+			ndlsch_harq->resource_assignment = rel13->number_of_subframes_for_resource_assignment;//value 2 or 8
+			ndlsch_harq->repetition_number = rel13->repetition_number;//should be always fix to 0 to be mapped in 1
+			ndlsch_harq->modulation = rel13->modulation;
+
+
+			//SI information in reality have no feedback (so there is no retransmission from the HARQ view point since no sck and nack)
+	//        ndlsch_harq->frame = frame;
+	//        ndlsch_harq->subframe = subframe;
+
+			ndlsch->nrs_antenna_ports = rel13->nrs_antenna_ports_assumed_by_the_ue;
+			ndlsch->scrambling_sequence_intialization = rel13->scrambling_sequence_initialization_cinit;
+		}
+		else
+		{
+			//continue the remaining transmission of the previous SI at PHY if any (otherwise nothing)
+			//there is no need of repeating the configuration on the ndlsch
+			ndlsch_harq->pdu = NULL;
+		}
+
+		//Independently if we have the PDU or not (first transmission or repetition) the process is activated for triggering the ndlsch_procedure
+	  	ndlsch_harq->status = ACTIVE_NB_IoT;
+
+
+  }
+  //ue specific data or RAR (we already have received the DCI for this)
+  else if(rel13->rnti != 65535 && rel13->rnti_type == 1)
+  {
+
+	  //check if the PDU is for RAR
+	  if(eNB->ndlsch_ra != NULL && rel13->rnti == eNB->ndlsch_ra->rnti) //rnti for the RAR should have been set priviously by the DCI
+	  {
+		  eNB->ndlsch_ra->harq_process->pdu = sdu;
+		  eNB->ndlsch_ra->npdsch_start_symbol = rel13->start_symbol;
+		  eNB->ndlsch_ra->active = 1;
+	  }
+	  else
+	  { //this for ue data
+		  //TODO
+		  //program addition DLSCH parameters not from DCI (for the moment we only pass the pdu)
+		  //int UE_id = find_dlsch(rel13->rnti,eNB,SEARCH_EXIST);
+
+
+		  UE_id =  find_ue_NB_IoT(rel13->rnti,eNB);
+	  	  AssertFatal(UE_id==-1,"no existing ue specific dlsch_context\n");
+
+	  	  ndlsch = eNB->ndlsch[(uint8_t)UE_id];
+	  	  ndlsch_harq     = eNB->ndlsch[(uint8_t)UE_id]->harq_process;
+	  	  AssertFatal(ndlsch_harq!=NULL,"dlsch_harq for ue specific is null\n");
+
+	  	  ndlsch->npdsch_start_symbol = rel13->start_symbol;
+	  	  ndlsch_harq->pdu  = sdu;
+	  	  ndlsch->active = 1;
+
+	  }
+
+  }
+  //I don't know which kind of data is
+  else
+  {
+	  LOG_E(PHY, "handle_nfapi_dlsch_pdu_NB_IoT: Unknown type of data (rnti type %d, rnti %d)\n", rel13->rnti_type, rel13->rnti);
+  }
+
+}
+
+
+
+/////////////////////////////////////////////////////////////////////////////////////////////////
+//Memo for initialization TODO: target/SIMU/USER/init_lte.c/init_lte_eNB --> new_eNB_dlsch(..) //
+//this is where the allocation of PHy_vars_eNB_NB_IoT and all the ndlsch structures happen            //
+/////////////////////////////////////////////////////////////////////////////////////////////////
+
+
+// do the schedule response and trigger the TX
+void schedule_response(Sched_Rsp_t *Sched_INFO)
+{
+
+  //XXX check if correct to take eNB like this
+  PHY_VARS_eNB_NB_IoT 		*eNB     = PHY_vars_eNB_NB_IoT_g[0][Sched_INFO->CC_id];
+  eNB_rxtx_proc_NB_IoT_t 	*proc 	 = &eNB->proc.proc_rxtx[0];
+  NB_IoT_eNB_NPBCH_t 		*npbch;
+  ///
+  int 						i;
+  //module_id_t                     Mod_id    = Sched_INFO->module_id;
+  //uint8_t                         CC_id     = Sched_INFO->CC_id;
+  nfapi_dl_config_request_t 	*DL_req    		= Sched_INFO->DL_req;
+  nfapi_ul_config_request_t 	*UL_req    		= Sched_INFO->UL_req;
+  nfapi_hi_dci0_request_t 		*HI_DCI0_req 	= Sched_INFO->HI_DCI0_req;
+  nfapi_tx_request_t        	*TX_req    		= Sched_INFO->TX_req; 
+
+  //uint32_t                     hypersfn  		= Sched_INFO->hypersfn;
+  //frame_t                      frame     		= Sched_INFO->frame;       // unused for instance
+  sub_frame_t                    subframe  		= Sched_INFO->subframe;	 
+
+  // implicite declaration of AssertFatal
+  //AsserFatal(proc->subframe_tx != subframe, "Current subframe %d != NFAPI subframe %d\n",proc->subframe_tx,subframe);
+  //AsserFatal(proc->frame_tx != frame, "Current sframe %d != NFAPI frame %d\n", proc->frame_tx,frame );
+
+  uint8_t number_dl_pdu             = DL_req->dl_config_request_body.number_pdu;
+  uint8_t number_ul_pdu				= UL_req->ul_config_request_body.number_of_pdus;
+  uint8_t number_ul_dci             = HI_DCI0_req->hi_dci0_request_body.number_of_dci;
+  //uint8_t number_pdsch_rnti         = DL_req->number_pdsch_rnti; // for the moment not used
+  // at most 2 pdus (DCI) in the case of NPDCCH
+  nfapi_dl_config_request_pdu_t 	*dl_config_pdu;
+  nfapi_ul_config_request_pdu_t 	*ul_config_pdu;
+  nfapi_hi_dci0_request_pdu_t 		*hi_dci0_pdu;
+
+  //clear previous possible allocation (maybe someone else should be added)
+  for(int i = 0; i < NUMBER_OF_UE_MAX_NB_IoT; i++)
+  {
+	  if(eNB->ndlsch[i])
+	  {
+		  eNB->ndlsch[i]->harq_process->round=0; // may not needed
+		  /*clear previous allocation information for all UEs*/
+		  eNB->ndlsch[i]->subframe_tx[subframe] = 0;
+	  }
+
+	  /*clear the DCI allocation maps for new subframe*/
+	  if(eNB->nulsch[i])
+	  {
+		  eNB->nulsch[i]->harq_process->dci_alloc = 0; //flag for indicating that a DCI has been allocated for UL
+		  eNB->nulsch[i]->harq_process->rar_alloc = 0; //Flag indicating that this ULSCH has been allocated by a RAR (for Msg3)
+		  //no phich for NB-IoT so no DMRS should be utilized
+	  }
+
+  }
+
+
+  for (i=0;i<number_dl_pdu;i++) //in principle this should be at most 2 (in case of DCI)
+  {
+    dl_config_pdu = &DL_req->dl_config_request_body.dl_config_pdu_list[i];
+    switch (dl_config_pdu->pdu_type) 
+    {
+    	case NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE:
+    		//Remember: there is no DCI for SI information
+    		//TODO: separate the ndlsch structure configuration from the DCI (here we will encode only the DCI)
+      		generate_eNB_dlsch_params_NB_IoT(eNB,proc,dl_config_pdu);
+
+      		break;
+    	case NFAPI_DL_CONFIG_NBCH_PDU_TYPE:
+
+    		// for the moment we don't care about the n-bch pdu content since we need only the sdu if tx.request
+    		npbch = eNB->npbch; //in the main of the lte-softmodem they should allocate this memory of PHY_vars
+    		npbch->h_sfn_lsb = dl_config_pdu->nbch_pdu.nbch_pdu_rel13.hyper_sfn_2_lsbs;
+
+    		if(TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->nbch_pdu.nbch_pdu_rel13.pdu_index].segments[0].segment_data != NULL)
+    			npbch->pdu = TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->nbch_pdu.nbch_pdu_rel13.pdu_index].segments[0].segment_data;
+    		else
+    			LOG_E(PHY, "Received a schedule_response with N-BCH but no SDU!!\n");
+
+      		break;
+    	case NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE:
+    		//we can have three types of NDLSCH based on our assumptions: SIB1, SI, Data, RAR
+    		//remember that SI messages have no DCI in NB-IoT therefore this is the only way to configure the ndlsch_SI/ndlsch_SIB1 structures ndlsch->active = 1;
+
+    		/*
+    		 * OBSERVATION:
+    		 * Although 2 DCI may be received over a schedule_response the transmission of the NDLSCH data foresees only 1 NDLSCH PDU at time.
+    		 * Therefore is the MAC scheduler that knowing the different timing delay will send the corresponding schedule_response containing the NDLSCH PDU and the MAC PDU
+    		 * at the proper DL subframe
+    		 * -for this reason the activation of the ndslch structure is done only when we receive the NDLSCH pdu (here) such the in the TX procedure only 1 ue-specific pdu
+    		 * 	result active from the loop before calling the ndlsch_procedure
+    		 */
+
+    		handle_nfapi_dlsch_pdu_NB_IoT(eNB, proc,dl_config_pdu,TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index].segments[0].segment_data);
+
+    		break;
+    	default:
+    		LOG_E(PHY, "dl_config_pdu type not for NB_IoT\n");
+    		break;
+   }
+  }
+  
+  for (i=0;i<number_ul_dci;i++) 
+  {
+    hi_dci0_pdu = &HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list[i];
+    switch (hi_dci0_pdu->pdu_type) 
+    {
+    	case NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE:
+
+      		generate_eNB_ulsch_params_NB_IoT(eNB,proc,hi_dci0_pdu);
+
+      		break;
+    	default:
+    		LOG_E(PHY, "dl_config_pdu type not for NB_IoT\n");
+    		break;
+
+  	}
+  }
+
+
+  for(i = 0; i< number_ul_pdu; i++)
+  {
+	  ul_config_pdu = &UL_req->ul_config_request_body.ul_config_pdu_list[i];
+	  switch(ul_config_pdu->pdu_type)
+	  {
+	  case NFAPI_UL_CONFIG_NULSCH_PDU_TYPE:
+		  //TODO should distinguish between data and between data (npusch format)
+		  /*NB: for reception of Msg3 generally not exist a DCI (because scheduling information are implicitly given by the RAR)
+		   * but in case of FAPI specs we should receive an UL_config (containing the NULSCH pdu) for configuring the PHY for Msg3 reception from the MAC
+		   * (this UL_config most probably will be created by the MAC when fill the RAR)
+		   * (most probably we don't have the DL_config (for the RAR transmission) and the UL_CONFIG (for the Msg3 reception) at the same time (same subrame)
+		   * since we are working in HD-FDD mode so for sure the UE will transmit the Msg3 in another subframe so make sense to have a UL_CONFIG in subframe
+		   * diferent from the DL_CONFIG one)
+		   *
+		   */
+		  break;
+	  case NFAPI_UL_CONFIG_NRACH_PDU_TYPE:
+		  //TODO just for update the nprach  configuration (given at the beginning through phy_config_sib2)
+		  break;
+	  }
+  }
+
+
+  //XXX problem: although we may have nothing to transmit this function should be always triggered in order to allow the PHY layer to complete the repetitions
+  //of previous Transport Blocks
+  //phy_procedures_eNB_TX_NB_IoT(eNB,proc,NULL);
+  phy_procedures_eNB_TX_NB_IoT(eNB,proc,0); // check if 0 or NULL ?!
+
+}
+
+void PHY_config_req(PHY_Config_t* config_INFO){
+
+
+	if(config_INFO->get_MIB != 0){
+
+		//MIB-NB configuration
+		phy_config_mib_eNB_NB_IoT(config_INFO->mod_id,
+							  	  config_INFO->CC_id,
+							  	  config_INFO->cfg->nfapi_config.rf_bands.rf_band[0],//eutraband
+							  	  config_INFO->cfg->sch_config.physical_cell_id.value,
+							      config_INFO->cfg->subframe_config.dl_cyclic_prefix_type.value,
+							  	  config_INFO->cfg->subframe_config.ul_cyclic_prefix_type.value,
+							  	  config_INFO->cfg->rf_config.tx_antenna_ports.value,
+							  	  config_INFO->cfg->nfapi_config.earfcn.value,
+							  	  config_INFO->cfg->config_NB_IoT.prb_index.value,
+							  	  config_INFO->cfg->config_NB_IoT.operating_mode.value,
+							  	  config_INFO->cfg->config_NB_IoT.control_region_size.value,
+							  	  config_INFO->cfg->config_NB_IoT.assumed_crs_aps.value); //defined only in in-band different PCI
+
+	}
+
+	if(config_INFO->get_COMMON != 0)
+	{
+		//Common Configuration included in SIB2-NB
+		phy_config_sib2_eNB_NB_IoT(config_INFO->mod_id,
+							   	   config_INFO->CC_id,
+						       	   &config_INFO->cfg->config_NB_IoT, // FIXME to be evaluated is should be passed a pointer
+						       	   &config_INFO->cfg->rf_config,
+							   	   &config_INFO->cfg->uplink_reference_signal_config,
+							   	   &config_INFO->extra_phy_parms);
+	}
+
+	///FOR FAPI is not specified
+	if(config_INFO->get_DEDICATED!= 0)
+	{
+	//Dedicated Configuration
+
+			phy_config_dedicated_eNB_NB_IoT(config_INFO->mod_id,
+											config_INFO->CC_id,
+											config_INFO->rnti,
+											&config_INFO->extra_phy_parms);
+
+	}
+}
+
diff --git a/openair1/SCHED/IF_Module_L1_primitives_NB_IoT.h b/openair1/SCHED/IF_Module_L1_primitives_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..03151024617f9bfa5745b068b82639a7be3511b2
--- /dev/null
+++ b/openair1/SCHED/IF_Module_L1_primitives_NB_IoT.h
@@ -0,0 +1,30 @@
+
+
+
+
+
+
+#ifndef __IF_MODULE_L1_PRIMITIVES_NB_IOT_H__
+#define __IF_MODULE_L1_PRIMITIVES_NB_IOT_H__
+
+//#include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h"
+#include "openair1/PHY/defs_NB_IoT.h"
+//#include "LAYER2/MAC/extern.h"
+//#include "LAYER2/MAC/proto_NB_IoT.h"
+
+
+
+/*Interface for Downlink, transmitting the DLSCH SDU, DCI SDU*/
+void schedule_response(Sched_Rsp_t *Sched_INFO);
+
+/*Interface for PHY Configuration
+ * Trigger the phy_config_xxx functions using parameters from the shared PHY_Config structure
+ * */
+void PHY_config_req(PHY_Config_t* config_INFO);
+
+void handle_nfapi_dlsch_pdu_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,
+						  	   	   eNB_rxtx_proc_NB_IoT_t *proc,
+		       	   	   	   	       nfapi_dl_config_request_pdu_t *dl_config_pdu,
+						   	       uint8_t *sdu);
+
+#endif
diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h
index f00ca4a672001b3c761dbca9b8ce2d0eb86f2638..af3c4bdd252fe429e01ab50f01d73cae41d2cbed 100644
--- a/openair1/SCHED/defs.h
+++ b/openair1/SCHED/defs.h
@@ -374,6 +374,7 @@ uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1);
 
 
 int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB);
+
 int32_t add_ue(int16_t rnti, PHY_VARS_eNB *phy_vars_eNB);
 int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rnti);
 
diff --git a/openair1/SCHED/defs_NB_IoT.h b/openair1/SCHED/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..07070d096336f486116aaabeaca31a4f2cace61a
--- /dev/null
+++ b/openair1/SCHED/defs_NB_IoT.h
@@ -0,0 +1,53 @@
+
+
+#ifndef __openair_SCHED_NB_IOT_H__
+#define __openair_SCHED_NB_IOT_H__
+
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+//#include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h"
+#include "openair2/PHY_INTERFACE/nfapi_interface.h"
+
+
+
+enum openair_HARQ_TYPE_NB_IoT {
+  openair_harq_DL_NB_IoT = 0,
+  openair_harq_UL_NB_IoT,
+  openair_harq_RA_NB_IoT
+};
+
+
+void process_schedule_rsp_NB_IoT(Sched_Rsp_t *sched_rsp,
+                          		 PHY_VARS_eNB_NB_IoT *eNB,
+                          		 eNB_rxtx_proc_t *proc);
+
+/*Processing the ue-specific resources for uplink in NB-IoT*/
+void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc, UL_IND_t *UL_INFO);
+
+/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler,this generates NRS/NPSS/NSSS*/
+void common_signal_procedures_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc); 
+
+/*Generate the ulsch params and do the mapping for the FAPI style parameters to OAI, and then do the packing*/
+void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc,nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu);
+
+/*Generate the dlsch params and do the mapping for the FAPI style parameters to OAI, and then do the packing*/
+void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t * proc,nfapi_dl_config_request_pdu_t *dl_config_pdu);
+
+/*Process all the scheduling result from MAC and also common signals.*/
+void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc,int do_meas);
+
+int8_t find_ue_NB_IoT(uint16_t rnti, PHY_VARS_eNB_NB_IoT *eNB);
+
+NB_IoT_DL_FRAME_PARMS *get_NB_IoT_frame_parms(module_id_t Mod_id, uint8_t CC_id);
+
+int16_t get_hundred_times_delta_IF_eNB_NB_IoT(PHY_VARS_eNB_NB_IoT *phy_vars_eNB,uint8_t UE_id,uint8_t harq_pid, uint8_t bw_factor);
+
+uint32_t is_SIB1_NB_IoT(const frame_t          frameP,
+                        long                   schedulingInfoSIB1,   //from the mib
+                        int                    physCellId,           //by configuration
+                        NB_IoT_eNB_NDLSCH_t   *ndlsch_SIB1
+                        );
+
+#endif
+
+
diff --git a/openair1/SCHED/extern.h b/openair1/SCHED/extern.h
index 2c5ac12ca554bd1220996a1f8e5d3b904e317adb..f22be2f6389a63a34e1153bfe8956551ff552c8a 100644
--- a/openair1/SCHED/extern.h
+++ b/openair1/SCHED/extern.h
@@ -42,8 +42,6 @@
 #include <asm/page.h>
 
 
-
-
 #ifdef RTAI_ENABLED
 #include <rtai.h>
 //#include <rtai_posix.h>
@@ -78,4 +76,5 @@ extern fifo_dump_emos_eNB emos_dump_eNB;
 #endif
 */
 
+
 #endif /*__SCHED_EXTERN_H__ */
diff --git a/openair1/SCHED/extern_NB_IoT.h b/openair1/SCHED/extern_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..2d30eeb2986aaa2507f13015573bbec97b761ab5
--- /dev/null
+++ b/openair1/SCHED/extern_NB_IoT.h
@@ -0,0 +1,75 @@
+/*
+ * 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.0  (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
+ */
+
+/*!\brief SCHED external variables */
+
+#ifndef __SCHED_EXTERN_NB_IOT_H__
+#define __SCHED_EXTERN_NB_IOT_H__
+
+#ifndef USER_MODE
+#define __NO_VERSION__
+
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/module.h>
+#include <linux/version.h>
+#include <linux/types.h>
+
+#include <asm/io.h>
+#include <asm/bitops.h>
+
+#include <asm/uaccess.h>
+#include <asm/segment.h>
+#include <asm/page.h>
+
+
+#ifdef RTAI_ENABLED
+#include <rtai.h>
+//#include <rtai_posix.h>
+#include <rtai_fifos.h>
+#include <rtai_sched.h>
+#include <rtai_sem.h>
+//#include "rt_compat.h"
+
+#else
+#include <unistd.h>
+#endif
+
+#endif  /* USER_MODE */
+
+
+
+
+#include "defs_NB_IoT.h"
+
+
+
+#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
+
+
+extern uint16_t hundred_times_log10_NPRB_NB_IoT[100];
+
+extern Sched_Rsp_t* Sched_Rsp;
+
+
+
+#endif /*__SCHED_EXTERN_H__ */
diff --git a/openair1/SCHED/phy_procedures_lte_common.c b/openair1/SCHED/phy_procedures_lte_common.c
index e14a15601821890f0d089914476ee6ff4b45686b..7968ee607f5ee2226496f7cce48457931c0eaae3 100644
--- a/openair1/SCHED/phy_procedures_lte_common.c
+++ b/openair1/SCHED/phy_procedures_lte_common.c
@@ -1086,6 +1086,7 @@ LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t  CC_id,uint16_t rnti)
 
 int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *eNB)
 {
+
   uint8_t i;
 
   for (i=0; i<NUMBER_OF_UE_MAX; i++) {
@@ -1110,6 +1111,7 @@ int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *eNB)
   return(-1);
 }
 
+
 LTE_DL_FRAME_PARMS* get_lte_frame_parms(module_id_t Mod_id, uint8_t  CC_id)
 {
 
diff --git a/openair1/SCHED/phy_procedures_lte_common_NB_IoT.c b/openair1/SCHED/phy_procedures_lte_common_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..4b126c58c247d2454d04bfc0abe2e60059325f9d
--- /dev/null
+++ b/openair1/SCHED/phy_procedures_lte_common_NB_IoT.c
@@ -0,0 +1,1281 @@
+
+
+/*! \file phy_procedures_lte_eNB.c
+* \brief Implementation of common utilities for eNB/UE procedures from 36.213 LTE specifications
+* \author M. KANJ R. Knopp, F. Kaltenberger
+* \date 2017
+* \version 0.1
+* \company Bcom & Eurecom
+* \email: matthieu.kanj@b-com.com , knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
+* \note
+* \warning
+*/
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/extern_NB_IoT.h"
+//#include "SCHED/defs_nb_iot.h"
+//#include "SCHED/extern.h"
+
+#ifdef LOCALIZATION
+#include <sys/time.h>
+#endif
+
+/*
+void get_Msg3_alloc(LTE_DL_FRAME_PARMS *frame_parms,
+                    unsigned char current_subframe,
+                    unsigned int current_frame,
+                    unsigned int *frame,
+                    unsigned char *subframe)
+{
+
+  // Fill in other TDD Configuration!!!!
+
+  if (frame_parms->frame_type == FDD) {
+    *subframe = current_subframe+6;
+
+    if (*subframe>9) {
+      *subframe = *subframe-10;
+      *frame = (current_frame+1) & 1023;
+    } else {
+      *frame=current_frame;
+    }
+  } else { // TDD
+    if (frame_parms->tdd_config == 1) {
+      switch (current_subframe) {
+
+      case 0:
+        *subframe = 7;
+        *frame = current_frame;
+        break;
+
+      case 4:
+        *subframe = 2;
+        *frame = (current_frame+1) & 1023;
+        break;
+
+      case 5:
+        *subframe = 2;
+        *frame = (current_frame+1) & 1023;
+        break;
+
+      case 9:
+        *subframe = 7;
+        *frame = (current_frame+1) & 1023;
+        break;
+      }
+    } else if (frame_parms->tdd_config == 3) {
+      switch (current_subframe) {
+
+      case 0:
+      case 5:
+      case 6:
+        *subframe = 2;
+        *frame = (current_frame+1) & 1023;
+        break;
+
+      case 7:
+        *subframe = 3;
+        *frame = (current_frame+1) & 1023;
+        break;
+
+      case 8:
+        *subframe = 4;
+        *frame = (current_frame+1) & 1023;
+        break;
+
+      case 9:
+        *subframe = 2;
+        *frame = (current_frame+2) & 1023;
+        break;
+      }
+    } else if (frame_parms->tdd_config == 4) {
+        switch (current_subframe) {
+
+        case 0:
+        case 4:
+        case 5:
+        case 6:
+          *subframe = 2;
+          *frame = (current_frame+1) & 1023;
+          break;
+
+        case 7:
+          *subframe = 3;
+          *frame = (current_frame+1) & 1023;
+          break;
+
+        case 8:
+        case 9:
+          *subframe = 2;
+          *frame = (current_frame+2) & 1023;
+          break;
+        }
+      } else if (frame_parms->tdd_config == 5) {
+          switch (current_subframe) {
+
+          case 0:
+          case 4:
+          case 5:
+          case 6:
+            *subframe = 2;
+            *frame = (current_frame+1) & 1023;
+            break;
+
+          case 7:
+          case 8:
+          case 9:
+            *subframe = 2;
+            *frame = (current_frame+2) & 1023;
+            break;
+          }
+        }
+  }
+}
+
+void get_Msg3_alloc_ret(LTE_DL_FRAME_PARMS *frame_parms,
+                        unsigned char current_subframe,
+                        unsigned int current_frame,
+                        unsigned int *frame,
+                        unsigned char *subframe)
+{
+  if (frame_parms->frame_type == FDD) {
+    // always retransmit in n+8 /
+    *subframe = current_subframe + 8;
+
+    if (*subframe > 9) {
+      *subframe = *subframe - 10;
+      *frame = (current_frame + 1) & 1023;
+    } else {
+      *frame = current_frame;
+    }
+  } else {
+    if (frame_parms->tdd_config == 1) {
+      // original PUSCH in 2, PHICH in 6 (S), ret in 2
+      // original PUSCH in 3, PHICH in 9, ret in 3
+      // original PUSCH in 7, PHICH in 1 (S), ret in 7
+      // original PUSCH in 8, PHICH in 4, ret in 8
+      *frame = (current_frame+1) & 1023;
+    } else if (frame_parms->tdd_config == 3) {
+      // original PUSCH in 2, PHICH in 8, ret in 2 next frame
+      // original PUSCH in 3, PHICH in 9, ret in 3 next frame
+      // original PUSCH in 4, PHICH in 0, ret in 4 next frame
+      *frame=(current_frame+1) & 1023;
+    } else if (frame_parms->tdd_config == 4) {
+        // original PUSCH in 2, PHICH in 8, ret in 2 next frame
+        // original PUSCH in 3, PHICH in 9, ret in 3 next frame
+        *frame=(current_frame+1) & 1023;
+    } else if (frame_parms->tdd_config == 5) {
+        // original PUSCH in 2, PHICH in 8, ret in 2 next frame
+        *frame=(current_frame+1) & 1023;
+    }
+  }
+}
+
+uint8_t get_Msg3_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,
+                          uint32_t frame,
+                          unsigned char current_subframe)
+{
+
+  uint8_t ul_subframe=0;
+  uint32_t ul_frame=0;
+
+  if (frame_parms->frame_type ==FDD) {
+    ul_subframe = (current_subframe>3) ? (current_subframe-4) : (current_subframe+6);
+    ul_frame    = (current_subframe>3) ? ((frame+1)&1023) : frame;
+  } else {
+    switch (frame_parms->tdd_config) {
+    case 1:
+      switch (current_subframe) {
+
+      case 9:
+      case 0:
+        ul_subframe = 7;
+        break;
+
+      case 5:
+      case 7:
+        ul_subframe = 2;
+        break;
+
+      }
+
+      break;
+
+    case 3:
+      switch (current_subframe) {
+
+      case 0:
+      case 5:
+      case 6:
+        ul_subframe = 2;
+        break;
+
+      case 7:
+        ul_subframe = 3;
+        break;
+
+      case 8:
+        ul_subframe = 4;
+        break;
+
+      case 9:
+        ul_subframe = 2;
+        break;
+      }
+
+      break;
+
+    case 4:
+      switch (current_subframe) {
+
+      case 0:
+      case 5:
+      case 6:
+      case 8:
+      case 9:
+        ul_subframe = 2;
+        break;
+
+      case 7:
+        ul_subframe = 3;
+        break;
+      }
+
+      break;
+
+    case 5:
+      ul_subframe =2;
+      break;
+
+    default:
+      LOG_E(PHY,"get_Msg3_harq_pid: Unsupported TDD configuration %d\n",frame_parms->tdd_config);
+      mac_xface->macphy_exit("get_Msg3_harq_pid: Unsupported TDD configuration");
+      break;
+    }
+  }
+
+  return(subframe2harq_pid(frame_parms,ul_frame,ul_subframe));
+
+}
+
+unsigned char ul_ACK_subframe2_dl_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe,unsigned char ACK_index)
+{
+
+  if (frame_parms->frame_type == FDD) {
+    return((subframe<4) ? subframe+6 : subframe-4);
+  } else {
+    switch (frame_parms->tdd_config) {
+    case 3:
+      if (subframe == 2) {  // ACK subframes 5 and 6
+        if (ACK_index==2)
+          return(1);
+
+        return(5+ACK_index);
+      } else if (subframe == 3) { // ACK subframes 7 and 8
+        return(7+ACK_index);  // To be updated
+      } else if (subframe == 4) { // ACK subframes 9 and 0
+        return((9+ACK_index)%10);
+      } else {
+        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
+              subframe,frame_parms->tdd_config);
+        return(0);
+      }
+
+      break;
+
+    case 4:
+          if (subframe == 2) {  // ACK subframes 0, 4 and 5
+            //if (ACK_index==2)
+            //  return(1); TBC
+            if (ACK_index==2)
+            return(0);
+
+            return(4+ACK_index);
+          } else if (subframe == 3) { // ACK subframes 6, 7 8 and 9
+            return(6+ACK_index);  // To be updated
+          } else {
+            LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
+                  subframe,frame_parms->tdd_config);
+            return(0);
+          }
+
+          break;
+
+    case 1:
+      if (subframe == 2) {  // ACK subframes 5 and 6
+        return(5+ACK_index);
+      } else if (subframe == 3) { // ACK subframe 9
+        return(9);  // To be updated
+      } else if (subframe == 7) { // ACK subframes 0 and 1
+        return(ACK_index);  // To be updated
+      } else if (subframe == 8) { // ACK subframe 4
+        return(4);  // To be updated
+      } else {
+        LOG_E(PHY,"phy_procedures_lte_common.c/ul_ACK_subframe2_dl_subframe: illegal subframe %d for tdd_config %d\n",
+              subframe,frame_parms->tdd_config);
+        return(0);
+      }
+
+      break;
+    }
+  }
+
+  return(0);
+}
+
+unsigned char ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
+{
+
+  if (frame_parms->frame_type == FDD) {
+    return(1);
+  } else {
+    switch (frame_parms->tdd_config) {
+    case 3:
+      if (subframe == 2) {  // ACK subframes 5 and 6
+        return(2); // should be 3
+      } else if (subframe == 3) { // ACK subframes 7 and 8
+        return(2);  // To be updated
+      } else if (subframe == 4) { // ACK subframes 9 and 0
+        return(2);
+      } else {
+        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
+              subframe,frame_parms->tdd_config);
+        return(0);
+      }
+
+      break;
+
+    case 4:
+          if (subframe == 2) {  // ACK subframes 0,4 and 5
+            return(3); // should be 4
+          } else if (subframe == 3) { // ACK subframes 6,7,8 and 9
+            return(4);
+          } else {
+            LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
+                  subframe,frame_parms->tdd_config);
+            return(0);
+          }
+
+          break;
+
+    case 5:
+              if (subframe == 2) {  // ACK subframes 0,3,4,5,6,7,8 and 9
+                return(8); // should be 3
+              } else {
+                LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
+                      subframe,frame_parms->tdd_config);
+                return(0);
+              }
+
+              break;
+
+    case 1:
+      if (subframe == 2) {  // ACK subframes 5 and 6
+        return(2);
+      } else if (subframe == 3) { // ACK subframe 9
+        return(1);  // To be updated
+      } else if (subframe == 7) { // ACK subframes 0 and 1
+        return(2);  // To be updated
+      } else if (subframe == 8) { // ACK subframe 4
+        return(1);  // To be updated
+      } else {
+        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
+              subframe,frame_parms->tdd_config);
+        return(0);
+      }
+
+      break;
+    }
+  }
+
+  return(0);
+}
+
+// This function implements table 10.1-1 of 36-213, p. 69
+// return the number 'Nbundled'
+uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
+                harq_status_t *harq_ack,
+                unsigned char subframe_tx,
+                unsigned char subframe_rx,
+                unsigned char *o_ACK,
+                uint8_t *pN_bundled,
+                uint8_t cw_idx,
+                uint8_t do_reset) // 1 to reset ACK/NACK status : 0 otherwise
+{
+  uint8_t status=0;
+  uint8_t subframe_ul=0xff, subframe_dl0=0xff, subframe_dl1=0xff,subframe_dl2=0xff, subframe_dl3=0xff;
+
+  //  printf("get_ack: SF %d\n",subframe);
+  if (frame_parms->frame_type == FDD) {
+    if (subframe_tx < 4)
+      subframe_dl0 = subframe_tx + 6;
+    else
+      subframe_dl0 = subframe_tx - 4;
+
+    o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;
+    status = harq_ack[subframe_dl0].send_harq_status;
+
+    //LOG_I(PHY,"dl subframe %d send_harq_status %d cw_idx %d, reset %d\n",subframe_dl0, status, cw_idx, do_reset);
+    if(do_reset)
+    	harq_ack[subframe_dl0].send_harq_status = 0;
+    //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_tx == 2) {  // ACK subframes 5,6
+        subframe_ul  = 6;
+        subframe_dl0 = 5;
+        subframe_dl1 = 6;
+      } else if (subframe_tx == 3) { // ACK subframe 9
+        subframe_ul  = 9;
+        subframe_dl0 = 9;
+        subframe_dl1 = 0xff;
+      } else if (subframe_tx == 4) { // nothing
+        subframe_ul  = 0xff;
+        subframe_dl0 = 0xff; // invalid subframe number indicates ACK/NACK is not needed
+        subframe_dl1 = 0xff;
+      } else if (subframe_tx == 7) { // ACK subframes 0,1
+        subframe_ul  = 1;
+        subframe_dl0 = 0;
+        subframe_dl1 = 1;
+      } else if (subframe_tx == 8) { // ACK subframes 4
+        subframe_ul  = 4;
+        subframe_dl0 = 4;
+        subframe_dl1 = 0xff;
+      } else {
+        LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
+              subframe_tx,frame_parms->tdd_config);
+        return(0);
+      }
+
+      // report ACK/NACK status
+      o_ACK[cw_idx] = 1;
+      status = 0;
+      if ((subframe_dl0 < 10) && (harq_ack[subframe_dl0].send_harq_status)) {
+        o_ACK[cw_idx] &= 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[cw_idx] &= harq_ack[subframe_dl1].ack;
+        status = harq_ack[subframe_dl1].send_harq_status;
+      }
+      // report status = Nbundled
+      if (!status) {
+        o_ACK[cw_idx] = 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_tx, 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[cw_idx], 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_tx, 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[cw_idx], 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_tx, 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[cw_idx], 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_tx, 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_tx == 2) {  // ACK subframes 5 and 6
+        subframe_dl0 = 5;
+        subframe_dl1 = 6;
+        subframe_ul  = 2;
+        //printf("subframe_tx 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_tx == 3) { // ACK subframes 7 and 8
+        subframe_dl0 = 7;
+        subframe_dl1 = 8;
+        subframe_ul  = 3;
+        //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_tx == 4) { // ACK subframes 9 and 0
+        subframe_dl0 = 9;
+        subframe_dl1 = 0;
+        subframe_ul  = 4;
+        //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_tx %d for tdd_config %d\n",
+              subframe_tx,frame_parms->tdd_config);
+        return(0);
+      }
+
+      // report ACK/NACK status
+      o_ACK[cw_idx] = 0;
+      if (harq_ack[subframe_dl0].send_harq_status == 1) {
+        o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;
+
+        if (harq_ack[subframe_dl1].send_harq_status == 1)
+          o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;
+      } else if (harq_ack[subframe_dl1].send_harq_status == 1)
+        o_ACK[cw_idx] = harq_ack[subframe_dl1].ack;
+
+      pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL;
+      status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status;
+
+      //LOG_D(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d subframe_rx %d N_bundled %d \n",
+      //	  subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack,
+      //    subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack, subframe_rx, pN_bundled[0]);
+      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;
+
+    case 4:
+          if (subframe_tx == 2) {  // ACK subframes 4, 5 and 0
+            subframe_dl0 = 0;
+            subframe_dl1 = 4;
+            subframe_dl2 = 5;
+            subframe_ul  = 2;
+            //printf("subframe_tx 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_tx == 3) { // ACK subframes 6, 7 8 and 9
+            subframe_dl0 = 7;
+            subframe_dl1 = 8;
+            subframe_dl2 = 9;
+            subframe_dl3 = 6;
+            subframe_ul  = 3;
+            //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 {
+            LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
+                  subframe_tx,frame_parms->tdd_config);
+            return(0);
+          }
+
+          // report ACK/NACK status
+          o_ACK[cw_idx] = 0;
+          if (harq_ack[subframe_dl0].send_harq_status == 1)
+            o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;
+
+          if (harq_ack[subframe_dl1].send_harq_status == 1)
+            o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;
+
+          if (harq_ack[subframe_dl2].send_harq_status == 1)
+            o_ACK[cw_idx] &= harq_ack[subframe_dl2].ack;
+
+          if (harq_ack[subframe_dl3].send_harq_status == 1)
+            o_ACK[cw_idx] &= harq_ack[subframe_dl3].ack;
+
+          pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL;
+          status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status + harq_ack[subframe_dl2].send_harq_status + harq_ack[subframe_dl3].send_harq_status;
+
+          LOG_I(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d dl Sfn2 %d status %d o_Ack %d dl Sfn3 %d status %d o_Ack %d subframe_rx %d N_bundled %d status %d\n",
+                subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack,
+              subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack,
+              subframe_dl2, harq_ack[subframe_dl2].send_harq_status,harq_ack[subframe_dl2].ack,
+              subframe_dl3, harq_ack[subframe_dl3].send_harq_status,harq_ack[subframe_dl3].ack,subframe_rx, pN_bundled[0], status);
+          if (do_reset) {
+            // reset ACK/NACK status
+            harq_ack[subframe_dl0].ack = 2;
+            harq_ack[subframe_dl1].ack = 2;
+            harq_ack[subframe_dl2].ack = 2;
+            harq_ack[subframe_dl3].ack = 2;
+            harq_ack[subframe_dl0].send_harq_status = 0;
+            harq_ack[subframe_dl1].send_harq_status = 0;
+            harq_ack[subframe_dl2].send_harq_status = 0;
+            harq_ack[subframe_dl3].send_harq_status = 0;
+          }
+
+          break;
+
+    }
+  }
+
+  //printf("status %d\n",status);
+
+  return(status);
+}
+
+uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
+                harq_status_t *harq_ack,
+                unsigned char subframe_tx,
+                unsigned char subframe_rx,
+                unsigned char *o_ACK,
+                uint8_t cw_idx)
+{
+    uint8_t N_bundled = 0;
+  return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, &N_bundled, cw_idx, 0);
+}
+
+uint8_t reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
+                harq_status_t *harq_ack,
+                unsigned char subframe_tx,
+                unsigned char subframe_rx,
+                unsigned char *o_ACK,
+                uint8_t *pN_bundled,
+                uint8_t cw_idx)
+{
+  return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, pN_bundled, cw_idx, 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};
+uint8_t Np50[4]= {0,11,27,44};
+uint8_t Np75[4]= {0,16,41,66};
+uint8_t Np100[4]= {0,22,55,88};
+// This is part of the PUCCH allocation procedure (see Section 10.1 36.213)
+uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1)
+{
+  uint8_t *Np;
+
+  switch (N_RB_DL) {
+  case 6:
+    Np=Np6;
+    break;
+
+  case 15:
+    Np=Np15;
+    break;
+
+  case 25:
+    Np=Np25;
+    break;
+
+  case 50:
+    Np=Np50;
+    break;
+
+  case 75:
+    Np=Np75;
+    break;
+
+  case 100:
+    Np=Np100;
+    break;
+
+  default:
+    LOG_E(PHY,"get_Np() FATAL: unsupported N_RB_DL %d\n",N_RB_DL);
+    return(0);
+    break;
+  }
+
+  if (nCCE>=Np[2])
+    return(Np[2+plus1]);
+  else if (nCCE>=Np[1])
+    return(Np[1+plus1]);
+  else
+    return(Np[0+plus1]);
+}
+
+lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
+{
+
+  // if FDD return dummy value
+  if (frame_parms->frame_type == FDD)
+    return(SF_DL);
+
+  switch (frame_parms->tdd_config) {
+
+  case 1:
+    switch (subframe) {
+    case 0:
+    case 4:
+    case 5:
+    case 9:
+      return(SF_DL);
+      break;
+
+    case 2:
+    case 3:
+    case 7:
+    case 8:
+      return(SF_UL);
+      break;
+
+    default:
+      return(SF_S);
+      break;
+    }
+
+  case 3:
+    if  ((subframe<1) || (subframe>=5))
+      return(SF_DL);
+    else if ((subframe>1) && (subframe < 5))
+      return(SF_UL);
+    else if (subframe==1)
+      return (SF_S);
+    else  {
+      LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
+      return(255);
+    }
+
+  case 4:
+      if  ((subframe<1) || (subframe>=4))
+        return(SF_DL);
+      else if ((subframe>1) && (subframe < 4))
+        return(SF_UL);
+      else if (subframe==1)
+        return (SF_S);
+      else  {
+        LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
+        return(255);
+      }
+
+  case 5:
+        if  ((subframe<1) || (subframe>=3))
+          return(SF_DL);
+        else if ((subframe>1) && (subframe < 3))
+          return(SF_UL);
+        else if (subframe==1)
+          return (SF_S);
+        else  {
+          LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
+          return(255);
+        }
+    break;
+
+  default:
+    LOG_E(PHY,"subframe %d Unsupported TDD configuration %d\n",subframe,frame_parms->tdd_config);
+    mac_xface->macphy_exit("subframe x Unsupported TDD configuration");
+    return(255);
+
+  }
+}
+
+dci_detect_mode_t dci_detect_mode_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
+{
+  dci_detect_mode_t ret = 0;
+
+  static dci_detect_mode_t Table_8_2_3gpp_36_213[][10] = {
+     //subf0    , subf1     , subf2 , subf3         , subf4     , subf5     , subf6     , subf7 , subf8     , subf9
+      {UL_DL_DCI, UL_DL_DCI , NO_DCI    , NO_DCI    , NO_DCI    , UL_DL_DCI , UL_DL_DCI , NO_DCI, NO_DCI    , NO_DCI    },  // tdd0
+      {DL_DCI   , UL_DL_DCI , NO_DCI    , NO_DCI    , UL_DL_DCI , DL_DCI    , UL_DL_DCI , NO_DCI, NO_DCI    , UL_DL_DCI },  // tdd1
+      {DL_DCI   , DL_DCI    , NO_DCI    , UL_DL_DCI , DL_DCI    , DL_DCI    , DL_DCI    , NO_DCI, UL_DL_DCI , DL_DCI    },  // tdd2
+      {UL_DL_DCI, DL_DCI    , NO_DCI    , NO_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , UL_DL_DCI },  // tdd3
+      {DL_DCI   , DL_DCI    , NO_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , UL_DL_DCI },  // tdd4
+      {DL_DCI   , DL_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , DL_DCI    },  // tdd5
+      {UL_DL_DCI, UL_DL_DCI , NO_DCI    , NO_DCI    , NO_DCI    , UL_DL_DCI , UL_DL_DCI , NO_DCI, NO_DCI    , UL_DL_DCI }}; // tdd6
+
+
+  DevAssert(subframe>=0 && subframe<=9);
+  DevAssert((frame_parms->tdd_config)>=0 && (frame_parms->tdd_config)<=6);
+
+  if (frame_parms->frame_type == FDD) {
+    ret = UL_DL_DCI;
+  } else {
+    ret = Table_8_2_3gpp_36_213[frame_parms->tdd_config][subframe];
+  }
+
+  LOG_D(PHY, "subframe %d: detect UL_DCI=%d, detect DL_DCI=%d\n", subframe, (ret & UL_DCI)>0, (ret & DL_DCI)>0);
+  return ret;
+}
+
+lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe)
+{
+
+  return(subframe_select(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms,subframe));
+
+}
+
+uint8_t phich_subframe_to_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe)
+{
+
+  //LOG_D(PHY,"phich_subframe_to_harq_pid.c: frame %d, subframe %d\n",frame,subframe);
+  return(subframe2harq_pid(frame_parms,
+                           phich_frame2_pusch_frame(frame_parms,frame,subframe),
+                           phich_subframe2_pusch_subframe(frame_parms,subframe)));
+}
+
+unsigned int is_phich_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
+{
+
+  if (frame_parms->frame_type == FDD) {
+    return(1);
+  } else {
+    switch (frame_parms->tdd_config) {
+    case 1:
+      if ((subframe == 1) || (subframe == 4) || (subframe == 6) || (subframe == 9))
+        return(1);
+
+      break;
+
+    case 3:
+      if ((subframe == 0) || (subframe == 8) || (subframe == 9))
+        return(1);
+
+      break;
+
+    case 4:
+      if ((subframe == 8) || (subframe == 9) )
+        return(1);
+
+      break;
+
+    case 5:
+      if (subframe == 8)
+        return(1);
+
+      break;
+
+    default:
+      return(0);
+      break;
+    }
+  }
+
+  return(0);
+}
+
+
+#ifdef LOCALIZATION
+double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE_id, frame_t frame, sub_frame_t subframe, int32_t UE_tx_power_dB)
+{
+  // parameters declaration
+  int8_t Mod_id, CC_id;
+  //    int32_t harq_pid;
+  int32_t avg_power, avg_rssi, median_power, median_rssi, median_subcarrier_rss, median_TA, median_TA_update, ref_timestamp_ms, current_timestamp_ms;
+  char cqis[100], sub_powers[2048];
+  int len = 0, i;
+  struct timeval ts;
+  double sys_bw = 0;
+  uint8_t N_RB_DL;
+  LTE_DL_FRAME_PARMS *frame_parms = &eNB->frame_parms;
+
+  Mod_id = eNB->Mod_id;
+  CC_id = eNB->CC_id;
+  ref_timestamp_ms = eNB->ulsch[UE_id+1]->reference_timestamp_ms;
+
+  for (i=0; i<13; i++) {
+    len += sprintf(&cqis[len]," %d ", eNB->UE_stats[(uint32_t)UE_id].DL_subband_cqi[0][i]);
+  }
+
+  len = 0;
+
+  for (i=0; i<eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) {
+    len += sprintf(&sub_powers[len]," %d ", eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]);
+  }
+
+  gettimeofday(&ts, NULL);
+  current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;
+
+
+  LOG_D(LOCALIZE, " PHY: [UE %x/%d -> eNB %d], timestamp %d, "
+        "frame %d, subframe %d"
+        "UE Tx power %d dBm, "
+        "RSSI ant1 %d dBm, "
+        "RSSI ant2 %d dBm, "
+        "pwr ant1 %d dBm, "
+        "pwr ant2 %d dBm, "
+        "Rx gain %d dB, "
+        "TA %d, "
+        "TA update %d, "
+        "DL_CQI (%d,%d), "
+        "Wideband CQI (%d,%d), "
+        "DL Subband CQI[13] %s \n",
+        //          "timestamp %d, (%d active subcarrier) %s \n"
+        eNB->dlsch[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms,
+        frame,subframe,
+        UE_tx_power_dB,
+        eNB->UE_stats[(uint32_t)UE_id].UL_rssi[0],
+        eNB->UE_stats[(uint32_t)UE_id].UL_rssi[1],
+        dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]),
+        dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]),
+        eNB->rx_total_gain_eNB_dB,
+        eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset, // raw timing advance 1/sampling rate
+        eNB->UE_stats[(uint32_t)UE_id].timing_advance_update,
+        eNB->UE_stats[(uint32_t)UE_id].DL_cqi[0],eNB->UE_stats[(uint32_t)UE_id].DL_cqi[1],
+        eNB->measurements[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][0],
+        eNB->measurements[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][1],
+        cqis);
+  LOG_D(LOCALIZE, " PHY: timestamp %d, (%d active subcarrier) %s \n",
+        current_timestamp_ms,
+        eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier,
+        sub_powers);
+
+  N_RB_DL = frame_parms->N_RB_DL;
+
+  switch (N_RB_DL) {
+  case 6:
+    sys_bw = 1.92;
+    break;
+
+  case 25:
+    sys_bw = 7.68;
+    break;
+
+  case 50:
+    sys_bw = 15.36;
+    break;
+
+  case 100:
+    sys_bw = 30.72;
+    break;
+  }
+
+  if ((current_timestamp_ms - ref_timestamp_ms > eNB->ulsch[UE_id+1]->aggregation_period_ms)) {
+    // check the size of one list to be sure there was a message transmitted during the defined aggregation period
+
+    // make the reference timestamp == current timestamp
+    eNB->ulsch[UE_id+1]->reference_timestamp_ms = current_timestamp_ms;
+    int i;
+
+    for (i=0; i<10; i++) {
+      median_power = calculate_median(&eNB->ulsch[UE_id+1]->loc_rss_list[i]);
+      del(&eNB->ulsch[UE_id+1]->loc_rss_list[i]);
+      median_rssi = calculate_median(&eNB->ulsch[UE_id+1]->loc_rssi_list[i]);
+      del(&eNB->ulsch[UE_id+1]->loc_rssi_list[i]);
+      median_subcarrier_rss = calculate_median(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[i]);
+      del(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[i]);
+      median_TA = calculate_median(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[i]);
+      del(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[i]);
+      median_TA_update = calculate_median(&eNB->ulsch[UE_id+1]->loc_timing_update_list[i]);
+      del(&eNB->ulsch[UE_id+1]->loc_timing_update_list[i]);
+
+      if (median_power != 0)
+        push_front(&eNB->ulsch[UE_id+1]->tot_loc_rss_list,median_power);
+
+      if (median_rssi != 0)
+        push_front(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list,median_rssi);
+
+      if (median_subcarrier_rss != 0)
+        push_front(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list,median_subcarrier_rss);
+
+      if (median_TA != 0)
+        push_front(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list,median_TA);
+
+      if (median_TA_update != 0)
+        push_front(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list,median_TA_update);
+
+      initialize(&eNB->ulsch[UE_id+1]->loc_rss_list[i]);
+      initialize(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[i]);
+      initialize(&eNB->ulsch[UE_id+1]->loc_rssi_list[i]);
+      initialize(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[i]);
+      initialize(&eNB->ulsch[UE_id+1]->loc_timing_update_list[i]);
+    }
+
+    median_power = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_rss_list);
+    del(&eNB->ulsch[UE_id+1]->tot_loc_rss_list);
+    median_rssi = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list);
+    del(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list);
+    median_subcarrier_rss = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list);
+    del(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list);
+    median_TA = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list);
+    del(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list);
+    median_TA_update = calculate_median(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list);
+    del(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list);
+
+    initialize(&eNB->ulsch[UE_id+1]->tot_loc_rss_list);
+    initialize(&eNB->ulsch[UE_id+1]->tot_loc_subcarrier_rss_list);
+    initialize(&eNB->ulsch[UE_id+1]->tot_loc_rssi_list);
+    initialize(&eNB->ulsch[UE_id+1]->tot_loc_timing_advance_list);
+    initialize(&eNB->ulsch[UE_id+1]->tot_loc_timing_update_list);
+
+    double alpha = 2, power_distance, time_distance;
+    // distance = 10^((Ptx - Prx - A)/10alpha), A is a constance experimentally evaluated
+    // A includes the rx gain (eNB->rx_total_gain_eNB_dB) and hardware calibration
+    power_distance = pow(10, ((UE_tx_power_dB - median_power - eNB->rx_total_gain_eNB_dB + 133)/(10.0*alpha)));
+    // current measurements shows constant UE_timing_offset = 18
+       and timing_advance_update = 11 at 1m. at 5m, timing_advance_update = 12//
+    //time_distance = (double) 299792458*(eNB->UE_stats[(uint32_t)UE_id].timing_advance_update)/(sys_bw*1000000);
+    time_distance = (double) abs(eNB->UE_stats[(uint32_t)UE_id].timing_advance_update - 11) * 4.89;//  (3 x 108 x 1 / (15000 x 2048)) / 2 = 4.89 m
+
+    eNB->UE_stats[(uint32_t)UE_id].distance.time_based = time_distance;
+    eNB->UE_stats[(uint32_t)UE_id].distance.power_based = power_distance;
+
+    LOG_D(LOCALIZE, " PHY agg [UE %x/%d -> eNB %d], timestamp %d, "
+          "frame %d, subframe %d "
+          "UE Tx power %d dBm, "
+          "median RSSI %d dBm, "
+          "median Power %d dBm, "
+          "Rx gain %d dB, "
+          "power estimated r = %0.3f, "
+          " TA %d, update %d "
+          "TA estimated r = %0.3f\n"
+          ,eNB->dlsch[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms,
+          frame, subframe,
+          UE_tx_power_dB,
+          median_rssi,
+          median_power,
+          eNB->rx_total_gain_eNB_dB,
+          power_distance,
+          eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset, median_TA_update,
+          time_distance);
+
+    return 0;
+  } else {
+    avg_power = (dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]) + dB_fixed(eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]))/2;
+    avg_rssi = (eNB->UE_stats[(uint32_t)UE_id].UL_rssi[0] + eNB->UE_stats[(uint32_t)UE_id].UL_rssi[1])/2;
+
+    push_front(&eNB->ulsch[UE_id+1]->loc_rss_list[subframe],avg_power);
+    push_front(&eNB->ulsch[UE_id+1]->loc_rssi_list[subframe],avg_rssi);
+
+    for (i=0; i<eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) {
+      push_front(&eNB->ulsch[UE_id+1]->loc_subcarrier_rss_list[subframe], eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]);
+    }
+
+    push_front(&eNB->ulsch[UE_id+1]->loc_timing_advance_list[subframe], eNB->UE_stats[(uint32_t)UE_id].UE_timing_offset);
+    push_front(&eNB->ulsch[UE_id+1]->loc_timing_update_list[subframe], eNB->UE_stats[(uint32_t)UE_id].timing_advance_update);
+    return -1;
+  }
+}
+#endif
+LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t  CC_id,uint16_t rnti)
+{
+  int8_t UE_id;
+
+  if ((PHY_vars_eNB_g == NULL) || (PHY_vars_eNB_g[Mod_id] == NULL) || (PHY_vars_eNB_g[Mod_id][CC_id]==NULL)) {
+    LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",Mod_id,CC_id);
+    return NULL;
+  }
+
+  UE_id = find_ue(rnti, PHY_vars_eNB_g[Mod_id][CC_id]);
+
+  if (UE_id == -1) {
+    //    LOG_E(PHY,"get_UE_stats: UE with rnti %x not found\n",rnti);
+    return NULL;
+  }
+
+  return(&PHY_vars_eNB_g[Mod_id][CC_id]->UE_stats[(uint32_t)UE_id]);
+}
+
+int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *eNB)
+{
+
+  uint8_t i;
+
+  for (i=0; i<NUMBER_OF_UE_MAX_NB_IoT; i++) {
+    if ((eNB->dlsch[i]) &&
+        (eNB->dlsch[i][0]) &&
+        (eNB->dlsch[i][0]->rnti==rnti)) {
+      return(i);
+    }
+  }
+
+#ifdef CBA
+
+  for (i=0; i<NUM_MAX_CBA_GROUP; i++) {
+    if ((eNB->ulsch[i]) && // ue J is the representative of group j
+        (eNB->ulsch[i]->num_active_cba_groups) &&
+        (eNB->ulsch[i]->cba_rnti[i]== rnti))
+      return(i);
+  }
+
+#endif
+
+  return(-1);
+}
+*/
+int8_t find_ue_NB_IoT(uint16_t rnti, PHY_VARS_eNB_NB_IoT *eNB)
+{
+
+  uint8_t i;
+
+  for (i=0; i<NUMBER_OF_UE_MAX_NB_IoT; i++) {
+    if ((eNB->ndlsch[i]) &&
+        (eNB->ndlsch[i]->rnti==rnti)) {
+      return(i);
+    }
+  }
+
+  return(-1);
+}
+
+NB_IoT_DL_FRAME_PARMS* get_NB_IoT_frame_parms(module_id_t Mod_id, uint8_t  CC_id)
+{
+
+  return(&PHY_vars_eNB_NB_IoT_g[Mod_id][CC_id]->frame_parms);
+
+}
+
+/*
+
+LTE_DL_FRAME_PARMS* get_lte_frame_parms(module_id_t Mod_id, uint8_t  CC_id)
+{
+
+  return(&PHY_vars_eNB_g[Mod_id][CC_id]->frame_parms);
+
+}
+
+MU_MIMO_mode *get_mu_mimo_mode (module_id_t Mod_id, uint8_t  CC_id, rnti_t rnti)
+{
+  int8_t UE_id = find_ue( rnti, PHY_vars_eNB_g[Mod_id][CC_id] );
+
+  if (UE_id == -1)
+    return 0;
+
+  return &PHY_vars_eNB_g[Mod_id][CC_id]->mu_mimo_mode[UE_id];
+}
+
+int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subframe_tx)
+{
+  uint8_t isSubframeSRS   = 0; // SRS Cell Occasion
+
+  //ue->ulsch[eNB_id]->srs_active   = 0;
+  //ue->ulsch[eNB_id]->Nsymb_pusch  = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
+  if(frame_parms->soundingrs_ul_config_common.enabled_flag)
+  {
+
+    LOG_D(PHY," SRS SUBFRAMECONFIG: %d\n", frame_parms->soundingrs_ul_config_common.srs_SubframeConfig);
+
+      uint8_t  TSFC;
+      uint16_t deltaTSFC; // bitmap
+      uint8_t  srs_SubframeConfig;
+
+      // table resuming TSFC (Period) and deltaSFC (offset)
+      const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} };      // Table 5.5.3.3-2 3GPP 36.211 FDD
+      const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD
+
+      srs_SubframeConfig = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
+      if (FDD == frame_parms->frame_type)
+      {
+          // srs_SubframeConfig =< 14
+          deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
+          TSFC      = deltaTSFCTabType1[srs_SubframeConfig][1];
+      }
+      else
+      {
+          // srs_SubframeConfig =< 13
+          deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
+          TSFC      = deltaTSFCTabType2[srs_SubframeConfig][1];
+      }
+
+      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
+      uint16_t tmp = (subframe_tx %  TSFC);
+      if((1<<tmp) & deltaTSFC)
+      {
+          // This is a Sounding reference signal subframes
+          isSubframeSRS = 1;
+      }
+      LOG_D(PHY," ISTDD: %d, TSFC: %d, deltaTSFC: %d, AbsSubframeTX: %d.%d\n", frame_parms->frame_type, TSFC, deltaTSFC, frame_tx, subframe_tx);
+  }
+  return(isSubframeSRS);
+}
+
+void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset)
+{
+    if(TDD == frameType)
+    {
+        if(isrs<10)
+        {
+            mac_xface->macphy_exit("2 ms SRS periodicity not supported");
+        }
+
+        if((isrs>9)&&(isrs<15))
+        {
+            *psrsPeriodicity=5;
+            *psrsOffset=isrs-10;
+        }
+        if((isrs>14)&&(isrs<25))
+        {
+            *psrsPeriodicity=10;
+            *psrsOffset=isrs-15;
+        }
+        if((isrs>24)&&(isrs<45))
+        {
+            *psrsPeriodicity=20;
+            *psrsOffset=isrs-25;
+        }
+        if((isrs>44)&&(isrs<85))
+        {
+            *psrsPeriodicity=40;
+            *psrsOffset=isrs-45;
+        }
+        if((isrs>84)&&(isrs<165))
+        {
+            *psrsPeriodicity=80;
+            *psrsOffset=isrs-85;
+        }
+        if((isrs>164)&&(isrs<325))
+        {
+            *psrsPeriodicity=160;
+            *psrsOffset=isrs-165;
+        }
+        if((isrs>324)&&(isrs<645))
+        {
+            *psrsPeriodicity=320;
+            *psrsOffset=isrs-325;
+        }
+
+        if(isrs>644)
+        {
+            mac_xface->macphy_exit("Isrs out of range");
+        }
+
+    }
+    else
+    {
+        if(isrs<2)
+        {
+            *psrsPeriodicity=2;
+            *psrsOffset=isrs;
+        }
+        if((isrs>1)&&(isrs<7))
+        {
+            *psrsPeriodicity=5;
+            *psrsOffset=isrs-2;
+        }
+        if((isrs>6)&&(isrs<17))
+        {
+            *psrsPeriodicity=10;
+            *psrsOffset=isrs-7;
+        }
+        if((isrs>16)&&(isrs<37))
+        {
+            *psrsPeriodicity=20;
+            *psrsOffset=isrs-17;
+        }
+        if((isrs>36)&&(isrs<77))
+        {
+            *psrsPeriodicity=40;
+            *psrsOffset=isrs-37;
+        }
+        if((isrs>76)&&(isrs<157))
+        {
+            *psrsPeriodicity=80;
+            *psrsOffset=isrs-77;
+        }
+        if((isrs>156)&&(isrs<317))
+        {
+            *psrsPeriodicity=160;
+            *psrsOffset=isrs-157;
+        }
+        if((isrs>316)&&(isrs<637))
+        {
+            *psrsPeriodicity=320;
+            *psrsOffset=isrs-317;
+        }
+        if(isrs>636)
+        {
+            mac_xface->macphy_exit("Isrs out of range");
+        }
+    }
+}
+*/
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 504167bb2a1679df86f03bd3bb7ee7622c0d45b3..ba45d122ac05bd1f059d568615b6096bf3c1bbe7 100644
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -764,7 +764,8 @@ void generate_eNB_dlsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
       
 #endif
 
-      LOG_D(PHY,"Generating dlsch params for RNTI %x\n",dci_alloc->rnti);      
+      LOG_D(PHY,"Generating dlsch params for RNTI %x\n",dci_alloc->rnti);
+      //fill the dlsch structures
       generate_eNB_dlsch_params_from_dci(frame,
 					 subframe,
 					 &dci_alloc->dci_pdu[0],
@@ -911,7 +912,13 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
     T_INT(dci_alloc->firstCCE));
 }
 
-void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols) {
+void pdsch_procedures(PHY_VARS_eNB *eNB,
+					  eNB_rxtx_proc_t *proc,
+					  LTE_eNB_DLSCH_t *dlsch,
+					  LTE_eNB_DLSCH_t *dlsch1,
+					  LTE_eNB_UE_stats *ue_stats,
+					  int ra_flag,
+					  int num_pdcch_symbols) {
 
   int frame=proc->frame_tx;
   int subframe=proc->subframe_tx;
@@ -1008,6 +1015,20 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
 	  // Initialize indicator for first SR (to be cleared after ConnectionSetup is acknowledged)
 	  eNB->first_sr[(uint32_t)UE_id] = 1;
 	      
+
+	  /*
+	   * In FAPI style we don-t need to process the RAR because we have all the parameters for getting the MSG3 given by the
+	   * UL_CONFIG.request
+	   * 1) this data are given at the same time with the DLSCH PDU containing the RAR
+	   * 2) wee need to do a mapping of this parameters OAI->FAPI
+	   */
+
+
+	  /*this for MSG3*/
+	  //the problem of OAI is that i don't have any DCI0 for scheduling the info for getting Msg3 (because is direclty given in RAR)
+	  //so i should gather the information directly form RAR before sending it
+	  //In FAPI style apporach so we directly get it from the next UL-config given in the Sched_rsp
+	  //so most probably i don't care about it because i will receive all the information for get Msg3
 	  generate_eNB_ulsch_params_from_rar(DLSCH_pdu,
 					     frame,
 					     subframe,
@@ -1089,6 +1110,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
     LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
     // 36-212
     start_meas(&eNB->dlsch_encoding_stats);
+    //encoding
     eNB->te(eNB,
 	    DLSCH_pdu,
 	    num_pdcch_symbols,
@@ -1100,6 +1122,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
     stop_meas(&eNB->dlsch_encoding_stats);
     // 36-211
     start_meas(&eNB->dlsch_scrambling_stats);
+    //scrambling
     dlsch_scrambling(fp,
 		     0,
 		     dlsch,
@@ -1118,6 +1141,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
     start_meas(&eNB->dlsch_modulation_stats);
 
 
+    //modulation
     dlsch_modulation(eNB,
 		     eNB->common_vars.txdataF[0],
 		     AMP,
@@ -1422,7 +1446,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
 #endif
 
   // Check for SI activity
-
+  //MP: eNB->dlsch_SI->active is set by the function generate_dlsch_params_from_dci (depending on the DCI content)
   if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
 
     pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols);
@@ -2655,6 +2679,7 @@ void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) {
 
 }
 
+/*
 extern void *td_thread(void*);
 
 void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
@@ -2671,6 +2696,7 @@ void init_td_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_td) {
 
 }
 
+
 extern void *te_thread(void*);
 
 void init_te_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_te) {
@@ -2687,7 +2713,7 @@ void init_te_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_te) {
   pthread_create(&proc->pthread_te, attr_te, te_thread, (void*)&proc->tep);
 
 }
-
+*/
 
 void eNB_fep_full_2thread(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc_rxtx) {
 
diff --git a/openair1/SCHED/phy_procedures_lte_eNb_NB_IoT.c b/openair1/SCHED/phy_procedures_lte_eNb_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..f02965d951622d1159b5dca94be7f72fcca82c9b
--- /dev/null
+++ b/openair1/SCHED/phy_procedures_lte_eNb_NB_IoT.c
@@ -0,0 +1,1377 @@
+/*
+ * 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.0  (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_procedures_lte_eNB.c
+ * \brief Implementation of eNB procedures from 36.213 LTE specifications
+ * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas, Michele Paffetti, Nick Ho
+ * \date 2011
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk, michele.paffetti@studio.unibo.it, nick133371@gmail.com
+ * \note
+ * \warning
+ */
+
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/LTE_ESTIMATION/defs_NB_IoT.h"
+//#include "PHY/extern_NB_IoT.h" //where we get the global Sched_Rsp_t structure filled
+//#include "SCHED/defs.h"
+#include "SCHED/extern_NB_IoT.h"
+//#include "PHY/LTE_TRANSPORT/if4_tools.h"
+//#include "PHY/LTE_TRANSPORT/if5_tools.h"
+#include "RRC/LITE/proto_NB_IoT.h"
+#include "SIMULATION/TOOLS/defs.h"  // purpose: included for taus() function
+//#ifdef EMOS
+//#include "SCHED/phy_procedures_emos.h"
+//#endif
+
+// for NB-IoT
+#include "SCHED/defs_NB_IoT.h"
+
+//#define DEBUG_PHY_PROC (Already defined in cmake)
+//#define DEBUG_ULSCH
+
+//#include "LAYER2/MAC/extern.h"
+//#include "LAYER2/MAC/defs.h"
+#include "UTIL/LOG/log.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+
+#include "T.h"
+
+#include "assertions.h"
+#include "msc.h"
+
+#include <time.h>
+
+#if defined(ENABLE_ITTI)
+#   include "intertask_interface.h"
+#endif
+
+/*
+
+#if defined(FLEXRAN_AGENT_SB_IF)
+//Agent-related headers
+#include "ENB_APP/flexran_agent_extern.h"
+#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
+#include "LAYER2/MAC/flexran_agent_mac_proto.h"
+#endif
+*/
+
+//#define DIAG_PHY
+
+///#define NS_PER_SLOT 500000
+
+///#define PUCCH 1
+
+//DCI_ALLOC_t dci_alloc[8];
+
+///#ifdef EMOS
+///fifo_dump_emos_eNB emos_dump_eNB;
+///#endif
+
+int npdsch_rep_to_array[3]      = {4,8,16}; //TS 36.213 Table 16.4.1.3-3
+int sib1_startFrame_to_array[4] = {0,16,32,48};//TS 36.213 Table 16.4.1.3-4
+
+//New----------------------------------------------------
+//return -1 whenever no SIB1-NB transmission occur.
+//return sib1_startFrame when transmission occur in the current frame
+uint32_t is_SIB1_NB_IoT(const frame_t          frameP,
+                        long                   schedulingInfoSIB1,   //from the mib
+                        int                    physCellId,           //by configuration
+                        NB_IoT_eNB_NDLSCH_t   *ndlsch_SIB1
+                        )
+{
+  uint8_t    nb_rep=0; // number of sib1-nb repetitions within the 256 radio frames
+  uint32_t   sib1_startFrame;
+  uint32_t   sib1_period_NB_IoT = 256;//from specs TS 36.331 (rf)
+  uint8_t    index;
+  int        offset;
+  int        period_nb; // the number of the actual period over the 1024 frames
+
+        if(schedulingInfoSIB1 > 11 || schedulingInfoSIB1 < 0){
+          LOG_E(RRC, "is_SIB1_NB_IoT: schedulingInfoSIB1 value not allowed");
+          return 0;
+        }
+
+
+        //SIB1-NB period number
+        period_nb = (int) frameP/sib1_period_NB_IoT;
+
+
+        //number of repetitions
+        nb_rep = npdsch_rep_to_array[schedulingInfoSIB1%3];
+
+        //based on number of rep. and the physical cell id we derive the starting radio frame (TS 36.213 Table 16.4.1.3-3/4)
+        switch(nb_rep)
+        {
+        case 4:
+          //physCellId%4 possible value are 0,1,2,3
+          sib1_startFrame = sib1_startFrame_to_array[physCellId%4];
+          break;
+        case 8:
+          //physCellId%2possible value are 0,1
+          sib1_startFrame = sib1_startFrame_to_array[physCellId%2];
+          break;
+        case 16:
+          //physCellId%2 possible value are 0,1
+          if(physCellId%2 == 0)
+            sib1_startFrame = 0;
+          else
+            sib1_startFrame = 1; // the only case in which the starting frame is odd
+          break;
+        default:
+          LOG_E(RRC, "Number of repetitions %d not allowed", nb_rep);
+          return -1;
+        }
+
+        //check the actual frame w.r.t SIB1-NB starting frame
+        if(frameP < sib1_startFrame + period_nb*256){
+          LOG_T(RRC, "the actual frame %d is before the SIB1-NB starting frame %d of the period--> bcch_sdu_legnth = 0", frameP, sib1_startFrame + period_nb*256);
+          return -1;
+        }
+
+
+        //calculate offset between SIB1-NB repetitions (repetitions are equally spaced)
+        offset = (sib1_period_NB_IoT-(16*nb_rep))/nb_rep;
+
+        //loop over the SIB1-NB period
+        for( int i = 0; i < nb_rep; i++)
+        {
+          //find the correct sib1-nb repetition interval in which the actual frame is
+
+          //this is the start frame of a repetition
+          index = sib1_startFrame+ i*(16+offset) + period_nb*256;
+
+          //the actual frame is in a gap between two consecutive repetitions
+          if(frameP < index)
+          {
+              ndlsch_SIB1->sib1_rep_start      = 0;
+              ndlsch_SIB1->relative_sib1_frame = 0;
+                return -1;
+          }
+          //this is needed for ndlsch_procedure
+          else if(frameP == index)
+          {
+            //the actual frame is the start of a new repetition (SIB1-NB should be retransmitted)
+            ndlsch_SIB1->sib1_rep_start      = 1;
+            ndlsch_SIB1->relative_sib1_frame = 1;
+            return sib1_startFrame;
+          }
+          else
+            ndlsch_SIB1->sib1_rep_start = 0;
+
+          //check in the current SIB1_NB repetition
+          if(frameP>= index && frameP <= (index+15))
+          {
+            //find if the actual frame is one of the "every other frame in 16 continuous frame" in which SIB1-NB is transmitted
+
+            for(int y = 0; y < 16; y += 2) //every other frame (increment by 2)
+            {
+              if(frameP == index + y)
+              {
+                //this flag tell which is the number of the current frame w.r.t the 8th (over the continuous 16) in a repetition
+                ndlsch_SIB1->relative_sib1_frame = y/2 + 1; //1st, 2nd, 3rd,...
+                return sib1_startFrame;
+              }
+            }
+
+            //if we are here means that the frame was inside the repetition interval but not considered for SIB1-NB transmission
+            ndlsch_SIB1->relative_sib1_frame = 0;
+            return -1;
+         }
+
+        }
+
+        return -1;
+}
+
+
+
+
+
+
+/* For NB-IoT, we put NPBCH in later part, since it would be scheduled by MAC scheduler
+* It generates NRS/NPSS/NSSS
+*
+*/
+void common_signal_procedures_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc) 
+{
+  NB_IoT_DL_FRAME_PARMS   *fp       =  &eNB->frame_parms_NB_IoT;
+  int                     **txdataF =  eNB->common_vars.txdataF[0];
+  int                     subframe  =  proc->subframe_tx;
+  int                     frame     =  proc->frame_tx;
+  uint16_t                Ntti      =  10;                      //ntti = 10
+  int                     RB_IoT_ID;                            // XXX should be initialized (RB reserved for NB-IoT, PRB index)
+  int                     With_NSSS;                            // With_NSSS = 1; if the frame include a sub-Frame with NSSS signal
+  
+  /*NSSS only happened in the even frame*/
+  if(frame%2==0)
+    {
+      With_NSSS = 1;
+    }
+  else
+    {
+      With_NSSS = 0;
+    }
+    
+  /*NPSS when subframe 5*/
+  if(subframe == 5)
+    {
+      generate_npss_NB_IoT(txdataF,
+                           AMP,
+                           fp,
+                           3,
+                           0,
+                           RB_IoT_ID);
+    }
+    
+  /*NSSS when subframe 9 on even frame*/
+  else if((subframe == 9)&&(With_NSSS == 1))
+    {
+      generate_sss_NB_IoT(txdataF,
+                          AMP,
+                          fp,
+                          3,
+                          0,
+                          frame,
+                          RB_IoT_ID);
+    }
+
+  else
+  {
+    /*NRS*/
+    generate_pilots_NB_IoT(eNB,
+                           txdataF,
+                           AMP,
+                           Ntti,
+                           RB_IoT_ID,
+                           With_NSSS);
+  }
+  
+}
+
+void phy_procedures_eNB_uespec_RX_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc,UL_IND_t *UL_INFO)
+{
+  //RX processing for ue-specific resources (i
+
+  uint32_t                  ret=0,i,j,k;
+  uint32_t                  harq_pid;   // round;
+  int                       sync_pos;
+  uint16_t                  rnti=0;
+  uint8_t                   access_mode;
+  NB_IoT_DL_FRAME_PARMS     *fp=&eNB->frame_parms_NB_IoT;
+
+  const int subframe    =   proc->subframe_rx;
+  const int frame       =   proc->frame_rx;
+
+  // add hyper subframe here
+  
+  /*NB-IoT IF module Common setting*/
+
+  UL_INFO->module_id    = eNB->Mod_id;
+  UL_INFO->CC_id        = eNB->CC_id;
+  UL_INFO->frame        =  frame;
+  UL_INFO->subframe     = subframe;
+
+  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
+
+  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
+    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms_NB_IoT.samples_per_tti],
+             eNB->frame_parms_NB_IoT.samples_per_tti * 4));
+
+  //if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;
+
+  //check if any RB using in this UL subframe
+  eNB->rb_mask_ul[0] = 0;
+  eNB->rb_mask_ul[1] = 0;
+  eNB->rb_mask_ul[2] = 0;
+  eNB->rb_mask_ul[3] = 0;
+
+  // Check for active processes in current subframe
+  // NB-IoT subframe2harq_pid is in dci_tools, always set the frame type to FDD, this would become simpler.
+  harq_pid = subframe2harq_pid_NB_IoT(fp,frame,subframe);
+  // delete the cba
+  // delete the srs
+  /*Loop over the UE, i is the UE ID */
+  for (i=0; i<NUMBER_OF_UE_MAX_NB_IoT; i++) 
+    {
+
+      // delete srs 
+      // delete Pucch procedure
+      // check for Msg3
+      if (eNB->mac_enabled==1) 
+        {
+          if (eNB->UE_stats[i].mode == RA_RESPONSE_NB_IoT) 
+            {
+	             /*Process Msg3 TODO*/
+              //process_Msg3(eNB,proc,i,harq_pid);
+            }
+        }
+
+      eNB->pusch_stats_rb[i][(frame*10)+subframe]    = -63;
+      eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
+      eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = -63;
+
+      /*Check if this UE is has ULSCH scheduling*/
+      if ((eNB->nulsch[i]) &&
+          (eNB->nulsch[i]->rnti>0) &&
+          (eNB->nulsch[i]->harq_process->subframe_scheduling_flag==1)) 
+        {
+          // UE is has ULSCH scheduling
+          //////////////////////////////////////round = eNB->nulsch[i]->harq_process->round; //commented to remove warning, to be added if round is used
+          /*NB-IoT The nb_rb always set to 1 */
+          for (int rb=0;rb<=eNB->nulsch[i]->harq_process->nb_rb;rb++) 
+            {
+	             int rb2 = rb+eNB->nulsch[i]->harq_process->first_rb;
+               eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
+            }
+
+          /*Log for what kind of the ULSCH Reception*/
+
+          /*Calculate for LTE C-RS*/
+          //nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
+
+          //eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +nPRS)%12;
+
+          if (fp->frame_type == FDD_NB_IoT ) 
+            {
+              int sf = (subframe<4) ? (subframe+6) : (subframe-4);
+              /*After Downlink Data transmission, simply have a notice to received ACK from PUCCH, I think it's not use for now */
+              if (eNB->ndlsch[i]->subframe_tx[sf]>0) // we have downlink transmission
+                { 
+                  eNB->nulsch[i]->harq_process->O_ACK = 1;
+                } 
+              else 
+                {
+                  eNB->nulsch[i]->harq_process->O_ACK = 0;
+                }
+            }
+
+          eNB->pusch_stats_rb[i][(frame*10)+subframe]    = eNB->nulsch[i]->harq_process->nb_rb;
+          eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->nulsch[i]->harq_process->round;
+          eNB->pusch_stats_mcs[i][(frame*10)+subframe]   = eNB->nulsch[i]->harq_process->mcs;
+
+  
+
+          rx_ulsch_NB_IoT(eNB,proc,
+                          eNB->UE_stats[i].sector,  // this is the effective sector id
+                          i,
+                          eNB->nulsch,
+                          0);
+
+          ret = ulsch_decoding_NB_IoT(eNB,proc,
+                                      i,
+                                      0, // control_only_flag
+                                      eNB->nulsch[i]->harq_process->V_UL_DAI,
+			                                eNB->nulsch[i]->harq_process->nb_rb>20 ? 1 : 0);
+
+          //compute the expected ULSCH RX power (for the stats)
+          eNB->nulsch[(uint32_t)i]->harq_process->delta_TF = get_hundred_times_delta_IF_eNB_NB_IoT(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
+          eNB->UE_stats[i].nulsch_decoding_attempts[harq_pid][eNB->nulsch[i]->harq_process->round]++;
+          eNB->nulsch[i]->harq_process->subframe_scheduling_flag=0;
+          if (eNB->nulsch[i]->harq_process->cqi_crc_status == 1) {
+
+              extract_CQI_NB_IoT(eNB->nulsch[i]->harq_process->o,
+                                 eNB->nulsch[i]->harq_process->uci_format,
+                                 &eNB->UE_stats[i],
+                                 fp->N_RB_DL,
+                                 &rnti, &access_mode);
+            
+              eNB->UE_stats[i].rank = eNB->nulsch[i]->harq_process->o_RI[0];
+          }
+
+          if (ret == (1+MAX_TURBO_ITERATIONS)) {
+
+              T(T_ENB_PHY_ULSCH_UE_NACK,
+                T_INT(eNB->Mod_id),
+                T_INT(frame),
+                T_INT(subframe),
+                T_INT(i),
+                T_INT(eNB->nulsch[i]->rnti),
+                T_INT(harq_pid));
+
+              eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->nulsch[i]->harq_process->round]++;
+              eNB->nulsch[i]->harq_process->phich_active = 1;
+              eNB->nulsch[i]->harq_process->phich_ACK = 0;
+              eNB->nulsch[i]->harq_process->round++;
+
+              LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->nulsch[i]->harq_process->round);
+
+          if (eNB->nulsch[i]->Msg3_flag == 1) 
+          {
+	             /*dump_ulsch(eNB,proc,i);
+	             exit(-1);*/
+
+               /*In NB-IoT MSG3 */
+                // activate retransmission for Msg3 (signalled to UE PHY by DCI
+                eNB->nulsch[(uint32_t)i]->Msg3_active = 1;
+                /* Need to check the procedure for NB-IoT (MSG3) retransmission
+                get_Msg3_alloc_ret(fp,subframe,frame,&eNB->ulsch[i]->Msg3_frame,&eNB->ulsch[i]->Msg3_subframe);
+                mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);
+                */
+                T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
+                  T_INT(i), T_INT(eNB->nulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
+                  T_INT(eNB->nulsch[i]->Msg3_frame), T_INT(eNB->nulsch[i]->Msg3_subframe));     
+          } // This is Msg3 error
+          else 
+          { //normal ULSCH
+              if (eNB->nulsch[i]->harq_process->round== eNB->nulsch[i]->Mlimit) 
+                {
+                  eNB->nulsch[i]->harq_process->round=0;
+                  eNB->nulsch[i]->harq_process->phich_active=0;
+                  eNB->UE_stats[i].ulsch_errors[harq_pid]++;
+                  eNB->UE_stats[i].ulsch_consecutive_errors++; 
+                  /*if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
+		                dump_ulsch(eNB,proc,i);
+	 	              exit(-1);
+                  }*/
+	                // indicate error to MAC
+	                if (eNB->mac_enabled == 1)
+                    {
+                      //instead rx_sdu to report The Uplink data not received successfully to MAC
+                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag = 1;
+                       UL_INFO->crc_ind.number_of_crcs++;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti      = eNB->nulsch[i]->rnti;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data                        = NULL;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length   = 0;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid  = harq_pid;
+                       UL_INFO->RX_NPUSCH.number_of_pdus++;
+                    }
+                }
+            }
+        }  // ulsch in error
+        else 
+          {
+            T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->nulsch[i]->rnti),
+              T_INT(harq_pid));
+
+          // Delete MSG3  log for the PHICH 
+
+          for (j=0; j<fp->nb_antennas_rx; j++)
+          //this is the RSSI per RB
+          eNB->UE_stats[i].UL_rssi[j] =
+            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j] * (eNB->nulsch[i]->harq_process->nb_rb*12) / fp->ofdm_symbol_size) - eNB->rx_total_gain_dB -
+            hundred_times_log10_NPRB_NB_IoT[eNB->nulsch[i]->harq_process->nb_rb-1]/100 -
+            get_hundred_times_delta_IF_eNB_NB_IoT(eNB,i,harq_pid, 0)/100;
+          //for NB-IoT PHICH not work
+	        /*eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
+          eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;*/
+          eNB->nulsch[i]->harq_process->round = 0;
+          eNB->UE_stats[i].ulsch_consecutive_errors = 0;
+
+          if (eNB->nulsch[i]->Msg3_flag == 1) 
+            {
+	            if (eNB->mac_enabled==1) 
+                {
+	                LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
+		                    eNB->Mod_id,frame,harq_pid,i);
+	                if (eNB->mac_enabled)
+                    {
+                      // store successful MSG3 in UL_Info instead rx_sdu
+                      (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
+                      UL_INFO->crc_ind.number_of_crcs++;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti       = eNB->nulsch[i]->rnti;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data                         = eNB->nulsch[i]->harq_process->b;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length    = eNB->nulsch[i]->harq_process->TBS>>3;
+                      (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid   = harq_pid;
+                      UL_INFO->RX_NPUSCH.number_of_pdus++;
+                    }
+
+	                /* Need check if this needed in NB-IoT
+	                // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
+	                if (eNB->ulsch[i]->Msg3_flag == 0 ) {
+	               eNB->UE_stats[i].mode = PRACH;
+	               mac_xface->cancel_ra_proc(eNB->Mod_id,
+					       eNB->CC_id,
+					       frame,
+					       eNB->UE_stats[i].crnti);
+	               mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
+	               eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
+	               } // Msg3_flag == 0*/
+	    
+	            } // mac_enabled==1
+
+            eNB->UE_stats[i].mode     = PUSCH;
+            eNB->nulsch[i]->Msg3_flag = 0;
+
+	          LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",eNB->Mod_id,frame,subframe,i);
+
+            /*Init HARQ parameters, need to check*/
+            for (k=0; k<8; k++) 
+              { //harq_processes
+                for (j=0; j<eNB->ndlsch[i]->Mlimit; j++) 
+                  {
+                    eNB->UE_stats[i].dlsch_NAK[k][j]    = 0;
+                    eNB->UE_stats[i].dlsch_ACK[k][j]    = 0;
+                    eNB->UE_stats[i].dlsch_trials[k][j] = 0;
+                  }
+
+                eNB->UE_stats[i].dlsch_l2_errors[k]       = 0;
+                eNB->UE_stats[i].ulsch_errors[k]          = 0;
+                eNB->UE_stats[i].ulsch_consecutive_errors = 0;
+
+                for (j=0; j<eNB->nulsch[i]->Mlimit; j++) 
+                  {
+                    eNB->UE_stats[i].nulsch_decoding_attempts[k][j]     = 0;
+                    eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j] = 0;
+                    eNB->UE_stats[i].ulsch_round_errors[k][j]           = 0;
+                    eNB->UE_stats[i].ulsch_round_fer[k][j]              = 0;
+                  }
+              }
+
+            eNB->UE_stats[i].dlsch_sliding_cnt  = 0;
+            eNB->UE_stats[i].dlsch_NAK_round0   = 0;
+            eNB->UE_stats[i].dlsch_mcs_offset   = 0;
+          } // Msg3_flag==1
+	       else 
+          {  // Msg3_flag == 0
+	          if (eNB->mac_enabled == 1) 
+              {
+                  // store successful Uplink data in UL_Info instead rx_sdu
+                  (UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag  = 0;
+                  UL_INFO->crc_ind.number_of_crcs++;
+                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti       = eNB->nulsch[i]->rnti;
+                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data                         = eNB->nulsch[i]->harq_process->b;
+                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length    = eNB->nulsch[i]->harq_process->TBS>>3;
+                  (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.harq_pid   = harq_pid;
+                  UL_INFO->RX_NPUSCH.number_of_pdus++;
+	    
+	            } // mac_enabled==1
+          } // Msg3_flag == 0
+
+            // estimate timing advance for MAC
+              sync_pos                               = NB_IoT_est_timing_advance_pusch(eNB,i);
+              eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
+
+      }  // ulsch not in error
+
+
+      // Process HARQ only in NPUSCH
+      /*process_HARQ_feedback(i,
+                            eNB,proc,
+                            1, // pusch_flag
+                            0,
+                            0,
+                            0);*/
+
+
+      
+
+    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
+
+
+    // update ULSCH statistics for tracing
+
+
+
+
+  } // loop i=0 ... NUMBER_OF_UE_MAX-1
+
+}
+
+#undef DEBUG_PHY_PROC
+
+/*Generate eNB ndlsch params for NB-IoT from the NPDCCH PDU of the DCI, modify the input to the Sched Rsp variable*/
+
+void generate_eNB_dlsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t * proc,nfapi_dl_config_request_pdu_t *dl_config_pdu) 
+{
+  int                      UE_id         =  -1;
+  NB_IoT_DL_FRAME_PARMS    *fp           =  &eNB->frame_parms_NB_IoT;
+  int                      frame         =  proc->frame_tx;
+  int                      subframe      =  proc->subframe_tx;
+  DCI_CONTENT              *DCI_Content; 
+  DCI_format_NB_IoT_t      DCI_format;
+  NB_IoT_eNB_NDLSCH_t      *ndlsch;
+  NB_IoT_eNB_NPDCCH_t      *npdcch;
+
+
+
+  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
+
+  // check DCI format is N1 (format 0)
+  if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 0)
+    {
+      //check DCI format N1 is for RAR  rnti_type  in FAPI specs table 4-45
+      if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type == 1)
+        {
+
+    	  //mapping the fapi parameters to the oai parameters
+
+          DCI_format = DCIFormatN1_RAR;
+
+          //DCI format N1 to RAR
+          DCI_Content->DCIN1_RAR.type           = 1;
+          DCI_Content->DCIN1_RAR.orderIndicator = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication;
+          DCI_Content->DCIN1_RAR.Scheddly       = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
+          DCI_Content->DCIN1_RAR.ResAssign      = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
+          DCI_Content->DCIN1_RAR.mcs            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
+          DCI_Content->DCIN1_RAR.RepNum			    = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
+          DCI_Content->DCIN1_RAR.ndi            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
+          DCI_Content->DCIN1_RAR.HARQackRes     = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
+          DCI_Content->DCIN1_RAR.DCIRep         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;
+
+          //TODO calculate the number of common repetitions
+          //fp->nprach_config_common.number_repetition_RA = see TS 36.213 Table 16.1-3
+
+          // fill the dlsch_ra_NB structure for RAR, and packed the DCI PDU
+
+          ndlsch               =  eNB->ndlsch_ra;
+          ndlsch->ndlsch_type  =  RAR;
+
+          LOG_D(PHY,"Generating dlsch params for RA_RNTI and packing DCI\n");
+          generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
+                                                    frame,
+                                                    subframe,
+                                                    DCI_Content,
+                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
+                                                    DCI_format,
+                                                    ndlsch,
+                                                    fp,
+                                                    dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
+												                            dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol);
+
+          //eNB->dlsch_ra_NB->nCCE[subframe] = eNB->DCI_pdu->dci_alloc.firstCCE;
+        }
+      else
+        { //managing data
+
+    	  //TODO target/SIMU/USER?init_lte/init_lte_eNB we should allocate the ndlsch structures
+    	  UE_id = find_ue_NB_IoT(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti, eNB);
+    	  AssertFatal(UE_id != -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
+
+
+    	  	  //mapping the fapi parameters to the oai parameters
+
+    	  	  DCI_format = DCIFormatN1;
+
+              //DCI format N1 to DLSCH
+              DCI_Content->DCIN1.type           = 1;
+              DCI_Content->DCIN1.orderIndicator = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication;
+              DCI_Content->DCIN1.Scheddly       = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay;
+              DCI_Content->DCIN1.ResAssign      = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment;
+              DCI_Content->DCIN1.mcs            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs;
+              DCI_Content->DCIN1.RepNum			    = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number;
+              DCI_Content->DCIN1.ndi            = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator;
+              DCI_Content->DCIN1.HARQackRes     = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource;
+              DCI_Content->DCIN1.DCIRep         = dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number;
+
+
+              //set the NPDCCH UE-specific structure  (calculate R)
+              npdcch=eNB->npdcch[(uint8_t)UE_id];
+              AssertFatal(npdcch != NULL, "NPDCCH structure for UE specific is not exist\n");
+              npdcch->repetition_idx = 0; //this is used for the encoding mechanism to understand that is the first transmission
+
+              if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level) //whenever aggregation level is =1 we have only 1 repetition for USS
+              npdcch->repetition_number = 1;
+              else
+              {
+            	  //see TS 36.213 Table 16.1-1
+              }
+
+
+              //fill the ndlsch structure for UE and packed the DCI PD
+
+        	  ndlsch = eNB->ndlsch[(uint8_t)UE_id]; //in the old implementation they also consider UE_id = 1;
+        	  ndlsch->ndlsch_type = UE_Data;
+
+              //parameters we don't consider pdsch config dedicated since not calling the phy config dedicated step2
+
+        	  LOG_D(PHY,"Generating dlsch params for DCIN1 data and packing DCI\n");
+            generate_eNB_dlsch_params_from_dci_NB_IoT(eNB,
+                                                      frame,
+                                                      subframe,
+                                                      DCI_Content,
+                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti,
+                                                      DCI_format,
+                                                      ndlsch,
+                                                      fp,
+                                                      dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level,
+													                            dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.start_symbol); 
+
+              //eNB->ndlsch[(uint8_t)UE_id]->nCCE[subframe] = eNB->DCI_pdu->dci_alloc[i].firstCCE;
+
+
+        }
+    }
+  else if(dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format == 1)
+    { 
+      DCI_format = DCIFormatN2;
+      LOG_D(PHY,"Paging procedure not implemented\n");
+    }
+  else
+    LOG_E(PHY,"unknown DCI format for NB-IoT DL\n");
+
+
+}
+
+
+
+void generate_eNB_ulsch_params_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc,nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu) {
+
+  int UE_id = -1;
+  //int harq_pid = 0;
+
+  DCI_CONTENT *DCI_Content;
+  DCI_Content = (DCI_CONTENT*) malloc(sizeof(DCI_CONTENT));
+
+  //mapping the fapi parameters to the OAI parameters
+  DCI_Content->DCIN0.type       = 0;
+  DCI_Content->DCIN0.scind      = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication;
+  DCI_Content->DCIN0.ResAssign  = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication;
+  DCI_Content->DCIN0.mcs        = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.mcs;
+  DCI_Content->DCIN0.ndi        = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.new_data_indicator;
+  DCI_Content->DCIN0.Scheddly   = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.scheduling_delay;
+  DCI_Content->DCIN0.RepNum     = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.repetition_number;
+  DCI_Content->DCIN0.rv         = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.redudancy_version;
+  DCI_Content->DCIN0.DCIRep     = hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.dci_subframe_repetition_number;
+
+
+
+  UE_id = find_ue_NB_IoT(hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti, eNB);
+  AssertFatal(UE_id == -1, "no ndlsch context available or no ndlsch context corresponding to that rnti\n");
+
+
+  /*Log for generate ULSCH DCI*/
+
+  generate_eNB_ulsch_params_from_dci_NB_IoT(eNB,
+                                            proc,
+                                            DCI_Content,
+                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti,
+                                            DCIFormatN0,
+                                            UE_id,
+                                            hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level,
+										                        hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.start_symbol);  
+
+  
+  //LOG for ULSCH DCI Resource allocation
+  //CBA is not used in NB-IoT
+    eNB->nulsch[UE_id]->harq_process->subframe_scheduling_flag = 1;
+  
+}
+
+
+
+/*
+ * for NB-IoT ndlsch procedure
+ * this function is called by the PHy procedure TX in 3 possible occasion:
+ * 1) we manage BCCH pdu (SI)
+ * 2) we manage RA dlsch pdu
+ * 3) UE-specific dlsch pdu
+ * ** we need to know if exist and which value has the eutracontrolRegionSize (TS 36.213 ch 16.4.1.4) whenever we are in In-band mode
+ * ** CQI and PMI are not present in NB-IoT
+ * ** redundancy version exist only in UL for NB-IoT and not in DL
+ */
+void npdsch_procedures(PHY_VARS_eNB_NB_IoT      *eNB,
+						           eNB_rxtx_proc_t   *proc,     //Context data structure for RX/TX portion of subframe processing
+						           NB_IoT_eNB_NDLSCH_t      *ndlsch,
+						           //int num_pdcch_symbols,            //(BCOM says are not needed
+						           uint8_t                  *pdu
+									     )
+{
+  int                     frame                   =   proc->frame_tx;
+  int                     subframe                =   proc->subframe_tx;
+  NB_IoT_DL_eNB_HARQ_t    *ndlsch_harq            =   ndlsch->harq_process;
+  int                     input_buffer_length     =   ndlsch_harq->TBS/8;         // get in byte //the TBS is set in generate_dlsch_param
+  NB_IoT_DL_FRAME_PARMS   *fp                     =   &eNB->frame_parms_NB_IoT;
+  int                     G;
+  uint8_t                 *DLSCH_pdu              =   NULL;
+  uint8_t                 DLSCH_pdu_tmp[input_buffer_length+4];                   //[768*8];
+  //uint8_t DLSCH_pdu_rar[256];
+  int                     i;
+
+  LOG_D(PHY,
+	      "[eNB %"PRIu8"][PDSCH rnti%"PRIx16"] Frame %d, subframe %d: Generating PDSCH/DLSCH with input size = %"PRIu16", mcs %"PRIu8"(round %"PRIu8")\n",
+	      eNB->Mod_id,
+	      ndlsch->rnti,
+	      frame, subframe, input_buffer_length,
+	      ndlsch_harq->mcs,
+	      ndlsch_harq->round
+        );
+
+  if(ndlsch_harq->round == 0) { //first transmission so we encode... because we generate the sequence
+
+    if (eNB->mac_enabled == 1) { // set in lte-softmodem/main line 1646
+
+    	  DLSCH_pdu = pdu;
+
+  	  /*
+  	   * we don't need to manage the RAR here since should be managed in the MAC layer for two reasons:
+  	   * 1)we should receive directly the pdu containing the RAR from the MAC in the schedule_response
+  	   * 2)all the parameters for getting the MSG3 should be given by the UL_CONFIG.request (all inside the next schedule_response function)
+  	   *
+  	   */
+
+    	  //fill_rar shouduld be in the MAC
+    	  //cancel ra procedure should be in the mac
+    	  //scheduling request not implemented in NB-IoT
+    	  //nulsch_param configuration for MSG3 should be considered in handling UL_Config.request
+    	  //(in particular the nulsch structure for RAR is distinguished based on the harq_process->rar_alloc and the particular subframe in which we should have Msg3)
+    }
+
+    else {  //XXX we should change taus function???
+
+      DLSCH_pdu = DLSCH_pdu_tmp;
+
+      for (i=0; i<input_buffer_length; i++)
+
+	       DLSCH_pdu[i] = (unsigned char)(taus()&0xff);
+    }
+  }
+  else {
+	  //We are doing a retransmission (harq round > 0
+    #ifdef DEBUG_PHY_PROC
+    #ifdef DEBUG_DLSCH
+    LOG_D(PHY,"[eNB] This DLSCH is a retransmission\n");
+    #endif
+    #endif
+  }
+
+  if (eNB->abstraction_flag==0) { // used for simulation of the PHY??
+
+
+	  //we can distinguish among the different kind of NDLSCH structure (example)
+	  switch(ndlsch->ndlsch_type)
+	  {
+	  case SIB1:
+		  break;
+	  case SI_Message:
+		  break;
+	  case RAR: //maybe not needed
+		  break;
+	  case UE_Data: //maybe not needed
+		  break;
+	  }
+
+
+	 /*
+	  * in any case inside the encoding procedure is re-checked if this is round 0 or no
+	  * in the case of harq_process round = 0 --> generate the sequence and put it into the parameter *c[r]
+	  * otherwise do nothing(only rate maching)
+	  */
+
+
+	/*
+	 * REASONING:
+	 * Encoding procedure will generate a Table with encoded data ( in ndlsch structure)
+	 * The table will go in input to the scrambling
+	 * --we should take care if there are repetitions of data or not because scrambling should be called at the first frame and subframe in which each repetition
+	 * begin (see params Nf, Ns)
+	 */
+
+
+    // 36-212
+    //encoding---------------------------
+
+    /*
+     *
+     * REASONING:
+	 * Encoding procedure will generate a Table with encoded data ( in ndlsch structure)
+	 * The table will go in input to the scrambling
+	 * --we should take care if there are repetitions of data or not because scrambling should be called at the first frame and subframe in which each repetition
+	 * 	begin (see params Nf, Ns)
+     *
+     * we should have as an iput parameter also G for the encoding based on the switch/case over eutracontrolRegionSize (if exist) and operationModeInfo if defined
+     * NB: switch case of G is the same for npdsch and npdcch
+     *
+     * npdsch_start symbol index
+     * -refers to TS 36.213 ch 16.4.1.4:
+     * -if subframe k is a subframe for receiving the SIB1-NB
+     *	-- if operationModeInfo set to 00 or 01 (in band) --> npdsch_start_sysmbol = 3
+     *	-- otherwise --> npdsch_start_symbol = 0
+     * -if the k subframe is not for SIB1-NB
+     *	--npdsch_start_symbol = eutracontrolregionsize (defined for in-band operating mode (mode 0,1 for FAPI specs) and take values 1,2,3 [units in number of OFDM symbol])
+     * - otherwise --> npdsch_start_symbol = 0
+     * (is the starting OFDM for the NPDSCH transmission in the first slot in a subframe k)
+     * FAPI style:
+     * npdsch_start symbol is stored in the ndlsch structure from the reception of the NPDLSCH PDU in the DL_CONFIG.request (so should be set by the MAC and put inside the schedule response)
+     * Nsf needed as an input (number of subframe)-->inside harq_process of ndlsch
+     */
+
+    switch(ndlsch->npdsch_start_symbol)
+    {
+  	  case 0:
+  		  G = 304;
+	 	  break;
+  	  case 1:
+  		  G = 240;
+  		break;
+  	  case 2:
+  		  G = 224;
+  		break;
+  	  case 3:
+  		  G =200;
+  		break;
+  	  default:
+  		  LOG_E (PHY,"npdsch_start_index has unwanted value\n");
+  		break;
+
+    }
+    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
+    LOG_I(PHY, "NB-IoT Encoding step\n");
+
+    //    eNB->te(eNB,
+    //	    DLSCH_pdu,
+    //	    num_pdcch_symbols,
+    //	    dlsch,
+    //	    frame,subframe,
+    //	    &eNB->dlsch_rate_matching_stats,
+    //	    &eNB->dlsch_turbo_encoding_stats,
+    //	    &eNB->dlsch_interleaving_stats);
+
+
+   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
+
+    // 36-211
+    //scrambling-------------------------------------------
+
+   // start_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
+    LOG_I(PHY, "NB-IoT Scrambling step\n");
+
+    /*
+     * SOME RELEVANT FACTS:
+     *
+     *
+     */
+
+      //    dlsch_scrambling(fp,
+      //		     0,
+      //		     dlsch,
+      //		     get_G(fp,
+      //			   dlsch_harq->nb_rb,
+      //			   dlsch_harq->rb_alloc,
+      //			   get_Qm(dlsch_harq->mcs),
+      //			   dlsch_harq->Nl,
+      //			   num_pdcch_symbols,
+      //			   frame,subframe,
+      //			   0),
+      //		     0,
+      //		     subframe<<1);
+
+    //stop_meas_NB_IoT(&eNB->dlsch_scrambling_stats);
+
+
+    //modulation-------------------------------------------
+    //start_meas_NB_IoT(&eNB->dlsch_modulation_stats);
+    LOG_I(PHY, "NB-IoT Modulation step\n");
+
+    //    dlsch_modulation(eNB,
+    //		     eNB->common_vars.txdataF[0],
+    //		     AMP,
+    //		     subframe,
+    //		     num_pdcch_symbols,
+    //		     dlsch,
+    //		     dlsch1);
+
+    //stop_meas_NB_IoT(&eNB->dlsch_modulation_stats);
+  }
+
+
+#ifdef PHY_ABSTRACTION
+  else {
+    //start_meas_NB_IoT(&eNB->dlsch_encoding_stats);
+    //dlsch_encoding_emul(eNB,
+			//DLSCH_pdu,
+			//dlsch);
+   // stop_meas_NB_IoT(&eNB->dlsch_encoding_stats);
+  }
+
+#endif
+  ndlsch->active = 0;
+}
+
+
+extern int oai_exit;
+
+/*
+ * ASSUMPTION
+ *
+ * The MAC schedule the schedule_response in a SUBFRAME BASE (at least because otherwise we have problem with our assumptions on SI transmission)
+ *
+ *Since in FAPI specs seems to not manage the information for the sceduling of system information:
+ * Assume that the MAC layer manage the scheduling for the System information (SI messages) transmission while MIB and SIB1 are done directly at PHY layer
+ * This means that the MAC scheduler will send to the PHY the NDLSCH PDU and MIB PDU (DL_CONFIG.request)each time they should be transmitted. In particular:
+ ***MIB-NB
+ *schedule_response containing a n-BCH PDU is transmitted only at the beginning of the MIB period, then repetitions are made directly by the PHY layer (see FAPI specs pag 94 N-BCH 3.2.4.2)
+ *if no new N-BCH PDU is trasmitted at SFN mod 64=0 then stop MIB transmission
+ ***SIB1-NB
+ *schedule response containing a NDLSCH pdu (with appropiate configuration) will be transmitted only at the beginning of each SIB1-NB period (256 rf)
+ *then repetitions are managed directly by the PHY layer
+ *if no new NDLSCH pdu (configured for SIB1-NB) at SFN mod 256 = 0 is transmitted. stop SIB1-NB transmission
+ ****SI Messages
+ * -schedule_response is transmitted by the MAC in every subframe needed for the SI transmission (NDLSCH should have a proper configuration)
+ * -if the schedule_response carry any SDU for SI-Message (SDU!= NULL)--> put the SDU in the PHY buffer to be encoded ecc... and start the transmission
+ * -if the schedule_response not carry any SDU (SDU == NULL) but NDLSCH is properly set for SI, then PHY continue transmit the remaining part of the previous SDU
+ * (this because the PHY layer have no logic of repetition_pattern, si_window ecc.. so should be continuously instructed the PHY when to transmit.
+ *
+ * Furthermore, SI messages are transmitted in more that 1 subframe (2 or 8) and therefore MAC layer need to count how many subframes are available in the current frame for transmit it
+ * and take in consideration that other frames are needed before starting the transmission of a new one)
+ *
+ *
+ *We assume that whenever the NDLSCH pdu is a BCCH type, we consider as if it's a SIB1 while in other case can be data or SI-message depending on the RNTI
+ *
+ * **relevant aspects for the System information Transmission (Table 4-47 NDLSCH FAPi specs)
+ * 1)RNTI type = 0 (contains a BCCH)
+ * 2)Repetition number == scheduling info SIB1 mapped into 4-8-16
+ * 3)RNTI (0xFFFF = SI-RNTI)
+ * (see schedule_response implementation)
+ *
+ */
+
+/*
+ * This function is triggered by the schedule_response
+ * (the frequency at which is transmitted to the PHY depends on the MAC scheduler implementation)
+ * (in OAI in principle is every subframe)
+ */
+
+void phy_procedures_eNB_TX_NB_IoT(PHY_VARS_eNB_NB_IoT     *eNB,
+         	 	 	 	 	                eNB_rxtx_proc_t  *proc,
+							                    int                     do_meas)
+{
+  int                    frame           = proc->frame_tx;
+  int                    subframe        = proc->subframe_tx;
+  uint32_t               aa;
+  DCI_PDU_NB_IoT         *dci_pdu        = eNB->DCI_pdu;
+  NB_IoT_DL_FRAME_PARMS  *fp             = &eNB->frame_parms_NB_IoT;
+  int8_t                 UE_id           = 0;
+  int                    **txdataF       = eNB->common_vars.txdataF[0];
+  uint32_t               sib1_startFrame = -1;
+  //NB_IoT_eNB_NPDCCH_t*npdcch;
+
+  if(do_meas == 1)
+    //start_meas_NB_IoT(&eNB->phy_proc_tx);
+
+
+  /*the original scheduler "eNB_dlsch_ulsch_scheduler" now is no more done here but is triggered directly from UL_Indication (IF-Module Function)*/
+
+  // clear the transmit data array for the current subframe
+  for (aa=0; aa<fp->nb_antenna_ports_eNB; aa++) 
+    {      
+      memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
+                  0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
+    } 
+
+  //generate NPSS/NSSS
+  common_signal_procedures_NB_IoT(eNB,proc);
+
+    //Generate MIB
+    if(subframe ==0 && (eNB->npbch != NULL))
+     {
+          if(eNB->npbch->pdu != NULL)
+          {
+        	  //BCOM function
+        	  /*
+        	   * -the function get the MIB pdu and schedule the transmission over the 64 radio frame
+        	   * -need to check the subframe #0 (since encoding functions only check the frame)
+        	   * this functions should be called every frame (the function will transmit the remaining part of MIB)
+        	   * ( XXX Should check when the schedule_responce is transmitted by MAC scheduler)
+        	   * RB-ID only for the case of in-band operation but should be always considered
+        	   * (in stand alone i can put whatever the number)in other case consider the PRB index in the Table R&Shwartz pag 9
+        	   *
+        	   */
+
+    		    generate_npbch(eNB->npbch,
+                           txdataF,
+                           AMP,
+                           fp,
+						               eNB->npbch->pdu,
+                           frame%64,
+                           fp->NB_IoT_RB_ID);
+                        
+          }
+
+          //In the last frame in which the MIB-NB should be transmitted after we point to NULL since maybe we stop MIB trasnmission
+          //this should be in line with FAPI specs pag 94 (BCH procedure in Downlink 3.2.4.2 for NB-IoT)
+          if(frame%64 == 63)
+          {
+        	  eNB->npbch->pdu = NULL;
+          }
+      }
+
+
+    //Check for SIB1-NB transmission
+    /*
+     *
+     * the function should be called for each frame
+     * Parameters needed:
+     * -sib1-NB pdu if new one (should be given by the MAC at the start of each SIB1-NB period)
+     * -when start a new SIB1-NB repetition (sib1_rep_start)
+     * -the frame number relative to the 16 continuous frame within a repetition (relative_sib1_frame) 1st, 2nd ...
+     *
+     * we check that the transmission should occurr in subframe #4
+     *
+     * consider that if at the start of the new SIB1-NB period the MAC will not send an NPDSCH for the SIB1-NB transmission then SIB1-NB will be not transmitted (pdu = NULL)
+     *
+     */
+    if(subframe == 4 && eNB->ndlsch_SIB1 != NULL && eNB->ndlsch_SIB1->harq_process->status == ACTIVE_NB_IoT)
+    {
+      //check if current frame is for SIB1-NB transmission (if yes get the starting frame of SIB1-NB) and set the flag for the encoding
+      sib1_startFrame = is_SIB1_NB_IoT(frame,
+    		  	  	  	  	  	           (long)eNB->ndlsch_SIB1->harq_process->repetition_number,
+								                       fp->Nid_cell,
+								                       eNB->ndlsch_SIB1); //set the flags
+								                   
+  	  if(sib1_startFrame != -1 && eNB->ndlsch_SIB1->harq_process->pdu != NULL)
+  	  {
+    	   npdsch_procedures(eNB,
+          				         proc,
+					                 eNB->ndlsch_SIB1, //since we have no DCI for system information, this is filled directly when we receive the NDLSCH pdu from DL_CONFIG.request message
+					                 eNB->ndlsch_SIB1->harq_process->pdu);
+  	  }
+
+  	  //at the end of the period we put the PDU to NULL since we have to wait for the new one from the MAC for starting the next SIB1-NB transmission
+  	  if((frame-sib1_startFrame)%256 == 255)
+  	  {
+  		    //whenever we will not receive a new sdu from MAC at the start of the next SIB1-NB period we prevent future SIB1-NB transmission (may just only of the two condition is necessary)
+  		    eNB->ndlsch_SIB1->harq_process->status = DISABLED;
+  		    eNB->ndlsch_SIB1->harq_process->pdu = NULL;
+  	  }
+
+    }
+
+
+    //Check for SI transmission
+    /*
+     *Parameters needed:
+     * -total number of subframes for the transmission (2-8) (inside the NDLSCH structure --> HARQ process -->resource_assignment)
+     * XXX: in reality this flag is not needed because is enough to check if the PDU is NULL (continue the transmission) or not (new SI transmission)
+     * -SI_start (inside ndlsch structure): flag for indicate the starting of the SI transmission within the SI window (new PDU is received by the MAC) otherwise the PHY continue to transmit
+     *  what have in its buffer (so check the remaining encoded data continuously)
+     *
+     * SI transmission should not occurr in reserved subframes
+     * subframe = 0 (MIB-NB)
+     * subframe = 4 (SIB1-NB) but depends on the frame
+     * subframe = 5 (NPSS)
+     * subframe = 9 (NSSS) but depends on the frame (if is even)
+     *
+     * [This condition should be known by the MAC layer so it should trigger an DLSCH pdu only at proper instants]
+     *
+     * XXX Important: in the case the SI-window finish the PHY layer should have also being able to conclude all the SI transmission in time
+     * (because this is managed by the MAC layer that stops transmitting the SDU to PHY in advance because is counting the remaining subframe for the transmission)
+     *
+     *
+     *XXX important: set the flag HARQ process->status to DISABLE when PHY finished the SI-transmission over the 2 or 8 subframes
+     *XXX important: whenever we enter for some error in the ndlsch_procedure with a pdu that is NULL but all the data of the SI have been transmitted (pdu_buffer_index = 0)
+     *XXX  --> generate error
+     *XXX: the npdlsch_procedure in this case should be only called when is triggered by the MAC schedule_response (use the status flag set by the schedule_response)
+     *
+     */
+
+	if(eNB->ndlsch_SI->harq_process->status == ACTIVE_NB_IoT && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on SIB1-NB
+	{
+	    if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
+	    {
+	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5 && subframe != 9)
+	       {
+    		  //check if the PDU != NULL will be done inside just for understanding if a new SI message need to be transmitted or not
+    		  npdsch_procedures(eNB,
+            					      proc,
+								            eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
+								            eNB->ndlsch_SI->harq_process->pdu);
+
+    		  eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
+	    	}
+
+	     } else {//this frame not foresee the transmission of NSSS (subframe 9 is available)
+	    
+	    	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5)
+	    	      {
+	    		         npdsch_procedures(eNB,
+	            					             proc,
+									                   eNB->ndlsch_SI, //since we have no DCI for system information, this is filled directly when we receive the DL_CONFIG.request message
+									                   eNB->ndlsch_SI->harq_process->pdu);
+
+	    		         eNB->ndlsch_SI->harq_process->status = DISABLED_NB_IoT;
+
+	    	      }
+	         }
+
+	}
+
+      ///check for RAR transmission
+      if(eNB->ndlsch_ra != NULL && eNB->ndlsch_ra->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on SIB1-NB
+      {
+  	    if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
+  	     {
+  	      if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5 && subframe != 9)
+  	       {
+
+  	    	  npdsch_procedures(eNB,
+            					        proc,
+								              eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
+								              eNB->ndlsch_ra->harq_process->pdu);
+
+  	    	  //it should be activated only when we receive the proper DCIN1_RAR
+  	    	  eNB->ndlsch_ra->active= 0;
+  	       }
+  	     }
+	    else //this frame not foresee the transmission of NSSS (subframe 9 is available)
+	    {
+	    	if(eNB->ndlsch_SI != NULL &&  subframe!= 0 && subframe != 5)
+	    	   {
+	  	    	  npdsch_procedures(eNB,
+	            					        proc,
+									              eNB->ndlsch_ra, //should be filled ?? (in the old implementation was filled when from DCI we generate_dlsch_params
+									              eNB->ndlsch_ra->harq_process->pdu);
+
+	  	    	  //it should be activated only when we receive the proper DCIN1_RAR
+	  	    	  eNB->ndlsch_ra->active= 0; // maybe this is already done inside the ndlsch_procedure
+
+	    	   }
+	    }
+      }
+
+
+      //check for UE specific transmission
+      /*
+       * Delays between DCI transmission and NDLSCH transmission are taken in consideration by the MAC scheduler by sending in the proper subframe the scheduler_response
+       * (TS 36.213 ch 16.4.1: DCI format N1, N2, ending in subframe n intended for the UE, the UE shall decode, starting from subframe n+5 DL subframe,
+       * the corresponding NPDSCH transmission over the N consecutive NB/IoT DL subframes according to NPDCCH information)
+       * Transmission over more subframe and Repetitions are managed directly by the PHY layer
+       * We should have only 1 ue-specific ndlsch structure active at each time (active flag is set = 1 only at the corresponding NDLSCH pdu reception and not at the DCI time
+       * (NDLSCH transmission should be compliant with the FAPI procedure Figure 3-49)
+       *
+       * XXX how are managed the transmission and repetitions over the NPDSCH:
+       * -repetitions over the NPDSCH channel are defined inside the DCI
+       * -need to know the repetition number R (see specs)
+       * -repetition are made following a pattern rule (e.g. 00, 11 ...) (see specs)
+       * --whenever R>4 then repetition pattern rule changes
+       * -possibility to have DL-GAP (OPTIONAL) otherwise no gap in DCI transmission
+       *
+       * XXX During repetitions of DCI or NDLSCH we receive no schedule_response form MAC
+       *
+       */
+
+      //this should give only 1 result (since only 1 ndlsch procedure is activated at once) so we brak after the transmission
+      for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
+      {
+    	  if(eNB->ndlsch[(uint8_t)UE_id] != NULL && eNB->ndlsch[(uint8_t)UE_id]->active == 1 && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4)) //condition on sib1-NB
+    	  {
+    	  	if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
+    	  	  {
+    	  	    if( subframe!= 0 && subframe != 5 && subframe != 9)
+    	  	     {
+    	  	    	npdsch_procedures(eNB,
+                						      proc,
+										              eNB->ndlsch[(uint8_t)UE_id],
+										              eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
+    	  	    	break;
+    	  	       }
+    	  	     }
+    	    else //this frame not foresee the transmission of NSSS (subframe 9 is available)
+    	    {
+    	    	if( subframe!= 0 && subframe != 5)
+    	    	   {
+    	  	    	npdsch_procedures(eNB,
+                						      proc,
+										              eNB->ndlsch[(uint8_t)UE_id],
+										              eNB->ndlsch[(uint8_t)UE_id]->harq_process->pdu);
+    	  	    	break;
+
+    	    	   }
+    	    }
+    	  }
+
+
+      }
+
+
+      //no dedicated phy config
+
+
+      /*If we have DCI to generate do it now
+       *
+       * DCI in NB-IoT are transmitted over NPDCCH search spaces as described in TS 36.213 ch 16.6
+       *
+       * Don-t care about the concept of search space since will be managed by the MAC.
+       * MAC also evaluate the starting position of NPDCCH transmission and will send the corresponding scheduling_response
+       *
+       *
+       * The PHY layer should evaluate R (repetitions of DCI) based on:
+       *  -L (aggregation level) --> inside the NPDCCH PDU
+       *  -Rmax
+       *  -DCI subframe repetition number (2 bits) --> inside the NPDCCH PDU
+       *  -TS 36.213 Table 16.6/1/2/3
+       *
+       *
+       *  The higher layer parms (Rmax):
+       * -npdcch-NumRepetitions (UE-specific) [inside the NPDCCH UE-specific strucuture] --> configured through phyconfigDedicated
+       * -npdcch-NumRepetitionPaging (common)
+       * -npdcch-NumRepetitions-RA (common) [inside the NB_IoT_DL_FRAME_PARMS-> nprach_ParametersList] --> configured in phy_config_sib2
+       *
+       *  PROBLEM: in FAPI specs seems there is no way to trasnmit Rmax to the PHY (waiting for answers)
+       *
+       * *Rmax is also needed for evaluate the scheduling delay for NDLSCH (see scheduling delay field in NPDCCH PDU FAPI)
+       *
+       * *Scrambling re-initialization is needed at the beginning of the Search Space or every 4th NPDCCH subframe (See TS 36.211)
+       * (this is taken in cosideration by the NPDCCH parameter "scrambling re-initialization batch index" in FAPI specs (Table 4-45)
+       *
+       ****whenever we have aggregation level = 1 for UE-specific the R is always = 1 (see table 16.6-1)
+       ****DCI DL transmission should not happen in case of reference signals or SI messages (this function should be triggered every subframe)
+       *
+       * */
+
+
+      for(UE_id = 0 ; UE_id < NUMBER_OF_UE_MAX_NB_IoT; UE_id++)
+      {
+    	  if(eNB->npdcch[(uint8_t)UE_id] != NULL && eNB->npdcch[(uint8_t)UE_id]->rnti == dci_pdu->dci_alloc->rnti && (eNB->ndlsch_SIB1->harq_process->status != ACTIVE_NB_IoT || subframe != 4))
+    	  {
+      	  	if(frame%2 == 0)//condition on NSSS (subframe 9 not available)
+      	  	  {
+      	  	    if( subframe!= 0 && subframe != 5 && subframe != 9)
+      	  	     {
+
+      	  	    	generate_dci_top_NB_IoT(eNB->npdcch[(uint8_t)UE_id],
+    		      		  	  	                dci_pdu->Num_dci,
+    		  					                      dci_pdu->dci_alloc,
+    		  					                      AMP,
+    		  					                      fp,
+    		  					                      eNB->common_vars.txdataF[0],
+    		  					                      subframe,
+    		  					                      dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
+      	  	    	                        eNB->npdcch[(uint8_t)UE_id]->repetition_idx++; //can do also inside also the management
+
+    		  	  	  break;
+      	  	     }
+      	  	  }
+      	  else //this frame not foresee the transmission of NSSS (subframe 9 is available)
+      	     {
+      	     if( subframe!= 0 && subframe != 5)
+      	      {
+   	  	    	  generate_dci_top_NB_IoT(eNB->npdcch[(uint8_t)UE_id],
+ 		      		  	  	                  dci_pdu->Num_dci,
+ 		  					                        dci_pdu->dci_alloc,
+ 		  					                        AMP,
+ 		  					                        fp,
+ 		  					                        eNB->common_vars.txdataF[0],
+ 		  					                        subframe,
+ 		  					                        dci_pdu->npdcch_start_symbol); //this parameter depends by eutraControlRegionSize (see TS36.213 16.6.1)
+   	  	    	  
+                eNB->npdcch[(uint8_t)UE_id]->repetition_idx++; //can do also inside also the management
+
+ 		  	  	  break;
+      	      }
+
+      	     }
+      	   }
+    	  }
+
+}
diff --git a/openair1/SCHED/phy_procedures_lte_eNb_nb_iot.c b/openair1/SCHED/phy_procedures_lte_eNb_nb_iot.c
deleted file mode 100644
index 04c1ce98566ce92c3d35b866fcaf714a4eed3e9e..0000000000000000000000000000000000000000
--- a/openair1/SCHED/phy_procedures_lte_eNb_nb_iot.c
+++ /dev/null
@@ -1,705 +0,0 @@
-/*
- * 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.0  (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_procedures_lte_eNB.c
- * \brief Implementation of eNB procedures from 36.213 LTE specifications
- * \author R. Knopp, F. Kaltenberger, N. Nikaein, X. Foukas
- * \date 2011
- * \version 0.1
- * \company Eurecom
- * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr,navid.nikaein@eurecom.fr, x.foukas@sms.ed.ac.uk
- * \note
- * \warning
- */
-
-//NB-IoT test
-#include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h"
-#include "PHY/defs.h"
-#include "PHY/extern.h"
-#include "SCHED/defs.h"
-#include "SCHED/extern.h"
-
-#include "PHY/LTE_TRANSPORT/if4_tools.h"
-#include "PHY/LTE_TRANSPORT/if5_tools.h"
-
-#ifdef EMOS
-#include "SCHED/phy_procedures_emos.h"
-#endif
-
-//#define DEBUG_PHY_PROC (Already defined in cmake)
-//#define DEBUG_ULSCH
-
-#include "LAYER2/MAC/extern.h"
-#include "LAYER2/MAC/defs.h"
-#include "UTIL/LOG/log.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-
-#include "T.h"
-
-#include "assertions.h"
-#include "msc.h"
-
-#include <time.h>
-
-#if defined(ENABLE_ITTI)
-#   include "intertask_interface.h"
-#endif
-
-
-#if defined(FLEXRAN_AGENT_SB_IF)
-//Agent-related headers
-#include "ENB_APP/flexran_agent_extern.h"
-#include "ENB_APP/CONTROL_MODULES/MAC/flexran_agent_mac.h"
-#include "LAYER2/MAC/flexran_agent_mac_proto.h"
-#endif
-
-//#define DIAG_PHY
-
-#define NS_PER_SLOT 500000
-
-#define PUCCH 1
-
-void exit_fun(const char* s);
-
-extern int exit_openair;
-struct timespec start_fh, start_fh_prev;
-int start_fh_sf, start_fh_prev_sf;
-// Fix per CC openair rf/if device update
-// extern openair0_device openair0;
-
-unsigned char dlsch_input_buffer[2700] __attribute__ ((aligned(32)));
-int eNB_sync_buffer0[640*6] __attribute__ ((aligned(32)));
-int eNB_sync_buffer1[640*6] __attribute__ ((aligned(32)));
-int *eNB_sync_buffer[2] = {eNB_sync_buffer0, eNB_sync_buffer1};
-
-extern uint16_t hundred_times_log10_NPRB[100];
-
-unsigned int max_peak_val;
-int max_sync_pos;
-
-int harq_pid_updated[NUMBER_OF_UE_MAX][8] = {{0}};
-int harq_pid_round[NUMBER_OF_UE_MAX][8] = {{0}};
-
-//DCI_ALLOC_t dci_alloc[8];
-
-#ifdef EMOS
-fifo_dump_emos_eNB emos_dump_eNB;
-#endif
-
-#if defined(SMBV) 
-extern const char smbv_fname[];
-extern unsigned short config_frames[4];
-extern uint8_t smbv_frame_cnt;
-#endif
-
-#ifdef DIAG_PHY
-extern int rx_sig_fifo;
-#endif
-
-
-
-
-void NB_phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type)
-{
-  //RX processing for ue-specific resources (i
-  UNUSED(r_type);
-  uint32_t ret=0,i,j,k;
-  uint32_t harq_pid, harq_idx, round;
-  int sync_pos;
-  uint16_t rnti=0;
-  uint8_t access_mode;
-  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
-
-  const int subframe = proc->subframe_rx;
-  const int frame    = proc->frame_rx;
-  int offset         = eNB->CC_id;//(proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1;
-  
-  /*NB-IoT IF module Common setting*/
-  
-  UL_IND_t UL_Info;
-
-
-  UL_Info.module_id = eNB->Mod_id;
-  UL_Info.CC_id = eNB->CC_id;
-  UL_Info.frame =  frame;
-  UL_Info.subframe = subframe;
-
-
-  T(T_ENB_PHY_UL_TICK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe));
-
-  T(T_ENB_PHY_INPUT_SIGNAL, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(0),
-    T_BUFFER(&eNB->common_vars.rxdata[0][0][subframe*eNB->frame_parms.samples_per_tti],
-             eNB->frame_parms.samples_per_tti * 4));
-
-  //if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
-
-#ifdef DEBUG_PHY_PROC
-  LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe);
-  LOG_D(PHY,"[eNB %d] Frame %d: Set the Common part in UL_IND\n",eNB->Mod_id,frame);
-#endif
-
-  //check if any RB using in this UL subframe
-  eNB->rb_mask_ul[0]=0;
-  eNB->rb_mask_ul[1]=0;
-  eNB->rb_mask_ul[2]=0;
-  eNB->rb_mask_ul[3]=0;
-
-  // Check for active processes in current subframe
-  // NB-IoT subframe2harq_pid is in dci_tools, always set the frame type to FDD, this would become simpler.
-  harq_pid = subframe2harq_pid(fp,frame,subframe);
-
-  // delete the cba
-  // delete the srs
-  
-  /*Loop over the UE, i is the UE ID */
-  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
-
-    // delete srs 
-
-    // delete Pucch procedure
-
-    // check for Msg3
-    if (eNB->mac_enabled==1) {
-      if (eNB->UE_stats[i].mode == RA_RESPONSE) {
-	     /*Process Msg3 TODO*/
-       //process_Msg3(eNB,proc,i,harq_pid);
-      }
-    }
-
-
-    eNB->pusch_stats_rb[i][(frame*10)+subframe] = -63;
-    eNB->pusch_stats_round[i][(frame*10)+subframe] = 0;
-    eNB->pusch_stats_mcs[i][(frame*10)+subframe] = -63;
-
-    /*Check if this UE is has ULSCH scheduling*/
-    if ((eNB->ulsch[i]) &&
-        (eNB->ulsch[i]->rnti>0) &&
-        (eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag==1)) {
-      // UE is has ULSCH scheduling
-      round = eNB->ulsch[i]->harq_processes[harq_pid]->round;
-      /*NB-IoT The nb_rb always set to 1 */
-      for (int rb=0;
-           rb<=eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
-	         rb++) 
-      {
-	     int rb2 = rb+eNB->ulsch[i]->harq_processes[harq_pid]->first_rb;
-       eNB->rb_mask_ul[rb2>>5] |= (1<<(rb2&31));
-      }
-
-      /*Log for what kind of the ULSCH Reception*/
-      if (eNB->ulsch[i]->Msg3_flag == 1) { 
-        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for Msg3 in Sector %d\n",
-              eNB->Mod_id,
-              frame,
-              subframe,
-              eNB->UE_stats[i].sector);
-	       VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,1);
-      } else {
-
-        LOG_D(PHY,"[eNB %d] frame %d, subframe %d: Scheduling ULSCH Reception for UE %d Mode %s\n",
-              eNB->Mod_id,
-              frame,
-              subframe,
-              i,
-              mode_string[eNB->UE_stats[i].mode]);
-      }
-
-      /*Calculate for LTE C-RS*/
-      //nPRS = fp->pusch_config_common.ul_ReferenceSignalsPUSCH.nPRS[subframe<<1];
-
-      //eNB->ulsch[i]->cyclicShift = (eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2 + fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift +nPRS)%12;
-
-      if (fp->frame_type == FDD ) {
-        int sf = (subframe<4) ? (subframe+6) : (subframe-4);
-        /*After Downlink Data transmission, simply have a notice to received ACK from PUCCH, I think it's not use for now */
-        if (eNB->dlsch[i][0]->subframe_tx[sf]>0) { // we have downlink transmission
-          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 1;
-        } else {
-          eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK = 0;
-        }
-      }
-
-      LOG_D(PHY,
-            "[eNB %d][PUSCH %d] Frame %d Subframe %d Demodulating PUSCH: dci_alloc %d, rar_alloc %d, round %d, first_rb %d, nb_rb %d, mcs %d, TBS %d, rv %d, cyclic_shift %d (n_DMRS2 %d, cyclicShift_common %d), O_ACK %d \n",
-            eNB->Mod_id,harq_pid,frame,subframe,
-            eNB->ulsch[i]->harq_processes[harq_pid]->dci_alloc,
-            eNB->ulsch[i]->harq_processes[harq_pid]->rar_alloc,
-            eNB->ulsch[i]->harq_processes[harq_pid]->round,
-            eNB->ulsch[i]->harq_processes[harq_pid]->first_rb,
-            eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb,
-            eNB->ulsch[i]->harq_processes[harq_pid]->mcs,
-            eNB->ulsch[i]->harq_processes[harq_pid]->TBS,
-            eNB->ulsch[i]->harq_processes[harq_pid]->rvidx,
-            eNB->ulsch[i]->cyclicShift,
-            eNB->ulsch[i]->harq_processes[harq_pid]->n_DMRS2,
-            fp->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift,
-            eNB->ulsch[i]->harq_processes[harq_pid]->O_ACK);
-      eNB->pusch_stats_rb[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb;
-      eNB->pusch_stats_round[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->round;
-      eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->mcs;
-      start_meas(&eNB->ulsch_demodulation_stats);
-
-      if (eNB->abstraction_flag==0) {
-        rx_ulsch(eNB,proc,
-                 eNB->UE_stats[i].sector,  // this is the effective sector id
-                 i,
-                 eNB->ulsch,
-                 0);
-      }
-
-#ifdef PHY_ABSTRACTION
-      else {
-        rx_ulsch_emul(eNB,proc,
-                      eNB->UE_stats[i].sector,  // this is the effective sector id
-                      i);
-      }
-
-#endif
-      stop_meas(&eNB->ulsch_demodulation_stats);
-
-
-      start_meas(&eNB->ulsch_decoding_stats);
-
-      if (eNB->abstraction_flag == 0) {
-        ret = ulsch_decoding(eNB,proc,
-                             i,
-                             0, // control_only_flag
-                             eNB->ulsch[i]->harq_processes[harq_pid]->V_UL_DAI,
-			     eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb>20 ? 1 : 0);
-      }
-
-#ifdef PHY_ABSTRACTION
-      else {
-        ret = ulsch_decoding_emul(eNB,
-				  proc,
-                                  i,
-                                  &rnti);
-      }
-
-#endif
-      stop_meas(&eNB->ulsch_decoding_stats);
-
-      LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
-            eNB->Mod_id,harq_pid,
-            frame,subframe,
-            eNB->ulsch[i]->rnti,
-            dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
-            dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
-            eNB->UE_stats[i].UL_rssi[0],
-            eNB->UE_stats[i].UL_rssi[1],
-            eNB->measurements->n0_power_dB[0],
-            eNB->measurements->n0_power_dB[1],
-            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
-            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
-            ret);
-
-      //compute the expected ULSCH RX power (for the stats)
-      eNB->ulsch[(uint32_t)i]->harq_processes[harq_pid]->delta_TF =
-        get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0); // 0 means bw_factor is not considered
-
-      eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
-#ifdef DEBUG_PHY_PROC
-      LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d harq_pid %d Clearing subframe_scheduling_flag\n",
-            eNB->Mod_id,harq_pid,frame,subframe,i,harq_pid);
-#endif
-      eNB->ulsch[i]->harq_processes[harq_pid]->subframe_scheduling_flag=0;
-
-      if (eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status == 1) {
-#ifdef DEBUG_PHY_PROC
-        //if (((frame%10) == 0) || (frame < 50))
-        print_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,0,fp->N_RB_DL);
-#endif
-        extract_CQI(eNB->ulsch[i]->harq_processes[harq_pid]->o,
-                    eNB->ulsch[i]->harq_processes[harq_pid]->uci_format,
-                    &eNB->UE_stats[i],
-                    fp->N_RB_DL,
-                    &rnti, &access_mode);
-        eNB->UE_stats[i].rank = eNB->ulsch[i]->harq_processes[harq_pid]->o_RI[0];
-
-      }
-
-      if (eNB->ulsch[i]->Msg3_flag == 1)
-	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_ULSCH_MSG3,0);
-
-      if (ret == (1+MAX_TURBO_ITERATIONS)) 
-      {
-        T(T_ENB_PHY_ULSCH_UE_NACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->ulsch[i]->rnti),
-          T_INT(harq_pid));
-
-        eNB->UE_stats[i].ulsch_round_errors[harq_pid][eNB->ulsch[i]->harq_processes[harq_pid]->round]++;
-        eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
-        eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 0;
-        eNB->ulsch[i]->harq_processes[harq_pid]->round++;
-
-        LOG_D(PHY,"[eNB][PUSCH %d] Increasing to round %d\n",harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->round);
-
-      if (eNB->ulsch[i]->Msg3_flag == 1) 
-      {
-
-          LOG_D(PHY,"[eNB %d/%d][RAPROC] frame %d, subframe %d, UE %d: Error receiving ULSCH (Msg3), round %d/%d\n",
-                eNB->Mod_id,
-                eNB->CC_id,
-                frame,subframe, i,
-                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
-                fp->maxHARQ_Msg3Tx-1);
-	         /*dump_ulsch(eNB,proc,i);
-	           exit(-1);*/
-
-	        LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d RNTI %x RX power (%d,%d) RSSI (%d,%d) N0 (%d,%d) dB ACK (%d,%d), decoding iter %d\n",
-		      eNB->Mod_id,harq_pid,
-		      frame,subframe,
-		      eNB->ulsch[i]->rnti,
-		      dB_fixed(eNB->pusch_vars[i]->ulsch_power[0]),
-		      dB_fixed(eNB->pusch_vars[i]->ulsch_power[1]),
-		      eNB->UE_stats[i].UL_rssi[0],
-		      eNB->UE_stats[i].UL_rssi[1],
-		      eNB->measurements->n0_power_dB[0],
-		      eNB->measurements->n0_power_dB[1],
-		      eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
-		      eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
-		      ret);
-
-          /*In NB-IoT MSG3 */
-          // activate retransmission for Msg3 (signalled to UE PHY by DCI
-          eNB->ulsch[(uint32_t)i]->Msg3_active = 1;
-          /* Need to check the procedure for NB-IoT retransmission
-          get_Msg3_alloc_ret(fp,subframe,frame,&eNB->ulsch[i]->Msg3_frame,&eNB->ulsch[i]->Msg3_subframe);
-          mac_xface->set_msg3_subframe(eNB->Mod_id, eNB->CC_id, frame, subframe, eNB->ulsch[i]->rnti,eNB->ulsch[i]->Msg3_frame, eNB->ulsch[i]->Msg3_subframe);
-          */
-          T(T_ENB_PHY_MSG3_ALLOCATION, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe),
-                  T_INT(i), T_INT(eNB->ulsch[i]->rnti), T_INT(0 /* 0 is for retransmission*/),
-                  T_INT(eNB->ulsch[i]->Msg3_frame), T_INT(eNB->ulsch[i]->Msg3_subframe));
-              
-          LOG_D(PHY,"[eNB] Frame %d, Subframe %d: Msg3 in error, i = %d \n", frame,subframe,i);
-      } // This is Msg3 error
-
-      else 
-      { //normal ULSCH
-              LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d Error receiving ULSCH, round %d/%d (ACK %d,%d)\n",
-                eNB->Mod_id,harq_pid,
-                frame,subframe, i,
-                eNB->ulsch[i]->harq_processes[harq_pid]->round-1,
-                eNB->ulsch[i]->Mlimit,
-                eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
-                eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1]);
-
-#if defined(MESSAGE_CHART_GENERATOR_PHY)
-              MSC_LOG_RX_DISCARDED_MESSAGE(
-				       MSC_PHY_ENB,MSC_PHY_UE,
-				       NULL,0,
-				       "%05u:%02u ULSCH received rnti %x harq id %u round %d",
-				       frame,subframe,
-				       eNB->ulsch[i]->rnti,harq_pid,
-				       eNB->ulsch[i]->harq_processes[harq_pid]->round-1
-				       );
-#endif
-
-              if (eNB->ulsch[i]->harq_processes[harq_pid]->round== eNB->ulsch[i]->Mlimit) 
-              {
-                  LOG_D(PHY,"[eNB %d][PUSCH %d] frame %d subframe %d UE %d ULSCH Mlimit %d reached\n",
-                        eNB->Mod_id,harq_pid,
-                        frame,subframe, i,
-                        eNB->ulsch[i]->Mlimit);
-
-                  eNB->ulsch[i]->harq_processes[harq_pid]->round=0;
-                  eNB->ulsch[i]->harq_processes[harq_pid]->phich_active=0;
-                  eNB->UE_stats[i].ulsch_errors[harq_pid]++;
-                  eNB->UE_stats[i].ulsch_consecutive_errors++;
-
-	               /*if (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb > 20) {
-		              dump_ulsch(eNB,proc,i);
-	 	              exit(-1);
-                 }*/
-	               // indicate error to MAC
-	               if (eNB->mac_enabled == 1)
-                    {
-                      //instead rx_sdu to report NAK to MAC
-                      UL_Info.UL_SPEC_Info[i].rntiP= eNB->ulsch[i]->rnti;
-                      UL_Info.UL_SPEC_Info[i].sdu = NULL;
-                      UL_Info.UL_SPEC_Info[i].sdu_lenP = 0;
-                      UL_Info.UL_SPEC_Info[i].harq_pidP = harq_pid;
-                      UL_Info.UL_SPEC_Info[i].msg3_flagP = &eNB->ulsch[i]->Msg3_flag;
-                      UL_Info.UL_SPEC_Info[i].NAK=1;
-                      UL_Info.UE_NUM++;
-
-                    }
-              }
-        }
-      }  // ulsch in error
-      else {
-
-        
-        T(T_ENB_PHY_ULSCH_UE_ACK, T_INT(eNB->Mod_id), T_INT(frame), T_INT(subframe), T_INT(i), T_INT(eNB->ulsch[i]->rnti),
-          T_INT(harq_pid));
-
-        // Delete MSG3  log for the PHICH 
-#if defined(MESSAGE_CHART_GENERATOR_PHY)
-        MSC_LOG_RX_MESSAGE(
-			   MSC_PHY_ENB,MSC_PHY_UE,
-			   NULL,0,
-			   "%05u:%02u ULSCH received rnti %x harq id %u",
-			   frame,subframe,
-			   eNB->ulsch[i]->rnti,harq_pid
-			   );
-#endif
-        for (j=0; j<fp->nb_antennas_rx; j++)
-          //this is the RSSI per RB
-          eNB->UE_stats[i].UL_rssi[j] =
-	    
-            dB_fixed(eNB->pusch_vars[i]->ulsch_power[j]*
-                     (eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb*12)/
-                     fp->ofdm_symbol_size) -
-            eNB->rx_total_gain_dB -
-            hundred_times_log10_NPRB[eNB->ulsch[i]->harq_processes[harq_pid]->nb_rb-1]/100 -
-            get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 0)/100;
-        //for NB-IoT PHICH not work
-	      /*eNB->ulsch[i]->harq_processes[harq_pid]->phich_active = 1;
-        eNB->ulsch[i]->harq_processes[harq_pid]->phich_ACK = 1;*/
-        eNB->ulsch[i]->harq_processes[harq_pid]->round = 0;
-        eNB->UE_stats[i].ulsch_consecutive_errors = 0;
-
-        if (eNB->ulsch[i]->Msg3_flag == 1) 
-          {
-	        if (eNB->mac_enabled==1) 
-            {
-
-	            LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
-		                eNB->Mod_id,frame,harq_pid,i);
-	           if (eNB->mac_enabled)
-             {
-                // store successful MSG3 in UL_Info instead rx_sdu
-                UL_Info.UL_SPEC_Info[i].rntiP= eNB->ulsch[i]->rnti;
-                UL_Info.UL_SPEC_Info[i].sdu = eNB->ulsch[i]->harq_processes[harq_pid]->b;
-                UL_Info.UL_SPEC_Info[i].sdu_lenP = eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3;
-                UL_Info.UL_SPEC_Info[i].harq_pidP = harq_pid;
-                UL_Info.UL_SPEC_Info[i].msg3_flagP = &eNB->ulsch[i]->Msg3_flag;
-                UL_Info.UE_NUM++;
-              }
-
-	           /* Need check if this needed in NB-IoT
-	           // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
-	           if (eNB->ulsch[i]->Msg3_flag == 0 ) {
-	           eNB->UE_stats[i].mode = PRACH;
-	           mac_xface->cancel_ra_proc(eNB->Mod_id,
-					   eNB->CC_id,
-					   frame,
-					   eNB->UE_stats[i].crnti);
-	           mac_phy_remove_ue(eNB->Mod_id,eNB->UE_stats[i].crnti);
-	           eNB->ulsch[(uint32_t)i]->Msg3_active = 0;
-	           } // Msg3_flag == 0*/
-	    
-	         } // mac_enabled==1
-
-          eNB->UE_stats[i].mode = PUSCH;
-          eNB->ulsch[i]->Msg3_flag = 0;
-
-	        LOG_D(PHY,"[eNB %d][RAPROC] Frame %d : RX Subframe %d Setting UE %d mode to PUSCH\n",eNB->Mod_id,frame,subframe,i);
-
-          /*Init HARQ parameters, need to check*/
-          for (k=0; k<8; k++) { //harq_processes
-            for (j=0; j<eNB->dlsch[i][0]->Mlimit; j++) {
-              eNB->UE_stats[i].dlsch_NAK[k][j]=0;
-              eNB->UE_stats[i].dlsch_ACK[k][j]=0;
-              eNB->UE_stats[i].dlsch_trials[k][j]=0;
-            }
-
-            eNB->UE_stats[i].dlsch_l2_errors[k]=0;
-            eNB->UE_stats[i].ulsch_errors[k]=0;
-            eNB->UE_stats[i].ulsch_consecutive_errors=0;
-
-            for (j=0; j<eNB->ulsch[i]->Mlimit; j++) {
-              eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0;
-              eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
-              eNB->UE_stats[i].ulsch_round_errors[k][j]=0;
-              eNB->UE_stats[i].ulsch_round_fer[k][j]=0;
-            }
-          }
-
-          eNB->UE_stats[i].dlsch_sliding_cnt=0;
-          eNB->UE_stats[i].dlsch_NAK_round0=0;
-          eNB->UE_stats[i].dlsch_mcs_offset=0;
-        } // Msg3_flag==1
-	else {  // Msg3_flag == 0
-
-#ifdef DEBUG_PHY_PROC
-#ifdef DEBUG_ULSCH
-          LOG_D(PHY,"[eNB] Frame %d, Subframe %d : ULSCH SDU (RX harq_pid %d) %d bytes:",frame,subframe,
-                harq_pid,eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3);
-
-          for (j=0; j<eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3; j++)
-            LOG_T(PHY,"%x.",eNB->ulsch[i]->harq_processes[harq_pid]->b[j]);
-
-          LOG_T(PHY,"\n");
-#endif
-#endif
-
-	        if (eNB->mac_enabled==1) 
-              {
-                  // store successful Uplink data in UL_Info instead rx_sdu
-                  UL_Info.UL_SPEC_Info[i].rntiP= eNB->ulsch[i]->rnti;
-                  UL_Info.UL_SPEC_Info[i].sdu = eNB->ulsch[i]->harq_processes[harq_pid]->b;
-                  UL_Info.UL_SPEC_Info[i].sdu_lenP = eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3;
-                  UL_Info.UL_SPEC_Info[i].harq_pidP = harq_pid;
-                  UL_Info.UL_SPEC_Info[i].msg3_flagP = NULL;
-                  UL_Info.UE_NUM++;
-
-#ifdef LOCALIZATION
-	    start_meas(&eNB->localization_stats);
-	    aggregate_eNB_UE_localization_stats(eNB,i,frame,subframe,get_hundred_times_delta_IF_eNB(eNB,i,harq_pid, 1)/100);
-	    stop_meas(&eNB->localization_stats);
-#endif
-	    
-	           } // mac_enabled==1
-      } // Msg3_flag == 0
-
-          // estimate timing advance for MAC
-          if (eNB->abstraction_flag == 0) 
-            {
-              sync_pos = lte_est_timing_advance_pusch(eNB,i);
-              eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
-            }
-
-#ifdef DEBUG_PHY_PROC
-            LOG_D(PHY,"[eNB %d] frame %d, subframe %d: user %d: timing advance = %d\n",
-                  eNB->Mod_id,
-                  frame, subframe,
-                  i,
-                  eNB->UE_stats[i].timing_advance_update);
-#endif
-
-
-      }  // ulsch not in error
-
-#ifdef DEBUG_PHY_PROC
-      LOG_D(PHY,"[eNB %d][PDSCH %x] Frame %d subframe %d, Processing HARQ feedback for UE %d (after PUSCH)\n",eNB->Mod_id,
-            eNB->dlsch[i][0]->rnti,
-            frame,subframe,
-            i);
-#endif
-      // Process HARQ only in NPUSCH
-      /*process_HARQ_feedback(i,
-                            eNB,proc,
-                            1, // pusch_flag
-                            0,
-                            0,
-                            0);*/
-
-#ifdef DEBUG_PHY_PROC
-      LOG_D(PHY,"[eNB %d] Frame %d subframe %d, sect %d: received ULSCH harq_pid %d for UE %d, ret = %d, CQI CRC Status %d, ACK %d,%d, ulsch_errors %d/%d\n",
-            eNB->Mod_id,frame,subframe,
-            eNB->UE_stats[i].sector,
-            harq_pid,
-            i,
-            ret,
-            eNB->ulsch[i]->harq_processes[harq_pid]->cqi_crc_status,
-            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[0],
-            eNB->ulsch[i]->harq_processes[harq_pid]->o_ACK[1],
-            eNB->UE_stats[i].ulsch_errors[harq_pid],
-            eNB->UE_stats[i].ulsch_decoding_attempts[harq_pid][0]);
-#endif
-      
-      // dump stats to VCD
-      if (i==0) {
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_MCS0+harq_pid,eNB->pusch_stats_mcs[0][(frame*10)+subframe]);
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RB0+harq_pid,eNB->pusch_stats_rb[0][(frame*10)+subframe]);
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_ROUND0+harq_pid,eNB->pusch_stats_round[0][(frame*10)+subframe]);
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RSSI0+harq_pid,dB_fixed(eNB->pusch_vars[0]->ulsch_power[0]));
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_RES0+harq_pid,ret);
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_SFN0+harq_pid,(frame*10)+subframe);
-      }
-    } // ulsch[0] && ulsch[0]->rnti>0 && ulsch[0]->subframe_scheduling_flag == 1
-
-    //store the parameter to determine if UL failure or not
-    UL_Info.UL_SPEC_Info[i].ulsch_consecutive_errors = eNB->UE_stats[i].ulsch_consecutive_errors;
-
-
-    // update ULSCH statistics for tracing
-    if ((frame % 100 == 0) && (subframe == 4)) {
-      for (harq_idx=0; harq_idx<8; harq_idx++) {
-        for (round=0; round<eNB->ulsch[i]->Mlimit; round++) {
-          if ((eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] -
-               eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]) != 0) {
-            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] =
-              (100*(eNB->UE_stats[i].ulsch_round_errors[harq_idx][round] -
-                    eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round]))/
-              (eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round] -
-               eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round]);
-          } else {
-            eNB->UE_stats[i].ulsch_round_fer[harq_idx][round] = 0;
-          }
-
-          eNB->UE_stats[i].ulsch_decoding_attempts_last[harq_idx][round] =
-            eNB->UE_stats[i].ulsch_decoding_attempts[harq_idx][round];
-          eNB->UE_stats[i].ulsch_round_errors_last[harq_idx][round] =
-            eNB->UE_stats[i].ulsch_round_errors[harq_idx][round];
-        }
-      }
-    }
-
-    if ((frame % 100 == 0) && (subframe==4)) {
-      eNB->UE_stats[i].dlsch_bitrate = (eNB->UE_stats[i].total_TBS -
-					eNB->UE_stats[i].total_TBS_last);
-
-      eNB->UE_stats[i].total_TBS_last = eNB->UE_stats[i].total_TBS;
-    }
-
-  } // loop i=0 ... NUMBER_OF_UE_MAX-1
-
-  if (eNB->abstraction_flag == 0) {
-    lte_eNB_I0_measurements(eNB,
-			    subframe,
-			    0,
-			    eNB->first_run_I0_measurements);
-    eNB->first_run_I0_measurements = 0;
-  }
-
-#ifdef PHY_ABSTRACTION
-  else {
-    lte_eNB_I0_measurements_emul(eNB,
-				 0);
-  }
-
-#endif
-
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 0 );
-
-  stop_meas(&eNB->phy_proc_rx);
-
-  /*Exact not here, but use to debug*/
-  UL_indication(UL_Info);
-
-}
-
-#undef DEBUG_PHY_PROC
-
-
-void NB_phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
-         eNB_rxtx_proc_t *proc,
-         PHY_VARS_RN *rn,
-         int do_meas)
-{
-
-
-
-}
\ No newline at end of file
diff --git a/openair1/SCHED/pusch_pc_NB_IoT.c b/openair1/SCHED/pusch_pc_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..ae67e9e260ae421dbefdd02bdcef6f3e196cfd87
--- /dev/null
+++ b/openair1/SCHED/pusch_pc_NB_IoT.c
@@ -0,0 +1,270 @@
+/*
+ * 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.0  (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 pusch_pc.c
+ * \brief Implementation of UE PUSCH Power Control procedures from 36.213 LTE specifications (Section
+ * \author R. Knopp
+ * \date 2011
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+
+//#include "defs_nb_iot.h"
+#include "PHY/defs_NB_IoT.h"
+#include "PHY/TOOLS/dB_routines.h"
+//#include "PHY/LTE_TRANSPORT/proto_nb_iot.h"
+//#include "PHY/extern_NB_IoT.h"
+
+// This is the formula from Section 5.1.1.1 in 36.213 100*10*log10((2^(MPR*Ks)-1)), where MPR is in the range [0,6] and Ks=1.25
+int16_t hundred_times_delta_TF_NB_IoT[100] = {-32768,-1268,-956,-768,-631,-523,-431,-352,-282,-219,-161,-107,-57,-9,36,79,120,159,197,234,269,304,337,370,402,434,465,495,525,555,583,612,640,668,696,723,750,777,803,829,856,881,907,933,958,983,1008,1033,1058,1083,1108,1132,1157,1181,1205,1229,1254,1278,1302,1325,1349,1373,1397,1421,1444,1468,1491,1515,1538,1562,1585,1609,1632,1655,1679,1702,1725,1748,1772,1795,1818,1841,1864,1887,1910,1933,1956,1980,2003,2026,2049,2072,2095,2118,2141,2164,2186,2209,2232,2255};
+uint16_t hundred_times_log10_NPRB_NB_IoT[100] = {0,301,477,602,698,778,845,903,954,1000,1041,1079,1113,1146,1176,1204,1230,1255,1278,1301,1322,1342,1361,1380,1397,1414,1431,1447,1462,1477,1491,1505,1518,1531,1544,1556,1568,1579,1591,1602,1612,1623,1633,1643,1653,1662,1672,1681,1690,1698,1707,1716,1724,1732,1740,1748,1755,1763,1770,1778,1785,1792,1799,1806,1812,1819,1826,1832,1838,1845,1851,1857,1863,1869,1875,1880,1886,1892,1897,1903,1908,1913,1919,1924,1929,1934,1939,1944,1949,1954,1959,1963,1968,1973,1977,1982,1986,1991,1995,2000};
+
+int16_t get_hundred_times_delta_IF_eNB_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,uint8_t UE_id,uint8_t harq_pid, uint8_t bw_factor)
+{
+
+  uint32_t Nre,sumKr,MPR_x100,Kr,r;
+  uint16_t beta_offset_pusch;
+
+  DevAssert( UE_id < NUMBER_OF_UE_MAX_NB_IoT+1 );
+  DevAssert( harq_pid < 8 );
+
+  Nre = eNB->nulsch[UE_id]->harq_process->Nsymb_initial *
+        eNB->nulsch[UE_id]->harq_process->nb_rb*12;
+
+  sumKr = 0;
+
+  for (r=0; r<eNB->nulsch[UE_id]->harq_process->C; r++) {
+    if (r<eNB->nulsch[UE_id]->harq_process->Cminus)
+      Kr = eNB->nulsch[UE_id]->harq_process->Kminus;
+    else
+      Kr = eNB->nulsch[UE_id]->harq_process->Kplus;
+
+    sumKr += Kr;
+  }
+
+  if (Nre==0)
+    return(0);
+
+  MPR_x100 = 100*sumKr/Nre;
+  // Note: MPR=is the effective spectral efficiency of the PUSCH
+  // FK 20140908 sumKr is only set after the ulsch_encoding
+
+  beta_offset_pusch = 8;
+  //(eNB->ulsch[UE_id]->harq_processes[harq_pid]->control_only == 1) ? eNB->ulsch[UE_id]->beta_offset_cqi_times8:8;
+
+  DevAssert( UE_id < NUMBER_OF_UE_MAX_NB_IoT );
+//#warning "This condition happens sometimes. Need more investigation" // navid
+  //DevAssert( MPR_x100/6 < 100 );
+
+  if (eNB->ul_power_control_dedicated[UE_id].deltaMCS_Enabled == 1) {
+    // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch)
+    if (bw_factor == 1) {
+      uint8_t nb_rb = eNB->nulsch[UE_id]->harq_process->nb_rb;
+      return(hundred_times_delta_TF_NB_IoT[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3)) + hundred_times_log10_NPRB_NB_IoT[nb_rb-1];
+    } else
+      return(hundred_times_delta_TF_NB_IoT[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3));
+  } else {
+    return(0);
+  }
+
+}
+
+/*
+int16_t get_hundred_times_delta_IF_mac(module_id_t module_idP, uint8_t CC_id, rnti_t rnti, uint8_t harq_pid)
+{
+  int8_t UE_id = find_ue( rnti, PHY_vars_eNB_g[module_idP][CC_id] );
+
+  if (UE_id == -1) {
+    // not found
+    return 0;
+  }
+
+  return get_hundred_times_delta_IF_eNB( PHY_vars_eNB_g[module_idP][CC_id], UE_id, harq_pid, 0 );
+}
+
+int16_t get_hundred_times_delta_IF(PHY_VARS_UE *ue,uint8_t eNB_id,uint8_t harq_pid)
+{
+
+  uint32_t Nre = 2*ue->ulsch[eNB_id]->harq_processes[harq_pid]->Nsymb_initial *
+                 ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb*12;
+
+  if (Nre==0)
+    return(0);
+
+  uint32_t MPR_x100 = 100*ue->ulsch[eNB_id]->harq_processes[harq_pid]->TBS/Nre;
+  // Note: MPR=is the effective spectral efficiency of the PUSCH
+  // FK 20140908 sumKr is only set after the ulsch_encoding
+
+  uint16_t beta_offset_pusch = (ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ?
+    ue->ulsch[eNB_id]->beta_offset_cqi_times8:8;
+
+  if (ue->ul_power_control_dedicated[eNB_id].deltaMCS_Enabled == 1) {
+    // This is the formula from Section 5.1.1.1 in 36.213 10*log10(deltaIF_PUSCH = (2^(MPR*Ks)-1)*beta_offset_pusch)
+    return(hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch)>>3));
+  } else {
+    return(0);
+  }
+}
+
+
+
+uint8_t alpha_lut[8] = {0,40,50,60,70,80,90,100};
+
+void pusch_power_cntl(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag)
+{
+
+
+  uint8_t harq_pid = subframe2harq_pid(&ue->frame_parms,
+                                       proc->frame_tx,
+                                       proc->subframe_tx);
+
+  uint8_t nb_rb = ue->ulsch[eNB_id]->harq_processes[harq_pid]->nb_rb;
+  int16_t PL;
+
+
+  // P_pusch = 10*log10(nb_rb + P_opusch(j)+ alpha(u)*PL + delta_TF(i) + f(i))
+  //
+  // P_opusch(0) = P_oPTR + deltaP_Msg3 if PUSCH is transporting Msg3
+  // else
+  // P_opusch(0) = PO_NOMINAL_PUSCH(j) + P_O_UE_PUSCH(j)
+  PL = get_PL(ue->Mod_id,ue->CC_id,eNB_id);
+
+  ue->ulsch[eNB_id]->Po_PUSCH = (hundred_times_log10_NPRB[nb_rb-1]+
+				 get_hundred_times_delta_IF(ue,eNB_id,harq_pid) +
+				 100*ue->ulsch[eNB_id]->f_pusch)/100;
+
+  if(ue->ulsch_Msg3_active[eNB_id] == 1) {  // Msg3 PUSCH
+
+    ue->ulsch[eNB_id]->Po_PUSCH += (mac_xface->get_Po_NOMINAL_PUSCH(ue->Mod_id,0) + PL);
+
+    LOG_I(PHY,"[UE  %d][RAPROC] AbsSubframe %d.%d: Msg3 (%d PRBs) Po_PUSCH %d dBm (%d,%d,100*PL=%d,%d,%d)\n",
+          ue->Mod_id,proc->frame_tx,proc->subframe_tx,nb_rb,ue->ulsch[eNB_id]->Po_PUSCH,
+          100*mac_xface->get_Po_NOMINAL_PUSCH(ue->Mod_id,0),
+          hundred_times_log10_NPRB[nb_rb-1],
+          100*PL,
+          get_hundred_times_delta_IF(ue,eNB_id,harq_pid),
+          100*ue->ulsch[eNB_id]->f_pusch);
+  } else if (j==0) { // SPS PUSCH
+  } else if (j==1) { // Normal PUSCH
+
+    ue->ulsch[eNB_id]->Po_PUSCH +=  ((alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha]*PL)/100);
+    ue->ulsch[eNB_id]->Po_PUSCH +=  ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH;
+    ue->ulsch[eNB_id]->PHR       =  ue->tx_power_max_dBm-ue->ulsch[eNB_id]->Po_PUSCH;  
+
+    if (ue->ulsch[eNB_id]->PHR < -23)
+      ue->ulsch[eNB_id]->PHR = -23;
+    else if (ue->ulsch[eNB_id]->PHR > 40)
+      ue->ulsch[eNB_id]->PHR = 40;
+
+    LOG_D(PHY,"[UE  %d][PUSCH %d] AbsSubframe %d.%d: nb_rb: %d, Po_PUSCH %d dBm : tx power %d, Po_NOMINAL_PUSCH %d,log10(NPRB) %f,PHR %d, PL %d, alpha*PL %f,delta_IF %f,f_pusch %d\n",
+          ue->Mod_id,harq_pid,proc->frame_tx,proc->subframe_tx,nb_rb,
+          ue->ulsch[eNB_id]->Po_PUSCH,
+          ue->tx_power_max_dBm,
+          ue->frame_parms.ul_power_control_config_common.p0_NominalPUSCH,
+          hundred_times_log10_NPRB[nb_rb-1]/100.0,
+          ue->ulsch[eNB_id]->PHR,
+          PL,
+          alpha_lut[ue->frame_parms.ul_power_control_config_common.alpha]*PL/100.0,
+          get_hundred_times_delta_IF(ue,eNB_id,harq_pid)/100.0,
+          ue->ulsch[eNB_id]->f_pusch);
+  }
+
+}
+
+int8_t get_PHR(uint8_t Mod_id, uint8_t CC_id,uint8_t eNB_index)
+{
+
+  return PHY_vars_UE_g[Mod_id][CC_id]->ulsch[eNB_index]->PHR;
+}
+
+// uint8_t eNB_id,uint8_t harq_pid, uint8_t UE_id,
+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)
+{
+
+  /// The payload + CRC size in bits, "B"
+  uint32_t B;
+  /// Number of code segments
+  uint32_t C;
+  /// Number of "small" code segments
+  uint32_t Cminus;
+  /// Number of "large" code segments
+  uint32_t Cplus;
+  /// Number of bits in "small" code segments (<6144)
+  uint32_t Kminus;
+  /// Number of bits in "large" code segments (<6144)
+  uint32_t Kplus;
+  /// Total number of bits across all segments
+  uint32_t sumKr;
+  /// Number of "Filler" bits
+  uint32_t F;
+  // num resource elements
+  uint32_t num_re=0.0;
+  // num symbols
+  uint32_t num_symb=0.0;
+  /// effective spectral efficiency of the PUSCH
+  uint32_t MPR_x100=0;
+  /// beta_offset
+  uint16_t beta_offset_pusch_x8=8;
+  /// delta mcs
+  float delta_mcs=0.0;
+  /// bandwidth factor
+  float bw_factor=0.0;
+
+  B= tbs+24;
+  lte_segmentation(NULL,
+                   NULL,
+                   B,
+                   &C,
+                   &Cplus,
+                   &Cminus,
+                   &Kplus,
+                   &Kminus,
+                   &F);
+
+
+  sumKr = Cminus*Kminus + Cplus*Kplus;
+  num_symb = 12-(ncp<<1)-(use_srs==0?0:1);
+  num_re = num_symb * nb_rb * 12;
+
+  if (num_re == 0)
+    return(0);
+
+  MPR_x100 = 100*sumKr/num_re;
+
+  if (control_only == 1 )
+    beta_offset_pusch_x8=8; // fixme
+
+  //(beta_offset_pusch_x8=ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? ue->ulsch[eNB_id]->beta_offset_cqi_times8:8;
+
+  // if deltamcs_enabledm
+  delta_mcs = ((hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_times10((beta_offset_pusch_x8)>>3))/100.0);
+  bw_factor = (hundred_times_log10_NPRB[nb_rb-1]/100.0);
+#ifdef DEBUG_SEGMENTATION
+  printf("estimated ue tx power %d (num_re %d, sumKr %d, mpr_x100 %d, delta_mcs %f, bw_factor %f)\n",
+         (int16_t)ceil(delta_mcs + bw_factor), num_re, sumKr, MPR_x100, delta_mcs, bw_factor);
+#endif
+  return (int16_t)ceil(delta_mcs + bw_factor);
+
+}
+*/
\ No newline at end of file
diff --git a/openair2/COMMON/platform_types_NB_IoT.h b/openair2/COMMON/platform_types_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..5acf5e6cc39d346ac237a1f44f4e24625d83bf9b
--- /dev/null
+++ b/openair2/COMMON/platform_types_NB_IoT.h
@@ -0,0 +1,310 @@
+/*
+ * 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.0  (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
+ */
+
+/*
+                                 platform_types.h
+                             -------------------
+  AUTHOR  : Lionel GAUTHIER
+  COMPANY : EURECOM
+  EMAIL   : Lionel.Gauthier@eurecom.fr
+
+ ***************************************************************************/
+#ifndef __PLATFORM_TYPES_NB_IoT_H__
+#    define __PLATFORM_TYPES_NB_IoT_H__
+
+#ifdef USER_MODE
+#include <stdint.h>
+#endif
+
+#if defined(ENABLE_ITTI)
+#include "itti_types.h"
+#endif
+//-----------------------------------------------------------------------------
+// GENERIC TYPES
+//-----------------------------------------------------------------------------
+typedef uint16_t           rnti_NB_IoT_t;
+/* boolean_t is also defined in openair2/COMMON/commonDef.h,
+ * let's protect potential redefinition
+ */
+#ifndef _BOOLEAN_T_DEFINED_NB_IoT_
+#define _BOOLEAN_T_DEFINED_NB_IoT_
+
+typedef signed char        boolean_NB_IoT_t;
+
+#if !defined(TRUE)
+#define TRUE               (boolean_NB_IoT_t)0x01
+#endif
+
+#if !defined(FALSE)
+#define FALSE              (boolean_NB_IoT_t)0x00
+#endif
+
+#define BOOL_NOT(b) (b^TRUE)
+
+#endif /* _BOOLEAN_T_DEFINED_ */
+/*
+//-----------------------------------------------------------------------------
+// GENERIC ACCESS STRATUM TYPES
+//-----------------------------------------------------------------------------
+typedef int32_t               sdu_size_t;
+typedef uint32_t              frame_t;
+typedef int32_t               sframe_t;
+typedef uint32_t              sub_frame_t;
+typedef uint8_t               module_id_t;
+typedef uint8_t               eNB_index_t;
+typedef uint16_t              ue_id_t;
+typedef int16_t               smodule_id_t;
+typedef uint16_t              rb_id_t;
+typedef uint16_t              srb_id_t;
+
+typedef boolean_t             MBMS_flag_t;
+#define  MBMS_FLAG_NO         FALSE
+#define  MBMS_FLAG_YES        TRUE
+
+typedef boolean_t             eNB_flag_t;
+#define  ENB_FLAG_NO          FALSE
+#define  ENB_FLAG_YES         TRUE
+
+typedef boolean_t             srb_flag_t;
+#define  SRB_FLAG_NO          FALSE
+#define  SRB_FLAG_YES         TRUE
+
+///NB-IoT
+typedef boolean_t srb1bis_flag_t;
+#define SRB1BIS_FLAG_NO	   FALSE
+#define SRB1BIS_FLAG_YES	TRUE
+
+typedef boolean_t mib_flag_t;
+#define MIB_FLAG_YES	TRUE
+#define MIB_FLAG_NO		FALSE
+
+
+typedef enum link_direction_e {
+  UNKNOWN_DIR          = 0,
+  DIR_UPLINK           = 1,
+  DIR_DOWNLINK         = 2
+} link_direction_t;
+
+typedef enum rb_type_e {
+  UNKNOWN_RADIO_BEARER        = 0,
+  SIGNALLING_RADIO_BEARER     = 1,
+  RADIO_ACCESS_BEARER         = 2
+} rb_type_t;
+
+//-----------------------------------------------------------------------------
+// PHY TYPES
+//-----------------------------------------------------------------------------
+typedef uint8_t            crc8_t;
+typedef uint16_t           crc16_t;
+typedef uint32_t           crc32_t;
+typedef unsigned int       crc_t;
+
+//-----------------------------------------------------------------------------
+// MAC TYPES
+//-----------------------------------------------------------------------------
+typedef sdu_size_t         tbs_size_t;
+typedef sdu_size_t         tb_size_t;
+typedef unsigned int       logical_chan_id_t;
+typedef unsigned int       num_tb_t;
+typedef uint8_t            mac_enb_index_t;
+
+//-----------------------------------------------------------------------------
+// RLC TYPES
+//-----------------------------------------------------------------------------
+typedef unsigned int       mui_t;
+typedef unsigned int       confirm_t;
+typedef unsigned int       rlc_tx_status_t;
+typedef int16_t            rlc_sn_t;
+typedef uint16_t           rlc_usn_t;
+typedef int32_t            rlc_buffer_occupancy_t;
+typedef signed int         rlc_op_status_t;
+
+#define  SDU_CONFIRM_NO          FALSE
+#define  SDU_CONFIRM_YES         TRUE
+//-----------------------------------------------------------------------------
+// PDCP TYPES
+//-----------------------------------------------------------------------------
+typedef uint16_t           pdcp_sn_t;
+typedef uint32_t           pdcp_hfn_t;
+typedef int16_t            pdcp_hfn_offset_t;
+
+typedef enum pdcp_transmission_mode_e {
+  PDCP_TRANSMISSION_MODE_UNKNOWN     = 0,
+  PDCP_TRANSMISSION_MODE_CONTROL     = 1,
+  PDCP_TRANSMISSION_MODE_DATA        = 2,
+  PDCP_TRANSMISSION_MODE_TRANSPARENT = 3
+} pdcp_transmission_mode_t;
+//-----------------------------------------------------------------------------
+// IP DRIVER / PDCP TYPES
+//-----------------------------------------------------------------------------
+typedef uint16_t           tcp_udp_port_t;
+typedef enum  ip_traffic_type_e {
+  TRAFFIC_IPVX_TYPE_UNKNOWN    =  0,
+  TRAFFIC_IPV6_TYPE_UNICAST    =  1,
+  TRAFFIC_IPV6_TYPE_MULTICAST  =  2,
+  TRAFFIC_IPV6_TYPE_UNKNOWN    =  3,
+  TRAFFIC_IPV4_TYPE_UNICAST    =  5,
+  TRAFFIC_IPV4_TYPE_MULTICAST  =  6,
+  TRAFFIC_IPV4_TYPE_BROADCAST  =  7,
+  TRAFFIC_IPV4_TYPE_UNKNOWN    =  8
+} ip_traffic_type_t;
+*/
+//-----------------------------------------------------------------------------
+// RRC TYPES
+//-----------------------------------------------------------------------------
+//typedef uint32_t           mbms_session_id_t;
+//typedef uint16_t           mbms_service_id_t;
+
+//typedef uint8_t            rrc_enb_index_t;
+//typedef uint8_t            mme_code_t;
+//typedef uint32_t           m_tmsi_t;
+/*
+//Random UE identity length = 40 bits
+#if ! defined(NOT_A_RANDOM_UE_IDENTITY)
+#define NOT_A_RANDOM_UE_IDENTITY (uint64_t)0xFFFFFFFF
+#endif
+#if ! defined(NOT_A_RNTI)
+#define NOT_A_RNTI (rnti_t)0
+#endif
+#if ! defined(M_RNTI)
+#define M_RNTI     (rnti_t)0xFFFD
+#endif
+#if ! defined(P_RNTI)
+#define P_RNTI     (rnti_t)0xFFFE
+#endif
+#if ! defined(SI_RNTI)
+#define SI_RNTI    (rnti_t)0xFFFF
+#endif
+typedef enum config_action_e {
+  CONFIG_ACTION_NULL              = 0,
+  CONFIG_ACTION_ADD               = 1,
+  CONFIG_ACTION_REMOVE            = 2,
+  CONFIG_ACTION_MODIFY            = 3,
+  CONFIG_ACTION_SET_SECURITY_MODE = 4,
+  CONFIG_ACTION_MBMS_ADD          = 10,
+  CONFIG_ACTION_MBMS_MODIFY       = 11
+} config_action_t;
+
+//-----------------------------------------------------------------------------
+// GTPV1U TYPES
+//-----------------------------------------------------------------------------
+typedef uint32_t           teid_t; // tunnel endpoint identifier
+typedef uint8_t            ebi_t;  // eps bearer id
+
+
+
+//-----------------------------------------------------------------------------
+//
+//-----------------------------------------------------------------------------
+// may be ITTI not enabled, but type instance is useful also for OTG,
+#if !defined(instance_t)
+typedef uint16_t instance_t;
+#endif
+typedef struct protocol_ctxt_s {
+  module_id_t module_id;     /!< \brief  Virtualized module identifier      /
+  eNB_flag_t  enb_flag;      /!< \brief  Flag to indicate eNB (1) or UE (0) /
+  instance_t  instance;      /!< \brief  ITTI or OTG module identifier      /
+  rnti_t      rnti;
+  frame_t     frame;         /!< \brief  LTE frame number./
+  sub_frame_t subframe;      /!< \brief  LTE sub frame number./
+  eNB_index_t eNB_index;     /!< \brief  valid for UE indicating the index of connected eNB(s)      /
+  boolean_t   configured;  /!< \brief  flag indicating whether the instance is configured or not  /
+} protocol_ctxt_t;
+// warning time hardcoded
+#define PROTOCOL_CTXT_TIME_MILLI_SECONDS(CtXt_h) ((CtXt_h)->frame*10+(CtXt_h)->subframe)
+
+#define UE_MODULE_ID_TO_INSTANCE( mODULE_iD ) mODULE_iD + NB_eNB_INST
+#define ENB_MODULE_ID_TO_INSTANCE( mODULE_iD ) mODULE_iD
+#define UE_INSTANCE_TO_MODULE_ID( iNSTANCE ) iNSTANCE - NB_eNB_INST
+#define ENB_INSTANCE_TO_MODULE_ID( iNSTANCE )iNSTANCE
+
+
+#define MODULE_ID_TO_INSTANCE(mODULE_iD, iNSTANCE, eNB_fLAG) \
+    if(eNB_fLAG == ENB_FLAG_YES) \
+        iNSTANCE = ENB_MODULE_ID_TO_INSTANCE(mODULE_iD); \
+    else \
+        iNSTANCE = UE_MODULE_ID_TO_INSTANCE(mODULE_iD)
+
+#define INSTANCE_TO_MODULE_ID(iNSTANCE, mODULE_iD, eNB_fLAG) \
+    if(eNB_fLAG == ENB_FLAG_YES) \
+        mODULE_iD = ENB_INSTANCE_TO_MODULE_ID(iNSTANCE); \
+    else \
+        mODULE_iD = UE_INSTANCE_TO_MODULE_ID(iNSTANCE)
+
+#define PROTOCOL_CTXT_COMPUTE_MODULE_ID(CtXt_h) \
+    INSTANCE_TO_MODULE_ID( (CtXt_h)->instance , (CtXt_h)->module_id , (CtXt_h)->enb_flag )
+
+
+#define PROTOCOL_CTXT_COMPUTE_INSTANCE(CtXt_h) \
+    MODULE_ID_TO_INSTANCE( (CtXt_h)->module_id , (CtXt_h)->instance , (CtXt_h)->enb_flag )
+
+
+#define PROTOCOL_CTXT_SET_BY_MODULE_ID(Ctxt_Pp, mODULE_iD, eNB_fLAG, rNTI, fRAME, sUBfRAME, eNB_iNDEX) \
+    (Ctxt_Pp)->module_id = mODULE_iD; \
+    (Ctxt_Pp)->enb_flag  = eNB_fLAG; \
+    (Ctxt_Pp)->rnti      = rNTI; \
+    (Ctxt_Pp)->frame     = fRAME; \
+    (Ctxt_Pp)->subframe  = sUBfRAME; \
+    (Ctxt_Pp)->eNB_index  = eNB_iNDEX; \
+    PROTOCOL_CTXT_COMPUTE_INSTANCE(Ctxt_Pp)
+
+#define PROTOCOL_CTXT_SET_BY_INSTANCE(Ctxt_Pp, iNSTANCE, eNB_fLAG, rNTI, fRAME, sUBfRAME) \
+    (Ctxt_Pp)->instance  = iNSTANCE; \
+    (Ctxt_Pp)->enb_flag  = eNB_fLAG; \
+    (Ctxt_Pp)->rnti      = rNTI; \
+    (Ctxt_Pp)->frame     = fRAME; \
+    (Ctxt_Pp)->subframe  = sUBfRAME; \
+    PROTOCOL_CTXT_COMPUTE_MODULE_ID(Ctxt_Pp)
+
+#define PROTOCOL_CTXT_FMT "[FRAME %05u][%s][MOD %02u][RNTI %" PRIx16 "]"
+#define PROTOCOL_CTXT_ARGS(CTXT_Pp) \
+    (CTXT_Pp)->frame, \
+    ((CTXT_Pp)->enb_flag == ENB_FLAG_YES) ? "eNB":" UE", \
+    (CTXT_Pp)->module_id, \
+    (CTXT_Pp)->rnti
+
+#ifdef OAI_EMU
+#define CHECK_CTXT_ARGS(CTXT_Pp) \
+    if ((CTXT_Pp)->enb_flag) {\
+        AssertFatal (((CTXT_Pp)->module_id >= oai_emulation.info.first_enb_local) && (oai_emulation.info.nb_enb_local > 0),\
+                     "eNB module id is too low (%u/%d/%d)!\n",\
+                     (CTXT_Pp)->module_id,\
+                     oai_emulation.info.first_enb_local,\
+                     oai_emulation.info.nb_enb_local);\
+        AssertFatal (((CTXT_Pp)->module_id < (oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local)) && (oai_emulation.info.nb_enb_local > 0),\
+                     "eNB module id is too high (%u/%d)!\n",\
+                     (CTXT_Pp)->module_id,\
+                     oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local);\
+    } else {\
+        AssertFatal ((CTXT_Pp)->module_id  < (oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local),\
+                     "UE module id is too high (%u/%d)!\n",\
+                     (CTXT_Pp)->module_id,\
+                     oai_emulation.info.first_ue_local + oai_emulation.info.nb_ue_local);\
+        AssertFatal ((CTXT_Pp)->module_id  >= oai_emulation.info.first_ue_local,\
+                     "UE module id is too low (%u/%d)!\n",\
+                     (CTXT_Pp)->module_id,\
+                     oai_emulation.info.first_ue_local);\
+    }
+#else
+#define CHECK_CTXT_ARGS(CTXT_Pp)
+#endif
+*/
+#endif
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index 4f671800fca112b2debecf69bb37cd82024f3978..55b94e2db16db251054343ac75e2d828aa6d57bb 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -108,6 +108,7 @@ typedef struct RrcConfigurationReq_s {
   uint8_t                 tdd_config[MAX_NUM_CCs];
   uint8_t                 tdd_config_s[MAX_NUM_CCs];
   lte_prefix_type_t       prefix_type[MAX_NUM_CCs];
+  lte_prefix_type_t		  prefix_type_UL[MAX_NUM_CCs];
   int16_t                 eutra_band[MAX_NUM_CCs];
   uint32_t                downlink_frequency[MAX_NUM_CCs];
   int32_t                 uplink_frequency_offset[MAX_NUM_CCs];
@@ -115,10 +116,11 @@ typedef struct RrcConfigurationReq_s {
   int16_t                 Nid_cell[MAX_NUM_CCs];// for testing, change later
   int16_t                 N_RB_DL[MAX_NUM_CCs];// for testing, change later
 
-  int                  	  nb_antennas_tx[MAX_NUM_CCs]; //MP: may no more used
-  int                     nb_antennas_rx[MAX_NUM_CCs]; //MP: may no more used
+  int                  	  nb_antennas_tx[MAX_NUM_CCs];
+  int                     nb_antennas_rx[MAX_NUM_CCs];
 
   int					  nb_antenna_ports[MAX_NUM_CCs];
+  int					  nb_antenna_ports_rx[MAX_NUM_CCs];
 
   //PRACH
   long                    prach_root[MAX_NUM_CCs];
@@ -200,7 +202,7 @@ typedef struct RrcConfigurationReq_s {
   long					  rach_macContentionResolutionTimer_NB[MAX_NUM_CCs];
   long					  rach_powerRampingStep_NB[MAX_NUM_CCs];
   long					  rach_preambleInitialReceivedTargetPower_NB[MAX_NUM_CCs];
-  long					  preambleTransMax_CE_NB[MAX_NUM_CCs]; //da ricontrollare se va bene il tipo
+  long					  rach_preambleTransMax_CE_NB[MAX_NUM_CCs];
   //BCCH
   long					  bcch_modificationPeriodCoeff_NB[MAX_NUM_CCs];
   //PCCH
@@ -209,7 +211,7 @@ typedef struct RrcConfigurationReq_s {
   long					  pcch_npdcch_NumRepetitionPaging_NB[MAX_NUM_CCs];
   //NPRACH
   long					  nprach_CP_Length[MAX_NUM_CCs];
-  long					  nprach_rsrp_range_NB[MAX_NUM_CCs];
+  long					  nprach_rsrp_range[MAX_NUM_CCs];
   long					  nprach_Periodicity[MAX_NUM_CCs];
   long					  nprach_StartTime[MAX_NUM_CCs];
   long					  nprach_SubcarrierOffset[MAX_NUM_CCs];
@@ -230,19 +232,14 @@ typedef struct RrcConfigurationReq_s {
   BOOLEAN_t				  npusch_groupHoppingEnabled[MAX_NUM_CCs];
   long					  npusch_groupAssignmentNPUSCH_r13[MAX_NUM_CCs];
 
-   /*NPUCCH
-   * all data are sent over the NPUSCH. This includes also the UL control information (UCI), which is transmitted using a different format.
-   * Consequently there is no equivalent to the PUCCH of LTE in NB-IoT.
-   */
-
   //DL_GapConfig
   long					  dl_GapThreshold_NB[MAX_NUM_CCs];
   long	 				  dl_GapPeriodicity_NB[MAX_NUM_CCs];
   long	 				  dl_GapDurationCoeff_NB[MAX_NUM_CCs];
   //Uplink power control Common
-  long					  npusch_p0_NominalNPUSCH_r13[MAX_NUM_CCs];
-  long					  npusch_alpha_r13[MAX_NUM_CCs];
-  long					  deltaPreambleMsg3_r13[MAX_NUM_CCs];
+  long					  npusch_p0_NominalNPUSCH[MAX_NUM_CCs];
+  long					  npusch_alpha[MAX_NUM_CCs];
+  long					  deltaPreambleMsg3[MAX_NUM_CCs];
   //UE timers and constants
   long					  ue_TimersAndConstants_t300_NB[MAX_NUM_CCs];
   long					  ue_TimersAndConstants_t301_NB[MAX_NUM_CCs];
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index 153c89b3e2b2d4fb63461151b155b7607e66666d..323f23597b3ca77e5cf9e29b2fb66fa4437046aa 100644
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -768,6 +768,9 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
     enb_properties_index = 0;
     num_enbs = config_setting_length(setting);
 
+
+    //Start the loop for parsing all the element over the .config file
+
     for (i = 0; i < num_enbs; i++) {
       setting_enb = config_setting_get_elem(setting, i);
 
@@ -783,6 +786,8 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
 # endif
       }
 
+      //Identification Parameters
+
       if (  !(       config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_CELL_TYPE,           &cell_type)
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_ENB_NAME,            &enb_name)
                     && config_setting_lookup_string(setting_enb, ENB_CONFIG_STRING_TRACKING_AREA_CODE,  &tac)
@@ -2519,7 +2524,7 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
           }
 	  
 
-          // OTG _CONFIG
+          // OTG _CONFIG //MP: refers to USB On the GO Features ?? (use USB devices as a fleshdrives)
           setting_otg = config_setting_get_member (setting_enb, ENB_CONF_STRING_OTG_CONFIG);
 
           if (setting_otg != NULL) {
diff --git a/openair2/LAYER2/MAC/IF_Module_nb_iot.c b/openair2/LAYER2/MAC/IF_Module_nb_iot.c
deleted file mode 100644
index 5edbb04e75c654faad40b7c3307512edfd3263da..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/MAC/IF_Module_nb_iot.c
+++ /dev/null
@@ -1,40 +0,0 @@
-#include "openair2/PHY_INTERFACE/IF_Module_nb_iot.h"
-#include "LAYER2/MAC/extern.h"
-#include "LAYER2/MAC/proto_nb_iot.h"
-
-void UL_indication(UL_IND_t UL_INFO)
-{
-    int i=0;
-    UL_INFO.test=1;
-    if(UL_INFO.test == 1)
-        {
-          /*If there is a preamble, do the initiate RA procedure*/
-          if(UL_INFO.preamble_index && UL_INFO.timing_offset)
-              NB_initiate_ra_proc(UL_INFO.module_id,UL_INFO.CC_id,UL_INFO.frame,UL_INFO.preamble_index,UL_INFO.timing_offset,UL_INFO.subframe);
-
-          /*If there is a Uplink SDU (even MSG3, NAK) need to send to MAC*/
-          for(i=0;i<UL_INFO.UE_NUM;i++)
-              {
-                  /*For MSG3, Normal Uplink Data, NAK*/
-                  if(UL_INFO.UL_SPEC_Info[i].rntiP)
-                      NB_rx_sdu(UL_INFO.module_id,
-                                UL_INFO.CC_id,
-                                UL_INFO.frame,
-                                UL_INFO.subframe,
-                                UL_INFO.UL_SPEC_Info[i].rntiP,
-                                UL_INFO.UL_SPEC_Info[i].sdu,
-                                UL_INFO.UL_SPEC_Info[i].sdu_lenP,
-                                UL_INFO.UL_SPEC_Info[i].harq_pidP,
-                                UL_INFO.UL_SPEC_Info[i].msg3_flagP
-                                );
-                    
-
-              }
-        }
-
-    NB_eNB_dlsch_ulsch_scheduler(UL_INFO.module_id,0,UL_INFO.frame,UL_INFO.subframe);
-}
-
-void Schedule_Response(Sched_Rsp_t Sched_INFO){
-      //todo
-}
\ No newline at end of file
diff --git a/openair2/LAYER2/MAC/config_NB_IoT.c b/openair2/LAYER2/MAC/config_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..789533550af828cc73f04f3fef199b7dc04814b4
--- /dev/null
+++ b/openair2/LAYER2/MAC/config_NB_IoT.c
@@ -0,0 +1,648 @@
+
+/*! \file config_NB_IoT.c
+ * \brief configuration primitives between RRC and MAC
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "LAYER2/MAC/defs_NB_IoT.h"
+#include "LAYER2/MAC/proto_NB_IoT.h"
+#include "LAYER2/MAC/extern_NB_IoT.h"
+#include "BCCH-DL-SCH-Message-NB.h"
+#include "RRCConnectionSetup-NB.h"
+#include "BCCH-BCH-Message-NB.h"
+//#include "SIB-Type-NB-r13.h"
+
+typedef struct eutra_bandentry_NB_s {
+  //this should be the colum order of the table below
+    int16_t   band;
+    uint32_t  ul_min;
+    uint32_t  ul_max;
+    uint32_t  dl_min;
+    uint32_t  dl_max;
+    uint32_t  N_OFFs_DL;
+} eutra_bandentry_NB_IoT_t;
+
+typedef struct band_info_s {
+
+    int                        nbands;
+    eutra_bandentry_NB_IoT_t   band_info[100];
+
+} band_info_t;
+
+static const eutra_bandentry_NB_IoT_t eutra_bandtable[] = {
+//[BAND] [FUL_low] [FUL_hi] [FDL_low] [FDL_hig] [NOFF_DL]
+  { 1, 19200, 19800, 21100, 21700, 0},
+  { 2, 18500, 19100, 19300, 19900, 6000},
+  { 3, 17100, 17850, 18050, 18800, 12000},
+  { 5,  8240,  8490,  8690,  8940, 24000},
+  { 8,  8800, 9150,  9250,  9600, 34500},
+  {11, 14279, 14529, 14759, 15009, 47500},
+  {12,  6980,  7160,  7280,  7460, 50100},
+  {13,  7770,  7870,  7460,  7560, 51800},
+  {17,  7040,  7160,  7340,  7460, 57300},
+  {18,  8150,  9650,  8600, 10100, 58500},
+  {19,  8300,  8450,  8750,  8900, 60000},
+  {20,  8320,  8620,  7910,  8210, 61500},
+  {25, 18500, 19150, 19300, 19950, 80400},
+  {26, 8140,  8490,  8590,  8940, 86900},
+  {28, 7030,  7580,  7580,  8130, 92100},
+  {31, 45250, 34900, 46250, 35900, 98700},
+  {66, 17100, 18000, 21100, 22000, 664360},
+  {70, 16950 , 17100,  19950,  20200, 683360}}; //may not used for Rel.13 equipment
+
+//this function is used in phy_config_mib_NB for getting the DL Carrier Frequency from the EARFCN
+uint32_t from_earfcn_NB_IoT(int eutra_bandP,uint32_t dl_earfcn, float m_dl) {
+
+  int i;
+
+ // float m_dl = 0; //for the moment we fix but maybe should be dynamic (anyway the 0 works for any case)
+
+  AssertFatal(eutra_bandP <= 70,"eutra_band %d > 70\n",eutra_bandP);
+  for (i=0;i<= 70 && eutra_bandtable[i].band!=eutra_bandP;i++);
+
+  return(eutra_bandtable[i].dl_min + 0.0025*(2*m_dl+1)+(dl_earfcn-(eutra_bandtable[i].N_OFFs_DL/10)))*100000;
+}
+
+
+int32_t get_uldl_offset_NB_IoT(int eutra_band) {
+  return(-eutra_bandtable[eutra_band].dl_min + eutra_bandtable[eutra_band].ul_min);
+}
+
+uint32_t to_earfcn(int eutra_bandP,uint32_t dl_CarrierFreq, float m_dl) {
+
+  uint32_t dl_CarrierFreq_by_100k = dl_CarrierFreq/100000;
+
+  int i;
+
+  AssertFatal(eutra_bandP < 70,"eutra_band %d > 70\n",eutra_bandP);
+  for (i=0;i<69 && eutra_bandtable[i].band!=eutra_bandP;i++);
+
+  AssertFatal(dl_CarrierFreq_by_100k>=eutra_bandtable[i].dl_min,
+        "Band %d : DL carrier frequency %u Hz < %u\n",
+        eutra_bandP,dl_CarrierFreq,eutra_bandtable[i].dl_min);
+
+  //I would say that for sure the EUTRA band is larger that 1 PRB for NB-IoT so this check may is unuseful
+//  AssertFatal(dl_CarrierFreq_by_100k<=(eutra_bandtable[i].dl_max-bw_by_100),
+//        "Band %d, bw %u: DL carrier frequency %u Hz > %d\n",
+//        eutra_bandP,bw,dl_CarrierFreq,eutra_bandtable[i].dl_max-bw_by_100);
+
+
+  //based on formula TS 36.101 5.7.3F
+  return(dl_CarrierFreq_by_100k - eutra_bandtable[i].dl_min - 0.0025*(2*m_dl+ 1)+ (eutra_bandtable[i].N_OFFs_DL/10));
+}
+
+
+
+void config_mib_fapi_NB_IoT(
+
+        int                     rntiP,
+        int                     physCellId,
+        uint8_t                 eutra_band,
+        int                     Ncp,
+        int                     Ncp_UL,
+        int                     p_eNB,
+        int                     p_rx_eNB,
+        int                     dl_CarrierFreq,
+        int                     ul_CarrierFreq,
+        long                    *eutraControlRegionSize,
+        BCCH_BCH_Message_NB_t   *mib_NB_IoT
+        )
+
+{
+
+    //XXX MP: one important problem to solve is how we decide when we deal with anchor or non anchor carrier?? configuration time?
+    //anchor carrier refers to the allowed PRBs index in the in-band operation mode at the beginning the UE is always camp on an anchor carrier from which
+    //receive NSSS, NPSSS ecc... but the RRCConnectionReconfiguration may could indicate non-anchor carrier to be used for data transmission
+    //ASSUMPTION: we always use an anchor carrier
+
+    float m_dl = 0; //this is the category offset for NB1/NB2 UE category used for EARFCN evaluation (TS 36.101 ch. 5.7.3F) (for the moment we keep this value fixed)
+    config_INFO->get_MIB                                          = 1;
+    config_INFO->rnti                                             = rntiP;
+    config_INFO->cfg->nfapi_config.rf_bands.rf_band[0]            = (uint16_t)eutra_band;
+    config_INFO->cfg->sch_config.physical_cell_id.value           = physCellId;
+    config_INFO->cfg->subframe_config.dl_cyclic_prefix_type.value = Ncp;
+    config_INFO->cfg->subframe_config.ul_cyclic_prefix_type.value = Ncp_UL;
+    config_INFO->cfg->rf_config.tx_antenna_ports.value            = p_eNB;
+    config_INFO->cfg->rf_config.rx_antenna_ports.value            = p_rx_eNB;
+
+
+
+    //PROBLEM: we need to know the LTE bandwidht for In-band and Guard band operating mode in order to choose the proper PRB idex or is given at configuration time??
+    //The prb index allowed are the one specified in R&shwarz pag 9 NB-IoT white papaer
+
+
+    switch (mib_NB_IoT->message.operationModeInfo_r13.present)
+    {
+      //FAPI specs pag 135
+      case MasterInformationBlock_NB__operationModeInfo_r13_PR_inband_SamePCI_r13:
+
+              config_INFO->cfg->config_NB_IoT.operating_mode.value  = 0;
+              config_INFO->cfg->config_NB_IoT.prb_index.value       = mib_NB_IoT->message.operationModeInfo_r13.choice.inband_SamePCI_r13.eutra_CRS_SequenceInfo_r13; //see TS 36.213 ch 16.0
+              config_INFO->cfg->config_NB_IoT.assumed_crs_aps.value = -1; //is not defined so we put a negative value
+
+              if(eutraControlRegionSize == NULL)
+                   LOG_E(RRC, "rrc_mac_config_req_eNB_NB_IoT: operation mode is in-band but eutraControlRegionSize is not defined");
+              else
+                   config_INFO->cfg->config_NB_IoT.control_region_size.value = *eutraControlRegionSize;
+
+
+              //m_dl = NB_Category_Offset_anchor[rand()%4];
+
+
+          break;
+
+      case MasterInformationBlock_NB__operationModeInfo_r13_PR_inband_DifferentPCI_r13:
+
+           config_INFO->cfg->config_NB_IoT.operating_mode.value = 1;
+           //XXX problem: fapi think to define also eutra_CRS_sequenceInfo also for in band with different PCI but the problem is that we don-t have i
+           //XXX should pass the prb_index may defined by configuration file depending on the LTE band we are considering (see Rhode&Shwartz whitepaper pag9)
+           //config_INFO->config_NB_IoT.prb_index.value =
+           config_INFO->cfg->config_NB_IoT.assumed_crs_aps.value = mib_NB_IoT->message.operationModeInfo_r13.choice.inband_DifferentPCI_r13.eutra_NumCRS_Ports_r13;
+
+             if(eutraControlRegionSize == NULL)
+                   LOG_E(RRC, "rrc_mac_config_req_eNB_NB_IoT: operation mode is in-band but eutraControlRegionSize is not defined");
+             else
+                   config_INFO->cfg->config_NB_IoT.control_region_size.value = *eutraControlRegionSize;
+
+        break;
+
+      case MasterInformationBlock_NB__operationModeInfo_r13_PR_guardband_r13:
+        
+          config_INFO->cfg->config_NB_IoT.operating_mode.value      = 2;
+          //XXX should pass the prb_index may defined by configuration file depending on the LTE band we are considering (see Rhode&Shwartz whitepaper pag9)
+          //config_INFO->config_NB_IoT.prb_index.value =
+            config_INFO->cfg->config_NB_IoT.control_region_size.value = -1; //should not being defined so we put a negative value
+              config_INFO->cfg->config_NB_IoT.assumed_crs_aps.value     = -1; //is not defined so we put a negative value
+
+        break;
+
+      case MasterInformationBlock_NB__operationModeInfo_r13_PR_standalone_r13:
+
+            config_INFO->cfg->config_NB_IoT.operating_mode.value       = 3;
+            config_INFO->cfg->config_NB_IoT.prb_index.value            = -1;   // is not defined for this case (put a negative random value--> will be not considered for encoding, scrambling procedures)
+            config_INFO->cfg->config_NB_IoT.control_region_size.value  = -1;   //is not defined so we put a negative value
+              config_INFO->cfg->config_NB_IoT.assumed_crs_aps.value      = -1;   //is not defined so we put a negative value
+
+        break;
+      default:
+            LOG_E(RRC, "rrc_mac_config_req_eNB_NB_IoT: NB-IoT operating Mode (MIB-NB) not set\n");
+        break;
+    }
+
+    //we shoud use dl_CarrierConfig for generating the earfcn for LTE-CAT N2 based on  TS 36.101 5.7.3F
+    /*
+     * 1) takes a random number from the offset of category NB1 and NB2 based on the operating mode (we assume always the usage of anchor carrier)
+     * 2)evaluate the EARFCN value based on the corresponding formula
+     */
+    config_INFO->cfg->nfapi_config.earfcn.value = to_earfcn(eutra_band,dl_CarrierFreq, m_dl);
+
+}
+
+void config_sib2_fapi_NB_IoT(
+                        int physCellId,
+                        RadioResourceConfigCommonSIB_NB_r13_t   *radioResourceConfigCommon
+                        )
+{
+
+    /*
+     * Following the FAPI like approach:
+     * 1)fill the PHY_Config_t structure (PHY_INTERFACE/IF_Module_NB_IoT.h)
+     * 1.1) check for how many NPRACH resources has been set and enable the corresponding parameter
+     * 1.2)fill the structure PHY_Config_t (shared structure of the IF_Module
+     * 2)Call the PHY_config_req for trigger the NB_phy_config_sib2_eNB()
+     */
+
+    /*NPRACH Resources*/
+
+    NPRACH_Parameters_NB_r13_t* nprach_parameter;
+
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_enabled.value = 0;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_enabled.value = 0;
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_enabled.value = 0;
+
+    switch(radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.size)
+    {
+    case 0:
+        LOG_E(MAC, "nprach_ParametersLis is empty\n");
+      break;
+    case 1:
+      nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[0];
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_enabled.value = 1;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_cp_length.value = radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_sf_periodicity.value = nprach_parameter->nprach_Periodicity_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_start_time.value = nprach_parameter->nprach_StartTime_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_subcarrier_offset.value = nprach_parameter->nprach_SubcarrierOffset_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_number_of_subcarriers.value = nprach_parameter->nprach_NumSubcarriers_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_number_of_repetitions_per_attempt.value = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+
+      //MP: missed configuration for FAPI-style structure (I have added on my own byt maybe are not needed)
+      config_INFO->extra_phy_parms.nprach_config_0_subcarrier_MSG3_range_start = nprach_parameter->nprach_SubcarrierMSG3_RangeStart_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_max_num_preamble_attempt_CE = nprach_parameter->maxNumPreambleAttemptCE_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_num_repetitions_RA = nprach_parameter->npdcch_NumRepetitions_RA_r13; //Rmax
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_startSF_CSS_RA = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_offset_RA = nprach_parameter->npdcch_Offset_RA_r13;
+      //rsrp_ThresholdsPrachInfoList_r13 /*OPTIONAL*/
+
+      break;
+    case 2:
+      nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[0];
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_enabled.value = 1;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_cp_length.value = radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_sf_periodicity.value = nprach_parameter->nprach_Periodicity_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_start_time.value = nprach_parameter->nprach_StartTime_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_subcarrier_offset.value = nprach_parameter->nprach_SubcarrierOffset_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_number_of_subcarriers.value = nprach_parameter->nprach_NumSubcarriers_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_number_of_repetitions_per_attempt.value = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+
+      //MP: missed configuration for FAPI-style structure (I have added on my own byt maybe are not needed)
+      config_INFO->extra_phy_parms.nprach_config_0_subcarrier_MSG3_range_start = nprach_parameter->nprach_SubcarrierMSG3_RangeStart_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_max_num_preamble_attempt_CE = nprach_parameter->maxNumPreambleAttemptCE_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_num_repetitions_RA = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_startSF_CSS_RA = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_offset_RA = nprach_parameter->npdcch_Offset_RA_r13;
+      //rsrp_ThresholdsPrachInfoList_r13 /*OPTIONAL*/
+
+
+      nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[1];
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_enabled.value = 1;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_cp_length.value = radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_sf_periodicity.value = nprach_parameter->nprach_Periodicity_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_start_time.value = nprach_parameter->nprach_StartTime_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_subcarrier_offset.value = nprach_parameter->nprach_SubcarrierOffset_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_number_of_subcarriers.value = nprach_parameter->nprach_NumSubcarriers_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_number_of_repetitions_per_attempt.value = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+
+      //MP: missed configuration for FAPI-style structure (I have added on my own byt maybe are not needed)
+      config_INFO->extra_phy_parms.nprach_config_1_subcarrier_MSG3_range_start = nprach_parameter->nprach_SubcarrierMSG3_RangeStart_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_max_num_preamble_attempt_CE = nprach_parameter->maxNumPreambleAttemptCE_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_npdcch_num_repetitions_RA = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_npdcch_startSF_CSS_RA = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_npdcch_offset_RA = nprach_parameter->npdcch_Offset_RA_r13;
+      //rsrp_ThresholdsPrachInfoList_r13 /*OPTIONAL*/
+      break;
+    case 3:
+      nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[0];
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_enabled.value = 1;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_cp_length.value = radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_sf_periodicity.value = nprach_parameter->nprach_Periodicity_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_start_time.value = nprach_parameter->nprach_StartTime_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_subcarrier_offset.value = nprach_parameter->nprach_SubcarrierOffset_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_number_of_subcarriers.value = nprach_parameter->nprach_NumSubcarriers_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_0_number_of_repetitions_per_attempt.value = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+
+      //MP: missed configuration for FAPI-style structure (I have added on my own byt maybe are not needed)
+      config_INFO->extra_phy_parms.nprach_config_0_subcarrier_MSG3_range_start = nprach_parameter->nprach_SubcarrierMSG3_RangeStart_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_max_num_preamble_attempt_CE = nprach_parameter->maxNumPreambleAttemptCE_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_num_repetitions_RA = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_startSF_CSS_RA = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_0_npdcch_offset_RA = nprach_parameter->npdcch_Offset_RA_r13;
+      //rsrp_ThresholdsPrachInfoList_r13 /*OPTIONAL*/
+
+
+      nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[1];
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_enabled.value = 1;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_cp_length.value = radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_sf_periodicity.value = nprach_parameter->nprach_Periodicity_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_start_time.value = nprach_parameter->nprach_StartTime_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_subcarrier_offset.value = nprach_parameter->nprach_SubcarrierOffset_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_number_of_subcarriers.value = nprach_parameter->nprach_NumSubcarriers_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_1_number_of_repetitions_per_attempt.value = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+
+      //MP: missed configuration for FAPI-style structure (I have added on my own byt maybe are not needed)
+      config_INFO->extra_phy_parms.nprach_config_1_subcarrier_MSG3_range_start = nprach_parameter->nprach_SubcarrierMSG3_RangeStart_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_max_num_preamble_attempt_CE = nprach_parameter->maxNumPreambleAttemptCE_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_npdcch_num_repetitions_RA = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_npdcch_startSF_CSS_RA = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_1_npdcch_offset_RA = nprach_parameter->npdcch_Offset_RA_r13;
+      //rsrp_ThresholdsPrachInfoList_r13 /*OPTIONAL*/
+
+
+      nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[2];
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_enabled.value = 1;
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_cp_length.value = radioResourceConfigCommon->nprach_Config_r13.nprach_CP_Length_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_sf_periodicity.value = nprach_parameter->nprach_Periodicity_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_start_time.value = nprach_parameter->nprach_StartTime_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_subcarrier_offset.value = nprach_parameter->nprach_SubcarrierOffset_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_number_of_subcarriers.value = nprach_parameter->nprach_NumSubcarriers_r13;
+      config_INFO->cfg->config_NB_IoT.nprach_config_2_number_of_repetitions_per_attempt.value = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+
+      //MP: missed configuration for FAPI-style structure (I have added on my own byt maybe are not needed)
+      config_INFO->extra_phy_parms.nprach_config_2_subcarrier_MSG3_range_start = nprach_parameter->nprach_SubcarrierMSG3_RangeStart_r13;
+      config_INFO->extra_phy_parms.nprach_config_2_max_num_preamble_attempt_CE = nprach_parameter->maxNumPreambleAttemptCE_r13;
+      config_INFO->extra_phy_parms.nprach_config_2_npdcch_num_repetitions_RA = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_2_npdcch_startSF_CSS_RA = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+      config_INFO->extra_phy_parms.nprach_config_2_npdcch_offset_RA = nprach_parameter->npdcch_Offset_RA_r13;
+      //rsrp_ThresholdsPrachInfoList_r13 /*OPTIONAL*/
+      break;
+
+    default:
+      LOG_E(RRC,"rrc_mac_config_req_eNB_NB_IoT: nprach_ParametersList size not valid\n");
+      break;
+
+    }
+
+    /*NPDSCH ConfigCommon*/
+
+    //FIXME: MP: FAPI specs define a range of value [0-255]==[0db - 63.75db] with 0.25db step -- corrispondence in 3GPP specs???
+    config_INFO->cfg->rf_config.reference_signal_power.value = radioResourceConfigCommon->npdsch_ConfigCommon_r13.nrs_Power_r13;
+
+    /*NPUSCH ConfigCommon*/
+
+    //a pointer to the first element of the list
+    config_INFO->extra_phy_parms.ack_nack_numRepetitions_MSG4 = radioResourceConfigCommon->npusch_ConfigCommon_r13.ack_NACK_NumRepetitions_Msg4_r13.list.array[0];
+
+
+    if(radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13 != NULL)/* OPTIONAL */
+    {
+      /* OPTIONAL */
+      if(radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_BaseSequence_r13!= NULL)
+          config_INFO->cfg->config_NB_IoT.three_tone_base_sequence.value  = *(radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_BaseSequence_r13);
+      else
+        config_INFO->cfg->config_NB_IoT.three_tone_base_sequence.value = physCellId%12; //see spec TS 36.331 NPUSCH-Config-NB
+
+      /* OPTIONAL */
+      if(radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_BaseSequence_r13!= NULL)
+          config_INFO->cfg->config_NB_IoT.six_tone_base_sequence.value = *(radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_BaseSequence_r13);
+      else
+        config_INFO->cfg->config_NB_IoT.six_tone_base_sequence.value = physCellId%14; //see spec TS 36.331 NPUSCH-Config-NB
+
+      /* OPTIONAL */
+      if(radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->twelveTone_BaseSequence_r13!= NULL)
+        config_INFO->cfg->config_NB_IoT.twelve_tone_base_sequence.value = *(radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->twelveTone_BaseSequence_r13);
+      else
+        config_INFO->cfg->config_NB_IoT.twelve_tone_base_sequence.value = physCellId%30; //see spec TS 36.331 NPUSCH-Config-NB
+
+        config_INFO->cfg->config_NB_IoT.three_tone_cyclic_shift.value = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13;
+        config_INFO->cfg->config_NB_IoT.six_tone_cyclic_shift.value = radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13;
+    }
+
+
+    //NOTE: MP: FAPI specs for UL RS Configurations seems to be targeted for LTE and not for NB-IoT
+    if(radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13 == TRUE)
+      config_INFO->cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 1; //RS_GROUP_HOPPING (FAPI specs pag 127)
+    else
+      config_INFO->cfg->uplink_reference_signal_config.uplink_rs_hopping.value = 0;//RS_NO_HOPPING
+
+    config_INFO->cfg->uplink_reference_signal_config.group_assignment.value = radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13;
+
+    //Some missed parameters are in UL_CONFIG.request message (P7) in FAPI specs. and not configured through P5 procedure
+       //ack_NACK_NumRepetitions_Msg4_r13
+       //srs_SubframeConfig_r13 /* OPTIONAL */
+
+      /*DL GAP config */
+    if(radioResourceConfigCommon->dl_Gap_r13 !=NULL)/* OPTIONAL */
+    {
+      config_INFO->cfg->config_NB_IoT.dl_gap_config_enable.value        = 1;
+      config_INFO->cfg->config_NB_IoT.dl_gap_threshold.value            = radioResourceConfigCommon->dl_Gap_r13->dl_GapThreshold_r13;
+          config_INFO->cfg->config_NB_IoT.dl_gap_duration_coefficient.value = radioResourceConfigCommon->dl_Gap_r13->dl_GapDurationCoeff_r13;
+          config_INFO->cfg->config_NB_IoT.dl_gap_periodicity.value          = radioResourceConfigCommon->dl_Gap_r13->dl_GapPeriodicity_r13;
+    }
+    else
+      config_INFO->cfg->config_NB_IoT.dl_gap_config_enable.value        = 0;
+
+
+      /*UL Power Control ConfigCommon*/
+    //nothing defined in FAPI specs
+    config_INFO->extra_phy_parms.p0_nominal_npusch  = radioResourceConfigCommon->uplinkPowerControlCommon_r13.p0_NominalNPUSCH_r13;
+    config_INFO->extra_phy_parms.alpha              = radioResourceConfigCommon->uplinkPowerControlCommon_r13.alpha_r13;
+    config_INFO->extra_phy_parms.delta_preamle_MSG3 = radioResourceConfigCommon->uplinkPowerControlCommon_r13.deltaPreambleMsg3_r13;
+
+      /*RACH Config Common*/
+    //nothing defined in FAPI specs
+
+}
+
+///-------------------------------------------Function---------------------------------------------///
+
+void rrc_mac_config_req_NB_IoT(
+    module_id_t                             Mod_idP,
+    int                                     CC_idP,
+    int                                     rntiP,
+    rrc_eNB_carrier_data_NB_IoT_t           *carrier,
+    SystemInformationBlockType1_NB_t        *sib1_NB_IoT,
+    RadioResourceConfigCommonSIB_NB_r13_t   *radioResourceConfigCommon,
+    PhysicalConfigDedicated_NB_r13_t        *physicalConfigDedicated,
+    LogicalChannelConfig_NB_r13_t           *logicalChannelConfig,            //FIXME: decide how to use it
+    rrc_config_NB_IoT_t                     *mac_config,
+    uint8_t                                 ded_flag,
+    uint8_t                                 ue_list_ded_num)
+{
+
+    int UE_id = -1;
+
+    //find ue_id here
+
+    config_INFO->get_MIB                                 = 0;
+    config_INFO->get_COMMON                              = 0;
+    config_INFO->get_DEDICATED                           = 0;
+    config_INFO->mod_id                                  = Mod_idP;
+    config_INFO->CC_id                                   = CC_idP;
+    config_INFO->cfg->subframe_config.duplex_mode.value  = 2;               //HD-FDD for NB-IoT
+
+    if (&carrier->mib_NB_IoT != NULL){
+           /*printf(MAC,
+            "Configuring MIB for instance %d, CCid %d : (band %ld,Nid_cell %d,TX antenna port (p) %d,DL freq %u\n",
+            Mod_idP,
+            CC_idP,
+            sib1_NB_IoT->freqBandIndicator_r13,
+            carrier->physCellId,
+            carrier->p_eNB,
+            carrier->dl_CarrierFreq
+           );*/
+
+    /*
+     * Following the FAPI like approach:
+     * 1)fill the PHY_Config_t structure (PHY_INTERFACE/IF_Module_NB_IoT.h)
+     * 2)Call the PHY_config_req for trigger the NB_phy_config_mib_eNB() at the end
+     */
+
+    //XXX where allocate memory for cfg??
+    if(config_INFO->cfg != NULL) LOG_E(MAC, "rrc_mac_config_req_eNB_NB_IoT: trying to configure PHY but no config.request message in config_INFO is allocated\n");
+
+
+    //Mapping OAI params into FAPI params
+            config_mib_fapi_NB_IoT( rntiP,
+                                    carrier->physCellId,
+                                    sib1_NB_IoT->freqBandIndicator_r13,
+                                    carrier->Ncp,
+                                    carrier->Ncp_UL,
+                                    carrier->p_eNB,
+                                    carrier->p_rx_eNB,
+                                    carrier->dl_CarrierFreq,
+                                    carrier->ul_CarrierFreq,
+                                    sib1_NB_IoT->eutraControlRegionSize_r13,
+                                    &carrier->mib_NB_IoT
+                                    );
+
+
+    }
+
+    if(sib1_NB_IoT != NULL)
+    {
+        mac_config->sib1_NB_IoT_sched_config.repetitions = 4;
+        mac_config->sib1_NB_IoT_sched_config.starting_rf = sib1_NB_IoT->si_RadioFrameOffset_r13[0];
+        mac_config->si_window_length = sib1_NB_IoT->si_WindowLength_r13;
+
+        SchedulingInfo_NB_r13_t *scheduling_info_list;
+
+        ///CE level 0
+        scheduling_info_list = sib1_NB_IoT->schedulingInfoList_r13.list.array[0];
+
+        mac_config->sibs_NB_IoT_sched[0].si_periodicity =           scheduling_info_list->si_Periodicity_r13 ;
+        mac_config->sibs_NB_IoT_sched[0].si_repetition_pattern =    scheduling_info_list->si_RepetitionPattern_r13 ;
+        mac_config->sibs_NB_IoT_sched[0].sib_mapping_info =         scheduling_info_list->sib_MappingInfo_r13.list.array[0][0] | scheduling_info_list->sib_MappingInfo_r13.list.array[1][0];
+        mac_config->sibs_NB_IoT_sched[0].si_tb =                    scheduling_info_list->si_TB_r13  ;
+
+        ///CE level 1
+        scheduling_info_list = sib1_NB_IoT->schedulingInfoList_r13.list.array[1];
+
+        mac_config->sibs_NB_IoT_sched[1].si_periodicity =           scheduling_info_list->si_Periodicity_r13 ;
+        mac_config->sibs_NB_IoT_sched[1].si_repetition_pattern =    scheduling_info_list->si_RepetitionPattern_r13 ;
+        mac_config->sibs_NB_IoT_sched[1].sib_mapping_info =         scheduling_info_list->sib_MappingInfo_r13.list.array[0][0] | scheduling_info_list->sib_MappingInfo_r13.list.array[1][0];
+        mac_config->sibs_NB_IoT_sched[1].si_tb =                    scheduling_info_list->si_TB_r13  ;
+
+        ///CE level 2
+        scheduling_info_list = sib1_NB_IoT->schedulingInfoList_r13.list.array[2];
+
+        mac_config->sibs_NB_IoT_sched[2].si_periodicity =           scheduling_info_list->si_Periodicity_r13 ;
+        mac_config->sibs_NB_IoT_sched[2].si_repetition_pattern =    scheduling_info_list->si_RepetitionPattern_r13 ;
+        mac_config->sibs_NB_IoT_sched[2].sib_mapping_info =         scheduling_info_list->sib_MappingInfo_r13.list.array[0][0] | scheduling_info_list->sib_MappingInfo_r13.list.array[1][0];
+        mac_config->sibs_NB_IoT_sched[2].si_tb =                    scheduling_info_list->si_TB_r13  ;
+
+        mac_config->sibs_NB_IoT_sched[3].sib_mapping_info = 0x0;
+        mac_config->sibs_NB_IoT_sched[4].sib_mapping_info = 0x0;
+        mac_config->sibs_NB_IoT_sched[5].sib_mapping_info = 0x0;
+    }
+
+
+    if (radioResourceConfigCommon!=NULL) {
+
+        //if(config_INFO->cfg == NULL) LOG_E(MAC, "rrc_mac_config_req_eNB_NB_IoT: trying to configure PHY but no config.request message in config_INFO is allocated\n");
+
+        config_INFO->get_COMMON = 1;
+
+        //LOG_I(MAC,"[CONFIG]SIB2/3-NB radioResourceConfigCommon Contents (partial)\n");
+
+        //LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13= %ld\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13);
+        //LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13= %ld\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13);
+        //LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13= %d\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13);
+        //LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13= %ld\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13);
+
+        NPRACH_Parameters_NB_r13_t* nprach_parameter;
+
+        ///CE level 0
+        nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[0];
+
+        mac_config->mac_NPRACH_ConfigSIB[0].mac_numRepetitionsPerPreambleAttempt_NB_IoT = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+        mac_config->mac_NPRACH_ConfigSIB[0].mac_npdcch_NumRepetitions_RA_NB_IoT         = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+        mac_config->mac_NPRACH_ConfigSIB[0].mac_npdcch_StartSF_CSS_RA_NB_IoT            = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+        mac_config->mac_NPRACH_ConfigSIB[0].mac_npdcch_Offset_RA_NB_IoT                 = nprach_parameter->npdcch_Offset_RA_r13;
+
+        ///CE level 1
+        nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[1];
+
+        mac_config->mac_NPRACH_ConfigSIB[1].mac_numRepetitionsPerPreambleAttempt_NB_IoT = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+        mac_config->mac_NPRACH_ConfigSIB[1].mac_npdcch_NumRepetitions_RA_NB_IoT         = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+        mac_config->mac_NPRACH_ConfigSIB[1].mac_npdcch_StartSF_CSS_RA_NB_IoT            = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+        mac_config->mac_NPRACH_ConfigSIB[1].mac_npdcch_Offset_RA_NB_IoT                 = nprach_parameter->npdcch_Offset_RA_r13;
+
+        ///CE level 2
+        nprach_parameter = radioResourceConfigCommon->nprach_Config_r13.nprach_ParametersList_r13.list.array[2];
+
+        mac_config->mac_NPRACH_ConfigSIB[2].mac_numRepetitionsPerPreambleAttempt_NB_IoT = nprach_parameter->numRepetitionsPerPreambleAttempt_r13;
+        mac_config->mac_NPRACH_ConfigSIB[2].mac_npdcch_NumRepetitions_RA_NB_IoT         = nprach_parameter->npdcch_NumRepetitions_RA_r13;
+        mac_config->mac_NPRACH_ConfigSIB[2].mac_npdcch_StartSF_CSS_RA_NB_IoT            = nprach_parameter->npdcch_StartSF_CSS_RA_r13;
+        mac_config->mac_NPRACH_ConfigSIB[2].mac_npdcch_Offset_RA_NB_IoT                 = nprach_parameter->npdcch_Offset_RA_r13;
+
+
+        //eNB_mac_inst_NB_IoT[Mod_idP].common_channels[CC_idP].radioResourceConfigCommon  = radioResourceConfigCommon;
+        if (carrier->ul_CarrierFreq>0)
+        //eNB_mac_inst_NB_IoT[Mod_idP].common_channels[CC_idP].ul_CarrierFreq   = ul_CarrierFreq;
+
+        config_sib2_fapi_NB_IoT(carrier->physCellId,radioResourceConfigCommon);
+
+    }
+
+    if (logicalChannelConfig!= NULL) {
+
+
+        if(config_INFO->cfg == NULL) LOG_E(MAC, "rrc_mac_config_req_eNB_NB_IoT: trying to configure PHY but no config.request message in config_INFO is allocated\n");
+
+        if (UE_id == -1)
+        {
+            LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__);
+        }
+        else
+        {
+        //logical channel group not defined for nb-iot --> no UL specific Parameter
+        // or at least LCGID should be set to 0 for NB-IoT (See TS 36.321 ch 6.1.3.1) so no make sense to store this
+        }
+    }
+
+    if (physicalConfigDedicated != NULL) {
+
+
+        if(config_INFO->cfg == NULL) LOG_E(MAC, "rrc_mac_config_req_eNB_NB_IoT: trying to configure PHY but no config.request message in config_INFO is allocated\n");
+
+        if (UE_id == -1)
+            LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__);
+        else
+        {
+
+        config_INFO->get_DEDICATED = 1;
+
+        //XXX this parameters seems to be not defined by FAPi specs
+        //this are UE specific information that should be transmitted to the PHY layer
+        //use UE-specific structure at phy layer where to store this information (NPDCCH structure) this structure will be scrambled based on the rnti
+        //config_INFO->rnti = UE_RNTI_NB_IoT(Mod_idP, UE_id);
+        config_INFO->extra_phy_parms.npdcch_NumRepetitions = physicalConfigDedicated->npdcch_ConfigDedicated_r13->npdcch_NumRepetitions_r13; //Rmax
+        config_INFO->extra_phy_parms.npdcch_Offset_USS     = physicalConfigDedicated->npdcch_ConfigDedicated_r13->npdcch_Offset_USS_r13;
+        config_INFO->extra_phy_parms.npdcch_StartSF_USS    = physicalConfigDedicated->npdcch_ConfigDedicated_r13->npdcch_StartSF_USS_r13;
+
+        //config_INFO->extra_phy_parms.phy_config_dedicated = physicalConfigDedicated; //for the moment fapi not allow this so not used
+
+        }
+    }
+
+    //Now trigger the phy_config_xxx for configuring PHY through the PHY_config_req
+     AssertFatal(if_inst->PHY_config_req != NULL, "rrc_mac_config_req_eNB_NB_IoT: PHY_config_req pointer function is NULL\n");
+    if(if_inst->PHY_config_req)
+        if_inst->PHY_config_req(config_INFO);
+
+    //return 0;
+
+      init_mac_NB_IoT(mac_inst);
+
+
+   /*if( ded_flag!=0 )
+   {
+    
+    mac_config->npdcch_ConfigDedicated[0].R_max         =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[0].npdcch_ConfigDedicated_r13->npdcch_NumRepetitions_r13;
+    mac_config->npdcch_ConfigDedicated[1].R_max         =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[1].npdcch_ConfigDedicated_r13->npdcch_NumRepetitions_r13;
+    mac_config->npdcch_ConfigDedicated[2].R_max         =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[2].npdcch_ConfigDedicated_r13->npdcch_NumRepetitions_r13;
+
+    mac_config->npdcch_ConfigDedicated[0].G             =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[0].npdcch_ConfigDedicated_r13->npdcch_StartSF_USS_r13;
+    mac_config->npdcch_ConfigDedicated[1].G             =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[1].npdcch_ConfigDedicated_r13->npdcch_StartSF_USS_r13;
+    mac_config->npdcch_ConfigDedicated[2].G             =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[2].npdcch_ConfigDedicated_r13->npdcch_StartSF_USS_r13;
+
+    mac_config->npdcch_ConfigDedicated[0].a_offset      =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[0].npdcch_ConfigDedicated_r13->npdcch_Offset_USS_r13;
+    mac_config->npdcch_ConfigDedicated[1].a_offset      =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[1].npdcch_ConfigDedicated_r13->npdcch_Offset_USS_r13;
+    mac_config->npdcch_ConfigDedicated[2].a_offset      =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[2].npdcch_ConfigDedicated_r13->npdcch_Offset_USS_r13;
+    
+    // now we only have 3 UE list USS
+    mac_config->npdcch_ConfigDedicated[ue_list_ded_num].R_max         =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[ue_list_ded_num].npdcch_ConfigDedicated_r13->npdcch_NumRepetitions_r13;
+
+    mac_config->npdcch_ConfigDedicated[ue_list_ded_num].G             =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[ue_list_ded_num].npdcch_ConfigDedicated_r13->npdcch_StartSF_USS_r13;
+
+    mac_config->npdcch_ConfigDedicated[ue_list_ded_num].a_offset      =DED_Config.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13[ue_list_ded_num].npdcch_ConfigDedicated_r13->npdcch_Offset_USS_r13;
+    }
+
+
+    return 0;*/
+
+
+}
\ No newline at end of file
diff --git a/openair2/LAYER2/MAC/config_NB_IoT.h b/openair2/LAYER2/MAC/config_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..cb0d445e3f511125255f8b9b5544197e60da8939
--- /dev/null
+++ b/openair2/LAYER2/MAC/config_NB_IoT.h
@@ -0,0 +1,301 @@
+
+/*! \file config_NB_IoT.h
+ * \brief configured structures used by scheduler
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#ifndef _CONFIG_H_
+#define _CONFIG_H_
+
+//#include "NB_IoT_Message_definitions.h"
+
+#define NUMBER_OF_SIBS_MAX_NB_IoT 6
+
+///MIB
+typedef enum operationModeInf{
+    iNB_IoTand_SamePCI_r13          = 1,
+    iNB_IoTand_DifferentPCI_r13     = 2,
+    guardband_r13               = 3,
+    standalone_r13              = 4
+}operationModeInf_t;
+
+///SIB1_SchedulingInfo_NB_IoT_r13
+typedef enum si_Periodicity{
+    si_Periodicity_rf64=640,
+    si_Periodicity_rf128=1280,
+    si_Periodicity_rf256=2560,
+    si_Periodicity_rf512=5120,
+    si_Periodicity_rf1024=10240,
+    si_Periodicity_rf2048=20480,
+    si_Periodicity_rf4096=40960
+}si_Periodicity_NB_IoT;
+
+typedef enum si_RepetitionPattern{
+    si_RepetitionPattern_every2ndRF=20,
+    si_RepetitionPattern_every4thRF=40,
+    si_RepetitionPattern_every8thRF=80,
+    si_RepetitionPattern_every16thRF=160
+}si_RepetitionPattern_NB_IoT;
+
+typedef enum sib_MappingInfo{
+    sib2_v=0x1,
+    sib3_v=0x2,
+    sib4_v=0x4,
+    sib5_v=0x8,
+    sib14_v=0x10,
+    sib16_v=0x20
+}sib_MappingInfo_NB_IoT;
+
+typedef enum si_TB{
+    si_TB_56=56,
+    si_TB_120=120,
+    si_TB_208=208,
+    si_TB_256=256,
+    si_TB_328=328,
+    si_TB_440=440,
+    si_TB_552=552,
+    si_TB_680=680
+}si_TB_NB_IoT;
+
+///RACH_ConfigCommon configuration
+
+typedef enum ra_ResponseWindowSize{
+    ra_ResponseWindowSize_pp2=2,
+    ra_ResponseWindowSize_pp3=3,
+    ra_ResponseWindowSize_pp4=4,
+    ra_ResponseWindowSize_pp5=5,
+    ra_ResponseWindowSize_pp6=6,
+    ra_ResponseWindowSize_pp7=7,
+    ra_ResponseWindowSize_pp8=8,
+    ra_ResponseWindowSize_pp10=10
+}ra_ResponseWindowSize_NB_IoT;
+
+typedef enum mac_ContentionResolutionTimer{
+    mac_ContentionResolutionTimer_pp1=1,
+    mac_ContentionResolutionTimer_pp2=2,
+    mac_ContentionResolutionTimer_pp3=3,
+    mac_ContentionResolutionTimer_pp4=4,
+    mac_ContentionResolutionTimer_pp8=8,
+    mac_ContentionResolutionTimer_pp16=16,
+    mac_ContentionResolutionTimer_pp32=32,
+    mac_ContentionResolutionTimer_pp64=64
+}mac_ContentionResolutionTimer_NB_IoT;
+
+///NPRACH_ConfigSIB configuration
+
+typedef enum nprach_Periodicity{
+    nprach_Periodicity_ms40=40,
+    nprach_Periodicity_ms80=80,
+    nprach_Periodicity_ms160=160,
+    nprach_Periodicity_ms240=240,
+	nprach_Periodicity_ms320=320,
+    nprach_Periodicity_ms640=640,
+    nprach_Periodicity_ms1280=1280,
+    nprach_Periodicity_ms2560=2560
+}nprach_Periodicity_NB_IoT;
+
+typedef enum nprach_StartTime{
+    nprach_StartTime_ms8=8,
+    nprach_StartTime_ms16=16,
+    nprach_StartTime_ms32=32,
+    nprach_StartTime_ms64=64,
+    nprach_StartTime_ms128=128,
+    nprach_StartTime_ms256=256,
+    nprach_StartTime_ms512=512,
+    nprach_StartTime_ms1024=1024
+}nprach_StartTime_NB_IoT;
+
+typedef enum nprach_SubcarrierOffset{
+    nprach_SubcarrierOffset_n0=0,
+    nprach_SubcarrierOffset_n12=12,
+    nprach_SubcarrierOffset_n24=24,
+    nprach_SubcarrierOffset_n36=36,
+    nprach_SubcarrierOffset_n2=2,
+    nprach_SubcarrierOffset_n18=18,
+    nprach_SubcarrierOffset_n34=34
+}nprach_SubcarrierOffset_NB_IoT;
+
+typedef enum nprach_NumSubcarriers{
+    nprach_NumSubcarriers_n12=12,
+    nprach_NumSubcarriers_n24=24,
+    nprach_NumSubcarriers_n36=36,
+    nprach_NumSubcarriers_n48=48
+}nprach_NumSubcarriers_NB_IoT;
+
+typedef enum nprach_SubcarrierMSG3_RangeStart{
+    nprach_SubcarrierMSG3_RangeStart_zero=0,
+    nprach_SubcarrierMSG3_RangeStart_oneThird=1/3,
+    nprach_SubcarrierMSG3_RangeStart_twoThird=2/3,
+    nprach_SubcarrierMSG3_RangeStart_one=1
+}nprach_SubcarrierMSG3_RangeStart_NB_IoT;
+
+typedef enum maxNumPreambleAttemptCE{
+    maxNumPreambleAttemptCE_n3=3,
+    maxNumPreambleAttemptCE_n4=4,
+    maxNumPreambleAttemptCE_n5=5,
+    maxNumPreambleAttemptCE_n6=6,
+    maxNumPreambleAttemptCE_n7=7,
+    maxNumPreambleAttemptCE_n8=8,
+    maxNumPreambleAttemptCE_n10=10
+}maxNumPreambleAttemptCE_NB_IoT;
+
+typedef enum numRepetitionsPerPreambleAttempt{
+    numRepetitionsPerPreambleAttempt_n1=1,
+    numRepetitionsPerPreambleAttempt_n2=2,
+    numRepetitionsPerPreambleAttempt_n4=4,
+    numRepetitionsPerPreambleAttempt_n8=8,
+    numRepetitionsPerPreambleAttempt_n16=16,
+    numRepetitionsPerPreambleAttempt_n32=32,
+    numRepetitionsPerPreambleAttempt_n64=64,
+    numRepetitionsPerPreambleAttempt_n128=128
+}numRepetitionsPerPreambleAttempt_NB_IoT;
+
+typedef enum npdcch_NumRepetitions_RA{
+    npdcch_NumRepetitions_RA_r1=1,
+    npdcch_NumRepetitions_RA_r2=2,
+    npdcch_NumRepetitions_RA_r4=4,
+    npdcch_NumRepetitions_RA_r8=8,
+    npdcch_NumRepetitions_RA_r16=16,
+    npdcch_NumRepetitions_RA_r32=32,
+    npdcch_NumRepetitions_RA_r64=64,
+    npdcch_NumRepetitions_RA_r128=128,
+    npdcch_NumRepetitions_RA_r256=256,
+    npdcch_NumRepetitions_RA_r512=512,
+    npdcch_NumRepetitions_RA_r1024=1024,
+    npdcch_NumRepetitions_RA_r2048=2048
+}npdcch_NumRepetitions_RA_NB_IoT;
+
+typedef enum npdcch_StartSF_CSS_RA{
+    npdcch_StartSF_CSS_RA_v1dot5=3/2,
+    npdcch_StartSF_CSS_RA_v2=2,
+    npdcch_StartSF_CSS_RA_v4=4,
+    npdcch_StartSF_CSS_RA_v8=8,
+    npdcch_StartSF_CSS_RA_v16=16,
+    npdcch_StartSF_CSS_RA_v32=32,
+    npdcch_StartSF_CSS_RA_v48=48,
+    npdcch_StartSF_CSS_RA_v64=64
+}npdcch_StartSF_CSS_RA_NB_IoT;
+
+typedef enum npdcch_Offset_RA{
+    zero=0,
+    oneEighth=1/8,
+    oneFourth=1/4,
+    threeEighth=3/8
+}npdcch_Offset_RA_NB_IoT;
+
+typedef enum si_window_length_e{
+    ms160=160,
+    ms320=320,
+    ms480=480,
+    ms640=640,
+    ms960=960,
+    ms1280=1280,
+    ms1600=1600
+}si_window_length_t;
+
+typedef enum si_periodicity_e{
+    rf64=640,
+    rf128=1280,
+    rf256=2560,
+    rf512=5120,
+	rf1024=10240,
+    rf2048=20480,
+    rf4096=40960
+}si_periodicity_t;
+
+typedef enum si_repetition_pattern_e{
+    every2ndRF=20,
+    every4thRF=40,
+	every8thRF=80,
+    every16thRF=160
+}si_repetition_pattern_t;
+
+typedef enum si_tb_e{
+    b56=2,
+    b120=2,
+    b208=8,
+    b256=8,
+    b328=8,
+    b440=8,
+    b552=8,
+    b680=8
+}si_tb_t;
+
+
+typedef struct sibs_NB_IoT_sched_s{
+	si_periodicity_t si_periodicity;
+    si_repetition_pattern_t si_repetition_pattern;
+    sib_MappingInfo_NB_IoT sib_mapping_info;   //bit vector
+    si_tb_t si_tb;
+
+}sibs_NB_IoT_sched_t;
+
+
+///-------------------------------------------------------MAC--------------------------------------------------------------------///
+typedef struct sib1_NB_IoT_sched_s{
+    int repetitions;    //  4, 8, 16
+    int starting_rf;
+}sib1_NB_IoT_sched_t;
+
+typedef struct {
+
+    uint32_t    mac_ra_ResponseWindowSize_NB_IoT;
+    uint32_t    mac_ContentionResolutionTimer_NB_IoT;
+
+}mac_RACH_ConfigCommon_NB_IoT;
+
+typedef struct {
+
+    uint32_t    mac_nprach_Periodicity_NB_IoT;
+    uint32_t    mac_nprach_StartTime_NB_IoT;
+    uint32_t    mac_nprach_SubcarrierOffset_NB_IoT;
+    uint32_t    mac_nprach_NumSubcarriers_NB_IoT;
+    uint32_t    mac_nprach_SubcarrierMSG3_RangeStart_NB_IoT;
+    uint32_t    mac_maxNumPreambleAttemptCE_NB_IoT;
+    uint32_t    mac_numRepetitionsPerPreambleAttempt_NB_IoT;
+	//	css
+    uint32_t    mac_npdcch_NumRepetitions_RA_NB_IoT;		//	rmax
+    uint32_t    mac_npdcch_StartSF_CSS_RA_NB_IoT;			//	G
+    uint32_t    mac_npdcch_Offset_RA_NB_IoT;				//	alpha offset
+
+}mac_NPRACH_ConfigSIB_NB_IoT;
+
+typedef struct{
+    //npdcch-NumRepetitions-r13
+    uint32_t R_max;
+    //npdcch-StartSF-USS-r13
+    double G;
+    //npdcch-Offset-USS-r13
+    double a_offset;
+}npdcch_ConfigDedicated_NB_IoT;
+
+typedef struct rrc_config_NB_IoT_s{
+
+    ///MIB
+    uint16_t schedulingInfoSIB1_NB_IoT;
+
+    ///SIB1
+    uint32_t cellIdentity_NB_IoT;
+
+	sib1_NB_IoT_sched_t sib1_NB_IoT_sched_config;
+	///SIBS
+	sibs_NB_IoT_sched_t sibs_NB_IoT_sched[NUMBER_OF_SIBS_MAX_NB_IoT];
+	si_window_length_t si_window_length;
+	uint32_t si_radio_frame_offset;
+
+    ///SIB2 mac_RACH_ConfigCommon_NB_IoT
+    mac_RACH_ConfigCommon_NB_IoT mac_RACH_ConfigCommon[3];
+
+    ///SIB2 mac_NPRACH_ConfigSIB_NB_IoT
+    mac_NPRACH_ConfigSIB_NB_IoT mac_NPRACH_ConfigSIB[3];
+
+    ///NPDCCH Dedicated config
+    npdcch_ConfigDedicated_NB_IoT npdcch_ConfigDedicated[3];
+
+}rrc_config_NB_IoT_t;
+
+#endif
diff --git a/openair2/LAYER2/MAC/defs_NB_IoT.h b/openair2/LAYER2/MAC/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..8d713da8b23720d5461b26584d4f332f03d17170
--- /dev/null
+++ b/openair2/LAYER2/MAC/defs_NB_IoT.h
@@ -0,0 +1,537 @@
+
+/*! \file defs_NB_IoT.c
+ * \brief MAC layer structures
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+#ifndef __LAYER2_MAC_DEFS_NB_IOT_H__
+#define __LAYER2_MAC_DEFS_NB_IOT_H__
+#ifdef USER_MODE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+//#include "COMMON/openair_defs.h"
+#include "COMMON/platform_constants.h"
+#include "COMMON/mac_rrc_primitives.h"
+#include "PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
+#include "config_NB_IoT.h"
+
+#define sim_end_time 100000
+
+//  MAC definition
+#define MAX_FRAME 0xfffff
+#define MAX(a, b) ((a>b)?a:b)
+
+//  RA-RNTI: 1+SFN_id>>2
+#define RA_RNTI_LOW   0x0001  //  SFN_id = 0
+#define RA_RNTI_HIGH  0x0100  //  SFN_id = 1023
+#define C_RNTI_LOW  0x0101
+#define C_RNTI_HIGH
+
+// ULSCH LCHAN IDs
+/*!\brief LCID of extended power headroom for ULSCH */
+#define EXTENDED_POWER_HEADROOM 25
+/*!\brief LCID of power headroom for ULSCH */
+#define POWER_HEADROOM 26
+/*!\brief LCID of CRNTI for ULSCH */
+#define CRNTI 27
+/*!\brief LCID of truncated BSR for ULSCH */
+#define TRUNCATED_BSR 28
+/*!\brief LCID of short BSR for ULSCH */
+#define SHORT_BSR 29
+/*!\brief LCID of long BSR for ULSCH */
+#define LONG_BSR 30
+/*! \brief Values of CCCH LCID for DLSCH */ 
+#define CCCH_LCHANID 0
+/*!\brief Values of BCCH logical channel */
+#define BCCH 3  // SI 
+/*!\brief Values of PCCH logical channel */
+#define PCCH 4  // Paging 
+/*!\brief Value of CCCH / SRB0 logical channel */
+#define CCCH 0  // srb0
+/*!\brief DCCH / SRB1 logical channel */
+#define DCCH 1  // srb1
+/*!\brief DCCH1 / SRB2  logical channel */
+#define DCCH1 2 // srb2
+/*!\brief DTCH DRB1  logical channel */
+#define DTCH 3 // LCID
+/*!\brief MCCH logical channel */
+#define MCCH 4 
+/*!\brief MTCH logical channel */
+#define MTCH 1 
+// DLSCH LCHAN ID
+/*!\brief LCID of UE contention resolution identity for DLSCH*/
+#define UE_CONT_RES 28
+/*!\brief LCID of timing advance for DLSCH */
+#define TIMING_ADV_CMD 29
+/*!\brief LCID of discontinous reception mode for DLSCH */
+#define DRX_CMD 30
+/*!\brief LCID of padding LCID for DLSCH */
+#define SHORT_PADDING 31
+
+
+typedef enum tone_type_e
+{
+  sixtone = 0,
+  threetone,
+  singletone1,
+  singletone2,
+  singletone3
+}tone_type_t;
+
+typedef enum channel_NB_IoT_e
+{
+  NPDCCH = 0,
+  NPUSCH,
+  NPDSCH
+}channel_NB_IoT_t;
+
+typedef enum{
+  UL = 0,
+  DL
+}message_direction_t;
+
+#define MAX_NUMBER_OF_UE_MAX_NB_IoT 20
+#define SCH_PAYLOAD_SIZE_MAX_NB_IoT 320
+#define MAX_NUMBER_OF_SIBs_NB_IoT 16
+
+/*!\brief Values of BCCH0 logical channel for MIB*/
+#define BCCH0_NB_IoT 11 // MIB-NB_IoT
+/*!\brief Values of BCCH1 logical channel for SIBs */
+#define BCCH1_NB_IoT 12 // SI-SIB-NB_IoTs
+/*!\brief Values of PCCH logical channel */
+#define PCCH_NB_IoT 13  // Paging XXX not used for the moment
+#define MCCH_NB_IoT 14
+/*!\brief Value of CCCH / SRB0 logical channel */
+#define CCCH_NB_IoT 0  // srb0 ---> XXX exactly the same as in LTE (commented for compilation purposes)
+/*!\brief DCCH0 / SRB1bis logical channel */
+#define DCCH0_NB_IoT 3  // srb1bis
+/*!\brief DCCH1 / SRB1  logical channel */
+#define DCCH1_NB_IoT 1 // srb1 //XXX we redefine it for the SRB1
+/*!\brief DTCH0 DRB0  logical channel */
+#define DTCH0_NB_IoT 4 // DRB0
+/*!\brief DTCH1 DRB1  logical channel */
+#define DTCH1_NB_IoT 5 // DRB1
+/*Index of UE contention resoulution logical channel*/
+#define UE_CONTENTION_RESOLUTION 28
+/*Index of TIMING_ADVANCE logical channel*/
+#define TIMING_ADVANCE 29
+/*Index of DRX_COMMAND logical channel*/
+#define DRX_COMMAND 30
+/*Index of PADDING logical channel*/
+#define PADDING 31
+
+
+/// NPRACH-ParametersList-NB_IoT-r13 from 36.331 RRC spec defined in PHY
+/*typedef struct NPRACH_Parameters_NB_IoT{
+
+    /// the period time for nprach
+    int nprach_Periodicity;
+    /// for the start time for the NPRACH resource from 40ms-2560ms
+    int nprach_StartTime;
+    /// for the subcarrier of set to the NPRACH preamble from n0 - n34
+    int nprach_SubcarrierOffset;
+    ///number of subcarriers in a NPRACH resource allowed values (n12,n24,n36,n48)
+    int nprach_NumSubcarriers;
+    /// where is the region that in NPRACH resource to indicate if this UE support MSG3 for multi-tone or not. from 0 - 1
+    int nprach_SubcarrierMSG3_RangeStart;
+    /// The max preamble transmission attempt for the CE level from 1 - 128
+    int maxNumPreambleAttemptCE;
+    /// Number of NPRACH repetitions per attempt for each NPRACH resource
+    int numRepetitionsPerPreambleAttempt;
+    /// The number of the repetition for DCI use in RAR/MSG3/MSG4 from 1 - 2048 (Rmax)
+    int npdcch_NumRepetitions_RA;
+    /// Starting subframe for NPDCCH Common searching space for (RAR/MSG3/MSG4)
+    int npdcch_StartSF_CSS_RA;
+    /// Fractional period offset of starting subframe for NPDCCH common search space
+    int npdcch_Offset_RA;
+
+} nprach_parameters_NB_IoT_t;*/
+
+/*! \brief Downlink SCH PDU Structure */
+typedef struct {
+  uint8_t payload[SCH_PAYLOAD_SIZE_MAX_NB_IoT];
+  uint32_t pdu_size;
+} __attribute__ ((__packed__)) DLSCH_PDU_NB_IoT;
+
+/*! \brief eNB template for UE context information  */
+typedef struct {
+    // C-RNTI of UE
+  rnti_t rnti;
+  // UE CE level
+  int CE_level;
+  // Direction of transmission(DL:0\UL:1\NONE:-1)
+  int32_t direction;
+  // DCI Reptition
+  uint32_t R_dci;
+  // MAX repetition
+  uint32_t R_max;
+
+  // HARQ round
+  uint32_t HARQ_round;
+  /*Downlink information*/
+
+  /// DLSCH pdu
+  DLSCH_PDU_NB_IoT DLSCH_pdu;
+  // PDU size
+  uint32_t DLSCH_pdu_size;
+  // Data Reptition
+  uint32_t R_dl;
+  // MCS index
+  uint32_t I_mcs_dl;
+  // total downlink buffer DCCH0_NB_IoT
+  uint32_t dl_buffer_DCCH0_NB_IoT;
+  // NDI
+  int oldNDI_DL;
+  //HARQ ACK/NACK repetition
+  uint32_t R_harq;
+
+  /*Uplink information*/
+  int oldNDI_UL;
+  // Uplink data repeat, now just follow the rach repeat number
+  uint32_t R_ul;
+  // PHR value (0-3)
+  uint32_t PHR;
+  // The uplink data size from BSR or DVI
+  uint32_t ul_total_buffer;
+  // Determine if this UE support multi-tone transmission or not
+  int multi_tone;
+  // Next UE_template ID
+  int next;
+  // Previous UE_template ID
+  int prev;
+  // MSG4 complete
+  int RRC_connected;
+  // UE active flag
+  boolean_t active;
+
+} UE_TEMPLATE_NB_IoT;
+
+/*36331 NPDCCH-ConfigDedicated-NB_IoT*/
+typedef struct{
+  //npdcch-NumRepetitions-r13
+  uint32_t R_max;
+  //npdcch-StartSF-USS-r13
+  double G;
+  //npdcch-Offset-USS-r13
+  double a_offset;
+  //NPDCCH period
+  uint32_t T;
+  //Starting subfrane of Search Space which is mod T
+  uint32_t ss_start_uss;
+}NPDCCH_config_dedicated_NB_IoT_t;
+
+
+/*! \brief UE list used by eNB to order UEs/CC for scheduling*/
+typedef struct {
+
+  /// DCI template and MAC connection parameters for UEs
+  UE_TEMPLATE_NB_IoT UE_template_NB_IoT[NUMBER_OF_UE_MAX_NB_IoT];
+
+  /// NPDCCH Period and searching space info
+  NPDCCH_config_dedicated_NB_IoT_t NPDCCH_config_dedicated;
+  //int next[MAX_NUMBER_OF_UE_MAX_NB_IoT];
+  // -1:No UE in list
+  int head;
+  // -1:No UE in list
+  int tail;
+  int num_UEs;
+  //boolean_t active[MAX_NUMBER_OF_UE_MAX_NB_IoT];
+
+} UE_list_NB_IoT_t;
+
+
+typedef struct{
+
+  // flag to indicate scheduing MIB-NB_IoT
+  uint8_t flag_MIB;
+  // flag to indicate scheduling SIB1-NB_IoT
+  uint8_t flag_SIB1;
+  // flag to indicate scheduling SIBs-NB_IoT
+  uint8_t flag_SIBs[MAX_NUMBER_OF_SIBs_NB_IoT];
+  // flag to indicate scheduling type2 NPDCCH CSS with different CE level
+  uint8_t flag_type2_css[3];
+  // flag to indicate scheduling type1 NPDCCH CSS with different CE level
+  uint8_t flag_type1_css[3];
+  // flag to indicate scheduling NPDCCH USS with UE list
+  uint8_t flag_uss[MAX_NUMBER_OF_UE_MAX_NB_IoT];
+  // flag to indicate scheduling sib1/MIB
+  uint8_t flag_fix_scheduling;
+  // number of the type2 css to schedule in this period
+  uint8_t num_type2_css_run;
+  // number of the type1 css to schedule in this period
+  uint8_t num_type1_css_run;
+  // number of the uss to schedule in this period
+  uint8_t num_uss_run;
+
+}scheduling_flag_t;
+
+typedef struct available_resource_UL_s{
+
+    ///Resource start subframe
+    uint32_t start_subframe;
+    ///Resource end subframe
+    uint32_t end_subframe;
+    // pointer to next node
+    struct available_resource_UL_s *next, *prev;
+
+}available_resource_UL_t;
+
+typedef struct available_resource_DL_s{
+  uint32_t start_subframe;
+  uint32_t end_subframe;
+  uint32_t DLSF_num;
+
+  struct available_resource_DL_s *next, *prev;
+}available_resource_DL_t;
+
+/*Structure used for scheduling*/
+typedef struct{
+  //resource position info.
+  uint32_t sf_end,sf_start;
+  //resource position info. separate by HyperSF, Frame, Subframe
+  uint32_t start_h, end_h;
+  uint32_t start_f, end_f;
+  uint32_t start_sf, end_sf;
+  //whcih available resource node is used
+  available_resource_DL_t *node;
+}sched_temp_DL_NB_IoT_t;
+
+/*!\brief  MAC subheader short with 7bit Length field */
+typedef struct {
+  uint8_t LCID:5;  // octet 1 LSB
+  uint8_t E:1;
+  uint8_t F2:1;
+  uint8_t R:1;     // octet 1 MSB
+  uint8_t L:7;     // octet 2 LSB
+  uint8_t F:1;     // octet 2 MSB
+} __attribute__((__packed__))SCH_SUBHEADER_SHORT_NB_IoT;
+typedef struct {
+  uint8_t LCID:5;   // octet 1 LSB
+  uint8_t E:1;
+  uint8_t F2:1;
+  uint8_t R:1;      // octet 1 MSB
+  uint8_t L_MSB:7;
+  uint8_t F:1;      // octet 2 MSB
+  uint8_t L_LSB:8;
+} __attribute__((__packed__))SCH_SUBHEADER_LONG_NB_IoT;
+typedef struct {
+  uint8_t LCID:5;   // octet 1 LSB
+  uint8_t E:1;
+  uint8_t F2:1;
+  uint8_t R:1;      // octet 1 MSB
+  uint8_t L_MSB:8;      // octet 2 MSB
+  uint8_t L_LSB:8;
+} __attribute__((__packed__))SCH_SUBHEADER_LONG_EXTEND_NB_IoT;
+/*!\brief MAC subheader short without length field */
+typedef struct {
+  uint8_t LCID:5;
+  uint8_t F2:1;
+  uint8_t E:1;
+  uint8_t R:1;
+} __attribute__((__packed__))SCH_SUBHEADER_FIXED_NB_IoT;
+
+
+/*! \brief Uplink SCH PDU Structure */
+typedef struct {
+  int8_t payload[SCH_PAYLOAD_SIZE_MAX_NB_IoT];         /*!< \brief SACH payload */
+  uint16_t Pdu_size;
+} __attribute__ ((__packed__)) ULSCH_PDU_NB_IoT;
+
+typedef struct {
+  uint8_t PH:6;
+  uint8_t R:2;
+} __attribute__((__packed__))POWER_HEADROOM_CMD_NB_IoT;
+
+typedef struct {
+  uint8_t RAPID:6;
+  uint8_t T:1;
+  uint8_t E:1;
+} __attribute__((__packed__))RA_HEADER_RAPID_NB_IoT;
+
+/*Structure used for UL scheduling*/
+typedef struct{
+  //resource position info.
+  uint32_t sf_end, sf_start;
+  //resource position info. separate by HyperSF, Frame, Subframe
+  //uint32_t start_h, end_h;
+  //uint32_t start_f, end_f;
+  //uint32_t start_sf, end_sf;
+  // information for allocating the resource
+  int tone;
+  int scheduling_delay;
+  int subcarrier_indication;
+  int ACK_NACK_resource_field;
+  available_resource_UL_t *node;
+}sched_temp_UL_NB_IoT_t;
+
+typedef struct Available_available_resource_DL{
+
+    ///Available Resoruce for sixtone
+    available_resource_UL_t *sixtone_Head;//, *sixtone_npusch_frame;
+  uint32_t sixtone_end_subframe;
+    ///Available Resoruce for threetone
+    available_resource_UL_t *threetone_Head;//, *threetone_npusch_frame;
+  uint32_t threetone_end_subframe;
+    ///Available Resoruce for singletone1
+    available_resource_UL_t *singletone1_Head;//, *singletone1_npusch_frame;
+  uint32_t singletone1_end_subframe;
+    ///Available Resoruce for singletone2
+    available_resource_UL_t *singletone2_Head;//, *singletone2_npusch_frame;
+    uint32_t singletone2_end_subframe;
+  ///Available Resoruce for singletone3
+    available_resource_UL_t *singletone3_Head;//, *singletone3_npusch_frame;
+  uint32_t singletone3_end_subframe;
+  
+}available_resource_tones_UL_t;
+
+typedef struct schedule_result{
+  // The subframe read by output handler
+  uint32_t output_subframe;
+  // SDU length
+  uint32_t sdu_length;
+  // MAC PDU
+  uint8_t *DLSCH_pdu;
+  // The data direction indicated by this DCI
+  uint8_t direction;
+  // pointer to DCI
+  void *DCI_pdu;
+  // when all the procedure related to this DCI, enable this flag
+  boolean_t DCI_release;
+  // Indicate the channel which to transmit
+  channel_NB_IoT_t channel;
+  // rnti
+  rnti_t rnti;
+  // 0 = TC-RNTI , 1 = RA-RNTI, 2 = P-RNTI, 3 = others
+  uint8_t rnti_type;
+  // 0 = data, 1 = ACK/NACK
+  uint8_t npusch_format;
+  //HARQ ACK/NACK repetition
+  uint32_t R_harq;
+  // pointer to next node
+  struct schedule_result *next;
+
+  uint32_t end_subframe;
+  
+  uint8_t *rar_buffer;
+  
+  uint8_t *debug_str;
+
+}schedule_result_t;
+
+/*Flag structure used for trigger each scheduler*/
+typedef struct{
+  scheduling_flag_t scheduling_flag;
+  //sched_temp_DL_NB_IoT_t sched_result_DL;
+  //resource grid for Uplink
+  available_resource_tones_UL_t *UL_resource;
+  //scheduling result read by output handler
+  schedule_result_t *schedule_result_list_UL;
+  schedule_result_t *schedule_result_list_DL;
+}SCHEDULE_NB_IoT_t;
+
+typedef struct{
+  uint32_t num_dlsf_per_period;
+  uint16_t *sf_to_dlsf_table;
+  uint16_t *dlsf_to_sf_table;
+}DLSF_INFO_t;
+
+typedef enum ce_level_e{
+  ce0=0,
+  ce1,
+  ce2,
+  ce_level_total
+}ce_level_t;
+
+
+
+/*! \brief eNB template for the Random access information */
+typedef struct RA_TEMPLATE_NB_IoT_s{
+
+  boolean_t active;
+  uint32_t msg3_retransmit_count;
+  uint32_t msg4_retransmit_count;
+  uint16_t ta;
+  uint8_t preamble_index;
+  ce_level_t ce_level;
+  rnti_t ue_rnti;
+  rnti_t ra_rnti;
+  struct RA_TEMPLATE_NB_IoT_s *next, *prev;
+  boolean_t wait_msg4_ack;
+  boolean_t wait_msg3_ack;
+  uint8_t rar_buffer[7];
+
+} RA_TEMPLATE_NB_IoT;
+
+typedef struct RA_template_list_s{
+  RA_TEMPLATE_NB_IoT *head;
+  RA_TEMPLATE_NB_IoT *tail;
+}RA_template_list_t;
+
+
+/*! \brief top level eNB MAC structure */
+typedef struct {
+
+  //  System
+  uint32_t hyper_system_frame;
+  uint32_t system_frame;
+  uint32_t sub_frame;
+
+  uint32_t current_subframe;
+
+  //  RA
+  RA_template_list_t RA_msg2_list;
+  RA_template_list_t RA_msg3_list;
+  RA_template_list_t RA_msg4_list;
+
+  RA_TEMPLATE_NB_IoT RA_template[MAX_NUMBER_OF_UE_MAX_NB_IoT];
+
+  //int32_t last_tx_subframe;
+
+  //  for tool
+  int32_t sib1_flag[64];
+  int32_t sib1_count[64];
+  int32_t sib1_period;
+  uint16_t dlsf_table[64];
+  int32_t sibs_table[256];
+
+  //  channel config
+
+  //USS list
+  //Number of USS period is used
+  int num_uss_list;
+  UE_list_NB_IoT_t *UE_list_spec;
+
+  scheduling_flag_t scheduling_flag;
+
+  uint32_t schedule_subframe_DL;
+  uint32_t schedule_subframe_UL;
+
+  rrc_config_NB_IoT_t rrc_config;
+
+} eNB_MAC_INST_NB_IoT;
+
+// actually not here, but for now put it here
+typedef  struct {
+  uint32_t       bytes_in_buffer; /*!< \brief Bytes buffered in RLC protocol instance. */
+  uint32_t       pdus_in_buffer;  /*!< \brief Number of PDUs buffered in RLC protocol instance (OBSOLETE). */
+  uint32_t       head_sdu_creation_time;           /*!< \brief Head SDU creation time. */
+  uint32_t       head_sdu_remaining_size_to_send;  /*!< \brief remaining size of sdu: could be the total size or the remaining size of already segmented sdu */
+  boolean_t      head_sdu_is_segmented;     /*!< \brief 0 if head SDU has not been segmented, 1 if already segmented */
+} mac_rlc_status_resp_NB_IoT_t;
+
+// global variables
+
+nprach_parameters_NB_IoT_t nprach_list[3];
+
+//DLSF Table
+DLSF_INFO_t DLSF_information;
+
+#endif /*__LAYER2_MAC_DEFS_NB_IoT_H__ */
diff --git a/openair2/LAYER2/MAC/defs_nb_iot.h b/openair2/LAYER2/MAC/defs_nb_iot.h
deleted file mode 100644
index e7e44a4cab7afbe48ba061fdd490b912fd9dad69..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/MAC/defs_nb_iot.h
+++ /dev/null
@@ -1,611 +0,0 @@
-/*
- * 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.0  (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 LAYER2/MAC/defs.h
-* \brief MAC data structures, constant, and function prototype
-* \author Navid Nikaein and Raymond Knopp
-* \date 2011
-* \version 0.5
-* \email navid.nikaein@eurecom.fr
-*/
-/** @defgroup _oai2  openair2 Reference Implementation
- * @ingroup _ref_implementation_
- * @{
- */
-/*@}*/
-#ifndef __LAYER2_MAC_DEFS_NB_IOT_H__
-#define __LAYER2_MAC_DEFS_NB_IOT_H__
-#ifdef USER_MODE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#endif
-//#include "COMMON/openair_defs.h"
-#include "COMMON/platform_constants.h"
-#include "COMMON/mac_rrc_primitives.h"
-#include "PHY/defs.h"
-#include "RadioResourceConfigCommonSIB-NB-r13.h"
-#include "RadioResourceConfigDedicated-NB-r13.h"
-#include "RACH-ConfigCommon-NB-r13.h"
-#include "MasterInformationBlock-NB.h"
-#include "BCCH-BCH-Message-NB.h"
-//#ifdef PHY_EMUL
-//#include "SIMULATION/PHY_EMULATION/impl_defs.h"
-//#endif
-/** @defgroup _mac  MAC
- * @ingroup _oai2
- * @{
- */
-/*! \brief Downlink SCH PDU Structure */
-typedef struct {
-  int8_t payload[8][SCH_PAYLOAD_SIZE_MAX];
-  uint16_t Pdu_size[8];
-} __attribute__ ((__packed__)) DLSCH_PDU_NB;
-/*! \brief eNB template for UE context information  */
-typedef struct {
-  /// C-RNTI of UE
-  rnti_t rnti;
-  /// NDI from last scheduling
-  uint8_t oldNDI[8];
-  /// NDI from last UL scheduling
-  uint8_t oldNDI_UL[8];
-  /// Flag to indicate UL has been scheduled at least once
-  boolean_t ul_active;
-  /// Flag to indicate UE has been configured (ACK from RRCConnectionSetup received)
-  boolean_t configured;
-  /// MCS from last scheduling
-  //Modify uint8_t mcs[8];
-  /// TPC from last scheduling
-  //Delete uint8_t oldTPC[8];
-  // PHY interface info
-  /// DCI format for DLSCH
-  uint16_t DLSCH_dci_fmt;
-  /// Current Aggregation Level for DCI
-  uint8_t DCI_aggregation_min;
-  /// size of DLSCH size in bit
-  uint8_t DLSCH_dci_size_bits;
-  /// DCI buffer for DLSCH
-  /* rounded to 32 bits unit (actual value should be 8 due to the logic
-   * of the function generate_dci0) */
-  //Modifyuint8_t DLSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4];
-  /// Number of Allocated RBs for DL after scheduling (prior to frequency allocation)
-  //Delete uint16_t nb_rb[8]; // num_max_harq
-  /// Number of Allocated RBs for UL after scheduling (prior to frequency allocation)
-  //Delete uint16_t nb_rb_ul[8]; // num_max_harq
-  /// Number of Allocated RBs by the ulsch preprocessor
-  //Delete uint8_t pre_allocated_nb_rb_ul;
-  /// index of Allocated RBs by the ulsch preprocessor
-  //Delete int8_t pre_allocated_rb_table_index_ul;
-  /// total allocated RBs
-  //Delete int8_t total_allocated_rbs;
-  /// pre-assigned MCS by the ulsch preprocessor
-  uint8_t pre_assigned_mcs_ul;
-  /// assigned MCS by the ulsch scheduler
-  uint8_t assigned_mcs_ul;
-  /// DCI buffer for ULSCH
-  /* rounded to 32 bits unit (actual value should be 8 due to the logic
-   * of the function generate_dci0) */
-  //Modify uint8_t ULSCH_DCI[8][(((MAX_DCI_SIZE_BITS)+31)>>5)*4];
-  /// DL DAI
-  //Delete uint8_t DAI;
-  /// UL DAI
-  //Delete uint8_t DAI_ul[10];
-  /// UL Scheduling Request Received
-  //Delete uint8_t ul_SR;
-  /// Resource Block indication for each sub-band in MU-MIMO
-  //Delete uint8_t rballoc_subband[8][50];
-  // Logical channel info for link with RLC
-  /// Last received UE BSR info for each logical channel group id
-  uint8_t bsr_info[MAX_NUM_LCGID];
-  /// LCGID mapping
-  //Delete long lcgidmap[11];
-  /// phr information, received from DPR MAC control element
-  int8_t phr_info;
-  /// phr information, received from DPR MAC control element
-  int8_t phr_info_configured;
-  ///dl buffer info
-  uint32_t dl_buffer_info[MAX_NUM_LCID];
-  /// total downlink buffer info
-  uint32_t dl_buffer_total;
-  /// total downlink pdus
-  uint32_t dl_pdus_total;
-  /// downlink pdus for each LCID
-  uint32_t dl_pdus_in_buffer[MAX_NUM_LCID];
-  /// creation time of the downlink buffer head for each LCID
-  uint32_t dl_buffer_head_sdu_creation_time[MAX_NUM_LCID];
-  /// maximum creation time of the downlink buffer head across all LCID
-  uint32_t  dl_buffer_head_sdu_creation_time_max;
-  /// a flag indicating that the downlink head SDU is segmented
-  uint8_t    dl_buffer_head_sdu_is_segmented[MAX_NUM_LCID];
-  /// size of remaining size to send for the downlink head SDU
-  uint32_t dl_buffer_head_sdu_remaining_size_to_send[MAX_NUM_LCID];
-  /// total uplink buffer size
-  uint32_t ul_total_buffer;
-  /// uplink buffer creation time for each LCID
-  uint32_t ul_buffer_creation_time[MAX_NUM_LCGID];
-  /// maximum uplink buffer creation time across all the LCIDs
-  uint32_t ul_buffer_creation_time_max;
-  /// uplink buffer size per LCID
-  uint32_t ul_buffer_info[MAX_NUM_LCGID];
-  /// UE tx power
-  int32_t ue_tx_power;
-  /// stores the frame where the last TPC was transmitted
-  //Delete uint32_t pusch_tpc_tx_frame;
-  //Delete uint32_t pusch_tpc_tx_subframe;
-  //Delete uint32_t pucch_tpc_tx_frame;
-  //Delete uint32_t pucch_tpc_tx_subframe;
-//Delete eNB_UE_estimated_distances distance;
-} UE_TEMPLATE_NB;
-/*! \brief eNB statistics for the connected UEs*/
-typedef struct {
-  /// CRNTI of UE
-  rnti_t crnti; ///user id (rnti) of connected UEs
-  // rrc status
-  uint8_t rrc_status;
-  /// harq pid
-  uint8_t harq_pid;
-  /// harq rounf
-  uint8_t harq_round;
-  /// DL Wideband CQI index (2 TBs)
-  uint8_t dl_cqi;
-  /// total available number of PRBs for a new transmission
-  uint16_t rbs_used;
-  /// total available number of PRBs for a retransmission
-  uint16_t rbs_used_retx;
-  /// total nccc used for a new transmission: num control channel element
-  uint16_t ncce_used;
-  /// total avilable nccc for a retransmission: num control channel element
-  uint16_t ncce_used_retx;
-  // mcs1 before the rate adaptaion
-  uint8_t dlsch_mcs1;
-  /// Target mcs2 after rate-adaptation
-  uint8_t dlsch_mcs2;
-  //  current TBS with mcs2
-  uint32_t TBS;
-  //  total TBS with mcs2
-  //  uint32_t total_TBS;
-  //  total rb used for a new transmission
-  uint32_t total_rbs_used;
-  //  total rb used for retransmission
-  uint32_t total_rbs_used_retx;
-   /// TX
-  /// Num pkt
-  uint32_t num_pdu_tx[NB_RB_MAX];
-  /// num bytes
-  uint32_t num_bytes_tx[NB_RB_MAX];
-  /// num retransmission / harq
-  uint32_t num_retransmission;
-  /// instantaneous tx throughput for each TTI
-  //  uint32_t tti_throughput[NB_RB_MAX];
-  /// overall
-  //
-  uint32_t  dlsch_bitrate;
-  //total
-  uint32_t  total_dlsch_bitrate;
-  /// headers+ CE +  padding bytes for a MAC PDU
-  uint64_t overhead_bytes;
-  /// headers+ CE +  padding bytes for a MAC PDU
-  uint64_t total_overhead_bytes;
-  /// headers+ CE +  padding bytes for a MAC PDU
-  uint64_t avg_overhead_bytes;
-  // MAC multiplexed payload
-  uint64_t total_sdu_bytes;
-  // total MAC pdu bytes
-  uint64_t total_pdu_bytes;
-  // total num pdu
-  uint32_t total_num_pdus;
-  //
-  //  uint32_t avg_pdu_size;
-  /// RX
-  /// preassigned mcs after rate adaptation
-  uint8_t ulsch_mcs1;
-  /// adjusted mcs
-  uint8_t ulsch_mcs2;
-  /// estimated average pdu inter-departure time
-  uint32_t avg_pdu_idt;
-  /// estimated average pdu size
-  uint32_t avg_pdu_ps;
-  ///
-  uint32_t aggregated_pdu_size;
-  uint32_t aggregated_pdu_arrival;
-  ///  uplink transport block size
-  uint32_t ulsch_TBS;
-  ///  total rb used for a new uplink transmission
-  uint32_t num_retransmission_rx;
-  ///  total rb used for a new uplink transmission
-  uint32_t rbs_used_rx;
-   ///  total rb used for a new uplink retransmission
-  uint32_t rbs_used_retx_rx;
-  ///  total rb used for a new uplink transmission
-  uint32_t total_rbs_used_rx;
-  /// normalized rx power
-  int32_t      normalized_rx_power;
-   /// target rx power
-  int32_t    target_rx_power;
-  /// num rx pdu
-  uint32_t num_pdu_rx[NB_RB_MAX];
-  /// num bytes rx
-  uint32_t num_bytes_rx[NB_RB_MAX];
-  /// instantaneous rx throughput for each TTI
-  //  uint32_t tti_goodput[NB_RB_MAX];
-  /// errors
-  uint32_t num_errors_rx;
-  uint64_t overhead_bytes_rx;
-  /// headers+ CE +  padding bytes for a MAC PDU
-  uint64_t total_overhead_bytes_rx;
-  /// headers+ CE +  padding bytes for a MAC PDU
-  uint64_t avg_overhead_bytes_rx;
- //
-  uint32_t  ulsch_bitrate;
-  //total
-  uint32_t  total_ulsch_bitrate;
-  /// overall
-  ///  MAC pdu bytes
-  uint64_t pdu_bytes_rx;
-  /// total MAC pdu bytes
-  uint64_t total_pdu_bytes_rx;
-  /// total num pdu
-  uint32_t total_num_pdus_rx;
-  /// num of error pdus
-  uint32_t total_num_errors_rx;
-} eNB_UE_STATS_NB;
-/*! \brief scheduling control information set through an API (not used)*/
-typedef struct {
-  ///UL transmission bandwidth in RBs
-  uint8_t ul_bandwidth[MAX_NUM_LCID];
-  ///DL transmission bandwidth in RBs
-  uint8_t dl_bandwidth[MAX_NUM_LCID];
-  //To do GBR bearer
-  uint8_t min_ul_bandwidth[MAX_NUM_LCID];
-  uint8_t min_dl_bandwidth[MAX_NUM_LCID];
-  ///aggregated bit rate of non-gbr bearer per UE
-  uint64_t  ue_AggregatedMaximumBitrateDL;
-  ///aggregated bit rate of non-gbr bearer per UE
-  uint64_t  ue_AggregatedMaximumBitrateUL;
-  ///CQI scheduling interval in subframes.
-  //Delete uint16_t cqiSchedInterval;
-  ///Contention resolution timer used during random access
-  uint8_t mac_ContentionResolutionTimer;
-  //Delete uint16_t max_allowed_rbs[MAX_NUM_LCID];
-  uint8_t max_mcs[MAX_NUM_LCID];
-  uint16_t priority[MAX_NUM_LCID];
-  // resource scheduling information
-  uint8_t       harq_pid[MAX_NUM_CCs];
-  uint8_t       round[MAX_NUM_CCs];
-  uint8_t       dl_pow_off[MAX_NUM_CCs];
-  //Delete uint16_t      pre_nb_available_rbs[MAX_NUM_CCs];
-  //Delete unsigned char rballoc_sub_UE[MAX_NUM_CCs][N_RBG_MAX];
-  uint16_t      ta_timer;
-  int16_t       ta_update;
-  int32_t       context_active_timer;
-  //Delete int32_t       cqi_req_timer;
-  int32_t       ul_inactivity_timer;
-  int32_t       ul_failure_timer;
-  int32_t       ul_scheduled;
-  int32_t       ra_pdcch_order_sent;
-  int32_t       ul_out_of_sync;
-  int32_t       phr_received;// received from Msg3 MAC Control Element
-} UE_sched_ctrl_NB;
-/*! \brief UE list used by eNB to order UEs/CC for scheduling*/
-typedef struct {
-  /// DLSCH pdu
-  DLSCH_PDU_NB DLSCH_pdu[MAX_NUM_CCs][2][NUMBER_OF_UE_MAX];
-  /// DCI template and MAC connection parameters for UEs
-  UE_TEMPLATE_NB UE_template[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
-  /// DCI template and MAC connection for RA processes
-  int pCC_id[NUMBER_OF_UE_MAX];
-  /// Delete sorted downlink component carrier for the scheduler
-  /// Delete number of downlink active component carrier
-  /// Delete sorted uplink component carrier for the scheduler
-  /// Delete number of uplink active component carrier
-  /// Delete number of downlink active component carrier
-  /// eNB to UE statistics
-  eNB_UE_STATS_NB eNB_UE_stats[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
-  /// scheduling control info
-  UE_sched_ctrl_NB UE_sched_ctrl[NUMBER_OF_UE_MAX];
-  int next[NUMBER_OF_UE_MAX];
-  int head;
-  int next_ul[NUMBER_OF_UE_MAX];
-  int head_ul;
-  int avail;
-  int num_UEs;
-  boolean_t active[NUMBER_OF_UE_MAX];
-} UE_list_NB_t;
-/*!\brief Values of BCCH0 logical channel for MIB*/
-#define BCCH0 11 // MIB-NB
-/*!\brief Values of BCCH1 logical channel for SIBs */
-#define BCCH1 12 // SI-SIB-NBs
-/*!\brief Values of PCCH logical channel */
-//#define PCCH 13  // Paging XXX not used for the moment
-/*!\brief Value of CCCH / SRB0 logical channel */
-//#define CCCH 0  // srb0 ---> XXX exactly the same as in LTE (commented for compilation purposes)
-/*!\brief DCCH0 / SRB1bis logical channel */
-#define DCCH0 3  // srb1bis
-/*!\brief DCCH1 / SRB1  logical channel */
-//#define DCCH1 1 // srb1 //XXX we redefine it for the SRB1
-/*!\brief DTCH0 DRB0  logical channel */
-#define DTCH0 4 // DRB0
-/*!\brief DTCH1 DRB1  logical channel */
-#define DTCH1 5 // DRB1
-// DLSCH LCHAN ID all the same as NB-IoT
-/*!\brief  DCI PDU filled by MAC for the PHY  */
-/* 
- * eNB part 
- */ 
-
-
-/* 
- * UE/ENB common part 
- */ 
-/*!\brief MAC header of Random Access Response for Random access preamble identifier (RAPID) for NB-IoT */
-typedef struct {
-  uint8_t RAPID:6;
-  uint8_t T:1;
-  uint8_t E:1;
-} __attribute__((__packed__))RA_HEADER_RAPID_NB;
-
-/*!\brief  MAC header of Random Access Response for backoff indicator (BI) for NB-IoT*/
-typedef struct {
-  uint8_t BI:4;
-  uint8_t R:2;
-  uint8_t T:1;
-  uint8_t E:1;
-} __attribute__((__packed__))RA_HEADER_BI_NB;
-
-/*Seems not to do the packed of RAR pdu*/
-
-/*!\brief  MAC subheader short with 7bit Length field */
-typedef struct {
-  uint8_t LCID:5;  // octet 1 LSB
-  uint8_t E:1;
-  uint8_t R:2;     // octet 1 MSB
-  uint8_t L:7;     // octet 2 LSB
-  uint8_t F:1;     // octet 2 MSB
-} __attribute__((__packed__))SCH_SUBHEADER_SHORT_NB;
-/*!\brief  MAC subheader long  with 15bit Length field */
-typedef struct {
-  uint8_t LCID:5;   // octet 1 LSB
-  uint8_t E:1;
-  uint8_t R:2;      // octet 1 MSB
-  uint8_t L_MSB:7;
-  uint8_t F:1;      // octet 2 MSB
-  uint8_t L_LSB:8;
-  uint8_t padding;
-} __attribute__((__packed__))SCH_SUBHEADER_LONG_NB;
-/*!\brief MAC subheader short without length field */
-typedef struct {
-  uint8_t LCID:5;
-  uint8_t E:1;
-  uint8_t R:2;
-} __attribute__((__packed__))SCH_SUBHEADER_FIXED_NB;
-
-/*!\brief  mac control element: short buffer status report for a specific logical channel group ID*/
-typedef struct {
-  uint8_t Buffer_size:6;  // octet 1 LSB
-  uint8_t LCGID:2;        // octet 1 MSB
-} __attribute__((__packed__))BSR_SHORT_NB;
-
-/*!\TRUNCATED BSR and Long BSR is not supported in NB-IoT*/
-
-/*!\brief  mac control element: timing advance  */
-typedef struct {
-  uint8_t TA:6;
-  uint8_t R:2;
-} __attribute__((__packed__))TIMING_ADVANCE_CMD_NB;
-/*!\brief  mac control element: power headroom report  */
-typedef struct {
-  uint8_t PH:6;
-  uint8_t R:2;
-} __attribute__((__packed__))POWER_HEADROOM_CMD_NB;
-
-typedef struct {
-  uint8_t Num_ue_spec_dci ;
-  uint8_t Num_common_dci  ;
-  //  uint32_t nCCE;
-  uint32_t num_pdcch_symbols;
-  DCI_ALLOC_t dci_alloc[NUM_DCI_MAX] ;
-} DCI_PDU_NB;
-typedef struct {
-  uint8_t payload[BCCH_PAYLOAD_SIZE_MAX] ;
-} __attribute__((__packed__))BCCH_PDU_NB;
-/*! \brief CCCH payload */
-typedef struct {
-  uint8_t payload[CCCH_PAYLOAD_SIZE_MAX] ;
-} __attribute__((__packed__))CCCH_PDU_NB;
-/*! \brief eNB template for the Random access information */
-typedef struct {
-  /// Flag to indicate this process is active
-  boolean_t RA_active;
-  /// Size of DCI for RA-Response (bytes)
-  uint8_t RA_dci_size_bytes1;
-  /// Size of DCI for RA-Response (bits)
-  uint8_t RA_dci_size_bits1;
-  /// Actual DCI to transmit for RA-Response
-  uint8_t RA_alloc_pdu1[(MAX_DCI_SIZE_BITS>>3)+1];
-  /// DCI format for RA-Response (should be 1A)
-  uint8_t RA_dci_fmt1;
-  /// Size of DCI for Msg4/ContRes (bytes)
-  uint8_t RA_dci_size_bytes2;
-  /// Size of DCI for Msg4/ContRes (bits)
-  uint8_t RA_dci_size_bits2;
-  /// Actual DCI to transmit for Msg4/ContRes
-  uint8_t RA_alloc_pdu2[(MAX_DCI_SIZE_BITS>>3)+1];
-  /// DCI format for Msg4/ContRes (should be 1A)
-  uint8_t RA_dci_fmt2;
-  /// Flag to indicate the eNB should generate RAR.  This is triggered by detection of PRACH
-  uint8_t generate_rar;
-  /// Subframe where preamble was received, Delete?
-  uint8_t preamble_subframe;
-  /// Subframe where Msg3 is to be sent
-  uint8_t Msg3_subframe;
-  /// Flag to indicate the eNB should generate Msg4 upon reception of SDU from RRC.  This is triggered by first ULSCH reception at eNB for new user.
-  uint8_t generate_Msg4;
-  /// Flag to indicate that eNB is waiting for ACK that UE has received Msg3.
-  uint8_t wait_ack_Msg4;
-  /// UE RNTI allocated during RAR
-  rnti_t rnti;
-  /// RA RNTI allocated from received PRACH
-  uint16_t RA_rnti;
-  /// Re-use preamble_index, but it would be subcarrier index (0-47)
-  uint8_t preamble_index;
-  /// Received UE Contention Resolution Identifier
-  uint8_t cont_res_id[6];
-  /// Timing offset indicated by PHY
-  int16_t timing_offset;
-  /// Timeout for RRC connection
-  int16_t RRC_timer;
-} RA_TEMPLATE_NB;
-/*! \brief eNB common channels */
-typedef struct {
-  int                              physCellId;
-  int                              p_eNB;
-  int                              Ncp;
-  int                              eutra_band;
-  uint32_t                         dl_CarrierFreq;
-  BCCH_BCH_Message_NB_t               *mib_NB;
-  RadioResourceConfigCommonSIB_NB_r13_t   *radioResourceConfigCommon;
-  ARFCN_ValueEUTRA_r9_t               ul_CarrierFreq;
-  struct MasterInformationBlock_NB__operationModeInfo_r13 operationModeInfo;
-  /// Outgoing DCI for PHY generated by eNB scheduler
-  DCI_PDU_NB DCI_pdu;
-  /// Outgoing BCCH pdu for PHY
-  BCCH_PDU_NB BCCH_pdu;
-  /// Outgoing BCCH DCI allocation
-  uint32_t BCCH_alloc_pdu;
-  /// Outgoing CCCH pdu for PHY
-  CCCH_PDU_NB CCCH_pdu;
-  RA_TEMPLATE_NB RA_template[NB_RA_PROC_MAX];
-  /// Delete VRB map for common channels
-  /// Delete MBSFN SubframeConfig
-  /// Delete number of subframe allocation pattern available for MBSFN sync area
-// #if defined(Rel10) || defined(Rel14)
-  /// Delete MBMS Flag
-  /// Delete Outgoing MCCH pdu for PHY
-  /// Delete MCCH active flag
-  /// Delete MCCH active flag
-  /// Delete MTCH active flag
-  /// Delete number of active MBSFN area
-  /// Delete MBSFN Area Info
-  /// Delete PMCH Config
-  /// Delete MBMS session info list
-  /// Delete Outgoing MCH pdu for PHY
-// #endif
-// #ifdef CBA
-  /// Delete number of CBA groups
-  /// Delete RNTI for each CBA group
-  /// Delete MCS for each CBA group
-// #endif
-}COMMON_channels_NB_t;
-/*! \brief eNB overall statistics */
-typedef struct {
-  /// num BCCH PDU per CC
-  uint32_t total_num_bcch_pdu;
-  /// BCCH buffer size
-  uint32_t bcch_buffer;
-  /// total BCCH buffer size
-  uint32_t total_bcch_buffer;
-  /// BCCH MCS
-  uint32_t bcch_mcs;
-  /// num CCCH PDU per CC
-  uint32_t total_num_ccch_pdu;
-  /// BCCH buffer size
-  uint32_t ccch_buffer;
-  /// total BCCH buffer size
-  uint32_t total_ccch_buffertotal_ccch_buffer;
-  /// BCCH MCS
-  uint32_t ccch_mcs;
-/// num active users
-  uint16_t num_dlactive_UEs;
-  ///  available number of PRBs for a give SF fixed in 1 in NB-IoT
-  uint16_t available_prbs;
-  /// total number of PRB available for the user plane fixed in 1 in NB-IoT
-  uint32_t total_available_prbs;
-  /// aggregation
-  /// total avilable nccc : num control channel element
-  uint16_t available_ncces;
-  // only for a new transmission, should be extended for retransmission
-  // current dlsch  bit rate for all transport channels
-  uint32_t dlsch_bitrate;
-  //
-  uint32_t dlsch_bytes_tx;
-  //
-  uint32_t dlsch_pdus_tx;
-  //
-  uint32_t total_dlsch_bitrate;
-  //
-  uint32_t total_dlsch_bytes_tx;
-  //
-  uint32_t total_dlsch_pdus_tx;
-  // here for RX
-  //
-  uint32_t ulsch_bitrate;
-  //
-  uint32_t ulsch_bytes_rx;
-  //
-  uint64_t ulsch_pdus_rx;
-  uint32_t total_ulsch_bitrate;
-  //
-  uint32_t total_ulsch_bytes_rx;
-  //
-  uint32_t total_ulsch_pdus_rx;
-  /// MAC agent-related stats
-  /// total number of scheduling decisions
-  int sched_decisions;
-  /// missed deadlines
-  int missed_deadlines;
-} eNB_STATS_NB;
-/*! \brief top level eNB MAC structure */
-typedef struct {
-  ///
-  uint16_t Node_id;
-  /// frame counter
-  frame_t frame;
-  /// subframe counter
-  sub_frame_t subframe;
-  /// Common cell resources
-  COMMON_channels_NB_t common_channels[MAX_NUM_CCs];
-  UE_list_NB_t UE_list;
-  ///Delete subband bitmap configuration, no related CQI report
-  // / Modify CCE table used to build DCI scheduling information
-  int CCE_table[MAX_NUM_CCs][12];//180 khz for Anchor carrier
-  ///  active flag for Other lcid
-  uint8_t lcid_active[NB_RB_MAX];
-  /// eNB stats
-  eNB_STATS_NB eNB_stats[MAX_NUM_CCs];
-  // MAC function execution peformance profiler
-  /// processing time of eNB scheduler
-  time_stats_t eNB_scheduler;
-  /// processing time of eNB scheduler for SI
-  time_stats_t schedule_si;
-  /// processing time of eNB scheduler for Random access
-  time_stats_t schedule_ra;
-  /// processing time of eNB ULSCH scheduler
-  time_stats_t schedule_ulsch;
-  /// processing time of eNB DCI generation
-  time_stats_t fill_DLSCH_dci;
-  /// processing time of eNB MAC preprocessor
-  time_stats_t schedule_dlsch_preprocessor;
-  /// processing time of eNB DLSCH scheduler
-  time_stats_t schedule_dlsch; // include rlc_data_req + MAC header + preprocessor
-  /// Delete processing time of eNB MCH scheduler
-  /// processing time of eNB ULSCH reception
-  time_stats_t rx_ulsch_sdu; // include rlc_data_ind
-} eNB_MAC_INST_NB;
-#endif /*__LAYER2_MAC_DEFS_NB_IoT_H__ */
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_NB_IoT.c b/openair2/LAYER2/MAC/eNB_scheduler_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..13b51235cb65a7bcddba37bbda8a0f2be48c3101
--- /dev/null
+++ b/openair2/LAYER2/MAC/eNB_scheduler_NB_IoT.c
@@ -0,0 +1,220 @@
+
+/*! \file eNB_scheduler_NB_IoT.c
+ * \brief top level of the scheduler, it scheduled in pdcch period based.
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "defs_NB_IoT.h"
+#include "proto_NB_IoT.h"
+#include "extern_NB_IoT.h"
+
+
+//	scheduler
+#define flag_css_type1 0x1
+#define flag_css_type2 0x2
+#define flag_uss_v	   0x4
+
+//	common
+#define flag_mib      0x1
+#define flag_sib1     0x2
+#define flag_npss     0x4
+#define flag_nsss     0x8
+
+
+#define num_flags 2
+int extend_space[num_flags] = {160, 160};
+int extend_alpha_offset[num_flags] = {10, 10};
+
+int uss_space = 320;
+int uss_alpha_offset = 10;
+
+void eNB_scheduler_computing_flag_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe, int *scheduler_flags, int *common_flags){
+	uint32_t subframe = abs_subframe % 10;
+	uint32_t frame = abs_subframe / 10;
+	int i;
+
+	if(subframe == 0){
+		*common_flags |= flag_mib;
+	}else if(subframe == 5){
+		*common_flags |= flag_npss;
+	}else if(subframe == 9 && (frame&0x1)==0){
+		*common_flags |= flag_nsss;
+	}else if(subframe == 4 && mac_inst->sib1_flag[frame%mac_inst->sib1_period]){
+		*common_flags |= flag_sib1;
+	}
+	for(i=0; i<num_flags; ++i){
+		if(((abs_subframe+1)%extend_space[i])==(extend_space[i]>>extend_alpha_offset[i])){
+			*scheduler_flags |= (0x1<<i);
+		}
+	}
+	//USS trigger flag
+	for(i=0;i<mac_inst->num_uss_list;++i)
+	{
+		//printf("[eNB Computing falg] USS trigger time %d ss start time %d\n", ((abs_subframe+1)%mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.T), mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.ss_start_uss);
+		if(((abs_subframe+1)%mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.T)==mac_inst->UE_list_spec[i].NPDCCH_config_dedicated.ss_start_uss)
+		{
+			//SCHEDULE_LOG("1\n");
+			*scheduler_flags |= (flag_uss_v<<i);
+		}
+	}
+	//printf("[eNB Computing falg] scheduler_flags %X\n", *scheduler_flags);
+	/*
+	//USS trigger flag
+	if((abs_subframe%uss_space)==(uss_space>>uss_alpha_offset)){
+		*scheduler_flags |= flag_uss_v;
+	}
+	*/
+}
+/*function description:
+* top level of the scheduler, this will trigger in every subframe,
+* and determined if do the schedule by checking this current subframe is the start of the NPDCCH period or not
+*/
+void eNB_dlsch_ulsch_scheduler_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe){
+ // eNB_MAC_INST_NB_IoT *eNB = &eNB_mac_inst_NB_IoT[module_id];
+	int i, max_subframe, scheduler_flags, common_flags,MIB_flag,SIB1_flag;
+	int a = 0;
+	/*Check this subframe should schedule something, set the flag*/
+	scheduler_flags = 0;
+	common_flags = 0;
+	MIB_flag = 0;
+	SIB1_flag = 0;
+	uint32_t h,f,sf;
+	//int a;
+	//DEBUG("--------------[%04d][eNB scheduler NB-IoT] Start Scheduling------------\n", mac_inst->current_subframe);
+	eNB_scheduler_computing_flag_NB_IoT(mac_inst, abs_subframe, &scheduler_flags, &common_flags);
+	/*Update the available resource list to current state*/
+	//NB_IoT_maintain_available_resource(subframe, frame, hypersfn);
+	max_subframe = 0;
+	for(i=0; i<num_flags; ++i){
+		if(1 == (scheduler_flags&(0x1<<i))){
+			if(max_subframe < extend_space[i]){
+				max_subframe = extend_space[i];
+			}
+		}
+	}
+
+	if(scheduler_flags > 0){
+	        extend_available_resource_DL(mac_inst, mac_inst->current_subframe + 1 + max_subframe);
+	}
+	
+	maintain_available_resource(mac_inst);
+
+    //static int test=2;
+	if((abs_subframe % rachperiod[4]) == rachstart[0]){
+
+		   add_UL_Resource();
+	}
+
+	//Check if type2 searching space scheduling
+	if((scheduler_flags&flag_css_type2)>0){
+		schedule_RA_NB_IoT(mac_inst);
+		scheduler_flags &= ~(flag_css_type2);
+	}
+
+	//Check if type1 searching space scheduling
+	if((scheduler_flags&flag_css_type1)>0){
+		scheduler_flags &= ~(flag_css_type1);
+ 	}
+	
+	// loop all USS period
+	for(i=0;i<mac_inst->num_uss_list;++i)
+	{
+		if((scheduler_flags&(flag_uss_v<<i))>0){
+			printf("--------------[%04d][SchedulerUSS] Schedule USS list %d------------\n", mac_inst->current_subframe, (scheduler_flags&(flag_uss_v<<i))>>3);
+			scheduler_flags &= ~(flag_uss_v<<i);
+			convert_system_number(abs_subframe, &h, &f, &sf);
+			//DEBUG("=====t:%d======\n", mac_inst->current_subframe);
+			//print_available_resource_DL();
+			schedule_uss_NB_IoT(0, mac_inst,sf, f, h, i);
+		}
+	}
+	/*
+	//Check if UE-specific searching space scheduling
+	if((scheduler_flags&flag_uss_v)>0){
+		scheduler_flags &= ~(flag_uss_v);
+		convert_system_number(abs_subframe, &h, &f, &sf);
+		//DEBUG("=====t:%d======\n", mac_inst->current_subframe);
+		//print_available_resource_DL();
+		schedule_uss_NB_IoT(0, mac_inst,sf, f, h, 0);
+	}
+	*/
+	if(common_flags ==  flag_mib)
+		MIB_flag = 1;
+	if(common_flags == flag_sib1)
+		SIB1_flag = 1;
+	convert_system_number(abs_subframe, &h, &f, &sf);
+	a = output_handler(mac_inst, 0,0,h,f,sf,MIB_flag,SIB1_flag, abs_subframe);
+
+	printf("Output_handler_return value : %d", a);
+	//DEBUG("--------------[%04d][eNB scheduler NB-IoT] End Scheduling------------\n", mac_inst->current_subframe);
+}
+
+void schedule_uss_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, uint32_t subframe, uint32_t frame, uint32_t hypersfn, int index_ss)
+{
+	//int32_t i;
+	//SCHEDULE_NB_IoT_t *scheduler =  &eNB->scheduler;
+  	mac_inst->scheduling_flag.flag_uss[0]=1;
+  	mac_inst->scheduling_flag.flag_uss[1]=0;
+  	mac_inst->scheduling_flag.flag_uss[2]=0;
+  	mac_inst->scheduling_flag.num_uss_run = 0;
+
+	//search space index
+	//int index_ss=0;
+	int UE_ID;
+	UE_TEMPLATE_NB_IoT *UE_template_temp;
+
+	if(mac_inst->scheduling_flag.num_uss_run > 1)
+	{
+		//spectial case
+	}
+	else
+	{
+		//general case
+	}
+
+  UE_ID = mac_inst->UE_list_spec[index_ss].head;
+  //DEBUG("t=%d   UE ID head %d\n", mac_inst->current_subframe,UE_ID);
+  while(UE_ID>-1)
+  {
+    
+    UE_template_temp = &(mac_inst->UE_list_spec[index_ss].UE_template_NB_IoT[UE_ID]);
+    printf("------Start Scheduling USS UE RNTI %d------\n", UE_template_temp->rnti);
+    if(UE_template_temp->RRC_connected!=1)
+    {
+    	printf("[schedule_uss_NB_IoT] UE ID %d RRC not connected\n", UE_ID);
+	  	printf("[%04d][USS scheduler][UE%d] rrc not connected\n", mac_inst->current_subframe, UE_template_temp->rnti);
+    }
+    else
+    {
+    	printf("t=%d*******[schedule_uss_NB_IoT] schedule UE_ID %d direction %d*******%d %d %d\n", mac_inst->current_subframe, UE_ID, UE_template_temp->direction, hypersfn, frame, subframe);
+		printf("[%04d][USS scheduler][UE%d] ", mac_inst->current_subframe, UE_template_temp->rnti);
+      switch(UE_template_temp->direction)
+      {
+        //Downlink Scheduling
+        case 1:
+			printf("uss downlink scheduling.. \n");
+          schedule_DL_NB_IoT(0, mac_inst, UE_template_temp,  hypersfn, frame, subframe);
+          break;
+        //Uplink Scheduling
+        case 0:
+			printf("uss uplink scheduling.. \n");
+          schedule_UL_NB_IoT(mac_inst, UE_template_temp, subframe, frame, hypersfn);
+          break;
+		case -1:
+			printf("current idle.. \n");
+		default:
+			break;
+      }
+      //printf("----------------End Scheduling USS UE RNTI %d-------------------\n", UE_template_temp->rnti);
+      UE_template_temp->direction = -1;
+    }
+
+    UE_ID = UE_template_temp->next;
+  }
+
+}
+
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA_NB_IoT.c b/openair2/LAYER2/MAC/eNB_scheduler_RA_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..b3f61d2d854d15b32d0d1fa3a724c82552799a3e
--- /dev/null
+++ b/openair2/LAYER2/MAC/eNB_scheduler_RA_NB_IoT.c
@@ -0,0 +1,674 @@
+
+/*! \file eNB_scheduler_RA_NB_IoT.c
+ * \brief functions used in Random access scheduling 
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "defs_NB_IoT.h"
+#include "proto_NB_IoT.h"
+#include "extern_NB_IoT.h"
+
+unsigned char str1[] = "rar_dci";
+unsigned char str2[] = "rar";
+unsigned char str3[] = "msg4_dci";
+unsigned char str4[] = "msg4";
+unsigned char str5[] = "ack_msg4";
+unsigned char str6[] = "msg3_dci(retransmit)";
+unsigned char str7[] = "msg3(retransmit)";
+unsigned char str8[] = "msg4_dci(retransmit)";
+unsigned char str9[] = "msg4(retransmit)";
+unsigned char str10[] = "ack_msg4(retransmit)";
+unsigned char str11[] = "msg3";
+unsigned char str12[] = "msg3(retransmit)";
+
+/*void init_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint8_t preamble_index, ce_level_t ce_level, uint32_t sfn_id, uint16_t ta){
+
+	int i;
+	RA_TEMPLATE_NB_IoT *msg2_list_tail = mac_inst->RA_msg2_list.tail;
+	RA_TEMPLATE_NB_IoT *migrate_node;
+
+	static int static_count=0;
+	printf("[%04d][RA scheduler][MSG1] RX %d\n", mac_inst->current_subframe, static_count++);
+
+	for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
+		if(0 == mac_inst->RA_template[i].active){
+			migrate_node = &mac_inst->RA_template[i];
+			break;
+		}
+	}
+
+	if(i==MAX_NUMBER_OF_UE_MAX_NB_IoT){
+		printf("[%04d][RA scheduler][MSG1] number of RA procedures is up to maximum..\n", mac_inst->current_subframe);
+		return ;
+	}
+
+	migrate_node->active = 1;
+	migrate_node->preamble_index = preamble_index;
+	migrate_node->ce_level = ce_level;
+	migrate_node->ra_rnti = (sfn_id>>2) + 1;
+	migrate_node->ta = ta;
+	migrate_node->next = (RA_template_NB_IoT *)0;
+	migrate_node->prev = (RA_template_NB_IoT *)0;
+
+	//	insert to end of list
+	if((RA_template_NB_IoT *)0 == mac_inst->RA_msg2_list.head){
+		mac_inst->RA_msg2_list.head = migrate_node;
+	}else{
+		//	not empty
+		mac_inst->RA_msg2_list.tail->next = migrate_node;
+		migrate_node->prev = mac_inst->RA_msg2_list.tail;
+	}
+	mac_inst->RA_msg2_list.tail = migrate_node;
+
+}*/
+
+//  7bytes
+void fill_rar_NB_IoT(
+	eNB_MAC_INST_NB_IoT *inst, 
+	RA_TEMPLATE_NB_IoT *ra_template,
+	uint8_t msg3_schedule_delay,
+	uint8_t msg3_rep,
+	sched_temp_UL_NB_IoT_t *schedule_template
+)
+//------------------------------------------------------------------------------
+{
+	uint8_t *dlsch_buffer = &ra_template->rar_buffer[0];
+	RA_HEADER_RAPID_NB_IoT *rarh = (RA_HEADER_RAPID_NB_IoT *)dlsch_buffer;
+	int i;
+	//uint16_t rballoc;
+	//uint8_t mcs,TPC,ULdelay,cqireq;
+	
+	for(i=0; i<7; ++i){
+	    dlsch_buffer[i] = 0x0;
+    }
+	
+	// subheader fixed
+	rarh->E                     = 0; // First and last RAR
+	rarh->T                     = 1; // 0 for E/T/R/R/BI subheader, 1 for E/T/RAPID subheader
+	rarh->RAPID                 = ra_template->preamble_index; // Respond to Preamble 0 only for the moment
+	
+	uint8_t *rar = (uint8_t *)(dlsch_buffer+1);
+	//	ta
+	ra_template->ta >>= 4;
+	rar[0] = (uint8_t)(ra_template->ta>>(2+4)); // 7 MSBs of timing advance + divide by 4
+	rar[1] = (uint8_t)(ra_template->ta<<(4-2))&0xf0; // 4 LSBs of timing advance + divide by 4
+	
+	//	msg3 grant (15bits)
+	//	subcarrier spacing:1 subcarrier indication:6 scheduling delay:2 msg3 repetition:3 MCS index: 3
+	uint8_t subcarrier_spacing = 1;	// 1bit 15kHz
+	uint8_t subcarrier_indication = schedule_template->subcarrier_indication; // 6bits
+	uint8_t i_delay = msg3_schedule_delay; // 2bits
+	uint8_t msg3_repetition = msg3_rep;// 3bit
+	uint8_t mcs_index = 0;//3bit, msg3 88bits 3'b000
+	
+	rar[1] |= (subcarrier_spacing<<4) | (subcarrier_indication>>3);
+	rar[2] = (uint8_t)(subcarrier_indication<<5) | (i_delay<<3) | msg3_repetition;
+	rar[3] = (mcs_index<<5)&0xe0;  //  maped
+	
+	//	tc-rnti
+	rar[4] = (uint8_t)(ra_template->ue_rnti>>8);
+	rar[5] = (uint8_t)(ra_template->ue_rnti&0xff);
+	
+	
+}
+
+
+void schedule_msg3_retransimission_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
+
+	RA_TEMPLATE_NB_IoT *msg3_nodes = mac_inst->RA_msg3_list.head;
+
+	available_resource_DL_t *dci_node;
+	int rmax, fail, res, r;
+	int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe;
+	int msg3_subframe;
+
+	int dci_candidate, num_candidate;
+	int msg3_scheduling_delay;
+	schedule_result_t *dci_result;//, *msg3_result;
+
+	int rep=1;
+	//sched_temp_UL_NB_IoT_t npusch_info;
+
+	while((RA_TEMPLATE_NB_IoT *)0 != msg3_nodes){
+		if(msg3_nodes->wait_msg3_ack == 0){
+		    
+			fail=0;
+			//	check dci resource
+			rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg3_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32;
+	    num_candidate = 8;//rmax / r;
+		r = rmax/num_candidate;
+		num_dci_subframe = r;
+		dci_subframe = mac_inst->current_subframe;
+			for(dci_candidate=0; dci_candidate<8; ++dci_candidate){
+                while(!is_dlsf(mac_inst, dci_subframe)){
+                    ++dci_subframe;
+                }
+				dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe);
+				if((available_resource_DL_t *)0 != dci_node){
+					//dci_subframe += dci_candidate*num_dci_subframe;
+					//printf("[RA scheduler][%d][MSG3] [%x][HARQ][DCI]\tstart %3d, num %3d, end %3d\n", mac_inst->current_subframe, msg3_nodes->ue_rnti, dci_subframe, num_dci_subframe, dci_end_subframe);
+					break;
+				}
+				res = num_dci_subframe;
+    			while(res != 0){ //  cost lot of time to search
+                    if(is_dlsf(mac_inst, dci_subframe)){
+                        res--;
+                    }
+                    dci_subframe++;
+                }
+			}
+			if(8==dci_candidate){
+				//failed
+				fail|=0x1;
+			}
+			//	check msg3 resource
+			msg3_subframe = dci_end_subframe+8;
+			rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg3_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT;
+			sched_temp_UL_NB_IoT_t npusch_info;
+		
+        	uint32_t Iru = 0, mcs, Nru;
+		uint32_t mappedMcsIndex = 4;  //  assume all ue supported multi-tone
+		mcs = mapped_mcs[msg3_nodes->ce_level][mappedMcsIndex]; //  assume all ue supported multi-tone
+		int TBS = get_TBS_UL_NB_IoT(mcs,1,Iru);
+		while((TBS<11)&&(Iru<=7)){
+            Iru++;
+            TBS=get_TBS_UL_NB_IoT(mcs,1,Iru);
+        }
+		Nru = RU_table[Iru];
+		
+			for(msg3_scheduling_delay=0; msg3_scheduling_delay<4; ++msg3_scheduling_delay){
+				if(0==Check_UL_resource(msg3_subframe+msg3_scheduling_delay_table[msg3_scheduling_delay]+1, Nru*rep, &npusch_info, 1, 0)){	//1: multi-tones 0: single-tone. 1: format 2(ack/nack) 0: format 1
+					//msg3_subframe += (msg3_scheduling_delay<<2);
+					//printf("[MSG3][%x][HARQ]\t\tstart %3d, num %3d, end %3d\n", msg3_nodes->ue_rnti, msg3_subframe, npusch_info.sf_end-msg3_subframe, npusch_info.sf_end);
+					break;
+				}
+			}
+			if(4==msg3_scheduling_delay){
+				//failed
+				fail|=0x2;
+			}
+	        
+			if(0 == fail){
+				
+				msg3_nodes->wait_msg3_ack = 1;
+				
+				DCIFormatN0_t *dci_n0_msg3 = (DCIFormatN0_t *)malloc(sizeof(DCIFormatN0_t));
+				//	dci entity
+				dci_n0_msg3->type = 0;
+				dci_n0_msg3->scind = npusch_info.subcarrier_indication;
+				dci_n0_msg3->ResAssign = 0;
+				dci_n0_msg3->mcs = 0;
+				dci_n0_msg3->ndi = 0;	//	retrnasmit
+				dci_n0_msg3->Scheddly = msg3_scheduling_delay;
+				dci_n0_msg3->RepNum = rep;
+				dci_n0_msg3->rv = 0;
+				dci_n0_msg3->DCIRep = 1;//get_DCI_REP()
+				//	for dci
+				dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
+			    dci_result->output_subframe = dci_first_subframe;//dci_subframe;
+			    dci_result->end_subframe = dci_end_subframe;
+			    dci_result->sdu_length = 0;
+			    dci_result->direction = UL;
+			    dci_result->DCI_release = 0;
+			    dci_result->channel = NPDCCH;
+			    dci_result->rnti = msg3_nodes->ue_rnti;
+			    dci_result->rnti_type = 1;
+			    dci_result->npusch_format = 0; //useless
+			    dci_result->R_harq = 0;
+			    dci_result->next = (schedule_result_t *)0;
+			    dci_result->DCI_pdu = (void *)dci_n0_msg3;
+		        dci_result->debug_str = str6;
+	            
+       		    //simulate_rx(&simulate_rx_msg3_list, msg3_nodes->ue_rnti, npusch_info.sf_start);
+
+			    //	fill dci resource
+			    fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result);
+			    //	fill msg3 resource
+			    generate_scheduling_result_UL(-1, -1, npusch_info.sf_start, npusch_info.sf_end, dci_n0_msg3, msg3_nodes->ue_rnti, str12, (void *)0);	//	rnti
+				adjust_UL_resource_list(&npusch_info);
+	            printf("[%04d][RA scheduler][MSG3 re] MSG3DCI %d-%d MSG3 %d-%d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe, npusch_info.sf_start, npusch_info.sf_end );
+			}else{
+				printf("[%04d][RA scheduler][MSG3 re] fail vector %d\n", mac_inst->current_subframe, fail );
+			}
+
+			++msg3_nodes->msg3_retransmit_count;
+		}
+		msg3_nodes = msg3_nodes->next;
+	}
+	return ;
+}
+
+void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
+
+	RA_TEMPLATE_NB_IoT *msg2_nodes = mac_inst->RA_msg2_list.head;
+	//RA_TEMPLATE_NB_IoT *msg3_list_tail = mac_inst->RA_msg3_list.tail;
+	RA_TEMPLATE_NB_IoT *migrate_node;
+	schedule_result_t *dci_result, *msg2_result;
+    DCIFormatN0_t *dci_n0;
+    DCIFormatN1_t *dci_n1_rar;
+	available_resource_DL_t *dci_node, *msg2_node;
+	int rmax, fail, r, res;
+	int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe;
+	int msg2_subframe, msg2_end_subframe, msg2_first_subframe, num_msg2_subframe;
+	int msg3_subframe;
+
+	int dci_candidate, i, num_candidate;
+	int msg2_i_delay;
+	int msg3_scheduling_delay;
+	static uint16_t tc_rnti = 0x0101;
+	int rep=1;
+	sched_temp_UL_NB_IoT_t npusch_info;
+    int fail_num = 0;
+
+	while((RA_TEMPLATE_NB_IoT *)0 != msg2_nodes){
+		fail=0;
+		rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg2_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32;
+		num_candidate = 8;//rmax / r;
+		r = rmax/num_candidate;
+		num_dci_subframe = r;
+		dci_subframe = mac_inst->current_subframe;
+		for(dci_candidate=0; dci_candidate<num_candidate; ++dci_candidate){
+            while(!is_dlsf(mac_inst, dci_subframe)){
+                ++dci_subframe;
+            }
+			dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe);
+			if((available_resource_DL_t *)0 != dci_node){
+				//dci_subframe += dci_candidate*num_dci_subframe;
+				break;
+			}
+			res = num_dci_subframe;
+			while(res != 0){ //  maybe would cost lots of time to search
+                if(is_dlsf(mac_inst, dci_subframe)){
+                    res--;
+                }
+                dci_subframe++;
+            }
+		}
+		if(num_candidate==dci_candidate){
+			fail|=0x1;
+		}
+		//	check msg2 resource
+		uint32_t TBS, I_tbs, I_mcs, I_sf, Nrep;
+		
+		I_mcs = get_I_mcs_NB_IoT(msg2_nodes->ce_level);
+	    I_tbs = I_mcs;
+		TBS = get_tbs(7, I_tbs, &I_sf);   //  rar 7 bytes
+		Nrep = dl_rep[msg2_nodes->ce_level];
+		num_msg2_subframe = get_num_sf(I_sf) * Nrep;
+		
+		//num_msg2_subframe = 8;
+		msg2_i_delay = find_suit_i_delay(rmax, r, dci_candidate);
+		for(i=0; i<8; ++i, ++msg2_i_delay){
+		    msg2_i_delay = (msg2_i_delay==8)?0:msg2_i_delay;
+		    msg2_subframe = dci_end_subframe+4+get_scheduling_delay(msg2_i_delay, rmax);
+			msg2_node = (available_resource_DL_t *)check_resource_DL(mac_inst, msg2_subframe, num_msg2_subframe, &msg2_end_subframe, &msg2_first_subframe);
+			if((available_resource_DL_t *)0 != msg2_node){
+				break;
+			}
+		}
+		if(-1==msg2_i_delay){
+			fail|=0x2;
+		}
+		//	check msg3 resource
+		rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg2_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT;
+		msg3_subframe = msg2_end_subframe;
+		
+		uint32_t Iru = 0, mcs, Nru;
+		uint32_t mappedMcsIndex = 4;  //  assume all ue supported multi-tone
+		mcs = mapped_mcs[msg2_nodes->ce_level][mappedMcsIndex]; //  assume all ue supported multi-tone
+		
+        TBS = get_TBS_UL_NB_IoT(mcs,1,Iru);
+		while((TBS<11)&&(Iru<=7)){    //  88 bits
+            Iru++;
+            TBS=get_TBS_UL_NB_IoT(mcs,1,Iru);
+        }
+		Nru = RU_table[Iru];
+		
+        for(msg3_scheduling_delay=0; msg3_scheduling_delay<4; ++msg3_scheduling_delay){
+		    //    36.213 Table 16.3.3-1 Imcs=3'b000 Nru=4
+			if(0==Check_UL_resource(msg3_subframe+msg3_scheduling_delay_table[msg3_scheduling_delay]+1, Nru*rep, &npusch_info, 1, 0)){	//1: multi-tones 0: single-tone. 1: format 2(ack/nack) 0: format 1
+				break;
+			}
+		}
+		if(4==msg3_scheduling_delay){
+			fail|=0x4;
+		}
+		if(0 < fail){
+		    fail_num++;
+		    printf("[%04d][RA scheduler][MSG2] fail vector %d\n", mac_inst->current_subframe, fail);
+		    //SCHEDULE_LOG("[%04d][RA scheduler][MSG2] rnti: %d preamble: %d fail vector %d\n", mac_inst->current_subframe, msg2_nodes->ra_rnti, msg2_nodes->preamble_index, fail);
+		    msg2_nodes = msg2_nodes->next;
+		}else{
+		    //SCHEDULE_LOG("[%04d][RA scheduler][MSG2] rnti: %d preamble: %d success\n", mac_inst->current_subframe, msg2_nodes->ra_rnti, msg2_nodes->preamble_index);
+		    dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
+		    msg2_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
+		    dci_n0 = (DCIFormatN0_t *)malloc(sizeof(DCIFormatN0_t));
+			dci_n1_rar = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
+			
+		    fill_rar_NB_IoT(mac_inst, msg2_nodes, msg3_scheduling_delay, rep, &npusch_info);
+		    
+            msg2_nodes->wait_msg3_ack = 1;
+			//	dci entity
+			dci_n1_rar->type = 1;
+			dci_n1_rar->orderIndicator = 0;
+			dci_n1_rar->Scheddly = msg2_i_delay;
+			dci_n1_rar->ResAssign = 0;
+			dci_n1_rar->mcs = 0;	
+			dci_n1_rar->RepNum = 0;	//	36.213 table 16.4.1.3-2, 8 candidates
+			dci_n1_rar->ndi = 0;	//	ndi is useless in RAR	36.212 says the feild is reserved
+			dci_n1_rar->HARQackRes = 0;	//	no HARQ procedure in RAR	36.212 says the feild is reserved
+			dci_n1_rar->DCIRep = 0;	//	36.213 table 16.6-1 R=Rmax/8
+
+			//	for dci
+		    dci_result->output_subframe = dci_first_subframe;//dci_subframe;
+			dci_result->end_subframe = dci_end_subframe;
+		    dci_result->sdu_length = 0;
+		    dci_result->direction = DL;
+		    dci_result->DCI_release = 0;
+		    dci_result->channel = NPDCCH;
+		    dci_result->rnti = msg2_nodes->ra_rnti;//ra_rnti;
+		    dci_result->rnti_type = 1;
+		    dci_result->npusch_format = 0; //useless
+		    dci_result->R_harq = 0;
+		    dci_result->next = (schedule_result_t *)0;
+		    dci_result->DCI_pdu = (void *)dci_n1_rar;
+		    dci_result->debug_str = &str1[0];
+		    
+			//	for msg2
+		    msg2_result->output_subframe = msg2_first_subframe;//msg2_subframe;
+		    msg2_result->end_subframe = msg2_end_subframe;
+		    msg2_result->sdu_length = 56;   //  rar size
+		    msg2_result->DLSCH_pdu = msg2_nodes->rar_buffer;
+		    msg2_result->direction = DL;
+		    msg2_result->DCI_release = 1;
+		    msg2_result->channel = NPDSCH;
+		    msg2_result->rnti = msg2_nodes->ra_rnti;//ra_rnti;
+		    msg2_result->rnti_type = 1;
+		    msg2_result->npusch_format = 0;	//useless
+		    msg2_result->R_harq = 0;
+		    msg2_result->next = (schedule_result_t *)0;
+		    msg2_result->DCI_pdu = (void *)dci_n1_rar;
+			msg2_result->debug_str = str2;
+			msg2_result->rar_buffer = msg2_nodes->rar_buffer;
+
+			//	for msg3(fake DCI N0)
+			dci_n0->type = 0;
+			dci_n0->scind = npusch_info.subcarrier_indication;
+			dci_n0->ResAssign = 0;
+			dci_n0->mcs = 0;
+			dci_n0->ndi = 1;
+			dci_n0->Scheddly = msg3_scheduling_delay;
+			dci_n0->RepNum = rep;
+			dci_n0->rv = 0;
+			dci_n0->DCIRep = 1;//get_DCI_REP()
+			
+			msg2_nodes->ue_rnti = tc_rnti;
+			
+			printf("[%04d][RA scheduler][MSG2] RARDCI %d-%d RAR %d-%d MSG3 %d-%d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe, msg2_first_subframe, msg2_end_subframe, npusch_info.sf_start, npusch_info.sf_end);
+			
+            //	fill dci resource
+			fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result);
+			//	fill msg2 resource
+			fill_resource_DL(mac_inst, msg2_node, msg2_first_subframe, msg2_end_subframe, msg2_result);
+
+			//	fill msg3 resource
+			generate_scheduling_result_UL(-1, -1, npusch_info.sf_start, npusch_info.sf_end, dci_n0, tc_rnti, str11, (void *)0);
+			adjust_UL_resource_list(&npusch_info);
+
+			//simulate_rx(&simulate_rx_msg3_list, tc_rnti, npusch_info.sf_start);
+
+			migrate_node = msg2_nodes;
+			//migrate_node->ue_rnti = tc_rnti;
+			tc_rnti++;
+	        msg2_nodes = msg2_nodes->next;
+
+			//	maintain list
+			if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->prev){
+				//	first node
+				mac_inst->RA_msg2_list.head = migrate_node->next;	//	including null
+			}else{
+				//	not first node
+				migrate_node->prev->next = migrate_node->next;		//	including null
+			}
+			if((RA_TEMPLATE_NB_IoT *)0 == migrate_node->next){
+				//	last node
+				mac_inst->RA_msg2_list.tail = migrate_node->prev;	//	including null
+			}else{
+				//	not last node
+				migrate_node->next->prev = migrate_node->prev;		//	including null
+			}
+
+			//	migrate to next list
+			//	insert to end of list
+			migrate_node->next = (RA_TEMPLATE_NB_IoT *)0;
+			migrate_node->prev = (RA_TEMPLATE_NB_IoT *)0;
+			if((RA_TEMPLATE_NB_IoT *)0 == mac_inst->RA_msg3_list.head){
+				mac_inst->RA_msg3_list.head = migrate_node;
+			}else{
+				//	not empty
+				mac_inst->RA_msg3_list.tail->next = migrate_node;
+				migrate_node->prev = mac_inst->RA_msg3_list.tail;
+			}
+			mac_inst->RA_msg3_list.tail = migrate_node;
+
+		}
+	}
+	//SCHEDULE_LOG("[%04d][RA scheduler][MSG2] failed number: %d\n", mac_inst->current_subframe, fail_num);
+	return ;
+}
+
+//	msg4 scheduling: both first time or retransmit would be scheduled in this function(msg4_list).
+void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
+
+	RA_TEMPLATE_NB_IoT *msg4_nodes = mac_inst->RA_msg4_list.head;
+
+	available_resource_DL_t *dci_node, *msg4_node;
+	int rmax, fail, r;
+	int dci_subframe, dci_end_subframe, dci_first_subframe, num_dci_subframe;
+	int msg4_subframe, msg4_end_subframe, msg4_first_subframe, num_msg4_subframe;
+	int harq_subframe, harq_end_subframe;
+
+	int dci_candidate, num_candidate;
+	int msg4_i_delay, i, res, rep;
+	int end_flagHARQ, HARQ_delay;
+	sched_temp_UL_NB_IoT_t HARQ_info;
+	schedule_result_t *dci_result;
+	schedule_result_t *msg4_result;
+	schedule_result_t *harq_result;
+
+	//print_available_resource_DL();
+
+	while((RA_TEMPLATE_NB_IoT *)0 != msg4_nodes){
+
+		if(msg4_nodes->wait_msg4_ack == 0){
+			fail=0;
+			//	check dci resource
+			rmax = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg4_nodes->ce_level].mac_npdcch_NumRepetitions_RA_NB_IoT;//32;
+    	    num_candidate = 8;//rmax / r;
+    		r = rmax/num_candidate;
+    		num_dci_subframe = r;
+    		dci_subframe = mac_inst->current_subframe;
+			for(dci_candidate=0; dci_candidate<num_candidate; ++dci_candidate){
+	            while(!is_dlsf(mac_inst, dci_subframe)){
+                    ++dci_subframe;
+                }
+				dci_node = (available_resource_DL_t *)check_resource_DL(mac_inst, dci_subframe, num_dci_subframe, &dci_end_subframe, &dci_first_subframe);
+				if((available_resource_DL_t *)0 != dci_node){
+					//dci_subframe += dci_candidate*num_dci_subframe;
+					printf("%d msg4 dci %d - %d\n", mac_inst->current_subframe, dci_first_subframe, dci_end_subframe);
+					break;
+				}
+				res = num_dci_subframe;
+    			while(res != 0){ //  cost lot of time to search
+                    if(is_dlsf(mac_inst, dci_subframe)){
+                        res--;
+                    }
+                    dci_subframe++;
+                }
+			}
+			if(num_candidate==dci_candidate){
+				//failed
+				fail|=1;
+			}
+
+			//	check msg4 resource
+			rep = dl_rep[msg4_nodes->ce_level];
+			num_msg4_subframe = 1*rep;   //  8 subframes
+			msg4_i_delay = find_suit_i_delay(rmax, r, dci_candidate);
+			for(i=msg4_i_delay; i<8; ++i){
+				msg4_i_delay = (msg4_i_delay==8)?0:msg4_i_delay;
+				msg4_subframe = dci_end_subframe+4+get_scheduling_delay(msg4_i_delay, rmax);
+				msg4_node = (available_resource_DL_t *)check_resource_DL(mac_inst, msg4_subframe, num_msg4_subframe*rep, &msg4_end_subframe, &msg4_first_subframe);
+				if((available_resource_DL_t *)0 != msg4_node){
+					//printf("[MSG4]\t\t\tstart %3d, num %3d, end %3d\n", msg4_subframe, num_msg4_subframe, msg4_end_subframe);
+					printf("%d msg4 %d - %d\n", mac_inst->current_subframe, msg4_first_subframe, msg4_end_subframe);
+					break;
+				}
+			}
+			if(8==i){
+				//failed
+				fail|=2;
+			}
+
+            rep = mac_inst->rrc_config.mac_NPRACH_ConfigSIB[msg4_nodes->ce_level].mac_numRepetitionsPerPreambleAttempt_NB_IoT;
+            //print_available_UL_resource();
+			for(HARQ_delay=0;HARQ_delay<4;++HARQ_delay){
+	            end_flagHARQ=Check_UL_resource(msg4_end_subframe+get_HARQ_delay(1, HARQ_delay), rep, &HARQ_info, 0, 1);	//	RA_template->R
+				if(0 == end_flagHARQ){
+					harq_subframe = msg4_end_subframe + get_HARQ_delay(1, HARQ_delay);
+					harq_end_subframe = harq_subframe + 2*rep -1;
+					HARQ_info.ACK_NACK_resource_field=get_resource_field_value(HARQ_info.subcarrier_indication, get_scheduling_delay(HARQ_delay, rmax));
+					break;
+				}
+			}
+			if(4 == HARQ_delay){
+				fail |= 4;
+			}
+
+			if(0==fail){
+			    //SCHEDULE_LOG("[%04d][RA scheduler][MSG4] rnti: %d preamble: %d success\n", mac_inst->current_subframe, msg4_nodes->ra_rnti, msg4_nodes->preamble_index);
+			    
+			    msg4_nodes->wait_msg4_ack = 1;	
+				DCIFormatN1_t *dci_n1_msg4 = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
+				//	dci entity
+				dci_n1_msg4->type = 1;
+				dci_n1_msg4->orderIndicator = 0;
+				dci_n1_msg4->Scheddly = msg4_i_delay;
+				dci_n1_msg4->ResAssign = 0;
+				dci_n1_msg4->mcs = 0;
+				dci_n1_msg4->RepNum = 1;
+				dci_n1_msg4->ndi = 1;
+				dci_n1_msg4->HARQackRes = HARQ_info.ACK_NACK_resource_field;
+				dci_n1_msg4->DCIRep = 1;
+
+				//	for dci
+				dci_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
+				dci_result->output_subframe = dci_first_subframe;//dci_subframe;
+				dci_result->end_subframe = dci_end_subframe;
+				dci_result->sdu_length = 0;
+				dci_result->direction = DL;
+				dci_result->DCI_release = 0;
+				dci_result->channel = NPDCCH;
+				dci_result->rnti = msg4_nodes->ue_rnti;
+				dci_result->rnti_type = 1;
+				dci_result->npusch_format = 0; //useless
+				dci_result->R_harq = 0;
+				dci_result->next = (schedule_result_t *)0;
+				dci_result->DCI_pdu = (void *)dci_n1_msg4;
+				
+				//	for msg4
+				msg4_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
+				msg4_result->output_subframe = msg4_first_subframe;// msg4_subframe;
+				msg4_result->end_subframe = msg4_end_subframe;
+				msg4_result->sdu_length = 0;
+				msg4_result->direction = DL;
+				msg4_result->DCI_release = 0;
+				msg4_result->channel = NPDSCH;
+				msg4_result->rnti = msg4_nodes->ue_rnti;
+		    	msg4_result->rnti_type = 1;
+		    	msg4_result->npusch_format = 0;	//useless
+		    	msg4_result->R_harq = 0;
+				msg4_result->next = (schedule_result_t *)0;
+				msg4_result->DCI_pdu = (void *)dci_n1_msg4;
+				
+
+				harq_result = (schedule_result_t *)malloc(sizeof(schedule_result_t));
+				harq_result->rnti = msg4_nodes->ue_rnti;
+			    harq_result->output_subframe = harq_subframe;
+			    harq_result->end_subframe = harq_end_subframe;
+			    harq_result->sdu_length = 0;
+			    harq_result->direction = UL;
+			    harq_result->rnti_type = 3;
+			    harq_result->DLSCH_pdu = NULL;
+			    harq_result->DCI_pdu = (void *)dci_n1_msg4;
+			    harq_result->DCI_release = 1;
+			    harq_result->channel = NPUSCH;
+			    harq_result->next = (schedule_result_t *)0;
+				
+				if(msg4_nodes->msg4_retransmit_count==0){
+			        dci_result->debug_str = str3;
+			        msg4_result->debug_str = str4;
+			        harq_result->debug_str = str5;
+                }else{
+                    dci_result->debug_str = str8;
+			        msg4_result->debug_str = str9;
+			        harq_result->debug_str = str10;
+                }
+				
+				//simulate_rx(&simulate_rx_msg4_list, msg4_nodes->ue_rnti, harq_subframe);
+				
+				//DEBUG("[%04d][RA scheduler][MSG4] UE:%x MSG4DCI %d-%d MSG4 %d-%d HARQ %d-%d\n", mac_inst->current_subframe, msg4_nodes->ue_rnti, dci_first_subframe, dci_end_subframe, msg4_first_subframe, msg4_end_subframe, HARQ_info.sf_start, HARQ_info.sf_end);
+	            msg4_nodes->msg4_retransmit_count++;
+	            
+	            
+				//	fill dci resource
+				fill_resource_DL(mac_inst, dci_node, dci_first_subframe, dci_end_subframe, dci_result);
+
+                //	fill msg4 resource
+				fill_resource_DL(mac_inst, msg4_node, msg4_first_subframe, msg4_end_subframe, msg4_result);
+
+				//	fill ack/nack resource
+				insert_schedule_result(&schedule_result_list_UL, harq_subframe, harq_result);
+				//DEBUG("check point\n");
+				adjust_UL_resource_list(&HARQ_info);
+                
+				//	active ue_list ul/dl
+				UE_list_NB_IoT_t *UE_list = mac_inst->UE_list_spec;
+				for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
+					if(UE_list->UE_template_NB_IoT[i].active == 1 && UE_list->UE_template_NB_IoT[i].rnti == msg4_nodes->ue_rnti){
+						UE_list->UE_template_NB_IoT[i].direction = rand()&1;
+					}
+				}	
+			}else{
+			    //DEBUG("[%04d][RA scheduler][MSG4] fail vector %d\n", mac_inst->current_subframe, fail );
+			    //SCHEDULE_LOG("[%04d][RA scheduler][MSG4] rnti: %d preamble: %d fail vector %d\n", mac_inst->current_subframe, msg4_nodes->ra_rnti, msg4_nodes->preamble_index, fail);
+            }
+		}
+		
+        msg4_nodes = msg4_nodes->next;
+		
+	}
+
+	return ;
+}
+
+void schedule_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst){
+
+    //uint32_t current_subframe = mac_inst->current_subframe;
+    
+    schedule_msg3_retransimission_NB_IoT(mac_inst);
+    schedule_rar_NB_IoT(mac_inst);
+	schedule_msg4_NB_IoT(mac_inst);
+
+	return ;
+}
+
+
+
+
+
+
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_RA_nb_iot.c b/openair2/LAYER2/MAC/eNB_scheduler_RA_nb_iot.c
deleted file mode 100644
index 570e1c3a16b1b3aa277f6fbf3f272a185f80a655..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/MAC/eNB_scheduler_RA_nb_iot.c
+++ /dev/null
@@ -1,287 +0,0 @@
-/*
- * 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.0  (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 eNB_scheduler_RA.c
- * \brief primitives used for random access
- * \author  Navid Nikaein and Raymond Knopp
- * \date 2010 - 2014
- * \email: navid.nikaein@eurecom.fr
- * \version 1.0
- * @ingroup _mac
-
- */
-
-#include "assertions.h"
-#include "platform_types.h"
-#include "PHY/defs.h"
-#include "PHY/extern.h"
-#include "msc.h"
-
-#include "SCHED/defs.h"
-#include "SCHED/extern.h"
-
-#include "LAYER2/MAC/defs.h"
-#include "LAYER2/MAC/extern.h"
-
-#include "LAYER2/MAC/proto.h"
-#include "UTIL/LOG/log.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-#include "UTIL/OPT/opt.h"
-#include "OCG.h"
-#include "OCG_extern.h"
-
-#include "RRC/LITE/extern.h"
-#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
-
-//NB-IoT
-#include "proto_nb_iot.h"
-#include "defs_nb_iot.h"
-#include "math.h"
-#include "openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h"
-//#include "LAYER2/MAC/pre_processor.c"
-#include "pdcp.h"
-
-#if defined(ENABLE_ITTI)
-# include "intertask_interface.h"
-#endif
-
-#include "SIMULATION/TOOLS/defs.h" // for taus
-
-#include "T.h"
-
-void NB_schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP)
-{
-
-  int CC_id;
-  eNB_MAC_INST_NB *eNB = &eNB_mac_inst_NB[module_idP];
-
-
-  RA_TEMPLATE_NB *RA_template;
-  unsigned char i,harq_pid,round;
-  int16_t rrc_sdu_length;
-  unsigned char lcid,offset;
-  int UE_id = -1;
-  unsigned short TBsize = -1;
-  unsigned short msg4_padding,msg4_post_padding,msg4_header;
-  DCI_PDU_NB *DCI_pdu;
-
-  // start_meas(&eNB->schedule_ra);
-
-  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-
-
-    
-    DCI_pdu = &eNB->common_channels[CC_id].DCI_pdu;
-
-    for (i=0; i<NB_RA_PROC_MAX; i++) {
-
-      RA_template = (RA_TEMPLATE_NB *)&eNB->common_channels[CC_id].RA_template[i];
-
-      if (RA_template->RA_active == TRUE) {
-
-        LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d RA %d is active (generate RAR %d, generate_Msg4 %d, wait_ack_Msg4 %d, rnti %x)\n",
-              module_idP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti);
-
-        if (RA_template->generate_rar == 1) {
-
-          LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI (proc %d), RA_active %d format 1A (%d,%d))\n",
-                module_idP, CC_id, frameP, subframeP,i,
-                RA_template->RA_active,
-                RA_template->RA_dci_fmt1,
-                RA_template->RA_dci_size_bits1);
-              //directly fill DCI Filed base on DCI Nq for RAR
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->type=1;
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->orderIndicator=0;
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->Scheddly=1;//fixed delay approach?
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->ResAssign=0;
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->mcs=0;//fixes?//fixes? base on CE levels?
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->RepNum=0;//fixes? base on CE levels?
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->Reserved=0;
-              ((DCIFormatN1_RAR_t*)&RA_template->RA_alloc_pdu1[0])->DCIRep=0;//fixes?
-        }
-    //New appoach for CCE allocaton, delete !CCE_allocation_infeasible..
-        else if (RA_template->generate_Msg4 == 1) {
-
-          // check for Msg4 Message
-          UE_id = find_UE_id(module_idP,RA_template->rnti);
-          if (UE_id == -1) { printf("%s:%d:%s: FATAL ERROR\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
-
-          if (Is_rrc_registered == 1) {//Fixed mac_rrc_data_req
-
-            // Get RRCConnectionSetup for Piggyback
-            rrc_sdu_length = mac_rrc_data_req(module_idP,
-                                              CC_id,
-                                              frameP,
-                                              CCCH,
-                                              1, // 1 transport block
-                                              &eNB->common_channels[CC_id].CCCH_pdu.payload[0],
-                                              ENB_FLAG_YES,
-                                              module_idP,
-                                              0); // not used in this case
-
-            if (rrc_sdu_length == -1) {
-              mac_xface->macphy_exit("[MAC][eNB Scheduler] CCCH not allocated\n");
-              return; // not reached
-            } else {
-              //msg("[MAC][eNB %d] Frame %d, subframeP %d: got %d bytes from RRC\n",module_idP,frameP, subframeP,rrc_sdu_length);
-            }
-          }
-
-          LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, Is_rrc_registered %d, rrc_sdu_length %d\n",
-                module_idP, CC_id, frameP, subframeP,UE_id, Is_rrc_registered,rrc_sdu_length);
-
-          if (rrc_sdu_length>0) {
-            LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RA proc %d, RNTI %x)\n",
-                  module_idP, CC_id, frameP, subframeP,i,RA_template->rnti);
-            // Compute MCS for 3 PRB
-            msg4_header = 1+6+1;  // CR header, CR CE, SDU header
-
-            //need to fixed ndi & msc base on NB-IoT DCI for Msg4
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1;
-            if ((rrc_sdu_length+msg4_header) <= 22) {
-              ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=4;
-              TBsize = 22;
-            } else if ((rrc_sdu_length+msg4_header) <= 28) {
-              ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=5;
-              TBsize = 28;
-            } else if ((rrc_sdu_length+msg4_header) <= 32) {
-              ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=6;
-              TBsize = 32;
-            } else if ((rrc_sdu_length+msg4_header) <= 41) {
-              ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=7;
-              TBsize = 41;
-            } else if ((rrc_sdu_length+msg4_header) <= 49) {
-              ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=8;
-              TBsize = 49;
-            } else if ((rrc_sdu_length+msg4_header) <= 57) {
-              ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->mcs=9;
-              TBsize = 57;
-            }
-
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->type=1;
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->orderIndicator=0;
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->Scheddly=1;//fixed delay approach?
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ResAssign=5;//fixed depend on mcs/tbs to Nsf
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->RepNum=1;//fixed base on CE levels
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->HARQackRes=0;//Avoid confict multiple Msg ACk
-            ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->DCIRep=0;//fixed base on CE levels
-            }
-      }else if (RA_template->wait_ack_Msg4==1) {
-  // check HARQ status and retransmit if necessary
-  LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \n",
-        module_idP,CC_id,frameP,subframeP);
-  // Get candidate harq_pid from PHY
-  mac_xface->get_ue_active_harq_pid(module_idP,CC_id,RA_template->rnti,frameP,subframeP,&harq_pid,&round,openair_harq_RA);
-  
-  if (round>0) {
-    //RA_template->wait_ack_Msg4++;
-    // we have to schedule a retransmission
-    ((DCIFormatN1_t*)&RA_template->RA_alloc_pdu2[0])->ndi=1;
-    
-    //     if (!CCE_allocation_infeasible(module_idP,CC_id,0,subframeP,2,RA_template->rnti)) {
-    //       add_ue_spec_dci(DCI_pdu,
-    //           (void*)&RA_template->RA_alloc_pdu2[0],
-    //           RA_template->rnti,
-    //           RA_template->RA_dci_size_bytes2,
-    //           2,
-    //           RA_template->RA_dci_size_bits2,
-    //           RA_template->RA_dci_fmt2,
-    //           0);
-    // printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP);
-    //     }
-      }else
-      printf("MAC: msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP);
-          LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n",
-          module_idP,CC_id,frameP,subframeP,RA_template->rnti);
-  } else {
-    /*      msg4 not received
-      if ((round == 0) && (RA_template->wait_ack_Msg4>1){
-      remove UE instance across all the layers: mac_xface->cancel_RA();
-      }
-    */
-printf("MAC: msg4 acknowledged for rnti %x fsf %d/%d, let's configure it\n", RA_template->rnti, frameP, subframeP);
-    LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_id,frameP,subframeP);
-    RA_template->wait_ack_Msg4=0;
-    RA_template->RA_active=FALSE;
-    UE_id = find_UE_id(module_idP,RA_template->rnti);
-    DevAssert( UE_id != -1 );
-    eNB_mac_inst_NB[module_idP].UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE;
-    
-  }
-  
-    }// RA_active
-  } // for i=0 .. N_RA_PROC-1 
-} // CC_id
-
-  // stop_meas(&eNB->schedule_ra);
-}
-/*This function should loop all over the preamble index*/
-void NB_initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,sub_frame_t subframeP)
-{
-
-  uint8_t i;
-  uint8_t carrier_id = 0;/*The index of the UL carrier associated with the NPRACH, the carrier_id of the anchor carrier is 0*/
-
-  RA_TEMPLATE_NB *RA_template = (RA_TEMPLATE_NB *)&eNB_mac_inst_NB[module_idP].common_channels[CC_id].RA_template[0];
-    /*preamble index will be a subcarrier index (0-47)*/
-  LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,1);
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,0);
-  /*May up to 48 RA Procdeure MAX at the moment*/
-  for (i=0; i<NB_RA_PROC_MAX; i++) {
-    if (RA_template[i].RA_active==FALSE &&
-        RA_template[i].wait_ack_Msg4 == 0) {
-      int loop = 0;
-      RA_template[i].RA_active=TRUE;
-      RA_template[i].generate_rar=1;
-      RA_template[i].generate_Msg4=0;
-      RA_template[i].wait_ack_Msg4=0;
-      RA_template[i].timing_offset=timing_offset;
-      /* TODO: find better procedure to allocate RNTI */
-      do {
-        RA_template[i].rnti = taus();
-        loop++;
-      } while (loop != 100 &&
-               /* TODO: this is not correct, the rnti may be in use without
-                * being in the MAC yet. To be refined.
-                */
-               !(find_UE_id(module_idP, RA_template[i].rnti) == -1 &&
-                 /* 1024 and 60000 arbirarily chosen, not coming from standard */
-                 RA_template[i].rnti >= 1024 && RA_template[i].rnti < 60000));
-      if (loop == 100) { printf("%s:%d:%s: FATAL ERROR! contact the authors\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
-      //RA_template[i].RA_rnti = 1+subframeP+(10*f_id);
-      /*for NB-IoT, RA_rnti is counted in 36.321 5.1.4*/
-      RA_template[i].RA_rnti = 1+floor(frameP/4)+256*carrier_id;
-      RA_template[i].preamble_index = preamble_index;
-      LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation for process %d, rnti %x, RA_active %d\n",
-            module_idP,CC_id,frameP,i,RA_template[i].rnti,
-            RA_template[i].RA_active);
-
-      return;
-    }
-  }
-
-  LOG_E(MAC,"[eNB %d][RAPROC] FAILURE: CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
-}
-
-
-
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_bch_NB_IoT.c b/openair2/LAYER2/MAC/eNB_scheduler_bch_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..2ab7911ded4c88e1e5afdffa36632f265f8e7239
--- /dev/null
+++ b/openair2/LAYER2/MAC/eNB_scheduler_bch_NB_IoT.c
@@ -0,0 +1,72 @@
+
+/*! \file eNB_scheduler_bch_NB_IoT.c
+ * \brief schedule functions for SIBs transmission in NB-IoT
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "defs_NB_IoT.h"
+#include "proto_NB_IoT.h"
+#include "extern_NB_IoT.h"
+
+unsigned char str[6][7] = { "SIBs_1", "SIBs_2", "SIBs_3", "SIBs_4", "SIBs_5", "SIBs_6" };
+
+void schedule_sibs_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, int start_subframe1){
+	
+	available_resource_DL_t *pt[8] = { (available_resource_DL_t *)0 };
+	uint32_t first_subframe[8] = { -1 };
+	//uint32_t end_subframe[8] = { -1 };
+	schedule_result_t *new_node;	
+	DCIFormatN1_t *sibs_dci;
+	uint32_t j, i, k, num_subframe, last_subframe, residual_subframe;
+	num_subframe = mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_tb;
+	
+	for(k=0, i=start_subframe1;i<(start_subframe1+mac_inst->rrc_config.si_window_length);i+=mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern, ++k){
+		//printf("[debug][sibs%d] subframe: %d, check %d", sibs_order, i, num_subframe);
+		
+		pt[k] = (available_resource_DL_t *)check_sibs_resource(mac_inst, i, i+9, num_subframe, &residual_subframe, &last_subframe, &first_subframe[k]);
+		
+		num_subframe = residual_subframe;
+		//printf("-- rest: %d, last: %d start: %d\n", num_subframe, last_subframe, start_subframe1);
+		
+		if(0==residual_subframe){
+
+			sibs_dci = (DCIFormatN1_t *)malloc(sizeof(DCIFormatN1_t));
+			sibs_dci->type = 1;
+			sibs_dci->orderIndicator = 0;
+			sibs_dci->Scheddly = 0;
+			sibs_dci->ResAssign = mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_tb;
+			sibs_dci->mcs = 2;
+			sibs_dci->RepNum = 0;
+			sibs_dci->ndi = 0;
+			sibs_dci->HARQackRes = 0;
+			sibs_dci->DCIRep = 0;
+			
+			for(k=0, j=start_subframe1;j<=i;++k, j+=mac_inst->rrc_config.sibs_NB_IoT_sched[sibs_order].si_repetition_pattern){	
+				if((available_resource_DL_t *)0 != pt[k]){
+					new_node = (schedule_result_t *)malloc(sizeof(schedule_result_t));
+					//	fill new node
+					new_node->output_subframe = first_subframe[k];
+					new_node->end_subframe = (j==i)?last_subframe:j+9;
+					new_node->sdu_length = 0;
+					new_node->direction = DL;	
+					new_node->DCI_release = (j==i);
+					new_node->channel = NPDSCH;
+					new_node->rnti = SI_RNTI;
+					new_node->rnti_type = 3;
+					new_node->npusch_format = 0;	//	useless
+					new_node->R_harq = 0;		//	useless
+					new_node->next = (schedule_result_t *)0;
+					new_node->DCI_pdu = (void *)sibs_dci;
+					new_node->debug_str = str[sibs_order];
+					fill_resource_DL(mac_inst, pt[k], first_subframe[k], (j==i)?last_subframe:j+9, new_node);
+				}
+			}
+			return ;
+		}
+	}
+	return ;
+}
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch_NB_IoT.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..d83c2c9aa2778f4ab00b662986ebdcc602725621
--- /dev/null
+++ b/openair2/LAYER2/MAC/eNB_scheduler_dlsch_NB_IoT.c
@@ -0,0 +1,844 @@
+
+/*! \file eNB_scheduler_dlsch_NB_IoT.c
+ * \brief handle DL UE-specific scheduling
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "defs_NB_IoT.h"
+#include "proto_NB_IoT.h"
+#include "extern_NB_IoT.h"
+
+void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE_TEMPLATE_NB_IoT *UE_info, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start)
+{
+	//number of candidate
+	int cdd_num;
+	//Transport block size
+	int TBS;
+	//Scheduling result buffer
+	sched_temp_DL_NB_IoT_t *NPDCCH_info = (sched_temp_DL_NB_IoT_t*)malloc(sizeof(sched_temp_DL_NB_IoT_t));
+	sched_temp_DL_NB_IoT_t *NPDSCH_info = (sched_temp_DL_NB_IoT_t*)malloc(sizeof(sched_temp_DL_NB_IoT_t));
+	sched_temp_UL_NB_IoT_t *HARQ_info = (sched_temp_UL_NB_IoT_t*)malloc(sizeof(sched_temp_UL_NB_IoT_t));
+	//DCI N1
+	DCIFormatN1_t *DCI_N1 = (DCIFormatN1_t*)malloc(sizeof(DCIFormatN1_t));
+	//RLC Status
+	//mac_rlc_status_resp_NB_IoT_t rlc_status;
+	/*Index in DCI_N1*/
+	uint32_t I_mcs, I_tbs, I_delay, I_sf;
+	/*value for corresponding index*/
+	/*Number of subframe per repetition*/
+	int n_sf;
+	/*flag*/
+	int end_flagCCH=0;
+	int end_flagSCH=0;
+	int end_flagHARQ=0;
+	int flag_retransmission=0;
+
+	int HARQ_delay=0;
+	uint32_t data_size;
+	//uint32_t mac_sdu_size;
+
+	//uint8_t sdu_temp[SCH_PAYLOAD_SIZE_MAX_NB_IoT];
+	logical_chan_id_t logical_channel;
+
+	uint32_t subheader_length=2;
+	//uint32_t payload_offset;
+
+	uint32_t search_space_end_sf, h_temp, f_temp, sf_temp;
+
+	I_mcs = get_I_mcs_NB_IoT(UE_info->CE_level);
+	I_tbs = I_mcs;
+	//get max TBS
+	TBS = get_max_tbs(I_tbs);
+	printf("[%04d][DLSchedulerUSS] Max TBS %d MCS index %d TBS index %d\n", mac_inst->current_subframe, TBS, I_mcs, I_tbs);
+	/*set UE data information*/
+	/*New transmission*/
+	if(UE_info->HARQ_round==0)
+	{
+		//Get RLC status
+		/*
+		rlc_status = mac_rlc_status_ind_NB_IoT(
+										module_id,
+										UE_info->rnti,
+										module_id,
+										frame_start,
+										subframe_start,
+										1,
+										0,
+										DCCH0_NB_IoT,
+										0);
+		data_size = rlc_status.bytes_in_buffer;
+		*/
+		data_size = 200;
+	}
+	/*Retransmission*/
+	else
+	{
+		data_size = UE_info->DLSCH_pdu_size;
+		flag_retransmission = 1;
+		if((UE_info->HARQ_round>0)&&(TBS<data_size))
+		{
+			printf("[%04d][DLSchedulerUSS][Fail] TBS is not enough for retransmission\n", mac_inst->current_subframe);
+			return;
+		}
+	}
+	printf("[%04d][DLSchedulerUSS] UE data size %d\n", mac_inst->current_subframe, data_size);
+	//Have DCCH data
+	if(data_size == 0)
+	{
+		printf("[%04d][DLSchedulerUSS][Fail] No data in DCCH0_NB_IoT\n", mac_inst->current_subframe);
+		return;
+	}
+	if(data_size>127)
+	{
+		subheader_length=3;
+	}
+	if(TBS > data_size+subheader_length)
+	{
+		TBS = get_tbs(data_size, I_tbs, &I_sf);
+		printf("[%04d][DLSchedulerUSS] TBS change to %d because data size is smaller than previous TBS\n", mac_inst->current_subframe, TBS);
+	}
+
+  search_space_end_sf=cal_num_dlsf(mac_inst, hyperSF_start, frame_start, subframe_start, &h_temp, &f_temp, &sf_temp, UE_info->R_max);
+  printf("[%04d][DLSchedulerUSS] Search_space_start_sf %d Search_space_end_sf %d\n", convert_system_number_sf(hyperSF_start, frame_start, subframe_start), mac_inst->current_subframe, search_space_end_sf);
+	/*Loop all NPDCCH candidate position*/
+	for(cdd_num=0;cdd_num<UE_info->R_max/UE_info->R_dci;++cdd_num)
+	{
+		//DEBUG("[%04d][DLSchedulerUSS] Candidate num %d DCI Rep %d\n", cdd_num, UE_info->R_dci);
+		/*Check NPDCCH Resource*/
+		end_flagCCH = check_resource_NPDCCH_NB_IoT(mac_inst, hyperSF_start, frame_start, subframe_start, NPDCCH_info, cdd_num, UE_info->R_dci);
+
+		//This candidate position is available
+		/*Check NPDSCH Resource*/
+		if(end_flagCCH!=-1)
+		{
+		  //DEBUG("[%04d][DLSchedulerUSS] Candidate num %d allocate success\n", cdd_num);
+			//DEBUG("[%04d][DLSchedulerUSS] Allocate NPDCCH subframe %d to subframe %d cdd index %d\n", mac_inst->current_subframe, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
+			/*
+			//Max DL TBS
+			if(TBS > data_size+subheader_length)
+			{
+				TBS = get_tbs(data_size, I_tbs, &I_sf);
+				DEBUG("[%04d][DLSchedulerUSS] TBS change to %d because data size is smaller than previous TBS\n", mac_inst->current_subframe, TBS);
+			}
+			*/
+			//Get number of subframe this UE need per repetition
+			n_sf = get_num_sf(I_sf);
+			//DEBUG("[%04d][DLSchedulerUSS] Number SF %d index SF %d\n", n_sf, I_sf);
+			//DEBUG("[%04d][DLSchedulerUSS] Require total %d DL SF Rep %d\n", n_sf*UE_info->R_dl, UE_info->R_dl);
+			//Check have enough NPDSCH resource or not
+			//loop 8 scheduling delay index
+			for(I_delay=0;I_delay<8;++I_delay)
+			{
+		        if(search_space_end_sf<NPDCCH_info->sf_end+get_scheduling_delay(I_delay, UE_info->R_max)+5)
+		        {
+		          end_flagSCH = check_resource_NPDSCH_NB_IoT(mac_inst, NPDSCH_info, NPDCCH_info->sf_end, I_delay, UE_info->R_max, UE_info->R_dl, n_sf);
+		          //Have available resource
+		          /*Check HARQ resource*/
+		          if(end_flagSCH!=-1)
+		          {
+		            //DEBUG("[%04d][DLSchedulerUSS] Scheduling delay index: %d value: %d + 4 allocate success\n", mac_inst->current_subframe, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
+		            //DEBUG("[%04d][DLSchedulerUSS] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
+		            for(HARQ_delay=0;HARQ_delay<4;++HARQ_delay)
+		            {
+		              //DEBUG("[%04d][DLSchedulerUSS] HARQ delay %d\n", mac_inst->current_subframe,get_HARQ_delay(1, HARQ_delay) );
+		              end_flagHARQ=Check_UL_resource(NPDSCH_info->sf_end+get_HARQ_delay(1, HARQ_delay), UE_info->R_harq, HARQ_info, 0, 1);
+		              if(end_flagHARQ!=-1)
+		              {
+		                //DEBUG("[%04d][DLSchedulerUSS] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, HARQ_info->sf_start, HARQ_info->sf_end);
+		                HARQ_info->ACK_NACK_resource_field=get_resource_field_value(HARQ_info->subcarrier_indication, get_scheduling_delay(HARQ_delay, UE_info->R_max));
+		                //toggle NDI
+		                if(flag_retransmission==0)
+		                {
+		                  UE_info->oldNDI_DL=(UE_info->oldNDI_DL+1)%2;
+		                  //New transmission need to request data from RLC and generate new MAC PDU
+		                  UE_info->I_mcs_dl = I_mcs;
+		                  /*
+		                  //Request data from RLC layer
+		                  rlc_status = mac_rlc_status_ind_NB_IoT(
+		                        module_id,
+		                        UE_info->rnti,
+		                        module_id,
+		                        frame_start,
+		                        subframe_start,
+		                        1,
+		                        0,
+		                        DCCH0_NB_IoT,
+		                        TBS-subheader_length);
+		                  */
+		                  //mac_sdu_size = mac_rlc_data_req_eNB_NB_IoT(module_id, UE_info->rnti, 0, frame_start, 0, DCCH0_NB_IoT, sdu_temp);
+		                  logical_channel=DCCH0_NB_IoT;
+		                  //Generate header
+		                  //payload_offset = generate_dlsch_header_NB_IoT(UE_info->DLSCH_pdu.payload, 1, &logical_channel, &mac_sdu_size, 0, 0, TBS);
+		                  //Complete MAC PDU
+		                  //memcpy(UE_info->DLSCH_pdu.payload+payload_offset, sdu_temp, mac_sdu_size);
+		                  UE_info->DLSCH_pdu.pdu_size=TBS;
+		                }
+		                //SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] RNTI %d complete scheduling\n", mac_inst->current_subframe, UE_info->rnti);
+		                //SCHEDULE_LOG("[%04d][DLSchedulerUSS] RNTI %d\n", mac_inst->current_subframe, UE_info->rnti);
+		                //SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Allocate NPDCCH subframe %d to subframe %d cdd index %d\n", mac_inst->current_subframe, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
+		                //SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Scheduling delay index: %d value: %d + 4\n", mac_inst->current_subframe, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
+		                //SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
+		                //SCHEDULE_LOG("[%04d][DLSchedulerUSS][Success] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, HARQ_info->sf_start, HARQ_info->sf_end);
+		                //DEBUG("[%04d][DLSchedulerUSS] Allocate NPDCCH subframe %d to subframe %d cdd index %d\n", mac_inst->current_subframe, NPDCCH_info->sf_start, NPDCCH_info->sf_end, cdd_num);
+		                //DEBUG("[%04d][DLSchedulerUSS] Scheduling delay index: %d value: %d + 4\n", mac_inst->current_subframe, I_delay, get_scheduling_delay(I_delay, UE_info->R_max));
+		                //DEBUG("[%04d][DLSchedulerUSS] Allocate NPDSCH subframe %d to subframe %d\n", mac_inst->current_subframe, NPDSCH_info->sf_start, NPDSCH_info->sf_end);
+		                //DEBUG("[%04d][DLSchedulerUSS] Allocate HARQ feedback subframe %d to subframe %d\n", mac_inst->current_subframe, HARQ_info->sf_start, HARQ_info->sf_end);
+		                //Store PDU in UE template for retransmission
+		                fill_DCI_N1(DCI_N1, UE_info, I_delay, I_sf, HARQ_info->ACK_NACK_resource_field);
+		                //DEBUG("[%04d][DLSchedulerUSS] HARQ index %d\n", HARQ_info->ACK_NACK_resource_field);
+		                printf("[%04d][DLSchedulerUSS] DCI N1 type:%d order:%d MCS:%d HARQ index:%d R:%d RscAssign:%d scheddly:%d DCI_R:%d\n", mac_inst->current_subframe, DCI_N1->type, DCI_N1->orderIndicator, DCI_N1->mcs, DCI_N1->HARQackRes, DCI_N1->RepNum, DCI_N1->ResAssign, DCI_N1->Scheddly, DCI_N1->DCIRep);
+		                //Generate Scheduling result for this UE
+		                generate_scheduling_result_DL(NPDCCH_info->sf_start, NPDSCH_info->sf_start, HARQ_info->sf_start, DCI_N1, UE_info->rnti, TBS, UE_info->DLSCH_pdu.payload);
+		                //DEBUG("[%04d][DLSchedulerUSS] finish generate scheduling result\n");
+		                //matain DL avialable resource
+		                maintain_resource_DL(mac_inst, NPDCCH_info, NPDSCH_info);
+		                //available_resource_DL_t *temp=available_resource_DL;
+		                /*
+		                while(temp!=NULL)
+		                {
+		                  DEBUG("[%04d][DLSchedulerUSS] Available resource node subframe start %d end %d\n", mac_inst->current_subframe, temp->start_subframe, temp->end_subframe);
+		                  temp=temp->next;
+		                }
+		                */
+		                //Do maintain UL resource
+		                adjust_UL_resource_list(HARQ_info);
+		                printf("[%04d][DLSchedulerUSS] Complete DL scheduling\n", mac_inst->current_subframe);
+		                
+
+		                //SCHEDULE_LOG("[%04d][DLSchedulerUSS] RNTI %d complete scheduling\n", mac_inst->current_subframe, UE_info->rnti);
+
+		                return;
+		              }
+		            }
+		            /*harq resource fail*/
+		            if(end_flagHARQ==-1)
+		            {
+		              //DEBUG("[%04d][DLSchedulerUSS] [Fail]HARQ_delay %d HARQ Resource fail\n", mac_inst->current_subframe, HARQ_delay);
+		            }
+		          }
+		          //DEBUG("[%04d][DLSchedulerUSS] Scheduling delay index %d allocate fail\n", mac_inst->current_subframe, I_delay);
+		        }
+			}
+			/*NPDSCH resource fail*/
+			if(end_flagSCH==-1)
+			{
+				//DEBUG("[%04d][DLSchedulerUSS] [Fail]I_delay %d NPDSCH Resource fail\n", mac_inst->current_subframe, I_delay);
+			}
+		}
+		//DEBUG("[%04d][DLSchedulerUSS] Candidate %d no resource\n", mac_inst->current_subframe, cdd_num);
+
+	}
+	/*Resource allocate fail*/
+	if((end_flagCCH==-1)||(end_flagSCH==-1)||(end_flagHARQ==-1))
+	{
+		printf("[%04d][DLSchedulerUSS][Fail]Resource allocate fail\n", mac_inst->current_subframe);
+		printf("[%04d][DLSchedulerUSS][Fail]RNTI %d resource allocate fail\n", mac_inst->current_subframe, UE_info->rnti);
+	}
+}
+
+int check_resource_NPDCCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, sched_temp_DL_NB_IoT_t *NPDCCH_info, uint32_t cdd_num, uint32_t dci_rep)
+{
+	NPDCCH_info->sf_start = cal_num_dlsf(mac_inst, hyperSF_start, frame_start, subframe_start, &(NPDCCH_info->start_h), &(NPDCCH_info->start_f), &(NPDCCH_info->start_sf), dci_rep*cdd_num+1);
+	//DEBUG("[check_resource_NPDCCH_NB_IoT]abs start : %d\n", NPDCCH_info->sf_start);
+	return check_resource_DL_NB_IoT(mac_inst, NPDCCH_info->start_h, NPDCCH_info->start_f, NPDCCH_info->start_sf, dci_rep, NPDCCH_info);
+}
+
+int check_resource_NPDSCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDSCH_info, uint32_t sf_end, uint32_t I_delay, uint32_t R_max, uint32_t R_dl, uint32_t n_sf)
+{
+	int sf_temp = sf_end+get_scheduling_delay(I_delay, R_max)+5;
+	while(is_dlsf(mac_inst, sf_temp)!=1)
+  {
+    ++sf_temp;
+  }
+	NPDSCH_info->sf_start = sf_temp;
+	//transform sf into Hyper SF, Frame and subframe
+	convert_system_number(NPDSCH_info->sf_start,&(NPDSCH_info->start_h), &(NPDSCH_info->start_f), &(NPDSCH_info->start_sf));
+	//check this position available or not
+	return check_resource_DL_NB_IoT(mac_inst, NPDSCH_info->start_h, NPDSCH_info->start_f, NPDSCH_info->start_sf, R_dl*n_sf, NPDSCH_info);
+}
+
+/*Check the available resource is enough or not from input starting position*/
+/*return 0:success\1:fail*/
+int check_resource_DL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, uint32_t dlsf_require, sched_temp_DL_NB_IoT_t *schedule_info)
+{
+
+	uint32_t node_start_sf, node_end_sf;
+	uint32_t rsc_start_sf, rsc_end_sf;
+
+	/*calculate the last subframe number for this transmission*/
+	schedule_info->sf_end= cal_num_dlsf(mac_inst, hyperSF_start, frame_start, subframe_start, &(schedule_info->end_h), &(schedule_info->end_f), &(schedule_info->end_sf), dlsf_require);
+	//DEBUG("abs_end = %d\n", schedule_info->sf_end);
+	rsc_start_sf = schedule_info->sf_start;
+	if(schedule_info->sf_start<=schedule_info->sf_end)
+	{
+		rsc_end_sf = schedule_info->sf_end;
+	}
+	else
+	{
+		/*input position + Upper bound of subframe*/
+		rsc_end_sf = schedule_info->sf_end+(1024*1024*10);
+	}
+	//DEBUG("check_resource_DL_NB_IoT flag 1\n");
+	/*initialize*/
+	schedule_info->node = available_resource_DL;
+	//DEBUG("rsc need start subframe %d end subframe %d\n", rsc_start_sf, rsc_end_sf);
+	/*Check available resource nodes to find the appropriate resource position*/
+	while(schedule_info->node!=NULL)
+	{
+		//schedule_info->node->start_subframe <= schedule_info->sf_end
+		//DEBUG("check_resource_DL_NB_IoT flag 2\n");
+		node_start_sf = schedule_info->node->start_subframe;
+		if(schedule_info->node->start_subframe<=schedule_info->node->end_subframe)
+		{
+			node_end_sf = schedule_info->node->end_subframe;
+		}
+		else
+		{
+			/*input position + Upper bound of subframe*/
+			node_end_sf = schedule_info->node->end_subframe+(1024*1024*10);
+		}
+		//DEBUG("node start %d node end %d\n", node_start_sf, node_end_sf);
+        if((node_start_sf<=rsc_start_sf)&&(node_end_sf>=rsc_end_sf))
+        {
+            return 0;
+        }
+        schedule_info->node = schedule_info->node->next;
+	}
+	//DEBUG("check_resource_DL_NB_IoT flag 3\n");
+	return -1;
+}
+
+uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_chan_id_t *logical_channel, uint32_t *sdu_length, uint8_t flag_drx, uint8_t flag_ta, uint32_t TBS)
+{
+	int i;
+	uint32_t total_sdu_size=0;
+	//number of control element
+	uint32_t num_ce=0;
+	uint32_t num_subheader=0;
+	uint32_t num_sdu_L_15;
+	int32_t padding_size;
+	uint8_t flag_end_padding=0;
+	SCH_SUBHEADER_FIXED_NB_IoT *mac_header=(SCH_SUBHEADER_FIXED_NB_IoT*)pdu;
+	uint32_t offset=0;
+
+	for(i=0;i<num_sdu;++i)
+	{
+		printf("index %d sdu size %d\n", i, sdu_length[i]);
+		if(sdu_length[i]>127)
+		{
+			num_sdu_L_15++;
+		}
+		total_sdu_size+=sdu_length[i];
+	}
+	if(flag_drx==1)
+		num_ce++;
+	if(flag_ta==1)
+		num_ce++;
+	num_subheader=num_ce+num_sdu;
+	padding_size = TBS-total_sdu_size-num_ce;
+	if(padding_size<0)
+	{
+		printf("[ERROR]TBS less than require subheader and control element\n");
+		return -1;
+	}
+	printf("total SDU size %d\n", total_sdu_size);
+	printf("padding size %d\n", padding_size);
+	if(padding_size>2)
+	{
+		flag_end_padding=1;
+	}
+	if((padding_size<=2)&&(padding_size>0))
+	{
+		mac_header->LCID=PADDING;
+		mac_header->E=1;
+		mac_header->F2=0;
+		mac_header->R=0;
+		mac_header++;
+		offset++;
+	}
+	if(padding_size==2)
+	{
+		mac_header->LCID=PADDING;
+		mac_header->E=1;
+		mac_header->F2=0;
+		mac_header->R=0;
+		mac_header++;
+		offset++;
+	}
+	if(flag_drx==1)
+	{
+		mac_header->LCID=DRX_COMMAND;
+		mac_header->E=1;
+		mac_header->F2=0;
+		mac_header->R=0;
+		mac_header++;
+		num_subheader--;
+		offset++;
+	}
+	for(i=0;i<num_sdu;++i)
+	{
+		if((num_subheader==1)&&(flag_end_padding!=1))
+        {
+            mac_header->E=0;
+            mac_header->LCID = logical_channel[i];
+            mac_header->F2=0;
+            mac_header->R=0;
+            offset++;
+            printf("last sdu\n");
+        }
+        else
+        {
+            if(sdu_length[i]<128)
+            {
+                ((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->LCID = logical_channel[i];
+                ((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->F2=0;
+                ((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->R=0;
+                ((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->E=1;
+                ((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->F=0;
+                ((SCH_SUBHEADER_SHORT_NB_IoT*)mac_header)->L=(uint8_t)sdu_length[i];
+                num_subheader--;
+                mac_header+=2;
+                offset+=2;
+            }
+            else
+            {
+                ((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->LCID = logical_channel[i];
+                ((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->F2=0;
+                ((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->R=0;
+                ((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->F=1;
+                ((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->E=1;
+                ((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->L_MSB=(uint8_t)(sdu_length[i]/256);
+                ((SCH_SUBHEADER_LONG_NB_IoT*)mac_header)->L_LSB=(uint8_t)(sdu_length[i]%256);
+                mac_header+=3;
+                num_subheader--;
+                offset+=3;
+            }
+        }
+	}
+	if(flag_end_padding==1)
+	{
+		mac_header->LCID=PADDING;
+		mac_header->E=0;
+		mac_header->F2=0;
+		mac_header->R=0;
+		mac_header++;
+		offset++;
+	}
+	return offset;
+}
+
+void fill_DCI_N1(DCIFormatN1_t *DCI_N1, UE_TEMPLATE_NB_IoT *UE_info, uint32_t scheddly, uint32_t I_sf, uint32_t I_harq)
+{
+	DCI_N1->type=1;
+	DCI_N1->orderIndicator = 0;
+	DCI_N1->Scheddly = scheddly;
+	DCI_N1->ResAssign = I_sf;
+	DCI_N1->mcs = UE_info->I_mcs_dl;
+	DCI_N1->RepNum = get_index_Rep_dl(UE_info->R_dl);
+	DCI_N1->HARQackRes = I_harq;
+	//DCI_N1->DCIRep = 3-UE_info->R_max/UE_info->R_dci/2;
+	DCI_N1->DCIRep = UE_info->R_dci;
+}
+
+void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subframe, uint32_t HARQ_subframe, DCIFormatN1_t *DCI_pdu, rnti_t rnti, uint32_t TBS, uint8_t *DLSCH_pdu)
+{
+	// create the schedule result node for this time transmission
+	schedule_result_t *NPDCCH_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+	schedule_result_t *NPDSCH_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+	schedule_result_t *HARQ_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+
+	schedule_result_t *tmp, *tmp1;
+	/*fill NPDCCH result*/
+	NPDCCH_result->rnti=rnti;
+	NPDCCH_result->output_subframe = DCI_subframe;
+	NPDCCH_result->sdu_length = TBS;
+	NPDCCH_result->direction = 1;
+	NPDCCH_result->rnti_type = 3;
+	NPDCCH_result->DLSCH_pdu = NULL;
+	NPDCCH_result->DCI_pdu = DCI_pdu;
+	NPDCCH_result->DCI_release = 0;
+	NPDCCH_result->channel = NPDCCH;
+	NPDCCH_result->next = NULL;
+	/*fill NPDSCH result*/
+	NPDSCH_result->rnti=rnti;
+	NPDSCH_result->output_subframe = NPDSCH_subframe;
+	NPDSCH_result->sdu_length = TBS;
+	//NPDSCH_result->DLSCH_pdu = DLSCH_pdu;
+	NPDSCH_result->DLSCH_pdu = NULL;
+	NPDSCH_result->direction = 1;
+	NPDSCH_result->rnti_type = 3;
+	NPDSCH_result->DCI_pdu = DCI_pdu;
+	NPDSCH_result->DCI_release = 0;
+	NPDSCH_result->channel = NPDSCH;
+	NPDSCH_result->next = NULL;
+	/*fill HARQ result*/
+	HARQ_result->rnti=rnti;
+	HARQ_result->output_subframe = HARQ_subframe;
+	HARQ_result->sdu_length = 0;
+	HARQ_result->direction = 1;
+	HARQ_result->rnti_type = 3;
+	HARQ_result->DLSCH_pdu = NULL;
+	HARQ_result->DCI_pdu = DCI_pdu;
+	HARQ_result->DCI_release = 1;
+	HARQ_result->channel = NPUSCH;
+	HARQ_result->npusch_format = 1;
+	HARQ_result->next = NULL;
+  //DEBUG("[generate_scheduling_result_DL] Generate NPDCCH node\n");
+	/*NPDCCH scheduling result*/
+	// be the first node of the DL scheduling result
+	
+	tmp = NULL;
+	tmp1 = NULL;
+	
+	if(schedule_result_list_DL == NULL)
+	{
+		//schedule_result_list_DL = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+		schedule_result_list_DL = NPDCCH_result;
+		printf("[generate_scheduling_result_DL] Generate NPDCCH node at head\n");
+	}
+	else
+	{
+		tmp = schedule_result_list_DL;
+		while(tmp!=NULL)
+		{
+			if(DCI_subframe < tmp->output_subframe)
+			{
+				break;
+			}
+			tmp1 = tmp;
+			tmp = tmp->next;
+			//DEBUG("[generate_scheduling_result_DL] node output subframe %d at NPDCCH part\n", tmp->output_subframe);
+		}
+		/*tail*/
+		if(tmp==NULL)
+		{
+			tmp1->next = NPDCCH_result;
+		}
+		else
+		{
+			NPDCCH_result->next = tmp;
+			if(tmp1)
+			{
+				tmp1->next = NPDCCH_result;
+			}
+			else
+			{
+				schedule_result_list_DL = NPDCCH_result;
+			}
+		}
+	}
+	//DEBUG("[generate_scheduling_result_DL] Generate NPDCSH node\n");
+	/*NPDSCH scheduling result*/
+	tmp1 = NULL;
+	tmp = schedule_result_list_DL;
+	while(tmp!=NULL)
+	{
+		if(NPDSCH_subframe < tmp->output_subframe)
+		{
+			break;
+		}
+		//DEBUG("[generate_scheduling_result_DL] node output subframe %d at NPDSCH part\n", tmp->output_subframe);
+		tmp1 = tmp;
+		tmp = tmp->next;
+	}
+	if(tmp==NULL)
+	{
+		tmp1->next = NPDSCH_result;
+	}
+	else
+	{
+		NPDSCH_result->next = tmp;
+		if(tmp1)
+		{
+			tmp1->next = NPDSCH_result;
+		}
+		else
+		{
+			schedule_result_list_DL = NPDSCH_result;
+		}
+	}
+  //DEBUG("[generate_scheduling_result_DL] Generate HARQ node\n");
+	/*HARQ scheduling result*/
+	// be the first node of UL
+	// be the first node of UL
+	
+	tmp1 = NULL;
+	if(schedule_result_list_UL == NULL)
+	{
+	  //schedule_result_list_UL = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+	  schedule_result_list_UL = HARQ_result;
+	}
+	else
+	{
+		tmp = schedule_result_list_UL;
+		while(tmp!=NULL)
+		{
+			if(HARQ_subframe < tmp->output_subframe)
+			{
+				break;
+			}
+			//DEBUG("[generate_scheduling_result_DL] node output subframe %d at HARQ part\n", tmp->output_subframe);
+			tmp1 = tmp;
+			tmp = tmp->next;
+		}
+		if(tmp==NULL)
+		{
+			tmp1->next = HARQ_result;
+		}
+		else
+		{
+			HARQ_result->next = tmp;
+			if(tmp1)
+			{
+				tmp1->next = HARQ_result;
+			}else
+			{
+				schedule_result_list_UL = HARQ_result;
+			}
+		}
+	}
+	/*
+	DEBUG("---[generate_scheduling_result_DL] schedule result after generate---\n");
+	tmp = schedule_result_list_DL;
+	while(tmp!=NULL)
+	{
+		DEBUG("[generate_scheduling_result_DL] node output subframe %d\n", tmp->output_subframe);
+		tmp = tmp->next;
+	}
+	*/
+}
+
+void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDCCH_info, sched_temp_DL_NB_IoT_t *NPDSCH_info)
+{
+	available_resource_DL_t *temp;
+	uint8_t flag_same=0;
+	int align_left;
+	int align_right;
+	uint32_t H_temp, f_temp, sf_temp;
+  uint32_t H_temp_r, f_temp_r, sf_temp_r;
+
+	if(NPDSCH_info==NULL)
+	{
+		/****Maintain NPDCCH node*******/
+		//	divided into two node
+		//	keep one node(align left or right)
+		//	delete node
+		convert_system_number(NPDCCH_info->node->start_subframe, &H_temp, &f_temp, &sf_temp);
+		//align_left = (calculate_DLSF(mac_inst, NPDCCH_info->node->start_subframe, NPDCCH_info->sf_start) == 0);
+		align_left=(cal_num_dlsf(mac_inst, H_temp, f_temp, sf_temp, &H_temp_r, &f_temp_r, &sf_temp_r, 1)==NPDCCH_info->sf_start);
+		align_right = ((calculate_DLSF(mac_inst, NPDCCH_info->sf_end, NPDCCH_info->node->end_subframe) == 0)||(NPDCCH_info->sf_end==NPDCCH_info->node->end_subframe));
+		//align_left = (calculate_DLSF(mac_inst, NPDCCH_info->node->start_subframe, NPDCCH_info->sf_start) == 0);
+		//DEBUG("[maintain_resource_DL] align left %d align right %d\n", align_left, align_right);
+		switch(align_left+align_right)
+		{
+			case 0:
+				//	divided into two node
+				temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
+				temp->next = NPDCCH_info->node->next;
+				temp->prev = NPDCCH_info->node;
+				NPDCCH_info->node->next = temp;
+
+				temp->start_subframe = NPDCCH_info->sf_end+1;
+				temp->end_subframe = NPDCCH_info->node->end_subframe;
+
+				NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start - 1;
+				break;
+			case 1:
+				//	keep one node
+				if(align_left)
+				{
+					NPDCCH_info->node->start_subframe = NPDCCH_info->sf_end+1;
+				}
+				else
+				{
+					NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start-1 ;
+				}
+				break;
+			case 2:
+				//	delete
+				if(NPDCCH_info->node->prev==NULL)
+        {
+          available_resource_DL = NPDCCH_info->node->next;
+        }
+        else
+        {
+          NPDCCH_info->node->prev->next = NPDCCH_info->node->next;
+          if(NPDCCH_info->node->next!=NULL)
+          {
+            NPDCCH_info->node->next->prev = NPDCCH_info->node->prev;
+          }
+        }
+				free(NPDCCH_info->node);
+				break;
+			default:
+				//error
+				break;
+      free(NPDCCH_info);
+		}
+	}
+	else
+	{
+    if(NPDCCH_info->node==NPDSCH_info->node)
+		{
+			flag_same=1;
+			printf("[%04d][maintain_resource_DL] NPDCCH and NPDSCH using the same node\n", mac_inst->current_subframe);
+		}
+		/****Maintain NPDCCH node*******/
+		//	divided into two node
+		//	keep one node(align left or right)
+		//	delete node
+
+		convert_system_number(NPDCCH_info->node->start_subframe, &H_temp, &f_temp, &sf_temp);
+		//align_left = (calculate_DLSF(mac_inst, NPDCCH_info->node->start_subframe, NPDCCH_info->sf_start) == 0);
+		align_left=(cal_num_dlsf(mac_inst, H_temp, f_temp, sf_temp, &H_temp_r, &f_temp_r, &sf_temp_r, 1)==NPDCCH_info->sf_start);
+		align_right = ((calculate_DLSF(mac_inst, NPDCCH_info->sf_end, NPDCCH_info->node->end_subframe) == 0)||(NPDCCH_info->sf_end==NPDCCH_info->node->end_subframe));
+		//DEBUG("[maintain_resource_DL] align left %d align right %d\n", align_left, align_right);
+		switch(align_left+align_right)
+		{
+			case 0:
+				//	divided into two node
+				temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
+				
+				//	calvin added
+				if((available_resource_DL_t *)0 == NPDCCH_info->node->next){
+					available_resource_DL_last = temp;
+				}
+				
+				temp->next = NPDCCH_info->node->next;
+				temp->prev = NPDCCH_info->node;
+				NPDCCH_info->node->next = temp;
+
+				temp->start_subframe = NPDCCH_info->sf_end+1;
+				temp->end_subframe = NPDCCH_info->node->end_subframe;
+
+				NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start - 1;
+				if(flag_same==1)
+				{
+					NPDSCH_info->node = temp;
+				}
+				break;
+			case 1:
+				//	keep one node
+				if(align_left)
+				{
+					NPDCCH_info->node->start_subframe = NPDCCH_info->sf_end+1;
+					printf("[%04d][maintain_resource_DL] NPDCCH keep one node\n", mac_inst->current_subframe);
+				}
+				else
+				{
+					NPDCCH_info->node->end_subframe = NPDCCH_info->sf_start-1 ;
+				}
+				break;
+			case 2:
+				//	delete
+				printf("[%04d][maintain_resource_DL] NPDCCH delete node\n", mac_inst->current_subframe);
+				
+				//	calvin add
+				if((available_resource_DL_t *)0 == NPDCCH_info->node->next){
+					available_resource_DL_last = NPDCCH_info->node->prev;
+				}
+				
+        if(NPDCCH_info->node->prev==NULL)
+        {
+          available_resource_DL = NPDCCH_info->node->next;
+        }
+        else
+        {
+          NPDCCH_info->node->prev->next = NPDCCH_info->node->next;
+          if(NPDCCH_info->node->next!=NULL)
+          {
+            NPDCCH_info->node->next->prev = NPDCCH_info->node->prev;
+          }
+        }
+				free(NPDCCH_info->node);
+				break;
+			default:
+				//error
+				break;
+		}
+		/****Maintain NPDSCH node*******/
+		align_left = (calculate_DLSF(mac_inst, NPDSCH_info->node->start_subframe, NPDSCH_info->sf_start) == 0);
+		align_right = ((calculate_DLSF(mac_inst, NPDSCH_info->sf_end, NPDSCH_info->node->end_subframe) == 0)||(NPDSCH_info->sf_end==NPDSCH_info->node->end_subframe));
+		switch(align_left+align_right)
+		{
+			case 0:
+				//	divided into two node
+				temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
+				
+				//	calvin added
+				if((available_resource_DL_t *)0 == NPDSCH_info->node->next){
+					available_resource_DL_last = temp;
+				}
+				
+				temp->next = NPDSCH_info->node->next;
+				temp->prev = NPDSCH_info->node;
+				NPDSCH_info->node->next = temp;
+
+				temp->start_subframe = NPDSCH_info->sf_end+1;
+				temp->end_subframe = NPDSCH_info->node->end_subframe;
+
+				NPDSCH_info->node->end_subframe = NPDSCH_info->sf_start - 1;
+
+				break;
+			case 1:
+				//	keep one node
+				if(align_left)
+				{
+					NPDSCH_info->node->start_subframe = NPDSCH_info->sf_end+1;
+				}
+				else
+				{
+					NPDSCH_info->node->end_subframe = NPDSCH_info->sf_start-1 ;
+				}
+				break;
+			case 2:
+				//	delete
+				
+				//	calvin added
+				if((available_resource_DL_t *)0 == NPDSCH_info->node->next){
+					available_resource_DL_last = NPDSCH_info->node->prev;
+				}
+				
+				if(NPDSCH_info->node->prev==NULL)
+        {
+          available_resource_DL = NPDSCH_info->node->next;
+        }
+        else
+        {
+          NPDSCH_info->node->prev->next = NPDSCH_info->node->next;
+          if(NPDSCH_info->node->next!=NULL)
+          {
+            NPDSCH_info->node->next->prev = NPDSCH_info->node->prev;
+          }
+        }
+				free(NPDSCH_info->node);
+				break;
+			default:
+				//error
+				break;
+		}
+		free(NPDCCH_info);
+		free(NPDSCH_info);
+	}
+}
+
+uint8_t get_index_Rep_dl(uint16_t R)
+{
+  int i;
+  if(R<=128)
+  {
+    for(i=0;i<16;++i)
+    {
+      if(R==R_dl_table[i])
+      {
+        return i;
+      }
+    }
+    printf("[get_index_Rep] error\n");
+  }
+  return -1;
+}
\ No newline at end of file
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_dlsch_nb_iot.c b/openair2/LAYER2/MAC/eNB_scheduler_dlsch_nb_iot.c
deleted file mode 100644
index 574250ceb45241d0f71a1903bc5bc5a5366c8096..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/MAC/eNB_scheduler_dlsch_nb_iot.c
+++ /dev/null
@@ -1,101 +0,0 @@
-/*
- * 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.0  (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 eNB_scheduler_dlsch.c
- * \brief procedures related to eNB for the DLSCH transport channel
- * \author  Navid Nikaein and Raymond Knopp
- * \date 2010 - 2014
- * \email: navid.nikaein@eurecom.fr
- * \version 1.0
- * @ingroup _mac
-
- */
-
-#include "assertions.h"
-#include "PHY/defs.h"
-#include "PHY/extern.h"
-
-#include "SCHED/defs.h"
-#include "SCHED/extern.h"
-
-#include "LAYER2/MAC/defs.h"
-#include "LAYER2/MAC/proto.h"
-#include "LAYER2/MAC/extern.h"
-#include "UTIL/LOG/log.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-#include "UTIL/OPT/opt.h"
-#include "OCG.h"
-#include "OCG_extern.h"
-//NB-IoT
-#include "defs_nb_iot.h"
-#include "proto_nb_iot.h"
-
-#include "RRC/LITE/extern.h"
-#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
-
-//#include "LAYER2/MAC/pre_processor.c"
-#include "pdcp.h"
-
-#include "SIMULATION/TOOLS/defs.h" // for taus
-
-#if defined(ENABLE_ITTI)
-# include "intertask_interface.h"
-#endif
-
-#include "T.h"
-
-#define ENABLE_MAC_PAYLOAD_DEBUG
-//#define DEBUG_eNB_SCHEDULER 1
-
-
-uint8_t *NB_get_dlsch_sdu(
-  module_id_t module_idP,
-  int CC_id,
-  frame_t frameP,
-  rnti_t rntiP,
-  uint8_t TBindex
-)
-//------------------------------------------------------------------------------
-{
-
-  int UE_id;
-  eNB_MAC_INST_NB *eNB=&eNB_mac_inst_NB[module_idP];
-
-  /*for SIBs*/
-  if (rntiP==SI_RNTI) {
-    LOG_D(MAC,"[eNB %d] CC_id %d Frame %d Get DLSCH sdu for BCCH \n", module_idP, CC_id, frameP);
-
-    return((unsigned char *)&eNB->common_channels[CC_id].BCCH_pdu.payload[0]);
-  }
-
-  UE_id = find_UE_id(module_idP,rntiP);
-
-  if (UE_id != -1) {
-    LOG_D(MAC,"[eNB %d] Frame %d:  CC_id %d Get DLSCH sdu for rnti %x => UE_id %d\n",module_idP,frameP,CC_id,rntiP,UE_id);
-    return((unsigned char *)&eNB->UE_list.DLSCH_pdu[CC_id][TBindex][UE_id].payload[0]);
-  } else {
-    LOG_E(MAC,"[eNB %d] Frame %d: CC_id %d UE with RNTI %x does not exist\n", module_idP,frameP,CC_id,rntiP);
-    return NULL;
-  }
-
-}
-
-
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
index 6c7ec35399e2829329c70904ad5028ae3422b7dc..6e426a710ab375ac38c5066fdfd61972711b0865 100644
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
+++ b/openair2/LAYER2/MAC/eNB_scheduler_primitives.c
@@ -59,7 +59,6 @@
 #define ENABLE_MAC_PAYLOAD_DEBUG
 #define DEBUG_eNB_SCHEDULER 1
 
-
 //------------------------------------------------------------------------------
 void init_ue_sched_info(void)
 //------------------------------------------------------------------------------
@@ -261,6 +260,9 @@ void dump_ue_list(UE_list_t *listP, int ul_flag)
   }
 }
 
+
+//---------------------
+
 int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP)
 {
   int UE_id;
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_primitives_nb_iot.c b/openair2/LAYER2/MAC/eNB_scheduler_primitives_nb_iot.c
deleted file mode 100644
index 8c8ac558842cba38413c78f007a1d7603e792f57..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/MAC/eNB_scheduler_primitives_nb_iot.c
+++ /dev/null
@@ -1,137 +0,0 @@
-/*
- * 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.0  (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 eNB_scheduler_primitives.c
- * \brief primitives used by eNB for BCH, RACH, ULSCH, DLSCH scheduling
- * \author  Navid Nikaein and Raymond Knopp
- * \date 2010 - 2014
- * \email: navid.nikaein@eurecom.fr
- * \version 1.0
- * @ingroup _mac
-
- */
-
-#include "assertions.h"
-#include "PHY/defs.h"
-#include "PHY/extern.h"
-
-#include "SCHED/defs.h"
-#include "SCHED/extern.h"
-
-#include "LAYER2/MAC/defs.h"
-#include "LAYER2/MAC/extern.h"
-
-#include "LAYER2/MAC/proto.h"
-#include "UTIL/LOG/log.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-#include "UTIL/OPT/opt.h"
-#include "OCG.h"
-#include "OCG_extern.h"
-
-#include "RRC/LITE/extern.h"
-#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
-//NB-IoT
-#include "defs_nb_iot.h"
-#include "proto_nb_iot.h"
-//#include "LAYER2/MAC/pre_processor.c"
-#include "pdcp.h"
-
-#if defined(ENABLE_ITTI)
-# include "intertask_interface.h"
-#endif
-
-#define ENABLE_MAC_PAYLOAD_DEBUG
-#define DEBUG_eNB_SCHEDULER 1
-
-/*TODO NB_mac_phy_remove_ue*/
-
-
-int NB_rrc_mac_remove_ue(
-		module_id_t mod_idP,
-		rnti_t rntiP)
-{
-  int i;
-  UE_list_NB_t *UE_list = &eNB_mac_inst_NB[mod_idP].UE_list;
-  int UE_id = find_UE_id(mod_idP,rntiP); //may should be changed
-  int pCC_id;
-
-  if (UE_id == -1) {
-printf("MAC: cannot remove UE rnti %x\n", rntiP);
-    LOG_W(MAC,"NB_rrc_mac_remove_ue: UE %x not found\n", rntiP);
-    //NB_mac_phy_remove_ue(mod_idP, rntiP);
-    return 0;
-  }
-
-  pCC_id = UE_PCCID(mod_idP,UE_id);
-
-printf("MAC: remove UE %d rnti %x\n", UE_id, rntiP);
-  LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP);
-  //dump_ue_list(UE_list,0); //may should be changed
-
-  UE_list->active[UE_id] = FALSE;
-  UE_list->num_UEs--;
-
-  // clear all remaining pending transmissions no lcgid in NB-IoT
-  /*UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0]  = 0;
-  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1]  = 0;
-  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2]  = 0;
-  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3]  = 0;*/
-
-  //UE_list->UE_template[pCC_id][UE_id].ul_SR             = 0;
-  UE_list->UE_template[pCC_id][UE_id].rnti              = NOT_A_RNTI;
-  UE_list->UE_template[pCC_id][UE_id].ul_active         = FALSE;
-  eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
-  eNB_ulsch_info[mod_idP][pCC_id][UE_id].status                      = S_UL_NONE;
-  eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
-  eNB_dlsch_info[mod_idP][pCC_id][UE_id].status                      = S_DL_NONE;
-
-  //NB_mac_phy_remove_ue(mod_idP,rntiP);
-
-  // check if this has an RA process active
-  RA_TEMPLATE_NB *RA_template;
-  for (i=0;i<NB_RA_PROC_MAX;i++) {
-    RA_template = (RA_TEMPLATE_NB *)&eNB_mac_inst_NB[mod_idP].common_channels[pCC_id].RA_template[i];
-    if (RA_template->rnti == rntiP){
-      RA_template->RA_active=FALSE;
-      RA_template->generate_rar=0;
-      RA_template->generate_Msg4=0;
-      RA_template->wait_ack_Msg4=0;
-      RA_template->timing_offset=0;
-      RA_template->RRC_timer=20;
-      RA_template->rnti = 0;
-      //break;
-    }
-  }
-
-  return 0;
-}
-
-//------------------------------------------------------------------------------
-DCI_PDU_NB *NB_get_dci_sdu(module_id_t module_idP, int CC_id,frame_t frameP, sub_frame_t subframeP)
-//------------------------------------------------------------------------------
-{
-
-  return(&eNB_mac_inst_NB[module_idP].common_channels[CC_id].DCI_pdu);
-
-}
-
-//NB_UL_failure_indication... some of the used primitive haven't defined
-
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch_NB_IoT.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..21e9a073ba9c0ec4dfab429d3fd274ba5949af61
--- /dev/null
+++ b/openair2/LAYER2/MAC/eNB_scheduler_ulsch_NB_IoT.c
@@ -0,0 +1,562 @@
+
+/*! \file eNB_scheduler_ulsch_NB_IoT.c
+ * \brief handle UL UE-specific scheduling
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "defs_NB_IoT.h"
+#include "proto_NB_IoT.h"
+#include "extern_NB_IoT.h"
+
+
+unsigned char str20[] = "DCI_uss";
+unsigned char str21[] = "DATA_uss";
+
+// scheduling UL
+int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info,uint32_t subframe, uint32_t frame, uint32_t H_SFN){
+
+	int i,ndi = 0,check_DCI_result = 0,check_UL_result = 0,candidate;
+	uint32_t DL_end;
+    //Scheduling resource temp buffer
+    sched_temp_DL_NB_IoT_t *NPDCCH_info = (sched_temp_DL_NB_IoT_t*)malloc(sizeof(sched_temp_DL_NB_IoT_t));
+
+	candidate = UE_info->R_max/UE_info->R_dci;
+    uint32_t mcs = max_mcs[UE_info->multi_tone];
+    uint32_t mappedMcsIndex=UE_info->PHR+(4 * UE_info->multi_tone);
+    int TBS = 0;
+    int Iru = 0, Nru, I_rep,N_rep,total_ru;
+    int dly = 0,uplink_time = 0;
+
+    TBS=get_TBS_UL_NB_IoT(mcs,UE_info->multi_tone,Iru);
+
+    sched_temp_UL_NB_IoT_t *NPUSCH_info = (sched_temp_UL_NB_IoT_t*)malloc(sizeof(sched_temp_UL_NB_IoT_t));
+
+    DCIFormatN0_t *DCI_N0 = (DCIFormatN0_t*)malloc(sizeof(DCIFormatN0_t));
+
+    //available_resource_DL_t *node;
+
+    // setting of the NDI
+    if(UE_info->HARQ_round == 0)
+    {
+        ndi = 1-UE_info->oldNDI_UL;
+        UE_info->oldNDI_UL=ndi;
+    }
+
+    for (i = 0; i < candidate; i++)
+	{
+		/*step 1 : Check DL resource is available for DCI N0 or not*/
+		check_DCI_result = check_resource_NPDCCH_NB_IoT(mac_inst,H_SFN, frame, subframe, NPDCCH_info, i, UE_info->R_dci);
+
+        //node = check_resource_DL(mac_inst,);
+
+        //just use to check when there is no DL function
+        //NPDCCH_info->sf_start = H_SFN*10240+frame*10 +subframe + i * UE_info->R_dci;
+        //NPDCCH_info->sf_end = NPDCCH_info->sf_start + (i+1) * UE_info->R_dci;
+
+        //DEBUG("UE : %5d, NPDCCH result: %d ,NPDCCH start: %d,NPDCCH end : %d\n",UE_info->rnti,check_DCI_result,NPDCCH_info->sf_start,NPDCCH_info->sf_end);
+        if( check_DCI_result != -1)
+		{
+			/*step 2 : Determine MCS / TBS / REP / RU number*/
+            /*while((mapped_mcs[UE_info->CE_level][mappedMcsIndex]< mcs)||((TBS>UE_info->ul_total_buffer)&&(mcs>=0)))
+                {
+                    --mcs;
+                    TBS=get_TBS_UL(mcs,UE_info->multi_tone,Iru);
+                }*/
+
+            mcs = mapped_mcs[UE_info->CE_level][mappedMcsIndex];
+
+            while((TBS<UE_info->ul_total_buffer)&&(Iru<=7))
+                {
+                    Iru++;
+                    TBS=get_TBS_UL_NB_IoT(mcs,UE_info->multi_tone,Iru);
+                }
+
+            //DEBUG("TBS : %d UL_buffer: %d\n", TBS, UE_info->ul_total_buffer);
+
+            Nru = RU_table[Iru];
+            DL_end = NPDCCH_info->sf_end;
+            N_rep = get_N_REP(UE_info->CE_level);
+            I_rep = get_I_REP(N_rep);
+            total_ru = Nru * N_rep;
+
+            printf("[%04d][UL scheduler][UE:%05d] Multi-tone:%d,MCS:%d,TBS:%d,UL_buffer:%d,DL_start:%d,DL_end:%d,N_rep:%d,N_ru:%d,Total_ru:%d\n", mac_inst->current_subframe,UE_info->rnti,UE_info->multi_tone,mcs,TBS,UE_info->ul_total_buffer,NPDCCH_info->sf_start,DL_end,N_rep,Nru,total_ru);
+
+            /*step 3 Check UL resource for Uplink data*/
+			// we will loop the scheduling delay here
+            for(dly=0;dly<4;dly++)
+            {
+                uplink_time = DL_end +scheduling_delay[dly];
+                check_UL_result = Check_UL_resource(uplink_time,total_ru, NPUSCH_info, UE_info->multi_tone, 0);
+                if (check_UL_result != -1)
+                {
+                    // step 4 : generate DCI content
+                    DCI_N0->type = 0;
+                    DCI_N0->scind = NPUSCH_info->subcarrier_indication;
+                    DCI_N0->ResAssign = Iru;
+                    DCI_N0->mcs = mcs;
+                    DCI_N0->ndi = ndi;
+                    DCI_N0->Scheddly = dly;
+                    DCI_N0->RepNum = I_rep;
+                    DCI_N0->rv = (UE_info->HARQ_round%2==0)?0:1; // rv will loop 0 & 2
+                    DCI_N0->DCIRep = get_DCI_REP(UE_info->R_dci,UE_info->R_max);
+
+                printf("[%04d][UL scheduler][UE:%05d] DCI content = scind : %d ResAssign : %d mcs : %d ndi : %d scheddly : %d RepNum : %d rv : %d DCIRep : %d\n", mac_inst->current_subframe,UE_info->rnti,DCI_N0->scind,DCI_N0->ResAssign,DCI_N0->mcs,DCI_N0->ndi,DCI_N0->Scheddly,DCI_N0->RepNum,DCI_N0->rv,DCI_N0->DCIRep);
+                // step 5 resource allocation and generate scheduling result
+                generate_scheduling_result_UL(NPDCCH_info->sf_start, NPDCCH_info->sf_end,NPUSCH_info->sf_start, NPUSCH_info->sf_end,DCI_N0,UE_info->rnti, str20, str21);
+                //fill_resource_DL();
+                maintain_resource_DL(mac_inst,NPDCCH_info,NULL);
+
+                adjust_UL_resource_list(NPUSCH_info);
+
+                return 0;
+                }
+            }
+
+		}
+        /*break now, we only loop one candidiate*/
+        //break;
+	}
+
+	printf("[%04d][UL scheduler][UE:%05d] there is no available UL resource\n", mac_inst->current_subframe, UE_info->rnti);
+	return -1;
+}
+
+int single_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int fmt2_flag)
+{
+    available_resource_UL_t *single_node_tmp;
+    uint32_t uplink_time_end;
+
+    if(fmt2_flag == 0)
+        // 16 * 0.5 (slot) = 8 subframe
+        uplink_time_end = uplink_time + total_ru*8 -1;
+    else
+        // 4 * 0.5 (slot) = 2 subframe
+        uplink_time_end = uplink_time + total_ru*2 -1;
+
+    //check first list of single tone
+    single_node_tmp = available_resource_UL->singletone1_Head;
+
+    while(single_node_tmp!=NULL)
+    {
+        if (uplink_time >= single_node_tmp->start_subframe)
+        {
+            
+            if ( uplink_time_end <= single_node_tmp->end_subframe)
+            {
+                NPUSCH_info->sf_end = uplink_time_end;
+                NPUSCH_info->sf_start = uplink_time;
+                NPUSCH_info->tone = singletone1;
+                NPUSCH_info->subcarrier_indication = 0 ; // Isc when single tone : 0-2
+                NPUSCH_info->node = single_node_tmp;
+                printf("[UL scheduler] Use uplink resource single tone 1, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
+                return 0;
+            }
+        }
+        single_node_tmp = single_node_tmp->next;
+    }
+
+    //check second list of single tone
+    single_node_tmp = available_resource_UL->singletone2_Head;
+
+    while(single_node_tmp!=NULL)
+    {
+        if (uplink_time >= single_node_tmp->start_subframe)
+        {
+            if ( uplink_time_end <= single_node_tmp->end_subframe)
+            {
+                NPUSCH_info->sf_end = uplink_time_end;
+                NPUSCH_info->sf_start = uplink_time;
+                NPUSCH_info->tone = singletone2;
+                NPUSCH_info->subcarrier_indication = 1 ; // Isc when single tone : 0-2
+                NPUSCH_info->node = single_node_tmp;
+                printf("[UL scheduler] Use uplink resource single tone 2, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
+                return 0;
+            }
+        }
+        single_node_tmp = single_node_tmp->next;
+    }
+
+    //check third list of single tone
+    single_node_tmp = available_resource_UL->singletone3_Head;
+
+    while(single_node_tmp!=NULL)
+    {
+        if (uplink_time >= single_node_tmp->start_subframe)
+        {
+            if ( uplink_time_end <= single_node_tmp->end_subframe)
+            {
+                NPUSCH_info->sf_end = uplink_time_end;
+                NPUSCH_info->sf_start = uplink_time;
+                NPUSCH_info->tone = singletone3;
+                NPUSCH_info->subcarrier_indication = 2 ; // Isc when single tone : 0-2
+                NPUSCH_info->node = single_node_tmp;
+                printf("[UL scheduler]Use uplink resource single tone 3, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
+                return 0;
+            }
+        }
+        single_node_tmp = single_node_tmp->next;
+    }
+
+    //DEBUG("[UL scheduler][singletone]no proper resource for this allocation\n");
+    return -1;
+
+}
+
+int multi_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info)
+{
+    available_resource_UL_t *Next_Node;
+    int single_tone_result = -1;
+    uint32_t uplink_time_end;
+    /*This checking order may result in the different of the resource optimization*/
+    /*check 6 tones first*/
+    Next_Node = available_resource_UL->sixtone_Head;
+
+    // 4 * 0.5 (slot) = 2 subframe
+    uplink_time_end = uplink_time + total_ru*2 -1;
+    while(Next_Node!=NULL)
+    {
+        if (uplink_time >= Next_Node->start_subframe)
+        {
+            if ( uplink_time_end <= Next_Node->end_subframe)
+            {
+                NPUSCH_info->sf_end = uplink_time_end;
+                NPUSCH_info->sf_start = uplink_time;
+                NPUSCH_info->tone = sixtone;
+                NPUSCH_info->subcarrier_indication = 17 ; // Isc when 6 tone : 6 - 12
+                NPUSCH_info->node = Next_Node;
+                printf("[UL scheduler] Use uplink resource six tone, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
+                return 0;
+            }
+        }
+        Next_Node = Next_Node->next;
+    }
+
+    /*check 3 tones*/
+    Next_Node = available_resource_UL->threetone_Head;
+    // 8 * 0.5 (slot) = 4 subframe
+    uplink_time_end = uplink_time + total_ru * 4 -1;
+    while(Next_Node!=NULL)
+    {
+        if (uplink_time >= Next_Node->start_subframe)
+        {
+            if ( uplink_time_end <= Next_Node->end_subframe)
+            {
+                NPUSCH_info->sf_end = uplink_time_end;
+                NPUSCH_info->sf_start = uplink_time;
+                NPUSCH_info->tone = threetone;
+                NPUSCH_info->subcarrier_indication = 13 ; // Isc when 3 tone : 3-5
+                NPUSCH_info->node = Next_Node;
+                printf("[UL scheduler] Use uplink resource three tone, sf_start: %d, sf_end: %d\n",NPUSCH_info->sf_start,NPUSCH_info->sf_end);
+                return 0;
+            }
+        }
+        Next_Node = Next_Node->next;
+    }
+
+    /*if there is no multi-tone resource, try to allocate the single tone resource*/
+    single_tone_result = single_tone_ru_allocation(uplink_time,total_ru,NPUSCH_info,0);
+    if(single_tone_result == 0)
+        return 0;
+
+    //DEBUG("[UL scheduler][multi_tone]there is no available UL resource !\n");
+    return -1;
+}
+
+int Check_UL_resource(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int multi_tone, int fmt2_flag)
+{
+
+    int result =-1;
+    if(fmt2_flag ==0)
+    {
+        if(multi_tone == 1)
+            result = multi_tone_ru_allocation(uplink_time, total_ru, NPUSCH_info);
+        else if(multi_tone == 0)
+           result = single_tone_ru_allocation(uplink_time, total_ru, NPUSCH_info,0);
+
+    }else if (fmt2_flag == 1)
+        {
+            result = single_tone_ru_allocation(uplink_time, total_ru, NPUSCH_info, 1);
+            printf("harq result %d, time:%d total ru:%d\n", result, uplink_time, total_ru);
+            //if(result == 0)
+                    //NPUSCH_info->ACK_NACK_resource_field = get_resource_field_value(NPUSCH_info->subcarrier_indication,ack_nack_delay[i]);
+                    //DEBUG("[UL scheduler] There is available resource for ACK / NACK\n");
+        }
+    if(result == 0)
+    {
+        return 0;
+    }
+    //DEBUG("[UL scheduler] no available UL resource\n");
+    return -1;
+}
+
+
+void generate_scheduling_result_UL(int32_t DCI_subframe, int32_t DCI_end_subframe, uint32_t UL_subframe, uint32_t UL_end_subframe, DCIFormatN0_t *DCI_pdu, rnti_t rnti, uint8_t *ul_debug_str, uint8_t *dl_debug_str){
+
+    // create the schedule result node for this time transmission
+    schedule_result_t *UL_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+    schedule_result_t *DL_result;
+    schedule_result_t *tmp1, *tmp;
+
+	UL_result->direction = UL;
+    UL_result->output_subframe = UL_subframe;
+	UL_result->end_subframe = UL_end_subframe;
+    UL_result->DCI_pdu = DCI_pdu;
+    UL_result->npusch_format = 0;
+    UL_result->DCI_release = 1;
+    UL_result->channel = NPUSCH;
+    UL_result->rnti = rnti;
+    UL_result->next = NULL;
+	UL_result->debug_str = ul_debug_str;
+	
+    if(-1 == DCI_subframe){
+        printf("[UL scheduler][UE:%05d] UL_result = output subframe : %d\n", rnti, UL_result->output_subframe);
+
+    }else{
+        DL_result = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+
+        DL_result->output_subframe = DCI_subframe;
+        DL_result->end_subframe = DCI_end_subframe;
+		DL_result->DCI_pdu = DCI_pdu;
+        DL_result->DCI_release = 0;
+        DL_result->direction = UL;
+        DL_result->channel = NPDCCH;
+        DL_result->rnti = rnti;
+        DL_result->next = NULL;
+		DL_result->debug_str = dl_debug_str;
+		
+	insert_schedule_result(&schedule_result_list_DL, DCI_subframe, DL_result);
+        
+        printf("[UL scheduler][UE:%05d] DL_result = output subframe : %d UL_result = output subframe : %d\n", rnti, DL_result->output_subframe,UL_result->output_subframe);
+    }
+
+    tmp1 = NULL;
+
+    // be the first node of UL
+    if(schedule_result_list_UL == NULL)
+    {
+        //schedule_result_list_UL = (schedule_result_t*)malloc(sizeof(schedule_result_t));
+        schedule_result_list_UL = UL_result;
+    }else
+    {
+        tmp = schedule_result_list_UL;
+				while(tmp!=NULL)
+				{
+					if(UL_subframe < tmp->output_subframe)
+					{
+						break;
+					}
+					tmp1 = tmp;
+					tmp = tmp->next;
+				}
+				if(tmp==NULL)
+				{
+					tmp1->next = UL_result;
+				}
+				else
+				{
+					UL_result->next = tmp;
+					if(tmp1){
+						tmp1->next = UL_result;
+					}else{
+						schedule_result_list_UL = UL_result;
+					}
+				}
+    }
+
+}
+
+void adjust_UL_resource_list(sched_temp_UL_NB_IoT_t *NPUSCH_info)
+{
+	available_resource_UL_t *temp;
+	available_resource_UL_t *node = NPUSCH_info->node;
+	//	divided into two node
+	//	keep one node(align left or right)
+	//	delete node
+	int align_left = (node->start_subframe==NPUSCH_info->sf_start);
+	int align_right = (node->end_subframe==NPUSCH_info->sf_end);
+
+	switch(align_left+align_right){
+		case 0:
+			//	divided into two node
+			temp = (available_resource_UL_t *)malloc(sizeof(available_resource_UL_t));
+
+			temp->next = node->next;
+			node->next = temp;
+
+			temp->start_subframe = NPUSCH_info->sf_end +1;
+			temp->end_subframe = node->end_subframe;
+
+			node->end_subframe = NPUSCH_info->sf_start - 1;
+
+			break;
+		case 1:
+			//	keep one node
+			if(align_left){
+				node->start_subframe = NPUSCH_info->sf_end +1;
+			}else{
+				node->end_subframe = NPUSCH_info->sf_start - 1 ;
+			}
+			break;
+		case 2:
+			//	delete
+			node->prev->next = node->next;
+			node->next->prev = node->prev;
+			free(node);
+			break;
+		default:
+			//error
+			break;
+	}
+
+//	free(NPUSCH_info);
+}
+
+uint8_t *parse_ulsch_header_NB_IoT( uint8_t *mac_header,
+                             uint8_t *num_ce,
+                             uint8_t *num_sdu,
+                             uint8_t *rx_ces,
+                             uint8_t *rx_lcids,
+                             uint16_t *rx_lengths,
+                             uint16_t tb_length ){
+
+uint8_t not_done=1, num_ces=0, num_sdus=0, lcid,num_sdu_cnt;
+uint8_t *mac_header_ptr = mac_header;
+uint16_t length, ce_len=0;
+
+  while(not_done==1){
+
+    if(((SCH_SUBHEADER_FIXED_NB_IoT*)mac_header_ptr)->E == 0){
+      not_done = 0;
+    }
+
+    lcid = ((SCH_SUBHEADER_FIXED_NB_IoT*)mac_header_ptr)->LCID;
+
+    if(lcid < EXTENDED_POWER_HEADROOM){
+      if (not_done==0) { // last MAC SDU, length is implicit
+        mac_header_ptr++;
+        length = tb_length-(mac_header_ptr-mac_header)-ce_len;
+
+        for(num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++){
+          length -= rx_lengths[num_sdu_cnt];
+        }
+      }else{
+        if(((SCH_SUBHEADER_SHORT_NB_IoT *)mac_header_ptr)->F == 0){
+          length = ((SCH_SUBHEADER_SHORT_NB_IoT *)mac_header_ptr)->L;
+          mac_header_ptr += 2;//sizeof(SCH_SUBHEADER_SHORT);
+        }else{ // F = 1
+          length = ((((SCH_SUBHEADER_LONG_NB_IoT *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG_NB_IoT *)mac_header_ptr)->L_LSB & 0xff);
+          mac_header_ptr += 3;//sizeof(SCH_SUBHEADER_LONG);
+        }
+      }
+
+      rx_lcids[num_sdus] = lcid;
+      rx_lengths[num_sdus] = length;
+      num_sdus++;
+    }else{ // This is a control element subheader POWER_HEADROOM, BSR and CRNTI
+      if(lcid == SHORT_PADDING){
+        mac_header_ptr++;
+      }else{
+        rx_ces[num_ces] = lcid;
+        num_ces++;
+        mac_header_ptr++;
+
+        if(lcid==LONG_BSR){
+          ce_len+=3;
+        }else if(lcid==CRNTI){
+          ce_len+=2;
+        }else if((lcid==POWER_HEADROOM) || (lcid==TRUNCATED_BSR)|| (lcid== SHORT_BSR)) {
+          ce_len++;
+        }else{
+          // wrong lcid
+        }
+      }
+    }
+  }
+
+  *num_ce = num_ces;
+  *num_sdu = num_sdus;
+
+  return(mac_header_ptr);
+}
+
+
+void rx_sdu_NB_IoT(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t subframe, uint16_t rnti, uint8_t *sdu, uint16_t  length)
+{
+    unsigned char  rx_ces[5], num_ce = 0, num_sdu = 0, *payload_ptr, i; // MAX Control element
+    unsigned char  rx_lcids[5];//for NB_IoT-IoT, NB_IoT_RB_MAX should be fixed to 5 (2 DRB+ 3SRB) 
+  unsigned short rx_lengths[5];
+  //int UE_id = 0;
+  int BSR_index=0;
+  int DVI_index = 0;
+  int PHR = 0;
+  int ul_total_buffer = 0;
+  //mac_NB_IoT_t *mac_inst;
+  UE_TEMPLATE_NB_IoT *UE_info;
+
+  //mac_inst = get_mac_inst(module_id);
+
+  // note: if lcid < 25 this is sdu, otherwise this is CE
+  payload_ptr = parse_ulsch_header_NB_IoT(sdu, &num_ce, &num_sdu,rx_ces, rx_lcids, rx_lengths, length);
+
+  //printf("num_CE= %d, num_sdu= %d, rx_ces[0] = %d, rx_lcids =  %d, rx_lengths[0] = %d, length = %d\n",num_ce,num_sdu,rx_ces[0],rx_lcids[0],rx_lengths[0],length);
+
+  for (i = 0; i < num_ce; i++)
+  {
+    switch(rx_ces[i])
+    {
+        case CRNTI:
+          // find UE id again, confirm the UE, intial some ue specific parameters
+          payload_ptr+=2;
+            break;
+        case SHORT_BSR:
+            // update BSR here
+        UE_info = get_ue_from_rnti(mac_inst, rnti);
+        BSR_index = payload_ptr[0] & 0x3f;
+        UE_info->ul_total_buffer = BSR_table[BSR_index];
+            payload_ptr+=1;
+            break;
+        default:
+        printf("Received unknown MAC header (0x%02x)\n", rx_ces[i]);
+                break;
+        }
+    }
+    for (i = 0; i < num_sdu; i++)
+    {
+        switch(rx_lcids[i])
+        {
+            case CCCH_NB_IoT:
+                
+                // MSG3 content: |R|R|PHR|PHR|DVI|DVI|DVI|DVI|CCCH payload
+                PHR = ((payload_ptr[0] >> 5) & 0x01)*2+((payload_ptr[0]>>4) & 0x01);
+                DVI_index = (payload_ptr[0] >>3 & 0x01)*8+ (payload_ptr[0] >>2 & 0x01)*4 + (payload_ptr[0] >>1 & 0x01)*2 +(payload_ptr[0] >>0 & 0x01);
+          //printf("DVI_index= %d\n",DVI_index);
+                ul_total_buffer = DV_table[DVI_index];
+                printf("PHR = %d, ul_total_buffer = %d\n",PHR,ul_total_buffer);
+                // go to payload
+                payload_ptr+=1; 
+                rx_lengths[i]-=1;
+                printf("rx_lengths : %d\n", rx_lengths[i]);
+                //NB_IoT_mac_rrc_data_ind(payload_ptr,mac_inst,rnti);
+                //NB_IoT_receive_msg3(mac_inst,rnti,PHR,ul_total_buffer);
+          break;
+            case DCCH0_NB_IoT:
+            case DCCH1_NB_IoT:
+                // UE specific here
+                //NB_IoT_mac_rlc_data_ind(payload_ptr,mac_inst,rnti);
+            
+          break;
+            // all the DRBS
+            case DTCH0_NB_IoT:
+            default:
+                //NB_IoT_mac_rlc_data_ind(payload_ptr,mac_inst,rnti);
+          break;
+        }
+        payload_ptr+=rx_lengths[i];
+    }
+
+   
+}
\ No newline at end of file
diff --git a/openair2/LAYER2/MAC/eNB_scheduler_ulsch_nb_iot.c b/openair2/LAYER2/MAC/eNB_scheduler_ulsch_nb_iot.c
deleted file mode 100644
index 48bbf7bb79d3563ccd6a70fd92559a68b1c36b8b..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/MAC/eNB_scheduler_ulsch_nb_iot.c
+++ /dev/null
@@ -1,428 +0,0 @@
-/*
- * 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.0  (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 eNB_scheduler_ulsch.c
- * \brief eNB procedures for the ULSCH transport channel
- * \author Navid Nikaein and Raymond Knopp
- * \date 2010 - 2014
- * \email: navid.nikaein@eurecom.fr
- * \version 1.0
- * @ingroup _mac
-
- */
-
-#include "assertions.h"
-#include "PHY/defs.h"
-#include "PHY/extern.h"
-
-#include "SCHED/defs.h"
-#include "SCHED/extern.h"
-
-//#include "LAYER2/MAC/defs.h"
-#include "LAYER2/MAC/proto.h"
-#include "LAYER2/MAC/extern.h"
-#include "UTIL/LOG/log.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-#include "UTIL/OPT/opt.h"
-#include "OCG.h"
-#include "OCG_extern.h"
-
-#include "RRC/LITE/extern.h"
-#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
-//NB-IoT
-#include "LAYER2/MAC/defs_nb_iot.h"
-#include "LAYER2/MAC/proto_nb_iot.h"
-
-
-//#include "LAYER2/MAC/pre_processor.c"
-#include "pdcp.h"
-
-#if defined(ENABLE_ITTI)
-# include "intertask_interface.h"
-#endif
-
-#include "T.h"
-
-#define ENABLE_MAC_PAYLOAD_DEBUG
-#define DEBUG_eNB_SCHEDULER 1
-
-// This table holds the allowable PRB sizes for ULSCH transmissions
-uint8_t rb_table[33] = {1,2,3,4,5,6,8,9,10,12,15,16,18,20,24,25,27,30,32,36,40,45,48,50,54,60,72,75,80,81,90,96,100};
-
-
-
-void NB_rx_sdu(const module_id_t enb_mod_idP,
-	    const int         CC_idP,
-	    const frame_t     frameP,
-	    const sub_frame_t subframeP,
-	    const rnti_t      rntiP,
-	    uint8_t          *sduP,
-	    const uint16_t    sdu_lenP,
-	    const int         harq_pidP,
-	    uint8_t          *msg3_flagP)
-{
-
-  unsigned char  rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
-  unsigned char  rx_lcids[NB_RB_MAX];//for NB-IoT, NB_RB_MAX should be fixed to 5 (2 DRB+ 3SRB) 
-  unsigned short rx_lengths[NB_RB_MAX];
-  int    UE_id = find_UE_id(enb_mod_idP,rntiP);
-  int ii,j;
-  eNB_MAC_INST_NB *eNB = &eNB_mac_inst_NB[enb_mod_idP];
-  UE_list_NB_t *UE_list= &eNB->UE_list;
-  int crnti_rx=0;
-  //int old_buffer_info;
-
-  start_meas(&eNB->rx_ulsch_sdu);
-
-  /*if there is an error for UE_id> max or UE_id==-1, set rx_lengths to 0*/
-  if ((UE_id >  NUMBER_OF_UE_MAX) || (UE_id == -1)  )
-    for(ii=0; ii<NB_RB_MAX; ii++) {
-      rx_lengths[ii] = 0;
-    }
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,1);
-  if (opt_enabled == 1) {
-    trace_pdu(0, sduP,sdu_lenP, 0, 3, rntiP, frameP, subframeP, 0,0);
-    LOG_D(OPT,"[eNB %d][ULSCH] Frame %d  rnti %x  with size %d\n",
-    		  enb_mod_idP, frameP, rntiP, sdu_lenP);
-  }
-
-  LOG_D(MAC,"[eNB %d] CC_id %d Received ULSCH sdu from PHY (rnti %x, UE_id %d), parsing header\n",enb_mod_idP,CC_idP,rntiP,UE_id);
-
-  if (sduP==NULL) { // we've got an error after N rounds
-    UE_list->UE_sched_ctrl[UE_id].ul_scheduled       &= (~(1<<harq_pidP)); //ul_scheduled: A kind of resource scheduling information
-    return;
-  }
-
-  if (UE_id!=-1) {
-    UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer=0;
-    UE_list->UE_sched_ctrl[UE_id].ul_failure_timer   =0;
-    UE_list->UE_sched_ctrl[UE_id].ul_scheduled       &= (~(1<<harq_pidP));
-    /*RLF procedure this part just check UE context is NULL or not, if not, means UL in synch*/
-    if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
-      UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=0;
-      NB_mac_eNB_rrc_ul_in_sync(enb_mod_idP,CC_idP,frameP,subframeP,UE_RNTI(enb_mod_idP,UE_id));
-    }
-  }
-
-
-  payload_ptr = parse_ulsch_header(sduP,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_lenP);
-
-  T(T_ENB_MAC_UE_UL_PDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
-    T_INT(harq_pidP), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu));
-  T(T_ENB_MAC_UE_UL_PDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
-    T_INT(harq_pidP), T_INT(sdu_lenP), T_INT(num_ce), T_INT(num_sdu), T_BUFFER(sduP, sdu_lenP));
-
-  eNB->eNB_stats[CC_idP].ulsch_bytes_rx=sdu_lenP;
-  eNB->eNB_stats[CC_idP].total_ulsch_bytes_rx+=sdu_lenP;
-  eNB->eNB_stats[CC_idP].total_ulsch_pdus_rx+=1;
-  // control element
-  for (i=0; i<num_ce; i++) {
-
-    T(T_ENB_MAC_UE_UL_CE, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
-      T_INT(rx_ces[i]));
-    /*rx_ces = lcid in parse_ulsch_header() if not short padding*/
-    switch (rx_ces[i]) { // implement and process BSR + CRNTI + PHR
-    case POWER_HEADROOM:
-      if (UE_id != -1) {
-        UE_list->UE_template[CC_idP][UE_id].phr_info =  (payload_ptr[0] & 0x3f) - PHR_MAPPING_OFFSET;
-        LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received PHR PH = %d (db)\n",
-              enb_mod_idP, CC_idP, rx_ces[i], UE_list->UE_template[CC_idP][UE_id].phr_info);
-        UE_list->UE_template[CC_idP][UE_id].phr_info_configured=1;
-	UE_list->UE_sched_ctrl[UE_id].phr_received = 1;
-      }
-      payload_ptr+=sizeof(POWER_HEADROOM_CMD);
-      break;
-
-    case CRNTI:
-      UE_id = find_UE_id(enb_mod_idP,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]);
-      LOG_I(MAC, "[eNB %d] Frame %d, Subframe %d CC_id %d MAC CE_LCID %d (ce %d/%d): CRNTI %x (UE_id %d) in Msg3\n",
-	    frameP,subframeP,enb_mod_idP, CC_idP, rx_ces[i], i,num_ce,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1],UE_id);
-      if (UE_id!=-1) {
-	UE_list->UE_sched_ctrl[UE_id].ul_inactivity_timer=0;
-	UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=0;
-	if (UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync > 0) {
-	  UE_list->UE_sched_ctrl[UE_id].ul_out_of_sync=0;
-	  /*In RRC branch*/
-    //NB_mac_eNB_rrc_ul_in_sync(enb_mod_idP,CC_idP,frameP,subframeP,(((uint16_t)payload_ptr[0])<<8) + payload_ptr[1]);
-	}
-      }
-      crnti_rx=1;
-      payload_ptr+=2;
-
-      if (msg3_flagP != NULL) {
-		*msg3_flagP = 0;
-    
-      break;
-    /*For this moment, long bsr is not processed in the case*/
-    //case TRUNCATED_BSR:
-    /*DV lcid =???*/
-    //case DATA_VOLUME_INDICATOR
-    case SHORT_BSR: {
-      uint8_t lcgid;
-      lcgid = (payload_ptr[0] >> 6);
-
-      LOG_D(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n",
-	    enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f);
-
-      if (crnti_rx==1)
-	LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : Received short BSR LCGID = %u bsr = %d\n",
-	      enb_mod_idP, CC_idP, rx_ces[i], lcgid, payload_ptr[0] & 0x3f);
-      if (UE_id  != -1) {
-
-        UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid] = (payload_ptr[0] & 0x3f);
-
-	// update buffer info
-	
-	UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]=BSR_TABLE[UE_list->UE_template[CC_idP][UE_id].bsr_info[lcgid]];
-
-	UE_list->UE_template[CC_idP][UE_id].ul_total_buffer= UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid];
-
-	PHY_vars_eNB_g[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP*10)+subframeP] = (payload_ptr[0] & 0x3f);
-	if (UE_id == UE_list->head)
-	  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE0_BSR,PHY_vars_eNB_g[enb_mod_idP][CC_idP]->pusch_stats_bsr[UE_id][(frameP*10)+subframeP]);	
-        if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid] == 0 ) {
-          UE_list->UE_template[CC_idP][UE_id].ul_buffer_creation_time[lcgid]=frameP;
-        }
-	if (mac_eNB_get_rrc_status(enb_mod_idP,UE_RNTI(enb_mod_idP,UE_id)) < RRC_CONNECTED)
-	  LOG_I(MAC, "[eNB %d] CC_id %d MAC CE_LCID %d : ul_total_buffer = %d (lcg increment %d)\n",
-		enb_mod_idP, CC_idP, rx_ces[i], UE_list->UE_template[CC_idP][UE_id].ul_total_buffer,
-		UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[lcgid]);	
-      }
-      else {
-
-      }
-      payload_ptr += 1;//sizeof(SHORT_BSR); // fixme
-    }
-    break;
-
-	
-
-    default:
-      LOG_E(MAC, "[eNB %d] CC_id %d Received unknown MAC header (0x%02x)\n", enb_mod_idP, CC_idP, rx_ces[i]);
-      break;
-    }
-  }
-
-  for (i=0; i<num_sdu; i++) {
-    LOG_D(MAC,"SDU Number %d MAC Subheader SDU_LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
-
-    T(T_ENB_MAC_UE_UL_SDU, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
-      T_INT(rx_lcids[i]), T_INT(rx_lengths[i]));
-    T(T_ENB_MAC_UE_UL_SDU_WITH_DATA, T_INT(enb_mod_idP), T_INT(CC_idP), T_INT(rntiP), T_INT(frameP), T_INT(subframeP),
-      T_INT(rx_lcids[i]), T_INT(rx_lengths[i]), T_BUFFER(payload_ptr, rx_lengths[i]));
-
-    switch (rx_lcids[i]) {
-    case CCCH :
-      if (rx_lengths[i] > CCCH_PAYLOAD_SIZE_MAX) {
-        LOG_E(MAC, "[eNB %d/%d] frame %d received CCCH of size %d (too big, maximum allowed is %d), dropping packet\n",
-              enb_mod_idP, CC_idP, frameP, rx_lengths[i], CCCH_PAYLOAD_SIZE_MAX);
-        break;
-      }
-      LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, Received CCCH:  %x.%x.%x.%x.%x.%x, Terminating RA procedure for UE rnti %x\n",
-            enb_mod_idP,CC_idP,frameP,
-            payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4], payload_ptr[5], rntiP);
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC,1);
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_TERMINATE_RA_PROC,0);
-      for (ii=0; ii<NB_RA_PROC_MAX; ii++) {
-        LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Checking proc %d : rnti (%x, %x), active %d\n",
-              enb_mod_idP, CC_idP, ii,
-              eNB->common_channels[CC_idP].RA_template[ii].rnti, rntiP,
-              eNB->common_channels[CC_idP].RA_template[ii].RA_active);
-
-        if ((eNB->common_channels[CC_idP].RA_template[ii].rnti==rntiP) &&
-            (eNB->common_channels[CC_idP].RA_template[ii].RA_active==TRUE)) {
-
-          //payload_ptr = parse_ulsch_header(msg3,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,msg3_len);
-
-          if (UE_id < 0) {
-            memcpy(&eNB->common_channels[CC_idP].RA_template[ii].cont_res_id[0],payload_ptr,6);
-            LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3: length %d, offset %ld\n",
-                  enb_mod_idP,CC_idP,frameP,rx_lengths[i],payload_ptr-sduP);
-
-            if ((UE_id=add_new_ue(enb_mod_idP,CC_idP,eNB->common_channels[CC_idP].RA_template[ii].rnti,harq_pidP)) == -1 ) {
-              mac_xface->macphy_exit("[MAC][eNB] Max user count reached\n");
-	      // kill RA procedure
-            } else
-              LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Added user with rnti %x => UE %d\n",
-                    enb_mod_idP,CC_idP,frameP,eNB->common_channels[CC_idP].RA_template[ii].rnti,UE_id);
-          } else {
-            LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d CCCH: Received Msg3 from already registered UE %d: length %d, offset %ld\n",
-                  enb_mod_idP,CC_idP,frameP,UE_id,rx_lengths[i],payload_ptr-sduP);
-	    // kill RA procedure
-          }
-
-          if (Is_rrc_registered == 1)
-            /* In RRC branch
-            NB_mac_rrc_data_ind(
-              enb_mod_idP,
-              CC_idP,
-              frameP,subframeP,
-              rntiP,
-              CCCH,
-              (uint8_t*)payload_ptr,
-              rx_lengths[i],
-              ENB_FLAG_YES,
-              enb_mod_idP,
-              0);*/
-
-
-          if (num_ce >0) {  // handle msg3 which is not RRCConnectionRequest
-            //  process_ra_message(msg3,num_ce,rx_lcids,rx_ces);
-          }
-
-          eNB->common_channels[CC_idP].RA_template[ii].generate_Msg4 = 1;
-          eNB->common_channels[CC_idP].RA_template[ii].wait_ack_Msg4 = 0;
-
-        } // if process is active
-      } // loop on RA processes
-      
-      break ;
-    /*DCCH0 is for SRB1bis, DCCH1 is for SRB1*/
-    case DCCH0 :
-    case DCCH1 :
-      //      if(eNB_mac_inst[module_idP][CC_idP].Dcch_lchan[UE_id].Active==1){
-      
-
-#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
-      LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP));
-      for (j=0; j<32; j++) {
-        LOG_T(MAC,"%x ",payload_ptr[j]);
-      }
-      LOG_T(MAC,"\n");
-#endif
-
-      if (UE_id != -1) {
-
-		/*NO lcg in NB-IoT, anyway set to 0*/
-	// adjust buffer occupancy of the correponding logical channel group
-	/*if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i])
-	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i];
-	else
-	  UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0;*/
-
-          LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DCCH, received %d bytes form UE %d on LCID %d \n",
-                enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]);
-
-		  /*TODO*/
-          /*mac_rlc_data_ind(
-			   enb_mod_idP,
-			   rntiP,
-			   enb_mod_idP,
-			   frameP,
-			   ENB_FLAG_YES,
-			   MBMS_FLAG_NO,
-			   rx_lcids[i],
-			   (char *)payload_ptr,
-			   rx_lengths[i],
-			   1,
-			   NULL);//(unsigned int*)crc_status);*/
-          UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1;
-          UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i];
-      } /* UE_id != -1 */
- 
-      // } 
-      break;
-
-      // all the DRBS
-    case DTCH0:
-    default :
-
-#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
-      LOG_T(MAC,"offset: %d\n",(unsigned char)((unsigned char*)payload_ptr-sduP));
-      for (j=0; j<32; j++) {
-        LOG_T(MAC,"%x ",payload_ptr[j]);
-      }
-      LOG_T(MAC,"\n");
-#endif
-      if (rx_lcids[i]  < NB_RB_MAX ) {
-	LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n",
-	      enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id, rx_lcids[i]);
-	
-	if (UE_id != -1) {
-	  // adjust buffer occupancy of the correponding logical channel group
-	  LOG_D(MAC,"[eNB %d] CC_id %d Frame %d : ULSCH -> UL-DTCH, received %d bytes from UE %d for lcid %d\n",
-		enb_mod_idP,CC_idP,frameP, rx_lengths[i], UE_id,rx_lcids[i]);
-	  
-	  /*if (UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] >= rx_lengths[i])
-	    UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] -= rx_lengths[i];
-	  else
-	    UE_list->UE_template[CC_idP][UE_id].ul_buffer_info[UE_list->UE_template[CC_idP][UE_id].lcgidmap[rx_lcids[i]]] = 0;*/
-	  if ((rx_lengths[i] <SCH_PAYLOAD_SIZE_MAX) &&  (rx_lengths[i] > 0) ) {   // MAX SIZE OF transport block
-	    /*mac_rlc_data_ind(
-			     enb_mod_idP,
-			     rntiP,
-			     enb_mod_idP,
-			     frameP,
-			     ENB_FLAG_YES,
-			     MBMS_FLAG_NO,
-			     rx_lcids[i],
-			     (char *)payload_ptr,
-			     rx_lengths[i],
-			     1,
-			     NULL);//(unsigned int*)crc_status);*/
-	    
-	    UE_list->eNB_UE_stats[CC_idP][UE_id].num_pdu_rx[rx_lcids[i]]+=1;
-	    UE_list->eNB_UE_stats[CC_idP][UE_id].num_bytes_rx[rx_lcids[i]]+=rx_lengths[i];
-	  }
-	  else { /* rx_length[i] */
-	    UE_list->eNB_UE_stats[CC_idP][UE_id].num_errors_rx+=1;
-	    LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : Max size of transport block reached LCID %d from UE %d ",
-		  enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id);
-	  }
-	}    
-	else {/*(UE_id != -1*/ 
-	  LOG_E(MAC,"[eNB %d] CC_id %d Frame %d : received unsupported or unknown LCID %d from UE %d ",
-		enb_mod_idP, CC_idP, frameP, rx_lcids[i], UE_id);
-	}
-      }
-
-      break;
-    }
-  
-    payload_ptr+=rx_lengths[i];
-  }
-
-  /* NN--> FK: we could either check the payload, or use a phy helper to detect a false msg3 */
-  if ((num_sdu == 0) && (num_ce==0)) {
-    if (UE_id != -1)
-      UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_errors_rx+=1;
-
-    if (msg3_flagP != NULL) {
-      if( *msg3_flagP == 1 ) {
-        LOG_N(MAC,"[eNB %d] CC_id %d frame %d : false msg3 detection: signal phy to canceling RA and remove the UE\n", enb_mod_idP, CC_idP, frameP);
-        *msg3_flagP=0;
-      }
-    }
-  } else {
-    if (UE_id != -1) {
-      UE_list->eNB_UE_stats[CC_idP][UE_id].pdu_bytes_rx=sdu_lenP;
-      UE_list->eNB_UE_stats[CC_idP][UE_id].total_pdu_bytes_rx+=sdu_lenP;
-      UE_list->eNB_UE_stats[CC_idP][UE_id].total_num_pdus_rx+=1;
-    }
-  }
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_SDU,0);
-  stop_meas(&eNB->rx_ulsch_sdu);
-}
-}
-\
-
diff --git a/openair2/LAYER2/MAC/extern.h b/openair2/LAYER2/MAC/extern.h
index 14276a02a28f7e89943e8e161111693d477e1ce8..02346ba20372913bb00d5f433192b76894c6e84d 100644
--- a/openair2/LAYER2/MAC/extern.h
+++ b/openair2/LAYER2/MAC/extern.h
@@ -38,14 +38,12 @@
 #endif //USER_MODE
 #include "PHY/defs.h"
 #include "defs.h"
-#include "defs_nb_iot.h"
 #include "COMMON/mac_rrc_primitives.h"
 #ifdef PHY_EMUL
 //#include "SIMULATION/simulation_defs.h"
 #endif //PHY_EMUL
 #include "PHY_INTERFACE/defs.h"
 #include "RRC/LITE/defs.h"
-#include "defs_nb_iot.h"
 
 extern const uint32_t BSR_TABLE[BSR_TABLE_SIZE];
 //extern uint32_t EBSR_Level[63];
@@ -66,8 +64,6 @@ extern UE_MAC_INST *ue_mac_inst;
 extern MAC_RLC_XFACE *Mac_rlc_xface;
 extern uint8_t Is_rrc_registered;
 
-//NB-IoT
-extern eNB_MAC_INST_NB *eNB_mac_inst_NB;
 
 extern eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8
 extern eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8
@@ -124,6 +120,7 @@ extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu1;
 extern DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2;
 extern DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E;
 
+
 #endif //DEF_H
 
 
diff --git a/openair2/LAYER2/MAC/extern_NB_IoT.h b/openair2/LAYER2/MAC/extern_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..eb2116835a5c213340c76c1621e1fe9a70d3e73d
--- /dev/null
+++ b/openair2/LAYER2/MAC/extern_NB_IoT.h
@@ -0,0 +1,133 @@
+
+/*! \file extern_NB_IoT.h
+ * \brief MAC extern
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#ifndef __MAC_EXTERN_NB_IOT_H__
+#define __MAC_EXTERN_NB_IOT_H__
+
+
+// #ifdef USER_MODE
+// //#include "stdio.h"
+// #endif //USER_MODE
+// #include "PHY/defs.h"
+// #include "defs.h"
+// #include "COMMON/mac_rrc_primitives.h"
+// #ifdef PHY_EMUL
+// //#include "SIMULATION/simulation_defs.h"
+// #endif //PHY_EMUL
+#include "openair2/PHY_INTERFACE/defs_NB_IoT.h" 
+//#include "RRC/LITE/defs_NB_IoT.h"
+
+//#include "LAYER2/MAC/vars_NB_IoT.h"
+
+//NB-IoT
+extern IF_Module_t *if_inst;
+extern eNB_MAC_INST_NB_IoT *mac_inst;
+
+// //extern uint32_t EBSR_Level[63];
+// extern const uint32_t Extended_BSR_TABLE[BSR_TABLE_SIZE];
+// //extern uint32_t Extended_BSR_TABLE[63];  ----currently not used 
+
+// extern const uint8_t cqi2fmt0_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE];
+
+// extern const uint8_t cqi2fmt1x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE];
+
+// extern const uint8_t cqi2fmt2x_agg[MAX_SUPPORTED_BW][CQI_VALUE_RANGE];
+
+// extern UE_MAC_INST *UE_mac_inst;
+// extern eNB_MAC_INST *eNB_mac_inst;
+// extern eNB_RRC_INST *eNB_rrc_inst;
+//extern UE_RRC_INST_NB_IoT *UE_rrc_inst_NB_IoT;
+// extern UE_MAC_INST *ue_mac_inst;
+// extern MAC_RLC_XFACE *Mac_rlc_xface;
+// extern uint8_t Is_rrc_registered;
+
+
+//#ifndef USER_MODE
+
+// extern RRC_XFACE *Rrc_xface;          //// to uncomment when it is used
+
+extern uint8_t Is_rrc_registered;
+
+#ifndef PHY_EMUL
+#ifndef PHYSIM
+#define NB_INST 1
+#else
+extern unsigned char NB_INST;
+#endif
+extern unsigned char NB_eNB_INST;
+extern unsigned char NB_UE_INST;
+extern unsigned char NB_RN_INST;
+extern unsigned short NODE_ID[1];
+extern void* bigphys_malloc(int);
+#else
+extern EMULATION_VARS *Emul_vars;
+#endif //PHY_EMUL
+
+
+
+
+//NB-IoT---------------------------------
+
+extern eNB_MAC_INST_NB_IoT *mac_inst;
+extern uint8_t Is_rrc_registered_NB_IoT;
+//extern BCCH_BCH_Message_NB_t               MIB;
+//extern BCCH_DL_SCH_Message_NB_t            SIB;
+//extern RRCConnectionSetup_NB_r13_IEs_t     DED_Config;
+
+extern available_resource_DL_t *available_resource_DL;
+extern available_resource_tones_UL_t *available_resource_UL;
+extern available_resource_DL_t *available_resource_DL_last;
+extern schedule_result_t *schedule_result_list_UL;
+extern schedule_result_t *schedule_result_list_DL;
+
+// array will be active when they are used
+
+// 10 -> single-tone / 12 -> multi-tone
+extern const uint32_t max_mcs[2];
+
+// [CE level] [0 - 3] -> single-tone / [CE level] [4-7] -> multi-tone
+extern const uint32_t mapped_mcs[3][8];
+
+//TBS table for NPUSCH transmission TS 36.213 v14.2 table Table 16.5.1.2-2:
+extern const int UL_TBS_Table[14][8];
+
+extern const int rachperiod[8];
+extern const int rachstart[8];
+extern const int rachrepeat[8];
+extern const int rachscofst[7];
+extern const int rachnumsc[4];
+
+extern const uint32_t RU_table[8];
+
+extern const uint32_t scheduling_delay[4];
+extern const uint32_t msg3_scheduling_delay_table[4];
+
+extern const uint32_t ack_nack_delay[4];
+extern const uint32_t R_dl_table[16];
+
+// TBS table for the case not containing SIB1-NB_IoT, Table 16.4.1.5.1-1 in TS 36.213 v14.2
+extern const uint32_t MAC_TBStable_NB_IoT[14][8];
+
+//TBS table for the case containing S1B1-NB_IoT, Table 16.4.1.5.2-1 in TS 36.213 v14.2 (Itbs = 12 ~ 15 is reserved field
+//mapping ITBS to SIB1-NB_IoT
+extern const unsigned int MAC_TBStable_NB_IoT_SIB1[16];
+
+extern const int DV_table[16];
+extern const int BSR_table[64];
+
+extern const int dl_rep[3];
+extern const uint32_t dci_rep[3];
+extern const uint32_t harq_rep[3];
+
+
+
+#endif //DEF_H
+
+
diff --git a/openair2/LAYER2/MAC/main.c b/openair2/LAYER2/MAC/main.c
index e04d7c3b8ad14f7b069ca8147be8712399c1bfea..a00408542049d967a5ef64b6e3b1f26a4f9bd1db 100644
--- a/openair2/LAYER2/MAC/main.c
+++ b/openair2/LAYER2/MAC/main.c
@@ -399,8 +399,12 @@ int mac_init_global_param(void)
   //  Mac_rlc_xface->mrbch_phy_sync_failure=mrbch_phy_sync_failure;
   //  Mac_rlc_xface->dl_phy_sync_success=dl_phy_sync_success;
 
+
+
   LOG_I(MAC,"[MAIN] RLC interface setup and init\n");
   rrc_init_global_param();
+  //MP: otherwise we call the initialization of the RRC NB-IoT module (see mac_init_global_param_NB_IoT)
+
 
 #ifdef USER_MODE
   pdcp_layer_init ();
@@ -436,7 +440,6 @@ int l2_init(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,ui
 {
 
 
-
   LOG_I(MAC,"[MAIN] MAC_INIT_GLOBAL_PARAM IN...\n");
   //    NB_NODE=2;
   //    NB_INST=2;
diff --git a/openair2/LAYER2/MAC/main_NB_IoT.c b/openair2/LAYER2/MAC/main_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..2e475bd0dfe4dd6cfc2bb452a72a1ffe2e36600e
--- /dev/null
+++ b/openair2/LAYER2/MAC/main_NB_IoT.c
@@ -0,0 +1,219 @@
+
+/*! \file main_NB_IoT.c
+ * \brief top init of Layer 2
+ * \author  NTUST BMW LAB./
+ * \date 2017
+ * \version 1.0
+ * \email: 
+ */
+
+
+//#include "asn1_constants.h"
+#include "LAYER2/MAC/defs_NB_IoT.h"
+#include "LAYER2/MAC/proto_NB_IoT.h"
+#include "LAYER2/MAC/extern_NB_IoT.h"
+#include "vars_NB_IoT.h"
+#include "RRC/LITE/proto_NB_IoT.h"
+
+#define NUM_USS_PP 3
+#define USER_NUM_USS 10
+
+int mac_init_global_param_NB_IoT(void)
+{
+
+  if (rlc_module_init()!=0) {
+    return(-1);
+ }
+
+  LOG_I(MAC,"[MAIN] RRC NB-IoT initialization of global params\n");
+  rrc_init_global_param_NB_IoT();
+
+
+  LOG_I(MAC,"[MAIN] PDCP layer init\n");
+#ifdef USER_MODE
+  pdcp_layer_init ();
+#else
+  pdcp_module_init ();
+#endif
+
+  return 0;
+}
+
+
+// Initial function of the intialization for NB-IoT MAC
+void init_mac_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst)
+{
+  int32_t i, j, k;  
+  
+  for(i=0;i<64;++i)
+  {
+    mac_inst->sib1_flag[i] = 0;
+    mac_inst->sib1_count[i] = 0;
+  }
+  
+  //rrc_mac_config_req_NB_IoT(&mac_inst->rrc_config, 1, 1, 0, 0);
+  init_tool_sib1(mac_inst);
+
+  //  output handler 
+  //  RA
+  mac_inst->RA_msg2_list.head = (RA_TEMPLATE_NB_IoT *)0;
+  mac_inst->RA_msg3_list.head = (RA_TEMPLATE_NB_IoT *)0;
+  mac_inst->RA_msg4_list.head = (RA_TEMPLATE_NB_IoT *)0;
+  mac_inst->RA_msg2_list.tail = (RA_TEMPLATE_NB_IoT *)0;
+  mac_inst->RA_msg3_list.tail = (RA_TEMPLATE_NB_IoT *)0;
+  mac_inst->RA_msg4_list.tail = (RA_TEMPLATE_NB_IoT *)0;
+
+  sib1_NB_IoT_sched_t *config = &mac_inst->rrc_config.sib1_NB_IoT_sched_config;
+  
+  
+  // DLSF Table
+  init_dlsf_info(mac_inst, &DLSF_information);
+
+  //  init sib1 tool
+  //int repetition_pattern = 1;// 1:every2frame, 2:every4frame, 3:every8frame, 4:every16frame
+  for(i=0;i<8;++i){
+    mac_inst->sib1_flag[(i<<1)+config->starting_rf] = 1;
+  }
+
+  for(i=0, j=0;i<64;++i){
+    if(mac_inst->sib1_flag[i]==1){
+      ++j;
+    }
+    mac_inst->sib1_count[i]=j;
+  }
+//printf("%d", mac_inst->sib1_period);
+  for(i=0, j=0;i<640;++i){
+    //printf("*%d", i);
+    if(is_dlsf(mac_inst, i)){
+      ++j;
+    }
+    //printf("-");
+    if(i%10==9){
+      mac_inst->dlsf_table[i/10] = j;
+    }
+  }
+
+  //mac_inst->si_window_length = ms160;
+  //mac_inst->sibs_NB_IoT_sched[0].si_periodicity = rf64;
+
+  for(i=0;i<256;++i){
+    mac_inst->sibs_table[i] = -1;
+  }
+  for(j=0;j<6;++j){
+    if(0x0 != mac_inst->rrc_config.sibs_NB_IoT_sched[j].sib_mapping_info){
+      k = mac_inst->rrc_config.sibs_NB_IoT_sched[j].si_periodicity / mac_inst->rrc_config.si_window_length;
+      for(i=0;i<(256/k);++i){
+        mac_inst->sibs_table[(i*k)+j] = j;
+      }
+    }
+  }
+
+  mac_inst->schedule_subframe_DL = 0;
+  mac_inst->schedule_subframe_UL = 0;
+
+  available_resource_DL = available_resource_DL_last = (available_resource_DL_t *)0;
+
+  //  init downlink list 0-100
+  init_dl_list(mac_inst);
+
+  for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
+    mac_inst->RA_template[i].active = 0;
+    mac_inst->RA_template[i].msg3_retransmit_count = 0;
+    mac_inst->RA_template[i].msg4_retransmit_count = 0;
+    mac_inst->RA_template[i].ta = 0;
+    mac_inst->RA_template[i].preamble_index = 0;
+    mac_inst->RA_template[i].ue_rnti = 0x0;
+    mac_inst->RA_template[i].ra_rnti = 0x0;
+    mac_inst->RA_template[i].next = (RA_TEMPLATE_NB_IoT *)0;
+    mac_inst->RA_template[i].prev = (RA_TEMPLATE_NB_IoT *)0;
+    mac_inst->RA_template[i].wait_msg4_ack = 0;
+    mac_inst->RA_template[i].wait_msg3_ack = 0;
+  }
+  //3 CE level USS list
+  mac_inst->UE_list_spec = (UE_list_NB_IoT_t*)malloc(NUM_USS_PP*sizeof(UE_list_NB_IoT_t));
+  //initial UE list
+  printf("[init_mac_NB_IoT] Initial UE list\n");
+
+  mac_inst->num_uss_list = NUM_USS_PP;
+  for(i=0;i<NUM_USS_PP;++i)
+  {
+    //rrc_mac_config_req_NB_IoT(&mac_inst->rrc_config, 0, 0, 1, i);
+    (mac_inst->UE_list_spec+i)->head = -1;
+    (mac_inst->UE_list_spec+i)->tail = -1;
+    (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.R_max = mac_inst->rrc_config.npdcch_ConfigDedicated[i].R_max;
+    (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.G = mac_inst->rrc_config.npdcch_ConfigDedicated[i].G;
+    (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.a_offset = mac_inst->rrc_config.npdcch_ConfigDedicated[i].a_offset;
+    //(mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.R_max = 8;
+    //(mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.G = 1;
+    //(mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.a_offset = 0;
+    (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.T = (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.R_max * (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.G;
+    (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.ss_start_uss = (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.T * (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.a_offset;
+    for(j=0;j<MAX_NUMBER_OF_UE_MAX_NB_IoT;++j)
+    {
+      (mac_inst->UE_list_spec+i)->UE_template_NB_IoT[j].active=0;
+      (mac_inst->UE_list_spec+i)->UE_template_NB_IoT[j].RRC_connected=0;
+      (mac_inst->UE_list_spec+i)->UE_template_NB_IoT[j].direction = -1;
+    }
+    //SCHEDULE_LOG("[%04d][init_mac_NB_IoT] List_number %d R_max %d G %.1f a_offset %.1f T %d SS_start %d\n", mac_inst->current_subframe, i, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.R_max, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.G, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.a_offset, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.T, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.ss_start_uss);
+    printf("[init_mac_NB_IoT] List_number %d R_max %d G %.1f a_offset %.1f T %d SS_start %d\n", i, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.R_max, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.G, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.a_offset, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.T, (mac_inst->UE_list_spec+i)->NPDCCH_config_dedicated.ss_start_uss);
+  }
+
+/*
+  //Initial one UE template
+  //UE_TEMPLATE_NB_IoT *UE_info=(UE_TEMPLATE_NB_IoT*)malloc(USER_NUM_USS*sizeof(UE_TEMPLATE_NB_IoT));
+
+  mac_inst->UE_list_spec->head=0;
+  mac_inst->UE_list_spec->tail=0;
+
+  for(i=0;i<USER_NUM_USS;++i)
+  {
+    UE_info_setting(mac_inst->UE_list_spec->UE_template_NB_IoT+i);
+
+    if(i==0)
+    {
+      (mac_inst->UE_list_spec->UE_template_NB_IoT+i)->prev=-1;
+      (mac_inst->UE_list_spec->UE_template_NB_IoT+i)->next=1;
+      //mac_inst->UE_list_spec->next[i]=-1;
+    }
+    else if(i>=USER_NUM_USS-1)
+    {
+      (mac_inst->UE_list_spec->UE_template_NB_IoT+i)->prev=i-1;
+      (mac_inst->UE_list_spec->UE_template_NB_IoT+i)->next=-1;
+    }
+    else
+    {
+      (mac_inst->UE_list_spec->UE_template_NB_IoT+i)->prev=i-1;
+      (mac_inst->UE_list_spec->UE_template_NB_IoT+i)->next=i+1;
+    }
+    //mac_inst->UE_list_spec->UE_template_NB_IoT[i]=UE_info[i];
+    mac_inst->UE_list_spec->tail=i;
+  }
+*/
+  //UL initial
+  //Setting nprach configuration
+  setting_nprach();
+  //Initialize uplink resource from nprach configuration
+  Initialize_Resource();
+  //add_UL_Resource(mac_inst);    
+  extend_available_resource_DL(mac_inst, mac_inst->current_subframe + 1 + 160);
+}
+
+
+int l2_init_eNB_NB_IoT(void)
+{
+  LOG_I(MAC,"[MAIN] Mapping L2 IF-Module functions\n");
+  IF_Module_init_L2();
+
+  LOG_I(MAC,"[MAIN] MAC_INIT_GLOBAL_PARAM NB-IoT IN...\n");
+
+  mac_inst = (eNB_MAC_INST_NB_IoT *) malloc (sizeof(eNB_MAC_INST_NB_IoT));
+
+  Is_rrc_registered_NB_IoT=0;
+  mac_init_global_param_NB_IoT();
+  Is_rrc_registered_NB_IoT=1;
+
+  //init_mac_NB_IoT(mac_inst);
+
+  return(1);
+}
+
diff --git a/openair2/LAYER2/MAC/output_handler_NB_IoT.c b/openair2/LAYER2/MAC/output_handler_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..7017ba3720a12c63e10a5c2521dd5ce2199e07c3
--- /dev/null
+++ b/openair2/LAYER2/MAC/output_handler_NB_IoT.c
@@ -0,0 +1,286 @@
+
+/*! \file output_handler_NB_IoT.c
+ * \brief Convert MAC scheduler result and output the FAPI structure by subframe based
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "defs_NB_IoT.h"
+#include "proto_NB_IoT.h"
+#include "extern_NB_IoT.h"
+
+int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_id, uint32_t hypersfn, uint32_t frame, uint32_t subframe, uint8_t MIB_flag, uint8_t SIB1_flag, uint32_t current_time)
+{
+    //if(schedule_result_list_UL != (schedule_result_t *)0){
+    //    printf("time %d\n", mac_inst->current_subframe);
+    //    print_schedule_result_DL(); print_schedule_result_UL(); getchar();
+    //}
+    
+    // MIB SIB1 PDU command here
+	uint8_t MIB_size = 0;
+	uint8_t SIB1_size = 0, i = 0;
+
+	Sched_Rsp_t *SCHED_info = (Sched_Rsp_t*) malloc(sizeof(Sched_Rsp_t));
+	nfapi_dl_config_request_pdu_t *dl_config_pdu;
+	nfapi_hi_dci0_request_pdu_t* hi_dci0_pdu;
+	nfapi_ul_config_request_pdu_t* ul_config_pdu;
+	schedule_result_t *tmp;
+	int DL_empty = 0, UL_empty = 0; 
+	//uint32_t current_time = 0;
+	//current_time = hypersfn * 10240 + frame * 10 + subframe;
+
+	// filled common part of schedule_resoponse
+
+
+	SCHED_info->module_id = module_id;
+	SCHED_info->hypersfn = hypersfn;
+	SCHED_info->frame = frame;
+	SCHED_info->subframe = subframe;
+	void *DCI_pdu;
+
+	SCHED_info->TX_req = (nfapi_tx_request_t *) malloc (sizeof(nfapi_tx_request_t));
+	SCHED_info->DL_req = (nfapi_dl_config_request_t*) malloc (sizeof(nfapi_dl_config_request_t));
+	SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list = (nfapi_dl_config_request_pdu_t*)malloc(sizeof(nfapi_dl_config_request_pdu_t));
+	dl_config_pdu = SCHED_info->DL_req->dl_config_request_body.dl_config_pdu_list;
+
+	//printf("first DL node output: %d current: %d\n",schedule_result_list_DL->output_subframe,current_time);
+
+	//printf("test current: %d\n",current_time);
+
+	if(MIB_flag == 1)
+		{
+			//printf("[%d]MIB\n",current_time);
+			//MIB_size = mac_rrc_data_req_eNB_NB_IoT(*MIB)
+        	SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
+			dl_config_pdu->pdu_type                                               	 = NFAPI_DL_CONFIG_NBCH_PDU_TYPE;
+      		dl_config_pdu->pdu_size                                               	 = 2+sizeof(nfapi_dl_config_nbch_pdu_rel13_t);
+      		dl_config_pdu->nbch_pdu.nbch_pdu_rel13.length                            = MIB_size;
+      		dl_config_pdu->nbch_pdu.nbch_pdu_rel13.pdu_index                         = 1;
+      		dl_config_pdu->nbch_pdu.nbch_pdu_rel13.transmission_power                = 6000;
+      		// fill MIB PDU
+      		//SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->NB_IoTch_pdu.NB_IoTch_pdu_rel13.pdu_index].segments[0].segment_data = MIB;
+      		
+      		//dl_scheduled(mac_inst->current_subframe, _NPBCH, 0, "MIB");
+		}
+		else if(SIB1_flag == 1)
+		{
+			//SIB1_size = mac_rrc_data_req_eNB_NB_IoT(*SIB1);
+			SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
+			dl_config_pdu->pdu_type                                                   = NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE;
+			dl_config_pdu->pdu_size                                                   = 2+sizeof(nfapi_dl_config_ndlsch_pdu_rel13_t);
+			dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.length                         = SIB1_size;
+			dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index					  = 1;
+			dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti_type                      = 0;
+			dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti                           = 0xFFFF; // SI-rnti
+			dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.modulation                     = 2;
+
+			//SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index].segments[0].segment_data = SIB1;
+
+			//start symbol, Resource assignment, Repetition number, Number of subframe Resource assignment lost for now
+			//dl_scheduled(mac_inst->current_subframe, _NPDSCH, SI_RNTI, "SIB1");
+		}
+
+	else if(schedule_result_list_DL==NULL)
+	{
+		DL_empty = 1;
+		//printf("no remaining node of DL scheduling result\n");
+	}else
+	{
+		if(schedule_result_list_DL->output_subframe < current_time)
+		{
+			while(schedule_result_list_DL->output_subframe < current_time)
+			{
+				//printf("This error if there is DL scheduling result node before the current time\n");
+				tmp = schedule_result_list_DL;
+				schedule_result_list_DL = schedule_result_list_DL->next;
+				free(tmp);
+				//printf("test2 current: %d\n",current_time);
+				//break;
+				if(schedule_result_list_DL == NULL){
+					return -1;
+				}
+			}
+			//printf("return\n");
+			//return -1;
+		}
+		else if (schedule_result_list_DL->output_subframe == current_time)
+		{
+			switch(schedule_result_list_DL->channel)
+			{
+				case NPDCCH:
+
+					if(schedule_result_list_DL->direction == DL)
+					{
+						//printf("Sched Info DL DCI here\n");
+						SCHED_info->DL_req->dl_config_request_body.number_dci = 1;
+						DCI_pdu = schedule_result_list_DL->DCI_pdu;
+						// not consider the case transmitting 2 DCIs for the moment also not consider N2 now
+						dl_config_pdu->pdu_type                                                          = NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE;
+						dl_config_pdu->pdu_size                                                          = 2+sizeof(nfapi_dl_config_npdcch_pdu_rel13_t);
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.length				                 = schedule_result_list_DL->sdu_length;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.pdu_index                             = 1;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.ncce_index                            = 0;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.aggregation_level     				 = 1;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti_type                             = schedule_result_list_DL->rnti_type; // 3 = UE-specific RNTI TODO: add RNTI type in scheduling result
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.rnti                                  = schedule_result_list_DL->rnti;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_format                            = 0; // N1
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.scheduling_delay                      = ((DCIFormatN1_t *)DCI_pdu)->Scheddly;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.resource_assignment                   = ((DCIFormatN1_t *)DCI_pdu)->ResAssign;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.repetition_number                     = ((DCIFormatN1_t *)DCI_pdu)->RepNum;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.mcs                                   = ((DCIFormatN1_t *)DCI_pdu)->mcs;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.new_data_indicator                    = ((DCIFormatN1_t *)DCI_pdu)->ndi;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.harq_ack_resource                     = ((DCIFormatN1_t *)DCI_pdu)->HARQackRes;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.npdcch_order_indication               = ((DCIFormatN1_t *)DCI_pdu)->orderIndicator;
+						dl_config_pdu->npdcch_pdu.npdcch_pdu_rel13.dci_subframe_repetition_number        = ((DCIFormatN1_t *)DCI_pdu)->DCIRep;
+					}else if(schedule_result_list_DL->direction == UL)
+					{
+						SCHED_info->HI_DCI0_req = (nfapi_hi_dci0_request_t*)malloc(sizeof(nfapi_hi_dci0_request_t));
+						SCHED_info->HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list = (nfapi_hi_dci0_request_pdu_t*)malloc(sizeof(nfapi_hi_dci0_request_pdu_t));
+						hi_dci0_pdu = SCHED_info->HI_DCI0_req->hi_dci0_request_body.hi_dci0_pdu_list;
+						DCI_pdu = schedule_result_list_DL-> DCI_pdu;
+						SCHED_info-> HI_DCI0_req->hi_dci0_request_body.number_of_dci =1;
+						hi_dci0_pdu->pdu_type                                                            = NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE;
+						hi_dci0_pdu->pdu_size                                                            = 2 + sizeof(nfapi_hi_dci0_npdcch_dci_pdu_rel13_t);
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.ncce_index                      = 0;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.aggregation_level               = 1;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.rnti                            = schedule_result_list_DL->rnti;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.subcarrier_indication           = ((DCIFormatN0_t *)DCI_pdu)->scind;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.resource_assignment             = ((DCIFormatN0_t *)DCI_pdu)->ResAssign;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.scheduling_delay                = ((DCIFormatN0_t *)DCI_pdu)->Scheddly;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.mcs                             = ((DCIFormatN0_t *)DCI_pdu)->mcs;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.redudancy_version               = ((DCIFormatN0_t *)DCI_pdu)->rv;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.repetition_number               = ((DCIFormatN0_t *)DCI_pdu)->RepNum;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.new_data_indicator              = ((DCIFormatN0_t *)DCI_pdu)->ndi;
+						hi_dci0_pdu->npdcch_dci_pdu.npdcch_dci_pdu_rel13.dci_subframe_repetition_number  = ((DCIFormatN0_t *)DCI_pdu)->DCIRep;
+					}
+					break;
+				case NPDSCH:
+
+				    DCI_pdu = schedule_result_list_DL-> DCI_pdu;
+					SCHED_info->DL_req->dl_config_request_body.number_pdu = 1;
+					dl_config_pdu->pdu_type                                           = NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE;
+					dl_config_pdu->pdu_size                                           = 2+sizeof(nfapi_dl_config_ndlsch_pdu_rel13_t);
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.length                 = schedule_result_list_DL->sdu_length;
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index			  = 1;
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti_type              = 1;
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.rnti                   = schedule_result_list_DL->rnti; // C-RNTI
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.resource_assignment    = ((DCIFormatN1_t *)DCI_pdu)->ResAssign;
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.repetition_number      = ((DCIFormatN1_t *)DCI_pdu)->RepNum;
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.modulation             = 2;
+					dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.number_of_subframes_for_resource_assignment = get_num_sf(dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.resource_assignment);
+					//SCHED_info->TX_req->tx_request_body.tx_pdu_list[dl_config_pdu->ndlsch_pdu.ndlsch_pdu_rel13.pdu_index].segments[0].segment_data = schedule_result_list_DL->DLSCH_pdu;
+					break;
+				default:
+					break;
+			}
+
+			if(schedule_result_list_DL->DCI_release == 1)
+				free(schedule_result_list_DL->DCI_pdu);
+			
+            tmp = schedule_result_list_DL;
+			schedule_result_list_DL = schedule_result_list_DL->next;
+			
+
+			//printf("subframe check scheduling result next %d\n",schedule_result_list_DL->output_subframe);
+		}
+	}
+		//printf("There is no downlink transmission\n");
+
+	
+
+	if(schedule_result_list_UL==NULL)
+	{
+		UL_empty = 1;
+		//printf("no remaining node of UL scheduling result\n");
+	}else
+	{
+		if(schedule_result_list_UL->output_subframe < current_time)
+		{
+			while(schedule_result_list_UL->output_subframe < current_time)
+			{
+				//printf("This error if there is UL scheduling result node before the current time\n");
+				tmp = schedule_result_list_UL;
+				schedule_result_list_UL = schedule_result_list_UL->next;
+				free(tmp);
+				return -1;
+			}
+			//printf("return\n");
+			//return -1;
+		}
+		else if(schedule_result_list_UL->output_subframe == current_time)
+		{
+			SCHED_info->UL_req = (nfapi_ul_config_request_t *)malloc(sizeof(nfapi_ul_config_request_t));
+			SCHED_info->UL_req->ul_config_request_body.number_of_pdus = 0;
+			SCHED_info->UL_req->ul_config_request_body.ul_config_pdu_list = (nfapi_ul_config_request_pdu_t *)malloc(5 * sizeof(nfapi_ul_config_request_pdu_t));
+			ul_config_pdu = SCHED_info->UL_req->ul_config_request_body.ul_config_pdu_list;
+		}	
+		while(schedule_result_list_UL->output_subframe == current_time)
+		{
+			if(schedule_result_list_UL->channel == NPUSCH)
+			{
+				printf("first UL \n");
+				SCHED_info->UL_req->ul_config_request_body.number_of_pdus ++;
+				//SCHED_info->UL_req.sfn_sf = ;
+				(ul_config_pdu + i) ->pdu_type                                            = NFAPI_UL_CONFIG_NULSCH_PDU_TYPE;
+				(ul_config_pdu + i) ->pdu_size                                            = 2 + sizeof(nfapi_ul_config_nulsch_pdu_rel13_t);
+
+				if(schedule_result_list_UL->npusch_format == 0)
+				{
+					DCI_pdu = schedule_result_list_UL->DCI_pdu;
+					// bug here
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.nulsch_format           = 0;
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.size                    = UL_TBS_Table[((DCIFormatN0_t *)DCI_pdu)->mcs][((DCIFormatN0_t *)DCI_pdu)->ResAssign];
+					//printf("test\n");
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.rnti                    = schedule_result_list_UL->rnti;
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.subcarrier_indication   = ((DCIFormatN0_t *)DCI_pdu)->scind;
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.resource_assignment     = ((DCIFormatN0_t *)DCI_pdu)->ResAssign;
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.mcs                     = ((DCIFormatN0_t *)DCI_pdu)->mcs;
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.redudancy_version       = ((DCIFormatN0_t *)DCI_pdu)->rv;
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.repetition_number       = ((DCIFormatN0_t *)DCI_pdu)->RepNum;
+					(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.new_data_indication     = ((DCIFormatN0_t *)DCI_pdu)->ndi;
+
+				}else if(schedule_result_list_UL->npusch_format == 1)
+					{
+						DCI_pdu = schedule_result_list_UL->DCI_pdu;
+						(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.nulsch_format       = 1;
+						(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.rnti                = schedule_result_list_UL->rnti;
+						(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.ue_information.ue_information_rel13.total_number_of_repetitions = schedule_result_list_UL->R_harq;
+						//for ACK /NACK
+						(ul_config_pdu + i) ->nulsch_pdu.nulsch_pdu_rel13.nb_harq_information.nb_harq_information_rel13_fdd.harq_ack_resource = ((DCIFormatN1_t *)DCI_pdu)->HARQackRes;
+					}
+				//print_scheduling_result_UL();
+				
+                if(schedule_result_list_UL->DCI_release == 1){
+                    free(schedule_result_list_UL->DCI_pdu);
+                }
+                
+                tmp = schedule_result_list_UL;
+				schedule_result_list_UL = schedule_result_list_UL->next;
+				
+				free(tmp);
+
+				i++;
+				if(schedule_result_list_UL == NULL)
+					break;
+			}else{
+				printf("error");
+			}
+		}
+	}
+
+	if(DL_empty == 1 )
+	{
+		//printf("[hypersfn:%2d][frame:%2d][subframe:%2d]No remaining DL result\n",hypersfn,frame,subframe);
+	}
+	if(UL_empty == 1)
+	{
+		//printf("[hypersfn:%2d][frame:%2d][subframe:%2d]no remaining UL result\n",hypersfn,frame,subframe);
+	}
+	
+	//printf("[hypersfn:%2d][frame:%2d][subframe:%2d]filling the schedule response successfully\n",hypersfn,frame,subframe);
+
+	return 0;
+}
diff --git a/openair2/LAYER2/MAC/proto_NB_IoT.h b/openair2/LAYER2/MAC/proto_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..9f5edd21cb967730e7da2808f2094eb940441a08
--- /dev/null
+++ b/openair2/LAYER2/MAC/proto_NB_IoT.h
@@ -0,0 +1,224 @@
+/*
+ * 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.0  (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 LAYER2/MAC/proto_NB_IoT.h
+ * \brief MAC functions prototypes for eNB and UE
+ * \author Navid Nikaein and Raymond Knopp
+ * \date 2010 - 2014
+ * \email navid.nikaein@eurecom.fr
+ * \version 1.0
+ */
+
+#ifndef __LAYER2_MAC_PROTO_NB_IoT_H__
+#define __LAYER2_MAC_PROTO_NB_IoT_H__
+
+#include "openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+#include "LAYER2/MAC/defs_NB_IoT.h"
+#include "COMMON/platform_types.h"
+#include "openair2/RRC/LITE/defs_NB_IoT.h"
+/** \addtogroup _mac
+ *  @{
+ */
+
+int l2_init_eNB_NB_IoT(void);
+
+// main schedule functions
+
+void eNB_scheduler_computing_flag_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe, int *scheduler_flags, int *common_flags);
+
+/*function description:
+* top level of the scheduler, this will trigger in every subframe,
+* and determined if do the schedule by checking this current subframe is the start of the NPDCCH period or not
+*/
+void eNB_dlsch_ulsch_scheduler_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t abs_subframe);
+
+void schedule_sibs_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t sibs_order, int start_subframe1);
+
+void schedule_uss_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, uint32_t subframe, uint32_t frame, uint32_t hypersfn, int index_ss);
+
+void schedule_RA_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
+
+void schedule_msg3_retransimission_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
+
+void schedule_msg4_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
+
+void schedule_rar_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
+
+int schedule_UL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst,UE_TEMPLATE_NB_IoT *UE_info,uint32_t subframe, uint32_t frame, uint32_t H_SFN);
+
+void schedule_DL_NB_IoT(module_id_t module_id, eNB_MAC_INST_NB_IoT *mac_inst, UE_TEMPLATE_NB_IoT *UE_info, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start);
+
+int output_handler(eNB_MAC_INST_NB_IoT *mac_inst, module_id_t module_id, int CC_id, uint32_t hypersfn, uint32_t frame, uint32_t subframe, uint8_t MIB_flag, uint8_t SIB1_flag, uint32_t current_time);
+
+/*Scheduler resource/environment setting*/
+
+void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst);
+
+void init_dlsf_info(eNB_MAC_INST_NB_IoT *mac_inst, DLSF_INFO_t *DLSF_info);
+
+void init_mac_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst);
+
+int is_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe);
+
+void init_dl_list(eNB_MAC_INST_NB_IoT *mac_inst);
+
+void setting_nprach(void);
+
+void init_rrc_NB_IoT(void);
+
+void add_UL_Resource_node(available_resource_UL_t **head, uint32_t *end_subframe, uint32_t ce_level);
+
+void add_UL_Resource(void);
+
+void Initialize_Resource(void);
+
+void extend_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int max_subframe);
+
+//Transfrom source into hyperSF, Frame, Subframe format
+void convert_system_number(uint32_t source_sf,uint32_t *hyperSF, uint32_t *frame, uint32_t *subframe);
+
+uint32_t convert_system_number_sf(uint32_t hyperSF, uint32_t frame, uint32_t subframe);
+
+uint32_t to_earfcn(int eutra_bandP,uint32_t dl_CarrierFreq, float m_dl);
+
+uint32_t from_earfcn_NB_IoT(int eutra_bandP,uint32_t dl_earfcn, float m_dl);
+
+int32_t get_uldl_offset_NB_IoT(int eutra_band);
+
+void config_mib_fapi_NB_IoT(
+		int                     rntiP,
+        int                     physCellId,
+        uint8_t                 eutra_band,
+        int                     Ncp,
+        int                     Ncp_UL,
+        int                     p_eNB,
+        int                     p_rx_eNB,
+        int                     dl_CarrierFreq,
+        int                     ul_CarrierFreq,
+        long                    *eutraControlRegionSize,
+        BCCH_BCH_Message_NB_t   *mib_NB_IoT
+        );
+
+void config_sib2_fapi_NB_IoT(
+                        int physCellId,
+                        RadioResourceConfigCommonSIB_NB_r13_t   *radioResourceConfigCommon
+                        );
+
+void rrc_mac_config_req_NB_IoT(
+    module_id_t                             Mod_idP,
+    int                                     CC_idP,
+    int                                     rntiP,
+    rrc_eNB_carrier_data_NB_IoT_t           *carrier,
+    SystemInformationBlockType1_NB_t        *sib1_NB_IoT,
+    RadioResourceConfigCommonSIB_NB_r13_t   *radioResourceConfigCommon,
+    PhysicalConfigDedicated_NB_r13_t        *physicalConfigDedicated,
+    LogicalChannelConfig_NB_r13_t           *logicalChannelConfig,            //FIXME: decide how to use it
+    rrc_config_NB_IoT_t                     *mac_config,
+    uint8_t                                 ded_flag,
+    uint8_t                                 ue_list_ded_num);
+
+// schedule helper functinons
+
+void fill_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, available_resource_DL_t *node, int start_subframe, int end_subframe, schedule_result_t *new_node);
+
+available_resource_DL_t *check_sibs_resource(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t check_start_subframe, uint32_t check_end_subframe, uint32_t num_subframe, uint32_t *residual_subframe, uint32_t *out_last_subframe, uint32_t *out_first_subframe);
+
+uint32_t calculate_DLSF(eNB_MAC_INST_NB_IoT *mac_inst, int abs_start_subframe, int abs_end_subframe);
+
+//	check_subframe must be DLSF, you can use is_dlsf() to check before call function
+available_resource_DL_t *check_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int check_subframe, int num_subframes, int *out_last_subframe, int *out_first_subframe);
+
+void maintain_available_resource(eNB_MAC_INST_NB_IoT *mac_inst);
+
+int multi_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info);
+
+int single_tone_ru_allocation(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int fmt2_flag);
+
+int Check_UL_resource(uint32_t uplink_time, int total_ru, sched_temp_UL_NB_IoT_t *NPUSCH_info, int multi_tone, int fmt2_flag);
+
+void insert_schedule_result(schedule_result_t **list, int subframe, schedule_result_t *node);
+
+void adjust_UL_resource_list(sched_temp_UL_NB_IoT_t *NPUSCH_info);
+
+void generate_scheduling_result_UL(int32_t DCI_subframe, int32_t DCI_end_subframe, uint32_t UL_subframe, uint32_t UL_end_subframe, DCIFormatN0_t *DCI_pdu, rnti_t rnti, uint8_t *ul_debug_str, uint8_t *dl_debug_str);
+
+uint32_t get_I_mcs_NB_IoT(int CE_level);
+
+int get_TBS_UL_NB_IoT(uint32_t mcs,uint32_t multi_tone,int Iru);
+
+// DL TBS
+uint32_t get_tbs(uint32_t data_size, uint32_t I_tbs, uint32_t *I_sf);
+
+uint32_t get_max_tbs(uint32_t I_tbs);
+
+uint32_t get_num_sf(uint32_t I_sf);
+
+uint16_t find_suit_i_delay(uint32_t rmax, uint32_t r, uint32_t dci_candidate);
+
+uint32_t get_scheduling_delay(uint32_t I_delay, uint32_t R_max);
+
+uint32_t get_HARQ_delay(int subcarrier_spacing, uint32_t HARQ_delay_index);
+
+int get_resource_field_value(int subcarrier, int k0);
+
+void fill_rar_NB_IoT(eNB_MAC_INST_NB_IoT *inst, RA_TEMPLATE_NB_IoT *ra_template, uint8_t msg3_schedule_delay, uint8_t msg3_rep, sched_temp_UL_NB_IoT_t *schedule_template);
+
+uint32_t cal_num_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF, uint32_t frame, uint32_t subframe, uint32_t* hyperSF_result, uint32_t* frame_result, uint32_t* subframe_result, uint32_t num_dlsf_require);
+
+int check_resource_NPDCCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, sched_temp_DL_NB_IoT_t *NPDCCH_info, uint32_t cdd_num, uint32_t dci_rep);
+
+int check_resource_NPDSCH_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDSCH_info, uint32_t sf_end, uint32_t I_delay, uint32_t R_max, uint32_t R_dl, uint32_t n_sf);
+
+int check_resource_DL_NB_IoT(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF_start, uint32_t frame_start, uint32_t subframe_start, uint32_t dlsf_require, sched_temp_DL_NB_IoT_t *schedule_info);
+
+void fill_DCI_N1(DCIFormatN1_t *DCI_N1, UE_TEMPLATE_NB_IoT *UE_info, uint32_t scheddly, uint32_t I_sf, uint32_t I_harq);
+
+uint32_t generate_dlsch_header_NB_IoT(uint8_t *pdu, uint32_t num_sdu, logical_chan_id_t *logical_channel, uint32_t *sdu_length, uint8_t flag_drx, uint8_t flag_ta, uint32_t TBS);
+
+void generate_scheduling_result_DL(uint32_t DCI_subframe, uint32_t NPDSCH_subframe, uint32_t HARQ_subframe, DCIFormatN1_t *DCI_pdu, rnti_t rnti, uint32_t TBS, uint8_t *DLSCH_pdu);
+
+void maintain_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, sched_temp_DL_NB_IoT_t *NPDCCH_info, sched_temp_DL_NB_IoT_t *NPDSCH_info);
+
+int get_N_REP(int CE_level);
+
+int get_I_REP(int N_rep);
+
+int get_DCI_REP(uint32_t R,uint32_t R_max);
+
+int get_I_TBS_NB_IoT(int x,int y);
+
+uint8_t get_index_Rep_dl(uint16_t R);
+
+UE_TEMPLATE_NB_IoT *get_ue_from_rnti(eNB_MAC_INST_NB_IoT *inst, rnti_t rnti);
+
+//debug function
+
+void print_available_resource_DL(void);
+
+void print_available_UL_resource(void);
+
+//interface with IF
+
+uint8_t *parse_ulsch_header_NB_IoT( uint8_t *mac_header, uint8_t *num_ce, uint8_t *num_sdu, uint8_t *rx_ces, uint8_t *rx_lcids, uint16_t *rx_lengths, uint16_t tb_length);
+
+void rx_sdu_NB_IoT(module_id_t module_id, int CC_id, frame_t frame, sub_frame_t subframe, uint16_t rnti, uint8_t *sdu, uint16_t  length);
+
+#endif
diff --git a/openair2/LAYER2/MAC/proto_nb_iot.h b/openair2/LAYER2/MAC/proto_nb_iot.h
deleted file mode 100644
index 2b0b97c92682e391a2ed03723a386c8d6cb0de9c..0000000000000000000000000000000000000000
--- a/openair2/LAYER2/MAC/proto_nb_iot.h
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * 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.0  (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 LAYER2/MAC/proto.h
- * \brief MAC functions prototypes for eNB and UE
- * \author Navid Nikaein and Raymond Knopp
- * \date 2010 - 2014
- * \email navid.nikaein@eurecom.fr
- * \version 1.0
- */
-
- 
-
-
-/** \addtogroup _mac
- *  @{
- */
-
-/*for NB-IoT*/
-
-/* \brief Function to indicate a received SDU on ULSCH for NB-IoT.
-*/
-void NB_rx_sdu(const module_id_t module_idP, const int CC_id,const frame_t frameP, const sub_frame_t subframeP, const rnti_t rnti, uint8_t *sdu, const uint16_t sdu_len, const int harq_pid,uint8_t *msg3_flag);
-
-/* \brief Function to retrieve result of scheduling (DCI) in current subframe.  Can be called an arbitrary numeber of times after eNB_dlsch_ulsch_scheduler
-in a given subframe. 
-*/
-DCI_PDU_NB *NB_get_dci_sdu(module_id_t module_idP,int CC_id,frame_t frameP,sub_frame_t subframe);
-
-
-/* \brief Function to trigger the eNB scheduling procedure.  It is called by PHY at the beginning of each subframe, \f$n$\f
-   and generates all DLSCH allocations for subframe \f$n\f$ and ULSCH allocations for subframe \f$n+k$\f. The resultant DCI_PDU is
-   ready after returning from this call.
-
-*/
-void NB_eNB_dlsch_ulsch_scheduler(module_id_t module_idP, uint8_t cooperation_flag, frame_t frameP, sub_frame_t subframeP);
-
-/* \brief Function to indicate a received preamble on PRACH.  It initiates the RA procedure.
-    In NB-IoT, it indicate preamble using the frequency to indicate the preamble.
-*/
-void NB_schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP);
-
-void NB_initiate_ra_proc(module_id_t module_idP, int CC_id,frame_t frameP, uint16_t preamble_index,int16_t timing_offset,sub_frame_t subframeP);
-
-uint8_t *NB_get_dlsch_sdu(module_id_t module_idP,int CC_id,frame_t frameP,rnti_t rnti,uint8_t TBindex);
-
-
-int NB_rrc_mac_remove_ue(module_id_t Mod_id, rnti_t rntiP);
-
-int NB_l2_init_eNB(LTE_DL_FRAME_PARMS *frame_parms,int eMBMS_active, char *uecap_xer,uint8_t cba_group_active, uint8_t HO_active);
-
-
-
diff --git a/openair2/LAYER2/MAC/schedule_tool_NB_IoT.c b/openair2/LAYER2/MAC/schedule_tool_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..4cb0c5d96cfba7b265d54364d1f04a4058442eda
--- /dev/null
+++ b/openair2/LAYER2/MAC/schedule_tool_NB_IoT.c
@@ -0,0 +1,899 @@
+
+/*! \file schedule_tool_NB_IoT.c
+ * \brief scheduler helper function
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+#include "defs_NB_IoT.h"
+#include "proto_NB_IoT.h"
+#include "extern_NB_IoT.h"
+
+void init_tool_sib1(eNB_MAC_INST_NB_IoT *mac_inst){
+	int i, j;
+
+	//int repetition_pattern = 1;//	1:every2frame, 2:every4frame, 3:every8frame, 4:every16frame
+	for(i=0;i<8;++i){
+		mac_inst->sib1_flag[(i<<1)+mac_inst->rrc_config.sib1_NB_IoT_sched_config.starting_rf] = 1;
+	}
+
+	for(i=0, j=0;i<64;++i){
+		if(mac_inst->sib1_flag[i]==1){
+			++j;
+		}
+		mac_inst->sib1_count[i]=j;
+	}
+
+	mac_inst->sib1_period = 256 / mac_inst->rrc_config.sib1_NB_IoT_sched_config.repetitions;
+
+	return ;
+}
+
+void init_dlsf_info(eNB_MAC_INST_NB_IoT *mac_inst, DLSF_INFO_t *DLSF_info)
+{
+  uint16_t dlsf_num_temp=0;
+  uint16_t i;
+  uint16_t j=0;
+
+  DLSF_info->sf_to_dlsf_table=(uint16_t*)malloc(mac_inst->sib1_period*10*sizeof(uint16_t));
+  for(i=0;i<mac_inst->sib1_period*10;++i)
+  {
+    if(is_dlsf(mac_inst, i)==1)
+    {
+      dlsf_num_temp++;
+      DLSF_info->sf_to_dlsf_table[i]=dlsf_num_temp;
+    }
+    else
+    {
+      DLSF_info->sf_to_dlsf_table[i]=dlsf_num_temp;
+    }
+  }
+  DLSF_info->num_dlsf_per_period = dlsf_num_temp;
+  DLSF_info->dlsf_to_sf_table = (uint16_t*)malloc(dlsf_num_temp*sizeof(uint16_t));
+  for(i=0;i<mac_inst->sib1_period*10;++i)
+  {
+    if(is_dlsf(mac_inst, i)==1)
+    {
+      DLSF_info->dlsf_to_sf_table[j]= i;
+      j++;
+    }
+  }
+}
+
+int is_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, int abs_subframe){
+	int frame = abs_subframe/10;
+	int subframe = abs_subframe%10;
+
+	return !(subframe==0||subframe==5||((frame&0x1)==0&&subframe==9)||(mac_inst->sib1_flag[frame%mac_inst->sib1_period]==1&&subframe==4));
+}
+
+void init_dl_list(eNB_MAC_INST_NB_IoT *mac_inst){
+	available_resource_DL_t *node;
+
+	node = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
+	node->next = (available_resource_DL_t *)0;
+	node->prev = (available_resource_DL_t *)0;
+
+	available_resource_DL = node;
+	available_resource_DL_last = node;
+
+	node->start_subframe = 0;
+	node->end_subframe = mac_inst->rrc_config.si_window_length;
+	node->DLSF_num = calculate_DLSF(mac_inst, node->start_subframe, node->end_subframe);
+	mac_inst->schedule_subframe_DL = mac_inst->rrc_config.si_window_length;
+
+	//	init sibs for first si-window
+	schedule_sibs_NB_IoT(mac_inst, 0, 0);
+}
+
+void setting_nprach(void){
+
+	nprach_list[0].nprach_Periodicity = rachperiod[4];
+	nprach_list[0].nprach_StartTime = rachstart[0];
+	nprach_list[0].nprach_SubcarrierOffset = rachscofst[0];
+	nprach_list[0].nprach_NumSubcarriers = rachnumsc[0];
+	nprach_list[0].numRepetitionsPerPreambleAttempt = rachrepeat[1];
+
+	nprach_list[1].nprach_Periodicity = rachperiod[4];
+	nprach_list[1].nprach_StartTime = rachstart[0];
+	nprach_list[1].nprach_SubcarrierOffset = rachscofst[1];
+	nprach_list[1].nprach_NumSubcarriers = rachnumsc[0];
+	nprach_list[1].numRepetitionsPerPreambleAttempt = rachrepeat[3];
+
+	nprach_list[2].nprach_Periodicity = rachperiod[4];
+	nprach_list[2].nprach_StartTime = rachstart[0];
+	nprach_list[2].nprach_SubcarrierOffset = rachscofst[2];
+	nprach_list[2].nprach_NumSubcarriers = rachnumsc[1];
+	nprach_list[2].numRepetitionsPerPreambleAttempt = rachrepeat[5];
+
+	// fixed nprach configuration
+}
+
+void add_UL_Resource_node(available_resource_UL_t **head, uint32_t *end_subframe, uint32_t ce_level){
+	available_resource_UL_t *new_node, *iterator;
+    new_node = (available_resource_UL_t *)malloc(sizeof(available_resource_UL_t));
+	
+	new_node->next = (available_resource_UL_t *)0;
+	
+	new_node->start_subframe = *end_subframe + ceil( (nprach_list+ce_level)->nprach_StartTime + 1.4*4*((nprach_list+ce_level)->numRepetitionsPerPreambleAttempt) ) ;
+	
+    new_node->end_subframe = *end_subframe + (nprach_list+ce_level)->nprach_Periodicity - 1;
+	
+	if( (available_resource_UL_t *)0 == *head){
+		*head = new_node;
+		new_node->prev = (available_resource_UL_t *)0;
+	}else{
+		iterator = *head;
+		while( (available_resource_UL_t *)0 != iterator->next){
+			iterator = iterator->next;
+		}
+		iterator->next = new_node;
+		new_node->prev = iterator;
+	}
+	
+
+    *end_subframe += (nprach_list+ce_level)->nprach_Periodicity;
+}
+
+/// Use to extend the UL resource grid (5 list) at the end of nprach peroid time
+/// void add_UL_Resource(eNB_MAC_INST_NB_IoT *mac_inst)
+void add_UL_Resource(void)
+{
+	
+	add_UL_Resource_node(&available_resource_UL->sixtone_Head, &available_resource_UL->sixtone_end_subframe, 2);
+	add_UL_Resource_node(&available_resource_UL->threetone_Head, &available_resource_UL->threetone_end_subframe, 1);
+	add_UL_Resource_node(&available_resource_UL->singletone1_Head, &available_resource_UL->singletone1_end_subframe, 0);
+	add_UL_Resource_node(&available_resource_UL->singletone2_Head, &available_resource_UL->singletone2_end_subframe, 0);
+	add_UL_Resource_node(&available_resource_UL->singletone3_Head, &available_resource_UL->singletone3_end_subframe, 0);
+	
+	//print_available_UL_resource(); getchar();
+}
+
+/*when there is SIB-2 configuration coming to MAC, filled the uplink resource grid*/
+void Initialize_Resource(void){
+
+    ///memory allocate to Head
+    available_resource_UL = (available_resource_tones_UL_t*)malloc(sizeof(available_resource_tones_UL_t));
+
+    available_resource_UL->sixtone_Head = (available_resource_UL_t *)0;
+    available_resource_UL->threetone_Head = (available_resource_UL_t *)0;
+    available_resource_UL->singletone1_Head = (available_resource_UL_t *)0;
+    available_resource_UL->singletone2_Head = (available_resource_UL_t *)0;
+    available_resource_UL->singletone3_Head = (available_resource_UL_t *)0;
+
+	available_resource_UL->sixtone_end_subframe = 0;
+	available_resource_UL->threetone_end_subframe = 0;
+	available_resource_UL->singletone1_end_subframe = 0;
+	available_resource_UL->singletone2_end_subframe = 0;
+	available_resource_UL->singletone3_end_subframe = 0;
+	
+	add_UL_Resource();
+	add_UL_Resource();
+	
+    printf("Initialization of the UL Resource grid has been done\n");
+}
+
+//	extend subframe align to si-period
+void extend_available_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int max_subframe){	//	assume max_subframe is found.
+    
+	available_resource_DL_t *pt, *new_node;
+	//int temp;
+	uint32_t i, i_div_si_window;
+	//uint32_t si_period_div_window;
+	pt = available_resource_DL;
+    
+    printf("%d %d\n", max_subframe, mac_inst->schedule_subframe_DL);
+    
+	if(max_subframe > mac_inst->schedule_subframe_DL){
+		//	align to si-period
+
+		max_subframe = ((max_subframe%mac_inst->rrc_config.si_window_length)==0)? max_subframe : (((max_subframe/mac_inst->rrc_config.si_window_length)+1)*mac_inst->rrc_config.si_window_length);
+		printf("max %d last->end %p\n", max_subframe, available_resource_DL_last);
+		if(mac_inst->schedule_subframe_DL == available_resource_DL_last->end_subframe){
+			available_resource_DL_last->end_subframe = max_subframe;
+			//available_resource_DL_last->DLSF_num += calculate_DLSF(mac_inst, mac_inst->schedule_subframe_DL+1, max_subframe);
+		}else{
+			new_node = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
+
+			available_resource_DL_last->next = new_node;
+			new_node->start_subframe = mac_inst->schedule_subframe_DL+1;
+			new_node->end_subframe = max_subframe;
+			new_node->next = (available_resource_DL_t *)0;
+			//new_node->DLSF_num = calculate_DLSF(mac_inst, mac_inst->schedule_subframe_DL+1, max_subframe);
+		}
+
+		//	do schedule sibs after extend.
+		for(i=mac_inst->schedule_subframe_DL;i<max_subframe;i+=mac_inst->rrc_config.si_window_length){
+			i_div_si_window = i / mac_inst->rrc_config.si_window_length;
+			if(-1 != mac_inst->sibs_table[i_div_si_window]){
+				printf("[sibs%d] %d\n", mac_inst->sibs_table[i_div_si_window], i);
+				schedule_sibs_NB_IoT(mac_inst, mac_inst->sibs_table[i_div_si_window], i);
+			}
+		}
+
+		mac_inst->schedule_subframe_DL = max_subframe;
+	}
+	return ;
+}
+
+
+void fill_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, available_resource_DL_t *node, int start_subframe, int end_subframe, schedule_result_t *new_node){
+	available_resource_DL_t *temp;
+	schedule_result_t *iterator, *temp1;
+	//	divided into two node
+	//	keep one node(align left or right)
+	//	delete node
+
+	int align_left = (node->start_subframe==start_subframe)||(calculate_DLSF(mac_inst, node->start_subframe, start_subframe-1) == 0);
+	int align_right = (end_subframe==node->end_subframe)||(calculate_DLSF(mac_inst, end_subframe+1, node->end_subframe) == 0);
+	//print_available_resource_DL();
+	//DEBUG("[debug] align : %d %d\n", align_left, align_right);
+	switch(align_left+align_right){
+		case 0:
+			//	divided into two node
+			//	A | node | B
+			//	A | temp | node | B
+			temp = (available_resource_DL_t *)malloc(sizeof(available_resource_DL_t));
+			if(node->prev){
+				node->prev->next = temp;
+			}else{
+				available_resource_DL = temp;
+			}
+			temp->prev = node->prev;
+			temp->next = node;
+			node->prev = temp;
+			//node->next don't need to change
+
+			temp->start_subframe = node->start_subframe;
+			temp->end_subframe = start_subframe - 1;
+
+			node->start_subframe = end_subframe + 1;
+
+			node->DLSF_num = calculate_DLSF(mac_inst, node->start_subframe, node->end_subframe);
+			temp->DLSF_num = calculate_DLSF(mac_inst, temp->start_subframe, temp->end_subframe);
+			break;
+		case 1:
+			//	keep one node
+			if(align_left){
+				node->start_subframe = end_subframe + 1 ;
+			}else{
+				node->end_subframe = start_subframe - 1 ;
+			}
+
+			node->DLSF_num = calculate_DLSF(mac_inst, node->start_subframe, node->end_subframe);
+			break;
+		case 2:
+			//	delete
+			if(node->next){
+			    node->next->prev = node->prev;
+            }else{
+                available_resource_DL_last = node->prev;
+            }
+				
+			if(node->prev){
+				node->prev->next = node->next;
+			}else{
+				available_resource_DL = node->next;
+			}
+
+			free(node);
+			break;
+		default:
+			//error
+			break;
+	}
+	
+	//	new node allocate from up-layer calling function.
+	iterator = schedule_result_list_DL;
+    temp1 = (schedule_result_t *)0;
+	if((schedule_result_t *)0 == schedule_result_list_DL){
+		schedule_result_list_DL = new_node;
+	}else{
+		while((schedule_result_t *)0 != iterator){
+			if(start_subframe < iterator->output_subframe){
+				break;
+			}
+			temp1 = iterator;
+			iterator = iterator->next;
+		}
+		if((schedule_result_t *)0 == iterator){
+			temp1->next = new_node;
+		}else{
+			new_node->next = iterator;
+			if(temp1){
+				temp1->next = new_node;
+			}else{
+				schedule_result_list_DL = new_node;
+			}
+		}
+	}
+}
+
+available_resource_DL_t *check_sibs_resource(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t check_start_subframe, uint32_t check_end_subframe, uint32_t num_subframe, uint32_t *residual_subframe, uint32_t *out_last_subframe, uint32_t *out_first_subframe){
+	available_resource_DL_t *pt;
+	uint32_t num_dlsf;
+	uint8_t output = 0x0;
+	pt = available_resource_DL;
+	//	TODO find the pt which can cover part of check_start_subframe, e.g. 1280-> 1281-1440
+	while((available_resource_DL_t *)0 != pt){
+		if(pt->start_subframe <= check_start_subframe && pt->end_subframe >= check_start_subframe){
+			break;
+		}
+		pt = pt->next;
+	}
+	//print_available_resource_DL();
+	//DEBUG("sibs %d", check_start_subframe);
+	if((available_resource_DL_t *)0 == pt){
+		return (available_resource_DL_t *)0;
+	}
+	
+	num_dlsf = calculate_DLSF(mac_inst, check_start_subframe, pt->end_subframe);
+
+	if((available_resource_DL_t *)0 == pt){
+		return (available_resource_DL_t *)0;
+	}else{
+
+		if(num_subframe <= num_dlsf){
+
+			while(num_subframe>0){
+				if(is_dlsf(mac_inst, check_start_subframe)){
+					--num_subframe;
+					if(output == 0x0){
+						*out_first_subframe = check_start_subframe;
+						output = 0x1;
+					}
+				}
+				if(num_subframe==0||check_start_subframe>=check_end_subframe){
+					break;
+				}else{
+					++check_start_subframe;
+				}
+			}
+
+			*residual_subframe = num_subframe;
+			*out_last_subframe = check_start_subframe;
+
+		}else{
+			if(num_dlsf == 0){
+				return (available_resource_DL_t *)0;
+			}else{
+				while(!is_dlsf(mac_inst, check_start_subframe)){
+					++check_start_subframe;
+				}
+				*out_first_subframe = check_start_subframe;
+			}
+			*residual_subframe = num_subframe - num_dlsf;
+			*out_last_subframe = pt->end_subframe;
+		}
+		return pt;
+	}
+}
+
+
+uint32_t calculate_DLSF(eNB_MAC_INST_NB_IoT *mac_inst, int abs_start_subframe, int abs_end_subframe){
+	int i;
+	int num_dlsf=0;
+	//int diff_subframe = abs_end_subframe - abs_start_subframe;
+
+	int start_frame = abs_start_subframe / 10;
+	int end_frame = abs_end_subframe / 10;
+	int start_subframe = abs_start_subframe % 10;
+	int end_subframe = abs_end_subframe % 10;
+
+	int start_frame_mod_64 = start_frame & 0x0000003f;
+	int end_frame_mod_64 = end_frame & 0x0000003f;
+	int start_frame_div_64 = (start_frame & 0xffffffc0)>>6;
+	int end_frame_div_64 = (end_frame & 0xffffffc0)>>6;
+
+	if(start_frame > end_frame){
+		return calculate_DLSF(mac_inst, abs_start_subframe, MAX_FRAME*10+9) + calculate_DLSF(mac_inst, 0, abs_end_subframe);
+	}
+	if(start_frame_div_64==end_frame_div_64 && start_frame==end_frame){
+	    for(i=abs_start_subframe;i<=abs_end_subframe;++i){
+			num_dlsf += is_dlsf(mac_inst, i);
+		}
+	}else{
+	    num_dlsf = mac_inst->dlsf_table[end_frame_mod_64];
+		num_dlsf -= (start_frame_mod_64==0)?0:mac_inst->dlsf_table[start_frame_mod_64-1];
+		for(i=0;i<start_subframe;++i, --abs_start_subframe){
+			num_dlsf -= is_dlsf(mac_inst, abs_start_subframe-1);
+		}
+		for(i=end_subframe;i<9;++i, ++abs_end_subframe){
+			num_dlsf -= is_dlsf(mac_inst, abs_end_subframe+1);
+		}
+	    if(start_frame_div_64!=end_frame_div_64){
+	        num_dlsf+= (472+(end_frame_div_64-start_frame_div_64-1)*472);
+        }
+    }
+	return num_dlsf;
+}
+
+
+void maintain_available_resource(eNB_MAC_INST_NB_IoT *mac_inst){
+
+	available_resource_DL_t *pfree;
+
+	if(mac_inst->current_subframe >= available_resource_DL->end_subframe){
+	    //DEBUG("[maintain before kill]=====t:%d=end:%d====%p\n", mac_inst->current_subframe, available_resource_DL->end_subframe, available_resource_DL->next);
+		//print_available_resource_DL();
+		
+        pfree = available_resource_DL;
+		available_resource_DL = available_resource_DL->next;
+		available_resource_DL->prev = (available_resource_DL_t *)0;
+		free((available_resource_DL_t *)pfree);
+		//DEBUG("[maintain after kill]=====t:%d=====\n", mac_inst->current_subframe);
+		//print_available_resource_DL();
+	}else{
+		available_resource_DL->start_subframe = mac_inst->current_subframe;
+	}
+
+	return ;
+}
+
+//	check_subframe must be DLSF, you can use is_dlsf() to check before call function
+available_resource_DL_t *check_resource_DL(eNB_MAC_INST_NB_IoT *mac_inst, int check_subframe, int num_subframes, int *out_last_subframe, int *out_first_subframe){
+	available_resource_DL_t *pt;
+	pt = available_resource_DL;
+	int end_subframe = check_subframe + num_subframes - 1;
+	int diff_gap;
+
+	while((available_resource_DL_t *)0 != pt){
+		if(pt->start_subframe <= check_subframe && pt->end_subframe >= check_subframe){
+			break;
+		}
+		pt = pt->next;
+	}
+
+	if((available_resource_DL_t *)0 == pt){
+		return (available_resource_DL_t *)0;
+	}else{
+		if(num_subframes <= calculate_DLSF(mac_inst, check_subframe, pt->end_subframe)){
+
+			diff_gap = num_subframes - calculate_DLSF(mac_inst, check_subframe, end_subframe);
+
+			while(diff_gap){
+				++end_subframe;
+				if(is_dlsf(mac_inst, end_subframe)){
+					--diff_gap;
+				}
+			}
+			*out_last_subframe = end_subframe;
+			while(!is_dlsf(mac_inst, check_subframe)){
+				++check_subframe;
+			}
+			*out_first_subframe = check_subframe;
+			return pt;
+		}else{
+			return (available_resource_DL_t *)0;
+		}
+	}
+}
+
+int get_I_TBS_NB_IoT(int x,int y)
+{
+    int I_TBS = 0;
+    if(y==1) I_TBS=x;
+    else
+    {
+        if(x==1)    I_TBS=2;
+        else if(x==2)   I_TBS=1;
+        else
+        {
+            I_TBS=x;
+        }
+    }
+    return I_TBS;
+}
+
+
+int get_TBS_UL_NB_IoT(uint32_t mcs,uint32_t multi_tone,int Iru)
+{
+    int TBS;
+    uint32_t I_TBS=get_I_TBS_NB_IoT(mcs,multi_tone);
+    TBS=UL_TBS_Table[I_TBS][Iru];
+    //if((TBS==0)||(Iru>7))
+    //{
+        //--Iru;
+    //}
+    //TBS=UL_TBS_Table[I_TBS][Iru];
+
+    return TBS>>3;
+}
+
+void insert_schedule_result(schedule_result_t **list, int subframe, schedule_result_t *node){
+	schedule_result_t *tmp, *tmp1;
+	if((schedule_result_t *)0 == *list){
+            *list = node;
+        }else{
+            tmp = *list;
+            tmp1 = (schedule_result_t *)0;
+            while((schedule_result_t *)0 != tmp){
+                if(subframe < tmp->output_subframe){
+                    break;
+                }
+                tmp1 = tmp;
+                tmp = tmp->next;
+            }
+            if((schedule_result_t *)0 == tmp){
+                tmp1->next = node;
+            }else{
+		node->next = tmp;
+		if(tmp1){
+			tmp1->next = node;
+		}else{
+			*list = node;
+		}
+            }
+        }
+}
+
+void print_available_resource_DL(void){
+	available_resource_DL_t *pt;
+	pt = available_resource_DL;
+	int i=0;
+	printf("=== print available resource ===\n");
+	while(pt){
+		printf("[%2d] %p %3d-%3d\n", i, pt, pt->start_subframe, pt->end_subframe);
+		pt = pt->next;
+	}
+}
+
+/*Get MCS index*/
+uint32_t get_I_mcs_NB_IoT(int CE_level)
+{
+	if(CE_level==0)
+	{
+		return 13;
+	}
+	else if(CE_level==1)
+	{
+		return 8;
+	}
+	else
+	{
+		return 2;
+	}
+}
+
+uint32_t get_tbs(uint32_t data_size, uint32_t I_tbs, uint32_t *I_sf)
+{
+	for((*I_sf)=0;(*I_sf)<8;++(*I_sf))
+	{
+		//DEBUG("[get_tbs]TBS %d SF index %d\n", MAC_TBStable_NB_IoT[I_tbs][(*I_sf)], *I_sf);
+		if(MAC_TBStable_NB_IoT[I_tbs][(*I_sf)]>=data_size*8)
+		{
+			return MAC_TBStable_NB_IoT[I_tbs][(*I_sf)]/8;
+		}
+	}
+	printf("error\n");
+	return 0;
+}
+
+uint32_t get_num_sf(uint32_t I_sf)
+{
+	if(I_sf==6)
+	{
+		return 8;
+	}
+	else if(I_sf==7)
+	{
+		return 10;
+	}
+	else
+	{
+		return I_sf+1;
+	}
+}
+
+uint16_t find_suit_i_delay(uint32_t rmax, uint32_t r, uint32_t dci_candidate){
+    uint32_t i;
+	uint32_t num_candidates = rmax / r;
+	uint32_t left_candidates = num_candidates - dci_candidate - 1;	// 0-7
+	uint32_t resource_gap = left_candidates * r;
+	resource_gap = ((resource_gap * 10)>>3);	//	x1.125
+	for(i=0;i<8;++i){
+		if(resource_gap <= get_scheduling_delay(i, rmax)){
+			return i;
+		}
+	}
+	return 0;
+}
+
+uint32_t get_scheduling_delay(uint32_t I_delay, uint32_t R_max)
+{
+	if(I_delay==0)
+	{
+		return 0;
+	}
+	else
+	{
+		if(R_max<128)
+		{
+			if(I_delay<=4)
+				return 4*I_delay;
+			else
+				return (uint32_t)(2<<I_delay);//pow(2, I_delay);
+		}
+		else
+		{
+			return (uint32_t)(16<<(I_delay-1));//*pow(2, I_delay-1);
+		}
+	}
+}
+
+/*Subcarrier_spacing 0:3.75kHz \ 1 : 15kHz*/
+uint32_t get_HARQ_delay(int subcarrier_spacing, uint32_t HARQ_delay_index)
+{
+	if(subcarrier_spacing==1)
+	{
+		if(HARQ_delay_index==0)
+			return 13;
+		else if(HARQ_delay_index==1)
+			return 15;
+		else if(HARQ_delay_index==2)
+			return 17;
+		else
+			return 18;
+	}
+	else
+	{
+		if((HARQ_delay_index==0)&&(HARQ_delay_index==1))
+			return 13;
+		else
+			return 21;
+	}
+}
+
+int get_resource_field_value(int subcarrier, int k0)
+{
+    int value = 0;
+    if (k0 == 13)
+        value = subcarrier;
+    else if (k0 == 15)
+        value = subcarrier + 4;
+    else if (k0 == 17)
+        value = subcarrier + 8;
+    else if (k0 == 18)
+        value = subcarrier + 12;
+
+    return value;
+}
+
+//Transfrom source into hyperSF, Frame, Subframe format
+void convert_system_number(uint32_t source_sf,uint32_t *hyperSF, uint32_t *frame, uint32_t *subframe)
+{
+	*hyperSF = (source_sf/10)/1024;
+	*frame = (source_sf/10)%1024;
+	*subframe = (source_sf%1024)%10;
+}
+
+uint32_t get_max_tbs(uint32_t I_tbs)
+{
+	return MAC_TBStable_NB_IoT[I_tbs][7]/8;
+}
+
+//convert hyperSF, Frame, Subframe format into subframe unit
+uint32_t convert_system_number_sf(uint32_t hyperSF, uint32_t frame, uint32_t subframe)
+{
+	return hyperSF*1024*10+frame*10+subframe;
+}
+
+/*input start position amd num_dlsf DL subframe, caculate the last subframe number*/
+uint32_t cal_num_dlsf(eNB_MAC_INST_NB_IoT *mac_inst, uint32_t hyperSF, uint32_t frame, uint32_t subframe, uint32_t* hyperSF_result, uint32_t* frame_result, uint32_t* subframe_result, uint32_t num_dlsf_require)
+{
+  uint16_t sf_dlsf_index;
+  uint16_t dlsf_num_temp;
+  uint32_t abs_sf_start = 0;
+  uint32_t abs_sf_end = 0;
+  uint8_t period_count=0;
+  uint8_t shift_flag=0;
+  uint8_t scale_flag=0;
+
+  abs_sf_start=convert_system_number_sf(hyperSF, frame, subframe);
+  sf_dlsf_index = abs_sf_start%2560%(mac_inst->sib1_period*10);
+  dlsf_num_temp = DLSF_information.sf_to_dlsf_table[sf_dlsf_index];
+  //DEBUG("[cal_num_dlsf]sf_dlsf_index %d dlsf_num_temp %d\n", sf_dlsf_index, dlsf_num_temp);
+
+  while(num_dlsf_require>DLSF_information.num_dlsf_per_period)
+  {
+    period_count++;
+    num_dlsf_require-=DLSF_information.num_dlsf_per_period;
+  }
+  abs_sf_end = abs_sf_start+period_count*mac_inst->sib1_period*10;
+  //DEBUG("[cal_num_dlsf]abs_sf_end %d after loop\n", abs_sf_end);
+  if(num_dlsf_require>DLSF_information.num_dlsf_per_period-dlsf_num_temp+1)
+  {
+    if(is_dlsf(mac_inst, sf_dlsf_index)==1)
+    {
+      num_dlsf_require-=DLSF_information.num_dlsf_per_period-dlsf_num_temp+1;
+    }
+    else
+    {
+      num_dlsf_require-=DLSF_information.num_dlsf_per_period-dlsf_num_temp;
+    }
+    abs_sf_end+=mac_inst->sib1_period*10-abs_sf_end%(mac_inst->sib1_period*10);
+    dlsf_num_temp = 0;
+    scale_flag = 1;
+    //DEBUG("[cal_num_dlsf]abs_sf_end %d after scale\n", abs_sf_end);
+  }
+  //DEBUG("[cal_num_dlsf]num_dlsf_require remain %d\n", num_dlsf_require);
+
+  if(num_dlsf_require!=0)
+  {
+    if(scale_flag!=1)
+    {
+      if(is_dlsf(mac_inst, abs_sf_end)==1)
+      {
+        shift_flag = 1;
+      }
+    }
+    if(abs_sf_end%(mac_inst->sib1_period*10)!=0)
+    {
+      abs_sf_end-=abs_sf_end%(mac_inst->sib1_period*10);
+      //DEBUG("[cal_num_dlsf] abs_sf_end is %d mod period =  %d\n", abs_sf_end, abs_sf_end%(mac_inst->sib1_NB_IoT_sched_config.sib1_period*10));
+    }
+    if(shift_flag==1)
+    {
+      abs_sf_end +=DLSF_information.dlsf_to_sf_table[dlsf_num_temp+num_dlsf_require-2];
+    }
+    else
+    {
+      abs_sf_end +=DLSF_information.dlsf_to_sf_table[dlsf_num_temp+num_dlsf_require-1];
+    }
+
+    //DEBUG("[cal_num_dlsf]2 DLSF_information.dlsf_to_sf_table = %d dlsf index %d\n", DLSF_information.dlsf_to_sf_table[num_dlsf_require], num_dlsf_require);
+  }
+  //DEBUG("[cal_num_dlsf]abs_sf_end %d\n", abs_sf_end);
+  convert_system_number(abs_sf_end, hyperSF_result, frame_result, subframe_result);
+  //DEBUG("[cal_num_dlsf]h %d f %d end %d\n", *hyperSF_result, *frame_result, *subframe_result);
+  return abs_sf_end;
+}
+
+int get_N_REP(int CE_level)
+{
+    int N_rep= 0;
+    if(CE_level == 0)
+    {
+        N_rep = (nprach_list)->numRepetitionsPerPreambleAttempt;
+    }else if (CE_level == 1)
+    {
+        N_rep = (nprach_list+1)->numRepetitionsPerPreambleAttempt;
+    }else if (CE_level == 2)
+    {
+        N_rep = (nprach_list+2)->numRepetitionsPerPreambleAttempt;
+    }else
+    {
+        printf("unknown CE level!\n");
+        return -1;
+    }
+
+    return N_rep;
+}
+
+int get_I_REP(int N_rep)
+{
+    int i;
+    for(i = 0; i < 8;i++)
+        {
+            if(N_rep == rachrepeat[i])
+                return i;
+        }
+    printf("unknown repetition value!\n");
+    return -1;
+}
+
+int get_DCI_REP(uint32_t R,uint32_t R_max)
+{
+    int value = -1;
+    if (R_max == 1)
+    {
+        if(R == 1)
+        {
+            value =0;
+        }
+
+    }else if (R_max == 2)
+    {
+        if(R == 1)
+            value = 0;
+        if(R == 2)
+            value = 1;
+     }else if (R_max == 4)
+     {
+        if(R == 1)
+            value = 0;
+        if(R == 2)
+            value = 1;
+        if(R == 4)
+            value = 2;
+     }else if (R_max >= 8)
+     {
+        if(R == R_max/8)
+            value = 0;
+        if(R == R_max/4)
+            value = 1;
+        if(R == R_max/2)
+            value = 2;
+        if(R == R_max)
+            value = 3;
+     }
+     return value;
+}
+
+void print_available_UL_resource(void){
+
+    int sixtone_num=0;
+    int threetone_num=0;
+    int singletone1_num=0;
+    int singletone2_num=0;
+    int singletone3_num=0;
+
+    available_resource_UL_t *available_resource;
+
+    ///sixtone
+    available_resource = available_resource_UL->sixtone_Head;
+
+    while(available_resource!=NULL)
+    {
+        sixtone_num++;
+        printf("[sixtone][Node %d] start %d , end %d\n",sixtone_num,available_resource->start_subframe,available_resource->end_subframe);
+        available_resource = available_resource->next;
+    }
+
+    ///threetone
+    available_resource = available_resource_UL->threetone_Head;
+
+    while(available_resource!=NULL)
+    {
+        threetone_num++;
+        printf("[threetone][Node %d] start %d, end %d\n",threetone_num,available_resource->start_subframe,available_resource->end_subframe);
+        available_resource = available_resource->next;
+    }
+
+    ///singletone1
+    available_resource = available_resource_UL->singletone1_Head;
+
+    while(available_resource!=NULL)
+    {
+        singletone1_num++;
+        printf("[singletone1][Node %d] start %d, end %d\n",singletone1_num,available_resource->start_subframe,available_resource->end_subframe);
+        available_resource = available_resource->next;
+    }
+
+    ///singletone1
+    available_resource = available_resource_UL->singletone2_Head;
+
+    while(available_resource!=NULL)
+    {
+        singletone2_num++;
+        printf("[singletone2][Node %d] start %d, end %d\n",singletone2_num,available_resource->start_subframe,available_resource->end_subframe);
+        available_resource = available_resource->next;
+    }
+
+    ///singletone1
+    available_resource = available_resource_UL->singletone3_Head;
+
+    while(available_resource!=NULL)
+    {
+        singletone3_num++;
+        printf("[singletone3][Node %d] start %d, end %d\n",singletone3_num,available_resource->start_subframe,available_resource->end_subframe);
+        available_resource = available_resource->next;
+    }
+
+}
+
+//  maybe we can try to use hash table to enhance searching time.
+UE_TEMPLATE_NB_IoT *get_ue_from_rnti(eNB_MAC_INST_NB_IoT *inst, rnti_t rnti){
+  uint32_t i;
+  for(i=0; i<MAX_NUMBER_OF_UE_MAX_NB_IoT; ++i){
+    if(inst->UE_list_spec->UE_template_NB_IoT[i].active == 1){
+      if(inst->UE_list_spec->UE_template_NB_IoT[i].rnti == rnti){
+        return &inst->UE_list_spec->UE_template_NB_IoT[i];
+      }
+    }
+  }
+  return (UE_TEMPLATE_NB_IoT *)0;
+}
\ No newline at end of file
diff --git a/openair2/LAYER2/MAC/vars.h b/openair2/LAYER2/MAC/vars.h
index f125395a34a11eeb3429e0c622f7ce433142ddaa..419ade1b45faee9cff0219dd38ab845029086222 100644
--- a/openair2/LAYER2/MAC/vars.h
+++ b/openair2/LAYER2/MAC/vars.h
@@ -37,12 +37,10 @@
 #endif //USER_MODE
 #include "PHY/defs.h"
 #include "defs.h"
-#include "defs_nb_iot.h"
+#include "defs_NB_IoT.h"
 #include "PHY_INTERFACE/defs.h"
 #include "COMMON/mac_rrc_primitives.h"
 
-//NB-IoT
-eNB_MAC_INST_NB *eNB_mac_inst_NB;
 
 const uint32_t BSR_TABLE[BSR_TABLE_SIZE]= {0,10,12,14,17,19,22,26,31,36,42,49,57,67,78,91,
                                            105,125,146,171,200,234,274,321,376,440,515,603,706,826,967,1132,
@@ -102,9 +100,6 @@ MAC_RLC_XFACE *Mac_rlc_xface;
 /// Primary component carrier index of eNB
 int pCC_id[NUMBER_OF_eNB_MAX];
 
-//NB-IoT
-eNB_MAC_INST_NB *eNB_mac_inst_NB;
-
 
 eNB_ULSCH_INFO eNB_ulsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8
 eNB_DLSCH_INFO eNB_dlsch_info[NUMBER_OF_eNB_MAX][MAX_NUM_CCs][NUMBER_OF_UE_MAX]; // eNBxUE = 8x8
@@ -156,6 +151,8 @@ DCI2_5MHz_2A_TDD_t DLSCH_alloc_pdu2;
 
 DCI1E_5MHz_2A_M10PRB_TDD_t DLSCH_alloc_pdu1E;
 
+
+
 #endif
 
 
diff --git a/openair2/LAYER2/MAC/vars_NB_IoT.h b/openair2/LAYER2/MAC/vars_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..b4b805d50bb1e6da13a2ce804317f64ab7d16b41
--- /dev/null
+++ b/openair2/LAYER2/MAC/vars_NB_IoT.h
@@ -0,0 +1,120 @@
+
+/*! \file vars_NB_IoT.h
+ * \brief declare the MAC global variables
+ * \author  NTUST BMW Lab./
+ * \date 2017
+ * \email: 
+ * \version 1.0
+ *
+ */
+
+
+#ifndef __MAC_VARS_NB_IOT_H__
+#define __MAC_VARS_NB_IOT_H__
+#ifdef USER_MODE
+//#include "stdio.h"
+#endif //USER_MODE
+//#include "PHY/defs.h"
+//#include "defs.h"
+#include "LAYER2/MAC/defs_NB_IoT.h"
+//#include "PHY_INTERFACE/defs.h"
+//#include "COMMON/mac_rrc_primitives.h"
+
+
+IF_Module_t *if_inst;
+
+//NB-IoT--------------------------------------
+eNB_MAC_INST_NB_IoT *mac_inst;
+
+//BCCH_BCH_Message_NB_t               MIB;
+//BCCH_DL_SCH_Message_NB_t            SIB;
+//RRCConnectionSetup_NB_r13_IEs_t     DED_Config;
+schedule_result_t *schedule_result_list_UL;
+schedule_result_t *schedule_result_list_DL;
+available_resource_DL_t *available_resource_DL;
+available_resource_tones_UL_t *available_resource_UL;
+available_resource_DL_t *available_resource_DL_last;
+//should be utilized in: schedule_RA_NB_IoT,rx_sdu_NB_IoT, mac_top_init_NB_IoT,
+uint8_t Is_rrc_registered_NB_IoT;
+
+// array will be active when they are used
+
+// 10 -> single-tone / 12 -> multi-tone
+const uint32_t max_mcs[2] = {10, 12};
+
+// [CE level] [0 - 3] -> single-tone / [CE level] [4-7] -> multi-tone
+const uint32_t mapped_mcs[3][8]={{1,5,9,10,3,7,11,12},
+                            {0,3,7,10,3,7,11,12},
+                            {0,2,6,10,0,4,8,12}};
+
+//TBS table for NPUSCH transmission TS 36.213 v14.2 table Table 16.5.1.2-2:
+const int UL_TBS_Table[14][8]=
+{
+  {16,2,56,88,120,152,208,256},
+  {24,56,88,144,176,208,256,344},
+  {32,72,144,176,208,256,328,424},
+  {40,104,176,208,256,328,440,568},
+  {56,120,208,256,328,408,552,680},
+  {72,144,224,328,424,504,680,872},
+  {88,176,256,392,504,600,808,1000},
+  {104,224,328,472,584,712,1000,1224},
+  {120,256,392,536,680,808,1096,1384},
+  {136,296,456,616,776,936,1256,1544},
+  {144,328,504,680,872,1000,1384,1736},
+  {176,376,584,776,1000,1192,1608,2024},
+  {208,440,680,1000,1128,1352,1800,2280},
+  {224,488,744,1128,1256,1544,2024,2536}
+};
+
+const int rachperiod[8]={40,80,160,240,320,640,1280,2560};
+const int rachstart[8]={8,16,32,64,128,256,512,1024};
+const int rachrepeat[8]={1,2,4,8,16,32,64,128};
+const int rachscofst[7]={0,12,24,36,2,18,34};
+const int rachnumsc[4]={12,24,36,48};
+
+const uint32_t RU_table[8]={1,2,3,4,5,6,8,10};
+
+const uint32_t scheduling_delay[4]={8,16,32,64};
+const uint32_t msg3_scheduling_delay_table[4] = {12,16,32,64};
+
+const uint32_t ack_nack_delay[4]={13,15,17,18};
+const uint32_t R_dl_table[16]={1,2,4,8,16,32,64,128,192,256,384,512,768,1024,1536,2048};
+
+// TBS table for the case not containing SIB1-NB_IoT, Table 16.4.1.5.1-1 in TS 36.213 v14.2
+const uint32_t MAC_TBStable_NB_IoT[14][8] ={ //[ITBS][ISF]
+  {16,32,56,88,120.152,208,256},
+  {24,56,88,144,176,208,256,344},
+  {32,72,144,176,208,256,328,424},
+  {40,104,176,208,256,328,440,568},
+  {56,120,208,256,328,408,552,680},
+  {72,144,244,328,424,504,680,872},
+  {88,176,256,392,504,600,808,1032},
+  {104,224,328,472,584,680,968,1224},
+  {120,256,392,536,680,808,1096,1352},
+  {136,296,456,616,776,936,1256,1544},
+  {144,328,504,680,872,1032,1384,1736},
+  {176,376,584,776,1000,1192,1608,2024},
+  {208,440,680,904,1128,1352,1800,2280},
+  {224,488,744,1128,1256,1544,2024,2536}
+};
+
+//TBS table for the case containing S1B1-NB_IoT, Table 16.4.1.5.2-1 in TS 36.213 v14.2 (Itbs = 12 ~ 15 is reserved field
+//mapping ITBS to SIB1-NB_IoT
+const unsigned int MAC_TBStable_NB_IoT_SIB1[16] = {208,208,208,328,328,328,440,440,440,680,680,680};
+
+const int DV_table[16]={0,10,14,19,26,36,49,67,91,125,171,234,321,768,1500,1500};
+
+const int BSR_table[64]= {0,10,12,14,17,19,22,26,31,36,42,49,57,67,78,91,
+                           105,125,146,171,200,234,274,321,376,440,515,603,706,826,967,1132,
+                           1326,1552,1817,2127,2490,2915,3413,3995,4677,5467,6411,7505,8787,10287,12043,14099,
+                           16507,19325,22624,26487,31009,36304,42502,49759,58255,68201,79846,93479,109439,128125,150000,300000
+                           };
+
+const int dl_rep[3] = {1, 2, 4};
+const uint32_t dci_rep[3] = {1, 2, 4};
+const uint32_t harq_rep[3] = {1, 2, 4};
+
+
+#endif
+
+
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
index ab5058b92436ba808c6c9466a7e9c5b2c180a5fb..ce67b37a02e5a9e9d705a4bbb0ac3a746f60912e 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.c
@@ -69,6 +69,15 @@ extern int otg_enabled;
 #endif
 
 
+#ifdef NB_IOT
+#include "openair2/RRC/LITE/proto_NB_IoT.h"
+#undef maxDRB
+#define maxDRB maxDRB_NB_r13
+#endif
+
+
+
+
 //-----------------------------------------------------------------------------
 /*
  * If PDCP_UNIT_TEST is set here then data flow between PDCP and RLC is broken
@@ -1669,9 +1678,9 @@ pdcp_config_set_security(
 	  pdcp_pP->integrityProtAlgorithm,
 	  ctxt_pP->rnti);
   }
-  /*particular case activated by SecurityModeFailure*/
+  /*]SecurityModeFailure*/
   else if(security_modeP == -1){
-	  // in this way in NB_pdcp_data_req function you never call "pdcp_apply_security"
+	  // in this way in pdcp_data_req_NB_IoT function you never call "pdcp_apply_security"
 	  // and we never call pdcp_validate_security in NB_pdcp_data_indi
 	    	pdcp_pP->security_activated = 0;
 	    	pdcp_pP->cipheringAlgorithm = 0;
@@ -1972,6 +1981,7 @@ void pdcp_layer_init(void)
   memset(Pdcp_stats_rx_rate, 0, sizeof(Pdcp_stats_rx_rate));
 }
 
+
 //-----------------------------------------------------------------------------
 void pdcp_layer_cleanup (void)
 //-----------------------------------------------------------------------------
diff --git a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
index 94084273d15b5254859875c0bb8aa4975eb40c5d..ad9a6a4f4a24703c6f6d3e38a5f8fb09d74ef14a 100644
--- a/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
+++ b/openair2/LAYER2/PDCP_v10.1.0/pdcp.h
@@ -375,6 +375,12 @@ protected_pdcp_fifo(int pdcp_fifo_read_input_sdus                 (
 protected_pdcp_fifo(void pdcp_fifo_read_input_sdus_from_otg       (
                       const protocol_ctxt_t* const  ctxt_pP);)
 
+//NB-IoT
+public_pdcp(void pdcp_layer_init_NB_IoT(void);)
+
+
+
+
 //-----------------------------------------------------------------------------
 
 /*
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h
index de201db22917fb28ae709b9dba2f7adaf8180835..c3e5de7e01fb745d7f787484012b4118f5f403a7 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_entity.h
@@ -134,7 +134,16 @@ typedef struct rlc_am_entity_s {
   uint16_t           max_retx_threshold; /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to limit the number of retransmissions of an AMD PDU. */
   uint16_t           poll_pdu;           /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollPDU PDUs. */
   uint32_t           poll_byte;          /*!< \brief This parameter is used by the transmitting side of each AM RLC entity to trigger a poll for every pollByte bytes. */
-  uint16_t	     enableStatusReportSN_Gap;
+
+  //----------------------------------------------------
+  // NB-IOT RLC Parameters
+  //----------------------------------------------------
+
+  //DL-AM-RLC Config NB-IoT parameter
+  uint32_t      *enableStatusReportSN_Gap_NB_IoT;
+  //UL-AM-RLC Config. NB-IoT parameter
+  uint16_t       max_retx_threshold_NB_IoT;
+  rlc_am_timer_t t_poll_retransmit_NB_IoT; //TIMER
 
   //---------------------------------------------------------------------
   // STATISTICS
diff --git a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
index 14217fc94cb04905a17f25d7510a1f64f0842daa..bb0bca234614b642aee7a316ff708c4a7ad0999d 100644
--- a/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
+++ b/openair2/LAYER2/RLC/AM_v9.3.0/rlc_am_init.h
@@ -71,10 +71,12 @@ typedef volatile struct {
 } rlc_am_info_t;
 
 typedef volatile struct {
-uint16_t max_retx_threshold;
-uint32_t t_poll_retransmit;
-uint32_t enableStatusReportSN_Gap;
-}rlc_am_info_NB_t;
+//UL-AM-RLC Configurations
+uint16_t max_retx_threshold_NB_IoT;
+uint32_t t_poll_retransmit_NB_IoT;
+//DL-AM-RLC Configurations
+uint32_t* enableStatusReportSN_Gap_NB_IoT; /*OPTIONAL*/
+}rlc_am_info_NB_IoT_t;
 
 //-----------------------------------------------------------------------------
 /*! \fn void rlc_am_init   (const protocol_ctxt_t* const ctxtP, rlc_am_entity_t * const rlc_pP)
diff --git a/openair2/LAYER2/RLC/rlc.c b/openair2/LAYER2/RLC/rlc.c
index 7aca1b9cc63814012a46222ab554893957608ae8..846e70de1286f3bde087588554c3b5f0d2fc0c14 100644
--- a/openair2/LAYER2/RLC/rlc.c
+++ b/openair2/LAYER2/RLC/rlc.c
@@ -48,6 +48,13 @@ extern boolean_t pdcp_data_ind(
 //#define TRACE_RLC_PAYLOAD 1
 #define DEBUG_RLC_DATA_REQ 1
 
+#ifdef NB_IOT
+#include "openair2/RRC/LITE/proto_NB_IoT.h"
+#undef maxDRB
+#define maxDRB maxDRB_NB_r13
+#endif
+
+
 //-----------------------------------------------------------------------------
 void rlc_util_print_hex_octets(comp_name_t componentP, unsigned char* dataP, const signed long sizeP)
 //-----------------------------------------------------------------------------
@@ -613,6 +620,12 @@ rlc_module_init (void)
   rlc_rrc_data_ind  = NULL;
   rlc_rrc_data_conf = NULL;
 
+#ifdef NB_IOT
+  //MP: change variable maxDRB for NB-IoT --> see ifdef at the beginning
+  rlc_rrc_data_ind_NB_IoT = NULL;
+#endif
+
+
   rlc_coll_p = hashtable_create ((maxDRB + 2) * 16, NULL, rb_free_rlc_union);
   AssertFatal(rlc_coll_p != NULL, "UNRECOVERABLE error, RLC hashtable_create failed");
 
@@ -650,6 +663,8 @@ rlc_module_init (void)
 
   return(0);
 }
+//-----------------------------------------------------------------------------
+
 //-----------------------------------------------------------------------------
 void
 rlc_module_cleanup (void)
diff --git a/openair2/LAYER2/RLC/rlc.h b/openair2/LAYER2/RLC/rlc.h
index 6f759cb20790044ea712088e13d20cd841abd5d2..c329b43cc687e4bcb9b5e0c831183433d081dca4 100644
--- a/openair2/LAYER2/RLC/rlc.h
+++ b/openair2/LAYER2/RLC/rlc.h
@@ -137,7 +137,7 @@ typedef volatile struct {
   rlc_mode_t             rlc_mode;
   union {
     rlc_am_info_t              rlc_am_info; /*!< \sa rlc_am.h. */
-    rlc_am_info_NB_t		rlc_am_info_NB;
+    rlc_am_info_NB_IoT_t		   rlc_am_info_NB_IoT; //integrate NB-IoT
     rlc_tm_info_t              rlc_tm_info; /*!< \sa rlc_tm.h. */
     rlc_um_info_t              rlc_um_info; /*!< \sa rlc_um.h. */
   } rlc;
@@ -177,6 +177,8 @@ typedef struct {
 #define  RLC_MAX_MBMS_LC (maxSessionPerPMCH * maxServiceCount)
 #define  RLC_MAX_LC  ((max_val_DRB_Identity+1)* NUMBER_OF_UE_MAX)
 
+
+//pointer functions
 protected_rlc(void (*rlc_rrc_data_ind)(
                 const protocol_ctxt_t* const ctxtP,
                 const rb_id_t     rb_idP,
@@ -189,6 +191,7 @@ protected_rlc(void (*rlc_rrc_data_conf)(
                 const mui_t           muiP,
                 const rlc_tx_status_t statusP);)
 
+//define the type of the function that return void and take in input that parameters
 typedef void (rrc_data_ind_cb_t)(
   const protocol_ctxt_t* const ctxtP,
   const rb_id_t     rb_idP,
@@ -202,6 +205,28 @@ typedef void (rrc_data_conf_cb_t)(
   const rlc_tx_status_t statusP);
 
 
+//------------------------------------------------
+// NB-IoT (may this stuff are no more used)
+//------------------------------------------------
+//pointer functions
+protected_rlc(void (*rlc_rrc_data_ind_NB_IoT)(
+                const protocol_ctxt_t* const ctxtP,
+                const rb_id_t     rb_idP,
+                const sdu_size_t  sdu_sizeP,
+                const uint8_t   * const sduP,
+				const srb1bis_flag_t srb1bis_flag);)
+
+typedef void (rrc_data_ind_cb_NB_IoT_t)(
+  const protocol_ctxt_t* const ctxtP,
+  const rb_id_t     rb_idP,
+  const sdu_size_t  sdu_sizeP,
+  const uint8_t   * const sduP,
+  const srb1bis_flag_t srb1bis_flag);
+
+
+//------------------------------------------------
+
+
 /*! \struct  rlc_t
 * \brief Structure to be instanciated to allocate memory for RLC protocol instances.
 */
@@ -209,7 +234,7 @@ typedef struct rlc_union_s {
   rlc_mode_t           mode;
   union {
     rlc_am_entity_t  am;
-    rlc_um_entity_t  um;
+    rlc_um_entity_t  um; //not allowed for NB-IoT
     rlc_tm_entity_t  tm;
   } rlc;
 } rlc_union_t;
diff --git a/openair2/LAYER2/RLC/rlc_rrc.c b/openair2/LAYER2/RLC/rlc_rrc.c
index a45838603e324f9aa3adb0fc78e67f3a0adce011..41d479b8a4bad5849904828a23820e7ddb87cdda 100644
--- a/openair2/LAYER2/RLC/rlc_rrc.c
+++ b/openair2/LAYER2/RLC/rlc_rrc.c
@@ -800,6 +800,7 @@ rlc_op_status_t rrc_rlc_data_req     (
 void rrc_rlc_register_rrc (rrc_data_ind_cb_t rrc_data_indP, rrc_data_conf_cb_t rrc_data_confP)
 {
   //-----------------------------------------------------------------------------
+
   rlc_rrc_data_ind  = rrc_data_indP;
   rlc_rrc_data_conf = rrc_data_confP;
 }
diff --git a/openair2/PHY_INTERFACE/IF_Module_L2_primitives_NB_IoT.c b/openair2/PHY_INTERFACE/IF_Module_L2_primitives_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..9fbf5637c04bd088ddaa0d9ab229df3de9348d9f
--- /dev/null
+++ b/openair2/PHY_INTERFACE/IF_Module_L2_primitives_NB_IoT.c
@@ -0,0 +1,70 @@
+#include "IF_Module_L2_primitives_NB_IoT.h"
+#include "LAYER2/MAC/proto_NB_IoT.h"
+
+
+// Sched_INFO as a input for the scheduler
+void UL_indication(UL_IND_t *UL_INFO)
+{
+    int i=0;
+    //UE_TEMPLATE_NB_IoT *UE_info;
+    //mac_NB_IoT_t *mac_inst;
+
+      //If there is a preamble, do the initiate RA procedure
+      if(UL_INFO->NRACH.number_of_initial_scs_detected>0)
+        {
+          for(i=0;i<UL_INFO->NRACH.number_of_initial_scs_detected;i++)
+            {
+              // initiate_ra here, some useful inforamtion : 
+              //(UL_INFO->NRACH.nrach_pdu_list+i)->nrach_indication_rel13.initial_sc
+              //(UL_INFO->NRACH.nrach_pdu_list+i)->nrach_indication_rel13.timing_advance
+              /*init_RA_NB_IoT(UL_INFO->module_id,
+                                      UL_INFO->CC_id,
+                                      UL_INFO->frame,
+                                      (UL_INFO->NRACH.nrach_pdu_list+i)->nrach_indication_rel13.initial_sc,
+                                      //timing_offset = Timing_advance * 16
+                                      (UL_INFO->NRACH.nrach_pdu_list+i)->nrach_indication_rel13.timing_advance * 16,
+                                      UL_INFO->subframe
+                                     );*/
+
+            }
+        }
+
+        // crc indication if there is error for this round UL transmission
+
+        if(UL_INFO->crc_ind.number_of_crcs>0)
+        {
+          for(i=0;i<UL_INFO->crc_ind.number_of_crcs;i++)
+          {
+            if((UL_INFO->crc_ind.crc_pdu_list+i)->crc_indication_rel8.crc_flag == 0)
+            {
+              //unsuccessfully received this UE PDU
+              //UE_info = get_ue_from_rnti(mac_inst,((UL_INFO->crc_ind.crc_pdu_list)+i)->rx_ue_information.rnti);
+              //UE_info->HARQ_round++;
+            }
+          }
+        }
+
+        /*If there is a Uplink SDU which needs to send to MAC*/
+
+        if(UL_INFO->RX_NPUSCH.number_of_pdus>0)
+          {
+            for(i=0;i<UL_INFO->RX_NPUSCH.number_of_pdus;i++)
+              {
+                /*For MSG3, Normal Uplink Data, NAK*/
+                rx_sdu_NB_IoT(UL_INFO->module_id,
+                              UL_INFO->CC_id,
+                              UL_INFO->frame,
+                              UL_INFO->subframe,
+                              (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_ue_information.rnti,
+                              (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->data,
+                              (UL_INFO->RX_NPUSCH.rx_pdu_list+i)->rx_indication_rel8.length
+                             );
+
+              }
+
+          }
+
+    //scheduler here
+    //Schedule subframe should be next four subframe, means that UL_INFO->frame*10+UL_INFO->subframe + 4
+    //eNB_dlsch_ulsch_scheduler_NB_IoT(mac_inst,abs_subframe);
+}
\ No newline at end of file
diff --git a/openair2/PHY_INTERFACE/IF_Module_L2_primitives_NB_IoT.h b/openair2/PHY_INTERFACE/IF_Module_L2_primitives_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..332f370aa8c0b500189586ed1115aab53c0f6df3
--- /dev/null
+++ b/openair2/PHY_INTERFACE/IF_Module_L2_primitives_NB_IoT.h
@@ -0,0 +1,13 @@
+#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
+//#include "LAYER2/MAC/extern.h"
+
+
+
+#ifndef __IF_MODULE_L2_PRIMITIVES_NB_IOT_H__
+#define __IF_MODULE_L2_PRIMITIVES_NB_IOT_H__
+
+/*Interface for uplink, transmitting the Preamble(list), ULSCH SDU, NAK, Tick (trigger scheduler)
+*/
+void UL_indication(UL_IND_t *UL_INFO);
+
+#endif
diff --git a/openair2/PHY_INTERFACE/IF_Module_NB_IoT.c b/openair2/PHY_INTERFACE/IF_Module_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..93313b8f11073db1bf13a96f94e59df8616e0411
--- /dev/null
+++ b/openair2/PHY_INTERFACE/IF_Module_NB_IoT.c
@@ -0,0 +1,27 @@
+#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
+#include "openair2/PHY_INTERFACE/IF_Module_L2_primitives_NB_IoT.h"
+#include "openair1/SCHED/IF_Module_L1_primitives_NB_IoT.h"
+#include "LAYER2/MAC/extern_NB_IoT.h"
+//#include "LAYER2/MAC/proto_NB_IoT.h"
+
+
+//called at initialization of L2
+void IF_Module_init_L2(void) // northbound IF-Module Interface
+{
+	//mapping the IF-Module function to L2 definition
+	if_inst->UL_indication = UL_indication;
+
+	//return if_inst;
+}
+
+
+//called at initialization of L1 (phy_init_lte_eNB)
+void IF_Module_init_L1(void) //southbound IF-Module Interface
+{
+	//mapping the IF-module function to L1 definition
+	if_inst->schedule_response = schedule_response;
+	if_inst->PHY_config_req  = PHY_config_req;
+
+	//return if_inst;
+}
+
diff --git a/openair2/PHY_INTERFACE/IF_Module_NB_IoT.h b/openair2/PHY_INTERFACE/IF_Module_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..db96845cc70575a56180952ad6bb35c19f4a2cef
--- /dev/null
+++ b/openair2/PHY_INTERFACE/IF_Module_NB_IoT.h
@@ -0,0 +1,202 @@
+
+/*This is the interface module between PHY
+*Provided the FAPI style interface structures for P7.
+*Provide the semi-FAPI style interface for P5 (configuration)
+*
+*/
+
+#ifndef __IF_MODULE_NB_IoT__H__
+#define __IF_MODULE_NB_IoT__H__
+
+#include "nfapi_interface.h"
+//#include "openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h"
+#include "PhysicalConfigDedicated-NB-r13.h"
+//#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
+#include "openair2/COMMON/platform_types.h"
+
+//#define SCH_PAYLOAD_SIZE_MAX 4096
+#define BCCH_PAYLOAD_SIZE_MAX_NB_IoT 128
+
+
+
+// P5 FAPI-like configuration structures-------------------------------------------------------------------------------
+
+/*MP: MISSED COMMON CONFIG. of SIB2-NB in FAPI SPECS
+ * some of them may not needed because are used only at UE side
+ * some of them are not needed because not necessary at PHY level
+ * other have to be clarified since seems to be needed at PHY layer
+ * there is no UE_Config. request message carrying NB-IoT parameters???
+ *
+ * */
+typedef struct{
+	//nprach_config
+	uint16_t nprach_config_0_subcarrier_MSG3_range_start;
+	uint16_t nprach_config_1_subcarrier_MSG3_range_start;
+	uint16_t nprach_config_2_subcarrier_MSG3_range_start;
+	uint16_t nprach_config_0_max_num_preamble_attempt_CE;
+	uint16_t nprach_config_1_max_num_preamble_attempt_CE;
+	uint16_t nprach_config_2_max_num_preamble_attempt_CE;
+	uint16_t nprach_config_0_npdcch_num_repetitions_RA; //Rmax (see TS 36.213 ch 16.6) -->only this is managed at PHY layer
+	uint16_t nprach_config_1_npdcch_num_repetitions_RA;
+	uint16_t nprach_config_2_npdcch_num_repetitions_RA;
+	uint16_t nprach_config_0_npdcch_startSF_CSS_RA; //G (see TS 36.213 ch 16.6)
+	uint16_t nprach_config_1_npdcch_startSF_CSS_RA;
+	uint16_t nprach_config_2_npdcch_startSF_CSS_RA;
+	uint16_t nprach_config_0_npdcch_offset_RA; //Alfa_offset (see TS 36.213 ch 16.6)
+	uint16_t nprach_config_1_npdcch_offset_RA;
+	uint16_t nprach_config_2_npdcch_offset_RA;
+
+	//configured through the phy_config_dedicated
+	//Higher layer parameter for NPDCCH UE-spec search space
+	uint16_t npdcch_NumRepetitions;//Rmax (see TS 36.213 ch 16.6)  -->only this is managed at PHY layer
+	uint16_t npdcch_StartSF_USS; //G (see TS 36.213 ch 16.6)
+	uint16_t npdcch_Offset_USS; //Alfa_offset (see TS 36.213 ch 16.6)
+
+
+	ACK_NACK_NumRepetitions_NB_r13_t *ack_nack_numRepetitions_MSG4; //pointer to the first cell of a list of ack_nack_num_repetitions
+
+    //ulPowerControlCommon (UE side)
+    uint16_t p0_nominal_npusch;
+	uint16_t alpha;
+	uint16_t delta_preamle_MSG3;
+
+
+	/*Dedicated configuration -->not supported by FAPI (may not needed)
+	 * In OAI at least are needed when we manage the phy_procedures_eNB_TX in which we call the phy_config_dedicated_eNB_step2
+	 * that use the physicalConfigDedicated info previously stored in the PHY_VARS_eNB_NB_IoT structure through the phy_config_dedicated procedure
+	 */
+	//PhysicalConfigDedicated_NB_r13_t *phy_config_dedicated;
+
+
+
+
+}extra_phyConfig_t;
+
+typedef struct{
+
+	/*OAI config. parameters*/
+	module_id_t mod_id;
+	int CC_id;
+	uint16_t rnti;
+	int get_MIB; //should be different from 0 only when the mib!= null (NB_rrc_mac_config_req_eNB_IoT)
+	int get_COMMON;
+	int get_DEDICATED;
+
+	//ID of the Resource Block dedicated to NB-IoT
+	//For Nb-IoT only a restricted values of PRB indexes are allowed (see Rhode&Shwartz pag9)
+	//unsigned short NB_IoT_RB_ID; (should coincide with PRB index)
+
+
+
+
+	/*FAPI useful config. parameters used in the code
+	 *
+	 * -nfapi_uplink_reference_signal_config_t uplink_reference_signal_config
+	 * -nfapi_subframe_config_t subframe_config;
+	 * -nfapi_rf_config_t rf_config;
+	 * -nfapi_sch_config_t sch_config;
+	 * -nfapi_nb_iot_config_t config_NB_IoT;
+	 * -nfapi_l23_config_t l23_config;
+	 * -nfapi_config --> EARFCN (for the transport of the dl_CarrierFreq
+	 * */
+
+	//XXX where allocate memory??
+	nfapi_config_request_t* cfg;
+
+	/*MP: MISSED COMMON CONFIG. of SIB2-NB in FAPI SPECS (may non needed)*/
+	extra_phyConfig_t extra_phy_parms;
+
+}PHY_Config_t;
+
+
+
+// uplink subframe P7---------------------------------------------------------------------------------
+
+
+/*UL_IND_t:
+* A structure handles all the uplink information.
+* Corresponding to the NRACH.indicaiton, UL_Config_indication, RX_ULSCH.indication, CRC.inidcation, NB_HARQ.indication in FAPI
+*/
+typedef struct{
+
+ 	/*Start at the common part*/
+
+ 	int test;
+
+ 	//Module ID
+ 	module_id_t module_id;
+ 	//CC ID
+ 	int CC_id;
+ 	//frame 
+ 	frame_t frame;
+ 	//subframe
+ 	sub_frame_t subframe;
+ 	//Hyper frame for NB-IoT implementation
+ 	uint32_t hypersfn;
+
+ 	/*preamble part*/
+
+ 	nfapi_nrach_indication_body_t NRACH;
+
+ 	/*Uplink data part*/
+
+ 	/*indication of the harq feedback*/
+ 	nfapi_nb_harq_indication_t nb_harq_ind;
+ 	/*indication of the uplink data PDU*/
+  	nfapi_rx_indication_body_t RX_NPUSCH;
+ 	/*crc_indication*/
+ 	nfapi_crc_indication_body_t crc_ind;
+
+ }UL_IND_t;
+
+ // Downlink subframe P7
+
+
+typedef struct{
+
+ 	/*Start at the common part*/
+
+ 	//Module ID
+	module_id_t module_id; 
+ 	//CC ID
+ 	int CC_id;
+ 	// hyper subframe
+ 	uint32_t hypersfn;
+ 	//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;
+  	/// nFAPI TX Request
+  	nfapi_tx_request_t        *TX_req; 
+  	/// Pointers to DL SDUs
+  	//uint8_t **sdu;
+
+}Sched_Rsp_t;
+
+
+/*IF_Module_t a group for gathering the Interface
+It should be allocated at the main () in lte-softmodem.c*/
+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);
+
+}IF_Module_t;
+
+/*Initial */
+
+//int IF_Module_init(IF_Module_t *if_inst);
+
+void IF_Module_init_L1(void);
+void IF_Module_init_L2(void);
+
+
+#endif
diff --git a/openair2/PHY_INTERFACE/IF_Module_nb_iot.h b/openair2/PHY_INTERFACE/IF_Module_nb_iot.h
deleted file mode 100644
index fc1a5f04ab69b0dd7ec571e3aca3f2c676f24fd8..0000000000000000000000000000000000000000
--- a/openair2/PHY_INTERFACE/IF_Module_nb_iot.h
+++ /dev/null
@@ -1,102 +0,0 @@
-
-/*This is the interface module between PHY
-* this will trigger the corresponding function in MAC or PHY layer according to the type of the message
-*
-*
-*
-*/
-
-
-#include "platform_types.h"
-#include "openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h"
-
-
-
-#define NUMBER_OF_UE_MAX 20
-
-typedef struct{
-	
-//flag to show which message is
-uint8_t UL_MSG_flag;
-
-//rnti
-rnti_t rntiP;
-//Pointer to sdu
-uint8_t *sdu;
-//Pointer to sdu length 
-uint16_t sdu_lenP;
-//HARQ ID
-int harq_pidP;
-//MSG3 flag
-uint8_t *msg3_flagP;
-//ACK/NAK
-boolean_t NAK;
-// ULSCH consecutive error
-uint32_t ulsch_consecutive_errors;
-
-}UL_SPEC_t;
-
-//UL_IND
-typedef struct{
-
- /*Start at the common part*/
-
- int test;
- //Module ID
- module_id_t module_id;
- //CC ID
- int CC_id;
- //frame 
- frame_t frame;
- //subframe
- sub_frame_t subframe;
- //Number of availble UE
- int UE_NUM;
-
- /*preamble part*/
- //index of the preamble
- uint16_t preamble_index;
- //timing offset by PHY
- int16_t timing_offset;
-
- /*UE specific part*/
- UL_SPEC_t UL_SPEC_Info[NUMBER_OF_UE_MAX]; 
-
- }UL_IND_t;
-
-
-typedef struct{
-
- /*Common part*/
- module_id_t module_idP; 
- int CC_id;
- frame_t frameP;
- sub_frame_t subframeP;
-
- rnti_t rntiP;
-
- /*Downlink data*/
- //TB size for Downlink data
- uint8_t TBindex;
- //PDU for MIB,SIBs
- uint8_t *BCCH_pdu_payload;
- //PDU for DL-SCH
- uint8_t *DLSCH_pdu_payload;
-
- /*DCI start*/
- // Format of DCI
- uint8_t DCI_Format;
- // Content of DCI
- DCI_CONTENT DCI_Content;
-
-}Sched_Rsp_t;
-
-/*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);
-
-/*Interface for Configuration*/
-//void Config_Request();
diff --git a/openair2/PHY_INTERFACE/defs_NB_IoT.h b/openair2/PHY_INTERFACE/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..87382a5f1c2f329aedd5186d69c18b773b433ec4
--- /dev/null
+++ b/openair2/PHY_INTERFACE/defs_NB_IoT.h
@@ -0,0 +1,61 @@
+/*
+ * 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.0  (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_NB_IOT_H__
+#define __MAC_PHY_PRIMITIVES_NB_IOT_H__
+
+#include "LAYER2/MAC/defs_NB_IoT.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
+ * @{
+ */
+
+
+
+#endif
+
+
+/** @} */
diff --git a/openair2/PHY_INTERFACE/nfapi_interface.h b/openair2/PHY_INTERFACE/nfapi_interface.h
new file mode 100644
index 0000000000000000000000000000000000000000..6452df003b359f2460aea1aa677c88664fc404f3
--- /dev/null
+++ b/openair2/PHY_INTERFACE/nfapi_interface.h
@@ -0,0 +1,3857 @@
+/*
+ * Copyright 2017 Cisco Systems, Inc.
+ * 
+ * Licensed under the Apache License, Version 2.0 (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.apache.org/licenses/LICENSE-2.0
+ * 
+ * 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.
+ */
+
+
+#ifndef _NFAPI_INTERFACE_H_
+#define _NFAPI_INTERFACE_H_
+
+#include "stddef.h"
+#include "ACK-NACK-NumRepetitions-NB-r13.h"
+
+// Constants - update based on implementation
+#define NFAPI_MAX_PHY_RF_INSTANCES 2
+#define NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH 16
+#define NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH 3
+#define NFAPI_MAX_NUM_RF_BANDS 16
+
+// The following definition control the size of arrays used in the interface.
+// These may be changed if desired. They are used in the encoder to make sure 
+// that the user has not specified a 'count' larger than the max array, and also
+// used by the decoder when decode an array. If the 'count' received is larger
+// than the array it is to be stored in the decode fails. 
+#define NFAPI_MAX_NUM_ANTENNAS 8
+#define NFAPI_MAX_NUM_SUBBANDS 13
+#define NFAPI_MAX_BF_VECTORS 8
+#define NFAPI_MAX_CC 1
+#define NFAPI_MAX_NUM_PHYSICAL_ANTENNAS 8
+#define NFAPI_MAX_RSSI 8
+#define NFAPI_MAX_PSC_LIST 32
+#define NFAPI_MAX_PCI_LIST 32
+#define NFAPI_MAX_CARRIER_LIST 32
+#define NFAPI_MAX_ARFCN_LIST 128
+#define NFAPI_MAX_LTE_CELLS_FOUND 8
+#define NFAPI_MAX_UTRAN_CELLS_FOUND 8
+#define NFAPI_MAX_GSM_CELLS_FOUND 8
+#define NFAPI_MAX_NB_IOT_CELLS_FOUND 8
+#define NFAPI_MAX_SI_PERIODICITY 8
+#define NFAPI_MAX_SI_INDEX 8
+#define NFAPI_MAX_MIB_LENGTH 32
+#define NFAPI_MAX_SIB_LENGTH 256
+#define NFAPI_MAX_SI_LENGTH 256
+#define NFAPI_MAX_OPAQUE_DATA 64
+#define NFAPI_MAX_NUM_SCHEDULED_UES 8 // Used in the TPM structure
+#define NFAPI_MAX_PNF_PHY 5
+#define NFAPI_MAX_PNF_PHY_RF_CONFIG 5
+#define NFAPI_MAX_PNF_RF  5
+#define NFAPI_MAX_NMM_FREQUENCY_BANDS 32
+#define NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS 100
+#define NFAPI_MAX_UL_DL_CONFIGURATIONS 5
+#define NFAPI_MAX_CSI_RS_RESOURCE_CONFIG 4
+#define NFAPI_MAX_ANTENNA_PORT_COUNT 8
+#define NFAPI_MAX_EPDCCH_PRB 8
+#define NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS 8
+#define NFAPI_MAX_NUMBER_ACK_NACK_TDD 8
+#define NFAPI_MAX_RO_DL 8
+
+#define NFAPI_HEADER_LENGTH 8
+#define NFAPI_P7_HEADER_LENGTH 16
+
+#define NFAPI_VENDOR_EXTENSION_MIN_TAG_VALUE 0xF000
+#define NFAPI_VENDOR_EXTENSION_MAX_TAG_VALUE 0xFFFF
+
+#define NFAPI_VERSION_3_0_11	0x000
+#define NFAPI_VERSION_3_0_12    0x001
+
+// The IANA agreed port definition of the P5 SCTP VNF enpoint 
+// http://www.iana.org/assignments/service-names-port-numbers/service-names-port-numbers.xhtml?search=7701
+#define NFAPI_P5_SCTP_PORT		7701
+
+typedef unsigned int	uint32_t;
+typedef unsigned short	uint16_t;
+typedef unsigned char	uint8_t;
+typedef signed int		int32_t;
+typedef signed short	int16_t;
+typedef signed char		int8_t;
+
+typedef struct {
+	uint16_t phy_id;
+	uint16_t message_id;
+	uint16_t message_length;
+	uint16_t spare;
+} nfapi_p4_p5_message_header_t;
+
+typedef struct {
+	uint16_t phy_id;
+	uint16_t message_id;
+	uint16_t message_length;
+	uint16_t m_segment_sequence; /* This consists of 3 fields - namely, M, Segement & Sequence number*/
+	uint32_t checksum;
+	uint32_t transmit_timestamp;
+} nfapi_p7_message_header_t;
+
+#define NFAPI_PHY_ID_NA 0
+
+//#define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x80) >> 7 )
+//#define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x70) >> 4 )
+#define NFAPI_P7_GET_MORE(_mss) ( ((_mss) & 0x8000) >> 15 )
+#define NFAPI_P7_GET_SEGMENT(_mss) ( ((_mss) & 0x7F00) >> 8 )
+#define NFAPI_P7_GET_SEQUENCE(_mss) ( (_mss) & 0x00FF )
+#define NFAPI_P7_SET_MSS(_more, _segm, _sequ) ( (((_more) & 0x1) << 7) | (((_segm) & 0x7) << 4) | ((_sequ) & 0xF) )
+
+typedef struct {
+	uint16_t tag;
+	uint16_t length;
+} nfapi_tl_t;
+#define NFAPI_TAG_LENGTH_PACKED_LEN 4
+
+// Convenience methods to convert between SFN/SFN formats
+#define NFAPI_SFNSF2DEC(_sfnsf) ((((_sfnsf) >> 4) * 10) + ((_sfnsf) & 0xF))
+#define NFAPI_SFNSFDEC2SFNSF(_sfnsf_dec) ((((_sfnsf_dec) / 10) << 4) | (((_sfnsf_dec) - (((_sfnsf_dec) / 10) * 10)) & 0xF))
+
+#define NFAPI_SFNSF2SFN(_sfnsf) ((_sfnsf) >> 4)
+#define NFAPI_SFNSF2SF(_sfnsf) ((_sfnsf) & 0xF)
+
+#define NFAPI_MAX_SFNSFDEC 10240
+
+typedef nfapi_tl_t* nfapi_vendor_extension_tlv_t;
+
+
+// nFAPI Message IDs
+typedef enum {
+	NFAPI_DL_CONFIG_REQUEST = 0x0080,
+	NFAPI_UL_CONFIG_REQUEST,
+	NFAPI_SUBFRAME_INDICATION,
+	NFAPI_HI_DCI0_REQUEST,
+	NFAPI_TX_REQUEST,
+	NFAPI_HARQ_INDICATION,
+	NFAPI_CRC_INDICATION,
+	NFAPI_RX_ULSCH_INDICATION,
+	NFAPI_RACH_INDICATION,
+	NFAPI_SRS_INDICATION,
+	NFAPI_RX_SR_INDICATION,
+	NFAPI_RX_CQI_INDICATION,
+	NFAPI_LBT_DL_CONFIG_REQUEST,
+	NFAPI_LBT_DL_INDICATION,
+	NFAPI_NB_HARQ_INDICATION,
+	NFAPI_NRACH_INDICATION,
+
+	NFAPI_PNF_PARAM_REQUEST = 0x0100,
+	NFAPI_PNF_PARAM_RESPONSE,
+	NFAPI_PNF_CONFIG_REQUEST,
+	NFAPI_PNF_CONFIG_RESPONSE,
+	NFAPI_PNF_START_REQUEST,
+	NFAPI_PNF_START_RESPONSE,
+	NFAPI_PNF_STOP_REQUEST,
+	NFAPI_PNF_STOP_RESPONSE,
+	NFAPI_PARAM_REQUEST,
+	NFAPI_PARAM_RESPONSE,
+	NFAPI_CONFIG_REQUEST,
+	NFAPI_CONFIG_RESPONSE,
+	NFAPI_START_REQUEST,
+	NFAPI_START_RESPONSE,
+	NFAPI_STOP_REQUEST,
+	NFAPI_STOP_RESPONSE,
+	NFAPI_MEASUREMENT_REQUEST,
+	NFAPI_MEASUREMENT_RESPONSE,
+
+	NFAPI_UL_NODE_SYNC = 0x0180,
+	NFAPI_DL_NODE_SYNC,
+	NFAPI_TIMING_INFO,
+
+
+	NFAPI_RSSI_REQUEST = 0x0200,
+	NFAPI_RSSI_RESPONSE,
+	NFAPI_RSSI_INDICATION,
+	NFAPI_CELL_SEARCH_REQUEST,
+	NFAPI_CELL_SEARCH_RESPONSE,
+	NFAPI_CELL_SEARCH_INDICATION,
+	NFAPI_BROADCAST_DETECT_REQUEST,
+	NFAPI_BROADCAST_DETECT_RESPONSE,
+	NFAPI_BROADCAST_DETECT_INDICATION,
+	NFAPI_SYSTEM_INFORMATION_SCHEDULE_REQUEST,
+	NFAPI_SYSTEM_INFORMATION_SCHEDULE_RESPONSE,
+	NFAPI_SYSTEM_INFORMATION_SCHEDULE_INDICATION,
+	NFAPI_SYSTEM_INFORMATION_REQUEST,
+	NFAPI_SYSTEM_INFORMATION_RESPONSE,
+	NFAPI_SYSTEM_INFORMATION_INDICATION,
+	NFAPI_NMM_STOP_REQUEST,
+	NFAPI_NMM_STOP_RESPONSE,
+
+	NFAPI_VENDOR_EXT_MSG_MIN = 0x0300,
+	NFAPI_VENDOR_EXT_MSG_MAX = 0x03FF,
+
+
+	NFAPI_MAX_MESSAGE_ID,
+} nfapi_message_id_e;
+
+// nFAPI Error Codes
+typedef enum {
+	NFAPI_MSG_OK = 0,
+	NFAPI_MSG_INVALID_STATE,
+	NFAPI_MSG_INVALID_CONFIG,
+	NFAPI_SFN_OUT_OF_SYNC,
+	NFAPI_MSG_SUBFRAME_ERR,
+	NFAPI_MSG_BCH_MISSING,
+	NFAPI_MSG_INVALID_SFN,
+	NFAPI_MSG_HI_ERR,
+	NFAPI_MSG_TX_ERR,
+	
+	NFAPI_LBT_NO_PDU_IN_DL_REQ,
+	NFAPI_LBT_NO_VALID_CONFIG_REQ_RECEIVED,
+	NFAPI_FAPI_E_LBT_SF_SFN_PASSED_END_SF_SFN,
+	NFAPI_FAPI_E_LBT_OVERLAP,
+	NFAPI_MSG_BCH_PRESENT,
+	
+	NFAPI_NBIOT_UNEXPECTED_REQ,
+
+	// This is special return code that indicates that a response has
+	// been send via P9
+	NFAPI_MSG_P9_RESPONSE = 0xAA
+} nfapi_error_code_e;
+
+
+typedef enum {
+	NFAPI_P4_MSG_OK = 100,
+	NFAPI_P4_MSG_INVALID_STATE = 101,
+	NFAPI_P4_MSG_INVALID_CONFIG = 102,
+	NFAPI_P4_MSG_RAT_NOT_SUPPORTED = 103,
+	NFAPI_P4_MSG_NMM_STOP_OK = 200,
+	NFAPI_P4_MSG_NMM_STOP_IGNOREDED = 201,
+	NFAPI_P4_MSG_NMM_STOP_INVALID_STATE = 202,
+	NFAPI_P4_MSG_PROCEDURE_COMPLETE = 300,
+	NFAPI_P4_MSG_PROCEDURE_STOPPED = 301,
+	NFAPI_P4_MSG_PARTIAL_RESULTS = 302,
+	NFAPI_P4_MSG_TIMEOUT = 303
+} nfapi_p4_error_code_e;
+
+// nFAPI enums
+typedef enum {
+	NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE = 0,
+	NFAPI_DL_CONFIG_BCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_MCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_DLSCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_PCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_PRS_PDU_TYPE,
+	NFAPI_DL_CONFIG_CSI_RS_PDU_TYPE,
+	NFAPI_DL_CONFIG_EPDCCH_DL_PDU_TYPE,
+	NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_NBCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_NPDCCH_PDU_TYPE,
+	NFAPI_DL_CONFIG_NDLSCH_PDU_TYPE
+} nfapi_dl_config_pdu_type_e;
+
+typedef enum {
+	NFAPI_DL_DCI_FORMAT_1 = 0,
+	NFAPI_DL_DCI_FORMAT_1A,
+	NFAPI_DL_DCI_FORMAT_1B,
+	NFAPI_DL_DCI_FORMAT_1C,
+	NFAPI_DL_DCI_FORMAT_1D,
+	NFAPI_DL_DCI_FORMAT_2,
+	NFAPI_DL_DCI_FORMAT_2A,
+	NFAPI_DL_DCI_FORMAT_2B,
+	NFAPI_DL_DCI_FORMAT_2C
+} nfapi_dl_dci_format_e;
+
+typedef enum {
+	NFAPI_UL_DCI_FORMAT_0 = 0,
+	NFAPI_UL_DCI_FORMAT_3,
+	NFAPI_UL_DCI_FORMAT_3A,
+	NFAPI_UL_DCI_FORMAT_4
+} nfapi_ul_dci_format_e;
+
+typedef enum {
+	NFAPI_UL_CONFIG_ULSCH_PDU_TYPE = 0,
+	NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE,
+	NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_SRS_PDU_TYPE,
+	NFAPI_UL_CONFIG_HARQ_BUFFER_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE,
+	NFAPI_UL_CONFIG_NULSCH_PDU_TYPE,
+	NFAPI_UL_CONFIG_NRACH_PDU_TYPE,
+} nfapi_ul_config_pdu_type_e;
+
+typedef enum {
+	NFAPI_HI_DCI0_HI_PDU_TYPE = 0,
+	NFAPI_HI_DCI0_DCI_PDU_TYPE,
+	NFAPI_HI_DCI0_EPDCCH_DCI_PDU_TYPE,
+	NFAPI_HI_DCI0_MPDCCH_DCI_PDU_TYPE,
+	NFAPI_HI_DCI0_NPDCCH_DCI_PDU_TYPE,
+} nfapi_hi_dci0_pdu_type_e;
+
+typedef enum {
+	NFAPI_HARQ_ACK = 1,
+	NFAPI_HARQ_NACK,
+	NFAPI_HARQ_ACK_OR_NACK,
+	NFAPI_HARQ_DTX,
+	NFAPI_HARQ_ACK_OR_DTX,
+	NFAPI_HARQ_NACK_OR_DTX,
+	NFAPI_HARQ_ACK_OR_NACK_OR_DTX
+} nfapi_harq_type_e;
+
+typedef enum {
+	NFAPI_CSI_REPORT_TYPE_PERIODIC = 0,
+	NFAPI_CSI_REPORT_TYPE_APERIODIC
+} nfapi_csi_report_type_e;
+
+typedef enum {
+	NFAPI_DL_BW_SUPPORTED_6 = 1,
+	NFAPI_DL_BW_SUPPORTED_15 = 2,
+	NFAPI_DL_BW_SUPPORTED_25 = 4,
+	NFAPI_DL_BW_SUPPORTED_50 = 8,
+	NFAPI_DL_BW_SUPPORTED_75 = 16,
+	NFAPI_DL_BW_SUPPORTED_100 = 32
+} nfapi_dl_bandwith_supported_e;
+
+typedef enum {
+	NFAPI_UL_BW_SUPPORTED_6 = 1,
+	NFAPI_UL_BW_SUPPORTED_15 = 2,
+	NFAPI_UL_BW_SUPPORTED_25 = 4,
+	NFAPI_UL_BW_SUPPORTED_50 = 8,
+	NFAPI_UL_BW_SUPPORTED_75 = 16,
+	NFAPI_UL_BW_SUPPORTED_100 = 32
+} nfapi_ul_bandwith_supported_e;
+
+typedef enum {
+	NFAPI_3GPP_REL_SUPPORTED_8 = 0,
+	NFAPI_3GPP_REL_SUPPORTED_9 = 1,
+	NFAPI_3GPP_REL_SUPPORTED_10 = 2,
+	NFAPI_3GPP_REL_SUPPORTED_11 = 4,
+	NFAPI_3GPP_REL_SUPPORTED_12 = 8
+} nfapi_3gpp_release_supported_e;
+
+
+typedef enum {
+	NFAPI_DUPLEXING_MODE_TDD = 0,
+	NFAPI_DUPLEXING_MODE_FDD = 1,
+	NFAPI_DUPLEXING_MODE_HD_FDD = 2,
+} nfapi_duplexing_mode_e;
+
+typedef enum {
+	NFAPI_CP_NORMAL = 0,
+	NFAPI_CP_EXTENDED = 1
+} nfapi_cyclic_prefix_type_e;
+
+typedef enum {
+	NFAPI_RAT_TYPE_LTE = 0,
+	NFAPI_RAT_TYPE_UTRAN = 1,
+	NFAPI_RAT_TYPE_GERAN = 2,
+	NFAPI_RAT_TYPE_NB_IOT = 3
+} nfapi_rat_type_e;
+
+typedef enum {
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_BUNDLING,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_MULIPLEXING,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_SPECIAL_BUNDLING,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_CHANNEL_SELECTION,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_3,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_4,
+	NFAPI_HARQ_INDICATION_TDD_HARQ_ACK_NACK_FORMAT_FORMAT_5
+} nfapi_harq_indication_tdd_ack_nackformat_e;
+
+
+typedef enum {
+	NFAPI_LBT_DL_CONFIG_REQUEST_PDSCH_PDU_TYPE = 0,
+	NFAPI_LBT_DL_CONFIG_REQUEST_DRS_PDU_TYPE
+} nfapi_lbt_dl_config_pdu_type_e;
+
+typedef enum {
+	NFAPI_LBT_DL_RSP_PDSCH_PDU_TYPE = 0,
+	NFAPI_LBT_DL_RSP_DRS_PDU_TYPE
+} nfapi_lbt_dl_rsp_pdu_type_e;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t length;
+	uint8_t value[NFAPI_MAX_OPAQUE_DATA];
+} nfapi_opaqaue_data_t;
+
+// Utility functions to turn enums into char*
+const char* nfapi_error_code_to_str(nfapi_error_code_e value);
+
+
+// P5 Sub Structures
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t nfapi_sync_mode;
+	uint8_t location_mode;
+	uint16_t location_coordinates_length;
+	uint8_t location_coordinates[NFAPI_PNF_PARAM_GENERAL_LOCATION_LENGTH];
+	uint32_t dl_config_timing;
+	uint32_t tx_timing;
+	uint32_t ul_config_timing;
+	uint32_t hi_dci0_timing;
+	uint16_t maximum_number_phys;
+	uint16_t maximum_total_bandwidth;
+	uint8_t maximum_total_number_dl_layers;
+	uint8_t maximum_total_number_ul_layers;
+	uint8_t shared_bands;
+	uint8_t shared_pa;
+	int16_t maximum_total_power;
+	uint8_t oui[NFAPI_PNF_PARAM_GENERAL_OUI_LENGTH];
+} nfapi_pnf_param_general_t;
+#define NFAPI_PNF_PARAM_GENERAL_TAG 0x1000
+
+
+
+
+
+typedef struct {
+	uint16_t rf_config_index;
+} nfapi_rf_config_info_t;
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t number_of_rfs;
+	nfapi_rf_config_info_t rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint16_t number_of_rf_exclusions;
+	nfapi_rf_config_info_t excluded_rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint16_t downlink_channel_bandwidth_supported;
+	uint16_t uplink_channel_bandwidth_supported;
+	uint8_t number_of_dl_layers_supported;
+	uint8_t number_of_ul_layers_supported;
+	uint16_t maximum_3gpp_release_supported;
+	uint8_t nmm_modes_supported;
+} nfapi_pnf_phy_info_t;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_t;
+#define NFAPI_PNF_PHY_TAG 0x1001
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t transmission_mode_7_supported;
+	uint16_t transmission_mode_8_supported;
+	uint16_t two_antenna_ports_for_pucch;
+	uint16_t transmission_mode_9_supported;
+	uint16_t simultaneous_pucch_pusch;
+	uint16_t four_layer_tx_with_tm3_and_tm4;
+} nfapi_pnf_phy_rel10_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel10_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel10_t;
+#define NFAPI_PNF_PHY_REL10_TAG 0x100A
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t edpcch_supported;
+	uint16_t multi_ack_csi_reporting;
+	uint16_t pucch_tx_diversity;
+	uint16_t ul_comp_supported;
+	uint16_t transmission_mode_5_supported;
+} nfapi_pnf_phy_rel11_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel11_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel11_t;
+#define NFAPI_PNF_PHY_REL11_TAG 0x100B
+
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t csi_subframe_set;
+	uint16_t enhanced_4tx_codebook;
+	uint16_t drs_supported;
+	uint16_t ul_64qam_supported;
+	uint16_t transmission_mode_10_supported;
+	uint16_t alternative_bts_indices;
+} nfapi_pnf_phy_rel12_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel12_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel12_t;
+#define NFAPI_PNF_PHY_REL12_TAG 0x100C
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t pucch_format4_supported;
+	uint16_t pucch_format5_supported;
+	uint16_t more_than_5_ca_support;
+	uint16_t laa_supported;
+	uint16_t laa_ending_in_dwpts_supported;
+	uint16_t laa_starting_in_second_slot_supported;
+	uint16_t beamforming_supported;
+	uint16_t csi_rs_enhancement_supported;
+	uint16_t drms_enhancement_supported;
+	uint16_t srs_enhancement_supported;
+} nfapi_pnf_phy_rel13_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel13_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel13_t;
+#define NFAPI_PNF_PHY_REL13_TAG 0x100D
+
+typedef struct {
+	uint16_t phy_config_index;
+	uint16_t number_of_rfs;
+	nfapi_rf_config_info_t rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint16_t number_of_rf_exclusions;
+	nfapi_rf_config_info_t excluded_rf_config[NFAPI_MAX_PNF_PHY_RF_CONFIG];
+	uint8_t number_of_dl_layers_supported;
+	uint8_t number_of_ul_layers_supported;
+	uint16_t maximum_3gpp_release_supported;
+	uint8_t nmm_modes_supported;
+} nfapi_pnf_phy_rel13_nb_iot_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_phys;
+	nfapi_pnf_phy_rel13_nb_iot_info_t phy[NFAPI_MAX_PNF_PHY];
+} nfapi_pnf_phy_rel13_nb_iot_t;
+#define NFAPI_PNF_PHY_REL13_NB_IOT_TAG 0x100E
+
+
+
+typedef struct {
+	uint16_t rf_config_index;
+	uint16_t band;
+	int16_t maximum_transmit_power; 
+	int16_t minimum_transmit_power;
+	uint8_t number_of_antennas_suppported;
+	uint32_t minimum_downlink_frequency;
+	uint32_t maximum_downlink_frequency;
+	uint32_t minimum_uplink_frequency;
+	uint32_t maximum_uplink_frequency;
+} nfapi_pnf_rf_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_rfs;
+	nfapi_pnf_rf_info_t rf[NFAPI_MAX_PNF_RF];
+} nfapi_pnf_rf_t;
+#define NFAPI_PNF_RF_TAG 0x1002
+
+typedef struct {
+	uint16_t phy_id;
+	uint16_t phy_config_index;
+	uint16_t rf_config_index;
+} nfapi_phy_rf_config_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_phy_rf_config_info;
+	nfapi_phy_rf_config_info_t phy_rf_config[NFAPI_MAX_PHY_RF_INSTANCES];
+} nfapi_pnf_phy_rf_config_t;
+#define NFAPI_PNF_PHY_RF_TAG 0x1003
+
+// Generic strucutre for single tlv value.
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t value;
+} nfapi_uint16_tlv_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	int16_t value;
+} nfapi_int16_tlv_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t value;
+} nfapi_uint8_tlv_t;
+
+typedef struct {
+	nfapi_uint16_tlv_t phy_state;
+} nfapi_l1_status;
+
+#define NFAPI_L1_STATUS_PHY_STATE_TAG 0x00FA
+
+typedef struct {
+	nfapi_uint16_tlv_t dl_bandwidth_support;
+	nfapi_uint16_tlv_t ul_bandwidth_support;
+	nfapi_uint16_tlv_t dl_modulation_support;
+	nfapi_uint16_tlv_t ul_modulation_support;
+	nfapi_uint16_tlv_t phy_antenna_capability;
+	nfapi_uint16_tlv_t release_capability;
+	nfapi_uint16_tlv_t mbsfn_capability;
+} nfapi_phy_capabilities_t;
+
+#define NFAPI_PHY_CAPABILITIES_DL_BANDWIDTH_SUPPORT_TAG 0x00C8
+#define NFAPI_PHY_CAPABILITIES_UL_BANDWIDTH_SUPPORT_TAG 0x00C9
+#define NFAPI_PHY_CAPABILITIES_DL_MODULATION_SUPPORT_TAG 0x00CA
+#define NFAPI_PHY_CAPABILITIES_UL_MODULATION_SUPPORT_TAG 0x00CB
+#define NFAPI_PHY_CAPABILITIES_PHY_ANTENNA_CAPABILITY_TAG 0x00CC
+#define NFAPI_PHY_CAPABILITIES_RELEASE_CAPABILITY_TAG 0x00CD
+#define NFAPI_PHY_CAPABILITIES_MBSFN_CAPABILITY_TAG 0x00CE
+
+
+typedef struct {
+	nfapi_uint16_tlv_t data_report_mode;
+	nfapi_uint16_tlv_t sfnsf;
+} nfapi_l23_config_t;
+
+
+#define NFAPI_L23_CONFIG_DATA_REPORT_MODE_TAG 0x00F0
+#define NFAPI_L23_CONFIG_SFNSF_TAG 0x00F1
+
+typedef struct {
+	nfapi_uint16_tlv_t duplex_mode;
+	nfapi_uint16_tlv_t pcfich_power_offset;
+	nfapi_uint16_tlv_t pb;
+	nfapi_uint16_tlv_t dl_cyclic_prefix_type;
+	nfapi_uint16_tlv_t ul_cyclic_prefix_type;
+} nfapi_subframe_config_t;
+
+#define NFAPI_SUBFRAME_CONFIG_DUPLEX_MODE_TAG 0x0001
+#define NFAPI_SUBFRAME_CONFIG_PCFICH_POWER_OFFSET_TAG 0x0002
+#define NFAPI_SUBFRAME_CONFIG_PB_TAG 0x0003
+#define NFAPI_SUBFRAME_CONFIG_DL_CYCLIC_PREFIX_TYPE_TAG 0x0004
+#define NFAPI_SUBFRAME_CONFIG_UL_CYCLIC_PREFIX_TYPE_TAG 0x0005
+
+typedef struct {
+	nfapi_uint16_tlv_t dl_channel_bandwidth;
+	nfapi_uint16_tlv_t ul_channel_bandwidth;
+	nfapi_uint16_tlv_t reference_signal_power;
+	nfapi_uint16_tlv_t tx_antenna_ports;
+	nfapi_uint16_tlv_t rx_antenna_ports;
+} nfapi_rf_config_t;
+
+#define NFAPI_RF_CONFIG_DL_CHANNEL_BANDWIDTH_TAG 0x000A
+#define NFAPI_RF_CONFIG_UL_CHANNEL_BANDWIDTH_TAG 0x000B
+#define NFAPI_RF_CONFIG_REFERENCE_SIGNAL_POWER_TAG 0x000C
+#define NFAPI_RF_CONFIG_TX_ANTENNA_PORTS_TAG 0x000D
+#define NFAPI_RF_CONFIG_RX_ANTENNA_PORTS_TAG 0x000E
+
+typedef struct {
+	nfapi_uint16_tlv_t phich_resource;
+	nfapi_uint16_tlv_t phich_duration;
+	nfapi_uint16_tlv_t phich_power_offset;
+} nfapi_phich_config_t;
+
+#define NFAPI_PHICH_CONFIG_PHICH_RESOURCE_TAG 0x0014
+#define NFAPI_PHICH_CONFIG_PHICH_DURATION_TAG 0x0015
+#define NFAPI_PHICH_CONFIG_PHICH_POWER_OFFSET_TAG 0x0016
+
+typedef struct {
+	nfapi_uint16_tlv_t primary_synchronization_signal_epre_eprers;
+	nfapi_uint16_tlv_t secondary_synchronization_signal_epre_eprers;
+	nfapi_uint16_tlv_t physical_cell_id;
+} nfapi_sch_config_t;
+
+#define NFAPI_SCH_CONFIG_PRIMARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG 0x001E
+#define NFAPI_SCH_CONFIG_SECONDARY_SYNCHRONIZATION_SIGNAL_EPRE_EPRERS_TAG 0x001F
+#define NFAPI_SCH_CONFIG_PHYSICAL_CELL_ID_TAG 0x0020
+
+typedef struct {
+	nfapi_uint16_tlv_t configuration_index;
+	nfapi_uint16_tlv_t root_sequence_index;
+	nfapi_uint16_tlv_t zero_correlation_zone_configuration;
+	nfapi_uint16_tlv_t high_speed_flag;
+	nfapi_uint16_tlv_t frequency_offset;
+} nfapi_prach_config_t;
+
+#define NFAPI_PRACH_CONFIG_CONFIGURATION_INDEX_TAG 0x0028
+#define NFAPI_PRACH_CONFIG_ROOT_SEQUENCE_INDEX_TAG 0x0029
+#define NFAPI_PRACH_CONFIG_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG 0x002A
+#define NFAPI_PRACH_CONFIG_HIGH_SPEED_FLAG_TAG 0x002B
+#define NFAPI_PRACH_CONFIG_FREQUENCY_OFFSET_TAG 0x002C
+
+typedef struct {
+	nfapi_uint16_tlv_t hopping_mode;
+	nfapi_uint16_tlv_t hopping_offset;
+	nfapi_uint16_tlv_t number_of_subbands;
+} nfapi_pusch_config_t;
+
+#define NFAPI_PUSCH_CONFIG_HOPPING_MODE_TAG 0x0032
+#define NFAPI_PUSCH_CONFIG_HOPPING_OFFSET_TAG 0x0033
+#define NFAPI_PUSCH_CONFIG_NUMBER_OF_SUBBANDS_TAG 0x0034
+
+typedef struct {
+	nfapi_uint16_tlv_t delta_pucch_shift;
+	nfapi_uint16_tlv_t n_cqi_rb;
+	nfapi_uint16_tlv_t n_an_cs;
+	nfapi_uint16_tlv_t n1_pucch_an;
+} nfapi_pucch_config_t;
+
+#define NFAPI_PUCCH_CONFIG_DELTA_PUCCH_SHIFT_TAG 0x003C
+#define NFAPI_PUCCH_CONFIG_N_CQI_RB_TAG 0x003D
+#define NFAPI_PUCCH_CONFIG_N_AN_CS_TAG 0x003E
+#define NFAPI_PUCCH_CONFIG_N1_PUCCH_AN_TAG 0x003F
+
+typedef struct {
+	nfapi_uint16_tlv_t bandwidth_configuration;
+	nfapi_uint16_tlv_t max_up_pts;
+	nfapi_uint16_tlv_t srs_subframe_configuration;
+	nfapi_uint16_tlv_t srs_acknack_srs_simultaneous_transmission;
+} nfapi_srs_config_t;
+
+#define NFAPI_SRS_CONFIG_BANDWIDTH_CONFIGURATION_TAG 0x0046
+#define NFAPI_SRS_CONFIG_MAX_UP_PTS_TAG 0x0047
+#define NFAPI_SRS_CONFIG_SRS_SUBFRAME_CONFIGURATION_TAG 0x0048
+#define NFAPI_SRS_CONFIG_SRS_ACKNACK_SRS_SIMULTANEOUS_TRANSMISSION_TAG 0x0049
+
+typedef struct {
+	nfapi_uint16_tlv_t uplink_rs_hopping;
+	nfapi_uint16_tlv_t group_assignment;
+	nfapi_uint16_tlv_t cyclic_shift_1_for_drms;
+} nfapi_uplink_reference_signal_config_t;
+
+#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_UPLINK_RS_HOPPING_TAG 0x0050
+#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_GROUP_ASSIGNMENT_TAG 0x0051
+#define NFAPI_UPLINK_REFERENCE_SIGNAL_CONFIG_CYCLIC_SHIFT_1_FOR_DRMS_TAG 0x0052
+
+
+typedef struct {
+	nfapi_uint16_tlv_t ed_threshold_lbt_pdsch;
+	nfapi_uint16_tlv_t ed_threshold_lbt_drs;
+	nfapi_uint16_tlv_t pd_threshold;
+	nfapi_uint16_tlv_t multi_carrier_type;
+	nfapi_uint16_tlv_t multi_carrier_tx;
+	nfapi_uint16_tlv_t multi_carrier_freeze;
+	nfapi_uint16_tlv_t tx_antenna_ports_drs;
+	nfapi_uint16_tlv_t tx_power_drs;
+} nfapi_laa_config_t;
+
+#define NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_PDSCH_TAG 0x0064
+#define NFAPI_LAA_CONFIG_ED_THRESHOLD_FOR_LBT_FOR_DRS_TAG 0x0065
+#define NFAPI_LAA_CONFIG_PD_THRESHOLD_TAG 0x0066
+#define NFAPI_LAA_CONFIG_MULTI_CARRIER_TYPE_TAG 0x0067
+#define NFAPI_LAA_CONFIG_MULTI_CARRIER_TX_TAG 0x0068
+#define NFAPI_LAA_CONFIG_MULTI_CARRIER_FREEZE_TAG 0x0069
+#define NFAPI_LAA_CONFIG_TX_ANTENNA_PORTS_FOR_DRS_TAG 0x006A
+#define NFAPI_LAA_CONFIG_TRANSMISSION_POWER_FOR_DRS_TAG 0x006B
+
+typedef struct {
+
+	nfapi_uint16_tlv_t pbch_repetitions_enable_r13;
+	nfapi_uint16_tlv_t prach_catm_root_sequence_index;
+	nfapi_uint16_tlv_t prach_catm_zero_correlation_zone_configuration;
+	nfapi_uint16_tlv_t prach_catm_high_speed_flag;
+	nfapi_uint16_tlv_t prach_ce_level_0_enable;
+	nfapi_uint16_tlv_t prach_ce_level_0_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_0_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_0_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_0_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_0_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_0_hopping_offset;
+	nfapi_uint16_tlv_t prach_ce_level_1_enable;
+	nfapi_uint16_tlv_t prach_ce_level_1_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_1_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_1_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_1_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_1_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_1_hopping_offset;
+	nfapi_uint16_tlv_t prach_ce_level_2_enable;
+	nfapi_uint16_tlv_t prach_ce_level_2_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_2_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_2_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_2_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_2_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_2_hopping_offset;
+	nfapi_uint16_tlv_t prach_ce_level_3_enable;
+	nfapi_uint16_tlv_t prach_ce_level_3_configuration_index;
+	nfapi_uint16_tlv_t prach_ce_level_3_frequency_offset;
+	nfapi_uint16_tlv_t prach_ce_level_3_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t prach_ce_level_3_starting_subframe_periodicity;
+	nfapi_uint16_tlv_t prach_ce_level_3_hopping_enable;
+	nfapi_uint16_tlv_t prach_ce_level_3_hopping_offset;
+	nfapi_uint16_tlv_t pucch_interval_ulhoppingconfigcommonmodea;
+	nfapi_uint16_tlv_t pucch_interval_ulhoppingconfigcommonmodeb;
+} nfapi_emtc_config_t;
+
+#define NFAPI_EMTC_CONFIG_PBCH_REPETITIONS_ENABLE_R13_TAG 0x0078
+#define NFAPI_EMTC_CONFIG_PRACH_CATM_ROOT_SEQUENCE_INDEX_TAG 0x0079
+#define NFAPI_EMTC_CONFIG_PRACH_CATM_ZERO_CORRELATION_ZONE_CONFIGURATION_TAG 0x007A
+#define NFAPI_EMTC_CONFIG_PRACH_CATM_HIGH_SPEED_FLAG 0x007B
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_ENABLE_TAG 0x007C
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_CONFIGURATION_INDEX_TAG 0x007D
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_FREQUENCY_OFFSET_TAG 0x007E
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x007F
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_STARTING_SUBFRAME_PERIODICITY_TAG 0x0080
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_ENABLE_TAG 0x0081
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_0_HOPPING_OFFSET_TAG 0x0082
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_ENABLE_TAG 0x0083
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_CONFIGURATION_INDEX_TAG 0x0084
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_FREQUENCY_OFFSET_TAG 0x0085
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x0086
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_STARTING_SUBFRAME_PERIODICITY_TAG 0x0087
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_ENABLE_TAG 0x0088
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_1_HOPPING_OFFSET_TAG 0x0089
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_ENABLE_TAG 0x008A
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_CONFIGURATION_INDEX_TAG 0x008B
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_FREQUENCY_OFFSET_TAG 0x008C
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x008D
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_STARTING_SUBFRAME_PERIODICITY_TAG 0x008E
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_ENABLE_TAG 0x008F
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_2_HOPPING_OFFSET_TAG 0x0090
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_ENABLE_TAG 0x0091
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_CONFIGURATION_INDEX_TAG 0x0092
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_FREQUENCY_OFFSET_TAG 0x0093
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x0094
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_STARTING_SUBFRAME_PERIODICITY_TAG 0x0095
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_ENABLE_TAG 0x0096
+#define NFAPI_EMTC_CONFIG_PRACH_CE_LEVEL_3_HOPPING_OFFSET_TAG 0x0097
+#define NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEA_TAG 0x0098
+#define NFAPI_EMTC_CONFIG_PUCCH_INTERVAL_ULHOPPINGCONFIGCOMMONMODEB_TAG 0x0099
+
+typedef struct {
+	nfapi_uint16_tlv_t operating_mode;
+	nfapi_uint16_tlv_t anchor;
+	nfapi_uint16_tlv_t prb_index;
+	nfapi_uint16_tlv_t control_region_size;
+	nfapi_uint16_tlv_t assumed_crs_aps;
+	nfapi_uint16_tlv_t nprach_config_0_enabled;
+	nfapi_uint16_tlv_t nprach_config_0_sf_periodicity;
+	nfapi_uint16_tlv_t nprach_config_0_start_time;
+	nfapi_uint16_tlv_t nprach_config_0_subcarrier_offset;
+	nfapi_uint16_tlv_t nprach_config_0_number_of_subcarriers;
+	nfapi_uint16_tlv_t nprach_config_0_cp_length;
+	nfapi_uint16_tlv_t nprach_config_0_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t nprach_config_1_enabled;
+	nfapi_uint16_tlv_t nprach_config_1_sf_periodicity;
+	nfapi_uint16_tlv_t nprach_config_1_start_time;
+	nfapi_uint16_tlv_t nprach_config_1_subcarrier_offset;
+	nfapi_uint16_tlv_t nprach_config_1_number_of_subcarriers;
+	nfapi_uint16_tlv_t nprach_config_1_cp_length;
+	nfapi_uint16_tlv_t nprach_config_1_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t nprach_config_2_enabled;
+	nfapi_uint16_tlv_t nprach_config_2_sf_periodicity;
+	nfapi_uint16_tlv_t nprach_config_2_start_time;
+	nfapi_uint16_tlv_t nprach_config_2_subcarrier_offset;
+	nfapi_uint16_tlv_t nprach_config_2_number_of_subcarriers;
+	nfapi_uint16_tlv_t nprach_config_2_cp_length;
+	nfapi_uint16_tlv_t nprach_config_2_number_of_repetitions_per_attempt;
+	nfapi_uint16_tlv_t three_tone_base_sequence;
+	nfapi_uint16_tlv_t six_tone_base_sequence;
+	nfapi_uint16_tlv_t twelve_tone_base_sequence;
+	nfapi_uint16_tlv_t three_tone_cyclic_shift;
+	nfapi_uint16_tlv_t six_tone_cyclic_shift;
+	nfapi_uint16_tlv_t dl_gap_config_enable;
+	nfapi_uint16_tlv_t dl_gap_threshold;
+	nfapi_uint16_tlv_t dl_gap_periodicity;
+	nfapi_uint16_tlv_t dl_gap_duration_coefficient;
+} nfapi_config_NB_IoT_t;
+
+#define NFAPI_NB_IOT_CONFIG_OPERATING_MODE_TAG 0x00A5
+#define NFAPI_NB_IOT_CONFIG_ANCHOR_TAG 0x00A6
+#define NFAPI_NB_IOT_CONFIG_PRB_INDEX_TAG 0x00A7
+#define NFAPI_NB_IOT_CONFIG_CONTROL_REGION_SIZE_TAG 0x00A8
+#define NFAPI_NB_IOT_CONFIG_ASSUMED_CRS_APS_TAG 0x00A9
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_ENABLED_TAG 0x00AA
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SF_PERIODICITY_TAG 0x00AB
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_START_TIME_TAG 0x00AC
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_SUBCARRIER_OFFSET_TAG 0x00AD
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_SUBCARRIERS_TAG 0x00AE
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_CP_LENGTH_TAG 0x00AF
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_0_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00B0
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_ENABLED_TAG 0x00B1
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SF_PERIODICITY_TAG 0x00B2
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_START_TIME_TAG 0x00B3
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_SUBCARRIER_OFFSET_TAG 0x00B4
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_SUBCARRIERS_TAG 0x00B5
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_CP_LENGTH_TAG 0x00B6
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_1_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00B7
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_ENABLED_TAG 0x00B8
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SF_PERIODICITY_TAG 0x00B9
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_START_TIME_TAG 0x00BA
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_SUBCARRIER_OFFSET_TAG 0x00BB
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_SUBCARRIERS_TAG 0x00BC
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_CP_LENGTH_TAG 0x00BD
+#define NFAPI_NB_IOT_CONFIG_NPRACH_CONFIG_2_NUMBER_OF_REPETITIONS_PER_ATTEMPT_TAG 0x00BE
+#define NFAPI_NB_IOT_CONFIG_THREE_TONE_BASE_SEQUENCE_TAG 0x00BF
+#define NFAPI_NB_IOT_CONFIG_SIX_TONE_BASE_SEQUENCE_TAG 0x00C0
+#define NFAPI_NB_IOT_CONFIG_TWELVE_TONE_BASE_SEQUENCE_TAG 0x00C1
+#define NFAPI_NB_IOT_CONFIG_THREE_TONE_CYCLIC_SHIFT_TAG 0x00C2
+#define NFAPI_NB_IOT_CONFIG_SIX_TONE_CYCLIC_SHIFT_TAG 0x00C3
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_CONFIG_ENABLE_TAG 0x00C4
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_THRESHOLD_TAG 0x00C5
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_PERIODICITY_TAG 0x00C6
+#define NFAPI_NB_IOT_CONFIG_DL_GAP_DURATION_COEFFICIENT_TAG 0x00C7
+
+typedef struct {
+	nfapi_uint16_tlv_t laa_support;
+	nfapi_uint16_tlv_t pd_sensing_lbt_support;
+	nfapi_uint16_tlv_t multi_carrier_lbt_support;
+	nfapi_uint16_tlv_t partial_sf_support;
+} nfapi_laa_capability_t;
+
+#define NFAPI_LAA_CAPABILITY_LAA_SUPPORT_TAG 0x00D1
+#define NFAPI_LAA_CAPABILITY_PD_SENSING_LBT_SUPPORT_TAG 0x00D2
+#define NFAPI_LAA_CAPABILITY_MULTI_CARRIER_LBT_SUPPORT_TAG 0x00D3
+#define NFAPI_LAA_CAPABILITY_PARTIAL_SF_SUPPORT_TAG 0x00D4
+
+typedef struct {
+	nfapi_uint16_tlv_t nb_iot_support;
+	nfapi_uint16_tlv_t nb_iot_operating_mode_capability;
+} nfapi_nb_iot_capability_t;
+
+#define NFAPI_LAA_CAPABILITY_NB_IOT_SUPPORT_TAG 0x00D5
+#define NFAPI_LAA_CAPABILITY_NB_IOT_OPERATING_MODE_CAPABILITY_TAG 0x00D6
+
+typedef struct {
+	nfapi_uint16_tlv_t subframe_assignment;
+	nfapi_uint16_tlv_t special_subframe_patterns;
+} nfapi_tdd_frame_structure_t;
+
+#define NFAPI_TDD_FRAME_STRUCTURE_SUBFRAME_ASSIGNMENT_TAG 0x005A
+#define NFAPI_TDD_FRAME_STRUCTURE_SPECIAL_SUBFRAME_PATTERNS_TAG 0x005B
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_rf_bands;
+	uint16_t rf_band[NFAPI_MAX_NUM_RF_BANDS];
+} nfapi_rf_bands_t;
+#define NFAPI_PHY_RF_BANDS_TAG 0x0114
+
+#define NFAPI_IPV4_ADDRESS_LENGTH 4
+#define NFAPI_IPV6_ADDRESS_LENGTH 16
+
+// Convience enum to allow the ip addres type to be distinguished
+typedef enum {
+	NFAPI_IP_ADDRESS_IPV4 = 0,
+	NFAPI_IP_ADDRESS_IPV6
+} nfapi_ip_address_type_e;
+
+// The type could be infered from the length, but it is clearer in 
+// code to have a type variable set
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t type;
+	union {
+		uint8_t ipv4_address[NFAPI_IPV4_ADDRESS_LENGTH];
+		uint8_t ipv6_address[NFAPI_IPV6_ADDRESS_LENGTH];
+	} u;
+} nfapi_ip_address_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t address[NFAPI_IPV4_ADDRESS_LENGTH];
+} nfapi_ipv4_address_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t address[NFAPI_IPV6_ADDRESS_LENGTH];
+} nfapi_ipv6_address_t;
+
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_rf_bands;
+	uint16_t bands[NFAPI_MAX_NMM_FREQUENCY_BANDS];
+} nfapi_nmm_frequency_bands_t;
+
+//These TLVs are used exclusively by nFAPI
+typedef struct
+{
+	// These TLVs are used to setup the transport connection between VNF and PNF
+	nfapi_ipv4_address_t p7_vnf_address_ipv4;
+	nfapi_ipv6_address_t p7_vnf_address_ipv6;
+	nfapi_uint16_tlv_t p7_vnf_port;
+
+	nfapi_ipv4_address_t p7_pnf_address_ipv4;
+	nfapi_ipv6_address_t p7_pnf_address_ipv6;
+	nfapi_uint16_tlv_t p7_pnf_port;
+	
+	// These TLVs are used to setup the transport connection between VNF and PNF
+	nfapi_uint8_tlv_t dl_ue_per_sf;
+	nfapi_uint8_tlv_t ul_ue_per_sf;
+
+	// These TLVs are used by PNF to report its RF capabilities to the VNF software
+	nfapi_rf_bands_t rf_bands;
+
+	// These TLVs are used by the VNF to configure the synchronization with the PNF.
+	nfapi_uint8_tlv_t timing_window;
+	nfapi_uint8_tlv_t timing_info_mode;
+	nfapi_uint8_tlv_t timing_info_period;
+
+	// These TLVs are used by the VNF to configure the RF in the PNF
+	nfapi_uint16_tlv_t max_transmit_power;
+	nfapi_uint16_tlv_t earfcn;
+
+	nfapi_nmm_frequency_bands_t nmm_gsm_frequency_bands;
+	nfapi_nmm_frequency_bands_t nmm_umts_frequency_bands;
+	nfapi_nmm_frequency_bands_t nmm_lte_frequency_bands;
+	nfapi_uint8_tlv_t nmm_uplink_rssi_supported;
+
+} nfapi_nfapi_t;
+
+#define NFAPI_NFAPI_P7_VNF_ADDRESS_IPV4_TAG 0x0100
+#define NFAPI_NFAPI_P7_VNF_ADDRESS_IPV6_TAG 0x0101
+#define NFAPI_NFAPI_P7_VNF_PORT_TAG 0x0102
+#define NFAPI_NFAPI_P7_PNF_ADDRESS_IPV4_TAG 0x0103
+#define NFAPI_NFAPI_P7_PNF_ADDRESS_IPV6_TAG 0x0104
+#define NFAPI_NFAPI_P7_PNF_PORT_TAG 0x0105
+
+#define NFAPI_NFAPI_DOWNLINK_UES_PER_SUBFRAME_TAG 0x010A
+#define NFAPI_NFAPI_UPLINK_UES_PER_SUBFRAME_TAG 0x010B
+#define NFAPI_NFAPI_RF_BANDS_TAG 0x0114
+#define NFAPI_NFAPI_TIMING_WINDOW_TAG 0x011E
+#define NFAPI_NFAPI_TIMING_INFO_MODE_TAG 0x011F
+#define NFAPI_NFAPI_TIMING_INFO_PERIOD_TAG 0x0120
+#define NFAPI_NFAPI_MAXIMUM_TRANSMIT_POWER_TAG 0x0128
+#define NFAPI_NFAPI_EARFCN_TAG 0x0129
+#define NFAPI_NFAPI_NMM_GSM_FREQUENCY_BANDS_TAG 0x0130
+#define NFAPI_NFAPI_NMM_UMTS_FREQUENCY_BANDS_TAG 0x0131
+#define NFAPI_NFAPI_NMM_LTE_FREQUENCY_BANDS_TAG 0x0132
+#define NFAPI_NFAPI_NMM_UPLINK_RSSI_SUPPORTED_TAG 0x0133
+
+
+// P5 Message Structures
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_param_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_pnf_param_general_t pnf_param_general;
+	nfapi_pnf_phy_t pnf_phy;
+	nfapi_pnf_rf_t pnf_rf;
+	nfapi_pnf_phy_rel10_t pnf_phy_rel10;
+	nfapi_pnf_phy_rel11_t pnf_phy_rel11;
+	nfapi_pnf_phy_rel12_t pnf_phy_rel12;
+	nfapi_pnf_phy_rel13_t pnf_phy_rel13;
+	nfapi_pnf_phy_rel13_nb_iot_t pnf_phy_rel13_nb_iot;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_param_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_pnf_phy_rf_config_t pnf_phy_rf_config;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_config_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_config_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_start_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_start_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_stop_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_pnf_stop_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_param_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t error_code;
+	uint8_t num_tlv;
+	// fdd or tdd in idle or configured tlvs
+	nfapi_l1_status l1_status;
+	nfapi_phy_capabilities_t phy_capabilities;
+	nfapi_laa_capability_t laa_capability;
+	nfapi_nb_iot_capability_t nb_iot_capability;
+	
+	nfapi_subframe_config_t subframe_config;
+	nfapi_rf_config_t rf_config;
+	nfapi_phich_config_t phich_config;
+	nfapi_sch_config_t sch_config;
+	nfapi_prach_config_t prach_config;
+	nfapi_pusch_config_t pusch_config;
+	nfapi_pucch_config_t pucch_config;
+	nfapi_srs_config_t srs_config;
+	nfapi_uplink_reference_signal_config_t uplink_reference_signal_config;
+	nfapi_tdd_frame_structure_t tdd_frame_structure_config;
+	nfapi_l23_config_t l23_config;
+	nfapi_config_NB_IoT_t config_NB_IoT;
+
+	// addition nfapi tlvs as per table 2-16 in idle or configure
+	nfapi_nfapi_t nfapi_config;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_param_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t num_tlv;
+	nfapi_subframe_config_t subframe_config;
+	nfapi_rf_config_t rf_config;
+	nfapi_phich_config_t phich_config;
+	nfapi_sch_config_t sch_config;
+	nfapi_prach_config_t prach_config;
+	nfapi_pusch_config_t pusch_config;
+	nfapi_pucch_config_t pucch_config;
+	nfapi_srs_config_t srs_config;
+	nfapi_uplink_reference_signal_config_t uplink_reference_signal_config;
+	nfapi_laa_config_t laa_config;
+	nfapi_emtc_config_t emtc_config;
+	nfapi_tdd_frame_structure_t tdd_frame_structure_config;
+	nfapi_l23_config_t l23_config;
+	nfapi_config_NB_IoT_t config_NB_IoT;
+	
+	// addition nfapi tlvs as per table 2-16 in idle or configure
+	nfapi_nfapi_t nfapi_config;
+
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_config_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_config_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_start_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_start_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_stop_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_stop_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_uint16_tlv_t dl_rs_tx_power;
+	nfapi_uint16_tlv_t received_interference_power;
+	nfapi_uint16_tlv_t thermal_noise_power;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_measurement_request_t;
+
+#define NFAPI_MEASUREMENT_REQUEST_DL_RS_XTX_POWER_TAG 0x1004
+#define NFAPI_MEASUREMENT_REQUEST_RECEIVED_INTERFERENCE_POWER_TAG 0x1005
+#define NFAPI_MEASUREMENT_REQUEST_THERMAL_NOISE_POWER_TAG 0x1006
+
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_resource_blocks;
+	int16_t received_interference_power[NFAPI_MAX_RECEIVED_INTERFERENCE_POWER_RESULTS];
+} nfapi_received_interference_power_measurement_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_int16_tlv_t dl_rs_tx_power_measurement;
+	nfapi_received_interference_power_measurement_t received_interference_power_measurement;
+	nfapi_int16_tlv_t thermal_noise_power_measurement;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_measurement_response_t;
+
+#define NFAPI_MEASUREMENT_RESPONSE_DL_RS_POWER_MEASUREMENT_TAG 0x1007
+#define NFAPI_MEASUREMENT_RESPONSE_RECEIVED_INTERFERENCE_POWER_MEASUREMENT_TAG 0x1008
+#define NFAPI_MEASUREMENT_RESPONSE_THERMAL_NOISE_MEASUREMENT_TAG 0x1009
+
+// P7 Sub Structures
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dci_format;
+	uint8_t cce_idx;
+	uint8_t aggregation_level;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t mcs_1;
+	uint8_t redundancy_version_1;
+	uint8_t new_data_indicator_1;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t mcs_2;
+	uint8_t redundancy_version_2;
+	uint8_t new_data_indicator_2;
+	uint8_t harq_process;
+	uint8_t tpmi;
+	uint8_t pmi;
+	uint8_t precoding_information;
+	uint8_t tpc;
+	uint8_t downlink_assignment_index;
+	uint8_t ngap;
+	uint8_t transport_block_size_index;
+	uint8_t downlink_power_offset;
+	uint8_t allocate_prach_flag;
+	uint8_t preamble_index;
+	uint8_t prach_mask_index;
+	uint8_t rnti_type;
+	uint16_t transmission_power;
+} nfapi_dl_config_dci_dl_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG 0x2001
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mcch_flag;
+	uint8_t mcch_change_notification;
+	uint8_t scrambling_identity;
+} nfapi_dl_config_dci_dl_pdu_rel9_t;
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL9_TAG 0x2002
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t cross_carrier_scheduling_flag;
+	uint8_t carrier_indicator;
+	uint8_t srs_flag;
+	uint8_t srs_request;
+	uint8_t antenna_ports_scrambling_and_layers;
+	uint8_t total_dci_length_including_padding;
+	uint8_t n_dl_rb;
+} nfapi_dl_config_dci_dl_pdu_rel10_t;
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL10_TAG 0x2003
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t harq_ack_resource_offset;
+	uint8_t pdsch_re_mapping_quasi_co_location_indicator;
+} nfapi_dl_config_dci_dl_pdu_rel11_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL11_TAG 0x2039
+
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t primary_cell_type;
+	uint8_t ul_dl_configuration_flag;
+	uint8_t number_ul_dl_configurations;
+	uint8_t ul_dl_configuration_indication[NFAPI_MAX_UL_DL_CONFIGURATIONS];
+} nfapi_dl_config_dci_dl_pdu_rel12_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL12_TAG 0x203a
+
+
+
+typedef struct {
+	uint8_t subband_index;
+	uint8_t scheduled_ues;
+	uint16_t precoding_value[NFAPI_MAX_NUM_PHYSICAL_ANTENNAS][NFAPI_MAX_NUM_SCHEDULED_UES];
+} nfapi_dl_config_dci_dl_tpm_subband_info_t;
+
+typedef struct {
+	uint8_t num_prb_per_subband;
+	uint8_t number_of_subbands;
+	uint8_t num_antennas;
+	nfapi_dl_config_dci_dl_tpm_subband_info_t subband_info[NFAPI_MAX_NUM_SUBBANDS];
+} nfapi_dl_config_dci_dl_tpm_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t laa_end_partial_sf_flag;
+	uint8_t laa_end_partial_sf_configuration;
+	uint8_t initial_lbt_sf;
+	uint8_t codebook_size_determination;
+	uint8_t drms_table_flag;
+	uint8_t tpm_struct_flag;
+	nfapi_dl_config_dci_dl_tpm_t tpm;
+} nfapi_dl_config_dci_dl_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL13_TAG 0x203b
+
+typedef struct {
+	nfapi_dl_config_dci_dl_pdu_rel8_t dci_dl_pdu_rel8;
+	nfapi_dl_config_dci_dl_pdu_rel9_t dci_dl_pdu_rel9;
+	nfapi_dl_config_dci_dl_pdu_rel10_t dci_dl_pdu_rel10;
+	nfapi_dl_config_dci_dl_pdu_rel11_t dci_dl_pdu_rel11;
+	nfapi_dl_config_dci_dl_pdu_rel12_t dci_dl_pdu_rel12;
+	nfapi_dl_config_dci_dl_pdu_rel13_t dci_dl_pdu_rel13;
+} nfapi_dl_config_dci_dl_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t transmission_power;
+} nfapi_dl_config_bch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_BCH_PDU_REL8_TAG 0x2004
+
+typedef struct {
+	nfapi_dl_config_bch_pdu_rel8_t bch_pdu_rel8;
+} nfapi_dl_config_bch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t modulation;
+	uint16_t transmission_power;
+	uint16_t mbsfn_area_id;
+} nfapi_dl_config_mch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG 0x2005
+
+typedef struct {
+	nfapi_dl_config_mch_pdu_rel8_t mch_pdu_rel8;
+} nfapi_dl_config_mch_pdu;
+
+
+typedef struct {
+	uint8_t subband_index;
+	uint8_t num_antennas;
+	uint16_t bf_value[NFAPI_MAX_NUM_ANTENNAS];
+} nfapi_bf_vector_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t modulation;
+	uint8_t redundancy_version;
+	uint8_t transport_blocks;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t number_of_subbands;
+	uint8_t codebook_index[NFAPI_MAX_NUM_SUBBANDS];
+	uint8_t ue_category_capacity;
+	uint8_t pa;
+	uint8_t delta_power_offset_index;
+	uint8_t ngap;
+	uint8_t nprb;
+	uint8_t transmission_mode;
+	uint8_t num_bf_prb_per_subband;
+	uint8_t num_bf_vector;
+	nfapi_bf_vector_t bf_vector[NFAPI_MAX_BF_VECTORS];
+} nfapi_dl_config_dlsch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG 0x2006
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t nscid;
+} nfapi_dl_config_dlsch_pdu_rel9_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL9_TAG 0x2007
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_rs_flag;
+	uint8_t csi_rs_resource_config_r10;
+	uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10;
+	uint8_t csi_rs_number_nzp_configuration;
+	uint8_t csi_rs_resource_config[NFAPI_MAX_CSI_RS_RESOURCE_CONFIG];
+	uint8_t pdsch_start;
+} nfapi_dl_config_dlsch_pdu_rel10_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL10_TAG 0x2008
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t drms_config_flag;
+	uint16_t drms_scrambling;
+	uint8_t csi_config_flag;
+	uint16_t csi_scrambling;
+	uint8_t pdsch_re_mapping_flag;
+	uint8_t pdsch_re_mapping_atenna_ports;
+	uint8_t pdsch_re_mapping_freq_shift;
+} nfapi_dl_config_dlsch_pdu_rel11_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL11_TAG 0x203C
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t altcqi_table_r12;
+	uint8_t maxlayers;
+	uint8_t n_dl_harq;
+} nfapi_dl_config_dlsch_pdu_rel12_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL12_TAG 0x203D
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dwpts_symbols;
+	uint8_t initial_lbt_sf;
+	uint8_t ue_type;
+	uint8_t pdsch_payload_type;
+	uint16_t initial_transmission_sf_io;
+	uint8_t drms_table_flag;
+} nfapi_dl_config_dlsch_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL13_TAG 0x203E
+
+typedef struct {
+	nfapi_dl_config_dlsch_pdu_rel8_t dlsch_pdu_rel8;
+	nfapi_dl_config_dlsch_pdu_rel9_t dlsch_pdu_rel9;
+	nfapi_dl_config_dlsch_pdu_rel10_t dlsch_pdu_rel10;
+	nfapi_dl_config_dlsch_pdu_rel11_t dlsch_pdu_rel11;
+	nfapi_dl_config_dlsch_pdu_rel12_t dlsch_pdu_rel12;
+	nfapi_dl_config_dlsch_pdu_rel13_t dlsch_pdu_rel13;
+} nfapi_dl_config_dlsch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t p_rnti;
+	uint8_t resource_allocation_type;
+	uint8_t virtual_resource_block_assignment_flag;
+	uint32_t resource_block_coding;
+	uint8_t mcs;
+	uint8_t redundancy_version;
+	uint8_t number_of_transport_blocks;
+	uint8_t transport_block_to_codeword_swap_flag;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t codebook_index;
+	uint8_t ue_category_capacity;
+	uint8_t pa;
+	uint16_t transmission_power;
+	uint8_t nprb;
+	uint8_t ngap;
+} nfapi_dl_config_pch_pdu_rel8_t;
+#define NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL8_TAG 0x2009
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t ue_mode;
+	uint16_t initial_transmission_sf_io;
+} nfapi_dl_config_pch_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_PCH_PDU_REL13_TAG 0x203F
+
+typedef struct {
+	nfapi_dl_config_pch_pdu_rel8_t pch_pdu_rel8;
+	nfapi_dl_config_pch_pdu_rel13_t pch_pdu_rel13;
+} nfapi_dl_config_pch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t transmission_power;
+	uint8_t prs_bandwidth;
+	uint8_t prs_cyclic_prefix_type;
+	uint8_t prs_muting;
+} nfapi_dl_config_prs_pdu_rel9_t;
+#define NFAPI_DL_CONFIG_REQUEST_PRS_PDU_REL9_TAG 0x200A
+
+typedef struct {
+	nfapi_dl_config_prs_pdu_rel9_t prs_pdu_rel9;
+} nfapi_dl_config_prs_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_rs_antenna_port_count_r10;
+	uint8_t csi_rs_resource_config_r10;
+	uint16_t transmission_power;
+	uint16_t csi_rs_zero_tx_power_resource_config_bitmap_r10;
+	uint8_t csi_rs_number_of_nzp_configuration;
+	uint8_t csi_rs_resource_config[NFAPI_MAX_CSI_RS_RESOURCE_CONFIG];
+} nfapi_dl_config_csi_rs_pdu_rel10_t;
+#define NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL10_TAG 0x200B
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_rs_class;
+	uint8_t cdm_type;
+	uint8_t num_bf_vector;
+	struct {
+		uint8_t csi_rs_resource_index;
+		uint16_t bf_value[NFAPI_MAX_ANTENNA_PORT_COUNT];
+	} bf_vector[NFAPI_MAX_BF_VECTORS];
+
+}nfapi_dl_config_csi_rs_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_CSI_RS_PDU_REL13_TAG 0x2040
+
+typedef struct {
+	nfapi_dl_config_csi_rs_pdu_rel10_t csi_rs_pdu_rel10;
+	nfapi_dl_config_csi_rs_pdu_rel13_t csi_rs_pdu_rel13;
+} nfapi_dl_config_csi_rs_pdu;
+
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL8_TAG 0x2001
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL9_TAG 0x2002
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL10_TAG 0x2003
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL11_TAG 0x2039
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL12_TAG 0x203a
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PDU_REL13_TAG 0x203b
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t epdcch_resource_assignment_flag;
+	uint16_t epdcch_id;
+	uint8_t epdcch_start_symbol;
+	uint8_t epdcch_num_prb;
+	uint8_t epdcch_prb_index[NFAPI_MAX_EPDCCH_PRB];
+	nfapi_bf_vector_t bf_vector;
+} nfapi_dl_config_epdcch_parameters_rel11_t;
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL11_TAG 0x2041
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dwpts_symbols;
+	uint8_t initial_lbt_sf;
+} nfapi_dl_config_epdcch_parameters_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_EPDCCH_PARAM_REL13_TAG 0x2042
+
+typedef struct {
+	nfapi_dl_config_dci_dl_pdu_rel8_t			epdcch_pdu_rel8;
+	nfapi_dl_config_dci_dl_pdu_rel9_t			epdcch_pdu_rel9;
+	nfapi_dl_config_dci_dl_pdu_rel10_t			epdcch_pdu_rel10;
+	nfapi_dl_config_dci_dl_pdu_rel11_t			epdcch_pdu_rel11;
+	nfapi_dl_config_dci_dl_pdu_rel12_t			epdcch_pdu_rel12;
+	nfapi_dl_config_dci_dl_pdu_rel13_t			epdcch_pdu_rel13;
+	nfapi_dl_config_epdcch_parameters_rel11_t	epdcch_params_rel11;
+	nfapi_dl_config_epdcch_parameters_rel13_t	epdcch_params_rel13;
+} nfapi_dl_config_epdcch_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mpdcch_narrow_band;
+	uint8_t number_of_prb_pairs;
+	uint8_t resource_block_assignment;
+	uint8_t mpdcch_tansmission_type;
+	uint8_t start_symbol;
+	uint8_t ecce_index;
+	uint8_t aggregation_level;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t ce_mode;
+	uint16_t drms_scrambling_init;
+	uint16_t initial_transmission_sf_io;
+	uint16_t transmission_power;
+	uint8_t dci_format;
+	uint16_t resource_block_coding;
+	uint8_t mcs;
+	uint8_t pdsch_reptition_levels;
+	uint8_t redundancy_version;
+	uint8_t new_data_indicator;
+	uint8_t harq_process;
+	uint8_t tpmi_length;
+	uint8_t tpmi;
+	uint8_t pmi_flag;
+	uint8_t pmi;
+	uint8_t harq_resource_offset;
+	uint8_t dci_subframe_repetition_number;
+	uint8_t tpc;
+	uint8_t downlink_assignment_index_length;
+	uint8_t downlink_assignment_index;
+	uint8_t allocate_prach_flag;
+	uint8_t preamble_index;
+	uint8_t prach_mask_index;
+	uint8_t starting_ce_level;
+	uint8_t srs_request;
+	uint8_t antenna_ports_and_scrambling_identity_flag;
+	uint8_t antenna_ports_and_scrambling_identity;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t paging_direct_indication_differentiation_flag;
+	uint8_t direct_indication;
+	uint8_t total_dci_length_including_padding;
+	uint8_t number_of_tx_antenna_ports;
+	uint16_t precoding_value[NFAPI_MAX_TX_PHYSICAL_ANTENNA_PORTS];
+} nfapi_dl_config_mpdcch_pdu_rel13_t;
+#define NFAPI_DL_CONFIG_REQUEST_MPDCCH_PDU_REL13_TAG 0x205B
+
+
+typedef struct {
+	nfapi_dl_config_mpdcch_pdu_rel13_t mpdcch_pdu_rel13;
+} nfapi_dl_config_mpdcch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint16_t transmission_power;
+	uint16_t hyper_sfn_2_lsbs;
+} nfapi_dl_config_nbch_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_NBCH_PDU_REL13_TAG 0x205C
+
+typedef struct {
+	nfapi_dl_config_nbch_pdu_rel13_t nbch_pdu_rel13;
+} nfapi_dl_config_nbch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint8_t ncce_index;
+	uint8_t aggregation_level;
+	uint8_t start_symbol;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t scrambling_reinitialization_batch_index;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+	uint8_t dci_format;
+	uint8_t scheduling_delay;
+	uint8_t resource_assignment;
+	uint8_t repetition_number;
+	uint8_t mcs;
+	uint8_t new_data_indicator;
+	uint8_t harq_ack_resource;
+	uint8_t npdcch_order_indication;
+	uint8_t starting_number_of_nprach_repetitions;
+	uint8_t subcarrier_indication_of_nprach;
+	uint8_t paging_direct_indication_differentation_flag;
+	uint8_t direct_indication;
+	uint8_t dci_subframe_repetition_number;
+	uint8_t total_dci_length_including_padding;
+} nfapi_dl_config_npdcch_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_NPDCCH_PDU_REL13_TAG 0x205D
+
+typedef struct {
+	nfapi_dl_config_npdcch_pdu_rel13_t npdcch_pdu_rel13;
+} nfapi_dl_config_npdcch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t pdu_index;
+	uint8_t start_symbol;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint16_t resource_assignment;
+	uint16_t repetition_number;
+	uint8_t modulation;
+	uint8_t number_of_subframes_for_resource_assignment;
+	uint8_t scrambling_sequence_initialization_cinit;
+	uint16_t sf_idx;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+} nfapi_dl_config_ndlsch_pdu_rel13_t;
+
+#define NFAPI_DL_CONFIG_REQUEST_NDLSCH_PDU_REL13_TAG 0x205E
+
+typedef struct {
+	nfapi_dl_config_ndlsch_pdu_rel13_t ndlsch_pdu_rel13;
+} nfapi_dl_config_ndlsch_pdu;
+
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_dl_config_dci_dl_pdu	dci_dl_pdu;
+		nfapi_dl_config_bch_pdu		bch_pdu;
+		nfapi_dl_config_mch_pdu		mch_pdu;
+		nfapi_dl_config_dlsch_pdu	dlsch_pdu;
+		nfapi_dl_config_pch_pdu		pch_pdu;
+		nfapi_dl_config_prs_pdu		prs_pdu;
+		nfapi_dl_config_csi_rs_pdu	csi_rs_pdu;
+		nfapi_dl_config_epdcch_pdu	epdcch_pdu;
+		nfapi_dl_config_mpdcch_pdu	mpdcch_pdu;
+		nfapi_dl_config_nbch_pdu	nbch_pdu;
+		nfapi_dl_config_npdcch_pdu	npdcch_pdu;
+		nfapi_dl_config_ndlsch_pdu	ndlsch_pdu;
+	};
+} nfapi_dl_config_request_pdu_t;
+
+#define NFAPI_DL_CONFIG_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_pdcch_ofdm_symbols;
+	uint8_t number_dci;
+	uint16_t number_pdu;
+	uint8_t number_pdsch_rnti;
+	uint16_t transmission_power_pcfich;
+	nfapi_dl_config_request_pdu_t* dl_config_pdu_list;
+} nfapi_dl_config_request_body_t;
+#define NFAPI_DL_CONFIG_REQUEST_BODY_TAG 0x2000
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t modulation_type;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_bits;
+	uint8_t new_data_indication;
+	uint8_t redundancy_version;
+	uint8_t harq_process_number;
+	uint8_t ul_tx_mode;
+	uint8_t current_tx_nb;
+	uint8_t n_srs;
+} nfapi_ul_config_ulsch_pdu_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG 0x200D
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t transport_blocks;
+	uint8_t transmission_scheme;
+	uint8_t number_of_layers;
+	uint8_t codebook_index;
+	uint8_t disable_sequence_hopping_flag;
+} nfapi_ul_config_ulsch_pdu_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL10_TAG 0x200E
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t virtual_cell_id_enabled_flag;
+	uint16_t npusch_identity;
+	uint8_t dmrs_config_flag;
+	uint16_t ndmrs_csh_identity;
+} nfapi_ul_config_ulsch_pdu_rel11_t;
+
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL11_TAG 0x2043
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t  ue_type;
+	uint16_t total_number_of_repetitions;
+	uint16_t repetition_number;
+	uint16_t initial_transmission_sf_io;
+	uint8_t  empty_symbols_due_to_re_tunning;
+} nfapi_ul_config_ulsch_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG 0x2044
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu_rel8_t ulsch_pdu_rel8;
+	nfapi_ul_config_ulsch_pdu_rel10_t ulsch_pdu_rel10;
+	nfapi_ul_config_ulsch_pdu_rel11_t ulsch_pdu_rel11;
+	nfapi_ul_config_ulsch_pdu_rel13_t ulsch_pdu_rel13;
+} nfapi_ul_config_ulsch_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dl_cqi_pmi_size_rank_1;
+	uint8_t dl_cqi_pmi_size_rank_greater_1;
+	uint8_t ri_size;
+	uint8_t delta_offset_cqi;
+	uint8_t delta_offset_ri;
+} nfapi_ul_config_cqi_ri_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL8_TAG 0x2010
+
+typedef struct {
+	uint8_t dl_cqi_pmi_ri_size;
+	uint8_t control_type;
+} nfapi_ul_config_periodic_cqi_pmi_ri_report_t;
+
+typedef struct {
+	uint8_t number_of_cc;
+	struct {
+		uint8_t ri_size;
+		uint8_t dl_cqi_pmi_size;
+	} cc[NFAPI_MAX_CC];
+} nfapi_ul_config_aperiodic_cqi_pmi_ri_report_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t report_type;
+	uint8_t delta_offset_cqi;
+	uint8_t delta_offset_ri;
+	union {
+		nfapi_ul_config_periodic_cqi_pmi_ri_report_t periodic_cqi_pmi_ri_report;
+		nfapi_ul_config_aperiodic_cqi_pmi_ri_report_t aperiodic_cqi_pmi_ri_report;
+	};
+} nfapi_ul_config_cqi_ri_information_rel9_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG 0x2011
+
+typedef struct {
+	uint16_t dl_cqi_pmi_ri_size_2;
+} nfapi_ul_config_periodic_cqi_pmi_ri_report_re13_t;
+
+typedef struct {
+} nfapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t report_type; // Convience parameter, not sent on the wire
+	union {
+		nfapi_ul_config_periodic_cqi_pmi_ri_report_re13_t periodic_cqi_pmi_ri_report;
+		nfapi_ul_config_aperiodic_cqi_pmi_ri_report_re13_t aperiodic_cqi_pmi_ri_report;
+	};
+} nfapi_ul_config_cqi_ri_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL13_TAG 0x2045
+
+typedef struct {
+	nfapi_ul_config_cqi_ri_information_rel8_t cqi_ri_information_rel8;
+	nfapi_ul_config_cqi_ri_information_rel9_t cqi_ri_information_rel9;
+	nfapi_ul_config_cqi_ri_information_rel13_t cqi_ri_information_rel13;
+} nfapi_ul_config_cqi_ri_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t harq_size;
+	uint8_t delta_offset_harq;
+	uint8_t ack_nack_mode;
+} nfapi_ul_config_ulsch_harq_information_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG 0x2012
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t harq_size_2;
+	uint8_t delta_offset_harq_2;
+} nfapi_ul_config_ulsch_harq_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL13_TAG 0x2046
+
+typedef struct {
+	nfapi_ul_config_ulsch_harq_information_rel10_t harq_information_rel10;
+	nfapi_ul_config_ulsch_harq_information_rel13_t harq_information_rel13;
+} nfapi_ul_config_ulsch_harq_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t n_srs_initial;
+	uint8_t initial_number_of_resource_blocks;
+} nfapi_ul_config_initial_transmission_parameters_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG 0x200F
+
+typedef struct {
+	nfapi_ul_config_initial_transmission_parameters_rel8_t initial_transmission_parameters_rel8;
+} nfapi_ul_config_initial_transmission_parameters;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_ri_information cqi_ri_information;
+	nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters;
+} nfapi_ul_config_ulsch_cqi_ri_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_ulsch_harq_information harq_information;
+	nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters;
+} nfapi_ul_config_ulsch_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_ri_information cqi_ri_information;
+	nfapi_ul_config_ulsch_harq_information harq_information;
+	nfapi_ul_config_initial_transmission_parameters initial_transmission_parameters;
+} nfapi_ul_config_ulsch_cqi_harq_ri_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint16_t rnti;
+} nfapi_ul_config_ue_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG 0x2013
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t virtual_cell_id_enabled_flag;
+	uint16_t npusch_identity;
+} nfapi_ul_config_ue_information_rel11_t;
+
+#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL11_TAG 0x2047
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t  ue_type;
+	uint8_t  empty_symbols;
+	uint16_t total_number_of_repetitions;
+	uint16_t repetition_number;
+} nfapi_ul_config_ue_information_rel13_t;
+
+#define NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL13_TAG 0x2048
+
+typedef struct {
+	nfapi_ul_config_ue_information_rel8_t ue_information_rel8;
+	nfapi_ul_config_ue_information_rel11_t ue_information_rel11;
+	nfapi_ul_config_ue_information_rel13_t ue_information_rel13;
+} nfapi_ul_config_ue_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t pucch_index;
+	uint8_t dl_cqi_pmi_size;
+} nfapi_ul_config_cqi_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL8_TAG 0x2014
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_pucch_resource;
+	uint16_t pucch_index_p1;
+} nfapi_ul_config_cqi_information_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL10_TAG 0x2015
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t csi_mode;
+	uint16_t dl_cqi_pmi_size_2;
+	uint8_t starting_prb;
+	uint8_t n_prb;
+	uint8_t cdm_index;
+	uint8_t n_srs;
+} nfapi_ul_config_cqi_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_CQI_INFORMATION_REL13_TAG 0x2049
+
+typedef struct {
+	nfapi_ul_config_cqi_information_rel8_t cqi_information_rel8;
+	nfapi_ul_config_cqi_information_rel10_t cqi_information_rel10;
+	nfapi_ul_config_cqi_information_rel13_t cqi_information_rel13;
+} nfapi_ul_config_cqi_information;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t pucch_index;
+} nfapi_ul_config_sr_information_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL8_TAG 0x2016
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_pucch_resources;
+	uint16_t pucch_index_p1;
+} nfapi_ul_config_sr_information_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_SR_INFORMATION_REL10_TAG 0x2017
+
+typedef struct { 
+	nfapi_ul_config_sr_information_rel8_t sr_information_rel8;
+	nfapi_ul_config_sr_information_rel10_t sr_information_rel10;
+} nfapi_ul_config_sr_information;
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t harq_size;
+	uint8_t ack_nack_mode;
+	uint8_t number_of_pucch_resources;
+	uint16_t n_pucch_1_0;
+	uint16_t n_pucch_1_1;
+	uint16_t n_pucch_1_2;
+	uint16_t n_pucch_1_3;
+} nfapi_ul_config_harq_information_rel10_tdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG 0x2018
+
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t n_pucch_1_0;
+	uint8_t harq_size;
+} nfapi_ul_config_harq_information_rel8_fdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL8_FDD_TAG 0x2019
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t harq_size;
+	uint8_t ack_nack_mode;
+	uint8_t number_of_pucch_resources;
+	uint16_t n_pucch_1_0;
+	uint16_t n_pucch_1_1;
+	uint16_t n_pucch_1_2;
+	uint16_t n_pucch_1_3;
+} nfapi_ul_config_harq_information_rel9_fdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG 0x201a
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t  num_ant_ports;
+	uint16_t n_pucch_2_0;
+	uint16_t n_pucch_2_1;
+	uint16_t n_pucch_2_2;
+	uint16_t n_pucch_2_3;	
+} nfapi_ul_config_harq_information_rel11_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG 0x204A
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t  harq_size_2;
+	uint8_t starting_prb;
+	uint8_t n_prb;
+	uint8_t cdm_index;
+	uint8_t n_srs;
+} nfapi_ul_config_harq_information_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL13_TAG 0x204B
+
+typedef struct {
+	nfapi_ul_config_harq_information_rel10_tdd_t harq_information_rel10_tdd;
+	nfapi_ul_config_harq_information_rel8_fdd_t harq_information_rel8_fdd;
+	nfapi_ul_config_harq_information_rel9_fdd_t harq_information_rel9_fdd;
+	nfapi_ul_config_harq_information_rel11_t harq_information_rel11;
+	nfapi_ul_config_harq_information_rel13_t harq_information_rel13;
+} nfapi_ul_config_harq_information;
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t srs_bandwidth;
+	uint8_t frequency_domain_position;
+	uint8_t srs_hopping_bandwidth;
+	uint8_t transmission_comb;
+	uint16_t i_srs;
+	uint8_t sounding_reference_cyclic_shift;
+} nfapi_ul_config_srs_pdu_rel8_t;
+#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL8_TAG 0x201b
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t antenna_port;
+} nfapi_ul_config_srs_pdu_rel10_t;
+#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL10_TAG 0x201c
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t number_of_combs;
+} nfapi_ul_config_srs_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_SRS_PDU_REL13_TAG 0x204c
+
+typedef struct {
+	nfapi_ul_config_srs_pdu_rel8_t srs_pdu_rel8;
+	nfapi_ul_config_srs_pdu_rel10_t srs_pdu_rel10;
+	nfapi_ul_config_srs_pdu_rel13_t srs_pdu_rel13;
+} nfapi_ul_config_srs_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+} nfapi_ul_config_uci_cqi_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_sr_information sr_information;
+} nfapi_ul_config_uci_sr_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_sr_information sr_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_sr_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_cqi_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+	nfapi_ul_config_sr_information sr_information;
+} nfapi_ul_config_uci_cqi_sr_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_cqi_information cqi_information;
+	nfapi_ul_config_sr_information sr_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_uci_cqi_sr_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ue_information ue_information;
+} nfapi_ul_config_harq_buffer_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_information csi_information;
+} nfapi_ul_config_ulsch_uci_csi_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_ulsch_uci_harq_pdu;
+
+typedef struct {
+	nfapi_ul_config_ulsch_pdu ulsch_pdu;
+	nfapi_ul_config_cqi_information csi_information;
+	nfapi_ul_config_harq_information harq_information;
+} nfapi_ul_config_ulsch_csi_uci_harq_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t harq_ack_resource;
+} nfapi_ul_config_nb_harq_information_rel13_fdd_t;
+#define NFAPI_UL_CONFIG_REQUEST_NB_HARQ_INFORMATION_REL13_FDD_TAG 0x2061
+
+typedef struct {
+	nfapi_ul_config_nb_harq_information_rel13_fdd_t nb_harq_information_rel13_fdd;
+} nfapi_ul_config_nb_harq_information;
+
+typedef struct {
+	nfapi_tl_t tl;	
+	uint8_t nulsch_format;
+	uint32_t handle;
+	uint16_t size;
+	uint16_t rnti;
+	uint8_t subcarrier_indication;
+	uint8_t resource_assignment;
+	uint8_t mcs;
+	uint8_t redudancy_version;
+	uint8_t repetition_number;
+	uint8_t new_data_indication;
+	uint8_t n_srs;
+	uint16_t scrambling_sequence_initialization_cinit;
+	uint16_t sf_idx;
+	nfapi_ul_config_ue_information ue_information;
+	nfapi_ul_config_nb_harq_information nb_harq_information;
+} nfapi_ul_config_nulsch_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_NULSCH_PDU_REL13_TAG 0x205F
+
+typedef struct {
+	nfapi_ul_config_nulsch_pdu_rel13_t nulsch_pdu_rel13;
+} nfapi_ul_config_nulsch_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t nprach_config_0;
+	uint8_t nprach_config_1;
+	uint8_t nprach_config_2;
+} nfapi_ul_config_nrach_pdu_rel13_t;
+#define NFAPI_UL_CONFIG_REQUEST_NRACH_PDU_REL13_TAG 0x2067
+
+typedef struct {
+	nfapi_ul_config_nrach_pdu_rel13_t nrach_pdu_rel13;
+} nfapi_ul_config_nrach_pdu;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_ul_config_ulsch_pdu				ulsch_pdu;
+		nfapi_ul_config_ulsch_cqi_ri_pdu		ulsch_cqi_ri_pdu;
+		nfapi_ul_config_ulsch_harq_pdu			ulsch_harq_pdu;
+		nfapi_ul_config_ulsch_cqi_harq_ri_pdu	ulsch_cqi_harq_ri_pdu;
+		nfapi_ul_config_uci_cqi_pdu				uci_cqi_pdu;
+		nfapi_ul_config_uci_sr_pdu				uci_sr_pdu;
+		nfapi_ul_config_uci_harq_pdu			uci_harq_pdu;
+		nfapi_ul_config_uci_sr_harq_pdu			uci_sr_harq_pdu;
+		nfapi_ul_config_uci_cqi_harq_pdu		uci_cqi_harq_pdu;
+		nfapi_ul_config_uci_cqi_sr_pdu			uci_cqi_sr_pdu;
+		nfapi_ul_config_uci_cqi_sr_harq_pdu		uci_cqi_sr_harq_pdu;
+		nfapi_ul_config_srs_pdu					srs_pdu;
+		nfapi_ul_config_harq_buffer_pdu			harq_buffer_pdu;
+		nfapi_ul_config_ulsch_uci_csi_pdu		ulsch_uci_csi_pdu;
+		nfapi_ul_config_ulsch_uci_harq_pdu		ulsch_uci_harq_pdu;
+		nfapi_ul_config_ulsch_csi_uci_harq_pdu	ulsch_csi_uci_harq_pdu;
+		nfapi_ul_config_nulsch_pdu				nulsch_pdu;
+		nfapi_ul_config_nrach_pdu				nrach_pdu;
+	};
+} nfapi_ul_config_request_pdu_t;
+
+#define NFAPI_UL_CONFIG_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_pdus;
+	uint8_t rach_prach_frequency_resources;
+	uint8_t srs_present;
+	nfapi_ul_config_request_pdu_t* ul_config_pdu_list;
+} nfapi_ul_config_request_body_t;
+#define NFAPI_UL_CONFIG_REQUEST_BODY_TAG 0x200C
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t resource_block_start;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t hi_value;
+	uint8_t i_phich;
+	uint16_t transmission_power;
+} nfapi_hi_dci0_hi_pdu_rel8_t;
+#define NFAPI_HI_DCI0_REQUEST_HI_PDU_REL8_TAG 0x201e
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t flag_tb2;
+	uint8_t hi_value_2;
+} nfapi_hi_dci0_hi_pdu_rel10_t;
+#define NFAPI_HI_DCI0_REQUEST_HI_PDU_REL10_TAG 0x201f
+
+typedef struct {
+	nfapi_hi_dci0_hi_pdu_rel8_t		hi_pdu_rel8;
+	nfapi_hi_dci0_hi_pdu_rel10_t	hi_pdu_rel10;
+} nfapi_hi_dci0_hi_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t dci_format;
+	uint8_t cce_index;
+	uint8_t aggregation_level;
+	uint16_t rnti;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_block;
+	uint8_t mcs_1;
+	uint8_t cyclic_shift_2_for_drms;
+	uint8_t frequency_hopping_enabled_flag;
+	uint8_t frequency_hopping_bits;
+	uint8_t new_data_indication_1;
+	uint8_t ue_tx_antenna_seleciton;
+	uint8_t tpc;
+	uint8_t cqi_csi_request;
+	uint8_t ul_index;
+	uint8_t dl_assignment_index;
+	uint32_t tpc_bitmap;
+	uint16_t transmission_power;
+} nfapi_hi_dci0_dci_pdu_rel8_t;
+#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG 0x2020
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t cross_carrier_scheduling_flag;
+	uint8_t carrier_indicator;
+	uint8_t size_of_cqi_csi_feild;
+	uint8_t srs_flag;
+	uint8_t srs_request;
+	uint8_t resource_allocation_flag;
+	uint8_t resource_allocation_type;
+	uint32_t resource_block_coding;
+	uint8_t mcs_2;
+	uint8_t new_data_indication_2;
+	uint8_t number_of_antenna_ports;
+	uint8_t tpmi;
+	uint8_t total_dci_length_including_padding;
+	uint8_t n_ul_rb;
+} nfapi_hi_dci0_dci_pdu_rel10_t;
+#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL10_TAG 0x2021
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t pscch_resource;
+	uint8_t time_resource_pattern;
+} nfapi_hi_dci0_dci_pdu_rel12_t;
+
+#define NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL12_TAG 0x204D
+
+typedef struct {
+	nfapi_hi_dci0_dci_pdu_rel8_t	dci_pdu_rel8;
+	nfapi_hi_dci0_dci_pdu_rel10_t	dci_pdu_rel10;
+	nfapi_hi_dci0_dci_pdu_rel12_t	dci_pdu_rel12;
+} nfapi_hi_dci0_dci_pdu;
+
+typedef nfapi_hi_dci0_dci_pdu_rel8_t nfapi_hi_dci0_epdcch_dci_pdu_rel8_t;
+#define NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL8_TAG 0x2020
+
+typedef nfapi_hi_dci0_dci_pdu_rel10_t nfapi_hi_dci0_epdcch_dci_pdu_rel10_t;
+#define NFAPI_HI_DCI0_REQUEST_EPDCCH_DCI_PDU_REL10_TAG 0x2021
+
+typedef nfapi_dl_config_epdcch_parameters_rel11_t nfapi_hi_dci0_epdcch_parameters_rel11_t;
+#define NFAPI_HI_DCI0_REQUEST_EPDCCH_PARAMETERS_REL11_TAG 0x2041
+
+typedef struct {
+	nfapi_hi_dci0_epdcch_dci_pdu_rel8_t		epdcch_dci_pdu_rel8;
+	nfapi_hi_dci0_epdcch_dci_pdu_rel10_t	epdcch_dci_pdu_rel10;
+	nfapi_hi_dci0_epdcch_parameters_rel11_t	epdcch_parameters_rel11;
+} nfapi_hi_dci0_epdcch_dci_pdu;
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mpdcch_narrowband;
+	uint8_t number_of_prb_pairs;
+	uint8_t resource_block_assignment;
+	uint8_t mpdcch_transmission_type;
+	uint8_t start_symbol;
+	uint8_t ecce_index;
+	uint8_t aggreagation_level;
+	uint8_t rnti_type;
+	uint16_t rnti;
+	uint8_t ce_mode;
+	uint16_t drms_scrambling_init;
+	uint16_t initial_transmission_sf_io;
+	uint16_t transmission_power;
+	uint8_t dci_format;
+	uint8_t resource_block_start;
+	uint8_t number_of_resource_blocks;
+	uint8_t mcs;
+	uint8_t pusch_repetition_levels;
+	uint8_t frequency_hopping_flag;
+	uint8_t new_data_indication;
+	uint8_t harq_process;
+	uint8_t redudency_version;
+	uint8_t tpc;
+	uint8_t csi_request;
+	uint8_t ul_inex;
+	uint8_t dai_presence_flag;
+	uint8_t dl_assignment_index;
+	uint8_t srs_request;
+	uint8_t dci_subframe_repetition_number;
+	uint32_t tcp_bitmap;
+	uint8_t total_dci_length_include_padding;
+	uint8_t number_of_tx_antenna_ports;
+	uint16_t precoding_value[NFAPI_MAX_ANTENNA_PORT_COUNT];
+} nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t;
+#define NFAPI_HI_DCI0_REQUEST_MPDCCH_DCI_PDU_REL13_TAG 0x204E
+
+typedef struct {
+	nfapi_hi_dci0_mpdcch_dci_pdu_rel13_t	mpdcch_dci_pdu_rel13;
+} nfapi_hi_dci0_mpdcch_dci_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t ncce_index;
+	uint8_t aggregation_level;
+	uint8_t start_symbol;
+	uint16_t rnti;
+	uint8_t scrambling_reinitialization_batch_index;
+	uint8_t nrs_antenna_ports_assumed_by_the_ue;
+	uint8_t subcarrier_indication;
+	uint8_t resource_assignment;
+	uint8_t scheduling_delay;
+	uint8_t mcs;
+	uint8_t redudancy_version;
+	uint8_t repetition_number;
+	uint8_t new_data_indicator;
+	uint8_t dci_subframe_repetition_number;
+} nfapi_hi_dci0_npdcch_dci_pdu_rel13_t;
+
+#define NFAPI_HI_DCI0_REQUEST_NPDCCH_DCI_PDU_REL13_TAG 0x2062
+
+typedef struct {
+	nfapi_hi_dci0_npdcch_dci_pdu_rel13_t	npdcch_dci_pdu_rel13;
+} nfapi_hi_dci0_npdcch_dci_pdu;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_hi_dci0_hi_pdu			hi_pdu;
+		nfapi_hi_dci0_dci_pdu			dci_pdu;
+		nfapi_hi_dci0_epdcch_dci_pdu	epdcch_dci_pdu;
+		nfapi_hi_dci0_mpdcch_dci_pdu	mpdcch_dci_pdu;
+		nfapi_hi_dci0_npdcch_dci_pdu	npdcch_dci_pdu;
+	};
+} nfapi_hi_dci0_request_pdu_t;
+
+#define NFAPI_HI_DCI0_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t sfnsf;
+	uint8_t number_of_dci;
+	uint8_t number_of_hi;
+	nfapi_hi_dci0_request_pdu_t* hi_dci0_pdu_list;
+} nfapi_hi_dci0_request_body_t;
+#define NFAPI_HI_DCI0_REQUEST_BODY_TAG 0x201D
+
+#define NFAPI_TX_MAX_SEGMENTS 32
+typedef struct {
+	uint16_t pdu_length;
+	uint16_t pdu_index;
+	uint8_t num_segments;
+	struct {
+		uint32_t segment_length;
+		uint8_t* segment_data;
+	} segments[NFAPI_TX_MAX_SEGMENTS];
+} nfapi_tx_request_pdu_t;
+
+#define NFAPI_TX_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_tx_request_pdu_t* tx_pdu_list;
+} nfapi_tx_request_body_t;
+#define NFAPI_TX_REQUEST_BODY_TAG 0x2022
+
+// P7 Message Structures
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint32_t t1;
+	int32_t delta_sfn_sf;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_dl_node_sync_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint32_t t1;
+	uint32_t t2;
+	uint32_t t3;	
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_ul_node_sync_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint32_t last_sfn_sf;
+	uint32_t time_since_last_timing_info;
+	uint32_t dl_config_jitter;
+	uint32_t tx_request_jitter;
+	uint32_t ul_config_jitter;
+	uint32_t hi_dci0_jitter;
+	int32_t dl_config_latest_delay;
+	int32_t tx_request_latest_delay;
+	int32_t ul_config_latest_delay;
+	int32_t hi_dci0_latest_delay;
+	int32_t dl_config_earliest_arrival;
+	int32_t tx_request_earliest_arrival;
+	int32_t ul_config_earliest_arrival;
+	int32_t hi_dci0_earliest_arrival;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_timing_info_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint8_t harq_pid;
+	uint16_t rnti;
+} nfapi_rx_ue_information;
+#define NFAPI_RX_UE_INFORMATION_TAG 0x2038
+
+typedef struct { 
+	uint8_t value_0;
+	uint8_t value_1;
+} nfapi_harq_indication_tdd_harq_data_bundling_t;
+
+typedef struct { 
+	uint8_t value_0;
+	uint8_t value_1;
+	uint8_t value_2;
+	uint8_t value_3;
+} nfapi_harq_indication_tdd_harq_data_multiplexing_t;
+
+typedef struct { 
+	uint8_t value_0;
+} nfapi_harq_indication_tdd_harq_data_special_bundling_t;
+
+typedef struct { 
+	uint8_t value_0;
+} nfapi_harq_indication_tdd_harq_data_t;
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	union{
+		nfapi_harq_indication_tdd_harq_data_bundling_t			bundling;
+		nfapi_harq_indication_tdd_harq_data_multiplexing_t		multiplex;
+		nfapi_harq_indication_tdd_harq_data_special_bundling_t	special_bundling;
+	} harq_data;
+} nfapi_harq_indication_tdd_rel8_t;
+#define NFAPI_HARQ_INDICATION_TDD_REL8_TAG 0x2027
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	union{
+		nfapi_harq_indication_tdd_harq_data_t	bundling;
+		nfapi_harq_indication_tdd_harq_data_t	multiplex;
+		nfapi_harq_indication_tdd_harq_data_special_bundling_t	special_bundling;
+		nfapi_harq_indication_tdd_harq_data_t	channel_selection;
+		nfapi_harq_indication_tdd_harq_data_t	format_3;
+	} harq_data[NFAPI_MAX_NUMBER_ACK_NACK_TDD];
+} nfapi_harq_indication_tdd_rel9_t;
+#define NFAPI_HARQ_INDICATION_TDD_REL9_TAG 0x2028
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint16_t number_of_ack_nack;
+	union{
+		nfapi_harq_indication_tdd_harq_data_t					bundling;
+		nfapi_harq_indication_tdd_harq_data_t					multiplex;
+		nfapi_harq_indication_tdd_harq_data_special_bundling_t	special_bundling;
+		nfapi_harq_indication_tdd_harq_data_t					channel_selection;
+		nfapi_harq_indication_tdd_harq_data_t			format_3;
+		nfapi_harq_indication_tdd_harq_data_t			format_4;
+		nfapi_harq_indication_tdd_harq_data_t			format_5;
+	} harq_data[NFAPI_MAX_NUMBER_ACK_NACK_TDD];
+} nfapi_harq_indication_tdd_rel13_t;
+#define NFAPI_HARQ_INDICATION_TDD_REL13_TAG 0x204F
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t harq_tb1;
+	uint8_t harq_tb2;
+} nfapi_harq_indication_fdd_rel8_t;
+#define NFAPI_HARQ_INDICATION_FDD_REL8_TAG 0x2029
+
+#define NFAPI_HARQ_ACK_NACK_REL9_MAX 10
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint8_t number_of_ack_nack;
+	uint8_t harq_tb_n[NFAPI_HARQ_ACK_NACK_REL9_MAX];
+} nfapi_harq_indication_fdd_rel9_t;
+#define NFAPI_HARQ_INDICATION_FDD_REL9_TAG 0x202a
+
+#define NFAPI_HARQ_ACK_NACK_REL13_MAX 22 // Need to check this max?
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t mode;
+	uint16_t number_of_ack_nack;
+	uint8_t harq_tb_n[NFAPI_HARQ_ACK_NACK_REL13_MAX];
+} nfapi_harq_indication_fdd_rel13_t;
+#define NFAPI_HARQ_INDICATION_FDD_REL13_TAG 0x2050
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t ul_cqi;
+	uint8_t channel;
+} nfapi_ul_cqi_information_t;
+#define NFAPI_UL_CQI_INFORMATION_TAG 0x2052
+
+// Only expect 1 harq_indication TLV.tag to be set
+// Would this be a better a an union, but not clear which combinations
+// are valid
+typedef struct {
+	uint16_t							instance_length;
+	nfapi_rx_ue_information				rx_ue_information;
+	nfapi_harq_indication_tdd_rel8_t	harq_indication_tdd_rel8;
+	nfapi_harq_indication_tdd_rel9_t	harq_indication_tdd_rel9;
+	nfapi_harq_indication_tdd_rel13_t	harq_indication_tdd_rel13;
+	nfapi_harq_indication_fdd_rel8_t	harq_indication_fdd_rel8;
+	nfapi_harq_indication_fdd_rel9_t	harq_indication_fdd_rel9;
+	nfapi_harq_indication_fdd_rel13_t	harq_indication_fdd_rel13;
+	nfapi_ul_cqi_information_t			ul_cqi_information;
+} nfapi_harq_indication_pdu_t;
+
+#define NFAPI_HARQ_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_harqs;
+	nfapi_harq_indication_pdu_t* harq_pdu_list;
+} nfapi_harq_indication_body_t;
+#define NFAPI_HARQ_INDICATION_BODY_TAG 0x2026
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t crc_flag;
+} nfapi_crc_indication_rel8_t;
+#define NFAPI_CRC_INDICATION_REL8_TAG 0x202c
+
+typedef struct {
+	uint16_t					instance_length;
+	nfapi_rx_ue_information		rx_ue_information;
+	nfapi_crc_indication_rel8_t	crc_indication_rel8;
+} nfapi_crc_indication_pdu_t;
+
+#define NFAPI_CRC_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_crcs;
+	nfapi_crc_indication_pdu_t* crc_pdu_list;
+} nfapi_crc_indication_body_t;
+#define NFAPI_CRC_INDICATION_BODY_TAG 0x202b
+
+typedef struct {
+	uint16_t					instance_length;
+	nfapi_rx_ue_information		rx_ue_information;
+	nfapi_ul_cqi_information_t	ul_cqi_information;
+} nfapi_sr_indication_pdu_t;
+
+#define NFAPI_SR_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_srs;				// Question : should this be srs
+	nfapi_sr_indication_pdu_t* sr_pdu_list;
+} nfapi_sr_indication_body_t;
+#define NFAPI_SR_INDICATION_BODY_TAG 0x202d
+
+// The data offset should be set to 0 or 1 before encoding
+// If it is set to 1 the nfapi library will detemine the correct offset
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t data_offset;
+	uint8_t ul_cqi;
+	uint8_t ri;
+	uint16_t timing_advance;
+} nfapi_cqi_indication_rel8_t;
+#define NFAPI_CQI_INDICATION_REL8_TAG 0x202f
+
+#define NFAPI_CC_MAX 4
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t data_offset;
+	uint8_t ul_cqi;
+	uint8_t number_of_cc_reported;
+	uint8_t ri[NFAPI_CC_MAX];
+	uint16_t timing_advance;
+	uint16_t timing_advance_r9;
+} nfapi_cqi_indication_rel9_t;
+#define NFAPI_CQI_INDICATION_REL9_TAG 0x2030
+
+typedef struct {
+	uint16_t					instance_length;
+	nfapi_rx_ue_information		rx_ue_information;
+	nfapi_cqi_indication_rel8_t cqi_indication_rel8;
+	nfapi_cqi_indication_rel9_t cqi_indication_rel9;
+	nfapi_ul_cqi_information_t	ul_cqi_information;
+} nfapi_cqi_indication_pdu_t;
+
+#define NFAPI_CQI_RAW_MAX_LEN 12
+typedef struct {
+	uint8_t pdu[NFAPI_CQI_RAW_MAX_LEN];
+} nfapi_cqi_indication_raw_pdu_t;
+
+#define NFAPI_CQI_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_cqis;
+	nfapi_cqi_indication_pdu_t*			cqi_pdu_list;
+	nfapi_cqi_indication_raw_pdu_t*		cqi_raw_pdu_list;
+} nfapi_cqi_indication_body_t;
+#define NFAPI_CQI_INDICATION_BODY_TAG 0x202e
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t rnti;
+	uint8_t preamble;
+	uint16_t timing_advance;
+} nfapi_preamble_pdu_rel8_t;
+#define NFAPI_PREAMBLE_REL8_TAG 0x2032
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t timing_advance_r9;
+} nfapi_preamble_pdu_rel9_t;
+#define NFAPI_PREAMBLE_REL9_TAG 0x2033
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t rach_resource_type;
+} nfapi_preamble_pdu_rel13_t;
+#define NFAPI_PREAMBLE_REL13_TAG 0x2051
+
+typedef struct { 
+	uint16_t					instance_length;
+	nfapi_preamble_pdu_rel8_t	preamble_rel8;
+	nfapi_preamble_pdu_rel9_t	preamble_rel9;
+	nfapi_preamble_pdu_rel13_t	preamble_rel13;
+} nfapi_preamble_pdu_t;
+
+#define NFAPI_PREAMBLE_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_preambles;
+	nfapi_preamble_pdu_t*			preamble_list;
+} nfapi_rach_indication_body_t;
+#define NFAPI_RACH_INDICATION_BODY_TAG 0x2031
+
+#define NFAPI_NUM_RB_MAX 1000
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t doppler_estimation;
+	uint16_t timing_advance;
+	uint8_t number_of_resource_blocks;
+	uint8_t rb_start;
+	uint8_t snr[NFAPI_NUM_RB_MAX];
+} nfapi_srs_indication_fdd_rel8_t;
+#define NFAPI_SRS_INDICATION_FDD_REL8_TAG 0x2035
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t timing_advance_r9;
+} nfapi_srs_indication_fdd_rel9_t;
+#define NFAPI_SRS_INDICATION_FDD_REL9_TAG 0x2036
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint8_t uppts_symbol;
+} nfapi_srs_indication_ttd_rel10_t;
+#define NFAPI_SRS_INDICATION_TDD_REL10_TAG 0x2037
+
+typedef struct { 
+	nfapi_tl_t tl;
+	uint16_t ul_rtoa;
+} nfapi_srs_indication_fdd_rel11_t;
+#define NFAPI_SRS_INDICATION_FDD_REL11_TAG 0x2053
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t num_prb_per_subband;
+	uint8_t number_of_subbands;
+	uint8_t num_atennas;
+	struct {
+		uint8_t subband_index;
+		uint16_t channel[NFAPI_MAX_NUM_PHYSICAL_ANTENNAS];
+	} subands[NFAPI_MAX_NUM_SUBBANDS];
+} nfapi_tdd_channel_measurement_t;
+#define NFAPI_TDD_CHANNEL_MEASUREMENT_TAG 0x2054
+
+typedef struct {
+	uint16_t							instance_length;
+	nfapi_rx_ue_information				rx_ue_information;
+	nfapi_srs_indication_fdd_rel8_t		srs_indication_fdd_rel8;
+	nfapi_srs_indication_fdd_rel9_t		srs_indication_fdd_rel9;
+	nfapi_srs_indication_ttd_rel10_t	srs_indication_tdd_rel10;
+	nfapi_srs_indication_fdd_rel11_t	srs_indication_fdd_rel11;
+	nfapi_tdd_channel_measurement_t		tdd_channel_measurement;
+} nfapi_srs_indication_pdu_t;
+
+#define NFAPI_SRS_IND_MAX_PDU 16
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_ues;
+	nfapi_srs_indication_pdu_t* srs_pdu_list;
+} nfapi_srs_indication_body_t;
+#define NFAPI_SRS_INDICATION_BODY_TAG 0x2034
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t length;
+	uint16_t offset;
+	uint8_t ul_cqi;
+	uint16_t timing_advance;
+} nfapi_rx_indication_rel8_t;
+#define NFAPI_RX_INDICATION_REL8_TAG 0x2024
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t timing_advance_r9;
+ } nfapi_rx_indication_rel9_t;
+#define NFAPI_RX_INDICATION_REL9_TAG 0x2025
+
+typedef struct {
+	nfapi_rx_ue_information rx_ue_information;
+	nfapi_rx_indication_rel8_t rx_indication_rel8;
+	nfapi_rx_indication_rel9_t rx_indication_rel9;
+	uint8_t* data;
+} nfapi_rx_indication_pdu_t;
+
+#define NFAPI_RX_IND_MAX_PDU 100
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_rx_indication_pdu_t* rx_pdu_list;
+} nfapi_rx_indication_body_t;
+#define NFAPI_RX_INDICATION_BODY_TAG 0x2023
+
+typedef struct {
+	nfapi_tl_t tl;	
+	uint8_t harq_tb1;
+} nfapi_nb_harq_indication_fdd_rel13_t;
+#define NFAPI_NB_HARQ_INDICATION_FDD_REL13_TAG 0x2064
+
+typedef struct {
+	uint16_t								instance_length;
+	nfapi_rx_ue_information					rx_ue_information;
+	nfapi_nb_harq_indication_fdd_rel13_t	nb_harq_indication_fdd_rel13;
+	nfapi_ul_cqi_information_t				ul_cqi_information;
+} nfapi_nb_harq_indication_pdu_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_harqs;
+	nfapi_nb_harq_indication_pdu_t* nb_harq_pdu_list;
+} nfapi_nb_harq_indication_body_t;
+#define NFAPI_NB_HARQ_INDICATION_BODY_TAG 0x2063
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t rnti;
+	uint8_t initial_sc;
+	uint16_t timing_advance;
+	uint8_t nrach_ce_level;
+} nfapi_nrach_indication_pdu_rel13_t;
+#define NFAPI_NRACH_INDICATION_REL13_TAG 0x2066
+
+typedef struct {
+	nfapi_nrach_indication_pdu_rel13_t		nrach_indication_rel13;
+} nfapi_nrach_indication_pdu_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_initial_scs_detected;
+	nfapi_nrach_indication_pdu_t* nrach_pdu_list;
+} nfapi_nrach_indication_body_t;
+#define NFAPI_NRACH_INDICATION_BODY_TAG 0x2065
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t mp_cca;
+	uint32_t n_cca;
+	uint32_t offset;
+	uint32_t lte_txop_sf;
+	uint16_t txop_sfn_sf_end;
+	uint32_t lbt_mode;
+} nfapi_lbt_pdsch_req_pdu_rel13_t;
+#define NFAPI_LBT_PDSCH_REQ_PDU_REL13_TAG 0x2056
+
+typedef struct {
+	nfapi_lbt_pdsch_req_pdu_rel13_t lbt_pdsch_req_pdu_rel13;
+} nfapi_lbt_pdsch_req_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t offset;
+	uint16_t sfn_sf_end;
+	uint32_t lbt_mode;
+} nfapi_lbt_drs_req_pdu_rel13_t;
+#define NFAPI_LBT_DRS_REQ_PDU_REL13_TAG 0x2057
+
+typedef struct {
+	nfapi_lbt_drs_req_pdu_rel13_t lbt_drs_req_pdu_rel13;
+} nfapi_lbt_drs_req_pdu;
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_lbt_pdsch_req_pdu		lbt_pdsch_req_pdu;
+		nfapi_lbt_drs_req_pdu		lbt_drs_req_pdu;
+	};
+} nfapi_lbt_dl_config_request_pdu_t;
+
+#define NFAPI_LBT_DL_CONFIG_REQ_MAX_PDU 16
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_lbt_dl_config_request_pdu_t*		lbt_dl_config_req_pdu_list;
+} nfapi_lbt_dl_config_request_body_t;
+#define NFAPI_LBT_DL_CONFIG_REQUEST_BODY_TAG 0x2055
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t result;
+	uint32_t lte_txop_symbols;
+	uint32_t initial_partial_sf;
+} nfapi_lbt_pdsch_rsp_pdu_rel13_t;
+#define NFAPI_LBT_PDSCH_RSP_PDU_REL13_TAG 0x2059
+
+typedef struct {
+	nfapi_lbt_pdsch_rsp_pdu_rel13_t lbt_pdsch_rsp_pdu_rel13;
+} nfapi_lbt_pdsch_rsp_pdu;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t handle;
+	uint32_t result;
+} nfapi_lbt_drs_rsp_pdu_rel13_t;
+#define NFAPI_LBT_DRS_RSP_PDU_REL13_TAG 0x205A
+
+typedef struct {
+	nfapi_lbt_drs_rsp_pdu_rel13_t lbt_drs_rsp_pdu_rel13;
+} nfapi_lbt_drs_rsp_pdu;
+
+
+typedef struct {
+	uint8_t pdu_type;
+	uint8_t pdu_size;
+	union {
+		nfapi_lbt_pdsch_rsp_pdu		lbt_pdsch_rsp_pdu;
+		nfapi_lbt_drs_rsp_pdu		lbt_drs_rsp_pdu;
+	};
+} nfapi_lbt_dl_indication_pdu_t;
+
+#define NFAPI_LBT_IND_MAX_PDU 16
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_pdus;
+	nfapi_lbt_dl_indication_pdu_t* lbt_indication_pdu_list;
+} nfapi_lbt_dl_indication_body_t;
+#define NFAPI_LBT_DL_INDICATION_BODY_TAG 0x2058
+
+typedef struct {
+} nfapi_error_indication_msg_invalid_state;
+
+typedef struct {
+} nfapi_error_indication_msg_bch_missing;
+
+typedef struct {
+	uint16_t recieved_sfn_sf;
+	uint16_t expected_sfn_sf;
+} nfapi_error_indication_sfn_out_of_sync;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint8_t direction;
+	uint16_t rnti;
+	uint8_t pdu_type;
+} nfapi_error_indication_msg_pdu_err;
+
+typedef struct {
+	uint16_t recieved_sfn_sf;
+	uint16_t expected_sfn_sf;
+} nfapi_error_indication_msg_invalid_sfn;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint8_t phich_lowest_ul_rb_index;
+} nfapi_error_indication_msg_hi_err;
+
+typedef struct {
+	uint8_t sub_error_code;
+	uint16_t pdu_index;
+} nfapi_error_indication_msg_tx_err;
+
+// 
+// P4 Message Structures
+//
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint8_t bandwidth;
+	uint32_t timeout;
+	uint8_t number_of_earfcns;
+	uint16_t earfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_lte_rssi_request_t;
+
+#define NFAPI_LTE_RSSI_REQUEST_TAG 0x3000
+
+#define NFAPI_P4_START_TAG NFAPI_LTE_RSSI_REQUEST_TAG
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint32_t timeout;
+	uint8_t number_of_uarfcns;
+	uint16_t uarfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_utran_rssi_request_t;
+
+#define NFAPI_UTRAN_RSSI_REQUEST_TAG 0x3001
+
+typedef struct {
+	uint16_t arfcn;
+	uint8_t direction;
+} nfapi_arfcn_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint32_t timeout;
+	uint8_t number_of_arfcns;
+	nfapi_arfcn_t arfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_geran_rssi_request_t;
+
+#define NFAPI_GERAN_RSSI_REQUEST_TAG 0x3002
+
+
+
+typedef struct {
+	uint16_t earfcn;
+	uint8_t number_of_ro_dl;
+	uint8_t ro_dl[NFAPI_MAX_RO_DL];
+} nfapi_earfcn_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t frequency_band_indicator;
+	uint16_t measurement_period;
+	uint32_t timeout;
+	uint8_t number_of_earfcns;
+	nfapi_earfcn_t earfcn[NFAPI_MAX_CARRIER_LIST];
+} nfapi_nb_iot_rssi_request_t;
+
+#define NFAPI_NB_IOT_RSSI_REQUEST_TAG 0x3020
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_rssi;
+	int16_t rssi[NFAPI_MAX_RSSI];
+} nfapi_rssi_indication_body_t;
+
+#define NFAPI_RSSI_INDICATION_TAG 0x3003
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t measurement_bandwidth;
+	uint8_t exhaustive_search;
+	uint32_t timeout;
+	uint8_t number_of_pci;
+	uint16_t pci[NFAPI_MAX_PCI_LIST];
+} nfapi_lte_cell_search_request_t;
+
+#define NFAPI_LTE_CELL_SEARCH_REQUEST_TAG 0x3004
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t uarfcn;
+	uint8_t exhaustive_search;
+	uint32_t timeout;
+	uint8_t number_of_psc;
+	uint16_t psc[NFAPI_MAX_PSC_LIST];
+} nfapi_utran_cell_search_request_t;
+
+#define NFAPI_UTRAN_CELL_SEARCH_REQUEST_TAG 0x3005
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint32_t timeout;
+	uint8_t number_of_arfcn;
+	uint16_t arfcn[NFAPI_MAX_ARFCN_LIST];
+} nfapi_geran_cell_search_request_t;
+
+#define NFAPI_GERAN_CELL_SEARCH_REQUEST_TAG 0x3006
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint8_t exhaustive_search;
+	uint32_t timeout;
+	uint8_t number_of_pci;
+	uint16_t pci[NFAPI_MAX_PCI_LIST];
+} nfapi_nb_iot_cell_search_request_t;
+
+#define NFAPI_NB_IOT_CELL_SEARCH_REQUEST_TAG 0x3021
+
+typedef struct {
+	uint16_t pci;
+	uint8_t rsrp;
+	uint8_t rsrq;
+	int16_t frequency_offset;
+} nfapi_lte_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_lte_cells_found;
+	nfapi_lte_found_cell_t lte_found_cells[NFAPI_MAX_LTE_CELLS_FOUND];
+} nfapi_lte_cell_search_indication_t;
+
+#define NFAPI_LTE_CELL_SEARCH_INDICATION_TAG 0x3007
+
+typedef struct {
+	uint16_t psc;
+	uint8_t rscp;
+	uint8_t ecno;
+	int16_t frequency_offset;
+} nfapi_utran_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_utran_cells_found;
+	nfapi_utran_found_cell_t utran_found_cells[NFAPI_MAX_UTRAN_CELLS_FOUND];
+} nfapi_utran_cell_search_indication_t;
+
+#define NFAPI_UTRAN_CELL_SEARCH_INDICATION_TAG 0x3008
+
+typedef struct {
+	uint16_t arfcn;
+	uint8_t bsic;
+	uint8_t rxlev;
+	uint8_t rxqual;
+	int16_t frequency_offset;
+	uint32_t sfn_offset;
+} nfapi_gsm_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_gsm_cells_found;
+	nfapi_gsm_found_cell_t gsm_found_cells[NFAPI_MAX_GSM_CELLS_FOUND];
+} nfapi_geran_cell_search_indication_t;
+
+#define NFAPI_GERAN_CELL_SEARCH_INDICATION_TAG 0x3009
+
+typedef struct {
+	uint16_t pci;
+	uint8_t rsrp;
+	uint8_t rsrq;
+	int16_t frequency_offset;
+} nfapi_nb_iot_found_cell_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t number_of_nb_iot_cells_found;
+	nfapi_nb_iot_found_cell_t nb_iot_found_cells[NFAPI_MAX_NB_IOT_CELLS_FOUND];
+} nfapi_nb_iot_cell_search_indication_t;
+
+#define NFAPI_NB_IOT_CELL_SEARCH_INDICATION_TAG 0x3022
+
+typedef nfapi_opaqaue_data_t nfapi_pnf_cell_search_state_t;
+
+#define NFAPI_PNF_CELL_SEARCH_STATE_TAG 0x300A
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint16_t pci;
+	uint32_t timeout;
+} nfapi_lte_broadcast_detect_request_t;
+
+#define NFAPI_LTE_BROADCAST_DETECT_REQUEST_TAG 0x300B
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t uarfcn;
+	uint16_t psc;
+	uint32_t timeout;
+} nfapi_utran_broadcast_detect_request_t;
+
+#define NFAPI_UTRAN_BROADCAST_DETECT_REQUEST_TAG 0x300C
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint16_t pci;
+	uint32_t timeout;
+} nfapi_nb_iot_broadcast_detect_request_t;
+
+#define NFAPI_NB_IOT_BROADCAST_DETECT_REQUEST_TAG 0x3023
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_tx_antenna;
+	uint16_t mib_length;
+	uint8_t mib[NFAPI_MAX_MIB_LENGTH];
+	uint32_t sfn_offset;
+} nfapi_lte_broadcast_detect_indication_t;
+
+#define NFAPI_LTE_BROADCAST_DETECT_INDICATION_TAG 0x300E
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t mib_length;
+	uint8_t mib[NFAPI_MAX_MIB_LENGTH];
+	uint32_t sfn_offset;
+} nfapi_utran_broadcast_detect_indication_t;
+
+#define NFAPI_UTRAN_BROADCAST_DETECT_INDICATION_TAG 0x300F
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t number_of_tx_antenna;
+	uint16_t mib_length;
+	uint8_t mib[NFAPI_MAX_MIB_LENGTH];
+	uint32_t sfn_offset;
+} nfapi_nb_iot_broadcast_detect_indication_t;
+
+#define NFAPI_NB_IOT_BROADCAST_DETECT_INDICATION_TAG 0x3024
+
+#define NFAPI_PNF_CELL_BROADCAST_STATE_TAG 0x3010
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint16_t pci;
+	uint16_t downlink_channel_bandwidth;
+	uint8_t phich_configuration;
+	uint8_t number_of_tx_antenna;
+	uint8_t retry_count;
+	uint32_t timeout;
+} nfapi_lte_system_information_schedule_request_t;
+
+#define NFAPI_LTE_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG 0x3011
+
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint16_t pci;
+	uint8_t scheduling_info_sib1_nb;
+	uint32_t timeout;
+} nfapi_nb_iot_system_information_schedule_request_t;
+
+#define NFAPI_NB_IOT_SYSTEM_INFORMATION_SCHEDULE_REQUEST_TAG 0x3025
+
+typedef nfapi_opaqaue_data_t nfapi_pnf_cell_broadcast_state_t;
+
+typedef struct {
+	uint8_t si_periodicity;
+	uint8_t si_index;
+} nfapi_lte_system_information_si_periodicity_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint16_t pci;
+	uint16_t downlink_channel_bandwidth;
+	uint8_t phich_configuration;
+	uint8_t number_of_tx_antenna;
+	uint8_t number_of_si_periodicity;
+	nfapi_lte_system_information_si_periodicity_t si_periodicity[NFAPI_MAX_SI_PERIODICITY];
+	uint8_t si_window_length;
+	uint32_t timeout;
+} nfapi_lte_system_information_request_t;
+
+#define NFAPI_LTE_SYSTEM_INFORMATION_REQUEST_TAG 0x3014
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t uarfcn;
+	uint16_t psc;
+	uint32_t timeout;
+} nfapi_utran_system_information_request_t;
+
+#define NFAPI_UTRAN_SYSTEM_INFORMATION_REQUEST_TAG 0x3015
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t arfcn;
+	uint8_t bsic;
+	uint32_t timeout;
+} nfapi_geran_system_information_request_t;
+
+#define NFAPI_GERAN_SYSTEM_INFORMATION_REQUEST_TAG 0x3016
+
+typedef struct {
+	uint8_t si_periodicity;
+	uint8_t si_repetition_pattern;
+	uint8_t si_tb_size;
+	uint8_t number_of_si_index;
+	uint8_t si_index[NFAPI_MAX_SI_INDEX];
+} nfapi_nb_iot_system_information_si_periodicity_t;
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t earfcn;
+	uint8_t ro_dl;
+	uint16_t pci;
+	uint8_t number_of_si_periodicity;
+	nfapi_nb_iot_system_information_si_periodicity_t si_periodicity[NFAPI_MAX_SI_PERIODICITY];
+	uint8_t si_window_length;
+	uint32_t timeout;
+} nfapi_nb_iot_system_information_request_t;
+
+#define NFAPI_NB_IOT_SYSTEM_INFORMATION_REQUEST_TAG 0x3027
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t sib_type;
+	uint16_t sib_length;
+	uint8_t sib[NFAPI_MAX_SIB_LENGTH];
+} nfapi_lte_system_information_indication_t;
+
+#define NFAPI_LTE_SYSTEM_INFORMATION_INDICATION_TAG 0x3018
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t sib_length;
+	uint8_t sib[NFAPI_MAX_SIB_LENGTH];
+} nfapi_utran_system_information_indication_t;
+
+#define NFAPI_UTRAN_SYSTEM_INFORMATION_INDICATION_TAG 0x3019
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint16_t si_length;
+	uint8_t si[NFAPI_MAX_SI_LENGTH];
+} nfapi_geran_system_information_indication_t;
+
+#define NFAPI_GERAN_SYSTEM_INFORMATION_INDICATION_TAG 0x301a
+
+typedef struct {
+	nfapi_tl_t tl;
+	uint8_t sib_type;
+	uint16_t sib_length;
+	uint8_t sib[NFAPI_MAX_SIB_LENGTH];
+} nfapi_nb_iot_system_information_indication_t;
+
+#define NFAPI_NB_IOT_SYSTEM_INFORMATION_INDICATION_TAG 0x3026
+
+
+//
+// Top level NFAP messages
+//
+
+//
+// P7
+//
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_dl_config_request_body_t dl_config_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_dl_config_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_ul_config_request_body_t ul_config_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_ul_config_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_hi_dci0_request_body_t hi_dci0_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_hi_dci0_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_tx_request_body_t tx_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_tx_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+} nfapi_subframe_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_harq_indication_body_t harq_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_harq_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_crc_indication_body_t crc_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_crc_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_sr_indication_body_t sr_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_sr_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_cqi_indication_body_t cqi_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cqi_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_rach_indication_body_t rach_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rach_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_srs_indication_body_t srs_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_srs_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_rx_indication_body_t rx_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rx_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_nb_harq_indication_body_t nb_harq_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nb_harq_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_nrach_indication_body_t nrach_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nrach_indication_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_lbt_dl_config_request_body_t lbt_dl_config_request_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_lbt_dl_config_request_t;
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint16_t sfn_sf;
+	nfapi_lbt_dl_indication_body_t lbt_dl_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_lbt_dl_indication_t;
+
+
+typedef struct {
+	nfapi_p7_message_header_t header;
+	uint8_t message_id;
+	uint8_t error_code;
+	union {
+		nfapi_error_indication_msg_invalid_state	msg_invalid_state;
+		nfapi_error_indication_msg_bch_missing		msg_bch_missing;
+		nfapi_error_indication_sfn_out_of_sync		sfn_out_of_sync;
+		nfapi_error_indication_msg_pdu_err			msg_pdu_err;
+		nfapi_error_indication_msg_invalid_sfn		msg_invalid_sfn;
+		nfapi_error_indication_msg_hi_err			msg_hi_err;
+		nfapi_error_indication_msg_tx_err			msg_tx_err;
+	};
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_error_indication_t;
+
+// 
+// P4 Messages
+// 
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_rssi_request_t					lte_rssi_request;
+		nfapi_utran_rssi_request_t					utran_rssi_request;
+		nfapi_geran_rssi_request_t					geran_rssi_request;
+		nfapi_nb_iot_rssi_request_t					nb_iot_rssi_request;
+	};
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rssi_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rssi_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_rssi_indication_body_t rssi_indication_body;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_rssi_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_cell_search_request_t				lte_cell_search_request;
+		nfapi_utran_cell_search_request_t			utran_cell_search_request;
+		nfapi_geran_cell_search_request_t			geran_cell_search_request;
+		nfapi_nb_iot_cell_search_request_t			nb_iot_cell_search_request;
+	};
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cell_search_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cell_search_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_cell_search_indication_t lte_cell_search_indication;
+	nfapi_utran_cell_search_indication_t utran_cell_search_indication;
+	nfapi_geran_cell_search_indication_t geran_cell_search_indication;
+	nfapi_pnf_cell_search_state_t pnf_cell_search_state;
+	nfapi_nb_iot_cell_search_indication_t nb_iot_cell_search_indication;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_cell_search_indication_t;
+
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_broadcast_detect_request_t		lte_broadcast_detect_request;
+		nfapi_utran_broadcast_detect_request_t		utran_broadcast_detect_request;
+		nfapi_nb_iot_broadcast_detect_request_t		nb_iot_broadcast_detect_request;
+	};
+	nfapi_pnf_cell_search_state_t pnf_cell_search_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_broadcast_detect_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_broadcast_detect_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_broadcast_detect_indication_t lte_broadcast_detect_indication;
+	nfapi_utran_broadcast_detect_indication_t utran_broadcast_detect_indication;
+	nfapi_nb_iot_broadcast_detect_indication_t nb_iot_broadcast_detect_indication;
+	nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_broadcast_detect_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_system_information_schedule_request_t lte_system_information_schedule_request;
+		nfapi_nb_iot_system_information_schedule_request_t nb_iot_system_information_schedule_request;
+	};
+	nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_schedule_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_schedule_response_t;
+
+typedef struct { 
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_system_information_indication_t lte_system_information_indication;
+	nfapi_nb_iot_system_information_indication_t nb_iot_system_information_indication;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_schedule_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint8_t rat_type;
+	union {
+		nfapi_lte_system_information_request_t lte_system_information_request;
+		nfapi_utran_system_information_request_t utran_system_information_request;
+		nfapi_geran_system_information_request_t geran_system_information_request;
+		nfapi_nb_iot_system_information_request_t nb_iot_system_information_request;
+	};
+	nfapi_pnf_cell_broadcast_state_t pnf_cell_broadcast_state;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_response_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_lte_system_information_indication_t lte_system_information_indication;
+	nfapi_utran_system_information_indication_t utran_system_information_indication;
+	nfapi_geran_system_information_indication_t geran_system_information_indication;
+	nfapi_nb_iot_system_information_indication_t nb_iot_system_information_indication;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_system_information_indication_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nmm_stop_request_t;
+
+typedef struct {
+	nfapi_p4_p5_message_header_t header;
+	uint32_t error_code;
+	nfapi_vendor_extension_tlv_t vendor_extension;
+} nfapi_nmm_stop_response_t;
+
+//
+// Configuration options for the encode decode functions
+//
+
+/*! Configuration options for the p7 pack unpack functions
+ *
+ */
+typedef struct nfapi_p7_codec_config {
+
+	/*! Optional call back to allow the user to define the memory allocator. 
+	 *  \param size The size of the memory to allocate
+	 *  \return a pointer to a valid memory block or 0 if it has failed.
+	 *
+	 * If not set the nfapi unpack functions will use malloc
+	 */
+	void* (*allocate)(size_t size);
+
+	/*! Optional call back to allow the user to define the memory deallocator. 
+	 *  \param ptr A poiner to a memory block allocated by the allocate callback
+	 * 
+	 *	If not set the client should use free
+	 */
+	void (*deallocate)(void* ptr);
+
+	/*! Optional call back function to handle unpacking vendor extension tlv.
+	 *  \param tl A pointer to a decoded tag length structure
+	 *  \param ppReadPackedMsg A handle to the read buffer. 
+	 *  \param end The end of the read buffer
+	 *  \param ve A handle to a vendor extention structure that the call back should allocate if the structure can be decoded
+	 *  \param config A pointer to the p7 codec configuration
+	 *  \return return 0 if packed successfully, -1 if failed.
+	 *
+	 *  If not set the tlv will be skipped
+	 *
+	 *  Client should use the help methods in nfapi.h to decode the vendor extention.
+	 * 
+	 *  \todo Add code example
+	 */
+	int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p7_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension tlv. 
+	 *  \param ve A pointer to a vendor extention structure.
+	 *  \param ppWritePackedMsg A handle to the write buffer
+	 *  \param end The end of the write buffer. The callee should make sure not to write beyond the end
+	 *  \param config A pointer to the p7 codec configuration
+	 *  \return return 0 if packed successfully, -1 if failed.
+	 * 
+	 *  If not set the the tlv will be skipped
+	 * 
+	 *  Client should use the help methods in nfapi.h to encode the vendor extention
+	 * 
+	 *  \todo Add code example
+	 */
+	int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config);
+
+	/*! Optional call back function to handle unpacking vendor extension messages. 
+	 *  \param header A pointer to a decode P7 message header for the vendor extention message
+	 *  \param ppReadPackedMsg A handle to the encoded data buffer
+	 *  \param end A pointer to the end of the encoded data buffer
+	 *  \param config  A pointer to the p7 codec configuration
+	 *  \return 0 if unpacked successfully, -1 if failed
+	 *
+	 *  If not set the message will be ignored
+	 *
+	 *  If the message if is unknown the function should return -1
+	 */
+	int (*unpack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p7_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension messages. 
+	 *  \param header A poiner to a P7 message structure for the venfor extention message
+	 *  \param ppWritePackedmsg A handle to the buffer to write the encoded message into
+	 *  \param end A pointer to the end of the buffer
+	 *  \param cofig A pointer to the p7 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 * 
+	 * If not set the the message will be ingored
+	 *	 
+	 *  If the message if is unknown the function should return -1
+	 */
+	int (*pack_p7_vendor_extension)(nfapi_p7_message_header_t* header, uint8_t **ppWritePackedmsg, uint8_t *end, struct nfapi_p7_codec_config* config);
+
+	/*! Optional user data that will be passed back with callbacks
+	 */
+	void* user_data;
+
+} nfapi_p7_codec_config_t;
+
+/*! Configuration options for the p4 & p5 pack unpack functions
+ *
+ */
+typedef struct nfapi_p4_p5_codec_config {
+
+	/*! Optional call back to allow the user to define the memory allocator.
+     *  \param size The size of the memory to allocate
+	 *  \return a pointer to a valid memory block or 0 if it has failed.
+	 *
+	 *  If not set the nfapi unpack functions will use malloc
+	 */
+	void* (*allocate)(size_t size);
+
+	/*! Optional call back to allow the user to define the memory deallocator. 
+	 *  \param ptr A poiner to a memory block allocated by the allocate callback
+	 *
+	 *  If not set free will be used
+	 */
+	void (*deallocate)(void* ptr);
+
+	/*! Optional call back function to handle unpacking vendor extension tlv.
+	 *  \param tl A pointer to a decoded tag length structure
+	 *  \param ppReadPackedMsg A handle to the data buffer to decode
+	 *  \param end A pointer to the end of the buffer
+	 *  \param ve A handle to a vendor extention structure that will be allocated by this callback
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if unpacked successfully, -1 if failed
+	 *  
+	 *  If not set the tlv will be skipped
+	 */
+	int (*unpack_vendor_extension_tlv)(nfapi_tl_t* tl, uint8_t **ppReadPackedMsg, uint8_t *end, void** ve, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension tlv. 
+	 *  \param ve
+	 *  \param ppWritePackedMsg A handle to the data buffer pack the tlv into
+	 *  \param end A pointer to the end of the buffer
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 *
+	 *  If not set the the tlv will be skipped
+	 */
+	int (*pack_vendor_extension_tlv)(void* ve, uint8_t **ppWritePackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional call back function to handle unpacking vendor extension messages. 
+	 *  \param header A pointer to a decode P4/P5 message header
+	 *  \param ppReadPackgedMsg A handle to the data buffer to decode
+	 *  \param end A pointer to the end of the buffer
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 *
+	 * If not set the message will be ignored
+	 */
+	int (*unpack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppReadPackedMsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional call back function to handle packing vendor extension messages.
+	 *  \param header A pointer to the P4/P5 message header to be encoded
+	 *  \param ppWritePackedMsg A handle to the data buffer pack the message into
+	 *  \param end A pointer to the end of the buffer
+	 *  \param config A pointer to the P4/P5 codec configuration
+	 *  \return 0 if packed successfully, -1 if failed
+	 *  
+	 *  If not set the the message will be ingored
+	 */
+	int (*pack_p4_p5_vendor_extension)(nfapi_p4_p5_message_header_t* header, uint8_t **ppwritepackedmsg, uint8_t *end, struct nfapi_p4_p5_codec_config* config);
+
+	/*! Optional user data that will be passed back with callbacks
+	 */
+	void* user_data;
+
+} nfapi_p4_p5_codec_config_t;
+
+//
+// Functions
+// 
+
+/*! \brief Encodes an NFAPI P4 message to a buffer
+ *  \param pMessageBuf A pointer to a nfapi p4 message structure
+ *  \param messageBufLen The size of the p4 message structure
+ *  \param pPackedBuf A pointer to the buffer that the p4 message will be packed into
+ *  \param packedBufLen The size of the buffer 
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will encode a nFAPI P4 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf.
+ * 
+ */
+int nfapi_p4_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P4 message header
+ *  \param pMessageBuf A pointer to an encoded P4 message header
+ *  \param messageBufLen The size of the encoded P4 message header
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p4_p5_message_header structure pointer to by pUnpackedBuf
+ */
+int nfapi_p4_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P4 message
+ *  \param pMessageBuf A pointer to an encoded P4 message
+ *  \param messageBufLen The size of the encoded P4 message
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p4 message structure pointer to by pUnpackedBuf 
+ */
+int nfapi_p4_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Encodes an NFAPI P5 message to a buffer
+ *  \param pMessageBuf A pointer to a nfapi p5 message structure
+ *  \param messageBufLen The size of the p5 message structure
+ *  \param pPackedBuf A pointer to the buffer that the p5 message will be packed into
+ *  \param packedBufLen The size of the buffer 
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will encode a nFAPI P5 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf.
+ * 
+ */
+int nfapi_p5_message_pack(void *pMessageBuf, uint32_t messageBufLen, void *pPackedBuf, uint32_t packedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes an NFAPI P5 message header
+ *  \param pMessageBuf A pointer to an encoded P5 message header
+ *  \param messageBufLen The size of the encoded P5 message header
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p4_p5_message_header structure pointer to by pUnpackedBuf
+ */
+int nfapi_p5_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P5 message
+ *  \param pMessageBuf A pointer to an encoded P5 message
+ *  \param messageBufLen The size of the encoded P5 message
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p5 message structure pointer to by pUnpackedBuf 
+ */
+int nfapi_p5_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p4_p5_codec_config_t* config);
+
+/*! \brief Encodes an NFAPI P7 message to a buffer
+ *  \param pMessageBuf A pointer to a nfapi p7 message structure
+ *  \param pPackedBuf A pointer to the buffer that the p7 message will be packed into
+ *  \param packedBufLen The size of the buffer 
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will encode a nFAPI P7 message structure pointed to be pMessageBuf into a byte stream pointed to by pPackedBuf.
+ * 
+ */
+int nfapi_p7_message_pack(void *pMessageBuf, void *pPackedBuf, uint32_t packedBufLen, nfapi_p7_codec_config_t* config);
+
+/*! \brief Decodes an NFAPI P7 message header
+ *  \param pMessageBuf A pointer to an encoded P7 message header
+ *  \param messageBufLen The size of the encoded P7 message header
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi_p7_message_header structure pointer to by pUnpackedBuf
+
+ */
+int nfapi_p7_message_header_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config);
+
+/*! \brief Decodes a NFAPI P7 message
+ *  \param pMessageBuf A pointer to an encoded P7 message
+ *  \param messageBufLen The size of the encoded P7 message
+ *  \param pUnpackedBuf A pointer to the nfapi_message_header
+ *  \param unpackedBufLen The size of nfapi_message_header structure.
+ *  \param config A pointer to the nfapi configuration structure
+ *  \return 0 means success, -1 means failure.
+ *
+ * The function will decode a byte stream pointed to by pMessageBuf into a nfapi p7 message structure pointer to by pUnpackedBuf 
+ */
+int nfapi_p7_message_unpack(void *pMessageBuf, uint32_t messageBufLen, void *pUnpackedBuf, uint32_t unpackedBufLen, nfapi_p7_codec_config_t* config);
+
+/*! \brief Calculates the checksum of a  message
+ *
+ *  \param buffer Pointer to the packed message
+ *  \param len The length of the message
+ *  \return The checksum. If there is an error the function with return -1
+ */
+uint32_t nfapi_p7_calculate_checksum(uint8_t* buffer, uint32_t len);
+
+/*! \brief Calculates & updates the checksum in the message
+ *
+ *  \param buffer Pointer to the packed message
+ *  \param len The length of the message
+  *  \return 0 means success, -1 means failure.
+ */
+int nfapi_p7_update_checksum(uint8_t* buffer, uint32_t len);
+
+/*! \brief Updates the transmition time stamp in the p7 message header
+ *
+ *  \param buffer Pointer to the packed message
+ *  \param timestamp The time stamp value
+  *  \return 0 means success, -1 means failure.
+ */
+int nfapi_p7_update_transmit_timestamp(uint8_t* buffer, uint32_t timestamp);
+
+#endif /* _NFAPI_INTERFACE_H_ */
diff --git a/openair2/PHY_INTERFACE/vars.h b/openair2/PHY_INTERFACE/vars.h
index 810d073a233606d77a51ca9f67fb7de5c422932c..76674c300189c940b79a0acdc158b1ac46387039 100644
--- a/openair2/PHY_INTERFACE/vars.h
+++ b/openair2/PHY_INTERFACE/vars.h
@@ -34,6 +34,7 @@
 unsigned int mac_debug;
 
 //MAC_xface *mac_xface;
+IF_Module_t* if_inst;
 
 //MACPHY_PARAMS MACPHY_params;
 
diff --git a/openair2/RRC/LITE/L2_interface_nb_iot.c b/openair2/RRC/LITE/L2_interface_NB_IoT.c
similarity index 76%
rename from openair2/RRC/LITE/L2_interface_nb_iot.c
rename to openair2/RRC/LITE/L2_interface_NB_IoT.c
index 0ecf539667821a1aa1f7db246006f68b4bca30b8..163e2842ed9f2f7e1bc64c8de6a3f6bb6357adcb 100644
--- a/openair2/RRC/LITE/L2_interface_nb_iot.c
+++ b/openair2/RRC/LITE/L2_interface_NB_IoT.c
@@ -26,29 +26,34 @@
  * \company Eurecom
  * \email: raymond.knopp@eurecom.fr
  */
-#include "PHY/defs.h"
-#include "SCHED/defs.h"
-#include "platform_types.h"
-#include "defs_nb_iot.h" //RRC
-#include "LAYER2/MAC/defs_nb_iot.h" //MAC
-#include "extern.h"
-#include "LAYER2/MAC/extern.h"
+//#include "PHY/defs.h"
+#include "PHY/defs_NB_IoT.h"
+#include "openair2/LAYER2/MAC/proto_NB_IoT.h"
+#include "openair2/LAYER2/MAC/extern_NB_IoT.h"
+//#include "PHY/INIT/defs_NB_IoT.h"
+//#include "SCHED/defs.h"
+//#include "platform_types.h"
+//#include "defs_NB_IoT.h" //RRC
+//#include "LAYER2/MAC/defs_NB_IoT.h" //MAC
+//#include "LAYER2/MAC/defs.h" // MAC because see the PHY functions
+//#include "extern.h"
+//#include "LAYER2/MAC/extern.h"
 #include "UTIL/LOG/log.h"
 #include "UTIL/OCG/OCG_vars.h"
-#include "rrc_eNB_UE_context.h"
+#include "RRC/LITE/rrc_eNB_UE_context_NB_IoT.h"
 #include "pdcp_primitives.h"
 #include "pdcp.h"
+#include "pdcp_util.h"
+#include "rlc.h"
 #include "msc.h"
 #include "UTIL/LOG/vcd_signal_dumper.h"
-#include "gtpv1u.h"
+//#include "gtpv1u.h"
 #include "osa_defs.h"
-
-#ifdef PHY_EMUL
-#include "SIMULATION/simulation_defs.h"
-extern EMULATION_VARS *Emul_vars;
-extern eNB_MAC_INST *eNB_mac_inst;
-extern UE_MAC_INST *UE_mac_inst;
-#endif
+#include "pdcp_sequence_manager.h"
+#include "UTIL/OTG/otg_rx.h"
+#include "openair2/PHY_INTERFACE/IF_Module_NB_IoT.h"
+#include "openair1/SCHED/IF_Module_L1_primitives_NB_IoT.h"
+#include "openair3/GTPV1-U/gtpv1u.h"
 
 #if defined(ENABLE_ITTI)
 # include "intertask_interface.h"
@@ -66,17 +71,17 @@ typedef boolean_t mib_flag_t;
 #define MIB_FLAG_YES	TRUE
 #define MIB_FLAG_NO		FALSE
 
-mui_t mui=0;
+//mui_t mui_NB=0;
 
 //XXX MP: just temporary usage since i put in one single file all the primitives modified (but they should be relocated in the
 //proper file where they are defined as indicated in the comments
 
 //XXX access of protected variables in pdcp.h
 extern unsigned int           pdcp_eNB_UE_instance_to_rnti_index;
-extern rnti_t                 pdcp_eNB_UE_instance_to_rnti[NUMBER_OF_UE_MAX];
+extern rnti_t                 pdcp_eNB_UE_instance_to_rnti[NUMBER_OF_UE_MAX_NB_IoT];
 extern list_t                 pdcp_sdu_list;
 //extern struct mac_data_req rlc_am_mac_data_request (const protocol_ctxt_t* const ctxtP,void * const rlc_pP);
-//extern eNB_MAC_INST_NB *eNB;
+
 extern void rlc_tm_init ( const protocol_ctxt_t* const  ctxt_pP, rlc_tm_entity_t * const rlcP);
 extern void rlc_tm_set_debug_infos(
         const protocol_ctxt_t* const  ctxt_pP,
@@ -95,539 +100,363 @@ extern struct mac_data_ind mac_rlc_deserialize_tb (
 		  const tb_size_t tb_sizeP,
 		  num_tb_t  num_tbP,
 		  crc_t    *crcs_pP);
+extern void rlc_am_init_timer_poll_retransmit(
+	    const protocol_ctxt_t* const ctxt_pP,
+	    rlc_am_entity_t* const       rlc_pP,
+	    const uint32_t               time_outP);
 
-
-/*---------------------------------RRC-MAC-----------------------------------*/
-
-//defined in MAC/config.c
-//FIXME: this function has no implication in terms of logical channel configuration for MAC
-int NB_rrc_mac_config_req_eNB(
-			   module_id_t       				Mod_idP,
-			   int                              CC_idP,
-			   int								rntiP, //FIXME: Raymond bug?
-			   int                              physCellId,
-			   int                              p_eNB,
-			   int                              Ncp,
-			   long                             eutra_band,//FIXME: frequencyBandIndicator in sib1 (is a long not an int!!)
-			   struct NS_PmaxList_NB_r13        *frequencyBandInfo, //optional SIB1
-			   struct MultiBandInfoList_NB_r13  *multiBandInfoList, //optional SIB1
-			   struct DL_Bitmap_NB_r13          *dl_bitmap, //optional SIB1
-			   long*                            eutraControlRegionSize, //optional sib1
-			   long*							nrs_CRS_PowerOffset, //optional
-			   uint8_t                          *SIwindowsize, //maybe no more needed because TDD only
-			   uint16_t                         *SIperiod, //maybe no more needed because TDD only
-			   uint32_t                         dl_CarrierFreq,
-			   uint32_t                         ul_CarrierFreq,
-			   BCCH_BCH_Message_NB_t            *mib_NB,
-			   RadioResourceConfigCommonSIB_NB_r13_t   *radioResourceConfigCommon,
-			   struct PhysicalConfigDedicated_NB_r13  *physicalConfigDedicated,
-			   MAC_MainConfig_NB_r13_t                *mac_MainConfig, //most probably not needed since only used at UE side
-			   long                             logicalChannelIdentity,//FIXME: decide how to use it
-			   LogicalChannelConfig_NB_r13_t          *logicalChannelConfig //FIXME: decide how to use it
-			   )
-{
-
-  //int i;
-
-  int UE_id = -1;
-  //eNB_MAC_INST_NB *eNB = &eNB_mac_inst_NB[Mod_idP];
-  //UE_list_NB_t *UE_list= &eNB_mac_inst_NB->UE_list;
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_IN);
-
-  UE_id = find_UE_id(Mod_idP, rntiP);
+//pointer function in rlc.h file
+extern void (*rlc_rrc_data_ind_NB_IoT)(
+                const protocol_ctxt_t* const ctxtP,
+                const rb_id_t     rb_idP,
+                const sdu_size_t  sdu_sizeP,
+                const uint8_t   * const sduP,
+				const srb1bis_flag_t srb1bis_flag);
+extern void (*rlc_rrc_data_conf)(
+        const protocol_ctxt_t* const ctxtP,
+        const rb_id_t         rb_idP,
+        const mui_t           muiP,
+        const rlc_tx_status_t statusP);
 
 
-  if (mib_NB!=NULL) {
-    if (eNB_mac_inst == NULL) l2_init_eNB(); //XXX MP: to be included in the MAC/main.c
 
-    mac_top_init_eNB(); //XXX MP:  to be included in the MAC/main.c
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
+/// Most of the Functions re-defined for NB-IoT should be re-located in their proper position over the code as already indicated the comments//
+///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 
-    eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].mib_NB           = mib_NB;
-    eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].physCellId     = physCellId;
-    eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].p_eNB          = p_eNB;
-    eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].Ncp            = Ncp;
-    eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].eutra_band     = eutra_band;
-    eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].dl_CarrierFreq = dl_CarrierFreq;
 
-//  NB_phy_config_mib_eNB(Mod_idP,CC_idP, //XXX MP: defined by Nick in lte_init_nb_iot.c
-//				  eutra_band,
-//				  physCellId,
-//				  Ncp,
-//				  p_eNB,
-//				  dl_CarrierFreq,
-//				  ul_CarrierFreq,
-//				  mib_NB->message.operationModeInfo_r13);
 
-    mac_init_cell_params(Mod_idP,CC_idP);
-  }
-
-  //phy_config_sib1_eNB--> not implemented for NB_IoT
+/*---------------------------------RRC-MAC-----------------------------------*/
 
-  if (radioResourceConfigCommon!=NULL) {
-      LOG_I(MAC,"[CONFIG]SIB2/3-NB Contents (partial)\n");
+int8_t mac_rrc_data_req_eNB_NB_IoT(
+  const module_id_t Mod_idP,
+  const int         CC_id,
+  const frame_t     frameP,
+  const frame_t		h_frameP,
+  const sub_frame_t   subframeP, //need for the case in which both SIB1-NB_IoT and SIB23-NB_IoT will be scheduled in the same frame
+  const rb_id_t     Srb_id,
+  uint8_t*    const buffer_pP,
+  uint8_t		flag
+)
+{
+    SRB_INFO_NB_IoT *Srb_info;
+    uint8_t Sdu_size=0;
 
-      LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13= %d\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13);
-      LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13= %d\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13);
-      LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13= %d\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13);
-      LOG_I(MAC,"[CONFIG]npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13= %d\n", radioResourceConfigCommon->npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13);
+    ///MIB
+    if( flag == 1 )
+    {
+        if (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_MIB_NB_IoT == 255)
+        {
+            printf("[eNB %d] MAC Request for MIB-NB and MIB-NB not initialized\n",Mod_idP);
+            // exit here
+        }
 
+        memcpy(&buffer_pP[0],eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].MIB_NB_IoT,eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_MIB_NB_IoT);
 
-      eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].radioResourceConfigCommon = radioResourceConfigCommon;
+        return (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_MIB_NB_IoT);
+    }
+    ///SIB1
+    else if( flag == 2 )
+    {
+        if (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT == 255)
+        {
+            printf("[eNB %d] MAC Request for SIB1-NB and SIB1-NB_IoT not initialized\n",Mod_idP);
+            // exit here
+        }
 
-      if (ul_CarrierFreq>0) eNB_mac_inst_NB[Mod_idP].common_channels[CC_idP].ul_CarrierFreq   = ul_CarrierFreq;
+        memcpy(&buffer_pP[0],eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].SIB1_NB_IoT,eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT);
 
-      //no ul_Bandwidth
+        return (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT);
+    }
+    ///SIB23
+    else if( flag == 3 )
+    {
+        if (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB23_NB_IoT == 255)
+        {
+            printf("[eNB %d] MAC Request for SIB23-NB and SIB23-NB_IoT not initialized\n",Mod_idP);
+            // exit here
+        }
 
-//     NB_phy_config_sib2_eNB( //XXX MP: defined by Nick in lte_init_nb_iot.c
-//    		  Mod_idP,
-//    		  CC_idP,
-//			  radioResourceConfigCommon,
-//			  NULL //ul_carrier_frequency
-//			  );
+        memcpy(&buffer_pP[0],eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].SIB23_NB_IoT,eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB23_NB_IoT);
+        return(eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB23_NB_IoT);
+    }
+    ///Msg4 transmission (RRCConnectionSetup)
+    else
+    {
+        printf("[eNB %d] Frame %d CCCH request (Srb_id %d)\n",Mod_idP,frameP, Srb_id);
 
+        if(eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].Srb0.Active==0)
+        {
+            printf("[eNB %d] CCCH Not active\n",Mod_idP);
+            return -1;
+        }
 
-  }
+        Srb_info = &eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].Srb0;
 
-  if (logicalChannelConfig!= NULL) {
-    if (UE_id == -1) {
-      LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__);
-    } else {
-    	//no logical channel group not defined for nb-iot --> no UL specific Parameter
-    	//XXX: lcgidmap in MAC/defs.h most probably is not needed
-    }
-  }
+        // check if data is there for MAC
+        if(Srb_info->Tx_buffer.payload_size>0) //Fill buffer
+        {
+            printf("[eNB %d] CCCH (%p) has %d bytes (dest: %p, src %p)\n",Mod_idP,Srb_info,Srb_info->Tx_buffer.payload_size,buffer_pP,Srb_info->Tx_buffer.Payload);
 
+            //RRC_MAC_CCCH_DATA_REQ not implemented in MAC/eNB_scheduler.c
 
-  ///mac_mainConfig not needed for the eNB side but only for UE
+            memcpy(buffer_pP, //CCCH_pdu.payload[0]
+                    Srb_info->Tx_buffer.Payload,Srb_info->Tx_buffer.payload_size);
 
+            Sdu_size = Srb_info->Tx_buffer.payload_size;
+            Srb_info->Tx_buffer.payload_size=0;
+        }
 
-  if (physicalConfigDedicated != NULL) {
-    if (UE_id == -1)
-      LOG_E(MAC,"%s:%d:%s: ERROR, UE_id == -1\n", __FILE__, __LINE__, __FUNCTION__);
-    else
-    {
-//   NB_phy_config_dedicated_eNB( //XXX MP: defined by Nick in lte_init_nb_iot.c
-//    		  Mod_idP,
-//			  CC_idP,
-//			  UE_RNTI(Mod_idP, UE_id),
-//			  physicalConfigDedicated);
+        return (Sdu_size);
     }
-  }
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_MAC_CONFIG, VCD_FUNCTION_OUT);
-  return(0);
 
 }
 
-
-//New
-int npdsch_rep_to_array[3] ={4,8,16}; //TS 36.213 Table 16.4.1.3-3
-int sib1_startFrame_to_array[4] = {0,16,32,48};//TS 36.213 Table 16.4.1.3-4
-//New----------------------------------------------------
-boolean_t is_SIB1_NB(
-		const frame_t    	frameP,
-		long				schedulingInfoSIB1,//from the mib
-		int					physCellId //by configuration
-		)
-{
-	uint8_t nb_rep=0; // number of sib1-nb repetitions within the 256 radio frames
-	uint32_t sib1_startFrame;
-	uint32_t sib1_NB_period = 256;//from specs TS 36.331 (rf)
-	uint8_t index;
-	int offset;
-	int period_nb; // the number of the actual period over the 1024 frames
-
-
-
-			/*SIB1
-	         *
-	         * the entire scheduling of SIB1-NB is based on the SchedulingInfoSIB1 of MIB-NB
-	         *
-	         * SIB1-NB transmission occurs in subframe #4 of every other frame in 16 continuous frames (i.e. alternate frames)
-	         * schedule with a periodicity of 2560 ms (256 Radio Frames) and repetitions (4, 8 or 16) are made, equally spaced
-	         * within the 2560 ms period
-	         *
-	         *
-	         * 0)find the SIB1-NB period over the 1024 frames in which the actual frame fall (FIXME check if every 1023 wrap around the frame in OAI)
-	         * 1)from the schedulingInfoSIB1 of MIB-NB and the physCell_id we deduce the starting radio frame
-	         * 2)check if the actual frame is after the staring radio frame
-	         * 3)check if the actual frame is within a SIB1-transmission interval
-	         * 4)based on the starting radio frame we can state  when SIB1-NB is transmitted in odd or even frame
-	         * (if the starting frame is even (0,16,32,48) then SIB1-NB is transmitted in even frames, if starting frame is odd (1)
-	         * we can state that SIB1-NB will be transmitted in every odd frame since repetitions are 16 in 256 radio frame period)
-	         *
-	         * *0) is necessary because at least i need to know in which of the even frames the repetition are -> is based on the offset
-	         * *in 1023 frames there are exactly 4 period of SIB1-NB
-	         **/
-
-
-		  //SIB1-NB period number
-		  period_nb = (int) frameP/sib1_NB_period;
-
-
-	      //number of repetitions
-	      nb_rep = npdsch_rep_to_array[schedulingInfoSIB1%3];
-
-	      //based on number of rep. and the physical cell id we derive the starting radio frame (TS 36.213 Table 16.4.1.3-3/4)
-	      switch(nb_rep)
-	      {
-	      case 4:
-	    	  //physCellId%4 possible value are 0,1,2,3
-	    	  sib1_startFrame = sib1_startFrame_to_array[physCellId%4];
-	    	  break;
-	      case 8:
-	    	  //physCellId%2possible value are 0,1
-	    	  sib1_startFrame = sib1_startFrame_to_array[physCellId%2];
-	    	  break;
-	      case 16:
-	    	  //physCellId%2 possible value are 0,1
-	    	  if(physCellId%2 == 0)
-	    		  sib1_startFrame = 0;
-	    	  else
-	    		  sib1_startFrame = 1; // the only case in which the starting frame is odd
-	    	  break;
-	      default:
-	    	  LOG_E(RRC, "Number of repetitions %d not allowed", nb_rep);
-	    	  return FALSE;
-	      }
-
-	      //check the actual frame w.r.t SIB1-NB starting frame
-	      if(frameP < sib1_startFrame + period_nb*256){
-	    	  LOG_T(RRC, "the actual frame %d is before the SIB1-NB starting frame %d of the period--> bcch_sdu_legnth = 0", frameP, sib1_startFrame + period_nb*256);
-	    	  return FALSE;
-	      }
-
-
-	      //calculate offset between SIB1-NB repetitions (repetitions are equally spaced)
-	      offset = (sib1_NB_period-(16*nb_rep))/nb_rep;
-	      /*
-	       * possible offset results (even numbers):
-	       * nb_rep= 4 ---> offset = 48
-	       * nb_rep = 8 --> offset = 16
-	       * nb_rep = 16 --> offset = 0
-	       */
-
-
-
-	      for( int i = 0; i < nb_rep; i++)
-	      {
-	    	  //find the correct sib1-nb repetition interval in which the actual frame is
-
-	    	  index = sib1_startFrame+ i*(16+offset) + period_nb*256;
-
-	    	  if(frameP>= index && frameP <= (index+15)) //SIB1_NB transmission interval
-	    	  {
-	    		  //find if the actual frame is one of the "every other frame in 16 continuous frame" in which SIB1-NB is transmitted
-
-	    		  if(sib1_startFrame%2 != 0){ // means that the starting frame was 1 --> sib1-NB is transmitted in every odd frame
-	    			  if(frameP%2 == 1){
-	    				  return TRUE;
-	    			 }
-	    		  }
-
-	    		  //in all other starting frame cases SIB1-NB is transmitted in the even frames inside the corresponding repetition interval
-	    		  if(frameP%2 == 0){ // SIB1-NB is transmitted
-	    			  return TRUE;
-	    		  }
-	    	  }
-
-	    	  if(index> frameP) // was not inside an interval of 16 radio frames for sib1-nb transmission
-	    	  	    return 0;
-	      }
-
-	      return FALSE;
-}
-//---------------------------------------------------------------------------
-//New
-int si_windowLength_to_rf[7]={16,32,48,64,96,128,160}; //TS 36.331  v14.2.1 pag 587
-int si_repPattern_to_nb[4]={2,4,8,16};
-int si_period_to_nb[7]={64,128,256,512,1024,2048,4096};
-//New---------------------------------------------------------------------------
-boolean_t is_SIB23_NB(
-		const frame_t     	frameP,
-		const frame_t		h_frameP, // the HSFN (increased by 1 every SFN wrap around) (10 bits)
-		long				si_period, //SI-periodicity (rf)
-		long				si_windowLength_ms, //Si-windowlength (ms) XXX received as an enumerative (see the IE of SIB1-NB)
-		long*				si_RadioFrameOffset, //Optional
-		long				si_RepetitionPattern // is given as an Enumerated
-		)
+//defined in L2_interface
+//called by rx_sdu only in case of CCCH message (e.g RRCConnectionRequest-NB - SRB0) --> is used for a direct communication between MAC and RRC
+int8_t mac_rrc_data_ind_eNB_NB_IoT(
+  const module_id_t     module_idP,
+  const int             CC_id,
+  const frame_t         frameP,
+  const sub_frame_t     sub_frameP,
+  const rnti_t          rntiP,
+  const rb_id_t         srb_idP,//could be skipped since always go through the CCCH channel
+  const uint8_t*        sduP,
+  const sdu_size_t      sdu_lenP
+)
 {
+  SRB_INFO_NB_IoT *Srb_info;
+  protocol_ctxt_t ctxt;
+  sdu_size_t      sdu_size = 0;
 
-	long w_start; //start of the si-window
-	long nb_periods; // number of si_periodicity inside an HSFN (1024 rf)
-	long si_offset; // offset for the starting of the SI-window
-	long si_windowLength;
-	long si_pattern;
-	long hsfn_in_periodicity;
-	long si_periodicity;
-
-
-	/*
-	 * SIB23-NB (xxx should be decided if include the SIB3 or not)
-	 *
-	 * The entire scheduling of the SI-Message is given by SIB1-NB information
-	 *
-	 * Parameters:
-	 * -si_windowlenght(w) (millisecond) (same for all SI messages)
-	 * -si_radioFrameOffset (radio frame) (same for all SI messages) //optional
-	 * -si_periodicity (T) (radioframe)
-	 * -si_repetitionPattern (long)
-	 *
-	 * Staring of the SI-Window: (TS 36.331 ch 5.2.3a)
-	 * >Since we have only 1 entry in the SchedulingInfoList (SIB23-NB) --> n=1
-	 * >therefore  x = (n-1)*w = 0
-	 * >Staring subframe = #0
-	 * >Starting Frame = (HSFN*1024 + SFN) mod T = FLOOR(x/10 = 0) + si_radioFrameOffset = si_radioFrameOffset
-	 *
-	 *Procedure
-	 *0) get the si_period in frame and check if the actual frame is in an HSFN interval that will include an si-window
-	 *0.1)check si_window value is not a spare and get the si_windowLength in radio frames
-	 *0.2)check si-window length and si-periodicity relation make sense
-	 *0.3) get the si_repetitionPattern
-	 *0.4)Since the si_offset is optional, whenever is not defined we put to 0 that value otherwise we use the value defined
-	 *1)consider the number of time of si_periodiciy within 1 HFSN (1024) because after SFN wrap around
-	 *2)evaluate the start of the si_window and check over the nb_periodicity if the current frame is within one of them
-	 *3)check is the si_offset is even or odd
-	 *
-	 *NOTE1:
-	 *(due to the si_repetitionPattern that start from the first frame of the si_window used and any value is even)
-	 *-if si_offset is even: the radio frame for SI-Transmission must be even (following the repPattern)
-	 *-if si_offset is odd:  the radio frame for the SI-Transmission must be odd (following the pattern)
-	 *
-	 *NOTE2:
-	 *the starting frame (thanks to HSFN) is always between 0-1023 --> the working interval to be considered
-	 *the nb_periods is not affected by the offset since maxOffset = 15 but the minPeriodicity = 64
-	 *
-	 */
-
-	if(si_period == SchedulingInfo_NB_r13__si_Periodicity_r13_spare)
-	{
-		LOG_E(RRC, "is_SIB23_NB: Invalid parameters in SIB1-NB --> si_periodicity not defined (spare value)\n");
-						return FALSE;
-	}
-
-	si_periodicity = si_period_to_nb[si_period];
-
-	//check if the actual frame is within an HSFN interval that will include si-window (relation with the si-periodicity)
-	//XXX this could happen when the si-periodicity is larger than a HSFN interval (1024 rf)
-	hsfn_in_periodicity = (int) si_periodicity/1024;
-
-	if(hsfn_in_periodicity > 1){//periodicity is larger than 1024rf (HSFN) and  not in all the hsfn a transmission will occurr
-
-		if(h_frameP%hsfn_in_periodicity != 0)// is not an hsfn inside the periodicity in which a transmission will occurr
-		{
-		LOG_I(RRC, "the actual HSFN correspond to an interval in which a SIB23 transmission will not occurr\n");
-		return FALSE;
-		}
-	}
-
-	if(si_windowLength_ms == SystemInformationBlockType1_NB__si_WindowLength_r13_spare1){
-		LOG_E(RRC, "is_SIB23_NB: Invalid parameters in SIB1-NB --> si_windowLength not defined (spare value)\n");
-				return FALSE;
-	}
-
-	//get the si_window in Radio Frame
-	si_windowLength = si_windowLength_to_rf[si_windowLength_ms];
+  /* for no gcc warnings */
+  (void)sdu_size;
 
-	if(si_windowLength > si_periodicity){
-		LOG_E(RRC, "is_SIB23_NB: Invalid parameters in SIB1-NB --> si_windowLength > si_periodicity\n");
-		return FALSE;
-	}
+  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, rntiP, frameP, sub_frameP,module_idP);
 
-	//get the si_pattern
-	si_pattern = si_repPattern_to_nb[si_RepetitionPattern];
+    Srb_info = &eNB_rrc_inst_NB_IoT[module_idP].carrier[CC_id].Srb0;
+    LOG_T(RRC,"[eNB %d] Received SDU for CCCH on SRB %d\n",module_idP,Srb_info->Srb_id);
 
-	if(si_RadioFrameOffset == NULL)//is not defined
-	{
-		LOG_I(RRC, "si_RadioFrame offset was NULL --> set = 0\n");
-		si_offset = 0;
-	}
-	else{
-		si_offset = *(si_RadioFrameOffset);
-	}
 
+    //this messages are used by the RRC if ITTI enabled
+#if defined(ENABLE_ITTI)
+    {
+      MessageDef *message_p;
+      int msg_sdu_size = sizeof(RRC_MAC_CCCH_DATA_IND (message_p).sdu);
 
-	//check how many nb_of periods in 1 hsfn
-	if(si_periodicity >= 1024){
-		nb_periods = 1;
-	}
-	else
-		nb_periods = 1024L / si_periodicity; // can get: 16,8,4,2 based on si_peridicity values
+      if (sdu_lenP > msg_sdu_size) {
+        LOG_E(RRC, "SDU larger than CCCH SDU buffer size (%d, %d)", sdu_lenP, msg_sdu_size);
+        sdu_size = msg_sdu_size;
+      } else {
+        sdu_size = sdu_lenP;
+      }
 
+      message_p = itti_alloc_new_message (TASK_MAC_ENB, RRC_MAC_CCCH_DATA_IND);
+      RRC_MAC_CCCH_DATA_IND (message_p).frame     = frameP;
+      RRC_MAC_CCCH_DATA_IND (message_p).sub_frame = sub_frameP;
+      RRC_MAC_CCCH_DATA_IND (message_p).rnti      = rntiP;
+      RRC_MAC_CCCH_DATA_IND (message_p).sdu_size  = sdu_size;
+      RRC_MAC_CCCH_DATA_IND (message_p).CC_id = CC_id;
+      memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE);
+      memcpy (RRC_MAC_CCCH_DATA_IND (message_p).sdu, sduP, sdu_size);
+      itti_send_msg_to_task (TASK_RRC_ENB, ctxt.instance, message_p);
+    }
+#else
 
-	for(int i = 0; i < nb_periods; i++) {
+    if (sdu_lenP > 0) {
+      memcpy(Srb_info->Rx_buffer.Payload,sduP,sdu_lenP);
+      Srb_info->Rx_buffer.payload_size = sdu_lenP;
+      rrc_eNB_decode_ccch_NB_IoT(&ctxt, Srb_info, CC_id);
+    }
 
-		w_start = si_offset+(i*si_periodicity); //if si_periodicity >= 1024--> imax =0
+#endif
+  return(0);
 
-	    if(frameP >= w_start && frameP <= w_start + si_windowLength -1)
-	    {
-	    	//this implementation is quite inefficent --> loop through the si-window
-	    	for(int x= 0; x < si_windowLength/si_pattern; x++)
-	    	{
-	    		 if(frameP == w_start +x*si_pattern)
-	    			 return 1;
-	    	}
+}
 
-	    	return 0; //the frame is in the si_window bu not belongs to the repetition pattern
-	    }
 
-	    if(w_start > frameP)// the frame is out of the si_window in the current period
-	    	return FALSE;
-	}
+//defined in L2_interface
+void mac_eNB_rrc_ul_failure_NB_IoT(
+		const module_id_t mod_idP,
+	    const int CC_idP,
+	    const frame_t frameP,
+	    const sub_frame_t subframeP,
+	    const rnti_t rntiP)
+{
+  struct rrc_eNB_ue_context_NB_IoT_s* ue_context_p = NULL;
+  ue_context_p = rrc_eNB_get_ue_context_NB_IoT(
+                   &eNB_rrc_inst_NB_IoT[mod_idP],
+                   rntiP);
 
-	return FALSE;
+  if (ue_context_p != NULL) {
+    LOG_I(RRC,"Frame %d, Subframe %d: UE %x UL failure, activating timer\n",frameP,subframeP,rntiP);
+    ue_context_p->ue_context.ul_failure_timer=1;
+  }
+  else {
+    LOG_W(RRC,"Frame %d, Subframe %d: UL failure: UE %x unknown \n",frameP,subframeP,rntiP);
+  }
+  //rrc_mac_remove_ue_NB_IoT(mod_idP,rntiP);
 }
 
-//defined in L2_interface
-//function called by eNB_dlsch_ulsch_scheduler--> Schedule_SI (eNB_scheduler_bch) for getting the bcch_sdu_legnth (BCCH case for SIBs and MIB)
-//Function called in schedule_RA for getting RRCConnectionSetup message (Msg4) length of rrc_sdu_length (CCCH case)
-//Function will be called by schedule_MIB??? when subframe#0
-int8_t NB_mac_rrc_data_req_eNB(
+
+//------------------------------------------------------------------------------
+int8_t mac_rrc_data_req_NB_IoT(
   const module_id_t Mod_idP,
   const int         CC_id,
   const frame_t     frameP,
-  const frame_t		h_frameP,
   const rb_id_t     Srb_id,
+  const uint8_t     Nb_tb,
   uint8_t*    const buffer_pP,
-  long				schedulingInfoSIB1,//from the mib
-  int				physCellId, //from the MAC instance-> common_channel
-  mib_flag_t		mib_flag
+  const eNB_flag_t  enb_flagP,
+  const uint8_t     eNB_index,
+  const uint8_t     mbsfn_sync_area
 )
+//--------------------------------------------------------------------------
 {
-  SRB_INFO_NB *Srb_info;
+  //MAC_xface_NB_IoT *mac_xface_NB_IoT; //test_xface
+  
+  SRB_INFO_NB_IoT *Srb_info;
   uint8_t Sdu_size=0;
 
-
 #ifdef DEBUG_RRC
   int i;
-  LOG_T(RRC,"[eNB %d] NB_mac_rrc_data_req_eNB to SRB ID=%d\n",Mod_idP,Srb_id);
+  LOG_T(RRC,"[eNB %d] mac_rrc_data_req to SRB ID=%d\n",Mod_idP,Srb_id);
 #endif
 
+  if( enb_flagP == ENB_FLAG_YES) {
 
-    if((Srb_id & RAB_OFFSET) == BCCH){
-
-
-     // Requesting for the MIB-NB
-      if(mib_flag == MIB_FLAG_YES){
-
-    	  //XXX to be check when MIB-NB should be initialized
-    	  if (eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_MIB_NB == 255) {
-    	       LOG_E(RRC,"[eNB %d] MAC Request for MIB-NB and MIB-NB not initialized\n",Mod_idP);
-    	       mac_xface->macphy_exit("NB_mac_rrc_data_req_eNB:  MAC Request for MIB-NB and MIB-NB not initialized");
-    	   }
-
-    	  memcpy(&buffer_pP[0],
-    	      	eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].MIB_NB,
-    	      	eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_MIB_NB);
-
-    	  	//XXX RRC_MAC_BCCH_DATA_REQ message not implemented in MAC layer (eNB_scheduler.c under ITTI)
-
-    	  	#ifdef DEBUG_RRC
-    	      LOG_T(RRC,"[eNB %d] Frame %d : BCCH request => MIB_NB\n",Mod_idP,frameP);
-
-    	     for (i=0; i<eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_MIB_NB; i++) {
-    	      		    LOG_T(RRC,"%x.",buffer_pP[i]);
-    	      	}
-
-    	      		    LOG_T(RRC,"\n");
-    	    #endif
-
-    	    return (eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_MIB_NB);
-      }
-
-      //Requesting for SI Message
-      //XXX to be check when it is initialized
-      if(eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].SI.Active==0) {
-    	  LOG_E(RRC, "SI value on the carrier = 0");
+    if((Srb_id & RAB_OFFSET) == BCCH0_NB_IoT) {
+      if(eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].SI.Active==0) {
         return 0;
       }
 
-      if(schedulingInfoSIB1 > 11 || schedulingInfoSIB1 < 0){
-    	  LOG_E(RRC, "schedulingInfoSIB1 value incorrect");
-    	  return 0;
+      // All even frames transmit SIB in SF 5
+      if (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT == 255) {
+        LOG_E(RRC,"[eNB %d] MAC Request for SIB1 and SIB1 not initialized\n",Mod_idP);
+        //exit here
       }
 
+      if ((frameP%2) == 0) {
+        memcpy(&buffer_pP[0],
+               eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].SIB1_NB_IoT,
+               eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT);
 
-      /*check if SIBs are initialized*/
-      //FIXME to be check when both are initialize and if make sense to have it
-            if (eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB1_NB == 255) {
-              LOG_E(RRC,"[eNB %d] MAC Request for SIB1-NB and SIB1-NB not initialized\n",Mod_idP);
-              mac_xface->macphy_exit("NB_mac_rrc_data_req_eNB:  MAC Request for SIB1-NB and SIB1-NB not initialized");
-            }
-
-            if (eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB23_NB == 255) {
-                    LOG_E(RRC,"[eNB %d] MAC Request for SIB23-NB and SIB23-NB not initialized\n",Mod_idP);
-                    mac_xface->macphy_exit("NB_mac_rrc_data_req_eNB:  MAC Request for SIB23-NB and SIB23-NB not initialized");
-            }
-
-
-         if(is_SIB1_NB(frameP,schedulingInfoSIB1, physCellId)){
-
-			  memcpy(&buffer_pP[0],
-					  eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].SIB1_NB,
-					  eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB1_NB);
-
-			  //XXX RRC_MAC_BCCH_DATA_REQ message not implemented in MAC layer (eNB_scheduler.c under ITTI)
+#if defined(ENABLE_ITTI)
+        {
+          MessageDef *message_p;
+          int sib1_size = eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT;
+          int sdu_size = sizeof(RRC_MAC_BCCH_DATA_REQ (message_p).sdu);
+
+          if (sib1_size > sdu_size) {
+            LOG_E(RRC, "SIB1 SDU larger than BCCH SDU buffer size (%d, %d)", sib1_size, sdu_size);
+            sib1_size = sdu_size;
+          }
 
+          message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_MAC_BCCH_DATA_REQ);
+          RRC_MAC_BCCH_DATA_REQ (message_p).frame    = frameP;
+          RRC_MAC_BCCH_DATA_REQ (message_p).sdu_size = sib1_size;
+          memset (RRC_MAC_BCCH_DATA_REQ (message_p).sdu, 0, BCCH_SDU_SIZE);
+          memcpy (RRC_MAC_BCCH_DATA_REQ (message_p).sdu,
+                  eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].SIB1_NB_IoT,
+                  sib1_size);
+          RRC_MAC_BCCH_DATA_REQ (message_p).enb_index = eNB_index;
 
-			#ifdef DEBUG_RRC
-			   LOG_T(RRC,"[eNB %d] Frame %d : BCCH request => SIB1_NB\n",Mod_idP,frameP);
+          itti_send_msg_to_task (TASK_MAC_ENB, ENB_MODULE_ID_TO_INSTANCE(Mod_idP), message_p);
+        }
+#endif
 
-			   for (i=0; i<eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB1_NB; i++) {
-			    LOG_T(RRC,"%x.",buffer_pP[i]);
-			    }
+#ifdef DEBUG_RRC
+        LOG_T(RRC,"[eNB %d] Frame %d : BCCH request => SIB 1\n",Mod_idP,frameP);
 
-			    LOG_T(RRC,"\n");
-			#endif
+        for (i=0; i<eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT; i++) {
+          LOG_T(RRC,"%x.",buffer_pP[i]);
+        }
 
-			    return (eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB1_NB);
-         }
+        LOG_T(RRC,"\n");
+#endif
 
-         //check for SIB23-Transmission
+        return (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB1_NB_IoT);
+      } // All RFN mod 8 transmit SIB2-3 in SF 5
+      else if ((frameP%8) == 1) {
+        memcpy(&buffer_pP[0],
+               eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].SIB23_NB_IoT,
+               eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB23_NB_IoT);
 
-         for(int i = 0; i<  eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sib1_NB->schedulingInfoList_r13.list.count; i++){
-        	 if(is_SIB23_NB(frameP,h_frameP,
-        		 eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sib1_NB->schedulingInfoList_r13.list.array[i]->si_Periodicity_r13,
-				 eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sib1_NB->si_WindowLength_r13,
-				 eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sib1_NB->si_RadioFrameOffset_r13,
-				 eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sib1_NB->schedulingInfoList_r13.list.array[i]->si_RepetitionPattern_r13))
-        	 {
+#if defined(ENABLE_ITTI)
+        {
+          MessageDef *message_p;
+          int sib23_size = eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB23_NB_IoT;
+          int sdu_size = sizeof(RRC_MAC_BCCH_DATA_REQ (message_p).sdu);
+
+          if (sib23_size > sdu_size) {
+            LOG_E(RRC, "SIB23 SDU larger than BCCH SDU buffer size (%d, %d)", sib23_size, sdu_size);
+            sib23_size = sdu_size;
+          }
 
-        	 memcpy(&buffer_pP[0],
-        			eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].SIB23_NB,
-        	    	eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB23_NB);
+          message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_MAC_BCCH_DATA_REQ);
+          RRC_MAC_BCCH_DATA_REQ (message_p).frame = frameP;
+          RRC_MAC_BCCH_DATA_REQ (message_p).sdu_size = sib23_size;
+          memset (RRC_MAC_BCCH_DATA_REQ (message_p).sdu, 0, BCCH_SDU_SIZE);
+          memcpy (RRC_MAC_BCCH_DATA_REQ (message_p).sdu,
+                  eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].SIB23_NB_IoT,
+                  sib23_size);
+          RRC_MAC_BCCH_DATA_REQ (message_p).enb_index = eNB_index;
 
-        	    #ifdef DEBUG_RRC
-        	    	LOG_T(RRC,"[eNB %d] Frame %d BCCH request => SIB 2-3\n",Mod_idP,frameP);
+          itti_send_msg_to_task (TASK_MAC_ENB, ENB_MODULE_ID_TO_INSTANCE(Mod_idP), message_p);
+        }
+#endif
 
-        	    	for (i=0; i<eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB23_NB; i++) {
-        	    		    LOG_T(RRC,"%x.",buffer_pP[i]);
-        	    		 }
+#ifdef DEBUG_RRC
+        LOG_T(RRC,"[eNB %d] Frame %d BCCH request => SIB 2-3\n",Mod_idP,frameP);
 
-        	    		 LOG_T(RRC,"\n");
-        	    #endif
+        for (i=0; i<eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB23_NB_IoT; i++) {
+          LOG_T(RRC,"%x.",buffer_pP[i]);
+        }
 
-        	    return(eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].sizeof_SIB23_NB);
-        	 }
-         }
+        LOG_T(RRC,"\n");
+#endif
+        return(eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_SIB23_NB_IoT);
+      } else {
         return(0);
+      }
     }
 
-    if( (Srb_id & RAB_OFFSET ) == CCCH) { //called when is requested the Msg3 transmission
+    if( (Srb_id & RAB_OFFSET ) == CCCH_NB_IoT) {
       LOG_T(RRC,"[eNB %d] Frame %d CCCH request (Srb_id %d)\n",Mod_idP,frameP, Srb_id);
 
-      if(eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].Srb0.Active==0) {
+      if(eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].Srb0.Active==0) {
         LOG_E(RRC,"[eNB %d] CCCH Not active\n",Mod_idP);
         return -1;
       }
 
-      Srb_info=&eNB_rrc_inst_NB[Mod_idP].carrier[CC_id].Srb0;
+      Srb_info=&eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].Srb0;
 
       // check if data is there for MAC
       if(Srb_info->Tx_buffer.payload_size>0) { //Fill buffer
         LOG_D(RRC,"[eNB %d] CCCH (%p) has %d bytes (dest: %p, src %p)\n",Mod_idP,Srb_info,Srb_info->Tx_buffer.payload_size,buffer_pP,Srb_info->Tx_buffer.Payload);
 
+#if defined(ENABLE_ITTI)
+        {
+          MessageDef *message_p;
+          int ccch_size = Srb_info->Tx_buffer.payload_size;
+          int sdu_size = sizeof(RRC_MAC_CCCH_DATA_REQ (message_p).sdu);
+
+          if (ccch_size > sdu_size) {
+            LOG_E(RRC, "SDU larger than CCCH SDU buffer size (%d, %d)", ccch_size, sdu_size);
+            ccch_size = sdu_size;
+          }
+
+          message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_MAC_CCCH_DATA_REQ);
+          RRC_MAC_CCCH_DATA_REQ (message_p).frame = frameP;
+          RRC_MAC_CCCH_DATA_REQ (message_p).sdu_size = ccch_size;
+          memset (RRC_MAC_CCCH_DATA_REQ (message_p).sdu, 0, CCCH_SDU_SIZE);
+          memcpy (RRC_MAC_CCCH_DATA_REQ (message_p).sdu, Srb_info->Tx_buffer.Payload, ccch_size);
+          RRC_MAC_CCCH_DATA_REQ (message_p).enb_index = eNB_index;
+
+          itti_send_msg_to_task (TASK_MAC_ENB, ENB_MODULE_ID_TO_INSTANCE(Mod_idP), message_p);
+        }
+#endif
+
         memcpy(buffer_pP,Srb_info->Tx_buffer.Payload,Srb_info->Tx_buffer.payload_size);
         Sdu_size = Srb_info->Tx_buffer.payload_size;
         Srb_info->Tx_buffer.payload_size=0;
@@ -636,169 +465,119 @@ int8_t NB_mac_rrc_data_req_eNB(
       return (Sdu_size);
     }
 
-  return(0);
-}
+#if defined(Rel10) || defined(Rel14)
 
-//defined in L2_interface
-//called by rx_sdu only in case of CCCH message (e.g RRCConnectionRequest-NB)
-int8_t NB_mac_rrc_data_ind_eNB(
-  const module_id_t     module_idP,
-  const int             CC_id,
-  const frame_t         frameP,
-  const sub_frame_t     sub_frameP,
-  const rnti_t          rntiP,
-  const rb_id_t         srb_idP,//could be skipped since always go through the CCCH channel
-  const uint8_t*        sduP,
-  const sdu_size_t      sdu_lenP
-)
-{
-  SRB_INFO_NB *Srb_info;
-  protocol_ctxt_t ctxt;
-  sdu_size_t      sdu_size = 0;
+    if((Srb_id & RAB_OFFSET) == MCCH_NB_IoT) {
+      if(eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].MCCH_MESS[mbsfn_sync_area].Active==0) {
+        return 0;  // this parameter is set in function init_mcch in rrc_eNB.c
+      }
 
-  /* for no gcc warnings */
-  (void)sdu_size;
 
-  //MP: XXX eNB_index (last parameter) set = 0 (verify)
-  PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, rntiP, frameP, sub_frameP,0);
 
-    Srb_info = &eNB_rrc_inst_NB[module_idP].carrier[CC_id].Srb0;
-    LOG_T(RRC,"[eNB %d] Received SDU for CCCH on SRB %d\n",module_idP,Srb_info->Srb_id);
+#if defined(ENABLE_ITTI)
+      {
+        MessageDef *message_p;
+        int mcch_size = eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area];
+        int sdu_size = sizeof(RRC_MAC_MCCH_DATA_REQ (message_p).sdu);
 
+        if (mcch_size > sdu_size) {
+          LOG_E(RRC, "SDU larger than MCCH SDU buffer size (%d, %d)", mcch_size, sdu_size);
+          mcch_size = sdu_size;
+        }
 
-    //this messages are used by the RRC if ITTI enabled
-#if defined(ENABLE_ITTI)
-    {
-      MessageDef *message_p;
-      int msg_sdu_size = sizeof(RRC_MAC_CCCH_DATA_IND (message_p).sdu);
+        message_p = itti_alloc_new_message (TASK_RRC_ENB, RRC_MAC_MCCH_DATA_REQ);
+        RRC_MAC_MCCH_DATA_REQ (message_p).frame = frameP;
+        RRC_MAC_MCCH_DATA_REQ (message_p).sdu_size = mcch_size;
+        memset (RRC_MAC_MCCH_DATA_REQ (message_p).sdu, 0, MCCH_SDU_SIZE);
+        memcpy (RRC_MAC_MCCH_DATA_REQ (message_p).sdu,
+                eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].MCCH_MESSAGE[mbsfn_sync_area],
+                mcch_size);
+        RRC_MAC_MCCH_DATA_REQ (message_p).enb_index = eNB_index;
+        RRC_MAC_MCCH_DATA_REQ (message_p).mbsfn_sync_area = mbsfn_sync_area;
+
+        itti_send_msg_to_task (TASK_MAC_ENB, ENB_MODULE_ID_TO_INSTANCE(Mod_idP), message_p);
+      }
+#endif
 
-      if (sdu_lenP > msg_sdu_size) {
-        LOG_E(RRC, "SDU larger than CCCH SDU buffer size (%d, %d)", sdu_lenP, msg_sdu_size);
-        sdu_size = msg_sdu_size;
-      } else {
-        sdu_size = sdu_lenP;
+      memcpy(&buffer_pP[0],
+             eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].MCCH_MESSAGE[mbsfn_sync_area],
+             eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]);
+
+#ifdef DEBUG_RRC
+      LOG_D(RRC,"[eNB %d] Frame %d : MCCH request => MCCH_MESSAGE \n",Mod_idP,frameP);
+
+      for (i=0; i<eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]; i++) {
+        LOG_T(RRC,"%x.",buffer_pP[i]);
       }
 
-      message_p = itti_alloc_new_message (TASK_MAC_ENB, RRC_MAC_CCCH_DATA_IND);
-      RRC_MAC_CCCH_DATA_IND (message_p).frame     = frameP;
-      RRC_MAC_CCCH_DATA_IND (message_p).sub_frame = sub_frameP;
-      RRC_MAC_CCCH_DATA_IND (message_p).rnti      = rntiP;
-      RRC_MAC_CCCH_DATA_IND (message_p).sdu_size  = sdu_size;
-      RRC_MAC_CCCH_DATA_IND (message_p).CC_id = CC_id;
-      memset (RRC_MAC_CCCH_DATA_IND (message_p).sdu, 0, CCCH_SDU_SIZE);
-      memcpy (RRC_MAC_CCCH_DATA_IND (message_p).sdu, sduP, sdu_size);
-      itti_send_msg_to_task (TASK_RRC_ENB, ctxt.instance, message_p);
-    }
-#else
+      LOG_T(RRC,"\n");
+#endif
 
-    if (sdu_lenP > 0) {
-      memcpy(Srb_info->Rx_buffer.Payload,sduP,sdu_lenP);
-      Srb_info->Rx_buffer.payload_size = sdu_lenP;
-      rrc_eNB_decode_ccch_NB(&ctxt, Srb_info, CC_id);
+      return (eNB_rrc_inst_NB_IoT[Mod_idP].carrier[CC_id].sizeof_MCCH_MESSAGE[mbsfn_sync_area]);
+      //      }
+      //else
+      //return(0);
     }
 
-#endif
-  return(0);
+#endif //Rel10 || Rel14
+  } else {  //This is an UE
 
-}
+    LOG_D(RRC,"[UE %d] Frame %d Filling CCCH SRB_ID %d\n",Mod_idP,frameP,Srb_id);
+    LOG_D(RRC,"[UE %d] Frame %d buffer_pP status %d,\n",Mod_idP,frameP, UE_rrc_inst_NB_IoT[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size);
 
 
-//defined in L2_interface
-void NB_mac_eNB_rrc_ul_failure(
-		const module_id_t mod_idP,
-	    const int CC_idP,
-	    const frame_t frameP,
-	    const sub_frame_t subframeP,
-	    const rnti_t rntiP)
-{
-  struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL;
-  ue_context_p = rrc_eNB_get_ue_context_NB(
-                   &eNB_rrc_inst_NB[mod_idP],
-                   rntiP);
+    if( (UE_rrc_inst_NB_IoT[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size > 0) ) {
 
-  if (ue_context_p != NULL) {
-    LOG_I(RRC,"Frame %d, Subframe %d: UE %x UL failure, activating timer\n",frameP,subframeP,rntiP);
-    ue_context_p->ue_context.ul_failure_timer=1;
-  }
-  else {
-    LOG_W(RRC,"Frame %d, Subframe %d: UL failure: UE %x unknown \n",frameP,subframeP,rntiP);
-  }
-  NB_rrc_mac_remove_ue(mod_idP,rntiP);
-}
+#if defined(ENABLE_ITTI)
+      {
+        MessageDef *message_p;
+        int ccch_size = UE_rrc_inst_NB_IoT[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size;
+        int sdu_size = sizeof(RRC_MAC_CCCH_DATA_REQ (message_p).sdu);
 
+        if (ccch_size > sdu_size) {
+          LOG_E(RRC, "SDU larger than CCCH SDU buffer size (%d, %d)", ccch_size, sdu_size);
+          ccch_size = sdu_size;
+        }
 
-//defined in eNB_scheduler_primitives.c
-int NB_rrc_mac_remove_ue(
-		module_id_t mod_idP,
-		rnti_t rntiP)
-{
-  int i;
-  UE_list_NB_t *UE_list = &eNB_mac_inst_NB[mod_idP].UE_list;
-  int UE_id = find_UE_id(mod_idP,rntiP); //may should be changed
-  int pCC_id;
-
-  if (UE_id == -1) {
-printf("MAC: cannot remove UE rnti %x\n", rntiP);
-    LOG_W(MAC,"NB_rrc_mac_remove_ue: UE %x not found\n", rntiP);
-    mac_phy_remove_ue(mod_idP, rntiP); //PHY/defs.h
-    return 0;
-  }
+        message_p = itti_alloc_new_message (TASK_RRC_UE, RRC_MAC_CCCH_DATA_REQ);
+        RRC_MAC_CCCH_DATA_REQ (message_p).frame = frameP;
+        RRC_MAC_CCCH_DATA_REQ (message_p).sdu_size = ccch_size;
+        memset (RRC_MAC_CCCH_DATA_REQ (message_p).sdu, 0, CCCH_SDU_SIZE);
+        memcpy (RRC_MAC_CCCH_DATA_REQ (message_p).sdu, UE_rrc_inst_NB_IoT[Mod_idP].Srb0[eNB_index].Tx_buffer.Payload, ccch_size);
+        RRC_MAC_CCCH_DATA_REQ (message_p).enb_index = eNB_index;
 
-  pCC_id = UE_PCCID(mod_idP,UE_id);
-
-printf("MAC: remove UE %d rnti %x\n", UE_id, rntiP);
-  LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP);
-  dump_ue_list(UE_list,0); //may should be changed
-
-  UE_list->active[UE_id] = FALSE;
-  UE_list->num_UEs--;
-
-  // clear all remaining pending transmissions
-  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0]  = 0;
-  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1]  = 0;
-  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2]  = 0;
-  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3]  = 0;
-
-  UE_list->UE_template[pCC_id][UE_id].rnti              = NOT_A_RNTI;
-  UE_list->UE_template[pCC_id][UE_id].ul_active         = FALSE;
-  eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
-  eNB_ulsch_info[mod_idP][pCC_id][UE_id].status                      = S_UL_NONE;
-  eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
-  eNB_dlsch_info[mod_idP][pCC_id][UE_id].status                      = S_DL_NONE;
-
-  NB_mac_phy_remove_ue(mod_idP,rntiP);
-
-  // check if this has an RA process active
-  RA_TEMPLATE_NB *RA_template;
-  for (i=0;i<NB_RA_PROC_MAX;i++) {
-
-    RA_template = (RA_TEMPLATE_NB *)&eNB_mac_inst[mod_idP].common_channels[pCC_id].RA_template[i];
-    if (RA_template->rnti == rntiP){
-      RA_template->RA_active=FALSE;
-      RA_template->generate_rar=0;
-      RA_template->generate_Msg4=0;
-      RA_template->wait_ack_Msg4=0;
-      RA_template->timing_offset=0;
-      RA_template->RRC_timer=20;
-      RA_template->rnti = 0;
-      //break;
+        itti_send_msg_to_task (TASK_MAC_UE, UE_MODULE_ID_TO_INSTANCE(Mod_idP), message_p);
+      }
+#endif
+
+      memcpy(&buffer_pP[0],&UE_rrc_inst_NB_IoT[Mod_idP].Srb0[eNB_index].Tx_buffer.Payload[0],UE_rrc_inst_NB_IoT[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size);
+      uint8_t Ret_size=UE_rrc_inst_NB_IoT[Mod_idP].Srb0[eNB_index].Tx_buffer.payload_size;
+      //   UE_rrc_inst[Mod_id].Srb0[eNB_index].Tx_buffer.payload_size=0;
+      UE_rrc_inst_NB_IoT[Mod_idP].Info[eNB_index].T300_active = 1;
+      UE_rrc_inst_NB_IoT[Mod_idP].Info[eNB_index].T300_cnt = 0;
+      //      msg("[RRC][UE %d] Sending rach\n",Mod_id);
+      return(Ret_size);
+    } else {
+      return 0;
     }
   }
 
-  return 0;
+  return(0);
 }
 
+
+
 //defined in L2_interface
-void NB_mac_eNB_rrc_ul_in_sync(
+void mac_eNB_rrc_ul_in_sync_NB_IoT(
 				const module_id_t mod_idP,
 			    const int CC_idP,
 			    const frame_t frameP,
 			    const sub_frame_t subframeP,
 			    const rnti_t rntiP)
 {
-  struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL;
-  ue_context_p = rrc_eNB_get_ue_context_NB(
-                   &eNB_rrc_inst_NB[mod_idP],
+  struct rrc_eNB_ue_context_NB_IoT_s* ue_context_p = NULL;
+  ue_context_p = rrc_eNB_get_ue_context_NB_IoT(
+                   &eNB_rrc_inst_NB_IoT[mod_idP],
                    rntiP);
 
   if (ue_context_p != NULL) {
@@ -812,35 +591,63 @@ void NB_mac_eNB_rrc_ul_in_sync(
 }
 
 //defined in L2_interface
-int NB_mac_eNB_get_rrc_status(
+int mac_eNB_get_rrc_status_NB_IoT(
   const module_id_t Mod_idP,
   const rnti_t      rntiP
 )
 {
-  struct rrc_eNB_ue_context_NB_s* ue_context_p = NULL;
-  ue_context_p = rrc_eNB_get_ue_context_NB(
-                   &eNB_rrc_inst_NB[Mod_idP],
+  struct rrc_eNB_ue_context_NB_IoT_s* ue_context_p = NULL;
+  ue_context_p = rrc_eNB_get_ue_context_NB_IoT(
+                   &eNB_rrc_inst_NB_IoT[Mod_idP],
                    rntiP);
 
   if (ue_context_p != NULL) {
     return(ue_context_p->ue_context.Status);
   } else {
-    return RRC_INACTIVE;
+    return RRC_INACTIVE_NB_IoT;
   }
 }
 
 /*----------------------------------RRC-PDCP--------------------------------------*/
 
+//defined in pdcp_security.c
+static
+uint32_t pdcp_get_next_count_tx_NB_IoT(pdcp_t *const pdcp_pP, const srb_flag_t srb_flagP, const uint16_t pdcp_sn);
+
+//-----------------------------------------------------------------------------
+static
+uint32_t pdcp_get_next_count_tx_NB_IoT(
+  pdcp_t * const pdcp_pP,
+  const srb_flag_t srb_flagP,
+  const uint16_t pdcp_sn
+)
+{
+  uint32_t count; //32 bits
+
+  /* For TX COUNT = TX_HFN << length of SN | pdcp SN */
+  if (srb_flagP) {
+    /* 5 bits length SN */
+    count = ((pdcp_pP->tx_hfn << 5)  | (pdcp_sn & 0x001F));
+  } else { //DRB
+    /*Default is the 7 bits length SN TS 36.323 ch 6.2.4*/
+    count = ((pdcp_pP->tx_hfn << 7) | (pdcp_sn & 0x007F)); //FIXME: MP: to be check if ok
+  }
+
+  LOG_D(PDCP, "[OSA] TX COUNT = 0x%08x\n", count);
+
+  return count;
+}
+
+
 
 //defined in pdcp_security.c
-//called in NB_pdcp_data_req
+//called in pdcp_data_req_NB_IoT
 //-----------------------------------------------------------------------------
-int
-NB_pdcp_apply_security(
+int pdcp_apply_security_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   pdcp_t        *const pdcp_pP,
   const srb_flag_t     srb_flagP,
-  const rb_id_t        rb_id, //rb_idP % maxDRB_NB_r13
+  const rb_id_t        rb_id, //rb_idP % maxDRB_NB_r13 = rb_id % 2 --> 0,1
   const uint8_t        pdcp_header_len,
   const uint16_t       current_sn,
   uint8_t       * const pdcp_pdu_buffer,
@@ -858,7 +665,7 @@ NB_pdcp_apply_security(
 
   encrypt_params.direction  = (pdcp_pP->is_ue == 1) ? SECU_DIRECTION_UPLINK : SECU_DIRECTION_DOWNLINK;
   encrypt_params.bearer     = rb_id - 1;
-  encrypt_params.count      = pdcp_get_next_count_tx(pdcp_pP, srb_flagP, current_sn);
+  encrypt_params.count      = pdcp_get_next_count_tx_NB_IoT(pdcp_pP, srb_flagP, current_sn); //XXX (warning) because static defined in pdcp_security.c
   encrypt_params.key_length = 16;
 
   if (srb_flagP) {
@@ -904,11 +711,9 @@ NB_pdcp_apply_security(
 }
 
 
-
-
 //FIXME for the moment we not configure PDCP for SRB1bis (but used as it is SRB1)
 //defined in pdcp.c
-boolean_t NB_rrc_pdcp_config_asn1_req (
+boolean_t rrc_pdcp_config_asn1_req_NB_IoT (
   const protocol_ctxt_t* const  ctxt_pP,
   SRB_ToAddModList_NB_r13_t  *const srb2add_list_pP,
   DRB_ToAddModList_NB_r13_t  *const drb2add_list_pP,
@@ -952,31 +757,31 @@ boolean_t NB_rrc_pdcp_config_asn1_req (
 
   if (srb2add_list_pP != NULL) {
 
-	  if(LCID == DCCH0) //SRB1bis
+	  if(LCID == DCCH0_NB_IoT) //SRB1bis
 	  	{
-		  LOG_E(PDCP, PROTOCOL_PDCP_CTXT_FMT" PDCP Configiration for SRB1bis not allowed\n");
+		  LOG_E(PDCP,"PDCP Configuration for SRB1bis not allowed\n");
 		  return 0;
 		}
 	  else
 	   {
 		  //is SRB1
-		  srb_id = DCCH1;
+		  srb_id = DCCH1_NB_IoT;
 		  lc_id = srb_id;
 	   }
 
 	/*Security Mode Failure*/
     if(security_modeP == -1){
 
-    	LOG_D(PDCP, "SecurityModeFailure --> NB_rrc_pdcp_config_asn1_req --> Disabling security for srb2add_list_pP\n");
+    	LOG_D(PDCP, "SecurityModeFailure --> rrc_pdcp_config_asn1_req_NB_IoT --> Disabling security for srb2add_list_pP\n");
 
-    	for(int cnt=0; cnt< srb2add_list_pP->list.count; cnt++)//may not needed a loop
+    	for(int cnt=0; cnt< srb2add_list_pP->list.count; cnt++)
     	   {
 
     	    key = PDCP_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ENB_FLAG_YES, srb_id, SRB_FLAG_YES);
     	    h_rc = hashtable_get(pdcp_coll_p,key, (void**)&pdcp_p);
 
     	    if(h_rc != HASH_TABLE_OK){
-    	       LOG_I(PDCP, "SecurityModeFailure --> NB_rrc_pdcp_config_asn1_req not available pdcp entity for disable security for this SRB");
+    	       LOG_I(PDCP, "SecurityModeFailure --> rrc_pdcp_config_asn1_req_NB_IoT not available pdcp entity for disable security for this SRB");
     	    	    	continue;
     	      }
 
@@ -1040,7 +845,7 @@ boolean_t NB_rrc_pdcp_config_asn1_req (
           default:
         	  //configure the pdcp depend on the action
         	  //is a switch case on the "action" parameter
-            NB_pdcp_config_req_asn1 (
+            pdcp_config_req_asn1_NB_IoT (
               ctxt_pP,
               pdcp_p,
               SRB_FLAG_YES,
@@ -1061,7 +866,7 @@ boolean_t NB_rrc_pdcp_config_asn1_req (
           break;
 
         case SRB_ToAddMod_NB_r13__rlc_Config_r13_PR_defaultValue:
-        	NB_pdcp_config_req_asn1 (
+        	pdcp_config_req_asn1_NB_IoT (
         	              ctxt_pP,
         	              pdcp_p,
         	              SRB_FLAG_YES,
@@ -1199,7 +1004,7 @@ boolean_t NB_rrc_pdcp_config_asn1_req (
           break;
         }
 
-        NB_pdcp_config_req_asn1 (
+        pdcp_config_req_asn1_NB_IoT (
           ctxt_pP,
           pdcp_p,
           SRB_FLAG_NO,
@@ -1234,7 +1039,7 @@ boolean_t NB_rrc_pdcp_config_asn1_req (
       lc_id = pdcp_p->lcid;
 
       action = CONFIG_ACTION_REMOVE;
-      NB_pdcp_config_req_asn1 (
+      pdcp_config_req_asn1_NB_IoT (
         ctxt_pP,
         pdcp_p,
         SRB_FLAG_NO,
@@ -1271,8 +1076,7 @@ boolean_t NB_rrc_pdcp_config_asn1_req (
 
 //defined in pdcp.c --> should be called only by a SRB1 (is internal to PDCP so is not an interface)
 //-----------------------------------------------------------------------------
-boolean_t
-NB_pdcp_config_req_asn1 (
+boolean_t pdcp_config_req_asn1_NB_IoT (
   const protocol_ctxt_t* const  ctxt_pP,
   pdcp_t         * const        pdcp_pP,
   const srb_flag_t              srb_flagP,
@@ -1431,7 +1235,7 @@ NB_pdcp_config_req_asn1 (
 //defined in L2_interface/pdcp.c
 //FIXME SRB1bis should bypass the pdcp
 //Distinction between different SRBs will be done by means of rd_id
-uint8_t NB_rrc_data_req(
+uint8_t rrc_data_req_NB_IoT(
   const protocol_ctxt_t*   const ctxt_pP,
   const rb_id_t                  rb_idP,
   const mui_t                    muiP,
@@ -1493,7 +1297,7 @@ uint8_t NB_rrc_data_req(
 #else
 
   //MP:in this case since is called by RRC for sure we have "SRB_FLAG_YES"
-  return NB_pdcp_data_req(
+  return pdcp_data_req_NB_IoT(
            ctxt_pP,
            SRB_FLAG_YES,
            rb_idP,
@@ -1507,7 +1311,7 @@ uint8_t NB_rrc_data_req(
 
 
 //we distinguish the SRBs based on the logical channel id and the transmission mode
-boolean_t NB_pdcp_data_req(
+boolean_t pdcp_data_req_NB_IoT(
   protocol_ctxt_t*  ctxt_pP,
   const srb_flag_t     srb_flagP, //SRB_FLAG_YES if called by RRC
   const rb_id_t        rb_idP,
@@ -1518,7 +1322,6 @@ boolean_t NB_pdcp_data_req(
   const pdcp_transmission_mode_t modeP
 )
 {
-
   pdcp_t            *pdcp_p          = NULL;
   uint8_t            i               = 0;
   uint8_t            pdcp_header_len = 0;
@@ -1557,8 +1360,7 @@ boolean_t NB_pdcp_data_req(
   if (sdu_buffer_sizeP > MAX_IP_PACKET_SIZE) {
     LOG_E(PDCP, "Requested SDU size (%d) is bigger than that can be handled by PDCP (%u)!\n",
           sdu_buffer_sizeP, MAX_IP_PACKET_SIZE);
-    // XXX What does following call do?
-    mac_xface->macphy_exit("PDCP sdu buffer size > MAX_IP_PACKET_SIZE");
+    // exit here
   }
 
   //check for MBMS not needed for NB-IoT*/
@@ -1620,7 +1422,7 @@ boolean_t NB_pdcp_data_req(
 	                                      sdu_buffer_sizeP);
 	      #endif
 
-	      rlc_status = NB_rlc_data_req(ctxt_pP, srb_flagP, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
+	      rlc_status = rlc_data_req_NB_IoT(ctxt_pP, srb_flagP, rb_idP, muiP, confirmP, sdu_buffer_sizeP, pdcp_pdu_p);
 	      //MP: if all ok rlc_status = RLC_OP_STATUS_OK
 
 	   } else {
@@ -1755,8 +1557,8 @@ boolean_t NB_pdcp_data_req(
           start_meas(&UE_pdcp_stats[ctxt_pP->module_id].apply_security);
         }
 
-        //FIXME also this function should be checked for NB-IoT (defined in pdcp_security.c)
-        NB_pdcp_apply_security(ctxt_pP,
+
+        pdcp_apply_security_NB_IoT(ctxt_pP,
                             pdcp_p,
                             srb_flagP,
                             rb_idP % maxDRB_NB_r13,
@@ -1814,7 +1616,7 @@ boolean_t NB_pdcp_data_req(
 
     LOG_F(PDCP,"\n");
 #endif
-    rlc_status = NB_rlc_data_req(ctxt_pP, srb_flagP,rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
+    rlc_status = rlc_data_req_NB_IoT(ctxt_pP, srb_flagP,rb_idP, muiP, confirmP, pdcp_pdu_size, pdcp_pdu_p);
 
   }
 
@@ -1862,9 +1664,10 @@ boolean_t NB_pdcp_data_req(
 
 
 
-
 //defined in L2_interface
-void NB_rrc_data_ind(
+//called by the PDCP in the pdcp_data_ind
+//mapped to rlc_rrc_data_ind (but maybe no more used for this purpose)
+void rrc_data_ind_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const rb_id_t                Srb_id,
   const sdu_size_t             sdu_sizeP,
@@ -1893,7 +1696,7 @@ void NB_rrc_data_ind(
           ctxt_pP->rnti);
   }
 
-  //FiXME: MP: we should put out this messages from ITTI
+  //FiXME: MP: we should put out this messages from ITTI ??
 #if defined(ENABLE_ITTI) //From PDCP to RRC
   {
     MessageDef *message_p;
@@ -1917,9 +1720,9 @@ void NB_rrc_data_ind(
 #else
 
   if (ctxt_pP->enb_flag == ENB_FLAG_YES) {
-    rrc_eNB_decode_dcch_NB(
+    rrc_eNB_decode_dcch_NB_IoT(
       ctxt_pP,
-	  DCCH_index, //--> becomes the srb_id in decode_dcch
+	  DCCH_index, // becomes the srb_id in decode_dcch
       buffer_pP,
       sdu_sizeP);
   } else {
@@ -1934,16 +1737,12 @@ void NB_rrc_data_ind(
 #endif
 }
 
-//defined in pdcp.c
-boolean_t NB_pdcp_remove_UE(
-  const protocol_ctxt_t* const  ctxt_pP
-);
 
 
 /*---------------------------------RRC-RLC-----------------------------------*/
 
 //defined in rlc_rrc.c
-rlc_op_status_t NB_rrc_rlc_config_asn1_req (
+rlc_op_status_t rrc_rlc_config_asn1_req_NB_IoT (
 	const protocol_ctxt_t   * const ctxt_pP,
     const SRB_ToAddModList_NB_r13_t   * const srb2add_listP,
     const DRB_ToAddModList_NB_r13_t   * const drb2add_listP,
@@ -1981,10 +1780,10 @@ rlc_op_status_t NB_rrc_rlc_config_asn1_req (
 
   if (srb2add_listP != NULL) {
 		if(srb1bis_flag == SRB1BIS_FLAG_YES){
-	    	rb_id = DCCH0;
+	    	rb_id = DCCH0_NB_IoT; //3
 		}//srb1bis
 	    else{
-	    	rb_id = DCCH1;
+	    	rb_id = DCCH1_NB_IoT; //1
 	    }//srb1
 
 	    lc_id = rb_id;
@@ -2005,8 +1804,8 @@ rlc_op_status_t NB_rrc_rlc_config_asn1_req (
             break;
 
           case RLC_Config_NB_r13_PR_am:
-            if (NB_rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, rb_id, lc_id, RLC_MODE_AM) != NULL) {
-              NB_config_req_rlc_am_asn1 (
+            if (rrc_rlc_add_rlc_NB_IoT (ctxt_pP, SRB_FLAG_YES, rb_id, lc_id, RLC_MODE_AM) != NULL) {
+              config_req_rlc_am_asn1_NB_IoT (
                 ctxt_pP,
                 SRB_FLAG_YES,
                 &srb_toaddmod_p->rlc_Config_r13->choice.explicitValue.choice.am,
@@ -2030,19 +1829,20 @@ rlc_op_status_t NB_rrc_rlc_config_asn1_req (
           break; //RLC explicit value
 
         case SRB_ToAddMod_NB_r13__rlc_Config_r13_PR_defaultValue:
-//#warning TO DO SRB_ToAddMod__rlc_Config_PR_defaultValue
+
           LOG_I(RRC, "RLC SRB1/SRB1bis is default value !!\n");
           struct RLC_Config_NB_r13__am  *  config_am_pP = &srb_toaddmod_p->rlc_Config_r13->choice.explicitValue.choice.am;
           config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13     = T_PollRetransmit_NB_r13_ms25000;
           config_am_pP->ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t4;
           config_am_pP->dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = NULL; //should be disabled
 
-          if (NB_rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_YES, rb_id, lc_id, RLC_MODE_AM) != NULL) {
-            NB_config_req_rlc_am_asn1 (
+          if (rrc_rlc_add_rlc_NB_IoT (ctxt_pP, SRB_FLAG_YES, rb_id, lc_id, RLC_MODE_AM) != NULL) {
+            config_req_rlc_am_asn1_NB_IoT (
               ctxt_pP,
               SRB_FLAG_YES,
               &srb_toaddmod_p->rlc_Config_r13->choice.explicitValue.choice.am,
-              rb_id,lc_id);
+              rb_id,
+			  lc_id);
           } else {
             LOG_E(RLC, PROTOCOL_CTXT_FMT" ERROR IN ALLOCATING SRB %d \n",
                   PROTOCOL_CTXT_ARGS(ctxt_pP),
@@ -2084,8 +1884,8 @@ rlc_op_status_t NB_rrc_rlc_config_asn1_req (
           break;
 
         case RLC_Config_NB_r13_PR_am:
-          if (NB_rrc_rlc_add_rlc (ctxt_pP, SRB_FLAG_NO, drb_id, lc_id, RLC_MODE_AM) != NULL) {
-            NB_config_req_rlc_am_asn1 (
+          if (rrc_rlc_add_rlc_NB_IoT (ctxt_pP, SRB_FLAG_NO, drb_id, lc_id, RLC_MODE_AM) != NULL) {
+            config_req_rlc_am_asn1_NB_IoT (
               ctxt_pP,
               SRB_FLAG_NO,
               &drb_toaddmod_p->rlc_Config_r13->choice.am,
@@ -2106,10 +1906,10 @@ rlc_op_status_t NB_rrc_rlc_config_asn1_req (
   if (drb2release_listP != NULL) {
     for (cnt=0; cnt<drb2release_listP->list.count; cnt++) {
       pdrb_id = drb2release_listP->list.array[cnt];
-      NB_rrc_rlc_remove_rlc(
-        ctxt_pP,
-        SRB_FLAG_NO,
-        *pdrb_id);
+      rrc_rlc_remove_rlc_NB_IoT(
+                                ctxt_pP,
+                                SRB_FLAG_NO,
+                                *pdrb_id);
     }
   }
 
@@ -2125,7 +1925,7 @@ rlc_op_status_t NB_rrc_rlc_config_asn1_req (
 uint32_t pollRetransmit_NB_tab[T_PollRetransmit_NB_r13_spare1] = {250,500,1000,2000,3000,4000,6000,10000,15000,25000,40000,60000,90000,120000,180000};
 uint32_t maxRetxThreshold_NB_tab[UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t32 +1] = {1,2,3,4,6,8,16,32};
 //-----------------------------------------------------------------------------
-void NB_config_req_rlc_am_asn1 (
+void config_req_rlc_am_asn1_NB_IoT (
   const protocol_ctxt_t* const         ctxt_pP,
   const srb_flag_t                     srb_flagP,
   const struct RLC_Config_NB_r13__am  * const config_am_pP, //extracted from the srb_toAddMod
@@ -2142,10 +1942,10 @@ void NB_config_req_rlc_am_asn1 (
   if (h_rc == HASH_TABLE_OK) {
     l_rlc_p = &rlc_union_p->rlc.am;
 
-    //MP: TODO: check if this conditions are correct
+    //MP: check if this conditions are correct
     if ((config_am_pP->ul_AM_RLC_r13.maxRetxThreshold_r13 <= UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t32) &&
-        (config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13 < T_PollRetransmit_NB_r13_spare1))
-		//&&(config_am_pP->dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 == NULL) //MP: may this check is not needed
+        (config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13 < T_PollRetransmit_NB_r13_spare1)
+		&&(config_am_pP->dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 == NULL))
 		{
 
       MSC_LOG_RX_MESSAGE(
@@ -2158,19 +1958,19 @@ void NB_config_req_rlc_am_asn1 (
         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p),
         pollRetransmit_NB_tab[config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13]);
 
-      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold_NB = %d t_poll_retransmit_NB = %d \n",
+      LOG_D(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold_NB_IoT = %d t_poll_retransmit_NB_IoT = %d \n",
             PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
             maxRetxThreshold_NB_tab[config_am_pP->ul_AM_RLC_r13.maxRetxThreshold_r13],
             pollRetransmit_NB_tab[config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13]);
 
-      //FIXME: the following function are ok for NB_IoT??
+      //XXX: the following function are ok for NB_IoT??
       rlc_am_init(ctxt_pP, l_rlc_p);
       rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
-      NB_rlc_am_configure(ctxt_pP,
-    		  	  	  	  l_rlc_p,
-						  maxRetxThreshold_NB_tab[config_am_pP->ul_AM_RLC_r13.maxRetxThreshold_r13],
-						  pollRetransmit_NB_tab[config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13],
-						  config_am_pP->dl_AM_RLC_r13.enableStatusReportSN_Gap_r13); //may not needed to be passed
+      rlc_am_configure_NB_IoT(ctxt_pP,
+    		  	  	  	l_rlc_p,
+						maxRetxThreshold_NB_tab[config_am_pP->ul_AM_RLC_r13.maxRetxThreshold_r13],
+						pollRetransmit_NB_tab[config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13],
+						(uint32_t*) config_am_pP->dl_AM_RLC_r13.enableStatusReportSN_Gap_r13); //MP:XXX this cast generate problem??
     } else {
       MSC_LOG_RX_DISCARDED_MESSAGE(
         (ctxt_pP->enb_flag == ENB_FLAG_YES) ? MSC_RLC_ENB:MSC_RLC_UE,
@@ -2182,7 +1982,7 @@ void NB_config_req_rlc_am_asn1 (
         PROTOCOL_RLC_AM_MSC_ARGS(ctxt_pP, l_rlc_p));
 
       LOG_D(RLC,
-            PROTOCOL_RLC_AM_CTXT_FMT"ILLEGAL CONFIG_REQ (max_retx_threshold_NB=%ld t_poll_retransmit_NB=%ld), RLC-AM NOT CONFIGURED\n",
+            PROTOCOL_RLC_AM_CTXT_FMT"ILLEGAL CONFIG_REQ (max_retx_threshold_NB_IoT=%ld t_poll_retransmit_NB_IoT=%ld), RLC-AM NOT CONFIGURED\n",
             PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
             config_am_pP->ul_AM_RLC_r13.maxRetxThreshold_r13,
             config_am_pP->ul_AM_RLC_r13.t_PollRetransmit_r13);
@@ -2195,17 +1995,16 @@ void NB_config_req_rlc_am_asn1 (
 
 //defined in rlc_am_init.c
 //-----------------------------------------------------------------------------
-void
-NB_rlc_am_configure(
-  const protocol_ctxt_t* const  ctxt_pP,
-  rlc_am_entity_t *const        rlc_pP,
+void rlc_am_configure_NB_IoT(
+  const protocol_ctxt_t         *const  ctxt_pP,
+  rlc_am_entity_t               *const  rlc_pP,
   const uint16_t                max_retx_thresholdP,
   const uint16_t                t_poll_retransmitP,
-  const uint16_t* const			enableStatusReportSN_Gap
+  uint32_t                *enableStatusReportSN_Gap
   )
 {
   if (rlc_pP->configured == TRUE) {
-    LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RECONFIGURE] max_retx_threshold_NB %d t_poll_retransmit_NB %d\n",
+    LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[RECONFIGURE] max_retx_threshold_NB_IoT %d t_poll_retransmit_NB_IoT %d\n",
           PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
           max_retx_thresholdP,
           t_poll_retransmitP
@@ -2213,23 +2012,23 @@ NB_rlc_am_configure(
 
     //FIXME: rlc_am_entity_t should be modified??
 
-    rlc_pP->max_retx_threshold = max_retx_thresholdP;
+    rlc_pP->max_retx_threshold_NB_IoT = max_retx_thresholdP;
     rlc_pP->protocol_state     = RLC_DATA_TRANSFER_READY_STATE;
-    rlc_pP->t_poll_retransmit.ms_duration   = t_poll_retransmitP;
-    rlc_pP->enableStatusReportSN_Gap = *(enableStatusReportSN_Gap); //FIXME: new defined in rlc_am_entity
+    rlc_pP->t_poll_retransmit_NB_IoT.ms_duration   = t_poll_retransmitP;
+    rlc_pP->enableStatusReportSN_Gap_NB_IoT = enableStatusReportSN_Gap;
 
 
   } else {
-    LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[CONFIGURE] max_retx_threshold_NB %d t_poll_retransmit_NB %d\n",
+    LOG_I(RLC, PROTOCOL_RLC_AM_CTXT_FMT"[CONFIGURE] max_retx_threshold_NB_IoT %d t_poll_retransmit_NB_IoT %d\n",
           PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,rlc_pP),
           max_retx_thresholdP,
           t_poll_retransmitP
 		  //enableStatusReportSN_Gap
     		);
 
-    rlc_pP->max_retx_threshold = max_retx_thresholdP;
+    rlc_pP->max_retx_threshold_NB_IoT = max_retx_thresholdP;
     rlc_pP->protocol_state     = RLC_DATA_TRANSFER_READY_STATE;
-    rlc_pP->enableStatusReportSN_Gap = enableStatusReportSN_Gap;
+    rlc_pP->enableStatusReportSN_Gap_NB_IoT = enableStatusReportSN_Gap;
 
 
     rlc_am_init_timer_poll_retransmit(ctxt_pP, rlc_pP, t_poll_retransmitP);
@@ -2241,7 +2040,7 @@ NB_rlc_am_configure(
 
 //defined in rlc_rrc.c
 //-----------------------------------------------------------------------------
-rlc_union_t* NB_rrc_rlc_add_rlc   (
+rlc_union_t* rrc_rlc_add_rlc_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t        srb_flagP,
   const rb_id_t           rb_idP,
@@ -2322,7 +2121,7 @@ rlc_union_t* NB_rrc_rlc_add_rlc   (
 
 //defined in rlc_rrc.c
 //-----------------------------------------------------------------------------
-rlc_op_status_t NB_rrc_rlc_remove_rlc   (
+rlc_op_status_t rrc_rlc_remove_rlc_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t  srb_flagP,
   const rb_id_t     rb_idP)
@@ -2341,7 +2140,7 @@ rlc_op_status_t NB_rrc_rlc_remove_rlc   (
 #endif
 
   if(rb_idP == 2){
-	  LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] NB_rrc_rlc_remove_rlc --> rb_id = 2 (SRB2) should not be used in NB-IoT!\n",
+	  LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_remove_rlc_NB_IoT --> rb_id = 2 (SRB2) should not be used in NB-IoT!\n",
 	              PROTOCOL_CTXT_ARGS(ctxt_pP),
 	              (srb_flagP) ? "SRB" : "DRB",
 	              rb_idP);
@@ -2353,7 +2152,7 @@ rlc_op_status_t NB_rrc_rlc_remove_rlc   (
 
   {
 	  //MP: this function know that if i have to search for a DRB the rb_idP that i pass could also be 1,3,... so add something ??
-	  //see NB_rrc_rlc_remove_ue
+	  //see rrc_rlc_remove_ue_NB_IoT
     key = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
   }
 
@@ -2410,14 +2209,54 @@ rlc_op_status_t NB_rrc_rlc_remove_rlc   (
   return RLC_OP_STATUS_OK;
 }
 
-//defined in rlc_rrc.c //used only for process_RRCConnectionReconfigurationComplete --> CONFIG_ACTION_REMOVE
-//used also for rrc_t310_expiration --> I don't know if it is used (probably not)
-rlc_op_status_t NB_rrc_rlc_config_req   (
-  const protocol_ctxt_t* const ctxt_pP,
-  const srb_flag_t      srb_flagP,
-  const config_action_t actionP,
-  const rb_id_t         rb_idP,
-  const rlc_info_t      rlc_infoP)
+
+//defined in rlc_am.c
+//-----------------------------------------------------------------------------
+void config_req_rlc_am_NB_IoT (
+  const protocol_ctxt_t        *const ctxt_pP,
+  const srb_flag_t             srb_flagP,
+  rlc_am_info_NB_IoT_t         *const config_am_pP, //XXX: MP: rlc_am_init.c --> this structure has been modified for NB-IoT
+  const rb_id_t                rb_idP,
+  const logical_chan_id_t      chan_idP
+)
+{
+  rlc_union_t       *rlc_union_p = NULL;
+  rlc_am_entity_t *l_rlc_p         = NULL;
+  hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
+  hashtable_rc_t   h_rc;
+
+  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
+
+  if (h_rc == HASH_TABLE_OK) {
+    l_rlc_p = &rlc_union_p->rlc.am;
+    LOG_D(RLC,
+          PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d t_poll_retransmit=%d)\n",
+          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
+          config_am_pP->max_retx_threshold_NB_IoT,
+          config_am_pP->t_poll_retransmit_NB_IoT
+      //enableStatusReportSN_Gap_r13
+      );
+    rlc_am_init(ctxt_pP, l_rlc_p);
+    rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
+    rlc_am_configure_NB_IoT(ctxt_pP,
+              l_rlc_p,
+            config_am_pP->max_retx_threshold_NB_IoT,
+            config_am_pP->t_poll_retransmit_NB_IoT,
+            config_am_pP->enableStatusReportSN_Gap_NB_IoT);
+  } else {
+    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ RLC NOT FOUND\n",
+          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
+  }
+}
+
+//defined in rlc_rrc.c
+//used only for rrc_t310_expiration --> I don't know if it is used (probably not)
+rlc_op_status_t rrc_rlc_config_req_NB_IoT (
+  const protocol_ctxt_t                    *const ctxt_pP,
+  const srb_flag_t                         srb_flagP,
+  const config_action_t                    actionP,
+  const rb_id_t                            rb_idP,
+  rlc_info_t                               rlc_infoP)
 {
   //-----------------------------------------------------------------------------
   //rlc_op_status_t status;
@@ -2435,9 +2274,9 @@ rlc_op_status_t NB_rrc_rlc_config_req   (
 
   switch (actionP) {
 
-  //XXX MP:is not used for adding rlc instance??
+  //XXX MP:this functuion is not used for adding rlc instance
   case CONFIG_ACTION_ADD:
-    if (NB_rrc_rlc_add_rlc(ctxt_pP, srb_flagP, rb_idP, rb_idP, rlc_infoP.rlc_mode) != NULL) {
+    if (rrc_rlc_add_rlc_NB_IoT(ctxt_pP, srb_flagP, rb_idP, rb_idP, rlc_infoP.rlc_mode) != NULL) {
       return RLC_OP_STATUS_INTERNAL_ERROR;
     }
 
@@ -2449,10 +2288,10 @@ rlc_op_status_t NB_rrc_rlc_config_req   (
             PROTOCOL_CTXT_ARGS(ctxt_pP),
             rb_idP);
 
-      NB_config_req_rlc_am(
+      config_req_rlc_am_NB_IoT(
         ctxt_pP,
         srb_flagP,
-        &rlc_infoP.rlc.rlc_am_info_NB, //MP: pass the volatile structure for NB_IoT protocol params in rlc_am_init.h
+        &rlc_infoP.rlc.rlc_am_info_NB_IoT, //MP: pass the volatile structure for NB_IoT protocol params in rlc_am_init.h // warning present
         rb_idP, rb_idP);
       break;
 
@@ -2460,7 +2299,7 @@ rlc_op_status_t NB_rrc_rlc_config_req   (
       LOG_I(RLC, PROTOCOL_CTXT_FMT"[RB %u] MODIFY RB TM\n",
             PROTOCOL_CTXT_ARGS(ctxt_pP),
             rb_idP);
-      NB_config_req_rlc_tm( //MP: TM mode configuration
+      config_req_rlc_tm_NB_IoT( //MP: TM mode configuration
         ctxt_pP,
         srb_flagP,
         &rlc_infoP.rlc.rlc_tm_info,
@@ -2475,7 +2314,7 @@ rlc_op_status_t NB_rrc_rlc_config_req   (
     break;
 
   case CONFIG_ACTION_REMOVE:
-    return NB_rrc_rlc_remove_rlc(ctxt_pP, srb_flagP, rb_idP);
+    return rrc_rlc_remove_rlc_NB_IoT(ctxt_pP, srb_flagP, rb_idP);
     break;
 
   default:
@@ -2486,50 +2325,11 @@ rlc_op_status_t NB_rrc_rlc_config_req   (
 }
 
 
-//defined in rlc_am.c
-//-----------------------------------------------------------------------------
-void
-NB_config_req_rlc_am (
-  const protocol_ctxt_t* const ctxt_pP,
-  const srb_flag_t             srb_flagP,
-  rlc_am_info_NB_t  * const       config_am_pP, //XXX: MP: rlc_am_init.c --> this structure has been modified for NB-IoT
-  const rb_id_t                rb_idP,
-  const logical_chan_id_t      chan_idP
-)
-{
-  rlc_union_t       *rlc_union_p = NULL;
-  rlc_am_entity_t *l_rlc_p         = NULL;
-  hash_key_t       key           = RLC_COLL_KEY_VALUE(ctxt_pP->module_id, ctxt_pP->rnti, ctxt_pP->enb_flag, rb_idP, srb_flagP);
-  hashtable_rc_t   h_rc;
-
-  h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
-
-  if (h_rc == HASH_TABLE_OK) {
-    l_rlc_p = &rlc_union_p->rlc.am;
-    LOG_D(RLC,
-          PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ (max_retx_threshold=%d t_poll_retransmit=%d)\n",
-          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p),
-          config_am_pP->max_retx_threshold,
-          config_am_pP->t_poll_retransmit
-		  //enableStatusReportSN_Gap_r13
-		  );
-    rlc_am_init(ctxt_pP, l_rlc_p);
-    rlc_am_set_debug_infos(ctxt_pP, l_rlc_p, srb_flagP, rb_idP, chan_idP);
-    NB_rlc_am_configure(ctxt_pP,
-    					l_rlc_p,
-						config_am_pP->max_retx_threshold,
-                    	config_am_pP->t_poll_retransmit,
-						&config_am_pP->enableStatusReportSN_Gap);
-  } else {
-    LOG_E(RLC, PROTOCOL_RLC_AM_CTXT_FMT" CONFIG_REQ RLC NOT FOUND\n",
-          PROTOCOL_RLC_AM_CTXT_ARGS(ctxt_pP,l_rlc_p));
-  }
-}
 
 
 //defined in rlc_tm_init.c (nothing to be changed)
 //-----------------------------------------------------------------------------
-void NB_config_req_rlc_tm (
+void config_req_rlc_tm_NB_IoT (
   const protocol_ctxt_t* const  ctxt_pP,
   const srb_flag_t  srb_flagP,
   const rlc_tm_info_t * const config_tmP,
@@ -2564,7 +2364,7 @@ void NB_config_req_rlc_tm (
 }
 
 //defined in rlc_rrc.c
-rlc_op_status_t NB_rrc_rlc_remove_ue (
+rlc_op_status_t rrc_rlc_remove_ue_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP)
 {
   //-----------------------------------------------------------------------------
@@ -2573,25 +2373,26 @@ rlc_op_status_t NB_rrc_rlc_remove_ue (
   //XXX MP: rb_id = 2 should be not used (SRB2 not defined for NB-IoT)
   for (rb_id = 1; rb_id <= 3; rb_id++) {
     if(rb_id != 2){
-    	NB_rrc_rlc_remove_rlc(ctxt_pP,
-    						  SRB_FLAG_YES,
-						      rb_id);
+    	rrc_rlc_remove_rlc_NB_IoT(ctxt_pP,
+    						                SRB_FLAG_YES,
+						                    rb_id);
     }
     else
     {
-    	LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] NB_rrc_rlc_remove_ue --> removing an UE with rb_id = 2 in NB_IoT!\n",
+    	LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_remove_ue_NB_IoT --> removing an UE with rb_id = 2 in NB_IoT!\n",
     		              PROTOCOL_CTXT_ARGS(ctxt_pP), "SRB", rb_id);
     }
   }
 
-  for (rb_id = 1; rb_id <= maxDRB_NB_r13; rb_id++) { //FIXME: maxDRB_NB_r13 +3 ??
+  //XXX possible BUG here???
+  for (rb_id = 1; rb_id <= maxDRB_NB_r13 + 3; rb_id++) {
 	  if(rb_id != 2){
-		  NB_rrc_rlc_remove_rlc(ctxt_pP,
-                       SRB_FLAG_NO,
-                       rb_id);
+		  rrc_rlc_remove_rlc_NB_IoT(ctxt_pP,
+                                SRB_FLAG_NO,
+                                rb_id);
 	  }
 	  else
-	      LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] NB_rrc_rlc_remove_ue --> removing an UE with rb_id = 2 in NB_IoT!\n",
+	      LOG_E(RLC, PROTOCOL_CTXT_FMT"[%s %u] rrc_rlc_remove_ue_NB_IoT --> removing an UE with rb_id = 2 in NB_IoT!\n",
 	      		              PROTOCOL_CTXT_ARGS(ctxt_pP), "DRB", rb_id);
   }
 
@@ -2599,16 +2400,22 @@ rlc_op_status_t NB_rrc_rlc_remove_ue (
 }
 
 //defined in rlc_rrc.c --> NO MORE USED PROBABLY
-//void NB_rrc_rlc_register_rrc ( //what do?
-//		rrc_data_ind_cb_t rrc_data_indP,
-//		rrc_data_conf_cb_t rrc_data_confP
-//		);
+//------------------------------------------------------------------------------
+void rrc_rlc_register_rrc_NB_IoT (rrc_data_ind_cb_NB_IoT_t rrc_data_indP_NB_IoT, rrc_data_conf_cb_t rrc_data_confP)
+{
+	//his function is called by RRC to register its DATA-INDICATE and DATA-CONFIRM handlers to RLC laye
+	//map the function pointer to the function in input
+	//rlc_rrc_data_ind  and rlc_rrc_data_conf are protected internal functions in the rlc.c file
+	 rlc_rrc_data_ind_NB_IoT  = rrc_data_indP_NB_IoT;
+	//rlc_rrc_data_conf = rrc_data_confP; not used since only asn.1 function are considered
+}
 
 /*--------------------------------------------RLC-PDCP--------------------------------------------------*/
-
+//XXX to be integrated in the data flow for NB-IoT
+//called by rlc_am_send_sdu and rlc_tm_send_sdu
 //defined in rlc.c
 //--------------------------------------------
-void NB_rlc_data_ind     (
+void rlc_data_ind_NB_IoT  (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t  srb_flagP,
   const srb1bis_flag_t srb1bis_flag,
@@ -2635,7 +2442,7 @@ void NB_rlc_data_ind     (
 #endif
 
 
-  NB_pdcp_data_ind (
+  pdcp_data_ind_NB_IoT (
     ctxt_pP,
     srb_flagP,
 	srb1bis_flag,
@@ -2646,13 +2453,13 @@ void NB_rlc_data_ind     (
 
 //defined in rlc.c
 //-----------------------------------------------------------------------------
-rlc_op_status_t NB_rlc_data_req     (const protocol_ctxt_t* const ctxt_pP,
-                                  const srb_flag_t   srb_flagP,
-                                  const rb_id_t      rb_idP,
-                                  const mui_t        muiP,
-                                  confirm_t    confirmP,
-                                  sdu_size_t   sdu_sizeP,
-                                  mem_block_t *sdu_pP)
+rlc_op_status_t rlc_data_req_NB_IoT (const protocol_ctxt_t* const ctxt_pP,
+                                     const srb_flag_t   srb_flagP,
+                                     const rb_id_t      rb_idP,
+                                     const mui_t        muiP,
+                                     confirm_t    confirmP,
+                                     sdu_size_t   sdu_sizeP,
+                                     mem_block_t *sdu_pP)
 {
   //-----------------------------------------------------------------------------
   mem_block_t           *new_sdu_p    = NULL;
@@ -2663,7 +2470,7 @@ rlc_op_status_t NB_rlc_data_req     (const protocol_ctxt_t* const ctxt_pP,
 
 #if defined(Rel10) || defined(Rel14)
 
-  logical_chan_id_t      log_ch_id  = 0;
+ //logical_chan_id_t      log_ch_id  = 0;
 #endif
 #ifdef DEBUG_RLC_DATA_REQ
   LOG_D(RLC,PROTOCOL_CTXT_FMT"rlc_data_req:  rb_id %u (MAX %d), muip %d, confirmP %d, sdu_sizeP %d, sdu_pP %p\n",
@@ -2863,10 +2670,9 @@ rlc_op_status_t NB_rlc_data_req     (const protocol_ctxt_t* const ctxt_pP,
 
 
 //defined in pdcp.c
-//FIXME: should go transparent through the PDCP
+//if SRB1bis go transparently through PDCP
 //--------------------------------------------
-boolean_t
-NB_pdcp_data_ind(
+boolean_t pdcp_data_ind_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t   srb_flagP,
   const srb1bis_flag_t srb1bis_flag,
@@ -3090,7 +2896,7 @@ NB_pdcp_data_ind(
         PROTOCOL_PDCP_CTXT_ARGS(ctxt_pP, pdcp_p),
         sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len);
 
-      NB_rrc_data_ind(ctxt_pP,
+      rrc_data_ind_NB_IoT(ctxt_pP,
     		  	  	  rb_id,
 					  sdu_buffer_sizeP - pdcp_header_len - pdcp_tailer_len,
 					  (uint8_t*)&sdu_buffer_pP->data[pdcp_header_len],
@@ -3187,6 +2993,7 @@ NB_pdcp_data_ind(
 
 #else
 
+  /*
   if (otg_enabled==1) {
     LOG_D(OTG,"Discarding received packed\n");
     free_mem_block(sdu_buffer_pP, __func__);
@@ -3199,7 +3006,7 @@ NB_pdcp_data_ind(
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDCP_DATA_IND,VCD_FUNCTION_OUT);
     return TRUE;
-  }
+  }*/
 
 #endif
 
@@ -3345,7 +3152,7 @@ NB_pdcp_data_ind(
 
 //-----------------------------------------------------------------------------
 //defined in rlc_mac.c
-void NB_mac_rlc_data_ind     (
+void mac_rlc_data_ind_NB_IoT  (
   const module_id_t         module_idP,
   const rnti_t              rntiP,
   const module_id_t         eNB_index,
@@ -3355,7 +3162,7 @@ void NB_mac_rlc_data_ind     (
   const logical_chan_id_t   channel_idP,
   char                     *buffer_pP,
   const tb_size_t           tb_sizeP,
-  num_tb_t                  num_tbP,
+  num_tb_t                  num_tbP, //number of transport block
   crc_t                    *crcs_pP)
 {
   //-----------------------------------------------------------------------------
@@ -3363,22 +3170,25 @@ void NB_mac_rlc_data_ind     (
   rlc_union_t           *rlc_union_p     = NULL;
   hash_key_t             key             = HASHTABLE_NOT_A_KEY_VALUE;
   hashtable_rc_t         h_rc;
-  //XXX MP: modify the check on LCID
   srb_flag_t             srb_flag        = (channel_idP <= 3) ? SRB_FLAG_YES : SRB_FLAG_NO;
-  srb1bis_flag_t         srb1bis_flag    = (channel_idP == 3) ? SRB1BIS_FLAG_YES : SRB1BIS_FLAG_NO; //may not needed?
+  //srb1bis_flag_t         srb1bis_flag    = (channel_idP == 3) ? SRB1BIS_FLAG_YES : SRB1BIS_FLAG_NO; //may not needed?
   protocol_ctxt_t     ctxt;
 
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, enb_flagP, rntiP, frameP, 0, eNB_index);
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_IND,VCD_FUNCTION_IN);
 
+  if(channel_idP == 2)
+	  LOG_E(RLC, "mac_rlc_data_ind_NB_IoT over srb_id invalid (%d)\n", channel_idP);
+
+
 #ifdef DEBUG_MAC_INTERFACE
 
   if (num_tbP) {
     LOG_D(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_IND on channel %d (%d), rb max %d, Num_tb %d\n",
           PROTOCOL_CTXT_ARGS(&ctxt),
           channel_idP,
-          RLC_MAX_LC, //XXX ???
+          RLC_MAX_LC,
 		  NB_RB_MAX_NB_IOT,
           num_tbP);
   }
@@ -3407,7 +3217,7 @@ void NB_mac_rlc_data_ind     (
 
   h_rc = hashtable_get(rlc_coll_p, key, (void**)&rlc_union_p);
 
-  //XXX MP: also for SRB1bis an RLC-AM mode should be configured
+  //MP: also for SRB1bis an RLC-AM mode should be configured
   if (h_rc == HASH_TABLE_OK) {
     rlc_mode = rlc_union_p->mode;
   } else {
@@ -3423,17 +3233,17 @@ void NB_mac_rlc_data_ind     (
     break;
 
   case RLC_MODE_AM:
-    NB_rlc_am_mac_data_indication(&ctxt, &rlc_union_p->rlc.am, data_ind);
+    rlc_am_mac_data_indication_NB_IoT(&ctxt, &rlc_union_p->rlc.am, data_ind);
     break;
 
-   //XXX MP: no UM mode for NB_IoT
+   //MP: no UM mode for NB_IoT
 
   case RLC_MODE_TM:
     rlc_tm_mac_data_indication(&ctxt, &rlc_union_p->rlc.tm, data_ind);
     break;
 
   default:
-	  LOG_E(RLC,PROTOCOL_PDCP_CTXT_FMT"mac_rlc_data_ind -> RLC mode unknown");
+	  LOG_E(RLC,"mac_rlc_data_ind -> RLC mode unknown");
 	break;
   }
 
@@ -3443,8 +3253,7 @@ void NB_mac_rlc_data_ind     (
 
 //-----------------------------------------------------------------------------
 //defined in rlc_am.c
-void
-NB_rlc_am_mac_data_indication (
+void rlc_am_mac_data_indication_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP,
   void * const                 rlc_pP,
   struct mac_data_ind          data_indP
@@ -3671,7 +3480,7 @@ NB_rlc_am_mac_data_indication (
 //-----------------------------------------------------------------------------
 //defined in rlc_mac.c
 //called by the schedule_ue_spec for getting SDU to be transmitted from SRB1/SRB1bis and DRBs
-tbs_size_t NB_mac_rlc_data_req_eNB(
+tbs_size_t mac_rlc_data_req_eNB_NB_IoT(
   const module_id_t       module_idP,
   const rnti_t            rntiP,
   const eNB_index_t       eNB_index,
@@ -3687,13 +3496,18 @@ tbs_size_t NB_mac_rlc_data_req_eNB(
   hash_key_t             key             = HASHTABLE_NOT_A_KEY_VALUE;
   hashtable_rc_t         h_rc;
   srb_flag_t             srb_flag        = (channel_idP <= 3) ? SRB_FLAG_YES : SRB_FLAG_NO;
-  srb1bis_flag_t			srb1bis_flag = (channel_idP == 3) ? SRB1BIS_FLAG_YES : SRB1BIS_FLAG_NO;
+  //srb1bis_flag_t			srb1bis_flag = (channel_idP == 3) ? SRB1BIS_FLAG_YES : SRB1BIS_FLAG_NO;
   tbs_size_t             ret_tb_size         = 0;
   protocol_ctxt_t     ctxt;
 
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, rntiP, frameP, 0,eNB_index);
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_MAC_RLC_DATA_REQ,VCD_FUNCTION_IN);
+
+  if(channel_idP == 2)
+  	  LOG_E(RLC, "mac_rlc_data_req_eNB_NB_IoT over srb_id invalid (%d)\n", channel_idP);
+
+
 #ifdef DEBUG_MAC_INTERFACE
   LOG_D(RLC, PROTOCOL_CTXT_FMT" MAC_RLC_DATA_REQ channel %d (%d) MAX RB %d, Num_tb %d\n",
         PROTOCOL_CTXT_ARGS((&ctxt)),
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg_NB_IoT.c b/openair2/RRC/LITE/MESSAGES/asn1_msg_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..b61e8da8dc69734d7e547b51532f4bfc177ac24e
--- /dev/null
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg_NB_IoT.c
@@ -0,0 +1,1405 @@
+/* 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.0  (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 asn1_msg.c
+* \brief primitives to build the asn1 messages
+* \author Raymond Knopp, Navid Nikaein and Michele Paffetti
+* \date 2011, 2017
+* \version 1.0
+* \company Eurecom
+* \email: raymond.knopp@eurecom.fr, navid.nikaein@eurecom.fr, michele.paffetti@studio.unibo.it
+*/
+
+#ifdef USER_MODE
+#include <stdio.h>
+#include <sys/types.h>
+#include <stdlib.h> /* for atoi(3) */
+#include <unistd.h> /* for getopt(3) */
+#include <string.h> /* for strerror(3) */
+#include <sysexits.h> /* for EX_* exit codes */
+#include <errno.h>  /* for errno */
+#else
+#include <linux/module.h>  /* Needed by all modules */
+#endif
+#ifdef USER_MODE
+//#include "RRC/LITE/defs.h"
+//#include "COMMON/mac_rrc_primitives.h"
+#include "UTIL/LOG/log.h"
+#endif
+#include <asn_application.h>
+#include <asn_internal.h> /* for _ASN_DEFAULT_STACK_MAX */
+#include <per_encoder.h>
+
+#include "assertions.h"
+
+
+//#include for NB-IoT-------------------
+#include "RRCConnectionRequest-NB.h"
+#include "BCCH-DL-SCH-Message-NB.h"
+#include "UL-CCCH-Message-NB.h"
+#include "UL-DCCH-Message-NB.h"
+#include "DL-CCCH-Message-NB.h"
+#include "DL-DCCH-Message-NB.h"
+#include "EstablishmentCause-NB-r13.h"
+#include "RRCConnectionSetup-NB.h"
+#include "SRB-ToAddModList-NB-r13.h"
+#include "DRB-ToAddModList-NB-r13.h"
+#include "RRC/LITE/defs_NB_IoT.h"
+#include "RRCConnectionSetupComplete-NB.h"
+#include "RRCConnectionReconfigurationComplete-NB.h"
+#include "RRCConnectionReconfiguration-NB.h"
+#include "MasterInformationBlock-NB.h"
+#include "SystemInformation-NB.h"
+#include "SystemInformationBlockType1.h"
+#include "SIB-Type-NB-r13.h"
+#include "RRCConnectionResume-NB.h"
+#include "RRCConnectionReestablishment-NB.h"
+#include "PHY/defs_NB_IoT.h"
+//----------------------------------------
+
+//#include "PHY/defs.h"
+#include "enb_config.h"
+
+#if defined(ENABLE_ITTI)
+# include "intertask_interface.h"
+#endif
+
+#ifndef USER_MODE
+#define msg printk
+#ifndef errno
+int errno;
+#endif
+#else
+# if !defined (msg)
+#   define msg printf
+# endif
+#endif
+
+
+/*do_MIB_NB_NB_IoT*/
+uint8_t do_MIB_NB_IoT(
+		rrc_eNB_carrier_data_NB_IoT_t *carrier,
+		uint16_t N_RB_DL,//may not needed--> for NB_IoT only 1 PRB is used
+		uint32_t frame)
+{
+  asn_enc_rval_t enc_rval;
+  BCCH_BCH_Message_NB_t *mib_NB_IoT = &(carrier->mib_NB_IoT);
+
+  /*
+   * systemFrameNumber-MSB: (TS 36.331 pag 576)
+   * define the 4 MSB of the SFN (10 bits). The last significant 6 bits will be acquired implicitly by decoding the NPBCH
+   * NOTE: 6 LSB will be used for counting the 64 radio frames in the TTI period (640 ms) that is exactly the MIB period
+   *
+   * hyperSFN-LSB:
+   * indicates the 2 least significant bits of the HSFN. The remaining 8 bits are present in SIB1-NB
+   * NOTE: with the 2 bits we count the 4 HSFN (is 1 SIB1-Nb modification period) while the other 6 count the number of modification periods
+   *
+   *
+   * NOTE: in OAI never modify the SIB messages!!??
+   */
+
+  //XXX check if correct the bit assignment
+  uint8_t sfn_MSB = (uint8_t)((frame>>6) & 0x0f); // all the 4 bits are set to 1
+  uint8_t hsfn_LSB = (uint8_t)(frame & 0x3); //2 bits set to 1 (0x3 = 0011)
+  uint16_t spare=0; //11 bits --> use uint16
+
+  mib_NB_IoT->message.systemFrameNumber_MSB_r13.buf = &sfn_MSB;
+  mib_NB_IoT->message.systemFrameNumber_MSB_r13.size = 1; //if expressed in byte
+  mib_NB_IoT->message.systemFrameNumber_MSB_r13.bits_unused = 4; //is byte based (so how many bits you don't use of the 8 bits of a bite
+
+  mib_NB_IoT->message.hyperSFN_LSB_r13.buf= &hsfn_LSB;
+  mib_NB_IoT->message.hyperSFN_LSB_r13.size= 1;
+  mib_NB_IoT->message.hyperSFN_LSB_r13.bits_unused = 6;
+
+  //XXX to be set??
+  mib_NB_IoT->message.spare.buf = (uint16_t *)&spare;
+  mib_NB_IoT->message.spare.size = 2;
+  mib_NB_IoT->message.spare.bits_unused = 5;
+
+  //decide how to set it
+  mib_NB_IoT->message.schedulingInfoSIB1_r13 =11; //see TS 36.213-->tables 16.4.1.3-3 ecc...
+  mib_NB_IoT->message.systemInfoValueTag_r13= 0;
+  mib_NB_IoT->message.ab_Enabled_r13 = 0;
+
+  //to be decided
+  mib_NB_IoT->message.operationModeInfo_r13.present = MasterInformationBlock_NB__operationModeInfo_r13_PR_inband_SamePCI_r13;
+  mib_NB_IoT->message.operationModeInfo_r13.choice.inband_SamePCI_r13.eutra_CRS_SequenceInfo_r13 = 0;
+
+  printf("[MIB] something to write HERE ,sfn_MSB %x, hsfn_LSB %x\n",
+         (uint32_t)sfn_MSB,
+		 (uint32_t)hsfn_LSB);
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_BCH_Message_NB,
+                                   (void*)mib_NB_IoT,
+                                   carrier->MIB_NB_IoT,
+                                   100);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  if (enc_rval.encoded==-1) {
+    return(-1);
+  }
+
+  return((enc_rval.encoded+7)/8);
+
+}
+
+/*do_SIB1_NB*/
+uint8_t do_SIB1_NB_IoT(uint8_t Mod_id, int CC_id,
+				rrc_eNB_carrier_data_NB_IoT_t *carrier,
+                RrcConfigurationReq *configuration,
+				uint32_t frame
+               )
+{
+  BCCH_DL_SCH_Message_NB_t *bcch_message= &(carrier->siblock1_NB_IoT);
+  SystemInformationBlockType1_NB_t *sib1_NB_IoT;
+
+  asn_enc_rval_t enc_rval;
+
+  PLMN_IdentityInfo_NB_r13_t PLMN_identity_info_NB_IoT;
+  MCC_MNC_Digit_t dummy_mcc[3],dummy_mnc[3];
+  SchedulingInfo_NB_r13_t schedulingInfo_NB_IoT;
+  SIB_Type_NB_r13_t sib_type_NB_IoT;
+
+
+  long* attachWithoutPDN_Connectivity = NULL;
+  attachWithoutPDN_Connectivity = CALLOC(1,sizeof(long));
+  long *nrs_CRS_PowerOffset=NULL;
+  nrs_CRS_PowerOffset = CALLOC(1, sizeof(long));
+  long *eutraControlRegionSize=NULL; //this parameter should be set only if we are considering in-band operating mode (samePCI or differentPCI)
+   eutraControlRegionSize = CALLOC(1,sizeof(long));
+  long systemInfoValueTagSI = 0;
+
+  memset(bcch_message,0,sizeof(BCCH_DL_SCH_Message_NB_t));
+  bcch_message->message.present = BCCH_DL_SCH_MessageType_NB_PR_c1;
+  bcch_message->message.choice.c1.present = BCCH_DL_SCH_MessageType_NB__c1_PR_systemInformationBlockType1_r13;
+
+  //allocation
+  carrier->sib1_NB_IoT = &bcch_message->message.choice.c1.choice.systemInformationBlockType1_r13;
+  sib1_NB_IoT = carrier->sib1_NB_IoT;
+
+
+  /*TS 36.331 v14.2.0 pag 589
+   * hyperSFN-MSB
+   * Indicates the 8 most significant bits of the hyper-SFN. Together with the hyper-LSB in MIB-NB the complete HSFN is build up
+   */
+  //FIXME see if correct
+  uint8_t hyperSFN_MSB = (uint8_t) ((frame>>2)& 0xff);
+
+  //XXX to be checked
+  sib1_NB_IoT->hyperSFN_MSB_r13.buf = &hyperSFN_MSB;
+  sib1_NB_IoT->hyperSFN_MSB_r13.size = 1;
+  sib1_NB_IoT->hyperSFN_MSB_r13.bits_unused = 0;
+
+  memset(&PLMN_identity_info_NB_IoT,0,sizeof(PLMN_IdentityInfo_NB_r13_t));
+  memset(&schedulingInfo_NB_IoT,0,sizeof(SchedulingInfo_NB_r13_t));
+  memset(&sib_type_NB_IoT,0,sizeof(SIB_Type_NB_r13_t));
+
+
+  PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc = CALLOC(1,sizeof(*PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc));
+  memset(PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc,0,sizeof(*PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc));
+
+  asn_set_empty(&PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc->list);//.size=0;
+
+  //left as it is???
+#if defined(ENABLE_ITTI)
+  dummy_mcc[0] = (configuration->mcc / 100) % 10;
+  dummy_mcc[1] = (configuration->mcc / 10) % 10;
+  dummy_mcc[2] = (configuration->mcc / 1) % 10;
+#else
+  dummy_mcc[0] = 0;
+  dummy_mcc[1] = 0;
+  dummy_mcc[2] = 1;
+#endif
+  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc->list,&dummy_mcc[0]);
+  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc->list,&dummy_mcc[1]);
+  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB_IoT.plmn_Identity_r13.mcc->list,&dummy_mcc[2]);
+
+  PLMN_identity_info_NB_IoT.plmn_Identity_r13.mnc.list.size=0;
+  PLMN_identity_info_NB_IoT.plmn_Identity_r13.mnc.list.count=0;
+
+
+#if defined(ENABLE_ITTI)
+
+  if (configuration->mnc >= 100) {
+    dummy_mnc[0] = (configuration->mnc / 100) % 10;
+    dummy_mnc[1] = (configuration->mnc / 10) % 10;
+    dummy_mnc[2] = (configuration->mnc / 1) % 10;
+  } else {
+    if (configuration->mnc_digit_length == 2) {
+      dummy_mnc[0] = (configuration->mnc / 10) % 10;
+      dummy_mnc[1] = (configuration->mnc / 1) % 10;
+      dummy_mnc[2] = 0xf;
+    } else {
+      dummy_mnc[0] = (configuration->mnc / 100) % 100;
+      dummy_mnc[1] = (configuration->mnc / 10) % 10;
+      dummy_mnc[2] = (configuration->mnc / 1) % 10;
+    }
+  }
+
+#else
+  dummy_mnc[0] = 0;
+  dummy_mnc[1] = 1;
+  dummy_mnc[2] = 0xf;
+#endif
+  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB_IoT.plmn_Identity_r13.mnc.list,&dummy_mnc[0]);
+  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB_IoT.plmn_Identity_r13.mnc.list,&dummy_mnc[1]);
+
+  if (dummy_mnc[2] != 0xf) {
+    ASN_SEQUENCE_ADD(&PLMN_identity_info_NB_IoT.plmn_Identity_r13.mnc.list,&dummy_mnc[2]);
+  }
+
+  //still set to "notReserved" as in the previous case
+  PLMN_identity_info_NB_IoT.cellReservedForOperatorUse_r13=PLMN_IdentityInfo_NB_r13__cellReservedForOperatorUse_r13_notReserved;
+
+  *attachWithoutPDN_Connectivity = 0;
+  PLMN_identity_info_NB_IoT.attachWithoutPDN_Connectivity_r13 = attachWithoutPDN_Connectivity;
+
+  ASN_SEQUENCE_ADD(&sib1_NB_IoT->cellAccessRelatedInfo_r13.plmn_IdentityList_r13.list,&PLMN_identity_info_NB_IoT);
+
+  // 16 bits = 2 byte
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf = MALLOC(2); //MALLOC works in byte
+
+  //lefts as it is?
+#if defined(ENABLE_ITTI)
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[0] = (configuration->tac >> 8) & 0xff;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[1] = (configuration->tac >> 0) & 0xff;
+#else
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[0] = 0x00;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[1] = 0x01;
+#endif
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.trackingAreaCode_r13.size=2;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.trackingAreaCode_r13.bits_unused=0;
+
+  // 28 bits --> i have to use 32 bits = 4 byte
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf = MALLOC(8); // why allocate 8 byte?
+#if defined(ENABLE_ITTI)
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[0] = (configuration->cell_identity >> 20) & 0xff;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[1] = (configuration->cell_identity >> 12) & 0xff;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[2] = (configuration->cell_identity >>  4) & 0xff;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[3] = (configuration->cell_identity <<  4) & 0xf0;
+#else
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[0] = 0x00;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[1] = 0x00;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[2] = 0x00;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[3] = 0x10;
+#endif
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.size=4;
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellIdentity_r13.bits_unused=4;
+
+  //Still set to "notBarred" as in the previous case
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.cellBarred_r13=SystemInformationBlockType1_NB__cellAccessRelatedInfo_r13__cellBarred_r13_notBarred;
+
+  //Still Set to "notAllowed" like in the previous case
+  sib1_NB_IoT->cellAccessRelatedInfo_r13.intraFreqReselection_r13=SystemInformationBlockType1_NB__cellAccessRelatedInfo_r13__intraFreqReselection_r13_notAllowed;
+
+
+  sib1_NB_IoT->cellSelectionInfo_r13.q_RxLevMin_r13=-65; //which value?? TS 36.331 V14.2.1 pag. 589
+  sib1_NB_IoT->cellSelectionInfo_r13.q_QualMin_r13 = 0; //FIXME new parameter for SIB1-NB, not present in SIB1 (for cell reselection but if not used the UE should apply the default value)
+
+  sib1_NB_IoT->p_Max_r13 = CALLOC(1, sizeof(P_Max_t));
+  *(sib1_NB_IoT->p_Max_r13) = 23;
+
+  //FIXME
+  sib1_NB_IoT->freqBandIndicator_r13 =
+#if defined(ENABLE_ITTI)
+    configuration->eutra_band[CC_id];
+#else
+    5; //if not configured we use band 5 (UL: 824 MHz - 849MHz / DL: 869 MHz - 894 MHz  FDD mode)
+#endif
+
+    //OPTIONAL new parameters, to be used?
+      /*
+       * freqBandInfo_r13
+       * multiBandInfoList_r13
+       * nrs_CRS_PowerOffset_r13
+       * sib1_NB_IoT->downlinkBitmap_r13.choice.subframePattern10_r13 =(is a BIT_STRING)
+       */
+
+
+   sib1_NB_IoT->downlinkBitmap_r13 = CALLOC(1, sizeof(struct DL_Bitmap_NB_r13));
+   (sib1_NB_IoT->downlinkBitmap_r13)->present= DL_Bitmap_NB_r13_PR_NOTHING;
+
+   *eutraControlRegionSize = 0;
+   sib1_NB_IoT->eutraControlRegionSize_r13 = eutraControlRegionSize;
+
+
+   *nrs_CRS_PowerOffset= 0;
+   sib1_NB_IoT->nrs_CRS_PowerOffset_r13 = nrs_CRS_PowerOffset;
+
+
+  //FIXME which value to set?
+  schedulingInfo_NB_IoT.si_Periodicity_r13=SchedulingInfo_NB_r13__si_Periodicity_r13_rf64;
+  schedulingInfo_NB_IoT.si_RepetitionPattern_r13=SchedulingInfo_NB_r13__si_RepetitionPattern_r13_every2ndRF; //This Indicates the starting radio frames within the SI window used for SI message transmission.
+  schedulingInfo_NB_IoT.si_TB_r13= SchedulingInfo_NB_r13__si_TB_r13_b208;//208 bits
+  //from ASN1 tools we have seen that sib2 + sib3 we are always below 200 bits so we use this si_TB size.
+  //from the specs the SI-message will be transmitted in 8 subframe = 8ms (pag 590 TS 36.331)
+
+  // This is for SIB2/3
+  /*SIB3 --> There is no mapping information of SIB2 since it is always present
+    *  in the first SystemInformation message
+    * listed in the schedulingInfoList list.
+    * */
+  sib_type_NB_IoT=SIB_Type_NB_r13_sibType3_NB_r13;
+
+  ASN_SEQUENCE_ADD(&schedulingInfo_NB_IoT.sib_MappingInfo_r13.list,&sib_type_NB_IoT);
+  ASN_SEQUENCE_ADD(&sib1_NB_IoT->schedulingInfoList_r13.list,&schedulingInfo_NB_IoT);
+
+#if defined(ENABLE_ITTI)
+
+  if (configuration->frame_type[CC_id] == TDD)
+#endif
+  {
+	//FIXME in NB-IoT mandatory to be FDD --> so must give an error
+	  LOG_E(RRC,"[eNB %d] Frame Type is TDD --> not supported by NB-IoT, exiting\n", Mod_id); //correct?
+	  exit(-1);
+  }
+
+  //FIXME which value chose for the following parameter
+  sib1_NB_IoT->si_WindowLength_r13=SystemInformationBlockType1_NB__si_WindowLength_r13_ms160;
+  sib1_NB_IoT->si_RadioFrameOffset_r13= 0;
+
+  /*In Nb-IoT change/update of specific SI message can additionally be indicated by a SI message specific value tag
+   * systemInfoValueTagSI (there is no SystemInfoValueTag in SIB1-NB but only in MIB-NB)
+   *contained in systemInfoValueTagList_r13
+   **/
+  //FIXME correct?
+  sib1_NB_IoT->systemInfoValueTagList_r13 = CALLOC(1, sizeof(struct SystemInfoValueTagList_NB_r13));
+  asn_set_empty(&sib1_NB_IoT->systemInfoValueTagList_r13->list);
+  ASN_SEQUENCE_ADD(&sib1_NB_IoT->systemInfoValueTagList_r13->list,&systemInfoValueTagSI);
+
+
+#ifdef XER_PRINT //generate xml files
+  xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
+#endif
+
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_DL_SCH_Message_NB,
+                                   (void*)bcch_message,
+                                   carrier->SIB1_NB_IoT,
+                                   100);
+
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+
+#ifdef USER_MODE
+  LOG_D(RRC,"[eNB] SystemInformationBlockType1-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+#endif
+
+  if (enc_rval.encoded==-1) {
+    return(-1);
+  }
+
+  return((enc_rval.encoded+7)/8);
+}
+
+/*SIB23_NB_IoT*/
+//to be clarified is it is possible to carry SIB2 and SIB3  in the same SI message for NB-IoT?
+uint8_t do_SIB23_NB_IoT(uint8_t Mod_id,
+                        int CC_id,
+                        rrc_eNB_carrier_data_NB_IoT_t *carrier,//MP: this is already a carrier[CC_id]
+                        RrcConfigurationReq *configuration ) //openair2/COMMON/rrc_messages_types.h
+{
+  struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member *sib2_NB_part;
+  struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member *sib3_NB_part;
+
+  BCCH_DL_SCH_Message_NB_t *bcch_message = &(carrier->systemInformation_NB_IoT); //is the systeminformation-->BCCH_DL_SCH_Message_NB
+  SystemInformationBlockType2_NB_r13_t *sib2_NB_IoT;
+  SystemInformationBlockType3_NB_r13_t *sib3_NB_IoT;
+
+  asn_enc_rval_t enc_rval;
+  RACH_Info_NB_r13_t rach_Info_NB_IoT;
+  NPRACH_Parameters_NB_r13_t nprach_parameters;
+
+  //optional
+  long *connEstFailOffset = NULL;
+  connEstFailOffset = CALLOC(1, sizeof(long));
+
+  RSRP_ThresholdsNPRACH_InfoList_NB_r13_t *rsrp_ThresholdsPrachInfoList;
+  RSRP_Range_t rsrp_range;
+  ACK_NACK_NumRepetitions_NB_r13_t ack_nack_repetition;
+  struct NPUSCH_ConfigCommon_NB_r13__dmrs_Config_r13 *dmrs_config;
+  struct DL_GapConfig_NB_r13	*dl_Gap;
+
+  long *srs_SubframeConfig;
+  srs_SubframeConfig= CALLOC(1, sizeof(long));
+
+
+  if (bcch_message) {
+    memset(bcch_message,0,sizeof(BCCH_DL_SCH_Message_NB_t));
+  } else {
+    LOG_E(RRC,"[eNB %d] BCCH_MESSAGE_NB is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  //before schould be allocated memory somewhere?
+  if (!carrier->sib2_NB_IoT) {
+    LOG_E(RRC,"[eNB %d] sib2_NB_IoT is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+  if (!carrier->sib3_NB_IoT) {
+    LOG_E(RRC,"[eNB %d] sib3_NB_IoT is null, exiting\n", Mod_id);
+    exit(-1);
+  }
+
+
+  LOG_I(RRC,"[eNB %d] Configuration SIB2/3\n", Mod_id);
+
+  sib2_NB_part = CALLOC(1,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
+  sib3_NB_part = CALLOC(1,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
+  memset(sib2_NB_part,0,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
+  memset(sib3_NB_part,0,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
+
+  sib2_NB_part->present = SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member_PR_sib2_r13;
+  sib3_NB_part->present = SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member_PR_sib3_r13;
+
+  //may bug if not correct allocation of memory
+  carrier->sib2_NB_IoT = &sib2_NB_part->choice.sib2_r13;
+  carrier->sib3_NB_IoT = &sib3_NB_part->choice.sib3_r13;
+  sib2_NB_IoT = carrier->sib2_NB_IoT;
+  sib3_NB_IoT = carrier->sib3_NB_IoT;
+
+
+/// SIB2-NB-----------------------------------------
+
+  //Barring is manage by ab-Enabled in MIB-NB (but is not a struct as ac-BarringInfo in LTE legacy)
+
+  //RACH Config. Common--------------------------------------------------------------
+  sib2_NB_IoT->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.preambleTransMax_CE_r13 =
+   		  configuration->rach_preambleTransMax_CE_NB[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.powerRampingParameters_r13.powerRampingStep =
+	configuration->rach_powerRampingStep_NB[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.powerRampingParameters_r13.preambleInitialReceivedTargetPower =
+    configuration->rach_preambleInitialReceivedTargetPower_NB[CC_id];
+
+  rach_Info_NB_IoT.ra_ResponseWindowSize_r13 = configuration->rach_raResponseWindowSize_NB[CC_id];
+  rach_Info_NB_IoT.mac_ContentionResolutionTimer_r13 = configuration-> rach_macContentionResolutionTimer_NB[CC_id];
+  //rach_infoList max size = maxNPRACH-Resources-NB-r13 = 3
+  ASN_SEQUENCE_ADD(&sib2_NB_IoT->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.rach_InfoList_r13.list,&rach_Info_NB_IoT);
+
+  //TS 36.331 pag 614 --> if not present the value to infinity sould be used
+  *connEstFailOffset = 0;
+   sib2_NB_IoT->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.connEstFailOffset_r13 = connEstFailOffset; /*OPTIONAL*/
+
+
+  // BCCH-Config-NB-IoT----------------------------------------------------------------
+  sib2_NB_IoT->radioResourceConfigCommon_r13.bcch_Config_r13.modificationPeriodCoeff_r13
+    = configuration->bcch_modificationPeriodCoeff_NB[CC_id];
+
+  // PCCH-Config-NB-IoT-----------------------------------------------------------------
+  sib2_NB_IoT->radioResourceConfigCommon_r13.pcch_Config_r13.defaultPagingCycle_r13
+    = configuration->pcch_defaultPagingCycle_NB[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.pcch_Config_r13.nB_r13 = configuration->pcch_nB_NB[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.pcch_Config_r13.npdcch_NumRepetitionPaging_r13 = configuration-> pcch_npdcch_NumRepetitionPaging_NB[CC_id];
+
+  //NPRACH-Config-NB-IoT-----------------------------------------------------------------
+  sib2_NB_IoT->radioResourceConfigCommon_r13.nprach_Config_r13.nprach_CP_Length_r13 = configuration->nprach_CP_Length[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13 = NULL; /*OPTIONAL*/
+//   =CALLOC(1, sizeof(struct RSRP_ThresholdsNPRACH_InfoList_NB_r13)); //fatto uguale dopo
+//   rsrp_ThresholdsPrachInfoList = sib2_NB_IoT->radioResourceConfigCommon_r13.nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13;
+//   rsrp_range = configuration->nprach_rsrp_range_NB;
+//   ASN_SEQUENCE_ADD(&rsrp_ThresholdsPrachInfoList->list,rsrp_range);
+
+  nprach_parameters.nprach_Periodicity_r13 = configuration->nprach_Periodicity[CC_id];
+  nprach_parameters.nprach_StartTime_r13 = configuration->nprach_StartTime[CC_id];
+  nprach_parameters.nprach_SubcarrierOffset_r13 = configuration->nprach_SubcarrierOffset[CC_id];
+  nprach_parameters.nprach_NumSubcarriers_r13= configuration->nprach_NumSubcarriers[CC_id];
+  nprach_parameters.nprach_SubcarrierMSG3_RangeStart_r13= configuration->nprach_SubcarrierMSG3_RangeStart[CC_id];
+  nprach_parameters.maxNumPreambleAttemptCE_r13= configuration->maxNumPreambleAttemptCE_NB[CC_id];
+  nprach_parameters.numRepetitionsPerPreambleAttempt_r13 = configuration->numRepetitionsPerPreambleAttempt_NB[CC_id];
+  nprach_parameters.npdcch_NumRepetitions_RA_r13 = configuration->npdcch_NumRepetitions_RA[CC_id];
+  nprach_parameters.npdcch_StartSF_CSS_RA_r13= configuration->npdcch_StartSF_CSS_RA[CC_id];
+  nprach_parameters.npdcch_Offset_RA_r13= configuration->npdcch_Offset_RA[CC_id];
+
+  //nprach_parameterList have a max size of 3 possible nprach configuration (see maxNPRACH_Resources_NB_r13)
+  ASN_SEQUENCE_ADD(&sib2_NB_IoT->radioResourceConfigCommon_r13.nprach_Config_r13.nprach_ParametersList_r13.list,&nprach_parameters);
+
+  // NPDSCH-Config NB-IOT
+  sib2_NB_IoT->radioResourceConfigCommon_r13.npdsch_ConfigCommon_r13.nrs_Power_r13= configuration->npdsch_nrs_Power[CC_id];
+
+
+  //NPUSCH-Config NB-IoT----------------------------------------------------------------
+  //list of size 3 (see maxNPRACH_Resources_NB_r13)
+  ack_nack_repetition = configuration-> npusch_ack_nack_numRepetitions_NB[CC_id]; //is an enumerative
+  ASN_SEQUENCE_ADD(&sib2_NB_IoT->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ack_NACK_NumRepetitions_Msg4_r13.list,ack_nack_repetition);
+
+  *srs_SubframeConfig = configuration->npusch_srs_SubframeConfig_NB[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.srs_SubframeConfig_r13= srs_SubframeConfig; /*OPTIONAL*/
+
+
+  /*OPTIONAL*/
+  dmrs_config = CALLOC(1,sizeof(struct NPUSCH_ConfigCommon_NB_r13__dmrs_Config_r13));
+  dmrs_config->threeTone_CyclicShift_r13 = configuration->npusch_threeTone_CyclicShift_r13[CC_id];
+  dmrs_config->sixTone_CyclicShift_r13 = configuration->npusch_sixTone_CyclicShift_r13[CC_id];
+
+  /*OPTIONAL
+   * -define the base sequence for a DMRS sequence in a cell with multi tone transmission (3,6,12) see TS 36.331 NPUSCH-Config-NB
+   * -if not defined will be calculated based on the cellID once we configure the phy layer (rrc_mac_config_req) through the config_sib2 */
+  dmrs_config->threeTone_BaseSequence_r13 = NULL;
+  dmrs_config->sixTone_BaseSequence_r13 = NULL;
+  dmrs_config->twelveTone_BaseSequence_r13 = NULL;
+
+  sib2_NB_IoT->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.dmrs_Config_r13 = dmrs_config;
+
+  //ulReferenceSignalsNPUSCH
+  /*Reference Signal (RS) for UL in NB-IoT is called DRS (Demodulation Reference Signal)
+   * sequence-group hopping can be enabled or disabled by means of the cell-specific parameter groupHoppingEnabled_r13
+   * sequence-group hopping can be disabled for certain specific UE through the parameter groupHoppingDisabled (physicalConfigDedicated)
+   * groupAssignmentNPUSCH--> is used for generate the sequence-shift pattern
+   */
+  sib2_NB_IoT->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13= configuration->npusch_groupHoppingEnabled[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13 =configuration->npusch_groupAssignmentNPUSCH_r13[CC_id];
+
+
+  //dl_GAP---------------------------------------------------------------------------------/*OPTIONAL*/
+  dl_Gap = CALLOC(1,sizeof(struct DL_GapConfig_NB_r13));
+  dl_Gap->dl_GapDurationCoeff_r13= configuration-> dl_GapDurationCoeff_NB[CC_id];
+  dl_Gap->dl_GapPeriodicity_r13= configuration->dl_GapPeriodicity_NB[CC_id];
+  dl_Gap->dl_GapThreshold_r13= configuration->dl_GapThreshold_NB[CC_id];
+  sib2_NB_IoT->radioResourceConfigCommon_r13.dl_Gap_r13 = dl_Gap;
+
+
+  // uplinkPowerControlCommon - NB-IoT------------------------------------------------------
+  sib2_NB_IoT->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.p0_NominalNPUSCH_r13 = configuration->npusch_p0_NominalNPUSCH;
+  sib2_NB_IoT->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.deltaPreambleMsg3_r13 = configuration->deltaPreambleMsg3;
+  sib2_NB_IoT->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.alpha_r13 = configuration->npusch_alpha;
+  //no deltaFlist_PUCCH and no UL cyclic prefix
+
+  // UE Timers and Constants -NB-IoT--------------------------------------------------------
+  sib2_NB_IoT->ue_TimersAndConstants_r13.t300_r13 = configuration-> ue_TimersAndConstants_t300_NB[CC_id];
+  sib2_NB_IoT->ue_TimersAndConstants_r13.t301_r13 = configuration-> ue_TimersAndConstants_t301_NB[CC_id];
+  sib2_NB_IoT->ue_TimersAndConstants_r13.t310_r13 = configuration-> ue_TimersAndConstants_t310_NB[CC_id];
+  sib2_NB_IoT->ue_TimersAndConstants_r13.t311_r13 = configuration-> ue_TimersAndConstants_t311_NB[CC_id];
+  sib2_NB_IoT->ue_TimersAndConstants_r13.n310_r13 = configuration-> ue_TimersAndConstants_n310_NB[CC_id];
+  sib2_NB_IoT->ue_TimersAndConstants_r13.n311_r13 = configuration-> ue_TimersAndConstants_n311_NB[CC_id];
+
+  //other SIB2-NB Parameters--------------------------------------------------------------------------------
+  sib2_NB_IoT->freqInfo_r13.additionalSpectrumEmission_r13 = 1;
+  sib2_NB_IoT->freqInfo_r13.ul_CarrierFreq_r13 = NULL; /*OPTIONAL*/
+
+  sib2_NB_IoT->timeAlignmentTimerCommon_r13=TimeAlignmentTimer_infinity;//TimeAlignmentTimer_sf5120;
+
+  /*OPTIONAL*/
+  sib2_NB_IoT->multiBandInfoList_r13 = NULL;
+
+/// SIB3-NB-------------------------------------------------------
+
+  sib3_NB_IoT->cellReselectionInfoCommon_r13.q_Hyst_r13=SystemInformationBlockType3_NB_r13__cellReselectionInfoCommon_r13__q_Hyst_r13_dB4;
+  sib3_NB_IoT->cellReselectionServingFreqInfo_r13.s_NonIntraSearch_r13=NULL; //or define in configuration?
+
+  sib3_NB_IoT->intraFreqCellReselectionInfo_r13.q_RxLevMin_r13 = -70;
+  //new
+  sib3_NB_IoT->intraFreqCellReselectionInfo_r13.q_QualMin_r13 = CALLOC(1,sizeof(*sib3_NB_IoT->intraFreqCellReselectionInfo_r13.q_QualMin_r13));
+  *(sib3_NB_IoT->intraFreqCellReselectionInfo_r13.q_QualMin_r13)= 10; //a caso
+
+  sib3_NB_IoT->intraFreqCellReselectionInfo_r13.p_Max_r13 = NULL;
+  sib3_NB_IoT->intraFreqCellReselectionInfo_r13.s_IntraSearchP_r13 = 31; // s_intraSearch --> s_intraSearchP!!! (they call in a different way)
+  sib3_NB_IoT->intraFreqCellReselectionInfo_r13.t_Reselection_r13=1;
+
+  //how to manage?
+  sib3_NB_IoT->freqBandInfo_r13 = NULL;
+  sib3_NB_IoT->multiBandInfoList_r13 = NULL;
+
+
+///BCCH message (generate the SI message)
+  bcch_message->message.present = BCCH_DL_SCH_MessageType_NB_PR_c1;
+  bcch_message->message.choice.c1.present = BCCH_DL_SCH_MessageType_NB__c1_PR_systemInformation_r13;
+
+  bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.present = SystemInformation_NB__criticalExtensions_PR_systemInformation_r13;
+  bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.list.count=0;
+
+  ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.list,
+                   sib2_NB_part);
+  ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.list,
+                   sib3_NB_part);
+
+#ifdef XER_PRINT
+  xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
+#endif
+  enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_DL_SCH_Message_NB,
+                                   (void*)bcch_message,
+                                   carrier->SIB23_NB_IoT,
+                                   900);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+//#if defined(ENABLE_ITTI).....
+
+
+#ifdef USER_MODE
+  LOG_D(RRC,"[eNB] SystemInformation-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+#endif
+
+  if (enc_rval.encoded==-1) {
+    msg("[RRC] ASN1 : SI-NB encoding failed for SIB23_NB_IoT\n");
+    return(-1);
+  }
+
+  return((enc_rval.encoded+7)/8);
+}
+
+/*do_RRCConnectionSetup_NB_IoT--> the aim is to establish SRB1 and SRB1bis(implicitly)*/
+uint8_t do_RRCConnectionSetup_NB_IoT(
+  const protocol_ctxt_t*     const ctxt_pP,
+  rrc_eNB_ue_context_NB_IoT_t*      const ue_context_pP,
+  int                              CC_id,
+  uint8_t*                   const buffer, //Srb0.Tx_buffer.Payload
+  const uint8_t                    Transaction_id,
+  const NB_IoT_DL_FRAME_PARMS* const frame_parms, // maybe not used
+  SRB_ToAddModList_NB_r13_t**             SRB_configList_NB_IoT, //for both SRB1bis and SRB1
+  struct PhysicalConfigDedicated_NB_r13** physicalConfigDedicated_NB_IoT
+)
+
+{
+
+ asn_enc_rval_t enc_rval;
+ uint8_t ecause=0;
+
+ //MP:logical channel group not defined for Nb-IoT
+
+ //MP: logical channel priority pag 605 (is 1 for SRB1 and for SRB1bis should be the same)
+ long* prioritySRB1 = NULL;
+ long* prioritySRB1bis = NULL;
+ BOOLEAN_t* logicalChannelSR_Prohibit =NULL; //pag 605
+ BOOLEAN_t* npusch_AllSymbols= NULL;
+
+// struct SRB_ToAddMod_NB_r13* SRB1_config_NB = NULL;
+// struct SRB_ToAddMod_NB_r13__rlc_Config_r13* SRB1_rlc_config_NB = NULL;
+// struct SRB_ToAddMod_NB_r13__logicalChannelConfig_r13* SRB1_lchan_config_NB = NULL;
+
+ struct SRB_ToAddMod_NB_r13* SRB1bis_config_NB_IoT = NULL;
+ struct SRB_ToAddMod_NB_r13__rlc_Config_r13* SRB1bis_rlc_config_NB_IoT = NULL;
+ struct SRB_ToAddMod_NB_r13__logicalChannelConfig_r13* SRB1bis_lchan_config_NB_IoT = NULL;
+
+ //No UL_specific parameters for NB-IoT in LogicalChanelConfig-NB
+
+ PhysicalConfigDedicated_NB_r13_t* physicalConfigDedicated2_NB_IoT = NULL;
+ DL_CCCH_Message_NB_t dl_ccch_msg_NB_IoT;
+ RRCConnectionSetup_NB_t* rrcConnectionSetup_NB_IoT = NULL;
+
+ memset((void *)&dl_ccch_msg_NB_IoT,0,sizeof(DL_CCCH_Message_NB_t));
+ dl_ccch_msg_NB_IoT.message.present = DL_CCCH_MessageType_NB_PR_c1;
+ dl_ccch_msg_NB_IoT.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionSetup_r13;
+ rrcConnectionSetup_NB_IoT = &dl_ccch_msg_NB_IoT.message.choice.c1.choice.rrcConnectionSetup_r13;
+
+
+ if (*SRB_configList_NB_IoT) {
+   free(*SRB_configList_NB_IoT);
+ }
+ *SRB_configList_NB_IoT = CALLOC(1,sizeof(SRB_ToAddModList_NB_r13_t));
+
+/// SRB1--------------------
+ {
+// SRB1_config_NB = CALLOC(1,sizeof(*SRB1_config_NB));
+//
+// //no srb_Identity in SRB_ToAddMod_NB
+//
+// SRB1_rlc_config_NB = CALLOC(1,sizeof(*SRB1_rlc_config_NB));
+// SRB1_config_NB->rlc_Config_r13   = SRB1_rlc_config_NB;
+//
+// SRB1_rlc_config_NB->present = SRB_ToAddMod_NB_r13__rlc_Config_r13_PR_explicitValue;
+// SRB1_rlc_config_NB->choice.explicitValue.present=RLC_Config_NB_r13_PR_am;//the only possible in NB_IoT
+//
+//// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = enb_properties.properties[ctxt_pP->module_id]->srb1_timer_poll_retransmit_r13;
+//// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = enb_properties.properties[ctxt_pP->module_id]->srb1_max_retx_threshold_r13;
+//// //(musT be disabled--> SRB1 config pag 640 specs )
+//// SRB1_rlc_config_NB->choice.explicitValue.choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 =NULL;
+//
+//
+// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms25000;
+// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t8;
+// //(musT be disabled--> SRB1 config pag 640 specs )
+// SRB1_rlc_config_NB->choice.explicitValue.choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = NULL;
+//
+// SRB1_lchan_config_NB = CALLOC(1,sizeof(*SRB1_lchan_config_NB));
+// SRB1_config_NB->logicalChannelConfig_r13  = SRB1_lchan_config_NB;
+//
+// SRB1_lchan_config_NB->present = SRB_ToAddMod_NB_r13__logicalChannelConfig_r13_PR_explicitValue;
+//
+//
+// prioritySRB1 = CALLOC(1, sizeof(long));
+// *prioritySRB1 = 1;
+// SRB1_lchan_config_NB->choice.explicitValue.priority_r13 = prioritySRB1;
+//
+// logicalChannelSR_Prohibit = CALLOC(1, sizeof(BOOLEAN_t));
+// *logicalChannelSR_Prohibit = 1;
+// //schould be set to TRUE (specs pag 641)
+// SRB1_lchan_config_NB->choice.explicitValue.logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit;
+//
+// //ADD SRB1
+// ASN_SEQUENCE_ADD(&(*SRB_configList_NB_IoT)->list,SRB1_config_NB);
+ }
+
+///SRB1bis (The configuration for SRB1 and SRB1bis is the same) the only difference is the logical channel identity = 3 but not set here
+
+		 SRB1bis_config_NB_IoT = CALLOC(1,sizeof(*SRB1bis_config_NB_IoT));
+
+		 //no srb_Identity in SRB_ToAddMod_NB
+		 SRB1bis_rlc_config_NB_IoT = CALLOC(1,sizeof(*SRB1bis_rlc_config_NB_IoT));
+		 SRB1bis_config_NB_IoT->rlc_Config_r13   = SRB1bis_rlc_config_NB_IoT;
+
+		 SRB1bis_rlc_config_NB_IoT->present = SRB_ToAddMod_NB_r13__rlc_Config_r13_PR_explicitValue;
+		 SRB1bis_rlc_config_NB_IoT->choice.explicitValue.present=RLC_Config_NB_r13_PR_am;//MP: the only possible RLC config in NB_IoT
+
+		 SRB1bis_rlc_config_NB_IoT->choice.explicitValue.choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms25000;
+		 SRB1bis_rlc_config_NB_IoT->choice.explicitValue.choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t8;
+		 //(musT be disabled--> SRB1 config pag 640 specs )
+		 SRB1bis_rlc_config_NB_IoT->choice.explicitValue.choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 =NULL;
+
+		 SRB1bis_lchan_config_NB_IoT = CALLOC(1,sizeof(*SRB1bis_lchan_config_NB_IoT));
+		 SRB1bis_config_NB_IoT->logicalChannelConfig_r13  = SRB1bis_lchan_config_NB_IoT;
+
+		 SRB1bis_lchan_config_NB_IoT->present = SRB_ToAddMod_NB_r13__logicalChannelConfig_r13_PR_explicitValue;
+
+		 prioritySRB1bis = CALLOC(1, sizeof(long));
+		 *prioritySRB1bis = 1; //same as SRB1?
+		 SRB1bis_lchan_config_NB_IoT->choice.explicitValue.priority_r13 = prioritySRB1bis;
+
+		 logicalChannelSR_Prohibit = CALLOC(1, sizeof(BOOLEAN_t));
+		 *logicalChannelSR_Prohibit = 1; //schould be set to TRUE (specs pag 641)
+		 SRB1bis_lchan_config_NB_IoT->choice.explicitValue.logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit;
+
+		 //ADD SRB1bis
+		 //MP: Actually there is no way to distinguish SRB1 and SRB1bis once put in the list
+		 //MP: SRB_ToAddModList_NB_r13_t size = 1
+		 ASN_SEQUENCE_ADD(&(*SRB_configList_NB_IoT)->list,SRB1bis_config_NB_IoT);
+
+
+ // PhysicalConfigDedicated (NPDCCH, NPUSCH, CarrierConfig, UplinkPowerControl)
+
+ physicalConfigDedicated2_NB_IoT = CALLOC(1,sizeof(*physicalConfigDedicated2_NB_IoT));
+ *physicalConfigDedicated_NB_IoT = physicalConfigDedicated2_NB_IoT;
+
+ physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13= CALLOC(1, sizeof(*physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13));
+ physicalConfigDedicated2_NB_IoT->npdcch_ConfigDedicated_r13 = CALLOC(1,sizeof(*physicalConfigDedicated2_NB_IoT->npdcch_ConfigDedicated_r13));
+ physicalConfigDedicated2_NB_IoT->npusch_ConfigDedicated_r13 = CALLOC(1,sizeof(*physicalConfigDedicated2_NB_IoT->npusch_ConfigDedicated_r13));
+ physicalConfigDedicated2_NB_IoT->uplinkPowerControlDedicated_r13 = CALLOC(1,sizeof(*physicalConfigDedicated2_NB_IoT->uplinkPowerControlDedicated_r13));
+
+ //no tpc, no cqi and no pucch, no pdsch, no soundingRS, no AntennaInfo, no scheduling request config
+
+ /*
+  * NB-IoT supports the operation with either one or two antenna ports, AP0 and AP1.
+  * For the latter case, Space Frequency Block Coding (SFBC) is applied.
+  * Once selected, the same transmission scheme applies to NPBCH, NPDCCH, and NPDSCH.
+  * */
+
+ //FIXME: MP: CarrierConfigDedicated check the set values ----------------------------------------------
+
+  //DL
+
+ physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13->dl_CarrierConfig_r13.dl_CarrierFreq_r13.carrierFreq_r13=0;//random value set
+ physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13->dl_CarrierConfig_r13.downlinkBitmapNonAnchor_r13= CALLOC(1,sizeof(struct DL_CarrierConfigDedicated_NB_r13__downlinkBitmapNonAnchor_r13));
+		 physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13->dl_CarrierConfig_r13.downlinkBitmapNonAnchor_r13->present=
+				 	 	 	 	 	 	 	 	 DL_CarrierConfigDedicated_NB_r13__downlinkBitmapNonAnchor_r13_PR_useNoBitmap_r13;
+
+ physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13->dl_CarrierConfig_r13.dl_GapNonAnchor_r13 = CALLOC(1,sizeof(struct DL_CarrierConfigDedicated_NB_r13__dl_GapNonAnchor_r13));
+ physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13->dl_CarrierConfig_r13.dl_GapNonAnchor_r13->present =
+		  	  	  	  	  	  	  	  	  	  	  DL_CarrierConfigDedicated_NB_r13__dl_GapNonAnchor_r13_PR_useNoGap_r13;
+
+ physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13->dl_CarrierConfig_r13.inbandCarrierInfo_r13= NULL;
+
+  //UL
+ physicalConfigDedicated2_NB_IoT->carrierConfigDedicated_r13->ul_CarrierConfig_r13.ul_CarrierFreq_r13= NULL;
+
+ // NPDCCH
+ physicalConfigDedicated2_NB_IoT->npdcch_ConfigDedicated_r13->npdcch_NumRepetitions_r13 =0;
+ physicalConfigDedicated2_NB_IoT->npdcch_ConfigDedicated_r13->npdcch_Offset_USS_r13 =0;
+ physicalConfigDedicated2_NB_IoT->npdcch_ConfigDedicated_r13->npdcch_StartSF_USS_r13=0;
+
+ // NPUSCH //(specs TS 36.331 v14.2.1 pag 643) /* OPTIONAL */
+ physicalConfigDedicated2_NB_IoT->npusch_ConfigDedicated_r13->ack_NACK_NumRepetitions_r13= NULL;
+ npusch_AllSymbols= CALLOC(1, sizeof(BOOLEAN_t));
+ *npusch_AllSymbols= 1; //TRUE
+ physicalConfigDedicated2_NB_IoT->npusch_ConfigDedicated_r13->npusch_AllSymbols_r13= npusch_AllSymbols; /* OPTIONAL */
+ physicalConfigDedicated2_NB_IoT->npusch_ConfigDedicated_r13->groupHoppingDisabled_r13=NULL; /* OPTIONAL */
+
+ // UplinkPowerControlDedicated
+ physicalConfigDedicated2_NB_IoT->uplinkPowerControlDedicated_r13->p0_UE_NPUSCH_r13 = 0; // 0 dB (specs TS36.331 v14.2.1 pag 643)
+
+
+ //Fill the rrcConnectionSetup-NB message
+ rrcConnectionSetup_NB_IoT->rrc_TransactionIdentifier = Transaction_id; //input value
+ rrcConnectionSetup_NB_IoT->criticalExtensions.present = RRCConnectionSetup_NB__criticalExtensions_PR_c1;
+ rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.present =RRCConnectionSetup_NB__criticalExtensions__c1_PR_rrcConnectionSetup_r13 ;
+ //MP: carry only SRB1bis at the moment and phyConfigDedicated
+ rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.srb_ToAddModList_r13 = *SRB_configList_NB_IoT;
+ rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.drb_ToAddModList_r13 = NULL;
+ rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.drb_ToReleaseList_r13 = NULL;
+ rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.rlf_TimersAndConstants_r13 = NULL;
+ rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13 = physicalConfigDedicated2_NB_IoT;
+ rrcConnectionSetup_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.mac_MainConfig_r13 = NULL;
+
+#ifdef XER_PRINT
+ xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
+#endif
+ enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
+                                  (void*)&dl_ccch_msg_NB_IoT,
+                                  buffer,
+                                  100);
+ AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+              enc_rval.failed_type->name, enc_rval.encoded);
+
+
+#ifdef USER_MODE
+ LOG_D(RRC,"RRCConnectionSetup-NB Encoded %d bits (%d bytes), ecause %d\n",
+       enc_rval.encoded,(enc_rval.encoded+7)/8,ecause);
+#endif
+
+ return((enc_rval.encoded+7)/8);
+}
+
+/*do_SecurityModeCommand - exactly the same as previous implementation*/
+uint8_t do_SecurityModeCommand_NB_IoT(
+  const protocol_ctxt_t* const ctxt_pP,
+  uint8_t* const buffer,
+  const uint8_t Transaction_id,
+  const uint8_t cipheringAlgorithm,
+  const uint8_t integrityProtAlgorithm)
+{
+  DL_DCCH_Message_NB_t dl_dcch_msg_NB_IoT;
+  asn_enc_rval_t enc_rval;
+
+  memset(&dl_dcch_msg_NB_IoT,0,sizeof(DL_DCCH_Message_NB_t));
+
+  dl_dcch_msg_NB_IoT.message.present = DL_DCCH_MessageType_NB_PR_c1;
+  dl_dcch_msg_NB_IoT.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_securityModeCommand_r13;
+
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.securityModeCommand_r13.rrc_TransactionIdentifier = Transaction_id;
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.present = SecurityModeCommand__criticalExtensions_PR_c1;
+
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.choice.c1.present =
+		  SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8;
+
+  // the two following information could be based on the mod_id
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm
+    = (CipheringAlgorithm_r12_t)cipheringAlgorithm; //bug solved
+
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm
+    = (e_SecurityAlgorithmConfig__integrityProtAlgorithm)integrityProtAlgorithm;
+
+//only changed "asn_DEF_DL_DCCH_Message_NB"
+#ifdef XER_PRINT
+  xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB_IoT);
+#endif
+  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
+                                   (void*)&dl_dcch_msg_NB_IoT,
+                                   buffer,
+                                   100);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+
+//#if defined(ENABLE_ITTI)
+//# if !defined(DISABLE_XER_SPRINT)....
+
+#ifdef USER_MODE
+  LOG_D(RRC,"[eNB %d] securityModeCommand-NB for UE %x Encoded %d bits (%d bytes)\n",
+        ctxt_pP->module_id,
+        ctxt_pP->rnti,
+        enc_rval.encoded,
+        (enc_rval.encoded+7)/8);
+#endif
+
+  if (enc_rval.encoded==-1) {
+    LOG_E(RRC,"[eNB %d] ASN1 : securityModeCommand-NB encoding failed for UE %x\n",
+          ctxt_pP->module_id,
+          ctxt_pP->rnti);
+    return(-1);
+  }
+
+  return((enc_rval.encoded+7)/8);
+}
+
+/*do_UECapabilityEnquiry_NB_IoT - very similar to legacy lte*/
+uint8_t do_UECapabilityEnquiry_NB_IoT(
+  const protocol_ctxt_t* const ctxt_pP,
+  uint8_t*               const buffer,
+  const uint8_t                Transaction_id
+)
+
+{
+
+  DL_DCCH_Message_NB_t dl_dcch_msg_NB_IoT;
+  //no RAT type in NB-IoT
+  asn_enc_rval_t enc_rval;
+
+  memset(&dl_dcch_msg_NB_IoT,0,sizeof(DL_DCCH_Message_NB_t));
+
+  dl_dcch_msg_NB_IoT.message.present           = DL_DCCH_MessageType_NB_PR_c1;
+  dl_dcch_msg_NB_IoT.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_ueCapabilityEnquiry_r13;
+
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.ueCapabilityEnquiry_r13.rrc_TransactionIdentifier = Transaction_id;
+
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.ueCapabilityEnquiry_r13.criticalExtensions.present = UECapabilityEnquiry_NB__criticalExtensions_PR_c1;
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.ueCapabilityEnquiry_r13.criticalExtensions.choice.c1.present =
+		  UECapabilityEnquiry_NB__criticalExtensions__c1_PR_ueCapabilityEnquiry_r13;
+
+  //no ue_CapabilityRequest (list of RAT_Type)
+
+//only changed "asn_DEF_DL_DCCH_Message_NB"
+#ifdef XER_PRINT
+  xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB_IoT);
+#endif
+  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
+                                   (void*)&dl_dcch_msg_NB_IoT,
+                                   buffer,
+                                   100);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+//#if defined(ENABLE_ITTI)
+//# if !defined(DISABLE_XER_SPRINT)....
+
+#ifdef USER_MODE
+  LOG_D(RRC,"[eNB %d] UECapabilityEnquiry-NB for UE %x Encoded %d bits (%d bytes)\n",
+        ctxt_pP->module_id,
+        ctxt_pP->rnti,
+        enc_rval.encoded,
+        (enc_rval.encoded+7)/8);
+#endif
+
+  if (enc_rval.encoded==-1) {
+    LOG_E(RRC,"[eNB %d] ASN1 : UECapabilityEnquiry-NB encoding failed for UE %x\n",
+          ctxt_pP->module_id,
+          ctxt_pP->rnti);
+    return(-1);
+  }
+
+  return((enc_rval.encoded+7)/8);
+}
+
+/*do_RRCConnectionReconfiguration_NB_IoT-->may convey information for resource configuration
+ * (including RBs, MAC main configuration and physical channel configuration)
+ * including any associated dedicated NAS information.*/
+uint16_t do_RRCConnectionReconfiguration_NB_IoT(
+  const protocol_ctxt_t*        const ctxt_pP,
+    uint8_t                            *buffer,
+    uint8_t                             Transaction_id,
+    SRB_ToAddModList_NB_r13_t          *SRB1_list_NB, //SRB_ConfigList2 (default)--> only SRB1
+    DRB_ToAddModList_NB_r13_t          *DRB_list_NB_IoT, //DRB_ConfigList (default)
+    DRB_ToReleaseList_NB_r13_t         *DRB_list2_NB_IoT, //is NULL when passed
+    struct PhysicalConfigDedicated_NB_r13     *physicalConfigDedicated_NB_IoT,
+	MAC_MainConfig_NB_r13_t                   *mac_MainConfig_NB_IoT,
+  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13* dedicatedInfoNASList_NB_IoT)
+
+{
+
+ //check on DRB_list if contains more than 2 DRB?
+
+  asn_enc_rval_t enc_rval;
+  DL_DCCH_Message_NB_t dl_dcch_msg_NB_IoT;
+  RRCConnectionReconfiguration_NB_t *rrcConnectionReconfiguration_NB;
+
+
+  memset(&dl_dcch_msg_NB_IoT,0,sizeof(DL_DCCH_Message_NB_t));
+
+  dl_dcch_msg_NB_IoT.message.present           = DL_DCCH_MessageType_NB_PR_c1;
+  dl_dcch_msg_NB_IoT.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_rrcConnectionReconfiguration_r13;
+  rrcConnectionReconfiguration_NB          = &dl_dcch_msg_NB_IoT.message.choice.c1.choice.rrcConnectionReconfiguration_r13;
+
+  // RRCConnectionReconfiguration
+  rrcConnectionReconfiguration_NB->rrc_TransactionIdentifier = Transaction_id;
+  rrcConnectionReconfiguration_NB->criticalExtensions.present = RRCConnectionReconfiguration_NB__criticalExtensions_PR_c1;
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.present =RRCConnectionReconfiguration_NB__criticalExtensions__c1_PR_rrcConnectionReconfiguration_r13 ;
+
+  //RAdioResourceconfigDedicated
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13 =
+		  CALLOC(1,sizeof(*rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13));
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->srb_ToAddModList_r13 = SRB1_list_NB; //only SRB1
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->drb_ToAddModList_r13 = DRB_list_NB_IoT;
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->drb_ToReleaseList_r13 = DRB_list2_NB_IoT; //NULL
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->physicalConfigDedicated_r13 = physicalConfigDedicated_NB_IoT;
+  //FIXME may not used now
+  //rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->rlf_TimersAndConstants_r13
+
+  if (mac_MainConfig_NB_IoT!=NULL) {
+    rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13 =
+    		CALLOC(1, sizeof(*rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13));
+    rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13->present
+      =RadioResourceConfigDedicated_NB_r13__mac_MainConfig_r13_PR_explicitValue_r13;
+   //why memcopy only this one?
+    memcpy(&rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13->choice.explicitValue_r13,
+           mac_MainConfig_NB_IoT, sizeof(*mac_MainConfig_NB_IoT));
+
+  } else {
+	  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13=NULL;
+  }
+
+  //no measConfig, measIDlist
+  //no mobilityControlInfo
+
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.dedicatedInfoNASList_r13 = dedicatedInfoNASList_NB_IoT;
+  //mainly used for cell-reselection/handover purposes??
+  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.fullConfig_r13 = NULL;
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
+                                   (void*)&dl_dcch_msg_NB_IoT,
+                                   buffer,
+                                   RRC_BUF_SIZE);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %l)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  //changed only asn_DEF_DL_DCCH_Message_NB
+#ifdef XER_PRINT
+  xer_fprint(stdout,&asn_DEF_DL_DCCH_Message_NB,(void*)&dl_dcch_msg_NB_IoT);
+#endif
+
+//#if defined(ENABLE_ITTI)
+//# if !defined(DISABLE_XER_SPRINT)...
+
+
+  LOG_I(RRC,"RRCConnectionReconfiguration-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+
+  return((enc_rval.encoded+7)/8);
+}
+
+/*do_RRCConnectionReestablishmentReject - exactly the same as legacy LTE*/
+uint8_t do_RRCConnectionReestablishmentReject_NB_IoT(
+    uint8_t                    Mod_id,
+    uint8_t*                   const buffer)
+{
+
+  asn_enc_rval_t enc_rval;
+
+  DL_CCCH_Message_NB_t dl_ccch_msg_NB_IoT;
+  RRCConnectionReestablishmentReject_t *rrcConnectionReestablishmentReject;
+
+  memset((void *)&dl_ccch_msg_NB_IoT,0,sizeof(DL_CCCH_Message_NB_t));
+  dl_ccch_msg_NB_IoT.message.present = DL_CCCH_MessageType_NB_PR_c1;
+  dl_ccch_msg_NB_IoT.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionReestablishmentReject_r13;
+  rrcConnectionReestablishmentReject    = &dl_ccch_msg_NB_IoT.message.choice.c1.choice.rrcConnectionReestablishmentReject_r13;
+
+  // RRCConnectionReestablishmentReject //exactly the same as LTE
+  rrcConnectionReestablishmentReject->criticalExtensions.present = RRCConnectionReestablishmentReject__criticalExtensions_PR_rrcConnectionReestablishmentReject_r8;
+
+  //Only change in "asn_DEF_DL_CCCH_Message_NB"
+#ifdef XER_PRINT
+  xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg_NB_IoT);
+#endif
+  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
+                                   (void*)&dl_ccch_msg_NB_IoT,
+                                   buffer,
+                                   100);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+  //Only change in "asn_DEF_DL_CCCH_Message_NB"
+#if defined(ENABLE_ITTI)
+# if !defined(DISABLE_XER_SPRINT)
+  {
+    char        message_string[20000];
+    size_t      message_string_size;
+
+    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message_NB, (void *) &dl_ccch_msg_NB_IoT)) > 0) {
+      MessageDef *msg_p;
+
+      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText));
+      msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size;
+      memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size);
+
+      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
+    }
+  }
+# endif
+#endif
+
+#ifdef USER_MODE
+  LOG_D(RRC,"RRCConnectionReestablishmentReject Encoded %d bits (%d bytes)\n",
+        enc_rval.encoded,(enc_rval.encoded+7)/8);
+#endif
+
+  return((enc_rval.encoded+7)/8);
+}
+
+/*do_RRCConnectionReject_NB_IoT*/
+uint8_t do_RRCConnectionReject_NB_IoT(
+    uint8_t                    Mod_id,
+    uint8_t*                   const buffer)
+
+{
+
+  asn_enc_rval_t enc_rval;
+
+  DL_CCCH_Message_NB_t          dl_ccch_msg_NB_IoT;
+  RRCConnectionReject_NB_t      *rrcConnectionReject_NB_IoT;
+
+  memset((void *)&dl_ccch_msg_NB_IoT,0,sizeof(DL_CCCH_Message_NB_t));
+  dl_ccch_msg_NB_IoT.message.present           = DL_CCCH_MessageType_NB_PR_c1;
+  dl_ccch_msg_NB_IoT.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionReject_r13;
+  rrcConnectionReject_NB_IoT = &dl_ccch_msg_NB_IoT.message.choice.c1.choice.rrcConnectionReject_r13;
+
+  // RRCConnectionReject-NB_IoT
+  rrcConnectionReject_NB_IoT->criticalExtensions.present = RRCConnectionReject_NB__criticalExtensions_PR_c1;
+  rrcConnectionReject_NB_IoT->criticalExtensions.choice.c1.present = RRCConnectionReject_NB__criticalExtensions__c1_PR_rrcConnectionReject_r13;
+  /* let's put an extended wait time of 1s for the moment */
+  rrcConnectionReject_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReject_r13.extendedWaitTime_r13 = 1;
+  //new-use of suspend indication
+  //If present, this field indicates that the UE should remain suspended and not release its stored context.
+  rrcConnectionReject_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReject_r13.rrc_SuspendIndication_r13=
+		  CALLOC(1, sizeof(long));
+  *(rrcConnectionReject_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReject_r13.rrc_SuspendIndication_r13)=
+		  RRCConnectionReject_NB_r13_IEs__rrc_SuspendIndication_r13_true;
+
+  //Only Modified "asn_DEF_DL_CCCH_Message_NB"
+#ifdef XER_PRINT
+  xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg);
+#endif
+  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
+                                   (void*)&dl_ccch_msg_NB_IoT,
+                                   buffer,
+                                   100);
+  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %ld)!\n",
+               enc_rval.failed_type->name, enc_rval.encoded);
+
+#if defined(ENABLE_ITTI)
+# if !defined(DISABLE_XER_SPRINT)
+  {
+    char        message_string[20000];
+    size_t      message_string_size;
+
+    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message_NB, (void *) &dl_ccch_msg_NB_IoT)) > 0) {
+      MessageDef *msg_p;
+
+      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText));
+      msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size;
+      memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size);
+
+      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
+    }
+  }
+# endif
+#endif
+
+#ifdef USER_MODE
+  LOG_D(RRC,"RRCConnectionReject-NB Encoded %d bits (%d bytes)\n",
+        enc_rval.encoded,(enc_rval.encoded+7)/8);
+#endif
+
+  return((enc_rval.encoded+7)/8);
+}
+
+
+//no do_MBSFNAreaConfig(..) in NB-IoT
+//no do_MeasurementReport(..) in NB-IoT
+
+/*do_DLInformationTransfer_NB*/
+uint8_t do_DLInformationTransfer_NB_IoT(
+		uint8_t Mod_id,
+		uint8_t **buffer,
+		uint8_t transaction_id,
+		uint32_t pdu_length,
+		uint8_t *pdu_buffer)
+
+{
+  ssize_t encoded;
+
+  DL_DCCH_Message_NB_t dl_dcch_msg_NB_IoT;
+
+  memset(&dl_dcch_msg_NB_IoT, 0, sizeof(DL_DCCH_Message_NB_t));
+
+  dl_dcch_msg_NB_IoT.message.present           = DL_DCCH_MessageType_NB_PR_c1;
+  dl_dcch_msg_NB_IoT.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_dlInformationTransfer_r13;
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.dlInformationTransfer_r13.rrc_TransactionIdentifier = transaction_id;
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.present = DLInformationTransfer_NB__criticalExtensions_PR_c1;
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.choice.c1.present = DLInformationTransfer_NB__criticalExtensions__c1_PR_dlInformationTransfer_r13;
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.choice.c1.choice.dlInformationTransfer_r13.dedicatedInfoNAS_r13.size = pdu_length;
+  dl_dcch_msg_NB_IoT.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.choice.c1.choice.dlInformationTransfer_r13.dedicatedInfoNAS_r13.buf = pdu_buffer;
+
+  encoded = uper_encode_to_new_buffer (&asn_DEF_DL_DCCH_Message_NB, NULL, (void*) &dl_dcch_msg_NB_IoT, (void **) buffer);
+
+  //only change in "asn_DEF_DL_DCCH_Message_NB"
+#if defined(ENABLE_ITTI)
+# if !defined(DISABLE_XER_SPRINT)
+  {
+    char        message_string[10000];
+    size_t      message_string_size;
+
+    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_DCCH_Message_NB, (void *)&dl_dcch_msg_NB_IoT)) > 0) {
+      MessageDef *msg_p;
+
+      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_DCCH, message_string_size + sizeof (IttiMsgText));
+      msg_p->ittiMsg.rrc_dl_dcch.size = message_string_size;
+      memcpy(&msg_p->ittiMsg.rrc_dl_dcch.text, message_string, message_string_size);
+
+      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
+    }
+  }
+# endif
+#endif
+
+  return encoded;
+}
+
+/*do_ULInformationTransfer*/
+//for the moment is not needed (UE-SIDE)
+
+/*OAI_UECapability_t *fill_ue_capability*/
+
+/*do_RRCConnectionReestablishment_NB-->used to re-establish SRB1*/ //which parameter to use?
+uint8_t do_RRCConnectionReestablishment_NB_IoT(
+		uint8_t Mod_id,
+		uint8_t* const buffer,
+		const uint8_t     Transaction_id,
+		const NB_IoT_DL_FRAME_PARMS* const frame_parms, //to be changed
+		SRB_ToAddModList_NB_r13_t*      SRB_list_NB_IoT) //should contain SRB1 already configured?
+{
+
+	asn_enc_rval_t enc_rval;
+	DL_CCCH_Message_NB_t dl_ccch_msg_NB_IoT;
+	RRCConnectionReestablishment_NB_t* rrcConnectionReestablishment_NB_IoT;
+
+	memset(&dl_ccch_msg_NB_IoT, 0, sizeof(DL_CCCH_Message_NB_t));
+
+	dl_ccch_msg_NB_IoT.message.present = DL_CCCH_MessageType_NB_PR_c1;
+	dl_ccch_msg_NB_IoT.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionReestablishment_r13;
+	rrcConnectionReestablishment_NB_IoT = &dl_ccch_msg_NB_IoT.message.choice.c1.choice.rrcConnectionReestablishment_r13;
+
+	//rrcConnectionReestablishment_NB
+	rrcConnectionReestablishment_NB_IoT->rrc_TransactionIdentifier = Transaction_id;
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.present = RRCConnectionReestablishment_NB__criticalExtensions_PR_c1;
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.present = RRCConnectionReestablishment_NB__criticalExtensions__c1_PR_rrcConnectionReestablishment_r13;
+
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.srb_ToAddModList_r13 = SRB_list_NB_IoT;
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.drb_ToAddModList_r13 = NULL;
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.drb_ToReleaseList_r13 = NULL;
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.rlf_TimersAndConstants_r13= NULL;
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.mac_MainConfig_r13= NULL;
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13 = NULL;
+
+	rrcConnectionReestablishment_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.nextHopChainingCount_r13=0;
+
+	enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
+	                                   (void*)&dl_ccch_msg_NB_IoT,
+	                                   buffer,
+	                                   RRC_BUF_SIZE);
+
+	 AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %l)!\n",
+	               enc_rval.failed_type->name, enc_rval.encoded);
+
+#ifdef XER_PRINT
+  xer_fprint(stdout,&asn_DEF_DL_CCCH_Message_NB,(void*)&dl_ccch_msg_NB_IoT);
+#endif
+
+#if defined(ENABLE_ITTI)
+# if !defined(DISABLE_XER_SPRINT)
+  {
+    char        message_string[30000];
+    size_t      message_string_size;
+
+    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message_NB, (void *) &dl_ccch_msg_NB_IoT)) > 0) {
+      MessageDef *msg_p;
+
+      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText));
+      msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size;
+      memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size);
+
+      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
+    }
+  }
+# endif
+#endif
+
+  LOG_I(RRC,"RRCConnectionReestablishment-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
+
+}
+
+/*do_RRCConnectionRelease_NB--> is used to command the release of an RRC connection*/
+uint8_t do_RRCConnectionRelease_NB_IoT(
+  uint8_t                             Mod_id,
+  uint8_t                            *buffer,
+ const uint8_t                             Transaction_id)
+{
+
+  asn_enc_rval_t enc_rval;
+
+  DL_DCCH_Message_NB_t dl_dcch_msg_NB_IoT;
+  RRCConnectionRelease_NB_t *rrcConnectionRelease_NB_IoT;
+
+
+  memset(&dl_dcch_msg_NB_IoT,0,sizeof(DL_DCCH_Message_NB_t));
+
+  dl_dcch_msg_NB_IoT.message.present           = DL_DCCH_MessageType_NB_PR_c1;
+  dl_dcch_msg_NB_IoT.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_rrcConnectionRelease_r13;
+  rrcConnectionRelease_NB_IoT                  = &dl_dcch_msg_NB_IoT.message.choice.c1.choice.rrcConnectionRelease_r13;
+
+  // RRCConnectionRelease
+  rrcConnectionRelease_NB_IoT->rrc_TransactionIdentifier = Transaction_id;
+  rrcConnectionRelease_NB_IoT->criticalExtensions.present = RRCConnectionRelease_NB__criticalExtensions_PR_c1;
+  rrcConnectionRelease_NB_IoT->criticalExtensions.choice.c1.present =RRCConnectionRelease_NB__criticalExtensions__c1_PR_rrcConnectionRelease_r13 ;
+
+  rrcConnectionRelease_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.releaseCause_r13 = ReleaseCause_NB_r13_other;
+  rrcConnectionRelease_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.redirectedCarrierInfo_r13 = NULL;
+  rrcConnectionRelease_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.extendedWaitTime_r13 = NULL;
+
+  //Why allocate memory for non critical extension?
+  rrcConnectionRelease_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.nonCriticalExtension=CALLOC(1,
+      sizeof(*rrcConnectionRelease_NB_IoT->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.nonCriticalExtension));
+
+  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
+                                   (void*)&dl_dcch_msg_NB_IoT,
+                                   buffer,
+                                   RRC_BUF_SIZE);//check
+
+  return((enc_rval.encoded+7)/8);
+}
+
+
+// -----??????--------------------
+#ifndef USER_MODE
+int init_module_NB_IoT(void)
+{
+  printk("Init asn1_msg_nb_iot module\n");
+
+  // A non 0 return means init_module failed; module can't be loaded.
+  return 0;
+}
+
+
+void cleanup_module_NB_IoT(void)
+{
+  printk("Stopping asn1_msg_nb_iot module\n");
+}
+
+EXPORT_SYMBOL(do_SIB1_NB_IoT);
+EXPORT_SYMBOL(do_SIB23_NB_IoT);
+EXPORT_SYMBOL(do_RRCConnectionRequest_NB_IoT);
+EXPORT_SYMBOL(do_RRCConnectionSetupComplete_NB_IoT);
+EXPORT_SYMBOL(do_RRCConnectionReconfigurationComplete_NB_IoT);
+EXPORT_SYMBOL(do_RRCConnectionSetup_NB_IoT);
+EXPORT_SYMBOL(do_RRCConnectionReestablishmentReject_NB_IoT);
+EXPORT_SYMBOL(do_RRCConnectionReconfiguration_NB_IoT);
+EXPORT_SYMBOL(asn_DEF_UL_DCCH_Message_NB);
+EXPORT_SYMBOL(asn_DEF_UL_CCCH_Message_NB);
+EXPORT_SYMBOL(asn_DEF_SystemInformation_NB_IoT);
+EXPORT_SYMBOL(asn_DEF_DL_DCCH_Message_NB);
+EXPORT_SYMBOL(asn_DEF_SystemInformationBlockType1_NB_IoT);
+EXPORT_SYMBOL(asn_DEF_DL_CCCH_Message_NB);
+EXPORT_SYMBOL(uper_decode_complete);
+EXPORT_SYMBOL(uper_decode);
+EXPORT_SYMBOL(transmission_mode_rrc);
+#endif
+
+//----------------------------------
+
+
+
+
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg_nb_iot.h b/openair2/RRC/LITE/MESSAGES/asn1_msg_NB_IoT.h
similarity index 77%
rename from openair2/RRC/LITE/MESSAGES/asn1_msg_nb_iot.h
rename to openair2/RRC/LITE/MESSAGES/asn1_msg_NB_IoT.h
index eb0450f533d5da688c21729431b7d60ff67e1e31..ea0fea91d54de5e65e38c08c70d182e27cf0d997 100644
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg_nb_iot.h
+++ b/openair2/RRC/LITE/MESSAGES/asn1_msg_NB_IoT.h
@@ -44,7 +44,7 @@
 #include <asn_internal.h> /* for _ASN_DEFAULT_STACK_MAX */
 
 
-#include "RRC/LITE/defs_nb_iot.h"
+#include "RRC/LITE/defs_NB_IoT.h"
 
 /*
  * The variant of the above function which dumps the BASIC-XER (XER_F_BASIC)
@@ -52,17 +52,9 @@
  * RETURN VALUES:
  *       0: The structure is printed.
  *      -1: Problem printing the structure.
- * WARNING: No sensible errno value is returned.
+ * WARNING: No sensible error value is returned.
  */
 
-//not touched
-int xer_sprint(char *string, size_t string_size, struct asn_TYPE_descriptor_s *td, void *sptr);
-
-//not touched
-uint16_t get_adjacent_cell_id(uint8_t Mod_id,uint8_t index);
-
-//Not touched
-uint8_t get_adjacent_cell_mod_id(uint16_t phyCellId);
 
 /**
 \brief Generate configuration for SIB1 (eNB).
@@ -70,8 +62,8 @@ uint8_t get_adjacent_cell_mod_id(uint16_t phyCellId);
 @param N_RB_DL Number of downlink PRBs
 @param frame radio frame number
 @return size of encoded bit stream in bytes*/
-uint8_t do_MIB_NB(
-		rrc_eNB_carrier_data_NB_t *carrier,
+uint8_t do_MIB_NB_IoT(
+		rrc_eNB_carrier_data_NB_IoT_t *carrier,
 		uint32_t N_RB_DL,
 		uint32_t frame);
 
@@ -84,25 +76,27 @@ uint8_t do_MIB_NB(
 @param configuration Pointer Configuration Request structure
 @return size of encoded bit stream in bytes*/
 
-uint8_t do_SIB1_NB(uint8_t Mod_id, int CC_id,
-				rrc_eNB_carrier_data_NB_t *carrier,
-                RrcConfigurationReq *configuration
-               );
+uint8_t do_SIB1_NB_IoT(uint8_t Mod_id, 
+                       int CC_id,
+				               rrc_eNB_carrier_data_NB_IoT_t *carrier,
+                       RrcConfigurationReq *configuration,
+				               uint32_t frame
+                      );
 
 /**
 \brief Generate a default configuration for SIB2/SIB3-NB in one System Information PDU (eNB).
 @param Mod_id Index of eNB (used to derive some parameters)
 @param buffer Pointer to PER-encoded ASN.1 description of SI-NB PDU
-@param systemInformation_NB Pointer to asn1c C representation of SI-NB PDU
+@param systemInformation_NB_IoT Pointer to asn1c C representation of SI-NB PDU
 @param sib2_NB Pointer (returned) to sib2_NB component withing SI-NB PDU
 @param sib3_NB Pointer (returned) to sib3_NB component withing SI-NB PDU
 @return size of encoded bit stream in bytes*/
 
-uint8_t do_SIB23_NB(uint8_t Mod_id,
-                 int CC_id,
-                rrc_eNB_carrier_data_NB_t *carrier,
-                  RrcConfigurationReq *configuration
-                );
+uint8_t do_SIB23_NB_IoT(uint8_t Mod_id,
+                        int CC_id,
+                        rrc_eNB_carrier_data_NB_IoT_t *carrier,
+                        RrcConfigurationReq *configuration
+                        );
 
 /**(UE-SIDE)
 \brief Generate an RRCConnectionRequest-NB UL-CCCH-Message (UE) based on random string or S-TMSI.  This
@@ -112,7 +106,7 @@ routine only generates an mo-data establishment cause.
 @param Mod_id
 @returns Size of encoded bit stream in bytes*/
 
-uint8_t do_RRCConnectionRequest_NB(uint8_t Mod_id, uint8_t *buffer,uint8_t *rv);
+uint8_t do_RRCConnectionRequest_NB_IoT(uint8_t Mod_id, uint8_t *buffer,uint8_t *rv);
 
 
 /**(UE -SIDE)
@@ -124,8 +118,8 @@ uint8_t do_RRCConnectionRequest_NB(uint8_t Mod_id, uint8_t *buffer,uint8_t *rv);
 @param buffer Pointer to PER-encoded ASN.1 description of UL-DCCH-Message PDU
 @returns Size of encoded bit stream in bytes*/
 
-uint8_t do_RRCConnectionSetupComplete_NB(uint8_t Mod_id, uint8_t* buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength,
-                                      const char* dedicatedInfoNAS);
+uint8_t do_RRCConnectionSetupComplete_NB_IoT(uint8_t Mod_id, uint8_t* buffer, const uint8_t Transaction_id, const int dedicatedInfoNASLength,
+                                             const char* dedicatedInfoNAS);
 
 /** (UE-SIDE)
 \brief Generate an RRCConnectionReconfigurationComplete-NB UL-DCCH-Message (UE)
@@ -134,8 +128,7 @@ uint8_t do_RRCConnectionSetupComplete_NB(uint8_t Mod_id, uint8_t* buffer, const
 @param Transaction_id
 @returns Size of encoded bit stream in bytes*/
 
-uint8_t
-do_RRCConnectionReconfigurationComplete_NB(
+uint8_t do_RRCConnectionReconfigurationComplete_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   uint8_t* buffer,
   const uint8_t Transaction_id
@@ -155,16 +148,15 @@ PhysicalConfigDedicated-NB IEs.
 @param physicalConfigDedicated_NB Pointer (returned) to PhysicalConfigDedicated-NB IE for this UE
 @returns Size of encoded bit stream in bytes*/
 
-uint8_t
-do_RRCConnectionSetup_NB(
+uint8_t do_RRCConnectionSetup_NB_IoT(
   const protocol_ctxt_t*     const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*      const ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*      const ue_context_pP,
   int                              CC_id,
   uint8_t*                   const buffer, //carrier[CC_id].Srb0.Tx_buffer.Payload
   const uint8_t                    Transaction_id,
-  const LTE_DL_FRAME_PARMS* const frame_parms, //to be changed but not deleted
-  SRB_ToAddModList_NB_r13_t**             SRB_configList_NB, //in order to be configured--> stanno puntando alla SRB_configlist dell ue_context
-  struct PhysicalConfigDedicated_NB_r13** physicalConfigDedicated_NB //in order to be configured--> stanno puntando alla physicalConfigDedicated dell ue_context
+  const NB_IoT_DL_FRAME_PARMS* const frame_parms, //to be changed but not deleted
+  SRB_ToAddModList_NB_r13_t**             SRB_configList_NB_IoT, //in order to be configured--> stanno puntando alla SRB_configlist dell ue_context
+  struct PhysicalConfigDedicated_NB_r13** physicalConfigDedicated_NB_IoT //in order to be configured--> stanno puntando alla physicalConfigDedicated dell ue_context
 );
 
 
@@ -186,16 +178,16 @@ do_RRCConnectionSetup_NB(
 @returns Size of encoded bit stream in bytes*/
 
 uint16_t
-do_RRCConnectionReconfiguration_NB(
+do_RRCConnectionReconfiguration_NB_IoT(
   const protocol_ctxt_t*        const ctxt_pP,
     uint8_t                            *buffer,
     uint8_t                             Transaction_id,
-    SRB_ToAddModList_NB_r13_t          *SRB_list_NB,
-    DRB_ToAddModList_NB_r13_t          *DRB_list_NB,
-    DRB_ToReleaseList_NB_r13_t         *DRB_list2_NB,
+    SRB_ToAddModList_NB_r13_t          *SRB_list_NB_IoT,
+    DRB_ToAddModList_NB_r13_t          *DRB_list_NB_IoT,
+    DRB_ToReleaseList_NB_r13_t         *DRB_list2_NB_IoT,
     struct PhysicalConfigDedicated_NB_r13     *physicalConfigDedicated,
     MAC_MainConfig_t                   *mac_MainConfig,
-  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13* dedicatedInfoNASList_NB);
+  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13* dedicatedInfoNASList_NB_IoT);
 
 /**
  * E-UTRAN applies the procedure as follows: when only for NB-IoT SRB1 and SRB1bis is established
@@ -207,7 +199,7 @@ do_RRCConnectionReconfiguration_NB(
  @param integrityProtAlgorithm
  */
 
-uint8_t do_SecurityModeCommand_NB(
+uint8_t do_SecurityModeCommand_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   uint8_t* const buffer,
   const uint8_t Transaction_id,
@@ -222,7 +214,7 @@ uint8_t do_SecurityModeCommand_NB(
  @param Transaction_id Transaction_ID for this message
  */
 
-uint8_t do_UECapabilityEnquiry_NB(
+uint8_t do_UECapabilityEnquiry_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   uint8_t*               const buffer,
   const uint8_t                Transaction_id
@@ -237,7 +229,7 @@ uint8_t do_UECapabilityEnquiry_NB(
 @returns Size of encoded bit stream in bytes*/
 
 uint8_t
-do_RRCConnectionReestablishmentReject_NB(
+do_RRCConnectionReestablishmentReject_NB_IoT(
     uint8_t                    Mod_id,
     uint8_t*                   const buffer);
 
@@ -248,7 +240,7 @@ do_RRCConnectionReestablishmentReject_NB(
 @param buffer Pointer to PER-encoded ASN.1 description of DL-CCCH-Message PDU
 @returns Size of encoded bit stream in bytes*/
 uint8_t
-do_RRCConnectionReject_NB(
+do_RRCConnectionReject_NB_IoT(
     uint8_t                    Mod_id,
     uint8_t*                   const buffer);
 
@@ -260,10 +252,10 @@ do_RRCConnectionReject_NB(
 @param transaction_id Transaction index
 @returns Size of encoded bit stream in bytes*/
 
-uint8_t do_RRCConnectionRelease_NB(uint8_t Mod_id, uint8_t *buffer,int Transaction_id);
+uint8_t do_RRCConnectionRelease_NB_IoT(uint8_t Mod_id, uint8_t *buffer,int Transaction_id);
 
 
-uint8_t do_DLInformationTransfer_NB(
+uint8_t do_DLInformationTransfer_NB_IoT(
 		uint8_t Mod_id,
 		uint8_t **buffer,
 		uint8_t transaction_id,
@@ -282,12 +274,12 @@ uint8_t do_DLInformationTransfer_NB(
  *
  */
 
-uint8_t do_RRCConnectionReestablishment_NB(
+uint8_t do_RRCConnectionReestablishment_NB_IoT(
 		uint8_t Mod_id,
 		uint8_t* const buffer,
 		const uint8_t     Transaction_id,
-		const LTE_DL_FRAME_PARMS* const frame_parms, //to be changed
-		SRB_ToAddModList_NB_r13_t**             SRB_configList_NB
+		const NB_IoT_DL_FRAME_PARMS* const frame_parms, //to be changed
+		SRB_ToAddModList_NB_r13_t**             SRB_configList_NB_IoT
 		 );
 
 /**
@@ -297,4 +289,4 @@ uint8_t do_RRCConnectionReestablishment_NB(
 @param transaction_id Transaction index
 @returns Size of encoded bit stream in bytes*/
 
-uint8_t do_RRCConnectionRelease_NB(uint8_t Mod_id, uint8_t *buffer,int Transaction_id);
+//uint8_t do_RRCConnectionRelease_NB_IoT(uint8_t Mod_id, uint8_t *buffer,int Transaction_id);
diff --git a/openair2/RRC/LITE/MESSAGES/asn1_msg_nb_iot.c b/openair2/RRC/LITE/MESSAGES/asn1_msg_nb_iot.c
deleted file mode 100644
index 6dc3be4fb2fa33da6a756a33025cbcfef64858ec..0000000000000000000000000000000000000000
--- a/openair2/RRC/LITE/MESSAGES/asn1_msg_nb_iot.c
+++ /dev/null
@@ -1,1593 +0,0 @@
-/* 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.0  (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 asn1_msg.c
-* \brief primitives to build the asn1 messages
-* \author Raymond Knopp, Navid Nikaein and Michele Paffetti
-* \date 2011, 2017
-* \version 1.0
-* \company Eurecom
-* \email: raymond.knopp@eurecom.fr, navid.nikaein@eurecom.fr, michele.paffetti@studio.unibo.it
-*/
-
-#ifdef USER_MODE
-#include <stdio.h>
-#include <sys/types.h>
-#include <stdlib.h> /* for atoi(3) */
-#include <unistd.h> /* for getopt(3) */
-#include <string.h> /* for strerror(3) */
-#include <sysexits.h> /* for EX_* exit codes */
-#include <errno.h>  /* for errno */
-#else
-#include <linux/module.h>  /* Needed by all modules */
-#endif
-#ifdef USER_MODE
-//#include "RRC/LITE/defs.h"
-//#include "COMMON/mac_rrc_primitives.h"
-#include "UTIL/LOG/log.h"
-#endif
-#include <asn_application.h>
-#include <asn_internal.h> /* for _ASN_DEFAULT_STACK_MAX */
-#include <per_encoder.h>
-
-#include "assertions.h"
-//#include "RRCConnectionRequest.h"
-//#include "UL-CCCH-Message.h"
-//#include "UL-DCCH-Message.h"
-//#include "DL-CCCH-Message.h"
-//#include "DL-DCCH-Message.h"
-//#include "EstablishmentCause.h"
-//#include "RRCConnectionSetup.h"
-//#include "SRB-ToAddModList.h"
-//#include "DRB-ToAddModList.h"
-//#if defined(Rel10) || defined(Rel14)
-//#include "MCCH-Message.h"
-////#define MRB1 1
-//#endif
-
-//#include "RRC/LITE/defs.h"
-//#include "RRCConnectionSetupComplete.h"
-//#include "RRCConnectionReconfigurationComplete.h"
-//#include "RRCConnectionReconfiguration.h"
-//#include "MasterInformationBlock.h"
-//#include "SystemInformation.h"
-//#include "SystemInformationBlockType1.h"
-//#include "SIB-Type.h"
-//#include "BCCH-DL-SCH-Message.h"
-
-//#include for NB-IoT-------------------
-#include "RRCConnectionRequest-NB.h"
-#include "BCCH-DL-SCH-Message-NB.h"
-#include "UL-CCCH-Message-NB.h"
-#include "UL-DCCH-Message-NB.h"
-#include "DL-CCCH-Message-NB.h"
-#include "DL-DCCH-Message-NB.h"
-#include "EstablishmentCause-NB-r13.h"
-#include "RRCConnectionSetup-NB.h"
-#include "SRB-ToAddModList-NB-r13.h"
-#include "DRB-ToAddModList-NB-r13.h"
-#include "RRC/LITE/defs_nb_iot.h"
-#include "RRCConnectionSetupComplete-NB.h"
-#include "RRCConnectionReconfigurationComplete-NB.h"
-#include "RRCConnectionReconfiguration-NB.h"
-#include "MasterInformationBlock-NB.h"
-#include "SystemInformation-NB.h"
-#include "SystemInformationBlockType1.h"
-#include "SIB-Type-NB-r13.h"
-#include "RRCConnectionResume-NB.h"
-#include "RRCConnectionReestablishment-NB.h"
-//----------------------------------------
-
-#include "PHY/defs.h"
-
-//#include "MeasObjectToAddModList.h"
-//#include "ReportConfigToAddModList.h"
-//#include "MeasIdToAddModList.h"
-#include "enb_config.h"
-
-#if defined(ENABLE_ITTI)
-# include "intertask_interface.h"
-#endif
-
-#ifndef USER_MODE
-#define msg printk
-#ifndef errno
-int errno;
-#endif
-#else
-# if !defined (msg)
-#   define msg printf
-# endif
-#endif
-
-
-
-//Not touched
-//#define XER_PRINT
-extern Enb_properties_array_t enb_properties;
-typedef struct xer_sprint_string_s {
-  char *string;
-  size_t string_size;
-  size_t string_index;
-} xer_sprint_string_t;
-
-extern unsigned char NB_eNB_INST;
-extern uint8_t usim_test;
-
-uint16_t two_tier_hexagonal_cellIds[7] = {0,1,2,4,5,7,8};
-uint16_t two_tier_hexagonal_adjacent_cellIds[7][6] = {{1,2,4,5,7,8},    // CellId 0
-  {11,18,2,0,8,15}, // CellId 1
-  {18,13,3,4,0,1},  // CellId 2
-  {2,3,14,6,5,0},   // CellId 4
-  {0,4,6,16,9,7},   // CellId 5
-  {8,0,5,9,17,12},  // CellId 7
-  {15,1,0,7,12,10}
-};// CellId 8
-
-/*
- * This is a helper function for xer_sprint, which directs all incoming data
- * into the provided string.
- */
-static int xer__print2s (const void *buffer, size_t size, void *app_key)
-{
-  xer_sprint_string_t *string_buffer = (xer_sprint_string_t *) app_key;
-  size_t string_remaining = string_buffer->string_size - string_buffer->string_index;
-
-  if (string_remaining > 0) {
-    if (size > string_remaining) {
-      size = string_remaining;
-    }
-
-    memcpy(&string_buffer->string[string_buffer->string_index], buffer, size);
-    string_buffer->string_index += size;
-  }
-
-  return 0;
-}
-
-int xer_sprint (char *string, size_t string_size, asn_TYPE_descriptor_t *td, void *sptr)
-{
-  asn_enc_rval_t er;
-  xer_sprint_string_t string_buffer;
-
-  string_buffer.string = string;
-  string_buffer.string_size = string_size;
-  string_buffer.string_index = 0;
-
-  er = xer_encode(td, sptr, XER_F_BASIC, xer__print2s, &string_buffer);
-
-  if (er.encoded < 0) {
-    LOG_E(RRC, "xer_sprint encoding error (%d)!", er.encoded);
-    er.encoded = string_buffer.string_size;
-  } else {
-    if (er.encoded > string_buffer.string_size) {
-      LOG_E(RRC, "xer_sprint string buffer too small, got %d need %d!", string_buffer.string_size, er.encoded);
-      er.encoded = string_buffer.string_size;
-    }
-  }
-
-  return er.encoded;
-}
-
-uint16_t get_adjacent_cell_id(uint8_t Mod_id,uint8_t index)
-{
-  return(two_tier_hexagonal_adjacent_cellIds[Mod_id][index]);
-}
-/* This only works for the hexagonal topology...need a more general function for other topologies */
-
-uint8_t get_adjacent_cell_mod_id(uint16_t phyCellId)
-{
-  uint8_t i;
-
-  for(i=0; i<7; i++) {
-    if(two_tier_hexagonal_cellIds[i] == phyCellId) {
-      return i;
-    }
-  }
-
-  LOG_E(RRC,"\nCannot get adjacent cell mod id! Fatal error!\n");
-  return 0xFF; //error!
-}
-
-/*do_MIB_NB*/ //FIXME: to decide lots of things
-uint8_t do_MIB_NB(
-		rrc_eNB_carrier_data_NB_t *carrier,
-		uint16_t N_RB_DL,//may not needed--> for NB_IoT only 1 PRB is used
-		uint32_t frame)
-{
-  asn_enc_rval_t enc_rval;
-  BCCH_BCH_Message_NB_t *mib_NB = &(carrier->mib_NB);
-
-  uint8_t sfn_MSB = (uint8_t)((frame>>2)&0xff); //4 bits FIXME
-  uint8_t hsfn_LSB = (uint8_t)((frame>>2)&0xff); //2 bits
-  uint16_t spare=0; //11 bits --> use uint16
-
-  //no DL_Bandwidth, no PCHIC
-
-  mib_NB->message.systemFrameNumber_MSB_r13.buf = &sfn_MSB;
-  mib_NB->message.systemFrameNumber_MSB_r13.size = 1; //if expressed in byte
-  mib_NB->message.systemFrameNumber_MSB_r13.bits_unused = 4;
-
-  mib_NB->message.hyperSFN_LSB_r13.buf= &hsfn_LSB;
-  mib_NB->message.hyperSFN_LSB_r13.size= 1;
-  mib_NB->message.hyperSFN_LSB_r13.bits_unused = 6;
-
-  mib_NB->message.spare.buf = (uint8_t *)&spare; //left the pointer to type uint8?
-  mib_NB->message.spare.size = 2;
-  mib_NB->message.spare.bits_unused = 5;
-
-  //decide how to set it
-  mib_NB->message.schedulingInfoSIB1_r13 =0; //see TS 36.213-->tables 16.4.1.3-3 ecc...
-  mib_NB->message.systemInfoValueTag_r13= 0;
-  mib_NB->message.ab_Enabled_r13 = 0;
-
-  //to be decided
-  mib_NB->message.operationModeInfo_r13.present = MasterInformationBlock_NB__operationModeInfo_r13_PR_inband_SamePCI_r13;
-  mib_NB->message.operationModeInfo_r13.choice.inband_SamePCI_r13.eutra_CRS_SequenceInfo_r13 = 0;
-
-
-  printf("[MIB] something to write HERE ,sfn_MSB %x, hsfn_LSB %x\n",
-         (uint32_t)sfn_MSB,
-		 (uint32_t)hsfn_LSB);
-
-  //only changes in "asn_DEF_BCCH_BCH_Message_NB"
-  enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_BCH_Message_NB,
-                                   (void*)mib_NB,
-                                   carrier->MIB_NB,
-                                   100);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-  if (enc_rval.encoded==-1) {
-    return(-1);
-  }
-
-  return((enc_rval.encoded+7)/8);
-  /*
-  printf("MIB: %x ((MIB>>10)&63)+(MIB&3<<6)=SFN %x, MIB>>2&3 = phich_resource %d, MIB>>4&1 = phich_duration %d, MIB>>5&7 = system_bandwidth %d)\n",*(uint32_t *)buffer,
-   (((*(uint32_t *)buffer)>>10)&0x3f)+(((*(uint32_t *)buffer)&3)<<6),
-   ((*(uint32_t *)buffer)>>2)&0x3,
-   ((*(uint32_t *)buffer)>>4)&0x1,
-   ((*(uint32_t *)buffer)>>5)&0x7
-   );
-  */
-}
-
-/*do_SIB1_NB*/
-uint8_t do_SIB1_NB(uint8_t Mod_id, int CC_id,
-				rrc_eNB_carrier_data_NB_t *carrier,
-                RrcConfigurationReq *configuration
-               )
-{
-  BCCH_DL_SCH_Message_NB_t *bcch_message= &(carrier->siblock1_NB);
-  SystemInformationBlockType1_NB_t *sib1_NB;
-
-  asn_enc_rval_t enc_rval;
-
-  PLMN_IdentityInfo_NB_r13_t PLMN_identity_info_NB;
-  MCC_MNC_Digit_t dummy_mcc[3],dummy_mnc[3];
-  SchedulingInfo_NB_r13_t schedulingInfo_NB;
-  SIB_Type_NB_r13_t sib_type_NB;
-
-  //New parameters
-  //uint8_t hyperSFN_MSB_r13 ?? (BITSTRING)
-
-  long* attachWithoutPDN_Connectivity = NULL;
-  attachWithoutPDN_Connectivity = CALLOC(1,sizeof(long));
-  long *nrs_CRS_PowerOffset=NULL;
-  nrs_CRS_PowerOffset = CALLOC(1, sizeof(long));
-  long *eutraControlRegionSize=NULL;
-   eutraControlRegionSize = CALLOC(1,sizeof(long));
-  long systemInfoValueTagSI = 0;
-
-  memset(bcch_message,0,sizeof(BCCH_DL_SCH_Message_NB_t));
-  bcch_message->message.present = BCCH_DL_SCH_MessageType_NB_PR_c1;
-  bcch_message->message.choice.c1.present = BCCH_DL_SCH_MessageType_NB__c1_PR_systemInformationBlockType1_r13;
-
-  //allocation
-  carrier->sib1_NB = &bcch_message->message.choice.c1.choice.systemInformationBlockType1_r13;
-  sib1_NB = carrier->sib1_NB;
-
-  memset(&PLMN_identity_info_NB,0,sizeof(PLMN_IdentityInfo_NB_r13_t));
-  memset(&schedulingInfo_NB,0,sizeof(SchedulingInfo_NB_r13_t));
-  memset(&sib_type_NB,0,sizeof(SIB_Type_NB_r13_t));
-
-
-  PLMN_identity_info_NB.plmn_Identity_r13.mcc = CALLOC(1,sizeof(*PLMN_identity_info_NB.plmn_Identity_r13.mcc));
-  memset(PLMN_identity_info_NB.plmn_Identity_r13.mcc,0,sizeof(*PLMN_identity_info_NB.plmn_Identity_r13.mcc));
-
-  asn_set_empty(&PLMN_identity_info_NB.plmn_Identity_r13.mcc->list);//.size=0;
-
-  //left as it is???
-#if defined(ENABLE_ITTI)
-  dummy_mcc[0] = (configuration->mcc / 100) % 10;
-  dummy_mcc[1] = (configuration->mcc / 10) % 10;
-  dummy_mcc[2] = (configuration->mcc / 1) % 10;
-#else
-  dummy_mcc[0] = 0;
-  dummy_mcc[1] = 0;
-  dummy_mcc[2] = 1;
-#endif
-  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB.plmn_Identity_r13.mcc->list,&dummy_mcc[0]);
-  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB.plmn_Identity_r13.mcc->list,&dummy_mcc[1]);
-  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB.plmn_Identity_r13.mcc->list,&dummy_mcc[2]);
-
-  PLMN_identity_info_NB.plmn_Identity_r13.mnc.list.size=0;
-  PLMN_identity_info_NB.plmn_Identity_r13.mnc.list.count=0;
-
-  //FIXME
-#if defined(ENABLE_ITTI)
-
-  if (configuration->mnc >= 100) {
-    dummy_mnc[0] = (configuration->mnc / 100) % 10;
-    dummy_mnc[1] = (configuration->mnc / 10) % 10;
-    dummy_mnc[2] = (configuration->mnc / 1) % 10;
-  } else {
-    if (configuration->mnc_digit_length == 2) {
-      dummy_mnc[0] = (configuration->mnc / 10) % 10;
-      dummy_mnc[1] = (configuration->mnc / 1) % 10;
-      dummy_mnc[2] = 0xf;
-    } else {
-      dummy_mnc[0] = (configuration->mnc / 100) % 100;
-      dummy_mnc[1] = (configuration->mnc / 10) % 10;
-      dummy_mnc[2] = (configuration->mnc / 1) % 10;
-    }
-  }
-
-#else
-  dummy_mnc[0] = 0;
-  dummy_mnc[1] = 1;
-  dummy_mnc[2] = 0xf;
-#endif
-  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB.plmn_Identity_r13.mnc.list,&dummy_mnc[0]);
-  ASN_SEQUENCE_ADD(&PLMN_identity_info_NB.plmn_Identity_r13.mnc.list,&dummy_mnc[1]);
-
-  if (dummy_mnc[2] != 0xf) {
-    ASN_SEQUENCE_ADD(&PLMN_identity_info_NB.plmn_Identity_r13.mnc.list,&dummy_mnc[2]);
-  }
-
-  //still set to "notReserved" as in the previous case
-  PLMN_identity_info_NB.cellReservedForOperatorUse_r13=PLMN_IdentityInfo_NB_r13__cellReservedForOperatorUse_r13_notReserved;
-
-  *attachWithoutPDN_Connectivity = 0;
-  PLMN_identity_info_NB.attachWithoutPDN_Connectivity_r13 = attachWithoutPDN_Connectivity;
-
-  ASN_SEQUENCE_ADD(&sib1_NB->cellAccessRelatedInfo_r13.plmn_IdentityList_r13.list,&PLMN_identity_info_NB);
-
-  // 16 bits = 2 byte
-  sib1_NB->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf = MALLOC(2); //MALLOC works in byte
-
-  //lefts as it is?
-#if defined(ENABLE_ITTI)
-  sib1_NB->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[0] = (configuration->tac >> 8) & 0xff;
-  sib1_NB->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[1] = (configuration->tac >> 0) & 0xff;
-#else
-  sib1_NB->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[0] = 0x00;
-  sib1_NB->cellAccessRelatedInfo_r13.trackingAreaCode_r13.buf[1] = 0x01;
-#endif
-  sib1_NB->cellAccessRelatedInfo_r13.trackingAreaCode_r13.size=2;
-  sib1_NB->cellAccessRelatedInfo_r13.trackingAreaCode_r13.bits_unused=0;
-
-  // 28 bits --> i have to use 32 bits = 4 byte
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf = MALLOC(8); // why allocate 8 byte?
-#if defined(ENABLE_ITTI)
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[0] = (configuration->cell_identity >> 20) & 0xff;
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[1] = (configuration->cell_identity >> 12) & 0xff;
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[2] = (configuration->cell_identity >>  4) & 0xff;
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[3] = (configuration->cell_identity <<  4) & 0xf0;
-#else
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[0] = 0x00;
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[1] = 0x00;
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[2] = 0x00;
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.buf[3] = 0x10;
-#endif
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.size=4;
-  sib1_NB->cellAccessRelatedInfo_r13.cellIdentity_r13.bits_unused=4;
-
-  //Still set to "notBarred" as in the previous case
-  sib1_NB->cellAccessRelatedInfo_r13.cellBarred_r13=SystemInformationBlockType1_NB__cellAccessRelatedInfo_r13__cellBarred_r13_notBarred;
-
-  //Still Set to "notAllowed" like in the previous case
-  sib1_NB->cellAccessRelatedInfo_r13.intraFreqReselection_r13=SystemInformationBlockType1_NB__cellAccessRelatedInfo_r13__intraFreqReselection_r13_notAllowed;
-
-
-  sib1_NB->cellSelectionInfo_r13.q_RxLevMin_r13=-65; //which value?? TS 36.331 V14.2.1 pag. 589
-  sib1_NB->cellSelectionInfo_r13.q_QualMin_r13 = 0; // FIXME new parameter for SIB1-NB, not present in SIB1
-
-  sib1_NB->p_Max_r13 = CALLOC(1, sizeof(P_Max_t));
-  *(sib1_NB->p_Max_r13) = 23;
-
-  //FIXME
-  sib1_NB->freqBandIndicator_r13 =
-#if defined(ENABLE_ITTI)
-    configuration->eutra_band[CC_id];
-#else
-    7; // UL:2500 MHz–2570 MHz	DL:2620 MHz	–2690 MHz	mode:FDD
-       //FIXME For NB-IoT depends on the operation mode (in/out/guard band) and also, not all PRBs are allowed ?
-#endif
-
-    //OPTIONAL new parameters, to be used?
-      /*
-       * freqBandInfo_r13
-       * multiBandInfoList_r13
-       * nrs_CRS_PowerOffset_r13
-       * sib1_NB->downlinkBitmap_r13.choice.subframePattern10_r13 =(is a BIT_STRING)
-       */
-
-   sib1_NB->downlinkBitmap_r13 = CALLOC(1, sizeof(struct DL_Bitmap_NB_r13));
-   (sib1_NB->downlinkBitmap_r13)->present= DL_Bitmap_NB_r13_PR_NOTHING;
-
-   *eutraControlRegionSize = 0;
-   sib1_NB->eutraControlRegionSize_r13 = eutraControlRegionSize;
-
-
-   *nrs_CRS_PowerOffset= 0;
-   sib1_NB->nrs_CRS_PowerOffset_r13 = nrs_CRS_PowerOffset;
-
-
-  //FIXME which value to set?
-  schedulingInfo_NB.si_Periodicity_r13=SchedulingInfo_NB_r13__si_Periodicity_r13_rf64;
-  schedulingInfo_NB.si_RepetitionPattern_r13=SchedulingInfo_NB_r13__si_RepetitionPattern_r13_every2ndRF; //This Indicates the starting radio frames within the SI window used for SI message transmission.
-  schedulingInfo_NB.si_TB_r13= SchedulingInfo_NB_r13__si_TB_r13_b56; //in 2 subframe = 2ms (pag 590 TS 36.331)
-
-  // This is for SIB2/3
-  /*SIB3 --> There is no mapping information of SIB2 since it is always present
-    *  in the first SystemInformation message
-    * listed in the schedulingInfoList list.
-    * */
-  sib_type_NB=SIB_Type_NB_r13_sibType3_NB_r13;
-
-  ASN_SEQUENCE_ADD(&schedulingInfo_NB.sib_MappingInfo_r13.list,&sib_type_NB);
-  ASN_SEQUENCE_ADD(&sib1_NB->schedulingInfoList_r13.list,&schedulingInfo_NB);
-
-#if defined(ENABLE_ITTI)
-
-  if (configuration->frame_type[CC_id] == TDD)
-#endif
-  {
-	//FIXME in NB-IoT mandatory to be FDD --> so must give an error
-	  LOG_E(RRC,"[eNB %d] Frame Type is TDD --> not supported by NB-IoT, exiting\n", Mod_id); //correct?
-	  exit(-1);
-  }
-
-  //FIXME which value chose for the following parameter
-  sib1_NB->si_WindowLength_r13=SystemInformationBlockType1_NB__si_WindowLength_r13_ms160;
-  sib1_NB->si_RadioFrameOffset_r13= 0;
-
-  /*In Nb-IoT change/update of specific SI message can additionally be indicated by a SI message specific value tag
-   * systemInfoValueTagSI (there is no SystemInfoValueTag in SIB1-NB but only in MIB-NB)
-   *contained in systemInfoValueTagList_r13
-   **/
-  //FIXME correct?
-  sib1_NB->systemInfoValueTagList_r13 = CALLOC(1, sizeof(struct SystemInfoValueTagList_NB_r13));
-  asn_set_empty(&sib1_NB->systemInfoValueTagList_r13->list);
-  ASN_SEQUENCE_ADD(&sib1_NB->systemInfoValueTagList_r13->list,&systemInfoValueTagSI);
-
-
-#ifdef XER_PRINT //generate xml files
-  xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
-#endif
-
-
-  enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_DL_SCH_Message_NB,
-                                   (void*)bcch_message,
-                                   carrier->SIB1_NB,
-                                   100);
-
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-
-#ifdef USER_MODE
-  LOG_D(RRC,"[eNB] SystemInformationBlockType1-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
-#endif
-
-  if (enc_rval.encoded==-1) {
-    return(-1);
-  }
-
-  return((enc_rval.encoded+7)/8);
-}
-
-/*SIB23_NB*/
-//to be clarified is it is possible to carry SIB2 and SIB3  in the same SI message for NB-IoT?
-uint8_t do_SIB23_NB(uint8_t Mod_id,
-                 int CC_id,
-                 rrc_eNB_carrier_data_NB_t *carrier,
-                 RrcConfigurationReq *configuration )
-{
-  struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member *sib2_NB_part;
-  struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member *sib3_NB_part;
-
-  BCCH_DL_SCH_Message_NB_t *bcch_message = &(carrier->systemInformation_NB); //is the systeminformation-->BCCH_DL_SCH_Message_NB
-  SystemInformationBlockType2_NB_r13_t *sib2_NB;
-  SystemInformationBlockType3_NB_r13_t *sib3_NB;
-
-  asn_enc_rval_t enc_rval;
-  RACH_Info_NB_r13_t rach_Info_NB;
-  NPRACH_Parameters_NB_r13_t nprach_parameters;
-
-  //new
-  long *connEstFailOffset = NULL;
-  connEstFailOffset = CALLOC(1, sizeof(long));
-
-  RSRP_ThresholdsNPRACH_InfoList_NB_r13_t *rsrp_ThresholdsPrachInfoList;
-  RSRP_Range_t rsrp_range;
-  ACK_NACK_NumRepetitions_NB_r13_t ack_nack_repetition;
-
-  long *srs_SubframeConfig;
-  srs_SubframeConfig= CALLOC(1, sizeof(long));
-
-
-  if (bcch_message) {
-    memset(bcch_message,0,sizeof(BCCH_DL_SCH_Message_NB_t));
-  } else {
-    LOG_E(RRC,"[eNB %d] BCCH_MESSAGE_NB is null, exiting\n", Mod_id);
-    exit(-1);
-  }
-
-  //before schould be allocated memory somewhere?
-  if (!carrier->sib2_NB) {
-    LOG_E(RRC,"[eNB %d] sib2_NB is null, exiting\n", Mod_id);
-    exit(-1);
-  }
-
-  if (!carrier->sib3_NB) {
-    LOG_E(RRC,"[eNB %d] sib3_NB is null, exiting\n", Mod_id);
-    exit(-1);
-  }
-
-
-  LOG_I(RRC,"[eNB %d] Configuration SIB2/3\n", Mod_id);
-
-  sib2_NB_part = CALLOC(1,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
-  sib3_NB_part = CALLOC(1,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
-  memset(sib2_NB_part,0,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
-  memset(sib3_NB_part,0,sizeof(struct SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member));
-
-  sib2_NB_part->present = SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member_PR_sib2_r13;
-  sib3_NB_part->present = SystemInformation_NB_r13_IEs__sib_TypeAndInfo_r13__Member_PR_sib3_r13;
-
-  //FIXME: may a bug?
-  carrier->sib2_NB = &sib2_NB_part->choice.sib2_r13;
-  carrier->sib3_NB = &sib3_NB_part->choice.sib3_r13;
-  sib2_NB = carrier->sib2_NB;
-  sib3_NB = carrier->sib3_NB;
-
-
-/// SIB2-NB-----------------------------------------
-
-  //Barring is manage by ab-Enabled in MIB-NB (but is not a struct as ac-BarringInfo)
-
-  sib2_NB->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.preambleTransMax_CE_r13 =
-   		  configuration->preambleTransMax_CE_NB[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.powerRampingParameters_r13.powerRampingStep =
-	configuration->rach_powerRampingStep_NB[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.powerRampingParameters_r13.preambleInitialReceivedTargetPower =
-    configuration->rach_preambleInitialReceivedTargetPower_NB[CC_id];
-
-  rach_Info_NB.ra_ResponseWindowSize_r13 = configuration->rach_raResponseWindowSize_NB[CC_id];
-  rach_Info_NB.mac_ContentionResolutionTimer_r13 = configuration-> rach_macContentionResolutionTimer_NB[CC_id];
-  //initialize this list? how to use it? correct?
-  ASN_SEQUENCE_ADD(&sib2_NB->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.rach_InfoList_r13.list,&rach_Info_NB);
-
-  //new parameter
-  *connEstFailOffset = 0;
-   sib2_NB->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.connEstFailOffset_r13 = connEstFailOffset;
-
-
-  // BCCH-Config-NB-IoT
-  sib2_NB->radioResourceConfigCommon_r13.bcch_Config_r13.modificationPeriodCoeff_r13
-    = configuration->bcch_modificationPeriodCoeff_NB[CC_id];
-
-  // PCCH-Config-NB-IoT
-  sib2_NB->radioResourceConfigCommon_r13.pcch_Config_r13.defaultPagingCycle_r13
-    = configuration->pcch_defaultPagingCycle_NB[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.pcch_Config_r13.nB_r13 = configuration->pcch_nB_NB[CC_id];
-  //new
-  sib2_NB->radioResourceConfigCommon_r13.pcch_Config_r13.npdcch_NumRepetitionPaging_r13 = configuration-> pcch_npdcch_NumRepetitionPaging_NB[CC_id];
-
-  //NPRACH-Config-NB-IoT
-  sib2_NB->radioResourceConfigCommon_r13.nprach_Config_r13.nprach_CP_Length_r13 = configuration->nprach_CP_Length[CC_id];
-
-  //new
-
-   sib2_NB->radioResourceConfigCommon_r13.nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13 =
-		   CALLOC(1, sizeof(struct RSRP_ThresholdsNPRACH_InfoList_NB_r13)); //fatto uguale dopo
-   rsrp_ThresholdsPrachInfoList = sib2_NB->radioResourceConfigCommon_r13.nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13;
-   rsrp_range = configuration->nprach_rsrp_range_NB;
-   ASN_SEQUENCE_ADD(&rsrp_ThresholdsPrachInfoList->list,rsrp_range);
-
-  nprach_parameters.nprach_Periodicity_r13 = configuration->nprach_Periodicity[CC_id];
-  nprach_parameters.nprach_StartTime_r13 = configuration->nprach_StartTime[CC_id];
-  nprach_parameters.nprach_SubcarrierOffset_r13 = configuration->nprach_SubcarrierOffset[CC_id];
-  nprach_parameters.nprach_NumSubcarriers_r13= configuration->nprach_NumSubcarriers[CC_id];
-  nprach_parameters.nprach_SubcarrierMSG3_RangeStart_r13= configuration->nprach_SubcarrierMSG3_RangeStart[CC_id];
-  nprach_parameters.maxNumPreambleAttemptCE_r13= configuration->maxNumPreambleAttemptCE_NB[CC_id];
-  nprach_parameters.numRepetitionsPerPreambleAttempt_r13 = configuration->numRepetitionsPerPreambleAttempt_NB[CC_id];
-  nprach_parameters.npdcch_NumRepetitions_RA_r13 = configuration->npdcch_NumRepetitions_RA[CC_id];
-  nprach_parameters.npdcch_StartSF_CSS_RA_r13= configuration->npdcch_StartSF_CSS_RA[CC_id];
-  nprach_parameters.npdcch_Offset_RA_r13= configuration->npdcch_Offset_RA[CC_id];
-
-  //FIXME check if nprach parameter is added properly to the list
-  ASN_SEQUENCE_ADD(&sib2_NB->radioResourceConfigCommon_r13.nprach_Config_r13.nprach_ParametersList_r13.list,&nprach_parameters);
-
-  // NPDSCH-Config NB-IOT
-  sib2_NB->radioResourceConfigCommon_r13.npdsch_ConfigCommon_r13.nrs_Power_r13= configuration->npdsch_nrs_Power[CC_id];
-
-
-  //NPUSCH-Config NB-IoT
-  //new
-  ack_nack_repetition = configuration-> npusch_ack_nack_numRepetitions_NB[CC_id]; //is an enumerative
-  ASN_SEQUENCE_ADD(&sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ack_NACK_NumRepetitions_Msg4_r13.list,ack_nack_repetition);
-
-  *srs_SubframeConfig = configuration->npusch_srs_SubframeConfig_NB[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.srs_SubframeConfig_r13= srs_SubframeConfig;
-
-
-  //new (occhio che dmrs_config_r13 è un puntatore quando lo richiami)
-  sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13 =configuration->npusch_threeTone_CyclicShift_r13[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13 = configuration->npusch_sixTone_CyclicShift_r13[CC_id];
-
-  /*
-    * threeTone_BaseSequence_r13
-    * sixTone_BaseSequence_r13
-    * twelveTone_BaseSequence_r13
-    */
-
-  sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13= configuration->npusch_groupHoppingEnabled[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13 =configuration->npusch_groupAssignmentNPUSCH_r13[CC_id];
-
-
-  // PUCCH-Config NB-IoT
- /*
-  * all data are sent over the NPUSCH. This includes also the UL control information (UCI),
-  * which is transmitted using a different format. Consequently there is no equivalent to the PUCCH of LTE in NB-IoT.
-  */
-
-  //New: DL_GapConfig
-  sib2_NB->radioResourceConfigCommon_r13.dl_Gap_r13->dl_GapDurationCoeff_r13= configuration-> dl_GapDurationCoeff_NB[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.dl_Gap_r13->dl_GapPeriodicity_r13= configuration->dl_GapPeriodicity_NB[CC_id];
-  sib2_NB->radioResourceConfigCommon_r13.dl_Gap_r13->dl_GapThreshold_r13= configuration->dl_GapThreshold_NB[CC_id];
-
-  // SRS Config --May not implemented in NB-IoT!
-
-  // uplinkPowerControlCommon - NB-IoT
-  sib2_NB->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.p0_NominalNPUSCH_r13 = configuration->npusch_p0_NominalNPUSCH_r13;
-  sib2_NB->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.deltaPreambleMsg3_r13 = configuration->deltaPreambleMsg3_r13;
-  sib2_NB->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.alpha_r13 = configuration->npusch_alpha_r13;
-  //no deltaFlist_PUCCH and no UL cyclic prefix
-
-  // UE Timers and Constants -NB-IoT
-  sib2_NB->ue_TimersAndConstants_r13.t300_r13 = configuration-> ue_TimersAndConstants_t300_NB[CC_id];
-  sib2_NB->ue_TimersAndConstants_r13.t301_r13 = configuration-> ue_TimersAndConstants_t301_NB[CC_id];
-  sib2_NB->ue_TimersAndConstants_r13.t310_r13 = configuration-> ue_TimersAndConstants_t310_NB[CC_id];
-  sib2_NB->ue_TimersAndConstants_r13.t311_r13 = configuration-> ue_TimersAndConstants_t311_NB[CC_id];
-  sib2_NB->ue_TimersAndConstants_r13.n310_r13 = configuration-> ue_TimersAndConstants_n310_NB[CC_id];
-  sib2_NB->ue_TimersAndConstants_r13.n311_r13 = configuration-> ue_TimersAndConstants_n311_NB[CC_id];
-
- /*FIXME:static assignment will be not used
-
-
-
-  	//RACH-Config-NB-IoT
-  	//no numberOfRA_Preambles
-    //no preamblesGroupAConfig..
-    //no maxHARQ_Msg3Tx
-
-    (*sib2_NB)->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.preambleTransMax_CE_r13 = PreambleTransMax_n10; //problem
-    (*sib2_NB)->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.powerRampingParameters_r13.powerRampingStep =
-    		PowerRampingParameters__powerRampingStep_dB2;
-    (*sib2_NB)->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.powerRampingParameters_r13.preambleInitialReceivedTargetPower =
-    		PowerRampingParameters__preambleInitialReceivedTargetPower_dBm_100;
-
-    //valori a caso
-    rach_Info_NB.ra_ResponseWindowSize_r13 = RACH_Info_NB_r13__ra_ResponseWindowSize_r13_pp2; //pp = PDCCH periods (pag 614)
-    rach_Info_NB.mac_ContentionResolutionTimer_r13 = RACH_Info_NB_r13__mac_ContentionResolutionTimer_r13_pp1;
-    ASN_SEQUENCE_ADD(&(*sib2_NB)->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.rach_InfoList_r13.list,rach_Info_NB);
-
-    *connEstFailOffset= 0;
-    (*sib2_NB)->radioResourceConfigCommon_r13.rach_ConfigCommon_r13.connEstFailOffset_r13 = connEstFailOffset;
-
-    // BCCH-Config-NB-IoT
-    (*sib2_NB)->radioResourceConfigCommon_r13.bcch_Config_r13.modificationPeriodCoeff_r13= BCCH_Config_NB_r13__modificationPeriodCoeff_r13_n16;
-
-    // PCCH-Config-NB-IoT
-    (*sib2_NB)->radioResourceConfigCommon_r13.pcch_Config_r13.defaultPagingCycle_r13 = PCCH_Config_NB_r13__defaultPagingCycle_r13_rf128;
-    (*sib2_NB)->radioResourceConfigCommon_r13.pcch_Config_r13.nB_r13 = PCCH_Config_NB_r13__nB_r13_oneT;
-    (*sib2_NB)->radioResourceConfigCommon_r13.pcch_Config_r13.npdcch_NumRepetitionPaging_r13 = PCCH_Config_NB_r13__npdcch_NumRepetitionPaging_r13_r1;
-
-    //NPRACH-Config-NB-IoT
-    (*sib2_NB)->radioResourceConfigCommon_r13.nprach_Config_r13.nprach_CP_Length_r13 = NPRACH_ConfigSIB_NB_r13__nprach_CP_Length_r13_us66dot7; //66.7 microsec
-
-    (*sib2_NB)->radioResourceConfigCommon_r13.nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13 =
-    		CALLOC(1, sizeof(struct RSRP_ThresholdsNPRACH_InfoList_NB_r13));
-    rsrp_ThresholdsPrachInfoList = (*sib2_NB)->radioResourceConfigCommon_r13.nprach_Config_r13.rsrp_ThresholdsPrachInfoList_r13;
-    rsrp_range = 0;
-    ASN_SEQUENCE_ADD(&rsrp_ThresholdsPrachInfoList->list,rsrp_range);
-
-    //totalmente a caso
-      nprach_parameters->nprach_Periodicity_r13 = NPRACH_Parameters_NB_r13__nprach_Periodicity_r13_ms40;
-      nprach_parameters->nprach_StartTime_r13 = NPRACH_Parameters_NB_r13__nprach_StartTime_r13_ms8;
-      nprach_parameters->nprach_SubcarrierOffset_r13 = NPRACH_Parameters_NB_r13__nprach_SubcarrierOffset_r13_n0;
-      nprach_parameters->nprach_NumSubcarriers_r13= NPRACH_Parameters_NB_r13__nprach_NumSubcarriers_r13_n12;
-      nprach_parameters->nprach_SubcarrierMSG3_RangeStart_r13= NPRACH_Parameters_NB_r13__nprach_SubcarrierMSG3_RangeStart_r13_zero;
-      nprach_parameters->maxNumPreambleAttemptCE_r13= NPRACH_Parameters_NB_r13__maxNumPreambleAttemptCE_r13_n3;
-      nprach_parameters->numRepetitionsPerPreambleAttempt_r13 = NPRACH_Parameters_NB_r13__numRepetitionsPerPreambleAttempt_r13_n1;
-      nprach_parameters->npdcch_NumRepetitions_RA_r13 = NPRACH_Parameters_NB_r13__npdcch_NumRepetitions_RA_r13_r1;
-      nprach_parameters->npdcch_StartSF_CSS_RA_r13= NPRACH_Parameters_NB_r13__npdcch_StartSF_CSS_RA_r13_v1dot5;
-      nprach_parameters->npdcch_Offset_RA_r13= NPRACH_Parameters_NB_r13__npdcch_Offset_RA_r13_zero;
-      ASN_SEQUENCE_ADD(&(*sib2_NB)->radioResourceConfigCommon_r13.nprach_Config_r13.nprach_ParametersList_r13.list,nprach_parameters);
-
-    // NPDSCH-Config NB-IOT
-    (*sib2_NB)->radioResourceConfigCommon_r13.npdsch_ConfigCommon_r13.nrs_Power_r13= 0; //?? see TS 36.213 16.2 for the value
-
-    //NPUSCH-Config NB-IoT
-    ack_nack_repetition = ACK_NACK_NumRepetitions_NB_r13_r1; //is an enumerative
-    ASN_SEQUENCE_ADD(&(*sib2_NB)->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ack_NACK_NumRepetitions_Msg4_r13.list,ack_nack_repetition);
-
-    *srs_SubframeConfig = 0;
-    (*sib2_NB)->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.srs_SubframeConfig_r13= srs_SubframeConfig;
-
-
-       * threeTone_BaseSequence_r13
-       * sixTone_BaseSequence_r13
-       * twelveTone_BaseSequence_r13
-
-
-      //new (occhio che dmrs_config_r13 è un puntatore quando lo richiami)
-      (*sib2_NB)->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.dmrs_Config_r13->threeTone_CyclicShift_r13 =0;
-      (*sib2_NB)->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.dmrs_Config_r13->sixTone_CyclicShift_r13 = 0;
-
-      (*sib2_NB)->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupHoppingEnabled_r13= 1;
-      (*sib2_NB)->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13 =0;
-
-
-    // PUCCH-Config NB-IoT
-
-    * all data are sent over the NPUSCH. This includes also the UL control information (UCI),
-    * which is transmitted using a different format. Consequently there is no equivalent to the PUCCH of LTE in NB-IoT.
-
-    // SRS Config --May not implemented in NB-IoT!
-
-    // uplinkPowerControlCommon - NB-IoT
-    (*sib2_NB)->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.p0_NominalNPUSCH_r13 = -108;
-    (*sib2_NB)->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.deltaPreambleMsg3_r13 = -6;
-    (*sib2_NB)->radioResourceConfigCommon_r13.uplinkPowerControlCommon_r13.alpha_r13 = UplinkPowerControlCommon_NB_r13__alpha_r13_al1;
-    //no deltaFlist_PUCCH, no UL cyclic Prefix
-
-    //New: DL_GapConfig
-     (*sib2_NB)->radioResourceConfigCommon_r13.dl_Gap_r13->dl_GapDurationCoeff_r13= DL_GapConfig_NB_r13__dl_GapDurationCoeff_r13_oneEighth;
-     (*sib2_NB)->radioResourceConfigCommon_r13.dl_Gap_r13->dl_GapPeriodicity_r13= DL_GapConfig_NB_r13__dl_GapPeriodicity_r13_sf64;
-     (*sib2_NB)->radioResourceConfigCommon_r13.dl_Gap_r13->dl_GapThreshold_r13= DL_GapConfig_NB_r13__dl_GapThreshold_r13_n32;
-
-    // UE Timers and Constants -NB-IoT
-    (*sib2_NB)->ue_TimersAndConstants_r13.t300_r13 = UE_TimersAndConstants_NB_r13__t300_r13_ms2500;
-    (*sib2_NB)->ue_TimersAndConstants_r13.t301_r13 = UE_TimersAndConstants_NB_r13__t301_r13_ms2500;
-    (*sib2_NB)->ue_TimersAndConstants_r13.t310_r13 = UE_TimersAndConstants_NB_r13__t310_r13_ms1000;//(specs pag 643)
-    (*sib2_NB)->ue_TimersAndConstants_r13.t311_r13 = UE_TimersAndConstants_NB_r13__t311_r13_ms1000;//(specs pag 643)
-    (*sib2_NB)->ue_TimersAndConstants_r13.n310_r13 = UE_TimersAndConstants_NB_r13__n310_r13_n1;//(specs pag 643)
-    (*sib2_NB)->ue_TimersAndConstants_r13.n311_r13 = UE_TimersAndConstants_NB_r13__n311_r13_n1;//(specs pag 643)
-
-*/
-
-  sib2_NB->freqInfo_r13.additionalSpectrumEmission_r13 = 1;
-  sib2_NB->freqInfo_r13.ul_CarrierFreq_r13 = NULL;
-  sib2_NB->timeAlignmentTimerCommon_r13=TimeAlignmentTimer_infinity;//TimeAlignmentTimer_sf5120;
-  //new
-  sib2_NB->multiBandInfoList_r13 = NULL; //-->Additional Spectrum Emission
-
-/// SIB3-NB-------------------------------------------------------
-
-  sib3_NB->cellReselectionInfoCommon_r13.q_Hyst_r13=SystemInformationBlockType3_NB_r13__cellReselectionInfoCommon_r13__q_Hyst_r13_dB4;
-  sib3_NB->cellReselectionServingFreqInfo_r13.s_NonIntraSearch_r13=NULL; //or define in configuration?
-
-  sib3_NB->intraFreqCellReselectionInfo_r13.q_RxLevMin_r13 = -70;
-  //new
-  sib3_NB->intraFreqCellReselectionInfo_r13.q_QualMin_r13 = CALLOC(1,sizeof(*sib3_NB->intraFreqCellReselectionInfo_r13.q_QualMin_r13));
-  *(sib3_NB->intraFreqCellReselectionInfo_r13.q_QualMin_r13)= 10; //a caso
-
-  sib3_NB->intraFreqCellReselectionInfo_r13.p_Max_r13 = NULL;
-  sib3_NB->intraFreqCellReselectionInfo_r13.s_IntraSearchP_r13 = 31; // s_intraSearch --> s_intraSearchP!!! (they call in a different way)
-  sib3_NB->intraFreqCellReselectionInfo_r13.t_Reselection_r13=1;
-
-  //how to manage?
-  sib3_NB->freqBandInfo_r13 = NULL;
-  sib3_NB->multiBandInfoList_r13 = NULL;
-
-
-///BCCH message (generate the SI message)
-  bcch_message->message.present = BCCH_DL_SCH_MessageType_NB_PR_c1;
-  bcch_message->message.choice.c1.present = BCCH_DL_SCH_MessageType_NB__c1_PR_systemInformation_r13;
-
-  bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.present = SystemInformation_NB__criticalExtensions_PR_systemInformation_r13;
-  bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.list.count=0;
-
-  ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.list,
-                   sib2_NB_part);
-  ASN_SEQUENCE_ADD(&bcch_message->message.choice.c1.choice.systemInformation_r13.criticalExtensions.choice.systemInformation_r13.sib_TypeAndInfo_r13.list,
-                   sib3_NB_part);
-
-#ifdef XER_PRINT
-  xer_fprint(stdout, &asn_DEF_BCCH_DL_SCH_Message_NB, (void*)bcch_message);
-#endif
-  enc_rval = uper_encode_to_buffer(&asn_DEF_BCCH_DL_SCH_Message_NB,
-                                   (void*)bcch_message,
-                                   carrier->SIB23_NB,
-                                   900);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-//#if defined(ENABLE_ITTI).....
-
-
-#ifdef USER_MODE
-  LOG_D(RRC,"[eNB] SystemInformation-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
-#endif
-
-  if (enc_rval.encoded==-1) {
-    msg("[RRC] ASN1 : SI-NB encoding failed for SIB23_NB\n");
-    return(-1);
-  }
-
-  return((enc_rval.encoded+7)/8);
-}
-
-/*do_RRCConnectionSetup_NB--> the aim is to establish SRB1 and SRB1bis(implicitly)*/
-uint8_t do_RRCConnectionSetup_NB(
-  const protocol_ctxt_t*     const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*      const ue_context_pP,
-  int                              CC_id,
-  uint8_t*                   const buffer, //Srb0.Tx_buffer.Payload
-  const uint8_t                    Transaction_id,
-  const LTE_DL_FRAME_PARMS* const frame_parms, //to be changed or maybe not used
-  SRB_ToAddModList_NB_r13_t**             SRB_configList_NB, //for both SRB1bis and SRB1
-  struct PhysicalConfigDedicated_NB_r13** physicalConfigDedicated_NB
-)
-
-{
-
- asn_enc_rval_t enc_rval;
- uint8_t ecause=0;
-
- //MP:logical channel group not defined for Nb-IoT
-
- //MP: logical channel priority pag 605 (is 1 for SRB1 and for SRB1bis should be the same)
- long* prioritySRB1 = NULL;
- long* prioritySRB1bis = NULL;
- BOOLEAN_t* logicalChannelSR_Prohibit =NULL; //pag 605
- BOOLEAN_t* npusch_AllSymbols= NULL;
-
-// struct SRB_ToAddMod_NB_r13* SRB1_config_NB = NULL;
-// struct SRB_ToAddMod_NB_r13__rlc_Config_r13* SRB1_rlc_config_NB = NULL;
-// struct SRB_ToAddMod_NB_r13__logicalChannelConfig_r13* SRB1_lchan_config_NB = NULL;
-
- struct SRB_ToAddMod_NB_r13* SRB1bis_config_NB = NULL;
- struct SRB_ToAddMod_NB_r13__rlc_Config_r13* SRB1bis_rlc_config_NB = NULL;
- struct SRB_ToAddMod_NB_r13__logicalChannelConfig_r13* SRB1bis_lchan_config_NB = NULL;
-
- //No UL_specific parameters for NB-IoT in LogicalChanelConfig-NB
-
- PhysicalConfigDedicated_NB_r13_t* physicalConfigDedicated2_NB = NULL;
- DL_CCCH_Message_NB_t dl_ccch_msg_NB;
- RRCConnectionSetup_NB_t* rrcConnectionSetup_NB = NULL;
-
- memset((void *)&dl_ccch_msg_NB,0,sizeof(DL_CCCH_Message_NB_t));
- dl_ccch_msg_NB.message.present = DL_CCCH_MessageType_NB_PR_c1;
- dl_ccch_msg_NB.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionSetup_r13;
- rrcConnectionSetup_NB = &dl_ccch_msg_NB.message.choice.c1.choice.rrcConnectionSetup_r13;
-
-
- if (*SRB_configList_NB) {
-   free(*SRB_configList_NB);
- }
- *SRB_configList_NB = CALLOC(1,sizeof(SRB_ToAddModList_NB_r13_t));
-
-/// SRB1--------------------
-
-// SRB1_config_NB = CALLOC(1,sizeof(*SRB1_config_NB));
-//
-// //no srb_Identity in SRB_ToAddMod_NB
-//
-// SRB1_rlc_config_NB = CALLOC(1,sizeof(*SRB1_rlc_config_NB));
-// SRB1_config_NB->rlc_Config_r13   = SRB1_rlc_config_NB;
-//
-// SRB1_rlc_config_NB->present = SRB_ToAddMod_NB_r13__rlc_Config_r13_PR_explicitValue;
-// SRB1_rlc_config_NB->choice.explicitValue.present=RLC_Config_NB_r13_PR_am;//the only possible in NB_IoT
-//
-//
-//// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = enb_properties.properties[ctxt_pP->module_id]->srb1_timer_poll_retransmit_r13;
-//// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = enb_properties.properties[ctxt_pP->module_id]->srb1_max_retx_threshold_r13;
-//// //(musT be disabled--> SRB1 config pag 640 specs )
-//// SRB1_rlc_config_NB->choice.explicitValue.choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 =NULL;
-//
-//
-// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms25000;
-// SRB1_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t8;
-// //(musT be disabled--> SRB1 config pag 640 specs )
-// SRB1_rlc_config_NB->choice.explicitValue.choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = NULL;
-//
-// SRB1_lchan_config_NB = CALLOC(1,sizeof(*SRB1_lchan_config_NB));
-// SRB1_config_NB->logicalChannelConfig_r13  = SRB1_lchan_config_NB;
-//
-// SRB1_lchan_config_NB->present = SRB_ToAddMod_NB_r13__logicalChannelConfig_r13_PR_explicitValue;
-//
-//
-// prioritySRB1 = CALLOC(1, sizeof(long));
-// *prioritySRB1 = 1;
-// SRB1_lchan_config_NB->choice.explicitValue.priority_r13 = prioritySRB1;
-//
-// logicalChannelSR_Prohibit = CALLOC(1, sizeof(BOOLEAN_t));
-// *logicalChannelSR_Prohibit = 1;
-// //schould be set to TRUE (specs pag 641)
-// SRB1_lchan_config_NB->choice.explicitValue.logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit;
-//
-// //ADD SRB1
-// ASN_SEQUENCE_ADD(&(*SRB_configList_NB)->list,SRB1_config_NB);
-
-
-///SRB1bis (The configuration for SRB1 and SRB1bis is the same)
- // the only difference is the logical channel identity = 3 but not set here
-
-		 SRB1bis_config_NB = CALLOC(1,sizeof(*SRB1bis_config_NB));
-
-		 //no srb_Identity in SRB_ToAddMod_NB
-		 SRB1bis_rlc_config_NB = CALLOC(1,sizeof(*SRB1bis_rlc_config_NB));
-		 SRB1bis_config_NB->rlc_Config_r13   = SRB1bis_rlc_config_NB;
-
-		 SRB1bis_rlc_config_NB->present = SRB_ToAddMod_NB_r13__rlc_Config_r13_PR_explicitValue;
-		 SRB1bis_rlc_config_NB->choice.explicitValue.present=RLC_Config_NB_r13_PR_am;//MP: the only possible RLC config in NB_IoT
-
-		 SRB1bis_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms25000;
-		 SRB1bis_rlc_config_NB->choice.explicitValue.choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t8;
-		 //(musT be disabled--> SRB1 config pag 640 specs )
-		 SRB1bis_rlc_config_NB->choice.explicitValue.choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 =NULL;
-
-		 SRB1bis_lchan_config_NB = CALLOC(1,sizeof(*SRB1bis_lchan_config_NB));
-		 SRB1bis_config_NB->logicalChannelConfig_r13  = SRB1bis_lchan_config_NB;
-
-		 SRB1bis_lchan_config_NB->present = SRB_ToAddMod_NB_r13__logicalChannelConfig_r13_PR_explicitValue;
-
-		 prioritySRB1bis = CALLOC(1, sizeof(long));
-		 *prioritySRB1bis = 1; //same as SRB1?
-		 SRB1bis_lchan_config_NB->choice.explicitValue.priority_r13 = prioritySRB1bis;
-
-		 logicalChannelSR_Prohibit = CALLOC(1, sizeof(BOOLEAN_t));
-		 *logicalChannelSR_Prohibit = 1; //schould be set to TRUE (specs pag 641)
-		 SRB1bis_lchan_config_NB->choice.explicitValue.logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit;
-
-		 //ADD SRB1bis
-		 //MP: Actually there is no way to distinguish SRB1 and SRB1bis once in the list
-		 //MP: XXX SRB_ToAddModList_NB_r13_t size = 1
-		 ASN_SEQUENCE_ADD(&(*SRB_configList_NB)->list,SRB1bis_config_NB);
-
-
- // PhysicalConfigDedicated (NPDCCH, NPUSCH, CarrierConfig, UplinkPowerControl)
-
- physicalConfigDedicated2_NB = CALLOC(1,sizeof(*physicalConfigDedicated2_NB));
- *physicalConfigDedicated_NB = physicalConfigDedicated2_NB;
-
- physicalConfigDedicated2_NB->carrierConfigDedicated_r13= CALLOC(1, sizeof(*physicalConfigDedicated2_NB->carrierConfigDedicated_r13));
- physicalConfigDedicated2_NB->npdcch_ConfigDedicated_r13 = CALLOC(1,sizeof(*physicalConfigDedicated2_NB->npdcch_ConfigDedicated_r13));
- physicalConfigDedicated2_NB->npusch_ConfigDedicated_r13 = CALLOC(1,sizeof(*physicalConfigDedicated2_NB->npusch_ConfigDedicated_r13));
- physicalConfigDedicated2_NB->uplinkPowerControlDedicated_r13 = CALLOC(1,sizeof(*physicalConfigDedicated2_NB->uplinkPowerControlDedicated_r13));
-
- //no tpc, no cqi and no pucch, no pdsch, no soundingRS, no AntennaInfo, no scheduling request config
-
- /*
-  * NB-IoT supports the operation with either one or two antenna ports, AP0 and AP1.
-  * For the latter case, Space Frequency Block Coding (SFBC) is applied.
-  * Once selected, the same transmission scheme applies to NPBCH, NPDCCH, and NPDSCH.
-  * */
-
- //FIXME: CarrierConfigDedicated check the set values
-  physicalConfigDedicated2_NB->carrierConfigDedicated_r13->dl_CarrierConfig_r13.downlinkBitmapNonAnchor_r13->present=
-		  DL_CarrierConfigDedicated_NB_r13__downlinkBitmapNonAnchor_r13_PR_useNoBitmap_r13;
-  physicalConfigDedicated2_NB->carrierConfigDedicated_r13->dl_CarrierConfig_r13.dl_GapNonAnchor_r13->present =
-		  DL_CarrierConfigDedicated_NB_r13__dl_GapNonAnchor_r13_PR_useNoGap_r13;
-  physicalConfigDedicated2_NB->carrierConfigDedicated_r13->dl_CarrierConfig_r13.inbandCarrierInfo_r13= NULL;
-
-  physicalConfigDedicated2_NB->carrierConfigDedicated_r13->ul_CarrierConfig_r13.ul_CarrierFreq_r13->carrierFreq_r13=0;
-  physicalConfigDedicated2_NB->carrierConfigDedicated_r13->ul_CarrierConfig_r13.ul_CarrierFreq_r13->carrierFreqOffset_r13= NULL;
-
- // NPDCCH
- physicalConfigDedicated2_NB->npdcch_ConfigDedicated_r13->npdcch_NumRepetitions_r13 =0;
- physicalConfigDedicated2_NB->npdcch_ConfigDedicated_r13->npdcch_Offset_USS_r13 =0;
- physicalConfigDedicated2_NB->npdcch_ConfigDedicated_r13->npdcch_StartSF_USS_r13=0;
-
- // NPUSCH
- physicalConfigDedicated2_NB->npusch_ConfigDedicated_r13->ack_NACK_NumRepetitions_r13= NULL; //(specs pag 643)
- npusch_AllSymbols= CALLOC(1, sizeof(BOOLEAN_t));
- *npusch_AllSymbols= 1; //TRUE
- physicalConfigDedicated2_NB->npusch_ConfigDedicated_r13->npusch_AllSymbols_r13= npusch_AllSymbols;
- physicalConfigDedicated2_NB->npusch_ConfigDedicated_r13->groupHoppingDisabled_r13=NULL;
-
- // UplinkPowerControlDedicated
- physicalConfigDedicated2_NB->uplinkPowerControlDedicated_r13->p0_UE_NPUSCH_r13 = 0; // 0 dB (specs pag 643)
-
-
- //Fill the rrcConnectionSetup-NB message
- rrcConnectionSetup_NB->rrc_TransactionIdentifier = Transaction_id; //input value
- rrcConnectionSetup_NB->criticalExtensions.present = RRCConnectionSetup_NB__criticalExtensions_PR_c1;
- rrcConnectionSetup_NB->criticalExtensions.choice.c1.present =RRCConnectionSetup_NB__criticalExtensions__c1_PR_rrcConnectionSetup_r13 ;
- //XXX: carry only SRB1bis at the moment and phyConfigDedicated
- rrcConnectionSetup_NB->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.srb_ToAddModList_r13 = *SRB_configList_NB;
- rrcConnectionSetup_NB->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.drb_ToAddModList_r13 = NULL;
- rrcConnectionSetup_NB->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.drb_ToReleaseList_r13 = NULL;
- rrcConnectionSetup_NB->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.rlf_TimersAndConstants_r13 = NULL;
- rrcConnectionSetup_NB->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13 = physicalConfigDedicated2_NB;
- rrcConnectionSetup_NB->criticalExtensions.choice.c1.choice.rrcConnectionSetup_r13.radioResourceConfigDedicated_r13.mac_MainConfig_r13 = NULL;
-
-#ifdef XER_PRINT
- xer_fprint(stdout, &asn_DEF_DL_CCCH_Message, (void*)&dl_ccch_msg);
-#endif
- enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
-                                  (void*)&dl_ccch_msg_NB,
-                                  buffer,
-                                  100);
- AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-              enc_rval.failed_type->name, enc_rval.encoded);
-
-
-#ifdef USER_MODE
- LOG_D(RRC,"RRCConnectionSetup-NB Encoded %d bits (%d bytes), ecause %d\n",
-       enc_rval.encoded,(enc_rval.encoded+7)/8,ecause);
-#endif
-
- return((enc_rval.encoded+7)/8);
-}
-
-/*do_SecurityModeCommand - exactly the same as previous implementation*/
-uint8_t do_SecurityModeCommand_NB(
-  const protocol_ctxt_t* const ctxt_pP,
-  uint8_t* const buffer,
-  const uint8_t Transaction_id,
-  const uint8_t cipheringAlgorithm,
-  const uint8_t integrityProtAlgorithm)
-{
-  DL_DCCH_Message_NB_t dl_dcch_msg_NB;
-  asn_enc_rval_t enc_rval;
-
-  memset(&dl_dcch_msg_NB,0,sizeof(DL_DCCH_Message_NB_t));
-
-  dl_dcch_msg_NB.message.present = DL_DCCH_MessageType_NB_PR_c1;
-  dl_dcch_msg_NB.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_securityModeCommand_r13;
-
-  dl_dcch_msg_NB.message.choice.c1.choice.securityModeCommand_r13.rrc_TransactionIdentifier = Transaction_id;
-  dl_dcch_msg_NB.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.present = SecurityModeCommand__criticalExtensions_PR_c1;
-
-  dl_dcch_msg_NB.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.choice.c1.present =
-		  SecurityModeCommand__criticalExtensions__c1_PR_securityModeCommand_r8;
-
-  // the two following information could be based on the mod_id
-  dl_dcch_msg_NB.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.cipheringAlgorithm
-    = (CipheringAlgorithm_r12_t)cipheringAlgorithm; //bug solved
-
-  dl_dcch_msg_NB.message.choice.c1.choice.securityModeCommand_r13.criticalExtensions.choice.c1.choice.securityModeCommand_r8.securityConfigSMC.securityAlgorithmConfig.integrityProtAlgorithm
-    = (e_SecurityAlgorithmConfig__integrityProtAlgorithm)integrityProtAlgorithm;
-
-//only changed "asn_DEF_DL_DCCH_Message_NB"
-#ifdef XER_PRINT
-  xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB);
-#endif
-  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
-                                   (void*)&dl_dcch_msg_NB,
-                                   buffer,
-                                   100);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-
-//#if defined(ENABLE_ITTI)
-//# if !defined(DISABLE_XER_SPRINT)....
-
-#ifdef USER_MODE
-  LOG_D(RRC,"[eNB %d] securityModeCommand-NB for UE %x Encoded %d bits (%d bytes)\n",
-        ctxt_pP->module_id,
-        ctxt_pP->rnti,
-        enc_rval.encoded,
-        (enc_rval.encoded+7)/8);
-#endif
-
-  if (enc_rval.encoded==-1) {
-    LOG_E(RRC,"[eNB %d] ASN1 : securityModeCommand-NB encoding failed for UE %x\n",
-          ctxt_pP->module_id,
-          ctxt_pP->rnti);
-    return(-1);
-  }
-
-  return((enc_rval.encoded+7)/8);
-}
-
-/*do_UECapabilityEnquiry_NB - very similar to legacy lte*/
-uint8_t do_UECapabilityEnquiry_NB(
-  const protocol_ctxt_t* const ctxt_pP,
-  uint8_t*               const buffer,
-  const uint8_t                Transaction_id
-)
-
-{
-
-  DL_DCCH_Message_NB_t dl_dcch_msg_NB;
-  //no RAT type in NB-IoT
-  asn_enc_rval_t enc_rval;
-
-  memset(&dl_dcch_msg_NB,0,sizeof(DL_DCCH_Message_NB_t));
-
-  dl_dcch_msg_NB.message.present           = DL_DCCH_MessageType_NB_PR_c1;
-  dl_dcch_msg_NB.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_ueCapabilityEnquiry_r13;
-
-  dl_dcch_msg_NB.message.choice.c1.choice.ueCapabilityEnquiry_r13.rrc_TransactionIdentifier = Transaction_id;
-
-  dl_dcch_msg_NB.message.choice.c1.choice.ueCapabilityEnquiry_r13.criticalExtensions.present = UECapabilityEnquiry_NB__criticalExtensions_PR_c1;
-  dl_dcch_msg_NB.message.choice.c1.choice.ueCapabilityEnquiry_r13.criticalExtensions.choice.c1.present =
-		  UECapabilityEnquiry_NB__criticalExtensions__c1_PR_ueCapabilityEnquiry_r13;
-
-  //no ue_CapabilityRequest (list of RAT_Type)
-
-//only changed "asn_DEF_DL_DCCH_Message_NB"
-#ifdef XER_PRINT
-  xer_fprint(stdout, &asn_DEF_DL_DCCH_Message_NB, (void*)&dl_dcch_msg_NB);
-#endif
-  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
-                                   (void*)&dl_dcch_msg_NB,
-                                   buffer,
-                                   100);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-//#if defined(ENABLE_ITTI)
-//# if !defined(DISABLE_XER_SPRINT)....
-
-#ifdef USER_MODE
-  LOG_D(RRC,"[eNB %d] UECapabilityEnquiry-NB for UE %x Encoded %d bits (%d bytes)\n",
-        ctxt_pP->module_id,
-        ctxt_pP->rnti,
-        enc_rval.encoded,
-        (enc_rval.encoded+7)/8);
-#endif
-
-  if (enc_rval.encoded==-1) {
-    LOG_E(RRC,"[eNB %d] ASN1 : UECapabilityEnquiry-NB encoding failed for UE %x\n",
-          ctxt_pP->module_id,
-          ctxt_pP->rnti);
-    return(-1);
-  }
-
-  return((enc_rval.encoded+7)/8);
-}
-
-/*do_RRCConnectionReconfiguration_NB-->may convey information for resource configuration
- * (including RBs, MAC main configuration and physical channel configuration)
- * including any associated dedicated NAS information.*/
-uint16_t do_RRCConnectionReconfiguration_NB(
-  const protocol_ctxt_t*        const ctxt_pP,
-    uint8_t                            *buffer,
-    uint8_t                             Transaction_id,
-    SRB_ToAddModList_NB_r13_t          *SRB1_list_NB, //SRB_ConfigList2 (default)--> only SRB1
-    DRB_ToAddModList_NB_r13_t          *DRB_list_NB, //DRB_ConfigList (default)
-    DRB_ToReleaseList_NB_r13_t         *DRB_list2_NB, //is NULL when passed
-    struct PhysicalConfigDedicated_NB_r13     *physicalConfigDedicated_NB,
-	MAC_MainConfig_NB_r13_t                   *mac_MainConfig_NB,
-  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13* dedicatedInfoNASList_NB)
-
-{
-
- //check on DRB_list if contains more than 2 DRB?
-
-  asn_enc_rval_t enc_rval;
-  DL_DCCH_Message_NB_t dl_dcch_msg_NB;
-  RRCConnectionReconfiguration_NB_t *rrcConnectionReconfiguration_NB;
-
-
-  memset(&dl_dcch_msg_NB,0,sizeof(DL_DCCH_Message_NB_t));
-
-  dl_dcch_msg_NB.message.present           = DL_DCCH_MessageType_NB_PR_c1;
-  dl_dcch_msg_NB.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_rrcConnectionReconfiguration_r13;
-  rrcConnectionReconfiguration_NB          = &dl_dcch_msg_NB.message.choice.c1.choice.rrcConnectionReconfiguration_r13;
-
-  // RRCConnectionReconfiguration
-  rrcConnectionReconfiguration_NB->rrc_TransactionIdentifier = Transaction_id;
-  rrcConnectionReconfiguration_NB->criticalExtensions.present = RRCConnectionReconfiguration_NB__criticalExtensions_PR_c1;
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.present =RRCConnectionReconfiguration_NB__criticalExtensions__c1_PR_rrcConnectionReconfiguration_r13 ;
-
-  //RAdioResourceconfigDedicated
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13 =
-		  CALLOC(1,sizeof(*rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13));
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->srb_ToAddModList_r13 = SRB1_list_NB; //only SRB1
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->drb_ToAddModList_r13 = DRB_list_NB;
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->drb_ToReleaseList_r13 = DRB_list2_NB; //NULL
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->physicalConfigDedicated_r13 = physicalConfigDedicated_NB;
-  //FIXME may not used now
-  //rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->rlf_TimersAndConstants_r13
-
-  if (mac_MainConfig_NB!=NULL) {
-    rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13 =
-    		CALLOC(1, sizeof(*rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13));
-    rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13->present
-      =RadioResourceConfigDedicated_NB_r13__mac_MainConfig_r13_PR_explicitValue_r13;
-   //why memcopy only this one?
-    memcpy(&rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13->choice.explicitValue_r13,
-           mac_MainConfig_NB, sizeof(*mac_MainConfig_NB));
-
-  } else {
-	  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.radioResourceConfigDedicated_r13->mac_MainConfig_r13=NULL;
-  }
-
-  //no measConfig, measIDlist
-  //no mobilityControlInfo
-
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.dedicatedInfoNASList_r13 = dedicatedInfoNASList_NB;
-  //mainly used for cell-reselection/handover purposes??
-  rrcConnectionReconfiguration_NB->criticalExtensions.choice.c1.choice.rrcConnectionReconfiguration_r13.fullConfig_r13 = NULL;
-
-  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
-                                   (void*)&dl_dcch_msg_NB,
-                                   buffer,
-                                   RRC_BUF_SIZE);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %l)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-  //changed only asn_DEF_DL_DCCH_Message_NB
-#ifdef XER_PRINT
-  xer_fprint(stdout,&asn_DEF_DL_DCCH_Message_NB,(void*)&dl_dcch_msg_NB);
-#endif
-
-//#if defined(ENABLE_ITTI)
-//# if !defined(DISABLE_XER_SPRINT)...
-
-
-  LOG_I(RRC,"RRCConnectionReconfiguration-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
-
-  return((enc_rval.encoded+7)/8);
-}
-
-/*do_RRCConnectionReestablishmentReject - exactly the same as legacy LTE*/
-uint8_t do_RRCConnectionReestablishmentReject_NB(
-    uint8_t                    Mod_id,
-    uint8_t*                   const buffer)
-{
-
-  asn_enc_rval_t enc_rval;
-
-  DL_CCCH_Message_NB_t dl_ccch_msg_NB;
-  RRCConnectionReestablishmentReject_t *rrcConnectionReestablishmentReject;
-
-  memset((void *)&dl_ccch_msg_NB,0,sizeof(DL_CCCH_Message_NB_t));
-  dl_ccch_msg_NB.message.present = DL_CCCH_MessageType_NB_PR_c1;
-  dl_ccch_msg_NB.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionReestablishmentReject_r13;
-  rrcConnectionReestablishmentReject    = &dl_ccch_msg_NB.message.choice.c1.choice.rrcConnectionReestablishmentReject_r13;
-
-  // RRCConnectionReestablishmentReject //exactly the same as LTE
-  rrcConnectionReestablishmentReject->criticalExtensions.present = RRCConnectionReestablishmentReject__criticalExtensions_PR_rrcConnectionReestablishmentReject_r8;
-
-  //Only change in "asn_DEF_DL_CCCH_Message_NB"
-#ifdef XER_PRINT
-  xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg_NB);
-#endif
-  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
-                                   (void*)&dl_ccch_msg_NB,
-                                   buffer,
-                                   100);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %lu)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-  //Only change in "asn_DEF_DL_CCCH_Message_NB"
-#if defined(ENABLE_ITTI)
-# if !defined(DISABLE_XER_SPRINT)
-  {
-    char        message_string[20000];
-    size_t      message_string_size;
-
-    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message_NB, (void *) &dl_ccch_msg_NB)) > 0) {
-      MessageDef *msg_p;
-
-      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText));
-      msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size;
-      memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size);
-
-      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
-    }
-  }
-# endif
-#endif
-
-#ifdef USER_MODE
-  LOG_D(RRC,"RRCConnectionReestablishmentReject Encoded %d bits (%d bytes)\n",
-        enc_rval.encoded,(enc_rval.encoded+7)/8);
-#endif
-
-  return((enc_rval.encoded+7)/8);
-}
-
-/*do_RRCConnectionReject_NB*/
-uint8_t do_RRCConnectionReject_NB(
-    uint8_t                    Mod_id,
-    uint8_t*                   const buffer)
-
-{
-
-  asn_enc_rval_t enc_rval;
-
-  DL_CCCH_Message_NB_t dl_ccch_msg_NB;
-  RRCConnectionReject_NB_t *rrcConnectionReject_NB;
-
-  memset((void *)&dl_ccch_msg_NB,0,sizeof(DL_CCCH_Message_NB_t));
-  dl_ccch_msg_NB.message.present           = DL_CCCH_MessageType_NB_PR_c1;
-  dl_ccch_msg_NB.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionReject_r13;
-  rrcConnectionReject_NB = &dl_ccch_msg_NB.message.choice.c1.choice.rrcConnectionReject_r13;
-
-  // RRCConnectionReject-NB
-  rrcConnectionReject_NB->criticalExtensions.present = RRCConnectionReject_NB__criticalExtensions_PR_c1;
-  rrcConnectionReject_NB->criticalExtensions.choice.c1.present = RRCConnectionReject_NB__criticalExtensions__c1_PR_rrcConnectionReject_r13;
-  /* let's put an extended wait time of 1s for the moment */
-  rrcConnectionReject_NB->criticalExtensions.choice.c1.choice.rrcConnectionReject_r13.extendedWaitTime_r13 = 1;
-  //new-use of suspend indication
-  //If present, this field indicates that the UE should remain suspended and not release its stored context.
-  rrcConnectionReject_NB->criticalExtensions.choice.c1.choice.rrcConnectionReject_r13.rrc_SuspendIndication_r13=
-		  CALLOC(1, sizeof(long));
-  *(rrcConnectionReject_NB->criticalExtensions.choice.c1.choice.rrcConnectionReject_r13.rrc_SuspendIndication_r13)=
-		  RRCConnectionReject_NB_r13_IEs__rrc_SuspendIndication_r13_true;
-
-  //Only Modified "asn_DEF_DL_CCCH_Message_NB"
-#ifdef XER_PRINT
-  xer_fprint(stdout, &asn_DEF_DL_CCCH_Message_NB, (void*)&dl_ccch_msg);
-#endif
-  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
-                                   (void*)&dl_ccch_msg_NB,
-                                   buffer,
-                                   100);
-  AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %ld)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
-
-#if defined(ENABLE_ITTI)
-# if !defined(DISABLE_XER_SPRINT)
-  {
-    char        message_string[20000];
-    size_t      message_string_size;
-
-    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message_NB, (void *) &dl_ccch_msg_NB)) > 0) {
-      MessageDef *msg_p;
-
-      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText));
-      msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size;
-      memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size);
-
-      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
-    }
-  }
-# endif
-#endif
-
-#ifdef USER_MODE
-  LOG_D(RRC,"RRCConnectionReject-NB Encoded %d bits (%d bytes)\n",
-        enc_rval.encoded,(enc_rval.encoded+7)/8);
-#endif
-
-  return((enc_rval.encoded+7)/8);
-}
-
-
-//no do_MBSFNAreaConfig(..) in NB-IoT
-//no do_MeasurementReport(..) in NB-IoT
-
-/*do_DLInformationTransfer_NB*/
-uint8_t do_DLInformationTransfer_NB(
-		uint8_t Mod_id,
-		uint8_t **buffer,
-		uint8_t transaction_id,
-		uint32_t pdu_length,
-		uint8_t *pdu_buffer)
-
-{
-  ssize_t encoded;
-
-  DL_DCCH_Message_NB_t dl_dcch_msg_NB;
-
-  memset(&dl_dcch_msg_NB, 0, sizeof(DL_DCCH_Message_NB_t));
-
-  dl_dcch_msg_NB.message.present           = DL_DCCH_MessageType_NB_PR_c1;
-  dl_dcch_msg_NB.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_dlInformationTransfer_r13;
-  dl_dcch_msg_NB.message.choice.c1.choice.dlInformationTransfer_r13.rrc_TransactionIdentifier = transaction_id;
-  dl_dcch_msg_NB.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.present = DLInformationTransfer_NB__criticalExtensions_PR_c1;
-  dl_dcch_msg_NB.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.choice.c1.present = DLInformationTransfer_NB__criticalExtensions__c1_PR_dlInformationTransfer_r13;
-  dl_dcch_msg_NB.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.choice.c1.choice.dlInformationTransfer_r13.dedicatedInfoNAS_r13.size = pdu_length;
-  dl_dcch_msg_NB.message.choice.c1.choice.dlInformationTransfer_r13.criticalExtensions.choice.c1.choice.dlInformationTransfer_r13.dedicatedInfoNAS_r13.buf = pdu_buffer;
-
-  encoded = uper_encode_to_new_buffer (&asn_DEF_DL_DCCH_Message_NB, NULL, (void*) &dl_dcch_msg_NB, (void **) buffer);
-
-  //only change in "asn_DEF_DL_DCCH_Message_NB"
-#if defined(ENABLE_ITTI)
-# if !defined(DISABLE_XER_SPRINT)
-  {
-    char        message_string[10000];
-    size_t      message_string_size;
-
-    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_DCCH_Message_NB, (void *)&dl_dcch_msg_NB)) > 0) {
-      MessageDef *msg_p;
-
-      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_DCCH, message_string_size + sizeof (IttiMsgText));
-      msg_p->ittiMsg.rrc_dl_dcch.size = message_string_size;
-      memcpy(&msg_p->ittiMsg.rrc_dl_dcch.text, message_string, message_string_size);
-
-      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
-    }
-  }
-# endif
-#endif
-
-  return encoded;
-}
-
-/*do_ULInformationTransfer*/
-//for the moment is not needed (UE-SIDE)
-
-/*OAI_UECapability_t *fill_ue_capability*/
-
-/*do_RRCConnectionReestablishment_NB-->used to re-establish SRB1*/ //which parameter to use?
-uint8_t do_RRCConnectionReestablishment_NB(
-		uint8_t Mod_id,
-		uint8_t* const buffer,
-		const uint8_t     Transaction_id,
-		const LTE_DL_FRAME_PARMS* const frame_parms, //to be changed
-		SRB_ToAddModList_NB_r13_t*      SRB_list_NB) //should contain SRB1 already configured?
-{
-
-	asn_enc_rval_t enc_rval;
-	DL_CCCH_Message_NB_t dl_ccch_msg_NB;
-	RRCConnectionReestablishment_NB_t* rrcConnectionReestablishment_NB;
-
-	memset(&dl_ccch_msg_NB, 0, sizeof(DL_CCCH_Message_NB_t));
-
-	dl_ccch_msg_NB.message.present = DL_CCCH_MessageType_NB_PR_c1;
-	dl_ccch_msg_NB.message.choice.c1.present = DL_CCCH_MessageType_NB__c1_PR_rrcConnectionReestablishment_r13;
-	rrcConnectionReestablishment_NB = &dl_ccch_msg_NB.message.choice.c1.choice.rrcConnectionReestablishment_r13;
-
-	//rrcConnectionReestablishment_NB
-	rrcConnectionReestablishment_NB->rrc_TransactionIdentifier = Transaction_id;
-	rrcConnectionReestablishment_NB->criticalExtensions.present = RRCConnectionReestablishment_NB__criticalExtensions_PR_c1;
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.present = RRCConnectionReestablishment_NB__criticalExtensions__c1_PR_rrcConnectionReestablishment_r13;
-
-	//FIXME: which parameters are needed?
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.srb_ToAddModList_r13 = SRB_list_NB;
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.drb_ToAddModList_r13 = NULL;
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.drb_ToReleaseList_r13 = NULL;
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.rlf_TimersAndConstants_r13= NULL;
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.mac_MainConfig_r13= NULL;
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.radioResourceConfigDedicated_r13.physicalConfigDedicated_r13 = NULL;
-
-	rrcConnectionReestablishment_NB->criticalExtensions.choice.c1.choice.rrcConnectionReestablishment_r13.nextHopChainingCount_r13=0;
-
-	enc_rval = uper_encode_to_buffer(&asn_DEF_DL_CCCH_Message_NB,
-	                                   (void*)&dl_ccch_msg_NB,
-	                                   buffer,
-	                                   RRC_BUF_SIZE);
-
-	 AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %l)!\n",
-	               enc_rval.failed_type->name, enc_rval.encoded);
-
-#ifdef XER_PRINT
-  xer_fprint(stdout,&asn_DEF_DL_CCCH_Message_NB,(void*)&dl_ccch_msg_NB);
-#endif
-
-#if defined(ENABLE_ITTI)
-# if !defined(DISABLE_XER_SPRINT)
-  {
-    char        message_string[30000];
-    size_t      message_string_size;
-
-    if ((message_string_size = xer_sprint(message_string, sizeof(message_string), &asn_DEF_DL_CCCH_Message_NB, (void *) &dl_ccch_msg_NB)) > 0) {
-      MessageDef *msg_p;
-
-      msg_p = itti_alloc_new_message_sized (TASK_RRC_ENB, RRC_DL_CCCH, message_string_size + sizeof (IttiMsgText));
-      msg_p->ittiMsg.rrc_dl_ccch.size = message_string_size;
-      memcpy(&msg_p->ittiMsg.rrc_dl_ccch.text, message_string, message_string_size);
-
-      itti_send_msg_to_task(TASK_UNKNOWN, Mod_id, msg_p);
-    }
-  }
-# endif
-#endif
-
-  LOG_I(RRC,"RRCConnectionReestablishment-NB Encoded %d bits (%d bytes)\n",enc_rval.encoded,(enc_rval.encoded+7)/8);
-
-}
-
-/*do_RRCConnectionRelease_NB--> is used to command the release of an RRC connection*/
-uint8_t do_RRCConnectionRelease_NB(
-  uint8_t                             Mod_id,
-  uint8_t                            *buffer,
- const uint8_t                             Transaction_id)
-{
-
-  asn_enc_rval_t enc_rval;
-
-  DL_DCCH_Message_NB_t dl_dcch_msg_NB;
-  RRCConnectionRelease_NB_t *rrcConnectionRelease_NB;
-
-
-  memset(&dl_dcch_msg_NB,0,sizeof(DL_DCCH_Message_NB_t));
-
-  dl_dcch_msg_NB.message.present           = DL_DCCH_MessageType_NB_PR_c1;
-  dl_dcch_msg_NB.message.choice.c1.present = DL_DCCH_MessageType_NB__c1_PR_rrcConnectionRelease_r13;
-  rrcConnectionRelease_NB                  = &dl_dcch_msg_NB.message.choice.c1.choice.rrcConnectionRelease_r13;
-
-  // RRCConnectionRelease
-  rrcConnectionRelease_NB->rrc_TransactionIdentifier = Transaction_id;
-  rrcConnectionRelease_NB->criticalExtensions.present = RRCConnectionRelease_NB__criticalExtensions_PR_c1;
-  rrcConnectionRelease_NB->criticalExtensions.choice.c1.present =RRCConnectionRelease_NB__criticalExtensions__c1_PR_rrcConnectionRelease_r13 ;
-
-  rrcConnectionRelease_NB->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.releaseCause_r13 = ReleaseCause_NB_r13_other;
-  rrcConnectionRelease_NB->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.redirectedCarrierInfo_r13 = NULL;
-  rrcConnectionRelease_NB->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.extendedWaitTime_r13 = NULL;
-
-  //Why allocate memory for non critical extension?
-  rrcConnectionRelease_NB->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.nonCriticalExtension=CALLOC(1,
-      sizeof(*rrcConnectionRelease_NB->criticalExtensions.choice.c1.choice.rrcConnectionRelease_r13.nonCriticalExtension));
-
-  enc_rval = uper_encode_to_buffer(&asn_DEF_DL_DCCH_Message_NB,
-                                   (void*)&dl_dcch_msg_NB,
-                                   buffer,
-                                   RRC_BUF_SIZE);//check
-
-  return((enc_rval.encoded+7)/8);
-}
-
-
-// -----??????--------------------
-#ifndef USER_MODE
-int init_module_NB(void)
-{
-  printk("Init asn1_msg_nb_iot module\n");
-
-  // A non 0 return means init_module failed; module can't be loaded.
-  return 0;
-}
-
-
-void cleanup_module_NB(void)
-{
-  printk("Stopping asn1_msg_nb_iot module\n");
-}
-
-EXPORT_SYMBOL(do_SIB1_NB);
-EXPORT_SYMBOL(do_SIB23_NB);
-EXPORT_SYMBOL(do_RRCConnectionRequest_NB);
-EXPORT_SYMBOL(do_RRCConnectionSetupComplete_NB);
-EXPORT_SYMBOL(do_RRCConnectionReconfigurationComplete_NB);
-EXPORT_SYMBOL(do_RRCConnectionSetup_NB);
-EXPORT_SYMBOL(do_RRCConnectionReestablishmentReject_NB);
-EXPORT_SYMBOL(do_RRCConnectionReconfiguration_NB);
-EXPORT_SYMBOL(asn_DEF_UL_DCCH_Message_NB);
-EXPORT_SYMBOL(asn_DEF_UL_CCCH_Message_NB);
-EXPORT_SYMBOL(asn_DEF_SystemInformation_NB);
-EXPORT_SYMBOL(asn_DEF_DL_DCCH_Message_NB);
-EXPORT_SYMBOL(asn_DEF_SystemInformationBlockType1_NB);
-EXPORT_SYMBOL(asn_DEF_DL_CCCH_Message_NB);
-EXPORT_SYMBOL(uper_decode_complete);
-EXPORT_SYMBOL(uper_decode);
-EXPORT_SYMBOL(transmission_mode_rrc);
-#endif
-
-//----------------------------------
-
-
-
-
diff --git a/openair2/RRC/LITE/defs_NB_IoT.h b/openair2/RRC/LITE/defs_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..d150e6a3b24ceb0ecdc9fb7aadff7f1099a9bf76
--- /dev/null
+++ b/openair2/RRC/LITE/defs_NB_IoT.h
@@ -0,0 +1,578 @@
+/* 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.0  (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 RRC/LITE/defs_NB_IoT.h
+* \brief NB-IoT RRC struct definitions and function prototypes
+* \author Navid Nikaein, Raymond Knopp and Michele Paffetti
+* \date 2010 - 2014, 2017
+* \version 1.0
+* \company Eurecom
+* \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr, michele.paffetti@studio.unibo.it
+*/
+
+#ifndef __OPENAIR_RRC_DEFS_NB_IOT_H__
+#define __OPENAIR_RRC_DEFS_NB_IOT_H__
+
+
+#ifdef USER_MODE
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#endif
+
+#include "collection/tree.h"
+#include "rrc_types_NB_IoT.h"
+//#include "PHY/defs.h"
+//#include "PHY/defs_NB_IoT.h"
+#include "COMMON/platform_constants.h"
+#include "COMMON/platform_types.h"
+
+#include "COMMON/mac_rrc_primitives.h"
+//#include "LAYER2/MAC/defs.h"
+
+//#include "COMMON/openair_defs.h"
+#ifndef USER_MODE
+#include <rtai.h>
+#endif
+
+
+//-----NB-IoT #include files-------
+
+//#include "SystemInformationBlockType1-NB.h"
+//#include "SystemInformation-NB.h"
+#include "RRCConnectionReconfiguration-NB.h"
+#include "RRCConnectionReconfigurationComplete-NB.h"
+#include "RRCConnectionSetup-NB.h"
+#include "RRCConnectionSetupComplete-NB.h"
+#include "RRCConnectionRequest-NB.h"
+#include "RRCConnectionReestablishmentRequest-NB.h"
+#include "BCCH-DL-SCH-Message-NB.h"
+#include "BCCH-BCH-Message-NB.h"
+#include "AS-Config-NB.h"
+#include "AS-Context-NB.h"
+#include "UE-Capability-NB-r13.h" //equivalent of UE-EUTRA-Capability.h
+//-------------------
+
+#if defined(ENABLE_ITTI)
+# include "intertask_interface.h"
+#endif
+
+/* TODO: be sure this include is correct.
+ * It solves a problem of compilation of the RRH GW,
+ * issue #186.
+ */
+#if !defined(ENABLE_ITTI)
+# include "as_message.h"
+#endif
+
+#if defined(ENABLE_USE_MME)
+# include "commonDef.h"
+#endif
+
+#if ENABLE_RAL
+# include "collection/hashtable/obj_hashtable.h"
+#endif
+
+
+
+/*I will change the name of the structure for compile purposes--> hope not to undo this process*/
+
+typedef unsigned int uid_NB_IoT_t;
+#define UID_LINEAR_ALLOCATOR_BITMAP_SIZE_NB_IoT (((NUMBER_OF_UE_MAX_NB_IoT/8)/sizeof(unsigned int)) + 1)
+
+typedef struct uid_linear_allocator_NB_IoT_s {
+  unsigned int   bitmap[UID_LINEAR_ALLOCATOR_BITMAP_SIZE_NB_IoT];
+} uid_allocator_NB_IoT_t;
+
+
+#define PROTOCOL_RRC_CTXT_UE_FMT           PROTOCOL_CTXT_FMT
+#define PROTOCOL_RRC_CTXT_UE_ARGS(CTXT_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp)
+
+#define PROTOCOL_RRC_CTXT_FMT           PROTOCOL_CTXT_FMT
+#define PROTOCOL_RRC_CTXT_ARGS(CTXT_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp)
+
+
+//left as they are --> used in LAYER2/epenair2_proc.c and UE side
+typedef enum UE_STATE_NB_IoT_e {
+ RRC_INACTIVE_NB_IoT=0,
+ RRC_IDLE_NB_IoT,
+ RRC_SI_RECEIVED_NB_IoT,
+ RRC_CONNECTED_NB_IoT,
+ RRC_RECONFIGURED_NB_IoT,
+ RRC_HO_EXECUTION_NB_IoT //maybe not needed?
+} UE_STATE_NB_IoT_t;
+
+
+/** @defgroup _rrc RRC
+ * @ingroup _oai2
+ * @{
+ */
+typedef struct UE_RRC_INFO_NB_IoT_s {
+  UE_STATE_NB_IoT_t State;
+  uint8_t SIB1systemInfoValueTag;
+  uint32_t SIStatus;
+  uint32_t SIcnt;
+#if defined(Rel10) || defined(Rel14)
+  uint8_t MCCHStatus[8]; // MAX_MBSFN_AREA
+#endif
+  uint8_t SIwindowsize; //!< Corresponds to the SIB1 si-WindowLength parameter. The unit is ms. Possible values are (final): 1,2,5,10,15,20,40
+  uint8_t handoverTarget;
+  //HO_STATE_t ho_state;
+  uint16_t SIperiod; //!< Corresponds to the SIB1 si-Periodicity parameter (multiplied by 10). Possible values are (final): 80,160,320,640,1280,2560,5120
+  unsigned short UE_index;
+  uint32_t T300_active;
+  uint32_t T300_cnt;
+  uint32_t T304_active;
+  uint32_t T304_cnt;
+  uint32_t T310_active;
+  uint32_t T310_cnt;
+  uint32_t N310_cnt;
+  uint32_t N311_cnt;
+  rnti_t   rnti;
+} __attribute__ ((__packed__)) UE_RRC_INFO_NB_IoT;
+
+//#define NUM_PRECONFIGURED_LCHAN (NB_CH_CX*2)  //BCCH, CCCH
+
+#define UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!!
+#define UE_INDEX_INVALID  ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1
+
+
+
+// HO_STATE is not supported by NB-IoT
+
+//#define NUMBER_OF_UE_MAX MAX_MOBILES_PER_RG
+#define RRM_FREE(p)       if ( (p) != NULL) { free(p) ; p=NULL ; }
+#define RRM_MALLOC(t,n)   (t *) malloc16( sizeof(t) * n )
+#define RRM_CALLOC(t,n)   (t *) malloc16( sizeof(t) * n)
+#define RRM_CALLOC2(t,s)  (t *) malloc16( s )
+
+//Measurement Report not supported in NB-IoT
+
+#define PAYLOAD_SIZE_MAX 1024
+#define RRC_BUF_SIZE 255
+#define UNDEF_SECURITY_MODE 0xff
+#define NO_SECURITY_MODE 0x20
+
+/* TS 36.331: RRC-TransactionIdentifier ::= INTEGER (0..3) */
+#define RRC_TRANSACTION_IDENTIFIER_NUMBER  3
+
+typedef struct UE_S_TMSI_NB_IoT_s {
+  boolean_t  presence;
+  mme_code_t mme_code;
+  m_tmsi_t   m_tmsi;
+} __attribute__ ((__packed__)) UE_S_TMSI_NB_IoT;
+
+
+typedef enum e_rab_satus_NB_IoT_e {
+  E_RAB_STATUS_NEW_NB_IoT,
+  E_RAB_STATUS_DONE_NB_IoT, // from the eNB perspective
+  E_RAB_STATUS_ESTABLISHED_NB_IoT, // get the reconfigurationcomplete form UE
+  E_RAB_STATUS_FAILED_NB_IoT,
+} e_rab_status_NB_IoT_t;
+
+typedef struct e_rab_param_NB_IoT_s {
+  e_rab_t param;
+  uint8_t status;
+  uint8_t xid; // transaction_id
+} __attribute__ ((__packed__)) e_rab_param_NB_IoT_t;
+
+
+//HANDOVER_INFO not implemented in NB-IoT delete
+
+
+#define RRC_HEADER_SIZE_MAX 64
+#define RRC_BUFFER_SIZE_MAX 1024
+
+typedef struct {
+  char Payload[RRC_BUFFER_SIZE_MAX];
+  char Header[RRC_HEADER_SIZE_MAX];
+  char payload_size;
+} RRC_BUFFER_NB_IoT;
+
+#define RRC_BUFFER_SIZE_NB_IoT sizeof(RRC_BUFFER_NB_IoT)
+
+
+typedef struct RB_INFO_NB_IoT_s {
+  uint16_t Rb_id;  //=Lchan_id
+  //LCHAN_DESC Lchan_desc[2]; no more used
+  //MAC_MEAS_REQ_ENTRY *Meas_entry; //may not needed for NB-IoT
+} RB_INFO_NB_IoT;
+
+typedef struct SRB_INFO_NB_IoT_s {
+  uint16_t Srb_id;  //=Lchan_id---> useful for distinguish between SRB1 and SRB1bis?
+  RRC_BUFFER_NB_IoT Rx_buffer;
+  RRC_BUFFER_NB_IoT Tx_buffer;
+  //LCHAN_DESC Lchan_desc[2]; no more used
+  unsigned int Trans_id;
+  uint8_t Active;
+} SRB_INFO_NB_IoT;
+
+
+typedef struct RB_INFO_TABLE_ENTRY_NB_IoT_s {
+  RB_INFO_NB_IoT Rb_info;
+  uint8_t Active;
+  uint32_t Next_check_frame;
+  uint8_t Status;
+} RB_INFO_TABLE_ENTRY_NB_IoT;
+
+typedef struct SRB_INFO_TABLE_ENTRY_NB_IoT_s {
+  SRB_INFO_NB_IoT Srb_info;
+  uint8_t Active;
+  uint8_t Status;
+  uint32_t Next_check_frame;
+} SRB_INFO_TABLE_ENTRY_NB_IoT;
+
+//MEAS_REPORT_LIST_s not implemented in NB-IoT but is used at UE side
+//HANDOVER_INFO_UE not implemented in NB-IoT
+typedef struct HANDOVER_INFO_UE_NB_IoT_s {
+  PhysCellId_t targetCellId;
+  uint8_t measFlag;
+} HANDOVER_INFO_UE_NB_IoT;
+
+//NB-IoT eNB_RRC_UE_NB_IoT_s--(used as a context in eNB --> ue_context in rrc_eNB_ue_context)------
+typedef struct eNB_RRC_UE_NB_IoT_s {
+  uint8_t                            primaryCC_id;
+  //in NB-IoT only SRB0, SRB1 and SRB1bis (until AS security activation) exist
+
+  /*MP: Concept behind List and List2
+   *
+   * SRB_configList --> is used for the actual list of SRBs that is managed/that should be send over the RRC message
+   * SRB_configList2--> refers to all the SRBs configured for that specific transaction identifier
+   * 					this because in a single transaction one or more SRBs could be established
+   * 					and you want to keep memory on what happen for every transaction
+   * Transaction ID (xid): is used to associate the proper RRC....Complete message received by the UE to the corresponding
+   * 					   message previously sent by the eNB (e.g. RRCConnectionSetup -- RRCConnectionSetupComplete)
+   * 					   this because it could happen that more messages are transmitted at the same time
+   */
+  SRB_ToAddModList_NB_r13_t*                SRB_configList;//for SRB1 and SRB1bis
+  SRB_ToAddModList_NB_r13_t*                SRB_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER];
+  DRB_ToAddModList_NB_r13_t*                DRB_configList; //for all the DRBs
+  DRB_ToAddModList_NB_r13_t*                DRB_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER]; //for the configured DRBs of a xid
+  uint8_t                            		DRB_active[2];//in LTE was 8 --> at most 2 for NB-IoT
+
+  struct PhysicalConfigDedicated_NB_r13*    physicalConfigDedicated_NB_IoT;
+  MAC_MainConfig_NB_r13_t*           mac_MainConfig_NB_IoT;
+
+  //No SPS(semi-persistent scheduling) in NB-IoT
+  //No Measurement report in NB-IoT
+
+  SRB_INFO_NB_IoT                           SI;
+  SRB_INFO_NB_IoT                           Srb0;
+  SRB_INFO_TABLE_ENTRY_NB_IoT               Srb1;
+  SRB_INFO_TABLE_ENTRY_NB_IoT               Srb1bis;
+
+#if defined(ENABLE_SECURITY)
+  /* KeNB as derived from KASME received from EPC */
+  uint8_t kenb[32];
+#endif
+
+  /* Used integrity/ciphering algorithms--> maintained the same for NB-IoT */
+  e_CipheringAlgorithm_r12     ciphering_algorithm; //Specs. TS 36.331 V14.1.0 pag 432 Change position of chipering enumerative w.r.t previous version
+  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
+
+  uint8_t                            Status;
+  rnti_t                             rnti;
+  uint64_t                           random_ue_identity;
+
+
+
+  /* Information from UE RRC ConnectionRequest-NB-r13_IE--> NB-IoT */
+  UE_S_TMSI_NB_IoT                          Initialue_identity_s_TMSI;
+  EstablishmentCause_NB_r13_t               establishment_cause_NB_IoT; //different set for NB-IoT
+
+  /* Information from UE RRC ConnectionReestablishmentRequest-NB--> NB-IoT */
+  ReestablishmentCause_NB_r13_t             reestablishment_cause_NB_IoT; //different set for NB_IoT
+
+  /* UE id for initial connection to S1AP */
+  uint16_t                           ue_initial_id;
+
+  /* Information from S1AP initial_context_setup_req */
+  uint32_t                           eNB_ue_s1ap_id :24;
+
+  security_capabilities_t            security_capabilities;
+
+  /* Total number of e_rab already setup in the list */ //NAS list?
+  uint8_t                           setup_e_rabs;
+  /* Number of e_rab to be setup in the list */ //NAS list?
+  uint8_t                            nb_of_e_rabs;
+  /* list of e_rab to be setup by RRC layers */
+  e_rab_param_NB_IoT_t                      e_rab[NB_RB_MAX_NB_IOT];//[S1AP_MAX_E_RAB];
+
+  // LG: For GTPV1 TUNNELS
+  uint32_t                           enb_gtp_teid[S1AP_MAX_E_RAB];
+  transport_layer_addr_t             enb_gtp_addrs[S1AP_MAX_E_RAB];
+  rb_id_t                            enb_gtp_ebi[S1AP_MAX_E_RAB];
+
+ //Which timers are referring to?
+  uint32_t                           ul_failure_timer;
+  uint32_t                           ue_release_timer;
+  //threshold of the release timer--> set in RRCConnectionRelease
+  uint32_t                           ue_release_timer_thres;
+} eNB_RRC_UE_NB_IoT_t;
+//--------------------------------------------------------------------------------
+
+typedef uid_NB_IoT_t ue_uid_t;
+
+
+//generally variable called: ue_context_pP
+typedef struct rrc_eNB_ue_context_NB_IoT_s {
+
+  /* Tree related data */
+  RB_ENTRY(rrc_eNB_ue_context_NB_IoT_s) entries;
+
+  /* Uniquely identifies the UE between MME and eNB within the eNB.
+   * This id is encoded on 24bits.
+   */
+  rnti_t         ue_id_rnti;
+
+  // another key for protocol layers but should not be used as a key for RB tree
+  ue_uid_t       local_uid;
+
+  /* UE id for initial connection to S1AP */
+  struct eNB_RRC_UE_NB_IoT_s   ue_context; //context of ue in the e-nB
+
+} rrc_eNB_ue_context_NB_IoT_t;
+
+
+
+//---NB-IoT (completely changed)-------------------------------
+//called "carrier"--> data from PHY layer
+typedef struct {
+
+  // buffer that contains the encoded messages
+  uint8_t							*MIB_NB_IoT;
+  uint8_t							sizeof_MIB_NB_IoT;
+
+  uint8_t                           *SIB1_NB_IoT;
+  uint8_t                           sizeof_SIB1_NB_IoT;
+  uint8_t                         	*SIB23_NB_IoT;
+  uint8_t                        	sizeof_SIB23_NB_IoT;
+
+
+  //not actually implemented in OAI
+  uint8_t                           *SIB4_NB_IoT;
+  uint8_t                           sizeof_SIB4_NB_IoT;
+  uint8_t                           *SIB5_NB_IoT;
+  uint8_t                           sizeof_SIB5_NB_IoT;
+  uint8_t                           *SIB14_NB_IoT;
+  uint8_t                           sizeof_SIB14_NB_IoT;
+  uint8_t                           *SIB16_NB_IoT;
+  uint8_t                           sizeof_SIB16_NB_IoT;
+
+  //TS 36.331 V14.2.1
+//  uint8_t                           *SIB15_NB;
+//  uint8_t                           sizeof_SIB15_NB;
+//  uint8_t                           *SIB20_NB;
+//  uint8_t                           sizeof_SIB20_NB;
+//  uint8_t                           *SIB22_NB;
+//  uint8_t                           sizeof_SIB22_NB;
+
+  //implicit parameters needed
+  int                               Ncp; //cyclic prefix for DL
+  int								Ncp_UL; //cyclic prefix for UL
+  int                               p_eNB; //number of tx antenna port
+  int								p_rx_eNB; //number of receiving antenna ports
+  uint32_t                          dl_CarrierFreq; //detected by the UE
+  uint32_t                          ul_CarrierFreq; //detected by the UE
+  uint16_t                          physCellId; //not stored in the MIB-NB but is getting through NPSS/NSSS
+
+  //are the only static one (memory has been already allocated)
+  BCCH_BCH_Message_NB_t                mib_NB_IoT;
+  BCCH_DL_SCH_Message_NB_t             siblock1_NB_IoT; //SIB1-NB
+  BCCH_DL_SCH_Message_NB_t             systemInformation_NB_IoT; //SI
+
+  SystemInformationBlockType1_NB_t     		*sib1_NB_IoT;
+  SystemInformationBlockType2_NB_r13_t   	*sib2_NB_IoT;
+  SystemInformationBlockType3_NB_r13_t   	*sib3_NB_IoT;
+  //not implemented yet
+  SystemInformationBlockType4_NB_r13_t    	*sib4_NB_IoT;
+  SystemInformationBlockType5_NB_r13_t     	*sib5_NB_IoT;
+  SystemInformationBlockType14_NB_r13_t     *sib14_NB_IoT;
+  SystemInformationBlockType16_NB_r13_t     *sib16_NB_IoT;
+
+
+  SRB_INFO_NB_IoT                          SI;
+  SRB_INFO_NB_IoT                          Srb0;
+
+  uint8_t                           **MCCH_MESSAGE; //  probably not needed , but added to remove errors
+  uint8_t                           sizeof_MCCH_MESSAGE[8];// but added to remove errors
+  SRB_INFO_NB_IoT                          MCCH_MESS[8];// MAX_MBSFN_AREA
+  /*future implementation TS 36.331 V14.2.1
+  SystemInformationBlockType15_NB_r14_t     *sib15;
+  SystemInformationBlockType20_NB_r14_t     *sib20;
+  SystemInformationBlockType22_NB_r14_t     *sib22;
+
+  uint8_t							SCPTM_flag;
+  uint8_t							sizeof_SC_MCHH_MESS[];
+  SC_MCCH_Message_NB_t				scptm;*/
+
+
+} rrc_eNB_carrier_data_NB_IoT_t;
+//---------------------------------------------------
+
+
+
+//---NB-IoT---(completely change)---------------------
+typedef struct eNB_RRC_INST_NB_IoT_s {
+
+  rrc_eNB_carrier_data_NB_IoT_t          carrier[MAX_NUM_CCs];
+
+  uid_allocator_NB_IoT_t                    uid_allocator; // for rrc_ue_head
+  RB_HEAD(rrc_ue_tree_NB_IoT_s, rrc_eNB_ue_context_NB_IoT_s)     rrc_ue_head; // ue_context tree key search by rnti
+
+  uint8_t                           Nb_ue;
+
+  hash_table_t                      *initial_id2_s1ap_ids; // key is    content is rrc_ue_s1ap_ids_t
+  hash_table_t                      *s1ap_id2_s1ap_ids   ; // key is    content is rrc_ue_s1ap_ids_t
+
+  //RRC configuration
+  RrcConfigurationReq configuration; //rrc_messages_types.h
+
+  // other PLMN parameters
+  /// Mobile country code
+  int mcc;
+  /// Mobile network code
+  int mnc;
+  /// number of mnc digits
+  int mnc_digit_length;
+
+  // other RAN parameters //FIXME: to be checked--> depends on APP layer
+  int srb1_timer_poll_retransmit;
+  int srb1_max_retx_threshold;
+  int srb1_timer_reordering;
+  int srb1_timer_status_prohibit;
+  int srs_enable[MAX_NUM_CCs];
+
+
+} eNB_RRC_INST_NB_IoT;
+
+#define RRC_HEADER_SIZE_MAX_NB_IoT 64
+#define MAX_UE_CAPABILITY_SIZE_NB_IoT 255
+
+//not needed for the moment
+typedef struct OAI_UECapability_NB_IoT_s {
+ uint8_t sdu[MAX_UE_CAPABILITY_SIZE_NB_IoT];
+ uint8_t sdu_size;
+////NB-IoT------
+  UE_Capability_NB_r13_t  UE_Capability_NB_IoT; //replace the UE_EUTRA_Capability of LTE
+} OAI_UECapability_NB_IoT_t;
+
+#define RRC_BUFFER_SIZE_MAX_NB_IoT 1024
+
+
+
+typedef struct UE_RRC_INST_NB_IoT_s {
+  Rrc_State_NB_IoT_t     RrcState;
+  Rrc_Sub_State_NB_IoT_t RrcSubState;
+# if defined(ENABLE_USE_MME)
+  plmn_t          plmnID;
+  Byte_t          rat;
+  as_nas_info_t   initialNasMsg;
+# endif
+  OAI_UECapability_NB_IoT_t *UECap;
+  uint8_t *UECapability;
+  uint8_t UECapability_size;
+
+  UE_RRC_INFO_NB_IoT Info[NB_SIG_CNX_UE];
+  
+  SRB_INFO_NB_IoT                 Srb0[NB_SIG_CNX_UE];
+  SRB_INFO_TABLE_ENTRY_NB_IoT     Srb1[NB_CNX_UE];
+  SRB_INFO_TABLE_ENTRY_NB_IoT     Srb2[NB_CNX_UE];
+  HANDOVER_INFO_UE_NB_IoT         HandoverInfoUe;
+  /*
+  uint8_t *SIB1[NB_CNX_UE];
+  uint8_t sizeof_SIB1[NB_CNX_UE];
+  uint8_t *SI[NB_CNX_UE];
+  uint8_t sizeof_SI[NB_CNX_UE];
+  uint8_t SIB1Status[NB_CNX_UE];
+  uint8_t SIStatus[NB_CNX_UE];
+  SystemInformationBlockType1_t *sib1[NB_CNX_UE];
+  SystemInformation_t *si[NB_CNX_UE]; //!< Temporary storage for an SI message. Decoding happens in decode_SI().
+  */
+  SystemInformationBlockType2_t *sib2[NB_CNX_UE];
+  /*
+  SystemInformationBlockType3_t *sib3[NB_CNX_UE];
+  SystemInformationBlockType4_t *sib4[NB_CNX_UE];
+  SystemInformationBlockType5_t *sib5[NB_CNX_UE];
+  SystemInformationBlockType6_t *sib6[NB_CNX_UE];
+  SystemInformationBlockType7_t *sib7[NB_CNX_UE];
+  SystemInformationBlockType8_t *sib8[NB_CNX_UE];
+  SystemInformationBlockType9_t *sib9[NB_CNX_UE];
+  SystemInformationBlockType10_t *sib10[NB_CNX_UE];
+  SystemInformationBlockType11_t *sib11[NB_CNX_UE];
+
+#if defined(Rel10) || defined(Rel14)
+  uint8_t                           MBMS_flag;
+  uint8_t *MCCH_MESSAGE[NB_CNX_UE];
+  uint8_t sizeof_MCCH_MESSAGE[NB_CNX_UE];
+  uint8_t MCCH_MESSAGEStatus[NB_CNX_UE];
+  MBSFNAreaConfiguration_r9_t       *mcch_message[NB_CNX_UE];
+  SystemInformationBlockType12_r9_t *sib12[NB_CNX_UE];
+  SystemInformationBlockType13_r9_t *sib13[NB_CNX_UE];
+#endif
+#ifdef CBA
+  uint8_t                         num_active_cba_groups;
+  uint16_t                        cba_rnti[NUM_MAX_CBA_GROUP];
+#endif
+  uint8_t                         num_srb;
+  struct SRB_ToAddMod             *SRB1_config[NB_CNX_UE];
+  struct SRB_ToAddMod             *SRB2_config[NB_CNX_UE];
+  struct DRB_ToAddMod             *DRB_config[NB_CNX_UE][8];
+  rb_id_t                         *defaultDRB; // remember the ID of the default DRB
+  MeasObjectToAddMod_t            *MeasObj[NB_CNX_UE][MAX_MEAS_OBJ];
+  struct ReportConfigToAddMod     *ReportConfig[NB_CNX_UE][MAX_MEAS_CONFIG];
+  */
+  struct QuantityConfig           *QuantityConfig[NB_CNX_UE];
+  /*
+  struct MeasIdToAddMod           *MeasId[NB_CNX_UE][MAX_MEAS_ID];
+  MEAS_REPORT_LIST      *measReportList[NB_CNX_UE][MAX_MEAS_ID];
+  uint32_t           measTimer[NB_CNX_UE][MAX_MEAS_ID][6]; // 6 neighboring cells
+  RSRP_Range_t                    s_measure;
+  struct MeasConfig__speedStatePars *speedStatePars;
+  struct PhysicalConfigDedicated  *physicalConfigDedicated[NB_CNX_UE];
+  struct SPS_Config               *sps_Config[NB_CNX_UE];
+  MAC_MainConfig_t                *mac_MainConfig[NB_CNX_UE];
+  MeasGapConfig_t                 *measGapConfig[NB_CNX_UE];
+  double                          filter_coeff_rsrp; // [7] ???
+  double                          filter_coeff_rsrq; // [7] ???
+  float                           rsrp_db[7];
+  float                           rsrq_db[7];
+  float                           rsrp_db_filtered[7];
+  float                           rsrq_db_filtered[7];
+#if ENABLE_RAL
+  obj_hash_table_t               *ral_meas_thresholds;
+  ral_transaction_id_t            scan_transaction_id;
+#endif
+#if defined(ENABLE_SECURITY)
+  // KeNB as computed from parameters within USIM card //
+  uint8_t kenb[32];
+#endif
+
+  // Used integrity/ciphering algorithms //
+  CipheringAlgorithm_r12_t                          ciphering_algorithm;
+  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
+  */
+} UE_RRC_INST_NB_IoT;
+
+
+#include "proto_NB_IoT.h" //should be put here otherwise compilation error
+
+#endif
+/** @} */
diff --git a/openair2/RRC/LITE/defs_nb_iot.h b/openair2/RRC/LITE/defs_nb_iot.h
deleted file mode 100644
index 133868429b69e58b04b42c338cb1e21a07302c96..0000000000000000000000000000000000000000
--- a/openair2/RRC/LITE/defs_nb_iot.h
+++ /dev/null
@@ -1,746 +0,0 @@
-/* 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.0  (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 RRC/LITE/defs_nb_iot.h
-* \brief NB-IoT RRC struct definitions and function prototypes
-* \author Navid Nikaein, Raymond Knopp and Michele Paffetti
-* \date 2010 - 2014, 2017
-* \version 1.0
-* \company Eurecom
-* \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr, michele.paffetti@studio.unibo.it
-*/
-
-#ifndef __OPENAIR_RRC_DEFS_NB_IOT_H__
-#define __OPENAIR_RRC_DEFS_NB_IOT_H__
-
-
-#ifdef USER_MODE
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#endif
-
-#include "collection/tree.h"
-#include "rrc_types.h"
-#include "PHY/defs.h"
-#include "COMMON/platform_constants.h"
-#include "COMMON/platform_types.h"
-
-#include "COMMON/mac_rrc_primitives.h"
-#include "LAYER2/MAC/defs.h"
-
-//#include "COMMON/openair_defs.h"
-#ifndef USER_MODE
-#include <rtai.h>
-#endif
-
-
-
-//----Not needed for NB-IoT??-------- (but have to left for UE?)
-//#include "SystemInformationBlockType1.h"
-//#include "SystemInformation.h"
-//#include "RRCConnectionReconfiguration.h"
-//#include "RRCConnectionReconfigurationComplete.h"
-//#include "RRCConnectionSetup.h"
-//#include "RRCConnectionSetupComplete.h"
-//#include "RRCConnectionRequest.h"
-//#include "RRCConnectionReestablishmentRequest.h"
-//#include "BCCH-DL-SCH-Message.h"
-//#include "BCCH-BCH-Message.h"
-//
-//#if defined(Rel10) || defined(Rel14)
-//#include "MCCH-Message.h"
-//#include "MBSFNAreaConfiguration-r9.h"
-//#include "SCellToAddMod-r10.h"
-//#endif
-//
-//#include "AS-Config.h"
-//#include "AS-Context.h"
-//#include "UE-EUTRA-Capability.h"
-//#include "MeasResults.h"
-//--------------------------------------
-
-
-//-----NB-IoT #include files-------
-
-#include "SystemInformationBlockType1-NB.h"
-#include "SystemInformation-NB.h"
-#include "RRCConnectionReconfiguration-NB.h"
-#include "RRCConnectionReconfigurationComplete-NB.h"
-#include "RRCConnectionSetup-NB.h"
-#include "RRCConnectionSetupComplete-NB.h"
-#include "RRCConnectionRequest-NB.h"
-#include "RRCConnectionReestablishmentRequest-NB.h"
-#include "BCCH-DL-SCH-Message-NB.h"
-#include "BCCH-BCH-Message-NB.h"
-#include "AS-Config-NB.h"
-#include "AS-Context-NB.h"
-#include "UE-Capability-NB-r13.h" //equivalent of UE-EUTRA-Capability.h
-//-------------------
-
-
-/* correct Rel(8|10)/Rel14 differences
- * the code is in favor of Rel14, those defines do the translation
- */
-#if !defined(Rel14)
-#  define CipheringAlgorithm_r12_t e_SecurityAlgorithmConfig__cipheringAlgorithm
-#  define CipheringAlgorithm_r12_t e_CipheringAlgorithm_r12 //maybe this solve the problem of the previous line
-#  define CipheringAlgorithm_r12_eea0 SecurityAlgorithmConfig__cipheringAlgorithm_eea0
-#  define CipheringAlgorithm_r12_eea1 SecurityAlgorithmConfig__cipheringAlgorithm_eea1
-#  define CipheringAlgorithm_r12_eea2 SecurityAlgorithmConfig__cipheringAlgorithm_eea2
-#  define CipheringAlgorithm_r12_spare1 SecurityAlgorithmConfig__cipheringAlgorithm_spare1
-#  define Alpha_r12_al0 UplinkPowerControlCommon__alpha_al0
-#  define Alpha_r12_al04 UplinkPowerControlCommon__alpha_al04
-#  define Alpha_r12_al05 UplinkPowerControlCommon__alpha_al05
-#  define Alpha_r12_al06 UplinkPowerControlCommon__alpha_al06
-#  define Alpha_r12_al07 UplinkPowerControlCommon__alpha_al07
-#  define Alpha_r12_al08 UplinkPowerControlCommon__alpha_al08
-#  define Alpha_r12_al09 UplinkPowerControlCommon__alpha_al09
-#  define Alpha_r12_al1 UplinkPowerControlCommon__alpha_al1
-#  define PreambleTransMax_t e_PreambleTransMax //maybe this solve problem (asn1_msg_nb_iot.c line 726)
-#  define PreambleTransMax_n3 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n3
-#  define PreambleTransMax_n4 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n4
-#  define PreambleTransMax_n5 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n5
-#  define PreambleTransMax_n6 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n6
-#  define PreambleTransMax_n7 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n7
-#  define PreambleTransMax_n8 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n8
-#  define PreambleTransMax_n10 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n10
-#  define PreambleTransMax_n20 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n20
-#  define PreambleTransMax_n50 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n50
-#  define PreambleTransMax_n100 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n100
-#  define PreambleTransMax_n200 RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n200
-#  define PeriodicBSR_Timer_r12_sf5 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf5
-#  define PeriodicBSR_Timer_r12_sf10 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf10
-#  define PeriodicBSR_Timer_r12_sf16 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf16
-#  define PeriodicBSR_Timer_r12_sf20 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf20
-#  define PeriodicBSR_Timer_r12_sf32 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf32
-#  define PeriodicBSR_Timer_r12_sf40 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf40
-#  define PeriodicBSR_Timer_r12_sf64 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf64
-#  define PeriodicBSR_Timer_r12_sf80 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf80
-#  define PeriodicBSR_Timer_r12_sf128 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf128
-#  define PeriodicBSR_Timer_r12_sf160 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf160
-#  define PeriodicBSR_Timer_r12_sf320 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf320
-#  define PeriodicBSR_Timer_r12_sf640 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf640
-#  define PeriodicBSR_Timer_r12_sf1280 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf1280
-#  define PeriodicBSR_Timer_r12_sf2560 MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_sf2560
-#  define PeriodicBSR_Timer_r12_infinity MAC_MainConfig__ul_SCH_Config__periodicBSR_Timer_infinity
-#  define RetxBSR_Timer_r12_sf320 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf320
-#  define RetxBSR_Timer_r12_sf640 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf640
-#  define RetxBSR_Timer_r12_sf1280 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf1280
-#  define RetxBSR_Timer_r12_sf2560 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf2560
-#  define RetxBSR_Timer_r12_sf5120 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf5120
-#  define RetxBSR_Timer_r12_sf10240 MAC_MainConfig__ul_SCH_Config__retxBSR_Timer_sf10240
-#endif
-
-// This corrects something generated by asn1c which is different between Rel8 and Rel10
-#if !defined(Rel10) && !defined(Rel14)
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member SystemInformation_r8_IEs_sib_TypeAndInfo_Member
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib2 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib2
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib3 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib3
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib4 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib4
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib5 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib5
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib6 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib6
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib7 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib7
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib8 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib8
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib9 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib9
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib10 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib10
-#define SystemInformation_r8_IEs__sib_TypeAndInfo__Member_PR_sib11 SystemInformation_r8_IEs_sib_TypeAndInfo_Member_PR_sib11
-#endif
-
-
-#ifndef NO_RRM
-#include "L3_rrc_interface.h"
-#include "rrc_rrm_msg.h"
-#include "rrc_rrm_interface.h"
-#endif
-
-#if defined(ENABLE_ITTI)
-# include "intertask_interface.h"
-#endif
-
-/* TODO: be sure this include is correct.
- * It solves a problem of compilation of the RRH GW,
- * issue #186.
- */
-#if !defined(ENABLE_ITTI)
-# include "as_message.h"
-#endif
-
-#if defined(ENABLE_USE_MME)
-# include "commonDef.h"
-#endif
-
-#if ENABLE_RAL
-# include "collection/hashtable/obj_hashtable.h"
-#endif
-
-
-
-/*I will change the name of the structure for compile purposes--> hope not to undo this process*/
-
-typedef unsigned int uid_NB_t;
-#define UID_LINEAR_ALLOCATOR_BITMAP_SIZE (((NUMBER_OF_UE_MAX/8)/sizeof(unsigned int)) + 1)
-
-typedef struct uid_linear_allocator_NB_s {
-  unsigned int   bitmap[UID_LINEAR_ALLOCATOR_BITMAP_SIZE];
-} uid_allocator_NB_t;
-
-
-#define PROTOCOL_RRC_CTXT_UE_FMT           PROTOCOL_CTXT_FMT
-#define PROTOCOL_RRC_CTXT_UE_ARGS(CTXT_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp)
-
-#define PROTOCOL_RRC_CTXT_FMT           PROTOCOL_CTXT_FMT
-#define PROTOCOL_RRC_CTXT_ARGS(CTXT_Pp) PROTOCOL_CTXT_ARGS(CTXT_Pp)
-
-/** @defgroup _rrc RRC
- * @ingroup _oai2
- * @{
- */
-
-
-//#define NUM_PRECONFIGURED_LCHAN (NB_CH_CX*2)  //BCCH, CCCH
-
-#define UE_MODULE_INVALID ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!!
-#define UE_INDEX_INVALID  ((module_id_t) ~0) // FIXME attention! depends on type uint8_t!!! used to be -1
-
-
-//left as they are --> used in LAYER2/epenair2_proc.c and UE side
-//typedef enum UE_STATE_NB_e {
-//  RRC_INACTIVE=0,
-//  RRC_IDLE,
-//  RRC_SI_RECEIVED,
-//  RRC_CONNECTED,
-//  RRC_RECONFIGURED,
-//  RRC_HO_EXECUTION //maybe not needed?
-//} UE_STATE_NB_t;
-
-
-// HO_STATE is not supported by NB-IoT
-
-//#define NUMBER_OF_UE_MAX MAX_MOBILES_PER_RG
-#define RRM_FREE(p)       if ( (p) != NULL) { free(p) ; p=NULL ; }
-#define RRM_MALLOC(t,n)   (t *) malloc16( sizeof(t) * n )
-#define RRM_CALLOC(t,n)   (t *) malloc16( sizeof(t) * n)
-#define RRM_CALLOC2(t,s)  (t *) malloc16( s )
-
-//Measurement Report not supported in NB-IoT
-
-#define PAYLOAD_SIZE_MAX 1024
-#define RRC_BUF_SIZE 255
-#define UNDEF_SECURITY_MODE 0xff
-#define NO_SECURITY_MODE 0x20
-
-/* TS 36.331: RRC-TransactionIdentifier ::= INTEGER (0..3) */
-#define RRC_TRANSACTION_IDENTIFIER_NUMBER  3
-
-//NB-IoT version (not used for the moment)
-//typedef struct UE_RRC_INFO_s { //is used in UE_RRC_INST
-//  UE_STATE_NB_t State;
-//  uint8_t SIB1systemInfoValueTag;
-//  uint32_t SIStatus;
-//  uint32_t SIcnt;
-//#if defined(Rel10) || defined(Rel14)
-//  uint8_t MCCHStatus[8]; // MAX_MBSFN_AREA
-//#endif
-//  uint8_t SIwindowsize; //!< Corresponds to the SIB1 si-WindowLength parameter. The unit is ms. Possible values are (final): 1,2,5,10,15,20,40
-//  uint8_t handoverTarget;
-//  HO_STATE_t ho_state;
-//  uint16_t SIperiod; //!< Corresponds to the SIB1 si-Periodicity parameter (multiplied by 10). Possible values are (final): 80,160,320,640,1280,2560,5120
-//  unsigned short UE_index;
-//  uint32_t T300_active;
-//  uint32_t T300_cnt;
-//  uint32_t T304_active;
-//  uint32_t T304_cnt;
-//  uint32_t T310_active;
-//  uint32_t T310_cnt;
-//  uint32_t N310_cnt;
-//  uint32_t N311_cnt;
-//  rnti_t   rnti;
-//} __attribute__ ((__packed__)) UE_RRC_INFO;
-
-
-
-//left as it is
-typedef struct UE_S_TMSI_NB_s {
-  boolean_t  presence;
-  mme_code_t mme_code;
-  m_tmsi_t   m_tmsi;
-} __attribute__ ((__packed__)) UE_S_TMSI_NB;
-
-
-typedef enum e_rab_satus_NB_e {
-  E_RAB_NB_STATUS_NEW,
-  E_RAB_NB_STATUS_DONE, // from the eNB perspective
-  E_RAB_NB_STATUS_ESTABLISHED, // get the reconfigurationcomplete form UE
-  E_RAB_NB_STATUS_FAILED,
-} e_rab_status_NB_t;
-
-typedef struct e_rab_param_NB_s {
-  e_rab_t param;
-  uint8_t status;
-  uint8_t xid; // transaction_id
-} __attribute__ ((__packed__)) e_rab_param_NB_t;
-
-
-//HANDOVER_INFO not implemented in NB-IoT delete
-
-
-#define RRC_HEADER_SIZE_MAX 64
-#define RRC_BUFFER_SIZE_MAX 1024
-
-typedef struct {
-  char Payload[RRC_BUFFER_SIZE_MAX];
-  char Header[RRC_HEADER_SIZE_MAX];
-  char payload_size;
-} RRC_BUFFER_NB;
-
-#define RRC_BUFFER_SIZE_NB sizeof(RRC_BUFFER_NB)
-
-
-typedef struct RB_INFO_NB_s {
-  uint16_t Rb_id;  //=Lchan_id
-  LCHAN_DESC Lchan_desc[2]; //MP: Lchan_desc is an old structure no more used in general --> remove also where it is setup
-  //MAC_MEAS_REQ_ENTRY *Meas_entry; //may not needed for NB-IoT
-} RB_INFO_NB;
-
-typedef struct SRB_INFO_NB_s {
-  uint16_t Srb_id;  //=Lchan_id---> useful for distinguish between SRB1 and SRB1bis?
-  RRC_BUFFER_NB Rx_buffer;
-  RRC_BUFFER_NB Tx_buffer;
-  LCHAN_DESC Lchan_desc[2]; //MP: Lchan_desc is an old structure no more used in general --> remove also where it is setup
-  unsigned int Trans_id;
-  uint8_t Active;
-} SRB_INFO_NB;
-
-
-typedef struct RB_INFO_TABLE_ENTRY_NB_s {
-  RB_INFO_NB Rb_info;
-  uint8_t Active;
-  uint32_t Next_check_frame;
-  uint8_t Status;
-} RB_INFO_TABLE_ENTRY_NB;
-
-typedef struct SRB_INFO_TABLE_ENTRY_NB_s {
-  SRB_INFO_NB Srb_info;
-  uint8_t Active;
-  uint8_t Status;
-  uint32_t Next_check_frame;
-} SRB_INFO_TABLE_ENTRY_NB;
-
-//MEAS_REPORT_LIST_s not implemented in NB-IoT but is used at UE side
-//HANDOVER_INFO_UE not implemented in NB-IoT
-
-
-//NB-IoT eNB_RRC_UE_NB_s--(used as a context in eNB --> ue_context in rrc_eNB_ue_context)------
-typedef struct eNB_RRC_UE_NB_s {
-  uint8_t                            primaryCC_id;
-  //in NB-IoT only SRB0, SRB1 and SRB1bis (until AS security activation) exist
-
-  /*MP: Concept behind List and List2
-   *
-   * SRB_configList --> is used for the actual list of SRBs that is managed/that should be send over the RRC message
-   * SRB_configList2--> refers to all the SRBs configured for that specific transaction identifier
-   * 					this because in a single transaction one or more SRBs could be established
-   * 					and you want to keep memory on what happen for every transaction
-   * Transaction ID (xid): is used to associate the proper RRC....Complete message received by the UE to the corresponding
-   * 					   message previously sent by the eNB (e.g. RRCConnectionSetup -- RRCConnectionSetupComplete)
-   * 					   this because it could happen that more messages are transmitted at the same time
-   */
-  SRB_ToAddModList_NB_r13_t*                SRB_configList;//for SRB1 and SRB1bis
-  SRB_ToAddModList_NB_r13_t*                SRB_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER];
-  DRB_ToAddModList_NB_r13_t*                DRB_configList; //for all the DRBs
-  DRB_ToAddModList_NB_r13_t*                DRB_configList2[RRC_TRANSACTION_IDENTIFIER_NUMBER]; //for the configured DRBs of a xid
-  uint8_t                            		DRB_active[2];//in LTE was 8 --> at most 2 for NB-IoT
-
-  struct PhysicalConfigDedicated_NB_r13*    physicalConfigDedicated_NB;
-  MAC_MainConfig_NB_r13_t*           mac_MainConfig_NB;
-
-  //No SPS(semi-persistent scheduling) in NB-IoT
-  //No Measurement report in NB-IoT
-
-  SRB_INFO_NB                           SI;
-  SRB_INFO_NB                           Srb0;
-  SRB_INFO_TABLE_ENTRY_NB               Srb1;
-  SRB_INFO_TABLE_ENTRY_NB               Srb1bis;
-
-#if defined(ENABLE_SECURITY)
-  /* KeNB as derived from KASME received from EPC */
-  uint8_t kenb[32];
-#endif
-
-  /* Used integrity/ciphering algorithms--> maintained the same for NB-IoT */
-  e_CipheringAlgorithm_r12     ciphering_algorithm; //Specs. TS 36.331 V14.1.0 pag 432 Change position of chipering enumerative w.r.t previous version
-  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
-
-  uint8_t                            Status;
-  rnti_t                             rnti;
-  uint64_t                           random_ue_identity;
-
-
-
-  /* Information from UE RRC ConnectionRequest-NB-r13_IE--> NB-IoT */
-  UE_S_TMSI_NB                          Initialue_identity_s_TMSI;
-  EstablishmentCause_NB_r13_t               establishment_cause_NB; //different set for NB-IoT
-
-  /* Information from UE RRC ConnectionReestablishmentRequest-NB--> NB-IoT */
-  ReestablishmentCause_NB_r13_t             reestablishment_cause_NB; //different set for NB_IoT
-
-  /* UE id for initial connection to S1AP */
-  uint16_t                           ue_initial_id;
-
-  /* Information from S1AP initial_context_setup_req */
-  uint32_t                           eNB_ue_s1ap_id :24;
-
-  security_capabilities_t            security_capabilities;
-
-  /* Total number of e_rab already setup in the list */ //NAS list?
-  uint8_t                           setup_e_rabs;
-  /* Number of e_rab to be setup in the list */ //NAS list?
-  uint8_t                            nb_of_e_rabs;
-  /* list of e_rab to be setup by RRC layers */
-  e_rab_param_NB_t                      e_rab[NB_RB_MAX_NB_IOT];//[S1AP_MAX_E_RAB];
-
-  // LG: For GTPV1 TUNNELS
-  uint32_t                           enb_gtp_teid[S1AP_MAX_E_RAB];
-  transport_layer_addr_t             enb_gtp_addrs[S1AP_MAX_E_RAB];
-  rb_id_t                            enb_gtp_ebi[S1AP_MAX_E_RAB];
-
- //Which timers are referring to?
-  uint32_t                           ul_failure_timer;
-  uint32_t                           ue_release_timer;
-  //threshold of the release timer--> set in RRCConnectionRelease
-  uint32_t                           ue_release_timer_thres;
-} eNB_RRC_UE_NB_t;
-//--------------------------------------------------------------------------------
-
-typedef uid_NB_t ue_uid_t;
-
-
-//generally variable called: ue_context_pP
-typedef struct rrc_eNB_ue_context_NB_s {
-
-  /* Tree related data */
-  RB_ENTRY(rrc_eNB_ue_context_NB_s) entries;
-
-  /* Uniquely identifies the UE between MME and eNB within the eNB.
-   * This id is encoded on 24bits.
-   */
-  rnti_t         ue_id_rnti;
-
-  // another key for protocol layers but should not be used as a key for RB tree
-  ue_uid_t       local_uid;
-
-  /* UE id for initial connection to S1AP */
-  struct eNB_RRC_UE_NB_s   ue_context; //context of ue in the e-nB
-
-} rrc_eNB_ue_context_NB_t;
-
-
-
-//---NB-IoT (completely changed)-------------------------------
-//called "carrier"--> data from PHY layer
-typedef struct {
-
-  // buffer that contains the encoded messages
-  uint8_t							*MIB_NB;
-  uint8_t							sizeof_MIB_NB;
-
-  uint8_t                           *SIB1_NB;
-  uint8_t                           sizeof_SIB1_NB;
-  uint8_t                         	*SIB23_NB;
-  uint8_t                        	sizeof_SIB23_NB;
-
-  //uint8_t                           *SIB2_NB;
-  //uint8_t                           sizeof_SIB2_NB;
-  //uint8_t                           *SIB3_NB;
-  //uint8_t                           sizeof_SIB3_NB;
-
-  //not actually implemented in OAI
-  uint8_t                           *SIB4_NB;
-  uint8_t                           sizeof_SIB4_NB;
-  uint8_t                           *SIB5_NB;
-  uint8_t                           sizeof_SIB5_NB;
-  uint8_t                           *SIB14_NB;
-  uint8_t                           sizeof_SIB14_NB;
-  uint8_t                           *SIB16_NB;
-  uint8_t                           sizeof_SIB16_NB;
-
-  //TS 36.331 V14.2.1
-  uint8_t                           *SIB15_NB;
-  uint8_t                           sizeof_SIB15_NB;
-  uint8_t                           *SIB20_NB;
-  uint8_t                           sizeof_SIB20_NB;
-  uint8_t                           *SIB22_NB;
-  uint8_t                           sizeof_SIB22_NB;
-
-  //implicit parameters needed
-  int                               Ncp; //extended cyclic prefix
-  int                               p_eNB; //number of antenna port (getting from the CRS of the MIB-NB)
-  uint32_t                          dl_CarrierFreq; //detected by the UE
-  uint32_t                          ul_CarrierFreq; //detected by the UE
-  uint16_t                          physCellId; //not stored in the MIB-NB but is getting through NPSS/NSSS
-
-  //are the only static one (memory has been already allocated)
-  BCCH_BCH_Message_NB_t                mib_NB;
-  BCCH_DL_SCH_Message_NB_t             siblock1_NB; //SIB1-NB
-  BCCH_DL_SCH_Message_NB_t             systemInformation_NB; //SI
-
-  //memory should be allocated--> in principle are only for commodity?
-  SystemInformationBlockType1_NB_t     		*sib1_NB;
-  SystemInformationBlockType2_NB_r13_t   	*sib2_NB;
-  SystemInformationBlockType3_NB_r13_t   	*sib3_NB;
-  //not implemented yet
-  SystemInformationBlockType4_NB_r13_t    	*sib4_NB;
-  SystemInformationBlockType5_NB_r13_t     	*sib5_NB;
-  SystemInformationBlockType14_NB_r13_t     *sib14_NB;
-  SystemInformationBlockType16_NB_r13_t     *sib16_NB;
-
-  /*future implementation TS 36.331 V14.2.1
-  SystemInformationBlockType15_NB_r14_t     *sib15;
-  SystemInformationBlockType20_NB_r14_t     *sib20;
-  SystemInformationBlockType22_NB_r14_t     *sib22;
-
-  uint8_t							SCPTM_flag;
-  uint8_t							sizeof_SC_MCHH_MESS[];
-  SC_MCCH_Message_NB_t				scptm;*/
-
-  SRB_INFO_NB                          SI;
-  SRB_INFO_NB                          Srb0;
-} rrc_eNB_carrier_data_NB_t;
-//---------------------------------------------------
-
-
-
-//---NB-IoT---(completely change)---------------------
-typedef struct eNB_RRC_INST_NB_s {
-
-  rrc_eNB_carrier_data_NB_t          carrier[MAX_NUM_CCs];
-
-  uid_allocator_NB_t                    uid_allocator; // for rrc_ue_head
-  RB_HEAD(rrc_ue_tree_NB_s, rrc_eNB_ue_context_NB_s)     rrc_ue_head; // ue_context tree key search by rnti
-
-  uint8_t                           Nb_ue;
-
-  hash_table_t                      *initial_id2_s1ap_ids; // key is    content is rrc_ue_s1ap_ids_t
-  hash_table_t                      *s1ap_id2_s1ap_ids   ; // key is    content is rrc_ue_s1ap_ids_t
-
-  //RRC configuration
-  RrcConfigurationReq configuration; //rrc_messages_types.h
-
-  // other PLMN parameters
-  /// Mobile country code
-  int mcc;
-  /// Mobile network code
-  int mnc;
-  /// number of mnc digits
-  int mnc_digit_length;
-
-  // other RAN parameters //FIXME: to be checked--> depends on APP layer
-  int srb1_timer_poll_retransmit;
-  int srb1_max_retx_threshold;
-  int srb1_timer_reordering;
-  int srb1_timer_status_prohibit;
-  int srs_enable[MAX_NUM_CCs];
-
-
-} eNB_RRC_INST_NB;
-
-
-#define MAX_UE_CAPABILITY_SIZE 255
-//not needed for the moment
-//typedef struct OAI_UECapability_s {
-//  uint8_t sdu[MAX_UE_CAPABILITY_SIZE];
-//  uint8_t sdu_size;
-////NB-IoT------
-//  UE_Capability_NB_r13_t	UE_Capability_NB; //replace the UE_EUTRA_Capability of LTE
-//} OAI_UECapability_t;
-
-
-//Old implementation --> see NB_iot version
-//typedef struct UE_RRC_INST_s {
-//  Rrc_State_t     RrcState;
-//  Rrc_Sub_State_t RrcSubState;
-//# if defined(ENABLE_USE_MME)
-//  plmn_t          plmnID;
-//  Byte_t          rat;
-//  as_nas_info_t   initialNasMsg;
-//# endif
-//  OAI_UECapability_t *UECap;
-//  uint8_t *UECapability;
-//  uint8_t UECapability_size;
-//  UE_RRC_INFO Info[NB_SIG_CNX_UE];
-//  SRB_INFO Srb0[NB_SIG_CNX_UE];
-//  SRB_INFO_TABLE_ENTRY Srb1[NB_CNX_UE];
-//  SRB_INFO_TABLE_ENTRY Srb2[NB_CNX_UE];
-//  HANDOVER_INFO_UE HandoverInfoUe;
-//  uint8_t *SIB1[NB_CNX_UE];
-//  uint8_t sizeof_SIB1[NB_CNX_UE];
-//  uint8_t *SI[NB_CNX_UE];
-//  uint8_t sizeof_SI[NB_CNX_UE];
-//  uint8_t SIB1Status[NB_CNX_UE];
-//  uint8_t SIStatus[NB_CNX_UE];
-//  SystemInformationBlockType1_t *sib1[NB_CNX_UE];
-//  SystemInformation_t *si[NB_CNX_UE]; //!< Temporary storage for an SI message. Decoding happens in decode_SI().
-//  SystemInformationBlockType2_t *sib2[NB_CNX_UE];
-//  SystemInformationBlockType3_t *sib3[NB_CNX_UE];
-//  SystemInformationBlockType4_t *sib4[NB_CNX_UE];
-//  SystemInformationBlockType5_t *sib5[NB_CNX_UE];
-//  SystemInformationBlockType6_t *sib6[NB_CNX_UE];
-//  SystemInformationBlockType7_t *sib7[NB_CNX_UE];
-//  SystemInformationBlockType8_t *sib8[NB_CNX_UE];
-//  SystemInformationBlockType9_t *sib9[NB_CNX_UE];
-//  SystemInformationBlockType10_t *sib10[NB_CNX_UE];
-//  SystemInformationBlockType11_t *sib11[NB_CNX_UE];
-//
-//#if defined(Rel10) || defined(Rel14)
-//  uint8_t                           MBMS_flag;
-//  uint8_t *MCCH_MESSAGE[NB_CNX_UE];
-//  uint8_t sizeof_MCCH_MESSAGE[NB_CNX_UE];
-//  uint8_t MCCH_MESSAGEStatus[NB_CNX_UE];
-//  MBSFNAreaConfiguration_r9_t       *mcch_message[NB_CNX_UE];
-//  SystemInformationBlockType12_r9_t *sib12[NB_CNX_UE];
-//  SystemInformationBlockType13_r9_t *sib13[NB_CNX_UE];
-//#endif
-//#ifdef CBA
-//  uint8_t                         num_active_cba_groups;
-//  uint16_t                        cba_rnti[NUM_MAX_CBA_GROUP];
-//#endif
-//  uint8_t                         num_srb;
-//  struct SRB_ToAddMod             *SRB1_config[NB_CNX_UE];
-//  struct SRB_ToAddMod             *SRB2_config[NB_CNX_UE];
-//  struct DRB_ToAddMod             *DRB_config[NB_CNX_UE][8];
-//  rb_id_t                         *defaultDRB; // remember the ID of the default DRB
-//  MeasObjectToAddMod_t            *MeasObj[NB_CNX_UE][MAX_MEAS_OBJ];
-//  struct ReportConfigToAddMod     *ReportConfig[NB_CNX_UE][MAX_MEAS_CONFIG];
-//  struct QuantityConfig           *QuantityConfig[NB_CNX_UE];
-//  struct MeasIdToAddMod           *MeasId[NB_CNX_UE][MAX_MEAS_ID];
-//  MEAS_REPORT_LIST      *measReportList[NB_CNX_UE][MAX_MEAS_ID];
-//  uint32_t           measTimer[NB_CNX_UE][MAX_MEAS_ID][6]; // 6 neighboring cells
-//  RSRP_Range_t                    s_measure;
-//  struct MeasConfig__speedStatePars *speedStatePars;
-//  struct PhysicalConfigDedicated  *physicalConfigDedicated[NB_CNX_UE];
-//  struct SPS_Config               *sps_Config[NB_CNX_UE];
-//  MAC_MainConfig_t                *mac_MainConfig[NB_CNX_UE];
-//  MeasGapConfig_t                 *measGapConfig[NB_CNX_UE];
-//  double                          filter_coeff_rsrp; // [7] ???
-//  double                          filter_coeff_rsrq; // [7] ???
-//  float                           rsrp_db[7];
-//  float                           rsrq_db[7];
-//  float                           rsrp_db_filtered[7];
-//  float                           rsrq_db_filtered[7];
-//#if ENABLE_RAL
-//  obj_hash_table_t               *ral_meas_thresholds;
-//  ral_transaction_id_t            scan_transaction_id;
-//#endif
-//#if defined(ENABLE_SECURITY)
-//  /* KeNB as computed from parameters within USIM card */
-//  uint8_t kenb[32];
-//#endif
-//
-//  /* Used integrity/ciphering algorithms */
-//  e_CipheringAlgorithm_r12                          ciphering_algorithm;
-//  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
-//
-//} UE_RRC_INST;
-
-
-
-//NB-IoT version (for now not consider UE-side)--------------
-
-//typedef struct UE_RRC_INST_s {
-//  Rrc_State_t     RrcState; //are the same?
-//  Rrc_Sub_State_t RrcSubState;
-//
-//# if defined(ENABLE_USE_MME)
-//  plmn_t          plmnID;
-//  Byte_t          rat;
-//  as_nas_info_t   initialNasMsg;
-//# endif
-//
-//  OAI_UECapability_t *UECap;
-//  uint8_t *UECapability;
-//  uint8_t UECapability_size;
-//  UE_RRC_INFO Info[NB_SIG_CNX_UE];
-//  SRB_INFO Srb0[NB_SIG_CNX_UE];
-//  SRB_INFO_TABLE_ENTRY Srb1[NB_CNX_UE];
-//  SRB_INFO_TABLE_ENTRY Srb1bis[NB_CNX_UE]; //not exist srb2
-//
-//  //needed for NB-IoT?
-//  HANDOVER_INFO_UE HandoverInfoUe;
-//
-//  uint8_t *SIB1_NB[NB_CNX_UE];
-//  uint8_t sizeof_SIB1_NB[N_NBB_CNX_UE];
-//  uint8_t *SI_NB[NB_CNX_UE];
-//  uint8_t sizeof_SI_NB[NB_CNX_UE];
-//  uint8_t SIB1_NB_Status[NB_CNX_UE];
-//  uint8_t SI_NB_Status[NB_CNX_UE];
-//
-//  //NB-IoT SIBs
-//  SystemInformationBlockType1_NB_t *sib1_NB[NB_CNX_UE];
-//  SystemInformation_NB_t *si_NB[NB_CNX_UE]; //!< Temporary storage for an SI-NB message. Decoding happens in decode_SI()-->UE side (to be changed).
-//
-//  SystemInformationBlockType2_NB_r13_t *sib2_NB[NB_CNX_UE];
-//  SystemInformationBlockType3_NB_r13_t *sib3_NB[NB_CNX_UE];
-//  SystemInformationBlockType4_NB_r13_t *sib4_NB[NB_CNX_UE];
-//  SystemInformationBlockType5_NB_r13_t *sib5_NB[NB_CNX_UE];
-//  SystemInformationBlockType14_NB_r13_t *sib14_NB[NB_CNX_UE];
-//  SystemInformationBlockType16_NB_r13_t *sib16_NB[NB_CNX_UE];
-//
-//  future implementation TS 36.331 V14.2.1--(preliminary)
-//  SystemInformationBlockType15_NB_r14_t *sib15_NB[NB_CNX_UE];
-//  SystemInformationBlockType20_NB_r14_t *sib20_NB[NB_CNX_UE];
-//  SystemInformationBlockType22_NB_r14_t *sib22_NB[NB_CNX_UE];
-//
-//  uint8_t							SCPTM_flag;
-//  uint8_t							sizeof_SC_MCHH_MESS[];
-//  SC_MCCH_Message_NB_t				scptm;
-//
-//
-//  uint8_t                         num_srb;
-//  struct SRB_ToAddMod_NB_r13_t             *SRB1_config_NB[NB_CNX_UE];
-//  struct SRB_ToAddMod_NB_r13_t             *SRB1bis_config_NB[NB_CNX_UE];
-//  struct DRB_ToAddMod_NB_r13_t             *DRB_config_NB[NB_CNX_UE][8];
-//  rb_id_t                         *defaultDRB; // remember the ID of the default DRB
-//
-//  //no measurement Reports in NB-IoT
-//
-//  struct PhysicalConfigDedicated_NB_r13  *physicalConfigDedicated_NB[NB_CNX_UE];
-//  MAC_MainConfig_NB_r13_t                *mac_MainConfig_NB[NB_CNX_UE];
-//
-//  //no RAL
-//
-//#if defined(ENABLE_SECURITY)
-//  /* KeNB as computed from parameters within USIM card */
-//  uint8_t kenb[32];
-//#endif
-//  /* KeNB as computed from parameters within USIM card */
-//  uint8_t kenb[32];
-//#endif
-//
-//  // Used integrity/ciphering algorithms
-//  e_CipheringAlgorithm_r12                          ciphering_algorithm;
-//  e_SecurityAlgorithmConfig__integrityProtAlgorithm integrity_algorithm;
-//
-//} UE_RRC_INST;
-
-#include "proto_nb_iot.h" //should be put here otherwise compilation error
-
-#endif
-/** @} */
diff --git a/openair2/RRC/LITE/extern.h b/openair2/RRC/LITE/extern.h
index b1046075b37eb899ffdda01b56490f423d5e00fc..c7e490f89e73fea29d31da9a8dc11185ea478fa8 100644
--- a/openair2/RRC/LITE/extern.h
+++ b/openair2/RRC/LITE/extern.h
@@ -37,8 +37,8 @@
 #include "LAYER2/RLC/rlc.h"
 
 ///NB_IoT
-#include "defs_nb_iot.h"
-extern eNB_RRC_INST_NB *eNB_rrc_inst_NB;
+#include "defs_NB_IoT.h"
+extern eNB_RRC_INST_NB_IoT *eNB_rrc_inst_NB_IoT;
 
 extern UE_RRC_INST *UE_rrc_inst;
 extern eNB_RRC_INST *eNB_rrc_inst;
diff --git a/openair2/RRC/LITE/extern_nb_iot.h b/openair2/RRC/LITE/extern_NB_IoT.h
similarity index 60%
rename from openair2/RRC/LITE/extern_nb_iot.h
rename to openair2/RRC/LITE/extern_NB_IoT.h
index e2dccb746f50529fc37f220adf8994c1bca8e5a5..ba5970bf2e9b2551d5db8ae2f324080169de2861 100644
--- a/openair2/RRC/LITE/extern_nb_iot.h
+++ b/openair2/RRC/LITE/extern_NB_IoT.h
@@ -30,22 +30,37 @@
 
 #ifndef __OPENAIR_RRC_EXTERN_NB_IOT_H__
 #define __OPENAIR_RRC_EXTERN_NB_IOT_H__
-#include "defs_nb_iot.h"
-#include "COMMON/mac_rrc_primitives.h"
-#include "LAYER2/MAC/defs.h"
-#include "LAYER2/MAC/extern.h"
+#include "RRC/LITE/defs_NB_IoT.h"
+//#include "COMMON/mac_rrc_primitives.h"
+#include "PHY_INTERFACE/IF_Module_NB_IoT.h"
+//#include "LAYER2/MAC/defs.h"
+//#include "LAYER2/MAC/extern.h"
 #include "LAYER2/RLC/rlc.h"
 #include "LogicalChannelConfig-NB-r13.h"
+#include "LAYER2/MAC/defs_NB_IoT.h"
+
+extern IF_Module_t *if_inst;
+extern eNB_MAC_INST_NB_IoT *mac_inst;
+
 
 //MP: NOTE:XXX some of the parameters defined in vars_nb_iot are called by the extern.h file so not replicated here
 
+extern UE_RRC_INST_NB_IoT 					*UE_rrc_inst_NB_IoT;
+
+extern eNB_RRC_INST_NB_IoT 					*eNB_rrc_inst_NB_IoT;
+extern PHY_Config_t 						*config_INFO;
 
-extern eNB_RRC_INST_NB *eNB_rrc_inst_NB;
+extern rlc_info_t 							Rlc_info_am_NB_IoT,Rlc_info_am_config_NB_IoT;
+extern uint8_t 								DRB2LCHAN_NB_IoT[2];
+extern LogicalChannelConfig_NB_r13_t 		SRB1bis_logicalChannelConfig_defaultValue_NB_IoT;
+extern LogicalChannelConfig_NB_r13_t 		SRB1_logicalChannelConfig_defaultValue_NB_IoT;
 
-extern rlc_info_t Rlc_info_um,Rlc_info_am_config,Rlc_info_am;
-extern uint8_t DRB2LCHAN_NB[2];
-extern LogicalChannelConfig_NB_r13_t SRB1bis_NB_logicalChannelConfig_defaultValue;
-extern LogicalChannelConfig_NB_r13_t SRB1_NB_logicalChannelConfig_defaultValue;
+extern uint16_t 							T300_NB_IoT[8];
+extern uint16_t 							T301_NB_IoT[8];
+extern uint16_t 							T310_NB_IoT[8];
+extern uint16_t 							T311_NB_IoT[8];
+extern uint16_t 							N310_NB_IoT[8];
+extern uint16_t 							N311_NB_IoT[8];
 
 #endif
 
diff --git a/openair2/RRC/LITE/proto_nb_iot.h b/openair2/RRC/LITE/proto_NB_IoT.h
similarity index 65%
rename from openair2/RRC/LITE/proto_nb_iot.h
rename to openair2/RRC/LITE/proto_NB_IoT.h
index ed46e7ed692927305446931be98dbf64e275f609..1582b03afeab4cec002311d52df0ae58163b2ca1 100644
--- a/openair2/RRC/LITE/proto_nb_iot.h
+++ b/openair2/RRC/LITE/proto_NB_IoT.h
@@ -18,7 +18,7 @@
  *      contact@openairinterface.org
  */
 
-/*! \file proto_nb_iot.h
+/*! \file proto_NB_IoT.h
  * \brief RRC functions prototypes for eNB and UE for NB-IoT
  * \author Navid Nikaein, Raymond Knopp and Michele Paffetti
  * \date 2010 - 2014
@@ -30,24 +30,24 @@
  *  @{
  */
 
-#include "RRC/LITE/defs_nb_iot.h"
+#include "RRC/LITE/defs_NB_IoT.h"
 #include "pdcp.h"
 #include "rlc.h"
-#include "extern_nb_iot.h"
-
+#include "extern_NB_IoT.h"
+#include "LAYER2/MAC/defs_NB_IoT.h"
 /*NOTE: no static function should be declared in this header file (e.g. init_SI_NB)*/
 
 /*------------------------common_nb_iot.c----------------------------------------*/
 
 /** \brief configure  BCCH & CCCH Logical Channels and associated rrc_buffers, configure associated SRBs
  */
-void openair_rrc_on_NB(const protocol_ctxt_t* const ctxt_pP);
+void openair_rrc_on_NB_IoT(const protocol_ctxt_t* const ctxt_pP);
 
-void rrc_config_buffer_NB(SRB_INFO_NB *srb_info, uint8_t Lchan_type, uint8_t Role);
+void rrc_config_buffer_NB_IoT(SRB_INFO_NB_IoT *srb_info, uint8_t Lchan_type, uint8_t Role);
 
-int L3_xface_init_NB(void);
+int L3_xface_init_NB_IoT(void);
 
-void openair_rrc_top_init_NB( char *uecap_xer);
+void openair_rrc_top_init_eNB_NB_IoT(void);
 
 //void rrc_top_cleanup(void); -->seems not to be used
 
@@ -58,87 +58,19 @@ void openair_rrc_top_init_NB( char *uecap_xer);
 @param enb_index
 @param CC_id
 */
-RRC_status_t rrc_rx_tx_NB(protocol_ctxt_t* const ctxt_pP, const uint8_t  enb_index, const int CC_id);
+RRC_status_t rrc_rx_tx_NB_IoT(protocol_ctxt_t* const ctxt_pP, const uint8_t  enb_index, const int CC_id);
 
 //long binary_search_int(int elements[], long numElem, int value);--> seems not to be used
 //long binary_search_float(float elements[], long numElem, float value);--> used only at UE side
 
-/*------------------------L2_interface_nb_iot.c (temporary location for most of the interfaces)--------*/
-
-//defined in MAC/config.c
-//FIXME: this function has no implication in terms of logical channel configuration for MAC
-int NB_rrc_mac_config_req_eNB(
-			   module_id_t       				Mod_idP,
-			   int                              CC_idP,
-			   int								rntiP, //FIXME: Raymond bug?
-			   int                              physCellId,
-			   int                              p_eNB,
-			   int                              Ncp,
-			   long                             eutra_band,//FIXME: frequencyBandIndicator in sib1 (is a long not an int!!)
-			   struct NS_PmaxList_NB_r13        *frequencyBandInfo, //optional SIB1
-			   struct MultiBandInfoList_NB_r13  *multiBandInfoList, //optional SIB1
-			   struct DL_Bitmap_NB_r13          *dl_bitmap, //optional SIB1
-			   long*                            eutraControlRegionSize, //optional sib1
-			   long*							nrs_CRS_PowerOffset, //optional
-			   uint8_t                          *SIwindowsize, //maybe no more needed because TDD only
-			   uint16_t                         *SIperiod, //maybe no more needed because TDD only
-			   uint32_t                         dl_CarrierFreq,
-			   uint32_t                         ul_CarrierFreq,
-			   BCCH_BCH_Message_NB_t            *mib_NB,
-			   RadioResourceConfigCommonSIB_NB_r13_t   *radioResourceConfigCommon,
-			   struct PhysicalConfigDedicated_NB_r13  *physicalConfigDedicated,
-			   MAC_MainConfig_NB_r13_t                *mac_MainConfig,
-			   long                             logicalChannelIdentity,//FIXME: decide how to use it
-			   LogicalChannelConfig_NB_r13_t          *logicalChannelConfig //FIXME: decide how to use it
-			   );
-
-//----------------------------------------
-
-//New
-/**\brief function for evaluate if the SIB1-NB transmission occur
- * called by the NB_mac_rrc_data_req
- */
-boolean_t is_SIB1_NB(
-		const frame_t   frameP,
-		long			schedulingInfoSIB1,//from the mib
-		int				physCellId
-		);
-//--------------------------------------
-
-//New
-/**\brief function for evaluate if the SIB23-NB transmission occurr
- * called by the NB_mac_rrc_data_req
- *
- */
-boolean_t is_SIB23_NB(
-		const frame_t     	frameP,
-		const frame_t		h_frameP, // the HSFN (increased by 1 every SFN wrap around) (10 bits)
-		long				si_period, //SI-periodicity (rf)
-		long				si_windowLength_ms, //Si-windowlength (ms) XXX received as an enumerative (see the IE of SIB1-NB)
-		long*				si_RadioFrameOffset, //Optional
-		long				si_RepetitionPattern // is given as an Enumerated
-		);
-//-----------------------------------
 
 
-//defined in L2_interface
-int8_t NB_mac_rrc_data_req_eNB(
-  const module_id_t Mod_idP,
-  const int         CC_id,
-  const frame_t     frameP,
-  const frame_t		h_frameP,
-  const rb_id_t     Srb_id,
-  uint8_t*    const buffer_pP,
-  long				schedulingInfoSIB1,//from the mib
-  int				physCellId, //from the MAC instance-> common_channel
-  mib_flag_t		mib_flag
-);
 //---------------------------------------
 
 
 //defined in L2_interface
 //called by rx_sdu only in case of CCCH message (e.g RRCConnectionRequest-NB)
-int8_t NB_mac_rrc_data_ind_eNB(
+int8_t mac_rrc_data_ind_eNB_NB_IoT(
   const module_id_t     module_idP,
   const int             CC_id,
   const frame_t         frameP,
@@ -151,7 +83,12 @@ int8_t NB_mac_rrc_data_ind_eNB(
 //-------------------------------------------
 
 //defined in L2_interface
-void NB_mac_eNB_rrc_ul_failure(
+void dump_ue_list_NB_IoT(UE_list_NB_IoT_t *listP, int ul_flag);
+//-------------------------------------------
+
+
+//defined in L2_interface
+void mac_eNB_rrc_ul_failure_NB_IoT(
 		const module_id_t mod_idP,
 	    const int CC_idP,
 	    const frame_t frameP,
@@ -160,12 +97,12 @@ void NB_mac_eNB_rrc_ul_failure(
 //------------------------------------------
 
 //defined in eNB_scheduler_primitives.c
-int NB_rrc_mac_remove_ue(
+int rrc_mac_remove_ue_NB_IoT(
 		module_id_t mod_idP,
 		rnti_t rntiP);
 //------------------------------------------
 //defined in L2_interface
-void NB_mac_eNB_rrc_ul_in_sync(
+void mac_eNB_rrc_ul_in_sync_NB_IoT(
 				const module_id_t mod_idP,
 			    const int CC_idP,
 			    const frame_t frameP,
@@ -173,15 +110,29 @@ void NB_mac_eNB_rrc_ul_in_sync(
 			    const rnti_t rntiP);
 //------------------------------------------
 //defined in L2_interface
-int NB_mac_eNB_get_rrc_status(
+int mac_eNB_get_rrc_status_NB_IoT(
   const module_id_t Mod_idP,
   const rnti_t      rntiP
 );
 //---------------------------
 
-//FIXME for the moment we not configure PDCP for SRB1bis (but used as it is SRB1)
+//----------------------------------------
+int pdcp_apply_security_NB_IoT(
+  const protocol_ctxt_t* const ctxt_pP,
+  pdcp_t        *const pdcp_pP,
+  const srb_flag_t     srb_flagP,
+  const rb_id_t        rb_id, //rb_idP % maxDRB_NB_r13
+  const uint8_t        pdcp_header_len,
+  const uint16_t       current_sn,
+  uint8_t       * const pdcp_pdu_buffer,
+  const uint16_t      sdu_buffer_size
+);
+//-------------------------------------------
+
+
+//XXX for the moment we not configure PDCP for SRB1bis (but used as it is SRB1)
 //defined in pdcp.c
-boolean_t NB_rrc_pdcp_config_asn1_req (
+boolean_t rrc_pdcp_config_asn1_req_NB_IoT (
   const protocol_ctxt_t* const  ctxt_pP,
   SRB_ToAddModList_NB_r13_t  *const srb2add_list_pP,
   DRB_ToAddModList_NB_r13_t  *const drb2add_list_pP,
@@ -197,8 +148,7 @@ boolean_t NB_rrc_pdcp_config_asn1_req (
 
 //defined in pdcp.c --> should be called only by a SRB1 (is internal to PDCP so is not an interface)
 //-----------------------------------------------------------------------------
-boolean_t
-NB_pdcp_config_req_asn1 (
+boolean_t pdcp_config_req_asn1_NB_IoT (
   const protocol_ctxt_t* const  ctxt_pP,
   pdcp_t         * const        pdcp_pP,
   const srb_flag_t              srb_flagP,
@@ -218,7 +168,7 @@ NB_pdcp_config_req_asn1 (
 //defined in L2_interface/pdcp.c
 //FIXME SRB1bis should bypass the pdcp
 //Distinction between different SRBs will be done by means of rd_id
-uint8_t NB_rrc_data_req(
+uint8_t rrc_data_req_NB_IoT(
   const protocol_ctxt_t*   const ctxt_pP,
   const rb_id_t                  rb_idP,
   const mui_t                    muiP,
@@ -229,7 +179,7 @@ uint8_t NB_rrc_data_req(
 );
 //-------------------------------------------------------------
 //we distinguish the SRBs based on the logical channel id and the transmission mode
-boolean_t NB_pdcp_data_req(
+boolean_t pdcp_data_req_NB_IoT(
   protocol_ctxt_t*  ctxt_pP,
   const srb_flag_t     srb_flagP, //SRB_FLAG_YES if called by RRC
   const rb_id_t        rb_idP,
@@ -243,7 +193,7 @@ boolean_t NB_pdcp_data_req(
 //----------------------------------------------------------------
 
 //defined in L2_interface
-void NB_rrc_data_ind(
+void rrc_data_ind_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const rb_id_t                Srb_id,
   const sdu_size_t             sdu_sizeP,
@@ -253,7 +203,7 @@ void NB_rrc_data_ind(
 //------------------------------------------------------------------------------
 
 //defined in rlc_rrc.c
-rlc_op_status_t NB_rrc_rlc_config_asn1_req (
+rlc_op_status_t rrc_rlc_config_asn1_req_NB_IoT (
 	const protocol_ctxt_t   * const ctxt_pP,
     const SRB_ToAddModList_NB_r13_t   * const srb2add_listP,
     const DRB_ToAddModList_NB_r13_t   * const drb2add_listP,
@@ -263,7 +213,7 @@ rlc_op_status_t NB_rrc_rlc_config_asn1_req (
 //-------------------------------------------------------------------------
 
 // defined in rlc_am.c
-void NB_config_req_rlc_am_asn1 (
+void config_req_rlc_am_asn1_NB_IoT (
   const protocol_ctxt_t* const         ctxt_pP,
   const srb_flag_t                     srb_flagP,
   const struct RLC_Config_NB_r13__am  * const config_am_pP, //extracted from the srb_toAddMod
@@ -273,19 +223,18 @@ void NB_config_req_rlc_am_asn1 (
 
 //defined in rlc_am_init.c
 //------------------------------------------------------------
-void
-NB_rlc_am_configure(
+void rlc_am_configure_NB_IoT(
   const protocol_ctxt_t* const  ctxt_pP,
   rlc_am_entity_t *const        rlc_pP,
   const uint16_t                max_retx_thresholdP,
   const uint16_t                t_poll_retransmitP,
-  const uint16_t* const			enableStatusReportSN_Gap
+  uint32_t                      *enableStatusReportSN_Gap
   );
 //--------------------------------------------------------------
 
 //defined in rlc_rrc.c
 //-------------------------------------------------------------
-rlc_union_t* NB_rrc_rlc_add_rlc   (
+rlc_union_t* rrc_rlc_add_rlc_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t        srb_flagP,
   const rb_id_t           rb_idP,
@@ -295,7 +244,7 @@ rlc_union_t* NB_rrc_rlc_add_rlc   (
 
 //defined in rlc_rrc.c
 //--------------------------------------------------------------
-rlc_op_status_t NB_rrc_rlc_remove_rlc   (
+rlc_op_status_t rrc_rlc_remove_rlc_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t  srb_flagP,
   const rb_id_t     rb_idP);
@@ -303,22 +252,21 @@ rlc_op_status_t NB_rrc_rlc_remove_rlc   (
 
 //defined in rlc_rrc.c //used only for process_RRCConnectionReconfigurationComplete --> CONFIG_ACTION_REMOVE
 //used also for rrc_t310_expiration --> I don't know if it is used (probably not)
-rlc_op_status_t NB_rrc_rlc_config_req   (
+rlc_op_status_t rrc_rlc_config_req_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t      srb_flagP,
   const config_action_t actionP,
   const rb_id_t         rb_idP,
-  const rlc_info_t      rlc_infoP);
+   rlc_info_t      rlc_infoP);
 //-----------------------------------------------------
 
 
 //defined in rlc_am.c
 //------------------------------------------------------
-void
-NB_config_req_rlc_am (
-  const protocol_ctxt_t* const ctxt_pP,
+void config_req_rlc_am_NB_IoT (
+  const protocol_ctxt_t        * const ctxt_pP,
   const srb_flag_t             srb_flagP,
-  rlc_am_info_NB_t  * const       config_am_pP, //XXX: MP: rlc_am_init.c --> this structure has been modified for NB-IoT
+  rlc_am_info_NB_IoT_t         *const config_am_pP, //XXX: MP: rlc_am_init.c --> this structure has been modified for NB-IoT
   const rb_id_t                rb_idP,
   const logical_chan_id_t      chan_idP
 );
@@ -326,7 +274,7 @@ NB_config_req_rlc_am (
 
 //defined in rlc_tm_init.c (nothing to be changed)
 //-----------------------------------------------------------------------------
-void NB_config_req_rlc_tm (
+void config_req_rlc_tm_NB_IoT (
   const protocol_ctxt_t* const  ctxt_pP,
   const srb_flag_t  srb_flagP,
   const rlc_tm_info_t * const config_tmP,
@@ -335,13 +283,13 @@ void NB_config_req_rlc_tm (
 );
 //------------------------------------------------------
 //defined in rlc_rrc.c
-rlc_op_status_t NB_rrc_rlc_remove_ue (
+rlc_op_status_t rrc_rlc_remove_ue_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP);
 //----------------------------------------------------
 
 //defined in rlc.c
 //--------------------------------------------
-void NB_rlc_data_ind     (
+void rlc_data_ind_NB_IoT  (
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t  srb_flagP,
   const srb1bis_flag_t srb1bis_flag,
@@ -352,20 +300,26 @@ void NB_rlc_data_ind     (
 
 //defined in rlc.c
 //-----------------------------------------------------------------------------
-rlc_op_status_t NB_rlc_data_req     (const protocol_ctxt_t* const ctxt_pP,
-                                  const srb_flag_t   srb_flagP,
-                                  const rb_id_t      rb_idP,
-                                  const mui_t        muiP,
-                                  confirm_t    confirmP,
-                                  sdu_size_t   sdu_sizeP,
-                                  mem_block_t *sdu_pP);
+rlc_op_status_t rlc_data_req_NB_IoT  (const protocol_ctxt_t* const ctxt_pP,
+                                      const srb_flag_t   srb_flagP,
+                                      const rb_id_t      rb_idP,
+                                      const mui_t        muiP,
+                                      confirm_t    confirmP,
+                                      sdu_size_t   sdu_sizeP,
+                                      mem_block_t *sdu_pP);
 //-----------------------------------------------------------------------------
 
+
+//defined in rlc_rrc.c --> NO MORE USED PROBABLY
+//------------------------------------------------------------------------------
+void rrc_rlc_register_rrc_NB_IoT (rrc_data_ind_cb_NB_IoT_t rrc_data_indP_NB_IoT, rrc_data_conf_cb_t rrc_data_confP);
+
+
+
 //defined in pdcp.c
 //FIXME: should go transparent through the PDCP
 //--------------------------------------------
-boolean_t
-NB_pdcp_data_ind(
+boolean_t pdcp_data_ind_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const srb_flag_t   srb_flagP,
   const srb1bis_flag_t srb1bis_flag,
@@ -376,7 +330,7 @@ NB_pdcp_data_ind(
 //---------------------------------------------
 
 //defined in rlc_mac.c
-void NB_mac_rlc_data_ind     (
+void mac_rlc_data_ind_NB_IoT (
   const module_id_t         module_idP,
   const rnti_t              rntiP,
   const module_id_t         eNB_index,
@@ -391,8 +345,7 @@ void NB_mac_rlc_data_ind     (
 //-------------------------------------------
 
 //defined in rlc_am.c
-void
-NB_rlc_am_mac_data_indication (
+void rlc_am_mac_data_indication_NB_IoT (
   const protocol_ctxt_t* const ctxt_pP,
   void * const                 rlc_pP,
   struct mac_data_ind          data_indP
@@ -401,7 +354,7 @@ NB_rlc_am_mac_data_indication (
 
 //defined in rlc_mac.c
 //called by the schedule_ue_spec for getting SDU to be transmitted from SRB1/SRB1bis and DRBs
-tbs_size_t NB_mac_rlc_data_req_eNB(
+tbs_size_t mac_rlc_data_req_eNB_NB_IoT(
   const module_id_t       module_idP,
   const rnti_t            rntiP,
   const eNB_index_t       eNB_index,
@@ -413,25 +366,20 @@ tbs_size_t NB_mac_rlc_data_req_eNB(
 
 
 
-/*UE procedures*/
-
-/*eNB procedures*/
+/*-----------eNB procedures (rrc_eNB_nb_iot.c)---------------*/
 
 //---Initialization--------------
-void
-openair_eNB_rrc_on_NB(
+void openair_eNB_rrc_on_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP
 );
 
-void
-rrc_config_buffer_NB(
-  SRB_INFO_NB* Srb_info,
+void rrc_config_buffer_NB_IoT(
+  SRB_INFO_NB_IoT* Srb_info,
   uint8_t Lchan_type,
   uint8_t Role
 );
 
-char
-openair_rrc_eNB_configuration_NB(
+char openair_rrc_eNB_configuration_NB_IoT(
   const module_id_t enb_mod_idP,
   RrcConfigurationReq* configuration
 );
@@ -439,15 +387,14 @@ openair_rrc_eNB_configuration_NB(
 //-----------------------------
 /**\brief RRC eNB task. (starting of the RRC state machine)
    \param void *args_p Pointer on arguments to start the task. */
-void *rrc_enb_task_NB(void *args_p);
+void *rrc_enb_task_NB_IoT(void *args_p);
 
 /**\brief Entry routine to decode a UL-CCCH-Message-NB.  Invokes PER decoder and parses message.
    \param ctxt_pP Running context
    \param Srb_info Pointer to SRB0 information structure (buffer, etc.)*/
-int
-rrc_eNB_decode_ccch_NB(
+int rrc_eNB_decode_ccch_NB_IoT(
   protocol_ctxt_t* const ctxt_pP,
-  const SRB_INFO_NB*        const Srb_info,
+  const SRB_INFO_NB_IoT*        const Srb_info,
   const int              CC_id
 );
 
@@ -455,8 +402,7 @@ rrc_eNB_decode_ccch_NB(
    \param ctxt_pP Context
    \param Rx_sdu Pointer Received Message
    \param sdu_size Size of incoming SDU*/
-int
-rrc_eNB_decode_dcch_NB(
+int rrc_eNB_decode_dcch_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const rb_id_t                Srb_id,
   const uint8_t*    const      Rx_sdu,
@@ -467,78 +413,74 @@ rrc_eNB_decode_dcch_NB(
    \param ctxt_pP       Running context
    \param ue_context_pP UE context
    \param CC_id         Component Carrier ID*/
-void
-rrc_eNB_generate_RRCConnectionReestablishmentReject_NB(
+void rrc_eNB_generate_RRCConnectionReestablishmentReject_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP,
   const int                    CC_id
 );
 
-void
-rrc_eNB_generate_RRCConnectionReject_NB(
+void rrc_eNB_generate_RRCConnectionReject_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP,
   const int                    CC_id
 );
 
-void
-rrc_eNB_generate_RRCConnectionSetup_NB(
+void rrc_eNB_generate_RRCConnectionSetup_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP,
   const int                    CC_id
 );
 
-void
-rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
+void rrc_eNB_process_RRCConnectionReconfigurationComplete_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*        ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*        ue_context_pP,
   const uint8_t xid //transaction identifier
 );
 
 
 void //was under ITTI
-rrc_eNB_reconfigure_DRBs_NB(const protocol_ctxt_t* const ctxt_pP,
-			       rrc_eNB_ue_context_NB_t*  ue_context_pP);
+rrc_eNB_reconfigure_DRBs_NB_IoT(const protocol_ctxt_t* const ctxt_pP,
+			       rrc_eNB_ue_context_NB_IoT_t*  ue_context_pP);
 
 void //was under ITTI
-rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
+rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB_IoT(
 		const protocol_ctxt_t* const ctxt_pP,
-	    rrc_eNB_ue_context_NB_t*          const ue_context_pP
+	    rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
         //no ho state
 	     );
 
-void
-rrc_eNB_process_RRCConnectionSetupComplete_NB(
+void rrc_eNB_process_RRCConnectionSetupComplete_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*         ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*         ue_context_pP,
   RRCConnectionSetupComplete_NB_r13_IEs_t * rrcConnectionSetupComplete_NB
 );
 
-void
-rrc_eNB_generate_SecurityModeCommand_NB(
+void rrc_eNB_generate_SecurityModeCommand_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
 );
 
-void
-rrc_eNB_generate_UECapabilityEnquiry_NB(
+void rrc_eNB_generate_UECapabilityEnquiry_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
 );
 
-void
-rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* const ctxt_pP,
-						     rrc_eNB_ue_context_NB_t*          const ue_context_pP
-						//no HO flag
-						     );
+void rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB_IoT(const protocol_ctxt_t* const ctxt_pP,
+						                                                     rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
+						                                                     //no HO flag
+						                                                    );
 
 
 /// Utilities------------------------------------------------
 
-void
-rrc_eNB_free_mem_UE_context_NB(
+void rrc_eNB_free_UE_NB_IoT(
+		const module_id_t enb_mod_idP,
+		const struct rrc_eNB_ue_context_NB_IoT_s*        const ue_context_pP
+		);
+
+void rrc_eNB_free_mem_UE_context_NB_IoT(
   const protocol_ctxt_t*               const ctxt_pP,
-  struct rrc_eNB_ue_context_NB_s*         const ue_context_pP
+  struct rrc_eNB_ue_context_NB_IoT_s*         const ue_context_pP
 );
 
 
@@ -546,5 +488,22 @@ rrc_eNB_free_mem_UE_context_NB(
 /**\brief Function to get the next transaction identifier.
    \param module_idP Instance ID for CH/eNB
    \return a transaction identifier*/
-uint8_t rrc_eNB_get_next_transaction_identifier_NB(module_id_t module_idP);
+uint8_t rrc_eNB_get_next_transaction_identifier_NB_IoT(module_id_t module_idP);
+
+
+int rrc_init_global_param_NB_IoT(void);
+
+//L2_interface.c
+int8_t mac_rrc_data_req_eNB_NB_IoT(
+  const module_id_t Mod_idP,
+  const int         CC_id,
+  const frame_t     frameP,
+  const frame_t   h_frameP,
+  const sub_frame_t   subframeP, //need for the case in which both SIB1-NB_IoT and SIB23-NB_IoT will be scheduled in the same frame
+  const rb_id_t     Srb_id,
+  uint8_t* const buffer_pP,
+  uint8_t   flag
+);
+
+
 
diff --git a/openair2/RRC/LITE/rrc_common.c b/openair2/RRC/LITE/rrc_common.c
index 3f7fa3067c946d5dbba02bcaced61cf227e7c4e3..49500811facda805526ee997d01601510e86ce3b 100644
--- a/openair2/RRC/LITE/rrc_common.c
+++ b/openair2/RRC/LITE/rrc_common.c
@@ -96,73 +96,20 @@ rrc_init_global_param(
 //-----------------------------------------------------------------------------
 {
 
-  //#ifdef USER_MODE
-  //  Rrc_xface = (RRC_XFACE*)malloc16(sizeof(RRC_XFACE));
-  //#endif //USRE_MODE
 
-  //  Rrc_xface->openair_rrc_top_init = openair_rrc_top_init;
-  //  Rrc_xface->openair_rrc_eNB_init = openair_rrc_eNB_init;
-  //  Rrc_xface->openair_rrc_UE_init  = openair_rrc_ue_init;
-  //  Rrc_xface->mac_rrc_data_ind     = mac_rrc_data_ind;
-  //Rrc_xface->mac_rrc_data_req     = mac_rrc_data_req;
-  // Rrc_xface->rrc_data_indP        = (void *)rlcrrc_data_ind;
-  //  Rrc_xface->rrc_rx_tx            = rrc_rx_tx;
-  //  Rrc_xface->mac_rrc_meas_ind     = mac_rrc_meas_ind;
-  //  Rrc_xface->get_rrc_status       = get_rrc_status;
-
-  //Rrc_xface->rrc_get_status = ...
-
-  //  Mac_rlc_xface->mac_out_of_sync_ind=mac_out_of_sync_ind;
-
-#ifndef NO_RRM
-  //  Rrc_xface->fn_rrc=fn_rrc;
-#endif
-  //  LOG_D(RRC, "[RRC]INIT_GLOBAL_PARAM: Mac_rlc_xface %p, rrc_rlc_register %p,rlcrrc_data_ind%p\n",Mac_rlc_xface,Mac_rlc_xface->rrc_rlc_register_rrc,rlcrrc_data_ind);
-  /*
-   if((Mac_rlc_xface==NULL) || (Mac_rlc_xface->rrc_rlc_register_rrc==NULL) ||
-   (rlcrrc_data_ind==NULL)) {
-   LOG_E(RRC,"Data structured is not initialized \n");
-   return -1;
-   }
-   */
   rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc
 
-  DCCH_LCHAN_DESC.transport_block_size = 4;
-  DCCH_LCHAN_DESC.max_transport_blocks = 16;
-  DCCH_LCHAN_DESC.Delay_class = 1;
-  DTCH_DL_LCHAN_DESC.transport_block_size = 52;
-  DTCH_DL_LCHAN_DESC.max_transport_blocks = 20;
-  DTCH_DL_LCHAN_DESC.Delay_class = 1;
-  DTCH_UL_LCHAN_DESC.transport_block_size = 52;
-  DTCH_UL_LCHAN_DESC.max_transport_blocks = 20;
-  DTCH_UL_LCHAN_DESC.Delay_class = 1;
-
-  Rlc_info_um.rlc_mode = RLC_MODE_UM;
-  Rlc_info_um.rlc.rlc_um_info.timer_reordering = 5;
-  Rlc_info_um.rlc.rlc_um_info.sn_field_length = 10;
-  Rlc_info_um.rlc.rlc_um_info.is_mXch = 0;
-  //Rlc_info_um.rlc.rlc_um_info.sdu_discard_mode=16;
-
-  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
-  Rlc_info_am_config.rlc.rlc_am_info.max_retx_threshold = 50;
-  Rlc_info_am_config.rlc.rlc_am_info.poll_pdu = 8;
-  Rlc_info_am_config.rlc.rlc_am_info.poll_byte = 1000;
-  Rlc_info_am_config.rlc.rlc_am_info.t_poll_retransmit = 15;
-  Rlc_info_am_config.rlc.rlc_am_info.t_reordering = 50;
-  Rlc_info_am_config.rlc.rlc_am_info.t_status_prohibit = 10;
-#ifndef NO_RRM
+  //no more LCHAN_DESCH used
+  //no more static configuration of RLC params
+  //no more L3_xface_init called
 
-  if (L3_xface_init ()) {
-    return (-1);
-  }
-
-#endif
 
   return 0;
 }
 
 #ifndef NO_RRM
 //-----------------------------------------------------------------------------
+//NO more USED
 int
 L3_xface_init(
   void
@@ -191,6 +138,7 @@ L3_xface_init(
 
 #else
 
+  //MP: rtf_create(fifo ID, size in bytes) --> for creating FIFO
   ret=rtf_create(RRC2RRM_FIFO,32768);
 
   if (ret < 0) {
@@ -324,18 +272,19 @@ openair_rrc_top_init(
     eNB_rrc_inst = NULL;
   }
 
-#ifndef NO_RRM
-#ifndef USER_MODE
-
-  Header_buf=(char*)malloc16(sizeof(msg_head_t));
-  Data=(char*)malloc16(2400);
-  Header_read_idx=0;
-  Data_read_idx=0;
-  Header_size=sizeof(msg_head_t);
-
-#endif //NO_RRM
-  Data_to_read = 0;
-#endif //USER_MODE
+//#ifndef NO_RRM
+//#ifndef USER_MODE
+//
+//  //no more used since are exploited by RRC_xface
+//  Header_buf=(char*)malloc16(sizeof(msg_head_t));
+//  Data=(char*)malloc16(2400);
+//  Header_read_idx=0;
+//  Data_read_idx=0;
+//  Header_size=sizeof(msg_head_t);
+//
+//#endif //NO_RRM
+//  Data_to_read = 0;
+//#endif //USER_MODE
 }
 
 //-----------------------------------------------------------------------------
diff --git a/openair2/RRC/LITE/rrc_common_NB_IoT.c b/openair2/RRC/LITE/rrc_common_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..8fd5522f4232c09c662e9acaa585d3da768b523a
--- /dev/null
+++ b/openair2/RRC/LITE/rrc_common_NB_IoT.c
@@ -0,0 +1,430 @@
+/*
+ * 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.0  (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 rrc_common.c
+ * \brief rrc common procedures for eNB and UE
+ * \author Navid Nikaein and Raymond Knopp
+ * \date 2011 - 2014
+ * \version 1.0
+ * \company Eurecom
+ * \email:  navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
+ */
+
+//#include "defs_NB_IoT.h"
+//#include "extern.h"
+//#include "RRC/LITE/extern_NB_IoT.h"
+#include "common/utils/collection/tree.h"
+#include "LAYER2/MAC/extern_NB_IoT.h"
+//#include "COMMON/openair_defs.h"
+//#include "COMMON/platform_types.h"
+//#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
+#include "LAYER2/RLC/rlc.h"
+//#include "COMMON/mac_rrc_primitives.h"
+#include "UTIL/LOG/log.h"
+#include "asn1_msg.h"
+#include "pdcp.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+//#include "rrc_eNB_UE_context.h"
+//#include "proto_NB_IoT.h"
+#include "RRC/LITE/defs_NB_IoT.h"
+#include "RRC/LITE/vars_NB_IoT.h"
+
+#ifdef LOCALIZATION
+#include <sys/time.h>
+#endif
+
+#define DEBUG_RRC 1
+extern eNB_MAC_INST *eNB_mac_inst;
+extern UE_MAC_INST *UE_mac_inst;
+
+extern mui_t rrc_eNB_mui;
+
+/*missed functions*/
+//rrc_top_cleanup
+//binary_search_init
+//binary_search_float
+
+
+//--------------
+//MP: Most probably is not needed (old code)
+//-----------------------------------------------------------------------------
+void rrc_t310_expiration_NB_IoT(
+  const protocol_ctxt_t* const ctxt_pP,
+  const uint8_t                 eNB_index
+)
+//-----------------------------------------------------------------------------
+{
+
+  if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[eNB_index].State != RRC_CONNECTED_NB_IoT) {
+    LOG_D(RRC, "Timer 310 expired, going to RRC_IDLE_NB_IoT\n");
+    UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[eNB_index].State = RRC_IDLE_NB_IoT;
+    UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[eNB_index].UE_index = 0xffff;
+    UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb0[eNB_index].Rx_buffer.payload_size = 0;
+    UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb0[eNB_index].Tx_buffer.payload_size = 0;
+    UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb1[eNB_index].Srb_info.Rx_buffer.payload_size = 0;
+    UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb1[eNB_index].Srb_info.Tx_buffer.payload_size = 0;
+
+    if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb2[eNB_index].Active == 1) {
+      msg ("[RRC Inst %d] eNB_index %d, Remove RB %d\n ", ctxt_pP->module_id, eNB_index,
+           UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id);
+      rrc_pdcp_config_req (ctxt_pP, // MP
+                           SRB_FLAG_YES,
+                           CONFIG_ACTION_REMOVE,
+                           UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
+                           0);
+
+      rrc_rlc_config_req_NB_IoT(
+    		  	  	  	  	        ctxt_pP,
+							                  SRB_FLAG_YES,
+							                  CONFIG_ACTION_REMOVE,
+							                  UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb2[eNB_index].Srb_info.Srb_id,
+							                  Rlc_info_am_NB_IoT);
+
+
+      UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb2[eNB_index].Active = 0;
+      UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb2[eNB_index].Status = IDLE;
+      UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb2[eNB_index].Next_check_frame = 0;
+    }
+  } else { // Restablishment procedure
+    LOG_D(RRC, "Timer 310 expired, trying RRCRestablishment ...\n");
+  }
+}
+
+
+
+
+//configure  BCCH & CCCH Logical Channels and associated rrc_buffers, configure associated SRBs
+//called by openair_rrc_eNB_configuration_NB_IoT
+//-----------------------------------------------------------------------------
+void openair_eNB_rrc_on_NB_IoT(
+  const protocol_ctxt_t* const ctxt_pP
+)
+//-----------------------------------------------------------------------------
+{
+
+  int            CC_id;
+
+    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC-NB IN....\n",
+          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
+    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
+      rrc_config_buffer_NB_IoT (&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].SI, BCCH, 1);
+      eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].SI.Active = 1;
+      rrc_config_buffer_NB_IoT (&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0, CCCH, 1);
+      eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Active = 1;
+    }
+    //no UE side
+ }
+
+
+
+//-----------------------------------------------------------------------------
+void rrc_config_buffer_NB_IoT(
+  SRB_INFO_NB_IoT* Srb_info,
+  uint8_t Lchan_type,
+  uint8_t Role
+)
+//-----------------------------------------------------------------------------
+{
+
+  Srb_info->Rx_buffer.payload_size = 0;
+  Srb_info->Tx_buffer.payload_size = 0;
+}
+
+
+//-----------------------------------------------------------------------------
+//XXX NEW mplementation by Raymond: still used but no more called by MAC/main.c instead directly called by rrc_eNB_nb_iot.c
+//XXX maybe this function is no more useful
+int rrc_init_global_param_NB_IoT( void )
+//-----------------------------------------------------------------------------
+{
+
+  //may no more used (defined in rlc_rrc.c)
+  rrc_rlc_register_rrc_NB_IoT (rrc_data_ind_NB_IoT, NULL); //register with rlc
+
+  //XXX MP: most probably ALL of this stuff are no more needed (also the one not commented)
+
+  //DCCH_LCHAN_DESC.transport_block_size = 4;....
+
+  //Setting of this values????
+  Rlc_info_am_config_NB_IoT.rlc_mode = RLC_MODE_AM; //only allowed for NB-IoT
+  Rlc_info_am_config_NB_IoT.rlc.rlc_am_info_NB_IoT.max_retx_threshold_NB_IoT = 50;
+  Rlc_info_am_config_NB_IoT.rlc.rlc_am_info_NB_IoT.t_poll_retransmit_NB_IoT = 15;
+  Rlc_info_am_config_NB_IoT.rlc.rlc_am_info_NB_IoT.enableStatusReportSN_Gap_NB_IoT = NULL; //should be disabled
+
+
+#ifndef NO_RRM
+
+if (L3_xface_init_NB_IoT ()) { //XXX to be modified???
+    return (-1);
+  }
+
+#endif
+
+  return 0;
+}
+
+
+#ifndef NO_RRM
+//-----------------------------------------------------------------------------
+int L3_xface_init_NB_IoT( //Exact copy of the LTE implementation
+  void
+)
+//-----------------------------------------------------------------------------
+{
+
+  int ret = 0;
+
+#ifdef USER_MODE
+
+  int sock;
+  LOG_D(RRC, "[L3_XFACE] init de l'interface \n");
+
+  if (open_socket (&S_rrc, RRC_RRM_SOCK_PATH, RRM_RRC_SOCK_PATH, 0) == -1) {
+    return (-1);
+  }
+
+  if (S_rrc.s == -1) {
+    return (-1);
+  }
+
+  socket_setnonblocking (S_rrc.s);
+  msg ("Interface Connected... RRM-RRC\n");
+  return 0;
+
+#else
+
+  ret=rtf_create(RRC2RRM_FIFO,32768);
+
+  if (ret < 0) {
+    msg("[openair][MAC][INIT] Cannot create RRC2RRM fifo %d (ERROR %d)\n",RRC2RRM_FIFO,ret);
+    return(-1);
+  } else {
+    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRC2RRM_FIFO);
+    rtf_reset(RRC2RRM_FIFO);
+  }
+
+  ret=rtf_create(RRM2RRC_FIFO,32768);
+
+  if (ret < 0) {
+    msg("[openair][MAC][INIT] Cannot create RRM2RRC fifo %d (ERROR %d)\n",RRM2RRC_FIFO,ret);
+    return(-1);
+  } else {
+    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRM2RRC_FIFO);
+    rtf_reset(RRM2RRC_FIFO);
+  }
+
+  return(0);
+
+#endif
+}
+#endif
+
+//------------------------------------------------------------------------------
+//specialized function for the eNB initialization (NB-IoT)
+//(OLD was called in MAC/main.c--> mac_top_init)(NEW is called in directly in "openair_rrc_eNB_configuration_NB_IoT")
+void openair_rrc_top_init_eNB_NB_IoT(void)//MP: XXX Raymond put this directly the definition on rrc_eNB.c file
+//-----------------------------------------------------------------------------
+{
+
+  int                 CC_id;
+
+  /* for no gcc warnings */
+  (void)CC_id;
+
+//not consider UE part
+
+    eNB_rrc_inst_NB_IoT = (eNB_RRC_INST_NB_IoT*) malloc16(sizeof(eNB_RRC_INST_NB_IoT));
+    memset (eNB_rrc_inst_NB_IoT, 0, sizeof(eNB_RRC_INST_NB_IoT));
+    LOG_D(RRC, "ALLOCATE %d Bytes for eNB_RRC_INST NB-IoT @ %p\n", (unsigned int)(sizeof(eNB_RRC_INST_NB_IoT)), eNB_rrc_inst_NB_IoT);
+
+//no CBA, no LOcalization, no MBMS flag
+
+    LOG_D(RRC,
+          "ALLOCATE %d Bytes for eNB_RRC_INST_NB @ %p\n", (unsigned int)(sizeof(eNB_RRC_INST_NB_IoT)), eNB_rrc_inst_NB_IoT);
+
+
+}
+
+//-----------------------------------------------------------------------------
+//XXX MP: most probably is not needed
+RRC_status_t rrc_rx_tx_NB_IoT(
+  protocol_ctxt_t* const ctxt_pP,
+  const uint8_t      enb_indexP,
+  const int          CC_id
+)
+//-----------------------------------------------------------------------------
+{
+  //uint8_t        UE_id;
+  int32_t        current_timestamp_ms, ref_timestamp_ms;
+  struct timeval ts;
+  struct rrc_eNB_ue_context_NB_IoT_s   *ue_context_p = NULL;
+  struct rrc_eNB_ue_context_NB_IoT_s   *ue_to_be_removed = NULL;
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);
+
+  if(ctxt_pP->enb_flag == ENB_FLAG_NO) {  //is an UE
+    // check timers
+
+    if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T300_active == 1) {
+      if ((UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T300_cnt % 10) == 0)
+        LOG_D(RRC,
+              "[UE %d][RAPROC] Frame %d T300 Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T300_cnt);
+
+      if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T300_cnt
+          == T300_NB_IoT[UE_rrc_inst_NB_IoT[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t300]) {
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T300_active = 0;
+        // ALLOW CCCH to be used
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb0[enb_indexP].Tx_buffer.payload_size = 0;
+        rrc_ue_generate_RRCConnectionRequest (ctxt_pP, enb_indexP);
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
+        return (RRC_ConnSetup_failed);
+      }
+
+      UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T300_cnt++;
+    }
+
+    if ((UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].SIStatus&2)>0) {
+      if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].N310_cnt
+          == N310_NB_IoT[UE_rrc_inst_NB_IoT[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n310]) {
+	LOG_I(RRC,"Activating T310_NB_IoT\n");
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_active = 1;
+      }
+    } else { // in case we have not received SIB2 yet
+      /*      if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].N310_cnt == 100) {
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].N310_cnt = 0;
+
+	}*/
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
+      return RRC_OK;
+    }
+
+    if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_active == 1) {
+      if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].N311_cnt
+          == N311_NB_IoT[UE_rrc_inst_NB_IoT[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n311]) {
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].N311_cnt = 0;
+      }
+
+      if ((UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_cnt % 10) == 0) {
+        LOG_D(RRC, "[UE %d] Frame %d T310_NB_IoT Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_cnt);
+      }
+
+      if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_cnt    == T310_NB_IoT[UE_rrc_inst_NB_IoT[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t310]) {
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
+        rrc_t310_expiration_NB_IoT (ctxt_pP, enb_indexP); //FIXME: maybe is required a NB_iot version of this function
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
+	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n");
+        return RRC_PHY_RESYNCH;
+      }
+
+      UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T310_cnt++;
+    }
+
+    if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T304_active==1) {
+      if ((UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T304_cnt % 10) == 0)
+        LOG_D(RRC,"[UE %d][RAPROC] Frame %d T304 Count %d ms\n",ctxt_pP->module_id,ctxt_pP->frame,
+              UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T304_cnt);
+
+      if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T304_cnt == 0) {
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T304_active = 0;
+        UE_rrc_inst_NB_IoT[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1;
+        LOG_E(RRC,"[UE %d] Handover failure..initiating connection re-establishment procedure... \n",
+              ctxt_pP->module_id);
+        //Implement 36.331, section 5.3.5.6 here
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
+        return(RRC_Handover_failed);
+      }
+
+      UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].T304_cnt--;
+    }
+
+    // Layer 3 filtering of RRC measurements
+    if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].QuantityConfig[0] != NULL) {
+      ue_meas_filtering(ctxt_pP,enb_indexP);
+    }
+
+    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
+
+    if (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[0].handoverTarget > 0) {
+      LOG_I(RRC,"[UE %d] Frame %d : RRC handover initiated\n", ctxt_pP->module_id, ctxt_pP->frame);
+    }
+
+    if((UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].State == RRC_HO_EXECUTION_NB_IoT)   &&
+        (UE_rrc_inst_NB_IoT[ctxt_pP->module_id].HandoverInfoUe.targetCellId != 0xFF)) {
+      UE_rrc_inst_NB_IoT[ctxt_pP->module_id].Info[enb_indexP].State= RRC_IDLE_NB_IoT;
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
+      return(RRC_HO_STARTED);
+    }
+
+  } else { // eNB
+
+	 //no handover in NB_IoT
+    // counter, and get the value and aggregate
+
+    // check for UL failure
+    RB_FOREACH(ue_context_p, rrc_ue_tree_NB_IoT_s, &(eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].rrc_ue_head)) {
+      if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) {
+	if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
+	  LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n",
+		ue_context_p->ue_context.rnti,
+		ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
+		ue_context_p->ue_context.ul_failure_timer);
+	}
+	else {
+	  LOG_I(RRC,"UE rnti %x failure timer %d/20000\n",
+		ue_context_p->ue_context.rnti,
+		ue_context_p->ue_context.ul_failure_timer);
+	}
+      }
+      if (ue_context_p->ue_context.ul_failure_timer>0) {
+	ue_context_p->ue_context.ul_failure_timer++;
+	if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
+	  // remove UE after 20 seconds after MAC has indicated UL failure
+	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
+	  ue_to_be_removed = ue_context_p;
+	  break;
+	}
+      }
+      if (ue_context_p->ue_context.ue_release_timer>0) {
+	ue_context_p->ue_context.ue_release_timer++;
+	if (ue_context_p->ue_context.ue_release_timer >=
+	    ue_context_p->ue_context.ue_release_timer_thres) {
+	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
+	  ue_to_be_removed = ue_context_p;
+	  break;
+	}
+      }
+    }
+    if (ue_to_be_removed)
+    	rrc_eNB_free_UE_NB_IoT(ctxt_pP->module_id,ue_to_be_removed);
+//no localization in NB-IoT
+
+    (void)ts; /* remove gcc warning "unused variable" */
+    (void)ref_timestamp_ms; /* remove gcc warning "unused variable" */
+    (void)current_timestamp_ms; /* remove gcc warning "unused variable" */
+  }
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
+  return (RRC_OK);
+}
+
+
+
diff --git a/openair2/RRC/LITE/rrc_common_nb_iot.c b/openair2/RRC/LITE/rrc_common_nb_iot.c
deleted file mode 100644
index 01ae789782be5ec3d05bd7913421986d5e67ba06..0000000000000000000000000000000000000000
--- a/openair2/RRC/LITE/rrc_common_nb_iot.c
+++ /dev/null
@@ -1,406 +0,0 @@
-/*
- * 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.0  (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 rrc_common.c
- * \brief rrc common procedures for eNB and UE
- * \author Navid Nikaein and Raymond Knopp
- * \date 2011 - 2014
- * \version 1.0
- * \company Eurecom
- * \email:  navid.nikaein@eurecom.fr and raymond.knopp@eurecom.fr
- */
-
-#include "defs_nb_iot.h"
-#include "extern.h"
-#include "LAYER2/MAC/extern.h"
-#include "COMMON/openair_defs.h"
-#include "COMMON/platform_types.h"
-#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
-#include "LAYER2/RLC/rlc.h"
-#include "COMMON/mac_rrc_primitives.h"
-#include "UTIL/LOG/log.h"
-#include "asn1_msg.h"
-#include "pdcp.h"
-#include "UTIL/LOG/vcd_signal_dumper.h"
-#include "rrc_eNB_UE_context.h"
-
-#ifdef LOCALIZATION
-#include <sys/time.h>
-#endif
-
-#define DEBUG_RRC 1
-extern eNB_MAC_INST *eNB_mac_inst;
-extern UE_MAC_INST *UE_mac_inst;
-
-extern mui_t rrc_eNB_mui;
-
-/*missed functions*/
-//rrc_top_cleanup
-//rrc_t310_expiration
-//binary_search_init
-//binary_search_float
-
-
-//configure  BCCH & CCCH Logical Channels and associated rrc_buffers, configure associated SRBs
-//called by openair_rrc_eNB_configuration_NB
-//-----------------------------------------------------------------------------
-void
-openair_eNB_rrc_on_NB(
-  const protocol_ctxt_t* const ctxt_pP
-)
-//-----------------------------------------------------------------------------
-{
-
-  int            CC_id;
-
-    LOG_I(RRC, PROTOCOL_RRC_CTXT_FMT" OPENAIR RRC-NB IN....\n",
-          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
-    for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-      rrc_config_buffer_NB (&eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SI, BCCH, 1);
-      eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SI.Active = 1;
-      rrc_config_buffer_NB (&eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0, CCCH, 1);
-      eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Active = 1;
-    }
-    //no UE side
- }
-
-
-
-//-----------------------------------------------------------------------------
-void
-rrc_config_buffer_NB(
-  SRB_INFO_NB* Srb_info,
-  uint8_t Lchan_type,
-  uint8_t Role
-)
-//-----------------------------------------------------------------------------
-{
-
-  Srb_info->Rx_buffer.payload_size = 0;
-  Srb_info->Tx_buffer.payload_size = 0;
-}
-
-
-//-----------------------------------------------------------------------------
-//XXX NEW mplementation by Raymond: still used but no more called by MAC/main.c instead directly called by rrc_eNB_nb_iot.c
-//XXX maybe this function is no more useful
-int
-rrc_init_global_param_NB(
-  void
-)
-//-----------------------------------------------------------------------------
-{
-
-  rrc_rlc_register_rrc (rrc_data_ind, NULL); //register with rlc
-
-  //XXX MP: most probably ALL of this stuff are no more needed (also the one not commented)
-
-//  DCCH_LCHAN_DESC.transport_block_size = 4;
-//  DCCH_LCHAN_DESC.max_transport_blocks = 16;
-//  DCCH_LCHAN_DESC.Delay_class = 1;
-//  DTCH_DL_LCHAN_DESC.transport_block_size = 52;
-//  DTCH_DL_LCHAN_DESC.max_transport_blocks = 20;
-//  DTCH_DL_LCHAN_DESC.Delay_class = 1;
-//  DTCH_UL_LCHAN_DESC.transport_block_size = 52;
-//  DTCH_UL_LCHAN_DESC.max_transport_blocks = 20;
-//  DTCH_UL_LCHAN_DESC.Delay_class = 1;
-
-  Rlc_info_am_config.rlc_mode = RLC_MODE_AM;
-  Rlc_info_am_config.rlc.rlc_am_info_NB.max_retx_threshold = 50;
-  Rlc_info_am_config.rlc.rlc_am_info_NB.t_poll_retransmit = 15;
-  Rlc_info_am_config.rlc.rlc_am_info_NB.enableStatusReportSN_Gap = 0; //FIXME MP: should be disabled
-
-#ifndef NO_RRM
-
-  if (L3_xface_init_NB ()) {
-    return (-1);
-  }
-
-#endif
-
-  return 0;
-}
-
-//shoudl be changed?
-#ifndef NO_RRM
-//-----------------------------------------------------------------------------
-int
-L3_xface_init_NB(
-  void
-)
-//-----------------------------------------------------------------------------
-{
-
-  int ret = 0;
-
-#ifdef USER_MODE
-
-  int sock;
-  LOG_D(RRC, "[L3_XFACE] init de l'interface \n");
-
-  if (open_socket (&S_rrc, RRC_RRM_SOCK_PATH, RRM_RRC_SOCK_PATH, 0) == -1) {
-    return (-1);
-  }
-
-  if (S_rrc.s == -1) {
-    return (-1);
-  }
-
-  socket_setnonblocking (S_rrc.s);
-  msg ("Interface Connected... RRM-RRC\n");
-  return 0;
-
-#else
-
-  ret=rtf_create(RRC2RRM_FIFO,32768);
-
-  if (ret < 0) {
-    msg("[openair][MAC][INIT] Cannot create RRC2RRM fifo %d (ERROR %d)\n",RRC2RRM_FIFO,ret);
-    return(-1);
-  } else {
-    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRC2RRM_FIFO);
-    rtf_reset(RRC2RRM_FIFO);
-  }
-
-  ret=rtf_create(RRM2RRC_FIFO,32768);
-
-  if (ret < 0) {
-    msg("[openair][MAC][INIT] Cannot create RRM2RRC fifo %d (ERROR %d)\n",RRM2RRC_FIFO,ret);
-    return(-1);
-  } else {
-    msg("[openair][MAC][INIT] Created RRC2RRM fifo %d\n",RRM2RRC_FIFO);
-    rtf_reset(RRM2RRC_FIFO);
-  }
-
-  return(0);
-
-#endif
-}
-#endif
-
-//------------------------------------------------------------------------------
-//specialized function for the eNB initialization (NB-IoT)
-//(OLD was called in MAC/main.c--> mac_top_init)(NEW is called in directly in "openair_rrc_eNB_configuration_NB")
-void
-openair_rrc_top_init_eNB_NB(void)//MP: XXX Raymond put this directly the definition on rrc_eNB.c file
-//-----------------------------------------------------------------------------
-{
-
-  int                 CC_id;
-
-  /* for no gcc warnings */
-  (void)CC_id;
-
-//not consider UE part
-
-  if (NB_eNB_INST > 0) {
-    eNB_rrc_inst_NB = (eNB_RRC_INST_NB*) malloc16(NB_eNB_INST*sizeof(eNB_RRC_INST_NB));
-    memset (eNB_rrc_inst_NB, 0, NB_eNB_INST * sizeof(eNB_RRC_INST_NB));
-
-//no CBA, no LOcalization, no MBMS flag
-
-    LOG_D(RRC,
-          "ALLOCATE %d Bytes for eNB_RRC_INST_NB @ %p\n", (unsigned int)(NB_eNB_INST*sizeof(eNB_RRC_INST_NB)), eNB_rrc_inst_NB);
-  } else {
-    eNB_rrc_inst_NB = NULL;
-  }
-
-#ifndef NO_RRM
-#ifndef USER_MODE
-
-  Header_buf=(char*)malloc16(sizeof(msg_head_t));
-  Data=(char*)malloc16(2400);
-  Header_read_idx=0;
-  Data_read_idx=0;
-  Header_size=sizeof(msg_head_t);
-
-#endif //NO_RRM
-  Data_to_read = 0;
-#endif //USER_MODE
-}
-
-//-----------------------------------------------------------------------------
-//XXX MP: most probably is not needed
-RRC_status_t
-rrc_rx_tx_NB(
-  protocol_ctxt_t* const ctxt_pP,
-  const uint8_t      enb_indexP,
-  const int          CC_id
-)
-//-----------------------------------------------------------------------------
-{
-  //uint8_t        UE_id;
-  int32_t        current_timestamp_ms, ref_timestamp_ms;
-  struct timeval ts;
-  struct rrc_eNB_ue_context_NB_s   *ue_context_p = NULL;
-  struct rrc_eNB_ue_context_NB_s		  *ue_to_be_removed = NULL;
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_IN);
-
-  if(ctxt_pP->enb_flag == ENB_FLAG_NO) {  //is an UE
-    // check timers
-
-    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_active == 1) {
-      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt % 10) == 0)
-        LOG_D(RRC,
-              "[UE %d][RAPROC] Frame %d T300 Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt);
-
-      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt
-          == T300[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t300]) {
-        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_active = 0;
-        // ALLOW CCCH to be used
-        UE_rrc_inst[ctxt_pP->module_id].Srb0[enb_indexP].Tx_buffer.payload_size = 0;
-        rrc_ue_generate_RRCConnectionRequest (ctxt_pP, enb_indexP);
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
-        return (RRC_ConnSetup_failed);
-      }
-
-      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T300_cnt++;
-    }
-
-    if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].SIStatus&2)>0) {
-      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt
-          == N310[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n310]) {
-	LOG_I(RRC,"Activating T310\n");
-        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 1;
-      }
-    } else { // in case we have not received SIB2 yet
-      /*      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt == 100) {
-        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N310_cnt = 0;
-
-	}*/
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
-      return RRC_OK;
-    }
-
-    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active == 1) {
-      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N311_cnt
-          == N311[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.n311]) {
-        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
-        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].N311_cnt = 0;
-      }
-
-      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt % 10) == 0) {
-        LOG_D(RRC, "[UE %d] Frame %d T310 Count %d ms\n", ctxt_pP->module_id, ctxt_pP->frame, UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt);
-      }
-
-      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt    == T310[UE_rrc_inst[ctxt_pP->module_id].sib2[enb_indexP]->ue_TimersAndConstants.t310]) {
-        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_active = 0;
-        rrc_t310_expiration (ctxt_pP, enb_indexP); //FIXME: maybe is required a NB_iot version of this function
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
-	LOG_I(RRC,"Returning RRC_PHY_RESYNCH: T310 expired\n");
-        return RRC_PHY_RESYNCH;
-      }
-
-      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T310_cnt++;
-    }
-
-    if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_active==1) {
-      if ((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt % 10) == 0)
-        LOG_D(RRC,"[UE %d][RAPROC] Frame %d T304 Count %d ms\n",ctxt_pP->module_id,ctxt_pP->frame,
-              UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt);
-
-      if (UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt == 0) {
-        UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_active = 0;
-        UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.measFlag = 1;
-        LOG_E(RRC,"[UE %d] Handover failure..initiating connection re-establishment procedure... \n",
-              ctxt_pP->module_id);
-        //Implement 36.331, section 5.3.5.6 here
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
-        return(RRC_Handover_failed);
-      }
-
-      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].T304_cnt--;
-    }
-
-    // Layer 3 filtering of RRC measurements
-    if (UE_rrc_inst[ctxt_pP->module_id].QuantityConfig[0] != NULL) {
-      ue_meas_filtering(ctxt_pP,enb_indexP);
-    }
-
-    ue_measurement_report_triggering(ctxt_pP,enb_indexP);
-
-    if (UE_rrc_inst[ctxt_pP->module_id].Info[0].handoverTarget > 0) {
-      LOG_I(RRC,"[UE %d] Frame %d : RRC handover initiated\n", ctxt_pP->module_id, ctxt_pP->frame);
-    }
-
-    if((UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State == RRC_HO_EXECUTION)   &&
-        (UE_rrc_inst[ctxt_pP->module_id].HandoverInfoUe.targetCellId != 0xFF)) {
-      UE_rrc_inst[ctxt_pP->module_id].Info[enb_indexP].State= RRC_IDLE;
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
-      return(RRC_HO_STARTED);
-    }
-
-  } else { // eNB
-
-	 //no handover in NB_IoT
-    // counter, and get the value and aggregate
-
-    // check for UL failure
-    RB_FOREACH(ue_context_p, rrc_ue_tree_NB_s, &(eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head)) {
-      if ((ctxt_pP->frame == 0) && (ctxt_pP->subframe==0)) {
-	if (ue_context_p->ue_context.Initialue_identity_s_TMSI.presence == TRUE) {
-	  LOG_I(RRC,"UE rnti %x:S-TMSI %x failure timer %d/20000\n",
-		ue_context_p->ue_context.rnti,
-		ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
-		ue_context_p->ue_context.ul_failure_timer);
-	}
-	else {
-	  LOG_I(RRC,"UE rnti %x failure timer %d/20000\n",
-		ue_context_p->ue_context.rnti,
-		ue_context_p->ue_context.ul_failure_timer);
-	}
-      }
-      if (ue_context_p->ue_context.ul_failure_timer>0) {
-	ue_context_p->ue_context.ul_failure_timer++;
-	if (ue_context_p->ue_context.ul_failure_timer >= 20000) {
-	  // remove UE after 20 seconds after MAC has indicated UL failure
-	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
-	  ue_to_be_removed = ue_context_p;
-	  break;
-	}
-      }
-      if (ue_context_p->ue_context.ue_release_timer>0) {
-	ue_context_p->ue_context.ue_release_timer++;
-	if (ue_context_p->ue_context.ue_release_timer >=
-	    ue_context_p->ue_context.ue_release_timer_thres) {
-	  LOG_I(RRC,"Removing UE %x instance\n",ue_context_p->ue_context.rnti);
-	  ue_to_be_removed = ue_context_p;
-	  break;
-	}
-      }
-    }
-    if (ue_to_be_removed)
-      rrc_eNB_free_UE(ctxt_pP->module_id,ue_to_be_removed); //FIXME: quite comple procedure, should use the same for NB-IoT?
-
-//no localization in NB-IoT
-
-    (void)ts; /* remove gcc warning "unused variable" */
-    (void)ref_timestamp_ms; /* remove gcc warning "unused variable" */
-    (void)current_timestamp_ms; /* remove gcc warning "unused variable" */
-  }
-
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RRC_RX_TX,VCD_FUNCTION_OUT);
-  return (RRC_OK);
-}
-
-
-
diff --git a/openair2/RRC/LITE/rrc_eNB.c b/openair2/RRC/LITE/rrc_eNB.c
index 0e8496e02a3f12be213c235159ebd2f6126b299d..80a4d25dc6a96e78b0c459ce4b74065ce15b8bd5 100644
--- a/openair2/RRC/LITE/rrc_eNB.c
+++ b/openair2/RRC/LITE/rrc_eNB.c
@@ -3628,7 +3628,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete(
 
         } else {        // remove LCHAN from MAC/PHY
 
-          if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) { //???
+          if (ue_context_pP->ue_context.DRB_active[drb_id] == 1) {
             // DRB has just been removed so remove RLC + PDCP for DRB
             /*      rrc_pdcp_config_req (ctxt_pP->module_id, frameP, 1, CONFIG_ACTION_REMOVE,
                (ue_mod_idP * NB_RB_MAX) + DRB2LCHAN[i],UNDEF_SECURITY_MODE);
diff --git a/openair2/RRC/LITE/rrc_eNB_nb_iot.c b/openair2/RRC/LITE/rrc_eNB_NB_IoT.c
similarity index 67%
rename from openair2/RRC/LITE/rrc_eNB_nb_iot.c
rename to openair2/RRC/LITE/rrc_eNB_NB_IoT.c
index 6fb2c1b7005e11f18ba9fce301c92c12f60b3437..1beb33649937b977c1903bfaeb6553c725c16b54 100644
--- a/openair2/RRC/LITE/rrc_eNB_nb_iot.c
+++ b/openair2/RRC/LITE/rrc_eNB_NB_IoT.c
@@ -30,8 +30,12 @@
 #define RRC_ENB_C
 
 /*NB-IoT include files*/
-#include "defs_nb_iot.h"
-#include "RRC/LITE/MESSAGES/asn1_msg_nb_iot.h"
+//#include "PHY/extern_NB_IoT.h"
+#include "LAYER2/MAC/extern_NB_IoT.h"
+//#include "RRC/LITE/proto_NB_IoT.h"
+#include "defs_NB_IoT.h"
+#include "openair1/SCHED/defs_NB_IoT.h"
+#include "RRC/LITE/MESSAGES/asn1_msg_NB_IoT.h"
 #include "RRCConnectionRequest-NB.h"
 #include "RRCConnectionReestablishmentRequest-NB.h"
 #include "ReestablishmentCause-NB-r13.h"
@@ -39,36 +43,28 @@
 #include "DL-CCCH-Message-NB.h"
 #include "UL-DCCH-Message-NB.h"
 #include "DL-DCCH-Message-NB.h"
+#include "SRB-ToAddMod-NB-r13.h"
 
-#include "extern.h"
-#include "extern_nb_iot.h"
+#include "common/utils/collection/tree.h"
+//#include "extern.h"
+#include "extern_NB_IoT.h"
 #include "assertions.h"
 #include "asn1_conversions.h"
 #include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
 #include "LAYER2/RLC/rlc.h"
-#include "LAYER2/MAC/proto.h"
+//#include "LAYER2/MAC/proto.h"
+#include "LAYER2/MAC/proto_NB_IoT.h"
 #include "UTIL/LOG/log.h"
 #include "COMMON/mac_rrc_primitives.h"
-//#include "RRC/LITE/MESSAGES/asn1_msg.h"
-//#include "RRCConnectionRequest.h"
-//#include "RRCConnectionReestablishmentRequest.h"
-//#include "ReestablishmentCause.h"
-//#include "UL-CCCH-Message.h"
-//#include "DL-CCCH-Message.h"
-//#include "UL-DCCH-Message.h"
-//#include "DL-DCCH-Message.h"
-//#include "TDD-Config.h"
-//#include "HandoverCommand.h"
 #include "rlc.h"
 #include "SIMULATION/ETH_TRANSPORT/extern.h"
-#include "rrc_eNB_UE_context.h"
+#include "rrc_eNB_UE_context_NB_IoT.h"
 #include "platform_types.h"
 #include "msc.h"
 #include "T.h"
 
-//FIXME: MP: once defined properly the MAC/defs_nb_iot this should be deleted
-#include "LAYER2/MAC/defs.h"
-#include "LAYER2/MAC/defs_nb_iot.h"
+//#include "LAYER2/MAC/defs.h"
+#include "LAYER2/MAC/defs_NB_IoT.h"
 
 
 #ifdef USER_MODE
@@ -97,7 +93,7 @@
 #   include "intertask_interface.h"
 #endif
 
-#include "SIMULATION/TOOLS/defs.h" // for taus
+//#include "SIMULATION/TOOLS/defs.h" // for taus
 
 #if defined(FLEXRAN_AGENT_SB_IF)
 #include "flexran_agent_extern.h"
@@ -107,26 +103,78 @@
 #ifdef PHY_EMUL
 extern EMULATION_VARS              *Emul_vars;
 #endif
-extern eNB_MAC_INST              *eNB_mac_inst;
-extern UE_MAC_INST                 *UE_mac_inst;
+
 #ifdef BIGPHYSAREA
-extern void*                        bigphys_malloc(int);
+extern void*                       bigphys_malloc(int);
 #endif
 
-extern uint16_t                     two_tier_hexagonal_cellIds[7];
 
-mui_t                               rrc_eNB_mui = 0;
+/*the Message Unit Identifieer (MUI) is an Identity of the RLC SDU, whic is used to indicate which RLC SDU that is confirmed
+ * with the RLC-AM-Data-conf. e.g. ((struct rlc_am_data_req *) (new_sdu_p->data))->mui (rlc_data_req_NB_IoT)
+ */
+mui_t                               rrc_eNB_mui_NB_IoT = 0;
 
 
 
+// should be called when UE is lost by eNB
+void rrc_eNB_free_UE_NB_IoT(const module_id_t enb_mod_idP,const struct rrc_eNB_ue_context_NB_IoT_s*        const ue_context_pP)
+//-----------------------------------------------------------------------------
+{
+
+
+  protocol_ctxt_t                     ctxt;
+#if !defined(ENABLE_USE_MME)
+  module_id_t                         ue_module_id;
+  /* avoid gcc warnings */
+  (void)ue_module_id;
+#endif
+  rnti_t rnti = ue_context_pP->ue_context.rnti;
+
+  /*  ue_context_p = rrc_eNB_get_ue_context(
+                   &eNB_rrc_inst[enb_mod_idP],
+                   rntiP
+                 );
+  */
+  if (NULL != ue_context_pP) {
+    PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, enb_mod_idP, ENB_FLAG_YES, rnti, 0, 0,enb_mod_idP);
+    LOG_W(RRC, "[eNB %d] Removing UE RNTI %x\n", enb_mod_idP, rnti);
+
+#if defined(ENABLE_USE_MME)
+    // warning here because of  we don't have NB-IoT S1AP functions
+    //rrc_eNB_send_S1AP_UE_CONTEXT_RELEASE_REQ(enb_mod_idP, ue_context_pP, S1AP_CAUSE_RADIO_NETWORK, 21); // send cause 21: connection with ue lost
+    /* From 3GPP 36300v10 p129 : 19.2.2.2.2 S1 UE Context Release Request (eNB triggered)
+     * If the E-UTRAN internal reason is a radio link failure detected in the eNB, the eNB shall wait a sufficient time before
+     *  triggering the S1 UE Context Release Request procedure
+     *  in order to allow the UE to perform the NAS recovery
+     *  procedure, see TS 23.401 [17].
+     */
+#else
+#if defined(OAI_EMU)
+    AssertFatal(ue_context_pP->local_uid < NUMBER_OF_UE_MAX_NB_IoT, "local_uid invalid (%d<%d) for UE %x!", ue_context_pP->local_uid, NUMBER_OF_UE_MAX_NB_IoT, rnti);
+    ue_module_id = oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[enb_mod_idP][ue_context_pP->local_uid];
+    AssertFatal(ue_module_id < NUMBER_OF_UE_MAX_NB_IoT, "ue_module_id invalid (%d<%d) for UE %x!", ue_module_id, NUMBER_OF_UE_MAX_NB_IoT, rnti);
+    oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[enb_mod_idP][ue_context_pP->local_uid] = -1;
+    oai_emulation.info.eNB_ue_module_id_to_rnti[enb_mod_idP][ue_module_id] = NOT_A_RNTI;
+#endif
+#endif
+
+    //rrc_mac_remove_ue_NB_IoT(enb_mod_idP,rnti);
+    rrc_rlc_remove_ue(&ctxt);
+    pdcp_remove_UE(&ctxt);
+
+    rrc_eNB_remove_ue_context_NB_IoT(
+      &ctxt,
+      &eNB_rrc_inst_NB_IoT[enb_mod_idP],
+      (struct rrc_eNB_ue_context_NB_IoT_s*) ue_context_pP);
+  }
+}
 
 
 //-----------------------------------------------------------------------------
 //actually is not used
-void
-rrc_eNB_generate_RRCConnectionRelease_NB(
+void rrc_eNB_generate_RRCConnectionRelease_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
 )
 //-----------------------------------------------------------------------------
 {
@@ -139,9 +187,9 @@ rrc_eNB_generate_RRCConnectionRelease_NB(
 
   memset(buffer, 0, RRC_BUF_SIZE);
 
-  size = do_RRCConnectionRelease_NB(ctxt_pP->module_id,
+  size = do_RRCConnectionRelease_NB_IoT(ctxt_pP->module_id,
 		  	  	  	  	  	  	  	  buffer,
-									  rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id));
+									  rrc_eNB_get_next_transaction_identifier_NB_IoT(ctxt_pP->module_id));
   // set release timer
   ue_context_pP->ue_context.ue_release_timer=1;
   // remove UE after 10 frames after RRCConnectionRelease is triggered
@@ -156,8 +204,8 @@ rrc_eNB_generate_RRCConnectionRelease_NB(
         PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (rrcConnectionRelease-NB MUI %d) --->[PDCP][RB %u]\n",
         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
         size,
-        rrc_eNB_mui,
-        DCCH1);//Through SRB1/or SRB1bis
+        rrc_eNB_mui_NB_IoT,
+        DCCH1_NB_IoT);//Through SRB1/or SRB1bis
 
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
@@ -167,13 +215,13 @@ rrc_eNB_generate_RRCConnectionRelease_NB(
     MSC_AS_TIME_FMT" rrcConnectionRelease-NB UE %x MUI %d size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP->ue_context.rnti,
-    rrc_eNB_mui,
+    rrc_eNB_mui_NB_IoT,
     size);
 
-  rrc_data_req(
+  rrc_data_req_NB_IoT(
 	       ctxt_pP,
-	       DCCH1,//Through SRB1/or SRB1bis
-	       rrc_eNB_mui++,
+	       DCCH1_NB_IoT,//Through SRB1/or SRB1bis
+	       rrc_eNB_mui_NB_IoT++,
 	       SDU_CONFIRM_NO,
 	       size,
 	       buffer,
@@ -182,10 +230,9 @@ rrc_eNB_generate_RRCConnectionRelease_NB(
 
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_generate_RRCConnectionReestablishmentReject_NB(
+void rrc_eNB_generate_RRCConnectionReestablishmentReject_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP,
   const int                    CC_id
 )
 //-----------------------------------------------------------------------------
@@ -198,15 +245,15 @@ rrc_eNB_generate_RRCConnectionReestablishmentReject_NB(
   T(T_ENB_RRC_CONNECTION_REESTABLISHMENT_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
-    do_RRCConnectionReestablishmentReject_NB(ctxt_pP->module_id,
-                          (uint8_t*) eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload);
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
+    do_RRCConnectionReestablishmentReject_NB_IoT(ctxt_pP->module_id,
+                          (uint8_t*) eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload);
 
 #ifdef RRC_MSG_PRINT
   LOG_F(RRC,"[MSG] RRCConnectionReestablishmentReject\n");
 
-  for (cnt = 0; cnt < eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
-    LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]);
+  for (cnt = 0; cnt < eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
+    LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]);
   }
 
   LOG_F(RRC,"\n");
@@ -215,24 +262,23 @@ rrc_eNB_generate_RRCConnectionReestablishmentReject_NB(
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
     MSC_RRC_UE,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size,
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header,
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size,
     MSC_AS_TIME_FMT" RRCConnectionReestablishmentReject UE %x size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
 
   LOG_I(RRC,
         PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReestablishmentReject (bytes %d)\n",
         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-        eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
+        eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_free_mem_UE_context_NB(
+void rrc_eNB_free_mem_UE_context_NB_IoT(
   const protocol_ctxt_t*               const ctxt_pP,
-  struct rrc_eNB_ue_context_NB_s*         const ue_context_pP
+  struct rrc_eNB_ue_context_NB_IoT_s*         const ue_context_pP
 )
 //-----------------------------------------------------------------------------
 {
@@ -255,15 +301,15 @@ rrc_eNB_free_mem_UE_context_NB(
 
   memset(ue_context_pP->ue_context.DRB_active, 0, sizeof(ue_context_pP->ue_context.DRB_active));
 
-  if (ue_context_pP->ue_context.physicalConfigDedicated_NB) {
-    ASN_STRUCT_FREE(asn_DEF_PhysicalConfigDedicated_NB_r13, ue_context_pP->ue_context.physicalConfigDedicated_NB);
-    ue_context_pP->ue_context.physicalConfigDedicated_NB = NULL;
+  if (ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT) {
+    ASN_STRUCT_FREE(asn_DEF_PhysicalConfigDedicated_NB_r13, ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT);
+    ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT = NULL;
   }
 
 
-  if (ue_context_pP->ue_context.mac_MainConfig_NB) {
-    ASN_STRUCT_FREE(asn_DEF_MAC_MainConfig_NB_r13, ue_context_pP->ue_context.mac_MainConfig_NB);
-    ue_context_pP->ue_context.mac_MainConfig_NB = NULL;
+  if (ue_context_pP->ue_context.mac_MainConfig_NB_IoT) {
+    ASN_STRUCT_FREE(asn_DEF_MAC_MainConfig_NB_r13, ue_context_pP->ue_context.mac_MainConfig_NB_IoT);
+    ue_context_pP->ue_context.mac_MainConfig_NB_IoT = NULL;
   }
 
   //no sps in NB_IoT
@@ -278,16 +324,16 @@ rrc_eNB_free_mem_UE_context_NB(
 
 //-----------------------------------------------------------------------------
 // return the ue context if there is already an UE with ue_identityP, NULL otherwise
-static struct rrc_eNB_ue_context_NB_s*
-rrc_eNB_ue_context_random_exist_NB(
+static struct rrc_eNB_ue_context_NB_IoT_s*
+rrc_eNB_ue_context_random_exist_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const uint64_t               ue_identityP
 )
 //-----------------------------------------------------------------------------
 {
-  struct rrc_eNB_ue_context_NB_s*        ue_context_p = NULL;
-  //FIXME: there is a warning related to the new  type rrc_ue_tree_NB_s
-  RB_FOREACH(ue_context_p, rrc_ue_tree_NB_s, &(eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head)) {
+  struct rrc_eNB_ue_context_NB_IoT_s*        ue_context_p = NULL;
+  //FIXME: there is a warning related to the new  type rrc_ue_tree_NB_IoT_s
+  RB_FOREACH(ue_context_p, rrc_ue_tree_NB_IoT_s, &(eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].rrc_ue_head)) {
     if (ue_context_p->ue_context.random_ue_identity == ue_identityP)
       return ue_context_p;
   }
@@ -296,20 +342,20 @@ rrc_eNB_ue_context_random_exist_NB(
 
 //-----------------------------------------------------------------------------
 // return a new ue context structure if ue_identityP, ctxt_pP->rnti not found in collection
-static struct rrc_eNB_ue_context_NB_s*
-rrc_eNB_get_next_free_ue_context_NB(
+static struct rrc_eNB_ue_context_NB_IoT_s*
+rrc_eNB_get_next_free_ue_context_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const uint64_t               ue_identityP
 )
 //-----------------------------------------------------------------------------
 {
-  struct rrc_eNB_ue_context_NB_s*        ue_context_p = NULL;
-  ue_context_p = rrc_eNB_get_ue_context_NB(
-                   &eNB_rrc_inst_NB[ctxt_pP->module_id],
+  struct rrc_eNB_ue_context_NB_IoT_s*        ue_context_p = NULL;
+  ue_context_p = rrc_eNB_get_ue_context_NB_IoT(
+                   &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id],
                    ctxt_pP->rnti);
 
   if (ue_context_p == NULL) {
-    RB_FOREACH(ue_context_p, rrc_ue_tree_NB_s, &(eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head)) {
+    RB_FOREACH(ue_context_p, rrc_ue_tree_NB_IoT_s, &(eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].rrc_ue_head)) {
       if (ue_context_p->ue_context.random_ue_identity == ue_identityP) {
         LOG_D(RRC,
               PROTOCOL_RRC_CTXT_UE_FMT" Cannot create new UE context, already exist rand UE id 0x%"PRIx64", uid %u\n",
@@ -319,7 +365,7 @@ rrc_eNB_get_next_free_ue_context_NB(
         return NULL;
       }
     }
-    ue_context_p = rrc_eNB_allocate_new_UE_context(&eNB_rrc_inst_NB[ctxt_pP->module_id]);
+    ue_context_p = rrc_eNB_allocate_new_UE_context_NB_IoT(&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id]);
 
     if (ue_context_p == NULL) {
       LOG_E(RRC,
@@ -331,7 +377,7 @@ rrc_eNB_get_next_free_ue_context_NB(
     ue_context_p->ue_id_rnti                    = ctxt_pP->rnti; // here ue_id_rnti is just a key, may be something else
     ue_context_p->ue_context.rnti               = ctxt_pP->rnti; // yes duplicate, 1 may be removed
     ue_context_p->ue_context.random_ue_identity = ue_identityP;
-    RB_INSERT(rrc_ue_tree_NB_s, &eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
+    RB_INSERT(rrc_ue_tree_NB_IoT_s, &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
     LOG_D(RRC,
           PROTOCOL_RRC_CTXT_UE_FMT" Created new UE context uid %u\n",
           PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
@@ -348,7 +394,7 @@ rrc_eNB_get_next_free_ue_context_NB(
 
 //-----------------------------------------------------------------------------
 // return the ue context if there is already an UE with the same S-TMSI(MMEC+M-TMSI), NULL otherwise
-static struct rrc_eNB_ue_context_NB_s*
+static struct rrc_eNB_ue_context_NB_IoT_s*
 rrc_eNB_ue_context_stmsi_exist_NB(
   const protocol_ctxt_t* const ctxt_pP,
   const mme_code_t             mme_codeP,
@@ -356,8 +402,8 @@ rrc_eNB_ue_context_stmsi_exist_NB(
 )
 //-----------------------------------------------------------------------------
 {
-  struct rrc_eNB_ue_context_NB_s*        ue_context_p = NULL;
-  RB_FOREACH(ue_context_p, rrc_ue_tree_NB_s, &(eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head)) {
+  struct rrc_eNB_ue_context_NB_IoT_s*        ue_context_p = NULL;
+  RB_FOREACH(ue_context_p, rrc_ue_tree_NB_IoT_s, &(eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].rrc_ue_head)) {
     LOG_I(RRC,"checking for UE S-TMSI %x, mme %x (%p): rnti %x",
 	  m_tmsiP, mme_codeP, ue_context_p,
 	  ue_context_p->ue_context.rnti);
@@ -377,8 +423,7 @@ rrc_eNB_ue_context_stmsi_exist_NB(
 }
 
 //-----------------------------------------------------------------------------
-uint8_t
-rrc_eNB_get_next_transaction_identifier_NB(
+uint8_t rrc_eNB_get_next_transaction_identifier_NB_IoT(
   module_id_t enb_mod_idP
 )
 //-----------------------------------------------------------------------------
@@ -390,10 +435,9 @@ rrc_eNB_get_next_transaction_identifier_NB(
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_generate_RRCConnectionReject_NB(
+void rrc_eNB_generate_RRCConnectionReject_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP,
   const int                    CC_id
 )
 //-----------------------------------------------------------------------------
@@ -405,15 +449,15 @@ rrc_eNB_generate_RRCConnectionReject_NB(
   T(T_ENB_RRC_CONNECTION_REJECT, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
-    do_RRCConnectionReject_NB(ctxt_pP->module_id,
-                          (uint8_t*) eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload);
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
+    do_RRCConnectionReject_NB_IoT(ctxt_pP->module_id,
+                                  (uint8_t*) eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload);
 
 #ifdef RRC_MSG_PRINT
   LOG_F(RRC,"[MSG] RRCConnectionReject-NB\n");
 
-  for (cnt = 0; cnt < eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
-    LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]);
+  for (cnt = 0; cnt < eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
+    LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]);
   }
 
   LOG_F(RRC,"\n");
@@ -422,29 +466,27 @@ rrc_eNB_generate_RRCConnectionReject_NB(
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
     MSC_RRC_UE,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size,
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header,
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size,
     MSC_AS_TIME_FMT" RRCConnectionReject-NB UE %x size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP == NULL ? -1 : ue_context_pP->ue_context.rnti,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
 
   LOG_I(RRC,
         PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionReject-NB (bytes %d)\n",
         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-        eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
+        eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_generate_RRCConnectionSetup_NB(
+void rrc_eNB_generate_RRCConnectionSetup_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP,
   const int                    CC_id
 )
 //-----------------------------------------------------------------------------
 {
-
 	//connection setup involve the establishment of SRB1 and SRB1bis (but srb1bis is established implicitly)
 	//XXX: this message should go through SRB0 to see this--> uper_encode
 	//XXX: they are assuming that 2 RLC-AM entities are used for SRB1 and SRB1bis
@@ -454,35 +496,36 @@ rrc_eNB_generate_RRCConnectionSetup_NB(
 //  SRB_ToAddMod_NB_r13_t                     *SRB1_config; //may not needed now
 //  LogicalChannelConfig_NB_r13_t             *SRB1_logicalChannelConfig;
 
-  SRB_ToAddModList_NB_r13_t                **SRB_configList; //for both SRB1 and SRB1bis
-  SRB_ToAddMod_NB_r13_t						*SRB1bis_config;
+  SRB_ToAddModList_NB_r13_t           **SRB_configList; //for both SRB1 and SRB1bis
+  SRB_ToAddMod_NB_r13_t						    *SRB1bis_config;
   LogicalChannelConfig_NB_r13_t				*SRB1bis_logicalChannelConfig;
 
   int  										cnt;
 
-  //FIXME: MP: structure to be chaged at phy layer
-  LTE_DL_FRAME_PARMS *fp = mac_xface->get_lte_frame_parms(ctxt_pP->module_id,CC_id);
 
+  //XXX MP:warning due to function still not completed at PHY (get_lte_frame_parms)
+  //XXX this approach is gone most probably
+  NB_IoT_DL_FRAME_PARMS *fp = get_NB_IoT_frame_parms(ctxt_pP->module_id,CC_id);
   T(T_ENB_RRC_CONNECTION_SETUP, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
   SRB_configList = &ue_context_pP->ue_context.SRB_configList;
 
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
-    do_RRCConnectionSetup_NB(ctxt_pP,
-                          ue_context_pP,
-                          CC_id,
-                          (uint8_t*) eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload,
-                          rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id),
-                          fp,
-                          SRB_configList, //MP:should contain only SRb1bis for the moment
-                          &ue_context_pP->ue_context.physicalConfigDedicated_NB);
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size =
+    do_RRCConnectionSetup_NB_IoT(ctxt_pP,
+                                 ue_context_pP,
+                                 CC_id,
+                                 (uint8_t*) eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Payload,
+                                 rrc_eNB_get_next_transaction_identifier_NB_IoT(ctxt_pP->module_id),
+                                 fp,
+                                 SRB_configList, //MP:should contain only SRb1bis for the moment
+                                 &ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT);
 
 #ifdef RRC_MSG_PRINT
   LOG_F(RRC,"[MSG] RRC Connection Setup\n");
 
-  for (cnt = 0; cnt < eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
-    LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]);
+  for (cnt = 0; cnt < eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size; cnt++) {
+    LOG_F(RRC,"%02x ", ((uint8_t*)eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].Srb0.Tx_buffer.Payload)[cnt]);
   }
 
   LOG_F(RRC,"\n");
@@ -493,8 +536,7 @@ rrc_eNB_generate_RRCConnectionSetup_NB(
 
   if (*SRB_configList != NULL) {
 
-	  //XXX MP: srb_identity is no more used in NB-IoT
-	  //XXX MP: the list should contain just one element
+	  // MP: the list should contain just one element
 	  for(cnt = 0; cnt < (*SRB_configList)->list.count; cnt++){
 
         SRB1bis_config = (*SRB_configList)->list.array[cnt];
@@ -505,11 +547,10 @@ rrc_eNB_generate_RRCConnectionSetup_NB(
             SRB1bis_logicalChannelConfig = &SRB1bis_config->logicalChannelConfig_r13->choice.explicitValue;
           }
           else {
-        	  //XXX MP: warning saying "assignment from incompatible pointer type"
-            SRB1bis_logicalChannelConfig = &SRB1bis_NB_logicalChannelConfig_defaultValue;
+            SRB1bis_logicalChannelConfig = &SRB1bis_logicalChannelConfig_defaultValue_NB_IoT;
           	  }
         } else {
-          SRB1bis_logicalChannelConfig = &SRB1bis_NB_logicalChannelConfig_defaultValue;
+          SRB1bis_logicalChannelConfig = &SRB1bis_logicalChannelConfig_defaultValue_NB_IoT;
         }
 
         LOG_D(RRC,
@@ -517,33 +558,35 @@ rrc_eNB_generate_RRCConnectionSetup_NB(
               PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
 
 
-        //FIXME: Connection Setup could be called also after security activation
+        //XXX: Maybe some problem if Connection Setup could be called also after security activation
 
-        //configure the MAC for SRB1bis/SRb1???? (but in principle this configuration should be not LCID dependent)
-        NB_rrc_mac_config_req_eNB(
+        //configure the MAC for SRB1bis/SRb1 (but in principle this configuration should be not LCID dependent)
+        /*rrc_mac_config_req_eNB_NB_IoT(
           ctxt_pP->module_id,
           ue_context_pP->ue_context.primaryCC_id,
           ue_context_pP->ue_context.rnti,
           0, //physCellID
 		  0, //p_eNB
+		  0, //p_rx_eNB
 		  0, //Ncp
+		  0, //Ncp_UL
 		  0, //eutraband
 		  (NS_PmaxList_NB_r13_t*) NULL,
 		  (MultiBandInfoList_NB_r13_t*) NULL,
 		  (DL_Bitmap_NB_r13_t*) NULL,
-		  (long*) NULL,
+		  (long*) NULL,//eutraControlRegionSize
 		  (long*)NULL,
-		  (uint8_t*) NULL, //SIWindowSize
-		  (uint16_t*)NULL, //SIperiod
+//		  (uint8_t*) NULL, //SIWindowSize
+//		  (uint16_t*)NULL, //SIperiod
 		  0, //dl_carrierFrequency
 		  0, //ul_carrierFrequency
 		  (BCCH_BCH_Message_NB_t*) NULL,
           (RadioResourceConfigCommonSIB_NB_r13_t *) NULL,
-          (PhysicalConfigDedicated_NB_r13_t*) ue_context_pP->ue_context.physicalConfigDedicated_NB,
-          ue_context_pP->ue_context.mac_MainConfig_NB, //XXX most probably is not needed since is only at UE side
-          DCCH0, //LCID  = 3 of SRB1bis
+          (PhysicalConfigDedicated_NB_r13_t*) ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT,
+          ue_context_pP->ue_context.mac_MainConfig_NB_IoT, //XXX most probably is not needed since is only at UE side
+          DCCH0_NB_IoT, //LCID  = 3 of SRB1bis
           SRB1bis_logicalChannelConfig
-		  );
+		  );*/
         break;
     }
   }
@@ -551,18 +594,18 @@ rrc_eNB_generate_RRCConnectionSetup_NB(
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
     MSC_RRC_UE,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header, // LG WARNING
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size,
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.Header, // LG WARNING
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size,
     MSC_AS_TIME_FMT" RRCConnectionSetup-NB UE %x size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP->ue_context.rnti,
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
 
 
   LOG_I(RRC,
         PROTOCOL_RRC_CTXT_UE_FMT" [RAPROC] Logical Channel DL-CCCH, Generating RRCConnectionSetup-NB (bytes %d)\n",
         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-        eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
+        eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Srb0.Tx_buffer.payload_size);
 
   // activate release timer, if RRCSetupComplete-NB not received after 10 frames, remove UE
   ue_context_pP->ue_context.ue_release_timer=1;
@@ -572,10 +615,9 @@ rrc_eNB_generate_RRCConnectionSetup_NB(
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
+void rrc_eNB_process_RRCConnectionReconfigurationComplete_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*        ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*        ue_context_pP,
   const uint8_t xid //transaction identifier
 )
 //-----------------------------------------------------------------------------
@@ -632,7 +674,7 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP->ue_context.rnti);
 
-  NB_rrc_pdcp_config_asn1_req(
+  rrc_pdcp_config_asn1_req_NB_IoT(
     ctxt_pP,
     SRB_configList2,
     DRB_configList2,
@@ -642,10 +684,10 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
     kRRCint,
     kUPenc,
 	NULL,
-	DCCH1); //SRB1
+	DCCH1_NB_IoT); //SRB1
 
   // Refresh SRBs/DRBs for RLC
-  NB_rrc_rlc_config_asn1_req(
+  rrc_rlc_config_asn1_req_NB_IoT(
     ctxt_pP,
     SRB_configList2,
     DRB_configList2,
@@ -656,14 +698,13 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
   // set the SRB active in Ue context
 
   if (SRB_configList2 != NULL) {
-	  //MP: SRB_ToAddModList_NB_r13_t  size = 1 TS 36.331 V14.2.1 pag 615
-	  //MP: may for loop is not needed --> should stop at first iteration
+	  //MP: SRB_ToAddModList_NB_r13_t  size = 1 TS 36.331 V14.2.1 pag 615  should stop at first iteration
 
     for (i = 0; (i < SRB_configList2->list.count) && (i < 3); i++) {
     	//no need of checking the srb-Identity
     	//we should have only SRB1 in the list
     	ue_context_pP->ue_context.Srb1.Active=1;
-	    ue_context_pP->ue_context.Srb1.Srb_info.Srb_id=DCCH1; //LCHAN_iD
+	    ue_context_pP->ue_context.Srb1.Srb_info.Srb_id=DCCH1_NB_IoT; //LCHAN_iD
 	     LOG_I(RRC,"[eNB %d] Frame  %d CC %d : SRB1 is now active\n",
 		ctxt_pP->module_id,
 		ctxt_pP->frame,
@@ -713,12 +754,11 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
           if (oip_ifup == 0) {    // interface is up --> send a config the DRB
 #      ifdef OAI_EMU
             oai_emulation.info.oai_ifup[ctxt_pP->module_id] = 1;
-            dest_ip_offset = NB_eNB_INST;
 #      else
             dest_ip_offset = 8;
 #      endif
             LOG_I(OIP,
-                  "[eNB %d] Config the oai%d to send/receive pkt on DRB %d to/from the protocol stack\n",
+                  "[eNB %d] Config the oai%d to send/receive pkt on DRB %ld to/from the protocol stack\n",
                   ctxt_pP->module_id, ctxt_pP->module_id,
                   (ue_context_pP->local_uid * maxDRB_NB_r13) + DRB_configList2->list.array[i]->drb_Identity_r13);
             ue_module_id = oai_emulation.info.eNB_ue_local_uid_to_ue_module_id[ctxt_pP->module_id][ue_context_pP->local_uid];
@@ -745,34 +785,36 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
                 PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
 
           if (DRB_configList2->list.array[i]->logicalChannelIdentity_r13) {
-            DRB2LCHAN_NB[i] = (uint8_t) * DRB_configList2->list.array[i]->logicalChannelIdentity_r13; //set in RRCConnectionReconfiguration (x+3)
+            DRB2LCHAN_NB_IoT[i] = (uint8_t) * DRB_configList2->list.array[i]->logicalChannelIdentity_r13; //set in RRCConnectionReconfiguration (x+3)
           }
 
-          //MP: for each DRB I send a rrc_mac_config_req--> what change is the DRB2LCHAN_NB and logicalChannelConfig_r13
-          NB_rrc_mac_config_req_eNB(
+          //MP: for each DRB I send a rrc_mac_config_req--> what change is the DRB2LCHAN_NB_IoT and logicalChannelConfig_r13
+          /*rrc_mac_config_req_eNB_NB_IoT(
             ctxt_pP->module_id,
             ue_context_pP->ue_context.primaryCC_id,
             ue_context_pP->ue_context.rnti,
             0,//physCellId --> this parameters could be set to 0 since no MIB is present
 			0,// p_eNB
+			0,//p_rx_eNB
 			0, //Ncp
+			0, //Ncp_UL
 			0, //eutra_band
 			(struct NS_PmaxList_NB_r13*) NULL,
 			(struct MultiBandInfoList_NB_r13*) NULL,
 			(struct DL_Bitmap_NB_r13*) NULL,
 			(long*)NULL,//eutraControlRegionSize
 			(long*)NULL, //nrs_CRS_PowerOffset
-			(uint8_t*)NULL,
-			(uint16_t*)NULL,
+//			(uint8_t*)NULL,
+//			(uint16_t*)NULL,
 			0, //dl_CarrierFreq
 			0, //ul_CarrierFreq
 			(BCCH_BCH_Message_NB_t*)NULL,
 			(RadioResourceConfigCommonSIB_NB_r13_t*)NULL,
-            ue_context_pP->ue_context.physicalConfigDedicated_NB,
-            ue_context_pP->ue_context.mac_MainConfig_NB,
-            DRB2LCHAN_NB[i], //over the logical channel id of the DRB (>=4)
+            ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT,
+            ue_context_pP->ue_context.mac_MainConfig_NB_IoT,
+            DRB2LCHAN_NB_IoT[i], //over the logical channel id of the DRB (>=4)
             DRB_configList2->list.array[i]->logicalChannelConfig_r13
-			);
+			);*/
 
         } else { //ue_context_pP->ue_context.DRB_active[drb_id] == 1 (means that DRB has been modified)
 
@@ -782,37 +824,41 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
         	 */
 
         	if (DRB_configList2->list.array[i]->logicalChannelIdentity_r13) {
-        	     DRB2LCHAN_NB[i] = (uint8_t) * DRB_configList2->list.array[i]->logicalChannelIdentity_r13; //set in RRCConnectionReconfiguration (x+3)
+        	     DRB2LCHAN_NB_IoT[i] = (uint8_t) * DRB_configList2->list.array[i]->logicalChannelIdentity_r13; //set in RRCConnectionReconfiguration (x+3)
         	    }
 
           LOG_D(RRC,
                 PROTOCOL_RRC_CTXT_UE_FMT" RRC_eNB --- MAC_CONFIG_REQ  (DRB) ---> MAC_eNB\n",
                 PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
 
-          NB_rrc_mac_config_req_eNB(
+          //MP: The only change w.r.t previous case is that we not put logicalChannelConfig
+
+          /*rrc_mac_config_req_eNB_NB_IoT(
                       ctxt_pP->module_id,
                       ue_context_pP->ue_context.primaryCC_id,
                       ue_context_pP->ue_context.rnti,
                       0,//physCellId --> this parameters could be set to 0 since no MIB is present
 					  0,// p_eNB
+					  0,//p_rx_eNB
 					  0, //Ncp
+					  0, //Ncp_UL
 					  0, //eutra_band
 					  (struct NS_PmaxList_NB_r13*) NULL,
 					  (struct MultiBandInfoList_NB_r13*) NULL,
 					  (struct DL_Bitmap_NB_r13*) NULL,
 					  (long*)NULL,//eutraControlRegionSize
 					  (long*)NULL, //nrs_CRS_PowerOffset
-					  (uint8_t*)NULL,
-					  (uint16_t*)NULL,
+//					  (uint8_t*)NULL,
+//					  (uint16_t*)NULL,
 					  0, //dl_CarrierFreq
 					  0, //ul_CarrierFreq
 					  (BCCH_BCH_Message_NB_t*)NULL,
 					  (RadioResourceConfigCommonSIB_NB_r13_t*)NULL,
-                      ue_context_pP->ue_context.physicalConfigDedicated_NB,
-                      ue_context_pP->ue_context.mac_MainConfig_NB,
-                      DRB2LCHAN_NB[i], //over the logical channel id of the DRB (>=4)
-                      (LogicalChannelConfig_NB_r13_t*)NULL //XXX MP: is the only change w.r.t previous case
-          			);
+                      ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT,
+                      ue_context_pP->ue_context.mac_MainConfig_NB_IoT,
+                      DRB2LCHAN_NB_IoT[i], //over the logical channel id of the DRB (>=4)
+                      (LogicalChannelConfig_NB_r13_t*)NULL
+          			);*/
         }
       }
     }
@@ -822,9 +868,9 @@ rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
 //-----------------------------------------------------------------------------
 void //was under ITTI
 // This function triggers the establishment of dedicated bearer in the absence of EPC (oaisim case -- noS1)
-// to emulate it only establish 2 bearers (max number for NB-IoT
-rrc_eNB_reconfigure_DRBs_NB(const protocol_ctxt_t* const ctxt_pP,
-			       rrc_eNB_ue_context_NB_t*  ue_context_pP)
+// to emulate it only establish 2 bearers (max number for NB-IoT)
+rrc_eNB_reconfigure_DRBs_NB_IoT(const protocol_ctxt_t* const ctxt_pP,
+			       rrc_eNB_ue_context_NB_IoT_t*  ue_context_pP)
 //------------------------------------------------------------------
 {
 
@@ -834,8 +880,8 @@ rrc_eNB_reconfigure_DRBs_NB(const protocol_ctxt_t* const ctxt_pP,
 
   for (i = 0; i < NB_RB_MAX_NB_IOT-3; i++) { //most 2 DRB for NB-IoT = at most 2 e-rab (DRB)
 
-    if ( ue_context_pP->ue_context.e_rab[i].status < E_RAB_NB_STATUS_DONE){ // all those new e-rab ( E_RAB_NB_STATUS_NEW)
-      ue_context_pP->ue_context.e_rab[i].status = E_RAB_NB_STATUS_NEW;
+    if ( ue_context_pP->ue_context.e_rab[i].status < E_RAB_STATUS_DONE_NB_IoT){ // all those new e-rab ( E_RAB_STATUS_NEW_NB_IoT)
+      ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_NEW_NB_IoT;
       ue_context_pP->ue_context.e_rab[i].param.e_rab_id = i + 1;
       ue_context_pP->ue_context.e_rab[i].param.qos.qci = i % 9;
       ue_context_pP->ue_context.e_rab[i].param.qos.allocation_retention_priority.priority_level= i % PRIORITY_LEVEL_LOWEST;
@@ -856,16 +902,16 @@ rrc_eNB_reconfigure_DRBs_NB(const protocol_ctxt_t* const ctxt_pP,
   ue_context_pP->ue_context.setup_e_rabs+=e_rab_done;
 
   //MP: in the case of EPC this function is called directly by S1AP (see rrc_eNB_S1AP.c)
-  rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(ctxt_pP, ue_context_pP ); //XXX MP: no ho state
+  rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB_IoT(ctxt_pP, ue_context_pP ); //XXX MP: no ho state
 }
 //-----------------------------------------------------------------------------
-uint8_t qci_to_priority[9]={2,4,3,5,1,6,7,8,9}; //FIXME understand if used in NB_IoT (no GBR so only 5-9)
+//uint8_t qci_to_priority[9]={2,4,3,5,1,6,7,8,9};
 
 //-----------------------------------------------------------------------------
 void //was under ITTI
-rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
+rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB_IoT(
 		const protocol_ctxt_t* const ctxt_pP,
-	    rrc_eNB_ue_context_NB_t*          const ue_context_pP
+	    rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
         //no ho state
 	     )
 //-----------------------------------------------------------------------------
@@ -886,7 +932,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
   DRB_ToAddModList_NB_r13_t*                DRB_configList=ue_context_pP->ue_context.DRB_configList;
   DRB_ToAddModList_NB_r13_t**               DRB_configList2=NULL;
 
-  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13 *dedicatedInfoNASList_NB = NULL;
+  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13 *dedicatedInfoNASList_NB_IoT = NULL;
   DedicatedInfoNAS_t                 *dedicatedInfoNas                 = NULL;
   /* for no gcc warnings */
   (void)dedicatedInfoNas;
@@ -895,7 +941,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
   int e_rab_done=0;
 
 
-  uint8_t xid = rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id);   //Transaction_id,
+  uint8_t xid = rrc_eNB_get_next_transaction_identifier_NB_IoT(ctxt_pP->module_id);   //Transaction_id,
 
   DRB_configList2=&ue_context_pP->ue_context.DRB_configList2[xid];
   if (*DRB_configList2) {
@@ -905,7 +951,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
   *DRB_configList2 = CALLOC(1, sizeof(**DRB_configList2));
 
   /* Initialize NAS list */
-  dedicatedInfoNASList_NB = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13));
+  dedicatedInfoNASList_NB_IoT = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13));
 
   //MP:add a check on number of setup e_rabs
   if(ue_context_pP->ue_context.setup_e_rabs > 2){
@@ -916,7 +962,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
   for ( i = 0  ; i < ue_context_pP->ue_context.setup_e_rabs ; i++){ //max must be 2 DRBs that are established
 
     // bypass the new and already configured erabs
-    if (ue_context_pP->ue_context.e_rab[i].status >= E_RAB_NB_STATUS_DONE) {
+    if (ue_context_pP->ue_context.e_rab[i].status >= E_RAB_STATUS_DONE_NB_IoT) {
       drb_identity_index++;
       continue; //skip to the next loop iteration
     }
@@ -943,7 +989,8 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
 
 
     /*XXX MP:old implementation foresee a switch case on e_context_pP->ue_context.e_rab[i].param.qos.qci (TS 36.413 and TS 23.401)
-     * but in reality since in NB-IoT only RLC-AM mode is allowed we can directly set DRBs whatever the qci
+     * but in reality since in NB-IoT only RLC-AM mode is allowed we can directly configure the DRBs whatever the qci
+     * furthermore, the priority of the SRB is set fix to 1
      */
 
     // RLC conf
@@ -951,13 +998,13 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
     DRB_rlc_config->present = RLC_Config_NB_r13_PR_am;
     DRB_rlc_config->choice.am.ul_AM_RLC_r13.t_PollRetransmit_r13 = T_PollRetransmit_NB_r13_ms250; //random
     DRB_rlc_config->choice.am.ul_AM_RLC_r13.maxRetxThreshold_r13 = UL_AM_RLC_NB_r13__maxRetxThreshold_r13_t8;
-    DRB_rlc_config->choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = CALLOC(1,sizeof(long));
+    DRB_rlc_config->choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13 = CALLOC(1,sizeof(long)); /* OPTIONAL */
     *(DRB_rlc_config->choice.am.dl_AM_RLC_r13.enableStatusReportSN_Gap_r13)= DL_AM_RLC_NB_r13__enableStatusReportSN_Gap_r13_true;
 
-    //FIXME MP: TS 36.323 v14.2.0 PDCP status report operation is not applicable for NB-IoT
+    //XXX MP: TS 36.323 v14.2.0 ch5.3.2 PDCP status report operation is not applicable for NB-IoT
     //(in any case they set to FALSE in the LTE DRBs setup in OAI)
 
-    //MP: not used header compression PDCP in OAI
+    //MP: not used header compression PDCP fr DRBs in OAI
     DRB_pdcp_config->headerCompression_r13.present = PDCP_Config_NB_r13__headerCompression_r13_PR_notUsed;
 
     DRB_lchan_config = CALLOC(1, sizeof(*DRB_lchan_config));
@@ -967,7 +1014,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
     *(DRB_lchan_config->priority_r13) = 1L;
 
 
-    //DRB_lchan_config->logicalChannelSR_Prohibit_r13 = NULL; /*OPTIONAL*/ --> FIXME not needed to set it now?
+    DRB_lchan_config->logicalChannelSR_Prohibit_r13 = NULL; /*OPTIONAL*/
 
     //no prioritized bitrate
     //no bucketsize duration
@@ -985,7 +1032,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
 	  );
 
     e_rab_done++;
-    ue_context_pP->ue_context.e_rab[i].status = E_RAB_NB_STATUS_DONE;
+    ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE_NB_IoT;
     ue_context_pP->ue_context.e_rab[i].xid = xid;
 
     {
@@ -995,7 +1042,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
 	OCTET_STRING_fromBuf(dedicatedInfoNas,
 			     (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer,
 			     ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length);
-	ASN_SEQUENCE_ADD(&dedicatedInfoNASList_NB->list, dedicatedInfoNas);
+	ASN_SEQUENCE_ADD(&dedicatedInfoNASList_NB_IoT->list, dedicatedInfoNas);
 	LOG_I(RRC,"add NAS info with size %d (rab id %d)\n",ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length, i);
       }
       else {
@@ -1012,10 +1059,10 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
   }
 
   /* If list is empty free the list and reset the address */
-  if (dedicatedInfoNASList_NB != NULL) {
-    if (dedicatedInfoNASList_NB->list.count == 0) {
-      free(dedicatedInfoNASList_NB);
-      dedicatedInfoNASList_NB = NULL;
+  if (dedicatedInfoNASList_NB_IoT != NULL) {
+    if (dedicatedInfoNASList_NB_IoT->list.count == 0) {
+      free(dedicatedInfoNASList_NB_IoT);
+      dedicatedInfoNASList_NB_IoT = NULL;
       LOG_W(RRC,"dedicated NAS list is empty, free the list and reset the address\n");
     }
   } else {
@@ -1024,15 +1071,15 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
 
   memset(buffer, 0, RRC_BUF_SIZE);
 
-   size = do_RRCConnectionReconfiguration_NB(ctxt_pP,
-					  buffer,
-					  xid,
-					  (SRB_ToAddModList_NB_r13_t*)NULL,
-					  (DRB_ToAddModList_NB_r13_t*)*DRB_configList2,
-					  (DRB_ToReleaseList_NB_r13_t*)NULL,  // DRB2_list,
-					  NULL, NULL, //physical an MAC config dedicated
-					  (struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13*)dedicatedInfoNASList_NB
-                                        );
+   size = do_RRCConnectionReconfiguration_NB_IoT(ctxt_pP,
+					                                       buffer,
+					                                       xid,
+					                                       (SRB_ToAddModList_NB_r13_t*)NULL,
+					                                       (DRB_ToAddModList_NB_r13_t*)*DRB_configList2,
+					                                       (DRB_ToReleaseList_NB_r13_t*)NULL,  // DRB2_list,
+					                                       NULL, NULL, //physical an MAC config dedicated
+					                                       (struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13*)dedicatedInfoNASList_NB_IoT
+                                                );
 
 
 #ifdef RRC_MSG_PRINT
@@ -1062,7 +1109,7 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
 
   LOG_D(RRC,
         "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n",
-        ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH1); //through SRB1
+        ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB_IoT, ctxt_pP->module_id, DCCH1_NB_IoT); //through SRB1
 
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
@@ -1072,14 +1119,14 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
     MSC_AS_TIME_FMT" dedicated rrcConnectionReconfiguration-NB UE %x MUI %d size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP->ue_context.rnti,
-    rrc_eNB_mui,
+    rrc_eNB_mui_NB_IoT,
     size);
 
   //transmit the RRCConnectionReconfiguration-NB
-  NB_rrc_data_req(
+  rrc_data_req_NB_IoT(
     ctxt_pP,
-    DCCH1,//through SRB1
-    rrc_eNB_mui++,
+    DCCH1_NB_IoT,//through SRB1
+    rrc_eNB_mui_NB_IoT++,
     SDU_CONFIRM_NO,
     size,
     buffer,
@@ -1088,10 +1135,9 @@ rrc_eNB_generate_dedicatedRRCConnectionReconfiguration_NB(
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_process_RRCConnectionSetupComplete_NB(
+void rrc_eNB_process_RRCConnectionSetupComplete_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*         ue_context_pP,
+  rrc_eNB_ue_context_NB_IoT_t*         ue_context_pP,
   RRCConnectionSetupComplete_NB_r13_IEs_t * rrcConnectionSetupComplete_NB
 )
 //-----------------------------------------------------------------------------
@@ -1109,26 +1155,25 @@ rrc_eNB_process_RRCConnectionSetupComplete_NB(
 #if defined(ENABLE_USE_MME)
 
   if (EPC_MODE_ENABLED == 1) {
-    // Forward message to S1AP layer
-    rrc_eNB_send_S1AP_NAS_FIRST_REQ(
+    // Forward message to S1AP layer we don't have S1 AP functions for the moment
+    /*rrc_eNB_send_S1AP_NAS_FIRST_REQ(
       ctxt_pP,
       ue_context_pP,
-      rrcConnectionSetupComplete_NB); ///TODO: look at NAS messages
+      rrcConnectionSetupComplete_NB);*/
   } else
 #endif
   {
     // RRC loop back (no S1AP), send SecurityModeCommand to UE
-    rrc_eNB_generate_SecurityModeCommand_NB(
+    rrc_eNB_generate_SecurityModeCommand_NB_IoT(
       ctxt_pP,
       ue_context_pP);
   }
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_generate_SecurityModeCommand_NB(
+void rrc_eNB_generate_SecurityModeCommand_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
 )
 //-----------------------------------------------------------------------------
 {
@@ -1144,10 +1189,10 @@ rrc_eNB_generate_SecurityModeCommand_NB(
   T(T_ENB_RRC_SECURITY_MODE_COMMAND, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
-  size = do_SecurityModeCommand_NB(
+  size = do_SecurityModeCommand_NB_IoT(
            ctxt_pP,
            buffer,
-           rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id),
+           rrc_eNB_get_next_transaction_identifier_NB_IoT(ctxt_pP->module_id),
            ue_context_pP->ue_context.ciphering_algorithm,
            ue_context_pP->ue_context.integrity_algorithm);
 
@@ -1171,8 +1216,8 @@ rrc_eNB_generate_SecurityModeCommand_NB(
         PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (securityModeCommand to UE MUI %d) --->[PDCP][RB %02d]\n",
         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
         size,
-        rrc_eNB_mui,
-        DCCH0); //MP: SRB1bis
+        rrc_eNB_mui_NB_IoT,
+        DCCH0_NB_IoT); //MP: SRB1bis
 
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
@@ -1182,13 +1227,13 @@ rrc_eNB_generate_SecurityModeCommand_NB(
     MSC_AS_TIME_FMT" securityModeCommand UE %x MUI %d size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP->ue_context.rnti,
-    rrc_eNB_mui,
+    rrc_eNB_mui_NB_IoT,
     size);
 
-  NB_rrc_data_req( //to PDCP
+  rrc_data_req_NB_IoT( //to PDCP
 	       ctxt_pP,
-	       DCCH0,//MP:through SRB1bis
-	       rrc_eNB_mui++,
+	       DCCH0_NB_IoT,//MP:through SRB1bis
+	       rrc_eNB_mui_NB_IoT++,
 	       SDU_CONFIRM_NO,
 	       size,
 	       buffer,
@@ -1197,14 +1242,13 @@ rrc_eNB_generate_SecurityModeCommand_NB(
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_generate_UECapabilityEnquiry_NB(
+void rrc_eNB_generate_UECapabilityEnquiry_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
-  rrc_eNB_ue_context_NB_t*          const ue_context_pP
+  rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
 )
 //-----------------------------------------------------------------------------
 {
-//XXX: Clarify: this message is also called when we receive SecurityModeFailure--> we agree that in any case we start using SRB1
+//MP: this message is also transmitted when we receive SecurityModeFailure--> in any case we start using SRB1
 
   uint8_t                             buffer[100];
   uint8_t                             size;
@@ -1212,10 +1256,10 @@ rrc_eNB_generate_UECapabilityEnquiry_NB(
   T(T_ENB_RRC_UE_CAPABILITY_ENQUIRY, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
-  size = do_UECapabilityEnquiry_NB(
+  size = do_UECapabilityEnquiry_NB_IoT(
            ctxt_pP,
            buffer,
-           rrc_eNB_get_next_transaction_identifier(ctxt_pP->module_id));
+           rrc_eNB_get_next_transaction_identifier_NB_IoT(ctxt_pP->module_id));
 
   LOG_I(RRC,
         PROTOCOL_RRC_CTXT_UE_FMT" Logical Channel DL-DCCH, Generate UECapabilityEnquiry-NB (bytes %d)\n",
@@ -1226,8 +1270,8 @@ rrc_eNB_generate_UECapabilityEnquiry_NB(
         PROTOCOL_RRC_CTXT_UE_FMT" --- PDCP_DATA_REQ/%d Bytes (UECapabilityEnquiry-NB MUI %d) --->[PDCP][RB %02d]\n",
         PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
         size,
-        rrc_eNB_mui,
-        DCCH0);//through SRB1bis
+        rrc_eNB_mui_NB_IoT,
+        DCCH0_NB_IoT);//through SRB1bis
 
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
@@ -1237,26 +1281,25 @@ rrc_eNB_generate_UECapabilityEnquiry_NB(
     MSC_AS_TIME_FMT" rrcUECapabilityEnquiry UE %x MUI %d size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP->ue_context.rnti,
-    rrc_eNB_mui,
+    rrc_eNB_mui_NB_IoT,
     size);
 
-  NB_rrc_data_req( //to PDCP
+  rrc_data_req_NB_IoT( //to PDCP
 	       ctxt_pP,
-	       DCCH1, //XXX we send it over SRB1
-	       rrc_eNB_mui++,
+	       DCCH1_NB_IoT, //MP: send over SRB1
+	       rrc_eNB_mui_NB_IoT++,
 	       SDU_CONFIRM_NO,
 	       size,
 	       buffer,
-	       PDCP_TRANSMISSION_MODE_CONTROL);//XXX MP: no more transparent to PDCP // SRB1 was registered to the pdcp at the beginning
+	       PDCP_TRANSMISSION_MODE_CONTROL);//MP: no more transparent to PDCP -->SRB1 was registered to the pdcp at the beginning
 
 }
 
 //-----------------------------------------------------------------------------
-void
-rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* const ctxt_pP,
-						     rrc_eNB_ue_context_NB_t*          const ue_context_pP
-						//no HO flag
-						     )
+void rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB_IoT(const protocol_ctxt_t* const ctxt_pP,
+						                                                     rrc_eNB_ue_context_NB_IoT_t*          const ue_context_pP
+						                                                     //no HO flag
+						                                                    )
 //-----------------------------------------------------------------------------
 {
   uint8_t                             buffer[RRC_BUF_SIZE];
@@ -1264,40 +1307,39 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
   int                                 i;
 
   // configure SRB1, PhysicalConfigDedicated, MAC_MainConfig for UE
+  //eNB_RRC_INST_NB_IoT*                       rrc_inst = &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id];
 
-  eNB_RRC_INST_NB*                       rrc_inst = &eNB_rrc_inst_NB[ctxt_pP->module_id];
-  struct PhysicalConfigDedicated_NB_r13**    physicalConfigDedicated_NB = &ue_context_pP->ue_context.physicalConfigDedicated_NB;
+  struct PhysicalConfigDedicated_NB_r13**    physicalConfigDedicated_NB_IoT = &ue_context_pP->ue_context.physicalConfigDedicated_NB_IoT;
 
-  struct SRB_ToAddMod_NB_r13                           *SRB1_config                      = NULL;
-  struct SRB_ToAddMod_NB_r13__rlc_Config_r13    	   *SRB1_rlc_config                  = NULL;
-  struct SRB_ToAddMod_NB_r13__logicalChannelConfig_r13 *SRB1_lchan_config          		 = NULL;
+  struct SRB_ToAddMod_NB_r13                             *SRB1_config                      = NULL;
+  struct SRB_ToAddMod_NB_r13__rlc_Config_r13    	       *SRB1_rlc_config                  = NULL;
+  struct SRB_ToAddMod_NB_r13__logicalChannelConfig_r13   *SRB1_lchan_config          		   = NULL;
 
-  SRB_ToAddModList_NB_r13_t                 *SRB_configList = ue_context_pP->ue_context.SRB_configList; //both SRB1 and SRB1bis
+  SRB_ToAddModList_NB_r13_t                 *SRB_configList                   = ue_context_pP->ue_context.SRB_configList; //both SRB1 and SRB1bis
   SRB_ToAddModList_NB_r13_t                 **SRB_configList2                 = NULL; //only SRB1
 
   struct DRB_ToAddMod_NB_r13                *DRB_config                       = NULL;
   struct RLC_Config_NB_r13                  *DRB_rlc_config                   = NULL;
   struct PDCP_Config_NB_r13                 *DRB_pdcp_config                  = NULL;
-  //only AM is supported by NB-IoT
   struct LogicalChannelConfig_NB_r13        *DRB_lchan_config                 = NULL;
 
-  DRB_ToAddModList_NB_r13_t**                DRB_configList = &ue_context_pP->ue_context.DRB_configList;
-  DRB_ToAddModList_NB_r13_t**                DRB_configList2 = NULL;
+  DRB_ToAddModList_NB_r13_t**                DRB_configList                   = &ue_context_pP->ue_context.DRB_configList;
+  DRB_ToAddModList_NB_r13_t**                DRB_configList2                  = NULL;
 
-   MAC_MainConfig_NB_r13_t                   *mac_MainConfig_NB               = NULL;
+   MAC_MainConfig_NB_r13_t                   *mac_MainConfig_NB_IoT           = NULL;
 
-  long                              *periodicBSR_Timer;
-  long								*enableStatusReportSN_Gap = NULL; //should be disabled
-  long								*priority= NULL; //1 for SRB1 and 1 for SRB1bis
-  BOOLEAN_t						    *logicalChannelSR_Prohibit = NULL;
-  RSRP_Range_t                       *rsrp                             = NULL; //may not used
+  long                *periodicBSR_Timer;
+  long								*enableStatusReportSN_Gap  = NULL; //should be disabled
+  long								*priority                  = NULL; //1 for SRB1 and 1 for SRB1bis
+  BOOLEAN_t						*logicalChannelSR_Prohibit = NULL;
+  //RSRP_Range_t                       *rsrp                             = NULL; //may not used
 
-  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13 *dedicatedInfoNASList_NB = NULL;
-  DedicatedInfoNAS_t                 									   *dedicatedInfoNas        = NULL;
+  struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13    *dedicatedInfoNASList_NB_IoT = NULL;
+  DedicatedInfoNAS_t                 									                        *dedicatedInfoNas            = NULL;
   /* for no gcc warnings */
   (void)dedicatedInfoNas;
 
-  uint8_t xid = rrc_eNB_get_next_transaction_identifier_NB(ctxt_pP->module_id);   //Transaction_id,
+  uint8_t xid = rrc_eNB_get_next_transaction_identifier_NB_IoT(ctxt_pP->module_id);   //Transaction_id,
 
   T(T_ENB_RRC_CONNECTION_RECONFIGURATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
@@ -1332,11 +1374,12 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
   SRB1_lchan_config->choice.explicitValue.priority_r13 =priority;
 
   logicalChannelSR_Prohibit = CALLOC(1, sizeof(BOOLEAN_t));
-  *logicalChannelSR_Prohibit = 1;
-  SRB1_lchan_config->choice.explicitValue.logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit;
+  *logicalChannelSR_Prohibit = 1; // is the timer for BSR
+  SRB1_lchan_config->choice.explicitValue.logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit; /* OPTIONAL */
 
   // this list has the configuration for SRB1 and SRB1bis
   //XXX: Problems ? because SRB_ToAddModList_NB_r13_t max size = 1
+  // should before flush the list??? or directly overwrite
   ASN_SEQUENCE_ADD(&SRB_configList->list, SRB1_config);
 
   // this list has only the configuration for SRB1
@@ -1399,52 +1442,52 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
 
   DRB_lchan_config->priority_r13 = CALLOC(1, sizeof(long));
   *(DRB_lchan_config->priority_r13) = 12; // lower priority than srb1, srb1bis and other dedicated bearer
-  DRB_lchan_config->logicalChannelSR_Prohibit_r13 = logicalChannelSR_Prohibit;//FIXME: for DRB should be used?
+  DRB_lchan_config->logicalChannelSR_Prohibit_r13 = NULL;// is the timer for BSR /* OPTIONAL */
 
   //Add the DRB in both list
   ASN_SEQUENCE_ADD(&(*DRB_configList)->list, DRB_config);
   ASN_SEQUENCE_ADD(&(*DRB_configList2)->list, DRB_config);
 
 
-  ///Mac_MainConfig
-  mac_MainConfig_NB = CALLOC(1, sizeof(*mac_MainConfig_NB));
-  ue_context_pP->ue_context.mac_MainConfig_NB = mac_MainConfig_NB;
+  ///Mac_MainConfig (default as defined in TS 36.331 ch 9.2.2)
+  mac_MainConfig_NB_IoT = CALLOC(1, sizeof(*mac_MainConfig_NB_IoT));
+  ue_context_pP->ue_context.mac_MainConfig_NB_IoT = mac_MainConfig_NB_IoT;
 
-  mac_MainConfig_NB->ul_SCH_Config_r13 = CALLOC(1, sizeof(*mac_MainConfig_NB->ul_SCH_Config_r13));
+  mac_MainConfig_NB_IoT->ul_SCH_Config_r13 = CALLOC(1, sizeof(*mac_MainConfig_NB_IoT->ul_SCH_Config_r13));
 
   //no maxARQtx
 
-  periodicBSR_Timer = CALLOC(1, sizeof(long));
+  periodicBSR_Timer  = CALLOC(1, sizeof(long));
   *periodicBSR_Timer = PeriodicBSR_Timer_NB_r13_pp8;
-  mac_MainConfig_NB->ul_SCH_Config_r13->periodicBSR_Timer_r13 = periodicBSR_Timer;
-  mac_MainConfig_NB->ul_SCH_Config_r13->retxBSR_Timer_r13 = RetxBSR_Timer_NB_r13_infinity;
+  mac_MainConfig_NB_IoT->ul_SCH_Config_r13->periodicBSR_Timer_r13 = periodicBSR_Timer;
+  mac_MainConfig_NB_IoT->ul_SCH_Config_r13->retxBSR_Timer_r13 = RetxBSR_Timer_NB_r13_infinity;
 
-  mac_MainConfig_NB->timeAlignmentTimerDedicated_r13 = TimeAlignmentTimer_infinity;
+  mac_MainConfig_NB_IoT->timeAlignmentTimerDedicated_r13 = TimeAlignmentTimer_infinity;
 
-  mac_MainConfig_NB->drx_Config_r13 = NULL;
+  mac_MainConfig_NB_IoT->drx_Config_r13 = NULL;
 
   //no phr_config
 
-  mac_MainConfig_NB->logicalChannelSR_Config_r13 = CALLOC(1, sizeof(struct MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13));
-  mac_MainConfig_NB->logicalChannelSR_Config_r13->present = MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13_PR_setup;
+  mac_MainConfig_NB_IoT->logicalChannelSR_Config_r13 = CALLOC(1, sizeof(struct MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13));
+  mac_MainConfig_NB_IoT->logicalChannelSR_Config_r13->present = MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13_PR_setup;
   //depends if previously activated
-  mac_MainConfig_NB->logicalChannelSR_Config_r13->choice.setup.logicalChannelSR_ProhibitTimer_r13 =
+  mac_MainConfig_NB_IoT->logicalChannelSR_Config_r13->choice.setup.logicalChannelSR_ProhibitTimer_r13 =
 		  MAC_MainConfig_NB_r13__logicalChannelSR_Config_r13__setup__logicalChannelSR_ProhibitTimer_r13_pp2; //value in PP=PDCCH periods
 
 
-  struct PhysicalConfigDedicated ciao;
+  if (*physicalConfigDedicated_NB_IoT) {
 
-  if (*physicalConfigDedicated_NB) {
+	  //DL_CarrierConfigDedicated_NB_r13_t cio;
+	  //UL_CarrierConfigDedicated_NB_r13_t c;
 
 	  //TODO: which value should be configured of phisical config dedicated?
 	  //antennaInfo not present in PhysicalConfigDedicated for NB_IoT
       //cqi reporting is not present in PhysicalConfigDedicated for NB_IoT
-	  /*
-	   * carrierConfigDedicated_r13
-	   * npdcch_ConfigDedicated_r13
-	   * npusch_ConfigDedicated_r13
-	   * uplinkPowerControlDedicated_r13
-	   */
+
+	   //* carrierConfigDedicated_r13 /* OPTIONAL */
+	   //* npdcch_ConfigDedicated_r13 /* OPTIONAL */
+	   //* npusch_ConfigDedicated_r13 /* OPTIONAL */
+	   //* uplinkPowerControlDedicated_r13 /* OPTIONAL */
   }
   else {
     LOG_E(RRC,"physical_config_dedicated not present in RRCConnectionReconfiguration-NB. Not reconfiguring!\n");
@@ -1459,7 +1502,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
 //#if defined(ENABLE_ITTI).....
 
   /* Initialize NAS list */
-  dedicatedInfoNASList_NB = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13));
+  dedicatedInfoNASList_NB_IoT = CALLOC(1, sizeof(struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13));
 
   /* Add all NAS PDUs to the list */
   for (i = 0; i < ue_context_pP->ue_context.nb_of_e_rabs; i++) {
@@ -1469,7 +1512,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
       OCTET_STRING_fromBuf(dedicatedInfoNas,
 			   (char*)ue_context_pP->ue_context.e_rab[i].param.nas_pdu.buffer,
                            ue_context_pP->ue_context.e_rab[i].param.nas_pdu.length);
-      ASN_SEQUENCE_ADD(&dedicatedInfoNASList_NB->list, dedicatedInfoNas);
+      ASN_SEQUENCE_ADD(&dedicatedInfoNASList_NB_IoT->list, dedicatedInfoNas);
     }
 
     /*OLD  TODO parameters yet to process ... */
@@ -1480,30 +1523,30 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
     }
 
     /* TODO should test if e RAB are Ok before! */
-    ue_context_pP->ue_context.e_rab[i].status = E_RAB_NB_STATUS_DONE;
+    ue_context_pP->ue_context.e_rab[i].status = E_RAB_STATUS_DONE_NB_IoT;
     LOG_D(RRC, "setting the status for the default DRB (index %d) to (%d,%s)\n",
-	  i, ue_context_pP->ue_context.e_rab[i].status, "E_RAB_NB_STATUS_DONE");
+	  i, ue_context_pP->ue_context.e_rab[i].status, "E_RAB_STATUS_DONE_NB_IoT");
   }
 
   /* If list is empty free the list and reset the address */
-  if (dedicatedInfoNASList_NB->list.count == 0) {
-    free(dedicatedInfoNASList_NB);
-    dedicatedInfoNASList_NB = NULL;
+  if (dedicatedInfoNASList_NB_IoT->list.count == 0) {
+    free(dedicatedInfoNASList_NB_IoT);
+    dedicatedInfoNASList_NB_IoT = NULL;
   }
 
 
   memset(buffer, 0, RRC_BUF_SIZE);
 
-  size = do_RRCConnectionReconfiguration_NB(ctxt_pP,
-                                         buffer,
-                                         xid,   //Transaction_id,
-                                         (SRB_ToAddModList_NB_r13_t*)*SRB_configList2, //only SRB1
-                                         (DRB_ToAddModList_NB_r13_t*)*DRB_configList,
-                                         (DRB_ToReleaseList_NB_r13_t*)NULL,  // DRB2_list,
-                                         (struct PhysicalConfigDedicated_NB_r13*)*physicalConfigDedicated_NB,
-                                         (MAC_MainConfig_t*)mac_MainConfig_NB,
-                                         (struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13*)dedicatedInfoNASList_NB
-                                        );
+  size = do_RRCConnectionReconfiguration_NB_IoT(ctxt_pP,
+                                                buffer,
+                                                xid,   //Transaction_id,
+                                                (SRB_ToAddModList_NB_r13_t*)*SRB_configList2, //only SRB1
+                                                (DRB_ToAddModList_NB_r13_t*)*DRB_configList,
+                                                (DRB_ToReleaseList_NB_r13_t*)NULL,  // DRB2_list,
+                                                (struct PhysicalConfigDedicated_NB_r13*)*physicalConfigDedicated_NB_IoT,
+                                                (MAC_MainConfig_t*)mac_MainConfig_NB_IoT,
+                                                (struct RRCConnectionReconfiguration_NB_r13_IEs__dedicatedInfoNASList_r13*)dedicatedInfoNASList_NB_IoT
+                                                );
 
 #ifdef RRC_MSG_PRINT
   LOG_F(RRC,"[MSG] RRCConnectionReconfiguration-NB\n");
@@ -1531,7 +1574,7 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
 
   LOG_D(RRC,
         "[FRAME %05d][RRC_eNB][MOD %u][][--- PDCP_DATA_REQ/%d Bytes (rrcConnectionReconfiguration-NB to UE %x MUI %d) --->][PDCP][MOD %u][RB %u]\n",
-        ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui, ctxt_pP->module_id, DCCH1);//through SRB1
+        ctxt_pP->frame, ctxt_pP->module_id, size, ue_context_pP->ue_context.rnti, rrc_eNB_mui_NB_IoT, ctxt_pP->module_id, DCCH1_NB_IoT);//through SRB1
 
   MSC_LOG_TX_MESSAGE(
     MSC_RRC_ENB,
@@ -1541,13 +1584,13 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
     MSC_AS_TIME_FMT" rrcConnectionReconfiguration-NB UE %x MUI %d size %u",
     MSC_AS_TIME_ARGS(ctxt_pP),
     ue_context_pP->ue_context.rnti,
-    rrc_eNB_mui,
+    rrc_eNB_mui_NB_IoT,
     size);
 
-  NB_rrc_data_req( //to PDCP
+  rrc_data_req_NB_IoT( //to PDCP
 	       ctxt_pP,
-	       DCCH1,//through SRB1
-	       rrc_eNB_mui++,
+	       DCCH1_NB_IoT,//through SRB1
+	       rrc_eNB_mui_NB_IoT++,
 	       SDU_CONFIRM_NO,
 	       size,
 	       buffer,
@@ -1558,91 +1601,93 @@ rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(const protocol_ctxt_t* c
 /*-----------------CONFIGURATION-------------------*/
 
 //-----------------------------------------------------------------------------
-static void
-init_SI_NB(
+static void init_SI_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const int              CC_id,
-  RrcConfigurationReq* configuration
+  RrcConfigurationReq* configuration //openair2/COMMON/rrc_messages_types
 )
 //-----------------------------------------------------------------------------
-{
-
-	//FIXME: MP: may this two  parameters are not needed
-  uint8_t                             SIwindowsize = 1; //frame
-  uint16_t                            SIperiod = 8; // in frames
+{ 
+	/*WE should allocate memory for PHY_Config structure
+	 * is declared in vars_nb_iot.c and put also in the extern_nb_iot
+	 * */
+	config_INFO = malloc(sizeof(PHY_Config_t));
 
 
   //copy basic parameters
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].physCellId      = configuration->Nid_cell[CC_id];
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].p_eNB           = configuration->nb_antenna_ports[CC_id];
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Ncp             = configuration->prefix_type[CC_id];
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].dl_CarrierFreq  = configuration->downlink_frequency[CC_id];
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].ul_CarrierFreq  = configuration->downlink_frequency[CC_id]+ configuration->uplink_frequency_offset[CC_id];
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].physCellId      = configuration->Nid_cell[CC_id];
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].p_eNB           = configuration->nb_antenna_ports[CC_id];
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].p_rx_eNB		     = configuration->nb_antenna_ports_rx[CC_id];
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Ncp             = configuration->prefix_type[CC_id]; //DL Cyclic prefix
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].Ncp_UL			     = configuration->prefix_type_UL[CC_id];//UL cyclic prefix
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].dl_CarrierFreq  = configuration->downlink_frequency[CC_id];
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].ul_CarrierFreq  = configuration->downlink_frequency[CC_id]+ configuration->uplink_frequency_offset[CC_id];
 
 
-  //TODO: verify who allocate memory for sib1_NB, sib2_NB, sib3_NB and mib_nb in the carrier before being passed as parameter
+  //TODO: verify who allocate memory for sib1_NB_IoT, sib2_NB_IoT, sib3_NB and mib_nb in the carrier before being passed as parameter
 
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB = 0;
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB = 0;
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB = 0;
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB_IoT  = 0;
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB_IoT = 0;
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB_IoT   = 0;
 
   //MIB
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].MIB_NB = (uint8_t*) malloc16(32); //MIB is 34 bits=5bytes needed
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].MIB_NB_IoT = (uint8_t*) malloc16(32); //MIB is 34 bits=5bytes needed
+
 
-  //FIXME do_MIB_NB parameters
-  if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].MIB_NB)
+  if (eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].MIB_NB_IoT)
   {
-	  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB =
-	  			  do_MIB_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id],
-	  					  	configuration->N_RB_DL,
-					        0
+	  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB_IoT =
+	  			  do_MIB_NB_IoT(&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id],
+	  					  	configuration->N_RB_DL[CC_id],
+					        0 //FIXME is correct to pass frame = 0??
 					        );
   }
   else {
-      LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for MIB_NB allocated\n",
+      LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for MIB_NB_IoT allocated\n",
             PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
-      mac_xface->macphy_exit("[RRC][init_SI] FATAL, no memory for MIB_NB allocated");
+      //exit here
     }
 
 
-  if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB == 255) {
-      mac_xface->macphy_exit("[RRC][init_SI] FATAL, eNB_rrc_inst_NB[enb_mod_idP].carrier[CC_id].sizeof_MIB_NB == 255");
+  if (eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_MIB_NB_IoT == 255) {
+     // exit here
     }
 
- //SIB1_NB
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB1_NB = (uint8_t*) malloc16(32);//allocation of buffer memory for SIB1_NB
+ //SIB1_NB_IoT
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].SIB1_NB_IoT = (uint8_t*) malloc16(32);//allocation of buffer memory for SIB1_NB_IOT
 
-  if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB1_NB)
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB = do_SIB1_NB( //follow the new implementation
+  if (eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].SIB1_NB_IoT)
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB_IoT = do_SIB1_NB_IoT( //follow the new implementation
     				ctxt_pP->module_id,
 					CC_id,
-					&eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id],
-					configuration
+					&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id],
+					configuration,
+					0 //FIXME is correct to pass frame = 0??
     				);
 
   else {
-    LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for SIB1_NB allocated\n",
+    LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for SIB1_NB_IoT allocated\n",
           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
-    mac_xface->macphy_exit("[RRC][init_SI] FATAL, no memory for SIB1_NB allocated");
+    //exit here
   }
 
-  if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB == 255) {
-    mac_xface->macphy_exit("[RRC][init_SI] FATAL, eNB_rrc_inst_NB[enb_mod_idP].carrier[CC_id].sizeof_SIB1_NB == 255");
+  if (eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB1_NB_IoT == 255) {
+    //exit here
   }
 
-  //SIB23_NB
-  eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB23_NB = (uint8_t*) malloc16(64);
+  //SIB23_NB_IoT
+  eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].SIB23_NB_IoT = (uint8_t*) malloc16(64);
 
-  if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].SIB23_NB) {
-    eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB = do_SIB23_NB(
+  if (eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].SIB23_NB_IoT) {
+    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB_IoT = do_SIB23_NB_IoT(
           ctxt_pP->module_id,
           CC_id,
-		  &eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id],
+		  &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id],
 		  configuration
         );
 
-    if (eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB == 255) {
-      mac_xface->macphy_exit("[RRC][init_SI] FATAL, eNB_rrc_inst_NB[mod].carrier[CC_id].sizeof_SIB23_NB == 255");
+    if (eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sizeof_SIB23_NB_IoT == 255) {
+      //exit here
     }
 
     LOG_T(RRC, PROTOCOL_RRC_CTXT_FMT" SIB2/3 Contents (partial)\n",
@@ -1656,54 +1701,40 @@ init_SI_NB(
     //Use the following as an example
 //    LOG_T(RRC, PROTOCOL_RRC_CTXT_FMT" npusch_config_common.groupAssignmentNPUSCH = %ld\n",
 //          PROTOCOL_RRC_CTXT_ARGS(ctxt_pP),
-//          eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib2_NB->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.
+//          eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sib2_NB_IoT->radioResourceConfigCommon_r13.npusch_ConfigCommon_r13.
 //		  ul_ReferenceSignalsNPUSCH_r13.groupAssignmentNPUSCH_r13);
 
 
     //Configure MAC
     LOG_D(RRC,
-          PROTOCOL_RRC_CTXT_FMT" RRC_UE --- MAC_CONFIG_REQ (SIB1_NB & SIB2_NB params) ---> MAC_UE\n",
+          PROTOCOL_RRC_CTXT_FMT" RRC_UE --- MAC_CONFIG_REQ (SIB1_NB_IoT & SIB2_NB params) ---> MAC_UE\n",
           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
 
     //
-    NB_rrc_mac_config_req_eNB(ctxt_pP->module_id,
-    							CC_id,
-								0,//rnti
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].physCellId,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].p_eNB,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].Ncp,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->freqBandIndicator_r13,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->freqBandInfo_r13,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->multiBandInfoList_r13,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->downlinkBitmap_r13,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->eutraControlRegionSize_r13,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib1_NB->nrs_CRS_PowerOffset_r13,
-								&SIwindowsize,
-								&SIperiod,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].dl_CarrierFreq,
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].ul_CarrierFreq,
-								(BCCH_BCH_Message_NB_t*) &
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].mib_NB,
-								(RadioResourceConfigCommonSIB_NB_r13_t *) &
-								eNB_rrc_inst_NB[ctxt_pP->module_id].carrier[CC_id].sib2_NB->radioResourceConfigCommon_r13,
-								(struct PhysicalConfigDedicated_NB_r13_t *)NULL,
-								(MAC_MainConfig_NB_r13_t *) NULL,
-								0,// MP:logicalChannelID  //TODO still have to be properly managed in the interface
-								(struct LogicalChannelConfig_NB_r13_t *)NULL
-								);
+         rrc_mac_config_req_NB_IoT(ctxt_pP->module_id,
+                                  CC_id,
+                                  0,
+                                  &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id],
+                                  (SystemInformationBlockType1_NB_t*) &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sib1_NB_IoT,
+                                  (RadioResourceConfigCommonSIB_NB_r13_t *) &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].carrier[CC_id].sib2_NB_IoT->radioResourceConfigCommon_r13,
+                                  (struct PhysicalConfigDedicated_NB_r13 *)NULL,
+                                  (struct LogicalChannelConfig_NB_r13 *)NULL,
+                                  &mac_inst->rrc_config,
+                                  0,
+                                  0
+                                  );
   } else {
     LOG_E(RRC, PROTOCOL_RRC_CTXT_FMT" init_SI: FATAL, no memory for SIB2/3_NB allocated\n",
           PROTOCOL_RRC_CTXT_ARGS(ctxt_pP));
-    mac_xface->macphy_exit("[RRC][init_SI] FATAL, no memory for SIB2/3_NB allocated");
+    //exit here
   }
 }
 
 //-----------------------------------------------------------------------------
 //aka openair_rrc_eNB_init
-char
-openair_rrc_eNB_configuration_NB(
+char openair_rrc_eNB_configuration_NB_IoT(
   const module_id_t enb_mod_idP,
-  RrcConfigurationReq* configuration //FIXME MP: previously was insiede ITTI but actually I put it out
+  RrcConfigurationReq* configuration //MP: previously was insiede ITTI but actually I put it out
 )
 //-----------------------------------------------------------------------------
 {
@@ -1716,27 +1747,27 @@ openair_rrc_eNB_configuration_NB(
         PROTOCOL_RRC_CTXT_ARGS(&ctxt));
 
 #if OCP_FRAMEWORK
-while ( eNB_rrc_inst_NB == NULL ) {
-  LOG_E(RRC, "eNB_rrc_inst_NB not yet initialized, waiting 1 second\n");
+while ( eNB_rrc_inst_NB_IoT == NULL ) {
+  LOG_E(RRC, "eNB_rrc_inst_NB_IoT not yet initialized, waiting 1 second\n");
   sleep(1);
 }
 #endif
-  AssertFatal(eNB_rrc_inst_NB != NULL, "eNB_rrc_nb_iot_inst not initialized!");
-  AssertFatal(NUMBER_OF_UE_MAX < (module_id_t)0xFFFFFFFFFFFFFFFF, " variable overflow");
+  AssertFatal(eNB_rrc_inst_NB_IoT != NULL, "eNB_rrc_nb_iot_inst not initialized!");
+  AssertFatal(NUMBER_OF_UE_MAX_NB_IoT < (module_id_t)0xFFFFFFFFFFFFFFFF, " variable overflow");
 
-  eNB_rrc_inst_NB[ctxt.module_id].Nb_ue = 0;
+  eNB_rrc_inst_NB_IoT[ctxt.module_id].Nb_ue = 0;
 
   for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-    eNB_rrc_inst_NB[ctxt.module_id].carrier[CC_id].Srb0.Active = 0;
+    eNB_rrc_inst_NB_IoT[ctxt.module_id].carrier[CC_id].Srb0.Active = 0;
   }
 
-  uid_linear_allocator_init_NB(&eNB_rrc_inst_NB[ctxt.module_id].uid_allocator); //rrc_eNB_UE_context
-  RB_INIT(&eNB_rrc_inst_NB[ctxt.module_id].rrc_ue_head);
+  uid_linear_allocator_init_NB_IoT(&eNB_rrc_inst_NB_IoT[ctxt.module_id].uid_allocator); //rrc_eNB_UE_context
+  RB_INIT(&eNB_rrc_inst_NB_IoT[ctxt.module_id].rrc_ue_head);
 
-  eNB_rrc_inst_NB[ctxt.module_id].initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
-  eNB_rrc_inst_NB[ctxt.module_id].s1ap_id2_s1ap_ids    = hashtable_create (NUMBER_OF_UE_MAX * 2, NULL, NULL);
+  eNB_rrc_inst_NB_IoT[ctxt.module_id].initial_id2_s1ap_ids = hashtable_create (NUMBER_OF_UE_MAX_NB_IoT * 2, NULL, NULL);
+  eNB_rrc_inst_NB_IoT[ctxt.module_id].s1ap_id2_s1ap_ids    = hashtable_create (NUMBER_OF_UE_MAX_NB_IoT * 2, NULL, NULL);
 
-  memcpy(&eNB_rrc_inst_NB[ctxt.module_id].configuration,configuration,sizeof(RrcConfigurationReq));
+  memcpy(&eNB_rrc_inst_NB_IoT[ctxt.module_id].configuration,configuration,sizeof(RrcConfigurationReq));
 
   /// System Information INIT
 
@@ -1749,7 +1780,7 @@ while ( eNB_rrc_inst_NB == NULL ) {
 
   //init SI
   for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
-    init_SI_NB(&ctxt, CC_id,configuration);
+    init_SI_NB_IoT(&ctxt, CC_id,configuration);
   }
 
   /*New implementation Raymond*/
@@ -1757,15 +1788,11 @@ while ( eNB_rrc_inst_NB == NULL ) {
   //rrc_init_global_param_NB();
 
   //XXX following the old implementation: openair_rrc_top_init is called in MAC/main.c
-
-  //FIXME: this probably would create some bug for the following reaon:
-  //in the onld implementation this function was called in the MAC/main.c
-  //actually is called here --> we are allocating memory so maybe we generate some problems
-
-  //openair_rrc_top_init_eNB_NB();
+  //In Rymond version actually is called here
+  //openair_rrc_top_init_eNB_NB_IoT();
 
   //init ch SRB0, SRB1 & BDTCH
-  openair_eNB_rrc_on_NB(&ctxt);
+  openair_eNB_rrc_on_NB_IoT(&ctxt);
 
   return 0;
 
@@ -1775,22 +1802,20 @@ while ( eNB_rrc_inst_NB == NULL ) {
 /*-----------------STATE MACHINE---------------*/
 
 //-----------------------------------------------------------------------------
-int
-rrc_eNB_decode_ccch_NB(
+int rrc_eNB_decode_ccch_NB_IoT(
   protocol_ctxt_t* const ctxt_pP,
-  const SRB_INFO_NB*        const Srb_info, //SRB0
+  const SRB_INFO_NB_IoT*        const Srb_info, //SRB0
   const int              CC_id
 )
 //-----------------------------------------------------------------------------
 {
-  module_id_t                                   Idx;
   asn_dec_rval_t                      dec_rval;
-  UL_CCCH_Message_NB_t                  *ul_ccch_msg_NB = NULL;
-  RRCConnectionRequest_NB_r13_IEs_t                *rrcConnectionRequest_NB = NULL;
-  RRCConnectionReestablishmentRequest_NB_r13_IEs_t* rrcConnectionReestablishmentRequest_NB = NULL;
-  RRCConnectionResumeRequest_NB_r13_IEs_t *rrcConnectionResumeRequest_NB= NULL;
+  UL_CCCH_Message_NB_t                  *ul_ccch_msg_NB_IoT = NULL;
+  RRCConnectionRequest_NB_r13_IEs_t                *rrcConnectionRequest_NB_IoT = NULL;
+  RRCConnectionReestablishmentRequest_NB_r13_IEs_t* rrcConnectionReestablishmentRequest_NB_IoT = NULL;
+  RRCConnectionResumeRequest_NB_r13_IEs_t *rrcConnectionResumeRequest_NB_IoT= NULL;
   int                                 i, rval;
-  struct rrc_eNB_ue_context_NB_s*                  ue_context_p = NULL;
+  struct rrc_eNB_ue_context_NB_IoT_s*                  ue_context_p = NULL;
   uint64_t                                      random_value = 0;
   int                                           stmsi_received = 0;
 
@@ -1811,7 +1836,7 @@ rrc_eNB_decode_ccch_NB(
   dec_rval = uper_decode(
                NULL,
                &asn_DEF_UL_CCCH_Message_NB,
-               (void**)&ul_ccch_msg_NB,
+               (void**)&ul_ccch_msg_NB_IoT,
                (uint8_t*) Srb_info->Rx_buffer.Payload,
                100,
                0,
@@ -1822,7 +1847,7 @@ rrc_eNB_decode_ccch_NB(
 
 
   for (i = 0; i < 8; i++) { //MP: FIXME why 8?
-    LOG_T(RRC, "%x.", ((uint8_t *) & ul_ccch_msg_NB)[i]);
+    LOG_T(RRC, "%x.", ((uint8_t *) & ul_ccch_msg_NB_IoT)[i]);
   }
 
   if (dec_rval.consumed == 0) {
@@ -1832,9 +1857,9 @@ rrc_eNB_decode_ccch_NB(
     return -1;
   }
 
-  if (ul_ccch_msg_NB->message.present == UL_CCCH_MessageType_NB_PR_c1) {
+  if (ul_ccch_msg_NB_IoT->message.present == UL_CCCH_MessageType_NB_PR_c1) {
 
-    switch (ul_ccch_msg_NB->message.choice.c1.present) {
+    switch (ul_ccch_msg_NB_IoT->message.choice.c1.present) {
 
     case UL_CCCH_MessageType_NB__c1_PR_NOTHING:
       LOG_I(RRC,
@@ -1858,18 +1883,18 @@ rrc_eNB_decode_ccch_NB(
       LOG_D(RRC,
             PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB--- MAC_DATA_IND (rrcConnectionReestablishmentRequest-NB on SRB0) --> RRC_eNB\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
-      rrcConnectionReestablishmentRequest_NB =
-        &ul_ccch_msg_NB->message.choice.c1.choice.rrcConnectionReestablishmentRequest_r13.criticalExtensions.choice.rrcConnectionReestablishmentRequest_r13;
+      rrcConnectionReestablishmentRequest_NB_IoT =
+        &ul_ccch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionReestablishmentRequest_r13.criticalExtensions.choice.rrcConnectionReestablishmentRequest_r13;
 
       //for NB-IoT only "reconfiguration Failure" and "other failure" are allowed as reestablishment cause
       LOG_I(RRC,
             PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionReestablishmentRequest-NB cause %s\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            ((rrcConnectionReestablishmentRequest_NB->reestablishmentCause_r13 == ReestablishmentCause_NB_r13_otherFailure) ? "Other Failure" :
+            ((rrcConnectionReestablishmentRequest_NB_IoT->reestablishmentCause_r13 == ReestablishmentCause_NB_r13_otherFailure) ? "Other Failure" :
              "reconfigurationFailure"));
 
 
-     //FIXME:connection reestablishment to be implemented
+     //TODO:connection reestablishment to be implemented
       /*{
       uint64_t                            c_rnti = 0;
 
@@ -1878,7 +1903,7 @@ rrc_eNB_decode_ccch_NB(
       ue_mod_id = rrc_eNB_get_UE_index(enb_mod_idP, c_rnti);
       }
 
-      if ((eNB_rrc_inst_NB[enb_mod_idP].phyCellId == rrcConnectionReestablishmentRequest.UE_identity.physCellId) &&
+      if ((eNB_rrc_inst_NB_IoT[enb_mod_idP].phyCellId == rrcConnectionReestablishmentRequest.UE_identity.physCellId) &&
       (ue_mod_id != UE_INDEX_INVALID)){
       rrc_eNB_generate_RRCConnectionReestablishment(enb_mod_idP, frameP, ue_mod_id);
       }else {
@@ -1887,9 +1912,9 @@ rrc_eNB_decode_ccch_NB(
       */
       /* reject all reestablishment attempts for the moment */
 
-      //for the moment we only reject
-      rrc_eNB_generate_RRCConnectionReestablishmentReject_NB(ctxt_pP,
-                       rrc_eNB_get_ue_context_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti),
+      //MP:for the moment we only reject
+      rrc_eNB_generate_RRCConnectionReestablishmentReject_NB_IoT(ctxt_pP,
+                       rrc_eNB_get_ue_context_NB_IoT(&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id], ctxt_pP->rnti),
                        CC_id);
 
       break;
@@ -1911,13 +1936,13 @@ rrc_eNB_decode_ccch_NB(
             PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB --- MAC_DATA_IND  (rrcConnectionRequest-NB on SRB0) --> RRC_eNB\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
 
-      ue_context_p = rrc_eNB_get_ue_context_NB( //XXX define new function in rrc_eNB_UE_context
-                       &eNB_rrc_inst_NB[ctxt_pP->module_id],
+      ue_context_p = rrc_eNB_get_ue_context_NB_IoT( //XXX define new function in rrc_eNB_UE_context
+                       &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id],
                        ctxt_pP->rnti);
 
       if (ue_context_p != NULL) { //MP: i receive a ConnectionRequest from a UE which have already a context
         // erase content
-        rrc_eNB_free_mem_UE_context_NB(ctxt_pP, ue_context_p);
+        rrc_eNB_free_mem_UE_context_NB_IoT(ctxt_pP, ue_context_p);
 
         MSC_LOG_RX_DISCARDED_MESSAGE(
           MSC_RRC_ENB,
@@ -1930,61 +1955,61 @@ rrc_eNB_decode_ccch_NB(
           dec_rval.consumed);
       }
       else {
-        rrcConnectionRequest_NB = &ul_ccch_msg_NB->message.choice.c1.choice.rrcConnectionRequest_r13.criticalExtensions.choice.rrcConnectionRequest_r13;
+        rrcConnectionRequest_NB_IoT = &ul_ccch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionRequest_r13.criticalExtensions.choice.rrcConnectionRequest_r13;
         {
-          if (InitialUE_Identity_PR_randomValue == rrcConnectionRequest_NB->ue_Identity_r13.present) {
+          if (InitialUE_Identity_PR_randomValue == rrcConnectionRequest_NB_IoT->ue_Identity_r13.present) {
 
         	  //InitialUE-Identity randomValue size should be 40bits = 5 byte
-            AssertFatal(rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.size == 5,
+            AssertFatal(rrcConnectionRequest_NB_IoT->ue_Identity_r13.choice.randomValue.size == 5,
                         "wrong InitialUE-Identity randomValue size, expected 5, provided %d",
-                        rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.size);
+                        rrcConnectionRequest_NB_IoT->ue_Identity_r13.choice.randomValue.size);
 
             memcpy(((uint8_t*) & random_value) + 3,
-                   rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.buf,
-                   rrcConnectionRequest_NB->ue_Identity_r13.choice.randomValue.size);
+                   rrcConnectionRequest_NB_IoT->ue_Identity_r13.choice.randomValue.buf,
+                   rrcConnectionRequest_NB_IoT->ue_Identity_r13.choice.randomValue.size);
 
             /* if there is already a registered UE (with another RNTI) with this random_value,
              * the current one must be removed from MAC/PHY (zombie UE)
              */
-            if ((ue_context_p = rrc_eNB_ue_context_random_exist_NB(ctxt_pP, random_value))) {
+            if ((ue_context_p = rrc_eNB_ue_context_random_exist_NB_IoT(ctxt_pP, random_value))) {
               LOG_W(RRC, "new UE rnti %x (coming with random value) is already there as UE %x, removing %x from MAC/PHY\n",
                     ctxt_pP->rnti, ue_context_p->ue_context.rnti, ctxt_pP->rnti);
 
-	      NB_rrc_mac_remove_ue(ctxt_pP->module_id, ctxt_pP->rnti);
+	      //rrc_mac_remove_ue_NB_IoT(ctxt_pP->module_id, ctxt_pP->rnti);
               ue_context_p = NULL;
               return 0;
             } else {
-              ue_context_p = rrc_eNB_get_next_free_ue_context_NB(ctxt_pP, random_value);
+              ue_context_p = rrc_eNB_get_next_free_ue_context_NB_IoT(ctxt_pP, random_value);
             }
-          } else if (InitialUE_Identity_PR_s_TMSI == rrcConnectionRequest_NB->ue_Identity_r13.present) {
+          } else if (InitialUE_Identity_PR_s_TMSI == rrcConnectionRequest_NB_IoT->ue_Identity_r13.present) {
             /* Save s-TMSI */
-            S_TMSI_t   s_TMSI = rrcConnectionRequest_NB->ue_Identity_r13.choice.s_TMSI;
+            S_TMSI_t   s_TMSI = rrcConnectionRequest_NB_IoT->ue_Identity_r13.choice.s_TMSI;
             mme_code_t mme_code = BIT_STRING_to_uint8(&s_TMSI.mmec);
             m_tmsi_t   m_tmsi   = BIT_STRING_to_uint32(&s_TMSI.m_TMSI);
             random_value = (((uint64_t)mme_code) << 32) | m_tmsi;
 
             if ((ue_context_p = rrc_eNB_ue_context_stmsi_exist_NB(ctxt_pP, mme_code, m_tmsi))) {
 	      LOG_I(RRC," S-TMSI exists, ue_context_p %p, old rnti %x => %x\n",ue_context_p,ue_context_p->ue_context.rnti,ctxt_pP->rnti);
-	      NB_rrc_mac_remove_ue(ctxt_pP->module_id, ue_context_p->ue_context.rnti);
+	      //rrc_mac_remove_ue_NB_IoT(ctxt_pP->module_id, ue_context_p->ue_context.rnti);
 	      stmsi_received=1;
 
               /* replace rnti in the context */
               /* for that, remove the context from the RB tree */
 
-	      ///FIXME MP: warning --> implicit declaration because I insert the new type "rrc_ue_tree_NB_s"
-              RB_REMOVE(rrc_ue_tree_NB_s, &eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
+	      ///FIXME MP: warning --> implicit declaration because I insert the new type "rrc_ue_tree_NB_IoT_s"
+              RB_REMOVE(rrc_ue_tree_NB_IoT_s, &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
               /* and insert again, after changing rnti everywhere it has to be changed */
               ue_context_p->ue_id_rnti = ctxt_pP->rnti;
 	      ue_context_p->ue_context.rnti = ctxt_pP->rnti;
-              RB_INSERT(rrc_ue_tree_NB_s, &eNB_rrc_inst_NB[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
+              RB_INSERT(rrc_ue_tree_NB_IoT_s, &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].rrc_ue_head, ue_context_p);
               /* reset timers */
               ue_context_p->ue_context.ul_failure_timer = 0;
               ue_context_p->ue_context.ue_release_timer = 0;
             } else {
 	      LOG_I(RRC," S-TMSI doesn't exist, setting Initialue_identity_s_TMSI.m_tmsi to %p => %x\n",ue_context_p,m_tmsi);
-              ue_context_p = rrc_eNB_get_next_free_ue_context_NB(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY);
+              ue_context_p = rrc_eNB_get_next_free_ue_context_NB_IoT(ctxt_pP, NOT_A_RANDOM_UE_IDENTITY);
               if (ue_context_p == NULL)
-                LOG_E(RRC, "%s:%d:%s: rrc_eNB_get_next_free_ue_context returned NULL\n", __FILE__, __LINE__, __FUNCTION__);
+                LOG_E(RRC, "%s:%d:%s: rrc_eNB_get_next_free_ue_context_NB_IoT returned NULL\n", __FILE__, __LINE__, __FUNCTION__);
               if (ue_context_p != NULL) {
 	        ue_context_p->ue_context.Initialue_identity_s_TMSI.presence = TRUE;
 	        ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code = mme_code;
@@ -2012,8 +2037,8 @@ rrc_eNB_decode_ccch_NB(
                   PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionRequest-NB without random UE identity or S-TMSI not supported, let's reject the UE\n",
                   PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
 
-            rrc_eNB_generate_RRCConnectionReject_NB(ctxt_pP,
-                             rrc_eNB_get_ue_context_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti),
+            rrc_eNB_generate_RRCConnectionReject_NB_IoT(ctxt_pP,
+                             rrc_eNB_get_ue_context_NB_IoT(&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id], ctxt_pP->rnti),
                              CC_id);
             break;
           }
@@ -2028,21 +2053,21 @@ rrc_eNB_decode_ccch_NB(
 
 
 //#if defined(ENABLE_ITTI)
-          ue_context_p->ue_context.establishment_cause_NB = rrcConnectionRequest_NB->establishmentCause_r13;
+          ue_context_p->ue_context.establishment_cause_NB_IoT = rrcConnectionRequest_NB_IoT->establishmentCause_r13;
 	  if (stmsi_received==0){
 	    LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection from UE random UE identity (0x%" PRIx64 ") MME code %u TMSI %u cause %ld\n",
 		  PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
 		  ue_context_p->ue_context.random_ue_identity,
 		  ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code,
 		  ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
-		  ue_context_p->ue_context.establishment_cause_NB);
+		  ue_context_p->ue_context.establishment_cause_NB_IoT);
 	  }
 	  else{
 	    LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection from UE  MME code %u TMSI %u cause %ld\n",
 		  PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
 		  ue_context_p->ue_context.Initialue_identity_s_TMSI.mme_code,
 		  ue_context_p->ue_context.Initialue_identity_s_TMSI.m_tmsi,
-		  ue_context_p->ue_context.establishment_cause_NB);
+		  ue_context_p->ue_context.establishment_cause_NB_IoT);
 	  }
 //#else
 //          LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Accept new connection for UE random UE identity (0x%" PRIx64 ")\n",
@@ -2050,19 +2075,19 @@ rrc_eNB_decode_ccch_NB(
 //                ue_context_p->ue_context.random_ue_identity);
 //#endif
           if (stmsi_received == 0)
-	    eNB_rrc_inst_NB[ctxt_pP->module_id].Nb_ue++;
+	    eNB_rrc_inst_NB_IoT[ctxt_pP->module_id].Nb_ue++;
 
         } else {
           // no context available
           LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Can't create new context for UE random UE identity (0x%" PRIx64 ")\n",
                 PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
                 random_value);
-          NB_rrc_mac_remove_ue(ctxt_pP->module_id,ctxt_pP->rnti);
+          //rrc_mac_remove_ue_NB_IoT(ctxt_pP->module_id,ctxt_pP->rnti);
           return -1;
         }
       }
 
-//XXX MP: RRM not used
+//MP: RRM not used
 //#ifndef NO_RRM
 //      send_msg(&S_rrc, msg_rrc_MR_attach_ind(ctxt_pP->module_id, Mac_id));
 //#else
@@ -2071,14 +2096,14 @@ rrc_eNB_decode_ccch_NB(
 
       // SRB1bis (LCID = 3 = DCCH0)
       ue_context_p->ue_context.Srb1bis.Active = 1;
-      ue_context_p->ue_context.Srb1bis.Srb_info.Srb_id = DCCH0;
+      ue_context_p->ue_context.Srb1bis.Srb_info.Srb_id = DCCH0_NB_IoT;
 
       //generate RRCConnectionSetup-NB
-      rrc_eNB_generate_RRCConnectionSetup_NB(ctxt_pP, ue_context_p, CC_id);
+      rrc_eNB_generate_RRCConnectionSetup_NB_IoT(ctxt_pP, ue_context_p, CC_id);
 
-      LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT"CALLING RLC CONFIG SRB1 (rbid %d)\n",
+      LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT"CALLING RLC CONFIG SRB1bis and SRB1 (rbid %d, rbid %d)\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            Idx);
+            DCCH0_NB_IoT, DCCH1_NB_IoT);
 
       MSC_LOG_TX_MESSAGE(
         MSC_RRC_ENB,
@@ -2089,27 +2114,27 @@ rrc_eNB_decode_ccch_NB(
         MSC_AS_TIME_ARGS(ctxt_pP),
         ue_context_p->ue_context.rnti);
 
-      //XXX we should not configure PDCP for SRB1bis but only for SRB1
-      NB_rrc_pdcp_config_asn1_req(ctxt_pP,
-                               ue_context_p->ue_context.SRB_configList, //contain SRB1bis but used as SRB1
-                               (DRB_ToAddModList_NB_r13_t *) NULL,
-                               (DRB_ToReleaseList_NB_r13_t*) NULL,
-                               0xff,
-                               NULL,
-                               NULL,
-                               NULL,
-                               NULL,
-							   DCCH1);
+      //MP: we should not configure PDCP for SRB1bis but only for SRB1
+      rrc_pdcp_config_asn1_req_NB_IoT(ctxt_pP,
+                                      ue_context_p->ue_context.SRB_configList, //contain SRB1bis but used as SRB1
+                                      (DRB_ToAddModList_NB_r13_t *) NULL,
+                                      (DRB_ToReleaseList_NB_r13_t*) NULL,
+                                      0xff,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+                                      NULL,
+							                        DCCH1_NB_IoT);
 
       ///MP: Configure RLC for SRB1bis
-      NB_rrc_rlc_config_asn1_req(ctxt_pP,
-                              ue_context_p->ue_context.SRB_configList,
-                              (DRB_ToAddModList_NB_r13_t*) NULL,
-                              (DRB_ToReleaseList_NB_r13_t*) NULL,
-							  SRB1BIS_FLAG_YES
-                             );
+      rrc_rlc_config_asn1_req_NB_IoT(ctxt_pP,
+                                     ue_context_p->ue_context.SRB_configList,
+                                     (DRB_ToAddModList_NB_r13_t*) NULL,
+                                     (DRB_ToReleaseList_NB_r13_t*) NULL,
+							                       SRB1BIS_FLAG_YES
+                                     );
       //MP: Configure RLC for SRB1
-            NB_rrc_rlc_config_asn1_req(ctxt_pP,
+            rrc_rlc_config_asn1_req_NB_IoT(ctxt_pP,
                                     ue_context_p->ue_context.SRB_configList,
                                     (DRB_ToAddModList_NB_r13_t*) NULL,
                                     (DRB_ToReleaseList_NB_r13_t*) NULL,
@@ -2137,20 +2162,20 @@ rrc_eNB_decode_ccch_NB(
 
     LOG_D(RRC, PROTOCOL_RRC_CTXT_UE_FMT"MAC_eNB--- MAC_DATA_IND (rrcConnectionResumeRequest-NB on SRB0) --> RRC_eNB\n",
     	                  PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
-    rrcConnectionResumeRequest_NB=
-    	              &ul_ccch_msg_NB->message.choice.c1.choice.rrcConnectionResumeRequest_r13.criticalExtensions.choice.rrcConnectionResumeRequest_r13;
+    rrcConnectionResumeRequest_NB_IoT=
+    	              &ul_ccch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionResumeRequest_r13.criticalExtensions.choice.rrcConnectionResumeRequest_r13;
 
     LOG_I(RRC,PROTOCOL_RRC_CTXT_UE_FMT" RRCConnectionResumeRequest-NB cause %s\n",
                 PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-                ((rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mt_Access) ?    "mt Access" :
-                 (rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mo_Signalling) ? "mo Signalling" :
-                 (rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mo_Data) ? "mo Data":
-                (rrcConnectionResumeRequest_NB->resumeCause_r13 == EstablishmentCause_NB_r13_mo_ExceptionData) ? "mo Exception data" :
+                ((rrcConnectionResumeRequest_NB_IoT->resumeCause_r13 == EstablishmentCause_NB_r13_mt_Access) ?    "mt Access" :
+                 (rrcConnectionResumeRequest_NB_IoT->resumeCause_r13 == EstablishmentCause_NB_r13_mo_Signalling) ? "mo Signalling" :
+                 (rrcConnectionResumeRequest_NB_IoT->resumeCause_r13 == EstablishmentCause_NB_r13_mo_Data) ? "mo Data":
+                (rrcConnectionResumeRequest_NB_IoT->resumeCause_r13 == EstablishmentCause_NB_r13_mo_ExceptionData) ? "mo Exception data" :
                 "delay tollerant Access v1330"));
 
-    //only reject for now
-    rrc_eNB_generate_RRCConnectionReject_NB(ctxt_pP,
-                                 rrc_eNB_get_ue_context_NB(&eNB_rrc_inst_NB[ctxt_pP->module_id], ctxt_pP->rnti),
+    //MP: only reject for now
+    rrc_eNB_generate_RRCConnectionReject_NB_IoT(ctxt_pP,
+                                 rrc_eNB_get_ue_context_NB_IoT(&eNB_rrc_inst_NB_IoT[ctxt_pP->module_id], ctxt_pP->rnti),
                                  CC_id);
       break;
 
@@ -2172,8 +2197,7 @@ rrc_eNB_decode_ccch_NB(
 }
 
 //-----------------------------------------------------------------------------
-int
-rrc_eNB_decode_dcch_NB(
+int rrc_eNB_decode_dcch_NB_IoT(
   const protocol_ctxt_t* const ctxt_pP,
   const rb_id_t                Srb_id, //Dcch_index
   const uint8_t*    const      Rx_sdu,
@@ -2183,17 +2207,16 @@ rrc_eNB_decode_dcch_NB(
 {
 
   asn_dec_rval_t                      dec_rval;
-  UL_DCCH_Message_NB_t                  *ul_dcch_msg_NB = NULL;
+  UL_DCCH_Message_NB_t                  *ul_dcch_msg_NB_IoT = NULL;
   UE_Capability_NB_r13_t              *UE_Capability_NB = NULL;
   int i;
-  struct rrc_eNB_ue_context_NB_s*        ue_context_p = NULL;
+  struct rrc_eNB_ue_context_NB_IoT_s*        ue_context_p = NULL;
 
   int dedicated_DRB=0;
 
   T(T_ENB_RRC_UL_DCCH_DATA_IN, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
     T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
 
-  //FIXME : depends on how SRBs are managed
   if ((Srb_id != 1) && (Srb_id != 3)) {
     LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Received message on SRB%d, should not have ...\n",
           PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
@@ -2209,42 +2232,14 @@ rrc_eNB_decode_dcch_NB(
   dec_rval = uper_decode(
                NULL,
                &asn_DEF_UL_DCCH_Message_NB,
-               (void**)&ul_dcch_msg_NB,
+               (void**)&ul_dcch_msg_NB_IoT,
                Rx_sdu,
                sdu_sizeP,
                0,
                0);
 
-  //TODO:delete?
-#if defined(ENABLE_ITTI)
-#   if defined(DISABLE_ITTI_XER_PRINT)
-  {
-    MessageDef                         *message_p;
-
-    message_p = itti_alloc_new_message(TASK_RRC_ENB, RRC_UL_DCCH_MESSAGE);
-    memcpy(&message_p->ittiMsg, (void *)ul_dcch_msg, sizeof(RrcUlDcchMessage));
-
-    itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, message_p);
-  }
-#   else
-  {
-    char                                message_string[10000];
-    size_t                              message_string_size;
-
-    if ((message_string_size =
-           xer_sprint(message_string, sizeof(message_string), &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg_NB)) >= 0) {
-      MessageDef                         *msg_p;
-
-      msg_p = itti_alloc_new_message_sized(TASK_RRC_ENB, RRC_UL_DCCH, message_string_size + sizeof(IttiMsgText));
-      msg_p->ittiMsg.rrc_ul_dcch.size = message_string_size;
-      memcpy(&msg_p->ittiMsg.rrc_ul_dcch.text, message_string, message_string_size);
-
-      itti_send_msg_to_task(TASK_UNKNOWN, ctxt_pP->instance, msg_p);
-    }
-  }
-#   endif
-#endif
-
+//#if defined(ENABLE_ITTI)
+//#   if defined(DISABLE_ITTI_XER_PRINT)
 
   {
     for (i = 0; i < sdu_sizeP; i++) {
@@ -2261,13 +2256,13 @@ rrc_eNB_decode_dcch_NB(
     return -1;
   }
 
-  ue_context_p = rrc_eNB_get_ue_context_NB(
-                   &eNB_rrc_inst_NB[ctxt_pP->module_id],
+  ue_context_p = rrc_eNB_get_ue_context_NB_IoT(
+                   &eNB_rrc_inst_NB_IoT[ctxt_pP->module_id],
                    ctxt_pP->rnti);
 
-  if (ul_dcch_msg_NB->message.present == UL_DCCH_MessageType_NB_PR_c1) {
+  if (ul_dcch_msg_NB_IoT->message.present == UL_DCCH_MessageType_NB_PR_c1) {
 
-    switch (ul_dcch_msg_NB->message.choice.c1.present) {
+    switch (ul_dcch_msg_NB_IoT->message.choice.c1.present) {
     case UL_DCCH_MessageType_NB__c1_PR_NOTHING:   /* No components present */
       break;
 
@@ -2298,38 +2293,32 @@ rrc_eNB_decode_dcch_NB(
             PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
             "(RRCConnectionReconfigurationComplete-NB) ---> RRC_eNB]\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH1, //through SRB1
+            DCCH1_NB_IoT, //through SRB1
             sdu_sizeP);
 
-      if (ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.criticalExtensions.
+      if (ul_dcch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.criticalExtensions.
           present == RRCConnectionReconfigurationComplete_NB__criticalExtensions_PR_rrcConnectionReconfigurationComplete_r13) {
 	/*NN: revise the condition */
-    	  //XXX MP: RRC_RECONFIGURED indicate if the default/dedicated bearer has been/has been not established
-        if (ue_context_p->ue_context.Status == RRC_RECONFIGURED){ // a dedicated bearers has been established
+
+   //MP: RRC_RECONFIGURED_NB_IoT indicate if the default/dedicated bearer has been/not established
+
+        if (ue_context_p->ue_context.Status == RRC_RECONFIGURED_NB_IoT){ // a dedicated bearers has been established
 	  dedicated_DRB = 1;
 	  LOG_I(RRC,
-		PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (dedicated DRB, xid %ld)\n",
-		PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
+		PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED_NB_IoT (dedicated DRB, xid %ld)\n",
+		PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
 	}else { //a default bearer has been established
 	  dedicated_DRB = 0;
-	  ue_context_p->ue_context.Status = RRC_RECONFIGURED;
+	  ue_context_p->ue_context.Status = RRC_RECONFIGURED_NB_IoT;
 	  LOG_I(RRC,
-		PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED (default DRB, xid %ld)\n",
-		PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
+		PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_RECONFIGURED_NB_IoT (default DRB, xid %ld)\n",
+		PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),ul_dcch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
 	}
-	rrc_eNB_process_RRCConnectionReconfigurationComplete_NB(
+	rrc_eNB_process_RRCConnectionReconfigurationComplete_NB_IoT(
           ctxt_pP,
           ue_context_p,
-	  ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
+	  ul_dcch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
 
-#if defined(FLEXRAN_AGENT_SB_IF)
-	//WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
-	if (mac_agent_registered[ctxt_pP->module_id]) {
-	  agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
-										ue_context_p->ue_id_rnti,
-										PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_UPDATED);
-	}
-#endif
       }
 
 //#if defined(ENABLE_ITTI)...
@@ -2338,15 +2327,16 @@ rrc_eNB_decode_dcch_NB(
 	if (dedicated_DRB == 1){
 	  rrc_eNB_send_S1AP_E_RAB_SETUP_RESP(ctxt_pP,
 					     ue_context_p,
-					     ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
+					     ul_dcch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionReconfigurationComplete_r13.rrc_TransactionIdentifier);
 	}else {
 	  rrc_eNB_send_S1AP_INITIAL_CONTEXT_SETUP_RESP(ctxt_pP,
 						       ue_context_p);
 	}
       }
-#else  // MP: ENABLE_USE_MME ??
+#else  // MP: not use of MME
+      //dedicated bearer in the absence of EPC
       if (dedicated_DRB == 0 ) {
-	rrc_eNB_reconfigure_DRBs_NB(ctxt_pP,ue_context_p); //MP: establish a dedicated DRB
+	rrc_eNB_reconfigure_DRBs_NB_IoT(ctxt_pP,ue_context_p); //MP: establish a dedicated DRB
       }
 #endif
 
@@ -2382,12 +2372,12 @@ rrc_eNB_decode_dcch_NB(
             PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
             "(rrcConnectionReestablishmentComplete-NB) ---> RRC_eNB\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH,
+            DCCH0_NB_IoT,
             sdu_sizeP);
       break;
 
     case UL_DCCH_MessageType_NB__c1_PR_rrcConnectionSetupComplete_r13:
-    	//XXX MP: Ts 36.331 V14.2.1 RRCConnectionSetupComplete is transmitted over SRB1bis (pag 585)
+    	//MP: Ts 36.331 V14.2.1 RRCConnectionSetupComplete is transmitted over SRB1bis (pag 585)
 
 #ifdef RRC_MSG_PRINT
       LOG_F(RRC,"[MSG] RRCConnectionSetupComplete-NB\n");
@@ -2413,31 +2403,23 @@ rrc_eNB_decode_dcch_NB(
             PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
             "(RRCConnectionSetupComplete-NB) ---> RRC_eNB\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH0,//SRB1bis
+            DCCH0_NB_IoT,//SRB1bis
             sdu_sizeP);
 
-      if (ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionSetupComplete_r13.criticalExtensions.present ==
+      if (ul_dcch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionSetupComplete_r13.criticalExtensions.present ==
     		  RRCConnectionSetupComplete_NB__criticalExtensions_PR_rrcConnectionSetupComplete_r13) {
 
-          rrc_eNB_process_RRCConnectionSetupComplete_NB(
+          rrc_eNB_process_RRCConnectionSetupComplete_NB_IoT(
             ctxt_pP,
             ue_context_p,
-            &ul_dcch_msg_NB->message.choice.c1.choice.rrcConnectionSetupComplete_r13.criticalExtensions.choice.rrcConnectionSetupComplete_r13);
+            &ul_dcch_msg_NB_IoT->message.choice.c1.choice.rrcConnectionSetupComplete_r13.criticalExtensions.choice.rrcConnectionSetupComplete_r13);
 
           //set Ue status CONNECTED
-          ue_context_p->ue_context.Status = RRC_CONNECTED;
+          ue_context_p->ue_context.Status = RRC_CONNECTED_NB_IoT;
 
-          LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_CONNECTED \n",
+          LOG_I(RRC, PROTOCOL_RRC_CTXT_UE_FMT" UE State = RRC_CONNECTED_NB_IoT \n",
                 PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
 
-#if defined(FLEXRAN_AGENT_SB_IF)
-	  //WARNING:Inform the controller about the UE activation. Should be moved to RRC agent in the future
-	  if (mac_agent_registered[ctxt_pP->module_id]) {
-	    agent_mac_xface[ctxt_pP->eNB_index]->flexran_agent_notify_ue_state_change(ctxt_pP->module_id,
-										  ue_context_p->ue_id_rnti,
-										  PROTOCOL__FLEX_UE_STATE_CHANGE_TYPE__FLUESC_ACTIVATED);
-	  }
-#endif
 
       }
 
@@ -2449,7 +2431,6 @@ rrc_eNB_decode_dcch_NB(
 
     	/* R2-163262 3GPP NB-IOT Ad-hoc Meeting #2
     	 * After receiving the SMC and performing the security activation, the UE shall use the SRB1.
-    	 * If the UE fails the security activation, the UE shall use the SRB1-bis for Security Mode Complete message failure
     	 */
 
       T(T_ENB_RRC_SECURITY_MODE_COMPLETE, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
@@ -2478,26 +2459,24 @@ rrc_eNB_decode_dcch_NB(
       LOG_I(RRC,
             PROTOCOL_RRC_CTXT_UE_FMT" received securityModeComplete-NB on UL-DCCH %d from UE\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH);
+            DCCH0_NB_IoT);
       LOG_D(RRC,
             PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
             "(securityModeComplete-NB) ---> RRC_eNB\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH0,//through SRB1bis
+            DCCH0_NB_IoT,//through SRB1bis
             sdu_sizeP);
 #ifdef XER_PRINT
-      xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg_NB);
+      xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg_NB_IoT);
 #endif
 
-      // confirm with PDCP about the security mode for DCCH
-      //rrc_pdcp_config_req (enb_mod_idP, frameP, 1,CONFIG_ACTION_SET_SECURITY_MODE, (ue_mod_idP * NB_RB_MAX) + DCCH, 0x77);
-      // continue the procedure
 
-      //MP: this is OPTIONAL operation
+
+      //MP: this is OPTIONAL
       ue_context_p->ue_context.Srb1bis.Active=0;
 
 
-      rrc_eNB_generate_UECapabilityEnquiry_NB(ctxt_pP, ue_context_p);
+      rrc_eNB_generate_UECapabilityEnquiry_NB_IoT(ctxt_pP, ue_context_p);
 
       break;
 
@@ -2545,27 +2524,26 @@ rrc_eNB_decode_dcch_NB(
             PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
             "(securityModeFailure-NB) ---> RRC_eNB\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH0,
+            DCCH0_NB_IoT,
             sdu_sizeP);
 
 #ifdef XER_PRINT
-      xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg_NB);
+      xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg_NB_IoT);
 #endif
 
 
-//XXX MP: According with prof.Navid, after reception of SecurityModeFailure we should configure no security
-      	 //therefore setting securityActivated=0 for the corresponding PDCP entity in the PDCP but still start the usage of SRB1
+//MP: After reception of SecurityModeFailure we should configure no security
+//therefore setting securityActivated=0 for the corresponding PDCP entity in the PDCP but still start the usage of SRB1
 
-//MP: problem1: rrc_pdcp_config_req function is no more used and have no definition for CONFIG_ACTION_REMOVE (old implementation)
 
-      //   pdcp_pP-> security_activated modified (=1) by pdcp_config_set_security in NB_pdcp_config_req_asn1 at configuration time
+      //   pdcp_pP-> security_activated modified (=1) by pdcp_config_set_security in pdcp_config_req_asn1_NB_IoT at configuration time
       //   we now create a particular case for pdcp_config_set_securityy function in which for a particular securityMode (= -1) we deactivate security.
-      //   we first invoke the NB_rrc_pdcp_config_asn1_req that with the particular case of securityMode = -1 will disable security through the pdcp_config_set_security
+      //   we first invoke the rrc_pdcp_config_asn1_req_NB_IoT that with the particular case of securityMode = -1 will disable security through the pdcp_config_set_security
 
 
-//XXX MP: the integrity protection is still not used in OAI --> MAC-I is padded always to 0 so no need to modify it
+//MP: the integrity protection is still not used in OAI --> MAC-I is padded always to 0 so no need to modify it
 
-      NB_rrc_pdcp_config_asn1_req(
+      rrc_pdcp_config_asn1_req_NB_IoT(
     		  	  	  	  	  	  ctxt_pP,
 								  ue_context_p->ue_context.SRB_configList,
 								  (DRB_ToAddModList_NB_r13_t *)NULL,
@@ -2575,16 +2553,16 @@ rrc_eNB_decode_dcch_NB(
 								  NULL,
 								  NULL,
 								  NULL,
-								  DCCH1//its only for check purposes (if correctly called could be deleted)
+								  DCCH1_NB_IoT//its only for check purposes (if correctly called could be deleted)
       	  	  	  	  	  	  	  );
 
-      rrc_eNB_generate_UECapabilityEnquiry_NB(ctxt_pP, ue_context_p);
+      rrc_eNB_generate_UECapabilityEnquiry_NB_IoT(ctxt_pP, ue_context_p);
 
       break;
 
     case UL_DCCH_MessageType_NB__c1_PR_ueCapabilityInformation_r13:
 
-    	//XXX message received over SRB1
+    	//MP: received over SRB1
 
       T(T_ENB_RRC_UE_CAPABILITY_INFORMATION, T_INT(ctxt_pP->module_id), T_INT(ctxt_pP->frame),
         T_INT(ctxt_pP->subframe), T_INT(ctxt_pP->rnti));
@@ -2612,12 +2590,12 @@ rrc_eNB_decode_dcch_NB(
       LOG_I(RRC,
             PROTOCOL_RRC_CTXT_UE_FMT" received ueCapabilityInformation-NB on UL-DCCH %d from UE\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH1);
+            DCCH1_NB_IoT);
       LOG_D(RRC,
             PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
             "(UECapabilityInformation) ---> RRC_eNB\n",
             PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-            DCCH1,
+            DCCH1_NB_IoT,
             sdu_sizeP);
 #ifdef XER_PRINT
       xer_fprint(stdout, &asn_DEF_UL_DCCH_Message_NB, (void *)ul_dcch_msg);
@@ -2639,20 +2617,20 @@ rrc_eNB_decode_dcch_NB(
       if (EPC_MODE_ENABLED == 1) {
         rrc_eNB_send_S1AP_UE_CAPABILITIES_IND(ctxt_pP,
                                               ue_context_p,
-                                              ul_dcch_msg_NB);
+                                              ul_dcch_msg_NB_IoT);
       }
 #else
       ue_context_p->ue_context.nb_of_e_rabs = 1;
       //FIXME may no more present in NB_IoT or different parameter to set
       for (i = 0; i < ue_context_p->ue_context.nb_of_e_rabs; i++){
-	ue_context_p->ue_context.e_rab[i].status = E_RAB_NB_STATUS_NEW;
+	ue_context_p->ue_context.e_rab[i].status = E_RAB_STATUS_NEW_NB_IoT;
 	ue_context_p->ue_context.e_rab[i].param.e_rab_id = 1+i;
-	ue_context_p->ue_context.e_rab[i].param.qos.qci=9; //Non-GBR the default value (TS
+	ue_context_p->ue_context.e_rab[i].param.qos.qci=9; //Non-GBR
       }
       ue_context_p->ue_context.setup_e_rabs =ue_context_p->ue_context.nb_of_e_rabs;
 #endif
 
-      rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB(ctxt_pP, ue_context_p);//no HO_FLAG
+      rrc_eNB_generate_defaultRRCConnectionReconfiguration_NB_IoT(ctxt_pP, ue_context_p);//no HO_FLAG
 
       break;
 
@@ -2688,7 +2666,7 @@ rrc_eNB_decode_dcch_NB(
       if (EPC_MODE_ENABLED == 1) {
         rrc_eNB_send_S1AP_UPLINK_NAS(ctxt_pP,
                                      ue_context_p,
-                                     ul_dcch_msg_NB);
+                                     ul_dcch_msg_NB_IoT);
       }
 
 #endif
@@ -2727,7 +2705,7 @@ rrc_eNB_decode_dcch_NB(
     	            PROTOCOL_RRC_CTXT_UE_FMT" RLC RB %02d --- RLC_DATA_IND %d bytes "
     	            "(rrcConnectionResumeComplete-NB) ---> RRC_eNB\n",
     	            PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP),
-    	            DCCH, //check
+    	            DCCH0_NB_IoT, //check
     	            sdu_sizeP);
 
 	break;
@@ -2755,8 +2733,7 @@ rrc_eNB_decode_dcch_NB(
 
 //-----------------------------------------------------------------------------
 //put out from the ITTI FIXME is completely based on ITTI--> must be changed (msg_p, itti_receive_msg ecc...)
-void*
-rrc_enb_task_NB(
+void* rrc_enb_task_NB_IoT(
   void* args_p
 )
 //-----------------------------------------------------------------------------
@@ -2765,7 +2742,7 @@ rrc_enb_task_NB(
   const char                         *msg_name_p;
   instance_t                          instance;
   int                                 result;
-  SRB_INFO_NB                           *srb_info_p;
+  SRB_INFO_NB_IoT                     *srb_info_p;
   int                                 CC_id;
 
   protocol_ctxt_t                     ctxt;
@@ -2802,7 +2779,7 @@ rrc_enb_task_NB(
       CC_id = RRC_MAC_CCCH_DATA_IND(msg_p).CC_id;
 
       ///SRB0
-      srb_info_p = &eNB_rrc_inst_NB[instance].carrier[CC_id].Srb0;
+      srb_info_p = &eNB_rrc_inst_NB_IoT[instance].carrier[CC_id].Srb0;
 
       memcpy(srb_info_p->Rx_buffer.Payload,
              RRC_MAC_CCCH_DATA_IND(msg_p).sdu,
@@ -2810,7 +2787,7 @@ rrc_enb_task_NB(
 
       srb_info_p->Rx_buffer.payload_size = RRC_MAC_CCCH_DATA_IND(msg_p).sdu_size;
 
-      rrc_eNB_decode_ccch_NB(&ctxt, srb_info_p, CC_id); //SRB0
+      rrc_eNB_decode_ccch_NB_IoT(&ctxt, srb_info_p, CC_id); //SRB0
 
       break;
 
@@ -2826,10 +2803,10 @@ rrc_enb_task_NB(
             PROTOCOL_RRC_CTXT_UE_ARGS(&ctxt),
             RRC_DCCH_DATA_IND(msg_p).dcch_index,
             msg_name_p);
-      rrc_eNB_decode_dcch_NB(&ctxt,
-                          RRC_DCCH_DATA_IND(msg_p).dcch_index, //3 if SRB1bis and 1 for SRB1
-                          RRC_DCCH_DATA_IND(msg_p).sdu_p, //rx_sdu
-                          RRC_DCCH_DATA_IND(msg_p).sdu_size);
+      rrc_eNB_decode_dcch_NB_IoT(&ctxt,
+                                 RRC_DCCH_DATA_IND(msg_p).dcch_index, //3 if SRB1bis and 1 for SRB1
+                                 RRC_DCCH_DATA_IND(msg_p).sdu_p, //rx_sdu
+                                 RRC_DCCH_DATA_IND(msg_p).sdu_size);
 
       // Message buffer has been processed, free it now.
       result = itti_free(ITTI_MSG_ORIGIN_ID(msg_p), RRC_DCCH_DATA_IND(msg_p).sdu_p);
@@ -2840,7 +2817,7 @@ rrc_enb_task_NB(
 
       /* Messages from S1AP */
     case S1AP_DOWNLINK_NAS:
-      rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_eNB_mui);
+      rrc_eNB_process_S1AP_DOWNLINK_NAS(msg_p, msg_name_p, instance, &rrc_eNB_mui_NB_IoT);
       break;
 
     case S1AP_INITIAL_CONTEXT_SETUP_REQ:
@@ -2879,7 +2856,7 @@ rrc_enb_task_NB(
       /* Messages from eNB app */
     case RRC_CONFIGURATION_REQ:
       LOG_I(RRC, "[eNB %d] Received %s\n", instance, msg_name_p);
-      openair_rrc_eNB_configuration_NB(ENB_INSTANCE_TO_MODULE_ID(instance), &RRC_CONFIGURATION_REQ(msg_p));
+      openair_rrc_eNB_configuration_NB_IoT(ENB_INSTANCE_TO_MODULE_ID(instance), &RRC_CONFIGURATION_REQ(msg_p));
       break;
 
     default:
diff --git a/openair2/RRC/LITE/rrc_eNB_S1AP.h b/openair2/RRC/LITE/rrc_eNB_S1AP.h
index a57002010c646f23b5b6d8b35735c29af5342c47..7e236d946667e69ad77719220759da506913f9b9 100644
--- a/openair2/RRC/LITE/rrc_eNB_S1AP.h
+++ b/openair2/RRC/LITE/rrc_eNB_S1AP.h
@@ -33,6 +33,7 @@
 
 # if defined(ENABLE_USE_MME)
 
+#include "defs.h"
 #include "UL-DCCH-Message.h"
 
 /* Up link procedures */
diff --git a/openair2/RRC/LITE/rrc_eNB_UE_context.c b/openair2/RRC/LITE/rrc_eNB_UE_context.c
index 740cc8be73871341c2f20a2f687bde69da7cee16..c0243ca6bf6aa9eceb2fca52956e806b1c08cb1b 100644
--- a/openair2/RRC/LITE/rrc_eNB_UE_context.c
+++ b/openair2/RRC/LITE/rrc_eNB_UE_context.c
@@ -48,17 +48,6 @@ uid_linear_allocator_init(
   memset(uid_pP, 0, sizeof(uid_allocator_t));
 }
 
-//------------------------------------------------------------------------------
-void
-uid_linear_allocator_init_NB(
-  uid_allocator_NB_t* const uid_pP
-)
-//------------------------------------------------------------------------------
-{
-  memset(uid_pP, 0, sizeof(uid_allocator_NB_t));
-}
-
-
 //------------------------------------------------------------------------------
 uid_t
 uid_linear_allocator_new(
@@ -166,21 +155,6 @@ rrc_eNB_get_ue_context(
 }
 
 
-//--(NB-IoT implementation)-----------------------------------------------------
-struct rrc_eNB_ue_context_NB_s*
-rrc_eNB_get_ue_context_NB(
-  eNB_RRC_INST_NB* rrc_instance_pP,
-  rnti_t rntiP)
-//------------------------------------------------------------------------------
-{
-  rrc_eNB_ue_context_NB_t temp;
-  memset(&temp, 0, sizeof(struct rrc_eNB_ue_context_NB_s));
-  /* eNB ue rrc id = 24 bits wide */
-  temp.ue_id_rnti = rntiP;
-  return RB_FIND(rrc_ue_tree_s, &rrc_instance_pP->rrc_ue_head, &temp);
-}
-
-
 //------------------------------------------------------------------------------
 void rrc_eNB_remove_ue_context(
   const protocol_ctxt_t* const ctxt_pP,
diff --git a/openair2/RRC/LITE/rrc_eNB_UE_context.h b/openair2/RRC/LITE/rrc_eNB_UE_context.h
index dfaa4b5e6e15c10e6601b7c8be023ce9bb30ed8c..63eeb6f4a1cc894c36c7de1b6b72d85dfe5ae4cf 100644
--- a/openair2/RRC/LITE/rrc_eNB_UE_context.h
+++ b/openair2/RRC/LITE/rrc_eNB_UE_context.h
@@ -31,7 +31,6 @@
 #include "collection/tree.h"
 #include "COMMON/platform_types.h"
 #include "defs.h"
-#include "defs_nb_iot.h"
 
 
 void
@@ -39,6 +38,7 @@ uid_linear_allocator_init(
   uid_allocator_t* const uid_pP
 );
 
+
 uid_t
 uid_linear_allocator_new(
   eNB_RRC_INST* rrc_instance_pP
@@ -72,11 +72,6 @@ rrc_eNB_get_ue_context(
   rnti_t rntiP
 );
 
-//NB-IoT
-struct rrc_eNB_ue_context_NB_s*
-rrc_eNB_get_ue_context_NB(
-  eNB_RRC_INST_NB* rrc_instance_pP,
-  rnti_t rntiP);
 
 void rrc_eNB_remove_ue_context(
   const protocol_ctxt_t* const ctxt_pP,
diff --git a/openair2/RRC/LITE/rrc_eNB_UE_context_NB_IoT.c b/openair2/RRC/LITE/rrc_eNB_UE_context_NB_IoT.c
new file mode 100644
index 0000000000000000000000000000000000000000..4abe53d0153fcd78fb07e85d6633ad8be68a7ff9
--- /dev/null
+++ b/openair2/RRC/LITE/rrc_eNB_UE_context_NB_IoT.c
@@ -0,0 +1,191 @@
+/*
+ * 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.0  (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 rrc_eNB_UE_context.h
+ * \brief rrc procedures for UE context
+ * \author Lionel GAUTHIER
+ * \date 2015
+ * \version 1.0
+ * \company Eurecom
+ * \email: lionel.gauthier@eurecom.fr
+ */
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <limits.h>
+
+#include "UTIL/LOG/log.h"
+#include "rrc_eNB_UE_context_NB_IoT.h"
+#include "msc.h"
+
+//------------------------------------------------------------------------------
+void uid_linear_allocator_init_NB_IoT(
+
+  uid_allocator_NB_IoT_t* const uid_pP
+)
+//------------------------------------------------------------------------------
+{
+  memset(uid_pP, 0, sizeof(uid_allocator_NB_IoT_t));
+}
+
+
+//------------------------------------------------------------------------------
+uid_t uid_linear_allocator_new_NB_IoT(
+
+  eNB_RRC_INST_NB_IoT* const rrc_instance_pP
+)
+//------------------------------------------------------------------------------
+{
+  unsigned int i;
+  unsigned int bit_index = 1;
+  uid_t        uid = 0;
+  uid_allocator_NB_IoT_t* uia_p = &rrc_instance_pP->uid_allocator;
+
+  for (i=0; i < UID_LINEAR_ALLOCATOR_BITMAP_SIZE_NB_IoT; i++) {
+    if (uia_p->bitmap[i] != UINT_MAX) {
+      bit_index = 1;
+      uid       = 0;
+
+      while ((uia_p->bitmap[i] & bit_index) == bit_index) {
+        bit_index = bit_index << 1;
+        uid       += 1;
+      }
+
+      uia_p->bitmap[i] |= bit_index;
+      return uid + (i*sizeof(unsigned int)*8);
+    }
+  }
+
+  return UINT_MAX;
+}
+
+//------------------------------------------------------------------------------
+void uid_linear_allocator_free_NB_IoT(
+
+  eNB_RRC_INST_NB_IoT*   rrc_instance_pP,
+  uid_t                  uidP
+)
+//------------------------------------------------------------------------------
+{
+  unsigned int i      =  uidP/sizeof(unsigned int)/8;
+  unsigned int bit    =  uidP % (sizeof(unsigned int) * 8);
+  unsigned int value  =  ~(0x00000001 << bit);
+
+  if (i < UID_LINEAR_ALLOCATOR_BITMAP_SIZE_NB_IoT) {
+    rrc_instance_pP->uid_allocator.bitmap[i] &=  value;
+  }
+}
+
+
+
+int rrc_eNB_compare_ue_rnti_id_NB_IoT(
+
+  struct rrc_eNB_ue_context_NB_IoT_s   *c1_pP,
+  struct rrc_eNB_ue_context_NB_IoT_s   *c2_pP)
+//------------------------------------------------------------------------------
+{
+  if (c1_pP->ue_id_rnti > c2_pP->ue_id_rnti) {
+    return 1;
+  }
+
+  if (c1_pP->ue_id_rnti < c2_pP->ue_id_rnti) {
+    return -1;
+  }
+
+  return 0;
+}
+
+/* Generate the tree management functions for NB-IoT structures */
+RB_GENERATE(rrc_ue_tree_NB_IoT_s, rrc_eNB_ue_context_NB_IoT_s, entries,
+            rrc_eNB_compare_ue_rnti_id_NB_IoT);
+
+
+//------------------------------------------------------------------------------
+struct rrc_eNB_ue_context_NB_IoT_s*
+rrc_eNB_allocate_new_UE_context_NB_IoT(
+  eNB_RRC_INST_NB_IoT* rrc_instance_pP
+)
+//------------------------------------------------------------------------------
+{
+  struct rrc_eNB_ue_context_NB_IoT_s* new_p;
+  new_p = malloc(sizeof(struct rrc_eNB_ue_context_NB_IoT_s));
+
+  if (new_p == NULL) {
+    LOG_E(RRC, "Cannot allocate new ue context\n");
+    return NULL;
+  }
+
+  memset(new_p, 0, sizeof(struct rrc_eNB_ue_context_NB_IoT_s));
+  new_p->local_uid = uid_linear_allocator_new_NB_IoT(rrc_instance_pP);
+  return new_p;
+}
+
+
+struct rrc_eNB_ue_context_NB_IoT_s*
+rrc_eNB_get_ue_context_NB_IoT(
+  eNB_RRC_INST_NB_IoT* rrc_instance_pP,
+  rnti_t rntiP)
+//------------------------------------------------------------------------------
+{
+  rrc_eNB_ue_context_NB_IoT_t temp;
+  memset(&temp, 0, sizeof(struct rrc_eNB_ue_context_NB_IoT_s));
+  /* eNB ue rrc id = 24 bits wide */
+  temp.ue_id_rnti = rntiP;
+  return RB_FIND(rrc_ue_tree_NB_IoT_s, &rrc_instance_pP->rrc_ue_head, &temp);
+}
+
+//------------------------------------------------------------------------------
+void rrc_eNB_remove_ue_context_NB_IoT(
+  const protocol_ctxt_t* const ctxt_pP,
+  eNB_RRC_INST_NB_IoT*                rrc_instance_pP,
+  struct rrc_eNB_ue_context_NB_IoT_s* ue_context_pP)
+//------------------------------------------------------------------------------
+{
+  if (rrc_instance_pP == NULL) {
+    LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Bad RRC instance\n",
+          PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+    return;
+  }
+
+  if (ue_context_pP == NULL) {
+    LOG_E(RRC, PROTOCOL_RRC_CTXT_UE_FMT" Trying to free a NULL UE context\n",
+          PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+    return;
+  }
+
+  RB_REMOVE(rrc_ue_tree_NB_IoT_s, &rrc_instance_pP->rrc_ue_head, ue_context_pP);
+
+  MSC_LOG_EVENT(
+    MSC_RRC_ENB,
+    "0 Removed UE %"PRIx16" ",
+    ue_context_pP->ue_context.rnti);
+
+  rrc_eNB_free_mem_UE_context_NB_IoT(ctxt_pP, ue_context_pP);
+  uid_linear_allocator_free_NB_IoT(rrc_instance_pP, ue_context_pP->local_uid);
+  free(ue_context_pP);
+  LOG_I(RRC,
+        PROTOCOL_RRC_CTXT_UE_FMT" Removed UE context\n",
+        PROTOCOL_RRC_CTXT_UE_ARGS(ctxt_pP));
+}
+
+
+
diff --git a/openair2/RRC/LITE/rrc_eNB_UE_context_NB_IoT.h b/openair2/RRC/LITE/rrc_eNB_UE_context_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..ef02d49bf326ca9e3d44dc4f510aca16ae2907d0
--- /dev/null
+++ b/openair2/RRC/LITE/rrc_eNB_UE_context_NB_IoT.h
@@ -0,0 +1,78 @@
+/*
+ * 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.0  (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 rrc_eNB_UE_context.h
+ * \brief rrc procedures for UE context
+ * \author Lionel GAUTHIER
+ * \date 2015
+ * \version 1.0
+ * \company Eurecom
+ * \email: lionel.gauthier@eurecom.fr
+ */
+#ifndef __RRC_ENB_UE_CONTEXT_NB_IoT_H__
+#define __RRC_ENB_UE_CONTEXT_NB_IoT_H__
+
+
+#include "collection/tree.h"
+#include "COMMON/platform_types.h"
+//#include "defs.h"
+#include "defs_NB_IoT.h"
+
+
+void
+uid_linear_allocator_init_NB_IoT(
+  uid_allocator_NB_IoT_t* const uid_pP
+);
+
+
+uid_t
+uid_linear_allocator_new_NB_IoT(
+  eNB_RRC_INST_NB_IoT* const rrc_instance_pP
+);
+
+void
+uid_linear_allocator_free_NB_IoT(
+  eNB_RRC_INST_NB_IoT* rrc_instance_pP,
+  uid_t uidP
+);
+
+
+int rrc_eNB_compare_ue_rnti_id_NB_IoT(
+  struct rrc_eNB_ue_context_NB_IoT_s* c1_pP, struct rrc_eNB_ue_context_NB_IoT_s* c2_pP);
+
+RB_PROTOTYPE(rrc_ue_tree_NB_IoT_s, rrc_eNB_ue_context_NB_IoT_s, entries, rrc_eNB_compare_ue_rnti_id_NB_IoT);
+
+struct rrc_eNB_ue_context_NB_IoT_s*
+rrc_eNB_allocate_new_UE_context_NB_IoT(
+  eNB_RRC_INST_NB_IoT* rrc_instance_pP
+);
+
+struct rrc_eNB_ue_context_NB_IoT_s*
+rrc_eNB_get_ue_context_NB_IoT(
+  eNB_RRC_INST_NB_IoT* rrc_instance_pP,
+  rnti_t rntiP);
+
+void rrc_eNB_remove_ue_context_NB_IoT(
+  const protocol_ctxt_t* const ctxt_pP,
+  eNB_RRC_INST_NB_IoT*                rrc_instance_pP,
+  struct rrc_eNB_ue_context_NB_IoT_s* ue_context_pP);
+
+#endif
diff --git a/openair2/RRC/LITE/rrc_types_NB_IoT.h b/openair2/RRC/LITE/rrc_types_NB_IoT.h
new file mode 100644
index 0000000000000000000000000000000000000000..55e98ea5f1bc5248387aa1baf2303cc7fd00e775
--- /dev/null
+++ b/openair2/RRC/LITE/rrc_types_NB_IoT.h
@@ -0,0 +1,64 @@
+/*
+ * 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.0  (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 rrc_types.h
+* \brief rrc types and subtypes
+* \author Navid Nikaein and Raymond Knopp
+* \date 2011 - 2014
+* \version 1.0
+* \company Eurecom
+* \email: navid.nikaein@eurecom.fr, raymond.knopp@eurecom.fr
+*/
+
+#ifndef RRC_TYPES_NB_IOT_H_
+#define RRC_TYPES_NB_IOT_H_
+
+typedef enum Rrc_State_NB_IoT_e {
+  RRC_STATE_INACTIVE_NB_IoT=0,
+  RRC_STATE_IDLE_NB_IoT,
+  RRC_STATE_CONNECTED_NB_IoT,
+
+  RRC_STATE_FIRST_NB_IoT = RRC_STATE_INACTIVE_NB_IoT,
+  RRC_STATE_LAST_NB_IoT = RRC_STATE_CONNECTED_NB_IoT,
+} Rrc_State_NB_IoT_t;
+
+typedef enum Rrc_Sub_State_NB_IoT_e {
+  RRC_SUB_STATE_INACTIVE_NB_IoT=0,
+
+  RRC_SUB_STATE_IDLE_SEARCHING_NB_IoT,
+  RRC_SUB_STATE_IDLE_RECEIVING_SIB_NB_IoT,
+  RRC_SUB_STATE_IDLE_SIB_COMPLETE_NB_IoT,
+  RRC_SUB_STATE_IDLE_CONNECTING_NB_IoT,
+  RRC_SUB_STATE_IDLE_NB_IoT,
+
+  RRC_SUB_STATE_CONNECTED_NB_IoT,
+
+  RRC_SUB_STATE_INACTIVE_FIRST_NB_IoT = RRC_SUB_STATE_INACTIVE_NB_IoT,
+  RRC_SUB_STATE_INACTIVE_LAST_NB_IoT = RRC_SUB_STATE_INACTIVE_NB_IoT,
+
+  RRC_SUB_STATE_IDLE_FIRST_NB_IoT = RRC_SUB_STATE_IDLE_SEARCHING_NB_IoT,
+  RRC_SUB_STATE_IDLE_LAST_NB_IoT = RRC_SUB_STATE_IDLE_NB_IoT,
+
+  RRC_SUB_STATE_CONNECTED_FIRST_NB_IoT = RRC_SUB_STATE_CONNECTED_NB_IoT,
+  RRC_SUB_STATE_CONNECTED_LAST_NB_IoT = RRC_SUB_STATE_CONNECTED_NB_IoT,
+} Rrc_Sub_State_NB_IoT_t;
+
+#endif /* RRC_TYPES_H_ */
diff --git a/openair2/RRC/LITE/vars.h b/openair2/RRC/LITE/vars.h
index 93bc9c75808700bdb04ef0cb54eff344637803ee..0ef0cb850b9df32592d6042975cd8766dc068fce 100644
--- a/openair2/RRC/LITE/vars.h
+++ b/openair2/RRC/LITE/vars.h
@@ -101,9 +101,7 @@ LogicalChannelConfig_t SRB2_logicalChannelConfig_defaultValue = {ul_SpecificPara
                                                                 };
 
 //CONSTANTS
-rlc_info_t Rlc_info_um,Rlc_info_am_config,
-//NB-IoT
-Rlc_info_am;
+rlc_info_t Rlc_info_um,Rlc_info_am_config;
 
 uint16_t RACH_FREQ_ALLOC;
 //uint8_t NB_RACH;
diff --git a/openair2/RRC/LITE/vars_nb_iot.c b/openair2/RRC/LITE/vars_NB_IoT.h
similarity index 57%
rename from openair2/RRC/LITE/vars_nb_iot.c
rename to openair2/RRC/LITE/vars_NB_IoT.h
index eb7af922fd421eb899bbf627e107c7b6f600ee99..7ed8c587e419f0c4171f389ea2d5366fe9b2036e 100644
--- a/openair2/RRC/LITE/vars_nb_iot.c
+++ b/openair2/RRC/LITE/vars_NB_IoT.h
@@ -1,114 +1,111 @@
-/*
- * 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.0  (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_nb_iot.c
-* \brief rrc variables for NB_IoT
-* \author Raymond Knopp, Navid Nikaein and Michele Paffetti
-* \date 2013 -2017
-* \version 1.0
-* \company Eurecom
-* \email: navid.nikaein@eurecom.fr, michele.paffetti@studio.unibo.it
-*/
-
-
-//#ifndef __OPENAIR_RRC_VARS_NB_H__
-//#define __OPENAIR_RRC_VARS_NB_H__
-#include "defs_nb_iot.h"
-#include "LAYER2/RLC/rlc.h"
-#include "COMMON/mac_rrc_primitives.h"
-#include "LAYER2/MAC/defs_nb_iot.h"
-#include "LogicalChannelConfig-NB-r13.h"
-
-
-//UE_RRC_INST *UE_rrc_inst; //MP: may not used for the moment
-
-
-#ifndef USER_MODE
-
-#ifndef NO_RRM
-int S_rrc= RRC2RRM_FIFO;
-#endif //NO_RRM
-
-#else
-#include "LAYER2/MAC/extern.h"
-#ifndef NO_RRM
-sock_rrm_t S_rrc;
-#endif
-#endif
-
-#ifndef NO_RRM
-#ifndef USER_MODE
-char *Header_buf;
-char *Data;
-unsigned short Header_read_idx,Data_read_idx,Header_size;
-#endif
-unsigned short Data_to_read;
-#endif //NO_RRM
-
-#include "LAYER2/MAC/extern.h"
-#define MAX_U32 0xFFFFFFFF
-
-//LogicalChannelConfig__ext1 logicalChannelSR_Mask_r9_ext1--> not defined for NB-IoT
-
-eNB_RRC_INST_NB *eNB_rrc_inst_NB;
-
-uint8_t DRB2LCHAN_NB[2];//max can be 2 DRBs for NB_IoT --> it used for saving the LCID of DRBs
-
-BOOLEAN_t logicalChannelSR_Prohibit = 1;
-long priority =1;
-
-// Default SRB configurations from 36.331 (9.2.1.1 pag 641  V14.2.1)
-struct LogicalChannelConfig_NB_r13 SRB1bis_NB_logicalChannelConfig_defaultValue = {
-		priority_r13: &priority, //priority
-		logicalChannelSR_Prohibit_r13: &logicalChannelSR_Prohibit //set to TRUE
-};
-struct LogicalChannelConfig_NB_r13 SRB1_NB_logicalChannelConfig_defaultValue = {
-		priority_r13: &priority, //priority
-		logicalChannelSR_Prohibit_r13: &logicalChannelSR_Prohibit //set to TRUE
-};
-
-
-
-//CONSTANTS
-rlc_info_t Rlc_info_um,Rlc_info_am_config, Rlc_info_am;
-uint16_t RACH_FREQ_ALLOC;
-
-//TODO: MP: to e changed --> mac_rrc_primitives
-LCHAN_DESC BCCH_LCHAN_DESC,CCCH_LCHAN_DESC,DCCH_LCHAN_DESC,DTCH_DL_LCHAN_DESC,DTCH_UL_LCHAN_DESC;
-
-//XXX //MP:May not needed
-//MAC_MEAS_T BCCH_MEAS_TRIGGER,CCCH_MEAS_TRIGGER,DCCH_MEAS_TRIGGER,DTCH_MEAS_TRIGGER;
-//MAC_AVG_T BCCH_MEAS_AVG, CCCH_MEAS_AVG,DCCH_MEAS_AVG, DTCH_MEAS_AVG;
-
-// timers (TS 36.331 "UE-TimersAndConstants-NB" pag 622) (milliseconds) XXX MP:--> not sure they will be used
-uint16_t T300[8] = {2500,4000,6000,10000, 15000,25000,40000,60000};
-uint16_t T301[8] = {2500,4000,6000,10000, 15000,25000,40000,60000}; //MP: this start at RRCconnectionReestablishmentReq (not implemented in OAI)
-uint16_t T310[8] = {0,200,500,1000,2000,4000,8000};
-uint16_t T311[8] = {1000, 3000, 5000, 10000, 15000, 20000, 30000}; //MP: may not used
-uint16_t N310[8] = {1,2,3,4,6,8,10,20};
-uint16_t N311[8] = {1,2,3,4,5,6,8,10};
-
-
-// MP: TimeToTrigger not used in NB-IoT
-/* MP: 36.133 Section 9.1.4 RSRP Measurement Report Mapping and RSRQ Mapping, Table: 9.1.4-1 --> not for NB-IoT*/
-
-
-//#endif
+/*
+ * 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.0  (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_nb_iot.c
+* \brief rrc variables for NB_IoT
+* \author Raymond Knopp, Navid Nikaein and Michele Paffetti
+* \date 2013 -2017
+* \version 1.0
+* \company Eurecom
+* \email: navid.nikaein@eurecom.fr, michele.paffetti@studio.unibo.it
+*/
+
+#ifndef __RRC_VARS_NB_IOT_H__
+#define __RRC_VARS_NB_IOT_H__
+
+#include "defs_NB_IoT.h"
+#include "LAYER2/RLC/rlc.h"
+#include "COMMON/mac_rrc_primitives.h"
+#include "LAYER2/MAC/defs_NB_IoT.h"
+#include "LogicalChannelConfig-NB-r13.h"
+
+//-----------------------------------------------------------------------
+// ALL what is defined here should be shared through extern_NB_IoT.h file
+//------------------------------------------------------------------------
+
+
+UE_RRC_INST_NB_IoT *UE_rrc_inst_NB_IoT; //MP: may not used for the moment
+#ifndef USER_MODE
+
+#ifndef NO_RRM
+int S_rrc= RRC2RRM_FIFO;
+#endif //NO_RRM
+
+#else
+//#include "LAYER2/MAC/extern.h"
+#ifndef NO_RRM
+sock_rrm_t S_rrc;
+#endif
+#endif
+
+#ifndef NO_RRM
+#ifndef USER_MODE
+char *Header_buf;
+char *Data;
+unsigned short Header_read_idx,Data_read_idx,Header_size;
+#endif
+unsigned short Data_to_read;
+#endif //NO_RRM
+
+//#include "LAYER2/MAC/extern.h"
+#define MAX_U32 0xFFFFFFFF
+
+eNB_RRC_INST_NB_IoT *eNB_rrc_inst_NB_IoT;
+uint8_t DRB2LCHAN_NB_IoT[2];//max can be 2 DRBs for NB_IoT --> it used for saving the LCID of DRBs
+
+//structure for FAPI-like configuration (memory for this is allocated in init_SI)
+PHY_Config_t *config_INFO;
+
+BOOLEAN_t logicalChannelSR_Prohibit = 1;
+long priority =1;
+
+// Default SRB configurations from 36.331 (9.2.1.1 pag 641  V14.2.1)
+struct LogicalChannelConfig_NB_r13 SRB1bis_logicalChannelConfig_defaultValue_NB_IoT = {
+		priority_r13: &priority, //priority
+		logicalChannelSR_Prohibit_r13: &logicalChannelSR_Prohibit //set to TRUE
+};
+struct LogicalChannelConfig_NB_r13 SRB1_logicalChannelConfig_defaultValue_NB_IoT = {
+		priority_r13: &priority, //priority
+		logicalChannelSR_Prohibit_r13: &logicalChannelSR_Prohibit //set to TRUE
+};
+
+
+
+//CONSTANTS
+rlc_info_t Rlc_info_am_NB_IoT, Rlc_info_am_config_NB_IoT;
+//MP:  LCHAN_DESC (mac_rrc_primitives) is not needed, was only an old implementation for storing LCH information
+
+
+// timers (TS 36.331 v14.2.1 "UE-TimersAndConstants-NB" pag 622) (milliseconds)
+//seems to be not used or only at UE side
+uint16_t T300_NB_IoT[8] = {2500,4000,6000,10000, 15000,25000,40000,60000};
+uint16_t T301_NB_IoT[8] = {2500,4000,6000,10000, 15000,25000,40000,60000}; //MP: this start at RRCconnectionReestablishmentReq (not implemented in OAI)
+uint16_t T310_NB_IoT[8] = {0,200,500,1000,2000,4000,8000};
+uint16_t T311_NB_IoT[8] = {1000, 3000, 5000, 10000, 15000, 20000, 30000}; //MP: may not used
+uint16_t N310_NB_IoT[8] = {1,2,3,4,6,8,10,20};
+uint16_t N311_NB_IoT[8] = {1,2,3,4,5,6,8,10};
+
+
+// MP: TimeToTrigger not used in NB-IoT
+/* MP: 36.133 Section 9.1.4 RSRP Measurement Report Mapping and RSRQ Mapping, Table: 9.1.4-1 --> not for NB-IoT*/
+
+
+#endif
\ No newline at end of file
diff --git a/record.txt b/record.txt
index eb8ceab182a75d577626f51bfaf05221a57b9103..c982b053b0f8a6c05b5088326b878976b1bd5909 100644
--- a/record.txt
+++ b/record.txt
@@ -4,45 +4,45 @@ Nick (nick133371@gmail.com)
 
 
 5/13 
-Add:	    openair1/PHY/impl_defs_lte_nb_iot.h
-Add:        openair1/PHY/INIT/defs_nb_iot.h
-Add:        openair1/PHY/INIT/Lte_init_nb_iot.c
+Add:	    openair1/PHY/impl_defs_lte_NB_IoT.h
+Add:        openair1/PHY/INIT/defs_NB_IoT.h
+Add:        openair1/PHY/INIT/lte_init_NB_IoT.c
 
 Comment: 
-Functions: NB_phy_config_mib_eNB(), NB_phy_config_sib2_eNB(), NB_phy_config_dedicated_eNB().
-Parameters: NB_DL_FRAME_PARAMS(Original LTE_DL_FRAME_PARAMS)
+Functions: phy_config_mib_eNB_NB_IoT(), phy_config_sib2_eNB_NB_IoT(), phy_config_dedicated_eNB_NB_IoT().
+Parameters: NB_IoT_DL_FRAME_PARAMS(Original LTE_DL_FRAME_PARAMS)
 
 5/14
-Add:        openair2/Layer2/MAC/defs_nb_iot.h
-Add:        openair2/Layer2/MAC/proto_nb_iot.h
-Add:        openair2/Layer2/MAC/eNB_scheduler_ulsch_nb_iot.c
-Add:        openair2/Layer2/MAC/eNB_scheduler_prmitives_nb_iot.c
-Add:        openair2/Layer2/MAC/eNB_scheduler_dlsch_nb_iot.c
+Add:        openair2/Layer2/MAC/defs_NB_IoT.h
+Add:        openair2/Layer2/MAC/proto_NB_IoT.h
+Add:        openair2/Layer2/MAC/eNB_scheduler_ulsch_NB_IoT.c
+Add:        openair2/Layer2/MAC/eNB_scheduler_prmitives_NB_IoT.c
+Add:        openair2/Layer2/MAC/eNB_scheduler_dlsch_NB_IoT.c
 
 comment:
-Functions: NB_rx_sdu(), NB_get_dci_sdu(), NB_rrc_mac_remove_ue(), NB_get_dlsch_sdu();
+Functions: rx_sdu_NB_IoT(), get_dci_sdu_NB_IoT(), rrc_mac_remove_ue_NB_IoT(), get_dlsch_sdu_NB_IoT();
 Parameters: All parameters/structures used in MAC Layer.
 
 5/15
-Add:        openair2/Layer2/MAC/eNB_scheduler_RA_nb_iot.c
+Add:        openair2/Layer2/MAC/eNB_scheduler_RA_NB_IoT.c
 
 comment:
-Functions: NB_initiate_ra_proc()
+Functions: initiate_ra_proc_NB_IoT()
 
 5/15
-modified:   openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h
+modified:   openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h
 modified:   openair1/PHY/LTE_TRANSPORT/defs.hod
-modified:   openair2/LAYER2/MAC/eNB_scheduler_RA_nb_iot.c
-modified:   openair2/LAYER2/MAC/proto_nb_iot.h
+modified:   openair2/LAYER2/MAC/eNB_scheduler_RA_NB_IoT.c
+modified:   openair2/LAYER2/MAC/proto_NB_IoT.h
 
 comment:
-Functions: NB_schedule_RA()
+Functions: schedule_RA_NB_IoT()
 Parameters: Add DCI unpacked format 
 
 5/16
-Add:	    openair2/LAYER2/MAC/IF_Module_nb_iot.c
-Add:        openair2/PHY_INTERFACE/IF_Module_nb_iot.h
-Add:        openair1/PHY/sched/phy_procedures_lte_eNB_nb_iot.c
+Add:	    openair2/LAYER2/MAC/IF_Module_NB_IoT.c
+Add:        openair2/PHY_INTERFACE/IF_Module_NB_IoT.h
+Add:        openair1/PHY/sched/phy_procedures_lte_eNB_NB_IoT.c
 
 Comment: Modify NB_phy_procedures_uespec_RX, change the way using primitive, use UL_IND data structure to store the needed parameters.
 	 Add the implementation for UL_INDICATION, it handles the Uplink information from PHY, also trigger the scheduler.
@@ -50,9 +50,9 @@ Functions: NB_phy_procedures_uespec_RX(), UL_INDICATION()
 Parameters: UL_IND for Interface Module
 
 5/18
-Modified:   openair1/PHY/LTE_TRANSPORT/dci_nb_iot.h
-Modified:   openair2/PHY_INTERFACE/IF_Module_nb_iot.h
-Modified:   openair2/LAYER2/MAC/IF_Module_nb_iot.c
+Modified:   openair1/PHY/LTE_TRANSPORT/dci_NB_IoT.h
+Modified:   openair2/PHY_INTERFACE/IF_Module_NB_IoT.h
+Modified:   openair2/LAYER2/MAC/IF_Module_NB_IoT.c
 
 Comment: Complete the UL_INDICATION
 Functions: UL_INDICATION()
@@ -62,3 +62,32 @@ Parameters: Sched_Rsp for Interface Module
 
 Comment: 15 warnings fixed 
 
+5/23
+Add:        openair1/PHY/LTE_TRANSPORT/defs_NB_IoT.h
+Modified:   openair2/PHY_INTERFACE/IF_Module_NB_IoT.h
+Modified:   openair1/Sched/phy_procedures_lte_eNB_NB_IoT.c
+
+Comment: merge with RRC branch, start the TX part implementation
+
+5/27
+Modified:   openair2/LAYER2/MAC/phy_procedures_lte_eNB_NB_IoT.c
+
+Comment: Complete the TX part, add the NB_generate_eNB_dlsch_params and NB_generate_eNB_ulsch_params
+	 	 Since original OAI packed the DCI in MAC, and unpack at PHY to apply the physical layer configuration.
+         so we'll apply the configuration and pack the DCI at the same time.
+5/31
+
+Comment: Complete the dci_tools the part configuring the PHY and do the pack of dci at the same times.
+		 Add DCI packed format in dci_NB_IoT.h
+
+6/6
+
+Comment: Update the IF Module header file to fit the FAPI structure and types.
+
+6/15
+
+Comment: New RXTX defined for NB-IoT, use the FAPI parameters adapting to the physical layer parameters.
+
+7/11
+
+Comment: start MAC scheduler implementation
\ No newline at end of file
diff --git a/targets/COMMON/openairinterface5g_limits.h b/targets/COMMON/openairinterface5g_limits.h
index d5a3b7f61c10d97699879d8f90b9e6d7ce818e10..3a79514afbbe20be5dabadcce4660f7229fb31de 100644
--- a/targets/COMMON/openairinterface5g_limits.h
+++ b/targets/COMMON/openairinterface5g_limits.h
@@ -27,4 +27,7 @@
 #        endif
 #endif
 
+
+#define NUMBER_OF_UE_MAX_NB_IoT 16
+
 #endif /* OPENAIRINTERFACE5G_LIMITS_H_ */
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.nbiot.bandxxx.generic.config b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.nbiot.bandxxx.generic.config
new file mode 100644
index 0000000000000000000000000000000000000000..9c52d47a7a3456e3f1df43068db100a29e29f864
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.nbiot.bandxxx.generic.config
@@ -0,0 +1,219 @@
+Active_eNBs = ( "eNB_Eurecom_LTE_NB_IoT_Box");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+eNBs =
+(
+ {
+    ////////// Identification parameters:
+    eNB_ID    =  0xe00;
+    
+    cell_type =  "CELL_MACRO_ENB";
+    
+    eNB_name  =  "eNB_Eurecom_LTE_NB_IoT_Box";
+    
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  "1";
+    
+    mobile_country_code =  "208";
+    
+    mobile_network_code =  "92";
+    
+       ////////// Physical parameters:
+  
+    component_carriers = (
+    		       	 {
+                           node_function                                        = "eNodeB_3GPP";
+	                   	   node_timing                                          = "synch_to_ext_device";
+	           	           node_synch_ref                                       = 0;
+  			               frame_type					      	= "FDD";
+	
+			//TDD config should be not used for NB-IoT
+			/*
+                           tdd_config 					      	= 3;
+                           tdd_config_s            			      	= 0;
+			*/
+
+			   #NORMAL cyclic prefix should be applied for DL frame
+ 			   prefix_type             			     	= "NORMAL";
+			   #set of allowed bands TS 36.104: 1,2,3,5,8,11,12,13,17,18,19,20,25,26,28,31,66,70 
+  			   eutra_band              			      	= 3;
+                           downlink_frequency      			      	= ;
+                           uplink_frequency_offset 			      	= ; //shuld be the duplexing gap??
+  			   Nid_cell					      	= 0;
+                           N_RB_DL                 			      	= 1;//only 1 RB assigned for NB_IoT
+               #it is also needed to know the NRB_DL and NRB_UL of LTE when we are in in-band and guard band mode
+               #it is also needed the PRB index choosen for NB-IoT depending on the LTE bandwidht we are using (only specific indexes are allowed)
+                           nb_antennas_tx          			      	= 1;
+                           nb_antennas_rx          			      	= 1; 
+			   tx_gain                                            	= 25;
+			   rx_gain                                           	= 20;
+
+                           nprach_CP_length              		      	= ;
+			   #OPTIONAL (rsrp_thresholdsNPRACH)
+                           rsrp_range      			      	      	= ;
+                           nprach_Periodicity      				= ;
+  	                   nprach_StartTime 			      		= ;
+                           nprach_SubcarrierOffset       			= ;
+			   nprach_NumSubcarriers_r13       			= ;
+                           nprach_SubcarrierMSG3_RangeStart           	        = ;
+                           maxNumPreambleAttemptCE            			= ;
+                           numRepetitionsPerPreambleAttempt             	= ;
+
+                           npdcch_NumRepetitions_RA 			        = ;
+                           npdcch_StartSF_CSS_RA                  	  	= ;
+                           npdcch_Offset_RA                 			= ;
+ 
+                           npdsch_nrs_Power          			      	= ;
+
+			   ACK_NACK_NumRepetitions_NB                           = ;
+			   threeTone_CyclicShift                                = ;
+     	                   sixTone_CyclicShift  			      	= ;
+	                   pusch_groupAssignment      			      	= ;
+			//OPTIONAL
+			   srs_SubframeConfig					= ;
+	                   threeTone_BaseSequence		   	      	= ;
+	                   sixTone_BaseSequence                                 = ;
+	                   twelveTone_BaseSequence                              = ;
+
+			//OPTIONAL
+	                   dl_GapThreshold                                     	= ;
+	                   dl_GapPeriodicity                                    = ;
+	                   dl_GapDurationCoeff                                	= ;
+			
+			//ULPowerControlCommon
+	                   p0_NominalNPUSCH                                     = ; 
+	                   alpha_r13                                            = ;
+	                   deltaPreambleMsg3                                    = ;
+	                   msg3_delta_Preamble                                  = ;
+
+	
+                           preambleTransMax_CE                          	= ;
+                           powerRampingStep                         		= ;
+                           preambleInitialReceivedTargetPower                   = ;
+                           ra_ResponseWindowSize                             	= ;
+                           mac_ContentionResolutionTimer                      	= ; 
+			 //OPTIONAL
+                           connEstFailOffset                              	= ;
+
+			   ue_TimersAndConstants_t300			      	= 1000;
+			   ue_TimersAndConstants_t301			     	= 1000;
+			   ue_TimersAndConstants_t310			      	= 1000;
+			   ue_TimersAndConstants_t311			      	= 10000;
+			   ue_TimersAndConstants_n310			      	= 20;
+			   ue_TimersAndConstants_n311			      	= 1;
+
+
+			///freqInfo
+                  	   additionalSpectrumEmission				= ;
+			//OPTIONAL   
+			   carrierFreq						= ;
+			   carrierFreqOffset					= ;
+
+			///multiBandInfoList(OPTIONAL)
+			   AdditionalSpectrumEmission_t				= ;
+
+			   ue_TransmissionMode                                	= 1;
+			 }
+			 );
+
+
+
+    #Default SRB1-NB configuration for RLC (same as for SIB1bis)
+    srb1_NB_parameters : 
+    {
+
+	#NOTE: "N/A" means that the UE does not apply a specific value (E-UTRAN can not assume the UE to keeps the previously configured value upon switching to a default configuration
+
+        # timer_poll_retransmit = (ms) [250, 500, 1000,..., 4000, 6000, 10000, 15000, 25000,...] TS 36.331 v14.2.0 pag 616 
+        timer_poll_retransmit    = 25000;
+        
+	//OPTIONAL
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = N/A;
+        
+	//OPTIONAL
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = N/A;
+        
+	//OPTIONAL
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  N/A;
+        
+	//OPTIONAL
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  N/A;
+        
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+
+	#enableStatusReportSN_Gap = ENUMERATED {TRUE} (Enable the status reporting due to detection of reception failure)
+	enableStatusReportSN_Gap = "DISABLE"
+    }
+    
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+        
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.13.11";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES : 
+    {
+        ENB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.13.10/24";
+
+        ENB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        ENB_IPV4_ADDRESS_FOR_S1U                 = "192.168.13.10/24";
+        ENB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+ /*
+    otg_config = (
+    	         {	      	
+    	      	 ue_id				=1;
+	     	 app_type			="scbr";
+	      	 bg_traffic			="disable";
+	      	 },
+	      	 {	      	
+    	      	 ue_id				=2;
+	      	 app_type			="bcbr";
+	      	 bg_traffic			="enable";
+	      	 }
+	      );
+*/
+    log_config : 
+    {
+	global_log_level                      ="info"; 
+    	global_log_verbosity                  ="medium";
+	hw_log_level                          ="debug"; 
+    	hw_log_verbosity                      ="medium";
+	phy_log_level                         ="info"; 
+    	phy_log_verbosity                     ="medium";
+	mac_log_level                         ="info"; 
+    	mac_log_verbosity                     ="high";
+	rlc_log_level                         ="info"; 
+    	rlc_log_verbosity                     ="medium";
+	pdcp_log_level                        ="info"; 
+    	pdcp_log_verbosity                    ="medium";
+	rrc_log_level                         ="debug"; 
+    	rrc_log_verbosity                     ="medium";
+	gtpu_log_level                         ="error"; 
+    	gtpu_log_verbosity                     ="medium";
+	udp_log_level                         ="error"; 
+    	udp_log_verbosity                     ="medium";
+	osa_log_level                         ="warn"; 
+    	osa_log_verbosity                     ="low";
+
+   };	
+   
+  }
+);
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 5cbe0fe1d4d2bb40bfd20c34512c0413d83234c3..ee9f6c610a4b4b25919d48197718e6b860b29631 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -71,6 +71,12 @@
 
 #include "../../SIMU/USER/init_lte.h"
 
+//NB-IoT 
+#include "PHY/defs_NB_IoT.h"
+#include "SCHED/defs_NB_IoT.h"
+#include "PHY_INTERFACE/IF_Module_NB_IoT.h"
+#include "LAYER2/MAC/extern_NB_IoT.h"
+#include "PHY/extern_NB_IoT.h"
 #include "LAYER2/MAC/defs.h"
 #include "LAYER2/MAC/extern.h"
 #include "LAYER2/MAC/proto.h"
@@ -571,6 +577,58 @@ int wait_CCs(eNB_rxtx_proc_t *proc) {
   return(0);
 }
 
+
+/*NB-IoT rxtx
+ *
+ * IMPORTANT When we run the rxtx thread for NB-IoT we should not run at the same time otherwise we fill the same buffers in PHY_Vars_eNB
+ *
+ * For the moment the NB-IoT implementation foresees a single thread implementation
+ * */
+static inline int rxtx_NB_IoT(PHY_VARS_eNB_NB_IoT *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {
+
+  //Allocate memory for the structures used by PHY and MAC
+  UL_IND_t *UL_INFO;
+  Sched_Rsp_t *Sched_Rsp; 
+
+  UL_INFO = (UL_IND_t*) malloc(sizeof(UL_IND_t));
+  Sched_Rsp = (Sched_Rsp_t*) malloc(sizeof(Sched_Rsp_t)); 
+
+  start_meas(&softmodem_stats_rxtx_sf);
+
+  // ****************************************
+  // Common RX procedures subframe n
+
+  if ((eNB->do_prach)&&((eNB->node_function != NGFI_RCC_IF4p5_NB_IoT)))
+    eNB->do_prach(eNB,proc->frame_rx,proc->subframe_rx);
+  
+  /*UE-specific RX processing for subframe n*/
+
+
+  /*
+   * stored the Upink information in UL_info struct, process it and made it into FAPI style,
+   */
+
+  phy_procedures_eNB_uespec_RX_NB_IoT(eNB,proc,UL_INFO);
+
+  /*
+   * send the UL_Indication to higher layer that also provide a tick to the scheduler_dlsch_ulsch
+   * (on its turn the scheduler will trigger the phy_procedure_eNB_TX through schedule_responce function
+   */
+
+  if(if_inst->UL_indication) if_inst->UL_indication(UL_INFO);
+  
+
+  if (oai_exit) return(-1);
+  
+  
+  if (release_thread(&proc->mutex_rxtx,&proc->instance_cnt_rxtx,thread_name)<0) return(-1);
+
+  stop_meas( &softmodem_stats_rxtx_sf );
+  
+  return(0);
+}
+
+
 static inline int rxtx(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc, char *thread_name) {
 
   start_meas(&softmodem_stats_rxtx_sf);
@@ -613,8 +671,12 @@ static void* eNB_thread_rxtx( void* param ) {
   static int eNB_thread_rxtx_status;
 
   eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param;
+  eNB_rxtx_proc_NB_IoT_t *proc_NB_IoT = (eNB_rxtx_proc_NB_IoT_t*)param;  // to remove when eNB_thread_rxtx_status is duplicated for NB-IoT
+
   PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
 
+  PHY_VARS_eNB_NB_IoT *eNB_NB_IoT = PHY_vars_eNB_NB_IoT_g[0][proc_NB_IoT->CC_id]; // to remove when eNB_thread_rxtx_status is duplicated for NB-IoT
+
   char thread_name[100];
 
 
@@ -637,7 +699,13 @@ static void* eNB_thread_rxtx( void* param ) {
     if (oai_exit) break;
 
     if (eNB->CC_id==0)
+    {
+#ifdef NB_IOT
+      if(rxtx_NB_IoT(eNB_NB_IoT, proc_NB_IoT,thread_name)<0) break;
+#else
       if (rxtx(eNB,proc,thread_name) < 0) break;
+#endif
+    }
 
   } // while !oai_exit
 
@@ -1195,6 +1263,7 @@ void rx_fh_slave(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
 
 int wakeup_rxtx(eNB_proc_t *proc,eNB_rxtx_proc_t *proc_rxtx,LTE_DL_FRAME_PARMS *fp) {
 
+
   int i;
   struct timespec wait;
   
@@ -1530,10 +1599,12 @@ static void* eNB_thread_single( void* param ) {
 
   static int eNB_thread_single_status;
 
-  eNB_proc_t *proc = (eNB_proc_t*)param;
-  eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
+  eNB_proc_t             *proc = (eNB_proc_t*)param;
+  eNB_rxtx_proc_t        *proc_rxtx = &proc->proc_rxtx[0];
   PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
+  PHY_VARS_eNB_NB_IoT *eNB_NB_IoT = PHY_vars_eNB_NB_IoT_g[0][proc->CC_id];
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+  NB_IoT_DL_FRAME_PARMS *fp_NB_IoT = &eNB_NB_IoT->frame_parms;
   eNB->CC_id =  proc->CC_id;
 
   void *rxp[2],*rxp2[2];
@@ -1685,6 +1756,7 @@ static void* eNB_thread_single( void* param ) {
     wakeup_slaves(proc);
 
     if (rxtx(eNB,proc_rxtx,"eNB_thread_single") < 0) break;
+    if (rxtx_NB_IoT(eNB_NB_IoT,proc_rxtx,"eNB_thread_single") < 0) break;
   }
   
 
@@ -1695,10 +1767,13 @@ static void* eNB_thread_single( void* param ) {
 
 }
 
+
+
+
 extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
-extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
+/*extern void init_td_thread(PHY_VARS_eNB *, pthread_attr_t *);
 extern void init_te_thread(PHY_VARS_eNB *, pthread_attr_t *);
-
+*/
 void init_eNB_proc(int inst) {
   
   int i=0;
@@ -1768,6 +1843,7 @@ void init_eNB_proc(int inst) {
 #endif
 
     if (eNB->single_thread_flag==0) {
+      //the two threads that manage tw consecutive subframes
       pthread_create( &proc_rxtx[0].pthread_rxtx, attr0, eNB_thread_rxtx, &proc_rxtx[0] );
       pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
       pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc );
@@ -1775,8 +1851,10 @@ void init_eNB_proc(int inst) {
     else {
       pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc);
       init_fep_thread(eNB,attr_fep);
+      /*
       init_td_thread(eNB,attr_td);
       init_te_thread(eNB,attr_te);
+      */
     }
     pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc );
     pthread_create( &proc->pthread_synch, attr_synch, eNB_thread_synch, eNB);
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 68fcbc49d5eb2e88dec2d63221044b53c2b5505f..c33a91c6f412336e679ad0e691e5ece3dd7f2bc0 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -49,8 +49,16 @@
 #include "LAYER2/MAC/defs.h"
 #include "LAYER2/MAC/vars.h"
 #include "LAYER2/MAC/proto.h"
+
 #include "RRC/LITE/vars.h"
 #include "PHY_INTERFACE/vars.h"
+#include "PHY_INTERFACE/defs.h"
+
+//NB-IoT Parameters here
+
+#include "LAYER2/MAC/proto_NB_IoT.h"
+//#include "LAYER2/MAC/defs_NB_IoT.h"
+//#include "LAYER2/MAC/vars_NB_IoT.h"
 
 #ifdef SMBV
 #include "PHY/TOOLS/smbv.h"
@@ -167,6 +175,9 @@ int                             otg_enabled;
 //int                             number_of_cards =   1;
 
 static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
+//NB-IoT
+static NB_IoT_DL_FRAME_PARMS *frame_parms_NB_IoT[MAX_NUM_CCs]; // this will be still inside the PHY_VARS of LTE
+
 eNB_func_t node_function[MAX_NUM_CCs];
 eNB_timing_t node_timing[MAX_NUM_CCs];
 int16_t   node_synch_ref[MAX_NUM_CCs];
@@ -1254,6 +1265,52 @@ void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
 
 }
 
+//NB_IoT-------------------------------------------------
+void set_default_frame_parms_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
+void set_default_frame_parms_NB_IoT(NB_IoT_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
+
+    int CC_id;
+
+    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+        frame_parms[CC_id] = (NB_IoT_DL_FRAME_PARMS*) malloc(sizeof(NB_IoT_DL_FRAME_PARMS));
+        /* Set some default values that may be overwritten while reading options */
+
+        //XXX check if there are other parameters to be set
+
+        frame_parms[CC_id]->Ncp                 = NORMAL;
+        frame_parms[CC_id]->Ncp_UL              = NORMAL;
+        frame_parms[CC_id]->Nid_cell            = 0;
+        frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
+        frame_parms[CC_id]->nb_antennas_tx      = 1;
+        frame_parms[CC_id]->nb_antennas_rx      = 1;
+
+        frame_parms[CC_id]->nushift             = 0;
+
+        // UL RS Config
+        frame_parms[CC_id]->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupHoppingEnabled = 0;
+        frame_parms[CC_id]->npusch_config_common.ul_ReferenceSignalsNPUSCH.groupAssignmentNPUSCH = 0;
+
+
+        //frame_parms[CC_id]->nprach_config_common.nprach_CP_Length
+		//frame_parms[CC_id]->nprach_config_common.nprach_ParametersList.list.array[CC_id]
+		//frame_parms[CC_id]->nprach_config_common.rsrp_ThresholdsPrachInfoList
+
+
+		//already initialized in the set_default_frame_parms function for LTE
+
+//        downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
+//        downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
+//        downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
+//        downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
+//        //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
+
+    }
+
+}
+
+
+
+
 void init_openair0(void);
 
 void init_openair0() {
@@ -1393,6 +1450,10 @@ int main( int argc, char **argv ) {
     // set default parameters
     set_default_frame_parms(frame_parms);
 
+    set_default_frame_parms_NB_IoT(frame_parms_NB_IoT);
+
+
+
     // initialize logging
     logInit();
 
@@ -1534,8 +1595,19 @@ int main( int argc, char **argv ) {
       frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
 
       LOG_I(PHY,"Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms[CC_id]->nb_antennas_rx, frame_parms[CC_id]->nb_antennas_tx);
+
+#ifdef NB_IOT
+      frame_parms_NB_IoT[CC_id]->nb_antennas_tx     = nb_antenna_tx;
+      frame_parms_NB_IoT[CC_id]->nb_antennas_rx     = nb_antenna_rx;
+      frame_parms_NB_IoT[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
+
+      LOG_I(PHY,"[NB-IoT] Set nb_rx_antenna %d , nb_tx_antenna %d \n",frame_parms_NB_IoT[CC_id]->nb_antennas_rx, frame_parms_NB_IoT[CC_id]->nb_antennas_tx);
+
+#endif
     }
 
+
+    //XXXX we need to modify it for NB-IoT????
     init_ul_hopping(frame_parms[CC_id]);
     init_frame_parms(frame_parms[CC_id],1);
     //   phy_init_top(frame_parms[CC_id]);
@@ -1620,11 +1692,18 @@ int main( int argc, char **argv ) {
         //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_poHwer,tx_max_power));
     } else {
         //this is eNB
-        PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**));
+        PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**)); //global PHY_vars --> is a matrix
         PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*));
 
         for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+        	//we initialiaze DL/UL buffer and HARQ (inside the LTE_eNB_DLSCH)
+
             PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,frame_parms[CC_id]->Nid_cell,node_function[CC_id],abstraction_flag);
+            //this is a complementary function for just initialize manage NB_ioT stuff inside the PHY_Vars
+#ifdef NB_IOT
+            //init_lte_eNB_NB(PHY_vars_eNB_g[0][CC_id],frame_parms_NB_IoT[CC_id], 0, frame_parms_NB_IoT[CC_id]->Nid_cell,node_function[CC_id],abstraction_flag);
+#endif
+
             PHY_vars_eNB_g[0][CC_id]->ue_dl_rb_alloc=0x1fff;
             PHY_vars_eNB_g[0][CC_id]->target_ue_dl_mcs=target_dl_mcs;
             PHY_vars_eNB_g[0][CC_id]->ue_ul_nb_rb=6;
@@ -1656,6 +1735,7 @@ int main( int argc, char **argv ) {
                 }
             }
 
+            //TODO: this is different for NB-IoT
             compute_prach_seq(&PHY_vars_eNB_g[0][CC_id]->frame_parms.prach_config_common,
                               PHY_vars_eNB_g[0][CC_id]->frame_parms.frame_type,
                               PHY_vars_eNB_g[0][CC_id]->X_u);
@@ -1736,11 +1816,26 @@ int main( int argc, char **argv ) {
 
     int eMBMS_active=0;
     if (node_function[0] <= NGFI_RAU_IF4p5) { // don't initialize L2 for RRU
+
+        // MP, Nick: Initialization of IF module for NB-IoT should be here
+
+        	if_inst = malloc(sizeof(IF_Module_t));
+        	LOG_I(PHY,"Allocate IF-Module for NB-IoT\n");
+
+        //---------------------------
+
         LOG_I(PHY,"Intializing L2\n");
+
         mac_xface = malloc(sizeof(MAC_xface));
         l2_init(frame_parms[0],eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
                 0,// cba_group_active
                 0); // HO flag
+
+//initialize L2 for NB-IoT stuff (complementary to legacy OAI initialization)
+
+        l2_init_eNB_NB_IoT();
+
+
         mac_xface->macphy_exit = &exit_fun;
     } else if (node_function[0] == NGFI_RRU_IF4p5) { // Initialize PRACH in this case
 
@@ -1848,6 +1943,13 @@ int main( int argc, char **argv ) {
             PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
         }
     } else {
+
+#ifdef NB_IOT
+        printf("Initializing IF Module in PHY layer\n");
+        //register function
+        IF_Module_init_L1();
+#endif
+
         printf("Initializing eNB threads\n");
         init_eNB(node_function,node_timing,1,eth_params,single_thread_flag,wait_for_sync);
 
diff --git a/targets/SIMU/USER/init_lte.c b/targets/SIMU/USER/init_lte.c
index 3baf8fdad66b285b0019d4e7fb08cad62a499c4a..5574b1cf50bf9a538dcfc16fa5802b8465687325 100644
--- a/targets/SIMU/USER/init_lte.c
+++ b/targets/SIMU/USER/init_lte.c
@@ -148,6 +148,100 @@ PHY_VARS_eNB* init_lte_eNB(LTE_DL_FRAME_PARMS *frame_parms,
   return (PHY_vars_eNB);
 }
 
+
+
+/*this is a function just for initialization of NB-IoT stuff*/
+
+/*
+
+void init_lte_eNB_NB(
+					PHY_VARS_eNB  *PHY_vars_eNB,
+					NB_IoT_DL_FRAME_PARMS *frame_parms,
+                    uint8_t eNB_id,
+                    uint8_t Nid_cell,
+				    eNB_func_t node_function,
+                    int8_t abstraction_flag)
+{
+
+  int i,j;
+
+  memset(PHY_vars_eNB,0,sizeof(PHY_VARS_eNB));
+  PHY_vars_eNB->Mod_id=eNB_id;
+  PHY_vars_eNB->cooperation_flag=0;//cooperation_flag;
+  memcpy(&(PHY_vars_eNB->frame_parms_nb_iot), frame_parms, sizeof(NB_IoT_DL_FRAME_PARMS));
+  PHY_vars_eNB->frame_parms_nb_iot.Nid_cell = ((Nid_cell/3)*3)+((eNB_id+Nid_cell)%3); //XXX NB_IoT ????
+  PHY_vars_eNB->frame_parms_nb_iot.nushift = PHY_vars_eNB->frame_parms.Nid_cell%6;
+  phy_init_lte_eNB(PHY_vars_eNB,0,abstraction_flag);
+
+  LOG_I(PHY,"init eNB NB_IoT: Node Function %d\n",node_function);
+  LOG_I(PHY,"init eNB NB_IoT: Nid_cell %d\n", frame_parms->Nid_cell);
+  LOG_I(PHY,"init eNB NB_IoT: number of ue max %d number of enb max %d \n",
+        NUMBER_OF_UE_MAX, NUMBER_OF_eNB_MAX);
+ //LOG_I(PHY,"init eNB NB_IoT: N_RB_DL %d\n", frame_parms->N_RB_DL);
+  //LOG_I(PHY,"init eNB NB_IoT: prach_config_index %d\n", frame_parms->nprach_config_common.prach_ConfigInfo.prach_ConfigIndex);
+
+  if (node_function >= NGFI_RRU_IF5)
+    // For RRU, don't allocate DLSCH/ULSCH Transport channel buffers
+    return;
+
+
+
+
+  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
+    LOG_I(PHY,"[NB-IoT] Allocating Transport Channel Buffers for NDLSCH, UE %d\n",i);
+      PHY_vars_eNB->ndlsch[i] = new_eNB_dlsch_NB_IoT(NSOFT,abstraction_flag,frame_parms);
+      if (!PHY_vars_eNB->ndlsch[i]) {
+	LOG_E(PHY,"Can't get eNB ndlsch structures for UE %d \n", i);
+	exit(-1);
+      } else {
+	LOG_D(PHY,"dlsch[%d] => %p\n",i,PHY_vars_eNB->ndlsch[i]);
+	PHY_vars_eNB->ndlsch[i]->rnti=0;
+      }
+
+
+    LOG_I(PHY," [NB-IoT] Allocating Transport Channel Buffer for ULSCH, UE %d\n", i);
+    PHY_vars_eNB->nulsch[1+i] = new_eNB_ulsch_NB(abstraction_flag);
+
+    if (!PHY_vars_eNB->nulsch[1+i]) {
+      LOG_E(PHY,"Can't get eNB nulsch structures\n");
+      exit(-1);
+    }
+  }
+
+  // ULSCH for RA
+  PHY_vars_eNB->nulsch[0] = new_eNB_ulsch_NB(abstraction_flag);
+
+  if (!PHY_vars_eNB->nulsch[0]) {
+    LOG_E(PHY,"Can't get eNB nulsch structures\n");
+    exit(-1);
+  }
+  PHY_vars_eNB->dlsch_SI_NB  = new_eNB_dlsch_NB_IoT(NSOFT, abstraction_flag, frame_parms);
+  LOG_D(PHY,"[NB-IoT] eNB %d : SI %p\n",eNB_id,PHY_vars_eNB->dlsch_SI_NB);
+  PHY_vars_eNB->dlsch_ra_NB  = new_eNB_dlsch_NB_IoT(NSOFT, abstraction_flag, frame_parms);
+  LOG_D(PHY,"[NB-IoT] eNB %d : RA %p\n",eNB_id,PHY_vars_eNB->dlsch_ra_NB);
+
+
+  //already set in the LTE function version
+  //PHY_vars_eNB->rx_total_gain_dB=130;
+
+//  for(i=0; i<NUMBER_OF_UE_MAX; i++)
+//  PHY_vars_eNB->mu_mimo_mode[i].dl_pow_off = 2;
+//
+//  PHY_vars_eNB->check_for_total_transmissions = 0;
+//
+//  PHY_vars_eNB->check_for_MUMIMO_transmissions = 0;
+//
+//  PHY_vars_eNB->FULL_MUMIMO_transmissions = 0;
+//
+//  PHY_vars_eNB->check_for_SUMIMO_transmissions = 0;
+//
+//    PHY_vars_eNB->frame_parms.pucch_config_common.deltaPUCCH_Shift = 1;
+
+  return;
+}
+
+*/
+
 PHY_VARS_UE* init_lte_UE(LTE_DL_FRAME_PARMS *frame_parms,
                          uint8_t UE_id,
                          uint8_t abstraction_flag)