eNB_scheduler_RA.c 64.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * 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.0  (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
 */
knopp's avatar
 
knopp committed
21

22
/*! \file eNB_scheduler_RA.c
23
 * \brief primitives used for random access
knopp's avatar
 
knopp committed
24 25 26 27 28 29 30 31 32
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \email: navid.nikaein@eurecom.fr
 * \version 1.0
 * @ingroup _mac

 */

#include "assertions.h"
33
#include "platform_types.h"
knopp's avatar
 
knopp committed
34 35
#include "PHY/defs.h"
#include "PHY/extern.h"
gauthier's avatar
gauthier committed
36
#include "msc.h"
knopp's avatar
 
knopp committed
37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60

#include "SCHED/defs.h"
#include "SCHED/extern.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"

#include "LAYER2/MAC/proto.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

61
#include "SIMULATION/TOOLS/defs.h" // for taus
knopp's avatar
 
knopp committed
62

Cedric Roux's avatar
Cedric Roux committed
63
#include "T.h"
64

65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87
void check_and_add_msg3(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP) {

  eNB_MAC_INST                    *eNB = RC.mac[module_idP];
  RA_TEMPLATE                     *RA_template;
  COMMON_channels_t               *cc  = eNB->common_channels;
  uint8_t                         i;
  int msg3_prog_subframe,msg3_prog_frame;
  int CC_id;
  nfapi_ul_config_request_pdu_t  *ul_config_pdu;
  nfapi_ul_config_request_body_t *ul_req;
  nfapi_hi_dci0_request_body_t   *hi_dci0_req;
  nfapi_hi_dci0_request_pdu_t    *hi_dci0_pdu;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    hi_dci0_req   = &eNB->HI_DCI0_req[CC_id].hi_dci0_request_body;
    ul_req        = &eNB->UL_req[CC_id].ul_config_request_body;

    for (i=0; i<NB_RA_PROC_MAX; i++) {

      RA_template = (RA_TEMPLATE *)&cc[CC_id].RA_template[i];

      if (RA_template->RA_active == TRUE) {

88
	// program reception 4 subframes prior to transmission
89 90 91 92 93 94 95 96 97 98 99 100
	msg3_prog_subframe =  (RA_template->Msg3_subframe + 6)%10;
	
	if (RA_template->Msg3_subframe<4) msg3_prog_frame=(RA_template->Msg3_frame+1023)&1023;
	else                              msg3_prog_frame=RA_template->Msg3_frame;
        LOG_I(MAC,"[eNB %d][RAPROC] Frame %d, Subframe %d CC_id %d RA %d is active, Msg3 in (%d,%d), programmed in (%d,%d)\n",
              module_idP,frameP,subframeP,CC_id,i,RA_template->Msg3_frame,RA_template->Msg3_subframe,
	      msg3_prog_frame,msg3_prog_subframe);

	if ((msg3_prog_frame==frameP) && 
	    (msg3_prog_subframe==subframeP)) {
	  LOG_I(MAC,"Frame %d, Subframe %d Adding Msg3 UL Config Request for (%d,%d)\n",
		frameP,subframeP,RA_template->Msg3_frame,RA_template->Msg3_subframe);
101
	  eNB->UL_req[CC_id].sfn_sf                                                      = (RA_template->Msg3_frame<<4) + RA_template->Msg3_subframe;
102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145
	  if (RA_template->msg3_round == 0) { // program ULSCH
	    ul_config_pdu                                                                  = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; 
	    
	    memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t));
	    ul_config_pdu->pdu_type                                                        = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE; 
	    ul_config_pdu->pdu_size                                                        = (uint8_t)(2+sizeof(nfapi_ul_config_ulsch_pdu));
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle                                 = eNB->ul_handle++;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti                                   = RA_template->rnti;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start                   = 1;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks              = 1;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type                        = 2;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms                = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_enabled_flag         = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits                 = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication                    = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version                     = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number                    = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode                             = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb                          = 0;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs                                  = 1;
	    ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size                                   = get_TBS_UL(10,ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks);
	    ul_req->number_of_pdus++;
	  }
	  else { // program HI
	    hi_dci0_pdu                                                         = &hi_dci0_req->hi_dci0_pdu_list[hi_dci0_req->number_of_dci+hi_dci0_req->number_of_hi]; 	
	    memset((void*)hi_dci0_pdu,0,sizeof(nfapi_hi_dci0_request_pdu_t));
	    hi_dci0_pdu->pdu_type                                               = NFAPI_HI_DCI0_HI_PDU_TYPE; 
	    hi_dci0_pdu->pdu_size                                               = 2+sizeof(nfapi_hi_dci0_hi_pdu);
	    hi_dci0_pdu->hi_pdu.hi_pdu_rel8.resource_block_start                = 1; // note this is hard-coded like in fill_rar
	    hi_dci0_pdu->hi_pdu.hi_pdu_rel8.cyclic_shift_2_for_drms             = 0;
	    hi_dci0_pdu->hi_pdu.hi_pdu_rel8.hi_value                            = 0;
	    hi_dci0_req->number_of_hi++;
	    
	    LOG_I(MAC,"[eNB %d][PUSCH-RA %x] CC_id %d Frame %d subframeP %d Scheduled (PHICH) RA %d (mcs %d, first rb %d, nb_rb %d,round %d)\n",
		  module_idP,RA_template[i].rnti,CC_id,frameP,subframeP,i,10,
		  1,1,
		  RA_template[i].msg3_round-1);
	  }
	}
      }
    }
  }
}

