nr_ra_procedures.c 29.8 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
/*
 * 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"

/* 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
45
#include "PHY/NR_UE_ESTIMATION/nr_estimation.h"
46 47 48 49 50 51 52 53

/* 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_3_prachConfig_Index [256][9];

cig's avatar
cig committed
54
//extern uint8_t  nfapi_mode;
cig's avatar
cig committed
55
static uint8_t first_Msg3 = 0;
cig's avatar
cig committed
56 57 58
static int starting_preamble_nb = 0;
static long cb_preambles_per_ssb; // Nb of preambles per SSB
static uint8_t RA_usedGroupA;
59

60 61
void nr_get_RA_window(NR_UE_MAC_INST_t *mac);

cig's avatar
cig committed
62
void ssb_rach_config(NR_PRACH_RESOURCES_t *prach_resources, NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon, fapi_nr_ul_config_prach_pdu *prach_pdu){
63

cig's avatar
cig committed
64 65 66
  // Determine the SSB to RACH mapping ratio
  // =======================================
  if (prach_resources->RA_TYPE == RA_4STEP){
Mario Hudon's avatar
Mario Hudon committed
67 68 69 70 71
    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
    int total_preambles_per_ssb;
    uint8_t ssb_nb_in_ro;
cig's avatar
cig committed
72
    int numberOfRA_Preambles = 64;
Mario Hudon's avatar
Mario Hudon committed
73 74 75 76 77

    switch (ssb_perRACH_config){
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneEighth:
        multiple_ssb_per_ro = false;
        ssb_rach_ratio = 8;
78
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
Mario Hudon's avatar
Mario Hudon committed
79 80 81 82
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
        multiple_ssb_per_ro = false;
        ssb_rach_ratio = 4;
83
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
Mario Hudon's avatar
Mario Hudon committed
84 85 86 87
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
        multiple_ssb_per_ro = false;
        ssb_rach_ratio = 2;
88
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
Mario Hudon's avatar
Mario Hudon committed
89 90 91 92
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
        multiple_ssb_per_ro = true;
        ssb_rach_ratio = 1;
93
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
Mario Hudon's avatar
Mario Hudon committed
94 95 96 97
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
        multiple_ssb_per_ro = true;
        ssb_rach_ratio = 2;
98
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
Mario Hudon's avatar
Mario Hudon committed
99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119
        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;
    }

cig's avatar
cig committed
120
    if (nr_rach_ConfigCommon->totalNumberOfRA_Preambles)
121
      numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
cig's avatar
cig committed
122

Mario Hudon's avatar
Mario Hudon committed
123 124 125 126 127
    // 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;

128
      ssb_nb_in_ro = prach_pdu->ssb_nb_in_ro;
Mario Hudon's avatar
Mario Hudon committed
129 130 131 132 133 134
      starting_preamble_nb = total_preambles_per_ssb * ssb_nb_in_ro;
    }
    else {
      total_preambles_per_ssb = numberOfRA_Preambles;
      starting_preamble_nb = 0;
    }
cig's avatar
cig committed
135 136 137 138 139 140 141 142 143 144 145 146 147
  } else {
    LOG_E(MAC, "In %s:%d: missing implementation for 2-step RA...\n", __FUNCTION__, __LINE__);
  }
}

// This routine implements RA premable configuration according to
// section 5.1 (Random Access procedure) of 3GPP TS 38.321 version 16.2.1 Release 16
void ra_preambles_config(NR_PRACH_RESOURCES_t *prach_resources, NR_UE_MAC_INST_t *mac, int16_t dl_pathloss){

  int messageSizeGroupA = 0;
  int sizeOfRA_PreamblesGroupA = 0;
  int messagePowerOffsetGroupB = 0;
  int PLThreshold;
148
  long deltaPreamble_Msg3 = 0;
cig's avatar
cig committed
149 150 151 152 153
  uint8_t noGroupB = 0;
  NR_ServingCellConfigCommon_t *scc = mac->scc;
  NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
  NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric;
  uint8_t Msg3_size = mac->RA_Msg3_size;
Mario Hudon's avatar
Mario Hudon committed
154

cig's avatar
cig committed
155
  if (prach_resources->RA_TYPE == RA_4STEP){
156 157 158 159 160 161

    if (scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble){
      deltaPreamble_Msg3 = *scc->uplinkConfigCommon->initialUplinkBWP->pusch_ConfigCommon->choice.setup->msg3_DeltaPreamble;
      LOG_D(MAC, "In %s: deltaPreamble_Msg3 set to %ld\n", __FUNCTION__, deltaPreamble_Msg3);
    }

162 163
    if (!nr_rach_ConfigCommon->groupBconfigured) {
      noGroupB = 1;
cig's avatar
cig committed
164
      LOG_D(MAC, "In %s:%d: preambles group B is not configured...\n", __FUNCTION__, __LINE__);
165 166
    } else {
      // RA preambles group B is configured 
cig's avatar
cig committed
167 168
      // - Random Access Preambles group B is configured for 4-step RA type
      // - Defining the number of RA preambles in RA Preamble Group A for each SSB
cig's avatar
cig committed
169
      LOG_D(MAC, "In %s:%d: preambles group B is configured...\n", __FUNCTION__, __LINE__);
170 171 172 173 174 175 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 203
      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
204
      AssertFatal(1 == 0, "Unknown ra_Msg3SizeGroupA %lu\n", nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA);
205 206
      /* todo cases 10 -15*/
      }
