ra_procedures.c 21.1 KB
Newer Older
1
2
3
4
5
/*
 * 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
 * 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
 */
21

nikaeinn's avatar
nikaeinn committed
22
/*! \file ra_procedures.c
gauthier's avatar
gauthier committed
23
 * \brief Routines for UE MAC-layer Random-access procedures (36.321) V8.6 2009-03
nikaeinn's avatar
nikaeinn committed
24
 * \author R. Knopp and Navid Nikaein
gauthier's avatar
gauthier committed
25
26
27
 * \date 2011
 * \version 0.1
 * \company Eurecom
nikaeinn's avatar
nikaeinn committed
28
 * \email: knopp@eurecom.fr navid.nikaein@eurecom.fr
gauthier's avatar
gauthier committed
29
30
31
 * \note
 * \warning
 */
32
33
34

#include "extern.h"
#include "defs.h"
35
36
#include "proto.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
37
#include "PHY_INTERFACE/extern.h"
Cedric Roux's avatar
Cedric Roux committed
38
#include "SCHED/defs.h"
39
40
#include "COMMON/mac_rrc_primitives.h"
#include "RRC/LITE/extern.h"
winckel's avatar
winckel committed
41
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
42
#include "UTIL/LOG/log.h"
winckel's avatar
winckel committed
43
#include "UTIL/OPT/opt.h"
44
45
46
47
48
49
#include "OCG.h"
#include "OCG_extern.h"
#ifdef PHY_EMUL
#include "SIMULATION/simulation_defs.h"
#endif

50
#include "SIMULATION/TOOLS/defs.h" // for taus
51

52
extern uint8_t  nfapi_mode;
David Price's avatar
David Price committed
53
54
extern UE_MODE_t get_ue_mode(uint8_t Mod_id,uint8_t CC_id,uint8_t eNB_index);

55

56
57
int8_t get_DELTA_PREAMBLE(module_id_t module_idP,int CC_id)
{
knopp's avatar
   
knopp committed
58

59
60
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
gauthier's avatar
gauthier committed
61
62
  uint8_t prachConfigIndex = UE_mac_inst[module_idP].radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex;
  uint8_t preambleformat;
63

gauthier's avatar
gauthier committed
64
  if (UE_mac_inst[module_idP].tdd_Config) { // TDD
65
    if (prachConfigIndex < 20) {
66
      preambleformat = 0;
67
    } else if (prachConfigIndex < 30) {
68
      preambleformat = 1;
69
    } else if (prachConfigIndex < 40) {
70
      preambleformat = 2;
71
    } else if (prachConfigIndex < 48) {
72
      preambleformat = 3;
73
    } else {
74
      preambleformat = 4;
75
    }
76
77
  } else { // FDD
    preambleformat = prachConfigIndex>>2;
78
  }
79

80
81
82
83
  switch (preambleformat) {
  case 0:
  case 1:
    return(0);
84

85
86
87
  case 2:
  case 3:
    return(-3);
88

89
90
  case 4:
    return(8);
91

92
  default:
93
94
95
    AssertFatal(1==0,"[UE %d] ue_procedures.c: FATAL, Illegal preambleformat %d, prachConfigIndex %d\n",
		module_idP,
		preambleformat,prachConfigIndex);
96
97
98
99
  }

}

knopp's avatar
knopp committed
100

knopp's avatar
   
knopp committed
101
/// This routine implements Section 5.1.2 (UE Random Access Resource Selection) from 36.321
gauthier's avatar
gauthier committed
102
void get_prach_resources(module_id_t module_idP,
103
104
105
106
107
108
                         int CC_id,
                         uint8_t eNB_index,
                         uint8_t t_id,
                         uint8_t first_Msg3,
                         RACH_ConfigDedicated_t *rach_ConfigDedicated)
{
109
	LOG_I(MAC, "Panos-D: get_prach_resources 1");
gauthier's avatar
gauthier committed
110

gauthier's avatar
gauthier committed
111
  uint8_t Msg3_size = UE_mac_inst[module_idP].RA_Msg3_size;
gauthier's avatar
gauthier committed
112
  PRACH_RESOURCES_t *prach_resources = &UE_mac_inst[module_idP].RA_prach_resources;
113
  RACH_ConfigCommon_t *rach_ConfigCommon = NULL;
gauthier's avatar
gauthier committed
114
115
  uint8_t noGroupB = 0;
  uint8_t f_id = 0,num_prach=0;
116
  int numberOfRA_Preambles;
knopp's avatar
knopp committed
117
118
119
120
  int messageSizeGroupA;
  int sizeOfRA_PreamblesGroupA;
  int messagePowerOffsetGroupB;
  int PLThreshold;
121

122
123
124
125
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
  AssertFatal(UE_mac_inst[module_idP].radioResourceConfigCommon!=NULL,
	      "[UE %d] FATAL  radioResourceConfigCommon is NULL !!!\n",module_idP);
126

127
  rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon;
128
129
  numberOfRA_Preambles = (1+rach_ConfigCommon->preambleInfo.numberOfRA_Preambles)<<2;  

130
  if (rach_ConfigDedicated) {   // This is for network controlled Mobility, later
131
132
133
134
135
    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;
    }
136
137
  }

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

