gNB_scheduler_RA.c 35.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
/*
 * 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
 */

22 23 24 25 26
/*! \file     gNB_scheduler_RA.c
 * \brief     primitives used for random access
 * \author    Guido Casati
 * \date      2019
 * \email:    guido.casati@iis.fraunhofer.de
27 28 29
 * \version
 */

30
#include "platform_types.h"
31

cig's avatar
cig committed
32
/* MAC */
33 34 35
#include "nr_mac_gNB.h"
#include "NR_MAC_gNB/mac_proto.h"
#include "NR_MAC_COMMON/nr_mac_extern.h"
36

cig's avatar
cig committed
37 38 39
/* Utils */
#include "common/utils/LOG/log.h"
#include "common/utils/LOG/vcd_signal_dumper.h"
cig's avatar
cig committed
40
#include "common/utils/nr/nr_common.h"
41
#include "UTIL/OPT/opt.h"
cig's avatar
cig committed
42
#include "SIMULATION/TOOLS/sim.h" // for taus
43

cig's avatar
cig committed
44
extern RAN_CONTEXT_t RC;
cig's avatar
cig committed
45
extern const uint8_t nr_slots_per_frame[5];
46

47
uint8_t DELTA[4]= {2,3,4,6};
48 49 50 51 52 53 54 55

void schedule_nr_prach(module_id_t module_idP, frame_t frameP, sub_frame_t slotP) {

  gNB_MAC_INST *gNB = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = gNB->common_channels;
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
  nfapi_nr_ul_tti_request_t *UL_tti_req = &RC.nrmac[module_idP]->UL_tti_req[0];

56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115
  if (is_nr_UL_slot(scc,slotP)) {

    uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
    uint8_t mu,N_dur,N_t_slot,start_symbol;
    uint16_t format;

    if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing)
      mu = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg1_SubcarrierSpacing;
    else
      mu = scc->downlinkConfigCommon->frequencyInfoDL->scs_SpecificCarrierList.list.array[0]->subcarrierSpacing;

    // prach is scheduled according to configuration index and tables 6.3.3.2.2 to 6.3.3.2.4
    if ( get_nr_prach_info_from_index(config_index,
                                      (int)frameP,
                                      (int)slotP,
                                      scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
                                      mu,
                                      cc->frame_type,
                                      &format,
                                      &start_symbol,
                                      &N_t_slot,
                                      &N_dur) ) {

      int fdm = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.msg1_FDM;
      uint16_t format0 = format&0xff;      // first column of format from table
      uint16_t format1 = (format>>8)&0xff; // second column of format from table

      UL_tti_req->SFN = frameP;
      UL_tti_req->Slot = slotP;
      for (int n=0; n<(1<<fdm); n++) { // one structure per frequency domain occasion
        UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PRACH_PDU_TYPE;
        UL_tti_req->pdus_list[UL_tti_req->n_pdus].pdu_size = sizeof(nfapi_nr_prach_pdu_t);
        nfapi_nr_prach_pdu_t  *prach_pdu = &UL_tti_req->pdus_list[UL_tti_req->n_pdus].prach_pdu;
        memset(prach_pdu,0,sizeof(nfapi_nr_prach_pdu_t));
        UL_tti_req->n_pdus+=1;

        // filling the prach fapi structure
        prach_pdu->phys_cell_id = *scc->physCellId;
        prach_pdu->num_prach_ocas = N_t_slot;
        prach_pdu->prach_start_symbol = start_symbol;
        prach_pdu->num_ra = n;
        prach_pdu->num_cs = get_NCS(scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.zeroCorrelationZoneConfig,
                                    format0,
                                    scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->restrictedSetConfig);
        // SCF PRACH PDU format field does not consider A1/B1 etc. possibilities
        // We added 9 = A1/B1 10 = A2/B2 11 A3/B3
        if (format1!=0xff) {
          switch(format0) {
            case 0xa1:
              prach_pdu->prach_format = 9;
              break;
            case 0xa2:
              prach_pdu->prach_format = 10;
              break;
            case 0xa3:
              prach_pdu->prach_format = 11;
              break;
          default:
            AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
          }
116
        }
117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 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
        else{
          switch(format0) {
            case 0xa1:
              prach_pdu->prach_format = 0;
              break;
            case 0xa2:
              prach_pdu->prach_format = 1;
              break;
            case 0xa3:
              prach_pdu->prach_format = 2;
              break;
            case 0xb1:
              prach_pdu->prach_format = 3;
              break;
            case 0xb2:
              prach_pdu->prach_format = 4;
              break;
            case 0xb3:
              prach_pdu->prach_format = 5;
              break;
            case 0xb4:
              prach_pdu->prach_format = 6;
              break;
            case 0xc0:
              prach_pdu->prach_format = 7;
              break;
            case 0xc2:
              prach_pdu->prach_format = 8;
              break;
            case 0:
              // long formats are handled @ PHY
              break;
            case 1:
              // long formats are handled @ PHY
              break;
            case 2:
              // long formats are handled @ PHY
              break;
            case 3:
              // long formats are handled @ PHY
              break;
          default:
            AssertFatal(1==0,"Invalid PRACH format");
          }
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188
        }
      }
    }
  }
}

