ue_procedures.c 96.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
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 79 80
/*
#ifndef USER_MODE
#define msg debug_msg
#endif
gauthier's avatar
gauthier committed
81
 */
82
mapping BSR_names[] = {
83 84 85 86 87 88
  {"NONE", 0},
  {"SHORT BSR", 1},
  {"TRUNCATED BSR", 2},
  {"LONG BSR", 3},
  {"PADDING BSR", 4},
  {NULL, -1}
89 90 91
};


92 93
void ue_init_mac(module_id_t module_idP)
{
94 95
  int i;
  // default values as deined in 36.331 sec 9.2.2
gauthier's avatar
gauthier committed
96 97
  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
98 99
  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
100 101 102 103 104 105 106 107 108
  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
109 110
  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
111 112
  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
113
  // 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
114 115
  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
116
  UE_mac_inst[module_idP].BSR_reporting_active = BSR_TRIGGER_NONE;
calvin wang's avatar
calvin wang committed
117
  
gauthier's avatar
gauthier committed
118 119 120
  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
121
  UE_mac_inst[module_idP].PHR_reporting_active = 0;
122 123

  for (i=0; i < MAX_NUM_LCID; i++) {
124 125
    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;
126 127
    UE_mac_inst[module_idP].scheduling_info.bucket_size[i]=-1;

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

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

138
#ifdef CBA
139

140
  for (i=0; i <NUM_MAX_CBA_GROUP; i++) {
141
    UE_mac_inst[module_idP].cba_last_access[i]= round(uniform_rngen(1,30));
142
  }
143 144

#endif
145 146
}

147

148
unsigned char *parse_header(unsigned char *mac_header,
149 150 151 152 153 154 155
                            unsigned char *num_ce,
                            unsigned char *num_sdu,
                            unsigned char *rx_ces,
                            unsigned char *rx_lcids,
                            unsigned short *rx_lengths,
                            unsigned short tb_length)
{
156

fnabet's avatar
fnabet committed
157
  unsigned char not_done=1,num_ces=0,num_cont_res = 0,num_padding = 0,num_sdus=0,lcid, num_sdu_cnt;
158 159 160 161 162
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length,ce_len=0;

  while (not_done==1) {

163 164 165 166 167 168 169 170 171 172 173 174 175
    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;

176
        for (num_sdu_cnt=0; num_sdu_cnt < num_sdus ; num_sdu_cnt++) {
177
          length -= rx_lengths[num_sdu_cnt];
178
        }
179 180 181 182
      } 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;
183
#ifdef DEBUG_HEADER_PARSING
184
          LOG_D(MAC,"[UE] parse long sdu, size %x \n",length);
185
#endif
gauthier's avatar
gauthier committed
186

187 188 189 190 191 192
        }  else { //if (((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F == 0) {
          length = ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L;
          mac_header_ptr += 2;
        }
      }

193
#ifdef DEBUG_HEADER_PARSING
Cedric Roux's avatar
Cedric Roux committed
194
      LOG_D(MAC,"[UE] sdu %d lcid %d length %d (offset now %ld)\n",
195
            num_sdus,lcid,length,mac_header_ptr-mac_header);
196
#endif
197 198 199 200 201
      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
202
    	num_padding ++;
203 204 205 206 207 208
        mac_header_ptr++;
      } else {
        rx_ces[num_ces] = lcid;
        num_ces++;
        mac_header_ptr ++;

209
        if (lcid==TIMING_ADV_CMD) {
210
          ce_len++;
211
        } else if (lcid==UE_CONT_RES) {
fnabet's avatar
fnabet committed
212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228

        	// 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 ++;
229
          ce_len+=6;
230
        }
231
      }
232

233
#ifdef DEBUG_HEADER_PARSING
Cedric Roux's avatar
Cedric Roux committed
234
      LOG_D(MAC,"[UE] ce %d lcid %d (offset now %ld)\n",num_ces,lcid,mac_header_ptr-mac_header);
235
#endif
236
    }