cig's avatar
cig committed
207

208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237
      /* Power offset for preamble selection in dB */
      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:
      AssertFatal(1 == 0,"Unknown messagePowerOffsetGroupB %lu\n", nr_rach_ConfigCommon->groupBconfigured->messagePowerOffsetGroupB);
      }
238

cig's avatar
cig committed
239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272
      PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB;

    }
  } else {
    // todo:
    // - groupB-ConfiguredTwoStepRA
    // - msgA-DeltaPreamble
    LOG_E(MAC, "In %s:%d: missing implementation for 2-step RA...\n", __FUNCTION__, __LINE__);
  }
  /* Msg3 has not been transmitted yet */
  if (first_Msg3) {
    if (noGroupB) {
      // use Group A preamble
      prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
      RA_usedGroupA = 1;
    } else if ((Msg3_size < messageSizeGroupA) && (dl_pathloss > 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 = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
      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 = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
      RA_usedGroupA = 0;
    }
  } else { // Msg3 is being retransmitted
    if (RA_usedGroupA && noGroupB) {
      prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
    } else if (RA_usedGroupA && !noGroupB){
      prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
    } else {
      prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
273
    }
cig's avatar
cig committed
274 275
  }
}
276

cig's avatar
cig committed
277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324
// 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,
                            NR_PRACH_RESOURCES_t *prach_resources,
                            fapi_nr_ul_config_prach_pdu *prach_pdu,
                            NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){

  uint8_t s_id, t_id, f_id, ul_carrier_id;
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
  NR_RACH_ConfigCommon_t *nr_rach_ConfigCommon = mac->scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;

  LOG_D(PHY, "In %s: getting PRACH resources frame (first_Msg3 %d)\n", __FUNCTION__, first_Msg3);

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

  // 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

  if (rach_ConfigDedicated) {
    //////////* Contention free RA *//////////
    // - the PRACH preamble for the UE to transmit is set through RRC configuration
    // - this is the default mode in current implementation!
    // Operation for contention-free RA resources when:
    // - available SSB with SS-RSRP above rsrp-ThresholdSSB: SSB selection
    // - available CSI-RS with CSI-RSRP above rsrp-ThresholdCSI-RS: CSI-RS selection
    // - network controlled Mobility

    if (rach_ConfigDedicated->cfra){
      uint8_t cfra_ssb_resource_idx = 0;
      prach_resources->ra_PreambleIndex = rach_ConfigDedicated->cfra->resources.choice.ssb->ssb_ResourceList.list.array[cfra_ssb_resource_idx]->ra_PreambleIndex;
      LOG_D(MAC, "In %s: selected RA preamble index %d for contention-free random access procedure\n", __FUNCTION__, prach_resources->ra_PreambleIndex);
    }

    if (rach_ConfigDedicated->ext1){
      if (rach_ConfigDedicated->ext1->cfra_TwoStep_r16){
        LOG_I(MAC, "In %s: setting RA type to 2-step...\n", __FUNCTION__);
        prach_resources->RA_TYPE = RA_2STEP;
325
      }
326
    }
327

cig's avatar
cig committed
328 329 330 331 332 333 334 335 336 337
  } else {
    //////////* Contention-based RA preamble selection *//////////
    // todo:
    // - selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB
    // - determine next available PRACH occasion

    // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
    int16_t dl_pathloss = get_nr_PL(mod_id, CC_id, gNB_id);
    ssb_rach_config(prach_resources, nr_rach_ConfigCommon, prach_pdu);
    ra_preambles_config(prach_resources, mac, dl_pathloss);
338
    LOG_D(MAC, "[RAPROC] - Selected RA preamble index %d for contention-based random access procedure... \n", prach_resources->ra_PreambleIndex);
cig's avatar
cig committed
339

cig's avatar
cig committed
340
  }
341

cig's avatar
cig committed
342 343 344 345
  // 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
346 347 348 349

  /////////////////////////////////////////////////////////////////////////////
  //////////* Random Access Preamble Transmission (5.1.3 TS 38.321) *//////////
  /////////////////////////////////////////////////////////////////////////////
cig's avatar
cig committed
350 351 352
  // 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
353
  // - Extend RA_rnti computation (e.g. f_id selection, ul_carrier_id are hardcoded)
354

cig's avatar
cig committed
355
  if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER > 1)
