diff --git a/ci-scripts/xml_files/fr1_ran_ue_proc.xml b/ci-scripts/xml_files/fr1_ran_ue_proc.xml
index 330fb27f21b047dcfe0c1748ee4e51ebedc483c0..446433ec306a34b88da01b573ab6ff80ea1a3d8b 100644
--- a/ci-scripts/xml_files/fr1_ran_ue_proc.xml
+++ b/ci-scripts/xml_files/fr1_ran_ue_proc.xml
@@ -32,9 +32,13 @@
  000001
  050000
  050001
+ 050002
+ 050003
+ 000001
+ 010002
+ 000001
  070001
  070000
- 010002
  010003
 	</TestCaseRequestedList>
 	<TestCaseExclusionList></TestCaseExclusionList>
@@ -89,16 +93,30 @@
 		<class>Ping</class>
 		<desc>Ping: 20pings in 20sec</desc>
 		<ping_args>-c 20</ping_args>
-		<ping_packetloss_threshold>50</ping_packetloss_threshold>
+		<ping_packetloss_threshold>0</ping_packetloss_threshold>
 	</testCase>
 
 	<testCase id="050001">
 		<class>Ping</class>
 		<desc>Ping: 5pings in 1sec</desc>
 		<ping_args>-c 5 -i 0.2</ping_args>
-		<ping_packetloss_threshold>50</ping_packetloss_threshold>
+		<ping_packetloss_threshold>0</ping_packetloss_threshold>
 	</testCase>
 
+	<testCase id="050002">
+		<class>Ping</class>
+		<desc>Ping: 100pings in 20sec</desc>
+		<ping_args>-c 100 -i 0.2</ping_args>
+		<ping_packetloss_threshold>0</ping_packetloss_threshold>
+	</testCase>
+
+	<testCase id="050003">$
+	<class>Ping</class>$
+	<desc>Ping: 100pings in 20sec size 1000</desc>$
+	<ping_args>-c 100 -i 0.2 -s 1000</ping_args>$
+	<ping_packetloss_threshold>0</ping_packetloss_threshold>$
+	</testCase>$
+
 	<testCase id="070000">
 		<class>Terminate_eNB</class>
 		<desc>Terminate eNB</desc>
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index e034120781eb8ecb6a0c00934857552cff3d2cbb..94d55d5fe5073825c0feabcfcdb2693afc2bc6cc 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -2087,6 +2087,7 @@ set (MAC_NR_SRC
   ${NR_GNB_MAC_DIR}/gNB_scheduler_ulsch.c
   ${NR_GNB_MAC_DIR}/gNB_scheduler_primitives.c
   ${NR_GNB_MAC_DIR}/gNB_scheduler_phytest.c
+  ${NR_GNB_MAC_DIR}/gNB_scheduler_uci.c
   ${NR_GNB_MAC_DIR}/gNB_scheduler_RA.c
  )
 
diff --git a/cmake_targets/autotests/test_case_list.xml b/cmake_targets/autotests/test_case_list.xml
index 7e43a9d01c7f1db7d6a0035babdf62b9675d5d24..0c31ba8ea68da0de7761dda17c37064dd121f235 100644
--- a/cmake_targets/autotests/test_case_list.xml
+++ b/cmake_targets/autotests/test_case_list.xml
@@ -1095,7 +1095,10 @@
                                  (Test10: 106 PRBs 50 PDSCH-PRBs MCS Index 16),
                                  (Test11: HARQ test 25% TP (4 rounds),
                                  (Test12: HARQ test 33% TP (3 rounds),
-                                 (Test13: HARQ test 50% TP (2 rounds)</desc>
+                                 (Test13: HARQ test 50% TP (2 rounds),
+                                 (Test14: 3 PTRS, 8 Interpolated Symbols),
+                                 (Test15: 6 PTRS, 5 Interpolated Symbols),
+                                 (Test16: 11 PTRS, 0 Interpolated Symbols)</desc>
       <pre_compile_prog></pre_compile_prog>
       <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog>
       <compile_prog_args> --phy_simulators  -c </compile_prog_args>
@@ -1114,8 +1117,11 @@
                   -n100 -e16 -s10 
                   -n100 -s1 -t25
                   -n100 -s1 -t33
-                  -n100 -s1 -t50</main_exec_args>
-      <tags>nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13</tags>
+                  -n100 -s1 -t50
+                  -n100 -s5 -T 2 2 2
+                  -n100 -s5 -T 2 1 2
+                  -n100 -s5 -T 2 0 4</main_exec_args>
+      <tags>nr_dlsim.test1 nr_dlsim.test2 nr_dlsim.test3 nr_dlsim.test4 nr_dlsim.test5 nr_dlsim.test6 nr_dlsim.test7 nr_dlsim.test8 nr_dlsim.test9 nr_dlsim.test10 nr_dlsim.test11 nr_dlsim.test12 nr_dlsim.test13 nr_dlsim.test14 nr_dlsim.test15 nr_dlsim.test16</tags>
       <search_expr_true>PDSCH test OK</search_expr_true>
       <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
       <nruns>3</nruns>
@@ -1302,10 +1308,12 @@
 
     <testCase id="015112">
       <class>execution</class>
-      <desc>nr_prachsim Test cases. (Test1: 106 PRBs - Prach format A2),
-                                    (Test2: 217 PRBs - Prach format A2),
-                                    (Test3: 273 PRBs - Prach format A2),
-				    (Test4: 106 PRBs - Prach format 0)</desc>
+      <desc>nr_prachsim Test cases. (Test1: 30kHz SCS, 106 PRBs, Prach format A2),
+                                    (Test2: 30kHz SCS, 217 PRBs, Prach format A2),
+                                    (Test3: 30kHz SCS, 273 PRBs, Prach format A2),
+				    (Test4: 30kHz SCS, 106 PRBs, Prach format 0),
+                                    (Test5: 120kHz SCS, 32 PRBs, Prach format A2),
+                                    (Test6: 120kHz SCS, 66 PRBs, Prach format A2)</desc>
       <pre_compile_prog></pre_compile_prog>
       <compile_prog>$OPENAIR_DIR/cmake_targets/build_oai</compile_prog>
       <compile_prog_args> --phy_simulators -c </compile_prog_args>
@@ -1315,8 +1323,10 @@
       <main_exec_args>-a -s -30 -n 100 -p 63 -R 106
                       -a -s -30 -n 100 -p 63 -R 217
                       -a -s -30 -n 100 -p 63 -R 273
-		      -a -s -30 -n 100 -p 63 -R 106 -c 4</main_exec_args>
-      <tags>nr_prachsim.test1 nr_prachsim.test2 nr_prachsim.test3 nr_prachsim.test4</tags>
+		      -a -s -30 -n 100 -p 63 -R 106 -c 4
+		      -a -s -30 -n 100 -p 32 -R 32 -m 3 -c52 
+		      -a -s -30 -n 100 -p 32 -R 66 -m 3 -c52</main_exec_args>
+      <tags>nr_prachsim.test1 nr_prachsim.test2 nr_prachsim.test3 nr_prachsim.test4 nr_prachsim.test5 nr_prachsim.test6</tags>
       <search_expr_true>PRACH test OK</search_expr_true>
       <search_expr_false>segmentation fault|assertion|exiting|fatal</search_expr_false>
       <nruns>3</nruns>
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
index 87a4d6f6af96ac2463434466bc9f4fab5d6e2132..da8490160211f17ef2a94f976628c13e9ee7fcc2 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
@@ -472,6 +472,21 @@ typedef struct {
   uint8_t cbgti;
   uint8_t codeBlockGroupFlushIndicator;
   //  to be check the fields needed to L1 with NR_DL_UE_HARQ_t and NR_UE_DLSCH_t
+  // PTRS [TS38.214, sec 5.1.6.3]
+  /// PT-RS antenna ports [TS38.214, sec 5.1.6.3] [TS38.211, table 7.4.1.2.2-1] Bitmap occupying the 6 LSBs with: bit 0: antenna port 1000 bit 5: antenna port 1005 and for each bit 0: PTRS port not used 1: PTRS port used
+  uint8_t PTRSPortIndex ;
+  /// PT-RS time density [TS38.214, table 5.1.6.3-1] 0: 1 1: 2 2: 4
+  uint8_t PTRSTimeDensity;
+  /// PT-RS frequency density [TS38.214, table 5.1.6.3-2] 0: 2 1: 4
+  uint8_t PTRSFreqDensity;
+  /// PT-RS resource element offset [TS38.211, table 7.4.1.2.2-1] Value: 0->3
+  uint8_t PTRSReOffset;
+  ///  PT-RS-to-PDSCH EPRE ratio [TS38.214, table 4.1-2] Value :0->3
+  uint8_t nEpreRatioOfPDSCHToPTRS;
+  /// MCS table for this DLSCH
+  uint8_t mcs_table;
+
+  uint16_t pduBitmap;
 } fapi_nr_dl_config_dlsch_pdu_rel15_t;
 
 typedef struct {
@@ -783,7 +798,7 @@ typedef struct {
 } fapi_nr_pusch_power_control_t;
 
 typedef enum {tx_config_codebook = 1, tx_config_nonCodebook = 2} tx_config_t;
-typedef enum {transform_precoder_disabled = 0, transform_precoder_enabled = 1} transform_precoder_t;
+typedef enum {transform_precoder_enabled = 0, transform_precoder_disabled = 1} transform_precoder_t;
 typedef enum {
   codebook_subset_fullyAndPartialAndNonCoherent = 1,
   codebook_subset_partialAndNonCoherent = 2,
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index 80469f3e815817fc97b8805ed31b4c2472924e78..49ec60c94beceffcf324f613ebb84a7798f21958 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -431,11 +431,18 @@ void nr_phy_config_request_sim(PHY_VARS_gNB *gNB,
   //gNB_config->subframe_config.dl_cyclic_prefix_type.value = (fp->Ncp == NORMAL) ? NFAPI_CP_NORMAL : NFAPI_CP_EXTENDED;
 
   gNB->mac_enabled   = 1;
-  fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
-  fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
-  fp->nr_band = 78;
-//  fp->threequarter_fs= 0;
-
+  if (mu==1) {
+    fp->dl_CarrierFreq = 3500000000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
+    fp->ul_CarrierFreq = 3500000000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
+    fp->nr_band = 78;
+    //  fp->threequarter_fs= 0;
+  } else if (mu==3) {
+    fp->dl_CarrierFreq = 27524520000;//from_nrarfcn(gNB_config->nfapi_config.rf_bands.rf_band[0],gNB_config->nfapi_config.nrarfcn.value);
+    fp->ul_CarrierFreq = 27524520000;//fp->dl_CarrierFreq - (get_uldl_offset(gNB_config->nfapi_config.rf_bands.rf_band[0])*100000);
+    fp->nr_band = 261;
+    //  fp->threequarter_fs= 0;
+  }
+    
   gNB_config->carrier_config.dl_bandwidth.value = config_bandwidth(mu, N_RB_DL, fp->nr_band);
 
   nr_init_frame_parms(gNB_config, fp);
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index 24e41d7bfbe027dd7ba1ae6eff8733e00209b0a8..9c74f3dba4b560bdc2665c4a913a77dc79480c4e 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -393,6 +393,9 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch,
   //pdsch->dl_ch_rho2_ext         = (int32_t**)malloc16_clear( 8*sizeof(int32_t*) );
   pdsch->dl_ch_mag0             = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
   pdsch->dl_ch_magb0            = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+  pdsch->ptrs_phase_per_slot    = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+  pdsch->ptrs_re_per_slot       = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
+  pdsch->dl_ch_ptrs_estimates_ext = (int32_t **)malloc16_clear( 8*sizeof(int32_t *) );
   // the allocated memory size is fixed:
   AssertFatal( fp->nb_antennas_rx <= 2, "nb_antennas_rx > 2" );
 
@@ -413,6 +416,9 @@ void phy_init_nr_ue__PDSCH(NR_UE_PDSCH *const pdsch,
       //pdsch->dl_ch_rho2_ext[idx]          = (int32_t*)malloc16_clear( sizeof(int32_t) * num );
       pdsch->dl_ch_mag0[idx]              = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
       pdsch->dl_ch_magb0[idx]             = (int32_t *)malloc16_clear( sizeof(int32_t) * num );
+      pdsch->ptrs_re_per_slot[idx]        = (int32_t *)malloc16_clear(sizeof(int32_t) * 14);
+      pdsch->ptrs_phase_per_slot[idx]     = (int32_t *)malloc16_clear( sizeof(int32_t) * 14 );
+      pdsch->dl_ch_ptrs_estimates_ext[idx]= (int32_t *)malloc16_clear( sizeof(int32_t) * num);
     }
   }
 }
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
index b6388fb903d50be7b0ecae827c47c42183dd6146..27c1ef2ac64a51ec7e379038fd40803a8661615f 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
@@ -25,6 +25,7 @@
 #include "nr_ul_estimation.h"
 #include "PHY/sse_intrin.h"
 #include "PHY/NR_REFSIG/nr_refsig.h"
+#include "PHY/NR_REFSIG/dmrs_nr.h"
 #include "PHY/NR_REFSIG/ptrs_nr.h"
 #include "PHY/NR_TRANSPORT/nr_transport_proto.h"
 #include "PHY/NR_UE_ESTIMATION/filt16a_32.h"
@@ -533,384 +534,107 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
  *  3) Compensated DMRS based estimated signal with PTRS estimation for slot
  *********************************************************************/
 void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
+                              NR_DL_FRAME_PARMS *frame_parms,
                               nfapi_nr_pusch_pdu_t *rel15_ul,
                               uint8_t ulsch_id,
                               uint8_t nr_tti_rx,
-                              uint8_t dmrs_symbol_flag,
                               unsigned char symbol,
                               uint32_t nb_re_pusch)
 {
-  NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
-  int16_t *phase_per_symbol;
-
-  uint8_t         L_ptrs          = 0;
-  uint8_t         right_side_ref  = 0;
-  uint8_t         left_side_ref   = 0;
-  uint8_t         nb_dmrs_in_slot = 0;
-
   //#define DEBUG_UL_PTRS 1
-  /* First symbol calculate PTRS symbol index for slot & set the variables */
-  if(symbol == rel15_ul->start_symbol_index)
-  {
-    gNB->pusch_vars[ulsch_id]->ptrs_symbols = 0;
-    L_ptrs = 1<<(rel15_ul->pusch_ptrs.ptrs_time_density);
-    set_ptrs_symb_idx(&gNB->pusch_vars[ulsch_id]->ptrs_symbols,
-                      rel15_ul->nr_of_symbols,
-                      rel15_ul->start_symbol_index,
-                      L_ptrs,
-                      rel15_ul->ul_dmrs_symb_pos);
-  }/* First symbol check */
-
+  int16_t *phase_per_symbol = NULL;
+  int32_t *ptrs_re_symbol   = NULL;
+  int8_t   ret = 0;
+
+  uint8_t  symbInSlot       = rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols;
+  uint8_t *startSymbIndex   = &rel15_ul->start_symbol_index;
+  uint8_t *nbSymb           = &rel15_ul->nr_of_symbols;
+  uint8_t  *L_ptrs          = &rel15_ul->pusch_ptrs.ptrs_time_density;
+  uint8_t  *K_ptrs          = &rel15_ul->pusch_ptrs.ptrs_freq_density;
+  uint16_t *dmrsSymbPos     = &rel15_ul->ul_dmrs_symb_pos;
+  uint16_t *ptrsSymbPos     = &gNB->pusch_vars[ulsch_id]->ptrs_symbols;
+  uint8_t  *ptrsSymbIdx     = &gNB->pusch_vars[ulsch_id]->ptrs_symbol_index;
+  uint8_t  *dmrsConfigType  = &rel15_ul->dmrs_config_type;
+  uint16_t *nb_rb           = &rel15_ul->rb_size;
+  uint8_t  *ptrsReOffset    = &rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset;
   /* loop over antennas */
-  for (int aarx=0; aarx< frame_parms->nb_antennas_rx; aarx++)
-  {
+  for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
     phase_per_symbol = (int16_t*)gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx];
-    /* set the previous estimations to zero at first symbol */
-    if(symbol == rel15_ul->start_symbol_index)
-    {
-      memset(phase_per_symbol,0,sizeof(int32_t)*frame_parms->symbols_per_slot);
+    ptrs_re_symbol = &gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot;
+    *ptrs_re_symbol = 0;
+    phase_per_symbol[(2*symbol)+1] = 0; // Imag
+    /* set DMRS estimates to 0 angle with magnitude 1 */
+    if(is_dmrs_symbol(symbol,*dmrsSymbPos)) {
+      /* set DMRS real estimation to 32767 */
+      phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767
+#ifdef DEBUG_UL_PTRS
+      printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]);
+#endif
+    }
+    else {// real ptrs value is set to 0
+      phase_per_symbol[2*symbol] = 0; // Real
+    }
+
+    if(symbol == *startSymbIndex) {
+      *ptrsSymbPos = 0;
+      set_ptrs_symb_idx(ptrsSymbPos,
+                        *nbSymb,
+                        *startSymbIndex,
+                        1<< *L_ptrs,
+                        *dmrsSymbPos);
     }
     /* if not PTRS symbol set current ptrs symbol index to zero*/
-    gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = 0;
-    gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol = 0;
+    *ptrsSymbIdx = 0;
     /* Check if current symbol contains PTRS */
-    if(is_ptrs_symbol(symbol, gNB->pusch_vars[ulsch_id]->ptrs_symbols))
-    {
-      gNB->pusch_vars[ulsch_id]->ptrs_symbol_index = symbol;
+    if(is_ptrs_symbol(symbol, *ptrsSymbPos)) {
+      *ptrsSymbIdx = symbol;
       /*------------------------------------------------------------------------------------------------------- */
-      /* 1) Estimate phase noise per PTRS symbol                                                                */
+      /* 1) Estimate common phase error per PTRS symbol                                                                */
       /*------------------------------------------------------------------------------------------------------- */
-      nr_pusch_phase_estimation(frame_parms,
-                                rel15_ul,
-                                (int16_t *)&gNB->pusch_vars[ulsch_id]->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch],
-                                nr_tti_rx,
-                                symbol,
-                                (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)],
-                                gNB->nr_gold_pusch_dmrs[rel15_ul->scid],
-                                &phase_per_symbol[2* symbol],
-                                &gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol);
-    }
-    /* DMRS Symbol channel estimates extraction */
-    else if(dmrs_symbol_flag)
-    {
-      phase_per_symbol[2* symbol]= (int16_t)((1<<15)-1); // 32767
-      phase_per_symbol[2* symbol +1]= 0;// no angle
+      nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb,
+                             rel15_ul->rnti,
+                             (int16_t *)&gNB->pusch_vars[ulsch_id]->ul_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pusch],
+                             nr_tti_rx,
+                             symbol,frame_parms->ofdm_symbol_size,
+                             (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(symbol * nb_re_pusch)],
+                             gNB->nr_gold_pusch_dmrs[rel15_ul->scid][nr_tti_rx][symbol],
+                             &phase_per_symbol[2* symbol],
+                             ptrs_re_symbol);
     }
     /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
-    if(symbol == (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols -1))
-    {
-      nb_dmrs_in_slot = get_dmrs_symbols_in_slot(rel15_ul->ul_dmrs_symb_pos,(rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols));
-      for(uint8_t dmrs_sym = 0; dmrs_sym < nb_dmrs_in_slot;  dmrs_sym ++)
-      {
-        if(dmrs_sym == 0)
-        {
-          /* get first DMRS position */
-          left_side_ref = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, rel15_ul->start_symbol_index, (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols));
-          /* get first DMRS position is not at start symbol position then we need to extrapolate left side  */
-          if(left_side_ref > rel15_ul->start_symbol_index)
-          {
-            left_side_ref = rel15_ul->start_symbol_index;
-          }
-        }
-        /* get the next symbol from left_side_ref value */
-        right_side_ref = get_next_dmrs_symbol_in_slot(rel15_ul->ul_dmrs_symb_pos, left_side_ref+1, (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols));
-        /* if no symbol found then interpolate till end of slot*/
-        if(right_side_ref == 0)
-        {
-          right_side_ref = (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);
+    if(symbol == (symbInSlot -1)) {
+      /*------------------------------------------------------------------------------------------------------- */
+      /* 2) Interpolate PTRS estimated value in TD */
+      /*------------------------------------------------------------------------------------------------------- */
+      /* If L-PTRS is > 0 then we need interpolation */
+      if(*L_ptrs > 0) {
+        ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb);
+        if(ret != 0) {
+          LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
         }
-        /*------------------------------------------------------------------------------------------------------- */
-        /* 2) Interpolate PTRS estimated value in TD */
-        /*------------------------------------------------------------------------------------------------------- */
-        nr_pusch_phase_interpolation(phase_per_symbol,left_side_ref,right_side_ref);
-        /* set left to last dmrs */
-        left_side_ref = right_side_ref;
-      } /*loop over dmrs positions */
-
+      }
 #ifdef DEBUG_UL_PTRS
-      LOG_M("ptrsEst.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
-      LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp",
+      LOG_M("ptrsEstUl.m","est",gNB->pusch_vars[ulsch_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
+      LOG_M("rxdataF_bf_ptrs_comp_ul.m","bf_ptrs_cmp",
             &gNB->pusch_vars[0]->rxdataF_comp[aarx][rel15_ul->start_symbol_index * NR_NB_SC_PER_RB * rel15_ul->rb_size],
             rel15_ul->nr_of_symbols * NR_NB_SC_PER_RB * rel15_ul->rb_size,1,1);
 #endif
-
       /*------------------------------------------------------------------------------------------------------- */
       /* 3) Compensated DMRS based estimated signal with PTRS estimation                                        */
       /*--------------------------------------------------------------------------------------------------------*/
-      for(uint8_t i =rel15_ul->start_symbol_index; i< (rel15_ul->start_symbol_index + rel15_ul->nr_of_symbols);i++)
-      {
+      for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) {
+        /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
+        /* Skip rotation if the slot processing is wrong */
+        if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) {
 #ifdef DEBUG_UL_PTRS
-        printf("PTRS: Rotate Symbol %2d with  %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]);
+          printf("[PHY][UL][PTRS]: Rotate Symbol %2d with  %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]);
 #endif
-        rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)],
-                          &phase_per_symbol[2* i],
-                          (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)],
-                          (rel15_ul->rb_size * NR_NB_SC_PER_RB),
-                          15);
+          rotate_cpx_vector((int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)],
+                            &phase_per_symbol[2* i],
+                            (int16_t*)&gNB->pusch_vars[ulsch_id]->rxdataF_comp[aarx][(i * rel15_ul->rb_size * NR_NB_SC_PER_RB)],
+                            ((*nb_rb) * NR_NB_SC_PER_RB), 15);
+        }// if not DMRS Symbol
       }// symbol loop
-    }//interpolation and compensation
-  }// Antenna loop
-}
-
-/*******************************************************************
- *
- * NAME :         nr_pusch_phase_estimation
- *
- * PARAMETERS :   frame_parms  : UL frame parameters
- *                rel15_ul     : UL PDU Structure
- *                Ns           :
- *                Symbol       : OFDM symbol index
- *                rxF          : Channel compensated signal
- *                ptrs_gold_seq: Gold sequence for PTRS regeneration
- *                error_est    : Estimated error output vector [Re Im]
- * RETURN :       nothing
- *
- * DESCRIPTION :
- *  perform phase estimation from regenerated PTRS SC and channel compensated
- *  signal
- *********************************************************************/
-void nr_pusch_phase_estimation(NR_DL_FRAME_PARMS *frame_parms,
-                               nfapi_nr_pusch_pdu_t *rel15_ul,
-                               int16_t *ptrs_ch_p,
-                               unsigned char Ns,
-                               unsigned char symbol,
-                               int16_t *rxF_comp,
-                               uint32_t ***ptrs_gold_seq,
-                               int16_t *error_est,
-                               uint16_t *ptrs_sc)
-{
-  uint8_t               is_ptrs_re       = 0;
-  uint16_t              re_cnt           = 0;
-  uint16_t              cnt              = 0;
-  unsigned short        nb_re_pusch      = NR_NB_SC_PER_RB * rel15_ul->rb_size;
-  uint8_t               K_ptrs           = rel15_ul->pusch_ptrs.ptrs_freq_density;
-  uint16_t              sc_per_symbol    = (rel15_ul->rb_size + K_ptrs - 1)/K_ptrs;
-  int16_t              *ptrs_p           = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol));
-  int16_t              *dmrs_comp_p      = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol));
-  double                abs              = 0.0;
-  double                real             = 0.0;
-  double                imag             = 0.0;
-#ifdef DEBUG_UL_PTRS
-  double                alpha            = 0;
-#endif
-  /* generate PTRS RE for the symbol */
-  nr_gen_ref_conj_symbols(ptrs_gold_seq[Ns][symbol],sc_per_symbol*2,ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK
-
-  /* loop over all sub carriers to get compensated RE on ptrs symbols*/
-  for (int re = 0; re < nb_re_pusch; re++)
-  {
-    is_ptrs_re = is_ptrs_subcarrier(re,
-                                    rel15_ul->rnti,
-                                    0,
-                                    rel15_ul->dmrs_config_type,
-                                    K_ptrs,
-                                    rel15_ul->rb_size,
-                                    rel15_ul->pusch_ptrs.ptrs_ports_list[0].ptrs_re_offset,
-                                    0,// start_re is 0 here
-                                    frame_parms->ofdm_symbol_size);
-    if(is_ptrs_re)
-    {
-      dmrs_comp_p[re_cnt*2]     = rxF_comp[re *2];
-      dmrs_comp_p[(re_cnt*2)+1] = rxF_comp[(re *2)+1];
-      re_cnt++;
-    }
-    else
-    {
-      /* Skip PTRS symbols and keep data in a continuous vector */
-      rxF_comp[cnt *2]= rxF_comp[re *2];
-      rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1];
-      cnt++;
-    }
-  }/* RE loop */
-  /* update the total ptrs RE in a symbol */
-  *ptrs_sc = re_cnt;
-
-  /*Multiple compensated data with conj of PTRS */
-  mult_cpx_vector(dmrs_comp_p, ptrs_p, ptrs_ch_p,(1 + sc_per_symbol/4)*4,15); // 2^15 shifted
-
-  /* loop over all ptrs sub carriers in a symbol */
-  /* sum the error vector */
-  for(int i = 0;i < sc_per_symbol; i++)
-  {
-    real+= ptrs_ch_p[(2*i)];
-    imag+= ptrs_ch_p[(2*i)+1];
-  }
-#ifdef DEBUG_UL_PTRS
-    alpha = atan(imag/real);
-    printf("PTRS: Symbol  %d atan(Im,real):= %f \n",symbol, alpha );
-#endif
-  /* mean */
-  real /= sc_per_symbol;
-  imag /= sc_per_symbol;
-  /* absolute calculation */
-  abs = sqrt(((real * real) + (imag *  imag)));
-  /* normalized error estimation */
-  error_est[0]= (real / abs)*(1<<15);
-  /* compensation in given by conjugate of estimated phase (e^-j*2*pi*fd*t)*/
-  error_est[1]= (-1)*(imag / abs)*(1<<15);
-#ifdef DEBUG_UL_PTRS
-    printf("PTRS: Estimated Symbol  %d -> %d + j* %d \n",symbol, error_est[0], error_est[1] );
-#endif
-  /* free vectors */
-  free(ptrs_p);
-  free(dmrs_comp_p);
-}
-
-
-/*******************************************************************
- *
- * NAME :         nr_pusch_phase_interpolation
- *
- * PARAMETERS :   *error_est    : Data Pointer [Re Im Re Im ...]
- *                 start_symbol : Start Symbol
- *                 end_symbol   : End Symbol
- * RETURN :       nothing
- *
- * DESCRIPTION :
- * Perform Interpolation, extrapolation based upon the estimation
- * location between the data Pointer Array.
- *
- *********************************************************************/
-void nr_pusch_phase_interpolation(int16_t *error_est,
-                                  uint8_t start_symbol,
-                                  uint8_t end_symbol
-                                  )
-{
-
-  int next = 0, prev = 0, candidates= 0, distance=0, leftEdge= 0, rightEdge = 0, getDiff =0 ;
-  double weight = 0.0;
-  double scale  = 0.125 ; // to avoid saturation due to fixed point multiplication
-#ifdef DEBUG_UL_PTRS
-  printf("PTRS: INT: Left limit %d, Right limit %d, Loop over %d Symbols \n",
-         start_symbol,end_symbol-1, (end_symbol -start_symbol)-1);
-#endif
-  for(int i =start_symbol; i< end_symbol;i++)
-  {
-    /* Only update when an estimation is found */
-    if( error_est[i*2] != 0 )
-    {
-      /* if found a symbol then set next symbol also */
-      next = nr_ptrs_find_next_estimate(error_est, i, end_symbol);
-      /* left extrapolation, if first estimate value is zero */
-      if( error_est[i*2] == 0 )
-      {
-        leftEdge = 1;
-      }
-      /* right extrapolation, if next is 0 before end symbol */
-      if((next == 0) && (end_symbol > i))
-      {
-        rightEdge = 1;
-        /* special case as no right extrapolation possible with DMRS on left */
-        /* In this case take mean of most recent 2 estimated points */
-        if(prev ==0)
-        {
-          prev = start_symbol -1;
-          next = start_symbol -2;
-          getDiff =1;
-        }else
-        {
-          /* for right edge  previous is second last from right side */
-          next = prev;
-          /* Set the current as recent estimation reference */
-          prev = i;
-        }
-      }
-      /* update  current symbol as prev  for next symbol */
-      if (rightEdge==0)
-        /* Set the current as recent estimation reference */
-        prev = i;
-    }
-    /*extrapolation left side*/
-    if(leftEdge)
-    {
-      distance = next - prev;
-      weight = 1.0/distance;
-      candidates = i;
-      for(int j = 1; j <= candidates; j++)
-      {
-        error_est[(i-j)*2]    = 8 *(((double)(error_est[prev*2]) * scale * (distance + j) * weight) -
-                                    ((double)(error_est[next*2]) * scale * j * weight));
-        error_est[((i-j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale* (distance + j) * weight) -
-                                    ((double)(error_est[((next*2)+1)]) * scale * j * weight));
-#ifdef DEBUG_UL_PTRS
-        printf("PTRS: INT: Left Edge i= %d weight= %f %d + j*%d, Prev %d Next %d \n",
-               (i-j),weight, error_est[(i-j)*2],error_est[((i-j)*2)+1], prev,next);
-#endif
-      }
-      leftEdge = 0;
-    }
-    /* extrapolation at right side */
-    else if (rightEdge )
-    {
-      if(getDiff)
-      {
-        error_est[(i+1)*2]    = ((1<<15) +(error_est[prev*2]) - error_est[next*2]);
-        error_est[((i+1)*2)+1]= error_est[(prev*2)+1] - error_est[(next*2)+1];
-#ifdef DEBUG_UL_PTRS
-        printf("PTRS: INT: Right Edge Special Case i= %d weight= %f %d + j*%d, Prev %d Next %d \n",
-               (i+1),weight, error_est[(i+1)*2],error_est[((i+1)*2)+1], prev,next);
-#endif
-        i++;
-      }
-      else
-      {
-        distance = prev - next;
-        candidates = (end_symbol -1) - i;
-        weight = 1.0/distance;
-        for(int j = 1; j <= candidates; j++)
-        {
-          error_est[(i+j)*2]    =  8 *(((double)(error_est[prev*2]) * scale * (distance + j) * weight) -
-                                       ((double)(error_est[next*2]) * scale * j * weight));
-          error_est[((i+j)*2)+1]=  8 *(((double)(error_est[(prev*2)+1]) * scale * (distance + j) * weight) -
-                                       ((double)(error_est[((next*2)+1)]) * scale *j * weight));
-#ifdef DEBUG_UL_PTRS
-          printf("PTRS: INT: Right Edge i= %d weight= %f %d + j*%d, Prev %d Next %d \n",
-                 (i+j),weight, error_est[(i+j)*2],error_est[((i+j)*2)+1], prev,next);
-#endif
-        }
-        if(candidates > 1)
-        {
-          i+=candidates;
-        }
-      }
-    }
-    /* Interpolation between 2 estimated points */
-    else if(next != 0 && ( error_est[2*i] == 0 ))
-    {
-      distance = next - prev;
-      weight = 1.0/distance;
-      candidates = next - i ;
-      for(int j = 0; j < candidates; j++)
-      {
-
-        error_est[(i+j)*2]    = 8 *(((double)(error_est[prev*2]) * scale * (distance - (j+1)) * weight) +
-                                    ((double)(error_est[next*2]) * scale * (j+1) * weight));
-        error_est[((i+j)*2)+1]= 8 *(((double)(error_est[(prev*2)+1]) * scale *(distance - (j+1)) * weight) +
-                                    ((double)(error_est[((next*2)+1)]) * scale *(j+1) * weight));
-#ifdef DEBUG_UL_PTRS
-        printf("PTRS: INT: Interpolation i= %d weight= %f %d + j*%d, Prev %d Next %d\n",
-               (i+j),weight, error_est[(i+j)*2],error_est[((i+j)*2)+1],prev,next);
-#endif
-      }
-      if(candidates > 1)
-      {
-        i+=candidates-1;
-      }
-    }// interpolation
-  }// symbol loop
-}
-
-/* Find the next non zero Real value in a complex vector */
-int nr_ptrs_find_next_estimate(int16_t *error_est,
-                               uint8_t counter,
-                               uint8_t end_symbol)
-{
-  for (int i = counter +1 ; i< end_symbol; i++)
-  {
-    if( error_est[2*i] != 0)
-    {
-      return i;
-    }
-  }
-  return 0;
+    }// last symbol check
+  }//Antenna loop
 }
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
index 0f71487e36366b740f3ee49a25ff2ec58dea2d89..a463e21839a70ba6515c8347cce3df5589047d39 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
@@ -53,28 +53,10 @@ int nr_est_timing_advance_pusch(PHY_VARS_gNB* phy_vars_gNB, int UE_id);
 
 
 void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
+                              NR_DL_FRAME_PARMS *frame_parms,
                               nfapi_nr_pusch_pdu_t *rel15_ul,
                               uint8_t ulsch_id,
                               uint8_t nr_tti_rx,
-                              uint8_t dmrs_symbol_flag,
                               unsigned char symbol,
                               uint32_t nb_re_pusch);
-
-void nr_pusch_phase_estimation(NR_DL_FRAME_PARMS *frame_parms,
-                               nfapi_nr_pusch_pdu_t *rel15_ul,
-                               int16_t *ptrs_ch_p,
-                               unsigned char Ns,
-                               unsigned char symbol,
-                               int16_t *rxF_comp,
-                               uint32_t ***ptrs_gold_seq,
-                               int16_t *error_est,
-                               uint16_t  *ptrs_sc);
-
-void nr_pusch_phase_interpolation(int16_t *error_est,
-                                  uint8_t start_symbol,
-                                  uint8_t end_symbol);
-
-int nr_ptrs_find_next_estimate(int16_t *error_est,
-                               uint8_t counter,
-                               uint8_t end_symbol);
 #endif
diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.c b/openair1/PHY/NR_REFSIG/dmrs_nr.c
index 72cb60003e08e541e07c0bb21d1cfc935e4c6061..03a37e2b279f63b8c658105db6dcab94e3c7d41b 100644
--- a/openair1/PHY/NR_REFSIG/dmrs_nr.c
+++ b/openair1/PHY/NR_REFSIG/dmrs_nr.c
@@ -364,14 +364,14 @@ void generate_dmrs_pbch(uint32_t dmrs_pbch_bitmap[DMRS_PBCH_I_SSB][DMRS_PBCH_N_H
 #endif
 }
 /* return the position of next dmrs symbol in a slot */
-int get_next_dmrs_symbol_in_slot(uint16_t  ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol)
+int8_t get_next_dmrs_symbol_in_slot(uint16_t  ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol)
 {
-  for(uint8_t symbol = counter; symbol < end_symbol; symbol++)
-    if((ul_dmrs_symb_pos >>symbol)&0x01 )
-    {
+  for(uint8_t symbol = counter; symbol < end_symbol; symbol++) {
+    if((ul_dmrs_symb_pos >> symbol) & 0x01 ) {
       return symbol;
     }
-  return 0;
+  }
+  return -1;
 }
 
 
@@ -379,9 +379,30 @@ int get_next_dmrs_symbol_in_slot(uint16_t  ul_dmrs_symb_pos, uint8_t counter, ui
 uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask,  uint16_t nb_symb)
 {
   uint8_t tmp = 0;
-  for (int i = 0; i < nb_symb; i++)
-  {
+  for (int i = 0; i < nb_symb; i++) {
     tmp += (l_prime_mask >> i) & 0x01;
   }
   return tmp;
 }
+
+/* return the position of valid dmrs symbol in a slot for channel compensation */
+int8_t get_valid_dmrs_idx_for_channel_est(uint16_t  dmrs_symb_pos, uint8_t counter)
+{
+  int8_t  symbIdx = -1;
+  /* if current symbol is DMRS then return this index */
+  if(is_dmrs_symbol(counter,  dmrs_symb_pos ) ==1) {
+    return counter;
+  }
+  /* find previous DMRS symbol */
+  for(int8_t symbol = counter;symbol >=0 ; symbol--) {
+    if((1<<symbol & dmrs_symb_pos)> 0) {
+      symbIdx = symbol;
+      break;
+    }
+  }
+  /* if there is no previous dmrs available then find the next possible*/
+  if(symbIdx == -1) {
+    symbIdx = get_next_dmrs_symbol_in_slot(dmrs_symb_pos,counter,15);
+  }
+  return symbIdx;
+}
diff --git a/openair1/PHY/NR_REFSIG/dmrs_nr.h b/openair1/PHY/NR_REFSIG/dmrs_nr.h
index 860f9977347f8b8728d3d0c7a11339639f991170..b9e9ca6f0dc7dda7f6f6ffd93e1a414e66710785 100644
--- a/openair1/PHY/NR_REFSIG/dmrs_nr.h
+++ b/openair1/PHY/NR_REFSIG/dmrs_nr.h
@@ -62,6 +62,12 @@ uint8_t allowed_xlsch_re_in_dmrs_symbol(uint16_t k,
                                         uint8_t numDmrsCdmGrpsNoData,
                                         uint8_t dmrs_type);
 
+void nr_gen_ref_conj_symbols(uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order);
+int8_t get_next_dmrs_symbol_in_slot(uint16_t  ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol);
+uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask,  uint16_t nb_symb);
+int8_t get_valid_dmrs_idx_for_channel_est(uint16_t  dmrs_symb_pos, uint8_t counter);
+
+static inline uint8_t is_dmrs_symbol(uint8_t l, uint16_t dmrsSymbMask ) { return ((dmrsSymbMask >> l) & 0x1); }
 #undef EXTERN
 
 #endif /* DMRS_NR_H */
diff --git a/openair1/PHY/NR_REFSIG/nr_gold_ue.c b/openair1/PHY/NR_REFSIG/nr_gold_ue.c
index 39ab13b1f1e7384089e7c410a1870da743b0c119..414582a31d800d26b342dbb222a4184ddd9cb278 100644
--- a/openair1/PHY/NR_REFSIG/nr_gold_ue.c
+++ b/openair1/PHY/NR_REFSIG/nr_gold_ue.c
@@ -107,9 +107,7 @@ void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
 }
 
 void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
-                   unsigned short lbar,
-                   unsigned short *n_idDMRS,
-                   unsigned short length_dmrs)
+                   unsigned short *n_idDMRS)
 {
   unsigned char ns,l;
   unsigned int n,x1,x2,x2tmp0;
@@ -129,12 +127,12 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
 
     for (ns=0; ns<20; ns++) {
 
-      for (l=0; l<length_dmrs; l++) {
+      for (l=0; l<14; l++) {
 
-    	x2tmp0 = ((14*ns+(lbar+l)+1)*((nid<<1)+1))<<17;
+        x2tmp0 = ((14*ns+l+1)*((nid<<1)+1))<<17;
         x2 = (x2tmp0+(nid<<1)+nscid)%(1<<31);  //cinit
-	LOG_D(PHY,"UE DMRS slot %d, symb %d, lbar %d, x2 %x, nscid %d\n",ns,l,lbar,x2,nscid);
-                //printf("ns %d gold pdsch x2 %d\n",ns,x2);
+        LOG_D(PHY,"UE DMRS slot %d, symb %d, x2 %x, nscid %d\n",ns,l,x2,nscid);
+        //printf("ns %d gold pdsch x2 %d\n",ns,x2);
 
         x1 = 1+ (1<<31);
         x2=x2 ^ ((x2 ^ (x2>>1) ^ (x2>>2) ^ (x2>>3))<<31);
@@ -145,7 +143,7 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
           x1 = x1 ^ (x1<<31) ^ (x1<<28);
           x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
           x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
-            //printf("x1 : %x, x2 : %x\n",x1,x2);
+          //printf("x1 : %x, x2 : %x\n",x1,x2);
         }
 
         for (n=0; n<NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD; n++) {
@@ -154,8 +152,8 @@ void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
           x2 = (x2>>1) ^ (x2>>2) ^ (x2>>3) ^ (x2>>4);
           x2 = x2 ^ (x2<<31) ^ (x2<<30) ^ (x2<<29) ^ (x2<<28);
           ue->nr_gold_pdsch[nscid][ns][l][n] = x1^x2;
-            // if ((ns==2)&&(l==0))
-            //printf("n=%d : c %x\n",n,x1^x2);
+          // if ((ns==2)&&(l==0))
+          //printf("n=%d : c %x\n",n,x1^x2);
         }
 
       }
diff --git a/openair1/PHY/NR_REFSIG/nr_refsig.h b/openair1/PHY/NR_REFSIG/nr_refsig.h
index f82a7880bba5fcc13203a692884ee597795fdc32..c5bba196a54cf47483abac7746b75dcfb49608c6 100644
--- a/openair1/PHY/NR_REFSIG/nr_refsig.h
+++ b/openair1/PHY/NR_REFSIG/nr_refsig.h
@@ -53,10 +53,6 @@ int nr_pusch_dmrs_rx(PHY_VARS_gNB *gNB,
                      uint8_t dmrs_type);
 
 void init_scrambling_luts(void);
-void nr_gen_ref_conj_symbols(uint32_t *in, uint32_t length, int16_t *output, uint16_t offset, int mod_order);
-uint8_t get_next_dmrs_symbol_in_slot(uint16_t  ul_dmrs_symb_pos, uint8_t counter, uint8_t end_symbol);
-uint8_t get_dmrs_symbols_in_slot(uint16_t l_prime_mask,  uint16_t nb_symb);
-
 void nr_generate_modulation_table(void);
 
 extern __m64 byte2m64_re[256];
diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.c b/openair1/PHY/NR_REFSIG/ptrs_nr.c
index 785252126af64cb1e5df2948c2a27038e906f1dd..b50c9a7bc9e33494e8a7881c4f58573de6c64112 100644
--- a/openair1/PHY/NR_REFSIG/ptrs_nr.c
+++ b/openair1/PHY/NR_REFSIG/ptrs_nr.c
@@ -34,7 +34,7 @@
 #include <stdio.h>
 #include "dmrs_nr.h"
 #include "PHY/NR_REFSIG/ptrs_nr.h"
-
+#include "PHY/NR_REFSIG/nr_refsig.h"
 /***********************************************************************/
 
 
@@ -180,93 +180,249 @@ uint8_t is_ptrs_subcarrier(uint16_t k,
 
   return 0;
 }
-
-/*
-int main(int argc, char const *argv[])
+/* return the total number of ptrs symbol in a slot */
+uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb)
 {
-
-  dmrs_UplinkConfig_t dmrs_Uplink_Config;
-  ptrs_UplinkConfig_t ptrs_Uplink_Config;
-  uint8_t resourceElementOffset;
-  uint8_t dmrs_antenna_port;
-  uint8_t L_ptrs, K_ptrs;
-  int16_t k_RE_ref;
-  uint16_t N_RB, ptrs_symbols, ofdm_symbol_size, k;
-  uint8_t duration_in_symbols, I_mcs;
-  uint8_t start_symbol, l;
-  uint8_t ptrs_symbol_flag;
-  uint16_t n_rnti;
-
-    dmrs_Uplink_Config.pusch_dmrs_type = pusch_dmrs_type1;
-    dmrs_Uplink_Config.pusch_dmrs_AdditionalPosition = pusch_dmrs_pos1;
-    dmrs_Uplink_Config.pusch_maxLength = pusch_len2;
-
-    ptrs_Uplink_Config.timeDensity.ptrs_mcs1 = 0; // setting MCS values to 0 indicate abscence of time_density field in the configuration
-    ptrs_Uplink_Config.timeDensity.ptrs_mcs2 = 0;
-    ptrs_Uplink_Config.timeDensity.ptrs_mcs3 = 0;
-    ptrs_Uplink_Config.frequencyDensity.n_rb0 = 0;     // setting N_RB values to 0 indicate abscence of frequency_density field in the configuration
-    ptrs_Uplink_Config.frequencyDensity.n_rb1 = 0;
-    ptrs_Uplink_Config.resourceElementOffset = 0;
-
-    n_rnti = 0x1234;
-    resourceElementOffset = 0;
-    ptrs_symbols = 0;
-  dmrs_antenna_port = 0;
-  N_RB = 50;
-  duration_in_symbols = 14;
-  ofdm_symbol_size = 2048;
-  I_mcs = 9;
-  start_symbol = 0;
-  ptrs_symbol_flag = 0;
-
-    k_RE_ref = get_kRE_ref(dmrs_antenna_port, dmrs_Uplink_Config.pusch_dmrs_type, resourceElementOffset);
-
-    K_ptrs = get_K_ptrs(&ptrs_Uplink_Config, N_RB);
-
-    L_ptrs = get_L_ptrs(&ptrs_Uplink_Config, I_mcs);
-
-    set_ptrs_symb_idx(&ptrs_symbols,
-                      &ptrs_Uplink_Config,
-                      &dmrs_Uplink_Config,
-                      1,
-                      duration_in_symbols,
-                      start_symbol,
-                      L_ptrs,
-                      ofdm_symbol_size);
-
-    printf("PTRS OFDM symbol indicies: ");
-
-    for (l = start_symbol; l < start_symbol + duration_in_symbols; l++){
-
-        ptrs_symbol_flag = is_ptrs_symbol(l,
-                                          0,
-                                          n_rnti,
-                                          N_RB,
-                                          duration_in_symbols,
-                                          dmrs_antenna_port,
-                                          K_ptrs,
-                                          ptrs_symbols,
-                                          dmrs_Uplink_Config.pusch_dmrs_type,
-                                          &ptrs_Uplink_Config);
-
-        if (ptrs_symbol_flag == 1)
-            printf(" %d ", l);
-
+  uint8_t tmp = 0;
+  for (int i = start_symb; i <= nb_symb; i++)
+    {
+      tmp += (l_prime_mask >> i) & 0x01;
     }
+  return tmp;
+}
 
-    printf("\n");
+/* return the position of next ptrs symbol in a slot */
+int8_t get_next_ptrs_symbol_in_slot(uint16_t  ptrs_symb_pos, uint8_t counter, uint8_t nb_symb)
+{
+  for(int8_t symbol = counter; symbol < nb_symb; symbol++) {
+    if((ptrs_symb_pos >>symbol)&0x01 ) {
+      return symbol;
+    }
+  }
+  return -1;
+}
 
-    printf("PTRS subcarrier indicies: ");
+/* get the next nearest estimate from DMRS or PTRS */
+int8_t get_next_estimate_in_slot(uint16_t  ptrsSymbPos,uint16_t  dmrsSymbPos, uint8_t counter,uint8_t nb_symb)
+{
+  int8_t nextPtrs = get_next_ptrs_symbol_in_slot(ptrsSymbPos, counter,nb_symb);
+  int8_t nextDmrs = get_next_dmrs_symbol_in_slot(dmrsSymbPos, counter,nb_symb);
+  if(nextDmrs == -1) {
+    return nextPtrs;
+  }
+  /* Special case when DMRS is next valid estimation */
+  if(nextPtrs == -1) {
+    return nextDmrs;
+  }
+  return (nextPtrs > nextDmrs)?nextDmrs:nextPtrs;
+}
 
-    for (k = 0; k < N_RB*12; k++){
+/*******************************************************************
+ *
+ * NAME :         nr_ptrs_cpe_estimation
+ *
+ * PARAMETERS :   K_ptrs        : K value for PTRS
+ *                ptrsReOffset  : RE offset for PTRS
+ *                dmrsConfigType: DMRS configuration type
+ *                nb_rb         : No. of resource blocks
+ *                rnti          : RNTI
+ *                ptrs_ch_p     : pointer to ptrs channel structure
+ *                Ns            :
+ *                symbol        : OFDM symbol
+ *              ofdm_symbol_size: OFDM Symbol Size
+ *                rxF_comp      : pointer to channel compensated signal
+ *                gold_seq      : Gold sequence pointer
+ *                error_est     : Estimated error output vector [Re Im]
+ *                ptrs_sc       : Total PTRS RE in a symbol
+ * RETURN :       nothing
+ *
+ * DESCRIPTION :
+ *  perform phase estimation from regenerated PTRS SC and channel compensated
+ *  signal
+ *********************************************************************/
+void nr_ptrs_cpe_estimation(uint8_t K_ptrs,
+                            uint8_t ptrsReOffset,
+                            uint8_t dmrsConfigType,
+                            uint16_t nb_rb,
+                            uint16_t rnti,
+                            int16_t *ptrs_ch_p,
+                            unsigned char Ns,
+                            unsigned char symbol,
+                            uint16_t ofdm_symbol_size,
+                            int16_t *rxF_comp,
+                            uint32_t *gold_seq,
+                            int16_t *error_est,
+                            int32_t *ptrs_sc)
+{
+//#define DEBUG_PTRS 1
+  uint8_t               is_ptrs_re       = 0;
+  uint16_t              re_cnt           = 0;
+  uint16_t              cnt              = 0;
+  unsigned short        nb_re_pdsch      = NR_NB_SC_PER_RB * nb_rb;
+  uint16_t              sc_per_symbol    = (nb_rb + K_ptrs - 1)/K_ptrs;
+  int16_t              *ptrs_p           = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol));
+  int16_t              *dmrs_comp_p      = (int16_t *)malloc(sizeof(int32_t)*(sc_per_symbol));
+  double                abs              = 0.0;
+  double                real             = 0.0;
+  double                imag             = 0.0;
+#ifdef DEBUG_PTRS
+  double                alpha            = 0;
+#endif
+  /* generate PTRS RE for the symbol */
+  nr_gen_ref_conj_symbols(gold_seq,sc_per_symbol*2,ptrs_p, NR_MOD_TABLE_QPSK_OFFSET,2);// 2 for QPSK
+
+  /* loop over all sub carriers to get compensated RE on ptrs symbols*/
+  for (int re = 0; re < nb_re_pdsch; re++) {
+    is_ptrs_re = is_ptrs_subcarrier(re,
+                                    rnti,
+                                    0,
+                                    dmrsConfigType,
+                                    K_ptrs,
+                                    nb_rb,
+                                    ptrsReOffset,
+                                    0,// start_re is 0 here
+                                    ofdm_symbol_size);
+    if(is_ptrs_re) {
+      dmrs_comp_p[re_cnt*2]     = rxF_comp[re *2];
+      dmrs_comp_p[(re_cnt*2)+1] = rxF_comp[(re *2)+1];
+      re_cnt++;
+    }
+    else {
+      /* Skip PTRS symbols and keep data in a continuous vector */
+      rxF_comp[cnt *2]= rxF_comp[re *2];
+      rxF_comp[(cnt *2)+1]= rxF_comp[(re *2)+1];
+      cnt++;
+    }
+  }/* RE loop */
+  /* update the total ptrs RE in a symbol */
+  *ptrs_sc = re_cnt;
+
+  /*Multiple compensated data with conj of PTRS */
+  mult_cpx_vector(dmrs_comp_p, ptrs_p, ptrs_ch_p,(1 + sc_per_symbol/4)*4,15); // 2^15 shifted
+
+  /* loop over all ptrs sub carriers in a symbol */
+  /* sum the error vector */
+  for(int i = 0;i < sc_per_symbol; i++) {
+    real+= ptrs_ch_p[(2*i)];
+    imag+= ptrs_ch_p[(2*i)+1];
+  }
+#ifdef DEBUG_PTRS
+  alpha = atan(imag/real);
+  printf("[PHY][PTRS]: Symbol  %d atan(Im,real):= %f \n",symbol, alpha );
+#endif
+  /* mean */
+  real /= sc_per_symbol;
+  imag /= sc_per_symbol;
+  /* absolute calculation */
+  abs = sqrt(((real * real) + (imag *  imag)));
+  /* normalized error estimation */
+  error_est[0]= (real / abs)*(1<<15);
+  /* compensation in given by conjugate of estimated phase (e^-j*2*pi*fd*t)*/
+  error_est[1]= (-1)*(imag / abs)*(1<<15);
+#ifdef DEBUG_PTRS
+  printf("[PHY][PTRS]: Estimated Symbol  %d -> %d + j* %d \n",symbol, error_est[0], error_est[1] );
+#endif
+  /* free vectors */
+  free(ptrs_p);
+  free(dmrs_comp_p);
+}
 
-        if (is_ptrs_subcarrier(k, K_ptrs, n_rnti, N_RB, k_RE_ref) == 1)
-            printf(" %d ", k);
 
+/*******************************************************************
+ *
+ * NAME :     nr_ptrs_process_slot
+ *
+ * PARAMETERS : dmrsSymbPos            DMRS symbol index mask per slot
+ *              ptrsSymbpos            PTRS symbol index mask per slot
+ *              estPerSymb             Estimated CPE pointer
+ *              startSymbIdx           First symbol index in a slot
+ *              noSymb                 total number of OFDM symbols in a slot
+ * RETURN :     True if slot is process correctly
+ * DESCRIPTION :
+ *  Process whole slot and interpolate or extrapolate estimation for the symbols
+ *  where there is neither PTRS nor DMRS configured
+ *
+ *********************************************************************/
+int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos,
+                            uint16_t ptrsSymbPos,
+                            int16_t *estPerSymb,
+                            uint16_t startSymbIdx,
+                            uint16_t noSymb)
+{
+  double         slope[2]    = {0,0};
+  double         *slope_p    = &slope[0]; 
+  uint8_t         symbInSlot = startSymbIdx + noSymb;
+  int8_t         rightRef   = 0;
+  int8_t         leftRef    = 0;
+  int8_t         tmp        = 0;
+  for(uint8_t symb = startSymbIdx; symb <symbInSlot;  symb ++) {
+    /* Update left and right reference from an estimated symbol */
+    if((is_ptrs_symbol(symb, ptrsSymbPos)) || (is_dmrs_symbol(symb,dmrsSymbPos))) {
+      leftRef  =  symb;
+      rightRef =  get_next_estimate_in_slot(ptrsSymbPos,dmrsSymbPos,symb+1,symbInSlot);
     }
+    else {
+      /* The very first symbol must be a PTRS or DMRS */
+      if((symb == startSymbIdx) && (leftRef == -1) && (rightRef == -1)) {
+        printf("Wrong PTRS Setup, PTRS compensation will be skipped !");
+        return -1;
+      }
+      /* check for left side first */
+      /*  right side a DMRS symbol then we need to left extrapolate */
+      if(is_dmrs_symbol(rightRef,dmrsSymbPos)) {
+        /* calculate slope from next valid estimates*/
+        tmp =  get_next_estimate_in_slot(ptrsSymbPos,dmrsSymbPos,rightRef+1,symbInSlot);
+        /* Special case when DMRS is not followed by PTRS symbol then reuse old slope */
+        if(tmp!=-1) {
+          get_slope_from_estimates(rightRef, tmp, estPerSymb, slope_p);
+        }
+        ptrs_estimate_from_slope(estPerSymb,slope_p,leftRef, rightRef);
+        symb = rightRef -1;
+      }
+      else if(is_ptrs_symbol(rightRef,ptrsSymbPos)) {
+        /* calculate slope from next valid estimates */
+        get_slope_from_estimates(leftRef,rightRef,estPerSymb, slope_p);
+        ptrs_estimate_from_slope(estPerSymb,slope_p,leftRef, rightRef);
+        symb = rightRef -1;
+      }
+      else if((rightRef ==-1) && (symb <symbInSlot)) {
+        // in right extrapolation use the last slope
+#ifdef DEBUG_PTRS
+        printf("[PHY][PTRS]: Last Slop Reused :(%4f %4f)\n", slope_p[0],slope_p[1]);
+#endif
+        ptrs_estimate_from_slope(estPerSymb,slope_p,symb-1,symbInSlot);
+        symb = symbInSlot;
+      }
+      else {
+        printf("Wrong PTRS Setup, PTRS compensation will be skipped !");
+        return -1;
+      }
+    }
+  }
+  return 0;
+}
 
-    printf("\n");
+/* Calculate slope from 2 reference points */
+void get_slope_from_estimates(uint8_t start, uint8_t end, int16_t *est_p, double *slope_p)
+{
+  uint8_t distance = end - start;
+  slope_p[0] = (double)(est_p[end*2] - est_p[start*2]) /distance;
+  slope_p[1] = (double)(est_p[(end*2)+1] - est_p[(start*2)+1]) /distance;
+#ifdef DEBUG_PTRS
+  printf("[PHY][PTRS]: Slop is :(%4f %4f) between Symbol %2d & Symbol %2d\n", slope_p[0],slope_p[1], start, end);
+  //printf("%d %d - %d %d\n",est_p[end*2],est_p[(end*2)+1],est_p[start*2],est_p[(start*2)+1]);
+#endif
+}
 
-  return 0;
+/* estimate from slope */
+void ptrs_estimate_from_slope(int16_t *error_est, double *slope_p, uint8_t start, uint8_t end)
+{
+  for(uint8_t i = 1; i< (end -start);i++) {
+    error_est[(start+i)*2]      = (error_est[start*2]   + (int16_t)(i * slope_p[0]));// real
+    error_est[((start +i)*2)+1] = (error_est[(start*2)+1] + (int16_t)( i * slope_p[1])); //imag
+#ifdef DEBUG_PTRS
+    printf("[PHY][PTRS]: Estimated Symbol %2d -> %4d %4d from Slope (%4f %4f)\n", start+i,error_est[(start+i)*2],error_est[((start +i)*2)+1],
+           slope_p[0],slope_p[1]);
+#endif
+  }
 }
-*/
diff --git a/openair1/PHY/NR_REFSIG/ptrs_nr.h b/openair1/PHY/NR_REFSIG/ptrs_nr.h
index e8a4e61232278c63ef559e36dadb82c94c020316..41acde0d0648ecbef152dfae6a7e39aca0e614c0 100644
--- a/openair1/PHY/NR_REFSIG/ptrs_nr.h
+++ b/openair1/PHY/NR_REFSIG/ptrs_nr.h
@@ -80,6 +80,31 @@ uint8_t is_ptrs_subcarrier(uint16_t k,
 
 static inline uint8_t is_ptrs_symbol(uint8_t l, uint16_t ptrs_symbols) { return ((ptrs_symbols >> l) & 1); }
 
-
-
+uint8_t get_ptrs_symbols_in_slot(uint16_t l_prime_mask, uint16_t start_symb, uint16_t nb_symb);
+int8_t get_next_ptrs_symbol_in_slot(uint16_t  ptrsSymbPos, uint8_t counter, uint8_t nb_symb);
+int8_t get_next_estimate_in_slot(uint16_t  ptrsSymbPos,uint16_t  dmrsSymbPos, uint8_t counter,uint8_t nb_symb);
+
+int8_t nr_ptrs_process_slot(uint16_t dmrsSymbPos,
+                            uint16_t ptrsSymbPos,
+                            int16_t *estPerSymb,
+                            uint16_t startSymbIdx,
+                            uint16_t noSymb
+                            );
+/*  general function to estimate common phase error based upon PTRS */
+void nr_ptrs_cpe_estimation(uint8_t K_ptrs,
+                            uint8_t ptrsReOffset,
+                            uint8_t dmrsConfigType,
+                            uint16_t nb_rb,
+                            uint16_t rnti,
+                            int16_t *ptrs_ch_p,
+                            unsigned char Ns,
+                            unsigned char symbol,
+                            uint16_t ofdm_symbol_size,
+                            int16_t *rxF_comp,
+                            uint32_t *gold_seq,
+                            int16_t *error_est,
+                            int32_t *ptrs_sc);
+
+void get_slope_from_estimates(uint8_t start, uint8_t end, int16_t *est_p, double *slope_p);
+void ptrs_estimate_from_slope(int16_t *error_est, double *slope_p, uint8_t start, uint8_t end);
 #endif /* PTRS_NR_H */
diff --git a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h
index 93a64051de74ba4e3d15d089981bb9deac62b9c3..f349cfcd9880ada8d7e63a6efc84a0154dc58850 100644
--- a/openair1/PHY/NR_REFSIG/refsig_defs_ue.h
+++ b/openair1/PHY/NR_REFSIG/refsig_defs_ue.h
@@ -61,9 +61,7 @@ void nr_gold_pdcch(PHY_VARS_NR_UE* ue,
                    unsigned short length_dmrs);
 
 void nr_gold_pdsch(PHY_VARS_NR_UE* ue,
-                   unsigned short lbar,
-                   unsigned short *n_idDMRS,
-                   unsigned short length_dmrs);
+                   unsigned short *n_idDMRS);
 
 void nr_init_pusch_dmrs(PHY_VARS_NR_UE* ue,
                         uint16_t *N_n_scid,
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index 7b275ea981b5a848f5187efffb9c0adbe30ea2f4..d1b868eac857e8f293fbeedf87d3f347799d3625 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -35,7 +35,9 @@
 #include "nr_sch_dmrs.h"
 #include "PHY/MODULATION/nr_modulation.h"
 #include "PHY/NR_REFSIG/dmrs_nr.h"
+#include "PHY/NR_REFSIG/ptrs_nr.h"
 #include "common/utils/LOG/vcd_signal_dumper.h"
+#include "LAYER2/NR_MAC_gNB/mac_proto.h"
 
 //#define DEBUG_DLSCH
 //#define DEBUG_DLSCH_MAPPING
@@ -117,8 +119,8 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
   uint32_t ***pdsch_dmrs = gNB->nr_gold_pdsch_dmrs[slot];
   int32_t** txdataF = gNB->common_vars.txdataF;
   int16_t amp = AMP;
-  NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
   int xOverhead = 0;
+  NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
   time_stats_t *dlsch_encoding_stats=&gNB->dlsch_encoding_stats;
   time_stats_t *dlsch_scrambling_stats=&gNB->dlsch_scrambling_stats;
   time_stats_t *dlsch_modulation_stats=&gNB->dlsch_modulation_stats;
@@ -152,13 +154,31 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
       nb_re_dmrs = 4*rel15->numDmrsCdmGrpsNoData;
       n_dmrs = ((rel15->rbSize+rel15->rbStart)*4)<<1;
     }
-    uint16_t nb_re;
-    nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs-xOverhead)*rel15->rbSize*rel15->nrOfLayers;
+
+    uint16_t dmrs_symbol_map = rel15->dlDmrsSymbPos;//single DMRS: 010000100 Double DMRS 110001100
+    uint8_t dmrs_len = get_num_dmrs(rel15->dlDmrsSymbPos);
+    uint16_t nb_re = ((12*rel15->NrOfSymbols)-nb_re_dmrs*dmrs_len-xOverhead)*rel15->rbSize*rel15->nrOfLayers;
     uint8_t Qm = rel15->qamModOrder[0];
     uint32_t encoded_length = nb_re*Qm;
     int16_t mod_dmrs[14][n_dmrs] __attribute__ ((aligned(16)));
