diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf
index f5d2da91b729458e22bcb4f31274f3c6c763bf19..b71bd3acd9e932a023a31882689f0238c46457e5 100644
--- a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf
+++ b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf
@@ -41,6 +41,7 @@ gNBs =
     pdsch_AntennaPorts                                        = 1;
     pusch_AntennaPorts                                        = 2;
     ul_prbblacklist                                           = "51,52,53,54"
+    do_SRS                                                    = 1;
 
     pdcch_ConfigSIB1 = (
       {
diff --git a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf
index 11931d17004dd80d392552f6b5bc3ac58192e697..32a40fe9516eb60ac3651f4c8428995673fed0c6 100644
--- a/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf
+++ b/ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.usrpn310.conf
@@ -44,6 +44,7 @@ gNBs =
     #pucch_TargetSNRx10                                        = 200;
     ul_prbblacklist                                           = "51,52,53,54"
     min_rxtxtime = 6;
+    do_SRS                                                    = 1;
 
     pdcch_ConfigSIB1 = (
       {
diff --git a/ci-scripts/ran.py b/ci-scripts/ran.py
index da20998297faa91d02a3be634ff3fc3f05790dba..ad360d217979d30bcf982b7279a12f0b30f09938 100644
--- a/ci-scripts/ran.py
+++ b/ci-scripts/ran.py
@@ -671,10 +671,14 @@ class RANManagement():
 				mySSH.command('echo ' + localEpcPassword + ' | sudo -S chmod 666 /tmp/' + self.epcPcapFile, '\$', 5)
 				mySSH.copyin(localEpcIpAddr, localEpcUserName, localEpcPassword, '/tmp/' + self.epcPcapFile, '.')
 				mySSH.copyout(lIpAddr, lUserName, lPassWord, self.epcPcapFile, lSourcePath + '/cmake_targets/.')
+			mySSH.command('killall --signal SIGKILL record', '\$', 5)
 			mySSH.close()
+		# if T tracer was run with option 0 (no logs), analyze logs
+		# from textlog, otherwise do normal analysis (e.g., option 2)
+		result = re.search('T_stdout 0', str(self.Initialize_eNB_args))
+		if (result is not None):
 			logging.debug('\u001B[1m Replaying RAW record file\u001B[0m')
 			mySSH.open(lIpAddr, lUserName, lPassWord)
-			mySSH.command('killall --signal SIGKILL record', '\$', 5)
 			mySSH.command('cd ' + lSourcePath + '/common/utils/T/tracer/', '\$', 5)
 			enbLogFile = self.eNBLogFiles[int(self.eNB_instance)]
 			raw_record_file = enbLogFile.replace('.log', '_record.raw')
diff --git a/ci-scripts/xml_files/fr1_sa_quectel.xml b/ci-scripts/xml_files/fr1_sa_quectel.xml
index cd67637ec01f0611c960bdb36865d4b13c2136cd..8d15015c0747e4c84d46dcc7322421f7c0d2b080 100644
--- a/ci-scripts/xml_files/fr1_sa_quectel.xml
+++ b/ci-scripts/xml_files/fr1_sa_quectel.xml
@@ -63,7 +63,7 @@
 	<testCase id="040000">
 		<class>Initialize_eNB</class>
 		<desc>Initialize gNB</desc>
-		<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
+		<Initialize_eNB_args>-O ci-scripts/conf_files/gnb.band78.sa.fr1.106PRB.2x2.usrpn310.conf --sa -q --usrp-tx-thread-config 1 --T_stdout 2 --log_config.global_log_options level,nocolor,time</Initialize_eNB_args>
 		<eNB_instance>0</eNB_instance>
 		<eNB_serverId>0</eNB_serverId>
 		<air_interface>nr</air_interface>
diff --git a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml
index 1e10d021807b0a2e504a62dccf14074353530874..3e497ede13caa63b094799b4d44a63406819cf92 100644
--- a/ci-scripts/xml_files/fr1_sa_quectel_stages.xml
+++ b/ci-scripts/xml_files/fr1_sa_quectel_stages.xml
@@ -28,7 +28,7 @@
 	<TestCaseRequestedList>
  041000
  000002
- 010000
+ 011000
  000001
  051000
  000001
@@ -42,12 +42,12 @@
  000001
  071004
  000001
- 010002
- 080000
+ 011002
+ 081000
 	</TestCaseRequestedList>
 	<TestCaseExclusionList></TestCaseExclusionList>
 
-	<testCase id="010000">
+	<testCase id="011000">
 		<class>Initialize_UE</class>
 		<desc>Initialize Quectel</desc>
 		<id>nrmodule2_quectel</id>
@@ -55,7 +55,7 @@
 	</testCase>
 
 
-	<testCase id="010002">
+	<testCase id="011002">
 		<class>Terminate_UE</class>
 		<desc>Terminate Quectel</desc>
 		<id>nrmodule2_quectel</id>
@@ -151,7 +151,7 @@
 
 
 
-	<testCase id="080000">
+	<testCase id="081000">
 		<class>Terminate_eNB</class>
 		<desc>Terminate gNB</desc>
 		<eNB_instance>0</eNB_instance>
diff --git a/cmake_targets/CMakeLists.txt b/cmake_targets/CMakeLists.txt
index 52d551875e1c141cfb78a335e4ad846605cf0c7f..b7b365741cb90c9c9a3ec1f196c42ed9bd1ccbf9 100644
--- a/cmake_targets/CMakeLists.txt
+++ b/cmake_targets/CMakeLists.txt
@@ -1710,6 +1710,9 @@ set(PHY_SRC_UE
 
   set(PHY_NR_SRC_COMMON
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_prach_common.c
+  ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
+  ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_scrambling.c
+  ${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c
   )
 
   set(PHY_NR_SRC
@@ -1735,7 +1738,6 @@ set(PHY_SRC_UE
   ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_dmrs_rx.c
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_csi_rs.c
   ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gold.c
-  ${OPENAIR1_DIR}/PHY/NR_REFSIG/scrambling_luts.c
   ${OPENAIR1_DIR}/PHY/NR_REFSIG/nr_gen_mod_table.c
   ${OPENAIR1_DIR}/PHY/NR_REFSIG/dmrs_nr.c
   ${OPENAIR1_DIR}/PHY/NR_REFSIG/ptrs_nr.c
@@ -1758,6 +1760,7 @@ set(PHY_SRC_UE
   ${PHY_SMALLBLOCKSRC}
   ${PHY_NR_CODINGIF}
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/pucch_rx.c
+  ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/srs_rx.c
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_uci_tools_common.c
   )
   set(PHY_NR_UE_SRC
@@ -1779,7 +1782,6 @@ set(PHY_SRC_UE
   ${OPENAIR1_DIR}/PHY/NR_TRANSPORT/nr_sch_dmrs.c
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/nr_prach.c
-  ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_nr.c
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/dci_tools_nr.c
   ${OPENAIR1_DIR}/PHY/NR_UE_TRANSPORT/pucch_nr.c
@@ -2074,6 +2076,7 @@ set (MAC_NR_SRC
   ${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_srs.c
   ${NR_GNB_MAC_DIR}/gNB_scheduler_RA.c
  )
 
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index a8a4f57fcddb8fb92a881f07c80bc6d1157c0acf..a8b919e5252459e007c696744515a42ef7ac7e9c 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -93,6 +93,14 @@ ID = GNB_PHY_PUCCH_PUSCH_IQ
     DESC = gNodeB input data in the frequency domain for a slot where some PUCCH or PUSCH detection was done
     GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
     FORMAT = int,frame : int,slot : buffer,rxdataF
+ID = GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE
+    DESC = gNodeB channel estimation in the frequency domain
+    GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
+    FORMAT = int,gNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,chest_t
+ID = GNB_PHY_UL_TIME_CHANNEL_ESTIMATE
+    DESC = gNodeB channel estimation in the time domain
+    GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
+    FORMAT = int,gNB_ID : int,rnti : int,frame : int,subframe : int,antenna : buffer,chest_t
 ID = GNB_PHY_PRACH_INPUT_SIGNAL
     DESC = gNodeB input data in the time domain for slots with PRACH detection
     GROUP = ALL:PHY:GRAPHIC:HEAVY:GNB
diff --git a/common/utils/T/tracer/gnb.c b/common/utils/T/tracer/gnb.c
index 4aaa4898a1fcc7902c189d8732f3a481c9562634..6629a1efd6e39ee26acd0551ef8cb6e53acc0b0b 100644
--- a/common/utils/T/tracer/gnb.c
+++ b/common/utils/T/tracer/gnb.c
@@ -4,15 +4,28 @@
 #include <pthread.h>
 #include <unistd.h>
 #include "database.h"
+#include "event.h"
 #include "handler.h"
 #include "config.h"
 #include "logger/logger.h"
-#include "view/view.h"
 #include "gui/gui.h"
+#include "utils.h"
+#include "openair_logo.h"
+
+int ue_id[65536];
+int next_ue_id;
 
 typedef struct {
   widget *pucch_pusch_iq_plot;
+  widget *ul_freq_estimate_ue_xy_plot;
+  widget *ul_time_estimate_ue_xy_plot;
+  widget *current_ue_label;
+  widget *current_ue_button;
+  widget *prev_ue_button;
+  widget *next_ue_button;
   logger *pucch_pusch_iq_logger;
+  logger *ul_freq_estimate_ue_logger;
+  logger *ul_time_estimate_ue_logger;
 } gnb_gui;
 
 typedef struct {
@@ -21,6 +34,7 @@ typedef struct {
   int nevents;
   pthread_mutex_t lock;
   gnb_gui *e;
+  int ue;                /* what UE is displayed in the UE specific views */
   void *database;
 } gnb_data;
 
@@ -69,34 +83,133 @@ static void *gui_thread(void *_g)
   return NULL;
 }
 
-static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database,
-    gnb_data *ed)
+static void set_current_ue(gui *g, gnb_data *e, int ue)
+{
+  char s[256];
+
+  sprintf(s, "[UE %d]  ", ue);
+  label_set_text(g, e->e->current_ue_label, s);
+
+  sprintf(s, "GNB_PHY_PUCCH_PUSCH_IQ [UE %d]", ue);
+  xy_plot_set_title(g, e->e->pucch_pusch_iq_plot, s);
+
+  sprintf(s, "UL channel estimation in frequency domain [UE %d]", ue);
+  xy_plot_set_title(g, e->e->ul_freq_estimate_ue_xy_plot, s);
+
+  sprintf(s, "UL channel estimation in time domain [UE %d]", ue);
+  xy_plot_set_title(g, e->e->ul_time_estimate_ue_xy_plot, s);
+}
+
+void reset_ue_ids(void)
+{
+  int i;
+  printf("resetting known UEs\n");
+  for (i = 0; i < 65536; i++) ue_id[i] = -1;
+  ue_id[65535] = 0;
+  ue_id[65534] = 1;     /* HACK: to be removed */
+  ue_id[2]     = 2;     /* this supposes RA RNTI = 2, very openair specific */
+  next_ue_id = 0;
+}
+
+static void click(void *private, gui *g, char *notification, widget *w, void *notification_data)
+{
+  int *d = notification_data;
+  int button = d[0];
+  gnb_data *ed = private;
+  gnb_gui *e = ed->e;
+  int ue = ed->ue;
+  int do_reset = 0;
+
+  if (button != 1) return;
+  if (w == e->prev_ue_button) { ue--; if (ue < 0) ue = 0; }
+  if (w == e->next_ue_button) ue++;
+  if (w == e->current_ue_button) do_reset = 1;
+
+  if (pthread_mutex_lock(&ed->lock)) abort();
+  if (do_reset) reset_ue_ids();
+  if (ue != ed->ue) {
+    set_current_ue(g, ed, ue);
+    ed->ue = ue;
+  }
+  if (pthread_mutex_unlock(&ed->lock)) abort();
+}
+
+static void gnb_main_gui(gnb_gui *e, gui *g, event_handler *h, void *database, gnb_data *ed)
 {
   widget *main_window;
   widget *top_container;
   widget *line;
+  widget *col;
+  widget *logo;
   widget *w;
+  widget *w2;
   logger *l;
   view *v;
 
-  main_window = new_toplevel_window(g, 500, 300, "gNB tracer");
-
+  main_window = new_toplevel_window(g, 1500, 230, "gNB tracer");
   top_container = new_container(g, VERTICAL);
   widget_add_child(g, main_window, top_container, -1);
 
   line = new_container(g, HORIZONTAL);
   widget_add_child(g, top_container, line, -1);
+  logo = new_image(g, openair_logo_png, openair_logo_png_len);
+
+  /* logo + prev/next UE buttons */
+  col = new_container(g, VERTICAL);
+  widget_add_child(g, col, logo, -1);
+  w = new_container(g, HORIZONTAL);
+  widget_add_child(g, col, w, -1);
+  w2 = new_label(g, "");
+  widget_add_child(g, w, w2, -1);
+  label_set_clickable(g, w2, 1);
+  e->current_ue_button = w2;
+  e->current_ue_label = w2;
+  w2 = new_label(g, "  [prev UE]  ");
+  widget_add_child(g, w, w2, -1);
+  label_set_clickable(g, w2, 1);
+  e->prev_ue_button = w2;
+  w2 = new_label(g, "  [next UE]  ");
+  widget_add_child(g, w, w2, -1);
+  label_set_clickable(g, w2, 1);
+  e->next_ue_button = w2;
+  widget_add_child(g, line, col, -1);
 
   /* PUCCH/PUSCH IQ data */
-  w = new_xy_plot(g, 55, 55, "", 50);
+  w = new_xy_plot(g, 200, 200, "", 10);
   e->pucch_pusch_iq_plot = w;
   widget_add_child(g, line, w, -1);
   xy_plot_set_range(g, w, -1000, 1000, -1000, 1000);
-  xy_plot_set_title(g, w, "rxdataF");
   l = new_iqlog_full(h, database, "GNB_PHY_PUCCH_PUSCH_IQ", "rxdataF");
   v = new_view_xy(300*12*14,10,g,w,new_color(g,"#000"),XY_FORCED_MODE);
   logger_add_view(l, v);
   e->pucch_pusch_iq_logger = l;
+
+  /* UL channel estimation in frequency domain */
+  w = new_xy_plot(g, 490, 200, "", 50);
+  e->ul_freq_estimate_ue_xy_plot = w;
+  widget_add_child(g, line, w, -1);
+  xy_plot_set_range(g, w, 0, 2048, -10, 80);
+  l = new_framelog(h, database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", "subframe", "chest_t");
+  framelog_set_update_only_at_sf9(l, 0);
+  v = new_view_xy(2048, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE);
+  logger_add_view(l, v);
+  e->ul_freq_estimate_ue_logger = l;
+
+  /* UL channel estimation in time domain */
+  w = new_xy_plot(g, 490, 200, "", 50);
+  e->ul_time_estimate_ue_xy_plot = w;
+  widget_add_child(g, line, w, -1);
+  xy_plot_set_range(g, w, 0, 2048, -10, 80);
+  l = new_framelog(h, database, "GNB_PHY_UL_TIME_CHANNEL_ESTIMATE", "subframe", "chest_t");
+  framelog_set_update_only_at_sf9(l, 0);
+  v = new_view_xy(2048, 10, g, w, new_color(g, "#0c0c72"), XY_LOOP_MODE);
+  logger_add_view(l, v);
+  e->ul_time_estimate_ue_logger = l;
+
+  set_current_ue(g, ed, ed->ue);
+  register_notifier(g, "click", e->current_ue_button, click, ed);
+  register_notifier(g, "click", e->prev_ue_button, click, ed);
+  register_notifier(g, "click", e->next_ue_button, click, ed);
 }
 
 int main(int n, char **v)
@@ -136,7 +249,11 @@ int main(int n, char **v)
   h = new_handler(database);
 
   on_off(database, "GNB_PHY_PUCCH_PUSCH_IQ", is_on, 1);
+  on_off(database, "GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE", is_on, 1);
+  on_off(database, "GNB_PHY_UL_TIME_CHANNEL_ESTIMATE", is_on, 1);
 
+  gnb_data.ue = 0;
+  gnb_data.e = &eg;
   gnb_data.database = database;
   gnb_data.socket = -1;
   gnb_data.is_on = is_on;
diff --git a/common/utils/nr/nr_common.h b/common/utils/nr/nr_common.h
index 6dd0965e10a8f539e47cb26e3ec614f5cdfa3ba3..882f99338c3533c785a567adbaafe0db88bf843d 100644
--- a/common/utils/nr/nr_common.h
+++ b/common/utils/nr/nr_common.h
@@ -80,6 +80,7 @@ void SLIV2SL(int SLIV,int *S,int *L);
 int get_dmrs_port(int nl, uint16_t dmrs_ports);
 uint16_t SL_to_bitmap(int startSymbolIndex, int nrOfSymbols);
 int get_nb_periods_per_frame(uint8_t tdd_period);
+long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS);
 
 #define CEILIDIV(a,b) ((a+b-1)/b)
 #define ROUNDIDIV(a,b) (((a<<1)+b)/(b<<1))
diff --git a/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h b/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h
index a275272e809ebd26eabfb98d9caf6a24a78dcde2..ed8b5e23013b6341175743177f58cb7bd7179b7f 100644
--- a/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h
+++ b/common/utils/telnetsrv/telnetsrv_cpumeasur_def.h
@@ -106,12 +106,13 @@
     {"phy_proc",          &(UE->phy_proc[0]),0,RX_NB_TH},\
     {"phy_proc_rx",       &(UE-> phy_proc_rx[0]),0,RX_NB_TH},\
     {"phy_proc_tx",       &(UE->phy_proc_tx),0,1},\
+    {"ue_ul_indication_stats",       &(UE->ue_ul_indication_stats),0,1},\
     {"ofdm_mod_stats",       &(UE->ofdm_mod_stats),0,1},\
     {"ulsch_encoding_stats",       &(UE->ulsch_encoding_stats),0,1},\
     {"ulsch_modulation_stats",       &(UE->ulsch_modulation_stats),0,1},\
     {"ulsch_segmentation_stats",       &(UE->ulsch_segmentation_stats),0,1},\
     {"ulsch_rate_matching_stats",       &(UE->ulsch_rate_matching_stats),0,1},\
-    {"ulsch_turbo_encoding_stats",       &(UE->ulsch_turbo_encoding_stats),0,1},\
+    {"ulsch_ldpc_encoding_stats",       &(UE->ulsch_ldpc_encoding_stats),0,1},\
     {"ulsch_interleaving_stats",       &(UE->ulsch_interleaving_stats),0,1},\
     {"ulsch_multiplexing_stats",       &(UE->ulsch_multiplexing_stats),0,1},\
     {"generic_stat",       &(UE->generic_stat),0,1},\
@@ -123,12 +124,12 @@
     {"dlsch_f...timation_stats",       &(UE->dlsch_freq_offset_estimation_stats),0,1},\
     {"dlsch_demodulation_stats",       &(UE->dlsch_demodulation_stats),0,1},\
     {"dlsch_rate_unmatching_stats",       &(UE->dlsch_rate_unmatching_stats),0,1},\
-    {"dlsch_turbo_decoding_stats",       &(UE->dlsch_turbo_decoding_stats),0,1},\
+    {"dlsch_ldpc_decoding_stats",       &(UE->dlsch_ldpc_decoding_stats),0,1},\
     {"dlsch_deinterleaving_stats",       &(UE->dlsch_deinterleaving_stats),0,1},\
     {"dlsch_llr_stats",       &(UE->dlsch_llr_stats),0,1},\
     {"dlsch_unscrambling_stats",       &(UE->dlsch_unscrambling_stats),0,1},\
     {"dlsch_rate_matching_stats",       &(UE->dlsch_rate_matching_stats),0,1},\
-    {"dlsch_turbo_encoding_stats",       &(UE->dlsch_turbo_encoding_stats),0,1},\
+    {"dlsch_ldpc_encoding_stats",       &(UE->dlsch_ldpc_encoding_stats),0,1},\
     {"dlsch_interleaving_stats",       &(UE->dlsch_interleaving_stats),0,1},\
     {"dlsch_tc_init_stats",       &(UE->dlsch_tc_init_stats),0,1},\
     {"dlsch_tc_alpha_stats",       &(UE->dlsch_tc_alpha_stats),0,1},\
@@ -146,6 +147,7 @@
     {"ue_front_end_stat",       &(UE->ue_front_end_stat[0]),0,RX_NB_TH},\
     {"ue_front_end_per_slot_stat",      &(UE->ue_front_end_per_slot_stat[0][0]),0,RX_NB_TH,LTE_SLOTS_PER_SUBFRAME},\
     {"pdcch_procedures_stat",       &(UE->pdcch_procedures_stat[0]),0,RX_NB_TH},\
+    {"rx_pdsch_stats",              &(UE->rx_pdsch_stats), 0, 1}, \
     {"pdsch_procedures_stat",       &(UE->pdsch_procedures_stat[0]),0,RX_NB_TH},\
     {"pdsch_procedures_per_slot_stat",  &(UE->pdsch_procedures_per_slot_stat[0][0]),0,RX_NB_TH,LTE_SLOTS_PER_SUBFRAME},\
     {"dlsch_procedures_stat",       &(UE->dlsch_procedures_stat[0]),0,RX_NB_TH},\
diff --git a/doc/FEATURE_SET.md b/doc/FEATURE_SET.md
index 2fc7115193c66dc59f843f2b0eab87413489269e..eaa691d6ef07142ba399cb1e308b7b9926183c3a 100644
--- a/doc/FEATURE_SET.md
+++ b/doc/FEATURE_SET.md
@@ -294,6 +294,10 @@ The following features are valid for the gNB and the 5G-NR UE.
 *  NR-PUCCH 
    - Format 0 (2 bits, for ACK/NACK and SR)
    - Format 2 (up to 11 bits, mainly for CSI feedback)
+*  NR-SRS
+    - SRS signal reception
+    - Channel estimation (with T tracer real time monitoring)
+    - Power noise estimation
 *  NR-PRACH
    - Formats 0,1,2,3, A1-A3, B1-B3
 *  Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported)
@@ -322,6 +326,8 @@ The following features are valid for the gNB and the 5G-NR UE.
   - phy-test scheduler (fixed allocation)
   - regular scheduler with dynamic allocation
   - HARQ procedures for uplink
+- Scheduler procedures for SRS reception
+  - Periodic SRS reception
 - MAC procedures to handle CSI measurement report
   - evalution of RSRP report
   - evaluation of CQI report
@@ -433,11 +439,12 @@ The following features are valid for the gNB and the 5G-NR UE.
    - Format 0 (2 bits for ACK/NACK and SR)
    - Format 2 (up to 64 bits, mainly for CSI feedback)
    - Format 1, 3 and 4 present but old code never dested (need restructuring before verification)
-*  NR-PRACH
+* NR-SRS
+    - Generation of sequence at PHY
+    - SRS signal transmission
+* NR-PRACH
    - Formats 0,1,2,3, A1-A3, B1-B3
-*  NR-SRS
-   - Old code never dested (need restructuring before verification)
-*  SS-RSRP
+* SS-RSRP
    - RSRP measured on synchronization SSB (ok only for single SSB)
 *  Highly efficient 3GPP compliant LDPC encoder and decoder (BG1 and BG2 are supported)
 *  Highly efficient 3GPP compliant polar encoder and decoder
@@ -452,21 +459,21 @@ The following features are valid for the gNB and the 5G-NR UE.
 ## NR UE Higher Layers ##
 
 **UE MAC**
-*  Minimum system information (MSI)
+* Minimum system information (MSI)
    - MIB processing
    - Scheduling of system information block 1 (SIB1) reception
-*  Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY)
+* Random access procedure (needs improvement, there is still not a clear separation between MAC and PHY)
    - Mapping SSBs to multiple ROs
    - Scheduling of PRACH
    - Processing of RAR
    - Transmission and re-transmission of Msg3
    - Msg4 and contention resolution
-*  DCI processing
+* DCI processing
    - format 10 (RA-RNTI, C-RNTI, SI-RNTI, TC-RNTI)
    - format 00 (C-RNTI, TC-RNTI)
    - format 11 (C-RNTI)
    - format 01 (C-RNTI)
-*  UCI processing
+* UCI processing
    - ACK/NACK processing
    - Triggering periodic SR
    - CSI measurement reporting (SSB RSRP only)
@@ -475,6 +482,8 @@ The following features are valid for the gNB and the 5G-NR UE.
    - HARQ procedures
 * ULSCH scheduler
    - Configuration of fapi PDU according to DCI
+* Scheduler procedures for SRS transmission
+   - Periodic SRS transmission
 
 
 **UE RLC**
diff --git a/executables/nr-ue.c b/executables/nr-ue.c
index 90d3d2cd1c88f00105a50f09e036d915d8039b1e..0b5ee675331438402e4602cdfc5767766c80726c 100644
--- a/executables/nr-ue.c
+++ b/executables/nr-ue.c
@@ -104,6 +104,49 @@ queue_t nr_rach_ind_queue;
 
 static void *NRUE_phy_stub_standalone_pnf_task(void *arg);
 
+static int dump_L1_UE_meas_stats(PHY_VARS_NR_UE *ue, char *output, int max_len)
+{
+  int stroff = 0;
+  stroff += print_meas_log(&ue->phy_proc_tx, "L1 TX processing", NULL, NULL, output);
+  stroff += print_meas_log(&ue->ulsch_encoding_stats, "ULSCH encoding", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->phy_proc_rx[0], "L1 RX processing t0", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->phy_proc_rx[1], "L1 RX processing t1", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->ue_ul_indication_stats, "UL Indication", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->rx_pdsch_stats, "PDSCH receiver", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->dlsch_decoding_stats[0], "PDSCH decoding t0", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->dlsch_decoding_stats[1], "PDSCH decoding t1", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->dlsch_deinterleaving_stats, " -> Deinterleive", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->dlsch_rate_unmatching_stats, " -> Rate Unmatch", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->dlsch_ldpc_decoding_stats, " ->  LDPC Decode", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->dlsch_unscrambling_stats, "PDSCH unscrambling", NULL, NULL, output + stroff);
+  stroff += print_meas_log(&ue->dlsch_rx_pdcch_stats, "PDCCH handling", NULL, NULL, output + stroff);
+  return stroff;
+}
+
+static void *nrL1_UE_stats_thread(void *param)
+{
+  PHY_VARS_NR_UE *ue = (PHY_VARS_NR_UE *) param;
+  const int max_len = 16384;
+  char output[max_len];
+  char filename[30];
+  snprintf(filename, 29, "nrL1_UE_stats-%d.log", ue->Mod_id);
+  filename[29] = 0;
+  FILE *fd = fopen(filename, "w");
+  AssertFatal(fd != NULL, "Cannot open %s\n", filename);
+
+  while (!oai_exit) {
+    sleep(1);
+    const int len = dump_L1_UE_meas_stats(ue, output, max_len);
+    AssertFatal(len < max_len, "exceeded length\n");
+    fwrite(output, len + 1, 1, fd); // + 1 for terminating NULL byte
+    fflush(fd);
+    fseek(fd, 0, SEEK_SET);
+  }
+  fclose(fd);
+
+  return NULL;
+}
+
 void init_nr_ue_vars(PHY_VARS_NR_UE *ue,
                      uint8_t UE_id,
                      uint8_t abstraction_flag)
@@ -593,7 +636,7 @@ static void UE_synch(void *arg) {
       uint64_t dl_carrier, ul_carrier;
       nr_get_carrier_frequencies(UE, &dl_carrier, &ul_carrier);
 
-      if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa, get_nrUE_params()->nr_dlsch_parallel) == 0) {
+      if (nr_initial_sync(&syncD->proc, UE, 2, get_softmodem_params()->sa) == 0) {
         freq_offset = UE->common_vars.freq_offset; // frequency offset computed with pss in initial sync
         hw_slot_offset = ((UE->rx_offset<<1) / UE->frame_parms.samples_per_subframe * UE->frame_parms.slots_per_subframe) +
                          round((float)((UE->rx_offset<<1) % UE->frame_parms.samples_per_subframe)/UE->frame_parms.samples_per_slot0);
@@ -666,6 +709,7 @@ void processSlotTX(void *arg) {
     // trigger L2 to run ue_scheduler thru IF module
     // [TODO] mapping right after NR initial sync
     if(UE->if_inst != NULL && UE->if_inst->ul_indication != NULL) {
+      start_meas(&UE->ue_ul_indication_stats);
       nr_uplink_indication_t ul_indication;
       memset((void*)&ul_indication, 0, sizeof(ul_indication));
 
@@ -680,6 +724,7 @@ void processSlotTX(void *arg) {
       ul_indication.ue_sched_mode = rxtxD->ue_sched_mode;
 
       UE->if_inst->ul_indication(&ul_indication);
+      stop_meas(&UE->ue_ul_indication_stats);
     }
 
     if ((UE->mode != loop_through_memory) && (rxtxD->ue_sched_mode != NOT_PUSCH)) {
@@ -1151,6 +1196,8 @@ void init_NR_UE_threads(int nb_inst) {
 
     LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
     threadCreate(&threads[inst], UE_thread, (void *)UE, "UEthread", -1, OAI_PRIORITY_RT_MAX);
+    pthread_t stat_pthread;
+    threadCreate(&stat_pthread, nrL1_UE_stats_thread, UE, "L1_UE_stats", -1, OAI_PRIORITY_RT_LOW);
   }
 }
 
diff --git a/executables/nr-uesoftmodem.c b/executables/nr-uesoftmodem.c
index ddbbbdf52c1eccb9c7a0a4b02ac2818375d61a8a..7663e9ebd8da5d439ae7fb35a8600dfa5ee34aca 100644
--- a/executables/nr-uesoftmodem.c
+++ b/executables/nr-uesoftmodem.c
@@ -422,11 +422,11 @@ int main( int argc, char **argv ) {
   get_options (); //Command-line options specific for NRUE
 
   get_common_options(SOFTMODEM_5GUE_BIT);
-  init_tpools(nrUE_params.nr_dlsch_parallel);
   CONFIG_CLEARRTFLAG(CONFIG_NOEXITONHELP);
 #if T_TRACER
   T_Config_Init();
 #endif
+  init_tpools(nrUE_params.nr_dlsch_parallel);
   //randominit (0);
   set_taus_seed (0);
 
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 4ef7a73152f96a905b0770b89174f0e8fbd91636..3b429a5e84e30edd094246b44bf2b65b5e15fff7 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
@@ -339,7 +339,33 @@ typedef struct
 } nfapi_nr_ue_pusch_pdu_t;
 
 typedef struct {
+} fapi_nr_ul_srs_parms_v4;
 
+typedef struct {
+  uint16_t rnti;                      // UE RNTI, Value: 1->65535
+  uint32_t handle;                    // An opaque handling returned in the SRS.indication
+  uint16_t bwp_size;                  // Bandwidth part size [3GPP TS 38.213, sec 12]. Number of contiguous PRBs allocated to the BWP, Value: 1->275
+  uint16_t bwp_start;                 // Bandwidth part start RB index from reference CRB [3GPP TS 38.213, sec 12], Value: 0->274
+  uint8_t subcarrier_spacing;         // subcarrierSpacing [3GPP TS 38.211, sec 4.2], Value:0->4
+  uint8_t cyclic_prefix;              // Cyclic prefix type [3GPP TS 38.211, sec 4.2], 0: Normal; 1: Extended
+  uint8_t num_ant_ports;              // Number of antenna ports N_SRS_ap [3GPP TS 38.211, Sec 6.4.1.4.1], Value: 0 = 1 port, 1 = 2 ports, 2 = 4 ports
+  uint8_t num_symbols;                // Number of symbols N_SRS_symb [3GPP TS 38.211, Sec 6.4.1.4.1], Value: 0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols
+  uint8_t num_repetitions;            // Repetition factor R [3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0 = 1, 1 = 2, 2 = 4
+  uint8_t time_start_position;        // Starting position in the time domain l_0 [3GPP TS 38.211, Sec 6.4.1.4.1], Note: the MAC undertakes the translation from startPosition to l_0, Value: 0 --> 13
+  uint8_t config_index;               // SRS bandwidth config index C_SRS [3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0 --> 63
+  uint16_t sequence_id;               // SRS sequence ID n_SRS_ID [3GPP TS 38.211, Sec 6.4.1.4.2], Value: 0 --> 1023
+  uint8_t bandwidth_index;            // SRS bandwidth index B_SRS [3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0 --> 3
+  uint8_t comb_size;                  // Transmission comb size K_TC [3GPP TS 38.211, Sec 6.4.1.4.2], Value: 0 = comb size 2, 1 = comb size 4, 2 = comb size 8 (Rel16)
+  uint8_t comb_offset;                // Transmission comb offset K'_TC[3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0 --> 1 (combSize = 0), Value: 0 --> 3 (combSize = 1), Value: 0 --> 7 (combSize = 2)
+  uint8_t cyclic_shift;               // Cyclic shift n_CS_SRS [3GPP TS 38.211, Sec 6.4.1.4.2], Value: 0 --> 7 (combSize = 0), Value: 0 --> 11 (combSize = 1), Value: 0 --> 5 (combSize = 2)
+  uint8_t frequency_position;         // Frequency domain position n_RRC [3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0 --> 67
+  uint16_t frequency_shift;           // Frequency domain shift n_shift [3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0 --> 268
+  uint8_t frequency_hopping;          // Frequency hopping b_hop [3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0 --> 3
+  uint8_t group_or_sequence_hopping;  // Group or sequence hopping configuration (RRC parameter groupOrSequenceHopping in SRSResource IE), Value: 0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping
+  uint8_t resource_type;              // Type of SRS resource allocation [3GPP TS 38.211, Sec 6.4.1.4.3], Value: 0: aperiodic, 1: semi-persistent, 2: periodic
+  uint16_t t_srs;                     // SRS-Periodicity in slots [3GPP TS 38.211, Sec 6.4.1.4.4], Value: 1,2,3,4,5,8,10,16,20,32,40,64,80,160,320,640,1280,2560
+  uint16_t t_offset;                  // Slot offset value [3GPP TS 38.211, Sec 6.4.1.4.3], Value:0->2559
+  nfapi_nr_ue_ul_beamforming_t beamforming;
 } fapi_nr_ul_config_srs_pdu;
 
 typedef struct {
@@ -348,7 +374,7 @@ typedef struct {
     fapi_nr_ul_config_prach_pdu prach_config_pdu;
     fapi_nr_ul_config_pucch_pdu pucch_config_pdu;
     nfapi_nr_ue_pusch_pdu_t     pusch_config_pdu;
-    fapi_nr_ul_config_srs_pdu srs_config_pdu;
+    fapi_nr_ul_config_srs_pdu   srs_config_pdu;
   };
 } fapi_nr_ul_config_request_pdu_t;
 
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
index 9681c1d19bb9828f7660e3757f9a6a48f44983b6..c3a173758cc30cceb688775293039799780b6604 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface_scf.h
@@ -1312,7 +1312,7 @@ typedef struct
   uint8_t  comb_offset;//Transmission comb offset 𝑘 ̄ TC [TS38.211, Sec 6.4.1.4.3] Value: 0 → 1 (combSize = 0) Value: 0 → 3 (combSize = 1)
   uint8_t  cyclic_shift;
   uint8_t  frequency_position;
-  uint8_t  frequency_shift;
+  uint16_t frequency_shift;
   uint8_t  frequency_hopping;
   uint8_t  group_or_sequence_hopping;//Group or sequence hopping configuration (RRC parameter groupOrSequenceHopping in SRS-Resource
   uint8_t  resource_type;//Type of SRS resource allocation
diff --git a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
index adc6d6e384124b1b3ebcf97cad27f2d1d52e71cf..0e43c803e75a26f31632e8c605f346c3d4775f82 100644
--- a/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
+++ b/nfapi/open-nFAPI/nfapi/src/nfapi_p7.c
@@ -4548,7 +4548,7 @@ static uint8_t unpack_ul_tti_request_srs_pdu(void *tlv, uint8_t **ppReadPackedMs
           pull8(ppReadPackedMsg, &srs_pdu->comb_offset, end) &&
           pull8(ppReadPackedMsg, &srs_pdu->cyclic_shift, end) &&
           pull8(ppReadPackedMsg, &srs_pdu->frequency_position, end) &&
-          pull8(ppReadPackedMsg, &srs_pdu->frequency_shift, end) &&
+          pull16(ppReadPackedMsg, &srs_pdu->frequency_shift, end) &&
           pull8(ppReadPackedMsg, &srs_pdu->frequency_hopping, end) &&
           pull8(ppReadPackedMsg, &srs_pdu->group_or_sequence_hopping, end) &&
           pull8(ppReadPackedMsg, &srs_pdu->resource_type, end) &&
diff --git a/openair1/PHY/CODING/nr_rate_matching.c b/openair1/PHY/CODING/nr_rate_matching.c
index ae49f9a4a7cb82d74ac320ab999458a970056767..29cba0a55729b2b7347a4a8b8324afeeb9a10f43 100644
--- a/openair1/PHY/CODING/nr_rate_matching.c
+++ b/openair1/PHY/CODING/nr_rate_matching.c
@@ -405,7 +405,7 @@ int nr_rate_matching_ldpc(uint8_t Ilbrm,
   ind = (index_k0[BG-1][rvidx]*Ncb/N)*Z;
 
 #ifdef RM_DEBUG
-  printf("nr_rate_matching_ldpc: E %d, F %d, Foffset %d, k0 %d, Ncb %d, rvidx %d\n", E, F, Foffset,ind, Ncb, rvidx);
+  printf("nr_rate_matching_ldpc: E %d, F %d, Foffset %d, k0 %d, Ncb %d, rvidx %d, Ilbrm %d\n", E, F, Foffset,ind, Ncb, rvidx, Ilbrm);
 #endif
 
   if (Foffset > E) {
@@ -502,7 +502,7 @@ int nr_rate_matching_ldpc_rx(uint8_t Ilbrm,
   }
 
 #ifdef RM_DEBUG
-  printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d\n", clear, E, ind, Ncb, rvidx);
+  printf("nr_rate_matching_ldpc_rx: Clear %d, E %d, k0 %d, Ncb %d, rvidx %d, Ilbrm %d\n", clear, E, ind, Ncb, rvidx, Ilbrm);
 #endif
 
   if (clear==1) memset(w,0,Ncb*sizeof(int16_t));
diff --git a/openair1/PHY/INIT/nr_init.c b/openair1/PHY/INIT/nr_init.c
index 9e1e472fd69bcc8bf9352c0053a43d8724c5ff64..3bf450703cddc6384adcb2bc91035735f7f7f50d 100644
--- a/openair1/PHY/INIT/nr_init.c
+++ b/openair1/PHY/INIT/nr_init.c
@@ -195,6 +195,26 @@ int phy_init_nr_gNB(PHY_VARS_gNB *gNB,
 
   nr_init_csi_rs(gNB, cfg->cell_config.phy_cell_id.value);
 
+  for (int id=0; id<NUMBER_OF_NR_SRS_MAX; id++) {
+    gNB->nr_srs_info[id] = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
+    gNB->nr_srs_info[id]->srs_generated_signal = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+    gNB->nr_srs_info[id]->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t));
+    gNB->nr_srs_info[id]->srs_received_signal = (int32_t **)malloc16(Prx*sizeof(int32_t*));
+    gNB->nr_srs_info[id]->srs_ls_estimated_channel = (int32_t **)malloc16(Prx*sizeof(int32_t*));
+    gNB->nr_srs_info[id]->srs_estimated_channel_freq = (int32_t **)malloc16(Prx*sizeof(int32_t*));
+    gNB->nr_srs_info[id]->srs_estimated_channel_time = (int32_t **)malloc16(Prx*sizeof(int32_t*));
+    gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted = (int32_t **)malloc16(Prx*sizeof(int32_t*));
+    for (i=0;i<Prx;i++){
+      gNB->nr_srs_info[id]->srs_received_signal[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      gNB->nr_srs_info[id]->srs_ls_estimated_channel[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      gNB->nr_srs_info[id]->srs_estimated_channel_freq[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      gNB->nr_srs_info[id]->srs_estimated_channel_time[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      gNB->nr_srs_info[id]->srs_estimated_channel_time_shifted[i] = (int32_t*)malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+    }
+  }
+
+  generate_ul_reference_signal_sequences(SHRT_MAX);
+
   /* Generate low PAPR type 1 sequences for PUSCH DMRS, these are used if transform precoding is enabled.  */
   generate_lowpapr_typ1_refsig_sequences(SHRT_MAX);
 
@@ -546,6 +566,12 @@ void init_nr_transport(PHY_VARS_gNB *gNB) {
     AssertFatal(gNB->pucch[i]!=NULL,"Can't initialize pucch %d \n", i);
   }
 
+  for (int i=0; i<NUMBER_OF_NR_SRS_MAX; i++) {
+    LOG_I(PHY,"Allocating Transport Channel Buffers for SRS %d/%d\n",i,NUMBER_OF_NR_SRS_MAX);
+    gNB->srs[i] = new_gNB_srs();
+    AssertFatal(gNB->srs[i]!=NULL,"Can't initialize srs %d \n", i);
+  }
+
   for (int i=0; i<gNB->number_of_nr_ulsch_max; i++) {
 
     LOG_I(PHY,"Allocating Transport Channel Buffer for ULSCH  %d/%d\n",i,gNB->number_of_nr_ulsch_max);
diff --git a/openair1/PHY/INIT/nr_init_ue.c b/openair1/PHY/INIT/nr_init_ue.c
index a516f20165ad4eb5781f8c5f2652d0b067cb24e6..b571afe41631da5a307b3e31cce8fd5067cef195 100644
--- a/openair1/PHY/INIT/nr_init_ue.c
+++ b/openair1/PHY/INIT/nr_init_ue.c
@@ -128,6 +128,8 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue,
   NR_UE_COMMON *const common_vars        = &ue->common_vars;
   NR_UE_PBCH  **const pbch_vars          = ue->pbch_vars;
   NR_UE_PRACH **const prach_vars         = ue->prach_vars;
+  NR_UE_SRS **const srs_vars             = ue->srs_vars;
+
   int i,j,k,l,slot,symb,q;
   int gNB_id;
   int th_id;
@@ -310,6 +312,24 @@ int init_nr_ue_signal(PHY_VARS_NR_UE *ue,
 
     prach_vars[gNB_id] = (NR_UE_PRACH *)malloc16_clear(sizeof(NR_UE_PRACH));
     pbch_vars[gNB_id] = (NR_UE_PBCH *)malloc16_clear(sizeof(NR_UE_PBCH));
+    srs_vars[gNB_id] = (NR_UE_SRS *)malloc16_clear(sizeof(NR_UE_SRS));
+
+    srs_vars[gNB_id]->active = false;
+    ue->nr_srs_info = (nr_srs_info_t *)malloc16_clear(sizeof(nr_srs_info_t));
+    ue->nr_srs_info->srs_generated_signal = (int32_t *) malloc16_clear( (2*(fp->samples_per_frame)+2048)*sizeof(int32_t) );
+    ue->nr_srs_info->noise_power = (uint32_t*)malloc16_clear(sizeof(uint32_t));
+    ue->nr_srs_info->srs_received_signal = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
+    ue->nr_srs_info->srs_ls_estimated_channel = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
+    ue->nr_srs_info->srs_estimated_channel_freq = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
+    ue->nr_srs_info->srs_estimated_channel_time = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
+    ue->nr_srs_info->srs_estimated_channel_time_shifted = (int32_t **)malloc16( fp->nb_antennas_rx*sizeof(int32_t *) );
+    for (i=0; i<fp->nb_antennas_rx; i++) {
+      ue->nr_srs_info->srs_received_signal[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      ue->nr_srs_info->srs_ls_estimated_channel[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      ue->nr_srs_info->srs_estimated_channel_freq[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      ue->nr_srs_info->srs_estimated_channel_time[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+      ue->nr_srs_info->srs_estimated_channel_time_shifted[i] = (int32_t *) malloc16_clear(fp->ofdm_symbol_size*MAX_NUM_NR_SRS_SYMBOLS*sizeof(int32_t));
+    }
 
     if (abstraction_flag == 0) {
       for (th_id=0; th_id<RX_NB_TH_MAX; th_id++) {
@@ -522,6 +542,7 @@ void init_N_TA_offset(PHY_VARS_NR_UE *ue){
 void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
   NR_DL_FRAME_PARMS *frame_parms = &ue->frame_parms;
   crcTableInit();
+  init_scrambling_luts();
   load_dftslib();
   init_context_synchro_nr(frame_parms);
   generate_ul_reference_signal_sequences(SHRT_MAX);
@@ -533,6 +554,5 @@ void phy_init_nr_top(PHY_VARS_NR_UE *ue) {
   //generate_16qam_table();
   //generate_RIV_tables();
   //init_unscrambling_lut();
-  //init_scrambling_lut();
   //set_taus_seed(1328);
 }
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
index 1f164748bf53d5936044e16c0169c9e6fa6aaf86..9aaba7fb66789bcda3d29103ff383a4aa944c40d 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_channel_estimation.c
@@ -36,10 +36,46 @@
 
 //#define DEBUG_CH
 //#define DEBUG_PUSCH
+//#define SRS_DEBUG
 
 #define NO_INTERP 1
 #define dBc(x,y) (dB_fixed(((int32_t)(x))*(x) + ((int32_t)(y))*(y)))
 
+void freq2time(uint16_t ofdm_symbol_size,
+               int16_t *freq_signal,
+               int16_t *time_signal) {
+
+  switch (ofdm_symbol_size) {
+    case 128:
+      idft(IDFT_128, freq_signal, time_signal, 1);
+      break;
+    case 256:
+      idft(IDFT_256, freq_signal, time_signal, 1);
+      break;
+    case 512:
+      idft(IDFT_512, freq_signal, time_signal, 1);
+      break;
+    case 1024:
+      idft(IDFT_1024, freq_signal, time_signal, 1);
+      break;
+    case 1536:
+      idft(IDFT_1536, freq_signal, time_signal, 1);
+      break;
+    case 2048:
+      idft(IDFT_2048, freq_signal, time_signal, 1);
+      break;
+    case 4096:
+      idft(IDFT_4096, freq_signal, time_signal, 1);
+      break;
+    case 8192:
+      idft(IDFT_8192, freq_signal, time_signal, 1);
+      break;
+    default:
+      idft(IDFT_512, freq_signal, time_signal, 1);
+      break;
+  }
+}
+
 int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
                                 unsigned char Ns,
                                 unsigned short p,
@@ -273,10 +309,10 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
                                          ch,
                                          ul_ch,
                                          8);
-                                         
+
       //for (int i= 0; i<16; i++)
       //printf("ul_ch addr %p %d\n", ul_ch+i, *(ul_ch+i));
-      
+
       pil += 2;
       re_offset = (re_offset+2) % gNB->frame_parms.ofdm_symbol_size;
       rxF   = (int16_t *)&rxdataF[aarx][(soffset+symbol_offset+nushift+re_offset)];
@@ -898,63 +934,9 @@ int nr_pusch_channel_estimation(PHY_VARS_gNB *gNB,
 #endif
 
     // Convert to time domain
-
-    switch (gNB->frame_parms.ofdm_symbol_size) {
-        case 128:
-          idft(IDFT_128,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        case 256:
-          idft(IDFT_256,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        case 512:
-          idft(IDFT_512,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        case 1024:
-          idft(IDFT_1024,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        case 1536:
-          idft(IDFT_1536,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        case 2048:
-          idft(IDFT_2048,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        case 4096:
-          idft(IDFT_4096,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        case 8192:
-          idft(IDFT_8192,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-
-        default:
-          idft(IDFT_512,(int16_t*) &ul_ch_estimates[aarx][symbol_offset],
-                 (int16_t*) ul_ch_estimates_time[aarx],
-                 1);
-          break;
-      }
-
+    freq2time(gNB->frame_parms.ofdm_symbol_size,
+              (int16_t*) &ul_ch_estimates[aarx][symbol_offset],
+              (int16_t*) ul_ch_estimates_time[aarx]);
   }
 
 #ifdef DEBUG_CH
@@ -1091,3 +1073,178 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
     }// last symbol check
   }//Antenna loop
 }
+
+uint32_t calc_power(uint16_t *x, uint32_t size) {
+  uint64_t sum_x = 0;
+  uint64_t sum_x2 = 0;
+  for(int k = 0; k<size; k++) {
+    sum_x = sum_x + x[k];
+    sum_x2 = sum_x2 + x[k]*x[k];
+  }
+  return sum_x2/size - (sum_x/size)*(sum_x/size);
+}
+
+int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
+                              int frame,
+                              int slot,
+                              nfapi_nr_srs_pdu_t *srs_pdu,
+                              nr_srs_info_t *nr_srs_info,
+                              int32_t *srs_generated_signal,
+                              int32_t **srs_received_signal,
+                              int32_t **srs_estimated_channel_freq,
+                              int32_t **srs_estimated_channel_time,
+                              int32_t **srs_estimated_channel_time_shifted,
+                              uint32_t *noise_power) {
+
+  if(nr_srs_info->sc_list_length == 0) {
+    LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot);
+    return -1;
+  }
+
+  NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
+  int32_t **srs_ls_estimated_channel = nr_srs_info->srs_ls_estimated_channel;
+
+  uint16_t noise_real[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
+  uint16_t noise_imag[frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length];
+
+  int16_t ls_estimated[2];
+
+  for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
+
+    memset(srs_ls_estimated_channel[ant], 0, frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)*sizeof(int32_t));
+    memset(srs_estimated_channel_freq[ant], 0, frame_parms->ofdm_symbol_size*(1<<srs_pdu->num_symbols)*sizeof(int32_t));
+
+    int16_t *srs_estimated_channel16 = (int16_t *)&srs_estimated_channel_freq[ant][nr_srs_info->sc_list[0]];
+
+    for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
+
+      int16_t generated_real = srs_generated_signal[nr_srs_info->sc_list[sc_idx]] & 0xFFFF;
+      int16_t generated_imag = (srs_generated_signal[nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF;
+
+      int16_t received_real = srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] & 0xFFFF;
+      int16_t received_imag = (srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] >> 16) & 0xFFFF;
+
+      // We know that nr_srs_info->srs_generated_signal_bits bits are enough to represent the generated_real and generated_imag.
+      // So we only need a nr_srs_info->srs_generated_signal_bits shift to ensure that the result fits into 16 bits.
+      ls_estimated[0] = (int16_t)(((int32_t)generated_real*received_real + (int32_t)generated_imag*received_imag)>>nr_srs_info->srs_generated_signal_bits);
+      ls_estimated[1] = (int16_t)(((int32_t)generated_real*received_imag - (int32_t)generated_imag*received_real)>>nr_srs_info->srs_generated_signal_bits);
+      srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]] = ls_estimated[0] + (((int32_t)ls_estimated[1] << 16) & 0xFFFF0000);
+
+      // Channel interpolation
+      if(srs_pdu->comb_size == 0) {
+        if(sc_idx == 0) { // First subcarrier case
+          // filt8_start is {12288,8192,4096,0,0,0,0,0}
+          multadd_real_vector_complex_scalar(filt8_start, ls_estimated, srs_estimated_channel16, 8);
+        } else if(nr_srs_info->sc_list[sc_idx] < nr_srs_info->sc_list[sc_idx - 1]) { // Start of OFDM symbol case
+          // filt8_start is {12288,8192,4096,0,0,0,0,0}
+          srs_estimated_channel16 = (int16_t *)&srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx + 2]] - sizeof(uint64_t);
+          multadd_real_vector_complex_scalar(filt8_start, ls_estimated, srs_estimated_channel16, 8);
+        } else if((sc_idx < (nr_srs_info->sc_list_length - 1) && nr_srs_info->sc_list[sc_idx + 1] < nr_srs_info->sc_list[sc_idx])
+                    || (sc_idx == (nr_srs_info->sc_list_length - 1))) { // End of OFDM symbol or last subcarrier cases
+          // filt8_end is {4096,8192,12288,16384,0,0,0,0}
+          multadd_real_vector_complex_scalar(filt8_end, ls_estimated, srs_estimated_channel16, 8);
+        } else if(sc_idx%2 == 1) { // 1st middle case
+          // filt8_middle2 is {4096,8192,8192,8192,4096,0,0,0}
+          multadd_real_vector_complex_scalar(filt8_middle2, ls_estimated, srs_estimated_channel16, 8);
+        } else if(sc_idx%2 == 0) { // 2nd middle case
+          // filt8_middle4 is {0,0,4096,8192,8192,8192,4096,0}
+          multadd_real_vector_complex_scalar(filt8_middle4, ls_estimated, srs_estimated_channel16, 8);
+          srs_estimated_channel16 = (int16_t *)&srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]];
+        }
+      } else {
+        if(sc_idx == 0) { // First subcarrier case
+          // filt16_start is {12288,8192,8192,8192,4096,0,0,0,0,0,0,0,0,0,0,0}
+          multadd_real_vector_complex_scalar(filt16_start, ls_estimated, srs_estimated_channel16, 16);
+        } else if(nr_srs_info->sc_list[sc_idx] < nr_srs_info->sc_list[sc_idx - 1]) { // Start of OFDM symbol case
+          srs_estimated_channel16 = (int16_t *)&srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx + 1]] - sizeof(uint64_t);
+          // filt16_start is {12288,8192,8192,8192,4096,0,0,0,0,0,0,0,0,0,0,0}
+          multadd_real_vector_complex_scalar(filt16_start, ls_estimated, srs_estimated_channel16, 16);
+        } else if((sc_idx < (nr_srs_info->sc_list_length - 1) && nr_srs_info->sc_list[sc_idx + 1] < nr_srs_info->sc_list[sc_idx])
+                  || (sc_idx == (nr_srs_info->sc_list_length - 1))) { // End of OFDM symbol or last subcarrier cases
+          // filt16_end is {4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0}
+          multadd_real_vector_complex_scalar(filt16_end, ls_estimated, srs_estimated_channel16, 16);
+        } else { // Middle case
+          // filt16_middle4 is {4096,8192,8192,8192,8192,8192,8192,8192,4096,0,0,0,0,0,0,0}
+          multadd_real_vector_complex_scalar(filt16_middle4, ls_estimated, srs_estimated_channel16, 16);
+          srs_estimated_channel16 = (int16_t *)&srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]];
+        }
+      }
+
+#ifdef SRS_DEBUG
+      uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12;
+      int subcarrier_log = nr_srs_info->sc_list[sc_idx]-subcarrier_offset;
+      if(subcarrier_log < 0) {
+        subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size;
+      }
+      if(sc_idx == 0) {
+        LOG_I(NR_PHY,"______________________________ Rx antenna %i _______________________________\n", ant);
+      }
+      if(subcarrier_log%12 == 0) {
+        LOG_I(NR_PHY,":::::::::::::::::::::::::::::::::::: %i ::::::::::::::::::::::::::::::::::::\n", subcarrier_log/12);
+        LOG_I(NR_PHY,"\t  __genRe________genIm__|____rxRe_________rxIm__|____lsRe________lsIm_\n");
+      }
+      LOG_I(NR_PHY,"(%4i) %6i\t%6i  |  %6i\t%6i  |  %6i\t%6i\n",
+            subcarrier_log,
+            generated_real, generated_imag,
+            received_real, received_imag,
+            ls_estimated[0], ls_estimated[1]);
+#endif
+    }
+
+    // Compute noise
+    for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
+      noise_real[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) & 0xFFFF));
+      noise_imag[ant*nr_srs_info->sc_list_length + sc_idx] = abs((int16_t)(((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]]-srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]]) >> 16) & 0xFFFF));
+    }
+
+    // Convert to time domain
+    freq2time(gNB->frame_parms.ofdm_symbol_size,
+              (int16_t*) srs_estimated_channel_freq[ant],
+              (int16_t*) srs_estimated_channel_time[ant]);
+
+    memcpy(&srs_estimated_channel_time_shifted[ant][0],
+           &srs_estimated_channel_time[ant][gNB->frame_parms.ofdm_symbol_size>>1],
+           (gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t));
+
+    memcpy(&srs_estimated_channel_time_shifted[ant][gNB->frame_parms.ofdm_symbol_size>>1],
+           &srs_estimated_channel_time[ant][0],
+           (gNB->frame_parms.ofdm_symbol_size>>1)*sizeof(int32_t));
+  }
+
+  *noise_power = calc_power(noise_real,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length)
+                  + calc_power(noise_imag,frame_parms->nb_antennas_rx*nr_srs_info->sc_list_length);
+
+#ifdef SRS_DEBUG
+  uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12;
+  uint8_t R = srs_pdu->comb_size == 0 ? 2 : 4;
+  for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
+    for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
+      int subcarrier_log = nr_srs_info->sc_list[sc_idx]-subcarrier_offset;
+      if(subcarrier_log < 0) {
+        subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size;
+      }
+      if(sc_idx == 0) {
+        LOG_I(NR_PHY,"______________________________ Rx antenna %i _______________________________\n", ant);
+      }
+      if(subcarrier_log%12 == 0) {
+        LOG_I(NR_PHY,":::::::::::::::::::::::::::::::::::: %i ::::::::::::::::::::::::::::::::::::\n", subcarrier_log/12);
+        LOG_I(NR_PHY,"\t  __lsRe__________lsIm__|____intRe_______intIm__|____noiRe_______noiIm_\n");
+      }
+      for(int r = 0; r<R; r++) {
+        LOG_I(NR_PHY,"(%4i) %6i\t%6i  |  %6i\t%6i  |  %6i\t%6i\n",
+              subcarrier_log+r,
+              (int16_t)(srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]+r]&0xFFFF),
+              (int16_t)((srs_ls_estimated_channel[ant][nr_srs_info->sc_list[sc_idx]+r]>>16)&0xFFFF),
+              (int16_t)(srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]+r]&0xFFFF),
+              (int16_t)((srs_estimated_channel_freq[ant][nr_srs_info->sc_list[sc_idx]+r]>>16)&0xFFFF),
+              noise_real[ant*nr_srs_info->sc_list_length+sc_idx],
+              noise_imag[ant*nr_srs_info->sc_list_length+sc_idx]);
+      }
+
+    }
+  }
+  LOG_I(NR_PHY,"noise_power = %u\n", *noise_power);
+#endif
+
+  return 0;
+}
\ No newline at end of file
diff --git a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
index fd3403236e9ef244a22d19dbe52170ba82b84930..a01106adb5465e96536c67721ddf82e8361c63cf 100644
--- a/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
+++ b/openair1/PHY/NR_ESTIMATION/nr_ul_estimation.h
@@ -62,4 +62,16 @@ void nr_pusch_ptrs_processing(PHY_VARS_gNB *gNB,
                               uint8_t nr_tti_rx,
                               unsigned char symbol,
                               uint32_t nb_re_pusch);
+
+int nr_srs_channel_estimation(PHY_VARS_gNB *gNB,
+                              int frame,
+                              int slot,
+                              nfapi_nr_srs_pdu_t *srs_pdu,
+                              nr_srs_info_t *nr_srs_info,
+                              int32_t *srs_generated_signal,
+                              int32_t **srs_received_signal,
+                              int32_t **srs_estimated_channel_freq,
+                              int32_t **srs_estimated_channel_time,
+                              int32_t **srs_estimated_channel_time_shifted,
+                              uint32_t *noise_power);
 #endif
diff --git a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h
index 43ec0c03dc65bd2eee15e5f4dbfe7c7933d7da41..dab8e040592bca6a7290f843ca66dc26c817050d 100644
--- a/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h
+++ b/openair1/PHY/NR_REFSIG/ul_ref_seq_nr.h
@@ -108,22 +108,22 @@ EXTERN const char phi_M_ZC_6[6*U_GROUP_NUMBER]
 #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
 = {
 /*        0   1   2   3   4   5  */
-/*  0 */ -3, -1,  3,  3, -1, -3,
-/*  1 */ -3,  3, -1, -1,  3, -3,
-/*  2 */ -3, -3, -3,  3,  1, -3,
-/*  3 */  1,  1,  1,  3, -1, -3,
-/*  4 */  1,  1,  1, -3, -1,  3,
-/*  5 */ -3,  1, -1, -3, -3, -3,
-/*  6 */ -3,  1,  3, -3, -3, -3,
-/*  7 */ -3, -1,  1, -3,  1, -1,
-/*  8 */ -3, -1, -3,  1, -3, -3,
-/*  9 */ -3, -3,  1, -3,  3, -3,
+/* 0  */ -3, -1,  3,  3, -1, -3,
+/* 1  */ -3,  3, -1, -1,  3, -3,
+/* 2  */ -3, -3, -3,  3,  1, -3,
+/* 3  */  1,  1,  1,  3, -1, -3,
+/* 4  */  1,  1,  1, -3, -1,  3,
+/* 5  */ -3,  1, -1, -3, -3, -3,
+/* 6  */ -3,  1,  3, -3, -3, -3,
+/* 7  */ -3, -1,  1, -3,  1, -1,
+/* 8  */ -3, -1, -3,  1, -3, -3,
+/* 9  */ -3, -3,  1, -3,  3, -3,
 /* 10 */ -3,  1,  3,  1, -3, -3,
 /* 11 */ -3, -1, -3,  1,  1, -3,
 /* 12 */  1,  1,  3, -1, -3,  3,
 /* 13 */  1,  1,  3,  3, -1,  3,
 /* 14 */  1,  1,  1, -3,  3, -1,
-/* 15 */ -1,  1,  1, -1,  3, -3,
+/* 15 */  1,  1,  1, -1,  3, -3,
 /* 16 */ -3, -1, -1, -1,  3, -1,
 /* 17 */ -3, -3, -1,  1, -1, -3,
 /* 18 */ -3, -3, -3,  1, -3, -1,
@@ -146,36 +146,36 @@ EXTERN const char phi_M_ZC_12[12*U_GROUP_NUMBER]
 #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
 = {
 /*        0   1   2   3   4   5   6   7   8   9  10  11  */
-/* 0  */  1, -1,  3,  1,  1, -1, -1, -1,  1,  3, -3,  1,
-/* 1  */ -1, -1, -1, -1,  1, -3, -1,  3,  3, -1, -3,  1,
-/* 2  */ -3,  1, -3, -3, -3,  3, -3, -1,  1,  1,  1, -3,
-/* 3  */ -3,  3,  1,  3, -3,  1,  1,  1,  1,  3, -3,  3,
-/* 4  */ -3,  1,  3, -1, -1, -3, -3, -1, -1,  3,  1, -3,
-/* 5  */ -1,  1,  1, -1,  1,  3,  3, -1, -1, -3,  1, -3,
-/* 6  */ -3, -3, -1,  3,  3,  3, -3,  3, -3,  1, -1, -3,
-/* 7  */ -3,  3, -3,  3,  3, -3, -1, -1,  3,  3,  1, -3,
-/* 8  */ -3, -1, -3, -1, -1, -3,  3,  3, -1, -1,  1, -3,
-/* 9  */ -3,  3,  3,  3, -1, -3, -3, -1, -3,  1,  3, -3,
-/* 10 */  1,  3, -3,  1,  3,  3,  3,  1, -1,  1, -1,  3,
-/* 11 */ -1, -3,  3, -1, -3, -3, -3, -1,  1, -1,  1, -3,
-/* 12 */  3,  1,  3,  1,  3, -3, -1,  1,  3,  1, -1, -3,
-/* 13 */ -3, -3,  3,  3,  3, -3, -1,  1, -3,  3,  1, -3,
-/* 14 */ -3, -1,  1, -3,  1,  3,  3,  3, -1, -3,  3,  3,
-/* 15 */ -3, -3,  3,  1, -3, -3, -3, -1,  3, -1,  1,  3,
-/* 16 */ -1,  1,  3, -3,  1, -1,  1, -1, -1, -3,  1, -1,
-/* 17 */ -3, -1, -1,  1,  3,  1,  1, -1,  1, -1, -3,  1,
-/* 18 */ -3, -1,  3, -3, -3, -1, -3,  1, -1, -3,  3,  3,
+/* 0  */ -3,  1, -3, -3, -3,  3, -3, -1,  1,  1,  1, -3,
+/* 1  */ -3,  3,  1, -3,  1,  3, -1, -1,  1,  3,  3,  3,
+/* 2  */ -3,  3,  3,  1, -3,  3, -1,  1,  3, -3,  3, -3,
+/* 3  */ -3, -3, -1,  3,  3,  3, -3,  3, -3,  1, -1, -3,
+/* 4  */ -3, -1, -1,  1,  3,  1,  1, -1,  1, -1, -3,  1,
+/* 5  */ -3, -3,  3,  1, -3, -3, -3, -1,  3, -1,  1,  3,
+/* 6  */  1, -1,  3, -1, -1, -1, -3, -1,  1,  1,  1, -3,
+/* 7  */ -1, -3,  3, -1, -3, -3, -3, -1,  1, -1,  1, -3,
+/* 8  */ -3, -1,  3,  1, -3, -1, -3,  3,  1,  3,  3,  1,
+/* 9  */ -3, -1, -1, -3, -3, -1, -3,  3,  1,  3, -1, -3,
+/* 10 */ -3,  3, -3,  3,  3, -3, -1, -1,  3,  3,  1, -3,
+/* 11 */ -3, -1, -3, -1, -1, -3,  3,  3, -1, -1,  1, -3,
+/* 12 */ -3, -1,  3, -3, -3, -1, -3,  1, -1, -3,  3,  3,
+/* 13 */ -3,  1, -1, -1,  3,  3, -3, -1, -1, -3, -1, -3,
+/* 14 */  1,  3, -3,  1,  3,  3,  3,  1, -1,  1, -1,  3,
+/* 15 */ -3,  1,  3, -1, -1, -3, -3, -1, -1,  3,  1, -3,
+/* 16 */ -1, -1, -1, -1,  1, -3, -1,  3,  3, -1, -3,  1,
+/* 17 */ -1,  1,  1, -1,  1,  3,  3, -1, -1, -3,  1, -3,
+/* 18 */ -3,  1,  3,  3, -1, -1, -3,  3,  3, -3,  3, -3,
 /* 19 */ -3, -3,  3, -3, -1,  3,  3,  3, -1, -3,  1, -3,
-/* 20 */ -3,  1, -1, -1,  3,  3, -3, -1, -1, -3, -1, -3,
-/* 21 */ -3,  1,  3,  3, -1, -1, -3,  3,  3, -3,  3, -3,
-/* 22 */ -3, -1, -1, -3, -3, -1, -3,  3,  1,  3, -1, -3,
-/* 23 */ -3, -1,  3,  1, -3, -1, -3,  3,  1,  3,  3,  1,
-/* 24 */ -3,  3,  3,  1, -3,  3, -1,  1,  3, -3,  3, -3,
-/* 25 */  3, -1, -3,  3, -3, -1,  3,  3,  3, -3, -1, -3,
-/* 26 */  1, -1,  3, -1, -1, -1, -3, -1,  1,  1,  1, -3,
-/* 27 */ -3,  3,  1, -3,  1,  3, -1, -1,  1,  3,  3,  3,
-/* 28 */ -3,  3, -3,  3, -3, -3,  3, -1, -1,  1,  3, -3,
-/* 29 */ -3,  3,  1, -1,  3,  3, -3,  1, -1,  1, -1,  1,
+/* 20 */  3,  1,  3,  1,  3, -3, -1,  1,  3,  1, -1, -3,
+/* 21 */ -3,  3,  1,  3, -3,  1,  1,  1,  1,  3, -3,  3,
+/* 22 */ -3,  3,  3,  3, -1, -3, -3, -1, -3,  1,  3, -3,
+/* 23 */  3, -1, -3,  3, -3, -1,  3,  3,  3, -3, -1, -3,
+/* 24 */ -3, -1,  1, -3,  1,  3,  3,  3, -1, -3,  3,  3,
+/* 25 */ -3,  3,  1, -1,  3,  3, -3,  1, -1,  1, -1,  1,
+/* 26 */ -1,  1,  3, -3,  1, -1,  1, -1, -1, -3,  1, -1,
+/* 27 */ -3, -3,  3,  3,  3, -3, -1,  1, -3,  3,  1, -3,
+/* 28 */  1, -1,  3,  1,  1, -1, -1, -1,  1,  3, -3,  1,
+/* 29 */ -3,  3, -3,  3, -3, -3,  3, -1, -1,  1,  3, -3,
 }
 #endif
 ;
@@ -185,36 +185,36 @@ EXTERN const char phi_M_ZC_18[18*U_GROUP_NUMBER]
 #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
 = {
 /*          0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17 */
-/* 0   */   3, -3,  3, -1,  1,  3, -3, -1, -3, -3, -1, -3,  3,  1, -1,  3, -3,  3,
-/* 1   */   3, -3,  1,  1,  3, -1,  1, -1, -1, -3,  1,  1, -1,  3,  3, -3,  3, -1,
-/* 2   */  -3,  3, -1, -3, -1, -3,  1,  1, -3, -3, -1, -1,  3, -3,  1,  3,  1,  1,
-/* 3   */   1,  1, -1, -1, -3, -1,  1, -3, -3, -3,  1, -3, -1, -1,  1, -1,  3,  1,
-/* 4   */   1,  1, -3,  3,  3,  1,  3, -3,  3, -1,  1,  1, -1,  1, -3, -3, -1,  3,
-/* 5   */  -3, -3,  1, -3,  3,  3,  3, -1,  3,  1,  1, -3, -3, -3,  3, -3, -1, -1,
-/* 6   */  -1,  3, -1, -3,  3,  1, -3, -1,  3, -3, -1, -1,  1,  1,  1, -1, -1, -1,
-/* 7   */  -3,  1, -3, -3,  1, -3, -3,  3,  1, -3, -1, -3, -3, -3, -1,  1,  1,  3,
-/* 8   */   1, -3, -1, -3,  3,  3, -1, -3,  1, -3, -3, -1, -3, -1,  1,  3,  3,  3,
-/* 9   */  -3,  3,  1, -1, -1, -1, -1,  1, -1,  3,  3, -3, -1,  1,  3, -1,  3, -1,
-/* 10  */  -3, -3,  1, -1, -1,  1,  1, -3, -1,  3,  3,  3,  3, -1,  3,  1,  3,  1,
-/* 11  */  -3, -3,  3,  3, -3,  1,  3, -1, -3,  1, -1, -3,  3, -3, -1, -1, -1,  3,
-/* 12  */  -3, -3,  3,  3,  3,  1, -3,  1,  3,  3,  1, -3, -3,  3, -1, -3, -1,  1,
-/* 13  */  -3,  3, -1,  1,  3,  1, -3, -1,  1,  1, -3,  1,  3,  3, -1, -3, -3, -3,
-/* 14  */  -3,  1, -3, -1, -1,  3,  1, -3, -3, -3, -1, -3, -3,  1,  1,  1, -1, -1,
-/* 15  */  -3, -3,  3,  3,  3, -1, -1, -3, -1, -1, -1,  3,  1, -3, -3, -1,  3, -1,
-/* 16  */  -3, -1,  3,  3, -1,  3, -1, -3, -1,  1, -1, -3, -1, -1, -1,  3,  3,  1,
-/* 17  */  -3, -1, -3, -1, -3,  1,  3, -3, -1,  3,  3,  3,  1, -1, -3,  3, -1, -3,
-/* 18  */  -3,  3,  1, -1, -1,  3, -3, -1,  1,  1,  1,  1,  1, -1,  3, -1, -3, -1,
-/* 19  */   3, -1, -3,  1, -3, -3, -3,  3,  3, -1,  1, -3, -1,  3,  1,  1,  3,  3,
-/* 20  */   3,  3,  3, -3, -1, -3, -1,  3, -1,  1, -1, -3,  1, -3, -3, -1,  3,  3,
-/* 21  */   3, -1,  3,  1, -3, -3, -1,  1, -3, -3,  3,  3,  3,  1,  3, -3,  3, -3,
-/* 22  */  -3,  1,  1, -3,  1,  1,  3, -3, -1, -3, -1,  3, -3,  3, -1, -1, -1, -3,
-/* 23  */  -3, -1, -1, -3,  1, -3,  3, -1, -1, -3,  3,  3, -3, -1,  3, -1, -1, -1,
-/* 24  */  -3, -3, -3,  1, -3,  3,  1,  1,  3, -3, -3,  1,  3, -1,  3, -3, -3,  3,
-/* 25  */   1,  1, -3, -3, -3, -3,  1,  3, -3,  3,  3,  1, -3, -1,  3, -1, -3,  1,
-/* 26  */   3, -1, -1,  1, -3, -1, -3, -1, -3, -3, -1, -3,  1,  1,  1, -3, -3,  3,
-/* 27  */   3,  1, -3,  1, -3,  3,  3, -1, -3, -3, -1, -3, -3,  3, -3, -1,  1,  3,
+/* 0   */  -1,  3, -1, -3,  3,  1, -3, -1,  3, -3, -1, -1,  1,  1,  1, -1, -1, -1,
+/* 1   */   3, -3,  3, -1,  1,  3, -3, -1, -3, -3, -1, -3,  3,  1, -1,  3, -3,  3,
+/* 2   */  -3,  3,  1, -1, -1,  3, -3, -1,  1,  1,  1,  1,  1, -1,  3, -1, -3, -1,
+/* 3   */  -3, -3,  3,  3,  3,  1, -3,  1,  3,  3,  1, -3, -3,  3, -1, -3, -1,  1,
+/* 4   */   1,  1, -1, -1, -3, -1,  1, -3, -3, -3,  1, -3, -1, -1,  1, -1,  3,  1,
+/* 5   */   3, -3,  1,  1,  3, -1,  1, -1, -1, -3,  1,  1, -1,  3,  3, -3,  3, -1,
+/* 6   */  -3,  3, -1,  1,  3,  1, -3, -1,  1,  1, -3,  1,  3,  3, -1, -3, -3, -3,
+/* 7   */   1,  1, -3,  3,  3,  1,  3, -3,  3, -1,  1,  1, -1,  1, -3, -3, -1,  3,
+/* 8   */  -3,  1, -3, -3,  1, -3, -3,  3,  1, -3, -1, -3, -3, -3, -1,  1,  1,  3,
+/* 9   */   3, -1,  3,  1, -3, -3, -1,  1, -3, -3,  3,  3,  3,  1,  3, -3,  3, -3,
+/* 10  */  -3, -3, -3,  1, -3,  3,  1,  1,  3, -3, -3,  1,  3, -1,  3, -3, -3,  3,
+/* 11  */  -3, -3,  3,  3,  3, -1, -1, -3, -1, -1, -1,  3,  1, -3, -3, -1,  3, -1,
+/* 12  */  -3, -1, -3, -3,  1,  1, -1, -3, -1, -3, -1, -1,  3,  3, -1,  3,  1,  3,
+/* 13  */   1,  1, -3, -3, -3, -3,  1,  3, -3,  3,  3,  1, -3, -1,  3, -1, -3,  1,
+/* 14  */  -3,  3, -1, -3, -1, -3,  1,  1, -3, -3, -1, -1,  3, -3,  1,  3,  1,  1,
+/* 15  */   3,  1, -3,  1, -3,  3,  3, -1, -3, -3, -1, -3, -3,  3, -3, -1,  1,  3,
+/* 16  */  -3, -1, -3, -1, -3,  1,  3, -3, -1,  3,  3,  3,  1, -1, -3,  3, -1, -3,
+/* 17  */  -3, -1,  3,  3, -1,  3, -1, -3, -1,  1, -1, -3, -1, -1, -1,  3,  3,  1,
+/* 18  */  -3,  1, -3, -1, -1,  3,  1, -3, -3, -3, -1, -3, -3,  1,  1,  1, -1, -1,
+/* 19  */   3,  3,  3, -3, -1, -3, -1,  3, -1,  1, -1, -3,  1, -3, -3, -1,  3,  3,
+/* 20  */  -3,  1,  1, -3,  1,  1,  3, -3, -1, -3, -1,  3, -3,  3, -1, -1, -1, -3,
+/* 21  */   1, -3, -1, -3,  3,  3, -1, -3,  1, -3, -3, -1, -3, -1,  1,  3,  3,  3,
+/* 22  */  -3, -3,  1, -1, -1,  1,  1, -3, -1,  3,  3,  3,  3, -1,  3,  1,  3,  1,
+/* 23  */   3, -1, -3,  1, -3, -3, -3,  3,  3, -1,  1, -3, -1,  3,  1,  1,  3,  3,
+/* 24  */   3, -1, -1,  1, -3, -1, -3, -1, -3, -3, -1, -3,  1,  1,  1, -3, -3,  3,
+/* 25  */  -3, -3,  1, -3,  3,  3,  3, -1,  3,  1,  1, -3, -3, -3,  3, -3, -1, -1,
+/* 26  */  -3, -1, -1, -3,  1, -3,  3, -1, -1, -3,  3,  3, -3, -1,  3, -1, -1, -1,
+/* 27  */  -3, -3,  3,  3, -3,  1,  3, -1, -3,  1, -1, -3,  3, -3, -1, -1, -1,  3,
 /* 28  */  -1, -3,  1, -3, -3, -3,  1,  1,  3,  3, -3,  3,  3, -3, -1,  3, -3,  1,
-/* 29  */  -3, -1, -3, -3,  1,  1, -1, -3, -1, -3, -1, -1,  3,  3, -1,  3,  1,  3,
+/* 29  */  -3,  3,  1, -1, -1, -1, -1,  1, -1,  3,  3, -3, -1,  1,  3, -1,  3, -1,
 }
 #endif
 ;
@@ -224,36 +224,36 @@ EXTERN const char phi_M_ZC_24[24*U_GROUP_NUMBER]
 #ifdef INIT_VARIABLES_LOWPAPR_SEQUENCES_NR_H
 = {
 /*          0   1   2   3   4   5   6   7   8   9  10  11  12  13  14  15  16  17  18  19  20  21  22  23 */
-/* 0   */  -1, -3,  3,  1,  1, -3,  1, -3, -3,  1, -3, -1, -1,  3, -3,  3,  3,  3, -3,  1,  3,  3, -3, -3,
-/* 1   */  -1, -3,  3, -1,  3,  1,  3, -1,  1, -3, -1, -3, -1,  1,  3, -3, -1, -3,  3,  3,  3, -3, -3, -3,
-/* 2   */  -3,  3,  1,  3, -1,  1, -3,  1, -3,  1, -1, -3, -1, -3, -3, -3, -3, -1, -1, -1,  1,  1, -3, -3,
-/* 3   */   3, -1,  3, -1,  1, -3,  1,  1, -3, -3,  3, -3, -1, -1, -1, -1, -1, -3, -3, -1,  1,  1, -3, -3,
-/* 4   */   1, -3,  3, -1, -3, -1,  3,  3,  1, -1,  1,  1,  3, -3, -1, -3, -3, -3, -1,  3, -3, -1, -3, -3,
-/* 5   */   3, -1,  1, -1,  3, -3,  1,  1,  3, -1, -3,  3,  1, -3,  3, -1, -1, -1, -1,  1, -3, -3, -3, -3,
-/* 6   */  -3,  3, -1,  3,  1, -1, -1, -1,  3,  3,  1,  1,  1,  3,  3,  1, -3, -3, -1,  1, -3,  1,  3, -3,
-/* 7   */  -3, -1,  1, -3, -3,  1,  1, -3,  3, -1, -1, -3,  1,  3,  1, -1, -3, -1, -3,  1, -3, -3, -3, -3,
-/* 8   */  -3,  1, -3,  1, -3, -3,  1, -3,  1, -3, -3, -3, -3, -3,  1, -3, -3,  1,  1, -3,  1,  1, -3, -3,
-/* 9   */   3, -3, -3, -1,  3,  3, -3, -1,  3,  1,  1,  1,  3, -1,  3, -3, -1,  3, -1,  3,  1, -1, -3, -3,
-/* 10  */  -3, -3, -1, -1, -1, -3,  1, -1, -3, -1,  3, -3,  1, -3,  3, -3,  3,  3,  1, -1, -1,  1, -3, -3,
-/* 11  */  -3, -3,  3,  3,  1, -1, -1, -1,  1, -3, -1,  1, -1,  3, -3, -1, -3, -1, -1,  1, -3,  3, -1, -3,
-/* 12  */  -3, -3,  1, -1,  3,  3, -3, -1,  1, -1, -1,  1,  1, -1, -1,  3, -3,  1, -3,  1, -1, -1, -1, -3,
-/* 13  */  -3,  1, -3,  3, -1, -1, -1, -3,  3,  1, -1, -3, -1,  1,  3, -1,  1, -1,  1, -3, -3, -3, -3, -3,
-/* 14  */  -3, -3, -3, -1,  3, -3,  3,  1,  3,  1, -3, -1, -1, -3,  1,  1,  3,  1, -1, -3,  3,  1,  3, -3,
-/* 15  */   1,  1, -1, -3, -1,  1,  1, -3,  1, -1,  1, -3,  3, -3, -3,  3, -1, -3,  1,  3, -3,  1, -3, -3,
-/* 16  */  -3,  3, -1,  3, -1,  3,  3,  1,  1, -3,  1,  3, -3,  3, -3, -3, -1,  1,  3, -3, -1, -1, -3, -3,
-/* 17  */  -1, -3, -3,  1, -1, -1, -3,  1,  3, -1, -3, -1, -1, -3,  1,  1,  3,  1, -3, -1, -1,  3, -3, -3,
-/* 18  */  -3,  1, -3,  1, -3,  1,  1,  3,  1, -3, -3, -1,  1,  3, -1, -3,  3,  1, -1, -3, -3, -3, -3, -3,
-/* 19  */   3, -3,  3, -1, -3,  1,  3,  1, -1, -1, -3, -1,  3, -3,  3, -1, -1,  3,  3, -3, -3,  3, -3, -3,
-/* 20  */  -1,  3, -3, -3, -1,  3, -1, -1,  1,  3,  1,  3, -1, -1, -3,  1,  3,  1, -1, -3,  1, -1, -3, -3,
-/* 21  */  -3,  1, -3, -1, -1,  3,  1,  3, -3,  1, -1,  3,  3, -1, -3,  3, -3, -1, -1, -3, -3, -3,  3, -3,
-/* 22  */  -3, -1, -1, -3,  1, -3, -3, -1, -1,  3, -1,  1, -1,  3,  1, -3, -1,  3,  1,  1, -1, -1, -3, -3,
-/* 23  */  -3,  1, -3,  3, -3,  1, -3,  3,  1, -1, -3, -1, -3, -3, -3, -3,  1,  3, -1,  1,  3,  3,  3, -3,
-/* 24  */  -3, -1,  1, -3, -1, -1,  1,  1,  1,  3,  3, -1,  1, -1,  1, -1, -1, -3, -3, -3,  3,  1, -1, -3,
-/* 25  */   3, -3, -1,  1,  3, -1, -1, -3, -1,  3, -1, -3, -1, -3,  3, -1,  3,  1,  1, -3,  3, -3, -3, -3,
-/* 26  */  -3,  1,  3, -1,  1, -1,  3, -3,  3, -1, -3, -1, -3,  3, -1, -1, -1, -3, -1, -1, -3,  3,  3, -3,
-/* 27  */  -3,  3, -1, -3, -1, -1, -1,  3, -1, -1,  3, -3, -1,  3, -3,  3, -3, -1,  3,  1,  1, -1, -3, -3,
-/* 28  */  -3,  1, -1, -3, -3, -1,  1, -3, -1, -3,  1,  1, -1,  1,  1,  3,  3,  3, -1,  1, -1,  1, -1, -3,
-/* 29  */  -1,  3, -1, -1,  3,  3, -1, -1, -1,  3, -1, -3,  1,  3,  1,  1, -3, -3, -3, -1, -3, -1, -3, -3,
+/* 0   */  -1, -3,  3, -1,  3,  1,  3, -1,  1, -3, -1, -3, -1,  1,  3, -3, -1, -3,  3,  3,  3, -3, -3, -3,
+/* 1   */  -1, -3,  3,  1,  1, -3,  1, -3, -3,  1, -3, -1, -1,  3, -3,  3,  3,  3, -3,  1,  3,  3, -3, -3,
+/* 2   */  -1, -3, -3,  1, -1, -1, -3,  1,  3, -1, -3, -1, -1, -3,  1,  1,  3,  1, -3, -1, -1,  3, -3, -3,
+/* 3   */   1, -3,  3, -1, -3, -1,  3,  3,  1, -1,  1,  1,  3, -3, -1, -3, -3, -3, -1,  3, -3, -1, -3, -3,
+/* 4   */  -1,  3, -3, -3, -1,  3, -1, -1,  1,  3,  1,  3, -1, -1, -3,  1,  3,  1, -1, -3,  1, -1, -3, -3,
+/* 5   */  -3, -1,  1, -3, -3,  1,  1, -3,  3, -1, -1, -3,  1,  3,  1, -1, -3, -1, -3,  1, -3, -3, -3, -3,
+/* 6   */  -3,  3,  1,  3, -1,  1, -3,  1, -3,  1, -1, -3, -1, -3, -3, -3, -3, -1, -1, -1,  1,  1, -3, -3,
+/* 7   */  -3,  1,  3, -1,  1, -1,  3, -3,  3, -1, -3, -1, -3,  3, -1, -1, -1, -3, -1, -1, -3,  3,  3, -3,
+/* 8   */  -3,  1, -3,  3, -1, -1, -1, -3,  3,  1, -1, -3, -1,  1,  3, -1,  1, -1,  1, -3, -3, -3, -3, -3,
+/* 9   */   1,  1, -1, -3, -1,  1,  1, -3,  1, -1,  1, -3,  3, -3, -3,  3, -1, -3,  1,  3, -3,  1, -3, -3,
+/* 10  */  -3, -3, -3, -1,  3, -3,  3,  1,  3,  1, -3, -1, -1, -3,  1,  1,  3,  1, -1, -3,  3,  1,  3, -3,
+/* 11  */  -3,  3, -1,  3,  1, -1, -1, -1,  3,  3,  1,  1,  1,  3,  3,  1, -3, -3, -1,  1, -3,  1,  3, -3,
+/* 12  */   3, -3,  3, -1, -3,  1,  3,  1, -1, -1, -3, -1,  3, -3,  3, -1, -1,  3,  3, -3, -3,  3, -3, -3,
+/* 13  */  -3,  3, -1,  3, -1,  3,  3,  1,  1, -3,  1,  3, -3,  3, -3, -3, -1,  1,  3, -3, -1, -1, -3, -3,
+/* 14  */  -3,  1, -3, -1, -1,  3,  1,  3, -3,  1, -1,  3,  3, -1, -3,  3, -3, -1, -1, -3, -3, -3,  3, -3,
+/* 15  */  -3, -1, -1, -3,  1, -3, -3, -1, -1,  3, -1,  1, -1,  3,  1, -3, -1,  3,  1,  1, -1, -1, -3, -3,
+/* 16  */  -3, -3,  1, -1,  3,  3, -3, -1,  1, -1, -1,  1,  1, -1, -1,  3, -3,  1, -3,  1, -1, -1, -1, -3,
+/* 17  */   3, -1,  3, -1,  1, -3,  1,  1, -3, -3,  3, -3, -1, -1, -1, -1, -1, -3, -3, -1,  1,  1, -3, -3,
+/* 18  */   3,  1, -3,  1, -3, -3,  1, -3,  1, -3, -3, -3, -3, -3,  1, -3, -3,  1,  1, -3,  1,  1, -3, -3,
+/* 19  */  -3, -3,  3,  3,  1, -1, -1, -1,  1, -3, -1,  1, -1,  3, -3, -1, -3, -1, -1,  1, -3,  3, -1, -3,
+/* 20  */  -3, -3, -1, -1, -1, -3,  1, -1, -3, -1,  3, -3,  1, -3,  3, -3,  3,  3,  1, -1, -1,  1, -3, -3,
+/* 21  */   3, -1,  1, -1,  3, -3,  1,  1,  3, -1, -3,  3,  1, -3,  3, -1, -1, -1, -1,  1, -3, -3, -3, -3,
+/* 22  */  -3,  1, -3,  3, -3,  1, -3,  3,  1, -1, -3, -1, -3, -3, -3, -3,  1,  3, -1,  1,  3,  3,  3, -3,
+/* 23  */  -3, -1,  1, -3, -1, -1,  1,  1,  1,  3,  3, -1,  1, -1,  1, -1, -1, -3, -3, -3,  3,  1, -1, -3,
+/* 24  */  -3,  3, -1, -3, -1, -1, -1,  3, -1, -1,  3, -3, -1,  3, -3,  3, -3, -1,  3,  1,  1, -1, -3, -3,
+/* 25  */  -3,  1, -1, -3, -3, -1,  1, -3, -1, -3,  1,  1, -1,  1,  1,  3,  3,  3, -1,  1, -1,  1, -1, -3,
+/* 26  */  -1,  3, -1, -1,  3,  3, -1, -1, -1,  3, -1, -3,  1,  3,  1,  1, -3, -3, -3, -1, -3, -1, -3, -3,
+/* 27  */   3, -3, -3, -1,  3,  3, -3, -1,  3,  1,  1,  1,  3, -1,  3, -3, -1,  3, -1,  3,  1, -1, -3, -3,
+/* 28  */  -3,  1, -3,  1, -3,  1,  1,  3,  1, -3, -3, -1,  1,  3, -1, -3,  3,  1, -1, -3, -3, -3, -3, -3,
+/* 29  */   3, -3, -1,  1,  3, -1, -1, -3, -1,  3, -1, -3, -1, -3,  3, -1,  3,  1,  1, -3,  3, -3, -3, -3,
 }
 #endif
 ;
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
index 920522aa35e652b69b52a0c7402da9d98a91b397..c6c89c80be9d415c8181cf32211b16009cb7e7e4 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch.c
@@ -47,70 +47,11 @@ void nr_pdsch_codeword_scrambling(uint8_t *in,
                                   uint8_t q,
                                   uint32_t Nid,
                                   uint32_t n_RNTI,
-                                  uint32_t* out) {
-
-  uint8_t reset, b_idx;
-  uint32_t x1, x2, s=0;
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_CODEWORD_SCRAMBLING, 1);
-  reset = 1;
-  x2 = (n_RNTI<<15) + (q<<14) + Nid;
-
-  for (int i=0; i<size; i++) {
-    b_idx = i&0x1f;
-    if (b_idx==0) {
-      s = lte_gold_generic(&x1, &x2, reset);
-      reset = 0;
-      if (i)
-        out++;
-    }
-    *out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
-    //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
-  }
-  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_CODEWORD_SCRAMBLING, 0);
+                                  uint32_t* out)
+{
+  nr_codeword_scrambling(in, size, q, Nid, n_RNTI, out);
 }
 
-void nr_pdsch_codeword_scrambling_optim(uint8_t *in,
-					uint32_t size,
-					uint8_t q,
-					uint32_t Nid,
-					uint32_t n_RNTI,
-					uint32_t* out) {
-  
-  uint32_t x1, x2, s=0,in32;
-
-  x2 = (n_RNTI<<15) + (q<<14) + Nid;
-
-  s=lte_gold_generic(&x1, &x2, 1);
-
-#if defined(__AVX2__)
-  for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++) {
-    in32=_mm256_movemask_epi8(_mm256_slli_epi16(((__m256i*)in)[i],7));
-    out[i]=(in32^s);
-    //printf("in[%d] %x => %x\n",i,in32,out[i]);
-    s=lte_gold_generic(&x1, &x2, 0);
-  }
-#elif defined(__SSE4__)
-  _m128i *in128;
-  for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++) {
-    in128=&((__m128i*)in)[i<<1];
-    ((uint16_t*)&in32)[0] = _mm128_movemask_epi8(_mm256_slli_epi16(in128[0],7));
-    ((uint16_t*)&in32)[1] = _mm128_movemask_epi8(_mm256_slli_epi16(in128[1],7));
-    out[i]=(in32^s);
-    s=lte_gold_generic(&x1, &x2, 0);
-  }
-  //#elsif defined(__arm__) || defined(__aarch64)
-  
-#else 
-  nr_pdsch_codeword_scrambling(in,
-			       size,
-			       q,
-			       Nid,
-			       n_RNTI,
-			       out);
-#endif
-}
-
-
 void nr_generate_pdsch(processingData_L1tx_t *msgTx,
                        int frame,
                        int slot) {
@@ -214,12 +155,12 @@ void nr_generate_pdsch(processingData_L1tx_t *msgTx,
     for (int q=0; q<rel15->NrOfCodewords; q++)
       memset((void*)scrambled_output[q], 0, (encoded_length>>5)*sizeof(uint32_t));
     for (int q=0; q<rel15->NrOfCodewords; q++)
-      nr_pdsch_codeword_scrambling_optim(output,
-					 encoded_length,
-					 q,
-					 rel15->dataScramblingId,
-					 rel15->rnti,
-					 scrambled_output[q]);
+      nr_pdsch_codeword_scrambling(output,
+                                   encoded_length,
+                                   q,
+                                   rel15->dataScramblingId,
+                                   rel15->rnti,
+                                   scrambled_output[q]);
     
     stop_meas(dlsch_scrambling_stats);
 #ifdef DEBUG_DLSCH
diff --git a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
index b006eaae89cbdaa6b33b88e10f0581c725dbecb4..6d16fa531c96f905abf93f7ba574207ad3aff017 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_dlsch_coding.c
@@ -108,7 +108,7 @@ NR_gNB_DLSCH_t *new_gNB_dlsch(NR_DL_FRAME_PARMS *frame_parms,
     a_segments = a_segments/273 +1;
   }
 
-  uint16_t dlsch_bytes = a_segments*1056;  // allocated bytes per segment
+  uint32_t dlsch_bytes = a_segments*1056;  // allocated bytes per segment
   NR_gNB_DLSCH_t *dlsch = malloc16(sizeof(NR_gNB_DLSCH_t));
   AssertFatal(dlsch, "cannot allocate dlsch\n");
   bzero(dlsch,sizeof(NR_gNB_DLSCH_t));
diff --git a/openair1/PHY/NR_TRANSPORT/nr_scrambling.c b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c
new file mode 100644
index 0000000000000000000000000000000000000000..b68ad2d89f9b86259bc613ba9fb315af140424f8
--- /dev/null
+++ b/openair1/PHY/NR_TRANSPORT/nr_scrambling.c
@@ -0,0 +1,107 @@
+/*
+ * 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
+ */
+
+#include "nr_transport_common_proto.h"
+#include "PHY/NR_REFSIG/nr_refsig.h"
+#include "common/utils/LOG/vcd_signal_dumper.h"
+
+void nr_codeword_scrambling(uint8_t *in,
+                            uint32_t size,
+                            uint8_t q,
+                            uint32_t Nid,
+                            uint32_t n_RNTI,
+                            uint32_t* out)
+{
+  uint32_t x1;
+  uint32_t x2 = (n_RNTI<<15) + (q<<14) + Nid;
+  uint32_t s = 0;
+
+#if defined(__AVX2__)
+  s=lte_gold_generic(&x1, &x2, 1);
+  for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++) {
+    __m256i c = ((__m256i*)in)[i];
+    uint32_t in32 = _mm256_movemask_epi8(_mm256_slli_epi16(c,7));
+    out[i]=(in32^s);
+    //printf("in[%d] %x => %x\n",i,in32,out[i]);
+    s=lte_gold_generic(&x1, &x2, 0);
+  }
+#elif defined(__SSE4__)
+  s=lte_gold_generic(&x1, &x2, 1);
+  __m128i *in128;
+  for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++) {
+    in128=&((__m128i*)in)[i<<1];
+    uint32_t in32;
+    ((uint16_t*)&in32)[0] = _mm_movemask_epi8(_mm_slli_epi16(in128[0],7));
+    ((uint16_t*)&in32)[1] = _mm_movemask_epi8(_mm_slli_epi16(in128[1],7));
+    out[i]=(in32^s);
+    s=lte_gold_generic(&x1, &x2, 0);
+  }
+//#elsif defined(__arm__) || defined(__aarch64)
+#else
+  uint8_t reset = 1;
+
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_CODEWORD_SCRAMBLING, 1);
+  for (int i = 0; i < size; i++) {
+    const uint8_t b_idx = i&0x1f;
+    if (b_idx==0) {
+      s = lte_gold_generic(&x1, &x2, reset);
+      reset = 0;
+      if (i)
+        out++;
+    }
+    *out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
+    //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
+  }
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_PDSCH_CODEWORD_SCRAMBLING, 0);
+#endif
+}
+
+void nr_codeword_unscrambling(int16_t* llr, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI)
+{
+  uint32_t x1;
+  uint32_t x2 = (n_RNTI << 15) + (q << 14) + Nid;
+  uint32_t s = 0;
+
+#if defined(__x86_64__) || defined(__i386__)
+  uint8_t *s8=(uint8_t *)&s;
+  __m128i *llr128 = (__m128i*)llr;
+  s = lte_gold_generic(&x1, &x2, 1);
+
+  for (int i = 0, j = 0; i < ((size >> 5) + ((size & 0x1f) > 0 ? 1 : 0)); i++, j += 4) {
+    llr128[j]   = _mm_mullo_epi16(llr128[j],byte2m128i[s8[0]]);
+    llr128[j+1] = _mm_mullo_epi16(llr128[j+1],byte2m128i[s8[1]]);
+    llr128[j+2] = _mm_mullo_epi16(llr128[j+2],byte2m128i[s8[2]]);
+    llr128[j+3] = _mm_mullo_epi16(llr128[j+3],byte2m128i[s8[3]]);
+    s = lte_gold_generic(&x1, &x2, 0);
+  }
+#else
+  uint8_t reset = 1;
+
+  for (uint32_t i=0; i<size; i++) {
+    if ((i&0x1f)==0) {
+      s = lte_gold_generic(&x1, &x2, reset);
+      reset = 0;
+    }
+    if (((s>>(i&0x1f))&1)==1)
+      llr[i] = -llr[i];
+  }
+#endif
+}
diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h
index 02e594e76a3509ab2488f9639434d2c760d71791..2daf2af1fb80922c90caacd2796ca39ff4eb4df8 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_transport_common_proto.h
@@ -77,6 +77,15 @@ void nr_fill_du(uint16_t N_ZC,uint16_t *prach_root_sequence_map);
 
 void init_nr_prach_tables(int N_ZC);
 