141
  if (!rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) {
142
143
    noGroupB = 1;
  } else {
knopp's avatar
knopp committed
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
    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
160
161
    /* TODO: what value to use as default? */
    messagePowerOffsetGroupB = -9999;
knopp's avatar
knopp committed
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
    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) {
193
      noGroupB = 1;
194
    }
195
196
197
  }

  if (first_Msg3 == 1) {
198
    if (noGroupB == 1) {
199
    	LOG_I(MAC, "Panos-D: get_prach_resources 2");
200
      // use Group A procedure
knopp's avatar
knopp committed
201
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())%numberOfRA_Preambles;
202
203
      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
      UE_mac_inst[module_idP].RA_usedGroupA = 1;
knopp's avatar
knopp committed
204
    } else if ((Msg3_size <messageSizeGroupA) ||
205
               (get_PL(module_idP,0,eNB_index) > PLThreshold)) {
206
    	LOG_I(MAC, "Panos-D: get_prach_resources 3");
207
      // use Group A procedure
knopp's avatar
knopp committed
208
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())%sizeOfRA_PreamblesGroupA;
209
210
211
      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
      UE_mac_inst[module_idP].RA_usedGroupA = 1;
    } else { // use Group B
212
    	LOG_I(MAC, "Panos-D: get_prach_resources 4");
knopp's avatar
knopp committed
213
214
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = sizeOfRA_PreamblesGroupA +
        (taus())%(numberOfRA_Preambles - sizeOfRA_PreamblesGroupA);
215
216
217
218
219
220
221
      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) {
222
      if (rach_ConfigCommon->preambleInfo.preamblesGroupAConfig) {
223
        UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())%rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA;
224
      } else {
225
        UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  = (taus())&0x3f;
226
      }
227
228
229

      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
    } else {
230
      // FIXME rach_ConfigCommon->preambleInfo.preamblesGroupAConfig may be zero
231
232
233
      UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex  =
        rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA +
        (taus())%(rach_ConfigCommon->preambleInfo.numberOfRA_Preambles -
gauthier's avatar
gauthier committed
234
                  rach_ConfigCommon->preambleInfo.preamblesGroupAConfig->sizeOfRA_PreamblesGroupA);
235
236
      UE_mac_inst[module_idP].RA_prach_resources.ra_RACH_MaskIndex = 0;
    }
237
  }
238

239
  // choose random PRACH resource in TDD
gauthier's avatar
gauthier committed
240
  if (UE_mac_inst[module_idP].tdd_Config) {
241
    num_prach = get_num_prach_tdd(module_idP);
242

243
    if ((num_prach>0) && (num_prach<6)) {
244
      UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index = (taus()%num_prach);
245
    }
246

247
248
    f_id = get_fid_prach_tdd(module_idP,
			     UE_mac_inst[module_idP].RA_prach_resources.ra_TDD_map_index);
249
250
251
  }

  // choose RA-RNTI
gauthier's avatar
gauthier committed
252
  UE_mac_inst[module_idP].RA_prach_resources.ra_RNTI = 1 + t_id + 10*f_id;
253
  LOG_I(MAC, "Panos-D: get_prach_resources 4");
254
255
}

