diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index a453b8eb8d0171db7073d072c3b4b8c59d9b8d1d..d5833817817590d31d9b3c9fcfd2e05eac46b952 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -1167,7 +1167,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
         frame_parms->phich_config_common.phich_duration);
   LOG_D(PHY,"[MSC_NEW][FRAME 00000][PHY_eNB][MOD %02"PRIu8"][]\n", eNB->Mod_id);
 
-  if (eNB->node_function != NGFI_RRU_IF4) {
+  if (eNB->node_function != NGFI_RRU_IF4p5) {
     lte_gold(frame_parms,eNB->lte_gold_table,frame_parms->Nid_cell);
     generate_pcfich_reg_mapping(frame_parms);
     generate_phich_reg_mapping(frame_parms);
@@ -1191,12 +1191,12 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
     if (abstraction_flag==0) {
       
       // TX vars
-      if (eNB->node_function != NGFI_RCC_IF4)
+      if (eNB->node_function != NGFI_RCC_IF4p5)
 	common_vars->txdata[eNB_id]  = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );
       common_vars->txdataF[eNB_id] = (int32_t **)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );
       
       for (i=0; i<frame_parms->nb_antennas_tx; i++) {
-	if (eNB->node_function != NGFI_RCC_IF4)
+	if (eNB->node_function != NGFI_RCC_IF4p5)
 	  common_vars->txdata[eNB_id][i]  = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) );
 	common_vars->txdataF[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX*sizeof(int32_t) );
 #ifdef DEBUG_PHY
@@ -1208,14 +1208,14 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
       }
       
       // RX vars
-      if (eNB->node_function != NGFI_RCC_IF4) {
+      if (eNB->node_function != NGFI_RCC_IF4p5) {
 	common_vars->rxdata[eNB_id]        = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
 	common_vars->rxdata_7_5kHz[eNB_id] = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
       }
       common_vars->rxdataF[eNB_id]       = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
       
       for (i=0; i<frame_parms->nb_antennas_rx; i++) {
-	if (eNB->node_function != NGFI_RCC_IF4) {
+	if (eNB->node_function != NGFI_RCC_IF4p5) {
 	  common_vars->rxdata[eNB_id][i] = (int32_t*)malloc16_clear( FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(int32_t) );
 	  common_vars->rxdata_7_5kHz[eNB_id][i] = (int32_t*)malloc16_clear( frame_parms->samples_per_tti*sizeof(int32_t) );
 	}
@@ -1227,7 +1227,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
 #endif
       }
       
-      if (eNB->node_function != NGFI_RRU_IF4) {
+      if (eNB->node_function != NGFI_RRU_IF4p5) {
 	// Channel estimates for SRS
 	for (UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
 	  
@@ -1250,7 +1250,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
   
   
   if (abstraction_flag==0) {
-    if (eNB->node_function != NGFI_RRU_IF4) {
+    if (eNB->node_function != NGFI_RRU_IF4p5) {
       generate_ul_ref_sigs_rx();
       
       // SRS
@@ -1264,7 +1264,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
   
   // ULSCH VARS, skip if NFGI_RRU_IF4
   
-  if (eNB->node_function!=NGFI_RRU_IF4)
+  if (eNB->node_function!=NGFI_RRU_IF4p5)
     prach_vars->prachF = (int16_t*)malloc16_clear( 1024*2*sizeof(int16_t) );
   
   /* number of elements of an array X is computed as sizeof(X) / sizeof(X[0]) */
@@ -1277,7 +1277,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
 #endif
   }
   
-  if (eNB->node_function != NGFI_RRU_IF4) {
+  if (eNB->node_function != NGFI_RRU_IF4p5) {
     AssertFatal(frame_parms->nb_antennas_rx <= sizeof(prach_vars->prach_ifft) / sizeof(prach_vars->prach_ifft[0]),
 		"nb_antennas_rx too large");
     for (i=0; i<frame_parms->nb_antennas_rx; i++) {
@@ -1399,7 +1399,7 @@ int phy_init_lte_eNB(PHY_VARS_eNB *eNB,
     eNB->pdsch_config_dedicated->p_a = dB0; //defaul value until overwritten by RRCConnectionReconfiguration
 
     init_prach_tables(839);
-  } // node_function != NGFI_RRU_IF4
+  } // node_function != NGFI_RRU_IF4p5
 
   return (0);
 }
diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.c b/openair1/PHY/LTE_TRANSPORT/if4_tools.c
index d492af16a713c3b1141f279aaec38024627e0162..738fe842b6f867ff056418af70b187a83f775eb0 100644
--- a/openair1/PHY/LTE_TRANSPORT/if4_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.c
@@ -42,9 +42,9 @@
 #include "PHY/TOOLS/alaw_lut.h"
 
 #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
 
-
-void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int k) {
+void send_IF4p5(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type, int k) {
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
   int32_t **txdataF = eNB->common_vars.txdataF[0];
   int32_t **rxdataF = eNB->common_vars.rxdataF[0];
@@ -57,16 +57,18 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type,
 
   uint16_t *data_block=NULL, *i=NULL;
 
-  if (packet_type == IF4_PDLFFT) {
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 );   
+
+  if (packet_type == IF4p5_PDLFFT) {
     db_fulllength = 12*fp->N_RB_DL;
     db_halflength = (db_fulllength)>>1;
     slotoffsetF = (subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1;
     blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; 
 
-    IF4_header_t *dl_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES);
-    data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t);
+    IF4p5_header_t *dl_header = (IF4p5_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES);
+    data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t);
 
-    gen_IF4_dl_header(dl_header, frame, subframe);
+    gen_IF4p5_dl_header(dl_header, frame, subframe);
 		    
     for (symbol_id=0; symbol_id<fp->symbols_per_tti; symbol_id++) {
       
@@ -86,23 +88,23 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type,
                                         &tx_buffer,
                                         db_fulllength,
       			                            1,
-                                        IF4_PDLFFT)) < 0) {
-        perror("ETHERNET write for IF4_PDLFFT\n");
+                                        IF4p5_PDLFFT)) < 0) {
+        perror("ETHERNET write for IF4p5_PDLFFT\n");
       }
       
       slotoffsetF  += fp->ofdm_symbol_size;
       blockoffsetF += fp->ofdm_symbol_size;    
     }
-  } else if (packet_type == IF4_PULFFT) {
+  } else if (packet_type == IF4p5_PULFFT) {
     db_fulllength = 12*fp->N_RB_UL;
     db_halflength = (db_fulllength)>>1;
     slotoffsetF = 1;
     blockoffsetF = slotoffsetF + fp->ofdm_symbol_size - db_halflength - 1; 
 
-    IF4_header_t *ul_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES);
-    data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t);
+    IF4p5_header_t *ul_header = (IF4p5_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES);
+    data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t);
 
-    gen_IF4_ul_header(ul_header, frame, subframe);
+    gen_IF4p5_ul_header(ul_header, frame, subframe);
 
     for (symbol_id=0; symbol_id<fp->symbols_per_tti; symbol_id++) {			
 
@@ -122,23 +124,23 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type,
                                         &tx_buffer,
                                         db_fulllength,
       			                            1,
-                                        IF4_PULFFT)) < 0) {
-        perror("ETHERNET write for IF4_PULFFT\n");
+                                        IF4p5_PULFFT)) < 0) {
+        perror("ETHERNET write for IF4p5_PULFFT\n");
       }
 
       slotoffsetF  += fp->ofdm_symbol_size;
       blockoffsetF += fp->ofdm_symbol_size;    
     }		
-  } else if (packet_type == IF4_PRACH) {
+  } else if (packet_type == IF4p5_PRACH) {
     // FIX: hard coded prach samples length
     db_fulllength = 839*2;
 
-    IF4_header_t *prach_header = (IF4_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES);
-    data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t);
+    IF4p5_header_t *prach_header = (IF4p5_header_t *)(tx_buffer + MAC_HEADER_SIZE_BYTES);
+    data_block = (uint16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t);
 
-    gen_IF4_prach_header(prach_header, frame, subframe);
+    gen_IF4p5_prach_header(prach_header, frame, subframe);
 		    
-    memcpy((int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t),
+    memcpy((int16_t*)(tx_buffer + MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t),
            (&rxsigF[0][k]), 
            db_fulllength*sizeof(int16_t));
     			              
@@ -147,18 +149,19 @@ void send_IF4(PHY_VARS_eNB *eNB, int frame, int subframe, uint16_t packet_type,
                                       &tx_buffer,
                                       db_fulllength,
                                       1,
-                                      IF4_PRACH)) < 0) {
-      perror("ETHERNET write for IF4_PRACH\n");
+                                      IF4p5_PRACH)) < 0) {
+      perror("ETHERNET write for IF4p5_PRACH\n");
     }      
   } else {    
-    AssertFatal(1==0, "send_IF4 - Unknown packet_type %x", packet_type);     
+    AssertFatal(1==0, "send_IF4p5 - Unknown packet_type %x", packet_type);     
   }
-  
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 );  
   return;  		    
 }
 
 
-void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) {
+void recv_IF4p5(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_type, uint32_t *symbol_number) {
   LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
   int32_t **txdataF = eNB->common_vars.txdataF[0];
   int32_t **rxdataF = eNB->common_vars.rxdataF[0];
@@ -168,15 +171,17 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ
   uint16_t element_id;
   uint16_t db_fulllength, db_halflength; 
   int slotoffsetF=0, blockoffsetF=0; 
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 );   
   
-  if (eNB->node_function == NGFI_RRU_IF4) {
+  if (eNB->node_function == NGFI_RRU_IF4p5) {
     db_fulllength = (12*fp->N_RB_DL); 
   } else {
     db_fulllength = (12*fp->N_RB_UL);     
   }  
   db_halflength = db_fulllength>>1;
 
-  IF4_header_t *packet_header=NULL;
+  IF4p5_header_t *packet_header=NULL;
   uint16_t *data_block=NULL, *i=NULL;
      
   if (eNB->ifdevice.trx_read_func(&eNB->ifdevice,
@@ -187,13 +192,13 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ
     perror("ETHERNET read");
   }
   
-  packet_header = (IF4_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES);
-  data_block = (uint16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t);
+  packet_header = (IF4p5_header_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES);
+  data_block = (uint16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t);
 
   *frame = ((packet_header->frame_status)>>6)&0xffff;
   *subframe = ((packet_header->frame_status)>>22)&0x000f; 
   
-  if (*packet_type == IF4_PDLFFT) {          
+  if (*packet_type == IF4p5_PDLFFT) {          
     *symbol_number = ((packet_header->frame_status)>>26)&0x000f;         
 
     slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + (*subframe)*(fp->ofdm_symbol_size)*((fp->Ncp==1) ? 12 : 14) + 1;
@@ -209,7 +214,7 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ
       *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ];
     }
 		        
-  } else if (*packet_type == IF4_PULFFT) {         
+  } else if (*packet_type == IF4p5_PULFFT) {         
     *symbol_number = ((packet_header->frame_status)>>26)&0x000f;         
 
     slotoffsetF = (*symbol_number)*(fp->ofdm_symbol_size) + 1;
@@ -225,25 +230,26 @@ void recv_IF4(PHY_VARS_eNB *eNB, int *frame, int *subframe, uint16_t *packet_typ
       *(i+1) = alaw2lin[ (data_block[element_id+db_halflength]>>8) ];
     }
 		
-  } else if (*packet_type == IF4_PRACH) {    
+  } else if (*packet_type == IF4p5_PRACH) {    
     // FIX: hard coded prach samples length
     db_fulllength = 839*2;
 		
     memcpy((&rxsigF[0][0]), 
-           (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4_header_t), 
+           (int16_t*) (rx_buffer+MAC_HEADER_SIZE_BYTES+sizeof_IF4p5_header_t), 
            db_fulllength*sizeof(int16_t));
        
   } else {
-    AssertFatal(1==0, "recv_IF4 - Unknown packet_type %x", *packet_type);            
+    AssertFatal(1==0, "recv_IF4p5 - Unknown packet_type %x", *packet_type);            
   }
-  
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 );     
   return;   
 }
 
 