+void nr_codeword_scrambling(uint8_t *in,
+                            uint32_t size,
+                            uint8_t q,
+                            uint32_t Nid,
+                            uint32_t n_RNTI,
+                            uint32_t* out);
+
+void nr_codeword_unscrambling(int16_t* llr, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI);
+
 /**@}*/
 
 void init_pucch2_luts(void);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
index 5cc246fd29d6260354c3a1cd7e5349240ffdb5d9..d45858bca0814c1155ffb4e86237e64602bb28b6 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_transport_proto.h
@@ -307,6 +307,24 @@ int nr_find_pucch(uint16_t rnti,
                   int slot,
                   PHY_VARS_gNB *gNB);
 
+NR_gNB_SRS_t *new_gNB_srs(void);
+
+int nr_find_srs(uint16_t rnti,
+                int frame,
+                int slot,
+                PHY_VARS_gNB *gNB);
+
+void nr_fill_srs(PHY_VARS_gNB *gNB,
+                 int frame,
+                 int slot,
+                 nfapi_nr_srs_pdu_t *srs_pdu);
+
+int nr_get_srs_signal(PHY_VARS_gNB *gNB,
+                      int frame,
+                      int slot,
+                      nfapi_nr_srs_pdu_t *srs_pdu,
+                      nr_srs_info_t *nr_srs_info,
+                      int32_t **srs_received_signal);
 
 void init_prach_list(PHY_VARS_gNB *gNB);
 void init_prach_ru_list(RU_t *ru);
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c
index 4278338dbcc382d3e81ce1566161b380b89c5342..1cb503489bbdcf28d10c1c07e34662e9f3537930 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.c
@@ -33,7 +33,6 @@
 #include <stdint.h>
 #include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
 #include "PHY/NR_TRANSPORT/nr_ulsch.h"
