diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index e1b2627c09a57c02a02aaef3c4c489a9be9adba8..e280b3f62578756236587ddd451be9237d475984 100755
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -165,6 +165,12 @@ typedef enum  {
   NGFI_RCC_IF4     // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) 
 } eNB_func_t;
   
+typedef enum {
+  synch_to_ext_device=0,  // synch to RF or Ethernet device
+  synch_to_other          // synch to another source (timer, other CC_id)
+} eNB_timing_t;
+
+
 typedef struct UE_SCAN_INFO_s {
   /// 10 best amplitudes (linear) for each pss signals
   int32_t amp[3][10];
@@ -211,7 +217,7 @@ typedef struct {
   struct sched_param sched_param_rxtx;
 } eNB_rxtx_proc_t;
 /// Context data structure for eNB subframe processing
-typedef struct {
+typedef struct eNB_proc_t_s {
   /// Component Carrier index
   uint8_t              CC_id;
   /// thread index
@@ -226,29 +232,46 @@ typedef struct {
   int frame_rx;
   /// frame to act upon for PRACH
   int frame_prach;
+  /// \brief Instance count for FH processing thread.
+  /// \internal This variable is protected by \ref mutex_FH.
+  int instance_cnt_FH;
   /// \brief Instance count for rx processing thread.
   /// \internal This variable is protected by \ref mutex_prach.
   int instance_cnt_prach;
-  /// pthread structure for rx processing thread
-  pthread_t pthread_rx;
+  /// pthread structure for FH processing thread
+  pthread_t pthread_FH;
+  /// pthread structure for asychronous RX processing thread
+  pthread_t pthread_asynch_rx;
   /// flag to indicate first RX acquisition
   int first_rx;
-  /// pthread attributes for rx processing thread
-  pthread_attr_t attr_rx;
+  /// pthread attributes for FH processing thread
+  pthread_attr_t attr_FH;
   /// pthread attributes for prach processing thread
   pthread_attr_t attr_prach;
-  /// scheduling parameters for rx thread
-  struct sched_param sched_param_rx;
+  /// pthread attributes for asynchronous RX thread
+  pthread_attr_t attr_asynch_rx;
+  /// scheduling parameters for FH thread
+  struct sched_param sched_param_FH;
   /// scheduling parameters for prach thread
   struct sched_param sched_param_prach;
-  /// condition variable for prach processing thread
+  /// scheduling parameters for asynch_rx thread
+  struct sched_param sched_param_asynch_rx;
+  /// condition variable for FH thread
   pthread_t pthread_prach;
-  /// condition variable for rx processing thread;
+  /// condition variable for FH thread
+  pthread_cond_t cond_FH;
+  /// condition variable for PRACH processing thread;
   pthread_cond_t cond_prach;
-  /// mutex for tx processing thread
+  /// mutex for FH
+  pthread_mutex_t mutex_FH;
+  /// mutex for PRACH thread
   pthread_mutex_t mutex_prach;
   /// set of scheduling variables RXn-TXnp4 threads
   eNB_rxtx_proc_t proc_rxtx[2];
+  /// number of slave threads
+  int                  num_slaves;
+  /// array of pointers to slaves
+  struct eNB_proc_t_s           **slave_proc;
 } eNB_proc_t;
 
 
@@ -311,6 +334,7 @@ typedef struct PHY_VARS_eNB_s {
   uint8_t              CC_id;
   eNB_proc_t           proc;
   eNB_func_t           node_function;
+  eNB_timing_t         node_timing;
   uint8_t              local_flag;
   uint32_t             rx_total_gain_dB;
   LTE_DL_FRAME_PARMS   frame_parms;
@@ -456,11 +480,6 @@ typedef struct PHY_VARS_eNB_s {
   time_stats_t phy_proc;
   time_stats_t phy_proc_tx;
   time_stats_t phy_proc_rx;
-  /*
-  time_stats_t phy_proc_sf[10]; // for each subframe
-  time_stats_t phy_proc_tx_sf[10];
-  time_stats_t phy_proc_rx_sf[10];
-  */
   time_stats_t rx_prach;
 
   time_stats_t ofdm_mod_stats;
@@ -505,11 +524,6 @@ typedef struct PHY_VARS_eNB_s {
   int32_t pusch_stats_mcs[NUMBER_OF_UE_MAX][10240];
   int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240];
   int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240];
-#if ENABLE_RAL
-  hash_table_t    *ral_thresholds_timed;
-  SLIST_HEAD(ral_thresholds_gen_poll_enb_s, ral_threshold_phy_t) ral_thresholds_gen_polled[RAL_LINK_PARAM_GEN_MAX];
-  SLIST_HEAD(ral_thresholds_lte_poll_enb_s, ral_threshold_phy_t) ral_thresholds_lte_polled[RAL_LINK_PARAM_LTE_MAX];
-#endif
   
   /// RF and Interface devices per CC
   openair0_device rfdevice; 
@@ -520,13 +534,6 @@ typedef struct PHY_VARS_eNB_s {
 } PHY_VARS_eNB;
 
 #define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg
-//#define debug_msg msg
-
-/*
-typedef enum {
-  max_gain=0,med_gain,byp_gain
-} rx_gain_t;
-*/
 
 /// Top-level PHY Data Structure for UE
 typedef struct {
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 653b5aeb1ec48b9ff45689e18fdd6eac343d84cf..1a1c2f4ad0bb75d58616644f399711b4837fb624 100755
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -2519,29 +2519,17 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl
 
   int i,l;
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
-  void *rxp[fp->nb_antennas_rx]; 
-  unsigned int rxs;
+
   eNB_proc_t *proc = &eNB->proc;
   int subframe = proc->subframe_rx;
   int frame = proc->frame_rx;
 
-  int prach_rx;
-
   uint8_t seqno=0;
 
-  uint16_t packet_type;
-  uint32_t symbol_number=0;
-  uint32_t symbol_mask, symbol_mask_full;
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 );
     
-  if (subframe==9) { 
-    subframe=0;
-    frame++;
-    frame&=1023;
-  } else {
-		subframe++;
-  }
+
   
-  //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_COMMON_RX,1);
   start_meas(&eNB->phy_proc_rx);
 
 #ifdef DEBUG_PHY_PROC
@@ -2549,77 +2537,11 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl
 #endif
 
   if (abstraction_flag==0) { // grab signal in chunks of 500 us (1 slot)
-		
-    if ((eNB->node_function == NGFI_RRU_IF4) ||
-        (eNB->node_function == NGFI_RRU_IF5) || 
-	      (eNB->node_function == eNodeB_3GPP)) { // acquisition from RF
-
-	    for (i=0; i<fp->nb_antennas_rx; i++)
-	      rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti];
-
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
-      rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
-			  	                              &proc->timestamp_rx,
-		  	 	                              rxp,
-				                                fp->samples_per_tti,
-				                                fp->nb_antennas_rx);
-      proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
-      proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
-
-      if (proc->first_rx == 0) {
-        if (proc->subframe_rx != subframe){
-          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe);
-          exit_fun("Exiting");
-	      }
-        if (proc->frame_rx != frame) {
-	        LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame);
-          exit_fun("Exiting");
-	      }
-      } else {
-        proc->first_rx = 0;
-			}
 
-      //      printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe);
-
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx );
-
-      if (rxs != fp->samples_per_tti)
-        exit_fun( "problem receiving samples" );
-	
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
-
-    } else if(eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF
-      /// **** recv_IF5 of rxdata from RRH **** ///       
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 );  
-      recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); 
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 );  
-      
-      proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
-      proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
 
