diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index c9741ce4884ed7a0918fe8d84066cc2a2fcdae9f..10f263100b884e852da089ed946b4f3467b99722 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -2090,9 +2090,9 @@ target_link_libraries (lte-softmodem
   -Wl,--end-group z dl)
 
 
-add_executable(simple-softmodem
+add_executable(ocp-softmodem
   ${OPENAIR_TARGETS}/RT/USER/rt_wrapper.c
-  ${OPENAIR_DIR}/executables/simple_main.c
+  ${OPENAIR_DIR}/executables/main-ocp.c
   ${OPENAIR_TARGETS}/RT/USER/lte-softmodem.c
   ${OPENAIR_TARGETS}/RT/USER/lte-softmodem-common.c
   ${OPENAIR2_DIR}/ENB_APP/NB_IoT_interface.c
@@ -2113,15 +2113,15 @@ add_executable(simple-softmodem
   ${CONFIG_SOURCES}
   ${SHLIB_LOADER_SOURCES}
   )
-add_dependencies(simple-softmodem rrc_flag s1ap_flag x2_flag)
+add_dependencies(ocp-softmodem rrc_flag s1ap_flag x2_flag)
 
-target_link_libraries (simple-softmodem
+target_link_libraries (ocp-softmodem
   -Wl,--start-group
   RRC_LIB S1AP_LIB S1AP_ENB F1AP_LIB F1AP X2AP_LIB X2AP_ENB GTPV1U SECU_CN SECU_OSA UTIL HASHTABLE SCTP_CLIENT UDP SCHED_LIB SCHED_RU_LIB PHY_COMMON PHY PHY_RU LFDS L2
   ${MSC_LIB} ${RAL_LIB} ${NAS_UE_LIB} ${ITTI_LIB} ${FLPT_MSG_LIB} ${ASYNC_IF_LIB} ${FLEXRAN_AGENT_LIB} ${FSPT_MSG_LIB} ${PROTO_AGENT_LIB} LFDS7
   NFAPI_COMMON_LIB NFAPI_LIB NFAPI_VNF_LIB NFAPI_PNF_LIB NFAPI_USER_LIB
   -Wl,--end-group z dl)
-target_link_libraries (simple-softmodem ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB}  ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB})
+target_link_libraries (ocp-softmodem ${LIBXML2_LIBRARIES} pthread m ${CONFIG_LIBRARIES} rt crypt ${CRYPTO_LIBRARIES} ${OPENSSL_LIBRARIES} ${NETTLE_LIBRARIES} sctp ${PROTOBUF_LIB}  ${CMAKE_DL_LIBS} ${LIBYAML_LIBRARIES} ${LIB_LMS_LIBRARIES} ${T_LIB})
 
 add_executable(cu_test
   ${OPENAIR2_DIR}/LAYER2/PROTO_AGENT/cu_test.c
diff --git a/executables/simple_main.c b/executables/main-ocp.c
similarity index 95%
rename from executables/simple_main.c
rename to executables/main-ocp.c
index 7a15f6df3caab88cf8ec2bc5f3f7e7eaaaab6d5c..b3472f17cb27f94e5afa451de3d53bfee732f64b 100644
--- a/executables/simple_main.c
+++ b/executables/main-ocp.c
@@ -50,9 +50,6 @@ void init_eNB_proc(int inst) {
     proc->CC_id                    = CC_id;
     proc->first_rx                 =1;
     proc->first_tx                 =1;
-    proc->RU_mask_tx               = (1<<eNB->num_RU)-1;
-    proc->RU_mask                  =0;
-    proc->RU_mask_prach            =0;
     pthread_mutex_init( &eNB->UL_INFO_mutex, NULL);
     pthread_mutex_init( &L1_proc->mutex, NULL);
     pthread_cond_init( &L1_proc->cond, NULL);
@@ -94,102 +91,12 @@ void init_RU_proc(RU_t *ru) {
   for (i=0; i<10; i++) proc->symbol_mask[i]=0;
 
   pthread_mutex_init( &proc->mutex_synch,NULL);
-
   pthread_cond_init( &proc->cond_synch,NULL);
   pthread_cond_init( &proc->cond_eNBs, NULL);
-
   pthread_t t;
   threadCreate(&t,  ru_thread, (void *)ru, "MainRu", -1, OAI_PRIORITY_RT_MAX);
 }
 
-void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
-  L1_proc_t *proc = &eNB->proc;
-  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
-
-  // check if we have to detect PRACH first
-  if (is_prach_subframe(fp,frame,subframe)>0) {
-    // set timing for prach thread
-    proc->frame_prach = frame;
-    proc->subframe_prach = subframe;
-    prach_procedures(eNB,0);
-  }
-}
-
-void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
-  L1_proc_t *proc = &eNB->proc;
-  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
-
-  // check if we have to detect PRACH first
-  if (is_prach_subframe(fp,frame,subframe)>0) {
-    LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe);
-    // set timing for prach thread
-    proc->frame_prach_br = frame;
-    proc->subframe_prach_br = subframe;
-    prach_procedures(eNB,1);
-  }
-}
-
-static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) {
-
-  AssertFatal( eNB !=NULL, "");
-
-  if (NFAPI_MODE==NFAPI_MODE_PNF) {
-    // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
-    //add_subframe(&frame, &subframe, 4);
-    //oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
-    oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
-  }
-
-  AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF &&
-		 eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), "");
-  
-  wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
-  wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
-  release_UE_in_freeList(eNB->Mod_id);
-
-  // UE-specific RX processing for subframe n
-  if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
-    phy_procedures_eNB_uespec_RX(eNB, proc);
-  }
-
-  pthread_mutex_lock(&eNB->UL_INFO_mutex);
-  eNB->UL_INFO.frame     = proc->frame_rx;
-  eNB->UL_INFO.subframe  = proc->subframe_rx;
-  eNB->UL_INFO.module_id = eNB->Mod_id;
-  eNB->UL_INFO.CC_id     = eNB->CC_id;
-  eNB->if_inst->UL_indication(&eNB->UL_INFO);
-  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
-  phy_procedures_eNB_TX(eNB, proc, 1);
-  
-  return(0);
-}
-
-void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru) {
-  L1_proc_t *proc           = &eNB->proc;
-  L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
-  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
-  RU_proc_t *ru_proc=&ru->proc;
-  proc->frame_rx    = frame_rx;
-  proc->subframe_rx = subframe_rx;
-
-  if (!oai_exit) {
-    L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
-    L1_proc->frame_rx     = ru_proc->frame_rx;
-    L1_proc->subframe_rx  = ru_proc->subframe_rx;
-    L1_proc->frame_tx     = (L1_proc->subframe_rx > (9-sf_ahead)) ?
-      (L1_proc->frame_rx+1)&1023 :
-      L1_proc->frame_rx;
-    L1_proc->subframe_tx  = (L1_proc->subframe_rx + sf_ahead)%10;
-
-    if (rxtx(eNB,L1_proc,string) < 0)
-      LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id);
-
-    ru_proc->timestamp_tx = L1_proc->timestamp_tx;
-    ru_proc->subframe_tx  = L1_proc->subframe_tx;
-    ru_proc->frame_tx     = L1_proc->frame_tx;
-  }
-}
-
 void init_transport(PHY_VARS_eNB *eNB) {
   int i;
   int j;
@@ -354,129 +261,6 @@ void stop_eNB(int nb_inst) {
     kill_eNB_proc(inst);
   }
 }
