diff --git a/targets/RT/USER/Makefile b/targets/RT/USER/Makefile
index 2017e250fc41b03fb23ac90e13ac1d57a85fef3f..d9b350a64c78bce0c1233781bda34c183882339b 100644
--- a/targets/RT/USER/Makefile
+++ b/targets/RT/USER/Makefile
@@ -218,6 +218,7 @@ SHARED_DEPENDENCIES 	+= $(LFDS_LIB)
 -include $(ASN1_MSG_OBJS1:.o=.d)
 -include $(RTAI_OBJ:.o=.d)
 -include lte-softmodem.d
+-include lte-ue.d
 -include rrh.d
 
 $(LFDS_LIB):
@@ -238,7 +239,7 @@ $(ETHERNET_OBJ):$(ETHERNET_FILE_OBJ)
 endif
 
 ifeq ($(RTAI),1)
-$(RTAI_OBJ) lte-softmodem.o: %.o : %.c
+$(RTAI_OBJ) lte-softmodem.o lte-ue.o: %.o : %.c
 else
 $(RTAI_OBJ): %.o : %.c
 endif
@@ -258,7 +259,7 @@ endif
 ifeq ($(RTAI),1)
 $(OBJ) $(ASN1_MSG_OBJS1): %.o : %.c
 else
-$(OBJ) $(ASN1_MSG_OBJS1) lte-softmodem.o: %.o : %.c
+$(OBJ) $(ASN1_MSG_OBJS1) lte-softmodem.o lte-ue.o: %.o : %.c
 endif
 
 rrh.o: %.o : %.c
@@ -286,9 +287,9 @@ synctest: $(OBJ_SYNC) $(SHARED_DEPENDENCIES) synctest.c
 sleeptest: rt_wrapper.o sleeptest.c
 	$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(RTAI_CFLAGS) rt_wrapper.o -o sleeptest sleeptest.c $(LDFLAGS) 
 
-lte-softmodem: $(OBJ) $(USRP_OBJ) $(ETHERNET_OBJ) $(ASN1_MSG_OBJS1) $(RTAI_OBJ) lte-softmodem.o $(SHARED_DEPENDENCIES)
+lte-softmodem: $(OBJ) $(USRP_OBJ) $(ETHERNET_OBJ) $(ASN1_MSG_OBJS1) $(RTAI_OBJ) lte-ue.o lte-softmodem.o $(SHARED_DEPENDENCIES)
 	@echo Linking $@
-	@$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(USRP_OBJ) $(ETHERNET_OBJ) $(RTAI_OBJ) $(ASN1_MSG_OBJS1) lte-softmodem.o -o lte-softmodem $(LDFLAGS) $(LIBS)
+	@$(CC) $(CFLAGS) $(EXTRA_CFLAGS) $(OBJ) $(USRP_OBJ) $(ETHERNET_OBJ) $(RTAI_OBJ) $(ASN1_MSG_OBJS1) lte-ue.o lte-softmodem.o -o lte-softmodem $(LDFLAGS) $(LIBS)
 
 rrh: rrh.o
 	@$(CC) $(CFLAGS) $(EXTRA_CFLAGS) rrh.o -o rrh -lpthread -lrt
@@ -381,8 +382,8 @@ cleanmodem:
 	@$(RM_F_V) $(OBJ) $(RTAI_OBJ) $(OBJ_EMOS) $(OBJ_SYNC) $(USRP_OBJ) $(ETHERNET_OBJ)
 	@$(RM_F_V) $(OBJ:.o=.d) $(RTAI_OBJ:.o=.d) $(OBJ_EMOS:.o=.d) $(OBJ_SYNC:.o=.d)
 	@$(RM_F_V) $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/asn1_msg.o $(OPENAIR2_DIR)/RRC/LITE/MESSAGES/asn1_msg.d
-	@$(RM_F_V) rrh.o rrh.d lte-softmodem.o lte-softmodem.d
-	@$(RM_F_V) rrh.o lte-softmodem.o
+	@$(RM_F_V) lte-ue.o lte-ue.d rrh.o rrh.d lte-softmodem.o lte-softmodem.d
+	@$(RM_F_V) rrh.o lte-ue.o lte-softmodem.o
 
 cleanasn1:
 	rm -f $(ASN1_MSG_OBJS1)
diff --git a/targets/RT/USER/eNB.gtkw b/targets/RT/USER/eNB.gtkw
index d448406e0a276366722df09a5f080e5ce5defefe..eadbb8538958c5d17af3fb9cdb7e0861b723affd 100644
--- a/targets/RT/USER/eNB.gtkw
+++ b/targets/RT/USER/eNB.gtkw
@@ -23,6 +23,8 @@ functions.trx_write
 @24
 variables.txcnt[63:0]
 variables.rxcnt[63:0]
+variables.trx_ts[63:0]
+variables.trx_tst[63:0]
 @25
 variables.frame_number_TX_eNB[63:0]
 variables.frame_number_RX_eNB[63:0]
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index 702f8940459e4d68650798c5c46ad4d372089a0c..d93a6067ba1c99fca4badc56f20ec8e5e5846e89 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -97,9 +97,7 @@ static int hw_subframe;
 #include "LAYER2/MAC/defs.h"
 #include "LAYER2/MAC/vars.h"
 #include "LAYER2/MAC/proto.h"
-#ifndef CELLULAR
 #include "RRC/LITE/vars.h"
-#endif
 #include "PHY_INTERFACE/vars.h"
 #endif
 
@@ -143,13 +141,7 @@ struct timing_info_t {
   unsigned int n_samples;
 } timing_info;
 
-extern int16_t* sync_corr_ue0;
-extern int16_t prach_ifft[4][1024*2];
 
-int init_dlsch_threads(void);
-void cleanup_dlsch_threads(void);
-int32_t init_rx_pdsch_thread(void);
-void cleanup_rx_pdsch_thread(void);
 
 openair0_config_t openair0_cfg[MAX_CARDS];
 
@@ -170,8 +162,10 @@ unsigned char                   scope_enb_num_ue = 1;
 #endif //XFORMS
 
 #ifdef RTAI
+
 static long                      main_eNB_thread;
 static long                      main_ue_thread;
+
 #else
 pthread_t                       main_eNB_thread;
 pthread_t                       main_ue_thread;
@@ -183,20 +177,16 @@ pthread_attr_t                  attr_UE_thread;
 #ifndef LOWLATENCY
 struct sched_param              sched_param_dlsch;
 #endif 
+#endif
 
 pthread_cond_t sync_cond;
 pthread_mutex_t sync_mutex;
 int sync_var=-1;
 
-RTIME T0;
 
-pthread_attr_t                  attr_UE_init_synch;
-pthread_attr_t                  attr_UE_thread_tx;
-pthread_attr_t                  attr_UE_thread_rx;
+
+
 struct sched_param              sched_param_UE_thread;
-struct sched_param              sched_param_UE_init_synch;
-struct sched_param              sched_param_UE_thread_tx;
-struct sched_param              sched_param_UE_thread_rx;
 
 pthread_attr_t                  attr_eNB_proc_tx[MAX_NUM_CCs][10];
 pthread_attr_t                  attr_eNB_proc_rx[MAX_NUM_CCs][10];
@@ -212,7 +202,7 @@ static pthread_t                thread3; //emos
 #endif
 
 openair0_device openair0;
-openair0_timestamp timestamp;
+
 
 /*
   static int instance_cnt=-1; //0 means worker is busy, -1 means its free
@@ -237,13 +227,11 @@ static int                      time_offset[4] = {0,0,0,0};
 
 
 static char                     UE_flag=0;
-static uint8_t                  eNB_id=0,UE_id=0;
+//static uint8_t                  eNB_id=0,UE_id=0;
+
 
-//uint32_t                        carrier_freq[MAX_NUM_CCs][4] =           {{1907600000,1907600000,1907600000,1907600000}}; /* For UE! */
-static uint32_t                 downlink_frequency[MAX_NUM_CCs][4];/* =     {{1907600000,1907600000,1907600000,1907600000},
-								      {1907600000,1907600000,1907600000,1907600000}};*/
-static int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4]; /*= {{0,0,0,0},{0,0,0,0}};
-									  */
+uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
+int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4]; 
 
 openair0_rf_map rf_map[MAX_NUM_CCs];
 
@@ -252,6 +240,10 @@ static char                    *conf_config_file_name = NULL;
 static char                    *itti_dump_file = NULL;
 #endif
 
+int UE_scan = 1;
+runmode_t mode = normal_txrx;
+
+
 #ifdef EXMIMO
 double tx_gain[MAX_NUM_CCs][4] = {{20,20,0,0},{20,20,0,0}};
 double rx_gain[MAX_NUM_CCs][4] = {{20,20,0,0},{20,20,0,0}};
@@ -262,13 +254,13 @@ double rx_gain[MAX_NUM_CCs][4] = {{20,20,0,0},{20,20,0,0}};
   static unsigned int             rxg_byp[4] =    {120,120,120,120};
 */
 // these are for EXMIMO2 card 39
-static unsigned int             rxg_max[4] =    {128,128,128,126};
-static unsigned int             rxg_med[4] =    {122,123,123,120};
-static unsigned int             rxg_byp[4] =    {116,117,116,116};
-static unsigned int             nf_max[4] =    {7,9,16,12};
-static unsigned int             nf_med[4] =    {12,13,22,17};
-static unsigned int             nf_byp[4] =    {15,20,29,23};
-static rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
+unsigned int             rxg_max[4] =    {128,128,128,126};
+unsigned int             rxg_med[4] =    {122,123,123,120};
+unsigned int             rxg_byp[4] =    {116,117,116,116};
+unsigned int             nf_max[4] =    {7,9,16,12};
+unsigned int             nf_med[4] =    {12,13,22,17};
+unsigned int             nf_byp[4] =    {15,20,29,23};
+rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
 #else
 double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
 double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
@@ -284,64 +276,12 @@ char ref[128] = "internal";
 char channels[128] = "0";
 
 unsigned int samples_per_frame = 307200;
-unsigned int samples_per_packets = 2048; // samples got every recv or send
 unsigned int tx_forward_nsamps;
-
-#ifndef USRP
-//256 sample blocks
-int sf_bounds_1_5[10]    = {8, 15, 23, 30, 38, 45, 53, 60, 68, 75};
-int sf_bounds_1_5_tx[10] = {4, 11, 19, 26, 34, 41, 49, 56, 64, 71};
-
-int sf_bounds_5[10] = {5,10,15,20,25,30,35,40,45,50};
-int sf_bounds_5_tx[10] = {3,8,13,18,23,28,33,38,43,48};
-
-int sf_bounds_10[10]    = {10, 20, 30, 40, 50, 60, 70, 80, 90, 100};
-int sf_bounds_10_tx[10] = {5, 15, 25, 35, 45, 55, 65, 75, 85,95};
-
-int sf_bounds_20[10] = {20, 40, 60, 80, 100, 120, 140, 160, 180, 200};
-int sf_bounds_20_tx[10] = {10, 30, 50, 70, 90, 110, 130, 150, 170, 190};
-
-#else
-
-int sf_bounds_1_5[10]    = {8, 15, 23, 30, 38, 45, 53, 60, 68, 75};
-int sf_bounds_1_5_tx[10] = {4, 11, 19, 26, 34, 41, 49, 56, 64, 71};
-
-int sf_bounds_5[10]    = {8, 15, 23, 30, 38, 45, 53, 60, 68, 75};
-int sf_bounds_5_tx[10] = {4, 11, 19, 26, 34, 41, 49, 56, 64, 71};
-
-int sf_bounds_10[10] = {8, 15, 23, 30, 38, 45, 53, 60, 68, 75};
-int sf_bounds_10_tx[10] = {4, 11, 19, 26, 34, 41, 49, 56, 64, 71};
-
-int sf_bounds_20[10] = {15, 30, 45, 60, 75, 90, 105, 120, 135, 150};
-int sf_bounds_20_tx[10] = {7, 22, 37, 52, 67, 82, 97, 112, 127, 142};
-#endif
-
-int *sf_bounds;
-int *sf_bounds_tx;
-
-int max_cnt;
 int tx_delay;
 
 #endif
-/*
-  uint32_t rf_mode_max[4]     = {55759,55759,55759,55759};
-  uint32_t rf_mode_med[4]     = {39375,39375,39375,39375};
-  uint32_t rf_mode_byp[4]     = {22991,22991,22991,22991};
-*/
-//static uint32_t                      rf_mode[4] =        {MY_RF_MODE,0,0,0};
-//static uint32_t                      rf_local[4] =       {8255000,8255000,8255000,8255000}; // UE zepto
-//{8254617, 8254617, 8254617, 8254617}; //eNB khalifa
-//{8255067,8254810,8257340,8257340}; // eNB PETRONAS
-
-//static uint32_t                      rf_vcocal[4] =      {910,910,910,910};
-//static uint32_t                      rf_vcocal_850[4] =  {2015, 2015, 2015, 2015};
-//static uint32_t                      rf_rxdc[4] =        {32896,32896,32896,32896};
-//static uint32_t                      rxgain[4] =         {20,20,20,20};
-//static uint32_t                      txgain[4] =         {20,20,20,20};
-
-static runmode_t                mode;
-static int                      rx_input_level_dBm;
-static int                      UE_scan=1;
+
+int                      rx_input_level_dBm;
 static int                      online_log_messages=0;
 #ifdef XFORMS
 extern int                      otg_enabled;
@@ -407,58 +347,9 @@ int rrh_UE_port = 51000;
 #endif
 
 char uecap_xer[1024],uecap_xer_in=0;
+extern void *UE_thread(void *arg);
+extern void init_UE_threads(void);
 