-      if (proc->first_rx == 0) {
-        if (proc->subframe_rx != subframe){
-          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe);
-          //exit_fun("Exiting");
-        }
-        if (proc->frame_rx != frame) {
-          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame);
-          //exit_fun("Exiting");
-        }
-      } else {
-        proc->first_rx = 0;
-      }
-
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx );
-    }
-        
     if ((eNB->node_function == NGFI_RRU_IF4) || 
-        (eNB->node_function == eNodeB_3GPP)  ||
-        (eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing
+	(eNB->node_function == eNodeB_3GPP)  ||
+	(eNB->node_function == eNodeB_3GPP_BBU)) { // front-end processing
 
       // now do common RX processing for first slot in subframe
       VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
@@ -2641,131 +2563,61 @@ void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_fl
                     0
                     );
       }
-    	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
 
-      if (eNB->node_function == NGFI_RRU_IF4 && is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)<=0) {
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
+
+      if (eNB->node_function == NGFI_RRU_IF4) {
         /// **** send_IF4 of rxdataF to RCC (no prach now) **** ///
         VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 );   
         send_IF4(eNB, frame, subframe, IF4_PULFFT, 0);
         VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 );   
       }
 
-      /// **** send_IF4 of prach to RCC **** /// done in prach thread (below)
-      // check if we have to detect PRACH first
-      if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) {
-        // wake up thread for PRACH RX
-        if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
-          LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach );
-          exit_fun( "error locking mutex_prach" );
-          return;
-		    }
-		
-        int cnt_prach = ++proc->instance_cnt_prach;
-        // set timing for prach thread
-        proc->frame_prach = proc->frame_rx;
-        proc->subframe_prach = proc->subframe_rx;
-
-        pthread_mutex_unlock( &proc->mutex_prach );
-		
-        if (cnt_prach == 0) {
-          // the thread was presumably waiting where it should and can now be woken up
-          if (pthread_cond_signal(&proc->cond_prach) != 0) {
-            LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index);
-            exit_fun( "ERROR pthread_cond_signal" );
-            return;
-          }
-        } else {
-          LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach);
-          exit_fun( "PRACH thread busy" );
-          return;
-        }
-      }
     