-    
-    
+
+    /* PTRS */
+    uint16_t beta_ptrs = 1;
+    uint8_t ptrs_symbol = 0;
+    uint16_t dlPtrsSymPos = 0;
+    uint16_t n_ptrs = 0;
+    uint16_t ptrs_idx = 0;
+    uint8_t is_ptrs_re = 0;
+    if(rel15->pduBitmap & 0x1) {
+      set_ptrs_symb_idx(&dlPtrsSymPos,
+                          rel15->NrOfSymbols,
+                          rel15->StartSymbolIndex,
+                          1<<rel15->PTRSTimeDensity,
+                          rel15->dlDmrsSymbPos);
+      n_ptrs = (rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity;
+    }
+    int16_t mod_ptrs[n_ptrs<<1] __attribute__ ((aligned(16)));
+
     /// CRC, coding, interleaving and rate matching
     AssertFatal(harq->pdu!=NULL,"harq->pdu is null\n");
     start_meas(dlsch_encoding_stats);
@@ -251,22 +271,21 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
 
     /// DMRS QPSK modulation
     for (int l=rel15->StartSymbolIndex; l<rel15->StartSymbolIndex+rel15->NrOfSymbols; l++) {
-      if (rel15->dlDmrsSymbPos & (1 << l))
+      if (rel15->dlDmrsSymbPos & (1 << l)) {
         nr_modulation(pdsch_dmrs[l][0], n_dmrs, DMRS_MOD_ORDER, mod_dmrs[l]); // currently only codeword 0 is modulated. Qm = 2 as DMRS is QPSK modulated
-    }
 
 #ifdef DEBUG_DLSCH
-    l0 = get_l0(rel15->dlDmrsSymbPos);
-    printf("DMRS modulation (single symbol %d, %d symbols, type %d):\n", l0, n_dmrs>>1, dmrs_Type);
-    for (int i=0; i<n_dmrs>>4; i++) {
-      for (int j=0; j<8; j++) {
-        printf("%d %d\t", mod_dmrs[((i<<3)+j)<<1], mod_dmrs[(((i<<3)+j)<<1)+1]);
+        printf("DMRS modulation (symbol %d, %d symbols, type %d):\n", l, n_dmrs>>1, dmrs_Type);
+        for (int i=0; i<n_dmrs>>4; i++) {
+          for (int j=0; j<8; j++) {
+            printf("%d %d\t", mod_dmrs[l][((i<<3)+j)<<1], mod_dmrs[l][(((i<<3)+j)<<1)+1]);
+          }
+          printf("\n");
+        }
+#endif
       }
-      printf("\n");
     }
-#endif
-    
-    
+
     /// Resource mapping
     
     // Non interleaved VRB to PRB mapping
@@ -293,30 +312,63 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
       printf("DMRS Type %d params for ap %d: Wt %d %d \t Wf %d %d \t delta %d \t l_prime %d \t l0 %d\tDMRS symbol %d\n",
 	     1+dmrs_Type,ap, Wt[0], Wt[1], Wf[0], Wf[1], delta, l_prime, l0, dmrs_symbol);
 #endif
-      uint8_t k_prime=0;
-      uint16_t m=0, n=0, dmrs_idx=0, k=0;
-      
+
+      uint16_t m=0, dmrs_idx=0, k=0;
+
       int txdataF_offset = (slot%2)*frame_parms->samples_per_slot_wCP;
 
+      // Loop Over OFDM symbols:
       for (int l=rel15->StartSymbolIndex; l<rel15->StartSymbolIndex+rel15->NrOfSymbols; l++) {
-        k = start_sc;
-        n = 0;
-        k_prime = 0;
-        if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k)
-          dmrs_idx = rel15->rbStart*6;
-        else
-          dmrs_idx = rel15->rbStart*4;
-        for (int i=0; i<rel15->rbSize*NR_NB_SC_PER_RB; i++) {
+        /// DMRS QPSK modulation
+        uint8_t k_prime=0;
+        uint16_t n=0;
+        if ((dmrs_symbol_map & (1 << l))){ //DMRS time occasion
+          if (dmrs_Type == NFAPI_NR_DMRS_TYPE1) // another if condition to be included to check pdsch config type (reference of k)
+            dmrs_idx = rel15->rbStart*6;
+          else
+            dmrs_idx = rel15->rbStart*4;
+        }
 
-          if ((rel15->dlDmrsSymbPos & (1 << l)) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) {
+        // Update l_prime in the case of double DMRS config
+        if ((dmrs_symbol_map & (1 << l))){ //DMRS time occasion
+          if (l==(l_overline+1)) //take into account the double DMRS symbols
+            l_prime = 1;
+          else if (l>(l_overline+1)) {//new DMRS pair
+            l_overline = l;
+            l_prime = 0;
+          }
+        }
 
-            if (l==(l_overline+1)) //take into account the double DMRS symbols
-              l_prime = 1;
-            else if (l>(l_overline+1)) {//new DMRS pair
-              l_overline = l;
-              l_prime = 0;
-            }
+        /* calculate if current symbol is PTRS symbols */
+        ptrs_idx = 0;
+
+        if(rel15->pduBitmap & 0x1) {
+          ptrs_symbol = is_ptrs_symbol(l,dlPtrsSymPos);
+          if(ptrs_symbol) {
+            /* PTRS QPSK Modulation for each OFDM symbol in a slot */
+            nr_modulation(pdsch_dmrs[l][0], (n_ptrs<<1), DMRS_MOD_ORDER, mod_ptrs);
+          }
+        }
+        k = start_sc;
+        // Loop Over SCs:
+        for (int i=0; i<rel15->rbSize*NR_NB_SC_PER_RB; i++) {
+          /* check if cuurent RE is PTRS RE*/
+          is_ptrs_re=0;
+          /* check for PTRS symbol and set flag for PTRS RE */
+          if(ptrs_symbol){
+            is_ptrs_re = is_ptrs_subcarrier(k,
+                                            rel15->rnti,
+                                            ap,
+                                            rel15->dmrsConfigType,
+                                            rel15->PTRSFreqDensity,
+                                            rel15->rbSize,
+                                            rel15->PTRSReOffset,
+                                            start_sc,
+                                            frame_parms->ofdm_symbol_size);
+          }
 
+          /* Map DMRS Symbol */
+          if ( ( dmrs_symbol_map & (1 << l) ) && (k == ((start_sc+get_dmrs_freq_idx(n, k_prime, delta, dmrs_Type))%(frame_parms->ofdm_symbol_size)))) {
             ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[l][dmrs_idx<<1]) >> 15;
             ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (Wt[l_prime]*Wf[k_prime]*amp*mod_dmrs[l][(dmrs_idx<<1) + 1]) >> 15;
 #ifdef DEBUG_DLSCH_MAPPING
@@ -328,10 +380,21 @@ uint8_t nr_generate_pdsch(PHY_VARS_gNB *gNB,
             k_prime++;
             k_prime&=1;
             n+=(k_prime)?0:1;
-
-          } else {
-
-            if( (!(rel15->dlDmrsSymbPos & (1 << l))) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) {
+          }
+          /* Map PTRS Symbol */
+          else if(is_ptrs_re){
+            ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[ptrs_idx<<1]) >> 15;
+            ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (beta_ptrs*amp*mod_ptrs[(ptrs_idx<<1) + 1])>> 15;
+#ifdef DEBUG_DLSCH_MAPPING
+            printf("ptrs_idx %d\t l %d \t k %d \t k_prime %d \t n %d \t txdataF: %d %d\n",
+                   ptrs_idx, l, k, k_prime, n, ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)],
+                   ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)]);
+#endif
+            ptrs_idx++;
+          }
+          /* Map DATA Symbol */
+          else {
+            if( (!(dmrs_symbol_map & (1 << l))) || allowed_xlsch_re_in_dmrs_symbol(k,start_sc,frame_parms->ofdm_symbol_size,rel15->numDmrsCdmGrpsNoData,dmrs_Type)) {
               ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + (2*txdataF_offset)] = (amp * tx_layers[ap][m<<1]) >> 15;
               ((int16_t*)txdataF[ap])[((l*frame_parms->ofdm_symbol_size + k)<<1) + 1 + (2*txdataF_offset)] = (amp * tx_layers[ap][(m<<1) + 1]) >> 15;
 #ifdef DEBUG_DLSCH_MAPPING
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
index 80d6d13d9e2de0eb4ee027ae5e13f87790ee0a3e..cb395ff4aff5850306c85a728bef4aaeb9e1c405 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
@@ -328,8 +328,7 @@ int nr_dlsch_encoding(PHY_VARS_gNB *gNB,
   uint16_t nb_rb = rel15->rbSize;
   uint8_t nb_symb_sch = rel15->NrOfSymbols;
   uint32_t A, Kb, F=0;
-  static uint32_t Z = 0;
-  uint32_t *Zc = &Z;
+  uint32_t *Zc = &dlsch->harq_processes[harq_pid]->Z;
   uint8_t mod_order = rel15->qamModOrder[0];
   uint16_t Kr=0,r;
   uint32_t r_offset=0;
diff --git a/openair1/PHY/NR_TRANSPORT/nr_prach.c b/openair1/PHY/NR_TRANSPORT/nr_prach.c
index ba0705cde7d0973ca349e0e654f63a911cd19406..b5a3c061e9f4abbacd35d07186819a59209e106d 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_prach.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_prach.c
@@ -185,10 +185,10 @@ void rx_nr_prach_ru(RU_t *ru,
 
   for (int aa=0; aa<ru->nb_rx; aa++){ 
     if (prach_sequence_length == 0) slot2=(slot/fp->slots_per_subframe)*fp->slots_per_subframe; 
-    prach[aa] = (int16_t*)&ru->common.rxdata[aa][(slot2*fp->get_samples_per_slot(slot,fp))+sample_offset_slot-ru->N_TA_offset];
+    prach[aa] = (int16_t*)&ru->common.rxdata[aa][fp->get_samples_slot_timestamp(slot2,fp,0)+sample_offset_slot-ru->N_TA_offset];
   } 
 
-
+  idft_size_idx_t dftsize;
   int dftlen=0;
   int mu = fp->numerology_index;
   int Ncp = 0;
@@ -269,7 +269,8 @@ void rx_nr_prach_ru(RU_t *ru,
   if (LOG_DEBUGFLAG(PRACH)) {
     LOG_D(PHY,"rx_prach: Doing PRACH FFT for nb_rx:%d Ncp:%d\n",ru->nb_rx, Ncp);
   }
-  AssertFatal(mu==1,"only 30 kHz SCS handled for now\n");
+
+  
 
   // Note: Assumes PUSCH SCS @ 30 kHz, take values for formats 0-2 and adjust for others below
   int kbar = 1;
@@ -299,6 +300,7 @@ void rx_nr_prach_ru(RU_t *ru,
     AssertFatal(prach[aa]!=NULL,"prach[%d] is null\n",aa);
 
     // do DFT
+    if (mu==1) {
     if (fp->N_RB_UL <= 100)
       AssertFatal(1==0,"N_RB_UL %d not support for NR PRACH yet\n",fp->N_RB_UL);
     else if (fp->N_RB_UL < 137) {
@@ -327,36 +329,29 @@ void rx_nr_prach_ru(RU_t *ru,
 	  }
 	}// 839 sequence
 	else {
-	  if ((mu==0 && 
-	       (prachStartSymbol == 0 || prachStartSymbol == 7)) ||
-	      (mu==1 && prachStartSymbol == 0)) prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) 
-
-	  if (mu==0) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==1) {
-            dftlen=2048;
-            dft(DFT_2048,prach2,rxsigF[aa],1);
-	    if (prachFormat != 9/*C0*/) { 
-	      dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1);
-	      reps++;
-	    }
-	    if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-              dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1);
-              dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1);
-	      reps+=2;
-	    }
-	    if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-              dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1);
-              dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1);
-	      reps+=2;
-	    } 
-	    if (prachFormat == 8/*B4*/) {
-	      for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1);
-	      reps+=6;
-	    }
+	  if (prachStartSymbol == 0)
+	    prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe (15/30 kHz only) 
+
+	  dftlen=2048;
+	  dft(DFT_2048,prach2,rxsigF[aa],1);
+	  if (prachFormat != 9/*C0*/) { 
+	    dft(DFT_2048,prach2+4096,rxsigF[aa]+4096,1);
+	    reps++;
+	  }
+	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
+	    dft(DFT_2048,prach2+4096*2,rxsigF[aa]+4096*2,1);
+	    dft(DFT_2048,prach2+4096*3,rxsigF[aa]+4096*3,1);
+	    reps+=2;
+	  }
+	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
+	    dft(DFT_2048,prach2+4096*4,rxsigF[aa]+4096*4,1);
+	    dft(DFT_2048,prach2+4096*5,rxsigF[aa]+4096*5,1);
+	    reps+=2;
+	  } 
+	  if (prachFormat == 8/*B4*/) {
+	    for (int i=6;i<12;i++) dft(DFT_2048,prach2+(4096*i),rxsigF[aa]+(4096*i),1);
+	    reps+=6;
 	  }
-	  else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n");
 	}
       } else { // threequarter sampling
 	//	40 MHz @ 46.08 Ms/s
@@ -383,36 +378,28 @@ void rx_nr_prach_ru(RU_t *ru,
 	    reps=4;
 	  }
 	} else {
-	  if ((mu==0 && 
-	       (prachStartSymbol == 0 || prachStartSymbol == 7)) ||
-	      (mu==1 && prachStartSymbol == 0)) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only)
-	  if (mu==0) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==1) {
-	    dftlen=1536;
-	    dft(DFT_1536,prach2,rxsigF[aa],1);
-	    if (prachFormat != 9/*C0*/) {
-	      dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1);
-	      reps++;
-	    }
-	    
-	    if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-	      dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1);
-	      dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1);
-	      reps+=2;
-	    } 
-	    if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-	      dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1);
-	      dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1);
-	      reps+=2;
-	    } 
-	    if (prachFormat == 8/*B4*/) {
-	      for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1);
-	      reps+=6;
-	    }
-	  }// mu==1
-	  else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n");
+	  if (prachStartSymbol == 0) prach2+=48; // 24 samples @ 46.08 Ms/s in first symbol of each half subframe (15/30 kHz only)
+	  dftlen=1536;
+	  dft(DFT_1536,prach2,rxsigF[aa],1);
+	  if (prachFormat != 9/*C0*/) {
+	    dft(DFT_1536,prach2+3072,rxsigF[aa]+3072,1);
+	    reps++;
+	  }
+	  
+	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
+	    dft(DFT_1536,prach2+3072*2,rxsigF[aa]+3072*2,1);
+	    dft(DFT_1536,prach2+3072*3,rxsigF[aa]+3072*3,1);
+	    reps+=2;
+	  } 
+	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
+	    dft(DFT_1536,prach2+3072*4,rxsigF[aa]+3072*4,1);
+	    dft(DFT_1536,prach2+3072*5,rxsigF[aa]+3072*5,1);
+	    reps+=2;
+	  } 
+	  if (prachFormat == 8/*B4*/) {
+	    for (int i=6;i<12;i++) dft(DFT_1536,prach2+(3072*i),rxsigF[aa]+(3072*i),1);
+	    reps+=6;
+	  }
 	} // short format
       } // 3/4 sampling
     } // <=50 MHz BW
@@ -442,37 +429,29 @@ void rx_nr_prach_ru(RU_t *ru,
 	  }
 	}
 	else {
-	  if ((mu==0 && 
-	       (prachStartSymbol == 0 || prachStartSymbol == 7)) ||
-	      (mu==1 && prachStartSymbol == 0)) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) 
-
-	  if (mu==0) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==1) {
-	    dftlen=4096;
-	    dft(DFT_4096,prach2,rxsigF[aa],1);
-	    if (prachFormat != 9/*C0*/) { 
-	      dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1);
-	      reps++;
-	    }
-	    
-	    if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-              dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1);
-              dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1);
-	      reps+=2;
-	    } 
-	    if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-              dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1);
-              dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1);
-	      reps+=2;
-	    } 
-	    if (prachFormat == 8/*B4*/) {
-	      for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1);
-	      reps+=6;
-	    }
+	  if (prachStartSymbol == 0) prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) 
+
+	  dftlen=4096;
+	  dft(DFT_4096,prach2,rxsigF[aa],1);
+	  if (prachFormat != 9/*C0*/) { 
+	    dft(DFT_4096,prach2+8192,rxsigF[aa]+8192,1);
+	    reps++;
+	  }
+	  
+	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
+	    dft(DFT_4096,prach2+8192*2,rxsigF[aa]+8192*2,1);
+	    dft(DFT_4096,prach2+8192*3,rxsigF[aa]+8192*3,1);
+	    reps+=2;
+	  } 
+	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
+	    dft(DFT_4096,prach2+8192*4,rxsigF[aa]+8192*4,1);
+	    dft(DFT_4096,prach2+8192*5,rxsigF[aa]+8192*5,1);
+	    reps+=2;
+	  } 
+	  if (prachFormat == 8/*B4*/) {
+	    for (int i=6;i<12;i++) dft(DFT_4096,prach2+(8192*i),rxsigF[aa]+(8192*i),1);
+	    reps+=6;
 	  }
-	  else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n");
 	}
       } else {
 	AssertFatal(fp->N_RB_UL <= 217,"cannot do more than 217 PRBs with 3/4 sampling\n");
@@ -494,40 +473,85 @@ void rx_nr_prach_ru(RU_t *ru,
 	    reps=4;
 	  }
 	} else {
-	  if ((mu==0 && 
-	       (prachStartSymbol == 0 || prachStartSymbol == 7)) ||
-	      (mu==1 && prachStartSymbol == 0)) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) 
-
-	  if (mu==0) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==1) {
-	    dftlen=3072;
-	    dft(DFT_3072,prach2,rxsigF[aa],1);
-	    if (prachFormat != 9/*C0*/) {
-	      dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1);
-	      reps++;
-	    }
-	    
-	    if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
-              dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1);
-              dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1);
-	      reps+=2;
-	    } 
-	    if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
-              dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1);
-              dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1);
-	      reps+=2;
-	    } 
-	    if (prachFormat == 8/*B4*/) {
-	      for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1);
-	      reps+=6;
-	    }
+	  if (prachStartSymbol == 0) prach2+=96; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe (15/30 kHz only) 
+
+	  dftlen=3072;
+	  dft(DFT_3072,prach2,rxsigF[aa],1);
+	  if (prachFormat != 9/*C0*/) {
+	    dft(DFT_3072,prach2+6144,rxsigF[aa]+6144,1);
+	    reps++;
+	  }
+	  
+	  if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
+	    dft(DFT_3072,prach2+6144*2,rxsigF[aa]+6144*2,1);
+	    dft(DFT_3072,prach2+6144*3,rxsigF[aa]+6144*3,1);
+	    reps+=2;
+	  } 
+	  if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
+	    dft(DFT_3072,prach2+6144*4,rxsigF[aa]+6144*4,1);
+	    dft(DFT_3072,prach2+6144*5,rxsigF[aa]+6144*5,1);
+	    reps+=2;
+	  } 
+	  if (prachFormat == 8/*B4*/) {
+	    for (int i=6;i<12;i++) dft(DFT_3072,prach2+(6144*i),rxsigF[aa]+(6144*i),1);
+	    reps+=6;
 	  }
-	  else if (mu==2) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==3) AssertFatal(1==0,"Shouldn't get here\n");
-	  else if (mu==4) AssertFatal(1==0,"Shouldn't get here\n");
 	}
       }
     }
+    }
+    else if (mu==3) {
+      if (fp->threequarter_fs) {
+	AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu);
+      }
+      if (prach_sequence_length == 0) {
+	AssertFatal(1==0,"long prach not supported for numerology %d\n",mu);
+      }
+      if (fp->N_RB_UL == 32) {
+	prach2 = prach[aa] + (Ncp<<2); // Ncp is for 30.72 Ms/s, so multiply by 2 for I/Q, and 2 for 61.44Msps
+	if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0)
+	  prach2+=64; // 32 samples @ 61.44 Ms/s in first symbol of each half subframe
+	dftlen=512;
+	dftsize = DFT_512;
+      }
+      else if (fp->N_RB_UL == 66) {
+	prach2 = prach[aa] + (Ncp<<3); // Ncp is for 30.72 Ms/s, so multiply by 4 for I/Q, and 2 for 122.88Msps
+	if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0)
+	  prach2+=128; // 64 samples @ 122.88 Ms/s in first symbol of each half subframe 
+	dftlen=1024;
+	dftsize = DFT_1024;
+      }
+      else {
+	AssertFatal(1==0,"N_RB_UL %d not support for numerology %d\n",fp->N_RB_UL,mu);
+      }
+      
+      dft(dftsize,prach2,rxsigF[aa],1);
+      if (prachFormat != 9/*C0*/) {
+	dft(dftsize,prach2+dftlen*2,rxsigF[aa]+dftlen*2,1);
+	reps++;
+      }
+	  
+      if (prachFormat == 5/*A2*/ || prachFormat == 6/*A3*/|| prachFormat == 8/*B4*/ || prachFormat == 10/*C2*/) {     
+	dft(dftsize,prach2+dftlen*4,rxsigF[aa]+dftlen*4,1);
+	dft(dftsize,prach2+dftlen*6,rxsigF[aa]+dftlen*6,1);
+	reps+=2;
+      } 
+      if (prachFormat == 6/*A3*/ || prachFormat == 8/*B4*/) {     
+	dft(dftsize,prach2+dftlen*8,rxsigF[aa]+dftlen*8,1);
+	dft(dftsize,prach2+dftlen*10,rxsigF[aa]+dftlen*10,1);
+	reps+=2;
+      } 
+      if (prachFormat == 8/*B4*/) {
+	for (int i=6;i<12;i++)
+	  dft(dftsize,prach2+(dftlen*2*i),rxsigF[aa]+(dftlen*2*i),1);
+	reps+=6;
+      }
+    }
+    else {
+      AssertFatal(1==0,"Numerology not supported\n");
+    }
+
+    //LOG_M("ru_rxsigF_tmp.m","rxsFtmp", rxsigF[aa], dftlen*2*reps, 1, 1);
 
     //Coherent combining of PRACH repetitions (assumes channel does not change, to be revisted for "long" PRACH)
     LOG_D(PHY,"Doing PRACH combining of %d reptitions N_ZC %d\n",reps,N_ZC);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
index 4622c31db30522a22638bbd242b9822aa89e87cb..1372250aca76ff9f4f16381b5b93421866bd39dc 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
@@ -1234,16 +1234,16 @@ int nr_rx_pusch(PHY_VARS_gNB *gNB,
     {
       start_meas(&gNB->ulsch_ptrs_processing_stats);
       nr_pusch_ptrs_processing(gNB,
+                               frame_parms,
                                rel15_ul,
                                ulsch_id,
                                nr_tti_rx,
-                               dmrs_symbol_flag,
                                symbol,
                                nb_re_pusch);
       stop_meas(&gNB->ulsch_ptrs_processing_stats);
 
       /*  Subtract total PTRS RE's in the symbol from PUSCH RE's */
-      gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] -= gNB->pusch_vars[ulsch_id]->ptrs_sc_per_ofdm_symbol;
+      gNB->pusch_vars[ulsch_id]->ul_valid_re_per_slot[symbol] -= gNB->pusch_vars[ulsch_id]->ptrs_re_per_slot;
     }
 
     /*---------------------------------------------------------------------------------------------------- */
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 bbf4036ab8cf9cf386293c2dacf147b34d060fd1..0a37f7d6ad51d925871cabb7cd35985b99f5753e 100644
--- a/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_dl_channel_estimation.c
@@ -24,6 +24,9 @@
 #include "SCHED_NR_UE/defs.h"
 #include "nr_estimation.h"
 #include "PHY/NR_REFSIG/refsig_defs_ue.h"
+#include "PHY/NR_REFSIG/nr_refsig.h"
+#include "PHY/NR_REFSIG/dmrs_nr.h"
+#include "PHY/NR_REFSIG/ptrs_nr.h"
 #include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
 #include "filt16a_32.h"
 
@@ -667,7 +670,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
   int **dl_ch_estimates  =ue->pdsch_vars[proc->thread_id][eNB_offset]->dl_ch_estimates;
   int **rxdataF=ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF;
 
-  if (ue->high_speed_flag == 0) // use second channel estimate position for temporary storage
+  if (ue->high_speed_flag == 0)
     ch_offset     = ue->frame_parms.ofdm_symbol_size ;
   else
     ch_offset     = ue->frame_parms.ofdm_symbol_size*symbol;
@@ -686,7 +689,7 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
   uint16_t rb_offset = (bwp_start_subcarrier - ue->frame_parms.first_carrier_offset) / 12;
   uint8_t config_type = ue->dmrs_DownlinkConfig.pdsch_dmrs_type;
   int8_t delta = get_delta(p, config_type);
-  nr_pdsch_dmrs_rx(ue,Ns,ue->nr_gold_pdsch[eNB_offset][Ns][0], &pilot[0],1000+p,0,nb_rb_pdsch+rb_offset);
+  nr_pdsch_dmrs_rx(ue,Ns,ue->nr_gold_pdsch[eNB_offset][Ns][symbol], &pilot[0],1000,0,nb_rb_pdsch+rb_offset);
 
   if (config_type == pdsch_dmrs_type1){
     nushift = (p>>1)&1;
@@ -1196,3 +1199,168 @@ int nr_pdsch_channel_estimation(PHY_VARS_NR_UE *ue,
   }
   return(0);
 }
+
+/*******************************************************************
+ *
+ * NAME :         nr_pdsch_ptrs_processing
+ *
+ * PARAMETERS :   ue                : ue data structure
+ *                NR_UE_PDSCH       : pdsch_vars pointer
+ *                NR_DL_FRAME_PARMS : frame_parms pointer
+ *                NR_DL_UE_HARQ_t   : dlsch0_harq pointer
+ *                NR_DL_UE_HARQ_t   : dlsch1_harq pointer
+ *                uint8_t           : eNB_id,
+ *                uint8_t           : nr_slot_rx,
+ *                unsigned char     : symbol,
+ *                uint32_t          : nb_re_pdsch,
+ *                unsigned char     : harq_pid
+ *                uint16_t          : rnti
+ *                RX_type_t         : rx_type
+ * RETURN : Nothing
+ *
+ * DESCRIPTION :
+ *  If ptrs is enabled process the symbol accordingly
+ *  1) Estimate common phase error per PTRS symbol
+ *  2) Interpolate PTRS estimated value in TD after all PTRS symbols
+ *  3) Compensate signal with PTRS estimation for slot
+ *********************************************************************/
+void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
+                              NR_UE_PDSCH **pdsch_vars,
+                              NR_DL_FRAME_PARMS *frame_parms,
+                              NR_DL_UE_HARQ_t *dlsch0_harq,
+                              NR_DL_UE_HARQ_t *dlsch1_harq,
+                              uint8_t eNB_id,
+                              uint8_t nr_slot_rx,
+                              unsigned char symbol,
+                              uint32_t nb_re_pdsch,
+                              unsigned char harq_pid,
+                              uint16_t rnti,
+                              RX_type_t rx_type)
+{
+  //#define DEBUG_DL_PTRS 1
+  int16_t *phase_per_symbol = NULL;
+  int32_t *ptrs_re_symbol = NULL;
+  int8_t   ret = 0;
+  /* harq specific variables */
+  uint8_t  symbInSlot       = 0;
+  uint16_t *startSymbIndex  = NULL;
+  uint16_t *nbSymb          = NULL;
+  uint8_t  *L_ptrs          = NULL;
+  uint8_t  *K_ptrs          = NULL;
+  uint16_t *dmrsSymbPos     = NULL;
+  uint16_t *ptrsSymbPos     = NULL;
+  uint8_t  *ptrsSymbIdx     = NULL;
+  uint8_t  *ptrsReOffset    = NULL;
+  uint8_t  *dmrsConfigType  = NULL;
+  uint16_t *nb_rb           = NULL;
+
+  if(dlsch0_harq->status == ACTIVE) {
+    symbInSlot      = dlsch0_harq->start_symbol + dlsch0_harq->nb_symbols;
+    startSymbIndex  = &dlsch0_harq->start_symbol;
+    nbSymb          = &dlsch0_harq->nb_symbols;
+    L_ptrs          = &dlsch0_harq->PTRSTimeDensity;
+    K_ptrs          = &dlsch0_harq->PTRSFreqDensity;
+    dmrsSymbPos     = &dlsch0_harq->dlDmrsSymbPos;
+    ptrsSymbPos     = &dlsch0_harq->ptrs_symbols;
+    ptrsSymbIdx     = &dlsch0_harq->ptrs_symbol_index;
+    ptrsReOffset    = &dlsch0_harq->PTRSReOffset;
+    dmrsConfigType  = &dlsch0_harq->ptrs_symbol_index;
+    nb_rb           = &dlsch0_harq->nb_rb;
+  }
+  if(dlsch1_harq) {
+    symbInSlot      = dlsch1_harq->start_symbol + dlsch0_harq->nb_symbols;
+    startSymbIndex  = &dlsch1_harq->start_symbol;
+    nbSymb          = &dlsch1_harq->nb_symbols;
+    L_ptrs          = &dlsch1_harq->PTRSTimeDensity;
+    K_ptrs          = &dlsch1_harq->PTRSFreqDensity;
+    dmrsSymbPos     = &dlsch1_harq->dlDmrsSymbPos;
+    ptrsSymbPos     = &dlsch1_harq->ptrs_symbols;
+    ptrsSymbIdx     = &dlsch1_harq->ptrs_symbol_index;
+    ptrsReOffset    = &dlsch1_harq->PTRSReOffset;
+    dmrsConfigType  = &dlsch1_harq->ptrs_symbol_index;
+    nb_rb           = &dlsch1_harq->nb_rb;
+  }
+  /* loop over antennas */
+  for (int aarx=0; aarx<frame_parms->nb_antennas_rx; aarx++) {
+    phase_per_symbol = (int16_t*)pdsch_vars[eNB_id]->ptrs_phase_per_slot[aarx];
+    ptrs_re_symbol = (int32_t*)pdsch_vars[eNB_id]->ptrs_re_per_slot[aarx];
+    ptrs_re_symbol[symbol] = 0;
+    phase_per_symbol[(2*symbol)+1] = 0; // Imag
+    /* set DMRS estimates to 0 angle with magnitude 1 */
+    if(is_dmrs_symbol(symbol,*dmrsSymbPos)) {
+      /* set DMRS real estimation to 32767 */
+      phase_per_symbol[2*symbol]=(int16_t)((1<<15)-1); // 32767
+#ifdef DEBUG_DL_PTRS
+      printf("[PHY][PTRS]: DMRS Symbol %d -> %4d + j*%4d\n", symbol, phase_per_symbol[2*symbol],phase_per_symbol[(2*symbol)+1]);
+#endif
+    }
+    else { // real ptrs value is set to 0
+      phase_per_symbol[2*symbol] = 0; // Real
+    }
+
+    if(dlsch0_harq->status == ACTIVE) {
+      if(symbol == *startSymbIndex) {
+        *ptrsSymbPos = 0;
+        set_ptrs_symb_idx(ptrsSymbPos,
+                          *nbSymb,
+                          *startSymbIndex,
+                          1<< *L_ptrs,
+                          *dmrsSymbPos);
+      }
+      /* if not PTRS symbol set current ptrs symbol index to zero*/
+      *ptrsSymbIdx = 0;
+      /* Check if current symbol contains PTRS */
+      if(is_ptrs_symbol(symbol, *ptrsSymbPos)) {
+        *ptrsSymbIdx = symbol;
+        /*------------------------------------------------------------------------------------------------------- */
+        /* 1) Estimate common phase error per PTRS symbol                                                                */
+        /*------------------------------------------------------------------------------------------------------- */
+        nr_ptrs_cpe_estimation(*K_ptrs,*ptrsReOffset,*dmrsConfigType,*nb_rb,
+                               rnti,
+                               (int16_t *)&pdsch_vars[eNB_id]->dl_ch_ptrs_estimates_ext[aarx][symbol*nb_re_pdsch],
+                               nr_slot_rx,
+                               symbol,frame_parms->ofdm_symbol_size,
+                               (int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(symbol * nb_re_pdsch)],
+                               ue->nr_gold_pdsch[eNB_id][nr_slot_rx][symbol],
+                               &phase_per_symbol[2* symbol],
+                               &ptrs_re_symbol[symbol]);
+      }
+    }// HARQ 0
+
+    /* For last OFDM symbol at each antenna perform interpolation and compensation for the slot*/
+    if(symbol == (symbInSlot -1)) {
+      /*------------------------------------------------------------------------------------------------------- */
+      /* 2) Interpolate PTRS estimated value in TD */
+      /*------------------------------------------------------------------------------------------------------- */
+      /* If L-PTRS is > 0 then we need interpolation */
+      if(*L_ptrs > 0) {
+        ret = nr_ptrs_process_slot(*dmrsSymbPos, *ptrsSymbPos, phase_per_symbol, *startSymbIndex, *nbSymb);
+        if(ret != 0) {
+          LOG_W(PHY,"[PTRS] Compensation is skipped due to error in PTRS slot processing !!\n");
+        }
+      }
+#ifdef DEBUG_DL_PTRS
+      LOG_M("ptrsEst.m","est",pdsch_vars[eNB_id]->ptrs_phase_per_slot[aarx],frame_parms->symbols_per_slot,1,1 );
+      LOG_M("rxdataF_bf_ptrs_comp.m","bf_ptrs_cmp",
+            &pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(*startSymbIndex) * NR_NB_SC_PER_RB * (*nb_rb) ],
+            (*nb_rb) * NR_NB_SC_PER_RB * (*nbSymb),1,1);
+#endif
+      /*------------------------------------------------------------------------------------------------------- */
+      /* 3) Compensated DMRS based estimated signal with PTRS estimation                                        */
+      /*--------------------------------------------------------------------------------------------------------*/
+      for(uint8_t i = *startSymbIndex; i< symbInSlot ;i++) {
+        /* DMRS Symbol has 0 phase so no need to rotate the respective symbol */
+        /* Skip rotation if the slot processing is wrong */
+        if((!is_dmrs_symbol(i,*dmrsSymbPos)) && (ret == 0)) {
+#ifdef DEBUG_DL_PTRS
+          printf("[PHY][DL][PTRS]: Rotate Symbol %2d with  %d + j* %d\n", i, phase_per_symbol[2* i],phase_per_symbol[(2* i) +1]);
+#endif
+          rotate_cpx_vector((int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
+                            &phase_per_symbol[2* i],
+                            (int16_t*)&pdsch_vars[eNB_id]->rxdataF_comp0[aarx][(i * (*nb_rb) * NR_NB_SC_PER_RB)],
+                            ((*nb_rb) * NR_NB_SC_PER_RB), 15);
+        }// if not DMRS Symbol
+      }// symbol loop
+    }// last symbol check
+  }//Antenna loop
+}//main function
diff --git a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h
index 74168cb67133db6045cd38c465306fd10c4d9d09..419f84d4180ce3a35b9d657d5182a6e96e36c070 100644
--- a/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h
+++ b/openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h
@@ -103,6 +103,18 @@ void phy_adjust_gain_nr(PHY_VARS_NR_UE *ue,
 
 int16_t get_nr_PL(uint8_t Mod_id, uint8_t CC_id, uint8_t gNB_index);
 
+void nr_pdsch_ptrs_processing(PHY_VARS_NR_UE *ue,
+                              NR_UE_PDSCH **pdsch_vars,
+                              NR_DL_FRAME_PARMS *frame_parms,
+                              NR_DL_UE_HARQ_t *dlsch0_harq,
+                              NR_DL_UE_HARQ_t *dlsch1_harq,
+                              uint8_t eNB_id,
+                              uint8_t nr_slot_rx,
+                              unsigned char symbol,
+                              uint32_t nb_re_pdsch,
+                              unsigned char harq_pid,
+                              uint16_t rnti,
+                              RX_type_t rx_type);
 
 float_t get_nr_RSRP(module_id_t Mod_id,uint8_t CC_id,uint8_t gNB_index);
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index 61d6c72ddffd3d5ce79ce292819ffc5df470395a..75cb6ff91b1cf2f0c700cb29304cbfc2d5545194 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -279,7 +279,6 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
     nb_re_dmrs = 4*harq_process->n_dmrs_cdm_groups;
   }
   uint16_t dmrs_length = get_num_dmrs(harq_process->dlDmrsSymbPos);
-  AssertFatal(dmrs_length == 1 || dmrs_length == 2,"Illegal dmrs_length %d\n",dmrs_length);
 
   uint32_t i,j;
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
index 51e34e0c89061045fc3aff78dd6e71ce5d886e37..81349f202cc58b7a76f5ee42549dcba3c221c133 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_demodulation.c
@@ -37,7 +37,10 @@
 //#include "extern.h"
 #include "PHY/sse_intrin.h"
 #include "T.h"
+#include "openair1/PHY/NR_UE_ESTIMATION/nr_estimation.h"
 #include "openair1/PHY/NR_TRANSPORT/nr_dlsch.h"
+#include "PHY/NR_REFSIG/nr_refsig.h"
+#include "PHY/NR_REFSIG/dmrs_nr.h"
 
 #ifndef USER_MODE
 #define NOCYGWIN_STATIC static
@@ -99,6 +102,29 @@ static void nr_dlsch_layer_demapping(int16_t **llr_cw,
 				     uint16_t length,
 				     int16_t **llr_layers);
 
+
+/* compute LLR */
+static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
+                        NR_DL_FRAME_PARMS *frame_parms,
+                        int32_t **rxdataF_comp_ptr,
+                        int32_t **dl_ch_mag_ptr,
+                        NR_DL_UE_HARQ_t *dlsch0_harq,
+                        NR_DL_UE_HARQ_t *dlsch1_harq,
+                        RX_type_t rx_type,
+                        unsigned char harq_pid,
+                        unsigned char eNB_id,
+                        unsigned char eNB_id_i,
+                        unsigned char first_symbol_flag,
+                        unsigned char symbol,
+                        unsigned short nb_rb,
+                        unsigned short round,
+                        int32_t codeword_TB0,
+                        int32_t codeword_TB1,
+                        uint32_t len,
+                        uint8_t nr_slot_rx,
+                        uint8_t beamforming_mode);
+
+/* Main Function */
 int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
                 UE_nr_rxtx_proc_t *proc,
                 PDSCH_t type,
@@ -143,19 +169,17 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
   //to be updated higher layer
   unsigned short start_rb = 0;
   unsigned short nb_rb_pdsch = 50;
-  int16_t  *pllr_symbol_cw0;
-  int16_t  *pllr_symbol_cw1;
-  int16_t  *pllr_symbol_layer0;
-  int16_t  *pllr_symbol_layer1;
   //int16_t  *pllr_symbol_cw0_deint;
   //int16_t  *pllr_symbol_cw1_deint;
-  uint32_t llr_offset_symbol;
   //uint16_t bundle_L = 2;
   uint8_t pilots=0;
   uint8_t config_type = ue->dmrs_DownlinkConfig.pdsch_dmrs_type;
   uint16_t n_tx=1, n_rx=1;
   int32_t median[16];
   uint32_t len;