-void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) {      
-  dl_packet->type = IF4_PACKET_TYPE; 
-  dl_packet->sub_type = IF4_PDLFFT;
+void gen_IF4p5_dl_header(IF4p5_header_t *dl_packet, int frame, int subframe) {      
+  dl_packet->type = IF4p5_PACKET_TYPE; 
+  dl_packet->sub_type = IF4p5_PDLFFT;
 
   dl_packet->rsvd = 0;
   
@@ -254,9 +260,9 @@ void gen_IF4_dl_header(IF4_header_t *dl_packet, int frame, int subframe) {
 }
 
 
-void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) {  
-  ul_packet->type = IF4_PACKET_TYPE; 
-  ul_packet->sub_type = IF4_PULFFT;
+void gen_IF4p5_ul_header(IF4p5_header_t *ul_packet, int frame, int subframe) {  
+  ul_packet->type = IF4p5_PACKET_TYPE; 
+  ul_packet->sub_type = IF4p5_PULFFT;
 
   ul_packet->rsvd = 0;
   
@@ -267,9 +273,9 @@ void gen_IF4_ul_header(IF4_header_t *ul_packet, int frame, int subframe) {
 }
 
 
-void gen_IF4_prach_header(IF4_header_t *prach_packet, int frame, int subframe) {
-  prach_packet->type = IF4_PACKET_TYPE; 
-  prach_packet->sub_type = IF4_PRACH;
+void gen_IF4p5_prach_header(IF4p5_header_t *prach_packet, int frame, int subframe) {
+  prach_packet->type = IF4p5_PACKET_TYPE; 
+  prach_packet->sub_type = IF4p5_PRACH;
 
   prach_packet->rsvd = 0;
   
@@ -280,8 +286,8 @@ void gen_IF4_prach_header(IF4_header_t *prach_packet, int frame, int subframe) {
 } 
 
 
-void malloc_IF4_buffer(PHY_VARS_eNB *eNB) {
+void malloc_IF4p5_buffer(PHY_VARS_eNB *eNB) {
   // Keep the size large enough 
-  eNB->ifbuffer.tx = malloc(RAW_IF4_PRACH_SIZE_BYTES);
-  eNB->ifbuffer.rx = malloc(RAW_IF4_PRACH_SIZE_BYTES);      
+  eNB->ifbuffer.tx = malloc(RAW_IF4p5_PRACH_SIZE_BYTES);
+  eNB->ifbuffer.rx = malloc(RAW_IF4p5_PRACH_SIZE_BYTES);      
 }
diff --git a/openair1/PHY/LTE_TRANSPORT/if4_tools.h b/openair1/PHY/LTE_TRANSPORT/if4_tools.h
index 7276d97efaf5b3e556938990111d8f598adc3500..95798e5bb816f8c75f52c60e05a16160757b37c0 100644
--- a/openair1/PHY/LTE_TRANSPORT/if4_tools.h
+++ b/openair1/PHY/LTE_TRANSPORT/if4_tools.h
@@ -41,12 +41,12 @@
 #include "PHY/defs.h"
 
 /// Macro for IF4 packet type
-#define IF4_PACKET_TYPE 0x080A 
-#define IF4_PULFFT 0x0019 
-#define IF4_PDLFFT 0x0020
-#define IF4_PRACH 0x0021
+#define IF4p5_PACKET_TYPE 0x080A 
+#define IF4p5_PULFFT 0x0019 
+#define IF4p5_PDLFFT 0x0020
+#define IF4p5_PRACH 0x0021
 
-struct IF4_header {  
+struct IF4p5_header {  
   /// Type
   uint16_t type; 
   /// Sub-Type
@@ -58,17 +58,17 @@ struct IF4_header {
 
 } __attribute__ ((__packed__));
 
-typedef struct IF4_header IF4_header_t;
-#define sizeof_IF4_header_t 12 
+typedef struct IF4p5_header IF4p5_header_t;
+#define sizeof_IF4p5_header_t 12 
 
-void gen_IF4_dl_header(IF4_header_t*, int, int);
+void gen_IF4p5_dl_header(IF4p5_header_t*, int, int);
 
-void gen_IF4_ul_header(IF4_header_t*, int, int);
+void gen_IF4p5_ul_header(IF4p5_header_t*, int, int);
 
-void gen_IF4_prach_header(IF4_header_t*, int, int);
+void gen_IF4p5_prach_header(IF4p5_header_t*, int, int);
 
-void send_IF4(PHY_VARS_eNB*, int, int, uint16_t, int);
+void send_IF4p5(PHY_VARS_eNB*, int, int, uint16_t, int);
 
-void recv_IF4(PHY_VARS_eNB*, int*, int*, uint16_t*, uint32_t*);
+void recv_IF4p5(PHY_VARS_eNB*, int*, int*, uint16_t*, uint32_t*);
 
-void malloc_IF4_buffer(PHY_VARS_eNB*);
+void malloc_IF4p5_buffer(PHY_VARS_eNB*);
diff --git a/openair1/PHY/LTE_TRANSPORT/if5_tools.c b/openair1/PHY/LTE_TRANSPORT/if5_tools.c
index 59a3e70cd670768be576c4b7201af62b66f8eb29..92d516d7e878343efc04d0742c39893b1950e48a 100644
--- a/openair1/PHY/LTE_TRANSPORT/if5_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/if5_tools.c
@@ -41,7 +41,7 @@
 #include "PHY/defs.h"
 
 #include "targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
-
+#include "UTIL/LOG/vcd_signal_dumper.h"
 
 void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe, uint8_t *seqno, uint16_t packet_type) {      
   
@@ -54,6 +54,8 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe
   uint32_t spp_eth  = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_packet;
   uint32_t spsf     = (uint32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10;
   
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );  
+
   if (packet_type == IF5_RRH_GW_DL) {    
 
     for (i=0; i < fp->nb_antennas_tx; i++)
@@ -143,6 +145,8 @@ void send_IF5(PHY_VARS_eNB *eNB, openair0_timestamp proc_timestamp, int subframe
   }  
   
   free(tx_buffer);
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );  
+
   return;  		    
 }
 
@@ -158,6 +162,8 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram
   int32_t spsf     = (int32_t) eNB->ifdevice.openair0_cfg->samples_per_frame/10;
 
   openair0_timestamp timestamp[spsf / spp_eth];
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 );  
   
   if (packet_type == IF5_RRH_GW_DL) {
         
@@ -205,6 +211,8 @@ void recv_IF5(PHY_VARS_eNB *eNB, openair0_timestamp *proc_timestamp, int subfram
   } else {
     AssertFatal(1==0, "recv_IF5 - Unknown packet_type %x", packet_type);     
   }  
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 );  
   
   return;  
 }
diff --git a/openair1/PHY/LTE_TRANSPORT/phich.c b/openair1/PHY/LTE_TRANSPORT/phich.c
index d5dff4ef306d28868085ece0e6dd050c6011f917..b3b45453505dc066c6a64adfec162444ab3db8ac 100644
--- a/openair1/PHY/LTE_TRANSPORT/phich.c
+++ b/openair1/PHY/LTE_TRANSPORT/phich.c
@@ -1424,8 +1424,7 @@ void rx_phich(PHY_VARS_UE *ue,
 void generate_phich_top(PHY_VARS_eNB *eNB,
                         eNB_rxtx_proc_t *proc,
 			int16_t amp,
-                        uint8_t sect_id,
-                        uint8_t abstraction_flag)
+                        uint8_t sect_id)
 {
 
 
@@ -1486,7 +1485,7 @@ void generate_phich_top(PHY_VARS_eNB *eNB,
                 ulsch[UE_id]->harq_processes[harq_pid]->first_rb);
         }
 
-        if (abstraction_flag == 0) {
+        if (eNB->abstraction_flag == 0) {
           generate_phich(frame_parms,
                          amp,//amp*2,
                          nseq_PHICH,
diff --git a/openair1/PHY/LTE_TRANSPORT/pmch.c b/openair1/PHY/LTE_TRANSPORT/pmch.c
index 325e0918a50515e0c3cd1837e0e1ef27365bb0a8..93922207bb98e2222dd492d1cbb31dcffa21ec8f 100644
--- a/openair1/PHY/LTE_TRANSPORT/pmch.c
+++ b/openair1/PHY/LTE_TRANSPORT/pmch.c
@@ -190,7 +190,7 @@ int is_pmch_subframe(uint32_t frame, int subframe, LTE_DL_FRAME_PARMS *frame_par
   return(0);
 }
 
-void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx, int abstraction_flag)
+void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx)
 {
 
   LTE_eNB_DLSCH_t *dlsch = eNB->dlsch_MCH;
@@ -227,7 +227,7 @@ void fill_eNB_dlsch_MCH(PHY_VARS_eNB *eNB,int mcs,int ndi,int rvidx, int abstrac
     break;
   }
 
-  if (abstraction_flag) {
+  if (eNB->abstraction_flag) {
     eNB_transport_info[eNB->Mod_id][eNB->CC_id].cntl.pmch_flag=1;
     eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_pmch=1; // assumption: there is always one pmch in each SF
     eNB_transport_info[eNB->Mod_id][eNB->CC_id].num_common_dci=0;
@@ -286,13 +286,13 @@ void fill_UE_dlsch_MCH(PHY_VARS_UE *ue,int mcs,int ndi,int rvidx,int eNB_id)
   }
 }
 
-void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a,int abstraction_flag)
+void generate_mch(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t *a)
 {
 
   int G;
   int subframe = proc->subframe_tx;
 
-  if (abstraction_flag != 0) {
+  if (eNB->abstraction_flag != 0) {
     if (eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]!=0)
       printf("[PHY][EMU] PMCH transport block position is different than zero %d \n", eNB_transport_info_TB_index[eNB->Mod_id][eNB->CC_id]);
 
diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c
index 471b572a5642f1a32836b589e6d8093b05f5f602..dfdf4ed47085004b22e842c207b4c6aeaa23b175 100644
--- a/openair1/PHY/LTE_TRANSPORT/prach.c
+++ b/openair1/PHY/LTE_TRANSPORT/prach.c
@@ -1183,7 +1183,7 @@ void rx_prach(PHY_VARS_eNB *eNB,
 
 
   if ((eNB->node_function == eNodeB_3GPP) ||
-      (eNB->node_function == NGFI_RRU_IF4)) { // compute the DFTs of the PRACH temporal resources
+      (eNB->node_function == NGFI_RRU_IF4p5)) { // compute the DFTs of the PRACH temporal resources
     // Do forward transform
     for (aa=0; aa<nb_ant_rx; aa++) {
       prach2 = prach[aa] + (Ncp<<1);
@@ -1269,7 +1269,7 @@ void rx_prach(PHY_VARS_eNB *eNB,
     }
   }
 
-  if (eNB->node_function == NGFI_RRU_IF4) {
+  if (eNB->node_function == NGFI_RRU_IF4p5) {
     k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL;
     
     if (k<0) {
@@ -1281,12 +1281,10 @@ void rx_prach(PHY_VARS_eNB *eNB,
     k*=2;
     
     /// **** send_IF4 of rxsigF to RCC **** ///    
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 );   
-    send_IF4(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4_PRACH, k);
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 );   
+    send_IF4p5(eNB, eNB->proc.frame_rx, eNB->proc.subframe_rx, IF4p5_PRACH, k);
 
     return;
-  } else if (eNB->node_function == NGFI_RCC_IF4) {
+  } else if (eNB->node_function == NGFI_RCC_IF4p5) {
     k = (12*n_ra_prb) - 6*eNB->frame_parms.N_RB_UL;
     
     if (k<0) {
@@ -1305,7 +1303,7 @@ void rx_prach(PHY_VARS_eNB *eNB,
   
   // in case of RCC and prach received rx_thread wakes up prach
 
-  // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4
+  // here onwards is for eNodeB_3GPP or NGFI_RCC_IF4p5
 
   preamble_offset_old = 99;
 
diff --git a/openair1/PHY/LTE_TRANSPORT/proto.h b/openair1/PHY/LTE_TRANSPORT/proto.h
index 6993dd18c01a44eb9b86541dd6c1bf5cae75e3f7..c3922b13d51f2f26c078a79fabdad5b3424dfaec 100644
--- a/openair1/PHY/LTE_TRANSPORT/proto.h
+++ b/openair1/PHY/LTE_TRANSPORT/proto.h
@@ -232,7 +232,7 @@ int mch_modulation(int32_t **txdataF,
     @param abstraction_flag
 
 */
-void generate_mch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t *a,int abstraction_flag);
+void generate_mch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t *a);
 
 /** \brief This function generates the frequency-domain pilots (cell-specific downlink reference signals)
     @param phy_vars_eNB Pointer to eNB variables
@@ -240,10 +240,8 @@ void generate_mch(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t *a,in
     @param mcs MCS for MBSFN
     @param ndi new data indicator
     @param rdvix
-    @param abstraction_flag
-
 */
-void fill_eNB_dlsch_MCH(PHY_VARS_eNB *phy_vars_eNB,int mcs,int ndi,int rvidx,int abstraction_flag);
+void fill_eNB_dlsch_MCH(PHY_VARS_eNB *phy_vars_eNB,int mcs,int ndi,int rvidx);
 
 /** \brief This function generates the frequency-domain pilots (cell-specific downlink reference signals)
     @param phy_vars_ue Pointer to UE variables
@@ -1546,8 +1544,7 @@ uint32_t ulsch_decoding_emul(PHY_VARS_eNB *phy_vars_eNB,
 void generate_phich_top(PHY_VARS_eNB *phy_vars_eNB,
 			eNB_rxtx_proc_t *proc,
                         int16_t amp,
-                        uint8_t sect_id,
-                        uint8_t abstraction_flag);
+                        uint8_t sect_id);
 
 /* \brief  This routine demodulates the PHICH and updates PUSCH/ULSCH parameters.
    @param phy_vars_ue Pointer to UE variables
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 3b3f277894187d06427dc1090b728c1a172c6235..7bcc3810ae66fc16317b6a3eec3f5640d362413a 100755
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -161,8 +161,9 @@ typedef enum  {
   eNodeB_3GPP=0,   // classical eNodeB function
   eNodeB_3GPP_BBU, // eNodeB with NGFI IF5
   NGFI_RRU_IF5,    // NGFI_RRU with IF5
-  NGFI_RRU_IF4,    // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4) 
-  NGFI_RCC_IF4     // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4) 
+  NGFI_RRU_IF4p5,    // NGFI_RRU (NGFI remote radio-unit, currently split at common - ue_specific interface, IF4p5) 
+  NGFI_RCC_IF4p5,     // NGFI_RCC (NGFI radio cloud center, currently split at common - ue_specific interface, IF4p5) 
+  NGFI_RAU_IF4p5
 } eNB_func_t;
 
 typedef enum {
@@ -187,6 +188,20 @@ typedef struct ral_threshold_phy_s {
 } ral_threshold_phy_t;
 #endif
 
+/// Top-level PHY Data Structure for RN
+typedef struct {
+  /// Module ID indicator for this instance
+  uint8_t Mod_id;
+  uint32_t frame;
+  // phy_vars_eNB
+  // phy_vars ue
+  // cuurently only used to store and forward the PMCH
+  uint8_t mch_avtive[10];
+  uint8_t sync_area[10]; // num SF
+  LTE_UE_DLSCH_t   *dlsch_rn_MCH[10];
+
+} PHY_VARS_RN;
+
 /// Context data structure for RX/TX portion of subframe processing
 typedef struct {
   /// Component Carrier index
@@ -340,6 +355,15 @@ typedef struct PHY_VARS_eNB_s {
   eNB_proc_t           proc;
   eNB_func_t           node_function;
   eNB_timing_t         node_timing;
+  int                  abstraction_flag;
+  void                 (*do_prach)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc);
+  void                 (*fep)(struct PHY_VARS_eNB_s *eNB,eNB_proc_t *proc);
+  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,eNB_proc_t *proc,int *frame, int *subframe);
+  int                  (*start_rf)(struct PHY_VARS_eNB_s *eNB);
+  int                  (*start_if)(struct PHY_VARS_eNB_s *eNB);
   uint8_t              local_flag;
   uint32_t             rx_total_gain_dB;
   LTE_DL_FRAME_PARMS   frame_parms;
@@ -785,19 +809,7 @@ typedef struct {
 #endif
 } PHY_VARS_UE;
 
-/// Top-level PHY Data Structure for RN
-typedef struct {
-  /// Module ID indicator for this instance
-  uint8_t Mod_id;
-  uint32_t frame;
-  // phy_vars_eNB
-  // phy_vars ue
-  // cuurently only used to store and forward the PMCH
-  uint8_t mch_avtive[10];
-  uint8_t sync_area[10]; // num SF
-  LTE_UE_DLSCH_t   *dlsch_rn_MCH[10];
 
-} PHY_VARS_RN;
 
 #include "PHY/INIT/defs.h"
 #include "PHY/LTE_REFSIG/defs.h"
diff --git a/openair1/SCHED/defs.h b/openair1/SCHED/defs.h
index 279703b78ac341dda70b9fdd8e08caff4c482d52..a9f8633e30407292c6b83d78775d20aa6f7e0783 100644
--- a/openair1/SCHED/defs.h
+++ b/openair1/SCHED/defs.h
@@ -164,20 +164,18 @@ void phy_procedures_UE_S_RX(PHY_VARS_UE *phy_vars_ue,uint8_t eNB_id,uint8_t abst
   @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying
   @param phy_vars_rn pointer to the RN variables
 */
-void phy_procedures_eNB_TX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn);
+void phy_procedures_eNB_TX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type,PHY_VARS_RN *phy_vars_rn);
 
 /*! \brief Scheduling for eNB RX UE-specific procedures in normal subframes.
   @param phy_vars_eNB Pointer to eNB variables on which to act
   @param proc Pointer to RXn-TXnp4 proc information
-  @param abstraction_flag Indicator of PHY abstraction
   @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying
 */
-void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type);
+void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type);
 
 /*! \brief Scheduling for eNB TX procedures in TDD S-subframes.
   @param phy_vars_eNB Pointer to eNB variables on which to act
   @param proc Pointer to RXn-TXnp4 proc information
-  @param abstraction_flag Indicator of PHY abstraction
   @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying
 */
 
@@ -185,29 +183,26 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *pr
   @param phy_vars_eNB Pointer to eNB variables on which to act
   @param abstraction_flag Indicator of PHY abstraction
 */
-void phy_procedures_eNB_common_RX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag);
+void phy_procedures_eNB_common_RX(PHY_VARS_eNB *phy_vars_eNB);
 
 /*! \brief Scheduling for eNB TX procedures in TDD S-subframes.
   @param phy_vars_eNB Pointer to eNB variables on which to act
-  @param abstraction_flag Indicator of PHY abstraction
   @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying
 */
 
-void phy_procedures_eNB_S_TX(PHY_VARS_eNB *phy_vars_eNB,uint8_t abstraction_flag,relaying_type_t r_type);
+void phy_procedures_eNB_S_TX(PHY_VARS_eNB *phy_vars_eNB,relaying_type_t r_type);
 
 /*! \brief Scheduling for eNB RX procedures in TDD S-subframes.
   @param phy_vars_eNB Pointer to eNB variables on which to act
-  @param abstraction_flag Indicator of PHY abstraction
   @param r_type indicates the relaying operation: 0: no_relaying, 1: unicast relaying type 1, 2: unicast relaying type 2, 3: multicast relaying
 */
-void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type);
+void phy_procedures_eNB_S_RX(PHY_VARS_eNB *phy_vars_eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type);
 
 /*! \brief Scheduling for eNB PRACH RX procedures 
   @param phy_vars_eNB Pointer to eNB variables on which to act
   @param proc Pointer to RXn-TXnp4 proc information
-  @param abstraction_flag Indicator of PHY abstraction
 */
-void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag);
+void prach_procedures(PHY_VARS_eNB *eNB);
 
 /*! \brief Function to compute subframe type as a function of Frame type and TDD Configuration (implements Table 4.2.2 from 36.211, p.11 from version 8.6) and subframe index.
   @param frame_parms Pointer to DL frame parameter descriptor
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 6be9ff208071021d2b622bc75c39644c2490746b..593d2b61fb6a2e809b9076e624ce97fc6c43179c 100755
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -180,7 +180,7 @@ int32_t add_ue(int16_t rnti, PHY_VARS_eNB *eNB)
 
 int mac_phy_remove_ue(module_id_t Mod_idP,rnti_t rntiP) {
   uint8_t i;
-  int j,CC_id;
+  int CC_id;
   PHY_VARS_eNB *eNB;
 
   for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
@@ -295,7 +295,7 @@ void phy_procedures_emos_eNB_TX(unsigned char subframe, PHY_VARS_eNB *eNB)
 
 
 
-void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t abstraction_flag,relaying_type_t r_type)
+void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,relaying_type_t r_type)
 {
   UNUSED(r_type);
   int subframe = proc->subframe_rx;
@@ -305,7 +305,7 @@ void phy_procedures_eNB_S_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,uint8_t abs
 #endif
 
 
-  if (abstraction_flag == 0) {
+  if (eNB->abstraction_flag == 0) {
     lte_eNB_I0_measurements(eNB,
 			    subframe,
                             0,
@@ -392,7 +392,7 @@ unsigned int taus(void);
 DCI_PDU DCI_pdu_tmp;
 
 
-void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, int abstraction_flag,relaying_type_t r_type) {
+void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn,relaying_type_t r_type) {
 
 
 #ifdef Rel10
@@ -403,7 +403,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, in
 
   int subframe = proc->subframe_tx;
 
-  if (abstraction_flag==0) {
+  if (eNB->abstraction_flag==0) {
     // This is DL-Cell spec pilots in Control region
     generate_pilots_slot(eNB,
 			 eNB->common_vars.txdataF[0],
@@ -464,9 +464,9 @@ void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, in
   }// switch
   
   if (mch_pduP) {
-    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0, abstraction_flag);
+    fill_eNB_dlsch_MCH(eNB,mch_pduP->mcs,1,0);
     // Generate PMCH
-    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload,abstraction_flag);
+    generate_mch(eNB,proc,(uint8_t*)mch_pduP->payload);
   } else {
     LOG_D(PHY,"[eNB/RN] Frame %d subframe %d: MCH not generated \n",proc->frame_tx,subframe);
   }
@@ -474,7 +474,7 @@ void pmch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,PHY_VARS_RN *rn, in
 #endif
 }
 
-void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstraction_flag) {
+void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
 
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
   int **txdataF = eNB->common_vars.txdataF[0];
@@ -483,7 +483,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
   int frame = proc->frame_tx;
 
   // generate Cell-Specific Reference Signals for both slots
-  if (abstraction_flag==0) {
+  if (eNB->abstraction_flag==0) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_RS_TX,1);
     generate_pilots_slot(eNB,
 			 txdataF,
@@ -502,7 +502,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
   // First half of PSS/SSS (FDD, slot 0)
   if (subframe == 0) {
     if ((fp->frame_type == FDD) &&
-	(abstraction_flag==0)) {
+	(eNB->abstraction_flag==0)) {
       generate_pss(txdataF,
 		   AMP,
 		   fp,
@@ -585,7 +585,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
     /// First half of SSS (TDD, slot 1)
     
     if ((fp->frame_type == TDD)&&
-	(abstraction_flag==0)){
+	(eNB->abstraction_flag==0)){
       generate_sss(txdataF,
 		   AMP,
 		   fp,
@@ -594,7 +594,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
     }
 
     /// generate PBCH
-    if (abstraction_flag==0) {
+    if (eNB->abstraction_flag==0) {
       generate_pbch(&eNB->pbch,
                     txdataF,
                     AMP,
@@ -611,7 +611,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
   }
   else if ((subframe == 1) &&
 	   (fp->frame_type == TDD)&&
-	   (abstraction_flag==0)) {
+	   (eNB->abstraction_flag==0)) {
     generate_pss(txdataF,
 		 AMP,
 		 fp,
@@ -622,7 +622,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
   // Second half of PSS/SSS (FDD, slot 10)
   else if ((subframe == 5) && 
 	   (fp->frame_type == FDD) &&
-	   (abstraction_flag==0)) {
+	   (eNB->abstraction_flag==0)) {
     generate_pss(txdataF,
 		 AMP,
 		 &eNB->frame_parms,
@@ -639,7 +639,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
   //  Second-half of SSS (TDD, slot 11)
   else if ((subframe == 5) &&
 	   (fp->frame_type == TDD) &&
-	   (abstraction_flag==0)) {
+	   (eNB->abstraction_flag==0)) {
     generate_sss(txdataF,
 		 AMP,
 		 fp,
@@ -650,7 +650,7 @@ void common_signal_procedures (PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int abstr
   // Second half of PSS (TDD, slot 12)
   else if ((subframe == 6) &&
 	   (fp->frame_type == TDD) &&
-	   (abstraction_flag==0)) {
+	   (eNB->abstraction_flag==0)) {
     generate_pss(txdataF,
 		 AMP,
 		 fp,
@@ -867,7 +867,7 @@ void generate_eNB_ulsch_params(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,DCI_ALLOC
 
 }
 
-void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols,int abstraction_flag) {
+void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *dlsch, LTE_eNB_DLSCH_t *dlsch1,LTE_eNB_UE_stats *ue_stats,int ra_flag,int num_pdcch_symbols) {
 
   int frame=proc->frame_tx;
   int subframe=proc->subframe_tx;
@@ -1025,7 +1025,7 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
 #endif
   }
 
-  if (abstraction_flag==0) {
+  if (eNB->abstraction_flag==0) {
 
     LOG_D(PHY,"Generating DLSCH/PDSCH %d\n",ra_flag);
     // 36-212
@@ -1083,7 +1083,6 @@ void pdsch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,LTE_eNB_DLSCH_t *d
 
 void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
 			   eNB_rxtx_proc_t *proc,
-			   uint8_t abstraction_flag,
                            relaying_type_t r_type,
 			   PHY_VARS_RN *rn)
 {
@@ -1145,7 +1144,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
   }
 
   // clear the transmit data array for the current subframe
-  if (abstraction_flag==0) {
+  if (eNB->abstraction_flag==0) {
     for (aa=0; aa<fp->nb_antennas_tx_eNB; aa++) {      
       memset(&eNB->common_vars.txdataF[0][aa][subframe*fp->ofdm_symbol_size*(fp->symbols_per_tti)],
              0,fp->ofdm_symbol_size*(fp->symbols_per_tti)*sizeof(int32_t));
@@ -1153,11 +1152,11 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
   }
 
   if (is_pmch_subframe(frame,subframe,fp)) {
-    pmch_procedures(eNB,proc,rn,abstraction_flag,r_type);
+    pmch_procedures(eNB,proc,rn,r_type);
   }
   else {
     // this is not a pmch subframe, so generate PSS/SSS/PBCH
-    common_signal_procedures(eNB,proc,abstraction_flag);
+    common_signal_procedures(eNB,proc);
   }
 
 #if defined(SMBV) 
@@ -1283,7 +1282,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
     eNB->num_common_dci[(subframe)&1]=0;
   }
 
-  if (abstraction_flag == 0) {
+  if (eNB->abstraction_flag == 0) {
 
     if (DCI_pdu->Num_ue_spec_dci+DCI_pdu->Num_common_dci > 0) {
       LOG_D(PHY,"[eNB %"PRIu8"] Frame %d, subframe %d: Calling generate_dci_top (pdcch) (common %"PRIu8",ue_spec %"PRIu8")\n",eNB->Mod_id,frame, subframe,
@@ -1316,7 +1315,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
 
   if ((eNB->dlsch_SI) && (eNB->dlsch_SI->active == 1)) {
 
-    pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols,abstraction_flag);
+    pdsch_procedures(eNB,proc,eNB->dlsch_SI,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,0,num_pdcch_symbols);
 
 #if defined(SMBV) 
 
@@ -1349,7 +1348,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
 	  eNB->ulsch[(uint32_t)UE_id]->Msg3_frame,
 	  eNB->ulsch[(uint32_t)UE_id]->Msg3_subframe);
     
-    pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols,abstraction_flag);
+    pdsch_procedures(eNB,proc,eNB->dlsch_ra,(LTE_eNB_DLSCH_t*)NULL,(LTE_eNB_UE_stats*)NULL,1,num_pdcch_symbols);
     
     
     eNB->dlsch_ra->active = 0;
@@ -1362,7 +1361,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
 	  (eNB->dlsch[(uint8_t)UE_id][0]->rnti>0)&&
 	  (eNB->dlsch[(uint8_t)UE_id][0]->active == 1)) {
 
-	pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols,abstraction_flag);
+	pdsch_procedures(eNB,proc,eNB->dlsch[(uint8_t)UE_id][0],eNB->dlsch[(uint8_t)UE_id][1],&eNB->UE_stats[(uint32_t)UE_id],0,num_pdcch_symbols);
 
 
       }
@@ -1385,8 +1384,7 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
       generate_phich_top(eNB,
 			 proc,
 			 AMP,
-			 0,
-			 abstraction_flag);
+			 0);
     }
 
 
@@ -1395,24 +1393,6 @@ void phy_procedures_eNB_TX(PHY_VARS_eNB *eNB,
   phy_procedures_emos_eNB_TX(subframe, eNB);
 #endif
 
-#if !(defined(EXMIMO) || defined(OAI_USRP) || defined (CPRIGW))
-  
-  if (abstraction_flag==0)
-    {
-      start_meas(&eNB->ofdm_mod_stats);
-      do_OFDM_mod(eNB->common_vars.txdataF[0],
-		  eNB->common_vars.txdata[0],
-		  frame,subframe<<1,
-		  fp);
-      do_OFDM_mod(eNB->common_vars.txdataF[0],
-		  eNB->common_vars.txdata[0],
-		  frame,1+(subframe<<1),
-		  fp);
-      stop_meas(&eNB->ofdm_mod_stats);
-    }
-
-#endif
-
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_TX+(subframe&1),0);
   stop_meas(&eNB->phy_proc_tx);
   
@@ -1869,8 +1849,7 @@ void get_n1_pucch_eNB(PHY_VARS_eNB *eNB,
   }
 }
 
-void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag)
-{
+void prach_procedures(PHY_VARS_eNB *eNB) {
 
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
   uint16_t preamble_energy_list[64],preamble_delay_list[64];
@@ -1881,10 +1860,11 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag)
   int frame = eNB->proc.frame_prach;
   uint8_t CC_id = eNB->CC_id;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
   memset(&preamble_energy_list[0],0,64*sizeof(uint16_t));
   memset(&preamble_delay_list[0],0,64*sizeof(uint16_t));
 
-  if (abstraction_flag == 0) {
+  if (eNB->abstraction_flag == 0) {
     LOG_D(PHY,"[eNB %d][RAPROC] Frame %d, Subframe %d : PRACH RX Signal Power : %d dBm\n",eNB->Mod_id, 
           frame,subframe,dB_fixed(signal_energy(&eNB->common_vars.rxdata[0][0][subframe*fp->samples_per_tti],512)) - eNB->rx_total_gain_dB);
 
@@ -1984,9 +1964,10 @@ void prach_procedures(PHY_VARS_eNB *eNB,uint8_t abstraction_flag)
             eNB->Mod_id,frame, subframe);
     }
   }
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
 }
 
-void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) {
+void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
 
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
   uint8_t SR_payload = 0,*pucch_payload=NULL,pucch_payload0[2]= {0,0},pucch_payload1[2]= {0,0};
@@ -2059,7 +2040,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
 	eNB->UE_stats[UE_id].sr_total++;
 
 
-	if (abstraction_flag == 0)
+	if (eNB->abstraction_flag == 0)
 	  metric0_SR = rx_pucch(eNB,
 				pucch_format1,
 				UE_id,
@@ -2115,7 +2096,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
 	
 	LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload);
 	
-	if (abstraction_flag == 0) {
+	if (eNB->abstraction_flag == 0) {
 	  
 	  
 	  
@@ -2160,7 +2141,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
       
       LOG_D(PHY,"Demodulating PUCCH for ACK/NAK: n1_pucch0 %d (%d), SR_payload %d\n",n1_pucch0,eNB->scheduling_request_config[UE_id].sr_PUCCH_ResourceIndex,SR_payload);
       
-      if (abstraction_flag == 0) {
+      if (eNB->abstraction_flag == 0) {
 	
 	
 	
@@ -2236,7 +2217,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
 	      n1_pucch0,n1_pucch1,n1_pucch2,n1_pucch3,format);
 #endif
 
-	if (abstraction_flag == 0)
+	if (eNB->abstraction_flag == 0)
 	  metric0_SR = rx_pucch(eNB,
 				format,
 				UE_id,
@@ -2268,7 +2249,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
 
 	// Check n1_pucch0 metric
 	if (n1_pucch0 != -1) {
-	  if (abstraction_flag == 0)
+	  if (eNB->abstraction_flag == 0)
 	    metric0 = rx_pucch(eNB,
 			       format,
 			       UE_id,
@@ -2293,7 +2274,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
 
 	// Check n1_pucch1 metric
 	if (n1_pucch1 != -1) {
-	  if (abstraction_flag == 0)
+	  if (eNB->abstraction_flag == 0)
 	    metric1 = rx_pucch(eNB,
 			       format,
 			       UE_id,
@@ -2350,7 +2331,7 @@ void pucch_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq
 }
 
 
-void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid,const uint8_t abstraction_flag) {
+void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_pid) {
 
   uint8_t access_mode;
   int num_active_cba_groups;
@@ -2375,7 +2356,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p
 	  UE_id, (uint16_t)eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups],mode_string[eNB->UE_stats[UE_id].mode]);
 #endif
     
-    if (abstraction_flag==0) {
+    if (eNB->abstraction_flag==0) {
       rx_ulsch(eNB,proc,
 	       eNB->UE_stats[UE_id].sector,  // this is the effective sector id
 	       UE_id,
@@ -2392,7 +2373,7 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p
     
 #endif
     
-    if (abstraction_flag == 0) {
+    if (eNB->abstraction_flag == 0) {
       ret = ulsch_decoding(eNB,proc,
 			   UE_id,
 			   0, // control_only_flag
@@ -2509,116 +2490,121 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p
 
 }
 
-
-void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB,const uint8_t abstraction_flag) {
+void eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc) {
 
   int l;
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
+  remove_7_5_kHz(eNB,proc->subframe_rx<<1);
+  remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1));
+  for (l=0; l<fp->symbols_per_tti/2; l++) {
+    slot_fep_ul(fp,
+		&eNB->common_vars,
+		l,
+		proc->subframe_rx<<1,
+		  0,
+		0
+		);
+    slot_fep_ul(fp,
+		&eNB->common_vars,
+		l,
+		1+(proc->subframe_rx<<1),
+		0,
+		0
+		);
+  }
+  
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
+  
+  if (eNB->node_function == NGFI_RRU_IF4p5) {
+    /// **** send_IF4 of rxdataF to RCC (no prach now) **** ///
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 );   
+    send_IF4p5(eNB, proc->frame_rx, proc->subframe_rx, IF4p5_PULFFT, 0);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 );   
+    }    
+}
+
+void eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc) {
+
+  uint8_t seqno=0;
+
+  /// **** 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 );          
+
+}
+
+void do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc) {
+
+  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
+
+  // check if we have to detect PRACH first
+  if (is_prach_subframe(fp,proc->frame_rx,proc->subframe_rx)>0) { 
+    /* accept some delay in processing - up to 5ms */
+    int i;
+    for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) {
+      LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
+      usleep(500);
+    }
+    if (proc->instance_cnt_prach == 0) {
+      exit_fun( "PRACH thread busy" );
+      return;
+    }
+    
+    // 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;
+    }
+    
+    ++proc->instance_cnt_prach;
+    // set timing for prach thread
+    proc->frame_prach = proc->frame_rx;
+    proc->subframe_prach = proc->subframe_rx;
+    
+    // the thread 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;
+    }
+    
+    pthread_mutex_unlock( &proc->mutex_prach );
+  }
+
+}
+
+void phy_procedures_eNB_common_RX(PHY_VARS_eNB *eNB){
+
+
   eNB_proc_t *proc = &eNB->proc;
 
   const int subframe = proc->subframe_rx;
   const int frame = proc->frame_rx;
 
-  uint8_t seqno=0;
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 1 );
   
   start_meas(&eNB->phy_proc_rx);
 
-#ifdef DEBUG_PHY_PROC
+
   LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_common_RX(%d)\n",eNB->Mod_id,frame,subframe);
-#endif
 
-  if (abstraction_flag==0) {
-
-    if ((eNB->node_function == NGFI_RRU_IF4) || 
-        (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);
-      remove_7_5_kHz(eNB,proc->subframe_rx<<1);
-      remove_7_5_kHz(eNB,1+(proc->subframe_rx<<1));
-      for (l=0; l<fp->symbols_per_tti/2; l++) {
-        slot_fep_ul(fp,
-                    &eNB->common_vars,
-                    l,
-                    proc->subframe_rx<<1,
-                    0,
-                    0
-                    );
-        slot_fep_ul(fp,
-                    &eNB->common_vars,
-                    l,
-                    1+(proc->subframe_rx<<1),
-                    0,
-                    0
-                    );
-      }
 
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
+  if (eNB->fep) eNB->fep(eNB,proc);
 
-      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, proc->frame_rx, proc->subframe_rx, IF4_PULFFT, 0);
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 );   
-      }    
-    }
-    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 );          
-    }
-    
-    /// **** 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
-      /* accept some delay in processing - up to 5ms */
-      int i;
-      for (i = 0; i < 10 && proc->instance_cnt_prach == 0; i++) {
-        LOG_W(PHY,"[eNB] Frame %d Subframe %d, eNB PRACH thread busy (IC %d)!!\n", proc->frame_rx,proc->subframe_rx,proc->instance_cnt_prach);
-        usleep(500);
-      }
-      if (proc->instance_cnt_prach == 0) {
-        exit_fun( "PRACH thread busy" );
-        return;
-      }
-
-      // 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;
-      }
-      
-      ++proc->instance_cnt_prach;
-      // set timing for prach thread
-      proc->frame_prach = proc->frame_rx;
-      proc->subframe_prach = proc->subframe_rx;
-      
-      // the thread 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;
-      }
-
-      pthread_mutex_unlock( &proc->mutex_prach );
-    }
-    
-  } else { // grab transport channel information from network interface
+  if (eNB->do_prach) eNB->do_prach(eNB,proc);
+  
 
-  }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_COMMON+(subframe&1), 0 );
 }
 
 