146
void generate_Msg2(module_id_t module_idP,int CC_idP,frame_t frameP,sub_frame_t subframeP,RA_TEMPLATE *RA_template) {
knopp's avatar
 
knopp committed
147

148 149
  eNB_MAC_INST                    *eNB = RC.mac[module_idP];
  COMMON_channels_t               *cc  = eNB->common_channels;
150
 
151 152 153 154 155
  uint8_t                         *vrb_map;
  int                             first_rb;
  int                             N_RB_DL;
  nfapi_dl_config_request_pdu_t   *dl_config_pdu;
  nfapi_tx_request_pdu_t          *TX_req;
156
  nfapi_dl_config_request_body_t *dl_req;
gauthier's avatar
 
gauthier committed
157

158 159 160 161 162
  vrb_map       = cc[CC_idP].vrb_map;
  dl_req        = &eNB->DL_req[CC_idP].dl_config_request_body;
  dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
  N_RB_DL       = to_prb(cc[CC_idP].mib->message.dl_Bandwidth);  

163 164 165 166 167
#ifdef Rel14
  int rmax            = 0;
  int rep             = 0; 
  int reps            = 0;
  int num_nb          = 0;
168

169
  first_rb        = 0;
170 171
  struct PRACH_ConfigSIB_v1310 *ext4_prach;
  PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13;
172
  PRACH_ParametersCE_r13_t *p[4]={NULL,NULL,NULL,NULL};
173

174
  if (cc[CC_idP].radioResourceConfigCommon_BR) {
175

176
    ext4_prach                 = cc[CC_idP].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310;
177 178 179 180 181 182 183 184 185 186 187 188 189 190
    prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13;
        
    switch (prach_ParametersListCE_r13->list.count) {
    case 4:
      p[3]=prach_ParametersListCE_r13->list.array[3];
    case 3:
      p[2]=prach_ParametersListCE_r13->list.array[2];
    case 2:
      p[1]=prach_ParametersListCE_r13->list.array[1];
    case 1:
      p[0]=prach_ParametersListCE_r13->list.array[0];
    default:
      AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",prach_ParametersListCE_r13->list.count);
    }
191
  }
192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338

  if (RA_template->rach_resource_type > 0) {
    
    // This uses an MPDCCH Type 2 common allocation according to Section 9.1.5 36-213
    // Parameters:
    //    p=2+4 PRB set (number of PRB pairs 3)
    //    rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3
    //    if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates
    //    if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates
    //    distributed transmission
    
    // rmax from SIB2 information
    rmax           = p[RA_template->rach_resource_type-1]->mpdcch_NumRepetition_RA_r13;
    // choose r3 by default for RAR (Table 9.1.5-5)
    rep            = 2; 
    // get actual repetition count from Table 9.1.5-3
    reps           = (rmax<=8)?(1<<rep):(rmax>>(3-rep));
    // get narrowband according to higher-layer config 
    num_nb = p[RA_template->rach_resource_type-1]->mpdcch_NarrowbandsToMonitor_r13.list.count;
    RA_template->msg2_narrowband = *p[RA_template->rach_resource_type-1]->mpdcch_NarrowbandsToMonitor_r13.list.array[RA_template->preamble_index%num_nb];
    first_rb = RA_template->msg2_narrowband*6;
    
    if ((RA_template->msg2_mpdcch_repetition_cnt == 0) &&
	(mpdcch_sf_condition(eNB,CC_idP,frameP,subframeP,rmax,TYPE2)>0)){
      // MPDCCH configuration for RAR
      
      
      
      memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
      dl_config_pdu->pdu_type                                                                  = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; 
      dl_config_pdu->pdu_size                                                                  = (uint8_t)(2+sizeof(nfapi_dl_config_mpdcch_pdu));
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format                                    = (RA_template->rach_resource_type > 1) ? 11 : 10;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band                            = RA_template->msg2_narrowband;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_prb_pairs                           = 6;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment                     = 0; // Note: this can be dynamic
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type                       = 1; // imposed (9.1.5 in 213) for Type 2 Common search space  
      AssertFatal(cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL,
		  "cc[CC_id].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n");
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol                                  = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index                                    = 0;  // Note: this should be dynamic
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level                             = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type                                     = 2;  // RA-RNTI
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti                                          = RA_template->RA_rnti;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode                                       = (RA_template->rach_resource_type < 3) ? 1 : 2;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init                          = cc[CC_idP].physCellId;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.initial_transmission_sf_io                    = (frameP*10)+subframeP;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power                            = 6000; // 0dB
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding                         = getRIV(6,0,6);  // Note: still to be checked if it should not be (getRIV(N_RB_DL,first_rb,6)) : Check nFAPI specifications and what is done L1 with this parameter
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs                                           = 4; // adjust according to size of RAR, 208 bits with N1A_PRB=3
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels                        = 4; // fix to 4 for now
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version                            = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator                            = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process                                  = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length                                   = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi                                          = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag                                      = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi                                           = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_resource_offset                          = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_subframe_repetition_number                = rep; 
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc                                           = 1;// N1A_PRB=3 (36.212); => 208 bits for mcs=4, choose mcs according t message size TBD
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index_length              = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index                     = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.allocate_prach_flag                           = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index                                = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index                              = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level                             = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request                                   = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag    = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity         = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.frequency_hopping_enabled_flag                = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication                             = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding            = 0; // this is not needed by OAI L1, but should be filled in
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports                    = 1;
      RA_template->msg2_mpdcch_repetition_cnt++;
      dl_req->number_pdu++;
      
    } //repetition_count==0 && SF condition met
    else if (RA_template->msg2_mpdcch_repetition_cnt>0) { // we're in a stream of repetitions
      RA_template->msg2_mpdcch_repetition_cnt++;	      
      if (RA_template->msg2_mpdcch_repetition_cnt==reps) { // this is the last mpdcch repetition
	if (cc[CC_idP].tdd_Config==NULL) { // FDD case
	  // wait 2 subframes for PDSCH transmission
	  if (subframeP>7) RA_template->Msg2_frame = (frameP+1)&1023;
	  else             RA_template->Msg2_frame = frameP;
	  RA_template->Msg2_subframe               = (subframeP+2)%10; // +2 is the "n+x" from Section 7.1.11  in 36.213
	}
	else {
	  AssertFatal(1==0,"TDD case not done yet\n");
	}
      } // mpdcch_repetition_count == reps
      if ((RA_template->Msg2_frame == frameP) && (RA_template->Msg2_subframe == subframeP)) {
	// Program PDSCH
	RA_template->generate_rar = 0;	      
	
	dl_config_pdu                                                                  = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
	memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	dl_config_pdu->pdu_type                                                        = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; 
	dl_config_pdu->pdu_size                                                        = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu));
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index                              = eNB->pdu_index[CC_idP];
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti                                   = RA_template->RA_rnti;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type               = 2;   // format 1A/1B/1D
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0;   // localized
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding                  = getRIV(N_RB_DL,first_rb,6);
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation                             = 2; //QPSK
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version                     = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks                       = 1;// first block
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag  = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme                    = (cc->p_eNB==1 ) ? 0 : 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers                       = 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands                     = 1;
	//	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = ;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity                   = 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa                                     = 4; // 0 dB
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index               = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap                                   = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb                                   = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode                      = (cc->p_eNB==1 ) ? 1 : 2;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband                 = 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = 1;
	//	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector                    = ; 
	
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type                               = (RA_template->rach_resource_type < 3) ? 1 : 2;;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type                    = 2;  // not SI message
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io            = (10*frameP)+subframeP;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag                       = 0;
	dl_req->number_pdu++;
	
	// Program UL processing for Msg3, same as regular LTE
	get_Msg3alloc(&cc[CC_idP],subframeP,frameP,&RA_template->Msg3_frame,&RA_template->Msg3_subframe);
	
	
	fill_rar_br(eNB,CC_idP,RA_template,frameP,subframeP,cc[CC_idP].RAR_pdu.payload,RA_template->rach_resource_type-1);
	// DL request
	eNB->TX_req[CC_idP].sfn_sf                                            = (frameP<<3)+subframeP;
	TX_req                                                                = &eNB->TX_req[CC_idP].tx_request_body.tx_pdu_list[eNB->TX_req[CC_idP].tx_request_body.number_of_pdus]; 		     
	TX_req->pdu_length                                                    = 7;  // This should be changed if we have more than 1 preamble 
	TX_req->pdu_index                                                     = eNB->pdu_index[CC_idP]++;
	TX_req->num_segments                                                  = 1;
	TX_req->segments[0].segment_length                                    = 7;
	TX_req->segments[0].segment_data                                      = cc[CC_idP].RAR_pdu.payload;
	eNB->TX_req[CC_idP].tx_request_body.number_of_pdus++;
      }
    }      
    
  }		
  else
