ue_procedures.c 102 KB
Newer Older
1
/*
2
3
4
5
6
7
8
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one
 * or more contributor license agreements.  See the NOTICE file
 * distributed with this work for additional information regarding
 * copyright ownership.  The OpenAirInterface Software Alliance
 * licenses this file to You under the OAI Public License, Version 1.1
 * (the "License"); you may not use this file except in compliance
 * with the License.  You may obtain a copy of the License at
9
10
11
12
13
14
15
16
17
18
19
20
 *
 *      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
22

/*! \file ue_procedures.c
gauthier's avatar
gauthier committed
23
 * \brief procedures related to UE
24
25
26
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \version 1
gauthier's avatar
gauthier committed
27
28
 * \email: navid.nikaein@eurecom.fr
 * @ingroup _mac
29

gauthier's avatar
gauthier committed
30
 */
31

32
33
34
35
#ifdef EXMIMO
#include <pthread.h>
#endif

36
37
#include "extern.h"
#include "defs.h"
38
#include "proto.h"
39
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
40
# include "SIMULATION/PHY_EMULATION/impl_defs.h"
41
#else
Cedric Roux's avatar
Cedric Roux committed
42
43
# include "SCHED/defs.h"
# include "PHY/impl_defs_top.h"
44
45
46
#endif
#include "PHY_INTERFACE/extern.h"
#include "COMMON/mac_rrc_primitives.h"
Cedric Roux's avatar
Cedric Roux committed
47
48

#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"
49
50
51
#include "RRC/LITE/extern.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
Cedric Roux's avatar
Cedric Roux committed
52
#include "UTIL/OPT/opt.h"
53
54
#include "OCG.h"
#include "OCG_extern.h"
55
#include "openair2/PHY_INTERFACE/phy_stub_UE.h"
Cedric Roux's avatar
Cedric Roux committed
56

57
#ifdef PHY_EMUL
Cedric Roux's avatar
Cedric Roux committed
58
# include "SIMULATION/simulation_defs.h"
59
#endif
60
#include "pdcp.h"
61

62
63
64
65
#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

66
67
#include "assertions.h"

68
69
#include "SIMULATION/TOOLS/defs.h" // for taus

70
#define DEBUG_HEADER_PARSING 1
71
#define ENABLE_MAC_PAYLOAD_DEBUG 1
72

fnabet's avatar
fnabet committed
73
74
extern uint8_t usim_test;

75
76
extern UL_IND_t *UL_INFO;

77
78
extern uint8_t  nfapi_mode;

79
80
81
82
/*
#ifndef USER_MODE
#define msg debug_msg
#endif
gauthier's avatar
gauthier committed
83
 */
84
mapping BSR_names[] = {
85
86
87
88
89
90
  {"NONE", 0},
  {"SHORT BSR", 1},
  {"TRUNCATED BSR", 2},
  {"LONG BSR", 3},
  {"PADDING BSR", 4},
  {NULL, -1}
91
92
93
};


