diff --git a/openair1/PHY/MODULATION/nr_modulation.c b/openair1/PHY/MODULATION/nr_modulation.c
index 6c4d9c85ca3cb26920519ab2e313cca8c8ddbced..74f09d9fae0054651f34a599dc00436bdfceb512 100644
--- a/openair1/PHY/MODULATION/nr_modulation.c
+++ b/openair1/PHY/MODULATION/nr_modulation.c
@@ -119,4 +119,183 @@ void nr_layer_mapping(int16_t **mod_symbs,
   default:
   AssertFatal(0, "Invalid number of layers %d\n", n_layers);
   }
-}
\ No newline at end of file
+}
+
+
+void nr_dft(int32_t *z, int32_t *d, uint32_t Msc_PUSCH)
+{
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i dft_in128[1][1200], dft_out128[1][1200];
+#elif defined(__arm__)
+  int16x8_t dft_in128[1][1200], dft_out128[1][1200];
+#endif
+  uint32_t *dft_in0 = (uint32_t*)dft_in128[0], *dft_out0 = (uint32_t*)dft_out128[0];
+
+  uint32_t i, ip;
+
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i norm128;
+#elif defined(__arm__)
+  int16x8_t norm128;
+#endif
+
+  for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
+    dft_in0[ip] = d[i];
+  }
+
+  switch (Msc_PUSCH) {
+    case 12:
+      dft12((int16_t *)dft_in0, (int16_t *)dft_out0);
+
+#if defined(__x86_64__) || defined(__i386__)
+      norm128 = _mm_set1_epi16(9459);
+#elif defined(__arm__)
+      norm128 = vdupq_n_s16(9459);
+#endif
+      for (i=0; i<12; i++) {
+#if defined(__x86_64__) || defined(__i386__)
+        ((__m128i*)dft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)dft_out0)[i], norm128), 1);
+#elif defined(__arm__)
+        ((int16x8_t*)dft_out0)[i] = vqdmulhq_s16(((int16x8_t*)dft_out0)[i], norm128);
+#endif
+      }
+
+      break;
+
+    case 24:
+      dft24((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 36:
+      dft36((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 48:
+      dft48((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 60:
+      dft60((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 72:
+      dft72((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 96:
+      dft96((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 108:
+      dft108((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 120:
+      dft120((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 144:
+      dft144((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 180:
+      dft180((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 192:
+      dft192((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 216:
+      dft216((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 240:
+      dft240((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 288:
+      dft288((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 300:
+      dft300((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 324:
+      dft324((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 360:
+      dft360((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 384:
+      dft384((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 432:
+      dft432((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 480:
+      dft480((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 540:
+      dft540((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 576:
+      dft576((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 600:
+      dft600((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 648:
+      dft648((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 720:
+      dft720((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 768:
+      dft768((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 864:
+      dft864((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 900:
+      dft900((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 960:
+      dft960((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 972:
+      dft972((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1080:
+      dft1080((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1152:
+      dft1152((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+
+    case 1200:
+      dft1200((int16_t*)dft_in0, (int16_t*)dft_out0, 1);
+      break;
+  }
+
+  for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
+    z[i] = dft_out0[ip];
+  }
+}
diff --git a/openair1/PHY/MODULATION/nr_modulation.h b/openair1/PHY/MODULATION/nr_modulation.h
index 01b62025c2ca383282b1d9dd83feece5bb0df729..d807244ba293d9da573e8cc52063fcecf945ad8b 100644
--- a/openair1/PHY/MODULATION/nr_modulation.h
+++ b/openair1/PHY/MODULATION/nr_modulation.h
@@ -68,4 +68,12 @@ int nr_slot_fep_ul(PHY_VARS_gNB *phy_vars_gNB,
                    int sample_offset,
                    int no_prefix);
 
+/*!
+\brief This function implements the dft transform precoding in PUSCH
+\param z Pointer to output in frequnecy domain
+\param d Pointer to input in time domain
+\param Msc_PUSCH number of allocated data subcarriers
+*/
+void nr_dft(int32_t *z,int32_t *d, uint32_t Msc_PUSCH);
+
 #endif
\ No newline at end of file
diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
index 90f6119d2b31df548583b08f934e91a36081312c..2dbef1d733ff2b88aabc9194306ff110d725d29c 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
@@ -73,6 +73,12 @@ void nr_ulsch_extract_rbs_single(int **rxdataF,
                                  unsigned short nb_rb_pusch,
                                  NR_DL_FRAME_PARMS *frame_parms);
 
+/*!
+\brief This function implements the idft transform precoding in PUSCH
+\param z Pointer to input in frequnecy domain, and it is also the output in time domain
+\param Msc_PUSCH number of allocated data subcarriers
+*/
+void nr_idft(uint32_t *z, uint32_t Msc_PUSCH);
 
 /** \brief This function generates log-likelihood ratios (decoder input) for single-stream QPSK received waveforms.
     @param rxdataF_comp Compensated channel output
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
index b59b97b89ef250dcad68eb2eef971b6f21dd5b22..957d2971b02a90b93498edeeddd02cbfe0174a8e 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_demodulation.c
@@ -2,7 +2,219 @@
 #include "nr_transport_proto.h"
 #include "PHY/impl_defs_top.h"
 #include "PHY/NR_TRANSPORT/nr_sch_dmrs.h"
+#include "PHY/defs_nr_common.h"
 
+short conjugate2[8]__attribute__((aligned(16))) = {1,-1,1,-1,1,-1,1,-1};
+
+void nr_idft(uint32_t *z, uint32_t Msc_PUSCH)
+{
+
+#if defined(__x86_64__) || defined(__i386__)
+  __m128i idft_in128[1][1200], idft_out128[1][1200];
+  __m128i norm128;
+#elif defined(__arm__)
+  int16x8_t idft_in128[1][1200], idft_out128[1][1200];
+  int16x8_t norm128;
+#endif
+  int16_t *idft_in0 = (int16_t*)idft_in128[0], *idft_out0 = (int16_t*)idft_out128[0];
+
+  int i, ip;
+
+  LOG_T(PHY,"Doing lte_idft for Msc_PUSCH %d\n",Msc_PUSCH);
+
+  // conjugate input
+  for (i = 0; i < (Msc_PUSCH>>2); i++) {
+#if defined(__x86_64__)||defined(__i386__)
+    *&(((__m128i*)z)[i]) = _mm_sign_epi16(*&(((__m128i*)z)[i]), *(__m128i*)&conjugate2[0]);
+#elif defined(__arm__)
+    *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
+#endif
+  }
+
+  for (i=0,ip=0; i<Msc_PUSCH; i++, ip+=4) {
+    ((uint32_t*)idft_in0)[ip+0] = z[i];
+  }
+
+
+  switch (Msc_PUSCH) {
+    case 12:
+      dft12((int16_t *)idft_in0, (int16_t *)idft_out0);
+
+#if defined(__x86_64__)||defined(__i386__)
+      norm128 = _mm_set1_epi16(9459);
+#elif defined(__arm__)
+      norm128 = vdupq_n_s16(9459);
+#endif
+
+      for (i = 0; i < 12; i++) {
+#if defined(__x86_64__)||defined(__i386__)
+        ((__m128i*)idft_out0)[i] = _mm_slli_epi16(_mm_mulhi_epi16(((__m128i*)idft_out0)[i], norm128), 1);
+#elif defined(__arm__)
+        ((int16x8_t*)idft_out0)[i] = vqdmulhq_s16(((int16x8_t*)idft_out0)[i], norm128);
+#endif
+      }
+
+      break;
+
+    case 24:
+      dft24(idft_in0, idft_out0, 1);
+      break;
+
+    case 36:
+      dft36(idft_in0, idft_out0, 1);
+      break;
+
+    case 48:
+      dft48(idft_in0, idft_out0, 1);
+      break;
+
+    case 60:
+      dft60(idft_in0, idft_out0, 1);
+      break;
+
+    case 72:
+      dft72(idft_in0, idft_out0, 1);
+      break;
+
+    case 96:
+      dft96(idft_in0, idft_out0, 1);
+      break;
+
+    case 108:
+      dft108(idft_in0, idft_out0, 1);
+      break;
+
+    case 120:
+      dft120(idft_in0, idft_out0, 1);
+      break;
+
+    case 144:
+      dft144(idft_in0, idft_out0, 1);
+      break;
+
+    case 180:
+      dft180(idft_in0, idft_out0, 1);
+      break;
+
+    case 192:
+      dft192(idft_in0, idft_out0, 1);
+      break;
+
+    case 216:
+      dft216(idft_in0, idft_out0, 1);
+      break;
+
+    case 240:
+      dft240(idft_in0, idft_out0, 1);
+      break;
+
+    case 288:
+      dft288(idft_in0, idft_out0, 1);
+      break;
+
+    case 300:
+      dft300(idft_in0, idft_out0, 1);
+      break;
+
+    case 324:
+      dft324((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 360:
+      dft360((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 384:
+      dft384((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 432:
+      dft432((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 480:
+      dft480((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 540:
+      dft540((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 576:
+      dft576((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 600:
+      dft600((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 648:
+      dft648((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 720:
+      dft720((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 768:
+      dft768((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 864:
+      dft864((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 900:
+      dft900((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 960:
+      dft960((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 972:
+      dft972((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1080:
+      dft1080((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1152:
+      dft1152((int16_t*)idft_in0, (int16_t*)idft_out0, 1);
+      break;
+
+    case 1200:
+      dft1200(idft_in0, idft_out0, 1);
+      break;
+
+    default:
+      // should not be reached
+      LOG_E( PHY, "Unsupported Msc_PUSCH value of %"PRIu16"\n", Msc_PUSCH );
+      return;
+  }
+
+
+
+  for (i = 0, ip = 0; i < Msc_PUSCH; i++, ip+=4) {
+    z[i] = ((uint32_t*)idft_out0)[ip];
+  }
+
+  // conjugate output
+  for (i = 0; i < (Msc_PUSCH>>2); i++) {
+#if defined(__x86_64__) || defined(__i386__)
+    ((__m128i*)z)[i] = _mm_sign_epi16(((__m128i*)z)[i], *(__m128i*)&conjugate2[0]);
+#elif defined(__arm__)
+    *&(((int16x8_t*)z)[i]) = vmulq_s16(*&(((int16x8_t*)z)[i]), *(int16x8_t*)&conjugate2[0]);
+#endif
+  }
+
+#if defined(__x86_64__) || defined(__i386__)
+  _mm_empty();
+  _m_empty();
+#endif
+
+}
 
 void nr_ulsch_extract_rbs_single(int **rxdataF,
                                  int **rxdataF_ext,
@@ -51,18 +263,18 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
                  unsigned char symbol,
                  unsigned char harq_pid)
 {
-  
+
   NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
   nfapi_nr_ul_config_ulsch_pdu_rel15_t *rel15_ul = &gNB->ulsch[UE_id+1][0]->harq_processes[harq_pid]->ulsch_pdu.ulsch_pdu_rel15;
-  uint32_t nb_re;
-
+  uint32_t nb_re_pusch;
+  
   if(symbol == rel15_ul->start_symbol)
     gNB->pusch_vars[UE_id]->rxdataF_ext_offset = 0;
 
   if (symbol == 2)  // [hna] here it is assumed that symbol 2 carries 6 DMRS REs (dmrs-type 1)
-    nb_re = rel15_ul->number_rbs * 6;
+    nb_re_pusch = rel15_ul->number_rbs * 6;
   else
-    nb_re = rel15_ul->number_rbs * 12;
+    nb_re_pusch = rel15_ul->number_rbs * NR_NB_SC_PER_RB;
 
   //----------------------------------------------------------
   //--------------------- RBs extraction ---------------------
@@ -76,8 +288,11 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
                               rel15_ul->start_rb,
                               rel15_ul->number_rbs,
                               frame_parms);
-    
-  
+
+#ifdef NR_SC_FDMA
+  nr_idft(&((uint32_t*)gNB->pusch_vars[UE_id]->rxdataF_ext[0])[gNB->pusch_vars[UE_id]->rxdataF_ext_offset], nb_re_pusch);
+#endif
+
   //----------------------------------------------------------
   //-------------------- LLRs computation --------------------
   //----------------------------------------------------------
@@ -86,10 +301,10 @@ void nr_rx_pusch(PHY_VARS_gNB *gNB,
                        gNB->pusch_vars[UE_id]->ul_ch_mag,
                        gNB->pusch_vars[UE_id]->ul_ch_magb,
                        &gNB->pusch_vars[UE_id]->llr[gNB->pusch_vars[UE_id]->rxdataF_ext_offset * rel15_ul->Qm],
-                       nb_re,
+                       nb_re_pusch,
                        symbol,
                        rel15_ul->Qm);
   
-  gNB->pusch_vars[UE_id]->rxdataF_ext_offset = gNB->pusch_vars[UE_id]->rxdataF_ext_offset +  nb_re;
-
+  gNB->pusch_vars[UE_id]->rxdataF_ext_offset = gNB->pusch_vars[UE_id]->rxdataF_ext_offset +  nb_re_pusch;
+  
 }
\ No newline at end of file
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 a9fab4d601d39dc60ec11b66cc3de97bf5c8b496..a2bfb84027abc5da11066f6e7790510dd0468df9 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -1082,10 +1082,6 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
                          uint32_t n_RNTI,
                          uint32_t* out);
 
-void pusch_transform_precoding(NR_UE_ULSCH_t *ulsch,
-                         NR_DL_FRAME_PARMS *frame_parms,
-                         int harq_pid);
-
 /** \brief Perform the following functionalities:
     - encoding
     - scrambling
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
index d4cb82d88640aa3f97c918f98a8a059171dc62f6..4a505911ab97671f51c077190424ba543a36174f 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
@@ -204,7 +204,7 @@ typedef struct {
   /// Modulated "d"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
   uint32_t d_mod[MAX_NUM_NR_RE] __attribute__ ((aligned(16)));
   /// Transform-coded "y"-sequences (for definition see 38-211 V15.3.0 2018-09, subsection 6.3.1.4)
-  uint32_t y[MAX_NUM_NR_RE];
+  uint32_t y[MAX_NUM_NR_RE] __attribute__ ((aligned(16)));
   /*
   /// "q" sequences for CQI/PMI (for definition see 36-212 V8.6 2009-03, p.27)
   uint8_t q[MAX_CQI_PAYLOAD];
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
index 9982a2a8091cca2b3bbd7aca9d415d6f4671638f..4620d7604e2a47626cc32fd380be822260f6e9bd 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
@@ -41,11 +41,6 @@
 
 //#define DEBUG_SCFDMA
 
-#ifdef DEBUG_SCFDMA
-
-  FILE *debug_scfdma;
-
-#endif
 
 int generate_ue_ulsch_params(PHY_VARS_NR_UE *UE,
                              uint8_t thread_id,
@@ -152,105 +147,6 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
 
 }
 
-
-void pusch_transform_precoding(NR_UE_ULSCH_t *ulsch, NR_DL_FRAME_PARMS *frame_parms, int harq_pid){
-
-  NR_UL_UE_HARQ_t *harq_process;
-  int x[8192]__attribute__ ((aligned (32))); // 8192 is the maximum number of fft bins
-  uint32_t *dmod;
-  int sc, pusch_symb, pusch_sc;
-  int symb, k, l, num_mod_symb;
-
-  harq_process = ulsch->harq_processes[harq_pid];
-
-#ifdef DEBUG_SCFDMA
-  debug_scfdma = fopen("debug_scfdma.txt","w");
-#endif
-
-  dmod = ulsch->d_mod;
-  pusch_symb = ulsch->Nsymb_pusch;
-  pusch_sc = ulsch->Nsc_pusch;
-  num_mod_symb = harq_process->num_of_mod_symbols;
-
-  void (*dft)(int16_t *,int16_t *, int);
-
-  switch (frame_parms->ofdm_symbol_size) {
-  case 128:
-    dft = dft128;
-    break;
-
-  case 256:
-    dft = dft256;
-    break;
-
-  case 512:
-    dft = dft512;
-    break;
-
-  case 1024:
-    dft = dft1024;
-    break;
-
-  case 1536:
-    dft = dft1536;
-    break;
-
-  case 2048:
-    dft = dft2048;
-    break;
-
-  case 4096:
-    dft = dft4096;
-    break;
-
-  case 8192:
-    dft = dft8192;
-    break;
-
-  default:
-    dft = dft512;
-    break;
-  }
-
-  k = 0;
-  symb = 0;
-
-  for(l = 0; l < pusch_symb; l++){
-
-    for (sc = 0; sc < pusch_sc; sc++){
-
-      ((int16_t *)x)[sc*2] = (symb<num_mod_symb)?(AMP*((int16_t *)dmod)[symb*2])>>15:0;
-      ((int16_t *)x)[sc*2 + 1] = (symb<num_mod_symb)?(AMP*((int16_t *)dmod)[symb*2 + 1])>>15:0;
-
-  #ifdef DEBUG_SCFDMA
-      fprintf(debug_scfdma, "x[%d] = %d\n", symb*2, ((int16_t *)x)[sc*2] );
-      fprintf(debug_scfdma, "x[%d] = %d\n", symb*2 + 1, ((int16_t *)x)[sc*2 + 1] );
-  #endif
-
-      symb++;
-
-    }
-
-
-    dft((int16_t *)x, (int16_t *)&ulsch->y[l*pusch_sc], 1);
-
-  }
-
-#ifdef DEBUG_SCFDMA
-
-  for (symb = 0; symb < num_mod_symb; symb++)
-  {
-    fprintf(debug_scfdma, "ulsch->y[%d] = %d\n", symb*2, ((int16_t *)ulsch->y)[symb*2] );
-    fprintf(debug_scfdma, "ulsch->y[%d] = %d\n", symb*2 + 1, ((int16_t *)ulsch->y)[symb*2 + 1] );
-  }
-
-  fclose(debug_scfdma);
-#endif
-
-}
-
-
-
 uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
                                unsigned char harq_pid,
                                uint8_t slot,
@@ -327,7 +223,7 @@ uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
                   mod_order,
                   (int16_t *)ulsch_ue->d_mod);
 
-    pusch_transform_precoding(ulsch_ue, frame_parms, harq_pid);
+    // pusch_transform_precoding(ulsch_ue, frame_parms, harq_pid);
 
     ///////////
     ////////////////////////////////////////////////////////////////////////
@@ -365,11 +261,46 @@ uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
                    harq_process_ul_ue->Nl,
                    available_bits/mod_order,
                    tx_layers);
+  
+  for (uint32_t i = 0; i < 2*available_bits/mod_order; i++)
+      tx_layers[0][i] = (tx_layers[0][i] * AMP) >> 15;
 
+  ///////////
+  ////////////////////////////////////////////////////////////////////////
+
+
+  //////////////////////// ULSCH transform precoding ////////////////////////
+  ///////////
+
+  l_prime[0] = 0; // single symbol ap 0
+  uint8_t dmrs_symbol = l0+l_prime[0], l; // Assuming dmrs-AdditionalPosition = 0
+
+#ifdef NR_SC_FDMA
+  uint32_t nb_re_pusch, nb_re_dmrs_per_rb;
+  uint32_t y_offset = 0;
+
+  for (l = start_symbol; l < start_symbol + ulsch_ue->Nsymb_pusch; l++) {
+
+    if(l == dmrs_symbol)
+      nb_re_dmrs_per_rb = ulsch_ue->nb_re_dmrs; // [hna] ulsch_ue->nb_re_dmrs = 6 in this configuration
+    else
+      nb_re_dmrs_per_rb = 0;
+    
+    nb_re_pusch = harq_process_ul_ue->nb_rb * (NR_NB_SC_PER_RB - nb_re_dmrs_per_rb);
+
+    nr_dft(&ulsch_ue->y[y_offset], &((int32_t*)tx_layers[0])[y_offset], nb_re_pusch);
+
+    y_offset = y_offset + nb_re_pusch;
+  }
+#else
+  memcpy(ulsch_ue->y, tx_layers[0], (available_bits/mod_order)*sizeof(int32_t));
+#endif
 
   ///////////
   ////////////////////////////////////////////////////////////////////////
 
+
+
   /////////////////////////ULSCH RE mapping/////////////////////////
   ///////////
 
@@ -387,10 +318,9 @@ uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
     get_Wt(Wt, ap, dmrs_type);
     get_Wf(Wf, ap, dmrs_type);
     delta = get_delta(ap, dmrs_type);
-    l_prime[0] = 0; // single symbol ap 0
-    uint8_t dmrs_symbol = l0+l_prime[0]; // Assuming dmrs-AdditionalPosition = 0
+    
 
-    uint8_t k_prime=0, l;
+    uint8_t k_prime=0;
     uint16_t m=0, n=0, dmrs_idx=0, k=0;
 
     for (l=start_symbol; l<start_symbol+ulsch_ue->Nsymb_pusch; l++) {
@@ -420,8 +350,8 @@ uint8_t nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
 
         else {
 
-          ((int16_t*)txdataF[ap])[(sample_offsetF)<<1] = (AMP * tx_layers[ap][m<<1]) >> 15;
-          ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = (AMP * tx_layers[ap][(m<<1) + 1]) >> 15;
+          ((int16_t*)txdataF[ap])[(sample_offsetF)<<1]       = ((int16_t *) ulsch_ue->y)[m<<1];
+          ((int16_t*)txdataF[ap])[((sample_offsetF)<<1) + 1] = ((int16_t *) ulsch_ue->y)[(m<<1) + 1];
 
           #ifdef DEBUG_PUSCH_MAPPING
             printf("m %d\t l %d \t k %d \t txdataF: %d %d\n",
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 299982ea64c4b6dc4cc6f18b661f7ce5259b6ced..dda59eeeb0f9ecbf9324e7e347b3ba60c4ae7449 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -42,6 +42,11 @@
 #define nr_subframe_t lte_subframe_t
 #define nr_slot_t lte_subframe_t
 
+// [hna] This enables SC-FDMA transmission in Uplink. If disabled, then OFDMA is used in UPLINK.
+#ifndef NR_SC_FDMA
+#define NR_SC_FDMA
+#endif
+
 #define MAX_NUM_SUBCARRIER_SPACING 5
 
 #define NR_MAX_NB_RB 275
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index ad302074346cc13c92a8b32d3df3589d057b535f..c9fff8da156a6e61a9459252a77eaea32982a16e 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -236,8 +236,8 @@ void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc) {
   uint8_t symbol;
 
   for(symbol = 0; symbol < NR_SYMBOLS_PER_SLOT; symbol++) {
-        nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0);
-      }
+    nr_slot_fep_ul(gNB, symbol, proc->slot_rx, 0, 0);
+  }
 
 }
 
@@ -251,11 +251,9 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, gNB_L1_rxtx_proc_t *proc, u
 
   for (UE_id = 0; UE_id < NUMBER_OF_NR_UE_MAX; UE_id++) {
     
-    
-
     for(symbol = symbol_start; symbol < symbol_end; symbol++) {
 
-          nr_rx_pusch(gNB, UE_id, proc->frame_rx, proc->slot_rx, symbol, harq_pid);
+      nr_rx_pusch(gNB, UE_id, proc->frame_rx, proc->slot_rx, symbol, harq_pid);
 
     }
       
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index ed154b26f71469f285620405500f69687c372edb..5a99142edb49661d4595af350cc5c6917bcfff6f 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -167,7 +167,7 @@ int main(int argc, char **argv) {
   int ap;
   int tx_offset;
   double txlev;
-  int start_rb = 90;
+  int start_rb = 30;
   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)