diff --git a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf
index 32de0aa4f57d6ea6d05d8625fc93b547056db0dc..5c004e67e448dba388f4ed103238faf7dda1fb9c 100644
--- a/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf
+++ b/ci-scripts/conf_files/gnb.band66.tm1.106PRB.usrpn300.conf
@@ -55,27 +55,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-       #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_3                    = 0;  #for mixed slot
+        initialDLBWPmappingType_3           = 0;
+        initialDLBWPstartSymbolAndLength_3  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon
      #frequencyInfoUL
       ul_frequencyBand                                                 = 66;
@@ -131,20 +118,18 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-  initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
+
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
 
diff --git a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
index a11509a3f021afde65da345cb0de036e661c193a..e2fdbc8448b8e916829a85ae7a57bbf71f323281 100644
--- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -56,27 +56,13 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=5
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
 
   #uplinkConfigCommon 
      #frequencyInfoUL
@@ -132,20 +118,17 @@ gNBs =
         restrictedSetConfig                                         = 0,
 
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-        initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
index daee5486c1d9fab9734563b5d998a8255992263a..8d2f490dc39aba770d3d57f9e8d75d6227c9e3cd 100644
--- a/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
+++ b/ci-scripts/conf_files/gnb.band78.tm1.fr1.106PRB.usrpb210.conf
@@ -57,27 +57,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-       #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
-             initialDLBWPstartSymbolAndLength_3  = 57; //43; //57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -132,20 +119,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
-   
-  initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/doc/SW_archi.md b/doc/SW_archi.md
index d92f8021488fb30b6a2b3fb7d209fc733b92347d..a82043fd10cbaf3babc510f4ed27d02598012923 100644
--- a/doc/SW_archi.md
+++ b/doc/SW_archi.md
@@ -171,24 +171,31 @@ NR_sched_pusch_t (for values changing every TTI, e.g., frequency domain
 allocation) and NR_sched_pusch_save_t (for values changing less frequently, at
 least in FR1 [to my understanding], e.g., DMRS fields when the time domain
 allocation stays between TTIs) structures. Furthermore, the preprocessor is an
-exchangeable module that might schedule differently, e.g., one user for
-phytest, multiple users in FR1, or maybe FR2: phytest is in
-nr_ul_preprocessor_phytest(), for FR1 is nr_simple_ulsch_preprocessor() [under
-development], for FR2 does not exist yet.
+exchangeable module that schedules differently based on a particular
+use-case/deployment type, e.g., one user for phytest [in
+nr_ul_preprocessor_phytest()], multiple users in FR1
+[nr_fr1_ulsch_preprocessor()], or maybe FR2 [does not exist yet]:
 * calls preprocessor via pre_processor_ul(): the preprocessor is responsible
-  for allocating CCEs (using allocate_nr_CCEs()). Note that we do not yet have
-  scheduling requests or buffer status reports, and only one UE. E.g.,
-  nr_simple_ulsch_preprocessor():
+  for allocating CCEs (using allocate_nr_CCEs()) and deciding on resource
+  allocation for the UEs including TB size. Note that we do not yet have
+  scheduling requests. What it typically does:
   1)  check whether the current frame/slot plus K2 is an UL slot, and return if
       not.
   2)  Find first free start RB in vrb_map_UL, and as many free consecutive RBs
       as possible.
-  3)  allocate a CCE for the UE (and return if it is not possible)
-  4)  Calculate DMRS stuff (nr_save_pusch_fields()) and the TBS.
-  5)  Mark used resources in vrb_map_UL.
-* loop through all users: get a free HARQ PID and
-  update statistics. Fill nFAPI structures directly for PUSCH, and call
-  config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH messages.
+  3)  Either set up resource allocation directly (e.g., for a single UE,
+      phytest), or call into a function to perform actual resource allocation.
+      Currently, this is done using pf_ul() which implements a basic
+      proportional fair scheduler:
+      * for every UE, check for retransmission and allocate as necessary
+      * Calculate DMRS stuff (nr_set_pusch_semi_static())
+      * Calculate the PF coefficient and put eligible UEs into a list
+      * Allocate resources to the UE(s) with the highest coefficient
+  4)  Mark used resources in vrb_map_UL.
+* loop through all users: get a HARQ process as indicated through the
+  preprocessor, update statistics, fill nFAPI structures directly for PUSCH,
+  and call config_uldci() and fill_dci_pdu_rel15() for DCI filling and PDCCH
+  messages.
 
 Calls nr_schedule_ue_spec(). It is divided into the "preprocessor" and the
 "postprocessor": the first makes the scheduling decisions, the second fills
@@ -196,29 +203,28 @@ nFAPI structures to indicate to the PHY what it is supposed to do. To signal
 which users have how many resources, the preprocessor populates the
 NR_UE_sched_ctrl_t structure of affected users. In particular, the field rbSize
 decides whether a user is to be allocated. Furthermore, the preprocessor is an
-exchangeable module that might schedule differently, e.g., one user for
-phytest, multiple users in FR1, or maybe FR2: phytest is in
-nr_preprocessor_phytest(), for FR1 is nr_simple_dlsch_preprocessor() [under
-development], for FR2 does not exist yet.
+exchangeable module that schedules differently based on a particular
+use-case/deployment type, e.g., one user for phytest [in
+nr_preprocessor_phytest()], multiple users in FR1
+[nr_fr1_dlsch_preprocessor()], or maybe FR2 [does not exist yet].
 * calls preprocessor via pre_processor_dl(): the preprocessor is responsible
   for allocating CCEs and PUCCH (using allocate_nr_CCEs() and
   nr_acknack_scheduling()) and deciding on the frequency/time domain
-  allocation. E.g., nr_simple_dlsch_preprocessor():
-  1)  mac_rlc_status_ind() locks and checks directly inside rlc data the
-      quantity of waiting data.
-  2)  return from the preprocessor if there is no data and no timing advance to
-      send,
-  3)  otherwise, allocate a CCE for the UE (and return if it is not possible)
-  4)  find a PUCCH occasion for HARQ
-  5a) check if there is a retransmission: if yes, find free resources to
-      transmit using the same resources, else
-  5b) calculate the necessary RBs needed to get a TBS large enough to hold all
-      data, or until no more resources are available
-  6)  Mark taken resources in the vrb_map
+  allocation including the TB size. What it typically does:
+  1)  Check available resources in the vrb_map
+  2)  Checks the quantity of waiting data in RLC
+  3)  Either set up resource allocation directly (e.g., for a single UE,
+      phytest), or call into a function to perform actual resource allocation.
+      Currently, this is done using pf_dl() which implements a basic
+      proportional fair scheduler:
+      * for every UE, check for retransmission and allocate as necessary
+      * Calculate the PF coefficient and put eligible UEs into a list
+      * Allocate resources to the UE(s) with the highest coefficient
+  4)  Mark taken resources in the vrb_map
 * loop through all users: check if a new TA is necessary. Then, if a user has
-  allocated resources, compute its TBS, and fill nFAPI structures
-  (nr_fill_nfapi_dl_pdu() to populate what should be done by the lower layers
-  to make the Tx subframe). Update statistics (round, sent bytes).
+  allocated resources, update statistics (round, sent bytes), update HARQ
+  process information, and fill nFAPI structures (allocate a DCI and PDCCH
+  messages, TX_req, ...)
 
 # RRC
 RRC is a regular thread with itti loop on queue: TASK_RRC_GNB
diff --git a/executables/nr-softmodem-common.h b/executables/nr-softmodem-common.h
index 500819e6844016ea2829d7b0472a8358fff9f70b..813ffcf8fac29f3060f72dbe74057fb8cb03755a 100644
--- a/executables/nr-softmodem-common.h
+++ b/executables/nr-softmodem-common.h
@@ -68,11 +68,15 @@
 #define CONFIG_HLP_SOFTS         "Enable soft scope and L1 and L2 stats (Xforms)\n"
 #define CONFIG_HLP_EXMCAL        "Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n"
 #define CONFIG_HLP_ITTIL         "Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n"
-#define CONFIG_HLP_DLMCS         "Set the maximum downlink MCS\n"
+#define CONFIG_HLP_DLMCS_PHYTEST "Set the downlink MCS for PHYTEST mode\n"
 #define CONFIG_HLP_STMON         "Enable processing timing measurement of lte softmodem on per subframe basis \n"
 #define CONFIG_HLP_PRB           "Set the PRB, valid values: 6, 25, 50, 100  \n"
 #define CONFIG_HLP_MSLOTS        "Skip the missed slots/subframes \n"
-#define CONFIG_HLP_ULMCS         "Set the maximum uplink MCS\n"
+#define CONFIG_HLP_ULMCS_PHYTEST "Set the uplink MCS for PHYTEST mode\n"
+#define CONFIG_HLP_DLBW_PHYTEST  "Set the number of PRBs used for DLSCH in PHYTEST mode\n"
+#define CONFIG_HLP_ULBW_PHYTEST  "Set the number of PRBs used for ULSCH in PHYTEST mode\n"
+#define CONFIG_HLP_DLBM_PHYTEST  "Bitmap for DLSCH slots (slot 0 starts at LSB)\n"
+#define CONFIG_HLP_ULBM_PHYTEST  "Bitmap for ULSCH slots (slot 0 starts at LSB)\n"
 #define CONFIG_HLP_TDD           "Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n"
 #define CONFIG_HLP_UE            "Set the lte softmodem as a UE\n"
 #define CONFIG_HLP_L2MONW        "Enable L2 wireshark messages on localhost \n"
diff --git a/executables/nr-softmodem.c b/executables/nr-softmodem.c
index 63c06563d288666ad25e86905b4b89a4abb85049..a29295ff52a8d00e0b9596cfb8d9e59a0cbed1cd 100644
--- a/executables/nr-softmodem.c
+++ b/executables/nr-softmodem.c
@@ -160,8 +160,6 @@ int otg_enabled;
 
 //static NR_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
 //static nfapi_nr_config_request_t *config[MAX_NUM_CCs];
-uint32_t target_dl_mcs = 28; //maximum allowed mcs
-uint32_t target_ul_mcs = 20;
 uint32_t timing_advance = 0;
 uint64_t num_missed_slots=0; // counter for the number of missed slots
 
diff --git a/executables/nr-softmodem.h b/executables/nr-softmodem.h
index d6cfe6b906acef4026dcf08d7b03433b32fd1986..62c7328144b590b7668826af21d96ae5da46b275 100644
--- a/executables/nr-softmodem.h
+++ b/executables/nr-softmodem.h
@@ -23,14 +23,24 @@
     {"A" ,                    CONFIG_HLP_TADV,        0,                uptr:&timing_advance,               defintval:0,                   TYPE_UINT,   0},        \
     {"E" ,                    CONFIG_HLP_TQFS,        PARAMFLAG_BOOL,   i8ptr:&threequarter_fs,             defintval:0,                   TYPE_INT8,   0},        \
     {"K" ,                    CONFIG_HLP_ITTIL,       PARAMFLAG_NOFREE, strptr:&itti_dump_file,             defstrval:"/tmp/itti.dump",    TYPE_STRING, 0},        \
-    {"m" ,                    CONFIG_HLP_DLMCS,       0,                uptr:&target_dl_mcs,                defintval:0,                   TYPE_UINT,   0},        \
-    {"t" ,                    CONFIG_HLP_ULMCS,       0,                uptr:&target_ul_mcs,                defintval:0,                   TYPE_UINT,   0},        \
+    {"m" ,                    CONFIG_HLP_DLMCS_PHYTEST,0,               uptr:&target_dl_mcs,                defintval:0,                   TYPE_UINT,   0},        \
+    {"t" ,                    CONFIG_HLP_ULMCS_PHYTEST,0,               uptr:&target_ul_mcs,                defintval:0,                   TYPE_UINT,   0},        \
+    {"M" ,                    CONFIG_HLP_DLBW_PHYTEST,0,                uptr:&target_dl_bw,                 defintval:0,                   TYPE_UINT,   0},        \
+    {"T" ,                    CONFIG_HLP_ULBW_PHYTEST,0,                uptr:&target_ul_bw,                 defintval:0,                   TYPE_UINT,   0},        \
+    {"D" ,                    CONFIG_HLP_DLBM_PHYTEST,0,                u64ptr:&dlsch_slot_bitmap,          defintval:0,                   TYPE_UINT64, 0},        \
+    {"U" ,                    CONFIG_HLP_ULBM_PHYTEST,0,                u64ptr:&ulsch_slot_bitmap,          defintval:0,                   TYPE_UINT64, 0},        \
     {"usrp-tx-thread-config", CONFIG_HLP_USRP_THREAD, 0,                iptr:&usrp_tx_thread,               defstrval:0,                   TYPE_INT,    0},        \
     {"s" ,                    CONFIG_HLP_SNR,         0,                dblptr:&snr_dB,                     defdblval:25,                  TYPE_DOUBLE, 0},        \
   }
 
 #include "threads_t.h"
 extern threads_t threads;