void nr_schedule_msg2(uint16_t rach_frame, uint16_t rach_slot,
                      uint16_t *msg2_frame, uint16_t *msg2_slot,
                      NR_ServingCellConfigCommon_t *scc,
                      uint16_t monitoring_slot_period,
                      uint16_t monitoring_offset){

  // preferentially we schedule the msg2 in the mixed slot or in the last dl slot
  // if they are allowed by search space configuration

  uint8_t mu = *scc->ssbSubcarrierSpacing;
  uint8_t response_window = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.ra_ResponseWindow;
  uint8_t slot_window;
  // number of mixed slot or of last dl slot if there is no mixed slot
  uint8_t last_dl_slot_period = scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots;
  // lenght of tdd period in slots
  uint8_t tdd_period_slot =  scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSlots + scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSlots;
  if (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols == 0)
    last_dl_slot_period--;
  if ((scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofDownlinkSymbols > 0) || (scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols > 0))
    tdd_period_slot++;

  // computing start of next period
cig's avatar
cig committed
189
  uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu];
190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220
  *msg2_slot = start_next_period + last_dl_slot_period; // initializing scheduling of slot to next mixed (or last dl) slot
  *msg2_frame = (*msg2_slot>(rach_slot))? rach_frame : (rach_frame +1);

  switch(response_window){
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl1:
      slot_window = 1;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl2:
      slot_window = 2;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl4:
      slot_window = 4;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl8:
      slot_window = 8;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl10:
      slot_window = 10;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl20:
      slot_window = 20;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl40:
      slot_window = 40;
      break;
    case NR_RACH_ConfigGeneric__ra_ResponseWindow_sl80:
      slot_window = 80;
      break;
    default:
      AssertFatal(1==0,"Invalid response window value %d\n",response_window);
  }
cig's avatar
cig committed
221
  AssertFatal(slot_window<=nr_slots_per_frame[mu],"Msg2 response window needs to be lower or equal to 10ms");
222 223

  // slot and frame limit to transmit msg2 according to response window
cig's avatar
cig committed
224
  uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu];
225
  //uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1);
226 227 228 229


  // go to previous slot if the current scheduled slot is beyond the response window
  // and if the slot is not among the PDCCH monitored ones (38.213 10.1)
cig's avatar
cig committed
230
  while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0))  {
231
    if((*msg2_slot%tdd_period_slot) > 0)
Raphael Defosseux's avatar
Raphael Defosseux committed
232
      (*msg2_slot)--;
233 234 235
    else
      AssertFatal(1==0,"No available DL slot to schedule msg2 has been found");
  }
cig's avatar
cig committed
236
}
237

238

239 240 241 242 243
void nr_initiate_ra_proc(module_id_t module_idP,
                         int CC_id,
                         frame_t frameP,
                         sub_frame_t slotP,
                         uint16_t preamble_index,
244 245
                         uint8_t freq_index,
                         uint8_t symbol,
246 247
                         int16_t timing_offset){

248 249 250 251
  uint8_t ul_carrier_id = 0; // 0 for NUL 1 for SUL
  NR_SearchSpace_t *ss;
  // ra_rnti from 5.1.3 in 38.321
  uint16_t ra_rnti=1+symbol+(slotP*14)+(freq_index*14*80)+(ul_carrier_id*14*80*8);
252

253
  uint16_t msg2_frame, msg2_slot,monitoring_slot_period,monitoring_offset;
cig's avatar
cig committed
254 255
  gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
256
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
257 258
  NR_RA_t *ra = &cc->ra[0];

259 260 261
  // if the preamble received correspond to one of the listed
  // the UE sent a RACH either for starting RA procedure or RA procedure failed and UE retries
  int pr_found=0;
262 263
  for (int i = 0; i < ra->preambles.num_preambles; i++) {
    if (preamble_index == ra->preambles.preamble_list[i]) {
264 265 266 267
      pr_found=1;
      break;
    }
  }
268
  if (!pr_found) {
269 270
    LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: preamble %d does not correspond to any of the ones in rach_ConfigDedicated\n",
          module_idP, preamble_index);
271 272 273
    return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
  }

274 275
  // This should be handled differently when we use the initialBWP for RA
  ra->bwp_id=1;
276
  NR_BWP_Downlink_t *bwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1];
277

cig's avatar
cig committed
278
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1);
279