237
  }
238

239 240 241 242 243 244
  *num_ce = num_ces;
  *num_sdu = num_sdus;

  return(mac_header_ptr);
}

245 246
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)
{
247 248 249

  // 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
250 251 252
  int MGRP       = 0; // measurement gap repetition period in ms
  int gapOffset  = -1;
  int T          = 0;
253

254
  DevCheck(module_idP < (int)NB_UE_INST, module_idP, NB_UE_INST, 0);
255

256 257
  AssertFatal(CC_id==0,
	      "Transmission on secondary CCs is not supported yet\n");
258

259
  // determin the measurement gap
260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 277 278 279
  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);
    }
280
  }
281 282

  if ((UE_mac_inst[module_idP].physicalConfigDedicated != NULL) &&
283
      (UE_mac_inst[module_idP].scheduling_info.SR_pending==1) &&
gauthier's avatar
gauthier committed
284
      (UE_mac_inst[module_idP].scheduling_info.SR_COUNTER <
285 286
       (1<<(2+UE_mac_inst[module_idP].physicalConfigDedicated->schedulingRequestConfig->choice.setup.dsr_TransMax)))
     ) {
287
    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",
288
          module_idP,rnti,frameP,subframe,
gauthier's avatar
gauthier committed
289 290 291 292
          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);

293
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER++;
gauthier's avatar
gauthier committed
294

295 296 297 298
    // 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;
299
    } else {
300
      UE_mac_inst[module_idP].scheduling_info.sr_ProhibitTimer_Running=0;
301
    }
302 303 304 305 306 307 308 309 310 311 312 313 314

    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
315 316 317 318
      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
319
          UE_mac_inst[module_idP].BSR_reporting_active=BSR_TRIGGER_NONE;
Bilel's avatar
Bilel committed
320 321 322

          LOG_I(MAC,"[UE %d] Release all SRs \n", module_idP);
      }
323 324 325
    UE_mac_inst[module_idP].scheduling_info.SR_pending=0;
    UE_mac_inst[module_idP].scheduling_info.SR_COUNTER=0;
    return(0);
326 327 328
  }
}

329 330
//------------------------------------------------------------------------------
void
fnabet's avatar
fnabet committed
331 332
ue_send_sdu(
  module_id_t module_idP,
333 334
	    uint8_t CC_id,
	    frame_t frameP,
335
        sub_frame_t subframeP,
336 337
	    uint8_t* sdu,
	    uint16_t sdu_len,
fnabet's avatar
fnabet committed
338 339 340 341
  uint8_t eNB_index
)
//------------------------------------------------------------------------------
{
342 343 344 345 346

  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
347
#if UE_TIMING_TRACE
348
  start_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
Gabriel's avatar
Gabriel committed
349
#endif
gauthier's avatar
gauthier committed
350
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_IN);
351 352 353

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

gauthier's avatar
gauthier committed
354
  if (opt_enabled) {
355
    trace_pdu(1, sdu, sdu_len, module_idP, 3, UE_mac_inst[module_idP].crnti,
356
        frameP, subframeP, 0, 0);
navid's avatar
navid committed
357 358
    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);
359 360 361 362 363
  }

  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
364
  LOG_D(MAC,"[UE %d] ue_send_sdu : Frame %d eNB_index %d : num_ce %d num_sdu %d\n",module_idP,
365
        frameP,eNB_index,num_ce,num_sdu);
366 367 368
#endif

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

371
  for (i=0; i<32; i++) {
372
    LOG_T(MAC,"%x.",sdu[i]);
373
  }
374

375
  LOG_T(MAC,"\n");
376 377
#endif