-#define KHz (1000UL)
-#define MHz (1000 * KHz)
-
-typedef struct eutra_band_s {
-  int16_t band;
-  uint32_t ul_min;
-  uint32_t ul_max;
-  uint32_t dl_min;
-  uint32_t dl_max;
-  lte_frame_type_t frame_type;
-} eutra_band_t;
-
-typedef struct band_info_s {
-  int nbands;
-  eutra_band_t band_info[100];
-} band_info_t;
-
-band_info_t bands_to_scan;
-
-static const eutra_band_t eutra_bands[] =
-  {
-    { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
-    { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
-    { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
-    { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
-    { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
-    { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
-    { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
-    { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
-    { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
-    {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
-    {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
-    {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
-    {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
-    {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
-
-    {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
-
-    {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
-    {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
-    {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
-    {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
-    {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
-    {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
-    {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
-    {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
-    {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
-    {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
-    {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
-    {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
-  };
 unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
 {
   return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
@@ -585,6 +476,7 @@ static void *scope_thread(void *arg) {
   int len = 0;
 # endif
   struct sched_param sched_param;
+  int UE_id;
 
   sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1; 
   sched_setscheduler(0, SCHED_FIFO,&sched_param);
@@ -606,10 +498,10 @@ static void *scope_thread(void *arg) {
 	dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
       fl_set_object_label(form_stats->stats_text, stats_buffer);
 
-      phy_scope_UE(form_ue[UE_id], 
-		   PHY_vars_UE_g[UE_id][0],
-		   eNB_id,
-		   UE_id,7);
+      phy_scope_UE(form_ue[0], 
+		   PHY_vars_UE_g[0][0],
+		   0,
+		   0,7);
             
     } else {
 # ifdef ENABLE_XFORMS_WRITE_STATS
@@ -626,7 +518,7 @@ static void *scope_thread(void *arg) {
 
       for(UE_id=0;UE_id<scope_enb_num_ue;UE_id++) {
 	phy_scope_eNB(form_enb[UE_id], 
-		      PHY_vars_eNB_g[eNB_id][0],
+		      PHY_vars_eNB_g[0][0],
 		      UE_id);
       }
               
@@ -1412,7 +1304,7 @@ static void *eNB_thread(void *arg)
 #ifdef LOWLATENCY
   struct sched_attr attr;
   unsigned int flags = 0;
-  unsigned long mask = 1; /* processor 0 */
+//  unsigned long mask = 1; /* processor 0 */
 #endif
 #endif
 
@@ -1436,14 +1328,21 @@ static void *eNB_thread(void *arg)
   int ret;
   int first_run=1;
 #else
-  unsigned int rx_cnt = 0;
-  unsigned int tx_cnt = tx_delay;
+  unsigned int rx_pos = 0;
+  unsigned int tx_pos;
+  int spp;
+  int tx_launched=0;
+ 
   //  int tx_offset;
   void *rxp[2],*txp[2];
   int i;
 
+  openair0_timestamp timestamp;
+
   //  int trace_cnt=0;
   hw_subframe = 0;
+  spp = openair0_cfg[0].samples_per_packet;
+  tx_pos = spp*tx_delay;
 #endif
 
   struct timespec trx_time0,trx_time1,trx_time2;
@@ -1512,7 +1411,6 @@ static void *eNB_thread(void *arg)
     while (sync_var<0)
       pthread_cond_wait(&sync_cond, &sync_mutex);
     pthread_mutex_unlock(&sync_mutex);
-    printf("starting eNB thread\n");
 
     while (!oai_exit) {
       start_meas(&softmodem_stats_mt);
@@ -1590,32 +1488,32 @@ static void *eNB_thread(void *arg)
 #else  // EXMIMO
       vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe);
       vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
-      while (rx_cnt < sf_bounds[hw_subframe]) {
+      tx_launched = 0;
+      while (rx_pos < ((1+hw_subframe)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti)) {
 
 	//	openair0_timestamp time0,time1;
 	unsigned int rxs;
 #ifndef USRP_DEBUG
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,1);
-
-	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_TXCNT,tx_cnt);
-	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_RXCNT,rx_cnt*samples_per_packets);
+	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_TXCNT,tx_pos);
+	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_RXCNT,rx_pos);
 
 
 	clock_gettime(CLOCK_MONOTONIC,&trx_time0);
 	for (i=0;i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx;i++)
-	  rxp[i] = (void*)&rxdata[i][rx_cnt*samples_per_packets];
+	  rxp[i] = (void*)&rxdata[i][rx_pos];
 	start_meas(&softmodem_stats_hw);
 	//	printf("rxp[0] %p\n",rxp[0]);
 
 	rxs = openair0.trx_read_func(&openair0, 
 				     &timestamp, 
 				     rxp, 
-				     samples_per_packets,
+				     spp,
 				     PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_rx);
 	stop_meas(&softmodem_stats_hw);
 	clock_gettime(CLOCK_MONOTONIC,&trx_time1);
 
-	if (rxs != samples_per_packets)
+	if (rxs != spp)
 	  exit_fun("problem receiving samples");
  
 
@@ -1625,15 +1523,20 @@ static void *eNB_thread(void *arg)
 	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,1);
 	
 	for (i=0;i<PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx;i++)
-	  txp[i] = (void*)&txdata[i][tx_cnt*samples_per_packets];
-		
-	openair0.trx_write_func(&openair0, 
-				(timestamp+samples_per_packets*tx_delay-tx_forward_nsamps), 
-				txp,
-				samples_per_packets, 
-				PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
-				1);
-	
+	  txp[i] = (void*)&txdata[i][tx_pos];
+	if (frame > 50) {
+	  openair0.trx_write_func(&openair0, 
+				  (timestamp+(tx_delay*spp)-tx_forward_nsamps), 
+				  txp,
+				  spp, 
+				  PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx,
+				  1);
+	}
+
+	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TS,timestamp&0xffffffff);
+	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_TRX_TST,(timestamp+(tx_delay*spp)-tx_forward_nsamps)&0xffffffff);
+
+
 	stop_meas(&softmodem_stats_mt);
 	clock_gettime(CLOCK_MONOTONIC,&trx_time2);
 
@@ -1645,7 +1548,9 @@ static void *eNB_thread(void *arg)
 #else
 	rt_sleep_ns(1000000);
 #endif
-	if (rx_cnt == sf_bounds_tx[hw_subframe]) {
+	if ((tx_launched == 0) && 
+	    (rx_pos >=(((2*hw_subframe)+1)*PHY_vars_eNB_g[0][0]->lte_frame_parms.samples_per_tti>>1))) {
+	  tx_launched = 1;
 	  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
 	    if (pthread_mutex_lock(&PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].mutex_tx) != 0) {
 	      LOG_E(PHY,"[eNB] ERROR pthread_mutex_lock for eNB TX thread %d (IC %d)\n",hw_subframe,PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].instance_cnt_tx);   
@@ -1660,21 +1565,22 @@ static void *eNB_thread(void *arg)
 		}
 	      }
 	      else {
-		LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (rx_cnt %d)\n",PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].frame_tx,hw_subframe,rx_cnt);
+		LOG_W(PHY,"[eNB] Frame %d, eNB TX thread %d busy!! (rx_cnt %d)\n",PHY_vars_eNB_g[0][CC_id]->proc[hw_subframe].frame_tx,hw_subframe,rx_pos);
 		exit_fun("nothing to add");
 	      }
 	    }
 	  }
 	}
-	rx_cnt++;
-	tx_cnt++;
+	rx_pos += spp;
+	tx_pos += spp;
 
-	if(tx_cnt == max_cnt)
-	  tx_cnt = 0;
+
+	if(tx_pos >= samples_per_frame)
+	  tx_pos -= samples_per_frame;
       }
 
-      if(rx_cnt == max_cnt)
-	rx_cnt = 0; 
+      if (rx_pos >= samples_per_frame)
+	rx_pos -= samples_per_frame; 
       
 
 #endif // USRP
@@ -1813,1277 +1719,116 @@ static void *eNB_thread(void *arg)
   return 0;
 }
 
-typedef enum {
-  pss=0,
-  pbch=1,
-  si=2
-} sync_mode_t;
-
-static void *UE_thread_synch(void *arg) {
-
-  int i,hw_slot_offset;
-  PHY_VARS_UE *UE = arg;
-  int current_band = 0;
-  int current_offset = 0;
-  sync_mode_t sync_mode = pss;
-
-#ifdef RTAI
-  RT_TASK *task = rt_task_init_schmod(nam2num("UEsync"), 0, 0, 0, SCHED_FIFO, 0xF);
-  if (task==NULL) {
-    LOG_E(PHY,"[SCHED][UE] Problem starting UE_sync_thread!!!!\n");
-    return 0;
-  }
-#endif 
 
-  UE->is_synchronized = 0;
-  printf("UE_thread_sync in with PHY_vars_UE %p\n",arg);
-  printf("waiting for sync (UE_thread_synch) \n");
-  pthread_mutex_lock(&sync_mutex);
-  printf("Locked sync_mutex, waiting (UE_sync_thread)\n");
-  while (sync_var<0)
-    pthread_cond_wait(&sync_cond, &sync_mutex);
-  pthread_mutex_unlock(&sync_mutex);
-  printf("unlocked sync_mutex (UE_sync_thread)\n");
-  printf("starting UE synch thread\n");
-  
-  if (UE_scan == 1) {
-    for (card=0;card<MAX_CARDS;card++) {
-      for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
-	downlink_frequency[card][i] = bands_to_scan.band_info[0].dl_min;
-	uplink_frequency_offset[card][i] = bands_to_scan.band_info[0].ul_min-bands_to_scan.band_info[0].dl_min;
-    
-	openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i];
-	openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i];
-	openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB-USRP_GAIN_OFFSET;  
+static void get_options (int argc, char **argv) {
+  int c;
+  //  char                          line[1000];
+  //  int                           l;
+  int k;//i,j,k;
 #ifdef USRP
-#ifndef USRP_DEBUG
-	openair0_set_rx_frequencies(&openair0,&openair0_cfg[0]);
-	openair0_set_gains(&openair0,&openair0_cfg[0]);
+  int clock_src;
 #endif
+  int CC_id;
+#ifdef EXMIMO
+  char rxg_fname[256], line[1000];
+  FILE *rxg_fd;
+  int l;
 #endif
-      }
-    }    
-    LOG_D(PHY,"[SCHED][UE] Scanning band %d, freq %u\n",bands_to_scan.band_info[0].band, bands_to_scan.band_info[0].dl_min);
-  }
-  else {
-    LOG_D(PHY,"[SCHED][UE] Check absolute frequency %u\n",downlink_frequency[0][0]);
-    sync_mode=pbch;
-  }
-  while (!oai_exit) {
-    
-    if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
-      LOG_E(PHY,"[SCHED][UE] error locking mutex for UE initial synch thread\n");
-      exit_fun("noting to add");
-    }
-    else {
-      while (UE->instance_cnt_synch < 0) {
-	pthread_cond_wait(&UE->cond_synch,&UE->mutex_synch);
-      }
-      if (pthread_mutex_unlock(&UE->mutex_synch) != 0) {	
-	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for UE Initial Synch thread\n");
-	exit_fun("nothing to add");
-      }
-    
-    }  // mutex_lock      
-    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,1); 
 
-    switch (sync_mode) {
-    case pss:
-	
 
 
-      current_offset += 20000000; // increase by 20 MHz
-      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
-	current_band++;
-	current_offset=0;
-      }
-      if (current_band==bands_to_scan.nbands) {
-	current_band=0;
-	oai_exit=1; 
-      }
+
+  const Enb_properties_array_t *enb_properties;
+  
+  enum long_option_e {
+    LONG_OPTION_START = 0x100, /* Start after regular single char options */
+    LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS,
+    LONG_OPTION_CALIB_UE_RX,
+    LONG_OPTION_CALIB_UE_RX_MED,
+    LONG_OPTION_CALIB_UE_RX_BYP,
+    LONG_OPTION_DEBUG_UE_PRACH,
+    LONG_OPTION_NO_L2_CONNECT
+  };
+  
+  static const struct option long_options[] = {
+    {"ulsch-max-errors",required_argument,  NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS},
+    {"calib-ue-rx",     required_argument,  NULL, LONG_OPTION_CALIB_UE_RX},
+    {"calib-ue-rx-med", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_MED},
+    {"calib-ue-rx-byp", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_BYP},
+    {"debug-ue-prach",  no_argument,        NULL, LONG_OPTION_DEBUG_UE_PRACH},
+    {"no-L2-connect",   no_argument,        NULL, LONG_OPTION_NO_L2_CONNECT},
+    {NULL, 0, NULL, 0}};
+  
+  while ((c = getopt_long (argc, argv, "C:dK:g:F:G:qO:m:SUVRM:r:P:s:t:x:",long_options,NULL)) != -1) {
+    switch (c) {
+    case LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS:
+      ULSCH_max_consecutive_errors = atoi(optarg);
+      printf("Set ULSCH_max_consecutive_errors = %d\n",ULSCH_max_consecutive_errors);
+      break;
       
-      for (card=0;card<MAX_CARDS;card++) {
-	for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
-	  downlink_frequency[card][i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
-	  uplink_frequency_offset[card][i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
-	  
-	  
-	  openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]+openair_daq_vars.freq_offset;
-	  openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]+openair_daq_vars.freq_offset;
-	  openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB-USRP_GAIN_OFFSET;  // 65 calibrated for USRP B210 @ 2.6 GHz
-#ifdef USRP
-#ifndef USRP_DEBUG
-	  openair0_set_rx_frequencies(&openair0,&openair0_cfg[0]);
-	  //	openair0_set_gains(&openair0,&openair0_cfg[0]);
-#endif
-#endif
-	}
-      }	
+    case LONG_OPTION_CALIB_UE_RX:
+      mode = rx_calib_ue;
+      rx_input_level_dBm = atoi(optarg);
+      printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm);
+      break;
       
+    case LONG_OPTION_CALIB_UE_RX_MED:
+      mode = rx_calib_ue_med;
+      rx_input_level_dBm = atoi(optarg);
+      printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm);
       break;
-    case pbch:
-
-      if (initial_sync(UE,mode)==0) {
-	/*
-	  lte_adjust_synch(&PHY_vars_UE_g[0]->lte_frame_parms,
-	  PHY_vars_UE_g[0],
-	  0,
-	  1,
-	  16384);
-	*/
-	//for better visualization afterwards
-	/*
-	  for (aa=0; aa<PHY_vars_UE_g[0]->lte_frame_parms.nb_antennas_rx; aa++)
-	  memset(PHY_vars_UE_g[0]->lte_ue_common_vars.rxdata[aa],0,
-	  PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int));
-	*/
-	
-	T0 = rt_get_time_ns();
-	
-	UE->is_synchronized = 1;
-#ifndef EXMIMO
-	UE->slot_rx = 0;
-	UE->slot_tx = 4;
-#else
-	UE->slot_rx = 18;
-	UE->slot_tx = 2;
+      
+    case LONG_OPTION_CALIB_UE_RX_BYP:
+      mode = rx_calib_ue_byp;
+      rx_input_level_dBm = atoi(optarg);
+      printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm);
+      break;
+      
+    case LONG_OPTION_DEBUG_UE_PRACH:
+      mode = debug_prach;
+      break;
+      
+    case LONG_OPTION_NO_L2_CONNECT:
+      mode = no_L2_connect;
+      break;
+    case 'M':
+#ifdef ETHERNET
+      strcpy(rrh_eNB_ip,optarg);
 #endif
-	hw_slot_offset = (UE->rx_offset<<1) / UE->lte_frame_parms.samples_per_tti;
-	LOG_I(HW,"Got synch: hw_slot_offset %d\n",hw_slot_offset);
-	  
+      break;
+    case 'C':
+      for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
+	downlink_frequency[CC_id][0] = atof(optarg); // Use float to avoid issue with frequency over 2^31.
+	downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
+	downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
+	downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
+	printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
       }
-      else {
-	  
-	if (openair_daq_vars.freq_offset >= 0) {
-	  openair_daq_vars.freq_offset += 100;
-	  openair_daq_vars.freq_offset *= -1;
-	}
-      else {
-	  openair_daq_vars.freq_offset *= -1;
-	}
-      if (abs(openair_daq_vars.freq_offset) > 7500) {
-	  LOG_I(PHY,"[initial_sync] No cell synchronization found, abandoning\n");
-	  mac_xface->macphy_exit("No cell synchronization found, abandoning");
-	}
-      else {
-	  LOG_I(PHY,"[initial_sync] trying carrier off %d Hz, rxgain %d\n",openair_daq_vars.freq_offset,
-		UE->rx_total_gain_dB);
-	  for (card=0;card<MAX_CARDS;card++) {
-	    for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
-	      openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]+openair_daq_vars.freq_offset;
-	      openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]+openair_daq_vars.freq_offset;
-	      openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB-USRP_GAIN_OFFSET;  // 65 calibrated for USRP B210 @ 2.6 GHz
-#ifdef USRP
-#ifndef USRP_DEBUG
-	      openair0_set_frequencies(&openair0,&openair0_cfg[0]);
-	      //	    openair0_set_gains(&openair0,&openair0_cfg[0]);
-#endif
-#endif
-	    }
-	  }
-	    
-	  //	    openair0_dump_config(&openair0_cfg[0],UE_flag);
-	
-	//	    rt_sleep_ns(FRAME_PERIOD);
-      } // freq_offset
-    } // initial_sync=0
-    
-  break;
- case si:
- default:
-break;
-}
-    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,0);  
-    printf("Finished synch : Locking synch mutex (thread_sync)\n");
-    if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
-      printf("[openair][SCHED][eNB] error locking mutex for UE synch\n");
-    }
-    else {
-      UE->instance_cnt_synch--;
+      UE_scan=0;
+      break;
       
-      if (pthread_mutex_unlock(&UE->mutex_synch) != 0) {	
-	printf("[openair][SCHED][eNB] error unlocking mutex for UE synch\n");
-      }
-    }
-    
-    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,0); 
-  }  // while !oai_exit
-  return(0);
-}
-
-static void *UE_thread_tx(void *arg) {
-
-#ifdef RTAI
-  RT_TASK *task;
-#else 
-#ifdef LOWLATENCY
-  struct sched_attr attr;
-  unsigned int flags = 0;
-#endif
+    case 'd':
+#ifdef XFORMS
+      do_forms=1;
+      printf("Running with XFORMS!\n");
 #endif
-  int ret;
-
-  PHY_VARS_UE *UE = (PHY_VARS_UE*)arg;
-
-  UE->instance_cnt_tx=-1;
-
-#ifdef RTAI
-  task = rt_task_init_schmod(nam2num("UETX"), 0, 0, 0, SCHED_FIFO, 0xF);
-  if (task==NULL) {
-    LOG_E(PHY,"[SCHED][UE] Problem starting UE_thread_TX!!!!\n");
-    return 0;
-  }
+      break;
+      
+    case 'K':
+#if defined(ENABLE_ITTI)
+      itti_dump_file = strdup(optarg);
 #else
-#ifdef LOWLATENCY
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-  
-  /* This creates a 1ms reservation every 10ms period*/
-  attr.sched_policy = SCHED_DEADLINE;
-  attr.sched_runtime = 1 * 500000;  // each tx thread requires .5ms to finish its job
-  attr.sched_deadline =1 * 1000000; // each tx thread will finish within 1ms
-  attr.sched_period = 1 * 1000000; // each tx thread has a period of 1ms from the starting point
-
-  
-  if (sched_setattr(0, &attr, flags) < 0 ){
-    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
-    exit(-1);
-  }
-#endif
+      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
 #endif
-
-  printf("waiting for sync (UE_thread_tx)\n");
-  pthread_mutex_lock(&sync_mutex);
-  printf("Locked sync_mutex, waiting (UE_thread_tx)\n");
-  while (sync_var<0)
-    pthread_cond_wait(&sync_cond, &sync_mutex);
-  pthread_mutex_unlock(&sync_mutex);
-  printf("unlocked sync_mutex, waiting (UE_thread_tx)\n");
-  printf("Starting UE TX thread\n");
-
-  mlockall(MCL_CURRENT | MCL_FUTURE);
-
-  while (!oai_exit) {
-
-    if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
-      LOG_E(PHY,"[SCHED][eNB] error locking mutex for UE TX\n");
-      exit_fun("nothing to add");
-    }
-    else {
-      
-      while (UE->instance_cnt_tx < 0) {
-	pthread_cond_wait(&UE->cond_tx,&UE->mutex_tx);
-      }
-      if (pthread_mutex_unlock(&UE->mutex_tx) != 0) {	
-	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for UE TX\n");
-	exit_fun("nothing to add");
-      }
-    }
-    
-    
-    if ((subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1)==SF_UL)){
-      phy_procedures_UE_TX(UE,eNB_id,0,mode,no_relay);
-    }
-    if ((subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1)==SF_S) &&
-	((UE->slot_tx&1)==1)) {
-      phy_procedures_UE_S_TX(UE,eNB_id,0,no_relay);
-    }
-    
-    
-    if (UE->lte_frame_parms.frame_type == TDD) {
+      break;
       
-      ret = mac_xface->ue_scheduler(UE->Mod_id, 
-				    UE->frame_tx,
-				    UE->slot_rx>>1, 
-				    subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1),
-				    eNB_id);
+    case 'O':
+      conf_config_file_name = optarg;
+      break;
       
-      if (ret == CONNECTION_LOST) {
-	LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",UE->Mod_id,
-	      UE->frame_rx,UE->slot_tx>>1);
-	UE->UE_mode[eNB_id] = PRACH;
-	//      mac_xface->macphy_exit("Connection lost");
-      }
-      else if (ret == PHY_RESYNCH) {
-	LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n",
-	      UE->Mod_id,
-	      UE->frame_rx,UE->slot_tx>>1);
-	UE->UE_mode[eNB_id] = RESYNCH;
-	//     mac_xface->macphy_exit("Connection lost");
-	//exit(-1);
-      } else if (ret == PHY_HO_PRACH) {
-	LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n",
-	      UE->Mod_id,UE->frame_rx,UE->slot_tx>>1);
-	UE->UE_mode[eNB_id] = PRACH;
-      }
-    }
-    
-    
-    if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
-      printf("[openair][SCHED][eNB] error locking mutex for UE TX thread\n");
-    }
-    else {
-      UE->instance_cnt_tx--;
-      
-      if (pthread_mutex_unlock(&UE->mutex_tx) != 0) {	
-	printf("[openair][SCHED][eNB] error unlocking mutex for UE\n");
-      }
-    }
-    
-    UE->slot_tx+=2;
-    if (UE->slot_tx>=20) {
-      UE->slot_tx-=20;
-      UE->frame_tx++;
-      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_UE, UE->frame_tx);
-    }
-    vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_UE, UE->slot_tx>>1);
-  }
-  return(0);
-}
-
-static void *UE_thread_rx(void *arg) {
-  
-  PHY_VARS_UE *UE = (PHY_VARS_UE*)arg;
-  int i;
-  int ret;
-  
-#ifdef RTAI
-  RT_TASK *task;
-#else 
-#ifdef LOWLATENCY
-  struct sched_attr attr;
-  unsigned int flags = 0;
-#endif
-#endif
-  
-  UE->instance_cnt_rx=-1;
-
-#ifdef RTAI
-  task = rt_task_init_schmod(nam2num("UERX"), 0, 0, 0, SCHED_FIFO, 0xF);
-  if (task==NULL) {
-    LOG_E(PHY,"[SCHED][UE] Problem starting UE_thread_RX!!!!\n");
-    return 0;
-  }
-#else
-#ifdef LOWLATENCY
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-  
-  // This creates a 1ms reservation every 10ms period
-  attr.sched_policy = SCHED_DEADLINE;
-  attr.sched_runtime = 1 * 800000;  // each rx thread requires 1ms to finish its job
-  attr.sched_deadline =1 * 1000000; // each rx thread will finish within 1ms
-  attr.sched_period = 1 * 1000000; // each rx thread has a period of 1ms from the starting point
-  
-  if (sched_setattr(0, &attr, flags) < 0 ){
-    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
-    exit(-1);
-  }  
-#endif
-#endif
-  
-  mlockall(MCL_CURRENT | MCL_FUTURE);
-  
-  printf("waiting for sync (UE_thread_rx)\n");
-  pthread_mutex_lock(&sync_mutex);
-  printf("Locked sync_mutex, waiting (UE_thread_rx)\n");
-  while (sync_var<0)
-    pthread_cond_wait(&sync_cond, &sync_mutex);
-  pthread_mutex_unlock(&sync_mutex);
-  printf("unlocked sync_mutex, waiting (UE_thread_rx)\n");
-  printf("Starting UE RX thread\n");
-  
-  while (!oai_exit) { 
-    //   printf("UE_thread_rx: locking UE RX mutex\n");
-    if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
-      LOG_E(PHY,"[SCHED][eNB] error locking mutex for UE RX\n");
-      exit_fun("nothing to add");
-    }
-    else {
-      
-      while (UE->instance_cnt_rx < 0) {
-	pthread_cond_wait(&UE->cond_rx,&UE->mutex_rx);
-      }
-      if (pthread_mutex_unlock(&UE->mutex_rx) != 0) {	
-	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for UE RX\n");
-	exit_fun("nothing to add");
-      }
-      
-      for (i=0;i<2;i++) {
-	if ((subframe_select(&UE->lte_frame_parms,UE->slot_rx>>1)==SF_DL) |
-            (UE->lte_frame_parms.frame_type == FDD)) {
-	  phy_procedures_UE_RX(UE,eNB_id,0,mode,no_relay,NULL);
-	}
-	if ((subframe_select(&UE->lte_frame_parms,UE->slot_rx>>1)==SF_S) &&
-	    ((UE->slot_rx&1)==0)) {
-	  phy_procedures_UE_RX(UE,eNB_id,0,mode,no_relay,NULL);
-	}
-      	
-	if (i==0) {
-	  ret = mac_xface->ue_scheduler(UE->Mod_id, 
-					UE->frame_tx,
-					UE->slot_rx>>1,
-					subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1),
-					eNB_id);
-	  
-	  if (ret == CONNECTION_LOST) {
-	    LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",UE->Mod_id,
-		  UE->frame_rx,UE->slot_tx>>1);
-	    UE->UE_mode[eNB_id] = PRACH;
-	    //      mac_xface->macphy_exit("Connection lost");
-	  }
-	  else if (ret == PHY_RESYNCH) {
-	    LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n",
-		  UE->Mod_id,
-		  UE->frame_rx,UE->slot_tx>>1);
-	    UE->UE_mode[eNB_id] = RESYNCH;
-	    //     mac_xface->macphy_exit("Connection lost");
-	    //exit(-1);
-	  } 
-	  else if (ret == PHY_HO_PRACH) {
-	    LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n",
-		  UE->Mod_id,UE->frame_rx,UE->slot_tx>>1);
-	    UE->UE_mode[eNB_id] = PRACH;
-	  }
-	}	  
-	
-	UE->slot_rx++;
-	
-	if (UE->slot_rx==20) {
-	UE->slot_rx=0;
-	UE->frame_rx++;
-	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_UE, UE->frame_rx);
-      } 
-	
-      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_UE, UE->slot_rx>>1);
-      
-	}
-	
-	if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
-	printf("[openair][SCHED][eNB] error locking mutex for UE RX\n");
-      }
-	else {
-	UE->instance_cnt_rx--;
-	
-	if (pthread_mutex_unlock(&UE->mutex_rx) != 0) {	
-	printf("[openair][SCHED][eNB] error unlocking mutex for UE RX\n");
-      }
-      }
-	//    printf("UE_thread_rx done\n");
-      }
-      }      
-	return(0);
-      }
-    
-
-
-
-#ifndef EXMIMO
-#define RX_OFF_MAX 10
-#define RX_OFF_MIN 5
-#define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2)
-
-static void *UE_thread(void *arg) {
-
-  PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
-  LTE_DL_FRAME_PARMS *frame_parms=&UE->lte_frame_parms;
-
-  int slot=1,frame=0,hw_subframe=0,rx_cnt=0,tx_cnt=0;
-  // unsigned int aa;
-  int dummy[2][samples_per_packets];
-  int dummy_dump = 0;
-  int tx_enabled=0;
-  int start_rx_stream=0;
-  int rx_off_diff = 0;
-  int rx_correction_timer = 0;
-  int i;
-
-  unsigned int rxs;
-  void *rxp[2],*txp[2];
-
-#ifdef RTAI
-  RT_TASK *task;
-#else 
-  /*
-#ifdef LOWLATENCY
-  struct sched_attr attr;
-  unsigned int flags = 0;
-    unsigned long mask = 1; // processor 0 
-#endif
-  */
-#endif
-
-  printf("waiting for sync (UE_thread)\n");
-  pthread_mutex_lock(&sync_mutex);
-  printf("Locked sync_mutex, waiting (UE_thread)\n");
-  while (sync_var<0)
-    pthread_cond_wait(&sync_cond, &sync_mutex);
-  pthread_mutex_unlock(&sync_mutex);
-  printf("unlocked sync_mutex, waiting (UE_thread)\n");
-  printf("starting UE thread\n");
-
-#ifdef RTAI
-  task = rt_task_init_schmod(nam2num("UEmain"), 0, 0, 0, SCHED_FIFO, 0xF);
-  if (task==NULL) {
-    LOG_E(PHY,"[SCHED][UE] Problem starting main UE_thread!!!!\n");
-    return 0;
-  }
-#else
-  /*
-#ifdef LOWLATENCY
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-   
-    // This creates a .5 ms  reservation
-  attr.sched_policy = SCHED_DEADLINE;
-  attr.sched_runtime  = 0.5 * 1000000;
-  attr.sched_deadline = 0.5 * 1000000;
-  attr.sched_period   = 1   * 1000000;
-   
-    // pin the UE main thread to CPU0
-    // if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) <0) {
-    //   perror("[MAIN_ENB_THREAD] pthread_setaffinity_np failed\n");
-    //   }
-   
-  if (sched_setattr(0, &attr, flags) < 0 ){
-    perror("[SCHED] main eNB thread: sched_setattr failed\n");
-    exit_fun("Nothing to add");
-  } else {
-    LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n",
-	  gettid(),sched_getcpu());
-  }
-#endif
-  */
-#endif
-
-  mlockall(MCL_CURRENT | MCL_FUTURE);
-
-  T0 = rt_get_time_ns();
-  while (!oai_exit) {
-    vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe);
-    vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
-
-
-    while (rx_cnt < sf_bounds[hw_subframe]) {
-  
-      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,1);
-  
-#ifndef USRP_DEBUG
-
-      for (i=0;i<UE->lte_frame_parms.nb_antennas_rx;i++)
-	rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rx_cnt*samples_per_packets] : (void*)dummy[i];
-      rxs = openair0.trx_read_func(&openair0,
-				   &timestamp,
-				   rxp,
-				   samples_per_packets - ((rx_cnt==0) ? rx_off_diff : 0),
-				   UE->lte_frame_parms.nb_antennas_rx);
-      if (rxs != (samples_per_packets- ((rx_cnt==0) ? rx_off_diff : 0)))
-	exit_fun("problem in rx");
-
-      rx_off_diff = 0;
-      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,0);
-      
-      // Transmit TX buffer based on timestamp from RX
-      if (tx_enabled) {
-	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,1);
-	for (i=0;i<UE->lte_frame_parms.nb_antennas_tx;i++)
-	  txp[i] = (void*)&txdata[i][tx_cnt*samples_per_packets];
-	openair0.trx_write_func(&openair0,
-				(timestamp+samples_per_packets*tx_delay-tx_forward_nsamps),
-				txp,
-				samples_per_packets,
-				UE->lte_frame_parms.nb_antennas_tx,
-				1);
-				
-	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
-      }
-#else
-      rt_sleep_ns(1000000);
-#endif
-      rx_cnt++;
-      tx_cnt++;
-      
-      if(tx_cnt == max_cnt)
-	tx_cnt = 0;
-    }
-    
-    if(rx_cnt == max_cnt)
-      rx_cnt = 0;
-
-
-    
-    if (UE->is_synchronized==1)  {
-      LOG_D(HW,"UE_thread: hw_frame %d, hw_subframe %d (time %llu)\n",frame,hw_subframe,rt_get_time_ns()-T0);
-
-      if (start_rx_stream==1) {
-	//	printf("UE_thread: locking UE mutex_rx\n");
-	if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
-	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE RX thread\n");
-	  exit_fun("nothing to add");
-	}
-	else {
- 	  
-	  UE->instance_cnt_rx++;
-	  //	  printf("UE_thread: Unlocking UE mutex_rx\n");
-	  pthread_mutex_unlock(&UE->mutex_rx);
-	  if (UE->instance_cnt_rx == 0) {
-	    // LOG_D(HW,"Scheduling UE RX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_rx,frame,hw_subframe,UE->slot_rx>>1,mode);
-	    if (pthread_cond_signal(&UE->cond_rx) != 0) {
-	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n");
-	      exit_fun("nothing to add");
-	    }
-	    else {
-	      //	      printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
-	    }
-	    if (mode == rx_calib_ue) {
-	      if (frame == 10) {
-		LOG_D(PHY,"[SCHED][UE] Found cell with N_RB_DL %d, PHICH CONFIG (%d,%d), Nid_cell %d, NB_ANTENNAS_TX %d, initial frequency offset %d Hz, frequency offset %d Hz, RSSI (digital) %d dB, measured Gain %d dB, total_rx_gain %d dB, USRP rx gain %f dB\n",
-		      UE->lte_frame_parms.N_RB_DL,
-		      UE->lte_frame_parms.phich_config_common.phich_duration,
-		      UE->lte_frame_parms.phich_config_common.phich_resource,
-		      UE->lte_frame_parms.Nid_cell,
-		      UE->lte_frame_parms.nb_antennas_tx_eNB,
-		      openair_daq_vars.freq_offset,
-		      UE->lte_ue_common_vars.freq_offset,
-		      UE->PHY_measurements.rx_power_avg_dB[0],
-		      UE->PHY_measurements.rx_power_avg_dB[0] - rx_input_level_dBm,
-		      UE->rx_total_gain_dB,
-		      openair0_cfg[0].rx_gain[0]
-		      );
-		exit_fun("[HW][UE] UE in RX calibration mode, exiting");
-	      }
-	    }
-	  }
-	  else {
-	    LOG_E(PHY,"[SCHED][UE] UE RX thread busy!!\n");
-	    exit_fun("nothing to add");
-	  }
-	}
-      }
-    }
-    else {  // we are not yet synchronized
-      
-      if ((hw_subframe == 9)&&(dummy_dump == 0)) {
-	// Wake up initial synch thread
-	if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
-	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE initial synch thread\n");
-	  exit_fun("nothing to add");
-	}
-	else {
-	  
-	  UE->instance_cnt_synch++;
-	  pthread_mutex_unlock(&UE->mutex_synch);
-	  dummy_dump = 1;
-	  if (UE->instance_cnt_synch == 0) {
-	    if (pthread_cond_signal(&UE->cond_synch) != 0) {
-	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n");
-	      exit_fun("nothing to add");
-	    }
-	  }
-	  else {
-	    LOG_E(PHY,"[SCHED][UE] UE sync thread busy!!\n");
-	    exit_fun("nothing to add");
-	  }
-	}
-      }
-    }
-    
-    hw_subframe++;
-    slot+=2;
-    if(hw_subframe==10) {
-      hw_subframe = 0;
-      frame++;
-      slot = 1;
-      if (UE->instance_cnt_synch < 0) {
-	if (UE->is_synchronized == 1) {
-	  //	  openair0_set_gains(&openair0,&openair0_cfg[0]);
-	  rx_off_diff = 0;
-	  //	  LOG_D(PHY,"HW RESYNC: hw_frame %d: rx_offset = %d\n",frame,UE->rx_offset);
-	  if ((UE->rx_offset > RX_OFF_MAX)&&(start_rx_stream==0)) {
-	    start_rx_stream=1;
-	    //LOG_D(PHY,"HW RESYNC: hw_frame %d: Resynchronizing sample stream\n");
-	    frame=0;
-	    // dump ahead in time to start of frame
-#ifndef USRP_DEBUG
-	    rxs = openair0.trx_read_func(&openair0,
-					 &timestamp,
-					 (void**)rxdata,
-					 UE->rx_offset,
-					 UE->lte_frame_parms.nb_antennas_rx);
-#else
-	    rt_sleep_ns(10000000);
-#endif
-	    UE->rx_offset=0;
-	  }
-	  else if ((UE->rx_offset < RX_OFF_MIN)&&(start_rx_stream==1)) {
-	    //	    rx_off_diff = -UE->rx_offset + RX_OFF_MIN;
-	  }
-	  else if ((UE->rx_offset > (FRAME_LENGTH_COMPLEX_SAMPLES-RX_OFF_MAX)) &&(start_rx_stream==1) && (rx_correction_timer == 0)) {
-	    rx_off_diff = FRAME_LENGTH_COMPLEX_SAMPLES-UE->rx_offset;
-	    rx_correction_timer = 5;
-	  }
-	  if (rx_correction_timer>0)
-	    rx_correction_timer--;
-	  //	  LOG_D(PHY,"HW RESYNC: hw_frame %d: Correction: rx_off_diff %d (timer %d)\n",frame,rx_off_diff,rx_correction_timer);
-	}
-	dummy_dump=0;
-      }
-    }
-    
-#if defined(ENABLE_ITTI)
-    itti_update_lte_time(frame, slot);
-#endif
-  }
-  return(0);
-}
-#endif //#ifndef EXMIMO
-
-
-
-#ifdef EXMIMO
-/* This is the main UE thread. Initially it is doing a periodic get_frame. One synchronized it gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */
-static void *UE_thread(void *arg) {
-  PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
-#ifdef RTAI
-  RT_TASK *task;
-#endif
-  // RTIME in, out, diff;
-  int slot=0,frame=0,hw_slot,last_slot,next_slot;
-  // unsigned int aa;
-  int delay_cnt;
-  RTIME time_in;
-  int hw_slot_offset=0,rx_offset_mbox=0,mbox_target=0,mbox_current=0;
-  int diff2;
-  int i, ret;
-  int CC_id,card;
-  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
-
-  int wait_sync_cnt = 0;
-  int first_synch = 1;
-#ifdef LOWLATENCY
-  struct sched_attr attr;
-  unsigned int flags = 0;
-  unsigned long mask = 1; // processor 0 
-#endif
-
-  printf("waiting for sync (UE_thread)\n");
-  pthread_mutex_lock(&sync_mutex);
-  printf("Locked sync_mutex, waiting (UE_thread)\n");
-  while (sync_var<0)
-    pthread_cond_wait(&sync_cond, &sync_mutex);
-  pthread_mutex_unlock(&sync_mutex);
-  printf("unlocked sync_mutex, waiting (UE_thread)\n");
-  printf("starting UE thread\n");
-  
-#if defined(ENABLE_ITTI) && defined(ENABLE_USE_MME)
-  /* Wait for NAS UE to start cell selection */
-  wait_system_ready ("Waiting for UE to be activated by UserProcess %s\r", &start_UE);
-#endif
-
-#ifdef RTAI
-  task = rt_task_init_schmod(nam2num("UEmain"), 0, 0, 0, SCHED_FIFO, 0xF);
-  LOG_D(HW,"Started UE thread (id %p)\n",task);
-#endif
-
-#ifdef HARD_RT
-  rt_make_hard_real_time();
-#endif
-
-
-#ifdef LOWLATENCY
-  attr.size = sizeof(attr);
-  attr.sched_flags = 0;
-  attr.sched_nice = 0;
-  attr.sched_priority = 0;
-  
-  // This creates a .25 ms  reservation
-  attr.sched_policy = SCHED_DEADLINE;
-  attr.sched_runtime  = 0.25 * 1000000;
-  attr.sched_deadline = 0.25 * 1000000;
-  attr.sched_period   = 0.5 * 1000000;
-  
-  // pin the UE main thread to CPU0
-  // if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) <0) {
-  //   perror("[MAIN_ENB_THREAD] pthread_setaffinity_np failed\n");
-  //   }
-  
-  if (sched_setattr(0, &attr, flags) < 0 ){
-    perror("[SCHED] main UE thread: sched_setattr failed\n");
-    exit_fun("Nothing to add");
-  } else {
-    LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n",
-	  gettid(),sched_getcpu());
-  }
-#endif
-  
-
-  mlockall(MCL_CURRENT | MCL_FUTURE);
-
-  openair_daq_vars.freq_offset = 0; //-7500;
-
-  first_synch = 1;
-
-  while (!oai_exit)  {
-
-    hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; //the slot the hw is about to store
-
-     
-    if (UE->is_synchronized) {
-
-      if (first_synch == 1) {
-	first_synch = 0;
-	for (card=0;card<openair0_num_detected_cards;card++)
-          openair0_start_rt_acquisition(card);
-	rt_sleep_ns(FRAME_PERIOD/10);
-      }
-
-      //this is the mbox counter that indicates the start of the frame
-      rx_offset_mbox = (UE->rx_offset * 150) / (10*UE->lte_frame_parms.samples_per_tti);
-      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_UE_RX_OFFSET, UE->rx_offset);
-      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_UE_OFFSET_MBOX, rx_offset_mbox);
-      //this is the mbox counter where we should be
-      mbox_target = (((((slot+1)%20)*15+1)>>1) + rx_offset_mbox + 1)%150;
-      // round up to the next multiple of two (mbox counter from express MIMO gives only even numbers)
-      mbox_target = ((mbox_target+1)-((mbox_target-1)%2))%150;
-      //this is the mbox counter where we are
-      mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
-      //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD)
-      if ((mbox_current>=120) && (mbox_target<30)) //handle the frame wrap-arround
-	diff2 = 150-mbox_current+mbox_target;
-      else if ((mbox_current<30) && (mbox_target>=120))
-	diff2 = -150+mbox_target-mbox_current;
-      else
-	diff2 = mbox_target - mbox_current;
-	
-      if (diff2 <(-7)) {
-	LOG_D(HW,"UE Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, slot, hw_slot, diff2);
-	if (frame>0){
-	  if (exit_missed_slots==1)
-	    exit_fun("[HW][UE] missed slot");
-	  else{
-	    num_missed_slots++;
-	    LOG_W(HW,"[UE] just missed slot (total missed slots %ld)\n", num_missed_slots);
-	  }
-	}
-        slot++;
-        if (slot==20) {
-          slot=0;
-          frame++;
-        }
-	// update thread slot/frame counters because of skipped slot
-	UE->slot_rx++;
-	UE->slot_tx++;
-	
-	if (UE->slot_rx == 20) {
-	  UE->slot_rx = 0;
-	  UE->frame_rx++;
-	}
-	if (UE->slot_tx == 20) {
-	  UE->slot_tx = 0;
-	  UE->frame_tx++;
-	}
-	continue;
-      }
-      if (diff2>8)
-	LOG_D(HW,"UE Frame %d: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, slot, hw_slot, mbox_current, mbox_target, diff2);
-	
-	
-      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
-      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff2);
-	
-
-
-      // This loop implements the delay of 1 slot to allow for processing
-      delay_cnt = 0;
-      while ((diff2>0) && (!oai_exit) )  {
-        time_in = rt_get_time_ns();
-        //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d (%d), diff %d, time %llu\n",frame,delay_cnt,hw_slot,((volatile unsigned int *)DAQ_MBOX)[0],slot,mbox_target,diff2,time_in);
-        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
-        vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
-        ret = rt_sleep_ns(diff2*DAQ_PERIOD);
-        vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0);
-        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
-        if (ret)
-          LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
-          
-        hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
-        //LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns());
-        delay_cnt++;
-        if (delay_cnt == 30)  {
-          LOG_D(HW,"UE frame %d: HW stopped ... \n",frame);
-          exit_fun("[HW][UE] HW stopped");
-        }
-        mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
-        if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
-          diff2 = 150-mbox_current+mbox_target;
-        else if ((mbox_current<15) && (mbox_target>=135))
-          diff2 = -150+mbox_target-mbox_current;
-        else
-          diff2 = mbox_target - mbox_current;
-          
-        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
-        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff2);
-      }
-
-      // on even slots, schedule processing of entire subframe
-      if ((slot&1) == 0)  {
-	
-	if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
-	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE RX thread\n");
-	  exit_fun("nothing to add");
-	}
-	else {
-	  
-	  UE->instance_cnt_rx++;
-	  //printf("UE_thread: Unlocking UE mutex_rx\n");
-	  pthread_mutex_unlock(&UE->mutex_rx);
-	  if (UE->instance_cnt_rx == 0) {
-	    LOG_D(HW,"Scheduling UE RX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_rx,frame,slot>>1,UE->slot_rx>>1,mode);
-	    if (pthread_cond_signal(&UE->cond_rx) != 0) {
-	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n");
-	      exit_fun("nothing to add");
-	    }
-	    else {
-	      //	      printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
-	    }
-	    if (mode == rx_calib_ue) {
-	      if (frame == 10) {
-		LOG_D(PHY,"[SCHED][UE] Found cell with N_RB_DL %d, PHICH CONFIG (%d,%d), Nid_cell %d, NB_ANTENNAS_TX %d, initial frequency offset %d Hz, frequency offset %d Hz, RSSI (digital) %d dB, measured Gain %d dB, total_rx_gain %d dB, USRP rx gain %f dB\n",
-		      UE->lte_frame_parms.N_RB_DL,
-		      UE->lte_frame_parms.phich_config_common.phich_duration,
-		      UE->lte_frame_parms.phich_config_common.phich_resource,
-		      UE->lte_frame_parms.Nid_cell,
-		      UE->lte_frame_parms.nb_antennas_tx_eNB,
-		      openair_daq_vars.freq_offset,
-		      UE->lte_ue_common_vars.freq_offset,
-		      UE->PHY_measurements.rx_power_avg_dB[0],
-		      UE->PHY_measurements.rx_power_avg_dB[0] - rx_input_level_dBm,
-		      UE->rx_total_gain_dB,
-		      openair0_cfg[0].rx_gain[0]
-		      );
-		exit_fun("[HW][UE] UE in RX calibration mode, exiting");
-	      }
-	    }
-	  }
-	  else {
-	    LOG_E(PHY,"[SCHED][UE] UE RX thread busy!!\n");
-	    exit_fun("nothing to add");
-	  }
-	}
-
-	if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
-	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE TX thread\n");
-	  exit_fun("nothing to add");
-	}
-	else {
-	  
-	  UE->instance_cnt_tx++;
-	  //printf("UE_thread: Unlocking UE mutex_rx\n");
-	  pthread_mutex_unlock(&UE->mutex_tx);
-	  if (UE->instance_cnt_tx == 0) {
-	    LOG_D(HW,"Scheduling UE TX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_tx,frame,slot>>1,UE->slot_tx>>1,mode);
-	    if (pthread_cond_signal(&UE->cond_tx) != 0) {
-	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE TX thread\n");
-	      exit_fun("nothing to add");
-	    }
-	    else {
-	      //	      printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
-	    }
-	  }
-	  else {
-	    LOG_E(PHY,"[SCHED][UE] UE TX thread busy!!\n");
-	    exit_fun("nothing to add");
-	  }
-	}
-      }
-
-      /*
-	if ((slot%2000)<10)
-	LOG_D(HW,"fun0: doing very hard work\n");
-      */
-      // now increment slot and frame counters
-      slot++;
-      if (slot==20) {
-	slot=0;
-	frame++;
-      }
-    }	
-    else if (UE->is_synchronized == 0) {  // we are not yet synchronized
-      hw_slot_offset = 0;
-      first_synch = 1;
-      slot = 0;
-
-
-      // wait until we can lock mutex_synch
-      if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
-	LOG_E(PHY,"[SCHED][UE] error locking mutex for UE initial synch thread\n");
-	exit_fun("noting to add");
-      }
-      else {
-	if (UE->instance_cnt_synch < 0) {
-
-	  wait_sync_cnt=0;
-	  openair0_get_frame(0);
-	  // increment instance count for sync thread
-	  UE->instance_cnt_synch++;
-	  pthread_mutex_unlock(&UE->mutex_synch);
-	  if (pthread_cond_signal(&UE->cond_synch) != 0) {
-	    LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n");
-	    exit_fun("nothing to add");
-	  }
-	}
-	else {
-	  wait_sync_cnt++;
-	  pthread_mutex_unlock(&UE->mutex_synch);
-	  if (wait_sync_cnt>1000)
-	    exit_fun("waiting to long for synch thread");
-	  else
-	    rt_sleep_ns(FRAME_PERIOD);
-	}
-      }	  
-
-      
-      /*            
-		    if (initial_sync(UE,mode)==0) {
-
-		    if (mode == rx_calib_ue) {
-		    exit_fun("[HW][UE] UE in RX calibration mode");
-		    }
-		    else {
-		    is_synchronized = 1;
-		    //start the streaming DMA transfers
-		    for (card=0;card<openair0_num_detected_cards;card++)
-		    openair0_start_rt_acquisition(card);
-	  
-		    hw_slot_offset = (UE->rx_offset<<1) / UE->lte_frame_parms.samples_per_tti;
-		    }
-		    }
-		    else {
-		    if (openair_daq_vars.freq_offset >= 0) {
-		    openair_daq_vars.freq_offset += 100;
-		    openair_daq_vars.freq_offset *= -1;
-		    }
-		    else {
-		    openair_daq_vars.freq_offset *= -1;
-		    }
-		    if (abs(openair_daq_vars.freq_offset) > 7500) {
-		    LOG_I(PHY,"[initial_sync] No cell synchronization found, abondoning\n");
-		    mac_xface->macphy_exit("No cell synchronization found, abondoning");
-		    }
-		    else {
-		    //	  LOG_I(PHY,"[initial_sync] trying carrier off %d Hz\n",openair_daq_vars.freq_offset);
-		    #ifndef USRP
-		    for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
-		    for (i=0; i<openair0_cfg[rf_map[CC_id].card].rx_num_channels; i++) 
-		    openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+openair_daq_vars.freq_offset;
-		    for (i=0; i<openair0_cfg[rf_map[CC_id].card].tx_num_channels; i++) 
-		    openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+openair_daq_vars.freq_offset;
-		    }
-		    openair0_config(&openair0_cfg[0],UE_flag);
-		    #endif
-		    rt_sleep_ns(FRAME_PERIOD);
-		    }
-		    }
-      */
-    }
-  }
-
-  LOG_D(HW,"UE_thread: finished, ran %d times.\n",frame);
-  
-#ifdef HARD_RT
-  rt_make_soft_real_time();
-#endif
-  
-  // clean task
-#ifdef RTAI
-  rt_task_delete(task);
-#endif
-  LOG_D(HW,"Task deleted. returning\n");
-  return 0;
-}
-
-#else  // This is for USRP or ETHERNET targets
-
-#endif
-
-
-void init_UE_threads(void) {
-  
-  PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
-
-  pthread_attr_init(&attr_UE_thread_tx);
-  pthread_attr_setstacksize(&attr_UE_thread_tx,16*PTHREAD_STACK_MIN);
-  sched_param_UE_thread_tx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
-  pthread_attr_setschedparam  (&attr_UE_thread_tx, &sched_param_UE_thread_tx);
-  pthread_attr_setschedpolicy (&attr_UE_thread_tx, SCHED_FIFO);
-
-  pthread_attr_init(&attr_UE_thread_rx);
-  pthread_attr_setstacksize(&attr_UE_thread_rx,8*PTHREAD_STACK_MIN);
-  sched_param_UE_thread_rx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
-  pthread_attr_setschedparam  (&attr_UE_thread_rx, &sched_param_UE_thread_rx);
-  pthread_attr_setschedpolicy (&attr_UE_thread_rx, SCHED_FIFO);
-
-  UE->instance_cnt_tx=-1;
-  UE->instance_cnt_rx=-1;
-  UE->instance_cnt_synch=-1;
-  pthread_mutex_init(&UE->mutex_tx,NULL);
-  pthread_mutex_init(&UE->mutex_rx,NULL);
-  pthread_mutex_init(&UE->mutex_synch,NULL);
-  pthread_cond_init(&UE->cond_tx,NULL);
-  pthread_cond_init(&UE->cond_rx,NULL);
-  pthread_cond_init(&UE->cond_synch,NULL);
-  pthread_create(&UE->thread_tx,NULL,UE_thread_tx,(void*)UE);
-  pthread_create(&UE->thread_rx,NULL,UE_thread_rx,(void*)UE);
-  pthread_create(&UE->thread_rx,NULL,UE_thread_synch,(void*)UE);
-  UE->frame_tx = 0;
-  UE->frame_rx = 0;
-
-  
-}
-
-
-void fill_ue_band_info() {
-
-  UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
-  int i,j;
-
-  bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
-  
-  for (i=0;i<bands_to_scan.nbands;i++) {
-
-    for (j=0;j<sizeof (eutra_bands) / sizeof (eutra_bands[0]);j++)
-      if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
-	memcpy(&bands_to_scan.band_info[i],
-	       &eutra_bands[j],
-	       sizeof(eutra_band_t));
-	
-	printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
-	       bands_to_scan.band_info[i].band,
-	       UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
-	       bands_to_scan.band_info[i].dl_min,
-	       bands_to_scan.band_info[i].dl_max,
-	       bands_to_scan.band_info[i].ul_min,
-	       bands_to_scan.band_info[i].ul_max,
-	       (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
-	break;
-      }
-  }
-}
-static void get_options (int argc, char **argv) {
-  int c;
-  //  char                          line[1000];
-  //  int                           l;
-  int k;//i,j,k;
-#ifdef USRP
-  int clock_src;
-#endif
-  int CC_id;
-#ifdef EXMIMO
-  char rxg_fname[256], line[1000];
-  FILE *rxg_fd;
-  int l;
-#endif
-
-
-
-
-  const Enb_properties_array_t *enb_properties;
-  
-  enum long_option_e {
-    LONG_OPTION_START = 0x100, /* Start after regular single char options */
-    LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS,
-    LONG_OPTION_CALIB_UE_RX,
-    LONG_OPTION_CALIB_UE_RX_MED,
-    LONG_OPTION_CALIB_UE_RX_BYP,
-    LONG_OPTION_DEBUG_UE_PRACH,
-    LONG_OPTION_NO_L2_CONNECT
-  };
-  
-  static const struct option long_options[] = {
-    {"ulsch-max-errors",required_argument,  NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS},
-    {"calib-ue-rx",     required_argument,  NULL, LONG_OPTION_CALIB_UE_RX},
-    {"calib-ue-rx-med", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_MED},
-    {"calib-ue-rx-byp", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_BYP},
-    {"debug-ue-prach",  no_argument,        NULL, LONG_OPTION_DEBUG_UE_PRACH},
-    {"no-L2-connect",   no_argument,        NULL, LONG_OPTION_NO_L2_CONNECT},
-    {NULL, 0, NULL, 0}};
-  
-  while ((c = getopt_long (argc, argv, "C:dK:g:F:G:qO:m:SUVRM:r:P:s:t:x:",long_options,NULL)) != -1) {
-    switch (c) {
-    case LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS:
-      ULSCH_max_consecutive_errors = atoi(optarg);
-      printf("Set ULSCH_max_consecutive_errors = %d\n",ULSCH_max_consecutive_errors);
-      break;
-      
-    case LONG_OPTION_CALIB_UE_RX:
-      mode = rx_calib_ue;
-      rx_input_level_dBm = atoi(optarg);
-      printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm);
-      break;
-      
-    case LONG_OPTION_CALIB_UE_RX_MED:
-      mode = rx_calib_ue_med;
-      rx_input_level_dBm = atoi(optarg);
-      printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm);
-      break;
-      
-    case LONG_OPTION_CALIB_UE_RX_BYP:
-      mode = rx_calib_ue_byp;
-      rx_input_level_dBm = atoi(optarg);
-      printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm);
-      break;
-      
-    case LONG_OPTION_DEBUG_UE_PRACH:
-      mode = debug_prach;
-      break;
-      
-    case LONG_OPTION_NO_L2_CONNECT:
-      mode = no_L2_connect;
-      break;
-    case 'M':
-#ifdef ETHERNET
-      strcpy(rrh_eNB_ip,optarg);
-#endif
-      break;
-    case 'C':
-      for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
-	downlink_frequency[CC_id][0] = atof(optarg); // Use float to avoid issue with frequency over 2^31.
-	downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
-	downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
-	downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
-	printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
-      }
-      UE_scan=0;
-      break;
-      
-    case 'd':
-#ifdef XFORMS
-      do_forms=1;
-      printf("Running with XFORMS!\n");
-#endif
-      break;
-      
-    case 'K':
-#if defined(ENABLE_ITTI)
-      itti_dump_file = strdup(optarg);
-#else
-      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
-#endif
-      break;
-      
-    case 'O':
-      conf_config_file_name = optarg;
-      break;
-      
-    case 'U':
-      UE_flag = 1;
-      break;
+    case 'U':
+      UE_flag = 1;
+      break;
     
     case 'm':
       target_dl_mcs = atoi (optarg);