256
void Msg1_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id)
257
{
knopp's avatar
   
knopp committed
258

259
260
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
261
  // start contention resolution timer
gauthier's avatar
gauthier committed
262
  UE_mac_inst[module_idP].RA_attempt_number++;
263

navid's avatar
navid committed
264
  if (opt_enabled) {
265
    trace_pdu(0, NULL, 0, module_idP, 0 , UE_mac_inst[module_idP].RA_prach_resources.ra_PreambleIndex,
266
        UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, UE_mac_inst[module_idP].RA_attempt_number);
267
    LOG_D(OPT,"[UE %d][RAPROC] TX MSG1 Frame %d trace pdu for rnti %x  with size %d\n",
gauthier's avatar
gauthier committed
268
          module_idP, frameP, 1, UE_mac_inst[module_idP].RA_Msg3_size);
269
  }
270

271
272
273
}


274
void Msg3_transmitted(module_id_t module_idP,uint8_t CC_id,frame_t frameP, uint8_t eNB_id)
275
{
knopp's avatar
   
knopp committed
276

277
278
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
279
280

  // start contention resolution timer
281
  LOG_D(MAC,"[UE %d][RAPROC] Frame %d : Msg3_tx: Setting contention resolution timer\n",module_idP,frameP);
gauthier's avatar
gauthier committed
282
283
  UE_mac_inst[module_idP].RA_contention_resolution_cnt = 0;
  UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 1;
284

navid's avatar
navid committed
285
  if (opt_enabled) { // msg3
286
    trace_pdu(0, &UE_mac_inst[module_idP].CCCH_pdu.payload[0], UE_mac_inst[module_idP].RA_Msg3_size,
287
              module_idP, 3, UE_mac_inst[module_idP].crnti, UE_mac_inst[module_idP].txFrame, UE_mac_inst[module_idP].txSubframe, 0, 0);
288
    LOG_D(OPT,"[UE %d][RAPROC] MSG3 Frame %d trace pdu Preamble %d   with size %d\n",
289
          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);
290
  }
291

292
293
294
}