-    } else if (eNB->node_function == NGFI_RRU_IF5) {
+    }
+    else if (eNB->node_function == NGFI_RRU_IF5) {
       /// **** send_IF5 of rxdata to BBU **** ///       
       VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );  
       send_IF5(eNB, proc->timestamp_rx, proc->subframe_rx, &seqno, IF5_RRH_GW_UL);
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );  
-            
-    } else if (eNB->node_function == NGFI_RCC_IF4) {
-      /// **** recv_IF4 of rxdataF from RRU **** ///
-      /// **** recv_IF4 of rxsigF from RRU **** ///
-      // get frame/subframe information from IF4 interface
-      // timed loop (200 us)
-       
-      symbol_number = 0;
-      symbol_mask = 0;
-      symbol_mask_full = (1<<fp->symbols_per_tti)-1;
-      prach_rx = 0;
-         
-      do {
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 );   
-        recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 );   
-
-        if (packet_type == IF4_PULFFT) {
-          symbol_mask = symbol_mask | (1<<symbol_number);     
-                       
-        } else if (packet_type == IF4_PRACH) {
-          // wake up thread for PRACH RX
-          prach_rx = 1;
-
-          if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
-            LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach );
-            exit_fun( "error locking mutex_prach" );
-            return;
-		      }
-		
-          int cnt_prach = ++proc->instance_cnt_prach;
-          // set timing for prach thread
-          proc->frame_prach = proc->frame_rx;
-          proc->subframe_prach = proc->subframe_rx;
-
-          pthread_mutex_unlock( &proc->mutex_prach );
-		
-          if (cnt_prach == 0) {
-            // the thread was presumably waiting where it should and can now be woken up
-            if (pthread_cond_signal(&proc->cond_prach) != 0) {
-              LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index);
-              exit_fun( "ERROR pthread_cond_signal" );
-              return;
-            }
-          } else {
-            LOG_W( PHY,"[eNB] Frame %d, eNB PRACH thread busy!!\n", frame);
-            exit_fun( "PRACH thread busy" );
-            return;
-          }
-        }
-
-      } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0));    
-
-      if (proc->first_rx == 0) {
-        if (proc->subframe_rx != subframe){
-          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe);
-          //exit_fun("Exiting");
-        }
-        if (proc->frame_rx != frame) {
-          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame);
-          //exit_fun("Exiting");
-        }
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );          
+    }
+    
+    /// **** send_IF4 of prach to RCC **** /// done in prach thread (below)
+    // check if we have to detect PRACH first
+    if ((eNB->node_function != NGFI_RRU_IF5) && 
+	(is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0)) { // any other node must call prach procedure
+      // wake up thread for PRACH RX
+      if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
+	LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB PRACH thread %d (IC %d)\n", proc->instance_cnt_prach );
+	exit_fun( "error locking mutex_prach" );
+	return;
+      }
+      
+      int cnt_prach = ++proc->instance_cnt_prach;
+      // set timing for prach thread
+      proc->frame_prach = proc->frame_rx;
+      proc->subframe_prach = proc->subframe_rx;
+      
+      pthread_mutex_unlock( &proc->mutex_prach );
+      
+      if (cnt_prach == 0) {
+	// the thread was presumably waiting where it should and can now be woken up
+	if (pthread_cond_signal(&proc->cond_prach) != 0) {
+	  LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB PRACH thread %d\n", proc->thread_index);
+	  exit_fun( "ERROR pthread_cond_signal" );
+	  return;
+	}
       } else {
-        proc->first_rx = 0;
+	LOG_W( PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,cnt_prach);
+	exit_fun( "PRACH thread busy" );
+	return;
       }
-
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx );
-
-      // Tobi aka mr monaco: ETH
-		  
-    } else { // should not get here
-      AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function);
     }
-
   } else { // grab transport channel information from network interface
 
   }
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 );
 }
 
 
@@ -2784,7 +2636,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
   const int subframe = proc->subframe_rx;
   const int frame = proc->frame_rx;
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 );
   start_meas(&eNB->phy_proc_rx);
 #ifdef DEBUG_PHY_PROC
   LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_RX(%d)\n",eNB->Mod_id,frame, subframe);
