diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 70c2d88e82e57f101dfe863bb0247474968cc4f8..0dc849d2d643abacdba863b3114777dc353c2823 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1243,6 +1243,12 @@ set(PHY_SRC_UE
   # actual source
   ${OPENAIR1_DIR}/PHY/MODULATION/slot_fep.c
   ${OPENAIR1_DIR}/PHY/INIT/nr_parms.c
+  ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pss_nr.c
+  ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/sss_nr.c
+  ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
+  ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dmrs_nr.c
+  ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
+  ${OPENAIR1_DIR}/PHY/NR_REFSIG/ul_ref_seq_nr.c
   ${OPENAIR1_DIR}/PHY/TOOLS/file_output.c
   ${OPENAIR1_DIR}/PHY/TOOLS/cadd_vv.c
   ${OPENAIR1_DIR}/PHY/TOOLS/lte_dfts.c
@@ -2160,6 +2166,76 @@ target_link_libraries (nr-softmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRY
 target_link_libraries (nr-softmodem ${LIB_LMS_LIBRARIES})
 target_link_libraries (nr-softmodem ${T_LIB})
 
+# nr-uesoftmodem is  UE implementation
+#######################################
+
+add_executable(nr-uesoftmodem
+  ${rrc_h}
+  ${s1ap_h}
+  ${OPENAIR_BIN_DIR}/messages_xml.h
+  ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
+  ${OPENAIR_TARGETS}/RT/USER/nr-ue.c
+  ${OPENAIR_TARGETS}/RT/USER/nr-uesoftmodem.c
+  ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
+  ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
+  ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
+  ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
+  ${OPENAIR_DIR}/common/utils/utils.c
+  ${OPENAIR_DIR}/common/utils/system.c
+  ${XFORMS_SOURCE}
+  ${XFORMS_SOURCE_SOFTMODEM}
+  ${T_SOURCE}
+  ${CONFIG_SOURCES}
+  ${SHLIB_LOADER_SOURCES}
+  )
+
+target_link_libraries (nr-uesoftmodem
+  -Wl,--start-group
+  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_NR_UE PHY_COMMON PHY_UE PHY_RU LFDS L2_UE 
+  ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
+  -Wl,--end-group z dl)
+
+target_link_libraries (nr-uesoftmodem ${LIBXML2_LIBRARIES})
+target_link_libraries (nr-uesoftmodem pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp  ${XFORMS_LIBRARIES} ${PROTOBUF_LIB}  ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
+target_link_libraries (nr-uesoftmodem ${LIB_LMS_LIBRARIES})
+target_link_libraries (nr-uesoftmodem ${T_LIB})
+
+# nr-uesoftmodem is  UE implementation
+#######################################
+
+add_executable(nr-uesoftmodem-nos1
+  ${rrc_h}
+  ${s1ap_h}
+#  ${OPENAIR_BIN_DIR}/messages_xml.h
+  ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
+  ${OPENAIR_TARGETS}/RT/USER/nr-ue.c
+  ${OPENAIR_TARGETS}/RT/USER/nr-uesoftmodem.c
+  ${OPENAIR1_DIR}/SIMULATION/TOOLS/taus.c
+  ${OPENAIR_TARGETS}/COMMON/create_tasks_ue.c
+  ${OPENAIR_TARGETS}/ARCH/COMMON/common_lib.c
+  ${OPENAIR1_DIR}/SIMULATION/ETH_TRANSPORT/netlink_init.c
+  ${OPENAIR3_DIR}/NAS/UE/nas_ue_task.c
+  ${OPENAIR_DIR}/common/utils/utils.c
+  ${OPENAIR_DIR}/common/utils/system.c
+  ${XFORMS_SOURCE}
+  ${XFORMS_SOURCE_SOFTMODEM}
+  ${T_SOURCE}
+  ${CONFIG_SOURCES}
+  ${SHLIB_LOADER_SOURCES}
+  )
+
+target_link_libraries (nr-uesoftmodem-nos1
+  -Wl,--start-group
+  RRC_LIB S1AP_LIB S1AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_RU_LIB SCHED_UE_LIB PHY_NR_UE PHY_COMMON PHY_UE PHY_RU LFDS L2_UE 
+  ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} LFDS7
+  -Wl,--end-group z dl)
+
+target_link_libraries (nr-uesoftmodem-nos1 ${LIBXML2_LIBRARIES})
+target_link_libraries (nr-uesoftmodem-nos1 pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp  ${XFORMS_LIBRARIES} ${PROTOBUF_LIB}  ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES})
+target_link_libraries (nr-uesoftmodem-nos1 ${LIB_LMS_LIBRARIES})
+target_link_libraries (nr-uesoftmodem-nos1 ${T_LIB})
+
 # USIM process
 #################
 #add_executable(usim
diff --git a/openair1/PHY/MODULATION/modulation_UE.h b/openair1/PHY/MODULATION/modulation_UE.h
index 7e2a3c8a27778f75b59866ea60392916baf9c684..92afcea7246f6f8e097cf1ba25b11a5427fd6009 100644
--- a/openair1/PHY/MODULATION/modulation_UE.h
+++ b/openair1/PHY/MODULATION/modulation_UE.h
@@ -23,6 +23,8 @@
 #define __MODULATION_DEFS__H__
 #include "PHY/defs_common.h"
 #include "modulation_common.h"
+#include "PHY/defs_UE.h"
+#include "PHY/defs_nr_UE.h"
 /** @addtogroup _PHY_MODULATION_
  * @{
 */
@@ -46,6 +48,13 @@ int slot_fep(PHY_VARS_UE *phy_vars_ue,
              int no_prefix,
 	     int reset_freq_est);
 
+int slot_fep_pbch(PHY_VARS_NR_UE *phy_vars_ue,
+             unsigned char l,
+             unsigned char Ns,
+             int sample_offset,
+             int no_prefix,
+	     int reset_freq_est);
+
 int slot_fep_mbsfn(PHY_VARS_UE *phy_vars_ue,
                    unsigned char l,
                    int subframe,
diff --git a/openair1/PHY/MODULATION/slot_fep.c b/openair1/PHY/MODULATION/slot_fep.c
index b01979431dcf88212604aa71cf0d0470eb177d06..3b5a2f1840f6e9c240464b35d3bc3c3e26e565f9 100644
--- a/openair1/PHY/MODULATION/slot_fep.c
+++ b/openair1/PHY/MODULATION/slot_fep.c
@@ -20,6 +20,7 @@
  */
 
 #include "PHY/defs_UE.h"
+#include "PHY/defs_nr_UE.h"
 #include "modulation_UE.h"
 #include "PHY/LTE_ESTIMATION/lte_estimation.h"
 
@@ -27,6 +28,207 @@
 
 #define SOFFSET 0
 
+int slot_fep_pbch(PHY_VARS_NR_UE *ue,
+             unsigned char l,
+             unsigned char Ns,
+             int sample_offset,
+             int no_prefix,
+			 int reset_freq_est)
+{
+  NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+  NR_UE_COMMON *common_vars   = &ue->common_vars;
+  uint8_t eNB_id = 0;//ue_common_vars->eNb_id;
+  unsigned char aa;
+  unsigned char symbol = l+((7-frame_parms->Ncp)*(Ns&1)); ///symbol within sub-frame
+  unsigned int nb_prefix_samples = (no_prefix ? 0 : frame_parms->nb_prefix_samples);
+  unsigned int nb_prefix_samples0 = (no_prefix ? 0 : frame_parms->nb_prefix_samples0);
+  unsigned int subframe_offset;//,subframe_offset_F;
+  unsigned int slot_offset;
+  int i;
+  unsigned int frame_length_samples = frame_parms->samples_per_subframe * 10;
+  unsigned int rx_offset;
+
+  /*LTE_UE_DLSCH_t **dlsch_ue = phy_vars_ue->dlsch_ue[eNB_id];
+  unsigned char harq_pid = dlsch_ue[0]->current_harq_pid;
+  LTE_DL_UE_HARQ_t *dlsch0_harq = dlsch_ue[0]->harq_processes[harq_pid];
+  int uespec_pilot[9][1200];*/
+
+  void (*dft)(int16_t *,int16_t *, int);
+  int tmp_dft_in[2048] __attribute__ ((aligned (32)));  // This is for misalignment issues for 6 and 15 PRBs
+
+  switch (frame_parms->ofdm_symbol_size) {
+  case 128:
+    dft = dft128;
+    break;
+
+  case 256:
+    dft = dft256;
+    break;
+
+  case 512:
+    dft = dft512;
+    break;
+
+  case 1024:
+    dft = dft1024;
+    break;
+
+  case 1536:
+    dft = dft1536;
+    break;
+
+  case 2048:
+    dft = dft2048;
+    break;
+
+  default:
+    dft = dft512;
+    break;
+  }
+
+  if (no_prefix) {
+    subframe_offset = frame_parms->ofdm_symbol_size * frame_parms->symbols_per_tti * (Ns>>1);
+    slot_offset = frame_parms->ofdm_symbol_size * (frame_parms->symbols_per_tti>>1) * (Ns%2);
+  } else {
+    subframe_offset = frame_parms->samples_per_tti * (Ns>>1);
+    slot_offset = (frame_parms->samples_per_tti>>1) * (Ns%2);
+  }
+
+  if (l<0 || l>=7-frame_parms->Ncp) {
+    printf("slot_fep: l must be between 0 and %d\n",7-frame_parms->Ncp);
+    return(-1);
+  }
+
+  if (Ns<0 || Ns>=20) {
+    printf("slot_fep: Ns must be between 0 and 19\n");
+    return(-1);
+  }
+
+
+
+  for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
+    memset(&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],0,frame_parms->ofdm_symbol_size*sizeof(int));
+
+    rx_offset = sample_offset + slot_offset + nb_prefix_samples0 + subframe_offset - SOFFSET;
+    // Align with 256 bit
+    //    rx_offset = rx_offset&0xfffffff8;
+
+    if (l==0) {
+
+      if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
+        memcpy((short *)&common_vars->rxdata[aa][frame_length_samples],
+               (short *)&common_vars->rxdata[aa][0],
+               frame_parms->ofdm_symbol_size*sizeof(int));
+
+      if ((rx_offset&7)!=0) {  // if input to dft is not 256-bit aligned, issue for size 6,15 and 25 PRBs
+        memcpy((void *)tmp_dft_in,
+               (void *)&common_vars->rxdata[aa][rx_offset % frame_length_samples],
+               frame_parms->ofdm_symbol_size*sizeof(int));
+        dft((int16_t *)tmp_dft_in,
+            (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
+      } else { // use dft input from RX buffer directly
+#if UE_TIMING_TRACE
+          start_meas(&ue->rx_dft_stats);
+#endif
+
+        dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
+            (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
+#if UE_TIMING_TRACE
+        stop_meas(&ue->rx_dft_stats);
+#endif
+
+      }
+    } else {
+      rx_offset += (frame_parms->ofdm_symbol_size+nb_prefix_samples)*l;// +
+      //                   (frame_parms->ofdm_symbol_size+nb_prefix_samples)*(l-1);
+
+#ifdef DEBUG_FEP
+      //  if (ue->frame <100)
+      LOG_I(PHY,"slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol,
+          nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
+#endif
+
+      if (rx_offset > (frame_length_samples - frame_parms->ofdm_symbol_size))
+        memcpy((void *)&common_vars->rxdata[aa][frame_length_samples],
+               (void *)&common_vars->rxdata[aa][0],
+               frame_parms->ofdm_symbol_size*sizeof(int));
+#if UE_TIMING_TRACE
+      start_meas(&ue->rx_dft_stats);
+#endif
+
+      if ((rx_offset&7)!=0) {  // if input to dft is not 128-bit aligned, issue for size 6 and 15 PRBs
+        memcpy((void *)tmp_dft_in,
+               (void *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
+               frame_parms->ofdm_symbol_size*sizeof(int));
+        dft((int16_t *)tmp_dft_in,
+            (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
+      } else { // use dft input from RX buffer directly
+
+        dft((int16_t *)&common_vars->rxdata[aa][(rx_offset) % frame_length_samples],
+            (int16_t *)&common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].rxdataF[aa][frame_parms->ofdm_symbol_size*symbol],1);
+      }
+#if UE_TIMING_TRACE
+      stop_meas(&ue->rx_dft_stats);
+#endif
+
+
+    }
+
+    #ifdef DEBUG_FEP
+        //  if (ue->frame <100)
+        printf("slot_fep: frame %d: symbol %d rx_offset %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx, symbol,rx_offset);
+    #endif
+  }
+
+  if (ue->perfect_ce == 0) {
+    if ((l==0) || (l==(4-frame_parms->Ncp))) {
+      for (aa=0; aa<frame_parms->nb_antenna_ports_eNB; aa++) {
+
+#ifdef DEBUG_FEP
+        printf("Channel estimation eNB %d, aatx %d, slot %d, symbol %d\n",eNB_id,aa,Ns,l);
+#endif
+#if UE_TIMING_TRACE
+        start_meas(&ue->dlsch_channel_estimation_stats);
+#endif
+      /*  nr_pbch_channel_estimation(ue,eNB_id,0,
+                                  Ns,
+                                  aa,
+                                  l,
+                                  symbol);*/
+      }
+
+
+      // do frequency offset estimation here!
+      // use channel estimates from current symbol (=ch_t) and last symbol (ch_{t-1})
+#ifdef DEBUG_FEP
+      printf("Frequency offset estimation\n");
+#endif
+
+      if (l==(4-frame_parms->Ncp)) {
+
+#if UE_TIMING_TRACE
+          start_meas(&ue->dlsch_freq_offset_estimation_stats);
+#endif
+
+        /*lte_est_freq_offset(common_vars->common_vars_rx_data_per_thread[ue->current_thread_id[Ns>>1]].dl_ch_estimates[0],
+                            frame_parms,
+                            l,
+                            &common_vars->freq_offset,
+			    reset_freq_est);*/
+#if UE_TIMING_TRACE
+        stop_meas(&ue->dlsch_freq_offset_estimation_stats);
+#endif
+
+      }
+    }
+
+  }
+
+#ifdef DEBUG_FEP
+  printf("slot_fep: done\n");
+#endif
+  return(0);
+}
 
 int slot_fep(PHY_VARS_UE *ue,
              unsigned char l,
diff --git a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c
new file mode 100644
index 0000000000000000000000000000000000000000..1a64c8902c9ad89038a9a73e0b92bdf1cdd81e73
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.c
@@ -0,0 +1,234 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/***********************************************************************
+*
+* FILENAME    :  ul_ref_seq_nr.c
+*
+* MODULE      :  generation of uplink reference sequence for nr
+*
+* DESCRIPTION :  function to generate uplink reference sequences
+*                see 3GPP TS 38.211 5.2.2 Low-PAPR sequence generation
+*
+************************************************************************/
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <math.h>
+#include "defs.h"
+
+#define DEFINE_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
+#undef DEFINE_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+
+/*******************************************************************
+*
+* NAME :         base_sequence_less_3_RB
+*
+* PARAMETERS :   M_ZC length of Zadoff Chu sequence
+*                u sequence group number
+*                scaling to apply
+*
+* RETURN :       pointer to generated sequence
+*
+* DESCRIPTION :  base sequence generation of less than 36 elements
+*                see TS 38.211 5.2.2.2 Base sequences of length less than 36
+*
+*********************************************************************/
+
+int16_t *base_sequence_less_than_36(unsigned int M_ZC, unsigned int u, unsigned int scaling)
+{
+  char *phi_table;
+  int16_t *rv_overbar;
+  double x;
+  unsigned int n;
+
+  switch(M_ZC) {
+    case 6:
+      phi_table = (char *)phi_M_ZC_6;
+      break;
+    case 12:
+      phi_table = (char *)phi_M_ZC_12;
+      break;
+    case 18:
+      phi_table = (char *)phi_M_ZC_18;
+      break;
+    case 24:
+      phi_table = (char *)phi_M_ZC_24;
+      break;
+    case 30:
+      break;
+    default:
+      printf("function base_sequence_less_than 36_: unsupported base sequence size : %d \n", M_ZC);
+      assert(0);
+      break;
+  }
+
+  rv_overbar = malloc16(IQ_SIZE*M_ZC);
+
+  if (rv_overbar == NULL) {
+    msg("Fatal memory allocation problem \n");
+    assert(0);
+  }
+
+  if (M_ZC == 30) {
+    for (n=0; n<M_ZC; n++) {
+      x = -(M_PI * (u + 1) * (n + 1) * (n + 2))/(double)31;
+      rv_overbar[2*n]   =(int16_t)(floor(scaling*cos(x)));
+      rv_overbar[2*n+1] =(int16_t)(floor(scaling*sin(x)));
+    }
+  }
+  else {
+    for (n=0; n<M_ZC; n++) {
+      x = (double)phi_table[n + u*M_ZC] * (M_PI/4);
+      rv_overbar[2*n]   = (int16_t)(floor(scaling*cos(x)));
+      rv_overbar[2*n+1] = (int16_t)(floor(scaling*sin(x)));
+    }
+  }
+  return rv_overbar;
+}
+
+/*******************************************************************
+*
+* NAME :         base_sequence_36_or_larger
+*
+* PARAMETERS :   M_ZC length of Zadoff chu sequence
+*                u sequence group number
+*                scaling to apply
+*
+* RETURN :       pointer to generated sequence
+*
+* DESCRIPTION :  base sequence generation of less than 36 elements
+*                5.2.2.1 Base sequences of length 36 or larger
+*
+*********************************************************************/
+
+int16_t *base_sequence_36_or_larger(unsigned int Msc_RS, unsigned int u, unsigned int v, unsigned int scaling)
+{
+  int16_t *rv_overbar;
+  unsigned int N_ZC;
+  double q_overbar, x;
+  unsigned int q,m,n;
+  unsigned int M_ZC = ul_allocated_re[Msc_RS];
+
+  rv_overbar = malloc16(IQ_SIZE*M_ZC);
+  if (rv_overbar == NULL) {
+    msg("Fatal memory allocation problem \n");
+    assert(0);
+  }
+
+  N_ZC = ref_ul_primes[Msc_RS]; /* The length N_ZC is given by the largest prime number such that N_ZC < M_ZC */
+
+  q_overbar = N_ZC * (u+1)/(double)31;
+
+  /*  q = (q_overbar + 1/2) + v.(-1)^(2q_overbar) */
+  if ((((int)floor(2*q_overbar))&1) == 0)
+    q = (int)(floor(q_overbar+.5)) - v;
+  else
+    q = (int)(floor(q_overbar+.5)) + v;
+
+  for (n = 0; n < M_ZC; n++) {
+    m=n%N_ZC;
+    x = (double)q * m * (m+1)/N_ZC;
+    rv_overbar[2*n]   =  (int16_t)(floor(scaling*cos(M_PI*x)));   /* cos(-x) = cos(x) */
+    rv_overbar[2*n+1] = -(int16_t)(floor(scaling*sin(M_PI*x)));   /* sin(-x) = -sin(x) */
+  }
+  return rv_overbar;
+}
+
+/*******************************************************************
+*
+* NAME :         generate_ul_srs_sequences
+*
+* PARAMETERS :   scaling to apply
+*
+* RETURN :       none
+*
+* DESCRIPTION :  uplink reference signal sequences generation
+*                which are Low-PAPR base sequences
+*                see TS 38.211 5.2.2 Low-PAPR sequence generation
+*
+*********************************************************************/
+
+void generate_ul_reference_signal_sequences(unsigned int scaling)
+{
+	unsigned int u,v,Msc_RS;
+
+#if 0
+
+    char output_file[255];
+    char sequence_name[255];
+
+#endif
+
+  for (Msc_RS=0; Msc_RS <= INDEX_SB_LESS_32; Msc_RS++) {
+	v = 0;
+    for (u=0; u < U_GROUP_NUMBER; u++) {
+      rv_ul_ref_sig[u][v][Msc_RS] = base_sequence_less_than_36(ul_allocated_re[Msc_RS], u, scaling);
+#if 0
+      sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
+      sprintf(sequence_name, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
+      printf("u %d Msc_RS %d allocate memory %x of size %d \n", u, Msc_RS, rv_ul_ref_sig[u][v][Msc_RS], (IQ_SIZE* ul_allocated_re[Msc_RS]));
+      write_output(output_file, sequence_name,  rv_ul_ref_sig[u][v][Msc_RS], ul_allocated_re[Msc_RS], 1, 1);
+
+#endif
+    }
+  }
+
+  for (Msc_RS=INDEX_SB_LESS_32+1; Msc_RS < SRS_SB_CONF; Msc_RS++) {
+    for (u=0; u < U_GROUP_NUMBER; u++) {
+      for (v=0; v < V_BASE_SEQUENCE_NUMBER; v++) {
+        rv_ul_ref_sig[u][v][Msc_RS] = base_sequence_36_or_larger(Msc_RS, u, v, scaling);
+#if 0
+        sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
+        sprintf(sequence_name, "rv_seq_%d_%d_%d.m", u, v, ul_allocated_re[Msc_RS]);
+        printf("u %d Msc_RS %d allocate memory %x of size %d \n", u, Msc_RS, rv_ul_ref_sig[u][v][Msc_RS], (IQ_SIZE* ul_allocated_re[Msc_RS]));
+        write_output(output_file, sequence_name,  rv_ul_ref_sig[u][v][Msc_RS], ul_allocated_re[Msc_RS], 1, 1);
+
+#endif
+      }
+    }
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         free_ul_reference_signal_sequences
+*
+* PARAMETERS :   none
+*
+* RETURN :       none
+*
+* DESCRIPTION :  free of uplink reference signal sequences
+*
+*********************************************************************/
+void free_ul_reference_signal_sequences(void)
+{
+  unsigned int u,v,Msc_RS;
+  for (Msc_RS=0; Msc_RS < SRS_SB_CONF; Msc_RS++) {
+    for (u=0; u < U_GROUP_NUMBER; u++) {
+      for (v=0; v < V_BASE_SEQUENCE_NUMBER; v++) {
+        if (rv_ul_ref_sig[u][v][Msc_RS])
+          free16(rv_ul_ref_sig[u][v][Msc_RS],2*sizeof(int16_t)*ul_allocated_re[Msc_RS]);
+      }
+    }
+  }
+}
diff --git a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h
new file mode 100644
index 0000000000000000000000000000000000000000..dd967e8e5e6339478c9287bd1b352c2654042e36
--- /dev/null
+++ b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h
@@ -0,0 +1,271 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/***********************************************************************
+*
+* FILENAME    :  ul_ref_seq_nr.hh
+*
+* MODULE      :  generation of uplink reference sequence for nr
+*
+* DESCRIPTION :  variables to generate sequences with low peak to average power
+*                see 3GPP TS 38.211 5.2.2 Low-PAPR sequence generation
+*
+************************************************************************/
+
+#ifndef LOWPAPR_SEQUENCES_NR_H
+#define LOWPAPR_SEQUENCES_NR_H
+
+#include "PHY/defs_nr_UE.h"
+#include "PHY/types.h"
+
+#include "PHY/NR_REFSIG/ss_pbch_nr.h"
+
+#ifdef DEFINE_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+#define EXTERN
+#define INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+#else
+#define EXTERN  extern
+#endif
+
+/************** DEFINE ********************************************/
+#define U_GROUP_NUMBER               (30)    /* maximum number of sequence-group */
+#define V_BASE_SEQUENCE_NUMBER       (2)     /* maximum number of base sequences */
+#define SRS_SB_CONF                  (71)    /* maximum number of configuration for srs subcarrier allocation */
+
+/************** VARIABLES *****************************************/
+
+#define   INDEX_SB_LESS_32            (4)    /* index of dftsizes array for which subcarrier number is less than 36 */
+
+const uint16_t ul_allocated_re[SRS_SB_CONF]     /* number of uplink allocated resource elements */
+/* this table is derivated from TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration which gives m_SRS_b then all possible values of sequence length is */
+/* M_sc_b_SRS = m_SRS_b * N_SC_RB/K_TC with K_TC = 2 or K_TC = 4  as specified in TS 38.211 6.4.1.4.3 */
+#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+= { /*
+K_TC               3           3           3     3     3     3     3     3     3     3     3     3     3     3     3     3     3     3     3     3
+m_SRS_b            4           8          12    16    20    24    28    32    36    40    44    48    52    56    60    64    68    72    76    80   */
+             6,   12,   18,   24,   30,   36,   48,   60,   72,   84,   96,  108,  120,  132,  144,  156,  168,  180,  192,  204,  216,  228,  240,
+/*
+K_TC         3     3     3     3     3     3     3     3     3     3     3    3      3     3     3     3     3     3     3     3     6     3     3
+m_SRS_b     84    88    92    96   100   104   108   112   116   120   128   132   136   144   152   160   168   176   184   192   100   208   216   */
+           252,  264,  276,  288,  300,  312,  324,  336,  348,  360,  384,  396,  408,  432,  456,  480,  504,  528,  552,  576,  600,  624,  648,
+/*
+K_TC         3     6     3     3     3     3     6     6     6     6     6     6     6     6     6     6     6     6     6     6
+m_SRS_b    224   116,  240   256   264   272   144   152   160   168   176   184   192   208   216   224   240   256   264   272                     */
+           672,  696,  720,  768,  792,  816,  864,  912,  960, 1008, 1056, 1104, 1152, 1248, 1296, 1344, 1440, 1536, 1584, 1632,
+
+/* below numbers have been added just to include all possible lengths already used for lte */
+           540,  900,  972, 1080, 1200,
+}
+#endif
+;
+
+/* table of largest prime number lower than uplink allocated resource elements "ul_allocated_re" */
+const uint16_t ref_ul_primes[SRS_SB_CONF]
+#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+= {
+/*           6,   12,   18,   24,   30,   36,   48,   60,   72,   84,   96,  108,  120,  132,  144,  156,  168,  180,  192,  204,  216,  228,  240,  */
+             5,   11,   17,   23,   29,   31,   47,   59,   71,   83,   89,  107,  113,  127,  139,  151,  167,  179,  191,  199,  211,  227,  239,
+
+/*         252,  264,  276,  288,  300,  312,  324,  336,  348,  360,  384,  396,  408,  432,  456,  480,  504,  528,  552,  576,  600,  624,  648,  */
+           251,  263,  271,  283,  293,  311,  317,  331,  347,  359,  383,  389,  401,  431,  449,  479,  503,  523,  547,  571,  599,  619,  647,
+
+/*         672,  696,  720,  768,  792,  816,  864,  912,  960, 1008, 1056, 1104, 1152, 1248, 1296, 1344, 1440, 1536, 1584, 1632,                    */
+           661,  691,  719,  761,  787,  811,  863,  911,  953,  997, 1051, 1103, 1151, 1237, 1291, 1327, 1439, 1531, 1583, 1627,
+
+/*         540,  900,  972, 1080, 1200,                                                                                                              */
+           523,  887,  971, 1069, 1193,
+}
+#endif
+;
+
+/* Low-PAPR base sequence; see TS 38.211 clause 5.2.2 */
+int16_t  *rv_ul_ref_sig[U_GROUP_NUMBER][V_BASE_SEQUENCE_NUMBER][SRS_SB_CONF];
+
+/* 38.211 table Table 5.2.2.2-1: Definition of phi(n) for M_ZC = 6 */
+const char phi_M_ZC_6[6*U_GROUP_NUMBER]
+#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+= {
+/*        0   1   2   3   4   5  */
+/*  0 */ -3, -1,  3,  3, -1, -3,
+/*  1 */ -3,  3, -1, -1,  3, -3,
+/*  2 */ -3, -3, -3,  3,  1, -3,
+/*  3 */  1,  1,  1,  3, -1, -3,
+/*  4 */  1,  1,  1, -3, -1,  3,
+/*  5 */ -3,  1, -1, -3, -3, -3,
+/*  6 */ -3,  1,  3, -3, -3, -3,
+/*  7 */ -3, -1,  1, -3,  1, -1,
+/*  8 */ -3, -1, -3,  1, -3, -3,
+/*  9 */ -3, -3,  1, -3,  3, -3,
+/* 10 */ -3,  1,  3,  1, -3, -3,
+/* 11 */ -3, -1, -3,  1,  1, -3,
+/* 12 */  1,  1,  3, -1, -3,  3,
+/* 13 */  1,  1,  3,  3, -1,  3,
+/* 14 */  1,  1,  1, -3,  3, -1,
+/* 15 */ -1,  1,  1, -1,  3, -3,
+/* 16 */ -3, -1, -1, -1,  3, -1,
+/* 17 */ -3, -3, -1,  1, -1, -3,
+/* 18 */ -3, -3, -3,  1, -3, -1,
+/* 19 */ -3,  1,  1, -3, -1, -3,
+/* 20 */ -3,  3, -3,  1,  1, -3,
+/* 21 */ -3,  1, -3, -3, -3, -1,
+/* 22 */  1,  1, -3,  3,  1,  3,
+/* 23 */  1,  1, -3, -3,  1, -3,
+/* 24 */  1,  1,  3, -1,  3,  3,
+/* 25 */  1,  1, -3,  1,  3,  3,
+/* 26 */  1,  1, -1, -1,  3, -1,
+/* 27 */  1,  1, -1,  3, -1, -1,
+/* 28 */  1,  1, -1,  3, -3, -1,
+/* 29 */  1,  1, -3,  1, -1, -1,
+}
+#endif
+;
+/* Table 5.2.2.2-2: Definition of phi ( n ) for M ZC = 12  */
+const char phi_M_ZC_12[12*U_GROUP_NUMBER]
+#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+= {
+/*        0   1   2   3   4   5   6   7   8   9  10  11  */
+/* 0  */  1, -1,  3,  1,  1, -1, -1, -1,  1,  3, -3,  1,
+/* 1  */ -1, -1, -1, -1,  1, -3, -1,  3,  3, -1, -3,  1,
+/* 2  */ -3,  1, -3, -3, -3,  3, -3, -1,  1,  1,  1, -3,
+/* 3  */ -3,  3,  1,  3, -3,  1,  1,  1,  1,  3, -3,  3,
+/* 4  */ -3,  1,  3, -1, -1, -3, -3, -1, -1,  3,  1, -3,
+/* 5  */ -1,  1,  1, -1,  1,  3,  3, -1, -1, -3,  1, -3,
+/* 6  */ -3, -3, -1,  3,  3,  3, -3,  3, -3,  1, -1, -3,
+/* 7  */ -3,  3, -3,  3,  3, -3, -1, -1,  3,  3,  1, -3,
+/* 8  */ -3, -1, -3, -1, -1, -3,  3,  3, -1, -1,  1, -3,
+/* 9  */ -3,  3,  3,  3, -1, -3, -3, -1, -3,  1,  3, -3,
+/* 10 */  1,  3, -3,  1,  3,  3,  3,  1, -1,  1, -1,  3,
+/* 11 */ -1, -3,  3, -1, -3, -3, -3, -1,  1, -1,  1, -3,
+/* 12 */  3,  1,  3,  1,  3, -3, -1,  1,  3,  1, -1, -3,
+/* 13 */ -3, -3,  3,  3,  3, -3, -1,  1, -3,  3,  1, -3,
+/* 14 */ -3, -1,  1, -3,  1,  3,  3,  3, -1, -3,  3,  3,
+/* 15 */ -3, -3,  3,  1, -3, -3, -3, -1,  3, -1,  1,  3,
+/* 16 */ -1,  1,  3, -3,  1, -1,  1, -1, -1, -3,  1, -1,
+/* 17 */ -3, -1, -1,  1,  3,  1,  1, -1,  1, -1, -3,  1,
+/* 18 */ -3, -1,  3, -3, -3, -1, -3,  1, -1, -3,  3,  3,
+/* 19 */ -3, -3,  3, -3, -1,  3,  3,  3, -1, -3,  1, -3,
+/* 20 */ -3,  1, -1, -1,  3,  3, -3, -1, -1, -3, -1, -3,
+/* 21 */ -3,  1,  3,  3, -1, -1, -3,  3,  3, -3,  3, -3,
+/* 22 */ -3, -1, -1, -3, -3, -1, -3,  3,  1,  3, -1, -3,
+/* 23 */ -3, -1,  3,  1, -3, -1, -3,  3,  1,  3,  3,  1,
+/* 24 */ -3,  3,  3,  1, -3,  3, -1,  1,  3, -3,  3, -3,
+/* 25 */  3, -1, -3,  3, -3, -1,  3,  3,  3, -3, -1, -3,
+/* 26 */  1, -1,  3, -1, -1, -1, -3, -1,  1,  1,  1, -3,
+/* 27 */ -3,  3,  1, -3,  1,  3, -1, -1,  1,  3,  3,  3,
+/* 28 */ -3,  3, -3,  3, -3, -3,  3, -1, -1,  1,  3, -3,
+/* 29 */ -3,  3,  1, -1,  3,  3, -3,  1, -1,  1, -1,  1,
+}
+#endif
+;
+
+/* Table 5.2.2.2-3: Definition of phi (n ) for M_ZC = 18 */
+const char phi_M_ZC_18[18*U_GROUP_NUMBER]
+#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+= {
+/*          0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17 */
+/* 0   */   3, -3,  3, -1,  1,  3, -3, -1, -3, -3, -1, -3,  3,  1, -1,  3, -3,  3,
+/* 1   */   3, -3,  1,  1,  3, -1,  1, -1, -1, -3,  1,  1, -1,  3,  3, -3,  3, -1,
+/* 2   */  -3,  3, -1, -3, -1, -3,  1,  1, -3, -3, -1, -1,  3, -3,  1,  3,  1,  1,
+/* 3   */   1,  1, -1, -1, -3, -1,  1, -3, -3, -3,  1, -3, -1, -1,  1, -1,  3,  1,
+/* 4   */   1,  1, -3,  3,  3,  1,  3, -3,  3, -1,  1,  1, -1,  1, -3, -3, -1,  3,
+/* 5   */  -3, -3,  1, -3,  3,  3,  3, -1,  3,  1,  1, -3, -3, -3,  3, -3, -1, -1,
+/* 6   */  -1,  3, -1, -3,  3,  1, -3, -1,  3, -3, -1, -1,  1,  1,  1, -1, -1, -1,
+/* 7   */  -3,  1, -3, -3,  1, -3, -3,  3,  1, -3, -1, -3, -3, -3, -1,  1,  1,  3,
+/* 8   */   1, -3, -1, -3,  3,  3, -1, -3,  1, -3, -3, -1, -3, -1,  1,  3,  3,  3,
+/* 9   */  -3,  3,  1, -1, -1, -1, -1,  1, -1,  3,  3, -3, -1,  1,  3, -1,  3, -1,
+/* 10  */  -3, -3,  1, -1, -1,  1,  1, -3, -1,  3,  3,  3,  3, -1,  3,  1,  3,  1,
+/* 11  */  -3, -3,  3,  3, -3,  1,  3, -1, -3,  1, -1, -3,  3, -3, -1, -1, -1,  3,
+/* 12  */  -3, -3,  3,  3,  3,  1, -3,  1,  3,  3,  1, -3, -3,  3, -1, -3, -1,  1,
+/* 13  */  -3,  3, -1,  1,  3,  1, -3, -1,  1,  1, -3,  1,  3,  3, -1, -3, -3, -3,
+/* 14  */  -3,  1, -3, -1, -1,  3,  1, -3, -3, -3, -1, -3, -3,  1,  1,  1, -1, -1,
+/* 15  */  -3, -3,  3,  3,  3, -1, -1, -3, -1, -1, -1,  3,  1, -3, -3, -1,  3, -1,
+/* 16  */  -3, -1,  3,  3, -1,  3, -1, -3, -1,  1, -1, -3, -1, -1, -1,  3,  3,  1,
+/* 17  */  -3, -1, -3, -1, -3,  1,  3, -3, -1,  3,  3,  3,  1, -1, -3,  3, -1, -3,
+/* 18  */  -3,  3,  1, -1, -1,  3, -3, -1,  1,  1,  1,  1,  1, -1,  3, -1, -3, -1,
+/* 19  */   3, -1, -3,  1, -3, -3, -3,  3,  3, -1,  1, -3, -1,  3,  1,  1,  3,  3,
+/* 20  */   3,  3,  3, -3, -1, -3, -1,  3, -1,  1, -1, -3,  1, -3, -3, -1,  3,  3,
+/* 21  */   3, -1,  3,  1, -3, -3, -1,  1, -3, -3,  3,  3,  3,  1,  3, -3,  3, -3,
+/* 22  */  -3,  1,  1, -3,  1,  1,  3, -3, -1, -3, -1,  3, -3,  3, -1, -1, -1, -3,
+/* 23  */  -3, -1, -1, -3,  1, -3,  3, -1, -1, -3,  3,  3, -3, -1,  3, -1, -1, -1,
+/* 24  */  -3, -3, -3,  1, -3,  3,  1,  1,  3, -3, -3,  1,  3, -1,  3, -3, -3,  3,
+/* 25  */   1,  1, -3, -3, -3, -3,  1,  3, -3,  3,  3,  1, -3, -1,  3, -1, -3,  1,
+/* 26  */   3, -1, -1,  1, -3, -1, -3, -1, -3, -3, -1, -3,  1,  1,  1, -3, -3,  3,
+/* 27  */   3,  1, -3,  1, -3,  3,  3, -1, -3, -3, -1, -3, -3,  3, -3, -1,  1,  3,
+/* 28  */  -1, -3,  1, -3, -3, -3,  1,  1,  3,  3, -3,  3,  3, -3, -1,  3, -3,  1,
+/* 29  */  -3, -1, -3, -3,  1,  1, -1, -3, -1, -3, -1, -1,  3,  3, -1,  3,  1,  3,
+}
+#endif
+;
+
+/* Table 5.2.2.2-4: Definition of phi (n ) for M_ZC = 24 */
+const char phi_M_ZC_24[24*U_GROUP_NUMBER]
+#ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+= {
+/*          0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23 */
+/* 0   */  -1, -3,  3,  1,  1, -3,  1, -3, -3,  1, -3, -1, -1,  3, -3,  3,  3,  3, -3,  1,  3,  3, -3, -3,
+/* 1   */  -1, -3,  3, -1,  3,  1,  3, -1,  1, -3, -1, -3, -1,  1,  3, -3, -1, -3,  3,  3,  3, -3, -3, -3,
+/* 2   */  -3,  3,  1,  3, -1,  1, -3,  1, -3,  1, -1, -3, -1, -3, -3, -3, -3, -1, -1, -1,  1,  1, -3, -3,
+/* 3   */   3, -1,  3, -1,  1, -3,  1,  1, -3, -3,  3, -3, -1, -1, -1, -1, -1, -3, -3, -1,  1,  1, -3, -3,
+/* 4   */   1, -3,  3, -1, -3, -1,  3,  3,  1, -1,  1,  1,  3, -3, -1, -3, -3, -3, -1,  3, -3, -1, -3, -3,
+/* 5   */   3, -1,  1, -1,  3, -3,  1,  1,  3, -1, -3,  3,  1, -3,  3, -1, -1, -1, -1,  1, -3, -3, -3, -3,
+/* 6   */  -3,  3, -1,  3,  1, -1, -1, -1,  3,  3,  1,  1,  1,  3,  3,  1, -3, -3, -1,  1, -3,  1,  3, -3,
+/* 7   */  -3, -1,  1, -3, -3,  1,  1, -3,  3, -1, -1, -3,  1,  3,  1, -1, -3, -1, -3,  1, -3, -3, -3, -3,
+/* 8   */  -3,  1, -3,  1, -3, -3,  1, -3,  1, -3, -3, -3, -3, -3,  1, -3, -3,  1,  1, -3,  1,  1, -3, -3,
+/* 9   */   3, -3, -3, -1,  3,  3, -3, -1,  3,  1,  1,  1,  3, -1,  3, -3, -1,  3, -1,  3,  1, -1, -3, -3,
+/* 10  */  -3, -3, -1, -1, -1, -3,  1, -1, -3, -1,  3, -3,  1, -3,  3, -3,  3,  3,  1, -1, -1,  1, -3, -3,
+/* 11  */  -3, -3,  3,  3,  1, -1, -1, -1,  1, -3, -1,  1, -1,  3, -3, -1, -3, -1, -1,  1, -3,  3, -1, -3,
+/* 12  */  -3, -3,  1, -1,  3,  3, -3, -1,  1, -1, -1,  1,  1, -1, -1,  3, -3,  1, -3,  1, -1, -1, -1, -3,
+/* 13  */  -3,  1, -3,  3, -1, -1, -1, -3,  3,  1, -1, -3, -1,  1,  3, -1,  1, -1,  1, -3, -3, -3, -3, -3,
+/* 14  */  -3, -3, -3, -1,  3, -3,  3,  1,  3,  1, -3, -1, -1, -3,  1,  1,  3,  1, -1, -3,  3,  1,  3, -3,
+/* 15  */   1,  1, -1, -3, -1,  1,  1, -3,  1, -1,  1, -3,  3, -3, -3,  3, -1, -3,  1,  3, -3,  1, -3, -3,
+/* 16  */  -3,  3, -1,  3, -1,  3,  3,  1,  1, -3,  1,  3, -3,  3, -3, -3, -1,  1,  3, -3, -1, -1, -3, -3,
+/* 17  */  -1, -3, -3,  1, -1, -1, -3,  1,  3, -1, -3, -1, -1, -3,  1,  1,  3,  1, -3, -1, -1,  3, -3, -3,
+/* 18  */  -3,  1, -3,  1, -3,  1,  1,  3,  1, -3, -3, -1,  1,  3, -1, -3,  3,  1, -1, -3, -3, -3, -3, -3,
+/* 19  */   3, -3,  3, -1, -3,  1,  3,  1, -1, -1, -3, -1,  3, -3,  3, -1, -1,  3,  3, -3, -3,  3, -3, -3,
+/* 20  */  -1,  3, -3, -3, -1,  3, -1, -1,  1,  3,  1,  3, -1, -1, -3,  1,  3,  1, -1, -3,  1, -1, -3, -3,
+/* 21  */  -3,  1, -3, -1, -1,  3,  1,  3, -3,  1, -1,  3,  3, -1, -3,  3, -3, -1, -1, -3, -3, -3,  3, -3,
+/* 22  */  -3, -1, -1, -3,  1, -3, -3, -1, -1,  3, -1,  1, -1,  3,  1, -3, -1,  3,  1,  1, -1, -1, -3, -3,
+/* 23  */  -3,  1, -3,  3, -3,  1, -3,  3,  1, -1, -3, -1, -3, -3, -3, -3,  1,  3, -1,  1,  3,  3,  3, -3,
+/* 24  */  -3, -1,  1, -3, -1, -1,  1,  1,  1,  3,  3, -1,  1, -1,  1, -1, -1, -3, -3, -3,  3,  1, -1, -3,
+/* 25  */   3, -3, -1,  1,  3, -1, -1, -3, -1,  3, -1, -3, -1, -3,  3, -1,  3,  1,  1, -3,  3, -3, -3, -3,
+/* 26  */  -3,  1,  3, -1,  1, -1,  3, -3,  3, -1, -3, -1, -3,  3, -1, -1, -1, -3, -1, -1, -3,  3,  3, -3,
+/* 27  */  -3,  3, -1, -3, -1, -1, -1,  3, -1, -1,  3, -3, -1,  3, -3,  3, -3, -1,  3,  1,  1, -1, -3, -3,
+/* 28  */  -3,  1, -1, -3, -3, -1,  1, -3, -1, -3,  1,  1, -1,  1,  1,  3,  3,  3, -1,  1, -1,  1, -1, -3,
+/* 29  */  -1,  3, -1, -1,  3,  3, -1, -1, -1,  3, -1, -3,  1,  3,  1,  1, -3, -3, -3, -1, -3, -1, -3, -3,
+}
+#endif
+;
+/************** FUNCTION ******************************************/
+
+int16_t *base_sequence_36_or_larger(unsigned int M_ZC, unsigned int u, unsigned int v, unsigned int scaling);
+int16_t *base_sequence_less_than_36(unsigned int M_ZC, unsigned int u, unsigned int scaling);
+/*!
+\brief This function generate the sounding reference symbol (SRS) for the uplink.
+@param tables of srs
+@param scaling amplitude of the reference signal
+*/
+void generate_ul_reference_signal_sequences(unsigned int scaling);
+void free_ul_reference_signal_sequences(void);
+
+#undef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
+#undef EXTERN
+
+#endif /* SSS_NR_H */
diff --git a/openair1/PHY/NR_UE_TRANSPORT/cic_filter_nr.c b/openair1/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
new file mode 100644
index 0000000000000000000000000000000000000000..98248d02dd523267629419a48d87a9f73d605b3c
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/cic_filter_nr.c
@@ -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.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/**********************************************************************
+*
+* FILENAME    :  cic_filter_nr.c
+*
+* MODULE      :  generic functions for cic filters
+*
+* DESCRIPTION :  generic functions useful for decimation based on cascaded integrator comb filter
+*
+************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+#include <math.h>
+
+#include "PHY/defs_nr_UE.h"
+
+#define DEFINE_VARIABLES_CIC_FILTER_NR_H
+#include "PHY/NR_UE_TRANSPORT/cic_filter_nr.h"
+#undef DEFINE_VARIABLES_CIC_FILTER_NR_H
+
+/*******************************************************************
+*
+* NAME :         integrator_stage
+*
+* PARAMETERS :   pointer to input complex data
+*                pointer to output complex data
+*
+* RETURN :
+*
+* DESCRIPTION :  single stage of an integrator
+*
+*                It is a single-pole IIR filter with a unity feedback coefficient
+*
+*                y(n) = y(n-1) +x(n)*
+*
+*********************************************************************/
+
+void integrator_stage(int32_t *input, int32_t *output, int length)
+{
+  /* first sample is just copied */
+  for (int i = 0; i < 1; i++) {
+    output[2*i]   = input[2*i];
+    output[2*i+1] = input[2*i+1];
+  }
+
+  /* then process all other samples */
+  for (int i = 1; i < length; i++) {
+    output[2*i]   = output[2*(i-1)]   + input[2*i];
+    output[2*i+1] = output[2*(i-1)+1] + input[2*i+1];
+
+#ifdef DBG_CIC_FILTER_NR
+    if (i < 20) {
+      printf("output[%d] = output[%d]    + input[%d] \n", (2*i), 2*(i-1), 2*i);
+      printf("%d         =    %d         + %d \n", output[2*i], output[2*(i-1)], input[2*i]);
+    }
+#endif
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         comb_stage
+*
+* PARAMETERS :   pointer to input complex data
+*                pointer to output complex data
+*
+* RETURN :
+*
+* DESCRIPTION :  single stage of a comb filter which is an odd-symetric FIR filter
+*
+*                y(n) = x(n) - x(n - M)
+*
+*                M is called the differential delay. It can take any positive
+*                integer but it is usually limited to 1 or 2.
+*
+*********************************************************************/
+
+void comb_stage(int32_t *input, int32_t *output, int length, int differential_delay)
+{
+  /* first sample is just copied */
+  for (int i = 0; i < differential_delay; i++) {
+    output[2*i]   = input[2*i];
+	output[2*i+1] = input[2*i+1];
+  }
+
+  /* then process all other samples */
+  for (int i = differential_delay; i < length; i++) {
+    output[2*i]   = input[2*i]   - input[2*(i-differential_delay)];
+    output[2*i+1] = input[2*i+1] - input[2*(i-differential_delay)+1];
+
+#ifdef DBG_CIC_FILTER_NR
+    if (i < 20) {
+      printf("output[%d] = input[%d]    - input[%d] \n", (2*i), (2*i), 2*(i-differential_delay));
+      printf("%d         =    %d        - %d \n", output[2*i], input[2*i], input[2*(i-differential_delay)]);
+    }
+#endif
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         rate_change_stage
+*
+* PARAMETERS :   pointer to input complex data
+*                pointer to output complex data
+*
+* RETURN :       none
+*
+* DESCRIPTION :  change sampling rate by a factor of R
+*                just copy one samples over R from input to output buffer
+*
+*********************************************************************/
+
+void rate_change_stage(int32_t *input, int32_t *output, int length, int rate_change)
+{
+  for (int i = 0; (i*rate_change) < length; i++) {
+    output[2*i]   = input[2*i*rate_change];
+    output[2*i+1] = input[(2*i*rate_change)+1];
+
+#ifdef DBG_CIC_FILTER_NR
+    if (i < 20) {
+      printf("input[%d] : %d \n", 2*i*rate_change, input[2*i*rate_change]);
+      printf("output[%d] : %d \n", 2*i, output[2*i]);
+    }
+#endif
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         fir_filter
+*
+* PARAMETERS :   pointer to input complex data
+*                pointer to output complex data
+*
+* RETURN :       none
+*
+* DESCRIPTION :  implement a fir filter with taps from an array
+*
+*********************************************************************/
+
+void fir_filter_init(fir_filter_t* f, int taps_fir_number, int32_t *filter_taps) {
+  int i;
+  for(i = 0; i < taps_fir_number; ++i)
+    f->history[i] = 0;
+  f->last_index = 0;
+  if (taps_fir_number > MAX_SAMPLEFILTER_TAP_NUM) {
+    printf("Number of taps of this FIR filter %d exceeds maximum value %d \n", taps_fir_number, MAX_SAMPLEFILTER_TAP_NUM);
+    assert(0);
+  }
+  f->filter_tap_number = taps_fir_number;
+  f->filter_taps = filter_taps;
+}
+
+void fir_filter_put(fir_filter_t* f, int32_t input) {
+  f->history[f->last_index++] = input;
+  if(f->last_index == f->filter_tap_number)
+    f->last_index = 0;
+}
+
+int32_t fir_filter_get(fir_filter_t* f, int scaling_shift) {
+  long long acc = 0;
+  int index = f->last_index, i;
+  for(i = 0; i < f->filter_tap_number; ++i) {
+    index = index != 0 ? index-1 : f->filter_tap_number-1;
+    acc += (long long)f->history[index] * f->filter_taps[i];
+  };
+  return acc >> scaling_shift;
+}
+
+void fir_filter_basic(int32_t *input, int32_t *output, int length, int taps_fir_number, int32_t *filter_taps, int scaling_shift)
+{
+  fir_filter_t filter;
+
+  for (int j = 0; j < 2; j++) {
+
+    fir_filter_init(&filter, taps_fir_number, filter_taps);
+
+    for (int i = 0; i < length; i++) {
+      fir_filter_put(&filter, input[2*i+j]);
+      output[2*i+j] = fir_filter_get(&filter, scaling_shift);
+      //printf("i %d input %d output %d ", 2*i+j, input[2*i+j], output[2*i + j]);
+    }
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         fir_filter
+*
+* PARAMETERS :   pointer to input complex data
+*                pointer to output complex data
+*
+* RETURN :
+*
+* DESCRIPTION :  single stage of a fir filter which is an odd-symetric FIR filter
+*
+*                y(n) = SUM ( bi * x(n - i) )
+*
+*                bi are tags of FIR filter
+*
+*********************************************************************/
+
+void fir_filter(int32_t *input, int32_t *output, int length, int taps_fir_number, int *taps_fir, int scaling_shift)
+{
+  int32_t current;
+
+  /* taps start from 1 to taps_fir_number */
+  for (int i = 0; i < taps_fir_number; i++) {
+    for (int j=0; j<2 ; j++) {
+      current = 0;
+      for (int taps_number = 0; taps_number < taps_fir_number; taps_number++) {
+        if (i >= taps_number) {
+          current += taps_fir[taps_number]*input[2*(i-taps_number)+j];
+#ifdef DBG_CIC_FILTER_NR
+          printf("current[%d] %d = taps[%d] : %d x input[%d] : %d \n", (2*i+j), current, taps_number, taps_fir[taps_number], (2*(i-taps_number)+j), input[2*(i-taps_number)+j]);
+#endif
+        }
+      }
+      output[2*i+j] = current >> scaling_shift;
+    }
+  }
+
+  for (int i = taps_fir_number; i < length; i++) {
+    for (int j=0; j<2 ; j++) {
+      current = 0;
+      for (int taps_number = 0; taps_number < taps_fir_number; taps_number++) {
+        current += taps_fir[taps_number]*input[2*(i-taps_number)+j];
+#ifdef DBG_CIC_FILTER_NR
+        if (i < taps_fir_number + 16) {
+          printf("current[%d] %d = taps[%d] : %d x input[%d] : %d \n", (2*i+j), current, taps_number, taps_fir[taps_number], (2*(i-taps_number)+j), input[2*(i-taps_number)+j]);
+        }
+#endif
+      }
+      output[2*i+j] = current >> scaling_shift; // SHARPENED_FIR_SCALING_ACC;
+    }
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         cic_decimator
+*
+* PARAMETERS :   pointer to input complex data
+*                pointer to output complex data
+*                length size of input buffer
+*                decimation by a factor of R
+*
+* RETURN :       result of decimator is the output buffer
+*
+* DESCRIPTION :  Cascaded integrator-comb filter
+*                rate change by a factor of R
+*
+*                CIC filter with N stages is composed of:
+*                - N cascaded integrator filters clocked at high sampling rate fs
+*                - N cascaded comb stage running at fs/R
+*
+*              +-----------+  +----------+  +----------+  +----+  +----------+  +----------+  +----------+         +--------------+
+*              | Integrator|  |Integrator|  |Integrator|  |  R |  |   Comb   |  |   Comb   |  |   Comb   |         | Compensation |
+*    input --->|   stage   |->|   stage  |->| stage    |->|    |->|   stage  |->|   stage  |->|   stage  |-------->|   FIR Filter |---> output
+*              +-----------+  +----------+  +----------+  +----+  +----------+  +----------+  +----------+         +--------------+
+*             <---------------------------------------->    |      <-------------------------------------->
+*                   N cascaded integrator filters           |        N cascaded comb stage running at fs/R
+*                 clocked at high sampling rate fs          V
+*                                                        downsampling
+*                                                      from fs to fs/R
+*
+* In order that cic filter works properly, some caution should be taken for getting good accuracy.
+* Firstly data should be in fixed point in order to balance integrator and comb stages. If does not work with data in floating point.
+*
+* k1 is the number of significant bits for input
+* k2 is the number of significant bits for output
+* m = k2 - k2 > N * log2(RM - 1)   N number of stage, M differential delay and R rate change factor
+* for example with R=16  N=4 and M=1 with input data on 16 bits
+* output data should be on k2 = m + k1 > 31
+*
+* Additionally there is a bit growth so processing has a gain of
+* G = (RM)power(N)
+* For example with R=16 N=4 M=1  G=(16*1)power(4)=65536
+*
+* It gives size of output data with number of significant bit Bout = (N x log2(R x M)) + Bin
+* With R=16 N=4 M=1 Bin=16 => Bout = (4 x log2(16 x 1)) + 16 = (4 x 4) + 16 = 32 so output significant bits should be 32.
+* As a consequence, all computations are done with 32 bits up to the last stage (no rounding or truncation).
+* Except for the final result which can be casted from 32 bits to 16 bits.
+*
+*********************************************************************/
+
+void cic_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int number_cic_stage, int set_scaling_factor, int fir_rate_change)
+{
+  int32_t *buffer_one;
+  int32_t *buffer_two;
+  int32_t *input;
+  int32_t *output;
+  int32_t *tmp;
+  int new_length;
+  int current_rate_change;
+
+  /* for cic decimator, gain g of the output depends on rate change R, differential delay M and number of stage N */
+  /* g = power(R x M, N) / power(2 , log2 (R x M)  */
+  /* so a scale factor should be applied to output in order to get a unity DC gain */
+
+  int scaling_factor =  0; // pow(2, log2(rate_change * M_DIFFERENTIAL_DELAY))/pow((rate_change * M_DIFFERENTIAL_DELAY), number_cic_stage);
+
+  if (set_scaling_factor != 0) {
+    scaling_factor = set_scaling_factor;
+    printf("Decimation with rate change of %d with set gain of %d \n", rate_change, scaling_factor);
+  }
+
+  /* get working buffers */
+  buffer_one = malloc(length*sizeof(int32_t) * 2);   /* for i&q samples */
+  if (buffer_one == NULL) {
+     msg("Fatal memory allocation problem \n");
+     assert(0);
+  }
+
+  buffer_two = malloc(length*sizeof(int32_t) * 2);  /* for i&q samples */
+  if (buffer_two == NULL) {
+    msg("Fatal memory allocation problem \n");
+    assert(0);
+  }
+
+  /* copy of input buffer from int16 to int32 */
+  for (int i = 0; i < length; i++) {
+    buffer_one[2*i]     = input_buffer[2*i];
+    buffer_one[2*i + 1] = input_buffer[2*i + 1];
+
+#ifdef DBG_CIC_FILTER_NR
+    if (i < 10) {
+      printf("buffer_one[%d] : %d %d \n", i, buffer_one[2*i], buffer_one[2*i + 1]);
+    }
+#endif
+  }
+
+  input = buffer_one;
+  output = buffer_two;
+
+  /* call of integrator stages running at Fs */
+  for (int stage = 0; stage < number_cic_stage; stage++)
+  {
+    integrator_stage(input, output, length);
+
+    /* swap between output and input */
+    tmp = input;
+    input = output;
+    output = tmp;
+
+#if 0
+    char output_file[255];
+    char sequence_name[255];
+    sprintf(output_file, "int_seq_%d.m", stage);
+    sprintf(sequence_name, "int_seq_%d", stage);
+
+    printf("file %s signal %s\n", output_file, sequence_name);
+    write_output(output_file, sequence_name, input, length, 1, 3); /* format = 3 is for int32_t */
+#endif
+  }
+
+  /* a sharpened Fir filter can be added which can provide also a rate change */
+  current_rate_change = rate_change/fir_rate_change;
+
+  /* rate change from sampling frequency Fs to Fs/R */
+  rate_change_stage(input, output, length, current_rate_change);
+
+  /* new length of samples should be computed based on the rate change factor R */
+  new_length = length/current_rate_change;
+
+  /* swap between output and input */
+  tmp = input;
+  input = output;
+  output = tmp;
+
+  /* call of comb stages running at Fs/R */
+  for (int stage = 0; stage < number_cic_stage; stage++)
+  {
+    comb_stage(input, output, new_length, M_DIFFERENTIAL_DELAY);
+
+    /* swap between output and input */
+    tmp = input;
+    input = output;
+    output = tmp;
+
+#if 0
+    char output_file[255];
+    char sequence_name[255];
+    sprintf(output_file, "comb_seq_%d.m", stage);
+    sprintf(sequence_name, "comb_seq_%d", stage);
+    printf("file %s signal %s\n", output_file, sequence_name);
+    write_output(output_file, sequence_name, input, new_length, 1, 3); /* format = 3 for int32_t */
+#endif
+  }
+
+#if 1
+
+  if (fir_rate_change > 1)
+  {
+#define FIR_TAPS_SCALING   (10000)
+
+    /* convert float taps of fir filter to int32 taps */
+    int32_t *filter_taps_fixed_point = malloc(FIR_TAPS_NUMBER*sizeof(int32_t));
+    if (filter_taps_fixed_point == NULL) {
+      msg("Fatal memory allocation problem \n");
+      assert(0);
+    }
+
+    for (int i = 0; i < FIR_TAPS_NUMBER; i++) {
+      filter_taps_fixed_point[i] = (int32_t)(sharpened_fir_taps[i] * FIR_TAPS_SCALING);
+    }
+
+#if 1
+
+    /* compensation filter for equalizing the passband drop and perform a low rate change */
+    fir_filter(input, output, new_length, FIR_TAPS_NUMBER, filter_taps_fixed_point, FIR_FITER_SCALING_ACC);
+
+#else
+
+    fir_filter_basic(input, output, new_length,  FIR_TAPS_NUMBER, filter_taps, SHARPENED_FIR_SCALING_ACC);
+
+#endif
+  }
+  else
+  {
+    output = input;
+  }
+
+  /* new length of samples should be computed based on the rate change */
+  current_rate_change = fir_rate_change;
+  new_length = new_length/current_rate_change;
+
+  /* filter has created a delay on the signal which can be compensated */
+  //int delay = FIR_TAPS_NUMBER;
+  int delay = 0;
+
+  for (int i = 0; (i*fir_rate_change) < new_length; i++) {
+    output_buffer[2*i] = output[(2*i+delay)*current_rate_change]>> scaling_factor;
+    output_buffer[2*i+1] = output[((2*i+delay)*current_rate_change)+1]>> scaling_factor;
+
+#ifdef DBG_CIC_FILTER_NR
+    if (i < 10) {
+      printf("output_buffer[%d] = output[%d] >> scaling_factor \n", (2*i), ((2*i+delay)*current_rate_change));
+      printf("      %d           =     %d     >> %d \n", output_buffer[2*i], output[((2*i+delay)*current_rate_change)], scaling_factor);
+    }
+#endif
+  }
+
+#else
+
+  scaling_factor = 0;
+
+  /* copy of final result from int32 to int16 with a scaling factor and a rate change */
+  for (int i = 0; i < new_length; i++) {
+    output_buffer[2*i] = input[2*i] >> scaling_factor;
+    output_buffer[2*i + 1] = input[2*i + 1] >> scaling_factor;
+
+#ifdef DBG_CIC_FILTER_NR
+    if (i < 10) {
+      printf("output_buffer[%d] : %d \n", (2*i), output_buffer[2*i]);
+      printf("input[%d] : %d \n", 2*i, input[2*i] >> scaling_factor);
+    }
+#endif
+  }
+
+#endif
+
+#if 1
+  /* clear till end of the buffer */
+  for (int i = new_length; i < length; i++) {
+    output_buffer[2*i] = 0;
+    output_buffer[2*i + 1] = 0;
+  }
+#endif
+}
+
+/*******************************************************************
+*
+* NAME :         fir_decimator
+*
+* PARAMETERS :   pointer to input complex data
+*                pointer to output complex data
+*                length size of input buffer
+*                decimation by a factor of R
+*
+* RETURN :       result of decimator is the output buffer
+*
+* DESCRIPTION :  fir filter
+*                rate change by a factor of R
+*
+*
+*********************************************************************/
+
+void fir_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int scaling_factor)
+{
+  int32_t *buffer_one;
+  int32_t *buffer_two;
+  int32_t *input;
+  int32_t *output;
+  int new_length;
+
+  /* get working buffers */
+  buffer_one = malloc(length*sizeof(int32_t) * 2);   /* for i&q samples */
+  if (buffer_one == NULL) {
+    msg("Fatal memory allocation problem \n");
+    assert(0);
+  }
+
+  buffer_two = malloc(length*sizeof(int32_t) * 2);  /* for i&q samples */
+  if (buffer_two == NULL) {
+    msg("Fatal memory allocation problem \n");
+    assert(0);
+  }
+
+  /* copy of input buffer from int16 to int32 */
+  for (int i = 0; i < length; i++) {
+    buffer_one[2*i]     = input_buffer[2*i];
+    buffer_one[2*i + 1] = input_buffer[2*i + 1];
+  }
+
+  input = buffer_one;
+  output = buffer_two;
+
+#if 1
+
+  fir_filter(input, output, length, SAMPLEFILTER_TAP_NUM, filter_taps, FIR_SCALING_ACC);
+
+#else
+
+  fir_filter_basic(input, output, length,  SAMPLEFILTER_TAP_NUM, filter_taps, FIR_SCALING_ACC);
+
+#endif
+
+  /* rate change from sampling frequency Fs to Fs/R */
+  rate_change_stage(output, input, length, rate_change);
+
+  new_length = length/rate_change;
+
+  /* copy of final result from int32 to int16 with a scaling factor and a rate change */
+  for (int i = 0; i < new_length; i++) {
+    output_buffer[2*i] = input[2*i] >> scaling_factor;
+    output_buffer[2*i + 1] = input[2*i + 1] >> scaling_factor;
+  }
+
+#if 1
+  /* clear till end of the buffer */
+  for (int i = new_length; i < length; i++) {
+    output_buffer[2*i] = 0;
+    output_buffer[2*i + 1] = 0;
+  }
+#endif
+
+}
+
+
+
+
+
+
+
diff --git a/openair1/PHY/NR_UE_TRANSPORT/cic_filter_nr.h b/openair1/PHY/NR_UE_TRANSPORT/cic_filter_nr.h
new file mode 100644
index 0000000000000000000000000000000000000000..74e02731ff2a16dd634761af4afb3e1b9ad1c398
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/cic_filter_nr.h
@@ -0,0 +1,207 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/**********************************************************************
+*
+* FILENAME    :  cic_filter_nr.h
+*
+* MODULE      :  synchronisation signal
+*
+* DESCRIPTION :  function related to nr synchronisation
+*                It provides filters for sampling decimation
+*
+************************************************************************/
+
+#ifndef CIC_FILTER_NR_H
+#define CIC_FILTER_NR_H
+
+#include "PHY/defs_nr_UE.h"
+#include "PHY/types.h"
+
+#ifdef DEFINE_VARIABLES_CIC_FILTER_NR_H
+#define EXTERN
+#define INIT_VARIABLES_CIC_FILTER_NR_H
+#else
+#define EXTERN  extern
+#endif
+
+/************** DEFINE ********************************************/
+
+#define M_DIFFERENTIAL_DELAY        (1)
+#define FIR_RATE_CHANGE             (2)
+
+/************** VARIABLES *****************************************/
+
+#define FIR_TAPS_NUMBER                 (20)
+#define FIR_FITER_SCALING_ACC           (14)
+
+EXTERN double sharpened_fir_taps[FIR_TAPS_NUMBER]
+#ifdef INIT_VARIABLES_CIC_FILTER_NR_H
+= {
+/*
+cic filter and compensation FIR have been designed based on cic design tools provided at
+http://www.tsdconseil.fr/tutos/index.html
+-->cfir = cic_comp_design(4,4,1,30720000,2,1650000,20);
+R = 4.00, Fin = 30720000.00 Hz, Fout = 7680000.00 Hz.
+Attenuation for f > fout/2 : -14.82 dB.
+Attenuation at 1650000.00 Hz: -0.15 dB.
+Attenuation max. between 0 et 1650000.00 Hz: -0.15 dB.
+E.g. in linear scale : * 0.983
+Number of additionnal bits needed for implementation: 7.
+Fout = 7680000.00 Hz.
+index = 1026 / 4096.
+Correction Fint ?
+Filtre global :
+
+-->cfir
+ cfir  =
+*/
+  - 0.0059900,
+  - 0.0056191,
+    0.0107582,
+    0.0266043,
+    0.0130358,
+  - 0.0331228,
+  - 0.0680440,
+  - 0.0278570,
+    0.1106335,
+    0.2897060,
+    0.3607857,
+    0.2607354,
+    0.0983409,
+  - 0.0243749,
+  - 0.0583235,
+  - 0.0276023,
+    0.0104286,
+    0.0199533,
+    0.0071721,
+  - 0.0028096,
+}
+#endif
+;
+
+#define MAX_SAMPLEFILTER_TAP_NUM  (100)
+#define FIR_SCALING_ACC           (15)
+
+typedef struct {
+  int32_t history[MAX_SAMPLEFILTER_TAP_NUM];
+  int last_index;
+  int filter_tap_number;
+  int32_t *filter_taps;
+} fir_filter_t;
+
+#define SAMPLEFILTER_TAP_NUM       (59)
+
+/*
+ * This low pass filter was designed based on the tool at http://t-filter.engineerjs.com/
+ * with below parameters
+ * sampling frequency 30.72 MHz
+ * from 	to 	          gain 	ripple/att.
+ * 0 Hz     1.9 MHz        1     0.5 dB
+ * 2 MHz     15 MHz        0     -20 dB
+ */
+
+EXTERN int filter_taps[SAMPLEFILTER_TAP_NUM]
+#ifdef INIT_VARIABLES_CIC_FILTER_NR_H
+= {
+  -1572,
+  65,
+  -132,
+  197,
+  26,
+  393,
+  194,
+  536,
+  250,
+  514,
+  105,
+  279,
+  -234,
+  -105,
+  -646,
+  -466,
+  -924,
+  -583,
+  -856,
+  -279,
+  -321,
+  492,
+  639,
+  1601,
+  1812,
+  2766,
+  2872,
+  3650,
+  3503,
+  3976,
+  3503,
+  3650,
+  2872,
+  2766,
+  1812,
+  1601,
+  639,
+  492,
+  -321,
+  -279,
+  -856,
+  -583,
+  -924,
+  -466,
+  -646,
+  -105,
+  -234,
+  279,
+  105,
+  514,
+  250,
+  536,
+  194,
+  393,
+  26,
+  197,
+  -132,
+  65,
+  -1572
+}
+#endif
+;
+
+/************** FUNCTION ******************************************/
+
+void integrator_stage(int32_t *input, int32_t *output, int length);
+
+void comb_stage(int32_t *input, int32_t *output, int length, int differential_delay);
+
+void rate_change_stage(int32_t *input, int32_t *output, int length, int rate_change);
+
+void fir_filter(int32_t *input, int32_t *output, int length, int taps_fir_number, int32_t *taps_fir, int scaling_shift);
+
+void cic_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int number_cic_stage, int set_scaling_factor, int fir_rate_change);
+
+void fir_decimator(int16_t *input_buffer, int16_t *output_buffer, int length, int rate_change, int scaling_factor);
+
+#undef EXTERN
+#undef INIT_VARIABLES_CIC_FILTER_NR_H
+
+#endif /* CIC_FILTER_NR_H */
+
+
diff --git a/openair1/PHY/NR_UE_TRANSPORT/dmrs_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dmrs_nr.c
new file mode 100644
index 0000000000000000000000000000000000000000..06ccd9459f699be59ae45b12167710c64cbef0d2
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/dmrs_nr.c
@@ -0,0 +1,311 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/**********************************************************************
+*
+* FILENAME    :  dmrs_nr.c
+*
+* MODULE      :  demodulation reference signals
+*
+* DESCRIPTION :  generation of dmrs sequences
+*                3GPP TS 38.211
+*
+************************************************************************/
+
+//#include "PHY/LTE_REFSIG/defs.h"
+#include "PHY/NR_REFSIG/ss_pbch_nr.h"
+#include "PHY/NR_REFSIG/dmrs_nr.h"
+
+/*******************************************************************
+*
+* NAME :         pseudo_random_gold_sequence
+*
+* PARAMETERS :
+*
+* RETURN :       generate pseudo-random sequence which is a length-31 Gold sequence
+*
+* DESCRIPTION :  3GPP TS 38.211 5.2.1 Pseudo-random sequence generation
+*                Sequence generation is a length-31 Gold sequence
+*
+*********************************************************************/
+
+#define NC                     (1600)
+#define GOLD_SEQUENCE_LENGTH   (31)
+
+int pseudo_random_sequence(int M_PN, uint32_t *c, uint32_t cinit)
+{
+  int n;
+  int size_x =  NC + GOLD_SEQUENCE_LENGTH + M_PN;
+  uint32_t *x1;
+  uint32_t *x2;
+
+  x1 = calloc(size_x, sizeof(uint32_t));
+
+  if (x1 == NULL) {
+    msg("Fatal error: memory allocation problem \n");
+    assert(0);
+  }
+
+  x2 = calloc(size_x, sizeof(uint32_t));
+
+  if (x2 == NULL) {
+    free(x1);
+    msg("Fatal error: memory allocation problem \n");
+    assert(0);
+  }
+
+  x1[0] = 1;  /* init first m sequence */
+
+  /* cinit allows to initialise second m-sequence x2 */
+  for (n = 0; n < GOLD_SEQUENCE_LENGTH; n++) {
+     x2[n] = (cinit >> n) & 0x1;
+  }
+
+  for (n = 0; n < (NC + M_PN); n++) {
+    x1[n+31] = (x1[n+3] + x1[n])%2;
+    x2[n+31] = (x2[n+3] + x2[n+2] + x2[n+1] + x2[n])%2;
+  }
+
+  for (int n = 0; n < M_PN; n++) {
+    c[n] = (x1[n+NC] + x2[n+NC])%2;
+  }
+
+  free(x1);
+  free(x2);
+
+  return 0;
+}
+
+/*******************************************************************
+*
+* NAME :         pseudo_random_sequence_optimised
+*
+* PARAMETERS :
+*
+* RETURN :       generate pseudo-random sequence which is a length-31 Gold sequence
+*
+* DESCRIPTION :  3GPP TS 38.211 5.2.1 Pseudo-random sequence generation
+*                Sequence generation is a length-31 Gold sequence
+*                This is an optimized function based on bitmap variables
+*
+*                x1(0)=1,x1(1)=0,...x1(30)=0,x1(31)=1
+*                x2 <=> cinit, x2(31) = x2(3)+x2(2)+x2(1)+x2(0)
+*                x2 <=> cinit = sum_{i=0}^{30} x2(i)2^i
+*                c(n) = x1(n+Nc) + x2(n+Nc) mod 2
+*
+*                                             equivalent to
+* x1(n+31) = (x1(n+3)+x1(n))mod 2                   <=>      x1(n) = x1(n-28) + x1(n-31)
+* x2(n+31) = (x2(n+3)+x2(n+2)+x2(n+1)+x2(n))mod 2   <=>      x2(n) = x2(n-28) + x2(n-29) + x2(n-30) + x2(n-31)
+*
+*********************************************************************/
+
+void pseudo_random_sequence_optimised(unsigned int size, uint32_t *c, uint32_t cinit)
+{
+  unsigned int n,x1,x2;
+
+  /* init of m-sequences */
+  x1 = 1+ (1<<31);
+  x2 = cinit;
+  x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
+
+  /* skip first 50 double words of uint32_t (1600 bits) */
+  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);
+  }
+
+  for (n=0; n<size; 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);
+    c[n] = x1^x2;
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         lte_gold_new
+*
+* PARAMETERS :
+*
+* RETURN :       generate pseudo-random sequence which is a length-31 Gold sequence
+*
+* DESCRIPTION :  This function is the same as "lte_gold" function in file lte_gold.c
+*                It allows checking that optimization works fine.
+*                generated sequence is given in an array as a bit map.
+*
+*********************************************************************/
+
+#define CELL_DMRS_LENGTH   (224*2)
+#define CHECK_GOLD_SEQUENCE
+
+void lte_gold_new(LTE_DL_FRAME_PARMS *frame_parms, uint32_t lte_gold_table[20][2][14], uint16_t Nid_cell)
+{
+  unsigned char ns,l,Ncp=1-frame_parms->Ncp;
+  uint32_t cinit;
+
+#ifdef CHECK_GOLD_SEQUENCE
+
+  uint32_t dmrs_bitmap[20][2][14];
+  uint32_t *dmrs_sequence =  calloc(CELL_DMRS_LENGTH, sizeof(uint32_t));
+  if (dmrs_sequence == NULL) {
+    msg("Fatal error: memory allocation problem \n");
+  	assert(0);
+  }
+  else
+  {
+    printf("Check of demodulation reference signal of pbch sequence \n");
+  }
+
+#endif
+
+  /* for each slot number */
+  for (ns=0; ns<20; ns++) {
+
+  /* for each ofdm position */
+    for (l=0; l<2; l++) {
+
+      cinit = Ncp +
+             (Nid_cell<<1) +
+             (((1+(Nid_cell<<1))*(1 + (((frame_parms->Ncp==0)?4:3)*l) + (7*(1+ns))))<<10);
+
+      pseudo_random_sequence_optimised(14, &(lte_gold_table[ns][l][0]), cinit);
+
+#ifdef CHECK_GOLD_SEQUENCE
+
+      pseudo_random_sequence(CELL_DMRS_LENGTH, dmrs_sequence, cinit);
+
+      int j = 0;
+      int k = 0;
+
+      /* format for getting bitmap from uint32_t */
+      for (int i=0; i<14; i++) {
+        dmrs_bitmap[ns][l][i] = 0;
+        for (; j < k + 32; j++) {
+          dmrs_bitmap[ns][l][i] |= (dmrs_sequence[j]<<j);
+        }
+        k = j;
+      }
+
+      for (int i=0; i<14; i++) {
+        if (lte_gold_table[ns][l][i] != dmrs_bitmap[ns][l][i]) {
+          printf("Error in gold sequence computation for ns %d l %d and index %i : 0x%x 0x%x \n", ns, l, i, lte_gold_table[ns][l][i], dmrs_bitmap[ns][l][i]);
+          assert(0);
+        }
+      }
+
+#endif
+
+    }
+  }
+
+#ifdef CHECK_GOLD_SEQUENCE
+  free(dmrs_sequence);
+#endif
+}
+
+/*******************************************************************
+*
+* NAME :         get_dmrs_pbch
+*
+* PARAMETERS :   i_ssb : index of ssb/pbch beam
+*                n_hf  : number of the half frame in which PBCH is transmitted in frame
+*
+* RETURN :       demodulation reference signal for PBCH
+*
+* DESCRIPTION :  see TS 38.211 7.4.1.4 Demodulation reference signals for PBCH
+*
+*********************************************************************/
+
+#define CHECK_DMRS_PBCH_SEQUENCE
+
+void generate_dmrs_pbch(uint32_t dmrs_pbch_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_HF][DMRS_BITMAP_SIZE], uint16_t Nid_cell)
+{
+  uint32_t cinit;
+  int i_ssb;
+  int n_hf;
+  int _i_ssb;
+
+#ifdef CHECK_DMRS_PBCH_SEQUENCE
+
+  uint32_t dmrs_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_HF][DMRS_BITMAP_SIZE];
+  uint32_t *dmrs_sequence =  calloc(CELL_DMRS_LENGTH, sizeof(uint32_t));
+  if (dmrs_sequence == NULL) {
+    msg("Fatal error: memory allocation problem \n");
+  	assert(0);
+  }
+  else
+  {
+    printf("Check of demodulation reference signal of pbch sequence \n");
+  }
+
+#endif
+
+  /* for each slot number */
+  for (i_ssb = 0; i_ssb<DMRS_PBCH_I_SSB; i_ssb++) {
+
+    /* for each ofdm position */
+    for (n_hf=0; n_hf<DMRS_PBCH_N_HF; n_hf++) {
+
+      _i_ssb = i_ssb + 4*n_hf;
+
+      cinit = (((_i_ssb + 1)*((Nid_cell>>4) + 1))<<11) + ((_i_ssb + 1)<<6) + (Nid_cell%4);
+
+      pseudo_random_sequence_optimised(DMRS_BITMAP_SIZE, &(dmrs_pbch_bitmap[i_ssb][n_hf][0]), cinit);
+
+#ifdef CHECK_DMRS_PBCH_SEQUENCE
+
+      /* it allows checking generated with standard generation code */
+      pseudo_random_sequence(DMRS_BITMAP_SIZE*sizeof(uint32_t), dmrs_sequence, cinit);
+
+      int j = 0;
+      int k = 0;
+
+      /* format for getting bitmap from uint32_t */
+      for (int i=0; i<DMRS_BITMAP_SIZE; i++) {
+    	dmrs_bitmap[i_ssb][n_hf][i] = 0;
+    	/* convert to bitmap */
+      	for (; j < k + 32; j++) {
+          dmrs_bitmap[i_ssb][n_hf][i] |= (dmrs_sequence[j]<<j);
+      	}
+      	k = j;
+      }
+
+      for (int i=0; i<DMRS_BITMAP_SIZE; i++) {
+        if (dmrs_pbch_bitmap[i_ssb][n_hf][i] != dmrs_bitmap[i_ssb][n_hf][i]) {
+          printf("Error in gold sequence computation for ns %d l %d and index %i : 0x%x 0x%x \n", i_ssb, n_hf, i, dmrs_pbch_bitmap[i_ssb][n_hf][i], dmrs_bitmap[i_ssb][n_hf][i]);
+      	  assert(0);
+        }
+      }
+
+#endif
+
+    }
+  }
+
+#ifdef CHECK_DMRS_PBCH_SEQUENCE
+  free(dmrs_sequence);
+#endif
+}
+
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
new file mode 100644
index 0000000000000000000000000000000000000000..24134358c5b23c5d0575101f170b3a879a8fe999
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -0,0 +1,1662 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file PHY/NR_UE_TRANSPORT/transport_proto_ue.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 __NR_TRANSPORT_PROTO_UE__H__
+#define __NR_TRANSPORT_PROTO_UE__H__
+#include "PHY/defs_nr_UE.h"
+//#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
+#include <math.h>
+#include "nfapi_interface.h"
+
+// Functions below implement 36-211 and 36-212
+
+/** @addtogroup _PHY_TRANSPORT_
+ * @{
+ */
+
+/** \fn free_ue_dlsch(NR_UE_DLSCH_t *dlsch)
+    \brief This function frees memory allocated for a particular DLSCH at UE
+    @param dlsch Pointer to DLSCH to be removed
+*/
+void free_ue_dlsch(NR_UE_DLSCH_t *dlsch);
+
+/** \fn new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t abstraction_flag)
+    \brief This function allocates structures for a particular DLSCH at UE
+    @returns Pointer to DLSCH to be removed
+    @param Kmimo Kmimo factor from 36-212/36-213
+    @param Mdlharq Maximum number of HARQ rounds (36-212/36-213)
+    @param Nsoft Soft-LLR buffer size from UE-Category
+    @params N_RB_DL total number of resource blocks (determine the operating BW)
+    @param abstraction_flag Flag to indicate abstracted interface
+*/
+NR_UE_DLSCH_t *new_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint8_t max_turbo_iterations,uint8_t N_RB_DL, uint8_t abstraction_flag);
+
+
+void free_ue_ulsch(NR_UE_ULSCH_t *ulsch);
+
+
+NR_UE_ULSCH_t *new_ue_ulsch(unsigned char N_RB_UL, uint8_t abstraction_flag);
+
+void fill_UE_dlsch_MCH(PHY_VARS_NR_UE *ue,int mcs,int ndi,int rvidx,int eNB_id);
+
+int rx_pmch(PHY_VARS_NR_UE *phy_vars_ue,
+            unsigned char eNB_id,
+            uint8_t subframe,
+            unsigned char symbol);
+
+/** \brief Dump OCTAVE/MATLAB files for PMCH debugging
+    @param phy_vars_ue Pointer to UE variables
+    @param eNB_id index of eNB in ue variables
+    @param coded_bits_per_codeword G from 36.211
+    @param subframe Index of subframe
+    @returns 0 on success
+*/
+void dump_mch(PHY_VARS_NR_UE *phy_vars_ue,uint8_t eNB_id,uint16_t coded_bits_per_codeword,int subframe);
+
+
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream QPSK/QPSK reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qpsk_qpsk(int16_t *stream0_in,
+               int16_t *stream1_in,
+               int16_t *stream0_out,
+               int16_t *rho01,
+               int32_t length);
+
+/** \brief This function perform LLR computation for dual-stream (QPSK/QPSK) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr128p pointer to pointer to symbol in dlsch_llr*/
+int32_t dlsch_qpsk_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
+                            int32_t **rxdataF_comp,
+                            int32_t **rxdataF_comp_i,
+                            int32_t **rho_i,
+                            int16_t *dlsch_llr,
+                            uint8_t symbol,
+                            uint8_t first_symbol_flag,
+                            uint16_t nb_rb,
+                            uint16_t pbch_pss_sss_adj,
+                            int16_t **llr128p);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream QPSK/16QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qpsk_qam16(int16_t *stream0_in,
+                int16_t *stream1_in,
+                short *ch_mag_i,
+                int16_t *stream0_out,
+                int16_t *rho01,
+                int32_t length);
+
+/** \brief This function perform LLR computation for dual-stream (QPSK/16QAM) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr128p pointer to pointer to symbol in dlsch_llr*/
+int32_t dlsch_qpsk_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                             int32_t **rxdataF_comp,
+                             int32_t **rxdataF_comp_i,
+                             int **dl_ch_mag_i, //|h_1|^2*(2/sqrt{10})
+                             int32_t **rho_i,
+                             int16_t *dlsch_llr,
+                             uint8_t symbol,
+                             uint8_t first_symbol_flag,
+                             uint16_t nb_rb,
+                             uint16_t pbch_pss_sss_adj,
+                             int16_t **llr128p);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream QPSK/64QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qpsk_qam64(int16_t *stream0_in,
+                int16_t *stream1_in,
+                short *ch_mag_i,
+                int16_t *stream0_out,
+                int16_t *rho01,
+                int32_t length);
+
+/** \brief This function perform LLR computation for dual-stream (QPSK/64QAM) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr128p pointer to pointer to symbol in dlsch_llr*/
+int32_t dlsch_qpsk_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                             int32_t **rxdataF_comp,
+                             int32_t **rxdataF_comp_i,
+                             int **dl_ch_mag_i, //|h_1|^2*(2/sqrt{10})
+                             int32_t **rho_i,
+                             int16_t *dlsch_llr,
+                             uint8_t symbol,
+                             uint8_t first_symbol_flag,
+                             uint16_t nb_rb,
+                             uint16_t pbch_pss_sss_adj,
+                             int16_t **llr128p);
+
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 16QAM/QPSK reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam16_qpsk(short *stream0_in,
+                short *stream1_in,
+                short *ch_mag,
+                short *stream0_out,
+                short *rho01,
+                int length);
+/** \brief This function perform LLR computation for dual-stream (16QAM/QPSK) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr16p pointer to pointer to symbol in dlsch_llr*/
+int dlsch_16qam_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
+                         int **rxdataF_comp,
+                         int **rxdataF_comp_i,
+                         int **dl_ch_mag,   //|h_0|^2*(2/sqrt{10})
+                         int **rho_i,
+                         short *dlsch_llr,
+                         unsigned char symbol,
+                         unsigned char first_symbol_flag,
+                         unsigned short nb_rb,
+                         uint16_t pbch_pss_sss_adjust,
+                         short **llr16p);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 16QAM/16QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam16_qam16(short *stream0_in,
+                 short *stream1_in,
+                 short *ch_mag,
+                 short *ch_mag_i,
+                 short *stream0_out,
+                 short *rho01,
+                 int length);
+
+/** \brief This function perform LLR computation for dual-stream (16QAM/16QAM) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr16p pointer to pointer to symbol in dlsch_llr*/
+int dlsch_16qam_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                          int **rxdataF_comp,
+                          int **rxdataF_comp_i,
+                          int **dl_ch_mag,   //|h_0|^2*(2/sqrt{10})
+                          int **dl_ch_mag_i, //|h_1|^2*(2/sqrt{10})
+                          int **rho_i,
+                          short *dlsch_llr,
+                          unsigned char symbol,
+                          unsigned char first_symbol_flag,
+                          unsigned short nb_rb,
+                          uint16_t pbch_pss_sss_adjust,
+                          short **llr16p);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 16QAM/64QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam16_qam64(short *stream0_in,
+                 short *stream1_in,
+                 short *ch_mag,
+                 short *ch_mag_i,
+                 short *stream0_out,
+                 short *rho01,
+                 int length);
+
+/** \brief This function perform LLR computation for dual-stream (16QAM/64QAM) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr16p pointer to pointer to symbol in dlsch_llr*/
+int dlsch_16qam_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                          int **rxdataF_comp,
+                          int **rxdataF_comp_i,
+                          int **dl_ch_mag,   //|h_0|^2*(2/sqrt{10})
+                          int **dl_ch_mag_i, //|h_1|^2*(2/sqrt{10})
+                          int **rho_i,
+                          short *dlsch_llr,
+                          unsigned char symbol,
+                          unsigned char first_symbol_flag,
+                          unsigned short nb_rb,
+                          uint16_t pbch_pss_sss_adjust,
+                          short **llr16p);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 64QAM/64QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam64_qpsk(short *stream0_in,
+                short *stream1_in,
+                short *ch_mag,
+                short *stream0_out,
+                short *rho01,
+                int length);
+
+/** \brief This function perform LLR computation for dual-stream (64QAM/64QAM) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr16p pointer to pointer to symbol in dlsch_llr*/
+int dlsch_64qam_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
+                         int **rxdataF_comp,
+                         int **rxdataF_comp_i,
+                         int **dl_ch_mag,
+                         int **rho_i,
+                         short *dlsch_llr,
+                         unsigned char symbol,
+                         unsigned char first_symbol_flag,
+                         unsigned short nb_rb,
+                         uint16_t pbch_pss_sss_adjust,
+                         short **llr16p);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 64QAM/16QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam64_qam16(short *stream0_in,
+                 short *stream1_in,
+                 short *ch_mag,
+                 short *ch_mag_i,
+                 short *stream0_out,
+                 short *rho01,
+                 int length);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 64QAM/16QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam64_qam16_avx2(short *stream0_in,
+                      short *stream1_in,
+                      short *ch_mag,
+                      short *ch_mag_i,
+                      short *stream0_out,
+                      short *rho01,
+                      int length);
+
+/** \brief This function perform LLR computation for dual-stream (64QAM/16QAM) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr16p pointer to pointer to symbol in dlsch_llr*/
+int dlsch_64qam_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                          int **rxdataF_comp,
+                          int **rxdataF_comp_i,
+                          int **dl_ch_mag,
+                          int **dl_ch_mag_i,
+                          int **rho_i,
+                          short *dlsch_llr,
+                          unsigned char symbol,
+                          unsigned char first_symbol_flag,
+                          unsigned short nb_rb,
+                          uint16_t pbch_pss_sss_adjust,
+                          short **llr16p);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 64QAM/64QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam64_qam64(short *stream0_in,
+                 short *stream1_in,
+                 short *ch_mag,
+                 short *ch_mag_i,
+                 short *stream0_out,
+                 short *rho01,
+                 int length);
+
+/** \brief This function computes the LLRs for ML (max-logsum approximation) dual-stream 64QAM/64QAM reception.
+    @param stream0_in Input from channel compensated (MR combined) stream 0
+    @param stream1_in Input from channel compensated (MR combined) stream 1
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param stream0_out Output from LLR unit for stream0
+    @param rho01 Cross-correlation between channels (MR combined)
+    @param length in complex channel outputs*/
+void qam64_qam64_avx2(int32_t *stream0_in,
+                      int32_t *stream1_in,
+                      int32_t *ch_mag,
+                      int32_t *ch_mag_i,
+                      int16_t *stream0_out,
+                      int32_t *rho01,
+                      int length);
+
+/** \brief This function perform LLR computation for dual-stream (64QAM/64QAM) transmission.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param ch_mag   Input from scaled channel magnitude square of h0'*g0
+    @param ch_mag_i Input from scaled channel magnitude square of h0'*g1
+    @param rho_i Correlation between channel of signal and inteference
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag flag to indicate this is the first symbol of the dlsch
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr16p pointer to pointer to symbol in dlsch_llr*/
+int dlsch_64qam_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                          int **rxdataF_comp,
+                          int **rxdataF_comp_i,
+                          int **dl_ch_mag,
+                          int **dl_ch_mag_i,
+                          int **rho_i,
+                          short *dlsch_llr,
+                          unsigned char symbol,
+                          unsigned char first_symbol_flag,
+                          unsigned short nb_rb,
+                          uint16_t pbch_pss_sss_adjust,
+                          //short **llr16p,
+                          uint32_t llr_offset);
+
+
+/** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param dlsch_llr llr output
+    @param symbol OFDM symbol index in sub-frame
+    @param first_symbol_flag
+    @param nb_rb number of RBs for this allocation
+    @param pbch_pss_sss_adj Number of channel bits taken by PBCH/PSS/SSS
+    @param llr128p pointer to pointer to symbol in dlsch_llr
+    @param beamforming_mode beamforming mode
+*/
+int32_t dlsch_qpsk_llr(NR_DL_FRAME_PARMS *frame_parms,
+                       int32_t **rxdataF_comp,
+                       int16_t *dlsch_llr,
+                       uint8_t symbol,
+                       uint8_t first_symbol_flag,
+                       uint16_t nb_rb,
+                       uint16_t pbch_pss_sss_adj,
+                       //int16_t **llr128p,
+                       uint8_t beamforming_mode);
+
+/**
+   \brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
+   @param frame_parms Frame descriptor structure
+   @param rxdataF_comp Compensated channel output
+   @param dlsch_llr llr output
+   @param dl_ch_mag Squared-magnitude of channel in each resource element position corresponding to allocation and weighted for mid-point in 16QAM constellation
+   @param symbol OFDM symbol index in sub-frame
+   @param first_symbol_flag
+   @param nb_rb number of RBs for this allocation
+   @param pbch_pss_sss_adjust  Adjustment factor in RE for PBCH/PSS/SSS allocations
+   @param llr128p pointer to pointer to symbol in dlsch_llr
+   @param beamforming_mode beamforming mode
+*/
+
+int32_t dlsch_qpsk_llr_SIC(NR_DL_FRAME_PARMS *frame_parms,
+                           int **rxdataF_comp,
+                           int32_t **sic_buffer,
+                           int **rho_i,
+                           short *dlsch_llr,
+                           uint8_t num_pdcch_symbols,
+                           uint16_t nb_rb,
+                           uint8_t subframe,
+                           uint16_t mod_order_0,
+                           uint32_t rb_alloc);
+
+void dlsch_16qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                     int32_t **rxdataF_comp,
+                     int16_t *dlsch_llr,
+                     int32_t **dl_ch_mag,
+                     uint8_t symbol,
+                     uint8_t first_symbol_flag,
+                     uint16_t nb_rb,
+                     uint16_t pbch_pss_sss_adjust,
+                     int16_t **llr128p,
+                     uint8_t beamforming_mode);
+/**
+   \brief This function generates log-likelihood ratios (decoder input) for single-stream 16QAM received waveforms
+   @param frame_parms Frame descriptor structure
+   @param rxdataF_comp Compensated channel output
+   @param dlsch_llr llr output
+   @param dl_ch_mag Squared-magnitude of channel in each resource element position corresponding to allocation, weighted by first mid-point of 64-QAM constellation
+   @param dl_ch_magb Squared-magnitude of channel in each resource element position corresponding to allocation, weighted by second mid-point of 64-QAM constellation
+   @param symbol OFDM symbol index in sub-frame
+   @param first_symbol_flag
+   @param nb_rb number of RBs for this allocation
+   @param pbch_pss_sss_adjust PBCH/PSS/SSS RE adjustment (in REs)
+   @param beamforming_mode beamforming mode
+*/
+void dlsch_16qam_llr_SIC (NR_DL_FRAME_PARMS *frame_parms,
+                          int32_t **rxdataF_comp,
+                          int32_t **sic_buffer,  //Q15
+                          int32_t **rho_i,
+                          int16_t *dlsch_llr,
+                          uint8_t num_pdcch_symbols,
+                          int32_t **dl_ch_mag,
+                          uint16_t nb_rb,
+                          uint8_t subframe,
+                          uint16_t mod_order_0,
+                          uint32_t rb_alloc);
+
+void dlsch_64qam_llr_SIC(NR_DL_FRAME_PARMS *frame_parms,
+                         int32_t **rxdataF_comp,
+                         int32_t **sic_buffer,  //Q15
+                         int32_t **rho_i,
+                         int16_t *dlsch_llr,
+                         uint8_t num_pdcch_symbols,
+                         int32_t **dl_ch_mag,
+                         int32_t **dl_ch_magb,
+                         uint16_t nb_rb,
+                         uint8_t subframe,
+                         uint16_t mod_order_0,
+                         uint32_t rb_alloc);
+
+
+void dlsch_64qam_llr(NR_DL_FRAME_PARMS *frame_parms,
+                     int32_t **rxdataF_comp,
+                     int16_t *dlsch_llr,
+                     int32_t **dl_ch_mag,
+                     int32_t **dl_ch_magb,
+                     uint8_t symbol,
+                     uint8_t first_symbol_flag,
+                     uint16_t nb_rb,
+                     uint16_t pbch_pss_sss_adjust,
+                     //int16_t **llr_save,
+                     uint32_t llr_offset,
+                     uint8_t beamforming_mode);
+
+
+/** \fn dlsch_siso(NR_DL_FRAME_PARMS *frame_parms,
+    int32_t **rxdataF_comp,
+    int32_t **rxdataF_comp_i,
+    uint8_t l,
+    uint16_t nb_rb)
+    \brief This function does the first stage of llr computation for SISO, by just extracting the pilots, PBCH and primary/secondary synchronization sequences.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param l symbol in sub-frame
+    @param nb_rb Number of RBs in this allocation
+*/
+
+void dlsch_siso(NR_DL_FRAME_PARMS *frame_parms,
+                int32_t **rxdataF_comp,
+                int32_t **rxdataF_comp_i,
+                uint8_t l,
+                uint16_t nb_rb);
+
+/** \fn dlsch_alamouti(NR_DL_FRAME_PARMS *frame_parms,
+    int32_t **rxdataF_comp,
+    int32_t **dl_ch_mag,
+    int32_t **dl_ch_magb,
+    uint8_t symbol,
+    uint16_t nb_rb)
+    \brief This function does Alamouti combining on RX and prepares LLR inputs by skipping pilots, PBCH and primary/secondary synchronization signals.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param dl_ch_mag First squared-magnitude of channel (16QAM and 64QAM) for LLR computation.  Alamouti combining should be performed on this as well. Result is stored in first antenna position
+    @param dl_ch_magb Second squared-magnitude of channel (64QAM only) for LLR computation.  Alamouti combining should be performed on this as well. Result is stored in first antenna position
+    @param symbol Symbol in sub-frame
+    @param nb_rb Number of RBs in this allocation
+*/
+void dlsch_alamouti(NR_DL_FRAME_PARMS *frame_parms,
+                    int32_t **rxdataF_comp,
+                    int32_t **dl_ch_mag,
+                    int32_t **dl_ch_magb,
+                    uint8_t symbol,
+                    uint16_t nb_rb);
+
+/** \fn dlsch_antcyc(NR_DL_FRAME_PARMS *frame_parms,
+    int32_t **rxdataF_comp,
+    int32_t **dl_ch_mag,
+    int32_t **dl_ch_magb,
+    uint8_t symbol,
+    uint16_t nb_rb)
+    \brief This function does antenna selection (based on antenna cycling pattern) on RX and prepares LLR inputs by skipping pilots, PBCH and primary/secondary synchronization signals.  Note that this is not LTE, it is just included for comparison purposes.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param dl_ch_mag First squared-magnitude of channel (16QAM and 64QAM) for LLR computation.  Alamouti combining should be performed on this as well. Result is stored in first antenna position
+    @param dl_ch_magb Second squared-magnitude of channel (64QAM only) for LLR computation.  Alamouti combining should be performed on this as well. Result is stored in first antenna position
+    @param symbol Symbol in sub-frame
+    @param nb_rb Number of RBs in this allocation
+*/
+void dlsch_antcyc(NR_DL_FRAME_PARMS *frame_parms,
+                  int32_t **rxdataF_comp,
+                  int32_t **dl_ch_mag,
+                  int32_t **dl_ch_magb,
+                  uint8_t symbol,
+                  uint16_t nb_rb);
+
+/** \fn dlsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
+    int32_t **rxdataF_comp,
+    int32_t **rxdataF_comp_i,
+    int32_t **rho,
+    int32_t **rho_i,
+    int32_t **dl_ch_mag,
+    int32_t **dl_ch_magb,
+    uint8_t symbol,
+    uint16_t nb_rb,
+    uint8_t dual_stream_UE)
+
+    \brief This function does maximal-ratio combining for dual-antenna receivers.
+    @param frame_parms Frame descriptor structure
+    @param rxdataF_comp Compensated channel output
+    @param rxdataF_comp_i Compensated channel output for interference
+    @param rho Cross correlation between spatial channels
+    @param rho_i Cross correlation between signal and inteference channels
+    @param dl_ch_mag First squared-magnitude of channel (16QAM and 64QAM) for LLR computation.  Alamouti combining should be performed on this as well. Result is stored in first antenna position
+    @param dl_ch_magb Second squared-magnitude of channel (64QAM only) for LLR computation.  Alamouti combining should be performed on this as well. Result is stored in first antenna position
+    @param symbol Symbol in sub-frame
+    @param nb_rb Number of RBs in this allocation
+    @param dual_stream_UE Flag to indicate dual-stream detection
+*/
+void dlsch_detection_mrc(NR_DL_FRAME_PARMS *frame_parms,
+                         int32_t **rxdataF_comp,
+                         int32_t **rxdataF_comp_i,
+                         int32_t **rho,
+                         int32_t **rho_i,
+                         int32_t **dl_ch_mag,
+                         int32_t **dl_ch_magb,
+                         int32_t **dl_ch_mag_i,
+                         int32_t **dl_ch_magb_i,
+                         uint8_t symbol,
+                         uint16_t nb_rb,
+                         uint8_t dual_stream_UE);
+
+void dlsch_detection_mrc_TM34(NR_DL_FRAME_PARMS *frame_parms,
+                              NR_UE_PDSCH *lte_ue_pdsch_vars,
+                              int harq_pid,
+                              int round,
+                              unsigned char symbol,
+                              unsigned short nb_rb,
+                              unsigned char dual_stream_UE);
+
+/** \fn dlsch_extract_rbs_single(int32_t **rxdataF,
+    int32_t **dl_ch_estimates,
+    int32_t **rxdataF_ext,
+    int32_t **dl_ch_estimates_ext,
+    uint16_t pmi,
+    uint8_t *pmi_ext,
+    uint32_t *rb_alloc,
+    uint8_t symbol,
+    uint8_t subframe,
+    NR_DL_FRAME_PARMS *frame_parms)
+    \brief This function extracts the received resource blocks, both channel estimates and data symbols,
+    for the current allocation and for single antenna eNB transmission.
+    @param rxdataF Raw FFT output of received signal
+    @param dl_ch_estimates Channel estimates of current slot
+    @param rxdataF_ext FFT output for RBs in this allocation
+    @param dl_ch_estimates_ext Channel estimates for RBs in this allocation
+    @param pmi subband Precoding matrix indicator
+    @param pmi_ext Extracted PMI for chosen RBs
+    @param rb_alloc RB allocation vector
+    @param symbol Symbol to extract
+    @param subframe Subframe number
+    @param vrb_type Flag to indicate distributed VRB type
+    @param high_speed_flag
+    @param frame_parms Pointer to frame descriptor
+*/
+uint16_t dlsch_extract_rbs_single(int32_t **rxdataF,
+                                  int32_t **dl_ch_estimates,
+                                  int32_t **rxdataF_ext,
+                                  int32_t **dl_ch_estimates_ext,
+                                  uint16_t pmi,
+                                  uint8_t *pmi_ext,
+                                  uint32_t *rb_alloc,
+                                  uint8_t symbol,
+                                  uint8_t subframe,
+                                  uint32_t high_speed_flag,
+                                  NR_DL_FRAME_PARMS *frame_parms);
+
+/** \fn dlsch_extract_rbs_dual(int32_t **rxdataF,
+    int32_t **dl_ch_estimates,
+    int32_t **rxdataF_ext,
+    int32_t **dl_ch_estimates_ext,
+    uint16_t pmi,
+    uint8_t *pmi_ext,
+    uint32_t *rb_alloc,
+    uint8_t symbol,
+    NR_DL_FRAME_PARMS *frame_parms)
+    \brief This function extracts the received resource blocks, both channel estimates and data symbols,
+    for the current allocation and for dual antenna eNB transmission.
+    @param rxdataF Raw FFT output of received signal
+    @param dl_ch_estimates Channel estimates of current slot
+    @param rxdataF_ext FFT output for RBs in this allocation
+    @param dl_ch_estimates_ext Channel estimates for RBs in this allocation
+    @param pmi subband Precoding matrix indicator
+    @param pmi_ext Extracted PMI for chosen RBs
+    @param rb_alloc RB allocation vector
+    @param symbol Symbol to extract
+    @param subframe Subframe index
+    @param high_speed_flag
+    @param frame_parms Pointer to frame descriptor
+*/
+uint16_t dlsch_extract_rbs_dual(int32_t **rxdataF,
+                                int32_t **dl_ch_estimates,
+                                int32_t **rxdataF_ext,
+                                int32_t **dl_ch_estimates_ext,
+                                uint16_t pmi,
+                                uint8_t *pmi_ext,
+                                uint32_t *rb_alloc,
+                                uint8_t symbol,
+                                uint8_t subframe,
+                                uint32_t high_speed_flag,
+                                NR_DL_FRAME_PARMS *frame_parms,
+                                MIMO_mode_t mimo_mode);
+
+/** \fn dlsch_extract_rbs_TM7(int32_t **rxdataF,
+    int32_t **dl_bf_ch_estimates,
+    int32_t **rxdataF_ext,
+    int32_t **dl_bf_ch_estimates_ext,
+    uint32_t *rb_alloc,
+    uint8_t symbol,
+    uint8_t subframe,
+    uint32_t high_speed_flag,
+    NR_DL_FRAME_PARMS *frame_parms)
+    \brief This function extracts the received resource blocks, both channel estimates and data symbols,
+    for the current allocation and for single antenna eNB transmission.
+    @param rxdataF Raw FFT output of received signal
+    @param dl_bf_ch_estimates Beamforming channel estimates of current slot
+    @param rxdataF_ext FFT output for RBs in this allocation
+    @param dl_bf_ch_estimates_ext Beamforming channel estimates for RBs in this allocation
+    @param rb_alloc RB allocation vector
+    @param symbol Symbol to extract
+    @param subframe Subframe number
+    @param high_speed_flag
+    @param frame_parms Pointer to frame descriptor
+*/
+uint16_t dlsch_extract_rbs_TM7(int32_t **rxdataF,
+                               int32_t **dl_bf_ch_estimates,
+                               int32_t **rxdataF_ext,
+                               int32_t **dl_bf_ch_estimates_ext,
+                               uint32_t *rb_alloc,
+                               uint8_t symbol,
+                               uint8_t subframe,
+                               uint32_t high_speed_flag,
+                               NR_DL_FRAME_PARMS *frame_parms);
+
+/** \brief This function performs channel compensation (matched filtering) on the received RBs for this allocation.  In addition, it computes the squared-magnitude of the channel with weightings for 16QAM/64QAM detection as well as dual-stream detection (cross-correlation)
+    @param rxdataF_ext Frequency-domain received signal in RBs to be demodulated
+    @param dl_ch_estimates_ext Frequency-domain channel estimates in RBs to be demodulated
+    @param dl_ch_mag First Channel magnitudes (16QAM/64QAM)
+    @param dl_ch_magb Second weighted Channel magnitudes (64QAM)
+    @param rxdataF_comp Compensated received waveform
+    @param rho Cross-correlation between two spatial channels on each RX antenna
+    @param frame_parms Pointer to frame descriptor
+    @param symbol Symbol on which to operate
+    @param first_symbol_flag set to 1 on first DLSCH symbol
+    @param mod_order Modulation order of allocation
+    @param nb_rb Number of RBs in allocation
+    @param output_shift Rescaling for compensated output (should be energy-normalizing)
+    @param phy_measurements Pointer to UE PHY measurements
+*/
+void dlsch_channel_compensation(int32_t **rxdataF_ext,
+                                int32_t **dl_ch_estimates_ext,
+                                int32_t **dl_ch_mag,
+                                int32_t **dl_ch_magb,
+                                int32_t **rxdataF_comp,
+                                int32_t **rho,
+                                NR_DL_FRAME_PARMS *frame_parms,
+                                uint8_t symbol,
+                                uint8_t first_symbol_flag,
+                                uint8_t mod_order,
+                                uint16_t nb_rb,
+                                uint8_t output_shift,
+                                PHY_NR_MEASUREMENTS *phy_measurements);
+
+void dlsch_dual_stream_correlation(NR_DL_FRAME_PARMS *frame_parms,
+                                   unsigned char symbol,
+                                   unsigned short nb_rb,
+                                   int **dl_ch_estimates_ext,
+                                   int **dl_ch_estimates_ext_i,
+                                   int **dl_ch_rho_ext,
+                                   unsigned char output_shift);
+
+void dlsch_dual_stream_correlationTM34(NR_DL_FRAME_PARMS *frame_parms,
+                                   unsigned char symbol,
+                                   unsigned short nb_rb,
+                                   int **dl_ch_estimates_ext,
+                                   int **dl_ch_estimates_ext_i,
+                                   int **dl_ch_rho_ext,
+                                   unsigned char output_shift0,
+                                   unsigned char output_shift1);
+//This function is used to compute multiplications in Hhermitian * H matrix
+void conjch0_mult_ch1(int *ch0,
+                      int *ch1,
+                      int32_t *ch0conj_ch1,
+                      unsigned short nb_rb,
+                      unsigned char output_shift0);
+
+void construct_HhH_elements(int *ch0conj_ch0,
+                         int *ch1conj_ch1,
+                         int *ch2conj_ch2,
+                         int *ch3conj_ch3,
+                         int *ch0conj_ch1,
+                         int *ch1conj_ch0,
+                         int *ch2conj_ch3,
+                         int *ch3conj_ch2,
+                         int32_t *after_mf_00,
+                         int32_t *after_mf_01,
+                         int32_t *after_mf_10,
+                         int32_t *after_mf_11,
+                         unsigned short nb_rb);
+
+void squared_matrix_element(int32_t *Hh_h_00,
+                            int32_t *Hh_h_00_sq,
+                            unsigned short nb_rb);
+
+void dlsch_channel_level_TM34_meas(int *ch00,
+                                   int *ch01,
+                                   int *ch10,
+                                   int *ch11,
+                                   int *avg_0,
+                                   int *avg_1,
+                                   unsigned short nb_rb);
+
+void det_HhH(int32_t *after_mf_00,
+             int32_t *after_mf_01,
+             int32_t *after_mf_10,
+             int32_t *after_mf_11,
+             int32_t *det_fin_128,
+             unsigned short nb_rb);
+
+void numer(int32_t *Hh_h_00_sq,
+           int32_t *Hh_h_01_sq,
+           int32_t *Hh_h_10_sq,
+           int32_t *Hh_h_11_sq,
+           int32_t *num_fin,
+           unsigned short nb_rb);
+
+uint8_t rank_estimation_tm3_tm4(int *dl_ch_estimates_00,
+                                int *dl_ch_estimates_01,
+                                int *dl_ch_estimates_10,
+                                int *dl_ch_estimates_11,
+                                unsigned short nb_rb);
+
+void dlsch_channel_compensation_TM56(int **rxdataF_ext,
+                                     int **dl_ch_estimates_ext,
+                                     int **dl_ch_mag,
+                                     int **dl_ch_magb,
+                                     int **rxdataF_comp,
+                                     unsigned char *pmi_ext,
+                                     NR_DL_FRAME_PARMS *frame_parms,
+                                     PHY_NR_MEASUREMENTS *phy_measurements,
+                                     int eNB_id,
+                                     unsigned char symbol,
+                                     unsigned char mod_order,
+                                     unsigned short nb_rb,
+                                     unsigned char output_shift,
+                                     unsigned char dl_power_off);
+
+
+void dlsch_channel_compensation_TM34(NR_DL_FRAME_PARMS *frame_parms,
+                                    NR_UE_PDSCH *lte_ue_pdsch_vars,
+                                    PHY_NR_MEASUREMENTS *phy_measurements,
+                                    int eNB_id,
+                                    unsigned char symbol,
+                                    unsigned char mod_order0,
+                                    unsigned char mod_order1,
+                                    int harq_pid,
+                                    int round,
+                                    MIMO_mode_t mimo_mode,
+                                    unsigned short nb_rb,
+                                    unsigned char output_shift0,
+                                    unsigned char output_shift1);
+
+
+/** \brief This function computes the average channel level over all allocated RBs and antennas (TX/RX) in order to compute output shift for compensated signal
+    @param dl_ch_estimates_ext Channel estimates in allocated RBs
+    @param frame_parms Pointer to frame descriptor
+    @param avg Pointer to average signal strength
+    @param pilots_flag Flag to indicate pilots in symbol
+    @param nb_rb Number of allocated RBs
+*/
+void dlsch_channel_level(int32_t **dl_ch_estimates_ext,
+                         NR_DL_FRAME_PARMS *frame_parms,
+                         int32_t *avg,
+                         uint8_t pilots_flag,
+                         uint16_t nb_rb);
+
+
+void dlsch_channel_level_TM34(int **dl_ch_estimates_ext,
+                              NR_DL_FRAME_PARMS *frame_parms,
+                              unsigned char *pmi_ext,
+                              int *avg_0,
+                              int *avg_1,
+                              uint8_t symbol,
+                              unsigned short nb_rb,
+                              MIMO_mode_t mimo_mode);
+
+
+void dlsch_channel_level_TM56(int32_t **dl_ch_estimates_ext,
+                              NR_DL_FRAME_PARMS *frame_parms,
+                              unsigned char *pmi_ext,
+                              int32_t *avg,
+                              uint8_t symbol_mod,
+                              uint16_t nb_rb);
+
+void dlsch_channel_level_TM7(int32_t **dl_bf_ch_estimates_ext,
+                         NR_DL_FRAME_PARMS *frame_parms,
+                         int32_t *avg,
+                         uint8_t pilots_flag,
+                         uint16_t nb_rb);
+
+void dlsch_scale_channel(int32_t **dl_ch_estimates_ext,
+                         NR_DL_FRAME_PARMS *frame_parms,
+                         NR_UE_DLSCH_t **dlsch_ue,
+                         uint8_t symbol_mod,
+                         uint16_t nb_rb);
+
+/** \brief This is the top-level entry point for DLSCH decoding in UE.  It should be replicated on several
+    threads (on multi-core machines) corresponding to different HARQ processes. The routine first
+    computes the segmentation information, followed by rate dematching and sub-block deinterleaving the of the
+    received LLRs computed by dlsch_demodulation for each transport block segment. It then calls the
+    turbo-decoding algorithm for each segment and stops after either after unsuccesful decoding of at least
+    one segment or correct decoding of all segments.  Only the segment CRCs are check for the moment, the
+    overall CRC is ignored.  Finally transport block reassembly is performed.
+    @param phy_vars_ue Pointer to ue variables
+    @param dlsch_llr Pointer to LLR values computed by dlsch_demodulation
+    @param lte_frame_parms Pointer to frame descriptor
+    @param dlsch Pointer to DLSCH descriptor
+    @param frame Frame number
+    @param subframe Subframe number
+    @param num_pdcch_symbols Number of PDCCH symbols
+    @param is_crnti indicates if PDSCH belongs to a CRNTI (necessary for parallelizing decoding threads)
+    @param llr8_flag If 1, indicate that the 8-bit turbo decoder should be used
+    @returns 0 on success, 1 on unsuccessful decoding
+*/
+uint32_t dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
+                        int16_t *dlsch_llr,
+                        NR_DL_FRAME_PARMS *lte_frame_parms,
+                        NR_UE_DLSCH_t *dlsch,
+                        NR_DL_UE_HARQ_t *harq_process,
+                        uint32_t frame,
+                        uint8_t subframe,
+                        uint8_t harq_pid,
+                        uint8_t is_crnti,
+                        uint8_t llr8_flag);
+
+
+uint32_t dlsch_decoding_emul(PHY_VARS_NR_UE *phy_vars_ue,
+                             uint8_t subframe,
+                             PDSCH_t dlsch_id,
+                             uint8_t eNB_id);
+
+/** \brief This function is the top-level entry point to PDSCH demodulation, after frequency-domain transformation and channel estimation.  It performs
+    - RB extraction (signal and channel estimates)
+    - channel compensation (matched filtering)
+    - RE extraction (pilot, PBCH, synch. signals)
+    - antenna combining (MRC, Alamouti, cycling)
+    - LLR computation
+    This function supports TM1, 2, 3, 5, and 6.
+    @param PHY_VARS_NR_UE Pointer to PHY variables
+    @param type Type of PDSCH (SI_PDSCH,RA_PDSCH,PDSCH,PMCH)
+    @param eNB_id eNb index (Nid1) 0,1,2
+    @param eNB_id_i Interfering eNB index (Nid1) 0,1,2, or 3 in case of MU-MIMO IC receiver
+    @param subframe Subframe number
+    @param symbol Symbol on which to act (within sub-frame)
+    @param first_symbol_flag set to 1 on first DLSCH symbol
+    @param rx_type. rx_type=RX_IC_single_stream will enable interference cancellation of a second stream when decoding the first stream. In case of TM1, 2, 5, and this can cancel interference from a neighbouring cell given by eNB_id_i. In case of TM5, eNB_id_i should be set to n_connected_eNB to perform multi-user interference cancellation. In case of TM3, eNB_id_i should be set to eNB_id to perform co-channel interference cancellation; this option should be used together with an interference cancellation step [...]. In case of TM3, if rx_type=RX_IC_dual_stream, both streams will be decoded by applying the IC single stream receiver twice.
+    @param i_mod Modulation order of the interfering stream
+*/
+int32_t rx_pdsch(PHY_VARS_NR_UE *phy_vars_ue,
+                 PDSCH_t type,
+                 uint8_t eNB_id,
+                 uint8_t eNB_id_i,
+                 uint32_t frame,
+                 uint8_t subframe,
+                 uint8_t symbol,
+                 uint8_t first_symbol_flag,
+                 RX_type_t rx_type,
+                 uint8_t i_mod,
+                 uint8_t harq_pid);
+
+int32_t rx_pdcch(PHY_VARS_NR_UE *ue,
+                 uint32_t frame,
+                 uint8_t subframe,
+                 uint8_t eNB_id,
+                 MIMO_mode_t mimo_mode,
+                 uint32_t high_speed_flag);
+
+/*! \brief Extract PSS and SSS resource elements
+  @param phy_vars_ue Pointer to UE variables
+  @param[out] pss_ext contain the PSS signals after the extraction
+  @param[out] sss_ext contain the SSS signals after the extraction
+  @returns 0 on success
+*/
+int pss_sss_extract(PHY_VARS_NR_UE *phy_vars_ue,
+                    int32_t pss_ext[4][72],
+                    int32_t sss_ext[4][72],
+                                        uint8_t subframe);
+
+/*! \brief Extract only PSS resource elements
+  @param phy_vars_ue Pointer to UE variables
+  @param[out] pss_ext contain the PSS signals after the extraction
+  @returns 0 on success
+*/
+int pss_only_extract(PHY_VARS_NR_UE *phy_vars_ue,
+                    int32_t pss_ext[4][72],
+                    uint8_t subframe);
+
+/*! \brief Extract only SSS resource elements
+  @param phy_vars_ue Pointer to UE variables
+  @param[out] sss_ext contain the SSS signals after the extraction
+  @returns 0 on success
+*/
+int sss_only_extract(PHY_VARS_NR_UE *phy_vars_ue,
+                    int32_t sss_ext[4][72],
+                    uint8_t subframe);
+
+/*! \brief Performs detection of SSS to find cell ID and other framing parameters (FDD/TDD, normal/extended prefix)
+  @param phy_vars_ue Pointer to UE variables
+  @param tot_metric Pointer to variable containing maximum metric under framing hypothesis (to be compared to other hypotheses
+  @param flip_max Pointer to variable indicating if start of frame is in second have of RX buffer (i.e. PSS/SSS is flipped)
+  @param phase_max Pointer to variable (0 ... 6) containing rought phase offset between PSS and SSS (can be used for carrier
+  frequency adjustment. 0 means -pi/3, 6 means pi/3.
+  @returns 0 on success
+*/
+int rx_sss(PHY_VARS_NR_UE *phy_vars_ue,int32_t *tot_metric,uint8_t *flip_max,uint8_t *phase_max);
+
+/*! \brief receiver for the PBCH
+  \returns number of tx antennas or -1 if error
+*/
+uint16_t rx_pbch(NR_UE_COMMON *lte_ue_common_vars,
+                 NR_UE_PBCH *lte_ue_pbch_vars,
+                 NR_DL_FRAME_PARMS *frame_parms,
+                 uint8_t eNB_id,
+                 MIMO_mode_t mimo_mode,
+                 uint32_t high_speed_flag,
+                 uint8_t frame_mod4);
+
+uint16_t rx_pbch_emul(PHY_VARS_NR_UE *phy_vars_ue,
+                      uint8_t eNB_id,
+                      uint8_t pbch_phase);
+
+
+/*! \brief PBCH unscrambling
+  This is similar to pbch_scrabling with the difference that inputs are signed s16s (llr values) and instead of flipping bits we change signs.
+  \param frame_parms Pointer to frame descriptor
+  \param llr Output of the demodulator
+  \param length Length of the sequence
+  \param frame_mod4 Frame number modulo 4*/
+void pbch_unscrambling(NR_DL_FRAME_PARMS *frame_parms,
+                       int8_t* llr,
+                       uint32_t length,
+                       uint8_t frame_mod4);
+
+
+void generate_64qam_table(void);
+void generate_16qam_table(void);
+void generate_qpsk_table(void);
+
+uint16_t extract_crc(uint8_t *dci,uint8_t DCI_LENGTH);
+
+/*! \brief LLR from two streams. This function takes two streams (qpsk modulated) and calculates the LLR, considering one stream as interference.
+  \param stream0_in pointer to first stream0
+  \param stream1_in pointer to first stream1
+  \param stream0_out pointer to output stream
+  \param rho01 pointer to correlation matrix
+  \param length*/
+void qpsk_qpsk_TM3456(short *stream0_in,
+                      short *stream1_in,
+                      short *stream0_out,
+                      short *rho01,
+                      int length
+                     );
+
+/** \brief Attempt decoding of a particular DCI with given length and format.
+    @param DCI_LENGTH length of DCI in bits
+    @param DCI_FMT Format of DCI
+    @param e e-sequence (soft bits)
+    @param decoded_output Output of Viterbi decoder
+*/
+void dci_decoding(uint8_t DCI_LENGTH,
+                  uint8_t DCI_FMT,
+                  int8_t *e,
+                  uint8_t *decoded_output);
+
+/** \brief Do 36.213 DCI decoding procedure by searching different RNTI options and aggregation levels.  Currently does
+    not employ the complexity reducing procedure based on RNTI.
+    @param phy_vars_ue UE variables
+    @param dci_alloc Pointer to DCI_ALLOC_t array to store results for DLSCH/ULSCH programming
+    @param do_common If 1 perform search in common search-space else ue-specific search-space
+    @param eNB_id eNB Index on which to act
+    @param subframe Index of subframe
+    @returns bitmap of occupied CCE positions (i.e. those detected)
+*/
+uint16_t dci_decoding_procedure(PHY_VARS_NR_UE *phy_vars_ue,
+                                DCI_ALLOC_t *dci_alloc,
+                                int do_common,
+                                int16_t eNB_id,
+                                uint8_t subframe);
+
+uint16_t dci_CRNTI_decoding_procedure(PHY_VARS_NR_UE *ue,
+                                DCI_ALLOC_t *dci_alloc,
+                                uint8_t DCIFormat,
+                                uint8_t agregationLevel,
+                                int16_t eNB_id,
+                                uint8_t subframe);
+
+uint16_t dci_decoding_procedure_emul(NR_UE_PDCCH **lte_ue_pdcch_vars,
+                                     uint8_t num_ue_spec_dci,
+                                     uint8_t num_common_dci,
+                                     DCI_ALLOC_t *dci_alloc_tx,
+                                     DCI_ALLOC_t *dci_alloc_rx,
+                                     int16_t eNB_id);
+
+/** \brief Compute Q (modulation order) based on I_MCS PDSCH.  Implements table 7.1.7.1-1 from 36.213.
+    @param I_MCS */
+uint8_t get_Qm(uint8_t I_MCS);
+
+/** \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(uint8_t I_MCS);
+
+/** \brief Compute I_TBS (transport-block size) based on I_MCS for PDSCH.  Implements table 7.1.7.1-1 from 36.213.
+    @param I_MCS */
+uint8_t get_I_TBS(uint8_t I_MCS);
+
+/** \brief Compute I_TBS (transport-block size) based on I_MCS for PUSCH.  Implements table 8.6.1-1 from 36.213.
+    @param I_MCS */
+unsigned char get_I_TBS_UL(unsigned char I_MCS);
+
+/** \brief Compute Q (modulation order) based on downlink I_MCS. Implements table 7.1.7.1-1 from 36.213.
+    @param I_MCS
+    @param nb_rb
+    @return Transport block size */
+uint32_t get_TBS_DL(uint8_t mcs, uint16_t nb_rb);
+
+/** \brief Compute Q (modulation order) based on uplink I_MCS. Implements table 7.1.7.1-1 from 36.213.
+    @param I_MCS
+    @param nb_rb
+    @return Transport block size */
+uint32_t get_TBS_UL(uint8_t mcs, uint16_t nb_rb);
+
+/* \brief Return bit-map of resource allocation for a given DCI rballoc (RIV format) and vrb type
+   @param N_RB_DL number of PRB on DL
+   @param indicator for even/odd slot
+   @param vrb vrb index
+   @param Ngap Gap indicator
+*/
+uint32_t get_prb(int N_RB_DL,int odd_slot,int vrb,int Ngap);
+
+/* \brief Return prb for a given vrb index
+   @param vrb_type VRB type (0=localized,1=distributed)
+   @param rb_alloc_dci rballoc field from DCI
+*/
+uint32_t get_rballoc(vrb_t vrb_type,uint16_t rb_alloc_dci);
+
+
+/* \brief Return bit-map of resource allocation for a given DCI rballoc (RIV format) and vrb type
+   @returns Transmission mode (1-7)
+*/
+uint8_t get_transmission_mode(module_id_t Mod_id, uint8_t CC_id, rnti_t rnti);
+
+
+/* \brief
+   @param ra_header Header of resource allocation (0,1) (See sections 7.1.6.1/7.1.6.2 of 36.213 Rel8.6)
+   @param rb_alloc Bitmap allocation from DCI (format 1,2)
+   @returns number of physical resource blocks
+*/
+uint32_t conv_nprb(uint8_t ra_header,uint32_t rb_alloc,int N_RB_DL);
+
+int get_G(NR_DL_FRAME_PARMS *frame_parms,uint16_t nb_rb,uint32_t *rb_alloc,uint8_t mod_order,uint8_t Nl,uint8_t num_pdcch_symbols,int frame,uint8_t subframe, uint8_t beamforming_mode);
+
+int adjust_G(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe);
+int adjust_G2(NR_DL_FRAME_PARMS *frame_parms,uint32_t *rb_alloc,uint8_t mod_order,uint8_t subframe,uint8_t symbol);
+
+
+#ifndef modOrder
+#define modOrder(I_MCS,I_TBS) ((I_MCS-I_TBS)*2+2) // Find modulation order from I_TBS and I_MCS
+#endif
+
+/** \fn uint8_t I_TBS2I_MCS(uint8_t I_TBS);
+    \brief This function maps I_tbs to I_mcs according to Table 7.1.7.1-1 in 3GPP TS 36.213 V8.6.0. Where there is two supported modulation orders for the same I_TBS then either high or low modulation is chosen by changing the equality of the two first comparisons in the if-else statement.
+    \param I_TBS Index of Transport Block Size
+    \return I_MCS given I_TBS
+*/
+uint8_t I_TBS2I_MCS(uint8_t I_TBS);
+
+/** \fn uint8_t SE2I_TBS(float SE,
+    uint8_t N_PRB,
+    uint8_t symbPerRB);
+    \brief This function maps a requested throughput in number of bits to I_tbs. The throughput is calculated as a function of modulation order, RB allocation and number of symbols per RB. The mapping orginates in the "Transport block size table" (Table 7.1.7.2.1-1 in 3GPP TS 36.213 V8.6.0)
+    \param SE Spectral Efficiency (before casting to integer, multiply by 1024, remember to divide result by 1024!)
+    \param N_PRB Number of PhysicalResourceBlocks allocated \sa lte_frame_parms->N_RB_DL
+    \param symbPerRB Number of symbols per resource block allocated to this channel
+    \return I_TBS given an SE and an N_PRB
+*/
+uint8_t SE2I_TBS(float SE,
+                 uint8_t N_PRB,
+                 uint8_t symbPerRB);
+/** \brief This function generates the sounding reference symbol (SRS) for the uplink according to 36.211 v8.6.0. If IFFT_FPGA is defined, the SRS is quantized to a QPSK sequence.
+    @param frame_parms LTE DL Frame Parameters
+    @param soundingrs_ul_config_dedicated Dynamic configuration from RRC during Connection Establishment
+    @param txdataF pointer to the frequency domain TX signal
+    @returns 0 on success*/
+int generate_srs(NR_DL_FRAME_PARMS *frame_parms,
+		 SOUNDINGRS_UL_CONFIG_DEDICATED *soundingrs_ul_config_dedicated,
+		 int *txdataF,
+		 int16_t amp,
+		 uint32_t subframe);
+
+
+/*!
+  \brief This function is similar to generate_srs_tx but generates a conjugate sequence for channel estimation. If IFFT_FPGA is defined, the SRS is quantized to a QPSK sequence.
+  @param phy_vars_ue Pointer to PHY_VARS structure
+  @param eNB_id Index of destination eNB for this SRS
+  @param amp Linear amplitude of SRS
+  @param subframe Index of subframe on which to act
+  @returns 0 on success, -1 on error with message
+*/
+
+int32_t generate_srs_tx(PHY_VARS_NR_UE *phy_vars_ue,
+                        uint8_t eNB_id,
+                        int16_t amp,
+                        uint32_t subframe);
+
+/*!
+  \brief This function generates the downlink reference signal for the PUSCH according to 36.211 v8.6.0. The DRS occuies the RS defined by rb_alloc and the symbols 2 and 8 for extended CP and 3 and 10 for normal CP.
+*/
+
+int32_t generate_drs_pusch(PHY_VARS_NR_UE *phy_vars_ue,
+                           UE_nr_rxtx_proc_t *proc,
+                           uint8_t eNB_id,
+                           int16_t amp,
+                           uint32_t subframe,
+                           uint32_t first_rb,
+                           uint32_t nb_rb,
+                           uint8_t ant);
+
+/*!
+  \brief This function initializes the Group Hopping, Sequence Hopping and nPRS sequences for PUCCH/PUSCH according to 36.211 v8.6.0. It should be called after configuration of UE (reception of SIB2/3) and initial configuration of eNB (or after reconfiguration of cell-specific parameters).
+  @param frame_parms Pointer to a NR_DL_FRAME_PARMS structure (eNB or UE)*/
+void init_ul_hopping(NR_DL_FRAME_PARMS *frame_parms);
+
+
+/*!
+  \brief This function implements the initialization of paging parameters for UE (See Section 7, 36.304).It must be called after setting IMSImod1024 during UE startup and after receiving SIB2
+  @param ue Pointer to UE context
+  @param defaultPagingCycle T from 36.304 (0=32,1=64,2=128,3=256)
+  @param nB nB from 36.304 (0=4T,1=2T,2=T,3=T/2,4=T/4,5=T/8,6=T/16,7=T/32*/
+int init_ue_paging_info(PHY_VARS_NR_UE *ue, long defaultPagingCycle, long nB);
+
+int32_t compareints (const void * a, const void * b);
+
+
+void ulsch_modulation(int32_t **txdataF,
+                      int16_t amp,
+                      frame_t frame,
+                      uint32_t subframe,
+                      NR_DL_FRAME_PARMS *frame_parms,
+                      NR_UE_ULSCH_t *ulsch);
+
+
+
+
+
+
+int generate_ue_dlsch_params_from_dci(int frame,
+                                      uint8_t subframe,
+                                      void *dci_pdu,
+                                      rnti_t rnti,
+                                      DCI_format_t dci_format,
+                                      NR_UE_PDCCH *pdcch_vars,
+                                      NR_UE_PDSCH *pdsch_vars,
+                                      NR_UE_DLSCH_t **dlsch,
+                                      NR_DL_FRAME_PARMS *frame_parms,
+                                      PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
+                                      uint16_t si_rnti,
+                                      uint16_t ra_rnti,
+                                      uint16_t p_rnti,
+                                      uint8_t beamforming_mode,
+                                      uint16_t tc_rnti);
+
+
+int generate_ue_ulsch_params_from_dci(void *dci_pdu,
+                                      rnti_t rnti,
+                                      uint8_t subframe,
+                                      DCI_format_t dci_format,
+                                      PHY_VARS_NR_UE *phy_vars_ue,
+                                      UE_nr_rxtx_proc_t *proc,
+                                      uint16_t si_rnti,
+                                      uint16_t ra_rnti,
+                                      uint16_t p_rnti,
+                                      uint16_t cba_rnti,
+                                      uint8_t eNB_id,
+                                      uint8_t use_srs);
+
+int32_t generate_ue_ulsch_params_from_rar(PHY_VARS_NR_UE *phy_vars_ue,
+                                          UE_nr_rxtx_proc_t *proc,
+                                          uint8_t eNB_id);
+double sinr_eff_cqi_calc(PHY_VARS_NR_UE *phy_vars_ue,
+                         uint8_t eNB_id,
+                                                 uint8_t subframe);
+
+uint8_t sinr2cqi(double sinr,uint8_t trans_mode);
+
+
+int dump_dci(NR_DL_FRAME_PARMS *frame_parms, DCI_ALLOC_t *dci);
+
+int dump_ue_stats(PHY_VARS_NR_UE *phy_vars_ue, UE_nr_rxtx_proc_t *proc, char* buffer, int length, runmode_t mode, int input_level_dBm);
+
+
+
+void generate_pcfich_reg_mapping(NR_DL_FRAME_PARMS *frame_parms);
+
+
+void pcfich_unscrambling(NR_DL_FRAME_PARMS *frame_parms,
+                         uint8_t subframe,
+                         int16_t *d);
+
+
+uint8_t rx_pcfich(NR_DL_FRAME_PARMS *frame_parms,
+                  uint8_t subframe,
+                  NR_UE_PDCCH *lte_ue_pdcch_vars,
+                  MIMO_mode_t mimo_mode);
+
+void generate_phich_reg_mapping(NR_DL_FRAME_PARMS *frame_parms);
+
+
+void init_transport_channels(uint8_t);
+
+void generate_RIV_tables(void);
+
+/*!
+  \brief This function performs the initial cell search procedure - PSS detection, SSS detection and PBCH detection.  At the
+  end, the basic frame parameters are known (Frame configuration - TDD/FDD and cyclic prefix length,
+  N_RB_DL, PHICH_CONFIG and Nid_cell) and the UE can begin decoding PDCCH and DLSCH SI to retrieve the rest.  Once these
+  parameters are know, the routine calls some basic initialization routines (cell-specific reference signals, etc.)
+  @param phy_vars_ue Pointer to UE variables
+*/
+int initial_sync(PHY_VARS_NR_UE *phy_vars_ue, runmode_t mode);
+
+
+/*!
+  \brief Encoding of PUSCH/ACK/RI/ACK from 36-212.
+  @param a Pointer to ulsch SDU
+  @param frame_parms Pointer to Frame parameters
+  @param ulsch Pointer to ulsch descriptor
+  @param harq_pid HARQ process ID
+  @param tmode Transmission mode (1-7)
+  @param control_only_flag Generate PUSCH with control information only
+  @param Nbundled Parameter for ACK/NAK bundling (36.213 Section 7.3)
+*/
+uint32_t ulsch_encoding(uint8_t *a,
+                        PHY_VARS_NR_UE *phy_vars_ue,
+                        uint8_t harq_pid,
+                        uint8_t eNB_id,
+                        uint8_t subframe_rx,
+                        uint8_t tmode,
+                        uint8_t control_only_flag,
+                        uint8_t Nbundled);
+
+
+
+
+/* \brief  This routine demodulates the PHICH and updates PUSCH/ULSCH parameters.
+   @param phy_vars_ue Pointer to UE variables
+   @param proc Pointer to RXN_TXNp4 proc
+   @param subframe Subframe of received PDCCH/PHICH
+   @param eNB_id Index of eNB
+*/
+
+void rx_phich(PHY_VARS_NR_UE *phy_vars_ue,
+              UE_nr_rxtx_proc_t *proc,
+              uint8_t subframe,
+              uint8_t eNB_id);
+
+
+/** \brief  This routine provides the relationship between a PHICH TXOp and its corresponding PUSCH subframe (Table 8.3.-1 from 36.213).
+    @param frame_parms Pointer to DL frame configuration parameters
+    @param subframe Subframe of received/transmitted PHICH
+    @returns subframe of PUSCH transmission
+*/
+uint8_t phich_subframe2_pusch_subframe(NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
+
+/** \brief  This routine provides the relationship between a PHICH TXOp and its corresponding PUSCH frame (Table 8.3.-1 from 36.213).
+    @param frame_parms Pointer to DL frame configuration parameters
+    @param frame Frame of received/transmitted PHICH
+    @param subframe Subframe of received/transmitted PHICH
+    @returns frame of PUSCH transmission
+*/
+int phich_frame2_pusch_frame(NR_DL_FRAME_PARMS *frame_parms, int frame, int subframe);
+
+void print_CQI(void *o,UCI_format_t uci_format,uint8_t eNB_id,int N_RB_DL);
+
+void fill_CQI(NR_UE_ULSCH_t *ulsch,PHY_NR_MEASUREMENTS *meas,uint8_t eNB_id, uint8_t harq_pid,int N_RB_DL, rnti_t rnti, uint8_t trans_mode,double sinr_eff);
+
+void reset_cba_uci(void *o);
+
+/** \brief  This routine computes the subband PMI bitmap based on measurements (0,1,2,3 for rank 0 and 0,1 for rank 1) in the format needed for UCI
+    @param meas pointer to measurements
+    @param eNB_id eNB_id
+    @param nb_subbands number of subbands
+    @returns subband PMI bitmap
+*/
+uint16_t quantize_subband_pmi(PHY_NR_MEASUREMENTS *meas,uint8_t eNB_id,int nb_subbands);
+
+int32_t pmi_convert_rank1_from_rank2(uint16_t pmi_alloc, int tpmi, int nb_rb);
+
+uint16_t quantize_subband_pmi2(PHY_NR_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t a_id,int nb_subbands);
+
+
+
+uint64_t cqi2hex(uint32_t cqi);
+
+uint16_t computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs);
+
+
+/** \brief  This routine extracts a single subband PMI from a bitmap coming from UCI or the pmi_extend function
+    @param N_RB_DL number of resource blocks
+    @param mimo_mode
+    @param pmi_alloc subband PMI bitmap
+    @param rb resource block for which to extract PMI
+    @returns subband PMI
+*/
+uint8_t get_pmi(uint8_t N_RB_DL,MIMO_mode_t mode, uint32_t pmi_alloc,uint16_t rb);
+
+int get_nCCE_offset_l1(int *CCE_table,
+                       const unsigned char L,
+                       const int nCCE,
+                       const int common_dci,
+                       const unsigned short rnti,
+                       const unsigned char subframe);
+
+uint16_t get_nCCE(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi);
+
+uint16_t get_nquad(uint8_t num_pdcch_symbols,NR_DL_FRAME_PARMS *frame_parms,uint8_t mi);
+
+uint8_t get_mi(NR_DL_FRAME_PARMS *frame,uint8_t subframe);
+
+uint16_t get_nCCE_mac(uint8_t Mod_id,uint8_t CC_id,int num_pdcch_symbols,int subframe);
+
+uint8_t get_num_pdcch_symbols(uint8_t num_dci,DCI_ALLOC_t *dci_alloc,NR_DL_FRAME_PARMS *frame_parms,uint8_t subframe);
+
+void pdcch_interleaving(NR_DL_FRAME_PARMS *frame_parms,int32_t **z, int32_t **wbar,uint8_t n_symbols_pdcch,uint8_t mi);
+
+void pdcch_unscrambling(NR_DL_FRAME_PARMS *frame_parms,
+                        uint8_t subframe,
+                        int8_t* llr,
+                        uint32_t length);
+
+
+
+void dlsch_unscrambling(NR_DL_FRAME_PARMS *frame_parms,
+                        int mbsfn_flag,
+                        NR_UE_DLSCH_t *dlsch,
+                        int G,
+                        int16_t* llr,
+                        uint8_t q,
+                        uint8_t Ns);
+
+void init_ncs_cell(NR_DL_FRAME_PARMS *frame_parms,uint8_t ncs_cell[20][7]);
+
+void generate_pucch1x(int32_t **txdataF,
+                      NR_DL_FRAME_PARMS *frame_parms,
+                      uint8_t ncs_cell[20][7],
+                      PUCCH_FMT_t fmt,
+                      PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
+                      uint16_t n1_pucch,
+                      uint8_t shortened_format,
+                      uint8_t *payload,
+                      int16_t amp,
+                      uint8_t subframe);
+
+void generate_pucch2x(int32_t **txdataF,
+                      NR_DL_FRAME_PARMS *fp,
+                      uint8_t ncs_cell[20][7],
+                      PUCCH_FMT_t fmt,
+                      PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
+                      uint16_t n2_pucch,
+                      uint8_t *payload,
+                      int A,
+                      int B2,
+                      int16_t amp,
+                      uint8_t subframe,
+                      uint16_t rnti);
+
+void generate_pucch3x(int32_t **txdataF,
+                    NR_DL_FRAME_PARMS *frame_parms,
+                    uint8_t ncs_cell[20][7],
+                    PUCCH_FMT_t fmt,
+                    PUCCH_CONFIG_DEDICATED *pucch_config_dedicated,
+                    uint16_t n3_pucch,
+                    uint8_t shortened_format,
+                    uint8_t *payload,
+                    int16_t amp,
+                    uint8_t subframe,
+                    uint16_t rnti);
+
+
+void init_ulsch_power_LUT(void);
+
+/*!
+  \brief Check for PRACH TXop in subframe
+  @param frame_parms Pointer to NR_DL_FRAME_PARMS
+  @param frame frame index to check
+  @param subframe subframe index to check
+  @returns 0 on success
+*/
+int is_prach_subframe(NR_DL_FRAME_PARMS *frame_parms,frame_t frame, uint8_t subframe);
+
+/*!
+  \brief Generate PRACH waveform
+  @param phy_vars_ue Pointer to ue top-level descriptor
+  @param eNB_id Index of destination eNB
+  @param subframe subframe index to operate on
+  @param index of preamble (0-63)
+  @param Nf System frame number
+  @returns 0 on success
+
+*/
+int32_t generate_prach(PHY_VARS_NR_UE *phy_vars_ue,uint8_t eNB_id,uint8_t subframe,uint16_t Nf);
+
+
+/*!
+  \brief Helper for MAC, returns number of available PRACH in TDD for a particular configuration index
+  @param frame_parms Pointer to NR_DL_FRAME_PARMS structure
+  @returns 0-5 depending on number of available prach
+*/
+uint8_t get_num_prach_tdd(module_id_t Mod_id);
+
+/*!
+  \brief Return the PRACH format as a function of the Configuration Index and Frame type.
+  @param prach_ConfigIndex PRACH Configuration Index
+  @param frame_type 0-FDD, 1-TDD
+  @returns 0-1 accordingly
+*/
+uint8_t get_prach_fmt(uint8_t prach_ConfigIndex,lte_frame_type_t frame_type);
+
+/*!
+  \brief Helper for MAC, returns frequency index of PRACH resource in TDD for a particular configuration index
+  @param frame_parms Pointer to NR_DL_FRAME_PARMS structure
+  @returns 0-5 depending on number of available prach
+*/
+uint8_t get_fid_prach_tdd(module_id_t Mod_id,uint8_t tdd_map_index);
+
+/*!
+  \brief Comp ute DFT of PRACH ZC sequences.  Used for generation of prach in UE and reception of PRACH in eNB.
+  @param rootSequenceIndex PRACH root sequence
+  #param prach_ConfigIndex PRACH Configuration Index
+  @param zeroCorrelationZoneConfig PRACH ncs_config
+  @param highSpeedFlat PRACH High-Speed Flag
+  @param frame_type TDD/FDD flag
+  @param Xu DFT output
+*/
+void compute_prach_seq(uint16_t rootSequenceIndex,
+		       uint8_t prach_ConfigIndex,
+		       uint8_t zeroCorrelationZoneConfig,
+		       uint8_t highSpeedFlag,
+		       lte_frame_type_t frame_type,
+		       uint32_t X_u[64][839]);
+
+
+void init_prach_tables(int N_ZC);
+
+void init_unscrambling_lut(void);
+void init_scrambling_lut(void);
+
+/*!
+  \brief Return the status of MBSFN in this frame/subframe
+  @param frame Frame index
+  @param subframe Subframe index
+  @param frame_parms Pointer to frame parameters
+  @returns 1 if subframe is for MBSFN
+*/
+int is_pmch_subframe(frame_t frame, int subframe, NR_DL_FRAME_PARMS *frame_parms);
+
+uint8_t is_not_pilot(uint8_t pilots, uint8_t re, uint8_t nushift, uint8_t use2ndpilots);
+
+uint8_t is_not_UEspecRS(int8_t lprime, uint8_t re, uint8_t nushift, uint8_t Ncp, uint8_t beamforming_mode);
+
+uint32_t dlsch_decoding_abstraction(double *dlsch_MIPB,
+                                    NR_DL_FRAME_PARMS *lte_frame_parms,
+                                    NR_UE_DLSCH_t *dlsch,
+                                    uint8_t subframe,
+                                    uint8_t num_pdcch_symbols);
+
+// DL power control functions
+double get_pa_dB(uint8_t pa);
+
+
+double computeRhoA_UE(PDSCH_CONFIG_DEDICATED *pdsch_config_dedicated,
+                      NR_UE_DLSCH_t *dlsch_ue,
+                      uint8_t dl_power_off,
+                      uint8_t n_antenna_port);
+
+double computeRhoB_UE(PDSCH_CONFIG_DEDICATED  *pdsch_config_dedicated,
+                      PDSCH_CONFIG_COMMON *pdsch_config_common,
+                      uint8_t n_antenna_port,
+                      NR_UE_DLSCH_t *dlsch_ue,
+                      uint8_t dl_power_off);
+
+/*void compute_sqrt_RhoAoRhoB(PDSCH_CONFIG_DEDICATED  *pdsch_config_dedicated,
+  PDSCH_CONFIG_COMMON *pdsch_config_common,
+  uint8_t n_antenna_port,
+  NR_UE_DLSCH_t *dlsch_ue);
+*/
+
+uint8_t get_prach_prb_offset(NR_DL_FRAME_PARMS *frame_parms,
+			     uint8_t prach_ConfigIndex, 
+			     uint8_t n_ra_prboffset,
+			     uint8_t tdd_mapindex, uint16_t Nf);
+
+
+
+
+
+/**@}*/
+#endif
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
new file mode 100644
index 0000000000000000000000000000000000000000..3ff99c12d6f7a8d64dddba1884cf7fd1ff87853e
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
@@ -0,0 +1,335 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file PHY/NR_TRANSPORT/defs.h
+* \brief data structures for PDSCH/DLSCH/PUSCH/ULSCH physical and transport channel descriptors (TX/RX)
+* \author R. Knopp
+* \date 2011
+* \version 0.1
+* \company Eurecom
+* \email: raymond.knopp@eurecom.fr, florian.kaltenberger@eurecom.fr, oscar.tonelli@yahoo.it
+* \note
+* \warning
+*/
+#ifndef __NR_TRANSPORT_UE__H__
+#define __NR_TRANSPORT_UE__H__
+#include "PHY/defs_nr_UE.h"
+//#include "../LTE_TRANSPORT/dci.h"
+//#include "../LTE_TRANSPORT/mdci.h"
+//#include "../LTE_TRANSPORT/uci_common.h"
+//#include "../LTE_TRANSPORT/transport_common.h"
+#ifndef STANDALONE_COMPILE
+#include "UTIL/LISTS/list.h"
+#endif
+
+//#include "../LTE_TRANSPORT/transport_common.h"
+
+// structures below implement 36-211 and 36-212
+
+/** @addtogroup _PHY_TRANSPORT_
+ * @{
+ */
+
+#define SHRT_MAX   32767
+
+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;
+  /// Flag indicating that this ULSCH has a new packet (start of new round)
+  //  uint8_t Ndi;
+  /// Status Flag indicating for this ULSCH (idle,active,disabled)
+  SCH_status_t status;
+  /// Subframe scheduling indicator (i.e. Transmission opportunity indicator)
+  uint8_t subframe_scheduling_flag;
+  /// Subframe cba scheduling indicator (i.e. Transmission opportunity indicator)
+  uint8_t subframe_cba_scheduling_flag;
+  /// First Allocated RB
+  uint16_t first_rb;
+  /// Current Number of RBs
+  uint16_t nb_rb;
+  /// Last TPC command
+  uint8_t TPC;
+  /// Transport block size
+  uint32_t TBS;
+  /// The payload + CRC size in bits, "B" from 36-212
+  uint32_t B;
+  /// Length of ACK information (bits)
+  uint8_t O_ACK;
+  /// Pointer to the payload
+  uint8_t *b;
+  /// Pointers to transport block segments
+  uint8_t *c[MAX_NUM_ULSCH_SEGMENTS];
+  /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
+  uint32_t RTC[MAX_NUM_ULSCH_SEGMENTS];
+  /// Index of current HARQ round for this ULSCH
+  uint8_t round;
+  /// MCS format of this ULSCH
+  uint8_t mcs;
+  /// Redundancy-version of the current sub-frame
+  uint8_t rvidx;
+  /// Turbo-code outputs (36-212 V8.6 2009-03, p.12
+  uint8_t d[MAX_NUM_ULSCH_SEGMENTS][(96+3+(3*6144))];
+  /// Sub-block interleaver outputs (36-212 V8.6 2009-03, p.16-17)
+  uint8_t w[MAX_NUM_ULSCH_SEGMENTS][3*6144];
+  /// 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;
+  /// Total number of bits across all segments
+  uint32_t sumKr;
+  /// Number of "Filler" bits (for definition see 36-212 V8.6 2009-03, p.10)
+  uint32_t F;
+  /// 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_DMRS2 for cyclic shift of DMRS (36.211 Table 5.5.1.1.-1)
+  uint8_t n_DMRS2;
+  /// Flag to indicate that this is a control only ULSCH (i.e. no MAC SDU)
+  uint8_t control_only;
+  /// Flag to indicate that this is a calibration ULSCH (i.e. no MAC SDU and filled with TDD calibration information)
+  //  int calibration_flag;
+  /// Number of soft channel bits
+  uint32_t G;
+
+  // decode phich
+  uint8_t decode_phich;
+} NR_UL_UE_HARQ_t;
+
+typedef struct {
+  /// Current Number of Symbols
+  uint8_t Nsymb_pusch;
+  /// SRS active flag
+  uint8_t srs_active;
+  /// Pointers to 8 HARQ processes for the ULSCH
+  NR_UL_UE_HARQ_t *harq_processes[8];
+  /// Pointer to CQI data (+1 for 8 bits crc)
+  uint8_t o[1+MAX_CQI_BYTES];
+  /// Length of CQI data (bits)
+  uint8_t O;
+  /// Format of CQI data
+  UCI_format_t uci_format;
+  /// Rank information
+  uint8_t o_RI[2];
+  /// Length of rank information (bits)
+  uint8_t O_RI;
+  /// Pointer to ACK
+  uint8_t o_ACK[4];
+  /// Minimum number of CQI bits for PUSCH (36-212 r8.6, Sec 5.2.4.1 p. 37)
+  uint8_t O_CQI_MIN;
+  /// ACK/NAK Bundling flag
+  uint8_t bundling;
+  /// Concatenated "e"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
+  uint8_t e[MAX_NUM_CHANNEL_BITS];
+  /// Interleaved "h"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
+  uint8_t h[MAX_NUM_CHANNEL_BITS];
+  /// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
+  uint8_t b_tilde[MAX_NUM_CHANNEL_BITS];
+  /// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
+  int32_t d[MAX_NUM_RE];
+  /// Transform-coded "z"-sequences (for definition see 36-211 V8.6 2009-03, p.14-15)
+  int32_t z[MAX_NUM_RE];
+  /// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27)
+  uint8_t q[MAX_CQI_PAYLOAD];
+  /// coded and interleaved CQI bits
+  uint8_t o_w[(MAX_CQI_BITS+8)*3];
+  /// coded CQI bits
+  uint8_t o_d[96+((MAX_CQI_BITS+8)*3)];
+  /// coded ACK bits
+  uint8_t q_ACK[MAX_ACK_PAYLOAD];
+  /// coded RI bits
+  uint8_t q_RI[MAX_RI_PAYLOAD];
+  /// 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;
+  /// power_offset
+  uint8_t power_offset;
+  // for cooperative communication
+  uint8_t cooperation_flag;
+  /// RNTI attributed to this ULSCH
+  uint16_t rnti;
+  /// f_PUSCH parameter for PUSCH power control
+  int16_t f_pusch;
+  /// Po_PUSCH - target output power for PUSCH
+  int16_t Po_PUSCH;
+  /// PHR - current power headroom (based on last PUSCH transmission)
+  int16_t PHR;
+  /// Po_SRS - target output power for SRS
+  int16_t Po_SRS;
+  /// num active cba group
+  uint8_t num_active_cba_groups;
+  /// num dci found for cba
+  uint8_t num_cba_dci[10];
+  /// allocated CBA RNTI
+  uint16_t cba_rnti[4];//NUM_MAX_CBA_GROUP];
+  /// UL max-harq-retransmission
+  uint8_t Mlimit;
+} NR_UE_ULSCH_t;
+
+
+
+
+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];
+  /// RTC values for each segment (for definition see 36-212 V8.6 2009-03, p.15)
+  uint32_t RTC[MAX_NUM_DLSCH_SEGMENTS];
+  /// 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][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][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];
+  /// 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;
+} NR_DL_UE_HARQ_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;
+} nr_harq_status_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
+  nr_harq_status_t harq_ack[10];
+  /// Pointers to up to 8 HARQ processes
+  NR_DL_UE_HARQ_t *harq_processes[8];
+  /// 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;
+} NR_UE_DLSCH_t;
+
+
+
+
+/**@}*/
+#endif
diff --git a/openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c
new file mode 100644
index 0000000000000000000000000000000000000000..334faafecd4f0593d2d2b623bb29064468b68a10
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/pbch_nr.c
@@ -0,0 +1,100 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/**********************************************************************
+*
+* FILENAME    :  pbch_nr.c
+*
+* MODULE      :  broacast channel
+*
+* DESCRIPTION :  generation of pbch
+*                3GPP TS 38.211 7.3.3 Physical broadcast channel
+*
+************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "PHY/defs.h"
+
+#define DEFINE_VARIABLES_PBCH_NR_H
+#include "PHY/NR_REFSIG/pbch_nr.h"
+#undef DEFINE_VARIABLES_PBCH_NR_H
+
+/*******************************************************************
+*
+* NAME :         pseudo_random_gold_sequence
+*
+* PARAMETERS :
+*
+* RETURN :       generate pseudo-random sequence which is a length-31 Gold sequence
+*
+* DESCRIPTION :  3GPP TS 38.211 5.2.1 Pseudo-random sequence generation
+*                Sequence generation
+*
+*********************************************************************/
+
+#define NC           (1600)
+#define GOLD_LENGTH  (31)
+
+uint32_t *pseudo_random_gold_sequence(length M_PN, uint32_t cinit)
+{
+  int size = M_PN * sizeof(uint32_t);
+  int size_x = (sizeof(int)*M_PN + size;
+  int *x1 = malloc(size_x);
+  int *x2 = malloc(size_x);
+
+  if ((x1 == NULL) || (x2 == NULL)) {
+    msg("Fatal memory allocation problem \n");
+	assert(0);
+  }
+  else {
+    bzero(x1, size_x);
+    bzero(x2, size_x);
+  }
+
+  x1[0] = 1;
+
+  for (n = 0; n < 31; n++) {
+     x2[n] = (cinit >> n) & 0x1;
+  }
+
+  for (int n = 0; n < (NC+M_PN); n++) {
+    x1(n+31) = (x1(n+3) + x1(n))%2;
+    x2(n+31) = (x2(n+3) + x2(n+2) + x2(n+1) + x2(n))%2;
+  }
+
+  int *c = calloc(size);
+  if (c != NULL) {
+    bzero(c, size);
+  }
+  else {
+   msg("Fatal memory allocation problem \n");
+   assert(0);
+  }
+
+  for (int n = 0; n < M_PN; n++) {
+    c(i) = (x1(n+NC) + x2(n+NC))%2;
+  }
+
+  return c;
+}
diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c
new file mode 100644
index 0000000000000000000000000000000000000000..8a93271d90bc05defebbbd3f334c7c6c5b5ab72d
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c
@@ -0,0 +1,873 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/**********************************************************************
+*
+* FILENAME    :  pss_nr.c
+*
+* MODULE      :  synchronisation signal
+*
+* DESCRIPTION :  generation of pss
+*                3GPP TS 38.211 7.4.2.2 Primary synchronisation signal
+*
+************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "PHY/defs_nr_UE.h"
+
+#include "PHY/NR_REFSIG/ss_pbch_nr.h"
+
+#define DEFINE_VARIABLES_PSS_NR_H
+#include "PHY/NR_REFSIG/pss_nr.h"
+#undef DEFINE_VARIABLES_PSS_NR_H
+
+#include "PHY/NR_REFSIG/sss_nr.h"
+#include "PHY/NR_UE_TRANSPORT/cic_filter_nr.h"
+
+/*******************************************************************
+*
+* NAME :         get_idft
+*
+* PARAMETERS :   size of ofdm symbol
+*
+* RETURN :       function idft
+*
+* DESCRIPTION :  get idft function depending of ofdm size
+*
+*********************************************************************/
+
+void *get_idft(int ofdm_symbol_size)
+{
+  void (*idft)(int16_t *,int16_t *, int);
+
+  switch (ofdm_symbol_size) {
+    case 128:
+      idft = idft128;
+      break;
+
+    case 256:
+      idft = idft256;
+      break;
+
+    case 512:
+      idft = idft512;
+      break;
+
+    case 1024:
+      idft = idft1024;
+      break;
+
+    case 1536:
+      idft = idft1536;
+      break;
+
+    case 2048:
+      idft = idft2048;
+      break;
+
+    default:
+      printf("function get_idft : unsupported ofdm symbol size \n");
+      assert(0);
+      break;
+ }
+ return idft;
+}
+
+/*******************************************************************
+*
+* NAME :         get_dft
+*
+* PARAMETERS :   size of ofdm symbol
+*
+* RETURN :       function for discrete fourier transform
+*
+* DESCRIPTION :  get dft function depending of ofdm size
+*
+*********************************************************************/
+
+void *get_dft(int ofdm_symbol_size)
+{
+  void (*dft)(int16_t *,int16_t *, int);
+
+  switch (ofdm_symbol_size) {
+    case 128:
+      dft = dft128;
+      break;
+
+    case 256:
+      dft = dft256;
+      break;
+
+    case 512:
+      dft = dft512;
+      break;
+
+    case 1024:
+      dft = dft1024;
+      break;
+
+    case 1536:
+      dft = dft1536;
+      break;
+
+    case 2048:
+      dft = dft2048;
+      break;
+
+    default:
+      printf("function get_dft : unsupported ofdm symbol size \n");
+      assert(0);
+      break;
+ }
+ return dft;
+}
+
+/*******************************************************************
+*
+* NAME :         generate_pss_nr
+*
+* PARAMETERS :   N_ID_2 : element 2 of physical layer cell identity
+*                value : { 0, 1, 2}
+*
+* RETURN :       generate binary pss sequence (this is a m-sequence)
+*
+* DESCRIPTION :  3GPP TS 38.211 7.4.2.2 Primary synchronisation signal
+*                Sequence generation
+*
+*********************************************************************/
+
+void generate_pss_nr(int N_ID_2, int ofdm_symbol_size)
+{
+  int16_t d_pss[LENGTH_PSS_NR];
+  int16_t x[LENGTH_PSS_NR];
+  int16_t *primary_synchro_time = primary_synchro_time_nr[N_ID_2];
+  unsigned int length = ofdm_symbol_size;
+  unsigned int size = length * IQ_SIZE; /* i & q */
+  int16_t *primary_synchro = primary_synchro_nr[N_ID_2]; /* pss in complex with alternatively i then q */
+  void (*idft)(int16_t *,int16_t *, int);
+
+  #define INITIAL_PSS_NR    (7)
+  const int x_initial[INITIAL_PSS_NR] = {0, 1, 1 , 0, 1, 1, 1};
+
+  assert(N_ID_2 < NUMBER_PSS_SEQUENCE);
+  assert(size <= SYNCF_TMP_SIZE);
+  assert(size <= SYNC_TMP_SIZE);
+
+  bzero(synchroF_tmp, size);
+  bzero(synchro_tmp, size);
+
+  for (int i=0; i < INITIAL_PSS_NR; i++) {
+    x[i] = x_initial[i];
+  }
+
+  for (int i=0; i < (LENGTH_PSS_NR - INITIAL_PSS_NR); i++) {
+    x[i+INITIAL_PSS_NR] = (x[i + 4] + x[i])%(2);
+  }
+
+  for (int n=0; n < LENGTH_PSS_NR; n++) {
+	int m = (n + 43*N_ID_2)%(LENGTH_PSS_NR);
+    d_pss[n] = 1 - 2*x[m];
+  }
+
+  /* PSS is directly mapped to subcarrier without modulation 38.211 */
+  for (int i=0; i < LENGTH_PSS_NR; i++) {
+#if 1
+    primary_synchro[2*i] = (d_pss[i] * SHRT_MAX)>>SCALING_PSS_NR; /* Maximum value for type short int ie int16_t */
+    primary_synchro[2*i+1] = 0;
+#else
+    primary_synchro[2*i] = d_pss[i] * AMP;
+    primary_synchro[2*i+1] = 0;
+#endif
+  }
+
+#ifdef DBG_PSS_NR
+
+  if (N_ID_2 == 0) {
+    char output_file[255];
+    char sequence_name[255];
+    sprintf(output_file, "pss_seq_%d_%d.m", N_ID_2, length);
+    sprintf(sequence_name, "pss_seq_%d_%d", N_ID_2, length);
+    printf("file %s sequence %s\n", output_file, sequence_name);
+
+    write_output(output_file, sequence_name, primary_synchro, LENGTH_PSS_NR, 1, 1);
+  }
+
+#endif
+
+  /* call of IDFT should be done with ordered input as below
+  *
+  *                n input samples
+  *  <------------------------------------------------>
+  *  0                                                n
+  *  are written into input buffer for IFFT
+  *   -------------------------------------------------
+  *  |xxxxxxx                       N/2       xxxxxxxx|
+  *  --------------------------------------------------
+  *  ^      ^                 ^               ^          ^
+  *  |      |                 |               |          |
+  * n/2    end of            n=0            start of    n/2-1
+  *         pss                               pss
+  *
+  *                   Frequencies
+  *      positives                   negatives
+  * 0                 (+N/2)(-N/2)
+  * |-----------------------><-------------------------|
+  *
+  * sample 0 is for continuous frequency which is used here
+  */
+
+  unsigned int k = length - (LENGTH_PSS_NR/2+1);
+
+  for (int i=0; i < LENGTH_PSS_NR; i++) {
+    synchroF_tmp[2*k] = primary_synchro[2*i];
+    synchroF_tmp[2*k+1] = primary_synchro[2*i+1];
+
+    k++;
+
+    if (k >= length) {
+      k++;
+      k-=length;
+    }
+  }
+
+  /* IFFT will give temporal signal of Pss */
+
+  idft = get_idft(length);
+
+  idft(synchroF_tmp,          /* complex input */
+       synchro_tmp,           /* complex output */
+       1);                 /* scaling factor */
+
+  /* then get final pss in time */
+  for (unsigned int i=0; i<length; i++) {
+    ((int32_t *)primary_synchro_time)[i] = ((int32_t *)synchro_tmp)[i];
+  }
+
+#ifdef DBG_PSS_NR
+
+  if (N_ID_2 == 0) {
+    char output_file[255];
+    char sequence_name[255];
+    sprintf(output_file, "%s%d_%d%s","pss_seq_t_", N_ID_2, length, ".m");
+    sprintf(sequence_name, "%s%d_%d","pss_seq_t_", N_ID_2, length);
+
+    printf("file %s sequence %s\n", output_file, sequence_name);
+
+    write_output(output_file, sequence_name, primary_synchro_time, length, 1, 1);
+  }
+
+#endif
+
+
+#if 0
+
+/* it allows checking that process of idft on a signal and then dft gives same signal with limited errors */
+
+  if ((N_ID_2 == 0) && (length == 256)) {
+
+    write_output("pss_f00.m","pss_f00",synchro_tmp,length,1,1);
+
+
+    bzero(synchroF_tmp, size);
+
+    void (*dft)(int16_t *,int16_t *, int) = get_dft(length);
+
+    /* get pss in the time domain by applying an inverse FFT */
+    dft(synchro_tmp,           /* complex input */
+        synchroF_tmp,          /* complex output */
+        1);                 /* scaling factor */
+
+    if ((N_ID_2 == 0) && (length == 256)) {
+      write_output("pss_f_0.m","pss_f_0",synchroF_tmp,length,1,1);
+    }
+
+    /* check Pss */
+    k = length - (LENGTH_PSS_NR/2);
+
+#define LIMIT_ERROR_FFT   (10)
+
+    for (int i=0; i < LENGTH_PSS_NR; i++) {
+      if (abs(synchroF_tmp[2*k] - primary_synchro[2*i]) > LIMIT_ERROR_FFT) {
+      printf("Pss Error[%d] Compute %d Reference %d \n", k, synchroF_tmp[2*k], primary_synchro[2*i]);
+      }
+    
+      if (abs(synchroF_tmp[2*k+1] - primary_synchro[2*i+1]) > LIMIT_ERROR_FFT) {
+        printf("Pss Error[%d] Compute %d Reference %d\n", (2*k+1), synchroF_tmp[2*k+1], primary_synchro[2*i+1]);
+      }
+
+      k++;
+
+      if (k >= length) {
+        k-=length;
+      }
+    }
+  }
+#endif
+}
+
+/*******************************************************************
+*
+* NAME :         init_context_pss_nr
+*
+* PARAMETERS :   structure NR_DL_FRAME_PARMS give frame parameters
+*
+* RETURN :       generate binary pss sequences (this is a m-sequence)
+*
+* DESCRIPTION :  3GPP TS 38.211 7.4.2.2 Primary synchronisation signal
+*                Sequence generation
+*
+*********************************************************************/
+
+void init_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
+{
+  int ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size;
+  int sizePss = LENGTH_PSS_NR * IQ_SIZE;  /* complex value i & q signed 16 bits */
+  int size = ofdm_symbol_size * IQ_SIZE; /* i and q samples signed 16 bits */
+  int16_t *p = NULL;
+  int *q = NULL;
+
+  for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
+
+    p = malloc16(sizePss); /* pss in complex with alternatively i then q */
+    if (p != NULL) {
+      primary_synchro_nr[i] = p;
+      bzero( primary_synchro_nr[i], sizePss);
+    }
+    else {
+     msg("Fatal memory allocation problem \n");
+     assert(0);
+    }
+
+    p = malloc16(size);
+    if (p != NULL) {
+      primary_synchro_time_nr[i] = p;
+      bzero( primary_synchro_time_nr[i], size);
+    }
+    else {
+     msg("Fatal memory allocation problem \n");
+     assert(0);
+    }
+
+    size = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int)*frame_parms_ue->samples_per_subframe;
+    q = malloc16(size);
+    if (q != NULL) {
+      pss_corr_ue[i] = q;
+      bzero( pss_corr_ue[i], size);
+    }
+    else {
+      msg("Fatal memory allocation problem \n");
+      assert(0);
+    }
+
+    generate_pss_nr(i, ofdm_symbol_size);
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         free_context_pss_nr
+*
+* PARAMETERS :   none
+*
+* RETURN :       none
+*
+* DESCRIPTION :  free context related to pss
+*
+*********************************************************************/
+
+void free_context_pss_nr(void)
+{
+  for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
+
+    if (primary_synchro_time_nr[i] != NULL) {
+      free(primary_synchro_time_nr[i]);
+      primary_synchro_time_nr[i] = NULL;
+    }
+    else {
+      msg("Fatal memory deallocation problem \n");
+      assert(0);
+    }
+
+    if (primary_synchro_nr[i] != NULL) {
+      free(primary_synchro_nr[i]);
+      primary_synchro_nr[i] = NULL;
+    }
+    else {
+      msg("Fatal memory deallocation problem \n");
+      assert(0);
+    }
+
+    if (pss_corr_ue[i] != NULL) {
+      free(pss_corr_ue[i]);
+      pss_corr_ue[i] = NULL;
+    }
+    else {
+      msg("Fatal memory deallocation problem \n");
+      assert(0);
+    }
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         init_context_synchro_nr
+*
+* PARAMETERS :   none
+*
+* RETURN :       generate context for pss and sss
+*
+* DESCRIPTION :  initialise contexts and buffers for synchronisation
+*
+*********************************************************************/
+
+void init_context_synchro_nr(NR_DL_FRAME_PARMS *frame_parms_ue)
+{
+#ifndef STATIC_SYNC_BUFFER
+
+  /* initialise global buffers for synchronisation */
+  synchroF_tmp = malloc16(SYNCF_TMP_SIZE);
+  if (synchroF_tmp == NULL) {
+    msg("Fatal memory allocation problem \n");
+    assert(0);
+  }
+
+  synchro_tmp = malloc16(SYNC_TMP_SIZE);
+  if (synchro_tmp == NULL) {
+    msg("Fatal memory allocation problem \n");
+    assert(0);
+  }
+
+#endif
+
+  init_context_pss_nr(frame_parms_ue);
+
+  init_context_sss_nr(AMP);
+}
+
+/*******************************************************************
+*
+* NAME :         free_context_synchro_nr
+*
+* PARAMETERS :   none
+*
+* RETURN :       free context for pss and sss
+*
+* DESCRIPTION :  deallocate memory of synchronisation
+*
+*********************************************************************/
+
+void free_context_synchro_nr(void)
+{
+#ifndef STATIC_SYNC_BUFFER
+
+  if (synchroF_tmp != NULL) {
+    free(synchroF_tmp);
+    synchroF_tmp = NULL;
+  }
+  else {
+    msg("Fatal memory deallocation problem \n");
+    assert(0);
+  }
+
+  if (synchro_tmp != NULL) {
+    free(synchro_tmp);
+    synchro_tmp = NULL;
+  }
+  else {
+    msg("Fatal memory deallocation problem \n");
+    assert(0);
+  }
+
+#endif
+
+  free_context_pss_nr();
+}
+
+/*******************************************************************
+*
+* NAME :         set_frame_context_pss_nr
+*
+* PARAMETERS :   configuration for UE with new FFT size
+*
+* RETURN :       0 if OK else error
+*
+* DESCRIPTION :  initialisation of UE contexts
+*
+*********************************************************************/
+
+void set_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change)
+{
+  /* set new value according to rate_change */
+  frame_parms_ue->ofdm_symbol_size = (frame_parms_ue->ofdm_symbol_size / rate_change);
+  frame_parms_ue->samples_per_tti = (frame_parms_ue->samples_per_tti / rate_change);
+  frame_parms_ue->samples_per_subframe = (frame_parms_ue->samples_per_subframe / rate_change);
+
+  free_context_pss_nr();
+
+  /* pss reference have to be rebuild with new parameters ie ofdm symbol size */
+  init_context_synchro_nr(frame_parms_ue);
+
+#ifdef SYNCHRO_DECIMAT
+  set_pss_nr(frame_parms_ue->ofdm_symbol_size);
+#endif
+}
+
+/*******************************************************************
+*
+* NAME :         restore_frame_context_pss_nr
+*
+* PARAMETERS :   configuration for UE and eNB with new FFT size
+*
+* RETURN :       0 if OK else error
+*
+* DESCRIPTION :  initialisation of UE and eNode contexts
+*
+*********************************************************************/
+
+void restore_frame_context_pss_nr(NR_DL_FRAME_PARMS *frame_parms_ue, int rate_change)
+{
+  frame_parms_ue->ofdm_symbol_size = frame_parms_ue->ofdm_symbol_size * rate_change;
+  frame_parms_ue->samples_per_tti = frame_parms_ue->samples_per_tti * rate_change;
+  frame_parms_ue->samples_per_subframe = frame_parms_ue->samples_per_subframe * rate_change;
+
+  free_context_pss_nr();
+
+  /* pss reference have to be rebuild with new parameters ie ofdm symbol size */
+  init_context_synchro_nr(frame_parms_ue);
+#ifdef SYNCHRO_DECIMAT
+  set_pss_nr(frame_parms_ue->ofdm_symbol_size);
+#endif
+}
+
+/********************************************************************
+*
+* NAME :         decimation_synchro_nr
+*
+* INPUT :        UE context
+*                for first and second pss sequence
+*                - position of pss in the received UE buffer
+*                - number of pss sequence
+*
+* RETURN :      0 if OK else error
+*
+* DESCRIPTION :  detect pss sequences in the received UE buffer
+*
+********************************************************************/
+
+void decimation_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change, int **rxdata)
+{
+  NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms);
+  int samples_for_frame = LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_tti;
+
+#if TEST_SYNCHRO_TIMING_PSS
+
+  opp_enabled = 1;
+
+  start_meas(&generic_time[TIME_RATE_CHANGE]);
+
+#endif
+
+/* build with cic filter does not work properly. Performances are significantly deteriorated */
+#ifdef CIC_DECIMATOR
+
+  cic_decimator((int16_t *)&(PHY_vars_UE->common_vars.rxdata[0][0]), (int16_t *)&(rxdata[0][0]),
+                            samples_for_frame, rate_change, CIC_FILTER_STAGE_NUMBER, 0, FIR_RATE_CHANGE);
+#else
+
+  fir_decimator((int16_t *)&(PHY_vars_UE->common_vars.rxdata[0][0]), (int16_t *)&(rxdata[0][0]),
+                            samples_for_frame, rate_change, 0);
+
+#endif
+
+  set_frame_context_pss_nr(frame_parms, rate_change);
+
+#if TEST_SYNCHRO_TIMING_PSS
+
+  stop_meas(&generic_time[TIME_RATE_CHANGE]);
+
+  printf("Rate change execution duration %5.2f \n", generic_time[TIME_RATE_CHANGE].p_time/(cpuf*1000.0));
+
+#endif
+}
+
+/*******************************************************************
+*
+* NAME :         pss_synchro_nr
+*
+* PARAMETERS :   int rate_change
+*
+* RETURN :       position of detected pss
+*
+* DESCRIPTION :  pss search can be done with sampling decimation.*
+*
+*********************************************************************/
+
+int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change)
+{
+  NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms);
+  int synchro_position;
+  int **rxdata = NULL;
+
+#ifdef DBG_PSS_NR
+
+  int samples_for_frame = frame_parms->samples_per_subframe*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME;
+
+  write_output("rxdata0_rand.m","rxd0_rand", &PHY_vars_UE->common_vars.rxdata[0][0], samples_for_frame, 1, 1);
+
+#endif
+
+  if (rate_change != 1) {
+
+    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
+
+    for (int aa=0; aa < frame_parms->nb_antennas_rx; aa++) {
+      rxdata[aa] = (int32_t*) malloc16_clear( (frame_parms->samples_per_subframe*10+2048)*sizeof(int32_t));
+    }
+#ifdef SYNCHRO_DECIMAT
+
+    decimation_synchro_nr(PHY_vars_UE, rate_change, rxdata);
+
+#endif
+  }
+  else {
+
+    rxdata = PHY_vars_UE->common_vars.rxdata;
+  }
+
+#ifdef DBG_PSS_NR
+
+  write_output("rxdata0_des.m","rxd0_des", &rxdata[0][0], samples_for_frame,1,1);
+
+#endif
+
+#if TEST_SYNCHRO_TIMING_PSS
+
+  opp_enabled = 1;
+
+  start_meas(&generic_time[TIME_PSS]);
+
+#endif
+
+#if 1
+
+  synchro_position = pss_search_time_nr(rxdata,
+                                        frame_parms,
+                                        (int *)&PHY_vars_UE->common_vars.eNb_id);
+
+#else
+
+  synchro_position = lte_sync_time(rxdata,
+                                          frame_parms,
+                                          (int *)&PHY_vars_UE->common_vars.eNb_id);
+#endif
+
+#if TEST_SYNCHRO_TIMING_PSS
+
+  stop_meas(&generic_time[TIME_PSS]);
+
+  printf("PSS execution duration %5.2f \n", generic_time[TIME_PSS].p_time/(cpuf*1000.0));
+
+#endif
+
+#ifdef SYNCHRO_DECIMAT
+
+  if (rate_change != 1) {
+
+    if (rxdata[0] != NULL) {
+
+      for (int aa=0;aa<frame_parms->nb_antennas_rx;aa++) {
+        free(rxdata[aa]);
+      }
+
+      free(rxdata);
+    }
+
+    restore_frame_context_pss_nr(frame_parms, rate_change);  
+  }
+#endif
+
+  return synchro_position;
+}
+
+static inline int abs32(int x)
+{
+  return (((int)((short*)&x)[0])*((int)((short*)&x)[0]) + ((int)((short*)&x)[1])*((int)((short*)&x)[1]));
+}
+
+/*******************************************************************
+*
+* NAME :         pss_search_time_nr
+*
+* PARAMETERS :   received buffer
+*                frame parameters
+*
+* RETURN :       position of detected pss
+*
+* DESCRIPTION :  Synchronisation on pss sequence is based on a time domain correlation between received samples and pss sequence
+*                A maximum likelihood detector finds the timing offset (position) that corresponds to the maximum correlation
+*                Length of received buffer should be a minimum of 2 frames (see TS 38.213 4.1 Cell search)
+*                Search pss in the received buffer is done each 4 samples which ensures a memory alignment to 128 bits (32 bits x 4).
+*                This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors
+*                Correlation computation is based on a a dot product which is realized thank to SIMS extensions
+*
+*                                    (x frames)
+*     <--------------------------------------------------------------------------->
+*
+*
+*     -----------------------------------------------------------------------------
+*     |                      Received UE data buffer                              |
+*     ----------------------------------------------------------------------------
+*                -------------
+*     <--------->|    pss    |
+*      position  -------------
+*                ^
+*                |
+*            peak position
+*            given by maximum of correlation result
+*            position matches beginning of first ofdm symbol of pss sequence
+*
+*     Remark: memory position should be aligned on a multiple of 4 due to I & Q samples of int16
+*             An OFDM symbol is composed of x number of received samples depending of Rf front end sample rate.
+*
+*     I & Q storage in memory
+*
+*             First samples       Second  samples
+*     ------------------------- -------------------------  ...
+*     |     I1     |     Q1    |     I2     |     Q2    |
+*     ---------------------------------------------------  ...
+*     ^    16  bits   16 bits  ^
+*     |                        |
+*     ---------------------------------------------------  ...
+*     |         sample 1       |    sample   2          |
+*    ----------------------------------------------------  ...
+*     ^
+*
+*********************************************************************/
+
+#define DOT_PRODUCT_SCALING_SHIFT    (17)
+
+int pss_search_time_nr(int **rxdata, ///rx data in time domain
+                       NR_DL_FRAME_PARMS *frame_parms,
+                       int *eNB_id)
+{
+  unsigned int n, ar, peak_position, peak_value, pss_source;
+  int result;
+  int synchro_out;
+  unsigned int tmp[NUMBER_PSS_SEQUENCE];
+  unsigned int length = (LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->ttis_per_subframe*frame_parms->samples_per_tti);  /* 1 frame for now, it should be 2 TODO_NR */
+
+  for (int i = 0; i < NUMBER_PSS_SEQUENCE; i++) {
+	  tmp[i] = 0;
+    if (pss_corr_ue[i] == NULL) {
+      msg("[SYNC TIME] pss_corr_ue[%d] not yet allocated! Exiting.\n", i);
+      return(-1);
+    }
+  }
+
+  peak_value = 0;
+  peak_position = 0;
+  pss_source = 0;
+
+  /* Search pss in the received buffer each 4 samples which ensures a memory alignment on 128 bits (32 bits x 4 ) */
+  /* This is required by SIMD (single instruction Multiple Data) Extensions of Intel processors. */
+  /* Correlation computation is based on a a dot product which is realized thank to SIMS extensions */
+  for (n=0; n < length; n+=4) {
+
+#ifdef RTAI_ENABLED
+
+    // This is necessary since the sync takes a long time and it seems to block all other threads thus screwing up RTAI. If we pause it for a little while during its execution we give RTAI a chance to catch up with its other tasks.
+    if ((n%frame_parms->samples_per_subframe == 0) && (n>0) && (openair_daq_vars.sync_state==0)) {
+#ifdef DEBUG_PHY
+      msg("[SYNC TIME] pausing for 1000ns, n=%d\n",n);
+#endif
+      rt_sleep(nano2count(1000));
+    }
+
+#endif
+
+    for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) {
+
+      pss_corr_ue[pss_index][n] = 0; /* clean correlation for position n */
+
+      synchro_out = 0;
+
+      if ( n < (length - frame_parms->ofdm_symbol_size)) {
+
+        /* calculate dot product of primary_synchro_time_nr and rxdata[ar][n] (ar=0..nb_ant_rx) and store the sum in temp[n]; */
+        for (ar=0; ar<frame_parms->nb_antennas_rx; ar++) {
+
+          /* perform correlation of rx data and pss sequence ie it is a dot product */
+          result  = dot_product((short*)primary_synchro_time_nr[pss_index], (short*) &(rxdata[ar][n]), frame_parms->ofdm_symbol_size, DOT_PRODUCT_SCALING_SHIFT);
+
+          ((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0];   /* real part */
+          ((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
+          ((short*)&synchro_out)[0] += ((short*) &result)[0];               /* real part */
+          ((short*)&synchro_out)[1] += ((short*) &result)[1];               /* imaginary part */
+        }
+      }
+
+      pss_corr_ue[pss_index][n] = abs32(pss_corr_ue[pss_index][n]);
+
+      /* calculate the absolute value of sync_corr[n] */
+      tmp[pss_index] = (abs32(synchro_out)) ;
+
+      if (tmp[pss_index] > peak_value) {
+        peak_value = tmp[pss_index];
+        peak_position = n;
+        pss_source = pss_index;
+
+        //printf("pss_index %d: n %6d peak_value %10d, synchro_out (% 6d,% 6d) \n", pss_index, n, abs32(synchro_out),((int16_t*)&synchro_out)[0],((int16_t*)&synchro_out)[1]);
+      }
+    }
+  }
+
+  *eNB_id = pss_source;
+
+  LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n", pss_source, peak_position, peak_value, dB_fixed(peak_value)/2);
+
+#ifdef DEBUG_PSS_NR
+
+#define  PSS_DETECTION_FLOOR_NR     (31)
+  if ((dB_fixed(peak_value)/2) > PSS_DETECTION_FLOOR_NR) {
+
+    printf("[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %d (%d dB)\n", pss_source, peak_position, peak_value,dB_fixed(peak_value)/2);
+  }
+#endif
+
+#ifdef DEBUG_PHY
+
+  if (debug_cnt == 0) {
+    write_output("pss_corr_ue0.m","pss_corr_ue0",pss_corr_ue[0],length,1,2);
+    write_output("pss_corr_ue1.m","pss_corr_ue1",pss_corr_ue[1],length,1,2);
+    write_output("pss_corr_ue2.m","pss_corr_ue2",pss_corr_ue[2],length,1,2);
+    write_output("rxdata0.m","rxd0",rxdata[0],length,1,1);
+  } else {
+    debug_cnt++;
+  }
+
+#endif
+
+  return(peak_position);
+}
+
diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
new file mode 100644
index 0000000000000000000000000000000000000000..aba3c12636e3a675aa0c4b9ed4bcf2e9b09bba9a
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
@@ -0,0 +1,488 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/***********************************************************************
+*
+* FILENAME    :  srs_modulation_nr_nr.c
+*
+* MODULE      :
+*
+* DESCRIPTION :  function to set uplink reference symbols
+*                see TS 38211 6.4.1.4 Sounding reference signal
+*
+************************************************************************/
+
+#include <stdio.h>
+#include <math.h>
+
+#define DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+#include "PHY/impl_defs_nr.h"
+#undef DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+
+#include "PHY/defs_nr_UE.h"
+//#include "extern.h"
+#include "PHY/NR_REFSIG/ss_pbch_nr.h"
+#include "PHY/NR_REFSIG/dmrs_nr.h"
+#include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
+
+#define DEFINE_VARIABLES_SRS_MODULATION_NR_H
+#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h"
+#undef DEFINE_VARIABLES_SRS_MODULATION_NR_H
+
+/*******************************************************************
+*
+* NAME :         generate_srs
+*
+* PARAMETERS :   pointer to resource set
+*                pointer to transmit buffer
+*                amplitude scaling for this physical signal
+*                slot number of transmission
+* RETURN :       0  if srs sequence has been successfully generated
+*                -1 if sequence can not be properly generated
+*
+* DESCRIPTION :  generate/map srs symbol into transmit buffer
+*                see TS 38211 6.4.1.4 Sounding reference signal
+*
+*                FFS_TODO_NR
+*                Current supported configuration:
+*                - single resource per resource set
+*                - single port antenna
+*                - 1 symbol for SRS
+*                - no symbol offset
+*                - periodic mode
+*                - no hopping
+*                - no carrier switching
+*                - no antenna switching*
+*
+*********************************************************************/
+int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
+                        NR_DL_FRAME_PARMS *frame_parms,
+                        int32_t *txptr,
+                        int16_t amp,
+                        UE_nr_rxtx_proc_t *proc)
+{
+  uint8_t n_SRS_cs_max;
+  uint8_t u, v_nu;
+  uint32_t f_gh = 0;
+  SRS_Resource_t *p_SRS_Resource;
+  int frame_number = proc->frame_tx;
+  int slot_number = proc->nr_tti_tx;
+  uint16_t n_SRS, n_SRS_cs_i;
+  double alpha_i;
+  uint8_t K_TC_p;
+  uint16_t n_b[B_SRS_NUMBER], F_b, subcarrier;
+  uint8_t N_b, k_0_overbar_p;
+
+  if (p_srs_resource_set->p_srs_ResourceList[0] == NULL) {
+    LOG_E(PHY,"generate_srs: No resource associated with the SRS resource set!\n");
+    return (-1);
+  }
+  else {
+    if (p_srs_resource_set->number_srs_Resource <= MAX_NR_OF_SRS_RESOURCES_PER_SET) {
+      p_SRS_Resource = p_srs_resource_set->p_srs_ResourceList[0];
+    }
+    else {
+      LOG_E(PHY,"generate_srs: resource number of this resource set %d exceeds maximum supported value %d!\n", p_srs_resource_set->number_srs_Resource, MAX_NR_OF_SRS_RESOURCES_PER_SET);
+      return (-1);
+    }
+  }
+
+  if (p_srs_resource_set->resourceType != periodic) {
+    LOG_E(PHY,"generate_srs: only SRS periodic is supported up to now!\n");
+    return (-1);
+  }
+  /* get parameters from SRS resource configuration */
+  uint8_t B_SRS  = p_SRS_Resource->freqHopping_b_SRS;
+  uint8_t C_SRS  = p_SRS_Resource->freqHopping_c_SRS;
+  uint8_t b_hop = p_SRS_Resource->freqHopping_b_hop;
+  uint8_t K_TC = p_SRS_Resource->transmissionComb;
+  uint8_t K_TC_overbar = p_SRS_Resource->combOffset;    /* FFS_TODO_NR is this parameter for K_TC_overbar ?? */
+  uint8_t n_SRS_cs = p_SRS_Resource->cyclicShift;
+  uint8_t n_ID_SRS = p_SRS_Resource->sequenceId;
+  uint8_t n_shift = p_SRS_Resource->freqDomainPosition; /* it adjusts the SRS allocation to align with the common resource block grid in multiples of four */
+  uint8_t n_RRC = p_SRS_Resource->freqDomainShift;
+  uint8_t groupOrSequenceHopping = p_SRS_Resource->groupOrSequenceHopping;
+
+  uint8_t l_offset = p_SRS_Resource->resourceMapping_startPosition;
+
+  uint16_t T_SRS = srs_period[p_SRS_Resource->SRS_Periodicity];
+  uint16_t T_offset = p_SRS_Resource->SRS_Offset;;                   /* FFS_TODO_NR to check interface with RRC */
+  uint8_t R = p_SRS_Resource->resourceMapping_repetitionFactor;
+
+  /* TS 38.211 6.4.1.4.1 SRS resource */
+  uint8_t N_ap = (uint8_t)p_SRS_Resource->nrof_SrsPorts;            /* antenna port for transmission */
+  uint8_t N_symb_SRS = p_SRS_Resource->resourceMapping_nrofSymbols; /* consecutive OFDM symbols */
+  uint8_t l0 = N_SYMB_SLOT - 1 - l_offset;                          /* starting position in the time domain */
+  uint8_t k_0_p;                                                    /* frequency domain starting position */
+
+  if (N_ap != port1) {
+    LOG_E(PHY, "generate_srs: this number of antenna ports %d is not yet supported!\n", N_ap);
+    return (-1);
+  }
+  if (N_symb_SRS != 1) {
+    LOG_E(PHY, "generate_srs: this number of srs symbol  %d is not yet supported!\n", N_symb_SRS);
+  	return (-1);
+  }
+  if (groupOrSequenceHopping != neitherHopping) {
+    LOG_E(PHY, "generate_srs: sequence hopping is not yet supported!\n");
+    return (-1);
+  }
+  if (R == 0) {
+    LOG_E(PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", R);
+    return (-1);
+  }
+  else if (R > N_symb_SRS) {
+    LOG_E(PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", R, N_symb_SRS);
+    return (-1);
+  }
+  /* see 38211 6.4.1.4.2 Sequence generation */
+  if (K_TC == 4) {
+    n_SRS_cs_max = 12;
+    // delta = 2;     /* delta = log2(K_TC) */
+  }
+  else if (K_TC == 2) {
+    n_SRS_cs_max = 8;
+    // delta = 1;     /* delta = log2(K_TC) */
+  }
+  else {
+	LOG_E(PHY, "generate_srs: SRS unknown value for K_TC %d !\n", K_TC);
+    return (-1);
+  }
+  if (n_SRS_cs >= n_SRS_cs_max) {
+    LOG_E(PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >=  n_SRS_cs_max %d !\n", n_SRS_cs, n_SRS_cs_max);
+    return (-1);
+  }
+  if (T_SRS == 0) {
+    LOG_E(PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", T_SRS);
+    return (-1);
+  }
+  else
+  {
+    int index = 0;
+    while (srs_periodicity[index] != T_SRS) {
+      index++;
+      if (index == SRS_PERIODICITY) {
+        LOG_E(PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", T_SRS);
+        return (-1);
+      }
+    }
+  }
+
+  uint16_t m_SRS_b = srs_bandwidth_config[C_SRS][B_SRS][0];     /* m_SRS_b is given by TS 38211 clause 6.4.1.4.3 */
+  uint16_t M_sc_b_SRS = m_SRS_b * N_SC_RB/K_TC;                 /* length of the sounding reference signal sequence */
+
+  /* for each antenna ports for transmission */
+  for (int p_index = 0; p_index < N_ap; p_index++) {
+
+  /* see TS 38.211 6.4.1.4.2 Sequence generation */
+
+    n_SRS_cs_i = (n_SRS_cs +  (n_SRS_cs_max * (SRS_antenna_port[p_index] - 1000)/N_ap))%n_SRS_cs_max;
+    alpha_i = 2 * M_PI * ((double)n_SRS_cs_i / (double)n_SRS_cs_max);
+
+    /* for each SRS symbol which should be managed by SRS configuration */
+    /* from TS 38.214 6.2.1.1 UE SRS frequency hopping procedure */
+    /* A UE may be configured to transmit an SRS resource on  adjacent symbols within the last six symbols of a slot, */
+    /* where all antenna ports of the SRS resource are mapped to each symbol of the resource */
+
+
+    uint8_t l = p_index;
+    if (l >= N_symb_SRS) {
+      LOG_E(PHY, "generate_srs: number of antenna ports %d and number of srs symbols %d are different !\n", N_ap, N_symb_SRS);
+    }
+
+    switch(groupOrSequenceHopping) {
+      case neitherHopping:
+      {
+        f_gh = 0;
+        v_nu = 0;
+        break;
+      }
+      case groupHopping:
+      {
+        uint8_t c_last_index = 8 * (slot_number * N_SYMB_SLOT + l0 + l) + 7; /* compute maximum value of the random sequence */
+        uint32_t *c_sequence =  calloc(c_last_index+1, sizeof(uint32_t));
+        uint32_t cinit = n_ID_SRS/30;
+        pseudo_random_sequence(c_last_index+1,  c_sequence, cinit);
+        for (int m = 0; m < 8; m++) {
+          f_gh += c_sequence[8 * (slot_number * N_SYMB_SLOT + l0 + l) + m]<<m;
+        }
+        free(c_sequence);
+        f_gh = f_gh%30;
+        v_nu = 0;
+        break;
+      }
+      case sequenceHopping:
+      {
+        f_gh = 0;
+        if (M_sc_b_SRS > 6 * N_SC_RB) {
+          uint8_t c_last_index = (slot_number * N_SYMB_SLOT + l0 + l); /* compute maximum value of the random sequence */
+          uint32_t *c_sequence =  calloc(c_last_index+1, sizeof(uint32_t));
+          uint32_t cinit = n_ID_SRS;
+          pseudo_random_sequence(c_last_index+1,  c_sequence, cinit);
+          v_nu = c_sequence[c_last_index];
+          free(c_sequence);
+        }
+        else {
+          v_nu = 0;
+        }
+        break;
+      }
+      default:
+      {
+        LOG_E(PHY, "generate_srs: unknown hopping setting %d !\n", groupOrSequenceHopping);
+        return (-1);
+      }
+    }
+
+    /* u is the sequence-group number defined in section 6.4.1.4.1 */
+    u = (f_gh + n_ID_SRS)%U_GROUP_NUMBER; /* 30 */
+
+    /* TS 38.211 6.4.1.4.3  Mapping to physical resources */
+
+    if((n_SRS_cs >= n_SRS_cs_max/2)&&(n_SRS_cs < n_SRS_cs_max)&&(N_ap == 4) && ((SRS_antenna_port[p_index] == 1001) || (SRS_antenna_port[p_index] == 1003))) {
+      K_TC_p = (K_TC_overbar + K_TC/2)%K_TC;
+    }
+    else {
+      K_TC_p = K_TC_overbar;
+    }
+
+    for (int b = 0; b <= B_SRS; b++) {
+      N_b = srs_bandwidth_config[C_SRS][b][1];
+      if (b_hop >= B_SRS) {
+        n_b[b] = (4 * n_RRC/m_SRS_b)%N_b; /* frequency hopping is disabled and the frequency position index n_b remains constant */
+      }
+      else {
+        if (b == b_hop) {
+          N_b = 1;
+        }
+        /* periodicity and offset */
+        if (p_srs_resource_set->resourceType == aperiodic) {
+          n_SRS = l/R;
+        }
+        else {
+          int8_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * frame_parms->ttis_per_subframe;
+          n_SRS = ((N_slot_frame*frame_number + slot_number - T_offset)/T_SRS)*(N_symb_SRS/R)+(l/R);
+        }
+
+        uint16_t product_N_b = 1;  /* for b_hop to b-1 */
+        for (unsigned int b_prime = b_hop; b_prime < B_SRS; b_prime++) {  /* product for b_hop to b-1 */
+          if (b_prime != b_hop) {
+            product_N_b *= srs_bandwidth_config[C_SRS][b_prime][1];
+          }
+        }
+
+        if (N_b & 1) {      /* Nb odd */
+          F_b = (N_b/2)*(n_SRS/product_N_b);
+        }
+        else {              /* Nb even */
+          uint16_t product_N_b_B_SRS = product_N_b;
+          product_N_b_B_SRS *= srs_bandwidth_config[C_SRS][B_SRS][1]; /* product for b_hop to b */
+          F_b = (N_b/2)*((n_SRS%product_N_b_B_SRS)/product_N_b) + ((n_SRS%product_N_b_B_SRS)/2*product_N_b);
+        }
+
+        if (b <= b_hop) {
+          n_b[b] = (4 * n_RRC/m_SRS_b)%N_b;
+        }
+        else {
+          n_b[b] = (F_b + (4 * n_RRC/m_SRS_b))%N_b;
+        }
+      }
+    }
+
+    k_0_overbar_p = n_shift * N_SC_RB + K_TC_p;
+
+    k_0_p = k_0_overbar_p; /* it is the frequency-domain starting position */
+
+    for (int b = 0; b <= B_SRS; b++) {
+      k_0_p += K_TC * M_sc_b_SRS * n_b[b];
+    }
+
+    subcarrier = (frame_parms->first_carrier_offset) + k_0_p;
+    if (subcarrier>frame_parms->ofdm_symbol_size) {
+      subcarrier -= frame_parms->ofdm_symbol_size;
+    }
+
+    /* find index of table which is for this srs length */
+    unsigned int M_sc_b_SRS_index = 0;
+    while((ul_allocated_re[M_sc_b_SRS_index] != M_sc_b_SRS) && (M_sc_b_SRS_index < SRS_SB_CONF)){
+      M_sc_b_SRS_index++;
+    }
+
+    if (ul_allocated_re[M_sc_b_SRS_index] != M_sc_b_SRS) {
+      LOG_E(PHY, "generate_srs: srs uplink allocation %d can not be found! \n", M_sc_b_SRS);
+      return (-1);
+    }
+
+#if 0
+
+    char output_file[255];
+    char sequence_name[255];
+    sprintf(output_file, "rv_seq_%d_%d_%d.m", u, v_nu, ul_allocated_re[M_sc_b_SRS_index]);
+    sprintf(sequence_name, "rv_seq_%d_%d_%d", u, v_nu, ul_allocated_re[M_sc_b_SRS_index]);
+    write_output(output_file, sequence_name,  rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index], ul_allocated_re[M_sc_b_SRS_index], 1, 1);
+
+#endif
+
+    for (int k=0; k < M_sc_b_SRS; k++) {
+
+      double real_shift = cos(alpha_i*k);
+      double imag_shift = sin(alpha_i*k);
+
+      /* cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
+      double real = ((real_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k]) - (imag_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k+1]))/sqrt(N_ap);
+      /* sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
+      double imag = ((imag_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k]) + (real_shift*rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k+1]))/sqrt(N_ap);
+
+      int32_t real_amp = ((int32_t)round((double) amp * real)) >> 15;
+      int32_t imag_amp = ((int32_t)round((double) amp * imag)) >> 15;
+
+#if 0
+      printf("subcarrier %5d srs[%3d] r: %4d i: %4d reference[%d][%d][%d] r: %6d i: %6d\n", subcarrier, k, real_amp, imag_amp,
+                                                                                            u, v_nu, M_sc_b_SRS_index,
+                                                                                            rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k],
+                                                                                            rv_ul_ref_sig[u][v_nu][M_sc_b_SRS_index][2*k+1]);
+#endif
+
+      txptr[subcarrier] = (real_amp & 0xFFFF) + ((imag_amp<<16)&0xFFFF0000);
+
+      subcarrier += (K_TC); /* subcarrier increment */
+
+      if (subcarrier >= frame_parms->ofdm_symbol_size)
+        subcarrier=subcarrier-frame_parms->ofdm_symbol_size;
+    }
+    /* process next symbol */
+    txptr = txptr + frame_parms->ofdm_symbol_size;
+  }
+
+  return (0);
+}
+
+/*******************************************************************
+*
+* NAME :         is_srs_period_nr
+*
+* PARAMETERS :   pointer to resource set
+*                pointer to transmit buffer
+*                amplitude scaling for this physical signal
+*                slot number of transmission
+* RETURN :        0  if it is a valid slot for transmitting srs
+*                -1 if srs should not be transmitted
+*
+* DESCRIPTION :  for periodic,
+*
+*********************************************************************/
+int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, NR_DL_FRAME_PARMS *frame_parms, int frame_tx, int slot_tx)
+{
+  uint16_t T_SRS = srs_period[p_SRS_Resource->SRS_Periodicity];
+  uint16_t T_offset = p_SRS_Resource->SRS_Offset; /* FFS_TODO_NR to check interface */
+
+  if (T_offset > T_SRS) {
+    LOG_E(PHY,"is_srs_occasion_nr: T_offset %d is greater than T_SRS %d!\n", T_offset, T_SRS);
+    return (-1);
+  }
+
+  int16_t N_slot_frame = NR_NUMBER_OF_SUBFRAMES_PER_FRAME * frame_parms->ttis_per_subframe;
+  if ((N_slot_frame*frame_tx + slot_tx - T_offset)%T_SRS == 0) {
+    return (0);
+  }
+  else {
+    return (-1);
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         ue_srs_procedure_nr
+*
+* PARAMETERS :   pointer to ue context
+*                pointer to rxtx context*
+*
+* RETURN :        0 if it is a valid slot for transmitting srs
+*                -1 if srs should not be transmitted
+*
+* DESCRIPTION :  ue srs procedure
+*                send srs according to current configuration
+*
+*********************************************************************/
+int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id)
+{
+  NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms);
+  SRS_NR *p_srs_nr = &(ue->frame_parms.srs_nr);
+  SRS_ResourceSet_t *p_srs_resource_set = frame_parms->srs_nr.p_SRS_ResourceSetList[p_srs_nr->active_srs_Resource_Set];
+  int generate_srs = 0;
+
+  /* is there any resource set which has been configurated ? */
+  if (p_srs_nr->number_srs_Resource_Set != 0) {
+
+    /* what is the current active resource set ? */
+    if (p_srs_nr->active_srs_Resource_Set > MAX_NR_OF_SRS_RESOURCE_SET) {
+      LOG_W(PHY,"phy_procedures_UE_TX: srs active %d greater than maximum %d!\n", p_srs_nr->active_srs_Resource_Set, MAX_NR_OF_SRS_RESOURCE_SET);
+    }
+    else {
+      /* SRS resource set configurated ? */
+      if (p_srs_resource_set != NULL) {
+
+        SRS_Resource_t *p_srs_resource = frame_parms->srs_nr.p_SRS_ResourceSetList[p_srs_nr->active_srs_Resource_Set]->p_srs_ResourceList[0];
+
+        /* SRS resource configurated ? */
+        if (p_srs_resource != NULL) {
+          if (p_srs_resource_set->resourceType == periodic) {
+            if (is_srs_period_nr(p_srs_resource, frame_parms, proc->frame_tx, proc->nr_tti_tx) == 0) {
+              generate_srs = 1;
+            }
+          }
+        }
+        else {
+          LOG_W(PHY,"phy_procedures_UE_TX: no configurated srs resource!\n");
+        }
+      }
+    }
+  }
+  if (generate_srs == 1) {
+    int16_t txptr = AMP;
+    uint16_t nsymb = (ue->frame_parms.Ncp==0) ? 14:12;
+    uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((proc->nr_tti_tx*nsymb)+(nsymb-1));
+    if (generate_srs_nr(p_srs_resource_set, frame_parms, &ue->common_vars.txdataF[eNB_id][symbol_offset], txptr, proc) == 0) {
+      return 0;
+    }
+    else
+    {
+      return (-1);
+    }
+  }
+  else {
+    return (-1);
+  }
+}
+
+
+
+
+
+
+
+
+
+
+
+
+
+
diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h
new file mode 100644
index 0000000000000000000000000000000000000000..86fd7fcc917f5ada3eaff86d814198576d6ece62
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h
@@ -0,0 +1,169 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/***********************************************************************
+*
+* FILENAME    :  srs_modulation_nr.h
+*
+* MODULE      :
+*
+* DESCRIPTION :  function to generate uplink reference sequences
+*                see 3GPP TS 38.211 6.4.1.4 Sounding reference signal
+*
+************************************************************************/
+
+#ifndef SRS_MODULATION_NR_H
+#define SRS_MODULATION_NR_H
+
+#ifdef DEFINE_VARIABLES_SRS_MODULATION_NR_H
+#define EXTERN
+#define INIT_VARIABLES_SRS_MODULATION_NR_H
+#else
+#define EXTERN extern
+#undef INIT_VARIABLES_SRS_MODULATION_NR_H
+#endif
+
+
+/************** DEFINE ********************************************/
+
+#define C_SRS_NUMBER       (64)
+#define B_SRS_NUMBER       (4)
+
+/************** VARIABLES *****************************************/
+
+/* TS 38.211 Table 6.4.1.4.3-1: SRS bandwidth configuration */
+EXTERN const unsigned short srs_bandwidth_config[C_SRS_NUMBER][B_SRS_NUMBER][2]
+#ifdef INIT_VARIABLES_SRS_MODULATION_NR_H
+= {
+/*           B_SRS = 0    B_SRS = 1   B_SRS = 2    B_SRS = 3     */
+/* C SRS   m_srs0  N_0  m_srs1 N_1  m_srs2   N_2 m_srs3   N_3    */
+/* 0  */   { {   4,  1 },{   4,  1 },{   4,  1  },{   4,  1  } },
+/* 1  */   { {   8,  1 },{   4,  2 },{   4,  1  },{   4,  1  } },
+/* 2  */   { {  12,  1 },{   4,  3 },{   4,  1  },{   4,  1  } },
+/* 3  */   { {  16,  1 },{   4,  4 },{   4,  1  },{   4,  1  } },
+/* 4  */   { {  16,  1 },{   8,  2 },{   4,  2  },{   4,  1  } },
+/* 5  */   { {  20,  1 },{   4,  5 },{   4,  1  },{   4,  1  } },
+/* 6  */   { {  24,  1 },{   4,  6 },{   4,  1  },{   4,  1  } },
+/* 7  */   { {  24,  1 },{  12,  2 },{   4,  3  },{   4,  1  } },
+/* 8  */   { {  28,  1 },{   4,  7 },{   4,  1  },{   4,  1  } },
+/* 9  */   { {  32,  1 },{  16,  2 },{   8,  2  },{   4,  2  } },
+/* 10 */   { {  36,  1 },{  12,  3 },{   4,  3  },{   4,  1  } },
+/* 11 */   { {  40,  1 },{  20,  2 },{   4,  5  },{   4,  1  } },
+/* 12 */   { {  48,  1 },{  16,  3 },{   8,  2  },{   4,  2  } },
+/* 13 */   { {  48,  1 },{  24,  2 },{  12,  2  },{   4,  3  } },
+/* 14 */   { {  52,  1 },{   4, 13 },{   4,  1  },{   4,  1  } },
+/* 15 */   { {  56,  1 },{  28,  2 },{   4,  7  },{   4,  1  } },
+/* 16 */   { {  60,  1 },{  20,  3 },{   4,  5  },{   4,  1  } },
+/* 17 */   { {  64,  1 },{  32,  2 },{  16,  2  },{   4,  4  } },
+/* 18 */   { {  72,  1 },{  24,  3 },{  12,  2  },{   4,  3  } },
+/* 19 */   { {  72,  1 },{  36,  2 },{  12,  3  },{   4,  3  } },
+/* 20 */   { {  76,  1 },{   4, 19 },{   4,  1  },{   4,  1  } },
+/* 21 */   { {  80,  1 },{  40,  2 },{  20,  2  },{   4,  5  } },
+/* 22 */   { {  88,  1 },{  44,  2 },{   4, 11  },{   4,  1  } },
+/* 23 */   { {  96,  1 },{  32,  3 },{  16,  2  },{   4,  4  } },
+/* 24 */   { {  96,  1 },{  48,  2 },{  24,  2  },{   4,  6  } },
+/* 25 */   { { 104,  1 },{  52,  2 },{   4, 13  },{   4,  1  } },
+/* 26 */   { { 112,  1 },{  56,  2 },{  28,  2  },{   4,  7  } },
+/* 27 */   { { 120,  1 },{  60,  2 },{  20,  3  },{   4,  5  } },
+/* 28 */   { { 120,  1 },{  40,  3 },{   8,  5  },{   4,  2  } },
+/* 29 */   { { 120,  1 },{  24,  5 },{  12,  2  },{   4,  3  } },
+/* 30 */   { { 128,  1 },{  64,  2 },{  32,  2  },{   4,  8  } },
+/* 31 */   { { 128,  1 },{  64,  2 },{  16,  4  },{   4,  4  } },
+/* 32 */   { { 128,  1 },{  16,  8 },{   8,  2  },{   4,  2  } },
+/* 33 */   { { 132,  1 },{  44,  3 },{   4, 11  },{   4,  1  } },
+/* 34 */   { { 136,  1 },{  68,  2 },{   4, 17  },{   4,  1  } },
+/* 35 */   { { 144,  1 },{  72,  2 },{  36,  2  },{   4,  9  } },
+/* 36 */   { { 144,  1 },{  48,  3 },{  24,  2  },{  12,  2  } },
+/* 37 */   { { 144,  1 },{  48,  3 },{  16,  3  },{   4,  4  } },
+/* 38 */   { { 144,  1 },{  16,  9 },{   8,  2  },{   4,  2  } },
+/* 39 */   { { 152,  1 },{  76,  2 },{   4, 19  },{   4,  1  } },
+/* 40 */   { { 160,  1 },{  80,  2 },{  40,  2  },{   4, 10  } },
+/* 41 */   { { 160,  1 },{  80,  2 },{  20,  4  },{   4,  5  } },
+/* 42 */   { { 160,  1 },{  32,  5 },{  16,  2  },{   4,  4  } },
+/* 43 */   { { 168,  1 },{  84,  2 },{  28,  3  },{   4,  7  } },
+/* 44 */   { { 176,  1 },{  88,  2 },{  44,  2  },{   4, 11  } },
+/* 45 */   { { 184,  1 },{  92,  2 },{   4, 23  },{   4,  1  } },
+/* 46 */   { { 192,  1 },{  96,  2 },{  48,  2  },{   4, 12  } },
+/* 47 */   { { 192,  1 },{  96,  2 },{  24,  4  },{   4,  6  } },
+/* 48 */   { { 192,  1 },{  64,  3 },{  16,  4  },{   4,  4  } },
+/* 49 */   { { 192,  1 },{  24,  8 },{   8,  3  },{   4,  2  } },
+/* 50 */   { { 208,  1 },{ 104,  2 },{  52,  2  },{   4, 13  } },
+/* 51 */   { { 216,  1 },{ 108,  2 },{  36,  3  },{   4,  9  } },
+/* 52 */   { { 224,  1 },{ 112,  2 },{  56,  2  },{   4, 14  } },
+/* 53 */   { { 240,  1 },{ 120,  2 },{  60,  2  },{   4, 15  } },
+/* 54 */   { { 240,  1 },{  80,  3 },{  20,  4  },{   4,  5  } },
+/* 55 */   { { 240,  1 },{  48,  5 },{  16,  3  },{   8,  2  } },
+/* 56 */   { { 240,  1 },{  24, 10 },{  12,  2  },{   4,  3  } },
+/* 57 */   { { 256,  1 },{ 128,  2 },{  64,  2  },{   4, 16  } },
+/* 58 */   { { 256,  1 },{ 128,  2 },{  32,  4  },{   4,  8  } },
+/* 59 */   { { 256,  1 },{  16, 16 },{   8,  2  },{   4,  2  } },
+/* 60 */   { { 264,  1 },{ 132,  2 },{  44,  3  },{   4, 11  } },
+/* 61 */   { { 272,  1 },{ 136,  2 },{  68,  2  },{   4, 17  } },
+/* 62 */   { { 272,  1 },{  68,  4 },{   4, 17  },{   4,  1  } },
+/* 63 */   { { 272,  1 },{  16, 17 },{   8,  2  },{   4,  2  } },
+}
+#endif
+;
+
+#define SRS_PERIODICITY                 (17)
+
+EXTERN const uint16_t srs_periodicity[SRS_PERIODICITY]
+#ifdef INIT_VARIABLES_SRS_MODULATION_NR_H
+= { 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}
+#endif
+;
+
+/*************** FUNCTIONS *****************************************/
+
+/** \brief This function generates the sounding reference symbol (SRS) for the uplink according to 38.211 6.4.1.4 Sounding reference signal
+    @param frame_parms NR DL Frame parameters
+    @param txdataF pointer to the frequency domain TX signal
+    @param amp amplitude of generated signal
+    @param proc pointer to the transmit parameters
+    @returns 0 on success -1 on error with message */
+
+int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
+                        NR_DL_FRAME_PARMS *frame_parms,
+                        int32_t *txptr,
+                        int16_t amp,
+                        UE_nr_rxtx_proc_t *proc);
+
+/** \brief This function checks for periodic srs if srs should be transmitted in this slot
+ *  @param p_SRS_Resource pointer to active resource
+    @param frame_parms NR DL Frame parameters
+    @param txdataF pointer to the frequency domain TX signal
+    @returns 0 if srs should be transmitted -1 on error with message */
+
+int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource,
+                     NR_DL_FRAME_PARMS *frame_parms,
+                     int frame_tx, int slot_tx);
+/** \brief This function processes srs configuration
+ *  @param ue context
+    @param rxtx context
+    @param current eNB identifier
+    @returns 0 if srs is transmitted -1 otherwise */
+
+int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id);
+
+#undef EXTERN
+#undef INIT_VARIABLES_SRS_MODULATION_NR_H
+
+#endif /* SRS_MODULATION_NR_H */
diff --git a/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c
new file mode 100644
index 0000000000000000000000000000000000000000..904afb653cd0a77c3e264861a66a62fe5043d4f5
--- /dev/null
+++ b/openair1/PHY/NR_UE_TRANSPORT/sss_nr.c
@@ -0,0 +1,603 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/**********************************************************************
+*
+* FILENAME    :  sss_nr.c
+*
+* MODULE      :  Functions for secundary synchronisation signal
+*
+* DESCRIPTION :  generation of sss
+*                3GPP TS 38.211 7.4.2.3 Secondary synchronisation signal
+*
+************************************************************************/
+
+#include <stdio.h>
+#include <assert.h>
+#include <errno.h>
+
+#include "PHY/defs_nr_UE.h"
+#include "PHY/MODULATION/modulation_UE.h"
+
+#include "PHY/NR_REFSIG/ss_pbch_nr.h"
+
+#define DEFINE_VARIABLES_SSS_NR_H
+#include "PHY/NR_REFSIG/sss_nr.h"
+#undef DEFINE_VARIABLES_SSS_NR_H
+
+/*******************************************************************
+*
+* NAME :         init_context_sss_nr
+*
+* PARAMETERS :   N_ID_2 : element 2 of physical layer cell identity
+*                value : { 0, 1, 2 }
+*
+* RETURN :       generate binary sss sequence (this is a m-sequence)
+*                d_sss is a third dimension array depending on
+*                Cell identity elements:
+*                - N_ID_1 : value from 0 to 335
+*                - N_ID_2 : value from 0 to 2
+*
+* DESCRIPTION :  3GPP TS 38.211 7.4.2.3 Secundary synchronisation signal
+*                Sequence generation
+*
+*********************************************************************/
+
+#define INITIAL_SSS_NR    (7)
+
+void init_context_sss_nr(int amp)
+{
+  int16_t x0[LENGTH_SSS_NR];
+  int16_t x1[LENGTH_SSS_NR];
+  int16_t dss_current;
+  int m0, m1;
+
+  const int x0_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
+  const int x1_initial[INITIAL_SSS_NR] = { 1, 0, 0, 0, 0, 0, 0 };
+
+  for (int i=0; i < INITIAL_SSS_NR; i++) {
+    x0[i] = x0_initial[i];
+    x1[i] = x1_initial[i];
+  }
+
+  for (int i=0; i < (LENGTH_SSS_NR - INITIAL_SSS_NR); i++) {
+    x0[i+7] = (x0[i + 4] + x0[i])%(2);
+    x1[i+7] = (x1[i + 1] + x1[i])%(2);
+  }
+
+  for (int N_ID_2 = 0; N_ID_2 < N_ID_2_NUMBER; N_ID_2++) {
+
+    for (int N_ID_1 = 0; N_ID_1 < N_ID_1_NUMBER; N_ID_1++) {
+
+      m0 = 15*(N_ID_1/112) + (5*N_ID_2);
+      m1 = N_ID_1%112;
+
+      for (int n = 0; n < LENGTH_SSS_NR; n++) {
+
+        dss_current = (1 - 2*x0[(n + m0)%(LENGTH_SSS_NR)])*(1 - 2*x1[(n + m1)%(LENGTH_SSS_NR)]);
+
+      /* Modulation of SSS is a BPSK TS 36.211 chapter 5.1.2 BPSK */
+#if 1
+        d_sss[N_ID_2][N_ID_1][n]   = dss_current * amp;
+#else
+        (void) amp;
+        d_sss[N_ID_2][N_ID_1][n]   = (dss_current * SHRT_MAX)>>SCALING_PSS_NR;
+#endif
+      }
+    }
+  }
+
+#if 0
+  for (int i = 0; i < LENGTH_SSS_NR; i++) {
+    printf("sss ref[%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
+  }
+#endif
+}
+
+/*******************************************************************
+*
+* NAME :         insert_sss_nr
+*
+* PARAMETERS :   pointer to input buffer for which sss in inserted
+*                amp amplitude applied to input
+*                frame parameters for cell identity
+*
+* RETURN :       none
+*
+* DESCRIPTION :  Allow to generate a reference sss sequence according to cell identity
+*
+*********************************************************************/
+
+void insert_sss_nr(int16_t *sss_time,
+                   NR_DL_FRAME_PARMS *frame_parms)
+{
+  unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
+  unsigned int size = ofdm_symbol_size * IQ_SIZE; /* i & q */
+
+  assert(size <= SYNCF_TMP_SIZE);
+  assert(size <= SYNC_TMP_SIZE);
+
+  bzero(synchroF_tmp, size);
+  bzero(synchro_tmp, size);
+
+  int Nid2 = GET_NID2(frame_parms->Nid_cell);
+  int Nid1 = GET_NID1(frame_parms->Nid_cell);
+
+  /* call of IDFT should be done with ordered input as below
+    *
+    *                n input samples
+    *  <------------------------------------------------>
+    *  0                                                n
+    *  are written into input buffer for IFFT in this order
+    *   -------------------------------------------------
+    *  |xxxxxxx                       N/2       xxxxxxxx|
+    *  --------------------------------------------------
+    *  ^      ^                 ^               ^          ^
+    *  |      |                 |               |          |
+    * n/2    end of            n=0            start of    n/2-1
+    *         sss                               sss
+    *
+    *                   Frequencies
+    *      positives                   negatives
+    * 0                 (+N/2)(-N/2)
+    * |-----------------------><-------------------------|
+    *
+    * sample 0 is for continuous frequency which is not used here
+    */
+
+  unsigned int k = ofdm_symbol_size - ((LENGTH_SSS_NR/2)+1);
+
+  /* SSS is directly mapped to subcarrier */
+  for (int i=0; i<LENGTH_SSS_NR; i++) {
+    synchroF_tmp[2*k] = d_sss[Nid2][Nid1][i];
+    synchroF_tmp[2*k+1] = 0;
+
+    k++;
+
+    if (k >= ofdm_symbol_size) {
+      k++;
+      k-=ofdm_symbol_size;
+    }
+  }
+
+  /* get sss in the frequency domain by applying an inverse FFT */
+  idft2048(synchroF_tmp,          /* complex input */
+           synchro_tmp,           /* complex output */
+   	       1);                 /* scaling factor */
+
+  /* then get final sss in time */
+  for (unsigned int i=0; i<ofdm_symbol_size; i++) {
+    ((int32_t *)sss_time)[i] = ((int32_t *)synchro_tmp)[i];
+  }
+}
+
+/*******************************************************************
+*
+* NAME :         pss_ch_est
+*
+* PARAMETERS :   none
+*
+* RETURN :       none
+*
+* DESCRIPTION :  pss channel estimation
+*
+*********************************************************************/
+
+int pss_ch_est_nr(PHY_VARS_NR_UE *ue,
+                  int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
+                  int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR])
+{
+  int16_t *pss;
+  int16_t *pss_ext2,*sss_ext2,*sss_ext3,tmp_re,tmp_im,tmp_re2,tmp_im2;
+  uint8_t aarx,i;
+  NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+
+  pss = primary_synchro_nr[ue->common_vars.eNb_id];
+
+  sss_ext3 = (int16_t*)&sss_ext[0][0];
+
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+    sss_ext2 = (int16_t*)&sss_ext[aarx][0];
+    pss_ext2 = (int16_t*)&pss_ext[aarx][0];
+
+
+#if 0
+
+  int16_t *p = pss;
+
+  for (int i = 0; i < LENGTH_PSS_NR; i++) {
+    printf(" pss ref [%d]  %d  %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
+    printf(" pss ext [%d]  %d  %d at address %p\n", i, pss_ext2[2*i], pss_ext2[2*i+1], &pss_ext2[2*i]);
+  }
+
+#endif
+
+#if 0
+
+  for (int i = 0; i < LENGTH_PSS_NR; i++) {
+    printf(" sss ext 2 [%d]  %d  %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1], &sss_ext2[2*i]);
+    printf(" sss ref   [%d]  %d  %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
+  }
+
+#endif
+
+    for (i = 0; i < LENGTH_PSS_NR; i++) {
+
+      // This is H*(PSS) = R* \cdot PSS
+      tmp_re = (int16_t)(((pss_ext2[i*2] * (int32_t)pss[i*2])>>SCALING_CE_PSS_NR)   + ((pss_ext2[i*2+1] * (int32_t)pss[i*2+1])>>SCALING_CE_PSS_NR));
+      tmp_im = (int16_t)(((pss_ext2[i*2] * (int32_t)pss[i*2+1])>>SCALING_CE_PSS_NR) - ((pss_ext2[i*2+1] * (int32_t)pss[i*2])>>SCALING_CE_PSS_NR));
+      //printf("H*(%d,%d) : (%d,%d)\n",aarx,i,tmp_re,tmp_im);
+      //printf("pss(%d,%d) : (%d,%d)\n",aarx,i,pss[2*i],pss[2*i+1]);
+      //printf("pss_ext(%d,%d) : (%d,%d)\n",aarx,i,pss_ext2[2*i],pss_ext2[2*i+1]);
+
+      // This is R(SSS) \cdot H*(PSS)
+      tmp_re2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2])>>SCALING_CE_PSS_NR)    - ((tmp_im * (int32_t)sss_ext2[i*2+1]>>SCALING_CE_PSS_NR)));
+      tmp_im2 = (int16_t)(((tmp_re * (int32_t)sss_ext2[i*2+1])>>SCALING_CE_PSS_NR)  + ((tmp_im * (int32_t)sss_ext2[i*2]>>SCALING_CE_PSS_NR)));
+
+      // printf("SSSi(%d,%d) : (%d,%d)\n",aarx,i,sss_ext2[i<<1],sss_ext2[1+(i<<1)]);
+      // printf("SSSo(%d,%d) : (%d,%d)\n",aarx,i,tmp_re2,tmp_im2);
+      // MRC on RX antennas
+      if (aarx==0) {
+        sss_ext3[i<<1]      = tmp_re2;
+        sss_ext3[1+(i<<1)]  = tmp_im2;
+      } else {
+        sss_ext3[i<<1]      += tmp_re2;
+        sss_ext3[1+(i<<1)]  += tmp_im2;
+      }
+    }
+  }
+
+#if 0
+
+  for (int i = 0; i < LENGTH_PSS_NR; i++) {
+    printf(" sss ext 2 [%d]  %d  %d at address %p\n", i, sss_ext2[2*i], sss_ext2[2*i+1]);
+    printf(" sss ref   [%d]  %d  %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i]);
+    printf(" sss ext 3 [%d]  %d  %d at address %p\n", i, sss_ext3[2*i], sss_ext3[2*i+1]);
+  }
+
+#endif
+
+  // sss_ext now contains the compensated SSS
+  return(0);
+}
+
+/*******************************************************************
+*
+* NAME :         do_pss_sss_extract
+*
+* PARAMETERS :   none
+*
+* RETURN :       none
+*
+* DESCRIPTION : it allows extracting sss from samples buffer
+*
+*********************************************************************/
+
+int do_pss_sss_extract_nr(PHY_VARS_NR_UE *ue,
+                          int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
+                          int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
+                          uint8_t doPss, uint8_t doSss,
+					      uint8_t subframe) // add flag to indicate extracting only PSS, only SSS, or both
+{
+  uint8_t aarx;
+  int32_t *pss_rxF,*pss_rxF_ext;
+  int32_t *sss_rxF,*sss_rxF_ext;
+  uint8_t pss_symbol, sss_symbol;
+  int32_t **rxdataF;
+  NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
+
+#if 1
+
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+    pss_symbol = PSS_SYMBOL_NB;  /* symbol position */
+    sss_symbol = SSS_SYMBOL_NB;
+
+    rxdataF  =  ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF;
+
+    unsigned int ofdm_symbol_size = frame_parms->ofdm_symbol_size;
+
+    pss_rxF  =  &rxdataF[aarx][pss_symbol*ofdm_symbol_size];
+    sss_rxF  =  &rxdataF[aarx][sss_symbol*ofdm_symbol_size];
+
+    pss_rxF_ext = &pss_ext[aarx][0];
+    sss_rxF_ext = &sss_ext[aarx][0];
+
+    unsigned int k = ofdm_symbol_size - ((LENGTH_PSS_NR/2)+1);
+
+    for (int i=0; i < LENGTH_PSS_NR; i++) {
+      if (doPss) {		  
+        pss_rxF_ext[i] = pss_rxF[k];
+      }
+
+      if (doSss) {
+        sss_rxF_ext[i] = sss_rxF[k];
+      }
+
+      k++;
+
+      if (k >= ofdm_symbol_size) {
+	    k++;
+        k-=ofdm_symbol_size;
+      }
+    }
+  }
+
+#if 0
+
+  int16_t *p = (int16_t *)sss_rxF_ext;
+
+  for (int i = 0; i < LENGTH_PSS_NR; i++) {
+    printf(" sss ext 2 [%d]  %d  %d at address %p\n", i, p[2*i], p[2*i+1], &p[2*i]);
+    printf(" sss ref   [%d]  %d  %d at address %p\n", i, d_sss[0][0][i], d_sss[0][0][i], &d_sss[0][0][i]);
+  }
+
+#endif
+
+#if 0
+
+  int16_t *p2 = (int16_t *)pss_rxF_ext;
+
+  for (int i = 0; i < LENGTH_PSS_NR; i++) {
+    printf(" pss_rxF_ext [%d]  %d  %d at address %p\n", i, p2[2*i], p2[2*i+1], &p2[2*i]);
+  }
+
+#endif
+
+#else
+
+  /* same method as LTE implementation */
+
+  uint16_t rb,nb_rb = N_RB_SS_PBCH_BLOCK;
+
+  int rx_offset = frame_parms->ofdm_symbol_size - (LENGTH_SSS_NR/2);
+
+  for (aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+
+    pss_symbol = PSS_SYMBOL_NB;
+    sss_symbol = SSS_SYMBOL_NB;
+
+    rxdataF  =  ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[subframe]].rxdataF;
+    pss_rxF  =  &rxdataF[aarx][(rx_offset + (pss_symbol*(frame_parms->ofdm_symbol_size)))];
+    sss_rxF  =  &rxdataF[aarx][(rx_offset + (sss_symbol*(frame_parms->ofdm_symbol_size)))];
+
+    //printf("extract_rbs: symbol_mod=%d, rx_offset=%d, ch_offset=%d\n",symbol_mod,
+    //   (rx_offset + (symbol*(frame_parms->ofdm_symbol_size)))*2,
+    //   LTE_CE_OFFSET+ch_offset+(symbol_mod*(frame_parms->ofdm_symbol_size)));
+
+    pss_rxF_ext = &pss_ext[aarx][0];
+    sss_rxF_ext = &sss_ext[aarx][0];
+
+    for (rb=0; rb<nb_rb; rb++) {
+
+      for (int i=0; i<N_SC_RB; i++) {
+        if (doPss) {pss_rxF_ext[i] = pss_rxF[i];}
+        if (doSss) {sss_rxF_ext[i] = sss_rxF[i];}
+      }
+
+      pss_rxF += N_SC_RB;
+      sss_rxF += N_SC_RB;
+      pss_rxF_ext += N_SC_RB;
+      sss_rxF_ext += N_SC_RB;
+    }
+  }
+
+#endif
+
+  return(0);
+}
+
+/*******************************************************************
+*
+* NAME :         rx_sss_nr
+*
+* PARAMETERS :   none
+*
+* RETURN :       none
+*
+* DESCRIPTION :
+*
+*********************************************************************/
+
+int pss_sss_extract_nr(PHY_VARS_NR_UE *phy_vars_ue,
+                       int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR],
+                       int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR],
+					   uint8_t subframe)
+{
+  return do_pss_sss_extract_nr(phy_vars_ue, pss_ext, sss_ext, 1 /* doPss */, 1 /* doSss */, subframe);
+}
+
+/*******************************************************************
+*
+* NAME :         rx_sss_nr
+*
+* PARAMETERS :   none
+*
+* RETURN :       Set Nid_cell in ue context
+*
+* DESCRIPTION :  Determine element Nid1 of cell identity
+*                so Nid_cell in ue context is set according to Nid1 & Nid2
+*
+*********************************************************************/
+
+int rx_sss_nr(PHY_VARS_NR_UE *ue, int32_t *tot_metric,uint8_t *phase_max)
+{
+  uint8_t i;
+  int32_t pss_ext[NB_ANTENNAS_RX][LENGTH_PSS_NR];
+  int32_t sss_ext[NB_ANTENNAS_RX][LENGTH_SSS_NR];
+  uint8_t Nid2 = GET_NID2(ue->common_vars.eNb_id);
+  uint16_t Nid1;
+  uint8_t phase;
+  int16_t *sss;
+  NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
+  int32_t metric, metric_re;
+  int16_t *d;
+
+  /* slop_fep function works for lte and takes into account begining of frame with prefix for subframe 0 */
+  /* for NR this is not the case but slot_fep is still used for computing FFT of samples */
+  /* in order to achieve correct processing for NR prefix samples is forced to 0 and then restored after function call */
+  /* symbol number are from beginning of SS/PBCH blocks as below:  */
+  /*    Signal            PSS  PBCH  SSS  PBCH                     */
+  /*    symbol number      0     1    2    3                       */
+  /* time samples in buffer rxdata are used as input of FFT -> FFT results are stored in the frequency buffer rxdataF */
+  /* rxdataF stores SS/PBCH from beginning of buffers in the same symbol order as in time domain */
+
+  int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
+  frame_parms->nb_prefix_samples0 = 0;
+
+  // Do FFTs for SSS/PSS
+  // SSS
+  slot_fep_pbch(ue,
+           SSS_SYMBOL_NB,      // symbol number
+           0,                  // Ns slot number
+           ue->rx_offset,      // sample_offset of int16_t
+           0,                  // no_prefix
+           1);                 // reset frequency estimation
+
+  // PSS
+  slot_fep_pbch(ue,
+           PSS_SYMBOL_NB,
+           0,
+           ue->rx_offset,
+           0,
+           1);
+
+  frame_parms->nb_prefix_samples0 = nb_prefix_samples0;
+
+  // pss sss extraction
+  pss_sss_extract_nr(ue,
+                     pss_ext,
+                     sss_ext,
+                     0);          /* subframe */
+
+#ifdef DEBUG_PLOT_SSS
+
+  write_output("rxsig0.m","rxs0",&ue->common_vars.rxdata[0][0],ue->frame_parms.samples_per_tti,1,1);
+  write_output("rxdataF0.m","rxF0",&ue->common_vars.common_vars_rx_data_per_thread[ue->current_thread_id[0]].rxdataF[0],frame_parms->ofdm_symbol_size,2,1);
+  write_output("pss_ext.m","pss_ext",pss_ext,LENGTH_PSS_NR,1,1);
+
+#endif
+
+#if 0
+
+  write_output("sss_ext.m","sss_ext",sss_ext,LENGTH_SSS_NR,1,1);
+  write_output("sss_ref.m","sss_ref", d_sss,LENGTH_SSS_NR,1,1);
+
+#endif
+
+#if 0
+  int16_t *p = (int16_t *)sss_ext[0];
+  int16_t *p2 = (int16_t *)pss_ext[0];
+
+  for (int i = 0; i < LENGTH_SSS_NR; i++) {
+    printf("sss ref  [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
+    printf("sss ext  [%i] : %d %d \n", i, p[2*i], p[2*i+1]);
+
+    printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr[0][2*i], primary_synchro_nr[0][2*i+1]);
+    printf("pss ext [%i] : %d %d \n", i, p2[2*i], p2[2*i+1]);
+  }
+#endif
+
+  // get conjugated channel estimate from PSS, H* = R* \cdot PSS
+  // and do channel estimation and compensation based on PSS
+
+  pss_ch_est_nr(ue,
+                pss_ext,
+                sss_ext);
+
+  // now do the SSS detection based on the precomputed sequences in PHY/LTE_TRANSPORT/sss.h
+  *tot_metric = INT_MIN;
+
+  sss = (int16_t*)&sss_ext[0][0];
+
+#if 0
+
+  /* simulate of a phase shift on the signal */
+
+  int phase_shift_index = 0;
+
+  phase_shift_samples(sss, LENGTH_SSS_NR, phase_re_nr[phase_shift_index], phase_im_nr[phase_shift_index]);
+
+#endif
+
+#if 0
+        int16_t *ps = (int16_t *)pss_ext;
+
+        for (int i = 0; i < LENGTH_SSS_NR; i++) {
+          printf("sss ref  [%i] : %d %d \n", i, d_sss[0][0][i], d_sss[0][0][i]);
+          printf("sss ext  [%i] : %d %d \n", i, sss[2*i], sss[2*i+1]);
+
+          printf("pss ref [%i] : %d %d \n", i, primary_synchro_nr[0][2*i], primary_synchro_nr[0][2*i+1]);
+          printf("pss ext [%i] : %d %d \n", i, ps[2*i], ps[2*i+1]);
+        }
+#endif
+
+  /* for phase evaluation, one uses an array of possible phase shifts */
+  /* then a correlation is done between received signal with a shift pĥase and the reference signal */
+  /* Computation of signal with shift phase is based on below formula */
+  /* cosinus cos(x + y) = cos(x)cos(y) - sin(x)sin(y) */
+  /* sinus   sin(x + y) = sin(x)cos(y) + cos(x)sin(y) */
+
+  for (phase=0; phase < PHASE_HYPOTHESIS_NUMBER; phase++) {  // phase offset between PSS and SSS
+    for (Nid1 = 0 ; Nid1 < N_ID_1_NUMBER; Nid1++) {          // all possible Nid1 values
+
+      metric = 0;
+      metric_re = 0;
+
+      d = (int16_t *)&d_sss[Nid2][Nid1];
+
+      // This is the inner product using one particular value of each unknown parameter
+      for (i=0; i < LENGTH_SSS_NR; i++) {
+
+        metric_re += d[i]*(((phase_re_nr[phase]*sss[2*i])>>SCALING_METRIC_SSS_NR) - ((phase_im_nr[phase]*sss[2*i+1])>>SCALING_METRIC_SSS_NR))
+                   + d[i]*(((phase_im_nr[phase]*sss[2*i])>>SCALING_METRIC_SSS_NR) + ((phase_re_nr[phase]*sss[2*i+1])>>SCALING_METRIC_SSS_NR));
+      }
+
+      metric = metric_re;
+
+      // if the current metric is better than the last save it
+      if (metric > *tot_metric) {
+        *tot_metric = metric;
+        ue->frame_parms.Nid_cell = Nid2+(3*Nid1);
+        *phase_max = phase;
+
+#ifdef DEBUG_SSS_NR
+
+        printf("(phase,Nid1) (%d,%d), metric_phase %d tot_metric %d, phase_max %d \n",phase, Nid1, metric, *tot_metric, *phase_max);
+
+#endif
+      }
+    }
+  }
+
+#ifdef DEBUG_SSS_NR
+
+#define SSS_METRIC_FLOOR_NR   (30000)
+if (*tot_metric > SSS_METRIC_FLOOR_NR) {	
+    Nid2 = GET_NID2(frame_parms->Nid_cell);
+    Nid1 = GET_NID1(frame_parms->Nid_cell);
+    printf("Nid2 %d Nid1 %d tot_metric %d, phase_max %d \n", Nid2, Nid1, *tot_metric, *phase_max);
+}
+#endif
+
+  return(0);
+}
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index c4e83cc6a4243fe8350d192dbe28afcf196e8af3..4c41852bad9953392d983a0720f46ad02b7f6bf6 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -19,9 +19,9 @@
  *      contact@openairinterface.org
  */
 
-/*! \file PHY/defs_gNB.h
- \brief Top-level defines and structure definitions for gNB
- \author Guy De Souza
+/*! \file PHY/defs_nr_UE.h
+ \brief Top-level defines and structure definitions for nr ue
+ \author Guy De Souza, H. WANG
  \date 2018
  \version 0.1
  \company Eurecom
@@ -29,15 +29,1026 @@
  \note
  \warning
 */
-#ifndef __PHY_DEFS_GNB__H__
-#define __PHY_DEFS_GNB__H__
+#ifndef __PHY_DEFS_NR_UE__H__
+#define __PHY_DEFS_NR_UE__H__
 
 
 #include "defs_nr_common.h"
 
+#define _GNU_SOURCE 
+#include <stdio.h>
+#include <stdlib.h>
+#include <malloc.h>
+#include <string.h>
+#include <math.h>
+#include "common_lib.h"
+#include "msc.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
+
+//#define RX_NB_TH_MAX 3
+//#define RX_NB_TH 3
+
+
+//#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 "impl_defs_top.h"
+#include "impl_defs_nr.h"
+
+#include "PHY/TOOLS/time_meas.h"
+#include "PHY/CODING/coding_defs.h"
+#include "PHY/TOOLS/tools_defs.h"
+#include "platform_types.h"
+#include "NR_UE_TRANSPORT/nr_transport_ue.h"
+
+#if defined(UPGRADE_RAT_NR)
+
+#include "PHY/NR_REFSIG/ss_pbch_nr.h"
+
+#endif
+
+//#include "PHY/LTE_TRANSPORT/defs.h"
+#include <pthread.h>
+
+#include "targets/ARCH/COMMON/common_lib.h"
+
+
+
+/// 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;
+//#ifdef UE_NR_PHY_DEMO
+  /// NR TTI index within subframe_tx [0 .. ttis_per_subframe - 1] to act upon for transmission
+  int nr_tti_tx;
+  /// NR TTI index within subframe_rx [0 .. ttis_per_subframe - 1] to act upon for reception
+  int nr_tti_rx;
+//#endif
+  /// 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;
+
+  /// internal This variable is protected by ref mutex_fep_slot1.
+  //int instance_cnt_slot0_dl_processing;
+  int instance_cnt_slot1_dl_processing;
+  /// pthread descriptor fep_slot1 thread
+  //pthread_t pthread_slot0_dl_processing;
+  pthread_t pthread_slot1_dl_processing;
+  /// pthread attributes for fep_slot1 processing thread
+ // pthread_attr_t attr_slot0_dl_processing;
+  pthread_attr_t attr_slot1_dl_processing;
+  /// condition variable for UE fep_slot1 thread;
+  //pthread_cond_t cond_slot0_dl_processing;
+  pthread_cond_t cond_slot1_dl_processing;
+  /// mutex for UE synch thread
+  //pthread_mutex_t mutex_slot0_dl_processing;
+  pthread_mutex_t mutex_slot1_dl_processing;
+  //int instance_cnt_slot0_dl_processing;
+  int instance_cnt_dlsch_td;
+  /// pthread descriptor fep_slot1 thread
+  //pthread_t pthread_slot0_dl_processing;
+  pthread_t pthread_dlsch_td;
+  /// pthread attributes for fep_slot1 processing thread
+ // pthread_attr_t attr_slot0_dl_processing;
+  pthread_attr_t attr_dlsch_td;
+  /// condition variable for UE fep_slot1 thread;
+  //pthread_cond_t cond_slot0_dl_processing;
+  pthread_cond_t cond_dlsch_td;
+  /// mutex for UE synch thread
+  //pthread_mutex_t mutex_slot0_dl_processing;
+  pthread_mutex_t mutex_dlsch_td;
+  //
+  uint8_t chan_est_pilot0_slot1_available;
+  uint8_t chan_est_slot1_available;
+  uint8_t llr_slot1_available;
+  uint8_t dci_slot0_available;
+  uint8_t first_symbol_available;
+  uint8_t decoder_thread_available;
+  uint8_t decoder_main_available;
+  uint8_t decoder_switch;
+  int counter_decoder;
+  uint8_t channel_level;
+  int eNB_id;
+  int harq_pid;
+  int llr8_flag;
+  /// scheduling parameters for fep_slot1 thread
+  struct sched_param sched_param_fep_slot1;
+
+  int sub_frame_start;
+  int sub_frame_step;
+  unsigned long long gotIQs;
+  uint8_t decoder_thread_available1;
+  int instance_cnt_dlsch_td1;
+  /// pthread descriptor fep_slot1 thread
+  //pthread_t pthread_slot0_dl_processing;
+  pthread_t pthread_dlsch_td1;
+  /// pthread attributes for fep_slot1 processing thread
+ // pthread_attr_t attr_slot0_dl_processing;
+  pthread_attr_t attr_dlsch_td1;
+  /// condition variable for UE fep_slot1 thread;
+  //pthread_cond_t cond_slot0_dl_processing;
+  pthread_cond_t cond_dlsch_td1;
+  /// mutex for UE synch thread
+  //pthread_mutex_t mutex_slot0_dl_processing;
+  pthread_mutex_t mutex_dlsch_td1;
+  int dci_err_cnt;
+} UE_nr_rxtx_proc_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_nr_rxtx_proc_t proc_rxtx[RX_NB_TH];
+} UE_nr_proc_t;
+
+#define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg
+
+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_NR_MEASUREMENTS;
+
+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];
+}NR_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;
+
+  NR_UE_COMMON_PER_THREAD common_vars_rx_data_per_thread[RX_NB_TH_MAX];
+
+  /// 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;
+} NR_UE_COMMON;
+
+typedef struct {
+  /// \brief Received frequency-domain signal after extraction.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **rxdataF_ext;
+  /// \brief Received frequency-domain ue specific pilots.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..12*N_RB_DL[
+  int32_t **rxdataF_uespec_pilots;
+  /// \brief Received frequency-domain signal after extraction and channel compensation.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **rxdataF_comp0;
+  /// \brief Received frequency-domain signal after extraction and channel compensation for the second stream. For the SIC receiver we need to store the history of this for each harq process and round
+  /// - first index: ? [0..7] (hard coded) accessed via \c harq_pid
+  /// - second index: ? [0..7] (hard coded) accessed via \c round
+  /// - third index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - fourth index: ? [0..168*N_RB_DL[
+  int32_t **rxdataF_comp1[8][8];
+  /// \brief Downlink channel estimates extracted in PRBS.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_estimates_ext;
+  /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. For the SIC receiver we need to store the history of this for each harq process and round
+  /// - first index: ? [0..7] (hard coded) accessed via \c harq_pid
+  /// - second index: ? [0..7] (hard coded) accessed via \c round
+  /// - third index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - fourth index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_rho_ext[8][8];
+  /// \brief Downlink beamforming channel estimates in frequency domain.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: samples? [0..symbols_per_tti*(ofdm_symbol_size+LTE_CE_FILTER_LENGTH)[
+  int32_t **dl_bf_ch_estimates;
+  /// \brief Downlink beamforming channel estimates.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_bf_ch_estimates_ext;
+  /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_rho2_ext;
+  /// \brief Downlink PMIs extracted in PRBS and grouped in subbands.
+  /// - first index: ressource block [0..N_RB_DL[
+  uint8_t *pmi_ext;
+  /// \brief Magnitude of Downlink Channel first layer (16QAM level/First 64QAM level).
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_mag0;
+  /// \brief Magnitude of Downlink Channel second layer (16QAM level/First 64QAM level).
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_mag1[8][8];
+  /// \brief Magnitude of Downlink Channel, first layer (2nd 64QAM level).
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_magb0;
+  /// \brief Magnitude of Downlink Channel second layer (2nd 64QAM level).
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_magb1[8][8];
+  /// \brief Cross-correlation of two eNB signals.
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: symbol [0..]
+  int32_t **rho;
+  /// never used... always send dl_ch_rho_ext instead...
+  int32_t **rho_i;
+  /// \brief Pointers to llr vectors (2 TBs).
+  /// - first index: ? [0..1] (hard coded)
+  /// - second index: ? [0..1179743] (hard coded)
+  int16_t *llr[2];
+  /// \f$\log_2(\max|H_i|^2)\f$
+  int16_t log2_maxh;
+    /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer1 channel compensation
+  int16_t log2_maxh0;
+    /// \f$\log_2(\max|H_i|^2)\f$ //this is for TM3-4 layer2 channel commpensation
+  int16_t log2_maxh1;
+  /// \brief LLR shifts for subband scaling.
+  /// - first index: ? [0..168*N_RB_DL[
+  uint8_t *llr_shifts;
+  /// \brief Pointer to LLR shifts.
+  /// - first index: ? [0..168*N_RB_DL[
+  uint8_t *llr_shifts_p;
+  /// \brief Pointers to llr vectors (128-bit alignment).
+  /// - first index: ? [0..0] (hard coded)
+  /// - second index: ? [0..]
+  int16_t **llr128;
+  /// \brief Pointers to llr vectors (128-bit alignment).
+  /// - first index: ? [0..0] (hard coded)
+  /// - second index: ? [0..]
+  int16_t **llr128_2ndstream;
+  //uint32_t *rb_alloc;
+  //uint8_t Qm[2];
+  //MIMO_mode_t mimo_mode;
+  // llr offset per ofdm symbol
+  uint32_t llr_offset[14];
+  // llr length per ofdm symbol
+  uint32_t llr_length[14];
+} NR_UE_PDSCH;
+
+typedef struct {
+  /// \brief Received frequency-domain signal after extraction.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..]
+  int32_t **rxdataF_ext;
+  /// \brief Received frequency-domain signal after extraction and channel compensation.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..]
+  double **rxdataF_comp;
+  /// \brief Downlink channel estimates extracted in PRBS.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..]
+  int32_t **dl_ch_estimates_ext;
+  ///  \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..]
+  double **dl_ch_rho_ext;
+  /// \brief Downlink PMIs extracted in PRBS and grouped in subbands.
+  /// - first index: ressource block [0..N_RB_DL[
+  uint8_t *pmi_ext;
+  /// \brief Magnitude of Downlink Channel (16QAM level/First 64QAM level).
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..]
+  double **dl_ch_mag;
+  /// \brief Magnitude of Downlink Channel (2nd 64QAM level).
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..]
+  double **dl_ch_magb;
+  /// \brief Cross-correlation of two eNB signals.
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: ? [0..]
+  double **rho;
+  /// never used... always send dl_ch_rho_ext instead...
+  double **rho_i;
+  /// \brief Pointers to llr vectors (2 TBs).
+  /// - first index: ? [0..1] (hard coded)
+  /// - second index: ? [0..1179743] (hard coded)
+  int16_t *llr[2];
+  /// \f$\log_2(\max|H_i|^2)\f$
+  uint8_t log2_maxh;
+  /// \brief Pointers to llr vectors (128-bit alignment).
+  /// - first index: ? [0..0] (hard coded)
+  /// - second index: ? [0..]
+  int16_t **llr128;
+  //uint32_t *rb_alloc;
+  //uint8_t Qm[2];
+  //MIMO_mode_t mimo_mode;
+} NR_UE_PDSCH_FLP;
+
+typedef struct {
+  /// \brief Pointers to extracted PDCCH symbols in frequency-domain.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **rxdataF_ext;
+  /// \brief Pointers to extracted and compensated PDCCH symbols in frequency-domain.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **rxdataF_comp;
+  /// \brief Pointers to extracted channel estimates of PDCCH symbols.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_estimates_ext;
+  /// \brief Pointers to channel cross-correlation vectors for multi-eNB detection.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_rho_ext;
+  /// \brief Pointers to channel cross-correlation vectors for multi-eNB detection.
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: ? [0..]
+  int32_t **rho;
+  /// \brief Pointer to llrs, 4-bit resolution.
+  /// - first index: ? [0..48*N_RB_DL[
+  uint16_t *llr;
+  /// \brief Pointer to llrs, 16-bit resolution.
+  /// - first index: ? [0..96*N_RB_DL[
+  uint16_t *llr16;
+  /// \brief \f$\overline{w}\f$ from 36-211.
+  /// - first index: ? [0..48*N_RB_DL[
+  uint16_t *wbar;
+  /// \brief PDCCH/DCI e-sequence (input to rate matching).
+  /// - first index: ? [0..96*N_RB_DL[
+  int8_t *e_rx;
+  /// number of PDCCH symbols in current subframe
+  uint8_t num_pdcch_symbols;
+  /// Allocated CRNTI for UE
+  uint16_t crnti;
+  /// 1: the allocated crnti is Temporary C-RNTI / 0: otherwise
+  uint8_t crnti_is_temporary;
+  /// Total number of PDU errors (diagnostic mode)
+  uint32_t dci_errors;
+  /// Total number of PDU received
+  uint32_t dci_received;
+  /// Total number of DCI False detection (diagnostic mode)
+  uint32_t dci_false;
+  /// Total number of DCI missed (diagnostic mode)
+  uint32_t dci_missed;
+  /// nCCE for PUCCH per subframe
+  uint8_t nCCE[10];
+  //Check for specific DCIFormat and AgregationLevel
+  uint8_t dciFormat;
+  uint8_t agregationLevel;
+} NR_UE_PDCCH;
+
+#define PBCH_A 24
+
+typedef struct {
+  /// \brief Pointers to extracted PBCH symbols in frequency-domain.
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: ? [0..287] (hard coded)
+  int32_t **rxdataF_ext;
+  /// \brief Pointers to extracted and compensated PBCH symbols in frequency-domain.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..287] (hard coded)
+  int32_t **rxdataF_comp;
+  /// \brief Pointers to downlink channel estimates in frequency-domain extracted in PRBS.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..287] (hard coded)
+  int32_t **dl_ch_estimates_ext;
+  /// \brief Pointer to PBCH llrs.
+  /// - first index: ? [0..1919] (hard coded)
+  int8_t *llr;
+  /// \brief Pointer to PBCH decoded output.
+  /// - first index: ? [0..63] (hard coded)
+  uint8_t *decoded_output;
+  /// \brief Total number of PDU errors.
+  uint32_t pdu_errors;
+  /// \brief Total number of PDU errors 128 frames ago.
+  uint32_t pdu_errors_last;
+  /// \brief Total number of consecutive PDU errors.
+  uint32_t pdu_errors_conseq;
+  /// \brief FER (in percent) .
+  uint32_t pdu_fer;
+} NR_UE_PBCH;
+
+typedef struct {
+  int16_t amp;
+  int16_t *prachF;
+  int16_t *prach;
+} NR_UE_PRACH;
+
+/*typedef enum {
+  /// do not detect any DCIs in the current subframe
+  NO_DCI = 0x0,
+  /// detect only downlink DCIs in the current subframe
+  UL_DCI = 0x1,
+  /// detect only uplink DCIs in the current subframe
+  DL_DCI = 0x2,
+  /// detect both uplink and downlink DCIs in the current subframe
+  UL_DL_DCI = 0x3} nr_dci_detect_mode_t;*/
+
+typedef struct UE_NR_SCAN_INFO_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_NR_SCAN_INFO_t;
+
+/// 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_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_nr_proc_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_NR_MEASUREMENTS measurements;
+  NR_DL_FRAME_PARMS  frame_parms;
+  /// \brief Frame parame before ho used to recover if ho fails.
+  NR_DL_FRAME_PARMS  frame_parms_before_ho;
+  NR_UE_COMMON    common_vars;
+
+  // point to the current rxTx thread index
+  uint8_t current_thread_id[10];
 
+  NR_UE_PDSCH     *pdsch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX+1]; // two RxTx Threads
+  NR_UE_PDSCH_FLP *pdsch_vars_flp[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  NR_UE_PDSCH     *pdsch_vars_SI[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  NR_UE_PDSCH     *pdsch_vars_ra[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  NR_UE_PDSCH     *pdsch_vars_p[NUMBER_OF_CONNECTED_eNB_MAX+1];
+  NR_UE_PDSCH     *pdsch_vars_MCH[NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_UE_PBCH      *pbch_vars[NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_UE_PDCCH     *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_UE_PRACH     *prach_vars[NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_UE_DLSCH_t   *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_eNB_MAX][2]; // two RxTx Threads
+  NR_UE_ULSCH_t   *ulsch[NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_UE_DLSCH_t   *dlsch_SI[NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_UE_DLSCH_t   *dlsch_ra[NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_UE_DLSCH_t   *dlsch_p[NUMBER_OF_CONNECTED_eNB_MAX];
+  NR_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];
+
+#if defined(UPGRADE_RAT_NR)
+
+  /// demodulation reference signal for NR PBCH
+  uint32_t dmrs_pbch_bitmap_nr[DMRS_PBCH_I_SSB][DMRS_PBCH_N_HF][DMRS_BITMAP_SIZE];
+
+#endif
+
+  /// 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_NR_SCAN_INFO_t scan_info[NB_BANDS_MAX];
+
+  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              time_sync_cell;
+  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[RX_NB_TH];
+  time_stats_t phy_proc_tx;
+  time_stats_t phy_proc_rx[RX_NB_TH];
+
+  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 generic_stat_bis[RX_NB_TH][LTE_SLOTS_PER_SUBFRAME];
+  time_stats_t ue_front_end_stat[RX_NB_TH];
+  time_stats_t ue_front_end_per_slot_stat[RX_NB_TH][LTE_SLOTS_PER_SUBFRAME];
+  time_stats_t pdcch_procedures_stat[RX_NB_TH];
+  time_stats_t pdsch_procedures_stat[RX_NB_TH];
+  time_stats_t pdsch_procedures_per_slot_stat[RX_NB_TH][LTE_SLOTS_PER_SUBFRAME];
+  time_stats_t dlsch_procedures_stat[RX_NB_TH];
+
+  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_llr_stats_parallelization[RX_NB_TH][LTE_SLOTS_PER_SUBFRAME];
+  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_NR_UE;
+
+/* this structure is used to pass both UE phy vars and
+ * proc to the function UE_thread_rxn_txnp4
+ */
+struct nr_rxtx_thread_data {
+  PHY_VARS_NR_UE    *UE;
+  UE_nr_rxtx_proc_t *proc;
+};
+
+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) {
+
+  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.h"
+#include "PHY/LTE_REFSIG/defs.h"
+#include "PHY/MODULATION/defs.h"
+#include "PHY/LTE_TRANSPORT/proto.h"
+#include "PHY/LTE_ESTIMATION/defs.h"
+*/
+#include "SIMULATION/ETH_TRANSPORT/defs.h"
 #endif
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 65168dfb8c368cf4bbf98f4616e24290661b1965..996797a7adfb5ecb316337f3f6bd4b763edf947a 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -34,6 +34,7 @@
 #define __PHY_DEFS_NR_COMMON__H__
 
 #include "defs_common.h"
+#include "impl_defs_nr.h"
 #include "PHY/CODING/nrPolar_tools/nr_polar_defs.h"
 
 #define nr_subframe_t lte_subframe_t
@@ -73,6 +74,14 @@ typedef enum{
 } nr_ssb_type_e;
 
 typedef struct NR_DL_FRAME_PARMS {
+  /// Number of resource blocks (RB) in DL
+  uint8_t N_RB_DL;
+  /// Number of resource blocks (RB) in UL
+  uint8_t N_RB_UL;
+  ///  total Number of Resource Block Groups: this is ceil(N_PRB/P)
+  uint8_t N_RBG;
+  /// Total Number of Resource Block Groups SubSets: this is P
+  uint8_t N_RBGS;
   /// EUTRA Band
   uint8_t eutra_band;
   /// DL carrier frequency
@@ -84,6 +93,13 @@ typedef struct NR_DL_FRAME_PARMS {
   /// RX attenuation
   uint32_t att_rx;
   ///  total Number of Resource Block Groups: this is ceil(N_PRB/P)
+  /// Frame type (0 FDD, 1 TDD)
+  lte_frame_type_t frame_type;
+  /// TDD subframe assignment (0-7) (default = 3) (254=RX only, 255=TX only)
+  uint8_t tdd_config;
+  /// TDD S-subframe configuration (0-9)
+  /// Cell ID
+  uint16_t Nid_cell;
   uint32_t subcarrier_spacing;
   /// 3/4 sampling
   uint8_t threequarter_fs;
@@ -101,14 +117,45 @@ typedef struct NR_DL_FRAME_PARMS {
   uint16_t slots_per_subframe;
   /// Number of samples in a subframe
   uint32_t samples_per_subframe;
+  /// 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 samples in a radio frame
   uint32_t samples_per_frame;
   /// Number of samples in a subframe without CP
   uint32_t samples_per_subframe_wCP;
   /// Number of samples in a radio frame without CP
   uint32_t samples_per_frame_wCP;
-
-    //SSB related params
+  /// Number of samples in a tti (same as subrame in LTE, depending on numerology in NR)
+  uint32_t samples_per_tti;
+  /// NR numerology index [0..5] as specified in 38.211 Section 4 (mu). 0=15khZ SCS, 1=30khZ, 2=60kHz, etc
+  uint8_t numerology_index;
+  /// NR number of ttis per subframe deduced from numerology (cf 38.211): 1, 2, 4, 8(not supported),16(not supported),32(not supported)
+  uint8_t ttis_per_subframe;
+  /// NR number of slots per tti . Assumption only 2 Slot per TTI is supported (Slot Config 1 in 38.211)
+  uint8_t slots_per_tti;
+//#endif
+  /// 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;
+  /// Cyclic Prefix for DL (0=Normal CP, 1=Extended CP)
+  lte_prefix_type_t Ncp;
+  /// SRS configuration from TS 38.331 RRC
+  SRS_NR srs_nr;
+
+  /// for NR TDD management
+  TDD_UL_DL_configCommon_t  *p_tdd_UL_DL_Configuration;
+
+  TDD_UL_DL_configCommon_t  *p_tdd_UL_DL_ConfigurationCommon2;
+
+  TDD_UL_DL_SlotConfig_t    *p_TDD_UL_DL_ConfigDedicated;
+
+  /// TDD configuration
+  uint16_t tdd_uplink_nr[MAX_NR_OF_SLOTS]; /* this is a bitmap of symbol of each slot given for 2 frames */
+
+   //SSB related params
   /// Start in Subcarrier index of the SSB block
   uint16_t ssb_start_subcarrier;
   /// SSB type
diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h
new file mode 100644
index 0000000000000000000000000000000000000000..390949072ae720c79541a063fea7a8a485f5c92f
--- /dev/null
+++ b/openair1/PHY/impl_defs_nr.h
@@ -0,0 +1,345 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/***********************************************************************
+*
+* FILENAME    :  impl_defs_nr.h
+*
+* MODULE      :
+*
+* DESCRIPTION :  NR Physical channel configuration and variable structure definitions
+*                This is an interface between ue physical layer and RRC message from network
+*                see TS 38.336 Radio Resource Control (RRC) protocol specification
+*
+************************************************************************/
+
+#ifndef PHY_IMPL_DEFS_NR_H
+#define PHY_IMPL_DEFS_NR_H
+
+#include "types.h"
+
+#ifdef DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+#define EXTERN
+#define INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+#else
+#define EXTERN  extern
+#undef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+#endif
+
+#ifdef PHY_DBG_DEV_TST
+  #define PHY_DBG_DEV_TST_PRINTF(...)      printf(__VA_ARGS__)
+#else
+  #define PHY_DBG_DEV_TST_PRINTF(...)
+#endif
+
+/* to set for UE capabilities */
+#define MAX_NR_OF_SRS_RESOURCE_SET         (1)
+#define MAX_NR_OF_SRS_RESOURCES_PER_SET    (1)
+
+#define NR_NUMBER_OF_SUBFRAMES_PER_FRAME   (10)
+#define MAX_NROFSRS_PORTS                  (4)
+
+/* TS 38.211 Table 4.3.2-1: Number of OFDM symbols per slot, slots per frame, and slots per subframe for normal cyclic prefix */
+#define MU_NUMBER                          (5)
+EXTERN const uint8_t N_slot_subframe[MU_NUMBER]
+#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+= { 1, 2, 4, 8, 16}
+#endif
+;
+
+/***********************************************************************
+*
+* FUNCTIONALITY    :  Time Division Duplex
+*
+* DESCRIPTION      :  interface for FDD/TDD configuration
+*
+************************************************************************/
+
+#define MAX_NR_OF_SLOTS                    (320)    /* maximum number of slots for tdd configuration which is periodic */
+
+#define NR_TDD_DOWNLINK_SLOT               (0x0000)
+#define NR_TDD_UPLINK_SLOT                 (0x3FFF) /* uplink bitmap for each symbol, there are 14 symbols per slots */
+#define NR_TDD_SET_ALL_SYMBOLS             (0x3FFF)
+
+#define FRAME_DURATION_MICRO_SEC           (10000)  /* frame duration in microsecond */
+
+typedef enum {
+  SLOT_DL = 0,
+  SLOT_UL = 1,
+} nr_slot_t;
+
+typedef enum {
+  ms0p5    = 500,                 /* duration is given in microsecond */
+  ms0p625  = 625,
+  ms1      = 1000,
+  ms1p25   = 1250,
+  ms2      = 2000,
+  ms2p5    = 2500,
+  ms5      = 5000,
+  ms10     = 10000,
+} dl_UL_TransmissionPeriodicity_t;
+
+typedef struct {
+  /// Reference SCS used to determine the time domain boundaries in the UL-DL pattern which must be common across all subcarrier specific
+  /// virtual carriers, i.e., independent of the actual subcarrier spacing using for data transmission.
+  /// Only the values 15 or 30 kHz  (<6GHz), 60 or 120 kHz (>6GHz) are applicable.
+  /// Corresponds to L1 parameter 'reference-SCS' (see 38.211, section FFS_Section)
+  /// \ subcarrier spacing
+  uint8_t referenceSubcarrierSpacing;
+  /// \ Periodicity of the DL-UL pattern. Corresponds to L1 parameter 'DL-UL-transmission-periodicity' (see 38.211, section FFS_Section)
+  dl_UL_TransmissionPeriodicity_t dl_UL_TransmissionPeriodicity;
+  /// \ Number of consecutive full DL slots at the beginning of each DL-UL pattern.
+  /// Corresponds to L1 parameter 'number-of-DL-slots' (see 38.211, Table 4.3.2-1)
+  uint8_t nrofDownlinkSlots;
+  /// \ Number of consecutive DL symbols in the beginning of the slot following the last full DL slot (as derived from nrofDownlinkSlots).
+  /// If the field is absent or released, there is no partial-downlink slot.
+  /// Corresponds to L1 parameter 'number-of-DL-symbols-common' (see 38.211, section FFS_Section).
+  uint8_t nrofDownlinkSymbols;
+  /// \ Number of consecutive full UL slots at the end of each DL-UL pattern.
+  /// Corresponds to L1 parameter 'number-of-UL-slots' (see 38.211, Table 4.3.2-1)
+  uint8_t nrofUplinkSlots;
+  /// \ Number of consecutive UL symbols in the end of the slot preceding the first full UL slot (as derived from nrofUplinkSlots).
+  /// If the field is absent or released, there is no partial-uplink slot.
+  /// Corresponds to L1 parameter 'number-of-UL-symbols-common' (see 38.211, section FFS_Section)
+  uint8_t nrofUplinkSymbols;
+  /// \ for setting a sequence
+  struct TDD_UL_DL_configCommon_t *p_next_TDD_UL_DL_configCommon_t;
+} TDD_UL_DL_configCommon_t;
+
+typedef struct {
+  /// \ Identifies a slot within a dl-UL-TransmissionPeriodicity (given in tdd-UL-DL-configurationCommon)
+  uint16_t slotIndex;
+  /// \ The direction (downlink or uplink) for the symbols in this slot. "allDownlink" indicates that all symbols in this slot are used
+  /// for downlink; "allUplink" indicates that all symbols in this slot are used for uplink; "explicit" indicates explicitly how many symbols
+  /// in the beginning and end of this slot are allocated to downlink and uplink, respectively.
+  /// Number of consecutive DL symbols in the beginning of the slot identified by slotIndex.
+  /// If the field is absent the UE assumes that there are no leading DL symbols.
+  /// Corresponds to L1 parameter 'number-of-DL-symbols-dedicated' (see 38.211, section FFS_Section)
+  uint16_t nrofDownlinkSymbols;
+  /// Number of consecutive UL symbols in the end of the slot identified by slotIndex.
+  /// If the field is absent the UE assumes that there are no trailing UL symbols.
+  /// Corresponds to L1 parameter 'number-of-UL-symbols-dedicated' (see 38.211, section FFS_Section)
+  uint16_t nrofUplinkSymbols;
+  /// \ for setting a sequence
+  struct TDD_UL_DL_SlotConfig_t *p_next_TDD_UL_DL_SlotConfig;
+} TDD_UL_DL_SlotConfig_t;
+
+/***********************************************************************
+*
+* FUNCTIONALITY    :  Sounding Reference Signal
+*
+* DESCRIPTION      :  interface description for managing uplink SRS signals from UE
+*                     SRS are generated by UE and transmit to network
+*                     depending on configuration
+*
+************************************************************************/
+
+EXTERN const int16_t SRS_antenna_port[MAX_NROFSRS_PORTS]
+#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+= { 1000, 1001, 1002, 1003 }
+#endif
+;
+
+typedef enum {
+  port1           = 1,
+  port2           = 2,
+  port4           = 4
+} nrof_Srs_Ports_t;
+
+typedef enum {
+  neitherHopping  = 0,
+  groupHopping    = 1,
+  sequenceHopping = 2
+} groupOrSequenceHopping_t;
+
+typedef enum {
+  aperiodic       = 0,
+  semi_persistent = 1,
+  periodic        = 2
+} resourceType_t;
+
+typedef enum {
+  sl1    = 0,
+  sl2    = 1,
+  sl4    = 2,
+  sl5    = 3,
+  sl8    = 4,
+  sl10   = 5,
+  sl16   = 6,
+  sl20   = 7,
+  sl32   = 8,
+  sl40   = 9,
+  sl64   = 10,
+  sl80   = 11,
+  sl160  = 12,
+  sl320  = 13,
+  sl640  = 14,
+  sl1280 = 15,
+  sl2560 = 16
+} SRS_Periodicity_t;
+
+#define NB_SRS_PERIOD         (17)
+
+const uint16_t srs_period[NB_SRS_PERIOD]
+#ifdef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+= { 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}
+#endif
+;
+
+/// SRS_Resource of SRS_Config information element from 38.331 RRC specifications
+typedef struct {
+  /// \brief srs resource identity.
+  uint8_t srs_ResourceId;
+  /// \brief number of srs ports.
+  nrof_Srs_Ports_t nrof_SrsPorts;
+  /// \brief index of prts port index.
+  uint8_t ptrs_PortIndex;
+  /// \brief srs transmission comb see parameter SRS-TransmissionComb 38.214 section &6.2.1.
+  uint8_t transmissionComb;
+  /// \brief comb offset.
+  uint8_t combOffset;
+  /// \brief cyclic shift configuration - see parameter SRS-CyclicShiftConfig 38.214 &6.2.1.
+  uint8_t cyclicShift;
+  /// \brief OFDM symbol location of the SRS resource within a slot.
+  // Corresponds to L1 parameter 'SRS-ResourceMapping' (see 38.214, section 6.2.1 and 38.211, section 6.4.1.4).
+  // startPosition (SRSSymbolStartPosition = 0..5; "0" refers to the last symbol, "1" refers to the second last symbol.
+  uint8_t resourceMapping_startPosition;
+  /// \brief number of OFDM symbols (N = 1, 2 or 4 per SRS resource).
+  uint8_t resourceMapping_nrofSymbols;
+  /// \brief RepetitionFactor (r = 1, 2 or 4).
+  uint8_t resourceMapping_repetitionFactor;
+  /// \brief Parameter(s) defining frequency domain position and configurable shift to align SRS allocation to 4 PRB grid.
+  // Corresponds to L1 parameter 'SRS-FreqDomainPosition' (see 38.214, section 6.2.1)
+  uint8_t  freqDomainPosition;    // INTEGER (0..67),
+  uint16_t freqDomainShift;       // INTEGER (0..268),
+  /// \brief Includes  parameters capturing SRS frequency hopping
+  // Corresponds to L1 parameter 'SRS-FreqHopping' (see 38.214, section 6.2.1)
+  uint8_t freqHopping_c_SRS;      // INTEGER (0..63),
+  uint8_t freqHopping_b_SRS;      // INTEGER (0..3),
+  uint8_t freqHopping_b_hop;      // INTEGER (0..3)
+  // Parameter(s) for configuring group or sequence hopping
+  // Corresponds to L1 parameter 'SRS-GroupSequenceHopping' see 38.211
+  groupOrSequenceHopping_t groupOrSequenceHopping;
+  /// \brief Time domain behavior of SRS resource configuration.
+  // Corresponds to L1 parameter 'SRS-ResourceConfigType' (see 38.214, section 6.2.1).
+  // For codebook based uplink transmission, the network configures SRS resources in the same resource set with the same
+  // time domain behavior on periodic, aperiodic and semi-persistent SRS
+  SRS_Periodicity_t SRS_Periodicity;
+  uint16_t          SRS_Offset;
+  /// \brief Sequence ID used to initialize psedo random group and sequence hopping.
+  // Corresponds to L1 parameter 'SRS-SequenceId' (see 38.214, section 6.2.1).
+  uint16_t sequenceId;            // BIT STRING (SIZE (10))
+  /// \brief Configuration of the spatial relation between a reference RS and the target SRS. Reference RS can be SSB/CSI-RS/SRS.
+  // Corresponds to L1 parameter 'SRS-SpatialRelationInfo' (see 38.214, section 6.2.1)
+  uint8_t spatialRelationInfo_ssb_Index;      // SSB-Index,
+  uint8_t spatialRelationInfo_csi_RS_Index;   // NZP-CSI-RS-ResourceId,
+  uint8_t spatialRelationInfo_srs_Id;         // SRS-ResourceId
+} SRS_Resource_t;
+
+typedef enum {
+  beamManagement     = 0,
+  codebook           = 1,
+  nonCodebook        = 2,
+  antennaSwitching   = 3,
+} SRS_resourceSet_usage_t;
+
+typedef enum {
+  sameAsFci2         = 0,
+  separateClosedLoop = 1
+} srs_PowerControlAdjustmentStates_t;
+
+typedef enum {
+  ssb_Index          = 0,
+  csi_RS_Index       = 1,
+} pathlossReferenceRS_t;
+
+// SRS_Config information element from 38.331 RRC specifications from 38.331 RRC specifications.
+typedef struct {
+  /// \brief The ID of this resource set. It is unique in the context of the BWP in which the parent SRS-Config is defined.
+  uint8_t srs_ResourceSetId;
+  /// \brief number of resources in the resource set
+  uint8_t number_srs_Resource;
+  /// \brief The IDs of the SRS-Resources used in this SRS-ResourceSet.
+  /// in fact this is an array of pointers to resource structures
+  SRS_Resource_t *p_srs_ResourceList[MAX_NR_OF_SRS_RESOURCES_PER_SET];
+  resourceType_t resourceType;
+  /// \brief The DCI "code point" upon which the UE shall transmit SRS according to this SRS resource set configuration.
+  // Corresponds to L1 parameter 'AperiodicSRS-ResourceTrigger' (see 38.214, section 6.1.1.2)
+  uint8_t aperiodicSRS_ResourceTrigger;		 // INTEGER (0..maxNrofSRS-TriggerStates-1) : [0:3]
+  /// \brief ID of CSI-RS resource associated with this SRS resource set. (see 38.214, section 6.1.1.2).
+  uint8_t NZP_CSI_RS_ResourceId;
+  /// \brief An offset in number of slots between the triggering DCI and the actual transmission of this SRS-ResourceSet.
+  // If the field is absent the UE applies no offset (value 0)
+  uint8_t aperiodic_slotOffset; // INTEGER (1..8)
+  /// \brief Indicates if the SRS resource set is used for beam management vs. used for either codebook based or non-codebook based transmission.
+  // Corresponds to L1 parameter 'SRS-SetUse' (see 38.214, section 6.2.1)
+  // FFS_CHECK: Isn't codebook/noncodebook already known from the ulTxConfig in the SRS-Config? If so, isn't the only distinction
+  // in the set between BeamManagement, AtennaSwitching and "Other”? Or what happens if SRS-Config=Codebook but a Set=NonCodebook?
+  SRS_resourceSet_usage_t usage;
+  /// \brief alpha value for SRS power control. Corresponds to L1 parameter 'alpha-srs' (see 38.213, section 7.3).
+  // When the field is absent the UE applies the value 1
+  uint8_t alpha;
+  /// \brief P0 value for SRS power control. The value is in dBm. Only even values (step size 2) are allowed.
+  // Corresponds to L1 parameter 'p0-srs' (see 38.213, section 7.3)
+  int8_t p0;          // INTEGER (-202..24)
+  /// \brief A reference signal (e.g. a CSI-RS config or a SSblock) to be used for SRS path loss estimation.
+  /// Corresponds to L1 parameter 'srs-pathlossReference-rs-config' (see 38.213, section 7.3)
+  pathlossReferenceRS_t pathlossReferenceRS_t;
+  uint8_t path_loss_SSB_Index;
+  uint8_t path_loss_NZP_CSI_RS_ResourceId;
+  /// \brief Indicates whether hsrs,c(i) = fc(i,1) or hsrs,c(i) = fc(i,2) (if twoPUSCH-PC-AdjustmentStates are configured)
+  /// or separate close loop is configured for SRS. This parameter is applicable only for Uls on which UE also transmits PUSCH.
+  /// If absent or release, the UE applies the value sameAs-Fci1
+  /// Corresponds to L1 parameter 'srs-pcadjustment-state-config' (see 38.213, section 7.3)
+  srs_PowerControlAdjustmentStates_t srs_PowerControlAdjustmentStates;
+} SRS_ResourceSet_t;
+
+typedef struct {
+  uint8_t active_srs_Resource_Set;  /* ue implementation specific */
+  uint8_t number_srs_Resource_Set;  /* ue implementation specific */
+  SRS_ResourceSet_t *p_SRS_ResourceSetList[MAX_NR_OF_SRS_RESOURCE_SET]; /* ue implementation specific */
+} SRS_NR;
+
+//#define RX_NB_TH_MAX 3
+//#define RX_NB_TH 3
+
+#define LTE_SLOTS_PER_SUBFRAME 2
+
+#define LTE_NUMBER_OF_SUBFRAMES_PER_FRAME 10
+#define LTE_SLOTS_PER_FRAME  20
+#define LTE_CE_FILTER_LENGTH 5
+#define LTE_CE_OFFSET LTE_CE_FILTER_LENGTH
+#define TX_RX_SWITCH_SYMBOL (NUMBER_OF_SYMBOLS_PER_FRAME>>1)
+#define PBCH_PDU_SIZE 3 //bytes
+
+#define PRACH_SYMBOL 3 //position of the UL PSS wrt 2nd slot of special subframe
+
+#define NUMBER_OF_FREQUENCY_GROUPS (lte_frame_parms->N_RB_DL)
+
+#define SSS_AMP 1148
+
+#define MAX_NUM_PHICH_GROUPS 56  //110 RBs Ng=2, p.60 36-212, Sec. 6.9
+
+#define MAX_MBSFN_AREA 8
+
+#undef EXTERN
+#undef INIT_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
+#endif /* PHY_IMPL_DEFS_NR_H */
diff --git a/openair1/PHY/phy_extern_nr_ue.h b/openair1/PHY/phy_extern_nr_ue.h
new file mode 100644
index 0000000000000000000000000000000000000000..a9694ea058d6278fb7b2564d5bc294ee958f5dd2
--- /dev/null
+++ b/openair1/PHY/phy_extern_nr_ue.h
@@ -0,0 +1,124 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef __PHY_EXTERN_UE__H__
+#define __PHY_EXTERN_UE__H__
+
+#include "PHY/defs_nr_UE.h"
+#include "common/ran_context.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/transport_extern.h"
+
+extern int number_of_cards;
+
+
+#ifndef OCP_FRAMEWORK
+extern PHY_VARS_NR_UE ***PHY_vars_UE_g;
+extern NR_DL_FRAME_PARMS *lte_frame_parms_g;
+#else
+#define MAX_UE 10
+#define MAX_eNB 20
+
+extern PHY_VARS_NR_UE * PHY_vars_UE_g[MAX_UE][MAX_NUM_CCs];
+#endif
+
+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];
+
+extern unsigned char NB_RU;
+
+#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 char ru_if_types[MAX_RU_IF_TYPES][20];
+
+extern int16_t unscrambling_lut[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];
+extern uint8_t max_turbo_iterations;
+#endif /*__PHY_EXTERN_H__ */
+
diff --git a/openair1/PHY/phy_vars_nr_ue.h b/openair1/PHY/phy_vars_nr_ue.h
new file mode 100644
index 0000000000000000000000000000000000000000..a179f509c61ad2169f1173b5fc862eb968585d19
--- /dev/null
+++ b/openair1/PHY/phy_vars_nr_ue.h
@@ -0,0 +1,150 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+#ifndef __PHY_VARS_NR_H__
+#define __PHY_VARS_NR_H__
+
+#include "PHY/types.h"
+#include "PHY/defs_nr_UE.h"
+#include "PHY/phy_vars_nr_ue.h"
+
+#include "common/ran_context.h"
+
+char* namepointer_chMag ;
+char fmageren_name2[512];
+char* namepointer_log2;
+
+
+#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/coding_vars.h"
+
+//PHY_VARS *PHY_vars;
+#ifndef OCP_FRAMEWORK
+PHY_VARS_NR_UE ***PHY_vars_UE_g;
+LTE_DL_FRAME_PARMS *lte_frame_parms_g;
+#else
+PHY_VARS_NR_UE * PHY_vars_UE_g[MAX_UE][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 "SIMULATION/ETH_TRANSPORT/vars.h"
+
+unsigned char NB_RU=0;
+
+#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_RAU_IF4p5","NGFI_RRU_IF5","NGFI_RRU_IF4p5",};
+char eNB_timing[2][20]={"synch_to_ext_device","synch_to_other"};
+char ru_if_types[MAX_RU_IF_TYPES][20]={"local RF","IF5 RRU","IF5 Mobipass","IF4p5 RRU","IF1pp RRU"};
+#endif
+
+/// lookup table for unscrambling in RX
+int16_t unscrambling_lut[65536*16] __attribute__((aligned(32)));
+/// lookup table for scrambling in TX
+uint8_t scrambling_lut[65536*16] __attribute__((aligned(32)));
+
+uint8_t max_turbo_iterations=4;
+#endif /*__PHY_VARS_H__ */
diff --git a/openair1/SCHED_NR/phy_frame_config_nr.h b/openair1/SCHED_NR/phy_frame_config_nr.h
new file mode 100644
index 0000000000000000000000000000000000000000..80cf23b02672e0800edc78d4e29d11045b62bb40
--- /dev/null
+++ b/openair1/SCHED_NR/phy_frame_config_nr.h
@@ -0,0 +1,96 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/***********************************************************************
+*
+* FILENAME    :  phy_frame_configuration_nr.h
+*
+* DESCRIPTION :  functions related to FDD/TDD configuration  for NR
+*                see TS 38.213 11.1 Slot configuration
+*                and TS 38.331 for RRC configuration
+*
+************************************************************************/
+
+#ifndef PHY_FRAME_CONFIG_NR_H
+#define PHY_FRAME_CONFIG_NR_H
+
+/************** DEFINE ********************************************/
+
+#define TDD_CONFIG_NB_FRAMES           (2)
+
+/*************** FUNCTIONS *****************************************/
+
+/** \brief This function processes tdd dedicated configuration for nr
+ *  @param frame_parms NR DL Frame parameters
+ *  @param dl_UL_TransmissionPeriodicity periodicity
+ *  @param nrofDownlinkSlots number of downlink slots
+ *  @param nrofDownlinkSymbols number of downlink symbols
+ *  @param nrofUplinkSlots number of uplink slots
+ *  @param nrofUplinkSymbols number of uplink symbols
+    @returns 0 if tdd dedicated configuration has been properly set or -1 on error with message */
+
+int set_tdd_config_nr(NR_DL_FRAME_PARMS *frame_parms, int dl_UL_TransmissionPeriodicity,
+                       int nrofDownlinkSlots, int nrofDownlinkSymbols,
+                       int nrofUplinkSlots,   int nrofUplinkSymbols);
+
+/** \brief This function adds a slot configuration to current dedicated configuration for nr
+ *  @param frame_parms NR DL Frame parameters
+ *  @param slotIndex
+ *  @param nrofDownlinkSymbols
+ *  @param nrofUplinkSymbols
+    @returns none */
+
+void add_tdd_dedicated_configuration_nr(NR_DL_FRAME_PARMS *frame_parms, int slotIndex,
+                                        int nrofDownlinkSymbols, int nrofUplinkSymbols);
+
+/** \brief This function processes tdd dedicated configuration for nr
+ *  @param frame_parms nr frame parameters
+ *  @param dl_UL_TransmissionPeriodicity periodicity
+ *  @param nrofDownlinkSlots number of downlink slots
+ *  @param nrofDownlinkSymbols number of downlink symbols
+ *  @param nrofUplinkSlots number of uplink slots
+ *  @param nrofUplinkSymbols number of uplink symbols
+    @returns 0 if tdd dedicated configuration has been properly set or -1 on error with message */
+
+int set_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
+
+/** \brief This function checks nr slot direction : downlink or uplink
+ *  @param frame_parms NR DL Frame parameters
+ *  @param nr_frame : frame number
+ *  @param nr_tti   : slot number
+    @returns nr_slot_t : downlink or uplink */
+
+nr_slot_t slot_select_nr(NR_DL_FRAME_PARMS *frame_parms, int nr_frame, int nr_tti);
+
+/** \brief This function frees tdd configuration for nr
+ *  @param frame_parms NR DL Frame parameters
+    @returns none */
+
+void free_tdd_configuration_nr(NR_DL_FRAME_PARMS *frame_parms);
+
+/** \brief This function frees tdd dedicated configuration for nr
+ *  @param frame_parms NR DL Frame parameters
+    @returns none */
+
+void free_tdd_configuration_dedicated_nr(NR_DL_FRAME_PARMS *frame_parms);
+
+#endif  /* PHY_FRAME_CONFIG_NR_H */
+
diff --git a/targets/ARCH/COMMON/common_lib.h b/targets/ARCH/COMMON/common_lib.h
index 7460c4849bfa383048a100ef4184b562d5856f0e..e6f0d5d0f13e6d41b8ada32d42a69392259af807 100644
--- a/targets/ARCH/COMMON/common_lib.h
+++ b/targets/ARCH/COMMON/common_lib.h
@@ -211,6 +211,14 @@ typedef struct {
   int iq_rxrescale;
   //! Configuration file for LMS7002M
   char *configFilename;
+  //! remote IP/MAC addr for Ethernet interface
+  char *remote_addr;
+  //! remote port number for Ethernet interface
+  unsigned int remote_port;
+  //! local IP/MAC addr for Ethernet interface (eNB/BBU, UE)
+  char *my_addr;
+  //! local port number for Ethernet interface (eNB/BBU, UE)
+  unsigned int my_port;
 #if defined(USRP_REC_PLAY)
   unsigned short sf_mode;           // 1=record, 2=replay
   char           sf_filename[1024]; // subframes file path
diff --git a/targets/COMMON/threads_t.h b/targets/COMMON/threads_t.h
index ddc060e8c331328b9b8a3a564940df4fba896e80..99fb0d8cf449d225c0d771bbde630fb460cfe508 100644
--- a/targets/COMMON/threads_t.h
+++ b/targets/COMMON/threads_t.h
@@ -9,6 +9,12 @@ typedef struct threads_s {
     int slot1_proc_one;
     int slot1_proc_two;
     int slot1_proc_three;
+    int dlsch_td_one;
+	int dlsch_td_two;
+	int dlsch_td_three;
+	int dlsch_td1_one;
+	int dlsch_td1_two;
+	int dlsch_td1_three;
 } threads_t;
 
 #endif /* _THREADS_T_H_ */
diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c
index e69de29bb2d1d6434b8b29ae775ad8c2e48c5391..38b80f28480cb1a3027b261a7b07d4e838169084 100644
--- a/targets/RT/USER/nr-ue.c
+++ b/targets/RT/USER/nr-ue.c
@@ -0,0 +1,1077 @@
+/*
+ * 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-ue.c
+ * \brief threads and support functions for real-time LTE UE target
+ * \author R. Knopp, F. Kaltenberger, Navid Nikaein
+ * \date 2015
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
+ * \note
+ * \warning
+ */
+#include "nr-uesoftmodem.h"
+
+#include "rt_wrapper.h"
+
+#include "LAYER2/MAC/mac.h"
+#include "RRC/LTE/rrc_extern.h"
+#include "PHY_INTERFACE/phy_interface_extern.h"
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "PHY/phy_extern_nr_ue.h"
+#include "LAYER2/MAC/mac_extern.h"
+#include "LAYER2/MAC/mac_proto.h"
+
+#include "SCHED_NR/extern.h"
+//#ifndef NO_RAT_NR
+#include "SCHED_NR/phy_frame_config_nr.h"
+//#endif
+
+#include "../../../openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
+
+#include "UTIL/LOG/log_extern.h"
+#include "UTIL/OTG/otg_tx.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "UTIL/MATH/oml.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+
+#include "T.h"
+
+extern double cpuf;
+
+#define FRAME_PERIOD    100000000ULL
+#define DAQ_PERIOD      66667ULL
+#define FIFO_PRIORITY   40
+
+typedef enum {
+    pss=0,
+    pbch=1,
+    si=2
+} sync_mode_t;
+
+void init_UE_threads(PHY_VARS_NR_UE *UE);
+void *UE_thread(void *arg);
+void init_UE(int nb_inst);
+
+int32_t **rxdata;
+int32_t **txdata;
+
+#define KHz (1000UL)
+#define MHz (1000*KHz)
+#define SAIF_ENABLED
+
+#ifdef SAIF_ENABLED
+uint64_t	g_ue_rx_thread_busy	= 0;
+#endif
+
+typedef struct eutra_band_s {
+    int16_t band;
+    uint32_t ul_min;
+    uint32_t ul_max;
+    uint32_t dl_min;
+    uint32_t dl_max;
+    lte_frame_type_t frame_type;
+} eutra_band_t;
+
+typedef struct band_info_s {
+    int nbands;
+    eutra_band_t band_info[100];
+} band_info_t;
+
+band_info_t bands_to_scan;
+
+static const eutra_band_t eutra_bands[] = {
+    { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
+    { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
+    { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
+    { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
+    { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
+    { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
+    { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
+    { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
+    { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
+    {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
+    {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
+    {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
+    {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
+    {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
+    {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
+    {20,  832    * MHz,  862    * MHz,  791    * MHz,  821    * MHz, FDD},
+    {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
+    {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
+    {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
+    {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
+    {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
+    {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
+    {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
+    {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
+    {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
+    {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
+    {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
+    {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
+    {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
+};
+
+void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name) {
+
+#ifdef DEADLINE_SCHEDULER
+    if (sched_runtime!=0) {
+        struct sched_attr attr= {0};
+        attr.size = sizeof(attr);
+        attr.sched_policy = SCHED_DEADLINE;
+        attr.sched_runtime  = sched_runtime;
+        attr.sched_deadline = sched_deadline;
+        attr.sched_period   = 0;
+        AssertFatal(sched_setattr(0, &attr, 0) == 0,
+                    "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
+        LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
+              name, (unsigned long)gettid(), sched_getcpu());
+    }
+
+#else
+    if (CPU_COUNT(cpuset) > 0)
+        AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
+    struct sched_param sp;
+    sp.sched_priority = sched_fifo;
+    AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
+                "Can't set thread priority, Are you root?\n");
+    /* Check the actual affinity mask assigned to the thread */
+    cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
+    if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) {
+      char txt[512]={0};
+      for (int j = 0; j < CPU_SETSIZE; j++)
+        if (CPU_ISSET(j, cset))
+	  sprintf(txt+strlen(txt), " %d ", j);
+      printf("CPU Affinity of thread %s is %s\n", name, txt);
+    }
+    CPU_FREE(cset);
+#endif
+
+    // Lock memory from swapping. This is a process wide call (not constraint to this thread).
+    mlockall(MCL_CURRENT | MCL_FUTURE);
+    pthread_setname_np( pthread_self(), name );
+
+    // LTS: this sync stuff should be wrong
+    printf("waiting for sync (%s)\n",name);
+    pthread_mutex_lock(&sync_mutex);
+    printf("Locked sync_mutex, waiting (%s)\n",name);
+    while (sync_var<0)
+        pthread_cond_wait(&sync_cond, &sync_mutex);
+    pthread_mutex_unlock(&sync_mutex);
+    printf("started %s as PID: %ld\n",name, gettid());
+}
+
+void init_UE(int nb_inst)
+{
+  int inst;
+  for (inst=0; inst < nb_inst; inst++) {
+    //    UE->rfdevice.type      = NONE_DEV;
+    PHY_VARS_NR_UE *UE = PHY_vars_UE_g[inst][0];
+    AssertFatal(0 == pthread_create(&UE->proc.pthread_ue,
+                                    &UE->proc.attr_ue,
+                                    UE_thread,
+                                    (void*)UE), "");
+  }
+
+  printf("UE threads created by %ld\n", gettid());
+#if 0
+#if defined(ENABLE_USE_MME)
+  extern volatile int start_UE;
+  while (start_UE == 0) {
+    sleep(1);
+  }
+#endif
+#endif
+}
+
+/*!
+ * \brief This is the UE synchronize thread.
+ * It performs band scanning and synchonization.
+ * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+static void *UE_thread_synch(void *arg) {
+    static int __thread UE_thread_synch_retval;
+    int i, hw_slot_offset;
+    PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE*) arg;
+    int current_band = 0;
+    int current_offset = 0;
+    sync_mode_t sync_mode = pbch;
+    int CC_id = UE->CC_id;
+    int freq_offset=0;
+    char threadname[128];
+
+    cpu_set_t cpuset;
+    CPU_ZERO(&cpuset);
+    if ( threads.iq != -1 )
+        CPU_SET(threads.iq, &cpuset);
+    // this thread priority must be lower that the main acquisition thread
+    sprintf(threadname, "sync UE %d\n", UE->Mod_id);
+    init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname);
+
+    UE->is_synchronized = 0;
+
+    if (UE->UE_scan == 0) {
+        int ind;
+        for ( ind=0;
+                ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]);
+                ind++) {
+            current_band = eutra_bands[ind].band;
+            LOG_D(PHY, "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
+            if ( eutra_bands[ind].dl_min <= downlink_frequency[0][0] && eutra_bands[ind].dl_max >= downlink_frequency[0][0] ) {
+                for (i=0; i<4; i++)
+                    uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
+                break;
+            }
+        }
+        AssertFatal( ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]), "Can't find EUTRA band for frequency");
+
+        LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n",
+               downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],
+               oai_exit, openair0_cfg[0].rx_num_channels);
+
+        for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
+            openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
+                downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+            openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
+            if (uplink_frequency_offset[CC_id][i] != 0) //
+                openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
+            else //FDD
+                openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
+        }
+        sync_mode = pbch;
+
+    } else {
+        current_band=0;
+        for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+            downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min;
+            uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] =
+                bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min;
+            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
+            openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
+                downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+            openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
+        }
+    }
+
+    //    AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
+
+    while (oai_exit==0) {
+        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+        while (UE->proc.instance_cnt_synch < 0)
+            // the thread waits here most of the time
+            pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
+        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+
+        switch (sync_mode) {
+        case pss:
+            LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
+            lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
+            current_offset += 20000000; // increase by 20 MHz
+
+            if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
+                current_band++;
+                current_offset=0;
+            }
+
+            if (current_band==bands_to_scan.nbands) {
+                current_band=0;
+                oai_exit=1;
+            }
+
+            for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+                downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
+                uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
+
+                openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
+                openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+                openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
+                if (UE->UE_scan_carrier) {
+                    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
+                }
+
+            }
+
+            break;
+
+        case pbch:
+
+#if DISABLE_LOG_X
+            printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
+#else
+            LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
+#endif
+            if (initial_sync( UE, UE->mode ) == 0) {
+
+                hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
+                printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
+                       hw_slot_offset,
+                       freq_offset,
+                       UE->rx_total_gain_dB,
+                       downlink_frequency[0][0]+freq_offset,
+                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
+                       UE->UE_scan_carrier );
+
+
+                    // rerun with new cell parameters and frequency-offset
+                    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+                        openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
+			if (UE->UE_scan_carrier == 1) {
+                        if (freq_offset >= 0)
+                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
+                        else
+                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
+                        openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
+                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
+                        downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
+                        freq_offset=0;
+                    }
+	  }
+
+                    // reconfigure for potentially different bandwidth
+                    switch(UE->frame_parms.N_RB_DL) {
+                    case 6:
+                        openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
+                        openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
+                        openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
+                        //            openair0_cfg[0].rx_gain[0] -= 12;
+                        break;
+                    case 25:
+                        openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
+                        openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
+                        openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
+                        //            openair0_cfg[0].rx_gain[0] -= 6;
+                        break;
+                    case 50:
+                        openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
+                        openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
+                        openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
+                        //            openair0_cfg[0].rx_gain[0] -= 3;
+                        break;
+                    case 100:
+                        openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
+                        openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
+                        openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
+                        //            openair0_cfg[0].rx_gain[0] -= 0;
+                        break;
+                    }
+
+                    UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
+                    //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
+                    //UE->rfdevice.trx_stop_func(&UE->rfdevice);
+                    // sleep(1);
+                    //init_frame_parms(&UE->frame_parms,1);
+                    /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
+                        LOG_E(HW,"Could not start the device\n");
+                        oai_exit=1;
+                    }*/
+
+		if (UE->UE_scan_carrier == 1) {
+
+		  UE->UE_scan_carrier = 0;
+                } else {
+                    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+                    UE->is_synchronized = 1;
+                    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+
+                    if( UE->mode == rx_dump_frame ) {
+                        FILE *fd;
+                        if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present
+                            if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
+                                fwrite((void*)&UE->common_vars.rxdata[0][0],
+                                       sizeof(int32_t),
+                                       10*UE->frame_parms.samples_per_subframe,
+                                       fd);
+                                LOG_I(PHY,"Dummping Frame ... bye bye \n");
+                                fclose(fd);
+                                exit(0);
+                            } else {
+                                LOG_E(PHY,"Cannot open file for writing\n");
+                                exit(0);
+                            }
+                        } else {
+                            AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+                            UE->is_synchronized = 0;
+                            AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+
+                        }
+                    }
+                }
+            } else {
+                // initial sync failed
+                // calculate new offset and try again
+                if (UE->UE_scan_carrier == 1) {
+                    if (freq_offset >= 0)
+                        freq_offset += 100;
+                    freq_offset *= -1;
+
+                    if (abs(freq_offset) > 7500) {
+                        LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
+                        FILE *fd;
+                        if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
+                            fwrite((void*)&UE->common_vars.rxdata[0][0],
+                                   sizeof(int32_t),
+                                   10*UE->frame_parms.samples_per_subframe,
+                                   fd);
+                            LOG_I(PHY,"Dummping Frame ... bye bye \n");
+                            fclose(fd);
+                            exit(0);
+                        }
+                        //mac_xface->macphy_exit("No cell synchronization found, abandoning"); new mac
+                        return &UE_thread_synch_retval; // not reached
+                    }
+                }
+#if DISABLE_LOG_X
+                printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
+                       freq_offset,
+                       UE->rx_total_gain_dB,
+                       downlink_frequency[0][0]+freq_offset,
+                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
+#else
+                LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
+                       freq_offset,
+                       UE->rx_total_gain_dB,
+                       downlink_frequency[0][0]+freq_offset,
+                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
+#endif
+
+                for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
+                    openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
+                    openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
+                    openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
+                    if (UE->UE_scan_carrier==1)
+                        openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
+                }
+                UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
+            }// initial_sync=0
+            break;
+        case si:
+        default:
+            break;
+        }
+
+        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+        // indicate readiness
+        UE->proc.instance_cnt_synch--;
+        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
+    }  // while !oai_exit
+
+    return &UE_thread_synch_retval;
+}
+
+/*!
+ * \brief This is the UE thread for RX subframe n and TX subframe n+4.
+ * This thread performs the phy_procedures_UE_RX() on every received slot.
+ * then, if TX is enabled it performs TX for n+4.
+ * \param arg is a pointer to a \ref PHY_VARS_NR_UE structure.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+
+static void *UE_thread_rxn_txnp4(void *arg) {
+    static __thread int UE_thread_rxtx_retval;
+    struct nr_rxtx_thread_data *rtd = arg;
+    UE_nr_rxtx_proc_t *proc = rtd->proc;
+    PHY_VARS_NR_UE    *UE   = rtd->UE;
+    int ret;
+
+    //proc->counter_decoder = 0;
+    proc->instance_cnt_rxtx=-1;
+    proc->subframe_rx=proc->sub_frame_start;
+
+	proc->dci_err_cnt=0;
+    char threadname[256];
+    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
+    cpu_set_t cpuset;
+    CPU_ZERO(&cpuset);
+    char timing_proc_name[256];
+    sprintf(timing_proc_name,"Delay to process sub-frame proc %d",proc->sub_frame_start);
+
+    if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 )
+        CPU_SET(threads.one, &cpuset);
+    if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 )
+        CPU_SET(threads.two, &cpuset);
+    if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 )
+        CPU_SET(threads.three, &cpuset);
+            //CPU_SET(threads.three, &cpuset);
+    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
+                threadname);
+
+    while (!oai_exit) {
+        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
+          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
+          exit_fun("nothing to add");
+        }
+        while (proc->instance_cnt_rxtx < 0) {
+          // most of the time, the thread is waiting here
+          pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
+        }
+        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
+          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
+          exit_fun("nothing to add");
+        }
+
+//        initRefTimes(t2);
+        initRefTimes(t3);
+        pickTime(current);
+//        updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");
+
+#ifndef NO_RAT_NR
+        // Process Rx data for one sub-frame
+        nr_slot_t nr_slot ; //= slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx);
+
+        if (nr_slot == NR_TDD_DOWNLINK_SLOT) {
+#else
+        // Process Rx data for one sub-frame
+        lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
+        if ((sf_type == SF_DL) ||
+                (UE->frame_parms.frame_type == FDD) ||
+                (sf_type == SF_S)) {
+
+            if (UE->frame_parms.frame_type == TDD) {
+                LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
+                      threadname,
+                      UE->frame_parms.tdd_config,
+                      (sf_type==SF_DL? "SF_DL" :
+                       (sf_type==SF_UL? "SF_UL" :
+                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+            } else {
+                LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
+                      threadname,
+                      (UE->frame_parms.frame_type==FDD? "FDD":
+                       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
+                      (sf_type==SF_DL? "SF_DL" :
+                       (sf_type==SF_UL? "SF_UL" :
+                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
+            }
+#endif
+#ifdef UE_SLOT_PARALLELISATION
+            phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
+#else
+            phy_procedures_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
+#endif
+        }
+
+#if UE_TIMING_TRACE
+        start_meas(&UE->generic_stat);
+#endif
+        if (UE->mac_enabled==1) {
+
+#ifdef NEW_MAC
+          ret = mac_xface->ue_scheduler(UE->Mod_id,
+                                          proc->frame_rx,
+                                          proc->subframe_rx,
+                                          proc->nr_tti_rx,
+                                          proc->frame_tx,
+                                          proc->subframe_tx,
+                                          proc->nr_tti_tx%(UE->frame_parms.ttis_per_subframe),
+#ifndef NO_RAT_NR
+                                          slot_select_nr(&UE->frame_parms, proc->frame_tx, proc->nr_tti_tx),
+#else
+                                          subframe_select(&UE->frame_parms,proc->subframe_tx),
+#endif
+                                          0,
+                                          0/*FIXME CC_id*/);
+#endif
+
+/*#else
+            ret = mac_xface->ue_scheduler(UE->Mod_id,
+                                          proc->frame_rx,
+                                          proc->subframe_rx,
+                                          proc->frame_tx,
+                                          proc->subframe_tx,
+                                          subframe_select(&UE->frame_parms,proc->subframe_tx),
+                                          0,  */
+//                                          0/*FIXME CC_id*/);
+//#endif
+            if ( ret != CONNECTION_OK) {
+                char *txt;
+                switch (ret) {
+                case CONNECTION_LOST:
+                    txt="RRC Connection lost, returning to PRACH";
+                    break;
+                case PHY_RESYNCH:
+                    txt="RRC Connection lost, trying to resynch";
+                    break;
+                case RESYNCH:
+                    txt="return to PRACH and perform a contention-free access";
+                    break;
+                default:
+                    txt="UNKNOWN RETURN CODE";
+                };
+                LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
+                       UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
+            }
+        }
+#if UE_TIMING_TRACE
+        stop_meas(&UE->generic_stat);
+#endif
+
+        // Prepare the future Tx data
+#if 1
+        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
+                (UE->frame_parms.frame_type == FDD) )
+            if (UE->mode != loop_through_memory)
+                phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
+#endif
+
+        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
+                (UE->frame_parms.frame_type == TDD))
+            if (UE->mode != loop_through_memory)
+                phy_procedures_UE_S_TX(UE,0,0,no_relay);
+        updateTimes(current, &t3, 10000, timing_proc_name);
+
+        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
+          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
+          exit_fun("noting to add");
+        }
+        proc->instance_cnt_rxtx--;
+        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
+          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
+          exit_fun("noting to add");
+        }
+    }
+
+// thread finished
+    free(arg);
+    return &UE_thread_rxtx_retval;
+}
+
+/*!
+ * \brief This is the main UE thread.
+ * This thread controls the other three UE threads:
+ * - UE_thread_rxn_txnp4 (even subframes)
+ * - UE_thread_rxn_txnp4 (odd subframes)
+ * - UE_thread_synch
+ * \param arg unused
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+
+void *UE_thread(void *arg) {
+
+    PHY_VARS_NR_UE *UE = (PHY_VARS_NR_UE *) arg;
+    //  int tx_enabled = 0;
+    int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
+    openair0_timestamp timestamp,timestamp1;
+    void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
+    int start_rx_stream = 0;
+    int i;
+    char threadname[128];
+    int th_id;
+    UE->proc.proc_rxtx[0].counter_decoder = 0;
+    UE->proc.proc_rxtx[1].counter_decoder = 0;
+    UE->proc.proc_rxtx[2].counter_decoder = 0;
+
+    static uint8_t thread_idx = 0;
+
+    cpu_set_t cpuset;
+    CPU_ZERO(&cpuset);
+    if ( threads.iq != -1 )
+        CPU_SET(threads.iq, &cpuset);
+    init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
+                "UHD Threads");
+    if (oaisim_flag == 0)
+        AssertFatal(0== openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]), "");
+    UE->rfdevice.host_type = RAU_HOST;
+    sprintf(threadname, "Main UE %d", UE->Mod_id);
+    pthread_setname_np(pthread_self(), threadname);
+    init_UE_threads(UE);
+
+#ifdef NAS_UE
+    MessageDef *message_p;
+    message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
+    itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
+#endif
+
+    int tti_nr=-1;
+    //int cumulated_shift=0;
+    AssertFatal(UE->rfdevice.trx_start_func(&UE->rfdevice) == 0, "Could not start the device\n");
+    while (!oai_exit) {
+        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+        int instance_cnt_synch = UE->proc.instance_cnt_synch;
+        int is_synchronized    = UE->is_synchronized;
+        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+
+        if (is_synchronized == 0) {
+            if (instance_cnt_synch < 0) {  // we can invoke the synch
+                // grab 10 ms of signal and wakeup synch thread
+                for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+                    rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
+
+                if (UE->mode != loop_through_memory)
+                    AssertFatal( UE->frame_parms.samples_per_subframe*10 ==
+                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
+                                                            &timestamp,
+                                                            rxp,
+                                                            UE->frame_parms.samples_per_subframe*10,
+                                                            UE->frame_parms.nb_antennas_rx), "");
+		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
+                instance_cnt_synch = ++UE->proc.instance_cnt_synch;
+                if (instance_cnt_synch == 0) {
+                    AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
+                } else {
+                    LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
+                    exit_fun("nothing to add");
+                }
+		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
+            } else {
+#if OAISIM
+              (void)dummy_rx; /* avoid gcc warnings */
+              usleep(500);
+#else
+                // grab 10 ms of signal into dummy buffer
+                if (UE->mode != loop_through_memory) {
+                    for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+                        rxp[i] = (void*)&dummy_rx[i][0];
+                    for (int sf=0; sf<10; sf++)
+                        //	    printf("Reading dummy sf %d\n",sf);
+                          UE->rfdevice.trx_read_func(&UE->rfdevice,
+                                              &timestamp,
+                                              rxp,
+                                              UE->frame_parms.samples_per_subframe,
+                                              UE->frame_parms.nb_antennas_rx);
+                }
+#endif
+            }
+
+        } // UE->is_synchronized==0
+        else {
+            if (start_rx_stream==0) {
+                start_rx_stream=1;
+                if (UE->mode != loop_through_memory) {
+                    if (UE->no_timing_correction==0) {
+                        LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
+                        AssertFatal(UE->rx_offset ==
+                                    UE->rfdevice.trx_read_func(&UE->rfdevice,
+                                                               &timestamp,
+                                                               (void**)UE->common_vars.rxdata,
+                                                               UE->rx_offset,
+                                                               UE->frame_parms.nb_antennas_rx),"");
+                    }
+                    UE->rx_offset=0;
+                    UE->time_sync_cell=0;
+                    //UE->proc.proc_rxtx[0].frame_rx++;
+                    //UE->proc.proc_rxtx[1].frame_rx++;
+                    for (th_id=0; th_id < RX_NB_TH; th_id++) {
+                        UE->proc.proc_rxtx[th_id].frame_rx++;
+                    }
+
+                    // read in first symbol
+                    AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
+                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
+                                                            &timestamp,
+                                                            (void**)UE->common_vars.rxdata,
+                                                            UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
+                                                            UE->frame_parms.nb_antennas_rx),"");
+                    slot_fep_pbch(UE,0, 0, 0, 0, 0);
+                } //UE->mode != loop_through_memory
+                else
+                    rt_sleep_ns(1000*1000);
+
+            } else {
+                tti_nr++;
+                tti_nr%=10*UE->frame_parms.ttis_per_subframe;
+                UE_nr_rxtx_proc_t *proc = &UE->proc.proc_rxtx[thread_idx];
+                // update thread index for received subframe
+                UE->current_thread_id[tti_nr] = thread_idx;
+
+                LOG_D(PHY,"Process TTI %d thread Idx %d \n", tti_nr, UE->current_thread_id[tti_nr]);
+
+                thread_idx++;
+                if(thread_idx>=RX_NB_TH)
+                    thread_idx = 0;
+
+
+                if (UE->mode != loop_through_memory) {
+                    for (i=0; i<UE->frame_parms.nb_antennas_rx; i++)
+                        rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
+                                 UE->frame_parms.nb_prefix_samples0+
+                                 tti_nr*UE->frame_parms.samples_per_tti];
+                    for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
+                        txp[i] = (void*)&UE->common_vars.txdata[i][((tti_nr+2)%10*UE->frame_parms.ttis_per_subframe)*UE->frame_parms.samples_per_tti];
+
+                    int readBlockSize, writeBlockSize;
+                    if (tti_nr<(10*UE->frame_parms.ttis_per_subframe-1)) {
+                        readBlockSize=UE->frame_parms.samples_per_tti;
+                        writeBlockSize=UE->frame_parms.samples_per_tti;
+                    } else {
+                        // set TO compensation to zero
+                        UE->rx_offset_diff = 0;
+                        // compute TO compensation that should be applied for this frame
+                        if ( UE->rx_offset < 5*UE->frame_parms.samples_per_subframe  &&
+                                UE->rx_offset > 0 )
+                            UE->rx_offset_diff = -1 ;
+                        if ( UE->rx_offset > 5*UE->frame_parms.samples_per_subframe &&
+                                UE->rx_offset < 10*UE->frame_parms.samples_per_tti )
+                            UE->rx_offset_diff = 1;
+
+                        LOG_D(PHY,"AbsSubframe %d.%d TTI SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,tti_nr,UE->rx_offset_diff,UE->rx_offset);
+                        readBlockSize=UE->frame_parms.samples_per_tti -
+                                      UE->frame_parms.ofdm_symbol_size -
+                                      UE->frame_parms.nb_prefix_samples0 -
+                                      UE->rx_offset_diff;
+                        writeBlockSize=UE->frame_parms.samples_per_tti -
+                                       UE->rx_offset_diff;
+                    }
+
+                    AssertFatal(readBlockSize ==
+                                UE->rfdevice.trx_read_func(&UE->rfdevice,
+                                                           &timestamp,
+                                                           rxp,
+                                                           readBlockSize,
+                                                           UE->frame_parms.nb_antennas_rx),"");
+                    AssertFatal( writeBlockSize ==
+                                 UE->rfdevice.trx_write_func(&UE->rfdevice,
+                                         timestamp+
+                                         (2*UE->frame_parms.samples_per_tti) -
+                                         UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
+                                         openair0_cfg[0].tx_sample_advance,
+                                         txp,
+                                         writeBlockSize,
+                                         UE->frame_parms.nb_antennas_tx,
+                                         1),"");
+                    if( tti_nr==(10*UE->frame_parms.ttis_per_subframe-1)) {
+                        // read in first symbol of next frame and adjust for timing drift
+                        int first_symbols=writeBlockSize-readBlockSize;
+                        if ( first_symbols > 0 )
+                            AssertFatal(first_symbols ==
+                                        UE->rfdevice.trx_read_func(&UE->rfdevice,
+                                                                   &timestamp1,
+                                                                   (void**)UE->common_vars.rxdata,
+                                                                   first_symbols,
+                                                                   UE->frame_parms.nb_antennas_rx),"");
+                        if ( first_symbols <0 )
+                            LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
+                    }
+                    pickTime(gotIQs);
+                    // operate on thread sf mod 2
+                    AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,"");
+                    if(tti_nr == 0) {
+                        //UE->proc.proc_rxtx[0].frame_rx++;
+                        //UE->proc.proc_rxtx[1].frame_rx++;
+                        for (th_id=0; th_id < RX_NB_TH; th_id++) {
+                            UE->proc.proc_rxtx[th_id].frame_rx++;
+                        }
+#ifdef SAIF_ENABLED
+						if (!(proc->frame_rx%4000))
+						{
+							printf("frame_rx=%d rx_thread_busy=%ld - rate %8.3f\n",
+								proc->frame_rx, g_ue_rx_thread_busy,
+								(float)g_ue_rx_thread_busy/(proc->frame_rx*10+1)*100.0);
+							fflush(stdout);
+						}
+#endif
+                    }
+                    //UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs);
+                    //UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs);
+                    for (th_id=0; th_id < RX_NB_TH; th_id++) {
+                        UE->proc.proc_rxtx[th_id].gotIQs=readTime(gotIQs);
+                    }
+                    proc->nr_tti_rx=tti_nr;
+                    proc->nr_tti_tx=(tti_nr+4)%(10*UE->frame_parms.ttis_per_subframe);
+                    proc->subframe_rx=tti_nr>>((uint8_t)(log2 (UE->frame_parms.ttis_per_subframe)));
+                    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
+                    proc->subframe_tx=(proc->nr_tti_tx)>>((uint8_t)(log2 (UE->frame_parms.ttis_per_subframe)));
+                    proc->timestamp_tx = timestamp+
+                                         (4*UE->frame_parms.samples_per_tti)-
+                                         UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
+
+                    proc->instance_cnt_rxtx++;
+                    LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx);
+                    if (proc->instance_cnt_rxtx == 0) {
+                      if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
+                        LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
+                        exit_fun("nothing to add");
+                      }
+                    } else {
+#ifdef SAIF_ENABLED
+						g_ue_rx_thread_busy++;
+#endif
+                      LOG_E( PHY, "[SCHED][UE %d] !! UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx);
+                      if (proc->instance_cnt_rxtx > 4)
+                      {
+                        char exit_fun_string[256];
+                        sprintf(exit_fun_string,"[SCHED][UE %d] !!! UE instance_cnt_rxtx > 2 (IC %d) (Proc %d)!!",
+                        			UE->Mod_id, proc->instance_cnt_rxtx,
+                        			UE->current_thread_id[tti_nr]);
+          				printf("%s\n",exit_fun_string);
+          				fflush(stdout);
+          				sleep(1);
+                        exit_fun(exit_fun_string);
+                      }
+                    }
+
+                    AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,"");
+                    AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");
+//                    initRefTimes(t1);
+//                    initStaticTime(lastTime);
+//                    updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)");
+//                    pickStaticTime(lastTime);
+
+                } else {
+                    printf("Processing subframe %d",proc->subframe_rx);
+                    getchar();
+                }
+            } // start_rx_stream==1
+        } // UE->is_synchronized==1
+
+    } // while !oai_exit
+    return NULL;
+}
+
+/*!
+ * \brief Initialize the UE theads.
+ * Creates the UE threads:
+ * - UE_thread_rxtx0
+ * - UE_thread_rxtx1
+ * - UE_thread_synch
+ * - UE_thread_fep_slot0
+ * - UE_thread_fep_slot1
+ * - UE_thread_dlsch_proc_slot0
+ * - UE_thread_dlsch_proc_slot1
+ * and the locking between them.
+ */
+void init_UE_threads(PHY_VARS_NR_UE *UE) {
+    struct nr_rxtx_thread_data *rtd;
+
+    pthread_attr_init (&UE->proc.attr_ue);
+    pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
+
+    pthread_mutex_init(&UE->proc.mutex_synch,NULL);
+    pthread_cond_init(&UE->proc.cond_synch,NULL);
+
+    // the threads are not yet active, therefore access is allowed without locking
+    int nb_threads=RX_NB_TH;
+    for (int i=0; i<nb_threads; i++) {
+        rtd = calloc(1, sizeof(struct nr_rxtx_thread_data));
+        if (rtd == NULL) abort();
+        rtd->UE = UE;
+        rtd->proc = &UE->proc.proc_rxtx[i];
+
+        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
+        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
+        UE->proc.proc_rxtx[i].sub_frame_start=i;
+        UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
+        printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
+        pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd);
+
+#ifdef UE_DLSCH_PARALLELISATION
+        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_dlsch_td,NULL);
+        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_dlsch_td,NULL);
+        pthread_create(&UE->proc.proc_rxtx[i].pthread_dlsch_td,NULL,dlsch_decoding_2thread0, rtd);
+        //thread 2
+        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_dlsch_td1,NULL);
+        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_dlsch_td1,NULL);
+        pthread_create(&UE->proc.proc_rxtx[i].pthread_dlsch_td1,NULL,dlsch_decoding_2thread1, rtd);
+#endif
+
+#ifdef UE_SLOT_PARALLELISATION
+        //pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL);
+        //pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL);
+        //pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd);
+
+        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL);
+        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL);
+        pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd);
+#endif
+
+    }
+    pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
+}
+
+
+#ifdef OPENAIR2
+void fill_ue_band_info(void) {
+
+    UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
+    int i,j;
+
+    bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
+
+    for (i=0; i<bands_to_scan.nbands; i++) {
+
+        for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
+            if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
+                memcpy(&bands_to_scan.band_info[i],
+                       &eutra_bands[j],
+                       sizeof(eutra_band_t));
+
+                printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
+                       bands_to_scan.band_info[i].band,
+                       UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
+                       bands_to_scan.band_info[i].dl_min,
+                       bands_to_scan.band_info[i].dl_max,
+                       bands_to_scan.band_info[i].ul_min,
+                       bands_to_scan.band_info[i].ul_max,
+                       (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
+                break;
+            }
+    }
+}
+#endif
+
+int setup_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg) {
+
+    int i, CC_id;
+    LTE_DL_FRAME_PARMS *frame_parms;
+    openair0_rf_map *rf_map;
+
+    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+        rf_map = &phy_vars_ue[CC_id]->rf_map;
+
+        AssertFatal( phy_vars_ue[CC_id] !=0, "");
+        frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
+
+        // replace RX signal buffers with mmaped HW versions
+        rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
+        txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );
+
+        for (i=0; i<frame_parms->nb_antennas_rx; i++) {
+            LOG_I(PHY, "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",
+                  CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
+            free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
+            rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
+            phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
+        }
+
+        for (i=0; i<frame_parms->nb_antennas_tx; i++) {
+            LOG_I(PHY, "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",
+                  CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
+            free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
+            txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
+            phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
+        }
+
+        // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x]
+        // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x]
+        // be careful when releasing memory!
+        // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
+    }
+    return 0;
+}
+
diff --git a/targets/RT/USER/nr-uesoftmodem.c b/targets/RT/USER/nr-uesoftmodem.c
new file mode 100644
index 0000000000000000000000000000000000000000..eebc2b2ca2397567c4d577c8195eeae71df51201
--- /dev/null
+++ b/targets/RT/USER/nr-uesoftmodem.c
@@ -0,0 +1,1741 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+
+#define _GNU_SOURCE             /* See feature_test_macros(7) */
+#include <sched.h>
+
+#include "T.h"
+#include "rt_wrapper.h"
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "assertions.h"
+#include "msc.h"
+
+#include "PHY/types.h"
+#include "PHY/defs_nr_UE.h"
+#include "common/ran_context.h"
+#include "common/config/config_userapi.h"
+#include "common/utils/load_module_shlib.h"
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "../../ARCH/COMMON/common_lib.h"
+#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
+
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#include "PHY/phy_vars_nr_ue.h"
+#include "PHY/LTE_TRANSPORT/transport_vars.h"
+#include "SCHED/sched_common_vars.h"
+#include "PHY/MODULATION/modulation_vars.h"
+//#include "../../SIMU/USER/init_lte.h"
+
+#include "LAYER2/MAC/mac.h"
+#include "LAYER2/MAC/mac_vars.h"
+#include "LAYER2/MAC/mac_proto.h"
+#include "RRC/LTE/rrc_vars.h"
+#include "PHY_INTERFACE/phy_interface_vars.h"
+
+#ifdef SMBV
+#include "PHY/TOOLS/smbv.h"
+unsigned short config_frames[4] = {2,9,11,13};
+#endif
+#include "UTIL/LOG/log_extern.h"
+#include "UTIL/OTG/otg_tx.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "UTIL/MATH/oml.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+#include "enb_config.h"
+//#include "PHY/TOOLS/time_meas.h"
+
+#ifndef OPENAIR2
+#include "UTIL/OTG/otg_vars.h"
+#endif
+
+#if defined(ENABLE_ITTI)
+#include "intertask_interface_init.h"
+#include "create_tasks.h"
+#endif
+
+#include "PHY/INIT/phy_init.h"
+#include "system.h"
+#include "stats.h"
+#ifdef XFORMS
+#include "PHY/TOOLS/lte_phy_scope.h"
+//#include "stats.h"
+// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
+// at eNB 0, an UL scope for every UE
+FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
+FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
+FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
+char title[255];
+unsigned char                   scope_enb_num_ue = 2;
+static pthread_t                forms_thread; //xforms
+#endif //XFORMS
+#include "nr-uesoftmodem.h"
+
+RAN_CONTEXT_t RC;
+
+pthread_cond_t sync_cond;
+pthread_mutex_t sync_mutex;
+int sync_var=-1; //!< protected by mutex \ref sync_mutex.
+
+uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
+uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
+
+#if defined(ENABLE_ITTI)
+volatile int             start_eNB = 0;
+volatile int             start_UE = 0;
+#endif
+volatile int             oai_exit = 0;
+
+static clock_source_t clock_source = internal;
+static int wait_for_sync = 0;
+
+static char              UE_flag=0;
+unsigned int                    mmapped_dma=0;
+int                             single_thread_flag=1;
+
+static char                     threequarter_fs=0;
+
+uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
+int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
+
+
+static char                    *conf_config_file_name = NULL;
+#if defined(ENABLE_ITTI)
+static char                    *itti_dump_file = NULL;
+#endif
+
+int UE_scan = 1;
+int UE_scan_carrier = 0;
+runmode_t mode = normal_txrx;
+
+FILE *input_fd=NULL;
+
+
+#if MAX_NUM_CCs == 1
+rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
+double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
+double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
+#else
+rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
+double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
+double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
+#endif
+
+double rx_gain_off = 0.0;
+
+double sample_rate=30.72e6;
+double bw = 10.0e6;
+
+static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
+
+char   rf_config_file[1024];
+
+int chain_offset=0;
+int phy_test = 0;
+uint8_t usim_test = 0;
+
+uint8_t dci_Format = 0;
+uint8_t agregation_Level =0xFF;
+
+uint8_t nb_antenna_tx = 1;
+uint8_t nb_antenna_rx = 1;
+
+char ref[128] = "internal";
+char channels[128] = "0";
+
+int                      rx_input_level_dBm;
+static int                      online_log_messages=0;
+#ifdef XFORMS
+extern int                      otg_enabled;
+static char                     do_forms=0;
+#else
+int                             otg_enabled;
+#endif
+//int                             number_of_cards =   1;
+
+static NR_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
+static nfapi_config_request_t *config[MAX_NUM_CCs];
+int16_t   node_synch_ref[MAX_NUM_CCs];
+
+uint32_t target_dl_mcs = 28; //maximum allowed mcs
+uint32_t target_ul_mcs = 20;
+uint32_t timing_advance = 0;
+uint8_t exit_missed_slots=1;
+uint64_t num_missed_slots=0; // counter for the number of missed slots
+
+int transmission_mode=1;
+int numerology = 0;
+
+int16_t           glog_level         = LOG_INFO;
+int16_t           glog_verbosity     = LOG_MED;
+int16_t           hw_log_level       = LOG_INFO;
+int16_t           hw_log_verbosity   = LOG_MED;
+int16_t           phy_log_level      = LOG_INFO;
+int16_t           phy_log_verbosity  = LOG_MED;
+int16_t           mac_log_level      = LOG_INFO;
+int16_t           mac_log_verbosity  = LOG_MED;
+int16_t           rlc_log_level      = LOG_INFO;
+int16_t           rlc_log_verbosity  = LOG_MED;
+int16_t           pdcp_log_level     = LOG_INFO;
+int16_t           pdcp_log_verbosity = LOG_MED;
+int16_t           rrc_log_level      = LOG_INFO;
+int16_t           rrc_log_verbosity  = LOG_MED;
+int16_t           opt_log_level      = LOG_INFO;
+int16_t           opt_log_verbosity  = LOG_MED;
+
+# if defined(ENABLE_USE_MME)
+int16_t           gtpu_log_level     = LOG_DEBUG;
+int16_t           gtpu_log_verbosity = LOG_MED;
+int16_t           udp_log_level      = LOG_DEBUG;
+int16_t           udp_log_verbosity  = LOG_MED;
+#endif
+#if defined (ENABLE_SECURITY)
+int16_t           osa_log_level      = LOG_INFO;
+int16_t           osa_log_verbosity  = LOG_MED;
+#endif
+
+char *rrh_UE_ip = "127.0.0.1";
+int rrh_UE_port = 51000;
+
+/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */
+//uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD;
+/* struct for ethernet specific parameters given in eNB conf file */
+//eth_params_t *eth_params;
+
+openair0_config_t openair0_cfg[MAX_CARDS];
+
+double cpuf;
+
+char uecap_xer[1024],uecap_xer_in=0;
+
+int oaisim_flag=0;
+int emulate_rf = 0;
+
+threads_t threads= {-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1,-1};
+
+/* forward declarations */
+void set_default_frame_parms(nfapi_config_request_t *config[MAX_NUM_CCs], NR_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
+
+
+/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
+ * this is very hackish - find a proper solution
+ */
+uint8_t abstraction_flag=0;
+
+/*---------------------BMC: timespec helpers -----------------------------*/
+
+struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
+struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
+
+struct timespec clock_difftime(struct timespec start, struct timespec end) {
+    struct timespec temp;
+    if ((end.tv_nsec-start.tv_nsec)<0) {
+        temp.tv_sec = end.tv_sec-start.tv_sec-1;
+        temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
+    } else {
+        temp.tv_sec = end.tv_sec-start.tv_sec;
+        temp.tv_nsec = end.tv_nsec-start.tv_nsec;
+    }
+    return temp;
+}
+
+void print_difftimes(void) {
+#ifdef DEBUG
+    printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
+#else
+    LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
+#endif
+}
+
+void update_difftimes(struct timespec start, struct timespec end) {
+    struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
+    int             changed = 0;
+    diff_time = clock_difftime(start, end);
+    if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
+        min_diff_time.tv_nsec = diff_time.tv_nsec;
+        changed = 1;
+    }
+    if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
+        max_diff_time.tv_nsec = diff_time.tv_nsec;
+        changed = 1;
+    }
+#if 1
+    if (changed) print_difftimes();
+#endif
+}
+
+/*------------------------------------------------------------------------*/
+
+unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
+    return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
+}
+unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
+    return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
+}
+
+#if !defined(ENABLE_ITTI)
+void signal_handler(int sig) {
+    void *array[10];
+    size_t size;
+
+    if (sig==SIGSEGV) {
+        // get void*'s for all entries on the stack
+        size = backtrace(array, 10);
+
+        // print out all the frames to stderr
+        fprintf(stderr, "Error: signal %d:\n", sig);
+        backtrace_symbols_fd(array, size, 2);
+        exit(-1);
+    } else {
+        printf("trying to exit gracefully...\n");
+        oai_exit = 1;
+    }
+}
+#endif
+#define KNRM  "\x1B[0m"
+#define KRED  "\x1B[31m"
+#define KGRN  "\x1B[32m"
+#define KBLU  "\x1B[34m"
+#define RESET "\033[0m"
+
+void help (void) {
+  printf (KGRN "Usage:\n");
+  printf("  sudo -E lte-softmodem [options]\n");
+  printf("  sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n");
+  printf("Options:\n");
+  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
+  printf("  --ulsch-max-errors set the max ULSCH erros\n");
+  printf("  --calib-ue-rx set UE RX calibration\n");
+  printf("  --calib-ue-rx-med \n");
+  printf("  --calib-ue-rxbyp\n");
+  printf("  --debug-ue-prach run normal prach power ramping, but don't continue random-access\n");
+  printf("  --calib-prach-tx run normal prach with maximum power, but don't continue random-access\n");
+  printf("  --no-L2-connect bypass L2 and upper layers\n");
+  printf("  --ue-rxgain set UE RX gain\n");
+  printf("  --ue-rxgain-off external UE amplifier offset\n");
+  printf("  --ue-txgain set UE TX gain\n");
+  printf("  --ue-nb-ant-rx  set UE number of rx antennas\n");
+  printf("  --ue-scan-carrier set UE to scan around carrier\n");
+  printf("  --dlsch-demod-shift dynamic shift for LLR compuation for TM3/4 (default 0)\n");
+  printf("  --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n");
+  printf("  --mmapped-dma sets flag for improved EXMIMO UE performance\n");  
+  printf("  --external-clock tells hardware to use an external clock reference\n");
+  printf("  --usim-test use XOR autentication algo in case of test usim mode\n"); 
+  printf("  --single-thread-disable. Disables single-thread mode in lte-softmodem\n"); 
+  printf("  --AgregationLevel Choose the agregation level used by tghe eNB for the OAI use 1, it will save some time of processing the pdcch\n");
+  printf("  --DCIformat choose the DCI format, be careful when using this option(for the moment only valid for SISO DCI format 1)\n");
+  printf("  -A Set timing_advance\n");
+  printf("  -C Set the downlink frequency for all component carriers\n");
+  printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
+  printf("  -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n");
+  printf("  -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n");
+  printf("  -G Set the global log verbosity \n");
+  printf("  -h provides this help message!\n");
+  printf("  -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n");
+  printf("  -m Set the maximum downlink MCS\n");
+  printf("  -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n");
+  printf("  -q Enable processing timing measurement of lte softmodem on per subframe basis \n");
+  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
+  printf("  -S Skip the missed slots/subframes \n");    
+  printf("  -t Set the maximum uplink MCS\n");
+  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
+  printf("  -U Set the lte softmodem as a UE\n");
+  printf("  -W Enable L2 wireshark messages on localhost \n");
+  printf("  -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n");
+  printf("  -x Set the transmission mode, valid options: 1 \n");
+  printf("  -E Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n");
+#if T_TRACER
+    printf("  --T_port [port]    use given port\n");
+    printf("  --T_nowait         don't wait for tracer, start immediately\n");
+    printf("  --T_dont_fork      to ease debugging with gdb\n");
+#endif
+    printf(RESET);
+    fflush(stdout);
+}
+
+void exit_fun(const char* s) {
+    int CC_id;
+
+    if (s != NULL) {
+        printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
+    }
+
+    oai_exit = 1;
+
+    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+            if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
+                PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
+    }
+
+#if defined(ENABLE_ITTI)
+    sleep(1); //allow lte-softmodem threads to exit first
+    itti_terminate_tasks (TASK_UNKNOWN);
+#endif
+
+}
+
+
+#ifdef XFORMS
+
+
+void reset_stats(FL_OBJECT *button, long arg) {
+    int i,j,k;
+    /*PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
+
+    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
+        for (k=0; k<8; k++) { //harq_processes
+            for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
+                phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
+                phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
+                phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
+            }
+
+            phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
+            phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
+            phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;
+
+            for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) {
+                phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0;
+                phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
+                phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0;
+                phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0;
+            }
+        }
+
+        phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
+        phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
+        phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
+    }*/
+}
+
+static void *scope_thread(void *arg) {
+    char stats_buffer[16384];
+# ifdef ENABLE_XFORMS_WRITE_STATS
+    FILE *UE_stats, *eNB_stats;
+# endif
+    int len = 0;
+    struct sched_param sched_param;
+    int UE_id, CC_id;
+    int ue_cnt=0;
+
+    sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
+    sched_setscheduler(0, SCHED_FIFO,&sched_param);
+
+    printf("Scope thread has priority %d\n",sched_param.sched_priority);
+
+# ifdef ENABLE_XFORMS_WRITE_STATS
+
+    if (UE_flag==1)
+        UE_stats  = fopen("UE_stats.txt", "w");
+    else
+        eNB_stats = fopen("eNB_stats.txt", "w");
+
+#endif
+
+    while (!oai_exit) {
+        if (UE_flag==1) {
+            //len = dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm);
+            //fl_set_object_label(form_stats->stats_text, stats_buffer);
+            fl_clear_browser(form_stats->stats_text);
+            fl_add_browser_line(form_stats->stats_text, stats_buffer);
+
+            /*phy_scope_UE(form_ue[0],
+                         PHY_vars_UE_g[0][0],
+                         0,
+                         0,7);*/
+
+        }
+
+        //printf("doing forms\n");
+        //usleep(100000); // 100 ms
+        sleep(1);
+    }
+
+    //  printf("%s",stats_buffer);
+
+# ifdef ENABLE_XFORMS_WRITE_STATS
+
+    if (UE_flag==1) {
+        if (UE_stats) {
+            rewind (UE_stats);
+            fwrite (stats_buffer, 1, len, UE_stats);
+            fclose (UE_stats);
+        }
+    }
+
+# endif
+
+    pthread_exit((void*)arg);
+}
+#endif
+
+
+
+
+#if defined(ENABLE_ITTI)
+void *l2l1_task(void *arg) {
+    MessageDef *message_p = NULL;
+    int         result;
+
+    itti_set_task_real_time(TASK_L2L1);
+    itti_mark_task_ready(TASK_L2L1);
+
+    if (UE_flag == 0) {
+        /* Wait for the initialize message */
+        printf("Wait for the ITTI initialize message\n");
+        do {
+            if (message_p != NULL) {
+                result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
+                AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+            }
+
+            itti_receive_msg (TASK_L2L1, &message_p);
+
+            switch (ITTI_MSG_ID(message_p)) {
+            case INITIALIZE_MESSAGE:
+                /* Start eNB thread */
+                LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
+                start_eNB = 1;
+                break;
+
+            case TERMINATE_MESSAGE:
+                printf("received terminate message\n");
+                oai_exit=1;
+                itti_exit_task ();
+                break;
+
+            default:
+                LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
+                break;
+            }
+        } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
+
+        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
+        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    }
+
+    do {
+        // Wait for a message
+        itti_receive_msg (TASK_L2L1, &message_p);
+
+        switch (ITTI_MSG_ID(message_p)) {
+        case TERMINATE_MESSAGE:
+            oai_exit=1;
+            itti_exit_task ();
+            break;
+
+        case ACTIVATE_MESSAGE:
+            start_UE = 1;
+            break;
+
+        case DEACTIVATE_MESSAGE:
+            start_UE = 0;
+            break;
+
+        case MESSAGE_TEST:
+            LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
+            break;
+
+        default:
+            LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
+            break;
+        }
+
+        result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
+        AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
+    } while(!oai_exit);
+
+    return NULL;
+}
+#endif
+
+
+
+
+static void get_options (int argc, char **argv) {
+    int c;
+    //  char                          line[1000];
+    //  int                           l;
+    int k,i;//,j,k;
+#if defined(OAI_USRP) || defined(CPRIGW) || defined(OAI_ADRV9371_ZC706)
+    int clock_src;
+#endif
+    int CC_id;
+
+    enum long_option_e {
+        LONG_OPTION_START = 0x100, /* Start after regular single char options */
+        LONG_OPTION_RF_CONFIG_FILE,
+        LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS,
+        LONG_OPTION_CALIB_UE_RX,
+        LONG_OPTION_CALIB_UE_RX_MED,
+        LONG_OPTION_CALIB_UE_RX_BYP,
+        LONG_OPTION_DEBUG_UE_PRACH,
+        LONG_OPTION_NO_L2_CONNECT,
+        LONG_OPTION_CALIB_PRACH_TX,
+        LONG_OPTION_RXGAIN,
+        LONG_OPTION_RXGAINOFF,
+        LONG_OPTION_TXGAIN,
+	LONG_OPTION_NBRXANT,
+	LONG_OPTION_NBTXANT,
+        LONG_OPTION_SCANCARRIER,
+        LONG_OPTION_MAXPOWER,
+        LONG_OPTION_DUMP_FRAME,
+        LONG_OPTION_LOOPMEMORY,
+        LONG_OPTION_PHYTEST,
+        LONG_OPTION_USIMTEST,
+        LONG_OPTION_MMAPPED_DMA,
+        LONG_OPTION_EXTERNAL_CLOCK,
+        LONG_OPTION_WAIT_FOR_SYNC,
+        LONG_OPTION_SINGLE_THREAD_DISABLE,
+        LONG_OPTION_THREADIQ,
+        LONG_OPTION_THREADONESUBFRAME,
+        LONG_OPTION_THREADTWOSUBFRAME,
+        LONG_OPTION_THREADTHREESUBFRAME,
+        LONG_OPTION_THREADSLOT1PROCONE,
+        LONG_OPTION_THREADSLOT1PROCTWO,
+        LONG_OPTION_THREADSLOT1PROCTHREE,
+		LONG_OPTION_THREADDLSCHTDONE,
+		LONG_OPTION_THREADDLSCHTDTWO,
+		LONG_OPTION_THREADDLSCHTDTHREE,
+		LONG_OPTION_THREADDLSCHTD1ONE,
+		LONG_OPTION_THREADDLSCHTD1TWO,
+		LONG_OPTION_THREADDLSCHTD1THREE,
+        LONG_OPTION_DCIFORMAT,
+        LONG_OPTION_AGREGATIONLEVEL,
+        LONG_OPTION_DEMOD_SHIFT,
+#if T_TRACER
+        LONG_OPTION_T_PORT,
+        LONG_OPTION_T_NOWAIT,
+        LONG_OPTION_T_DONT_FORK,
+#endif
+
+    };
+
+    static const struct option long_options[] = {
+        {"rf-config-file",required_argument,  NULL, LONG_OPTION_RF_CONFIG_FILE},
+        {"ulsch-max-errors",required_argument,  NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS},
+        {"calib-ue-rx",     required_argument,  NULL, LONG_OPTION_CALIB_UE_RX},
+        {"calib-ue-rx-med", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_MED},
+        {"calib-ue-rx-byp", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_BYP},
+        {"debug-ue-prach",  no_argument,        NULL, LONG_OPTION_DEBUG_UE_PRACH},
+        {"no-L2-connect",   no_argument,        NULL, LONG_OPTION_NO_L2_CONNECT},
+        {"calib-prach-tx",   no_argument,        NULL, LONG_OPTION_CALIB_PRACH_TX},
+        {"ue-rxgain",   required_argument,  NULL, LONG_OPTION_RXGAIN},
+        {"ue-rxgain-off",   required_argument,  NULL, LONG_OPTION_RXGAINOFF},
+        {"ue-txgain",   required_argument,  NULL, LONG_OPTION_TXGAIN},
+     	{"ue-nb-ant-rx", required_argument,  NULL, LONG_OPTION_NBRXANT},
+	    {"ue-nb-ant-tx", required_argument,  NULL, LONG_OPTION_NBTXANT},
+        {"ue-scan-carrier",   no_argument,  NULL, LONG_OPTION_SCANCARRIER},
+        {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
+        {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
+        {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
+        {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
+        {"usim-test", no_argument, NULL, LONG_OPTION_USIMTEST},
+        {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
+        {"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK},
+        {"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC},
+        {"single-thread-disable", no_argument, NULL, LONG_OPTION_SINGLE_THREAD_DISABLE},
+        {"threadIQ",  required_argument, NULL, LONG_OPTION_THREADIQ},
+        {"threadOneSubframe",  required_argument, NULL, LONG_OPTION_THREADONESUBFRAME},
+        {"threadTwoSubframe",  required_argument, NULL, LONG_OPTION_THREADTWOSUBFRAME},
+        {"threadThreeSubframe",  required_argument, NULL, LONG_OPTION_THREADTHREESUBFRAME},
+        {"threadSlot1ProcOne",  required_argument, NULL, LONG_OPTION_THREADSLOT1PROCONE},
+        {"threadSlot1ProcTwo",  required_argument, NULL, LONG_OPTION_THREADSLOT1PROCTWO},
+        {"threadSlot1ProcThree",  required_argument, NULL, LONG_OPTION_THREADSLOT1PROCTHREE},
+		{"threadDlschTdOne",  required_argument, NULL, LONG_OPTION_THREADDLSCHTDONE},
+		{"threadDlschTdTwo",  required_argument, NULL, LONG_OPTION_THREADDLSCHTDTWO},
+		{"threadDlschTdThree",  required_argument, NULL, LONG_OPTION_THREADDLSCHTDTHREE},
+		{"threadDlschTd1One",  required_argument, NULL, LONG_OPTION_THREADDLSCHTD1ONE},
+		{"threadDlschTd1Two",  required_argument, NULL, LONG_OPTION_THREADDLSCHTD1TWO},
+		{"threadDlschTd1Three",  required_argument, NULL, LONG_OPTION_THREADDLSCHTD1THREE},
+        {"DCIformat",  required_argument, NULL, LONG_OPTION_DCIFORMAT},
+        {"AgregationLevel",  required_argument, NULL, LONG_OPTION_AGREGATIONLEVEL},
+        {"dlsch-demod-shift", required_argument,  NULL, LONG_OPTION_DEMOD_SHIFT},
+#if T_TRACER
+        {"T_port",                 required_argument, 0, LONG_OPTION_T_PORT},
+        {"T_nowait",               no_argument,       0, LONG_OPTION_T_NOWAIT},
+        {"T_dont_fork",            no_argument,       0, LONG_OPTION_T_DONT_FORK},
+#endif
+    {NULL, 0, NULL, 0}
+  };
+
+  while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:n:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) {
+    switch (c) {
+    case LONG_OPTION_RF_CONFIG_FILE:
+      if ((strcmp("null", optarg) == 0) || (strcmp("NULL", optarg) == 0)) {
+	printf("no configuration filename is provided\n");
+      }
+      else if (strlen(optarg)<=1024){
+	strcpy(rf_config_file,optarg);
+      }else {
+	printf("Configuration filename is too long\n");
+	exit(-1);   
+      }
+      break;
+    case LONG_OPTION_MAXPOWER:
+      tx_max_power[0]=atoi(optarg);
+      for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++)
+	tx_max_power[CC_id]=tx_max_power[0];
+      break;
+    case LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS:
+      ULSCH_max_consecutive_errors = atoi(optarg);
+      printf("Set ULSCH_max_consecutive_errors = %d\n",ULSCH_max_consecutive_errors);
+      break;
+
+    case LONG_OPTION_CALIB_UE_RX:
+      mode = rx_calib_ue;
+      rx_input_level_dBm = atoi(optarg);
+      printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm);
+      break;
+
+    case LONG_OPTION_CALIB_UE_RX_MED:
+      mode = rx_calib_ue_med;
+      rx_input_level_dBm = atoi(optarg);
+      printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm);
+      break;
+
+    case LONG_OPTION_CALIB_UE_RX_BYP:
+      mode = rx_calib_ue_byp;
+      rx_input_level_dBm = atoi(optarg);
+      printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm);
+      break;
+
+    case LONG_OPTION_DEBUG_UE_PRACH:
+      mode = debug_prach;
+      break;
+
+    case LONG_OPTION_NO_L2_CONNECT:
+      mode = no_L2_connect;
+      break;
+
+    case LONG_OPTION_CALIB_PRACH_TX:
+      mode = calib_prach_tx;
+      printf("Setting mode to calib_prach_tx (%d)\n",mode);
+      break;
+
+    case LONG_OPTION_RXGAIN:
+      for (i=0; i<4; i++)
+        rx_gain[0][i] = atof(optarg);
+
+      break;
+
+    case LONG_OPTION_RXGAINOFF:
+      rx_gain_off = atof(optarg);
+      break;
+
+    case LONG_OPTION_TXGAIN:
+      for (i=0; i<4; i++)
+        tx_gain[0][i] = atof(optarg);
+
+      break;
+    case LONG_OPTION_NBRXANT:
+    	nb_antenna_rx = atof(optarg);
+    	break;
+    case LONG_OPTION_NBTXANT:
+    	nb_antenna_tx = atof(optarg);
+    	break;
+    case LONG_OPTION_SCANCARRIER:
+      UE_scan_carrier=1;
+
+      break;
+
+    case LONG_OPTION_LOOPMEMORY:
+      mode=loop_through_memory;
+      input_fd = fopen(optarg,"r");
+      AssertFatal(input_fd != NULL,"Please provide an input file\n");
+      break;
+
+    case LONG_OPTION_DUMP_FRAME:
+      mode = rx_dump_frame;
+      break;
+      
+    case LONG_OPTION_PHYTEST:
+      phy_test = 1;
+      break;
+
+    case LONG_OPTION_USIMTEST:
+        usim_test = 1;
+      break;
+    case LONG_OPTION_MMAPPED_DMA:
+      mmapped_dma = 1;
+      break;
+
+    case LONG_OPTION_SINGLE_THREAD_DISABLE:
+      single_thread_flag = 0;
+      break;
+
+    case LONG_OPTION_EXTERNAL_CLOCK:
+      clock_source = external;
+      break;
+
+    case LONG_OPTION_WAIT_FOR_SYNC:
+      wait_for_sync = 1;
+      break;
+
+    case LONG_OPTION_THREADIQ:
+       threads.iq=atoi(optarg);
+       break;
+    case LONG_OPTION_THREADONESUBFRAME:
+       threads.one=atoi(optarg);
+       break;
+    case LONG_OPTION_THREADTWOSUBFRAME:
+       threads.two=atoi(optarg);
+       break;
+    case LONG_OPTION_THREADTHREESUBFRAME:
+       threads.three=atoi(optarg);
+    break;
+    case LONG_OPTION_THREADSLOT1PROCONE:
+       threads.slot1_proc_one=atoi(optarg);
+       break;
+    case LONG_OPTION_THREADSLOT1PROCTWO:
+       threads.slot1_proc_two=atoi(optarg);
+       break;
+    case LONG_OPTION_THREADSLOT1PROCTHREE:
+       threads.slot1_proc_three=atoi(optarg);
+       break;
+    case LONG_OPTION_THREADDLSCHTDONE:
+       threads.dlsch_td_one=atoi(optarg);
+       break;
+	case LONG_OPTION_THREADDLSCHTDTWO:
+       threads.dlsch_td_two=atoi(optarg);
+	   break;
+	case LONG_OPTION_THREADDLSCHTDTHREE:
+       threads.dlsch_td_three=atoi(optarg);
+    break;
+    case LONG_OPTION_THREADDLSCHTD1ONE:
+    	threads.dlsch_td1_one=atoi(optarg);
+    	break;
+	case LONG_OPTION_THREADDLSCHTD1TWO:
+		threads.dlsch_td1_two=atoi(optarg);
+	   break;
+	case LONG_OPTION_THREADDLSCHTD1THREE:
+		threads.dlsch_td1_three=atoi(optarg);
+		break;
+    case LONG_OPTION_DCIFORMAT:
+        dci_Format = atoi(optarg);
+       break;
+    case LONG_OPTION_AGREGATIONLEVEL:
+        agregation_Level = atoi(optarg);
+        break;
+    case LONG_OPTION_DEMOD_SHIFT: {
+        extern int16_t dlsch_demod_shift;
+        dlsch_demod_shift = atof(optarg);
+        break;
+    }
+#if T_TRACER
+        case LONG_OPTION_T_PORT: {
+            extern int T_port;
+            if (optarg == NULL) abort();  /* should not happen */
+            T_port = atoi(optarg);
+            break;
+        }
+
+        case LONG_OPTION_T_NOWAIT: {
+            extern int T_wait;
+            T_wait = 0;
+            break;
+        }
+
+        case LONG_OPTION_T_DONT_FORK: {
+            extern int T_dont_fork;
+            T_dont_fork = 1;
+            break;
+        }
+#endif
+
+        case 'A':
+            timing_advance = atoi (optarg);
+            break;
+
+        case 'C':
+            for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+                downlink_frequency[CC_id][0] = atof(optarg); // 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]);
+            }
+
+            UE_scan=0;
+
+            break;
+
+        case 'a':
+            chain_offset = atoi(optarg);
+            break;
+
+        case 'd':
+#ifdef XFORMS
+            do_forms=1;
+            printf("Running with XFORMS!\n");
+#endif
+            break;
+
+        case 'E':
+            threequarter_fs=1;
+            break;
+
+        case 'K':
+#if defined(ENABLE_ITTI)
+            itti_dump_file = strdup(optarg);
+#else
+            printf("-K option is disabled when ENABLE_ITTI is not defined\n");
+#endif
+            break;
+
+        case 'O':
+            conf_config_file_name = optarg;
+            break;
+
+        case 'U':
+            UE_flag = 1;
+            break;
+
+        case 'm':
+            target_dl_mcs = atoi (optarg);
+            break;
+
+        case 't':
+            target_ul_mcs = atoi (optarg);
+            break;
+
+        case 'W':
+            opt_enabled=1;
+            opt_type = OPT_WIRESHARK;
+            strncpy(in_ip, "127.0.0.1", sizeof(in_ip));
+            in_ip[sizeof(in_ip) - 1] = 0; // terminate string
+            printf("Enabling OPT for wireshark for local interface");
+            /*
+            if (optarg == NULL){
+            in_ip[0] =NULL;
+            printf("Enabling OPT for wireshark for local interface");
+            } else {
+            strncpy(in_ip, optarg, sizeof(in_ip));
+            in_ip[sizeof(in_ip) - 1] = 0; // terminate string
+            printf("Enabling OPT for wireshark with %s \n",in_ip);
+            }
+                 */
+            break;
+
+        case 'P':
+            opt_type = OPT_PCAP;
+            opt_enabled=1;
+
+            if (optarg == NULL) {
+                strncpy(in_path, "/tmp/oai_opt.pcap", sizeof(in_path));
+                in_path[sizeof(in_path) - 1] = 0; // terminate string
+                printf("Enabling OPT for PCAP with the following path /tmp/oai_opt.pcap");
+            } else {
+                strncpy(in_path, optarg, sizeof(in_path));
+                in_path[sizeof(in_path) - 1] = 0; // terminate string
+                printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
+            }
+
+            break;
+
+        case 'V':
+            ouput_vcd = 1;
+            break;
+
+        case  'q':
+            opp_enabled = 1;
+            break;
+
+        case  'R' :
+            online_log_messages =1;
+            break;
+
+        /*case 'r':
+            UE_scan = 0;
+
+            for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+                switch(atoi(optarg)) {
+                case 6:
+                    frame_parms[CC_id]->N_RB_DL=6;
+                    frame_parms[CC_id]->N_RB_UL=6;
+                    break;
+
+                case 25:
+                    frame_parms[CC_id]->N_RB_DL=25;
+                    frame_parms[CC_id]->N_RB_UL=25;
+                    break;
+
+                case 50:
+                    frame_parms[CC_id]->N_RB_DL=50;
+                    frame_parms[CC_id]->N_RB_UL=50;
+                    break;
+
+                case 100:
+                    frame_parms[CC_id]->N_RB_DL=100;
+                    frame_parms[CC_id]->N_RB_UL=100;
+                    break;
+
+                default:
+                    printf("Unknown N_RB_DL %d, switching to 25\n",atoi(optarg));
+                    break;
+                }
+            }
+
+            break;*/
+
+        case 's':
+#if defined(OAI_USRP) || defined(CPRIGW) || defined(OAI_ADRV9371_ZC706)
+
+            clock_src = atoi(optarg);
+
+            if (clock_src == 0) {
+                //  char ref[128] = "internal";
+                //strncpy(uhd_ref, ref, strlen(ref)+1);
+            } else if (clock_src == 1) {
+                //char ref[128] = "external";
+                //strncpy(uhd_ref, ref, strlen(ref)+1);
+            }
+
+#else
+            printf("Note: -s not defined for ExpressMIMO2\n");
+#endif
+            break;
+
+        case 'S':
+            exit_missed_slots=0;
+            printf("Skip exit for missed slots\n");
+            break;
+
+        case 'g':
+            glog_level=atoi(optarg); // value between 1 - 9
+            break;
+
+        case 'F':
+            break;
+
+        case 'G':
+            glog_verbosity=atoi(optarg);// value from 0, 0x5, 0x15, 0x35, 0x75
+            break;
+
+        case 'x':
+            printf("Transmission mode should be set in config file now\n");
+            exit(-1);
+            /*
+            transmission_mode = atoi(optarg);
+
+            if (transmission_mode > 7) {
+              printf("Transmission mode %d not supported for the moment\n",transmission_mode);
+              exit(-1);
+            }
+            */
+            break;
+
+        case 'T':
+            for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++)
+                frame_parms[CC_id]->frame_type = TDD;
+            break;
+
+        case 'n':
+	  numerology=atoi(optarg);
+	  break;
+
+        case 'h':
+            help ();
+            exit (-1);
+
+        default:
+            help ();
+            exit (-1);
+            break;
+        }
+    }
+
+    if (UE_flag == 0)
+        AssertFatal(conf_config_file_name != NULL,"Please provide a configuration file\n");
+
+    if (UE_flag == 1) {
+        if (conf_config_file_name != NULL) {
+
+            // Here the configuration file is the XER encoded UE capabilities
+            // Read it in and store in asn1c data structures
+            strcpy(uecap_xer,conf_config_file_name);
+            uecap_xer_in=1;
+        }
+    }
+}
+
+#if T_TRACER
+int T_wait = 1;       /* by default we wait for the tracer */
+int T_port = 2021;    /* default port to listen to to wait for the tracer */
+int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
+#endif
+
+void set_default_frame_parms(nfapi_config_request_t *config[MAX_NUM_CCs], NR_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] = (NR_DL_FRAME_PARMS*) malloc(sizeof(NR_DL_FRAME_PARMS));
+        /* Set some default values that may be overwritten while reading options */
+        frame_parms[CC_id] = (NR_DL_FRAME_PARMS*) malloc(sizeof(NR_DL_FRAME_PARMS));
+        config[CC_id] = (nfapi_config_request_t*) malloc(sizeof(nfapi_config_request_t));
+        config[CC_id]->subframe_config.numerology_index_mu.value =1;
+        config[CC_id]->subframe_config.duplex_mode.value = 1; //FDD
+        config[CC_id]->subframe_config.dl_cyclic_prefix_type.value = 0; //NORMAL
+        config[CC_id]->rf_config.dl_channel_bandwidth.value = 106;
+        config[CC_id]->rf_config.ul_channel_bandwidth.value = 106;
+        config[CC_id]->rf_config.tx_antenna_ports.value = 1;
+        config[CC_id]->rf_config.rx_antenna_ports.value = 1;
+        config[CC_id]->sch_config.physical_cell_id.value = 0;
+
+        /*frame_parms[CC_id]->frame_type          = FDD;
+        frame_parms[CC_id]->tdd_config          = 3;
+        frame_parms[CC_id]->tdd_config_S        = 0;
+        frame_parms[CC_id]->N_RB_DL             = 100;
+        frame_parms[CC_id]->N_RB_UL             = 100;
+        frame_parms[CC_id]->Ncp                 = NORMAL;
+        frame_parms[CC_id]->Ncp_UL              = NORMAL;
+        frame_parms[CC_id]->Nid_cell            = 0;
+        //frame_parms[CC_id]->num_MBSFN_config    = 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;*/
+
+        ///frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
+        //frame_parms[CC_id]->phich_config_common.phich_duration = normal;
+        // UL RS Config
+        /*frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 1;//n_DMRS1 set to 0
+        frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 1;
+        frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
+        frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
+
+	frame_parms[CC_id]->pusch_config_common.n_SB = 1;
+	frame_parms[CC_id]->pusch_config_common.hoppingMode = 0;
+	frame_parms[CC_id]->pusch_config_common.pusch_HoppingOffset = 0;
+	frame_parms[CC_id]->pusch_config_common.enable64QAM = 0;
+		
+        frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
+        frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
+        frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
+        frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
+        frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;*/
+
+        // NR: Init to legacy LTE 20Mhz params
+        frame_parms[CC_id]->numerology_index	= 0;
+        frame_parms[CC_id]->ttis_per_subframe	= 1;
+        frame_parms[CC_id]->slots_per_tti		= 2;
+
+        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() {
+
+    int card;
+    int i;
+
+    for (card=0; card<MAX_CARDS; card++) {
+
+        openair0_cfg[card].mmapped_dma=mmapped_dma;
+        openair0_cfg[card].configFilename = NULL;
+
+        if(frame_parms[0]->N_RB_DL == 100) {
+	  if (numerology==0) {
+            if (frame_parms[0]->threequarter_fs) {
+                openair0_cfg[card].sample_rate=23.04e6;
+                openair0_cfg[card].samples_per_frame = 230400;
+                openair0_cfg[card].tx_bw = 10e6;
+                openair0_cfg[card].rx_bw = 10e6;
+            } else {
+                openair0_cfg[card].sample_rate=30.72e6;
+                openair0_cfg[card].samples_per_frame = 307200;
+                openair0_cfg[card].tx_bw = 10e6;
+                openair0_cfg[card].rx_bw = 10e6;
+            }
+	  } else if (numerology==1) {
+	    openair0_cfg[card].sample_rate=61.44e6;
+	    openair0_cfg[card].samples_per_frame = 307200;
+	    openair0_cfg[card].tx_bw = 20e6;
+	    openair0_cfg[card].rx_bw = 20e6;
+	  } else if (numerology==2) {
+	    openair0_cfg[card].sample_rate=122.88e6;
+	    openair0_cfg[card].samples_per_frame = 307200;
+	    openair0_cfg[card].tx_bw = 40e6;
+	    openair0_cfg[card].rx_bw = 40e6;
+	  } else {
+	    LOG_E(PHY,"Unsupported numerology!\n");
+	    exit(-1);
+	  }
+        } else if(frame_parms[0]->N_RB_DL == 50) {
+            openair0_cfg[card].sample_rate=15.36e6;
+            openair0_cfg[card].samples_per_frame = 153600;
+            openair0_cfg[card].tx_bw = 5e6;
+            openair0_cfg[card].rx_bw = 5e6;
+        } else if (frame_parms[0]->N_RB_DL == 25) {
+            openair0_cfg[card].sample_rate=7.68e6;
+            openair0_cfg[card].samples_per_frame = 76800;
+            openair0_cfg[card].tx_bw = 2.5e6;
+            openair0_cfg[card].rx_bw = 2.5e6;
+        } else if (frame_parms[0]->N_RB_DL == 6) {
+            openair0_cfg[card].sample_rate=1.92e6;
+            openair0_cfg[card].samples_per_frame = 19200;
+            openair0_cfg[card].tx_bw = 1.5e6;
+            openair0_cfg[card].rx_bw = 1.5e6;
+        }
+
+            if (frame_parms[0]->frame_type==TDD)
+              openair0_cfg[card].duplex_mode = duplex_mode_TDD;
+            else //FDD
+              openair0_cfg[card].duplex_mode = duplex_mode_FDD;
+
+            printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
+        	   PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx,
+        	   PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);
+            openair0_cfg[card].Mod_id = 0;
+
+            openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
+
+            openair0_cfg[card].clock_source = clock_source;
+
+
+            openair0_cfg[card].tx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx);
+            openair0_cfg[card].rx_num_channels=min(2,PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx);
+
+            for (i=0; i<4; i++) {
+
+              if (i<openair0_cfg[card].tx_num_channels)
+        	openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
+              else
+        	openair0_cfg[card].tx_freq[i]=0.0;
+
+              if (i<openair0_cfg[card].rx_num_channels)
+        	openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
+              else
+        	openair0_cfg[card].rx_freq[i]=0.0;
+
+              openair0_cfg[card].autocal[i] = 1;
+              openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
+              openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
+
+
+              openair0_cfg[card].configFilename = rf_config_file;
+              printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
+        	     card,i, openair0_cfg[card].tx_gain[i],
+        	     openair0_cfg[card].rx_gain[i],
+        	     openair0_cfg[card].tx_freq[i],
+        	     openair0_cfg[card].rx_freq[i]);
+            }
+
+
+  }
+}*/
+
+int main( int argc, char **argv ) {
+    int i,j,k,aa,re;
+#if defined (XFORMS)
+    void *status;
+#endif
+
+    int CC_id;
+    uint8_t  abstraction_flag=0;
+    uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
+
+#if defined (XFORMS)
+    int ret;
+#endif
+
+    start_background_system();
+
+#ifdef DEBUG_CONSOLE
+    setvbuf(stdout, NULL, _IONBF, 0);
+    setvbuf(stderr, NULL, _IONBF, 0);
+#endif
+
+    PHY_VARS_NR_UE *UE[MAX_NUM_CCs];
+
+    mode = normal_txrx;
+    memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
+
+    memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
+
+    set_latency_target();
+
+    // set default parameters
+    //set_default_frame_parms(frame_parms);
+
+    // initialize logging
+    logInit();
+
+    // get options and fill parameters from configuration file
+    get_options (argc, argv); //Command-line options, enb_properties
+
+#if T_TRACER
+    T_init(T_port, T_wait, T_dont_fork);
+#endif
+
+    // initialize the log (see log.h for details)
+    set_glog(glog_level, glog_verbosity);
+
+    //randominit (0);
+    set_taus_seed (0);
+
+    if (UE_flag==1) {
+        printf("configuring for UE\n");
+
+        set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
+        set_comp_log(PHY,     LOG_DEBUG,   LOG_HIGH, 1);
+        set_comp_log(MAC,     LOG_DEBUG,   LOG_HIGH, 1);
+        set_comp_log(RLC,     LOG_INFO,   LOG_HIGH | FLAG_THREAD, 1);
+        set_comp_log(PDCP,    LOG_INFO,   LOG_HIGH, 1);
+        set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
+        set_comp_log(RRC,     LOG_DEBUG,   LOG_HIGH, 1);
+#if defined(ENABLE_ITTI)
+        set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
+# if defined(ENABLE_USE_MME)
+        set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
+# endif
+#endif
+    }
+
+    if (ouput_vcd) {
+        if (UE_flag==1)
+            VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
+        else
+            VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
+    }
+
+    //if (opp_enabled ==1) {
+    //    reset_opp_meas();
+    //}
+    cpuf=get_cpu_freq_GHz();
+
+#if defined(ENABLE_ITTI)
+
+    if (UE_flag == 1) {
+        log_set_instance_type (LOG_INSTANCE_UE);
+    } else {
+        log_set_instance_type (LOG_INSTANCE_ENB);
+    }
+
+    itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
+
+    // initialize mscgen log after ITTI
+    MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
+#endif
+
+    if (opt_type != OPT_NONE) {
+        radio_type_t radio_type;
+
+        if (frame_parms[0]->frame_type == FDD)
+            radio_type = RADIO_TYPE_FDD;
+        else
+            radio_type = RADIO_TYPE_TDD;
+
+        if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
+            LOG_E(OPT,"failed to run OPT \n");
+    }
+
+#ifdef PDCP_USE_NETLINK
+    netlink_init();
+#if defined(PDCP_USE_NETLINK_QUEUES)
+    pdcp_netlink_init();
+#endif
+#endif
+
+#if !defined(ENABLE_ITTI)
+    // to make a graceful exit when ctrl-c is pressed
+    signal(SIGSEGV, signal_handler);
+    signal(SIGINT, signal_handler);
+#endif
+
+
+    check_clock();
+
+#ifndef PACKAGE_VERSION
+#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
+#endif
+
+  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);
+
+  // init the parameters
+  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+    if (UE_flag==1) {
+      frame_parms[CC_id]->nb_antennas_tx     = nb_antenna_tx;
+      frame_parms[CC_id]->nb_antennas_rx     = nb_antenna_rx;
+      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);
+    }
+
+    //init_ul_hopping(frame_parms[CC_id]);
+    //nr_init_frame_parms(frame_parms[CC_id],1);
+    //   phy_init_top(frame_parms[CC_id]);
+    //phy_init_lte_top(frame_parms[CC_id]);
+  }
+
+
+
+    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+        //init prach for openair1 test
+
+        // prach_fmt = get_prach_fmt(frame_parms->prach_config_common.prach_ConfigInfo.prach_ConfigIndex, frame_parms->frame_type);
+        // N_ZC = (prach_fmt <4)?839:139;
+    }
+
+    if (UE_flag==1) {
+        NB_UE_INST=1;
+        NB_INST=1;
+
+
+        PHY_vars_UE_g = malloc(sizeof(PHY_VARS_NR_UE**));
+        PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_NR_UE*)*MAX_NUM_CCs);
+
+        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+            //PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag);
+            UE[CC_id] = PHY_vars_UE_g[0][CC_id];
+            printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
+
+            if (phy_test==1)
+                UE[CC_id]->mac_enabled = 0;
+            else
+                UE[CC_id]->mac_enabled = 1;
+
+            if (UE[CC_id]->mac_enabled == 0) {  //set default UL parameters for testing mode
+                for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
+                    UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
+                    UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
+                    UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
+
+                    UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
+                    UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
+                    UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
+                }
+            }
+
+            UE[CC_id]->UE_scan = UE_scan;
+            UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
+            UE[CC_id]->mode    = mode;
+            printf("UE[%d]->mode = %d\n",CC_id,mode);
+
+            for (uint8_t i=0; i<RX_NB_TH_MAX; i++) {
+                UE[CC_id]->pdcch_vars[i][0]->agregationLevel = agregation_Level;
+                UE[CC_id]->pdcch_vars[i][0]->dciFormat     = dci_Format;
+            }
+
+            /*compute_prach_seq(&UE[CC_id]->frame_parms.prach_config_common,
+                              UE[CC_id]->frame_parms.frame_type,
+                              UE[CC_id]->X_u);*/
+
+            if (UE[CC_id]->mac_enabled == 1)
+            {
+                UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234;
+                UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234;
+            }
+            else
+            {
+                UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235;
+                UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235;
+            }
+
+            UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0] + rx_gain_off;
+            UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
+
+            if (frame_parms[CC_id]->frame_type==FDD) {
+                UE[CC_id]->N_TA_offset = 0;
+            } else {
+                if (frame_parms[CC_id]->N_RB_DL == 100)
+                    UE[CC_id]->N_TA_offset = 624;
+                else if (frame_parms[CC_id]->N_RB_DL == 50)
+                    UE[CC_id]->N_TA_offset = 624/2;
+                else if (frame_parms[CC_id]->N_RB_DL == 25)
+                    UE[CC_id]->N_TA_offset = 624/4;
+            }
+
+        }
+
+        //  printf("tx_max_power = %d -> amp %d\n",tx_max_power,get_tx_amp(tx_max_poHwer,tx_max_power));
+    }
+
+    fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
+    cpuf=get_cpu_freq_GHz();
+
+
+    //dump_frame_parms(frame_parms[0]);
+
+    //init_openair0();
+
+
+
+#ifndef DEADLINE_SCHEDULER
+
+    /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
+
+    cpu_set_t cpuset;
+    int s;
+    char cpu_affinity[1024];
+    CPU_ZERO(&cpuset);
+#ifdef CPU_AFFINITY
+    if (get_nprocs() > 2) {
+        CPU_SET(0, &cpuset);
+        s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+        if (s != 0) {
+            perror( "pthread_setaffinity_np");
+            exit_fun("Error setting processor affinity");
+        }
+        LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
+    }
+#endif
+
+    /* Check the actual affinity mask assigned to the thread */
+    s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
+    if (s != 0) {
+        perror( "pthread_getaffinity_np");
+        exit_fun("Error getting processor affinity ");
+    }
+    memset(cpu_affinity, 0 , sizeof(cpu_affinity));
+    for (int j = 0; j < CPU_SETSIZE; j++) {
+        if (CPU_ISSET(j, &cpuset)) {
+            char temp[1024];
+            sprintf(temp, " CPU_%d ", j);
+            strcat(cpu_affinity, temp);
+        }
+    }
+    LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
+#endif
+
+    openair0_cfg[0].log_level = glog_level;
+
+
+
+
+    /*int eMBMS_active=0;
+    if (node_function[0] <= NGFI_RAU_IF4p5) { // don't initialize L2 for RRU
+        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
+        mac_xface->macphy_exit = &exit_fun;
+    } else if (node_function[0] == NGFI_RRU_IF4p5) { // Initialize PRACH in this case
+
+    }*/
+
+
+
+#if defined(ENABLE_ITTI)
+
+        // don't create if node doesn't connect to RRC/S1/GTP
+        /*if (create_tasks(1) < 0) {
+            printf("cannot create ITTI tasks\n");
+            exit(-1); // need a softer mode
+        }*/
+
+    printf("ITTI tasks created\n");
+#endif
+
+    /*if (phy_test==0) {
+        if (UE_flag==1) {
+            printf("Filling UE band info\n");
+            fill_ue_band_info();
+            mac_xface->dl_phy_sync_success (0, 0, 0, 1);
+        } else if (node_function[0]>NGFI_RRU_IF4p5)
+            mac_xface->mrbch_phy_sync_failure (0, 0, 0);
+    }*/
+
+
+
+    mlockall(MCL_CURRENT | MCL_FUTURE);
+
+    pthread_cond_init(&sync_cond,NULL);
+    pthread_mutex_init(&sync_mutex, NULL);
+
+#ifdef XFORMS
+    int UE_id;
+
+    if (do_forms==1) {
+        fl_initialize (&argc, argv, NULL, 0, 0);
+
+        if (UE_flag==1) {
+            //form_stats = create_form_stats_form();
+            //fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
+            UE_id = 0;
+            form_ue[UE_id] = create_lte_phy_scope_ue();
+            sprintf (title, "LTE DL SCOPE UE");
+            fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
+
+            /*
+            if (openair_daq_vars.use_ia_receiver) {
+                   fl_set_button(form_ue[UE_id]->button_0,1);
+                   fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON");
+            } else {
+                   fl_set_button(form_ue[UE_id]->button_0,0);
+                   fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
+            }*/
+            fl_set_button(form_ue[UE_id]->button_0,0);
+            fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
+        }
+
+        ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
+
+        if (ret == 0)
+            pthread_setname_np( forms_thread, "xforms" );
+
+        printf("Scope thread created, ret=%d\n",ret);
+    }
+
+#endif
+
+    rt_sleep_ns(10*100000000ULL);
+
+
+
+    // start the main thread
+    if (UE_flag == 1) {
+        init_UE(1);
+        number_of_cards = 1;
+
+        for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+            PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
+            PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
+        }
+    }
+
+    // connect the TX/RX buffers
+    if (UE_flag==1) {
+
+        for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+
+
+#if defined(OAI_USRP) || defined(OAI_ADRV9371_ZC706)
+            UE[CC_id]->hw_timing_advance = timing_advance;
+#else
+            UE[CC_id]->hw_timing_advance = 160;
+#endif
+        }
+        if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) {
+            printf("Error setting up eNB buffer\n");
+            exit(-1);
+        }
+
+
+
+        if (input_fd) {
+            printf("Reading in from file to antenna buffer %d\n",0);
+            if (fread(UE[0]->common_vars.rxdata[0],
+                      sizeof(int32_t),
+                      frame_parms[0]->samples_per_subframe*10,
+                      input_fd) != frame_parms[0]->samples_per_subframe*10)
+                printf("error reading from file\n");
+        }
+        //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
+    }
+    sleep(3);
+
+
+    printf("Sending sync to all threads\n");
+
+    pthread_mutex_lock(&sync_mutex);
+    sync_var=0;
+    pthread_cond_broadcast(&sync_cond);
+    pthread_mutex_unlock(&sync_mutex);
+
+    // wait for end of program
+    printf("TYPE <CTRL-C> TO TERMINATE\n");
+    //getchar();
+
+#if defined(ENABLE_ITTI)
+    printf("Entering ITTI signals handler\n");
+    itti_wait_tasks_end();
+    oai_exit=1;
+#else
+
+    while (oai_exit==0)
+        rt_sleep_ns(100000000ULL);
+
+#endif
+
+    // stop threads
+#ifdef XFORMS
+    printf("waiting for XFORMS thread\n");
+
+    if (do_forms==1) {
+        pthread_join(forms_thread,&status);
+        fl_hide_form(form_stats->stats_form);
+        fl_free_form(form_stats->stats_form);
+
+        if (UE_flag==1) {
+            fl_hide_form(form_ue[0]->lte_phy_scope_ue);
+            fl_free_form(form_ue[0]->lte_phy_scope_ue);
+        } else {
+            fl_hide_form(form_stats_l2->stats_form);
+            fl_free_form(form_stats_l2->stats_form);
+
+            for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
+                for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
+                    fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
+                    fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
+                }
+            }
+        }
+    }
+
+#endif
+
+    printf("stopping MODEM threads\n");
+
+    // cleanup
+    if (UE_flag == 1) {
+    } else {
+    //    stop_eNB(1);
+    }
+
+
+    pthread_cond_destroy(&sync_cond);
+    pthread_mutex_destroy(&sync_mutex);
+
+
+    // *** Handle per CC_id openair0
+    if (UE_flag==1) {
+        if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func)
+            PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice);
+    }
+    if (ouput_vcd)
+        VCD_SIGNAL_DUMPER_CLOSE();
+
+    if (opt_enabled == 1)
+        terminate_opt();
+
+    logClean();
+
+    return 0;
+}
diff --git a/targets/RT/USER/nr-uesoftmodem.h b/targets/RT/USER/nr-uesoftmodem.h
new file mode 100644
index 0000000000000000000000000000000000000000..64c7b9ea5c26cecf16f98fffc66f1bb9ecea6e83
--- /dev/null
+++ b/targets/RT/USER/nr-uesoftmodem.h
@@ -0,0 +1,83 @@
+#ifndef NR_UESOFTMODEM_H
+#define NR_UESOFTMODEM_H
+
+#define _GNU_SOURCE
+#include <execinfo.h>
+#include <fcntl.h>
+#include <getopt.h>
+#include <linux/sched.h>
+#include "rt_wrapper.h"
+#include <sched.h>
+#include <signal.h>
+#include <stdint.h>
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <syscall.h>
+#include <sys/ioctl.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <sys/sysinfo.h>
+#include <sys/types.h>
+#include <unistd.h>
+
+#include <sys/sysinfo.h>
+#include "rt_wrapper.h"
+#include "../../ARCH/COMMON/common_lib.h"
+#undef MALLOC
+#include "assertions.h"
+#include "msc.h"
+#include "PHY/types.h"
+#include "PHY/defs_nr_UE.h"
+#include "SIMULATION/ETH_TRANSPORT/proto.h"
+
+#if defined(ENABLE_ITTI)
+#if defined(ENABLE_USE_MME)
+#include "s1ap_eNB.h"
+#ifdef PDCP_USE_NETLINK
+#include "SIMULATION/ETH_TRANSPORT/proto.h"
+#endif
+#endif
+#endif
+
+extern pthread_cond_t sync_cond;
+extern pthread_mutex_t sync_mutex;
+extern int sync_var;
+
+
+extern uint32_t          downlink_frequency[MAX_NUM_CCs][4];
+extern int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];
+
+extern int rx_input_level_dBm;
+extern uint8_t exit_missed_slots;
+extern uint64_t num_missed_slots; // counter for the number of missed slots
+
+extern int oaisim_flag;
+extern volatile int  oai_exit;
+
+extern openair0_config_t openair0_cfg[MAX_CARDS];
+extern pthread_cond_t sync_cond;
+extern pthread_mutex_t sync_mutex;
+extern int sync_var;
+extern int transmission_mode;
+extern double cpuf;
+
+#if defined(ENABLE_ITTI)
+extern volatile int             start_eNB;
+extern volatile int             start_UE;
+#endif
+
+#include "threads_t.h"
+extern threads_t threads;
+
+extern void exit_fun(const char* s);
+
+// In nr-ue.c
+extern int setup_ue_buffers(PHY_VARS_NR_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
+extern void fill_ue_band_info(void);
+extern void init_UE(int);
+extern void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name);
+extern void reset_opp_meas(void);
+extern void print_opp_meas(void);
+
+#endif