94
95
void ue_init_mac(module_id_t module_idP)
{
96
97
  int i;
  // default values as deined in 36.331 sec 9.2.2
gauthier's avatar
gauthier committed
98
99
  LOG_I(MAC,"[UE%d] Applying default macMainConfig\n",module_idP);
  //UE_mac_inst[module_idP].scheduling_info.macConfig=NULL;
Cedric Roux's avatar
Cedric Roux committed
100
101
  UE_mac_inst[module_idP].scheduling_info.retxBSR_Timer= RetxBSR_Timer_r12_sf10240;
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_Timer=PeriodicBSR_Timer_r12_infinity;
gauthier's avatar
gauthier committed
102
103
104
105
106
107
108
109
110
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer = MAC_MainConfig__phr_Config__setup__periodicPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer = MAC_MainConfig__phr_Config__setup__prohibitPHR_Timer_sf20;
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db = MAC_MainConfig__phr_Config__setup__dl_PathlossChange_dB1;
  UE_mac_inst[module_idP].PHR_state = MAC_MainConfig__phr_Config_PR_setup;
  UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer=0;
  UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
  UE_mac_inst[module_idP].scheduling_info.maxHARQ_Tx=MAC_MainConfig__ul_SCH_Config__maxHARQ_Tx_n5;
  UE_mac_inst[module_idP].scheduling_info.ttiBundling=0;
fnabet's avatar
fnabet committed
111
112
  UE_mac_inst[module_idP].scheduling_info.extendedBSR_Sizes_r10=0;
  UE_mac_inst[module_idP].scheduling_info.extendedPHR_r10=0;
gauthier's avatar
gauthier committed
113
114
  UE_mac_inst[module_idP].scheduling_info.drx_config=NULL;
  UE_mac_inst[module_idP].scheduling_info.phr_config=NULL;
calvin wang's avatar
calvin wang committed
115
  // set init value 0xFFFF, make sure periodic timer and retx time counters are NOT active, after bsr transmission set the value configured by the NW.
Bilel's avatar
Bilel committed
116
117
  UE_mac_inst[module_idP].scheduling_info.periodicBSR_SF  =  MAC_UE_BSR_TIMER_NOT_RUNNING;
  UE_mac_inst[module_idP].scheduling_info.retxBSR_SF     =  MAC_UE_BSR_TIMER_NOT_RUNNING;
fnabet's avatar
fnabet committed
118
  UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
calvin wang's avatar
calvin wang committed
119
  
gauthier's avatar
gauthier committed
120
121
122
  UE_mac_inst[module_idP].scheduling_info.periodicPHR_SF =  get_sf_perioidicPHR_Timer(UE_mac_inst[module_idP].scheduling_info.periodicPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.prohibitPHR_SF =  get_sf_prohibitPHR_Timer(UE_mac_inst[module_idP].scheduling_info.prohibitPHR_Timer);
  UE_mac_inst[module_idP].scheduling_info.PathlossChange_db =  get_db_dl_PathlossChange(UE_mac_inst[module_idP].scheduling_info.PathlossChange);
fnabet's avatar
fnabet committed
123
  UE_mac_inst[module_idP].PHR_reporting_active = 0;
124
125

  for (i=0; i < MAX_NUM_LCID; i++) {
knopp's avatar
   
knopp committed
126
127
    LOG_D(MAC,"[UE%d] Applying default logical channel config for LCGID %d\n",module_idP,i);
    UE_mac_inst[module_idP].scheduling_info.Bj[i]=-1;
128
129
    UE_mac_inst[module_idP].scheduling_info.bucket_size[i]=-1;

130
    if (i < DTCH) { // initilize all control channels lcgid to 0
131
      UE_mac_inst[module_idP].scheduling_info.LCGID[i]=0;
132
    } else { // initialize all the data channels lcgid to 1
133
      UE_mac_inst[module_idP].scheduling_info.LCGID[i]=1;
134
    }
135

fnabet's avatar
fnabet committed
136
    UE_mac_inst[module_idP].scheduling_info.LCID_status[i]=LCID_EMPTY;
Bilel's avatar
Bilel committed
137
    UE_mac_inst[module_idP].scheduling_info.LCID_buffer_remain[i] = 0;
138
  }
139

140
141
  if(nfapi_mode == 3) {
	  pthread_mutex_init(&UE_mac_inst[module_idP].UL_INFO_mutex,NULL);
142
	  UE_mac_inst[module_idP].UE_mode[0] = NOT_SYNCHED; //PRACH;
143
144
145
146
147
148
149
	  UE_mac_inst[module_idP].first_ULSCH_Tx =0;
	  UE_mac_inst[module_idP].dl_config_req = NULL;
	  UE_mac_inst[module_idP].ul_config_req = NULL;
	  UE_mac_inst[module_idP].hi_dci0_req = NULL;
	  UE_mac_inst[module_idP].tx_req = NULL;
  }

150
#ifdef CBA
151

152
  for (i=0; i <NUM_MAX_CBA_GROUP; i++) {
153
    UE_mac_inst[module_idP].cba_last_access[i]= round(uniform_rngen(1,30));
154
  }
155
156

#endif
157
158
}

knopp's avatar
   
knopp committed
159

160
unsigned char *parse_header(unsigned char *mac_header,
161
162
163
164
165
166
167
                            unsigned char *num_ce,
                            unsigned char *num_sdu,
                            unsigned char *rx_ces,
                            unsigned char *rx_lcids,
                            unsigned short *rx_lengths,
                            unsigned short tb_length)
{
168

fnabet's avatar
fnabet committed
169
  unsigned char not_done=1,num_ces=0,num_cont_res = 0,num_padding = 0,num_sdus=0,lcid, num_sdu_cnt;
170
171
172
173
174
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length,ce_len=0;

  while (not_done==1) {

175
176
177
178
179
180
181
182
183
184
185
186
187
    if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
      //      printf("E=0\n");
      not_done = 0;
    }

    lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;

    if (lcid < UE_CONT_RES) {
      //printf("[MAC][UE] header %x.%x.%x\n",mac_header_ptr[0],mac_header_ptr[1],mac_header_ptr[2]);
      if (not_done==0) {// last MAC SDU, length is implicit
        mac_header_ptr++;
        length = tb_length-(mac_header_ptr-mac_header)-ce_len;

188
        for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++) {
189
          length -= rx_lengths[num_sdu_cnt];
190
        }
191
192
193
194
      } else {
        if (((SCH_SUBHEADER_LONG *)mac_header_ptr)->F == 1) {
          length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
          mac_header_ptr += 3;
195
#ifdef DEBUG_HEADER_PARSING
196
          LOG_D(MAC,"[UE] parse long sdu, size %x \n",length);
197
#endif
gauthier's avatar
gauthier committed
198

199
200
201
202
203
204
        }  else { //if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) {
          length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
          mac_header_ptr += 2;
        }
      }

205
#ifdef DEBUG_HEADER_PARSING
Cedric Roux's avatar
Cedric Roux committed
206
      LOG_D(MAC,"[UE] sdu %d lcid %d length %d (offset now %ld)\n",
207
            num_sdus,lcid,length,mac_header_ptr-mac_header);
208
#endif
209
210
211
212
213
      rx_lcids[num_sdus] = lcid;
      rx_lengths[num_sdus] = length;
      num_sdus++;
    } else { // This is a control element subheader
      if (lcid == SHORT_PADDING) {
fnabet's avatar
fnabet committed
214
    	num_padding ++;
215
216
217
218
219
220
        mac_header_ptr++;
      } else {
        rx_ces[num_ces] = lcid;
        num_ces++;
        mac_header_ptr ++;

221
        if (lcid==TIMING_ADV_CMD) {
222
          ce_len++;
223
        } else if (lcid==UE_CONT_RES) {
fnabet's avatar
fnabet committed
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240

        	// FNA: check MAC Header is one of thoses defined in Annex B of 36.321
        	// Check there is only 1 Contention Resolution
        	if (num_cont_res) {
        		LOG_W(MAC,"[UE] Msg4 Wrong received format: More than 1 Contention Resolution\n");
        		// exit parsing
        		return NULL;

        	}

        	// UE_CONT_RES shall never be the last subheader unless this is the only MAC subheader
        	if ((not_done == 0) && ((num_sdus) || (num_ces > 1) || (num_padding))) {
        		LOG_W(MAC,"[UE] Msg4 Wrong received format: Contention Resolution after num_ces=%d num_sdus=%d num_padding=%d\n",num_ces,num_sdus,num_padding);
        		// exit parsing
        		return NULL;
        	}
          num_cont_res ++;
241
          ce_len+=6;
242
        }
243
      }
244

245
#ifdef DEBUG_HEADER_PARSING
Cedric Roux's avatar
Cedric Roux committed
246
      LOG_D(MAC,"[UE] ce %d lcid %d (offset now %ld)\n",num_ces,lcid,mac_header_ptr-mac_header);
247
#endif
248
    }
249
  }
