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 60acb20ecbe18d553c2a854c7a9a8dc6ab90b5c4..6f081fa24ffe87cb61054bcaed03011724e0b5f4 100644
--- a/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
+++ b/ci-scripts/conf_files/gnb.band78.tm1.106PRB.usrpn300.conf
@@ -45,7 +45,7 @@ gNBs =
         dl_carrierBandwidth                                            = 106;
      #initialDownlinkBWP
       #genericParameters
-        # this is RBstart=0,L=50 (275*(L-1))+RBstart
+        # this is RBstart=41,L=24 (275*(L-1))+RBstart
         initialDLBWPlocationAndBandwidth                                        = 6366;
 # subcarrierSpacing
 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
@@ -74,7 +74,7 @@ gNBs =
 
              initialDLBWPk0_3                    = 0;
              initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4
+             #this is SS=1,L=5
              initialDLBWPstartSymbolAndLength_3  = 57;
 
   #uplinkConfigCommon 
@@ -135,18 +135,17 @@ gNBs =
         initialULBWPmappingType_0             = 1
         # this is SS=0 L=11
         initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 6;
+
+        initialULBWPk2_1                      = 6;
         initialULBWPmappingType_1             = 1;
         # this is SS=0 L=12
         initialULBWPstartSymbolAndLength_1    = 69;
 
-	initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;
         initialULBWPmappingType_2             = 1;
         # this is SS=10 L=4
         initialULBWPstartSymbolAndLength_2    = 52;
 
-
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;
 
