nr_ra_procedures.c 23.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

/*! \file ra_procedures.c
 * \brief Routines for UE MAC-layer Random Access procedures (TS 38.321, Release 15)
 * \author R. Knopp, Navid Nikaein, Guido Casati
 * \date 2019
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr navid.nikaein@eurecom.fr, guido.casati@iis.fraunhofer.de
 * \note
 * \warning
 */

#include "mac.h"

/*
#include "common/utils/LOG/vcd_signal_dumper.h"
#include "PHY_INTERFACE/phy_interface_extern.h"
#include "SCHED_UE/sched_UE.h"
#include "COMMON/mac_rrc_primitives.h"
#include "RRC/LTE/rrc_extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
#include "common/utils/LOG/log.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"*/

/* Tools */
#include "SIMULATION/TOOLS/sim.h"	// for taus

/* RRC */
#include "NR_RACH-ConfigCommon.h"

/* PHY */
#include "PHY/NR_TRANSPORT/nr_transport_common_proto.h"
#include "PHY/defs_common.h"
#include "PHY/defs_nr_common.h"
cig's avatar
cig committed
58
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
59 60 61 62 63 64 65 66 67

/* MAC */
#include "LAYER2/NR_MAC_COMMON/nr_mac_extern.h"
#include "NR_MAC_COMMON/nr_mac.h"
#include "LAYER2/NR_MAC_UE/mac_proto.h"

extern int64_t table_6_3_3_2_2_prachConfig_Index [256][9];
extern int64_t table_6_3_3_2_3_prachConfig_Index [256][9];

cig's avatar
cig committed
68
//extern uint8_t  nfapi_mode;
69

cig's avatar
cig committed
70
// WIP
71 72 73 74 75 76 77
// This routine implements Section 5.1.2 (UE Random Access Resource Selection)
// and Section 5.1.3 (Random Access Preamble Transmission) from 3GPP TS 38.321
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,
78
                            NR_PRACH_RESOURCES_t *prach_resources,
79 80
                            NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){

cig's avatar
cig committed
81
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
cig's avatar
cig committed
82
  NR_ServingCellConfigCommon_t *scc = mac->scc;
cig's avatar
cig committed
83
  NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon;
cig's avatar
cig committed
84 85
  NR_RACH_ConfigGeneric_t *rach_ConfigGeneric;

cig's avatar
cig committed
86
  // NR_BeamFailureRecoveryConfig_t *beam_failure_recovery_config = &mac->RA_BeamFailureRecoveryConfig; // todo
87

cig's avatar
cig committed
88
  int messagePowerOffsetGroupB, messageSizeGroupA, PLThreshold, sizeOfRA_PreamblesGroupA, numberOfRA_Preambles, i, deltaPreamble_Msg3;
cig's avatar
cig committed
89
  uint8_t noGroupB = 0, s_id, f_id, ul_carrier_id, prach_ConfigIndex, SFN_nbr, Msg3_size;
90

cig's avatar
cig committed
91
  // NR_RSRP_Range_t rsrp_ThresholdSSB; // todo
92 93 94 95 96

  ///////////////////////////////////////////////////////////
  //////////* UE Random Access Resource Selection *//////////
  ///////////////////////////////////////////////////////////

cig's avatar
cig committed
97 98 99 100 101 102 103 104 105
  // todo: 
  // - switch initialisation cases
  // -- RA initiated by beam failure recovery operation (subclause 5.17 TS 38.321)
  // --- SSB selection, set prach_resources->ra_PreambleIndex
  // -- RA initiated by PDCCH: ra_preamble_index provided by PDCCH && ra_PreambleIndex != 0b000000 
  // --- set PREAMBLE_INDEX to ra_preamble_index
  // --- select the SSB signalled by PDCCH
  // -- RA initiated for SI request:
  // --- SSB selection, set prach_resources->ra_PreambleIndex
cig's avatar
cig committed
106 107

  // if (rach_ConfigDedicated) {  // This is for network controlled Mobility
cig's avatar
cig committed
108
  //   // operation for contention-free RA resources when:
109 110 111 112 113
  //   // - available SSB with SS-RSRP above rsrp-ThresholdSSB: SSB selection
  //   // - availalbe CSI-RS with CSI-RSRP above rsrp-ThresholdCSI-RS: CSI-RS selection
  //   prach_resources->ra_PreambleIndex = rach_ConfigDedicated->ra_PreambleIndex;
  // }

cig's avatar
cig committed
114
  //////////* Contention-based RA preamble selection *//////////
cig's avatar
cig committed
115
  // todo:
cig's avatar
cig committed
116 117
  // - selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB
  // - todo determine next available PRACH occasion
cig's avatar
cig committed
118

cig's avatar
cig committed
119
  // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
cig's avatar
cig committed
120

121
  AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "[UE %d] FATAL nr_rach_ConfigCommon is NULL !!!\n", mod_id);
