nr_ra_procedures.c 29 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

/* 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
66
extern const uint8_t nr_slots_per_frame[5];
67

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

70 71
void nr_get_RA_window(NR_UE_MAC_INST_t *mac);

cig's avatar
cig committed
72
// WIP
73 74 75 76 77 78
// 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 first_Msg3,
79
                            NR_PRACH_RESOURCES_t *prach_resources,
Mario Hudon's avatar
Mario Hudon committed
80
                            NR_UE_PRACH *prach_vars,
81 82
                            NR_RACH_ConfigDedicated_t * rach_ConfigDedicated){

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

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

Mario Hudon's avatar
Mario Hudon committed
90 91
  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;
92

93 94 95 96
  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;
  rach_ConfigGeneric = &nr_rach_ConfigCommon->rach_ConfigGeneric;

cig's avatar
cig committed
97
  // NR_RSRP_Range_t rsrp_ThresholdSSB; // todo
98 99 100 101 102

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

Mario Hudon's avatar
Mario Hudon committed
103

cig's avatar
cig committed
104 105 106 107 108 109 110 111 112
  // 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
113

114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129
  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
    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, "[RAPROC] - Selected RA preamble index %d for contention-free random access procedure... \n", prach_resources->ra_PreambleIndex);
  } else {
    //////////* Contention-based RA preamble selection *//////////
    // todo:
    // - selection of SSB with SS-RSRP above rsrp-ThresholdSSB else select any SSB
    // - todo determine next available PRACH occasion
cig's avatar
cig committed
130

131
    // rsrp_ThresholdSSB = *nr_rach_ConfigCommon->rsrp_ThresholdSSB;
cig's avatar
cig committed
132

Mario Hudon's avatar
Mario Hudon committed
133 134 135 136 137 138 139 140 141 142 143 144 145 146
    // 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;
147
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneEighth + 1);
Mario Hudon's avatar
Mario Hudon committed
148 149 150 151
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneFourth:
        multiple_ssb_per_ro = false;
        ssb_rach_ratio = 4;
152
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneFourth + 1);
Mario Hudon's avatar
Mario Hudon committed
153 154 155 156
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_oneHalf:
        multiple_ssb_per_ro = false;
        ssb_rach_ratio = 2;
157
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.oneHalf + 1);
Mario Hudon's avatar
Mario Hudon committed
158 159 160 161
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_one:
        multiple_ssb_per_ro = true;
        ssb_rach_ratio = 1;
162
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.one + 1);
Mario Hudon's avatar
Mario Hudon committed
163 164 165 166
        break;
      case NR_RACH_ConfigCommon__ssb_perRACH_OccasionAndCB_PreamblesPerSSB_PR_two:
        multiple_ssb_per_ro = true;
        ssb_rach_ratio = 2;
167
        cb_preambles_per_ssb = 4 * (nr_rach_ConfigCommon->ssb_perRACH_OccasionAndCB_PreamblesPerSSB->choice.two + 1);
Mario Hudon's avatar
Mario Hudon committed
168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
        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;
    }

189
    Msg3_size = mac->RA_Msg3_size;
cig's avatar
cig committed
190

191 192 193
    numberOfRA_Preambles = 64;
    if(nr_rach_ConfigCommon->totalNumberOfRA_Preambles != NULL)
      numberOfRA_Preambles = *(nr_rach_ConfigCommon->totalNumberOfRA_Preambles);
cig's avatar
cig committed
194

Mario Hudon's avatar
Mario Hudon committed
195 196 197 198 199 200 201 202 203 204 205 206 207
    // 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_vars->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;
    }

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 238 239 240 241 242 243 244 245 246 247 248 249
    if (!nr_rach_ConfigCommon->groupBconfigured) {
      noGroupB = 1;
    } else {
      // RA preambles group B is configured 
      // - 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:
      AssertFatal(1 == 0,"Unknown ra_Msg3SizeGroupA %lu\n", nr_rach_ConfigCommon->groupBconfigured->ra_Msg3SizeGroupA);
      /* todo cases 10 -15*/
      }
cig's avatar
cig committed
250

