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

nikaeinn's avatar
nikaeinn committed
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


nikaeinn's avatar
nikaeinn committed
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

nikaeinn's avatar
nikaeinn committed
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
nikaeinn's avatar
nikaeinn committed
22
23
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
24
  OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
nikaeinn's avatar
nikaeinn committed
25

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

nikaeinn's avatar
nikaeinn committed
28
*******************************************************************************/
29

nikaeinn's avatar
nikaeinn committed
30
/*! \file ra_procedures.c
gauthier's avatar
gauthier committed
31
 * \brief Routines for UE MAC-layer Random-access procedures (36.321) V8.6 2009-03
nikaeinn's avatar
nikaeinn committed
32
 * \author R. Knopp and Navid Nikaein
gauthier's avatar
gauthier committed
33
34
35
 * \date 2011
 * \version 0.1
 * \company Eurecom
nikaeinn's avatar
nikaeinn committed
36
 * \email: knopp@eurecom.fr navid.nikaein@eurecom.fr
gauthier's avatar
gauthier committed
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)
{
knopp's avatar
   
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
knopp's avatar
   
knopp committed
67
  }
68

gauthier's avatar
gauthier committed
69
70
  uint8_t prachConfigIndex = UE_mac_inst[module_idP].radioResourceConfigCommon->prach_Config.prach_ConfigInfo.prach_ConfigIndex;
  uint8_t preambleformat;
71

gauthier's avatar
gauthier committed
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);
gauthier's avatar
gauthier committed
104
    mac_xface->macphy_exit("MAC get_DELTA_PREAMBLE Illegal preamble format");
105
106
107
108
109
    return(0);
  }

}

knopp's avatar
knopp committed
110

knopp's avatar
   
knopp committed
111
/// This routine implements Section 5.1.2 (UE Random Access Resource Selection) from 36.321
gauthier's avatar
gauthier committed
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)
{
gauthier's avatar
gauthier committed
119

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

knopp's avatar
   
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) {
gauthier's avatar
gauthier committed
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 {
knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
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
knopp's avatar
knopp committed
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;
knopp's avatar
knopp committed
220
221
    } else if ((Msg3_size <messageSizeGroupA) ||
               (mac_xface->get_PL(module_idP,0,eNB_index) > PLThreshold)) {
222
      // use Group A procedure
knopp's avatar
knopp committed
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
knopp's avatar
knopp committed
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 -
gauthier's avatar
gauthier committed
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
gauthier's avatar
gauthier committed
254
  if (UE_mac_inst[module_idP].tdd_Config) {
255
256
    num_prach = mac_xface->get_num_prach_tdd(mac_xface->lte_frame_parms);

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
262

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

  // choose RA-RNTI
gauthier's avatar
gauthier committed
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)
{
knopp's avatar
   
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
gauthier's avatar
gauthier committed
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",
gauthier's avatar
gauthier committed
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)
{
knopp's avatar
   
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);
gauthier's avatar
gauthier committed
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


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

knopp's avatar
   
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
knopp's avatar
   
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");
gauthier's avatar
gauthier committed
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);
gauthier's avatar
gauthier committed
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);
}