diff --git a/ci-scripts/reportTestLocally.sh b/ci-scripts/reportTestLocally.sh
index 03cda2054209b609706b0f03eee0badf89a54527..8562f4b2de49411b922b4f8f39fda765ecebe3c9 100755
--- a/ci-scripts/reportTestLocally.sh
+++ b/ci-scripts/reportTestLocally.sh
@@ -470,7 +470,7 @@ function report_test {
                     then
                         NB_UE_TUNNEL_UP=`egrep -c "Interface oaitun_ue1 successfully configured" $UE_LOG`
                     else
-                        NB_UE_TUNNEL_UP=`egrep -c "executing ifconfig oaitun_ue1" $UE_LOG`
+                        NB_UE_TUNNEL_UP=`egrep -c "ip link set oaitun_ue1 up" $UE_LOG`
                     fi
                     if [ $NB_ENB_GOT_SYNC -gt 0 ] && [ $NB_UE_GOT_SYNC -gt 0 ] && [ $NB_ENB_SYNCED_WITH_UE -gt 0 ]
                     then
@@ -768,55 +768,47 @@ function report_test {
 
                 #RA test (--do-ra option)
 
-# Currently disabled
-#                #build log files names
-#                RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log
-#                RA_UE_LOG=$ARCHIVES_LOC/ra_check_${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log
-#                if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ]
-#                then
-#                    #get rid of full path
-#                    NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"`
-#                    NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"`
-#                    echo "      <tr>" >> ./test_simulator_results.html
-#                    echo "        <td>$NAME_ENB --- $NAME_UE</td>" >> ./test_simulator_results.html
-#                    echo "        <td>Check if RA proc succeeded</td>" >> ./test_simulator_results.html
-#
-#                    #gNB RA check
-#                    GNB_RECEIVED=`egrep -c "received correctly" $RA_ENB_LOG`
-#                    GNB_CONNECTED=`egrep -c "now 5G connected" $RA_ENB_LOG`
-#                    #UE RA check
-#                    UE_RA_PROC_OK=`egrep -c "RA procedure succeeded" $RA_UE_LOG`
-#
-#
-#                    if [ $GNB_RECEIVED -gt 0 ] && [ $GNB_CONNECTED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ]
-#                    then
-#                        echo "        <td bgcolor = \"green\" >OK</td>" >> ./test_simulator_results.html
-#                    else
-#                        echo "        <td bgcolor = \"red\" >KO</td>" >> ./test_simulator_results.html
-#                    fi
-#
-#                    echo "        <td><pre>" >> ./test_simulator_results.html
-#                    if [ $GNB_RECEIVED -gt 0 ]
-#                    then
-#                        echo "<font color = \"blue\">- gNB --> RA received</font>" >> ./test_simulator_results.html
-#                    else
-#                        echo "<font color = \"red\"><b>- gNB RA NOT RECEIVED</b></font>" >> ./test_simulator_results.html
-#                    fi
-#                    if [ $GNB_CONNECTED -gt 0 ]
-#                    then
-#                        echo "<font color = \"blue\">- gNB --> 5G connected</font>" >> ./test_simulator_results.html
-#                    else
-#                        echo "<font color = \"red\"><b>- gNB NOT 5G CONNECTED</b></font>" >> ./test_simulator_results.html
-#                    fi
-#                    if [ $UE_RA_PROC_OK -gt 0 ]
-#                    then
-#                        echo "<font color = \"blue\">- NR UE  --> RA procedure succeded</font>" >> ./test_simulator_results.html
-#                    else
-#                        echo "<font color = \"red\"><b>- NR UE RA procedure failed</b></font>" >> ./test_simulator_results.html
-#                    fi
-#                    echo "        </pre></td>" >> ./test_simulator_results.html
-#                    echo "      </tr>" >> ./test_simulator_results.html
-#                fi
+                #build log files names
+                RA_ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb_ra_test.log
+                RA_UE_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_ue_ra_test.log
+                if [ -f $RA_ENB_LOG ] && [ -f $RA_UE_LOG ]
+                then
+                    #get rid of full path
+                    NAME_ENB=`echo $RA_ENB_LOG | sed -e "s#$ARCHIVES_LOC/##"`
+                    NAME_UE=`echo $RA_UE_LOG | sed -e "s#$ARCHIVES_LOC/##"`
+                    echo "      <tr>" >> ./test_simulator_results.html
+                    echo "        <td>$NAME_ENB --- $NAME_UE</td>" >> ./test_simulator_results.html
+                    echo "        <td>Check if RA proc succeeded</td>" >> ./test_simulator_results.html
+
+                    #gNB RA check
+                    GNB_RECEIVED=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $RA_ENB_LOG`
+                    #UE RA check
+                    UE_RA_PROC_OK=`egrep -c "\[RAPROC\] RA procedure succeeded" $RA_UE_LOG`
+
+
+                    if [ $GNB_RECEIVED -gt 0 ] && [ $UE_RA_PROC_OK -gt 0 ]
+                    then
+                        echo "        <td bgcolor = \"green\" >OK</td>" >> ./test_simulator_results.html
+                    else
+                        echo "        <td bgcolor = \"red\" >KO</td>" >> ./test_simulator_results.html
+                    fi
+
+                    echo "        <td><pre>" >> ./test_simulator_results.html
+                    if [ $GNB_RECEIVED -gt 0 ]
+                    then
+                        echo "<font color = \"blue\">- gNB --> RA received</font>" >> ./test_simulator_results.html
+                    else
+                        echo "<font color = \"red\"><b>- gNB RA NOT RECEIVED</b></font>" >> ./test_simulator_results.html
+                    fi
+                    if [ $UE_RA_PROC_OK -gt 0 ]
+                    then
+                        echo "<font color = \"blue\">- NR UE  --> RA procedure succeded</font>" >> ./test_simulator_results.html
+                    else
+                        echo "<font color = \"red\"><b>- NR UE RA procedure failed</b></font>" >> ./test_simulator_results.html
+                    fi
+                    echo "        </pre></td>" >> ./test_simulator_results.html
+                    echo "      </tr>" >> ./test_simulator_results.html
+                fi
 
                 #SYNC test
                 ENB_LOG=$ARCHIVES_LOC/${TMODE}_${BW}prb_${CN_CONFIG}_gnb.log
diff --git a/ci-scripts/runTestOnVM.sh b/ci-scripts/runTestOnVM.sh
index 734001040cd587005c44ed8a6420a1acb39a9397..9f44e0ae91970c68071ecbe065040a8491b26da3 100755
--- a/ci-scripts/runTestOnVM.sh
+++ b/ci-scripts/runTestOnVM.sh
@@ -281,14 +281,35 @@ function check_ra_result {
     local LOC_GNB_LOG=$1
     local LOC_UE_LOG=$2
 
-    #gNB RA test
-    echo "Checking gNB Log for RA success"
-    egrep "received correctly" $1 
-    egrep "now 5G connected" $1 
- 
-    #UE RA test
-    echo 'Checking UE Log for RA success'
-    egrep "RA procedure succeeded" $2
+    #if log files exist
+    if [ -f $LOC_GNB_LOG ] && [ -f $LOC_UE_LOG ]
+    then
+
+        #gNB RA test
+        #console check
+        echo "Checking gNB Log for RA success"
+        egrep "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1
+        #script check
+        local GNB_COMPLETE=`egrep -c "\[RAPROC\] PUSCH with TC_RNTI (.+) received correctly" $1`
+
+        #UE RA test
+        #console check
+        echo 'Checking UE Log for RA success'
+        egrep "\[RAPROC\] RA procedure succeeded" $2
+        #script check
+        local UE_COMPLETE=`egrep -c "\[RAPROC\] RA procedure succeeded" $2`
+
+        #generate status
+        if [ $GNB_COMPLETE -eq 0 ] || [ $UE_COMPLETE -eq 0 ]
+        then
+            RA_STATUS=-1
+            echo "RA test FAILED, could not find the markers"
+        fi
+    #case where log files do not exist
+    else
+        echo "RA test log files not present"
+        RA_STATUS=-1        
+    fi
 
 }
 
@@ -1225,16 +1246,6 @@ function start_rf_sim_gnb {
     ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1
     rm $1
 
-    # For the moment, in RA test, no check and no copy of generated raw files
-    if [ $LOC_RA_TEST -eq 1 ] # RA test
-    then
-        sleep 30
-        echo "echo \"free -m\"" > $1
-        echo "free -m" >> $1
-        ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_GNB_VM_IP_ADDR < $1
-        rm $1
-        return 0
-    fi
 
     local i="0"
     echo "egrep -c \"got sync\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1
@@ -1258,7 +1269,9 @@ function start_rf_sim_gnb {
         GNB_SYNC=1
         echo "RF-SIM gNB is sync'ed: waiting for UE(s) to connect"
     fi
-    if [ $LOC_S1_CONFIGURATION -eq 0 ]
+
+    # check noS1 config only outside RA test (as it does not support noS1)
+    if [ $LOC_S1_CONFIGURATION -eq 0 ] && [ $LOC_RA_TEST -eq 0 ]
     then
         echo "ifconfig oaitun_enb1 | egrep -c \"inet addr\"" > $1
         # Checking oaitun_enb1 interface has now an IP address
@@ -1341,14 +1354,6 @@ function start_rf_sim_nr_ue {
     ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1
     rm $1
 
-    # In case of RA test mode, no UE sync check for the moment.
-    # To be removed later?
-    if [ $LOC_RA_TEST -eq 1 ] # RA test
-    then
-         sleep 30
-         NR_UE_SYNC=1
-         return 0
-    fi
     local i="0"
     echo "egrep -c \"Initial sync: pbch decoded sucessfully\" /home/ubuntu/tmp/cmake_targets/log/$LOC_LOG_FILE" > $1
     while [ $i -lt 10 ]
@@ -1372,11 +1377,13 @@ function start_rf_sim_nr_ue {
     else
         echo "RF-SIM NR-UE is sync'ed w/ gNB"
     fi
-    # Checking oaitun_ue1 interface has now an IP address
-    i="0"
-    echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1
-    while [ $i -lt 10 ]
-    do
+    # Checking oaitun_ue1 interface has now an IP address (only outside RA test)
+    if [ $LOC_RA_TEST -eq  0 ]
+    then
+      i="0"
+      echo "ifconfig oaitun_ue1 | egrep -c \"inet addr\"" > $1
+      while [ $i -lt 10 ]
+      do
         sleep 5
         CONNECTED=`ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1`
         if [ $CONNECTED -eq 1 ]
@@ -1385,21 +1392,20 @@ function start_rf_sim_nr_ue {
         else
             i=$[$i+1]
         fi
-    done
-    echo "echo \"free -m\"" > $1
-    echo "free -m" >> $1
-    ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1
-    rm $1
-    if [ $i -lt 50 ]
-    then
+      done
+      echo "echo \"free -m\"" > $1
+      echo "free -m" >> $1
+      ssh -T -o StrictHostKeyChecking=no ubuntu@$LOC_NR_UE_VM_IP_ADDR < $1
+      rm $1
+      if [ $i -lt 50 ]
+      then
         NR_UE_SYNC=0
         echo "RF-SIM NR-UE oaitun_ue1 is DOWN or NOT CONFIGURED"
-    else
+      else
         echo "RF-SIM NR-UE oaitun_ue1 is UP and CONFIGURED"
-    fi
-    sleep 10
-
-
+      fi
+      sleep 10
+   fi
 }
 
 
@@ -2196,10 +2202,11 @@ function run_test_on_vm {
         NR_STATUS=0
 
         ######### start of RA TEST loop
-        while [ $try_cnt -lt 1 ]
+        while [ $try_cnt -lt 10 ] #10 because it hardly succeed within CI
         do
 
             SYNC_STATUS=0
+            RA_STATUS=0
 
             echo "############################################################"
             echo "${CN_CONFIG} : Starting the gNB"
@@ -2241,71 +2248,25 @@ function run_test_on_vm {
             echo "############################################################"
 
             # Proper check to be done when RA test is working!
-            #check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE
-
-            try_cnt=$[$try_cnt+1]
-
-        ########### end RA test
-        done
-        sleep 10
-        try_cnt="0"
-
-        ######### start of PHY TEST loop
-        while [ $try_cnt -lt 4 ]
-        do
-
-            #start RA test
-            SYNC_STATUS=0
-            PING_STATUS=0
-            IPERF_STATUS=0
-
-            echo "############################################################"
-            echo "${CN_CONFIG} : Starting the gNB"
-            echo "############################################################"
-            CURRENT_GNB_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_gnb.log
-            #last argument = 1 is to enable --do-ra for RA test
-            start_rf_sim_gnb $GNB_VM_CMDS "$GNB_VM_IP_ADDR" $CURRENT_GNB_LOG_FILE $PRB $CONF_FILE $S1_NOS1_CFG 1
-
-            echo "############################################################"
-            echo "${CN_CONFIG} : Starting the NR-UE"
-            echo "############################################################"
-            CURRENT_NR_UE_LOG_FILE=tdd_${PRB}prb_${CN_CONFIG}_ue.log
-            #last argument = 1 is to enable --do-ra for RA test
-            start_rf_sim_nr_ue $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR $GNB_VM_IP_ADDR $CURRENT_NR_UE_LOG_FILE $PRB $FREQUENCY $S1_NOS1_CFG 1
-            if [ $NR_UE_SYNC -eq 0 ]
+            check_ra_result $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE
+            if [ $RA_STATUS -ne 0 ]
             then
-                echo "Problem w/ gNB and NR-UE not syncing"
-                terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2
-                terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1
-                scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC
-                scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC
-                SYNC_STATUS=-1
+                echo "RA test NOT OK"
                 try_cnt=$[$try_cnt+1]
-                continue
+            else
+                try_cnt=$[$try_cnt+10]
             fi
+        done
+        ########### end RA test
+        
+        sleep 30
 
-            echo "############################################################"
-            echo "${CN_CONFIG} : Terminate gNB/NR-UE simulators"
-            echo "############################################################"
-            sleep 20
-            terminate_enb_ue_basic_sim $NR_UE_VM_CMDS $NR_UE_VM_IP_ADDR 2
-            terminate_enb_ue_basic_sim $GNB_VM_CMDS $GNB_VM_IP_ADDR 1
-            scp -o StrictHostKeyChecking=no ubuntu@$GNB_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC
-            scp -o StrictHostKeyChecking=no ubuntu@$NR_UE_VM_IP_ADDR:/home/ubuntu/tmp/cmake_targets/log/$CURRENT_NR_UE_LOG_FILE $ARCHIVES_LOC
-
-            #check RA markers in gNB and NR UE log files
-            echo "############################################################"
-            echo "${CN_CONFIG} : Checking RA on gNB / NR-UE"
-            echo "############################################################"
-
-            mv $ARCHIVES_LOC/$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE
-            mv $ARCHIVES_LOC/$CURRENT_NR_UE_LOG_FILE  $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE
-            # Proper check to be done when RA test is working!
-            #check_ra_result $ARCHIVES_LOC/ra_check_$CURRENT_GNB_LOG_FILE $ARCHIVES_LOC/ra_check_$CURRENT_NR_UE_LOG_FILE
 
+        ######### start of PHY TEST loop
+        try_cnt="0"
+        while [ $try_cnt -lt 4 ]
+        do
 
-            #end RA test
-            sleep 30
 
             SYNC_STATUS=0
             PING_STATUS=0
@@ -2409,6 +2370,7 @@ function run_test_on_vm {
         echo "Checking run status"
         echo "############################################################"
 
+        if [ $RA_STATUS -ne 0 ]; then NR_STATUS=-1; fi
         if [ $SYNC_STATUS -ne 0 ]; then NR_STATUS=-1; fi
         if [ $PING_STATUS -ne 0 ]; then NR_STATUS=-1; fi
         if [ $IPERF_STATUS -ne 0 ]; then NR_STATUS=-1; fi
diff --git a/common/utils/T/T_messages.txt b/common/utils/T/T_messages.txt
index d036b405606a78cb1b73d9564ec2b8ddc9383b29..a4c92f9e3c38dac67aa7ab4646df6245cc8c0e4e 100644
--- a/common/utils/T/T_messages.txt
+++ b/common/utils/T/T_messages.txt
@@ -85,6 +85,10 @@ ID = ENB_PHY_MIB
     DESC = MIB data
     GROUP = ALL:PHY:ENB:WIRESHARK
     FORMAT = int,eNB_ID : int,frame : int,subframe : buffer,data
+ID = GNB_PHY_MIB
+    DESC = NR MIB data
+    GROUP = ALL:PHY:GNB:WIRESHARK
+    FORMAT = int,gNB_ID : int,frame : int,slot : buffer,data
 
 #MAC logs
 ID = ENB_MAC_UE_DL_SDU
@@ -131,6 +135,18 @@ ID = ENB_MAC_UE_DL_RAR_PDU_WITH_DATA
     DESC = MAC downlink PDU for an UE
     GROUP = ALL:MAC:ENB:WIRESHARK
     FORMAT = int,eNB_ID : int,CC_id : int,rnti : int,frame : int,subframe : int,harq_pid : buffer,data
+ID = GNB_MAC_DL_PDU_WITH_DATA
+    DESC = NR MAC downlink PDU for an UE
+    GROUP = ALL:MAC:GNB:WIRESHARK
+    FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
+ID = GNB_MAC_UL_PDU_WITH_DATA
+    DESC = NR MAC uplink PDU for an UE
+    GROUP = ALL:MAC:GNB:WIRESHARK
+    FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
+ID = GNB_MAC_DL_RAR_PDU_WITH_DATA
+    DESC = NR MAC downlink PDU for RAR
+    GROUP = ALL:MAC:GNB:WIRESHARK
+    FORMAT = int,gNB_ID : int,CC_id : int,rnti : int,frame : int,slot : int,harq_pid : buffer,data
 
 #RLC logs
 ID = ENB_RLC_DL
diff --git a/common/utils/T/tracer/macpdu2wireshark.c b/common/utils/T/tracer/macpdu2wireshark.c
index c391a9978679731c013d132849bbd13f24fe1bb0..d262f09e4a610969290c27135773adf2bd9fa0c8 100644
--- a/common/utils/T/tracer/macpdu2wireshark.c
+++ b/common/utils/T/tracer/macpdu2wireshark.c
@@ -23,6 +23,8 @@ typedef struct {
   int socket;
   struct sockaddr_in to;
   OBUF buf;
+
+  /* LTE traces */
   /* ul */
   int ul_rnti;
   int ul_frame;
@@ -46,6 +48,28 @@ typedef struct {
   int rar_frame;
   int rar_subframe;
   int rar_data;
+
+  /* NR traces */
+  /* NR ul */
+  int nr_ul_rnti;
+  int nr_ul_frame;
+  int nr_ul_slot;
+  int nr_ul_data;
+  /* NR dl */
+  int nr_dl_rnti;
+  int nr_dl_frame;
+  int nr_dl_slot;
+  int nr_dl_data;
+  /* NR mib */
+  int nr_mib_frame;
+  int nr_mib_slot;
+  int nr_mib_data;
+  /* NR RAR */
+  int nr_rar_rnti;
+  int nr_rar_frame;
+  int nr_rar_slot;
+  int nr_rar_data;
+
   /* config */
   int no_mib;
   int no_sib;
@@ -58,8 +82,13 @@ typedef struct {
   int cur_sib;
 } ev_data;
 
-void trace(ev_data *d, int direction, int rnti_type, int rnti,
-           int frame, int subframe, void *buf, int bufsize, int preamble) {
+/****************************************************************************/
+/* LTE                                                                      */
+/****************************************************************************/
+
+void trace_lte(ev_data *d, int direction, int rnti_type, int rnti,
+        int frame, int subframe, void *buf, int bufsize, int preamble)
+{
   ssize_t ret;
   int fsf;
   int i;
@@ -100,15 +129,17 @@ void trace(ev_data *d, int direction, int rnti_type, int rnti,
   if (ret != d->buf.osize) abort();
 }
 
-void ul(void *_d, event e) {
+void ul(void *_d, event e)
+{
   ev_data *d = _d;
-  trace(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i,
-        e.e[d->ul_frame].i, e.e[d->ul_subframe].i,
-        e.e[d->ul_data].b, e.e[d->ul_data].bsize,
-        NO_PREAMBLE);
+  trace_lte(d, DIRECTION_UPLINK, C_RNTI, e.e[d->ul_rnti].i,
+            e.e[d->ul_frame].i, e.e[d->ul_subframe].i,
+            e.e[d->ul_data].b, e.e[d->ul_data].bsize,
+            NO_PREAMBLE);
 }
 
-void dl(void *_d, event e) {
+void dl(void *_d, event e)
+{
   ev_data *d = _d;
 
   if (e.e[d->dl_rnti].i == 0xffff) {
@@ -119,14 +150,15 @@ void dl(void *_d, event e) {
     d->cur_sib++;
   }
 
-  trace(d, DIRECTION_DOWNLINK,
-        e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i,
-        e.e[d->dl_frame].i, e.e[d->dl_subframe].i,
-        e.e[d->dl_data].b, e.e[d->dl_data].bsize,
-        NO_PREAMBLE);
+  trace_lte(d, DIRECTION_DOWNLINK,
+            e.e[d->dl_rnti].i != 0xffff ? C_RNTI : SI_RNTI, e.e[d->dl_rnti].i,
+            e.e[d->dl_frame].i, e.e[d->dl_subframe].i,
+            e.e[d->dl_data].b, e.e[d->dl_data].bsize,
+            NO_PREAMBLE);
 }
 
-void mib(void *_d, event e) {
+void mib(void *_d, event e)
+{
   ev_data *d = _d;
 
   if (d->no_mib) return;
@@ -134,30 +166,141 @@ void mib(void *_d, event e) {
   if (d->max_mib && d->cur_mib == d->max_mib) return;
 
   d->cur_mib++;
-  trace(d, DIRECTION_DOWNLINK, NO_RNTI, 0,
-        e.e[d->mib_frame].i, e.e[d->mib_subframe].i,
-        e.e[d->mib_data].b, e.e[d->mib_data].bsize,
-        NO_PREAMBLE);
+  trace_lte(d, DIRECTION_DOWNLINK, NO_RNTI, 0,
+            e.e[d->mib_frame].i, e.e[d->mib_subframe].i,
+            e.e[d->mib_data].b, e.e[d->mib_data].bsize,
+            NO_PREAMBLE);
+}
+
+void preamble(void *_d, event e)
+{
+  ev_data *d = _d;
+  trace_lte(d, DIRECTION_UPLINK, NO_RNTI, 0,
+            e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i,
+            NULL, 0,
+            e.e[d->preamble_preamble].i);
+}
+
+void rar(void *_d, event e)
+{
+  ev_data *d = _d;
+  trace_lte(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i,
+            e.e[d->rar_frame].i, e.e[d->rar_subframe].i,
+            e.e[d->rar_data].b, e.e[d->rar_data].bsize,
+            NO_PREAMBLE);
+}
+
+/****************************************************************************/
+/* NR                                                                       */
+/****************************************************************************/
+
+#define MAC_NR_START_STRING "mac-nr"
+
+#define MAC_NR_PAYLOAD_TAG    0x01
+#define MAC_NR_RNTI_TAG       0x02
+#define MAC_NR_FRAME_SLOT_TAG 0x07
+
+#define NR_FDD_RADIO 1
+#define NR_TDD_RADIO 2
+
+#define NR_DIRECTION_UPLINK   0
+#define NR_DIRECTION_DOWNLINK 1
+
+#define NR_NO_RNTI 0
+#define NR_RA_RNTI 2
+#define NR_C_RNTI  3
+
+void trace_nr(ev_data *d, int direction, int rnti_type, int rnti,
+        int frame, int slot, void *buf, int bufsize, int preamble)
+{
+  ssize_t ret;
+  int i;
+  d->buf.osize = 0;
+  PUTS(&d->buf, MAC_NR_START_STRING);
+  PUTC(&d->buf, NR_TDD_RADIO);
+  PUTC(&d->buf, direction);
+  PUTC(&d->buf, rnti_type);
+
+  if (rnti_type == NR_C_RNTI || rnti_type == NR_RA_RNTI) {
+    PUTC(&d->buf, MAC_NR_RNTI_TAG);
+    PUTC(&d->buf, (rnti>>8) & 255);
+    PUTC(&d->buf, rnti & 255);
+  }
+
+#if 0
+  /* for old versions of wireshark; not sure if correct */
+  int fsf = (frame << 4) + slot;
+  PUTC(&d->buf, 4 /* MAC_NR_FRAME_SUBFRAME_TAG */);
+  PUTC(&d->buf, (fsf>>8) & 255);
+  PUTC(&d->buf, fsf & 255);
+#else
+  PUTC(&d->buf, MAC_NR_FRAME_SLOT_TAG);
+  PUTC(&d->buf, (frame>>8) & 255);
+  PUTC(&d->buf, frame & 255);
+  PUTC(&d->buf, (slot>>8) & 255);
+  PUTC(&d->buf, slot & 255);
+#endif
+
+  PUTC(&d->buf, MAC_NR_PAYLOAD_TAG);
+
+  for (i = 0; i < bufsize; i++)
+    PUTC(&d->buf, ((char *)buf)[i]);
+
+  ret = sendto(d->socket, d->buf.obuf, d->buf.osize, 0,
+               (struct sockaddr *)&d->to, sizeof(struct sockaddr_in));
+
+  if (ret != d->buf.osize) abort();
 }
 
-void preamble(void *_d, event e) {
+void nr_ul(void *_d, event e)
+{
   ev_data *d = _d;
-  trace(d, DIRECTION_UPLINK, NO_RNTI, 0,
-        e.e[d->preamble_frame].i, e.e[d->preamble_subframe].i,
-        NULL, 0,
-        e.e[d->preamble_preamble].i);
+
+  trace_nr(d, NR_DIRECTION_UPLINK, NR_C_RNTI, e.e[d->nr_ul_rnti].i,
+           e.e[d->nr_ul_frame].i, e.e[d->nr_ul_slot].i,
+           e.e[d->nr_ul_data].b, e.e[d->nr_ul_data].bsize, NO_PREAMBLE);
 }
 
-void rar(void *_d, event e) {
+void nr_dl(void *_d, event e)
+{
   ev_data *d = _d;
-  trace(d, DIRECTION_DOWNLINK, RA_RNTI, e.e[d->rar_rnti].i,
-        e.e[d->rar_frame].i, e.e[d->rar_subframe].i,
-        e.e[d->rar_data].b, e.e[d->rar_data].bsize,
-        NO_PREAMBLE);
+
+  trace_nr(d, NR_DIRECTION_DOWNLINK, NR_C_RNTI, e.e[d->nr_dl_rnti].i,
+           e.e[d->nr_dl_frame].i, e.e[d->nr_dl_slot].i,
+           e.e[d->nr_dl_data].b, e.e[d->nr_dl_data].bsize, NO_PREAMBLE);
 }
 
+void nr_mib(void *_d, event e)
+{
+  ev_data *d = _d;
+
+  if (d->no_mib) return;
+
+  if (d->max_mib && d->cur_mib == d->max_mib) return;
+
+  d->cur_mib++;
+
+  trace_nr(d, NR_DIRECTION_DOWNLINK, NR_NO_RNTI, 0,
+           e.e[d->nr_mib_frame].i, e.e[d->nr_mib_slot].i,
+           e.e[d->nr_mib_data].b, e.e[d->nr_mib_data].bsize, NO_PREAMBLE);
+}
+
+void nr_rar(void *_d, event e)
+{
+  ev_data *d = _d;
+
+  trace_nr(d, NR_DIRECTION_DOWNLINK, NR_RA_RNTI, e.e[d->nr_rar_rnti].i,
+           e.e[d->nr_rar_frame].i, e.e[d->nr_rar_slot].i,
+           e.e[d->nr_rar_data].b, e.e[d->nr_rar_data].bsize, NO_PREAMBLE);
+}
+
+/****************************************************************************/
+/****************************************************************************/
+
 void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
-                int preamble_id, int rar_id) {
+                int preamble_id, int rar_id,
+                int nr_ul_id, int nr_dl_id, int nr_mib_id, int nr_rar_id)
+{
   database_event_format f;
   int i;
   d->ul_rnti           = -1;
@@ -174,10 +317,27 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
   d->preamble_frame    = -1;
   d->preamble_subframe = -1;
   d->preamble_preamble = -1;
-  d->rar_rnti           = -1;
-  d->rar_frame          = -1;
-  d->rar_subframe       = -1;
-  d->rar_data           = -1;
+  d->rar_rnti          = -1;
+  d->rar_frame         = -1;
+  d->rar_subframe      = -1;
+  d->rar_data          = -1;
+
+  d->nr_ul_rnti        = -1;
+  d->nr_ul_frame       = -1;
+  d->nr_ul_slot        = -1;
+  d->nr_ul_data        = -1;
+  d->nr_dl_rnti        = -1;
+  d->nr_dl_frame       = -1;
+  d->nr_dl_slot        = -1;
+  d->nr_dl_data        = -1;
+  d->nr_mib_frame      = -1;
+  d->nr_mib_slot       = -1;
+  d->nr_mib_data       = -1;
+  d->nr_rar_rnti       = -1;
+  d->nr_rar_frame      = -1;
+  d->nr_rar_slot       = -1;
+  d->nr_rar_data       = -1;
+
 #define G(var_name, var_type, var) \
   if (!strcmp(f.name[i], var_name)) { \
     if (strcmp(f.type[i], var_type)) goto error; \
@@ -247,6 +407,60 @@ void setup_data(ev_data *d, void *database, int ul_id, int dl_id, int mib_id,
   if (d->rar_rnti == -1 || d->rar_frame == -1 || d->rar_subframe == -1 ||
       d->rar_data == -1) goto error;
 
+  /* NR ul: rnti, frame, slot, data */
+  f = get_format(database, nr_ul_id);
+
+  for (i = 0; i < f.count; i++) {
+    G("rnti",  "int",    d->nr_ul_rnti);
+    G("frame", "int",    d->nr_ul_frame);
+    G("slot",  "int",    d->nr_ul_slot);
+    G("data",  "buffer", d->nr_ul_data);
+  }
+
+  if (d->nr_ul_rnti == -1 || d->nr_ul_frame == -1 || d->nr_ul_slot == -1 ||
+      d->nr_ul_data == -1)
+    goto error;
+
+  /* NR dl: rnti, frame, slot, data */
+  f = get_format(database, nr_dl_id);
+
+  for (i = 0; i < f.count; i++) {
+    G("rnti",  "int",    d->nr_dl_rnti);
+    G("frame", "int",    d->nr_dl_frame);
+    G("slot",  "int",    d->nr_dl_slot);
+    G("data",  "buffer", d->nr_dl_data);
+  }
+
+  if (d->nr_dl_rnti == -1 || d->nr_dl_frame == -1 || d->nr_dl_slot == -1 ||
+      d->nr_dl_data == -1)
+    goto error;
+
+  /* NR MIB: frame, slot, data */
+  f = get_format(database, nr_mib_id);
+
+  for (i = 0; i < f.count; i++) {
+    G("frame", "int",    d->nr_mib_frame);
+    G("slot",  "int",    d->nr_mib_slot);
+    G("data",  "buffer", d->nr_mib_data);
+  }
+
+  if (d->nr_mib_frame == -1 || d->nr_mib_slot== -1 || d->nr_mib_data == -1)
+    goto error;
+
+  /* NR RAR: rnti, frame, slot, data */
+  f = get_format(database, nr_rar_id);
+
+  for (i = 0; i < f.count; i++) {
+    G("rnti",  "int",    d->nr_rar_rnti);
+    G("frame", "int",    d->nr_rar_frame);
+    G("slot",  "int",    d->nr_rar_slot);
+    G("data",  "buffer", d->nr_rar_data);
+  }
+
+  if (d->nr_rar_rnti == -1 || d->nr_rar_frame == -1 || d->nr_rar_slot == -1 ||
+      d->nr_rar_data == -1)
+    goto error;
+
 #undef G
   return;
 error:
@@ -254,7 +468,8 @@ error:
   abort();
 }
 
-void *receiver(void *_d) {
+void *receiver(void *_d)
+{
   ev_data *d = _d;
   int s;
   char buf[100000];
@@ -279,7 +494,8 @@ void *receiver(void *_d) {
   return 0;
 }
 
-void usage(void) {
+void usage(void)
+{
   printf(
     "options:\n"
     "    -d <database file>        this option is mandatory\n"
@@ -304,14 +520,16 @@ void usage(void) {
   exit(1);
 }
 
-int main(int n, char **v) {
+int main(int n, char **v)
+{
   char *database_filename = NULL;
   char *input_filename = NULL;
   void *database;
   event_handler *h;
   int in;
   int i;
-  int ul_id, dl_id, mib_id = -1, preamble_id, rar_id;
+  int ul_id, dl_id, mib_id, preamble_id, rar_id;
+  int nr_ul_id, nr_dl_id, nr_mib_id, nr_rar_id;
   ev_data d;
   char *ip = DEFAULT_IP;
   int port = DEFAULT_PORT;
@@ -382,6 +600,11 @@ int main(int n, char **v) {
     on_off(database, "ENB_PHY_INITIATE_RA_PROCEDURE", is_on, 1);
     on_off(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA", is_on, 1);
 
+    on_off(database, "GNB_MAC_UL_PDU_WITH_DATA", is_on, 1);
+    on_off(database, "GNB_MAC_DL_PDU_WITH_DATA", is_on, 1);
+    on_off(database, "GNB_PHY_MIB", is_on, 1);
+    on_off(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA", is_on, 1);
+
     /* activate selected traces */
     if (socket_send(in, &mt, 1) == -1 ||
         socket_send(in, &number_of_events, sizeof(int)) == -1 ||
@@ -398,12 +621,26 @@ int main(int n, char **v) {
   mib_id = event_id_from_name(database, "ENB_PHY_MIB");
   preamble_id = event_id_from_name(database, "ENB_PHY_INITIATE_RA_PROCEDURE");
   rar_id = event_id_from_name(database, "ENB_MAC_UE_DL_RAR_PDU_WITH_DATA");
-  setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id);
+
+  nr_ul_id = event_id_from_name(database, "GNB_MAC_UL_PDU_WITH_DATA");
+  nr_dl_id = event_id_from_name(database, "GNB_MAC_DL_PDU_WITH_DATA");
+  nr_mib_id = event_id_from_name(database, "GNB_PHY_MIB");
+  nr_rar_id = event_id_from_name(database, "GNB_MAC_DL_RAR_PDU_WITH_DATA");
+
+  setup_data(&d, database, ul_id, dl_id, mib_id, preamble_id, rar_id,
+             nr_ul_id, nr_dl_id, nr_mib_id, nr_rar_id);
+
   register_handler_function(h, ul_id, ul, &d);
   register_handler_function(h, dl_id, dl, &d);
   register_handler_function(h, mib_id, mib, &d);
   register_handler_function(h, preamble_id, preamble, &d);
   register_handler_function(h, rar_id, rar, &d);
+
+  register_handler_function(h, nr_ul_id, nr_ul, &d);
+  register_handler_function(h, nr_dl_id, nr_dl, &d);
+  register_handler_function(h, nr_mib_id, nr_mib, &d);
+  register_handler_function(h, nr_rar_id, nr_rar, &d);
+
   d.socket = socket(AF_INET, SOCK_DGRAM, 0);
 
   if (d.socket == -1) {
@@ -424,8 +661,10 @@ int main(int n, char **v) {
 
     if (e.type == -1) break;
 
-    if (!(e.type == ul_id || e.type == dl_id || e.type == mib_id ||
-          e.type == preamble_id || e.type == rar_id)) continue;
+    if (!(e.type == ul_id       || e.type == dl_id    || e.type == mib_id ||
+          e.type == preamble_id || e.type == rar_id   ||
+          e.type == nr_ul_id    || e.type == nr_dl_id ||
+          e.type == nr_mib_id   || e.type == nr_rar_id)) continue;
 
     handle_event(h, e);
   }
diff --git a/common/utils/asn1_conversions.h b/common/utils/asn1_conversions.h
index 050c065d9d548bf5874c6d9fb58f4d80f2e09b66..82dca54c0825744504bebf715c2eb283bc377a9d 100644
--- a/common/utils/asn1_conversions.h
+++ b/common/utils/asn1_conversions.h
@@ -101,11 +101,11 @@ static inline uint64_t BIT_STRING_to_uint64(BIT_STRING_t *asn) {
 
   shift = ((asn->size - 1) * 8) - asn->bits_unused;
   for (index = 0; index < (asn->size - 1); index++) {
-    result |= asn->buf[index] << shift;
+    result |= ((uint64_t)asn->buf[index]) << shift;
     shift -= 8;
   }
 
-  result |= asn->buf[index] >> asn->bits_unused;
+  result |= ((uint64_t)asn->buf[index]) >> asn->bits_unused;
 
   return result;
 }
diff --git a/common/utils/telnetsrv/telnetsrv_proccmd.c b/common/utils/telnetsrv/telnetsrv_proccmd.c
index 9dd512091d73331c73940a4bf604018a50e56577..6a0da678e2c639e8a7255a4fbe7aafb3ad8fa1bb 100644
--- a/common/utils/telnetsrv/telnetsrv_proccmd.c
+++ b/common/utils/telnetsrv/telnetsrv_proccmd.c
@@ -121,9 +121,11 @@ char toksep[2];
               case SCHED_RR:
                    lptr+=sprintf(lptr,"%s ","rt: rr");
               break;
+#ifdef SCHED_DEADLINE
               case SCHED_DEADLINE:
                    lptr+=sprintf(lptr,"%s ","rt: deadline");
               break;
+#endif
               default:
                    lptr+=sprintf(lptr,"%s ","????");
               break;
diff --git a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
index 10058c441e908e6327ad9bb3ff6d8d5f1334e2ce..67b9d8e9dd6420ab2d869e8379aa91128a3d9900 100644
--- a/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
+++ b/nfapi/open-nFAPI/nfapi/public_inc/fapi_nr_ue_interface.h
@@ -170,6 +170,7 @@ typedef struct {
   uint8_t  prach_format;
   /// Num RA
   uint8_t  num_ra;
+  uint8_t  prach_slot;
   uint8_t  prach_start_symbol;
   /// 38.211 (NCS 38.211 6.3.3.1).
   uint16_t num_cs;
@@ -179,6 +180,8 @@ typedef struct {
   uint8_t  restricted_set;
   /// see TS 38.211 (6.3.3.2).
   uint16_t freq_msg1;
+  // When multiple SSBs per RO is configured, this indicates which one is selected in this RO -> this is used to properly compute the PRACH preamble
+  uint8_t ssb_nb_in_ro;
   // nfapi_nr_ul_beamforming_t beamforming;
 } fapi_nr_ul_config_prach_pdu;
 
diff --git a/openair1/PHY/INIT/nr_parms.c b/openair1/PHY/INIT/nr_parms.c
index c37ba49308bda57b0e165751e35e77dbdef79185..7847859314dd387d576804f7ed46e51d55ba55f7 100644
--- a/openair1/PHY/INIT/nr_parms.c
+++ b/openair1/PHY/INIT/nr_parms.c
@@ -400,7 +400,7 @@ int nr_init_frame_parms_ue(NR_DL_FRAME_PARMS *fp,
     fp->Lmax = 64;
   }
 
-  fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[1].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
+  fp->L_ssb = (((uint64_t) config->ssb_table.ssb_mask_list[0].ssb_mask)<<32) | config->ssb_table.ssb_mask_list[1].ssb_mask;
   
   fp->N_ssb = 0;
   for (int p=0; p<fp->Lmax; p++)
diff --git a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
index 42f88d16f4a5e9a3e6ce20ec69e2f2183d7dae97..a528eb734ce53349bc77a15429817878e941b8a0 100644
--- a/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
+++ b/openair1/PHY/NR_TRANSPORT/nr_ulsch_decoding.c
@@ -478,7 +478,12 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
 
   NR_gNB_ULSCH_t                       *ulsch                 = phy_vars_gNB->ulsch[UE_id][0];
   NR_UL_gNB_HARQ_t                     *harq_process          = ulsch->harq_processes[harq_pid];
-  
+
+  if (!harq_process) {
+    LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n");
+    return 1;
+  }
+
   t_nrLDPC_dec_params decParams;
   t_nrLDPC_dec_params* p_decParams    = &decParams;
 
@@ -488,11 +493,6 @@ uint32_t nr_ulsch_decoding(PHY_VARS_gNB *phy_vars_gNB,
   phy_vars_gNB->nbDecode = 0;
   harq_process->processedSegments = 0;
 
-  if (!harq_process) {
-    LOG_E(PHY,"ulsch_decoding.c: NULL harq_process pointer\n");
-    return 1; 
-  }
-
   double   Coderate = 0.0;
   
   // ------------------------------------------------------------------
diff --git a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
index 621f5ef806b78c96b8ffda1f6a14d580dc8906e0..465598d46859e50e3c185c40bad2b7808dfc5594 100644
--- a/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
+++ b/openair1/PHY/NR_UE_TRANSPORT/nr_prach.c
@@ -71,7 +71,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
 
   int16_t Ncp = 0, amp, *prach, *prach2, *prachF, *Xu;
   int32_t Xu_re, Xu_im;
-  int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k;
+  int prach_start, prach_sequence_length, i, prach_len, dftlen, mu, kbar, K, n_ra_prb, k, prachStartSymbol, sample_offset_slot;
   //int restricted_Type;
 
   prach                   = prach_tmp;
@@ -94,7 +94,7 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
   kbar                    = 1;
   K                       = 24;
   k                       = 12*n_ra_prb - 6*fp->N_RB_UL;
-  //prachStartSymbol     = prach_config_pdu->prach_start_symbol
+  prachStartSymbol        = prach_pdu->prach_start_symbol;
   //restricted_Type         = 0;
 
   compute_nr_prach_seq(nrUE_config->prach_config.prach_sequence_length,
@@ -102,7 +102,8 @@ int32_t generate_nr_prach(PHY_VARS_NR_UE *ue, uint8_t gNB_id, uint8_t slot){
                        nrUE_config->prach_config.num_prach_fd_occasions_list[fd_occasion].prach_root_sequence_index,
                        ue->X_u);
 
-  prach_start = fp->get_samples_slot_timestamp(slot, fp, 0);
+  sample_offset_slot = (prachStartSymbol==0?0:fp->ofdm_symbol_size*prachStartSymbol+fp->nb_prefix_samples0+fp->nb_prefix_samples*(prachStartSymbol-1));
+  prach_start = fp->get_samples_slot_timestamp(slot, fp, 0) + sample_offset_slot;
 
   // First compute physical root sequence
   /************************************************************************
diff --git a/openair1/SCHED_NR/phy_procedures_nr_gNB.c b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
index 914e691669e4858524643799cae5ef662c9f5c60..39f097a3bcb213f6442cc07296d24f6f8311f462 100644
--- a/openair1/SCHED_NR/phy_procedures_nr_gNB.c
+++ b/openair1/SCHED_NR/phy_procedures_nr_gNB.c
@@ -113,7 +113,15 @@ void nr_common_signal_procedures (PHY_VARS_gNB *gNB,int frame, int slot) {
 	  nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[n_hf][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
         else
 	  nr_generate_pbch_dmrs(gNB->nr_gold_pbch_dmrs[0][ssb_index&7],&txdataF[0][txdataF_offset], AMP, ssb_start_symbol, cfg, fp);
-	
+
+        if (T_ACTIVE(T_GNB_PHY_MIB)) {
+          unsigned char bch[3];
+          bch[0] = gNB->ssb_pdu.ssb_pdu_rel15.bchPayload & 0xff;
+          bch[1] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 8) & 0xff;
+          bch[2] = (gNB->ssb_pdu.ssb_pdu_rel15.bchPayload >> 16) & 0xff;
+          T(T_GNB_PHY_MIB, T_INT(0) /* module ID */, T_INT(frame), T_INT(slot), T_BUFFER(bch, 3));
+        }
+
 	nr_generate_pbch(&gNB->pbch,
 	                 &gNB->ssb_pdu,
 	                 gNB->nr_pbch_interleaver,
diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index 6e648f3fc01bcc363cb00f83938c00118a217fae..a6dd9fb8c77b6c19f0c7e19a28ceba6c22ed7929 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -218,7 +218,7 @@ void phy_procedures_nrUE_TX(PHY_VARS_NR_UE *ue,
 
   /* RACH */
   if (get_softmodem_params()->do_ra==1) {
-    if ((ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) {
+    if ((ue->UE_mode[gNB_id] > NOT_SYNCHED && ue->UE_mode[gNB_id] < PUSCH) && (ue->prach_vars[gNB_id]->prach_Config_enabled == 1)) {
       nr_ue_prach_procedures(ue, proc, gNB_id, mode);
     }
   }
@@ -896,6 +896,9 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
        int *dlsch_errors,
        runmode_t mode) {
 
+  if (dlsch0==NULL)
+    AssertFatal(0,"dlsch0 should be defined at this level \n");
+
   int harq_pid = dlsch0->current_harq_pid;
   int frame_rx = proc->frame_rx;
   int nr_tti_rx = proc->nr_tti_rx;
@@ -923,9 +926,6 @@ void nr_ue_dlsch_procedures(PHY_VARS_NR_UE *ue,
   uint16_t bw_scaling, start_symbol;
   float tc_factor;
 
-  if (dlsch0==NULL)
-    AssertFatal(0,"dlsch0 should be defined at this level \n");
-
   is_cw0_active = dlsch0->harq_processes[harq_pid]->status;
   nb_symb_sch = dlsch0->harq_processes[harq_pid]->nb_symbols;
   start_symbol = dlsch0->harq_processes[harq_pid]->start_symbol;
@@ -1354,9 +1354,9 @@ void *UE_thread_slot1_dl_processing(void *arg) {
   CPU_ZERO(&cpuset);
   if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.slot1_proc_one != -1 )
     CPU_SET(threads.slot1_proc_one, &cpuset);
-  if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 )
+  if ( RX_NB_TH > 1 && (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.slot1_proc_two != -1 )
     CPU_SET(threads.slot1_proc_two, &cpuset);
-  if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 )
+  if ( RX_NB_TH > 2 && (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.slot1_proc_three != -1 )
     CPU_SET(threads.slot1_proc_three, &cpuset);
 
   init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
@@ -1823,24 +1823,48 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
   if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_IN);
     nr_ue_pdsch_procedures(ue,
-                          proc,
-                          gNB_id,
-                          SI_PDSCH,
-                          ue->dlsch_SI[gNB_id],
-                          NULL);
+                           proc,
+                           gNB_id,
+                           SI_PDSCH,
+                           ue->dlsch_SI[gNB_id],
+                           NULL);
     
+    nr_ue_dlsch_procedures(ue,
+                           proc,
+                           gNB_id,
+                           SI_PDSCH,
+                           ue->dlsch_SI[gNB_id],
+                           NULL,
+                           &ue->dlsch_SI_errors[gNB_id],
+                           mode);
+
+    // deactivate dlsch once dlsch proc is done
+    ue->dlsch_SI[gNB_id]->active = 0;
+
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_SI, VCD_FUNCTION_OUT);
   }
 
-  // do procedures for SI-RNTI
+  // do procedures for P-RNTI
   if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_IN);
     nr_ue_pdsch_procedures(ue,
-                          proc,
-                          gNB_id,
-                          P_PDSCH,
-                          ue->dlsch_p[gNB_id],
-                          NULL);
+                           proc,
+                           gNB_id,
+                           P_PDSCH,
+                           ue->dlsch_p[gNB_id],
+                           NULL);
+
+    nr_ue_dlsch_procedures(ue,
+                           proc,
+                           gNB_id,
+                           P_PDSCH,
+                           ue->dlsch_p[gNB_id],
+                           NULL,
+                           &ue->dlsch_p_errors[gNB_id],
+                           mode);
+
+    // deactivate dlsch once dlsch proc is done
+    ue->dlsch_p[gNB_id]->active = 0;
 
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_P, VCD_FUNCTION_OUT);
   }
@@ -1849,15 +1873,11 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
   if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1)) {
     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_IN);
     nr_ue_pdsch_procedures(ue,
-                          proc,
-                          gNB_id,
-                          RA_PDSCH,
-                          ue->dlsch_ra[gNB_id],
-                          NULL);
-
-    // #if UE_TIMING_TRACE
-    //   start_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]);
-    // #endif
+                           proc,
+                           gNB_id,
+                           RA_PDSCH,
+                           ue->dlsch_ra[gNB_id],
+                           NULL);
 
     nr_ue_dlsch_procedures(ue,
                            proc,
@@ -1868,18 +1888,10 @@ int phy_procedures_nrUE_RX(PHY_VARS_NR_UE *ue,
                            &ue->dlsch_ra_errors[gNB_id],
                            mode);
 
-     // #if UE_TIMING_TRACE
-     //   stop_meas(&ue->dlsch_procedures_stat[ue->current_thread_id[nr_tti_rx]]);
-     #if DISABLE_LOG_X
-      printf("[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[nr_tti_rx]].p_time/(cpuf*1000.0));
-      printf("[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0));
-     #else
-      LOG_D(PHY, "[SFN %d] Slot1: Pdsch Proc %5.2f\n", nr_tti_rx, ue->pdsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0));
-      LOG_D(PHY, "[SFN %d] Slot0 Slot1: Dlsch Proc %5.2f\n", nr_tti_rx, ue->dlsch_procedures_stat[ue->current_thread_id[ nr_tti_rx]].p_time/(cpuf*1000.0));
-     #endif
-     // #endif
-
-     VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT);
+    // deactivate dlsch once dlsch proc is done
+    ue->dlsch_ra[gNB_id]->active = 0;
+
+    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PDSCH_PROC_RA, VCD_FUNCTION_OUT);
   }
     
   // do procedures for C-RNTI
@@ -1946,71 +1958,8 @@ start_meas(&ue->generic_stat);
   }
 #endif
 
-  // do procedures for SI-RNTI
-  if ((ue->dlsch_SI[gNB_id]) && (ue->dlsch_SI[gNB_id]->active == 1)) {
-    nr_ue_pdsch_procedures(ue,
-			   proc,
-			   gNB_id,
-			   SI_PDSCH,
-			   ue->dlsch_SI[gNB_id],
-			   NULL);
-
-    /*ue_dlsch_procedures(ue,
-      proc,
-      gNB_id,
-      SI_PDSCH,
-      ue->dlsch_SI[gNB_id],
-      NULL,
-      &ue->dlsch_SI_errors[gNB_id],
-      mode,
-      abstraction_flag);
-    ue->dlsch_SI[gNB_id]->active = 0;*/
-  }
-
-  // do procedures for P-RNTI
-  if ((ue->dlsch_p[gNB_id]) && (ue->dlsch_p[gNB_id]->active == 1)) {
-    nr_ue_pdsch_procedures(ue,
-			   proc,
-			   gNB_id,
-			   P_PDSCH,
-			   ue->dlsch_p[gNB_id],
-			   NULL);
-
-
-    /*ue_dlsch_procedures(ue,
-      proc,
-      gNB_id,
-      P_PDSCH,
-      ue->dlsch_p[gNB_id],
-      NULL,
-      &ue->dlsch_p_errors[gNB_id],
-      mode,
-      abstraction_flag);*/
-    ue->dlsch_p[gNB_id]->active = 0;
-  }
-  // do procedures for RA-RNTI
-  if ((ue->dlsch_ra[gNB_id]) && (ue->dlsch_ra[gNB_id]->active == 1)) {
-    nr_ue_pdsch_procedures(ue,
-			   proc,
-			   gNB_id,
-			   RA_PDSCH,
-			   ue->dlsch_ra[gNB_id],
-			   NULL);
-
-    /*ue_dlsch_procedures(ue,
-      proc,
-      gNB_id,
-      RA_PDSCH,
-      ue->dlsch_ra[gNB_id],
-      NULL,
-      &ue->dlsch_ra_errors[gNB_id],
-      mode,
-      abstraction_flag);*/
-    ue->dlsch_ra[gNB_id]->active = 0;
-  }
-
   // duplicate harq structure
-  /*
+/*
   uint8_t          current_harq_pid        = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->current_harq_pid;
   NR_DL_UE_HARQ_t *current_harq_processes = ue->dlsch[ue->current_thread_id[nr_tti_rx]][gNB_id][0]->harq_processes[current_harq_pid];
   NR_DL_UE_HARQ_t *harq_processes_dest    = ue->dlsch[next1_thread_id][gNB_id][0]->harq_processes[current_harq_pid];
@@ -2138,6 +2087,11 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
 
   VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_PHY_PROCEDURES_UE_TX_PRACH, VCD_FUNCTION_IN);
 
+  if (!prach_resources->init_msg1 && (frame_tx == (ue->prach_resources[gNB_id]->sync_frame + 150) % MAX_FRAME_NUMBER)){
+    ue->prach_cnt = 0;
+    prach_resources->init_msg1 = 1;
+  }
+
   if (ue->mac_enabled == 0){
     //    prach_resources->ra_PreambleIndex = preamble_tx;
     prach_resources->ra_TDD_map_index = 0;
@@ -2154,15 +2108,10 @@ void nr_ue_prach_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, uint8_t
           ue->ulsch_Msg3_active[i] = 0;
         }
       }
-      nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx);
+      nr_prach = nr_ue_get_rach(ue->prach_resources[gNB_id], &ue->prach_vars[0]->prach_pdu, mod_id, ue->CC_id, UE_mode, frame_tx, gNB_id, nr_tti_tx);
     }
   }
 
-  if (!prach_resources->init_msg1 && (frame_tx > ue->prach_resources[gNB_id]->sync_frame + 150)){
-    ue->prach_cnt = 0;
-    prach_resources->init_msg1 = 1;
-  }
-
   if (ue->prach_resources[gNB_id] != NULL && nr_prach == 1 && prach_resources->init_msg1) {
 
     pathloss = get_nr_PL(mod_id, ue->CC_id, gNB_id);
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
index 2b662e4808f297d69998610a328510e79ef872d7..fdf13f453ca5f24f3c68670be69fb5c548484141 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.c
@@ -948,6 +948,24 @@ int get_format0(uint8_t index,
   return format;
 }
 
+int64_t *get_prach_config_info(uint32_t pointa,
+                               uint8_t index,
+                               uint8_t unpaired) {
+  int64_t *prach_config_info_p;
+
+  if (pointa > 2016666) { //FR2
+    prach_config_info_p = table_6_3_3_2_4_prachConfig_Index[index];
+  }
+  else { // FR1
+    if (unpaired)
+      prach_config_info_p = table_6_3_3_2_3_prachConfig_Index[index];
+    else
+      prach_config_info_p = table_6_3_3_2_2_prachConfig_Index[index];
+  } // FR2 / FR1
+
+  return prach_config_info_p;
+}
+
 void find_monitoring_periodicity_offset_common(NR_SearchSpace_t *ss,
                                                uint16_t *slot_period,
                                                uint16_t *offset) {
diff --git a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
index a67a676075bf3ab22fea4cf6767fa136d70fc712..f31723a7d660dd25ac4008a2aea0070d00d913e7 100644
--- a/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
+++ b/openair2/LAYER2/NR_MAC_COMMON/nr_mac_common.h
@@ -36,6 +36,36 @@
 #include "NR_CellGroupConfig.h"
 #include "nr_mac.h"
 
+
+// ===============================================
+// SSB to RO mapping public defines and structures
+// ===============================================
+#define MAX_SSB_PER_RO (16) // Maximum number of SSBs that can be mapped to a single RO
+#define MAX_TDM (7) // Maximum nb of PRACH occasions TDMed in a slot
+#define MAX_FDM (8) // Maximum nb of PRACH occasions FDMed in a slot
+
+// PRACH occasion details
+typedef struct prach_occasion_info {
+  uint8_t start_symbol; // 0 - 13 (14 symbols in a slot)
+  uint8_t fdm; // 0-7 (possible values of msg1-FDM: 1, 2, 4 or 8)
+  uint8_t slot; // 0 - 159 (maximum number of slots in a 10ms frame - @ 240kHz)
+  uint8_t frame; // 0 - 15 (maximum number of frames in a 160ms association pattern)
+  uint8_t mapped_ssb_idx[MAX_SSB_PER_RO]; // List of mapped SSBs
+  uint8_t nb_mapped_ssb;
+  uint16_t format; // RO preamble format
+} prach_occasion_info_t;
+
+// PRACH occasion slot details
+// A PRACH occasion slot is a series of PRACH occasions in time (symbols) and frequency
+typedef struct prach_occasion_slot {
+  prach_occasion_info_t prach_occasion[MAX_TDM][MAX_FDM]; // Starting symbol of each PRACH occasions in a slot
+  uint8_t nb_of_prach_occasion_in_time;
+  uint8_t nb_of_prach_occasion_in_freq;
+} prach_occasion_slot_t;
+
+// ========================================
+
+
 typedef enum {
   NR_DL_DCI_FORMAT_1_0 = 0,
   NR_DL_DCI_FORMAT_1_1,
@@ -135,6 +165,10 @@ int ul_ant_bits(NR_DMRS_UplinkConfig_t *NR_DMRS_UplinkConfig,long transformPreco
 
 int get_format0(uint8_t index, uint8_t unpaired);
 
+int64_t *get_prach_config_info(uint32_t pointa,
+                               uint8_t index,
+                               uint8_t unpaired);
+
 uint16_t get_NCS(uint8_t index, uint16_t format, uint8_t restricted_set_config);
 
 int get_num_dmrs(uint16_t dmrs_mask );
diff --git a/openair2/LAYER2/NR_MAC_UE/config_ue.c b/openair2/LAYER2/NR_MAC_UE/config_ue.c
index 239d83728b7ff28578c7931b7bd884cafd8996f7..7f98af2453867c86bb18cc1196e539f5abad073e 100755
--- a/openair2/LAYER2/NR_MAC_UE/config_ue.c
+++ b/openair2/LAYER2/NR_MAC_UE/config_ue.c
@@ -236,8 +236,8 @@ void config_common_ue(NR_UE_MAC_INST_t *mac,
       cfg->ssb_table.ssb_mask_list[0].ssb_mask = 0;
       cfg->ssb_table.ssb_mask_list[1].ssb_mask = 0;
       for (i=0; i<4; i++) {
-        cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8);
-        cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8);
+        cfg->ssb_table.ssb_mask_list[0].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i]<<i*8);
+        cfg->ssb_table.ssb_mask_list[1].ssb_mask += (scc->ssb_PositionsInBurst->choice.longBitmap.buf[i+4]<<i*8);
       }
       break;
     default:
@@ -426,6 +426,9 @@ int nr_rrc_mac_config_req_ue(
 	LOG_I(MAC,"Configuring CRNTI %x\n",mac->crnti);
       }
 
+      // Setup the SSB to Rach Occasions mapping according to the config
+      build_ssb_to_ro_map(mac->scc, mac->phy_config.config_req.cell_config.frame_duplex_type);
+
       /*      
       if(mac_cell_group_configP != NULL){
 	if(mac_cell_group_configP->drx_Config != NULL ){
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index 4126b19b0bec445d05797d0d45c78b111c0a2a20..3844695222c02dc24d8a55600867dd1ac95c0b3a 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -267,6 +267,7 @@ andom-access to transmit a BSR along with the C-RNTI control element (see 5.1.4
 @param nr_tti_tx slot for PRACH transmission
 @returns indication to generate PRACH to phy */
 uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
+                       fapi_nr_ul_config_prach_pdu *prach_pdu,
                        module_id_t mod_id,
                        int CC_id,
                        UE_MODE_t UE_mode,
@@ -278,15 +279,14 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
 @param module_idP Index of UE instance
 @param CC_id Component Carrier Index
 @param gNB_index gNB index
-@param t_id
 @param rach_ConfigDedicated
 @returns void */
 void nr_get_prach_resources(module_id_t mod_id,
                             int CC_id,
                             uint8_t gNB_id,
-                            uint8_t t_id,
                             uint8_t first_Msg3,
                             NR_PRACH_RESOURCES_t *prach_resources,
+                            fapi_nr_ul_config_prach_pdu *prach_pdu,
                             NR_RACH_ConfigDedicated_t * rach_ConfigDedicated);
 
 void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id);
@@ -305,5 +305,8 @@ void get_num_re_dmrs(nfapi_nr_ue_pusch_pdu_t *pusch_pdu,
                      uint8_t *nb_dmrs_re_per_rb,
                      uint16_t *number_dmrs_symbols);
 
+void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired);
+
+
 #endif
 /** @}*/
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
index 117e5d2970fa5dcdb3ebe6a8cca8bdfc999a0db5..f54aa711f5c4af003293ed4e86755d7626975c87 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ra_procedures.c
@@ -75,9 +75,9 @@ void nr_get_RA_window(NR_UE_MAC_INST_t *mac);
 void nr_get_prach_resources(module_id_t mod_id,
                             int CC_id,
                             uint8_t gNB_id,
-                            uint8_t t_id,
                             uint8_t first_Msg3,
                             NR_PRACH_RESOURCES_t *prach_resources,
+                            fapi_nr_ul_config_prach_pdu *prach_pdu,
                             NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){
 
   NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
@@ -87,8 +87,8 @@ void nr_get_prach_resources(module_id_t mod_id,
 
   // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo
 
-  int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, i, deltaPreamble_Msg3 = 0;
-  uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size;
+  int messagePowerOffsetGroupB = 0, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA = 0, numberOfRA_Preambles, deltaPreamble_Msg3 = 0;
+  uint8_t noGroupB = 0, s_id, t_id, f_id, ul_carrier_id, Msg3_size;
 
   AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id);
   nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
@@ -100,6 +100,7 @@ void nr_get_prach_resources(module_id_t mod_id,
   //////////* UE Random Access Resource Selection *//////////
   ///////////////////////////////////////////////////////////
 
+
   // todo: 
   // - switch initialisation cases
   // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321)
@@ -129,12 +130,81 @@ void nr_get_prach_resources(module_id_t mod_id,
 
     // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
 
+    // Determine the SSB to RACH mapping ratio
+    // =======================================
+    NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
+    boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
+    uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
+    long cb_preambles_per_ssb; // Nb of preambles per SSB
+    int total_preambles_per_ssb;
+    int starting_preamble_nb = 0;
+    uint8_t ssb_nb_in_ro;
+
+    switch (ssb_perRACH_config){
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
+        multiple_ssb_per_ro = false;
+        ssb_rach_ratio = 8;
+        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
+        break;
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
+        multiple_ssb_per_ro = false;
+        ssb_rach_ratio = 4;
+        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
+        break;
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
+        multiple_ssb_per_ro = false;
+        ssb_rach_ratio = 2;
+        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
+        break;
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
+        multiple_ssb_per_ro = true;
+        ssb_rach_ratio = 1;
+        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
+        break;
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
+        multiple_ssb_per_ro = true;
+        ssb_rach_ratio = 2;
+        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
+        break;
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
+        multiple_ssb_per_ro = true;
+        ssb_rach_ratio = 4;
+        cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.four;
+        break;
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
+        multiple_ssb_per_ro = true;
+        ssb_rach_ratio = 8;
+        cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.eight;
+        break;
+      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
+        multiple_ssb_per_ro = true;
+        ssb_rach_ratio = 16;
+        cb_preambles_per_ssb = nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.sixteen;
+        break;
+      default:
+        AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
+        break;
+    }
+
     Msg3_size = mac->RA_Msg3_size;
 
     numberOfRA_Preambles = 64;
     if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
       numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
 
+    // Compute the proper Preamble selection params according to the selected SSB and the ssb_perRACH_OccasionAndCB_PreamblesPerSSB configuration
+    if ((true == multiple_ssb_per_ro) &&
+        (ssb_rach_ratio > 1)) {
+      total_preambles_per_ssb = numberOfRA_Preambles / ssb_rach_ratio;
+
+      ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro;
+      starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro;
+    }
+    else {
+      total_preambles_per_ssb = numberOfRA_Preambles;
+      starting_preamble_nb = 0;
+    }
+
     if (!nr_rach_ConfigCommon->groupBconfigured) {
       noGroupB = 1;
     } else {
@@ -220,29 +290,30 @@ void nr_get_prach_resources(module_id_t mod_id,
     if (first_Msg3 == 1) {
       if (noGroupB == 1) {
         // use Group A preamble
-        prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
+        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
         mac->RA_usedGroupA = 1;
       } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) {
         // Group B is configured and RA preamble Group A is used
         // - todo add condition on CCCH_sdu_size for initiation by CCCH
-        prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
+        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
         mac->RA_usedGroupA = 1;
       } else {
         // Group B preamble is configured and used
         // the first sizeOfRA_PreamblesGroupA RA preambles belong to RA Preambles Group A
         // the remaining belong to RA Preambles Group B
-        prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
+        prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
         mac->RA_usedGroupA = 0;
       }
     } else { // Msg3 is being retransmitted
       if (mac->RA_usedGroupA == 1 && noGroupB == 1) {
-        prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
+        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
       } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){
-        prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
+        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
       } else {
-        prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
+        prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
       }
     }
+
     LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex);
   }
 
@@ -268,27 +339,16 @@ void nr_get_prach_resources(module_id_t mod_id,
    // 1) this does not apply to contention-free RA Preamble for beam failure recovery request
    // 2) getting star_symb, SFN_nbr from table 6.3.3.2-3 (TDD and FR1 scenario)
 
-   prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex;
-
    // ra_RNTI computation
-   // - todo: this is for TDD FR1 only
    // - ul_carrier_id: UL carrier used for RA preamble transmission, hardcoded for NUL carrier
    // - f_id: index of the PRACH occasion in the frequency domain
    // - s_id is starting symbol of the PRACH occasion [0...14]
    // - t_id is the first slot of the PRACH occasion in a system frame [0...80]
-
    ul_carrier_id = 0; // NUL
-   f_id = rach_ConfigGeneric->msg1_FrequencyStart;
-   SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4]; 
-   s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5];
-
-   // Pick the first slot of the PRACH occasion in a system frame
-   for (i = 0; i < 10; i++){
-    if (((SFN_nbr & (1 << i)) >> i) == 1){
-      t_id = 2*i;
-      break;
-    }
-   }
+   f_id = prach_pdu->num_ra;
+   t_id = prach_pdu->prach_slot;
+   s_id = prach_pdu->prach_start_symbol;
+
    prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
    mac->ra_rnti = prach_resources->ra_RNTI;
 
@@ -335,6 +395,7 @@ void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint
 // - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)
 
 uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
+                       fapi_nr_ul_config_prach_pdu *prach_pdu,
                        module_id_t mod_id,
                        int CC_id,
                        UE_MODE_t UE_mode,
@@ -363,7 +424,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
 
   AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n");
 
-  if (UE_mode < PUSCH && prach_resources->init_msg1) {
+  if (prach_resources->init_msg1) {
 
     LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active);
 
@@ -449,7 +510,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
 
         // Fill in preamble and PRACH resources
         if (mac->generate_nr_prach == 1)
-          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, rach_ConfigDedicated);
+          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
 
         offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus,              // sdus buffer
                                        (uint8_t *) payload,               // UL MAC pdu pointer
@@ -576,7 +637,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
 
         // Fill in preamble and PRACH resources
         if (mac->generate_nr_prach == 1)
-          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
+          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
 
       } else {
 
@@ -590,7 +651,7 @@ uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
 
         // Fill in preamble and PRACH resources
         if (mac->generate_nr_prach == 1)
-          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, rach_ConfigDedicated);
+          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_pdu, rach_ConfigDedicated);
 
       }
     }
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 766ce79536d757cf3f8d4b8f70006003df89661e..50296e045fd764f09e87bc546f02a3bbda53cfb3 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -64,6 +64,10 @@
 /* utils */
 #include "assertions.h"
 
+/* Tools */
+#include "asn1_conversions.h"
+#include "SIMULATION/TOOLS/sim.h" // for taus
+
 #include "common/utils/LOG/log.h"
 #include "SIMULATION/TOOLS/sim.h" // for taus
 #include "openair2/LAYER2/NR_MAC_COMMON/nr_mac.h"
@@ -72,12 +76,73 @@
 #include <stdio.h>
 #include <math.h>
 
+// ================================================
+// SSB to RO mapping private defines and structures
+// ================================================
+
+#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD (16) // Maximum association period is 16
+#define MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max association pattern period is 160ms and minimum PRACH configuration period is 10ms
+#define MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD (16) // Max nb of association periods in an association pattern period of 160ms
+#define MAX_NB_FRAME_IN_PRACH_CONF_PERIOD (16) // Max PRACH configuration period is 160ms and frame is 10ms
+#define MAX_NB_SLOT_IN_FRAME (160) // Max number of slots in a frame (@ SCS 240kHz = 160)
+#define MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD (16) // Maximum number of frames in the maximum association pattern period
+#define MAX_NB_SSB (64) // Maximum number of possible SSB indexes
+#define MAX_RO_PER_SSB (8) // Maximum number of consecutive ROs that can be mapped to an SSB according to the ssb_per_RACH config
+
+// Maximum number of ROs that can be mapped to an SSB in an association pattern
+// This is to reserve enough elements in the SSBs list for each mapped ROs for a single SSB
+// An arbitrary maximum number is chosen to be safe: maximum number of slots in an association pattern * maximum number of ROs in a slot
+#define MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN (MAX_TDM*MAX_FDM*MAX_NB_SLOT_IN_FRAME*MAX_NB_FRAME_IN_ASSOCIATION_PATTERN_PERIOD)
+
+// The PRACH Config period is a series of selected slots in one or multiple frames
+typedef struct prach_conf_period {
+  prach_occasion_slot_t prach_occasion_slot_map[MAX_NB_FRAME_IN_PRACH_CONF_PERIOD][MAX_NB_SLOT_IN_FRAME];
+  uint16_t nb_of_prach_occasion; // Total number of PRACH occasions in the PRACH Config period
+  uint8_t nb_of_frame; // Size of the PRACH Config period in number of 10ms frames
+  uint8_t nb_of_slot; // Nb of slots in each frame
+} prach_conf_period_t;
+
+// The association period is a series of PRACH Config periods
+typedef struct prach_association_period {
+  prach_conf_period_t *prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PERIOD];
+  uint8_t nb_of_prach_conf_period; // Nb of PRACH configuration periods within the association period
+  uint8_t nb_of_frame; // Total number of frames included in the association period
+} prach_association_period_t;
+
+// The association pattern is a series of Association periods
+typedef struct prach_association_pattern {
+  prach_association_period_t prach_association_period_list[MAX_NB_ASSOCIATION_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD];
+  prach_conf_period_t prach_conf_period_list[MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD];
+  uint8_t nb_of_assoc_period; // Nb of association periods within the association pattern
+  uint8_t nb_of_prach_conf_period_in_max_period; // Nb of PRACH configuration periods within the maximum association pattern period (according to the size of the configured PRACH
+  uint8_t nb_of_frame; // Total number of frames included in the association pattern period (after mapping the SSBs and determining the real association pattern length)
+} prach_association_pattern_t;
+
+// SSB details
+typedef struct ssb_info {
+  boolean_t transmitted; // True if the SSB index is transmitted according to the SSB positions map configuration
+  prach_occasion_info_t *mapped_ro[MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN]; // List of mapped RACH Occasions to this SSB index
+  uint16_t nb_mapped_ro; // Total number of mapped ROs to this SSB index
+} ssb_info_t;
+
+// List of all the possible SSBs and their details
+typedef struct ssb_list_info {
+  ssb_info_t tx_ssb[MAX_NB_SSB];
+  uint8_t   nb_tx_ssb;
+} ssb_list_info_t;
+
+static prach_association_pattern_t prach_assoc_pattern;
+static ssb_list_info_t ssb_list;
+
+// ===============================================
+// ===============================================
+
 //#define ENABLE_MAC_PAYLOAD_DEBUG 1
 #define DEBUG_EXTRACT_DCI 1
 
 extern int bwp_id;
 extern dci_pdu_rel15_t *def_dci_pdu_rel15;
-extern const uint16_t nr_slots_per_frame[5];
+extern const uint8_t nr_slots_per_frame[5];
 
 extern void mac_rlc_data_ind     (
 				  const module_id_t         module_idP,
@@ -92,6 +157,617 @@ extern void mac_rlc_data_ind     (
 				  num_tb_t                  num_tbP,
 				  crc_t                    *crcs_pP);
 
+// Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config
+static void build_ro_list(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired) {
+
+  int x,y; // PRACH Configuration Index table variables used to compute the valid frame numbers
+  int y2;  // PRACH Configuration Index table additional variable used to compute the valid frame numbers
+  uint8_t slot_shift_for_map;
+  uint8_t map_shift;
+  boolean_t even_slot_invalid;
+  int64_t s_map;
+  uint8_t prach_conf_start_symbol; // Starting symbol of the PRACH occasions in the PRACH slot
+  uint8_t N_t_slot; // Number of PRACH occasions in a 14-symbols PRACH slot
+  uint8_t N_dur; // Duration of a PRACH occasion (nb of symbols)
+  uint8_t frame; // Maximum is NB_FRAMES_IN_MAX_ASSOCIATION_PATTERN_PERIOD
+  uint8_t slot; // Maximum is the number of slots in a frame @ SCS 240kHz
+  uint16_t format = 0xffff;
+  uint8_t format2 = 0xff;
+  int nb_fdm;
+
+  uint8_t config_index, mu;
+  uint32_t pointa;
+  int msg1_FDM;
+
+  uint8_t prach_conf_period_idx;
+  uint8_t nb_of_frames_per_prach_conf_period;
+  uint8_t prach_conf_period_frame_idx;
+  int64_t *prach_config_info_p;
+
+  NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
+  NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
+  NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
+
+  config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
+
+  if (setup->msg1_SubcarrierSpacing)
+    mu = *setup->msg1_SubcarrierSpacing;
+  else
+    mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
+
+  pointa = frequencyInfoDL->absoluteFrequencyPointA;
+  msg1_FDM = rach_ConfigGeneric->msg1_FDM;
+
+  switch (msg1_FDM){
+    case 0:
+    case 1:
+    case 2:
+    case 3:
+      nb_fdm = 1 << msg1_FDM;
+      break;
+    default:
+      AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", msg1_FDM);
+  }
+
+  // Create the PRACH occasions map
+  // ==============================
+  // WIP: For now assume no rejected PRACH occasions because of conflict with SSB or TDD_UL_DL_ConfigurationCommon schedule
+
+  // Identify the proper PRACH Configuration Index table according to the operating frequency
+  LOG_D(MAC,"Pointa %u, mu = %u, PRACH config index  = %u, unpaired = %u\n", pointa, mu, config_index, unpaired);
+
+  prach_config_info_p = get_prach_config_info(pointa, config_index, unpaired);
+
+  if (pointa > 2016666) { //FR2
+
+    x = prach_config_info_p[2];
+    y = prach_config_info_p[3];
+    y2 = prach_config_info_p[4];
+
+    s_map = prach_config_info_p[5];
+
+    prach_conf_start_symbol = prach_config_info_p[6];
+    N_t_slot = prach_config_info_p[8];
+    N_dur = prach_config_info_p[9];
+    if (prach_config_info_p[1] != -1)
+      format2 = (uint8_t) prach_config_info_p[1];
+    format = ((uint8_t) prach_config_info_p[0]) | (format2<<8);
+
+    slot_shift_for_map = mu-2;
+    if ( (mu == 3) && (prach_config_info_p[7] == 1) )
+      even_slot_invalid = true;
+    else
+      even_slot_invalid = false;
+  }
+  else { // FR1
+    x = prach_config_info_p[2];
+    y = prach_config_info_p[3];
+    y2 = y;
+
+    s_map = prach_config_info_p[4];
+
+    prach_conf_start_symbol = prach_config_info_p[5];
+    N_t_slot = prach_config_info_p[7];
+    N_dur = prach_config_info_p[8];
+    if (prach_config_info_p[1] != -1)
+      format2 = (uint8_t) prach_config_info_p[1];
+    format = ((uint8_t) prach_config_info_p[0]) | (format2<<8);
+
+    slot_shift_for_map = mu;
+    if ( (mu == 1) && (prach_config_info_p[6] <= 1) )
+      // no prach in even slots @ 30kHz for 1 prach per subframe
+      even_slot_invalid = true;
+    else
+      even_slot_invalid = false;
+  } // FR2 / FR1
+
+  prach_assoc_pattern.nb_of_prach_conf_period_in_max_period = MAX_NB_PRACH_CONF_PERIOD_IN_ASSOCIATION_PATTERN_PERIOD / x;
+  nb_of_frames_per_prach_conf_period = x;
+
+  LOG_D(MAC,"nb_of_prach_conf_period_in_max_period %d\n", prach_assoc_pattern.nb_of_prach_conf_period_in_max_period);
+
+  // Fill in the PRACH occasions table for every slot in every frame in every PRACH configuration periods in the maximum association pattern period
+  // ----------------------------------------------------------------------------------------------------------------------------------------------
+  // ----------------------------------------------------------------------------------------------------------------------------------------------
+  // For every PRACH configuration periods
+  // -------------------------------------
+  for (prach_conf_period_idx=0; prach_conf_period_idx<prach_assoc_pattern.nb_of_prach_conf_period_in_max_period; prach_conf_period_idx++) {
+    prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion = 0;
+    prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_frame = nb_of_frames_per_prach_conf_period;
+    prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_slot = nr_slots_per_frame[mu];
+
+    LOG_D(MAC,"PRACH Conf Period Idx %d\n", prach_conf_period_idx);
+
+    // For every frames in a PRACH configuration period
+    // ------------------------------------------------
+    for (prach_conf_period_frame_idx=0; prach_conf_period_frame_idx<nb_of_frames_per_prach_conf_period; prach_conf_period_frame_idx++) {
+      frame = (prach_conf_period_idx * nb_of_frames_per_prach_conf_period) + prach_conf_period_frame_idx;
+
+      LOG_D(MAC,"PRACH Conf Period Frame Idx %d - Frame %d\n", prach_conf_period_frame_idx, frame);
+      // Is it a valid frame for this PRACH configuration index? (n_sfn mod x = y)
+      if ( (frame%x)==y || (frame%x)==y2 ) {
+
+        // For every slot in a frame
+        // -------------------------
+        for (slot=0; slot<nr_slots_per_frame[mu]; slot++) {
+          // Is it a valid slot?
+          map_shift = slot >> slot_shift_for_map; // in PRACH configuration index table slots are numbered wrt 60kHz
+          if ( (s_map>>map_shift)&0x01 ) {
+            // Valid slot
+
+            // Additionally, for 30kHz/120kHz, we must check for the n_RA_Slot param also
+            if ( even_slot_invalid && (slot%2 == 0) )
+                continue; // no prach in even slots @ 30kHz/120kHz for 1 prach per 60khz slot/subframe
+
+            // We're good: valid frame and valid slot
+            // Compute all the PRACH occasions in the slot
+
+            uint8_t n_prach_occ_in_time;
+            uint8_t n_prach_occ_in_freq;
+
+            prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time = N_t_slot;
+            prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq = nb_fdm;
+
+            for (n_prach_occ_in_time=0; n_prach_occ_in_time<N_t_slot; n_prach_occ_in_time++) {
+              uint8_t start_symbol = prach_conf_start_symbol + n_prach_occ_in_time * N_dur;
+              LOG_D(MAC,"PRACH Occ in time %d\n", n_prach_occ_in_time);
+
+              for (n_prach_occ_in_freq=0; n_prach_occ_in_freq<nb_fdm; n_prach_occ_in_freq++) {
+                prach_occasion_info_t *prach_occasion_p = &prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].prach_occasion[n_prach_occ_in_time][n_prach_occ_in_freq];
+
+                prach_occasion_p->start_symbol = start_symbol;
+                prach_occasion_p->fdm = n_prach_occ_in_freq;
+                prach_occasion_p->frame = frame;
+                prach_occasion_p->slot = slot;
+                prach_occasion_p->format = format;
+                prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion++;
+
+                LOG_D(MAC,"Adding a PRACH occasion: frame %u, slot-symbol %d-%d, occ_in_time-occ_in-freq %d-%d, nb ROs in conf period %d, for this slot: RO# in time %d, RO# in freq %d\n",
+                    frame, slot, start_symbol, n_prach_occ_in_time, n_prach_occ_in_freq, prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].nb_of_prach_occasion,
+                    prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_time,
+                    prach_assoc_pattern.prach_conf_period_list[prach_conf_period_idx].prach_occasion_slot_map[prach_conf_period_frame_idx][slot].nb_of_prach_occasion_in_freq);
+              } // For every freq in the slot
+            } // For every time occasions in the slot
+          } // Valid slot?
+        } // For every slots in a frame
+      } // Valid frame?
+    } // For every frames in a prach configuration period
+  } // For every prach configuration periods in the maximum association pattern period (160ms)
+}
+
+// Build the list of all the valid/transmitted SSBs according to the config
+static void build_ssb_list(NR_ServingCellConfigCommon_t *scc) {
+
+  // Create the list of transmitted SSBs
+  // ===================================
+  BIT_STRING_t *ssb_bitmap;
+  uint64_t ssb_positionsInBurst;
+  uint8_t ssb_idx = 0;
+
+  switch (scc->ssb_PositionsInBurst->present) {
+    case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_shortBitmap:
+      ssb_bitmap = &scc->ssb_PositionsInBurst->choice.shortBitmap;
+
+      ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap);
+      LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
+
+      for (uint8_t bit_nb=3; bit_nb<=3; bit_nb--) {
+        // If SSB is transmitted
+        if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
+          ssb_list.nb_tx_ssb++;
+          ssb_list.tx_ssb[ssb_idx].transmitted = true;
+          LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
+        }
+        ssb_idx++;
+      }
+      break;
+    case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_mediumBitmap:
+      ssb_bitmap = &scc->ssb_PositionsInBurst->choice.mediumBitmap;
+
+      ssb_positionsInBurst = BIT_STRING_to_uint8(ssb_bitmap);
+      LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
+
+      for (uint8_t bit_nb=7; bit_nb<=7; bit_nb--) {
+        // If SSB is transmitted
+        if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
+          ssb_list.nb_tx_ssb++;
+          ssb_list.tx_ssb[ssb_idx].transmitted = true;
+          LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
+        }
+        ssb_idx++;
+      }
+      break;
+    case NR_ServingCellConfigCommon__ssb_PositionsInBurst_PR_longBitmap:
+      ssb_bitmap = &scc->ssb_PositionsInBurst->choice.longBitmap;
+
+      ssb_positionsInBurst = BIT_STRING_to_uint64(ssb_bitmap);
+      LOG_D(MAC,"SSB config: SSB_positions_in_burst 0x%lx\n", ssb_positionsInBurst);
+
+      for (uint8_t bit_nb=63; bit_nb<=63; bit_nb--) {
+        // If SSB is transmitted
+        if ((ssb_positionsInBurst>>bit_nb) & 0x01) {
+          ssb_list.nb_tx_ssb++;
+          ssb_list.tx_ssb[ssb_idx].transmitted = true;
+          LOG_D(MAC,"SSB idx %d transmitted\n", ssb_idx);
+        }
+        ssb_idx++;
+      }
+      break;
+    default:
+      AssertFatal(false,"ssb_PositionsInBurst not present\n");
+      break;
+  }
+}
+
+// Map the transmitted SSBs to the ROs and create the association pattern according to the config
+static void map_ssb_to_ro(NR_ServingCellConfigCommon_t *scc) {
+
+  // Map SSBs to PRACH occasions
+  // ===========================
+  // WIP: Assumption: No PRACH occasion is rejected because of a conflict with SSBs or TDD_UL_DL_ConfigurationCommon schedule
+  NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
+  NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR ssb_perRACH_config = setup->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->present;
+
+  boolean_t multiple_ssb_per_ro; // true if more than one or exactly one SSB per RACH occasion, false if more than one RO per SSB
+  uint8_t ssb_rach_ratio; // Nb of SSBs per RACH or RACHs per SSB
+  uint16_t required_nb_of_prach_occasion; // Nb of RACH occasions required to map all the SSBs
+  uint8_t required_nb_of_prach_conf_period; // Nb of PRACH configuration periods required to map all the SSBs
+
+  // Determine the SSB to RACH mapping ratio
+  // =======================================
+  switch (ssb_perRACH_config){
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
+      multiple_ssb_per_ro = false;
+      ssb_rach_ratio = 8;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
+      multiple_ssb_per_ro = false;
+      ssb_rach_ratio = 4;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
+      multiple_ssb_per_ro = false;
+      ssb_rach_ratio = 2;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
+      multiple_ssb_per_ro = true;
+      ssb_rach_ratio = 1;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
+      multiple_ssb_per_ro = true;
+      ssb_rach_ratio = 2;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_four:
+      multiple_ssb_per_ro = true;
+      ssb_rach_ratio = 4;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_eight:
+      multiple_ssb_per_ro = true;
+      ssb_rach_ratio = 8;
+      break;
+    case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_sixteen:
+      multiple_ssb_per_ro = true;
+      ssb_rach_ratio = 16;
+      break;
+    default:
+      AssertFatal(1 == 0, "Unsupported ssb_perRACH_config %d\n", ssb_perRACH_config);
+      break;
+  }
+  LOG_D(MAC,"SSB rach ratio %d, Multiple SSB per RO %d\n", ssb_rach_ratio, multiple_ssb_per_ro);
+
+  // Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period
+  // ==============================================================================================================
+  // WIP: Assumption for now is that all the PRACH configuration periods within a maximum association pattern period have the same number of PRACH occasions
+  //      (No PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule)
+  //      There is only one possible association period which can contain up to 16 PRACH configuration periods
+  LOG_D(MAC,"Evaluate the number of PRACH configuration periods required to map all the SSBs and set the association period\n");
+  if (true == multiple_ssb_per_ro) {
+    required_nb_of_prach_occasion = ((ssb_list.nb_tx_ssb-1) + ssb_rach_ratio) / ssb_rach_ratio;
+  }
+  else {
+    required_nb_of_prach_occasion = ssb_list.nb_tx_ssb * ssb_rach_ratio;
+  }
+
+  required_nb_of_prach_conf_period = ((required_nb_of_prach_occasion-1) + prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion) / prach_assoc_pattern.prach_conf_period_list[0].nb_of_prach_occasion;
+
+  if (required_nb_of_prach_conf_period == 1) {
+    prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 1;
+  }
+  else if (required_nb_of_prach_conf_period == 2) {
+    prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 2;
+  }
+  else if (required_nb_of_prach_conf_period <= 4) {
+    prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 4;
+  }
+  else if (required_nb_of_prach_conf_period <= 8) {
+    prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 8;
+  }
+  else if (required_nb_of_prach_conf_period <= 16) {
+    prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period = 16;
+  }
+  else {
+    AssertFatal(1 == 0, "Invalid number of PRACH config periods within an association period %d\n", required_nb_of_prach_conf_period);
+  }
+
+  prach_assoc_pattern.nb_of_assoc_period = 1; // WIP: only one possible association period
+  prach_assoc_pattern.prach_association_period_list[0].nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period * prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame;
+  prach_assoc_pattern.nb_of_frame = prach_assoc_pattern.prach_association_period_list[0].nb_of_frame;
+
+  LOG_D(MAC,"Assoc period %d, Nb of frames in assoc period %d\n",
+        prach_assoc_pattern.prach_association_period_list[0].nb_of_prach_conf_period,
+        prach_assoc_pattern.prach_association_period_list[0].nb_of_frame);
+
+  // Proceed to the SSB to RO mapping
+  // ================================
+  uint8_t association_period_idx; // Association period index within the association pattern
+  uint8_t ssb_idx = 0;
+  uint8_t prach_configuration_period_idx; // PRACH Configuration period index within the association pattern
+  prach_conf_period_t *prach_conf_period_p;
+
+  // Map all the association periods within the association pattern period
+  LOG_D(MAC,"Proceed to the SSB to RO mapping\n");
+  for (association_period_idx=0; association_period_idx<prach_assoc_pattern.nb_of_assoc_period; association_period_idx++) {
+    uint8_t n_prach_conf=0; // PRACH Configuration period index within the association period
+    uint8_t frame=0;
+    uint8_t slot=0;
+    uint8_t ro_in_time=0;
+    uint8_t ro_in_freq=0;
+
+    // Set the starting PRACH Configuration period index in the association_pattern map for this particular association period
+    prach_configuration_period_idx = 0;  // WIP: only one possible association period so the starting PRACH configuration period is automatically 0
+
+    // Check if we need to map multiple SSBs per RO or multiple ROs per SSB
+    if (true == multiple_ssb_per_ro) {
+      // --------------------
+      // --------------------
+      // Multiple SSBs per RO
+      // --------------------
+      // --------------------
+
+      // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
+      //      this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
+      ssb_idx = 0;
+
+      // Go through the list of PRACH config periods within this association period
+      for (n_prach_conf=0; n_prach_conf<prach_assoc_pattern.prach_association_period_list[association_period_idx].nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) {
+        // Build the association period with its association PRACH Configuration indexes
+        prach_conf_period_p = &prach_assoc_pattern.prach_conf_period_list[prach_configuration_period_idx];
+        prach_assoc_pattern.prach_association_period_list[association_period_idx].prach_conf_period_list[n_prach_conf] = prach_conf_period_p;
+
+        // Go through all the ROs within the PRACH config period
+        for (frame=0; frame<prach_conf_period_p->nb_of_frame; frame++) {
+          for (slot=0; slot<prach_conf_period_p->nb_of_slot; slot++) {
+            for (ro_in_time=0; ro_in_time<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) {
+              for (ro_in_freq=0; ro_in_freq<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) {
+                prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq];
+
+                // Go through the list of transmitted SSBs and map the required amount of SSBs to this RO
+                // WIP: For the moment, only map each SSB idx once per association period if configuration is multiple SSBs per RO
+                //      this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
+                for (; ssb_idx<MAX_NB_SSB; ssb_idx++) {
+                  // Map only the transmitted ssb_idx
+                  if (true == ssb_list.tx_ssb[ssb_idx].transmitted) {
+                    ro_p->mapped_ssb_idx[ro_p->nb_mapped_ssb] = ssb_idx;
+                    ro_p->nb_mapped_ssb++;
+                    ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p;
+                    ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++;
+                    AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
+
+                    LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq);
+                    LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
+
+                    // If all the required SSBs are mapped to this RO, exit the loop of SSBs
+                    if (ro_p->nb_mapped_ssb == ssb_rach_ratio) {
+                      ssb_idx++;
+                      break;
+                    }
+                  } // if ssb_idx is transmitted
+                } // for ssb_idx
+
+                // Exit the loop of ROs if there is no more SSB to map
+                if (MAX_NB_SSB == ssb_idx) break;
+              } // for ro_in_freq
+
+              // Exit the loop of ROs if there is no more SSB to map
+              if (MAX_NB_SSB == ssb_idx) break;
+            } // for ro_in_time
+
+            // Exit the loop of slots if there is no more SSB to map
+            if (MAX_NB_SSB == ssb_idx) break;
+          } // for slot
+
+          // Exit the loop frames if there is no more SSB to map
+          if (MAX_NB_SSB == ssb_idx) break;
+        } // for frame
+
+        // Exit the loop of PRACH configurations if there is no more SSB to map
+        if (MAX_NB_SSB == ssb_idx) break;
+      } // for n_prach_conf
+
+      // WIP: note that there is no re-mapping of the SSBs within the association period since there is no invalid ROs in the PRACH config periods that would create this situation
+
+    } // if multiple_ssbs_per_ro
+
+    else {
+      // --------------------
+      // --------------------
+      // Multiple ROs per SSB
+      // --------------------
+      // --------------------
+
+      n_prach_conf = 0;
+
+      // Go through the list of transmitted SSBs
+      for (ssb_idx=0; ssb_idx<MAX_NB_SSB; ssb_idx++) {
+        uint8_t nb_mapped_ro_in_association_period=0; // Reset the nb of mapped ROs for the new SSB index
+
+        // Map only the transmitted ssb_idx
+        if (true == ssb_list.tx_ssb[ssb_idx].transmitted) {
+
+          // Map all the required ROs to this SSB
+          // Go through the list of PRACH config periods within this association period
+          for (; n_prach_conf<prach_assoc_pattern.prach_association_period_list[association_period_idx].nb_of_prach_conf_period; n_prach_conf++, prach_configuration_period_idx++) {
+
+            // Build the association period with its association PRACH Configuration indexes
+            prach_conf_period_p = &prach_assoc_pattern.prach_conf_period_list[prach_configuration_period_idx];
+            prach_assoc_pattern.prach_association_period_list[association_period_idx].prach_conf_period_list[n_prach_conf] = prach_conf_period_p;
+
+            for (; frame<prach_conf_period_p->nb_of_frame; frame++) {
+              for (; slot<prach_conf_period_p->nb_of_slot; slot++) {
+                for (; ro_in_time<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_time; ro_in_time++) {
+                  for (; ro_in_freq<prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq; ro_in_freq++) {
+                    prach_occasion_info_t *ro_p = &prach_conf_period_p->prach_occasion_slot_map[frame][slot].prach_occasion[ro_in_time][ro_in_freq];
+
+                    ro_p->mapped_ssb_idx[0] = ssb_idx;
+                    ro_p->nb_mapped_ssb = 1;
+                    ssb_list.tx_ssb[ssb_idx].mapped_ro[ssb_list.tx_ssb[ssb_idx].nb_mapped_ro] = ro_p;
+                    ssb_list.tx_ssb[ssb_idx].nb_mapped_ro++;
+                    AssertFatal(MAX_NB_RO_PER_SSB_IN_ASSOCIATION_PATTERN > ssb_list.tx_ssb[ssb_idx].nb_mapped_ro,"Too many mapped ROs (%d) to a single SSB\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro);
+                    nb_mapped_ro_in_association_period++;
+
+                    LOG_D(MAC,"Mapped ssb_idx %u to RO slot-symbol %u-%u, %u-%u-%u/%u\n", ssb_idx, ro_p->slot, ro_p->start_symbol, slot, ro_in_time, ro_in_freq, prach_conf_period_p->prach_occasion_slot_map[frame][slot].nb_of_prach_occasion_in_freq);
+                    LOG_D(MAC,"Nb mapped ROs for this ssb idx: in the association period only %u / total %u\n", ssb_list.tx_ssb[ssb_idx].nb_mapped_ro, nb_mapped_ro_in_association_period);
+
+                    // Exit the loop if this SSB has been mapped to all the required ROs
+                    // WIP: Assuming that ssb_rach_ratio equals the maximum nb of times a given ssb_idx is mapped within an association period:
+                    //      this is true if no PRACH occasions are conflicting with SSBs nor TDD_UL_DL_ConfigurationCommon schedule
+                    if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
+                      ro_in_freq++;
+                      break;
+                    }
+                  } // for ro_in_freq
+
+                  // Exit the loop if this SSB has been mapped to all the required ROs
+                  if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
+                    break;
+                  }
+                  else ro_in_freq = 0; // else go to the next time symbol in that slot and reset the freq index
+                } // for ro_in_time
+
+                // Exit the loop if this SSB has been mapped to all the required ROs
+                if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
+                  break;
+                }
+                else ro_in_time = 0; // else go to the next slot in that PRACH config period and reset the symbol index
+              } // for slot
+
+              // Exit the loop if this SSB has been mapped to all the required ROs
+              if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
+                break;
+              }
+              else slot = 0; // else go to the next frame in that PRACH config period and reset the slot index
+            } // for frame
+
+            // Exit the loop if this SSB has been mapped to all the required ROs
+            if (nb_mapped_ro_in_association_period == ssb_rach_ratio) {
+              break;
+            }
+            else frame = 0; // else go to the next PRACH config period in that association period and reset the frame index
+          } // for n_prach_conf
+
+        } // if ssb_idx is transmitted
+      } // for ssb_idx
+    } // else if multiple_ssbs_per_ro
+
+  } // for association_period_index
+}
+
+// Returns a RACH occasion if any matches the SSB idx, the frame and the slot
+static int get_nr_prach_info_from_ssb_index(uint8_t ssb_idx,
+                                            int frame,
+                                            int slot,
+                                            prach_occasion_info_t **prach_occasion_info_pp) {
+
+  ssb_info_t *ssb_info_p;
+  prach_occasion_slot_t *prach_occasion_slot_p = NULL;
+
+  *prach_occasion_info_pp = NULL;
+
+  // Search for a matching RO slot in the SSB_to_RO map
+  // A valid RO slot will match:
+  //      - ssb_idx mapped to one of the ROs in that RO slot
+  //      - exact slot number
+  //      - frame offset
+  ssb_info_p = &ssb_list.tx_ssb[ssb_idx];
+  for (uint8_t n_mapped_ro=0; n_mapped_ro<ssb_info_p->nb_mapped_ro; n_mapped_ro++) {
+    if ((slot == ssb_info_p->mapped_ro[n_mapped_ro]->slot) &&
+        (ssb_info_p->mapped_ro[n_mapped_ro]->frame == (frame % prach_assoc_pattern.nb_of_frame))) {
+
+      uint8_t prach_config_period_nb = ssb_info_p->mapped_ro[n_mapped_ro]->frame / prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame;
+      uint8_t frame_nb_in_prach_config_period = ssb_info_p->mapped_ro[n_mapped_ro]->frame % prach_assoc_pattern.prach_conf_period_list[0].nb_of_frame;
+      prach_occasion_slot_p = &prach_assoc_pattern.prach_conf_period_list[prach_config_period_nb].prach_occasion_slot_map[frame_nb_in_prach_config_period][slot];
+    }
+  }
+
+  // If there is a matching RO slot in the SSB_to_RO map
+  if (NULL != prach_occasion_slot_p)
+  {
+    // A random RO mapped to the SSB index should be selected in the slot
+
+    // First count the number of times the SSB index is found in that RO
+    uint8_t nb_mapped_ssb = 0;
+
+    for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
+      for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
+        prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq];
+
+        for (uint8_t ssb_nb=0; ssb_nb<prach_occasion_info_p->nb_mapped_ssb; ssb_nb++) {
+          if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
+            nb_mapped_ssb++;
+          }
+        }
+      }
+    }
+
+    // Choose a random SSB nb
+    uint8_t random_ssb_nb = 0;
+
+    random_ssb_nb = ((taus()) % nb_mapped_ssb);
+
+    // Select the RO according to the chosen random SSB nb
+    nb_mapped_ssb=0;
+    for (int ro_in_time=0; ro_in_time < prach_occasion_slot_p->nb_of_prach_occasion_in_time; ro_in_time++) {
+      for (int ro_in_freq=0; ro_in_freq < prach_occasion_slot_p->nb_of_prach_occasion_in_freq; ro_in_freq++) {
+        prach_occasion_info_t *prach_occasion_info_p = &prach_occasion_slot_p->prach_occasion[ro_in_time][ro_in_freq];
+
+        for (uint8_t ssb_nb=0; ssb_nb<prach_occasion_info_p->nb_mapped_ssb; ssb_nb++) {
+          if (prach_occasion_info_p->mapped_ssb_idx[ssb_nb] == ssb_idx) {
+            if (nb_mapped_ssb == random_ssb_nb) {
+              *prach_occasion_info_pp = prach_occasion_info_p;
+              return 1;
+            }
+            else {
+              nb_mapped_ssb++;
+            }
+          }
+        }
+      }
+    }
+  }
+
+  return 0;
+}
+
+// Build the SSB to RO mapping upon RRC configuration update
+void build_ssb_to_ro_map(NR_ServingCellConfigCommon_t *scc, uint8_t unpaired){
+
+  // Clear all the lists and maps
+  memset(&prach_assoc_pattern, 0, sizeof(prach_association_pattern_t));
+  memset(&ssb_list, 0, sizeof(ssb_list_info_t));
+
+  // Build the list of all the valid RACH occasions in the maximum association pattern period according to the PRACH config
+  LOG_D(MAC,"Build RO list\n");
+  build_ro_list(scc, unpaired);
+
+  // Build the list of all the valid/transmitted SSBs according to the config
+  LOG_D(MAC,"Build SSB list\n");
+  build_ssb_list(scc);
+
+  // Map the transmitted SSBs to the ROs and create the association pattern according to the config
+  LOG_D(MAC,"Map SSB to RO\n");
+  map_ssb_to_ro(scc);
+  LOG_D(MAC,"Map SSB to RO done\n");
+}
+
 void fill_scheduled_response(nr_scheduled_response_t *scheduled_response,
                              fapi_nr_dl_config_request_t *dl_config,
                              fapi_nr_ul_config_request_t *ul_config,
@@ -498,8 +1174,8 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
   SFN_C_TYPE sfn_c=SFN_C_IMPOSSIBLE;   //  only valid for mux=1
   uint32_t n_c=UINT_MAX;
   uint32_t number_of_search_space_per_slot=UINT_MAX;
-  uint32_t first_symbol_index=UINT_MAX;
-  uint32_t search_space_duration;  //  element of search space
+//  uint32_t first_symbol_index=UINT_MAX;
+//  uint32_t search_space_duration;  //  element of search space
   //  38.213 table 10.1-1
 
   /// MUX PATTERN 1
@@ -516,13 +1192,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
       sfn_c = SFN_C_MOD_2_EQ_0;
     }
 
-    if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (ssb_index&1)){
-      first_symbol_index = num_symbols;
-    }else{
-      first_symbol_index = table_38213_13_11_c4[index_4lsb];
-    }
+//    if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 7) && (ssb_index&1)){
+//      first_symbol_index = num_symbols;
+//    }else{
+//      first_symbol_index = table_38213_13_11_c4[index_4lsb];
+//    }
     //  38.213 chapter 13: over two consecutive slots
-    search_space_duration = 2;
+//    search_space_duration = 2;
   }
 
   if(mac->type0_pdcch_ss_mux_pattern == 1 && frequency_range == FR2){
@@ -530,13 +1206,13 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
     number_of_search_space_per_slot = table_38213_13_11_c2[index_4lsb];
     big_m = table_38213_13_12_c3[index_4lsb];
 
-    if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (ssb_index&1)){
-      first_symbol_index = 7;
-    }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (ssb_index&1)){
-      first_symbol_index = num_symbols;
-    }else{
-      first_symbol_index = 0;
-    }
+//    if((index_4lsb == 1 || index_4lsb == 3 || index_4lsb == 5 || index_4lsb == 10) && (ssb_index&1)){
+//      first_symbol_index = 7;
+//    }else if((index_4lsb == 6 || index_4lsb == 7 || index_4lsb == 8 || index_4lsb == 11) && (ssb_index&1)){
+//      first_symbol_index = num_symbols;
+//    }else{
+//      first_symbol_index = 0;
+//    }
     //  38.213 chapter 13: over two consecutive slots
     //search_space_duration = 2;
   }
@@ -550,21 +1226,21 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
       //  PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot
       //                sfn_c = SFN_C_EQ_SFN_SSB;
       n_c = get_ssb_slot(ssb_index);
-      switch(ssb_index & 0x3){    //  ssb_index(i) mod 4
-      case 0: 
-	first_symbol_index = 0;
-	break;
-      case 1: 
-	first_symbol_index = 1;
-	break;
-      case 2: 
-	first_symbol_index = 6;
-	break;
-      case 3: 
-	first_symbol_index = 7;
-	break;
-      default: break; 
-      }
+//      switch(ssb_index & 0x3){    //  ssb_index(i) mod 4
+//      case 0:
+//	first_symbol_index = 0;
+//	break;
+//      case 1:
+//	first_symbol_index = 1;
+//	break;
+//      case 2:
+//	first_symbol_index = 6;
+//	break;
+//      case 3:
+//	first_symbol_index = 7;
+//	break;
+//      default: break;
+//      }
                 
     }else if((scs_ssb == scs_240kHz) && (scs_pdcch == scs_120kHz)){
       //  38.213 Table 13-14
@@ -574,36 +1250,36 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
       n_c = get_ssb_slot(ssb_index);
       switch(ssb_index & 0x7){    //  ssb_index(i) mod 8
       case 0: 
-	first_symbol_index = 0;
+//	first_symbol_index = 0;
 	break;
       case 1: 
-	first_symbol_index = 1;
+//	first_symbol_index = 1;
 	break;
       case 2: 
-	first_symbol_index = 2;
+//	first_symbol_index = 2;
 	break;
       case 3: 
-	first_symbol_index = 3;
+//	first_symbol_index = 3;
 	break;
       case 4: 
-	first_symbol_index = 12;
+//	first_symbol_index = 12;
 	n_c = get_ssb_slot(ssb_index) - 1;
 	break;
       case 5: 
-	first_symbol_index = 13;
+//	first_symbol_index = 13;
 	n_c = get_ssb_slot(ssb_index) - 1;
 	break;
       case 6: 
-	first_symbol_index = 0;
+//	first_symbol_index = 0;
 	break;
       case 7: 
-	first_symbol_index = 1;
+//	first_symbol_index = 1;
 	break;
       default: break; 
       }
     }else{ ; }
     //  38.213 chapter 13: over one slot
-    search_space_duration = 1;
+//    search_space_duration = 1;
   }
 
   /// MUX PATTERN 3
@@ -614,24 +1290,24 @@ int8_t nr_ue_decode_mib(module_id_t module_id,
       //  PDCCH monitoring occasions (SFN and slot number) same as SSB frame-slot
       //                sfn_c = SFN_C_EQ_SFN_SSB;
       n_c = get_ssb_slot(ssb_index);
-      switch(ssb_index & 0x3){    //  ssb_index(i) mod 4
-      case 0: 
-	first_symbol_index = 4;
-	break;
-      case 1: 
-	first_symbol_index = 8;
-	break;
-      case 2: 
-	first_symbol_index = 2;
-	break;
-      case 3: 
-	first_symbol_index = 6;
-	break;
-      default: break; 
-      }
+//      switch(ssb_index & 0x3){    //  ssb_index(i) mod 4
+//      case 0:
+//	first_symbol_index = 4;
+//	break;
+//      case 1:
+//	first_symbol_index = 8;
+//	break;
+//      case 2:
+//	first_symbol_index = 2;
+//	break;
+//      case 3:
+//	first_symbol_index = 6;
+//	break;
+//      default: break;
+//      }
     }else{ ; }
     //  38.213 chapter 13: over one slot
-    search_space_duration = 1;
+//    search_space_duration = 1;
   }
 
   AssertFatal(number_of_search_space_per_slot!=UINT_MAX,"");
@@ -1066,18 +1742,14 @@ void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac,
 }
 
 // This function schedules the PRACH according to prach_ConfigurationIndex and TS 38.211, tables 6.3.3.2.x
-// It fills the PRACH PDU per each FD occasion.
 // PRACH formats 9, 10, 11 are corresponding to dual PRACH format configurations A1/B1, A2/B2, A3/B3.
 // - todo:
 // - Partial configuration is actually already stored in (fapi_nr_prach_config_t) &mac->phy_config.config_req->prach_config
 void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {
 
-  uint8_t config_index, mu, N_dur, N_t_slot, start_symbol;
-  uint16_t RA_sfn_index;
-  uint8_t N_RA_slot;
-  uint8_t config_period;
   uint16_t format, format0, format1, ncs;
-  int msg1_FDM, is_nr_prach_slot, fdm;
+  int is_nr_prach_slot;
+  prach_occasion_info_t *prach_occasion_info_p;
 
   NR_UE_MAC_INST_t *mac = get_mac_inst(module_idP);
 
@@ -1089,136 +1761,121 @@ void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t s
 
   NR_ServingCellConfigCommon_t *scc = mac->scc;
   NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
-  NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
   NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
-  config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
 
   mac->RA_offset = 2; // to compensate the rx frame offset at the gNB
   mac->generate_nr_prach = 0; // Reset flag for PRACH generation
 
   if (is_nr_UL_slot(scc, slotP)) {
 
-    if (setup->msg1_SubcarrierSpacing)
-      mu = *setup->msg1_SubcarrierSpacing;
-    else
-      mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;
-
-    is_nr_prach_slot = get_nr_prach_info_from_index(config_index,
-                                                    (int)frameP,
-                                                    (int)slotP,
-                                                    frequencyInfoDL->absoluteFrequencyPointA,
-                                                    mu,
-                                                    cfg->cell_config.frame_duplex_type,
-                                                    &format,
-                                                    &start_symbol,
-                                                    &N_t_slot,
-                                                    &N_dur,
-						    &RA_sfn_index,
-						    &N_RA_slot,
-						    &config_period);
+    // WIP Need to get the proper selected ssb_idx
+    //     Initial beam selection functionality is not available yet
+    uint8_t selected_gnb_ssb_idx = 0;
+
+    // Get any valid PRACH occasion in the current slot for the selected SSB index
+    is_nr_prach_slot = get_nr_prach_info_from_ssb_index(selected_gnb_ssb_idx,
+                                                       (int)frameP,
+                                                       (int)slotP,
+                                                        &prach_occasion_info_p);
 
     if (is_nr_prach_slot && mac->ra_state == RA_UE_IDLE) {
+      AssertFatal(NULL != prach_occasion_info_p,"PRACH Occasion Info not returned in a valid NR Prach Slot\n");
 
       mac->generate_nr_prach = 1;
 
-      fdm = rach_ConfigGeneric->msg1_FDM;
-
-      switch (fdm){
-        case 0:
-        case 1:
-        case 2:
-        case 3:
-          msg1_FDM = 1 << fdm;
-          break;
-        default:
-          AssertFatal(1 == 0, "Unknown msg1_FDM from rach_ConfigGeneric %d\n", fdm);
-      }
-
+      format = prach_occasion_info_p->format;
       format0 = format & 0xff;        // single PRACH format
       format1 = (format >> 8) & 0xff; // dual PRACH format
 
       ul_config->sfn = frameP;
       ul_config->slot = slotP;
 
-      for (int n = 0; n < msg1_FDM; n++) { // one structure per frequency domain occasion
-
-        ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH;
-        prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu;
-        memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu));
-        ul_config->number_pdus += 1;
-
-        ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig);
-
-        // filling PRACH PDU for FAPI config request
-        prach_config_pdu->phys_cell_id = *scc->physCellId;
-        prach_config_pdu->num_prach_ocas = N_t_slot;
-        prach_config_pdu->prach_start_symbol = start_symbol;
-        prach_config_pdu->num_ra = n;
-        prach_config_pdu->num_cs = ncs;
-        prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[n].prach_root_sequence_index;
-        prach_config_pdu->restricted_set = prach_config->restricted_set_config;
-        prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[n].k1;
-
-        if (format1 != 0xff) {
-          switch(format0) { // dual PRACH format
-            case 0xa1:
-              prach_config_pdu->prach_format = 11;
-              break;
-            case 0xa2:
-              prach_config_pdu->prach_format = 12;
-              break;
-            case 0xa3:
-              prach_config_pdu->prach_format = 13;
-              break;
+      ul_config->ul_config_list[ul_config->number_pdus].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PRACH;
+      prach_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus].prach_config_pdu;
+      memset(prach_config_pdu, 0, sizeof(fapi_nr_ul_config_prach_pdu));
+      ul_config->number_pdus += 1;
+
+      ncs = get_NCS(rach_ConfigGeneric->zeroCorrelationZoneConfig, format0, setup->restrictedSetConfig);
+
+      prach_config_pdu->phys_cell_id = *scc->physCellId;
+      prach_config_pdu->num_prach_ocas = 1;
+      prach_config_pdu->prach_slot = prach_occasion_info_p->slot;
+      prach_config_pdu->prach_start_symbol = prach_occasion_info_p->start_symbol;
+      prach_config_pdu->num_ra = prach_occasion_info_p->fdm;
+
+      prach_config_pdu->num_cs = ncs;
+      prach_config_pdu->root_seq_id = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].prach_root_sequence_index;
+      prach_config_pdu->restricted_set = prach_config->restricted_set_config;
+      prach_config_pdu->freq_msg1 = prach_config->num_prach_fd_occasions_list[prach_occasion_info_p->fdm].k1;
+
+      LOG_D(MAC,"Selected RO Frame %u, Slot %u, Symbol %u, Fdm %u\n", frameP, prach_config_pdu->prach_slot, prach_config_pdu->prach_start_symbol, prach_config_pdu->num_ra);
+
+      // Search which SSB is mapped in the RO (among all the SSBs mapped to this RO)
+      for (prach_config_pdu->ssb_nb_in_ro=0; prach_config_pdu->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb; prach_config_pdu->ssb_nb_in_ro++) {
+        if (prach_occasion_info_p->mapped_ssb_idx[prach_config_pdu->ssb_nb_in_ro] == selected_gnb_ssb_idx)
+          break;
+      }
+      AssertFatal(prach_config_pdu->ssb_nb_in_ro<prach_occasion_info_p->nb_mapped_ssb, "%u not found in the mapped SSBs to the PRACH occasion", selected_gnb_ssb_idx);
+
+      if (format1 != 0xff) {
+        switch(format0) { // dual PRACH format
+          case 0xa1:
+            prach_config_pdu->prach_format = 11;
+            break;
+          case 0xa2:
+            prach_config_pdu->prach_format = 12;
+            break;
+          case 0xa3:
+            prach_config_pdu->prach_format = 13;
+            break;
+        default:
+          AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
+        }
+      } else {
+        switch(format0) { // single PRACH format
+          case 0:
+            prach_config_pdu->prach_format = 0;
+            break;
+          case 1:
+            prach_config_pdu->prach_format = 1;
+            break;
+          case 2:
+            prach_config_pdu->prach_format = 2;
+            break;
+          case 3:
+            prach_config_pdu->prach_format = 3;
+            break;
+          case 0xa1:
+            prach_config_pdu->prach_format = 4;
+            break;
+          case 0xa2:
+            prach_config_pdu->prach_format = 5;
+            break;
+          case 0xa3:
+            prach_config_pdu->prach_format = 6;
+            break;
+          case 0xb1:
+            prach_config_pdu->prach_format = 7;
+            break;
+          case 0xb4:
+            prach_config_pdu->prach_format = 8;
+            break;
+          case 0xc0:
+            prach_config_pdu->prach_format = 9;
+            break;
+          case 0xc2:
+            prach_config_pdu->prach_format = 10;
+            break;
           default:
-            AssertFatal(1 == 0, "Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
-          }
-        } else {
-          switch(format0) { // single PRACH format
-            case 0:
-              prach_config_pdu->prach_format = 0;
-              break;
-            case 1:
-              prach_config_pdu->prach_format = 1;
-              break;
-            case 2:
-              prach_config_pdu->prach_format = 2;
-              break;
-            case 3:
-              prach_config_pdu->prach_format = 3;
-              break;
-            case 0xa1:
-              prach_config_pdu->prach_format = 4;
-              break;
-            case 0xa2:
-              prach_config_pdu->prach_format = 5;
-              break;
-            case 0xa3:
-              prach_config_pdu->prach_format = 6;
-              break;
-            case 0xb1:
-              prach_config_pdu->prach_format = 7;
-              break;
-            case 0xb4:
-              prach_config_pdu->prach_format = 8;
-              break;
-            case 0xc0:
-              prach_config_pdu->prach_format = 9;
-              break;
-            case 0xc2:
-              prach_config_pdu->prach_format = 10;
-              break;
-            default:
-              AssertFatal(1 == 0, "Invalid PRACH format");
-          }
+            AssertFatal(1 == 0, "Invalid PRACH format");
         }
-      }
-    }
+      } // if format1
+    } // is_nr_prach_slot
 
     fill_scheduled_response(&scheduled_response, NULL, ul_config, NULL, module_idP, 0 /*TBR fix*/, frameP, slotP);
     if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL)
       mac->if_module->scheduled_response(&scheduled_response);
-  }
+  } // if is_nr_UL_slot
 }
 
 ////////////////////////////////////////////////////////////////////////////
@@ -2233,7 +2890,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
 						      uint8_t time_domain_ind
 						      ){
   int dmrs_typeA_pos = mac->scc->dmrs_TypeA_Position;
-  uint8_t k_offset=0;
+//  uint8_t k_offset=0;
   uint8_t sliv_S=0;
   uint8_t sliv_L=0;
   uint8_t table_5_1_2_1_1_2_time_dom_res_alloc_A[16][3]={ // for PDSCH from TS 38.214 subclause 5.1.2.1.1
@@ -2374,7 +3031,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
       dlsch_config_pdu->number_symbols=L;
     }
     else {// Default configuration from tables
-      k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0];
+//      k_offset = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0];
       sliv_S   = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1];
       sliv_L   = table_5_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2];
       // k_offset = table_5_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
@@ -2417,7 +3074,7 @@ int8_t nr_ue_process_dci_time_dom_resource_assignment(NR_UE_MAC_INST_t *mac,
       pusch_config_pdu->nr_of_symbols=L;
     }
     else {
-      k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0];
+//      k_offset = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][0];
       sliv_S   = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][1];
       sliv_L   = table_6_1_2_1_1_2_time_dom_res_alloc_A[time_domain_ind-1][2];
       // k_offset = table_6_1_2_1_1_3_time_dom_res_alloc_A_extCP[nr_pdci_info_extracted->time_dom_resource_assignment][0];
diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c
index 06db41df9c62efafca92764701e8b06325e5c9e2..c81a1f79115a13a8c8ebbd68a82f4d3916aa8c8a 100644
--- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c
+++ b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c
@@ -274,15 +274,22 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
     if (ue_mac->RA_RAPID_found) {
 
       uint8_t freq_hopping, mcs, Msg3_t_alloc, Msg3_f_alloc;
-      unsigned char tpc_command, csi_req;
+      unsigned char tpc_command;
+#ifdef DEBUG_RAR
+      unsigned char csi_req;
+#endif
 
       // TC-RNTI
       *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
       ue_mac->t_crnti = *t_crnti;
       // TA command
       ta_command = rar->TA2 + (rar->TA1 << 5);
+
+#ifdef DEBUG_RAR
       // CSI
       csi_req = (unsigned char) (rar->UL_GRANT_4 & 0x01);
+#endif
+
       // TPC
       tpc_command = (unsigned char) ((rar->UL_GRANT_4 >> 1) & 0x07);
       switch (tpc_command){
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
index af40c9ccd8733c66cffc4e6039af751d971711c4..03e0ffa6fd446920714c31ed7aabe87356ea0cf5 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_RA.c
@@ -921,6 +921,10 @@ void nr_generate_Msg2(module_id_t module_idP,
     nr_mac->TX_req[CC_id].Slot = slotP;
     memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length);
 
+    T(T_GNB_MAC_DL_RAR_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_id),
+      T_INT(RA_rnti), T_INT(frameP), T_INT(slotP), T_INT(0) /* harq pid, meaningful? */,
+      T_BUFFER(&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length));
+
     /* mark the corresponding RBs as used */
     uint8_t *vrb_map = cc[CC_id].vrb_map;
     for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++)
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
index f1d1ed2b725d1c5483272928e3f58cfc3976acf7..640068ecaeb2256616c87ec8008af482a88c77c6 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_dlsch.c
@@ -840,6 +840,9 @@ void nr_schedule_ue_spec(module_id_t module_id,
       retInfo->mcs = sched_ctrl->mcs;
       retInfo->numDmrsCdmGrpsNoData = sched_ctrl->numDmrsCdmGrpsNoData;
 
+      T(T_GNB_MAC_DL_PDU_WITH_DATA, T_INT(module_id), T_INT(CC_id), T_INT(rnti),
+        T_INT(frame), T_INT(slot), T_INT(current_harq_pid), T_BUFFER(buf, TBS));
+
 #if defined(ENABLE_MAC_PAYLOAD_DEBUG)
       if (frame%100 == 0) {
         LOG_I(MAC,
diff --git a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
index 1c2371131569a4e2ad535f980cad63876b1338bc..2dc6f14c960f3a6cba02b345a5b87f89a3393781 100644
--- a/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
+++ b/openair2/LAYER2/NR_MAC_gNB/gNB_scheduler_ulsch.c
@@ -324,6 +324,12 @@ void nr_rx_sdu(const module_id_t gnb_mod_idP,
 
   NR_RA_t *ra = &gNB_mac->common_channels[CC_idP].ra[0];
 
+  if (sduP != NULL) {
+    T(T_GNB_MAC_UL_PDU_WITH_DATA, T_INT(gnb_mod_idP), T_INT(CC_idP),
+      T_INT(rntiP), T_INT(frameP), T_INT(slotP), T_INT(-1) /* harq_pid */,
+      T_BUFFER(sduP, sdu_lenP));
+  }
+
   // random access pusch with TC-RNTI
   if (ra->state == WAIT_Msg3) {
     if (sduP != NULL) { // if the CRC passed
diff --git a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
index 78a49e4604a1f300d433fb185e126c30a9d49e48..e1ae1df077de0b54168dc3c830da3a15b0ca890d 100644
--- a/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
+++ b/openair2/LAYER2/nr_rlc/nr_rlc_entity_am.c
@@ -922,6 +922,7 @@ static missing_data_t next_missing(nr_rlc_entity_am_t *entity,
        */
       ret.sn_start = entity->rx_next;
       ret.so_start = 0;
+      ret.next = cur;
       goto set_end_different_sdu;
     }
   }
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 60acb20ecbe18d553c2a854c7a9a8dc6ab90b5c4..6f081fa24ffe87cb61054bcaed03011724e0b5f4 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
@@ -45,7 +45,7 @@ gNBs =
         dl_carrierBandwidth                                            = 106;
      #initialDownlinkBWP
       #genericParameters
-        # this is RBstart=0,L=50 (275*(L-1))+RBstart
+        # this is RBstart=41,L=24 (275*(L-1))+RBstart
         initialDLBWPlocationAndBandwidth                                        = 6366;
 # subcarrierSpacing
 # 0=kHz15, 1=kHz30, 2=kHz60, 3=kHz120  
@@ -74,7 +74,7 @@ gNBs =
 
              initialDLBWPk0_3                    = 0;
              initialDLBWPmappingType_3           = 0;
-             #this is SS=1,L=4
+             #this is SS=1,L=5
              initialDLBWPstartSymbolAndLength_3  = 57;
 
   #uplinkConfigCommon 
@@ -135,18 +135,17 @@ gNBs =
         initialULBWPmappingType_0             = 1
         # this is SS=0 L=11
         initialULBWPstartSymbolAndLength_0    = 55;
- 	
-	initialULBWPk2_1                      = 6;
+
+        initialULBWPk2_1                      = 6;
         initialULBWPmappingType_1             = 1;
         # this is SS=0 L=12
         initialULBWPstartSymbolAndLength_1    = 69;
 
-	initialULBWPk2_2                      = 7;
+        initialULBWPk2_2                      = 7;
         initialULBWPmappingType_2             = 1;
         # this is SS=10 L=4
         initialULBWPstartSymbolAndLength_2    = 52;
 
-
         msg3_DeltaPreamble                                          = 1;
         p0_NominalWithGrant                                         =-90;