cig's avatar
cig committed
356
    mac->RA_PREAMBLE_POWER_RAMPING_COUNTER++;
357

358
  prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
359

cig's avatar
cig committed
360
   // RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted)
361 362 363
   // 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
364 365 366 367 368
   // ra_RNTI computation
   // - 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
369
   ul_carrier_id = 0; // NUL
370 371 372
   f_id = prach_pdu->num_ra;
   t_id = prach_pdu->prach_slot;
   s_id = prach_pdu->prach_start_symbol;
Mario Hudon's avatar
Mario Hudon committed
373

374
   prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
cig's avatar
cig committed
375
   mac->ra_rnti = prach_resources->ra_RNTI;
cig's avatar
cig committed
376

377
   LOG_D(MAC, "Computed ra_RNTI is %x \n", prach_resources->ra_RNTI);
378 379
}

cig's avatar
cig committed
380
// TbD: RA_attempt_number not used
381
void nr_Msg1_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){
cig's avatar
cig committed
382
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
cig's avatar
cig committed
383
  mac->ra_state = WAIT_RAR;
cig's avatar
cig committed
384
  // Start contention resolution timer
cig's avatar
cig committed
385
  mac->RA_attempt_number++;
cig's avatar
cig committed
386
}
387 388

void nr_Msg3_transmitted(module_id_t mod_id, uint8_t CC_id, frame_t frameP, uint8_t gNB_id){
389 390 391
  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
392 393
  mac->RA_contention_resolution_cnt = 0;
  mac->RA_contention_resolution_timer_active = 1;
394 395 396 397 398 399 400 401
}

/////////////////////////////////////////////////////////////////////////
///////* 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
402
/// in the current implementation, RA is contention free only
403

cig's avatar
cig committed
404 405 406 407 408 409 410 411 412 413 414
// 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)
415

cig's avatar
cig committed
416
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
417
                       fapi_nr_ul_config_prach_pdu *prach_pdu,
cig's avatar
cig committed
418 419 420 421 422
                       module_id_t mod_id,
                       int CC_id,
                       UE_MODE_t UE_mode,
                       frame_t frame,
                       uint8_t gNB_id,
