gNB_scheduler_RA.c 44 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
#define MAX_NUMBER_OF_SSB 64		
float ssb_per_rach_occasion[8] = {0.125,0.25,0.5,1,2,4,8};

int16_t ssb_index_from_prach(module_id_t module_idP,
                             frame_t frameP,
Florian Kaltenberger's avatar
Florian Kaltenberger committed
54 55 56 57 58 59
			     sub_frame_t slotP,
			     uint16_t preamble_index,
			     uint8_t freq_index,
			     uint8_t symbol) {
  
  gNB_MAC_INST *gNB = RC.nrmac[module_idP];
60
  NR_COMMON_channels_t *cc = &gNB->common_channels[0];
61 62 63 64 65
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
  nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];

  uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
	uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
kn.raju's avatar
kn.raju committed
66 67
  
	uint8_t total_RApreambles = 64;
kn.raju's avatar
kn.raju committed
68
	if( scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles != NULL)
kn.raju's avatar
kn.raju committed
69 70 71
    total_RApreambles = *scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->totalNumberOfRA_Preambles;	
  
	float  num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];	
72
  uint16_t start_symbol_index = 0;
kn.raju's avatar
kn.raju committed
73 74
  uint8_t mu,N_dur,N_t_slot,start_symbol = 0, temp_start_symbol = 0, N_RA_slot;
  uint16_t format,RA_sfn_index = -1;
75
	uint8_t config_period = 1;
kn.raju's avatar
kn.raju committed
76
  uint16_t prach_occasion_id = -1;
77 78 79 80 81 82 83 84
	uint8_t num_active_ssb = cc->num_active_ssb;

  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;

  get_nr_prach_info_from_index(config_index,
85 86 87 88 89 90 91 92 93 94 95 96
			       (int)frameP,
			       (int)slotP,
			       scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
			       mu,
			       cc->frame_type,
			       &format,
			       &start_symbol,
			       &N_t_slot,
			       &N_dur,
			       &RA_sfn_index,
			       &N_RA_slot,
			       &config_period);
kn.raju's avatar
kn.raju committed
97
  uint8_t index = 0,slot_index = 0;
98 99 100 101 102
	for (slot_index = 0;slot_index < N_RA_slot; slot_index++) {
    if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
       if((mu == 1) || (mu == 3))
         slot_index = 1;  //For scs = 30khz and 120khz
    }
kn.raju's avatar
kn.raju committed
103 104
    for (int i=0; i< N_t_slot; i++) {
      temp_start_symbol = (start_symbol + i * N_dur + 14 * slot_index) % 14;
kn.raju's avatar
kn.raju committed
105
		  if(symbol == temp_start_symbol) {
kn.raju's avatar
kn.raju committed
106
			  start_symbol_index = i;
107
		    break;
kn.raju's avatar
kn.raju committed
108
		  }
109 110
	  }
	}
kn.raju's avatar
kn.raju committed
111 112 113 114 115
  if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
    if((mu == 1) || (mu == 3))
      slot_index = 0;  //For scs = 30khz and 120khz
  }
  
116
//  prach_occasion_id = subframe_index * N_t_slot * N_RA_slot * fdm + N_RA_slot_index * N_t_slot * fdm + freq_index + fdm * start_symbol_index; 
117
 prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period)*cc->total_prach_occasions_per_config_period) + (RA_sfn_index + slot_index) * N_t_slot * fdm + start_symbol_index * fdm + freq_index; 
118 119 120 121 122 123 124 125 126 127 128 129
//one RO is shared by one or more SSB
 if(num_ssb_per_RO <= 1 )
   index = (int) (prach_occasion_id / (int)(1/num_ssb_per_RO)) % num_active_ssb;
//one SSB have more than one continuous RO
 else if ( num_ssb_per_RO > 1) {
	 index = (prach_occasion_id * (int)num_ssb_per_RO)% num_active_ssb ;
   for(int j = 0;j < num_ssb_per_RO;j++) {
     if(preamble_index <  (((j+1) * total_RApreambles) / num_ssb_per_RO))
      index = index + j;
	  }		
	}

