diff --git a/openair1/PHY/CODING/coding_defs.h b/openair1/PHY/CODING/coding_defs.h
index 2040faf4a29dca0a722dfdf0208c90a9205242c5..0f316e7869a909f2ccef56cbd9a20c67c66bc108 100644
--- a/openair1/PHY/CODING/coding_defs.h
+++ b/openair1/PHY/CODING/coding_defs.h
@@ -467,33 +467,26 @@ void nr_interleaving_ldpc(uint32_t E, uint8_t Qm, uint8_t *e,uint8_t *f);
 
 void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f);
 
-uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm,
-							   uint32_t Tbslbrm,
-							   uint8_t BG,
-							   uint16_t Z,
-                               uint32_t G,
-                               uint8_t *w,
-                               uint8_t *e,
-                               uint8_t C,
-                               uint8_t rvidx,
-                               uint8_t Qm,
-                               uint8_t Nl,
-                               uint8_t r);
+int nr_rate_matching_ldpc(uint8_t Ilbrm,
+                          uint32_t Tbslbrm,
+                          uint8_t BG,
+                          uint16_t Z,
+                          uint8_t *w,
+                          uint8_t *e,
+                          uint8_t C,
+                          uint8_t rvidx,
+                          uint32_t E);
 
 int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
-		 	 	 	 	 	 uint32_t Tbslbrm,
-							 uint8_t BG,
-							 uint16_t Z,
-							 uint32_t G,
+                             uint32_t Tbslbrm,
+                             uint8_t BG,
+                             uint16_t Z,
                              int16_t *w,
                              int16_t *soft_input,
                              uint8_t C,
                              uint8_t rvidx,
                              uint8_t clear,
-                             uint8_t Qm,
-                             uint8_t Nl,
-                             uint8_t r,
-                             uint32_t *E_out);
+                             uint32_t E);
 
 decoder_if_t phy_threegpplte_turbo_decoder;
 decoder_if_t phy_threegpplte_turbo_decoder8;
diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c
index 01390f1f2ff991817ee443960fc5af7f9d7b351a..0bce31630f598e3a2f0b38acf278a582d313e215 100644
--- a/openair1/PHY/CODING/nr_rate_matching.c
+++ b/openair1/PHY/CODING/nr_rate_matching.c
@@ -63,55 +63,39 @@ void nr_deinterleaving_ldpc(uint32_t E, uint8_t Qm, int16_t *e,int16_t *f)
 }
 
 
-uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm,
-							   uint32_t Tbslbrm,
-							   uint8_t BG,
-							   uint16_t Z,
-                               uint32_t G,
-                               uint8_t *w,
-                               uint8_t *e,
-                               uint8_t C,
-                               uint8_t rvidx,
-                               uint8_t Qm,
-                               uint8_t Nl,
-                               uint8_t r)
+int nr_rate_matching_ldpc(uint8_t Ilbrm,
+                          uint32_t Tbslbrm,
+                          uint8_t BG,
+                          uint16_t Z,
+                          uint8_t *w,
+                          uint8_t *e,
+                          uint8_t C,
+                          uint8_t rvidx,
+                          uint32_t E)
 {
-  uint8_t Cprime;
-  uint32_t Ncb,E,ind,k,Nref,N;
-  //uint8_t *e2;
+  uint32_t Ncb,ind,k,Nref,N;
 
-  AssertFatal(Nl>0,"Nl is 0\n");
-  AssertFatal(Qm>0,"Qm is 0\n");
+  if (C==0) {
+    printf("nr_rate_matching: invalid parameters (C %d\n",C);
+    return -1;
+  }
 
   //Bit selection
   N = (BG==1)?(66*Z):(50*Z);
 
   if (Ilbrm == 0)
-	  Ncb = N;
+      Ncb = N;
   else {
       Nref = 3*Tbslbrm/(2*C); //R_LBRM = 2/3
       Ncb = min(N, Nref);
   }
 
-#ifdef RM_DEBUG
-  printf("nr_rate_matching: Ncb %d, rvidx %d, G %d, Qm %d, Nl%d, r %d\n",Ncb,rvidx, G, Qm,Nl,r);
-#endif
-
-  Cprime = C; //assume CBGTI not present
-
-  if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1)
-      E = Nl*Qm*(G/(Nl*Qm*Cprime));
-  else
-	  E = Nl*Qm*((G/(Nl*Qm*Cprime))+1);
-
   ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z;
 
 #ifdef RM_DEBUG
-  printf("nr_rate_matching: E %d, k0 %d Cprime %d modcprime %d\n",E,ind, Cprime,((G/(Nl*Qm))%Cprime));
+  printf("nr_rate_matching_ldpc: E %d, k0 %d, Ncb %d, rvidx %d\n", E, ind, Ncb, rvidx);
 #endif
 
-  //e2 = e;
-
   k=0;
 
   for (; (ind<Ncb)&&(k<E); ind++) {
@@ -120,7 +104,6 @@ uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm,
     printf("RM_TX k%d Ind: %d (%d)\n",k,ind,w[ind]);
 #endif
 
-    //if (w[ind] != NR_NULL) e2[k++]=w[ind];
     if (w[ind] != NR_NULL) e[k++]=w[ind];
   }
 
@@ -131,79 +114,60 @@ uint32_t nr_rate_matching_ldpc(uint8_t Ilbrm,
       printf("RM_TX k%d Ind: %d (%d)\n",k,ind,w[ind]);
 #endif
 
-      //if (w[ind] != NR_NULL) e2[k++]=w[ind];
       if (w[ind] != NR_NULL) e[k++]=w[ind];
     }
   }
 
 
-  return(E);
+  return 0;
 }
 
 int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
-		 	 	 	 	 	 uint32_t Tbslbrm,
-							 uint8_t BG,
-							 uint16_t Z,
-							 uint32_t G,
+                             uint32_t Tbslbrm,
+                             uint8_t BG,
+                             uint16_t Z,
                              int16_t *w,
                              int16_t *soft_input,
                              uint8_t C,
                              uint8_t rvidx,
                              uint8_t clear,