-void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const uint8_t abstraction_flag,const relaying_type_t r_type)
+void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const relaying_type_t r_type)
 {
   //RX processing for ue-specific resources (i
   UNUSED(r_type);
@@ -2664,7 +2650,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
   // Do PUCCH processing first
 
   for (i=0; i<NUMBER_OF_UE_MAX; i++) {
-    pucch_procedures(eNB,proc,i,harq_pid,abstraction_flag);
+    pucch_procedures(eNB,proc,i,harq_pid);
   }
 
   for (i=0; i<NUMBER_OF_UE_MAX; i++) {
@@ -2749,7 +2735,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
       eNB->pusch_stats_mcs[i][(frame*10)+subframe] = eNB->ulsch[i]->harq_processes[harq_pid]->mcs;
       start_meas(&eNB->ulsch_demodulation_stats);
 
-      if (abstraction_flag==0) {
+      if (eNB->abstraction_flag==0) {
         rx_ulsch(eNB,proc,
                  eNB->UE_stats[i].sector,  // this is the effective sector id
                  i,
@@ -2770,7 +2756,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
 
       start_meas(&eNB->ulsch_decoding_stats);
 
-      if (abstraction_flag == 0) {
+      if (eNB->abstraction_flag == 0) {
         ret = ulsch_decoding(eNB,proc,
                              i,
                              0, // control_only_flag
@@ -3082,7 +3068,7 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
         } // Msg3_flag == 0
 
         // estimate timing advance for MAC
-        if (abstraction_flag == 0) {
+        if (eNB->abstraction_flag == 0) {
           sync_pos = lte_est_timing_advance_pusch(eNB,i);
           eNB->UE_stats[i].timing_advance_update = sync_pos - fp->nb_prefix_samples/4; //to check
         }
@@ -3169,10 +3155,10 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
     }
 
     // CBA (non-LTE)
-    cba_procedures(eNB,proc,i,harq_pid,abstraction_flag);
+    cba_procedures(eNB,proc,i,harq_pid);
   } // loop i=0 ... NUMBER_OF_UE_MAX-1
 
-  if (abstraction_flag == 0) {
+  if (eNB->abstraction_flag == 0) {
     lte_eNB_I0_measurements(eNB,
 			    subframe,
 			    0,
diff --git a/openair2/ENB_APP/enb_config.c b/openair2/ENB_APP/enb_config.c
index cecdf623efd466d47e127da78532acd2489214e5..770b4afa251ea1d2598a25ed984ffcd9443d7f77 100755
--- a/openair2/ENB_APP/enb_config.c
+++ b/openair2/ENB_APP/enb_config.c
@@ -887,10 +887,12 @@ const Enb_properties_array_t *enb_config_init(char* lib_config_file_name_pP)
                 enb_properties.properties[enb_properties_index]->cc_node_function[j] = eNodeB_3GPP;
               } else if (strcmp(cc_node_function, "eNodeB_3GPP_BBU") == 0) {
                 enb_properties.properties[enb_properties_index]->cc_node_function[j] = eNodeB_3GPP_BBU;
-              } else if (strcmp(cc_node_function, "NGFI_RCC_IF4") == 0) {
-                enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RCC_IF4;
-              } else if (strcmp(cc_node_function, "NGFI_RRU_IF4") == 0) {
-                enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF4;
+              } else if (strcmp(cc_node_function, "NGFI_RCC_IF4p5") == 0) {
+                enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RCC_IF4p5;
+              } else if (strcmp(cc_node_function, "NGFI_RAU_IF4p5") == 0) {
+                enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RAU_IF4p5;
+              } else if (strcmp(cc_node_function, "NGFI_RRU_IF4p5") == 0) {
+                enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF4p5;
               } else if (strcmp(cc_node_function, "NGFI_RRU_IF5") == 0) {
                 enb_properties.properties[enb_properties_index]->cc_node_function[j] = NGFI_RRU_IF5;
               } else {
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c
index faf19c9fda7b2bd9628850f84496c3b705641de7..02ca6ee7eb4018ce334dab2c80cc35826acc21ac 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/eth_raw.c
@@ -201,7 +201,7 @@ int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, voi
 
 
 
-int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
 
   int nblocks = nsamps;  
   int bytes_sent = 0;
@@ -211,14 +211,14 @@ int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp,
   
   ssize_t packet_size;
   
-  if (flags == IF4_PDLFFT) {
-    packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks);    
-  } else if (flags == IF4_PULFFT) {
-    packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks);    
+  if (flags == IF4p5_PDLFFT) {
+    packet_size = RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks);    
+  } else if (flags == IF4p5_PULFFT) {
+    packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks);    
   } else if (flags == IF5_MOBIPASS) {
     packet_size = RAW_IF5_MOBIPASS_SIZE_BYTES;
   } else {
-    packet_size = RAW_IF4_PRACH_SIZE_BYTES;
+    packet_size = RAW_IF4p5_PRACH_SIZE_BYTES;
   }
   
   eth->tx_nsamps = nblocks;
@@ -304,7 +304,7 @@ int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, voi
 
 
 
-int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
+int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc) {
 
   // Read nblocks info from packet itself
   int nblocks = nsamps;  
@@ -312,8 +312,8 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp,
   eth_state_t *eth = (eth_state_t*)device->priv;
   int Mod_id = device->Mod_id;
   
-  ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t;      
-  IF4_header_t *test_header = (IF4_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES);
+  ssize_t packet_size = MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t;      
+  IF4p5_header_t *test_header = (IF4p5_header_t*)(buff[0] + MAC_HEADER_SIZE_BYTES);
   
   bytes_received = recv(eth->sockfd[Mod_id],
                         buff[0],
@@ -327,12 +327,12 @@ int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp,
  
   *timestamp = test_header->sub_type; 
   
-  if (test_header->sub_type == IF4_PDLFFT) {
-    packet_size = RAW_IF4_PDLFFT_SIZE_BYTES(nblocks);             
-  } else if (test_header->sub_type == IF4_PULFFT) {
-    packet_size = RAW_IF4_PULFFT_SIZE_BYTES(nblocks);             
+  if (test_header->sub_type == IF4p5_PDLFFT) {
+    packet_size = RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks);             
+  } else if (test_header->sub_type == IF4p5_PULFFT) {
+    packet_size = RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks);             
   } else {
-    packet_size = RAW_IF4_PRACH_SIZE_BYTES;
+    packet_size = RAW_IF4p5_PRACH_SIZE_BYTES;
   }
         
   while(bytes_received < packet_size) {
@@ -387,7 +387,7 @@ int eth_set_dev_conf_raw(openair0_device *device) {
 
 
 
-int eth_set_dev_conf_raw_IF4(openair0_device *device) {  
+int eth_set_dev_conf_raw_IF4p5(openair0_device *device) {  
   // use for cc_id info
 
   int 	       Mod_id = device->Mod_id;
@@ -448,7 +448,7 @@ int eth_get_dev_conf_raw(openair0_device *device) {
 }
 
 
-int eth_get_dev_conf_raw_IF4(openair0_device *device) {
+int eth_get_dev_conf_raw_IF4p5(openair0_device *device) {
   // use for cc_id info
 
   eth_state_t   *eth = (eth_state_t*)device->priv;
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
index 252bdbb47cf58dc38de01d507a615b82cd2a7b56..f2c69985bfba70a7fb3991978e8e6289950e7f3d 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.c
@@ -73,27 +73,27 @@ int trx_eth_start(openair0_device *device) {
     /* adjust MTU wrt number of samples per packet */
     if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0)  return -1;
 
-  } else if (eth->flags == ETH_RAW_IF4_MODE) {
+  } else if (eth->flags == ETH_RAW_IF4p5_MODE) {
     if (eth_socket_init_raw(device)!=0)   return -1;
     /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/
     if (device->host_type == BBU_HOST) {
-      if(eth_set_dev_conf_raw_IF4(device)!=0)  return -1;
+      if(eth_set_dev_conf_raw_IF4p5(device)!=0)  return -1;
     } else {
-      if(eth_get_dev_conf_raw_IF4(device)!=0)  return -1;
+      if(eth_get_dev_conf_raw_IF4p5(device)!=0)  return -1;
     }
     /* adjust MTU wrt number of samples per packet */
-    if(ethernet_tune (device,MTU_SIZE,RAW_IF4_PRACH_SIZE_BYTES)!=0)  return -1;
+    if(ethernet_tune (device,MTU_SIZE,RAW_IF4p5_PRACH_SIZE_BYTES)!=0)  return -1;
     
-  } else if (eth->flags == ETH_UDP_IF4_MODE) {
+  } else if (eth->flags == ETH_UDP_IF4p5_MODE) {
     
   
   } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
     if (eth_socket_init_raw(device)!=0)   return -1;
     /* RRH gets openair0 device configuration - BBU sets openair0 device configuration*/
     //if (device->host_type == BBU_HOST) {
-      //if(eth_set_dev_conf_raw_IF4(device)!=0)  return -1;
+      //if(eth_set_dev_conf_raw_IF4p5(device)!=0)  return -1;
     //} else {
-      //if(eth_get_dev_conf_raw_IF4(device)!=0)  return -1;
+      //if(eth_get_dev_conf_raw_IF4p5(device)!=0)  return -1;
 //
     /* adjust MTU wrt number of samples per packet */
    // if(ethernet_tune (device,MTU_SIZE,RAW_PACKET_SIZE_BYTES(device->openair0_cfg->samples_per_packet))!=0)  return -1;
@@ -339,9 +339,9 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth
   } else if (eth_params->transp_preference == 0) {
     eth->flags = ETH_UDP_MODE;
   } else if (eth_params->transp_preference == 3) {
-    eth->flags = ETH_RAW_IF4_MODE;
+    eth->flags = ETH_RAW_IF4p5_MODE;
   } else if (eth_params->transp_preference == 2) {
-    eth->flags = ETH_UDP_IF4_MODE;
+    eth->flags = ETH_UDP_IF4p5_MODE;
   } else if (eth_params->transp_preference == 4) {
     eth->flags = ETH_RAW_IF5_MOBIPASS;
   } else {
@@ -368,15 +368,15 @@ int transport_init(openair0_device *device, openair0_config_t *openair0_cfg, eth
   } else if (eth->flags == ETH_UDP_MODE) {
     device->trx_write_func   = trx_eth_write_udp;
     device->trx_read_func    = trx_eth_read_udp;     
-  } else if (eth->flags == ETH_RAW_IF4_MODE) {
-    device->trx_write_func   = trx_eth_write_raw_IF4;
-    device->trx_read_func    = trx_eth_read_raw_IF4;     
+  } else if (eth->flags == ETH_RAW_IF4p5_MODE) {
+    device->trx_write_func   = trx_eth_write_raw_IF4p5;
+    device->trx_read_func    = trx_eth_read_raw_IF4p5;     
   } else if (eth->flags == ETH_RAW_IF5_MOBIPASS) {
-    device->trx_write_func   = trx_eth_write_raw_IF4;
-    device->trx_read_func    = trx_eth_read_raw_IF4;     
+    device->trx_write_func   = trx_eth_write_raw_IF4p5;
+    device->trx_read_func    = trx_eth_read_raw_IF4p5;     
   } else {
-    //device->trx_write_func   = trx_eth_write_udp_IF4;
-    //device->trx_read_func    = trx_eth_read_udp_IF4;     
+    //device->trx_write_func   = trx_eth_write_udp_IF4p5;
+    //device->trx_read_func    = trx_eth_read_udp_IF4p5;     
   }
     
   eth->if_name[device->Mod_id] = eth_params->local_if_name;
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
index f7753fb51735d885a7f1753637b92ad119993e17..3adb0f45cb22b9e5b46019d58ecfed6cfdb7ff96 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/ethernet_lib.h
@@ -222,11 +222,11 @@ int eth_set_dev_conf_udp(openair0_device *device);
 int eth_socket_init_raw(openair0_device *device);
 int trx_eth_write_raw(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
 int trx_eth_read_raw(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
-int trx_eth_write_raw_IF4(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
-int trx_eth_read_raw_IF4(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
+int trx_eth_write_raw_IF4p5(openair0_device *device, openair0_timestamp timestamp, void **buff, int nsamps,int cc, int flags);
+int trx_eth_read_raw_IF4p5(openair0_device *device, openair0_timestamp *timestamp, void **buff, int nsamps, int cc);
 int eth_get_dev_conf_raw(openair0_device *device);
 int eth_set_dev_conf_raw(openair0_device *device);
-int eth_get_dev_conf_raw_IF4(openair0_device *device);
-int eth_set_dev_conf_raw_IF4(openair0_device *device);
+int eth_get_dev_conf_raw_IF4p5(openair0_device *device);
+int eth_set_dev_conf_raw_IF4p5(openair0_device *device);
 
 #endif
diff --git a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h
index 038129cf36293f801b672bb44d040113ca8c0a52..e118e9f99fee4b3bcc29b94d16f8719e2b6d4922 100644
--- a/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h
+++ b/targets/ARCH/ETHERNET/USERSPACE/LIB/if_defs.h
@@ -47,8 +47,8 @@
 // ETH transport preference modes
 #define ETH_UDP_MODE        0
 #define ETH_RAW_MODE        1
-#define ETH_UDP_IF4_MODE    2
-#define ETH_RAW_IF4_MODE    3
+#define ETH_UDP_IF4p5_MODE    2
+#define ETH_RAW_IF4p5_MODE    3
 #define ETH_RAW_IF5_MOBIPASS    4    
 
 // Time domain RRH packet sizes
@@ -58,13 +58,13 @@
 #define UDP_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
 #define RAW_PACKET_SIZE_BYTES(nsamps) (APP_HEADER_SIZE_BYTES + MAC_HEADER_SIZE_BYTES + PAYLOAD_SIZE_BYTES(nsamps))
 
-// Packet sizes for IF4 interface format
+// Packet sizes for IF4p5 interface format
 #define DATA_BLOCK_SIZE_BYTES(scaled_nblocks) (sizeof(uint16_t)*scaled_nblocks)
 #define PRACH_BLOCK_SIZE_BYTES (sizeof(int16_t)*839*2)  // FIX hard coded prach size (uncompressed)
  
-#define RAW_IF4_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))  
-#define RAW_IF4_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))  
-#define RAW_IF4_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4_header_t + PRACH_BLOCK_SIZE_BYTES)
+#define RAW_IF4p5_PDLFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))  
+#define RAW_IF4p5_PULFFT_SIZE_BYTES(nblocks) (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + DATA_BLOCK_SIZE_BYTES(nblocks))  
+#define RAW_IF4p5_PRACH_SIZE_BYTES (MAC_HEADER_SIZE_BYTES + sizeof_IF4p5_header_t + PRACH_BLOCK_SIZE_BYTES)
 
 // Mobipass packet sizes
 #define RAW_IF5_MOBIPASS_BLOCK_SIZE_BYTES 1280
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index ac552e82fe88caf2d3998918cbc8c5c3d9e26114..150a29e342a85d1f87b0a7957d7b379d51306daa 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -173,6 +173,8 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
   int len,len2;
   int16_t *txdata;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 );
+
   slot_offset_F = (subframe<<1)*slot_sizeF;
 
   slot_offset = subframe*phy_vars_eNB->frame_parms.samples_per_tti;
@@ -284,8 +286,101 @@ void do_OFDM_mod_rt(int subframe,PHY_VARS_eNB *phy_vars_eNB) {
      }
     }
   }
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 );
+}
+
+void tx_fh_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
+  uint8_t seqno;
+  send_IF5(eNB, proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL);
+}
+
+void tx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {    
+  send_IF4p5(eNB,proc->frame_tx, proc->subframe_tx, IF4p5_PDLFFT, 0);
+}
+
+void proc_tx_full(PHY_VARS_eNB *eNB,
+		  eNB_rxtx_proc_t *proc,
+		  uint8_t abstraction_flag,
+		  relaying_type_t r_type,
+		  PHY_VARS_RN *rn) {
+
+  phy_procedures_eNB_TX(eNB,proc,r_type,rn);
+
+  /* we're done, let the next one proceed */
+  if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
+    LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n");
+    exit_fun("nothing to add");
+  }	
+  sync_phy_proc.phy_proc_CC_id++;
+  sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs;
+  pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
+  if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
+    LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n");
+    exit_fun("nothing to add");
+  }
+
+
+  do_OFDM_mod_rt(proc->subframe_tx,eNB);
+
+  if (eNB->tx_fh) eNB->tx_fh(eNB,proc);
+
+
+
+}
+
+void proc_tx_rru_if4p5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
+
+  uint32_t symbol_number=0;
+  uint32_t symbol_mask, symbol_mask_full;
+  uint16_t packet_type;
+
+  /// **** recv_IF4 of txdataF from RCC **** ///             
+  symbol_number = 0;
+  symbol_mask = 0;
+  symbol_mask_full = (1<<eNB->frame_parms.symbols_per_tti)-1;
+  
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 );  
+  do { 
+    recv_IF4p5(eNB, &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number);
+    symbol_mask = symbol_mask | (1<<symbol_number);
+  } while (symbol_mask != symbol_mask_full); 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 );   
+
+
+  do_OFDM_mod_rt(proc->subframe_tx, eNB);
+}
+
+void proc_tx_rru_if5(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc) {
+  /// **** recv_IF5 of txdata from BBU **** ///       
+  recv_IF5(eNB, &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL);
 }
 
+int wait_CCs(eNB_rxtx_proc_t *proc) {
+
+  struct timespec wait;
+
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+  if (pthread_mutex_timedlock(&sync_phy_proc.mutex_phy_proc_tx,&wait) != 0) {
+    LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n");
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  
+  // wait for our turn or oai_exit
+  while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) {
+    pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx,
+		      &sync_phy_proc.mutex_phy_proc_tx);
+  }
+  
+  if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
+    LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX\n");
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
 
 /*!
  * \brief The RX UE-specific and TX thread of eNB.
@@ -297,14 +392,16 @@ static void* eNB_thread_rxtx( void* param ) {
   static int eNB_thread_rxtx_status;
 
   eNB_rxtx_proc_t *proc = (eNB_rxtx_proc_t*)param;
+  PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
+  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
+
   FILE  *tx_time_file = NULL;
   char tx_time_name[101];
-  void *txp[PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx]; 
+  void *txp[fp->nb_antennas_tx]; 
   int txs;
 
-  uint16_t packet_type;
-  uint32_t symbol_number=0;
-  uint32_t symbol_mask, symbol_mask_full;
+
+
   
   uint8_t seqno=0;
   
@@ -435,6 +532,7 @@ static void* eNB_thread_rxtx( void* param ) {
     }
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 1 );
+
     start_meas( &softmodem_stats_rxtx_sf );
   
     if (oai_exit) break;
@@ -443,158 +541,31 @@ static void* eNB_thread_rxtx( void* param ) {
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_ENB+(proc->subframe_rx&1), proc->subframe_rx );
 
     // 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)) {
-
-      // 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 );
-    }
+    phy_procedures_eNB_common_RX(eNB);
+    // Do UE-specific RX processing for subframe n if any
+    if (eNB->proc_uespec_rx) eNB->proc_uespec_rx(eNB, proc, no_relay );
 
     // TX processing for subframe n+4
-    if (((PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.frame_type == TDD) &&
-         ((subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_DL) ||
-          (subframe_select(&PHY_vars_eNB_g[0][proc->CC_id]->frame_parms,proc->subframe_tx) == SF_S))) ||
-        (PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.frame_type == FDD)) {
+    if (((fp->frame_type == TDD) &&
+         ((subframe_select(fp,proc->subframe_tx) == SF_DL) ||
+          (subframe_select(fp,proc->subframe_tx) == SF_S))) ||
+        (fp->frame_type == FDD)) {
       /* run PHY TX procedures the one after the other for all CCs to avoid race conditions
        * (may be relaxed in the future for performance reasons)
        */
-      
-      if (pthread_mutex_timedlock(&sync_phy_proc.mutex_phy_proc_tx,&wait) != 0) {
-        LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX\n");
-        exit_fun("nothing to add");
-        break;
-      }
-      
-      // wait for our turn or oai_exit
-      while (sync_phy_proc.phy_proc_CC_id != proc->CC_id && !oai_exit) {
-        pthread_cond_wait(&sync_phy_proc.cond_phy_proc_tx,
-                          &sync_phy_proc.mutex_phy_proc_tx);
-      }
 
-      if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
-        LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX\n");
-        exit_fun("nothing to add");
-      }
+      if (wait_CCs(proc)<0) break;
 
       VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->frame_tx );
       VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_ENB+(proc->subframe_tx&1), proc->subframe_tx );
       
       if (oai_exit) break;
-      
-      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)) { 
-        phy_procedures_eNB_TX(PHY_vars_eNB_g[0][proc->CC_id], proc, 0, no_relay, NULL );
-
-        /* we're done, let the next one proceed */
-        if (pthread_mutex_lock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
-          LOG_E(PHY, "[SCHED][eNB] error locking PHY proc mutex for eNB TX proc\n");
-          exit_fun("nothing to add");
-          break;
-        }	
-        sync_phy_proc.phy_proc_CC_id++;
-        sync_phy_proc.phy_proc_CC_id %= MAX_NUM_CCs;
-        pthread_cond_broadcast(&sync_phy_proc.cond_phy_proc_tx);
-        if (pthread_mutex_unlock(&sync_phy_proc.mutex_phy_proc_tx) != 0) {
-          LOG_E(PHY, "[SCHED][eNB] error unlocking PHY proc mutex for eNB TX proc\n");
-          exit_fun("nothing to add");
-          break;
-        }
-      } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) {
-        /// **** recv_IF4 of txdataF from RCC **** ///             
-        symbol_number = 0;
-        symbol_mask = 0;
-        symbol_mask_full = (1<<PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.symbols_per_tti)-1;
-        
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 1 );  
-        do { 
-          recv_IF4(PHY_vars_eNB_g[0][proc->CC_id], &proc->frame_tx, &proc->subframe_tx, &packet_type, &symbol_number);
-          symbol_mask = symbol_mask | (1<<symbol_number);
-          
-        } while (symbol_mask != symbol_mask_full); 
-        
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF4, 0 );   
-        
-      } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5) {
-        /// **** recv_IF5 of txdata from BBU **** ///       
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 1 );  
-        recv_IF5(PHY_vars_eNB_g[0][proc->CC_id], &proc->timestamp_tx, proc->subframe_tx, IF5_RRH_GW_DL);
-        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_RECV_IF5, 0 );  
-
-      }
-    }
 
