diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c
new file mode 100644
index 0000000000000000000000000000000000000000..dc02f5d28ae86973ce96fb9de031848bec1597be
--- /dev/null
+++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c
@@ -0,0 +1,674 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file PHY/NR_TRANSPORT/nr_prach.c
+ * \brief Top-level routines for generating and decoding the PRACH physical channel V15.4 2018-12
+ * \author R. Knopp
+ * \date 2019
+ * \version 0.1
+ * \company Eurecom
+ * \email: knopp@eurecom.fr
+ * \note
+ * \warning
+ */
+
+void rx_nr_prach(PHY_VARS_gNB *gNB,
+		 RU_t *ru,
+		 uint16_t *max_preamble,
+		 uint16_t *max_preamble_energy,
+		 uint16_t *max_preamble_delay,
+		 uint16_t Nf, 
+		 uint8_t tdd_mapindex
+		 )
+{
+
+  int i;
+
+  NR_DL_FRAME_PARMS *fp;
+  lte_frame_type_t   frame_type;
+  uint16_t           rootSequenceIndex;  
+  uint8_t            prach_ConfigIndex;   
+  uint8_t            Ncs_config;          
+  uint8_t            restricted_set;      
+  uint8_t            n_ra_prb;
+  int                subframe;
+  int16_t            *prachF=NULL;
+  int16_t            **rxsigF=NULL;
+  int                nb_rx;
+
+  int16_t *prach2;
+  uint8_t preamble_index;
+  uint16_t NCS,NCS2;
+  uint16_t preamble_offset=0,preamble_offset_old;
+  int16_t preamble_shift=0;
+  uint32_t preamble_shift2;
+  uint16_t preamble_index0=0,n_shift_ra=0,n_shift_ra_bar;
+  uint16_t d_start=0;
+  uint16_t numshift=0;
+  uint16_t *prach_root_sequence_map;
+  uint8_t not_found;
+  int k=0;
+  uint16_t u;
+  int16_t *Xu=0;
+  uint16_t offset;
+  int16_t Ncp;
+  uint16_t first_nonzero_root_idx=0;
+  uint8_t new_dft=0;
+  uint8_t aa;
+  int32_t lev;
+  int16_t levdB;
+  int fft_size,log2_ifft_size;
+  int16_t prach_ifft_tmp[2048*2] __attribute__((aligned(32)));
+  int32_t *prach_ifft=(int32_t*)NULL;
+  int32_t **prach_ifftp=(int32_t **)NULL;
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+  int prach_ifft_cnt=0;
+#endif
+
+
+  if (ru) { 
+    fp    = ru->frame_parms;
+    nb_rx = ru->nb_rx;
+  }
+  else if (gNB) {
+    fp    = &gNB->frame_parms;
+    nb_rx = fp->nb_antennas_rx;
+  }
+  else AssertFatal(1==0,"rx_prach called without valid RU or gNB descriptor\n");
+  
+  frame_type          = fp->frame_type;
+
+  rootSequenceIndex   = fp->prach_config_common.rootSequenceIndex;
+  prach_ConfigIndex   = fp->prach_config_common.prach_ConfigInfo.prach_ConfigIndex;
+  Ncs_config          = fp->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig;
+  restricted_set      = fp->prach_config_common.prach_ConfigInfo.highSpeedFlag;
+  n_ra_prb            = get_prach_prb_offset(fp,prach_ConfigIndex,
+					     fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,
+					     tdd_mapindex,Nf);
+   
+
+  int16_t *prach[nb_rx];
+  uint8_t prach_fmt = get_prach_fmt(prach_ConfigIndex,frame_type);
+  uint16_t N_ZC = (prach_fmt <4)?839:139;
+  
+  if (gNB) {
+    prach_ifftp       = gNB->prach_vars.prach_ifft[0];
+    subframe          = gNB->proc.subframe_prach;
+    prachF            = gNB->prach_vars.prachF;
+    rxsigF            = gNB->prach_vars.rxsigF[0];
+    if (LOG_DEBUGFLAG(PRACH)){
+      if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (gNB) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d , rootSequenceIndex %d\n", subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex,rootSequenceIndex);
+    }
+  }
+  else {
+    subframe          = ru->proc.subframe_prach;
+    rxsigF            = ru->prach_rxsigF;
+    if (LOG_DEBUGFLAG(PRACH)){
+      if (((ru->proc.frame_prach)&1023) < 20) LOG_I(PHY,"PRACH (RU) : running rx_prach for subframe %d, prach_FreqOffset %d, prach_ConfigIndex %d\n",
+						    subframe,fp->prach_config_common.prach_ConfigInfo.prach_FreqOffset,prach_ConfigIndex);
+    }
+  }
+
+  AssertFatal(ru!=NULL,"ru is null\n");
+
+  for (aa=0; aa<nb_rx; aa++) {
+    if (ru->if_south == LOCAL_RF) { // set the time-domain signal if we have to use it in this node
+      // DJP - indexing below in subframe zero takes us off the beginning of the array???
+      prach[aa] = (int16_t*)&ru->common.rxdata[aa][(subframe*fp->samples_per_tti)-ru->N_TA_offset];
+
+        if (LOG_DUMPFLAG(PRACH)){
+          int32_t en0=signal_energy((int32_t*)prach[aa],fp->samples_per_tti);
+          int8_t dbEn0 = dB_fixed(en0);
+          int8_t rach_dBm = dbEn0 - ru->rx_total_gain_dB;
+          char buffer[80];
+          if (dbEn0>32 && prach[0]!= NULL) {
+            static int counter=0;
+            sprintf(buffer, "%s%d", "/tmp/prach_rx",counter);
+            LOG_M(buffer,"prach_rx",prach[0],fp->samples_per_tti,1,13);
+          }
+        if (dB_fixed(en0)>32) {
+          sprintf(buffer, "rach_dBm:%d",rach_dBm);
+          if (prach[0]!= NULL) LOG_M("prach_rx","prach_rx",prach[0],fp->samples_per_tti,1,1);
+            LOG_I(PHY,"RU %d, br_flag %d ce_level %d frame %d subframe %d per_tti:%d prach:%p (energy %d) TA:%d %s rxdata:%p index:%d\n",
+                  ru->idx,br_flag,ce_level,ru->proc.frame_prach,subframe,fp->samples_per_tti,
+                  prach[aa],dbEn0,ru->N_TA_offset,buffer,ru->common.rxdata[aa], 
+                  (subframe*fp->samples_per_tti)-ru->N_TA_offset);
+        }
+      }
+    }
+  }
+
+  // First compute physical root sequence
+  if (restricted_set == 0) {
+    AssertFatal(Ncs_config<=15,
+		"Illegal Ncs_config for unrestricted format %d\n",Ncs_config);
+    NCS = NCS_unrestricted[Ncs_config];
+  } else {
+    AssertFatal(Ncs_config<=14,
+		"FATAL, Illegal Ncs_config for restricted format %d\n",Ncs_config);
+    NCS = NCS_restricted[Ncs_config];
+  }
+
+  if (gNB) start_meas(&gNB->rx_prach);
+
+
+  prach_root_sequence_map = (prach_fmt < 4) ? prach_root_sequence_map0_3 : prach_root_sequence_map4;
+
+  // PDP is oversampled, e.g. 1024 sample instead of 839
+  // Adapt the NCS (zero-correlation zones) with oversampling factor e.g. 1024/839
+  NCS2 = (N_ZC==839) ? ((NCS<<10)/839) : ((NCS<<8)/139);
+
+  if (NCS2==0)
+    NCS2 = N_ZC;
+
+  switch (prach_fmt) {
+  case 0:
+    Ncp = 3168;
+    break;
+
+  case 1:
+    Ncp = 21024;
+    break;
+
+  case 2:
+    Ncp = 4688;
+    break;
+
+  case 3:
+    Ncp = 3168;
+    break;
+
+  case 0xa1:
+    Ncp = 288/(1<<mu);
+    break;
+
+  case 0xa2:
+    Ncp = 576/(1<<mu);
+    break;
+
+  case 0xa3:
+    Ncp = 864/(1<<mu);
+    break;
+
+  case 0xb1:
+    Ncp = 216/(1<<mu);
+    break;
+
+  case 0xb2:
+    Ncp = 360/(1<<mu);
+    break;
+
+  case 0xb3:
+    Ncp = 504/(1<<mu);
+    break;
+
+  case 0xb4:
+    Ncp = 936/(1<<mu);
+    break;
+
+  case 0xc0:
+    Ncp = 1240/(1<<mu);
+    break;
+
+  case 0xc2:
+    Ncp = 2048/(1<<mu);
+    break;
+
+  default:
+    Ncp = 3168;
+    break;
+  }
+
+  // Note: Assumes PUSCH SCS @ 30 kHz, take values for formats 0-2 and adjust for others below
+  int kbar = 1;
+  int K    = 24;
+  if (prach_fmt == 3) { 
+    K=4;
+    kbar=10;
+  }
+  else if (prach_fmt > 3) {
+    // Note: Assumes that PRACH SCS is same as PUSCH SCS
+    K=1;
+    kbar=2;
+  }
+  if (((gNB!=NULL) && (ru->function != NGFI_RAU_IF4p5))||
+      ((gNB==NULL) && (ru->function == NGFI_RRU_IF4p5))) { // compute the DFTs of the PRACH temporal resources
+    // Do forward transform
+    if (LOG_DEBUGFLAG(PRACH)) {
+      LOG_D(PHY,"rx_prach: Doing FFT for N_RB_UL %d nb_rx:%d Ncp:%d\n",fp->N_RB_UL, nb_rx, Ncp);
+    }
+    for (aa=0; aa<nb_rx; aa++) {
+      AssertFatal(prach[aa]!=NULL,"prach[%d] is null\n",aa);
+      prach2 = prach[aa] + (Ncp<<1);
+  
+      // do DFT
+      switch (fp->N_RB_UL) {
+      case 6:
+      case 15:
+      case 25:
+      case 50:
+      case 75:
+      case 100:
+	AssertFatal(1==0,"N_RB_UL %d not support for NR PRACH yet\n",fp->N_RB_UL);
+	break;
+      case 106: 
+      case 136: 
+	if (fp->threequarter_fs==0) { 
+	  //40 MHz @ 61.44 Ms/s 
+	  //50 MHz @ 61.44 Ms/s 
+	  if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2)
+	    dft24576(prach2,rxsigF[aa],1);
+	  if (prach_fmt == 1 || prach_fmt == 2)
+	    dft24576(prach2+49152,rxsigF[aa]+49152,1);
+	  if (prach_fmt == 2) {
+	    dft24576(prach2+(49152*2),rxsigF[aa]+(49152*2),1);
+	    dft24576(prach2+(49152*3),rxsigF[aa]+(49152*3),1);
+	  }
+          if (prach_fmt == 3) 
+	    for (int i=0;i<4;i++) dft6144(prach2+(i*12288),rxsigF[aa]+(i*12288),1);
+	  if (prach_fmt >3) {
+	    dft2048(prach2,rxsigF[aa],1);
+	    if (prach_fmt != 0xc0) dft2048(prach2+4096,rxsigF[aa]+4096,1);
+	  } 
+	  if (prach_fmt == 0xa2 || prach_fmt == 0xa3 || prach_fmt == 0xb2 || prach_fmt == 0xb3 || prach_fmt == 0xb4 || prach_fmt == 0xc2) {     
+	    dft2048(prach2+4096*2,rxsigF[aa]+4096*2,1);
+	    dft2048(prach2+4096*3,rxsigF[aa]+4096*3,1);
+	  } 
+	  if (prach_fmt == 0xa3 || prach_fmt == 0xb3 || prach_fmt == 0xc2) {     
+	    dft2048(prach2+4096*4,rxsigF[aa]+4096*4,1);
+	    dft2048(prach2+4096*5,rxsigF[aa]+4096*5,1);
+	  } 
+          if (prach_fmt == 0xc2)
+	    for (int i=6;i<11;i++) dft2048(prach2+(3072*i),rxsigF[aa]+(3072*i),1);
+	} else {
+	  //	40 MHz @ 46.08 Ms/s
+	  AssertFatal(fp->N_RB_UL == 106,"cannot do 136 PRBs with 3/4 sampling\n");
+	  if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2)
+	    dft18432(prach2,rxsigF[aa],1);
+	  if (prach_fmt == 1 || prach_fmt == 2)
+	    dft18432(prach2+36864,rxsigF[aa]+36864,1);
+	  if (prach_fmt == 3)
+	    dft18432(prach2+(2*36864),rxsigF[aa]+(2*36864),1);
+	  if (prach_fmt >3) {
+	    dft1536(prach2,rxsigF[aa],1);
+	    if (prach_fmt != 0xc0) dft1536(prach2+3072,rxsigF[aa]+3072,1);
+	  } 
+	  if (prach_fmt == 0xa2 || prach_fmt == 0xa3 || prach_fmt == 0xb2 || prach_fmt == 0xb3 || prach_fmt == 0xb4 || prach_fmt == 0xc2) {     
+	    dft1536(prach2+3072*2,rxsigF[aa]+3072*2,1);
+	    dft1536(prach2+3072*3,rxsigF[aa]+3072*3,1);
+	  } 
+	  if (prach_fmt == 0xa3 || prach_fmt == 0xb3 || prach_fmt == c2) {     
+	    dft1536(prach2+3072*4,rxsigF[aa]+3072*4,1);
+	    dft1536(prach2+3072*5,rxsigF[aa]+3072*5,1);
+	  } 
+          if (prach_fmt == 0xc2)
+	    for (int i=6;i<11;i++) dft1536(prach2+(3072*i),rxsigF[aa]+(3072*i),1);
+	}
+	break;
+      case 216:
+      case 246:
+      case 272: 
+	if (fp->threequarter_fs==0) { 
+	  //80,90,100 MHz @ 61.44 Ms/s 
+	  if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2)
+	    dft49152(prach2,rxsigF[aa],1);
+	  if (prach_fmt == 1 || prach_fmt == 2)
+	    dft49152(prach2+98304,rxsigF[aa]+98304,1);
+          if (prach_fmt == 3)
+	    dft49152(prach2+(2*98304),rxsigF[aa]+(2*98304),1);
+
+	  if (prach_fmt >3) {
+	    dft4096(prach2,rxsigF[aa],1);
+	    if (prach_fmt != 0xc0) dft4096(prach2+8192,rxsigF[aa]+8192,1);
+	  } 
+	  if (prach_fmt == 0xa2 || prach_fmt == 0xa3 || prach_fmt == 0xb2 || prach_fmt == 0xb3 || prach_fmt == 0xb4 || prach_fmt == 0xc2) {     
+	    dft4096(prach2+8192*2,rxsigF[aa]+8192*2,1);
+	    dft4096(prach2+8192*3,rxsigF[aa]+8192*3,1);
+	  } 
+	  if (prach_fmt == 0xa3 || prach_fmt == 0xb3 || prach_fmt == c2) {     
+	    dft4096(prach2+8192*4,rxsigF[aa]+8192*4,1);
+	    dft4096(prach2+8192*5,rxsigF[aa]+8192*5,1);
+	  } 
+          if (prach_fmt == 0xc2)
+	    for (int i=6;i<11;i++) dft4096(prach2+(8192*i),rxsigF[aa]+(8192*i),1);
+	} else {
+	  AssertFatal(fp->N_RB_UL == 216,"cannot do 136 PRBs with 3/4 sampling\n");
+	  //	80 MHz @ 46.08 Ms/s
+	  AssertFatal(fp->N_RB_UL == 136,"cannot do 136 PRBs with 3/4 sampling\n");
+	  if (prach_fmt == 0 || prach_fmt == 1 || prach_fmt == 2)
+	    dft36864(prach2,rxsigF[aa],1);
+	  if (prach_fmt == 1 || prach_fmt == 2)
+	    dft36864(prach2+73728,rxsigF[aa]+73728,1);
+	  if (prach_fmt == 3)
+	    dft36864(prach2+(2*73728),rxsigF[aa]+(2*73728),1);
+
+	  if (prach_fmt >3) {
+	    dft3072(prach2,rxsigF[aa],1);
+	    if (prach_fmt != 0xc0) dft3072(prach2+6144,rxsigF[aa]+6144,1);
+	  } 
+	  if (prach_fmt == 0xa2 || prach_fmt == 0xa3 || prach_fmt == 0xb2 || prach_fmt == 0xb3 || prach_fmt == 0xb4 || prach_fmt == 0xc2) {     
+	    dft3072(prach2+6144*2,rxsigF[aa]+6144*2,1);
+	    dft3072(prach2+6144*3,rxsigF[aa]+6144*3,1);
+	  } 
+	  if (prach_fmt == 0xa3 || prach_fmt == 0xb3 || prach_fmt == c2) {     
+	    dft3072(prach2+6144*4,rxsigF[aa]+6144*4,1);
+	    dft3072(prach2+6144*5,rxsigF[aa]+6144*5,1);
+	  } 
+          if (prach_fmt == 0xc2)
+	    for (int i=6;i<11;i++) dft3072(prach2+(6144*i),rxsigF[aa]+(6144*i),1);
+	}
+	break;
+      }
+
+      k = (12*n_ra_prb) - 6*fp->N_RB_UL;
+      
+      if (k<0) {
+	k+=(fp->ofdm_symbol_size);
+      }
+      
+      k*=K;
+      k+=kbar; 
+      k*=2;
+      int dftsize_x2 = fp->ofdm_symbol_size*24;
+      //LOG_D(PHY,"Shifting prach_rxF from %d to 0\n",k);
+
+      if ((k+(839*2)) > dftsize_x2) { // PRACH signal is split around DC 
+	memmove((void*)&rxsigF[aa][dftsize_x2-k],(void*)&rxsigF[aa][0],(k+(839*2)-dftsize_x2)*2);	
+	memmove((void*)&rxsigF[aa][0],(void*)(&rxsigF[aa][k]),(dftsize_x2-k)*2);	
+      }
+      else  // PRACH signal is not split around DC
+	memmove((void*)&rxsigF[aa][0],(void*)(&rxsigF[aa][k]),839*4);	
+      
+    }
+	     
+  }
+
+  if ((eNB==NULL) && (ru!=NULL) && ru->function == NGFI_RRU_IF4p5) {
+
+    /// **** send_IF4 of rxsigF to RAU **** ///
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+    if (br_flag == 1) send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH+1+ce_level);      
+
+    else
+#endif
+      send_IF4p5(ru, ru->proc.frame_prach, ru->proc.subframe_prach, IF4p5_PRACH);
+    
+    return;
+  } else if (eNB!=NULL) {
+
+    if ( LOG_DEBUGFLAG(PRACH)) {
+      int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));
+      if ((en > 60)&&(br_flag==1)) LOG_I(PHY,"PRACH (br_flag %d,ce_level %d, n_ra_prb %d, k %d): Frame %d, Subframe %d => %d dB\n",br_flag,ce_level,n_ra_prb,k,eNB->proc.frame_rx,eNB->proc.subframe_rx,en);
+    }
+  }
+  
+  // in case of RAU and prach received rx_thread wakes up prach
+
+  // here onwards is for eNodeB_3GPP or NGFI_RAU_IF4p5
+
+  preamble_offset_old = 99;
+
+  uint8_t update_TA  = 4;
+  uint8_t update_TA2 = 1;
+  switch (eNB->frame_parms.N_RB_DL) {
+  case 6:
+    update_TA = 16;
+    break;
+    
+  case 25:
+    update_TA = 4;
+    break;
+    
+  case 50:
+    update_TA = 2;
+    break;
+    
+  case 75:
+    update_TA  = 3;
+    update_TA2 = 2;
+  case 100:
+    update_TA  = 1;
+    break;
+  }
+  
+  *max_preamble_energy=0;
+  for (preamble_index=0 ; preamble_index<64 ; preamble_index++) {
+
+    if (LOG_DEBUGFLAG(PRACH)){
+      int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));
+      if (en>60) LOG_I(PHY,"frame %d, subframe %d : Trying preamble %d (br_flag %d)\n",ru->proc.frame_prach,subframe,preamble_index,br_flag);
+    }
+    if (restricted_set == 0) {
+      // This is the relative offset in the root sequence table (5.7.2-4 from 36.211) for the given preamble index
+      preamble_offset = ((NCS==0)? preamble_index : (preamble_index/(N_ZC/NCS)));
+      
+      if (preamble_offset != preamble_offset_old) {
+        preamble_offset_old = preamble_offset;
+        new_dft = 1;
+        // This is the \nu corresponding to the preamble index
+        preamble_shift  = 0;
+      }
+      
+      else {
+        preamble_shift  -= NCS;
+	
+        if (preamble_shift < 0)
+          preamble_shift+=N_ZC;
+      }
+    } else { // This is the high-speed case
+      new_dft = 0;
+
+      // set preamble_offset to initial rootSequenceIndex and look if we need more root sequences for this
+      // preamble index and find the corresponding cyclic shift
+      // Check if all shifts for that root have been processed
+      if (preamble_index0 == numshift) {
+        not_found = 1;
+        new_dft   = 1;
+        preamble_index0 -= numshift;
+        (preamble_offset==0 && numshift==0) ? (preamble_offset) : (preamble_offset++);
+
+        while (not_found == 1) {
+          // current root depending on rootSequenceIndex
+          int index = (rootSequenceIndex + preamble_offset) % N_ZC;
+
+          if (prach_fmt<4) {
+            // prach_root_sequence_map points to prach_root_sequence_map0_3
+            DevAssert( index < sizeof(prach_root_sequence_map0_3) / sizeof(prach_root_sequence_map0_3[0]) );
+          } else {
+            // prach_root_sequence_map points to prach_root_sequence_map4
+            DevAssert( index < sizeof(prach_root_sequence_map4) / sizeof(prach_root_sequence_map4[0]) );
+          }
+
+          u = prach_root_sequence_map[index];
+
+          uint16_t n_group_ra = 0;
+
+          if ( (du[u]<(N_ZC/3)) && (du[u]>=NCS) ) {
+            n_shift_ra     = du[u]/NCS;
+            d_start        = (du[u]<<1) + (n_shift_ra * NCS);
+            n_group_ra     = N_ZC/d_start;
+            n_shift_ra_bar = max(0,(N_ZC-(du[u]<<1)-(n_group_ra*d_start))/N_ZC);
+          } else if  ( (du[u]>=(N_ZC/3)) && (du[u]<=((N_ZC - NCS)>>1)) ) {
+            n_shift_ra     = (N_ZC - (du[u]<<1))/NCS;
+            d_start        = N_ZC - (du[u]<<1) + (n_shift_ra * NCS);
+            n_group_ra     = du[u]/d_start;
+            n_shift_ra_bar = min(n_shift_ra,max(0,(du[u]- (n_group_ra*d_start))/NCS));
+          } else {
+            n_shift_ra     = 0;
+            n_shift_ra_bar = 0;
+          }
+
+          // This is the number of cyclic shifts for the current root u
+          numshift = (n_shift_ra*n_group_ra) + n_shift_ra_bar;
+          // skip to next root and recompute parameters if numshift==0
+          (numshift>0) ? (not_found = 0) : (preamble_offset++);
+        }
+      }
+
+      if (n_shift_ra>0)
+        preamble_shift = -((d_start * (preamble_index0/n_shift_ra)) + ((preamble_index0%n_shift_ra)*NCS)); // minus because the channel is h(t -\tau + Cv)
+      else
+        preamble_shift = 0;
+
+      if (preamble_shift < 0)
+        preamble_shift+=N_ZC;
+
+      preamble_index0++;
+
+      if (preamble_index == 0)
+        first_nonzero_root_idx = preamble_offset;
+    }
+
+    // Compute DFT of RX signal (conjugate input, results in conjugate output) for each new rootSequenceIndex
+    if (LOG_DEBUGFLAG(PRACH)) {
+      int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));
+      if (en>60) LOG_I(PHY,"frame %d, subframe %d : preamble index %d: offset %d, preamble shift %d (br_flag %d, en %d)\n",
+		       ru->proc.frame_prach,subframe,preamble_index,preamble_offset,preamble_shift,br_flag,en);
+    }
+    log2_ifft_size = 10;
+    fft_size = 6144;
+
+    if (new_dft == 1) {
+      new_dft = 0;
+
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+      if (br_flag == 1) {
+	Xu=(int16_t*)eNB->X_u_br[ce_level][preamble_offset-first_nonzero_root_idx];
+	prach_ifft = prach_ifftp[prach_ifft_cnt++];
+	if (eNB->prach_vars_br.repetition_number[ce_level]==1) memset(prach_ifft,0,((N_ZC==839)?2048:256)*sizeof(int32_t));
+      }
+      else
+#endif
+	{
+	  Xu=(int16_t*)eNB->X_u[preamble_offset-first_nonzero_root_idx];
+	  prach_ifft = prach_ifftp[0];
+          memset(prach_ifft,0,((N_ZC==839) ? 2048 : 256)*sizeof(int32_t));
+	}
+
+      memset(prachF, 0, sizeof(int16_t)*2*1024 );
+      if (LOG_DUMPFLAG(PRACH)) {      
+        if (prach[0]!= NULL) LOG_M("prach_rx0.m","prach_rx0",prach[0],6144+792,1,1);
+         LOG_M("prach_rx1.m","prach_rx1",prach[1],6144+792,1,1);
+         LOG_M("prach_rxF0.m","prach_rxF0",rxsigF[0],24576,1,1);
+         LOG_M("prach_rxF1.m","prach_rxF1",rxsigF[1],6144,1,1);
+      }
+   
+      for (aa=0;aa<nb_rx; aa++) {
+      // Do componentwise product with Xu* on each antenna 
+
+	k=0;	
+	for (offset=0; offset<(N_ZC<<1); offset+=2) {
+	  prachF[offset]   = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][k]   + (int32_t)Xu[offset+1]*rxsigF[aa][k+1])>>15);
+	  prachF[offset+1] = (int16_t)(((int32_t)Xu[offset]*rxsigF[aa][k+1] - (int32_t)Xu[offset+1]*rxsigF[aa][k])>>15);
+	  k+=2;
+	  if (k==(12*2*fp->ofdm_symbol_size))
+	    k=0;
+	}
+	
+	// Now do IFFT of size 1024 (N_ZC=839) or 256 (N_ZC=139)
+	if (N_ZC == 839) {
+	  log2_ifft_size = 10;
+	  idft1024(prachF,prach_ifft_tmp,1);
+	  // compute energy and accumulate over receive antennas and repetitions for BR
+	  for (i=0;i<2048;i++)
+	    prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[i<<1] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>10;
+	} else {
+	  idft256(prachF,prach_ifft_tmp,1);
+	  log2_ifft_size = 8;
+	  // compute energy and accumulate over receive antennas and repetitions for BR
+	  for (i=0;i<256;i++)
+	    prach_ifft[i] += (prach_ifft_tmp[i<<1]*prach_ifft_tmp[(i<<1)] + prach_ifft_tmp[1+(i<<1)]*prach_ifft_tmp[1+(i<<1)])>>10;
+	}
+
+        if (LOG_DUMPFLAG(PRACH)) {	
+	  if (aa==0) LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1);
+          if (aa==1) LOG_M("prach_rxF_comp1.m","prach_rxF_comp1",prachF,1024,1,1);
+        }
+      }// antennas_rx
+    } // new dft
+    
+    // check energy in nth time shift, for 
+#if (RRC_VERSION >= MAKE_VERSION(14, 0, 0))
+    if ((br_flag==0) ||
+	(eNB->prach_vars_br.repetition_number[ce_level]==
+	 eNB->frame_parms.prach_emtc_config_common.prach_ConfigInfo.prach_numRepetitionPerPreambleAttempt[ce_level]))
+#endif
+      {
+      if (LOG_DEBUGFLAG(PRACH)){
+        int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));
+	if (en>60) LOG_I(PHY,"frame %d, subframe %d: Checking for peak in time-domain (br_flag %d, en %d)\n",ru->proc.frame_prach,subframe,br_flag,en);
+      }
+	preamble_shift2 = ((preamble_shift==0) ? 0 : ((preamble_shift<<log2_ifft_size)/N_ZC));
+
+    
+	for (i=0; i<NCS2; i++) {
+	  lev = (int32_t)prach_ifft[(preamble_shift2+i)];
+	  levdB = dB_fixed_times10(lev);
+	  
+	  if (levdB>*max_preamble_energy) {
+	    *max_preamble_energy  = levdB;
+	    *max_preamble_delay   = ((i*fft_size)>>log2_ifft_size)*update_TA/update_TA2;
+	    *max_preamble         = preamble_index;
+            if (LOG_DEBUGFLAG(PRACH)){
+              int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));
+	      if ((en>60) && (br_flag==1)) 
+                 LOG_D(PHY,"frame %d, subframe %d : max_preamble_energy %d, max_preamble_delay %d, max_preamble %d (br_flag %d,ce_level %d, levdB %d, lev %d)\n",
+                       ru->proc.frame_prach,subframe,
+                       *max_preamble_energy,*max_preamble_delay,
+                       *max_preamble,br_flag,ce_level,levdB,lev);
+            }
+	  }
+	}
+
+      }
+  }// preamble_index
+
+  if (LOG_DUMPFLAG(PRACH)) {
+    int en = dB_fixed(signal_energy((int32_t*)&rxsigF[0][0],840));  
+    if (en>60) {
+      k = (12*n_ra_prb) - 6*fp->N_RB_UL;
+      
+      if (k<0) k+=fp->ofdm_symbol_size;
+      
+      k*=12;
+      k+=13;
+      k*=2;
+      
+      if (br_flag == 0) {
+  	  LOG_M("rxsigF.m","prach_rxF",&rxsigF[0][0],12288,1,1);
+  	  LOG_M("prach_rxF_comp0.m","prach_rxF_comp0",prachF,1024,1,1);
+  	  LOG_M("Xu.m","xu",Xu,N_ZC,1,1);
+  	  LOG_M("prach_ifft0.m","prach_t0",prach_ifft,1024,1,1);
+      }
+      else {
+  	LOG_E(PHY,"Dumping prach (br_flag %d), k = %d (n_ra_prb %d)\n",br_flag,k,n_ra_prb);
+  	LOG_M("rxsigF_br.m","prach_rxF_br",&rxsigF[0][0],12288,1,1);
+  	LOG_M("prach_rxF_comp0_br.m","prach_rxF_comp0_br",prachF,1024,1,1);
+  	LOG_M("Xu_br.m","xu_br",Xu,N_ZC,1,1);
+  	LOG_M("prach_ifft0_br.m","prach_t0_br",prach_ifft,1024,1,1);
+  	exit(-1);      
+      }
+
+    }
+  } /* LOG_DUMPFLAG(PRACH) */
+  if (eNB) stop_meas(&eNB->rx_prach);
+
+}