-                             uint8_t Qm,
-                             uint8_t Nl,
-                             uint8_t r,
-                             uint32_t *E_out)
+                             uint32_t E)
 {
-  uint8_t Cprime;
-  uint32_t Ncb,E,ind,k,Nref,N;
-
-  int16_t *soft_input2;
+  uint32_t Ncb,ind,k,Nref,N;
 
 #ifdef RM_DEBUG
   int nulled=0;
 #endif
 
-  if (C==0 || Qm==0 || Nl==0) {
-    printf("nr_rate_matching: invalid parameters (C %d, Qm %d, Nl %d\n",C,Qm,Nl);
-    return(-1);
+  if (C==0) {
+    printf("nr_rate_matching: invalid parameters (C %d\n",C);
+    return -1;
   }
 
-  AssertFatal(Nl>0,"Nl is 0\n");
-  AssertFatal(Qm>0,"Qm is 0\n");
-
   //Bit selection
   N = (BG==1)?(66*Z):(50*Z);
 
   if (Ilbrm == 0)
-	  Ncb = N;
+      Ncb = N;
   else {
       Nref = (3*Tbslbrm/(2*C)); //R_LBRM = 2/3
       Ncb = min(N, Nref);
   }
 
-  Cprime = C; //assume CBGTI not present
-
-  if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1)
-      E = Nl*Qm*(G/(Nl*Qm*Cprime));
-  else
-	  E = Nl*Qm*((G/(Nl*Qm*Cprime))+1);
-
   ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z;
 
 #ifdef RM_DEBUG
-  printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, Ncb %d,rvidx %d, G %d, Qm %d, Nl%d, r %d\n",clear,E,Ncb,rvidx, G, Qm,Nl,r);
+  printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d\n", clear, E, ind, Ncb, rvidx);
 #endif
 
   if (clear==1)
     memset(w,0,Ncb*sizeof(int16_t));
 
-  soft_input2 = soft_input;
   k=0;
 
   for (; (ind<Ncb)&&(k<E); ind++) {
-    if (soft_input2[ind] != NR_NULL) {
-      w[ind] += soft_input2[k++];
+    if (soft_input[ind] != NR_NULL) {
+      w[ind] += soft_input[k++];
 #ifdef RM_DEBUG
       printf("RM_RX k%d Ind: %d (%d)\n",k-1,ind,w[ind]);
 #endif
@@ -220,10 +184,10 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
 
   while(k<E) {
     for (ind=0; (ind<Ncb)&&(k<E); ind++) {
-      if (soft_input2[ind] != NR_NULL) {
-        w[ind] += soft_input2[k++];
+      if (soft_input[ind] != NR_NULL) {
+        w[ind] += soft_input[k++];
 #ifdef RM_DEBUG
-        printf("RM_RX k%d Ind: %d (%d)(soft in %d)\n",k-1,ind,w[ind],soft_input2[k-1]);
+        printf("RM_RX k%d Ind: %d (%d)(soft in %d)\n",k-1,ind,w[ind],soft_input[k-1]);
 #endif
       }
 
@@ -237,7 +201,5 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
     }
   }
 
-  *E_out = E;
-  return(0);
-
+  return 0;
 }
diff --git a/openair1/PHY/MODULATION/slot_fep_nr.c b/openair1/PHY/MODULATION/slot_fep_nr.c
index 8ef29d016d11d5f820f8397a8c4633503d22980e..22eb395da90e81d61a561f1a6560d2bcbcc50ed1 100644
--- a/openair1/PHY/MODULATION/slot_fep_nr.c
+++ b/openair1/PHY/MODULATION/slot_fep_nr.c
@@ -130,8 +130,8 @@ int nr_slot_fep(PHY_VARS_NR_UE *ue,
 
 #ifdef DEBUG_FEP
       //  if (ue->frame <100)
-    /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, subframe_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol,
-          nb_prefix_samples,nb_prefix_samples0,slot_offset,subframe_offset,sample_offset,rx_offset,frame_length_samples);
+    /*LOG_I(PHY,*/printf("slot_fep: frame %d: slot %d, symbol %d, nb_prefix_samples %d, nb_prefix_samples0 %d, slot_offset %d, sample_offset %d,rx_offset %d, frame_length_samples %d\n", ue->proc.proc_rxtx[(Ns>>1)&1].frame_rx,Ns, symbol,
+          nb_prefix_samples,nb_prefix_samples0,slot_offset,sample_offset,rx_offset,frame_length_samples);
 #endif
 
     if (l==0) {
diff --git a/openair1/PHY/NR_REFSIG/pss_nr.h b/openair1/PHY/NR_REFSIG/pss_nr.h
index 2f39f26ee475d2fcc1f2032d065bd438fa721be6..dc20ab24d7f8bbc9bdd08a597d24d0809529c4ea 100644
--- a/openair1/PHY/NR_REFSIG/pss_nr.h
+++ b/openair1/PHY/NR_REFSIG/pss_nr.h
@@ -137,7 +137,9 @@ int set_pss_nr(int ofdm_symbol_size);
 int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change);
 int pss_search_time_nr(int **rxdata, ///rx data in time domain
                        NR_DL_FRAME_PARMS *frame_parms,
-                       int *eNB_id);
+		       int fo_flag,
+                       int *eNB_id,
+		       int *f_off);
 
 #endif
 #undef EXTERN
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
index 205eae7f8e57e046d1bdec54e6870cc312559098..06969eded03422b43f0454a63d4924bac2e79a6d 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.h
@@ -90,6 +90,8 @@ uint8_t nr_generate_pdsch(NR_gNB_DLSCH_t dlsch,
     @param nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs */
 uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16_t length_dmrs,uint8_t Qm, uint8_t Nl);
 
+uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r);
+
 void free_gNB_dlsch(NR_gNB_DLSCH_t *dlsch);
 
 void clean_gNB_dlsch(NR_gNB_DLSCH_t *dlsch);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
index 0d59207480643ab4a9dd9220f27869670668f2ad..8a2877cc178aa6de1e3c5f9e4e78d3285bcd1116 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
@@ -280,7 +280,7 @@ int nr_dlsch_encoding(unsigned char *a,
   uint32_t A, Z;
   uint32_t *pz = &Z;
   uint8_t mod_order = rel15.modulation_order;
-  uint16_t Kr=0,r,r_offset=0;//Kr_bytes
+  uint16_t Kr=0,r,r_offset=0,Kr_bytes;
   uint8_t *d_tmp[MAX_NUM_DLSCH_SEGMENTS];
   uint8_t kb,BG=1;
   uint32_t E;
@@ -346,7 +346,7 @@ int nr_dlsch_encoding(unsigned char *a,
 	}
 
     Kr = dlsch->harq_processes[harq_pid]->K;
-    //Kr_bytes = Kr>>3;
+    Kr_bytes = Kr>>3;
 
     //printf("segment Z %d kb %d k %d Kr %d BG %d\n", *pz,kb,dlsch->harq_processes[harq_pid]->K,Kr,BG);
 
@@ -403,25 +403,24 @@ int nr_dlsch_encoding(unsigned char *a,
 
     //start_meas(rm_stats);
 #ifdef DEBUG_DLSCH_CODING
-  printf("rvidx in encoding = %d\n", dlsch->harq_processes[harq_pid]->rvidx);
+  printf("rvidx in encoding = %d\n", rel15.redundancy_version);
 #endif
 
-    E = nr_rate_matching_ldpc(Ilbrm,
-        		 	 	 	 	 	 Tbslbrm,
-    								 BG,
-    								 *pz,
-        							 G,
-									 dlsch->harq_processes[harq_pid]->d[r],
-									 dlsch->harq_processes[harq_pid]->e+r_offset,
-									 dlsch->harq_processes[harq_pid]->C,
-									 rel15.redundancy_version,
-									 mod_order,
-									 rel15.nb_layers,
-    								 r);
+    E = nr_get_E(G, dlsch->harq_processes[harq_pid]->C, mod_order, rel15.nb_layers, r);
+
+    nr_rate_matching_ldpc(Ilbrm,
+                          Tbslbrm,
+                          BG,
+                          *pz,
+                          dlsch->harq_processes[harq_pid]->d[r],
+                          dlsch->harq_processes[harq_pid]->e+r_offset,
+                          dlsch->harq_processes[harq_pid]->C,
+                          rel15.redundancy_version,
+                          E);
 
 #ifdef DEBUG_DLSCH_CODING
     for (int i =0; i<16; i++)
-       	printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i], r_offset);
+      printf("output ratematching e[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->e[i+r_offset], r_offset);
 #endif
     //stop_meas(rm_stats);
 
@@ -432,18 +431,15 @@ int nr_dlsch_encoding(unsigned char *a,
 						dlsch->harq_processes[harq_pid]->f+r_offset);
     //stop_meas(i_stats);
 
-    r_offset += E;
 #ifdef DEBUG_DLSCH_CODING
     for (int i =0; i<16; i++)
-    	printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r*r_offset], r_offset);
-#endif
-
-#ifdef DEBUG_DLSCH_CODING
+      printf("output interleaving f[%d]= %d r_offset %d\n", i,dlsch->harq_processes[harq_pid]->f[i+r_offset], r_offset);
 
     if (r==dlsch->harq_processes[harq_pid]->C-1)
-      write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,r_offset,1,4);
-
+      write_output("enc_output.m","enc",dlsch->harq_processes[harq_pid]->f,G,1,4);
 #endif
+
+    r_offset += E;
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_ENB_DLSCH_ENCODING, VCD_FUNCTION_OUT);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c
index 0b8ab563293acbd71a8f51ec45a0c144dea78026..f8b74540679ac3ebb2eea5c3ff730d75d85d188b 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_tbs_tools.c
@@ -176,3 +176,18 @@ uint32_t nr_get_G(uint16_t nb_rb, uint16_t nb_symb_sch,uint8_t nb_re_dmrs,uint16
 	G = ((NR_NB_SC_PER_RB*nb_symb_sch)-(nb_re_dmrs*length_dmrs))*nb_rb*Qm*Nl;
 	return(G);
 }
+
+uint32_t nr_get_E(uint32_t G, uint8_t C, uint8_t Qm, uint8_t Nl, uint8_t r) {
+  uint32_t E;
+  uint8_t Cprime = C; //assume CBGTI not present
+
+  AssertFatal(Nl>0,"Nl is 0\n");
+  AssertFatal(Qm>0,"Qm is 0\n");
+
+  if (r <= Cprime - ((G/(Nl*Qm))%Cprime) - 1)
+      E = Nl*Qm*(G/(Nl*Qm*Cprime));
+  else
+      E = Nl*Qm*((G/(Nl*Qm*Cprime))+1);
+
+  return E;
+}
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
index 942bf8c0ba22275c9a1a824c68b33f05f484b3e0..145c779be909055b42294cd705ec6c6c9d631c7c 100644
--- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
@@ -28,7 +28,7 @@
 #include "PHY/NR_REFSIG/refsig_defs_ue.h"
 #include "filt16a_32.h"
 #include "T.h"