@@ -3346,7 +3198,8 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
   phy_procedures_emos_eNB_RX(subframe,eNB);
 #endif
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,0);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 );
+
   stop_meas(&eNB->phy_proc_rx);
 
 }
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index bb00aced6661bb11d92e4012b66f954403e4fd55..c16fbb5e8d2ae4c4ecd07a6933bd919f9bf3e63c 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -435,14 +435,16 @@ static void* eNB_thread_rxtx( void* param ) {
   
     if (oai_exit) break;
 
+    // Common procedures
+    phy_procedures_eNB_common_RX(PHY_vars_eNB_g[0][proc->CC_id], 0);
+
     // UE-specific RX processing for subframe n
     if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) ||
         (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) ||
         (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4)) {
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 1 );
+
       // this is the ue-specific processing for the subframe and can be multi-threaded later
       phy_procedures_eNB_uespec_RX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay );
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC, 0 );
     }
 
     // TX processing for subframe n+4
@@ -629,23 +631,122 @@ static void wait_system_ready (char *message, volatile int *start_flag) {
 }
 #endif
 
+/*!
+ * \brief The Asynchronous RX FH thread of RAU/RCC/eNB.
+ * This handles the RX FH for an asynchronous RRU/UE
+ * \param param is a \ref eNB_proc_t structure which contains the info what to process.
+ * \returns a pointer to an int. The storage is not on the heap and must not be freed.
+ */
+static void* eNB_thread_asynch_rx( void* param ) {
+
+  eNB_proc_t *proc = (eNB_proc_t*)param;
+  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
+  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+  openair0_timestamp timestamp_rx;
+  int frame_rx,subframe_rx;
+  int first_rx = 1;
+  uint16_t packet_type;
+  uint32_t symbol_number=0;
+  uint32_t symbol_mask, symbol_mask_full;
+  int prach_rx;
+
+  if (eNB->node_function == eNodeB_3GPP_BBU) { // acquisition from IF
+      /// **** recv_IF5 of rxdata from RRH **** ///       
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 );  
+    recv_IF5(eNB, &timestamp_rx, subframe_rx++, IF5_RRH_GW_UL); 
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 );  
+    if (first_rx == 1) {
+      first_rx = 0;
+      subframe_rx = (timestamp_rx/fp->samples_per_tti)%10;
+    }
+    else {
+    // check timestamp
+      if ((timestamp_rx - proc->timestamp_rx) < (2*fp->samples_per_tti))
+	printf("RX overflow ...\n");
+
+    }
+  } // eNodeB_3GPP_BBU 
+  
+  else if (eNB->node_function == NGFI_RCC_IF4) {
+      /// **** recv_IF4 of rxdataF from RRU **** ///
+      /// **** recv_IF4 of rxsigF from RRU **** ///
+      // get frame/subframe information from IF4 interface
+      // timed loop (200 us)
+      
+      symbol_number = 0;
+      symbol_mask = 0;
+      symbol_mask_full = (1<<fp->symbols_per_tti)-1;
+      prach_rx = 0;
+         
+      do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
+
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 );   
+        recv_IF4(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number);
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 );   
+
+        if (packet_type == IF4_PULFFT) {
+          symbol_mask = symbol_mask | (1<<symbol_number);     
+                       
+        } else if (packet_type == IF4_PRACH) {
+          // wake up thread for PRACH RX
+          prach_rx = 1;
+	}
+
+
+
+      } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0));    
+
+      if (proc->first_rx == 0) {
+        if (subframe_rx < proc->subframe_rx+2){
+          LOG_E(PHY,"RX overflow (proc->subframe_rx %d, subframe_rx %d)\n",proc->subframe_rx,subframe_rx);
+        }
+      } else {
+        proc->first_rx = 0;
+      }
+    } // node_timing == synch_to_externs, node_function = NGFI_IF4
+    else { // should not get here
+      AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function);
+    }
+
+}
 
 /*!
- * \brief The RX common thread of eNB.
+ * \brief The Fronthaul thread of RRU/RAU/RCC/eNB
+ * In the case of RRU/eNB, handles interface with external RF
+ * In the case of RAU/RCC, handles fronthaul interface with RRU/RAU
  * \param param is a \ref eNB_proc_t structure which contains the info what to process.
  * \returns a pointer to an int. The storage is not on the heap and must not be freed.
  */