-    // eNodeB_3GPP, _BBU and RRU create txdata
-    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_RRU_IF4)) {
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 1 );
-      do_OFDM_mod_rt( proc->subframe_tx, PHY_vars_eNB_g[0][proc->CC_id] );
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_SFGEN , 0 );
-    }
-
-      /*
-        short *txdata = (short*)&PHY_vars_eNB_g[0][proc->CC_id]->common_vars.txdata[0][0][proc->subframe_tx*PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti];
-        int i;
-        for (i=0;i<PHY_vars_eNB_g[0][proc->CC_id]->frame_parms.samples_per_tti*2;i+=8) {
-        txdata[i] = 2047;
-        txdata[i+1] = 0;
-        txdata[i+2] = 0;
-        txdata[i+3] = 2047;
-        txdata[i+4] = -2047;
-        txdata[i+5] = 0;
-        txdata[i+6] = 0;
-        txdata[i+7] = -2047;      }
-      */      
-          
-
-    /*
-    // eNodeB_3GPP, RRU write to RF device    
-    if ((PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP) ||
-        (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF4) ||
-        (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RRU_IF5)) {
-      // Transmit TX buffer based on timestamp from RX  
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
-      // prepare tx buffer pointers
-      int i;
-      for (i=0; i<PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx; i++)
-        txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][proc->subframe_tx*PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti];
-    
-      txs = PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice,
-								    (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance),
-								    txp,
-								    PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti,
-								    PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx,
-								    1);
-	      
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
- 
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_tx-openair0_cfg[0].tx_sample_advance)&0xffffffff );
-
-      if (txs !=  PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti) {
-	LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti);
-	exit_fun( "problem transmitting samples" );
-      }	
-    }
-    */ 
-    if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == eNodeB_3GPP_BBU) {
-      /// **** send_IF5 of txdata to RRH **** ///       
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 1 );  
-      send_IF5(PHY_vars_eNB_g[0][proc->CC_id], proc->timestamp_tx, proc->subframe_tx, &seqno, IF5_RRH_GW_DL);
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF5, 0 );  
-
-    } else if (PHY_vars_eNB_g[0][proc->CC_id]->node_function == NGFI_RCC_IF4) { 
-      /// **** send_IF4 of txdataF to RRU **** ///       
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 1 );   
-      send_IF4(PHY_vars_eNB_g[0][proc->CC_id], proc->frame_tx, proc->subframe_tx, IF4_PDLFFT, 0);
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_SEND_IF4, 0 );
+      if (eNB->proc_tx)	eNB->proc_tx(eNB, proc, no_relay, NULL );
       
     }
 