cig's avatar
cig committed
122

cig's avatar
cig committed
123 124
  nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
  rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric;
cig's avatar
cig committed
125

cig's avatar
cig committed
126
  Msg3_size = mac->RA_Msg3_size;
cig's avatar
cig committed
127 128 129 130

  numberOfRA_Preambles = 64;
  if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
    numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
cig's avatar
cig committed
131

132 133 134
  if (!nr_rach_ConfigCommon->groupBconfigured) {
    noGroupB = 1;
  } else {
cig's avatar
cig committed
135
    // RA preambles group B is configured 
136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
    // - Defining the number of RA preambles in RA Preamble Group A for each SSB */
    sizeOfRA_PreamblesGroupA = nr_rach_ConfigCommon->groupBconfigured->numberOfRA_PreamblesGroupA;
    switch (nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA){
    /* - Threshold to determine the groups of RA preambles */
    case 0:
    messageSizeGroupA = 56;
    break;
    case 1:
    messageSizeGroupA = 144;
    break;
    case 2:
    messageSizeGroupA = 208;
    break;
    case 3:
    messageSizeGroupA = 256;
    break;
    case 4:
    messageSizeGroupA = 282;
    break;
    case 5:
    messageSizeGroupA = 480;
    break;
    case 6:
    messageSizeGroupA = 640;
    break;
    case 7:
    messageSizeGroupA = 800;
    break;
    case 8:
    messageSizeGroupA = 1000;
    break;
    case 9:
    messageSizeGroupA = 72;
    break;
    default:
cig's avatar
cig committed
171
    AssertFatal(1 == 0,"Unknown ra_Msg3SizeGroupA %lu\n", nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA);
cig's avatar
cig committed
172
    /* todo cases 10 -15*/
173 174
    }

cig's avatar
cig committed
175
    /* Power offset for preamble selection in dB */
176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202
    messagePowerOffsetGroupB = -9999;
    switch (nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB){
    case 0:
    messagePowerOffsetGroupB = -9999;
    break;
    case 1:
    messagePowerOffsetGroupB = 0;
    break;
    case 2:
    messagePowerOffsetGroupB = 5;
    break;
    case 3:
    messagePowerOffsetGroupB = 8;
    break;
    case 4:
    messagePowerOffsetGroupB = 10;
    break;
    case 5:
    messagePowerOffsetGroupB = 12;
    break;
    case 6:
    messagePowerOffsetGroupB = 15;
    break;
    case 7:
    messagePowerOffsetGroupB = 18;
    break;
    default:
cig's avatar
cig committed
203
    AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB);
204 205
    }

cig's avatar
cig committed
206
    // todo Msg3-DeltaPreamble should be provided from higher layers, otherwise is 0
cig's avatar
cig committed
207 208
    mac->deltaPreamble_Msg3 = 0;
    deltaPreamble_Msg3 = mac->deltaPreamble_Msg3;
209 210
  }

cig's avatar
cig committed
211
  PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB;
212 213 214 215 216 217

  /* Msg3 has not been transmitted yet */
  if (first_Msg3 == 1) {
    if (noGroupB == 1) {
      // use Group A preamble
      prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
cig's avatar
cig committed
218
      mac->RA_usedGroupA = 1;
219
    } else if ((Msg3_size < messageSizeGroupA) && (get_nr_PL(mod_id, CC_id, gNB_id) > PLThreshold)) {
220
      // Group B is configured and RA preamble Group A is used
cig's avatar
cig committed
221
      // - todo add condition on CCCH_sdu_size for initiation by CCCH
222
      prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
cig's avatar
cig committed
223
      mac->RA_usedGroupA = 1;
224 225 226 227
    } 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
cig's avatar
cig committed
228
      prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
cig's avatar
cig committed
229
      mac->RA_usedGroupA = 0;
230
    }