-#include "PHY/NR_REFSIG/nr_refsig.h"
 
 int16_t find_nr_ulsch(uint16_t rnti, PHY_VARS_gNB *gNB,find_type_t type) {
 
@@ -82,59 +81,9 @@ void nr_fill_ulsch(PHY_VARS_gNB *gNB,
 
 }
 
-void nr_ulsch_unscrambling(int16_t* llr,
-                           uint32_t size,
-                           uint8_t q,
-                           uint32_t Nid,
-                           uint32_t n_RNTI) {
-
-  uint8_t reset;
-  uint32_t x1, x2, s=0;
-
-  reset = 1;
-  x2 = (n_RNTI<<15) + Nid;
-
-  for (uint32_t i=0; i<size; i++) {
-    if ((i&0x1f)==0) {
-      s = lte_gold_generic(&x1, &x2, reset);
-      reset = 0;
-    }
-    if (((s>>(i&0x1f))&1)==1)
-      llr[i] = -llr[i];
-  }
-}
-
-void nr_ulsch_unscrambling_optim(int16_t* llr,
-				 uint32_t size,
-				 uint8_t q,
-				 uint32_t Nid,
-				 uint32_t n_RNTI) {
-  
-#if defined(__x86_64__) || defined(__i386__)
-  uint32_t x1, x2, s=0;
-
-  x2 = (n_RNTI<<15) + Nid;
-
-  uint8_t *s8=(uint8_t *)&s;
-  __m128i *llr128 = (__m128i*)llr;
-  int j=0;
-  s = lte_gold_generic(&x1, &x2, 1);
-
-  for (int i=0; i<((size>>5)+((size&0x1f) > 0 ? 1 : 0)); i++,j+=4) {
-    llr128[j]   = _mm_mullo_epi16(llr128[j],byte2m128i[s8[0]]);
-    llr128[j+1] = _mm_mullo_epi16(llr128[j+1],byte2m128i[s8[1]]);
-    llr128[j+2] = _mm_mullo_epi16(llr128[j+2],byte2m128i[s8[2]]);
-    llr128[j+3] = _mm_mullo_epi16(llr128[j+3],byte2m128i[s8[3]]);
-    s = lte_gold_generic(&x1, &x2, 0);
-  }
-#else
-
-    nr_ulsch_unscrambling(llr,
-                          size,
-                          q,
-                          Nid,
-                          n_RNTI);
-#endif
+void nr_ulsch_unscrambling(int16_t* llr, uint32_t size, uint32_t Nid, uint32_t n_RNTI)
+{
+  nr_codeword_unscrambling(llr, size, 0, Nid, n_RNTI);
 }
 
 void dump_pusch_stats(FILE *fd,PHY_VARS_gNB *gNB) {
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
index 80c10d74b15a4c7bc82862efe7142d049975320f..f7bb3be5772ecb11fe7e789ed9b07ac9b975ff41 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch.h
@@ -69,18 +69,7 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
   @param n_RNTI, CRNTI
 */
 
-void nr_ulsch_unscrambling(int16_t* llr,
-                         uint32_t size,
-                         uint8_t q,
-                         uint32_t Nid,
-                         uint32_t n_RNTI);
-
-
-void nr_ulsch_unscrambling_optim(int16_t* llr,
-				 uint32_t size,
-				 uint8_t q,
-				 uint32_t Nid,
-				 uint32_t n_RNTI);
+void nr_ulsch_unscrambling(int16_t* llr, uint32_t size, uint32_t Nid, uint32_t n_RNTI);
 
 void nr_ulsch_procedures(PHY_VARS_gNB *gNB,
                          int frame_rx,
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index 33071e40704a9d582075299175465b87c1298c81..31d44736d4ba758d8a7e88757046a4f0e0611811 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -119,7 +119,7 @@ NR_gNB_ULSCH_t *new_gNB_ulsch(uint8_t max_ldpc_iterations,uint16_t N_RB_UL, uint
     a_segments = a_segments/273 +1;
   }
 
-  uint16_t ulsch_bytes = a_segments*1056;  // allocated bytes per segment
+  uint32_t ulsch_bytes = a_segments*1056;  // allocated bytes per segment
   ulsch = (NR_gNB_ULSCH_t *)malloc16_clear(sizeof(NR_gNB_ULSCH_t));
   
   ulsch->max_ldpc_iterations = max_ldpc_iterations;
diff --git a/openair1/PHY/NR_TRANSPORT/srs_rx.c b/openair1/PHY/NR_TRANSPORT/srs_rx.c
new file mode 100644
index 0000000000000000000000000000000000000000..c16becdb20b2aa0403ef19253e6379f565c86076
--- /dev/null
+++ b/openair1/PHY/NR_TRANSPORT/srs_rx.c
@@ -0,0 +1,139 @@
+/*
+ * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
+ * contributor license agreements.  See the NOTICE file distributed with
+ * this work for additional information regarding copyright ownership.
+ * The OpenAirInterface Software Alliance licenses this file to You under
+ * the OAI Public License, Version 1.1  (the "License"); you may not use this file
+ * except in compliance with the License.
+ * You may obtain a copy of the License at
+ *
+ *      http://www.openairinterface.org/?page_id=698
+ *
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ *-------------------------------------------------------------------------------
+ * For more information about the OpenAirInterface (OAI) Software Alliance:
+ *      contact@openairinterface.org
+ */
+
+/*! \file PHY/NR_TRANSPORT/srs_rx.c
+ * \brief Top-level routines for getting the SRS physical channel
+ * \date 2021
+ * \version 1.0
+ */
+
+#include <stdio.h>
+#include <string.h>
+#include <unistd.h>
+#include <fcntl.h>
+
+#include "PHY/impl_defs_nr.h"
+#include "PHY/defs_nr_common.h"
+#include "PHY/defs_gNB.h"
+#include <openair1/PHY/CODING/nrSmallBlock/nr_small_block_defs.h>
+#include "common/utils/LOG/log.h"
+
+#include "nfapi/oai_integration/vendor_ext.h"
+
+#include "T.h"
+
+//#define SRS_DEBUG
+
+NR_gNB_SRS_t *new_gNB_srs(void){
+  NR_gNB_SRS_t *srs;
+  srs = (NR_gNB_SRS_t *)malloc16(sizeof(NR_gNB_SRS_t));
+  srs->active = 0;
+  return (srs);
+}
+
+int nr_find_srs(uint16_t rnti,
+                int frame,
+                int slot,
+                PHY_VARS_gNB *gNB) {
+
+  AssertFatal(gNB!=NULL,"gNB is null\n");
+  int index = -1;
+
+  for (int i=0; i<NUMBER_OF_NR_SRS_MAX; i++) {
+    AssertFatal(gNB->srs[i]!=NULL,"gNB->srs[%d] is null\n",i);
+    if ((gNB->srs[i]->active>0) &&
+        (gNB->srs[i]->srs_pdu.rnti==rnti) &&
+        (gNB->srs[i]->frame==frame) &&
+        (gNB->srs[i]->slot==slot)) return(i);
+    else if ((gNB->srs[i]->active == 0) && (index==-1)) index=i;
+  }
+
+  if (index==-1)
+    LOG_E(MAC,"SRS list is full\n");
+
+  return(index);
+}
+
+void nr_fill_srs(PHY_VARS_gNB *gNB,
+                 int frame,
+                 int slot,
+                 nfapi_nr_srs_pdu_t *srs_pdu) {
+
+  int id = nr_find_srs(srs_pdu->rnti,frame,slot,gNB);
+  AssertFatal( (id>=0) && (id<NUMBER_OF_NR_SRS_MAX),
+               "invalid id found for srs !!! rnti %04x id %d\n",srs_pdu->rnti,id);
+
+  NR_gNB_SRS_t  *srs = gNB->srs[id];
+  srs->frame = frame;
+  srs->slot = slot;
+  srs->active = 1;
+  memcpy((void*)&srs->srs_pdu, (void*)srs_pdu, sizeof(nfapi_nr_srs_pdu_t));
+}
+
+int nr_get_srs_signal(PHY_VARS_gNB *gNB,
+                      int frame,
+                      int slot,
+                      nfapi_nr_srs_pdu_t *srs_pdu,
+                      nr_srs_info_t *nr_srs_info,
+                      int32_t **srs_received_signal) {
+
+  if(nr_srs_info->sc_list_length == 0) {
+    LOG_E(NR_PHY, "(%d.%d) nr_srs_info was not generated yet!\n", frame, slot);
+    return -1;
+  }
+
+  int32_t **rxdataF = gNB->common_vars.rxdataF;
+  NR_DL_FRAME_PARMS *frame_parms = &gNB->frame_parms;
+
+  uint16_t n_symbols = (slot&3)*frame_parms->symbols_per_slot;                    // number of symbols until this slot
+  uint8_t l0 = frame_parms->symbols_per_slot - 1 - srs_pdu->time_start_position;  // starting symbol in this slot
+  uint64_t symbol_offset = (n_symbols+l0)*frame_parms->ofdm_symbol_size;
+
+  int32_t *rx_signal;
+  for (int ant = 0; ant < frame_parms->nb_antennas_rx; ant++) {
+
+    memset(srs_received_signal[ant], 0, frame_parms->ofdm_symbol_size*sizeof(int32_t));
+    rx_signal = &rxdataF[ant][symbol_offset];
+
+    for(int sc_idx = 0; sc_idx < nr_srs_info->sc_list_length; sc_idx++) {
+      srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]] = rx_signal[nr_srs_info->sc_list[sc_idx]];
+
+#ifdef SRS_DEBUG
+      uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_pdu->bwp_start*12;
+      int subcarrier_log = nr_srs_info->sc_list[sc_idx]-subcarrier_offset;
+      if(subcarrier_log < 0) {
+        subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size;
+      }
+      if(sc_idx == 0) {
+        LOG_I(NR_PHY,"________ Rx antenna %i ________\n", ant);
+      }
+      if(subcarrier_log%12 == 0) {
+        LOG_I(NR_PHY,"::::::::::::: %i :::::::::::::\n", subcarrier_log/12);
+      }
+      LOG_I(NR_PHY,"(%i)  \t%i\t%i\n",
+            subcarrier_log,
+            (int16_t)(srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]]&0xFFFF),
+            (int16_t)((srs_received_signal[ant][nr_srs_info->sc_list[sc_idx]]>>16)&0xFFFF));
+#endif
+    }
+  }
+  return 0;
+}
\ No newline at end of file
diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c
index 65ae28825201321ced5139d9bc785e2284f1f076..0c520aabe79418c3d077535e95bffd501cda95b1 100644
--- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c
+++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.c
@@ -260,3 +260,26 @@ short filt8_avlip5[8] = {
 
 short filt8_avlip6[8] = {
 13653,15019,16384,16384,16384,16384,16384,16384};
+
+// Comb size 2
+short filt8_start[8] = {
+    12288,8192,4096,0,0,0,0,0};
+
+short filt8_middle2[8] = {
+    4096,8192,8192,8192,4096,0,0,0};
+
+short filt8_middle4[8] = {
+    0,0,4096,8192,8192,8192,4096,0};
+
+short filt8_end[8] = {
+    4096,8192,12288,16384,0,0,0,0};
+
+// Comb size 4
+short filt16_start[16] = {
+    12288,8192,8192,8192,4096,0,0,0,0,0,0,0,0,0,0,0};
+
+short filt16_middle4[16] = {
+    4096,8192,8192,8192,8192,8192,8192,8192,4096,0,0,0,0,0,0,0};
+
+short filt16_end[16] = {
+    4096,8192,8192,8192,12288,16384,16384,16384,0,0,0,0,0,0,0,0};
\ No newline at end of file
diff --git a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
index e28736b51daf45dc7c133f1f210d46c89abfd571..72d1318545509905aed6c27e6d3a207311876a3a 100644
--- a/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
+++ b/openair1/PHY/NR_UE_ESTIMATION/filt16a_32.h
@@ -182,4 +182,15 @@ extern short filt8_avlip4[8];
 extern short filt8_avlip5[8];
 
 extern short filt8_avlip6[8];
+
+/*Comb size 2*/
+extern short filt8_start[8];
+extern short filt8_middle2[8];
+extern short filt8_middle4[8];
+extern short filt8_end[8];
+
+/*Comb size 4*/
+extern short filt16_start[16];
+extern short filt16_middle4[16];
+extern short filt16_end[16];
 #endif
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
index 7360eff4941cc8a847c4a8906fe6e26aa60902d3..8064093eed6e86c78ae92d29fb3143ee45480b30 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_dlsch_decoding.c
@@ -141,7 +141,7 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint
     a_segments = (a_segments/273)+1;
   }
 