fnabet's avatar
fnabet committed
378 379
  if (payload_ptr != NULL) {

380 381 382 383
  for (i=0; i<num_ce; i++) {
    //    printf("ce %d : %d\n",i,rx_ces[i]);
    switch (rx_ces[i]) {
    case UE_CONT_RES:
384

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

      if (UE_mac_inst[module_idP].RA_active == 1) {
Cedric Roux's avatar
Cedric Roux committed
389
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing RA_active flag\n", module_idP, frameP);
390 391 392 393 394 395 396 397 398
        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]) {
            LOG_E(MAC,"[UE %d][RAPROC] Contention detected, RA failed\n",module_idP);
399
            ra_failed(module_idP,CC_id,eNB_index);
gauthier's avatar
gauthier committed
400
            UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
gauthier's avatar
gauthier committed
401
            VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
402 403 404
            return;
          }

Cedric Roux's avatar
Cedric Roux committed
405
        LOG_I(MAC,"[UE %d][RAPROC] Frame %d : Clearing contention resolution timer\n", module_idP, frameP);
406
        UE_mac_inst[module_idP].RA_contention_resolution_timer_active = 0;
407 408 409 410

        //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;
        //ra_succeeded(module_idP,CC_id,eNB_index);
411 412 413 414 415 416
      }

      payload_ptr+=6;
      break;

    case TIMING_ADV_CMD:
417
#ifdef DEBUG_HEADER_PARSING
418
      LOG_D(MAC,"[UE] CE %d : UE Timing Advance : %d\n",i,payload_ptr[0]);
419
#endif
420
      process_timing_advance(module_idP,CC_id,payload_ptr[0]);
421 422 423 424
      payload_ptr++;
      break;

    case DRX_CMD:
425
#ifdef DEBUG_HEADER_PARSING
426
      LOG_D(MAC,"[UE] CE %d : UE DRX :",i);
427
#endif
428 429 430
      payload_ptr++;
      break;
    }
431
  }
432 433

  for (i=0; i<num_sdu; i++) {
434
#ifdef DEBUG_HEADER_PARSING
435
    LOG_D(MAC,"[UE] SDU %d : LCID %d, length %d\n",i,rx_lcids[i],rx_lengths[i]);
436
#endif
437
    
438 439
    if (rx_lcids[i] == CCCH) {

440 441 442 443 444 445
      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]);
446 447

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
448
      int j;
449

450
      for (j=0; j<rx_lengths[i]; j++) {
451
        LOG_T(MAC,"%x.",(uint8_t)payload_ptr[j]);
452
      }
453 454 455 456

      LOG_T(MAC,"\n");
#endif
      mac_rrc_data_ind(module_idP,
457
                       CC_id,
458
                       frameP,subframeP,
459
                       UE_mac_inst[module_idP].crnti,
460
                       CCCH,
461 462 463 464 465
                       (uint8_t*)payload_ptr,
                       rx_lengths[i],
                       ENB_FLAG_NO,
                       eNB_index,
                       0);
466

467
    } else if ((rx_lcids[i] == DCCH) || (rx_lcids[i] == DCCH1)) {
468
      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]);
469 470
      mac_rlc_data_ind(module_idP,
                       UE_mac_inst[module_idP].crnti,
471
		       eNB_index,
472 473 474
                       frameP,
                       ENB_FLAG_NO,
                       MBMS_FLAG_NO,
475
                       rx_lcids[i],
476 477 478 479
                       (char *)payload_ptr,
                       rx_lengths[i],
                       1,
                       NULL);
480 481 482
 
    } else if ((rx_lcids[i]  < NB_RB_MAX) && (rx_lcids[i] > DCCH1 )) {
      
483
      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]);
484 485

#if defined(ENABLE_MAC_PAYLOAD_DEBUG)
486
      int j;
487 488
      for (j=0;j<rx_lengths[i];j++)
	LOG_T(MAC,"%x.",(unsigned char)payload_ptr[j]);
489
      LOG_T(MAC,"\n");
490
#endif
491
      mac_rlc_data_ind(module_idP,
492
		       UE_mac_inst[module_idP].crnti,
493 494
		       eNB_index,
		       frameP,
495 496 497 498 499 500 501 502 503
		       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);
504 505
    }
    payload_ptr+= rx_lengths[i];
