diff --git a/common/utils/LOG/vcd_signal_dumper.c b/common/utils/LOG/vcd_signal_dumper.c
index 7ea15cf9dbe13897c7d0e245d9628fc37c330d18..63c5336bd88fc25751b623106a1417525f631588 100644
--- a/common/utils/LOG/vcd_signal_dumper.c
+++ b/common/utils/LOG/vcd_signal_dumper.c
@@ -247,7 +247,8 @@ const char* eurecomVariablesNames[] = {
   "slot_number_TX0_gNB",
   "slot_number_TX1_gNB",
   "slot_number_RX0_gNB",
-  "slot_number_RX1_gNB"
+  "slot_number_RX1_gNB",
+  "ru_tx_ofdm_mask"
 };
 
 const char* eurecomFunctionsNames[] = {
@@ -328,6 +329,13 @@ const char* eurecomFunctionsNames[] = {
   "phy_procedures_ru_feptx_ofdm7",
   "phy_procedures_ru_feptx_ofdm8",
   "phy_procedures_ru_feptx_ofdm9",
+  "phy_procedures_ru_feptx_ofdm10",
+  "phy_procedures_ru_feptx_ofdm11",
+  "phy_procedures_ru_feptx_ofdm12",
+  "phy_procedures_ru_feptx_ofdm13",
+  "phy_procedures_ru_feptx_ofdm14",
+  "phy_procedures_ru_feptx_ofdm15",
+  "phy_procedures_ru_feptx_ofdm16",
   "phy_procedures_ru_feptx_prec0",
   "phy_procedures_ru_feptx_prec1",
   "phy_procedures_ru_feptx_prec2",
@@ -502,6 +510,7 @@ const char* eurecomFunctionsNames[] = {
   "pdcch_interleaving",
   "pdcch_tx",
   /*NR softmodem signal*/
+  "wakeup_txfh",
   "gNB_thread_rxtx0",
   "gNB_thread_rxtx1"
 };
diff --git a/common/utils/LOG/vcd_signal_dumper.h b/common/utils/LOG/vcd_signal_dumper.h
index a7c4c10fe31a6dc88859dfc450683d07151f6761..3a6fb6d6abb9f932b700efa1acb747ef6fd5a1ad 100644
--- a/common/utils/LOG/vcd_signal_dumper.h
+++ b/common/utils/LOG/vcd_signal_dumper.h
@@ -225,6 +225,7 @@ typedef enum {
   VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,
   VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX0_GNB,
   VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_RX1_GNB,
+  VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK,
 
 
   VCD_SIGNAL_DUMPER_VARIABLES_END
@@ -309,6 +310,13 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM7,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM8,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM9,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM10,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM11,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM12,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM13,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM14,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM15,
+  VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM16,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC1,
   VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC2,
@@ -494,6 +502,7 @@ typedef enum {
   VCD_SIGNAL_DUMPER_FUNCTIONS_PDCCH_TX,
 
   /*NR softmodem signal*/
+  VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH,
   VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX0,
   VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1,
 
diff --git a/common/utils/T/T_defs.h b/common/utils/T/T_defs.h
index 4f2b10c3ae152d08a2eedebcd65e0d54cf28c467..ab275d4d62d9cd7f03474e0a0521881b963adecb 100644
--- a/common/utils/T/T_defs.h
+++ b/common/utils/T/T_defs.h
@@ -73,10 +73,10 @@ typedef struct {
 } T_cache_t;
 
 /* number of VCD functions (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_FUNCTIONS (237)//(232)
+#define VCD_NUM_FUNCTIONS (245)
 
 /* number of VCD variables (to be kept up to date! see in T_messages.txt) */
-#define VCD_NUM_VARIABLES (185)
+#define VCD_NUM_VARIABLES (186)
 
 /* first VCD function (to be kept up to date! see in T_messages.txt) */
 #define VCD_FIRST_FUNCTION    ((uintptr_t)T_VCD_FUNCTION_RT_SLEEP)
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index 0b10b6e25ece1fd6199919df2cd012df24804a20..407bb66be17416fccb5345f58198da518fdf4357 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -2050,6 +2050,11 @@ ID = VCD_VARIABLE_SLOT_NUMBER_RX1_GNB
     GROUP = ALL:VCD:ENB:VCD_VARIABLE
     FORMAT = ulong,value
     VCD_NAME = slot_number_RX1_gNB
+ID = VCD_VARIABLE_RU_TX_OFDM_MASK
+    DESC = VCD variable RU_TX_OFDM_MASK
+    GROUP = ALL:VCD:ENB:VCD_VARIABLE
+    FORMAT = ulong,value
+    VCD_NAME = ru_tx_ofdm_mask
 
 #functions
 
@@ -2418,6 +2423,41 @@ ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM9
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
     FORMAT = int,value
     VCD_NAME = phy_procedures_ru_feptx_ofdm9
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM10
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM10
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm10
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM11
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM11
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm11
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM12
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM12
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm12
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM13
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM13
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm13
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM14
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM14
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm14
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM15
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM15
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm15
+ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_OFDM16
+    DESC = VCD function PHY_PROCEDURES_RU_FEPTX_OFDM16
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = phy_procedures_ru_feptx_ofdm16
 ID = VCD_FUNCTION_PHY_PROCEDURES_RU_FEPTX_PREC
     DESC = VCD function PHY_PROCEDURES_RU_FEPTX_PREC
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
@@ -3230,6 +3270,11 @@ ID = VCD_FUNCTION_PDCCH_TX
     VCD_NAME = pdcch_tx
 
   #function for gNB
+ID = VCD_FUNCTION_WAKEUP_TXFH
+    DESC = VCD function WAKEUP_TXFH
+    GROUP = ALL:VCD:ENB:VCD_FUNCTION
+    FORMAT = int,value
+    VCD_NAME = wakeup_txfh
 ID = VCD_FUNCTION_gNB_PROC_RXTX0
     DESC = VCD function gNB_PROC_RXTX0
     GROUP = ALL:VCD:ENB:VCD_FUNCTION
diff --git a/executables/nr-gnb.c b/executables/nr-gnb.c
index b4bf5efe81e834ad77228041d9fe98b6281be239..cb1d45adc2d3667ab337f345195f0ce7a237e638 100644
--- a/executables/nr-gnb.c
+++ b/executables/nr-gnb.c
@@ -290,6 +290,8 @@ static void *gNB_L1_thread_tx(void *param) {
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_SLOT_NUMBER_TX1_GNB,slot_tx);
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX1_GNB,frame_tx);
     phy_procedures_gNB_TX(gNB, frame_tx,slot_tx, 1);
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 1 );
     pthread_mutex_lock( &L1_proc_tx->mutex );
     L1_proc_tx->instance_cnt = -1;
 
@@ -301,6 +303,7 @@ static void *gNB_L1_thread_tx(void *param) {
     pthread_mutex_unlock(&L1_proc_tx->mutex);
 
     wakeup_txfh(gNB,L1_proc_tx,frame_tx,slot_tx,timestamp_tx);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_WAKEUP_TXFH, 0 );
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PROC_RXTX1, 0 );
   }
 
@@ -420,10 +423,10 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
 
 // note this  should depend on the numerology used by the TX L1 thread, set here for 500us slot time
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,1);
-  waitret=timedwait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh",1000000); 
+  waitret=wait_on_condition(&proc->mutex_RUs_tx,&proc->cond_RUs,&proc->instance_cnt_RUs,"wakeup_txfh"); 
+  AssertFatal(release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing gNB lock on RUs\n"); 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL,0);
 
-  AssertFatal(release_thread(&proc->mutex_RUs_tx,&proc->instance_cnt_RUs,"wakeup_txfh")==0, "error releaseing gNB lock on RUs\n"); 
   VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,proc->instance_cnt_RUs);
 
   if (waitret == ETIMEDOUT) {
@@ -448,7 +451,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
     ru      = gNB->RU_list[i];
     ru_proc = &ru->proc;
     
-    AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
+    //AssertFatal((ret = pthread_mutex_lock(&ru_proc->mutex_gNBs))==0,"ERROR pthread_mutex_lock failed on mutex_gNBs L1_thread_tx with ret=%d\n",ret);
 
     if (ru_proc->instance_cnt_gNBs == 0) {
       VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 1);
@@ -456,7 +459,7 @@ int wakeup_txfh(PHY_VARS_gNB *gNB,gNB_L1_rxtx_proc_t *proc,int frame_tx,int slot
       AssertFatal((ret=pthread_mutex_lock(&gNB->proc.mutex_RU_tx))==0,"mutex_lock returns %d\n",ret);
       gNB->proc.RU_mask_tx = 0;
       AssertFatal((ret=pthread_mutex_unlock(&gNB->proc.mutex_RU_tx))==0,"mutex_unlock returns %d\n",ret);
-      AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_gNBs ))==0,"mutex_unlock return %d\n",ret);
+      //AssertFatal((ret=pthread_mutex_unlock( &ru_proc->mutex_gNBs ))==0,"mutex_unlock return %d\n",ret);
 
       VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST_UE, 0);
       return(-1);
@@ -522,6 +525,8 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
   RU_proc_t *ru_proc=&ru->proc;
   int ret;
   int i;
+  struct timespec abstime;
+  int time_ns = 50000;
   
   AssertFatal((ret=pthread_mutex_lock(&proc->mutex_RU))==0,"mutex_lock returns %d\n",ret);
   for (i=0;i<gNB->num_RU;i++) {
@@ -542,14 +547,22 @@ int wakeup_rxtx(PHY_VARS_gNB *gNB,RU_t *ru) {
     AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_RU))==0,"muex_unlock returns %d\n",ret);
   }
 
+  clock_gettime(CLOCK_REALTIME, &abstime);
+  abstime.tv_nsec = abstime.tv_nsec + time_ns;
+
+  if (abstime.tv_nsec >= 1000*1000*1000) {
+    abstime.tv_nsec -= 1000*1000*1000;
+    abstime.tv_sec  += 1;
+  }
 
   // wake up TX for subframe n+sl_ahead
   // lock the TX mutex and make sure the thread is ready
-  AssertFatal((ret=pthread_mutex_lock(&L1_proc->mutex)) == 0,"mutex_lock returns %d\n", ret);
+  AssertFatal((ret=pthread_mutex_timedlock(&L1_proc->mutex, &abstime)) == 0,"mutex_lock returns %d\n", ret);
 
   if (L1_proc->instance_cnt == 0) { // L1_thread is busy so abort the subframe
    AssertFatal((ret=pthread_mutex_unlock( &L1_proc->mutex))==0,"muex_unlock return %d\n",ret);
    LOG_W(PHY,"L1_thread isn't ready in %d.%d, aborting RX processing\n",ru_proc->frame_rx,ru_proc->tti_rx); 
+   return(-1);
   }
  
   ++L1_proc->instance_cnt;
diff --git a/executables/nr-ru.c b/executables/nr-ru.c
index 1abcd3b7a159669598ce48ec4f165f2fd3fe1dbf..b402110c4bb4cd08f0f33e7a4999cfdaf30fb9f9 100644
--- a/executables/nr-ru.c
+++ b/executables/nr-ru.c
@@ -91,7 +91,8 @@ unsigned short config_frames[4] = {2,9,11,13};
 /* these variables have to be defined before including ENB_APP/enb_paramdef.h and GNB_APP/gnb_paramdef.h */
 static int DEFBANDS[] = {7};
 static int DEFENBS[] = {0};
-
+static int DEFBFW[] = {0x00007fff};
+ 
 //static int DEFNRBANDS[] = {7};
 //static int DEFGNBS[] = {0};
 
@@ -677,9 +678,6 @@ void rx_rf(RU_t *ru,int *frame,int *slot) {
   proc->frame_rx     = (proc->timestamp_rx / (fp->samples_per_slot*fp->slots_per_frame))&1023;
   proc->tti_rx       = (proc->timestamp_rx / fp->samples_per_slot)%fp->slots_per_frame;
   // synchronize first reception to frame 0 subframe 0
-  proc->timestamp_tx = proc->timestamp_rx+(sl_ahead*fp->samples_per_slot);
-  proc->tti_tx  = (proc->tti_rx+sl_ahead)%fp->slots_per_frame;
-  proc->frame_tx     = (proc->tti_rx>(fp->slots_per_frame-1-sl_ahead)) ? (proc->frame_rx+1)&1023 : proc->frame_rx;
   LOG_D(PHY,"RU %d/%d TS %llu (off %d), frame %d, slot %d.%d / %d\n",
         ru->idx,
         0,
@@ -764,18 +762,22 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_RU, frame );
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TTI_NUMBER_TX0_RU, slot );
 
-    for (i=0; i<ru->nb_tx; i++)
+    for (i=0; i<ru->nb_tx; i++){
       txp[i] = (void *)&ru->common.txdata[i][(slot*fp->samples_per_slot)-sf_extension];
+    }
+
 
     VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST, (timestamp-ru->openair0_cfg.tx_sample_advance)&0xffffffff );
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
     // prepare tx buffer pointers
