diff --git a/openair1/PHY/LTE_TRANSPORT/dci_tools.c b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
index d673e12d387cf796c092f7031ae846e49e47a200..dbe06ea6bad17967707ae7681b0968da6f5391c0 100644
--- a/openair1/PHY/LTE_TRANSPORT/dci_tools.c
+++ b/openair1/PHY/LTE_TRANSPORT/dci_tools.c
@@ -44,7 +44,7 @@
 #include "PHY/vars.h"
 #endif
 #include "assertions.h"
-
+ 
 //#define DEBUG_DCI
 
 uint32_t localRIV2alloc_LUT6[32];
@@ -1216,7 +1216,7 @@ int generate_eNB_dlsch_params_from_dci(int frame,
 
     dlsch0_harq = dlsch[0]->harq_processes[harq_pid];
 
-    // msg("DCI: Setting subframe_tx for subframe %d\n",subframe);
+    // printf("DCI: Setting subframe_tx for subframe %d\n",subframe);
     dlsch[0]->subframe_tx[subframe] = 1;
 
     conv_rballoc(rah,
@@ -4467,7 +4467,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
       dlsch0_harq->Qm          = (mcs-28)<<1;
     else
       LOG_E(PHY,"invalid mcs %d\n",mcs);
-    //    msg("test: MCS %d, NPRB %d, TBS %d\n",mcs,NPRB,dlsch0_harq->TBS);
+    //    printf("test: MCS %d, NPRB %d, TBS %d\n",mcs,NPRB,dlsch0_harq->TBS);
     dlsch[0]->current_harq_pid = harq_pid;
 
     dlsch[0]->active = 1;
@@ -4735,7 +4735,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
     dlsch[0]->g_pucch += delta_PUCCH_lut[TPC&3];
     /*
       if (dlsch0_harq->mcs>20) {
-      msg("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs);
+      printf("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs);
       return(-1);
       }
     */
@@ -5411,7 +5411,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
 
     /*
       if (dlsch0_harq->mcs>20) {
-      msg("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs);
+      printf("dci_tools.c: mcs > 20 disabled for now (asked %d)\n",dlsch0_harq->mcs);
       return(-1);
       }
     */
@@ -5437,7 +5437,7 @@ int generate_ue_dlsch_params_from_dci(int frame,
 
     // Fix this
     tpmi = ((DCI1E_5MHz_2A_M10PRB_TDD_t *)dci_pdu)->tpmi;
-    //    msg("ue: tpmi %d\n",tpmi);
+    //    printf("ue: tpmi %d\n",tpmi);
 
     switch (tpmi) {
     case 0 :
@@ -5556,9 +5556,9 @@ uint8_t subframe2harq_pid(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t
   /*
     #ifdef DEBUG_DCI
     if (frame_parms->frame_type == TDD)
-    msg("dci_tools.c: subframe2_harq_pid, subframe %d for TDD configuration %d\n",subframe,frame_parms->tdd_config);
+    printf("dci_tools.c: subframe2_harq_pid, subframe %d for TDD configuration %d\n",subframe,frame_parms->tdd_config);
     else
-    msg("dci_tools.c: subframe2_harq_pid, subframe %d for FDD \n",subframe);
+    printf("dci_tools.c: subframe2_harq_pid, subframe %d for FDD \n",subframe);
     #endif
   */
   if (frame_parms->frame_type == FDD) {
@@ -5734,7 +5734,7 @@ uint16_t quantize_subband_pmi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,int nb_subba
       pmivect |= (pmiq<<(2*i));
     } else {
       // This needs to be done properly!!!
-      msg("PMI feedback for rank>1 not supported!\n");
+      printf("PMI feedback for rank>1 not supported!\n");
       pmivect = 0;
     }
   }
@@ -5928,7 +5928,7 @@ uint32_t fill_subband_cqi(PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t trans_mo
 void fill_CQI(LTE_UE_ULSCH_t *ulsch,PHY_MEASUREMENTS *meas,uint8_t eNB_id,uint8_t harq_pid,int N_RB_DL,uint16_t rnti, uint8_t trans_mode, double sinr_eff)
 {
 
-  //  msg("[PHY][UE] Filling CQI for eNB %d, meas->wideband_cqi_tot[%d] %d\n",
+  //  printf("[PHY][UE] Filling CQI for eNB %d, meas->wideband_cqi_tot[%d] %d\n",
   //      eNB_id,eNB_id,meas->wideband_cqi_tot[eNB_id]);
   double sinr_tmp;
   uint8_t *o = ulsch->o;
@@ -6288,7 +6288,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
       RIV_max = RIV_max25;
       ulsch->harq_processes[harq_pid]->first_rb                              = RIV2first_rb_LUT25[rballoc];
       ulsch->harq_processes[harq_pid]->nb_rb                                 = RIV2nb_rb_LUT25[rballoc];
-      //      printf("***********rballoc %d, first_rb %d, nb_rb %d\n",rballoc,ulsch->harq_processes[harq_pid]->first_rb,ulsch->harq_processes[harq_pid]->nb_rb);
+      //      printf("***********rballoc %d, first_rb %d, nb_rb %d (dci %p)\n",rballoc,ulsch->harq_processes[harq_pid]->first_rb,ulsch->harq_processes[harq_pid]->nb_rb,dci_pdu);
       break;
 
     case 50:
@@ -6409,7 +6409,7 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
       ulsch->rnti = rnti;
     }
 
-    //    msg("[PHY][UE] DCI format 0: harq_pid %d nb_rb %d, rballoc %d\n",harq_pid,ulsch->harq_processes[harq_pid]->nb_rb,
+    //    printf("[PHY][UE] DCI format 0: harq_pid %d nb_rb %d, rballoc %d\n",harq_pid,ulsch->harq_processes[harq_pid]->nb_rb,
     //     ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->rballoc);
     //Mapping of cyclic shift field in DCI format0 to n_DMRS2 (3GPP 36.211, Table 5.5.2.1.1-1)
     if(cshift == 0)
@@ -7007,21 +7007,21 @@ int generate_ue_ulsch_params_from_dci(void *dci_pdu,
     // ulsch->n_DMRS2 = ((DCI0_5MHz_TDD_1_6_t *)dci_pdu)->cshift;
 
 #ifdef DEBUG_DCI
-    msg("Format 0 DCI : ulsch (ue): NBRB        %d\n",ulsch->harq_processes[harq_pid]->nb_rb);
-    msg("Format 0 DCI :ulsch (ue): first_rb    %d\n",ulsch->harq_processes[harq_pid]->first_rb);
-    msg("Format 0 DCI :ulsch (ue): harq_pid    %d\n",harq_pid);
-    msg("Format 0 DCI :ulsch (ue): round       %d\n",ulsch->harq_processes[harq_pid]->round);
-    msg("Format 0 DCI :ulsch (ue): TBS         %d\n",ulsch->harq_processes[harq_pid]->TBS);
-    msg("Format 0 DCI :ulsch (ue): mcs         %d\n",ulsch->harq_processes[harq_pid]->mcs);
-    msg("Format 0 DCI :ulsch (ue): O           %d\n",ulsch->O);
+    printf("Format 0 DCI : ulsch (ue): NBRB        %d\n",ulsch->harq_processes[harq_pid]->nb_rb);
+    printf("Format 0 DCI :ulsch (ue): first_rb    %d\n",ulsch->harq_processes[harq_pid]->first_rb);
+    printf("Format 0 DCI :ulsch (ue): harq_pid    %d\n",harq_pid);
+    printf("Format 0 DCI :ulsch (ue): round       %d\n",ulsch->harq_processes[harq_pid]->round);
+    printf("Format 0 DCI :ulsch (ue): TBS         %d\n",ulsch->harq_processes[harq_pid]->TBS);
+    printf("Format 0 DCI :ulsch (ue): mcs         %d\n",ulsch->harq_processes[harq_pid]->mcs);
+    printf("Format 0 DCI :ulsch (ue): O           %d\n",ulsch->O);
 
     if (frame_parms->frame_type == TDD)
-      msg("Format 0 DCI :ulsch (ue): O_ACK/DAI   %d/%d\n",ulsch->harq_processes[harq_pid]->O_ACK,dai);
+      printf("Format 0 DCI :ulsch (ue): O_ACK/DAI   %d/%d\n",ulsch->harq_processes[harq_pid]->O_ACK,dai);
     else
-      msg("Format 0 DCI :ulsch (ue): O_ACK       %d\n",ulsch->harq_processes[harq_pid]->O_ACK);
+      printf("Format 0 DCI :ulsch (ue): O_ACK       %d\n",ulsch->harq_processes[harq_pid]->O_ACK);
 
-    msg("Format 0 DCI :ulsch (ue): Nsymb_pusch   %d\n",ulsch->Nsymb_pusch);
-    msg("Format 0 DCI :ulsch (ue): cshift        %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
+    printf("Format 0 DCI :ulsch (ue): Nsymb_pusch   %d\n",ulsch->Nsymb_pusch);
+    printf("Format 0 DCI :ulsch (ue): cshift        %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
 #else
     UNUSED_VARIABLE(dai);
 #endif
@@ -7066,7 +7066,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
   //  uint32_t type;
 
 #ifdef DEBUG_DCI
-  LOG_D(PHY,"filling eNB ulsch params for rnti %x, dci format %d, dci %x, subframe %d\n",
+  printf("filling eNB ulsch params for rnti %x, dci format %d, dci %x, subframe %d\n",
         rnti,dci_format,*(uint32_t*)dci_pdu,subframe);
 #endif
 
@@ -7200,7 +7200,7 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
     }
 
 #ifdef DEBUG_DCI
-    LOG_D(PHY,"generate_eNB_ulsch_params_from_dci: subframe %d, rnti %x,harq_pid %d,cqi_req %d\n",subframe,rnti,harq_pid,cqi_req);
+    printf("generate_eNB_ulsch_params_from_dci: subframe %d, rnti %x,harq_pid %d,cqi_req %d\n",subframe,rnti,harq_pid,cqi_req);
 #endif
 
     ulsch->harq_processes[harq_pid]->dci_alloc                             = 1;
@@ -7641,15 +7641,15 @@ int generate_eNB_ulsch_params_from_dci(PHY_VARS_eNB *eNB,
     //ulsch->n_DMRS2 = cshift;
 
 #ifdef DEBUG_DCI
-    msg("ulsch (eNB): NBRB          %d\n",ulsch->harq_processes[harq_pid]->nb_rb);
-    msg("ulsch (eNB): first_rb      %d\n",ulsch->harq_processes[harq_pid]->first_rb);
-    msg("ulsch (eNB): harq_pid      %d\n",harq_pid);
-    msg("ulsch (eNB): round         %d\n",ulsch->harq_processes[harq_pid]->round);
-    msg("ulsch (eNB): TBS           %d\n",ulsch->harq_processes[harq_pid]->TBS);
-    msg("ulsch (eNB): mcs           %d\n",ulsch->harq_processes[harq_pid]->mcs);
-    msg("ulsch (eNB): Or1           %d\n",ulsch->harq_processes[harq_pid]->Or1);
-    msg("ulsch (eNB): Nsymb_pusch   %d\n",ulsch->harq_processes[harq_pid]->Nsymb_pusch);
-    msg("ulsch (eNB): cshift        %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
+    printf("ulsch (eNB): NBRB          %d\n",ulsch->harq_processes[harq_pid]->nb_rb);
+    printf("ulsch (eNB): first_rb      %d\n",ulsch->harq_processes[harq_pid]->first_rb);
+    printf("ulsch (eNB): harq_pid      %d\n",harq_pid);
+    printf("ulsch (eNB): round         %d\n",ulsch->harq_processes[harq_pid]->round);
+    printf("ulsch (eNB): TBS           %d\n",ulsch->harq_processes[harq_pid]->TBS);
+    printf("ulsch (eNB): mcs           %d\n",ulsch->harq_processes[harq_pid]->mcs);
+    printf("ulsch (eNB): Or1           %d\n",ulsch->harq_processes[harq_pid]->Or1);
+    printf("ulsch (eNB): Nsymb_pusch   %d\n",ulsch->harq_processes[harq_pid]->Nsymb_pusch);
+    printf("ulsch (eNB): cshift        %d\n",ulsch->harq_processes[harq_pid]->n_DMRS2);
 #else
     UNUSED_VARIABLE(dai);
 #endif
@@ -7782,7 +7782,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
             break;
 
           default:
-            msg("Problem in SINR Calculation for TM5 \n");
+            printf("Problem in SINR Calculation for TM5 \n");
             break;
           }//switch(qq)
         }//a_rx
@@ -7848,7 +7848,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
             break;
 
           default:
-            msg("Problem in SINR Calculation for TM6 \n");
+            printf("Problem in SINR Calculation for TM6 \n");
             break;
           }//switch(qq)
         }//a_rx
@@ -7860,7 +7860,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
     break;
 
   default:
-    msg("Problem in SINR Calculation for CQI \n");
+    printf("Problem in SINR Calculation for CQI \n");
     break;
   }
 
@@ -7929,7 +7929,7 @@ double sinr_eff_cqi_calc(PHY_VARS_UE *ue, uint8_t eNB_id)
                     3) + p_qam64[5]*pow(I_qam64_avg,2) + p_qam64[6]*I_qam64_avg + p_qam64[7]);
   sinr_eff = cmax3(sinr_eff_qpsk,sinr_eff_qam16,sinr_eff_qam64);
 
-  //msg("SINR_Eff = %e\n",sinr_eff);
+  //printf("SINR_Eff = %e\n",sinr_eff);
 
   return(sinr_eff);
 }
@@ -7948,20 +7948,20 @@ main()
 
   rah = 0;
   rballoc = 0x1fff;
-  msg("rballoc 0 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
+  printf("rballoc 0 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
   rah = 1;
 
   rballoc = 0x1678;
-  msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
+  printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
 
   rballoc = 0xfffc;
-  msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
+  printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
   rballoc = 0xfffd;
-  msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
+  printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
   rballoc = 0xffff;
-  msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
+  printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
   rballoc = 0xfffe;
-  msg("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
+  printf("rballoc 1 %x => %x\n",rballoc,conv_rballoc(rah,rballoc));
 }
 
 #endif
diff --git a/openair1/PHY/LTE_TRANSPORT/prach.c b/openair1/PHY/LTE_TRANSPORT/prach.c
index b24535c43ac17db6f7027d1b921b9b9cae16ed4a..cab6544b6234c35f3f110779dcceb38584099c7a 100644
--- a/openair1/PHY/LTE_TRANSPORT/prach.c
+++ b/openair1/PHY/LTE_TRANSPORT/prach.c
@@ -1161,6 +1161,9 @@ void rx_prach(PHY_VARS_eNB *eNB,
     break;
   }
 
+  if (eNB->frame_parms.threequarter_fs == 1)
+    Ncp=(Ncp*3)>>2;
+
   switch (eNB->frame_parms.N_RB_UL) {
   case 6:
     Ncp>>=4;
@@ -1258,13 +1261,24 @@ void rx_prach(PHY_VARS_eNB *eNB,
 	break;
 	
       case 100:
-	if (prach_fmt == 4) {
-	  dft4096(prach2,rxsigF[aa],1);
+	if (eNB->frame_parms.threequarter_fs==0) {
+	  if (prach_fmt == 4) {
+	    dft4096(prach2,rxsigF[aa],1);
+	  } else {
+	    dft24576(prach2,rxsigF[aa]);
+	    
+	    if (prach_fmt>1)
+	      dft24576(prach2+49152,rxsigF[aa]+49152);
+	  }
 	} else {
-	  dft24576(prach2,rxsigF[aa]);
-	  
-	  if (prach_fmt>1)
-	    dft24576(prach2+49152,rxsigF[aa]+49152);
+	  if (prach_fmt == 4) {
+	    dft3072(prach2,rxsigF[aa]);
+	  } else {
+	    dft18432(prach2,rxsigF[aa]);
+	    
+	    if (prach_fmt>1)
+	      dft18432(prach2+36864,rxsigF[aa]+36864);
+	  }
 	}
 	
 	break;
diff --git a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c
index 16cd84701665ed83458ff7ff38ac4cadb59a408e..e673513f499c072212ab91a7565ec6e875597be4 100644
--- a/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c
+++ b/openair1/PHY/LTE_TRANSPORT/ulsch_demodulation.c
@@ -739,7 +739,7 @@ void ulsch_extract_rbs_single(int32_t **rxdataF,
 
     nb_rb1 = cmin(cmax((int)(frame_parms->N_RB_UL) - (int)(2*first_rb),(int)0),(int)(2*nb_rb));    // 2 times no. RBs before the DC
     nb_rb2 = 2*nb_rb - nb_rb1;                                   // 2 times no. RBs after the DC
-
+ 
 #ifdef DEBUG_ULSCH
     printf("ulsch_extract_rbs_single: 2*nb_rb1 = %d, 2*nb_rb2 = %d\n",nb_rb1,nb_rb2);
 #endif
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 8a6c827ff80b5b9c3cda69dc0f977e331d603a39..5fdd88cd2398b788466026551aa19a697a1c5cc1 100755
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -246,6 +246,8 @@ typedef struct eNB_proc_t_s {
   int frame_rx;
   /// frame to act upon for PRACH
   int frame_prach;
+  /// \internal This variable is protected by \ref mutex_fep.
+  int instance_cnt_fep;
   /// \brief Instance count for FH processing thread.
   /// \internal This variable is protected by \ref mutex_FH.
   int instance_cnt_FH;
@@ -264,6 +266,8 @@ typedef struct eNB_proc_t_s {
   int first_rx;
   /// flag to indicate first TX transmission
   int first_tx;
+  /// pthread attributes for parallel fep thread
+  pthread_attr_t attr_fep;
   /// pthread attributes for FH processing thread
   pthread_attr_t attr_FH;
   /// pthread attributes for single eNB processing thread
@@ -272,6 +276,8 @@ typedef struct eNB_proc_t_s {
   pthread_attr_t attr_prach;
   /// pthread attributes for asynchronous RX thread
   pthread_attr_t attr_asynch_rxtx;
+  /// scheduling parameters for parallel fep thread
+  struct sched_param sched_param_fep;
   /// scheduling parameters for FH thread
   struct sched_param sched_param_FH;
   /// scheduling parameters for single eNB thread
@@ -280,14 +286,20 @@ typedef struct eNB_proc_t_s {
   struct sched_param sched_param_prach;
   /// scheduling parameters for asynch_rxtx thread
   struct sched_param sched_param_asynch_rxtx;
+  /// pthread structure for parallel fep thread
+  pthread_t pthread_fep;
   /// pthread structure for PRACH thread
   pthread_t pthread_prach;
+  /// condition variable for parallel fep thread
+  pthread_cond_t cond_fep;
   /// condition variable for FH thread
   pthread_cond_t cond_FH;
   /// condition variable for PRACH processing thread;
   pthread_cond_t cond_prach;
   /// condition variable for asynch RX/TX thread
   pthread_cond_t cond_asynch_rxtx;
+  /// mutex for parallel fep thread
+  pthread_mutex_t mutex_fep;
   /// mutex for FH
   pthread_mutex_t mutex_FH;
   /// mutex for PRACH thread
diff --git a/openair1/SCHED/phy_procedures_lte_eNb.c b/openair1/SCHED/phy_procedures_lte_eNb.c
index 52820350f494c0025137669c1197d6f9cbb2ed57..980fa3335a232783431a7bb81d1ec43f7615240f 100755
--- a/openair1/SCHED/phy_procedures_lte_eNb.c
+++ b/openair1/SCHED/phy_procedures_lte_eNb.c
@@ -2346,10 +2346,11 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p
   int ret=0;
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
 
+  if (eNB->ulsch[UE_id]==NULL) return;
+
   num_active_cba_groups = eNB->ulsch[UE_id]->num_active_cba_groups;
-  
-  if ((eNB->ulsch[UE_id]) &&
-      (num_active_cba_groups > 0) &&
+ 
+  if ((num_active_cba_groups > 0) &&
       (eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]>0) &&
       (eNB->ulsch[UE_id]->harq_processes[harq_pid]->subframe_cba_scheduling_flag==1)) {
     rnti=0;
@@ -2462,7 +2463,8 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p
 	      UE_id % eNB->ulsch[UE_id]->num_active_cba_groups, eNB->ulsch[UE_id]->cba_rnti[UE_id%num_active_cba_groups]);
 
 	// detect if there is a CBA collision
-	if (eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) {
+	if ((eNB->cba_last_reception[UE_id%num_active_cba_groups] == 0 ) && 
+	    (eNB->mac_enabled==1)) {
 	  mac_xface->rx_sdu(eNB->Mod_id,
 			    eNB->CC_id,
 			    frame,subframe,
@@ -2495,6 +2497,155 @@ void cba_procedures(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,int UE_id,int harq_p
 
 }
 
+typedef struct {
+  PHY_VARS_eNB *eNB;
+  int slot;
+} fep_task;
+
+void fep0(PHY_VARS_eNB *eNB,int slot) {
+
+  eNB_proc_t *proc       = &eNB->proc;
+  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+  int l;
+
+  remove_7_5_kHz(eNB,(slot&1)+(proc->subframe_rx<<1));
+  for (l=0; l<fp->symbols_per_tti/2; l++) {
+    slot_fep_ul(fp,
+		&eNB->common_vars,
+		l,
+		(slot&1)+(proc->subframe_rx<<1),
+		0,
+		0
+		);
+  }
+}
+
+static inline int release_thread(pthread_mutex_t *mutex,int *instance_cnt,char *name) {
+
+  if (pthread_mutex_lock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  
+  *instance_cnt=*instance_cnt-1;
+  
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
+
+static inline int wait_on_condition(pthread_mutex_t *mutex,pthread_cond_t *cond,int *instance_cnt,char *name) {
+
+  if (pthread_mutex_lock(mutex) != 0) {
+    LOG_E( PHY, "[SCHED][eNB] error locking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  
+  while (*instance_cnt < 0) {
+    // most of the time the thread is waiting here
+    // proc->instance_cnt_rxtx is -1
+    pthread_cond_wait(cond,mutex); // this unlocks mutex_rxtx while waiting and then locks it again
+  }
+
+  if (pthread_mutex_unlock(mutex) != 0) {
+    LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for %s\n",name);
+    exit_fun("nothing to add");
+    return(-1);
+  }
+  return(0);
+}
+
+extern int oai_exit;
+
+
+static void *fep_thread(void *param) {
+
+  PHY_VARS_eNB *eNB = (PHY_VARS_eNB *)param;
+  eNB_proc_t *proc  = &eNB->proc;
+  while (!oai_exit) {
+    if (wait_on_condition(&proc->mutex_fep,&proc->cond_fep,&proc->instance_cnt_fep,"fep thread")<0) break;  
+    fep0(eNB,0);
+    if (release_thread(&proc->mutex_fep,&proc->instance_cnt_fep,"fep thread")<0) break;
+  }
+  return(NULL);
+}
+
+void init_fep_thread(PHY_VARS_eNB *eNB,pthread_attr_t *attr_fep) {
+
+  eNB_proc_t *proc = &eNB->proc;
+
+  proc->instance_cnt_fep         = -1;
+    
+  pthread_mutex_init( &proc->mutex_fep, NULL);
+  pthread_cond_init( &proc->cond_fep, NULL);
+
+  pthread_create(&proc->pthread_fep, attr_fep, fep_thread, (void*)eNB);
+
+}
+
+void eNB_fep_full_2thread(PHY_VARS_eNB *eNB) {
+
+  eNB_proc_t *proc = &eNB->proc;
+  struct timespec wait;
+  int wait_cnt=0;
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
+  start_meas(&eNB->ofdm_demod_stats);
+
+  if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
+    printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep);
+    exit_fun( "error locking mutex_fep" );
+    return;
+  }
+
+  if (proc->instance_cnt_fep==0) {
+    printf("[eNB] FEP thread busy\n");
+    exit_fun("FEP thread busy");
+    pthread_mutex_unlock( &proc->mutex_fep );
+    return;
+  }
+  
+  ++proc->instance_cnt_fep;
+
+
+  if (pthread_cond_signal(&proc->cond_fep) != 0) {
+    printf("[eNB] ERROR pthread_cond_signal for fep thread\n");
+    exit_fun( "ERROR pthread_cond_signal" );
+    return;
+  }
+  
+  pthread_mutex_unlock( &proc->mutex_fep );
+
+  // call second slot in this symbol
+  fep0(eNB,1);
+
+  if (pthread_mutex_timedlock(&proc->mutex_fep,&wait) != 0) {
+    printf("[eNB] ERROR pthread_mutex_lock for fep thread %d (IC %d)\n", proc->instance_cnt_fep);
+    exit_fun( "error locking mutex_fep" );
+    return;
+  }
+  while (proc->instance_cnt_fep==0) {
+    wait_cnt++;
+    if (wait_cnt>10000)
+      break;
+  };
+
+  pthread_mutex_unlock( &proc->mutex_fep );
+  if (wait_cnt>1000000) {
+    printf("[eNB] parallel FEP didn't finish\n");
+    exit_fun( "error" );
+  }
+
+  stop_meas(&eNB->ofdm_demod_stats);
+}
+
 void eNB_fep_full(PHY_VARS_eNB *eNB) {
 
   eNB_proc_t *proc = &eNB->proc;
@@ -2502,6 +2653,7 @@ void eNB_fep_full(PHY_VARS_eNB *eNB) {
   LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,1);
+  start_meas(&eNB->ofdm_demod_stats);
   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++) {
@@ -2520,6 +2672,7 @@ void eNB_fep_full(PHY_VARS_eNB *eNB) {
 		0
 		);
   }
+  stop_meas(&eNB->ofdm_demod_stats);
   
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_SLOT_FEP,0);
   
@@ -2626,10 +2779,11 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
   const int frame    = proc->frame_rx;
   int offset         = (proc == &eNB->proc.proc_rxtx[0]) ? 0 : 1;
 
+
   if ((fp->frame_type == TDD) && (subframe_select(fp,subframe)!=SF_UL)) return;
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX_UESPEC+offset, 1 );
-  start_meas(&eNB->phy_proc_rx);
+
 #ifdef DEBUG_PHY_PROC
   LOG_D(PHY,"[eNB %d] Frame %d: Doing phy_procedures_eNB_uespec_RX(%d)\n",eNB->Mod_id,frame, subframe);
 #endif
@@ -2920,14 +3074,15 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
             eNB->UE_stats[i].ulsch_consecutive_errors++;
 
 	    // indicate error to MAC
-	    mac_xface->rx_sdu(eNB->Mod_id,
-			      eNB->CC_id,
-			      frame,subframe,
-			      eNB->ulsch[i]->rnti,
-			      NULL,
-			      0,
-			      harq_pid,
-			      &eNB->ulsch[i]->Msg3_flag);
+	    if (eNB->mac_enabled == 1)
+	      mac_xface->rx_sdu(eNB->Mod_id,
+				eNB->CC_id,
+				frame,subframe,
+				eNB->ulsch[i]->rnti,
+				NULL,
+				0,
+				harq_pid,
+				&eNB->ulsch[i]->Msg3_flag);
           }
         }
       }  // ulsch in error
@@ -2987,15 +3142,15 @@ void phy_procedures_eNB_uespec_RX(PHY_VARS_eNB *eNB,eNB_rxtx_proc_t *proc,const
 	    LOG_I(PHY,"[eNB %d][RAPROC] Frame %d Terminating ra_proc for harq %d, UE %d\n",
 		  eNB->Mod_id,
 		  frame,harq_pid,i);
-	    
-	    mac_xface->rx_sdu(eNB->Mod_id,
-			      eNB->CC_id,
-			      frame,subframe,
-			      eNB->ulsch[i]->rnti,
-			      eNB->ulsch[i]->harq_processes[harq_pid]->b,
-			      eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
-			      harq_pid,
-			      &eNB->ulsch[i]->Msg3_flag);
+	    if (eNB->mac_enabled)
+	      mac_xface->rx_sdu(eNB->Mod_id,
+				eNB->CC_id,
+				frame,subframe,
+				eNB->ulsch[i]->rnti,
+				eNB->ulsch[i]->harq_processes[harq_pid]->b,
+				eNB->ulsch[i]->harq_processes[harq_pid]->TBS>>3,
+				harq_pid,
+				&eNB->ulsch[i]->Msg3_flag);
 	    
 	    // one-shot msg3 detection by MAC: empty PDU (e.g. CRNTI)
 	    if (eNB->ulsch[i]->Msg3_flag == 0 ) {
diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c
index 38609c6f437bde67344176236b5ca7d03f39d38b..2612302d54d4b2219a2434d6c88476f5403c716f 100755
--- a/openair1/SCHED/phy_procedures_lte_ue.c
+++ b/openair1/SCHED/phy_procedures_lte_ue.c
@@ -828,7 +828,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
   int i;
   int aa;
   int tx_amp;
-  uint8_t ulsch_input_buffer[2700] __attribute__ ((aligned(16)));
+  uint8_t ulsch_input_buffer[5477] __attribute__ ((aligned(32)));
   uint8_t access_mode;
 
   // get harq_pid from subframe relationship
diff --git a/openair1/SIMULATION/LTE_PHY/dlsim.c b/openair1/SIMULATION/LTE_PHY/dlsim.c
index f7824773e04c51033747f8e1580f5d6878350ada..fb6a9d0288009bc47ccca14186d1786011f8b938 100644
--- a/openair1/SIMULATION/LTE_PHY/dlsim.c
+++ b/openair1/SIMULATION/LTE_PHY/dlsim.c
@@ -13,7 +13,7 @@
     MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
     GNU General Public License for more details.
 
-    You should have received a copy of the GNU General Public License
+    You should haeve received a copy of the GNU General Public License
     along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
diff --git a/openair1/SIMULATION/LTE_PHY/ulsim.c b/openair1/SIMULATION/LTE_PHY/ulsim.c
index 135ad59037c8ed04f352ad21e0aa232052c543cb..48b3f8cec1d69587c3997fd0713c3ab7e317b934 100644
--- a/openair1/SIMULATION/LTE_PHY/ulsim.c
+++ b/openair1/SIMULATION/LTE_PHY/ulsim.c
@@ -85,6 +85,94 @@ double t_rx_min = 1000000000; /*!< \brief initial min process time for tx */
 int n_tx_dropped = 0; /*!< \brief initial max process time for tx */
 int n_rx_dropped = 0; /*!< \brief initial max process time for rx */
 
+
+void fill_ulsch_dci(PHY_VARS_eNB *eNB,void *UL_dci,int first_rb,int nb_rb,int mcs,int ndi,int cqi_flag) {
+
+  switch (eNB->frame_parms.N_RB_UL) {
+  case 6:
+    break;
+
+  case 25:
+    if (eNB->frame_parms.frame_type == TDD) {
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->type    = 0;
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
+      //printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci);
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->mcs     = mcs;
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->ndi     = ndi;
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->TPC     = 0;
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->cqi_req = cqi_flag&1;
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->cshift  = 0;
+      ((DCI0_5MHz_TDD_1_6_t*)UL_dci)->dai     = 1;
+    } else {
+      ((DCI0_5MHz_FDD_t*)UL_dci)->type    = 0;
+      ((DCI0_5MHz_FDD_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
+      //      printf("nb_rb %d/%d, rballoc %d (dci %x) (dcip %p)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci,UL_dci);
+      ((DCI0_5MHz_FDD_t*)UL_dci)->mcs     = mcs;
+      ((DCI0_5MHz_FDD_t*)UL_dci)->ndi     = ndi;
+      ((DCI0_5MHz_FDD_t*)UL_dci)->TPC     = 0;
+      ((DCI0_5MHz_FDD_t*)UL_dci)->cqi_req = cqi_flag&1;
+      ((DCI0_5MHz_FDD_t*)UL_dci)->cshift  = 0;
+    }
+
+    break;
+
+  case 50:
+    if (eNB->frame_parms.frame_type == TDD) {
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->type    = 0;
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
+      //      printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci);
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->mcs     = mcs;
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->ndi     = ndi;
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->TPC     = 0;
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->cqi_req = cqi_flag&1;
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->cshift  = 0;
+      ((DCI0_10MHz_TDD_1_6_t*)UL_dci)->dai     = 1;
+    } else {
+      ((DCI0_10MHz_FDD_t*)UL_dci)->type    = 0;
+      ((DCI0_10MHz_FDD_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
+      //printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci);
+      ((DCI0_10MHz_FDD_t*)UL_dci)->mcs     = mcs;
+      ((DCI0_10MHz_FDD_t*)UL_dci)->ndi     = ndi;
+      ((DCI0_10MHz_FDD_t*)UL_dci)->TPC     = 0;
+      ((DCI0_10MHz_FDD_t*)UL_dci)->cqi_req = cqi_flag&1;
+      ((DCI0_10MHz_FDD_t*)UL_dci)->cshift  = 0;
+    }
+
+    break;
+
+  case 100:
+    if (eNB->frame_parms.frame_type == TDD) {
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->type    = 0;
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
+      //      printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_TDD_1_6_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci);
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->mcs     = mcs;
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->ndi     = ndi;
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->TPC     = 0;
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->cqi_req = cqi_flag&1;
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->cshift  = 0;
+      ((DCI0_20MHz_TDD_1_6_t*)UL_dci)->dai     = 1;
+    } else {
+      ((DCI0_20MHz_FDD_t*)UL_dci)->type    = 0;
+      ((DCI0_20MHz_FDD_t*)UL_dci)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
+      //   printf("nb_rb %d/%d, rballoc %d (dci %x) (UL_dci %p)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_FDD_t*)UL_dci)->rballoc,*(uint32_t *)UL_dci,(void*)UL_dci);
+      ((DCI0_20MHz_FDD_t*)UL_dci)->mcs     = mcs;
+      ((DCI0_20MHz_FDD_t*)UL_dci)->ndi     = ndi;
+      ((DCI0_20MHz_FDD_t*)UL_dci)->TPC     = 0;
+      ((DCI0_20MHz_FDD_t*)UL_dci)->cqi_req = cqi_flag&1;
+      ((DCI0_20MHz_FDD_t*)UL_dci)->cshift  = 0;
+    }
+
+    break;
+
+  default:
+    break;
+  }
+
+}
+
+extern void eNB_fep_full(PHY_VARS_eNB *eNB);
+extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB);
+
 int main(int argc, char **argv)
 {
 
@@ -186,10 +274,12 @@ int main(int argc, char **argv)
   char channel_model_input[10];
 
   uint8_t max_turbo_iterations=4;
-  uint8_t llr8_flag=0;
+  uint8_t parallel_flag=0;
   int nb_rb_set = 0;
 
   int threequarter_fs=0;
+  int ndi;
+
   opp_enabled=1; // to enable the time meas
 
   cpu_freq_GHz = (double)get_cpu_freq_GHz();
@@ -442,7 +532,7 @@ int main(int argc, char **argv)
       break;
 
     case 'L':
-      llr8_flag=1;
+      parallel_flag=1;
       break;
 
     case 'I':
@@ -488,16 +578,6 @@ int main(int argc, char **argv)
   snr1 = snr0+snr_int;
   printf("SNR0 %f, SNR1 %f\n",snr0,snr1);
 
-  /*
-    txdataF    = (int **)malloc16(2*sizeof(int*));
-    txdataF[0] = (int *)malloc16(FRAME_LENGTH_BYTES);
-    txdataF[1] = (int *)malloc16(FRAME_LENGTH_BYTES);
-
-    txdata    = (int **)malloc16(2*sizeof(int*));
-    txdata[0] = (int *)malloc16(FRAME_LENGTH_BYTES);
-    txdata[1] = (int *)malloc16(FRAME_LENGTH_BYTES);
-  */
-
   frame_parms = &eNB->frame_parms;
 
   txdata = UE->common_vars.txdata;
@@ -539,32 +619,6 @@ int main(int argc, char **argv)
     }
   }
 
-  /*
-  if(abstx) {
-    sprintf(fperen_name,"ULchan_estims_F_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz);
-    fperen = fopen(fperen_name,"a+");
-    fprintf(fperen,"chest_f = [");
-    fclose(fperen);
-
-    sprintf(fmageren_name,"ChanMag_F_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz);
-    fmageren = fopen(fmageren_name,"a+");
-    fprintf(fmageren,"mag_f = [");
-    fclose(fmageren);
-
-    sprintf(flogeren_name,"Log2Max_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz);
-    flogeren = fopen(flogeren_name,"a+");
-    fprintf(flogeren,"mag_f = [");
-    fclose(flogeren);
-  }
-  */
-
-  /*
-    sprintf(ftxlev_name,"txlevel_mcs%d_rb%d_chanMod%d_nframes%d_chanReal%d.m",mcs,nb_rb,chMod,n_frames,n_ch_rlz);
-    ftxlev = fopen(ftxlev_name,"a+");
-    fprintf(ftxlev,"txlev = [");
-    fclose(ftexlv);
-  */
-
   if(abstx) {
     // CSV file
     sprintf(csv_fname,"EULdataout_tx%d_mcs%d_nbrb%d_chan%d_nsimus%d_eren.m",transmission_mode,mcs,nb_rb,chMod,n_frames);
@@ -581,10 +635,6 @@ int main(int argc, char **argv)
     s_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
     r_re[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
     r_im[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
-    //    r_re0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
-    //    bzero(r_re0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
-    //    r_im0[i] = malloc(FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
-    //    bzero(r_im0[i],FRAME_LENGTH_COMPLEX_SAMPLES*sizeof(double));
   }
 
 
@@ -639,6 +689,8 @@ int main(int argc, char **argv)
   eNB->ulsch[0] = new_eNB_ulsch(max_turbo_iterations,N_RB_DL,0);
   UE->ulsch[0]   = new_ue_ulsch(N_RB_DL,0);
 
+  if (parallel_flag == 1) init_fep_thread(eNB,&eNB->proc.attr_fep);
+
   // Create transport channel structures for 2 transport blocks (MIMO)
   for (i=0; i<2; i++) {
     eNB->dlsch[0][i] = new_eNB_dlsch(1,8,1827072,N_RB_DL,0);
@@ -660,85 +712,6 @@ int main(int argc, char **argv)
   } 
 
 
-  switch (eNB->frame_parms.N_RB_UL) {
-  case 6:
-    break;
-
-  case 25:
-    if (eNB->frame_parms.frame_type == TDD) {
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->type    = 0;
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
-      //      printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu);
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs     = mcs;
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi     = 1;
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC     = 0;
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1;
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->cshift  = 0;
-      ((DCI0_5MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai     = 1;
-    } else {
-      ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->type    = 0;
-      ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
-      //      printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu);
-      ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->mcs     = mcs;
-      ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->ndi     = 1;
-      ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->TPC     = 0;
-      ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1;
-      ((DCI0_5MHz_FDD_t*)&UL_alloc_pdu)->cshift  = 0;
-    }
-
-    break;
-
-  case 50:
-    if (eNB->frame_parms.frame_type == TDD) {
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->type    = 0;
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
-      //      printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu);
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs     = mcs;
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi     = 1;
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC     = 0;
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1;
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->cshift  = 0;
-      ((DCI0_10MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai     = 1;
-    } else {
-      ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->type    = 0;
-      ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
-      //printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu);
-      ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->mcs     = mcs;
-      ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->ndi     = 1;
-      ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->TPC     = 0;
-      ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1;
-      ((DCI0_10MHz_FDD_t*)&UL_alloc_pdu)->cshift  = 0;
-    }
-
-    break;
-
-  case 100:
-    if (eNB->frame_parms.frame_type == TDD) {
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->type    = 0;
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
-      printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu);
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->mcs     = mcs;
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->ndi     = 1;
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->TPC     = 0;
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1;
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->cshift  = 0;
-      ((DCI0_20MHz_TDD_1_6_t*)&UL_alloc_pdu)->dai     = 1;
-    } else {
-      ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->type    = 0;
-      ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc = computeRIV(eNB->frame_parms.N_RB_UL,first_rb,nb_rb);// 12 RBs from position 8
-      printf("nb_rb %d/%d, rballoc %d (dci %x)\n",nb_rb,eNB->frame_parms.N_RB_UL,((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->rballoc,*(uint32_t *)&UL_alloc_pdu);
-      ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->mcs     = mcs;
-      ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->ndi     = 1;
-      ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->TPC     = 0;
-      ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->cqi_req = cqi_flag&1;
-      ((DCI0_20MHz_FDD_t*)&UL_alloc_pdu)->cshift  = 0;
-    }
-
-    break;
-
-  default:
-    break;
-  }
 
 
   UE->measurements.rank[0] = 0;
@@ -753,16 +726,21 @@ int main(int argc, char **argv)
   UE->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
   eNB->frame_parms.pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
 
+
+  UE->mac_enabled=0;
   
-  eNB_rxtx_proc_t *proc_rxtx = &eNB->proc.proc_rxtx[subframe&1];
+  eNB_rxtx_proc_t *proc_rxtx   = &eNB->proc.proc_rxtx[subframe&1];
+  UE_rxtx_proc_t *proc_rxtx_ue = &UE->proc.proc_rxtx[subframe&1];
   proc_rxtx->frame_rx=1;
   proc_rxtx->subframe_rx=subframe;
 
   proc_rxtx->frame_tx=pdcch_alloc2ul_frame(&eNB->frame_parms,1,subframe);
   proc_rxtx->subframe_tx=pdcch_alloc2ul_subframe(&eNB->frame_parms,subframe);
 
-  UE->frame_tx = proc_rxtx->frame_rx;
-  UE->frame_rx = proc_rxtx->frame_tx;
+  proc_rxtx_ue->frame_tx = proc_rxtx->frame_rx;
+  proc_rxtx_ue->frame_rx = proc_rxtx->frame_tx;
+  proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx;
+  proc_rxtx_ue->subframe_rx = proc_rxtx->subframe_tx;
 
   printf("Init UL hopping UE\n");
   init_ul_hopping(&UE->frame_parms);
@@ -774,11 +752,13 @@ int main(int argc, char **argv)
 
   UE->ulsch_Msg3_active[eNB_id] = 0;
   UE->ul_power_control_dedicated[eNB_id].accumulationEnabled=1;
+  /*
   generate_ue_ulsch_params_from_dci((void *)&UL_alloc_pdu,
                                     14,
                                     proc_rxtx->subframe_tx,
                                     format0,
                                     UE,
+				    proc_rxtx_ue,
                                     SI_RNTI,
                                     0,
                                     P_RNTI,
@@ -798,6 +778,7 @@ int main(int argc, char **argv)
                                      P_RNTI,
                                      CBA_RNTI,
                                      srs_flag);
+  */
 
   coded_bits_per_codeword = nb_rb * (12 * get_Qm_ul(mcs)) * nsymb;
 
@@ -845,7 +826,7 @@ int main(int argc, char **argv)
       //randominit(0);
 
 
-      harq_pid = subframe2harq_pid(&UE->frame_parms,UE->frame_tx,subframe);
+      harq_pid = subframe2harq_pid(&UE->frame_parms,proc_rxtx_ue->frame_tx,subframe);
       input_buffer_length = UE->ulsch[0]->harq_processes[harq_pid]->TBS/8;
       input_buffer = (unsigned char *)memalign(32,input_buffer_length+64);
       //      printf("UL frame %d/subframe %d, harq_pid %d\n",UE->frame,subframe,harq_pid);
@@ -927,7 +908,7 @@ int main(int argc, char **argv)
       reset_meas(&eNB->ulsch_tc_intl1_stats);
       reset_meas(&eNB->ulsch_tc_intl2_stats);
 
-      // initialization
+      // initialization 
       struct list time_vector_tx;
       initialize(&time_vector_tx);
       struct list time_vector_tx_ifft;
@@ -946,32 +927,50 @@ int main(int argc, char **argv)
       struct list time_vector_rx_dec;
       initialize(&time_vector_rx_dec);
 
+      ndi=0;
       for (trials = 0; trials<n_frames; trials++) {
         //      printf("*");
         //        UE->frame++;
         //        eNB->frame++;
-
+	ndi = (1-ndi);
         fflush(stdout);
         round=0;
 
         while (round < 4) {
           eNB->ulsch[0]->harq_processes[harq_pid]->round=round;
           UE->ulsch[0]->harq_processes[harq_pid]->round=round;
-          //  printf("Trial %d : Round %d ",trials,round);
+	  //	  printf("Trial %d : Round %d (subframe %d, frame %d)\n",trials,round,proc_rxtx_ue->subframe_rx,proc_rxtx_ue->frame_rx);
           round_trials[round]++;
 
-          if (round == 0) {
-            //eNB->ulsch[0]->harq_processes[harq_pid]->Ndi = 1;
-            eNB->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1;
-            //UE->ulsch[0]->harq_processes[harq_pid]->Ndi = 1;
-            UE->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1;
-          } else {
-            //eNB->ulsch[0]->harq_processes[harq_pid]->Ndi = 0;
-            eNB->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1;
-            //UE->ulsch[0]->harq_processes[harq_pid]->Ndi = 0;
-            UE->ulsch[0]->harq_processes[harq_pid]->rvidx = round>>1;
-          }
 
+	  fill_ulsch_dci(eNB,(void*)&UL_alloc_pdu,first_rb,nb_rb,mcs,ndi,cqi_flag);
+
+	  UE->ulsch_Msg3_active[eNB_id] = 0;
+	  UE->ul_power_control_dedicated[eNB_id].accumulationEnabled=1;
+	  generate_ue_ulsch_params_from_dci((void *)&UL_alloc_pdu,
+					    14,
+					    proc_rxtx->subframe_tx,
+					    format0,
+					    UE,
+					    proc_rxtx_ue,
+					    SI_RNTI,
+					    0,
+					    P_RNTI,
+					    CBA_RNTI,
+					    0,
+					    srs_flag);
+
+	  generate_eNB_ulsch_params_from_dci(eNB,proc_rxtx,
+					     (void *)&UL_alloc_pdu,
+					     14,
+					     format0,
+					     0,
+					     SI_RNTI,
+					     0,
+					     P_RNTI,
+					     CBA_RNTI,
+					     srs_flag);
+	  eNB->ulsch[0]->harq_processes[harq_pid]->subframe_scheduling_flag = 1;
 
           /////////////////////
           if (abstx) {
@@ -991,26 +990,24 @@ int main(int argc, char **argv)
 
           if (input_fdUL == NULL) {
 
-            start_meas(&UE->phy_proc_tx);
-
-#ifdef OFDMA_ULSCH
-
-            if (srs_flag)
-              generate_srs_tx(UE,0,AMP,subframe);
-
-            generate_drs_pusch(UE,0,AMP,subframe,first_rb,nb_rb,0);
+	    eNB->proc.frame_rx = 1;
+	    eNB->proc.subframe_rx = subframe;
+	    proc_rxtx_ue->frame_tx = proc_rxtx->frame_rx;
+	    proc_rxtx_ue->frame_rx = proc_rxtx->frame_tx;
+	    proc_rxtx_ue->subframe_tx = proc_rxtx->subframe_rx;
+	    proc_rxtx_ue->subframe_rx = proc_rxtx->subframe_tx;
 
-#else
+	    phy_procedures_UE_TX(UE,proc_rxtx_ue,0,0,normal_txrx,no_relay);
 
+	    /*
             if (srs_flag)
               generate_srs_tx(UE,0,AMP,subframe);
 
-            generate_drs_pusch(UE,0,
+            generate_drs_pusch(UE,proc_rxtx_ue,0,
                                AMP,subframe,
                                UE->ulsch[0]->harq_processes[harq_pid]->first_rb,
                                UE->ulsch[0]->harq_processes[harq_pid]->nb_rb,
                                0);
-#endif
 
             if ((cqi_flag == 1) && (n_frames == 1) ) {
               printf("CQI information (O %d) %d %d\n",UE->ulsch[0]->O,
@@ -1037,27 +1034,17 @@ int main(int argc, char **argv)
             stop_meas(&UE->ulsch_encoding_stats);
 
             start_meas(&UE->ulsch_modulation_stats);
-#ifdef OFDMA_ULSCH
             ulsch_modulation(UE->common_vars.txdataF,AMP,
-                             UE->frame_tx,subframe,&UE->frame_parms,UE->ulsch[0]);
-#else
-            //    printf("Generating PUSCH in subframe %d with amp %d, nb_rb %d\n",subframe,AMP,nb_rb);
-            ulsch_modulation(UE->common_vars.txdataF,AMP,
-                             UE->frame_tx,subframe,&UE->frame_parms,
+                             proc_rxtx_ue->frame_tx,subframe,&UE->frame_parms,
                              UE->ulsch[0]);
-#endif
             stop_meas(&UE->ulsch_modulation_stats);
+	    */
 
-            if (n_frames==1) {
-              write_output("txsigF0UL.m","txsF0", &UE->common_vars.txdataF[0][eNB->frame_parms.ofdm_symbol_size*nsymb*subframe],eNB->frame_parms.ofdm_symbol_size*nsymb,1,
-                           1);
-              //write_output("txsigF1.m","txsF1", UE->common_vars.txdataF[0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1);
-            }
 
-            tx_lev=0;
-            start_meas(&UE->ofdm_mod_stats);
 
-            for (aa=0; aa<1; aa++) {
+
+	    /*
+	    for (aa=0; aa<1; aa++) {
               if (frame_parms->Ncp == EXTENDED)
                 PHY_ofdm_mod(&UE->common_vars.txdataF[aa][subframe*nsymb*OFDM_SYMBOL_SIZE_COMPLEX_SAMPLES_NO_PREFIX],        // input
                              &txdata[aa][eNB->frame_parms.samples_per_tti*subframe],         // output
@@ -1071,20 +1058,24 @@ int main(int argc, char **argv)
                                   nsymb,
                                   frame_parms);
 
-#ifndef OFDMA_ULSCH
+
               apply_7_5_kHz(UE,UE->common_vars.txdata[aa],subframe<<1);
               apply_7_5_kHz(UE,UE->common_vars.txdata[aa],1+(subframe<<1));
-#endif
 
-              stop_meas(&UE->ofdm_mod_stats);
-              stop_meas(&UE->phy_proc_tx);
-              tx_lev += signal_energy(&txdata[aa][eNB->frame_parms.samples_per_tti*subframe],
-                                      eNB->frame_parms.samples_per_tti);
+*/
 
+	    tx_lev = signal_energy(&UE->common_vars.txdata[0][eNB->frame_parms.samples_per_tti*subframe],
+				   eNB->frame_parms.samples_per_tti);
+	    
+	    
+            if (n_frames==1) {
+              write_output("txsigF0UL.m","txsF0", &UE->common_vars.txdataF[0][eNB->frame_parms.ofdm_symbol_size*nsymb*subframe],eNB->frame_parms.ofdm_symbol_size*nsymb,1,
+                           1);
+              //write_output("txsigF1.m","txsF1", UE->common_vars.txdataF[0],FRAME_LENGTH_COMPLEX_SAMPLES_NO_PREFIX,1,1);
             }
-          }  // input_fd == NULL
-
-
+	    
+	  }  // input_fd == NULL
+	  
           tx_lev_dB = (unsigned int) dB_fixed_times10(tx_lev);
 
           if (n_frames==1) {
@@ -1100,7 +1091,8 @@ int main(int argc, char **argv)
           // compute tx_gain to achieve target SNR (per resource element!)
           tx_gain = sqrt(pow(10.0,.1*(N0+SNR))*(nb_rb*12/(double)UE->frame_parms.ofdm_symbol_size)/(double)tx_lev);
 
-          if (n_frames==1)
+
+	  if (n_frames==1)
             printf("tx_lev = %d (%d.%d dB,%f), gain %f\n",tx_lev,tx_lev_dB/10,tx_lev_dB,10*log10((double)tx_lev),10*log10(tx_gain));
 
 
@@ -1117,8 +1109,8 @@ int main(int argc, char **argv)
 
           for (i=0; i<eNB->frame_parms.samples_per_tti; i++) {
             for (aa=0; aa<1; aa++) {
-              s_re[aa][i] = ((double)(((short *)&txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)]);
-              s_im[aa][i] = ((double)(((short *)&txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)+1]);
+              s_re[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)]);
+              s_im[aa][i] = ((double)(((short *)&UE->common_vars.txdata[aa][eNB->frame_parms.samples_per_tti*subframe]))[(i<<1)+1]);
             }
           }
 
@@ -1191,74 +1183,13 @@ int main(int argc, char **argv)
             //write_output("rxsig1UL.m","rxs1", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1);
           }
 
-#ifndef OFDMA_ULSCH
-          remove_7_5_kHz(eNB,subframe<<1);
-          remove_7_5_kHz(eNB,1+(subframe<<1));
-          //  write_output("rxsig0_75.m","rxs0_75", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1);
-          //  write_output("rxsig1_75.m","rxs1_75", &eNB->common_vars.rxdata[0][0][eNB->frame_parms.samples_per_tti*subframe],eNB->frame_parms.samples_per_tti,1,1);
-
-#endif
-
-          start_meas(&eNB->phy_proc_rx);
-          start_meas(&eNB->ofdm_demod_stats);
-          lte_eNB_I0_measurements(eNB,
-				  subframe,
-                                  0,
-                                  1);
-
-          for (l=subframe*UE->frame_parms.symbols_per_tti; l<((1+subframe)*UE->frame_parms.symbols_per_tti); l++) {
-
-            slot_fep_ul(&eNB->frame_parms,
-                        &eNB->common_vars,
-                        l%(eNB->frame_parms.symbols_per_tti/2),
-                        l/(eNB->frame_parms.symbols_per_tti/2),
-                        0,
-                        0);
-          }
-
-          stop_meas(&eNB->ofdm_demod_stats);
 
-          eNB->ulsch[0]->cyclicShift = cyclic_shift;// cyclic shift for DMRS
+	  eNB->fep = (parallel_flag == 1) ? eNB_fep_full_2thread : eNB_fep_full;
+	  eNB->do_prach = NULL;
 
-	  /*
-          if(abstx) {
-            namepointer_log2 = &flogeren_name;
-            namepointer_chMag = &fmageren_name;
-            //namepointer_txlev = &ftxlev;
-          }
-	  */
+	  phy_procedures_eNB_common_RX(eNB);
+	  phy_procedures_eNB_uespec_RX(eNB,proc_rxtx,no_relay);
 
-          start_meas(&eNB->ulsch_demodulation_stats);
-          rx_ulsch(eNB,proc_rxtx,
-                   0,  // this is the effective sector id
-                   0,  // this is the UE_id
-                   eNB->ulsch,
-                   cooperation_flag);
-          stop_meas(&eNB->ulsch_demodulation_stats);
-
-	  /*
-          if(abstx) {
-            namepointer_chMag = NULL;
-
-            if(trials==0 && round==0 && SNR==snr0) {
-              char* namepointer ;
-              namepointer = &fperen_name;
-              write_output(namepointer, "xxx" ,eNB->lte_eNB_pusch_vars[0]->drs_ch_estimates[0][0],300,1,10);
-              namepointer = NULL ;
-              // flagMag = 1;
-            }
-          }
-	  */
-
-          start_meas(&eNB->ulsch_decoding_stats);
-
-          ret= ulsch_decoding(eNB,proc_rxtx,
-                              0, // UE_id
-                              control_only_flag,
-                              1,  // Nbundled
-                              llr8_flag);
-          stop_meas(&eNB->ulsch_decoding_stats);
-          stop_meas(&eNB->phy_proc_rx);
 
           if (cqi_flag > 0) {
             cqi_error = 0;
@@ -1289,11 +1220,13 @@ int main(int argc, char **argv)
 
           //    printf("ulsch_coding: O[%d] %d\n",i,o_flip[i]);
 
+	  
+	  //          if (ret <= eNB->ulsch[0]->max_turbo_iterations) {
+	  
+	  if (eNB->ulsch[0]->harq_processes[harq_pid]->round == 0) {
 
-          if (ret <= eNB->ulsch[0]->max_turbo_iterations) {
-
-            avg_iter += ret;
-            iter_trials++;
+	    //  avg_iter += ret;
+	    iter_trials++;
 
             if (n_frames==1) {
               printf("No ULSCH errors found, o_ACK[0]= %d, cqi_crc_status=%d\n",eNB->ulsch[0]->harq_processes[harq_pid]->o_ACK[0],eNB->ulsch[0]->harq_processes[harq_pid]->cqi_crc_status);
@@ -1308,7 +1241,7 @@ int main(int argc, char **argv)
 
             round=5;
           } else {
-            avg_iter += ret-1;
+	    //            avg_iter += ret-1;
             iter_trials++;
 
             errs[round]++;
@@ -1342,6 +1275,8 @@ int main(int argc, char **argv)
               printf("ULSCH in error in round %d\n",round);
             }
           }  // ulsch error
+	  
+
         } // round
 
         //      printf("\n");
@@ -1757,7 +1692,7 @@ int main(int argc, char **argv)
 
       if (((double)errs[0]/(round_trials[0]))<1e-2)
         break;
-    } // SNR
+  } // SNR
 
     //
 
@@ -1767,30 +1702,11 @@ int main(int argc, char **argv)
 
   }//ch realization
 
-  /*
-  if(abstx) {
-    fperen = fopen(fperen_name,"a+");
-    fprintf(fperen,"];\n");
-    fclose(fperen);
-
-    fmageren = fopen(fmageren_name,"a+");
-    fprintf(fmageren,"];\n");
-    fclose(fmageren);
-
-    flogeren = fopen(flogeren_name,"a+");
-    fprintf(flogeren,"];\n");
-    fclose(flogeren);
-  }
-  */
-
-  // ftxlev = fopen(ftxlev_name,"a+");
-  //fprintf(ftxlev,"];\n");
-  //fclose(ftxlev);
-
 
-  //  write_output("chestim_f_dene.m","chestf",ulchestim_f_all,300*12,2,1);*/
+  oai_exit=1;
+  pthread_cond_signal(&eNB->proc.cond_fep);
 
-  if(abstx) { // ABSTRACTION
+  if (abstx) { // ABSTRACTION
     fprintf(csv_fdUL,"];");
     fclose(csv_fdUL);
   }
diff --git a/openair1/SIMULATION/LTE_PHY/unitary_defs.h b/openair1/SIMULATION/LTE_PHY/unitary_defs.h
new file mode 100644
index 0000000000000000000000000000000000000000..6fefc47a723fd7e12196c262c3820ebccd524bce
--- /dev/null
+++ b/openair1/SIMULATION/LTE_PHY/unitary_defs.h
@@ -0,0 +1,10 @@
+openair0_device openair0;
+int oai_exit=0;
+
+void exit_fun(const char *s) { exit(-1); }
+
+extern unsigned int dlsch_tbs25[27][25],TBStable[27][110];
+extern unsigned char offset_mumimo_llr_drange_fix;
+
+extern unsigned short dftsizes[33];
+extern short *ul_ref_sigs[30][2][33];
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index fc4f8d5d39b00a975444a72765c56ddf8b0df25c..b8e9b21866b4a65c5a54788f23e1a202ee75a4dd 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -610,7 +610,7 @@ extern "C" {
 
     switch ((int)openair0_cfg[0].sample_rate) {
     case 30720000:
-      s->usrp->set_master_clock_rate(61.44e6);
+      s->usrp->set_master_clock_rate(30.72e6);
       openair0_cfg[0].tx_sample_advance     = 115;
       openair0_cfg[0].tx_bw                 = 20e6;
       openair0_cfg[0].rx_bw                 = 20e6;
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 742406532740ebf8ceda77208dde06139eec5c74..60a067b7903653d148c6f958323d391217efa6d9 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -166,6 +166,7 @@ void stop_eNB(int nb_inst);
 
 
 static inline void thread_top_init(char *thread_name,
+				   int affinity,
 				   uint64_t runtime,
 				   uint64_t deadline,
 				   uint64_t period) {
@@ -209,7 +210,10 @@ static inline void thread_top_init(char *thread_name,
 #ifdef CPU_AFFINITY
   if (get_nprocs() > 2)
   {
-    for (j = 1; j < get_nprocs(); j++)
+    if (affinity == 0)
+      CPU_SET(0,&cpuset);
+    else
+      for (j = 1; j < get_nprocs(); j++)
         CPU_SET(j, &cpuset);
     s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
     if (s != 0)
@@ -628,7 +632,7 @@ static void* eNB_thread_rxtx( void* param ) {
 
 
   sprintf(thread_name,"RXn_TXnp4_%d\n",&eNB->proc.proc_rxtx[0] == proc ? 0 : 1);
-  thread_top_init(thread_name,850000L,1000000L,2000000L);
+  thread_top_init(thread_name,1,850000L,1000000L,2000000L);
 
   while (!oai_exit) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_eNB_PROC_RXTX0+(proc->subframe_rx&1), 0 );
@@ -834,7 +838,7 @@ static void* eNB_thread_asynch_rxtx( void* param ) {
 
   int subframe=0, frame=0; 
 
-  thread_top_init("thread_asynch",870000L,1000000L,1000000L);
+  thread_top_init("thread_asynch",1,870000L,1000000L,1000000L);
 
   // wait for top-level synchronization and do one acquisition to get timestamp for setting frame/subframe
 
@@ -1157,7 +1161,7 @@ static void* eNB_thread_FH( void* param ) {
   // set default return value
   eNB_thread_FH_status = 0;
 
-  thread_top_init("eNB_thread_FH",870000,1000000,1000000);
+  thread_top_init("eNB_thread_FH",0,870000,1000000,1000000);
 
   wait_sync("eNB_thread_FH");
 
@@ -1237,7 +1241,7 @@ static void* eNB_thread_prach( void* param ) {
   // set default return value
   eNB_thread_prach_status = 0;
 
-  thread_top_init("eNB_thread_prach",500000L,1000000L,20000000L);
+  thread_top_init("eNB_thread_prach",1,500000L,1000000L,20000000L);
 
   while (!oai_exit) {
     
@@ -1269,7 +1273,7 @@ static void* eNB_thread_single( void* param ) {
   // set default return value
   eNB_thread_single_status = 0;
 
-  thread_top_init("eNB_thread_single",870000,1000000,1000000);
+  thread_top_init("eNB_thread_single",0,870000,1000000,1000000);
 
   wait_sync("eNB_thread_single");
 
@@ -1333,6 +1337,7 @@ static void* eNB_thread_single( void* param ) {
 
 }
 
+extern void init_fep_thread(PHY_VARS_eNB *, pthread_attr_t *);
 
 void init_eNB_proc(int inst) {
   
@@ -1341,7 +1346,7 @@ void init_eNB_proc(int inst) {
   PHY_VARS_eNB *eNB;
   eNB_proc_t *proc;
   eNB_rxtx_proc_t *proc_rxtx;
-  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL;
+  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL;
 
   for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB = PHY_vars_eNB_g[inst][CC_id];
@@ -1351,10 +1356,10 @@ void init_eNB_proc(int inst) {
     proc_rxtx = proc->proc_rxtx;
     proc_rxtx[0].instance_cnt_rxtx = -1;
     proc_rxtx[1].instance_cnt_rxtx = -1;
-    proc->instance_cnt_prach = -1;
-    proc->instance_cnt_FH = -1;
+    proc->instance_cnt_prach       = -1;
+    proc->instance_cnt_FH          = -1;
     proc->instance_cnt_asynch_rxtx = -1;
-    proc->CC_id = CC_id;
+    proc->CC_id = CC_id;    
     
     proc->first_rx=1;
     proc->first_tx=1;
@@ -1370,6 +1375,14 @@ void init_eNB_proc(int inst) {
     pthread_cond_init( &proc->cond_prach, NULL);
     pthread_cond_init( &proc->cond_FH, NULL);
     pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
+
+    pthread_attr_init( &proc->attr_FH);
+    pthread_attr_init( &proc->attr_prach);
+    pthread_attr_init( &proc->attr_asynch_rxtx);
+    pthread_attr_init( &proc->attr_single);
+    pthread_attr_init( &proc->attr_fep);
+    pthread_attr_init( &proc_rxtx[0].attr_rxtx);
+    pthread_attr_init( &proc_rxtx[1].attr_rxtx);
 #ifndef DEADLINE_SCHEDULER
     attr0       = &proc_rxtx[0].attr_rxtx;
     attr1       = &proc_rxtx[1].attr_rxtx;
@@ -1377,6 +1390,7 @@ void init_eNB_proc(int inst) {
     attr_prach  = &proc->attr_prach;
     attr_asynch = &proc->attr_asynch_rxtx;
     attr_single = &proc->attr_single;
+    attr_fep    = &proc->attr_fep;
 #endif
 
     if (eNB->single_thread_flag==0) {
@@ -1384,9 +1398,10 @@ void init_eNB_proc(int inst) {
       pthread_create( &proc_rxtx[1].pthread_rxtx, attr1, eNB_thread_rxtx, &proc_rxtx[1] );
       pthread_create( &proc->pthread_FH, attr_FH, eNB_thread_FH, &eNB->proc );
     }
-    else 
+    else {
       pthread_create(&proc->pthread_single, attr_single, eNB_thread_single, &eNB->proc);
-
+      init_fep_thread(eNB,attr_fep);
+    }
     pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc );
     if ((eNB->node_timing == synch_to_other) ||
 	(eNB->node_function == NGFI_RRU_IF5) ||