+
     if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
       LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB TX proc\n");
       exit_fun("nothing to add");
@@ -611,13 +582,14 @@ static void* eNB_thread_rxtx( void* param ) {
 
     stop_meas( &softmodem_stats_rxtx_sf );
 
-#ifdef DEADLINE_SCHEDULER
     if (opp_enabled){
+      
+#ifdef DEADLINE_SCHEDULER
       if(softmodem_stats_rxtx_sf.diff_now/(cpuf) > attr.sched_runtime){
 	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RUNTIME_TX_ENB, (softmodem_stats_rxtx_sf.diff_now/cpuf - attr.sched_runtime)/1000000.0);
-    }
+      }
 #endif 
-
+    }    
     print_meas_now(&softmodem_stats_rxtx_sf,"eNB_TX_SF",tx_time_file);
   }
 
@@ -807,10 +779,10 @@ static void* eNB_thread_asynch_rx( void* param ) {
     }
   } // 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
+  else if (eNB->node_function == NGFI_RCC_IF4p5) {
+      /// **** recv_IF4p5 of rxdataF from RRU **** ///
+      /// **** recv_IF4p5 of rxsigF from RRU **** ///
+      // get frame/subframe information from IF4p5 interface
       // timed loop (200 us)
       
       symbol_number = 0;
@@ -819,14 +791,12 @@ static void* eNB_thread_asynch_rx( void* param ) {
       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 );   
+        recv_IF4p5(eNB, &frame_rx, &subframe_rx, &packet_type, &symbol_number);
 
-        if (packet_type == IF4_PULFFT) {
+        if (packet_type == IF4p5_PULFFT) {
           symbol_mask = symbol_mask | (1<<symbol_number);
           prach_rx = (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0) ? 1 : 0;                            
-        } else if (packet_type == IF4_PRACH) {
+        } else if (packet_type == IF4p5_PRACH) {
           prach_rx = 0;
         }
       } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1));    