-static void* eNB_thread_rx_common( void* param ) {
+static void* eNB_thread_FH( void* param ) {
   
-  static int eNB_thread_rx_status;
+  static int eNB_thread_FH_status;
 
   eNB_proc_t *proc = (eNB_proc_t*)param;
   PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
-  
+  void *rxp[fp->nb_antennas_rx]; 
+  unsigned int rxs;
   FILE  *rx_time_file = NULL;
   char rx_time_name[101];
   struct timespec wait;
+  int i;
+  int prach_rx;
+
+
+
+  uint16_t packet_type;
+  uint32_t symbol_number=0;
+  uint32_t symbol_mask, symbol_mask_full;
+
+  int subframe = proc->subframe_rx;
+  int frame = proc->frame_rx;
+  if (subframe==9) { 
+    subframe=0;
+    frame++;
+    frame&=1023;
+  } else {
+    subframe++;
+  }
 
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
@@ -655,7 +756,7 @@ static void* eNB_thread_rx_common( void* param ) {
     rx_time_file = fopen(rx_time_name,"w");
   }
   // set default return value
-  eNB_thread_rx_status = 0;
+  eNB_thread_FH_status = 0;
 
   MSC_START_USE();
 
@@ -678,7 +779,7 @@ static void* eNB_thread_rx_common( void* param ) {
 
   if (sched_setattr(0, &attr, flags) < 0 ) {
     perror("[SCHED] eNB RX sched_setattr failed\n");
-    return &eNB_thread_rx_status;
+    return &eNB_thread_FH_status;
   }
 
   LOG_I( HW, "[SCHED] eNB RX deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() );
@@ -796,32 +897,205 @@ static void* eNB_thread_rx_common( void* param ) {
       
   // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
   while (!oai_exit) {
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RX, 0 );
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 );
-    start_meas( &softmodem_stats_rx_sf );
    
     if (oai_exit) break;
    
-    if ((((fp->frame_type == TDD )&&(subframe_select(fp,proc->subframe_rx)==SF_UL)) ||
-	 (fp->frame_type == FDD))) {
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 1 );
-      // this spawns the prach inside and updates the frame and subframe counters
-      phy_procedures_eNB_common_RX(eNB, 0);
+
+    if ((eNB->node_timing == synch_to_other) &&
+	((eNB->node_function == NGFI_RRU_IF4) ||
+	 (eNB->node_function == NGFI_RRU_IF5) || 
+	 (eNB->node_function == eNodeB_3GPP))) {   // This case is for synchronization to another thread
+      //wait for event
+
+      // how long should we wait here, for MOBIPASS this could be long
+      //      if (pthread_mutex_timedlock(&proc->mutex_FH,&wait) != 0) {
+      if (pthread_mutex_lock(&proc->mutex_FH) != 0) {
+	LOG_E( PHY, "[SCHED][eNB] error locking mutex for FH\n");
+	exit_fun( "error locking mutex" );
+	break;
+      }
+      
+      while (proc->instance_cnt_FH < 0) {
+	// most of the time the thread is waiting here
+	// proc->instance_cnt_prach is -1
+	pthread_cond_wait( &proc->cond_FH,&proc->mutex_FH ); // this unlocks mutex_rxtx while waiting and then locks it again
+      }
       
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON, 0 );
+      proc->instance_cnt_FH++;
+
+
     }
+    // Remaining cases are all for synchronization on FH interface
+    else if ((eNB->node_timing == synch_to_ext_device) &&
+	     ((eNB->node_function == NGFI_RRU_IF4) ||
+	      (eNB->node_function == NGFI_RRU_IF5) || 
+	      (eNB->node_function == eNodeB_3GPP))) { // acquisition from RF
+      
+      for (i=0; i<fp->nb_antennas_rx; i++)
+	rxp[i] = (void*)&eNB->common_vars.rxdata[0][i][subframe*fp->samples_per_tti];
+      
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
+      
+      rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
+					&proc->timestamp_rx,
+					rxp,
+					fp->samples_per_tti,
+					fp->nb_antennas_rx);
+      proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
+      proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
+    
+      
+      if (proc->first_rx == 0) {
+	if (proc->subframe_rx != subframe){
+          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe);
+          exit_fun("Exiting");
+	}
+        if (proc->frame_rx != frame) {
+	  LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame);
+	  exit_fun("Exiting");
+	}
+      } else {
+        proc->first_rx = 0;
+      }
+      
+      //      printf("timestamp_rx %lu, frame %d(%d), subframe %d(%d)\n",proc->timestamp_rx,proc->frame_rx,frame,proc->subframe_rx,subframe);
+      
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx );
+      
+      if (rxs != fp->samples_per_tti)
+        exit_fun( "problem receiving samples" );
+      
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
+      
+    }  // node_timing==synch_to_ext_device && node_function == RRU || eNodeB
+    else if ((eNB->node_timing == synch_to_ext_device) &&
+	       (eNB->node_function == eNodeB_3GPP_BBU)) { // acquisition from IF
+      /// **** recv_IF5 of rxdata from RRH **** ///       
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 );  
+      recv_IF5(eNB, &proc->timestamp_rx, proc->subframe_rx, IF5_RRH_GW_UL); 
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 );  
+      
+      proc->frame_rx    = (proc->timestamp_rx / (fp->samples_per_tti*10))&1023;
+      proc->subframe_rx = (proc->timestamp_rx / fp->samples_per_tti)%10;
+      
+      if (proc->first_rx == 0) {
+	if (proc->subframe_rx != subframe){
+	  LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe);
+	  //exit_fun("Exiting");
+	}
+	if (proc->frame_rx != frame) {
+	  LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame);
+	  //exit_fun("Exiting");
+	}
+      } else {
+	proc->first_rx = 0;
+      }
+      
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx );
+    } // eNodeB_3GPP_BBU && node_timing == synch_to_ext_device
+
+    else if ((eNB->node_timing == synch_to_ext_device) &&
+	     (eNB->node_function == NGFI_RCC_IF4)) {
+      /// **** recv_IF4 of rxdataF from RRU **** ///
+      /// **** recv_IF4 of rxsigF from RRU **** ///
+      // get frame/subframe information from IF4 interface
+      // timed loop (200 us)
+      
+      symbol_number = 0;
+      symbol_mask = 0;
+      symbol_mask_full = (1<<fp->symbols_per_tti)-1;
+      prach_rx = 0;
+         
+      do {   // Blocking, we need a timeout on this !!!!!!!!!!!!!!!!!!!!!!!
+
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 );   
+        recv_IF4(eNB, &proc->frame_rx, &proc->subframe_rx, &packet_type, &symbol_number);
+        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 );   
+
+        if (packet_type == IF4_PULFFT) {
+          symbol_mask = symbol_mask | (1<<symbol_number);     
+                       
+        } else if (packet_type == IF4_PRACH) {
+          // wake up thread for PRACH RX
+          prach_rx = 1;
+	}
+
+
+
+      } while( (symbol_mask != symbol_mask_full) && (prach_rx == 0));    
+
+      if (proc->first_rx == 0) {
+        if (proc->subframe_rx != subframe){
+          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->subframe_rx %d, subframe %d)\n",proc->subframe_rx,subframe);
+          //exit_fun("Exiting");
+        }
+        if (proc->frame_rx != frame) {
+          LOG_E(PHY,"Received Timestamp doesn't correspond to the time we think it is (proc->frame_rx %d frame %d)\n",proc->frame_rx,frame);
+          //exit_fun("Exiting");
+        }
+      } else {
+        proc->first_rx = 0;
+      }
+
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_ENB, proc->frame_rx );
+      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_ENB, proc->subframe_rx );
 
