diff --git a/targets/SIMU/USER/oaisim.c b/targets/SIMU/USER/oaisim.c
index d5f49d9faffb881914c20167f1d533906d1073f3..723da842bbd93ebf733d0172f443954bef544b73 100644
--- a/targets/SIMU/USER/oaisim.c
+++ b/targets/SIMU/USER/oaisim.c
@@ -457,7 +457,8 @@ 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];
-
+extern openair0_timestamp last_eNB_rx_timestamp[NUMBER_OF_eNB_MAX][MAX_NUM_CCs];
+extern openair0_timestamp last_UE_rx_timestamp[NUMBER_OF_UE_MAX][MAX_NUM_CCs];
 
 /*------------------------------------------------------------------------------*/
 void *
@@ -731,38 +732,41 @@ 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
+          int i;
+          all_done = 1;
+          for (i = oai_emulation.info.first_enb_local;
+               i < oai_emulation.info.first_enb_local + oai_emulation.info.nb_enb_local;
+               i++)
+            for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
+              if (last_eNB_rx_timestamp[i][CC_id] != current_eNB_rx_timestamp[i][CC_id]) {
+                all_done = 0;
+                break;
+              }
+          if (all_done == 1)
+            for (i = 0; i < NB_UE_INST; i++)
+              for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
+                if (last_UE_rx_timestamp[i][CC_id] != current_UE_rx_timestamp[i][CC_id]) {
+                  all_done = 0;
+                  break;
+                }
+          if (all_done == 0)
 	    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 (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
+            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 (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++)
+            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;
diff --git a/targets/SIMU/USER/oaisim_functions.c b/targets/SIMU/USER/oaisim_functions.c
index 130a3393905e0325aa60d3ba1612c1772d6ed9aa..bcb6b7074c97ad459ca54938226f5e683c2fe06e 100644
--- a/targets/SIMU/USER/oaisim_functions.c
+++ b/targets/SIMU/USER/oaisim_functions.c
@@ -998,13 +998,15 @@ int UE_trx_set_gains(openair0_device *device, openair0_config_t *openair0_cfg) {
 extern pthread_mutex_t subframe_mutex;
 extern int subframe_eNB_mask,subframe_UE_mask;
 
-int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
-
+int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
+{
+  int ret = nsamps;
   int eNB_id = device->Mod_id;
   int CC_id  = device->CC_id;
 
   int subframe;
-  int sample_count=0;
+  int read_samples, max_samples;
+  openair0_timestamp last = last_eNB_rx_timestamp[eNB_id][CC_id];
 
   *ptimestamp = last_eNB_rx_timestamp[eNB_id][CC_id];
 
@@ -1014,49 +1016,55 @@ int eNB_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void *
 	(*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])) {
+  while (nsamps) {
+    while (current_eNB_rx_timestamp[eNB_id][CC_id] == last) {
       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]);
+    read_samples = nsamps;
+    max_samples = current_eNB_rx_timestamp[eNB_id][CC_id]-last;
+    if (read_samples > max_samples)
+      read_samples = max_samples;
+
+    last += read_samples;
+    nsamps -= read_samples;
+
+    if (current_eNB_rx_timestamp[eNB_id][CC_id] == last) {
+      subframe = (last/PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms.samples_per_tti)%10;
+      //subframe = (subframe+9) % 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
-	      &PHY_vars_eNB_g[eNB_id][CC_id]->frame_parms,
-	      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;
+      do_UL_sig(UE2eNB,
+                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,
+                CC_id);
+
+      last_eNB_rx_timestamp[eNB_id][CC_id] = last;
+    }
   }
   
+  last_eNB_rx_timestamp[eNB_id][CC_id] = last;
 
-
-  return(nsamps);
+  return ret;
 }
 
-int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc) {
-
+int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **buff, int nsamps, int cc)
+{
+  int ret = nsamps;
   int UE_id = device->Mod_id;
   int CC_id  = device->CC_id;
   int subframe;
-  int sample_count=0;
-  int read_size;
+  int read_samples, max_samples;
+  openair0_timestamp last = last_UE_rx_timestamp[UE_id][CC_id];
 
   *ptimestamp = last_UE_rx_timestamp[UE_id][CC_id];
 
@@ -1065,14 +1073,19 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
         (unsigned long long)last_UE_rx_timestamp[UE_id][CC_id],
 	cc);
 
-  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)) {
+  while (nsamps) {
+    /* wait for all processing to be finished */
+    while (1) {
+      PHY_VARS_UE *UE = PHY_vars_UE_g[UE_id][0];
+      int ready = 1;
+      int i;
+      for (i = 0; i < 2; i++)
+        if (UE->proc.proc_rxtx[i].instance_cnt_rxtx >= 0) ready = 0;
+      if (UE->proc.instance_cnt_synch >= 0) ready = 0;
+      if (ready) break;
+      usleep(500);
+    }
+    while (current_UE_rx_timestamp[UE_id][CC_id] == last) {
       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);
@@ -1080,40 +1093,39 @@ int UE_trx_read(openair0_device *device, openair0_timestamp *ptimestamp, void **
 
     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);
-
-
-    // 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_UE_g[UE_id][CC_id]->frame_parms,
-	      UE_id,
-	      CC_id);
-
-
+    read_samples = nsamps;
+    max_samples = current_UE_rx_timestamp[UE_id][CC_id]-last;
+    if (read_samples > max_samples)
+      read_samples = max_samples;
+
+    last += read_samples;
+    nsamps -= read_samples;
+
+    if (current_UE_rx_timestamp[UE_id][CC_id] == last) {
+      // we have one subframe here so generate the received signal
+      subframe = (last/PHY_vars_UE_g[UE_id][CC_id]->frame_parms.samples_per_tti)%10;
+      //subframe = (subframe+9) % 10;
+
+      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_UE_g[UE_id][CC_id]->frame_parms,
+                UE_id,
+                CC_id);
+
+      last_UE_rx_timestamp[UE_id][CC_id] = last;
+    }
   }
 
+  last_UE_rx_timestamp[UE_id][CC_id] = last;
 
-  return(nsamps);
+  return ret;
 }
 
 int eNB_trx_write(openair0_device *device,openair0_timestamp timestamp, void **buff, int nsamps, int cc, int flags) {