ra_procedures.c 23.1 KB
Newer Older
1
/*******************************************************************************
2 3
    OpenAirInterface
    Copyright(c) 1999 - 2014 Eurecom
4

5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

16 17 18 19
    You should have received a copy of the GNU General Public License
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
    see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
22 23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

28
*******************************************************************************/
29

30
/*! \file ra_procedures.c
31
 * \brief Routines for UE MAC-layer Random-access procedures (36.321) V8.6 2009-03
32
 * \author R. Knopp and Navid Nikaein
33 34 35
 * \date 2011
 * \version 0.1
 * \company Eurecom
36
 * \email: knopp@eurecom.fr navid.nikaein@eurecom.fr
37 38 39
 * \note
 * \warning
 */
40 41 42

#include "extern.h"
#include "defs.h"
43 44
#include "proto.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
45 46 47 48
#include "PHY_INTERFACE/defs.h"
#include "PHY_INTERFACE/extern.h"
#include "COMMON/mac_rrc_primitives.h"
#include "RRC/LITE/extern.h"
winckel's avatar
winckel committed
49
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
50
#include "UTIL/LOG/log.h"
winckel's avatar
winckel committed
51
#include "UTIL/OPT/opt.h"
52 53 54 55 56 57
#include "OCG.h"
#include "OCG_extern.h"
#ifdef PHY_EMUL
#include "SIMULATION/simulation_defs.h"
#endif

58
#include "SIMULATION/TOOLS/defs.h" // for taus
59

60 61
int8_t get_DELTA_PREAMBLE(module_id_t module_idP,int CC_id)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
62 63 64 65

  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
66
    return 0; // not reached
Raymond Knopp's avatar
 
Raymond Knopp committed
67
  }
68

69 70
  uint8_t prachConfigIndex = UE_mac_inst[module_idP].radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex;
  uint8_t preambleformat;
71

72
  if (UE_mac_inst[module_idP].tdd_Config) { // TDD
73
    if (prachConfigIndex < 20) {
74
      preambleformat = 0;
75
    } else if (prachConfigIndex < 30) {
76
      preambleformat = 1;
77
    } else if (prachConfigIndex < 40) {
78
      preambleformat = 2;
79
    } else if (prachConfigIndex < 48) {
80
      preambleformat = 3;
81
    } else {
82
      preambleformat = 4;
83
    }
84 85
  } else { // FDD
    preambleformat = prachConfigIndex>>2;
86
  }
87

88 89 90 91
  switch (preambleformat) {
  case 0:
  case 1:
    return(0);
92

93 94 95
  case 2:
  case 3:
    return(-3);
96

97 98
  case 4:
    return(8);
99

100 101
  default:
    LOG_E(MAC,"[UE %d] ue_procedures.c: FATAL, Illegal preambleformat %d, prachConfigIndex %d\n",
102 103
          module_idP,
          preambleformat,prachConfigIndex);
Lionel Gauthier's avatar
Lionel Gauthier committed
104
    mac_xface->macphy_exit("MAC get_DELTA_PREAMBLE Illegal preamble format");
105 106 107 108 109
    return(0);
  }

}

110

Raymond Knopp's avatar
 
Raymond Knopp committed
111
/// This routine implements Section 5.1.2 (UE Random Access Resource Selection) from 36.321
112
void get_prach_resources(module_id_t module_idP,
113 114 115 116 117 118
                         int CC_id,
                         uint8_t eNB_index,
                         uint8_t t_id,
                         uint8_t first_Msg3,
                         RACH_ConfigDedicated_t *rach_ConfigDedicated)
{
119

120
  uint8_t Msg3_size = UE_mac_inst[module_idP].RA_Msg3_size;
121
  PRACH_RESOURCES_t *prach_resources = &UE_mac_inst[module_idP].RA_prach_resources;
122
  RACH_ConfigCommon_t *rach_ConfigCommon = NULL;
123 124
  uint8_t noGroupB = 0;
  uint8_t f_id = 0,num_prach=0;
125
  int numberOfRA_Preambles;
126 127 128 129
  int messageSizeGroupA;
  int sizeOfRA_PreamblesGroupA;
  int messagePowerOffsetGroupB;
  int PLThreshold;
130

Raymond Knopp's avatar
 
Raymond Knopp committed
131 132 133 134 135
  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
    return;
  }
136

137
  if (UE_mac_inst[module_idP].radioResourceConfigCommon) {
138
    rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon;
139
  } else {
140 141 142
    LOG_E(MAC,"[UE %d] FATAL  radioResourceConfigCommon is NULL !!!\n",module_idP);
    mac_xface->macphy_exit("MAC FATAL  radioResourceConfigCommon is NULL");
    return; // not reached
143 144
  }