250

251
252
253
254
255
256
  *num_ce = num_ces;
  *num_sdu = num_sdus;

  return(mac_header_ptr);
}

257
258
uint32_t ue_get_SR(module_id_t module_idP,int CC_id,frame_t frameP,uint8_t eNB_id,uint16_t rnti, sub_frame_t subframe)
{
259
260
261

  // no UL-SCH resources available for this tti && UE has a valid PUCCH resources for SR configuration for this tti
  //  int MGL=6;// measurement gap length in ms
gauthier's avatar
gauthier committed
262
263
264
  int MGRP       = 0; // measurement gap repetition period in ms
  int gapOffset  = -1;
  int T          = 0;
265

266
  DevCheck(module_idP < (int)NB_UE_INST, module_idP, NB_UE_INST, 0);
267

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

271
  // determin the measurement gap
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
  if (UE_mac_inst[module_idP].measGapConfig !=NULL) {
    if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp0) {
      MGRP= 40;
      gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp0;
    } else if (UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.present == MeasGapConfig__setup__gapOffset_PR_gp1) {
      MGRP= 80;
      gapOffset= UE_mac_inst[module_idP].measGapConfig->choice.setup.gapOffset.choice.gp1;
    } else {
      LOG_W(MAC, "Measurement GAP offset is unknown\n");
    }

    T=MGRP/10;
    DevAssert( T != 0 );

    //check the measurement gap and sr prohibit timer
    if ((subframe ==  gapOffset %10) && ((frameP %T) == (floor(gapOffset/10)))
        && (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running ==0)) {
      UE_mac_inst[module_idP].scheduling_info.SR_pending=1;
      return(0);
    }
292
  }
293
294

  if ((UE_mac_inst[module_idP].physicalConfigDedicated != NULL) &&
295
      (UE_mac_inst[module_idP].scheduling_info.SR_pending==1) &&
gauthier's avatar
gauthier committed
296
      (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER <
297
298
       (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)))
     ) {
299
    LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d PHY asks for SR (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
300
          module_idP,rnti,frameP,subframe,
gauthier's avatar
gauthier committed
301
302
303
304
          UE_mac_inst[module_idP].scheduling_info.SR_COUNTER,
          (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)),
          UE_mac_inst[module_idP].scheduling_info.SR_pending);

305
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++;
gauthier's avatar
gauthier committed
306

307
308
309
310
    // start the sr-prohibittimer : rel 9 and above
    if (UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer > 0) { // timer configured
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer--;
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=1;
311
    } else {
312
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
313
    }
314
315
316
317
318
319
320
321
322
323
324
325
326

    LOG_D(MAC,"[UE %d][SR %x] Frame %d subframe %d send SR indication (SR_COUNTER/dsr_TransMax %d/%d), SR_pending %d\n",
          module_idP,rnti,frameP,subframe,
          UE_mac_inst[module_idP].scheduling_info.SR_COUNTER,
          (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)),
          UE_mac_inst[module_idP].scheduling_info.SR_pending);

    //UE_mac_inst[module_idP].ul_active =1;
    return(1); //instruct phy to signal SR
  } else {
    // notify RRC to relase PUCCH/SRS
    // clear any configured dl/ul
    // initiate RA
Bilel's avatar
Bilel committed
327
328
329
330
      if (UE_mac_inst[module_idP].scheduling_info.SR_pending){
          // release all pucch resource
          UE_mac_inst[module_idP].physicalConfigDedicated = NULL;
          UE_mac_inst[module_idP].ul_active=0;
fnabet's avatar
fnabet committed
331
          UE_mac_inst[module_idP].BSR_reporting_active=BSR_TRIGGER_NONE;
Bilel's avatar
Bilel committed
332
333
334

          LOG_I(MAC,"[UE %d] Release all SRs \n", module_idP);
      }
335
336
337
    UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
    return(0);
338
339
340
  }
}