+  uint16_t startSymbIdx=0;
+  uint16_t nbSymb=0;
+  uint16_t pduBitmap=0x0;
 
   switch (type) {
   case SI_PDSCH:
@@ -384,7 +408,8 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
 					nb_rb_pdsch,
 					nr_slot_rx,
 					ue->high_speed_flag,
-					frame_parms);
+                                        frame_parms,
+                                        dlsch0_harq->dlDmrsSymbPos);
   
   } /*else if(beamforming_mode>7) {
     LOG_W(PHY,"dlsch_demodulation: beamforming mode not supported yet.\n");
@@ -673,376 +698,66 @@ int nr_rx_pdsch(PHY_VARS_NR_UE *ue,
 
     start_meas(&ue->generic_stat_bis[proc->thread_id][slot]);
 #endif
-  //printf("LLR dlsch0_harq->Qm %d rx_type %d cw0 %d cw1 %d symbol %d \n",dlsch0_harq->Qm,rx_type,codeword_TB0,codeword_TB1,symbol);
-  // compute LLRs
-  // -> // compute @pointer where llrs should filled for this ofdm-symbol
-
-    if (first_symbol_flag==1) pdsch_vars[eNB_id]->llr_offset[symbol-1] = 0;
-    llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol-1];
-    //pllr_symbol_cw0_deint  = (int8_t*)pdsch_vars[eNB_id]->llr[0];
-    //pllr_symbol_cw1_deint  = (int8_t*)pdsch_vars[eNB_id]->llr[1];
-    pllr_symbol_layer0 = pdsch_vars[eNB_id]->layer_llr[0];
-    pllr_symbol_layer1 = pdsch_vars[eNB_id]->layer_llr[1];
-    pllr_symbol_layer0 += llr_offset_symbol;
-    pllr_symbol_layer1 += llr_offset_symbol;
-    pllr_symbol_cw0 = pdsch_vars[eNB_id]->llr[0];
-    pllr_symbol_cw1 = pdsch_vars[eNB_id]->llr[1];
-    pllr_symbol_cw0 += llr_offset_symbol;
-    pllr_symbol_cw1 += llr_offset_symbol;
-    
-    pdsch_vars[eNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol;
- 
-  LOG_D(PHY,"compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d energy %d\n",
-             symbol,
-             nb_rb,dlsch0_harq->Qm,
-             pdsch_vars[eNB_id]->llr_length[symbol],
-             pdsch_vars[eNB_id]->llr_offset[symbol],
-	     signal_energy(pdsch_vars[eNB_id]->rxdataF_comp0[0], 7*2*frame_parms->N_RB_DL*12));
-
-
-             /*printf("compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n",
-             symbol,
-             nb_rb,dlsch0_harq->Qm,
-             pdsch_vars[eNB_id]->llr_length[symbol],
-             pdsch_vars[eNB_id]->llr_offset[symbol],
-             pdsch_vars[eNB_id]->llr[0],
-             pllr_symbol_cw0);*/
-
-  switch (dlsch0_harq->Qm) {
-  case 2 :
-    if ((rx_type==rx_standard) || (codeword_TB1 == -1)) {
-        nr_dlsch_qpsk_llr(frame_parms,
-			  pdsch_vars[eNB_id]->rxdataF_comp0,
-			  pllr_symbol_cw0,
-			  symbol,
-			  len,
-			  first_symbol_flag,
-			  nb_rb,
-			  beamforming_mode);
+  /* Store the valid DL RE's */
+    pdsch_vars[eNB_id]->dl_valid_re[symbol-1] = len;
 
-    } else if (codeword_TB0 == -1){
-
-        nr_dlsch_qpsk_llr(frame_parms,
-                       pdsch_vars[eNB_id]->rxdataF_comp0,
-                       pllr_symbol_cw1,
-                       symbol,
-					   len,
-                       first_symbol_flag,
-                       nb_rb,
-                       beamforming_mode);
-    }
-      else if (rx_type >= rx_IC_single_stream) {
-        if (dlsch1_harq->Qm == 2) {
-          nr_dlsch_qpsk_qpsk_llr(frame_parms,
-                              pdsch_vars[eNB_id]->rxdataF_comp0,
-                              rxdataF_comp_ptr,
-                              pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                              pdsch_vars[eNB_id]->layer_llr[0],
-                              symbol,len,first_symbol_flag,nb_rb,
-                              adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol),
-                              pdsch_vars[eNB_id]->llr128);
-          if (rx_type==rx_IC_dual_stream) {
-            nr_dlsch_qpsk_qpsk_llr(frame_parms,
-                                rxdataF_comp_ptr,
-                                pdsch_vars[eNB_id]->rxdataF_comp0,
-                                pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                                pdsch_vars[eNB_id]->layer_llr[1],
-                                symbol,len,first_symbol_flag,nb_rb,
-                                adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol),
-                                pdsch_vars[eNB_id]->llr128_2ndstream);
-          }
-        }
-        else if (dlsch1_harq->Qm == 4) {
-          nr_dlsch_qpsk_16qam_llr(frame_parms,
-                               pdsch_vars[eNB_id]->rxdataF_comp0,
-                               rxdataF_comp_ptr,//i
-                               dl_ch_mag_ptr,//i
-                               pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                               pdsch_vars[eNB_id]->layer_llr[0],
-                               symbol,first_symbol_flag,nb_rb,
-                               adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol),
-                               pdsch_vars[eNB_id]->llr128);
-          if (rx_type==rx_IC_dual_stream) {
-            nr_dlsch_16qam_qpsk_llr(frame_parms,
-                                 rxdataF_comp_ptr,
-                                 pdsch_vars[eNB_id]->rxdataF_comp0,//i
-                                 dl_ch_mag_ptr,
-                                 pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                                 pdsch_vars[eNB_id]->layer_llr[1],
-                                 symbol,first_symbol_flag,nb_rb,
-                                 adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol),
-                                 pdsch_vars[eNB_id]->llr128_2ndstream);
-          }
-        }
-        else {
-          nr_dlsch_qpsk_64qam_llr(frame_parms,
-                               pdsch_vars[eNB_id]->rxdataF_comp0,
-                               rxdataF_comp_ptr,//i
-                               dl_ch_mag_ptr,//i
-                               pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                               pdsch_vars[eNB_id]->layer_llr[0],
-                               symbol,first_symbol_flag,nb_rb,
-                               adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol),
-                               pdsch_vars[eNB_id]->llr128);
-          if (rx_type==rx_IC_dual_stream) {
-            nr_dlsch_64qam_qpsk_llr(frame_parms,
-                                 rxdataF_comp_ptr,
-                                 pdsch_vars[eNB_id]->rxdataF_comp0,//i
-                                 dl_ch_mag_ptr,
-                                 pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                                 pdsch_vars[eNB_id]->layer_llr[1],
-                                 symbol,first_symbol_flag,nb_rb,
-                                 adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol),
-                                 pdsch_vars[eNB_id]->llr128_2ndstream);
-          }
-        }
-      }
-    break;
-  case 4 :
-    if ((rx_type==rx_standard ) || (codeword_TB1 == -1)) {
-      nr_dlsch_16qam_llr(frame_parms,
-                      pdsch_vars[eNB_id]->rxdataF_comp0,
-                      pdsch_vars[eNB_id]->llr[0],
-                      pdsch_vars[eNB_id]->dl_ch_mag0,
-                      symbol,len,first_symbol_flag,nb_rb,
-                      pdsch_vars[eNB_id]->llr128,
-                      beamforming_mode);
-    } else if (codeword_TB0 == -1){
-      nr_dlsch_16qam_llr(frame_parms,
-                      pdsch_vars[eNB_id]->rxdataF_comp0,
-                      pdsch_vars[eNB_id]->llr[1],
-                      pdsch_vars[eNB_id]->dl_ch_mag0,
-                      symbol,len,first_symbol_flag,nb_rb,
-                      pdsch_vars[eNB_id]->llr128_2ndstream,
-                      beamforming_mode);
-    }
-    else if (rx_type >= rx_IC_single_stream) {
-      if (dlsch1_harq->Qm == 2) {
-        nr_dlsch_16qam_qpsk_llr(frame_parms,
-                             pdsch_vars[eNB_id]->rxdataF_comp0,
-                             rxdataF_comp_ptr,//i
-                             pdsch_vars[eNB_id]->dl_ch_mag0,
-                             pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                             pdsch_vars[eNB_id]->layer_llr[0],
-                             symbol,first_symbol_flag,nb_rb,
-                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol),
-                             pdsch_vars[eNB_id]->llr128);
-        if (rx_type==rx_IC_dual_stream) {
-          nr_dlsch_qpsk_16qam_llr(frame_parms,
-                               rxdataF_comp_ptr,
-                               pdsch_vars[eNB_id]->rxdataF_comp0,//i
-                               pdsch_vars[eNB_id]->dl_ch_mag0,//i
-                               pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                               pdsch_vars[eNB_id]->layer_llr[1],
-                               symbol,first_symbol_flag,nb_rb,
-                               adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol),
-                               pdsch_vars[eNB_id]->llr128_2ndstream);
-        }
-      }
-      else if (dlsch1_harq->Qm == 4) {
-        nr_dlsch_16qam_16qam_llr(frame_parms,
-                              pdsch_vars[eNB_id]->rxdataF_comp0,
-                              rxdataF_comp_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_mag0,
-                              dl_ch_mag_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                              pdsch_vars[eNB_id]->layer_llr[0],
-                              symbol,len,first_symbol_flag,nb_rb,
-                              adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol),
-                              pdsch_vars[eNB_id]->llr128);
-        if (rx_type==rx_IC_dual_stream) {
-          nr_dlsch_16qam_16qam_llr(frame_parms,
-                                rxdataF_comp_ptr,
-                                pdsch_vars[eNB_id]->rxdataF_comp0,//i
-                                dl_ch_mag_ptr,
-                                pdsch_vars[eNB_id]->dl_ch_mag0,//i
-                                pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                                pdsch_vars[eNB_id]->layer_llr[1],
-                                symbol,len,first_symbol_flag,nb_rb,
-                                adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol),
-                                pdsch_vars[eNB_id]->llr128_2ndstream);
-        }
-      }
-      else {
-        nr_dlsch_16qam_64qam_llr(frame_parms,
-                              pdsch_vars[eNB_id]->rxdataF_comp0,
-                              rxdataF_comp_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_mag0,
-                              dl_ch_mag_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                              pdsch_vars[eNB_id]->layer_llr[0],
-                              symbol,first_symbol_flag,nb_rb,
-                              adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol),
-                              pdsch_vars[eNB_id]->llr128);
-        if (rx_type==rx_IC_dual_stream) {
-          nr_dlsch_64qam_16qam_llr(frame_parms,
-                                rxdataF_comp_ptr,
-                                pdsch_vars[eNB_id]->rxdataF_comp0,
-                                dl_ch_mag_ptr,
-                                pdsch_vars[eNB_id]->dl_ch_mag0,
-                                pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                                pdsch_vars[eNB_id]->layer_llr[1],
-                                symbol,first_symbol_flag,nb_rb,
-                                adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol),
-                                pdsch_vars[eNB_id]->llr128_2ndstream);
-        }
-      }
+    if(dlsch0_harq->status == ACTIVE) {
+      startSymbIdx = dlsch0_harq->start_symbol;
+      nbSymb = dlsch0_harq->nb_symbols;
+      pduBitmap = dlsch0_harq->pduBitmap;
     }
-    break;
-  case 6 :
-    if ((rx_type==rx_standard) || (codeword_TB1 == -1))  {
-      nr_dlsch_64qam_llr(frame_parms,
-                      pdsch_vars[eNB_id]->rxdataF_comp0,
-                      (int16_t*)pllr_symbol_cw0,
-                      pdsch_vars[eNB_id]->dl_ch_mag0,
-                      pdsch_vars[eNB_id]->dl_ch_magb0,
-                      symbol,len,first_symbol_flag,nb_rb,
-                      pdsch_vars[eNB_id]->llr_offset[symbol],
-                      beamforming_mode);
-    } else if (codeword_TB0 == -1){
-      nr_dlsch_64qam_llr(frame_parms,
-                      pdsch_vars[eNB_id]->rxdataF_comp0,
-                      pllr_symbol_cw1,
-                      pdsch_vars[eNB_id]->dl_ch_mag0,
-                      pdsch_vars[eNB_id]->dl_ch_magb0,
-                      symbol,len,first_symbol_flag,nb_rb,
-                      pdsch_vars[eNB_id]->llr_offset[symbol],
-                      beamforming_mode);
-    }
-    else if (rx_type >= rx_IC_single_stream) {
-      if (dlsch1_harq->Qm == 2) {
-        nr_dlsch_64qam_qpsk_llr(frame_parms,
-                             pdsch_vars[eNB_id]->rxdataF_comp0,
-                             rxdataF_comp_ptr,//i
-                             pdsch_vars[eNB_id]->dl_ch_mag0,
-                             pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                             pdsch_vars[eNB_id]->layer_llr[0],
-                             symbol,first_symbol_flag,nb_rb,
-                             adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol),
-                             pdsch_vars[eNB_id]->llr128);
-        if (rx_type==rx_IC_dual_stream) {
-          nr_dlsch_qpsk_64qam_llr(frame_parms,
-                               rxdataF_comp_ptr,
-                               pdsch_vars[eNB_id]->rxdataF_comp0,//i
-                               pdsch_vars[eNB_id]->dl_ch_mag0,
-                               pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                               pdsch_vars[eNB_id]->layer_llr[1],
-                               symbol,first_symbol_flag,nb_rb,
-                               adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol),
-                               pdsch_vars[eNB_id]->llr128_2ndstream);
-        }
-      }
-      else if (dlsch1_harq->Qm == 4) {
-        nr_dlsch_64qam_16qam_llr(frame_parms,
-                              pdsch_vars[eNB_id]->rxdataF_comp0,
-                              rxdataF_comp_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_mag0,
-                              dl_ch_mag_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                              pdsch_vars[eNB_id]->layer_llr[0],
-                              symbol,first_symbol_flag,nb_rb,
-                              adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol),
-                              pdsch_vars[eNB_id]->llr128);
-        if (rx_type==rx_IC_dual_stream) {
-          nr_dlsch_16qam_64qam_llr(frame_parms,
-                                rxdataF_comp_ptr,
-                                pdsch_vars[eNB_id]->rxdataF_comp0,//i
-                                dl_ch_mag_ptr,
-                                pdsch_vars[eNB_id]->dl_ch_mag0,//i
-                                pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                                pdsch_vars[eNB_id]->layer_llr[1],
-                                symbol,first_symbol_flag,nb_rb,
-                                adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol),
-                                pdsch_vars[eNB_id]->llr128_2ndstream);
-        }
-      }
-      else {
-        nr_dlsch_64qam_64qam_llr(frame_parms,
-                              pdsch_vars[eNB_id]->rxdataF_comp0,
-                              rxdataF_comp_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_mag0,
-                              dl_ch_mag_ptr,//i
-                              pdsch_vars[eNB_id]->dl_ch_rho2_ext,
-                              (int16_t*)pllr_symbol_layer0,
-                              symbol,len,first_symbol_flag,nb_rb,
-                              adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol),
-                              pdsch_vars[eNB_id]->llr_offset[symbol]);
-        if (rx_type==rx_IC_dual_stream) {
-          nr_dlsch_64qam_64qam_llr(frame_parms,
-                                rxdataF_comp_ptr,
-                                pdsch_vars[eNB_id]->rxdataF_comp0,//i
-                                dl_ch_mag_ptr,
-                                pdsch_vars[eNB_id]->dl_ch_mag0,//i
-                                pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
-                                pllr_symbol_layer1,
-                                symbol,len,first_symbol_flag,nb_rb,
-                                adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol),
-                                pdsch_vars[eNB_id]->llr_offset[symbol]);
-        }
-      }
+    if(dlsch1_harq) {
+      startSymbIdx = dlsch1_harq->start_symbol;
+      nbSymb = dlsch1_harq->nb_symbols;
+      pduBitmap = dlsch1_harq->pduBitmap;
     }
-    break;
-  default:
-    LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
-    return(-1);
-    break;
-  }
 
-  if (dlsch1_harq) {
-    uint8_t Qm = nr_get_Qm_dl(dlsch1_harq->mcs,dlsch1_harq->mcs_table);
-    if (Qm == 0){
-      LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected DL DCI.\n");
-        return -1;
+    /* Check for PTRS bitmap and process it respectively */
+    if((pduBitmap & 0x1) && (type == PDSCH)) {
+      nr_pdsch_ptrs_processing(ue,
+                               pdsch_vars,
+                               frame_parms,
+                               dlsch0_harq, dlsch1_harq,
+                               eNB_id, nr_slot_rx,
+                               symbol, (nb_rb*12),
+                               harq_pid,
+                               dlsch[0]->rnti,rx_type);
+      pdsch_vars[eNB_id]->dl_valid_re[symbol-1] -= pdsch_vars[eNB_id]->ptrs_re_per_slot[0][symbol];
     }
-    switch (Qm) {
-      case 2 :
-        if (rx_type==rx_standard) {
-            nr_dlsch_qpsk_llr(frame_parms,
-                              pdsch_vars[eNB_id]->rxdataF_comp0,
-                              pllr_symbol_cw0,
-                              symbol,len,first_symbol_flag,nb_rb,
-                              beamforming_mode);
-        }
-        break;
-      case 4:
-        if (rx_type==rx_standard) {
-          nr_dlsch_16qam_llr(frame_parms,
-                             pdsch_vars[eNB_id]->rxdataF_comp0,
-                             pdsch_vars[eNB_id]->llr[0],
-                             pdsch_vars[eNB_id]->dl_ch_mag0,
-                             symbol,len,first_symbol_flag,nb_rb,
-                             pdsch_vars[eNB_id]->llr128,
-                             beamforming_mode);
+
+    /* at last symbol in a slot calculate LLR's for whole slot */
+    if(symbol == (startSymbIdx + nbSymb -1)) {
+      for(uint8_t i =startSymbIdx; i <= nbSymb;i++) {
+        /* re evaluating the first symbol flag as LLR's are done in symbol loop  */
+        if(i == startSymbIdx && i < 3) {
+          first_symbol_flag =1;
         }
-        break;
-      case 6 :
-        if (rx_type==rx_standard) {
-          nr_dlsch_64qam_llr(frame_parms,
-                             pdsch_vars[eNB_id]->rxdataF_comp0,
-                             pllr_symbol_cw0,
-                             pdsch_vars[eNB_id]->dl_ch_mag0,
-                             pdsch_vars[eNB_id]->dl_ch_magb0,
-                             symbol,len,first_symbol_flag,nb_rb,
-                             pdsch_vars[eNB_id]->llr_offset[symbol],
-                             beamforming_mode);
+        else {
+          first_symbol_flag=0;
         }
-        break;
-      default:
-        LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
-        return(-1);
-        break;
+        /* Calculate LLR's for each symbol */
+        nr_dlsch_llr(pdsch_vars, frame_parms,
+                     rxdataF_comp_ptr, dl_ch_mag_ptr,
+                     dlsch0_harq, dlsch1_harq,
+                     rx_type, harq_pid,
+                     eNB_id, eNB_id_i,
+                     first_symbol_flag,
+                     i, nb_rb, round,
+                     codeword_TB0, codeword_TB1,
+                     pdsch_vars[eNB_id]->dl_valid_re[i-1],
+                     nr_slot_rx, beamforming_mode);
+      }
     }
-  }  
 
   //nr_dlsch_deinterleaving(symbol,bundle_L,(int16_t*)pllr_symbol_cw0,(int16_t*)pllr_symbol_cw0_deint, nb_rb_pdsch);
-  
- if (rx_type==rx_IC_dual_stream) {  
-	nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr,
-				 dlsch[0]->harq_processes[harq_pid]->Nl,
-				 dlsch[0]->harq_processes[harq_pid]->Qm,
-				 dlsch[0]->harq_processes[harq_pid]->G,
-				 pdsch_vars[eNB_id]->layer_llr);
- }
+
+    if (rx_type==rx_IC_dual_stream) {
+      nr_dlsch_layer_demapping(pdsch_vars[eNB_id]->llr,
+                               dlsch[0]->harq_processes[harq_pid]->Nl,
+                               dlsch[0]->harq_processes[harq_pid]->Qm,
+                               dlsch[0]->harq_processes[harq_pid]->G,
+                               pdsch_vars[eNB_id]->layer_llr);
+    }
 
 #if UE_TIMING_TRACE
     stop_meas(&ue->generic_stat_bis[proc->thread_id][slot]);
@@ -2367,7 +2082,8 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF,
 					   unsigned short nb_rb_pdsch,
 					   unsigned char nr_slot_rx,
 					   uint32_t high_speed_flag,
-					   NR_DL_FRAME_PARMS *frame_parms) {
+                                           NR_DL_FRAME_PARMS *frame_parms,
+                                           uint16_t dlDmrsSymbPos) {
 
 
 
@@ -2375,7 +2091,7 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF,
   unsigned char i,aarx; //,nsymb,sss_symb,pss_symb=0,l;
   int *dl_ch0,*dl_ch0_ext,*rxF,*rxF_ext;
 
-
+  int8_t validDmrsEst = 0; //store last DMRS Symbol index
 
   unsigned char j=0;
 
@@ -2390,10 +2106,9 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF,
 
     k = frame_parms->first_carrier_offset + NR_NB_SC_PER_RB*start_rb;
 
-    if (high_speed_flag == 1)
-      dl_ch0     = &dl_ch_estimates[aarx][(2*(frame_parms->ofdm_symbol_size))];
-    else
-      dl_ch0     = &dl_ch_estimates[aarx][0];
+    validDmrsEst = get_valid_dmrs_idx_for_channel_est(dlDmrsSymbPos,symbol);
+
+    dl_ch0     = &dl_ch_estimates[aarx][(validDmrsEst*(frame_parms->ofdm_symbol_size))];
 
     dl_ch0_ext = &dl_ch_estimates_ext[aarx][symbol*(nb_rb_pdsch*12)];
 
@@ -2572,6 +2287,387 @@ static void nr_dlsch_layer_demapping(int16_t **llr_cw,
   AssertFatal(0, "Not supported number of layers %d\n", Nl);
   }
 }
+
+static int nr_dlsch_llr(NR_UE_PDSCH **pdsch_vars,
+                        NR_DL_FRAME_PARMS *frame_parms,
+                        int32_t **rxdataF_comp_ptr,
+                        int32_t **dl_ch_mag_ptr,
+                        NR_DL_UE_HARQ_t *dlsch0_harq,
+                        NR_DL_UE_HARQ_t *dlsch1_harq,
+                        RX_type_t rx_type,
+                        unsigned char harq_pid,
+                        unsigned char eNB_id,
+                        unsigned char eNB_id_i,
+                        unsigned char first_symbol_flag,
+                        unsigned char symbol,
+                        unsigned short nb_rb,
+                        unsigned short round,
+                        int32_t codeword_TB0,
+                        int32_t codeword_TB1,
+                        uint32_t len,
+                        uint8_t nr_slot_rx,
+                        uint8_t beamforming_mode)
+{
+
+  int16_t  *pllr_symbol_cw0;
+  int16_t  *pllr_symbol_cw1;
+  int16_t  *pllr_symbol_layer0;
+  int16_t  *pllr_symbol_layer1;
+  uint32_t llr_offset_symbol;
+  
+  if (first_symbol_flag==1) pdsch_vars[eNB_id]->llr_offset[symbol-1] = 0;
+  llr_offset_symbol = pdsch_vars[eNB_id]->llr_offset[symbol-1];
+  //pllr_symbol_cw0_deint  = (int8_t*)pdsch_vars[eNB_id]->llr[0];
+  //pllr_symbol_cw1_deint  = (int8_t*)pdsch_vars[eNB_id]->llr[1];
+  pllr_symbol_layer0 = pdsch_vars[eNB_id]->layer_llr[0];
+  pllr_symbol_layer1 = pdsch_vars[eNB_id]->layer_llr[1];
+  pllr_symbol_layer0 += llr_offset_symbol;
+  pllr_symbol_layer1 += llr_offset_symbol;
+  pllr_symbol_cw0 = pdsch_vars[eNB_id]->llr[0];
+  pllr_symbol_cw1 = pdsch_vars[eNB_id]->llr[1];
+  pllr_symbol_cw0 += llr_offset_symbol;
+  pllr_symbol_cw1 += llr_offset_symbol;
+    
+  pdsch_vars[eNB_id]->llr_offset[symbol] = len*dlsch0_harq->Qm + llr_offset_symbol;
+ 
+  /*LOG_I(PHY,"compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %x @LLR Buff(symb) %x\n",
+    symbol,
+    nb_rb,dlsch0_harq->Qm,
+    pdsch_vars[eNB_id]->llr_length[symbol],
+    pdsch_vars[eNB_id]->llr_offset[symbol],
+    (int16_t*)pdsch_vars[eNB_id]->llr[0],
+    pllr_symbol_cw0);*/
+             
+  /*printf("compute LLRs [symbol %d] NbRB %d Qm %d LLRs-Length %d LLR-Offset %d @LLR Buff %p @LLR Buff(symb) %p\n",
+    symbol,
+    nb_rb,dlsch0_harq->Qm,
+    pdsch_vars[eNB_id]->llr_length[symbol],
+    pdsch_vars[eNB_id]->llr_offset[symbol],
+    pdsch_vars[eNB_id]->llr[0],
+    pllr_symbol_cw0);*/
+
+  switch (dlsch0_harq->Qm) {
+  case 2 :
+    if ((rx_type==rx_standard) || (codeword_TB1 == -1)) {
+      nr_dlsch_qpsk_llr(frame_parms,
+                        pdsch_vars[eNB_id]->rxdataF_comp0,
+                        pllr_symbol_cw0,
+                        symbol,
+                        len,
+                        first_symbol_flag,
+                        nb_rb,
+                        beamforming_mode);
+
+    } else if (codeword_TB0 == -1){
+
+      nr_dlsch_qpsk_llr(frame_parms,
+                        pdsch_vars[eNB_id]->rxdataF_comp0,
+                        pllr_symbol_cw1,
+                        symbol,
+                        len,
+                        first_symbol_flag,
+                        nb_rb,
+                        beamforming_mode);
+    }
+    else if (rx_type >= rx_IC_single_stream) {
+      if (dlsch1_harq->Qm == 2) {
+        nr_dlsch_qpsk_qpsk_llr(frame_parms,
+                               pdsch_vars[eNB_id]->rxdataF_comp0,
+                               rxdataF_comp_ptr,
+                               pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                               pdsch_vars[eNB_id]->layer_llr[0],
+                               symbol,len,first_symbol_flag,nb_rb,
+                               adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol),
+                               pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_qpsk_qpsk_llr(frame_parms,
+                                 rxdataF_comp_ptr,
+                                 pdsch_vars[eNB_id]->rxdataF_comp0,
+                                 pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                 pdsch_vars[eNB_id]->layer_llr[1],
+                                 symbol,len,first_symbol_flag,nb_rb,
+                                 adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol),
+                                 pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+      else if (dlsch1_harq->Qm == 4) {
+        nr_dlsch_qpsk_16qam_llr(frame_parms,
+                                pdsch_vars[eNB_id]->rxdataF_comp0,
+                                rxdataF_comp_ptr,//i
+                                dl_ch_mag_ptr,//i
+                                pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                pdsch_vars[eNB_id]->layer_llr[0],
+                                symbol,first_symbol_flag,nb_rb,
+                                adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol),
+                                pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_16qam_qpsk_llr(frame_parms,
+                                  rxdataF_comp_ptr,
+                                  pdsch_vars[eNB_id]->rxdataF_comp0,//i
+                                  dl_ch_mag_ptr,
+                                  pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                  pdsch_vars[eNB_id]->layer_llr[1],
+                                  symbol,first_symbol_flag,nb_rb,
+                                  adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol),
+                                  pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+      else {
+        nr_dlsch_qpsk_64qam_llr(frame_parms,
+                                pdsch_vars[eNB_id]->rxdataF_comp0,
+                                rxdataF_comp_ptr,//i
+                                dl_ch_mag_ptr,//i
+                                pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                pdsch_vars[eNB_id]->layer_llr[0],
+                                symbol,first_symbol_flag,nb_rb,
+                                adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,2,nr_slot_rx,symbol),
+                                pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_64qam_qpsk_llr(frame_parms,
+                                  rxdataF_comp_ptr,
+                                  pdsch_vars[eNB_id]->rxdataF_comp0,//i
+                                  dl_ch_mag_ptr,
+                                  pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                  pdsch_vars[eNB_id]->layer_llr[1],
+                                  symbol,first_symbol_flag,nb_rb,
+                                  adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol),
+                                  pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+    }
+    break;
+  case 4 :
+    if ((rx_type==rx_standard ) || (codeword_TB1 == -1)) {
+      nr_dlsch_16qam_llr(frame_parms,
+                         pdsch_vars[eNB_id]->rxdataF_comp0,
+                         pdsch_vars[eNB_id]->llr[0],
+                         pdsch_vars[eNB_id]->dl_ch_mag0,
+                         symbol,len,first_symbol_flag,nb_rb,
+                         pdsch_vars[eNB_id]->llr128,
+                         beamforming_mode);
+    } else if (codeword_TB0 == -1){
+      nr_dlsch_16qam_llr(frame_parms,
+                         pdsch_vars[eNB_id]->rxdataF_comp0,
+                         pdsch_vars[eNB_id]->llr[1],
+                         pdsch_vars[eNB_id]->dl_ch_mag0,
+                         symbol,len,first_symbol_flag,nb_rb,
+                         pdsch_vars[eNB_id]->llr128_2ndstream,
+                         beamforming_mode);
+    }
+    else if (rx_type >= rx_IC_single_stream) {
+      if (dlsch1_harq->Qm == 2) {
+        nr_dlsch_16qam_qpsk_llr(frame_parms,
+                                pdsch_vars[eNB_id]->rxdataF_comp0,
+                                rxdataF_comp_ptr,//i
+                                pdsch_vars[eNB_id]->dl_ch_mag0,
+                                pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                pdsch_vars[eNB_id]->layer_llr[0],
+                                symbol,first_symbol_flag,nb_rb,
+                                adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol),
+                                pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_qpsk_16qam_llr(frame_parms,
+                                  rxdataF_comp_ptr,
+                                  pdsch_vars[eNB_id]->rxdataF_comp0,//i
+                                  pdsch_vars[eNB_id]->dl_ch_mag0,//i
+                                  pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                  pdsch_vars[eNB_id]->layer_llr[1],
+                                  symbol,first_symbol_flag,nb_rb,
+                                  adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol),
+                                  pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+      else if (dlsch1_harq->Qm == 4) {
+        nr_dlsch_16qam_16qam_llr(frame_parms,
+                                 pdsch_vars[eNB_id]->rxdataF_comp0,
+                                 rxdataF_comp_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_mag0,
+                                 dl_ch_mag_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                 pdsch_vars[eNB_id]->layer_llr[0],
+                                 symbol,len,first_symbol_flag,nb_rb,
+                                 adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol),
+                                 pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_16qam_16qam_llr(frame_parms,
+                                   rxdataF_comp_ptr,
+                                   pdsch_vars[eNB_id]->rxdataF_comp0,//i
+                                   dl_ch_mag_ptr,
+                                   pdsch_vars[eNB_id]->dl_ch_mag0,//i
+                                   pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                   pdsch_vars[eNB_id]->layer_llr[1],
+                                   symbol,len,first_symbol_flag,nb_rb,
+                                   adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol),
+                                   pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+      else {
+        nr_dlsch_16qam_64qam_llr(frame_parms,
+                                 pdsch_vars[eNB_id]->rxdataF_comp0,
+                                 rxdataF_comp_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_mag0,
+                                 dl_ch_mag_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                 pdsch_vars[eNB_id]->layer_llr[0],
+                                 symbol,first_symbol_flag,nb_rb,
+                                 adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,4,nr_slot_rx,symbol),
+                                 pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_64qam_16qam_llr(frame_parms,
+                                   rxdataF_comp_ptr,
+                                   pdsch_vars[eNB_id]->rxdataF_comp0,
+                                   dl_ch_mag_ptr,
+                                   pdsch_vars[eNB_id]->dl_ch_mag0,
+                                   pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                   pdsch_vars[eNB_id]->layer_llr[1],
+                                   symbol,first_symbol_flag,nb_rb,
+                                   adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol),
+                                   pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+    }
+    break;
+  case 6 :
+    if ((rx_type==rx_standard) || (codeword_TB1 == -1))  {
+      nr_dlsch_64qam_llr(frame_parms,
+                         pdsch_vars[eNB_id]->rxdataF_comp0,
+                         (int16_t*)pllr_symbol_cw0,
+                         pdsch_vars[eNB_id]->dl_ch_mag0,
+                         pdsch_vars[eNB_id]->dl_ch_magb0,
+                         symbol,len,first_symbol_flag,nb_rb,
+                         pdsch_vars[eNB_id]->llr_offset[symbol],
+                         beamforming_mode);
+    } else if (codeword_TB0 == -1){
+      nr_dlsch_64qam_llr(frame_parms,
+                         pdsch_vars[eNB_id]->rxdataF_comp0,
+                         pllr_symbol_cw1,
+                         pdsch_vars[eNB_id]->dl_ch_mag0,
+                         pdsch_vars[eNB_id]->dl_ch_magb0,
+                         symbol,len,first_symbol_flag,nb_rb,
+                         pdsch_vars[eNB_id]->llr_offset[symbol],
+                         beamforming_mode);
+    }
+    else if (rx_type >= rx_IC_single_stream) {
+      if (dlsch1_harq->Qm == 2) {
+        nr_dlsch_64qam_qpsk_llr(frame_parms,
+                                pdsch_vars[eNB_id]->rxdataF_comp0,
+                                rxdataF_comp_ptr,//i
+                                pdsch_vars[eNB_id]->dl_ch_mag0,
+                                pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                pdsch_vars[eNB_id]->layer_llr[0],
+                                symbol,first_symbol_flag,nb_rb,
+                                adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol),
+                                pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_qpsk_64qam_llr(frame_parms,
+                                  rxdataF_comp_ptr,
+                                  pdsch_vars[eNB_id]->rxdataF_comp0,//i
+                                  pdsch_vars[eNB_id]->dl_ch_mag0,
+                                  pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                  pdsch_vars[eNB_id]->layer_llr[1],
+                                  symbol,first_symbol_flag,nb_rb,
+                                  adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,2,nr_slot_rx,symbol),
+                                  pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+      else if (dlsch1_harq->Qm == 4) {
+        nr_dlsch_64qam_16qam_llr(frame_parms,
+                                 pdsch_vars[eNB_id]->rxdataF_comp0,
+                                 rxdataF_comp_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_mag0,
+                                 dl_ch_mag_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                 pdsch_vars[eNB_id]->layer_llr[0],
+                                 symbol,first_symbol_flag,nb_rb,
+                                 adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol),
+                                 pdsch_vars[eNB_id]->llr128);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_16qam_64qam_llr(frame_parms,
+                                   rxdataF_comp_ptr,
+                                   pdsch_vars[eNB_id]->rxdataF_comp0,//i
+                                   dl_ch_mag_ptr,
+                                   pdsch_vars[eNB_id]->dl_ch_mag0,//i
+                                   pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                   pdsch_vars[eNB_id]->layer_llr[1],
+                                   symbol,first_symbol_flag,nb_rb,
+                                   adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,4,nr_slot_rx,symbol),
+                                   pdsch_vars[eNB_id]->llr128_2ndstream);
+        }
+      }
+      else {
+        nr_dlsch_64qam_64qam_llr(frame_parms,
+                                 pdsch_vars[eNB_id]->rxdataF_comp0,
+                                 rxdataF_comp_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_mag0,
+                                 dl_ch_mag_ptr,//i
+                                 pdsch_vars[eNB_id]->dl_ch_rho2_ext,
+                                 (int16_t*)pllr_symbol_layer0,
+                                 symbol,len,first_symbol_flag,nb_rb,
+                                 adjust_G2(frame_parms,dlsch0_harq->rb_alloc_even,6,nr_slot_rx,symbol),
+                                 pdsch_vars[eNB_id]->llr_offset[symbol]);
+        if (rx_type==rx_IC_dual_stream) {
+          nr_dlsch_64qam_64qam_llr(frame_parms,
+                                   rxdataF_comp_ptr,
+                                   pdsch_vars[eNB_id]->rxdataF_comp0,//i
+                                   dl_ch_mag_ptr,
+                                   pdsch_vars[eNB_id]->dl_ch_mag0,//i
+                                   pdsch_vars[eNB_id]->dl_ch_rho_ext[harq_pid][round],
+                                   pllr_symbol_layer1,
+                                   symbol,len,first_symbol_flag,nb_rb,
+                                   adjust_G2(frame_parms,dlsch1_harq->rb_alloc_even,6,nr_slot_rx,symbol),
+                                   pdsch_vars[eNB_id]->llr_offset[symbol]);
+        }
+      }
+    }
+    break;
+  default:
+    LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
+    return(-1);
+    break;
+  }
+
+  if (dlsch1_harq) {
+    switch (nr_get_Qm_dl(dlsch1_harq->mcs,dlsch1_harq->mcs_table)) {
+    case 2 :
+      if (rx_type==rx_standard) {
+        nr_dlsch_qpsk_llr(frame_parms,
+                          pdsch_vars[eNB_id]->rxdataF_comp0,
+                          pllr_symbol_cw0,
+                          symbol,len,first_symbol_flag,nb_rb,
+                          beamforming_mode);
+      }
+      break;
+    case 4:
+      if (rx_type==rx_standard) {
+        nr_dlsch_16qam_llr(frame_parms,
+                           pdsch_vars[eNB_id]->rxdataF_comp0,
+                           pdsch_vars[eNB_id]->llr[0],
+                           pdsch_vars[eNB_id]->dl_ch_mag0,
+                           symbol,len,first_symbol_flag,nb_rb,
+                           pdsch_vars[eNB_id]->llr128,
+                           beamforming_mode);
+      }
+      break;
+    case 6 :
+      if (rx_type==rx_standard) {
+        nr_dlsch_64qam_llr(frame_parms,
+                           pdsch_vars[eNB_id]->rxdataF_comp0,
+                           pllr_symbol_cw0,
+                             pdsch_vars[eNB_id]->dl_ch_mag0,
+                             pdsch_vars[eNB_id]->dl_ch_magb0,
+                             symbol,len,first_symbol_flag,nb_rb,
+                             pdsch_vars[eNB_id]->llr_offset[symbol],
+                             beamforming_mode);
+        }
+        break;
+      default:
+        LOG_W(PHY,"rx_dlsch.c : Unknown mod_order!!!!\n");
+        return(-1);
+        break;
+    }
+  }
+  return 0;
+}
 //==============================================================================================
 
 #ifdef USER_MODE
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
index 465598d46859e50e3c185c40bad2b7808dfc5594..3ab88dac0a5aeb804ec4e45667b3ef0ccdefd19c 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
@@ -105,6 +105,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
   sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1));
   prach_start = fp->get_samples_slot_timestamp(slot, fp, 0) + sample_offset_slot;
 
+  //printf("prachstartsymbold %d, sample_offset_slot %d, prach_start %d\n",prachStartSymbol, sample_offset_slot, prach_start);
+
   // First compute physical root sequence
   /************************************************************************
   * 4G and NR NCS tables are slightly different and depend on prach format
@@ -241,6 +243,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
    *
    *********************************************************/
 
+  if (mu==1) {
   if (fp->N_RB_UL <= 100)
     AssertFatal(1 == 0, "N_RB_UL %d not support for NR PRACH yet\n", fp->N_RB_UL);
   else if (fp->N_RB_UL < 137) {
@@ -321,6 +324,22 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
       }
     }
   }
+  }
+  else if (mu==3) {
+    if (fp->threequarter_fs) 
+      AssertFatal(1==0,"3/4 sampling not supported for numerology %d\n",mu);
+    
+    if (prach_sequence_length == 0) 
+	AssertFatal(1==0,"long prach not supported for numerology %d\n",mu);
+
+    if (fp->N_RB_UL == 32) 
+      dftlen=512;
+    else if (fp->N_RB_UL == 66) 
+      dftlen=1024;
+    else 
+      AssertFatal(1==0,"N_RB_UL %d not support for numerology %d\n",fp->N_RB_UL,mu);
+  }
+
 
   for (offset=0,offset2=0; offset<N_ZC; offset++,offset2+=preamble_shift) {
 
@@ -344,6 +363,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
 
     AssertFatal(prach_fmt_id < 4, "Illegal PRACH format %d for sequence length 839\n", prach_fmt_id);
 
+    // Ncp here is given in terms of T_s wich is 30.72MHz sampling
     switch (prach_fmt_id) {
     case 0:
       Ncp = 3168;
@@ -401,13 +421,149 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
     LOG_D(PHY, "PRACH [UE %d] Ncp %d, dftlen %d \n", Mod_id, Ncp, dftlen);
   #endif
 
-  if (fp->N_RB_UL <= 100)
-    AssertFatal(1==0,"N_RB_UL %d not supported for NR PRACH yet\n",fp->N_RB_UL);
+  //actually what we should be checking here is how often the current prach crosses a 0.5ms boundary. I am not quite sure for which paramter set this would be the case, so I will ignore it for now and just check if the prach starts on a 0.5ms boundary
+  uint8_t  use_extended_prach_prefix = 0;
+  if(fp->numerology_index == 0) {
+    if (prachStartSymbol == 0 || prachStartSymbol == 7)
+	  use_extended_prach_prefix = 1;
+  }
+  else {
+    if (slot%(fp->slots_per_subframe/2)==0 && prachStartSymbol == 0)
+	  use_extended_prach_prefix = 1;
+  }
+    
+  if (fp->N_RB_UL <= 34) { //32 PRB case 61.44Msps
+    if (fp->threequarter_fs == 0) {
+      Ncp<<=1; //to account for 61.44Mbps
+      // This is after cyclic prefix 
+      prach2 = prach+(Ncp<<1); //times 2 for complex samples
+      if (prach_sequence_length == 0)
+	AssertFatal(1==0,"no long PRACH for this PRACH size %d\n",fp->N_RB_UL);
+      else {
+	if (use_extended_prach_prefix) 
+          Ncp+=32;  // 16*kappa, kappa=2 for 61.44Msps
+	prach2 = prach+(Ncp<<1); //times 2 for complex samples
+        if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have |empty | Prach512 |
+          if (prach_fmt_id != 9) {
+            memmove(prach2+(512<<1),prach2,(512<<2));
+            prach_len = (512*2)+Ncp;
+          }
+          else prach_len = (512*1)+Ncp;
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have |Prefix | Prach512 | Prach512 (if ! 0xc0)  |
+        } else if (prach_fmt_id == 5) { // 6x512
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have |empty | Prach512 |
+          memmove(prach2+(512<<1),prach2,(512<<2));
+          // here we have |empty | Prach512 | Prach512| empty512 | empty512 |
+          memmove(prach2+(512<<2),prach2,(512<<3));
+          // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 |
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have |Prefix | Prach512 |
+          prach_len = (512*4)+Ncp;
+        } else if (prach_fmt_id == 6) { // 6x512
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have |empty | Prach512 |
+          memmove(prach2+(512<<1),prach2,(512<<2));
+          // here we have |empty | Prach512 | Prach512| empty512 | empty512 | empty512 | empty512
+          memmove(prach2+(512<<2),prach2,(512<<3));
+          // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | empty512 | empty512
+          memmove(prach2+(512<<3),prach2,(512<<3));
+          // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have |Prefix | Prach512 |
+          prach_len = (512*6)+Ncp;
+        } else if (prach_fmt_id == 8) { // 12x512
+          idft(IDFT_512,prachF,prach2,1);
+          // here we have |empty | Prach512 |
+          memmove(prach2+(512<<1),prach2,(512<<2));
+          // here we have |empty | Prach512 | Prach512| empty512 | empty512 | empty512 | empty512
+          memmove(prach2+(512<<2),prach2,(512<<3));
+          // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | empty512 | empty512
+          memmove(prach2+(512<<3),prach2,(512<<3));
+          // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512
+          memmove(prach2+(512<<1)*6,prach2,(512<<2)*6);
+          // here we have |empty | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512|
+          memmove(prach,prach+(512<<1),(Ncp<<2));
+          // here we have |Prefix | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512 | Prach512 | Prach512| Prach512 | Prach512 | Prach512 | Prach512|
+          prach_len = (512*12)+Ncp;
+	}		
+      }
+    }
+    else
+      AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL);
+   
+  }
+  else if (fp->N_RB_UL <= 68) {//66 PRB case, 122.88 Msps 
+    if (fp->threequarter_fs == 0) {
+      Ncp<<=2; //to account for 122.88Mbps
+      // This is after cyclic prefix 
+      prach2 = prach+(Ncp<<1); //times 2 for complex samples
+      if (prach_sequence_length == 0)
+	AssertFatal(1==0,"no long PRACH for this PRACH size %d\n",fp->N_RB_UL);
+      else {
+	if (use_extended_prach_prefix) 
+          Ncp+=64;  // 16*kappa, kappa=4 for 122.88Msps
+	prach2 = prach+(Ncp<<1); //times 2 for complex samples
+        if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have |empty | Prach1024 |
+          if (prach_fmt_id != 9) {
+            memmove(prach2+(1024<<1),prach2,(1024<<2));
+            prach_len = (1024*2)+Ncp;
+          }
+          else prach_len = (1024*1)+Ncp;
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have |Prefix | Prach1024 | Prach1024 (if ! 0xc0)  |
+        } else if (prach_fmt_id == 5) { // 6x1024
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have |empty | Prach1024 |
+          memmove(prach2+(1024<<1),prach2,(1024<<2));
+          // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 |
+          memmove(prach2+(1024<<2),prach2,(1024<<3));
+          // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 |
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have |Prefix | Prach1024 |
+          prach_len = (1024*4)+Ncp;
+        } else if (prach_fmt_id == 6) { // 6x1024
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have |empty | Prach1024 |
+          memmove(prach2+(1024<<1),prach2,(1024<<2));
+          // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | empty1024 | empty1024
+          memmove(prach2+(1024<<2),prach2,(1024<<3));
+          // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | empty1024 | empty1024
+          memmove(prach2+(1024<<3),prach2,(1024<<3));
+          // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have |Prefix | Prach1024 |
+          prach_len = (1024*6)+Ncp;
+        } else if (prach_fmt_id == 8) { // 12x1024
+          idft(IDFT_1024,prachF,prach2,1);
+          // here we have |empty | Prach1024 |
+          memmove(prach2+(1024<<1),prach2,(1024<<2));
+          // here we have |empty | Prach1024 | Prach1024| empty1024 | empty1024 | empty1024 | empty1024
+          memmove(prach2+(1024<<2),prach2,(1024<<3));
+          // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | empty1024 | empty1024
+          memmove(prach2+(1024<<3),prach2,(1024<<3));
+          // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024
+          memmove(prach2+(1024<<1)*6,prach2,(1024<<2)*6);
+          // here we have |empty | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024|
+          memmove(prach,prach+(1024<<1),(Ncp<<2));
+          // here we have |Prefix | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024 | Prach1024| Prach1024 | Prach1024 | Prach1024 | Prach1024|
+          prach_len = (1024*12)+Ncp;
+	}	
+      }
+    }
+    else
+      AssertFatal(1==0,"3/4 sampling not supported for this PRACH size %d\n",fp->N_RB_UL);
+  }
   else if (fp->N_RB_UL < 137) { // 46.08 or 61.44 Ms/s
     if (fp->threequarter_fs == 0) { // full sampling @ 61.44 Ms/s
-      Ncp<<=1;
-      // This is after cyclic prefix (Ncp<<1 samples for 30.72 Ms/s, Ncp<<2 samples for 61.44 Ms/s
-      prach2 = prach+(Ncp<<1);
+      Ncp<<=1; //to account for 61.44Mbps 
+      // This is after cyclic prefix 
+      prach2 = prach+(Ncp<<1); //times 2 for complex samples
       if (prach_sequence_length == 0){
         if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 49152 samples @ 61.44 Ms/s
           idft(IDFT_49152,prachF,prach2,1);
@@ -442,9 +598,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (12288*4)+Ncp;
         }
       } else { // short PRACH sequence
+	if (use_extended_prach_prefix) 
+	  Ncp+=32; // 16*kappa, kappa=2 for 61.44Msps 
+	prach2 = prach+(Ncp<<1); //times 2 for complex samples
         if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
-          Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_2048,prachF,prach2,1);
           // here we have |empty | Prach2048 |
           if (prach_fmt_id != 9) {
@@ -455,8 +612,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           memmove(prach,prach+(2048<<1),(Ncp<<2));
           // here we have |Prefix | Prach2048 | Prach2048 (if ! 0xc0)  |
         } else if (prach_fmt_id == 5) { // 6x2048
-          Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_2048,prachF,prach2,1);
           // here we have |empty | Prach2048 |
           memmove(prach2+(2048<<1),prach2,(2048<<2));
@@ -467,8 +622,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach2048 |
           prach_len = (2048*4)+Ncp;
         } else if (prach_fmt_id == 6) { // 6x2048
-          Ncp+=32;
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_2048,prachF,prach2,1);
           // here we have |empty | Prach2048 |
           memmove(prach2+(2048<<1),prach2,(2048<<2));
@@ -481,8 +634,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach2048 |
           prach_len = (2048*6)+Ncp;
         } else if (prach_fmt_id == 8) { // 12x2048
-          Ncp+=32; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_2048,prachF,prach2,1);
           // here we have |empty | Prach2048 |
           memmove(prach2+(2048<<1),prach2,(2048<<2));