145 146
  numberOfRA_Preambles = (1+rach_ConfigCommon->preambleInfo.numberOfRA_Preambles)<<2;  

147
  if (rach_ConfigDedicated) {   // This is for network controlled Mobility, later
148 149 150 151 152
    if (rach_ConfigDedicated->ra_PRACH_MaskIndex != 0) {
      prach_resources->ra_PreambleIndex = rach_ConfigDedicated->ra_PreambleIndex;
      prach_resources->ra_RACH_MaskIndex = rach_ConfigDedicated->ra_PRACH_MaskIndex;
      return;
    }
153 154
  }

Cedric Roux's avatar
Cedric Roux committed
155 156 157
  /* TODO: gcc warns if this variable is not always set, let's put -1 for no more warning */
  messageSizeGroupA = -1;

158
  if (!rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) {
159 160
    noGroupB = 1;
  } else {
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176
    sizeOfRA_PreamblesGroupA = (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA+1)<<2;
    switch (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->messageSizeGroupA) {
    case 0:
      messageSizeGroupA = 56;
      break;
    case 1:
      messageSizeGroupA = 144;
      break;
    case 2:
      messageSizeGroupA = 208;
      break;
    case 3:
      messageSizeGroupA = 256;
      break;
    }

Cedric Roux's avatar
Cedric Roux committed
177 178
    /* TODO: what value to use as default? */
    messagePowerOffsetGroupB = -9999;
179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209
    switch (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->messagePowerOffsetGroupB) {
    case 0:
      messagePowerOffsetGroupB = -9999;
      break;
    case 1:
      messagePowerOffsetGroupB = 0;
      break;
    case 2:
      messagePowerOffsetGroupB = 5;
      break;
    case 3:
      messagePowerOffsetGroupB = 8;
      break;
    case 4:
      messagePowerOffsetGroupB = 10;
      break;
    case 5:
      messagePowerOffsetGroupB = 12;
      break;
    case 6:
      messagePowerOffsetGroupB = 15;
      break;
    case 7:
      messagePowerOffsetGroupB = 18;
      break;
    }

    PLThreshold = 0 - get_DELTA_PREAMBLE(module_idP,CC_id) - get_Po_NOMINAL_PUSCH(module_idP,CC_id) - messagePowerOffsetGroupB;
    // Note Pcmax is set to 0 here, we have to fix this

    if (sizeOfRA_PreamblesGroupA == numberOfRA_Preambles) {
210
      noGroupB = 1;
211
    }
212 213 214
  }

  if (first_Msg3 == 1) {
215 216
    if (noGroupB == 1) {
      // use Group A procedure
217
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())%numberOfRA_Preambles;
218 219
      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
      UE_mac_inst[module_idP].RA_usedGroupA = 1;
220 221
    } else if ((Msg3_size <messageSizeGroupA) ||
               (mac_xface->get_PL(module_idP,0,eNB_index) > PLThreshold)) {
222
      // use Group A procedure
223
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())%sizeOfRA_PreamblesGroupA;
224 225 226
      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
      UE_mac_inst[module_idP].RA_usedGroupA = 1;
    } else { // use Group B
227 228
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = sizeOfRA_PreamblesGroupA +
        (taus())%(numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
229 230 231 232 233 234 235
      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
      UE_mac_inst[module_idP].RA_usedGroupA = 0;
    }

    UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER = get_Po_NOMINAL_PUSCH(module_idP,CC_id);
  } else { // Msg3 is being retransmitted
    if (UE_mac_inst[module_idP].RA_usedGroupA == 1) {
236
      if (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) {
237
        UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())%rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA;
238
      } else {
239
        UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())&0x3f;
240
      }
241 242 243

      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
    } else {
244
      // FIXME rach_ConfigCommon->preambleInfo.preamblesGroupAConfig may be zero
245 246 247
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  =
        rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA +
        (taus())%(rach_ConfigCommon->preambleInfo.numberOfRA_Preambles -
248
                  rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA);
249 250
      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
    }
251
  }
252

253
  // choose random PRACH resource in TDD
254
  if (UE_mac_inst[module_idP].tdd_Config) {
255
    num_prach = mac_xface->get_num_prach_tdd(mac_xface->frame_parms);
256

257
    if ((num_prach>0) && (num_prach<6)) {
258
      UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index = (taus()%num_prach);
259
    }
260

261
    f_id = mac_xface->get_fid_prach_tdd(mac_xface->frame_parms,
262
                                        UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index);
263 264 265
  }

  // choose RA-RNTI