cig's avatar
cig committed
231
  } else { // Msg3 is being retransmitted
cig's avatar
cig committed
232 233 234
    if (mac->RA_usedGroupA == 1 && noGroupB == 1) {
      prach_resources->ra_PreambleIndex = (taus()) % numberOfRA_Preambles;
    } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){
cig's avatar
cig committed
235 236 237
      prach_resources->ra_PreambleIndex = (taus()) % sizeOfRA_PreamblesGroupA;
    } else {
      prach_resources->ra_PreambleIndex = sizeOfRA_PreamblesGroupA + (taus()) % (numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
238
    }
cig's avatar
cig committed
239
  }
240

cig's avatar
cig committed
241 242 243 244
  // todo determine next available PRACH occasion
  // - if RA initiated for SI request and ra_AssociationPeriodIndex and si-RequestPeriod are configured
  // - else if SSB is selected above
  // - else if CSI-RS is selected above
245 246 247 248

  /////////////////////////////////////////////////////////////////////////////
  //////////* Random Access Preamble Transmission (5.1.3 TS 38.321) *//////////
  /////////////////////////////////////////////////////////////////////////////
cig's avatar
cig committed
249 250 251
  // todo:
  // - condition on notification of suspending power ramping counter from lower layer (5.1.3 TS 38.321)
  // - check if SSB or CSI-RS have not changed since the selection in the last RA Preamble tranmission
cig's avatar
cig committed
252
  // - Extend RA_rnti computation (e.g. f_id selection, ul_carrier_id are hardcoded)
253

cig's avatar
cig committed
254
  if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER > 1)
cig's avatar
cig committed
255
    mac->RA_PREAMBLE_POWER_RAMPING_COUNTER++;
256

257
  prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
258

cig's avatar
cig committed
259
   // RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted)
260 261 262
   // 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)

cig's avatar
cig committed
263
   prach_ConfigIndex = rach_ConfigGeneric->prach_ConfigurationIndex;
264

cig's avatar
cig committed
265 266 267 268 269 270 271
   // 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]

cig's avatar
cig committed
272
   ul_carrier_id = 0; // NUL
cig's avatar
cig committed
273
   f_id = rach_ConfigGeneric->msg1_FrequencyStart;
274
   SFN_nbr = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][4]; 
cig's avatar
cig committed
275
   s_id = table_6_3_3_2_3_prachConfig_Index[prach_ConfigIndex][5];
276

cig's avatar
cig committed
277
   // Pick the first slot of the PRACH occasion in a system frame
278 279 280 281 282 283 284
   for (i = 0; i < 10; i++){
    if (((SFN_nbr & (1 << i)) >> i) == 1){
      t_id = 2*i;
      break;
    }
   }
   prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
cig's avatar
cig committed
285
   mac->ra_rnti = prach_resources->ra_RNTI;
cig's avatar
cig committed
286 287

   LOG_D(MAC, "Computed ra_RNTI is %d", prach_resources->ra_RNTI);
288 289
}

cig's avatar
cig committed
290
// TbD: RA_attempt_number not used
291 292
void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){
  AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n");
cig's avatar
cig committed
293
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
cig's avatar
cig committed
294
  mac->ra_state = WAIT_RAR;
cig's avatar
cig committed
295
  // Start contention resolution timer
cig's avatar
cig committed
296
  mac->RA_attempt_number++;
cig's avatar
cig committed
297
}
298 299 300

void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){
  AssertFatal(CC_id == 0, "Transmission on secondary CCs is not supported yet\n");
301 302 303
  LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Starting contention resolution timer\n", mod_id, frameP);
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
  // start contention resolution timer
cig's avatar
cig committed
304 305
  mac->RA_contention_resolution_cnt = 0;
  mac->RA_contention_resolution_timer_active = 1;
306 307 308 309 310 311 312 313 314
}

/////////////////////////////////////////////////////////////////////////
///////* Random Access Preamble Initialization (5.1.1 TS 38.321) *///////
/////////////////////////////////////////////////////////////////////////
/// Handling inizialization by PDCCH order, MAC entity or RRC (TS 38.300)
/// Only one RA procedure is ongoing at any point in time in a MAC entity
/// the RA procedure on a SCell shall only be initiated by PDCCH order