+extern uint32_t target_dl_mcs;
+extern uint32_t target_ul_mcs;
+extern uint32_t target_dl_bw;
+extern uint32_t target_ul_bw;
+extern uint64_t dlsch_slot_bitmap;
+extern uint64_t ulsch_slot_bitmap;
 
 // In nr-gnb.c
 extern void init_gNB(int single_thread_flag,int wait_for_sync);
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 674ae82cc392fdf2fa0cb910fcb1e5fbf203a8ed..f49bd114c9ad56fc946a4bb2037ab4635e35f2b6 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -666,7 +666,7 @@ void phy_procedures_gNB_uespec_RX(PHY_VARS_gNB *gNB, int frame_rx, int slot_rx)
 	  start_meas(&gNB->rx_pusch_stats);
 	  for(uint8_t symbol = symbol_start; symbol < symbol_end; symbol++) {
 	    no_sig = nr_rx_pusch(gNB, ULSCH_id, frame_rx, slot_rx, symbol, harq_pid);
-            if (no_sig) {
+            if (no_sig && (get_softmodem_params()->phy_test == 0)) {
               LOG_I(PHY, "PUSCH not detected in symbol %d\n",symbol);
               nr_fill_indication(gNB,frame_rx, slot_rx, ULSCH_id, harq_pid, 1);
               return;
diff --git a/openair1/SIMULATION/NR_PHY/dlsim.c b/openair1/SIMULATION/NR_PHY/dlsim.c
index 9614b4b649abf46b0e59e5a391213ef70606d768..a2ece67f318363779b618b8319e9dcee09533646 100644
--- a/openair1/SIMULATION/NR_PHY/dlsim.c
+++ b/openair1/SIMULATION/NR_PHY/dlsim.c
@@ -228,13 +228,38 @@ void nr_dlsim_preprocessor(module_id_t module_id,
       sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
   sched_ctrl->cce_index = 0;
 
-  sched_ctrl->rbStart = g_rbStart;
-  sched_ctrl->rbSize = g_rbSize;
-  sched_ctrl->mcs = g_mcsIndex;
-  sched_ctrl->time_domain_allocation = 2;
-  sched_ctrl->mcsTableIdx = g_mcsTableIdx;
+  NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
+  const NR_ServingCellConfigCommon_t *scc = RC.nrmac[0]->common_channels[0].ServingCellConfigCommon;
+  nr_set_pdsch_semi_static(scc,
+                           UE_info->secondaryCellGroup[0],
+                           sched_ctrl->active_bwp,
+                           /* tda = */ 2,
+                           /* num_dmrs_cdm_grps_no_data = */ 1,
+                           ps);
+
+  NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
+  sched_pdsch->rbStart = g_rbStart;
+  sched_pdsch->rbSize = g_rbSize;
+  sched_pdsch->mcs = g_mcsIndex;
+  /* the following might override the table that is mandated by RRC
+   * configuration */
+  ps->mcsTableIdx = g_mcsTableIdx;
+
+  sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx);
+  sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx);
+  sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
+                                        sched_pdsch->R,
+                                        sched_pdsch->rbSize,
+                                        ps->nrOfSymbols,
+                                        ps->N_PRB_DMRS * ps->N_DMRS_SLOT,
+                                        0 /* N_PRB_oh, 0 for initialBWP */,
+                                        0 /* tb_scaling */,
+                                        1 /* nrOfLayers */)
+                         >> 3;
+
   /* the simulator assumes the HARQ PID is equal to the slot number */
-  sched_ctrl->dl_harq_pid = slot;
+  sched_pdsch->dl_harq_pid = slot;
+
   /* The scheduler uses lists to track whether a HARQ process is
    * free/busy/awaiting retransmission, and updates the HARQ process states.
    * However, in the simulation, we never get ack or nack for any HARQ process,
@@ -247,11 +272,10 @@ void nr_dlsim_preprocessor(module_id_t module_id,
   else
     add_front_nr_list(&sched_ctrl->retrans_dl_harq, slot);   // ... make PID retransmission
   sched_ctrl->harq_processes[slot].is_waiting = false;
-  AssertFatal(sched_ctrl->rbStart >= 0, "invalid rbStart %d\n", sched_ctrl->rbStart);
-  AssertFatal(sched_ctrl->rbSize > 0, "invalid rbSize %d\n", sched_ctrl->rbSize);
-  AssertFatal(sched_ctrl->mcs >= 0, "invalid sched_ctrl->mcs %d\n", sched_ctrl->mcs);
-  AssertFatal(sched_ctrl->mcsTableIdx >= 0 && sched_ctrl->mcsTableIdx <= 2, "invalid sched_ctrl->mcsTableIdx %d\n", sched_ctrl->mcsTableIdx);
-  sched_ctrl->numDmrsCdmGrpsNoData = 1;
+  AssertFatal(sched_pdsch->rbStart >= 0, "invalid rbStart %d\n", sched_pdsch->rbStart);
+  AssertFatal(sched_pdsch->rbSize > 0, "invalid rbSize %d\n", sched_pdsch->rbSize);
+  AssertFatal(sched_pdsch->mcs >= 0, "invalid mcs %d\n", sched_pdsch->mcs);
+  AssertFatal(ps->mcsTableIdx >= 0 && ps->mcsTableIdx <= 2, "invalid mcsTableIdx %d\n", ps->mcsTableIdx);
 }
 
 
@@ -626,7 +650,6 @@ int main(int argc, char **argv)
     RC.nb_nr_mac_CC[i] = 1;
   mac_top_init_gNB();
   gNB_mac = RC.nrmac[0];
-  gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
   gNB_RRC_INST rrc;
   memset((void*)&rrc,0,sizeof(rrc));
 
@@ -714,6 +737,9 @@ int main(int argc, char **argv)
   rrc_mac_config_req_gNB(0,0,n_tx,1,pusch_tgt_snrx10,pucch_tgt_snrx10,scc,0,0,NULL);
   // UE dedicated configuration
   rrc_mac_config_req_gNB(0,0,n_tx,1,pusch_tgt_snrx10,pucch_tgt_snrx10,NULL,1,secondaryCellGroup->spCellConfig->reconfigurationWithSync->newUE_Identity,secondaryCellGroup);
+  // reset preprocessor to the one of DLSIM after it has been set during
+  // rrc_mac_config_req_gNB
+  gNB_mac->pre_processor_dl = nr_dlsim_preprocessor;
   phy_init_nr_gNB(gNB,0,0);
   N_RB_DL = gNB->frame_parms.N_RB_DL;
   NR_UE_info_t *UE_info = &RC.nrmac[0]->UE_info;
diff --git a/openair1/SIMULATION/NR_PHY/pbchsim.c b/openair1/SIMULATION/NR_PHY/pbchsim.c
index a3c25011970097f68483b98f2f24e96ff54de5a0..276daee337dab99fd7bc68e96f77937e4c5b33a1 100644
--- a/openair1/SIMULATION/NR_PHY/pbchsim.c
+++ b/openair1/SIMULATION/NR_PHY/pbchsim.c
@@ -66,6 +66,7 @@ uint8_t const nr_rv_round_map[4] = {0, 2, 1, 3};
 uint8_t const nr_rv_round_map_ue[4] = {0, 2, 1, 3};
 
 uint64_t get_softmodem_optmask(void) {return 0;}
+softmodem_params_t *get_softmodem_params(void) {return 0;}
 
 void init_downlink_harq_status(NR_DL_UE_HARQ_t *dl_harq) {}
 
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
index 381dce11b2cddce03c9633c17add5dc24d3ad7e6..37bf8fdcb6b7f39544f15dede15129d732794364 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac.h
@@ -148,10 +148,10 @@ typedef struct {
 // single Entry PHR MAC CE
 // TS 38.321 ch. 6.1.3.8
 typedef struct {
-  uint8_t PH: 6;
-  uint8_t R1: 2;
-  uint8_t PCMAX: 6;
-  uint8_t R2: 6;
+  uint8_t PH: 6;    // octet 1 [5:0]
+  uint8_t R1: 2;    // octet 1 [7:6]
+  uint8_t PCMAX: 6; // octet 2 [5:0]
+  uint8_t R2: 2;    // octet 2 [7:6]
 } __attribute__ ((__packed__)) NR_SINGLE_ENTRY_PHR_MAC_CE;
 
 
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index 3e299d291e012f2c7f94efcfda47ac13b2058003..df2fdb3e3fb953e69ebadf3eada10fcfb4221b58 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -374,6 +374,8 @@ typedef struct {
   NR_SearchSpace_t *search_space_zero;
   NR_ControlResourceSet_t *coreset0;
 
+  dci_pdu_rel15_t def_dci_pdu_rel15[8];
+
 } NR_UE_MAC_INST_t;
 
 typedef enum seach_space_mask_e {
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
index 11edc6c20d26ef544dbc7e8bef284505dd88dfcb..64c8978ed02784eeb48ff450c6324925834e0d2c 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_dci_configuration.c
@@ -49,8 +49,6 @@
 
 // #define DEBUG_DCI
 
-dci_pdu_rel15_t *def_dci_pdu_rel15;
-
 void fill_dci_search_candidates(NR_SearchSpace_t *ss,fapi_nr_dl_config_dci_dl_pdu_rel15_t *rel15) {
 
   LOG_D(MAC,"Filling search candidates for DCI\n");
@@ -72,7 +70,6 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t
   uint16_t monitoringSymbolsWithinSlot = 0;
   uint8_t coreset_id = 1;
   int sps = 0;
-  def_dci_pdu_rel15 = calloc(1,2*sizeof(dci_pdu_rel15_t));
   AssertFatal(mac->scc != NULL, "scc is null\n");
   NR_BWP_Id_t bwp_id = mac->DL_BWP_Id;
   NR_ServingCellConfigCommon_t *scc = mac->scc;
@@ -135,7 +132,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t
     rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
     rel15->SubcarrierSpacing = bwp_Common->genericParameters.subcarrierSpacing;
     for (int i = 0; i < rel15->num_dci_options; i++) {
-      rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15+i, rel15->dci_format_options[i], NR_RNTI_C, rel15->BWPSize, bwp_id);
+      rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[i]], rel15->dci_format_options[i], NR_RNTI_C, rel15->BWPSize, bwp_id);
     }
     break;
     case NR_RNTI_RA:
@@ -146,7 +143,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t
     rel15->BWPSize = NRRIV2BW(initialDownlinkBWP->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
     rel15->BWPStart = NRRIV2PRBOFFSET(bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE); //NRRIV2PRBOFFSET(initialDownlinkBWP->genericParameters.locationAndBandwidth, 275);
     rel15->SubcarrierSpacing = initialDownlinkBWP->genericParameters.subcarrierSpacing;
-    rel15->dci_length_options[0] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format_options[0], NR_RNTI_RA, rel15->BWPSize, bwp_id);
+    rel15->dci_length_options[0] = nr_dci_size(scc, mac->scg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[0]], rel15->dci_format_options[0], NR_RNTI_RA, rel15->BWPSize, bwp_id);
     break;
     case NR_RNTI_P:
     break;
@@ -169,7 +166,7 @@ void config_dci_pdu(NR_UE_MAC_INST_t *mac, fapi_nr_dl_config_dci_dl_pdu_rel15_t
       rel15->SubcarrierSpacing = mac->mib->subCarrierSpacingCommon;
 
       for (int i = 0; i < rel15->num_dci_options; i++) {
-        rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, def_dci_pdu_rel15, rel15->dci_format_options[i], NR_RNTI_SI, rel15->BWPSize, 0);
+        rel15->dci_length_options[i] = nr_dci_size(scc, mac->scg, &mac->def_dci_pdu_rel15[rel15->dci_format_options[i]], rel15->dci_format_options[i], NR_RNTI_SI, rel15->BWPSize, 0);
       }
     break;
     case NR_RNTI_SFI:
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index cfcaac6c4bd90044b924b521f4c8d846ee2d8103..4d9a6731a2ba14b51590addb170138bdb66e9500 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -449,9 +449,9 @@ int nr_ue_process_dci_indication_pdu(module_id_t module_id,int cc_id, int gNB_in
   LOG_D(MAC,"Received dci indication (rnti %x,dci format %d,n_CCE %d,payloadSize %d,payload %llx)\n",
 	dci->rnti,dci->dci_format,dci->n_CCE,dci->payloadSize,*(unsigned long long*)dci->payloadBits);
 
-  if (nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, (uint64_t *)dci->payloadBits, def_dci_pdu_rel15))
+  if (nr_extract_dci_info(mac, dci->dci_format, dci->payloadSize, dci->rnti, (uint64_t *)dci->payloadBits, &mac->def_dci_pdu_rel15[dci->dci_format]))
     return -1;
-  return (nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, def_dci_pdu_rel15, dci->rnti, dci->dci_format));
+  return (nr_ue_process_dci(module_id, cc_id, gNB_index, frame, slot, &mac->def_dci_pdu_rel15[dci->dci_format], dci->rnti, dci->dci_format));
 }
 
 int8_t nr_ue_process_dci(module_id_t module_id, int cc_id, uint8_t gNB_index, frame_t frame, int slot, dci_pdu_rel15_t *dci, uint16_t rnti, uint8_t dci_format){
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
index 844ee95d3249583e38906c7d107452d85760d657..cbf14a89adb6a1e9fdcbed75383677ebe75c1e3e 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_scheduler.c
@@ -913,10 +913,9 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
               //and block this traffic from being forwarded to the upper layers at the gNB
               LOG_D(PHY, "In %s: Random data to be transmitted: TBS_bytes %d \n", __FUNCTION__, TBS_bytes);
 
-              //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
-              //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
-              //have a valid LCID (nr_process_mac_pdu function)
-              ulsch_input_buffer[0] = 0x31;
+              // Make the first byte padding so that gNB ignores the PHY random
+              // data in the TB for the PHY at the MAC layer
+              ulsch_input_buffer[0] = UL_SCH_LCID_PADDING;
 
               for (int i = 1; i < TBS_bytes; i++) {
                 ulsch_input_buffer[i] = (unsigned char) rand();
diff --git a/openair2/LAYER2/NR_MAC_gNB/config.c b/openair2/LAYER2/NR_MAC_gNB/config.c
index caa56bdff9118ea1c93e4542e0253a906782c610..a67a71d0be0fa2c19a3979ad2622d17171af8564 100644
--- a/openair2/LAYER2/NR_MAC_gNB/config.c
+++ b/openair2/LAYER2/NR_MAC_gNB/config.c
@@ -405,12 +405,53 @@ int rrc_mac_config_req_gNB(module_id_t Mod_idP,
 
     find_SSB_and_RO_available(Mod_idP);
 
+    const NR_TDD_UL_DL_Pattern_t *tdd = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
+    const int nr_mix_slots = tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0;
+    const int nr_slots_period = tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots;
+    const int nr_dlmix_slots = tdd->nrofDownlinkSlots + (tdd->nrofDownlinkSymbols != 0);
+    const int nr_ulstart_slot = tdd->nrofDownlinkSlots + (tdd->nrofUplinkSymbols == 0);
+    for (int slot = 0; slot < n; ++slot) {
+      /* FIXME: it seems there is a problem with slot 0/10/slots right after UL:
+       * we just get retransmissions. Thus, do not schedule such slots in DL */
+      if (slot % nr_slots_period != 0)
+        RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] |= ((slot % nr_slots_period) < nr_dlmix_slots) << (slot % 64);
+      RC.nrmac[Mod_idP]->ulsch_slot_bitmap[slot / 64] |= ((slot % nr_slots_period) >= nr_ulstart_slot) << (slot % 64);
+      LOG_D(MAC,
+            "slot %d DL %d UL %d\n",
+            slot,
+            (RC.nrmac[Mod_idP]->dlsch_slot_bitmap[slot / 64] & (1 << (slot % 64))) != 0,
+            (RC.nrmac[Mod_idP]->ulsch_slot_bitmap[slot / 64] & (1 << (slot % 64))) != 0);
+    }
+
+    if (get_softmodem_params()->phy_test) {
+      RC.nrmac[Mod_idP]->pre_processor_dl = nr_preprocessor_phytest;
+      RC.nrmac[Mod_idP]->pre_processor_ul = nr_ul_preprocessor_phytest;
+    } else {
+      RC.nrmac[Mod_idP]->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(Mod_idP, 0);
+      RC.nrmac[Mod_idP]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(Mod_idP, 0);
+    }
   }
   
   if (secondaryCellGroup) {
 
     RC.nrmac[Mod_idP]->secondaryCellGroupCommon = secondaryCellGroup;
 
+    const NR_ServingCellConfig_t *servingCellConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated;
+    const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList;
+    AssertFatal(bwpList->list.count > 0, "downlinkBWP_ToAddModList has no BWPs!\n");
+    for (int i = 0; i < bwpList->list.count; ++i) {
+      const NR_BWP_Downlink_t *bwp = bwpList->list.array[i];
+      calculate_preferred_dl_tda(Mod_idP, bwp);
+    }
+
+    const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList =
+        servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList;
+    AssertFatal(ubwpList->list.count > 0, "downlinkBWP_ToAddModList no BWPs!\n");
+    for (int i = 0; i < ubwpList->list.count; ++i) {
+      const NR_BWP_Uplink_t *ubwp = ubwpList->list.array[i];
+      calculate_preferred_ul_tda(Mod_idP, ubwp);
+    }
+
     NR_UE_info_t *UE_info = &RC.nrmac[Mod_idP]->UE_info;
     if (add_ue == 1 && get_softmodem_params()->phy_test) {
       const int UE_id = add_new_nr_ue(Mod_idP, rnti, secondaryCellGroup);
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
index 584648c67f84e81d954c94ed4213b67759df4ba4..8d1e899fcb03696b41082900f831e917ab1acf98 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler.c
@@ -53,6 +53,7 @@
 
 #include "executables/softmodem-common.h"
 #include "nfapi/oai_integration/vendor_ext.h"
+#include "executables/nr-softmodem.h"
 
 uint16_t nr_pdcch_order_table[6] = { 31, 31, 511, 2047, 2047, 8191 };
 
@@ -65,7 +66,13 @@ void dump_mac_stats(gNB_MAC_INST *gNB)
   NR_UE_info_t *UE_info = &gNB->UE_info;
   int num = 1;
   for (int UE_id = UE_info->list.head; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
-    LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d)\n", UE_id, UE_info->rnti[UE_id], num++, UE_info->num_UEs);
+    LOG_I(MAC, "UE ID %d RNTI %04x (%d/%d) PH %d dB PCMAX %d dBm\n",
+          UE_id,
+          UE_info->rnti[UE_id],
+          num++,
+          UE_info->num_UEs,
+          UE_info->UE_sched_ctrl[UE_id].ph,
+          UE_info->UE_sched_ctrl[UE_id].pcmax);
     NR_mac_stats_t *stats = &UE_info->mac_stats[UE_id];
     const int avg_rsrp = stats->num_rsrp_meas > 0 ? stats->cumul_rsrp / stats->num_rsrp_meas : 0;
     LOG_I(MAC, "UE %d: dlsch_rounds %d/%d/%d/%d, dlsch_errors %d, average RSRP %d (%d meas)\n",
@@ -76,10 +83,15 @@ void dump_mac_stats(gNB_MAC_INST *gNB)
     stats->num_rsrp_meas = 0;
     stats->cumul_rsrp = 0 ;
     LOG_I(MAC, "UE %d: dlsch_total_bytes %d\n", UE_id, stats->dlsch_total_bytes);
-    LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d\n",
+    const NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+    LOG_I(MAC, "UE %d: ulsch_rounds %d/%d/%d/%d, ulsch_errors %d, PUSCH SNR %2.1f dB, PUCCH SNR %2.1f dB, noise rssi %2.1f dB\n",
           UE_id,
           stats->ulsch_rounds[0], stats->ulsch_rounds[1],
-          stats->ulsch_rounds[2], stats->ulsch_rounds[3], stats->ulsch_errors);
+          stats->ulsch_rounds[2], stats->ulsch_rounds[3],
+          stats->ulsch_errors,
+          (float) sched_ctrl->pusch_snrx10 / 10,
+          (float) sched_ctrl->pucch_snrx10 / 10,
+          (float) (sched_ctrl->raw_rssi - 1280) / 10);
     LOG_I(MAC,
           "UE %d: ulsch_total_bytes_scheduled %d, ulsch_total_bytes_received %d\n",
           UE_id,
@@ -312,51 +324,11 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
   protocol_ctxt_t   ctxt;
   PROTOCOL_CTXT_SET_BY_MODULE_ID(&ctxt, module_idP, ENB_FLAG_YES, NOT_A_RNTI, frame, slot,module_idP);
  
-  int nb_periods_per_frame;
-
   const int bwp_id = 1;
 
   gNB_MAC_INST *gNB = RC.nrmac[module_idP];
   NR_COMMON_channels_t *cc = gNB->common_channels;
   NR_ServingCellConfigCommon_t        *scc     = cc->ServingCellConfigCommon;
-  NR_TDD_UL_DL_Pattern_t *tdd_pattern = &scc->tdd_UL_DL_ConfigurationCommon->pattern1;
-
-  switch(scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity) {
-    case 0:
-      nb_periods_per_frame = 20; // 10ms/0p5ms
-      break;
-
-    case 1:
-      nb_periods_per_frame = 16; // 10ms/0p625ms
-      break;
-
-    case 2:
-      nb_periods_per_frame = 10; // 10ms/1ms
-      break;
-
-    case 3:
-      nb_periods_per_frame = 8; // 10ms/1p25ms
-      break;
-
-    case 4:
-      nb_periods_per_frame = 5; // 10ms/2ms
-      break;
-
-    case 5:
-      nb_periods_per_frame = 4; // 10ms/2p5ms
-      break;
-
-    case 6:
-      nb_periods_per_frame = 2; // 10ms/5ms
-      break;
-
-    case 7:
-      nb_periods_per_frame = 1; // 10ms/10ms
-      break;
-
-    default:
-      AssertFatal(1==0,"Undefined tdd period %ld\n", scc->tdd_UL_DL_ConfigurationCommon->pattern1.dl_UL_TransmissionPeriodicity);
-  }
 
   if (slot==0 && (*scc->downlinkConfigCommon->frequencyInfoDL->frequencyBandList.list.array[0]>=257)) {
     // re-initialization of tdd_beam_association at beginning of frame (only for FR2)
@@ -364,10 +336,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
       gNB->tdd_beam_association[i] = -1;
   }
 
-  int num_slots_per_tdd = (nr_slots_per_frame[*scc->ssbSubcarrierSpacing])/nb_periods_per_frame;
-
-  const int nr_ulmix_slots = tdd_pattern->nrofUplinkSlots + (tdd_pattern->nrofUplinkSymbols!=0);
-
   start_meas(&RC.nrmac[module_idP]->eNB_scheduler);
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_gNB_DLSCH_ULSCH_SCHEDULER,VCD_FUNCTION_IN);
 
@@ -381,17 +349,6 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
     nr_rrc_trigger(&ctxt, 0 /*CC_id*/, frame, slot >> *scc->ssbSubcarrierSpacing);
   }
 
-#define BIT(x) (1 << (x))
-  const uint64_t dlsch_in_slot_bitmap = BIT( 1) | BIT( 2) | BIT( 3) | BIT( 4) | BIT( 5) | BIT( 6)
-                                      | BIT(11) | BIT(12) | BIT(13) | BIT(14) | BIT(15) | BIT(16);
-
-  uint8_t prach_config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
-  uint64_t ulsch_in_slot_bitmap;
-  if (prach_config_index==4) //this is the PRACH config used in the Benetel RRU. TODO: make this generic for any PRACH config. 
-    ulsch_in_slot_bitmap = BIT( 8) | BIT( 9);
-  else
-    ulsch_in_slot_bitmap = BIT( 8) | BIT(18);
-
   memset(RC.nrmac[module_idP]->cce_list[bwp_id][0],0,MAX_NUM_CCE*sizeof(int)); // coreset0
   memset(RC.nrmac[module_idP]->cce_list[bwp_id][1],0,MAX_NUM_CCE*sizeof(int)); // coresetid 1
   NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
@@ -452,14 +409,10 @@ void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
   }
 
   // This schedules the DCI for Uplink and subsequently PUSCH
-  {
-    nr_schedule_ulsch(module_idP, frame, slot, num_slots_per_tdd, nr_ulmix_slots, ulsch_in_slot_bitmap);
-  }
+  nr_schedule_ulsch(module_idP, frame, slot);
 
   // This schedules the DCI for Downlink and PDSCH
-  if (is_xlsch_in_slot(dlsch_in_slot_bitmap, slot))
-    nr_schedule_ue_spec(module_idP, frame, slot);
-
+  nr_schedule_ue_spec(module_idP, frame, slot);
 
   nr_schedule_pucch(module_idP, frame, slot);
 
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index bc297225aff6f95e56e04d95fcde11bcd44528aa..bc25279783d93630082a1d91dfe59d8e954db71e 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -377,6 +377,16 @@ void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP
           }
         }
       }
+
+      // block resources in vrb_map_UL
+      const NR_RACH_ConfigGeneric_t *rach_ConfigGeneric =
+          &scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric;
+      const uint8_t mu_pusch =
+          scc->uplinkConfigCommon->frequencyInfoUL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
+      const int16_t N_RA_RB = get_N_RA_RB(cfg->prach_config.prach_sub_c_spacing.value, mu_pusch);
+      uint16_t *vrb_map_UL = &cc->vrb_map_UL[slotP * MAX_BWP_SIZE];
+      for (int i = 0; i < N_RA_RB * fdm; ++i)
+        vrb_map_UL[rach_ConfigGeneric->msg1_FrequencyStart + i] = 0xff; // all symbols
     }
   }
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
index 0ceff015e718625af5edda6562366c82d327d6e8..3c90bf709b0334fb6288068415e57aea67ec981b 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_bch.c
@@ -295,9 +295,9 @@ void schedule_control_sib1(module_id_t module_id,
   }
   gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_AdditionalPosition = NULL;
 
-  gNB_mac->sched_ctrlCommon->time_domain_allocation = time_domain_allocation;
-  gNB_mac->sched_ctrlCommon->mcsTableIdx = mcsTableIdx;
-  gNB_mac->sched_ctrlCommon->mcs = mcs;
+  gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation = time_domain_allocation;
+  gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx = mcsTableIdx;
+  gNB_mac->sched_ctrlCommon->sched_pdsch.mcs = mcs;
   gNB_mac->sched_ctrlCommon->num_total_bytes = num_total_bytes;
 
   uint8_t nr_of_candidates;
@@ -318,18 +318,19 @@ void schedule_control_sib1(module_id_t module_id,
 
   // Calculate number of symbols
   struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
-  const int startSymbolAndLength = tdaList->list.array[gNB_mac->sched_ctrlCommon->time_domain_allocation]->startSymbolAndLength;
+  const int startSymbolAndLength =
+      tdaList->list.array[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation]->startSymbolAndLength;
   int startSymbolIndex, nrOfSymbols;
   SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
 
   if (nrOfSymbols == 2) {
-    gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData = 1;
+    gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 1;
   } else {
-    gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData = 2;
+    gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData = 2;
   }
 
   // Calculate number of PRB_DMRS
-  uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6;
+  uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 6;
   uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, startSymbolIndex+nrOfSymbols);
   uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos);
 
@@ -337,22 +338,24 @@ void schedule_control_sib1(module_id_t module_id,
   uint32_t TBS = 0;
   do {
     rbSize++;
-    TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
-                         nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
+    TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
+                                      gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
+                         nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
+                                             gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
                          rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0, 0,1) >> 3;
   } while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && TBS < gNB_mac->sched_ctrlCommon->num_total_bytes);
 
-  gNB_mac->sched_ctrlCommon->rbSize = rbSize;
-  gNB_mac->sched_ctrlCommon->rbStart = 0;
+  gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize = rbSize;
+  gNB_mac->sched_ctrlCommon->sched_pdsch.rbStart = 0;
 
   LOG_D(MAC,"SLIV = %i\n", startSymbolAndLength);
   LOG_D(MAC,"startSymbolIndex = %i\n", startSymbolIndex);
   LOG_D(MAC,"nrOfSymbols = %i\n", nrOfSymbols);
-  LOG_D(MAC,"rbSize = %i\n", gNB_mac->sched_ctrlCommon->rbSize);
+  LOG_D(MAC, "rbSize = %i\n", gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize);
   LOG_D(MAC,"TBS = %i\n", TBS);
 
   // Mark the corresponding RBs as used
-  for (int rb = 0; rb < gNB_mac->sched_ctrlCommon->rbSize; rb++) {
+  for (int rb = 0; rb < gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize; rb++) {
     vrb_map[rb + rbStart] = 1;
   }
 }
@@ -405,9 +408,9 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
   }
 
   pdsch_pdu_rel15->NrOfCodewords = 1;
-  pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs,0);
+  pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs, 0);
   pdsch_pdu_rel15->qamModOrder[0] = 2;
-  pdsch_pdu_rel15->mcsIndex[0] = gNB_mac->sched_ctrlCommon->mcs;
+  pdsch_pdu_rel15->mcsIndex[0] = gNB_mac->sched_ctrlCommon->sched_pdsch.mcs;
   pdsch_pdu_rel15->mcsTable[0] = 0;
   pdsch_pdu_rel15->rvIndex[0] = nr_rv_round_map[0];
   pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
@@ -417,15 +420,16 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
   pdsch_pdu_rel15->dmrsConfigType = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1;
   pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
   pdsch_pdu_rel15->SCID = 0;
-  pdsch_pdu_rel15->numDmrsCdmGrpsNoData = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData;
+  pdsch_pdu_rel15->numDmrsCdmGrpsNoData = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData;
   pdsch_pdu_rel15->dmrsPorts = 1;
   pdsch_pdu_rel15->resourceAlloc = 1;
-  pdsch_pdu_rel15->rbStart = gNB_mac->sched_ctrlCommon->rbStart;
-  pdsch_pdu_rel15->rbSize = gNB_mac->sched_ctrlCommon->rbSize;
+  pdsch_pdu_rel15->rbStart = gNB_mac->sched_ctrlCommon->sched_pdsch.rbStart;
+  pdsch_pdu_rel15->rbSize = gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize;
   pdsch_pdu_rel15->VRBtoPRBMapping = 0;
-  pdsch_pdu_rel15->qamModOrder[0] = nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx);
+  pdsch_pdu_rel15->qamModOrder[0] = nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
+                                                 gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx);
   pdsch_pdu_rel15->TBSize[0] = TBS;
-  pdsch_pdu_rel15->mcsTable[0] = gNB_mac->sched_ctrlCommon->mcsTableIdx;
+  pdsch_pdu_rel15->mcsTable[0] = gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx;
   pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
   pdsch_pdu_rel15->NrOfSymbols = NrOfSymbols;
 
@@ -454,8 +458,8 @@ void nr_fill_nfapi_dl_sib1_pdu(int Mod_idP,
   dci_payload.frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(
       pdsch_pdu_rel15->rbSize, pdsch_pdu_rel15->rbStart, gNB_mac->type0_PDCCH_CSS_config.num_rbs);
 
-  dci_payload.time_domain_assignment.val = gNB_mac->sched_ctrlCommon->time_domain_allocation;
-  dci_payload.mcs = gNB_mac->sched_ctrlCommon->mcs;
+  dci_payload.time_domain_assignment.val = gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation;
+  dci_payload.mcs = gNB_mac->sched_ctrlCommon->sched_pdsch.mcs;
   dci_payload.rv = pdsch_pdu_rel15->rvIndex[0];
   dci_payload.harq_pid = 0;
   dci_payload.ndi = 0;
@@ -525,17 +529,26 @@ void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t slotP)
     // Calculate number of symbols
     int startSymbolIndex, nrOfSymbols;
     struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList = gNB_mac->sched_ctrlCommon->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
-    const int startSymbolAndLength = tdaList->list.array[gNB_mac->sched_ctrlCommon->time_domain_allocation]->startSymbolAndLength;
+    const int startSymbolAndLength =
+        tdaList->list.array[gNB_mac->sched_ctrlCommon->pdsch_semi_static.time_domain_allocation]->startSymbolAndLength;
     SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
 
     // Calculate number of PRB_DMRS
-    uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->numDmrsCdmGrpsNoData * 6;
+    uint8_t N_PRB_DMRS = gNB_mac->sched_ctrlCommon->pdsch_semi_static.numDmrsCdmGrpsNoData * 6;
     uint16_t dlDmrsSymbPos = fill_dmrs_mask(gNB_mac->sched_ctrlCommon->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup, gNB_mac->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position, startSymbolIndex+nrOfSymbols);
     uint16_t dmrs_length = get_num_dmrs(dlDmrsSymbPos);
 