@@ -845,6 +815,248 @@ static void* eNB_thread_asynch_rx( void* param ) {
 
 }
 
+void rx_rf(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame,int *subframe) {
+
+  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+  void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; 
+  unsigned int rxs,txs;
+  int i;
+
+  if (proc->first_rx==0) {
+    
+    // Transmit TX buffer based on timestamp from RX  
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff );
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
+    // prepare tx buffer pointers
+	
+    for (i=0; i<fp->nb_antennas_tx; i++)
+      txp[i] = (void*)&eNB->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti];
+    
+    txs = eNB->rfdevice.trx_write_func(&eNB->rfdevice,
+				       proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance,
+				       txp,
+				       fp->samples_per_tti,
+				       fp->nb_antennas_tx,
+				       1);
+    
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
+    
+    
+    
+    if (txs !=  fp->samples_per_tti) {
+      LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, fp->samples_per_tti);
+      exit_fun( "problem transmitting samples" );
+    }	
+  }
+  
+  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;
+    *frame = proc->frame_rx;
+    *subframe = proc->subframe_rx;        
+  }
+  
+  //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 );
+  
+      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 );
+      
+}
+
+void rx_fh_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *frame, int *subframe) {
+
+  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+
+  recv_IF5(eNB, &proc->timestamp_rx, *subframe, IF5_RRH_GW_UL); 
+
+  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;
+    frame = proc->frame_rx;
+    subframe = proc->subframe_rx;        
+  }      
+  
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+
+}
+
+void rx_fh_if4p5(PHY_VARS_eNB *eNB,eNB_proc_t *proc,int *subframe,int *frame) {
+
+  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+
+  int prach_rx;
+
+  uint16_t packet_type;
+  uint32_t symbol_number=0;
+  uint32_t symbol_mask, symbol_mask_full;
+
+  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_IF4p5(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 == IF4p5_PULFFT) {
+      symbol_mask = symbol_mask | (1<<symbol_number);
+      prach_rx = (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0) ? 1 : 0;                            
+    } else if (packet_type == IF4p5_PRACH) {
+      prach_rx = 0;
+    }
+  } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1));    
+  
+  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;
+    *frame = proc->frame_rx;
+    *subframe = proc->subframe_rx;        
+  }
+  
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
+  
+}
+
+int wakeup_rxtx(eNB_proc_t *proc,eNB_rxtx_proc_t *proc_rxtx,LTE_DL_FRAME_PARMS *fp) {
+
+  int i;
+  struct timespec wait;
+  
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+  /* accept some delay in processing - up to 5ms */
+  for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) {
+    LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->instance_cnt_rxtx);
+    usleep(500);
+  }
+  if (proc_rxtx->instance_cnt_rxtx == 0) {
+    exit_fun( "TX thread busy" );
+    return(-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 RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx );
+    exit_fun( "error locking mutex_rxtx" );
+    return(-1);
+  }
+  
+  ++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).
+  // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, 
+  // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti,
+  // and proc->subframe_tx = proc->subframe_rx+3
+  proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
+  proc_rxtx->frame_rx     = proc->frame_rx;
+  proc_rxtx->subframe_rx  = proc->subframe_rx;
+  proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
+  proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + 4)%10;
+  
+  // the thread can now be woken up
+  if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
+    exit_fun( "ERROR pthread_cond_signal" );
+    return(-1);
+  }
+  
+  pthread_mutex_unlock( &proc_rxtx->mutex_rxtx );
+
+  return(0);
+}
+
+void wakeup_slaves(eNB_proc_t *proc) {
+
+  int i;
+  struct timespec wait;
+  
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+  
+  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_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave);
+      exit_fun( "FH thread busy" );
+      break;
+    }             
+  }
+}
+
 /*!
  * \brief The Fronthaul thread of RRU/RAU/RCC/eNB
  * In the case of RRU/eNB, handles interface with external RF
@@ -859,19 +1071,15 @@ static void* eNB_thread_FH( 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;
-  void *rxp[fp->nb_antennas_rx],*txp[fp->nb_antennas_tx]; 
-  unsigned int rxs,txs;
+
   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 i;
 
   int subframe=0, frame=0; 
+
+  struct timespec wait;
   
   wait.tv_sec=0;
   wait.tv_nsec=5000000L;
@@ -994,32 +1202,16 @@ static void* eNB_thread_FH( void* param ) {
   wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
 #endif 
 
-  // Create buffer for IF device and free when stopping
-  if (eNB->node_function == NGFI_RCC_IF4 || eNB->node_function == NGFI_RRU_IF4) {
-    malloc_IF4_buffer(eNB);
-    
-  } else if (eNB->node_function == NGFI_RRU_IF5 || eNB->node_function == eNodeB_3GPP_BBU) {
-    //malloc_IF5_buffer(eNB);
-
-  } else {
-    eNB->ifbuffer.tx = NULL;
-    eNB->ifbuffer.rx = NULL;
-  }
+  // 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");
 
-  // Start IF device for this CC
-  if (eNB->node_function != eNodeB_3GPP) {
-    if (eNB->ifdevice.trx_start_func(&eNB->ifdevice) != 0 ) 
+  // 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 for this CC
-  if ((eNB->node_function == eNodeB_3GPP) || 
-      (eNB->node_function == NGFI_RRU_IF4) || 
-      (eNB->node_function == NGFI_RRU_IF5)) {
-    if (eNB->rfdevice.trx_start_func(&eNB->rfdevice) != 0 ) 
-      LOG_E(HW,"Could not start the RF device\n");
-  }
-      
+
   // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
   while (!oai_exit) {
    
@@ -1035,7 +1227,7 @@ static void* eNB_thread_FH( void* param ) {
 
     // This case is for synchronization to another thread
     if ((eNB->node_timing == synch_to_other) &&
-       ((eNB->node_function == NGFI_RCC_IF4) ||
+       ((eNB->node_function == NGFI_RCC_IF4p5) ||
         (eNB->node_function == eNodeB_3GPP_BBU))) {   
       //wait for event
 
@@ -1056,232 +1248,24 @@ static void* eNB_thread_FH( void* param ) {
 
     }
     // 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
-
-      if (proc->first_rx==0) {
-
-	// Transmit TX buffer based on timestamp from RX  
-	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance)&0xffffffff );
-	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
-	// prepare tx buffer pointers
-	
-	for (i=0; i<PHY_vars_eNB_g[0][0]->frame_parms.nb_antennas_tx; i++)
-	  txp[i] = (void*)&PHY_vars_eNB_g[0][0]->common_vars.txdata[0][i][((proc->subframe_rx+3)%10)*fp->samples_per_tti];
-	
-	txs = PHY_vars_eNB_g[0][proc->CC_id]->rfdevice.trx_write_func(&PHY_vars_eNB_g[0][proc->CC_id]->rfdevice,
-								      proc->timestamp_rx+(3*fp->samples_per_tti)-openair0_cfg[0].tx_sample_advance,
-								      txp,
-								      fp->samples_per_tti,
-								      fp->nb_antennas_tx,
-								      1);
-	
-	VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
-      
-
-	
-	if (txs !=  PHY_vars_eNB_g[0][0]->frame_parms.samples_per_tti) {
-	  LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, fp->samples_per_tti);
-	  exit_fun( "problem transmitting samples" );
-	}	
-      }
-
-      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;
-        frame = proc->frame_rx;
-        subframe = proc->subframe_rx;        
-      }
-      
-      //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 );
-      
-      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, subframe, 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;
-        frame = proc->frame_rx;
-        subframe = proc->subframe_rx;        
-      }      
-      
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
-      
-    } // 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 **** ///
-      // 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);
-          prach_rx = (is_prach_subframe(fp, proc->frame_rx, proc->subframe_rx)>0) ? 1 : 0;                            
-        } else if (packet_type == IF4_PRACH) {
-          prach_rx = 0;
-        }
-      } while( (symbol_mask != symbol_mask_full) || (prach_rx == 1));    
-
-      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;
-        frame = proc->frame_rx;
-        subframe = proc->subframe_rx;        
-      }
+    else if ((eNB->node_timing == synch_to_ext_device) && 
+	     (eNB->rx_fh))
+      eNB->rx_fh(eNB,proc,&frame,&subframe);
 
-      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS, proc->timestamp_rx&0xffffffff );
-		  
-    } // 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);
+      AssertFatal(1==0, "Unknown fronthaul interface : eNB->node_function %d",eNB->node_function);
     }
 
     T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
 
     // 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_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave);
-	exit_fun( "FH thread busy" );
-	break;
-      }             
-    }
+    wakeup_slaves(proc);
       
     // 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];
-
-    /* accept some delay in processing - up to 5ms */
-    for (i = 0; i < 10 && proc_rxtx->instance_cnt_rxtx == 0; i++) {
-      LOG_W( PHY,"[eNB] Frame %d, eNB RXn-TXnp4 thread busy!! (cnt_rxtx %i)\n", proc_rxtx->frame_tx, proc_rxtx->instance_cnt_rxtx);
-      usleep(500);
-    }
-    if (proc_rxtx->instance_cnt_rxtx == 0) {
-      exit_fun( "TX thread busy" );
+    if (wakeup_rxtx(proc,&proc->proc_rxtx[proc->subframe_rx&1],fp) < 0)
       break;
-    }
-
-    // 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 RXTX thread %d (IC %d)\n", proc_rxtx->subframe_rx&1,proc_rxtx->instance_cnt_rxtx );
-      exit_fun( "error locking mutex_rxtx" );
-      break;
-    }
-
-    ++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).
-    // The last (TS_rx mod samples_per_frame) was n*samples_per_tti, 
-    // we want to generate subframe (n+3), so TS_tx = TX_rx+3*samples_per_tti,
-    // and proc->subframe_tx = proc->subframe_rx+3
-    proc_rxtx->timestamp_tx = proc->timestamp_rx + (4*fp->samples_per_tti);
-    proc_rxtx->frame_rx     = proc->frame_rx;
-    proc_rxtx->subframe_rx  = proc->subframe_rx;
-    proc_rxtx->frame_tx     = (proc_rxtx->subframe_rx > 5) ? (proc_rxtx->frame_rx+1)&1023 : proc_rxtx->frame_rx;
-    proc_rxtx->subframe_tx  = (proc_rxtx->subframe_rx + 4)%10;
-   
-    // the thread can now be woken up
-    if (pthread_cond_signal(&proc_rxtx->cond_rxtx) != 0) {
-      LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB RXn-TXnp4 thread\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-      break;
-    }
-
-    pthread_mutex_unlock( &proc_rxtx->mutex_rxtx );
 
     stop_meas( &softmodem_stats_rxtx_sf );
 #ifdef DEADLINE_SCHEDULER