Florian Kaltenberger's avatar
Florian Kaltenberger committed
130
  LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %d ssb per RO = %f number of active SSB %u index = %d fdm %u symbol index %u freq_index %u total_RApreambles %u\n", frameP, slotP, prach_occasion_id, num_ssb_per_RO, num_active_ssb, index, fdm, start_symbol_index, freq_index, total_RApreambles);
131 132 133 134 135 136
  return index;
}
//Compute Total active SSBs and RO available
void find_SSB_and_RO_available(module_id_t module_idP) {

	gNB_MAC_INST *gNB = RC.nrmac[module_idP];
137
  NR_COMMON_channels_t *cc = &gNB->common_channels[0];
138 139 140 141
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
  nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];

  uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
kn.raju's avatar
kn.raju committed
142 143
  uint8_t mu,N_dur,N_t_slot,start_symbol,N_RA_slot = 0;
  uint16_t format,N_RA_sfn = 0,unused_RA_occasion,repetition = 0;
144
	uint8_t num_active_ssb = 0;
145
  uint8_t max_association_period = 1;
146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161

  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
  get_nr_prach_occasion_info_from_index(config_index,
                                    scc->downlinkConfigCommon->frequencyInfoDL->absoluteFrequencyPointA,
                                    mu,
                                    cc->frame_type,
                                    &format,
                                    &start_symbol,
                                    &N_t_slot,
                                    &N_dur,
                                    &N_RA_slot,
kn.raju's avatar
kn.raju committed
162
	                                 &N_RA_sfn,
163 164 165 166 167
                                   &max_association_period);

  float num_ssb_per_RO = ssb_per_rach_occasion[cfg->prach_config.ssb_per_rach.value];	
	uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
  uint64_t L_ssb = (((uint64_t) cfg->ssb_table.ssb_mask_list[0].ssb_mask.value)<<32) | cfg->ssb_table.ssb_mask_list[1].ssb_mask.value ;
kn.raju's avatar
kn.raju committed
168
	uint32_t total_RA_occasions = N_RA_sfn * N_t_slot * N_RA_slot * fdm;
169 170 171

	for(int i = 0;i < 64;i++) {
    if ((L_ssb >> (63-i)) & 0x01) { // only if the bit of L_ssb at current ssb index is 1
172
      cc->ssb_index[num_active_ssb] = i; 
173 174 175 176
		  num_active_ssb++;
    }
	}	

177
	for(int i = 1; (1 << (i-1)) <= max_association_period;i++) {
178
    if(total_RA_occasions >= (int) (num_active_ssb/num_ssb_per_RO)) {
179 180 181 182 183 184
		  repetition = (uint16_t)((total_RA_occasions * num_ssb_per_RO )/num_active_ssb);
		  break;
		} 
		else { 
		  total_RA_occasions = total_RA_occasions * i;
		  cc->max_association_period = i;
185 186
		} 
	}
187 188
  if(cc->max_association_period == 0)
			cc->max_association_period = 1;
189 190 191 192 193

 unused_RA_occasion = total_RA_occasions - (int)((num_active_ssb * repetition)/num_ssb_per_RO);
 cc->total_prach_occasions = total_RA_occasions - unused_RA_occasion;
 cc->num_active_ssb = num_active_ssb;

kn.raju's avatar
kn.raju committed
194 195
  LOG_I(MAC, "Total available RO %d, num of active SSB %d: unused RO = %d max_association_period %u N_RA_sfn %u \n", cc->total_prach_occasions, cc->num_active_ssb, unused_RA_occasion, max_association_period, N_RA_sfn);

196 197
}		
		
198 199 200 201 202 203
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];
204
  nfapi_nr_config_request_scf_t *cfg = &RC.nrmac[module_idP]->config[0];
205