@@ -535,9 +686,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (9216*4)+Ncp;
         }
       } else { // short sequence
+	if (use_extended_prach_prefix) 
+	  Ncp+=24; // 16*kappa, kappa=1.5 for 46.08Msps 
+	prach2 = prach+(Ncp<<1); //times 2 for complex samples
         if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
-          Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_1536,prachF,prach2,1);
           // here we have |empty | Prach1536 |
           if (prach_fmt_id != 9) {
@@ -549,9 +701,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach1536 | Prach1536 (if ! 0xc0) |
 
         } else if (prach_fmt_id == 5) { // 6x1536
-
-          Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_1536,prachF,prach2,1);
           // here we have |empty | Prach1536 |
           memmove(prach2+(1536<<1),prach2,(1536<<2));
@@ -562,8 +711,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach1536 |
           prach_len = (1536*4)+Ncp;
         } else if (prach_fmt_id == 6) { // 6x1536
-          Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_1536,prachF,prach2,1);
           // here we have |empty | Prach1536 |
           memmove(prach2+(1536<<1),prach2,(1536<<2));
@@ -576,8 +723,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach1536 |
           prach_len = (1536*6)+Ncp;
         } else if (prach_fmt_id == 8) { // 12x1536
-          Ncp+=24; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_1536,prachF,prach2,1);
           // here we have |empty | Prach1536 |
           memmove(prach2+(1536<<1),prach2,(1536<<2));
@@ -596,8 +741,9 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
     }
   } else if (fp->N_RB_UL <= 273) {// 92.16 or 122.88 Ms/s
     if (fp->threequarter_fs == 0) { // full sampling @ 122.88 Ms/s
-      Ncp<<=2;
-      prach2 = prach+(Ncp<<1);
+      Ncp<<=2; //to account for 122.88Mbps
+      // This is after cyclic prefix
+      prach2 = prach+(Ncp<<1); //times 2 for complex samples
       if (prach_sequence_length == 0){
         if (prach_fmt_id == 0) { //24576 samples @ 30.72 Ms/s, 98304 samples @ 122.88 Ms/s
           idft(IDFT_98304,prachF,prach2,1);
@@ -632,9 +778,10 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (24576*4)+Ncp;
         }
       } else { // short sequence
+	if (use_extended_prach_prefix) 
+          Ncp+=64; // 16*kappa, kappa=4 for 122.88Msps
+	prach2 = prach+(Ncp<<1); //times 2 for complex samples
         if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
-          Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_4096,prachF,prach2,1);
           // here we have |empty | Prach4096 |
           if (prach_fmt_id != 9) {
@@ -644,8 +791,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           memmove(prach,prach+(4096<<1),(Ncp<<2));
           // here we have |Prefix | Prach4096 | Prach4096 (if ! 0xc0) |
         } else if (prach_fmt_id == 5) { // 4x4096
-          Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_4096,prachF,prach2,1);
           // here we have |empty | Prach4096 |
           memmove(prach2+(4096<<1),prach2,(4096<<2));
@@ -656,8 +801,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach4096 |
           prach_len = (4096*4)+Ncp;
         } else if (prach_fmt_id == 6) { // 6x4096
-          Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_4096,prachF,prach2,1);
           // here we have |empty | Prach4096 |
           memmove(prach2+(4096<<1),prach2,(4096<<2));
@@ -670,8 +813,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach4096 |
           prach_len = (4096*6)+Ncp;
         } else if (prach_fmt_id == 8) { // 12x4096
-          Ncp+=64; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_4096,prachF,prach2,1);
           // here we have |empty | Prach4096 |
           memmove(prach2+(4096<<1),prach2,(4096<<2));
@@ -688,8 +829,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
         }
       }
     } else { // three quarter sampling @ 92.16 Ms/s
-      Ncp = (Ncp*3);
-      prach2 = prach+(Ncp<<1);
+      Ncp = (Ncp*3); //to account for 92.16 Msps
+      prach2 = prach+(Ncp<<1); //times 2 for complex samples
       if (prach_sequence_length == 0){
         if (prach_fmt_id == 0) {
           idft(IDFT_73728,prachF,prach2,1);
@@ -724,20 +865,19 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           prach_len = (18432*4)+Ncp;
         }
       } else { // short sequence
-        if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
-          Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
+	if (use_extended_prach_prefix) 
+          Ncp+=48; // 16*kappa, kappa=3 for 92.16Msps 
+	prach2 = prach+(Ncp<<1); //times 2 for complex samples
+	if (prach_fmt_id == 4 || prach_fmt_id == 7 || prach_fmt_id == 9) {
           idft(IDFT_3072,prachF,prach2,1);
           // here we have |empty | Prach3072 |
           if (prach_fmt_id != 9) {
             memmove(prach2+(3072<<1),prach2,(3072<<2));
             prach_len = (3072*2)+Ncp;
           } else 	  prach_len = (3072*1)+Ncp;
-	       memmove(prach,prach+(3072<<1),(Ncp<<2));
-	       // here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) |
+	  memmove(prach,prach+(3072<<1),(Ncp<<2));
+	  // here we have |Prefix | Prach3072 | Prach3072 (if ! 0xc0) |
         } else if (prach_fmt_id == 6) { // 6x3072
-          Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_3072,prachF,prach2,1);
           // here we have |empty | Prach3072 |
           memmove(prach2+(3072<<1),prach2,(3072<<2));
@@ -750,8 +890,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach3072 |
           prach_len = (3072*6)+Ncp;
         } else if (prach_fmt_id == 5) { // 4x3072
-          Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_3072,prachF,prach2,1);
           // here we have |empty | Prach3072 |
           memmove(prach2+(3072<<1),prach2,(3072<<2));
@@ -762,8 +900,6 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
           // here we have |Prefix | Prach3072 |
           prach_len = (3072*4)+Ncp;
         } else if (prach_fmt_id == 6) { // 12x3072
-          Ncp+=48; // This assumes we are transmitting starting in symbol 0 of a PRACH slot, 30 kHz, full sampling
-          prach2 = prach+(Ncp<<1);
           idft(IDFT_3072,prachF,prach2,1);
           // here we have |empty | Prach3072 |
           memmove(prach2+(3072<<1),prach2,(3072<<2));
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
index 86e46402fdf04b46b0987ed6055f51c37cb4f355..c74d887101b8d57a4d46b025fd19c3a8e0972a4f 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -707,7 +707,8 @@ unsigned short nr_dlsch_extract_rbs_single(int **rxdataF,
                                         unsigned short nb_pdsch_rb,
                                         unsigned char nr_slot_rx,
                                         uint32_t high_speed_flag,
-                                        NR_DL_FRAME_PARMS *frame_parms);
+                                        NR_DL_FRAME_PARMS *frame_parms,
+                                        uint16_t dlDmrsSymbPos);
 
 /** \fn dlsch_extract_rbs_dual(int32_t **rxdataF,
     int32_t **dl_ch_estimates,
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
index a3e202d4fee38c262dafc023228a0d6aadd4eaaf..7d0febbb5a6aa0a958198736a1c8cf6fa57cb1f7 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
@@ -141,6 +141,8 @@ typedef struct {
   uint8_t decode_phich;
   // Encoder BG
   uint8_t BG;
+  // LDPC lifting size
+  uint32_t Z;
 } NR_UL_UE_HARQ_t;
 
 typedef struct {
@@ -316,6 +318,19 @@ typedef struct {
   uint8_t codeword;
   /// HARQ-ACKs
   NR_UE_HARQ_STATUS_t harq_ack;
+  /// PTRS Frequency Density
+  uint8_t PTRSFreqDensity;
+  /// PTRS Time Density
+  uint8_t PTRSTimeDensity;
+  uint8_t PTRSPortIndex ;
+  uint8_t nEpreRatioOfPDSCHToPTRS;
+  uint8_t PTRSReOffset;
+  /// bit mask of PT-RS ofdm symbol indicies
+  uint16_t ptrs_symbols;
+  // PTRS symbol index, to be updated every PTRS symbol within a slot.
+  uint8_t ptrs_symbol_index;
+  /// PDU BITMAP 
+  uint16_t pduBitmap;
 } NR_DL_UE_HARQ_t;
 
 typedef struct {
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
index fdd40feebaf4e0b3c39820a2fad086d20afaf583..d9bea8a3ac0b00bff35247c80930e482dc2fc731 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
@@ -227,8 +227,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
   NR_UL_UE_HARQ_t *harq_process; 
   uint16_t nb_rb ;
   uint32_t A, F;
-  static uint32_t Z = 0;
-  uint32_t *pz = &Z; 
+  uint32_t *pz; 
   uint8_t mod_order; 
   uint16_t Kr,r;
   uint32_t r_offset;
@@ -249,7 +248,7 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
   harq_process = ulsch->harq_processes[harq_pid];
   nb_rb = harq_process->pusch_pdu.rb_size;
   A = harq_process->pusch_pdu.pusch_data.tb_size*8;
-  pz = &Z;
+  pz = &harq_process->Z;
   mod_order = nr_get_Qm_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table);
   R = nr_get_code_rate_ul(harq_process->pusch_pdu.mcs_index, harq_process->pusch_pdu.mcs_table);
   Kr=0;
@@ -387,12 +386,13 @@ int nr_ulsch_encoding(NR_UE_ULSCH_t *ulsch,
       printf("%d \n",  harq_process->d[0][cnt]);
       }
       printf("\n");*/