+		  
+    } // node_timing == synch_to_externs, node_function = NGFI_IF4
+    else { // should not get here
+      AssertFatal(1==0, "Unknown eNB->node_function %d",eNB->node_function);
+    }
+
+    // At this point, all information for subframe has been received on FH interface
+    // If this proc is to provide synchronization, do so
+    for (i=0;i<proc->num_slaves;i++) {
+      eNB_proc_t *slave_proc = proc->slave_proc[i];
+      // wake up slave FH thread
+      // lock the FH mutex and make sure the thread is ready
+      if (pthread_mutex_timedlock(&slave_proc->mutex_FH,&wait) != 0) {
+	LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB CCid %d slave CCid %d (IC %d)\n",proc->CC_id,slave_proc->CC_id);
+	exit_fun( "error locking mutex_rxtx" );
+	break;
+      }
+      int cnt_slave            = ++slave_proc->instance_cnt_FH;
+      slave_proc->frame_rx     = proc->frame_rx;
+      slave_proc->subframe_rx  = proc->subframe_rx;
+      slave_proc->timestamp_rx = proc->timestamp_rx;
+ 
+      pthread_mutex_unlock( &slave_proc->mutex_FH );
+      
+      if (cnt_slave == 0) {
+	// the thread was presumably waiting where it should and can now be woken up
+	if (pthread_cond_signal(&slave_proc->cond_FH) != 0) {
+	  LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB CCid %d, slave CCid %d\n",proc->CC_id,slave_proc->CC_id);
+	  exit_fun( "ERROR pthread_cond_signal" );
+	  break;
+	}
+      } else {
+	LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_rxtx %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave);
+	exit_fun( "TX thread busy" );
+	break;
+      }             
+    }
+      
+    // wake up RXn_TXnp4 thread for the subframe
     // choose even or odd thread for RXn-TXnp4 processing 
     eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[proc->subframe_rx&1];
 
     // wake up TX for subframe n+4
     // lock the TX mutex and make sure the thread is ready
     if (pthread_mutex_timedlock(&proc_rxtx->mutex_rxtx,&wait) != 0) {
-      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n", proc_rxtx->instance_cnt_rxtx );
+      LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx );
       exit_fun( "error locking mutex_rxtx" );
       break;
     }
     int cnt_rxtx = ++proc_rxtx->instance_cnt_rxtx;