206
  if (is_nr_UL_slot(scc,slotP)) {
207
  uint8_t config_index = scc->uplinkConfigCommon->initialUplinkBWP->rach_ConfigCommon->choice.setup->rach_ConfigGeneric.prach_ConfigurationIndex;
kn.raju's avatar
kn.raju committed
208
  uint8_t mu,N_dur,N_t_slot,start_symbol = 0,N_RA_slot;
kn.raju's avatar
kn.raju committed
209
  uint16_t RA_sfn_index = -1;
210
	uint8_t config_period = 1;
211
  uint16_t format;
kn.raju's avatar
kn.raju committed
212
  int slot_index = 0;
213
  uint16_t prach_occasion_id = -1;
214 215 216 217 218 219

  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;

220
  uint8_t fdm = cfg->prach_config.num_prach_fd_occasions.value;
221 222 223 224 225 226 227 228 229 230
  // 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,
231 232
                                    &N_dur,
                                    &RA_sfn_index,
233 234
                                    &N_RA_slot,
																		&config_period) ) {
kn.raju's avatar
kn.raju committed
235 236
    uint16_t format0 = format&0xff;      // first column of format from table
    uint16_t format1 = (format>>8)&0xff; // second column of format from table
237 238 239

    if (N_RA_slot > 1) { //more than 1 PRACH slot in a subframe
      if (slotP%2 == 1){
kn.raju's avatar
kn.raju committed
240
	      slot_index = 1;
241 242
      }	
      else {
kn.raju's avatar
kn.raju committed
243
	      slot_index = 0;
244 245 246 247
			}	
    }else if (N_RA_slot <= 1) { //1 PRACH slot in a subframe
       slot_index = 0;
    }
248 249


250 251
    UL_tti_req->SFN = frameP;
    UL_tti_req->Slot = slotP;
kn.raju's avatar
kn.raju committed
252 253
    for (int fdm_index=0; fdm_index < fdm; fdm_index++) { // one structure per frequency domain occasion
    for (int td_index=0; td_index<N_t_slot; td_index++) {
254

kn.raju's avatar
kn.raju committed
255 256
      prach_occasion_id = (((frameP % (cc->max_association_period * config_period))/config_period) * cc->total_prach_occasions_per_config_period) + (RA_sfn_index + slot_index) * N_t_slot * fdm + td_index * fdm + fdm_index;
			if((prach_occasion_id < cc->total_prach_occasions) && (td_index == 0)){  
257

258 259 260 261 262 263 264 265 266
      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;
kn.raju's avatar
kn.raju committed
267 268
      prach_pdu->prach_start_symbol = start_symbol;
      prach_pdu->num_ra = fdm_index;
269 270 271
      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);
272
      
Florian Kaltenberger's avatar
Florian Kaltenberger committed
273
      LOG_D(MAC, "Frame %d, Slot %d: Prach Occasion id = %u  fdm index = %u start symbol = %u slot index = %u subframe index = %u \n",
274 275 276 277
	    frameP, slotP,
	    prach_occasion_id, prach_pdu->num_ra,
	    prach_pdu->prach_start_symbol,
	    slot_index, RA_sfn_index);
278 279 280 281 282
      // 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:
283
            prach_pdu->prach_format = 11;
284 285
            break;
          case 0xa2:
286
            prach_pdu->prach_format = 12;
287 288
            break;
          case 0xa3:
289
            prach_pdu->prach_format = 13;
290 291 292 293 294 295 296
            break;
        default:
          AssertFatal(1==0,"Only formats A1/B1 A2/B2 A3/B3 are valid for dual format");
        }
      }
      else{
        switch(format0) {
297
          case 0:
298 299
            prach_pdu->prach_format = 0;
            break;
300
          case 1:
301 302
            prach_pdu->prach_format = 1;
            break;
303
          case 2:
304 305
            prach_pdu->prach_format = 2;
            break;
306
          case 3:
307 308
            prach_pdu->prach_format = 3;
            break;
309
          case 0xa1:
310 311
            prach_pdu->prach_format = 4;
            break;
312
          case 0xa2:
313 314
            prach_pdu->prach_format = 5;
            break;
315
          case 0xa3:
316 317
            prach_pdu->prach_format = 6;
            break;
318
          case 0xb1:
319 320
            prach_pdu->prach_format = 7;
            break;
321
          case 0xb4:
322 323
            prach_pdu->prach_format = 8;
            break;
324 325
          case 0xc0:
            prach_pdu->prach_format = 9;
326
            break;
327 328
          case 0xc2:
            prach_pdu->prach_format = 10;
329 330 331 332
            break;
        default:
          AssertFatal(1==0,"Invalid PRACH format");
        }
333 334
      }		
     }