+    start_meas(&ru->tx_fhaul);
     txs = ru->rfdevice.trx_write_func(&ru->rfdevice,
                                       timestamp+ru->ts_offset-ru->openair0_cfg.tx_sample_advance-sf_extension,
                                       txp,
                                       siglen+sf_extension,
                                       ru->nb_tx,
                                       flags);
+    stop_meas(&ru->tx_fhaul);
     LOG_D(PHY,"[TXPATH] RU %d tx_rf, writing to TS %llu, frame %d, unwrapped_frame %d, subframe %d\n",ru->idx,
           (long long unsigned int)timestamp,frame,proc->frame_tx_unwrap,slot);
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
@@ -784,6 +786,7 @@ void tx_rf(RU_t *ru,int frame,int slot, uint64_t timestamp) {
 }
 
 
+
 /*!
  * \brief The Asynchronous RX/TX FH thread of RAU/RCC/gNB/RRU.
  * This handles the RX FH for an asynchronous RRU/UE
@@ -872,7 +875,7 @@ static void *ru_thread_prach( void *param ) {
                 0,0
           );
     }
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 ); */
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_RU_PRACH_RX, 0 );*/ 
     if (release_thread(&proc->mutex_prach,&proc->instance_cnt_prach,"ru_prach_thread") < 0) break;
   }
 