339
#endif
340 341 342 343 344 345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 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 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424
    {
      if ((RA_template->Msg2_frame == frameP) && (RA_template->Msg2_subframe == subframeP)) {
	LOG_D(MAC,"[eNB %d] CC_id %d Frame %d, subframeP %d: Generating RAR DCI, RA_active %d format 1A (%d,%d))\n",
	      module_idP, CC_idP, frameP, subframeP,
	      RA_template->RA_active,
	      
	      RA_template->RA_dci_fmt1,
	      RA_template->RA_dci_size_bits1);
	
	first_rb = 0;
	vrb_map[first_rb] = 1;
	vrb_map[first_rb+1] = 1;
	vrb_map[first_rb+2] = 1;
	vrb_map[first_rb+3] = 1;
	
	memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	dl_config_pdu->pdu_type                                                          = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; 
	dl_config_pdu->pdu_size                                                          = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                             = NFAPI_DL_DCI_FORMAT_1A;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level                      = 4;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                                   = RA_template->RA_rnti;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                              = 2;    // RA-RNTI : see Table 4-10 from SCF082 - nFAPI specifications
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power                     = 6000; // equal to RS power
	
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                           = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                                    = 1; // no TPC
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1                   = 1;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                                  = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1                   = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
	
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding                  = getRIV(N_RB_DL,first_rb,4);      
	
	if (!CCE_allocation_infeasible(module_idP,CC_idP,1,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->RA_rnti)) {
	  LOG_D(MAC,"Frame %d: Subframe %d : Adding common DCI for RA_RNTI %x\n",
		frameP,subframeP,RA_template->RA_rnti);
	  dl_req->number_dci++;
	  dl_req->number_pdu++;
	  
	  dl_config_pdu                                                                  = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
	  memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	  dl_config_pdu->pdu_type                                                        = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; 
	  dl_config_pdu->pdu_size                                                        = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu));
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index                              = eNB->pdu_index[CC_idP];
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti                                   = RA_template->RA_rnti;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type               = 2;   // format 1A/1B/1D
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0;   // localized
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding                  = getRIV(N_RB_DL,first_rb,4);
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation                             = 2; //QPSK
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version                     = 0;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks                       = 1;// first block
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag  = 0;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme                    = (cc->p_eNB==1 ) ? 0 : 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers                       = 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands                     = 1;
	  //	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = ;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity                   = 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa                                     = 4; // 0 dB
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index               = 0;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap                                   = 0;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb                                   = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode                      = (cc->p_eNB==1 ) ? 1 : 2;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband                 = 1;
	  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = 1;
	  //	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector                    = ; 
	  dl_req->number_pdu++;
	  
	  // Program UL processing for Msg3
	  get_Msg3alloc(&cc[CC_idP],subframeP,frameP,&RA_template->Msg3_frame,&RA_template->Msg3_subframe);
	  
	  
	  fill_rar(module_idP,CC_idP,frameP,cc[CC_idP].RAR_pdu.payload,N_RB_DL,7);
	  // DL request
	  eNB->TX_req[CC_idP].sfn_sf                                             = (frameP<<3)+subframeP;
	  TX_req                                                                = &eNB->TX_req[CC_idP].tx_request_body.tx_pdu_list[eNB->TX_req[CC_idP].tx_request_body.number_of_pdus]; 		     
	  TX_req->pdu_length                                                    = 7;  // This should be changed if we have more than 1 preamble 
	  TX_req->pdu_index                                                     = eNB->pdu_index[CC_idP]++;
	  TX_req->num_segments                                                  = 1;
	  TX_req->segments[0].segment_length                                    = 7;
	  TX_req->segments[0].segment_data                                      = cc[CC_idP].RAR_pdu.payload;
	  eNB->TX_req[CC_idP].tx_request_body.number_of_pdus++;
	} // PDCCH CCE allocation is feasible
      } // Msg2 frame/subframe condition
    } // else BL/CE
}
425