341
342
//------------------------------------------------------------------------------
void
fnabet's avatar
fnabet committed
343
344
ue_send_sdu(
  module_id_t module_idP,
345
346
	    uint8_t CC_id,
	    frame_t frameP,
347
        sub_frame_t subframeP,
348
349
	    uint8_t* sdu,
	    uint16_t sdu_len,
fnabet's avatar
fnabet committed
350
351
352
353
  uint8_t eNB_index
)
//------------------------------------------------------------------------------
{
354
355
356
357
358

  unsigned char rx_ces[MAX_NUM_CE],num_ce,num_sdu,i,*payload_ptr;
  unsigned char rx_lcids[NB_RB_MAX];
  unsigned short rx_lengths[NB_RB_MAX];
  unsigned char *tx_sdu;
Gabriel's avatar
Gabriel committed
359
#if UE_TIMING_TRACE
360
  start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
Gabriel's avatar
Gabriel committed
361
#endif
gauthier's avatar
gauthier committed
362
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
363
364
365

  LOG_T(MAC,"sdu: %x.%x.%x\n",sdu[0],sdu[1],sdu[2]);

gauthier's avatar
gauthier committed
366
  if (opt_enabled) {
367
    trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
368
        frameP, subframeP, 0, 0);
navid's avatar
navid committed
369
370
    LOG_D(OPT,"[UE %d][DLSCH] Frame %d trace pdu for rnti %x  with size %d\n",
          module_idP, frameP, UE_mac_inst[module_idP].crnti, sdu_len);
371
372
373
374
375
  }

  payload_ptr = parse_header(sdu,&num_ce,&num_sdu,rx_ces,rx_lcids,rx_lengths,sdu_len);

#ifdef DEBUG_HEADER_PARSING
gauthier's avatar
gauthier committed
376
  LOG_D(MAC,"[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n",module_idP,
377
        frameP,eNB_index,num_ce,num_sdu);
378
379
380
#endif

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
Cedric Roux's avatar
Cedric Roux committed
381
  LOG_T(MAC,"[UE %d] First 32 bytes of DLSCH : \n", module_idP);
382

383
  for (i=0; i<32; i++) {
384
    LOG_T(MAC,"%x.",sdu[i]);
385
  }
386

387
  LOG_T(MAC,"\n");
388
389
#endif