@@ -1209,14 +1212,20 @@ static void *ru_stats_thread(void *param) {
     sleep(1);
 
     if (opp_enabled == 1) {
+
       if (ru->feprx) print_meas(&ru->ofdm_demod_stats,"feprx",NULL,NULL);
 
-      if (ru->feptx_ofdm) print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
+      if (ru->feptx_ofdm){
+        print_meas(&ru->precoding_stats,"feptx_prec",NULL,NULL);
+        print_meas(&ru->txdataF_copy_stats,"txdataF_copy",NULL,NULL);
+        print_meas(&ru->ofdm_mod_stats,"feptx_ofdm",NULL,NULL);
+        print_meas(&ru->ofdm_total_stats,"feptx_total",NULL,NULL);
+      }
 
       if (ru->fh_north_asynch_in) print_meas(&ru->rx_fhaul,"rx_fhaul",NULL,NULL);
 
-      if (ru->fh_north_out) {
         print_meas(&ru->tx_fhaul,"tx_fhaul",NULL,NULL);
+      if (ru->fh_north_out) {
         print_meas(&ru->compression,"compression",NULL,NULL);
         print_meas(&ru->transport,"transport",NULL,NULL);
       }
@@ -1273,7 +1282,7 @@ static void *ru_thread_tx( void *param ) {
     // do TX front-end processing if needed (precoding and/or IDFTs)
     if (ru->feptx_prec) ru->feptx_prec(ru,frame_tx,tti_tx);
 
-    // do OFDM if needed
+    // do OFDM with/without TX front-end processing  if needed
     if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,frame_tx,tti_tx);
 
     if(!emulate_rf) {
@@ -1284,8 +1293,17 @@ static void *ru_thread_tx( void *param ) {
     } else {
       if(proc->frame_tx == print_frame) {
         for (i=0; i<ru->nb_tx; i++) {
-          sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
-          LOG_M(filename,"txdataF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
+
+          if(proc->tti_tx == 0) {
+            sprintf(filename,"gNBdataF_frame%d_sl%d.m", print_frame, proc->tti_tx);
+            LOG_M(filename,"txdataF_frame",&ru->gNB_list[0]->common_vars.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
+
+            sprintf(filename,"tx%ddataF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
+            LOG_M(filename,"txdataF_frame",&ru->common.txdataF[i][0],fp->samples_per_frame_wCP, 1, 1);
+
+            sprintf(filename,"tx%ddataF_BF_frame%d_sl%d.m", i, print_frame, proc->tti_tx);
+            LOG_M(filename,"txdataF_BF_frame",&ru->common.txdataF_BF[i][0],fp->samples_per_subframe_wCP, 1, 1);
+          }
 
           if(proc->tti_tx == 9) {
             sprintf(filename,"tx%ddata_frame%d.m", i, print_frame);
@@ -1338,14 +1356,14 @@ static void *ru_thread_tx( void *param ) {
         ret = pthread_mutex_lock(&L1_proc->mutex_RUs_tx);
         AssertFatal(ret == 0,"mutex_lock returns %d\n",ret);
         // the thread can now be woken up
-        if (L1_proc->instance_cnt_RUs==-1) {
-           AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
+        //if (L1_proc->instance_cnt_RUs == -1) {
+          L1_proc->instance_cnt_RUs = 0;
+          AssertFatal(pthread_cond_signal(&L1_proc->cond_RUs) == 0,
                        "ERROR pthread_cond_signal for gNB_L1_thread\n");
-        } //else AssertFatal(1==0,"gNB TX thread is not ready\n");
-        L1_proc->instance_cnt_RUs = 0;
-        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
+        //} //else AssertFatal(1==0,"gNB TX thread is not ready\n");
         ret = pthread_mutex_unlock(&L1_proc->mutex_RUs_tx);
         AssertFatal(ret == 0,"mutex_unlock returns %d\n",ret);
+        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE,L1_proc->instance_cnt_RUs);
       }
     }
   }
@@ -1507,7 +1525,7 @@ static void *ru_thread( void *param ) {
       // do TX front-end processing if needed (precoding and/or IDFTs)
       if (ru->feptx_prec) ru->feptx_prec(ru,proc->frame_tx,proc->tti_tx);
 
-      // do OFDM if needed
+      // do OFDM with/without TX front-end processing  if needed
       if ((ru->fh_north_asynch_in == NULL) && (ru->feptx_ofdm)) ru->feptx_ofdm(ru,proc->frame_tx,proc->tti_tx);
 
       if(!emulate_rf) {
@@ -1646,6 +1664,7 @@ int stop_rf(RU_t *ru) {
   return 0;
 }
 
+
 void init_RU_proc(RU_t *ru) {
   int i=0;
   RU_proc_t *proc;
@@ -1668,6 +1687,7 @@ void init_RU_proc(RU_t *ru) {
   proc->frame_offset             = 0;
   proc->num_slaves               = 0;
   proc->frame_tx_unwrap          = 0;
+  proc->feptx_mask               = 0;
 
   for (i=0; i<10; i++) proc->symbol_mask[i]=0;
 
@@ -2025,9 +2045,9 @@ void set_function_spec_param(RU_t *ru) {
         malloc_IF4p5_buffer(ru);
       } else if (ru->function == gNodeB_3GPP) {
         ru->do_prach             = 0;                       // no prach processing in RU
-        ru->feprx                = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full;     // RX DFTs
-        ru->feptx_ofdm           = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // this is fep with idft and precoding
-        ru->feptx_prec           = NULL;              // this is fep with idft and precoding
+        ru->feprx                = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread   : nr_fep_full;                // RX DFTs
+        ru->feptx_ofdm           = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm;              // this is fep with idft and precoding
+        ru->feptx_prec           = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL                  : nr_feptx_prec;           // this is fep with idft and precoding
         ru->fh_north_in          = NULL;                    // no incoming fronthaul from north
         ru->fh_north_out         = NULL;                    // no outgoing fronthaul to north
         ru->nr_start_if          = NULL;                    // no if interface
@@ -2055,8 +2075,8 @@ void set_function_spec_param(RU_t *ru) {
 
     case REMOTE_IF5: // the remote unit is IF5 RRU
       ru->do_prach               = 0;
-      ru->feprx                  = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread : nr_fep_full;     // this is frequency-shift + DFTs
-      ru->feptx_prec             = feptx_prec;          // need to do transmit Precoding + IDFTs
+      ru->feprx                  = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_fep_full_2thread   : nr_fep_full;     // this is frequency-shift + DFTs
+      ru->feptx_prec             = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL                  : nr_feptx_prec;          // need to do transmit Precoding + IDFTs
       ru->feptx_ofdm             = (get_thread_worker_conf() == WORKER_ENABLE) ? nr_feptx_ofdm_2thread : nr_feptx_ofdm; // need to do transmit Precoding + IDFTs
       ru->fh_south_in            = fh_if5_south_in;     // synchronous IF5 reception
       ru->fh_south_out           = fh_if5_south_out;    // synchronous IF5 transmission
@@ -2080,7 +2100,7 @@ void set_function_spec_param(RU_t *ru) {
     case REMOTE_IF4p5:
       ru->do_prach               = 0;
       ru->feprx                  = NULL;                // DFTs
-      ru->feptx_prec             = feptx_prec;          // Precoding operation
+      ru->feptx_prec             = (get_thread_worker_conf() == WORKER_ENABLE) ? NULL : nr_feptx_prec;          // Precoding operation
       ru->feptx_ofdm             = NULL;                // no OFDM mod
       ru->fh_south_in            = fh_if4p5_south_in;   // synchronous IF4p5 reception
       ru->fh_south_out           = fh_if4p5_south_out;  // synchronous IF4p5 transmission
@@ -2334,6 +2354,14 @@ void RCconfig_RU(void)
       RC.ru[j]->nb_rx                             = *(RUParamList.paramarray[j][RU_NB_RX_IDX].uptr);
       RC.ru[j]->att_tx                            = *(RUParamList.paramarray[j][RU_ATT_TX_IDX].uptr);
       RC.ru[j]->att_rx                            = *(RUParamList.paramarray[j][RU_ATT_RX_IDX].uptr);
+
+      if (config_isparamset(RUParamList.paramarray[j], RU_BF_WEIGHTS_LIST_IDX)) {
+        RC.ru[j]->nb_bfw = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].numelt;
+        for (i=0; i<RC.ru[j]->num_gNB; i++)  {
+          RC.ru[j]->bw_list[i] = (int32_t *)malloc16_clear((RC.ru[j]->nb_bfw)*sizeof(int32_t));
+          for (int b=0; b<RC.ru[j]->nb_bfw; b++) RC.ru[j]->bw_list[i][b] = RUParamList.paramarray[j][RU_BF_WEIGHTS_LIST_IDX].iptr[b];
+        }
+      }
     }// j=0..num_rus
   } else {
     RC.nb_RU = 0;
diff --git a/openair1/PHY/INIT/nr_init_ru.c b/openair1/PHY/INIT/nr_init_ru.c
index 206fcf3b6f3a65e2eab8d7748e3bcd9ec51d1a1b..e8828d805c9c5d5b96b7498b81deb1f15d3c4c60 100644
--- a/openair1/PHY/INIT/nr_init_ru.c
+++ b/openair1/PHY/INIT/nr_init_ru.c
@@ -74,6 +74,10 @@ int nr_phy_init_RU(RU_t *ru) {
     }
   
 
+    // allocate precoding input buffers (TX)
+    ru->common.txdataF = (int32_t **)malloc16(15*sizeof(int32_t*));
+    for(i=0; i< 15; ++i)  ru->common.txdataF[i] = (int32_t*)malloc16_clear(fp->samples_per_frame_wCP*sizeof(int32_t)); // [hna] samples_per_frame without CP
+
     // allocate IFFT input buffers (TX)
     ru->common.txdataF_BF = (int32_t **)malloc16(ru->nb_tx*sizeof(int32_t*));
     LOG_I(PHY,"[INIT] common.txdata_BF= %p (%lu bytes)\n",ru->common.txdataF_BF,
@@ -105,37 +109,33 @@ int nr_phy_init_RU(RU_t *ru) {
 		RC.nb_nr_L1_inst,NUMBER_OF_gNB_MAX);
 
     LOG_E(PHY,"[INIT] %s() RC.nb_nr_L1_inst:%d \n", __FUNCTION__, RC.nb_nr_L1_inst);
-
-    for (i=0; i<RC.nb_nr_L1_inst; i++) {
-      for (p=0;p<15;p++) {
-	if (p == 0|| p==5) {
-	  ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*));
-	  for (j=0; j<ru->nb_tx; j++) {
-	    ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
-	    // antenna ports 0-3 are mapped on antennas 0-3
-	    // antenna port 4 is mapped on antenna 0
-	    // antenna ports 5-14 are mapped on all antennas 
-	    if (((p<4) && (p==j)) || ((p==4) && (j==0))) {
-	      for (re=0; re<fp->ofdm_symbol_size; re++) 
-              {
-		ru->beam_weights[i][p][j][re] = 0x00007fff; 
-
-                //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d][%d][%d] = %d\n", i,p,j,re,ru->beam_weights[i][p][j][re]);
-              }
-	    }
-	    else if (p>4) {
-	      for (re=0; re<fp->ofdm_symbol_size; re++) 
-              {
-		ru->beam_weights[i][p][j][re] = 0x00007fff/ru->nb_tx; 
-                //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d][%d][%d] = %d\n", i,p,j,re,ru->beam_weights[i][p][j][re]);
-              }
-	    }  
-	    //LOG_D(PHY,"[INIT] lte_common_vars->beam_weights[%d][%d] = %p (%lu bytes)\n", i,j,ru->beam_weights[i][p][j], fp->ofdm_symbol_size*sizeof(int32_t)); 
-	  } // for (j=0
-	} // if (p<ru
-      } // for p
-    } //for i
+    
+    int beam_count = 0;
+    if (ru->nb_tx>1) {
+      for (p=0;p<fp->Lmax;p++) {
+        if ((fp->L_ssb >> p) & 0x01)
+          beam_count++;
+      }
+      AssertFatal(ru->nb_bfw==(beam_count*ru->nb_tx),"Number of beam weights from config file is %d while the expected number is %d",ru->nb_bfw,(beam_count*ru->nb_tx));
+    
+      int l_ind = 0;
+      for (i=0; i<RC.nb_nr_L1_inst; i++) {
+        for (p=0;p<fp->Lmax;p++) {
+          if ((fp->L_ssb >> p) & 0x01)  {
+	    ru->beam_weights[i][p] = (int32_t **)malloc16_clear(ru->nb_tx*sizeof(int32_t*));
+	    for (j=0; j<ru->nb_tx; j++) {
+	      ru->beam_weights[i][p][j] = (int32_t *)malloc16_clear(fp->ofdm_symbol_size*sizeof(int32_t));
+              for (re=0; re<fp->ofdm_symbol_size; re++) 
+		ru->beam_weights[i][p][j][re] = ru->bw_list[i][l_ind];
+              //printf("Beam Weight %08x for beam %d and tx %d\n",ru->bw_list[i][l_ind],p,j);
+              l_ind++; 
+  	    } // for j
+	  } // for p
+        }
+      } //for i
+    }
   } // !=IF5
+
   ru->common.sync_corr = (uint32_t*)malloc16_clear( LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(uint32_t)*fp->samples_per_subframe_wCP );
 
   return(0);
@@ -162,6 +162,10 @@ void nr_phy_free_RU(RU_t *ru)
     for (i = 0; i < ru->nb_rx; i++) free_and_zero(ru->common.rxdata_7_5kHz[i]);
     free_and_zero(ru->common.rxdata_7_5kHz);
 
+    // free beamforming input buffers (TX)
+    for (i = 0; i < 15; i++) free_and_zero(ru->common.txdataF[i]);
+    free_and_zero(ru->common.txdataF);
+
     // free IFFT input buffers (TX)
     for (i = 0; i < ru->nb_tx; i++) free_and_zero(ru->common.txdataF_BF[i]);
     free_and_zero(ru->common.txdataF_BF);
@@ -179,10 +183,8 @@ void nr_phy_free_RU(RU_t *ru)
 
     for (i = 0; i < RC.nb_nr_L1_inst; i++) {
       for (p = 0; p < 15; p++) {
-	if (p == 0 || p == 5) {
 	  for (j=0; j<ru->nb_tx; j++) free_and_zero(ru->beam_weights[i][p][j]);
 	  free_and_zero(ru->beam_weights[i][p]);
-	}
       }
     }
   }
diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c
index 6a13ac88a3eef98adc2514082d38d9d9da941bc9..856621e673593702f4dc933fba5e22a8fc08d5f2 100644
--- a/openair1/PHY/INIT/nr_parms.c
+++ b/openair1/PHY/INIT/nr_parms.c
@@ -273,15 +273,18 @@ int nr_init_frame_parms0(NR_DL_FRAME_PARMS *fp,
   fp->freq_range = (fp->dl_CarrierFreq < 6e9)? nr_FR1 : nr_FR2;
 
   // definition of Lmax according to ts 38.213 section 4.1
-  if (fp->dl_CarrierFreq < 6e9){
-	if(fp->frame_type && (fp->ssb_type==2))
-		fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8;
-	else
-		fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8;
-  }  
-  else
+  if (fp->dl_CarrierFreq < 6e9) {
+    if(fp->frame_type && (fp->ssb_type==2))
+      fp->Lmax = (fp->dl_CarrierFreq < 2.4e9)? 4 : 8;
+    else
+      fp->Lmax = (fp->dl_CarrierFreq < 3e9)? 4 : 8;
+  } else {
     fp->Lmax = 64;
+  }
 
+  fp->N_ssb = 0;
+  for (int p=0; p<fp->Lmax; p++)
+    fp->N_ssb += ((fp->L_ssb >> p) & 0x01);
 
   return 0;
 }
diff --git a/openair1/PHY/MODULATION/beamforming.c b/openair1/PHY/MODULATION/beamforming.c
index ab3271c61c87eed1046b6e2e2725f68d92e2605f..79e220ac37d2ecb8a7ef8873b4355e87c54da666 100644
--- a/openair1/PHY/MODULATION/beamforming.c
+++ b/openair1/PHY/MODULATION/beamforming.c
@@ -50,6 +50,7 @@
 #include "PHY/CODING/lte_interleaver_inline.h"
 #include "PHY/LTE_TRANSPORT/transport_eNB.h"
 #include "modulation_eNB.h"
+#include "nr_modulation.h"
 #include "common/utils/LOG/vcd_signal_dumper.h"
 
 int beam_precoding(int32_t **txdataF,
@@ -135,3 +136,33 @@ int beam_precoding_one_eNB(int32_t **txdataF,
   }
   return 0;
 }
+
+
+int nr_beam_precoding(int32_t **txdataF,
+	              int32_t **txdataF_BF,
+                      NR_DL_FRAME_PARMS *frame_parms,
+	              int32_t ***beam_weights,
+                      int slot,
+                      int symbol,
+                      int aa,
+                      int nb_antenna_ports)
+{
+
+
+  uint8_t p;
+
+  // clear txdata_BF[aa][re] for each call of ue_spec_beamforming
+  memset(&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size],0,sizeof(int32_t)*(frame_parms->ofdm_symbol_size));
+
+  for (p=0; p<nb_antenna_ports; p++) {
+    if ((frame_parms->L_ssb >> p) & 0x01)  {
+      multadd_cpx_vector((int16_t*)&txdataF[p][symbol*frame_parms->ofdm_symbol_size],
+			 (int16_t*)beam_weights[p][aa], 
+			 (int16_t*)&txdataF_BF[aa][symbol*frame_parms->ofdm_symbol_size], 
+			 0, 
+			 frame_parms->ofdm_symbol_size, 
+			 15);
+    }
+  }
+  return 0;
+}
diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h
index 8a6abd5de5a93d5ee650528552c446d89294a201..706b4dc113bbb23b9a7390c820614ee72034cf6c 100644
--- a/openair1/PHY/MODULATION/nr_modulation.h
+++ b/openair1/PHY/MODULATION/nr_modulation.h
@@ -93,4 +93,14 @@ int nr_slot_fep_ul(NR_DL_FRAME_PARMS *frame_parms,
 */
 void nr_dft(int32_t *z,int32_t *d, uint32_t Msc_PUSCH);
 
+int nr_beam_precoding(int32_t **txdataF,
+	              int32_t **txdataF_BF,
+                      NR_DL_FRAME_PARMS *frame_parms,
+	              int32_t ***beam_weights,
+                      int slot,
+                      int symbol,
+                      int aa,
+                      int nb_antenna_ports
+);
+
 #endif
diff --git a/openair1/PHY/MODULATION/ofdm_mod.c b/openair1/PHY/MODULATION/ofdm_mod.c
index b23fd2e2bfb8c9e53c12f43dba024e8756497e61..cbeeca13278f6147c0ce2657f95da5faef7e490d 100644
--- a/openair1/PHY/MODULATION/ofdm_mod.c
+++ b/openair1/PHY/MODULATION/ofdm_mod.c
@@ -86,6 +86,8 @@ void PHY_ofdm_mod(int *input,                       /// pointer to complex input
                  )
 {
 
+  if(nb_symbols == 0) return;
+
   short temp[4096*4] __attribute__((aligned(32)));
   unsigned short i,j;
   short k;
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index 665e9a690cfad491357cc4483347ca785275d8d9..7502d5d4a49d1a38439c75ae07447fec9cd93e9d 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -90,6 +90,7 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t *dlsch,
   uint8_t Qm = rel15->modulation_order;
   uint32_t encoded_length = nb_symbols*Qm;
 
+
   /// CRC, coding, interleaving and rate matching
   AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
   start_meas(dlsch_encoding_stats);
@@ -206,7 +207,6 @@ for (int i=0; i<n_dmrs>>4; i++) {
  printf("PDSCH resource mapping started (start SC %d\tstart symbol %d\tN_PRB %d\tnb_symbols %d)\n",
 	start_sc, rel15->start_symbol, rel15->n_prb, rel15->nb_symbols);
 #endif
-
   for (int ap=0; ap<rel15->nb_layers; ap++) {
 
     // DMRS params for this ap
@@ -221,6 +221,7 @@ ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol);
 #endif
     uint8_t k_prime=0;
     uint16_t m=0, n=0, dmrs_idx=0, k=0;
+    int txdataF_offset = (slot%2)*frame_parms->samples_per_slot_wCP;
     if (dmrs_type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k)
       dmrs_idx = rel15->start_prb*6;
     else
@@ -230,12 +231,12 @@ ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime[0], l0, dmrs_symbol);
       k = start_sc;
       for (int i=0; i<rel15->n_prb*NR_NB_SC_PER_RB; i++) {
         if ((l == dmrs_symbol) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_type))%(frame_parms->ofdm_symbol_size)))) {
-          ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
-          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[dmrs_idx<<1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime[0]]*Wf[k_prime]*amp*mod_dmrs[(dmrs_idx<<1) + 1]) >> 15;
 #ifdef DEBUG_DLSCH_MAPPING
 printf("dmrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
-dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1],
-((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]);
+dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
+((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
 #endif
           dmrs_idx++;
           k_prime++;
@@ -245,12 +246,12 @@ dmrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_
 
         else {
 
-          ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1] = (amp * tx_layers[ap][m<<1]) >> 15;
-          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15;
+          ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
 #ifdef DEBUG_DLSCH_MAPPING
 printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
-m, l, k, ((int16_t*)txdataF[ap])[(l*frame_parms->ofdm_symbol_size + k)<<1],
-((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1]);
+m, l, k, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
+((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
 #endif
           m++;
         }
diff --git a/openair1/PHY/defs_RU.h b/openair1/PHY/defs_RU.h
index 80d63cbdd9e307d56d8108f8cfd519def8b9bc62..0ec04dd5370ac200e8e12f68fc95c88484882d8a 100644
--- a/openair1/PHY/defs_RU.h
+++ b/openair1/PHY/defs_RU.h
@@ -104,6 +104,10 @@ typedef struct {
   /// - first index: tx antenna [0..nb_antennas_tx[
   /// - second index: sample [0..]
   int32_t **txdataF_BF;
+  /// \brief holds the transmit data before beamforming in the frequency domain.
+  /// - first index: tx antenna [0..nb_antennas_tx[
+  /// - second index: sample [0..]
+  int32_t **txdataF;
   /// \brief holds the transmit data before beamforming for epdcch/mpdcch
   /// - first index : tx antenna [0..nb_epdcch_antenna_ports[
   /// - second index: sampl [0..]
@@ -147,6 +151,44 @@ typedef struct {
 } RU_CALIBRATION;
 
 
+typedef struct RU_prec_t_s{
+  /// \internal This variable is protected by \ref mutex_feptx_prec
+  int instance_cnt_feptx_prec;
+  /// pthread struct for RU TX FEP PREC worker thread
+  pthread_t pthread_feptx_prec;
+  /// pthread attributes for worker feptx prec thread
+  pthread_attr_t attr_feptx_prec;
+  /// condition varible for RU TX FEP PREC thread
+  pthread_cond_t cond_feptx_prec;
+  /// mutex for fep PREC TX worker thread
+  pthread_mutex_t mutex_feptx_prec;
+  int symbol;
+  int p;//logical
+  int aa;//physical MAX nb_tx
+  struct RU_t_s *ru;
+  int index;
+} RU_prec_t;
+
+typedef struct RU_feptx_t_s{
+  /// \internal This variable is protected by \ref mutex_feptx_prec
+  int instance_cnt_feptx;
+  /// pthread struct for RU TX FEP PREC worker thread
+  pthread_t pthread_feptx;
+  /// pthread attributes for worker feptx prec thread
+  pthread_attr_t attr_feptx;
+  /// condition varible for RU TX FEP PREC thread
+  pthread_cond_t cond_feptx;
+  /// mutex for fep PREC TX worker thread
+  pthread_mutex_t mutex_feptx;
+  struct RU_t_s *ru;
+  int aa;//physical MAX nb_tx
+  int half_slot;//first or second half of a slot
+  int slot;//current slot
+  int symbol;//current symbol
+  int nb_antenna_ports;//number of logical port
+  int index;
+}RU_feptx_t;
+
 typedef struct RU_proc_t_s {
   /// Pointer to associated RU descriptor
   struct RU_t_s *ru;
@@ -339,8 +381,14 @@ typedef struct RU_proc_t_s {
   int ru_rx_ready;
   int ru_tx_ready;
   int emulate_rf_busy;
-} RU_proc_t;
 
+  /// structure for precoding thread
+  RU_prec_t prec[16];
+  /// structure for feptx thread
+  RU_feptx_t feptx[16];
+  /// mask for checking process finished
+  int feptx_mask;
+} RU_proc_t;
 
 typedef enum {
   LOCAL_RF        =0,
@@ -495,10 +543,16 @@ typedef struct RU_t_s {
   void (*eNB_top)(struct PHY_VARS_eNB_s *eNB, int frame_rx, int subframe_rx, char *string, struct RU_t_s *ru);
   void (*gNB_top)(struct PHY_VARS_gNB_s *gNB, int frame_rx, int slot_rx, char *string, struct RU_t_s *ru);
 
+  /// Timing data copy statistics (TX)
+  time_stats_t txdataF_copy_stats;
+  /// Timing statistics (TX)
+  time_stats_t precoding_stats;
   /// Timing statistics
   time_stats_t ofdm_demod_stats;
   /// Timing statistics (TX)
   time_stats_t ofdm_mod_stats;
+  /// Timing statistics (TX)
+  time_stats_t ofdm_total_stats;
   /// Timing wait statistics
   time_stats_t ofdm_demod_wait_stats;
   /// Timing wakeup statistics
@@ -518,10 +572,12 @@ typedef struct RU_t_s {
   /// RX and TX buffers for precoder output
   RU_COMMON common;
   RU_CALIBRATION calibration;
-  /// beamforming weight vectors per eNB
+  /// beamforming weight list size
+  int nb_bfw;
+  /// beamforming weight list of values
+  int32_t *bw_list[NUMBER_OF_eNB_MAX+1];
+  /// beamforming weight vectors
   int32_t **beam_weights[NUMBER_OF_eNB_MAX+1][15];
-  /// beamforming weight vectors per gNB
-  int32_t **nrbeam_weights[NUMBER_OF_gNB_MAX+1][16];
   /// received frequency-domain signal for PRACH (IF4p5 RRU)
   int16_t **prach_rxsigF;
   /// received frequency-domain signal for PRACH BR (IF4p5 RRU)
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 86d2a7531d2bb340067f643113db21e1fb04d797..048e48ae458569f2e0eb2e5104ed6f930b0892e5 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -319,6 +319,8 @@ typedef struct NR_DL_FRAME_PARMS {
   uint8_t Lmax;
   /// SS block pattern (max 64 ssb, each bit is on/off ssb)
   uint64_t L_ssb;
+  /// Total number of SSB transmitted
+  uint8_t N_ssb;
   /// PBCH polar encoder params
   t_nrPolar_params pbch_polar_params;
 
diff --git a/openair1/SCHED/sched_eNB.h b/openair1/SCHED/sched_eNB.h
index 150b0c194fddaac0326b1b83a5379605c69623a5..e74b9a312fda7bc7ed76430b83a73b4b92d9fa15 100644
--- a/openair1/SCHED/sched_eNB.h
+++ b/openair1/SCHED/sched_eNB.h
@@ -218,6 +218,8 @@ int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subf
 void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset);
 
 void release_rnti_of_phy(module_id_t mod_id);
+
+void ru_fep_full_2thread(RU_t *ru, int subframe);
 /*@}*/
 
 
diff --git a/openair1/SCHED_NR/nr_ru_procedures.c b/openair1/SCHED_NR/nr_ru_procedures.c
index e726bdc71173e2fdf8c4abcddd0a3f14aee1a936..c37db11188aedb8e38c78709e93525ea1219c673 100644
--- a/openair1/SCHED_NR/nr_ru_procedures.c
+++ b/openair1/SCHED_NR/nr_ru_procedures.c
@@ -56,160 +56,236 @@ extern openair0_config_t openair0_cfg[MAX_CARDS];
 
 extern int oai_exit;
 
-void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols) {
+void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa) {
 
   NR_DL_FRAME_PARMS *fp = ru->nr_frame_parms;
 
-  unsigned int aa,slot_offset,slot_offsetF;
+  unsigned int slot_offset,slot_offsetF;
   int slot = tti_tx;
 
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0) , 1 );
+  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0) , 1 );
 
   slot_offset  = slot*fp->samples_per_slot;
   slot_offsetF = first_symbol*fp->ofdm_symbol_size;
 
+
   if (first_symbol>0) slot_offset += (fp->ofdm_symbol_size*first_symbol) + (fp->nb_prefix_samples0) + (fp->nb_prefix_samples*(first_symbol-1));
 
   LOG_D(PHY,"SFN/SF:RU:TX:%d/%d Generating slot %d (first_symbol %d num_symbols %d)\n",ru->proc.frame_tx, ru->proc.tti_tx,slot,first_symbol,num_symbols);
 
-  for (aa=0; aa<ru->nb_tx; aa++) {
-    if (fp->Ncp == 1) {
+  if (fp->Ncp == 1) {
+    PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
+                 (int*)&ru->common.txdata[aa][slot_offset],
+                 fp->ofdm_symbol_size,
+                 num_symbols,
+                 fp->nb_prefix_samples,
+                 CYCLIC_PREFIX);
+  }
+  else {
+    if (first_symbol==0) {
       PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
-		   (int*)&ru->common.txdata[aa][slot_offset],
-		   fp->ofdm_symbol_size,
-		   num_symbols,
-		   fp->nb_prefix_samples,
-		   CYCLIC_PREFIX);
+                   (int*)&ru->common.txdata[aa][slot_offset],
+                   fp->ofdm_symbol_size,
+                   1,
+                   fp->nb_prefix_samples0,
+                   CYCLIC_PREFIX);
+      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size],
+                   (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size],
+                   fp->ofdm_symbol_size,
+                   num_symbols-1,
+                   fp->nb_prefix_samples,
+                   CYCLIC_PREFIX);
     }
     else {
-      if (first_symbol==0) {
-	PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
-		     (int*)&ru->common.txdata[aa][slot_offset],
-                     fp->ofdm_symbol_size,
-                     1,
-                     fp->nb_prefix_samples0,
-                     CYCLIC_PREFIX);
-	PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF+fp->ofdm_symbol_size],
-		     (int*)&ru->common.txdata[aa][slot_offset+fp->nb_prefix_samples0+fp->ofdm_symbol_size],
-                     fp->ofdm_symbol_size,
-                     num_symbols-1,
-                     fp->nb_prefix_samples,
-                     CYCLIC_PREFIX);
-      }
-      else {
-	PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
-		     (int*)&ru->common.txdata[aa][slot_offset],
-                     fp->ofdm_symbol_size,
-                     num_symbols,
-                     fp->nb_prefix_samples,
-                     CYCLIC_PREFIX);
-      }
+      PHY_ofdm_mod(&ru->common.txdataF_BF[aa][slot_offsetF],
+                   (int*)&ru->common.txdata[aa][slot_offset],
+                   fp->ofdm_symbol_size,
+                   num_symbols,
+                   fp->nb_prefix_samples,
+                   CYCLIC_PREFIX);
     }
   }
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0);
+  //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+(first_symbol!=0?1:0), 0);
 }
 
 void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx) {
 
-  NR_DL_FRAME_PARMS *fp=ru->nr_frame_parms;
   nfapi_nr_config_request_t *cfg = &ru->gNB_list[0]->gNB_config;
-  RU_proc_t *proc = &ru->proc;
-  struct timespec wait;
-  int slot = tti_tx;
+  RU_proc_t  *proc  = &ru->proc;
+  RU_feptx_t *feptx = proc->feptx;
 
-  wait.tv_sec=0;
-  wait.tv_nsec=5000000L;
+  PHY_VARS_gNB *gNB;
+  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
 
-  start_meas(&ru->ofdm_mod_stats);
+  int slot = tti_tx;
+  int i    = 0;
+  int j    = 0;
+  int aa   = 0;
+  int ret  = 0;
+  int nb_antenna_ports = fp->N_ssb;
+  int ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
+  int txdataF_offset   = ((tti_tx%2)*fp->samples_per_slot_wCP);
 
   if (nr_slot_select(cfg,slot,frame_tx) == SF_UL) return;
+  for (aa=0; aa<fp->Lmax; aa++) {
+    memset(ru->common.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t));
+  }
 
-  // this copy should be done in the precoding thread (currently inactive)
-  for (int aa=0;aa<ru->nb_tx;aa++)
-    memcpy((void*)ru->common.txdataF_BF[aa],
+  start_meas(&ru->ofdm_total_stats);
 
-	   (void*)ru->gNB_list[0]->common_vars.txdataF[aa], fp->samples_per_slot_wCP*sizeof(int32_t));
+  for(j=0; j<fp->symbols_per_slot; ++j){
 
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 1);
+    start_meas(&ru->txdataF_copy_stats);
+    if (ru->num_gNB == 1){
+      gNB = ru->gNB_list[0];
+      cfg = &gNB->gNB_config;
 
-  if (nr_slot_select(cfg,slot,frame_tx)==SF_DL) {
-    // If this is not an S-tti
-    if (pthread_mutex_timedlock(&proc->mutex_feptx,&wait) != 0) {
-      printf("[RU] ERROR pthread_mutex_lock for feptx thread (IC %d)\n", proc->instance_cnt_feptx);
-      exit_fun( "error locking mutex_feptx" );
-      return;
-    }
-    
-    if (proc->instance_cnt_feptx==0) {
-      printf("[RU] FEPtx thread busy\n");
-      exit_fun("FEPtx thread busy");
-      pthread_mutex_unlock( &proc->mutex_feptx );
-      return;
-    }
-    
-    ++proc->instance_cnt_feptx;
-    // slot to pass to worker thread
-    proc->slot_feptx = slot;
-    pthread_mutex_unlock( &proc->mutex_feptx );
-  
-    
-    if (pthread_cond_signal(&proc->cond_feptx) != 0) {
-      printf("[RU] ERROR pthread_cond_signal for feptx thread\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-      return;
+      for(i=0; i<nb_antenna_ports; ++i){
+        memcpy((void*)&ru->common.txdataF[i][j*fp->ofdm_symbol_size],
+           (void*)&gNB->common_vars.txdataF[i][j*fp->ofdm_symbol_size + txdataF_offset],
+           fp->ofdm_symbol_size*sizeof(int32_t));
+      }
+
+    }//num_gNB == 1
+    stop_meas(&ru->txdataF_copy_stats);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC+j , 0);
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
+
+    if (nr_slot_select(cfg,slot,frame_tx)==SF_DL) {
+      // If this is not an S-tti
+      for(i=0; i<ru->nb_tx; ++i){
+        if(j%2 == 0){
+          while(feptx[i].instance_cnt_feptx != -1){
+            usleep(5);
+          }
+          AssertFatal((ret=pthread_mutex_lock(&feptx[i].mutex_feptx))==0,"mutex_lock return %d\n",ret);
+          feptx[i].aa                      = i;
+          feptx[i].index                   = i;
+          feptx[i].ru                      = ru;
+          feptx[i].symbol                  = j;
+          feptx[i].slot                    = slot;
+          feptx[i].nb_antenna_ports        = nb_antenna_ports;
+          feptx[i].instance_cnt_feptx      = 0;
+          AssertFatal(pthread_cond_signal(&feptx[i].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
+          AssertFatal((ret=pthread_mutex_unlock(&feptx[i].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
+        }
+        else{
+          while(feptx[i+ru->nb_tx].instance_cnt_feptx != -1){
+            usleep(5);
+          }
+          AssertFatal((ret=pthread_mutex_lock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock return %d\n",ret);
+          feptx[i+ru->nb_tx].aa                      = i;
+          feptx[i+ru->nb_tx].index                   = i+ru->nb_tx;
+          feptx[i+ru->nb_tx].ru                      = ru;
+          feptx[i+ru->nb_tx].symbol                  = j;
+          feptx[i+ru->nb_tx].slot                    = slot;
+          feptx[i+ru->nb_tx].nb_antenna_ports        = nb_antenna_ports;
+          feptx[i+ru->nb_tx].instance_cnt_feptx      = 0;
+          AssertFatal(pthread_cond_signal(&feptx[i+ru->nb_tx].cond_feptx) == 0,"ERROR pthread_cond_signal for feptx_ofdm_thread\n");
+          AssertFatal((ret=pthread_mutex_unlock(&feptx[i+ru->nb_tx].mutex_feptx))==0,"mutex_lock returns %d\n",ret);
+        }
+      }
+       
+    }//if == SF_DL
+    else {
+      proc->feptx_mask = ofdm_mask_full;
     }
-    
+  }//j<fp->symbols_per_slot
+
+  // wait all process to finish
+  AssertFatal((ret=pthread_mutex_lock(&proc->mutex_feptx))==0,"mutex_lock return %d\n",ret);
+  while (proc->feptx_mask != ofdm_mask_full) {
+    // most of the time the thread is waiting here
+    // proc->instance_cnt_rxtx is -1
+    pthread_cond_wait(&proc->cond_feptx,&proc->mutex_feptx); // this unlocks mutex_rxtx while waiting and then locks it again
   }
+  proc->feptx_mask = 0;
+  AssertFatal((ret=pthread_mutex_unlock(&proc->mutex_feptx))==0,"mutex_lock return %d\n",ret);
 
-  // call first half-slot in this thread
-  nr_feptx0(ru,slot,0,fp->symbols_per_slot>>1);
-  wait_on_busy_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"NR feptx thread");
-
+  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK, proc->feptx_mask );
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 0 );
 
   //write_output
 
-  stop_meas(&ru->ofdm_mod_stats);
+  stop_meas(&ru->ofdm_total_stats);
 
 }
 
 static void *nr_feptx_thread(void *param) {
 
-  RU_t *ru = (RU_t *)param;
-  RU_proc_t *proc  = &ru->proc;
+  RU_feptx_t *feptx = (RU_feptx_t *)param;
+  RU_t       *ru;
+  int         aa, slot, start, l, nb_antenna_ports, ret;
+  int32_t ***bw;
+  NR_DL_FRAME_PARMS *fp;
+  int ofdm_mask_full;
 
 
   while (!oai_exit) {
 
-    if (wait_on_condition(&proc->mutex_feptx,&proc->cond_feptx,&proc->instance_cnt_feptx,"NR feptx thread")<0) break;
-    int slot=proc->slot_feptx;
-    if (release_thread(&proc->mutex_feptx,&proc->instance_cnt_feptx,"NR feptx thread")<0) break;
+    ret = 0;
+    if (wait_on_condition(&feptx->mutex_feptx,&feptx->cond_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 1 );
+
+    ru    = feptx->ru;
+    slot  = feptx->slot;
+    aa    = feptx->aa;
+    l     = feptx->symbol;
+    fp    = ru->nr_frame_parms;
+    start = feptx->symbol;
+    nb_antenna_ports = feptx->nb_antenna_ports;
+    ofdm_mask_full   = (1<<(ru->nb_tx*2))-1;
+
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1);
+    start_meas(&ru->precoding_stats);
+    if (ru->nb_tx == 1) {
+      AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx);
+      for (int p=0; p<fp->Lmax; p++) {
+        if ((fp->L_ssb >> p) & 0x01){
+          memcpy((void*)&ru->common.txdataF_BF[0][l*fp->ofdm_symbol_size],
+                 (void*)&ru->common.txdataF[p][l*fp->ofdm_symbol_size],
+                 fp->ofdm_symbol_size*sizeof(int32_t));
+        }
+      }
+    }
+    else {
+      bw  = ru->beam_weights[0];
+      nr_beam_precoding(ru->common.txdataF,
+                        ru->common.txdataF_BF,
+                        fp,
+                        bw,
+                        slot,
+                        l,
+                        aa,
+                        nb_antenna_ports);
+    }
+    stop_meas(&ru->precoding_stats);
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 0);
 
-    nr_feptx0(ru,slot,ru->nr_frame_parms->symbols_per_slot>>1,ru->nr_frame_parms->symbols_per_slot>>1);
 
-    if (pthread_cond_signal(&proc->cond_feptx) != 0) {
-      LOG_E(PHY,"[gNB] ERROR pthread_cond_signal for NR feptx thread exit\n");
-      exit_fun( "ERROR pthread_cond_signal" );
-      return NULL;
+    start_meas(&ru->ofdm_mod_stats);
+    nr_feptx0(ru,slot,start,1,aa);
+    stop_meas(&ru->ofdm_mod_stats);
+
+    if (release_thread(&feptx->mutex_feptx,&feptx->instance_cnt_feptx,"NR feptx thread")<0) break;
+
+    if(l >= fp->symbols_per_slot -2){
+      AssertFatal((ret=pthread_mutex_lock(&ru->proc.mutex_feptx))==0,"mutex_lock return %d\n",ret);
+      ru->proc.feptx_mask |= 1<<(feptx->index);
+      if(ru->proc.feptx_mask == ofdm_mask_full)
+        AssertFatal(pthread_cond_signal(&ru->proc.cond_feptx) == 0,"ERROR pthread_cond_signal for precoding and ofdm finish\n");
+      AssertFatal((ret=pthread_mutex_unlock(&ru->proc.mutex_feptx))==0,"mutex_lock returns %d\n",ret);
     }
+    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_RU_TX_OFDM_MASK, ru->proc.feptx_mask );
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM+feptx->index+1 , 0 );
   }
   return(NULL);
 }
 
-void nr_init_feptx_thread(RU_t *ru) {
-
-  RU_proc_t *proc = &ru->proc;
-
-  proc->instance_cnt_feptx         = -1;
-    
-  pthread_mutex_init( &proc->mutex_feptx, NULL);
-  pthread_cond_init( &proc->cond_feptx, NULL);
-
-  threadCreate(&proc->pthread_feptx, nr_feptx_thread, (void*)ru, "feptx", -1, OAI_PRIORITY_RT);
-
-
-}
 
 // is this supposed to generate a slot or a subframe???
 // seems to be hardcoded to numerology 1 (2 slots=1 subframe)
@@ -227,16 +303,12 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_OFDM , 1 );
   start_meas(&ru->ofdm_mod_stats);
 
-  // this copy should be done in the precoding thread (currently inactive)
-  for (int aa=0;aa<ru->nb_tx;aa++)
-    memcpy((void*)ru->common.txdataF_BF[aa],
-	   (void*)ru->gNB_list[0]->common_vars.txdataF[aa], fp->samples_per_slot_wCP*sizeof(int32_t));
-
   if ((nr_slot_select(cfg,slot,frame_tx)==SF_DL)||
       ((nr_slot_select(cfg,slot,frame_tx)==SF_S))) {
+
     //    LOG_D(HW,"Frame %d: Generating slot %d\n",frame,next_slot);
 
-    nr_feptx0(ru,slot,0,fp->symbols_per_slot);
+    nr_feptx0(ru,slot,0,fp->symbols_per_slot,aa);
 
   }
 
@@ -249,6 +321,79 @@ void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx) {
 
 }
 