@@ -3335,12 +2080,16 @@ int main(int argc, char **argv) {
   int error_code;
 #endif
 
+  PHY_VARS_UE *UE[MAX_NUM_CCs];
+  int UE_id = 0;
+
+  mode = normal_txrx;
   memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
 
   memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
   set_latency_target();
 
-  mode = normal_txrx;
+
 
   for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
     frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
@@ -3363,6 +2112,8 @@ int main(int argc, char **argv) {
   //randominit (0);
   set_taus_seed (0);
 
+  
+
   get_options (argc, argv); //Command-line options
   
 
@@ -3516,76 +2267,86 @@ int main(int argc, char **argv) {
 
     PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));
     PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
+  
     for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
-      PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], UE_id,abstraction_flag,transmission_mode);
-      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,PHY_vars_UE_g[0][CC_id]);
+
+      PHY_vars_UE_g[0][CC_id] = init_lte_UE(frame_parms[CC_id], 0,abstraction_flag,transmission_mode);
+      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
+      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
 #ifndef OPENAIR2
       for (i=0;i<NUMBER_OF_eNB_MAX;i++) {
-	PHY_vars_UE_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
-	PHY_vars_UE_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
-	PHY_vars_UE_g[0][CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
+	UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
+	UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
+	UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
 	
-	PHY_vars_UE_g[0][CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = UE_id;
-	PHY_vars_UE_g[0][CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(UE_id%3);
-	PHY_vars_UE_g[0][CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
+	UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
+	UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
+	UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
       }
 #endif
+
+
+      UE[CC_id]->UE_scan = UE_scan;
+      UE[CC_id]->mode    = mode;
+
+      compute_prach_seq(&UE[CC_id]->lte_frame_parms.prach_config_common,
+			UE[CC_id]->lte_frame_parms.frame_type,
+			UE[CC_id]->X_u);
       
-      compute_prach_seq(&PHY_vars_UE_g[0][CC_id]->lte_frame_parms.prach_config_common,
-			PHY_vars_UE_g[0][CC_id]->lte_frame_parms.frame_type,
-			PHY_vars_UE_g[0][CC_id]->X_u);
-      
-      PHY_vars_UE_g[0][CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
+      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1234;
 #ifndef OPENAIR2
-      PHY_vars_UE_g[0][CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
+      UE[CC_id]->lte_ue_pdcch_vars[0]->crnti = 0x1235;
 #endif
     
 #ifdef EXMIMO
       for (i=0;i<4;i++) {
-	PHY_vars_UE_g[0][CC_id]->rx_gain_max[i] = rxg_max[i];
-	PHY_vars_UE_g[0][CC_id]->rx_gain_med[i] = rxg_med[i];
-	PHY_vars_UE_g[0][CC_id]->rx_gain_byp[i] = rxg_byp[i];
+	UE[CC_id]->rx_gain_max[i] = rxg_max[i];
+	UE[CC_id]->rx_gain_med[i] = rxg_med[i];
+	UE[CC_id]->rx_gain_byp[i] = rxg_byp[i];
       }
 
-      if ((mode == normal_txrx) || (mode == rx_calib_ue) || (mode == no_L2_connect) || (mode == debug_prach)) {
+      if ((UE[0]->mode == normal_txrx) || 
+	  (UE[0]->mode == rx_calib_ue) || 
+	  (UE[0]->mode == no_L2_connect) || 
+	  (UE[0]->mode == debug_prach)) {
 	for (i=0;i<4;i++)
 	  rx_gain_mode[CC_id][i] = max_gain;
-	PHY_vars_UE_g[0][CC_id]->rx_total_gain_dB =  PHY_vars_UE_g[0][CC_id]->rx_gain_max[0] + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain
+	UE[CC_id]->rx_total_gain_dB =  UE[CC_id]->rx_gain_max[0] + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain
       }
       else if ((mode == rx_calib_ue_med)) {
 	for (i=0;i<4;i++)
 	  rx_gain_mode[CC_id][i] =  med_gain;
-	PHY_vars_UE_g[0][CC_id]->rx_total_gain_dB =  PHY_vars_UE_g[0][CC_id]->rx_gain_med[0]  + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain;
+	UE[CC_id]->rx_total_gain_dB =  UE[CC_id]->rx_gain_med[0]  + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain;
       }
       else if ((mode == rx_calib_ue_byp)) {
 	for (i=0;i<4;i++)
 	  rx_gain_mode[CC_id][i] =  byp_gain;
-	PHY_vars_UE_g[0][CC_id]->rx_total_gain_dB =  PHY_vars_UE_g[0][CC_id]->rx_gain_byp[0]  + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain;
+	UE[CC_id]->rx_total_gain_dB =  UE[CC_id]->rx_gain_byp[0]  + (int)rx_gain[CC_id][0] - 30; //-30 because it was calibrated with a 30dB gain;
       }
 #else
-      PHY_vars_UE_g[0][CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0]; 
+      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0]; 
 #endif
     
-      PHY_vars_UE_g[0][CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
+      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
     
 
    
 #ifdef EXMIMO
       //N_TA_offset
-      if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.frame_type == TDD) {
-	if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.N_RB_DL == 100)
-	  PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 624;
-	else if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.N_RB_DL == 50)
-	  PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 624/2;
-	else if (PHY_vars_UE_g[UE_id][CC_id]->lte_frame_parms.N_RB_DL == 25)
-	  PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 624/4;
+      if (UE[CC_id]->lte_frame_parms.frame_type == TDD) {
+	if (UE[CC_id]->lte_frame_parms.N_RB_DL == 100)
+	  UE[CC_id]->N_TA_offset = 624;
+	else if (UE[CC_id]->lte_frame_parms.N_RB_DL == 50)
+	  UE[CC_id]->N_TA_offset = 624/2;
+	else if (UE[CC_id]->lte_frame_parms.N_RB_DL == 25)
+	  UE[CC_id]->N_TA_offset = 624/4;
       }
       else {
-	PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 0;
+	UE[CC_id]->N_TA_offset = 0;
       }
 #else
       //already taken care of in lte-softmodem
-      PHY_vars_UE_g[UE_id][CC_id]->N_TA_offset = 0;
+      UE[CC_id]->N_TA_offset = 0;
 #endif 
     }
     openair_daq_vars.manual_timing_advance = 0;
@@ -3602,7 +2363,7 @@ int main(int argc, char **argv) {
       PHY_vars_eNB_g = malloc(sizeof(PHY_VARS_eNB**));
       PHY_vars_eNB_g[0] = malloc(sizeof(PHY_VARS_eNB*));
       for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
-	PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],eNB_id,Nid_cell,cooperation_flag,transmission_mode,abstraction_flag);
+	PHY_vars_eNB_g[0][CC_id] = init_lte_eNB(frame_parms[CC_id],0,Nid_cell,cooperation_flag,transmission_mode,abstraction_flag);
 	PHY_vars_eNB_g[0][CC_id]->CC_id = CC_id;
        
 #ifndef OPENAIR2
@@ -3637,20 +2398,20 @@ int main(int argc, char **argv) {
 
 #ifdef EXMIMO
 	//N_TA_offset
-	if (PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.frame_type == TDD) {
-	  if (PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL == 100)
-	    PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 624;
-	  else if (PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL == 50)
-	    PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 624/2;
-	  else if (PHY_vars_eNB_g[eNB_id][CC_id]->lte_frame_parms.N_RB_DL == 25)
-	    PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 624/4;
+	if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.frame_type == TDD) {
+	  if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 100)
+	    PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624;
+	  else if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 50)
+	    PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/2;
+	  else if (PHY_vars_eNB_g[0][CC_id]->lte_frame_parms.N_RB_DL == 25)
+	    PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 624/4;
 	}
 	else {
-	  PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 0;
+	  PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
 	}
 #else
 	//already taken care of in lte-softmodem
-	PHY_vars_eNB_g[eNB_id][CC_id]->N_TA_offset = 0;
+	PHY_vars_eNB_g[0][CC_id]->N_TA_offset = 0;
 #endif 
 	
       }
@@ -3673,65 +2434,52 @@ int main(int argc, char **argv) {
   if(frame_parms[0]->N_RB_DL == 100) {
     sample_rate = 30.72e6;
 #ifndef EXMIMO
-    samples_per_packets = 2048;
+    openair0_cfg[0].samples_per_packet = 2048;
     samples_per_frame = 307200;
     // from usrp_time_offset
     tx_forward_nsamps = 175;
-    sf_bounds = sf_bounds_20;
-    sf_bounds_tx = sf_bounds_20_tx;
-    max_cnt = 150;
     tx_delay = 8;
 #endif
   }
   else if(frame_parms[0]->N_RB_DL == 50){
     sample_rate = 15.36e6;
 #ifndef EXMIMO
-    samples_per_packets = 2048;
+    openair0_cfg[0].samples_per_packet = 2048;
     samples_per_frame = 153600;
     tx_forward_nsamps = 95;
-    sf_bounds = sf_bounds_10;
-    sf_bounds_tx = sf_bounds_10_tx;
-    max_cnt = 75;
-    tx_delay = 4;
+    tx_delay = 5;
 #endif
   }
   else if (frame_parms[0]->N_RB_DL == 25) {
     sample_rate = 7.68e6;
 #ifndef EXMIMO
-    samples_per_packets = 1024;
+    openair0_cfg[0].samples_per_packet = 1024;
     samples_per_frame = 76800;
     tx_forward_nsamps = 70;
-    sf_bounds = sf_bounds_5;
-    sf_bounds_tx = sf_bounds_5_tx;
-    max_cnt = 75;
     tx_delay = 6;
 #endif
   }
   else if (frame_parms[0]->N_RB_DL == 6) {
     sample_rate = 1.92e6;
 #ifndef EXMIMO
-    samples_per_packets = 256;
+    openair0_cfg[0].samples_per_packet = 256;
     samples_per_frame = 19200;
     tx_forward_nsamps = 40;
-    sf_bounds = sf_bounds_1_5;
-    sf_bounds_tx = sf_bounds_1_5_tx;
-    max_cnt = 75;
-    tx_delay = 5;
+    tx_delay = 8;
 #endif
   }
 
 #ifdef ETHERNET
-  if (frame_parms[0]->N_RB_DL == 6) samples_per_packets = 256;
-  else samples_per_packets = 1536;
+  if (frame_parms[0]->N_RB_DL == 6) openair0_cfg[0].samples_per_packet = 256
+  else openair0_cfg[0].samples_per_packet = 1536;
 
-  max_cnt = sf_bounds[9]; 
-  printf("HW: samples_per_packets %d, max_cnt %d\n",samples_per_packets,max_cnt);
+  printf("HW: samples_per_packet %d\n",openair0_cfg[0].samples_per_packet);
 #endif
 
 
   for (card=0;card<MAX_CARDS;card++) {
 #ifndef EXMIMO
-    openair0_cfg[card].samples_per_packet = samples_per_packets;
+    openair0_cfg[card].samples_per_packet = openair0_cfg[0].samples_per_packet;
 #endif
     printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
 	   ((UE_flag==0) ? PHY_vars_eNB_g[0][0]->lte_frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->lte_frame_parms.nb_antennas_tx),
@@ -3844,7 +2592,7 @@ int main(int argc, char **argv) {
   // connect the TX/RX buffers
   if (UE_flag==1) {
     openair_daq_vars.timing_advance = 170;
-    if (setup_ue_buffers(PHY_vars_UE_g[0],&openair0_cfg[0],rf_map)!=0) {
+    if (setup_ue_buffers(UE,&openair0_cfg[0],rf_map)!=0) {
       printf("Error setting up eNB buffer\n");
       exit(-1);
     }
@@ -3853,7 +2601,7 @@ int main(int argc, char **argv) {
     for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
       for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
 	for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++)
-	  PHY_vars_UE_g[0][CC_id]->lte_ue_common_vars.txdata[aa][i] = 0x00010001;
+	  UE[CC_id]->lte_ue_common_vars.txdata[aa][i] = 0x00010001;
     }
     //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
   }
@@ -3902,9 +2650,6 @@ int main(int argc, char **argv) {
   //rt_set_oneshot_mode();
   rt_set_periodic_mode();
   start_rt_timer(0);
-
-  //now = rt_get_time() + 10*PERIOD;
-  //rt_task_make_periodic(task, now, PERIOD);
 #endif
 
   pthread_cond_init(&sync_cond,NULL);
@@ -3993,16 +2738,12 @@ int main(int argc, char **argv) {
   pthread_attr_setschedparam  (&attr_dlsch_threads, &sched_param_dlsch);
   pthread_attr_setschedpolicy (&attr_dlsch_threads, SCHED_FIFO);
 #endif 
-  pthread_attr_init (&attr_UE_init_synch);
-  pthread_attr_setstacksize(&attr_UE_init_synch,8*PTHREAD_STACK_MIN);
-  sched_param_UE_init_synch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
-  pthread_attr_setschedparam  (&attr_UE_init_synch, &sched_param_UE_init_synch);
-  pthread_attr_setschedpolicy (&attr_UE_init_synch, SCHED_FIFO);
 
 #endif
 
   // start the main thread
   if (UE_flag == 1) {
+    printf("Intializing UE Threads ...\n");
     init_UE_threads();
 #ifdef DLSCH_THREAD
     init_rx_pdsch_thread();
@@ -4057,7 +2798,7 @@ int main(int argc, char **argv) {
 #endif
 #endif
 
-  printf("Starting all threads\n");
+
   pthread_mutex_lock(&sync_mutex);
   sync_var=0;
   pthread_cond_broadcast(&sync_cond);
@@ -4085,8 +2826,8 @@ int main(int argc, char **argv) {
       fl_hide_form(form_stats->stats_form);
       fl_free_form(form_stats->stats_form);
       if (UE_flag==1) {
-	fl_hide_form(form_ue[UE_id]->lte_phy_scope_ue);
-	fl_free_form(form_ue[UE_id]->lte_phy_scope_ue);
+	fl_hide_form(form_ue[0]->lte_phy_scope_ue);
+	fl_free_form(form_ue[0]->lte_phy_scope_ue);
       } else {
 	fl_hide_form(form_stats_l2->stats_form);
 	fl_free_form(form_stats_l2->stats_form);
@@ -4139,10 +2880,10 @@ int main(int argc, char **argv) {
 
 #ifdef RTAI
   stop_rt_timer();
-#else
+#endif
   pthread_cond_destroy(&sync_cond);
   pthread_mutex_destroy(&sync_mutex);
-#endif
+
 
 #ifdef EXMIMO
   printf("stopping card\n");
@@ -4173,99 +2914,6 @@ int main(int argc, char **argv) {
   return 0;
 }
 
-int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
-{
-
-#ifndef EXMIMO
-  uint16_t N_TA_offset = 0;
-#endif
-
-  int i, CC_id;
-  LTE_DL_FRAME_PARMS *frame_parms;
-  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
-    if (phy_vars_ue[CC_id]) {
-      frame_parms = &(phy_vars_ue[CC_id]->lte_frame_parms); 
-    }
-    else {
-      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
-      return(-1);
-    }
-
-
-#ifndef EXMIMO
-    if (frame_parms->frame_type == TDD) {
-      if (frame_parms->N_RB_DL == 100)
-	N_TA_offset = 624;
-      else if (frame_parms->N_RB_DL == 50)
-	N_TA_offset = 624/2;
-      else if (frame_parms->N_RB_DL == 25)
-	N_TA_offset = 624/4;
-    }
-#endif
-   
-#ifdef EXMIMO
-    openair0_cfg[CC_id].tx_num_channels = 0;
-    openair0_cfg[CC_id].rx_num_channels = 0;
-
-    // replace RX signal buffers with mmaped HW versions
-    for (i=0;i<frame_parms->nb_antennas_rx;i++) {
-      printf("Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
-      free(phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]);
-      phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i];
-      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
-	printf("Error with rf_map! A channel has already been allocated!\n");
-	return(-1);
-      }
-      else {
-	openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i];
-	openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i];
-	openair0_cfg[rf_map[CC_id].card].rxg_mode[rf_map[CC_id].chain+i] = rx_gain_mode[CC_id][i];
-	openair0_cfg[rf_map[CC_id].card].rx_num_channels++;
-      }
-
-      printf("rxdata[%d] @ %p\n",i,phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]);
-    }
-    for (i=0;i<frame_parms->nb_antennas_tx;i++) {
-      printf("Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
-      free(phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]);
-      phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i];
-      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
-	printf("Error with rf_map! A channel has already been allocated!\n");
-	return(-1);
-      }
-      else {
-	openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
-	openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i];
-	openair0_cfg[rf_map[CC_id].card].tx_num_channels++;
-      }
-
-      printf("txdata[%d] @ %p\n",i,phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]);
-    }
-  
-#else
-    // replace RX signal buffers with mmaped HW versions
-    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
-    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
-    for (i=0;i<frame_parms->nb_antennas_rx;i++) {
-      printf("Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
-      free(phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]);
-      rxdata[i] = (int32_t*)malloc16(samples_per_frame*sizeof(int32_t));
-      phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD
-    }
-    for (i=0;i<frame_parms->nb_antennas_tx;i++) {
-      printf("Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
-      free(phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]);
-      txdata[i] = (int32_t*)malloc16(samples_per_frame*sizeof(int32_t));
-      phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = txdata[i];
-      memset(txdata[i], 0, samples_per_frame*sizeof(int32_t));
-    }
-    
-#endif
-    
-  }
-  return(0);
-
-}
 
 /* this function maps the phy_vars_eNB tx and rx buffers to the available rf chains. 
    Each rf chain is is addressed by the card number and the chain on the card. The 
diff --git a/targets/RT/USER/lte-ue.c b/targets/RT/USER/lte-ue.c
new file mode 100644
index 0000000000000000000000000000000000000000..60afcf810698088ca0b2b162f6918e4bb98967f3
--- /dev/null
+++ b/targets/RT/USER/lte-ue.c
@@ -0,0 +1,1487 @@
+/*******************************************************************************
+    OpenAirInterface 
+    Copyright(c) 1999 - 2014 Eurecom
+
+    OpenAirInterface is free software: you can redistribute it and/or modify
+    it under the terms of the GNU General Public License as published by
+    the Free Software Foundation, either version 3 of the License, or
+    (at your option) any later version.
+
+
+    OpenAirInterface is distributed in the hope that it will be useful,
+    but WITHOUT ANY WARRANTY; without even the implied warranty of
+    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+    GNU General Public License for more details.
+
+    You should have received a copy of the GNU General Public License
+    along with OpenAirInterface.The full GNU General Public License is 
+    included in this distribution in the file called "COPYING". If not, 
+    see <http://www.gnu.org/licenses/>.
+
+   Contact Information
+   OpenAirInterface Admin: openair_admin@eurecom.fr
+   OpenAirInterface Tech : openair_tech@eurecom.fr
+   OpenAirInterface Dev  : openair4g-devel@eurecom.fr
+  
+   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
+
+*******************************************************************************/
+
+/*! \file lte-ue.c
+ * \brief threads and support functions for real-time LTE UE target
+ * \author R. Knopp, F. Kaltenberger, Navid Nikaein
+ * \date 2015
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
+ * \note
+ * \warning
+ */
+#define _GNU_SOURCE
+#include <stdio.h>
+#include <stdlib.h>
+#include <unistd.h>
+#include <string.h>
+#include <sys/ioctl.h>
+#include <sys/types.h>
+#include <sys/mman.h>
+#include <sys/stat.h>
+#include <fcntl.h>
+#include <sched.h>
+#include <linux/sched.h>
+#include <signal.h>
+#include <execinfo.h>
+#include <getopt.h>
+#include <syscall.h>
+
+#include "rt_wrapper.h"
+#include "assertions.h"
+#include "PHY/types.h"
+
+#include "PHY/defs.h"
+#include "LAYER2/MAC/defs.h"
+#include "RRC/LITE/extern.h"
+#include "PHY_INTERFACE/extern.h"
+
+#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
+//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
+
+#ifdef EXMIMO
+#include "openair0_lib.h"
+#else
+#include "../../ARCH/COMMON/common_lib.h"
+#endif
+
+#include "PHY/extern.h"
+#include "MAC_INTERFACE/extern.h"
+//#include "SCHED/defs.h"
+#include "SCHED/extern.h"
+#include "LAYER2/MAC/extern.h"
+#include "LAYER2/MAC/proto.h"
+
+#include "UTIL/LOG/log_extern.h"
+#include "UTIL/OTG/otg_tx.h"
+#include "UTIL/OTG/otg_externs.h"
+#include "UTIL/MATH/oml.h"
+#include "UTIL/LOG/vcd_signal_dumper.h"
+#include "UTIL/OPT/opt.h"
+
+#define FRAME_PERIOD    100000000ULL
+#define DAQ_PERIOD      66667ULL
+
+typedef enum {
+  pss=0,
+  pbch=1,
+  si=2
+} sync_mode_t;
+
+int init_dlsch_threads(void);
+void cleanup_dlsch_threads(void);
+int32_t init_rx_pdsch_thread(void);
+void cleanup_rx_pdsch_thread(void);
+
+pthread_attr_t                  attr_UE_init_synch;
+pthread_attr_t                  attr_UE_thread_tx;
+pthread_attr_t                  attr_UE_thread_rx;
+struct sched_param              sched_param_UE_init_synch;
+struct sched_param              sched_param_UE_thread_tx;
+struct sched_param              sched_param_UE_thread_rx;
+
+#ifdef RTAI
+extern SEM                     *mutex;
+//static CND *cond;
+
+extern SEM *sync_sem; // to sync rx & tx streaming
+
+//static int sync_thread;
+#else
+
+extern pthread_cond_t sync_cond;
+extern pthread_mutex_t sync_mutex;
+extern int sync_var;
+#endif
+
+extern openair0_config_t openair0_cfg[MAX_CARDS];
+extern uint32_t          downlink_frequency[MAX_NUM_CCs][4];
+extern int32_t           uplink_frequency_offset[MAX_NUM_CCs][4]; 
+extern openair0_rf_map rf_map[MAX_NUM_CCs];
+
+extern openair0_device openair0;
+extern int oai_exit;
+
+extern int32_t **rxdata;
+extern int32_t **txdata;
+
+extern unsigned int samples_per_frame;
+extern unsigned int tx_forward_nsamps;
+extern int tx_delay;
+
+extern int rx_input_level_dBm;
+extern uint8_t exit_missed_slots;
+extern uint64_t num_missed_slots; // counter for the number of missed slots
+
+extern void exit_fun(const char* s);
+
+#ifdef EXMIMO
+
+extern unsigned int             rxg_max[4];
+extern unsigned int             rxg_med[4];
+extern unsigned int             rxg_byp[4];
+extern unsigned int             nf_max[4];
+extern unsigned int             nf_med[4];
+extern unsigned int             nf_byp[4];
+extern rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4];
+
+extern double tx_gain[MAX_NUM_CCs][4];
+extern double rx_gain[MAX_NUM_CCs][4];
+#endif
+#define KHz (1000UL)
+#define MHz (1000 * KHz)
+
+typedef struct eutra_band_s {
+  int16_t band;
+  uint32_t ul_min;
+  uint32_t ul_max;
+  uint32_t dl_min;
+  uint32_t dl_max;
+  lte_frame_type_t frame_type;
+} eutra_band_t;
+
+typedef struct band_info_s {
+  int nbands;
+  eutra_band_t band_info[100];
+} band_info_t;
+
+band_info_t bands_to_scan;
+
+static const eutra_band_t eutra_bands[] =
+  {
+    { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
+    { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
+    { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
+    { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
+    { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
+    { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
+    { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
+    { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
+    { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
+    {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
+    {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
+    {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
+    {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
+    {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
+
+    {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
+
+    {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
+    {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
+    {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
+    {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
+    {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
+    {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
+    {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
+    {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
+    {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
+    {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
+    {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
+    {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
+  };
+
+static void *UE_thread_synch(void *arg) {
+
+  int i,hw_slot_offset;
+  PHY_VARS_UE *UE = arg;
+  int current_band = 0;
+  int current_offset = 0;
+  sync_mode_t sync_mode = pss;
+  int card;
+
+
+  UE->is_synchronized = 0;
+  printf("UE_thread_sync in with PHY_vars_UE %p\n",arg);
+  printf("waiting for sync (UE_thread_synch) \n");
+
+
+  pthread_mutex_lock(&sync_mutex);
+  printf("Locked sync_mutex, waiting (UE_sync_thread)\n");
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
+  printf("unlocked sync_mutex (UE_sync_thread)\n");
+
+  printf("starting UE synch thread\n");
+
+  if (UE->UE_scan == 1) {
+    for (card=0;card<MAX_CARDS;card++) {
+      for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
+	downlink_frequency[card][i] = bands_to_scan.band_info[0].dl_min;
+	uplink_frequency_offset[card][i] = bands_to_scan.band_info[0].ul_min-bands_to_scan.band_info[0].dl_min;
+    
+	openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i];
+	openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i];
+	openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB-USRP_GAIN_OFFSET;  
+#ifdef USRP
+#ifndef USRP_DEBUG
+	openair0_set_rx_frequencies(&openair0,&openair0_cfg[0]);
+	openair0_set_gains(&openair0,&openair0_cfg[0]);
+#endif
+#endif
+      }
+    }    
+    LOG_D(PHY,"[SCHED][UE] Scanning band %d, freq %u\n",bands_to_scan.band_info[0].band, bands_to_scan.band_info[0].dl_min);
+  }
+  else {
+    LOG_D(PHY,"[SCHED][UE] Check absolute frequency %u (oai_exit %d)\n",downlink_frequency[0][0],oai_exit);
+
+    sync_mode=pbch;
+  }
+
+  while (oai_exit==0) {
+    
+    if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
+      LOG_E(PHY,"[SCHED][UE] error locking mutex for UE initial synch thread\n");
+      exit_fun("noting to add");
+    }
+    else {
+      while (UE->instance_cnt_synch < 0) {
+	pthread_cond_wait(&UE->cond_synch,&UE->mutex_synch);
+      }
+      if (pthread_mutex_unlock(&UE->mutex_synch) != 0) {	
+	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for UE Initial Synch thread\n");
+	exit_fun("nothing to add");
+      }
+
+    }  // mutex_lock      
+
+    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,1); 
+    printf("Sync_mode %d\n",sync_mode);
+    switch (sync_mode) {
+    case pss:
+	
+
+
+      current_offset += 20000000; // increase by 20 MHz
+      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
+	current_band++;
+	current_offset=0;
+      }
+      if (current_band==bands_to_scan.nbands) {
+	current_band=0;
+	oai_exit=1; 
+      }
+      
+      for (card=0;card<MAX_CARDS;card++) {
+	for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
+	  downlink_frequency[card][i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
+	  uplink_frequency_offset[card][i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
+	  
+	  
+	  openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]+openair_daq_vars.freq_offset;
+	  openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]+openair_daq_vars.freq_offset;
+	  openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB-USRP_GAIN_OFFSET;  // 65 calibrated for USRP B210 @ 2.6 GHz
+#ifdef USRP
+#ifndef USRP_DEBUG
+	  openair0_set_rx_frequencies(&openair0,&openair0_cfg[0]);
+	  //	openair0_set_gains(&openair0,&openair0_cfg[0]);
+#endif
+#endif
+	}
+      }	
+      
+      break;
+    case pbch:
+      printf("Running initial sync\n");
+
+      if (initial_sync(UE,UE->mode)==0) {
+	/*
+	  lte_adjust_synch(&PHY_vars_UE_g[0]->lte_frame_parms,
+	  PHY_vars_UE_g[0],
+	  0,
+	  1,
+	  16384);
+	*/
+	//for better visualization afterwards
+	/*
+	  for (aa=0; aa<PHY_vars_UE_g[0]->lte_frame_parms.nb_antennas_rx; aa++)
+	  memset(PHY_vars_UE_g[0]->lte_ue_common_vars.rxdata[aa],0,
+	  PHY_vars_UE_g[0]->lte_frame_parms.samples_per_tti*LTE_NUMBER_OF_SUBFRAMES_PER_FRAME*sizeof(int));
+	*/
+	
+	
+	UE->is_synchronized = 1;
+#ifndef EXMIMO
+	UE->slot_rx = 0;
+	UE->slot_tx = 4;
+#else
+	UE->slot_rx = 18;
+	UE->slot_tx = 2;
+#endif
+	hw_slot_offset = (UE->rx_offset<<1) / UE->lte_frame_parms.samples_per_tti;
+	LOG_I(HW,"Got synch: hw_slot_offset %d\n",hw_slot_offset);
+	  
+      }
+      else {
+	  
+	if (openair_daq_vars.freq_offset >= 0) {
+	  openair_daq_vars.freq_offset += 100;
+	  openair_daq_vars.freq_offset *= -1;
+	}
+	else {
+	  openair_daq_vars.freq_offset *= -1;
+	}
+	if (abs(openair_daq_vars.freq_offset) > 7500) {
+	  LOG_I(PHY,"[initial_sync] No cell synchronization found, abandoning\n");
+	  mac_xface->macphy_exit("No cell synchronization found, abandoning");
+	}
+	else {
+	  LOG_I(PHY,"[initial_sync] trying carrier off %d Hz, rxgain %d\n",openair_daq_vars.freq_offset,
+		UE->rx_total_gain_dB);
+	  for (card=0;card<MAX_CARDS;card++) {
+	    for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
+	      openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]+openair_daq_vars.freq_offset;
+	      openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]+openair_daq_vars.freq_offset;
+	      openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB-USRP_GAIN_OFFSET;  // 65 calibrated for USRP B210 @ 2.6 GHz
+#ifdef USRP
+#ifndef USRP_DEBUG
+	      openair0_set_frequencies(&openair0,&openair0_cfg[0]);
+	      //	    openair0_set_gains(&openair0,&openair0_cfg[0]);
+#endif
+#endif
+	    }
+	  }
+	    
+	  //	    openair0_dump_config(&openair0_cfg[0],UE_flag);
+	    
+	  //	    rt_sleep_ns(FRAME_PERIOD);
+	} // freq_offset
+      } // initial_sync=0
+      break;
+    case si:
+    default:
+      break;
+    }
+    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,0);  
+    printf("Finished synch : Locking synch mutex (thread_sync)\n");
+    if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
+      printf("[openair][SCHED][eNB] error locking mutex for UE synch\n");
+    }
+    else {
+      UE->instance_cnt_synch--;
+      
+      if (pthread_mutex_unlock(&UE->mutex_synch) != 0) {	
+	printf("[openair][SCHED][eNB] error unlocking mutex for UE synch\n");
+      }
+    }
+    vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH,0); 
+  }  // while !oai_exit
+  return(0);
+}
+
+static void *UE_thread_tx(void *arg) {
+
+#ifdef LOWLATENCY
+  struct sched_attr attr;
+  unsigned int flags = 0;
+#endif
+#ifdef RTAI
+  RT_TASK *task;
+#endif
+  int ret;
+
+  PHY_VARS_UE *UE = (PHY_VARS_UE*)arg;
+
+  UE->instance_cnt_tx=-1;
+
+#ifdef RTAI
+  task = rt_task_init_schmod(nam2num("UE TX Thread"), 0, 0, 0, SCHED_FIFO, 0xF);
+  if (task==NULL) {
+    LOG_E(PHY,"[SCHED][UE] Problem starting UE TX thread!!!!\n");
+    return 0;
+  }
+  LOG_D(HW,"Started UE TX thread (id %p)\n",task);
+#else
+
+#ifdef LOWLATENCY
+  attr.size = sizeof(attr);
+  attr.sched_flags = 0;
+  attr.sched_nice = 0;
+  attr.sched_priority = 0;
+  
+  /* This creates a 1ms reservation every 10ms period*/
+  attr.sched_policy = SCHED_DEADLINE;
+  attr.sched_runtime = 1 * 500000;  // each tx thread requires .5ms to finish its job
+  attr.sched_deadline =1 * 1000000; // each tx thread will finish within 1ms
+  attr.sched_period = 1 * 1000000; // each tx thread has a period of 1ms from the starting point
+
+  
+  if (sched_setattr(0, &attr, flags) < 0 ){
+    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
+    exit(-1);
+  }
+#endif
+#endif
+  printf("waiting for sync (UE_thread_tx)\n");
+
+  pthread_mutex_lock(&sync_mutex);
+  printf("Locked sync_mutex, waiting (UE_thread_tx)\n");
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
+  printf("unlocked sync_mutex, waiting (UE_thread_tx)\n");
+
+
+
+  printf("Starting UE TX thread\n");
+
+  mlockall(MCL_CURRENT | MCL_FUTURE);
+
+  while (!oai_exit) {
+
+    if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
+      LOG_E(PHY,"[SCHED][eNB] error locking mutex for UE TX\n");
+      exit_fun("nothing to add");
+    }
+    else {
+      
+      while (UE->instance_cnt_tx < 0) {
+	pthread_cond_wait(&UE->cond_tx,&UE->mutex_tx);
+      }
+      if (pthread_mutex_unlock(&UE->mutex_tx) != 0) {	
+	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for UE TX\n");
+	exit_fun("nothing to add");
+      }
+    }
+    
+    
+    if ((subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1)==SF_UL)){
+      phy_procedures_UE_TX(UE,0,0,UE->mode,no_relay);
+    }
+    if ((subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1)==SF_S) &&
+	((UE->slot_tx&1)==1)) {
+      phy_procedures_UE_S_TX(UE,0,0,no_relay);
+    }
+    
+    
+    if (UE->lte_frame_parms.frame_type == TDD) {
+      
+      ret = mac_xface->ue_scheduler(UE->Mod_id, 
+				    UE->frame_tx,
+				    UE->slot_rx>>1, 
+				    subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1),
+				    0);
+      
+      if (ret == CONNECTION_LOST) {
+	LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",UE->Mod_id,
+	      UE->frame_rx,UE->slot_tx>>1);
+	UE->UE_mode[0] = PRACH;
+	//      mac_xface->macphy_exit("Connection lost");
+      }
+      else if (ret == PHY_RESYNCH) {
+	LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n",
+	      UE->Mod_id,
+	      UE->frame_rx,UE->slot_tx>>1);
+	UE->UE_mode[0] = RESYNCH;
+	//     mac_xface->macphy_exit("Connection lost");
+	//exit(-1);
+      } else if (ret == PHY_HO_PRACH) {
+	LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n",
+	      UE->Mod_id,UE->frame_rx,UE->slot_tx>>1);
+	UE->UE_mode[0] = PRACH;
+      }
+    }
+    
+    
+    if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
+      printf("[openair][SCHED][eNB] error locking mutex for UE TX thread\n");
+    }
+    else {
+      UE->instance_cnt_tx--;
+      
+      if (pthread_mutex_unlock(&UE->mutex_tx) != 0) {	
+	printf("[openair][SCHED][eNB] error unlocking mutex for UE\n");
+      }
+    }
+    
+    UE->slot_tx+=2;
+    if (UE->slot_tx>=20) {
+      UE->slot_tx-=20;
+      UE->frame_tx++;
+      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_UE, UE->frame_tx);
+    }
+    vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_UE, UE->slot_tx>>1);
+  }
+  return(0);
+}
+
+static void *UE_thread_rx(void *arg) {
+  
+  PHY_VARS_UE *UE = (PHY_VARS_UE*)arg;
+  int i;
+  int ret;
+  
+#ifdef LOWLATENCY
+  struct sched_attr attr;
+  unsigned int flags = 0;
+#endif
+#ifdef RTAI
+  RT_TASK *task;
+#endif
+  
+  UE->instance_cnt_rx=-1;
+
+#ifdef RTAI
+  task = rt_task_init_schmod(nam2num("UE Thread RX"), 0, 0, 0, SCHED_FIFO, 0xF);
+  if (task==NULL) {
+    LOG_E(PHY,"[SCHED][UE] Problem starting UE RX thread!!!!\n");
+    return 0;
+  }
+  LOG_D(HW,"Started UE RX thread (id %p)\n",task);
+#else
+  
+#ifdef LOWLATENCY
+  attr.size = sizeof(attr);
+  attr.sched_flags = 0;
+  attr.sched_nice = 0;
+  attr.sched_priority = 0;
+  
+  // This creates a 1ms reservation every 10ms period
+  attr.sched_policy = SCHED_DEADLINE;
+  attr.sched_runtime = 1 * 800000;  // each rx thread requires 1ms to finish its job
+  attr.sched_deadline =1 * 1000000; // each rx thread will finish within 1ms
+  attr.sched_period = 1 * 1000000; // each rx thread has a period of 1ms from the starting point
+  
+  if (sched_setattr(0, &attr, flags) < 0 ){
+    perror("[SCHED] eNB tx thread: sched_setattr failed\n");
+    exit(-1);
+  }  
+#endif
+#endif
+  
+  mlockall(MCL_CURRENT | MCL_FUTURE);
+  
+#ifndef EXMIMO
+  printf("waiting for sync (UE_thread_rx)\n");
+#ifdef RTAI
+  rt_sem_wait(sync_sem);
+#else
+  pthread_mutex_lock(&sync_mutex);
+  printf("Locked sync_mutex, waiting (UE_thread_rx)\n");
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
+  printf("unlocked sync_mutex, waiting (UE_thread_rx)\n");
+#endif
+#endif
+  
+  printf("Starting UE RX thread\n");
+  
+  while (!oai_exit) { 
+    //   printf("UE_thread_rx: locking UE RX mutex\n");
+    if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
+      LOG_E(PHY,"[SCHED][eNB] error locking mutex for UE RX\n");
+      exit_fun("nothing to add");
+    }
+    else {
+      
+      while (UE->instance_cnt_rx < 0) {
+	pthread_cond_wait(&UE->cond_rx,&UE->mutex_rx);
+      }
+      if (pthread_mutex_unlock(&UE->mutex_rx) != 0) {	
+	LOG_E(PHY,"[SCHED][eNB] error unlocking mutex for UE RX\n");
+	exit_fun("nothing to add");
+      }
+      
+      for (i=0;i<2;i++) {
+	if ((subframe_select(&UE->lte_frame_parms,UE->slot_rx>>1)==SF_DL) |
+            (UE->lte_frame_parms.frame_type == FDD)) {
+	  phy_procedures_UE_RX(UE,0,0,UE->mode,no_relay,NULL);
+	}
+	if ((subframe_select(&UE->lte_frame_parms,UE->slot_rx>>1)==SF_S) &&
+	    ((UE->slot_rx&1)==0)) {
+	  phy_procedures_UE_RX(UE,0,0,UE->mode,no_relay,NULL);
+	}
+      	
+	if (i==0) {
+	  ret = mac_xface->ue_scheduler(UE->Mod_id, 
+					UE->frame_tx,
+					UE->slot_rx>>1,
+					subframe_select(&UE->lte_frame_parms,UE->slot_tx>>1),
+					0);
+	  
+	  if (ret == CONNECTION_LOST) {
+	    LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, returning to PRACH\n",UE->Mod_id,
+		  UE->frame_rx,UE->slot_tx>>1);
+	    UE->UE_mode[0] = PRACH;
+	    //      mac_xface->macphy_exit("Connection lost");
+	  }
+	  else if (ret == PHY_RESYNCH) {
+	    LOG_E(PHY,"[UE %d] Frame %d, subframe %d RRC Connection lost, trying to resynch\n",
+		  UE->Mod_id,
+		  UE->frame_rx,UE->slot_tx>>1);
+	    UE->UE_mode[0] = RESYNCH;
+	    //     mac_xface->macphy_exit("Connection lost");
+	    //exit(-1);
+	  } 
+	  else if (ret == PHY_HO_PRACH) {
+	    LOG_I(PHY,"[UE %d] Frame %d, subframe %d, return to PRACH and perform a contention-free access\n",
+		  UE->Mod_id,UE->frame_rx,UE->slot_tx>>1);
+	    UE->UE_mode[0] = PRACH;
+	  }
+	}	  
+	
+	UE->slot_rx++;
+	
+	if (UE->slot_rx==20) {
+	UE->slot_rx=0;
+	UE->frame_rx++;
+	vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_UE, UE->frame_rx);
+      } 
+	
+      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_UE, UE->slot_rx>>1);
+      
+	}
+	
+	if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
+	printf("[openair][SCHED][eNB] error locking mutex for UE RX\n");
+      }
+	else {
+	UE->instance_cnt_rx--;
+	
+	if (pthread_mutex_unlock(&UE->mutex_rx) != 0) {	
+	printf("[openair][SCHED][eNB] error unlocking mutex for UE RX\n");
+      }
+      }
+	//    printf("UE_thread_rx done\n");
+      }
+      }      
+	return(0);
+      }
+    
+
+
+
+#ifndef EXMIMO
+#define RX_OFF_MAX 10
+#define RX_OFF_MIN 5
+#define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2)
+
+void *UE_thread(void *arg) {
+
+  PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
+  LTE_DL_FRAME_PARMS *frame_parms=&UE->lte_frame_parms;
+  int spp = openair0_cfg[0].samples_per_packet;
+
+  int slot=1,frame=0,hw_subframe=0,rxpos=0,txpos=0;
+  // unsigned int aa;
+  int dummy[2][spp];
+  int dummy_dump = 0;
+  int tx_enabled=0;
+  int start_rx_stream=0;
+  int rx_off_diff = 0;
+  int rx_correction_timer = 0;
+  int i;
+  int first_rx=0;
+  RTIME T0;
+#ifdef RTAI
+  RT_TASK *task;
+#endif
+
+  unsigned int rxs;
+  void *rxp[2],*txp[2];
+  openair0_timestamp timestamp;
+
+  
+#ifdef LOWLATENCY
+  struct sched_attr attr;
+  unsigned int flags = 0;
+  unsigned long mask = 1; // processor 0 
+#endif
+  
+
+
+#ifdef RTAI
+  task = rt_task_init_schmod(nam2num("UE thread"), 0, 0, 0, SCHED_FIFO, 0xF);
+  if (task==NULL) {
+    LOG_E(PHY,"[SCHED][UE] Problem starting UE thread!!!!\n");
+    return 0;
+  }
+#else
+  
+#ifdef LOWLATENCY
+  attr.size = sizeof(attr);
+  attr.sched_flags = 0;
+  attr.sched_nice = 0;
+  attr.sched_priority = 0;
+  
+  // This creates a .5 ms  reservation
+  attr.sched_policy = SCHED_DEADLINE;
+  attr.sched_runtime  = 0.25 * 1000000;
+  attr.sched_deadline = 0.25 * 1000000;
+  attr.sched_period   = 0.5 * 1000000;
+    
+  // pin the UE main thread to CPU0
+  // if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) <0) {
+  //   perror("[MAIN_ENB_THREAD] pthread_setaffinity_np failed\n");
+  //   }
+  
+  if (sched_setattr(0, &attr, flags) < 0 ){
+    perror("[SCHED] main eNB thread: sched_setattr failed\n");
+    exit_fun("Nothing to add");
+  } else {
+    LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n",
+	  gettid(),sched_getcpu());
+  }
+#endif
+#endif
+
+  mlockall(MCL_CURRENT | MCL_FUTURE);
+
+  printf("waiting for sync (UE_thread)\n");
+  pthread_mutex_lock(&sync_mutex);
+  printf("Locked sync_mutex, waiting (UE_thread)\n");
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
+  printf("unlocked sync_mutex, waiting (UE_thread)\n");
+
+  printf("starting UE thread\n");
+
+  
+
+
+  T0 = rt_get_time_ns();
+  first_rx = 1;
+  while (!oai_exit) {
+    vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe);
+    vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame);
+
+    
+    while (rxpos < (1+hw_subframe)*UE->lte_frame_parms.samples_per_tti) {
+       vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,1);
+  
+#ifndef USRP_DEBUG
+
+      for (i=0;i<UE->lte_frame_parms.nb_antennas_rx;i++)
+	rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rxpos] : (void*)dummy[i];
+      //      printf("rxpos %d, hw_subframe %d, dummy_dump %d (asking %d)\n",rxpos,hw_subframe,dummy_dump,spp - ((first_rx==1) ? rx_off_diff : 0));
+      rxs = openair0.trx_read_func(&openair0,
+				   &timestamp,
+				   rxp,
+				   spp - ((first_rx==1) ? rx_off_diff : 0),
+				   UE->lte_frame_parms.nb_antennas_rx);
+      if (rxs != (spp- ((first_rx==1) ? rx_off_diff : 0)))
+	exit_fun("problem in rx");
+
+      rx_off_diff = 0;
+      vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ,0);
+      
+      // Transmit TX buffer based on timestamp from RX
+      if (tx_enabled) {
+	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,1);
+	for (i=0;i<UE->lte_frame_parms.nb_antennas_tx;i++)
+	  txp[i] = (void*)&txdata[i][txpos];
+	openair0.trx_write_func(&openair0,
+				(timestamp+spp*tx_delay-tx_forward_nsamps),
+				txp,
+				spp,
+				UE->lte_frame_parms.nb_antennas_tx,
+				1);
+				
+	vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE,0);
+      }
+#else
+      rt_sleep_ns(1000000);
+#endif
+      rxpos+=spp;
+      txpos+=spp;
+      
+      if(txpos >= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti)
+	txpos -= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti;
+    }
+    
+    if(rxpos >= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti)
+      rxpos -= 10*PHY_vars_UE_g[0][0]->lte_frame_parms.samples_per_tti;
+
+    if (UE->is_synchronized==1)  {
+      LOG_D(HW,"UE_thread: hw_frame %d, hw_subframe %d (time %llu)\n",frame,hw_subframe,rt_get_time_ns()-T0);
+
+      if (start_rx_stream==1) {
+	//	printf("UE_thread: locking UE mutex_rx\n");
+	if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
+	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE RX thread\n");
+	  exit_fun("nothing to add");
+	}
+	else {
+ 	  
+	  UE->instance_cnt_rx++;
+	  //	  printf("UE_thread: Unlocking UE mutex_rx\n");
+	  pthread_mutex_unlock(&UE->mutex_rx);
+	  if (UE->instance_cnt_rx == 0) {
+	    // LOG_D(HW,"Scheduling UE RX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_rx,frame,hw_subframe,UE->slot_rx>>1,mode);
+	    if (pthread_cond_signal(&UE->cond_rx) != 0) {
+	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n");
+	      exit_fun("nothing to add");
+	    }
+	    else {
+	      //	      printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
+	    }
+	    if (UE->mode == rx_calib_ue) {
+	      if (frame == 10) {
+		LOG_D(PHY,"[SCHED][UE] Found cell with N_RB_DL %d, PHICH CONFIG (%d,%d), Nid_cell %d, NB_ANTENNAS_TX %d, initial frequency offset %d Hz, frequency offset %d Hz, RSSI (digital) %d dB, measured Gain %d dB, total_rx_gain %d dB, USRP rx gain %f dB\n",
+		      UE->lte_frame_parms.N_RB_DL,
+		      UE->lte_frame_parms.phich_config_common.phich_duration,
+		      UE->lte_frame_parms.phich_config_common.phich_resource,
+		      UE->lte_frame_parms.Nid_cell,
+		      UE->lte_frame_parms.nb_antennas_tx_eNB,
+		      openair_daq_vars.freq_offset,
+		      UE->lte_ue_common_vars.freq_offset,
+		      UE->PHY_measurements.rx_power_avg_dB[0],
+		      UE->PHY_measurements.rx_power_avg_dB[0] - rx_input_level_dBm,
+		      UE->rx_total_gain_dB,
+		      openair0_cfg[0].rx_gain[0]
+		      );
+		exit_fun("[HW][UE] UE in RX calibration mode, exiting");
+	      }
+	    }
+	  }
+	  else {
+	    LOG_E(PHY,"[SCHED][UE] UE RX thread busy!!\n");
+	    exit_fun("nothing to add");
+	  }
+	}
+      }
+    }
+    else {  // we are not yet synchronized
+      if ((hw_subframe == 9)&&(dummy_dump == 0)) {
+	// Wake up initial synch thread
+	if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
+	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE initial synch thread\n");
+	  exit_fun("nothing to add");
+	}
+	else {
+	  
+	  UE->instance_cnt_synch++;
+	  pthread_mutex_unlock(&UE->mutex_synch);
+	  dummy_dump = 1;
+	  if (UE->instance_cnt_synch == 0) {
+	    if (pthread_cond_signal(&UE->cond_synch) != 0) {
+	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n");
+	      exit_fun("nothing to add");
+	    }
+	  }
+	  else {
+	    LOG_E(PHY,"[SCHED][UE] UE sync thread busy!!\n");
+	    exit_fun("nothing to add");
+	  }
+	}
+      }
+    }
+    
+    hw_subframe++;
+    slot+=2;
+    if(hw_subframe==10) {
+      hw_subframe = 0;
+      first_rx = 1;
+      frame++;
+      slot = 1;
+      if (UE->instance_cnt_synch < 0) {
+	if (UE->is_synchronized == 1) {
+	  //	  openair0_set_gains(&openair0,&openair0_cfg[0]);
+	  rx_off_diff = 0;
+	  //	  LOG_D(PHY,"HW RESYNC: hw_frame %d: rx_offset = %d\n",frame,UE->rx_offset);
+	  if ((UE->rx_offset > RX_OFF_MAX)&&(start_rx_stream==0)) {
+	    start_rx_stream=1;
+	    //LOG_D(PHY,"HW RESYNC: hw_frame %d: Resynchronizing sample stream\n");
+	    frame=0;
+	    // dump ahead in time to start of frame
+
+#ifndef USRP_DEBUG
+	    rxs = openair0.trx_read_func(&openair0,
+					 &timestamp,
+					 (void**)rxdata,
+					 UE->rx_offset,
+					 UE->lte_frame_parms.nb_antennas_rx);
+#else
+	    rt_sleep_ns(10000000);
+#endif
+	    UE->rx_offset=0;
+	  }
+	  else if ((UE->rx_offset < RX_OFF_MIN)&&(start_rx_stream==1)) {
+	    //	    rx_off_diff = -UE->rx_offset + RX_OFF_MIN;
+	  }
+	  else if ((UE->rx_offset > (FRAME_LENGTH_COMPLEX_SAMPLES-RX_OFF_MAX)) &&(start_rx_stream==1) && (rx_correction_timer == 0)) {
+	    rx_off_diff = FRAME_LENGTH_COMPLEX_SAMPLES-UE->rx_offset;
+	    rx_correction_timer = 5;
+	  }
+	  if (rx_correction_timer>0)
+	    rx_correction_timer--;
+	  //	  LOG_D(PHY,"HW RESYNC: hw_frame %d: Correction: rx_off_diff %d (timer %d)\n",frame,rx_off_diff,rx_correction_timer);
+	}
+	dummy_dump=0;
+      }
+    }
+    
+#if defined(ENABLE_ITTI)
+    itti_update_lte_time(frame, slot);
+#endif
+  }
+  return(0);
+}
+#endif
+
+
+
+#ifdef EXMIMO
+/* This is the main UE thread. Initially it is doing a periodic get_frame. One synchronized it gets woken up by the kernel driver using the RTAI message mechanism (rt_send and rt_receive). */
+void *UE_thread(void *arg) {
+  PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
+#ifdef RTAI
+  RT_TASK *task;
+#endif
+  // RTIME in, out, diff;
+  int slot=0,frame=0,hw_slot,last_slot,next_slot;
+  // unsigned int aa;
+  int delay_cnt;
+  RTIME time_in;
+  int hw_slot_offset=0,rx_offset_mbox=0,mbox_target=0,mbox_current=0;
+  int diff2;
+  int i, ret;
+  int CC_id,card;
+  volatile unsigned int *DAQ_MBOX = openair0_daq_cnt();
+
+  int wait_sync_cnt = 0;
+  int first_synch = 1;
+#ifdef LOWLATENCY
+  struct sched_attr attr;
+  unsigned int flags = 0;
+  unsigned long mask = 1; // processor 0 
+#endif
+
+
+
+#ifdef RTAI
+  task = rt_task_init_schmod(nam2num("UE thread"), 0, 0, 0, SCHED_FIFO, 0xF);
+  if (task==NULL) {
+    LOG_E(PHY,"[SCHED][UE] Problem starting UE thread!!!!\n");
+    return 0;
+  }
+#endif
+
+
+#ifdef HARD_RT
+  rt_make_hard_real_time();
+#endif
+
+
+#ifdef LOWLATENCY
+  attr.size = sizeof(attr);
+  attr.sched_flags = 0;
+  attr.sched_nice = 0;
+  attr.sched_priority = 0;
+  
+  // This creates a .25 ms  reservation
+  attr.sched_policy = SCHED_DEADLINE;
+  attr.sched_runtime  = 0.25 * 1000000;
+  attr.sched_deadline = 0.25 * 1000000;
+  attr.sched_period   = 0.5 * 1000000;
+  
+  // pin the UE main thread to CPU0
+  // if (pthread_setaffinity_np(pthread_self(), sizeof(mask),&mask) <0) {
+  //   perror("[MAIN_ENB_THREAD] pthread_setaffinity_np failed\n");
+  //   }
+  
+  if (sched_setattr(0, &attr, flags) < 0 ){
+    perror("[SCHED] main UE thread: sched_setattr failed\n");
+    exit_fun("Nothing to add");
+  } else {
+    LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %ld started on CPU %d\n",
+	  gettid(),sched_getcpu());
+  }
+#endif
+  
+
+  mlockall(MCL_CURRENT | MCL_FUTURE);
+
+  printf("waiting for sync (UE_thread)\n");
+
+  pthread_mutex_lock(&sync_mutex);
+  printf("Locked sync_mutex, waiting (UE_thread)\n");
+  while (sync_var<0)
+    pthread_cond_wait(&sync_cond, &sync_mutex);
+  pthread_mutex_unlock(&sync_mutex);
+  printf("unlocked sync_mutex, waiting (UE_thread)\n");
+
+  printf("starting UE thread\n");
+
+  openair_daq_vars.freq_offset = 0; //-7500;
+
+  first_synch = 1;
+
+  while (!oai_exit)  {
+
+    hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15; //the slot the hw is about to store
+
+     
+    if (UE->is_synchronized) {
+
+      if (first_synch == 1) {
+	first_synch = 0;
+	for (card=0;card<openair0_num_detected_cards;card++)
+          openair0_start_rt_acquisition(card);
+	rt_sleep_ns(FRAME_PERIOD/10);
+      }
+
+      //this is the mbox counter that indicates the start of the frame
+      rx_offset_mbox = (UE->rx_offset * 150) / (10*UE->lte_frame_parms.samples_per_tti);
+      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_UE_RX_OFFSET, UE->rx_offset);
+      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_UE_OFFSET_MBOX, rx_offset_mbox);
+      //this is the mbox counter where we should be
+      mbox_target = (((((slot+1)%20)*15+1)>>1) + rx_offset_mbox + 1)%150;
+      // round up to the next multiple of two (mbox counter from express MIMO gives only even numbers)
+      mbox_target = ((mbox_target+1)-((mbox_target-1)%2))%150;
+      //this is the mbox counter where we are
+      mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
+      //this is the time we need to sleep in order to synchronize with the hw (in multiples of DAQ_PERIOD)
+      if ((mbox_current>=120) && (mbox_target<30)) //handle the frame wrap-arround
+	diff2 = 150-mbox_current+mbox_target;
+      else if ((mbox_current<30) && (mbox_target>=120))
+	diff2 = -150+mbox_target-mbox_current;
+      else
+	diff2 = mbox_target - mbox_current;
+	
+      if (diff2 <(-7)) {
+	LOG_D(HW,"UE Frame %d: missed slot, proceeding with next one (slot %d, hw_slot %d, diff %d)\n",frame, slot, hw_slot, diff2);
+	if (frame>0){
+	  if (exit_missed_slots==1)
+	    exit_fun("[HW][UE] missed slot");
+	  else{
+	    num_missed_slots++;
+	    LOG_W(HW,"[UE] just missed slot (total missed slots %ld)\n", num_missed_slots);
+	  }
+	}
+        slot++;
+        if (slot==20) {
+          slot=0;
+          frame++;
+        }
+	// update thread slot/frame counters because of skipped slot
+	UE->slot_rx++;
+	UE->slot_tx++;
+	
+	if (UE->slot_rx == 20) {
+	  UE->slot_rx = 0;
+	  UE->frame_rx++;
+	}
+	if (UE->slot_tx == 20) {
+	  UE->slot_tx = 0;
+	  UE->frame_tx++;
+	}
+	continue;
+      }
+      if (diff2>8)
+	LOG_D(HW,"UE Frame %d: skipped slot, waiting for hw to catch up (slot %d, hw_slot %d, mbox_current %d, mbox_target %d, diff %d)\n",frame, slot, hw_slot, mbox_current, mbox_target, diff2);
+	
+	
+      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
+      vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff2);
+	
+
+
+      // This loop implements the delay of 1 slot to allow for processing
+      delay_cnt = 0;
+      while ((diff2>0) && (!oai_exit) )  {
+        time_in = rt_get_time_ns();
+        //LOG_D(HW,"eNB Frame %d delaycnt %d : hw_slot %d (%d), slot %d (%d), diff %d, time %llu\n",frame,delay_cnt,hw_slot,((volatile unsigned int *)DAQ_MBOX)[0],slot,mbox_target,diff2,time_in);
+        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
+        vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,1);
+        ret = rt_sleep_ns(diff2*DAQ_PERIOD);
+        vcd_signal_dumper_dump_function_by_name(VCD_SIGNAL_DUMPER_FUNCTIONS_RT_SLEEP,0);
+        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
+        if (ret)
+          LOG_D(HW,"eNB Frame %d, time %llu: rt_sleep_ns returned %d\n",frame, time_in);
+          
+        hw_slot = (((((volatile unsigned int *)DAQ_MBOX)[0]+1)%150)<<1)/15;
+        //LOG_D(HW,"eNB Frame %d : hw_slot %d, time %llu\n",frame,hw_slot,rt_get_time_ns());
+        delay_cnt++;
+        if (delay_cnt == 30)  {
+          LOG_D(HW,"UE frame %d: HW stopped ... \n",frame);
+          exit_fun("[HW][UE] HW stopped");
+        }
+        mbox_current = ((volatile unsigned int *)DAQ_MBOX)[0];
+        if ((mbox_current>=135) && (mbox_target<15)) //handle the frame wrap-arround
+          diff2 = 150-mbox_current+mbox_target;
+        else if ((mbox_current<15) && (mbox_target>=135))
+          diff2 = -150+mbox_target-mbox_current;
+        else
+          diff2 = mbox_target - mbox_current;
+          
+        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DAQ_MBOX, *DAQ_MBOX);
+        vcd_signal_dumper_dump_variable_by_name(VCD_SIGNAL_DUMPER_VARIABLES_DIFF, diff2);
+      }
+
+      // on even slots, schedule processing of entire subframe
+      if ((slot&1) == 0)  {
+	
+	if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
+	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE RX thread\n");
+	  exit_fun("nothing to add");
+	}
+	else {
+	  
+	  UE->instance_cnt_rx++;
+	  //printf("UE_thread: Unlocking UE mutex_rx\n");
+	  pthread_mutex_unlock(&UE->mutex_rx);
+	  if (UE->instance_cnt_rx == 0) {
+	    LOG_D(HW,"Scheduling UE RX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_rx,frame,slot>>1,UE->slot_rx>>1,UE->mode);
+	    if (pthread_cond_signal(&UE->cond_rx) != 0) {
+	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n");
+	      exit_fun("nothing to add");
+	    }
+	    else {
+	      //	      printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
+	    }
+	    if (UE->mode == rx_calib_ue) {
+	      if (frame == 10) {
+		LOG_D(PHY,"[SCHED][UE] Found cell with N_RB_DL %d, PHICH CONFIG (%d,%d), Nid_cell %d, NB_ANTENNAS_TX %d, initial frequency offset %d Hz, frequency offset %d Hz, RSSI (digital) %d dB, measured Gain %d dB, total_rx_gain %d dB, USRP rx gain %f dB\n",
+		      UE->lte_frame_parms.N_RB_DL,
+		      UE->lte_frame_parms.phich_config_common.phich_duration,
+		      UE->lte_frame_parms.phich_config_common.phich_resource,
+		      UE->lte_frame_parms.Nid_cell,
+		      UE->lte_frame_parms.nb_antennas_tx_eNB,
+		      openair_daq_vars.freq_offset,
+		      UE->lte_ue_common_vars.freq_offset,
+		      UE->PHY_measurements.rx_power_avg_dB[0],
+		      UE->PHY_measurements.rx_power_avg_dB[0] - rx_input_level_dBm,
+		      UE->rx_total_gain_dB,
+		      openair0_cfg[0].rx_gain[0]
+		      );
+		exit_fun("[HW][UE] UE in RX calibration mode, exiting");
+	      }
+	    }
+	  }
+	  else {
+	    LOG_E(PHY,"[SCHED][UE] UE RX thread busy!!\n");
+	    exit_fun("nothing to add");
+	  }
+	}
+
+	if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
+	  LOG_E(PHY,"[SCHED][UE] error locking mutex for UE TX thread\n");
+	  exit_fun("nothing to add");
+	}
+	else {
+	  
+	  UE->instance_cnt_tx++;
+	  //printf("UE_thread: Unlocking UE mutex_rx\n");
+	  pthread_mutex_unlock(&UE->mutex_tx);
+	  if (UE->instance_cnt_tx == 0) {
+	    LOG_D(HW,"Scheduling UE TX for frame %d (hw frame %d), subframe %d (%d), mode %d\n",UE->frame_tx,frame,slot>>1,UE->slot_tx>>1,UE->mode);
+	    if (pthread_cond_signal(&UE->cond_tx) != 0) {
+	      LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE TX thread\n");
+	      exit_fun("nothing to add");
+	    }
+	    else {
+	      //	      printf("UE_thread: cond_signal for RX ok (%p) @ %llu\n",(void*)&UE->cond_rx,rt_get_time_ns()-T0);
+	    }
+	  }
+	  else {
+	    LOG_E(PHY,"[SCHED][UE] UE TX thread busy!!\n");
+	    exit_fun("nothing to add");
+	  }
+	}
+      }
+
+      /*
+	if ((slot%2000)<10)
+	LOG_D(HW,"fun0: doing very hard work\n");
+      */
+      // now increment slot and frame counters
+      slot++;
+      if (slot==20) {
+	slot=0;
+	frame++;
+      }
+    }	
+    else if (UE->is_synchronized == 0) {  // we are not yet synchronized
+      hw_slot_offset = 0;
+      first_synch = 1;
+      slot = 0;
+
+
+      // wait until we can lock mutex_synch
+      if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
+	LOG_E(PHY,"[SCHED][UE] error locking mutex for UE initial synch thread\n");
+	exit_fun("noting to add");
+      }
+      else {
+	if (UE->instance_cnt_synch < 0) {
+
+	  wait_sync_cnt=0;
+	  openair0_get_frame(0);
+	  // increment instance count for sync thread
+	  UE->instance_cnt_synch++;
+	  pthread_mutex_unlock(&UE->mutex_synch);
+	  if (pthread_cond_signal(&UE->cond_synch) != 0) {
+	    LOG_E(PHY,"[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n");
+	    exit_fun("nothing to add");
+	  }
+	}
+	else {
+	  wait_sync_cnt++;
+	  pthread_mutex_unlock(&UE->mutex_synch);
+	  if (wait_sync_cnt>1000)
+	    exit_fun("waiting to long for synch thread");
+	  else
+	    rt_sleep_ns(FRAME_PERIOD);
+	}
+      }	  
+
+      
+      /*            
+		    if (initial_sync(UE,mode)==0) {
+
+		    if (mode == rx_calib_ue) {
+		    exit_fun("[HW][UE] UE in RX calibration mode");
+		    }
+		    else {
+		    is_synchronized = 1;
+		    //start the streaming DMA transfers
+		    for (card=0;card<openair0_num_detected_cards;card++)
+		    openair0_start_rt_acquisition(card);
+	  
+		    hw_slot_offset = (UE->rx_offset<<1) / UE->lte_frame_parms.samples_per_tti;
+		    }
+		    }
+		    else {
+		    if (openair_daq_vars.freq_offset >= 0) {
+		    openair_daq_vars.freq_offset += 100;
+		    openair_daq_vars.freq_offset *= -1;
+		    }
+		    else {
+		    openair_daq_vars.freq_offset *= -1;
+		    }
+		    if (abs(openair_daq_vars.freq_offset) > 7500) {
+		    LOG_I(PHY,"[initial_sync] No cell synchronization found, abondoning\n");
+		    mac_xface->macphy_exit("No cell synchronization found, abondoning");
+		    }
+		    else {
+		    //	  LOG_I(PHY,"[initial_sync] trying carrier off %d Hz\n",openair_daq_vars.freq_offset);
+		    #ifndef USRP
+		    for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
+		    for (i=0; i<openair0_cfg[rf_map[CC_id].card].rx_num_channels; i++) 
+		    openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+openair_daq_vars.freq_offset;
+		    for (i=0; i<openair0_cfg[rf_map[CC_id].card].tx_num_channels; i++) 
+		    openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+openair_daq_vars.freq_offset;
+		    }
+		    openair0_config(&openair0_cfg[0],UE_flag);
+		    #endif
+		    rt_sleep_ns(FRAME_PERIOD);
+		    }
+		    }
+      */
+    }
+  }
+
+  LOG_D(HW,"UE_thread: finished, ran %d times.\n",frame);
+  
+#ifdef HARD_RT
+  rt_make_soft_real_time();
+#endif
+  
+  // clean task
+#ifdef RTAI
+  rt_task_delete(task);
+#endif
+  LOG_D(HW,"Task deleted. returning\n");
+  return 0;
+}
+
+#else  // This is for USRP or ETHERNET targets
+
+#endif
+
+
+void init_UE_threads(void) {
+  
+  PHY_VARS_UE *UE=PHY_vars_UE_g[0][0];
+
+  pthread_attr_init(&attr_UE_thread_tx);
+  pthread_attr_setstacksize(&attr_UE_thread_tx,16*PTHREAD_STACK_MIN);
+  sched_param_UE_thread_tx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
+  pthread_attr_setschedparam  (&attr_UE_thread_tx, &sched_param_UE_thread_tx);
+  pthread_attr_setschedpolicy (&attr_UE_thread_tx, SCHED_FIFO);
+
+  pthread_attr_init(&attr_UE_thread_rx);
+  pthread_attr_setstacksize(&attr_UE_thread_rx,8*PTHREAD_STACK_MIN);
+  sched_param_UE_thread_rx.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
+  pthread_attr_setschedparam  (&attr_UE_thread_rx, &sched_param_UE_thread_rx);
+  pthread_attr_setschedpolicy (&attr_UE_thread_rx, SCHED_FIFO);
+
+  pthread_attr_init (&attr_UE_init_synch);
+  pthread_attr_setstacksize(&attr_UE_init_synch,8*PTHREAD_STACK_MIN);
+  sched_param_UE_init_synch.sched_priority = sched_get_priority_max(SCHED_FIFO); //OPENAIR_THREAD_PRIORITY;
+  pthread_attr_setschedparam  (&attr_UE_init_synch, &sched_param_UE_init_synch);
+  pthread_attr_setschedpolicy (&attr_UE_init_synch, SCHED_FIFO);
+
+  UE->instance_cnt_tx=-1;
+  UE->instance_cnt_rx=-1;
+  UE->instance_cnt_synch=-1;
+  pthread_mutex_init(&UE->mutex_tx,NULL);
+  pthread_mutex_init(&UE->mutex_rx,NULL);
+  pthread_mutex_init(&UE->mutex_synch,NULL);
+  pthread_cond_init(&UE->cond_tx,NULL);
+  pthread_cond_init(&UE->cond_rx,NULL);
+  pthread_cond_init(&UE->cond_synch,NULL);
+  pthread_create(&UE->thread_tx,NULL,UE_thread_tx,(void*)UE);
+  pthread_create(&UE->thread_rx,NULL,UE_thread_rx,(void*)UE);
+  pthread_create(&UE->thread_rx,NULL,UE_thread_synch,(void*)UE);
+  UE->frame_tx = 0;
+  UE->frame_rx = 0;
+
+  
+}
+
+
+
+void fill_ue_band_info(void) {
+
+  UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
+  int i,j;
+
+  bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;
+  
+  for (i=0;i<bands_to_scan.nbands;i++) {
+
+    for (j=0;j<sizeof (eutra_bands) / sizeof (eutra_bands[0]);j++)
+      if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
+	memcpy(&bands_to_scan.band_info[i],
+	       &eutra_bands[j],
+	       sizeof(eutra_band_t));
+	
+	printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
+	       bands_to_scan.band_info[i].band,
+	       UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
+	       bands_to_scan.band_info[i].dl_min,
+	       bands_to_scan.band_info[i].dl_max,
+	       bands_to_scan.band_info[i].ul_min,
+	       bands_to_scan.band_info[i].ul_max,
+	       (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
+	break;
+      }
+  }
+}
+
+
+int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
+{
+
+#ifndef EXMIMO
+  uint16_t N_TA_offset = 0;
+#endif
+
+  int i, CC_id;
+  LTE_DL_FRAME_PARMS *frame_parms;
+  for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
+    if (phy_vars_ue[CC_id]) {
+      frame_parms = &(phy_vars_ue[CC_id]->lte_frame_parms); 
+    }
+    else {
+      printf("phy_vars_eNB[%d] not initialized\n", CC_id);
+      return(-1);
+    }
+
+
+#ifndef EXMIMO
+    if (frame_parms->frame_type == TDD) {
+      if (frame_parms->N_RB_DL == 100)
+	N_TA_offset = 624;
+      else if (frame_parms->N_RB_DL == 50)
+	N_TA_offset = 624/2;
+      else if (frame_parms->N_RB_DL == 25)
+	N_TA_offset = 624/4;
+    }
+#endif
+   
+#ifdef EXMIMO
+    openair0_cfg[CC_id].tx_num_channels = 0;
+    openair0_cfg[CC_id].rx_num_channels = 0;
+
+    // replace RX signal buffers with mmaped HW versions
+    for (i=0;i<frame_parms->nb_antennas_rx;i++) {
+      printf("Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
+      free(phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]);
+      phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].adc_head[rf_map[CC_id].chain+i];
+      if (openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i]) {
+	printf("Error with rf_map! A channel has already been allocated!\n");
+	return(-1);
+      }
+      else {
+	openair0_cfg[rf_map[CC_id].card].rx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i];
+	openair0_cfg[rf_map[CC_id].card].rx_gain[rf_map[CC_id].chain+i] = rx_gain[CC_id][i];
+	openair0_cfg[rf_map[CC_id].card].rxg_mode[rf_map[CC_id].chain+i] = rx_gain_mode[CC_id][i];
+	openair0_cfg[rf_map[CC_id].card].rx_num_channels++;
+      }
+
+      printf("rxdata[%d] @ %p\n",i,phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]);
+    }
+    for (i=0;i<frame_parms->nb_antennas_tx;i++) {
+      printf("Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
+      free(phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]);
+      phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = (int32_t*) openair0_exmimo_pci[rf_map[CC_id].card].dac_head[rf_map[CC_id].chain+i];
+      if (openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i]) {
+	printf("Error with rf_map! A channel has already been allocated!\n");
+	return(-1);
+      }
+      else {
+	openair0_cfg[rf_map[CC_id].card].tx_freq[rf_map[CC_id].chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
+	openair0_cfg[rf_map[CC_id].card].tx_gain[rf_map[CC_id].chain+i] = tx_gain[CC_id][i];
+	openair0_cfg[rf_map[CC_id].card].tx_num_channels++;
+      }
+
+      printf("txdata[%d] @ %p\n",i,phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]);
+    }
+  
+#else
+    // replace RX signal buffers with mmaped HW versions
+    rxdata = (int32_t**)malloc16(frame_parms->nb_antennas_rx*sizeof(int32_t*));
+    txdata = (int32_t**)malloc16(frame_parms->nb_antennas_tx*sizeof(int32_t*));
+    for (i=0;i<frame_parms->nb_antennas_rx;i++) {
+      printf("Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
+      free(phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i]);
+      rxdata[i] = (int32_t*)malloc16(samples_per_frame*sizeof(int32_t));
+      phy_vars_ue[CC_id]->lte_ue_common_vars.rxdata[i] = rxdata[i]-N_TA_offset; // N_TA offset for TDD
+    }
+    for (i=0;i<frame_parms->nb_antennas_tx;i++) {
+      printf("Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",CC_id,i,downlink_frequency[CC_id][i],rf_map[CC_id].card,rf_map[CC_id].chain+i);
+      free(phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i]);
+      txdata[i] = (int32_t*)malloc16(samples_per_frame*sizeof(int32_t));
+      phy_vars_ue[CC_id]->lte_ue_common_vars.txdata[i] = txdata[i];
+      memset(txdata[i], 0, samples_per_frame*sizeof(int32_t));
+    }
+    
+#endif
+    
+  }
+  return(0);
+
+}
diff --git a/targets/RT/USER/ue.gtkw b/targets/RT/USER/ue.gtkw
index bd87b29b72db12c4b35b57f10101376a4dd9a779..b5cbeed8a6234163b5de9ee48e1ebd8ee18343aa 100644
--- a/targets/RT/USER/ue.gtkw
+++ b/targets/RT/USER/ue.gtkw
@@ -26,6 +26,8 @@ variables.frame_number_TX_UE[63:0]
 variables.subframe_number_RX_UE[63:0]
 variables.subframe_number_TX_UE[63:0]
 @28
+functions.trx_read
+functions.ue_synch
 functions.ue_slot_fep
 functions.lte_ue_measurement_procedures
 functions.ue_rrc_measurements