-    const uint32_t TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
-                                        nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->mcs, gNB_mac->sched_ctrlCommon->mcsTableIdx),
-                                        gNB_mac->sched_ctrlCommon->rbSize, nrOfSymbols, N_PRB_DMRS * dmrs_length,0 ,0 ,1 ) >> 3;
+    const uint32_t TBS = nr_compute_tbs(nr_get_Qm_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
+                                                     gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
+                                        nr_get_code_rate_dl(gNB_mac->sched_ctrlCommon->sched_pdsch.mcs,
+                                                            gNB_mac->sched_ctrlCommon->pdsch_semi_static.mcsTableIdx),
+                                        gNB_mac->sched_ctrlCommon->sched_pdsch.rbSize,
+                                        nrOfSymbols,
+                                        N_PRB_DMRS * dmrs_length,
+                                        0,
+                                        0,
+                                        1)
+                         >> 3;
 
     nfapi_nr_dl_tti_request_body_t *dl_req = &gNB_mac->DL_req[CC_id].dl_tti_request_body;
     nr_fill_nfapi_dl_sib1_pdu(module_idP, dl_req, TBS, startSymbolIndex, nrOfSymbols);
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index 30a89cce77cf219bde280151b122ce0beddf4ef3..9cb07255b8d125da53e7903d42cc3e52caa5db74 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -56,6 +56,82 @@
 #define WORD 32
 //#define SIZE_OF_POINTER sizeof (void *)
 
+void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp)
+{
+  gNB_MAC_INST *nrmac = RC.nrmac[module_id];
+  const int bwp_id = bwp->bwp_Id;
+  if (nrmac->preferred_dl_tda[bwp_id])
+    return;
+
+  /* there is a mixed slot only when in TDD */
+  NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon;
+  const NR_TDD_UL_DL_Pattern_t *tdd =
+      scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
+  const int symb_dlMixed = tdd ? (1 << tdd->nrofDownlinkSymbols) - 1 : 0;
+
+  const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
+  const NR_SearchSpace_t *search_space = get_searchspace(bwp, target_ss);
+  const NR_ControlResourceSet_t *coreset = get_coreset(bwp, search_space, 1 /* dedicated */);
+  // get coreset symbol "map"
+  const uint16_t symb_coreset = (1 << coreset->duration) - 1;
+
+  /* check that TDA index 0 fits into DL and does not overlap CORESET */
+  const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList =
+      bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
+  AssertFatal(tdaList->list.count >= 1, "need to have at least one TDA for DL slots\n");
+  const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_DL = tdaList->list.array[0];
+  AssertFatal(!tdaP_DL->k0 || *tdaP_DL->k0 == 0,
+              "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n",
+              *tdaP_DL->k0);
+  int start, len;
+  SLIV2SL(tdaP_DL->startSymbolAndLength, &start, &len);
+  const uint16_t symb_tda = ((1 << len) - 1) << start;
+  // check whether coreset and TDA overlap: then we cannot use it. Note that
+  // here we assume that the coreset is scheduled every slot (which it
+  // currently is) and starting at symbol 0
+  AssertFatal((symb_coreset & symb_tda) == 0, "TDA index 0 for DL overlaps with CORESET\n");
+
+  /* check that TDA index 1 fits into DL part of mixed slot, if it exists */
+  int tdaMi = -1;
+  if (tdaList->list.count > 1) {
+    const NR_PDSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1];
+    AssertFatal(!tdaP_Mi->k0 || *tdaP_Mi->k0 == 0,
+                "TimeDomainAllocation at index 1: non-null k0 (%ld) is not supported by the scheduler\n",
+                *tdaP_Mi->k0);
+    int start, len;
+    SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len);
+    const uint16_t symb_tda = ((1 << start) - 1) << start;
+    // check whether coreset and TDA overlap: then, we cannot use it. Also,
+    // check whether TDA is entirely within mixed slot DL. Note that
+    // here we assume that the coreset is scheduled every slot (which it
+    // currently is)
+    if ((symb_coreset & symb_tda) == 0 && (symb_dlMixed & symb_tda) == symb_tda) {
+      tdaMi = 1;
+    } else {
+      LOG_E(MAC,
+            "TDA index 1 DL overlaps with CORESET or is not entirely in mixed slot (symb_coreset %x symb_dlMixed %x symb_tda %x), won't schedule DL mixed slot\n",
+            symb_coreset,
+            symb_dlMixed,
+            symb_tda);
+    }
+  }
+
+  const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160};
+  const int n = slots_per_frame[*scc->ssbSubcarrierSpacing];
+  nrmac->preferred_dl_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_dl_tda[bwp_id]));
+
+  const int nr_mix_slots = tdd ? tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0 : 0;
+  const int nr_slots_period = tdd ? tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots : n;
+  for (int i = 0; i < n; ++i) {
+    nrmac->preferred_dl_tda[bwp_id][i] = -1;
+    if (!tdd || i % nr_slots_period < tdd->nrofDownlinkSlots)
+      nrmac->preferred_dl_tda[bwp_id][i] = 0;
+    else if (tdd && nr_mix_slots && i % nr_slots_period == tdd->nrofDownlinkSlots)
+      nrmac->preferred_dl_tda[bwp_id][i] = tdaMi;
+    LOG_I(MAC, "slot %d preferred_dl_tda %d\n", i, nrmac->preferred_dl_tda[bwp_id][i]);
+  }
+}
+
 // Compute and write all MAC CEs and subheaders, and return number of written
 // bytes
 int nr_write_ce_dlsch_pdu(module_id_t module_idP,
@@ -302,35 +378,6 @@ int nr_write_ce_dlsch_pdu(module_id_t module_idP,
   return offset;
 }
 
-int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda) {
-  struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList =
-    bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
-  AssertFatal(tda < tdaList->list.count,
-              "time_domain_allocation %d>=%d\n",
-              tda,
-              tdaList->list.count);
-
-  const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength;
-  int startSymbolIndex, nrOfSymbols;
-  SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
-  return nrOfSymbols;
-}
-
-nfapi_nr_dmrs_type_e getDmrsConfigType(NR_BWP_Downlink_t *bwp) {
-  return bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type == NULL ? 0 : 1;
-}
-
-uint8_t getN_PRB_DMRS(NR_BWP_Downlink_t *bwp, int numDmrsCdmGrpsNoData) {
-  const nfapi_nr_dmrs_type_e dmrsConfigType = getDmrsConfigType(bwp);
-  if (dmrsConfigType == NFAPI_NR_DMRS_TYPE1) {
-    // if no data in dmrs cdm group is 1 only even REs have no data
-    // if no data in dmrs cdm group is 2 both odd and even REs have no data
-    return numDmrsCdmGrpsNoData * 6;
-  } else {
-    return numDmrsCdmGrpsNoData * 4;
-  }
-}
-
 void nr_store_dlsch_buffer(module_id_t module_id,
                            frame_t frame,
                            sub_frame_t slot) {
@@ -365,61 +412,125 @@ void nr_store_dlsch_buffer(module_id_t module_id,
   }
 }
 
-bool allocate_retransmission(module_id_t module_id,
-                             uint8_t *rballoc_mask,
-                             int *n_rb_sched,
-                             int UE_id,
-                             int current_harq_pid){
-  NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[module_id]->UE_info.UE_sched_ctrl[UE_id];
-  NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid];
+bool allocate_dl_retransmission(module_id_t module_id,
+                                frame_t frame,
+                                sub_frame_t slot,
+                                uint8_t *rballoc_mask,
+                                int *n_rb_sched,
+                                int UE_id,
+                                int current_harq_pid)
+{
+  const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels->ServingCellConfigCommon;
+  NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
+  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+  NR_sched_pdsch_t *retInfo = &sched_ctrl->harq_processes[current_harq_pid].sched_pdsch;
   const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
   int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+  const uint8_t num_dmrs_cdm_grps_no_data = 1;
 
-  sched_ctrl->time_domain_allocation = retInfo->time_domain_allocation;
-
-  /* ensure that there is a free place for RB allocation */
   int rbSize = 0;
-  while (rbSize < retInfo->rbSize) {
-    rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
-    rbSize = 0;
-    while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
-    if (rbStart >= bwpSize) {
-      LOG_D(MAC,
-            "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n",
-            UE_id,
-            RC.nrmac[module_id]->UE_info.rnti[UE_id]);
-      return false;
+  const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot];
+  if (tda == retInfo->time_domain_allocation) {
+    /* Check that there are enough resources for retransmission */
+    while (rbSize < retInfo->rbSize) {
+      rbStart += rbSize; /* last iteration rbSize was not enough, skip it */
+      rbSize = 0;
+      while (rbStart < bwpSize && !rballoc_mask[rbStart])
+        rbStart++;
+      if (rbStart >= bwpSize) {
+        LOG_D(MAC, "cannot allocate retransmission for UE %d/RNTI %04x: no resources\n", UE_id, UE_info->rnti[UE_id]);
+        return false;
+      }
+      while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize] && rbSize < retInfo->rbSize)
+        rbSize++;
     }
-    while (rbStart + rbSize < bwpSize
-           && rballoc_mask[rbStart + rbSize]
-           && rbSize < retInfo->rbSize)
+    /* check whether we need to switch the TDA allocation since the last
+     * (re-)transmission */
+    NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
+    if (ps->time_domain_allocation != tda || ps->numDmrsCdmGrpsNoData != num_dmrs_cdm_grps_no_data)
+      nr_set_pdsch_semi_static(
+          scc, UE_info->secondaryCellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps);
+  } else {
+    /* the retransmission will use a different time domain allocation, check
+     * that we have enough resources */
+    while (rbStart < bwpSize && !rballoc_mask[rbStart])
+      rbStart++;
+    while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize])
       rbSize++;
+    NR_pdsch_semi_static_t temp_ps;
+    nr_set_pdsch_semi_static(
+        scc, UE_info->secondaryCellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, &temp_ps);
+    uint32_t new_tbs;
+    uint16_t new_rbSize;
+    bool success = nr_find_nb_rb(retInfo->Qm,
+                                 retInfo->R,
+                                 temp_ps.nrOfSymbols,
+                                 temp_ps.N_PRB_DMRS * temp_ps.N_DMRS_SLOT,
+                                 retInfo->tb_size,
+                                 rbSize,
+                                 &new_tbs,
+                                 &new_rbSize);
+    if (!success || new_tbs != retInfo->tb_size) {
+      LOG_D(MAC, "%s(): new TBsize %d of new TDA does not match old TBS %d\n", __func__, new_tbs, retInfo->tb_size);
+      return false; /* the maximum TBsize we might have is smaller than what we need */
+    }
+    /* we can allocate it. Overwrite the time_domain_allocation, the number
+     * of RBs, and the new TB size. The rest is done below */
+    retInfo->tb_size = new_tbs;
+    retInfo->rbSize = new_rbSize;
+    retInfo->time_domain_allocation = tda;
+    sched_ctrl->pdsch_semi_static = temp_ps;
   }
-  sched_ctrl->rbSize = retInfo->rbSize;
-  sched_ctrl->rbStart = rbStart;
 
-  /* MCS etc: just reuse from previous scheduling opportunity */
-  sched_ctrl->mcsTableIdx = retInfo->mcsTableIdx;
-  sched_ctrl->mcs = retInfo->mcs;
-  sched_ctrl->numDmrsCdmGrpsNoData = retInfo->numDmrsCdmGrpsNoData;
+  /* Find a free CCE */
+  bool freeCCE = find_free_CCE(module_id, slot, UE_id);
+  if (!freeCCE) {
+    LOG_D(MAC, "%4d.%2d could not find CCE for DL DCI retransmission UE %d/RNTI %04x\n",
+          frame, slot, UE_id, UE_info->rnti[UE_id]);
+    return false;
+  }
+
+  /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH
+   * allocation after CCE alloc fail would be more complex) */
+  const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot);
+  if (!alloc) {
+    LOG_D(MAC,
+          "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
+          __func__,
+          UE_id,
+          UE_info->rnti[UE_id],
+          frame,
+          slot);
+    int cid = sched_ctrl->coreset->controlResourceSetId;
+    UE_info->num_pdcch_cand[UE_id][cid]--;
+    int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid];
+    for (int i = 0; i < sched_ctrl->aggregation_level; i++)
+      cce_list[sched_ctrl->cce_index + i] = 0;
+    return false;
+  }
+
+  /* just reuse from previous scheduling opportunity, set new start RB */
+  sched_ctrl->sched_pdsch = *retInfo;
+  sched_ctrl->sched_pdsch.rbStart = rbStart;
 
   /* retransmissions: directly allocate */
-  *n_rb_sched -= sched_ctrl->rbSize;
-  for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
-    rballoc_mask[rb+sched_ctrl->rbStart] = 0;
+  *n_rb_sched -= sched_ctrl->sched_pdsch.rbSize;
+  for (int rb = 0; rb < sched_ctrl->sched_pdsch.rbSize; rb++)
+    rballoc_mask[rb + sched_ctrl->sched_pdsch.rbStart] = 0;
   return true;
 }
 
 float thr_ue[MAX_MOBILES_PER_GNB];
+uint32_t pf_tbs[3][28]; // pre-computed, approximate TBS values for PF coefficient
 
 void pf_dl(module_id_t module_id,
            frame_t frame,
            sub_frame_t slot,
            NR_list_t *UE_list,
+           int max_num_ue,
            int n_rb_sched,
-           uint8_t *rballoc_mask,
-           int max_num_ue) {
-
+           uint8_t *rballoc_mask) {
+  const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels->ServingCellConfigCommon;
   NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
   float coeff_ue[MAX_MOBILES_PER_GNB];
   // UEs that could be scheduled
@@ -429,11 +540,10 @@ void pf_dl(module_id_t module_id,
   /* Loop UE_info->list to check retransmission */
   for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
-    sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, NR_SearchSpace__searchSpaceType_PR_ue_Specific);
-    sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
+    NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
+    NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
     /* get the PID of a HARQ process awaiting retrnasmission, or -1 otherwise */
-    sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
-    const rnti_t rnti = UE_info->rnti[UE_id];
+    sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
 
     /* Calculate Throughput */
     const float a = 0.0005f; // corresponds to 200ms window
@@ -441,33 +551,10 @@ void pf_dl(module_id_t module_id,
     thr_ue[UE_id] = (1 - a) * thr_ue[UE_id] + a * b;
 
     /* retransmission */
-    if (sched_ctrl->dl_harq_pid >= 0) {
-      /* Find a free CCE */
-      bool freeCCE = find_free_CCE(module_id, slot, UE_id);
-      if (!freeCCE){
-        LOG_D(MAC, "%4d.%2d could not find CCE for DL DCI retransmission UE %d/RNTI %04x\n", frame, slot, UE_id, rnti);
-        continue;
-      }
-      /* Find PUCCH occasion: if it fails, undo CCE allocation (undoing PUCCH
-       * allocation after CCE alloc fail would be more complex) */
-      const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot);
-      if (!alloc) {
-        LOG_W(MAC,
-              "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
-              __func__,
-              UE_id,
-              rnti,
-              frame,
-              slot);
-        int cid = sched_ctrl->coreset->controlResourceSetId;
-        UE_info->num_pdcch_cand[UE_id][cid]--;
-        int *cce_list = RC.nrmac[module_id]->cce_list[sched_ctrl->active_bwp->bwp_Id][cid];
-        for (int i = 0; i < sched_ctrl->aggregation_level; i++)
-          cce_list[sched_ctrl->cce_index + i] = 0;
-        return;
-      }
+    if (sched_pdsch->dl_harq_pid >= 0) {
       /* Allocate retransmission */
-      bool r = allocate_retransmission(module_id, rballoc_mask, &n_rb_sched, UE_id, sched_ctrl->dl_harq_pid);
+      bool r = allocate_dl_retransmission(
+          module_id, frame, slot, rballoc_mask, &n_rb_sched, UE_id, sched_pdsch->dl_harq_pid);
       if (!r) {
         LOG_D(MAC, "%4d.%2d retransmission can NOT be allocated\n", frame, slot);
         continue;
@@ -481,23 +568,8 @@ void pf_dl(module_id_t module_id,
         continue;
 
       /* Calculate coeff */
-      sched_ctrl->time_domain_allocation = 2;
-      sched_ctrl->mcsTableIdx = 0;
-      sched_ctrl->mcs = 9;
-      sched_ctrl->numDmrsCdmGrpsNoData = 1;
-      uint8_t N_PRB_DMRS =
-              getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData);
-      int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp,
-                                       sched_ctrl->time_domain_allocation);
-      uint32_t tbs = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
-                                    nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
-                                    1,  // rbSize
-                                    nrOfSymbols,
-                                    N_PRB_DMRS,  // FIXME // This should be multiplied by the
-                                    // number of dmrs symbols
-                                    0 /* N_PRB_oh, 0 for initialBWP */, 0 /* tb_scaling */,
-                                    1 /* nrOfLayers */)
-                     >> 3;
+      sched_pdsch->mcs = 9;
+      uint32_t tbs = pf_tbs[ps->mcsTableIdx][sched_pdsch->mcs];
       coeff_ue[UE_id] = (float) tbs / thr_ue[UE_id];
       LOG_D(MAC,"b %d, thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n",
             b, UE_id, thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]);
@@ -545,7 +617,7 @@ void pf_dl(module_id_t module_id,
     * allocation after CCE alloc fail would be more complex) */
     const bool alloc = nr_acknack_scheduling(module_id, UE_id, frame, slot);
     if (!alloc) {
-      LOG_W(MAC,
+      LOG_D(MAC,
             "%s(): could not find PUCCH for UE %d/%04x@%d.%d\n",
             __func__,
             UE_id,
@@ -560,57 +632,48 @@ void pf_dl(module_id_t module_id,
       return;
     }
 
-    /* Allocate transmission */
-    // Time-domain allocation
-    sched_ctrl->time_domain_allocation = 2;
-
-    // modulation scheme
-    sched_ctrl->mcsTableIdx = 0;
-    sched_ctrl->mcs = 9;
-    sched_ctrl->numDmrsCdmGrpsNoData = 1;
-
     // Freq-demain allocation
     while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
+    uint16_t max_rbSize = 1;
+    while (rbStart + max_rbSize < bwpSize && rballoc_mask[rbStart + max_rbSize])
+      max_rbSize++;
+
+    /* MCS has been set above */
+    const uint8_t num_dmrs_cdm_grps_no_data = 1;
+    const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot];
+    NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
+    NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
+    if (ps->time_domain_allocation != tda || ps->numDmrsCdmGrpsNoData != num_dmrs_cdm_grps_no_data)
+      nr_set_pdsch_semi_static(
+          scc, UE_info->secondaryCellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps);
+    sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx);
+    sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx);
 
-    const uint8_t N_PRB_DMRS =
-        getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData);
-    const int nrOfSymbols = getNrOfSymbols(sched_ctrl->active_bwp,
-        sched_ctrl->time_domain_allocation);
-    const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels->ServingCellConfigCommon;
-    const uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(
-        sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup,
-        scc->dmrs_TypeA_Position,
-        nrOfSymbols);
-
-    int rbSize = 0;
     uint32_t TBS = 0;
+    uint16_t rbSize;
     const int oh = 2 + (sched_ctrl->num_total_bytes >= 256)
                  + 2 * (frame == (sched_ctrl->ta_frame + 10) % 1024);
-    do {
-      rbSize++;
-      TBS = nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
-                           nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
-                           rbSize,
-                           nrOfSymbols,
-                           N_PRB_DMRS * N_DMRS_SLOT,
-                           0 /* N_PRB_oh, 0 for initialBWP */,
-                           0 /* tb_scaling */,
-                           1 /* nrOfLayers */)
-            >> 3;
-    } while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize] && TBS < sched_ctrl->num_total_bytes + oh);
-    sched_ctrl->rbSize = rbSize;
-    sched_ctrl->rbStart = rbStart;
+    nr_find_nb_rb(sched_pdsch->Qm,
+                  sched_pdsch->R,
+                  ps->nrOfSymbols,
+                  ps->N_PRB_DMRS * ps->N_DMRS_SLOT,
+                  sched_ctrl->num_total_bytes + oh,
+                  max_rbSize,
+                  &TBS,
+                  &rbSize);
+    sched_pdsch->rbSize = rbSize;
+    sched_pdsch->rbStart = rbStart;
+    sched_pdsch->tb_size = TBS;
 
     /* transmissions: directly allocate */
-    n_rb_sched -= sched_ctrl->rbSize;
-    for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
-      rballoc_mask[rb+sched_ctrl->rbStart] = 0;
+    n_rb_sched -= sched_pdsch->rbSize;
+    for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
+      rballoc_mask[rb + sched_pdsch->rbStart] = 0;
   }
 }
 
-void nr_simple_dlsch_preprocessor(module_id_t module_id,
-                                  frame_t frame,
-                                  sub_frame_t slot) {
+void nr_fr1_dlsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
+{
   NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
 
   if (UE_info->num_UEs == 0)
@@ -642,15 +705,45 @@ void nr_simple_dlsch_preprocessor(module_id_t module_id,
         frame,
         slot,
         &UE_info->list,
+        2,
         n_rb_sched,
-        rballoc_mask,
-        2);
+        rballoc_mask);
+}
+
+nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(module_id_t module_id, int CC_id)
+{
+  /* in the PF algorithm, we have to use the TBsize to compute the coefficient.
+   * This would include the number of DMRS symbols, which in turn depends on
+   * the time domain allocation. In case we are in a mixed slot, we do not want
+   * to recalculate all these values just, and therefore we provide a look-up
+   * table which should approximately give us the TBsize */
+  for (int mcsTableIdx = 0; mcsTableIdx < 3; ++mcsTableIdx) {
+    for (int mcs = 0; mcs < 29; ++mcs) {
+      if (mcs > 27 && mcsTableIdx == 1)
+        continue;
+      const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx);
+      const uint16_t R = nr_get_code_rate_dl(mcs, mcsTableIdx);
+      pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm,
+                                                R,
+                                                1, /* rbSize */
+                                                10, /* hypothetical number of slots */
+                                                0, /* N_PRB_DMRS * N_DMRS_SLOT */
+                                                0 /* N_PRB_oh, 0 for initialBWP */,
+                                                0 /* tb_scaling */,
+                                                1 /* nrOfLayers */)
+                                 >> 3;
+    }
+  }
+
+  return nr_fr1_dlsch_preprocessor;
 }
 
 void nr_schedule_ue_spec(module_id_t module_id,
                          frame_t frame,
                          sub_frame_t slot) {
   gNB_MAC_INST *gNB_mac = RC.nrmac[module_id];
+  if (!is_xlsch_in_slot(gNB_mac->dlsch_slot_bitmap[slot / 64], slot))
+    return;
 
   /* PREPROCESSOR */
   gNB_mac->pre_processor_dl(module_id, frame, slot);
@@ -664,6 +757,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
   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]) {
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+    NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
     UE_info->mac_stats[UE_id].dlsch_current_bytes = 0;
 
     /* update TA and set ta_apply every 10 frames.
@@ -675,45 +769,23 @@ void nr_schedule_ue_spec(module_id_t module_id,
       LOG_D(MAC, "[UE %d][%d.%d] UL timing alignment procedures: setting flag for Timing Advance command\n", UE_id, frame, slot);
     }
 
-    if (sched_ctrl->rbSize <= 0)
+    if (sched_pdsch->rbSize <= 0)
       continue;
 
     const rnti_t rnti = UE_info->rnti[UE_id];
 
     /* POST processing */
-    struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList =
-      sched_ctrl->active_bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
-    AssertFatal(sched_ctrl->time_domain_allocation < tdaList->list.count,
-                "time_domain_allocation %d>=%d\n",
-                sched_ctrl->time_domain_allocation,
-                tdaList->list.count);
-
-    const int startSymbolAndLength =
-      tdaList->list.array[sched_ctrl->time_domain_allocation]->startSymbolAndLength;
-    int startSymbolIndex, nrOfSymbols;
-    SLIV2SL(startSymbolAndLength, &startSymbolIndex, &nrOfSymbols);
-
-    uint8_t N_PRB_DMRS =
-        getN_PRB_DMRS(sched_ctrl->active_bwp, sched_ctrl->numDmrsCdmGrpsNoData);
-    uint8_t N_DMRS_SLOT = get_num_dmrs_symbols(sched_ctrl->active_bwp->bwp_Dedicated->pdsch_Config->choice.setup,
-                                               RC.nrmac[module_id]->common_channels->ServingCellConfigCommon->dmrs_TypeA_Position ,
-                                               nrOfSymbols);
-    const nfapi_nr_dmrs_type_e dmrsConfigType = getDmrsConfigType(sched_ctrl->active_bwp);
     const int nrOfLayers = 1;
-    const uint16_t R = nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx);
-    const uint8_t Qm = nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx);
-    const uint32_t TBS =
-        nr_compute_tbs(nr_get_Qm_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
-                       nr_get_code_rate_dl(sched_ctrl->mcs, sched_ctrl->mcsTableIdx),
-                       sched_ctrl->rbSize,
-                       nrOfSymbols,
-                       N_PRB_DMRS * N_DMRS_SLOT,
-                       0 /* N_PRB_oh, 0 for initialBWP */,
-                       0 /* tb_scaling */,
-                       nrOfLayers)
-        >> 3;
-
-    int8_t current_harq_pid = sched_ctrl->dl_harq_pid;
+    const uint16_t R = sched_pdsch->R;
+    const uint8_t Qm = sched_pdsch->Qm;
+    const uint32_t TBS = sched_pdsch->tb_size;
+
+    /* pre-computed PDSCH values that only change if time domain
+     * allocation/DMRS parameters change. Updated in the preprocessor through
+     * nr_set_pdsch_semi_static() */
+    NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
+
+    int8_t current_harq_pid = sched_pdsch->dl_harq_pid;
     if (current_harq_pid < 0) {
       /* PP has not selected a specific HARQ Process, get a new one */
       current_harq_pid = sched_ctrl->available_dl_harq.head;
@@ -721,7 +793,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
                   "no free HARQ process available for UE %d\n",
                   UE_id);
       remove_front_nr_list(&sched_ctrl->available_dl_harq);