-    encoder_implemparams_t impp;
-    impp.n_segments = harq_process->C;
-    impp.tinput     = NULL;
-    impp.tprep      = NULL;
-    impp.tparity    = NULL;
-    impp.toutput    = NULL;
+    encoder_implemparams_t impp = {
+      .n_segments=harq_process->C,
+      .macro_num=0,
+      .tinput  = NULL,
+      .tprep   = NULL,
+      .tparity = NULL,
+      .toutput = NULL};
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_LDPC_ENCODER_OPTIM, VCD_FUNCTION_IN);
 
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index b6ffd06c2ba9ee09881233f393e6110d3c31f368..cf5f74856ec6c29968b853d318f76c2b7954b8d6 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -112,6 +112,8 @@ typedef struct {
   uint32_t F;
   /// Encoder BG
   uint8_t BG;
+  /// LDPC lifting size
+  uint32_t Z;
 } NR_DL_gNB_HARQ_t;
 
 typedef struct {
@@ -467,7 +469,7 @@ typedef struct {
   /// bit mask of PT-RS ofdm symbol indicies
   uint16_t ptrs_symbols;
   // PTRS subcarriers per OFDM symbol
-  uint16_t ptrs_sc_per_ofdm_symbol;
+  int32_t ptrs_re_per_slot;
   /// \brief Estimated phase error based upon PTRS on each symbol .
   /// - first index: ? [0..7] Number of Antenna
   /// - second index: ? [0...14] smybol per slot
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index 8d31eb15f63a46305aa6245aaf7101e20f1acc7d..4a685bfeb9014b3b8dda4567060731daefa49b58 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -338,6 +338,10 @@ typedef struct {
   /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
   /// - second index: ? [0..168*N_RB_DL[
   int32_t **dl_ch_estimates_ext;
+  /// \brief Downlink channel estimates extracted in PRBS.
+  /// - first index: ? [0..7] (hard coded) FIXME! accessed via \c nb_antennas_rx
+  /// - second index: ? [0..168*N_RB_DL[
+  int32_t **dl_ch_ptrs_estimates_ext;
   /// \brief Downlink cross-correlation of MIMO channel estimates (unquantized PMI) extracted in PRBS. For the SIC receiver we need to store the history of this for each harq process and round
   /// - first index: ? [0..7] (hard coded) accessed via \c harq_pid
   /// - second index: ? [0..7] (hard coded) accessed via \c round
@@ -414,6 +418,16 @@ typedef struct {
   uint32_t llr_offset[14];
   // llr length per ofdm symbol
   uint32_t llr_length[14];
+  // llr offset per ofdm symbol
+  uint32_t dl_valid_re[14];
+  /// \brief Estimated phase error based upon PTRS on each symbol .
+  /// - first index: ? [0..7] Number of Antenna
+  /// - second index: ? [0...14] smybol per slot
+  int32_t **ptrs_phase_per_slot;
+  /// \brief Estimated phase error based upon PTRS on each symbol .
+  /// - first index: ? [0..7] Number of Antenna
+  /// - second index: ? [0...14] smybol per slot
+  int32_t **ptrs_re_per_slot;
 } NR_UE_PDSCH;
 
 #define NR_PDCCH_DEFS_NR_UE
@@ -889,7 +903,7 @@ typedef struct {
   uint32_t nr_gold_pbch[2][64][NR_PBCH_DMRS_LENGTH_DWORD];
 
   /// PDSCH DMRS
-  uint32_t nr_gold_pdsch[2][20][2][NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD];
+  uint32_t nr_gold_pdsch[2][20][14][NR_MAX_PDSCH_DMRS_INIT_LENGTH_DWORD];
 
   /// PDCCH DMRS
   uint32_t nr_gold_pdcch[7][20][3][52];
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index 4e6bc7497f943e80745dbf700ffdd39e955d603b..c600343ed019b9a8f29a0fa9423a796891d40dbd 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -108,9 +108,16 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
             dlsch0_harq->harq_ack.pucch_resource_indicator = dlsch_config_pdu->pucch_resource_id;
             dlsch0_harq->harq_ack.slot_for_feedback_ack = (slot+dlsch_config_pdu->pdsch_to_harq_feedback_time_ind)%frame_parms.slots_per_frame;
             dlsch0_harq->Nl=1;
-            dlsch0_harq->mcs_table=0;
+            dlsch0_harq->mcs_table=dlsch_config_pdu->mcs_table;
             dlsch0_harq->harq_ack.rx_status = downlink_harq_process(dlsch0_harq, dlsch0->current_harq_pid, dlsch_config_pdu->ndi, dlsch0->rnti_type);
             dlsch0_harq->harq_ack.vDAI_DL = dlsch_config_pdu->dai;
+            /* PTRS */
+            dlsch0_harq->PTRSFreqDensity = dlsch_config_pdu->PTRSFreqDensity;
+            dlsch0_harq->PTRSTimeDensity = dlsch_config_pdu->PTRSTimeDensity;
+            dlsch0_harq->PTRSPortIndex = dlsch_config_pdu->PTRSPortIndex;
+            dlsch0_harq->nEpreRatioOfPDSCHToPTRS = dlsch_config_pdu->nEpreRatioOfPDSCHToPTRS;
+            dlsch0_harq->PTRSReOffset = dlsch_config_pdu->PTRSReOffset;
+            dlsch0_harq->pduBitmap = dlsch_config_pdu->pduBitmap;
             LOG_D(MAC, ">>>> \tdlsch0->g_pucch = %d\tdlsch0_harq.mcs = %d\n", dlsch0->g_pucch, dlsch0_harq->mcs);
 		
           }
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index d2038cd1613980bd4e1cbd0fcf2bc71f6643a11b..bbe592b91450967499487b85a2b335b04e8a64e1 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -733,8 +733,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_
 
     LOG_D(PHY,"[UE %d] PDSCH type %d active in nr_slot_rx %d, harq_pid %d (%d), rb_start %d, nb_rb %d, symbol_start %d, nb_symbols %d, DMRS mask %x\n",ue->Mod_id,pdsch,nr_slot_rx,harq_pid,dlsch0->harq_processes[harq_pid]->status,pdsch_start_rb,pdsch_nb_rb,s0,s1,dlsch0->harq_processes[harq_pid]->dlDmrsSymbPos);
 
-    // do channel estimation for first DMRS only
-    for (m = s0; m < 3; m++) {
+    for (m = s0; m < (s0 +s1); m++) {
       if (((1<<m)&dlsch0->harq_processes[harq_pid]->dlDmrsSymbPos) > 0) {
         for (uint8_t aatx=0; aatx<1; aatx++) {//for MIMO Config: it shall loop over no_layers
           nr_pdsch_channel_estimation(ue,
@@ -752,12 +751,13 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB_
           char filename[100];
           for (uint8_t aarx=0; aarx<ue->frame_parms.nb_antennas_rx; aarx++) {
             sprintf(filename,"PDSCH_CHANNEL_frame%d_slot%d_sym%d_port%d_rx%d.m", nr_frame_rx, nr_slot_rx, m, aatx,aarx);
-            int **dl_ch_estimates = ue->pdsch_vars[ue->current_thread_id[nr_slot_rx]][0]->dl_ch_estimates;
+            int **dl_ch_estimates = ue->pdsch_vars[proc->thread_id][eNB_id]->dl_ch_estimates;
             LOG_M(filename,"channel_F",&dl_ch_estimates[aatx*ue->frame_parms.nb_antennas_rx+aarx][ue->frame_parms.ofdm_symbol_size*m],ue->frame_parms.ofdm_symbol_size, 1, 1);
           }
 #endif
         }
-        break;
+        if ( ue->high_speed_flag == 0 ) //for slow speed case only estimate the channel once per slot
+          break;
       }
     }
     for (m = s0; m < (s1 + s0); m++) {
@@ -930,7 +930,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
   uint8_t is_cw0_active = 0;
   uint8_t is_cw1_active = 0;
   uint8_t dmrs_type, nb_re_dmrs;
-  uint16_t length_dmrs = 1; 
+  uint16_t dmrs_len = get_num_dmrs(dlsch0->harq_processes[dlsch0->current_harq_pid]->dlDmrsSymbPos);
   uint16_t nb_symb_sch = 9;
   nr_downlink_indication_t dl_indication;
   fapi_nr_rx_indication_t rx_ind;
@@ -1016,7 +1016,7 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
     dlsch0->harq_processes[harq_pid]->G = nr_get_G(dlsch0->harq_processes[harq_pid]->nb_rb,
                                                    nb_symb_sch,
                                                    nb_re_dmrs,
-                                                   length_dmrs,
+                                                   dmrs_len,
                                                    dlsch0->harq_processes[harq_pid]->Qm,
                                                    dlsch0->harq_processes[harq_pid]->Nl);
 #if UE_TIMING_TRACE
@@ -1099,11 +1099,11 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
       if(is_cw1_active)
       {
           // start ldpc decode for CW 1
-          dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb,
-							 nb_symb_sch,
-							 nb_re_dmrs,
-							 length_dmrs,
-							 dlsch1->harq_processes[harq_pid]->Qm,
+        dlsch1->harq_processes[harq_pid]->G = nr_get_G(dlsch1->harq_processes[harq_pid]->nb_rb,
+                                                       nb_symb_sch,
+                                                       nb_re_dmrs,
+                                                       dmrs_len,
+                                                       dlsch1->harq_processes[harq_pid]->Qm,
 							 dlsch1->harq_processes[harq_pid]->Nl);
 #if UE_TIMING_TRACE
           start_meas(&ue->dlsch_unscrambling_stats);
@@ -1851,7 +1851,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
       for (int i=0;i<4;i++) if (((1<<i)&dlsch0_harq->dlDmrsSymbPos) > 0) {symb_dmrs=i;break;}
       AssertFatal(symb_dmrs>=0,"no dmrs in 0..3\n");
       LOG_D(PHY,"Initializing dmrs for symb %d DMRS mask %x\n",symb_dmrs,dlsch0_harq->dlDmrsSymbPos);
-      nr_gold_pdsch(ue,symb_dmrs,0, 1);
+      nr_gold_pdsch(ue,0);
     
       for (uint16_t m=start_symb_sch;m<(nb_symb_sch+start_symb_sch) ; m++){
         nr_slot_fep(ue,
@@ -2019,7 +2019,7 @@ start_meas(&ue->generic_stat);
 
   if(nr_slot_rx==5 &&  ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid]->nb_rb > 20){
        //write_output("decoder_llr.m","decllr",dlsch_llr,G,1,0);
-       //write_output("llr.m","llr",  &ue->pdsch_vars[gNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0);
+       //write_output("llr.m","llr",  &ue->pdsch_vars[proc->thread_id][gNB_id]->llr[0][0],(14*nb_rb*12*dlsch1_harq->Qm) - 4*(nb_rb*4*dlsch1_harq->Qm),1,0);
 
        write_output("rxdataF0_current.m"    , "rxdataF0", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1);
        //write_output("rxdataF0_previous.m"    , "rxdataF0_prev_sss", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1);
@@ -2027,10 +2027,10 @@ start_meas(&ue->generic_stat);
        //write_output("rxdataF0_previous.m"    , "rxdataF0_prev", &ue->common_vars.common_vars_rx_data_per_thread[next_thread_id].rxdataF[0][0],14*fp->ofdm_symbol_size,1,1);
 
        write_output("dl_ch_estimates.m", "dl_ch_estimates_sfn5", &ue->common_vars.common_vars_rx_data_per_thread[proc->thread_id].dl_ch_estimates[0][0][0],14*fp->ofdm_symbol_size,1,1);
-       write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[proc->thread_id][0]->dl_ch_estimates_ext[0][0],14*fp->N_RB_DL*12,1,1);
-       write_output("rxdataF_comp00.m","rxdataF_comp00",         &ue->pdsch_vars[proc->thread_id][0]->rxdataF_comp0[0][0],14*fp->N_RB_DL*12,1,1);
-       //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[proc->thread_id][0]->dl_ch_mag0[0][0],14*fp->N_RB_DL*12,1,1);
-       //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[proc->thread_id][0]->dl_ch_magb0[0][0],14*fp->N_RB_DL*12,1,1);
+       write_output("dl_ch_estimates_ext.m", "dl_ch_estimatesExt_sfn5", &ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_estimates_ext[0][0],14*fp->N_RB_DL*12,1,1);
+       write_output("rxdataF_comp00.m","rxdataF_comp00",         &ue->pdsch_vars[proc->thread_id][gNB_id]->rxdataF_comp0[0][0],14*fp->N_RB_DL*12,1,1);
+       //write_output("magDLFirst.m", "magDLFirst", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_mag0[0][0],14*fp->N_RB_DL*12,1,1);
+       //write_output("magDLSecond.m", "magDLSecond", &phy_vars_ue->pdsch_vars[proc->thread_id][gNB_id]->dl_ch_magb0[0][0],14*fp->N_RB_DL*12,1,1);
 
        AssertFatal (0,"");
   }
diff --git a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c
index 9a19aef98556fb667e8b7a5352a7d34054dfdb5b..6b1e9f62de2f006c89d1a4af8dc2ca406096544b 100644
--- a/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c
+++ b/openair1/SCHED_NR_UE/pucch_uci_ue_nr.c
@@ -1008,6 +1008,12 @@ boolean_t select_pucch_resource(PHY_VARS_NR_UE *ue, NR_UE_MAC_INST_t *mac, uint8
 
     if (resource_set_found == TRUE) {
       if (pucch_resource_indicator < MAX_PUCCH_RESOURCE_INDICATOR) {
+        // Verify that the value of pucch_resource_indicator is valid
+        if (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.count <= pucch_resource_indicator)
+        {
+          LOG_E(PHY, "Value of pucch_resource_indicator is out of bounds! Possibly due to a false DCI. \n");
+          return (FALSE);
+        }
         /* check if resource indexing by pucch_resource_indicator of this set is compatible */
         if ((ready_pucch_resource_id == TRUE) || (mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[pucch_resource_set_id]->resourceList.list.array[pucch_resource_indicator][0] != MAX_NB_OF_PUCCH_RESOURCES)) {
 
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 2ca8dae2793b7e400a88f670fc95b13627cd9493..2bd70021f7a4fd7ec99c821ae1804670c8f8a879 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -61,7 +61,7 @@
 #include "openair1/SIMULATION/TOOLS/sim.h"
 #include "openair1/SIMULATION/NR_PHY/nr_unitary_defs.h"
 //#include "openair1/SIMULATION/NR_PHY/nr_dummy_functions.c"
-
+#include "PHY/NR_REFSIG/ptrs_nr.h"
 #include "NR_RRCReconfiguration.h"
 #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
 #include "SIMULATION/LTE_PHY/common_sim.h"
@@ -148,7 +148,8 @@ int is_x2ap_enabled(void)
 
 // needed for some functions
 openair0_config_t openair0_cfg[MAX_CARDS];
-
+void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex,int8_t *ptrs_arg);
+void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg);
 
 /* specific dlsim DL preprocessor: uses rbStart/rbSize/mcs from command line of
    dlsim, does not search for CCE/PUCCH occasion but simply sets to 0 */
@@ -255,6 +256,19 @@ int main(int argc, char **argv)
   int css_flag=0;
 
   cpuf = get_cpu_freq_GHz();
+  int8_t enable_ptrs = 0;
+  int8_t modify_dmrs = 0;
+
+  int8_t dmrs_arg[2] = {-1,-1};// Invalid values
+  /* L_PTRS = ptrs_arg[0], K_PTRS = ptrs_arg[1] */
+  int8_t ptrs_arg[2] = {-1,-1};// Invalid values
+
+  uint16_t ptrsRePerSymb = 0;
+  uint16_t pdu_bit_map = 0x0;
+  uint16_t dlPtrsSymPos = 0;
+  uint16_t ptrsSymbPerSlot = 0;
+  uint16_t rbSize = 106;
+  uint8_t  mcsIndex = 9;
 
   if ( load_configmodule(argc,argv,CONFIG_ENABLECMDLINEONLY) == 0) {
     exit_fun("[NR_DLSIM] Error, configuration module init failed\n");
@@ -266,7 +280,7 @@ int main(int argc, char **argv)
 
   FILE *scg_fd=NULL;
   
-  while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:w")) != -1) {
+  while ((c = getopt (argc, argv, "f:hA:pf:g:i:j:n:s:S:t:x:y:z:M:N:F:GR:dPIL:Ea:b:e:m:w:T:U:")) != -1) {
     switch (c) {
     case 'f':
       scg_fd = fopen(optarg,"r");
@@ -450,6 +464,20 @@ int main(int argc, char **argv)
       output_fd = fopen("txdata.dat", "w+");
       break;
 
+    case 'T':
+      enable_ptrs=1;
+      for(i=0; i < atoi(optarg); i++) {
+        ptrs_arg[i] = atoi(argv[optind++]);
+      }
+      break;
+
+    case 'U':
+      modify_dmrs = 1;
+      for(i=0; i < atoi(optarg); i++) {
+        dmrs_arg[i] = atoi(argv[optind++]);
+      }
+      break;
+
     default:
     case 'h':
       printf("%s -h(elp) -p(extended_prefix) -N cell_id -f output_filename -F input_filename -g channel_model -n n_frames -t Delayspread -s snr0 -S snr1 -x transmission_mode -y TXant -z RXant -i Intefrence0 -j Interference1 -A interpolation_file -C(alibration offset dB) -N CellId\n",
@@ -480,6 +508,8 @@ int main(int argc, char **argv)
       printf("-j Number of symbols for PDSCH (fixed for now)\n");
       printf("-e MSC index\n");
       printf("-t Acceptable effective throughput (in percentage)\n");
+      printf("-T Enable PTRS, arguments list L_PTRS{0,1,2} K_PTRS{2,4}, e.g. -T 2 0 2 \n");
+      printf("-U Change DMRS Config, arguments list DMRS TYPE{0=A,1=B} DMRS AddPos{0:2}, e.g. -U 2 0 2 \n");
       printf("-P Print DLSCH performances\n");
       printf("-w Write txdata to binary file (one frame)\n");
       exit (-1);
@@ -490,6 +520,8 @@ int main(int argc, char **argv)
   logInit();
   set_glog(loglvl);
   T_stdout = 1;
+  /* initialize the sin table */
+  InitSinLUT();
 
   get_softmodem_params()->phy_test = 1;
   
@@ -578,7 +610,17 @@ int main(int argc, char **argv)
 				  n_tx,
 				  0);
 
-  xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
+  /* -U option modify DMRS */
+  if(modify_dmrs) {
+    update_dmrs_config(secondaryCellGroup, NULL,dmrs_arg);
+  }
+  /* -T option enable PTRS */
+  if(enable_ptrs) {
+    update_ptrs_config(secondaryCellGroup, &rbSize, &mcsIndex, ptrs_arg);
+  }
+
+
+  //xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
 
   AssertFatal((gNB->if_inst         = NR_IF_Module_init(0))!=NULL,"Cannot register interface");
   gNB->if_inst->NR_PHY_config_req      = nr_phy_config_request;
@@ -693,6 +735,9 @@ int main(int argc, char **argv)
     exit(-1);
   }
 
+  if(modify_dmrs) {
+    update_dmrs_config( NULL,UE,dmrs_arg);
+  }
   init_nr_ue_transport(UE,0);
 
   nr_gold_pbch(UE);
@@ -837,7 +882,22 @@ int main(int argc, char **argv)
         Sched_INFO.UL_dci_req  = NULL;
         Sched_INFO.TX_req    = &gNB_mac->TX_req[0];
         nr_schedule_response(&Sched_INFO);
-        
+
+        /* PTRS values for DLSIM calculations   */
+        nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[Sched_INFO.CC_id].dl_tti_request_body;
+        nfapi_nr_dl_tti_request_pdu_t  *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[1];
+        nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
+        pdu_bit_map = pdsch_pdu_rel15->pduBitmap;
+        if(pdu_bit_map & 0x1) {
+          set_ptrs_symb_idx(&dlPtrsSymPos,
+                            pdsch_pdu_rel15->NrOfSymbols,
+                            pdsch_pdu_rel15->StartSymbolIndex,
+                            1<<pdsch_pdu_rel15->PTRSTimeDensity,
+                            pdsch_pdu_rel15->dlDmrsSymbPos);
+          ptrsSymbPerSlot = get_ptrs_symbols_in_slot(dlPtrsSymPos, pdsch_pdu_rel15->StartSymbolIndex, pdsch_pdu_rel15->NrOfSymbols);
+          ptrsRePerSymb = ((rel15->rbSize + rel15->PTRSFreqDensity - 1)/rel15->PTRSFreqDensity);
+          printf("[DLSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
+        }
         if (run_initial_sync)
           nr_common_signal_procedures(gNB,frame,slot);
         else
@@ -894,7 +954,7 @@ int main(int argc, char **argv)
             r_im[aa][i] = ((double)(((short *)txdata[aa]))[(i<<1)+1]);
           }
         }
-        
+        double ts = 1.0/(frame_parms->subcarrier_spacing * frame_parms->ofdm_symbol_size); 
         //AWGN
         sigma2_dB = 10 * log10((double)txlev * ((double)UE->frame_parms.ofdm_symbol_size/(12*rel15->rbSize))) - SNR;
         sigma2    = pow(10, sigma2_dB/10);
@@ -907,6 +967,11 @@ int main(int argc, char **argv)
           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)));
             ((short*) UE->common_vars.rxdata[aa])[2*i+1] = (short) ((r_im[aa][i] + sqrt(sigma2/2)*gaussdouble(0.0,1.0)));
+            /* Add phase noise if enabled */
+            if (pdu_bit_map & 0x1) {
+              phase_noise(ts, &((short*) UE->common_vars.rxdata[aa])[2*i],
+                          &((short*) UE->common_vars.rxdata[aa])[2*i+1]);
+            }
           }
         }
         
@@ -934,13 +999,17 @@ int main(int argc, char **argv)
       int16_t *UE_llr = pdsch_vars[0]->llr[0];
 
       TBS                  = UE_harq_process->TBS;//rel15->TBSize[0];
-      uint16_t length_dmrs = 1;
+      uint16_t length_dmrs = get_num_dmrs(rel15->dlDmrsSymbPos);
       uint16_t nb_rb       = rel15->rbSize;
       uint8_t  nb_re_dmrs  = rel15->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4;
       uint8_t  mod_order   = rel15->qamModOrder[0];
       uint8_t  nb_symb_sch = rel15->NrOfSymbols;
 
       available_bits = nr_get_G(nb_rb, nb_symb_sch, nb_re_dmrs, length_dmrs, mod_order, rel15->nrOfLayers);
+      if(pdu_bit_map & 0x1) {
+        available_bits-= (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2);
+        printf("[DLSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5u \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb *rel15->nrOfLayers* 2) );
+      }
       
       for (i = 0; i < available_bits; i++) {
 	
@@ -992,7 +1061,7 @@ int main(int argc, char **argv)
     printf("*****************************************\n");
     printf("\n");
     dump_pdsch_stats(gNB);
-    printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %d bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS);
+    printf("SNR %f : n_errors (negative CRC) = %d/%d, Avg round %.2f, Channel BER %e, Eff Rate %.4f bits/slot, Eff Throughput %.2f, TBS %u bits/slot\n", SNR, n_errors, n_trials,roundStats[snrRun],(double)errors_scrambling/available_bits/n_trials,effRate,effRate/TBS*100,TBS);
     printf("\n");
 
     if (print_perf==1) {
@@ -1102,3 +1171,79 @@ int main(int argc, char **argv)
   return(n_errors);
   
 }
+
+
+void update_ptrs_config(NR_CellGroupConfig_t *secondaryCellGroup, uint16_t *rbSize, uint8_t *mcsIndex, int8_t *ptrs_arg)
+{
+  NR_BWP_Downlink_t *bwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
+  int *ptrsFreqDenst = calloc(2, sizeof(long));
+  ptrsFreqDenst[0]= 25;
+  ptrsFreqDenst[1]= 115;
+  int *ptrsTimeDenst = calloc(3, sizeof(long));
+  ptrsTimeDenst[0]= 2;
+  ptrsTimeDenst[1]= 4;
+  ptrsTimeDenst[2]= 10;
+
+  int epre_Ratio = 0;
+  int reOffset = 0;
+
+  if(ptrs_arg[0] ==0) {
+    ptrsTimeDenst[2]= *mcsIndex -1;
+  }
+  else if(ptrs_arg[0] == 1) {
+    ptrsTimeDenst[1]= *mcsIndex - 1;
+    ptrsTimeDenst[2]= *mcsIndex + 1;
+  }
+  else if(ptrs_arg[0] ==2) {
+    ptrsTimeDenst[0]= *mcsIndex - 1;
+    ptrsTimeDenst[1]= *mcsIndex + 1;
+  }
+  else {
+    printf("[DLSIM] Wrong L_PTRS value, using default values 1\n");
+  }
+  /* L = 4 if Imcs < MCS4 */
+  if(ptrs_arg[1] ==2) {
+    ptrsFreqDenst[0]= *rbSize - 1;
+    ptrsFreqDenst[1]= *rbSize + 1;
+  }
+  else if(ptrs_arg[1] == 4) {
+    ptrsFreqDenst[1]= *rbSize - 1;
+  }
+  else {
+    printf("[DLSIM] Wrong K_PTRS value, using default values 2\n");
+  }
+  printf("[DLSIM] PTRS Enabled with L %d, K %d \n", 1<<ptrs_arg[0], ptrs_arg[1] );
+  /* overwrite the values */
+  rrc_config_dl_ptrs_params(bwp, ptrsFreqDenst, ptrsTimeDenst, &epre_Ratio, &reOffset);
+}
+
+void update_dmrs_config(NR_CellGroupConfig_t *scg,PHY_VARS_NR_UE *ue, int8_t* dmrs_arg)
+{
+  int8_t  mapping_type = typeA;//default value
+  int8_t  add_pos = pdsch_dmrs_pos0;//default value
+  if(dmrs_arg[0] == 0) {
+    mapping_type = typeA;
+  }
+  else if (dmrs_arg[0] == 1) {
+    mapping_type = typeB;
+  }
+  /* Additional DMRS positions 0 ,1 and 2 */
+  if(dmrs_arg[1] >= 0 && dmrs_arg[1] <3 ) {
+    add_pos = dmrs_arg[1];
+  }
+
+  if(scg != NULL) {
+    NR_BWP_Downlink_t *bwp = scg->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[0];
+    *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = add_pos;
+    for (int i=0;i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count;i++) {
+      bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->mappingType = mapping_type; 
+    }
+  }
+  if(ue != NULL) {
+    for (int i=0;i<MAX_NR_OF_DL_ALLOCATIONS;i++) {
+      ue->PDSCH_Config.pdsch_TimeDomainResourceAllocation[i]->mappingType = mapping_type;
+    }
+    ue->dmrs_DownlinkConfig.pdsch_dmrs_AdditionalPosition = add_pos;
+  }
+  printf("[DLSIM] DMRS Config is modified with Mapping Type %d, Additional Positions %d \n", dmrs_arg[0], dmrs_arg[1] );
+}
diff --git a/openair1/SIMULATION/NR_PHY/prachsim.c b/openair1/SIMULATION/NR_PHY/prachsim.c
index 0cc7e9f08ae03c4df7e6facd8864146a4bd6dc8a..1f4db3138acf7cb637844eb90b2af436343330d4 100644
--- a/openair1/SIMULATION/NR_PHY/prachsim.c
+++ b/openair1/SIMULATION/NR_PHY/prachsim.c
@@ -116,10 +116,10 @@ int main(int argc, char **argv){
   int i, aa, aarx, **txdata, trial, n_frames = 1, prach_start, rx_prach_start; //, ntrials=1;
   int N_RB_UL = 106, delay = 0, NCS_config = 13, rootSequenceIndex = 1, threequarter_fs = 0, mu = 1, fd_occasion = 0, loglvl = OAILOG_INFO, numRA = 0, prachStartSymbol = 0;
   uint8_t snr1set = 0, ue_speed1set = 0, transmission_mode = 1, n_tx = 1, n_rx = 1, awgn_flag = 0, msg1_frequencystart = 0, num_prach_fd_occasions = 1, prach_format=0;
-  uint8_t frame = 1, subframe = 9, slot=19, slot_gNB=19, config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol;
+  uint8_t frame = 1, slot=19, slot_gNB=19, config_index = 98, prach_sequence_length = 1, restrictedSetConfig = 0, N_dur, N_t_slot, start_symbol;
   uint16_t Nid_cell = 0, preamble_tx = 0, preamble_delay, format, format0, format1;
   uint32_t tx_lev = 10000, prach_errors = 0; //,tx_lev_dB;
-  uint64_t SSB_positions = 0x01, absoluteFrequencyPointA = 640000;
+  uint64_t SSB_positions = 0x01;
   uint16_t RA_sfn_index;
   uint8_t N_RA_slot;
   uint8_t config_period;
@@ -153,7 +153,7 @@ int main(int argc, char **argv){
 
   randominit(0);
 
-  while ((c = getopt (argc, argv, "hHaA:Cc:r:p:g:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) {
+  while ((c = getopt (argc, argv, "hHaA:Cc:r:p:g:m:n:s:S:t:x:y:v:V:z:N:F:d:Z:L:R:E")) != -1) {
     switch (c) {
     case 'a':
       printf("Running AWGN simulation\n");
@@ -243,6 +243,10 @@ int main(int argc, char **argv){
       threequarter_fs=1;
       break;
 
+    case 'm':
+      mu = atoi(optarg);
+      break;
+
     case 'n':
       n_frames = atoi(optarg);
       break;
@@ -370,13 +374,6 @@ int main(int argc, char **argv){
     }
   }
 
-  
-  if (config_index<67)  { prach_sequence_length=0; slot = subframe*2; slot_gNB = 1+(subframe*2); }
-  uint16_t N_ZC;
-  N_ZC = prach_sequence_length == 0 ? 839 : 139;
-
-  printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length);
-
   // Configure log
   logInit();
   set_glog(loglvl);
@@ -411,12 +408,20 @@ int main(int argc, char **argv){
   frame_parms->N_RB_UL          = N_RB_UL;
   frame_parms->threequarter_fs  = threequarter_fs;
   frame_parms->frame_type       = TDD;
-  frame_parms->freq_range       = nr_FR1;
+  frame_parms->freq_range       = (mu==1 ? nr_FR1 : nr_FR2);
   frame_parms->numerology_index = mu;
 
   nr_phy_config_request_sim(gNB, N_RB_UL, N_RB_UL, mu, Nid_cell, SSB_positions);
 
-  //nsymb = (frame_parms->Ncp == 0) ? 14 : 12;
+  uint64_t absoluteFrequencyPointA = (mu==1 ? 640000 : 2070833);
+
+  uint8_t subframe = slot/frame_parms->slots_per_subframe;
+  
+  if (config_index<67 && mu==1)  { prach_sequence_length=0; slot = subframe*2; slot_gNB = 1+(subframe*2); }
+  uint16_t N_ZC = prach_sequence_length == 0 ? 839 : 139;
+
+  printf("Config_index %d, prach_sequence_length %d\n",config_index,prach_sequence_length);
+
 
   printf("FFT Size %d, Extended Prefix %d, Samples per subframe %d, Frame type %s, Frequency Range %s\n",
          NUMBER_OF_OFDM_CARRIERS,
@@ -432,7 +437,14 @@ int main(int argc, char **argv){
 
   gNB->gNB_config.carrier_config.num_tx_ant.value = 1;
   gNB->gNB_config.carrier_config.num_rx_ant.value = 1;
-  gNB->gNB_config.tdd_table.tdd_period.value = 6;
+  if (mu==1)
+    gNB->gNB_config.tdd_table.tdd_period.value = 6;
+  else if (mu==3)
+    gNB->gNB_config.tdd_table.tdd_period.value = 3;
+  else {
+    printf("unsupported numerology %d\n",mu);
+    exit(-1);
+  }
 
   gNB->gNB_config.prach_config.num_prach_fd_occasions.value = num_prach_fd_occasions;
   gNB->gNB_config.prach_config.num_prach_fd_occasions_list = (nfapi_nr_num_prach_fd_occasions_t *) malloc(num_prach_fd_occasions*sizeof(nfapi_nr_num_prach_fd_occasions_t));
@@ -752,7 +764,7 @@ int main(int argc, char **argv){
             LOG_M("prachF0.m","prachF0", &gNB->prach_vars.prachF[0], N_ZC, 1, 1);
             LOG_M("rxsig0.m","rxs0", &gNB->common_vars.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
             LOG_M("ru_rxsig0.m","rxs0", &ru->common.rxdata[0][subframe*frame_parms->samples_per_subframe], frame_parms->samples_per_subframe, 1, 1);
-            LOG_M("rxsigF0.m","rxsF0", gNB->prach_vars.rxsigF[0], N_ZC, 1, 1);
+            LOG_M("ru_rxsigF0.m","rxsF0", ru->prach_rxsigF[0][0], N_ZC, 1, 1);
             LOG_M("prach_preamble.m","prachp", &gNB->X_u[0], N_ZC, 1, 1);
             LOG_M("ue_prach_preamble.m","prachp", &UE->X_u[0], N_ZC, 1, 1);
           #endif
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index 19b107a80a1e6bd7486e60fc13b4e13c645f39cb..821ac75a648ba92b5b011152f0d4728bc268f2b2 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -56,7 +56,7 @@
 #include "openair2/LAYER2/NR_MAC_UE/mac_proto.h"
 #include "openair2/LAYER2/NR_MAC_gNB/mac_proto.h"
 #include "common/utils/threadPool/thread-pool.h"
-
+#include "PHY/NR_REFSIG/ptrs_nr.h"
 #define inMicroS(a) (((double)(a))/(cpu_freq_GHz*1000.0))
 #include "SIMULATION/LTE_PHY/common_sim.h"
 
@@ -163,8 +163,7 @@ int main(int argc, char **argv)
   FILE *input_fd = NULL;
   SCM_t channel_model = AWGN;  //Rayleigh1_anticorr;
   uint16_t N_RB_DL = 106, N_RB_UL = 106, mu = 1;
-  double tx_gain=1.0;
-  double N0=30;
+
   NB_UE_INST = 1;
 
   //unsigned char frame_type = 0;
@@ -179,7 +178,6 @@ int main(int argc, char **argv)
   int gNB_id = 0;
   int ap;
   int tx_offset;
-  double txlev_float;
   int32_t txlev;
   int start_rb = 0;
   int UE_id =0; // [hna] only works for UE_id = 0 because NUMBER_OF_NR_UE_MAX is set to 1 (phy_init_nr_gNB causes segmentation fault)
@@ -199,6 +197,9 @@ int main(int argc, char **argv)
   int ptrs_arg[2] = {-1,-1};// Invalid values
   /* DMRS TYPE = dmrs_arg[0], Add Pos = dmrs_arg[1] */
   int dmrs_arg[2] = {-1,-1};// Invalid values
+  uint16_t ptrsSymPos = 0;
+  uint16_t ptrsSymbPerSlot = 0;
+  uint16_t ptrsRePerSymb = 0;
 
   UE_nr_rxtx_proc_t UE_proc;
   FILE *scg_fd=NULL;
@@ -217,6 +218,9 @@ int main(int argc, char **argv)
   //logInit();
   randominit(0);
 
+  /* initialize the sin-cos table */
+   InitSinLUT();
+
   while ((c = getopt(argc, argv, "a:b:c:d:ef:g:h:i:j:kl:m:n:p:r:s:y:z:F:G:H:M:N:PR:S:T:U:L:")) != -1) {
     printf("handling optarg %c\n",c);
     switch (c) {
@@ -950,8 +954,6 @@ int main(int argc, char **argv)
       nr_fill_ulsch(gNB,frame,slot,pusch_pdu);
 
       for (int i=0;i<(TBS/8);i++) ulsch_ue[0]->harq_processes[harq_pid]->a[i]=i&0xff;
-      double scale = 1;
-
       if (input_fd == NULL) {
 
 	  // set FAPI parameters for UE, put them in the scheduled response and call
@@ -974,20 +976,16 @@ int main(int argc, char **argv)
 	  
 	  txlev = signal_energy(&UE->common_vars.txdata[0][tx_offset + 5*frame_parms->ofdm_symbol_size + 4*frame_parms->nb_prefix_samples + frame_parms->nb_prefix_samples0],
 				frame_parms->ofdm_symbol_size + frame_parms->nb_prefix_samples);
-	  
-	  txlev_float = (double)txlev/scale; // output of signal_energy is fixed point representation
-	  
-	  
       }	
       else n_trials = 1;
 
       if (input_fd == NULL ) {
 
-	sigma_dB = N0;
+	sigma_dB = 10 * log10((double)txlev * ((double)frame_parms->ofdm_symbol_size/(12*nb_rb))) - SNR;;
 	sigma    = pow(10,sigma_dB/10);
 
-	tx_gain = sqrt(pow(10.0,.1*(N0+SNR))/txlev_float);
-	if(n_trials==1) printf("txlev_float %f, sigma_dB %f, tx_gain %f tx_offset %d, slot_offset %d\n",10*log10(txlev_float),sigma_dB,tx_gain,tx_offset,slot_offset);
+
+	if(n_trials==1) printf("sigma %f (%f dB), txlev %f (factor %f)\n",sigma,sigma_dB,10*log10((double)txlev),(double)(double)frame_parms->ofdm_symbol_size/(12*nb_rb));
 
 	for (i=0; i<slot_length; i++) {
 	  for (int aa=0; aa<1; aa++) {
@@ -1006,8 +1004,8 @@ int main(int argc, char **argv)
 	}
 	for (i=0; i<slot_length; i++) {
 	  for (ap=0; ap<frame_parms->nb_antennas_rx; ap++) {
-	    ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)]   = (int16_t)((tx_gain*r_re[ap][i])   + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point
-	    ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)]   = (int16_t)((tx_gain*r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0)));
+	    ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i) + (delay*2)]   = (int16_t)((r_re[ap][i])   + (sqrt(sigma/2)*gaussdouble(0.0,1.0))); // convert to fixed point
+	    ((int16_t*) &gNB->common_vars.rxdata[ap][slot_offset])[(2*i)+1 + (delay*2)]   = (int16_t)((r_im[ap][i]) + (sqrt(sigma/2)*gaussdouble(0.0,1.0)));
             /* Add phase noise if enabled */
             if (pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
               phase_noise(ts, &((int16_t*)&gNB->common_vars.rxdata[ap][slot_offset])[(2*i)],
@@ -1018,6 +1016,17 @@ int main(int argc, char **argv)
 
       }
 
+
+      if(pusch_pdu->pdu_bit_map & PUSCH_PDU_BITMAP_PUSCH_PTRS) {
+        set_ptrs_symb_idx(&ptrsSymPos,
+                          pusch_pdu->nr_of_symbols,
+                          pusch_pdu->start_symbol_index,
+                          1<<ptrs_time_density,
+                          pusch_pdu->ul_dmrs_symb_pos);
+        ptrsSymbPerSlot = get_ptrs_symbols_in_slot(ptrsSymPos, pusch_pdu->start_symbol_index, pusch_pdu->nr_of_symbols);
+        ptrsRePerSymb = ((pusch_pdu->rb_size + ptrs_freq_density - 1)/ptrs_freq_density);
+        printf("[ULSIM] PTRS Symbols in a slot: %2u, RE per Symbol: %3u, RE in a slot %4d\n", ptrsSymbPerSlot,ptrsRePerSymb, ptrsSymbPerSlot*ptrsRePerSymb );
+      }
 	////////////////////////////////////////////////////////////
 	
 	//----------------------------------------------------------
@@ -1082,7 +1091,7 @@ int main(int argc, char **argv)
             }
             /*  2*5*(50/2), for RB = 50,K = 2 for 5 OFDM PTRS symbols */
             available_bits -= 2 * ptrs_symbols * ((nb_rb + ptrs_freq_density - 1) /ptrs_freq_density);
-            printf("After PTRS subtraction available_bits are : %u \n", available_bits);
+            printf("[ULSIM][PTRS] Available bits are: %5u, removed PTRS bits are: %5d \n",available_bits, (ptrsSymbPerSlot * ptrsRePerSymb * 2) );
         }
 
 	for (i = 0; i < available_bits; i++) {
diff --git a/openair1/SIMULATION/TOOLS/phase_noise.c b/openair1/SIMULATION/TOOLS/phase_noise.c
index f243a09c59ee1912a31c5609554f0de682ced6cb..5958a0ccdd566ba032021baa9182fb394db6daf1 100644
--- a/openair1/SIMULATION/TOOLS/phase_noise.c
+++ b/openair1/SIMULATION/TOOLS/phase_noise.c
@@ -29,14 +29,43 @@
 /* linear phase noise model */
 void phase_noise(double ts, int16_t * InRe, int16_t * InIm)
 {
+  static uint64_t i=0;
+  int32_t x=0 ,y=0;
   double fd = 300;//0.01*30000
-  static double i=0;
-  double real, imag,x ,y;
+  int16_t SinValue = 0, CosValue= 0;
+  double IdxDouble = (double)(i*fd * ts * ResolSinCos * 4);
+  int16_t IdxModulo = ((int32_t)(IdxDouble>0 ? IdxDouble+0.5 : IdxDouble-0.5)) % (ResolSinCos*4);
+  IdxModulo = IdxModulo<0 ? IdxModulo+ResolSinCos*4 : IdxModulo;
+
+  if(IdxModulo<2*ResolSinCos) {//< 2 check for 1st and 2nd
+    if(IdxModulo < ResolSinCos) {// 1st Quadrant
+      SinValue = LUTSin[IdxModulo];
+      CosValue = LUTSin[ResolSinCos-IdxModulo];
+    }
+    else {// 2nd Quadrant
+      SinValue = LUTSin[2*ResolSinCos-IdxModulo];
+      CosValue = -LUTSin[IdxModulo-ResolSinCos];
+    }
+  }
+  else {// 3rd and 4th Quadrant
+    if(IdxModulo < 3*ResolSinCos) {// 3rd Quadrant
+      SinValue = -LUTSin[IdxModulo-2*ResolSinCos];
+      CosValue = -LUTSin[3*ResolSinCos-IdxModulo];
+    }
+    else {//4th Quadrant
+      SinValue = -LUTSin[4*ResolSinCos-IdxModulo];
+      CosValue = LUTSin[IdxModulo-3*ResolSinCos];
+    }
+  }
+  x = ( ((int32_t)InRe[0] * CosValue) - ((int32_t)InIm[0] * SinValue ));
+  y = ( ((int32_t)InIm[0] * CosValue) + ((int32_t)InRe[0] * SinValue ));
+  InRe[0]= (int16_t)(x>>14);
+  InIm[0]= (int16_t)(y>>14);
   i++;
-  real = cos(fd * 2 * M_PI * i * ts);
-  imag = sin (fd * 2 * M_PI * i * ts);
-  x = ((real * (double)InRe[0]) - (imag * (double)InIm[0])) ;
-  y= ((real * (double)InIm[0]) + (imag * (double)InRe[0])) ;
-  InRe[0]= (int16_t)(x);
-  InIm[0]= (int16_t)(y);
+}
+/* Initialisation function for SIN table values */
+void InitSinLUT( void ) {
+  for ( int i=0; i<(ResolSinCos+1); i++ ) {
+    LUTSin[i] = sin((double)(M_PI*i)/(2*ResolSinCos)) * (1<<14); //Format: Q14
+  }
 }
diff --git a/openair1/SIMULATION/TOOLS/sim.h b/openair1/SIMULATION/TOOLS/sim.h
index d2684b15c1fd0602e553e9f9dc5d4d0355003a01..55a78e977866ec9ed63a1a73c4e47c4c597352f6 100644
--- a/openair1/SIMULATION/TOOLS/sim.h
+++ b/openair1/SIMULATION/TOOLS/sim.h
@@ -466,6 +466,10 @@ double N_RB2channel_bandwidth(uint16_t N_RB);
   \param ts Sampling time 
   \param *Re *Im Real and Imag part of the signal
 */
+//look-up table for the sine (cosine) function
+#define ResolSinCos 100
+uint16_t LUTSin[ResolSinCos+1];
+void InitSinLUT( void );
 void phase_noise(double ts, int16_t * InRe, int16_t * InIm);
 
 #include "targets/RT/USER/rfsim.h"
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index 9a5946498dbabf6a527b3fec56cd76f3c88423ce..cc6b1b9de3aa77904b8d9cdaec5b742adbc05fb2 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -1879,7 +1879,8 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
   }
   uint8_t N_sh_symb = pdsch_rel15->NrOfSymbols;
   uint8_t Imcs = pdsch_rel15->mcsIndex[0];
-  uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS - N_PRB_oh;
+  uint16_t dmrs_length = get_num_dmrs(pdsch_rel15->dlDmrsSymbPos);
+  uint16_t N_RE_prime = NR_NB_SC_PER_RB*N_sh_symb - N_PRB_DMRS*dmrs_length - N_PRB_oh;
   LOG_D(MAC, "N_RE_prime %d for %d symbols %d DMRS per PRB and %d overhead\n", N_RE_prime, N_sh_symb, N_PRB_DMRS, N_PRB_oh);
 
   uint16_t R;
@@ -1896,10 +1897,10 @@ void nr_get_tbs_dl(nfapi_nr_dl_tti_pdsch_pdu *pdsch_pdu,
 
   TBS = nr_compute_tbs(Qm,
                        R,
-		       pdsch_rel15->rbSize,
-		       N_sh_symb,
-		       N_PRB_DMRS, // FIXME // This should be multiplied by the number of dmrs symbols
-		       N_PRB_oh,
+                       pdsch_rel15->rbSize,
+                       N_sh_symb,
+                       N_PRB_DMRS*dmrs_length,
+                       N_PRB_oh,
                        tb_scaling,
 		       pdsch_rel15->nrOfLayers)>>3;
 
@@ -2784,6 +2785,8 @@ int16_t fill_dmrs_mask(NR_PDSCH_Config_t *pdsch_Config,int dmrs_TypeA_Position,i
 	if (NrOfSymbols < 13 && *dmrs_config->dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<<l0 | 1<<8);
 	if (*dmrs_config->dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<<l0);
 	if (*dmrs_config->dmrs_AdditionalPosition!=NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) return(1<<l0 | 1<<10);
+        if (*dmrs_config->dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos0) return(1<<l0);
+	if (*dmrs_config->dmrs_AdditionalPosition==NR_DMRS_DownlinkConfig__dmrs_AdditionalPosition_pos1) return(1<<l0 | 1<<10);
       }
     }
     else if (pdsch_Config->dmrs_DownlinkForPDSCH_MappingTypeB &&
@@ -2846,3 +2849,72 @@ int binomial(int n, int k) {
   return c;
 }
 
+/* extract PTRS values from RC and validate it based upon 38.214 5.1.6.3 */
+bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
+                        uint16_t rbSize,uint8_t mcsIndex, uint8_t mcsTable,
+                        uint8_t *K_ptrs, uint8_t *L_ptrs,
+                        uint8_t *portIndex,uint8_t *nERatio, uint8_t *reOffset,
+                        uint8_t NrOfSymbols)
+{
+  bool valid = true;
+
+  /* as defined in T 38.214 5.1.6.3 */
+  if(rbSize < 3) {
+    valid = false;
+    return valid;
+  }
+  /* Check for Frequency Density values */
+  if(ptrs_config->frequencyDensity->list.count < 2) {
+    /* Default value for K_PTRS = 2 as defined in T 38.214 5.1.6.3 */
+    *K_ptrs = 2;
+  }
+  else {
+    *K_ptrs = get_K_ptrs(*ptrs_config->frequencyDensity->list.array[0],
+                         *ptrs_config->frequencyDensity->list.array[1],
+                         rbSize);
+  }
+  /* Check for time Density values */
+  if(ptrs_config->timeDensity->list.count < 3) {
+    /* Default value for L_PTRS = 1 as defined in T 38.214 5.1.6.3 */
+       *L_ptrs = 1;
+  }
+  else {
+    *L_ptrs = get_L_ptrs(*ptrs_config->timeDensity->list.array[0],
+                         *ptrs_config->timeDensity->list.array[1],
+                         *ptrs_config->timeDensity->list.array[2],
+                         mcsIndex,
+                         mcsTable);
+  }
+  *portIndex =*ptrs_config->epre_Ratio;
+  *nERatio = *ptrs_config->resourceElementOffset;
+  *reOffset  = 0;
+  /* If either or both of the parameters PT-RS time density (LPT-RS) and PT-RS frequency density (KPT-RS), shown in Table
+   * 5.1.6.3-1 and Table 5.1.6.3-2, indicates that 'PT-RS not present', the UE shall assume that PT-RS is not present
+   */
+  if(*K_ptrs ==2  || *K_ptrs ==4 ) {
+    valid = true;
+  }
+  else {
+    valid = false;
+    return valid;
+  }
+  if(*L_ptrs ==0 || *L_ptrs ==1 || *L_ptrs ==2  ) {
+    valid = true;
+  }
+  else {
+    valid = false;
+    return valid;
+  }
+  /* PTRS is not present also :
+   * When the UE is receiving a PDSCH with allocation duration of 4 symbols and if LPT-RS is set to 4, the UE shall assume
+   * PT-RS is not transmitted
+   * When the UE is receiving a PDSCH with allocation duration of 2 symbols as defined in Clause 7.4.1.1.2 of [4, TS
+   * 38.211] and if LPT-RS is set to 2 or 4, the UE shall assume PT-RS is not transmitted.
+   */
+  if((NrOfSymbols == 4 && *L_ptrs ==2) || ((NrOfSymbols == 2 && *L_ptrs > 0))) {
+    valid = false;
+    return valid;
+  }
+  //printf("[MAC] PTRS is set  K= %u L= %u\n", *K_ptrs,1<<*L_ptrs);
+  return valid;
+}
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index f31723a7d660dd25ac4008a2aea0070d00d913e7..d4cc1bd2a74754bc6505e01d27efa31b5cebf721 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -179,4 +179,10 @@ uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint
 uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB);
 
 int16_t get_N_RA_RB (int delta_f_RA_PRACH,int delta_f_PUSCH);
+
+bool set_dl_ptrs_values(NR_PTRS_DownlinkConfig_t *ptrs_config,
+                        uint16_t rbSize, uint8_t mcsIndex, uint8_t mcsTable,
+                        uint8_t *K_ptrs, uint8_t *L_ptrs,uint8_t *portIndex,
+                        uint8_t *nERatio,uint8_t *reOffset,
+                        uint8_t NrOfSymbols);
 #endif
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index f3935d9269428cf8703a65cd3de54383706dcf8d..5e615b49f47dd31a3c028bb2123609dc5ef0cc9a 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -1393,7 +1393,7 @@ fapi_nr_ul_config_request_t *get_ul_config_request(NR_UE_MAC_INST_t *mac, int sl
   NR_TDD_UL_DL_Pattern_t *tdd_pattern = &mac->scc->tdd_UL_DL_ConfigurationCommon->pattern1;
   const int num_slots_per_tdd = nr_slots_per_frame[mu] >> (7 - tdd_pattern->dl_UL_TransmissionPeriodicity);
   const int num_slots_ul = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0);
-  int index = slot + num_slots_ul - num_slots_per_tdd;
+  int index = (slot + num_slots_ul - num_slots_per_tdd) % num_slots_per_tdd;
   LOG_D(MAC, "nr_ue_procedures: get_ul_config_request() slots per tdd %d, num_slots_ul %d, index %d\n", 
                 num_slots_per_tdd,
                 num_slots_ul,
@@ -2896,6 +2896,13 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
     dlsch_config_pdu->number_rbs = NRRIV2BW(riv,n_RB_DLBWP);
     dlsch_config_pdu->start_rb   = NRRIV2PRBOFFSET(riv,n_RB_DLBWP);
 
+    // Sanity check in case a false or erroneous DCI is received
+    if ((dlsch_config_pdu->number_rbs < 1 ) || (dlsch_config_pdu->number_rbs > n_RB_DLBWP - dlsch_config_pdu->start_rb)) {
+      // DCI is invalid!
+      LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_DLBWP: %d \n", dlsch_config_pdu->number_rbs, dlsch_config_pdu->start_rb, n_RB_DLBWP);
+      return -1;
+    }
+
   }
   if(pusch_config_pdu != NULL){
     /*
@@ -2910,6 +2917,14 @@ int8_t nr_ue_process_dci_freq_dom_resource_assignment(nfapi_nr_ue_pusch_pdu_t *p
 
     pusch_config_pdu->rb_size  = NRRIV2BW(riv,n_RB_ULBWP);
     pusch_config_pdu->rb_start = NRRIV2PRBOFFSET(riv,n_RB_ULBWP);
+
+    // Sanity check in case a false or erroneous DCI is received
+    if ((pusch_config_pdu->rb_size < 1) || (pusch_config_pdu->rb_size > n_RB_ULBWP - pusch_config_pdu->rb_start)) {
+      // DCI is invalid!
+      LOG_W(MAC, "Frequency domain assignment values are invalid! #RBs: %d, Start RB: %d, n_RB_ULBWP: %d \n",pusch_config_pdu->rb_size, pusch_config_pdu->rb_start, n_RB_ULBWP);
+      return -1;
+    }
+
   }
   return 0;
 }
@@ -3133,8 +3148,9 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
   int bwp_id = 1;
   int mu = 0;
   long k2 = 0;
+  int pucch_res_set_cnt = 0, valid = 0;
   uint16_t frame_tx = 0, slot_tx = 0;
-
+  bool valid_ptrs_setup = 0;
   NR_UE_MAC_INST_t *mac = get_mac_inst(module_id);
   fapi_nr_dl_config_request_t *dl_config = &mac->dl_config_request;
   fapi_nr_ul_config_request_t *ul_config = NULL;
@@ -3194,7 +3210,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu_0_0 = &ul_config->ul_config_list[ul_config->number_pdus].pusch_config_pdu;
     /* IDENTIFIER_DCI_FORMATS */
     /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */
-    nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val);
+    if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_0,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val) < 0)
+      return -1;
     /* TIME_DOM_RESOURCE_ASSIGNMENT */
     if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_0,NULL,dci->time_domain_assignment.val) < 0)
       return -1;
@@ -3205,6 +3222,27 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
 
     /* MCS */
     pusch_config_pdu_0_0->mcs_index = dci->mcs;
+
+    /* MCS TABLE */
+    if (mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL)
+      pusch_config_pdu_0_0->transform_precoding = 1;
+    else
+      pusch_config_pdu_0_0->transform_precoding = 0;
+      
+    if (pusch_config_pdu_0_0->transform_precoding == transform_precoder_disabled) 
+      pusch_config_pdu_0_0->mcs_table = get_pusch_mcs_table(pusch_config->mcs_Table, 0,
+                                                 dci_format, NR_RNTI_TC, NR_SearchSpace__searchSpaceType_PR_common, false);
+    else
+      pusch_config_pdu_0_0->mcs_table = get_pusch_mcs_table(pusch_config->mcs_TableTransformPrecoder, 1,
+                                                 dci_format, NR_RNTI_TC, NR_SearchSpace__searchSpaceType_PR_common, false);
+    
+    pusch_config_pdu_0_0->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu_0_0->mcs_index, pusch_config_pdu_0_0->mcs_table);
+    pusch_config_pdu_0_0->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu_0_0->mcs_index, pusch_config_pdu_0_0->mcs_table);
+    if (pusch_config_pdu_0_0->target_code_rate == 0 || pusch_config_pdu_0_0->qam_mod_order == 0) {
+      LOG_W(MAC, "Invalid code rate or Mod order, likely due to unexpected UL DCI. Ignoring DCI! \n");
+      return -1;
+    }
+
     /* NDI */
     pusch_config_pdu_0_0->pusch_data.new_data_indicator = dci->ndi;
     /* RV */
@@ -3293,7 +3331,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     /* BANDWIDTH_PART_IND */
     //pusch_config_pdu_0_1->bandwidth_part_ind = dci->bwp_indicator.val;
     /* FREQ_DOM_RESOURCE_ASSIGNMENT_UL */
-    nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val);
+    if (nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu_0_1,NULL,n_RB_ULBWP,0,dci->frequency_domain_assignment.val) < 0)
+      return -1;
     /* TIME_DOM_RESOURCE_ASSIGNMENT */
     if (nr_ue_process_dci_time_dom_resource_assignment(mac,pusch_config_pdu_0_1,NULL,dci->time_domain_assignment.val) < 0)
       return -1;
@@ -3651,7 +3690,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     dlsch_config_pdu_1_0->SubcarrierSpacing = mac->DLbwp[0]->bwp_Common->genericParameters.subcarrierSpacing;
     /* IDENTIFIER_DCI_FORMATS */
     /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */
-    nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val);
+    if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_0,0,n_RB_DLBWP,dci->frequency_domain_assignment.val) < 0)
+      return -1;
     /* TIME_DOM_RESOURCE_ASSIGNMENT */
     if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_0,dci->time_domain_assignment.val) < 0)
       return -1;
@@ -3669,6 +3709,11 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     dlsch_config_pdu_1_0->vrb_to_prb_mapping = (dci->vrb_to_prb_mapping.val == 0) ? vrb_to_prb_mapping_non_interleaved:vrb_to_prb_mapping_interleaved;
     /* MCS */
     dlsch_config_pdu_1_0->mcs = dci->mcs;
+    // Basic sanity check for MCS value to check for a false or erroneous DCI
+    if (dlsch_config_pdu_1_0->mcs > 28) {
+      LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_0->mcs);
+      return -1;
+    }
     /* NDI (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
     dlsch_config_pdu_1_0->ndi = dci->ndi;
     /* RV (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI or TC-RNTI)*/
@@ -3699,6 +3744,20 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     //if (dci->pucch_resource_indicator == 6) dlsch_config_pdu_1_0->pucch_resource_id = 7; //pucch-ResourceId obtained from the 7th value of resourceList FIXME!!
     //if (dci->pucch_resource_indicator == 7) dlsch_config_pdu_1_0->pucch_resource_id = 8; //pucch-ResourceId obtained from the 8th value of resourceList FIXME!!
     dlsch_config_pdu_1_0->pucch_resource_id = dci->pucch_resource_indicator;
+    // Sanity check for pucch_resource_indicator value received to check for false DCI.
+    valid = 0;
+    pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count;
+    for (int id = 0; id < pucch_res_set_cnt; id++) {
+      if (dlsch_config_pdu_1_0->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) {
+        valid = 1;
+        break;
+      }
+    }
+    if (!valid) {
+      LOG_W(MAC, "pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", dlsch_config_pdu_1_0->pucch_resource_id);
+      return -1;
+    }
+
     /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND (only if CRC scrambled by C-RNTI or CS-RNTI or new-RNTI)*/
     dlsch_config_pdu_1_0->pdsch_to_harq_feedback_time_ind = dci->pdsch_to_harq_feedback_timing_indicator.val;
 
@@ -3776,7 +3835,8 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     /* BANDWIDTH_PART_IND */
     //    dlsch_config_pdu_1_1->bandwidth_part_ind = dci->bandwidth_part_ind;
     /* FREQ_DOM_RESOURCE_ASSIGNMENT_DL */
-    nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val);
+    if (nr_ue_process_dci_freq_dom_resource_assignment(NULL,dlsch_config_pdu_1_1,0,n_RB_DLBWP,dci->frequency_domain_assignment.val) < 0)
+      return -1;
     /* TIME_DOM_RESOURCE_ASSIGNMENT */
     if (nr_ue_process_dci_time_dom_resource_assignment(mac,NULL,dlsch_config_pdu_1_1,dci->time_domain_assignment.val) < 0)
       return -1;