266
  UE_mac_inst[module_idP].RA_prach_resources.ra_RNTI = 1 + t_id + 10*f_id;
267 268
}

269 270
void Msg1_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
271 272 273 274 275 276

  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
    return;
  }
277 278

  // start contention resolution timer
279
  UE_mac_inst[module_idP].RA_attempt_number++;
280

navid's avatar
navid committed
281 282
  if (opt_enabled) {
    trace_pdu(0, NULL, 0, module_idP, 2, UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex,
283 284
              UE_mac_inst[module_idP].subframe, 0, UE_mac_inst[module_idP].RA_attempt_number);
    LOG_D(OPT,"[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x  with size %d\n",
285
          module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size);
286
  }
287

288 289 290
}


291 292
void Msg3_tx(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
293 294 295 296 297 298

  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
    return;
  }
299 300

  // start contention resolution timer
301
  LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Setting contention resolution timer\n",module_idP,frameP);
302 303
  UE_mac_inst[module_idP].RA_contention_resolution_cnt = 0;
  UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1;
304

navid's avatar
navid committed
305
  if (opt_enabled) { // msg3
306
    trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0], UE_mac_inst[module_idP].RA_Msg3_size,
307
              module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].subframe, 0, 0);
308
    LOG_D(OPT,"[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d   with size %d\n",
309
          module_idP, frameP, UE_mac_inst[module_idP].crnti /*UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex*/, UE_mac_inst[module_idP].RA_Msg3_size);
310
  }
311

312 313 314
}


315 316
PRACH_RESOURCES_t *ue_get_rach(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_indexP,sub_frame_t subframeP)
{
317 318


319
  uint8_t                        Size=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
320
  UE_MODE_t                 UE_mode = mac_xface->get_ue_mode(module_idP,0,eNB_indexP);
321 322
  uint8_t                        lcid = CCCH;
  uint16_t                       Size16;
323
  struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL;
324
  int32_t                       frame_diff=0;
325
  mac_rlc_status_resp_t     rlc_status;
326 327 328
  uint8_t                        dcch_header_len=0;
  uint16_t                       sdu_lengths[8];
  uint8_t                        ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];
329

Raymond Knopp's avatar
 
Raymond Knopp committed
330 331 332
  if (CC_id>0) {
    LOG_E(MAC,"Transmission on secondary CCs is not supported yet\n");
    mac_xface->macphy_exit("MAC FATAL  CC_id>0");
333
    return 0; // not reached
Raymond Knopp's avatar
 
Raymond Knopp committed
334 335
  }