295
296
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)
{
297

298
  LOG_I(MAC, "Panos-D: ue_get_rach 1");
299
  uint8_t                  Size               = 0;
300
  UE_MODE_t UE_mode;
301
  // Panos: Modification for phy_stub_ue operation
302
303
  if(nfapi_mode == 3) { // Panos: phy_stub_ue mode
	  UE_mode = UE_mac_inst[module_idP].UE_mode[0];
304
	  LOG_I(MAC, "Panos-D: ue_get_rach 2, E_mode: %d", UE_mode);
305
306
307
308
309
  }
  else { // Full stack mode
	  UE_mode = get_ue_mode(module_idP,0,eNB_indexP);
  }

310

311
312
  uint8_t                  lcid               = CCCH;
  uint16_t                 Size16;
313
  struct RACH_ConfigCommon *rach_ConfigCommon = (struct RACH_ConfigCommon *)NULL;
314
315
316
317
318
319
320
321
  int32_t                  frame_diff         = 0;
  mac_rlc_status_resp_t    rlc_status;
  uint8_t                  dcch_header_len    = 0;
  uint16_t                 sdu_lengths[8];
  uint8_t                  ulsch_buff[MAX_ULSCH_PAYLOAD_BYTES];

  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
knopp's avatar
   
knopp committed
322

323
  if (UE_mode == PRACH) {
324
	  LOG_I(MAC, "Panos-D: ue_get_rach 3");
325
    if (UE_mac_inst[module_idP].radioResourceConfigCommon) {
326
      rach_ConfigCommon = &UE_mac_inst[module_idP].radioResourceConfigCommon->rach_ConfigCommon;
327
    } else {
328
    	//AssertFatal(UE_mac_inst[module_idP].radioResourceConfigCommon!=NULL,"RadioResourceConfigCommon Null");
329
330
331
      return(NULL);
    }

332
    if (UE_mac_inst[module_idP].RA_active == 0) {
333
    	LOG_I(MAC, "Panos-D: ue_get_rach 4");
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
      LOG_I(MAC,"RA not active\n");
      // check if RRC is ready to initiate the RA procedure
      Size = mac_rrc_data_req(module_idP,
			      CC_id,
			      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_I(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_I(MAC,"[UE %d] Frame %d: Requested RRCConnectionRequest, got %d bytes\n",module_idP,frameP,Size);
      
      if (Size>0) {
351
    	  LOG_I(MAC, "Panos-D: ue_get_rach 5");
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
425
426
427
428
429
430
431
432
433
434
435
436
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
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
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
	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)
	
	AssertFatal(rach_ConfigCommon!=NULL,
		    "[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",module_idP,frameP);
	UE_mac_inst[module_idP].RA_window_cnt                    = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize;
	
	if (UE_mac_inst[module_idP].RA_window_cnt == 9) {
	  UE_mac_inst[module_idP].RA_window_cnt = 10;  // Note: 9 subframe window doesn't exist, after 8 is 10!
	}
	
	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);
	
      } else if (UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[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
	rlc_status = mac_rlc_status_ind(module_idP,UE_mac_inst[module_idP].crnti, eNB_indexP,frameP,subframeP,ENB_FLAG_NO,MBMS_FLAG_NO,
					DCCH,
					6);
	
	if (UE_mac_inst[module_idP].crnti_before_ho)
	  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",
		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);
	
	sdu_lengths[0] = mac_rlc_data_req(module_idP, UE_mac_inst[module_idP].crnti,
					  eNB_indexP, frameP,ENB_FLAG_NO, MBMS_FLAG_NO,
					  DCCH,
					  6,	//not used
					  (char *)&ulsch_buff[0]);
	
	LOG_D(MAC,"[UE %d] TX Got %d bytes for DCCH\n",module_idP,sdu_lengths[0]);
	update_bsr(module_idP, frameP, subframeP,eNB_indexP);
	UE_mac_inst[module_idP].scheduling_info.BSR[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]] =
	  locate_BsrIndexByBufferSize(BSR_TABLE, BSR_TABLE_SIZE, UE_mac_inst[module_idP].scheduling_info.BSR_bytes[UE_mac_inst[module_idP].scheduling_info.LCGID[DCCH]]);
	
	//TO DO: fill BSR infos in UL TBS
	
	//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)
	
	AssertFatal(rach_ConfigCommon!=NULL,
		    "[UE %d] FATAL Frame %d: rach_ConfigCommon is NULL !!!\n",module_idP,frameP);
	UE_mac_inst[module_idP].RA_window_cnt                    = 2+ rach_ConfigCommon->ra_SupervisionInfo.ra_ResponseWindowSize;
	
	if (UE_mac_inst[module_idP].RA_window_cnt == 9) {
	  UE_mac_inst[module_idP].RA_window_cnt = 10;  // Note: 9 subframe window doesn't exist, after 8 is 10!
	}
	
	
	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;
	
	if (frame_diff < 0) {
	  frame_diff = -frame_diff;
	}
	
	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;
	
	if (frame_diff < 0) {
	  frame_diff = -frame_diff;
	}
	
	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++;
	UE_mac_inst[module_idP].RA_prach_resources.ra_PREAMBLE_RECEIVED_TARGET_POWER +=
	  (rach_ConfigCommon->powerRampingParameters.powerRampingStep<<1);  // 2dB increments in ASN.1 definition
	int preambleTransMax = -1;
	switch (rach_ConfigCommon->ra_SupervisionInfo.preambleTransMax) {
	case PreambleTransMax_n3:
	  preambleTransMax = 3;
	  break;
	case PreambleTransMax_n4:
	  preambleTransMax = 4;
	  break;
	case PreambleTransMax_n5:
	  preambleTransMax = 5;
	  break;
	case PreambleTransMax_n6:
	  preambleTransMax = 6;
	  break;
	case PreambleTransMax_n7:
	  preambleTransMax = 7;
	  break;
	case PreambleTransMax_n8:
	  preambleTransMax = 8;
	  break;
	case PreambleTransMax_n10:
	  preambleTransMax = 10;
	  break;
	case PreambleTransMax_n20:
	  preambleTransMax = 20;
	  break;
	case PreambleTransMax_n50:
	  preambleTransMax = 50;
	  break;
	case PreambleTransMax_n100:
	  preambleTransMax = 100;
	  break;
	case 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);
	  // 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);
	}
	
	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);
542
      }
543
544
545
    }
  } else if (UE_mode == PUSCH) {
    LOG_D(MAC,"[UE %d] FATAL: Should not have checked for RACH in PUSCH yet ...",module_idP);
546
    AssertFatal(1==0,"");
547
  }
548
  
549
550
  return(NULL);
}