From 1309358bb5980a143e6ba5f79eb78f2177dc0259 Mon Sep 17 00:00:00 2001
From: Raymond Knopp <raymond.knopp@eurecom.fr>
Date: Wed, 24 Aug 2016 23:14:44 -0700
Subject: [PATCH] changes for oaisim to function with new threading
 architecture and trx_read/trx_write emulation. Tested for 5/10 MHz TM1.
 Multiple-antenna mode fails.

---
 cmake_targets/tools/build_helper              |   2 +-
 openair1/PHY/INIT/lte_init.c                  |   3 +-
 openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c |   5 +
 openair1/PHY/TOOLS/defs.h                     |   4 +-
 openair1/PHY/TOOLS/signal_energy.c            |   2 +-
 openair1/PHY/defs.h                           |   6 +-
 openair1/PHY/extern.h                         |   2 +-
 openair1/SCHED/phy_procedures_lte_ue.c        |  53 +++---
 openair1/SIMULATION/RF/adc.c                  |   4 +-
 openair1/SIMULATION/RF/dac.c                  |   8 +-
 openair1/SIMULATION/RF/defs.h                 |  16 +-
 openair1/SIMULATION/RF/rf.c                   |   4 +-
 openair1/SIMULATION/TOOLS/defs.h              |  16 +-
 openair1/SIMULATION/TOOLS/multipath_channel.c |  16 +-
 ...enb.band7.generic.oaisim.local_no_mme.conf |   2 +-
 targets/RT/USER/lte-enb.c                     |  22 +--
 targets/RT/USER/lte-ue.c                      |  38 ++--
 targets/SIMU/USER/channel_sim.c               |  15 +-
 targets/SIMU/USER/oaisim.c                    |  87 +++++----
 targets/SIMU/USER/oaisim_config.c             |   2 +-
 targets/SIMU/USER/oaisim_functions.c          | 166 ++++++++++++++----
 21 files changed, 320 insertions(+), 153 deletions(-)

diff --git a/cmake_targets/tools/build_helper b/cmake_targets/tools/build_helper
index 4738acb7f3c..514d7748ac7 100755
--- a/cmake_targets/tools/build_helper
+++ b/cmake_targets/tools/build_helper
@@ -179,7 +179,7 @@ install_nettle_from_source() {
     cd /tmp
     echo "Downloading nettle archive"
     $SUDO rm -rf /tmp/nettle-2.5.tar.gz* /tmp/nettle-2.5
-    wget https://ftp.gnu.org/gnu/nettle/nettle-2.5.tar.gz
+    wget http://ftp.nluug.nl/gnu/nettle/nettle-2.5.tar.gz
     if [ $? -ne 0 ]; then
       wget ftp://ftp.lysator.liu.se/pub/security/lsh/nettle-2.5.tar.gz
     fi
diff --git a/openair1/PHY/INIT/lte_init.c b/openair1/PHY/INIT/lte_init.c
index 4386ca5d47d..259a7ba77a5 100644
--- a/openair1/PHY/INIT/lte_init.c
+++ b/openair1/PHY/INIT/lte_init.c
@@ -988,7 +988,8 @@ int phy_init_lte_ue(PHY_VARS_UE *ue,
     ue->total_received_bits[eNB_id] = 0;
   }
 
-  ue->tx_power_dBm=-127;
+  for (i=0;i<10;i++)
+    ue->tx_power_dBm[i]=-127;
 
   if (abstraction_flag == 0) {
 
diff --git a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c
index b78a7e24fdb..c2be7ad1bd3 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_adjust_sync.c
@@ -30,6 +30,8 @@
 #include "PHY/defs.h"
 #include "PHY/extern.h"
 
+#include "UTIL/LOG/vcd_signal_dumper.h"
+
 #define DEBUG_PHY
 
 // Adjust location synchronization point to account for drift
@@ -48,6 +50,8 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms,
   int diff;
   short Re,Im,ncoef;
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN);
+
   ncoef = 32767 - coef;
 
 #ifdef DEBUG_PHY
@@ -98,6 +102,7 @@ void lte_adjust_synch(LTE_DL_FRAME_PARMS *frame_parms,
         ue->proc.proc_rxtx[0].frame_rx,ue->rx_offset,max_pos,max_pos_fil,temp);
 #endif //DEBUG_PHY
 
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT);
 
 }
 