-  uint16_t dlsch_bytes = a_segments*1056;  // allocated bytes per segment
+  uint32_t dlsch_bytes = a_segments*1056;  // allocated bytes per segment
   dlsch = (NR_UE_DLSCH_t *)malloc16(sizeof(NR_UE_DLSCH_t));
 
   if (dlsch) {
@@ -206,25 +206,9 @@ NR_UE_DLSCH_t *new_nr_ue_dlsch(uint8_t Kmimo,uint8_t Mdlharq,uint32_t Nsoft,uint
   return(NULL);
 }
 
-void nr_dlsch_unscrambling(int16_t *llr,
-                           uint32_t size,
-                           uint8_t q,
-                           uint32_t Nid,
-                           uint32_t n_RNTI) {
-  uint8_t reset;
-  uint32_t x1, x2, s=0;
-  reset = 1;
-  x2 = (n_RNTI<<15) + (q<<14) + Nid;
-
-  for (int i=0; i<size; i++) {
-    if ((i&0x1f)==0) {
-      s = lte_gold_generic(&x1, &x2, reset);
-      reset = 0;
-    }
-
-    if (((s>>(i&0x1f))&1)==1)
-      llr[i] = -llr[i];
-  }
+void nr_dlsch_unscrambling(int16_t *llr, uint32_t size, uint8_t q, uint32_t Nid, uint32_t n_RNTI)
+{
+  nr_codeword_unscrambling(llr, size, q, Nid, n_RNTI);
 }
 
 bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool last, notifiedFIFO_t *nf_p) {
@@ -233,6 +217,10 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool
   NR_UE_DLSCH_t *dlsch = (NR_UE_DLSCH_t *) rdata->dlsch;
   int r = rdata->segment_r;
 
+  merge_meas(&phy_vars_ue->dlsch_deinterleaving_stats, &rdata->ts_deinterleave);
+  merge_meas(&phy_vars_ue->dlsch_rate_unmatching_stats, &rdata->ts_rate_unmatch);
+  merge_meas(&phy_vars_ue->dlsch_ldpc_decoding_stats, &rdata->ts_ldpc_decode);
+
   bool decodeSuccess = (rdata->decodeIterations < (1+dlsch->max_ldpc_iterations));
 
   if (decodeSuccess) {
@@ -295,12 +283,6 @@ bool nr_ue_postDecode(PHY_VARS_NR_UE *phy_vars_ue, notifiedFIFO_elt_t *req, bool
 void nr_processDLSegment(void* arg) {
   ldpcDecode_ue_t *rdata = (ldpcDecode_ue_t*) arg;
   NR_UE_DLSCH_t *dlsch = rdata->dlsch;
-#if UE_TIMING_TRACE //TBD
-  PHY_VARS_NR_UE *phy_vars_ue = rdata->phy_vars_ue;
-  time_stats_t *dlsch_rate_unmatching_stats=&phy_vars_ue->dlsch_rate_unmatching_stats;
-  time_stats_t *dlsch_turbo_decoding_stats=&phy_vars_ue->dlsch_turbo_decoding_stats;
-  time_stats_t *dlsch_deinterleaving_stats=&phy_vars_ue->dlsch_deinterleaving_stats;
-#endif
   NR_DL_UE_HARQ_t *harq_process= rdata->harq_process;
   t_nrLDPC_dec_params *p_decoderParms = &rdata->decoderParms;
   int length_dec;
@@ -329,7 +311,7 @@ void nr_processDLSegment(void* arg) {
   __m128i *pv = (__m128i*)&z;
   __m128i *pl = (__m128i*)&l;
 
-  uint8_t  Ilbrm    = 0;
+  uint8_t Ilbrm = 1;
 
   Kr = harq_process->K; // [hna] overwrites this line "Kr = p_decParams->Z*kb"
   Kr_bytes = Kr>>3;
@@ -340,21 +322,16 @@ void nr_processDLSegment(void* arg) {
 
   t_nrLDPC_procBuf **p_nrLDPC_procBuf = harq_process->p_nrLDPC_procBuf;
 
-#if UE_TIMING_TRACE
-    start_meas(dlsch_deinterleaving_stats);
-#endif
+    start_meas(&rdata->ts_deinterleave);
     //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_IN);
     nr_deinterleaving_ldpc(E,
                            Qm,
                            harq_process->w[r], // [hna] w is e
                            dlsch_llr+r_offset);
     //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_DEINTERLEAVING, VCD_FUNCTION_OUT);
-#if UE_TIMING_TRACE
-    stop_meas(dlsch_deinterleaving_stats);
-#endif
-#if UE_TIMING_TRACE
-    start_meas(dlsch_rate_unmatching_stats);
-#endif
+    stop_meas(&rdata->ts_deinterleave);
+
+    start_meas(&rdata->ts_rate_unmatch);
     /* LOG_D(PHY,"HARQ_PID %d Rate Matching Segment %d (coded bits %d,E %d, F %d,unpunctured/repeated bits %d, TBS %d, mod_order %d, nb_rb %d, Nl %d, rv %d, round %d)...\n",
           harq_pid,r, G,E,harq_process->F,
           Kr*3,
@@ -379,22 +356,17 @@ void nr_processDLSegment(void* arg) {
                                  harq_process->F,
                                  Kr-harq_process->F-2*(p_decoderParms->Z))==-1) {
       //VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_DLSCH_RATE_MATCHING, VCD_FUNCTION_OUT);
-#if UE_TIMING_TRACE
-      stop_meas(dlsch_rate_unmatching_stats);
-#endif
+      stop_meas(&rdata->ts_rate_unmatch);
       LOG_E(PHY,"dlsch_decoding.c: Problem in rate_matching\n");
       rdata->decodeIterations = dlsch->max_ldpc_iterations + 1;
-	  return;
-    } else {
-#if UE_TIMING_TRACE
-      stop_meas(dlsch_rate_unmatching_stats);
-#endif
+      return;
     }
+    stop_meas(&rdata->ts_rate_unmatch);
 
     r_offset += E;
 
     if (LOG_DEBUGFLAG(DEBUG_DLSCH_DECOD)) {
-      LOG_I(PHY,"decoder input(segment %u) :",r);
+      LOG_D(PHY,"decoder input(segment %u) :",r);
 
       for (int i=0; i<E; i++)
         LOG_D(PHY,"%d : %d\n",i,harq_process->d[r][i]);
@@ -417,9 +389,7 @@ void nr_processDLSegment(void* arg) {
     }
 
     {
-#if UE_TIMING_TRACE
-      start_meas(dlsch_turbo_decoding_stats);
-#endif
+      start_meas(&rdata->ts_ldpc_decode);
       //set first 2*Z_c bits to zeros
       memset(&z[0],0,2*harq_process->Z*sizeof(int16_t));
       //set Filler bits
@@ -469,9 +439,7 @@ void nr_processDLSegment(void* arg) {
         harq_process->c[r][m]= (uint8_t) llrProcBuf[m];
       }
 
-#if UE_TIMING_TRACE
-      stop_meas(dlsch_turbo_decoding_stats);
-#endif
+      stop_meas(&rdata->ts_ldpc_decode);
     }
 }
 
@@ -502,6 +470,7 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
 
   // HARQ stats
   phy_vars_ue->dl_stats[harq_process->round]++;
+  LOG_D(PHY,"Round %d RV idx %d\n",harq_process->round,harq_process->rvidx);
   uint8_t kc;
   uint32_t Tbslbrm;// = 950984;
   uint16_t nb_rb;// = 30;
@@ -672,6 +641,9 @@ uint32_t nr_dlsch_decoding(PHY_VARS_NR_UE *phy_vars_ue,
     rdata->offset = offset;
     rdata->dlsch = dlsch;
     rdata->dlsch_id = 0;
+    reset_meas(&rdata->ts_deinterleave);
+    reset_meas(&rdata->ts_rate_unmatch);
+    reset_meas(&rdata->ts_ldpc_decode);
     pushTpool(&(pool_dl),req);
     nbDecode++;
     LOG_D(PHY,"Added a block to decode, in pipe: %d\n",nbDecode);
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
index 6acafe46530008b0d96fdc778cba4e7003bc878c..c79d873127226fee91b600021c33fa429bcb2bbb 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_initial_sync.c
@@ -193,8 +193,7 @@ char prefix_string[2][9] = {"NORMAL","EXTENDED"};
 
 int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
                     PHY_VARS_NR_UE *ue,
-                    int n_frames, int sa,
-                    int dlsch_parallel)
+                    int n_frames, int sa)
 {
 
   int32_t sync_pos, sync_pos_frame; // k_ssb, N_ssb_crb, sync_pos2,
@@ -561,8 +560,7 @@ int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
                                          SI_PDSCH,
                                          ue->dlsch_SI[gnb_id],
                                          NULL,
-                                         &ue->dlsch_SI_errors[gnb_id],
-                                         dlsch_parallel);
+                                         &ue->dlsch_SI_errors[gnb_id]);
 
           // deactivate dlsch once dlsch proc is done
           ue->dlsch_SI[gnb_id]->active = 0;
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 3cb002f9e1f39ee3f385ea2489ca03d2924f2a9c..239731208eb45ff117e4faff8ecee59348aef30b 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h
@@ -1055,14 +1055,15 @@ int nr_ulsch_encoding(PHY_VARS_NR_UE *ue,
   @param[in] size, of input bits
   @param[in] Nid, cell id
   @param[in] n_RNTI, CRNTI
+  @param[in] uci_on_pusch whether UCI placeholder bits need to be scrambled (true -> no optimized scrambling)
   @param[out] out, the scrambled bits
 */
-
 void nr_pusch_codeword_scrambling(uint8_t *in,
-                         uint32_t size,
-                         uint32_t Nid,
-                         uint32_t n_RNTI,
-                         uint32_t* out);
+                                  uint32_t size,
+                                  uint32_t Nid,
+                                  uint32_t n_RNTI,
+                                  bool uci_on_pusch,
+                                  uint32_t* out);
 
 /** \brief Perform the following functionalities:
     - encoding
@@ -1423,8 +1424,7 @@ void generate_RIV_tables(void);
 int nr_initial_sync(UE_nr_rxtx_proc_t *proc,
                     PHY_VARS_NR_UE *phy_vars_ue, 
                     int n_frames,
-                    int sa,
-                    int dlsch_parallel);
+                    int sa);
 
 /*!
   \brief This function gets the carrier frequencies either from FP or command-line-set global variables, depending on the availability of the latter
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
index b4ee4f5b41d047483cdd90afa7491a225072d478..9b9f1add6e175dd9d391e55660c956ff5739b1f7 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_transport_ue.h
@@ -149,7 +149,7 @@ typedef struct {
   /// ACK/NAK Bundling flag
   uint8_t bundling;
   /// Concatenated "g"-sequences (for definition see 36-212 V15.4.0 2018-12, p.31)
-  uint8_t g[MAX_NUM_NR_CHANNEL_BITS];
+  uint8_t g[MAX_NUM_NR_CHANNEL_BITS] __attribute__ ((aligned(32)));
   /// Interleaved "h"-sequences (for definition see 36-212 V8.6 2009-03, p.17-18)
   uint8_t h[MAX_NUM_NR_CHANNEL_BITS];
   /// Scrambled "b"-sequences (for definition see 36-211 V8.6 2009-03, p.14)
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
index b2e247667074a8a965cb53b5e9f70db15a684c03..553d4fa4f7baed980f9aeefb0d0432a7a32093ed 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_coding.c
@@ -118,7 +118,7 @@ NR_UE_ULSCH_t *new_nr_ue_ulsch(uint16_t N_RB_UL,
     a_segments = a_segments/273 +1;
   }  
 
-  uint16_t ulsch_bytes = a_segments*1056;  // allocated bytes per segment
+  uint32_t ulsch_bytes = a_segments*1056;  // allocated bytes per segment
 
   ulsch = (NR_UE_ULSCH_t *)malloc16(sizeof(NR_UE_ULSCH_t));
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
index 73615ffb6e74c194be2c86ead7d1b183f7b34261..0c188e9119ff49a4a1b9137b9cf4295b8354127e 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_ulsch_ue.c
@@ -53,12 +53,12 @@
 
 //extern int32_t uplink_counter;
 
-void nr_pusch_codeword_scrambling(uint8_t *in,
-                         uint32_t size,
-                         uint32_t Nid,
-                         uint32_t n_RNTI,
-                         uint32_t* out) {
-
+void nr_pusch_codeword_scrambling_uci(uint8_t *in,
+                                      uint32_t size,
+                                      uint32_t Nid,
+                                      uint32_t n_RNTI,
+                                      uint32_t* out)
+{
   uint8_t reset, b_idx;
   uint32_t x1, x2, s=0, temp_out;
 
@@ -89,7 +89,19 @@ void nr_pusch_codeword_scrambling(uint8_t *in,
       *out ^= (((in[i])&1) ^ ((s>>b_idx)&1))<<b_idx;
     //printf("i %d b_idx %d in %d s 0x%08x out 0x%08x\n", i, b_idx, in[i], s, *out);
   }
+}
 
+void nr_pusch_codeword_scrambling(uint8_t *in,
+                                  uint32_t size,
+                                  uint32_t Nid,
+                                  uint32_t n_RNTI,
+                                  bool uci_on_pusch,
+                                  uint32_t* out)
+{
+  if (uci_on_pusch)
+    nr_pusch_codeword_scrambling_uci(in, size, Nid, n_RNTI, out);
+  else
+    nr_codeword_scrambling(in, size, 0, Nid, n_RNTI, out);
 }
 
 void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
@@ -187,6 +199,7 @@ void nr_ue_ulsch_procedures(PHY_VARS_NR_UE *UE,
                                  available_bits,
                                  ulsch_ue->Nid_cell,
                                  rnti,
+                                 false,
                                  scrambled_output[cwd_index]); // assume one codeword for the moment
 
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
index 4109950df6156da0204c7d4e7fe7faa5f93d9971..f3a953c9a85f58030b28e0251c92e969e4b382e8 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.c
@@ -38,7 +38,6 @@
 #undef DEFINE_VARIABLES_PHY_IMPLEMENTATION_DEFS_NR_H
 
 #include "PHY/defs_nr_UE.h"
-//#include "extern.h"
 #include "PHY/NR_REFSIG/ss_pbch_nr.h"
 #include "PHY/NR_REFSIG/dmrs_nr.h"
 #include "PHY/NR_REFSIG/ul_ref_seq_nr.h"
@@ -47,11 +46,13 @@
 #include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h"
 #undef DEFINE_VARIABLES_SRS_MODULATION_NR_H
 
+//#define SRS_DEBUG
+
 /*******************************************************************
 *
 * NAME :         generate_srs
 *
-* PARAMETERS :   pointer to resource set
+* PARAMETERS :   pointer to srs config pdu
 *                pointer to transmit buffer
 *                amplitude scaling for this physical signal
 *                slot number of transmission
@@ -73,84 +74,94 @@
 *                - no antenna switching*
 *
 *********************************************************************/
-int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
-                        NR_DL_FRAME_PARMS *frame_parms,
-                        int32_t *txptr,
-                        int16_t amp,
-                        UE_nr_rxtx_proc_t *proc)
+int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
+                    NR_DL_FRAME_PARMS *frame_parms,
+                    int32_t *txptr,
+                    nr_srs_info_t *nr_srs_info,
+                    int16_t amp,
+                    int frame_number,
+                    int slot_number)
 {
   uint8_t n_SRS_cs_max;
-  uint8_t u, v_nu;
+  uint8_t u;
+  uint8_t v_nu;
   uint32_t f_gh = 0;
-  SRS_Resource_t *p_SRS_Resource;
-  int frame_number = proc->frame_tx;
-  int slot_number = proc->nr_slot_tx;
-  uint16_t n_SRS, n_SRS_cs_i;
+  uint16_t n_SRS;
+  uint16_t n_SRS_cs_i;
   double alpha_i;
   uint8_t K_TC_p;
-  uint16_t n_b[B_SRS_NUMBER], F_b, subcarrier;
-  uint8_t N_b, k_0_overbar_p;
-
-  if (p_srs_resource_set->p_srs_ResourceList[0] == NULL) {
-    LOG_E(PHY,"generate_srs: No resource associated with the SRS resource set!\n");
-    return (-1);
-  }
-  else {
-    if (p_srs_resource_set->number_srs_Resource <= MAX_NR_OF_SRS_RESOURCES_PER_SET) {
-      p_SRS_Resource = p_srs_resource_set->p_srs_ResourceList[0];
-    }
-    else {
-      LOG_E(PHY,"generate_srs: resource number of this resource set %d exceeds maximum supported value %d!\n", p_srs_resource_set->number_srs_Resource, MAX_NR_OF_SRS_RESOURCES_PER_SET);
-      return (-1);
-    }
+  uint16_t n_b[B_SRS_NUMBER];
+  uint16_t F_b;
+  uint16_t subcarrier;
+  uint8_t N_b;
+  uint8_t k_0_overbar_p;
+
+  // get parameters from srs_config_pdu
+  uint8_t B_SRS  = srs_config_pdu->bandwidth_index;
+  uint8_t C_SRS  = srs_config_pdu->config_index;
+  uint8_t b_hop = srs_config_pdu->frequency_hopping;
+  uint8_t K_TC = 2<<srs_config_pdu->comb_size;
+  uint8_t K_TC_overbar = srs_config_pdu->comb_offset;         // FFS_TODO_NR is this parameter for K_TC_overbar ??
+  uint8_t n_SRS_cs = srs_config_pdu->cyclic_shift;
+  uint8_t n_ID_SRS = srs_config_pdu->sequence_id;
+  uint8_t n_shift = srs_config_pdu->frequency_position;       // it adjusts the SRS allocation to align with the common resource block grid in multiples of four
+  uint8_t n_RRC = srs_config_pdu->frequency_shift;
+  uint8_t groupOrSequenceHopping = srs_config_pdu->group_or_sequence_hopping;
+  uint8_t l_offset = srs_config_pdu->time_start_position;
+  uint16_t T_SRS = srs_config_pdu->t_srs;
+  uint16_t T_offset = srs_config_pdu->t_offset;               // FFS_TODO_NR to check interface with RRC
+  uint8_t R = 1<<srs_config_pdu->num_repetitions;
+  uint8_t N_ap = 1<<srs_config_pdu->num_ant_ports;            // antenna port for transmission
+  uint8_t N_symb_SRS = 1<<srs_config_pdu->num_symbols;        // consecutive OFDM symbols
+  uint8_t l0 = frame_parms->symbols_per_slot - 1 - l_offset;  // starting position in the time domain
+  uint8_t k_0_p;                                              // frequency domain starting position
+
+  uint64_t subcarrier_offset = frame_parms->first_carrier_offset + srs_config_pdu->bwp_start*N_SC_RB;
+
+  if(nr_srs_info) {
+    nr_srs_info->sc_list_length = 0;
+    nr_srs_info->srs_generated_signal_bits = log2_approx(amp);
   }
 
-  if (p_srs_resource_set->resourceType != periodic) {
-    LOG_E(PHY,"generate_srs: only SRS periodic is supported up to now!\n");
-    return (-1);
-  }
-  /* get parameters from SRS resource configuration */
-  uint8_t B_SRS  = p_SRS_Resource->freqHopping_b_SRS;
-  uint8_t C_SRS  = p_SRS_Resource->freqHopping_c_SRS;
-  uint8_t b_hop = p_SRS_Resource->freqHopping_b_hop;
-  uint8_t K_TC = p_SRS_Resource->transmissionComb;
-  uint8_t K_TC_overbar = p_SRS_Resource->combOffset;    /* FFS_TODO_NR is this parameter for K_TC_overbar ?? */
-  uint8_t n_SRS_cs = p_SRS_Resource->cyclicShift;
-  uint8_t n_ID_SRS = p_SRS_Resource->sequenceId;
-  uint8_t n_shift = p_SRS_Resource->freqDomainPosition; /* it adjusts the SRS allocation to align with the common resource block grid in multiples of four */
-  uint8_t n_RRC = p_SRS_Resource->freqDomainShift;
-  uint8_t groupOrSequenceHopping = p_SRS_Resource->groupOrSequenceHopping;
-
-  uint8_t l_offset = p_SRS_Resource->resourceMapping_startPosition;
-
-  uint16_t T_SRS = srs_period[p_SRS_Resource->SRS_Periodicity];
-  uint16_t T_offset = p_SRS_Resource->SRS_Offset;;                   /* FFS_TODO_NR to check interface with RRC */
-  uint8_t R = p_SRS_Resource->resourceMapping_repetitionFactor;
-
-  /* TS 38.211 6.4.1.4.1 SRS resource */
-  uint8_t N_ap = (uint8_t)p_SRS_Resource->nrof_SrsPorts;            /* antenna port for transmission */
-  uint8_t N_symb_SRS = p_SRS_Resource->resourceMapping_nrofSymbols; /* consecutive OFDM symbols */
-  uint8_t l0 = N_SYMB_SLOT - 1 - l_offset;                          /* starting position in the time domain */
-  uint8_t k_0_p;                                                    /* frequency domain starting position */
+#ifdef SRS_DEBUG
+  LOG_I(NR_PHY,"Frame = %i, slot = %i\n", frame_number, slot_number);
+  LOG_I(NR_PHY,"B_SRS = %i\n", B_SRS);
+  LOG_I(NR_PHY,"C_SRS = %i\n", C_SRS);
+  LOG_I(NR_PHY,"b_hop = %i\n", b_hop);
+  LOG_I(NR_PHY,"K_TC = %i\n", K_TC);
+  LOG_I(NR_PHY,"K_TC_overbar = %i\n", K_TC_overbar);
+  LOG_I(NR_PHY,"n_SRS_cs = %i\n", n_SRS_cs);
+  LOG_I(NR_PHY,"n_ID_SRS = %i\n", n_ID_SRS);
+  LOG_I(NR_PHY,"n_shift = %i\n", n_shift);
+  LOG_I(NR_PHY,"n_RRC = %i\n", n_RRC);
+  LOG_I(NR_PHY,"groupOrSequenceHopping = %i\n", groupOrSequenceHopping);
+  LOG_I(NR_PHY,"l_offset = %i\n", l_offset);
+  LOG_I(NR_PHY,"T_SRS = %i\n", T_SRS);
+  LOG_I(NR_PHY,"T_offset = %i\n", T_offset);
+  LOG_I(NR_PHY,"R = %i\n", R);
+  LOG_I(NR_PHY,"N_ap = %i\n", N_ap);
+  LOG_I(NR_PHY,"N_symb_SRS = %i\n", N_symb_SRS);
+  LOG_I(NR_PHY,"l0 = %i\n", l0);
+#endif
 
   if (N_ap != port1) {
-    LOG_E(PHY, "generate_srs: this number of antenna ports %d is not yet supported!\n", N_ap);
+    LOG_E(NR_PHY, "generate_srs: this number of antenna ports %d is not yet supported!\n", N_ap);
     return (-1);
   }
   if (N_symb_SRS != 1) {
-    LOG_E(PHY, "generate_srs: this number of srs symbol  %d is not yet supported!\n", N_symb_SRS);
+    LOG_E(NR_PHY, "generate_srs: this number of srs symbol  %d is not yet supported!\n", N_symb_SRS);
   	return (-1);
   }
   if (groupOrSequenceHopping != neitherHopping) {
-    LOG_E(PHY, "generate_srs: sequence hopping is not yet supported!\n");
+    LOG_E(NR_PHY, "generate_srs: sequence hopping is not yet supported!\n");
     return (-1);
   }
   if (R == 0) {
-    LOG_E(PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", R);
+    LOG_E(NR_PHY, "generate_srs: this parameter repetition factor %d is not consistent !\n", R);
     return (-1);
   }
   else if (R > N_symb_SRS) {
-    LOG_E(PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", R, N_symb_SRS);
+    LOG_E(NR_PHY, "generate_srs: R %d can not be greater than N_symb_SRS %d !\n", R, N_symb_SRS);
     return (-1);
   }
   /* see 38211 6.4.1.4.2 Sequence generation */
@@ -163,15 +174,15 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
     // delta = 1;     /* delta = log2(K_TC) */
   }
   else {
-	LOG_E(PHY, "generate_srs: SRS unknown value for K_TC %d !\n", K_TC);
+	LOG_E(NR_PHY, "generate_srs: SRS unknown value for K_TC %d !\n", K_TC);
     return (-1);
   }
   if (n_SRS_cs >= n_SRS_cs_max) {
-    LOG_E(PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >=  n_SRS_cs_max %d !\n", n_SRS_cs, n_SRS_cs_max);
+    LOG_E(NR_PHY, "generate_srs: inconsistent parameter n_SRS_cs %d >=  n_SRS_cs_max %d !\n", n_SRS_cs, n_SRS_cs_max);
     return (-1);
   }
   if (T_SRS == 0) {
-    LOG_E(PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", T_SRS);
+    LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d can not be equal to zero !\n", T_SRS);
     return (-1);
   }
   else
@@ -180,7 +191,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
     while (srs_periodicity[index] != T_SRS) {
       index++;
       if (index == SRS_PERIODICITY) {
-        LOG_E(PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", T_SRS);
+        LOG_E(NR_PHY, "generate_srs: inconsistent parameter T_SRS %d not specified !\n", T_SRS);
         return (-1);
       }
     }
@@ -202,10 +213,9 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
     /* A UE may be configured to transmit an SRS resource on  adjacent symbols within the last six symbols of a slot, */
     /* where all antenna ports of the SRS resource are mapped to each symbol of the resource */
 
-
     uint8_t l = p_index;
     if (l >= N_symb_SRS) {
-      LOG_E(PHY, "generate_srs: number of antenna ports %d and number of srs symbols %d are different !\n", N_ap, N_symb_SRS);
+      LOG_E(NR_PHY, "generate_srs: number of antenna ports %d and number of srs symbols %d are different !\n", N_ap, N_symb_SRS);
     }
 
     switch(groupOrSequenceHopping) {
@@ -247,7 +257,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
       }
       default:
       {
-        LOG_E(PHY, "generate_srs: unknown hopping setting %d !\n", groupOrSequenceHopping);
+        LOG_E(NR_PHY, "generate_srs: unknown hopping setting %d !\n", groupOrSequenceHopping);
         return (-1);
       }
     }
@@ -274,7 +284,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
           N_b = 1;
         }
         /* periodicity and offset */
-        if (p_srs_resource_set->resourceType == aperiodic) {
+        if (srs_config_pdu->resource_type == aperiodic) {
           n_SRS = l/R;
         }
         else {
@@ -315,7 +325,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
       k_0_p += K_TC * M_sc_b_SRS * n_b[b];
     }
 
-    subcarrier = (frame_parms->first_carrier_offset) + k_0_p;
+    subcarrier = subcarrier_offset + k_0_p;
     if (subcarrier>frame_parms->ofdm_symbol_size) {
       subcarrier -= frame_parms->ofdm_symbol_size;
     }
@@ -327,7 +337,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
     }
 
     if (ul_allocated_re[M_sc_b_SRS_index] != M_sc_b_SRS) {
-      LOG_E(PHY, "generate_srs: srs uplink allocation %d can not be found! \n", M_sc_b_SRS);
+      LOG_E(NR_PHY, "generate_srs: srs uplink allocation %d can not be found! \n", M_sc_b_SRS);
       return (-1);
     }
 
@@ -363,13 +373,31 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
 
       txptr[subcarrier] = (real_amp & 0xFFFF) + ((imag_amp<<16)&0xFFFF0000);
 
+      if(nr_srs_info) {
+        nr_srs_info->sc_list[nr_srs_info->sc_list_length] = subcarrier;
+        nr_srs_info->sc_list_length++;
+      }
+
+#ifdef SRS_DEBUG
+      int subcarrier_log = subcarrier-subcarrier_offset;
+      if(subcarrier_log < 0) {
+        subcarrier_log = subcarrier_log + frame_parms->ofdm_symbol_size;
+      }
+      if( subcarrier_log%12 == 0 ) {
+        LOG_I(NR_PHY,"------------ %d ------------\n", subcarrier_log/12);
+      }
+      LOG_I(NR_PHY,"(%d)  \t%i\t%i\n", subcarrier_log, (int16_t)(real_amp&0xFFFF), (int16_t)(imag_amp&0xFFFF));
+#endif
+
       subcarrier += (K_TC); /* subcarrier increment */
 
-      if (subcarrier >= frame_parms->ofdm_symbol_size)
+      if (subcarrier >= frame_parms->ofdm_symbol_size) {
         subcarrier=subcarrier-frame_parms->ofdm_symbol_size;
+      }
+
     }
     /* process next symbol */
-    txptr = txptr + frame_parms->ofdm_symbol_size;
+    //txptr = txptr + frame_parms->ofdm_symbol_size;
   }
 
   return (0);
@@ -377,40 +405,7 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
 
 /*******************************************************************
 *
-* NAME :         is_srs_period_nr
-*
-* PARAMETERS :   pointer to resource set
-*                pointer to transmit buffer
-*                amplitude scaling for this physical signal
-*                slot number of transmission
-* RETURN :        0  if it is a valid slot for transmitting srs
-*                -1 if srs should not be transmitted
-*
-* DESCRIPTION :  for periodic,
-*
-*********************************************************************/
-int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, NR_DL_FRAME_PARMS *frame_parms, int frame_tx, int slot_tx)
-{
-  uint16_t T_SRS = srs_period[p_SRS_Resource->SRS_Periodicity];
-  uint16_t T_offset = p_SRS_Resource->SRS_Offset; /* FFS_TODO_NR to check interface */
-
-  if (T_offset > T_SRS) {
-    LOG_E(PHY,"is_srs_occasion_nr: T_offset %d is greater than T_SRS %d!\n", T_offset, T_SRS);
-    return (-1);
-  }
-
-  int16_t N_slot_frame = frame_parms->slots_per_frame;
-  if ((N_slot_frame*frame_tx + slot_tx - T_offset)%T_SRS == 0) {
-    return (0);
-  }
-  else {
-    return (-1);
-  }
-}
-
-/*******************************************************************
-*
-* NAME :         ue_srs_procedure_nr
+* NAME :         ue_srs_procedures_nr
 *
 * PARAMETERS :   pointer to ue context
 *                pointer to rxtx context*
@@ -422,54 +417,51 @@ int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource, NR_DL_FRAME_PARMS *frame_pa
 *                send srs according to current configuration
 *
 *********************************************************************/
-int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id)
+int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id)
 {
-  NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms);
-  SRS_NR *p_srs_nr = &(ue->frame_parms.srs_nr);
-  SRS_ResourceSet_t *p_srs_resource_set = frame_parms->srs_nr.p_SRS_ResourceSetList[p_srs_nr->active_srs_Resource_Set];
-  int generate_srs = 0;
 
-  /* is there any resource set which has been configurated ? */
-  if (p_srs_nr->number_srs_Resource_Set != 0) {
-
-    /* what is the current active resource set ? */
-    if (p_srs_nr->active_srs_Resource_Set > MAX_NR_OF_SRS_RESOURCE_SET) {
-      LOG_W(PHY,"phy_procedures_UE_TX: srs active %d greater than maximum %d!\n", p_srs_nr->active_srs_Resource_Set, MAX_NR_OF_SRS_RESOURCE_SET);
-    }
-    else {
-      /* SRS resource set configurated ? */
-      if (p_srs_resource_set != NULL) {
+  if(!ue->srs_vars[0]->active) {
+    return -1;
+  }
+  ue->srs_vars[0]->active = false;
+
+  nfapi_nr_srs_pdu_t *srs_config_pdu = (nfapi_nr_srs_pdu_t*)&ue->srs_vars[0]->srs_config_pdu;
+
+#ifdef SRS_DEBUG
+  LOG_I(NR_PHY,"Frame = %i, slot = %i\n", proc->frame_tx, proc->nr_slot_tx);
+  LOG_I(NR_PHY,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti);
+  LOG_I(NR_PHY,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle);
+  LOG_I(NR_PHY,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size);
+  LOG_I(NR_PHY,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start);
+  LOG_I(NR_PHY,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing);
+  LOG_I(NR_PHY,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix);
+  LOG_I(NR_PHY,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports);
+  LOG_I(NR_PHY,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols);
+  LOG_I(NR_PHY,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions);
+  LOG_I(NR_PHY,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position);
+  LOG_I(NR_PHY,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index);
+  LOG_I(NR_PHY,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id);
+  LOG_I(NR_PHY,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index);
+  LOG_I(NR_PHY,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size);
+  LOG_I(NR_PHY,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset);
+  LOG_I(NR_PHY,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift);
+  LOG_I(NR_PHY,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position);
+  LOG_I(NR_PHY,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift);
+  LOG_I(NR_PHY,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping);
+  LOG_I(NR_PHY,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping);
+  LOG_I(NR_PHY,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type);
+  LOG_I(NR_PHY,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs);
+  LOG_I(NR_PHY,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset);
+#endif
 
-        SRS_Resource_t *p_srs_resource = frame_parms->srs_nr.p_SRS_ResourceSetList[p_srs_nr->active_srs_Resource_Set]->p_srs_ResourceList[0];
+  NR_DL_FRAME_PARMS *frame_parms = &(ue->frame_parms);
+  uint16_t symbol_offset = (frame_parms->symbols_per_slot - 1 - srs_config_pdu->time_start_position)*frame_parms->ofdm_symbol_size;
 
-        /* SRS resource configurated ? */
-        if (p_srs_resource != NULL) {
-          if (p_srs_resource_set->resourceType == periodic) {
-            if (is_srs_period_nr(p_srs_resource, frame_parms, proc->frame_tx, proc->nr_slot_tx) == 0) {
-              generate_srs = 1;
-            }
-          }
-        }
-        else {
-          LOG_W(PHY,"phy_procedures_UE_TX: no configurated srs resource!\n");
-        }
-      }
-    }
-  }
-  if (generate_srs == 1) {
-    int16_t txptr = AMP;
-    uint16_t nsymb = (ue->frame_parms.Ncp==0) ? 14:12;
-    uint16_t symbol_offset = (int)ue->frame_parms.ofdm_symbol_size*((proc->nr_slot_tx*nsymb)+(nsymb-1));
-    if (generate_srs_nr(p_srs_resource_set, frame_parms, &ue->common_vars.txdataF[eNB_id][symbol_offset], txptr, proc) == 0) {
-      return 0;
-    }
-    else
-    {
-      return (-1);
-    }
-  }
-  else {
-    return (-1);
+  if (generate_srs_nr(srs_config_pdu, frame_parms, &ue->common_vars.txdataF[gNB_id][symbol_offset], ue->nr_srs_info,
+                      AMP, proc->frame_tx, proc->nr_slot_tx) == 0) {
+    return 0;
+  } else {
+    return -1;
   }
 }
 
diff --git a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h
index 86fd7fcc917f5ada3eaff86d814198576d6ece62..e43bbe4934bc58c8312dd99cd61845525c312145 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h
+++ b/openair1/PHY/NR_UE_TRANSPORT/srs_modulation_nr.h
@@ -136,15 +136,19 @@ EXTERN const uint16_t srs_periodicity[SRS_PERIODICITY]
 /** \brief This function generates the sounding reference symbol (SRS) for the uplink according to 38.211 6.4.1.4 Sounding reference signal
     @param frame_parms NR DL Frame parameters
     @param txdataF pointer to the frequency domain TX signal
+    @param nr_srs_info pointer to the srs info structure
     @param amp amplitude of generated signal
-    @param proc pointer to the transmit parameters
+    @param frame_number frame number
+    @param slot_number slot number
     @returns 0 on success -1 on error with message */
 
-int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
-                        NR_DL_FRAME_PARMS *frame_parms,
-                        int32_t *txptr,
-                        int16_t amp,
-                        UE_nr_rxtx_proc_t *proc);
+int generate_srs_nr(nfapi_nr_srs_pdu_t *srs_config_pdu,
+                    NR_DL_FRAME_PARMS *frame_parms,
+                    int32_t *txptr,
+                    nr_srs_info_t *nr_srs_info,
+                    int16_t amp,
+                    int frame_number,
+                    int slot_number);
 
 /** \brief This function checks for periodic srs if srs should be transmitted in this slot
  *  @param p_SRS_Resource pointer to active resource
@@ -155,13 +159,14 @@ int32_t generate_srs_nr(SRS_ResourceSet_t *p_srs_resource_set,
 int is_srs_period_nr(SRS_Resource_t *p_SRS_Resource,
                      NR_DL_FRAME_PARMS *frame_parms,
                      int frame_tx, int slot_tx);
+
 /** \brief This function processes srs configuration
  *  @param ue context
     @param rxtx context
-    @param current eNB identifier
+    @param current gNB_id identifier
     @returns 0 if srs is transmitted -1 otherwise */
 
-int ue_srs_procedure_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t eNB_id);
+int ue_srs_procedures_nr(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t gNB_id);
 
 #undef EXTERN
 #undef INIT_VARIABLES_SRS_MODULATION_NR_H
diff --git a/openair1/PHY/TOOLS/time_meas.h b/openair1/PHY/TOOLS/time_meas.h
index 023640aa0e69beb3d2c2be502a6ae28a18021a9a..ed4e9a125f1c5cf496c8819937a8d45df01a711d 100644
--- a/openair1/PHY/TOOLS/time_meas.h
+++ b/openair1/PHY/TOOLS/time_meas.h
@@ -179,6 +179,16 @@ static inline void copy_meas(time_stats_t *dst_ts,time_stats_t *src_ts) {
   }
 }
 