335
    }
336
   }
337 338 339 340 341 342 343 344
  }
  }
}

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,
345
                      uint16_t monitoring_offset,uint8_t index,uint8_t num_active_ssb){
346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362

  // 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
363
  uint8_t start_next_period = (rach_slot-(rach_slot%tdd_period_slot)+tdd_period_slot)%nr_slots_per_frame[mu];
364 365
  *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);
kn.raju's avatar
kn.raju committed
366
 
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394
  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
395
  AssertFatal(slot_window<=nr_slots_per_frame[mu],"Msg2 response window needs to be lower or equal to 10ms");
396 397

  // slot and frame limit to transmit msg2 according to response window
cig's avatar
cig committed
398
  uint8_t slot_limit = (rach_slot + slot_window)%nr_slots_per_frame[mu];
399
  //uint8_t frame_limit = (slot_limit>(rach_slot))? rach_frame : (rach_frame +1);
400 401 402 403


  // 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
404
  while ((*msg2_slot>slot_limit) || ((*msg2_frame*nr_slots_per_frame[mu]+*msg2_slot-monitoring_offset)%monitoring_slot_period !=0))  {
405
    if((*msg2_slot%tdd_period_slot) > 0)
Raphael Defosseux's avatar
Raphael Defosseux committed
406
      (*msg2_slot)--;
407 408 409
    else
      AssertFatal(1==0,"No available DL slot to schedule msg2 has been found");
  }
cig's avatar
cig committed
410
}
411

412

413 414 415 416 417
void nr_initiate_ra_proc(module_id_t module_idP,
                         int CC_id,
                         frame_t frameP,
                         sub_frame_t slotP,
                         uint16_t preamble_index,
418 419
                         uint8_t freq_index,
                         uint8_t symbol,
420 421
                         int16_t timing_offset){

422 423 424 425
  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);
426

427
  uint16_t msg2_frame, msg2_slot,monitoring_slot_period,monitoring_offset;
cig's avatar
cig committed
428 429
  gNB_MAC_INST *nr_mac = RC.nrmac[module_idP];
  NR_COMMON_channels_t *cc = &nr_mac->common_channels[CC_id];
430
  NR_ServingCellConfigCommon_t *scc = cc->ServingCellConfigCommon;
431
  NR_RA_t *ra = &cc->ra[0];
432 433 434
  // 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;
435 436
  for (int i = 0; i < ra->preambles.num_preambles; i++) {
    if (preamble_index == ra->preambles.preamble_list[i]) {
437 438 439 440
      pr_found=1;
      break;
    }
  }
441
  if (!pr_found) {
442 443
    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);
444 445
    return; // if the PRACH preamble does not correspond to any of the ones sent through RRC abort RA proc
  }
446 447
  // This should be handled differently when we use the initialBWP for RA
  ra->bwp_id=1;
448
  NR_BWP_Downlink_t *bwp=ra->secondaryCellGroup->spCellConfig->spCellConfigDedicated->downlinkBWP_ToAddModList->list.array[ra->bwp_id-1];
449

cig's avatar
cig committed
450
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 1);
451

Francesco Mani's avatar
Francesco Mani committed
452
  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);
453

cig's avatar
cig committed
454
  if (ra->state == RA_IDLE) {
kn.raju's avatar
kn.raju committed
455

456 457 458 459 460 461
    uint8_t beam_index = ssb_index_from_prach(module_idP,
		                              frameP,
					      slotP,
					      preamble_index,
					      freq_index,
					      symbol);
cig's avatar
cig committed
462
    int loop = 0;
Francesco Mani's avatar
Francesco Mani committed
463
    LOG_D(MAC, "Frame %d, Slot %d: Activating RA process \n", frameP, slotP);
cig's avatar
cig committed
464 465
    ra->state = Msg2;
    ra->timing_offset = timing_offset;
466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482
    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);