506
  }
fnabet's avatar
fnabet committed
507
  } // end if (payload_ptr != NULL)
508
  
gauthier's avatar
gauthier committed
509
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_SDU, VCD_FUNCTION_OUT);
Gabriel's avatar
Gabriel committed
510
#if UE_TIMING_TRACE
511
  stop_meas(&UE_mac_inst[module_idP].rx_dlsch_sdu);
Gabriel's avatar
Gabriel committed
512
#endif
513 514
}

515 516
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
517 518 519
#if UE_TIMING_TRACE
    start_meas(&UE_mac_inst[module_idP].rx_si);
#endif
gauthier's avatar
gauthier committed
520
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_IN);
521

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

gauthier's avatar
gauthier committed
524
  mac_rrc_data_ind(module_idP,
525
                   CC_id,
gauthier's avatar
gauthier committed
526
                   frameP,0, // unknown subframe
527
                   SI_RNTI,
528 529 530
                   BCCH,
                   (uint8_t *)pdu,
                   len,
531
                   ENB_FLAG_NO,
532 533
                   eNB_index,
                   0);
gauthier's avatar
gauthier committed
534
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_DECODE_SI, VCD_FUNCTION_OUT);
Gabriel's avatar
Gabriel committed
535
#if UE_TIMING_TRACE
536
  stop_meas(&UE_mac_inst[module_idP].rx_si);
Gabriel's avatar
Gabriel committed
537
#endif
navid's avatar
navid committed
538 539 540 541 542 543 544
  if (opt_enabled == 1) {
    trace_pdu(0,
	      (uint8_t *)pdu,
	      len,
	      module_idP,
	      4,
	      0xffff,
545 546
	      UE_mac_inst[module_idP].rxFrame,
	      UE_mac_inst[module_idP].rxSubframe,
navid's avatar
navid committed
547 548 549 550 551
	      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);
  }
552 553
}

554 555
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
556 557 558
#if UE_TIMING_TRACE
    start_meas(&UE_mac_inst[module_idP].rx_p);
#endif
559 560 561 562 563 564 565 566 567 568 569 570 571 572 573
  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
574
#if UE_TIMING_TRACE
575
  stop_meas(&UE_mac_inst[module_idP].rx_p);
Gabriel's avatar
Gabriel committed
576
#endif
577 578 579 580 581 582 583
  if (opt_enabled == 1) {
    trace_pdu(0,
	      (uint8_t *)pdu,
	      len,
	      module_idP,
	      4,
	      P_RNTI,
584 585
	      UE_mac_inst[module_idP].rxFrame,
	      UE_mac_inst[module_idP].rxSubframe,
586 587 588 589 590 591 592
	      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
593
#if defined(Rel10) || defined(Rel14)
594
unsigned char *parse_mch_header(unsigned char *mac_header,
595 596 597 598 599
                                unsigned char *num_sdu,
                                unsigned char *rx_lcids,
                                unsigned short *rx_lengths,
                                unsigned short tb_length)
{
600 601 602
  unsigned char not_done=1, num_sdus=0, lcid, i;
  unsigned char *mac_header_ptr = mac_header;
  unsigned short length;
603

604
  while (not_done == 1) {
605 606 607 608 609 610 611 612 613 614 615
    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);

616
        for (i=0; i<num_sdus; i++) {
617
          length -= rx_lengths[i];
618
        }
619 620 621 622 623 624 625 626 627
      } 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;
        }
628
      }
629 630 631 632 633 634 635 636

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

639 640 641 642 643
  *num_sdu = num_sdus;
  return(mac_header_ptr);
}

// this function is for sending mch_sdu from phy to mac
644 645
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)
{
646 647

  unsigned char num_sdu, i, *payload_ptr;
648
  unsigned char rx_lcids[NB_RB_MAX];
649
  unsigned short rx_lengths[NB_RB_MAX];
Gabriel's avatar
Gabriel committed
650
#if UE_TIMING_TRACE
651
  start_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
Gabriel's avatar
Gabriel committed
652
#endif
gauthier's avatar
gauthier committed
653
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_IN);
654