@@ -1453,9 +1437,8 @@ static void* eNB_thread_prach( void* param ) {
       break;
     }
    
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,1);
-    prach_procedures(eNB,0);
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PRACH_RX,0);
+
+    prach_procedures(eNB);
     
     if (pthread_mutex_lock(&proc->mutex_prach) != 0) {
       LOG_E( PHY, "[SCHED][eNB] error locking mutex for eNB PRACH proc %d\n");
@@ -1732,17 +1715,95 @@ void print_opp_meas(void) {
   }
 }
  
+int start_if(PHY_VARS_eNB *eNB) {
+  return(eNB->ifdevice.trx_start_func(&eNB->ifdevice));
+}
+
+int start_rf(PHY_VARS_eNB *eNB) {
+  return(eNB->rfdevice.trx_start_func(&eNB->rfdevice));
+}
 
- void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst) {
+extern eNB_fep_rru_if5(PHY_VARS_eNB *eNB,eNB_proc_t *proc);
+extern eNB_fep_full(PHY_VARS_eNB *eNB,eNB_proc_t *proc);
+extern do_prach(PHY_VARS_eNB *eNB,eNB_proc_t *proc);
 
+void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst) {
+  
   int CC_id;
   int inst;
-  
+  PHY_VARS_eNB *eNB;
   for (inst=0;inst<nb_inst;inst++) {
     for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
-      PHY_vars_eNB_g[inst][CC_id]->node_function = node_function[CC_id];
-      PHY_vars_eNB_g[inst][CC_id]->node_timing   = node_timing[CC_id];
+      eNB = PHY_vars_eNB_g[inst][CC_id]; 
+      eNB->node_function      = node_function[CC_id];
+      eNB->node_timing        = node_timing[CC_id];
+      eNB->abstraction_flag   = 0;
       LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]);