+void nr_init_feptx_thread(RU_t *ru) {
+
+  RU_proc_t  *proc  = &ru->proc;
+  RU_feptx_t *feptx = proc->feptx;
+  int i = 0;
+
+  for(i=0; i<16; i++){
+    feptx[i].instance_cnt_feptx         = -1;
+    
+    pthread_mutex_init( &feptx[i].mutex_feptx, NULL);
+    pthread_cond_init( &feptx[i].cond_feptx, NULL);
+
+    threadCreate(&feptx[i].pthread_feptx, nr_feptx_thread, (void*)&feptx[i], "feptx", -1, OAI_PRIORITY_RT);
+    LOG_I(PHY,"init feptx thread %d\n", i);
+  }
+
+}
+
+
+void nr_feptx_prec(RU_t *ru,int frame,int tti_tx) {
+
+  int l,aa;
+  PHY_VARS_gNB **gNB_list = ru->gNB_list,*gNB;
+  NR_DL_FRAME_PARMS *fp   = ru->nr_frame_parms;
+  nfapi_nr_config_request_t *cfg;
+  int32_t ***bw;
+  int i=0;
+
+  start_meas(&ru->precoding_stats);
+  if (ru->num_gNB == 1){
+    gNB = gNB_list[0];
+    cfg = &gNB->gNB_config;
+    if (nr_slot_select(cfg,tti_tx,frame) == SF_UL) return;
+
+    for(i=0; i<fp->Lmax; ++i)
+      memcpy((void*)ru->common.txdataF[i],
+           (void*)gNB->common_vars.txdataF[i],
+           fp->samples_per_slot_wCP*sizeof(int32_t));
+
+    if (ru->nb_tx == 1) {
+    
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 1);
+
+      AssertFatal(fp->N_ssb==ru->nb_tx,"Attempting to transmit %d SSB while Nb_tx = %d",fp->N_ssb,ru->nb_tx);
+
+      for (int p=0; p<fp->Lmax; p++) {
+        if ((fp->L_ssb >> p) & 0x01){
+          memcpy((void*)ru->common.txdataF_BF[0],
+                 (void*)ru->common.txdataF[p],
+                 fp->samples_per_slot_wCP*sizeof(int32_t));
+        }
+      }
+
+      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_RU_FEPTX_PREC , 0);
+    }// if (ru->nb_tx == 1)
+    else {
+      bw  = ru->beam_weights[0];
+      for (l=0;l<fp->symbols_per_slot;l++) {
+        for (aa=0;aa<ru->nb_tx;aa++) {
+          nr_beam_precoding(ru->common.txdataF,
+                            ru->common.txdataF_BF,
+                            fp,
+                            bw,
+                            tti_tx,
+                            l,
+                            aa,
+                            fp->Lmax);
+        }// for (aa=0;aa<ru->nb_tx;aa++)
+      }// for (l=0;l<fp->symbols_per_slot;l++)
+    }// if (ru->nb_tx == 1)
+  }// if (ru->num_gNB == 1)
+  stop_meas(&ru->precoding_stats);
+}
 
 void nr_fep0(RU_t *ru, int first_half) {
   
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index caf76528410f6b2bfc1c981c81d3a85dd65537c3..56bec9b4b9524536d86f455420ef09b1cb7af184 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -96,6 +96,7 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
   uint8_t *pbch_pdu=&gNB->pbch_pdu[0];
   uint8_t ssb_index, n_hf;
   int ssb_start_symbol, rel_slot;
+  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
   uint16_t slots_per_hf = fp->slots_per_frame / 2;
 
   n_hf = cfg->sch_config.half_frame_index.value;
@@ -124,19 +125,20 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
 
 	  nr_set_ssb_first_subcarrier(cfg, fp);  // setting the first subcarrier
 	  
+	  // it is supposed that each logical antenna port correspont to a different beam so each SSB is stored into its own index of txdataF
     	  LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol);