Francesco Mani's avatar
Francesco Mani committed
280
  LOG_I(MAC, "[gNB %d][RAPROC] CC_id %d Frame %d, Slot %d  Initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, slotP, preamble_index);
281

cig's avatar
cig committed
282 283
  if (ra->state == RA_IDLE) {
    int loop = 0;
Francesco Mani's avatar
Francesco Mani committed
284
    LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
cig's avatar
cig committed
285 286
    ra->state = Msg2;
    ra->timing_offset = timing_offset;
287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304
    ra->preamble_slot = slotP;

    struct NR_PDCCH_ConfigCommon__commonSearchSpaceList *commonSearchSpaceList = bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->commonSearchSpaceList;
    AssertFatal(commonSearchSpaceList->list.count>0,
	        "common SearchSpace list has 0 elements\n");
    // Common searchspace list
    for (int i=0;i<commonSearchSpaceList->list.count;i++) {
      ss=commonSearchSpaceList->list.array[i];
      if(ss->searchSpaceId == *bwp->bwp_Common->pdcch_ConfigCommon->choice.setup->ra_SearchSpace)
        ra->ra_ss=ss;
    }

    // retrieving ra pdcch monitoring period and offset
    find_monitoring_periodicity_offset_common(ra->ra_ss,
                                              &monitoring_slot_period,
                                              &monitoring_offset);

    nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset);
305

cig's avatar
cig committed
306
    ra->Msg2_frame = msg2_frame;
cig's avatar
cig committed
307
    ra->Msg2_slot = msg2_slot;
308

309
    LOG_D(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
310

Francesco Mani's avatar
Francesco Mani committed
311 312 313 314 315 316 317 318 319 320
    if (!ra->cfra) {
      do {
        ra->rnti = (taus() % 65518) + 1;
        loop++;
      }
      while (loop != 100 && !(find_nr_UE_id(module_idP, ra->rnti) == -1 && ra->rnti >= 1 && ra->rnti <= 65519));
      if (loop == 100) {
        LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
        abort();
      }
cig's avatar
cig committed
321 322 323
    }
    ra->RA_rnti = ra_rnti;
    ra->preamble_index = preamble_index;
324

325
    LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x\n",
cig's avatar
cig committed
326 327 328 329
      module_idP,
      CC_id,
      frameP,
      ra->Msg2_frame,
cig's avatar
cig committed
330
      ra->Msg2_slot,
331
      ra->RA_rnti);
332

cig's avatar
cig committed
333
    return;
334
  }
cig's avatar
cig committed
335
  LOG_E(MAC, "[gNB %d][RAPROC] FAILURE: CC_id %d Frame %d initiating RA procedure for preamble index %d\n", module_idP, CC_id, frameP, preamble_index);
336

cig's avatar
cig committed
337
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
338 339 340 341
}

void nr_schedule_RA(module_id_t module_idP, frame_t frameP, sub_frame_t slotP){

cig's avatar
cig committed
342 343
  //uint8_t i = 0;
  int CC_id = 0;
cig's avatar
cig committed
344
  gNB_MAC_INST *mac = RC.nrmac[module_idP];
cig's avatar
cig committed
345 346
  NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
  NR_RA_t *ra = &cc->ra[0];
347 348 349

  start_meas(&mac->schedule_ra);

cig's avatar
cig committed
350 351 352 353
  //for (i = 0; i < NR_NB_RA_PROC_MAX; i++) {
  LOG_D(MAC,"RA[state:%d]\n",ra->state);
  switch (ra->state){
    case Msg2:
354 355
      nr_generate_Msg2(module_idP, CC_id, frameP, slotP);
      break;
cig's avatar
cig committed
356
    case Msg4:
357 358
      //generate_Msg4(module_idP, CC_id, frameP, slotP, ra);
      break;
cig's avatar
cig committed
359
    case WAIT_Msg4_ACK:
360 361
      //check_Msg4_retransmission(module_idP, CC_id, frameP, slotP, ra);
      break;
cig's avatar
cig committed
362
    default:
cig's avatar
cig committed
363
    break;
cig's avatar
cig committed
364
  }
cig's avatar
cig committed
365
  //}
366 367 368
  stop_meas(&mac->schedule_ra);
}

369
void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc,
370
                      NR_BWP_Uplink_t *ubwp,
371 372 373 374
                      sub_frame_t current_slot,
                      frame_t current_frame,
                      NR_RA_t *ra) {

375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391
  // msg3 is schedulend in mixed slot in the following TDD period
  // for now we consider a TBS of 18 bytes

  int mu = ubwp->bwp_Common->genericParameters.subcarrierSpacing;
  int StartSymbolIndex, NrOfSymbols, startSymbolAndLength, temp_slot;
  ra->Msg3_tda_id = 16; // initialization to a value above limit

  for (int i=0; i<ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.count; i++) {
    startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength;
    SLIV2SL(startSymbolAndLength, &StartSymbolIndex, &NrOfSymbols);
    // we want to transmit in the uplink symbols of mixed slot
    if (NrOfSymbols == scc->tdd_UL_DL_ConfigurationCommon->pattern1.nrofUplinkSymbols) {
      ra->Msg3_tda_id = i;
      break;
    }
  }
  AssertFatal(ra->Msg3_tda_id<16,"Unable to find Msg3 time domain allocation in list\n");
392

393 394 395
  uint8_t k2 = *ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->k2;

  temp_slot = current_slot + k2 + DELTA[mu]; // msg3 slot according to 8.3 in 38.213
cig's avatar
cig committed
396 397
  ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu];
  if (nr_slots_per_frame[mu]>temp_slot)
398 399
    ra->Msg3_frame = current_frame;
  else
cig's avatar
cig committed
400
    ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]);
401 402 403

  ra->msg3_nb_rb = 18;
  ra->msg3_first_rb = 0;
404 405
}

406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424

void nr_schedule_reception_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){
  gNB_MAC_INST                                *mac = RC.nrmac[module_idP];
  nfapi_nr_ul_tti_request_t                   *ul_req = &mac->UL_tti_req[0];
  NR_COMMON_channels_t                        *cc = &mac->common_channels[CC_id];
  NR_RA_t                                     *ra = &cc->ra[0];

  if (ra->state == WAIT_Msg3) {
    if ((frameP == ra->Msg3_frame) && (slotP == ra->Msg3_slot) ){
      ul_req->SFN = ra->Msg3_frame;
      ul_req->Slot = ra->Msg3_slot;
      ul_req->pdus_list[ul_req->n_pdus].pdu_type = NFAPI_NR_UL_CONFIG_PUSCH_PDU_TYPE;
      ul_req->pdus_list[ul_req->n_pdus].pdu_size = sizeof(nfapi_nr_pusch_pdu_t);
      ul_req->pdus_list[ul_req->n_pdus].pusch_pdu = ra->pusch_pdu;
      ul_req->n_pdus+=1;
    }
  }
}