483
    nr_schedule_msg2(frameP, slotP, &msg2_frame, &msg2_slot, scc, monitoring_slot_period, monitoring_offset,beam_index,cc->num_active_ssb);
484

cig's avatar
cig committed
485
    ra->Msg2_frame = msg2_frame;
cig's avatar
cig committed
486
    ra->Msg2_slot = msg2_slot;
487

kn.raju's avatar
kn.raju committed
488
    LOG_I(MAC, "%s() Msg2[%04d%d] SFN/SF:%04d%d\n", __FUNCTION__, ra->Msg2_frame, ra->Msg2_slot, frameP, slotP);
489
    if(pr_found)
Francesco Mani's avatar
Francesco Mani committed
490 491 492 493
      do {
        ra->rnti = (taus() % 65518) + 1;
        loop++;
      }
kn.raju's avatar
kn.raju committed
494
    while (loop != 100 && !((find_nr_UE_id(module_idP, ra->rnti) == -1) && (find_nr_RA_id(module_idP, CC_id, ra->rnti) == -1) && ra->rnti >= 1 && ra->rnti <= 65519));
cig's avatar
cig committed
495 496 497 498 499 500
    if (loop == 100) {
      LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
      abort();
    }
    ra->RA_rnti = ra_rnti;
    ra->preamble_index = preamble_index;
501
    ra->beam_id = beam_index;
502

503
    LOG_I(MAC,"[gNB %d][RAPROC] CC_id %d Frame %d Activating Msg2 generation in frame %d, slot %d using RA rnti %x SSB index %u\n",
cig's avatar
cig committed
504 505 506 507
      module_idP,
      CC_id,
      frameP,
      ra->Msg2_frame,
cig's avatar
cig committed
508
      ra->Msg2_slot,
kn.raju's avatar
kn.raju committed
509
      ra->RA_rnti,
510
      cc->ssb_index[beam_index]);
511

cig's avatar
cig committed
512
    return;
513
  }
cig's avatar
cig committed
514
  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);
515

cig's avatar
cig committed
516
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC, 0);
517 518 519 520
}

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

cig's avatar
cig committed
521 522
  //uint8_t i = 0;
  int CC_id = 0;
cig's avatar
cig committed
523
  gNB_MAC_INST *mac = RC.nrmac[module_idP];
cig's avatar
cig committed
524
  NR_COMMON_channels_t *cc = &mac->common_channels[CC_id];
525 526 527

  start_meas(&mac->schedule_ra);

kn.raju's avatar
kn.raju committed
528 529
//  for (CC_id = 0; CC_id < MAX_NUM_CCs; CC_id++) {
//    for (int i = 0; i < NR_NB_RA_PROC_MAX; i++) {
kn.raju's avatar
kn.raju committed
530
  
kn.raju's avatar
kn.raju committed
531 532
//	NR_RA_t *ra = &cc->ra[i];
	NR_RA_t *ra = &cc->ra[0];
533

cig's avatar
cig committed
534 535 536
  LOG_D(MAC,"RA[state:%d]\n",ra->state);
  switch (ra->state){
    case Msg2:
537 538
      nr_generate_Msg2(module_idP, CC_id, frameP, slotP);
      break;
cig's avatar
cig committed
539
    case Msg4:
540
      //generate_Msg4(module_idP, CC_id, frameP, slotP);
541
      break;
cig's avatar
cig committed
542
    case WAIT_Msg4_ACK:
543
      //check_Msg4_retransmission(module_idP, CC_id, frameP, slotP);
544
      break;
cig's avatar
cig committed
545
    default:
cig's avatar
cig committed
546
    break;
cig's avatar
cig committed
547
  }
kn.raju's avatar
kn.raju committed
548 549
//    }
//  }
550 551 552
  stop_meas(&mac->schedule_ra);
}