336
  if (UE_mode == PRACH) {
337
    if (UE_mac_inst[module_idP].radioResourceConfigCommon) {
338
      rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon;
339
    } else {
340 341 342 343 344 345
      return(NULL);
    }

    if (Is_rrc_registered == 1) {

      if (UE_mac_inst[module_idP].RA_active == 0) {
knopp's avatar
knopp committed
346
        LOG_D(MAC,"RA not active\n");
347 348
        // check if RRC is ready to initiate the RA procedure
        Size = mac_rrc_data_req(module_idP,
349
                                CC_id,
350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
                                frameP,
                                CCCH,1,
                                &UE_mac_inst[module_idP].CCCH_pdu.payload[sizeof(SCH_SUBHEADER_SHORT)+1],0,
                                eNB_indexP,
                                0);
        Size16 = (uint16_t)Size;

        //  LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",module_idP,frameP,Size);
        LOG_D(RRC, "[MSC_MSG][FRAME %05d][RRC_UE][MOD %02d][][--- MAC_DATA_REQ (RRCConnectionRequest eNB %d) --->][MAC_UE][MOD %02d][]\n",
              frameP, module_idP, eNB_indexP, module_idP);
        LOG_D(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",module_idP,frameP,Size);

        if (Size>0) {

          UE_mac_inst[module_idP].RA_active                        = 1;
          UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
          UE_mac_inst[module_idP].RA_Msg3_size                     = Size+sizeof(SCH_SUBHEADER_SHORT)+sizeof(SCH_SUBHEADER_SHORT);
          UE_mac_inst[module_idP].RA_prachMaskIndex                = 0;
          UE_mac_inst[module_idP].RA_prach_resources.Msg3          = UE_mac_inst[module_idP].CCCH_pdu.payload;
          UE_mac_inst[module_idP].RA_backoff_cnt                   = 0;  // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)

          if (rach_ConfigCommon) {
            UE_mac_inst[module_idP].RA_window_cnt                    = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize;

374
            if (UE_mac_inst[module_idP].RA_window_cnt == 9) {
375
              UE_mac_inst[module_idP].RA_window_cnt = 10;  // Note: 9 subframe window doesn't exist, after 8 is 10!
376
            }
377 378 379
          } else {
            LOG_D(MAC,"[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",module_idP,frameP);
            mac_xface->macphy_exit("MAC rach_ConfigCommon is NULL");
380
          }
381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400

          UE_mac_inst[module_idP].RA_tx_frame         = frameP;
          UE_mac_inst[module_idP].RA_tx_subframe      = subframeP;
          UE_mac_inst[module_idP].RA_backoff_frame    = frameP;
          UE_mac_inst[module_idP].RA_backoff_subframe = subframeP;
          // Fill in preamble and PRACH resource
          get_prach_resources(module_idP,CC_id,eNB_indexP,subframeP,1,NULL);

          generate_ulsch_header((uint8_t*)&UE_mac_inst[module_idP].CCCH_pdu.payload[0],  // mac header
                                1,      // num sdus
                                0,            // short pading
                                &Size16,  // sdu length
                                &lcid,    // sdu lcid
                                NULL,  // power headroom
                                NULL,  // crnti
                                NULL,  // truncated bsr
                                NULL, // short bsr
                                NULL, // long_bsr
                                1); //post_padding
          return(&UE_mac_inst[module_idP].RA_prach_resources);
401

402 403 404
        } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[DCCH] > 0) {
          // This is for triggering a transmission on DCCH using PRACH (during handover, or sending SR for example)
          dcch_header_len = 2 + 2;  /// SHORT Subheader + C-RNTI control element
405
          rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,ENB_FLAG_NO,MBMS_FLAG_NO,
406 407 408 409
                                          DCCH,
                                          6);

          if (UE_mac_inst[module_idP].crnti_before_ho)
410 411
            LOG_D(MAC,
                  "[UE %d] Frame %d : UL-DCCH -> ULSCH, HO RRCConnectionReconfigurationComplete (%x, %x), RRC message has %d bytes to send throug PRACH (mac header len %d)\n",
412 413 414 415 416
                  module_idP,frameP, UE_mac_inst[module_idP].crnti,UE_mac_inst[module_idP].crnti_before_ho, rlc_status.bytes_in_buffer,dcch_header_len);
          else
            LOG_D(MAC,"[UE %d] Frame %d : UL-DCCH -> ULSCH, RRC message has %d bytes to send through PRACH(mac header len %d)\n",
                  module_idP,frameP, rlc_status.bytes_in_buffer,dcch_header_len);

417
          sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,
418
                                            eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO,
419 420 421 422
                                            DCCH,
                                            (char *)&ulsch_buff[0]);

          LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
423
          update_bsr(module_idP, frameP, eNB_indexP,DCCH,UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]);
424 425 426 427 428 429 430 431 432 433 434
          //header_len +=2;
          UE_mac_inst[module_idP].RA_active                        = 1;
          UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER = 1;
          UE_mac_inst[module_idP].RA_Msg3_size                     = Size+dcch_header_len;
          UE_mac_inst[module_idP].RA_prachMaskIndex                = 0;
          UE_mac_inst[module_idP].RA_prach_resources.Msg3          = ulsch_buff;
          UE_mac_inst[module_idP].RA_backoff_cnt                   = 0;  // add the backoff condition here if we have it from a previous RA reponse which failed (i.e. backoff indicator)

          if (rach_ConfigCommon) {
            UE_mac_inst[module_idP].RA_window_cnt                    = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize;

435
            if (UE_mac_inst[module_idP].RA_window_cnt == 9) {
436
              UE_mac_inst[module_idP].RA_window_cnt = 10;  // Note: 9 subframe window doesn't exist, after 8 is 10!
437
            }
438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471
          } else {
            LOG_D(MAC,"[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",module_idP,frameP);
            mac_xface->macphy_exit("MAC rach_ConfigCommon is NULL");
          }

          UE_mac_inst[module_idP].RA_tx_frame         = frameP;
          UE_mac_inst[module_idP].RA_tx_subframe      = subframeP;
          UE_mac_inst[module_idP].RA_backoff_frame    = frameP;
          UE_mac_inst[module_idP].RA_backoff_subframe = subframeP;
          // Fill in preamble and PRACH resource
          get_prach_resources(module_idP,CC_id,eNB_indexP,subframeP,1,NULL);
          generate_ulsch_header((uint8_t*)ulsch_buff,  // mac header
                                1,      // num sdus
                                0,            // short pading
                                &Size16,  // sdu length
                                &lcid,    // sdu lcid
                                NULL,  // power headroom
                                &UE_mac_inst[module_idP].crnti,  // crnti
                                NULL,  // truncated bsr
                                NULL, // short bsr
                                NULL, // long_bsr
                                0); //post_padding

          return(&UE_mac_inst[module_idP].RA_prach_resources);
        }
      } else { // RACH is active
        LOG_D(MAC,"[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, window cnt %d (RA_tx_frame %d, RA_tx_subframe %d)\n",module_idP,
              frameP,subframeP,UE_mac_inst[module_idP].RA_window_cnt,
              UE_mac_inst[module_idP].RA_tx_frame,UE_mac_inst[module_idP].RA_tx_subframe);

        // compute backoff parameters
        if (UE_mac_inst[module_idP].RA_backoff_cnt>0) {
          frame_diff = (sframe_t)frameP - UE_mac_inst[module_idP].RA_backoff_frame;

472
          if (frame_diff < 0) {
473
            frame_diff = -frame_diff;
474
          }
475 476 477 478 479 480 481 482 483 484 485

          UE_mac_inst[module_idP].RA_backoff_cnt -= ((10*frame_diff) + (subframeP-UE_mac_inst[module_idP].RA_backoff_subframe));

          UE_mac_inst[module_idP].RA_backoff_frame    = frameP;
          UE_mac_inst[module_idP].RA_backoff_subframe = subframeP;
        }

        // compute RA window parameters
        if (UE_mac_inst[module_idP].RA_window_cnt>0) {
          frame_diff = (frame_t)frameP - UE_mac_inst[module_idP].RA_tx_frame;

486
          if (frame_diff < 0) {
487
            frame_diff = -frame_diff;
488
          }
489 490 491 492 493 494 495 496 497 498 499 500

          UE_mac_inst[module_idP].RA_window_cnt -= ((10*frame_diff) + (subframeP-UE_mac_inst[module_idP].RA_tx_subframe));
          LOG_D(MAC,"[MAC][UE %d][RAPROC] frameP %d, subframe %d: RA Active, adjusted window cnt %d\n",module_idP,
                frameP,subframeP,UE_mac_inst[module_idP].RA_window_cnt);
        }

        if ((UE_mac_inst[module_idP].RA_window_cnt<=0) &&
            (UE_mac_inst[module_idP].RA_backoff_cnt<=0)) {

          UE_mac_inst[module_idP].RA_tx_frame    = frameP;
          UE_mac_inst[module_idP].RA_tx_subframe = subframeP;
          UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER++;
501 502
          UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER +=
            (rach_ConfigCommon->powerRampingParameters.powerRampingStep<<1);  // 2dB increments in ASN.1 definition
Cedric Roux's avatar
Cedric Roux committed
503
	  int preambleTransMax = -1;
504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541
	  switch (rach_ConfigCommon->ra_SupervisionInfo.preambleTransMax) {
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n3:
	    preambleTransMax = 3;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n4:
	    preambleTransMax = 4;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n5:
	    preambleTransMax = 5;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n6:
	    preambleTransMax = 6;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n7:
	    preambleTransMax = 7;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n8:
	    preambleTransMax = 8;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n10:
	    preambleTransMax = 10;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n20:
	    preambleTransMax = 20;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n50:
	    preambleTransMax = 50;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n100:
	    preambleTransMax = 100;
	    break;
	  case RACH_ConfigCommon__ra_SupervisionInfo__preambleTransMax_n200:
	    preambleTransMax = 200;
	    break;
	  } 

          if (UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER == preambleTransMax) {
            LOG_D(MAC,"[UE %d] Frame %d: Maximum number of RACH attempts (%d)\n",module_idP,frameP,preambleTransMax);
542 543 544
            // send message to RRC
            UE_mac_inst[module_idP].RA_PREAMBLE_TRANSMISSION_COUNTER=1;
            UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER = get_Po_NOMINAL_PUSCH(module_idP,CC_id);
545
          }
546 547 548 549 550 551 552 553

          UE_mac_inst[module_idP].RA_window_cnt                    = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize;
          UE_mac_inst[module_idP].RA_backoff_cnt                   = 0;

          // Fill in preamble and PRACH resource
          get_prach_resources(module_idP,CC_id,eNB_indexP,subframeP,0,NULL);
          return(&UE_mac_inst[module_idP].RA_prach_resources);
        }
554
      }
555 556 557 558
    }
  } else if (UE_mode == PUSCH) {
    LOG_D(MAC,"[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...",module_idP);
    mac_xface->macphy_exit("MAC FATAL: Should not have checked for RACH in PUSCH yet");
559
  }
560

561 562
  return(NULL);
}