diff --git a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
index 9f0ac9ff200a1dff14c8cc3083e8610c3e51f8e6..b4b8b0fd71d323baf75dfbce69217a92dcf7eb67 100644
--- a/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
+++ b/openair1/SCHED_NR_UE/phy_procedures_nr_ue.c
@@ -2974,7 +2974,7 @@ void nr_ue_pdsch_procedures(PHY_VARS_NR_UE *ue, UE_nr_rxtx_proc_t *proc, int eNB
 void nr_process_rar(nr_downlink_indication_t *dl_info) {
 
   module_id_t module_id = dl_info->module_id;
-  int cc_id = dl_info->cc_id, frame_rx = dl_info->proc->frame_rx, nr_tti_rx = dl_info->proc->nr_tti_rx, ta_command, k2, delta;
+  int cc_id = dl_info->cc_id, frame_rx = dl_info->proc->frame_rx, nr_tti_rx = dl_info->proc->nr_tti_rx, ta_command, delta;
   uint8_t gNB_index = dl_info->gNB_index; // *rar;
   //fapi_nr_dci_indication_t *dci_ind = dl_info->dci_ind;
   PHY_VARS_NR_UE *ue = PHY_vars_UE_g[module_id][cc_id];
@@ -3015,6 +3015,7 @@ void nr_process_rar(nr_downlink_indication_t *dl_info) {
       ta_command = nr_ue_process_rar(ue->Mod_id,
                                      cc_id,
                                      frame_rx,
+                                     nr_tti_rx,
                                      dlsch0->harq_processes[0]->b,
                                      &ue->pdcch_vars[ue->current_thread_id[nr_tti_rx]][gNB_index]->pdcch_config[0].rnti,
                                      prach_resources->ra_PreambleIndex,
@@ -3031,13 +3032,6 @@ void nr_process_rar(nr_downlink_indication_t *dl_info) {
         nr_process_timing_advance_rar(ue, dl_info->proc, ta_command);
 
         if (ue->mode != debug_prach) {
-          ue->ulsch_Msg3_active[gNB_index] = 1;
-          // TS 38.213 ch 8.3 Msg3 PUSCH
-          // PUSCH time domain resource allocation A for normal CP
-          // TS 38.214 ch 6.1.2.1.1
-          k2 = table_6_1_2_1_1_2_time_dom_res_alloc_A[0][0];
-          sliv_S = table_6_1_2_1_1_2_time_dom_res_alloc_A[0][1];
-          sliv_L = table_6_1_2_1_1_2_time_dom_res_alloc_A[0][2];
 
           switch (mu_pusch) {
             case 0:
@@ -3054,28 +3048,10 @@ void nr_process_rar(nr_downlink_indication_t *dl_info) {
             break;
           }
 
-          ue->Msg3_startSymbol[gNB_index] = sliv_S;
-          ue->Msg3_Length[gNB_index] = sliv_L;
-          ue->ulsch_Msg3_subframe[gNB_index] = (nr_tti_rx + k2 + delta) % slots_per_frame;
-          if (nr_tti_rx + k2 + delta > slots_per_frame){
-            ue->ulsch_Msg3_frame[gNB_index] = (frame_rx + 1) % 1024;
-          } else {
-            ue->ulsch_Msg3_frame[gNB_index] = frame_rx;
-          }
+          #ifdef DEBUG_RA
+          LOG_D(PHY,"[UE %d][RAPROC] Msg3 nr_tti_rx %d delta %d\n", ue->Mod_id, nr_tti_rx, delta);
+          #endif
 
-          LOG_D(PHY,"[UE %d][RAPROC] Got Msg3_alloc Frame %d subframe %d: Msg3_frame %d, Msg3_subframe %d\n",
-                ue->Mod_id,
-                frame_rx,
-                nr_tti_rx,
-                ue->ulsch_Msg3_frame[gNB_index],
-                ue->ulsch_Msg3_subframe[gNB_index]);
-          // harq_pid = subframe2harq_pid(&ue->frame_parms,
-          //                              ue->ulsch_Msg3_frame[gNB_index],
-          //                              ue->ulsch_Msg3_subframe[gNB_index]);
-          // ue->ulsch[gNB_index]->harq_processes[harq_pid]->round = 0;
-          // ue->Msg3_timer[gNB_index] = 10;
-          // ue->ulsch[gNB_index].power_offset = 6;
-          // ue->ulsch_no_allocation_counter[gNB_index] = 0;
           ue->UE_mode[gNB_index] = RA_RESPONSE;
         }
       } else {
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_defs.h b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
index e45f6a9b695873b1bbb3ca8753150b6269a1379f..9b1b2835ce3dfce629227a3f23c271ef1aa97eaf 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_defs.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_defs.h
@@ -221,6 +221,10 @@ typedef struct {
   uint32_t RA_tx_frame;
   /// Random-access variable for window calculation (subframe of last change in window counter)
   uint8_t RA_tx_subframe;
+  /// Scheduled TX frame for RA Msg3
+  frame_t msg3_frame;
+  /// Scheduled TX slot for RA Msg3
+  slot_t msg3_slot;
   /// Random-access variable for backoff (frame of last change in backoff counter)
   uint32_t RA_backoff_frame;
   /// Random-access variable for backoff (subframe of last change in backoff counter)
diff --git a/openair2/LAYER2/NR_MAC_UE/mac_proto.h b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
index e9d7a97a5da2edc498caab32f8d65416b14de03c..4716c1b49ddde856202d50c1c684d9c68c36d0ad 100755
--- a/openair2/LAYER2/NR_MAC_UE/mac_proto.h
+++ b/openair2/LAYER2/NR_MAC_UE/mac_proto.h
@@ -197,6 +197,17 @@ and fills the PRACH PDU per each FD occasion.
 */
 void nr_ue_prach_scheduler(module_id_t module_idP, frame_t frameP, sub_frame_t slotP);
 
+/* \brief This function schedules the Msg3 transmission
+@param
+@param
+@param
+@returns void
+*/
+void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac,
+                          frame_t current_frame,
+                          sub_frame_t current_slot,
+                          uint8_t Msg3_tda_id);
+
 /* \brief Function called by PHY to process the received RAR and check that the preamble matches what was sent by the gNB. It provides the timing advance and t-CRNTI.
 @param Mod_id Index of UE instance
 @param CC_id Index to a component carrier
@@ -212,6 +223,7 @@ random-access procedure
 uint16_t nr_ue_process_rar(module_id_t mod_id,
                            int CC_id,
                            frame_t frameP,
+                           sub_frame_t slotP,
                            uint8_t * dlsch_buffer,
                            rnti_t * t_crnti,
                            uint8_t preamble_index,
diff --git a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
index 60f331a08627534f34b3d70d7718c83919b11175..0205b4e3f19974ad863a08f4963f7a45d960e94c 100644
--- a/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
+++ b/openair2/LAYER2/NR_MAC_UE/nr_ue_procedures.c
@@ -895,7 +895,6 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
       scheduled_response.slot       = rx_slot;
 
       scheduled_response.ul_config->slot = ul_info->slot_tx;
-      scheduled_response.ul_config->number_pdus = 1;
       scheduled_response.ul_config->ul_config_list[0].pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH;
       scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rnti = rnti;
       scheduled_response.ul_config->ul_config_list[0].pusch_config_pdu.rb_size = rb_size;
@@ -929,11 +928,122 @@ NR_UE_L2_STATE_t nr_ue_scheduler(nr_downlink_indication_t *dl_info, nr_uplink_in
       // Note: Contention resolution is currently not active
       if (mac->RA_contention_resolution_timer_active == 1)
         ue_contention_resolution(mod_id, gNB_index, cc_id, ul_info->frame_tx);
+
+    } else if (get_softmodem_params()->do_ra){
+
+      NR_UE_MAC_INST_t *mac = get_mac_inst(ul_info->module_id);
+
+      if (ul_info->slot_tx == mac->msg3_slot && ul_info->frame_tx == mac->msg3_frame){
+
+        uint8_t ulsch_input_buffer[MAX_ULSCH_PAYLOAD_BYTES];
+        nr_scheduled_response_t scheduled_response;
+        scheduled_response.ul_config = &mac->ul_config_request;
+        scheduled_response.dl_config = NULL;
+        scheduled_response.ul_config->number_pdus++; //TBR fix
+        fapi_nr_ul_config_request_pdu_t *ul_config_list = &scheduled_response.ul_config->ul_config_list[scheduled_response.ul_config->number_pdus - 1];
+        fapi_nr_tx_request_t tx_req;
+        fapi_nr_tx_request_body_t tx_req_body;
+
+        uint16_t TBS_bytes = scheduled_response.ul_config->ul_config_list[scheduled_response.ul_config->number_pdus - 1].pusch_config_pdu.pusch_data.tb_size;
+
+        //if (IS_SOFTMODEM_NOS1){
+        //  // Getting IP traffic to be transmitted
+        //  data_existing = nr_ue_get_sdu(mod_id,
+        //                                cc_id,
+        //                                frame_tx,
+        //                                slot_tx,
+        //                                0,
+        //                                ulsch_input_buffer,
+        //                                TBS_bytes,
+        //                                &access_mode);
+        //}
+
+        //Random traffic to be transmitted if there is no IP traffic available for this Tx opportunity
+        //if (!IS_SOFTMODEM_NOS1 || !data_existing) {
+          //Use zeros for the header bytes in noS1 mode, in order to make sure that the LCID is not valid
+          //and block this traffic from being forwarded to the upper layers at the gNB
+          printf("[DEBUG_MSG3] Random data to be tranmsitted (TBS_bytes %d, pdu_index %d ul_config (%p) list (%p): \n", TBS_bytes, scheduled_response.ul_config->number_pdus - 1, scheduled_response.ul_config, ul_config_list);
+          //Give the first byte a dummy value (a value not corresponding to any valid LCID based on 38.321, Table 6.2.1-2)
+          //in order to distinguish the PHY random packets at the MAC layer of the gNB receiver from the normal packets that should
+          //have a valid LCID (nr_process_mac_pdu function)
+          ulsch_input_buffer[0] = 0x31;
+          for (int i = 1; i < TBS_bytes; i++) {
+            ulsch_input_buffer[i] = (unsigned char) rand();
+            //printf(" input encoder a[%d]=0x%02x\n",i,harq_process_ul_ue->a[i]);
+          }
+        //}
+
+        LOG_D(MAC, "[UE %d] Frame %d, Subframe %d Adding Msg3 UL Config Request for rnti: %x\n",
+          ul_info->module_id,
+          ul_info->frame_tx,
+          ul_info->slot_tx,
+          mac->t_crnti);
+
+        // Config UL TX PDU
+        tx_req.slot = ul_info->slot_tx;
+        tx_req.sfn = ul_info->frame_tx;
+        tx_req.number_of_pdus = 1;
+        tx_req_body.pdu_length = TBS_bytes;
+        tx_req_body.pdu_index = 0;
+        tx_req_body.pdu = ulsch_input_buffer;
+        ul_config_list->pdu_type = FAPI_NR_UL_CONFIG_TYPE_PUSCH;
+        scheduled_response.tx_request = &tx_req;
+        scheduled_response.tx_request->tx_request_body = &tx_req_body;
+        scheduled_response.module_id  = ul_info->module_id;
+        scheduled_response.CC_id      = ul_info->cc_id;
+        scheduled_response.frame      = ul_info->frame_rx;
+        scheduled_response.slot       = ul_info->slot_rx;
+
+        if(mac->if_module != NULL && mac->if_module->scheduled_response != NULL){
+          mac->if_module->scheduled_response(&scheduled_response);
+        }
+      }
     }
   }
   return UE_CONNECTION_OK;
 }
 
+// Scheduling the Msg3 transmission according to according to TS 38.213
+// Note: Msg3 tx in the uplink symbols of mixed slot
+void nr_ue_msg3_scheduler(NR_UE_MAC_INST_t *mac,
+                          frame_t current_frame,
+                          sub_frame_t current_slot,
+                          uint8_t Msg3_tda_id){
+
+  int delta;
+  NR_BWP_Uplink_t *ubwp = mac->ULbwp[0];
+  int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing;
+  struct NR_PUSCH_TimeDomainResourceAllocationList *pusch_TimeDomainAllocationList = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList;
+  // k2 as per 3GPP TS 38.214 version 15.9.0 Release 15 ch 6.1.2.1.1
+  // PUSCH time domain resource allocation is higher layer configured from uschTimeDomainAllocationList in either pusch-ConfigCommon
+  uint8_t k2 = *pusch_TimeDomainAllocationList->list.array[Msg3_tda_id]->k2;
+
+  switch (mu) {
+    case 0:
+      delta = 2;
+      break;
+    case 1:
+      delta = 3;
+      break;
+    case 2:
+      delta = 4;
+      break;
+    case 3:
+      delta = 6;
+      break;
+  }
+
+  mac->msg3_slot = (current_slot + k2 + delta) % nr_slots_per_frame[mu];
+  if (current_slot + k2 + delta > nr_slots_per_frame[mu])
+    mac->msg3_frame = (current_frame + 1) % 1024;
+  else
+    mac->msg3_frame = current_frame;
+
+  #ifdef DEBUG_MSG3
+  LOG_D(MAC, "[DEBUG_MSG3] current_slot %d k2 %d delta %d temp_slot %d mac->msg3_frame %d mac->msg3_slot %d \n", current_slot, k2, delta, current_slot + k2 + delta, mac->msg3_frame, mac->msg3_slot);
+  #endif
+}
+
 // 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.
diff --git a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c
index 8d52db6747849300881817f0f3b9b8dd39ecf05f..d291e74e45a69786d9bd52839ff1be267c28f7a7 100644
--- a/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c
+++ b/openair2/LAYER2/NR_MAC_UE/rar_tools_nrUE.c
@@ -46,7 +46,8 @@
 #include "NR_MAC_COMMON/nr_mac_extern.h"
 #include <common/utils/nr/nr_common.h>
 
-#define DEBUG_RAR
+// #define DEBUG_RAR
+// #define DEBUG_MSG3
 
 // table 7.2-1 TS 38.321
 uint16_t table_7_2_1[16] = {
@@ -66,6 +67,111 @@ uint16_t table_7_2_1[16] = {
   1920, // row index 13
 };
 
+void nr_config_Msg3_pdu(NR_UE_MAC_INST_t *mac,
+                        int Msg3_f_alloc,
+                        uint8_t Msg3_t_alloc,
+                        uint8_t mcs,
+                        uint8_t freq_hopping){
+
+  int f_alloc, mask, StartSymbolIndex, NrOfSymbols;
+  uint16_t TBS_bytes;
+  fapi_nr_ul_config_request_t *ul_config = &mac->ul_config_request;
+  ul_config->number_pdus++;
+  nfapi_nr_ue_pusch_pdu_t *pusch_config_pdu = &ul_config->ul_config_list[ul_config->number_pdus - 1].pusch_config_pdu;
+  NR_ServingCellConfigCommon_t *scc = mac->scc;
+  NR_BWP_Uplink_t *ubwp = mac->ULbwp[0];
+  int startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[Msg3_t_alloc]->startSymbolAndLength;
+
+  #ifdef DEBUG_MSG3
+  printf("[DEBUG_MSG3] Configuring Msg3 PDU of %d UL pdus \n", ul_config->number_pdus);
+  #endif
+
+  // active BWP start
+  int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
+  int abwp_size = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth, 275);
+
+  // initial BWP start
+  int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275);
+  int ibwp_size = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth, 275);
+
+  //// Resource assignment from RAR
+  // Frequency domain allocation
+  if (abwp_size < 180)
+    mask = (1 << ((int) ceil(log2((abwp_size*(abwp_size+1))>>1)))) - 1;
+  else
+    mask = (1 << (28 - (int)(ceil(log2((abwp_size*(abwp_size+1))>>1))))) - 1;
+  f_alloc = Msg3_f_alloc & mask;
+  pusch_config_pdu->bwp_size = ibwp_size;
+  if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size))
+    pusch_config_pdu->bwp_start = abwp_start;
+  else
+    pusch_config_pdu->bwp_start = ibwp_start;
+  nr_ue_process_dci_freq_dom_resource_assignment(pusch_config_pdu, NULL, ibwp_size, 0, f_alloc);
+  // virtual resource block to physical resource mapping for Msg3 PUSCH (6.3.1.7 in 38.211)
+  pusch_config_pdu->rb_start += ibwp_start - abwp_start;
+
+  // Time domain allocation
+  SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols);
+  pusch_config_pdu->ul_dmrs_symb_pos = 1<<StartSymbolIndex;
+  pusch_config_pdu->start_symbol_index = StartSymbolIndex;
+  pusch_config_pdu->nr_of_symbols = NrOfSymbols;
+
+  #ifdef DEBUG_MSG3
+  printf("[DEBUG_MSG3] Freq assignment (RB start %d size %d) BWP (start %d, size %d), Time assignment (sliv_S %d sliv_L %d) \n",
+    pusch_config_pdu->rb_start,
+    pusch_config_pdu->rb_size,
+    pusch_config_pdu->bwp_start,
+    pusch_config_pdu->bwp_size,
+    StartSymbolIndex,
+    NrOfSymbols);
+  #endif
+
+  // MCS
+  pusch_config_pdu->mcs_index = mcs;
+  // Frequency hopping
+  pusch_config_pdu->frequency_hopping = freq_hopping;
+  // TC-RNTI
+  pusch_config_pdu->rnti = mac->t_crnti;
+
+  //// Completing PUSCH PDU
+  pusch_config_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
+  pusch_config_pdu->mcs_table = 0;
+  pusch_config_pdu->nrOfLayers = 0;
+  pusch_config_pdu->dmrs_config_type = 0;
+  // no data in dmrs symbols as in 6.2.2 in 38.214
+  pusch_config_pdu->num_dmrs_cdm_grps_no_data = 2; // TBR
+  pusch_config_pdu->cyclic_prefix = 0;
+  pusch_config_pdu->target_code_rate = nr_get_code_rate_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table);
+  pusch_config_pdu->qam_mod_order = nr_get_Qm_ul(pusch_config_pdu->mcs_index, pusch_config_pdu->mcs_table);
+  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL)
+    pusch_config_pdu->transform_precoding = 1;
+  else
+    pusch_config_pdu->transform_precoding = 0;
+  pusch_config_pdu->data_scrambling_id = *scc->physCellId;
+  pusch_config_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id.
+  pusch_config_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0.
+  pusch_config_pdu->dmrs_ports = 1;  // 6.2.2 in 38.214 only port 0 to be used
+  pusch_config_pdu->resource_alloc = 1; //type 1
+  pusch_config_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing;
+  pusch_config_pdu->vrb_to_prb_mapping = 0;
+  pusch_config_pdu->uplink_frequency_shift_7p5khz = 0;
+  //Optional Data only included if indicated in pduBitmap
+  pusch_config_pdu->pusch_data.rv_index = 0;  // 8.3 in 38.213
+  pusch_config_pdu->pusch_data.harq_process_id = 0;
+  pusch_config_pdu->pusch_data.new_data_indicator = 1; // new data
+  pusch_config_pdu->pusch_data.num_cb = 0;
+  TBS_bytes = nr_compute_tbs(pusch_config_pdu->qam_mod_order,
+                             pusch_config_pdu->target_code_rate,
+                             pusch_config_pdu->rb_size,
+                             pusch_config_pdu->nr_of_symbols,
+                             12, // TBR compute accordingly - nb dmrs set for no data in dmrs symbol
+                             0, // nb_rb_oh
+                             0, // to verify tb scaling
+                             pusch_config_pdu->nrOfLayers = 1)/8;
+  pusch_config_pdu->pusch_data.tb_size = TBS_bytes;
+
+}
+
 /////////////////////////////////////
 //    Random Access Response PDU   //
 //         TS 38.213 ch 8.2        //
@@ -90,12 +196,13 @@ uint16_t table_7_2_1[16] = {
 //|    F_alloc    |Time allocation|//
 //|      MCS      |     TPC   |CSI|//
 /////////////////////////////////////
-// WIP todo:
+// TbD WIP Msg3 development ongoing
 // - apply UL grant freq alloc & time alloc as per 8.2 TS 38.213
-// - apply tpc command, csi req, mcs
+// - apply tpc command
 uint16_t nr_ue_process_rar(module_id_t mod_id,
                            int CC_id,
-                           frame_t frameP,
+                           frame_t frame,
+                           sub_frame_t slot,
                            uint8_t * dlsch_buffer,
                            rnti_t * t_crnti,
                            uint8_t preamble_index,
@@ -106,11 +213,7 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
     NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1);            // RAR subPDU pointer
     uint8_t n_subPDUs = 0;        // number of RAR payloads
     uint8_t n_subheaders = 0;     // number of MAC RAR subheaders
-    //uint8_t best_rx_rapid = -1;   // the closest RAPID receive from all RARs
-    //unsigned char freq_hopping, msg3_t_alloc, mcs, tpc_command, csi_req; // WIP
-    //uint16_t ta_command = 0, msg3_f_alloc, bwp_size; // WIP
     uint16_t ta_command = 0;
-    //int f_alloc, mask; // WIP
 
     AssertFatal(CC_id == 0, "RAR reception on secondary CCs is not supported yet\n");
 
@@ -139,17 +242,19 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
       }
     };
 
-    LOG_D(MAC, "number of RAR subheader %d; number of RAR pyloads %d\n", n_subheaders, n_subPDUs);
-
-    // LOG_I(MAC, "[UE %d][RAPROC] Frame %d Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n",
-    //   mod_id, frameP, *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index);
+    #ifdef DEBUG_RAR
+    LOG_D(MAC, "[DEBUG_RAR] (%d,%d) number of RAR subheader %d; number of RAR pyloads %d\n", frame, slot, n_subheaders, n_subPDUs);
+    LOG_D(MAC, "[DEBUG_RAR] Received RAR (%02x|%02x.%02x.%02x.%02x.%02x.%02x) for preamble %d/%d\n", *(uint8_t *) rarh, rar[0], rar[1], rar[2], rar[3], rar[4], rar[5], rarh->RAPID, preamble_index);
+    #endif
 
-    #if 0 // TbD WIP Msg3 development ongoing
     if (ue_mac->RA_RAPID_found) {
+
+      uint8_t freq_hopping, mcs, Msg3_t_alloc, Msg3_f_alloc;
+      unsigned char tpc_command, csi_req;
+
       // TC-RNTI
       *t_crnti = rar->TCRNTI_2 + (rar->TCRNTI_1 << 8);
       ue_mac->t_crnti = *t_crnti;
-      ue_mac->rnti_type = NR_RNTI_TC;
       // TA command
       ta_command = rar->TA2 + (rar->TA1 << 5);
       // CSI
@@ -182,27 +287,36 @@ uint16_t nr_ue_process_rar(module_id_t mod_id,
           ue_mac->Msg3_TPC = 8;
           break;
       }
-      //MCS
+      // MCS
       mcs = (unsigned char) (rar->UL_GRANT_4 >> 4);
-      // time and frequency alloc
-      bwp_size = NRRIV2BW(ue_mac->ULbwp[0]->bwp_Common->genericParameters.locationAndBandwidth,275);
-      msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07);
-      msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
+      // time alloc
+      Msg3_t_alloc = (unsigned char) (rar->UL_GRANT_3 & 0x07);
+      // frequency alloc
+      Msg3_f_alloc = (uint16_t) ((rar->UL_GRANT_3 >> 4) | (rar->UL_GRANT_2 << 4) | ((rar->UL_GRANT_1 & 0x03) << 12));
+      // frequency hopping
+      freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2);
 
-      if (bwp_size < 180)
-        mask = (1 << ((int) ceil(log2((bwp_size*(bwp_size+1))>>1)))) - 1;
-      else
-        mask = (1 << (28 - (int)(ceil(log2((bwp_size*(bwp_size+1))>>1))))) - 1;
+      #ifdef DEBUG_RAR
+      LOG_D(MAC, "[DEBUG_RAR] Received RAR with t_alloc %d f_alloc %d ta_command %d mcs %d freq_hopping %d tpc_command %d csi_req %d t_crnti %x \n",
+        Msg3_t_alloc,
+        Msg3_f_alloc,
+        ta_command,
+        mcs,
+        freq_hopping,
+        tpc_command,
+        csi_req,
+        ue_mac->t_crnti);
+      #endif
 
-      f_alloc = msg3_f_alloc & mask;
+      // Config Msg3 PDU
+      nr_config_Msg3_pdu(ue_mac, Msg3_f_alloc, Msg3_t_alloc, mcs, freq_hopping);
+      // Schedule Msg3
+      nr_ue_msg3_scheduler(ue_mac, frame, slot, Msg3_t_alloc);
 
-      // frequency hopping flag
-      freq_hopping = (unsigned char) (rar->UL_GRANT_1 >> 2);
     } else {
       ue_mac->t_crnti = 0;
       ta_command = (0xffff);
     }
-    #endif
 
     // move the selected RAR to the front of the RA_PDSCH buffer
     memcpy((void *) (selected_rar_buffer + 0), (void *) rarh, 1);