426
void generate_Msg4(module_id_t module_idP,int CC_idP,frame_t frameP,sub_frame_t subframeP,RA_TEMPLATE *RA_template){
gauthier's avatar
 
gauthier committed
427

428

429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
  eNB_MAC_INST                    *eNB = RC.mac[module_idP];
  COMMON_channels_t               *cc  = eNB->common_channels;
  int16_t                         rrc_sdu_length;
  int                             UE_id           = -1;
  uint16_t                        msg4_padding;
  uint16_t                        msg4_post_padding;
  uint16_t                        msg4_header;

  uint8_t                         *vrb_map;
  int                             first_rb;
  int                             N_RB_DL;
  nfapi_dl_config_request_pdu_t   *dl_config_pdu;
  nfapi_ul_config_request_pdu_t   *ul_config_pdu;
  nfapi_tx_request_pdu_t          *TX_req;
  UE_list_t                       *UE_list=&eNB->UE_list;
  nfapi_dl_config_request_body_t *dl_req;
  nfapi_ul_config_request_body_t *ul_req;
  uint8_t                         lcid;
  uint8_t                         offset;

449

gauthier's avatar
 
gauthier committed
450

451 452 453 454
#ifdef Rel14
  int rmax            = 0;
  int rep             = 0; 
  int reps            = 0;
gauthier's avatar
 
gauthier committed
455

456

457 458 459 460 461 462 463 464
  first_rb        = 0;
  struct PRACH_ConfigSIB_v1310 *ext4_prach;
  struct PUCCH_ConfigCommon_v1310 *ext4_pucch;
  PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13;
  struct N1PUCCH_AN_InfoList_r13 *pucch_N1PUCCH_AN_InfoList_r13;
  PRACH_ParametersCE_r13_t *p[4]={NULL,NULL,NULL,NULL};
  int pucchreps[4]={1,1,1,1};
  int n1pucchan[4]={0,0,0,0};
gauthier's avatar
 
gauthier committed
465

466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512
  if (cc[CC_idP].radioResourceConfigCommon_BR) {

    ext4_prach                    = cc[CC_idP].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310;
    ext4_pucch                    = cc[CC_idP].radioResourceConfigCommon_BR->ext4->pucch_ConfigCommon_v1310;
    prach_ParametersListCE_r13    = &ext4_prach->prach_ParametersListCE_r13;
    pucch_N1PUCCH_AN_InfoList_r13 = ext4_pucch->n1PUCCH_AN_InfoList_r13;
    AssertFatal(prach_ParametersListCE_r13!=NULL,"prach_ParametersListCE_r13 is null\n");
    AssertFatal(pucch_N1PUCCH_AN_InfoList_r13!=NULL,"pucch_N1PUCCH_AN_InfoList_r13 is null\n");
    // check to verify CE-Level compatibility in SIB2_BR
    AssertFatal(prach_ParametersListCE_r13->list.count == pucch_N1PUCCH_AN_InfoList_r13->list.count,
		"prach_ParametersListCE_r13->list.count!= pucch_N1PUCCH_AN_InfoList_r13->list.count\n");

    switch (prach_ParametersListCE_r13->list.count) {
    case 4:
      p[3]         = prach_ParametersListCE_r13->list.array[3];
      n1pucchan[3] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[3]; 
      AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level3_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level3 shouldn't be NULL\n");
      pucchreps[3] = (int)(4<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level3_r13);
      
    case 3:
      p[2]         = prach_ParametersListCE_r13->list.array[2];
      n1pucchan[2] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[2]; 
      AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level2 shouldn't be NULL\n");
      pucchreps[2] = (int)(4<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13);
    case 2:
      p[1]         =prach_ParametersListCE_r13->list.array[1];
      n1pucchan[1] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[1]; 
      AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level1 shouldn't be NULL\n");
      pucchreps[1] = (int)(1<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level1_r13);
    case 1:
      p[0]         = prach_ParametersListCE_r13->list.array[0];
      n1pucchan[0] = *pucch_N1PUCCH_AN_InfoList_r13->list.array[0]; 
      AssertFatal(ext4_pucch->pucch_NumRepetitionCE_Msg4_Level2_r13!=NULL,"pucch_NumRepetitionCE_Msg4_Level0 shouldn't be NULL\n");
      pucchreps[0] = (int)(1<<*ext4_pucch->pucch_NumRepetitionCE_Msg4_Level0_r13);
    default:
      AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",prach_ParametersListCE_r13->list.count);
    }
  }
#endif

  vrb_map       = cc[CC_idP].vrb_map;
  
  dl_req        = &eNB->DL_req[CC_idP].dl_config_request_body;
  dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
  ul_req        = &eNB->UL_req[CC_idP].ul_config_request_body;
  ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus]; 
  N_RB_DL       = to_prb(cc[CC_idP].mib->message.dl_Bandwidth);
513

514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535
  UE_id = find_UE_id(module_idP,RA_template->rnti);
  AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n");
  
  
  // Get RRCConnectionSetup for Piggyback
  rrc_sdu_length = mac_rrc_data_req(module_idP,
				    CC_idP,
				    frameP,
				    CCCH,
				    1, // 1 transport block
				    &cc[CC_idP].CCCH_pdu.payload[0],
				    ENB_FLAG_YES,
				    module_idP,
				    0); // not used in this case
  
  AssertFatal(rrc_sdu_length>=0,
	      "[MAC][eNB Scheduler] CCCH not allocated\n");
  
  
  LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: UE_id %d, rrc_sdu_length %d\n",
	module_idP, CC_idP, frameP, subframeP,UE_id, rrc_sdu_length);
  
536 537
  