+    
     // We have just received and processed the common part of a subframe, say n. 
     // TS_rx is the last received timestamp (start of 1st slot), TS_tx is the desired 
     // transmitted timestamp of the next TX slot (first).
@@ -865,12 +1139,20 @@ static void* eNB_thread_rx_common( void* param ) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
   }
  
-
-  printf( "Exiting eNB thread rx_common\n");
+  if (eNB->node_timing == synch_to_ext_device) {
+    proc->instance_cnt_FH--;
+    
+    if (pthread_mutex_unlock(&proc->mutex_FH) != 0) {
+      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for FH\n");
+      exit_fun( "error unlocking mutex" );
+    }
+  }
+    
+  printf( "Exiting FH thread \n");
 
  
-  eNB_thread_rx_status = 0;
-  return &eNB_thread_rx_status;
+  eNB_thread_FH_status = 0;
+  return &eNB_thread_FH_status;
 }
 
 
@@ -1070,9 +1352,9 @@ void init_eNB_proc(void) {
     pthread_attr_setschedparam  (&proc_rxtx[1].attr_rxtx, &proc_rxtx[1].sched_param_rxtx);
     pthread_attr_setschedpolicy (&proc_rxtx[1].attr_rxtx, SCHED_FIFO);
     
-    proc->sched_param_rx.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
-    pthread_attr_setschedparam  (&proc->attr_rx, &proc->sched_param_rx);
-    pthread_attr_setschedpolicy (&proc->attr_rx, SCHED_FIFO);
+    proc->sched_param_FH.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
+    pthread_attr_setschedparam  (&proc->attr_FH, &proc->sched_param_FH);
+    pthread_attr_setschedpolicy (&proc->attr_FH, SCHED_FIFO);
     
     proc->sched_param_prach.sched_priority = sched_get_priority_max(SCHED_FIFO)-1; //OPENAIR_THREAD_PRIORITY;
     pthread_attr_setschedparam  (&proc->attr_prach, &proc->sched_param_prach);
@@ -1083,6 +1365,7 @@ void init_eNB_proc(void) {
     proc_rxtx[0].instance_cnt_rxtx = -1;
     proc_rxtx[1].instance_cnt_rxtx = -1;
     proc->instance_cnt_prach = -1;
+    proc->instance_cnt_FH = -1;
     proc->CC_id = CC_id;
 
     proc->first_rx=4;
@@ -1093,24 +1376,30 @@ void init_eNB_proc(void) {
     pthread_cond_init( &proc_rxtx[0].cond_rxtx, NULL);
     pthread_cond_init( &proc_rxtx[1].cond_rxtx, NULL);
     pthread_cond_init( &proc->cond_prach, NULL);
+    pthread_cond_init( &proc->cond_FH, NULL);
 #ifndef DEADLINE_SCHEDULER
     pthread_create( &proc_rxtx[0].pthread_rxtx, &proc_rxtx[0].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[0] );
     pthread_create( &proc_rxtx[1].pthread_rxtx, &proc_rxtx[1].attr_rxtx, eNB_thread_rxtx, &proc_rxtx[1] );
-    pthread_create( &proc->pthread_rx, &proc->attr_rx, eNB_thread_rx_common, &eNB->proc );
+    pthread_create( &proc->pthread_FH, &proc->attr_FH, eNB_thread_FH, &eNB->proc );
     pthread_create( &proc->pthread_prach, &proc->attr_prach, eNB_thread_prach, &eNB->proc );
+    if (eNB->node_timing == synch_to_other) 
+      pthread_create( &proc->pthread_asynch_rx, &proc->attr_asynch_rx, eNB_thread_asynch_rx, &eNB->proc );
 #else 
     pthread_create( &proc_rxtx[0].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[0] );
     pthread_create( &proc_rxtx[1].pthread_rxtx, NULL, eNB_thread_rxtx, &eNB->proc_rxtx[1] );
-    pthread_create( &proc->pthread_rx, NULL, eNB_thread_rx_common, &eNB->proc );
+    pthread_create( &proc->pthread_FH, NULL, eNB_thread_FH, &eNB->proc );
     pthread_create( &proc->pthread_prach, NULL, eNB_thread_prach, &eNB->proc );
+    if (eNB->node_timing == synch_to_other) 
+      pthread_create( &proc->pthread_asynch_rx, NULL, eNB_thread_asynch_rx, &eNB->proc );
+
 #endif
     char name[16];
     snprintf( name, sizeof(name), "RXTX0 %d", i );
     pthread_setname_np( proc_rxtx[0].pthread_rxtx, name );
     snprintf( name, sizeof(name), "RXTX1 %d", i );
     pthread_setname_np( proc_rxtx[1].pthread_rxtx, name );
-    snprintf( name, sizeof(name), "RX %d", i );
-    pthread_setname_np( proc->pthread_rx, name );
+    snprintf( name, sizeof(name), "FH %d", i );
+    pthread_setname_np( proc->pthread_FH, name );
   }
   
   /* setup PHY proc TX sync mechanism */
@@ -1142,63 +1431,27 @@ void kill_eNB_proc(void) {
     proc_rxtx[0].instance_cnt_rxtx = 0; // FIXME data race!
     proc_rxtx[1].instance_cnt_rxtx = 0; // FIXME data race!
     proc->instance_cnt_prach = 0;
+    proc->instance_cnt_FH = 0;
     pthread_cond_signal( &proc_rxtx[0].cond_rxtx );    
     pthread_cond_signal( &proc_rxtx[1].cond_rxtx );
     pthread_cond_signal( &proc->cond_prach );
+    pthread_cond_signal( &proc->cond_FH );
     pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
 
-    pthread_join( proc->pthread_rx, (void**)&status );    
-
+    pthread_join( proc->pthread_FH, (void**)&status ); 
+    pthread_mutex_destroy( &proc->mutex_FH );
+    pthread_cond_destroy( &proc->cond_FH );
+            
+    pthread_join( proc->pthread_prach, (void**)&status );    
+    pthread_mutex_destroy( &proc->mutex_prach );
+    pthread_cond_destroy( &proc->cond_prach );         
 
-    int result,i;
+    int i;
     for (i=0;i<2;i++) {
       pthread_join( proc_rxtx[i].pthread_rxtx, (void**)&status );
-    
-#ifdef DEBUG_THREADS
-    
-      if (result != 0) {
-	printf( "Error joining thread.\n" );
-      } else {
-	if (status) {
-	  printf( "status %d\n", *status );
-	} else {
-	  printf( "The thread was killed. No status available.\n" );
-	}
-      }
-#else
-      UNUSED(result);
-#endif
-
       pthread_mutex_destroy( &proc_rxtx[i].mutex_rxtx );
       pthread_cond_destroy( &proc_rxtx[i].cond_rxtx );
     }
-
-#ifdef DEBUG_THREADS
-    printf( "Killing RX CC_id %d thread\n", CC_id);
-#endif
-    
-#ifdef DEBUG_THREADS
-    printf( "Joining eNB RX CC_id %d thread ...\n", CC_id);
-#endif
-
-    result = pthread_join( proc->pthread_rx, (void**)&status );
-    
-#ifdef DEBUG_THREADS 
-    if (result != 0) {
-      printf( "Error joining thread.\n" );
-    } else {
-      if (status) {
-	printf( "status %d\n", *status );
-      } else {
-	printf( "The thread was killed. No status available.\n" );
-      }
-    }    
-#else
-    UNUSED(result);
-#endif
-   
-    pthread_mutex_destroy( &proc->mutex_prach );
-    pthread_cond_destroy( &proc->cond_prach );         
   }
 }
 
diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c
index 5a970ca038f2eaba14d563f059070bcbf46be2a4..867d578ce918f335fcc5b1150e76f85651aad478 100644
--- a/targets/SIMU/USER/oaisim_functions.c
+++ b/targets/SIMU/USER/oaisim_functions.c
@@ -1166,17 +1166,6 @@ void init_ocm(void)
         LOG_D(OCM,"Initializing channel (%s, %d) from eNB %d to UE %d\n", oai_emulation.environment_system_config.fading.small_scale.selected_option,
               map_str_to_int(small_scale_names,oai_emulation.environment_system_config.fading.small_scale.selected_option), eNB_id, UE_id);
 
-        /* if (oai_emulation.info.transmission_mode == 5)
-                  eNB2UE[eNB_id][UE_id] = new_channel_desc_scm(PHY_vars_eNB_g[eNB_id]->frame_parms.nb_antennas_tx,
-                                                     PHY_vars_UE_g[UE_id]->frame_parms.nb_antennas_rx,
-                                                     (UE_id == 0)? Rice1_corr : Rice1_anticorr,
-                                                     oai_emulation.environment_system_config.system_bandwidth_MB,
-                                                     forgetting_factor,
-                                                     0,
-                                                     0);
-
-              else
-         */
 
         eNB2UE[eNB_id][UE_id][CC_id] = 
 	  new_channel_desc_scm(PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.nb_antennas_tx,