diff --git a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c
index dfb39a510f0faac40d8598bbc6a286908c627b66..5f0ba9b2d2e40080c7018caf2eaa0178e465b9e5 100644
--- a/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c
+++ b/openair1/PHY/LTE_ESTIMATION/lte_sync_time.c
@@ -517,14 +517,15 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
 
   // perform a time domain correlation using the oversampled sync sequence
 
-  unsigned int n, ar, peak_val, peak_pos, mean_val;
+  unsigned int n, ar, peak_val, peak_pos;
+  uint64_t mean_val;
   int result;
   short *primary_synch_time;
   int eNB_id = frame_parms->Nid_cell%3;
 
   // msg("[SYNC TIME] Calling sync_time_eNB(%p,%p,%d,%d)\n",rxdata,frame_parms,eNB_id,length);
   if (sync_corr_eNB == NULL) {
-    msg("[SYNC TIME] sync_corr_eNB not yet allocated! Exiting.\n");
+    LOG_E(PHY,"[SYNC TIME] sync_corr_eNB not yet allocated! Exiting.\n");
     return(-1);
   }
 
@@ -542,7 +543,7 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
     break;
 
   default:
-    msg("[SYNC TIME] Illegal eNB_id!\n");
+    LOG_E(PHY,"[SYNC TIME] Illegal eNB_id!\n");
     return (-1);
   }
 
@@ -574,7 +575,7 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
        peak_val);
     }
     */
-    mean_val += (sync_corr_eNB[n]>>10);
+    mean_val += sync_corr_eNB[n];
 
     if (sync_corr_eNB[n]>peak_val) {
       peak_val = sync_corr_eNB[n];
@@ -582,17 +583,15 @@ int lte_sync_time_eNB(int32_t **rxdata, ///rx data in time domain
     }
   }
 
+  mean_val/=length;
+
   *peak_val_out = peak_val;
 