251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280
      /* 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);
      }
281

282 283 284
      // todo Msg3-DeltaPreamble should be provided from higher layers, otherwise is 0
      mac->deltaPreamble_Msg3 = 0;
      deltaPreamble_Msg3 = mac->deltaPreamble_Msg3;
285 286
    }

287 288 289 290 291 292
    PLThreshold = prach_resources->RA_PCMAX - rach_ConfigGeneric->preambleReceivedTargetPower - deltaPreamble_Msg3 - messagePowerOffsetGroupB;

    /* Msg3 has not been transmitted yet */
    if (first_Msg3 == 1) {
      if (noGroupB == 1) {
        // use Group A preamble
Mario Hudon's avatar
Mario Hudon committed
293
        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
294 295 296 297
        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
Mario Hudon's avatar
Mario Hudon committed
298
        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
299 300 301 302 303
        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
Mario Hudon's avatar
Mario Hudon committed
304
        prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
305 306 307 308
        mac->RA_usedGroupA = 0;
      }
    } else { // Msg3 is being retransmitted
      if (mac->RA_usedGroupA == 1 && noGroupB == 1) {
Mario Hudon's avatar
Mario Hudon committed
309
        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % cb_preambles_per_ssb);
310
      } else if (mac->RA_usedGroupA == 1 && noGroupB == 0){
Mario Hudon's avatar
Mario Hudon committed
311
        prach_resources->ra_PreambleIndex = starting_preamble_nb + ((taus()) % sizeOfRA_PreamblesGroupA);
312
      } else {
Mario Hudon's avatar
Mario Hudon committed
313
        prach_resources->ra_PreambleIndex = starting_preamble_nb + sizeOfRA_PreamblesGroupA + ((taus()) % (cb_preambles_per_ssb - sizeOfRA_PreamblesGroupA));
314
      }
315
    }
316

317
    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
318
  }
319

cig's avatar
cig committed
320 321 322 323
  // 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
324 325 326 327

  /////////////////////////////////////////////////////////////////////////////
  //////////* Random Access Preamble Transmission (5.1.3 TS 38.321) *//////////
  /////////////////////////////////////////////////////////////////////////////
cig's avatar
cig committed
328 329 330
  // 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
331
  // - Extend RA_rnti computation (e.g. f_id selection, ul_carrier_id are hardcoded)
332

cig's avatar
cig committed
333
  if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER > 1)
cig's avatar
cig committed
334
    mac->RA_PREAMBLE_POWER_RAMPING_COUNTER++;
335

336
  prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
337

cig's avatar
cig committed
338
   // RA-RNTI computation (associated to PRACH occasion in which the RA Preamble is transmitted)
339 340 341
   // 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
342 343 344 345 346
   // 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
347
   ul_carrier_id = 0; // NUL
Mario Hudon's avatar
Mario Hudon committed
348 349 350 351
   f_id = prach_vars->prach_pdu.num_ra;
   t_id = prach_vars->prach_pdu.prach_slot;
   s_id = prach_vars->prach_pdu.prach_start_symbol;

352
   prach_resources->ra_RNTI = 1 + s_id + 14 * t_id + 1120 * f_id + 8960 * ul_carrier_id;
cig's avatar
cig committed
353
   mac->ra_rnti = prach_resources->ra_RNTI;
cig's avatar
cig committed
354

355
   LOG_D(MAC, "Computed ra_RNTI is %x \n", prach_resources->ra_RNTI);
356 357
}

cig's avatar
cig committed
358
// TbD: RA_attempt_number not used
359 360
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
361
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
cig's avatar
cig committed
362
  mac->ra_state = WAIT_RAR;
cig's avatar
cig committed
363
  // Start contention resolution timer
cig's avatar
cig committed
364
  mac->RA_attempt_number++;
cig's avatar
cig committed
365
}
366 367 368

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");
369 370 371
  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
372 373
  mac->RA_contention_resolution_cnt = 0;
  mac->RA_contention_resolution_timer_active = 1;
374 375 376 377 378 379 380 381
}

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