-    	  nr_generate_pss(gNB->d_pss, txdataF[0], AMP, ssb_start_symbol, cfg, fp);
-    	  nr_generate_sss(gNB->d_sss, txdataF[0], AMP, ssb_start_symbol, cfg, fp);
+    	  nr_generate_pss(gNB->d_pss, &txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
+    	  nr_generate_sss(gNB->d_sss, &txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
 
 	  if (fp->Lmax == 4)
-	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp);
+	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],&txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
 	  else
-	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp);
+	    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index],&txdataF[ssb_index][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
 
     	  nr_generate_pbch(&gNB->pbch,
                       pbch_pdu,
                       gNB->nr_pbch_interleaver,
-                      txdataF[0],
+                      &txdataF[ssb_index][txdataF_offset],
                       AMP,
                       ssb_start_symbol,
                       n_hf,fp->Lmax,ssb_index,
@@ -155,6 +157,7 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
   nfapi_nr_config_request_t *cfg = &gNB->gNB_config;
   int offset = gNB->CC_id;
   uint8_t ssb_frame_periodicity;  // every how many frames SSB are generated
+  int txdataF_offset = (slot%2)*fp->samples_per_slot_wCP;
 
   if (cfg->sch_config.ssb_periodicity.value < 20)
     ssb_frame_periodicity = 1;
@@ -168,8 +171,8 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
   if (do_meas==1) start_meas(&gNB->phy_proc_tx);
 
   // clear the transmit data array for the current subframe
-  for (aa=0; aa<1/*15*/; aa++) {
-    memset(gNB->common_vars.txdataF[aa],0,fp->samples_per_slot_wCP*sizeof(int32_t));
+  for (aa=0; aa<fp->Lmax; aa++) {
+    memset(&gNB->common_vars.txdataF[aa][txdataF_offset],0,fp->samples_per_slot_wCP*sizeof(int32_t));
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_COMMON_TX,1);
@@ -187,10 +190,12 @@ void phy_procedures_gNB_TX(PHY_VARS_gNB *gNB,
     Calling nr_generate_dci_top (number of DCI %d)\n", gNB->Mod_id, frame, slot, num_dci);
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,1);
+
     nr_generate_dci_top(gNB->pdcch_vars.dci_alloc[i],
-			gNB->nr_gold_pdcch_dmrs[slot],
-			gNB->common_vars.txdataF[0],
-			AMP, *fp, *cfg);
+                        gNB->nr_gold_pdcch_dmrs[slot],
+                        &gNB->common_vars.txdataF[0][txdataF_offset],  // hardcoded to beam 0
+                        AMP, *fp, *cfg);
+
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_ENB_PDCCH_TX,0);
   }
       
diff --git a/openair1/SCHED_NR/sched_nr.h b/openair1/SCHED_NR/sched_nr.h
index 91035854930a04839d6d86ab4453ded98a73a360..5b53aa919a588f0611aea286b66faff06d6aa542 100644
--- a/openair1/SCHED_NR/sched_nr.h
+++ b/openair1/SCHED_NR/sched_nr.h
@@ -42,8 +42,12 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx);
 void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot);
 void nr_feptx_ofdm(RU_t *ru,int frame_tx,int tti_tx);
 void nr_feptx_ofdm_2thread(RU_t *ru,int frame_tx,int tti_tx);