655
  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
656 657
  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);
658 659

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

  for (i=0; i<num_sdu; i++) {
663 664 665 666 667 668 669
    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;
670
      }
671 672 673
    } 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,
674
                       CC_id,
gauthier's avatar
gauthier committed
675
                       frameP,0, // unknown subframe
676
                       M_RNTI,
677 678 679 680 681 682 683 684
                       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,
685
          UE_mac_inst[module_idP].crnti,
686 687
          eNB_index,
	  frameP,
688 689 690 691 692 693 694
          ENB_FLAG_NO,
          MBMS_FLAG_YES,
          MTCH, /*+ (maxDRB + 3),*/
          (char *)payload_ptr,
          rx_lengths[i],
          1,
          NULL);
gauthier's avatar
gauthier committed
695 696

      }
697 698 699 700 701 702 703 704 705
    } 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
706

707
    payload_ptr += rx_lengths[i];
708 709
  }

gauthier's avatar
gauthier committed
710
  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SEND_MCH_SDU, VCD_FUNCTION_OUT);
Gabriel's avatar
Gabriel committed
711
#if UE_TIMING_TRACE
712
  stop_meas(&UE_mac_inst[module_idP].rx_mch_sdu);
Gabriel's avatar
Gabriel committed
713
#endif
714 715
}

716 717
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
718
  // currently there is one-to-one mapping between sf allocation pattern and sync area
719 720
  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 );
721
    return -1;
722
  } else if (UE_mac_inst[module_idP].mbsfn_SubframeConfig[mbsfn_sync_area] != NULL) {
723
    return mbsfn_sync_area;
724
  } else {
725
    LOG_W( MAC, "[UE %"PRIu8"] MBSFN Subframe Config pattern %"PRIu8" not found \n", module_idP, mbsfn_sync_area );
726
    return -1;
727 728
  }
}
729

730 731
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)
{
732

winckel's avatar
winckel committed
733
  int i=0, j=0, ii=0, msi_pos=0, mcch_mcs = - 1;
734
  int mcch_flag=0, mtch_flag=0, msi_flag=0;
gauthier's avatar
gauthier committed
735 736
  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
737
  int mch_scheduling_period = -1;
738

739
  int frame_FDD=1;
740

741

Gabriel's avatar
Gabriel committed
742
#if UE_TIMING_TRACE
743
  start_meas(&UE_mac_inst[module_idP].ue_query_mch);
Gabriel's avatar
Gabriel committed
744
#endif
745

746
  if (UE_mac_inst[module_idP].pmch_Config[0]) {
gauthier's avatar
gauthier committed
747
    mch_scheduling_period = 8<<(UE_mac_inst[module_idP].pmch_Config[0]->mch_SchedulingPeriod_r9);
748
  }
749

750
  for (i=0;
751 752 753
       i< UE_mac_inst[module_idP].num_active_mbsfn_area;
       i++ ) {
    // assume, that there is always a mapping
754
    if ((j=ue_get_mbsfn_sf_alloction(module_idP,i,eNB_index)) == -1) {
755
      return -1; // continue;
756
    }
757 758 759 760 761 762

    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);

763
    LOG_D(MAC,
Cedric Roux's avatar
Cedric Roux committed
764
          "[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",
765
          module_idP,frameP, subframe,i,UE_mac_inst[module_idP].num_active_mbsfn_area,
gauthier's avatar
gauthier committed
766 767 768
          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);

769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800
    // 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++;
            }
          }
        }

801 802
	if (UE_mac_inst[module_idP].tdd_Config == NULL) frame_FDD=1;
	else frame_FDD=0;
803 804 805
        // Check if the subframe is for MSI, MCCH or MTCHs and Set the correspoding flag to 1
        switch (subframe) {
        case 1:
806
          if (frame_FDD==1) {
807
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) {
808
              if (msi_pos == 1) {
809
                msi_flag = 1;
810
              }
811

812
	      if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
813
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF1) == MBSFN_FDD_SF1) ) {
814
                mcch_flag = 1;
815
              }