cig's avatar
cig committed
425 426 427 428 429 430 431
void nr_add_msg3(module_id_t module_idP, int CC_id, frame_t frameP, sub_frame_t slotP){

  gNB_MAC_INST                                   *mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t                            *cc = &mac->common_channels[CC_id];
  NR_ServingCellConfigCommon_t                   *scc = cc->ServingCellConfigCommon;
  NR_RA_t                                         *ra = &cc->ra[0];

432
  if (ra->state == RA_IDLE) {
433 434 435
    LOG_W(MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti);
    return;
  }
cig's avatar
cig committed
436 437

  LOG_D(MAC, "[gNB %d][RAPROC] Frame %d, Subframe %d : CC_id %d RA is active, Msg3 in (%d,%d)\n", module_idP, frameP, slotP, CC_id, ra->Msg3_frame, ra->Msg3_slot);
438 439

  nfapi_nr_pusch_pdu_t  *pusch_pdu = &ra->pusch_pdu;
cig's avatar
cig committed
440
  memset(pusch_pdu, 0, sizeof(nfapi_nr_pusch_pdu_t));
441

442 443 444 445 446 447
  AssertFatal(ra->secondaryCellGroup,
              "no secondaryCellGroup for RNTI %04x\n",
              ra->crnti);
  AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
    "downlinkBWP_ToAddModList has %d BWP!\n", ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
  NR_BWP_Uplink_t *ubwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id - 1];
cig's avatar
cig committed
448 449 450 451 452 453 454 455 456 457
  LOG_D(MAC, "Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d) : (%d,%d,%d) for rnti: %d\n",
    frameP,
    slotP,
    ra->Msg3_frame,
    ra->Msg3_slot,
    ra->msg3_nb_rb,
    ra->msg3_first_rb,
    ra->msg3_round,
    ra->rnti);

458 459 460 461
  int startSymbolAndLength = ubwp->bwp_Common->pusch_ConfigCommon->choice.setup->pusch_TimeDomainAllocationList->list.array[ra->Msg3_tda_id]->startSymbolAndLength;
  int start_symbol_index,nr_of_symbols;
  SLIV2SL(startSymbolAndLength, &start_symbol_index, &nr_of_symbols);

cig's avatar
cig committed
462 463 464
  pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
  pusch_pdu->rnti = ra->rnti;
  pusch_pdu->handle = 0;
465 466 467 468 469 470 471 472 473
  int abwp_size  = NRRIV2BW(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275);
  int abwp_start = NRRIV2PRBOFFSET(ubwp->bwp_Common->genericParameters.locationAndBandwidth,275);
  int ibwp_size  = NRRIV2BW(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275);
  int ibwp_start = NRRIV2PRBOFFSET(scc->uplinkConfigCommon->initialUplinkBWP->genericParameters.locationAndBandwidth,275);
  if ((ibwp_start < abwp_start) || (ibwp_size > abwp_size))
    pusch_pdu->bwp_start = abwp_start;
  else
    pusch_pdu->bwp_start = ibwp_start;
  pusch_pdu->bwp_size = ibwp_size;
cig's avatar
cig committed
474 475
  pusch_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing;
  pusch_pdu->cyclic_prefix = 0;
476
  pusch_pdu->mcs_index = 0;
cig's avatar
cig committed
477 478 479
  pusch_pdu->mcs_table = 0;
  pusch_pdu->target_code_rate = nr_get_code_rate_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table);
  pusch_pdu->qam_mod_order = nr_get_Qm_ul(pusch_pdu->mcs_index,pusch_pdu->mcs_table);
480 481 482 483 484
  if (scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->msg3_transformPrecoder == NULL)
    pusch_pdu->transform_precoding = 1;
  else
    pusch_pdu->transform_precoding = 0;
  pusch_pdu->data_scrambling_id = *scc->physCellId;
cig's avatar
cig committed
485
  pusch_pdu->nrOfLayers = 1;
486
  pusch_pdu->ul_dmrs_symb_pos = 1<<start_symbol_index; // ok for now but use fill dmrs mask later
cig's avatar
cig committed
487
  pusch_pdu->dmrs_config_type = 0;
488
  pusch_pdu->ul_dmrs_scrambling_id = *scc->physCellId; //If provided and the PUSCH is not a msg3 PUSCH, otherwise, L2 should set this to physical cell id.
cig's avatar
cig committed
489
  pusch_pdu->scid = 0; //DMRS sequence initialization [TS38.211, sec 6.4.1.1.1]. Should match what is sent in DCI 0_1, otherwise set to 0.
490 491
  pusch_pdu->dmrs_ports = 1;  // 6.2.2 in 38.214 only port 0 to be used
  pusch_pdu->num_dmrs_cdm_grps_no_data = 2;  // no data in dmrs symbols as in 6.2.2 in 38.214
cig's avatar
cig committed
492
  pusch_pdu->resource_alloc = 1; //type 1