cig's avatar
cig committed
315
// WIP
cig's avatar
cig committed
316 317 318 319 320 321 322 323 324 325 326 327
// todo TS 38.321:
// - check if carrier to use is explicitly signalled then do (1) RA CARRIER SELECTION (SUL, NUL) (2) set PCMAX
// - BWP operation (subclause 5.15 TS 38.321)
// - handle initialization by beam failure recovery
// - handle initialization by handover
// - handle transmission on DCCH using PRACH (during handover, or sending SR for example)
// - take into account MAC CEs in size_sdu (currently hardcoded size to 1 MAC subPDU and 1 padding subheader)
// - fix rrc data req logic
// - retrieve TBS
// - add mac_rrc_nr_data_req_ue, etc ...
// - add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)

328 329 330 331 332 333 334
void nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
                    module_id_t mod_id,
                    int CC_id,
                    UE_MODE_t UE_mode,
                    frame_t frame,
                    uint8_t gNB_id,
                    int nr_tti_tx){
335

cig's avatar
cig committed
336
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
337 338
  uint8_t mac_sdus[MAX_NR_ULSCH_PAYLOAD_BYTES];
  uint8_t lcid = UL_SCH_LCID_CCCH_MSG3, *payload, ra_ResponseWindow;
339 340
  uint8_t config_index, mu;
  int is_nr_prach_slot;
cig's avatar
cig committed
341 342
  uint16_t size_sdu = 0;
  unsigned short post_padding;
343
  fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
cig's avatar
cig committed
344 345 346
  NR_ServingCellConfigCommon_t *scc = mac->scc;
  NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
  NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
347
  NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
cig's avatar
cig committed
348
  // int32_t frame_diff = 0;
349

cig's avatar
cig committed
350 351 352
  uint8_t sdu_lcids[NB_RB_MAX] = {0};
  uint16_t sdu_lengths[NB_RB_MAX] = {0};
  int TBS_bytes = 848, header_length_total, num_sdus, offset, preambleTransMax, mac_ce_len;
353 354 355 356

  AssertFatal(CC_id == 0,"Transmission on secondary CCs is not supported yet\n");

  if (UE_mode == PRACH) {
cig's avatar
cig committed
357

cig's avatar
cig committed
358
    LOG_D(MAC, "nr_ue_get_rach, RA_active value: %d", mac->RA_active);
cig's avatar
cig committed
359

360 361 362 363 364 365 366 367 368 369 370 371 372 373 374 375 376 377 378 379 380
    config_index = rach_ConfigGeneric->prach_ConfigurationIndex;
    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)frame,
                                                    (int)nr_tti_tx,
                                                    frequencyInfoDL->absoluteFrequencyPointA,
                                                    mu,
                                                    cfg->cell_config.frame_duplex_type,
                                                    NULL,
                                                    NULL,
                                                    NULL,
                                                    NULL);
    if (is_nr_prach_slot)
      prach_resources->generate_nr_prach = 1;
    else
      prach_resources->generate_nr_prach = 0;

cig's avatar
cig committed
381
    AssertFatal(setup != NULL, "[UE %d] FATAL  nr_rach_ConfigCommon is NULL !!!\n", mod_id);
382