+      switch (node_function[CC_id]) {
+      case NGFI_RRU_IF5:
+	eNB->do_prach       = NULL;
+	eNB->fep            = eNB_fep_rru_if5;
+	eNB->proc_uespec_rx = NULL;
+	eNB->proc_tx        = NULL;
+	eNB->tx_fh          = NULL;
+	eNB->rx_fh          = rx_rf;
+	eNB->start_rf        = start_rf;
+	eNB->start_if        = start_if;
+	break;
+      case NGFI_RRU_IF4p5:
+	eNB->do_prach       = do_prach;
+	eNB->fep            = eNB_fep_full;
+	eNB->proc_uespec_rx = NULL;
+	eNB->proc_tx        = proc_tx_rru_if4p5;
+	eNB->tx_fh          = NULL;
+	eNB->rx_fh          = rx_rf;
+	eNB->start_rf       = start_rf;
+	eNB->start_if       = start_if;
+	malloc_IF4p5_buffer(eNB);
+	break;
+      case eNodeB_3GPP:
+	eNB->do_prach       = do_prach;
+	eNB->fep            = eNB_fep_full;
+	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;
+	break;
+      case eNodeB_3GPP_BBU:
+	eNB->do_prach       = do_prach;
+	eNB->fep            = eNB_fep_full;
+	eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
+	eNB->proc_tx        = proc_tx_full;
+	eNB->tx_fh          = tx_fh_if5;
+	eNB->rx_fh          = rx_fh_if5;
+	eNB->start_rf       = NULL;
+	eNB->start_if       = start_if;
+	break;
+      case NGFI_RCC_IF4p5:
+	eNB->do_prach       = do_prach;
+	eNB->fep            = eNB_fep_full;
+	eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
+	eNB->proc_tx        = proc_tx_full;
+	eNB->tx_fh          = tx_fh_if4p5;
+	eNB->rx_fh          = rx_fh_if4p5;
+	eNB->start_rf       = NULL;
+	eNB->start_if       = start_if;
+	malloc_IF4p5_buffer(eNB);
+	break;
+      case NGFI_RAU_IF4p5:
+	eNB->do_prach       = do_prach;
+	eNB->fep            = eNB_fep_full;
+	eNB->proc_uespec_rx = phy_procedures_eNB_uespec_RX;
+	eNB->proc_tx        = proc_tx_full;
+	eNB->tx_fh          = tx_fh_if4p5; 
+	eNB->rx_fh          = rx_fh_if4p5; 
+	eNB->start_rf       = NULL;
+	eNB->start_if       = start_if;
+	malloc_IF4p5_buffer(eNB);
+	break;	
+      }
     }
 
     init_eNB_proc(inst);
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 9c3ec6fb999645c00de3eeab53863ebe2b5ead92..38c95a4122b5b5c7f590ddd605a2e03d1fc31b45 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -1056,9 +1056,9 @@ static void get_options (int argc, char **argv)
           if (enb_properties->properties[i]->rrh_gw_config[j].raw == 1) {
             (eth_params+j)->transp_preference       = ETH_RAW_MODE; 
           } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif4 == 1) {
-            (eth_params+j)->transp_preference       = ETH_RAW_IF4_MODE;             
+            (eth_params+j)->transp_preference       = ETH_RAW_IF4p5_MODE;             
           } else if (enb_properties->properties[i]->rrh_gw_config[j].udpif4 == 1) {
-            (eth_params+j)->transp_preference       = ETH_UDP_IF4_MODE;             
+            (eth_params+j)->transp_preference       = ETH_UDP_IF4p5_MODE;             
           } else if (enb_properties->properties[i]->rrh_gw_config[j].rawif5_mobipass == 1) {
             (eth_params+j)->transp_preference       = ETH_RAW_IF5_MOBIPASS;             
           } else {
@@ -1645,7 +1645,7 @@ int main( int argc, char **argv )
 
   if (UE_flag == 0) {
     for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
-      if (node_function[CC_id] == NGFI_RRU_IF4 || node_function[CC_id] == NGFI_RRU_IF5) {
+      if (node_function[CC_id] == NGFI_RRU_IF4p5 || node_function[CC_id] == NGFI_RRU_IF5) {
         PHY_vars_eNB_g[0][CC_id]->rfdevice.host_type = RRH_HOST;
         PHY_vars_eNB_g[0][CC_id]->ifdevice.host_type = RRH_HOST;
       } else {
@@ -1667,7 +1667,7 @@ int main( int argc, char **argv )
     
   // Load RF device and initialize
   for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {  
-    if (node_function[CC_id] == NGFI_RRU_IF5 || node_function[CC_id] == NGFI_RRU_IF4 || node_function[CC_id] == eNodeB_3GPP) { 
+    if (node_function[CC_id] == NGFI_RRU_IF5 || node_function[CC_id] == NGFI_RRU_IF4p5 || node_function[CC_id] == eNodeB_3GPP) { 
       if (mode!=loop_through_memory) {
         returns= (UE_flag == 0) ? 
 	  openair0_device_load(&(PHY_vars_eNB_g[0][CC_id]->rfdevice), &openair0_cfg[0]) :