816 817 818 819 820 821 822 823

              mtch_flag = 1;
            }
          }

          break;

        case 2:
824
          if (frame_FDD==1) {
825
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) {
826
              if (msi_pos == 2) {
827
                msi_flag = 1;
828
              }
829 830

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
831
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF2) == MBSFN_FDD_SF2) ) {
832
                mcch_flag = 1;
833
              }
834 835 836 837

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

839 840 841
          break;

        case 3:
842
          if (frame_FDD==0) { //TDD
843
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) {
844
              if (msi_pos == 1) {
845
                msi_flag = 1;
846
              }
847 848

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
849
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF3) == MBSFN_TDD_SF3) ) {
850
                mcch_flag = 1;
851
              }
852 853 854 855 856

              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) {
857
              if (msi_pos == 3) {
858
                msi_flag = 1;
859
              }
860 861

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
862
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF3) == MBSFN_FDD_SF3) ) {
863
                mcch_flag = 1;
864
              }
865 866 867 868 869 870 871 872

              mtch_flag = 1;
            }
          }

          break;

        case 4:
873
          if (frame_FDD==0) {
874
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF4) == MBSFN_TDD_SF4) {
875
              if (msi_pos == 2) {
876
                msi_flag = 1;
877
              }
878 879

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

              mtch_flag = 1;
            }
          }

          break;

        case 6:
891
          if (frame_FDD==1) {
892
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) {
893
              if (msi_pos == 4) {
894
                msi_flag = 1;
895
              }
896 897

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
898
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF6) == MBSFN_FDD_SF6) ) {
899
                mcch_flag = 1;
900
              }
901 902 903

              mtch_flag = 1;
            }
gauthier's avatar
gauthier committed
904
          }
905 906 907 908

          break;

        case 7:
909
          if (frame_FDD==0) { // TDD
910
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF7) == MBSFN_TDD_SF7) {
911
              if (msi_pos == 3) {
912
                msi_flag = 1;
913
              }
914 915

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

              mtch_flag = 1;
            }
          } else { // FDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) {
924
              if (msi_pos == 5) {
925
                msi_flag = 1;
926
              }
927 928

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
929
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF7) == MBSFN_FDD_SF7) ) {
930
                mcch_flag = 1;
931
              }
932 933 934

              mtch_flag = 1;
            }
gauthier's avatar
gauthier committed
935
          }
936 937 938 939

          break;

        case 8:
940
          if (frame_FDD==0) { //TDD
941
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) {
942
              if (msi_pos == 4) {
943
                msi_flag = 1;
944
              }
945 946

              if ( (frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
947
                   ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF8) == MBSFN_TDD_SF8) ) {
948
                mcch_flag = 1;
949
              }
950 951 952 953 954

              mtch_flag = 1;
            }
          } else { // FDD
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) {
955
              if (msi_pos == 6) {
956
                msi_flag = 1;
957
              }
958 959

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
960
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_FDD_SF8) == MBSFN_FDD_SF8) ) {
961
                mcch_flag = 1;
962
              }
963 964 965 966 967 968 969 970

              mtch_flag = 1;
            }
          }

          break;

        case 9:
971
          if (frame_FDD==0) {
972
            if ((UE_mac_inst[module_idP].mbsfn_SubframeConfig[j]->subframeAllocation.choice.oneFrame.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) {
973
              if (msi_pos == 5) {
974
                msi_flag = 1;
975
              }
976 977

              if ((frameP % mcch_period == UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.mcch_Offset_r9) &&
978
                  ((UE_mac_inst[module_idP].mbsfn_AreaInfo[i]->mcch_Config_r9.sf_AllocInfo_r9.buf[0] & MBSFN_TDD_SF9) == MBSFN_TDD_SF9) ) {
979
                mcch_flag = 1;
980
              }