-//#define DEBUG_PDSCH
+//#define DEBUG_PDCCH
 
 
 int nr_pbch_channel_estimation(PHY_VARS_NR_UE *ue,
@@ -297,7 +297,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
 
 
   // generate pilot 
-  nr_pdcch_dmrs_rx(ue,eNB_offset,Ns,ue->nr_gold_pdcch[eNB_offset][Ns][symbol], &pilot[0],2000,nb_rb_coreset);
+  nr_pdcch_dmrs_rx(ue,eNB_offset,Ns,ue->nr_gold_pdcch[eNB_offset][Ns>>1][symbol], &pilot[0],2000,nb_rb_coreset);
 
 
   for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
@@ -459,7 +459,7 @@ int nr_pdcch_channel_estimation(PHY_VARS_NR_UE *ue,
     break;
   }
 
-  if( (Ns== 2) && (l == 0))
+  //if( (Ns== 2) && (l == 0))
   {
       // do ifft of channel estimate
       for (aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++)
diff --git a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
index cf419b0904e0b5c00bf60a5d46c66b6df9eed119..3d481a0468a670caf59bb021931575d52541ce78 100755
--- a/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/dci_nr.c
@@ -821,8 +821,8 @@ int32_t nr_rx_pdcch(PHY_VARS_NR_UE *ue,
   
 #ifdef NR_PDCCH_DCI_DEBUG
   printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> symbol_mon=(%d) and start_symbol=(%d)\n",symbol_mon,start_symbol);
-  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) \n",
-	 coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R);
+  printf("\t<-NR_PDCCH_DCI_DEBUG (nr_rx_pdcch)-> coreset_freq_dom=(%ld) n_rb_offset=(%d) coreset_time_dur=(%d) n_shift=(%d) reg_bundle_size_L=(%d) coreset_interleaver_size_R=(%d) scrambling_ID=(%d) \n",
+	 coreset_freq_dom,n_rb_offset,coreset_time_dur,n_shift,reg_bundle_size_L,coreset_interleaver_size_R,pdcch_DMRS_scrambling_id);
 #endif
 
   //
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index 610b8305df8a014cca0f26d7f7d3fe2fb2cc2741..2888a59606fc8b0c2b82f1f66b7f3ad7bab9e6ec 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -376,6 +376,22 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
   for (r=0; r<harq_process->C; r++) {
 
     //printf("start rx segment %d\n",r);
+    E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r);
+
+#if UE_TIMING_TRACE
+    start_meas(dlsch_deinterleaving_stats);
+#endif
+    nr_deinterleaving_ldpc(E,
+                           harq_process->Qm,
+                           harq_process->w[r],
+                           dlsch_llr+r_offset);
+
+    //for (int i =0; i<16; i++)
+    //        	printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+
+#if UE_TIMING_TRACE
+    stop_meas(dlsch_deinterleaving_stats);
+#endif
 
 #if UE_TIMING_TRACE
     start_meas(dlsch_rate_unmatching_stats);
@@ -394,20 +410,15 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
 #endif
 
     if (nr_rate_matching_ldpc_rx(Ilbrm,
-    		 	 	 	 	 	 Tbslbrm,
-								 p_decParams->BG,
-								 p_decParams->Z,
-    							 G,
-								 harq_process->w[r],
-								 dlsch_llr+r_offset,
-								 harq_process->C,
-								 harq_process->rvidx,
-								 (harq_process->round==0)?1:0,
-								 harq_process->Qm,
-								 harq_process->Nl,
-								 r,
-								 &E)==-1) {
-
+                                 Tbslbrm,
+                                 p_decParams->BG,
+                                 p_decParams->Z,
+                                 harq_process->d[r],
+                                 harq_process->w[r],
+                                 harq_process->C,
+                                 harq_process->rvidx,
+                                 (harq_process->round==0)?1:0,
+                                 E)==-1) {
 #if UE_TIMING_TRACE
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
@@ -419,27 +430,13 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
     }
-    r_offset += E;
 
     //for (int i =0; i<16; i++)
-    //    	printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
-
-#if UE_TIMING_TRACE
-    start_meas(dlsch_deinterleaving_stats);
-#endif
-    nr_deinterleaving_ldpc(E,
-    					   harq_process->Qm,
-                           harq_process->d[r],
-                           harq_process->w[r]);
+    //    	printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
 
-    //for (int i =0; i<16; i++)
-    //        	printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
+    r_offset += E;
 
-#if UE_TIMING_TRACE
-    stop_meas(dlsch_deinterleaving_stats);
-#endif
 #ifdef DEBUG_DLSCH_DECODING
-
     if (r==0) {
               write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
               write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
@@ -979,6 +976,30 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment
 
     Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl);
 
+    E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r);
+
+    /*
+    printf("Subblock deinterleaving, dlsch_llr %p, w %p\n",
+     dlsch_llr+r_offset,
+     &harq_process->w[r]);
+    */
+#if UE_TIMING_TRACE
+    start_meas(dlsch_deinterleaving_stats);
+#endif
+    nr_deinterleaving_ldpc(E,
+                           harq_process->Qm,
+                           harq_process->w[r],
+                           dlsch_llr+r_offset);
+
+#ifdef DEBUG_DLSCH_DECODING
+        for (int i =0; i<16; i++)
+              printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+#endif
+
+#if UE_TIMING_TRACE
+    stop_meas(dlsch_deinterleaving_stats);
+#endif
+
 #if UE_TIMING_TRACE
     start_meas(dlsch_rate_unmatching_stats);
 #endif
@@ -995,23 +1016,16 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment
           harq_process->round);
 #endif
 
-#ifdef DEBUG_DLSCH_DECODING
-    printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx);
-#endif
     if (nr_rate_matching_ldpc_rx(Ilbrm,
-         	 	 	 Tbslbrm,
-    				 p_decParams->BG,
-    				 p_decParams->Z,
-        			 G,
-    				 harq_process->w[r],
-    				 dlsch_llr+r_offset,
-    				 harq_process->C,
-    				 harq_process->rvidx,
-    				 (harq_process->round==0)?1:0,
-    				 harq_process->Qm,
-    				 harq_process->Nl,
-    				 r,
-    				 &E)==-1) {
+                                 Tbslbrm,
+                                 p_decParams->BG,
+                                 p_decParams->Z,
+                                 harq_process->d[r],
+                                 harq_process->w[r],
+                                 harq_process->C,
+                                 harq_process->rvidx,
+                                 (harq_process->round==0)?1:0,
+                                 E)==-1) {
 #if UE_TIMING_TRACE
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
@@ -1023,34 +1037,18 @@ if (harq_process->C>1) { // wakeup worker if more than 1 segment
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
     }
+
+    //for (int i =0; i<16; i++)
+    //    	printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
+
     //r_offset += E;
     //printf("main thread r_offset %d\n",r_offset);
  
 #ifdef DEBUG_DLSCH_DECODING   
     for (int i =0; i<16; i++)
-             printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+             printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
 #endif
 
-    /*
-    printf("Subblock deinterleaving, d %p w %p\n",
-     harq_process->d[r],
-     harq_process->w);
-    */
-#if UE_TIMING_TRACE
-    start_meas(dlsch_deinterleaving_stats);
-#endif
-    nr_deinterleaving_ldpc(E,
-        		   harq_process->Qm,
-                           harq_process->d[r],
-                           harq_process->w[r]);
-#ifdef DEBUG_DLSCH_DECODING                           
-        for (int i =0; i<16; i++)
-              printf("rx output interleaving d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
-#endif
-
-#if UE_TIMING_TRACE
-    stop_meas(dlsch_deinterleaving_stats);
-#endif
 #ifdef DEBUG_DLSCH_DECODING
 
     if (r==0) {
@@ -1526,6 +1524,23 @@ void *nr_dlsch_decoding_2thread0(void *arg)
 
   Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl);
 
+    E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r);
+
+#if UE_TIMING_TRACE
+    start_meas(dlsch_deinterleaving_stats);
+#endif
+    nr_deinterleaving_ldpc(E,
+                           harq_process->Qm,
+                           harq_process->w[r],
+                           dlsch_llr+r_offset);
+
+    //for (int i =0; i<16; i++)
+    //        	printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+
+#if UE_TIMING_TRACE
+    stop_meas(dlsch_deinterleaving_stats);
+#endif
+
 #if UE_TIMING_TRACE
     start_meas(dlsch_rate_unmatching_stats);
 #endif
@@ -1542,23 +1557,16 @@ void *nr_dlsch_decoding_2thread0(void *arg)
           harq_process->round);
 #endif
 
-#ifdef DEBUG_DLSCH_DECODING
-    printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx);
-#endif
     if (nr_rate_matching_ldpc_rx(Ilbrm,
-    	 	 	 	 Tbslbrm,
-				 p_decParams->BG,
-				 p_decParams->Z,
-				 G,
-				 harq_process->w[r],
-				 dlsch_llr+r_offset,
-				 harq_process->C,
-				 harq_process->rvidx,
-				 (harq_process->round==0)?1:0,
-				 harq_process->Qm,
-				 harq_process->Nl,
-				 r,
-				 &E)==-1) {
+                                 Tbslbrm,
+                                 p_decParams->BG,
+                                 p_decParams->Z,
+                                 harq_process->d[r],
+                                 harq_process->w[r],
+                                 harq_process->C,
+                                 harq_process->rvidx,
+                                 (harq_process->round==0)?1:0,
+                                 E)==-1) {
 #if UE_TIMING_TRACE
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
@@ -1570,23 +1578,13 @@ void *nr_dlsch_decoding_2thread0(void *arg)
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
     }
-    //r_offset += E;
 
     //for (int i =0; i<16; i++)
-    //    	printf("rx output ratematching w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+    //    	printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
 