+static inline void merge_meas(time_stats_t *dst_ts, time_stats_t *src_ts)
+{
+  if (!opp_enabled)
+    return;
+  dst_ts->trials += src_ts->trials;
+  dst_ts->diff += src_ts->diff;
+  if (src_ts->max > dst_ts->max)
+    dst_ts->max = src_ts->max;
+}
+
 extern notifiedFIFO_t measur_fifo;
 #define CPUMEASUR_SECTION "cpumeasur"
 
diff --git a/openair1/PHY/defs_gNB.h b/openair1/PHY/defs_gNB.h
index 0ba2a5dfd1ab4042f8b0f69a34fb890b6c911224..7c7d30a6e2f21ddb8c5dcf73fa7fb6f809f17320 100644
--- a/openair1/PHY/defs_gNB.h
+++ b/openair1/PHY/defs_gNB.h
@@ -397,6 +397,16 @@ typedef struct {
   nfapi_nr_pucch_pdu_t pucch_pdu;
 } NR_gNB_PUCCH_t;
 
+typedef struct {
+  uint8_t active;
+  /// Frame where current SRS pdu was received
+  uint32_t frame;
+  /// Slot where current SRS pdu was received
+  uint32_t slot;
+  /// ULSCH PDU
+  nfapi_nr_srs_pdu_t srs_pdu;
+} NR_gNB_SRS_t;
+
 typedef struct {
   /// \brief Pointers (dynamic) to the received data in the time domain.
   /// - first index: rx antenna [0..nb_antennas_rx[
@@ -757,6 +767,7 @@ typedef struct PHY_VARS_gNB_s {
   NR_gNB_PRACH       prach_vars;
   NR_gNB_PUSCH       *pusch_vars[NUMBER_OF_NR_ULSCH_MAX];
   NR_gNB_PUCCH_t     *pucch[NUMBER_OF_NR_PUCCH_MAX];
+  NR_gNB_SRS_t       *srs[NUMBER_OF_NR_SRS_MAX];
   NR_gNB_PDCCH_t     pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX];
   NR_gNB_UL_PDCCH_t  ul_pdcch_pdu[NUMBER_OF_NR_PDCCH_MAX];
   NR_gNB_DLSCH_t     *dlsch[NUMBER_OF_NR_DLSCH_MAX][2];    // Nusers times two spatial streams
@@ -770,6 +781,9 @@ typedef struct PHY_VARS_gNB_s {
   NR_gNB_UCI_STATS_t uci_stats[NUMBER_OF_NR_UCI_STATS_MAX];
   t_nrPolar_params    *uci_polarParams;
 
+  /// SRS variables
+  nr_srs_info_t *nr_srs_info[NUMBER_OF_NR_SRS_MAX];
+
   uint8_t pbch_configured;
   char gNB_generate_rar;
 
diff --git a/openair1/PHY/defs_nr_UE.h b/openair1/PHY/defs_nr_UE.h
index 69978f55482aa4675ad4600f7f0dacc44d480330..bca956bf75bcafb31526b77f3a2a803201bb17ad 100644
--- a/openair1/PHY/defs_nr_UE.h
+++ b/openair1/PHY/defs_nr_UE.h
@@ -706,6 +706,11 @@ typedef struct {
   fapi_nr_ul_config_prach_pdu prach_pdu;
 } NR_UE_PRACH;
 
+typedef struct {
+  bool active;
+  fapi_nr_ul_config_srs_pdu srs_config_pdu;
+} NR_UE_SRS;
+
 // structure used for multiple SSB detection
 typedef struct NR_UE_SSB {
   uint8_t i_ssb;   // i_ssb between 0 and 7 (it corresponds to ssb_index only for Lmax=4,8)
@@ -815,6 +820,7 @@ typedef struct {
   NR_UE_PBCH      *pbch_vars[NUMBER_OF_CONNECTED_gNB_MAX];
   NR_UE_PDCCH     *pdcch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX];
   NR_UE_PRACH     *prach_vars[NUMBER_OF_CONNECTED_gNB_MAX];
+  NR_UE_SRS       *srs_vars[NUMBER_OF_CONNECTED_gNB_MAX];
   NR_UE_PUSCH     *pusch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX];
   NR_UE_PUCCH     *pucch_vars[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX];
   NR_UE_DLSCH_t   *dlsch[RX_NB_TH_MAX][NUMBER_OF_CONNECTED_gNB_MAX][NR_MAX_NB_CODEWORDS]; // two RxTx Threads
@@ -967,6 +973,8 @@ typedef struct {
   /// PUSCH contention-based access vars
   PUSCH_CA_CONFIG_DEDICATED  pusch_ca_config_dedicated[NUMBER_OF_eNB_MAX]; // lola
 
+  /// SRS variables
+  nr_srs_info_t *nr_srs_info;
 
   //#if defined(UPGRADE_RAT_NR)
 #if 1
@@ -1004,6 +1012,8 @@ typedef struct {
   time_stats_t phy_proc_tx;
   time_stats_t phy_proc_rx[RX_NB_TH];
 
+  time_stats_t ue_ul_indication_stats;
+
   uint32_t use_ia_receiver;
 
   time_stats_t ofdm_mod_stats;
@@ -1012,7 +1022,6 @@ typedef struct {
   time_stats_t ulsch_modulation_stats;
   time_stats_t ulsch_segmentation_stats;
   time_stats_t ulsch_rate_matching_stats;
-  time_stats_t ulsch_turbo_encoding_stats;
   time_stats_t ulsch_interleaving_stats;
   time_stats_t ulsch_multiplexing_stats;
 
@@ -1025,6 +1034,7 @@ typedef struct {
   time_stats_t pdsch_procedures_per_slot_stat[RX_NB_TH][LTE_SLOTS_PER_SUBFRAME];
   time_stats_t dlsch_procedures_stat[RX_NB_TH];
 
+  time_stats_t rx_pdsch_stats;
   time_stats_t ofdm_demod_stats;
   time_stats_t dlsch_rx_pdcch_stats;
   time_stats_t rx_dft_stats;
@@ -1033,13 +1043,13 @@ typedef struct {
   time_stats_t dlsch_decoding_stats[2];
   time_stats_t dlsch_demodulation_stats;
   time_stats_t dlsch_rate_unmatching_stats;
-  time_stats_t dlsch_turbo_decoding_stats;
+  time_stats_t dlsch_ldpc_decoding_stats;
   time_stats_t dlsch_deinterleaving_stats;
   time_stats_t dlsch_llr_stats;
   time_stats_t dlsch_llr_stats_parallelization[RX_NB_TH][LTE_SLOTS_PER_SUBFRAME];
   time_stats_t dlsch_unscrambling_stats;
   time_stats_t dlsch_rate_matching_stats;
-  time_stats_t dlsch_turbo_encoding_stats;
+  time_stats_t dlsch_ldpc_encoding_stats;
   time_stats_t dlsch_interleaving_stats;
   time_stats_t dlsch_tc_init_stats;
   time_stats_t dlsch_tc_alpha_stats;
@@ -1098,6 +1108,9 @@ typedef struct LDPCDecode_ue_s {
   int offset;
   int Tbslbrm;
   int decodeIterations;
+  time_stats_t ts_deinterleave;
+  time_stats_t ts_rate_unmatch;
+  time_stats_t ts_ldpc_decode;
 } ldpcDecode_ue_t;
 
 #include "SIMULATION/ETH_TRANSPORT/defs.h"
diff --git a/openair1/PHY/defs_nr_common.h b/openair1/PHY/defs_nr_common.h
index 979b98e536eb654b5234e1909cc9d8651a358e41..78599dcbb65f3ab118aad088eecf24c2101e4fd5 100644
--- a/openair1/PHY/defs_nr_common.h
+++ b/openair1/PHY/defs_nr_common.h
@@ -107,6 +107,8 @@
 #define MAX_NUM_NR_ULSCH_SEGMENTS 34
 #define MAX_NR_ULSCH_PAYLOAD_BYTES (MAX_NUM_NR_ULSCH_SEGMENTS*1056)
 
+#define MAX_NUM_NR_SRS_SYMBOLS 4
+
 #define MAX_NUM_NR_CHANNEL_BITS (14*273*12*8)  // 14 symbols, 273 RB
 #define MAX_NUM_NR_RE (14*273*12)
 #define NR_RX_NB_TH 1
@@ -249,6 +251,19 @@ typedef struct {
   uint8_t init_msg1;
 } NR_PRACH_RESOURCES_t;
 
+typedef struct {
+  uint16_t sc_list_length;
+  uint16_t sc_list[6 * NR_MAX_NB_RB];
+  uint8_t srs_generated_signal_bits;
+  int32_t *srs_generated_signal;
+  int32_t **srs_received_signal;
+  int32_t **srs_ls_estimated_channel;
+  int32_t **srs_estimated_channel_freq;
+  int32_t **srs_estimated_channel_time;
+  int32_t **srs_estimated_channel_time_shifted;
+  uint32_t *noise_power;
+} nr_srs_info_t;
+
 typedef struct NR_DL_FRAME_PARMS NR_DL_FRAME_PARMS;
 
 typedef uint32_t (*get_samples_per_slot_t)(int slot, NR_DL_FRAME_PARMS* fp);
diff --git a/openair1/PHY/impl_defs_nr.h b/openair1/PHY/impl_defs_nr.h
index 59d82166790b791a6d6128f85da00d0488f238e9..87d193b4a31aa0c692dfba9d268a249d6576a46f 100644
--- a/openair1/PHY/impl_defs_nr.h
+++ b/openair1/PHY/impl_defs_nr.h
@@ -211,10 +211,10 @@ typedef enum {
   srs_sl2560 = 16
 } SRS_Periodicity_t;
 
-#define NB_SRS_PERIOD         (17)
+#define NB_SRS_PERIOD         (18)
 
 static const uint16_t srs_period[NB_SRS_PERIOD]
-= { 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}
+= { 0, 1, 2, 4, 5, 8, 10, 16, 20, 32, 40, 64, 80, 160, 320, 640, 1280, 2560}
 ;
 
 /// SRS_Resource of SRS_Config information element from 38.331 RRC specifications
diff --git a/openair1/SCHED_NR/fapi_nr_l1.c b/openair1/SCHED_NR/fapi_nr_l1.c
index 5a996d822266e0d505841222a753f1f58b76e35c..2dbaa738dc364a279592c7821879e5f176af683b 100644
--- a/openair1/SCHED_NR/fapi_nr_l1.c
+++ b/openair1/SCHED_NR/fapi_nr_l1.c
@@ -227,6 +227,10 @@ void nr_schedule_response(NR_Sched_Rsp_t *Sched_INFO){
           nr_fill_prach(gNB, UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
           if (gNB->RU_list[0]->if_south == LOCAL_RF) nr_fill_prach_ru(gNB->RU_list[0], UL_tti_req->SFN, UL_tti_req->Slot, prach_pdu);
           break;
+        case NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE:
+          LOG_D(PHY,"frame %d, slot %d, Got NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE for %d.%d\n", frame, slot, UL_tti_req->SFN, UL_tti_req->Slot);
+          nr_fill_srs(gNB,UL_tti_req->SFN, UL_tti_req->Slot, &UL_tti_req->pdus_list[i].srs_pdu);
+          break;
       }
     }
   }
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index e1f951ca7da62b251acea402f4ec416cc27afa71..7e9f4d091a988f649f830ed3d9f507d8c997f826 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -19,19 +19,13 @@
  *      contact@openairinterface.org
  */
 
-#include "PHY/phy_extern.h"
 #include "PHY/defs_gNB.h"
 #include "sched_nr.h"
-#include "PHY/NR_REFSIG/dmrs_nr.h"
 #include "PHY/NR_TRANSPORT/nr_transport_proto.h"
 #include "PHY/NR_TRANSPORT/nr_dlsch.h"
 #include "PHY/NR_TRANSPORT/nr_ulsch.h"
 #include "PHY/NR_TRANSPORT/nr_dci.h"
 #include "PHY/NR_ESTIMATION/nr_ul_estimation.h"
-#include "PHY/NR_UE_TRANSPORT/pucch_nr.h"
-#include "SCHED/sched_eNB.h"
-#include "sched_nr.h"
-#include "SCHED/sched_common_extern.h"
 #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_interface.h"
 #include "nfapi/open-nFAPI/nfapi/public_inc/nfapi_nr_interface.h"
 #include "fapi_nr_l1.h"
@@ -39,6 +33,7 @@
 #include "common/utils/LOG/vcd_signal_dumper.h"
 #include "PHY/INIT/phy_init.h"
 #include "PHY/MODULATION/nr_modulation.h"
+#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h"
 #include "T.h"
 #include "executables/nr-softmodem.h"
 #include "executables/softmodem-common.h"
@@ -183,7 +178,7 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
 
   for (int i=0;i<NUMBER_OF_NR_CSIRS_MAX;i++){
     NR_gNB_CSIRS_t *csirs = &msgTx->csirs_pdu[i];
-    if ((csirs->active == 1)) {
+    if (csirs->active == 1) {
       LOG_D(PHY, "CSI-RS generation started in frame %d.%d\n",frame,slot);
       nfapi_nr_dl_tti_csi_rs_pdu_rel15_t csi_params = csirs->csirs_pdu.csi_rs_pdu_rel15;
       nr_generate_csi_rs(gNB, AMP, csi_params, gNB->gNB_config.cell_config.phy_cell_id.value, slot);
@@ -191,8 +186,6 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
     }
   }
 
-  if (do_meas==1) stop_meas(&msgTx->phy_proc_tx);
-
 //  if ((frame&127) == 0) dump_pdsch_stats(gNB);
 
   //apply the OFDM symbol rotation here
@@ -201,21 +194,10 @@ void phy_procedures_gNB_TX(processingData_L1tx_t *msgTx,
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_gNB_TX+offset,0);
-  //pthread_mutex_unlock(&mutextest);
 
+  if (do_meas==1) stop_meas(&msgTx->phy_proc_tx);
 }
 
-
-
-/*
-
-  if ((cfg->subframe_config.duplex_mode.value == TDD) && 
-      ((nr_slot_select(fp,frame,slot)&NR_DOWNLINK_SLOT)==SF_DL)) return;
-
-  //  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_ENB_RX,1);
-
-*/
-
 void nr_postDecode(PHY_VARS_gNB *gNB, notifiedFIFO_elt_t *req) {
   ldpcDecode_t *rdata = (ldpcDecode_t*) NotifiedFifoData(req);
   NR_UL_gNB_HARQ_t *ulsch_harq = rdata->ulsch_harq;
@@ -369,11 +351,10 @@ void nr_ulsch_procedures(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx, int ULSCH
   //------------------- ULSCH unscrambling -------------------
   //----------------------------------------------------------
   start_meas(&gNB->ulsch_unscrambling_stats);
-  nr_ulsch_unscrambling_optim(gNB->pusch_vars[ULSCH_id]->llr,
-			      G,
-			      0,
-			      pusch_pdu->data_scrambling_id,
-			      pusch_pdu->rnti);
+  nr_ulsch_unscrambling(gNB->pusch_vars[ULSCH_id]->llr,
+                        G,
+                        pusch_pdu->data_scrambling_id,
+                        pusch_pdu->rnti);
   stop_meas(&gNB->ulsch_unscrambling_stats);
   //----------------------------------------------------------
   //--------------------- ULSCH decoding ---------------------
@@ -601,6 +582,20 @@ void fill_ul_rb_mask(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
     }
   }
 
+  for (int i=0;i<NUMBER_OF_NR_SRS_MAX;i++) {
+    NR_gNB_SRS_t *srs = gNB->srs[i];
+    if (srs) {
+      if ((srs->active == 1) && (srs->frame == frame_rx) && (srs->slot == slot_rx)) {
+        nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
+        for(int symbol = 0; symbol<(1<<srs_pdu->num_symbols); symbol++) {
+          for(rb = srs_pdu->bwp_start; rb < (srs_pdu->bwp_start+srs_pdu->bwp_size); rb++) {
+            gNB->rb_mask_ul[gNB->frame_parms.symbols_per_slot-srs_pdu->time_start_position-1+symbol][rb>>5] |= 1<<(rb&31);
+          }
+        }
+      }
+    }
+  }
+
 }
 
 void phy_procedures_gNB_common_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
@@ -808,6 +803,43 @@ int phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx) {
       }
     }
   }
+
+  for (int i=0;i<NUMBER_OF_NR_SRS_MAX;i++) {
+    NR_gNB_SRS_t *srs = gNB->srs[i];
+    if (srs) {
+      if ((srs->active == 1) && (srs->frame == frame_rx) && (srs->slot == slot_rx)) {
+
+        LOG_D(NR_PHY, "(%d.%d) gNB is waiting for SRS, id = %i\n", frame_rx, slot_rx, i);
+
+        nfapi_nr_srs_pdu_t *srs_pdu = &srs->srs_pdu;
+
+        // At least currently, the configuration is constant, so it is enough to generate the sequence just once.
+        if(gNB->nr_srs_info[i]->sc_list_length == 0) {
+          generate_srs_nr(srs_pdu, &gNB->frame_parms, gNB->nr_srs_info[i]->srs_generated_signal, gNB->nr_srs_info[i], AMP, frame_rx, slot_rx);
+        }
+
+        nr_get_srs_signal(gNB,frame_rx,slot_rx,srs_pdu, gNB->nr_srs_info[i], gNB->nr_srs_info[i]->srs_received_signal);
+
+        nr_srs_channel_estimation(gNB,frame_rx,slot_rx,srs_pdu,
+                                  gNB->nr_srs_info[i],
+                                  gNB->nr_srs_info[i]->srs_generated_signal,
+                                  gNB->nr_srs_info[i]->srs_received_signal,
+                                  gNB->nr_srs_info[i]->srs_estimated_channel_freq,
+                                  gNB->nr_srs_info[i]->srs_estimated_channel_time,
+                                  gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted,
+                                  gNB->nr_srs_info[i]->noise_power);
+
+        T(T_GNB_PHY_UL_FREQ_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0),
+          T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_freq[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t)));
+
+        T(T_GNB_PHY_UL_TIME_CHANNEL_ESTIMATE, T_INT(0), T_INT(srs_pdu->rnti), T_INT(frame_rx), T_INT(0), T_INT(0),
+          T_BUFFER(gNB->nr_srs_info[i]->srs_estimated_channel_time_shifted[0], gNB->frame_parms.ofdm_symbol_size*sizeof(int32_t)));
+
+        srs->active = 0;
+      }
+    }
+  }
+
   stop_meas(&gNB->phy_proc_rx);
   // figure out a better way to choose slot_rx, 19 is ok for a particular TDD configuration with 30kHz SCS
   if ((frame_rx&127) == 0 && slot_rx==19) {
diff --git a/openair1/SCHED_NR_UE/defs.h b/openair1/SCHED_NR_UE/defs.h
index b3527365a5f3a136efa00d48686bc50d7e728565..b85d4c1b507b43e6b62d11d4ebfdaa31ce582638 100644
--- a/openair1/SCHED_NR_UE/defs.h
+++ b/openair1/SCHED_NR_UE/defs.h
@@ -358,31 +358,12 @@ int16_t nr_pucch_power_cntl(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t s
  */
 void nr_pusch_power_cntl(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t j, uint8_t abstraction_flag);
 
-/*! \brief This function implements the power control mechanism for SRS from 36.213.
-    @param phy_vars_ue PHY variables
-    @param proc Pointer to proc descriptor
-    @param eNB_id Index of eNB
-    @param j index of type of PUSCH (SPS, Normal, Msg3)
-    @returns Transmit power
- */
-void nr_srs_power_cntl(PHY_VARS_NR_UE *ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t *pnb_rb_srs, uint8_t abstraction_flag);
-
 void nr_get_cqipmiri_params(PHY_VARS_NR_UE *ue,uint8_t eNB_id);
 
-
-
-
-
-
 void nr_dump_dlsch(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe,uint8_t harq_pid);
 void nr_dump_dlsch_SI(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe);
 void nr_dump_dlsch_ra(PHY_VARS_NR_UE *phy_vars_ue,UE_nr_rxtx_proc_t *proc,uint8_t eNB_id,uint8_t subframe);
 
-
-int nr_is_srs_occasion_common(NR_DL_FRAME_PARMS *frame_parms,int frame_tx,int subframe_tx);
-
-void nr_compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset);
-
 void set_tx_harq_id(NR_UE_ULSCH_t *ulsch, int harq_pid, int slot_tx);
 int get_tx_harq_id(NR_UE_ULSCH_t *ulsch, int slot_tx);
 
@@ -425,8 +406,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
                             PDSCH_t pdsch,
                             NR_UE_DLSCH_t *dlsch0,
                             NR_UE_DLSCH_t *dlsch1,
-                            int *dlsch_errors,
-                            uint8_t dlsch_parallel);
+                            int *dlsch_errors);
 
 int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue,
                            UE_nr_rxtx_proc_t *proc,