#ifdef Rel14
538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632
  if (RA_template->rach_resource_type>0) {
    
    // Generate DCI + repetitions first
    // This uses an MPDCCH Type 2 allocation according to Section 9.1.5 36-213 : Note: Assumption that this is still Type 2 Common Search 
    // Parameters:
    //    p=2+4 PRB set (number of PRB pairs 6)
    //    rmax = mpdcch-NumRepetition-RA-r13 => Table 9.1.5-3
    //    if CELevel = 0,1 => Table 9.1.5-1b for MPDCCH candidates
    //    if CELevel = 2,3 => Table 9.1.5-2b for MPDCCH candidates
    //    distributed transmission
    
    // rmax from SIB2 information
    rmax           = p[RA_template->rach_resource_type-1]->mpdcch_NumRepetition_RA_r13;
    AssertFatal(rmax>=4,"choose rmax>=4 for enough repeititions, or reduce rep to 1 or 2\n");

    // choose r3 by default for Msg4 (this is ok from table 9.1.5-3 for rmax = >=4, if we choose rmax <4 it has to be less
    rep            = 2; 
    // get actual repetition count from Table 9.1.5-3
    reps           = (rmax<=8)?(1<<rep):(rmax>>(3-rep));
    // get first narrowband
    first_rb = RA_template->msg34_narrowband*6;
    
    if ((RA_template->msg4_mpdcch_repetition_cnt == 0) &&
	(mpdcch_sf_condition(eNB,CC_idP,frameP,subframeP,rmax,TYPE2)>0)){
      // MPDCCH configuration for RAR
      
      memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
      dl_config_pdu->pdu_type                                                                  = NFAPI_DL_CONFIG_MPDCCH_PDU_TYPE; 
      dl_config_pdu->pdu_size                                                                  = (uint8_t)(2+sizeof(nfapi_dl_config_mpdcch_pdu));
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_format                                    = (RA_template->rach_resource_type > 1) ? 11 : 10;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_narrow_band                            = RA_template->msg34_narrowband;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_prb_pairs                           = 6;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_assignment                     = 0; // Note: this can be dynamic
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mpdcch_tansmission_type                       = 1;
      AssertFatal(cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13!=NULL,
		  "cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13 is null\n");
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.start_symbol                                  = cc[CC_idP].sib1_v13ext->bandwidthReducedAccessRelatedInfo_r13->startSymbolBR_r13;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ecce_index                                    = 0;  // Note: this should be dynamic
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.aggregation_level                             = 16; // OK for CEModeA r1-3 (9.1.5-1b) or CEModeB r1-4
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti_type                                     = 0;  // t-C-RNTI
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.rnti                                          = RA_template->RA_rnti;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.ce_mode                                       = (RA_template->rach_resource_type < 3) ? 1 : 2;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.drms_scrambling_init                          = cc[CC_idP].physCellId;  /// Check this is still N_id_cell for type2 common
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.initial_transmission_sf_io                    = (frameP*10)+subframeP;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.transmission_power                            = 6000; // 0dB
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.resource_block_coding                         = getRIV(6,0,6);// check if not getRIV(N_RB_DL,first_rb,6);
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.mcs                                           = 4; // adjust according to size of Msg4, 208 bits with N1A_PRB=3
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pdsch_reptition_levels                        = 4; // fix to 4 for now
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.redundancy_version                            = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.new_data_indicator                            = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_process                                  = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi_length                                   = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpmi                                          = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi_flag                                      = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.pmi                                           = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.harq_resource_offset                          = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.dci_subframe_repetition_number                = rep; 
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.tpc                                           = 1;// N1A_PRB=3; => 208 bits
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index_length              = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.downlink_assignment_index                     = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.allocate_prach_flag                           = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.preamble_index                                = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.prach_mask_index                              = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.starting_ce_level                             = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.srs_request                                   = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity_flag    = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.antenna_ports_and_scrambling_identity         = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.frequency_hopping_enabled_flag                = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.paging_direct_indication_differentiation_flag = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.direct_indication                             = 0;
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.total_dci_length_including_padding            = 0; // this is not needed by OAI L1, but should be filled in
      dl_config_pdu->mpdcch_pdu.mpdcch_pdu_rel13.number_of_tx_antenna_ports                    = 1;
      RA_template->msg4_mpdcch_repetition_cnt++;
      dl_req->number_pdu++;
      
    } //repetition_count==0 && SF condition met
    else if (RA_template->msg4_mpdcch_repetition_cnt>0) { // we're in a stream of repetitions
      RA_template->msg4_mpdcch_repetition_cnt++;	      
      if (RA_template->msg4_mpdcch_repetition_cnt==reps) { // this is the last mpdcch repetition
	if (cc[CC_idP].tdd_Config==NULL) { // FDD case
	  // wait 2 subframes for PDSCH transmission
	  if (subframeP>7) RA_template->Msg4_frame = (frameP+1)&1023;
	  else             RA_template->Msg4_frame = frameP;
	  RA_template->Msg4_subframe               = (subframeP+2)%10; 
	}
	else {
	  AssertFatal(1==0,"TDD case not done yet\n");
	}
      } // mpdcch_repetition_count == reps
      if ((RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) {
	
	// Program PDSCH
	
	LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 BR with RRC Piggyback (ce_level %d RNTI %x)\n",
	      module_idP, CC_idP, frameP, subframeP,RA_template->rach_resource_type-1,RA_template->rnti);
633

634 635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
	AssertFatal(1==0,"Msg4 generation not finished for BL/CE UE\n");
	dl_config_pdu                                                                  = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
	memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	dl_config_pdu->pdu_type                                                        = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE; 
	dl_config_pdu->pdu_size                                                        = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu));
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index                              = eNB->pdu_index[CC_idP];
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti                                   = RA_template->rnti;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type               = 2;   // format 1A/1B/1D
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = 0;   // localized
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding                  = getRIV(N_RB_DL,first_rb,6);  // check that this isn't getRIV(6,0,6)
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation                             = 2; //QPSK
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version                     = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks                       = 1;// first block
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag  = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme                    = (cc->p_eNB==1 ) ? 0 : 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers                       = 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands                     = 1;
	//	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = ;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity                   = 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa                                     = 4; // 0 dB
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index               = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap                                   = 0;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb                                   = get_subbandsize(cc->mib->message.dl_Bandwidth); // ignored
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode                      = (cc->p_eNB==1 ) ? 1 : 2;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband                 = 1;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = 1;
	//	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.bf_vector                    = ; 
	
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.ue_type                               = (RA_template->rach_resource_type < 3) ? 1 : 2;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.pdsch_payload_type                    = 2;  // not SI message
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.initial_transmission_sf_io            = (10*frameP)+subframeP;
	dl_config_pdu->dlsch_pdu.dlsch_pdu_rel13.drms_table_flag                       = 0;
	dl_req->number_pdu++;
	
	RA_template->generate_Msg4=0;
	RA_template->wait_ack_Msg4=1;
	RA_template->RA_active = FALSE;
	lcid=0;
	
	// set HARQ process 0 round to 0 for this UE
	UE_list->UE_sched_ctrl[UE_id].round[CC_idP] = 0;
	msg4_header = 1+6+1;  // CR header, CR CE, SDU header
	
	if ((RA_template->Msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) {
	  msg4_padding = RA_template->Msg4_TBsize - rrc_sdu_length - msg4_header;
	  msg4_post_padding = 0;
	} else {
	  msg4_padding = 0;
	  msg4_post_padding = RA_template->Msg4_TBsize - rrc_sdu_length - msg4_header -1;
	}
	
	LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n",
	      module_idP,CC_idP,frameP,subframeP,RA_template->Msg4_TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding);
	DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return
	// CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0]
	offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
				       1,                           //num_sdus
				       (unsigned short*)&rrc_sdu_length,             //
				       &lcid,                       // sdu_lcid
				       255,                         // no drx
				       0,                           // no timing advance
				       RA_template->cont_res_id,  // contention res id
				       msg4_padding,                // no padding
				       msg4_post_padding);
	
	memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset],
	       &cc[CC_idP].CCCH_pdu.payload[0],
	       rrc_sdu_length);
	
	// DL request
	eNB->TX_req[CC_idP].sfn_sf                                             = (frameP<<3)+subframeP;
	TX_req                                                                = &eNB->TX_req[CC_idP].tx_request_body.tx_pdu_list[eNB->TX_req[CC_idP].tx_request_body.number_of_pdus]; 		     	      
	TX_req->pdu_length                                                    = rrc_sdu_length;
	TX_req->pdu_index                                                     = eNB->pdu_index[CC_idP]++;
	TX_req->num_segments                                                  = 1;
	TX_req->segments[0].segment_length                                    = rrc_sdu_length;
	TX_req->segments[0].segment_data                                      = eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0];
	eNB->TX_req[CC_idP].tx_request_body.number_of_pdus++;
712