493 494 495 496 497
  pusch_pdu->rb_start = ra->msg3_first_rb + ibwp_start - abwp_start; // as for 6.3.1.7 in 38.211
  if (ra->msg3_nb_rb > pusch_pdu->bwp_size)
    AssertFatal(1==0,"MSG3 allocated number of RBs exceed the BWP size\n");
  else
    pusch_pdu->rb_size = ra->msg3_nb_rb;
cig's avatar
cig committed
498
  pusch_pdu->vrb_to_prb_mapping = 0;
499 500 501 502
  if (ubwp->bwp_Dedicated->pusch_Config->choice.setup->frequencyHopping == NULL)
    pusch_pdu->frequency_hopping = 0;
  else
    pusch_pdu->frequency_hopping = 1;
cig's avatar
cig committed
503 504 505
  //pusch_pdu->tx_direct_current_location;//The uplink Tx Direct Current location for the carrier. Only values in the value range of this field between 0 and 3299, which indicate the subcarrier index within the carrier corresponding 1o the numerology of the corresponding uplink BWP and value 3300, which indicates "Outside the carrier" and value 3301, which indicates "Undetermined position within the carrier" are used. [TS38.331, UplinkTxDirectCurrentBWP IE]
  pusch_pdu->uplink_frequency_shift_7p5khz = 0;
  //Resource Allocation in time domain
506 507
  pusch_pdu->start_symbol_index = start_symbol_index;
  pusch_pdu->nr_of_symbols = nr_of_symbols;
cig's avatar
cig committed
508
  //Optional Data only included if indicated in pduBitmap
509
  pusch_pdu->pusch_data.rv_index = 0;  // 8.3 in 38.213
cig's avatar
cig committed
510
  pusch_pdu->pusch_data.harq_process_id = 0;
511 512 513
  pusch_pdu->pusch_data.new_data_indicator = 1; // new data
  pusch_pdu->pusch_data.num_cb = 0;
  pusch_pdu->pusch_data.tb_size = nr_compute_tbs(pusch_pdu->qam_mod_order,
cig's avatar
cig committed
514 515 516
                                                 pusch_pdu->target_code_rate,
                                                 pusch_pdu->rb_size,
                                                 pusch_pdu->nr_of_symbols,
517
                                                 12, // nb dmrs set for no data in dmrs symbol
cig's avatar
cig committed
518
                                                 0, //nb_rb_oh
519
                                                 0, // to verify tb scaling
520 521 522 523 524
                                                 pusch_pdu->nrOfLayers = 1)>>3;

  // calling function to fill rar message
  nr_fill_rar(module_idP, ra, cc->RAR_pdu.payload, pusch_pdu);

cig's avatar
cig committed
525 526
}

cig's avatar
cig committed
527
// WIP
cig's avatar
cig committed
528 529 530
// todo:
// - fix me
// - get msg3 alloc (see nr_process_rar)
cig's avatar
cig committed
531 532 533 534 535
void nr_generate_Msg2(module_id_t module_idP,
                      int CC_id,
                      frame_t frameP,
                      sub_frame_t slotP){

536
  int dci_formats[2], rnti_types[2], mcsIndex;
537
  int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0;
cig's avatar
cig committed
538 539 540
  gNB_MAC_INST                      *nr_mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t                  *cc = &nr_mac->common_channels[0];
  NR_RA_t                               *ra = &cc->ra[0];
541
  NR_SearchSpace_t *ss = ra->ra_ss;
cig's avatar
cig committed
542

543
  uint16_t RA_rnti = ra->RA_rnti;
cig's avatar
cig committed
544 545
  long locationAndBandwidth;

546 547 548 549 550 551 552 553 554 555 556 557 558 559
  // check if UE is doing RA on CORESET0 , InitialBWP or configured BWP from SCD
  // get the BW of the PDCCH for PDCCH size and RAR PDSCH size

  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
  int dci10_bw;

  if (ra->coreset0_configured == 1) {
    AssertFatal(1==0,"This is a standalone condition\n");
  }
  else { // on configured BWP or initial LDBWP, bandwidth parameters in DCI correspond size of initialBWP
    locationAndBandwidth = scc->downlinkConfigCommon->initialDownlinkBWP->genericParameters.locationAndBandwidth;
    dci10_bw = NRRIV2BW(locationAndBandwidth,275); 
  }

cig's avatar
cig committed
560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576
  if ((ra->Msg2_frame == frameP) && (ra->Msg2_slot == slotP)) {

    nfapi_nr_dl_tti_request_body_t *dl_req = &nr_mac->DL_req[CC_id].dl_tti_request_body;
    nfapi_nr_pdu_t *tx_req = &nr_mac->TX_req[CC_id].pdu_list[nr_mac->TX_req[CC_id].Number_of_PDUs];

    nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdcch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs];
    memset((void*)dl_tti_pdcch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
    dl_tti_pdcch_pdu->PDUType = NFAPI_NR_DL_TTI_PDCCH_PDU_TYPE;
    dl_tti_pdcch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdcch_pdu));

    nfapi_nr_dl_tti_request_pdu_t *dl_tti_pdsch_pdu = &dl_req->dl_tti_pdu_list[dl_req->nPDUs+1];
    memset((void *)dl_tti_pdsch_pdu,0,sizeof(nfapi_nr_dl_tti_request_pdu_t));
    dl_tti_pdsch_pdu->PDUType = NFAPI_NR_DL_TTI_PDSCH_PDU_TYPE;
    dl_tti_pdsch_pdu->PDUSize = (uint8_t)(2+sizeof(nfapi_nr_dl_tti_pdsch_pdu));

    nfapi_nr_dl_tti_pdcch_pdu_rel15_t *pdcch_pdu_rel15 = &dl_tti_pdcch_pdu->pdcch_pdu.pdcch_pdu_rel15;
    nfapi_nr_dl_tti_pdsch_pdu_rel15_t *pdsch_pdu_rel15 = &dl_tti_pdsch_pdu->pdsch_pdu.pdsch_pdu_rel15;