423
                       int nr_slot_tx){
424

cig's avatar
cig committed
425
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
426
  uint8_t mac_sdus[MAX_NR_ULSCH_PAYLOAD_BYTES];
427 428
  uint8_t lcid = UL_SCH_LCID_CCCH_MSG3, *payload;
  //uint8_t ra_ResponseWindow;
cig's avatar
cig committed
429 430
  uint16_t size_sdu = 0;
  unsigned short post_padding;
431
  //fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
cig's avatar
cig committed
432
  NR_ServingCellConfigCommon_t *scc = mac->scc;
cig's avatar
cig committed
433
  AssertFatal(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup != NULL, "In %s: FATAL! nr_rach_ConfigCommon is NULL...\n", __FUNCTION__);
cig's avatar
cig committed
434
  NR_RACH_ConfigCommon_t *setup = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup;
cig's avatar
cig committed
435
  AssertFatal(&setup->rach_ConfigGeneric != NULL, "In %s: FATAL! rach_ConfigGeneric is NULL...\n", __FUNCTION__);
cig's avatar
cig committed
436
  NR_RACH_ConfigGeneric_t *rach_ConfigGeneric = &setup->rach_ConfigGeneric;
437
  //NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
438 439
  NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = mac->rach_ConfigDedicated;

cig's avatar
cig committed
440 441
  uint8_t sdu_lcids[NB_RB_MAX] = {0};
  uint16_t sdu_lengths[NB_RB_MAX] = {0};
Laurent's avatar
Laurent committed
442
  int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len;
443

444
  if (prach_resources->init_msg1) {
cig's avatar
cig committed
445

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

cig's avatar
cig committed
449
      LOG_I(MAC, "RA not active. Starting RA preamble initialization for 4-step RA\n");
450

cig's avatar
cig committed
451
      first_Msg3 = 0;
cig's avatar
cig committed
452
      mac->RA_RAPID_found = 0;
453 454

      /* Set RA_PREAMBLE_POWER_RAMPING_STEP */
cig's avatar
cig committed
455
      switch (rach_ConfigGeneric->powerRampingStep){ // in dB
456 457 458 459 460 461 462 463 464 465 466 467 468 469
       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
470
      prach_resources->RA_PREAMBLE_BACKOFF = 0;
471
      prach_resources->RA_SCALING_FACTOR_BI = 1;
cig's avatar
cig committed
472
      prach_resources->RA_PCMAX = 0; // currently hardcoded to 0
cig's avatar
cig committed
473
      prach_resources->RA_TYPE = RA_4STEP;
cig's avatar
cig committed
474

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

cig's avatar
cig committed
477 478 479
      mac_ce_len = 0;
      num_sdus = 1;
      post_padding = 1;
cig's avatar
cig committed
480

481
      if (0){
cig's avatar
cig committed
482 483
        // initialisation by RRC
        // CCCH PDU
cig's avatar
cig committed
484 485 486 487 488 489 490 491 492
        // 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
493 494 495
      } else {
        // fill ulsch_buffer with random data
        for (int i = 0; i < TBS_bytes; i++){
496
          mac_sdus[i] = (unsigned char) (lrand48()&0xff);
cig's avatar
cig committed
497 498 499
        }
        //Sending SDUs with size 1
        //Initialize elements of sdu_lcids and sdu_lengths
cig's avatar
cig committed
500 501
        sdu_lcids[0] = lcid;
        sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len;
cig's avatar
cig committed
502 503 504
        header_length_total += 2 + (sdu_lengths[0] >= 128);
        size_sdu += sdu_lengths[0];
      }
505

cig's avatar
cig committed
506
      //mac->RA_tx_frame = frame;
507
      //mac->RA_tx_slot  = nr_slot_tx;
cig's avatar
cig committed
508
      //mac->RA_backoff_frame = frame;
509
      //mac->RA_backoff_slot  = nr_slot_tx;
510

cig's avatar
cig committed
511
      if (size_sdu > 0) {
512 513 514

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

cig's avatar
cig committed
515 516
        mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
        mac->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1;
cig's avatar
cig committed
517
        mac->RA_Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
cig's avatar
cig committed
518
        mac->RA_prachMaskIndex = 0;
cig's avatar
cig committed
519
        // todo: add the backoff condition here
cig's avatar
cig committed
520 521
        mac->RA_backoff_cnt = 0;
        mac->RA_active = 1;
cig's avatar
cig committed
522
        prach_resources->Msg3 = payload;
523

cig's avatar
cig committed
524
        nr_get_RA_window(mac);
525 526

        // Fill in preamble and PRACH resources
527
        if (mac->generate_nr_prach == 1)
cig's avatar
cig committed
528
          nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated);
529

cig's avatar
cig committed
530
        offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus,              // sdus buffer
cig's avatar
cig committed
531
                                       (uint8_t *) payload,               // UL MAC pdu pointer
cig's avatar
cig committed
532 533 534 535 536 537 538 539
                                       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
540 541
                                       post_padding,
                                       0);
cig's avatar
cig committed
542

cig's avatar
cig committed
543
        // Padding: fill remainder with 0
cig's avatar
cig committed
544 545 546 547 548
        if (post_padding > 0){
          for (int j = 0; j < (TBS_bytes - offset); j++)
            payload[offset + j] = 0; // mac_pdu[offset + j] = 0;
        }
      } 
549
    } else if (mac->RA_window_cnt != -1) { // RACH is active
550 551 552 553

      ////////////////////////////////////////////////////////////////
      /////* Random Access Response reception (5.1.4 TS 38.321) */////
      ////////////////////////////////////////////////////////////////
cig's avatar
cig committed
554 555 556 557 558
      // 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
559
      // - handle backoff and raResponseWindow params
560

cig's avatar
cig committed
561
      LOG_D(MAC, "In %s [%d.%d] RA is active: RA window count %d (RA_tx_frame %d, RA_tx_subframe %d)\n", __FUNCTION__, frame, nr_slot_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe);
562

cig's avatar
cig committed
563
      if (mac->RA_BI_found){
cig's avatar
cig committed
564
        prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * mac->RA_backoff_indicator;
cig's avatar
cig committed
565 566 567
      } else {
        prach_resources->RA_PREAMBLE_BACKOFF = 0;
      }
568

cig's avatar
cig committed
569 570
      if (mac->RA_window_cnt >= 0 && mac->RA_RAPID_found == 1) {

cig's avatar
cig committed
571 572 573
        // Reset RA_active flag: it disables Msg3 retransmission (8.3 of TS 38.213)
        // TbD Msg3 Retransmissions to be scheduled by DCI 0_0
        mac->RA_active = 0;
574
        mac->RA_window_cnt = -1;
575
        mac->ra_state = RA_SUCCEEDED;
cig's avatar
cig committed
576 577
        mac->generate_nr_prach = 2;
        LOG_I(MAC, "[MAC][UE %d][RAPROC]: RAR successfully received \n", mod_id);
578

cig's avatar
cig committed
579 580
      } else if (mac->RA_window_cnt == 0 && !mac->RA_RAPID_found) {

581
        LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_slot_tx %d: RAR reception failed \n", mod_id, frame, nr_slot_tx);
582

cig's avatar
cig committed
583
        mac->ra_state = RA_UE_IDLE;
cig's avatar
cig committed
584
        mac->RA_PREAMBLE_TRANSMISSION_COUNTER++;
585

cig's avatar
cig committed
586
        preambleTransMax = -1;
cig's avatar
cig committed
587 588
        switch (rach_ConfigGeneric->preambleTransMax) {
        case 0:
589 590
          preambleTransMax = 3;
          break;
cig's avatar
cig committed
591
        case 1:
592 593
          preambleTransMax = 4;
          break;
cig's avatar
cig committed
594
        case 2:
595 596
          preambleTransMax = 5;
          break;
cig's avatar
cig committed
597
        case 3:
598 599
          preambleTransMax = 6;
          break;
cig's avatar
cig committed
600
        case 4:
601 602
          preambleTransMax = 7;
          break;
cig's avatar
cig committed
603
        case 5:
604 605
          preambleTransMax = 8;
          break;
cig's avatar
cig committed
606
        case 6:
607 608
          preambleTransMax = 10;
          break;
cig's avatar
cig committed
609
        case 7:
610 611
          preambleTransMax = 20;
          break;
cig's avatar
cig committed
612
        case 8:
613 614
          preambleTransMax = 50;
          break;
cig's avatar
cig committed
615
        case 9:
616 617
          preambleTransMax = 100;
          break;
cig's avatar
cig committed
618
        case 10:
619 620 621 622
          preambleTransMax = 200;
          break;
        }

cig's avatar
cig committed
623 624 625
        // Resetting RA window
        nr_get_RA_window(mac);

cig's avatar
cig committed
626
        if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax + 1){
627
          LOG_D(MAC, "[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n", mod_id, frame, preambleTransMax);
cig's avatar
cig committed
628 629
          mac->RA_backoff_cnt = rand() % (prach_resources->RA_PREAMBLE_BACKOFF + 1);
          mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
cig's avatar
cig committed
630
          prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP << 1; // 2 dB increment
631
          prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
632 633
        }

cig's avatar
cig committed
634 635 636 637 638
        // 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;
639
        //   mac->RA_backoff_slot  = nr_slot_tx;
cig's avatar
cig committed
640 641 642 643 644
        // }
        // 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;
645 646
        //   mac->RA_window_cnt -= ((10 * frame_diff) + (nr_slot_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_slot_tx, mac->RA_window_cnt);
cig's avatar
cig committed
647
        // }
648

cig's avatar
cig committed
649
        // mac->RA_tx_frame = frame;
650
        // mac->RA_tx_slot  = nr_slot_tx;
651

652
        // Fill in preamble and PRACH resources
653
        if (mac->generate_nr_prach == 1)
cig's avatar
cig committed
654
          nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated);