cig's avatar
cig committed
383
    if (mac->RA_active == 0) {
384 385
      /* RA not active - checking if RRC is ready to initiate the RA procedure */

cig's avatar
cig committed
386
      LOG_I(MAC, "RA not active. Starting RA preamble initialization.\n");
387

cig's avatar
cig committed
388
      mac->RA_RAPID_found = 0;
389 390

      /* Set RA_PREAMBLE_POWER_RAMPING_STEP */
cig's avatar
cig committed
391
      switch (rach_ConfigGeneric->powerRampingStep){ // in dB
392 393 394 395 396 397 398 399 400 401 402 403 404 405
       case 0:
       prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 0;
       break;
       case 1:
       prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 2;
       break;
       case 2:
       prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 4;
       break;
       case 3:
       prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP = 6;
       break;
      }

cig's avatar
cig committed
406
      prach_resources->RA_PREAMBLE_BACKOFF = 0;
407
      prach_resources->RA_SCALING_FACTOR_BI = 1;
cig's avatar
cig committed
408 409
      prach_resources->RA_PCMAX = 0; // currently hardcoded to 0

cig's avatar
cig committed
410
      payload = (uint8_t*) &mac->CCCH_pdu.payload;
cig's avatar
cig committed
411

cig's avatar
cig committed
412 413 414
      mac_ce_len = 0;
      num_sdus = 1;
      post_padding = 1;
cig's avatar
cig committed
415

416
      if (0){
cig's avatar
cig committed
417 418
        // initialisation by RRC
        // CCCH PDU
cig's avatar
cig committed
419 420 421 422 423 424 425 426 427
        // size_sdu = (uint16_t) mac_rrc_data_req_ue(mod_id,
        //                                           CC_id,
        //                                           frame,
        //                                           CCCH,
        //                                           1,
        //                                           mac_sdus,
        //                                           gNB_id,
        //                                           0);
        LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n", mod_id, frame, size_sdu);
cig's avatar
cig committed
428 429 430
      } else {
        // fill ulsch_buffer with random data
        for (int i = 0; i < TBS_bytes; i++){
431
          mac_sdus[i] = (unsigned char) (lrand48()&0xff);
cig's avatar
cig committed
432 433 434
        }
        //Sending SDUs with size 1
        //Initialize elements of sdu_lcids and sdu_lengths
cig's avatar
cig committed
435 436
        sdu_lcids[0] = lcid;
        sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len;
cig's avatar
cig committed
437 438 439
        header_length_total += 2 + (sdu_lengths[0] >= 128);
        size_sdu += sdu_lengths[0];
      }
440

cig's avatar
cig committed
441 442 443 444
      mac->RA_tx_frame = frame;
      mac->RA_tx_subframe = nr_tti_tx;
      mac->RA_backoff_frame = frame;
      mac->RA_backoff_subframe = nr_tti_tx;
445

cig's avatar
cig committed
446
      if (size_sdu > 0) {
447 448 449

        LOG_I(MAC, "[UE %d] Frame %d: Initialisation Random Access Procedure\n", mod_id, frame);

cig's avatar
cig committed
450 451
        mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
        mac->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1;
cig's avatar
cig committed
452
        mac->RA_Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
cig's avatar
cig committed
453
        mac->RA_prachMaskIndex = 0;
cig's avatar
cig committed
454
        // todo: add the backoff condition here
cig's avatar
cig committed
455 456
        mac->RA_backoff_cnt = 0;
        mac->RA_active = 1;
cig's avatar
cig committed
457
        prach_resources->Msg3 = payload;
458

cig's avatar
cig committed
459
        ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow;
cig's avatar
cig committed
460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485
        switch (ra_ResponseWindow) {
          case 0:
            mac->RA_window_cnt = 1;
            break;
          case 1:
            mac->RA_window_cnt = 2;
            break;
          case 2:
            mac->RA_window_cnt = 4;
            break;
          case 3:
            mac->RA_window_cnt = 8;
            break;
          case 4:
            mac->RA_window_cnt = 10;
            break;
          case 5:
            mac->RA_window_cnt = 20;
            break;
          case 6:
            mac->RA_window_cnt = 40;
            break;
          case 7:
            mac->RA_window_cnt = 80;
            break;
        }
486 487

        // Fill in preamble and PRACH resources
cig's avatar
cig committed
488
        nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 1, prach_resources, NULL);
489

cig's avatar
cig committed
490
        offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus,              // sdus buffer
cig's avatar
cig committed
491
                                       (uint8_t *) payload,               // UL MAC pdu pointer
cig's avatar
cig committed
492 493 494 495 496 497 498 499
                                       num_sdus,                          // num sdus
                                       sdu_lengths,                       // sdu length
                                       sdu_lcids,                         // sdu lcid
                                       0,                                 // power headroom
                                       0,                                 // crnti
                                       0,                                 // truncated bsr
                                       0,                                 // short bsr
                                       0,                                 // long_bsr
500 501
                                       post_padding,
                                       0);
cig's avatar
cig committed
502

cig's avatar
cig committed
503
        // Padding: fill remainder with 0
cig's avatar
cig committed
504 505 506 507 508
        if (post_padding > 0){
          for (int j = 0; j < (TBS_bytes - offset); j++)
            payload[offset + j] = 0; // mac_pdu[offset + j] = 0;
        }
      } 