553
void nr_get_Msg3alloc(NR_ServingCellConfigCommon_t *scc,
554
                      NR_BWP_Uplink_t *ubwp,
555 556 557 558
                      sub_frame_t current_slot,
                      frame_t current_frame,
                      NR_RA_t *ra) {

559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575
  // 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");
576

577 578 579
  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
580 581
  ra->Msg3_slot = temp_slot%nr_slots_per_frame[mu];
  if (nr_slots_per_frame[mu]>temp_slot)
582 583
    ra->Msg3_frame = current_frame;
  else
cig's avatar
cig committed
584
    ra->Msg3_frame = current_frame + (temp_slot/nr_slots_per_frame[mu]);
585

kn.raju's avatar
kn.raju committed
586
  LOG_I(MAC, "[RAPROC] Msg3 slot %d: current slot %u Msg3 frame %u k2 %u Msg3_tda_id %u start symbol index %u\n", ra->Msg3_slot, current_slot, ra->Msg3_frame, k2,ra->Msg3_tda_id, StartSymbolIndex);
587 588
  ra->msg3_nb_rb = 18;
  ra->msg3_first_rb = 0;
589 590
}

591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609

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
610 611 612 613 614 615 616
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];

617
  if (ra->state == RA_IDLE) {
618 619 620
    LOG_W(MAC,"RA is not active for RA %X. skipping msg3 scheduling\n", ra->rnti);
    return;
  }
cig's avatar
cig committed
621

kn.raju's avatar
kn.raju committed
622
  LOG_I(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);
623 624

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

627 628 629 630 631 632
  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
633 634 635 636 637 638 639 640 641 642
  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);

643 644 645 646
  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
647 648 649
  pusch_pdu->pdu_bit_map = PUSCH_PDU_BITMAP_PUSCH_DATA;
  pusch_pdu->rnti = ra->rnti;
  pusch_pdu->handle = 0;
650 651 652 653 654 655 656 657 658
  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
659 660
  pusch_pdu->subcarrier_spacing = ubwp->bwp_Common->genericParameters.subcarrierSpacing;
  pusch_pdu->cyclic_prefix = 0;
661
  pusch_pdu->mcs_index = 0;
cig's avatar
cig committed
662 663 664
  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);
665 666 667 668 669
  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
670
  pusch_pdu->nrOfLayers = 1;
671
  pusch_pdu->ul_dmrs_symb_pos = 1<<start_symbol_index; // ok for now but use fill dmrs mask later
cig's avatar
cig committed
672
  pusch_pdu->dmrs_config_type = 0;
673
  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
674
  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.
675 676
  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
677
  pusch_pdu->resource_alloc = 1; //type 1
678 679 680 681 682
  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
683
  pusch_pdu->vrb_to_prb_mapping = 0;
684 685 686 687
  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
688 689 690
  //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
691 692
  pusch_pdu->start_symbol_index = start_symbol_index;
  pusch_pdu->nr_of_symbols = nr_of_symbols;
cig's avatar
cig committed
693
  //Optional Data only included if indicated in pduBitmap
694
  pusch_pdu->pusch_data.rv_index = 0;  // 8.3 in 38.213
cig's avatar
cig committed
695
  pusch_pdu->pusch_data.harq_process_id = 0;
696 697 698
  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
699 700 701
                                                 pusch_pdu->target_code_rate,
                                                 pusch_pdu->rb_size,
                                                 pusch_pdu->nr_of_symbols,
702
                                                 12, // nb dmrs set for no data in dmrs symbol
cig's avatar
cig committed
703
                                                 0, //nb_rb_oh
704
                                                 0, // to verify tb scaling
705 706 707 708 709
                                                 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
710 711
}

cig's avatar
cig committed
712
// WIP
cig's avatar
cig committed
713 714 715
// todo:
// - fix me
// - get msg3 alloc (see nr_process_rar)
cig's avatar
cig committed
716 717 718
void nr_generate_Msg2(module_id_t module_idP,
                      int CC_id,
                      frame_t frameP,
719 720
                      sub_frame_t slotP)
{
cig's avatar
cig committed
721

722
  int dci_formats[2], rnti_types[2], mcsIndex;
723
  int startSymbolAndLength = 0, StartSymbolIndex = -1, NrOfSymbols = 14, StartSymbolIndex_tmp, NrOfSymbols_tmp, x_Overhead, time_domain_assignment = 0;
cig's avatar
cig committed
724
  gNB_MAC_INST                      *nr_mac = RC.nrmac[module_idP];
kn.raju's avatar
kn.raju committed
725
  NR_COMMON_channels_t                  *cc = &nr_mac->common_channels[CC_id];
726
  NR_RA_t                               *ra = &cc->ra[CC_id];
727
  NR_SearchSpace_t *ss = ra->ra_ss;
cig's avatar
cig committed
728

729
  uint16_t RA_rnti = ra->RA_rnti;
cig's avatar
cig committed
730 731
  long locationAndBandwidth;

732 733 734 735 736 737 738 739 740 741 742 743 744 745
  // 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
746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762
  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;
763

cig's avatar
cig committed
764 765 766 767 768
    // 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;
    }