-void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols);
+void nr_feptx0(RU_t *ru,int tti_tx,int first_symbol, int num_symbols, int aa);
 void nr_init_feptx_thread(RU_t *ru);
+void fep_full(RU_t *ru,int slot);
+void nr_feptx_prec(RU_t *ru,int frame_tx,int tti_tx);
+void nr_init_feptx_prec_thread(RU_t *ru);
+void nr_feptx_prec_control(RU_t *ru,int frame,int tti_tx);
 void nr_init_feprx_thread(RU_t *ru);
 void nr_fep_full(RU_t *ru, int slot);
 void nr_fep_full_2thread(RU_t *ru, int slot);
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index ced40c491aecffd2914d460b13101f1d949ca55a..1bd7071b9950cf10d8773905b98401ffbb577827 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -214,7 +214,7 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response)
 
 int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){
 
-  fapi_nr_config_request_t nrUE_config = PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config;
+  fapi_nr_config_request_t *nrUE_config = &PHY_vars_UE_g[phy_config->Mod_id][phy_config->CC_id]->nrUE_config;
   
   if(phy_config != NULL){
     if(phy_config->config_req.config_mask & FAPI_NR_CONFIG_REQUEST_MASK_PBCH){
@@ -230,7 +230,7 @@ int8_t nr_ue_phy_config_request(nr_phy_config_t *phy_config){
       LOG_I(MAC,"half frame bit:              %d\n", phy_config->config_req.pbch_config.half_frame_bit);
       LOG_I(MAC,"-------------------------------\n");
 
-      memcpy(&nrUE_config.pbch_config,&phy_config->config_req.pbch_config,sizeof(fapi_nr_pbch_config_t));
+      memcpy(&nrUE_config->pbch_config,&phy_config->config_req.pbch_config,sizeof(fapi_nr_pbch_config_t));
       
     }
         
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index bf350cea710fa00c995cb3a15e2df0bf9e49f6cc..99c413f376e3e6e8709d8c439109d5f5353a5ddc 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -602,24 +602,26 @@ int main(int argc, char **argv)
     phy_procedures_gNB_TX(gNB,frame,slot,0);
     
     //nr_common_signal_procedures (gNB,frame,subframe);
+    int txdataF_offset = (slot%2) * frame_parms->samples_per_slot_wCP;
 
     LOG_M("txsigF0.m","txsF0", gNB->common_vars.txdataF[0],frame_length_complex_samples_no_prefix,1,1);
     if (gNB->frame_parms.nb_antennas_tx>1)
       LOG_M("txsigF1.m","txsF1", gNB->common_vars.txdataF[1],frame_length_complex_samples_no_prefix,1,1);
 
     int tx_offset = slot*frame_parms->samples_per_slot;
+    printf("samples_per_slot_wCP = %d\n", frame_parms->samples_per_slot_wCP);
 
     //TODO: loop over slots
     for (aa=0; aa<gNB->frame_parms.nb_antennas_tx; aa++) {
       if (gNB_config->subframe_config.dl_cyclic_prefix_type.value == 1) {
-	PHY_ofdm_mod(gNB->common_vars.txdataF[aa],
+	PHY_ofdm_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
 		     &txdata[aa][tx_offset],
 		     frame_parms->ofdm_symbol_size,
 		     12,
 		     frame_parms->nb_prefix_samples,
 		     CYCLIC_PREFIX);
       } else {
-	nr_normal_prefix_mod(gNB->common_vars.txdataF[aa],
+	nr_normal_prefix_mod(&gNB->common_vars.txdataF[aa][txdataF_offset],
 			     &txdata[aa][tx_offset],
 			     14,
 			     frame_parms);
diff --git a/openair2/ENB_APP/enb_paramdef.h b/openair2/ENB_APP/enb_paramdef.h
index 106a9f297ee92f9516985093441ee2d5e079eaf9..0fedc04abd8404a547869093e28e342adcc1ac24 100644
--- a/openair2/ENB_APP/enb_paramdef.h
+++ b/openair2/ENB_APP/enb_paramdef.h
@@ -93,6 +93,7 @@ typedef enum {
 #define CONFIG_STRING_RU_SF_EXTENSION             "sf_extension"
 #define CONFIG_STRING_RU_END_OF_BURST_DELAY       "end_of_burst_delay"
 #define CONFIG_STRING_RU_OTA_SYNC_ENABLE          "ota_sync_enabled"
+#define CONFIG_STRING_RU_BF_WEIGHTS_LIST          "bf_weights"
 
 #define RU_LOCAL_IF_NAME_IDX          0
 #define RU_LOCAL_ADDRESS_IDX          1
@@ -118,23 +119,22 @@ typedef enum {
 #define RU_SF_EXTENSION_IDX           21
 #define RU_END_OF_BURST_DELAY_IDX     22
 #define RU_OTA_SYNC_ENABLE_IDX        23
-
-
+#define RU_BF_WEIGHTS_LIST_IDX        24
 
 /*-----------------------------------------------------------------------------------------------------------------------------------------*/
 /*                                            RU configuration parameters                                                                  */
 /*   optname                                   helpstr   paramflags    XXXptr          defXXXval                   type      numelt        */
 /*-----------------------------------------------------------------------------------------------------------------------------------------*/
 #define RUPARAMS_DESC { \
-    {CONFIG_STRING_RU_LOCAL_IF_NAME,               NULL,       0,       strptr:NULL,     defstrval:"lo",          TYPE_STRING,    0}, \
-    {CONFIG_STRING_RU_LOCAL_ADDRESS,               NULL,       0,       strptr:NULL,     defstrval:"127.0.0.2",   TYPE_STRING,    0}, \
-    {CONFIG_STRING_RU_REMOTE_ADDRESS,              NULL,       0,       strptr:NULL,     defstrval:"127.0.0.1",   TYPE_STRING,    0}, \
+    {CONFIG_STRING_RU_LOCAL_IF_NAME,               NULL,       0,       strptr:NULL,     defstrval:"lo",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_LOCAL_ADDRESS,               NULL,       0,       strptr:NULL,     defstrval:"127.0.0.2",   TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_REMOTE_ADDRESS,              NULL,       0,       strptr:NULL,     defstrval:"127.0.0.1",   TYPE_STRING,      0}, \
     {CONFIG_STRING_RU_LOCAL_PORTC,                 NULL,       0,       uptr:NULL,       defuintval:50000,        TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_REMOTE_PORTC,                NULL,       0,       uptr:NULL,       defuintval:50000,        TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_LOCAL_PORTD,                 NULL,       0,       uptr:NULL,       defuintval:50001,        TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_REMOTE_PORTD,                NULL,       0,       uptr:NULL,       defuintval:50001,        TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_TRANSPORT_PREFERENCE,        NULL,       0,       strptr:NULL,     defstrval:"udp_if5",     TYPE_STRING,    0}, \
-    {CONFIG_STRING_RU_LOCAL_RF,                    NULL,       0,       strptr:NULL,     defstrval:"yes",         TYPE_STRING,    0}, \
+    {CONFIG_STRING_RU_TRANSPORT_PREFERENCE,        NULL,       0,       strptr:NULL,     defstrval:"udp_if5",     TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_LOCAL_RF,                    NULL,       0,       strptr:NULL,     defstrval:"yes",         TYPE_STRING,      0}, \
     {CONFIG_STRING_RU_NB_TX,                       NULL,       0,       uptr:NULL,       defuintval:1,            TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_NB_RX,                       NULL,       0,       uptr:NULL,       defuintval:1,            TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_MAX_RS_EPRE,                 NULL,       0,       iptr:NULL,       defintval:-29,           TYPE_INT,         0}, \
@@ -143,13 +143,14 @@ typedef enum {
     {CONFIG_STRING_RU_ENB_LIST,                    NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
     {CONFIG_STRING_RU_ATT_TX,                      NULL,       0,       uptr:NULL,       defintval:0,             TYPE_UINT,        0}, \
     {CONFIG_STRING_RU_ATT_RX,                      NULL,       0,       uptr:NULL,       defintval:0,             TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_IS_SLAVE,                      NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
-    {CONFIG_STRING_RU_NBIOTRRC_LIST,                 NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
+    {CONFIG_STRING_RU_IS_SLAVE,                    NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_NBIOTRRC_LIST,               NULL,       0,       uptr:NULL,       defintarrayval:DEFENBS,  TYPE_INTARRAY,    1}, \
     {CONFIG_STRING_RU_SDR_ADDRS,                   NULL,       0,       strptr:NULL,     defstrval:"type=b200",   TYPE_STRING,      0}, \
     {CONFIG_STRING_RU_SDR_CLK_SRC,                 NULL,       0,       strptr:NULL,     defstrval:"internal",    TYPE_STRING,      0}, \
-    {CONFIG_STRING_RU_SF_EXTENSION,                  NULL,       0,       uptr:NULL,       defuintval:312,          TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_END_OF_BURST_DELAY,            NULL,       0,       uptr:NULL,       defuintval:400,          TYPE_UINT,        0}, \
-    {CONFIG_STRING_RU_OTA_SYNC_ENABLE,               NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_SF_EXTENSION,                NULL,       0,       uptr:NULL,       defuintval:312,          TYPE_UINT,        0}, \
+    {CONFIG_STRING_RU_END_OF_BURST_DELAY,          NULL,       0,       uptr:NULL,       defuintval:400,          TYPE_UINT,        0}, \
+    {CONFIG_STRING_RU_OTA_SYNC_ENABLE,             NULL,       0,       strptr:NULL,     defstrval:"no",          TYPE_STRING,      0}, \
+    {CONFIG_STRING_RU_BF_WEIGHTS_LIST,             NULL,       0,       iptr:NULL,       defintarrayval:DEFBFW,   TYPE_INTARRAY,    0}, \
   }
 
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index 1ca6f2d7ec6e3feb4e52cbd394fca6293bac1e25..8a55c61cd7f5d22a35dcd629d2e1b719a9ae07d1 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -67,83 +67,9 @@ typedef enum {
 
 #define CONFIG_STRING_ACTIVE_RUS                  "Active_RUs"
 /*------------------------------------------------------------------------------------------------------------------------------------------*/
-/*    RUs  configuration section name */
-#define CONFIG_STRING_RU_LIST                     "RUs"
-#define CONFIG_STRING_RU_CONFIG                   "ru_config"
-
-/*    RUs configuration parameters name   */
-#define CONFIG_STRING_RU_LOCAL_IF_NAME            "local_if_name"
-#define CONFIG_STRING_RU_LOCAL_ADDRESS            "local_address"
-#define CONFIG_STRING_RU_REMOTE_ADDRESS           "remote_address"
-#define CONFIG_STRING_RU_LOCAL_PORTC              "local_portc"
-#define CONFIG_STRING_RU_REMOTE_PORTC             "remote_portc"
-#define CONFIG_STRING_RU_LOCAL_PORTD              "local_portd"
-#define CONFIG_STRING_RU_REMOTE_PORTD             "remote_portd"
-#define CONFIG_STRING_RU_LOCAL_RF                 "local_rf"
-#define CONFIG_STRING_RU_TRANSPORT_PREFERENCE     "tr_preference"
-#define CONFIG_STRING_RU_BAND_LIST                "bands"
-#define CONFIG_STRING_RU_GNB_LIST                 "gNB_instances"
-#define CONFIG_STRING_RU_NB_TX                    "nb_tx"
-#define CONFIG_STRING_RU_NB_RX                    "nb_rx"
-#define CONFIG_STRING_RU_ATT_TX                   "att_tx"
-#define CONFIG_STRING_RU_ATT_RX                   "att_rx"
-#define CONFIG_STRING_RU_MAX_RS_EPRE              "max_pdschReferenceSignalPower"
-#define CONFIG_STRING_RU_MAX_RXGAIN               "max_rxgain"
-#define CONFIG_STRING_RU_IF_COMPRESSION           "if_compression"
-#define CONFIG_STRING_RU_NBIOTRRC_LIST            "NbIoT_RRC_instances"
-#define CONFIG_STRING_RU_SDR_ADDRS                "sdr_addrs"
-#define CONFIG_STRING_RU_SDR_CLK_SRC              "clock_src"
-
-#define RU_LOCAL_IF_NAME_IDX          0
-#define RU_LOCAL_ADDRESS_IDX          1
-#define RU_REMOTE_ADDRESS_IDX         2
-#define RU_LOCAL_PORTC_IDX            3
-#define RU_REMOTE_PORTC_IDX           4
-#define RU_LOCAL_PORTD_IDX            5
-#define RU_REMOTE_PORTD_IDX           6
-#define RU_TRANSPORT_PREFERENCE_IDX   7
-#define RU_LOCAL_RF_IDX               8
-#define RU_NB_TX_IDX                  9
-#define RU_NB_RX_IDX                  10
-#define RU_MAX_RS_EPRE_IDX            11
-#define RU_MAX_RXGAIN_IDX             12
-#define RU_BAND_LIST_IDX              13
-#define RU_GNB_LIST_IDX               14
-#define RU_ATT_TX_IDX                 15
-#define RU_ATT_RX_IDX                 16
-#define RU_IS_SLAVE_IDX               17
-#define RU_NBIOTRRC_LIST_IDX          18
-#define RU_SDR_ADDRS                  19
-#define RU_SDR_CLK_SRC                20
-#define RU_SF_EXTENSION_IDX           21
-#define RU_END_OF_BURST_DELAY_IDX     22
 
-
-
-/*-----------------------------------------------------------------------------------------------------------------------------------------*/
-/*                                            RU configuration parameters                                                                  */
-/*   optname                                   helpstr   paramflags    XXXptr          defXXXval                 type           numelt     */
-/*-----------------------------------------------------------------------------------------------------------------------------------------*/
-#define GNBRUPARAMS_DESC { \
-{CONFIG_STRING_RU_LOCAL_IF_NAME,            	 NULL,       0,       strptr:NULL,     defstrval:"lo",  	      TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_LOCAL_ADDRESS,            	 NULL,       0,       strptr:NULL,     defstrval:"127.0.0.2",     TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_REMOTE_ADDRESS,           	 NULL,       0,       strptr:NULL,     defstrval:"127.0.0.1",	  TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_LOCAL_PORTC,              	 NULL,       0,       uptr:NULL,       defuintval:50000,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_REMOTE_PORTC,             	 NULL,       0,       uptr:NULL,       defuintval:50000,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_LOCAL_PORTD,              	 NULL,       0,       uptr:NULL,       defuintval:50001,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_REMOTE_PORTD,             	 NULL,       0,       uptr:NULL,       defuintval:50001,          TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_TRANSPORT_PREFERENCE,     	 NULL,       0,       strptr:NULL,     defstrval:"udp_if5",       TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_LOCAL_RF,                 	 NULL,       0,       strptr:NULL,     defstrval:"yes",           TYPE_STRING,      0}, \
-{CONFIG_STRING_RU_NB_TX,                    	 NULL,       0,       uptr:NULL,       defuintval:1,              TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_NB_RX,                    	 NULL,       0,       uptr:NULL,       defuintval:1,              TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_MAX_RS_EPRE,              	 NULL,       0,       iptr:NULL,       defintval:-29,             TYPE_INT,         0}, \
-{CONFIG_STRING_RU_MAX_RXGAIN,               	 NULL,       0,       iptr:NULL,       defintval:120,             TYPE_INT,         0}, \
-{CONFIG_STRING_RU_BAND_LIST,                	 NULL,       0,       uptr:NULL,       defintarrayval:DEFNRBANDS, TYPE_INTARRAY,    1}, \
-{CONFIG_STRING_RU_GNB_LIST,                 	 NULL,       0,       uptr:NULL,       defintarrayval:DEFGNBS,    TYPE_INTARRAY,    1}, \
-{CONFIG_STRING_RU_ATT_TX,                   	 NULL,       0,       uptr:NULL,       defintval:0,               TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_ATT_RX,                   	 NULL,       0,       uptr:NULL,       defintval:0,               TYPE_UINT,        0}, \
-{CONFIG_STRING_RU_NBIOTRRC_LIST,                 NULL,       0,       uptr:NULL,       defintarrayval:DEFGNBS,    TYPE_INTARRAY,    1}, \
-}
+/*    RUs  configuration for gNB is the same for eNB */
+/*    Check file enb_paramdef.h */
 
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
 /*---------------------------------------------------------------------------------------------------------------------------------------*/
diff --git a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
index 10e591294b727eedac9e57b1e823e19a86cc8d3c..8cfa398615b3e27323d6cee4ae6ec87f64cf79f9 100644
--- a/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
+++ b/targets/ARCH/USRP/USERSPACE/LIB/usrp_lib.cpp
@@ -455,14 +455,14 @@ static int trx_usrp_write(openair0_device *device, openair0_timestamp timestamp,
 #if defined(__x86_64) || defined(__i386__)
   #ifdef __AVX2__
       nsamps2 = (nsamps+7)>>3;
-      __m256i buff_tx[2][nsamps2];
+      __m256i buff_tx[8][nsamps2];
   #else
     nsamps2 = (nsamps+3)>>2;
-    __m128i buff_tx[2][nsamps2];
+    __m128i buff_tx[8][nsamps2];
   #endif
 #elif defined(__arm__)
     nsamps2 = (nsamps+3)>>2;
-    int16x8_t buff_tx[2][nsamps2];
+    int16x8_t buff_tx[8][nsamps2];
 #else
     #error Unsupported CPU architecture, USRP device cannot be built
 #endif
@@ -566,14 +566,14 @@ static int trx_usrp_read(openair0_device *device, openair0_timestamp *ptimestamp
 #if defined(__x86_64) || defined(__i386__)
 #ifdef __AVX2__
     nsamps2 = (nsamps+7)>>3;
-    __m256i buff_tmp[2][nsamps2];
+    __m256i buff_tmp[8][nsamps2];
 #else
     nsamps2 = (nsamps+3)>>2;
-    __m128i buff_tmp[2][nsamps2];
+    __m128i buff_tmp[8][nsamps2];
 #endif
 #elif defined(__arm__)
     nsamps2 = (nsamps+3)>>2;
-    int16x8_t buff_tmp[2][nsamps2];
+    int16x8_t buff_tmp[8][nsamps2];
 #endif
 
     if (device->type == USRP_B200_DEV) {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
index 2a2ebd45fda3da67c1ea99d875f7d44b907aa38a..044c044fd68d41c7e8f2fac60b1fb194d8f7e187 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -246,15 +246,16 @@ L1s = (
 RUs = (
     {		  
        local_rf       = "yes"
-         nb_tx          = 1
-         nb_rx          = 1
-         att_tx         = 0
+         nb_tx          = 1; 
+         nb_rx          = 1; 
+         att_tx         = 0; 
          att_rx         = 0;
          bands          = [7];
          max_pdschReferenceSignalPower = -27;
          max_rxgain                    = 114;
          eNB_instances  = [0];
-	 sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,mgmt_addr=192.168.10.2,clock_source=external,time_source=external";
+
+	 sdr_addrs = "addr=192.168.10.2,second_addr=192.168.20.2,clock_source=external,time_source=external";
 
     }
 );  
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
index a11bf9d515bfa11106f25ce5a2b2d3ae9652482e..420188b80e8d4d280263e0b52b7d54bd4b76813a 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
@@ -70,7 +70,7 @@ gNBs =
       UL_BWP_prefix_type                                            = "NORMAL";
       UL_timeAlignmentTimerCommon                                   = "infinity";
       ServingCellConfigCommon_n_TimingAdvanceOffset                 = "n0"
-      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x01;
+      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x01;#####
       ServingCellConfigCommon_ssb_periodicityServingCell            = 10;
       ServingCellConfigCommon_dmrs_TypeA_Position                   = 2;
       NIA_SubcarrierSpacing                                         = "kHz15"; 
@@ -246,7 +246,7 @@ L1s = (
 RUs = (
     {		  
        local_rf       = "yes"
-         nb_tx          = 1
+         nb_tx          = 1 
          nb_rx          = 1
          att_tx         = 0
          att_rx         = 0;
@@ -264,7 +264,7 @@ THREAD_STRUCT = (
     #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
     parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
     #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
-    worker_config      = "WORKER_DISABLE";
+    worker_config      = "WORKER_ENABLE";
   }
 );
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
index 73f2214baf684154dccf9d075de50d0165934f62..691224b8835a9c3da20dd71b8643477a90c95267 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
@@ -70,7 +70,7 @@ gNBs =
       UL_BWP_prefix_type                                            = "NORMAL";
       UL_timeAlignmentTimerCommon                                   = "infinity";
       ServingCellConfigCommon_n_TimingAdvanceOffset                 = "n0"
-      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x01;
+      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x0ff;
       ServingCellConfigCommon_ssb_periodicityServingCell            = 10;
       ServingCellConfigCommon_dmrs_TypeA_Position                   = 2;
       NIA_SubcarrierSpacing                                         = "kHz15"; 
@@ -246,7 +246,7 @@ L1s = (
 RUs = (
     {		  
        local_rf       = "yes"
-         nb_tx          = 1
+         nb_tx          = 8
          nb_rx          = 1
          att_tx         = 0
          att_rx         = 0;
@@ -264,7 +264,7 @@ THREAD_STRUCT = (
     #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
     parallel_config    = "PARALLEL_SINGLE_THREAD";
     #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
-    worker_config      = "WORKER_DISABLE";
+    worker_config      = "WORKER_ENABLE";
   }
 );
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.beamw.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.beamw.usrpn300.conf
new file mode 100644
index 0000000000000000000000000000000000000000..a9d251efa2dc5d826ad34bd00d81d333ea3ce0b7
--- /dev/null
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.beamw.usrpn300.conf
@@ -0,0 +1,291 @@
+Active_gNBs = ( "gNB-Eurecom-5GNRBox");
+# Asn1_verbosity, choice in: none, info, annoying
+Asn1_verbosity = "none";
+
+gNBs =
+(
+ {
+    ////////// Identification parameters:
+    gNB_ID    =  0xe00;
+
+    cell_type =  "CELL_MACRO_GNB";
+
+    gNB_name  =  "gNB-Eurecom-5GNRBox";
+
+    // Tracking area code, 0x0000 and 0xfffe are reserved values
+    tracking_area_code  =  1;
+
+    plmn_list = ({mcc = 208; mnc = 93; mnc_length = 2;});	 
+
+    tr_s_preference     = "local_mac"
+
+    ////////// Physical parameters:
+
+    component_carriers = (
+      {
+      node_function                                                 = "3GPP_gNODEB";
+      node_timing                                                   = "synch_to_ext_device";
+      node_synch_ref                                                = 0;
+      frame_type                                                    = "TDD";
+      DL_prefix_type                                                = "NORMAL";
+      UL_prefix_type                                                = "NORMAL";
+      eutra_band                                                    = 78;
+      downlink_frequency                                            = 3510000000L;
+      uplink_frequency_offset                                       = -120000000;
+      Nid_cell                                                      = 0;
+      N_RB_DL                                                       = 217;
+      nb_antenna_ports                                              = 1;
+      nb_antennas_tx                                                = 1;
+      nb_antennas_rx                                                = 1;
+      tx_gain                                                       = 90;
+      rx_gain                                                       = 125;
+      MIB_subCarrierSpacingCommon                                   = 30;
+      MIB_ssb_SubcarrierOffset                                      = 0;
+      MIB_dmrs_TypeA_Position                                       = 2;
+      pdcch_ConfigSIB1                                              = 0;
+      SIB1_frequencyOffsetSSB                                       = "khz5";
+      SIB1_ssb_PeriodicityServingCell                               = 5;
+      SIB1_ss_PBCH_BlockPower                                       = -60;
+      absoluteFrequencySSB                                          = 0;
+      DL_FreqBandIndicatorNR                                        = 15;
+      DL_absoluteFrequencyPointA                                    = 15;
+      DL_offsetToCarrier                                            = 15;
+      DL_SCS_SubcarrierSpacing                                      = "kHz30";
+      DL_SCS_SpecificCarrier_k0                                     = 0;
+      DL_carrierBandwidth                                           = 15;
+      DL_locationAndBandwidth                                       = 15;
+      DL_BWP_SubcarrierSpacing                                      = "kHz30";
+      DL_BWP_prefix_type                                            = "NORMAL";
+      UL_FreqBandIndicatorNR                                        = 15;
+      UL_absoluteFrequencyPointA                                    = 13;
+      UL_additionalSpectrumEmission                                 = 3;
+      UL_p_Max                                                      = -1;
+      UL_frequencyShift7p5khz                                       = "TRUE";
+      UL_offsetToCarrier                                            = 10;
+      UL_SCS_SubcarrierSpacing                                      = "kHz30";
+      UL_SCS_SpecificCarrier_k0                                     = 0;
+      UL_carrierBandwidth                                           = 15;
+      UL_locationAndBandwidth                                       = 15;
+      UL_BWP_SubcarrierSpacing                                      = "kHz30";
+      UL_BWP_prefix_type                                            = "NORMAL";
+      UL_timeAlignmentTimerCommon                                   = "infinity";
+      ServingCellConfigCommon_n_TimingAdvanceOffset                 = "n0"
+      ServingCellConfigCommon_ssb_PositionsInBurst_PR               = 0x03;
+      ServingCellConfigCommon_ssb_periodicityServingCell            = 10;
+      ServingCellConfigCommon_dmrs_TypeA_Position                   = 2;
+      NIA_SubcarrierSpacing                                         = "kHz15"; 
+      ServingCellConfigCommon_ss_PBCH_BlockPower                    = -60;
+      referenceSubcarrierSpacing                                    = "kHz15";
+      dl_UL_TransmissionPeriodicity                                 = "ms0p5";
+      nrofDownlinkSlots                                             = 10;
+      nrofDownlinkSymbols                                           = 10;
+      nrofUplinkSlots                                               = 10;
+      nrofUplinkSymbols                                             = 10;
+      rach_totalNumberOfRA_Preambles                                = 63;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_choice         = "oneEighth";
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneEighth      = 4;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneFourth      = 8;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_oneHalf        = 16;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_one            = 24;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_two            = 32;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_four           = 8;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_eight          = 4;
+      rach_ssb_perRACH_OccasionAndCB_PreamblesPerSSB_sixteen        = 2;
+      rach_groupBconfigured                                         = "ENABLE";
+      rach_ra_Msg3SizeGroupA                                        = 56;
+      rach_messagePowerOffsetGroupB                                 = "dB0";
+      rach_numberOfRA_PreamblesGroupA                               = 32;
+      rach_ra_ContentionResolutionTimer                             = 8;
+      rsrp_ThresholdSSB                                             = 64;
+      rsrp_ThresholdSSB_SUL                                         = 64;
+      prach_RootSequenceIndex_choice                                = "l839";
+      prach_RootSequenceIndex_l839                                  = 0;
+      prach_RootSequenceIndex_l139                                  = 0;
+      prach_msg1_SubcarrierSpacing                                  = "kHz30";
+      restrictedSetConfig                                           = "unrestrictedSet";
+      msg3_transformPrecoding                                       = "ENABLE";
+      prach_ConfigurationIndex                                      = 10;
+      prach_msg1_FDM                                                = "one";
+      prach_msg1_FrequencyStart                                     = 10;
+      zeroCorrelationZoneConfig                                     = 10;
+      preambleReceivedTargetPower                                   = -150;
+      preambleTransMax                                              = 6;
+      powerRampingStep                                              = "dB0";
+      ra_ResponseWindow                                             = 8;
+      groupHoppingEnabledTransformPrecoding                         = "ENABLE";
+      msg3_DeltaPreamble                                            = 0;
+      p0_NominalWithGrant                                           = 0;
+      PUSCH_TimeDomainResourceAllocation_k2                         = 0;
+      PUSCH_TimeDomainResourceAllocation_mappingType                = "typeA";
+      PUSCH_TimeDomainResourceAllocation_startSymbolAndLength       = 0;
+      pucch_ResourceCommon                                          = 0;
+      pucch_GroupHopping                                            = "neither";
+      hoppingId                                                     = 0;
+      p0_nominal                                                    = -30;
+      PDSCH_TimeDomainResourceAllocation_k0                         = 2;
+      PDSCH_TimeDomainResourceAllocation_mappingType                = "typeA";
+      PDSCH_TimeDomainResourceAllocation_startSymbolAndLength       = 0;
+      rateMatchPatternId                                            = 0;
+      RateMatchPattern_patternType                                  = "bitmaps";
+      symbolsInResourceBlock                                        = "oneSlot";
+      periodicityAndPattern                                         = 2;
+      RateMatchPattern_controlResourceSet                           = 5;
+      RateMatchPattern_subcarrierSpacing                            = "kHz30";
+      RateMatchPattern_mode                                         = "dynamic";
+      controlResourceSetZero                                        = 0;
+      searchSpaceZero                                               = 0;
+      searchSpaceSIB1                                               = 10;
+      searchSpaceOtherSystemInformation                             = 10;
+      pagingSearchSpace                                             = 10;
+      ra_SearchSpace                                                = 10;
+      PDCCH_common_controlResourceSetId                             = 5;
+      PDCCH_common_ControlResourceSet_duration                      = 2;
+      PDCCH_cce_REG_MappingType                                     = "nonInterleaved";
+      PDCCH_reg_BundleSize                                          = 3;
+      PDCCH_interleaverSize                                         = 3;
+      PDCCH_shiftIndex                                              = 10;  
+      PDCCH_precoderGranularity                                     = "sameAsREG-bundle";
+      PDCCH_TCI_StateId                                             = 32;
+      tci_PresentInDCI                                              = "ENABLE";
+      PDCCH_DMRS_ScramblingID                                       = 0;
+      SearchSpaceId                                                 = 10;
+      commonSearchSpaces_controlResourceSetId                       = 5;
+      SearchSpace_monitoringSlotPeriodicityAndOffset_choice         = "sl1";
+      SearchSpace_monitoringSlotPeriodicityAndOffset_value          = 0;
+      SearchSpace_duration                                          = 2;
+      SearchSpace_nrofCandidates_aggregationLevel1                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel2                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel4                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel8                  = 0;
+      SearchSpace_nrofCandidates_aggregationLevel16                 = 0;
+      SearchSpace_searchSpaceType                                   = "common";
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel1     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel2     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel4     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel8     = 1;
+      Common_dci_Format2_0_nrofCandidates_SFI_aggregationLevel16    = 1; 
+      Common_dci_Format2_3_monitoringPeriodicity                    = 1;
+      Common_dci_Format2_3_nrofPDCCH_Candidates                     = 1;
+      ue_Specific__dci_Formats                                      = "formats0-0-And-1-0";
+      RateMatchPatternLTE_CRS_carrierFreqDL                         = 6;
+      RateMatchPatternLTE_CRS_carrierBandwidthDL                    = 6;
+      RateMatchPatternLTE_CRS_nrofCRS_Ports                         = 1;
+      RateMatchPatternLTE_CRS_v_Shift                               = 0;
+      RateMatchPatternLTE_CRS_radioframeAllocationPeriod            = 1;
+      RateMatchPatternLTE_CRS_radioframeAllocationOffset            = 0;
+      RateMatchPatternLTE_CRS_subframeAllocation_choice             = "oneFrame";
+      }
+    );
+
+
+    srb1_parameters :
+    {
+        # timer_poll_retransmit = (ms) [5, 10, 15, 20,... 250, 300, 350, ... 500]
+        timer_poll_retransmit    = 80;
+
+        # timer_reordering = (ms) [0,5, ... 100, 110, 120, ... ,200]
+        timer_reordering         = 35;
+
+        # timer_reordering = (ms) [0,5, ... 250, 300, 350, ... ,500]
+        timer_status_prohibit    = 0;
+
+        # poll_pdu = [4, 8, 16, 32 , 64, 128, 256, infinity(>10000)]
+        poll_pdu                 =  4;
+
+        # poll_byte = (kB) [25,50,75,100,125,250,375,500,750,1000,1250,1500,2000,3000,infinity(>10000)]
+        poll_byte                =  99999;
+
+        # max_retx_threshold = [1, 2, 3, 4 , 6, 8, 16, 32]
+        max_retx_threshold       =  4;
+    }
+
+    # ------- SCTP definitions
+    SCTP :
+    {
+        # Number of streams to use in input/output
+        SCTP_INSTREAMS  = 2;
+        SCTP_OUTSTREAMS = 2;
+    };
+
+
+    ////////// MME parameters:
+    mme_ip_address      = ( { ipv4       = "192.168.12.26";
+                              ipv6       = "192:168:30::17";
+                              active     = "yes";
+                              preference = "ipv4";
+                            }
+                          );
+
+    NETWORK_INTERFACES :
+    {
+
+        GNB_INTERFACE_NAME_FOR_S1_MME            = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1_MME              = "192.168.12.111/24";
+        GNB_INTERFACE_NAME_FOR_S1U               = "eth0";
+        GNB_IPV4_ADDRESS_FOR_S1U                 = "192.168.12.111/24";
+        GNB_PORT_FOR_S1U                         = 2152; # Spec 2152
+    };
+  }
+);
+
+MACRLCs = (
+	{
+	num_cc = 1;
+	tr_s_preference = "local_L1";
+	tr_n_preference = "local_RRC";
+        }  
+);
+
+L1s = (
+    	{
+	num_cc = 1;
+	tr_n_preference = "local_mac";
+        }  
+);
+
+RUs = (
+    {		  
+       local_rf       = "yes"
+         nb_tx          = 2
+         nb_rx          = 1
+         att_tx         = 0
+         att_rx         = 0;
+         bands          = [7];
+         max_pdschReferenceSignalPower = -27;
+         max_rxgain                    = 114;
+         eNB_instances  = [0];
+	 sdr_addrs = "addr=192.168.10.2";
+         # beamforming weights for static beams each of them is a int32 composed by two int16 representing imaginary and real part of the weight
+         # weights are input in an array, starting with the weights associated to first logical beam for all nb_tx , than the weights for 2nd logical beam and so on
+         # the list size is (nb_tx) X (number of logical beams) 
+   	 bf_weights = [0x00007fff, 0x00000000, 0x00000000, 0x00007fff];
+    }
+);  
+
+THREAD_STRUCT = (
+  {
+    #three config for level of parallelism "PARALLEL_SINGLE_THREAD", "PARALLEL_RU_L1_SPLIT", or "PARALLEL_RU_L1_TRX_SPLIT"
+    parallel_config    = "PARALLEL_RU_L1_TRX_SPLIT";
+    #two option for worker "WORKER_DISABLE" or "WORKER_ENABLE"
+    worker_config      = "WORKER_ENABLE";
+  }
+);
+
+     log_config :
+     {
+       global_log_level                      ="info";
+       global_log_verbosity                  ="medium";
+       hw_log_level                          ="info";
+       hw_log_verbosity                      ="medium";
+       phy_log_level                         ="info";
+       phy_log_verbosity                     ="medium";
+       mac_log_level                         ="info";
+       mac_log_verbosity                     ="high";
+       rlc_log_level                         ="info";
+       rlc_log_verbosity                     ="medium";
+       pdcp_log_level                        ="info";
+       pdcp_log_verbosity                    ="medium";
+       rrc_log_level                         ="info";
+       rrc_log_verbosity                     ="medium";
+    };
+
diff --git a/targets/RT/USER/gNB_usrp.gtkw b/targets/RT/USER/gNB_usrp.gtkw
index 069d1765a95358b9f4875addcac6bb9277a712e4..416dd3b62ba48806e7df7fdf43f1dd6d265ae09d 100644
--- a/targets/RT/USER/gNB_usrp.gtkw
+++ b/targets/RT/USER/gNB_usrp.gtkw
@@ -1,19 +1,19 @@
 [*]
-[*] GTKWave Analyzer v3.3.61 (w)1999-2014 BSI
-[*] Sat May 18 17:25:11 2019
+[*] GTKWave Analyzer v3.3.58 (w)1999-2014 BSI
+[*] Fri Sep  6 15:01:30 2019
 [*]
-[dumpfile] "/tmp/openair_dump_gNB40.vcd"
-[dumpfile_mtime] "Sat May 18 17:11:31 2019"
-[dumpfile_size] 53148516
-[savefile] "/home/caracal/raymond/openairinterface5g/targets/RT/USER/gNB_usrp.gtkw"
-[timestart] 11552775390
-[size] 1840 795
+[dumpfile] "/tmp/gNB_prec.vcd"
+[dumpfile_mtime] "Fri Sep  6 14:59:50 2019"
+[dumpfile_size] 13106022
+[savefile] "/homes/wangts/openairinterface5g/targets/RT/USER/gNB_usrp.gtkw"
+[timestart] 2183320000
+[size] 1920 1018
 [pos] -1 -1
-*-13.848083 11552814436 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
+*-18.423141 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1 -1
 [sst_width] 386
 [signals_width] 344
 [sst_expanded] 1
-[sst_vpaned_height] 197
+[sst_vpaned_height] 267
 @28
 functions.trx_read
 functions.trx_write
@@ -24,9 +24,8 @@ variables.frame_number_TX1_UE[63:0]
 functions.ue_gain_control
 @420
 variables.frame_number_RX1_UE[63:0]
-@25
-variables.trx_ts_ue[63:0]
 @24
+variables.trx_ts_ue[63:0]
 variables.trx_ts[63:0]
 variables.trx_tst[63:0]
 variables.frame_number_RX0_RU[63:0]
@@ -63,5 +62,7 @@ functions.phy_procedures_ru_feptx_ofdm0
 functions.phy_procedures_ru_feptx_ofdm1
 functions.phy_procedures_ru_feptx_prec0
 functions.phy_procedures_ru_feptx_prec1
+@23
+variables.ru_tx_ofdm_mask[63:0]
 [pattern_trace] 1
 [pattern_trace] 0
diff --git a/targets/RT/USER/lte-ru.c b/targets/RT/USER/lte-ru.c
index dea8c7a2b521399e1af66ac7f60a25566879d7e9..af96fa68dc998f59171e2d79a8475252388240d7 100644
--- a/targets/RT/USER/lte-ru.c
+++ b/targets/RT/USER/lte-ru.c
@@ -81,6 +81,7 @@
 /* these variables have to be defined before including ENB_APP/enb_paramdef.h */
 static int DEFBANDS[] = {7};
 static int DEFENBS[] = {0};
+static int DEFBFW[] = {0x00007fff};
 
 #include "ENB_APP/enb_paramdef.h"
 #include "common/config/config_userapi.h"