577

cig's avatar
cig committed
578 579 580 581 582
    // Checking if the DCI allocation is feasible in current subframe
    if (dl_req->nPDUs == NFAPI_NR_MAX_DL_TTI_PDUS) {
      LOG_I(MAC, "[RAPROC] Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", slotP, RA_rnti);
      return;
    }
583

584
    LOG_I(MAC,"[gNB %d] [RAPROC] CC_id %d Frame %d, slotP %d: Generating RAR DCI, state %d\n", module_idP, CC_id, frameP, slotP, ra->state);
cig's avatar
cig committed
585

586 587 588
    // This code from this point on will not work on initialBWP or CORESET0
    AssertFatal(ra->bwp_id>0,"cannot work on initialBWP for now\n");

589 590 591 592 593 594 595
    AssertFatal(ra->secondaryCellGroup,
                "no secondaryCellGroup for RNTI %04x\n",
                ra->crnti);
    AssertFatal(ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count == 1,
      "downlinkBWP_ToAddModList has %d BWP!\n", ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.count);
    NR_BWP_Downlink_t *bwp = ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id - 1];
    NR_BWP_Uplink_t *ubwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->uplinkConfig->uplinkBWP_ToAddModList->list.array[ra->bwp_id-1];
cig's avatar
cig committed
596

597
    LOG_D(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
cig's avatar
cig committed
598

599 600 601 602 603
    // Qm>2 not allowed for RAR
    if (get_softmodem_params()->do_ra)
      mcsIndex = 9;
    else
      mcsIndex = 0;
604

cig's avatar
cig committed
605
    pdsch_pdu_rel15->pduBitmap = 0;
606
    pdsch_pdu_rel15->rnti = RA_rnti;
cig's avatar
cig committed
607
    pdsch_pdu_rel15->pduIndex = 0;
608

609

610 611 612
    pdsch_pdu_rel15->BWPSize  = NRRIV2BW(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
    pdsch_pdu_rel15->BWPStart = NRRIV2PRBOFFSET(bwp->bwp_Common->genericParameters.locationAndBandwidth,275);
    pdsch_pdu_rel15->SubcarrierSpacing = bwp->bwp_Common->genericParameters.subcarrierSpacing;
cig's avatar
cig committed
613 614 615 616 617
    pdsch_pdu_rel15->CyclicPrefix = 0;
    pdsch_pdu_rel15->NrOfCodewords = 1;
    pdsch_pdu_rel15->targetCodeRate[0] = nr_get_code_rate_dl(mcsIndex,0);
    pdsch_pdu_rel15->qamModOrder[0] = 2;
    pdsch_pdu_rel15->mcsIndex[0] = mcsIndex;
618 619 620 621 622 623 624 625
    if (bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == NULL)
      pdsch_pdu_rel15->mcsTable[0] = 0;
    else{
      if (*bwp->bwp_Dedicated->pdsch_Config->choice.setup->mcs_Table == 0)
        pdsch_pdu_rel15->mcsTable[0] = 1;
      else
        pdsch_pdu_rel15->mcsTable[0] = 2;
    }
cig's avatar
cig committed
626 627 628 629 630 631 632 633
    pdsch_pdu_rel15->rvIndex[0] = 0;
    pdsch_pdu_rel15->dataScramblingId = *scc->physCellId;
    pdsch_pdu_rel15->nrOfLayers = 1;
    pdsch_pdu_rel15->transmissionScheme = 0;
    pdsch_pdu_rel15->refPoint = 0;
    pdsch_pdu_rel15->dmrsConfigType = 0;
    pdsch_pdu_rel15->dlDmrsScramblingId = *scc->physCellId;
    pdsch_pdu_rel15->SCID = 0;
634
    pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 2;
cig's avatar
cig committed
635 636 637
    pdsch_pdu_rel15->dmrsPorts = 1;
    pdsch_pdu_rel15->resourceAlloc = 1;
    pdsch_pdu_rel15->rbStart = 0;
638
    pdsch_pdu_rel15->rbSize = 6;
639
    pdsch_pdu_rel15->VRBtoPRBMapping = 0; // non interleaved
cig's avatar
cig committed
640

641 642
    for (int i=0; i<bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.count; i++) {
      startSymbolAndLength = bwp->bwp_Common->pdsch_ConfigCommon->choice.setup->pdsch_TimeDomainAllocationList->list.array[i]->startSymbolAndLength;
cig's avatar
cig committed
643 644 645 646
      SLIV2SL(startSymbolAndLength, &StartSymbolIndex_tmp, &NrOfSymbols_tmp);
      if (NrOfSymbols_tmp < NrOfSymbols) {
        NrOfSymbols = NrOfSymbols_tmp;
        StartSymbolIndex = StartSymbolIndex_tmp;
647
        time_domain_assignment = i; // this is short PDSCH added to the config to fit mixed slot
cig's avatar
cig committed
648 649 650 651
      }
    }

    AssertFatal(StartSymbolIndex >= 0, "StartSymbolIndex is negative\n");
652

cig's avatar
cig committed
653 654 655 656 657
    pdsch_pdu_rel15->StartSymbolIndex = StartSymbolIndex;
    pdsch_pdu_rel15->NrOfSymbols      = NrOfSymbols;
    pdsch_pdu_rel15->dlDmrsSymbPos = fill_dmrs_mask(NULL, scc->dmrs_TypeA_Position, NrOfSymbols);

    dci_pdu_rel15_t dci_pdu_rel15[MAX_DCI_CORESET];
658
    dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
659
										     pdsch_pdu_rel15->rbStart,dci10_bw);
660 661
    dci_pdu_rel15[0].time_domain_assignment.val = time_domain_assignment;
    dci_pdu_rel15[0].vrb_to_prb_mapping.val = 0;
cig's avatar
cig committed
662
    dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0];