-#if UE_TIMING_TRACE
-    start_meas(dlsch_deinterleaving_stats);
-#endif
-    nr_deinterleaving_ldpc(E,
-    			   harq_process->Qm,
-                           harq_process->d[r],
-                           harq_process->w[r]);
-#if UE_TIMING_TRACE
-    stop_meas(dlsch_deinterleaving_stats);
-#endif
-#ifdef DEBUG_DLSCH_DECODING
+    //r_offset += E;
 
+#ifdef DEBUG_DLSCH_DECODING
     if (r==0) {
               write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
               write_output("decoder_in.m","dec",&harq_process->d[0][0],(3*8*Kr_bytes)+12,1,0);
@@ -2043,6 +2041,28 @@ void *nr_dlsch_decoding_2thread1(void *arg)
 
   	  Tbslbrm = nr_compute_tbs(28,nb_rb,frame_parms->symbols_per_slot,0,0, harq_process->Nl);
 
+    E = nr_get_E(G, harq_process->C, harq_process->Qm, harq_process->Nl, r);
+
+    /*
+    printf("Subblock deinterleaving, d %p w %p\n",
+     harq_process->d[r],
+     harq_process->w);
+    */
+#if UE_TIMING_TRACE
+    start_meas(dlsch_deinterleaving_stats);
+#endif
+    nr_deinterleaving_ldpc(E,
+                           harq_process->Qm,
+                           harq_process->w[r],
+                           dlsch_llr+r_offset);
+
+    //for (int i =0; i<16; i++)
+    //        	printf("rx output deinterleaving w[%d]= %d r_offset %d\n", i,harq_process->w[r][i], r_offset);
+
+#if UE_TIMING_TRACE
+    stop_meas(dlsch_deinterleaving_stats);
+#endif
+
 #if UE_TIMING_TRACE
     start_meas(dlsch_rate_unmatching_stats);
 #endif
@@ -2059,23 +2079,16 @@ void *nr_dlsch_decoding_2thread1(void *arg)
           harq_process->round);
 #endif
 
-#ifdef DEBUG_DLSCH_DECODING
-    printf(" in decoding dlsch->harq_processes[harq_pid]->rvidx = %d\n", dlsch->harq_processes[harq_pid]->rvidx);
-#endif
     if (nr_rate_matching_ldpc_rx(Ilbrm,
      	 	 	 	 Tbslbrm,
 				 p_decParams->BG,
 				 p_decParams->Z,
-    				 G,
+				 harq_process->d[r],
 				 harq_process->w[r],
-				 dlsch_llr+r_offset,
 				 harq_process->C,
 				 harq_process->rvidx,
 				 (harq_process->round==0)?1:0,
-				 harq_process->Qm,
-				 harq_process->Nl,
-				 r,
-				 &E)==-1) {
+				 E)==-1) {
 #if UE_TIMING_TRACE
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
@@ -2087,23 +2100,12 @@ void *nr_dlsch_decoding_2thread1(void *arg)
       stop_meas(dlsch_rate_unmatching_stats);
 #endif
     }
+
+    //for (int i =0; i<16; i++)
+    //    	printf("rx output ratematching d[%d]= %d r_offset %d\n", i,harq_process->d[r][i], r_offset);
+
     //r_offset += E;
 
-    /*
-    printf("Subblock deinterleaving, d %p w %p\n",
-     harq_process->d[r],
-     harq_process->w);
-    */
-#if UE_TIMING_TRACE
-    start_meas(dlsch_deinterleaving_stats);
-#endif
-    nr_deinterleaving_ldpc(E,
-    			   harq_process->Qm,
-                           harq_process->d[r],
-                           harq_process->w[r]);
-#if UE_TIMING_TRACE
-    stop_meas(dlsch_deinterleaving_stats);
-#endif
 #ifdef DEBUG_DLSCH_DECODING
     if (r==0) {
               write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
index 4a6e6423f61698c7d7375a0385ae2b8a645ddb44..e5f079ebc31616eee707a4d87077cfd7fbb33b67 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
@@ -39,6 +39,7 @@
 //#include "SCHED/extern.h"
 
 #include "common_lib.h"
+#include <math.h>
 
 #include "PHY/NR_REFSIG/pss_nr.h"
 #include "PHY/NR_REFSIG/sss_nr.h"
@@ -56,6 +57,7 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode)
   NR_DL_FRAME_PARMS *frame_parms=&ue->frame_parms;
   int ret =-1;
 
+
 #ifdef DEBUG_INITIAL_SYNCH
   LOG_I(PHY,"[UE%d] Initial sync: starting PBCH detection (rx_offset %d)\n",ue->Mod_id,
         ue->rx_offset);
@@ -65,6 +67,7 @@ int nr_pbch_detection(PHY_VARS_NR_UE *ue, runmode_t mode)
   int nb_prefix_samples0 = frame_parms->nb_prefix_samples0;
   frame_parms->nb_prefix_samples0 = frame_parms->nb_prefix_samples;
 
+
   //symbol 1
   nr_slot_fep(ue,
 	      1,
@@ -143,6 +146,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
   int32_t sync_pos, sync_pos_slot; // k_ssb, N_ssb_crb, sync_pos2,
   int32_t metric_tdd_ncp=0;
   uint8_t phase_tdd_ncp;
+  double im, re;
 
   NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
   int ret=-1;
@@ -183,14 +187,14 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
   sync_pos = pss_synchro_nr(ue, NO_RATE_CHANGE);
 
   sync_pos_slot = (fp->samples_per_subframe/fp->slots_per_subframe) - 10*(fp->ofdm_symbol_size + fp->nb_prefix_samples);
-  
+
   if (sync_pos >= fp->nb_prefix_samples){
     ue->ssb_offset = sync_pos - fp->nb_prefix_samples;}
   else{
     ue->ssb_offset = sync_pos + (fp->samples_per_subframe * 10) - fp->nb_prefix_samples;}
     
-    ue->rx_offset = ue->ssb_offset - sync_pos_slot;
-  
+  ue->rx_offset = ue->ssb_offset - sync_pos_slot;
+
   //write_output("rxdata1.m","rxd1",ue->common_vars.rxdata[0],10*fp->samples_per_subframe,1,1);
 
 #ifdef DEBUG_INITIAL_SYNCH
@@ -198,6 +202,25 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
   LOG_I(PHY,"sync_pos %d ssb_offset %d sync_pos_slot %d \n",sync_pos,ue->ssb_offset,sync_pos_slot);
 #endif
 
+  // digital compensation of FFO for SSB symbols
+  if (ue->UE_fo_compensation){  
+	double s_time = 1/(1.0e3*fp->samples_per_subframe);  // sampling time
+	double off_angle = -2*M_PI*s_time*(ue->common_vars.freq_offset);  // offset rotation angle compensation per sample
+
+	int start = ue->ssb_offset;  // start for offset correction is at ssb_offset (pss time position)
+  	int end = start + 4*(fp->ofdm_symbol_size + fp->nb_prefix_samples);  // loop over samples in 4 symbols (ssb size), including prefix  
+
+	for(int n=start; n<end; n++){  	
+	  for (int ar=0; ar<fp->nb_antennas_rx; ar++) {
+		re = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n]);
+		im = ((double)(((short *)ue->common_vars.rxdata[ar]))[2*n+1]);
+		((short *)ue->common_vars.rxdata[ar])[2*n] = (short)(round(re*cos(n*off_angle) - im*sin(n*off_angle))); 
+		((short *)ue->common_vars.rxdata[ar])[2*n+1] = (short)(round(re*sin(n*off_angle) + im*cos(n*off_angle)));
+	  }
+	}
+  }
+
+
   /* check that SSS/PBCH block is continuous inside the received buffer */
   if (sync_pos < (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*fp->samples_per_subframe - (NB_SYMBOLS_PBCH * fp->ofdm_symbol_size))) {
 
@@ -244,7 +267,8 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
 	  ret = -1;
   }
 
