gNB_scheduler_RA.c 44.1 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);
Francesco Mani's avatar
Francesco Mani committed
489
    if (!ra->cfra) {
Francesco Mani's avatar
Francesco Mani committed
490 491 492 493
      do {
        ra->rnti = (taus() % 65518) + 1;
        loop++;
      }
Francesco Mani's avatar
Francesco Mani committed
494 495 496 497 498
      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));
      if (loop == 100) {
        LOG_E(MAC,"%s:%d:%s: [RAPROC] initialisation random access aborted\n", __FILE__, __LINE__, __FUNCTION__);
        abort();
      }
cig's avatar
cig committed
499 500 501
    }
    ra->RA_rnti = ra_rnti;
    ra->preamble_index = preamble_index;
502
    ra->beam_id = beam_index;
503

504
    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
505 506 507 508
      module_idP,
      CC_id,
      frameP,
      ra->Msg2_frame,
cig's avatar
cig committed
509
      ra->Msg2_slot,
kn.raju's avatar
kn.raju committed
510
      ra->RA_rnti,
511
      cc->ssb_index[beam_index]);
512

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

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

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

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

  start_meas(&mac->schedule_ra);

kn.raju's avatar
kn.raju committed
529 530
//  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
531
  
kn.raju's avatar
kn.raju committed
532 533
//	NR_RA_t *ra = &cc->ra[i];
	NR_RA_t *ra = &cc->ra[0];
534

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

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

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

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

kn.raju's avatar
kn.raju committed
587
  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);
588 589
  ra->msg3_nb_rb = 18;
  ra->msg3_first_rb = 0;
590 591
}

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

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

796

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

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

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

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

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

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

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

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

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

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

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

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

    // Program UL processing for Msg3
905
    nr_get_Msg3alloc(scc, ubwp, slotP, frameP, ra);
906
    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
907 908
    nr_add_msg3(module_idP, CC_id, frameP, slotP);
    ra->state = WAIT_Msg3;
kn.raju's avatar
kn.raju committed
909
    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
910 911

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

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

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

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

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

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

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

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

1009
  ra->msg3_TPC = tpc_command;
1010

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

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

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

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

}