-      sched_ctrl->dl_harq_pid = current_harq_pid;
+      sched_pdsch->dl_harq_pid = current_harq_pid;
     } else {
       /* PP selected a specific HARQ process. Check whether it will be a new
        * transmission or a retransmission, and remove from the corresponding
@@ -735,20 +807,21 @@ void nr_schedule_ue_spec(module_id_t module_id,
     DevAssert(!harq->is_waiting);
     add_tail_nr_list(&sched_ctrl->feedback_dl_harq, current_harq_pid);
     NR_sched_pucch_t *pucch = &sched_ctrl->sched_pucch[0];
+    harq->feedback_frame = pucch->frame;
     harq->feedback_slot = pucch->ul_slot;
     harq->is_waiting = true;
     UE_info->mac_stats[UE_id].dlsch_rounds[harq->round]++;
 
     LOG_D(MAC,
-          "%4d.%2d RNTI %04x start %d RBs %d startSymbol %d nb_symbsol %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
+          "%4d.%2d RNTI %04x start %3d RBs %3d startSymbol %2d nb_symbol %2d MCS %2d TBS %4d HARQ PID %2d round %d NDI %d\n",
           frame,
           slot,
           rnti,
-          sched_ctrl->rbStart,
-          sched_ctrl->rbSize,
-          startSymbolIndex,
-          nrOfSymbols,
-          sched_ctrl->mcs,
+          sched_pdsch->rbStart,
+          sched_pdsch->rbSize,
+          ps->startSymbolIndex,
+          ps->nrOfSymbols,
+          sched_pdsch->mcs,
           TBS,
           current_harq_pid,
           harq->round,
@@ -804,8 +877,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
     pdsch_pdu->NrOfCodewords = 1;
     pdsch_pdu->targetCodeRate[0] = R;
     pdsch_pdu->qamModOrder[0] = Qm;
-    pdsch_pdu->mcsIndex[0] = sched_ctrl->mcs;
-    pdsch_pdu->mcsTable[0] = sched_ctrl->mcsTableIdx;
+    pdsch_pdu->mcsIndex[0] = sched_pdsch->mcs;
+    pdsch_pdu->mcsTable[0] = ps->mcsTableIdx;
     pdsch_pdu->rvIndex[0] = nr_rv_round_map[harq->round];
     pdsch_pdu->TBSize[0] = TBS;
 
@@ -815,25 +888,22 @@ void nr_schedule_ue_spec(module_id_t module_id,
     pdsch_pdu->refPoint = 0; // Point A
 
     // DMRS
-    pdsch_pdu->dlDmrsSymbPos =
-        fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup,
-                       scc->dmrs_TypeA_Position,
-                       nrOfSymbols);
-    pdsch_pdu->dmrsConfigType = dmrsConfigType;
+    pdsch_pdu->dlDmrsSymbPos = ps->dl_dmrs_symb_pos;
+    pdsch_pdu->dmrsConfigType = ps->dmrsConfigType;
     pdsch_pdu->dlDmrsScramblingId = *scc->physCellId;
     pdsch_pdu->SCID = 0;
-    pdsch_pdu->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
+    pdsch_pdu->numDmrsCdmGrpsNoData = ps->numDmrsCdmGrpsNoData;
     pdsch_pdu->dmrsPorts = 1;
 
     // Pdsch Allocation in frequency domain
     pdsch_pdu->resourceAlloc = 1;
-    pdsch_pdu->rbStart = sched_ctrl->rbStart;
-    pdsch_pdu->rbSize = sched_ctrl->rbSize;
+    pdsch_pdu->rbStart = sched_pdsch->rbStart;
+    pdsch_pdu->rbSize = sched_pdsch->rbSize;
     pdsch_pdu->VRBtoPRBMapping = 1; // non-interleaved, check if this is ok for initialBWP
 
     // Resource Allocation in time domain
-    pdsch_pdu->StartSymbolIndex = startSymbolIndex;
-    pdsch_pdu->NrOfSymbols = nrOfSymbols;
+    pdsch_pdu->StartSymbolIndex = ps->startSymbolIndex;
+    pdsch_pdu->NrOfSymbols = ps->nrOfSymbols;
 
     /* Check and validate PTRS values */
     struct NR_SetupRelease_PTRS_DownlinkConfig *phaseTrackingRS =
@@ -887,8 +957,8 @@ void nr_schedule_ue_spec(module_id_t module_id,
             pdsch_pdu->rbSize,
             pdsch_pdu->rbStart,
             pdsch_pdu->BWPSize);
-    dci_payload.time_domain_assignment.val = sched_ctrl->time_domain_allocation;
-    dci_payload.mcs = sched_ctrl->mcs;
+    dci_payload.time_domain_assignment.val = ps->time_domain_allocation;
+    dci_payload.mcs = sched_pdsch->mcs;
     dci_payload.rv = pdsch_pdu->rvIndex[0];
     dci_payload.harq_pid = current_harq_pid;
     dci_payload.ndi = harq->ndi;
@@ -933,29 +1003,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
           pdcch_pdu->StartSymbolIndex,
           pdcch_pdu->DurationSymbols);
 