diff --git a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
index 4fd337eb09b64b4abb0e04b87f369c7d78f861a5..4f4757ec5a43f6bb27822930a165f27866cd6e16 100644
--- a/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
+++ b/openair1/SCHED_NR_UE/fapi_nr_ue_l1.c
@@ -336,6 +336,8 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
         /* PUCCH */
         fapi_nr_ul_config_pucch_pdu *pucch_config_pdu;
         LOG_D(PHY, "%d.%d ul B ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
+        /* SRS */
+        fapi_nr_ul_config_srs_pdu *srs_config_pdu;
 
         switch (pdu_type){
 
@@ -411,6 +413,15 @@ int8_t nr_ue_scheduled_response(nr_scheduled_response_t *scheduled_response){
           LOG_D(PHY, "%d.%d ul A ul_config %p t %d pdu_done %d number_pdus %d\n", scheduled_response->frame, slot, ul_config, pdu_type, pdu_done, ul_config->number_pdus);
         break;
 
+        case (FAPI_NR_UL_CONFIG_TYPE_SRS):
+          // srs config pdu
+          srs_config_pdu = &ul_config->ul_config_list[i].srs_config_pdu;
+          memcpy((void*)&(PHY_vars_UE_g[module_id][cc_id]->srs_vars[gNB_id]->srs_config_pdu), (void*)srs_config_pdu, sizeof(fapi_nr_ul_config_srs_pdu));
+          PHY_vars_UE_g[module_id][cc_id]->srs_vars[gNB_id]->active = true;
+          ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
+          pdu_done++;
+        break;
+
         default:
           ul_config->ul_config_list[i].pdu_type = FAPI_NR_UL_CONFIG_TYPE_DONE; // not handle it any more
           pdu_done++; // count the no of pdu processed
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index ce55219093fabec9fe1c6f5f6c90a28f8f8e7fc9..97a7e2e48996860b2815a2412bb42fc95f864709 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -38,16 +38,12 @@
 #include "PHY/defs_nr_UE.h"
 #include "PHY/phy_extern_nr_ue.h"
 #include "PHY/MODULATION/modulation_UE.h"
-#include "PHY/NR_REFSIG/refsig_defs_ue.h"
-#include "PHY/NR_REFSIG/pss_nr.h"
 #include "PHY/NR_UE_TRANSPORT/nr_transport_ue.h"
 #include "PHY/NR_UE_TRANSPORT/nr_transport_proto_ue.h"
-#include "SCHED_NR_UE/defs.h"
-#include "SCHED_NR_UE/pucch_uci_ue_nr.h"
+#include "PHY/NR_UE_TRANSPORT/srs_modulation_nr.h"
 #include "SCHED_NR/extern.h"
 #include "SCHED_NR_UE/phy_sch_processing_time.h"
 #include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
-#include "PHY/NR_TRANSPORT/nr_dci.h"
 #ifdef EMOS
 #include "SCHED/phy_procedures_emos.h"
 #endif
@@ -286,16 +282,17 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
 
   LOG_D(PHY,"****** start TX-Chain for AbsSubframe %d.%d ******\n", frame_tx, slot_tx);
 
-
   start_meas(&ue->phy_proc_tx);
 
   if (ue->UE_mode[gNB_id] <= PUSCH){
-
     for (uint8_t harq_pid = 0; harq_pid < ue->ulsch[proc->thread_id][gNB_id][0]->number_harq_processes_for_pusch; harq_pid++) {
       if (ue->ulsch[proc->thread_id][gNB_id][0]->harq_processes[harq_pid]->status == ACTIVE)
         nr_ue_ulsch_procedures(ue, harq_pid, frame_tx, slot_tx, proc->thread_id, gNB_id);
     }
+  }
 
+  if (ue->UE_mode[gNB_id] == PUSCH) {
+    ue_srs_procedures_nr(ue, proc, gNB_id);
   }
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX, VCD_FUNCTION_OUT);
@@ -495,187 +492,8 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id,
   NR_UE_PDCCH *pdcch_vars = ue->pdcch_vars[proc->thread_id][gNB_id];
   fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15 = &pdcch_vars->pdcch_config[n_ss];
 
-  /*
-  //  unsigned int dci_cnt=0, i;  //removed for nr_ue_pdcch_procedures and added in the loop for nb_coreset_active
-#ifdef NR_PDCCH_SCHED_DEBUG
-  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_ue_pdcch_procedures() \n");
-#endif
-
-  int frame_rx = proc->frame_rx;
-  int nr_slot_rx = proc->nr_slot_rx;
-  NR_DCI_ALLOC_t dci_alloc_rx[8];
-  
-  //uint8_t next1_thread_id = proc->thread_id== (RX_NB_TH-1) ? 0:(proc->thread_id+1);
-  //uint8_t next2_thread_id = next1_thread_id== (RX_NB_TH-1) ? 0:(next1_thread_id+1);
-  
-
-  // table dci_fields_sizes_cnt contains dci_fields_sizes for each time a dci is decoded in the slot
-  // each element represents the size in bits for each dci field, for each decoded dci -> [dci_cnt-1]
-  // each time a dci is decode at dci_cnt, the values of the table dci_fields_sizes[i][j] will be copied at table dci_fields_sizes_cnt[dci_cnt-1][i][j]
-  // table dci_fields_sizes_cnt[dci_cnt-1][i][j] will then be used in function nr_extract_dci_info
-  uint8_t dci_fields_sizes_cnt[MAX_NR_DCI_DECODED_SLOT][NBR_NR_DCI_FIELDS][NBR_NR_FORMATS];
-
-  int nb_searchspace_active=0;
-  NR_UE_PDCCH **pdcch_vars = ue->pdcch_vars[proc->thread_id];
-  NR_UE_PDCCH *pdcch_vars2 = ue->pdcch_vars[proc->thread_id][gNB_id];
-  // s in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 10 different search spaces
-  // Higher layers have updated the number of searchSpaces with are active in the current slot and this value is stored in variable nb_searchspace_total
-  int nb_searchspace_total = pdcch_vars2->nb_search_space;
-
-  pdcch_vars[gNB_id]->crnti = 0x1234; //to be check how to set when using loop memory
-
-  uint16_t c_rnti=pdcch_vars[gNB_id]->crnti;
-  uint16_t cs_rnti=0,new_rnti=0,tc_rnti=0;
-  uint16_t p_rnti=P_RNTI;
-  uint16_t si_rnti=SI_RNTI;
-  uint16_t ra_rnti=99;
-  uint16_t sp_csi_rnti=0,sfi_rnti=0,int_rnti=0,tpc_pusch_rnti=0,tpc_pucch_rnti=0,tpc_srs_rnti=0; //FIXME
-  uint16_t crc_scrambled_values[TOTAL_NBR_SCRAMBLED_VALUES] =
-    {c_rnti,cs_rnti,new_rnti,tc_rnti,p_rnti,si_rnti,ra_rnti,sp_csi_rnti,sfi_rnti,int_rnti,tpc_pusch_rnti,tpc_pucch_rnti,tpc_srs_rnti};
-  #ifdef NR_PDCCH_SCHED_DEBUG
-  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> there is a bug in FAPI to calculate nb_searchspace_total=%d\n",nb_searchspace_total);
-  #endif
-  if (nb_searchspace_total>1) nb_searchspace_total=1; // to be removed when fixing bug in FAPI
-  #ifdef NR_PDCCH_SCHED_DEBUG
-  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> there is a bug in FAPI to calculate nb_searchspace_total so we set it to 1...\n");
-  printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> the number of searchSpaces active in the current slot(%d) is %d) \n",
-	 nr_slot_rx,nb_searchspace_total);
-  #endif
-
-  //FK: we define dci_ind and dl_indication as local variables, this way the call to the mac should be thread safe
-  fapi_nr_dci_indication_t dci_ind;
-  nr_downlink_indication_t dl_indication;
-  
-  // p in TS 38.212 Subclause 10.1, for each active BWP the UE can deal with 3 different CORESETs (including coresetId 0 for common search space)
-  //int nb_coreset_total = NR_NBR_CORESET_ACT_BWP;
-  unsigned int dci_cnt=0;
-  // this table contains 56 (NBR_NR_DCI_FIELDS) elements for each dci field and format described in TS 38.212. Each element represents the size in bits for each dci field
-  //uint8_t dci_fields_sizes[NBR_NR_DCI_FIELDS][NBR_NR_FORMATS] = {{0}};
-  // this is the UL bandwidth part. FIXME! To be defined where this value comes from
-  //  uint16_t n_RB_ULBWP = 106;
-  // this is the DL bandwidth part. FIXME! To be defined where this value comes from
-
-  // First we have to identify each searchSpace active at a time and do PDCCH monitoring corresponding to current searchSpace
-  // Up to 10 searchSpaces can be configured to UE (s<=10)
-  for (nb_searchspace_active=0; nb_searchspace_active<nb_searchspace_total; nb_searchspace_active++){
-    int nb_coreset_active=nb_searchspace_active;
-    //int do_pdcch_monitoring_current_slot=1; // this variable can be removed and fapi is handling
-    
-     // The following code has been removed as it is handled by higher layers (fapi)
-     //
-     // Verify that monitoring is required at the slot nr_slot_rx. We will run pdcch procedure only if do_pdcch_monitoring_current_slot=1
-     // For Type0-PDCCH searchspace, we need to calculate the monitoring slot from Tables 13-1 .. 13-15 in TS 38.213 Subsection 13
-     //NR_UE_SLOT_PERIOD_OFFSET_t sl_period_offset_mon = pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset;
-     //if (sl_period_offset_mon == nr_sl1) {
-     //do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every slot
-     //} else if (nr_slot_rx%(uint16_t)sl_period_offset_mon == pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSlotPeriodicityAndOffset_offset) {
-     //do_pdcch_monitoring_current_slot=1; // PDCCH monitoring in every monitoringSlotPeriodicityAndOffset slot with offset
-     //}
-    
-     // FIXME
-     // For PDCCH monitoring when overlap with SS/PBCH according to 38.213 v15.1.0 Section 10
-     // To be implemented LATER !!!
-     
-    //int _offset,_index,_M;
-    //int searchSpace_id                              = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceId;
-
-
-    #ifdef NR_PDCCH_SCHED_DEBUG
-      printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> nb_searchspace_active=%d do_pdcch_monitoring_current_slot=%d (to be removed)\n",
-              nb_searchspace_active,
-              do_pdcch_monitoring_current_slot);
-    #endif
-
-//    if (do_pdcch_monitoring_current_slot) {
-      // the searchSpace indicates that we need to monitor PDCCH in current nr_slot_rx
-      // get the parameters describing the current SEARCHSPACE
-      // the CORESET id applicable to the current SearchSpace
-      //int searchSpace_coreset_id                      = pdcch_vars2->searchSpace[nb_searchspace_active].controlResourceSetId;
-      // FIXME this variable is a bit string (14 bits) identifying every OFDM symbol in a slot.
-      // at the moment we will not take into consideration this variable and we will consider that the OFDM symbol offset is always the first OFDM in a symbol
-      uint16_t symbol_within_slot_mon                 = pdcch_vars2->searchSpace[nb_searchspace_active].monitoringSymbolWithinSlot;
-      // get the remaining parameters describing the current SEARCHSPACE:     // FIXME! To be defined where we get this information from
-      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L1         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel1;
-      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L2         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel2;
-      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L4         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel4;
-      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L8         = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel8;
-      //NR_UE_SEARCHSPACE_nbrCAND_t num_cand_L16        = pdcch_vars2->searchSpace[nb_searchspace_active].nrofCandidates_aggrlevel16;
-                                                                                                  // FIXME! A table of five enum elements
-      // searchSpaceType indicates whether this is a common search space or a UE-specific search space
-      //int searchSpaceType                             = pdcch_vars2->searchSpace[nb_searchspace_active].searchSpaceType.type;
-      NR_SEARCHSPACE_TYPE_t searchSpaceType                             = ue_specific;//common;
-      #ifdef NR_PDCCH_SCHED_DEBUG
-        printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> searchSpaceType=%d is hardcoded THIS HAS TO BE FIXED!!!\n",
-                searchSpaceType);
-      #endif
-
-      //while ((searchSpace_coreset_id != pdcch_vars2->coreset[nb_coreset_active].controlResourceSetId) && (nb_coreset_active<nb_coreset_total)) {
-        // we need to identify the CORESET associated to the active searchSpace
-        //nb_coreset_active++;
-      if (nb_coreset_active >= nb_coreset_total) return 0; // the coreset_id could not be found. There is a problem
-      }
-
-
-    
-     //we do not need these parameters yet
-    
-     // get the parameters describing the current CORESET
-     //int coreset_duration                                      = pdcch_vars2->coreset[nb_coreset_active].duration;
-     //uint64_t coreset_freq_dom                                 = pdcch_vars2->coreset[nb_coreset_active].frequencyDomainResources;
-     //int coreset_shift_index                                   = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.shiftIndex;
-    // NR_UE_CORESET_REG_bundlesize_t coreset_bundlesize         = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.reg_bundlesize;
-    // NR_UE_CORESET_interleaversize_t coreset_interleaversize   = pdcch_vars2->coreset[nb_coreset_active].cce_reg_mappingType.interleaversize;
-    // NR_UE_CORESET_precoder_granularity_t precoder_granularity = pdcch_vars2->coreset[nb_coreset_active].precoderGranularity;
-    // int tci_statesPDCCH                                       = pdcch_vars2->coreset[nb_coreset_active].tciStatesPDCCH;
-    // int tci_present                                           = pdcch_vars2->coreset[nb_coreset_active].tciPresentInDCI;
-    // uint16_t pdcch_DMRS_scrambling_id                         = pdcch_vars2->coreset[nb_coreset_active].pdcchDMRSScramblingID;
-    
-
-    // A set of PDCCH candidates for a UE to monitor is defined in terms of PDCCH search spaces.
-    // Searchspace types:
-    // Type0-PDCCH  common search space for a DCI format with CRC scrambled by a SI-RNTI
-    // number of consecutive resource blocks and a number of consecutive symbols for
-    // the control resource set of the Type0-PDCCH common search space from
-    // the four most significant bits of RMSI-PDCCH-Config as described in Tables 13-1 through 13-10
-    // and determines PDCCH monitoring occasions
-    // from the four least significant bits of RMSI-PDCCH-Config,
-    // included in MasterInformationBlock, as described in Tables 13-11 through 13-15
-    // Type0A-PDCCH common search space for a DCI format with CRC scrambled by a SI-RNTI
-    // Type1-PDCCH  common search space for a DCI format with CRC scrambled by a RA-RNTI, or a TC-RNTI, or a C-RNTI
-    // Type2-PDCCH  common search space for a DCI format with CRC scrambled by a P-RNTI
-    // Type3-PDCCH  common search space for a DCI format with CRC scrambled by INT-RNTI, or SFI-RNTI,
-    // or TPC-PUSCH-RNTI, or TPC-PUCCH-RNTI, or TPC-SRS-RNTI, or C-RNTI, or CS-RNTI(s), or SP-CSI-RNTI
-
-
-
-    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_PDCCH_PROCEDURES, VCD_FUNCTION_IN);
-    start_meas(&ue->dlsch_rx_pdcch_stats);
+  start_meas(&ue->dlsch_rx_pdcch_stats);
 
-      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
-#ifdef NR_PDCCH_SCHED_DEBUG
-      printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Entering function nr_rx_pdcch with gNB_id=%d (nb_coreset_active=%d, (symbol_within_slot_mon&0x3FFF)=%d, searchSpaceType=%d)\n",
-                  gNB_id,nb_coreset_active,(symbol_within_slot_mon&0x3FFF),
-                  searchSpaceType);
-#endif
-        nr_rx_pdcch(ue,
-                    frame_rx,
-                    nr_slot_rx,
-                    gNB_id,
-                    //(ue->frame_parms.mode1_flag == 1) ? SISO : ALAMOUTI,
-                    SISO,
-                    ue->high_speed_flag,
-                    ue->is_secondary_ue,
-                    nb_coreset_active,
-                    (symbol_within_slot_mon&0x3FFF),
-                    searchSpaceType);
-#ifdef NR_PDCCH_SCHED_DEBUG
-          printf("<-NR_PDCCH_PHY_PROCEDURES_LTE_UE (nr_ue_pdcch_procedures)-> Ending function nr_rx_pdcch(nb_coreset_active=%d, (symbol_within_slot_mon&0x3FFF)=%d, searchSpaceType=%d)\n",
-                  nb_coreset_active,(symbol_within_slot_mon&0x3FFF),
-                  searchSpaceType);
-#endif
-
-  */
-  
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_IN);
   nr_rx_pdcch(ue, proc, rel15);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_RX_PDCCH, VCD_FUNCTION_OUT);
@@ -708,46 +526,10 @@ int nr_ue_pdcch_procedures(uint8_t gNB_id,
   ue->pdcch_vars[proc->thread_id][gNB_id]->dci_received += dci_cnt;
 
   dci_ind->number_of_dcis = dci_cnt;
-    /*
-    for (int i=0; i<dci_cnt; i++) {
-      
-	memset(&dci_ind.dci_list[i].dci,0,sizeof(fapi_nr_dci_pdu_rel15_t));
-	
-	dci_ind.dci_list[i].rnti = dci_alloc_rx[i].rnti;
-	dci_ind.dci_list[i].dci_format = dci_alloc_rx[i].format;
-	dci_ind.dci_list[i].n_CCE = dci_alloc_rx[i].firstCCE;
-	dci_ind.dci_list[i].N_CCE = (int)dci_alloc_rx[i].L;
-	
-	status = nr_extract_dci_info(ue,
-				     gNB_id,
-				     ue->frame_parms.frame_type,
-				     dci_alloc_rx[i].dci_length,
-				     dci_alloc_rx[i].rnti,
-				     dci_alloc_rx[i].dci_pdu,
-				     &dci_ind.dci_list[i].dci,
-				     dci_fields_sizes_cnt[i],
-				     dci_alloc_rx[i].format,
-				     nr_slot_rx,
-				     pdcch_vars2->n_RB_BWP[nb_searchspace_active],
-				     pdcch_vars2->n_RB_BWP[nb_searchspace_active],
-				     crc_scrambled_values);
-	
-	if(status == 0) {
-	  LOG_W(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> bad DCI %d !!! \n",dci_alloc_rx[i].format);
-	  return(-1);
-	}
-	
-	LOG_D(PHY,"<-NR_PDCCH_PHY_PROCEDURES_UE (nr_ue_pdcch_procedures)-> Ending function nr_extract_dci_info()\n");
-	
-
-        
-      } // end for loop dci_cnt
-    */
-
-    // fill dl_indication message
-    nr_fill_dl_indication(&dl_indication, dci_ind, NULL, proc, ue, gNB_id);
-    //  send to mac
-    ue->if_inst->dl_indication(&dl_indication, NULL);
+  // fill dl_indication message
+  nr_fill_dl_indication(&dl_indication, dci_ind, NULL, proc, ue, gNB_id);
+  //  send to mac
+  ue->if_inst->dl_indication(&dl_indication, NULL);
 
   stop_meas(&ue->dlsch_rx_pdcch_stats);
     
@@ -822,6 +604,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
       first_symbol_with_data++;
     }
 
+    start_meas(&ue->rx_pdsch_stats);
     for (m = s0; m < (s1 + s0); m++) {
  
       dual_stream_UE = 0;
@@ -861,6 +644,7 @@ int nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int gNB_
         proc->first_symbol_available = 1;
       }
     } // CRNTI active
+    stop_meas(&ue->rx_pdsch_stats);
   }
   return 0;
 }
@@ -871,8 +655,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
                             PDSCH_t pdsch,
                             NR_UE_DLSCH_t *dlsch0,
                             NR_UE_DLSCH_t *dlsch1,
-                            int *dlsch_errors,
-                            uint8_t dlsch_parallel) {
+                            int *dlsch_errors) {
 
   if (dlsch0==NULL)
     AssertFatal(0,"dlsch0 should be defined at this level \n");
@@ -1001,12 +784,9 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
                             harq_pid,
                             pdsch==PDSCH?1:0,
                             dlsch0->harq_processes[harq_pid]->TBS>256?1:0);
-    if( dlsch_parallel) {
-      LOG_T(PHY,"dlsch decoding is parallelized, ret = %d\n", ret);
-    }
-    else {
-      LOG_T(PHY,"Sequential dlsch decoding , ret = %d\n", ret);
-    }
+
+    LOG_T(PHY,"dlsch decoding, ret = %d\n", ret);
+
 
     if(ret<dlsch0->max_ldpc_iterations+1)
       dec = true;
@@ -1081,13 +861,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
                                harq_pid,
                                pdsch==PDSCH?1:0,//proc->decoder_switch,
                                dlsch1->harq_processes[harq_pid]->TBS>256?1:0);
-      if(dlsch_parallel) {
-        LOG_T(PHY,"CW dlsch decoding is parallelized, ret1 = %d\n", ret1);
-      }
-      else {
-
-        LOG_T(PHY,"CWW sequential dlsch decoding, ret1 = %d\n", ret1);
-      }
+      LOG_T(PHY,"CW dlsch decoding, ret1 = %d\n", ret1);
 
       stop_meas(&ue->dlsch_decoding_stats[proc->thread_id]);
       if (cpumeas(CPUMEAS_GETSTATE)) {
@@ -1601,6 +1375,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
   NR_DL_FRAME_PARMS *fp = &ue->frame_parms;
   
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_IN);
+  start_meas(&ue->phy_proc_rx[proc->thread_id]);
 
   LOG_D(PHY," ****** start RX-Chain for Frame.Slot %d.%d (energy %d dB)******  \n",
         frame_rx%1024, nr_slot_rx,
@@ -1782,8 +1557,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
                            SI_PDSCH,
                            ue->dlsch_SI[gNB_id],
                            NULL,
-                           &ue->dlsch_SI_errors[gNB_id],
-                           dlsch_parallel);
+                           &ue->dlsch_SI_errors[gNB_id]);
 
     // deactivate dlsch once dlsch proc is done
     ue->dlsch_SI[gNB_id]->active = 0;
@@ -1807,8 +1581,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
                            P_PDSCH,
                            ue->dlsch_p[gNB_id],
                            NULL,
-                           &ue->dlsch_p_errors[gNB_id],
-                           dlsch_parallel);
+                           &ue->dlsch_p_errors[gNB_id]);
 
     // deactivate dlsch once dlsch proc is done
     ue->dlsch_p[gNB_id]->active = 0;
@@ -1831,8 +1604,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
                            RA_PDSCH,
                            ue->dlsch_ra[gNB_id],
                            NULL,
-                           &ue->dlsch_ra_errors[gNB_id],
-                           dlsch_parallel);
+                           &ue->dlsch_ra_errors[gNB_id]);
 
     // deactivate dlsch once dlsch proc is done
     ue->dlsch_ra[gNB_id]->active = 0;
@@ -1854,8 +1626,7 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
 			   PDSCH,
 			   ue->dlsch[proc->thread_id][gNB_id][0],
 			   ue->dlsch[proc->thread_id][gNB_id][1],
-			   &ue->dlsch_errors[gNB_id],
-			   dlsch_parallel);
+			   &ue->dlsch_errors[gNB_id]);
 
   stop_meas(&ue->dlsch_procedures_stat[proc->thread_id]);
   if (cpumeas(CPUMEAS_GETSTATE)) {
@@ -1870,91 +1641,49 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
 
  }
 