cig's avatar
cig committed
384
// WIP
cig's avatar
cig committed
385 386 387 388 389 390 391 392 393 394 395
// 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)
396

cig's avatar
cig committed
397
uint8_t nr_ue_get_rach(NR_PRACH_RESOURCES_t *prach_resources,
Mario Hudon's avatar
Mario Hudon committed
398
                       NR_UE_PRACH *prach_vars,
cig's avatar
cig committed
399 400 401 402 403 404
                       module_id_t mod_id,
                       int CC_id,
                       UE_MODE_t UE_mode,
                       frame_t frame,
                       uint8_t gNB_id,
                       int nr_tti_tx){
405

cig's avatar
cig committed
406
  NR_UE_MAC_INST_t *mac = get_mac_inst(mod_id);
407
  uint8_t mac_sdus[MAX_NR_ULSCH_PAYLOAD_BYTES];
408 409
  uint8_t lcid = UL_SCH_LCID_CCCH_MSG3, *payload;
  //uint8_t ra_ResponseWindow;
cig's avatar
cig committed
410 411
  uint16_t size_sdu = 0;
  unsigned short post_padding;
412
  //fapi_nr_config_request_t *cfg = &mac->phy_config.config_req;
cig's avatar
cig committed
413 414 415
  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;
416
  //NR_FrequencyInfoDL_t *frequencyInfoDL = scc->downlinkConfigCommon->frequencyInfoDL;
417 418
  NR_RACH_ConfigDedicated_t *rach_ConfigDedicated = mac->rach_ConfigDedicated;

cig's avatar
cig committed
419
  // int32_t frame_diff = 0;
420

cig's avatar
cig committed
421 422
  uint8_t sdu_lcids[NB_RB_MAX] = {0};
  uint16_t sdu_lengths[NB_RB_MAX] = {0};
Laurent's avatar
Laurent committed
423
  int TBS_bytes = 848, header_length_total=0, num_sdus, offset, preambleTransMax, mac_ce_len;
424 425 426

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

427
  if (UE_mode < PUSCH && prach_resources->init_msg1) {
cig's avatar
cig committed
428

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

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

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

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

cig's avatar
cig committed
438
      mac->RA_RAPID_found = 0;
439 440

      /* Set RA_PREAMBLE_POWER_RAMPING_STEP */
cig's avatar
cig committed
441
      switch (rach_ConfigGeneric->powerRampingStep){ // in dB
442 443 444 445 446 447 448 449 450 451 452 453 454 455
       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
456
      prach_resources->RA_PREAMBLE_BACKOFF = 0;
457
      prach_resources->RA_SCALING_FACTOR_BI = 1;
cig's avatar
cig committed
458 459
      prach_resources->RA_PCMAX = 0; // currently hardcoded to 0

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

cig's avatar
cig committed
462 463 464
      mac_ce_len = 0;
      num_sdus = 1;
      post_padding = 1;
cig's avatar
cig committed
465

466
      if (0){
cig's avatar
cig committed
467 468
        // initialisation by RRC
        // CCCH PDU
cig's avatar
cig committed
469 470 471 472 473 474 475 476 477
        // 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
478 479 480
      } else {
        // fill ulsch_buffer with random data
        for (int i = 0; i < TBS_bytes; i++){
481
          mac_sdus[i] = (unsigned char) (lrand48()&0xff);
cig's avatar
cig committed
482 483 484
        }
        //Sending SDUs with size 1
        //Initialize elements of sdu_lcids and sdu_lengths
cig's avatar
cig committed
485 486
        sdu_lcids[0] = lcid;
        sdu_lengths[0] = TBS_bytes - 3 - post_padding - mac_ce_len;
cig's avatar
cig committed
487 488 489
        header_length_total += 2 + (sdu_lengths[0] >= 128);
        size_sdu += sdu_lengths[0];
      }
490

cig's avatar
cig committed
491 492 493 494
      //mac->RA_tx_frame = frame;
      //mac->RA_tx_subframe = nr_tti_tx;
      //mac->RA_backoff_frame = frame;
      //mac->RA_backoff_subframe = nr_tti_tx;
495

cig's avatar
cig committed
496
      if (size_sdu > 0) {
497 498 499

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

cig's avatar
cig committed
500 501
        mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
        mac->RA_PREAMBLE_POWER_RAMPING_COUNTER = 1;
cig's avatar
cig committed
502
        mac->RA_Msg3_size = size_sdu + sizeof(NR_MAC_SUBHEADER_SHORT) + sizeof(NR_MAC_SUBHEADER_SHORT);
cig's avatar
cig committed
503
        mac->RA_prachMaskIndex = 0;
cig's avatar
cig committed
504
        // todo: add the backoff condition here
cig's avatar
cig committed
505 506
        mac->RA_backoff_cnt = 0;
        mac->RA_active = 1;
cig's avatar
cig committed
507
        prach_resources->Msg3 = payload;
508

cig's avatar
cig committed
509
        nr_get_RA_window(mac);
510 511

        // Fill in preamble and PRACH resources
512
        if (mac->generate_nr_prach == 1)
Mario Hudon's avatar
Mario Hudon committed
513
          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated);
514

cig's avatar
cig committed
515
        offset = nr_generate_ulsch_pdu((uint8_t *) mac_sdus,              // sdus buffer
cig's avatar
cig committed
516
                                       (uint8_t *) payload,               // UL MAC pdu pointer
cig's avatar
cig committed
517 518 519 520 521 522 523 524
                                       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
525 526
                                       post_padding,
                                       0);
cig's avatar
cig committed
527

cig's avatar
cig committed
528
        // Padding: fill remainder with 0
cig's avatar
cig committed
529 530 531 532 533
        if (post_padding > 0){
          for (int j = 0; j < (TBS_bytes - offset); j++)
            payload[offset + j] = 0; // mac_pdu[offset + j] = 0;
        }
      } 
534
    } else if (mac->RA_window_cnt != -1) { // RACH is active
535 536 537 538

      ////////////////////////////////////////////////////////////////
      /////* Random Access Response reception (5.1.4 TS 38.321) */////
      ////////////////////////////////////////////////////////////////
cig's avatar
cig committed
539 540 541 542 543
      // 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
544
      // - handle backoff and raResponseWindow params
545

cig's avatar
cig committed
546 547
      // 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",
      //   mod_id, frame, nr_tti_tx, mac->RA_window_cnt, mac->RA_tx_frame, mac->RA_tx_subframe);
548

cig's avatar
cig committed
549
      if (mac->RA_BI_found){
cig's avatar
cig committed
550
        prach_resources->RA_PREAMBLE_BACKOFF = prach_resources->RA_SCALING_FACTOR_BI * mac->RA_backoff_indicator;
cig's avatar
cig committed
551 552 553
      } else {
        prach_resources->RA_PREAMBLE_BACKOFF = 0;
      }
554

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

cig's avatar
cig committed
557 558 559
        // 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;
560
        mac->RA_window_cnt = -1;
561
        mac->ra_state = RA_SUCCEEDED;
cig's avatar
cig committed
562 563
        mac->generate_nr_prach = 2;
        LOG_I(MAC, "[MAC][UE %d][RAPROC]: RAR successfully received \n", mod_id);
564

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

567
        LOG_I(MAC, "[MAC][UE %d][RAPROC] Frame %d: nr_tti_tx %d: RAR reception failed \n", mod_id, frame, nr_tti_tx);
568

cig's avatar
cig committed
569
        mac->ra_state = RA_UE_IDLE;
cig's avatar
cig committed
570
        mac->RA_PREAMBLE_TRANSMISSION_COUNTER++;
571

cig's avatar
cig committed
572
        preambleTransMax = -1;
cig's avatar
cig committed
573 574
        switch (rach_ConfigGeneric->preambleTransMax) {
        case 0:
575 576
          preambleTransMax = 3;
          break;
cig's avatar
cig committed
577
        case 1:
578 579
          preambleTransMax = 4;
          break;
cig's avatar
cig committed
580
        case 2:
581 582
          preambleTransMax = 5;
          break;
cig's avatar
cig committed
583
        case 3:
584 585
          preambleTransMax = 6;
          break;
cig's avatar
cig committed
586
        case 4:
587 588
          preambleTransMax = 7;
          break;
cig's avatar
cig committed
589
        case 5:
590 591
          preambleTransMax = 8;
          break;
cig's avatar
cig committed
592
        case 6:
593 594
          preambleTransMax = 10;
          break;
cig's avatar
cig committed
595
        case 7:
596 597
          preambleTransMax = 20;
          break;
cig's avatar
cig committed
598
        case 8:
599 600
          preambleTransMax = 50;
          break;
cig's avatar
cig committed
601
        case 9:
602 603
          preambleTransMax = 100;
          break;
cig's avatar
cig committed
604
        case 10:
605 606 607 608
          preambleTransMax = 200;
          break;
        }

cig's avatar
cig committed
609 610 611
        // Resetting RA window
        nr_get_RA_window(mac);

cig's avatar
cig committed
612
        if (mac->RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax + 1){
613
          LOG_D(MAC, "[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n", mod_id, frame, preambleTransMax);
cig's avatar
cig committed
614 615
          mac->RA_backoff_cnt = rand() % (prach_resources->RA_PREAMBLE_BACKOFF + 1);
          mac->RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
cig's avatar
cig committed
616
          prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP += prach_resources->RA_PREAMBLE_POWER_RAMPING_STEP << 1; // 2 dB increment
617
          prach_resources->ra_PREAMBLE_RECEIVED_TARGET_POWER = nr_get_Po_NOMINAL_PUSCH(prach_resources, mod_id, CC_id);
618 619
        }

cig's avatar
cig committed
620 621 622 623 624 625 626 627 628 629 630 631 632 633
        // 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);
        // }
634

cig's avatar
cig committed
635 636
        // mac->RA_tx_frame = frame;
        // mac->RA_tx_subframe = nr_tti_tx;
637

638
        // Fill in preamble and PRACH resources
639
        if (mac->generate_nr_prach == 1)
Mario Hudon's avatar
Mario Hudon committed
640
          nr_get_prach_resources(mod_id, CC_id, gNB_id, nr_tti_tx, prach_resources, prach_vars, rach_ConfigDedicated);
641

cig's avatar
cig committed
642 643 644 645
      } else {

        mac->RA_window_cnt--;

cig's avatar
cig committed
646
        LOG_D(MAC, "[MAC][UE %d][RAPROC][%d.%d]: RAR not received yet (RA window count %d) \n",
cig's avatar
cig committed
647 648 649 650 651 652
          mod_id,
          frame,
          nr_tti_tx,
          mac->RA_window_cnt);

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

656 657 658
      }
    }
  } else if (UE_mode == PUSCH) {
cig's avatar
cig committed
659 660
    LOG_D(MAC, "[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...", mod_id);
    AssertFatal(1 == 0, "");
661
  }
cig's avatar
cig committed
662
 return mac->generate_nr_prach;
663
}
cig's avatar
cig committed
664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682

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
683
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
cig's avatar
cig committed
684 685
      mac->RA_window_cnt += 1;
      break;
cig's avatar
cig committed
686
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
cig's avatar
cig committed
687 688
      mac->RA_window_cnt += 2;
      break;
cig's avatar
cig committed
689
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
cig's avatar
cig committed
690 691
      mac->RA_window_cnt += 4;
      break;
cig's avatar
cig committed
692
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
cig's avatar
cig committed
693 694
      mac->RA_window_cnt += 8;
      break;
cig's avatar
cig committed
695
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
cig's avatar
cig committed
696 697
      mac->RA_window_cnt += 10;
      break;
cig's avatar
cig committed
698
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
cig's avatar
cig committed
699 700
      mac->RA_window_cnt += 20;
      break;
cig's avatar
cig committed
701
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
cig's avatar
cig committed
702 703
      mac->RA_window_cnt += 40;
      break;
cig's avatar
cig committed
704
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
cig's avatar
cig committed
705 706 707
      mac->RA_window_cnt += 80;
      break;
  }
708
}