fnabet's avatar
fnabet committed
390
391
  if (payload_ptr != NULL) {

392
393
394
395
  for (i=0; i<num_ce; i++) {
    //    printf("ce %d : %d\n",i,rx_ces[i]);
    switch (rx_ces[i]) {
    case UE_CONT_RES:
396

397
      LOG_I(MAC,"[UE %d][RAPROC] Frame %d : received contention resolution msg: %x.%x.%x.%x.%x.%x, Terminating RA procedure\n",
398
            module_idP,frameP,payload_ptr[0],payload_ptr[1],payload_ptr[2],payload_ptr[3],payload_ptr[4],payload_ptr[5]);
399
400

      if (UE_mac_inst[module_idP].RA_active == 1) {
Cedric Roux's avatar
Cedric Roux committed
401
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n", module_idP, frameP);
402
403
404
405
406
407
408
409
        UE_mac_inst[module_idP].RA_active=0;
        // check if RA procedure has finished completely (no contention)
        tx_sdu = &UE_mac_inst[module_idP].CCCH_pdu.payload[3];

        //Note: 3 assumes sizeof(SCH_SUBHEADER_SHORT) + PADDING CE, which is when UL-Grant has TBS >= 9 (64 bits)
        // (other possibility is 1 for TBS=7 (SCH_SUBHEADER_FIXED), or 2 for TBS=8 (SCH_SUBHEADER_FIXED+PADDING or SCH_SUBHEADER_SHORT)
        for (i=0; i<6; i++)
          if (tx_sdu[i] != payload_ptr[i]) {
410
411
412
413
414
415
416
417
418
419
        	  LOG_E(MAC,"[UE %d][RAPROC] Contention detected, RA failed\n",module_idP);
        	  if(nfapi_mode == 3) { // Panos: phy_stub mode
        		  // Panos: Modification for phy_stub mode operation here. We only need to make sure that the ue_mode is back to
        		  // PRACH state.
        		  UE_mac_inst[module_idP].UE_mode[eNB_index] = PRACH;
        		  //ra_failed(module_idP,CC_id,eNB_index);UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
        	  }
        	  else { // Full stack mode
        		  ra_failed(module_idP,CC_id,eNB_index);
        	  }
gauthier's avatar
gauthier committed
420
            VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
421
422
423
            return;
          }

Cedric Roux's avatar
Cedric Roux committed
424
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n", module_idP, frameP);
425
        UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
426

427
428
429
430
431
432
433
434
        if(nfapi_mode == 3) // phy_stub mode
        {
        	//Panos: Modification for phy_stub mode operation here. We only need to change the ue_mode to PUSCH
        	UE_mac_inst[module_idP].UE_mode[eNB_index] = PUSCH;
        }
        else { // Full stack mode
        	ra_succeeded(module_idP,CC_id,eNB_index);
        }
435
436
437
438
439
440
      }

      payload_ptr+=6;
      break;

    case TIMING_ADV_CMD:
441
#ifdef DEBUG_HEADER_PARSING
442
      LOG_D(MAC,"[UE] CE %d : UE Timing Advance : %d\n",i,payload_ptr[0]);
443
#endif
444
      // Panos: Eliminate call to process_timing_advance for the phy_stub UE operation mode. Is this correct?
445
446
447
448
      if (nfapi_mode!=3)
      {
    	  process_timing_advance(module_idP,CC_id,payload_ptr[0]);
      }
449
450
451
452
      payload_ptr++;
      break;

    case DRX_CMD:
453
#ifdef DEBUG_HEADER_PARSING
454
      LOG_D(MAC,"[UE] CE %d : UE DRX :",i);
455
#endif
456
457
458
      payload_ptr++;
      break;
    }
459
  }
460
461

  for (i=0; i<num_sdu; i++) {
462
#ifdef DEBUG_HEADER_PARSING
463
    LOG_D(MAC,"[UE] SDU %d : LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
464
#endif
465
    
466
467
    if (rx_lcids[i] == CCCH) {

468
469
470
471
472
473
      LOG_D(MAC,"[UE %d] rnti %x Frame %d : DLSCH -> DL-CCCH, RRC message (eNB %d, %d bytes)\n",
            module_idP,
            UE_mac_inst[module_idP].crnti,
            frameP,
            eNB_index,
            rx_lengths[i]);
474
475

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
476
      int j;
477

478
      for (j=0; j<rx_lengths[i]; j++) {
479
        LOG_T(MAC,"%x.",(uint8_t)payload_ptr[j]);
480
      }
481
482
483
484

      LOG_T(MAC,"\n");
#endif
      mac_rrc_data_ind(module_idP,
485
                       CC_id,
486
                       frameP,subframeP,
487
                       UE_mac_inst[module_idP].crnti,
488
                       CCCH,
489
490
491
492
493
                       (uint8_t*)payload_ptr,
                       rx_lengths[i],
                       ENB_FLAG_NO,
                       eNB_index,
                       0);
494

495
    } else if ((rx_lcids[i] == DCCH) || (rx_lcids[i] == DCCH1)) {
496
      LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DCCH%d, RRC message (eNB %d, %d bytes)\n", module_idP, frameP, rx_lcids[i],eNB_index,rx_lengths[i]);
497
498
      mac_rlc_data_ind(module_idP,
                       UE_mac_inst[module_idP].crnti,
499
		       eNB_index,
500
501
502
                       frameP,
                       ENB_FLAG_NO,
                       MBMS_FLAG_NO,
503
                       rx_lcids[i],
504
505
506
507
                       (char *)payload_ptr,
                       rx_lengths[i],
                       1,
                       NULL);
508
509
510
 
    } else if ((rx_lcids[i]  < NB_RB_MAX) && (rx_lcids[i] > DCCH1 )) {
      
511
      LOG_D(MAC,"[UE %d] Frame %d : DLSCH -> DL-DTCH%d (eNB %d, %d bytes)\n", module_idP, frameP,rx_lcids[i], eNB_index,rx_lengths[i]);
512
513

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
514
      int j;
515
516
      for (j=0;j<rx_lengths[i];j++)
	LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]);
517
      LOG_T(MAC,"\n");
518
#endif
519
      mac_rlc_data_ind(module_idP,
520
		       UE_mac_inst[module_idP].crnti,
521
522
		       eNB_index,
		       frameP,
523
524
525
526
527
528
529
530
531
		       ENB_FLAG_NO,
		       MBMS_FLAG_NO,
		       rx_lcids[i],
		       (char *)payload_ptr,
		       rx_lengths[i],
		       1,
		       NULL);
    } else {
      LOG_E(MAC,"[UE %d] Frame %d : unknown LCID %d (eNB %d)\n", module_idP, frameP,rx_lcids[i], eNB_index);
532
533
    }
    payload_ptr+= rx_lengths[i];
534
  }
fnabet's avatar
fnabet committed
535
  } // end if (payload_ptr != NULL)
536
  
gauthier's avatar
gauthier committed
537
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
Gabriel's avatar
Gabriel committed
538
#if UE_TIMING_TRACE
539
  stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
Gabriel's avatar
Gabriel committed
540
#endif
541
542
}

543
544
void ue_decode_si(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len)
{
Gabriel's avatar
Gabriel committed
545
546
547
#if UE_TIMING_TRACE
    start_meas(&UE_mac_inst[module_idP].rx_si);
#endif
gauthier's avatar
gauthier committed
548
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);
549

550
  LOG_D(MAC,"[UE %d] Frame %d Sending SI to RRC (LCID Id %d,len %d)\n",module_idP,frameP,BCCH,len);
551

gauthier's avatar
gauthier committed
552
  mac_rrc_data_ind(module_idP,
553
                   CC_id,
gauthier's avatar
gauthier committed
554
                   frameP,0, // unknown subframe
555
                   SI_RNTI,
556
557
558
                   BCCH,
                   (uint8_t *)pdu,
                   len,
559
                   ENB_FLAG_NO,
560
561
                   eNB_index,
                   0);