@@ -3799,12 +3859,22 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     dlsch_config_pdu_1_1->zp_csi_rs_trigger = dci->zp_csi_rs_trigger.val;
     /* MCS (for transport block 1)*/
     dlsch_config_pdu_1_1->mcs = dci->mcs;
+    // Basic sanity check for MCS value to check for a false or erroneous DCI
+    if (dlsch_config_pdu_1_1->mcs > 28) {
+      LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_1->mcs);
+      return -1;
+    }
     /* NDI (for transport block 1)*/
     dlsch_config_pdu_1_1->ndi = dci->ndi;
     /* RV (for transport block 1)*/
     dlsch_config_pdu_1_1->rv = dci->rv;
     /* MCS (for transport block 2)*/
     dlsch_config_pdu_1_1->tb2_mcs = dci->mcs2.val;
+    // Basic sanity check for MCS value to check for a false or erroneous DCI
+    if (dlsch_config_pdu_1_1->tb2_mcs > 28) {
+      LOG_W(MAC, "MCS value % d out of bounds! Possibly due to false DCI. Ignoring DCI!!\n", dlsch_config_pdu_1_1->tb2_mcs);
+      return -1;
+    }
     /* NDI (for transport block 2)*/
     dlsch_config_pdu_1_1->tb2_ndi = dci->ndi2.val;
     /* RV (for transport block 2)*/
@@ -3821,6 +3891,20 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     if (dci->tpc == 3) dlsch_config_pdu_1_1->accumulated_delta_PUCCH = 3;
     /* PUCCH_RESOURCE_IND */
     dlsch_config_pdu_1_1->pucch_resource_id = dci->pucch_resource_indicator;
+    // Sanity check for pucch_resource_indicator value received to check for false DCI.
+    valid = 0;
+    pucch_res_set_cnt = mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.count;
+    for (int id = 0; id < pucch_res_set_cnt; id++) {
+      if (dlsch_config_pdu_1_1->pucch_resource_id < mac->ULbwp[0]->bwp_Dedicated->pucch_Config->choice.setup->resourceSetToAddModList->list.array[id]->resourceList.list.count) {
+        valid = 1;
+        break;
+      }
+    }
+    if (!valid) {
+      LOG_W(MAC, "pucch_resource_indicator value %d is out of bounds. Possibly due to false DCI. Ignoring DCI!\n", dlsch_config_pdu_1_1->pucch_resource_id);
+      return -1;
+    }
+
     /* PDSCH_TO_HARQ_FEEDBACK_TIME_IND */
     // according to TS 38.213 Table 9.2.3-1
     dlsch_config_pdu_1_1->pdsch_to_harq_feedback_time_ind = mac->ULbwp[bwp_id-1]->bwp_Dedicated->pucch_Config->choice.setup->dl_DataToUL_ACK->list.array[dci->pdsch_to_harq_feedback_timing_indicator.val][0];
@@ -3925,6 +4009,19 @@ int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, fr
     LOG_D(MAC,"(nr_ue_procedures.c) pdu_type=%d\n\n",dl_config->dl_config_list[dl_config->number_pdus].pdu_type);
             
     dl_config->number_pdus = dl_config->number_pdus + 1;
+    /* TODO same calculation for MCS table as done in UL */
+    dlsch_config_pdu_1_1->mcs_table = 0;
+    /*PTRS configuration */
+    if(mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) {
+      valid_ptrs_setup = set_dl_ptrs_values(mac->DLbwp[0]->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup,
+                                            dlsch_config_pdu_1_1->number_rbs, dlsch_config_pdu_1_1->mcs, dlsch_config_pdu_1_1->mcs_table,
+                                            &dlsch_config_pdu_1_1->PTRSFreqDensity,&dlsch_config_pdu_1_1->PTRSTimeDensity,
+                                            &dlsch_config_pdu_1_1->PTRSPortIndex,&dlsch_config_pdu_1_1->nEpreRatioOfPDSCHToPTRS,
+                                            &dlsch_config_pdu_1_1->PTRSReOffset, dlsch_config_pdu_1_1->number_symbols);
+      if(valid_ptrs_setup==true) {
+        dlsch_config_pdu_1_1->pduBitmap |= 0x1;
+      }
+    }
 
     break;
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 5d701bf5b8f2177b5066400c80f9c82cee09ac85..e4c2e11d7dd40b3833474f8690935d3a50ded6f0 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -337,61 +337,6 @@ void nr_schedule_pusch(int Mod_idP,
   }
 }
 
-
-void nr_schedule_pucch(int Mod_idP,
-                       int UE_id,
-                       int nr_ulmix_slots,
-                       frame_t frameP,
-                       sub_frame_t slotP) {
-
-  uint16_t O_csi, O_ack, O_uci;
-  uint8_t O_sr = 0; // no SR in PUCCH implemented for now
-  NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
-  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
-  AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id);
-
-  NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
-  int bwp_id=1;
-  NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1];
-  nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0];
-
-  NR_sched_pucch *curr_pucch;
-
-  for (int k=0; k<nr_ulmix_slots; k++) {
-    for (int l=0; l<2; l++) {
-      curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
-      O_ack = curr_pucch->dai_c;
-      O_csi = curr_pucch->csi_bits;
-      O_uci = O_ack + O_csi + O_sr;
-      if ((O_uci>0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) {
-        UL_tti_req->SFN = curr_pucch->frame;
-        UL_tti_req->Slot = curr_pucch->ul_slot;
-        UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
-        UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
-        nfapi_nr_pucch_pdu_t  *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu;
-        memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t));
-        UL_tti_req->n_pdus+=1;
-
-        LOG_D(MAC,"Scheduling pucch reception for frame %d slot %d with (%d, %d, %d) (SR ACK, CSI) bits\n",
-              frameP,slotP,O_sr,O_ack,curr_pucch->csi_bits);
-
-        nr_configure_pucch(pucch_pdu,
-                           scc,
-                           ubwp,
-                           UE_info->rnti[UE_id],
-                           curr_pucch->resource_indicator,
-                           O_csi,
-                           O_ack,
-                           O_sr);
-
-        memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
-               0,
-               sizeof(NR_sched_pucch));
-      }
-    }
-  }
-}
-
 bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
   return (bitmap >> slot) & 0x01;
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 7a7fe1288cac5a6932ab51845b78c15829083959..a9839ed985b91abbaa325713b4d47681e908d62a 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -304,9 +304,8 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
 
   // 2) Generation of DLSCH MAC subPDUs including subheaders and MAC SDUs
   for (i = 0; i < num_sdus; i++) {
-    LOG_D(MAC, "[gNB] Generate DLSCH header num sdu %d len sdu %d\n", num_sdus, sdu_lengths[i]);
 
-    if (sdu_lengths[i] < 128) {
+    if (sdu_lengths[i] < 256) {
       ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->R = 0;
       ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->F = 0;
       ((NR_MAC_SUBHEADER_SHORT *) mac_pdu_ptr)->LCID = sdu_lcids[i];
@@ -316,7 +315,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
       ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->R = 0;
       ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->F = 1;
       ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->LCID = sdu_lcids[i];
-      ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0x7f;
+      ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L1 = ((unsigned short) sdu_lengths[i] >> 8) & 0xff;
       ((NR_MAC_SUBHEADER_LONG *) mac_pdu_ptr)->L2 = (unsigned short) sdu_lengths[i] & 0xff;
       last_size = 3;
     }
@@ -326,6 +325,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
     memcpy((void *) mac_pdu_ptr, (void *) dlsch_buffer_ptr, sdu_lengths[i]);
     dlsch_buffer_ptr += sdu_lengths[i];
     mac_pdu_ptr += sdu_lengths[i];
+    LOG_D(MAC, "Generate DLSCH header num sdu %d len header %d len sdu %d -> offset %ld\n", num_sdus, last_size, sdu_lengths[i], (unsigned char *)mac_pdu_ptr - mac_pdu);
   }
 
   // 4) Compute final offset for padding
@@ -333,6 +333,7 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
     ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->R = 0;
     ((NR_MAC_SUBHEADER_FIXED *) mac_pdu_ptr)->LCID = DL_SCH_LCID_PADDING;
     mac_pdu_ptr++;
+    LOG_D(MAC, "Generate Padding -> offset %ld\n", (unsigned char *)mac_pdu_ptr - mac_pdu);
   } else {
     // no MAC subPDU with padding
   }
@@ -343,100 +344,6 @@ int nr_generate_dlsch_pdu(module_id_t module_idP,
   return offset;
 }
 
-void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch,
-                   nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01,
-                   nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234,
-                   NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) {
-
-  // TODO
-  int max_harq_rounds = 4; // TODO define macro
-
-  if (uci_01 != NULL) {
-    // handle harq
-    int harq_idx_s = 0;
-
-    // iterate over received harq bits
-    for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
-      // search for the right harq process
-      for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
-        // if the gNB received ack with a good confidence
-        if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
-          if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) &&
-              (uci_01->harq->harq_confidence_level == 0)) {
-            // toggle NDI and reset round
-            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
-            sched_ctrl->harq_processes[harq_idx].round = 0;
-          }
-          else
-            sched_ctrl->harq_processes[harq_idx].round++;
-          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
-          harq_idx_s = harq_idx + 1;
-          // if the max harq rounds was reached
-          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
-            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
-            sched_ctrl->harq_processes[harq_idx].round = 0;
-            stats->dlsch_errors++;
-          }
-          break;
-        }
-        // if feedback slot processing is aborted
-        else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
-                 (sched_ctrl->harq_processes[harq_idx].is_waiting)) {
-          sched_ctrl->harq_processes[harq_idx].round++;
-          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
-            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
-            sched_ctrl->harq_processes[harq_idx].round = 0;
-          }
-          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
-        }
-      }
-    }
-  }
-
-
-  if (uci_234 != NULL) {
-    int harq_idx_s = 0;
-    int acknack;
-
-    // iterate over received harq bits
-    for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
-      acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01;
-      for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) {
-        // if the gNB received ack with a good confidence or if the max harq rounds was reached
-        if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
-          // TODO add some confidence level for when there is no CRC
-          if ((uci_234->harq.harq_crc != 1) && acknack) {
-            // toggle NDI and reset round
-            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
-            sched_ctrl->harq_processes[harq_idx].round = 0;
-          }
-          else
-            sched_ctrl->harq_processes[harq_idx].round++;
-          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
-          harq_idx_s = harq_idx + 1;
-          // if the max harq rounds was reached
-          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
-            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
-            sched_ctrl->harq_processes[harq_idx].round = 0;
-            stats->dlsch_errors++;
-          }
-          break;
-        }
-        // if feedback slot processing is aborted
-        else if (((UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot) &&
-                 (sched_ctrl->harq_processes[harq_idx].is_waiting)) {
-          sched_ctrl->harq_processes[harq_idx].round++;
-          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
-            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
-            sched_ctrl->harq_processes[harq_idx].round = 0;
-          }
-          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
-        }
-      }
-    }
-  }
-}
-
 int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda) {
   struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList =
     bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
@@ -503,11 +410,12 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
       && !sched_ctrl->ta_apply) /* If TA should be applied, give at least one RB */
     return;
   LOG_D(MAC,
-        "%d.%d, DTCH%d->DLSCH, RLC status %d bytes\n",
+        "%d.%d, DTCH%d->DLSCH, RLC status %d bytes TA %d\n",
         frame,
         slot,
         lcid,
-        sched_ctrl->rlc_status[lcid].bytes_in_buffer);
+        sched_ctrl->rlc_status[lcid].bytes_in_buffer,
+        sched_ctrl->ta_apply);
 
   /* Find a free CCE */
   const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
@@ -598,6 +506,8 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
                                      sched_ctrl->time_domain_allocation);
 
     int rbSize = 0;
+    const int oh = 2 + (sched_ctrl->num_total_bytes >= 256)
+                 + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
     uint32_t TBS = 0;
     do {
       rbSize++;
@@ -611,7 +521,7 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
                            0 /* tb_scaling */,
                            1 /* nrOfLayers */)
             >> 3;
-    } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes);
+    } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes + oh);
     sched_ctrl->rbSize = rbSize;
     sched_ctrl->rbStart = rbStart;
   }
@@ -642,7 +552,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
      * If such UE is not scheduled now, it will be by the preprocessor later.
      * If we add the CE, ta_apply will be reset */
     if (frame == (sched_ctrl->ta_frame + 10) % 1024)
-      sched_ctrl->ta_apply = false; /* the timer is reset once TA CE is scheduled */
+      sched_ctrl->ta_apply = true; /* the timer is reset once TA CE is scheduled */
 
     if (sched_ctrl->rbSize <= 0)
       continue;
@@ -683,6 +593,10 @@ void nr_schedule_ue_spec(module_id_t module_id,
     harq->is_waiting = 1;
     UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
 
+    LOG_D(MAC, "%4d.%2d RNTI %04x start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
+          frame, slot, rnti, sched_ctrl->rbStart, sched_ctrl->rbSize, sched_ctrl->mcs,
+          TBS, current_harq_pid, harq->round, harq->ndi);
+
     nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
     nr_fill_nfapi_dl_pdu(module_id,
                          dl_req,
@@ -742,12 +656,17 @@ void nr_schedule_ue_spec(module_id_t module_id,
       unsigned char sdu_lcids[NB_RB_MAX] = {0};
       const int lcid = DL_SCH_LCID_DTCH;
       if (sched_ctrl->num_total_bytes > 0) {
+        /* this is the data from the RLC we would like to request (e.g., only
+         * some bytes for first LC and some more from a second one */
+        const rlc_buffer_occupancy_t ndata = sched_ctrl->rlc_status[lcid].bytes_in_buffer;
+        /* this is the maximum data we can transport based on TBS minus headers */
+        const int mindata = min(ndata, TBS - ta_len - header_length_total - sdu_length_total -  2 - (ndata >= 256));
         LOG_D(MAC,
               "[gNB %d][USER-PLANE DEFAULT DRB] Frame %d : DTCH->DLSCH, Requesting "
               "%d bytes from RLC (lcid %d total hdr len %d), TBS: %d \n \n",
               module_id,
               frame,
-              TBS - ta_len - header_length_total - sdu_length_total - 3,
+              mindata,
               lcid,
               header_length_total,
               TBS);
@@ -759,7 +678,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
             ENB_FLAG_YES,
             MBMS_FLAG_NO,
             lcid,
-            TBS - ta_len - header_length_total - sdu_length_total - 3,
+            mindata,
             (char *)&mac_sdus[sdu_length_total],
             0,
             0);
@@ -783,7 +702,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
           mac_sdus[i] = (unsigned char) (lrand48()&0xff);
         sdu_lcids[0] = 0x3f; // DRB
         sdu_lengths[0] = TBS - ta_len - 3;
-        header_length_total += 2 + (sdu_lengths[0] >= 128);
+        header_length_total += 2 + (sdu_lengths[0] >= 256);
         sdu_length_total += sdu_lengths[0];
         num_sdus +=1;
       }
@@ -791,7 +710,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
       UE_info->mac_stats[UE_id].dlsch_total_bytes += TBS;
       UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += sdu_length_total;
 
-      const int post_padding = TBS >= 2 + header_length_total + sdu_length_total + ta_len;
+      const int post_padding = TBS > header_length_total + sdu_length_total + ta_len;
 
       const int ntx_req = gNB_mac->TX_req[CC_id].Number_of_PDUs;
       nfapi_nr_pdu_t *tx_req = &gNB_mac->TX_req[CC_id].pdu_list[ntx_req];
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index dda70ef66add028dd9fb0265bb9f46f90dc0233f..ae389cd23bc2d6b711d08e2783c28fe8e1ac75f1 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -453,6 +453,7 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
   const int bwp_id = sched_ctrl->active_bwp->bwp_Id;
   const int nrOfLayers = 1;
   const int mcs = sched_ctrl->mcs;
+  bool valid_ptrs_setup = false;
 
   AssertFatal(secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
 	      "downlinkBWP_ToAddModList has %d BWP!\n",
@@ -521,6 +522,19 @@ void nr_fill_nfapi_dl_pdu(int Mod_idP,
                      scc->dmrs_TypeA_Position,
                      pdsch_pdu_rel15->NrOfSymbols);
 
+  /* Check and validate PTRS values */
+  if(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS != NULL) {
+    valid_ptrs_setup = set_dl_ptrs_values(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup,
+                                          pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->mcsIndex[0],
+                                          pdsch_pdu_rel15->mcsTable[0],
+                                          &pdsch_pdu_rel15->PTRSFreqDensity,&pdsch_pdu_rel15->PTRSTimeDensity,
+                                          &pdsch_pdu_rel15->PTRSPortIndex,&pdsch_pdu_rel15->nEpreRatioOfPDSCHToPTRS,
+                                          &pdsch_pdu_rel15->PTRSReOffset, pdsch_pdu_rel15->NrOfSymbols);
+    if(valid_ptrs_setup==true) {
+      pdsch_pdu_rel15->pduBitmap |=0x1;
+    }
+  }
+
   dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
   memset(dci_pdu_rel15, 0, sizeof(dci_pdu_rel15_t) * MAX_DCI_CORESET);
 
@@ -919,84 +933,6 @@ void nr_configure_pucch(nfapi_nr_pucch_pdu_t* pucch_pdu,
 }
 
 
-uint16_t compute_pucch_prb_size(uint8_t format,
-                                uint8_t nr_prbs,
-                                uint16_t O_tot,
-                                uint16_t O_csi,
-                                NR_PUCCH_MaxCodeRate_t *maxCodeRate,
-                                uint8_t Qm,
-                                uint8_t n_symb,
-                                uint8_t n_re_ctrl) {
-
-  uint16_t O_crc;
-
-  if (O_tot<12)
-    O_crc = 0;
-  else{
-    if (O_tot<20)
-      O_crc = 6;
-    else {
-      if (O_tot<360)
-        O_crc = 11;
-      else
-        AssertFatal(1==0,"Case for segmented PUCCH not yet implemented");
-    }
-  }
-
-  int rtimes100;
-  switch(*maxCodeRate){
-    case NR_PUCCH_MaxCodeRate_zeroDot08 :
-      rtimes100 = 8;
-      break;
-    case NR_PUCCH_MaxCodeRate_zeroDot15 :
-      rtimes100 = 15;
-      break;
-    case NR_PUCCH_MaxCodeRate_zeroDot25 :
-      rtimes100 = 25;
-      break;
-    case NR_PUCCH_MaxCodeRate_zeroDot35 :
-      rtimes100 = 35;
-      break;
-    case NR_PUCCH_MaxCodeRate_zeroDot45 :
-      rtimes100 = 45;
-      break;
-    case NR_PUCCH_MaxCodeRate_zeroDot60 :
-      rtimes100 = 60;
-      break;
-    case NR_PUCCH_MaxCodeRate_zeroDot80 :
-      rtimes100 = 80;
-      break;
-  default :
-    AssertFatal(1==0,"Invalid MaxCodeRate");
-  }
-
-  float r = (float)rtimes100/100;
-
-  if (O_csi == O_tot) {
-    if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r))
-      AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs",
-                  r,O_tot,O_crc,nr_prbs);
-    else
-      return nr_prbs;
-  }
-
-  if (format==2){
-    // TODO fix this for multiple CSI reports
-    for (int i=1; i<=nr_prbs; i++){
-      if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) &&
-         (O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r))
-        return i;
-    }
-    AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs",
-                r,O_tot,O_crc,nr_prbs);
-  }
-  else{
-    AssertFatal(1==0,"Not yet implemented");
-  }
-
-}
-
-
 void prepare_dci(NR_CellGroupConfig_t *secondaryCellGroup,
                  dci_pdu_rel15_t *dci_pdu_rel15,
                  nr_dci_format_t format,
@@ -1921,324 +1857,6 @@ void get_pdsch_to_harq_feedback(int Mod_idP,
 }
 
 
-uint16_t nr_get_csi_bitlen(int Mod_idP,
-                           int UE_id,
-                           uint8_t csi_report_id) {
-
-  uint16_t csi_bitlen =0;
-  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
-  CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL;
-
-  CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]);
-  csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
-               CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
-               (CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report);
-
-  return csi_bitlen;
-}
-
-
-void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
-                       int *period, int *offset) {
-
-    NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present;
-
-    switch(p_and_o){
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots4:
-        *period = 4;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots5:
-        *period = 5;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots8:
-        *period = 8;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots10:
-        *period = 10;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots16:
-        *period = 16;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots20:
-        *period = 20;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots40:
-        *period = 40;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots80:
-        *period = 80;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots160:
-        *period = 160;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160;
-        break;
-      case NR_CSI_ReportPeriodicityAndOffset_PR_slots320:
-        *period = 320;
-        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320;
-        break;
-    default:
-      AssertFatal(1==0,"No periodicity and offset resource found in CSI report");
-    }
-}
-
-
-//!TODO : same function can be written to handle csi_resources
-void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) {
-  uint8_t csi_report_id = 0;
-  uint8_t csi_resourceidx =0;
-  uint8_t csi_ssb_idx =0;
-
-  NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
-  NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
-  for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
-    csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement;
-    UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present;
-
-    for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
-      if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId)
-	continue;
-      else {
-      //Finding the CSI_RS or SSB Resources
-        UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present;
-        if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){
-          struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB;
-
-          UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0;
-          UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0;
-        }
-
-        if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){
-	  uint8_t nb_ssb_resources =0;
-          for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
-            if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
-                *(csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
-              if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled ==
-                csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) {
-	        if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
-                  UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
-                else
-		/*! From Spec 38.331
-		 * nrofReportedRS
-		 * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
-		 * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.
-		 * When the field is absent the UE applies the value 1
-		 */
-	          UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1;
-	        }else
-		  UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2;
-
-	      nb_ssb_resources=  csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
-	      if (nb_ssb_resources){
-		UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources));
-	        UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP 
-	        UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
-              }
-	      else{
-		UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0;
-	        UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0;
-	        UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0;
-              }
-
-	      LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d",
-			      UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen,
-			      UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen,
-			      UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen);
-	      break ;
-            }
-	  }
-        }
-	if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report){
-          AssertFatal(1==0,"Currently configuring only SSB beamreporting.");
-	}
-	break;
-      }
-    }
-  }
-}
-
-void nr_csi_meas_reporting(int Mod_idP,
-                           int UE_id,
-                           frame_t frame,
-                           sub_frame_t slot,
-                           int slots_per_tdd,
-                           int ul_slots,
-                           int n_slots_frame) {
-
-  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
-  NR_sched_pucch *curr_pucch;
-  NR_PUCCH_ResourceSet_t *pucchresset;
-  NR_CSI_ReportConfig_t *csirep;
-  NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
-  NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
-  NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];
-  NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
-
-  AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available");
-
-  for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
-
-    csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
-
-    AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently");
-    int period, offset, sched_slot;
-    csi_period_offset(csirep,&period,&offset);
-    sched_slot = (period+offset)%n_slots_frame;
-    // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
-    // preparation is done in first slot of tdd period
-    if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) {
-
-      // we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack)
-      curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[sched_slot-slots_per_tdd+ul_slots][0];
-
-      NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
-
-      int found = -1;
-      pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
-      int n_list = pucchresset->resourceList.list.count;
-      for (int i=0; i<n_list; i++) {
-        if (*pucchresset->resourceList.list.array[i] == pucchcsires->pucch_Resource)
-          found = i;
-      }
-      AssertFatal(found>-1,"CSI resource not found among PUCCH resources");
-
-      curr_pucch->resource_indicator = found;
-
-      n_list = pucch_Config->resourceToAddModList->list.count;
-
-      // going through the list of PUCCH resources to find the one indexed by resource_id
-      for (int i=0; i<n_list; i++) {
-        NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[i];
-        if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) {
-          switch(pucchres->format.present){
-            case NR_PUCCH_Resource__format_PR_format2:
-              if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
-                curr_pucch->simultaneous_harqcsi = false;
-              else
-                curr_pucch->simultaneous_harqcsi = true;
-              break;
-            case NR_PUCCH_Resource__format_PR_format3:
-              if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
-                curr_pucch->simultaneous_harqcsi = false;
-              else
-                curr_pucch->simultaneous_harqcsi = true;
-              break;
-            case NR_PUCCH_Resource__format_PR_format4:
-              if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
-                curr_pucch->simultaneous_harqcsi = false;
-              else
-                curr_pucch->simultaneous_harqcsi = true;
-              break;
-          default:
-            AssertFatal(1==0,"Invalid PUCCH format type");
-          }
-        }
-      }
-      curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size
-      curr_pucch->frame = frame;
-      curr_pucch->ul_slot = sched_slot;
-    }
-  }
-}
-
-
-// function to update pucch scheduling parameters in UE list when a USS DL is scheduled
-void nr_acknack_scheduling(int Mod_idP,
-                           int UE_id,
-                           frame_t frameP,
-                           sub_frame_t slotP,
-                           int slots_per_tdd,
-                           int *pucch_id,
-                           int *pucch_occ) {
-
-  NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
-  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
-  NR_sched_pucch *curr_pucch;
-  int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l;
-  uint8_t pdsch_to_harq_feedback[8];
-  int found = 0;
-  int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
-  if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0)
-    nr_ulmix_slots++;
-
-  bool csi_pres=false;
-  for (k=0; k<nr_ulmix_slots; k++) {
-    if(UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0)
-      csi_pres=true;
-  }
-
-  // As a preference always schedule ack nacks in PUCCH0 (max 2 per slots)
-  // Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot
-  if (csi_pres)
-    max_acknacks=10;
-  else
-    max_acknacks=2;
-
-  // this is hardcoded for now as ue specific
-  NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
-  get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback);
-
-  // for each possible ul or mixed slot
-  for (k=0; k<nr_ulmix_slots; k++) {
-    for (l=0; l<1; l++) { // scheduling 2 PUCCH in a single slot does not work with the phone, currently
-      curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
-      //if it is possible to schedule acknack in current pucch (no exclusive csi pucch)
-      if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) {
-        // if there is free room in current pucch structure
-        if (curr_pucch->dai_c<max_acknacks) {
-          pucch_res = get_pucch_resource(UE_info,UE_id,k,l);
-          if (pucch_res>-1){
-            curr_pucch->resource_indicator = pucch_res;
-            curr_pucch->frame = frameP;
-            // first pucch occasion in first UL or MIXED slot
-            first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
-            i = 0;
-            while (i<8 && found == 0)  {  // look if timing indicator is among allowed values
-              if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
-                found = 1;
-              if (found == 0) i++;
-            }
-            if (found == 1) {
-              // computing slot in which pucch is scheduled
-              curr_pucch->dai_c++;
-              curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
-              curr_pucch->timing_indicator = i; // index in the list of timing indicators
-              *pucch_id = k;
-              *pucch_occ = l;
-              return;
-            }
-          }
-        }
-      }
-    }
-  }
-  AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n");
-}
-
-
-int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) {
-
-  // to be updated later, for now simple implementation
-  // use the second allocation just in case there is csi in the first
-  // in that case use second resource (for a different symbol) see 9.2 in 38.213
-  if (l==1) {
-    if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0)
-      return -1;
-    else
-      return 1;
-  }
-  else
-    return 0;
-
-}
-
 void find_aggregation_candidates(uint8_t *aggregation_level,
                                  uint8_t *nr_of_candidates,
                                  NR_SearchSpace_t *ss) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