-start_meas(&ue->generic_stat);
-
-#if 0
-
-  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[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);
-
-       //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][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,"");
-  }
-#endif
-
-  // duplicate harq structure
-/*
-  uint8_t          current_harq_pid        = ue->dlsch[proc->thread_id][gNB_id][0]->current_harq_pid;
-  NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[proc->thread_id][gNB_id][0]->harq_processes[current_harq_pid];
-  NR_DL_UE_HARQ_t *harq_processes_dest    = ue->dlsch[next1_thread_id][gNB_id][0]->harq_processes[current_harq_pid];
-  NR_DL_UE_HARQ_t *harq_processes_dest1    = ue->dlsch[next2_thread_id][gNB_id][0]->harq_processes[current_harq_pid];
-  */
-  /*nr_harq_status_t *current_harq_ack = &ue->dlsch[proc->thread_id][gNB_id][0]->harq_ack[nr_slot_rx];
-  nr_harq_status_t *harq_ack_dest    = &ue->dlsch[next1_thread_id][gNB_id][0]->harq_ack[nr_slot_rx];
-  nr_harq_status_t *harq_ack_dest1    = &ue->dlsch[next2_thread_id][gNB_id][0]->harq_ack[nr_slot_rx];
-*/
-
-  //copy_harq_proc_struct(harq_processes_dest, current_harq_processes);
-//copy_ack_struct(harq_ack_dest, current_harq_ack);
-
-//copy_harq_proc_struct(harq_processes_dest1, current_harq_processes);
-//copy_ack_struct(harq_ack_dest1, current_harq_ack);
+  start_meas(&ue->generic_stat);
 
-if (nr_slot_rx==9) {
-  if (frame_rx % 10 == 0) {
-    if ((ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]) != 0)
-      ue->dlsch_fer[gNB_id] = (100*(ue->dlsch_errors[gNB_id] - ue->dlsch_errors_last[gNB_id]))/(ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]);
+  if (nr_slot_rx==9) {
+    if (frame_rx % 10 == 0) {
+      if ((ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]) != 0)
+        ue->dlsch_fer[gNB_id] = (100*(ue->dlsch_errors[gNB_id] - ue->dlsch_errors_last[gNB_id]))/(ue->dlsch_received[gNB_id] - ue->dlsch_received_last[gNB_id]);
 
-    ue->dlsch_errors_last[gNB_id] = ue->dlsch_errors[gNB_id];
-    ue->dlsch_received_last[gNB_id] = ue->dlsch_received[gNB_id];
-  }
+      ue->dlsch_errors_last[gNB_id] = ue->dlsch_errors[gNB_id];
+      ue->dlsch_received_last[gNB_id] = ue->dlsch_received[gNB_id];
+    }
 
 
-  ue->bitrate[gNB_id] = (ue->total_TBS[gNB_id] - ue->total_TBS_last[gNB_id])*100;
-  ue->total_TBS_last[gNB_id] = ue->total_TBS[gNB_id];
-  LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n",
-	ue->Mod_id,frame_rx,ue->total_TBS[gNB_id],
-	ue->total_TBS_last[gNB_id],(float) ue->bitrate[gNB_id]/1000.0);
+    ue->bitrate[gNB_id] = (ue->total_TBS[gNB_id] - ue->total_TBS_last[gNB_id])*100;
+    ue->total_TBS_last[gNB_id] = ue->total_TBS[gNB_id];
+    LOG_D(PHY,"[UE %d] Calculating bitrate Frame %d: total_TBS = %d, total_TBS_last = %d, bitrate %f kbits\n",
+          ue->Mod_id,frame_rx,ue->total_TBS[gNB_id],
+          ue->total_TBS_last[gNB_id],(float) ue->bitrate[gNB_id]/1000.0);
 
 #if UE_AUTOTEST_TRACE
-  if ((frame_rx % 100 == 0)) {
-    LOG_I(PHY,"[UE  %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[gNB_id]/1000.0, frame_rx);
-  }
+    if ((frame_rx % 100 == 0)) {
+      LOG_I(PHY,"[UE  %d] AUTOTEST Metric : UE_DLSCH_BITRATE = %5.2f kbps (frame = %d) \n", ue->Mod_id, (float) ue->bitrate[gNB_id]/1000.0, frame_rx);
+    }
 #endif
 
- }
+  }
 
-stop_meas(&ue->generic_stat);
-if (cpumeas(CPUMEAS_GETSTATE))
-  LOG_D(PHY,"after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0));
+  stop_meas(&ue->generic_stat);
+  if (cpumeas(CPUMEAS_GETSTATE))
+    LOG_D(PHY,"after tubo until end of Rx %5.2f \n",ue->generic_stat.p_time/(cpuf*1000.0));
 
 #ifdef EMOS
-phy_procedures_emos_UE_RX(ue,slot,gNB_id);
+  phy_procedures_emos_UE_RX(ue,slot,gNB_id);
 #endif
 
 
-VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
-
-stop_meas(&ue->phy_proc_rx[proc->thread_id]);
-if (cpumeas(CPUMEAS_GETSTATE))
-  LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx[proc->thread_id].p_time/(cpuf*1000.0));
-
+  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_RX, VCD_FUNCTION_OUT);
 
-//#endif //pdsch
+  stop_meas(&ue->phy_proc_rx[proc->thread_id]);
+  if (cpumeas(CPUMEAS_GETSTATE))
+    LOG_D(PHY, "------FULL RX PROC [SFN %d]: %5.2f ------\n",nr_slot_rx,ue->phy_proc_rx[proc->thread_id].p_time/(cpuf*1000.0));
 
-LOG_D(PHY," ****** end RX-Chain  for AbsSubframe %d.%d ******  \n", frame_rx%1024, nr_slot_rx);
-return (0);
+  LOG_D(PHY," ****** end RX-Chain  for AbsSubframe %d.%d ******  \n", frame_rx%1024, nr_slot_rx);
+  return (0);
 }
 
 
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 891951460c2c4ad55f79ef4cd65c5710c2bd77ce..b8f51f8e958fe0c69d11bdbba82a54f703e8acd6 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -280,7 +280,7 @@ void nr_dlsim_preprocessor(module_id_t module_id,
                            UE_info->CellGroup[0],
                            sched_ctrl->active_bwp,
                            NULL,
-                           /* tda = */ 0,
+                           /* tda = */ 2,
                            dci_format,
                            ps);
 
@@ -777,7 +777,7 @@ int main(int argc, char **argv)
 
   prepare_scd(scd);
 
-  fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 6, 0, 0, 0);
+  fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 6, 0, 0, 0, 0);
 
   /* RRC parameter validation for secondaryCellGroup */
   fix_scd(scd);
diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c
index 37c230cea513d00a6f465cae9f91ee4c6bc2aa2b..0f5752c2277250c68369162854bc8b8d3cda4214 100644
--- a/openair1/SIMULATION/NR_PHY/pbchsim.c
+++ b/openair1/SIMULATION/NR_PHY/pbchsim.c
@@ -90,8 +90,7 @@ bool nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
                             PDSCH_t pdsch,
                             NR_UE_DLSCH_t *dlsch0,
                             NR_UE_DLSCH_t *dlsch1,
-                            int *dlsch_errors,
-                            uint8_t dlsch_parallel) {
+                            int *dlsch_errors) {
   return false;
 }
 
@@ -719,7 +718,7 @@ int main(int argc, char **argv)
       }
       if (UE->is_synchronized == 0) {
 	UE_nr_rxtx_proc_t proc={0};
-	ret = nr_initial_sync(&proc, UE, 1, 0, 0);
+	ret = nr_initial_sync(&proc, UE, 1, 0);
 	printf("nr_initial_sync1 returns %d\n",ret);
 	if (ret<0) n_errors++;
       }
diff --git a/openair1/SIMULATION/NR_PHY/ulsim.c b/openair1/SIMULATION/NR_PHY/ulsim.c
index fe994dafe3427d3f26f56fd78e63d5406877767a..c71f52c41a65b148ebc8dbf49a6e8440b2b117b4 100644
--- a/openair1/SIMULATION/NR_PHY/ulsim.c
+++ b/openair1/SIMULATION/NR_PHY/ulsim.c
@@ -720,7 +720,7 @@ int main(int argc, char **argv)
 
   prepare_scd(scd);
 
-  fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0, 0, 0);
+  fill_default_secondaryCellGroup(scc, scd, secondaryCellGroup, 0, 1, n_tx, 0, 0, 0, 0, 0);
 
   // xer_fprint(stdout, &asn_DEF_NR_CellGroupConfig, (const void*)secondaryCellGroup);
 
diff --git a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c
index aedb5729a353a02c3040b235020f5522a5e94cf0..34ea68bc61f1ddb6d353a02a665254dbc5d7f292 100644
--- a/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c
+++ b/openair1/SIMULATION/NR_UE_PHY/unit_tests/src/srs_test.c
@@ -229,7 +229,7 @@ int test_srs_periodicity(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc)
         for (int slot_tx = 0; slot_tx < frame_parms->slots_per_frame; slot_tx++) {
           proc->frame_tx   = frame_tx;
           proc->nr_slot_tx = slot_tx;
-          if (ue_srs_procedure_nr( ue, proc, 0) == 0)  {
+          if (ue_srs_procedures_nr( ue, proc, 0) == 0)  {
             printf("test_srs_periodicity srs at frame %d slot %d \n", frame_tx, slot_tx);
           }
         }
diff --git a/openair2/COMMON/rrc_messages_types.h b/openair2/COMMON/rrc_messages_types.h
index 63a581b37b1c387af714f189e8f537282e10db91..769bc7d01d3bffd3569651dc1cb34d0bda946b8d 100644
--- a/openair2/COMMON/rrc_messages_types.h
+++ b/openair2/COMMON/rrc_messages_types.h
@@ -417,6 +417,7 @@ typedef struct NRRrcConfigurationReq_s {
   int                     pusch_AntennaPorts;
   int                     minRXTXTIME;
   int                     do_CSIRS;
+  int                     do_SRS;
   int                     pusch_TargetSNRx10;
   int                     pucch_TargetSNRx10;
 } gNB_RrcConfigurationReq;
diff --git a/openair2/GNB_APP/gnb_config.c b/openair2/GNB_APP/gnb_config.c
index 34286f386f36758350a2ba4a0e9e200cdb9c7fe4..db9614b13f886dd3ad3456d8fe449163b61e20c8 100644
--- a/openair2/GNB_APP/gnb_config.c
+++ b/openair2/GNB_APP/gnb_config.c
@@ -1166,6 +1166,8 @@ void RCconfig_NRRRC(MessageDef *msg_p, uint32_t i, gNB_RRC_INST *rrc) {
         NRRRC_CONFIGURATION_REQ (msg_p).sib1_tda = *GNBParamList.paramarray[i][GNB_SIB1_TDA_IDX].iptr;
         printf("Do CSI-RS %d\n",*GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr);
         NRRRC_CONFIGURATION_REQ (msg_p).do_CSIRS = *GNBParamList.paramarray[i][GNB_DO_CSIRS_IDX].iptr;
+        printf("Do SRS %d\n",*GNBParamList.paramarray[i][GNB_DO_SRS_IDX].iptr);
+        NRRRC_CONFIGURATION_REQ (msg_p).do_SRS = *GNBParamList.paramarray[i][GNB_DO_SRS_IDX].iptr;
         NRRRC_CONFIGURATION_REQ (msg_p).scc = scc;
         NRRRC_CONFIGURATION_REQ (msg_p).scd = scd;
 
diff --git a/openair2/GNB_APP/gnb_paramdef.h b/openair2/GNB_APP/gnb_paramdef.h
index 5b879e04f6488f430d5c0aebc561793c8ecdc371..cde7819e2556070fd095a0195e17db6fd60a43e6 100644
--- a/openair2/GNB_APP/gnb_paramdef.h
+++ b/openair2/GNB_APP/gnb_paramdef.h
@@ -118,6 +118,7 @@ typedef enum {
 #define GNB_CONFIG_STRING_PUSCHANTENNAPORTS             "pusch_AntennaPorts"
 #define GNB_CONFIG_STRING_SIB1TDA                       "sib1_tda"
 #define GNB_CONFIG_STRING_DOCSIRS                       "do_CSIRS"
+#define GNB_CONFIG_STRING_DOSRS                         "do_SRS"
 #define GNB_CONFIG_STRING_NRCELLID                      "nr_cellid"
 #define GNB_CONFIG_STRING_MINRXTXTIME                   "min_rxtxtime"
 #define GNB_CONFIG_STRING_ULPRBBLACKLIST                "ul_prbblacklist"
@@ -147,6 +148,7 @@ typedef enum {
 {GNB_CONFIG_STRING_PUSCHANTENNAPORTS,            NULL,   0,            iptr:NULL,   defintval:1,                 TYPE_INT,       0},  \
 {GNB_CONFIG_STRING_SIB1TDA,                      NULL,   0,            iptr:NULL,   defintval:0,                 TYPE_INT,       0},  \
 {GNB_CONFIG_STRING_DOCSIRS,                      NULL,   0,            iptr:NULL,   defintval:0,                 TYPE_INT,       0},  \
+{GNB_CONFIG_STRING_DOSRS,                        NULL,   0,            iptr:NULL,   defintval:0,                 TYPE_INT,       0},  \
 {GNB_CONFIG_STRING_NRCELLID,                     NULL,   0,            u64ptr:NULL, defint64val:1,               TYPE_UINT64,    0},  \
 {GNB_CONFIG_STRING_MINRXTXTIME,                  NULL,   0,            iptr:NULL,   defintval:2,                 TYPE_INT,       0},  \
 {GNB_CONFIG_STRING_ULPRBBLACKLIST,               NULL,   0,            strptr:NULL, defstrval:"",                TYPE_STRING,    0}   \
@@ -171,9 +173,10 @@ typedef enum {
 #define GNB_PUSCH_ANTENNAPORTS_IDX      16
 #define GNB_SIB1_TDA_IDX                17
 #define GNB_DO_CSIRS_IDX                18
-#define GNB_NRCELLID_IDX                19
-#define GNB_MINRXTXTIME_IDX             20
-#define GNB_ULPRBBLACKLIST_IDX          21
+#define GNB_DO_SRS_IDX                  19
+#define GNB_NRCELLID_IDX                20
+#define GNB_MINRXTXTIME_IDX             21
+#define GNB_ULPRBBLACKLIST_IDX          22
 
 #define TRACKING_AREA_CODE_OKRANGE {0x0001,0xFFFD}
 #define GNBPARAMS_CHECK {                                         \
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index 3f4be9dd58c4d119b9f10874e85c2069cf319b02..942e3afad166632f06ab107957e10556e1bff5eb 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -2495,6 +2495,61 @@ uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB) {
     return 4;
 }
 
+/*******************************************************************
+*
+* NAME :         get_nr_srs_offset
+*
+* PARAMETERS :   periodicityAndOffset for SRS
+*
+* RETURN :       the offset parameter for SRS
+*
+*********************************************************************/
+
+uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset) {
+
+  switch(periodicityAndOffset.present) {
+    case NR_SRS_PeriodicityAndOffset_PR_sl1:
+      return periodicityAndOffset.choice.sl1;
+    case NR_SRS_PeriodicityAndOffset_PR_sl2:
+      return periodicityAndOffset.choice.sl2;
+    case NR_SRS_PeriodicityAndOffset_PR_sl4:
+      return periodicityAndOffset.choice.sl4;
+    case NR_SRS_PeriodicityAndOffset_PR_sl5:
+      return periodicityAndOffset.choice.sl5;
+    case NR_SRS_PeriodicityAndOffset_PR_sl8:
+      return periodicityAndOffset.choice.sl8;
+    case NR_SRS_PeriodicityAndOffset_PR_sl10:
+      return periodicityAndOffset.choice.sl10;
+    case NR_SRS_PeriodicityAndOffset_PR_sl16:
+      return periodicityAndOffset.choice.sl16;
+    case NR_SRS_PeriodicityAndOffset_PR_sl20:
+      return periodicityAndOffset.choice.sl20;
+    case NR_SRS_PeriodicityAndOffset_PR_sl32:
+      return periodicityAndOffset.choice.sl32;
+    case NR_SRS_PeriodicityAndOffset_PR_sl40:
+      return periodicityAndOffset.choice.sl40;
+    case NR_SRS_PeriodicityAndOffset_PR_sl64:
+      return periodicityAndOffset.choice.sl64;
+    case NR_SRS_PeriodicityAndOffset_PR_sl80:
+      return periodicityAndOffset.choice.sl80;
+    case NR_SRS_PeriodicityAndOffset_PR_sl160:
+      return periodicityAndOffset.choice.sl160;
+    case NR_SRS_PeriodicityAndOffset_PR_sl320:
+      return periodicityAndOffset.choice.sl320;
+    case NR_SRS_PeriodicityAndOffset_PR_sl640:
+      return periodicityAndOffset.choice.sl640;
+    case NR_SRS_PeriodicityAndOffset_PR_sl1280:
+      return periodicityAndOffset.choice.sl1280;
+    case NR_SRS_PeriodicityAndOffset_PR_sl2560:
+      return periodicityAndOffset.choice.sl2560;
+    case NR_SRS_PeriodicityAndOffset_PR_NOTHING:
+      LOG_W(NR_MAC,"NR_SRS_PeriodicityAndOffset_PR_NOTHING\n");
+      return 0;
+    default:
+      return 0;
+  }
+}
+
 // Set the transform precoding status according to 6.1.3 of 3GPP TS 38.214 version 16.3.0 Release 16:
 // - "UE procedure for applying transform precoding on PUSCH"
 uint8_t get_transformPrecoding(const NR_BWP_UplinkCommon_t *initialUplinkBWP,
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index 8182e1c930837a1daf15a5e44b46b313a7d41850..91450fc7960539691bd8a824fce0f554db5fc96c 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -119,6 +119,8 @@ int32_t get_l_prime(uint8_t duration_in_symbols, uint8_t mapping_type, pusch_dmr
 uint8_t get_L_ptrs(uint8_t mcs1, uint8_t mcs2, uint8_t mcs3, uint8_t I_mcs, uint8_t mcs_table);
 uint8_t get_K_ptrs(uint16_t nrb0, uint16_t nrb1, uint16_t N_RB);
 
+uint16_t get_nr_srs_offset(NR_SRS_PeriodicityAndOffset_t periodicityAndOffset);
+
 void get_type0_PDCCH_CSS_config_parameters(NR_Type0_PDCCH_CSS_config_t *type0_PDCCH_CSS_config,
                                            frame_t frameP,
                                            NR_MIB_t *mib,
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index 22a13d223b47f1caba29f1e1b0496bb8cbe221f1..44bd8f0ce35d5ba01e16771505c004e57aba1021 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -57,6 +57,8 @@
 
 #include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
 
+//#define SRS_DEBUG
+
 static prach_association_pattern_t prach_assoc_pattern;
 static ssb_list_info_t ssb_list;
 
@@ -894,6 +896,133 @@ int nr_config_pusch_pdu(NR_UE_MAC_INST_t *mac,
 
 }
 
+// Periodic SRS scheduling
+bool nr_ue_periodic_srs_scheduling(module_id_t mod_id, frame_t frame, slot_t slot) {
+
+  bool srs_scheduled = false;
+
+  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
+
+  NR_SRS_Config_t *srs_config = NULL;
+  if (mac->cg &&
+      mac->cg->spCellConfig &&
+      mac->cg->spCellConfig->spCellConfigDedicated &&
+      mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig &&
+      mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) {
+    srs_config = mac->cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup;
+  } else {
+    return false;
+  }
+
+  for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
+
+    // Find periodic resource set
+    NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
+    if(srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_periodic) {
+      continue;
+    }
+
+    // Find the corresponding srs resource
+    NR_SRS_Resource_t *srs_resource = NULL;
+    for(int r1 = 0; r1 < srs_resource_set->srs_ResourceIdList->list.count; r1++) {
+      for (int r2 = 0; r2 < srs_config->srs_ResourceToAddModList->list.count; r2++) {
+        if ((*srs_resource_set->srs_ResourceIdList->list.array[r1] == srs_config->srs_ResourceToAddModList->list.array[r2]->srs_ResourceId) &&
+            (srs_config->srs_ResourceToAddModList->list.array[r2]->resourceType.present == NR_SRS_Resource__resourceType_PR_periodic)) {
+          srs_resource = srs_config->srs_ResourceToAddModList->list.array[r2];
+          break;
+        }
+      }
+    }
+
+    if(srs_resource == NULL) {
+      continue;
+    }
+
+    NR_BWP_t ubwp = mac->ULbwp[0] ?
+                      mac->ULbwp[0]->bwp_Common->genericParameters :
+                      mac->scc_SIB->uplinkConfigCommon->initialUplinkBWP.genericParameters;
+
+    uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
+    uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
+
+    int n_slots_frame = nr_slots_per_frame[ubwp.subcarrierSpacing];
+
+    // Check if UE should transmit the SRS
+    if((frame*n_slots_frame+slot-offset)%period == 0) {
+
+      fapi_nr_ul_config_request_t *ul_config = get_ul_config_request(mac, slot);
+      fapi_nr_ul_config_srs_pdu *srs_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].srs_config_pdu;
+
+      srs_config_pdu->rnti = mac->crnti;
+      srs_config_pdu->handle = 0;
+      srs_config_pdu->bwp_size = NRRIV2BW(ubwp.locationAndBandwidth, MAX_BWP_SIZE);;
+      srs_config_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp.locationAndBandwidth, MAX_BWP_SIZE);;
+      srs_config_pdu->subcarrier_spacing = ubwp.subcarrierSpacing;
+      srs_config_pdu->cyclic_prefix = 0;
+      srs_config_pdu->num_ant_ports = srs_resource->nrofSRS_Ports;
+      srs_config_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols;
+      srs_config_pdu->num_repetitions = srs_resource->resourceMapping.repetitionFactor;
+      srs_config_pdu->time_start_position = srs_resource->resourceMapping.startPosition;
+      srs_config_pdu->config_index = srs_resource->freqHopping.c_SRS;
+      srs_config_pdu->sequence_id = srs_resource->sequenceId;
+      srs_config_pdu->bandwidth_index = srs_resource->freqHopping.b_SRS;
+      srs_config_pdu->comb_size = srs_resource->transmissionComb.present - 1;
+
+      switch(srs_resource->transmissionComb.present) {
+        case NR_SRS_Resource__transmissionComb_PR_n2:
+          srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n2->combOffset_n2;
+          srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n2->cyclicShift_n2;
+          break;
+        case NR_SRS_Resource__transmissionComb_PR_n4:
+          srs_config_pdu->comb_offset = srs_resource->transmissionComb.choice.n4->combOffset_n4;
+          srs_config_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n4->cyclicShift_n4;
+          break;
+        default:
+          LOG_W(NR_MAC, "Invalid or not implemented comb_size!\n");
+      }
+
+      srs_config_pdu->frequency_position = srs_resource->freqDomainPosition;
+      srs_config_pdu->frequency_shift = srs_resource->freqDomainShift;
+      srs_config_pdu->frequency_hopping = srs_resource->freqHopping.b_hop;
+      srs_config_pdu->group_or_sequence_hopping = srs_resource->groupOrSequenceHopping;
+      srs_config_pdu->resource_type = srs_resource->resourceType.present - 1;
+      srs_config_pdu->t_srs = period;
+      srs_config_pdu->t_offset = offset;
+
+#ifdef SRS_DEBUG
+      LOG_I(NR_MAC,"Frame = %i, slot = %i\n", frame, slot);
+      LOG_I(NR_MAC,"srs_config_pdu->rnti = 0x%04x\n", srs_config_pdu->rnti);
+      LOG_I(NR_MAC,"srs_config_pdu->handle = %u\n", srs_config_pdu->handle);
+      LOG_I(NR_MAC,"srs_config_pdu->bwp_size = %u\n", srs_config_pdu->bwp_size);
+      LOG_I(NR_MAC,"srs_config_pdu->bwp_start = %u\n", srs_config_pdu->bwp_start);
+      LOG_I(NR_MAC,"srs_config_pdu->subcarrier_spacing = %u\n", srs_config_pdu->subcarrier_spacing);
+      LOG_I(NR_MAC,"srs_config_pdu->cyclic_prefix = %u (0: Normal; 1: Extended)\n", srs_config_pdu->cyclic_prefix);
+      LOG_I(NR_MAC,"srs_config_pdu->num_ant_ports = %u (0 = 1 port, 1 = 2 ports, 2 = 4 ports)\n", srs_config_pdu->num_ant_ports);
+      LOG_I(NR_MAC,"srs_config_pdu->num_symbols = %u (0 = 1 symbol, 1 = 2 symbols, 2 = 4 symbols)\n", srs_config_pdu->num_symbols);
+      LOG_I(NR_MAC,"srs_config_pdu->num_repetitions = %u (0 = 1, 1 = 2, 2 = 4)\n", srs_config_pdu->num_repetitions);
+      LOG_I(NR_MAC,"srs_config_pdu->time_start_position = %u\n", srs_config_pdu->time_start_position);
+      LOG_I(NR_MAC,"srs_config_pdu->config_index = %u\n", srs_config_pdu->config_index);
+      LOG_I(NR_MAC,"srs_config_pdu->sequence_id = %u\n", srs_config_pdu->sequence_id);
+      LOG_I(NR_MAC,"srs_config_pdu->bandwidth_index = %u\n", srs_config_pdu->bandwidth_index);
+      LOG_I(NR_MAC,"srs_config_pdu->comb_size = %u (0 = comb size 2, 1 = comb size 4, 2 = comb size 8)\n", srs_config_pdu->comb_size);
+      LOG_I(NR_MAC,"srs_config_pdu->comb_offset = %u\n", srs_config_pdu->comb_offset);
+      LOG_I(NR_MAC,"srs_config_pdu->cyclic_shift = %u\n", srs_config_pdu->cyclic_shift);
+      LOG_I(NR_MAC,"srs_config_pdu->frequency_position = %u\n", srs_config_pdu->frequency_position);
+      LOG_I(NR_MAC,"srs_config_pdu->frequency_shift = %u\n", srs_config_pdu->frequency_shift);
+      LOG_I(NR_MAC,"srs_config_pdu->frequency_hopping = %u\n", srs_config_pdu->frequency_hopping);
+      LOG_I(NR_MAC,"srs_config_pdu->group_or_sequence_hopping = %u (0 = No hopping, 1 = Group hopping groupOrSequenceHopping, 2 = Sequence hopping)\n", srs_config_pdu->group_or_sequence_hopping);
+      LOG_I(NR_MAC,"srs_config_pdu->resource_type = %u (0: aperiodic, 1: semi-persistent, 2: periodic)\n", srs_config_pdu->resource_type);
+      LOG_I(NR_MAC,"srs_config_pdu->t_srs = %u\n", srs_config_pdu->t_srs);
+      LOG_I(NR_MAC,"srs_config_pdu->t_offset = %u\n", srs_config_pdu->t_offset);
+#endif
+
+      fill_ul_config(ul_config, frame, slot, FAPI_NR_UL_CONFIG_TYPE_SRS);
+      srs_scheduled = true;
+    }
+  }
+  return srs_scheduled;
+}
+
 // Performs :
 // 1. TODO: Call RRC for link status return to PHY
 // 2. TODO: Perform SR/BSR procedures for scheduling feedback
@@ -962,6 +1091,10 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
     if (!ul_config) {
       LOG_E(NR_MAC, "mac->ul_config is null!\n");
     }
+
+    // Periodic SRS scheduling
+    nr_ue_periodic_srs_scheduling(mod_id, frame_tx, slot_tx);
+
     // Schedule ULSCH only if the current frame and slot match those in ul_config_req
     // AND if a UL grant (UL DCI or Msg3) has been received (as indicated by num_pdus)
     if (ul_config){
@@ -1052,7 +1185,7 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
   }
 
   if (dl_info) {
-    return (CONNECTION_OK);
+    return (UE_CONNECTION_OK);
   }
   module_id_t mod_id = ul_info->module_id;
   frame_t txFrameP = ul_info->frame_tx;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 0c9908d2617cbe94fca46386406af153f917103a..ba854608c53613889398c9d6fae85cc0f5070127 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -273,7 +273,6 @@ bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot) {
 void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
                                frame_t frame,
                                sub_frame_t slot){
-  //pthread_mutex_lock(&mutextest);
 
   protocol_ctxt_t   ctxt={0};
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP);
@@ -379,6 +378,10 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
   if (slot == 0)
     nr_csi_meas_reporting(module_idP, frame, slot);
 
+  // Schedule SRS: check in slot 0 for the whole frame
+  if (slot == 0)
+    nr_schedule_srs(module_idP, frame);
+
   // This schedule RA procedure if not in phy_test mode
   // Otherwise already consider 5G already connected
   if (get_softmodem_params()->phy_test == 0) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index 928d14c1aa28a53ccaf78976c286c2a254384952..a1dfc7c833f8df8eb4b6832602bb750e0b8dca15 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -2038,6 +2038,11 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *CellG
     sched_ctrl->pucch_consecutive_dtx_cnt = 0;
     sched_ctrl->pusch_consecutive_dtx_cnt = 0;
     sched_ctrl->ul_failure                = 0;
+
+    sched_ctrl->sched_srs.frame = -1;
+    sched_ctrl->sched_srs.slot = -1;
+    sched_ctrl->sched_srs.srs_scheduled = false;
+
     /* set illegal time domain allocation to force recomputation of all fields */
     sched_ctrl->pdsch_semi_static.time_domain_allocation = -1;
     sched_ctrl->pusch_semi_static.time_domain_allocation = -1;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c
new file mode 100644
index 0000000000000000000000000000000000000000..a2b27357dd99dbee1883860d753e7a512986bf28
--- /dev/null
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_srs.c
@@ -0,0 +1,186 @@
+/*
+ * 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_srs.c
+ * \brief MAC procedures related to SRS
+ * \date 2021
+ * \version 1.0
+ */
+
+#include <softmodem-common.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"
+#include "nfapi/oai_integration/vendor_ext.h"
+
+extern RAN_CONTEXT_t RC;
+
+void nr_configure_srs(nfapi_nr_srs_pdu_t *srs_pdu, int module_id, int CC_id, int UE_id, NR_SRS_Resource_t *srs_resource) {
+
+  gNB_MAC_INST *nrmac = RC.nrmac[module_id];
+  NR_ServingCellConfigCommon_t *scc = nrmac->common_channels[CC_id].ServingCellConfigCommon;
+  NR_UE_info_t *UE_info = &nrmac->UE_info;
+  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+
+  NR_BWP_t ubwp = sched_ctrl->active_ubwp ?
+                  sched_ctrl->active_ubwp->bwp_Common->genericParameters :
+                  scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
+
+  srs_pdu->rnti = UE_info->rnti[UE_id];
+  srs_pdu->handle = 0;
+  srs_pdu->bwp_size = NRRIV2BW(ubwp.locationAndBandwidth, MAX_BWP_SIZE);;
+  srs_pdu->bwp_start = NRRIV2PRBOFFSET(ubwp.locationAndBandwidth, MAX_BWP_SIZE);;
+  srs_pdu->subcarrier_spacing = ubwp.subcarrierSpacing;
+  srs_pdu->cyclic_prefix = 0;
+  srs_pdu->num_ant_ports = srs_resource->nrofSRS_Ports;
+  srs_pdu->num_symbols = srs_resource->resourceMapping.nrofSymbols;
+  srs_pdu->num_repetitions = srs_resource->resourceMapping.repetitionFactor;
+  srs_pdu->time_start_position = srs_resource->resourceMapping.startPosition;
+  srs_pdu->config_index = srs_resource->freqHopping.c_SRS;
+  srs_pdu->sequence_id = srs_resource->sequenceId;
+  srs_pdu->bandwidth_index = srs_resource->freqHopping.b_SRS;
+  srs_pdu->comb_size = srs_resource->transmissionComb.present - 1;
+
+  switch(srs_resource->transmissionComb.present) {
+    case NR_SRS_Resource__transmissionComb_PR_n2:
+      srs_pdu->comb_offset = srs_resource->transmissionComb.choice.n2->combOffset_n2;
+      srs_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n2->cyclicShift_n2;
+      break;
+    case NR_SRS_Resource__transmissionComb_PR_n4:
+      srs_pdu->comb_offset = srs_resource->transmissionComb.choice.n4->combOffset_n4;
+      srs_pdu->cyclic_shift = srs_resource->transmissionComb.choice.n4->cyclicShift_n4;
+      break;
+    default:
+      LOG_W(NR_MAC, "Invalid or not implemented comb_size!\n");
+  }
+
+  srs_pdu->frequency_position = srs_resource->freqDomainPosition;
+  srs_pdu->frequency_shift = srs_resource->freqDomainShift;
+  srs_pdu->frequency_hopping = srs_resource->freqHopping.b_hop;
+  srs_pdu->group_or_sequence_hopping = srs_resource->groupOrSequenceHopping;
+  srs_pdu->resource_type = srs_resource->resourceType.present - 1;
+  srs_pdu->t_srs = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
+  srs_pdu->t_offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
+}
+
+void nr_fill_nfapi_srs(int module_id, int CC_id, int UE_id, sub_frame_t slot, NR_SRS_Resource_t *srs_resource) {
+
+  nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][slot];
+
+  future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_SRS_PDU_TYPE;
+  future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_srs_pdu_t);
+  nfapi_nr_srs_pdu_t *srs_pdu = &future_ul_tti_req->pdus_list[future_ul_tti_req->n_pdus].srs_pdu;
+  memset(srs_pdu, 0, sizeof(nfapi_nr_srs_pdu_t));
+  future_ul_tti_req->n_pdus += 1;
+
+  nr_configure_srs(srs_pdu, module_id, CC_id, UE_id, srs_resource);
+}
+
+/*******************************************************************
+*
+* NAME :         nr_schedule_srs
+*
+* PARAMETERS :   module id
+*                frame number for possible SRS reception
+*
+* DESCRIPTION :  It informs the PHY layer that has an SRS to receive.
+*                Only for periodic scheduling yet.
+*
+*********************************************************************/
+void nr_schedule_srs(int module_id, frame_t frame) {
+
+  gNB_MAC_INST *nrmac = RC.nrmac[module_id];
+  NR_UE_info_t *UE_info = &nrmac->UE_info;
+  const NR_list_t *UE_list = &UE_info->list;
+
+  for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
+
+    const int CC_id = 0;
+    NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon;
+    NR_CellGroupConfig_t *cg = UE_info->CellGroup[UE_id];
+    NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+
+    sched_ctrl->sched_srs.frame = -1;
+    sched_ctrl->sched_srs.slot = -1;
+    sched_ctrl->sched_srs.srs_scheduled = false;
+
+    if(!UE_info->Msg4_ACKed[UE_id]) {
+      continue;
+    }
+
+    NR_SRS_Config_t *srs_config = NULL;
+    if (cg &&
+        cg->spCellConfig &&
+        cg->spCellConfig->spCellConfigDedicated &&
+        cg->spCellConfig->spCellConfigDedicated->uplinkConfig &&
+        cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP) {
+      srs_config = cg->spCellConfig->spCellConfigDedicated->uplinkConfig->initialUplinkBWP->srs_Config->choice.setup;
+    } else {
+      continue;
+    }
+
+    for(int rs = 0; rs < srs_config->srs_ResourceSetToAddModList->list.count; rs++) {
+
+      // Find periodic resource set
+      NR_SRS_ResourceSet_t *srs_resource_set = srs_config->srs_ResourceSetToAddModList->list.array[rs];
+      if (srs_resource_set->resourceType.present != NR_SRS_ResourceSet__resourceType_PR_periodic) {
+        continue;
+      }
+
+      // Find the corresponding srs resource
+      NR_SRS_Resource_t *srs_resource = NULL;
+      for (int r1 = 0; r1 < srs_resource_set->srs_ResourceIdList->list.count; r1++) {
+        for (int r2 = 0; r2 < srs_config->srs_ResourceToAddModList->list.count; r2++) {
+          if ((*srs_resource_set->srs_ResourceIdList->list.array[r1] ==
+               srs_config->srs_ResourceToAddModList->list.array[r2]->srs_ResourceId) &&
+              (srs_config->srs_ResourceToAddModList->list.array[r2]->resourceType.present ==
+               NR_SRS_Resource__resourceType_PR_periodic)) {
+            srs_resource = srs_config->srs_ResourceToAddModList->list.array[r2];
+            break;
+          }
+        }
+      }
+
+      if (srs_resource == NULL) {
+        continue;
+      }
+
+      NR_BWP_t ubwp = sched_ctrl->active_ubwp ?
+                        sched_ctrl->active_ubwp->bwp_Common->genericParameters :
+                        scc->uplinkConfigCommon->initialUplinkBWP->genericParameters;
+
+      uint16_t period = srs_period[srs_resource->resourceType.choice.periodic->periodicityAndOffset_p.present];
+      uint16_t offset = get_nr_srs_offset(srs_resource->resourceType.choice.periodic->periodicityAndOffset_p);
+
+      int n_slots_frame = nr_slots_per_frame[ubwp.subcarrierSpacing];
+
+      // Check if UE will transmit the SRS in this frame
+      if ( ((frame - offset/n_slots_frame)*n_slots_frame)%period == 0) {
+        LOG_D(NR_MAC,"Scheduling SRS reception for %d.%d\n", frame, offset%n_slots_frame);
+        nr_fill_nfapi_srs(module_id, CC_id, UE_id, offset%n_slots_frame, srs_resource);
+        sched_ctrl->sched_srs.frame = frame;
+        sched_ctrl->sched_srs.slot = offset%n_slots_frame;
+        sched_ctrl->sched_srs.srs_scheduled = true;
+      }
+    }
+  }
+}
\ No newline at end of file
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 6d7dbf5506aa825b4cf4c33460ff99f20dea2852..0a18731c0ae3c0b35795eec73d1a38eff80024aa 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -1408,6 +1408,15 @@ bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t
   if (sched_ctrl->active_ubwp==NULL && is_mixed_slot)
     return false;
 