gauthier's avatar
gauthier committed
562
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
Gabriel's avatar
Gabriel committed
563
#if UE_TIMING_TRACE
564
  stop_meas(&UE_mac_inst[module_idP].rx_si);
Gabriel's avatar
Gabriel committed
565
#endif
navid's avatar
navid committed
566
567
568
569
570
571
572
  if (opt_enabled == 1) {
    trace_pdu(0,
	      (uint8_t *)pdu,
	      len,
	      module_idP,
	      4,
	      0xffff,
573
574
	      UE_mac_inst[module_idP].rxFrame,
	      UE_mac_inst[module_idP].rxSubframe,
navid's avatar
navid committed
575
576
577
578
579
	      0,
	      0);
    LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
	    module_idP, frameP, CC_id, 0xffff, len);
  }
580
581
}

582
583
void ue_decode_p(module_id_t module_idP,int CC_id,frame_t frameP, uint8_t eNB_index, void *pdu,uint16_t len)
{
Gabriel's avatar
Gabriel committed
584
585
586
#if UE_TIMING_TRACE
    start_meas(&UE_mac_inst[module_idP].rx_p);
#endif
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_IN);

  LOG_D(MAC,"[UE %d] Frame %d Sending Paging message to RRC (LCID Id %d,len %d)\n",module_idP,frameP,PCCH,len);

  mac_rrc_data_ind(module_idP,
                   CC_id,
                   frameP,0, // unknown subframe
                   P_RNTI,
                   PCCH,
                   (uint8_t *)pdu,
                   len,
                   ENB_FLAG_NO,
                   eNB_index,
                   0);
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_PCCH, VCD_FUNCTION_OUT);
Gabriel's avatar
Gabriel committed
602
#if UE_TIMING_TRACE
603
  stop_meas(&UE_mac_inst[module_idP].rx_p);
Gabriel's avatar
Gabriel committed
604
#endif
605
606
607
608
609
610
611
  if (opt_enabled == 1) {
    trace_pdu(0,
	      (uint8_t *)pdu,
	      len,
	      module_idP,
	      4,
	      P_RNTI,
612
613
	      UE_mac_inst[module_idP].rxFrame,
	      UE_mac_inst[module_idP].rxSubframe,
614
615
616
617
618
619
620
	      0,
	      0);
    LOG_D(OPT,"[UE %d][BCH] Frame %d trace pdu for CC_id %d rnti %x with size %d\n",
	    module_idP, frameP, CC_id, P_RNTI, len);
  }
}