713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753
	// Program ACK/NAK for Msg4 PDSCH
	int absSF = (RA_template->Msg3_frame*10)+RA_template->Msg3_subframe;
	// see Section 10.2 from 36.213
	int ackNAK_absSF = absSF + reps + 4;
	
	eNB->UL_req[CC_idP].sfn_sf                                                                   = ((ackNAK_absSF/10)<<4) + (ackNAK_absSF%10);
	ul_config_pdu->pdu_type                                                                     = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE; 
	ul_config_pdu->pdu_size                                                                     = (uint8_t)(2+sizeof(nfapi_ul_config_uci_harq_pdu));
	ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle                       = 0; // don't know how to use this
	ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti                         = RA_template->rnti;
	ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.ue_type                     = (RA_template->rach_resource_type < 3) ? 1 : 2;
	ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.empty_symbols               = 0;
	ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.total_number_of_repetitions = pucchreps[RA_template->rach_resource_type-1];
	ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel13.repetition_number           = 0;
	// Note need to keep sending this across reptitions!!!! Not really for PUCCH, to ask small-cell forum, we'll see for the other messages, maybe parameters change across repetitions and FAPI has to provide for that
	if (cc[CC_idP].tdd_Config==NULL) { // FDD case
	  ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel8_fdd.n_pucch_1_0   = n1pucchan[RA_template->rach_resource_type-1];
	  // NOTE: How to fill in the rest of the n_pucch_1_0 information 213 Section 10.1.2.1 in the general case
	  // = N_ECCE_q + Delta_ARO + n1pucchan[ce_level]
	  // higher in the MPDCCH configuration, N_ECCE_q is hard-coded to 0, and harq resource offset to 0 =>
	  // Delta_ARO = 0 from Table 10.1.2.1-1
	  ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel8_fdd.harq_size     = 1;  // 1-bit ACK/NAK
	}
	else {
	  AssertFatal(1==0,"PUCCH configuration for ACK/NAK not handled yet for TDD BL/CE case\n");
	}
	ul_req->number_of_pdus++;
	T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_idP), T_INT(RA_template->rnti), T_INT(frameP), T_INT(subframeP),
	  T_INT(0 /*harq_pid always 0?*/), T_BUFFER(&eNB->UE_list.DLSCH_pdu[CC_idP][0][UE_id].payload[0], RA_template->Msg4_TBsize));
	
	if (opt_enabled==1) {
	  trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
		    rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id),
		    eNB->frame, eNB->subframe,0,0);
	  LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n",
		module_idP, CC_idP, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length);
	}
      } // Msg4 frame/subframe
    } // msg4_mpdcch_repetition_count
  } // rach_resource_type > 0 
  else
754
#endif
755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813
    { // This is normal LTE case
      if ((RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) {	      
	LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Generating Msg4 with RRC Piggyback (RNTI %x)\n",
	      module_idP, CC_idP, frameP, subframeP,RA_template->rnti);
	
	first_rb=0;
	
	vrb_map[first_rb] = 1;
	vrb_map[first_rb+1] = 1;
	vrb_map[first_rb+2] = 1;
	vrb_map[first_rb+3] = 1;
	
	
	memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	dl_config_pdu->pdu_type                                                          = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; 
	dl_config_pdu->pdu_size                                                          = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                             = NFAPI_DL_DCI_FORMAT_1A;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level                      = 4;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                                   = RA_template->rnti;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                              = 1;    // C-RNTI : see Table 4-10 from SCF082 - nFAPI specifications
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power                     = 6000; // equal to RS power
	
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                           = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                                    = 1; // no TPC
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1                   = 1;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1                   = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
	
	// Compute MCS for 3 PRB
	msg4_header = 1+6+1;  // CR header, CR CE, SDU header
	
	
	if ((rrc_sdu_length+msg4_header) <= 22) {
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = 4;
	  RA_template->Msg4_TBsize = 22;
	} else if ((rrc_sdu_length+msg4_header) <= 28) {
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = 5;
	  RA_template->Msg4_TBsize = 28;
	} else if ((rrc_sdu_length+msg4_header) <= 32) {
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = 6;
	  RA_template->Msg4_TBsize = 32;
	} else if ((rrc_sdu_length+msg4_header) <= 41) {
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = 7;
	  RA_template->Msg4_TBsize = 41;
	} else if ((rrc_sdu_length+msg4_header) <= 49) {
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = 8;
	  RA_template->Msg4_TBsize = 49;
	} else if ((rrc_sdu_length+msg4_header) <= 57) {
	  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                       = 9;
	  RA_template->Msg4_TBsize = 57;
	}

	RA_template->Msg4_mcs = dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1;

	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding= getRIV(N_RB_DL,first_rb,4);
	
	if (!CCE_allocation_infeasible(module_idP,CC_idP,0,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->rnti)) {
	  dl_req->number_dci++;
	  dl_req->number_pdu++;
814
	  
815 816 817 818
	  RA_template->generate_Msg4=0;
	  RA_template->wait_ack_Msg4=1;
	  RA_template->RA_active = FALSE;
	  lcid=0;
819
	  
820 821
	  // set HARQ process 0 round to 0 for this UE
	  UE_list->UE_sched_ctrl[UE_id].round[CC_idP] = 0;
822
	  
823 824 825 826 827 828 829
	  if ((RA_template->Msg4_TBsize - rrc_sdu_length - msg4_header) <= 2) {
	    msg4_padding = RA_template->Msg4_TBsize - rrc_sdu_length - msg4_header;
	    msg4_post_padding = 0;
	  } else {
	    msg4_padding = 0;
	    msg4_post_padding = RA_template->Msg4_TBsize - rrc_sdu_length - msg4_header -1;
	  }
830
	  
831 832 833 834 835 836 837 838 839 840 841 842 843
	  LOG_I(MAC,"[eNB %d][RAPROC] CC_idP %d Frame %d subframeP %d Msg4 : TBS %d, sdu_len %d, msg4_header %d, msg4_padding %d, msg4_post_padding %d\n",
		module_idP,CC_idP,frameP,subframeP,RA_template->Msg4_TBsize,rrc_sdu_length,msg4_header,msg4_padding,msg4_post_padding);
	  DevAssert( UE_id != UE_INDEX_INVALID ); // FIXME not sure how to gracefully return
	  // CHECK THIS: &cc[CC_idP].CCCH_pdu.payload[0]
	  offset = generate_dlsch_header((unsigned char*)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
					 1,                           //num_sdus
					 (unsigned short*)&rrc_sdu_length,             //
					 &lcid,                       // sdu_lcid
					 255,                         // no drx
					 0,                           // no timing advance
					 RA_template->cont_res_id,  // contention res id
					 msg4_padding,                // no padding
					 msg4_post_padding);
844
	  
845 846 847
	  memcpy((void*)&eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0][(unsigned char)offset],
		 &cc[CC_idP].CCCH_pdu.payload[0],
		 rrc_sdu_length);
848
	  
849 850 851 852 853 854 855 856 857
	  // DL request
	  eNB->TX_req[CC_idP].sfn_sf                                             = (frameP<<3)+subframeP;
	  TX_req                                                                = &eNB->TX_req[CC_idP].tx_request_body.tx_pdu_list[eNB->TX_req[CC_idP].tx_request_body.number_of_pdus]; 		     	      
	  TX_req->pdu_length                                                    = rrc_sdu_length;
	  TX_req->pdu_index                                                     = eNB->pdu_index[CC_idP]++;
	  TX_req->num_segments                                                  = 1;
	  TX_req->segments[0].segment_length                                    = rrc_sdu_length;
	  TX_req->segments[0].segment_data                                      = eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0];
	  eNB->TX_req[CC_idP].tx_request_body.number_of_pdus++;
858

859 860 861 862 863 864 865 866 867 868 869 870 871 872
	  // Program PUCCH1a for ACK/NAK
	  memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t));
	  ul_config_pdu->pdu_type                                                          = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE; 
	  ul_config_pdu->pdu_size                                                          = (uint8_t)(2+sizeof(nfapi_ul_config_uci_harq_pdu));
	  ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle            = 0; // don't know how to use this
	  ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti              = RA_template->rnti;
	  if (cc[CC_idP].tdd_Config==NULL) { // FDD case
	    ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel8_fdd.n_pucch_1_0   = cc[CC_idP].radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx;
	    // NOTE: How to fill in the rest of the n_pucch_1_0 information 213 Section 10.1.2.1 in the general case
	    ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel8_fdd.harq_size     = 1;  // 1-bit ACK/NAK
	  }
	  else {
	    AssertFatal(1==0,"PUCCH configuration for ACK/NAK not handled yet for TDD case yet\n");
	  }