663
    dci_pdu_rel15[0].tb_scaling = 0;
664

665
    LOG_I(MAC, "[RAPROC] DCI type 1 payload: freq_alloc %d (%d,%d,%d), time_alloc %d, vrb to prb %d, mcs %d tb_scaling %d \n",
666
	  dci_pdu_rel15[0].frequency_domain_assignment.val,
667 668 669
	  pdsch_pdu_rel15->rbStart,
	  pdsch_pdu_rel15->rbSize,
	  dci10_bw,
670 671
	  dci_pdu_rel15[0].time_domain_assignment.val,
	  dci_pdu_rel15[0].vrb_to_prb_mapping.val,
672 673
	  dci_pdu_rel15[0].mcs,
	  dci_pdu_rel15[0].tb_scaling);
cig's avatar
cig committed
674

675 676 677
    uint8_t nr_of_candidates, aggregation_level;
    find_aggregation_candidates(&aggregation_level, &nr_of_candidates, ss);
    NR_ControlResourceSet_t *coreset = get_coreset(bwp, ss, 0 /* common */);
678 679 680 681 682 683 684
    int CCEIndex = allocate_nr_CCEs(nr_mac,
                                    bwp,
                                    coreset,
                                    aggregation_level,
                                    0, // Y
                                    0, // m
                                    nr_of_candidates);
685 686

    if (CCEIndex < 0) {
687
      LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
688 689 690 691 692 693 694 695 696 697 698
      return;
    }
    nr_configure_pdcch(nr_mac,
                       pdcch_pdu_rel15,
                       RA_rnti,
                       ss,
                       coreset,
                       scc,
                       bwp,
                       aggregation_level,
                       CCEIndex);
cig's avatar
cig committed
699

700
    LOG_I(MAC, "Frame %d: Subframe %d : Adding common DL DCI for RA_RNTI %x\n", frameP, slotP, RA_rnti);
701

cig's avatar
cig committed
702 703 704
    dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
    rnti_types[0] = NR_RNTI_RA;

705
    LOG_D(MAC, "[RAPROC] DCI params: rnti %d, rnti_type %d, dci_format %d coreset params: FreqDomainResource %llx, start_symbol %d  n_symb %d\n",
cig's avatar
cig committed
706 707 708 709 710 711 712
      pdcch_pdu_rel15->dci_pdu.RNTI[0],
      rnti_types[0],
      dci_formats[0],
      (unsigned long long)pdcch_pdu_rel15->FreqDomainResource,
      pdcch_pdu_rel15->StartSymbolIndex,
      pdcch_pdu_rel15->DurationSymbols);

713
    fill_dci_pdu_rel15(scc,ra->secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id);
714 715

    dl_req->nPDUs+=2;
cig's avatar
cig committed
716 717

    // Program UL processing for Msg3
718
    nr_get_Msg3alloc(scc, ubwp, slotP, frameP, ra);
719
    LOG_I(MAC, "Frame %d, Subframe %d: Setting Msg3 reception for Frame %d Subframe %d\n", frameP, slotP, ra->Msg3_frame, ra->Msg3_slot);
cig's avatar
cig committed
720 721 722 723 724
    nr_add_msg3(module_idP, CC_id, frameP, slotP);
    ra->state = WAIT_Msg3;
    LOG_D(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);

    x_Overhead = 0;
725
    nr_get_tbs_dl(&dl_tti_pdsch_pdu->pdsch_pdu, x_Overhead, pdsch_pdu_rel15->numDmrsCdmGrpsNoData, dci_pdu_rel15[0].tb_scaling);
cig's avatar
cig committed
726 727 728 729 730 731 732 733 734 735

    // DL TX request
    tx_req->PDU_length = pdsch_pdu_rel15->TBSize[0];
    tx_req->PDU_index = nr_mac->pdu_index[CC_id]++;
    tx_req->num_TLV = 1;
    tx_req->TLVs[0].length = 8;
    nr_mac->TX_req[CC_id].SFN = frameP;
    nr_mac->TX_req[CC_id].Number_of_PDUs++;
    nr_mac->TX_req[CC_id].Slot = slotP;
    memcpy((void*)&tx_req->TLVs[0].value.direct[0], (void*)&cc[CC_id].RAR_pdu.payload[0], tx_req->TLVs[0].length);
