diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 703bdd2d6fde21273ea9d8bc56453df9db061f1e..6f1eb595bb61414fb25a02f45a90c91b1fb909e2 100755
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -159,8 +159,8 @@ typedef enum  {
 
 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;
+  synch_to_other          // synch to another source (timer, other RU)
+} RU_timing_t;
 
 typedef struct UE_SCAN_INFO_s {
   /// 10 best amplitudes (linear) for each pss signals
@@ -226,6 +226,57 @@ typedef struct {
   int G;
 } te_params;
 
+typedef struct pc_proc_t_s {
+  /// timestamp received from HW
+  openair0_timestamp timestamp_rx;
+  /// timestamp to send to "slave rru"
+  openair0_timestamp timestamp_tx;
+  /// subframe to act upon for reception
+  int subframe_rx;
+  /// frame to act upon for reception
+  int frame_rx;
+  /// \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_asynch_rxtx.
+  int instance_cnt_asynch_rxtx;
+  /// pthread structure for FH processing thread
+  pthread_t pthread_FH;
+  /// pthread structure for eNB single processing thread
+  pthread_t pthread_single;
+  /// pthread structure for asychronous RX/TX processing thread
+  pthread_t pthread_asynch_rxtx;
+  /// flag to indicate first RX acquisition
+  int first_rx;
+  /// flag to indicate first TX transmission
+  int first_tx;
+  /// pthread attributes for FH processing thread
+  pthread_attr_t attr_FH;
+  /// pthread attributes for single eNB processing thread
+  pthread_attr_t attr_single;
+  /// pthread attributes for asynchronous RX thread
+  pthread_attr_t attr_asynch_rxtx;
+  /// scheduling parameters for FH thread
+  struct sched_param sched_param_FH;
+  /// scheduling parameters for single eNB thread
+  struct sched_param sched_param_single;
+  /// scheduling parameters for asynch_rxtx thread
+  struct sched_param sched_param_asynch_rxtx;
+  /// condition variable for FH thread
+  pthread_cond_t cond_FH;
+  /// condition variable for asynch RX/TX thread
+  pthread_cond_t cond_asynch_rxtx;
+  /// mutex for FH
+  pthread_mutex_t mutex_FH;
+  /// mutex for asynch RX/TX thread
+  pthread_mutex_t mutex_asynch_rxtx;
+  /// number of slave threads
+  int                  num_slaves;
+  /// array of pointers to slaves
+  struct pc_proc_t_s           **slave_proc;
+} pc_proc_t;
+
 /// Context data structure for eNB subframe processing
 typedef struct eNB_proc_t_s {
   /// Component Carrier index
@@ -412,14 +463,12 @@ typedef struct PHY_VARS_eNB_s {
   int                  abstraction_flag;
   openair0_timestamp   ts_offset;
   void                 (*do_prach)(struct PHY_VARS_eNB_s *eNB);
-  void                 (*fep)(struct PHY_VARS_eNB_s *eNB);
   int                  (*td)(struct PHY_VARS_eNB_s *eNB,int UE_id,int harq_pid,int llr8_flag);
   int                  (*te)(struct PHY_VARS_eNB_s *,uint8_t *,uint8_t,LTE_eNB_DLSCH_t *,int,uint8_t,time_stats_t *,time_stats_t *,time_stats_t *);
   void                 (*proc_uespec_rx)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type);
   void                 (*proc_tx)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type,PHY_VARS_RN *rn);
   void                 (*tx_fh)(struct PHY_VARS_eNB_s *eNB,eNB_rxtx_proc_t *proc);
   void                 (*rx_fh)(struct PHY_VARS_eNB_s *eNB,int *frame, int *subframe);
-  int                  (*start_rf)(struct PHY_VARS_eNB_s *eNB);
   int                  (*start_if)(struct PHY_VARS_eNB_s *eNB);
   void                 (*fh_asynch)(struct PHY_VARS_eNB_s *eNB,int *frame, int *subframe);
   uint8_t              local_flag;
@@ -612,12 +661,6 @@ typedef struct PHY_VARS_eNB_s {
   int32_t pusch_stats_bsr[NUMBER_OF_UE_MAX][10240];
   int32_t pusch_stats_BO[NUMBER_OF_UE_MAX][10240];
   
-  /// RF and Interface devices per CC
-  openair0_device rfdevice; 
-  openair0_device ifdevice;
-  /// Pointer for ifdevice buffer struct
-  if_buffer_t ifbuffer;
-
 } PHY_VARS_eNB;
 
 #define debug_msg if (((mac_xface->frame%100) == 0) || (mac_xface->frame < 50)) msg
@@ -873,13 +916,69 @@ typedef struct {
 
   /// RF and Interface devices per CC
   openair0_device rfdevice; 
-
 } PHY_VARS_UE;
 
+typedef enum {
+  LOCAL_RF=0,
+  REMOTE_IF5=1,
+  REMOTE_IF4p5=2,
+  REMOTE_IF1pp=3,
+  MAX_RU_IF_TYPES=4
+} RU_if_in_t;
+
+typedef struct {
+
+  /// input interface
+  RU_if_in_t RU_if_in;
+  /// timing
+  RU_if_timing_t RU_if_timing;
+  /// number of RX paths on device
+  int nb_rx;
+  /// number of TX paths on device
+  int nb_tx;
+  /// Radio Unit device descriptor
+  openair0_device rudevice;
+  /// Pointer for ifdevice buffer struct
+  if_buffer_t ifbuffer;
+} RU_desc_t;
+
+typedef struct PRECODER_t_s{
+  /// pointer to RAN context governing this precoder
+  RAN_CONTEXT *RC;
+  /// function pointer to synchronous TX fronthaul function
+  void                 (*tx_fh)(PRECODER_t_s *pc);
+  /// function pointer to synchronous RX fronthaul function
+  void                 (*rx_fh)(PRECODER_t_s *pc,int *frame, int *subframe);
+  /// function pointer to asynchronous fronthaul interface
+  void                 (*fh_asynch)(struct PRECODER_t_s *pc,int *frame, int *subframe);
+  /// function pointer to initialization function for radio interface
+  int                  (*start_rf)(struct PRECODER_t_s *pc);
+  /// function pointer to RX front-end processing routine (DFTs/prefix removal or NULL)
+  void                 (*fep_rx)(struct PRECODER_t_s *pc);
+  /// function pointer to TX front-end processing routine (PRECODING and/or IDFTs and prefix removal or NULL)
+  void                 (*fep_tx)(struct PRECODER_t_s *pc);
+  /// RX and TX buffers for precoder output
+  RU_TIME              ru_time;
+} PRECODER_t;
+
+typedef struct {
+  /// Number of eNB instances in this node
+  int nb_inst;
+  /// Number of Component Carriers per instance in this node
+  int *nb_CC;
+  /// Number of radio units
+  int nb_RU;
+  /// eNB context variables
+  PHY_VARS_eNB **eNB;
+  /// RU descriptors
+  RU_desc_t *ru_desc;
+  /// Precoding descriptor per radio unit. This describes what each radio unit is supposed to do and contains the necessary functions for fronthaul interfaces
+  PRECODER_t *pc;
+} RAN_CONTEXT_t;
+
 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");
diff --git a/openair1/PHY/impl_defs_lte.h b/openair1/PHY/impl_defs_lte.h
index bed2057800275dc2797ea44b391fecb43497569a..19c3936b6c38a296be21ff28c2a6fdc40dab5e66 100644
--- a/openair1/PHY/impl_defs_lte.h
+++ b/openair1/PHY/impl_defs_lte.h
@@ -592,150 +592,83 @@ typedef enum {
   TM9_10=13
 } MIMO_mode_t;
 
+
 typedef struct {
-  /// \brief Holds the transmit data in time domain.
-  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
-  /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: tx antenna [0..nb_antennas_tx[
-  /// - third index:
-  int32_t **txdata[3];
-  /// \brief holds the transmit data in the frequency domain.
-  /// For IFFT_FPGA this points to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
-  /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: tx antenna [0..nb_antennas_tx[
-  /// - third index: sample [0..]
-  int32_t **txdataF[3];
-  /// \brief Holds the received data in time domain.
-  /// Should point to the same memory as PHY_vars->rx_vars[a].RX_DMA_BUFFER.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna [0..nb_antennas_rx[
-  /// - third index: sample [0..]
-  int32_t **rxdata[3];
+
+  int32_t **txdataF;
   /// \brief Holds the last subframe of received data in time domain after removal of 7.5kHz frequency offset.
-  /// - first index: secotr id [0..2] (hard coded)
-  /// - second index: rx antenna [0..nb_antennas_rx[
-  /// - third index: sample [0..samples_per_tti[
-  int32_t **rxdata_7_5kHz[3];
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: sample [0..samples_per_tti[
+  int32_t **rxdata_7_5kHz;
   /// \brief Holds the received data in the frequency domain.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna [0..nb_antennas_rx[
-  /// - third index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[
-  int32_t **rxdataF[3];
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[
+  int32_t **rxdataF;
   /// \brief Holds output of the sync correlator.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: sample [0..samples_per_tti*10[
+  /// - first index: sample [0..samples_per_tti*10[
   uint32_t *sync_corr[3];
 } LTE_eNB_COMMON;
 
+typedef struct {
+  /// \brief Holds the transmit data in the frequency domain.
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[
+  int32_t **txdata;
+  /// \brief Holds the receive data in the frequency domain.
+  /// - first index: rx antenna [0..nb_antennas_rx[
+  /// - second index: ? [0..2*ofdm_symbol_size*frame_parms->symbols_per_tti[
+  int32_t **rxdata;
+} RU_TIME;
+
 typedef struct {
   /// \brief Hold the channel estimates in frequency domain based on SRS.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..ofdm_symbol_size[
-  int32_t **srs_ch_estimates[3];
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..ofdm_symbol_size[
+  int32_t **srs_ch_estimates;
   /// \brief Hold the channel estimates in time domain based on SRS.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..2*ofdm_symbol_size[
-  int32_t **srs_ch_estimates_time[3];
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..2*ofdm_symbol_size[
+  int32_t **srs_ch_estimates_time;
   /// \brief Holds the SRS for channel estimation at the RX.
-  /// - first index: ? [0..ofdm_symbol_size[
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..ofdm_symbol_size[
   int32_t *srs;
 } LTE_eNB_SRS;
 
 typedef struct {
   /// \brief Holds the received data in the frequency domain for the allocated RBs in repeated format.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..2*ofdm_symbol_size[
-  /// - third index (definition from phy_init_lte_eNB()): ? [0..24*N_RB_UL*frame_parms->symbols_per_tti[
-  /// \warning inconsistent third index definition
-  int32_t **rxdataF_ext[3];
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..2*ofdm_symbol_size[
+  int32_t **rxdataF_ext;
   /// \brief Holds the received data in the frequency domain for the allocated RBs in normal format.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **rxdataF_ext2[3];
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index (definition from phy_init_lte_eNB()): ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **rxdataF_ext2;
   /// \brief Hold the channel estimates in time domain based on DRS.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..4*ofdm_symbol_size[
-  int32_t **drs_ch_estimates_time[3];
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..4*ofdm_symbol_size[
+  int32_t **drs_ch_estimates_time;
   /// \brief Hold the channel estimates in frequency domain based on DRS.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **drs_ch_estimates[3];
-  /// \brief Hold the channel estimates for UE0 in case of Distributed Alamouti Scheme.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **drs_ch_estimates_0[3];
-  /// \brief Hold the channel estimates for UE1 in case of Distributed Almouti Scheme.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **drs_ch_estimates_1[3];
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **drs_ch_estimates;
   /// \brief Holds the compensated signal.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **rxdataF_comp[3];
-  /// \brief Hold the compensated data (y)*(h0*) in case of Distributed Alamouti Scheme.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **rxdataF_comp_0[3];
-  /// \brief Hold the compensated data (y*)*(h1) in case of Distributed Alamouti Scheme.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **rxdataF_comp_1[3];
-  /// \brief ?.
-  /// - first index: sector id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **ul_ch_mag[3];
-  /// \brief ?.
-  /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **ul_ch_magb[3];
-  /// \brief Hold the channel mag for UE0 in case of Distributed Alamouti Scheme.
-  /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **ul_ch_mag_0[3];
-  /// \brief Hold the channel magb for UE0 in case of Distributed Alamouti Scheme.
-  /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **ul_ch_magb_0[3];
-  /// \brief Hold the channel mag for UE1 in case of Distributed Alamouti Scheme.
-  /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **ul_ch_mag_1[3];
-  /// \brief Hold the channel magb for UE1 in case of Distributed Alamouti Scheme.
-  /// - first index: eNB id [0..2] (hard coded)
-  /// - second index: rx antenna id [0..nb_antennas_rx[
-  /// - third index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
-  int32_t **ul_ch_magb_1[3];
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **rxdataF_comp;
+  /// \brief Magnitude of the UL channel estimates. Used for 2nd-bit level thresholds in LLR computation
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_mag;
+  /// \brief Magnitude of the UL channel estimates scaled for 3rd bit level thresholds in LLR computation
+  /// - first index: rx antenna id [0..nb_antennas_rx[
+  /// - second index: ? [0..12*N_RB_UL*frame_parms->symbols_per_tti[
+  int32_t **ul_ch_magb;
   /// measured RX power based on DRS
   int ulsch_power[2];
-  /// measured RX power based on DRS for UE0 in case of Distributed Alamouti Scheme
-  int ulsch_power_0[2];
-  /// measured RX power based on DRS for UE0 in case of Distributed Alamouti Scheme
-  int ulsch_power_1[2];
   /// \brief llr values.
   /// - first index: ? [0..1179743] (hard coded)
   int16_t *llr;
-#ifdef LOCALIZATION
-  /// number of active subcarrier for a specific UE
-  int32_t active_subcarrier;
-  /// subcarrier power in dBm
-  int32_t *subcarrier_power;
-#endif
 } LTE_eNB_PUSCH;
 
 typedef struct {
diff --git a/openair1/PHY/vars.h b/openair1/PHY/vars.h
index e773229a28dc06a5dc289d1e739d5a42df141923..448aa192ba6e6ca589efbf4ea645ef24547e990f 100755
--- a/openair1/PHY/vars.h
+++ b/openair1/PHY/vars.h
@@ -141,6 +141,7 @@ double beta2_dlsch[6][MCS_COUNT] = { {2.52163, 0.83231, 0.77472, 1.36536, 1.1682
 
 char eNB_functions[6][20]={"eNodeB_3GPP","eNodeB_3GPP_BBU","NGFI_RCC_IF4p5","NGFI_RAI_IF4p5","NGFI_RRU_IF5","NGFI_RRU_IF4p5",};
 char eNB_timing[2][20]={"synch_to_ext_device","synch_to_other"};
+char ru_if_types[MAX_RU_IF_TYPES][20]={"local RF","IF5 RRU","IF4p5 RRU","IF1pp RRU"};
 
 /// lookup table for unscrambling in RX
 int16_t unscrambling_lut[65536*16] __attribute__((aligned(32)));
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index fdad1e12c1ff07e1544b5271a872bc7a95d0a3da..de46d8f2f9505dd8d05b6a77dfc88abd908af1ca 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -1230,13 +1230,30 @@ static void* eNB_thread_prach( void* param ) {
   return &eNB_thread_prach_status;
 }
 
+static void *pc_thread(void* param) {
+
+  PRECODER *pc = (PRECODER_t*)param;
+
+  // Start IF device if any
+  if (eNB->start_if) 
+    if (eNB->start_if(eNB) != 0)
+      LOG_E(HW,"Could not start the IF device\n");
+
+  // Start RF device if any
+  if (eNB->start_rf)
+    if (eNB->start_rf(eNB) != 0)
+      LOG_E(HW,"Could not start the RF device\n");
+
+}
+
+
 static void* eNB_thread_single( void* param ) {
 
   static int eNB_thread_single_status;
 
   eNB_proc_t *proc = (eNB_proc_t*)param;
   eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
-  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
+  PHY_VARS_eNB *eNB = RC.eNB[0][proc->CC_id];
 
   int subframe=0, frame=0; 
 
@@ -1252,15 +1269,6 @@ static void* eNB_thread_single( void* param ) {
     wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
 #endif 
 
-  // Start IF device if any
-  if (eNB->start_if) 
-    if (eNB->start_if(eNB) != 0)
-      LOG_E(HW,"Could not start the IF device\n");
-
-  // Start RF device if any
-  if (eNB->start_rf)
-    if (eNB->start_rf(eNB) != 0)
-      LOG_E(HW,"Could not start the RF device\n");
 
   // wakeup asnych_rxtx thread because the devices are ready at this point
   pthread_mutex_lock(&proc->mutex_asynch_rxtx);
@@ -1607,6 +1615,183 @@ extern void eNB_fep_full(PHY_VARS_eNB *eNB);
 extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB);
 extern void do_prach(PHY_VARS_eNB *eNB);
 
+void init_RU(RAN_CONTEXT *rc,RU_if_in_t ru_if_in[], RU_if_timing_t ru_if_timing[], eth_params_t *eth_params) {
+  
+  int ru_id;
+
+  for (ru_id=0;ru_id<rc->nb_RU;ru_id++) {
+    ru = &rc.ru_desc[ru_id];
+    ru->RU_if_in[ru_id]     = ru_if_in[ru_id];
+    ru->RU_if_timing        = ru_if_timing[ru_id];
+    LOG_I(PHY,"Initializing RRU descriptor %d : (%s,%s)\n",ru_id,ru_if_types[ru_if_in[ru_id]],eNB_timing[ru_timing[ru_id]]);
+    
+    switch (ru->RU_if_in[ru_id]) {
+    case REMOTE_IF5:
+      pc->fep                   = pc_fep_rru_if5;
+      eNB->rx_fh                = rx_rf;
+      eNB->start_rf             = start_rf;
+      eNB->start_if             = start_if;
+      eNB->fh_asynch            = fh_if5_asynch_DL;
+      ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[CC_id]);
+      if (ret<0) {
+	printf("Exiting, cannot initialize rf device\n");
+	exit(-1);
+      }
+      eNB->rfdevice.host_type   = RRH_HOST;
+      eNB->ifdevice.host_type   = RRH_HOST;
+      ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], (eth_params+CC_id));
+      printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
+      if (ret<0) {
+	printf("Exiting, cannot initialize transport protocol\n");
+	exit(-1);
+      }
+      break;
+    case NGFI_RRU_IF4p5:
+      eNB->do_prach             = do_prach;
+      eNB->fep                  = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
+      eNB->td                   = NULL;
+      eNB->te                   = NULL;
+      eNB->proc_uespec_rx       = NULL;
+      eNB->proc_tx              = NULL;//proc_tx_rru_if4p5;
+      eNB->tx_fh                = NULL;
+      eNB->rx_fh                = rx_rf;
+      eNB->fh_asynch            = fh_if4p5_asynch_DL;
+      eNB->start_rf             = start_rf;
+      eNB->start_if             = start_if;
+      ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[CC_id]);
+      if (ret<0) {
+	printf("Exiting, cannot initialize rf device\n");
+	exit(-1);
+      }
+      eNB->rfdevice.host_type   = RRH_HOST;
+      eNB->ifdevice.host_type   = RRH_HOST;
+      ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], (eth_params+CC_id));
+      printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
+      if (ret<0) {
+	printf("Exiting, cannot initialize transport protocol\n");
+	exit(-1);
+      }
+      
+      malloc_IF4p5_buffer(eNB);
+      
+      break;
+    case eNodeB_3GPP:
+      eNB->do_prach             = do_prach;
+      eNB->fep                  = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
+      eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
+      eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
+      eNB->proc_uespec_rx       = phy_procedures_eNB_uespec_RX;
+      eNB->proc_tx              = proc_tx_full;
+      eNB->tx_fh                = NULL;
+      eNB->rx_fh                = rx_rf;
+      eNB->start_rf             = start_rf;
+      eNB->start_if             = NULL;
+      eNB->fh_asynch            = NULL;
+      ret = openair0_device_load(&eNB->rfdevice, &openair0_cfg[CC_id]);
+      if (ret<0) {
+	printf("Exiting, cannot initialize rf device\n");
+	exit(-1);
+      }
+      eNB->rfdevice.host_type   = BBU_HOST;
+      eNB->ifdevice.host_type   = BBU_HOST;
+      break;
+    case eNodeB_3GPP_BBU:
+      eNB->do_prach       = do_prach;
+      eNB->fep            = eNB_fep_full;//(single_thread_flag==1) ? eNB_fep_full_2thread : eNB_fep_full;
+      eNB->td             = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
+      eNB->te             = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
+      eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
+      eNB->proc_tx        = proc_tx_full;
+      if (eNB->node_timing == synch_to_other) {
+	eNB->tx_fh          = tx_fh_if5_mobipass;
+	eNB->rx_fh          = rx_fh_slave;
+	eNB->fh_asynch      = fh_if5_asynch_UL;
+	
+      }
+      else {
+	eNB->tx_fh          = tx_fh_if5;
+	eNB->rx_fh          = rx_fh_if5;
+	eNB->fh_asynch      = NULL;
+      }
+      
+      eNB->start_rf       = NULL;
+	eNB->start_if       = start_if;
+	eNB->rfdevice.host_type   = BBU_HOST;
+	
+	eNB->ifdevice.host_type   = BBU_HOST;
+
+        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], (eth_params+CC_id));
+        printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
+        if (ret<0) {
+          printf("Exiting, cannot initialize transport protocol\n");
+          exit(-1);
+        }
+	break;
+      case NGFI_RCC_IF4p5:
+	eNB->do_prach             = do_prach;
+	eNB->fep                  = NULL;
+	eNB->td                   = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
+	eNB->te                   = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
+	eNB->proc_uespec_rx       = phy_procedures_eNB_uespec_RX;
+	eNB->proc_tx              = proc_tx_high;
+	eNB->tx_fh                = tx_fh_if4p5;
+	eNB->rx_fh                = rx_fh_if4p5;
+	eNB->start_rf             = NULL;
+	eNB->start_if             = start_if;
+        eNB->fh_asynch            = (eNB->node_timing == synch_to_other) ? fh_if4p5_asynch_UL : NULL;
+	eNB->rfdevice.host_type   = BBU_HOST;
+	eNB->ifdevice.host_type   = BBU_HOST;
+        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], (eth_params+CC_id));
+        printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
+        if (ret<0) {
+          printf("Exiting, cannot initialize transport protocol\n");
+          exit(-1);
+        }
+	malloc_IF4p5_buffer(eNB);
+
+	break;
+      case NGFI_RAU_IF4p5:
+	eNB->do_prach       = do_prach;
+	eNB->fep            = NULL;
+
+	eNB->td             = ulsch_decoding_data;//(single_thread_flag==1) ? ulsch_decoding_data_2thread : ulsch_decoding_data;
+	eNB->te             = dlsch_encoding;//(single_thread_flag==1) ? dlsch_encoding_2threads : dlsch_encoding;
+	eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
+	eNB->proc_tx        = proc_tx_high;
+	eNB->tx_fh          = tx_fh_if4p5; 
+	eNB->rx_fh          = rx_fh_if4p5; 
+        eNB->fh_asynch      = (eNB->node_timing == synch_to_other) ? fh_if4p5_asynch_UL : NULL;
+	eNB->start_rf       = NULL;
+	eNB->start_if       = start_if;
+
+	eNB->rfdevice.host_type   = BBU_HOST;
+	eNB->ifdevice.host_type   = BBU_HOST;
+        ret = openair0_transport_load(&eNB->ifdevice, &openair0_cfg[CC_id], (eth_params+CC_id));
+        printf("openair0_transport_init returns %d for CC_id %d\n",ret,CC_id);
+        if (ret<0) {
+          printf("Exiting, cannot initialize transport protocol\n");
+          exit(-1);
+        }
+	break;	
+	malloc_IF4p5_buffer(eNB);
+
+      }
+    }
+
+    if (setup_eNB_buffers(PHY_vars_eNB_g[inst],&openair0_cfg[CC_id])!=0) {
+      printf("Exiting, cannot initialize eNodeB Buffers\n");
+      exit(-1);
+    }
+
+    init_eNB_proc(inst);
+  }
+
+  sleep(1);
+  LOG_D(HW,"[lte-softmodem.c] eNB threads created\n");
+  
+
+}
+
 void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params,int single_thread_flag) {
   
   int CC_id;