509 510 511 512 513
    } else { // RACH is active

      ////////////////////////////////////////////////////////////////
      /////* Random Access Response reception (5.1.4 TS 38.321) */////
      ////////////////////////////////////////////////////////////////
cig's avatar
cig committed
514 515 516 517 518
      // Handling ra_responseWindow, RA_PREAMBLE_TRANSMISSION_COUNTER
      // and RA_backoff_cnt
      // todo:
      // - handle beam failure recovery request
      // - handle DL assignment on PDCCH for RA-RNTI
cig's avatar
cig committed
519
      // - handle backoff and raResponseWindow params
520
      // - disabled contention resolution as OAI NSA is contention-free based
521 522

      LOG_D(MAC, "[MAC][UE %d][RAPROC] frame %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n",
cig's avatar
cig committed
523
        mod_id, frame, nr_tti_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe);
524

cig's avatar
cig committed
525 526
      if (mac->RA_BI_found){
        prach_resources->RA_PREAMBLE_BACKOFF =  prach_resources->RA_SCALING_FACTOR_BI * mac->RA_backoff_indicator;
cig's avatar
cig committed
527 528 529
      } else {
        prach_resources->RA_PREAMBLE_BACKOFF = 0;
      }
530

531 532
      if (mac->RA_window_cnt > 0 && mac->RA_RAPID_found == 1) {
        // mac->ra_state = WAIT_CONTENTION_RESOLUTION;
cig's avatar
cig committed
533 534 535 536 537 538
      } else {
        LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: subframe %d: RAR reception not successful, (RA window count %d) \n",
          mod_id,
          frame,
          nr_tti_tx,
          mac->RA_window_cnt);
539

cig's avatar
cig committed
540
        mac->RA_PREAMBLE_TRANSMISSION_COUNTER++;
541

cig's avatar
cig committed
542
        preambleTransMax = -1;
cig's avatar
cig committed
543 544
        switch (rach_ConfigGeneric->preambleTransMax) {
        case 0:
545 546
          preambleTransMax = 3;
          break;
cig's avatar
cig committed
547
        case 1:
548 549
          preambleTransMax = 4;
          break;
cig's avatar
cig committed
550
        case 2:
551 552
          preambleTransMax = 5;
          break;
cig's avatar
cig committed
553
        case 3:
554 555
          preambleTransMax = 6;
          break;
cig's avatar
cig committed
556
        case 4:
557 558
          preambleTransMax = 7;
          break;
cig's avatar
cig committed
559
        case 5:
560 561
          preambleTransMax = 8;
          break;
cig's avatar
cig committed
562
        case 6:
563 564
          preambleTransMax = 10;
          break;
cig's avatar
cig committed
565
        case 7:
566 567
          preambleTransMax = 20;
          break;
cig's avatar
cig committed
568
        case 8:
569 570
          preambleTransMax = 50;
          break;
cig's avatar
cig committed
571
        case 9:
572 573
          preambleTransMax = 100;
          break;
cig's avatar
cig committed
574
        case 10:
575 576 577 578
          preambleTransMax = 200;
          break;
        }

cig's avatar
cig committed
579
        if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax + 1){
580
          LOG_D(MAC, "[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n", mod_id, frame, preambleTransMax);
cig's avatar
cig committed
581 582
          mac->RA_backoff_cnt = rand() % (prach_resources->RA_PREAMBLE_BACKOFF + 1);
          mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
cig's avatar
cig committed
583
          prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP << 1; // 2 dB increment
584
          prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
585 586
        }

cig's avatar
cig committed
587 588 589 590 591 592 593 594 595 596 597 598 599 600
        // compute backoff parameters
        // if (mac->RA_backoff_cnt > 0){
        //   frame_diff = (sframe_t) frame - mac->RA_backoff_frame;
        //   if (frame_diff < 0) frame_diff = -frame_diff;
        //   mac->RA_backoff_frame = frame;
        //   mac->RA_backoff_subframe = nr_tti_tx;
        // }
        // compute RA window parameters
        // if (mac->RA_window_cnt > 0){
        //   frame_diff = (frame_t) frame - mac->RA_tx_frame;
        //   if (frame_diff < 0) frame_diff = -frame_diff;
        //   mac->RA_window_cnt -= ((10 * frame_diff) + (nr_tti_tx - mac->RA_tx_subframe));
        //   LOG_D(MAC, "[MAC][UE %d][RAPROC] Frame %d, subframe %d: RA Active, adjusted window cnt %d\n", mod_id, frame, nr_tti_tx, mac->RA_window_cnt);
        // }
601

cig's avatar
cig committed
602 603
        mac->RA_tx_frame = frame;
        mac->RA_tx_subframe = nr_tti_tx;
604
        // Fill in preamble and PRACH resources
cig's avatar
cig committed
605
        nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, 0, prach_resources, NULL);
606 607 608
      }
    }
  } else if (UE_mode == PUSCH) {
cig's avatar
cig committed
609 610
    LOG_D(MAC, "[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...", mod_id);
    AssertFatal(1 == 0, "");
611
  }
cig's avatar
cig committed
612
 return;
613
}