873

874 875 876 877
	  ul_req->number_of_pdus++;

	  T(T_ENB_MAC_UE_DL_PDU_WITH_DATA, T_INT(module_idP), T_INT(CC_idP), T_INT(RA_template->rnti), T_INT(frameP), T_INT(subframeP),
	    T_INT(0 /*harq_pid always 0?*/), T_BUFFER(&eNB->UE_list.DLSCH_pdu[CC_idP][0][UE_id].payload[0], RA_template->Msg4_TBsize));
878
	  
879 880 881 882 883 884 885
	  if (opt_enabled==1) {
	    trace_pdu(1, (uint8_t *)eNB->UE_list.DLSCH_pdu[CC_idP][0][(unsigned char)UE_id].payload[0],
		      rrc_sdu_length, UE_id, 3, UE_RNTI(module_idP, UE_id),
		      eNB->frame, eNB->subframe,0,0);
	    LOG_D(OPT,"[eNB %d][DLSCH] CC_id %d Frame %d trace pdu for rnti %x with size %d\n",
		  module_idP, CC_idP, frameP, UE_RNTI(module_idP,UE_id), rrc_sdu_length);
	  }
886
	  
887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
	} // CCE Allocation feasible
      } // msg4 frame/subframe
    } // else rach_resource_type
}

void check_Msg4_retransmission(module_id_t module_idP,int CC_idP,frame_t frameP,sub_frame_t subframeP,RA_TEMPLATE *RA_template) {
 
  eNB_MAC_INST                    *eNB = RC.mac[module_idP];
  COMMON_channels_t               *cc  = eNB->common_channels;
  int                             UE_id           = -1;
  uint8_t                         *vrb_map;
  int                             first_rb;
  int                             N_RB_DL;
  nfapi_dl_config_request_pdu_t   *dl_config_pdu;
  UE_list_t                       *UE_list=&eNB->UE_list;
  nfapi_dl_config_request_body_t *dl_req;
903

904 905
  int                             round;
  /*
906
#ifdef Rel14
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956
  COMMON_channels_t               *cc  = eNB->common_channels;

  int rmax            = 0;
  int rep             = 0; 
  int reps            = 0;

  first_rb        = 0;
  struct PRACH_ConfigSIB_v1310 *ext4_prach;
  PRACH_ParametersListCE_r13_t *prach_ParametersListCE_r13;
  PRACH_ParametersCE_r13_t *p[4];

  if (cc[CC_idP].radioResourceConfigCommon_BR) {

    ext4_prach                 = cc[CC_idP].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310;
    prach_ParametersListCE_r13 = &ext4_prach->prach_ParametersListCE_r13;
        
    switch (prach_ParametersListCE_r13->list.count) {
    case 4:
      p[3]=prach_ParametersListCE_r13->list.array[3];
    case 3:
      p[2]=prach_ParametersListCE_r13->list.array[2];
    case 2:
      p[1]=prach_ParametersListCE_r13->list.array[1];
    case 1:
      p[0]=prach_ParametersListCE_r13->list.array[0];
    default:
      AssertFatal(1==0,"Illegal count for prach_ParametersListCE_r13 %d\n",prach_ParametersListCE_r13->list.count);
    }
  }
#endif
  */

  // check HARQ status and retransmit if necessary
  LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Checking if Msg4 was acknowledged: \tn",
	module_idP,CC_idP,frameP,subframeP);
  // Get candidate harq_pid from PHY
  
  UE_id = find_UE_id(module_idP,RA_template->rnti);
  AssertFatal(UE_id>=0,"Can't find UE for t-crnti\n");
  round = UE_list->UE_sched_ctrl[UE_id].round[CC_idP];
  vrb_map       = cc[CC_idP].vrb_map;
  
  dl_req        = &eNB->DL_req[CC_idP].dl_config_request_body;
  dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu]; 
  N_RB_DL       = to_prb(cc[CC_idP].mib->message.dl_Bandwidth);
  
  if (round>0) {
    
#ifdef Rel14
    AssertFatal(1==0,"Msg4 Retransmissions not handled yet for BL/CE UEs\n");
957
#endif 
958 959 960 961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021
    {
      if ( (RA_template->Msg4_frame == frameP) && (RA_template->Msg4_subframe == subframeP)) {	       
	
	//RA_template->wait_ack_Msg4++;
	// we have to schedule a retransmission
	
	first_rb=0;
	vrb_map[first_rb] = 1;
	vrb_map[first_rb+1] = 1;
	vrb_map[first_rb+2] = 1;
	vrb_map[first_rb+3] = 1;
	
	memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
	dl_config_pdu->pdu_type                                                          = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE; 
	dl_config_pdu->pdu_size                                                          = (uint8_t)(2+sizeof(nfapi_dl_config_dci_dl_pdu));
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                             = NFAPI_DL_DCI_FORMAT_1A;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level                      = 4;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                                   = RA_template->rnti;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                              = 1;    // C-RNTI : see Table 4-10 from SCF082 - nFAPI specifications
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power                     = 6000; // equal to RS power
	
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                           = 0;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                                    = 1; // no TPC
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1                   = 1;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1                   = round;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                                  = RA_template->Msg4_mcs;
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = 0;
	
	dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding= getRIV(N_RB_DL,first_rb,4);
	
	if (!CCE_allocation_infeasible(module_idP,CC_idP,0,subframeP,dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,RA_template->rnti)) {
	  dl_req->number_dci++;
	  dl_req->number_pdu++;
	  
	  LOG_I(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d\n", RA_template->rnti, round, frameP, subframeP);
	}
	else
	  LOG_I(MAC,"msg4 retransmission for rnti %x (round %d) fsf %d/%d CCE allocation failed!\n", RA_template->rnti, round, frameP, subframeP);
	LOG_W(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d: Msg4 not acknowledged, adding ue specific dci (rnti %x) for RA (Msg4 Retransmission)\n",
	      module_idP,CC_idP,frameP,subframeP,RA_template->rnti);
      }
    }
    
  } else {
    LOG_I(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d, subframeP %d : Msg4 acknowledged\n",module_idP,CC_idP,frameP,subframeP);
    RA_template->wait_ack_Msg4=0;
    RA_template->RA_active=FALSE;
    UE_id = find_UE_id(module_idP,RA_template->rnti);
    DevAssert( UE_id != -1 );
    eNB->UE_list.UE_template[UE_PCCID(module_idP,UE_id)][UE_id].configured=TRUE;
  }
} 

void schedule_RA(module_id_t module_idP,frame_t frameP, sub_frame_t subframeP)
{

  int                             CC_id;
  eNB_MAC_INST                    *eNB = RC.mac[module_idP];
  COMMON_channels_t               *cc  = eNB->common_channels;
  RA_TEMPLATE                     *RA_template;
  uint8_t                         i;

  start_meas(&eNB->schedule_ra);

1022
 
1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    // skip UL component carriers
    if (is_UL_sf(&cc[CC_id],subframeP)==1) continue;


    for (i=0; i<NB_RA_PROC_MAX; i++) {

      RA_template = (RA_TEMPLATE *)&cc[CC_id].RA_template[i];

      if (RA_template->RA_active == TRUE) {

        LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d RA %d is active (generate RAR %d, generate_Msg4 %d, wait_ack_Msg4 %d, rnti %x)\n",
              module_idP,CC_id,i,RA_template->generate_rar,RA_template->generate_Msg4,RA_template->wait_ack_Msg4, RA_template->rnti);

        if      (RA_template->generate_rar == 1)  generate_Msg2(module_idP,CC_id,frameP,subframeP,RA_template);
	else if (RA_template->generate_Msg4 == 1) generate_Msg4(module_idP,CC_id,frameP,subframeP,RA_template);
 	else if (RA_template->wait_ack_Msg4==1)   check_Msg4_retransmission(module_idP,CC_id,frameP,subframeP,RA_template);


1042
      } // RA_active == TRUE
1043 1044
    } // for i=0 .. N_RA_PROC-1 
  } // CC_id