-  /* Consider this is a false detection if the offset is > 1000 Hz */
+  /* Consider this is a false detection if the offset is > 1000 Hz 
+     Not to be used now that offest estimation is in place
   if( (abs(ue->common_vars.freq_offset) > 150) && (ret == 0) )
   {
 	  ret=-1;
@@ -253,7 +277,7 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
 #else
 	  LOG_E(HW, "Ignore MIB with high freq offset [%d Hz] estimation \n",ue->common_vars.freq_offset);
 #endif
-  }
+  }*/
 
   if (ret==0) {  // PBCH found so indicate sync to higher layers and configure frame parameters
 
@@ -329,13 +353,13 @@ int nr_initial_sync(PHY_VARS_NR_UE *ue, runmode_t mode)
     printf("[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n",
 	  ue->Mod_id,
 	  ue->proc.proc_rxtx[0].frame_rx,
-	  openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset,
+	  openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset,
 	  ue->common_vars.freq_offset);
 #  else
     LOG_I(PHY, "[UE %d] Frame %d Measured Carrier Frequency %.0f Hz (offset %d Hz)\n",
 	  ue->Mod_id,
 	  ue->proc.proc_rxtx[0].frame_rx,
-	  openair0_cfg[0].rx_freq[0]-ue->common_vars.freq_offset,
+	  openair0_cfg[0].rx_freq[0]+ue->common_vars.freq_offset,
 	  ue->common_vars.freq_offset);
 #  endif
 #endif
diff --git a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c
index 01481d36120049a81cfa6a060f3b1bebe0d6ac73..9b09a846bbd6d4e909b215624ced6550ea192617 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/pss_nr.c
@@ -33,6 +33,7 @@
 #include <stdio.h>
 #include <assert.h>
 #include <errno.h>
+#include <math.h>
 
 #include "PHY/defs_nr_UE.h"
 
@@ -662,6 +663,7 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change)
   NR_DL_FRAME_PARMS *frame_parms = &(PHY_vars_UE->frame_parms);
   int synchro_position;
   int **rxdata = NULL;
+  int fo_flag = PHY_vars_UE->UE_fo_compensation;  // flag to enable freq offset estimation and compensation
 
 #ifdef DBG_PSS_NR
 
@@ -705,7 +707,10 @@ int pss_synchro_nr(PHY_VARS_NR_UE *PHY_vars_UE, int rate_change)
 
   synchro_position = pss_search_time_nr(rxdata,
                                         frame_parms,
-                                        (int *)&PHY_vars_UE->common_vars.eNb_id);
+					fo_flag,
+                                        (int *)&PHY_vars_UE->common_vars.eNb_id,
+					(int *)&PHY_vars_UE->common_vars.freq_offset);
+
 
 #if TEST_SYNCHRO_TIMING_PSS
 
@@ -751,6 +756,15 @@ static inline int64_t abs64(int64_t x)
   return (((int64_t)((int32_t*)&x)[0])*((int64_t)((int32_t*)&x)[0]) + ((int64_t)((int32_t*)&x)[1])*((int64_t)((int32_t*)&x)[1]));
 }
 
+static inline double angle64(int64_t x)
+{
+
+  double re=((int32_t*)&x)[0];
+  double im=((int32_t*)&x)[1];
+  return (atan2(im,re));
+}
+
+
 /*******************************************************************
 *
 * NAME :         pss_search_time_nr
@@ -805,12 +819,15 @@ static inline int64_t abs64(int64_t x)
 
 int pss_search_time_nr(int **rxdata, ///rx data in time domain
                        NR_DL_FRAME_PARMS *frame_parms,
-                       int *eNB_id)
+		       int fo_flag,
+                       int *eNB_id,
+		       int *f_off)
 {
   unsigned int n, ar, peak_position, pss_source;
   int64_t peak_value;
   int64_t result;
   int64_t avg[NUMBER_PSS_SEQUENCE];
+  double ffo_est=0;
 
 
   unsigned int length = (NR_NUMBER_OF_SUBFRAMES_PER_FRAME*frame_parms->samples_per_subframe);  /* 1 frame for now, it should be 2 TODO_NR */
@@ -831,7 +848,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
     maxval = max(maxval,-primary_synchro_time_nr[1][i]);
     maxval = max(maxval,primary_synchro_time_nr[2][i]);
     maxval = max(maxval,-primary_synchro_time_nr[2][i]);
-
   }
   int shift = log2_approx(maxval);//*(frame_parms->ofdm_symbol_size+frame_parms->nb_prefix_samples)*2);
 
@@ -859,7 +875,6 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
 				  frame_parms->ofdm_symbol_size, 
 				  shift);
 	  pss_corr_ue[pss_index][n] += abs64(result);
-	  
           //((short*)pss_corr_ue[pss_index])[2*n] += ((short*) &result)[0];   /* real part */
           //((short*)pss_corr_ue[pss_index])[2*n+1] += ((short*) &result)[1]; /* imaginary part */
           //((short*)&synchro_out)[0] += ((int*) &result)[0];               /* real part */
@@ -867,7 +882,7 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
 
         }
       }
-
+ 
       /* calculate the absolute value of sync_corr[n] */
       avg[pss_index]+=pss_corr_ue[pss_index][n];
       if (pss_corr_ue[pss_index][n] > peak_value) {
@@ -882,11 +897,45 @@ int pss_search_time_nr(int **rxdata, ///rx data in time domain
     }
   }
 
+  if (fo_flag){
+	  // fractional frequency offser computation according to Cross-correlation Synchronization Algorithm Using PSS
+	  // Shoujun Huang, Yongtao Su, Ying He and Shan Tang, "Joint time and frequency offset estimation in LTE downlink," 7th International Conference on Communications and Networking in China, 2012.
+
+	  int64_t result1,result2;
+	  // Computing cross-correlation at peak on half the symbol size for first half of data
+	  result1  = dot_product64((short*)primary_synchro_time_nr[pss_source], 
+				  (short*) &(rxdata[0][peak_position]), 
+				  frame_parms->ofdm_symbol_size>>1, 
+				  shift);
+	  // Computing cross-correlation at peak on half the symbol size for data shifted by half symbol size 
+	  // as it is real and complex it is necessary to shift by a value equal to symbol size to obtain such shift
+	  result2  = dot_product64((short*)primary_synchro_time_nr[pss_source]+(frame_parms->ofdm_symbol_size), 
+				  (short*) &(rxdata[0][peak_position])+(frame_parms->ofdm_symbol_size), 
+				  frame_parms->ofdm_symbol_size>>1, 
+				  shift);
+
+	  int64_t re1,re2,im1,im2;
+	  re1=((int*) &result1)[0];
+	  re2=((int*) &result2)[0];
+	  im1=((int*) &result1)[1];
+	  im2=((int*) &result2)[1];
+
+ 	  // estimation of fractional frequency offset: angle[(result1)'*(result2)]/pi
+	  ffo_est=atan2(re1*im2-re2*im1,re1*re2+im1*im2)/M_PI;
+  
+#ifdef DBG_PSS_NR
+	  printf("ffo %lf\n",ffo_est);
+#endif
+  }
+
+  // computing absolute value of frequency offset
+  *f_off = ffo_est*frame_parms->subcarrier_spacing;  
+
   for (int pss_index = 0; pss_index < NUMBER_PSS_SEQUENCE; pss_index++) avg[pss_index]/=(length/4);
 
   *eNB_id = pss_source;
 
-  LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]));
+  LOG_I(PHY,"[UE] nr_synchro_time: Sync source = %d, Peak found at pos %d, val = %llu (%d dB) avg %d dB, ffo %lf\n", pss_source, peak_position, (unsigned long long)peak_value, dB_fixed64(peak_value),dB_fixed64(avg[pss_source]),ffo_est);
 
   if (peak_value < 5*avg[pss_source])
     return(-1);