769

770
    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
771

772 773 774
    // 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");

775 776 777 778 779 780 781
    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
782

kn.raju's avatar
kn.raju committed
783
    LOG_I(MAC, "[RAPROC] Scheduling common search space DCI type 1 dlBWP BW %d\n", dci10_bw);
cig's avatar
cig committed
784

785 786 787 788 789
    // Qm>2 not allowed for RAR
    if (get_softmodem_params()->do_ra)
      mcsIndex = 9;
    else
      mcsIndex = 0;
790

cig's avatar
cig committed
791
    pdsch_pdu_rel15->pduBitmap = 0;
792
    pdsch_pdu_rel15->rnti = RA_rnti;
cig's avatar
cig committed
793
    pdsch_pdu_rel15->pduIndex = 0;
794

795

796 797 798
    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
799 800 801 802 803
    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;
804 805 806 807 808 809 810 811
    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
812 813 814 815 816 817 818 819
    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;
820
    pdsch_pdu_rel15->numDmrsCdmGrpsNoData = 2;
cig's avatar
cig committed
821 822 823
    pdsch_pdu_rel15->dmrsPorts = 1;
    pdsch_pdu_rel15->resourceAlloc = 1;
    pdsch_pdu_rel15->rbStart = 0;
824
    pdsch_pdu_rel15->rbSize = 6;
825
    pdsch_pdu_rel15->VRBtoPRBMapping = 0; // non interleaved
cig's avatar
cig committed
826

827 828
    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
829 830 831 832
      SLIV2SL(startSymbolAndLength, &StartSymbolIndex_tmp, &NrOfSymbols_tmp);
      if (NrOfSymbols_tmp < NrOfSymbols) {
        NrOfSymbols = NrOfSymbols_tmp;
        StartSymbolIndex = StartSymbolIndex_tmp;
833
        time_domain_assignment = i; // this is short PDSCH added to the config to fit mixed slot
cig's avatar
cig committed
834 835 836 837
      }
    }

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

cig's avatar
cig committed
839 840 841 842 843
    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];
844
    dci_pdu_rel15[0].frequency_domain_assignment.val = PRBalloc_to_locationandbandwidth0(pdsch_pdu_rel15->rbSize,
845
										     pdsch_pdu_rel15->rbStart,dci10_bw);
846 847
    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
848
    dci_pdu_rel15[0].mcs = pdsch_pdu_rel15->mcsIndex[0];
849
    dci_pdu_rel15[0].tb_scaling = 0;
850

851
    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",
852
	  dci_pdu_rel15[0].frequency_domain_assignment.val,
853 854 855
	  pdsch_pdu_rel15->rbStart,
	  pdsch_pdu_rel15->rbSize,
	  dci10_bw,
856 857
	  dci_pdu_rel15[0].time_domain_assignment.val,
	  dci_pdu_rel15[0].vrb_to_prb_mapping.val,
858 859
	  dci_pdu_rel15[0].mcs,
	  dci_pdu_rel15[0].tb_scaling);
cig's avatar
cig committed
860

861 862 863
    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 */);
864 865 866 867 868 869 870
    int CCEIndex = allocate_nr_CCEs(nr_mac,
                                    bwp,
                                    coreset,
                                    aggregation_level,
                                    0, // Y
                                    0, // m
                                    nr_of_candidates);