1045
  
1046 1047
  stop_meas(&eNB->schedule_ra);
}
gauthier's avatar
 
gauthier committed
1048

1049

1050
// handles the event of MSG1 reception
1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062
void initiate_ra_proc(module_id_t module_idP, 
		      int CC_id,
		      frame_t frameP, 
		      sub_frame_t subframeP,
		      uint16_t preamble_index,
		      int16_t timing_offset,
		      uint16_t ra_rnti
#ifdef Rel14
		      ,
		      uint8_t rach_resource_type
#endif
		      )
1063 1064 1065
{

  uint8_t i;
1066
  RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[module_idP]->common_channels[CC_id].RA_template[0];
1067

1068
  LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
1069
#ifdef Rel14
1070
  LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d PRACH resource type %d\n",module_idP,CC_id,frameP,rach_resource_type);
1071
#endif
1072

1073 1074 1075
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,1);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_INITIATE_RA_PROC,0);

1076
  for (i=0; i<NB_RA_PROC_MAX; i++) {
Cedric Roux's avatar
Cedric Roux committed
1077 1078
    if (RA_template[i].RA_active==FALSE &&
        RA_template[i].wait_ack_Msg4 == 0) {
Cedric Roux's avatar
Cedric Roux committed
1079
      int loop = 0;
1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090
      RA_template[i].RA_active          = TRUE;
      RA_template[i].generate_rar       = 1;
      RA_template[i].generate_Msg4      = 0;
      RA_template[i].wait_ack_Msg4      = 0;
      RA_template[i].timing_offset      = timing_offset;
      RA_template[i].preamble_subframe  = subframeP;
#ifdef Rel14
      RA_template[i].rach_resource_type = rach_resource_type;
      RA_template[i].msg2_mpdcch_repetition_cnt = 0;		      
      RA_template[i].msg4_mpdcch_repetition_cnt = 0;		      
#endif
Cedric Roux's avatar
Cedric Roux committed
1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102
      /* TODO: find better procedure to allocate RNTI */
      do {
        RA_template[i].rnti = taus();
        loop++;
      } while (loop != 100 &&
               /* TODO: this is not correct, the rnti may be in use without
                * being in the MAC yet. To be refined.
                */
               !(find_UE_id(module_idP, RA_template[i].rnti) == -1 &&
                 /* 1024 and 60000 arbirarily chosen, not coming from standard */
                 RA_template[i].rnti >= 1024 && RA_template[i].rnti < 60000));
      if (loop == 100) { printf("%s:%d:%s: FATAL ERROR! contact the authors\n", __FILE__, __LINE__, __FUNCTION__); abort(); }
1103
      RA_template[i].RA_rnti        = ra_rnti;
1104
      RA_template[i].preamble_index = preamble_index;
1105 1106
      LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Activating RAR generation for process %d, rnti %x, RA_active %d\n",
            module_idP,CC_id,frameP,i,RA_template[i].rnti,
1107 1108 1109 1110 1111
            RA_template[i].RA_active);

      return;
    }
  }
Cedric Roux's avatar
Cedric Roux committed
1112 1113

  LOG_E(MAC,"[eNB %d][RAPROC] FAILURE: CC_id %d Frame %d Initiating RA procedure for preamble index %d\n",module_idP,CC_id,frameP,preamble_index);
1114
}
gauthier's avatar
 
gauthier committed
1115

1116 1117 1118
void cancel_ra_proc(module_id_t module_idP, int CC_id, frame_t frameP, rnti_t rnti)
{
  unsigned char i;
1119
  RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[module_idP]->common_channels[CC_id].RA_template[0];
1120

gauthier's avatar
gauthier committed
1121
  MSC_LOG_EVENT(MSC_PHY_ENB, "RA Cancelling procedure ue %"PRIx16" ", rnti);
1122
  LOG_D(MAC,"[eNB %d][RAPROC] CC_id %d Frame %d Cancelling RA procedure for UE rnti %x\n",module_idP,CC_id,frameP,rnti);
1123 1124 1125 1126 1127 1128 1129 1130 1131 1132

  for (i=0; i<NB_RA_PROC_MAX; i++) {
    if (rnti == RA_template[i].rnti) {
      RA_template[i].RA_active=FALSE;
      RA_template[i].generate_rar=0;
      RA_template[i].generate_Msg4=0;
      RA_template[i].wait_ack_Msg4=0;
      RA_template[i].timing_offset=0;
      RA_template[i].RRC_timer=20;
      RA_template[i].rnti = 0;
1133
      RA_template[i].msg3_round = 0;
knopp's avatar
 
knopp committed
1134
    }
1135
  }
knopp's avatar
 
knopp committed
1136 1137
}