diff --git a/openair1/PHY/TOOLS/cdot_prod.c b/openair1/PHY/TOOLS/cdot_prod.c
index 63b74afe6d02c07fb74f3b36f2d2e16b673862ae..843a9605f11e229de07d4acfcffe1119dd43a1ce 100644
--- a/openair1/PHY/TOOLS/cdot_prod.c
+++ b/openair1/PHY/TOOLS/cdot_prod.c
@@ -169,7 +169,7 @@ int64_t dot_product64(int16_t *x,
 #if defined(__x86_64__) || defined(__i386__)
   __m128i *x128,*y128,mmtmp1,mmtmp2,mmtmp3,mmcumul,mmcumul_re,mmcumul_im;
   __m128i minus_i = _mm_set_epi16(-1,1,-1,1,-1,1,-1,1);
-  int32_t result;
+  int64_t result;
 
   x128 = (__m128i*) x;
   y128 = (__m128i*) y;
@@ -180,14 +180,13 @@ int64_t dot_product64(int16_t *x,
   for (n=0; n<(N>>2); n++) {
 
 //    printf("n=%d, x128=%p, y128=%p\n",n,x128,y128);
-  //      print_shorts("x",&x128[0]);
-    //    print_shorts("y",&y128[0]);
+       // print_shorts("x",&x128[0]);
+       // print_shorts("y",&y128[0]);
 
     // this computes Re(z) = Re(x)*Re(y) + Im(x)*Im(y)
     mmtmp1 = _mm_madd_epi16(x128[0],y128[0]);
       //  print_ints("retmp",&mmtmp1);
     // mmtmp1 contains real part of 4 consecutive outputs (32-bit)
-
     // shift and accumulate results
     mmtmp1 = _mm_srai_epi32(mmtmp1,output_shift);
     mmcumul_re = _mm_add_epi32(mmcumul_re,mmtmp1);
@@ -205,7 +204,6 @@ int64_t dot_product64(int16_t *x,
     mmtmp3 = _mm_madd_epi16(x128[0],mmtmp2);
             //print_ints("imtmp",&mmtmp3);
     // mmtmp3 contains imag part of 4 consecutive outputs (32-bit)
-
     // shift and accumulate results
     mmtmp3 = _mm_srai_epi32(mmtmp3,output_shift);
     mmcumul_im = _mm_add_epi32(mmcumul_im,mmtmp3);
@@ -218,13 +216,10 @@ int64_t dot_product64(int16_t *x,
   // this gives Re Re Im Im
   mmcumul = _mm_hadd_epi32(mmcumul_re,mmcumul_im);
     //print_ints("cumul1",&mmcumul);
-
   // this gives Re Im Re Im
   mmcumul = _mm_hadd_epi32(mmcumul,mmcumul);
-
     //print_ints("cumul2",&mmcumul);
 
-
   //mmcumul = _mm_srai_epi32(mmcumul,output_shift);
   // extract the lower half
   result = _mm_extract_epi64(mmcumul,0);
diff --git a/openair1/PHY/TOOLS/nr_phy_scope.c b/openair1/PHY/TOOLS/nr_phy_scope.c
index 25c40458a12f7a55e2c2e070d6f68ab2d303f742..e0ddc21607f2519cf75348d04eec248f1f50c096 100644
--- a/openair1/PHY/TOOLS/nr_phy_scope.c
+++ b/openair1/PHY/TOOLS/nr_phy_scope.c
@@ -458,10 +458,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
   float **rxsig_t_dB;
   float *time;
   float *corr;
-  /*
   int16_t **chest_t;
   int16_t **chest_f;
-  */
   int16_t *pdsch_llr;
   int16_t *pdsch_comp;
   //int16_t *pdsch_mag;
@@ -479,10 +477,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
   int coded_bits_per_codeword = num_re*Qm;
   int symbol, first_symbol,nb_re;
   int nb_rb_pdsch =50;
+  float ymax=1;
+  float **chest_t_abs;
+  float Re,Im;
+  float *chest_f_abs;
+  float *freq;
+  static int overlay = 0;
   /*
-  float Re,Im,ymax=1;
-  float **chest_t_abs, *chest_f_abs;
-  float freq[nsymb_ce*nb_antennas_rx*nb_antennas_tx];
   int frame = phy_vars_ue->proc.proc_rxtx[0].frame_rx;
   int mcs = 0;
   unsigned char harq_pid = 0;
@@ -523,20 +524,20 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
     coded_bits_per_codeword = 0; //frame_parms->N_RB_DL*12*get_Qm(mcs)*(frame_parms->symbols_per_tti);
   }
   */
-  if (!I) I = (float *) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float));
-
-  if (!Q) Q = (float *) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float));
-
   /*
+  I = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float));
+  Q = (float*) calloc(frame_parms->ofdm_symbol_size*frame_parms->symbols_per_slot*2,sizeof(float));
+
   chest_t_abs = (float**) malloc(nb_antennas_rx*sizeof(float*));
 
   for (int arx=0; arx<nb_antennas_rx; arx++) {
     chest_t_abs[arx] = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float));
   }
 
-  chest_f_abs = (float*) calloc(nsymb_ce*nb_antennas_rx*nb_antennas_tx,sizeof(float));
-  */
-  llr = (float *) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero
+  chest_f_abs = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float));
+  freq = (float*) calloc(frame_parms->ofdm_symbol_size,sizeof(float));
+
+  llr = (float*) calloc(coded_bits_per_codeword,sizeof(float)); // init to zero
   bit = malloc(coded_bits_per_codeword*sizeof(float));
   llr_pdcch = (float *) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float)); // init to zero
   bit_pdcch = (float *) calloc(12*frame_parms->N_RB_DL*num_pdcch_symbols*2,sizeof(float));
@@ -549,15 +550,16 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
 
   time = calloc(samples_per_frame,sizeof(float));
   corr = calloc(samples_per_frame,sizeof(float));
-  /*
+
   chest_t = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates_time[eNB_id];
   chest_f = (int16_t**) phy_vars_ue->common_vars.common_vars_rx_data_per_thread[phy_vars_ue->current_thread_id[subframe]].dl_ch_estimates[eNB_id];
-  */
-  pbch_llr = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->llr;
-  pbch_comp = (int16_t *) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0];
-  pdcch_llr = (int8_t *) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr;
-  pdcch_comp = (int16_t *) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp[0];
-  pdsch_llr = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; // stream 0
+
+  pbch_llr = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->llr;
+  pbch_comp = (int16_t*) phy_vars_ue->pbch_vars[eNB_id]->rxdataF_comp[0];
+
+  pdcch_llr = (int8_t*) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr;
+  pdcch_comp = (int16_t*) phy_vars_ue->pdcch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp[0];
+   pdsch_llr = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->llr[0]; // stream 0
   //    pdsch_llr = (int16_t*) phy_vars_ue->lte_ue_pdsch_vars_SI[eNB_id]->llr[0]; // stream 0
   pdsch_comp = (int16_t *) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->rxdataF_comp0[0];
   //pdsch_mag = (int16_t*) phy_vars_ue->pdsch_vars[phy_vars_ue->current_thread_id[subframe]][eNB_id]->dl_ch_mag0[0];
@@ -587,29 +589,38 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
   }
 
   if (phy_vars_ue->is_synchronized==0) {
-    for (int ind=0; ind<3; ind++) {
-      if (pss_corr_ue[ind]) {
-        for (int i=0; i<samples_per_frame; i++) {
-          corr[i] = (float) pss_corr_ue[ind][i];
-          time[i] = (float) i;
-        }
 
-        if (ind==0)
-          fl_set_xyplot_data(form->chest_t,time,corr,samples_per_frame,"","","");
-        else
-          fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]);
+    for (ind=0;ind<3;ind++) {
+      if (pss_corr_ue[ind]) {
+	for (i=0; i<samples_per_frame; i++) {
+	  corr[i] = (float) pss_corr_ue[ind][i];
+	  time[i] = (float) i;
+	}
+	
+	if (ind==0)
+	  fl_set_xyplot_data(form->chest_t,time,corr,samples_per_frame,"","","");
+	else
+	  fl_add_xyplot_overlay(form->chest_t,ind,time,corr,samples_per_frame,rx_antenna_colors[ind]);
+
+	overlay = 1;
       }
     }
+  } 
+  else {
+	
+  if (overlay) { //there was a previous overlay
+    fl_clear_xyplot(form->chest_t);
+    overlay = 0;
   }
 
-  /*
-  // Channel Impulse Response (still repeated format)
+  // Channel Impulse Response
   if (chest_t != NULL) {
     ymax = 0;
 
     if (chest_t[0] !=NULL) {
       for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) {
-        chest_t_abs[0][i] = (float) (chest_t[0][4*i]*chest_t[0][4*i]+chest_t[0][4*i+1]*chest_t[0][4*i+1]);
+        chest_t_abs[0][i] = (float) (chest_t[0][2*i]*chest_t[0][2*i]+chest_t[0][2*i+1]*chest_t[0][2*i+1]);
+	time[i] = (float) i;
 
         if (chest_t_abs[0][i] > ymax)
           ymax = chest_t_abs[0][i];
@@ -617,7 +628,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
 
       fl_set_xyplot_data(form->chest_t,time,chest_t_abs[0],(frame_parms->ofdm_symbol_size>>3),"","","");
     }
-
+    /*
     for (arx=1; arx<nb_antennas_rx; arx++) {
       if (chest_t[arx] !=NULL) {
         for (i=0; i<(frame_parms->ofdm_symbol_size>>3); i++) {
@@ -631,11 +642,12 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
         fl_set_xyplot_overlay_type(form->chest_t,arx,FL_DASHED_XYPLOT);
       }
     }
-
+    */
     // Avoid flickering effect
     //        fl_get_xyplot_ybounds(form->chest_t,&ymin,&ymax); // Does not always work...
     fl_set_xyplot_ybounds(form->chest_t,0,(double) ymax);
   }