871 872

    if (CCEIndex < 0) {
873
      LOG_E(MAC, "%s(): cannot find free CCE for RA RNTI %04x!\n", __func__, ra->rnti);
874 875 876 877 878 879 880 881 882 883 884
      return;
    }
    nr_configure_pdcch(nr_mac,
                       pdcch_pdu_rel15,
                       RA_rnti,
                       ss,
                       coreset,
                       scc,
                       bwp,
                       aggregation_level,
                       CCEIndex);
cig's avatar
cig committed
885

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

cig's avatar
cig committed
888 889 890
    dci_formats[0] = NR_DL_DCI_FORMAT_1_0;
    rnti_types[0] = NR_RNTI_RA;

kn.raju's avatar
kn.raju committed
891
    LOG_I(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
892 893 894 895 896 897 898
      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);

899
    fill_dci_pdu_rel15(scc,ra->secondaryCellGroup,pdcch_pdu_rel15, &dci_pdu_rel15[0], dci_formats, rnti_types,dci10_bw,ra->bwp_id);
900 901

    dl_req->nPDUs+=2;
cig's avatar
cig committed
902 903

    // Program UL processing for Msg3
904
    nr_get_Msg3alloc(scc, ubwp, slotP, frameP, ra);
905
    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
906 907
    nr_add_msg3(module_idP, CC_id, frameP, slotP);
    ra->state = WAIT_Msg3;
kn.raju's avatar
kn.raju committed
908
    LOG_I(MAC,"[gNB %d][RAPROC] Frame %d, Subframe %d: RA state %d\n", module_idP, frameP, slotP, ra->state);
cig's avatar
cig committed
909 910

    x_Overhead = 0;
911
    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
912 913 914 915 916 917 918 919 920 921

    // 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);
922 923 924 925 926

    /* 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
927
  }
928 929 930
}

void nr_clear_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP){
kn.raju's avatar
kn.raju committed
931
  
cig's avatar
cig committed
932
  NR_RA_t *ra = &RC.nrmac[module_idP]->common_channels[CC_id].ra[0];
cig's avatar
cig committed
933 934 935 936 937 938
  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;
939 940
}

941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965

/////////////////////////////////////
//    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
966
// WIP
cig's avatar
cig committed
967 968 969
// todo:
// - handle MAC RAR BI subheader
// - sending only 1 RAR subPDU
970
// - UL Grant: hardcoded CSI, TPC, time alloc
cig's avatar
cig committed
971
// - padding
972 973
void nr_fill_rar(uint8_t Mod_idP,
                 NR_RA_t * ra,
cig's avatar
cig committed
974
                 uint8_t * dlsch_buffer,
975
                 nfapi_nr_pusch_pdu_t  *pusch_pdu){
cig's avatar
cig committed
976

kn.raju's avatar
kn.raju committed
977
  LOG_I(MAC, "[gNB] Generate RAR MAC PDU frame %d slot %d preamble index %u", ra->Msg2_frame, ra-> Msg2_slot, ra->preamble_index);
978 979
  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
980
  unsigned char csi_req = 0, tpc_command;
981 982
  //uint8_t N_UL_Hop;
  uint8_t valid_bits;
983 984
  uint32_t ul_grant;
  uint16_t f_alloc, prb_alloc, bwp_size, truncation=0;
985

Francesco Mani's avatar
Francesco Mani committed
986 987
  tpc_command = 3; // this is 0 dB

988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006
  /// 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
1007

1008
  ra->msg3_TPC = tpc_command;
1009

1010
  bwp_size = pusch_pdu->bwp_size;
1011
  prb_alloc = PRBalloc_to_locationandbandwidth0(ra->msg3_nb_rb, ra->msg3_first_rb, bwp_size);
1012 1013 1014 1015 1016 1017
  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));
  }
1018

1019 1020
  if (pusch_pdu->frequency_hopping){
    AssertFatal(1==0,"PUSCH with frequency hopping currently not supported");
1021
  } else {
1022 1023 1024
    for (int i=0; i<valid_bits; i++)
      truncation |= (1<<i);
    f_alloc = (prb_alloc&truncation);
1025
  }
1026

1027
  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);
1028

1029 1030 1031 1032
  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;
1033 1034

}