Cedric Roux's avatar
Cedric Roux committed
621
#if defined(Rel10) || defined(Rel14)
622
unsigned char *parse_mch_header(unsigned char *mac_header,
623
624
625
626
627
                                unsigned char *num_sdu,
                                unsigned char *rx_lcids,
                                unsigned short *rx_lengths,
                                unsigned short tb_length)
{
628
629
630
  unsigned char not_done=1, num_sdus=0, lcid, i;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length;
631

632
  while (not_done == 1) {
633
634
635
636
637
638
639
640
641
642
643
    if (((SCH_SUBHEADER_FIXED *)mac_header_ptr)->E == 0) {
      not_done = 0;
    }

    lcid = ((SCH_SUBHEADER_FIXED *)mac_header_ptr)->LCID;

    if (lcid < SHORT_PADDING) {// subheader for MSI, MCCH or MTCH
      if (not_done == 0) { // last MAC SDU, length is implicit
        mac_header_ptr++;
        length = tb_length- (mac_header_ptr - mac_header);

644
        for (i=0; i<num_sdus; i++) {
645
          length -= rx_lengths[i];
646
        }
647
648
649
650
651
652
653
654
655
      } else { // not the last MAC SDU
        if ( ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F == 1) {// subheader has length of 3octets
          //    length = ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L;
          length = ((((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_MSB & 0x7f ) << 8 ) | (((SCH_SUBHEADER_LONG *)mac_header_ptr)->L_LSB & 0xff);
          mac_header_ptr += 3;
        } else { // subheader has length of 2octets
          length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
          mac_header_ptr += 2;
        }
656
      }
657
658
659
660
661
662
663
664

      rx_lcids[num_sdus] = lcid;
      rx_lengths[num_sdus] = length;
      num_sdus++;
    } else { // subheader for padding
      //     if (lcid == SHORT_PADDING)
      mac_header_ptr++;
    }
665
  }
666

667
668
669
670
671
  *num_sdu = num_sdus;
  return(mac_header_ptr);
}

// this function is for sending mch_sdu from phy to mac
672
673
void ue_send_mch_sdu(module_id_t module_idP, uint8_t CC_id, frame_t frameP, uint8_t *sdu, uint16_t sdu_len, uint8_t eNB_index, uint8_t sync_area)
{
674
675

  unsigned char num_sdu, i, *payload_ptr;
676
  unsigned char rx_lcids[NB_RB_MAX];
677
  unsigned short rx_lengths[NB_RB_MAX];
Gabriel's avatar
Gabriel committed
678
#if UE_TIMING_TRACE
679
  start_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
Gabriel's avatar
Gabriel committed
680
#endif
gauthier's avatar
gauthier committed
681
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN);
682

683
  LOG_D(MAC,"[UE %d] Frame %d : process the mch PDU for sync area %d \n",module_idP,frameP, sync_area);
gauthier's avatar
gauthier committed
684
685
  LOG_D(MAC,"[UE %d] sdu: %x.%x\n", module_idP,sdu[0], sdu[1]);
  LOG_D(MAC,"[UE %d] parse_mch_header, demultiplex\n",module_idP);
686
687

  payload_ptr = parse_mch_header(sdu, &num_sdu, rx_lcids, rx_lengths, sdu_len);
gauthier's avatar
gauthier committed
688
  LOG_D(MAC,"[UE %d] parse_mch_header, found %d sdus\n",module_idP,num_sdu);
689
690

  for (i=0; i<num_sdu; i++) {
691
692
693
694
695
696
697
    if (rx_lcids[i] == MCH_SCHDL_INFO) {
      if (UE_mac_inst[module_idP].mcch_status==1) {
        LOG_I(MAC,"[UE %d] Frame %d : MCH->MSI for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]);
        // ??store necessary scheduling info to ue_mac_inst in order to
        // calculate exact position of interested service (for the complex case has >1 mtch)
        // set msi_status to 1
        UE_mac_inst[module_idP].msi_status = 1;
698
      }
699
700
701
    } else if (rx_lcids[i] == MCCH_LCHANID) {
      LOG_I(MAC,"[UE %d] Frame %d : SDU %d MCH->MCCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, i, sync_area, eNB_index, rx_lengths[i]);
      mac_rrc_data_ind(module_idP,
702
                       CC_id,
gauthier's avatar
gauthier committed
703
                       frameP,0, // unknown subframe
704
                       M_RNTI,
705
706
707
708
709
710
711
712
                       MCCH,
                       payload_ptr, rx_lengths[i], 0, eNB_index, sync_area);
    } else if (rx_lcids[i] == MTCH) {
      if (UE_mac_inst[module_idP].msi_status==1) {
        LOG_I(MAC,"[UE %d] Frame %d : MCH->MTCH for sync area %d (eNB %d, %d bytes)\n",module_idP,frameP, sync_area, eNB_index, rx_lengths[i]);

        mac_rlc_data_ind(
          module_idP,
713
          UE_mac_inst[module_idP].crnti,
714
715
          eNB_index,
	  frameP,
716
717
718
719
720
721
722
          ENB_FLAG_NO,
          MBMS_FLAG_YES,
          MTCH, /*+ (maxDRB + 3),*/
          (char *)payload_ptr,
          rx_lengths[i],
          1,
          NULL);
gauthier's avatar
gauthier committed
723
724

      }
725
726
727
728
729
730
731
732
733
    } else {
      LOG_W(MAC,"[UE %d] Frame %d : unknown sdu %d rx_lcids[%d]=%d mcch status %d eNB %d \n",
            module_idP,
            frameP,
            rx_lengths[i],
            i,
            rx_lcids[i],
            UE_mac_inst[module_idP].mcch_status, eNB_index);
    }
gauthier's avatar
gauthier committed
734

735
    payload_ptr += rx_lengths[i];
736
737
  }

gauthier's avatar
gauthier committed
738
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT);
Gabriel's avatar
Gabriel committed
739
#if UE_TIMING_TRACE
740
  stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
Gabriel's avatar
Gabriel committed
741
#endif
742
743
}

knopp's avatar
knopp committed
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768

void ue_send_sl_sdu(module_id_t module_idP,
		    uint8_t CC_id,
		    frame_t frameP,
		    sub_frame_t subframeP,
		    uint8_t* sdu,
		    uint16_t sdu_len,
		    uint8_t eNB_index
		    ) {

  mac_rlc_data_ind(
		   module_idP,
		   0x1234,
		   eNB_index,
		   frameP,
		   ENB_FLAG_NO,
		   MBMS_FLAG_NO,
		   3,
		   (char *)sdu,
		   sdu_len,
		   1,
		   NULL);
}


769
770
int8_t ue_get_mbsfn_sf_alloction (module_id_t module_idP, uint8_t mbsfn_sync_area, unsigned char eNB_index)
{
gauthier's avatar
gauthier committed
771
  // currently there is one-to-one mapping between sf allocation pattern and sync area
772
773
  if (mbsfn_sync_area >= MAX_MBSFN_AREA) {
    LOG_W( MAC, "[UE %"PRIu8"] MBSFN synchronization area %"PRIu8" out of range for eNB %"PRIu8"\n", module_idP, mbsfn_sync_area, eNB_index );
774
    return -1;
775
  } else if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) {
776
    return mbsfn_sync_area;
777
  } else {
778
    LOG_W( MAC, "[UE %"PRIu8"] MBSFN Subframe Config pattern %"PRIu8" not found \n", module_idP, mbsfn_sync_area );
779
    return -1;
780
781
  }
}
782

783
784
int ue_query_mch(module_id_t module_idP, uint8_t CC_id, uint32_t frameP, uint32_t subframe, uint8_t eNB_index,uint8_t *sync_area, uint8_t *mcch_active)
{
785

winckel's avatar
winckel committed
786
  int i=0, j=0, ii=0, msi_pos=0, mcch_mcs = - 1;
787
  int mcch_flag=0, mtch_flag=0, msi_flag=0;
gauthier's avatar
gauthier committed
788
789
  int mbsfn_period = 0;// 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
  int mcch_period = 0;// 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);
winckel's avatar
winckel committed
790
  int mch_scheduling_period = -1;
791

792
  int frame_FDD=1;
793

794

Gabriel's avatar
Gabriel committed
795
#if UE_TIMING_TRACE
796
  start_meas(&UE_mac_inst[module_idP].ue_query_mch);
Gabriel's avatar
Gabriel committed
797
#endif
798

799
  if (UE_mac_inst[module_idP].pmch_Config[0]) {
gauthier's avatar
gauthier committed
800
    mch_scheduling_period = 8<<(UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9);
801
  }
802

803
  for (i=0;
804
805
806
       i< UE_mac_inst[module_idP].num_active_mbsfn_area;
       i++ ) {
    // assume, that there is always a mapping
807
    if ((j=ue_get_mbsfn_sf_alloction(module_idP,i,eNB_index)) == -1) {
808
      return -1; // continue;
809
    }
810
811
812
813
814
815

    ii=0;
    msi_pos=0;
    mbsfn_period = 1<<(UE_mac_inst[module_idP].mbsfn_SubframeConfig[0]->radioframeAllocationPeriod);
    mcch_period = 32<<(UE_mac_inst[module_idP].mbsfn_AreaInfo[0]->mcch_Config_r9.mcch_RepetitionPeriod_r9);

816
    LOG_D(MAC,
Cedric Roux's avatar
Cedric Roux committed
817
          "[UE %d] Frame %d subframe %d: Checking MBSFN Sync Area %d/%d with SF allocation %d/%d for MCCH and MTCH (mbsfn period %d, mcch period %d,mac sched period (%d,%ld))\n",
818
          module_idP,frameP, subframe,i,UE_mac_inst[module_idP].num_active_mbsfn_area,
gauthier's avatar
gauthier committed
819
820
821
          j,UE_mac_inst[module_idP].num_sf_allocation_pattern,mbsfn_period,mcch_period,
          mch_scheduling_period,UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset);

822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
    // get the real MCS value
    switch (UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.signallingMCS_r9) {
    case 0:
      mcch_mcs = 2;
      break;

    case 1:
      mcch_mcs = 7;
      break;

    case 2:
      mcch_mcs = 13;
      break;

    case 3:
      mcch_mcs = 19;
      break;
    }

    if (frameP % mbsfn_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset) { // MBSFN frameP
      if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.present == MBSFN_SubframeConfig__subframeAllocation_PR_oneFrame) { // one-frameP format

        if (UE_mac_inst[module_idP].pmch_Config[0]) {
          //  Find the first subframe in this MCH to transmit MSI
          if (frameP % mch_scheduling_period == UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->radioframeAllocationOffset ) {
            while (ii == 0) {
              ii = UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & (0x80>>msi_pos);
              msi_pos++;
            }
          }
        }

854
855
	if (UE_mac_inst[module_idP].tdd_Config == NULL) frame_FDD=1;
	else frame_FDD=0;
856
857
858
        // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
        switch (subframe) {
        case 1:
859
          if (frame_FDD==1) {
860
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) {
861
              if (msi_pos == 1) {
862
                msi_flag = 1;
863
              }
864

865
	      if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
866
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) ) {
867
                mcch_flag = 1;
868
              }
869
870
871
872
873
874
875
876

              mtch_flag = 1;
            }
          }

          break;

        case 2:
877
          if (frame_FDD==1) {
878
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) {
879
              if (msi_pos == 2) {
880
                msi_flag = 1;
881
              }
882
883

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
884
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) ) {
885
                mcch_flag = 1;
886
              }
887
888
889
890

              mtch_flag = 1;
            }
          }