-
-void rx_rf(RU_t *ru,int *frame,int *subframe) {
-  RU_proc_t *proc = &ru->proc;
-  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
-  void *rxp[ru->nb_rx];
-  unsigned int rxs;
-  int i;
-  openair0_timestamp ts=0,old_ts=0;
-
-  for (i=0; i<ru->nb_rx; i++)
-    rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
-
-  old_ts = proc->timestamp_rx;
-  rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
-                                   &ts,
-                                   rxp,
-                                   fp->samples_per_tti,
-                                   ru->nb_rx);
-  proc->timestamp_rx = ts-ru->ts_offset;
-
-  //  AssertFatal(rxs == fp->samples_per_tti,
-  //        "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
-  if(rxs != fp->samples_per_tti) {
-    LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
-  }
-
-  if (proc->first_rx == 1) {
-    ru->ts_offset = proc->timestamp_rx;
-    proc->timestamp_rx = 0;
-  } else {
-    if (proc->timestamp_rx - old_ts != fp->samples_per_tti) {
-      ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti);
-      proc->timestamp_rx = ts-ru->ts_offset;
-    }
-  }
-
-  proc->frame_rx     = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
-  proc->subframe_rx  = (proc->timestamp_rx / fp->samples_per_tti)%10;
-  // synchronize first reception to frame 0 subframe 0
-  proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
-  proc->subframe_tx  = (proc->subframe_rx+sf_ahead)%10;
-  proc->frame_tx     = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
-
-  if (proc->first_rx == 0) {
-    AssertFatal( proc->subframe_rx == *subframe && proc->frame_rx == *frame ,
-		 "Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d) (proc->frame_rx %d frame %d)\n",
-		 (long long unsigned int)proc->timestamp_rx,proc->subframe_rx,*subframe, proc->frame_rx,*frame);
-  } else {
-    proc->first_rx = 0;
-    *frame = proc->frame_rx;
-    *subframe = proc->subframe_rx;
-  }
-
-  if (rxs != fp->samples_per_tti) {
-#if defined(USRP_REC_PLAY)
-    exit_fun("Exiting IQ record/playback");
-#else
-    //exit_fun( "problem receiving samples" );
-    LOG_E(PHY, "problem receiving samples");
-#endif
-  }
-}
-
-void tx_rf(RU_t *ru) {
-  RU_proc_t *proc = &ru->proc;
-  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
-  void *txp[ru->nb_tx];
-  int i;
-  lte_subframe_t SF_type     = subframe_select(fp,proc->subframe_tx%10);
-  lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10);
-  int sf_extension = 0;
-
-  if ((SF_type == SF_DL) ||
-      (SF_type == SF_S)) {
-    int siglen=fp->samples_per_tti,flags=1;
-
-    if (SF_type == SF_S) {
-      /* end_of_burst_delay is used to stop TX only "after a while".
-       * If we stop right after effective signal, with USRP B210 and
-       * B200mini, we observe a high EVM on the S subframe (on the
-       * PSS).
-       * A value of 400 (for 30.72MHz) solves this issue. This is
-       * the default.
-       */
-      siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)
-               + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples)
-               + ru->end_of_burst_delay;
-      flags=3; // end of burst
-    }
-
-    if (fp->frame_type == TDD &&
-        SF_type == SF_DL &&
-        prevSF_type == SF_UL) {
-      flags = 2; // start of burst
-      sf_extension = ru->sf_extension;
-    }
-
-#if defined(__x86_64) || defined(__i386__)
-#ifdef __AVX2__
-    sf_extension = (sf_extension)&0xfffffff8;
-#else
-    sf_extension = (sf_extension)&0xfffffffc;
-#endif
-#elif defined(__arm__)
-    sf_extension = (sf_extension)&0xfffffffc;
-#endif
-
-    for (i=0; i<ru->nb_tx; i++)
-      txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension];
-
-    /* add fail safe for late command end */
-    // prepare tx buffer pointers
-    ru->rfdevice.trx_write_func(&ru->rfdevice,
-                                      proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
-                                      txp,
-                                      siglen+sf_extension,
-                                      ru->nb_tx,
-                                      flags);
-    LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
-          (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx);
-  }
-}
-
 // this is for RU with local RF unit
 void fill_rf_config(RU_t *ru, char *rf_config_file) {
   int i;
@@ -642,6 +426,247 @@ int setup_RU_buffers(RU_t *ru) {
   return(0);
 }
 
+
+void init_precoding_weights(PHY_VARS_eNB *eNB) {
+  int layer,ru_id,aa,re,ue,tb;
+  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
+  RU_t *ru;
+  LTE_eNB_DLSCH_t *dlsch;
+
+  // init precoding weigths
+  for (ue=0; ue<NUMBER_OF_UE_MAX; ue++) {
+    for (tb=0; tb<2; tb++) {
+      dlsch = eNB->dlsch[ue][tb];
+
+      for (layer=0; layer<4; layer++) {
+        int nb_tx=0;
+
+        for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
+          ru = RC.ru[ru_id];
+          nb_tx+=ru->nb_tx;
+        }
+
+        dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *));
+
+        for (aa=0; aa<nb_tx; aa++) {
+          dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t));
+
+          for (re=0; re<fp->ofdm_symbol_size; re++) {
+            dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
+          }
+        }
+      }
+    }
+  }
+}
+
+void wakeup_prach_eNB(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
+  L1_proc_t *proc = &eNB->proc;
+  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
+
+  // check if we have to detect PRACH first
+  if (is_prach_subframe(fp,frame,subframe)>0) {
+    // set timing for prach thread
+    proc->frame_prach = frame;
+    proc->subframe_prach = subframe;
+    prach_procedures(eNB,0);
+  }
+}
+
+void wakeup_prach_eNB_br(PHY_VARS_eNB *eNB,RU_t *ru,int frame,int subframe) {
+  L1_proc_t *proc = &eNB->proc;
+  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
+
+  // check if we have to detect PRACH first
+  if (is_prach_subframe(fp,frame,subframe)>0) {
+    LOG_D(PHY,"Triggering prach br processing, frame %d, subframe %d\n",frame,subframe);
+    // set timing for prach thread
+    proc->frame_prach_br = frame;
+    proc->subframe_prach_br = subframe;
+    prach_procedures(eNB,1);
+  }
+}
+
+static inline int rxtx(PHY_VARS_eNB *eNB,L1_rxtx_proc_t *proc, char *thread_name) {
+  AssertFatal( eNB !=NULL, "");
+
+  if (NFAPI_MODE==NFAPI_MODE_PNF) {
+    // I am a PNF and I need to let nFAPI know that we have a (sub)frame tick
+    //add_subframe(&frame, &subframe, 4);
+    //oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
+    oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
+  }
+
+  AssertFatal( !(NFAPI_MODE==NFAPI_MODE_PNF &&
+                 eNB->pdcch_vars[proc->subframe_tx&1].num_pdcch_symbols == 0), "");
+  wakeup_prach_eNB(eNB,NULL,proc->frame_rx,proc->subframe_rx);
+  wakeup_prach_eNB_br(eNB,NULL,proc->frame_rx,proc->subframe_rx);
+  release_UE_in_freeList(eNB->Mod_id);
+
+  // UE-specific RX processing for subframe n
+  if (NFAPI_MODE==NFAPI_MONOLITHIC || NFAPI_MODE==NFAPI_MODE_PNF) {
+    phy_procedures_eNB_uespec_RX(eNB, proc);
+  }
+
+  pthread_mutex_lock(&eNB->UL_INFO_mutex);
+  eNB->UL_INFO.frame     = proc->frame_rx;
+  eNB->UL_INFO.subframe  = proc->subframe_rx;
+  eNB->UL_INFO.module_id = eNB->Mod_id;
+  eNB->UL_INFO.CC_id     = eNB->CC_id;
+  eNB->if_inst->UL_indication(&eNB->UL_INFO);
+  pthread_mutex_unlock(&eNB->UL_INFO_mutex);
+  phy_procedures_eNB_TX(eNB, proc, 1);
+  return(0);
+}
+
+void eNB_top(PHY_VARS_eNB *eNB, int frame_rx, int subframe_rx, char *string,RU_t *ru) {
+  L1_proc_t *proc           = &eNB->proc;
+  L1_rxtx_proc_t *L1_proc = &proc->L1_proc;
+  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
+  RU_proc_t *ru_proc=&ru->proc;
+  proc->frame_rx    = frame_rx;
+  proc->subframe_rx = subframe_rx;
+
+  if (!oai_exit) {
+    L1_proc->timestamp_tx = ru_proc->timestamp_rx + (sf_ahead*fp->samples_per_tti);
+    L1_proc->frame_rx     = ru_proc->frame_rx;
+    L1_proc->subframe_rx  = ru_proc->subframe_rx;
+    L1_proc->frame_tx     = (L1_proc->subframe_rx > (9-sf_ahead)) ?
+                            (L1_proc->frame_rx+1)&1023 :
+                            L1_proc->frame_rx;
+    L1_proc->subframe_tx  = (L1_proc->subframe_rx + sf_ahead)%10;
+
+    if (rxtx(eNB,L1_proc,string) < 0)
+      LOG_E(PHY,"eNB %d CC_id %d failed during execution\n",eNB->Mod_id,eNB->CC_id);
+
+    ru_proc->timestamp_tx = L1_proc->timestamp_tx;
+    ru_proc->subframe_tx  = L1_proc->subframe_tx;
+    ru_proc->frame_tx     = L1_proc->frame_tx;
+  }
+}
+
+void rx_rf(RU_t *ru,int *frame,int *subframe) {
+  RU_proc_t *proc = &ru->proc;
+  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
+  void *rxp[ru->nb_rx];
+  unsigned int rxs;
+  int i;
+  openair0_timestamp ts=0,old_ts=0;
+
+  for (i=0; i<ru->nb_rx; i++)
+    rxp[i] = (void *)&ru->common.rxdata[i][*subframe*fp->samples_per_tti];
+
+  old_ts = proc->timestamp_rx;
+  rxs = ru->rfdevice.trx_read_func(&ru->rfdevice,
+                                   &ts,
+                                   rxp,
+                                   fp->samples_per_tti,
+                                   ru->nb_rx);
+  proc->timestamp_rx = ts-ru->ts_offset;
+
+  //  AssertFatal(rxs == fp->samples_per_tti,
+  //        "rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
+  if(rxs != fp->samples_per_tti) {
+    LOG_E(PHY,"rx_rf: Asked for %d samples, got %d from SDR\n",fp->samples_per_tti,rxs);
+  }
+
+  if (proc->first_rx == 1) {
+    ru->ts_offset = proc->timestamp_rx;
+    proc->timestamp_rx = 0;
+  } else {
+    if (proc->timestamp_rx - old_ts != fp->samples_per_tti) {
+      ru->ts_offset += (proc->timestamp_rx - old_ts - fp->samples_per_tti);
+      proc->timestamp_rx = ts-ru->ts_offset;
+    }
+  }
+
+  proc->frame_rx     = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
+  proc->subframe_rx  = (proc->timestamp_rx / fp->samples_per_tti)%10;
+  // synchronize first reception to frame 0 subframe 0
+  proc->timestamp_tx = proc->timestamp_rx+(sf_ahead*fp->samples_per_tti);
+  proc->subframe_tx  = (proc->subframe_rx+sf_ahead)%10;
+  proc->frame_tx     = (proc->subframe_rx>(9-sf_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
+
+  if (proc->first_rx == 0) {
+    AssertFatal( proc->subframe_rx == *subframe && proc->frame_rx == *frame,
+                 "Received Timestamp (%llu) doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d) (proc->frame_rx %d frame %d)\n",
+                 (long long unsigned int)proc->timestamp_rx,proc->subframe_rx,*subframe, proc->frame_rx,*frame);
+  } else {
+    proc->first_rx = 0;
+    *frame = proc->frame_rx;
+    *subframe = proc->subframe_rx;
+  }
+
+  if (rxs != fp->samples_per_tti) {
+#if defined(USRP_REC_PLAY)
+    exit_fun("Exiting IQ record/playback");
+#else
+    //exit_fun( "problem receiving samples" );
+    LOG_E(PHY, "problem receiving samples");
+#endif
+  }
+}
+
+void tx_rf(RU_t *ru) {
+  RU_proc_t *proc = &ru->proc;
+  LTE_DL_FRAME_PARMS *fp = &ru->frame_parms;
+  void *txp[ru->nb_tx];
+  int i;
+  lte_subframe_t SF_type     = subframe_select(fp,proc->subframe_tx%10);
+  lte_subframe_t prevSF_type = subframe_select(fp,(proc->subframe_tx+9)%10);
+  int sf_extension = 0;
+
+  if ((SF_type == SF_DL) ||
+      (SF_type == SF_S)) {
+    int siglen=fp->samples_per_tti,flags=1;
+
+    if (SF_type == SF_S) {
+      /* end_of_burst_delay is used to stop TX only "after a while".
+       * If we stop right after effective signal, with USRP B210 and
+       * B200mini, we observe a high EVM on the S subframe (on the
+       * PSS).
+       * A value of 400 (for 30.72MHz) solves this issue. This is
+       * the default.
+       */
+      siglen = (fp->ofdm_symbol_size + fp->nb_prefix_samples0)
+               + (fp->dl_symbols_in_S_subframe - 1) * (fp->ofdm_symbol_size + fp->nb_prefix_samples)
+               + ru->end_of_burst_delay;
+      flags=3; // end of burst
+    }
+
+    if (fp->frame_type == TDD &&
+        SF_type == SF_DL &&
+        prevSF_type == SF_UL) {
+      flags = 2; // start of burst
+      sf_extension = ru->sf_extension;
+    }
+
+#if defined(__x86_64) || defined(__i386__)
+#ifdef __AVX2__
+    sf_extension = (sf_extension)&0xfffffff8;
+#else
+    sf_extension = (sf_extension)&0xfffffffc;
+#endif
+#elif defined(__arm__)
+    sf_extension = (sf_extension)&0xfffffffc;
+#endif
+
+    for (i=0; i<ru->nb_tx; i++)
+      txp[i] = (void *)&ru->common.txdata[i][(proc->subframe_tx*fp->samples_per_tti)-sf_extension];
+
+    /* add fail safe for late command end */
+    // prepare tx buffer pointers
+    ru->rfdevice.trx_write_func(&ru->rfdevice,
+                                proc->timestamp_tx+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
+                                txp,
+                                siglen+sf_extension,
+                                ru->nb_tx,
+                                flags);
+    LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
+          (long long unsigned int)proc->timestamp_tx,proc->frame_tx,proc->frame_tx_unwrap,proc->subframe_tx);
+  }
+}
+
 static void *ru_thread( void *param ) {
   static int ru_thread_status;
   RU_t               *ru      = (RU_t *)param;
@@ -664,10 +689,6 @@ static void *ru_thread( void *param ) {
   }
 
   LOG_I(PHY, "Signaling main thread that RU %d is ready\n",ru->idx);
-  pthread_mutex_lock(&RC.ru_mutex);
-  RC.ru_mask &= ~(1<<ru->idx);
-  pthread_cond_signal(&RC.ru_cond);
-  pthread_mutex_unlock(&RC.ru_mutex);
   wait_sync("ru_thread");
 
   // Start RF device if any
@@ -745,41 +766,7 @@ int stop_rf(RU_t *ru) {
   return 0;
 }
 
-void init_precoding_weights(PHY_VARS_eNB *eNB) {
-  int layer,ru_id,aa,re,ue,tb;
-  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
-  RU_t *ru;
-  LTE_eNB_DLSCH_t *dlsch;
-
-  // init precoding weigths
-  for (ue=0; ue<NUMBER_OF_UE_MAX; ue++) {
-    for (tb=0; tb<2; tb++) {
-      dlsch = eNB->dlsch[ue][tb];
-
-      for (layer=0; layer<4; layer++) {
-        int nb_tx=0;
-
-        for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
-          ru = RC.ru[ru_id];
-          nb_tx+=ru->nb_tx;
-        }
-
-        dlsch->ue_spec_bf_weights[layer] = (int32_t **)malloc16(nb_tx*sizeof(int32_t *));
-
-        for (aa=0; aa<nb_tx; aa++) {
-          dlsch->ue_spec_bf_weights[layer][aa] = (int32_t *)malloc16(fp->ofdm_symbol_size*sizeof(int32_t));
-
-          for (re=0; re<fp->ofdm_symbol_size; re++) {
-            dlsch->ue_spec_bf_weights[layer][aa][re] = 0x00007fff;
-          }
-        }
-      }
-    }
-  }
-}
-
 void set_function_spec_param(RU_t *ru) {
-
   switch (ru->if_south) {
     case LOCAL_RF: { // this is an RU with integrated RF (RRU, eNB)
       ru->do_prach             = 0;                       // no prach processing in RU
@@ -819,21 +806,20 @@ void set_function_spec_param(RU_t *ru) {
 
 //extern void RCconfig_RU(void);
 
-void init_RU(char *rf_config_file) {
+void init_RU(char *rf_config_file, clock_source_t clock_source,clock_source_t time_source,int send_dmrssync) {
   int ru_id;
   RU_t *ru;
   PHY_VARS_eNB *eNB0= (PHY_VARS_eNB *)NULL;
   int i;
   int CC_id;
   // create status mask
-  RC.ru_mask = 0;
   pthread_mutex_init(&RC.ru_mutex,NULL);
   pthread_cond_init(&RC.ru_cond,NULL);
   // read in configuration file)
   printf("configuring RU from file\n");
   RCconfig_RU();
   LOG_I(PHY,"number of L1 instances %d, number of RU %d, number of CPU cores %d\n",
-	RC.nb_L1_inst,RC.nb_RU,get_nprocs());
+        RC.nb_L1_inst,RC.nb_RU,get_nprocs());
 
   if (RC.nb_CC != 0)
     for (i=0; i<RC.nb_L1_inst; i++)
@@ -847,16 +833,38 @@ void init_RU(char *rf_config_file) {
     ru->rf_config_file = rf_config_file;
     ru->idx          = ru_id;
     ru->ts_offset    = 0;
+
+    if (ru->is_slave == 1) {
+      ru->in_synch    = 0;
+      ru->generate_dmrs_sync = 0;
+    } else {
+      ru->in_synch    = 1;
+      ru->generate_dmrs_sync=send_dmrssync;
+    }
+
+    ru->cmd      = EMPTY;
+    ru->south_out_cnt= 0;
     // use eNB_list[0] as a reference for RU frame parameters
     // NOTE: multiple CC_id are not handled here yet!
+    ru->openair0_cfg.clock_source  = clock_source;
+    ru->openair0_cfg.time_source = time_source;
+
+    //    ru->generate_dmrs_sync = (ru->is_slave == 0) ? 1 : 0;
+    if (ru->generate_dmrs_sync == 1) {
+      generate_ul_ref_sigs();
+      ru->dmrssync = (int16_t *)malloc16_clear(ru->frame_parms.ofdm_symbol_size*2*sizeof(int16_t));
+    }
+
+    ru->wakeup_L1_sleeptime = 2000;
+    ru->wakeup_L1_sleep_cnt_max  = 3;
 
     if (ru->num_eNB > 0) {
       LOG_D(PHY, "%s() RC.ru[%d].num_eNB:%d ru->eNB_list[0]:%p RC.eNB[0][0]:%p rf_config_file:%s\n",
-	    __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file);
+            __FUNCTION__, ru_id, ru->num_eNB, ru->eNB_list[0], RC.eNB[0][0], ru->rf_config_file);
 
       if (ru->eNB_list[0] == 0) {
         LOG_E(PHY,"%s() DJP - ru->eNB_list ru->num_eNB are not initialized - so do it manually\n",
-	      __FUNCTION__);
+              __FUNCTION__);
         ru->eNB_list[0] = RC.eNB[0][0];
         ru->num_eNB=1;
         //
@@ -916,8 +924,6 @@ void RCconfig_RU(void) {
 
   if ( RUParamList.numelt > 0) {
     RC.ru = (RU_t **)malloc(RC.nb_RU*sizeof(RU_t *));
-    RC.ru_mask=(1<<RC.nb_RU) - 1;
-    printf("Set RU mask to %lx\n",RC.ru_mask);
 
     for (j = 0; j < RC.nb_RU; j++) {
       RC.ru[j]                                    = (RU_t *)malloc(sizeof(RU_t));
diff --git a/executables/split_headers.h b/executables/split_headers.h
index 1fe4088971cca48c84655da5dc09d9ce2d60a740..3d59f3c199cfe7e5c6e9d76c0f55745e5227ee87 100644
--- a/executables/split_headers.h
+++ b/executables/split_headers.h
@@ -23,6 +23,7 @@ typedef struct frequency_s {
 } frequency_t;
 
 int createListner (port);
-int receiveSubFrame(int sock, uint64_t expectedTS, void* bufferZone,  int bufferSize);
-int sendSubFrame(int sock, void* bufferZone, int nbBlocks);}
+int receiveSubFrame(int sock, uint64_t expectedTS, void *bufferZone,  int bufferSize);
+int sendSubFrame(int sock, void *bufferZone, int nbBlocks);
+}
 #endif
diff --git a/targets/ARCH/rfsimulator/simulator.c b/targets/ARCH/rfsimulator/simulator.c
index 1bb424d115f59133719c1f65014bb0ea29ee709b..42bf766bafa05006fbd836c749e8ab2547c8e56d 100644
--- a/targets/ARCH/rfsimulator/simulator.c
+++ b/targets/ARCH/rfsimulator/simulator.c
@@ -47,8 +47,8 @@ pthread_mutex_t Sockmutex;
 
 typedef struct buffer_s {
   int conn_sock;
-  bool alreadyRead;
-  uint64_t lastReceivedTS;
+  openair0_timestamp lastReceivedTS;
+  openair0_timestamp lastWroteTS;
   bool headerMode;
   samplesBlockHeader_t th;
   char *transferPtr;
@@ -60,7 +60,7 @@ typedef struct buffer_s {
 
 typedef struct {
   int listen_sock, epollfd;
-  uint64_t nextTimestamp;
+  openair0_timestamp nextTimestamp;
   uint64_t typeStamp;
   char *ip;
   int saveIQfile;
@@ -104,9 +104,9 @@ void rxAddInput( struct complex16 *input_sig, struct complex16 *after_channel_si
   // Fixme: how to convert a noise in Watt into a 12 bits value out of the RF ADC ?
   // the parameter "-s" is declared as SNR, but the input power is not well defined
   // −132.24 dBm is a LTE subcarrier noise, that was used in origin code (15KHz BW thermal noise)
-  const double rxGain= 132.24 - snr_dB; 
+  const double rxGain= 132.24 - snr_dB;
   // sqrt(4*noise_figure_watt) is the thermal noise factor (volts)
-  // fixme: the last constant is pure trial results to make decent noise 
+  // fixme: the last constant is pure trial results to make decent noise
   const double noise_per_sample = sqrt(4*noise_figure_watt) * pow(10,rxGain/20) *10;
   // Fixme: we don't fill the offset length samples at begining ?
   // anyway, in today code, channel_offset=0
@@ -153,8 +153,8 @@ void allocCirBuf(rfsimulator_state_t *bridge, int sock) {
   AssertFatal ( (ptr->circularBuf=(sample_t *) malloc(sampleToByte(CirSize,1))) != NULL, "");
   ptr->circularBufEnd=((char *)ptr->circularBuf)+sampleToByte(CirSize,1);
   ptr->conn_sock=sock;
-  ptr->alreadyRead=false;
   ptr->lastReceivedTS=0;
+  ptr->lastWroteTS=0;
   ptr->headerMode=true;
   ptr->transferPtr=(char *)&ptr->th;
   ptr->remainToTransfer=sizeof(samplesBlockHeader_t);
@@ -319,21 +319,22 @@ sin_addr:
 
   setblocking(sock, notBlocking);
   allocCirBuf(t, sock);
-  t->buf[sock].alreadyRead=true; // UE will start blocking on read
   return 0;
 }
 
-uint64_t lastW=-1;
 int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, void **samplesVoid, int nsamps, int nbAnt, int flags) {
   rfsimulator_state_t *t = device->priv;
   LOG_D(HW,"sending %d samples at time: %ld\n", nsamps, timestamp);
 
+
   for (int i=0; i<FD_SETSIZE; i++) {
-    buffer_t *ptr=&t->buf[i];
+    buffer_t *b=&t->buf[i];
 
-    if (ptr->conn_sock >= 0 ) {
+    if (b->conn_sock >= 0 ) {
+      if ( abs((double)b->lastWroteTS-timestamp) > (double)CirSize)
+	LOG_E(HW,"Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
       samplesBlockHeader_t header= {t->typeStamp, nsamps, nbAnt, timestamp};
-      fullwrite(ptr->conn_sock,&header, sizeof(header), t);
+      fullwrite(b->conn_sock,&header, sizeof(header), t);
       sample_t tmpSamples[nsamps][nbAnt];
 
       for(int a=0; a<nbAnt; a++) {
@@ -343,17 +344,17 @@ int rfsimulator_write(openair0_device *device, openair0_timestamp timestamp, voi
           tmpSamples[s][a]=in[s];
       }
 
-      if (ptr->conn_sock >= 0 )
-        fullwrite(ptr->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
+      if (b->conn_sock >= 0 ) {
+        fullwrite(b->conn_sock, (void *)tmpSamples, sampleToByte(nsamps,nbAnt), t);
+        b->lastWroteTS=timestamp+nsamps;
+      }
     }
   }
 
-  lastW=timestamp;
   LOG_D(HW,"sent %d samples at time: %ld->%ld, energy in first antenna: %d\n",
         nsamps, timestamp, timestamp+nsamps, signal_energy(samplesVoid[0], nsamps) );
   // Let's verify we don't have incoming data
   // This is mandatory when the opposite side don't transmit
-  // This is mandatory when the opposite side don't transmit
   flushInput(t, 0);
   pthread_mutex_unlock(&Sockmutex);
   return nsamps;
@@ -425,7 +426,6 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) {
         AssertFatal( (t->typeStamp == UE_MAGICDL_FDD  && b->th.magic==ENB_MAGICDL_FDD) ||
                      (t->typeStamp == ENB_MAGICDL_FDD && b->th.magic==UE_MAGICDL_FDD), "Socket Error in protocol");
         b->headerMode=false;
-        b->alreadyRead=true;
 
         if ( b->lastReceivedTS != b->th.timestamp) {
           int nbAnt= b->th.nbAnt;
@@ -441,8 +441,8 @@ static bool flushInput(rfsimulator_state_t *t, int timeout) {
         }
 
         b->lastReceivedTS=b->th.timestamp;
-        AssertFatal(lastW == -1 || ( abs((double)lastW-b->lastReceivedTS) < (double)CirSize),
-                    "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", lastW, b->lastReceivedTS);
+        AssertFatal(b->lastWroteTS == 0 || ( abs((double)b->lastWroteTS-b->lastReceivedTS) < (double)CirSize),
+                    "Tx/Rx shift too large Tx:%lu, Rx:%lu\n", b->lastWroteTS, b->lastReceivedTS);
         b->transferPtr=(char *)&b->circularBuf[b->lastReceivedTS%CirSize];
         b->remainToTransfer=sampleToByte(b->th.size, b->th.nbAnt);
       }
@@ -498,15 +498,33 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
       return nsamps;
     }
   } else {
+    
     bool have_to_wait;
 
     do {
       have_to_wait=false;
 
       for ( int sock=0; sock<FD_SETSIZE; sock++) {
-        if ( t->buf[sock].circularBuf && t->buf[sock].alreadyRead )
-          if ( t->buf[sock].lastReceivedTS == 0 ||
-               (t->nextTimestamp+nsamps) > t->buf[sock].lastReceivedTS ) {
+	buffer_t *b=&t->buf[sock];
+        if ( b->circularBuf) {
+          LOG_D(HW,"sock: %d, lastWroteTS: %lu, lastRecvTS: %lu, TS must be avail: %lu\n",
+                sock, b->lastWroteTS,
+                b->lastReceivedTS,
+                t->nextTimestamp+nsamps);
+	  if (  b->lastReceivedTS > b->lastWroteTS ) {
+	    // The caller momdem (NB, UE, ...) must send Tx in advance, so we fill TX if Rx is in advance
+	    // This occurs for example when UE is in sync mode: it doesn't transmit
+	    // with USRP, it seems ok: if "tx stream" is off, we may consider it actually cuts the Tx power
+	    struct complex16 v={0};
+	    void *samplesVoid[b->th.nbAnt];
+	    for ( int i=0; i <b->th.nbAnt; i++)
+	      samplesVoid[i]=(void*)&v;
+	    rfsimulator_write(device, b->lastReceivedTS, samplesVoid, 1, b->th.nbAnt, 0);
+	  }
+	}
+
+        if ( b->circularBuf )
+          if ( t->nextTimestamp+nsamps > b->lastReceivedTS ) {
             have_to_wait=true;
             break;
           }
@@ -529,7 +547,7 @@ int rfsimulator_read(openair0_device *device, openair0_timestamp *ptimestamp, vo
   for (int sock=0; sock<FD_SETSIZE; sock++) {
     buffer_t *ptr=&t->buf[sock];
 
-    if ( ptr->circularBuf && ptr->alreadyRead ) {
+    if ( ptr->circularBuf ) {
       bool reGenerateChannel=false;
 
       //fixme: when do we regenerate
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index dcd79668742a2b71a4a7ccc695afaa35c308855e..37e94de2b6f049c98d11ec51bc224bb6aae85dc7 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -80,7 +80,7 @@ unsigned short config_frames[4] = {2,9,11,13};
 //#include "PHY/TOOLS/time_meas.h"
 
 #ifndef OPENAIR2
-#include "UTIL/OTG/otg_vars.h"
+  #include "UTIL/OTG/otg_vars.h"
 #endif
 
 
@@ -91,6 +91,7 @@ unsigned short config_frames[4] = {2,9,11,13};
 
 #include "system.h"
 
+
 #include "lte-softmodem.h"
 #include "NB_IoT_interface.h"
 
@@ -107,6 +108,10 @@ pthread_mutex_t sync_mutex;
 int sync_var=-1; //!< protected by mutex \ref sync_mutex.
 int config_sync_var=-1;
 
+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]
+
+
 volatile int             oai_exit = 0;
 
 uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
@@ -145,10 +150,18 @@ char ref[128] = "internal";
 char channels[128] = "0";
 
 int rx_input_level_dBm;
+
 int    otg_enabled;
+
+
 uint8_t exit_missed_slots=1;
 uint64_t num_missed_slots=0; // counter for the number of missed slots
 
+
+extern void reset_opp_meas(void);
+extern void print_opp_meas(void);
+
+
 extern void init_eNB_afterRU(void);
 extern void  phy_free_RU(RU_t *);
 
@@ -159,11 +172,73 @@ int numerology = 0;
 THREAD_STRUCT thread_struct;
 /* struct for ethernet specific parameters given in eNB conf file */
 eth_params_t *eth_params;
+
 double cpuf;
 
+/* forward declarations */
+
 /* forward declarations */
 void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
 
+/*---------------------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));
+}
+
+
 void signal_handler(int sig) {
   void *array[10];
   size_t size;
@@ -181,6 +256,7 @@ void signal_handler(int sig) {
   }
 }
 
+
 void exit_function(const char *file, const char *function, const int line, const char *s) {
   int ru_id;
 
@@ -209,6 +285,7 @@ void exit_function(const char *file, const char *function, const int line, const
   exit(1);
 }
 
+
 static void get_options(void) {
   CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
   get_common_options();
@@ -232,6 +309,10 @@ static void get_options(void) {
   }
 }
 
+
+
+
+
 void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
   int CC_id;
 
@@ -446,11 +527,14 @@ int main( int argc, char **argv ) {
   int CC_id = 0;
   int ru_id;
 
-  AssertFatal(load_configmodule(argc,argv,0) != NULL,
-	     "[SOFTMODEM] Error, configuration module init failed\n");
+  if ( load_configmodule(argc,argv,0) == NULL) {
+    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
+  }
+
   mode = normal_txrx;
 
   logInit();
+  printf("Reading in command-line options\n");
   get_options ();
   AssertFatal(!CONFIG_ISFLAGSET(CONFIG_ABORT),"Getting configuration failed\n");
   
@@ -472,14 +556,21 @@ int main( int argc, char **argv ) {
 
   EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
 
+  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
+    fprintf(stderr,"Getting configuration failed\n");
+    exit(-1);
+  }
+
 #if T_TRACER
   T_Config_Init();
 #endif
   //randominit (0);
   set_taus_seed (0);
+  printf("configuring for RAU/RRU\n");
 
-  if (opp_enabled ==1) 
+  if (opp_enabled ==1) {
     reset_opp_meas();
+  }
 
   itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
   // allows to forward in wireshark L2 protocol for decoding
@@ -491,8 +582,9 @@ int main( int argc, char **argv ) {
     /* Start the agent. If it is turned off in the configuration, it won't start */
     RCconfig_flexran();
     
-    for (i = 0; i < RC.nb_inst; i++) 
+    for (i = 0; i < RC.nb_inst; i++) {
       flexran_agent_start(i);
+    }
     
     /* initializes PDCP and sets correct RLC Request/PDCP Indication callbacks
      * for monolithic/F1 modes */
@@ -521,7 +613,7 @@ int main( int argc, char **argv ) {
     ctxt.subframe = 0;
     pdcp_run(&ctxt);
   }
-    
+
   /* start threads if only L1 or not a CU */
   if (RC.nb_inst == 0 || !NODE_IS_CU(RC.rrc[0]->node_type)) {
     // init UE_PF_PO and mutex lock
@@ -531,53 +623,56 @@ int main( int argc, char **argv ) {
     pthread_mutex_init(&sync_mutex, NULL);
 
     rt_sleep_ns(10*100000000ULL);
-    
+
     if (NFAPI_MODE!=NFAPI_MONOLITHIC) {
       LOG_I(ENB_APP,"NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
       pthread_cond_init(&sync_cond,NULL);
       pthread_mutex_init(&sync_mutex, NULL);
     }
-    
+
     if (NFAPI_MODE==NFAPI_MODE_VNF) {// VNF
 #if defined(PRE_SCD_THREAD)
       init_ru_vnf();  // ru pointer is necessary for pre_scd.
 #endif
       wait_nfapi_init("main?");
     }
-    
+
     LOG_I(ENB_APP,"START MAIN THREADS\n");
     // start the main threads
     number_of_cards = 1;
     printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
-    
+
     if (RC.nb_L1_inst > 0) {
       printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
       init_eNB(get_softmodem_params()->single_thread_flag,get_softmodem_params()->wait_for_sync);
       //      for (inst=0;inst<RC.nb_L1_inst;inst++)
       //  for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0);
     }
-  printf("wait_eNBs()\n");
-  wait_eNBs();
-  printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
-  
-  // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator.
-  // but RU thread deals with pre_scd and this is necessary in VNF and simulator.
-  // some initialization is necessary and init_ru_vnf do this.
-  if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) {
-    printf("Initializing RU threads\n");
+
+    // no need to wait: openair_rrc_eNB_configuration() is called earlier from this thread
+    // openair_rrc_eNB_configuration()->init_SI()->rrc_mac_config_req_eNB ()->phy_config_request () sets the wait_eNBs() tested flag
+    // wait_eNBs();
+    // printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
+
+    // RU thread and some L1 procedure aren't necessary in VNF or L2 FAPI simulator.
+    // but RU thread deals with pre_scd and this is necessary in VNF and simulator.
+    // some initialization is necessary and init_ru_vnf do this.
+    if (RC.nb_RU >0 && NFAPI_MODE!=NFAPI_MODE_VNF) {
+      printf("Initializing RU threads\n");
     init_RU(get_softmodem_params()->rf_config_file,get_softmodem_params()->clock_source,get_softmodem_params()->timing_source,get_softmodem_params()->send_dmrs_sync);
-    
-    for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
-      RC.ru[ru_id]->rf_map.card=0;
-      RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
+
+      for (ru_id=0; ru_id<RC.nb_RU; ru_id++) {
+        RC.ru[ru_id]->rf_map.card=0;
+        RC.ru[ru_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
+      }
     }
-    
+
     config_sync_var=0;
-    
+
     if (NFAPI_MODE==NFAPI_MODE_PNF) { // PNF
       wait_nfapi_init("main?");
     }
-    
+
     printf("wait RUs\n");
     // end of CI modifications
     // fixme: very weird usage of bitmask
@@ -604,6 +699,7 @@ int main( int argc, char **argv ) {
     pthread_mutex_unlock(&sync_mutex);
     config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
   }
+
   // wait for end of program
   LOG_UI(ENB_APP,"TYPE <CTRL-C> TO TERMINATE\n");
   // CI -- Flushing the std outputs for the previous marker to show on the eNB / DU / CU log file
@@ -648,17 +744,17 @@ int main( int argc, char **argv ) {
 
     for(ru_id=0; ru_id<RC.nb_RU; ru_id++) {
       if (RC.ru[ru_id]->rfdevice.trx_end_func) {
-	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
-	RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
+        RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
+        RC.ru[ru_id]->rfdevice.trx_end_func = NULL;
       }
 
       if (RC.ru[ru_id]->ifdevice.trx_end_func) {
-	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
-	RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
+        RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);
+        RC.ru[ru_id]->ifdevice.trx_end_func = NULL;
       }
     }
   }
-   
+
   terminate_opt();
   logClean();
   printf("Bye.\n");