diff --git a/openair1/PHY/TOOLS/defs.h b/openair1/PHY/TOOLS/defs.h
index 8d30a7ea100..3a8a58b6f2c 100644
--- a/openair1/PHY/TOOLS/defs.h
+++ b/openair1/PHY/TOOLS/defs.h
@@ -296,10 +296,10 @@ int32_t subcarrier_energy(int32_t *,uint32_t, int32_t* subcarrier_energy, uint16
 */
 int32_t signal_energy_nodc(int32_t *,uint32_t);
 
-/*!\fn double signal_energy_fp(double **, double **,uint32_t, uint32_t,uint32_t);
+/*!\fn double signal_energy_fp(double s_re[2][30720], double s_im[2][30720],uint32_t, uint32_t,uint32_t);
 \brief Computes the signal energy per subcarrier
 */
-double signal_energy_fp(double **s_re, double **s_im, uint32_t nb_antennas, uint32_t length,uint32_t offset);
+double signal_energy_fp(double s_re[2][30720], double s_im[2][30720], uint32_t nb_antennas, uint32_t length,uint32_t offset);
 
 /*!\fn double signal_energy_fp2(struct complex *, uint32_t);
 \brief Computes the signal energy per subcarrier
diff --git a/openair1/PHY/TOOLS/signal_energy.c b/openair1/PHY/TOOLS/signal_energy.c
index 373fdc0d90a..afd1c727f38 100755
--- a/openair1/PHY/TOOLS/signal_energy.c
+++ b/openair1/PHY/TOOLS/signal_energy.c
@@ -255,7 +255,7 @@ int32_t signal_energy_nodc(int32_t *input,uint32_t length)
 }
 
 #endif
-double signal_energy_fp(double **s_re,double **s_im,uint32_t nb_antennas,uint32_t length,uint32_t offset)
+double signal_energy_fp(double s_re[2][30720],double s_im[2][30720],uint32_t nb_antennas,uint32_t length,uint32_t offset)
 {
 
   int32_t aa,i;
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 5fdd88cd239..c4c37d2b722 100755
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -612,6 +612,8 @@ typedef struct {
   int is_synchronized;
   /// Data structure for UE process scheduling
   UE_proc_t proc;
+  /// Flag to indicate the UE shouldn't do timing correction at all
+  int no_timing_correction;
   /// \brief Total gain of the TX chain (16-bit baseband I/Q to antenna)
   uint32_t tx_total_gain_dB;
   /// \brief Total gain of the RX chain (antenna to baseband I/Q) This is a function of rx_gain_mode (and the corresponding gain) and the rx_gain of the card.
@@ -623,9 +625,9 @@ typedef struct {
   /// \brief Total gains with bypassed RF gain stage (ExpressMIMO2/Lime)
   uint32_t rx_gain_byp[4];
   /// \brief Current transmit power
-  int8_t tx_power_dBm;
+  int8_t tx_power_dBm[10];
   /// \brief Total number of REs in current transmission
-  int tx_total_RE;
+  int tx_total_RE[10];
   /// \brief Maximum transmit power
   int8_t tx_power_max_dBm;
   /// \brief Number of eNB seen by UE
diff --git a/openair1/PHY/extern.h b/openair1/PHY/extern.h
index 2144c4f01d9..8a5bf5e8f5a 100755
--- a/openair1/PHY/extern.h
+++ b/openair1/PHY/extern.h
@@ -111,7 +111,7 @@ extern double p_qam64[8];
 extern double beta1_dlsch[6][MCS_COUNT];
 extern double beta2_dlsch[6][MCS_COUNT];
 
-extern char eNB_functions[5][20];
+extern char eNB_functions[6][20];
 extern char eNB_timing[2][20];
 
 
diff --git a/openair1/SCHED/phy_procedures_lte_ue.c b/openair1/SCHED/phy_procedures_lte_ue.c
index 2612302d54d..58bbcc8ac0a 100755
--- a/openair1/SCHED/phy_procedures_lte_ue.c
+++ b/openair1/SCHED/phy_procedures_lte_ue.c
@@ -718,7 +718,7 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 							   frame_tx,
 							   eNB_id,
 							   subframe_tx);
-      //    LOG_I(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[Mod_id].radioResourceConfigCommon);
+      LOG_D(PHY,"Got prach_resources for eNB %d address %d, RRCCommon %d\n",eNB_id,ue->prach_resources[eNB_id],UE_mac_inst[ue->Mod_id].radioResourceConfigCommon);
     }
   }
   
@@ -744,17 +744,17 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 	    ue->prach_resources[eNB_id]->ra_RNTI);
       
       if ((ue->mac_enabled==1) && (mode != calib_prach_tx)) {
-	ue->tx_power_dBm = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id);
+	ue->tx_power_dBm[subframe_tx] = ue->prach_resources[eNB_id]->ra_PREAMBLE_RECEIVED_TARGET_POWER+get_PL(ue->Mod_id,ue->CC_id,eNB_id);
       }
       else {
-	ue->tx_power_dBm = ue->tx_power_max_dBm;
+	ue->tx_power_dBm[subframe_tx] = ue->tx_power_max_dBm;
 	ue->prach_resources[eNB_id]->ra_PreambleIndex = 19;	      
       }
       
-      ue->tx_total_RE = 96;
+      ue->tx_total_RE[subframe_tx] = 96;
       
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
-      ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm,
+      ue->prach_vars[eNB_id]->amp = get_tx_amp(ue->tx_power_dBm[subframe_tx],
 					       ue->tx_power_max_dBm,
 					       ue->frame_parms.N_RB_UL,
 					       6);
@@ -766,7 +766,7 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
 	      ue->Mod_id,
 	      proc->frame_rx,
 	      proc->subframe_tx,
-	      ue->tx_power_dBm,
+	      ue->tx_power_dBm[subframe_tx],
 	      ue->prach_vars[eNB_id]->amp);
       
       
@@ -778,7 +778,7 @@ void ue_prach_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
       LOG_D(PHY,"[UE  %d][RAPROC] PRACH PL %d dB, power %d dBm, digital power %d dB (amp %d)\n",
 	    ue->Mod_id,
 	    get_PL(ue->Mod_id,ue->CC_id,eNB_id),
-	    ue->tx_power_dBm,
+	    ue->tx_power_dBm[subframe_tx],
 	    dB_fixed(prach_power),
 	    ue->prach_vars[eNB_id]->amp);
     } else {
@@ -1036,15 +1036,15 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
     if (abstraction_flag == 0) {
       if (ue->mac_enabled==1) {
 	pusch_power_cntl(ue,proc,eNB_id,1, abstraction_flag);
-	ue->tx_power_dBm = ue->ulsch[eNB_id]->Po_PUSCH;
+	ue->tx_power_dBm[subframe_tx] = ue->ulsch[eNB_id]->Po_PUSCH;
       }
       else {
-	ue->tx_power_dBm = ue->tx_power_max_dBm;
+	ue->tx_power_dBm[subframe_tx] = ue->tx_power_max_dBm;
       }
-      ue->tx_total_RE = nb_rb*12;
+      ue->tx_total_RE[subframe_tx] = nb_rb*12;
       
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
-      tx_amp = get_tx_amp(ue->tx_power_dBm,
+      tx_amp = get_tx_amp(ue->tx_power_dBm[,
 			  ue->tx_power_max_dBm,
 			  ue->frame_parms.N_RB_UL,
 			  nb_rb);
@@ -1052,7 +1052,7 @@ void ue_ulsch_uespec_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB
       tx_amp = AMP;
 #endif
       LOG_D(PHY,"[UE  %d][PUSCH %d] Frame %d subframe %d, generating PUSCH, Po_PUSCH: %d dBm (max %d dBm), amp %d\n",
-	    Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm,ue->tx_power_max_dBm, tx_amp);
+	    Mod_id,harq_pid,frame_tx,subframe_tx,ue->tx_power_dBm[subframe_tx],ue->tx_power_max_dBm, tx_amp);
       start_meas(&ue->ulsch_modulation_stats);
       ulsch_modulation(ue->common_vars.txdataF,
 		       tx_amp,
@@ -1156,8 +1156,8 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
     else {
       Po_PUCCH = ue->tx_power_max_dBm;
     }
-    ue->tx_power_dBm = Po_PUCCH;
-    ue->tx_total_RE = 12;
+    ue->tx_power_dBm[subframe_tx] = Po_PUCCH;
+    ue->tx_total_RE[subframe_tx] = 12;
 	    
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
     tx_amp = get_tx_amp(Po_PUCCH,
@@ -1220,8 +1220,8 @@ void ue_pucch_procedures(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,uin
     else {
       Po_PUCCH = ue->tx_power_max_dBm;
     }
-    ue->tx_power_dBm = Po_PUCCH;
-    ue->tx_total_RE = 12;
+    ue->tx_power_dBm[subframe_tx] = Po_PUCCH;
+    ue->tx_total_RE[subframe_tx] = 12;
 	    
 #if defined(EXMIMO) || defined(OAI_USRP) || defined(OAI_BLADERF) || defined(OAI_LMSSDR)
     tx_amp =  get_tx_amp(Po_PUCCH,
@@ -1286,7 +1286,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui
   //phy_procedures_emos_UE_TX(next_slot);
 #endif
 
-  ue->tx_power_dBm=-127;
+  ue->tx_power_dBm[subframe_tx]=-127;
       
   if (abstraction_flag==0) {
     for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
@@ -1391,6 +1391,7 @@ void phy_procedures_UE_TX(PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,uint8_t eNB_id,ui
       (ue->frame_parms.prach_config_common.prach_Config_enabled==1)) {
 	
     // check if we have PRACH opportunity
+
     if (is_prach_subframe(&ue->frame_parms,frame_tx,subframe_tx)) {
 
       ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
@@ -1484,17 +1485,17 @@ void ue_measurement_procedures(uint16_t l, PHY_VARS_UE *ue,UE_rxtx_proc_t *proc,
 #endif
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_GAIN_CONTROL, VCD_FUNCTION_OUT);
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_IN);
+
     eNB_id = 0;
     
-    if (abstraction_flag == 0)
-      lte_adjust_synch(&ue->frame_parms,
-		       ue,
-		       eNB_id,
-		       0,
-		       16384);
-    
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_ADJUST_SYNCH, VCD_FUNCTION_OUT);
+    if (abstraction_flag == 0) {
+      if (ue->no_timing_correction==0)
+	lte_adjust_synch(&ue->frame_parms,
+			 ue,
+			 eNB_id,
+			 0,
+			 16384);
+    }      
 
   }
 
diff --git a/openair1/SIMULATION/RF/adc.c b/openair1/SIMULATION/RF/adc.c
index 6dc1c7f8e65..3f89a3cfe57 100755
--- a/openair1/SIMULATION/RF/adc.c
+++ b/openair1/SIMULATION/RF/adc.c
@@ -26,8 +26,8 @@
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
 
  *******************************************************************************/
-void adc(double **r_re,
-         double **r_im,
+void adc(double r_re[2][30720],
+         double r_im[2][30720],
          unsigned int input_offset,
          unsigned int output_offset,
          unsigned int **output,
diff --git a/openair1/SIMULATION/RF/dac.c b/openair1/SIMULATION/RF/dac.c
index 22e286a496f..ba67eb1f323 100755
--- a/openair1/SIMULATION/RF/dac.c
+++ b/openair1/SIMULATION/RF/dac.c
@@ -31,8 +31,8 @@
 #include <stdio.h>
 #include "PHY/TOOLS/defs.h"
 
-void dac(double **s_re,
-         double **s_im,
+void dac(double s_re[2][30720],
+         double s_im[2][30720],
          uint32_t **input,
          uint32_t input_offset,
          uint32_t nb_tx_antennas,
@@ -81,8 +81,8 @@ void dac(double **s_re,
   }
 }
 
-double dac_fixed_gain(double **s_re,
-                      double **s_im,
+double dac_fixed_gain(double s_re[2][30720],
+                      double s_im[2][30720],
                       uint32_t **input,
                       uint32_t input_offset,
                       uint32_t nb_tx_antennas,
diff --git a/openair1/SIMULATION/RF/defs.h b/openair1/SIMULATION/RF/defs.h
index 984dfa6ca84..4bd9528daeb 100644
--- a/openair1/SIMULATION/RF/defs.h
+++ b/openair1/SIMULATION/RF/defs.h
@@ -64,16 +64,16 @@ void rf_rx(double **r_re,
            double IQ_imb_dB,
            double IQ_phase);
 
-void rf_rx_simple(double **r_re,
-                  double **r_im,
+void rf_rx_simple(double r_re[2][30720],
+                  double r_im[2][30720],
                   unsigned int nb_rx_antennas,
                   unsigned int length,
                   double s_time,
                   double rx_gain_dB);
 
 
-void adc(double **r_re,
-         double **r_im,
+void adc(double r_re[2][30720],
+         double r_im[2][30720],
          unsigned int input_offset,
          unsigned int output_offset,
          int **output,
@@ -81,8 +81,8 @@ void adc(double **r_re,
          unsigned int length,
          unsigned char B);
 
-void dac(double **s_re,
-         double **s_im,
+void dac(double s_re[2][30720],
+         double s_im[2][30720],
          int **input,
          unsigned int input_offset,
          unsigned int nb_tx_antennas,
@@ -92,8 +92,8 @@ void dac(double **s_re,
          unsigned int meas_length,
          unsigned int meas_offset);
 
-double dac_fixed_gain(double **s_re,
-                      double **s_im,
+double dac_fixed_gain(double s_re[2][30720],
+                      double s_im[2][30720],
                       int **input,
                       unsigned int input_offset,
                       unsigned int nb_tx_antennas,
diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c
index 1f240595aa6..2bcb64727dd 100644
--- a/openair1/SIMULATION/RF/rf.c
+++ b/openair1/SIMULATION/RF/rf.c
@@ -206,8 +206,8 @@ void rf_rx(double **r_re,
   }
 }
 
-void rf_rx_simple(double **r_re,
-                  double **r_im,
+void rf_rx_simple(double r_re[2][30720],
+                  double r_im[2][30720],
                   unsigned int nb_rx_antennas,
                   unsigned int length,
                   double s_time,
diff --git a/openair1/SIMULATION/TOOLS/defs.h b/openair1/SIMULATION/TOOLS/defs.h
index c72ea743b1e..536655340b5 100644
--- a/openair1/SIMULATION/TOOLS/defs.h
+++ b/openair1/SIMULATION/TOOLS/defs.h
@@ -219,10 +219,10 @@ channel_desc_t *new_channel_desc_scm(uint8_t nb_tx,
 int random_channel(channel_desc_t *desc, uint8_t abstraction_flag);
 
 /**\fn void multipath_channel(channel_desc_t *desc,
-           double **tx_sig_re,
-           double **tx_sig_im,
-           double **rx_sig_re,
-           double **rx_sig_im,
+           double tx_sig_re[2][30720],
+           double tx_sig_im[2][30720],
+           double rx_sig_re[2][30720],
+           double rx_sig_im[2][30720],
            uint32_t length,
            uint8_t keep_channel)
 
@@ -237,10 +237,10 @@ int random_channel(channel_desc_t *desc, uint8_t abstraction_flag);
 */
 
 void multipath_channel(channel_desc_t *desc,
-                       double **tx_sig_re,
-                       double **tx_sig_im,
-                       double **rx_sig_re,
-                       double **rx_sig_im,
+                       double tx_sig_re[2][30720],
+                       double tx_sig_im[2][30720],
+                       double rx_sig_re[2][30720],
+                       double rx_sig_im[2][30720],
                        uint32_t length,
                        uint8_t keep_channel);
 /*
diff --git a/openair1/SIMULATION/TOOLS/multipath_channel.c b/openair1/SIMULATION/TOOLS/multipath_channel.c
index 9a72ca64233..aae9e974a7a 100644
--- a/openair1/SIMULATION/TOOLS/multipath_channel.c
+++ b/openair1/SIMULATION/TOOLS/multipath_channel.c
@@ -44,10 +44,10 @@ uint8_t multipath_channel_nosigconv(channel_desc_t *desc)
 //#define CHANNEL_SSE
 #ifdef CHANNEL_SSE
 void multipath_channel(channel_desc_t *desc,
-                       double **tx_sig_re,
-                       double **tx_sig_im,
-                       double **rx_sig_re,
-                       double **rx_sig_im,
+                       double tx_sig_re[2][30720],
+                       double tx_sig_im[2][30720],
+                       double rx_sig_re[2][30720],
+                       double rx_sig_im[2][30720],
                        uint32_t length,
                        uint8_t keep_channel)
 {
@@ -150,10 +150,10 @@ void multipath_channel(channel_desc_t *desc,
 
 #else
 void multipath_channel(channel_desc_t *desc,
-                       double **tx_sig_re,
-                       double **tx_sig_im,
-                       double **rx_sig_re,
-                       double **rx_sig_im,
+                       double tx_sig_re[2][30720],
+                       double tx_sig_im[2][30720],
+                       double rx_sig_re[2][30720],
+                       double rx_sig_im[2][30720],
                        uint32_t length,
                        uint8_t keep_channel)
 {
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf
index ad3bcfcf92b..3504adfff02 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.generic.oaisim.local_no_mme.conf
@@ -24,7 +24,7 @@ eNBs =
     component_carriers = (
       {
         node_function                                         = "eNodeB_3GPP";
-	node_timing                                           = "synch_to_other";
+	node_timing                                           = "synch_to_ext_device";
 	node_synch_ref                                        = 0; 
         frame_type					      = "FDD";
         tdd_config 					      = 3;
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 51ea3709e1f..cddef6ccc85 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -191,7 +191,7 @@ static inline void thread_top_init(char *thread_name,
     return &eNB_thread_rxtx_status;
   }
 
-  LOG_I( HW, "[SCHED] eNB RXn-TXnp4 deadline thread (TID %ld) started on CPU %d\n", gettid(), sched_getcpu() );
+  LOG_I( HW, "[SCHED] eNB %s deadline thread (TID %ld) started on CPU %d\n", gettid(), thread_name,sched_getcpu() );
 
 #else //LOW_LATENCY
   int policy, s, j;
@@ -654,7 +654,7 @@ static void* eNB_thread_rxtx( void* param ) {
   return &eNB_thread_rxtx_status;
 }
 
-#if defined(ENABLE_ITTI)
+#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
 /* Wait for eNB application initialization to be complete (eNB registration to MME) */
 static void wait_system_ready (char *message, volatile int *start_flag) {
   
@@ -1032,7 +1032,7 @@ void rx_fh_if4p5(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
 
 void rx_fh_slave(PHY_VARS_eNB *eNB,int *frame,int *subframe) {
   // This case is for synchronization to another thread
-  // it just waits for an external event.  The actual rx_rh is handle by the asynchronous RX thread
+  // it just waits for an external event.  The actual rx_fh is handle by the asynchronous RX thread
   eNB_proc_t *proc=&eNB->proc;
 
   if (wait_on_condition(&proc->mutex_FH,&proc->cond_FH,&proc->instance_cnt_FH,"rx_fh_slave") < 0)
@@ -1129,7 +1129,7 @@ void wakeup_slaves(eNB_proc_t *proc) {
 	  break;
       }
     } else {
-      LOG_W( PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave);
+      LOG_W( PHY,"[eNB] Frame %d, slave CC_id %d thread busy!! (cnt_FH %i)\n",slave_proc->frame_rx,slave_proc->CC_id, cnt_slave);
       exit_fun( "FH thread busy" );
       break;
     }             
@@ -1161,7 +1161,7 @@ static void* eNB_thread_FH( void* param ) {
 
   wait_sync("eNB_thread_FH");
 
-#if defined(ENABLE_ITTI)
+#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
   if (eNB->node_function < NGFI_RRU_IF5)
     wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
 #endif 
@@ -1273,7 +1273,7 @@ static void* eNB_thread_single( void* param ) {
 
   wait_sync("eNB_thread_single");
 
-#if defined(ENABLE_ITTI)
+#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
   if (eNB->node_function < NGFI_RRU_IF5)
     wait_system_ready ("Waiting for eNB application to be ready %s\r", &start_eNB);
 #endif 
@@ -1307,6 +1307,7 @@ static void* eNB_thread_single( void* param ) {
       subframe++;
     }      
 
+    LOG_D(PHY,"eNB Fronthaul thread, frame %d, subframe %d\n",frame,subframe);
  
     // synchronization on FH interface, acquire signals/data and block
     if (eNB->rx_fh) eNB->rx_fh(eNB,&frame,&subframe);
@@ -1314,6 +1315,7 @@ static void* eNB_thread_single( void* param ) {
 
     T(T_ENB_MASTER_TICK, T_INT(0), T_INT(proc->frame_rx), T_INT(proc->subframe_rx));
 
+
     // At this point, all information for subframe has been received on FH interface
     // If this proc is to provide synchronization, do so
     wakeup_slaves(proc);
@@ -1546,17 +1548,17 @@ int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_c
       
       for (i=0; i<frame_parms->nb_antennas_rx; i++) {
 	free(phy_vars_eNB[CC_id]->common_vars.rxdata[0][i]);
-	rxdata[i] = (int32_t*)(32 + malloc16(32+openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
+	rxdata[i] = (int32_t*)(32 + malloc16(32+frame_parms->samples_per_tti*10*sizeof(int32_t))); // FIXME broken memory allocation
 	phy_vars_eNB[CC_id]->common_vars.rxdata[0][i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD         FIXME! N_TA_offset > 16 => access of unallocated memory
-	memset(rxdata[i], 0, openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t));
+	memset(rxdata[i], 0, frame_parms->samples_per_tti*10*sizeof(int32_t));
 	printf("rxdata[%d] @ %p (%p) (N_TA_OFFSET %d)\n", i, phy_vars_eNB[CC_id]->common_vars.rxdata[0][i],rxdata[i],N_TA_offset);      
       }
       
       for (i=0; i<frame_parms->nb_antennas_tx; i++) {
 	free(phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
-	txdata[i] = (int32_t*)(32 + malloc16(32 + openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t))); // FIXME broken memory allocation
+	txdata[i] = (int32_t*)(32 + malloc16(32 + frame_parms->samples_per_tti*10*sizeof(int32_t))); // FIXME broken memory allocation
 	phy_vars_eNB[CC_id]->common_vars.txdata[0][i] = txdata[i];
-	memset(txdata[i],0, openair0_cfg[phy_vars_eNB[CC_id]->rf_map.card].samples_per_frame*sizeof(int32_t));
+	memset(txdata[i],0, frame_parms->samples_per_tti*10*sizeof(int32_t));
 	printf("txdata[%d] @ %p\n", i, phy_vars_eNB[CC_id]->common_vars.txdata[0][i]);
       }
     }
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
index 88bce26d6cc..c33005ebabc 100644
--- a/targets/RT/USER/lte-ue.c
+++ b/targets/RT/USER/lte-ue.c
@@ -793,6 +793,16 @@ static void *UE_thread_rxn_txnp4(void *arg)
 	UE->UE_mode[0] = PRACH;
       }
     }
+
+    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
+	(UE->frame_parms.frame_type == FDD) ||
+	(subframe_select( &UE->frame_parms, proc->subframe_tx ) == SF_S)) {
+
+      if (UE->mode != loop_through_memory) {
+	phy_procedures_UE_TX(UE,proc,0,0,normal_txrx,no_relay);
+      }
+    }
+
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 0 );
 
     
@@ -967,15 +977,18 @@ void *UE_thread(void *arg) {
       if (start_rx_stream==0) {
 	start_rx_stream=1;
 	if (UE->mode != loop_through_memory) {
-	  LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
-	  rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
-					   &timestamp,
-					   (void**)rxdata,
-					   UE->rx_offset,
-					   UE->frame_parms.nb_antennas_rx);
-	  if (rxs != UE->rx_offset) {
-	    exit_fun("problem in rx");
-	    return &UE_thread_retval;
+
+	  if (UE->no_timing_correction==0) {
+	    LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
+	    rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
+					     &timestamp,
+					     (void**)rxdata,
+					     UE->rx_offset,
+					     UE->frame_parms.nb_antennas_rx);
+	    if (rxs != UE->rx_offset) {
+	      exit_fun("problem in rx");
+	      return &UE_thread_retval;
+	    }
 	  }
 	  UE->rx_offset=0;
 	  UE->proc.proc_rxtx[0].frame_rx++;
@@ -1049,10 +1062,15 @@ void *UE_thread(void *arg) {
 	  int instance_cnt_rxtx = ++proc->instance_cnt_rxtx;
 	  proc->subframe_rx=sf;
 	  proc->subframe_tx=(sf+4)%10;
-	  proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5)?1:0;
+	  proc->frame_tx = proc->frame_rx + ((proc->subframe_rx>5)?1:0);
 	  proc->timestamp_tx = timestamp+(4*UE->frame_parms.samples_per_tti)-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
 
 
+	  if (sf != (timestamp/UE->frame_parms.samples_per_tti)%10) {
+	    LOG_E(PHY,"steady-state UE_thread error : frame_rx %d, subframe_rx %d, frame_tx %d, subframe_tx %d, rx subframe %d\n",proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,(timestamp/UE->frame_parms.samples_per_tti)%10);
+	    exit(-1);
+	  }
+
 	  if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
 	    LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" );
 	    exit_fun("nothing to add");
diff --git a/targets/SIMU/USER/channel_sim.c b/targets/SIMU/USER/channel_sim.c
index 8ff6c889624..9034fc05740 100644
--- a/targets/SIMU/USER/channel_sim.c
+++ b/targets/SIMU/USER/channel_sim.c
@@ -437,9 +437,14 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N
       txdata = PHY_vars_UE_g[UE_id][CC_id]->common_vars.txdata;
       sf_offset = subframe*frame_parms->samples_per_tti;
       
-      if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm +
+      if (((double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe] +
 	   UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB) <= -125.0) {
 	// don't simulate a UE that is too weak
+	LOG_D(OCM,"[SIM][UL] UE %d tx_pwr %d dBm (num_RE %d) for subframe %d (sf_offset %d)\n",
+	      UE_id,
+	      PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe],
+	      PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe],
+	      subframe,sf_offset);	
       } else {
 	
 	tx_pwr = dac_fixed_gain((double**)s_re,
@@ -451,13 +456,13 @@ void do_UL_sig(channel_desc_t *UE2eNB[NUMBER_OF_UE_MAX][NUMBER_OF_eNB_MAX][MAX_N
 				sf_offset,
 				frame_parms->ofdm_symbol_size,
 				14,
-				(double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE),
-				PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE);  // This make the previous argument the total power
+				(double)PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe]-10*log10((double)PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]),
+				PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe]);  // This make the previous argument the total power
 	LOG_D(OCM,"[SIM][UL] UE %d tx_pwr %f dBm (target %d dBm, num_RE %d) for subframe %d (sf_offset %d)\n",
 	      UE_id,
 	      10*log10(tx_pwr),
-	      PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm,
-	      PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE,
+	      PHY_vars_UE_g[UE_id][CC_id]->tx_power_dBm[subframe],
+	      PHY_vars_UE_g[UE_id][CC_id]->tx_total_RE[subframe],
 	      subframe,sf_offset);
        
 	
diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index fddbf517fde..258096fe73f 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -139,8 +139,10 @@ node_desc_t *ue_data[NUMBER_OF_UE_MAX];
 
 pthread_cond_t sync_cond;
 pthread_mutex_t sync_mutex;
-int sync_var;
+int sync_var=-1;
 
+pthread_mutex_t subframe_mutex;
+int subframe_eNB_mask=0,subframe_UE_mask=0;
 
 openair0_config_t openair0_cfg[MAX_CARDS];
 uint32_t          downlink_frequency[MAX_NUM_CCs][4];
@@ -451,6 +453,10 @@ typedef enum l2l1_task_state_e {
 
 l2l1_task_state_t l2l1_state = L2L1_WAITTING;
 
+extern openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
+extern openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
+
+
 /*------------------------------------------------------------------------------*/
 void *
 l2l1_task (void *args_p)
@@ -719,6 +725,40 @@ l2l1_task (void *args_p)
 
 	clear_eNB_transport_info (oai_emulation.info.nb_enb_local);
 
+        CC_id=0;
+        int all_done=0;
+        while (all_done==0) {
+          pthread_mutex_lock(&subframe_mutex);
+          int subframe_eNB_mask_local = subframe_eNB_mask;
+          int subframe_UE_mask_local  = subframe_UE_mask;
+          pthread_mutex_unlock(&subframe_mutex);
+          LOG_D(EMU,"Frame %d, Subframe %d: Checking masks %x,%x\n",frame,sf,subframe_eNB_mask,subframe_UE_mask);
+          if ((subframe_eNB_mask_local == ((1<<NB_eNB_INST)-1)) &&
+              (subframe_UE_mask_local == ((1<<NB_UE_INST)-1)))
+             all_done=1;
+          else
+             usleep(500);
+        }
+
+        //clear subframe masks for next round
+        pthread_mutex_lock(&subframe_mutex);
+        subframe_eNB_mask=0;
+        subframe_UE_mask=0;
+        pthread_mutex_unlock(&subframe_mutex);
+
+        // increment timestamps
+        for (eNB_inst = oai_emulation.info.first_enb_local;
+             (eNB_inst
+              < (oai_emulation.info.first_enb_local
+                 + oai_emulation.info.nb_enb_local));
+             eNB_inst++) {
+             current_eNB_rx_timestamp[eNB_inst][CC_id] += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti;
+        }
+        for (UE_inst = 0; UE_inst<NB_UE_INST;UE_inst++) {
+             current_UE_rx_timestamp[UE_inst][CC_id] += PHY_vars_UE_g[UE_inst][CC_id]->frame_parms.samples_per_tti;
+        }
+
+
         for (eNB_inst = oai_emulation.info.first_enb_local;
              (eNB_inst
               < (oai_emulation.info.first_enb_local
@@ -727,6 +767,7 @@ l2l1_task (void *args_p)
           if (oai_emulation.info.cli_start_enb[eNB_inst] != 0) {
         
 	    T(T_ENB_MASTER_TICK, T_INT(eNB_inst), T_INT(frame % 1024), T_INT(sf));
+	    /*
 	    LOG_D(EMU,
 		  "PHY procedures eNB %d for frame %d, subframe %d TDD %d/%d Nid_cell %d\n",
 		  eNB_inst,
@@ -736,7 +777,7 @@ l2l1_task (void *args_p)
 		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.tdd_config,
 		  PHY_vars_eNB_g[eNB_inst][0]->frame_parms.Nid_cell);
             
-
+	    */
 #ifdef OPENAIR2
 	    //Application: traffic gen
             update_otg_eNB (eNB_inst, oai_emulation.info.time_ms);
@@ -744,35 +785,8 @@ l2l1_task (void *args_p)
             //IP/OTG to PDCP and PDCP to IP operation
             //        pdcp_run (frame, 1, 0, eNB_inst); //PHY_vars_eNB_g[eNB_id]->Mod_id
 #endif
+           
 
-	    CC_id=0;
-	    // trigger synch event to RAN FH thread for CC_id
-	    eNB_proc_t *proc =  &PHY_vars_eNB_g[eNB_inst][CC_id]->proc;
-
-
-	    if (pthread_mutex_lock(&proc->mutex_FH) != 0) {
-	      LOG_E( PHY, "error locking mutex for FH\n");
-	      exit_fun( "error locking mutex" );
-	      break;
-	    }	    
-	    int cnt_FH       = ++proc->instance_cnt_FH;
-	    proc->frame_rx    = frame;
-            proc->subframe_rx = sf;
-	    proc->timestamp_rx += PHY_vars_eNB_g[eNB_inst][CC_id]->frame_parms.samples_per_tti;
-	    pthread_mutex_unlock( &proc->mutex_FH );
-
-	    if (cnt_FH == 0) {
-	      if (pthread_cond_signal(&proc->cond_FH) != 0) {
-		LOG_E(PHY,"ERROR pthread_cond_signal for eNB FH CCid %d\n",proc->CC_id);
-		exit_fun("ERROR pthread_cond_signal");
-		break;
-	      }
-	    }
-	    else {
-	      LOG_W(PHY,"[eNB] Frame %d, FH CC_id %d thread busy!! (cnt_FH %d)\n",proc->instance_cnt_FH);
-	      exit_fun("FH thread busy");
-              break;
-	    }
 #ifdef PRINT_STATS
 
             if((sf==9) && frame%10==0)
@@ -1099,6 +1113,10 @@ main (int argc, char **argv)
     sinr_dB = -20;
   }
 
+  pthread_cond_init(&sync_cond,NULL);
+  pthread_mutex_init(&sync_mutex, NULL);
+  pthread_mutex_init(&subframe_mutex, NULL);
+
 #ifdef OPENAIR2
   init_omv ();
 #endif
@@ -1116,6 +1134,15 @@ main (int argc, char **argv)
   init_openair2 ();
 
   init_ocm ();
+  
+  // wait for all threads to startup 
+  sleep(3);
+  printf("Sending sync to all threads\n");
+
+  pthread_mutex_lock(&sync_mutex);
+  sync_var=0;
+  pthread_cond_broadcast(&sync_cond);
+  pthread_mutex_unlock(&sync_mutex);
 
 #ifdef SMBV
   // Rohde&Schwarz SMBV100A vector signal generator
diff --git a/targets/SIMU/USER/oaisim_config.c b/targets/SIMU/USER/oaisim_config.c
index 51a5a03eacc..a470558c27d 100644
--- a/targets/SIMU/USER/oaisim_config.c
+++ b/targets/SIMU/USER/oaisim_config.c
@@ -456,7 +456,7 @@ int olg_config(void)
    set_comp_log(PHY,  LOG_TRACE, 0x15, 1);
    set_comp_log(PDCP, LOG_DEBUG, 0x15,1);
    set_comp_log(RRC,  LOG_DEBUG, 0x15,1);
-   set_comp_log(OCM,  LOG_ERR, 0x15,20);
+   set_comp_log(OCM,  LOG_DEBUG, 0x15,20);
    set_comp_log(OTG,  LOG_DEBUG, 0x15,1);
    set_comp_log(OMG,  LOG_NOTICE, 0x15,1);
    set_comp_log(OPT,  LOG_ERR, 0x15,1);
diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c
index 7a5c36b45d3..f6cb9fcb04a 100644
--- a/targets/SIMU/USER/oaisim_functions.c
+++ b/targets/SIMU/USER/oaisim_functions.c
@@ -957,6 +957,11 @@ void init_seed(uint8_t set_seed)
   }
 }
 
+openair0_timestamp current_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
+openair0_timestamp current_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
+openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
+openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
+
 int eNB_trx_start(openair0_device *device) {
   return(0);
 }
@@ -990,53 +995,134 @@ int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
   return(0);
 }
 
-int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
-  return(0);
-}
-
-int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
-  return(0);
-}
+extern pthread_mutex_t subframe_mutex;
+extern int subframe_eNB_mask,subframe_UE_mask;
 
-int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
 
   int eNB_id = device->Mod_id;
   int CC_id  = device->CC_id;
-  int UE_id;
-  int subframe = (timestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10;
 
-  for (UE_id=0;UE_id<=NB_UE_INST;UE_id++) {
-    do_DL_sig(eNB2UE,
+  int subframe;
+  int ready_for_new_subframe=0;
+  int subframe_eNB_mask_local;
+  int sample_count=0;
+
+  *ptimestamp = last_eNB_rx_timestamp[eNB_id][CC_id];
+
+  LOG_D(PHY,"eNB_trx_read nsamps %d TS(%llu,%llu) => subframe %d\n",nsamps,
+        (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id],
+        (unsigned long long)last_eNB_rx_timestamp[eNB_id][CC_id],
+	(*ptimestamp/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10);
+  // if we're at a subframe boundary generate UL signals for this eNB
+
+  while (sample_count<nsamps) {
+    while (current_eNB_rx_timestamp[eNB_id][CC_id]<
+	   (nsamps+last_eNB_rx_timestamp[eNB_id][CC_id])) {
+      LOG_D(EMU,"eNB: current TS %llu, last TS %llu, sleeping\n",current_eNB_rx_timestamp[eNB_id][CC_id],last_eNB_rx_timestamp[eNB_id][CC_id]);
+      usleep(500);
+    }
+
+    // tell top-level we are busy
+    pthread_mutex_lock(&subframe_mutex);
+    subframe_eNB_mask|=(1<<eNB_id);
+    pthread_mutex_unlock(&subframe_mutex); 
+    
+    subframe = (last_eNB_rx_timestamp[eNB_id][CC_id]/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10;
+    LOG_D(PHY,"eNB_trx_read generating UL subframe %d (Ts %llu, current TS %llu)\n",
+	  subframe,(unsigned long long)*ptimestamp,
+	  (unsigned long long)current_eNB_rx_timestamp[eNB_id][CC_id]);
+    
+    do_UL_sig(UE2eNB,
 	      enb_data,
 	      ue_data,
 	      subframe,
-	      0, //abstraction_flag,
+	      0,  // abstraction_flag
 	      &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms,
-	      UE_id,
+	      0,  // frame is only used for abstraction
+	      eNB_id,
 	      CC_id);
+  
+
+    last_eNB_rx_timestamp[eNB_id][CC_id] += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
+    sample_count += PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
   }
-  return(0);
+
+  return(nsamps);
 }
 
-int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
 
   int UE_id = device->Mod_id;
   int CC_id  = device->CC_id;
-  int eNB_id;
-  int subframe = (timestamp/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10;
+  int subframe;
+  int ready_for_new_subframe=0;
+  int subframe_UE_mask_local;
+  int sample_count=0;
+  int read_size;
+
+  *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id];
+
+  LOG_D(PHY,"UE_trx_read nsamps %d TS(%llu,%llu)\n",nsamps,
+        (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id],
+        (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id]);
+
+  if (nsamps < PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)
+    read_size = nsamps;
+  else
+    read_size = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
+
+  while (sample_count<nsamps) {
+    while (current_UE_rx_timestamp[UE_id][CC_id] < 
+	   (last_UE_rx_timestamp[UE_id][CC_id]+read_size)) {
+      LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
+      
+      usleep(500);
+    }
 
-  for (eNB_id=0;eNB_id<=NB_eNB_INST;eNB_id++) {
-    do_UL_sig(UE2eNB,
+    LOG_D(EMU,"UE_trx_read : current TS %d, last TS %d, sleeping\n",current_UE_rx_timestamp[UE_id][CC_id],last_UE_rx_timestamp[UE_id][CC_id]);
+      
+    // tell top-level we are busy 
+    pthread_mutex_lock(&subframe_mutex);
+    subframe_UE_mask|=(1<<UE_id);
+    pthread_mutex_unlock(&subframe_mutex);
+    // if we didn't ask for at least a subframe's worth of samples return
+
+    // otherwise we have one subframe here so generate the received signal
+    subframe = (last_UE_rx_timestamp[UE_id][CC_id]/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10;
+    if ((last_UE_rx_timestamp[UE_id][CC_id]%PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti) > 0)
+      subframe++;
+
+    last_UE_rx_timestamp[UE_id][CC_id] += read_size;
+    sample_count += read_size;
+ 
+    if (subframe > 9) 
+      return(nsamps);
+
+    LOG_D(PHY,"UE_trx_read generating DL subframe %d (Ts %llu, current TS %llu)\n",
+	  subframe,(unsigned long long)*ptimestamp,
+	  (unsigned long long)current_UE_rx_timestamp[UE_id][CC_id]);    
+    do_DL_sig(eNB2UE,
 	      enb_data,
 	      ue_data,
 	      subframe,
-	      0,  // abstraction_flag
-	      &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms,
-	      0,  // frame is only used for abstraction
-	      eNB_id,
+	      0, //abstraction_flag,
+	      &PHY_vars_UE_g[UE_id][CC_id]->frame_parms,
+	      UE_id,
 	      CC_id);
   }
-  return(0);
+  
+  return(nsamps);
+}
+
+int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+
+  return(nsamps);
+}
+
+int UE_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {
+
+  return(nsamps);
 }
 
 void init_devices(void){
@@ -1055,8 +1141,10 @@ void init_devices(void){
       PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_stop_func      = eNB_trx_stop;
       PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_freq_func  = eNB_trx_set_freq;
       PHY_vars_eNB_g[eNB_id][CC_id]->rfdevice.trx_set_gains_func = eNB_trx_set_gains;
+      current_eNB_rx_timestamp[eNB_id][CC_id] = PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti;
+      last_eNB_rx_timestamp[eNB_id][CC_id] = 0;
     }
-    for (UE_id=0;UE_id<NB_eNB_INST;UE_id++) {
+    for (UE_id=0;UE_id<NB_UE_INST;UE_id++) {
       PHY_vars_UE_g[UE_id][CC_id]->rfdevice.Mod_id               = UE_id;
       PHY_vars_UE_g[UE_id][CC_id]->rfdevice.CC_id                = CC_id;
       PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_start_func       = UE_trx_start;
@@ -1066,6 +1154,9 @@ void init_devices(void){
       PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_stop_func        = UE_trx_stop;
       PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_freq_func    = UE_trx_set_freq;
       PHY_vars_UE_g[UE_id][CC_id]->rfdevice.trx_set_gains_func   = UE_trx_set_gains;
+      current_UE_rx_timestamp[UE_id][CC_id] = PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti;
+      last_UE_rx_timestamp[UE_id][CC_id] = 0;
+
     }
   }
 }
@@ -1123,7 +1214,11 @@ void init_openair1(void)
   //N_TA_offset
   for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     for (UE_id=0; UE_id<NB_UE_INST; UE_id++) {
-      PHY_vars_UE_g[UE_id][CC_id]->use_ia_receiver = 0;
+
+      PHY_vars_UE_g[UE_id][CC_id]->use_ia_receiver      = 0;
+      PHY_vars_UE_g[UE_id][CC_id]->mode                 = normal_txrx;
+      PHY_vars_UE_g[UE_id][CC_id]->mac_enabled          = 1;
+      PHY_vars_UE_g[UE_id][CC_id]->no_timing_correction = 1;
 
       if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.frame_type == TDD) {
         if (PHY_vars_UE_g[UE_id][CC_id]->frame_parms.N_RB_DL == 100)
@@ -1396,7 +1491,7 @@ void update_ocm()
     enb_data[eNB_id]->tx_power_dBm = PHY_vars_eNB_g[eNB_id][0]->frame_parms.pdsch_config_common.referenceSignalPower;
 
   for (UE_id = 0; UE_id < NB_UE_INST; UE_id++)
-    ue_data[UE_id]->tx_power_dBm = PHY_vars_UE_g[UE_id][0]->tx_power_dBm;
+    ue_data[UE_id]->tx_power_dBm = PHY_vars_UE_g[UE_id][0]->tx_power_dBm[0];
 
 
   /* check if the openair channel model is activated used for PHY abstraction : path loss*/
@@ -1450,10 +1545,10 @@ void update_ocm()
             UE2eNB[UE_id][eNB_id][CC_id]->path_loss_dB = -132.24 + sinr_dB - PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower;
           }
 
-          LOG_I(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",eNB_id,UE_id,CC_id,
+          LOG_D(OCM,"Path loss from eNB %d to UE %d (CCid %d)=> %f dB (eNB TX %d, SNR %f)\n",eNB_id,UE_id,CC_id,
                 eNB2UE[eNB_id][UE_id][CC_id]->path_loss_dB,
                 PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.pdsch_config_common.referenceSignalPower,snr_dB);
-          //      printf("[SIM] Path loss from UE %d to eNB %d => %f dB\n",UE_id,eNB_id,UE2eNB[UE_id][eNB_id]->path_loss_dB);
+        
         }
       }
     }
@@ -1721,3 +1816,14 @@ void init_time()
   td_avg        = TARGET_SF_TIME_NS;
 }
 
+int openair0_transport_load(openair0_device *device, openair0_config_t *openair0_cfg, eth_params_t * eth_params) {
+
+	return(0);
+
+
+}
+
+int openair0_device_load(openair0_device *device, openair0_config_t *openair0_cfg) {
+
+	return(0);
+}
-- 
GitLab