gauthier's avatar
gauthier committed
891

892
893
894
          break;

        case 3:
895
          if (frame_FDD==0) { //TDD
896
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) {
897
              if (msi_pos == 1) {
898
                msi_flag = 1;
899
              }
900
901

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
902
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) ) {
903
                mcch_flag = 1;
904
              }
905
906
907
908
909

              mtch_flag = 1;
            }
          } else { // FDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) {
910
              if (msi_pos == 3) {
911
                msi_flag = 1;
912
              }
913
914

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
915
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) ) {
916
                mcch_flag = 1;
917
              }
918
919
920
921
922
923
924
925

              mtch_flag = 1;
            }
          }

          break;

        case 4:
926
          if (frame_FDD==0) {
927
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) {
928
              if (msi_pos == 2) {
929
                msi_flag = 1;
930
              }
931
932

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
933
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) ) {
934
                mcch_flag = 1;
935
              }
936
937
938
939
940
941
942
943

              mtch_flag = 1;
            }
          }

          break;

        case 6:
944
          if (frame_FDD==1) {
945
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) {
946
              if (msi_pos == 4) {
947
                msi_flag = 1;
948
              }
949
950

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
951
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) ) {
952
                mcch_flag = 1;
953
              }
954
955
956

              mtch_flag = 1;
            }