655

cig's avatar
cig committed
656 657 658 659
      } else {

        mac->RA_window_cnt--;

cig's avatar
cig committed
660
        LOG_D(MAC, "[MAC][UE %d][RAPROC][%d.%d]: RAR not received yet (RA window count %d) \n",
cig's avatar
cig committed
661 662
          mod_id,
          frame,
663
          nr_slot_tx,
cig's avatar
cig committed
664 665 666
          mac->RA_window_cnt);

        // Fill in preamble and PRACH resources
667
        if (mac->generate_nr_prach == 1)
cig's avatar
cig committed
668
          nr_get_prach_resources(mod_id, CC_id, gNB_id, prach_resources, prach_pdu, rach_ConfigDedicated);
669

670 671 672
      }
    }
  } else if (UE_mode == PUSCH) {
cig's avatar
cig committed
673 674
    LOG_D(MAC, "[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...", mod_id);
    AssertFatal(1 == 0, "");
675
  }
cig's avatar
cig committed
676
 return mac->generate_nr_prach;
677
}
cig's avatar
cig committed
678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696

void nr_get_RA_window(NR_UE_MAC_INST_t *mac){

  uint8_t mu, ra_ResponseWindow;
  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;
  NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;

  ra_ResponseWindow = rach_ConfigGeneric->ra_ResponseWindow;

  if (setup->msg1_SubcarrierSpacing)
    mu = *setup->msg1_SubcarrierSpacing;
  else
    mu = frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;

  mac->RA_window_cnt = mac->RA_offset*nr_slots_per_frame[mu]; // taking into account the 2 frames gap introduced by OAI gNB

  switch (ra_ResponseWindow) {
cig's avatar
cig committed
697
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
cig's avatar
cig committed
698 699
      mac->RA_window_cnt += 1;
      break;
cig's avatar
cig committed
700
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
cig's avatar
cig committed
701 702
      mac->RA_window_cnt += 2;
      break;
cig's avatar
cig committed
703
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
cig's avatar
cig committed
704 705
      mac->RA_window_cnt += 4;
      break;
cig's avatar
cig committed
706
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
cig's avatar
cig committed
707 708
      mac->RA_window_cnt += 8;
      break;
cig's avatar
cig committed
709
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
cig's avatar
cig committed
710 711
      mac->RA_window_cnt += 10;
      break;
cig's avatar
cig committed
712
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
cig's avatar
cig committed
713 714
      mac->RA_window_cnt += 20;
      break;
cig's avatar
cig committed
715
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
cig's avatar
cig committed
716 717
      mac->RA_window_cnt += 40;
      break;
cig's avatar
cig committed
718
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
cig's avatar
cig committed
719 720 721
      mac->RA_window_cnt += 80;
      break;
  }
722
}