-    NR_UE_ret_info_t *retInfo = &sched_ctrl->retInfo[current_harq_pid];
     if (harq->round != 0) { /* retransmission */
-      if (sched_ctrl->rbSize != retInfo->rbSize)
-        LOG_W(MAC,
-              "retransmission uses different rbSize (%d vs. orig %d)\n",
-              sched_ctrl->rbSize,
-              retInfo->rbSize);
-      if (sched_ctrl->time_domain_allocation != retInfo->time_domain_allocation)
-        LOG_W(MAC,
-              "retransmission uses different time_domain_allocation (%d vs. orig %d)\n",
-              sched_ctrl->time_domain_allocation,
-              retInfo->time_domain_allocation);
-      if (sched_ctrl->mcs != retInfo->mcs
-          || sched_ctrl->mcsTableIdx != retInfo->mcsTableIdx
-          || sched_ctrl->numDmrsCdmGrpsNoData != retInfo->numDmrsCdmGrpsNoData)
-        LOG_W(MAC,
-              "retransmission uses different table/MCS/numDmrsCdmGrpsNoData (%d/%d/%d vs. orig %d/%d/%d)\n",
-              sched_ctrl->mcsTableIdx,
-              sched_ctrl->mcs,
-              sched_ctrl->numDmrsCdmGrpsNoData,
-              retInfo->mcsTableIdx,
-              retInfo->mcs,
-              retInfo->numDmrsCdmGrpsNoData);
       /* we do not have to do anything, since we do not require to get data
        * from RLC or encode MAC CEs. The TX_req structure is filled below 
        * or copy data to FAPI structures */
@@ -968,7 +1016,7 @@ void nr_schedule_ue_spec(module_id_t module_id,
             current_harq_pid,
             harq->round,
             harq->ndi);
-      AssertFatal(harq->tb_size == TBS,
+      AssertFatal(harq->sched_pdsch.tb_size == TBS,
                   "UE %d mismatch between scheduled TBS and buffered TB for HARQ PID %d\n",
                   UE_id,
                   current_harq_pid);
@@ -976,7 +1024,6 @@ void nr_schedule_ue_spec(module_id_t module_id,
 
       LOG_D(MAC, "[%s] Initial HARQ transmission in %d.%d\n", __FUNCTION__, frame, slot);
 
-      harq->tb_size = TBS;
       uint8_t *buf = (uint8_t *) harq->tb;
 
       /* first, write all CEs that might be there */
@@ -1084,11 +1131,11 @@ void nr_schedule_ue_spec(module_id_t module_id,
       UE_info->mac_stats[UE_id].dlsch_current_bytes = TBS;
       UE_info->mac_stats[UE_id].lc_bytes_tx[lcid] += dlsch_total_bytes;
 
-      retInfo->rbSize = sched_ctrl->rbSize;
-      retInfo->time_domain_allocation = sched_ctrl->time_domain_allocation;
-      retInfo->mcsTableIdx = sched_ctrl->mcsTableIdx;
-      retInfo->mcs = sched_ctrl->mcs;
-      retInfo->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
+      /* save retransmission information */
+      harq->sched_pdsch = *sched_pdsch;
+      /* save which time allocation has been used, to be used on
+       * retransmissions */
+      harq->sched_pdsch.time_domain_allocation = ps->time_domain_allocation;
 
       // ta command is sent, values are reset
       if (sched_ctrl->ta_apply) {
@@ -1117,6 +1164,6 @@ void nr_schedule_ue_spec(module_id_t module_id,
     gNB_mac->TX_req[CC_id].Slot = slot;
 
     /* mark UE as scheduled */
-    sched_ctrl->rbSize = 0;
+    memset(sched_pdsch, 0, sizeof(*sched_pdsch));
   }
 }
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
index 6487f391b9198bfb489dba0471ba670f53e3fa84..6c4e3398f10fdd254cc06192cf89829d863050b4 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_phytest.c
@@ -254,16 +254,22 @@ void nr_schedule_css_dlsch_phytest(module_id_t   module_idP,
   }
 }
 
+extern int getNrOfSymbols(NR_BWP_Downlink_t *bwp, int tda);
+extern uint8_t getN_PRB_DMRS(NR_BWP_Downlink_t *bwp, int numDmrsCdmGrpsNoData);
+uint32_t target_dl_mcs = 9;
+uint32_t target_dl_bw = 50;
+uint64_t dlsch_slot_bitmap = (1<<1);
 /* schedules whole bandwidth for first user, all the time */
 void nr_preprocessor_phytest(module_id_t module_id,
                              frame_t frame,
                              sub_frame_t slot)
 {
-  if (slot != 1)
+  if (!is_xlsch_in_slot(dlsch_slot_bitmap, slot))
     return;
+  const int CC_id = 0;
+  const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon;
   NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
   const int UE_id = 0;
-  const int CC_id = 0;
   AssertFatal(UE_info->active[UE_id],
               "%s(): expected UE %d to be active\n",
               __func__,
@@ -272,24 +278,25 @@ void nr_preprocessor_phytest(module_id_t module_id,
   /* find largest unallocated chunk */
   const int bwpSize = NRRIV2BW(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
   int rbStart = 0;
-  int tStart = 0;
   int rbSize = 0;
   uint16_t *vrb_map = RC.nrmac[module_id]->common_channels[CC_id].vrb_map;
-  /* find largest unallocated RB region */
-  do {
+  /* loop ensures that we allocate exactly target_dl_bw, or return */
+  while (true) {
     /* advance to first free RB */
-    while (tStart < bwpSize && vrb_map[tStart])
-      tStart++;
-    /* find maximum rbSize at current rbStart */
-    int tSize = 1;
-    while (tStart + tSize < bwpSize && !vrb_map[tStart + tSize])
-      tSize++;
-    if (tSize > rbSize) {
-      rbStart = tStart;
-      rbSize = tSize;
-    }
-    tStart += tSize;
-  } while (tStart < bwpSize);
+    while (rbStart < bwpSize && vrb_map[rbStart])
+      rbStart++;
+    rbSize = 1;
+    /* iterate until we are at target_dl_bw or no available RBs */
+    while (rbStart + rbSize < bwpSize && !vrb_map[rbStart + rbSize] && rbSize < target_dl_bw)
+      rbSize++;
+    /* found target_dl_bw? */
+    if (rbSize == target_dl_bw)
+      break;
+    /* at end and below target_dl_bw? */
+    if (rbStart + rbSize >= bwpSize)
+      return;
+    rbStart += rbSize;
+  }
 
   sched_ctrl->num_total_bytes = 0;
   const int lcid = DL_SCH_LCID_DTCH;
@@ -308,14 +315,10 @@ void nr_preprocessor_phytest(module_id_t module_id,
                                                     0);
   sched_ctrl->num_total_bytes += sched_ctrl->rlc_status[lcid].bytes_in_buffer;
 
-  const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
-  sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
   uint8_t nr_of_candidates;
   find_aggregation_candidates(&sched_ctrl->aggregation_level,
                               &nr_of_candidates,
                               sched_ctrl->search_space);
-  sched_ctrl->coreset = get_coreset(
-      sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
   const int cid = sched_ctrl->coreset->controlResourceSetId;
   const uint16_t Y = UE_info->Y[UE_id][cid][slot];
   const int m = UE_info->num_pdcch_cand[UE_id][cid];
@@ -351,32 +354,42 @@ void nr_preprocessor_phytest(module_id_t module_id,
               "could not find uplink slot for PUCCH (RNTI %04x@%d.%d)!\n",
               rnti, frame, slot);
 
-  sched_ctrl->rbStart = rbStart;
-  sched_ctrl->rbSize = rbSize;
-  sched_ctrl->time_domain_allocation = 2;
-  if (!UE_info->secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table)
-    sched_ctrl->mcsTableIdx = 0;
-  else {
-    if (*UE_info->secondaryCellGroup[UE_id]->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup->mcs_Table == 0)
-      sched_ctrl->mcsTableIdx = 1;
-    else
-      sched_ctrl->mcsTableIdx = 2;
-  }
-  sched_ctrl->mcs = 9;
-  sched_ctrl->numDmrsCdmGrpsNoData = 1;
+  NR_sched_pdsch_t *sched_pdsch = &sched_ctrl->sched_pdsch;
+  NR_pdsch_semi_static_t *ps = &sched_ctrl->pdsch_semi_static;
+  sched_pdsch->rbStart = rbStart;
+  sched_pdsch->rbSize = rbSize;
+  const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_bwp->bwp_Id][slot];
+  const uint8_t num_dmrs_cdm_grps_no_data = 1;
+  if (ps->time_domain_allocation != tda || ps->numDmrsCdmGrpsNoData != num_dmrs_cdm_grps_no_data)
+    nr_set_pdsch_semi_static(
+        scc, UE_info->secondaryCellGroup[UE_id], sched_ctrl->active_bwp, tda, num_dmrs_cdm_grps_no_data, ps);
+
+  sched_pdsch->mcs = target_dl_mcs;
+  sched_pdsch->Qm = nr_get_Qm_dl(sched_pdsch->mcs, ps->mcsTableIdx);
+  sched_pdsch->R = nr_get_code_rate_dl(sched_pdsch->mcs, ps->mcsTableIdx);
+  sched_pdsch->tb_size = nr_compute_tbs(sched_pdsch->Qm,
+                                        sched_pdsch->R,
+                                        sched_pdsch->rbSize,
+                                        ps->nrOfSymbols,
+                                        ps->N_PRB_DMRS * ps->N_DMRS_SLOT,
+                                        0 /* N_PRB_oh, 0 for initialBWP */,
+                                        0 /* tb_scaling */,
+                                        1 /* nrOfLayers */)
+                         >> 3;
+
   /* get the PID of a HARQ process awaiting retransmission, or -1 otherwise */
-  sched_ctrl->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
+  sched_pdsch->dl_harq_pid = sched_ctrl->retrans_dl_harq.head;
 
   /* mark the corresponding RBs as used */
-  for (int rb = 0; rb < sched_ctrl->rbSize; rb++)
-    vrb_map[rb + sched_ctrl->rbStart] = 1;
+  for (int rb = 0; rb < sched_pdsch->rbSize; rb++)
+    vrb_map[rb + sched_pdsch->rbStart] = 1;
 }
 
-bool nr_ul_preprocessor_phytest(module_id_t module_id,
-                                frame_t frame,
-                                sub_frame_t slot,
-                                int num_slots_per_tdd,
-                                uint64_t ulsch_in_slot_bitmap) {
+uint32_t target_ul_mcs = 9;
+uint32_t target_ul_bw = 50;
+uint64_t ulsch_slot_bitmap = (1 << 8) | (1 << 18);
+bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot)
+{
   gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
   NR_COMMON_channels_t *cc = nr_mac->common_channels;
   NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
@@ -395,7 +408,9 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id,
 
   NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
 
-  const int tda = 1;
+  const int tda = RC.nrmac[module_id]->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot];
+  if (tda < 0)
+    return false;
   const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList =
     sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
   AssertFatal(tda < tdaList->list.count,
@@ -408,14 +423,11 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id,
   /* check if slot is UL, and that slot is 8 (assuming K2=6 because of UE
    * limitations).  Note that if K2 or the TDD configuration is changed, below
    * conditions might exclude each other and never be true */
-  if (!(is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot) && sched_slot == 8))
+  if (!is_xlsch_in_slot(ulsch_slot_bitmap, sched_slot))
     return false;
 
-  const int bw = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
   uint16_t rbStart = 0;
-  uint16_t rbSize = 50; /* due to OAI UE limitations */
-  if (rbSize>bw)
-    rbSize = bw;
+  uint16_t rbSize = target_ul_bw;
 
   uint16_t *vrb_map_UL =
       &RC.nrmac[module_id]->common_channels[CC_id].vrb_map_UL[sched_slot * MAX_BWP_SIZE];
@@ -434,14 +446,10 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id,
   sched_ctrl->sched_pusch.slot = sched_slot;
   sched_ctrl->sched_pusch.frame = sched_frame;
 
-  const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
-  sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
   uint8_t nr_of_candidates;
   find_aggregation_candidates(&sched_ctrl->aggregation_level,
                               &nr_of_candidates,
                               sched_ctrl->search_space);
-  sched_ctrl->coreset = get_coreset(
-      sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
   const int cid = sched_ctrl->coreset->controlResourceSetId;
   const uint16_t Y = UE_info->Y[UE_id][cid][slot];
   const int m = UE_info->num_pdcch_cand[UE_id][cid];
@@ -458,25 +466,19 @@ bool nr_ul_preprocessor_phytest(module_id_t module_id,
   }
   UE_info->num_pdcch_cand[UE_id][cid]++;
 
-  sched_ctrl->sched_pusch.time_domain_allocation = tda;
   const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
   const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
   const uint8_t num_dmrs_cdm_grps_no_data = 1;
   /* we want to avoid a lengthy deduction of DMRS and other parameters in
    * every TTI if we can save it, so check whether dci_format, TDA, or
    * num_dmrs_cdm_grps_no_data has changed and only then recompute */
-  NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
+  NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
   if (ps->time_domain_allocation != tda
       || ps->dci_format != dci_format
       || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
-    nr_save_pusch_fields(scc,
-                         sched_ctrl->active_ubwp,
-                         dci_format,
-                         tda,
-                         num_dmrs_cdm_grps_no_data,
-                         ps);
-
-  const int mcs = 9;
+    nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
+
+  const int mcs = target_ul_mcs;
   NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
   sched_pusch->mcs = mcs;
   sched_pusch->rbStart = rbStart;
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
index 94524795f3264b13a0129035696ededc7d062f68..0717cc568e6f3ecf33282e533f9fb19a2d438deb 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_primitives.c
@@ -120,11 +120,10 @@ static inline uint8_t get_max_candidates(uint8_t scs) {
 static inline uint8_t get_max_cces(uint8_t scs) {
   AssertFatal(scs<4, "Invalid PDCCH subcarrier spacing %d\n", scs);
   return (nr_max_number_of_cces_per_slot[scs]);
-} 
+}
 
-NR_ControlResourceSet_t *get_coreset(NR_BWP_Downlink_t *bwp,
-                                     NR_SearchSpace_t *ss,
-                                     int ss_type) {
+NR_ControlResourceSet_t *get_coreset(const NR_BWP_Downlink_t *bwp, const NR_SearchSpace_t *ss, int ss_type)
+{
   NR_ControlResourceSetId_t coreset_id = *ss->controlResourceSetId;
   if (ss_type == 0) { // common search space
     AssertFatal(coreset_id != 0, "coreset0 currently not supported\n");
@@ -146,9 +145,8 @@ NR_ControlResourceSet_t *get_coreset(NR_BWP_Downlink_t *bwp,
   }
 }
 
-NR_SearchSpace_t *get_searchspace(
-    NR_BWP_Downlink_t *bwp,
-    NR_SearchSpace__searchSpaceType_PR target_ss) {
+NR_SearchSpace_t *get_searchspace(const NR_BWP_Downlink_t *bwp, NR_SearchSpace__searchSpaceType_PR target_ss)
+{
   DevAssert(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList);
   DevAssert(bwp->bwp_Dedicated->pdcch_Config->choice.setup->searchSpacesToAddModList->list.count > 0);
 
@@ -212,12 +210,98 @@ int allocate_nr_CCEs(gNB_MAC_INST *nr_mac,
 
 }
 
-void nr_save_pusch_fields(const NR_ServingCellConfigCommon_t *scc,
-                          const NR_BWP_Uplink_t *ubwp,
-                          long dci_format,
-                          int tda,
-                          uint8_t num_dmrs_cdm_grps_no_data,
-                          NR_sched_pusch_save_t *ps)
+bool nr_find_nb_rb(uint16_t Qm,
+                   uint16_t R,
+                   uint16_t nb_symb_sch,
+                   uint16_t nb_dmrs_prb,
+                   uint32_t bytes,
+                   uint16_t nb_rb_max,
+                   uint32_t *tbs,
+                   uint16_t *nb_rb)
+{
+  /* is the maximum (not even) enough? */
+  *nb_rb = nb_rb_max;
+  *tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, 1) >> 3;
+  /* check whether it does not fit, or whether it exactly fits. Some algorithms
+   * might depend on the return value! */
+  if (bytes > *tbs)
+    return false;
+  if (bytes == *tbs)
+    return true;
+
+  /* is the minimum enough? */
+  *nb_rb = 1;
+  *tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, 1) >> 3;
+  if (bytes <= *tbs)
+    return true;
+
+  /* perform binary search to allocate all bytes within a TBS up to nb_rb_max
+   * RBs */
+  int hi = nb_rb_max;
+  int lo = 1;
+  for (int p = (hi + lo) / 2; lo + 1 < hi; p = (hi + lo) / 2) {
+    const uint32_t TBS = nr_compute_tbs(Qm, R, p, nb_symb_sch, nb_dmrs_prb, 0, 0, 1) >> 3;
+    if (bytes == TBS) {
+      hi = p;
+      break;
+    } else if (bytes < TBS) {
+      hi = p;
+    } else {
+      lo = p;
+    }
+  }
+  *nb_rb = hi;
+  *tbs = nr_compute_tbs(Qm, R, *nb_rb, nb_symb_sch, nb_dmrs_prb, 0, 0, 1) >> 3;
+  /* return whether we could allocate all bytes and stay below nb_rb_max */
+  return *tbs >= bytes && *nb_rb <= nb_rb_max;
+}
+
+void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc,
+                              const NR_CellGroupConfig_t *secondaryCellGroup,
+                              const NR_BWP_Downlink_t *bwp,
+                              int tda,
+                              uint8_t num_dmrs_cdm_grps_no_data,
+                              NR_pdsch_semi_static_t *ps)
+{
+  ps->time_domain_allocation = tda;
+
+  const struct NR_PDSCH_TimeDomainResourceAllocationList *tdaList =
+      bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList;
+  AssertFatal(tda < tdaList->list.count, "time_domain_allocation %d>=%d\n", tda, tdaList->list.count);
+  const int startSymbolAndLength = tdaList->list.array[tda]->startSymbolAndLength;
+  SLIV2SL(startSymbolAndLength, &ps->startSymbolIndex, &ps->nrOfSymbols);
+
+  if (!secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup
+           ->mcs_Table)
+    ps->mcsTableIdx = 0;
+  else if (*secondaryCellGroup->spCellConfig->spCellConfigDedicated->initialDownlinkBWP->pdsch_Config->choice.setup
+                ->mcs_Table
+           == 0)
+    ps->mcsTableIdx = 1;
+  else
+    ps->mcsTableIdx = 2;
+
+  ps->numDmrsCdmGrpsNoData = num_dmrs_cdm_grps_no_data;
+  ps->dmrsConfigType =
+      bwp->bwp_Dedicated->pdsch_Config->choice.setup->dmrs_DownlinkForPDSCH_MappingTypeA->choice.setup->dmrs_Type
+              == NULL
+          ? 0
+          : 1;
+  // if no data in dmrs cdm group is 1 only even REs have no data
+  // if no data in dmrs cdm group is 2 both odd and even REs have no data
+  ps->N_PRB_DMRS = num_dmrs_cdm_grps_no_data * (ps->dmrsConfigType == NFAPI_NR_DMRS_TYPE1 ? 6 : 4);
+  ps->N_DMRS_SLOT =
+      get_num_dmrs_symbols(bwp->bwp_Dedicated->pdsch_Config->choice.setup, scc->dmrs_TypeA_Position, ps->nrOfSymbols);
+  ps->dl_dmrs_symb_pos =
+      fill_dmrs_mask(bwp->bwp_Dedicated->pdsch_Config->choice.setup, scc->dmrs_TypeA_Position, ps->nrOfSymbols);
+}
+
+void nr_set_pusch_semi_static(const NR_ServingCellConfigCommon_t *scc,
+                              const NR_BWP_Uplink_t *ubwp,
+                              long dci_format,
+                              int tda,
+                              uint8_t num_dmrs_cdm_grps_no_data,
+                              NR_pusch_semi_static_t *ps)
 {
   ps->dci_format = dci_format;
   ps->time_domain_allocation = tda;
@@ -1616,6 +1700,24 @@ int get_nrofHARQ_ProcessesForPDSCH(e_NR_PDSCH_ServingCellConfig__nrofHARQ_Proces
   }
 }
 
+int get_dl_bwp_id(const NR_ServingCellConfig_t *servingCellConfig)
+{
+  if (servingCellConfig->firstActiveDownlinkBWP_Id)
+    return *servingCellConfig->firstActiveDownlinkBWP_Id;
+  else if (servingCellConfig->defaultDownlinkBWP_Id)
+    return *servingCellConfig->defaultDownlinkBWP_Id;
+  else
+    return 1;
+}
+
+int get_ul_bwp_id(const NR_ServingCellConfig_t *servingCellConfig)
+{
+  if (servingCellConfig->uplinkConfig && servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id)
+    return *servingCellConfig->uplinkConfig->firstActiveUplinkBWP_Id;
+  else
+    return 1;
+}
+
 //------------------------------------------------------------------------------
 int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secondaryCellGroup)
 {
@@ -1644,23 +1746,32 @@ int add_new_nr_ue(module_id_t mod_idP, rnti_t rntiP, NR_CellGroupConfig_t *secon
     sched_ctrl->ta_frame = 0;
     sched_ctrl->ta_update = 31;
     sched_ctrl->ta_apply = false;
-    sched_ctrl->ul_rssi = 0;
     /* set illegal time domain allocation to force recomputation of all fields */
-    sched_ctrl->pusch_save.time_domain_allocation = -1;
+    sched_ctrl->pdsch_semi_static.time_domain_allocation = -1;
+    sched_ctrl->pusch_semi_static.time_domain_allocation = -1;
     const NR_ServingCellConfig_t *servingCellConfig = secondaryCellGroup->spCellConfig->spCellConfigDedicated;
 
     /* Set default BWPs */
     const struct NR_ServingCellConfig__downlinkBWP_ToAddModList *bwpList = servingCellConfig->downlinkBWP_ToAddModList;
-    AssertFatal(bwpList->list.count == 1,
-                "downlinkBWP_ToAddModList has %d BWP!\n",
+    const int bwp_id = get_dl_bwp_id(servingCellConfig);
+    AssertFatal(bwp_id > 0 && bwp_id <= bwpList->list.count,
+                "%s(): illegal bwp_id %d (max %d)!\n",
+                __func__,
+                bwp_id,
                 bwpList->list.count);
-    const int bwp_id = 1;
     sched_ctrl->active_bwp = bwpList->list.array[bwp_id - 1];
+    const int target_ss = NR_SearchSpace__searchSpaceType_PR_ue_Specific;
+    sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, target_ss);
+    sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
+
     const struct NR_UplinkConfig__uplinkBWP_ToAddModList *ubwpList = servingCellConfig->uplinkConfig->uplinkBWP_ToAddModList;
-    AssertFatal(ubwpList->list.count == 1,
-                "uplinkBWP_ToAddModList has %d BWP!\n",
+    const int ubwp_id = get_ul_bwp_id(servingCellConfig);
+    AssertFatal(ubwp_id > 0 && ubwp_id <= ubwpList->list.count,
+                "%s(): illegal ubwp_id %d (max %d)!\n",
+                __func__,
+                ubwp_id,
                 ubwpList->list.count);
-    sched_ctrl->active_ubwp = ubwpList->list.array[bwp_id - 1];
+    sched_ctrl->active_ubwp = ubwpList->list.array[ubwp_id - 1];
 
     /* get Number of HARQ processes for this UE */
     AssertFatal(servingCellConfig->pdsch_ServingCellConfig->present == NR_SetupRelease_PDSCH_ServingCellConfig_PR_setup,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
index 247a7e2c459292c3ef59d2aea863400fd5412ce0..bdd6cf0c1dba241b5369d75c9555847b5baa9424 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_uci.c
@@ -948,7 +948,50 @@ void extract_pucch_csi_report (NR_CSI_MeasConfig_t *csi_MeasConfig,
 
   if ( !(reportQuantity_type)) 
     AssertFatal(reportQuantity_type, "reportQuantity is not configured");
+}
 
+static NR_UE_harq_t *find_harq(module_id_t mod_id, frame_t frame, sub_frame_t slot, int UE_id)
+{
+  /* In case of realtime problems: we can only identify a HARQ process by
+   * timing. If the HARQ process's feedback_frame/feedback_slot is not the one we
+   * expected, we assume that processing has been aborted and we need to
+   * skip this HARQ process, which is what happens in the loop below.
+   * Similarly, we might be "in advance", in which case we need to skip
+   * this result. */
+  NR_UE_sched_ctrl_t *sched_ctrl = &RC.nrmac[mod_id]->UE_info.UE_sched_ctrl[UE_id];
+  int8_t pid = sched_ctrl->feedback_dl_harq.head;
+  if (pid < 0)
+    return NULL;
+  NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
+  /* old feedbacks we missed: mark for retransmission */
+  while (harq->feedback_frame != frame
+         || (harq->feedback_frame == frame && harq->feedback_slot < slot)) {
+    LOG_W(MAC,
+          "expected HARQ pid %d feedback at %d.%d, but is at %d.%d instead (HARQ feedback is in the past)\n",
+          pid,
+          harq->feedback_frame,
+          harq->feedback_slot,
+          frame,
+          slot);
+    remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
+    handle_dl_harq(mod_id, UE_id, pid, 0);
+    pid = sched_ctrl->feedback_dl_harq.head;
+    if (pid < 0)
+      return NULL;
+    harq = &sched_ctrl->harq_processes[pid];
+  }
+  /* feedbacks that we wait for in the future: don't do anything */
+  if (harq->feedback_slot > slot) {
+    LOG_W(MAC,
+          "expected HARQ pid %d feedback at %d.%d, but is at %d.%d instead (HARQ feedback is in the future)\n",
+          pid,
+          harq->feedback_frame,
+          harq->feedback_slot,
+          frame,
+          slot);
+    return NULL;
+  }
+  return harq;
 }
 
 void handle_nr_uci_pucch_0_1(module_id_t mod_id,
@@ -968,6 +1011,7 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
   sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10,
                                 uci_01->ul_cqi,
                                 30);
+  sched_ctrl->pucch_snrx10 = uci_01->ul_cqi * 5 - 640;
 
   NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
   const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
@@ -976,28 +1020,14 @@ void handle_nr_uci_pucch_0_1(module_id_t mod_id,
     for (int harq_bit = 0; harq_bit < uci_01->harq->num_harq; harq_bit++) {
       const uint8_t harq_value = uci_01->harq->harq_list[harq_bit].harq_value;
       const uint8_t harq_confidence = uci_01->harq->harq_confidence_level;
+      const int feedback_frame = slot == 0 ? (frame - 1 + 1024) % 1024 : frame;
       const int feedback_slot = (slot - 1 + num_slots) % num_slots;
-      /* In case of realtime problems: we can only identify a HARQ process by
-       * timing. If the HARQ process's feedback_slot is not the one we
-       * expected, we assume that processing has been aborted and we need to
-       * skip this HARQ process, which is what happens in the loop below. If
-       * you don't experience real-time problems, you might simply revert the
-       * commit that introduced these changes. */
-      int8_t pid = sched_ctrl->feedback_dl_harq.head;
-      DevAssert(pid >= 0);
-      while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) {
-        LOG_W(MAC,
-              "expected feedback slot %d, but found %d instead\n",
-              sched_ctrl->harq_processes[pid].feedback_slot,
-              feedback_slot);
-        remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
-        handle_dl_harq(mod_id, UE_id, pid, 0);
-        pid = sched_ctrl->feedback_dl_harq.head;
-        DevAssert(pid >= 0);
-      }
-      remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
-      NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
+      NR_UE_harq_t *harq = find_harq(mod_id, feedback_frame, feedback_slot, UE_id);
+      if (!harq)
+        break;
       DevAssert(harq->is_waiting);
+      const int8_t pid = sched_ctrl->feedback_dl_harq.head;
+      remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
       handle_dl_harq(mod_id, UE_id, pid, harq_value == 1 && harq_confidence == 0);
     }
   }
@@ -1021,6 +1051,7 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
   sched_ctrl->tpc1 = nr_get_tpc(RC.nrmac[mod_id]->pucch_target_snrx10,
                                 uci_234->ul_cqi,
                                 30);
+  sched_ctrl->pucch_snrx10 = uci_234->ul_cqi * 5 - 640;
 
   NR_ServingCellConfigCommon_t *scc = RC.nrmac[mod_id]->common_channels->ServingCellConfigCommon;
   const int num_slots = nr_slots_per_frame[*scc->ssbSubcarrierSpacing];
@@ -1028,28 +1059,14 @@ void handle_nr_uci_pucch_2_3_4(module_id_t mod_id,
     // iterate over received harq bits
     for (int harq_bit = 0; harq_bit < uci_234->harq.harq_bit_len; harq_bit++) {
       const int acknack = ((uci_234->harq.harq_payload[harq_bit >> 3]) >> harq_bit) & 0x01;
+      const int feedback_frame = slot == 0 ? (frame - 1 + 1024) % 1024 : frame;
       const int feedback_slot = (slot - 1 + num_slots) % num_slots;
-      /* In case of realtime problems: we can only identify a HARQ process by
-       * timing. If the HARQ process's feedback_slot is not the one we
-       * expected, we assume that processing has been aborted and we need to
-       * skip this HARQ process, which is what happens in the loop below. If
-       * you don't experience real-time problems, you might simply revert the
-       * commit that introduced these changes. */
-      int8_t pid = sched_ctrl->feedback_dl_harq.head;
-      DevAssert(pid >= 0);
-      while (sched_ctrl->harq_processes[pid].feedback_slot != feedback_slot) {
-        LOG_W(MAC,
-              "expected feedback slot %d, but found %d instead\n",
-              sched_ctrl->harq_processes[pid].feedback_slot,
-              feedback_slot);
-        remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
-        handle_dl_harq(mod_id, UE_id, pid, 0);
-        pid = sched_ctrl->feedback_dl_harq.head;
-        DevAssert(pid >= 0);
-      }
-      remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
-      NR_UE_harq_t *harq = &sched_ctrl->harq_processes[pid];
+      NR_UE_harq_t *harq = find_harq(mod_id, feedback_frame, feedback_slot, UE_id);
+      if (!harq)
+        break;
       DevAssert(harq->is_waiting);
+      const int8_t pid = sched_ctrl->feedback_dl_harq.head;
+      remove_front_nr_list(&sched_ctrl->feedback_dl_harq);
       handle_dl_harq(mod_id, UE_id, pid, uci_234->harq.harq_crc != 1 && acknack);
     }
   }
@@ -1218,6 +1235,29 @@ bool nr_acknack_scheduling(int mod_id,
   // advance ul_slot if it is not reachable by UE
   pucch->ul_slot = max(pucch->ul_slot, slot + pdsch_to_harq_feedback[0]);
 
+  // is there already CSI in this slot?
+  const NR_sched_pucch_t *csi_pucch = &sched_ctrl->sched_pucch[2];
+  // skip the CSI PUCCH if it is present and if in the next frame/slot
+  if (csi_pucch->csi_bits > 0
+      && csi_pucch->frame == pucch->frame
+      && csi_pucch->ul_slot == pucch->ul_slot) {
+    AssertFatal(!csi_pucch->simultaneous_harqcsi,
+                "%s(): %d.%d cannot handle simultaneous_harqcsi, but found for UE %d\n",
+                __func__,
+                pucch->frame,
+                pucch->ul_slot,
+                UE_id);
+    nr_fill_nfapi_pucch(mod_id, frame, slot, csi_pucch, UE_id);
+    /* advance the UL slot information in PUCCH by one so we won't schedule in
+     * the same slot again */
+    const int f = pucch->frame;
+    const int s = pucch->ul_slot;
+    memset(pucch, 0, sizeof(*pucch));
+    pucch->frame = s == n_slots_frame - 1 ? (f + 1) % 1024 : f;
+    pucch->ul_slot = (s + 1) % n_slots_frame;
+    return nr_acknack_scheduling(mod_id, UE_id, frame, slot);
+  }
+
   // Find the right timing_indicator value.
   int i = 0;
   while (i < 8) {
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 9784b6b79e9f391392fdf7684d353ba6bf44ac6b..db4e26ae85ded329da854f40bd56b5b65dee522f 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -61,13 +61,124 @@ const uint32_t NR_LONG_BSR_TABLE[256] ={
 35910462, 38241455, 40723756, 43367187, 46182206, 49179951, 52372284, 55771835, 59392055, 63247269, 67352729, 71724679, 76380419, 81338368, 162676736, 4294967295
 };
 
-void nr_process_mac_pdu(
-    module_id_t module_idP,
-    rnti_t rnti,
-    uint8_t CC_id,
-    frame_t frameP,
-    uint8_t *pduP,
-    uint16_t mac_pdu_len)
+void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp)
+{
+  gNB_MAC_INST *nrmac = RC.nrmac[module_id];
+  const int bwp_id = ubwp->bwp_Id;
+  if (nrmac->preferred_ul_tda[bwp_id])
+    return;
+
+  /* there is a mixed slot only when in TDD */
+  const NR_ServingCellConfigCommon_t *scc = nrmac->common_channels->ServingCellConfigCommon;
+  const int mu = scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.subcarrierSpacing;
+  const NR_TDD_UL_DL_Pattern_t *tdd =
+      scc->tdd_UL_DL_ConfigurationCommon ? &scc->tdd_UL_DL_ConfigurationCommon->pattern1 : NULL;
+  /* Uplink symbols are at the end of the slot */
+  const int symb_ulMixed = tdd ? ((1 << tdd->nrofUplinkSymbols) - 1) << (14 - tdd->nrofUplinkSymbols) : 0;
+
+  const struct NR_PUCCH_Config__resourceToAddModList *resList = ubwp->bwp_Dedicated->pucch_Config->choice.setup->resourceToAddModList;
+  // for the moment, just block any symbol that might hold a PUCCH, regardless
+  // of the RB. This is a big simplification, as most RBs will NOT have a PUCCH
+  // in the respective symbols, but it simplifies scheduling
+  uint16_t symb_pucch = 0;
+  for (int i = 0; i < resList->list.count; ++i) {
+    const NR_PUCCH_Resource_t *resource = resList->list.array[i];
+    int nrofSymbols = 0;
+    int startingSymbolIndex = 0;
+    switch (resource->format.present) {
+      case NR_PUCCH_Resource__format_PR_format0:
+        nrofSymbols = resource->format.choice.format0->nrofSymbols;
+        startingSymbolIndex = resource->format.choice.format0->startingSymbolIndex;
+        break;
+      case NR_PUCCH_Resource__format_PR_format1:
+        nrofSymbols = resource->format.choice.format1->nrofSymbols;
+        startingSymbolIndex = resource->format.choice.format1->startingSymbolIndex;
+        break;
+      case NR_PUCCH_Resource__format_PR_format2:
+        nrofSymbols = resource->format.choice.format2->nrofSymbols;
+        startingSymbolIndex = resource->format.choice.format2->startingSymbolIndex;
+        break;
+      case NR_PUCCH_Resource__format_PR_format3:
+        nrofSymbols = resource->format.choice.format3->nrofSymbols;
+        startingSymbolIndex = resource->format.choice.format3->startingSymbolIndex;
+        break;
+      case NR_PUCCH_Resource__format_PR_format4:
+        nrofSymbols = resource->format.choice.format4->nrofSymbols;
+        startingSymbolIndex = resource->format.choice.format4->startingSymbolIndex;
+        break;
+      default:
+        AssertFatal(0, "found NR_PUCCH format index %d\n", resource->format.present);
+        break;
+    }
+    symb_pucch |= ((1 << nrofSymbols) - 1) << startingSymbolIndex;
+  }
+
+  /* check that TDA index 1 fits into UL slot and does not overlap with PUCCH */
+  const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
+  AssertFatal(tdaList->list.count >= 3, "need to have at least three TDAs for UL slots\n");
+  const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_UL = tdaList->list.array[0];
+  const int k2 = get_K2(ubwp, /* tda = */ 0, mu);
+  int start, len;
+  SLIV2SL(tdaP_UL->startSymbolAndLength, &start, &len);
+  const uint16_t symb_tda = ((1 << len) - 1) << start;
+  // check whether PUCCH and TDA overlap: then, we cannot use it. Note that
+  // here we assume that the PUCCH is scheduled in every slot, and on all RBs
+  // (which is mostly not true, this is a simplification)
+  AssertFatal((symb_pucch & symb_tda) == 0, "TDA index 0 for UL overlaps with PUCCH\n");
+
+  // get largest time domain allocation (TDA) for UL slot and UL in mixed slot
+  int tdaMi = -1;
+  const NR_PUSCH_TimeDomainResourceAllocation_t *tdaP_Mi = tdaList->list.array[1];
+  AssertFatal(k2 == get_K2(ubwp, /* tda = */ 1, mu),
+              "scheduler cannot handle different k2 for UL slot (%d) and UL Mixed slot (%ld)\n",
+              k2,
+              get_K2(ubwp, /* tda = */ 1, mu));
+  SLIV2SL(tdaP_Mi->startSymbolAndLength, &start, &len);
+  const uint16_t symb_tda_mi = ((1 << len) - 1) << start;
+  // check whether PUCCH and TDA overlap: then, we cannot use it. Also, check
+  // whether TDA is entirely within mixed slot, UL. Note that here we assume
+  // that the PUCCH is scheduled in every slot, and on all RBs (which is
+  // mostly not true, this is a simplification)
+  if ((symb_pucch & symb_tda_mi) == 0 && (symb_ulMixed & symb_tda_mi) == symb_tda_mi) {
+    tdaMi = 1;
+  } else {
+    LOG_E(MAC,
+          "TDA index 1 UL overlaps with PUCCH or is not entirely in mixed slot (symb_pucch %x symb_ulMixed %x symb_tda_mi %x), won't schedule UL mixed slot\n",
+          symb_pucch,
+          symb_ulMixed,
+          symb_tda_mi);
+  }
+
+  const uint8_t slots_per_frame[5] = {10, 20, 40, 80, 160};
+  const int n = slots_per_frame[*scc->ssbSubcarrierSpacing];
+  nrmac->preferred_ul_tda[bwp_id] = malloc(n * sizeof(*nrmac->preferred_ul_tda[bwp_id]));
+
+  const int nr_mix_slots = tdd ? tdd->nrofDownlinkSymbols != 0 || tdd->nrofUplinkSymbols != 0 : 0;
+  const int nr_slots_period = tdd ? tdd->nrofDownlinkSlots + tdd->nrofUplinkSlots + nr_mix_slots : n;
+  for (int slot = 0; slot < n; ++slot) {
+    const int sched_slot = (slot + k2) % n;
+    nrmac->preferred_ul_tda[bwp_id][slot] = -1;
+    if (!tdd || sched_slot % nr_slots_period >= tdd->nrofDownlinkSlots + nr_mix_slots)
+      nrmac->preferred_ul_tda[bwp_id][slot] = 0;
+    else if (tdd && nr_mix_slots && sched_slot % nr_slots_period == tdd->nrofDownlinkSlots)
+      nrmac->preferred_ul_tda[bwp_id][slot] = tdaMi;
+    LOG_I(MAC, "DL slot %d UL slot %d preferred_ul_tda %d\n", slot, sched_slot, nrmac->preferred_ul_tda[bwp_id][slot]);
+  }
+
+  if (k2 < tdd->nrofUplinkSlots)
+    LOG_W(MAC,
+          "k2 %d < tdd->nrofUplinkSlots %ld: not all UL slots can be scheduled\n",
+          k2,
+          tdd->nrofUplinkSlots);
+}
+
+void nr_process_mac_pdu(module_id_t module_idP,
+                        int UE_id,
+                        uint8_t CC_id,
+                        frame_t frameP,
+                        sub_frame_t slot,
+                        uint8_t *pduP,
+                        uint16_t mac_pdu_len)
 {
 
     // This function is adapting code from the old
@@ -79,11 +190,6 @@ void nr_process_mac_pdu(
 
 
     NR_UE_info_t *UE_info = &RC.nrmac[module_idP]->UE_info;
-    int UE_id = find_nr_UE_id(module_idP, rnti);
-    if (UE_id == -1) {
-      LOG_E(MAC, "%s() UE_id == -1\n",__func__);
-      return;
-    }
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
     //  For both DL/UL-SCH
     //  Except:
@@ -145,12 +251,15 @@ void nr_process_mac_pdu(
                NR_BSR_SHORT *bsr_s = (NR_BSR_SHORT *) ce_ptr;
                sched_ctrl->estimated_ul_buffer = 0;
                sched_ctrl->estimated_ul_buffer = NR_SHORT_BSR_TABLE[bsr_s->Buffer_size];
-               LOG_D(MAC, "SHORT BSR, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n",
+               LOG_D(MAC,
+                     "SHORT BSR at %4d.%2d, LCG ID %d, BS Index %d, BS value < %d, est buf %d\n",
+                     frameP,
+                     slot,
                      bsr_s->LcgID,
                      bsr_s->Buffer_size,
                      NR_SHORT_BSR_TABLE[bsr_s->Buffer_size],
                      sched_ctrl->estimated_ul_buffer);
-        	break;
+               break;
 
         case UL_SCH_LCID_L_BSR:
         case UL_SCH_LCID_L_TRUNCATED_BSR:
@@ -170,16 +279,18 @@ void nr_process_mac_pdu(
                n_Lcg = bsr_l->LcgID7 + bsr_l->LcgID6 + bsr_l->LcgID5 + bsr_l->LcgID4 +
                        bsr_l->LcgID3 + bsr_l->LcgID2 + bsr_l->LcgID1 + bsr_l->LcgID0;
 
-               LOG_D(MAC, "LONG BSR, LCG ID(7-0) %d/%d/%d/%d/%d/%d/%d/%d\n",
-                     bsr_l->LcgID7, bsr_l->LcgID6, bsr_l->LcgID5, bsr_l->LcgID4,
-                     bsr_l->LcgID3, bsr_l->LcgID2, bsr_l->LcgID1, bsr_l->LcgID0);
-
                for (int n = 0; n < n_Lcg; n++){
-                 LOG_D(MAC, "LONG BSR, %d/%d (n/n_Lcg), BS Index %d, BS value < %d",
-                       n, n_Lcg, pdu_ptr[mac_subheader_len + 1 + n],
-                       NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]]);
                  sched_ctrl->estimated_ul_buffer +=
                        NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]];
+                 LOG_D(MAC,
+                       "LONG BSR at %4d.%2d, %d/%d (n/n_Lcg), BS Index %d, BS value < %d, total %d\n",
+                       frameP,
+                       slot,
+                       n,
+                       n_Lcg,
+                       pdu_ptr[mac_subheader_len + 1 + n],
+                       NR_LONG_BSR_TABLE[pdu_ptr[mac_subheader_len + 1 + n]],
+                       sched_ctrl->estimated_ul_buffer);
                }
 
                break;
@@ -196,6 +307,20 @@ void nr_process_mac_pdu(
         	//fixed length
         	mac_ce_len = 2;
         	/* Extract SINGLE ENTRY PHR elements for PHR calculation */
+                ce_ptr = &pdu_ptr[mac_subheader_len];
+                NR_SINGLE_ENTRY_PHR_MAC_CE *phr = (NR_SINGLE_ENTRY_PHR_MAC_CE *) ce_ptr;
+                /* Save the phr info */
+                const int PH = phr->PH;
+                const int PCMAX = phr->PCMAX;
+                /* 38.133 Table10.1.17.1-1 */
+                if (PH < 55)
+                  sched_ctrl->ph = PH - 32;
+                else
+                  sched_ctrl->ph = PH - 32 + (PH - 54);
+                /* 38.133 Table10.1.18.1-1 */
+                sched_ctrl->pcmax = PCMAX - 29;
+                LOG_D(MAC, "SINGLE ENTRY PHR R1 %d PH %d (%d dB) R2 %d PCMAX %d (%d dBm)\n",
+                      phr->R1, PH, sched_ctrl->ph, phr->R2, PCMAX, sched_ctrl->pcmax);
         	break;
 
         case UL_SCH_LCID_MULTI_ENTRY_PHR_1_OCT:
@@ -246,48 +371,51 @@ void nr_process_mac_pdu(
               break;
 
         case UL_SCH_LCID_DTCH:
-                //  check if LCID is valid at current time.
-                if(((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F){
-                    //mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
-                    mac_subheader_len = 3;
-                    mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L1 & 0x7f) << 8)
-                    | ((uint16_t)((NR_MAC_SUBHEADER_LONG *) pdu_ptr)->L2 & 0xff);
-
-                } else {
-                  mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
-                  mac_subheader_len = 2;
-                }
-
-                LOG_D(MAC, "[UE %d] Frame %d : ULSCH -> UL-DTCH %d (gNB %d, %d bytes)\n", module_idP, frameP, rx_lcid, module_idP, mac_sdu_len);
-		int UE_id = find_nr_UE_id(module_idP, rnti);
-		RC.nrmac[module_idP]->UE_info.mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len;
-                #if defined(ENABLE_MAC_PAYLOAD_DEBUG)
-		    log_dump(MAC, pdu_ptr + mac_subheader_len, 32, LOG_DUMP_CHAR, "\n");
-
-                #endif
-
-                mac_rlc_data_ind(module_idP,
-                                 rnti,
-                                 module_idP,
-                                 frameP,
-                                 ENB_FLAG_YES,
-                                 MBMS_FLAG_NO,
-                                 rx_lcid,
-                                 (char *) (pdu_ptr + mac_subheader_len),
-                                 mac_sdu_len,
-                                 1,
-                                 NULL);
-
-                /* Updated estimated buffer when receiving data */
-                if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len)
-                  sched_ctrl->estimated_ul_buffer -= mac_sdu_len;
-                else
-                  sched_ctrl->estimated_ul_buffer = 0;
+          //  check if LCID is valid at current time.
+          if (((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->F) {
+            // mac_sdu_len |= (uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2)<<8;
+            mac_subheader_len = 3;
+            mac_sdu_len = ((uint16_t)(((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L1 & 0x7f) << 8)
+                          | ((uint16_t)((NR_MAC_SUBHEADER_LONG *)pdu_ptr)->L2 & 0xff);
+
+          } else {
+            mac_sdu_len = (uint16_t)((NR_MAC_SUBHEADER_SHORT *)pdu_ptr)->L;
+            mac_subheader_len = 2;
+          }
+
+          LOG_D(MAC,
+                "[UE %d] Frame %d : ULSCH -> UL-DTCH %d (gNB %d, %d bytes)\n",
+                module_idP,
+                frameP,
+                rx_lcid,
+                module_idP,
+                mac_sdu_len);
+          UE_info->mac_stats[UE_id].lc_bytes_rx[rx_lcid] += mac_sdu_len;
+#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
+          log_dump(MAC, pdu_ptr + mac_subheader_len, 32, LOG_DUMP_CHAR, "\n");
+#endif
 
-            break;
+          mac_rlc_data_ind(module_idP,
+                           UE_info->rnti[UE_id],
+                           module_idP,
+                           frameP,
+                           ENB_FLAG_YES,
+                           MBMS_FLAG_NO,
+                           rx_lcid,
+                           (char *)(pdu_ptr + mac_subheader_len),
+                           mac_sdu_len,
+                           1,
+                           NULL);
+
+          /* Updated estimated buffer when receiving data */
+          if (sched_ctrl->estimated_ul_buffer >= mac_sdu_len)
+            sched_ctrl->estimated_ul_buffer -= mac_sdu_len;
+          else
+            sched_ctrl->estimated_ul_buffer = 0;
+          break;
 
         default:
-          LOG_D(MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid);
+          LOG_E(MAC, "Received unknown MAC header (LCID = 0x%02x)\n", rx_lcid);
           return;
           break;
         }
@@ -305,6 +433,24 @@ void nr_process_mac_pdu(
     }
 }
 
+void abort_nr_ul_harq(module_id_t mod_id, int UE_id, int8_t harq_pid)
+{
+  NR_UE_info_t *UE_info = &RC.nrmac[mod_id]->UE_info;
+  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+  NR_UE_ul_harq_t *harq = &sched_ctrl->ul_harq_processes[harq_pid];
+
+  harq->ndi ^= 1;
+  harq->round = 0;
+  UE_info->mac_stats[UE_id].ulsch_errors++;
+  add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
+
+  /* the transmission failed: the UE won't send the data we expected initially,
+   * so retrieve to correctly schedule after next BSR */
+  sched_ctrl->sched_ul_bytes -= harq->sched_pusch.tb_size;
+  if (sched_ctrl->sched_ul_bytes < 0)
+    sched_ctrl->sched_ul_bytes = 0;
+}
+
 void handle_nr_ul_harq(module_id_t mod_id,
                        frame_t frame,
                        sub_frame_t slot,
@@ -347,14 +493,11 @@ void handle_nr_ul_harq(module_id_t mod_id,
           crc_pdu->rnti);
     add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
   } else if (harq->round == MAX_HARQ_ROUNDS) {
-    harq->ndi ^= 1;
-    harq->round = 0;
+    abort_nr_ul_harq(mod_id, UE_id, harq_pid);
     LOG_D(MAC,
           "RNTI %04x: Ulharq id %d crc failed in all rounds\n",
           crc_pdu->rnti,
           harq_pid);
-    UE_info->mac_stats[UE_id].ulsch_errors++;
-    add_tail_nr_list(&sched_ctrl->available_ul_harq, harq_pid);
   } else {
     harq->round++;
     LOG_D(MAC,
@@ -407,11 +550,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
           sduP);
 
     // if not missed detection (10dB threshold for now)
-    if (UE_scheduling_control->ul_rssi < (100+rssi)) {
+    if (UE_scheduling_control->raw_rssi < 100 + rssi) {
       UE_scheduling_control->tpc0 = nr_get_tpc(target_snrx10,ul_cqi,30);
       if (timing_advance != 0xffff)
         UE_scheduling_control->ta_update = timing_advance;
-      UE_scheduling_control->ul_rssi = rssi;
+      UE_scheduling_control->raw_rssi = rssi;
+      UE_scheduling_control->pusch_snrx10 = ul_cqi * 5 - 640;
       LOG_D(NR_MAC, "[UE %d] PUSCH TPC %d and TA %d\n",UE_id,UE_scheduling_control->tpc0,UE_scheduling_control->ta_update);
     }
     else{
@@ -438,17 +582,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
       if (UE_scheduling_control->sched_ul_bytes < 0)
         UE_scheduling_control->sched_ul_bytes = 0;
 
-      nr_process_mac_pdu(gnb_mod_idP, current_rnti, CC_idP, frameP, sduP, sdu_lenP);
-    }
-    else {
-      NR_UE_ul_harq_t *cur_harq = &UE_scheduling_control->ul_harq_processes[harq_pid];
-      /* reduce sched_ul_bytes when cur_harq->round == 3 */
-      if (cur_harq->round == 3){
-        const uint32_t tb_size = UE_scheduling_control->ul_harq_processes[harq_pid].sched_pusch.tb_size;
-        UE_scheduling_control->sched_ul_bytes -= tb_size;
-        if (UE_scheduling_control->sched_ul_bytes < 0)
-          UE_scheduling_control->sched_ul_bytes = 0;
-      }
+      nr_process_mac_pdu(gnb_mod_idP, UE_id, CC_idP, frameP, slotP, sduP, sdu_lenP);
     }
   } else {
     if (!sduP) // check that CRC passed
@@ -504,7 +638,7 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
   }
 }
 
-long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) {
+long get_K2(const NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu) {
   DevAssert(ubwp);
   const NR_PUSCH_TimeDomainResourceAllocation_t *tda_list = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[time_domain_assignment];
   if (tda_list->k2)
@@ -524,21 +658,142 @@ int next_list_entry_looped(NR_list_t *list, int UE_id)
   return list->next[UE_id] < 0 ? list->head : list->next[UE_id];
 }
 
+bool allocate_ul_retransmission(module_id_t module_id,
+                                frame_t frame,
+                                sub_frame_t slot,
+                                uint8_t *rballoc_mask,
+                                int *n_rb_sched,
+                                int UE_id,
+                                int harq_pid)
+{
+  const int CC_id = 0;
+  const NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon;
+  NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
+  NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
+  NR_sched_pusch_t *retInfo = &sched_ctrl->ul_harq_processes[harq_pid].sched_pusch;
+  int rbStart =
+      NRRIV2PRBOFFSET(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+  const uint16_t bwpSize =
+      NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+
+  const uint8_t num_dmrs_cdm_grps_no_data = 1;
+  const int tda = RC.nrmac[module_id]->preferred_dl_tda[sched_ctrl->active_ubwp->bwp_Id][slot];
+  if (tda == retInfo->time_domain_allocation) {
+    /* Check the resource is enough for retransmission */
+    while (rbStart < bwpSize && !rballoc_mask[rbStart])
+      rbStart++;
+    if (rbStart + retInfo->rbSize >= bwpSize) {
+      LOG_D(MAC, "cannot allocate retransmission of UE %d/RNTI %04x: no resources\n", UE_id, UE_info->rnti[UE_id]);
+      return false;
+    }
+    /* check whether we need to switch the TDA allocation since tha last
+     * (re-)transmission */
+    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
+    const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
+    const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
+    if (ps->time_domain_allocation != tda
+        || ps->dci_format != dci_format
+        || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
+      nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
+    LOG_D(MAC, "%s(): retransmission keeping TDA %d and TBS %d\n", __func__, tda, retInfo->tb_size);
+  } else {
+    /* the retransmission will use a different time domain allocation, check
+     * that we have enough resources */
+    while (rbStart < bwpSize && !rballoc_mask[rbStart])
+      rbStart++;
+    int rbSize = 0;
+    while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart + rbSize])
+      rbSize++;
+    NR_pusch_semi_static_t temp_ps;
+    const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
+    const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
+    nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, &temp_ps);
+    uint32_t new_tbs;
+    uint16_t new_rbSize;
+    bool success = nr_find_nb_rb(retInfo->Qm,
+                                 retInfo->R,
+                                 temp_ps.nrOfSymbols,
+                                 temp_ps.N_PRB_DMRS * temp_ps.num_dmrs_symb,
+                                 retInfo->tb_size,
+                                 rbSize,
+                                 &new_tbs,
+                                 &new_rbSize);
+    if (!success || new_tbs != retInfo->tb_size) {
+      LOG_D(MAC, "%s(): new TBsize %d of new TDA does not match old TBS %d\n", __func__, new_tbs, retInfo->tb_size);
+      return false; /* the maximum TBsize we might have is smaller than what we need */
+    }
+    LOG_D(MAC, "%s(): retransmission with TDA %d->%d and TBS %d -> %d\n", __func__, retInfo->time_domain_allocation, tda, retInfo->tb_size, new_tbs);
+    /* we can allocate it. Overwrite the time_domain_allocation, the number
+     * of RBs, and the new TB size. The rest is done below */
+    retInfo->tb_size = new_tbs;
+    retInfo->rbSize = new_rbSize;
+    retInfo->time_domain_allocation = tda;
+    sched_ctrl->pusch_semi_static = temp_ps;
+  }
+
+  /* Find free CCE */
+  bool freeCCE = find_free_CCE(module_id, slot, UE_id);
+  if (!freeCCE) {
+    LOG_D(MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
+    return false;
+  }
+
+  /* frame/slot in sched_pusch has been set previously. In the following, we
+   * overwrite the information in the retransmission information before storing
+   * as the new scheduling instruction */
+  retInfo->frame = sched_ctrl->sched_pusch.frame;
+  retInfo->slot = sched_ctrl->sched_pusch.slot;
+  /* Get previous PSUCH field info */
+  sched_ctrl->sched_pusch = *retInfo;
+  NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
+  LOG_D(MAC,
+        "%4d.%2d Allocate UL retransmission UE %d/RNTI %04x sched %4d.%2d (%d RBs)\n",
+        frame,
+        slot,
+        UE_id,
+        UE_info->rnti[UE_id],
+        sched_pusch->frame,
+        sched_pusch->slot,
+        sched_pusch->rbSize);
+
+  sched_pusch->rbStart = rbStart;
+  /* no need to recompute the TBS, it will be the same */
+
+  /* Mark the corresponding RBs as used */
+  n_rb_sched -= sched_pusch->rbSize;
+  for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
+    rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
+  return true;
+}
+
+void update_ul_ue_R_Qm(NR_sched_pusch_t *sched_pusch, const NR_pusch_semi_static_t *ps)
+{
+  const int mcs = sched_pusch->mcs;
+  sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
+  sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table);
+  if (ps->pusch_Config->tp_pi2BPSK
+      && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) {
+    sched_pusch->R >>= 1;
+    sched_pusch->Qm <<= 1;
+  }
+}
+
 float ul_thr_ue[MAX_MOBILES_PER_GNB];
+uint32_t ul_pf_tbs[3][28]; // pre-computed, approximate TBS values for PF coefficient
 int bsr0ue = -1;
 void pf_ul(module_id_t module_id,
            frame_t frame,
            sub_frame_t slot,
-           int num_slots_per_tdd,
            NR_list_t *UE_list,
+           int max_num_ue,
            int n_rb_sched,
-           uint8_t *rballoc_mask,
-           int max_num_ue) {
+           uint8_t *rballoc_mask) {
 
   const int CC_id = 0;
-  const int tda = 1;
-  NR_ServingCellConfigCommon_t *scc = RC.nrmac[module_id]->common_channels[CC_id].ServingCellConfigCommon;
-  NR_UE_info_t *UE_info = &RC.nrmac[module_id]->UE_info;
+  const uint8_t num_dmrs_cdm_grps_no_data = 1;
+  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;
   const int min_rb = 5;
   float coeff_ue[MAX_MOBILES_PER_GNB];
   // UEs that could be scheduled
@@ -554,86 +809,34 @@ void pf_ul(module_id_t module_id,
   /* Loop UE_list to calculate throughput and coeff */
   for (int UE_id = UE_list->head; UE_id >= 0; UE_id = UE_list->next[UE_id]) {
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
-    int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+    int rbStart =
+        NRRIV2PRBOFFSET(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
     const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
+    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
 
     /* Calculate throughput */
     const float a = 0.0005f; // corresponds to 200ms window
     const uint32_t b = UE_info->mac_stats[UE_id].ulsch_current_bytes;
     ul_thr_ue[UE_id] = (1 - a) * ul_thr_ue[UE_id] + a * b;
 
-    /* Save PUSCH field */
-    /* we want to avoid a lengthy deduction of DMRS and other parameters in
-     * every TTI if we can save it, so check whether dci_format, TDA, or
-     * num_dmrs_cdm_grps_no_data has changed and only then recompute */
-    sched_ctrl->sched_pusch.time_domain_allocation = tda;
-    sched_ctrl->search_space = get_searchspace(sched_ctrl->active_bwp, NR_SearchSpace__searchSpaceType_PR_ue_Specific);
-    sched_ctrl->coreset = get_coreset(sched_ctrl->active_bwp, sched_ctrl->search_space, 1 /* dedicated */);
-    const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
-    const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
-    const uint8_t num_dmrs_cdm_grps_no_data = 1;
-    NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
-    if (ps->time_domain_allocation != tda
-        || ps->dci_format != dci_format
-        || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
-      nr_save_pusch_fields(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
-
     /* Check if retransmission is necessary */
-    sched_ctrl->sched_pusch.ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
-    if (sched_ctrl->sched_pusch.ul_harq_pid >= 0) {
-      /* RETRANSMISSION: Allocate retransmission*/
-      /* Find free CCE */
-      bool freeCCE = find_free_CCE(module_id, slot, UE_id);
-      if (!freeCCE) {
-        LOG_D(MAC, "%4d.%2d no free CCE for retransmission UL DCI UE %04x\n", frame, slot, UE_info->rnti[UE_id]);
+    sched_pusch->ul_harq_pid = sched_ctrl->retrans_ul_harq.head;
+    if (sched_pusch->ul_harq_pid >= 0) {
+      /* Allocate retransmission*/
+      bool r = allocate_ul_retransmission(
+          module_id, frame, slot, rballoc_mask, &n_rb_sched, UE_id, sched_pusch->ul_harq_pid);
+      if (!r) {
+        LOG_D(MAC, "%4d.%2d UL retransmission UE RNTI %04x can NOT be allocated\n", frame, slot, UE_info->rnti[UE_id]);
         continue;
       }
       /* reduce max_num_ue once we are sure UE can be allocated, i.e., has CCE */
       max_num_ue--;
       if (max_num_ue < 0)
         return;
-
-      /* Save shced_frame and sched_slot before overwrite by previous PUSCH filed */
-      NR_UE_ul_harq_t *cur_harq = &sched_ctrl->ul_harq_processes[sched_ctrl->sched_pusch.ul_harq_pid];
-      cur_harq->sched_pusch.frame = sched_ctrl->sched_pusch.frame;
-      cur_harq->sched_pusch.slot = sched_ctrl->sched_pusch.slot;
-      /* Get previous PSUCH filed info */
-      sched_ctrl->sched_pusch = cur_harq->sched_pusch;
-      NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
-      LOG_D(MAC, "%4d.%2d Allocate UL retransmission UE %d/RNTI %04x sched %4d.%2d (%d RBs)\n",
-            frame, slot, UE_id, UE_info->rnti[UE_id],
-            sched_pusch->frame, sched_pusch->slot,
-            sched_pusch->rbSize);
-
-      while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
-      if (rbStart + sched_pusch->rbSize >= bwpSize) {
-        LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
-              UE_id, UE_info->rnti[UE_id]);
-        return;
-      }
-      sched_pusch->rbStart = rbStart;
-      /* no need to recompute the TBS, it will be the same */
-
-      /* Mark the corresponding RBs as used */
-      n_rb_sched -= sched_pusch->rbSize;
-      for (int rb = 0; rb < sched_ctrl->sched_pusch.rbSize; rb++)
-        rballoc_mask[rb + sched_ctrl->sched_pusch.rbStart] = 0;
-
       continue;
     }
 
-    /* Calculate TBS from MCS */
-    NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
-    const int mcs = 9;
-    sched_pusch->mcs = mcs;
-    sched_pusch->R = nr_get_code_rate_ul(mcs, ps->mcs_table);
-    sched_pusch->Qm = nr_get_Qm_ul(mcs, ps->mcs_table);
-    if (ps->pusch_Config->tp_pi2BPSK
-        && ((ps->mcs_table == 3 && mcs < 2) || (ps->mcs_table == 4 && mcs < 6))) {
-      sched_pusch->R >>= 1;
-      sched_pusch->Qm <<= 1;
-    }
-
     /* Check BSR and schedule UE if it is zero to avoid starvation, since we do
      * not have SR (yet) */
     if (sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes <= 0) {
@@ -652,10 +855,25 @@ void pf_ul(module_id_t module_id,
 
       while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
       if (rbStart + min_rb >= bwpSize) {
-        LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
+        LOG_D(MAC, "cannot allocate continuous data for UE %d/RNTI %04x: no resources\n",
               UE_id, UE_info->rnti[UE_id]);
-        return;
+        continue;
       }
+
+      /* Save PUSCH field */
+      /* we want to avoid a lengthy deduction of DMRS and other parameters in
+       * every TTI if we can save it, so check whether dci_format, TDA, or
+       * num_dmrs_cdm_grps_no_data has changed and only then recompute */
+      const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
+      const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
+      const int tda = nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot];
+      if (ps->time_domain_allocation != tda
+          || ps->dci_format != dci_format
+          || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
+        nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
+      NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
+      sched_pusch->mcs = 9;
+      update_ul_ue_R_Qm(sched_pusch, ps);
       sched_pusch->rbStart = rbStart;
       sched_pusch->rbSize = min_rb;
       sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
@@ -680,15 +898,8 @@ void pf_ul(module_id_t module_id,
     add_tail_nr_list(&UE_sched, UE_id);
 
     /* Calculate coefficient*/
-    const uint32_t tbs = nr_compute_tbs(sched_pusch->Qm,
-                                        sched_pusch->R,
-                                        1, // rbSize
-                                        ps->nrOfSymbols,
-                                        ps->N_PRB_DMRS * ps->num_dmrs_symb,
-                                        0, // nb_rb_oh
-                                        0,
-                                        1 /* NrOfLayers */)
-                          >> 3;
+    sched_pusch->mcs = 9;
+    const uint32_t tbs = ul_pf_tbs[ps->mcs_table][sched_pusch->mcs];
     coeff_ue[UE_id] = (float) tbs / ul_thr_ue[UE_id];
     LOG_D(MAC,"b %d, ul_thr_ue[%d] %f, tbs %d, coeff_ue[%d] %f\n",
           b, UE_id, ul_thr_ue[UE_id], tbs, UE_id, coeff_ue[UE_id]);
@@ -727,35 +938,45 @@ void pf_ul(module_id_t module_id,
 
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
     int rbStart = NRRIV2PRBOFFSET(sched_ctrl->active_bwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
-    const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE);
+    /* for some reason, the UEs do not like when they are scheduled on the last
+     * RB. Hence, as a (hopefully temporary) fix, schedule one RB less. */
+    const uint16_t bwpSize = NRRIV2BW(sched_ctrl->active_ubwp->bwp_Common->genericParameters.locationAndBandwidth, MAX_BWP_SIZE) - 1;
     NR_sched_pusch_t *sched_pusch = &sched_ctrl->sched_pusch;
-
+    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
 
     while (rbStart < bwpSize && !rballoc_mask[rbStart]) rbStart++;
     sched_pusch->rbStart = rbStart;
-    if (rbStart + min_rb >= bwpSize) {
-      LOG_W(MAC, "cannot allocate UL data for UE %d/RNTI %04x: no resources\n",
-            UE_id, UE_info->rnti[UE_id]);
-      return;
-    }
+    uint16_t max_rbSize = 1;
+    while (rbStart + max_rbSize < bwpSize && rballoc_mask[rbStart + max_rbSize])
+      max_rbSize++;
+
+    /* Save PUSCH field */
+    /* we want to avoid a lengthy deduction of DMRS and other parameters in
+     * every TTI if we can save it, so check whether dci_format, TDA, or
+     * num_dmrs_cdm_grps_no_data has changed and only then recompute */
+    const long f = sched_ctrl->search_space->searchSpaceType->choice.ue_Specific->dci_Formats;
+    const int dci_format = f ? NR_UL_DCI_FORMAT_0_1 : NR_UL_DCI_FORMAT_0_0;
+    const int tda = nrmac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot];
+    if (ps->time_domain_allocation != tda
+        || ps->dci_format != dci_format
+        || ps->num_dmrs_cdm_grps_no_data != num_dmrs_cdm_grps_no_data)
+      nr_set_pusch_semi_static(scc, sched_ctrl->active_ubwp, dci_format, tda, num_dmrs_cdm_grps_no_data, ps);
+    update_ul_ue_R_Qm(sched_pusch, ps);
 
-    /* Calculate the current scheduling bytes */
+    /* Calculate the current scheduling bytes and the necessary RBs */
     const int B = cmax(sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes, 0);
-    uint16_t rbSize = min_rb - 1;
-    do {
-      rbSize++;
-      sched_pusch->rbSize = rbSize;
-      sched_pusch->tb_size = nr_compute_tbs(sched_pusch->Qm,
-                                            sched_pusch->R,
-                                            sched_pusch->rbSize,
-                                            sched_ctrl->pusch_save.nrOfSymbols,
-                                            sched_ctrl->pusch_save.N_PRB_DMRS * sched_ctrl->pusch_save.num_dmrs_symb,
-                                            0, // nb_rb_oh
-                                            0,
-                                            1 /* NrOfLayers */)
-                             >> 3;
-    } while (rbStart + rbSize < bwpSize && rballoc_mask[rbStart+rbSize] &&
-             sched_pusch->tb_size < B);
+    uint16_t rbSize = 0;
+    uint32_t TBS = 0;
+    nr_find_nb_rb(sched_pusch->Qm,
+                  sched_pusch->R,
+                  ps->nrOfSymbols,
+                  ps->N_PRB_DMRS * ps->num_dmrs_symb,
+                  B,
+                  max_rbSize,
+                  &TBS,
+                  &rbSize);
+    sched_pusch->rbSize = rbSize;
+    sched_pusch->tb_size = TBS;
     LOG_D(MAC,"rbSize %d, TBS %d, est buf %d, sched_ul %d, B %d\n",
           rbSize, sched_pusch->tb_size, sched_ctrl->estimated_ul_buffer, sched_ctrl->sched_ul_bytes, B);
 
@@ -766,11 +987,8 @@ void pf_ul(module_id_t module_id,
   }
 }
 
-bool nr_simple_ulsch_preprocessor(module_id_t module_id,
-                                  frame_t frame,
-                                  sub_frame_t slot,
-                                  int num_slots_per_tdd,
-                                  uint64_t ulsch_in_slot_bitmap) {
+bool nr_fr1_ulsch_preprocessor(module_id_t module_id, frame_t frame, sub_frame_t slot)
+{
   gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
   NR_COMMON_channels_t *cc = nr_mac->common_channels;
   NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
@@ -782,31 +1000,25 @@ bool nr_simple_ulsch_preprocessor(module_id_t module_id,
 
   const int CC_id = 0;
 
-  /* NOT support different K2 in here, Get the K2 for first UE */
+  /* Get the K2 for first UE to compute offset. The other UEs are guaranteed to
+   * have the same K2 (we don't support multiple/different K2s via different
+   * TDAs yet). If the TDA is negative, it means that there is no UL slot to
+   * schedule now (slot + k2 is not UL slot) */
   int UE_id = UE_info->list.head;
   NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
-  const int tda = 1;
-  const struct NR_PUSCH_TimeDomainResourceAllocationList *tdaList =
-    sched_ctrl->active_ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
-  AssertFatal(tda < tdaList->list.count,
-              "time domain assignment %d >= %d\n",
-              tda,
-              tdaList->list.count);
-
+  const int tda = nr_mac->preferred_ul_tda[sched_ctrl->active_ubwp->bwp_Id][slot];
+  if (tda < 0)
+    return false;
   int K2 = get_K2(sched_ctrl->active_ubwp, tda, mu);
   const int sched_frame = frame + (slot + K2 >= nr_slots_per_frame[mu]);
   const int sched_slot = (slot + K2) % nr_slots_per_frame[mu];
-  if (!is_xlsch_in_slot(ulsch_in_slot_bitmap, sched_slot))
+  if (!is_xlsch_in_slot(nr_mac->ulsch_slot_bitmap[slot / 64], sched_slot))
     return false;
 
   sched_ctrl->sched_pusch.slot = sched_slot;
   sched_ctrl->sched_pusch.frame = sched_frame;
-
-  /* Confirm all the UE have same K2 as the first UE */
   for (UE_id = UE_info->list.next[UE_id]; UE_id >= 0; UE_id = UE_info->list.next[UE_id]) {
     NR_UE_sched_ctrl_t *sched_ctrl = &UE_info->UE_sched_ctrl[UE_id];
-    AssertFatal(K2 == get_K2(sched_ctrl->active_ubwp, tda, mu),
-                "Different K2, %d(UE%d) != %ld(UE%d)\n", K2, 0, get_K2(sched_ctrl->active_ubwp, tda, mu), UE_id);
     sched_ctrl->sched_pusch.slot = sched_slot;
     sched_ctrl->sched_pusch.frame = sched_frame;
   }
@@ -839,28 +1051,53 @@ bool nr_simple_ulsch_preprocessor(module_id_t module_id,
   pf_ul(module_id,
         frame,
         slot,
-        num_slots_per_tdd,
         &UE_info->list,
+        2,
         len,
-        rballoc_mask,
-        2);
+        rballoc_mask);
   return true;
 }
 
-void nr_schedule_ulsch(module_id_t module_id,
-                       frame_t frame,
-                       sub_frame_t slot,
-                       int num_slots_per_tdd,
-                       int ul_slots,
-                       uint64_t ulsch_in_slot_bitmap) {
+nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(module_id_t module_id, int CC_id)
+{
+  /* in the PF algorithm, we have to use the TBsize to compute the coefficient.
+   * This would include the number of DMRS symbols, which in turn depends on
+   * the time domain allocation. In case we are in a mixed slot, we do not want
+   * to recalculate all these values, and therefore we provide a look-up table
+   * which should approximately(!) give us the TBsize. In particular, the
+   * number of symbols, the number of DMRS symbols, and the exact Qm and R, are
+   * not correct*/
+  for (int mcsTableIdx = 0; mcsTableIdx < 3; ++mcsTableIdx) {
+    for (int mcs = 0; mcs < 29; ++mcs) {
+      if (mcs > 27 && mcsTableIdx == 1)
+        continue;
+      const uint8_t Qm = nr_get_Qm_dl(mcs, mcsTableIdx);
+      const uint16_t R = nr_get_code_rate_dl(mcs, mcsTableIdx);
+      /* note: we do not update R/Qm based on low MCS or pi2BPSK */
+      ul_pf_tbs[mcsTableIdx][mcs] = nr_compute_tbs(Qm,
+                                                   R,
+                                                   1, /* rbSize */
+                                                   10, /* hypothetical number of slots */
+                                                   0, /* N_PRB_DMRS * N_DMRS_SLOT */
+                                                   0 /* N_PRB_oh, 0 for initialBWP */,
+                                                   0 /* tb_scaling */,
+                                                   1 /* nrOfLayers */)
+                                    >> 3;
+    }
+  }
+  return nr_fr1_ulsch_preprocessor;
+}
+
+void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot)
+{
+  gNB_MAC_INST *nr_mac = RC.nrmac[module_id];
   /* Uplink data ONLY can be scheduled when the current slot is downlink slot,
    * because we have to schedule the DCI0 first before schedule uplink data */
-  if (is_xlsch_in_slot(ulsch_in_slot_bitmap, slot)) {
+  if (!is_xlsch_in_slot(nr_mac->dlsch_slot_bitmap[slot / 64], slot)) {
     LOG_D(MAC, "Current slot %d is NOT DL slot, cannot schedule DCI0 for UL data\n", slot);
     return;
   }
-  bool do_sched = RC.nrmac[module_id]->pre_processor_ul(
-      module_id, frame, slot, num_slots_per_tdd, ulsch_in_slot_bitmap);
+  bool do_sched = RC.nrmac[module_id]->pre_processor_ul(module_id, frame, slot);
   if (!do_sched)
     return;
 
@@ -915,8 +1152,8 @@ void nr_schedule_ulsch(module_id_t module_id,
 
     /* pre-computed PUSCH values that only change if time domain allocation,
      * DCI format, or DMRS parameters change. Updated in the preprocessor
-     * through nr_save_pusch_fields() */
-    NR_sched_pusch_save_t *ps = &sched_ctrl->pusch_save;
+     * through nr_set_pusch_semi_static() */
+    NR_pusch_semi_static_t *ps = &sched_ctrl->pusch_semi_static;
 
     /* Statistics */
     UE_info->mac_stats[UE_id].ulsch_rounds[cur_harq->round]++;
@@ -925,6 +1162,9 @@ void nr_schedule_ulsch(module_id_t module_id,
       /* Save information on MCS, TBS etc for the current initial transmission
        * so we have access to it when retransmitting */
       cur_harq->sched_pusch = *sched_pusch;
+      /* save which time allocation has been used, to be used on
+       * retransmissions */
+      cur_harq->sched_pusch.time_domain_allocation = ps->time_domain_allocation;
       sched_ctrl->sched_ul_bytes += sched_pusch->tb_size;
     } else {
       LOG_D(MAC,
@@ -941,7 +1181,7 @@ void nr_schedule_ulsch(module_id_t module_id,
     UE_info->mac_stats[UE_id].ulsch_current_bytes = sched_pusch->tb_size;
 
     LOG_D(MAC,
-          "%4d.%2d RNTI %04x UL sched %4d.%2d start %d RBS %d MCS %d TBS %d HARQ PID %d round %d NDI %d\n",
+          "%4d.%2d RNTI %04x UL sched %4d.%2d start %2d RBS %3d startSymbol %2d nb_symbol %2d MCS %2d TBS %4d HARQ PID %2d round %d NDI %d est %6d sched %6d est BSR %6d\n",
           frame,
           slot,
           rnti,
@@ -949,11 +1189,17 @@ void nr_schedule_ulsch(module_id_t module_id,
           sched_pusch->slot,
           sched_pusch->rbStart,
           sched_pusch->rbSize,
+          ps->startSymbolIndex,
+          ps->nrOfSymbols,
           sched_pusch->mcs,
           sched_pusch->tb_size,
           harq_id,
           cur_harq->round,
-          cur_harq->ndi);
+          cur_harq->ndi,
+          sched_ctrl->estimated_ul_buffer,
+          sched_ctrl->sched_ul_bytes,
+          sched_ctrl->estimated_ul_buffer - sched_ctrl->sched_ul_bytes);
+
 
     /* PUSCH in a later slot, but corresponding DCI now! */
     nfapi_nr_ul_tti_request_t *future_ul_tti_req = &RC.nrmac[module_id]->UL_tti_req_ahead[0][sched_pusch->slot];
diff --git a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
index 7f9e2a9a8d0d2a4cf32a87377e342a313d154830..dd4ec15539613b480d1a812310cbae7e1585a7df 100644
--- a/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_gNB/mac_proto.h
@@ -66,10 +66,16 @@ void clear_nr_nfapi_information(gNB_MAC_INST * gNB,
 void gNB_dlsch_ulsch_scheduler(module_id_t module_idP,
 			       frame_t frame_rxP, sub_frame_t slot_rxP);
 
+/* \brief main DL scheduler function. Calls a preprocessor to decide on
+ * resource allocation, then "post-processes" resource allocation (nFAPI
+ * messages, statistics, HARQ handling, CEs, ... */
 void nr_schedule_ue_spec(module_id_t module_id,
                          frame_t frame,
                          sub_frame_t slot);
 
+/* \brief default FR1 DL preprocessor init routine, returns preprocessor to call */
+nr_pp_impl_dl nr_init_fr1_dlsch_preprocessor(module_id_t module_id, int CC_id);
+
 void schedule_control_sib1(module_id_t module_id,
                            int CC_id,
                            int time_domain_allocation,
@@ -80,30 +86,19 @@ void schedule_control_sib1(module_id_t module_id,
 
 void schedule_nr_sib1(module_id_t module_idP, frame_t frameP, sub_frame_t subframeP);
 
-/* \brief default preprocessor */
-void nr_simple_dlsch_preprocessor(module_id_t module_id,
-                                  frame_t frame,
-                                  sub_frame_t slot);
-
 void schedule_nr_mib(module_id_t module_idP,
                      frame_t frameP,
                      sub_frame_t subframeP,
                      uint8_t slots_per_frame,
                      int nb_periods_per_frame);
 
-/// uplink scheduler
-void nr_schedule_ulsch(module_id_t module_id,
-                       frame_t frame,
-                       sub_frame_t slot,
-                       int num_slots_per_tdd,
-                       int ul_slots,
-                       uint64_t ulsch_in_slot_bitmap);
+/* \brief main UL scheduler function. Calls a preprocessor to decide on
+ * resource allocation, then "post-processes" resource allocation (nFAPI
+ * messages, statistics, HARQ handling, ... */
+void nr_schedule_ulsch(module_id_t module_id, frame_t frame, sub_frame_t slot);
 
-bool nr_simple_ulsch_preprocessor(module_id_t module_id,
-                                  frame_t frame,
-                                  sub_frame_t slot,
-                                  int num_slots_per_tdd,
-                                  uint64_t ulsch_in_slot_bitmap);
+/* \brief default FR1 UL preprocessor init routine, returns preprocessor to call */
+nr_pp_impl_ul nr_init_fr1_ulsch_preprocessor(module_id_t module_id, int CC_id);
 
 /////// Random Access MAC-PHY interface functions and primitives ///////
 
@@ -157,11 +152,7 @@ void nr_preprocessor_phytest(module_id_t module_id,
                              sub_frame_t slot);
 /* \brief UL preprocessor for phytest: schedules UE_id 0 with fixed MCS on a
  * fixed set of resources */
-bool nr_ul_preprocessor_phytest(module_id_t module_id,
-                                frame_t frame,
-                                sub_frame_t slot,
-                                int num_slots_per_tdd,
-                                uint64_t ulsch_in_slot_bitmap);
+bool nr_ul_preprocessor_phytest(module_id_t module_id, frame_t frame, sub_frame_t slot);
 
 void nr_schedule_css_dlsch_phytest(module_id_t   module_idP,
                                    frame_t       frameP,
@@ -260,23 +251,26 @@ void prepare_dci(const NR_CellGroupConfig_t *secondaryCellGroup,
                  int bwp_id);
 
 /* find coreset within the search space */
-NR_ControlResourceSet_t *get_coreset(NR_BWP_Downlink_t *bwp,
-                                     NR_SearchSpace_t *ss,
-                                     int ss_type);
+NR_ControlResourceSet_t *get_coreset(const NR_BWP_Downlink_t *bwp, const NR_SearchSpace_t *ss, int ss_type);
 
 /* find a search space within a BWP */
-NR_SearchSpace_t *get_searchspace(
-    NR_BWP_Downlink_t *bwp,
-    NR_SearchSpace__searchSpaceType_PR target_ss);
+NR_SearchSpace_t *get_searchspace(const NR_BWP_Downlink_t *bwp, NR_SearchSpace__searchSpaceType_PR target_ss);
+
+long get_K2(const NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu);
 
-long get_K2(NR_BWP_Uplink_t *ubwp, int time_domain_assignment, int mu);
+void nr_set_pdsch_semi_static(const NR_ServingCellConfigCommon_t *scc,
+                              const NR_CellGroupConfig_t *secondaryCellGroup,
+                              const NR_BWP_Downlink_t *bwp,
+                              int tda,
+                              uint8_t num_dmrs_cdm_grps_no_data,
+                              NR_pdsch_semi_static_t *ps);
 
-void nr_save_pusch_fields(const NR_ServingCellConfigCommon_t *scc,
-                          const NR_BWP_Uplink_t *ubwp,
-                          long dci_format,
-                          int tda,
-                          uint8_t num_dmrs_cdm_grps_no_data,
-                          NR_sched_pusch_save_t *ps);
+void nr_set_pusch_semi_static(const NR_ServingCellConfigCommon_t *scc,
+                              const NR_BWP_Uplink_t *ubwp,
+                              long dci_format,
+                              int tda,
+                              uint8_t num_dmrs_cdm_grps_no_data,
+                              NR_pusch_semi_static_t *ps);
 
 uint8_t nr_get_tpc(int target, uint8_t cqi, int incr);
 
@@ -355,14 +349,6 @@ void config_nr_mib(int Mod_idP,
 
 void nr_generate_Msg2(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP, NR_RA_t *ra);
 
-void nr_process_mac_pdu(
-    module_id_t module_idP,
-    rnti_t rnti,
-    uint8_t CC_id,
-    frame_t frameP,
-    uint8_t *pduP,
-    uint16_t mac_pdu_len);
-
 int binomial(int n, int k);
 
 bool is_xlsch_in_slot(uint64_t bitmap, sub_frame_t slot);
@@ -404,5 +390,18 @@ int16_t ssb_index_from_prach(module_id_t module_idP,
 
 void find_SSB_and_RO_available(module_id_t module_idP);
 
+void calculate_preferred_dl_tda(module_id_t module_id, const NR_BWP_Downlink_t *bwp);
+void calculate_preferred_ul_tda(module_id_t module_id, const NR_BWP_Uplink_t *ubwp);
+
 bool find_free_CCE(module_id_t module_id, sub_frame_t slot, int UE_id);
+
+bool nr_find_nb_rb(uint16_t Qm,
+                   uint16_t R,
+                   uint16_t nb_symb_sch,
+                   uint16_t nb_dmrs_prb,
+                   uint32_t bytes,
+                   uint16_t nb_rb_max,
+                   uint32_t *tbs,
+                   uint16_t *nb_rb);
+
 #endif /*__LAYER2_NR_MAC_PROTO_H__*/
diff --git a/openair2/LAYER2/NR_MAC_gNB/main.c b/openair2/LAYER2/NR_MAC_gNB/main.c
index 33e575d2b9ce2ff71bea5e7238faab3826c79e20..60b0cac21525ec5c41cfef67e3328080da785890 100644
--- a/openair2/LAYER2/NR_MAC_gNB/main.c
+++ b/openair2/LAYER2/NR_MAC_gNB/main.c
@@ -85,8 +85,8 @@ void mac_top_init_gNB(void)
         RC.nrmac[i]->pre_processor_dl = nr_preprocessor_phytest;
         RC.nrmac[i]->pre_processor_ul = nr_ul_preprocessor_phytest;
       } else {
-        RC.nrmac[i]->pre_processor_dl = nr_simple_dlsch_preprocessor;
-        RC.nrmac[i]->pre_processor_ul = nr_simple_ulsch_preprocessor;
+        RC.nrmac[i]->pre_processor_dl = nr_init_fr1_dlsch_preprocessor(i, 0);
+        RC.nrmac[i]->pre_processor_ul = nr_init_fr1_ulsch_preprocessor(i, 0);
       }
 
     }//END for (i = 0; i < RC.nb_nr_macrlc_inst; i++)
diff --git a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
index 8452ca3c4c334d6bcda7b4c488586e7ed34f460d..a03b34f9e154a1cfec90ba7a2e3816a88b72175f 100644
--- a/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
+++ b/openair2/LAYER2/NR_MAC_gNB/nr_mac_gNB.h
@@ -305,11 +305,11 @@ typedef struct NR_sched_pucch {
   uint8_t resource_indicator;
 } NR_sched_pucch_t;
 
-/* this struct is a helper: as long as the TDA and DCI format remain the same
- * over the same uBWP and search space, there is no need to recalculate all
- * S/L, MCS table, or DMRS-related parameters over and over again. Hence, we
- * store them in this struct for easy reference. */
-typedef struct NR_sched_pusch_save {
+/* PUSCH semi-static configuration: as long as the TDA and DCI format remain
+ * the same over the same uBWP and search space, there is no need to
+ * recalculate all S/L, MCS table, or DMRS-related parameters over and over
+ * again. Hence, we store them in this struct for easy reference. */
+typedef struct NR_pusch_semi_static_t {
   int dci_format;
   int time_domain_allocation;
   uint8_t num_dmrs_cdm_grps_no_data;
@@ -327,7 +327,7 @@ typedef struct NR_sched_pusch_save {
   uint16_t ul_dmrs_symb_pos;
   uint8_t num_dmrs_symb;
   uint8_t N_PRB_DMRS;
-} NR_sched_pusch_save_t;
+} NR_pusch_semi_static_t;
 
 typedef struct NR_sched_pusch {
   int frame;
@@ -337,9 +337,6 @@ typedef struct NR_sched_pusch {
   uint16_t rbSize;
   uint16_t rbStart;
 
-  // time-domain allocation for scheduled RBs
-  int time_domain_allocation;
-
   /// MCS
   uint8_t mcs;
 
@@ -350,17 +347,68 @@ typedef struct NR_sched_pusch {
 
   /// UL HARQ PID to use for this UE, or -1 for "any new"
   int8_t ul_harq_pid;
+
+  /// the Time Domain Allocation used for this transmission. Note that this is
+  /// only important for retransmissions; otherwise, the TDA in
+  /// NR_pusch_semi_static_t has precedence
+  int time_domain_allocation;
 } NR_sched_pusch_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
+ * reference. */
+typedef struct NR_pdsch_semi_static {
+  int time_domain_allocation;
+  uint8_t numDmrsCdmGrpsNoData;
+
+  int startSymbolIndex;
+  int nrOfSymbols;
+
+  uint8_t mcsTableIdx;
+
+  uint8_t N_PRB_DMRS;
+  uint8_t N_DMRS_SLOT;
+  uint16_t dl_dmrs_symb_pos;
+  nfapi_nr_dmrs_type_e dmrsConfigType;
+} NR_pdsch_semi_static_t;
+
+typedef struct NR_sched_pdsch {
+  /// RB allocation within active BWP
+  uint16_t rbSize;
+  uint16_t rbStart;
+
+  /// MCS-related infos
+  uint8_t mcs;
+
+  /// TBS-related info
+  uint16_t R;
+  uint8_t Qm;
+  uint32_t tb_size;
+
+  /// DL HARQ PID to use for this UE, or -1 for "any new"
+  int8_t dl_harq_pid;
+
+  /// the Time Domain Allocation used for this transmission. Note that this is
+  /// only important for retransmissions; otherwise, the TDA in
+  /// NR_pdsch_semi_static_t has precedence
+  int time_domain_allocation;
+} NR_sched_pdsch_t;
+
 typedef struct NR_UE_harq {
   bool is_waiting;
   uint8_t ndi;
   uint8_t round;
+  uint16_t feedback_frame;
   uint16_t feedback_slot;
 
-  /* Transport block to be sent using this HARQ process */
+  /* Transport block to be sent using this HARQ process, its size is in
+   * sched_pdsch */
   uint32_t tb[16384];
   uint32_t tb_size;
+
+  /// sched_pdsch keeps information on MCS etc used for the initial transmission
+  NR_sched_pdsch_t sched_pdsch;
 } NR_UE_harq_t;
 
 //! fixme : need to enhace for the multiple TB CQI report
@@ -441,13 +489,6 @@ typedef struct nr_csi_report {
   From spec 38.214 section 5.2.1.2 For periodic and semi-persistent CSI Resource Settings, the number of CSI-RS Resource Sets configured is limited to S=1
  */
 #define MAX_CSI_RESOURCE_SET_IN_CSI_RESOURCE_CONFIG 16
-typedef struct NR_UE_old_sched {
-  uint16_t rbSize;
-  int time_domain_allocation;
-  uint8_t mcsTableIdx;
-  uint8_t mcs;
-  uint8_t numDmrsCdmGrpsNoData;
-} NR_UE_ret_info_t;
 
 typedef enum {
   INACTIVE = 0,
@@ -468,15 +509,18 @@ typedef struct NR_UE_ul_harq {
 /*! \brief scheduling control information set through an API */
 #define MAX_CSI_REPORTS 48
 typedef struct {
-  /// total amount of data awaiting for this UE
-  uint32_t num_total_bytes;
-  /// per-LC status data
-  mac_rlc_status_resp_t rlc_status[MAX_NUM_LCID];
-
   /// the currently active BWP in DL
   NR_BWP_Downlink_t *active_bwp;
   /// the currently active BWP in UL
   NR_BWP_Uplink_t *active_ubwp;
+  /// CCE index and aggregation, should be coherent with cce_list
+  NR_SearchSpace_t *search_space;
+  NR_ControlResourceSet_t *coreset;
+
+  /// CCE index and Aggr. Level are shared for PUSCH/PDSCH allocation decisions
+  /// corresponding to the sched_pusch/sched_pdsch structures below
+  int cce_index;
+  uint8_t aggregation_level;
 
   /// PUCCH scheduling information. Array of three, we assume for the moment:
   /// HARQ in the first field, SR in second, CSI in third (as fixed by RRC
@@ -484,44 +528,40 @@ typedef struct {
   /// nr_acknack_scheduling()!
   NR_sched_pucch_t sched_pucch[3];
 
-  NR_sched_pusch_save_t pusch_save;
+  /// 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
   NR_sched_pusch_t sched_pusch;
 
-  /// CCE index and aggregation, should be coherent with cce_list
-  NR_SearchSpace_t *search_space;
-  NR_ControlResourceSet_t *coreset;
-  int cce_index;
-  uint8_t aggregation_level;
-
-  /// RB allocation within active BWP
-  uint16_t rbSize;
-  uint16_t rbStart;
-
   /// uplink bytes that are currently scheduled
   int sched_ul_bytes;
   /// estimation of the UL buffer size
   int estimated_ul_buffer;
 
-  // time-domain allocation for scheduled RBs
-  int time_domain_allocation;
+  /// PHR info: power headroom level (dB)
+  int ph;
+  /// PHR info: nominal UE transmit power levels (dBm)
+  int pcmax;
 
-  /// MCS-related infos
-  uint8_t mcsTableIdx;
-  uint8_t mcs;
-  uint8_t numDmrsCdmGrpsNoData;
+  /// PDSCH semi-static configuration: is not cleared across TTIs
+  NR_pdsch_semi_static_t pdsch_semi_static;
+  /// Sched PDSCH: scheduling decisions, copied into HARQ and cleared every TTI
+  NR_sched_pdsch_t sched_pdsch;
 
-  /// Retransmission-related information
-  NR_UE_ret_info_t retInfo[NR_MAX_NB_HARQ_PROCESSES];
-  /// DL HARQ PID to use for this UE, or -1 for "any new"
-  int8_t dl_harq_pid;
+  /// total amount of data awaiting for this UE
+  uint32_t num_total_bytes;
+  /// per-LC status data
+  mac_rlc_status_resp_t rlc_status[MAX_NUM_LCID];
 
   uint16_t ta_frame;
   int16_t ta_update;
   bool ta_apply;
   uint8_t tpc0;
   uint8_t tpc1;
-  uint16_t ul_rssi;
-  uint8_t current_harq_pid;
+  int raw_rssi;
+  int pusch_snrx10;
+  int pucch_snrx10;
+
   struct CSI_Report CSI_report[MAX_CSI_REPORTS];
   /// information about every HARQ process
   NR_UE_harq_t harq_processes[NR_MAX_NB_HARQ_PROCESSES];
@@ -539,7 +579,6 @@ typedef struct {
   NR_list_t feedback_ul_harq;
   /// UL HARQ processes that await retransmission
   NR_list_t retrans_ul_harq;
-  int dummy;
   NR_UE_mac_ce_ctrl_t UE_mac_ce_ctrl;// MAC CE related information
 } NR_UE_sched_ctrl_t;
 
@@ -591,9 +630,7 @@ typedef void (*nr_pp_impl_dl)(module_id_t mod_id,
                               sub_frame_t slot);
 typedef bool (*nr_pp_impl_ul)(module_id_t mod_id,
                               frame_t frame,
-                              sub_frame_t slot,
-                              int num_slots_per_tdd,
-                              uint64_t ulsch_in_slot_bitmap);
+                              sub_frame_t slot);
 
 /*! \brief top level eNB MAC structure */
 typedef struct gNB_MAC_INST_s {
@@ -670,6 +707,19 @@ typedef struct gNB_MAC_INST_s {
   /// highest index not yet been used in a given slot. Dynamically allocated
   /// so we can have it for every slot as a function of the numerology
   int *pucch_index_used[MAX_NUM_BWP];
+
+  /// bitmap of DLSCH slots, can hold up to 160 slots
+  uint64_t dlsch_slot_bitmap[3];
+  /// Lookup for preferred time domain allocation for BWP, in DL, slots
+  /// dynamically allocated
+  int *preferred_dl_tda[MAX_NUM_BWP];
+  /// bitmap of ULSCH slots, can hold up to 160 slots
+  uint64_t ulsch_slot_bitmap[3];
+  /// Lookup for preferred time domain allocation for UL BWP, dynamically
+  /// allocated. The index refers to the DL slot, and the indicated TDA's k2
+  /// points to the right UL slot
+  int *preferred_ul_tda[MAX_NUM_BWP];
+
   /// DL preprocessor for differentiated scheduling
   nr_pp_impl_dl pre_processor_dl;
   /// UL preprocessor for differentiated scheduling
diff --git a/openair2/RRC/NR/rrc_gNB_reconfig.c b/openair2/RRC/NR/rrc_gNB_reconfig.c
index 8e60dafb276ee4ab84614fdc3dddc193c63f8ab0..7ecac9f7e6905c9253da8f38212f21770be59e61 100644
--- a/openair2/RRC/NR/rrc_gNB_reconfig.c
+++ b/openair2/RRC/NR/rrc_gNB_reconfig.c
@@ -186,8 +186,8 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
   secondaryCellGroup->mac_CellGroupConfig->drx_Config = NULL;
   secondaryCellGroup->mac_CellGroupConfig->schedulingRequestConfig = NULL;
   secondaryCellGroup->mac_CellGroupConfig->bsr_Config=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->bsr_Config));
-  secondaryCellGroup->mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf80;
-  secondaryCellGroup->mac_CellGroupConfig->bsr_Config->retxBSR_Timer     = NR_BSR_Config__retxBSR_Timer_sf320;
+  secondaryCellGroup->mac_CellGroupConfig->bsr_Config->periodicBSR_Timer = NR_BSR_Config__periodicBSR_Timer_sf10;
+  secondaryCellGroup->mac_CellGroupConfig->bsr_Config->retxBSR_Timer     = NR_BSR_Config__retxBSR_Timer_sf160;
   secondaryCellGroup->mac_CellGroupConfig->tag_Config=calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->tag_Config));
   secondaryCellGroup->mac_CellGroupConfig->tag_Config->tag_ToReleaseList = NULL;
   secondaryCellGroup->mac_CellGroupConfig->tag_Config->tag_ToAddModList  = calloc(1,sizeof(*secondaryCellGroup->mac_CellGroupConfig->tag_Config->tag_ToAddModList));
@@ -1031,7 +1031,7 @@ void fill_default_secondaryCellGroup(NR_ServingCellConfigCommon_t *servingcellco
  long *delay[8];
  for (int i=0;i<8;i++) {
    delay[i] = calloc(1,sizeof(*delay[i]));
-   *delay[i] = (i<6) ? (i+2) : 0;
+   *delay[i] = i+2;
    ASN_SEQUENCE_ADD(&pucch_Config->dl_DataToUL_ACK->list,delay[i]);
  }
  pucch_Config->spatialRelationInfoToAddModList = calloc(1,sizeof(*pucch_Config->spatialRelationInfoToAddModList));
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf
index 25edddde86bb9d99cab21ce9e49b2d592b0cd9e5..ec94306b7d909adfacda299927c951c12e14e27d 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.32PRB.usrpx300.conf
@@ -58,27 +58,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=3
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
-             initialDLBWPstartSymbolAndLength_3  = 57; //43; //57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 257;
@@ -133,20 +120,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-        initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 4;
+        initialULBWPk2_2                      = 4;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf
index 182398cd88003df4ba4cb7b84a43d074a2984565..22856200983973f5a9f9fc683d6831f2be511035 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band257.tm1.66PRB.usrpn300.conf
@@ -56,22 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=3
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot (but is not used here)
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 257;
@@ -126,15 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot (not used here)
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
+
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
+        initialULBWPmappingType_2             = 1;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
 
         msg3_DeltaPreamble                                          = 1;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf
index 535c1fce5a111ab224bc8eec11169c62be22ffe7..908e4501757a1073442287b5e2fa0dd873e26e36 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band261.tm1.32PRB.usrpn300.conf
@@ -58,27 +58,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=3
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
-             initialDLBWPstartSymbolAndLength_3  = 57; //43; //57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 261;
@@ -133,20 +120,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-        initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 4;
+        initialULBWPk2_2                      = 4;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf
index 632ae126cd3774211afdab98f24db10a93083f8e..9576b5eb8f3428cf54bc030624ea0d9add785dda 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpn300.conf
@@ -56,27 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-       #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon
      #frequencyInfoUL
       ul_frequencyBand                                                 = 66;
@@ -132,20 +119,18 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-  initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
+
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf
index 46868d01854cd061595b82e32f53a06a027f3c75..c303ae5a97f6b1cdc5ff787e94cf60df00019953 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band66.tm1.106PRB.usrpx300.conf
@@ -56,27 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-       #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon
      #frequencyInfoUL
       ul_frequencyBand                                                 = 66;
@@ -132,20 +119,18 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-  initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
+
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
 
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf
index cb5249423052d1179588d32255ff66bf60f477ce..8cb31cce65c474492c1ede27253624488b9daaf5 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.30kHz,usrpb2x0.conf
@@ -56,22 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=3
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -126,16 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
+        initialULBWPmappingType_2             = 1;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf
index 27ade965dc29869e5fcf915f351aea4a04b6a807..f157d886fc2b8fc4f23a730a31eadd355f66e469 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.106PRB.slave.conf
@@ -56,27 +56,13 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
 
   #uplinkConfigCommon 
      #frequencyInfoUL
@@ -132,21 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-	initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
-
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf
index 9bb91329173132150f812a867c76919b11f56589..c79133e956586f6aaa950c87d5af4cb096148e66 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.slave.conf
@@ -56,22 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=3
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot (but not used here)
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -126,16 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 63; # this is SS=7 L=5
 
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
+        initialULBWPmappingType_2             = 1;
+        initialULBWPstartSymbolAndLength_2    = 91; # this is SS=7 L=7
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf
index 3b384dd072fa9ee2f9bbc534452433f96f9d6c53..f020efbfdc82d5229786cb41e967cc6ee8119ec0 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpb210.conf
@@ -56,22 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=3
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -126,16 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
+        initialULBWPmappingType_2             = 1;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
index 0ff7e4aa80e2da5451e8f45923d1082a7e8499d5..53feb26dbc59f818f98c2ec5f7a49ee0576e55fc 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -56,27 +56,13 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=5
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  # used for (full) DL slot
+        initialDLBWPmappingType_0           = 0;  # 0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; # this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  # used for DL part mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; # this is SS=1,L=5
 
   #uplinkConfigCommon 
      #frequencyInfoUL
@@ -132,20 +118,17 @@ gNBs =
         restrictedSetConfig                                         = 0,
 
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for (full) UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-        initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for UL part mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
index d0775384c3bacc250a03cd5a7aa0a7828ad1c64c..b3c960dc843f0d7fafad268c12f8f5e671029274 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.106PRB.usrpx300.conf
@@ -56,27 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
 
   #uplinkConfigCommon 
      #frequencyInfoUL
@@ -132,20 +119,17 @@ gNBs =
         restrictedSetConfig                                         = 0,
 
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+        initialULBWPk2_1                      = 6;  # used for mixed slot
 
-        initialULBWPk2_1                      = 6;
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
index d6110e19d5394bcb1008f9e49357dee0f7934a94..afca060683a84893d6af0829bd48efd234b52a9e 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpn300.conf
@@ -56,27 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=5 
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -131,21 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6; #2;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 6; #2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
-
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
index 07d04e65f922c0ad74cd0e71b792524541b1bc8e..b310ef952de4222a73232545a7d2fc9dd27e3615 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.217PRB.usrpx300.conf
@@ -56,27 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=5 
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -131,16 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
+        initialULBWPmappingType_2             = 1;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf
index a42da67df304fa6de7a5d016c3074f78b23dc843..386766c96b821d9f2592b90ee55d973f54068638 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/gnb.band78.tm1.273PRB.usrpn300.conf
@@ -56,27 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=5 
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -131,21 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;#2;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 6;#2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
-
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
index b2a765c4476fac7d214e9eb0626b25b84e4a7629..30cce9f7ca3089bafd15350d074b19cf996e5c51 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb.conf
@@ -58,27 +58,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
-             initialDLBWPstartSymbolAndLength_3  = 57; //43; //57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -133,20 +120,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf
index e8fcced3863b66f546cc48bebb420c60b03c09a6..6441db03289b2f71c843b9d2e0443bf81b47086b 100644
--- a/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf
+++ b/targets/PROJECTS/GENERIC-LTE-EPC/CONF/testing_gnb_n310.conf
@@ -56,27 +56,14 @@ gNBs =
         initialDLBWPsearchSpaceZero                                             = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	     #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=1,L=13
-             initialDLBWPstartSymbolAndLength_0  = 40;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=12 
-             initialDLBWPstartSymbolAndLength_1  = 53;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12 
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4 //5 (4 is for 43, 5 is for 57)
-             initialDLBWPstartSymbolAndLength_3  = 57; //43; //57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
+
   #uplinkConfigCommon 
      #frequencyInfoUL
       ul_frequencyBand                                                 = 78;
@@ -131,20 +118,17 @@ gNBs =
 # 0=unrestricted, 1=restricted type A, 2=restricted type B
         restrictedSetConfig                                         = 0,
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 2;
+        initialULBWPk2_0                      = 2;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 2;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
+
+        initialULBWPk2_1                      = 2;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
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 42b87d5672729353a594bc4426a3178fc458e50a..35f9b1e7a099c1fcf911ccb02c15737ebe35c45b 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
@@ -60,32 +60,13 @@ gNBs =
         initialDLBWPsearchSpaceZero                                     = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	         #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=12
-             initialDLBWPstartSymbolAndLength_0  = 53;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=10
-             initialDLBWPstartSymbolAndLength_1  = 81;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12
-             initialDLBWPstartSymbolAndLength_2  = 95;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=2,L=7
-             initialDLBWPstartSymbolAndLength_3  = 86;
-
-             initialDLBWPk0_4                    = 0;
-             initialDLBWPmappingType_4           = 0;
-             #this is SS=2,L=5
-             initialDLBWPstartSymbolAndLength_4  = 58;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
 
   #uplinkConfigCommon
      #frequencyInfoUL
@@ -141,20 +122,17 @@ gNBs =
         restrictedSetConfig                                         = 0,
 
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-        initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
diff --git a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
index 96df4a971f7ae73b106c2ed9654f57df02a1340e..6bffa1f01c9f2a7f415fa457bdf5b502b01eafbb 100644
--- a/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
+++ b/targets/PROJECTS/GENERIC-NR-5GC/CONF/gnb.sa.band78.fr1.106PRB.usrpb210.conf
@@ -60,27 +60,13 @@ gNBs =
         initialDLBWPsearchSpaceZero                                     = 0;
       #pdsch-ConfigCommon
         #pdschTimeDomainAllocationList (up to 16 entries)
-             initialDLBWPk0_0                    = 0;
-             #initialULBWPmappingType
-	         #0=typeA,1=typeB
-             initialDLBWPmappingType_0           = 0;
-             #this is SS=2,L=12
-             initialDLBWPstartSymbolAndLength_0  = 53;
-
-             initialDLBWPk0_1                    = 0;
-             initialDLBWPmappingType_1           = 0;
-             #this is SS=2,L=10
-             initialDLBWPstartSymbolAndLength_1  = 81;
-
-             initialDLBWPk0_2                    = 0;
-             initialDLBWPmappingType_2           = 0;
-             #this is SS=1,L=12
-             initialDLBWPstartSymbolAndLength_2  = 54;
-
-             initialDLBWPk0_3                    = 0;
-             initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=5
-             initialDLBWPstartSymbolAndLength_3  = 57;
+        initialDLBWPk0_0                    = 0;  #for DL slot
+        initialDLBWPmappingType_0           = 0;  #0=typeA,1=typeB
+        initialDLBWPstartSymbolAndLength_0  = 40; #this is SS=1,L=13
+
+        initialDLBWPk0_1                    = 0;  #for mixed slot
+        initialDLBWPmappingType_1           = 0;
+        initialDLBWPstartSymbolAndLength_1  = 57; #this is SS=1,L=5
 
   #uplinkConfigCommon
      #frequencyInfoUL
@@ -136,20 +122,17 @@ gNBs =
         restrictedSetConfig                                         = 0,
 
       # pusch-ConfigCommon (up to 16 elements)
-        initialULBWPk2_0                      = 6;
+        initialULBWPk2_0                      = 6;  # used for UL slot
         initialULBWPmappingType_0             = 1
-        # this is SS=0 L=11
-        initialULBWPstartSymbolAndLength_0    = 55;
+        initialULBWPstartSymbolAndLength_0    = 55; # this is SS=0 L=12
 
-        initialULBWPk2_1                      = 6;
+        initialULBWPk2_1                      = 6;  # used for mixed slot
         initialULBWPmappingType_1             = 1;
-        # this is SS=0 L=12
-        initialULBWPstartSymbolAndLength_1    = 69;
+        initialULBWPstartSymbolAndLength_1    = 24; # this is SS=10 L=2
 
-        initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;  # used for Msg.3 during RA
         initialULBWPmappingType_2             = 1;
-        # this is SS=10 L=4
-        initialULBWPstartSymbolAndLength_2    = 52;
+        initialULBWPstartSymbolAndLength_2    = 52; # this is SS=10 L=4
 
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;