736 737 738 739 740

    /* mark the corresponding RBs as used */
    uint8_t *vrb_map = cc[CC_id].vrb_map;
    for (int rb = 0; rb < pdsch_pdu_rel15->rbSize; rb++)
      vrb_map[rb + pdsch_pdu_rel15->rbStart] = 1;
cig's avatar
cig committed
741
  }
742 743 744
}

void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP){
cig's avatar
cig committed
745
  NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[0];
cig's avatar
cig committed
746 747 748 749 750 751
  LOG_D(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Clear Random access information rnti %x\n", module_idP, CC_id, frameP, ra->rnti);
  ra->state = IDLE;
  ra->timing_offset = 0;
  ra->RRC_timer = 20;
  ra->rnti = 0;
  ra->msg3_round = 0;
752 753
}

754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778

/////////////////////////////////////
//    Random Access Response PDU   //
//         TS 38.213 ch 8.2        //
//        TS 38.321 ch 6.2.3       //
/////////////////////////////////////
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
//| E | T |       R A P I D       |//
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |//
//| R |           T A             |//
//|       T A         |  UL grant |//
//|            UL grant           |//
//|            UL grant           |//
//|            UL grant           |//
//|         T C - R N T I         |//
//|         T C - R N T I         |//
/////////////////////////////////////
//       UL grant  (27 bits)       //
/////////////////////////////////////
//| 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 |// bit-wise
//|-------------------|FHF|F_alloc|//
//|        Freq allocation        |//
//|    F_alloc    |Time allocation|//
//|      MCS      |     TPC   |CSI|//
/////////////////////////////////////
cig's avatar
cig committed
779
// WIP
cig's avatar
cig committed
780 781 782
// todo:
// - handle MAC RAR BI subheader
// - sending only 1 RAR subPDU
783
// - UL Grant: hardcoded CSI, TPC, time alloc
cig's avatar
cig committed
784
// - padding
785 786
void nr_fill_rar(uint8_t Mod_idP,
                 NR_RA_t * ra,
cig's avatar
cig committed
787
                 uint8_t * dlsch_buffer,
788
                 nfapi_nr_pusch_pdu_t  *pusch_pdu){
cig's avatar
cig committed
789

790 791 792
  LOG_D(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d ", ra->Msg2_frame, ra-> Msg2_slot);
  NR_RA_HEADER_RAPID *rarh = (NR_RA_HEADER_RAPID *) dlsch_buffer;
  NR_MAC_RAR *rar = (NR_MAC_RAR *) (dlsch_buffer + 1);
Francesco Mani's avatar
Francesco Mani committed
793
  unsigned char csi_req = 0, tpc_command;
794 795
  //uint8_t N_UL_Hop;
  uint8_t valid_bits;
796 797
  uint32_t ul_grant;
  uint16_t f_alloc, prb_alloc, bwp_size, truncation=0;
798

Francesco Mani's avatar
Francesco Mani committed
799 800
  tpc_command = 3; // this is 0 dB

801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
  /// E/T/RAPID subheader ///
  // E = 0, one only RAR, first and last
  // T = 1, RAPID
  rarh->E = 0;
  rarh->T = 1;
  rarh->RAPID = ra->preamble_index;

  /// RAR MAC payload ///
  rar->R = 0;

  // TA command
  rar->TA1 = (uint8_t) (ra->timing_offset >> 5);    // 7 MSBs of timing advance
  rar->TA2 = (uint8_t) (ra->timing_offset & 0x1f);  // 5 LSBs of timing advance

  // TC-RNTI
  rar->TCRNTI_1 = (uint8_t) (ra->rnti >> 8);        // 8 MSBs of rnti
  rar->TCRNTI_2 = (uint8_t) (ra->rnti & 0xff);      // 8 LSBs of rnti

  // UL grant
820

821
  ra->msg3_TPC = tpc_command;
822

823
  bwp_size = pusch_pdu->bwp_size;
824
  prb_alloc = PRBalloc_to_locationandbandwidth0(ra->msg3_nb_rb, ra->msg3_first_rb, bwp_size);
825 826 827 828 829 830
  if (bwp_size>180) {
    AssertFatal(1==0,"Initial UBWP larger than 180 currently not supported");
  }
  else {
    valid_bits = (uint8_t)ceil(log2(bwp_size*(bwp_size+1)>>1));
  }
831

832 833
  if (pusch_pdu->frequency_hopping){
    AssertFatal(1==0,"PUSCH with frequency hopping currently not supported");
834
  } else {
835 836 837
    for (int i=0; i<valid_bits; i++)
      truncation |= (1<<i);
    f_alloc = (prb_alloc&truncation);
838
  }
839

840
  ul_grant = csi_req | (tpc_command << 1) | (pusch_pdu->mcs_index << 4) | (ra->Msg3_tda_id << 8) | (f_alloc << 12) | (pusch_pdu->frequency_hopping << 26);
841

842 843 844 845
  rar->UL_GRANT_1 = (uint8_t) (ul_grant >> 24) & 0x07;
  rar->UL_GRANT_2 = (uint8_t) (ul_grant >> 16) & 0xff;
  rar->UL_GRANT_3 = (uint8_t) (ul_grant >> 8) & 0xff;
  rar->UL_GRANT_4 = (uint8_t) ul_grant & 0xff;
846 847

}