-  if (peak_val <= (40*mean_val)) {
-#ifdef DEBUG_PHY
-    msg("[SYNC TIME] No peak found (%u,%u,%u,%u)\n",peak_pos,peak_val,mean_val,40*mean_val);
-#endif
+  if (peak_val <= (40*(uint32_t)mean_val)) {
+    LOG_D(PHY,"[SYNC TIME] No peak found (%u,%u,%u,%u)\n",peak_pos,peak_val,mean_val,40*mean_val);
     return(-1);
   } else {
-#ifdef DEBUG_PHY
-    msg("[SYNC TIME] Peak found at pos %u, val = %u, mean_val = %u\n",peak_pos,peak_val,mean_val);
-#endif
+    LOG_D(PHY,"[SYNC TIME] Peak found at pos %u, val = %u, mean_val = %u\n",peak_pos,peak_val,mean_val);
     return(peak_pos);
   }
 
diff --git a/openair1/PHY/defs.h b/openair1/PHY/defs.h
index 703bdd2d6fde21273ea9d8bc56453df9db061f1e..e42157769db93e13298a39bed5de914718825ca8 100755
--- a/openair1/PHY/defs.h
+++ b/openair1/PHY/defs.h
@@ -256,6 +256,8 @@ typedef struct eNB_proc_t_s {
   /// \brief Instance count for rx processing thread.
   /// \internal This variable is protected by \ref mutex_prach.
   int instance_cnt_prach;
+  // instance count for over-the-air eNB synchronization
+  int instance_cnt_synch;
   /// \internal This variable is protected by \ref mutex_asynch_rxtx.
   int instance_cnt_asynch_rxtx;
   /// pthread structure for FH processing thread
@@ -280,6 +282,8 @@ typedef struct eNB_proc_t_s {
   pthread_attr_t attr_single;
   /// pthread attributes for prach processing thread
   pthread_attr_t attr_prach;
+  /// pthread attributes for over-the-air synch thread
+  pthread_attr_t attr_synch;
   /// pthread attributes for asynchronous RX thread
   pthread_attr_t attr_asynch_rxtx;
   /// scheduling parameters for parallel fep thread
@@ -294,6 +298,8 @@ typedef struct eNB_proc_t_s {
   struct sched_param sched_param_single;
   /// scheduling parameters for prach thread
   struct sched_param sched_param_prach;
+  /// scheduling parameters for over-the-air synchronization thread
+  struct sched_param sched_param_synch;
   /// scheduling parameters for asynch_rxtx thread
   struct sched_param sched_param_asynch_rxtx;
   /// pthread structure for parallel fep thread
@@ -304,6 +310,8 @@ typedef struct eNB_proc_t_s {
   pthread_t pthread_te;
   /// pthread structure for PRACH thread
   pthread_t pthread_prach;
+  /// pthread structure for eNB synch thread
+  pthread_t pthread_synch;
   /// condition variable for parallel fep thread
   pthread_cond_t cond_fep;
   /// condition variable for parallel turbo-decoder thread
@@ -314,6 +322,8 @@ typedef struct eNB_proc_t_s {
   pthread_cond_t cond_FH;
   /// condition variable for PRACH processing thread;
   pthread_cond_t cond_prach;
+  // condition variable for over-the-air eNB synchronization
+  pthread_cond_t cond_synch;
   /// condition variable for asynch RX/TX thread
   pthread_cond_t cond_asynch_rxtx;
   /// mutex for parallel fep thread
@@ -326,6 +336,8 @@ typedef struct eNB_proc_t_s {
   pthread_mutex_t mutex_FH;
   /// mutex for PRACH thread
   pthread_mutex_t mutex_prach;
+  // mutex for over-the-air eNB synchronization
+  pthread_mutex_t mutex_synch;
   /// mutex for asynch RX/TX thread
   pthread_mutex_t mutex_asynch_rxtx;
   /// parameters for turbo-decoding worker thread
@@ -411,6 +423,10 @@ typedef struct PHY_VARS_eNB_s {
   openair0_rf_map      rf_map;
   int                  abstraction_flag;
   openair0_timestamp   ts_offset;
+  // indicator for synchronization state of eNB
+  int                  in_synch;
+  // indicator for master/slave (RRU)
+  int                  is_slave;
   void                 (*do_prach)(struct PHY_VARS_eNB_s *eNB);
   void                 (*fep)(struct PHY_VARS_eNB_s *eNB);
   int                  (*td)(struct PHY_VARS_eNB_s *eNB,int UE_id,int harq_pid,int llr8_flag);
diff --git a/targets/RT/USER/lte-enb.c b/targets/RT/USER/lte-enb.c
index 58494caed4d845a3eb759c648e20d0eef85c0583..66d60bf2cccc068892435d23d1bf413bde6f33fc 100644
--- a/targets/RT/USER/lte-enb.c
+++ b/targets/RT/USER/lte-enb.c
@@ -161,7 +161,7 @@ static struct {
 
 void exit_fun(const char* s);
 
-void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *,int);
+void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *,int,int);
 void stop_eNB(int nb_inst);
 
 
@@ -1122,6 +1122,114 @@ void wakeup_slaves(eNB_proc_t *proc) {
   }
 }
 
+uint32_t sync_corr[307200] __attribute__((aligned(32)));
+
+// This thread run the initial synchronization like a UE
+void *eNB_thread_synch(void *arg) {
+
+  PHY_VARS_eNB *eNB = (PHY_VARS_eNB*)arg;
+  LTE_DL_FRAME_PARMS *fp=&eNB->frame_parms;
+  int32_t sync_pos,sync_pos2;
+  uint32_t peak_val;
+
+  thread_top_init("eNB_thread_synch",0,5000000,10000000,10000000);
+
+  wait_sync("eNB_thread_synch");
+
+  // initialize variables for PSS detection
+  lte_sync_time_init(&eNB->frame_parms);
+
+  while (!oai_exit) {
+
+    // wait to be woken up
+    pthread_mutex_lock(&eNB->proc.mutex_synch);
+    while (eNB->proc.instance_cnt_synch < 0)
+      pthread_cond_wait(&eNB->proc.cond_synch,&eNB->proc.mutex_synch);
+    pthread_mutex_unlock(&eNB->proc.mutex_synch);
+
+    // if we're not in synch, then run initial synch
+    if (eNB->in_synch == 0) { 
+      // run intial synch like UE
+      LOG_I(PHY,"Running initial synchronization\n");
+      
+      sync_pos = lte_sync_time_eNB(eNB->common_vars.rxdata[0],
+				   fp,
+				   fp->samples_per_tti*5,
+				   &peak_val,
+				   sync_corr);
+      LOG_I(PHY,"eNB synch: %d, val %d\n",sync_pos,peak_val);
+
+      if (sync_pos >= 0) {
+	if (sync_pos >= fp->nb_prefix_samples)
+	  sync_pos2 = sync_pos - fp->nb_prefix_samples;
+	else
+	  sync_pos2 = sync_pos + (fp->samples_per_tti*10) - fp->nb_prefix_samples;
+	
+	if (fp->frame_type == FDD) {
+	  
+	  // PSS is hypothesized in last symbol of first slot in Frame
+	  int sync_pos_slot = (fp->samples_per_tti>>1) - fp->ofdm_symbol_size - fp->nb_prefix_samples;
+	  
+	  if (sync_pos2 >= sync_pos_slot)
+	    eNB->rx_offset = sync_pos2 - sync_pos_slot;
+	  else
+	    eNB->rx_offset = (fp->samples_per_tti*10) + sync_pos2 - sync_pos_slot;
+	}
+	else {
+	  
+	}
+
+	LOG_I(PHY,"Estimated sync_pos %d, peak_val %d => timing offset %d\n",sync_pos,peak_val,eNB->rx_offset);
+	
+
+      /*      if ((peak_val > 10000) && (sync_pos == -1)) {
+	//      if (sync_pos++ > 3) {
+	write_output("eNB_sync.m","sync",(void*)&sync_corr[0],fp->samples_per_tti*5,1,2);
+	write_output("eNB_rx.m","rxs",(void*)eNB->common_vars.rxdata[0][0],fp->samples_per_tti*10,1,1);
+	exit(-1);
+	}*/
+      }
+    }
+
+    // release thread
+    pthread_mutex_lock(&eNB->proc.mutex_synch);
+    eNB->proc.instance_cnt_synch--;
+    pthread_mutex_unlock(&eNB->proc.mutex_synch);
+  } // oai_exit
+
+  lte_sync_time_free();
+
+}
+
+int wakeup_synch(PHY_VARS_eNB *eNB){
+
+  struct timespec wait;
+  
+  wait.tv_sec=0;
+  wait.tv_nsec=5000000L;
+
+  // wake up synch thread
+  // lock the synch mutex and make sure the thread is ready
+  if (pthread_mutex_timedlock(&eNB->proc.mutex_synch,&wait) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_mutex_lock for eNB synch thread (IC %d)\n", eNB->proc.instance_cnt_synch );
+    exit_fun( "error locking mutex_synch" );
+    return(-1);
+  }
+  
+  ++eNB->proc.instance_cnt_synch;
+  
+  // the thread can now be woken up
+  if (pthread_cond_signal(&eNB->proc.cond_synch) != 0) {
+    LOG_E( PHY, "[eNB] ERROR pthread_cond_signal for eNB synch thread\n");
+    exit_fun( "ERROR pthread_cond_signal" );
+    return(-1);
+  }
+  
+  pthread_mutex_unlock( &eNB->proc.mutex_synch );
+
+  return(0);
+}
+
 /*!
  * \brief The Fronthaul thread of RRU/RAU/RCC/eNB
  * In the case of RRU/eNB, handles interface with external RF
@@ -1242,6 +1350,8 @@ static void* eNB_thread_prach( void* param ) {
   return &eNB_thread_prach_status;
 }
 
+
+
 static void* eNB_thread_single( void* param ) {
 
   static int eNB_thread_single_status;
@@ -1249,9 +1359,24 @@ static void* eNB_thread_single( void* param ) {
   eNB_proc_t *proc = (eNB_proc_t*)param;
   eNB_rxtx_proc_t *proc_rxtx = &proc->proc_rxtx[0];
   PHY_VARS_eNB *eNB = PHY_vars_eNB_g[0][proc->CC_id];
+  LTE_DL_FRAME_PARMS *fp = &eNB->frame_parms;
+
+  void *rxp[2],*rxp2[2];
 
   int subframe=0, frame=0; 
 
+  int32_t dummy_rx[fp->nb_antennas_rx][fp->samples_per_tti] __attribute__((aligned(32)));
+
+  int ic;
+
+  int rxs;
+
+  int i;
+
+  // initialize the synchronization buffer to the common_vars.rxdata
+  for (int i=0;i<fp->nb_antennas_rx;i++)
+    rxp[i] = &eNB->common_vars.rxdata[0][i][0];
+
   // set default return value
   eNB_thread_single_status = 0;
 
@@ -1280,6 +1405,57 @@ static void* eNB_thread_single( void* param ) {
   pthread_mutex_unlock(&proc->mutex_asynch_rxtx);
   pthread_cond_signal(&proc->cond_asynch_rxtx);
 
+
+
+  // if this is a slave eNB, try to synchronize on the DL frequency
+  if ((eNB->is_slave) &&
+      ((eNB->node_function >= NGFI_RRU_IF5))) {
+    // if FDD, switch RX on DL frequency
+    
+    double temp_freq1 = eNB->rfdevice.openair0_cfg->rx_freq[0];
+    double temp_freq2 = eNB->rfdevice.openair0_cfg->tx_freq[0];
+    for (i=0;i<4;i++) {
+      eNB->rfdevice.openair0_cfg->rx_freq[i] = eNB->rfdevice.openair0_cfg->tx_freq[i];
+      eNB->rfdevice.openair0_cfg->tx_freq[i] = temp_freq1;
+    }
+    eNB->rfdevice.trx_set_freq_func(&eNB->rfdevice,eNB->rfdevice.openair0_cfg,0);
+
+    while ((eNB->in_synch ==0)&&(!oai_exit)) {
+      // read in frame
+      rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
+					&(proc->timestamp_rx),
+					rxp,
+					fp->samples_per_tti*10,
+					fp->nb_antennas_rx);
+      // wakeup synchronization processing thread
+      wakeup_synch(eNB);
+      ic=0;
+      
+      while ((ic>=0)&&(!oai_exit)) {
+	// continuously read in frames, 1ms at a time, 
+	// until we are done with the synchronization procedure
+	
+	for (i=0; i<fp->nb_antennas_rx; i++)
+	  rxp2[i] = (void*)&dummy_rx[i][0];
+	for (i=0;i<10;i++)
+	  rxs = eNB->rfdevice.trx_read_func(&eNB->rfdevice,
+					    &(proc->timestamp_rx),
+					    rxp2,
+					    fp->samples_per_tti,
+					    fp->nb_antennas_rx);
+	pthread_mutex_lock(&eNB->proc.mutex_synch);
+	ic = eNB->proc.instance_cnt_synch;
+	pthread_mutex_unlock(&eNB->proc.mutex_synch);
+      } // ic>=0
+    } // in_synch==0
+    for (i=0;i<4;i++) {
+      eNB->rfdevice.openair0_cfg->rx_freq[i] = temp_freq1;
+      eNB->rfdevice.openair0_cfg->rx_freq[i] = temp_freq2;
+    }
+    eNB->rfdevice.trx_set_freq_func(&eNB->rfdevice,eNB->rfdevice.openair0_cfg,0);
+  } // if RRU and slave
+
+
   // This is a forever while loop, it loops over subframes which are scheduled by incoming samples from HW devices
   while (!oai_exit) {
 
@@ -1334,7 +1510,7 @@ void init_eNB_proc(int inst) {
   PHY_VARS_eNB *eNB;
   eNB_proc_t *proc;
   eNB_rxtx_proc_t *proc_rxtx;
-  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te;
+  pthread_attr_t *attr0=NULL,*attr1=NULL,*attr_FH=NULL,*attr_prach=NULL,*attr_asynch=NULL,*attr_single=NULL,*attr_fep=NULL,*attr_td=NULL,*attr_te=NULL,*attr_synch=NULL;
 
   for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
     eNB = PHY_vars_eNB_g[inst][CC_id];
@@ -1348,7 +1524,8 @@ void init_eNB_proc(int inst) {
     proc->instance_cnt_FH          = -1;
     proc->instance_cnt_asynch_rxtx = -1;
     proc->CC_id = CC_id;    
-    
+    proc->instance_cnt_synch        =  -1;
+
     proc->first_rx=1;
     proc->first_tx=1;
 
@@ -1359,13 +1536,16 @@ void init_eNB_proc(int inst) {
 
     pthread_mutex_init( &proc->mutex_prach, NULL);
     pthread_mutex_init( &proc->mutex_asynch_rxtx, NULL);
+    pthread_mutex_init( &proc->mutex_synch,NULL);
 
     pthread_cond_init( &proc->cond_prach, NULL);
     pthread_cond_init( &proc->cond_FH, NULL);
     pthread_cond_init( &proc->cond_asynch_rxtx, NULL);
+    pthread_cond_init( &proc->cond_synch,NULL);
 
     pthread_attr_init( &proc->attr_FH);
     pthread_attr_init( &proc->attr_prach);
+    pthread_attr_init( &proc->attr_synch);
     pthread_attr_init( &proc->attr_asynch_rxtx);
     pthread_attr_init( &proc->attr_single);
     pthread_attr_init( &proc->attr_fep);
@@ -1378,6 +1558,7 @@ void init_eNB_proc(int inst) {
     attr1       = &proc_rxtx[1].attr_rxtx;
     attr_FH     = &proc->attr_FH;
     attr_prach  = &proc->attr_prach;
+    attr_synch  = &proc->attr_synch;
     attr_asynch = &proc->attr_asynch_rxtx;
     attr_single = &proc->attr_single;
     attr_fep    = &proc->attr_fep;
@@ -1397,6 +1578,7 @@ void init_eNB_proc(int inst) {
       init_te_thread(eNB,attr_te);
     }
     pthread_create( &proc->pthread_prach, attr_prach, eNB_thread_prach, &eNB->proc );
+    pthread_create( &proc->pthread_synch, attr_synch, eNB_thread_synch, eNB);
     if ((eNB->node_timing == synch_to_other) ||
 	(eNB->node_function == NGFI_RRU_IF5) ||
 	(eNB->node_function == NGFI_RRU_IF4p5))
@@ -1619,7 +1801,7 @@ extern void eNB_fep_full(PHY_VARS_eNB *eNB);
 extern void eNB_fep_full_2thread(PHY_VARS_eNB *eNB);
 extern void do_prach(PHY_VARS_eNB *eNB);
 
-void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params,int single_thread_flag) {
+void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst,eth_params_t *eth_params,int single_thread_flag,int wait_for_sync) {
   
   int CC_id;
   int inst;
@@ -1634,6 +1816,9 @@ void init_eNB(eNB_func_t node_function[], eNB_timing_t node_timing[],int nb_inst
       eNB->abstraction_flag   = 0;
       eNB->single_thread_flag = single_thread_flag;
       eNB->ts_offset          = 0;
+      eNB->in_synch           = 0;
+      eNB->is_slave           = (wait_for_sync>0) ? 1 : 0;
+
       LOG_I(PHY,"Initializing eNB %d CC_id %d : (%s,%s)\n",inst,CC_id,eNB_functions[node_function[CC_id]],eNB_timing[node_timing[CC_id]]);
 
       switch (node_function[CC_id]) {
diff --git a/targets/RT/USER/lte-softmodem.c b/targets/RT/USER/lte-softmodem.c
index eeb06753f3a0f10ef67a6c3416444b9b3b6c01e6..d2f2f9ccfbbea735596d38e7ce39a7779415078f 100644
--- a/targets/RT/USER/lte-softmodem.c
+++ b/targets/RT/USER/lte-softmodem.c
@@ -120,7 +120,7 @@ extern int netlink_init(void);
 
 // In lte-enb.c
 extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg);
-extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int);
+extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int,int);
 extern void stop_eNB(int);
 extern void kill_eNB_proc(void);
 
@@ -170,6 +170,8 @@ volatile int             oai_exit = 0;
 
 static clock_source_t clock_source = internal;
 
+static wait_for_sync = 0;
+
 static char              UE_flag=0;
 unsigned int                    mmapped_dma=0;
 int                             single_thread_flag=0;
@@ -696,6 +698,7 @@ static void get_options (int argc, char **argv)
     LONG_OPTION_MMAPPED_DMA,
     LONG_OPTION_SINGLE_THREAD,
     LONG_OPTION_EXTERNAL_CLOCK,
+    LONG_OPTION_WAIT_FOR_SYNC,
 #if T_TRACER
     LONG_OPTION_T_PORT,
     LONG_OPTION_T_NOWAIT,
@@ -722,6 +725,7 @@ static void get_options (int argc, char **argv)
     {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
     {"single-thread", no_argument, NULL, LONG_OPTION_SINGLE_THREAD},
     {"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK},
+    {"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC},
 #if T_TRACER
     {"T_port",                 required_argument, 0, LONG_OPTION_T_PORT},
     {"T_nowait",               no_argument,       0, LONG_OPTION_T_NOWAIT},
@@ -827,6 +831,10 @@ static void get_options (int argc, char **argv)
       clock_source = external;
       break;
 
+    case LONG_OPTION_WAIT_FOR_SYNC:
+      wait_for_sync = 1;
+      break;
+
 #if T_TRACER
     case LONG_OPTION_T_PORT: {
       extern int T_port;
@@ -1808,7 +1816,7 @@ int main( int argc, char **argv )
   // start the main thread
   if (UE_flag == 1) init_UE(1);
   else { 
-    init_eNB(node_function,node_timing,1,eth_params,single_thread_flag);
+    init_eNB(node_function,node_timing,1,eth_params,single_thread_flag,wait_for_sync);
   // Sleep to allow all threads to setup
 
     number_of_cards = 1;