+  }
 
   // Channel Frequency Response (includes 5 complex sample for filter)
   if (chest_f != NULL) {
@@ -644,7 +656,7 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
     for (atx=0; atx<nb_antennas_tx; atx++) {
       for (arx=0; arx<nb_antennas_rx; arx++) {
         if (chest_f[(atx<<1)+arx] != NULL) {
-          for (k=0; k<nsymb_ce; k++) {
+          for (k=0; k<frame_parms->ofdm_symbol_size; k++) {
             freq[ind] = (float)ind;
             Re = (float)(chest_f[(atx<<1)+arx][(2*k)]);
             Im = (float)(chest_f[(atx<<1)+arx][(2*k)+1]);
@@ -657,12 +669,13 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
     }
 
     // tx antenna 0
-    fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce);
+    //fl_set_xyplot_xbounds(form->chest_f,0,nb_antennas_rx*nb_antennas_tx*nsymb_ce);
     //fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*frame_parms->symbols_per_tti,2);
     //        fl_set_xyplot_xtics(form->chest_f,nb_antennas_rx*nb_antennas_tx*2,2);
-    fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR);
-    fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,nsymb_ce,"","","");
+    //fl_set_xyplot_xgrid(form->chest_f,FL_GRID_MAJOR);
+    fl_set_xyplot_data(form->chest_f,freq,chest_f_abs,frame_parms->ofdm_symbol_size,"","","");
 
+    /*
     for (arx=1; arx<nb_antennas_rx; arx++) {
       fl_add_xyplot_overlay(form->chest_f,1,&freq[arx*nsymb_ce],&chest_f_abs[arx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]);
     }
@@ -681,10 +694,10 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
         fl_add_xyplot_overlay(form->chest_f,atx,&freq[atx*nsymb_ce],&chest_f_abs[atx*nsymb_ce],nsymb_ce,rx_antenna_colors[arx]);
       }
     }
+    */
   }
-  */
 
-  // PBCH LLRs
+    // PBCH LLRs
   if (pbch_llr != NULL) {
     for (int i=0; i<864; i++) {
       llr_pbch[i] = (float) pbch_llr[i];
@@ -694,10 +707,8 @@ void phy_scope_UE(FD_lte_phy_scope_ue *form,
     fl_set_xyplot_data(form->pbch_llr,bit_pbch,llr_pbch,864,"","","");
   }
 
-  if (phy_vars_ue->is_synchronized!=1)
-    first_symbol=5;
-  else
-    first_symbol=1;
+
+  first_symbol=1;
 
   // PBCH I/Q of MF Output
   if (pbch_comp!=NULL) {
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index c11ba8933f561c9a3cf75128da013185ef6e5e97..54aed7adb18d9a7177e8bf1a5c67711d3bbe70bf 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -983,6 +983,8 @@ typedef struct {
   int UE_scan;
   /// \brief Indicator that UE should perform coarse scanning around carrier
   int UE_scan_carrier;
+  /// \brief Indicator that UE should enable estimation and compensation of frequency offset
+  int UE_fo_compensation;
   /// \brief Indicator that UE is synchronized to an eNB
   int is_synchronized;
   /// Data structure for UE process scheduling
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 7cbb70242efb939ed510d23a4db715ece84bc647..a7f8ef68840ffa041361b0770e809c79a6f66f08 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -138,20 +138,22 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
     LOG_D(PHY,"SS TX: frame %d, slot %d, start_symbol %d\n",frame,slot, ssb_start_symbol);
 
     nr_generate_pss(gNB->d_pss, txdataF[0], AMP, ssb_start_symbol, cfg, fp);
-    nr_generate_sss(gNB->d_sss, txdataF[0], AMP_OVER_2, ssb_start_symbol, cfg, fp);
+    nr_generate_sss(gNB->d_sss, txdataF[0], AMP, ssb_start_symbol, cfg, fp);
 
     if (!(frame&7)){
       LOG_D(PHY,"%d.%d : pbch_configured %d\n",frame,slot,gNB->pbch_configured);
       if (gNB->pbch_configured != 1)return;
       gNB->pbch_configured = 0;
     }
-    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP_OVER_2, ssb_start_symbol, cfg, fp);
+
+    nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index],txdataF[0], AMP, ssb_start_symbol, cfg, fp);
+
     nr_generate_pbch(&gNB->pbch,
                       gNB->nrPolar_params,
                       pbch_pdu,
                       gNB->nr_pbch_interleaver,
                       txdataF[0],
-                      AMP_OVER_2,
+                      AMP,
                       ssb_start_symbol,
                       n_hf,Lmax,ssb_index,
                       frame, cfg, fp);
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index a4d627823fae3f6899decf729d896b905a1df60c..5eee7b9c0c45c8dfcf0d9889366812125d9cc924 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -2781,8 +2781,6 @@ void nr_ue_measurement_procedures(
 */
     eNB_id = 0;
 
-
-		
       LOG_D(PHY,"start adjust sync l = %d slot = %d no timing %d\n",l, slot, ue->no_timing_correction);
       if (ue->no_timing_correction==0)
 	nr_adjust_synch_ue(&ue->frame_parms,
@@ -2791,7 +2789,6 @@ void nr_ue_measurement_procedures(
 			   nr_tti_rx,
 			   0,
 			   16384);
-
     
   }
 
@@ -5064,7 +5061,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eN
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SLOT_FEP, VCD_FUNCTION_IN);
     nr_slot_fep(ue,
 		l,
-		nr_tti_rx,
+		nr_tti_rx<<1,
 		0,
 		0,
 		1,
diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c
index 956c8ecd1ff3565fcda31357a821ab624f649ada..214a33fb73758b7e5ea6d05b827f9dab9f1eafcd 100644
--- a/openair1/SIMULATION/NR_PHY/pbchsim.c
+++ b/openair1/SIMULATION/NR_PHY/pbchsim.c
@@ -87,11 +87,13 @@ int main(int argc, char **argv)
 
   int i,aa;//,l;
   double sigma2, sigma2_dB=10,SNR,snr0=-2.0,snr1=2.0;
+  double cfo=0;
   uint8_t snr1set=0;
   int **txdata;
   double **s_re,**s_im,**r_re,**r_im;
-  //double iqim = 0.0;
-  //unsigned char pbch_pdu[6];
+  double iqim = 0.0;
+  double ip =0.0;
+  unsigned char pbch_pdu[6];
   //  int sync_pos, sync_pos_slot;
   //  FILE *rx_frame_file;
   FILE *output_fd = NULL;
@@ -146,7 +148,7 @@ int main(int argc, char **argv)
 
   randominit(0);
 
-  while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) {
+  while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:o:s:S:t:x:y:z:N:F:GR:dP:IL:")) != -1) {
     switch (c) {
     case 'f':
       write_output_file=1;
@@ -212,6 +214,11 @@ int main(int argc, char **argv)
       n_trials = atoi(optarg);
       break;
 
+    case 'o':
+      cfo = atof(optarg);
+      msg("Setting CFO to %f Hz\n",cfo);
+      break;
+
     case 's':
       snr0 = atof(optarg);
       msg("Setting SNR0 to %f\n",snr0);
@@ -325,6 +332,7 @@ int main(int argc, char **argv)
       printf("-z Number of RX antennas used in UE\n");
       printf("-i Relative strength of first intefering eNB (in dB) - cell_id mod 3 = 1\n");
       printf("-j Relative strength of second intefering eNB (in dB) - cell_id mod 3 = 2\n");
+      printf("-o Carrier frequency offset in Hz\n");
       printf("-N Nid_cell\n");
       printf("-R N_RB_DL\n");
       printf("-O oversampling factor (1,2,4,8,16)\n");
@@ -361,26 +369,44 @@ int main(int argc, char **argv)
   nr_phy_config_request_sim(gNB,N_RB_DL,N_RB_DL,mu,Nid_cell);
   phy_init_nr_gNB(gNB,0,0);
 
-  double fs,bw;
+  double fs,bw,scs,eps;
 
   if (mu == 1 && N_RB_DL == 217) { 
     fs = 122.88e6;
     bw = 80e6;
+    scs = 30000;
   }					       
   else if (mu == 1 && N_RB_DL == 245) {
     fs = 122.88e6;
     bw = 90e6;
+    scs = 30000;
   }
   else if (mu == 1 && N_RB_DL == 273) {
     fs = 122.88e6;
     bw = 100e6;
+    scs = 30000;
   }
   else if (mu == 1 && N_RB_DL == 106) { 
     fs = 61.44e6;
     bw = 40e6;
+    scs = 30000;
   }
   else AssertFatal(1==0,"Unsupported numerology for mu %d, N_RB %d\n",mu, N_RB_DL);
 
+  // cfo with respect to sub-carrier spacing
+  eps = cfo/scs;
+
+  // computation of integer and fractional FO to compare with estimation results
+  int IFO;
+  if(eps!=0.0){
+	printf("Introducing a CFO of %lf relative to SCS of %d kHz\n",eps,(int)(scs/1000));
+	if (eps>0)	
+  	  IFO=(int)(eps+0.5);
+	else
+	  IFO=(int)(eps-0.5);
+	printf("FFO = %lf; IFO = %d\n",eps-IFO,IFO);
+  }
+
   gNB2UE = new_channel_desc_scm(n_tx,
                                 n_rx,
                                 channel_model,
@@ -436,6 +462,9 @@ int main(int argc, char **argv)
                       
   UE->perfect_ce = 0;
 
+  if(eps!=0.0)
+	UE->UE_fo_compensation = 1; // if a frequency offset is set then perform fo estimation and compensation
+
   if (init_nr_ue_signal(UE, 1, 0) != 0)
   {
     printf("Error at UE NR initialisation\n");
@@ -493,6 +522,7 @@ int main(int argc, char **argv)
 
   //  printf("txlev %d (%f)\n",txlev,10*log10(txlev));
 
+
   for (i=0; i<frame_length_complex_samples; i++) {
     for (aa=0; aa<frame_parms->nb_antennas_tx; aa++) {
       r_re[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)]);
@@ -515,7 +545,28 @@ int main(int argc, char **argv)
       sigma2 = pow(10,sigma2_dB/10);
       //printf("sigma2 %f (%f dB), tx_lev %f (%f dB)\n",sigma2,sigma2_dB,txlev,10*log10((double)txlev));
 
-      for (i=0; i<frame_parms->samples_per_subframe; i++) {
+      if(eps!=0.0)
+        rf_rx(r_re,  // real part of txdata
+           r_im,  // imag part of txdata
+           NULL,  // interference real part
+           NULL, // interference imag part
+           0,  // interference power
+           frame_parms->nb_antennas_rx,  // number of rx antennas
+           frame_length_complex_samples,  // number of samples in frame
+           1.0e9/fs,   //sampling time (ns)
+           cfo,	// frequency offset in Hz
+           0.0, // drift (not implemented)
+           0.0, // noise figure (not implemented)
+           0.0, // rx gain in dB ?
+           200, // 3rd order non-linearity in dB ?
+           &ip, // initial phase
+           30.0e3,  // phase noise cutoff in kHz
+           -500.0, // phase noise amplitude in dBc
+           0.0,  // IQ imbalance (dB),
+	   0.0); // IQ phase imbalance (rad)
+
+   
+      for (i=0; i<frame_length_complex_samples; i++) {
 	for (aa=0; aa<frame_parms->nb_antennas_rx; aa++) {
 	  
 	  ((short*) UE->common_vars.rxdata[aa])[2*i]   = (short) ((r_re[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
diff --git a/openair1/SIMULATION/RF/rf.c b/openair1/SIMULATION/RF/rf.c
index e317fbd154034017a40521e23ae1281318aa0f74..bff3453de0c30ae3df4696a756b0202dbe80be62 100644
--- a/openair1/SIMULATION/RF/rf.c
+++ b/openair1/SIMULATION/RF/rf.c
@@ -107,10 +107,10 @@ void rf_rx(double **r_re,
     exit(-1);
   }
 
-  if (fabs(f_off) > 10000.0) {
+/*  if (fabs(f_off) > 10000.0) {
     printf("rf.c: Illegal f_off %f\n",f_off);
     exit(-1);
-  }
+  }*/
 
   if (fabs(drift) > 1000.0) {
     printf("rf.c: Illegal drift %f\n",drift);
diff --git a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
index 1ea888eeb972cbade1b025d2ce236e61289f0908..4e8b72614d2d5a9f9de157a76d2df7e91aa4a38e 100644
--- a/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
+++ b/openair2/NR_UE_PHY_INTERFACE/NR_IF_Module.c
@@ -268,11 +268,11 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) {
   //  Type0 PDCCH search space
   dl_config->number_pdus =  1;
   dl_config->dl_config_list[0].pdu_type = FAPI_NR_DL_CONFIG_TYPE_DCI;
-  dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 0xaaaa;	//	to be set
+  dl_config->dl_config_list[0].dci_config_pdu.dci_config_rel15.rnti = 0x1234;	//	to be set
   
   uint64_t mask = 0x0;
-  uint16_t num_rbs=48;
-  uint16_t rb_offset=47;
+  uint16_t num_rbs=24;
+  uint16_t rb_offset=0;
   uint16_t cell_id=0;
   uint16_t num_symbols=2;
   for(int i=0; i<(num_rbs/6); ++i){   //  38.331 Each bit corresponds a group of 6 RBs
@@ -292,7 +292,7 @@ int nr_ue_dcireq(nr_dcireq_t *dcireq) {
   
   uint32_t number_of_search_space_per_slot=1;
   uint32_t first_symbol_index=0;
-  uint32_t search_space_duration=1;  //  element of search space
+  uint32_t search_space_duration=0;  //  element of search space
   uint32_t coreset_duration;  //  element of coreset
   
   coreset_duration = num_symbols * number_of_search_space_per_slot;
diff --git a/targets/RT/USER/nr-ue.c b/targets/RT/USER/nr-ue.c
index 3903a4a3e949067b9a232bcd6e7b23e48f844757..a857feac968cbeb1ed9173781a7cfb6a2c05467e 100644
--- a/targets/RT/USER/nr-ue.c
+++ b/targets/RT/USER/nr-ue.c
@@ -444,6 +444,7 @@ static void *UE_thread_synch(void *arg) {
 
 	      //write_output("txdata_sym.m", "txdata_sym", UE->common_vars.rxdata[0], (10*UE->frame_parms.samples_per_subframe), 1, 1);
 
+		freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
                 hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe;
                 printf("Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
                        hw_slot_offset,
@@ -457,16 +458,13 @@ static void *UE_thread_synch(void *arg) {
                     // rerun with new cell parameters and frequency-offset
                     for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
                         openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
-			if (UE->UE_scan_carrier == 1) {
 			  if (freq_offset >= 0)
-                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
+                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(freq_offset);
 			  else
-                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
+                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(freq_offset);
 			  openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
                             openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
 			  downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
-			  freq_offset=0;
-			}
 		    }
 
                     // reconfigure for potentially different bandwidth
@@ -602,7 +600,7 @@ static void *UE_thread_synch(void *arg) {
 	  
 	  phy_scope_UE(form_ue[0],
 		       PHY_vars_UE_g[0][0],
-		       0,0,7);
+		       0,0,1);
 	}
 #endif
 
diff --git a/targets/RT/USER/nr-uesoftmodem.c b/targets/RT/USER/nr-uesoftmodem.c
index 45c3442d826e2532293ea4caaf1c00bc0f35010c..4cd2ea06df4286b0b0a73ce2c0c354a380131d63 100644
--- a/targets/RT/USER/nr-uesoftmodem.c
+++ b/targets/RT/USER/nr-uesoftmodem.c
@@ -130,6 +130,7 @@ static char                    *itti_dump_file = NULL;
 
 int UE_scan = 0;
 int UE_scan_carrier = 0;
+int UE_fo_compensation = 0;
 runmode_t mode = normal_txrx;
 
 FILE *input_fd=NULL;
@@ -978,6 +979,7 @@ int main( int argc, char **argv ) {
     
     UE[CC_id]->UE_scan = UE_scan;
     UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
+    UE[CC_id]->UE_fo_compensation = UE_fo_compensation;
     UE[CC_id]->mode    = mode;
     printf("UE[%d]->mode = %d\n",CC_id,mode);
     
diff --git a/targets/RT/USER/nr-uesoftmodem.h b/targets/RT/USER/nr-uesoftmodem.h
index 816e7530869e285ac5af1ca46bd60d544629bd13..7f96480b2bfe5be8969b5e67c1aa8c8e25af2baa 100644
--- a/targets/RT/USER/nr-uesoftmodem.h
+++ b/targets/RT/USER/nr-uesoftmodem.h
@@ -55,6 +55,7 @@
 #define CONFIG_HLP_UENANTR       "set UE number of rx antennas\n"
 #define CONFIG_HLP_UENANTT       "set UE number of tx antennas\n"
 #define CONFIG_HLP_UESCAN        "set UE to scan around carrier\n"
+#define CONFIG_HLP_UEFO	         "set UE to enable estimation and compensation of frequency offset\n"
 #define CONFIG_HLP_DUMPFRAME     "dump UE received frame to rxsig_frame0.dat and exit\n"
 #define CONFIG_HLP_DLSHIFT       "dynamic shift for LLR compuation for TM3/4 (default 0)\n"
 #define CONFIG_HLP_UELOOP        "get softmodem (UE) to loop through memory instead of acquiring from HW\n"
@@ -135,6 +136,7 @@
 {"ue-nb-ant-rx",     	       CONFIG_HLP_UENANTR,    0,		u8ptr:&nb_antenna_rx,		    defuintval:1,   TYPE_UINT8,    0},     \
 {"ue-nb-ant-tx",     	       CONFIG_HLP_UENANTT,    0,		u8ptr:&nb_antenna_tx,		    defuintval:1,   TYPE_UINT8,    0},     \
 {"ue-scan-carrier",  	       CONFIG_HLP_UESCAN,     PARAMFLAG_BOOL,	iptr:&UE_scan_carrier,  	    defintval:0,    TYPE_INT,	   0},     \
+{"ue-fo-compensation", 	       CONFIG_HLP_UEFO,	      PARAMFLAG_BOOL,	iptr:&UE_fo_compensation,  	    defintval:0,    TYPE_INT,	   0},     \
 {"ue-max-power",     	       NULL,		      0,		iptr:&(tx_max_power[0]),	    defintval:90,   TYPE_INT,	   0},     \
 {"r"  ,                        CONFIG_HLP_PRB,        0,                iptr:&(frame_parms[0]->N_RB_DL),   defintval:25,   TYPE_UINT,    0},     \
 {"dlsch-demod-shift",     	 CONFIG_HLP_DLSHIFT,	0,		  iptr:(int32_t *)&dlsch_demod_shift,	defintval:0,			   TYPE_INT,	  0},			   \