new file mode 100644
index 0000000000000000000000000000000000000000..909a3ea540bd21975699832ad702fe870498d49d
--- /dev/null
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -0,0 +1,588 @@
+/*
+ * 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 gNB_scheduler_uci.c
+ * \brief MAC procedures related to UCI
+ * \date 2020
+ * \version 1.0
+ * \company Eurecom
+ */
+
+#include "LAYER2/MAC/mac.h"
+#include "NR_MAC_gNB/nr_mac_gNB.h"
+#include "NR_MAC_COMMON/nr_mac_extern.h"
+#include "NR_MAC_gNB/mac_proto.h"
+#include "common/ran_context.h"
+
+extern RAN_CONTEXT_t RC;
+
+void nr_schedule_pucch(int Mod_idP,
+                       int UE_id,
+                       int nr_ulmix_slots,
+                       frame_t frameP,
+                       sub_frame_t slotP) {
+
+  uint16_t O_csi, O_ack, O_uci;
+  uint8_t O_sr = 0; // no SR in PUCCH implemented for now
+  NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  AssertFatal(UE_info->active[UE_id],"Cannot find UE_id %d is not active\n",UE_id);
+
+  NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
+  int bwp_id=1;
+  NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[bwp_id-1];
+  nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[Mod_idP]->UL_tti_req[0];
+
+  NR_sched_pucch *curr_pucch;
+
+  for (int k=0; k<nr_ulmix_slots; k++) {
+    for (int l=0; l<2; l++) {
+      curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
+      O_ack = curr_pucch->dai_c;
+      O_csi = curr_pucch->csi_bits;
+      O_uci = O_ack + O_csi + O_sr;
+      if ((O_uci>0) && (frameP == curr_pucch->frame) && (slotP == curr_pucch->ul_slot)) {
+        UL_tti_req->SFN = curr_pucch->frame;
+        UL_tti_req->Slot = curr_pucch->ul_slot;
+        UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUCCH_PDU_TYPE;
+        UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_pucch_pdu_t);
+        nfapi_nr_pucch_pdu_t  *pucch_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].pucch_pdu;
+        memset(pucch_pdu,0,sizeof(nfapi_nr_pucch_pdu_t));
+        UL_tti_req->n_pdus+=1;
+
+        LOG_D(MAC,"Scheduling pucch reception for frame %d slot %d with (%d, %d, %d) (SR ACK, CSI) bits\n",
+              frameP,slotP,O_sr,O_ack,curr_pucch->csi_bits);
+
+        nr_configure_pucch(pucch_pdu,
+                           scc,
+                           ubwp,
+                           UE_info->rnti[UE_id],
+                           curr_pucch->resource_indicator,
+                           O_csi,
+                           O_ack,
+                           O_sr);
+
+        memset((void *) &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l],
+               0,
+               sizeof(NR_sched_pucch));
+      }
+    }
+  }
+}
+
+
+//!TODO : same function can be written to handle csi_resources
+void compute_csi_bitlen (NR_CellGroupConfig_t *secondaryCellGroup, NR_UE_info_t *UE_info, int UE_id) {
+  uint8_t csi_report_id = 0;
+  uint8_t csi_resourceidx =0;
+  uint8_t csi_ssb_idx =0;
+
+  NR_CSI_MeasConfig_t *csi_MeasConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
+  NR_CSI_ResourceConfigId_t csi_ResourceConfigId;
+  for (csi_report_id=0; csi_report_id < csi_MeasConfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
+    csi_ResourceConfigId=csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->resourcesForChannelMeasurement;
+    UE_info->csi_report_template[UE_id][csi_report_id].reportQuantity_type = csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->reportQuantity.present;
+
+    for ( csi_resourceidx = 0; csi_resourceidx < csi_MeasConfig->csi_ResourceConfigToAddModList->list.count; csi_resourceidx++) {
+      if ( csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_ResourceConfigId != csi_ResourceConfigId)
+	continue;
+      else {
+      //Finding the CSI_RS or SSB Resources
+        UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type= csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.present;
+        if (NR_CSI_ResourceConfig__csi_RS_ResourceSetList_PR_nzp_CSI_RS_SSB ==UE_info->csi_report_template[UE_id][csi_report_id].CSI_Resource_type){
+          struct NR_CSI_ResourceConfig__csi_RS_ResourceSetList__nzp_CSI_RS_SSB * nzp_CSI_RS_SSB = csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB;
+
+          UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report = nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->nzp_CSI_RS_ResourceSetList->list.count:0;
+          UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report = nzp_CSI_RS_SSB->csi_SSB_ResourceSetList!=NULL ? nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.count:0;
+        }
+
+        if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report){
+	  uint8_t nb_ssb_resources =0;
+          for ( csi_ssb_idx = 0; csi_ssb_idx < csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.count; csi_ssb_idx++) {
+            if (csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceSetId ==
+                *(csi_MeasConfig->csi_ResourceConfigToAddModList->list.array[csi_resourceidx]->csi_RS_ResourceSetList.choice.nzp_CSI_RS_SSB->csi_SSB_ResourceSetList->list.array[0])) { 
+              ///We can configure only one SSB resource set from spec 38.331 IE CSI-ResourceConfig
+              if (NR_CSI_ReportConfig__groupBasedBeamReporting_PR_disabled ==
+                csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.present ) {
+	        if (NULL != csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)
+                  UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri = *(csi_MeasConfig->csi_ReportConfigToAddModList->list.array[csi_report_id]->groupBasedBeamReporting.choice.disabled->nrofReportedRS)+1;
+                else
+                  /*! From Spec 38.331
+                  * nrofReportedRS
+                  * The number (N) of measured RS resources to be reported per report setting in a non-group-based report. N <= N_max, where N_max is either 2 or 4 depending on UE
+                  * capability. FFS: The signaling mechanism for the gNB to select a subset of N beams for the UE to measure and report.
+                  * When the field is absent the UE applies the value 1
+                  */
+                  UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 1;
+              } else
+                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].nb_ssbri_cri= 2;
+
+              nb_ssb_resources=  csi_MeasConfig->csi_SSB_ResourceSetToAddModList->list.array[csi_ssb_idx]->csi_SSB_ResourceList.list.count;
+              if (nb_ssb_resources){
+                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =ceil(log2 (nb_ssb_resources));
+                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 7; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP 
+                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =4; //From spec 38.212 Table 6.3.1.1.2-6: CRI, SSBRI, and RSRP
+              }
+              else{
+                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen =0;
+                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen = 0;
+                UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen =0;
+              }
+
+              LOG_I (MAC, "UCI: CSI_bit len : ssbri %d, rsrp: %d, diff_rsrp: %d",
+                     UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].cri_ssbri_bitlen,
+                     UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].rsrp_bitlen,
+                     UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0].diff_rsrp_bitlen);
+              break ;
+            }
+          }
+        }
+        if (0 != UE_info->csi_report_template[UE_id][csi_report_id].nb_of_nzp_csi_report)
+          AssertFatal(1==0,"Currently configuring only SSB beamreporting.");
+        break;
+      }
+    }
+  }
+}
+
+
+uint16_t nr_get_csi_bitlen(int Mod_idP,
+                           int UE_id,
+                           uint8_t csi_report_id) {
+
+  uint16_t csi_bitlen =0;
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  CRI_SSBRI_RSRP_bitlen_t * CSI_report_bitlen = NULL;
+
+  CSI_report_bitlen = &(UE_info->csi_report_template[UE_id][csi_report_id].CSI_report_bitlen[0]);
+  csi_bitlen = ((CSI_report_bitlen->cri_ssbri_bitlen * CSI_report_bitlen->nb_ssbri_cri) +
+               CSI_report_bitlen->rsrp_bitlen +(CSI_report_bitlen->diff_rsrp_bitlen *
+               (CSI_report_bitlen->nb_ssbri_cri -1 )) *UE_info->csi_report_template[UE_id][csi_report_id].nb_of_csi_ssb_report);
+
+  return csi_bitlen;
+}
+
+
+void nr_csi_meas_reporting(int Mod_idP,
+                           int UE_id,
+                           frame_t frame,
+                           sub_frame_t slot,
+                           int slots_per_tdd,
+                           int ul_slots,
+                           int n_slots_frame) {
+
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  NR_sched_pucch *curr_pucch;
+  NR_PUCCH_ResourceSet_t *pucchresset;
+  NR_CSI_ReportConfig_t *csirep;
+  NR_CellGroupConfig_t *secondaryCellGroup = UE_info->secondaryCellGroup[UE_id];
+  NR_CSI_MeasConfig_t *csi_measconfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated->csi_MeasConfig->choice.setup;
+  NR_BWP_Uplink_t *ubwp=secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[0];
+  NR_PUCCH_Config_t *pucch_Config = ubwp->bwp_Dedicated->pucch_Config->choice.setup;
+
+  AssertFatal(csi_measconfig->csi_ReportConfigToAddModList->list.count>0,"NO CSI report configuration available");
+
+  for (int csi_report_id = 0; csi_report_id < csi_measconfig->csi_ReportConfigToAddModList->list.count; csi_report_id++){
+
+    csirep = csi_measconfig->csi_ReportConfigToAddModList->list.array[csi_report_id];
+
+    AssertFatal(csirep->reportConfigType.choice.periodic!=NULL,"Only periodic CSI reporting is implemented currently");
+    int period, offset, sched_slot;
+    csi_period_offset(csirep,&period,&offset);
+    sched_slot = (period+offset)%n_slots_frame;
+    // prepare to schedule csi measurement reception according to 5.2.1.4 in 38.214
+    // preparation is done in first slot of tdd period
+    if ( (frame%(period/n_slots_frame)==(offset/n_slots_frame)) && (slot==((sched_slot/slots_per_tdd)*slots_per_tdd))) {
+
+      // we are scheduling pucch for csi in the first pucch occasion (this comes before ack/nack)
+      curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[sched_slot-slots_per_tdd+ul_slots][0];
+
+      NR_PUCCH_CSI_Resource_t *pucchcsires = csirep->reportConfigType.choice.periodic->pucch_CSI_ResourceList.list.array[0];
+
+      int found = -1;
+      pucchresset = pucch_Config->resourceSetToAddModList->list.array[1]; // set with formats >1
+      int n_list = pucchresset->resourceList.list.count;
+      for (int i=0; i<n_list; i++) {
+        if (*pucchresset->resourceList.list.array[i] == pucchcsires->pucch_Resource)
+          found = i;
+      }
+      AssertFatal(found>-1,"CSI resource not found among PUCCH resources");
+
+      curr_pucch->resource_indicator = found;
+
+      n_list = pucch_Config->resourceToAddModList->list.count;
+
+      // going through the list of PUCCH resources to find the one indexed by resource_id
+      for (int i=0; i<n_list; i++) {
+        NR_PUCCH_Resource_t *pucchres = pucch_Config->resourceToAddModList->list.array[i];
+        if (pucchres->pucch_ResourceId == *pucchresset->resourceList.list.array[found]) {
+          switch(pucchres->format.present){
+            case NR_PUCCH_Resource__format_PR_format2:
+              if (pucch_Config->format2->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
+                curr_pucch->simultaneous_harqcsi = false;
+              else
+                curr_pucch->simultaneous_harqcsi = true;
+              break;
+            case NR_PUCCH_Resource__format_PR_format3:
+              if (pucch_Config->format3->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
+                curr_pucch->simultaneous_harqcsi = false;
+              else
+                curr_pucch->simultaneous_harqcsi = true;
+              break;
+            case NR_PUCCH_Resource__format_PR_format4:
+              if (pucch_Config->format4->choice.setup->simultaneousHARQ_ACK_CSI == NULL)
+                curr_pucch->simultaneous_harqcsi = false;
+              else
+                curr_pucch->simultaneous_harqcsi = true;
+              break;
+          default:
+            AssertFatal(1==0,"Invalid PUCCH format type");
+          }
+        }
+      }
+      curr_pucch->csi_bits += nr_get_csi_bitlen(Mod_idP,UE_id,csi_report_id); // TODO function to compute CSI meas report bit size
+      curr_pucch->frame = frame;
+      curr_pucch->ul_slot = sched_slot;
+    }
+  }
+}
+
+
+void nr_rx_acknack(nfapi_nr_uci_pusch_pdu_t *uci_pusch,
+                   nfapi_nr_uci_pucch_pdu_format_0_1_t *uci_01,
+                   nfapi_nr_uci_pucch_pdu_format_2_3_4_t *uci_234,
+                   NR_UL_IND_t *UL_info, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_stats_t *stats) {
+
+  // TODO
+  int max_harq_rounds = 4; // TODO define macro
+
+  if (uci_01 != NULL) {
+    // handle harq
+    int harq_idx_s = 0;
+
+    // iterate over received harq bits
+    for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
+      // search for the right harq process
+      for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES; harq_idx++) {
+        // if the gNB received ack with a good confidence
+        if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
+          sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
+          if ((uci_01->harq->harq_list[harq_bit].harq_value == 1) &&
+              (uci_01->harq->harq_confidence_level == 0)) {
+            // toggle NDI and reset round
+            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
+            sched_ctrl->harq_processes[harq_idx].round = 0;
+          }
+          else
+            sched_ctrl->harq_processes[harq_idx].round++;
+          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
+          harq_idx_s = harq_idx + 1;
+          // if the max harq rounds was reached
+          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
+            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
+            sched_ctrl->harq_processes[harq_idx].round = 0;
+            stats->dlsch_errors++;
+          }
+          break;
+        }
+        // if feedback slot processing is aborted
+        else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
+                 && (UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
+                 && sched_ctrl->harq_processes[harq_idx].is_waiting) {
+          sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
+          sched_ctrl->harq_processes[harq_idx].round++;
+          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
+            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
+            sched_ctrl->harq_processes[harq_idx].round = 0;
+          }
+          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
+        }
+      }
+    }
+  }
+
+
+  if (uci_234 != NULL) {
+    int harq_idx_s = 0;
+    int acknack;
+
+    // iterate over received harq bits
+    for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
+      acknack = ((uci_234->harq.harq_payload[harq_bit>>3])>>harq_bit)&0x01;
+      for (int harq_idx = harq_idx_s; harq_idx < NR_MAX_NB_HARQ_PROCESSES-1; harq_idx++) {
+        // if the gNB received ack with a good confidence or if the max harq rounds was reached
+        if ((UL_info->slot-1) == sched_ctrl->harq_processes[harq_idx].feedback_slot) {
+          // TODO add some confidence level for when there is no CRC
+          sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
+          if ((uci_234->harq.harq_crc != 1) && acknack) {
+            // toggle NDI and reset round
+            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
+            sched_ctrl->harq_processes[harq_idx].round = 0;
+          }
+          else
+            sched_ctrl->harq_processes[harq_idx].round++;
+          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
+          harq_idx_s = harq_idx + 1;
+          // if the max harq rounds was reached
+          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
+            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
+            sched_ctrl->harq_processes[harq_idx].round = 0;
+            stats->dlsch_errors++;
+          }
+          break;
+        }
+        // if feedback slot processing is aborted
+        else if (sched_ctrl->harq_processes[harq_idx].feedback_slot != -1
+                 && (UL_info->slot-1) > sched_ctrl->harq_processes[harq_idx].feedback_slot
+                 && sched_ctrl->harq_processes[harq_idx].is_waiting) {
+          sched_ctrl->harq_processes[harq_idx].feedback_slot = -1;
+          sched_ctrl->harq_processes[harq_idx].round++;
+          if (sched_ctrl->harq_processes[harq_idx].round == max_harq_rounds) {
+            sched_ctrl->harq_processes[harq_idx].ndi ^= 1;
+            sched_ctrl->harq_processes[harq_idx].round = 0;
+          }
+          sched_ctrl->harq_processes[harq_idx].is_waiting = 0;
+        }
+      }
+    }
+  }
+}
+
+
+// function to update pucch scheduling parameters in UE list when a USS DL is scheduled
+void nr_acknack_scheduling(int Mod_idP,
+                           int UE_id,
+                           frame_t frameP,
+                           sub_frame_t slotP,
+                           int slots_per_tdd,
+                           int *pucch_id,
+                           int *pucch_occ) {
+
+  NR_ServingCellConfigCommon_t *scc = RC.nrmac[Mod_idP]->common_channels->ServingCellConfigCommon;
+  NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
+  NR_sched_pucch *curr_pucch;
+  int max_acknacks,pucch_res,first_ul_slot_tdd,k,i,l;
+  uint8_t pdsch_to_harq_feedback[8];
+  int found = 0;
+  int nr_ulmix_slots = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
+  if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols!=0)
+    nr_ulmix_slots++;
+
+  bool csi_pres=false;
+  for (k=0; k<nr_ulmix_slots; k++) {
+    if(UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits>0)
+      csi_pres=true;
+  }
+
+  // As a preference always schedule ack nacks in PUCCH0 (max 2 per slots)
+  // Unless there is CSI meas reporting scheduled in the period to avoid conflicts in the same slot
+  if (csi_pres)
+    max_acknacks=10;
+  else
+    max_acknacks=2;
+
+  // this is hardcoded for now as ue specific
+  NR_SearchSpace__searchSpaceType_PR ss_type = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
+  get_pdsch_to_harq_feedback(Mod_idP,UE_id,ss_type,pdsch_to_harq_feedback);
+
+  // for each possible ul or mixed slot
+  for (k=0; k<nr_ulmix_slots; k++) {
+    for (l=0; l<1; l++) { // scheduling 2 PUCCH in a single slot does not work with the phone, currently
+      curr_pucch = &UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][l];
+      //if it is possible to schedule acknack in current pucch (no exclusive csi pucch)
+      if ((curr_pucch->csi_bits == 0) || (curr_pucch->simultaneous_harqcsi==true)) {
+        // if there is free room in current pucch structure
+        if (curr_pucch->dai_c<max_acknacks) {
+          pucch_res = get_pucch_resource(UE_info,UE_id,k,l);
+          if (pucch_res>-1){
+            curr_pucch->resource_indicator = pucch_res;
+            curr_pucch->frame = frameP;
+            // first pucch occasion in first UL or MIXED slot
+            first_ul_slot_tdd = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
+            i = 0;
+            while (i<8 && found == 0)  {  // look if timing indicator is among allowed values
+              if (pdsch_to_harq_feedback[i]==(first_ul_slot_tdd+k)-(slotP % slots_per_tdd))
+                found = 1;
+              if (found == 0) i++;
+            }
+            if (found == 1) {
+              // computing slot in which pucch is scheduled
+              curr_pucch->dai_c++;
+              curr_pucch->ul_slot = first_ul_slot_tdd + k + (slotP - (slotP % slots_per_tdd));
+              curr_pucch->timing_indicator = i; // index in the list of timing indicators
+              *pucch_id = k;
+              *pucch_occ = l;
+              return;
+            }
+          }
+        }
+      }
+    }
+  }
+  AssertFatal(1==0,"No Uplink slot available in accordance to allowed timing indicator\n");
+}
+
+
+void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
+                       int *period, int *offset) {
+
+    NR_CSI_ReportPeriodicityAndOffset_PR p_and_o = csirep->reportConfigType.choice.periodic->reportSlotConfig.present;
+
+    switch(p_and_o){
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots4:
+        *period = 4;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots4;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots5:
+        *period = 5;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots5;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots8:
+        *period = 8;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots8;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots10:
+        *period = 10;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots10;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots16:
+        *period = 16;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots16;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots20:
+        *period = 20;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots20;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots40:
+        *period = 40;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots40;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots80:
+        *period = 80;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots80;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots160:
+        *period = 160;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots160;
+        break;
+      case NR_CSI_ReportPeriodicityAndOffset_PR_slots320:
+        *period = 320;
+        *offset = csirep->reportConfigType.choice.periodic->reportSlotConfig.choice.slots320;
+        break;
+    default:
+      AssertFatal(1==0,"No periodicity and offset resource found in CSI report");
+    }
+}
+
+
+int get_pucch_resource(NR_UE_info_t *UE_info,int UE_id,int k,int l) {
+
+  // to be updated later, for now simple implementation
+  // use the second allocation just in case there is csi in the first
+  // in that case use second resource (for a different symbol) see 9.2 in 38.213
+  if (l==1) {
+    if (UE_info->UE_sched_ctrl[UE_id].sched_pucch[k][0].csi_bits==0)
+      return -1;
+    else
+      return 1;
+  }
+  else
+    return 0;
+
+}
+
+
+uint16_t compute_pucch_prb_size(uint8_t format,
+                                uint8_t nr_prbs,
+                                uint16_t O_tot,
+                                uint16_t O_csi,
+                                NR_PUCCH_MaxCodeRate_t *maxCodeRate,
+                                uint8_t Qm,
+                                uint8_t n_symb,
+                                uint8_t n_re_ctrl) {
+
+  uint16_t O_crc;
+
+  if (O_tot<12)
+    O_crc = 0;
+  else{
+    if (O_tot<20)
+      O_crc = 6;
+    else {
+      if (O_tot<360)
+        O_crc = 11;
+      else
+        AssertFatal(1==0,"Case for segmented PUCCH not yet implemented");
+    }
+  }
+
+  int rtimes100;
+  switch(*maxCodeRate){
+    case NR_PUCCH_MaxCodeRate_zeroDot08 :
+      rtimes100 = 8;
+      break;
+    case NR_PUCCH_MaxCodeRate_zeroDot15 :
+      rtimes100 = 15;
+      break;
+    case NR_PUCCH_MaxCodeRate_zeroDot25 :
+      rtimes100 = 25;
+      break;
+    case NR_PUCCH_MaxCodeRate_zeroDot35 :
+      rtimes100 = 35;
+      break;
+    case NR_PUCCH_MaxCodeRate_zeroDot45 :
+      rtimes100 = 45;
+      break;
+    case NR_PUCCH_MaxCodeRate_zeroDot60 :
+      rtimes100 = 60;
+      break;
+    case NR_PUCCH_MaxCodeRate_zeroDot80 :
+      rtimes100 = 80;
+      break;
+  default :
+    AssertFatal(1==0,"Invalid MaxCodeRate");
+  }
+
+  float r = (float)rtimes100/100;
+
+  if (O_csi == O_tot) {
+    if ((O_tot+O_csi)>(nr_prbs*n_re_ctrl*n_symb*Qm*r))
+      AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with %d PRBs",
+                  r,O_tot,O_crc,nr_prbs);
+    else
+      return nr_prbs;
+  }
+
+  if (format==2){
+    // TODO fix this for multiple CSI reports
+    for (int i=1; i<=nr_prbs; i++){
+      if((O_tot+O_crc)<=(i*n_symb*Qm*n_re_ctrl*r) &&
+         (O_tot+O_crc)>((i-1)*n_symb*Qm*n_re_ctrl*r))
+        return i;
+    }
+    AssertFatal(1==0,"MaxCodeRate %.2f can't support %d UCI bits and %d CRC bits with at most %d PRBs",
+                r,O_tot,O_crc,nr_prbs);
+  }
+  else{
+    AssertFatal(1==0,"Not yet implemented");
+  }
+
+}
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 84ad51f0726634170d9bdbd49e8f9e99328387fb..76c9dedf30c64cc387f13bc0cc83df5b70f9db27 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -291,7 +291,7 @@ void handle_nr_ul_harq(uint16_t slot, NR_UE_sched_ctrl_t *sched_ctrl, NR_mac_sta
     }
     return;
   } else
-    LOG_E(MAC,"Incorrect ULSCH HARQ process %d or invalid state %d\n",hrq_id,cur_harq->state);
+    LOG_W(MAC,"Incorrect ULSCH HARQ process %d or invalid state %d (ignore this warning for RA)\n",hrq_id,cur_harq->state);
 }
 
 /*
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index b3cd91fd0102fbab56489f1fccab9978b322a9d6..7bb08e4f046f2b714f7dbbc281d8db2987468889 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -183,6 +183,9 @@ void nr_schedule_pucch(int Mod_idP,
                        frame_t frameP,
                        sub_frame_t slotP);
 
+void csi_period_offset(NR_CSI_ReportConfig_t *csirep,
+                       int *period, int *offset);
+
 void nr_csi_meas_reporting(int Mod_idP,
                            int UE_id,
                            frame_t frameP,
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 27118ee5230125931402c10bdcc8e84a594286a4..130c6a0e346eedac60f055a4755cf950b9fee6e9 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -119,6 +119,14 @@ void *rrc_gnb_task(void *args_p);
 /* Trigger RRC periodic processing. To be called once per ms. */
 void nr_rrc_trigger(protocol_ctxt_t *ctxt, int CC_id, int frame, int subframe);
 
+/**\ Function to set or overwrite PTRS DL RRC parameters.
+   \ *bwp Pointer to dedicated RC config structure
+   \ *ptrsNrb Pointer to K_ptrs N_RB related parameters
+   \ *ptrsMcs Pointer to L_ptrs MCS related parameters
+   \ *epre_Ratio Pointer to ep_ratio
+   \ *reOffset Pointer to RE Offset Value */
+void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset);
+
 uint8_t
 nr_rrc_data_req(
   const protocol_ctxt_t   *const ctxt_pP,
@@ -133,4 +141,3 @@ nr_rrc_data_req(
 int
 nr_rrc_mac_remove_ue(module_id_t mod_idP,
                   rnti_t rntiP);
-
diff --git a/openair2/RRC/NR/rrc_gNB_internode.c b/openair2/RRC/NR/rrc_gNB_internode.c
index cacff5cf5c179fd9bf27db57973a2ef338df36a3..3c8d75edfac1913115fca20601af340fde926ab4 100644
--- a/openair2/RRC/NR/rrc_gNB_internode.c
+++ b/openair2/RRC/NR/rrc_gNB_internode.c
@@ -37,6 +37,7 @@
 #include "NR_UE-CapabilityRAT-ContainerList.h"
 #include "LTE_UE-CapabilityRAT-ContainerList.h"
 #include "NR_CG-Config.h"
+#include "executables/softmodem-common.h"
 
 int parse_CG_ConfigInfo(gNB_RRC_INST *rrc, NR_CG_ConfigInfo_t *CG_ConfigInfo, x2ap_ENDC_sgnb_addition_req_t *m) {
   if (CG_ConfigInfo->criticalExtensions.present == NR_CG_ConfigInfo__criticalExtensions_PR_c1) {
@@ -95,33 +96,48 @@ int generate_CG_Config(gNB_RRC_INST *rrc,
                        (const char *)buffer,
                        (enc_rval.encoded+7)>>3);
   total_size = (enc_rval.encoded+7)>>3;
-  LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3);
 
-  for (int i=0; i<(enc_rval.encoded+7)>>3; i++) {
-    printf("%02x",((uint8_t *)buffer)[i]);
+  FILE *fd; // file to be generated for nr-ue
+  if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) {
+    // This is for phytest only, emulate first X2 message if uecap.raw file is present
+    LOG_I(RRC,"Dumping NR_RRCReconfiguration message (%jd bytes)\n",(enc_rval.encoded+7)>>3);
+    for (int i=0; i<(enc_rval.encoded+7)>>3; i++) {
+      printf("%02x",((uint8_t *)buffer)[i]);
+    }
+    printf("\n");
+    fd = fopen("reconfig.raw","w");
+    if (fd != NULL) {
+      fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd);
+    }
+    fclose(fd);
   }
-
-  printf("\n");
-  FILE *fd = fopen("reconfig.raw","w");
-  fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd);
-  fclose(fd);
+  
   enc_rval = uper_encode_to_buffer(&asn_DEF_NR_RadioBearerConfig, NULL, (void *)rbconfig, buffer, 1024);
   AssertFatal (enc_rval.encoded > 0, "ASN1 message encoding failed (%s, %jd)!\n",
-               enc_rval.failed_type->name, enc_rval.encoded);
+	       enc_rval.failed_type->name, enc_rval.encoded);
   cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config = calloc(1,sizeof(OCTET_STRING_t));
+  
   OCTET_STRING_fromBuf(cg_Config->criticalExtensions.choice.c1->choice.cg_Config->scg_RB_Config,
-                       (const char *)buffer,
-                       (enc_rval.encoded+7)>>3);
-  LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3);
+		       (const char *)buffer,
+		       (enc_rval.encoded+7)>>3);
 
-  for (int i=0; i<(enc_rval.encoded+7)>>3; i++) {
-    printf("%02x",((uint8_t *)buffer)[i]);
-  }
 
-  printf("\n");
-  fd = fopen("rbconfig.raw","w");
-  fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd);
-  fclose(fd);
+  
+  if (get_softmodem_params()->phy_test==1 || get_softmodem_params()->do_ra > 0) {  
+
+    LOG_I(RRC,"Dumping scg_RB_Config message (%jd bytes)\n",(enc_rval.encoded+7)>>3);
+    for (int i=0; i<(enc_rval.encoded+7)>>3; i++) {
+      printf("%02x",((uint8_t *)buffer)[i]);
+    }
+    
+    printf("\n");
+    fd = fopen("rbconfig.raw","w");
+    if (fd != NULL) {
+      fwrite((void *)buffer,1,(size_t)((enc_rval.encoded+7)>>3),fd);
+    }
+    fclose(fd);
+  }
+  
   total_size = total_size + ((enc_rval.encoded+7)>>3);
   return(total_size);
 }
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index 197c3f1f87a0aec4415a03ee0b489e6615e9feeb..b5bcf09d478959994c80c034735876d8f3800932 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -1276,5 +1276,37 @@ void fill_default_rbconfig(NR_RadioBearerConfig_t *rbconfig) {
 
   xer_fprint(stdout, &asn_DEF_NR_RadioBearerConfig, (const void*)rbconfig);
 }
-
+/* Function to set or overwrite PTRS DL RRC parameters */
+void rrc_config_dl_ptrs_params(NR_BWP_Downlink_t *bwp, int *ptrsNrb, int *ptrsMcs, int *epre_Ratio, int * reOffset)
+{
+  int i=0;
+  /* check for memory allocation  */
+  if(bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS == NULL) {
+    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS=calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS));
+    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->present = NR_SetupRelease_PTRS_DownlinkConfig_PR_setup;
+    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup= calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup));
+    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity = calloc(1,sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity));
+    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity = calloc(1, sizeof(*bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity));
+    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = calloc(1,sizeof(long));
+    bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = calloc(1,sizeof(long));
+    /* Fill the given values */
+    for(i = 0; i < 2; i++) {
+      ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list,&ptrsNrb[i]);
+    }
+    for(i = 0; i < 3; i++) {
+      ASN_SEQUENCE_ADD(&bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list,&ptrsMcs[i]);
+    }
+  }// if memory exist then over write the old values
+  else {
+    for(i = 0; i < 2; i++) {
+      *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->frequencyDensity->list.array[i] = ptrsNrb[i];
+    }
+    for(i = 0; i < 3; i++) {
+      *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->timeDensity->list.array[i] = ptrsMcs[i];
+    }
+  }
+
+  *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->epre_Ratio = *epre_Ratio;
+  *bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->phaseTrackingRS->choice.setup->resourceElementOffset = *reOffset;
+}
 #endif