+  // Avoid slots with the SRS
+  const NR_list_t *UE_list = &UE_info->list;
+  for (int UE_idx = UE_list->head; UE_idx >= 0; UE_idx = UE_list->next[UE_idx]) {
+    NR_sched_srs_t sched_srs = UE_info->UE_sched_ctrl[UE_idx].sched_srs;
+    if(sched_srs.srs_scheduled && sched_srs.frame==sched_frame && sched_srs.slot==sched_slot) {
+      return false;
+    }
+  }
+
   sched_ctrl->sched_pusch.slot = sched_slot;
   sched_ctrl->sched_pusch.frame = sched_frame;
   for (UE_id = UE_info->list.next[UE_id]; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
@@ -1649,7 +1658,7 @@ void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
     memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t));
     future_ul_tti_req->n_pdus += 1;
 
-    LOG_D(NR_MAC, "%4d.%2d Scheduling UE specific PUSCH for sched %d.%d, ul_tto_req %d.%d\n", frame, slot,
+    LOG_D(NR_MAC, "%4d.%2d Scheduling UE specific PUSCH for sched %d.%d, ul_tti_req %d.%d\n", frame, slot,
     sched_pusch->frame,sched_pusch->slot,future_ul_tti_req->SFN,future_ul_tti_req->Slot);
 
     pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 2dbb924d7b792727bc27db9caaaf0a193a58817c..9afd2a40836d77e1d71bb428e9e37a4d0bb45081 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -190,6 +190,8 @@ void nr_schedule_pucch(int Mod_idP,
                        frame_t frameP,
                        sub_frame_t slotP);
 
+void nr_schedule_srs(int module_id, frame_t frame);
+
 void nr_csirs_scheduling(int Mod_idP,
                          frame_t frame,
                          sub_frame_t slot,
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index f7735a28b109e015114818b5b82616dbbb7b10f6..5b3fb91eb729bc2f57b083da50883defb1e3b640 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -378,6 +378,12 @@ typedef struct NR_sched_pusch {
   int time_domain_allocation;
 } NR_sched_pusch_t;
 
+typedef struct NR_sched_srs {
+  int frame;
+  int slot;
+  bool srs_scheduled;
+} NR_sched_srs_t;
+
 /* PDSCH semi-static configuratio: as long as the TDA/DMRS/mcsTable remains the
  * same, there is no need to recalculate all S/L or DMRS-related parameters
  * over and over again.  Hence, we store them in this struct for easy
@@ -565,9 +571,12 @@ typedef struct {
 
   /// PUSCH semi-static configuration: is not cleared across TTIs
   NR_pusch_semi_static_t pusch_semi_static;
-  /// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI
+  /// Sched PUSCH: scheduling decisions, copied into HARQ and cleared every TTI
   NR_sched_pusch_t sched_pusch;
 
+  /// Sched SRS: scheduling decisions
+  NR_sched_srs_t sched_srs;
+
   /// uplink bytes that are currently scheduled
   int sched_ul_bytes;
   /// estimation of the UL buffer size
diff --git a/openair2/RRC/NR/L2_nr_interface.c b/openair2/RRC/NR/L2_nr_interface.c
index eb402092b9a44aa82e6a1f4ea9ee41a7a775ae8f..cf7dcf1b644ee195b3e2bddac6ab63029d72b3b8 100644
--- a/openair2/RRC/NR/L2_nr_interface.c
+++ b/openair2/RRC/NR/L2_nr_interface.c
@@ -325,7 +325,7 @@ int8_t nr_mac_rrc_data_ind(const module_id_t     module_idP,
     NR_ServingCellConfigCommon_t *scc=RC.nrrrc[module_idP]->carrier.servingcellconfigcommon;
     memset(&cellGroupConfig,0,sizeof(cellGroupConfig));
 
-    fill_initial_cellGroupConfig(rntiP,&cellGroupConfig,scc,&RC.nrrrc[module_idP]->carrier);
+    fill_initial_cellGroupConfig(rntiP,-1,&cellGroupConfig,scc,&RC.nrrrc[module_idP]->carrier);
     MessageDef* tmp=itti_alloc_new_message_sized(TASK_RRC_GNB, 0, F1AP_INITIAL_UL_RRC_MESSAGE, sizeof(f1ap_initial_ul_rrc_message_t) + sdu_lenP);
     f1ap_initial_ul_rrc_message_t *msg = &F1AP_INITIAL_UL_RRC_MESSAGE(tmp);
 
@@ -346,14 +346,14 @@ int8_t nr_mac_rrc_data_ind(const module_id_t     module_idP,
     memcpy(msg->rrc_container, sduP, sdu_lenP);
     msg->rrc_container_length=sdu_lenP;
     itti_send_msg_to_task(TASK_DU_F1, 0, tmp);
-    
+
     struct rrc_gNB_ue_context_s *ue_context_p = rrc_gNB_allocate_new_UE_context(RC.nrrrc[module_idP]);
     ue_context_p->ue_id_rnti                    = rntiP;
     ue_context_p->ue_context.rnti               = rntiP;
     ue_context_p->ue_context.random_ue_identity = rntiP;
     ue_context_p->ue_context.Srb0.Active        = 1;
     RB_INSERT(rrc_nr_ue_tree_s, &RC.nrrrc[module_idP]->rrc_ue_head, ue_context_p);
-    
+
     return(0);
   }
 
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.c b/openair2/RRC/NR/MESSAGES/asn1_msg.c
index 84a0cf75d192af0f5a0d1ddd31b2f8a81adb0198..bbc05da506ef8358dfb036d8f9ad641e5e859130 100755
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.c
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.c
@@ -39,6 +39,7 @@
 #include <asn_application.h>
 #include <asn_internal.h> /* for _ASN_DEFAULT_STACK_MAX */
 #include <per_encoder.h>
+#include <nr/nr_common.h>
 
 #include "asn1_msg.h"
 #include "../nr_rrc_proto.h"
@@ -976,10 +977,42 @@ uint8_t do_RRCReject(uint8_t Mod_id,
     return((enc_rval.encoded+7)/8);
 }
 
+// TODO: Implement to b_SRS = 1 and b_SRS = 2
+long rrc_get_max_nr_csrs(uint8_t max_rbs, long b_SRS) {
+
+  if(b_SRS>0) {
+    LOG_E(NR_RRC,"rrc_get_max_nr_csrs(): Not implemented yet for b_SRS>0\n");
+    return 0; // This c_srs is always valid
+  }
+
+  const uint16_t m_SRS[64] = { 4, 8, 12, 16, 16, 20, 24, 24, 28, 32, 36, 40, 48, 48, 52, 56, 60, 64, 72, 72, 76, 80, 88,
+                               96, 96, 104, 112, 120, 120, 120, 128, 128, 128, 132, 136, 144, 144, 144, 144, 152, 160,
+                               160, 160, 168, 176, 184, 192, 192, 192, 192, 208, 216, 224, 240, 240, 240, 240, 256, 256,
+                               256, 264, 272, 272, 272 };
+
+  long c_srs = 0;
+  uint16_t m = 4;
+  for(int c = 1; c<64; c++) {
+    if(m_SRS[c]>m && m_SRS[c]<max_rbs) {
+      c_srs = c;
+      m = m_SRS[c];
+    }
+  }
+
+  return c_srs;
+}
+
 void fill_initial_SpCellConfig(rnti_t rnti,
+                               int uid,
                                NR_SpCellConfig_t *SpCellConfig,
                                NR_ServingCellConfigCommon_t *scc,
                                rrc_gNB_carrier_data_t *carrier) {
+
+  // This assert will never happen in the current implementation because NUMBER_OF_UE_MAX = 4.
+  // However, if in the future NUMBER_OF_UE_MAX is increased, it will be necessary to improve the allocation of SRS resources,
+  // where the startPosition = 2 or 3 and sl160 = 17, 17, 27 ... 157 only give us 30 different allocations.
+  AssertFatal(uid>=0 && uid<30, "gNB cannot allocate the SRS resources\n");
+
   int curr_bwp = NRRIV2BW(scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth,MAX_BWP_SIZE);
   SpCellConfig->servCellIndex = NULL;
   SpCellConfig->reconfigurationWithSync = NULL;
@@ -1058,7 +1091,7 @@ void fill_initial_SpCellConfig(rnti_t rnti,
   pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList = calloc(1,sizeof(*pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList));
   NR_PUSCH_PathlossReferenceRS_t *plrefRS = calloc(1,sizeof(*plrefRS));
   plrefRS->pusch_PathlossReferenceRS_Id=0;
-  plrefRS->referenceSignal.present = NR_PathlossReferenceRS_Config_PR_ssb_Index;
+  plrefRS->referenceSignal.present = NR_PUSCH_PathlossReferenceRS__referenceSignal_PR_ssb_Index;
   plrefRS->referenceSignal.choice.ssb_Index = 0;
   ASN_SEQUENCE_ADD(&pusch_Config->pusch_PowerControl->pathlossReferenceRSToAddModList->list,plrefRS);
   pusch_Config->pusch_PowerControl->pathlossReferenceRSToReleaseList = NULL;
@@ -1105,13 +1138,21 @@ void fill_initial_SpCellConfig(rnti_t rnti,
   *srs_resset0_id=0;
   ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list,srs_resset0_id);
   srs_Config->srs_ResourceToReleaseList=NULL;
-  srs_resset0->resourceType.present =  NR_SRS_ResourceSet__resourceType_PR_aperiodic;
-  srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic));
-  srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1;
-  srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL;
-  srs_resset0->resourceType.choice.aperiodic->slotOffset= calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset));
-  *srs_resset0->resourceType.choice.aperiodic->slotOffset=2;
-  srs_resset0->resourceType.choice.aperiodic->ext1=NULL;
+
+  if(carrier->do_SRS) {
+    srs_resset0->resourceType.present =  NR_SRS_ResourceSet__resourceType_PR_periodic;
+    srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic));
+    srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL;
+  } else {
+    srs_resset0->resourceType.present =  NR_SRS_ResourceSet__resourceType_PR_aperiodic;
+    srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic));
+    srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1;
+    srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL;
+    srs_resset0->resourceType.choice.aperiodic->slotOffset= calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset));
+    *srs_resset0->resourceType.choice.aperiodic->slotOffset=2;
+    srs_resset0->resourceType.choice.aperiodic->ext1=NULL;
+  }
+
   srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook;
   srs_resset0->alpha = calloc(1,sizeof(*srs_resset0->alpha));
   *srs_resset0->alpha = NR_Alpha_alpha1;
@@ -1130,17 +1171,28 @@ void fill_initial_SpCellConfig(rnti_t rnti,
   srs_res0->transmissionComb.choice.n2=calloc(1,sizeof(*srs_res0->transmissionComb.choice.n2));
   srs_res0->transmissionComb.choice.n2->combOffset_n2=0;
   srs_res0->transmissionComb.choice.n2->cyclicShift_n2=0;
-  srs_res0->resourceMapping.startPosition=2;
+  srs_res0->resourceMapping.startPosition = 2 + uid%2;
   srs_res0->resourceMapping.nrofSymbols=NR_SRS_Resource__resourceMapping__nrofSymbols_n1;
   srs_res0->resourceMapping.repetitionFactor=NR_SRS_Resource__resourceMapping__repetitionFactor_n1;
   srs_res0->freqDomainPosition=0;
   srs_res0->freqDomainShift=0;
-  srs_res0->freqHopping.c_SRS = 0;
   srs_res0->freqHopping.b_SRS=0;
   srs_res0->freqHopping.b_hop=0;
+  srs_res0->freqHopping.c_SRS = rrc_get_max_nr_csrs(
+      NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275),
+      srs_res0->freqHopping.b_SRS);
   srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither;
-  srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_aperiodic;
-  srs_res0->resourceType.choice.aperiodic=calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic));
+
+  if(carrier->do_SRS) {
+    srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_periodic;
+    srs_res0->resourceType.choice.periodic=calloc(1,sizeof(*srs_res0->resourceType.choice.periodic));
+    srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160;
+    srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.choice.sl160 = 17 + (uid>1)*10; // 17/17/.../147/157 are mixed slots
+  } else {
+    srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_aperiodic;
+    srs_res0->resourceType.choice.aperiodic=calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic));
+  }
+
   srs_res0->sequenceId=40;
   srs_res0->spatialRelationInfo=calloc(1,sizeof(*srs_res0->spatialRelationInfo));
   srs_res0->spatialRelationInfo->servingCellId=NULL;
@@ -1397,6 +1449,7 @@ void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGr
 }
 
 void fill_initial_cellGroupConfig(rnti_t rnti,
+                                  int uid,
                                   NR_CellGroupConfig_t *cellGroupConfig,
                                   NR_ServingCellConfigCommon_t *scc,
                                   rrc_gNB_carrier_data_t *carrier) {
@@ -1490,7 +1543,7 @@ void fill_initial_cellGroupConfig(rnti_t rnti,
   
   cellGroupConfig->spCellConfig                                             = calloc(1,sizeof(*cellGroupConfig->spCellConfig));
   
-  fill_initial_SpCellConfig(rnti,cellGroupConfig->spCellConfig,scc,carrier);
+  fill_initial_SpCellConfig(rnti,uid,cellGroupConfig->spCellConfig,scc,carrier);
   
   cellGroupConfig->sCellToAddModList                                        = NULL;
   cellGroupConfig->sCellToReleaseList                                       = NULL;
@@ -1569,7 +1622,7 @@ uint8_t do_RRCSetup(rrc_gNB_ue_context_t         *const ue_context_pP,
     }
     else {
       cellGroupConfig = calloc(1, sizeof(NR_CellGroupConfig_t));
-      fill_initial_cellGroupConfig(ue_context_pP->ue_context.rnti,cellGroupConfig,scc,carrier);
+      fill_initial_cellGroupConfig(ue_context_pP->ue_context.rnti,ue_context_pP->local_uid,cellGroupConfig,scc,carrier);
 
       enc_rval = uper_encode_to_buffer(&asn_DEF_NR_CellGroupConfig,
 				       NULL,
diff --git a/openair2/RRC/NR/MESSAGES/asn1_msg.h b/openair2/RRC/NR/MESSAGES/asn1_msg.h
index 6803cf21d7e7e4742359c968dc4a731c666afb49..ca92652c6ce21f85e126f5b168b4696432955e58 100644
--- a/openair2/RRC/NR/MESSAGES/asn1_msg.h
+++ b/openair2/RRC/NR/MESSAGES/asn1_msg.h
@@ -101,13 +101,15 @@ uint8_t do_RRCReject(uint8_t Mod_id,
                      uint8_t *const buffer);
 
 void fill_initial_SpCellConfig(rnti_t rnti,
-			       NR_SpCellConfig_t *SpCellConfig,
-			       NR_ServingCellConfigCommon_t *scc,
+                               int uid,
+                               NR_SpCellConfig_t *SpCellConfig,
+                               NR_ServingCellConfigCommon_t *scc,
                                rrc_gNB_carrier_data_t *carrier);
 
 void fill_initial_cellGroupConfig(rnti_t rnti,
-				  NR_CellGroupConfig_t *cellGroupConfig,
-				  NR_ServingCellConfigCommon_t *scc,
+                                  int uid,
+                                  NR_CellGroupConfig_t *cellGroupConfig,
+                                  NR_ServingCellConfigCommon_t *scc,
                                   rrc_gNB_carrier_data_t *carrier);
 
 void fill_mastercellGroupConfig(NR_CellGroupConfig_t *cellGroupConfig, NR_CellGroupConfig_t *ue_context_mastercellGroup);
diff --git a/openair2/RRC/NR/nr_rrc_defs.h b/openair2/RRC/NR/nr_rrc_defs.h
index a92cf9861c9e8cc0f38775f4554e9b4af625b5f0..667b5ed24a1213fb57e55fbde6fa1e8fd88b9678 100644
--- a/openair2/RRC/NR/nr_rrc_defs.h
+++ b/openair2/RRC/NR/nr_rrc_defs.h
@@ -451,6 +451,7 @@ typedef struct {
   int pusch_AntennaPorts;
   int minRXTXTIME;
   int do_CSIRS;
+  int do_SRS;
   NR_BCCH_DL_SCH_Message_t                  *siblock1;
   NR_ServingCellConfigCommon_t              *servingcellconfigcommon;
   NR_PDCCH_ConfigSIB1_t                     *pdcch_ConfigSIB1;
diff --git a/openair2/RRC/NR/nr_rrc_proto.h b/openair2/RRC/NR/nr_rrc_proto.h
index 22109c30296300d5db80cbd1685a3d97518fbff8..40de13dfb03467fd5c341c19e4540c9fc0ce1bf4 100644
--- a/openair2/RRC/NR/nr_rrc_proto.h
+++ b/openair2/RRC/NR/nr_rrc_proto.h
@@ -81,6 +81,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
                                      int dl_antenna_ports,
                                      int minRXTXTIMEpdsch,
                                      int do_csirs,
+                                     int do_srs,
                                      int initial_csi_index,
                                      int uid);
 
@@ -93,6 +94,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
                            int dl_antenna_ports,
                            int minRXTXTIMEpdsch,
                            int do_csirs,
+                           int do_srs,
                            int initial_csi_index,
                            int uid);
 
diff --git a/openair2/RRC/NR/rrc_gNB.c b/openair2/RRC/NR/rrc_gNB.c
index 049e1a68275e6c8b7d5adbe178e2a0173ec7d396..dda128f52f72545f4af6a8d7efe25d8d0c8ac704 100755
--- a/openair2/RRC/NR/rrc_gNB.c
+++ b/openair2/RRC/NR/rrc_gNB.c
@@ -239,6 +239,7 @@ char openair_rrc_gNB_configuration(const module_id_t gnb_mod_idP, gNB_RrcConfigu
   rrc->carrier.minRXTXTIME = configuration->minRXTXTIME;
   rrc->carrier.sib1_tda = configuration->sib1_tda;
   rrc->carrier.do_CSIRS = configuration->do_CSIRS;
+  rrc->carrier.do_SRS = configuration->do_SRS;
   nr_rrc_config_ul_tda(configuration->scc,configuration->minRXTXTIME);
    /// System Information INIT
   pthread_mutex_init(&rrc->cell_info_mutex,NULL);
diff --git a/openair2/RRC/NR/rrc_gNB_nsa.c b/openair2/RRC/NR/rrc_gNB_nsa.c
index 15caff0b4d8d4bfd084f144723ceb8844da495a0..536010bbc6b0c7bc3606b7859b786b2105d878e7 100644
--- a/openair2/RRC/NR/rrc_gNB_nsa.c
+++ b/openair2/RRC/NR/rrc_gNB_nsa.c
@@ -263,24 +263,26 @@ void rrc_add_nsa_user(gNB_RRC_INST *rrc,struct rrc_gNB_ue_context_s *ue_context_
   }
   if (ue_context_p->ue_context.spCellConfig) {
     fill_default_reconfig(carrier->servingcellconfigcommon,
-                        ue_context_p->ue_context.spCellConfig->spCellConfigDedicated,
-                        reconfig_ies,
-                        ue_context_p->ue_context.secondaryCellGroup,
-                        carrier->pdsch_AntennaPorts,
-                        carrier->minRXTXTIME,
-                        carrier->do_CSIRS,
-                        carrier->initial_csi_index[ue_context_p->local_uid + 1],
-                        ue_context_p->local_uid);
+                          ue_context_p->ue_context.spCellConfig->spCellConfigDedicated,
+                          reconfig_ies,
+                          ue_context_p->ue_context.secondaryCellGroup,
+                          carrier->pdsch_AntennaPorts,
+                          carrier->minRXTXTIME,
+                          carrier->do_CSIRS,
+                          carrier->do_SRS,
+                          carrier->initial_csi_index[ue_context_p->local_uid + 1],
+                          ue_context_p->local_uid);
   } else {
     fill_default_reconfig(carrier->servingcellconfigcommon,
-                        NULL,
-                        reconfig_ies,
-                        ue_context_p->ue_context.secondaryCellGroup,
-                        carrier->pdsch_AntennaPorts,
-                        carrier->minRXTXTIME,
-                        carrier->do_CSIRS,
-                        carrier->initial_csi_index[ue_context_p->local_uid + 1],
-                        ue_context_p->local_uid);
+                          NULL,
+                          reconfig_ies,
+                          ue_context_p->ue_context.secondaryCellGroup,
+                          carrier->pdsch_AntennaPorts,
+                          carrier->minRXTXTIME,
+                          carrier->do_CSIRS,
+                          carrier->do_SRS,
+                          carrier->initial_csi_index[ue_context_p->local_uid + 1],
+                          ue_context_p->local_uid);
   }
   ue_context_p->ue_id_rnti = ue_context_p->ue_context.secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity;
   NR_CG_Config_t *CG_Config = calloc(1,sizeof(*CG_Config));
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index 30604cd015fa451902b176a2e76c78ddaddad5d7..db4dc2d579af718f91c5e3e4c2e86ec2cae788e5 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -57,11 +57,17 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
                                      int dl_antenna_ports,
                                      int minRXTXTIME,
                                      int do_csirs,
+                                     int do_srs,
                                      int initial_csi_index,
                                      int uid) {
   AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
   AssertFatal(secondaryCellGroup!=NULL,"secondaryCellGroup is null\n");
 
+  // This assert will never happen in the current implementation because NUMBER_OF_UE_MAX = 4.
+  // However, if in the future NUMBER_OF_UE_MAX is increased, it will be necessary to improve the allocation of SRS resources,
+  // where the startPosition = 2 or 3 and sl160 = 17, 17, 27 ... 157 only give us 30 different allocations.
+  AssertFatal(uid>=0 && uid<30, "gNB cannot allocate the SRS resources\n");
+
   uint64_t bitmap=0;
   switch (servingcellconfigcommon->ssb_PositionsInBurst->present) {
     case 1 :
@@ -797,13 +803,21 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  *srs_resset0_id=0;
  ASN_SEQUENCE_ADD(&srs_resset0->srs_ResourceIdList->list,srs_resset0_id);
  srs_Config->srs_ResourceToReleaseList=NULL;
- srs_resset0->resourceType.present =  NR_SRS_ResourceSet__resourceType_PR_aperiodic;
- srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic));
- srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1;
- srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL;
- srs_resset0->resourceType.choice.aperiodic->slotOffset= calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset));
- *srs_resset0->resourceType.choice.aperiodic->slotOffset=2;
- srs_resset0->resourceType.choice.aperiodic->ext1=NULL;
+
+  if(do_srs) {
+    srs_resset0->resourceType.present =  NR_SRS_ResourceSet__resourceType_PR_periodic;
+    srs_resset0->resourceType.choice.periodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.periodic));
+    srs_resset0->resourceType.choice.periodic->associatedCSI_RS = NULL;
+  } else {
+    srs_resset0->resourceType.present =  NR_SRS_ResourceSet__resourceType_PR_aperiodic;
+    srs_resset0->resourceType.choice.aperiodic = calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic));
+    srs_resset0->resourceType.choice.aperiodic->aperiodicSRS_ResourceTrigger=1;
+    srs_resset0->resourceType.choice.aperiodic->csi_RS=NULL;
+    srs_resset0->resourceType.choice.aperiodic->slotOffset= calloc(1,sizeof(*srs_resset0->resourceType.choice.aperiodic->slotOffset));
+    *srs_resset0->resourceType.choice.aperiodic->slotOffset=2;
+    srs_resset0->resourceType.choice.aperiodic->ext1=NULL;
+  }
+
  srs_resset0->usage=NR_SRS_ResourceSet__usage_codebook;
  srs_resset0->alpha = calloc(1,sizeof(*srs_resset0->alpha));
  *srs_resset0->alpha = NR_Alpha_alpha1;
@@ -822,17 +836,28 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  srs_res0->transmissionComb.choice.n2=calloc(1,sizeof(*srs_res0->transmissionComb.choice.n2));
  srs_res0->transmissionComb.choice.n2->combOffset_n2=0;
  srs_res0->transmissionComb.choice.n2->cyclicShift_n2=0;
- srs_res0->resourceMapping.startPosition=2;
+ srs_res0->resourceMapping.startPosition = 2 + uid%2;
  srs_res0->resourceMapping.nrofSymbols=NR_SRS_Resource__resourceMapping__nrofSymbols_n1;
  srs_res0->resourceMapping.repetitionFactor=NR_SRS_Resource__resourceMapping__repetitionFactor_n1;
  srs_res0->freqDomainPosition=0;
  srs_res0->freqDomainShift=0;
- srs_res0->freqHopping.c_SRS = 0;
  srs_res0->freqHopping.b_SRS=0;
  srs_res0->freqHopping.b_hop=0;
+ srs_res0->freqHopping.c_SRS = rrc_get_max_nr_csrs(
+     NRRIV2BW(servingcellconfigcommon->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275),
+     srs_res0->freqHopping.b_SRS);
  srs_res0->groupOrSequenceHopping=NR_SRS_Resource__groupOrSequenceHopping_neither;
- srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_aperiodic;
- srs_res0->resourceType.choice.aperiodic=calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic));
+
+  if(do_srs) {
+    srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_periodic;
+    srs_res0->resourceType.choice.periodic=calloc(1,sizeof(*srs_res0->resourceType.choice.periodic));
+    srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.present = NR_SRS_PeriodicityAndOffset_PR_sl160;
+    srs_res0->resourceType.choice.periodic->periodicityAndOffset_p.choice.sl160 = 17 + (uid>1)*10; // 17/17/.../147/157 are mixed slots
+  } else {
+    srs_res0->resourceType.present= NR_SRS_Resource__resourceType_PR_aperiodic;
+    srs_res0->resourceType.choice.aperiodic=calloc(1,sizeof(*srs_res0->resourceType.choice.aperiodic));
+  }
+
  srs_res0->sequenceId=40;
  srs_res0->spatialRelationInfo=calloc(1,sizeof(*srs_res0->spatialRelationInfo));
  srs_res0->spatialRelationInfo->servingCellId=NULL;
@@ -1351,6 +1376,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
                            int dl_antenna_ports,
                            int minRXTXTIME,
                            int do_csirs,
+                           int do_srs,
                            int initial_csi_index,
                            int uid) {
   AssertFatal(servingcellconfigcommon!=NULL,"servingcellconfigcommon is null\n");
@@ -1367,6 +1393,7 @@ void fill_default_reconfig(NR_ServingCellConfigCommon_t *servingcellconfigcommon
                                   dl_antenna_ports,
                                   minRXTXTIME,
                                   do_csirs,
+                                  do_srs,
                                   initial_csi_index,
                                   uid);
 
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf
index cd4cdff48c513d5879847e8d8dce097f02dec758..2777035fddb45380d3f948c913108419d7522ab3 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band41.fr1.106PRB.usrpb210.conf
@@ -37,6 +37,7 @@ gNBs =
     pusch_AntennaPorts                                        = 1;
     min_rxtxtime                                              = 6;
     sib1_tda                                                  = 0;
+    do_SRS                                                    = 1;
 
      pdcch_ConfigSIB1 = (
       {
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf
index 81d86fa1c2d06804e7f9e78096e567c12bf0da02..27a1b6ad62c0258eeb0e5a9dd2a639db9dba3941 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.2x2.usrpn300.conf
@@ -35,7 +35,8 @@ gNBs =
     ssb_SubcarrierOffset                                      = 0;
     pdsch_AntennaPorts                                        = 1;
     pusch_AntennaPorts                                        = 2;
-    min_rxtxtime                                              = 6;
+    sib1_tda                                                  = 0;
+    do_SRS                                                    = 1;
     ul_prbblacklist                                           = "51,52,53,54"
 
     pdcch_ConfigSIB1 = (