eNB_scheduler_primitives.c 55.1 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * 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
 */

nikaeinn's avatar
nikaeinn committed
22
23
/*! \file eNB_scheduler_primitives.c
 * \brief primitives used by eNB for BCH, RACH, ULSCH, DLSCH scheduling
24
25
26
 * \author  Navid Nikaein and Raymond Knopp
 * \date 2010 - 2014
 * \email: navid.nikaein@eurecom.fr
nikaeinn's avatar
nikaeinn committed
27
 * \version 1.0
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
 * @ingroup _mac

 */

#include "assertions.h"
#include "PHY/defs.h"
#include "PHY/extern.h"

#include "SCHED/defs.h"
#include "SCHED/extern.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/extern.h"

#include "LAYER2/MAC/proto.h"
#include "UTIL/LOG/log.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

#include "RRC/LITE/extern.h"
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

//#include "LAYER2/MAC/pre_processor.c"
#include "pdcp.h"

#if defined(ENABLE_ITTI)
# include "intertask_interface.h"
#endif

#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1

knopp's avatar
knopp committed
62
63
int to_prb(int dl_Bandwidth) {
  int prbmap[6] = {6,15,25,50,75,100};
64

knopp's avatar
knopp committed
65
66
67
68
69
70
71
72
73
74
  AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n");
  return(prbmap[dl_Bandwidth]);
}

int to_rbg(int dl_Bandwidth) {
  int rbgmap[6] = {6,8,13,17,19,25};

  AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n");
  return(rbgmap[dl_Bandwidth]);
}
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99


int get_phich_resource_times6(COMMON_channels_t *cc) {
  int phichmap[4] = {1,3,6,12};
  AssertFatal(cc!=NULL,"cc is null\n");
  AssertFatal(cc->mib!=NULL,"cc->mib is null\n");
  AssertFatal((cc->mib->message.phich_Config.phich_Resource>=0) && 
	      (cc->mib->message.phich_Config.phich_Resource<4),
	      "phich_Resource %d not in 0..3\n",(int)cc->mib->message.phich_Config.phich_Resource);

  return(phichmap[cc->mib->message.phich_Config.phich_Resource]);
}

uint16_t mac_computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs) {

  uint16_t RIV;

  if (Lcrbs<=(1+(N_RB_DL>>1)))
    RIV = (N_RB_DL*(Lcrbs-1)) + RBstart;
  else
    RIV = (N_RB_DL*(N_RB_DL+1-Lcrbs)) + (N_RB_DL-1-RBstart);

  return(RIV);
}

100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
void get_Msg3alloc(COMMON_channels_t *cc,
		   unsigned char current_subframe,
		   unsigned int current_frame,
		   unsigned int *frame,
		   unsigned char *subframe)
{

  // Fill in other TDD Configuration!!!!

  if (cc->tdd_Config==NULL) { // FDD
    *subframe = current_subframe+6;

    if (*subframe>9) {
      *subframe = *subframe-10;
      *frame = (current_frame+1) & 1023;
    } else {
      *frame=current_frame;
    }
  } else { // TDD
    if (cc->tdd_Config->subframeAssignment == 1) {
      switch (current_subframe) {

      case 0:
        *subframe = 7;
        *frame = current_frame;
        break;

      case 4:
        *subframe = 2;
        *frame = (current_frame+1) & 1023;
        break;

      case 5:
        *subframe = 2;
        *frame = (current_frame+1) & 1023;
        break;

      case 9:
        *subframe = 7;
        *frame = (current_frame+1) & 1023;
        break;
      }
    } else if (cc->tdd_Config->subframeAssignment == 3) {
      switch (current_subframe) {

      case 0:
      case 5:
      case 6:
        *subframe = 2;
        *frame = (current_frame+1) & 1023;
        break;

      case 7:
        *subframe = 3;
        *frame = (current_frame+1) & 1023;
        break;

      case 8:
        *subframe = 4;
        *frame = (current_frame+1) & 1023;
        break;

      case 9:
        *subframe = 2;
        *frame = (current_frame+2) & 1023;
        break;
      }
    } else if (cc->tdd_Config->subframeAssignment == 4) {
        switch (current_subframe) {

        case 0:
        case 4:
        case 5:
        case 6:
          *subframe = 2;
          *frame = (current_frame+1) & 1023;
          break;

        case 7:
          *subframe = 3;
          *frame = (current_frame+1) & 1023;
          break;

        case 8:
        case 9:
          *subframe = 2;
          *frame = (current_frame+2) & 1023;
          break;
        }
      } else if (cc->tdd_Config->subframeAssignment == 5) {
          switch (current_subframe) {

          case 0:
          case 4:
          case 5:
          case 6:
            *subframe = 2;
            *frame = (current_frame+1) & 1023;
            break;

          case 7:
          case 8:
          case 9:
            *subframe = 2;
            *frame = (current_frame+2) & 1023;
            break;
          }
        }
  }
}

211
212


213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
void get_Msg3allocret(COMMON_channels_t *cc,
		      unsigned char current_subframe,
		      unsigned int current_frame,
		      unsigned int *frame,
		      unsigned char *subframe)
{
  if (cc->tdd_Config == NULL) { //FDD
    /* always retransmit in n+8 */
    *subframe = current_subframe + 8;

    if (*subframe > 9) {
      *subframe = *subframe - 10;
      *frame = (current_frame + 1) & 1023;
    } else {
      *frame = current_frame;
    }
  } else {
    if (cc->tdd_Config->subframeAssignment == 1) {
      // original PUSCH in 2, PHICH in 6 (S), ret in 2
      // original PUSCH in 3, PHICH in 9, ret in 3
      // original PUSCH in 7, PHICH in 1 (S), ret in 7
      // original PUSCH in 8, PHICH in 4, ret in 8
      *frame = (current_frame+1) & 1023;
    } else if (cc->tdd_Config->subframeAssignment == 3) {
      // original PUSCH in 2, PHICH in 8, ret in 2 next frame
      // original PUSCH in 3, PHICH in 9, ret in 3 next frame
      // original PUSCH in 4, PHICH in 0, ret in 4 next frame
      *frame=(current_frame+1) & 1023;
    } else if (cc->tdd_Config->subframeAssignment == 4) {
        // original PUSCH in 2, PHICH in 8, ret in 2 next frame
        // original PUSCH in 3, PHICH in 9, ret in 3 next frame
        *frame=(current_frame+1) & 1023;
    } else if (cc->tdd_Config->subframeAssignment == 5) {
        // original PUSCH in 2, PHICH in 8, ret in 2 next frame
        *frame=(current_frame+1) & 1023;
    }
  }
}

uint8_t subframe2harqpid(COMMON_channels_t *cc,uint32_t frame,uint8_t subframe)
{
  uint8_t ret = 255;

  AssertFatal(cc!=NULL,"cc is null\n");

  if (cc->tdd_Config == NULL) { // FDD
    ret = (((frame<<1)+subframe)&7);
  } else {

    switch (cc->tdd_Config->subframeAssignment) {

    case 1:
      if ((subframe==2) ||
          (subframe==3) ||
          (subframe==7) ||
          (subframe==8))
        switch (subframe) {
        case 2:
        case 3:
          ret = (subframe-2);
          break;

        case 7:
        case 8:
          ret = (subframe-5);
          break;

        default:
	  AssertFatal(1==0,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
          break;
        }

      break;

    case 2:
      AssertFatal((subframe==2) || (subframe==7),
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
       
      ret = (subframe/7);
      break;

    case 3:
      AssertFatal((subframe>1) && (subframe<5), 
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
      ret = (subframe-2);
      break;

    case 4:
      AssertFatal((subframe>1) && (subframe<4),
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
      ret = (subframe-2);
      break;

    case 5:
      AssertFatal(subframe==2,
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
      ret = (subframe-2);
      break;

    default:
      AssertFatal(1==0,"subframe2_harq_pid, Unsupported TDD mode %d\n",(int)cc->tdd_Config->subframeAssignment);
    }
  }
  return ret;
}

uint8_t get_Msg3harqpid(COMMON_channels_t *cc,
			uint32_t frame,
			unsigned char current_subframe)
{

  uint8_t ul_subframe=0;
  uint32_t ul_frame=0;

  if (cc->tdd_Config == NULL) { // FDD
    ul_subframe = (current_subframe>3) ? (current_subframe-4) : (current_subframe+6);
    ul_frame    = (current_subframe>3) ? ((frame+1)&1023) : frame;
  } else {
    switch (cc->tdd_Config->subframeAssignment) {
    case 1:
      switch (current_subframe) {

      case 9:
      case 0:
        ul_subframe = 7;
        break;

      case 5:
      case 7:
        ul_subframe = 2;
        break;

      }

      break;

    case 3:
      switch (current_subframe) {

      case 0:
      case 5:
      case 6:
        ul_subframe = 2;
        break;

      case 7:
        ul_subframe = 3;
        break;

      case 8:
        ul_subframe = 4;
        break;

      case 9:
        ul_subframe = 2;
        break;
      }

      break;

    case 4:
      switch (current_subframe) {

      case 0:
      case 5:
      case 6:
      case 8:
      case 9:
        ul_subframe = 2;
        break;

      case 7:
        ul_subframe = 3;
        break;
      }

      break;

    case 5:
      ul_subframe =2;
      break;

    default:
      LOG_E(PHY,"get_Msg3_harq_pid: Unsupported TDD configuration %d\n",(int)cc->tdd_Config->subframeAssignment);
      AssertFatal(1==0,"get_Msg3_harq_pid: Unsupported TDD configuration");
      break;
    }
  }

  return(subframe2harqpid(cc,ul_frame,ul_subframe));

}

406
int is_UL_sf(COMMON_channels_t *ccP,uint8_t subframeP)
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
{

  // if FDD return dummy value
  if (ccP->tdd_Config == NULL)
    return(0);

  switch (ccP->tdd_Config->subframeAssignment) {

  case 1:
    switch (subframeP) {
    case 0:
    case 4:
    case 5:
    case 9:
      return(0);
      break;

    case 2:
    case 3:
    case 7:
    case 8:
      return(1);
      break;

    default:
      return(0);
      break;
    }
    break;

  case 3:
    if  ((subframeP<=1) || (subframeP>=5))
      return(0);
    else if ((subframeP>1) && (subframeP < 5))
      return(1);
    else AssertFatal(1==0,"Unknown subframe number\n");
    break;

  case 4:
    if  ((subframeP<=1) || (subframeP>=4))
      return(0);
    else if ((subframeP>1) && (subframeP < 4))
      return(1);
    else AssertFatal(1==0,"Unknown subframe number\n");
    break;
    
  case 5:
    if  ((subframeP<=1) || (subframeP>=3))
      return(0);
    else if ((subframeP>1) && (subframeP < 3))
      return(1);
    else AssertFatal(1==0,"Unknown subframe number\n");
    break;

  default:
    AssertFatal(1==0,"subframe %d Unsupported TDD configuration %d\n",
		subframeP,ccP->tdd_Config->subframeAssignment);
    break;

  }
}

469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
#ifdef Rel14

int get_numnarrowbands(long dl_Bandwidth) {
  int nb_tab[6] = {1,2,4,8,12,16};

  AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n");
  return(nb_tab[dl_Bandwidth]);
}

int get_numnarrowbandbits(long dl_Bandwidth) {
  int nbbits_tab[6] = {0,1,2,3,4,4};

  AssertFatal(dl_Bandwidth<7 || dl_Bandwidth>=0,"dl_Bandwidth not in [0..6]\n");
  return(nbbits_tab[dl_Bandwidth]);
}

//This implements the frame/subframe condition for first subframe of MPDCCH transmission (Section 9.1.5 36.213, Rel 13/14)
int startSF_fdd_RA_times2[8] = {2,3,4,5,8,10,16,20};
int startSF_tdd_RA[7]        = {1,2,4,5,8,10,20};

int mpdcch_sf_condition(eNB_MAC_INST *eNB,int CC_id, frame_t frameP,sub_frame_t subframeP,int rmax,MPDCCH_TYPES_t mpdcch_type) {

  struct PRACH_ConfigSIB_v1310 *ext4_prach = eNB->common_channels[CC_id].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310;
  int T;

  switch (mpdcch_type) {
  case TYPE0:
    AssertFatal(1==0,"MPDCCH Type 0 not handled yet\n");
    break;
  case TYPE1:
    AssertFatal(1==0,"MPDCCH Type 1 not handled yet\n");
    break;
  case TYPE1A:
    AssertFatal(1==0,"MPDCCH Type 1A not handled yet\n");
    break;
  case TYPE2: // RAR
    AssertFatal(ext4_prach->mpdcch_startSF_CSS_RA_r13!=NULL,
		"mpdcch_startSF_CSS_RA_r13 is null\n");
    if (eNB->common_channels[CC_id].tdd_Config==NULL) //FDD
      T = rmax*startSF_fdd_RA_times2[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.fdd_r13]>>1;
    else //TDD
      T = rmax*startSF_tdd_RA[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.tdd_r13];
    break;
  case TYPE2A:
    AssertFatal(1==0,"MPDCCH Type 2A not handled yet\n");
    break;
  case TYPEUESPEC:
    AssertFatal(1==0,"MPDCCH Type UESPEC not handled yet\n");
    break;
  default:
    return(0);
  }

  if (((10*frameP) + subframeP)%T == 0) return(1);
  else return(0);

}


#endif

530
//------------------------------------------------------------------------------
531
void init_ue_sched_info(void)
532
//------------------------------------------------------------------------------
533
{
534
  module_id_t i,j,k;
535
536

  for (i=0; i<NUMBER_OF_eNB_MAX; i++) {
Cedric Roux's avatar
Cedric Roux committed
537
    for (k=0; k<MAX_NUM_CCs; k++) {
538
539
540
541
542
543
544
545
546
547
      for (j=0; j<NUMBER_OF_UE_MAX; j++) {
        // init DL
        eNB_dlsch_info[i][k][j].weight           = 0;
        eNB_dlsch_info[i][k][j].subframe         = 0;
        eNB_dlsch_info[i][k][j].serving_num      = 0;
        eNB_dlsch_info[i][k][j].status           = S_DL_NONE;
        // init UL
        eNB_ulsch_info[i][k][j].subframe         = 0;
        eNB_ulsch_info[i][k][j].serving_num      = 0;
        eNB_ulsch_info[i][k][j].status           = S_UL_NONE;
548
      }
549
    }
550
551
552
553
554
  }
}



555
//------------------------------------------------------------------------------
556
unsigned char get_ue_weight(module_id_t module_idP, int CC_idP, int ue_idP)
557
//------------------------------------------------------------------------------
558
{
559

560
  return(eNB_dlsch_info[module_idP][CC_idP][ue_idP].weight);
561
562
563

}

564
//------------------------------------------------------------------------------
565
int find_UE_id(module_id_t mod_idP, rnti_t rntiP)
566
//------------------------------------------------------------------------------
567
{
knopp's avatar
   
knopp committed
568
  int UE_id;
569
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
570

571
572
  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
    if (UE_list->active[UE_id] != TRUE) continue;
knopp's avatar
   
knopp committed
573
574
575
    if (UE_list->UE_template[UE_PCCID(mod_idP,UE_id)][UE_id].rnti==rntiP) {
      return(UE_id);
    }
576
  }
577

knopp's avatar
   
knopp committed
578
  return(-1);
579
580
}

581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
//------------------------------------------------------------------------------
int find_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP)
//------------------------------------------------------------------------------
{
  int RA_id;
  AssertFatal(RC.mac[mod_idP],"RC.mac[%d] is null\n",mod_idP);
  
  RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[mod_idP]->common_channels[CC_idP].RA_template[0];

 

  for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++)
    if (RA_template[RA_id].RA_active==TRUE && 
        RA_template[RA_id].wait_ack_Msg4 == 0 &&
	RA_template[RA_id].rnti == rntiP) return(RA_id);
  return(-1);
}

599
//------------------------------------------------------------------------------
600
int UE_num_active_CC(UE_list_t *listP,int ue_idP)
601
//------------------------------------------------------------------------------
602
{
knopp's avatar
   
knopp committed
603
604
  return(listP->numactiveCCs[ue_idP]);
}
605

606
//------------------------------------------------------------------------------
607
int UE_PCCID(module_id_t mod_idP,int ue_idP)
608
//------------------------------------------------------------------------------
609
{
610
  return(RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]);
knopp's avatar
   
knopp committed
611
}
612

613
//------------------------------------------------------------------------------
614
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
615
//------------------------------------------------------------------------------
616
{
617

618
  rnti_t rnti = RC.mac[mod_idP]->UE_list.UE_template[UE_PCCID(mod_idP,ue_idP)][ue_idP].rnti;
619

620
  if (rnti>0) {
knopp's avatar
   
knopp committed
621
    return (rnti);
622
  }
623

624
  LOG_D(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
625
626
  //display_backtrace();
  return(NOT_A_RNTI);
627
}
knopp's avatar
   
knopp committed
628

629
//------------------------------------------------------------------------------
630
boolean_t is_UE_active(module_id_t mod_idP, int ue_idP)
631
//------------------------------------------------------------------------------
632
{
633
  return(RC.mac[mod_idP]->UE_list.active[ue_idP]);
634
}
knopp's avatar
   
knopp committed
635
636
637

/*
uint8_t find_active_UEs(module_id_t module_idP,int CC_id){
638
639
640
641
642
643
644

  module_id_t        ue_mod_id      = 0;
  rnti_t        rnti         = 0;
  uint8_t            nb_active_ue = 0;

  for (ue_mod_id=0;ue_mod_id<NUMBER_OF_UE_MAX;ue_mod_id++) {

knopp's avatar
   
knopp committed
645
      if (((rnti=eNB_mac_inst[module_idP][CC_id].UE_template[ue_mod_id].rnti) !=0)&&(eNB_mac_inst[module_idP][CC_id].UE_template[ue_mod_id].ul_active==TRUE)){
646
647

          if (mac_xface->get_eNB_UE_stats(module_idP,rnti) != NULL){ // check at the phy enb_ue state for this rnti
648
      nb_active_ue++;
649
650
          }
          else { // this ue is removed at the phy => remove it at the mac as well
651
      mac_remove_ue(module_idP, CC_id, ue_mod_id);
652
653
654
655
656
          }
      }
  }
  return(nb_active_ue);
}
knopp's avatar
   
knopp committed
657
*/
658
659


660
661
// get aggregation (L) form phy for a give UE
unsigned char get_aggregation (uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt)
662
{
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
  unsigned char aggregation=3;
  
  switch (dci_fmt){
    
  case format0:
    aggregation = cqi2fmt0_agg[bw_index][cqi];
    break;
  case format1:
  case format1A:
  case format1B:
  case format1D:
    aggregation = cqi2fmt1x_agg[bw_index][cqi]; 
    break;
  case format2:
  case format2A:
  case format2B:
  case format2C:
  case format2D:
    aggregation = cqi2fmt2x_agg[bw_index][cqi]; 
    break;
  case format1C:
  case format1E_2A_M10PRB:
  case format3:
  case format3A:
  case format4:
  default:
    LOG_W(MAC,"unsupported DCI format %d\n",dci_fmt);
  }

   LOG_D(MAC,"Aggregation level %d (cqi %d, bw_index %d, format %d)\n", 
   	1<<aggregation, cqi,bw_index,dci_fmt);
   
695
  return 1<<aggregation;
696
}
knopp's avatar
   
knopp committed
697

698
699
void dump_ue_list(UE_list_t *listP, int ul_flag)
{
knopp's avatar
   
knopp committed
700
  int j;
701
702
703

  if ( ul_flag == 0 ) {
    for (j=listP->head; j>=0; j=listP->next[j]) {
704
705
706
      LOG_T(MAC,"node %d => %d\n",j,listP->next[j]);
    }
  } else {
707
    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
708
709
      LOG_T(MAC,"node %d => %d\n",j,listP->next_ul[j]);
    }
knopp's avatar
   
knopp committed
710
711
712
  }
}

713
714
int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP)
{
knopp's avatar
   
knopp committed
715
  int UE_id;
716
  int i, j;
717

718
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
719

knopp's avatar
   
knopp committed
720
  LOG_D(MAC,"[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n",mod_idP,cc_idP,rntiP,UE_list->avail,UE_list->num_UEs);
721
  dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
722

723
724
725
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] == TRUE) continue;
    UE_id = i;
knopp's avatar
   
knopp committed
726
727
728
729
730
731
732
    UE_list->UE_template[cc_idP][UE_id].rnti       = rntiP;
    UE_list->UE_template[cc_idP][UE_id].configured = FALSE;
    UE_list->numactiveCCs[UE_id]                   = 1;
    UE_list->numactiveULCCs[UE_id]                 = 1;
    UE_list->pCC_id[UE_id]                         = cc_idP;
    UE_list->ordered_CCids[0][UE_id]               = cc_idP;
    UE_list->ordered_ULCCids[0][UE_id]             = cc_idP;
knopp's avatar
   
knopp committed
733
    UE_list->num_UEs++;
knopp's avatar
   
knopp committed
734
    UE_list->active[UE_id]                         = TRUE;
735
    memset((void*)&UE_list->UE_sched_ctrl[UE_id],0,sizeof(UE_sched_ctrl));
736
    memset((void*)&UE_list->eNB_UE_stats[cc_idP][UE_id],0,sizeof(eNB_UE_STATS));
knopp's avatar
   
knopp committed
737

738
739
    for (j=0; j<8; j++) {
      UE_list->UE_template[cc_idP][UE_id].oldNDI[j]    = (j==0)?1:0;   // 1 because first transmission is with format1A (Msg4) for harq_pid 0
knopp's avatar
   
knopp committed
740
      UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = (j==harq_pidP)?0:1; // 1st transmission is with Msg3;
knopp's avatar
   
knopp committed
741
    }
742

743
    eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING;
744
    eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING;
knopp's avatar
   
knopp committed
745
    LOG_D(MAC,"[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",mod_idP,UE_id,cc_idP,rntiP);
746
    dump_ue_list(UE_list,0);
knopp's avatar
   
knopp committed
747
    return(UE_id);
748
  }
knopp's avatar
   
knopp committed
749

750
  printf("MAC: cannot add new UE for rnti %x\n", rntiP);
knopp's avatar
   
knopp committed
751
  LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
752
  dump_ue_list(UE_list,0);
753
754
755
  return(-1);
}

756
//------------------------------------------------------------------------------
757
int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP) 
758
//------------------------------------------------------------------------------
759
{
760
  int i;
761
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
762
  int UE_id = find_UE_id(mod_idP,rntiP);
763
  int pCC_id;
764

765
  if (UE_id == -1) {
766
printf("MAC: cannot remove UE rnti %x\n", rntiP);
767
    LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP);
768
    mac_phy_remove_ue(mod_idP, rntiP);
769
770
771
    return 0;
  }

772
773
  pCC_id = UE_PCCID(mod_idP,UE_id);

774
  LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",UE_id,pCC_id, rntiP);
775
  dump_ue_list(UE_list,0);
776

777
778
779
  UE_list->active[UE_id] = FALSE;
  UE_list->num_UEs--;

780
  // clear all remaining pending transmissions
781
782
783
784
785
786
787
788
789
790
791
792
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3]  = 0;

  UE_list->UE_template[pCC_id][UE_id].ul_SR             = 0;
  UE_list->UE_template[pCC_id][UE_id].rnti              = NOT_A_RNTI;
  UE_list->UE_template[pCC_id][UE_id].ul_active         = FALSE;
  eNB_ulsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
  eNB_ulsch_info[mod_idP][pCC_id][UE_id].status                      = S_UL_NONE;
  eNB_dlsch_info[mod_idP][pCC_id][UE_id].rnti                        = NOT_A_RNTI;
  eNB_dlsch_info[mod_idP][pCC_id][UE_id].status                      = S_DL_NONE;
knopp's avatar
   
knopp committed
793

794
795
  mac_phy_remove_ue(mod_idP,rntiP);

796
797
798
  // check if this has an RA process active
  RA_TEMPLATE *RA_template;
  for (i=0;i<NB_RA_PROC_MAX;i++) {
799
    RA_template = (RA_TEMPLATE *)&RC.mac[mod_idP]->common_channels[pCC_id].RA_template[i];
800
    if (RA_template->rnti == rntiP){
801
802
803
804
805
806
807
      RA_template->RA_active=FALSE;
      RA_template->generate_rar=0;
      RA_template->generate_Msg4=0;
      RA_template->wait_ack_Msg4=0;
      RA_template->timing_offset=0;
      RA_template->RRC_timer=20;
      RA_template->rnti = 0;
808
      //break;
809
810
    }
  }
knopp's avatar
   
knopp committed
811

812
  return 0;
813
814
815
}


knopp's avatar
   
knopp committed
816

817
818
int prev(UE_list_t *listP, int nodeP, int ul_flag)
{
knopp's avatar
   
knopp committed
819
  int j;
820

821
  if (ul_flag == 0 ) {
822
    if (nodeP==listP->head) {
823
      return(nodeP);
824
    }
825
826

    for (j=listP->head; j>=0; j=listP->next[j]) {
827
      if (listP->next[j]==nodeP) {
828
        return(j);
829
    }
830
    }
831
  } else {
832
    if (nodeP==listP->head_ul) {
833
      return(nodeP);
834
    }
835
836

    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
837
      if (listP->next_ul[j]==nodeP) {
838
        return(j);
839
      }
840
    }
knopp's avatar
   
knopp committed
841
  }
knopp's avatar
   
knopp committed
842

843
  LOG_E(MAC,"error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n",
844
        nodeP, (ul_flag == 0)? "DL" : "UL");
845
  dump_ue_list(listP, ul_flag);
knopp's avatar
   
knopp committed
846
847


knopp's avatar
   
knopp committed
848
849
  return(-1);
}
850

851
852
void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag)
{
853

knopp's avatar
   
knopp committed
854
855
  int prev_i,prev_j,next_i,next_j;

856
857
  LOG_T(MAC,"Swapping UE %d,%d\n",nodeiP,nodejP);
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
858

859
860
  prev_i = prev(listP,nodeiP,ul_flag);
  prev_j = prev(listP,nodejP,ul_flag);
861

862
863
  AssertFatal((prev_i>=0) && (prev_j>=0),
	      "swap_UEs: problem");
knopp's avatar
   
knopp committed
864

865
  if (ul_flag == 0) {
866
867
868
869
870
    next_i = listP->next[nodeiP];
    next_j = listP->next[nodejP];
  } else {
    next_i = listP->next_ul[nodeiP];
    next_j = listP->next_ul[nodejP];
knopp's avatar
   
knopp committed
871
  }
knopp's avatar
   
knopp committed
872

873
  LOG_T(MAC,"[%s] next_i %d, next_i, next_j %d, head %d \n",
874
875
        (ul_flag == 0)? "DL" : "UL",
        next_i,next_j,listP->head);
876
877

  if (ul_flag == 0 ) {
knopp's avatar
   
knopp committed
878

879
880
    if (next_i == nodejP) {   // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...
      LOG_T(MAC,"Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n");
881

882
883
      listP->next[nodeiP] = next_j;
      listP->next[nodejP] = nodeiP;
884

885
      if (nodeiP==listP->head) { // case i j n(j)
886
        listP->head = nodejP;
887
      } else {
888
        listP->next[prev_i] = nodejP;
889
      }
890
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
891
892
893
      LOG_T(MAC,"Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n");
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = nodejP;
894

895
      if (nodejP==listP->head) { // case j i n(i)
896
        listP->head = nodeiP;
897
      } else {
898
        listP->next[prev_j] = nodeiP;
899
      }
900
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...
901
902
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = next_j;
903
904


905
      if (nodeiP==listP->head) {
906
907
908
909
910
911
912
913
914
915
        LOG_T(MAC,"changing head to %d\n",nodejP);
        listP->head=nodejP;
        listP->next[prev_j] = nodeiP;
      } else if (nodejP==listP->head) {
        LOG_D(MAC,"changing head to %d\n",nodeiP);
        listP->head=nodeiP;
        listP->next[prev_i] = nodejP;
      } else {
        listP->next[prev_i] = nodejP;
        listP->next[prev_j] = nodeiP;
916
917
918
919
920
921
      }
    }
  } else { // ul_flag

    if (next_i == nodejP) {   // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...
      LOG_T(MAC,"[UL] Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n");
922

923
924
      listP->next_ul[nodeiP] = next_j;
      listP->next_ul[nodejP] = nodeiP;
925

926
      if (nodeiP==listP->head_ul) { // case i j n(j)
927
        listP->head_ul = nodejP;
928
      } else {
929
        listP->next_ul[prev_i] = nodejP;
930
      }
931
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
932
933
934
      LOG_T(MAC,"[UL]Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n");
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = nodejP;
935

936
      if (nodejP==listP->head_ul) { // case j i n(i)
937
        listP->head_ul = nodeiP;
938
      } else {
939
        listP->next_ul[prev_j] = nodeiP;
940
      }
941
942
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...

943
944
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = next_j;
945
946


947
      if (nodeiP==listP->head_ul) {
948
949
950
951
952
953
954
955
956
957
        LOG_T(MAC,"[UL]changing head to %d\n",nodejP);
        listP->head_ul=nodejP;
        listP->next_ul[prev_j] = nodeiP;
      } else if (nodejP==listP->head_ul) {
        LOG_T(MAC,"[UL]changing head to %d\n",nodeiP);
        listP->head_ul=nodeiP;
        listP->next_ul[prev_i] = nodejP;
      } else {
        listP->next_ul[prev_i] = nodejP;
        listP->next_ul[prev_j] = nodeiP;
958
      }
knopp's avatar
   
knopp committed
959
960
    }
  }
961

962
963
  LOG_T(MAC,"After swap\n");
  dump_ue_list(listP,ul_flag);
knopp's avatar
   
knopp committed
964
965
966
967
}



968

969
970
971
972
973




/*
Cedric Roux's avatar
Cedric Roux committed
974
  #if defined(Rel10) || defined(Rel14)
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
1001
1002
1003
1004
1005
1006
1007
1008
1009
1010
1011
1012
1013
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026
1027
1028
1029
1030
1031
1032
1033
1034
1035
1036
1037
1038
1039
1040
1041
1042
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068
1069
1070
1071
1072
1073
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085
1086
1087
1088
  unsigned char generate_mch_header( unsigned char *mac_header,
  unsigned char num_sdus,
  unsigned short *sdu_lengths,
  unsigned char *sdu_lcids,
  unsigned char msi,
  unsigned char short_padding,
  unsigned short post_padding) {

  SCH_SUBHEADER_FIXED *mac_header_ptr = (SCH_SUBHEADER_FIXED *)mac_header;
  uint8_t first_element=0,last_size=0,i;
  uint8_t mac_header_control_elements[2*num_sdus],*ce_ptr;

  ce_ptr = &mac_header_control_elements[0];

  if ((short_padding == 1) || (short_padding == 2)) {
  mac_header_ptr->R    = 0;
  mac_header_ptr->E    = 0;
  mac_header_ptr->LCID = SHORT_PADDING;
  first_element=1;
  last_size=1;
  }
  if (short_padding == 2) {
  mac_header_ptr->E = 1;
  mac_header_ptr++;
  mac_header_ptr->R = 0;
  mac_header_ptr->E    = 0;
  mac_header_ptr->LCID = SHORT_PADDING;
  last_size=1;
  }

  // SUBHEADER for MSI CE
  if (msi != 0) {// there is MSI MAC Control Element
  if (first_element>0) {
  mac_header_ptr->E = 1;
  mac_header_ptr+=last_size;
  }
  else {
  first_element = 1;
  }
  if (num_sdus*2 < 128) {
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R    = 0;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E    = 0;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F    = 0;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = MCH_SCHDL_INFO;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L    = num_sdus*2;
  last_size=2;
  }
  else {
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R    = 0;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E    = 0;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F    = 1;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = MCH_SCHDL_INFO;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L    = (num_sdus*2)&0x7fff;
  last_size=3;
  }
  // Create the MSI MAC Control Element here
  }

  // SUBHEADER for MAC SDU (MCCH+MTCHs)
  for (i=0;i<num_sdus;i++) {
  if (first_element>0) {
  mac_header_ptr->E = 1;
  mac_header_ptr+=last_size;
  }
  else {
  first_element = 1;
  }
  if (sdu_lengths[i] < 128) {
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->R    = 0;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->E    = 0;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->F    = 0;
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->LCID = sdu_lcids[i];
  ((SCH_SUBHEADER_SHORT *)mac_header_ptr)->L    = (unsigned char)sdu_lengths[i];
  last_size=2;
  }
  else {
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->R    = 0;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->E    = 0;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->F    = 1;
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->LCID = sdu_lcids[i];
  ((SCH_SUBHEADER_LONG *)mac_header_ptr)->L    = (unsigned short) sdu_lengths[i]&0x7fff;
  last_size=3;
  }
  }

  if (post_padding>0) {// we have lots of padding at the end of the packet
  mac_header_ptr->E = 1;
  mac_header_ptr+=last_size;
  // add a padding element
  mac_header_ptr->R    = 0;
  mac_header_ptr->E    = 0;
  mac_header_ptr->LCID = SHORT_PADDING;
  mac_header_ptr++;
  }
  else { // no end of packet padding
  // last SDU subhead is of fixed type (sdu length implicitly to be computed at UE)
  mac_header_ptr++;
  }

  // Copy MSI Control Element to the end of the MAC Header if it presents
  if ((ce_ptr-mac_header_control_elements) > 0) {
  // printf("Copying %d bytes for control elements\n",ce_ptr-mac_header_control_elements);
  memcpy((void*)mac_header_ptr,mac_header_control_elements,ce_ptr-mac_header_control_elements);
  mac_header_ptr+=(unsigned char)(ce_ptr-mac_header_control_elements);
  }

  return((unsigned char*)mac_header_ptr - mac_header);
  }
  #endif
 */



// This has to be updated to include BSR information
1089
1090
uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id)
{
1091

1092
1093
  UE_TEMPLATE *UE_template    = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id];
  UE_sched_ctrl *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id];
1094

1095

Florian Kaltenberger's avatar
Florian Kaltenberger committed
1096
1097
1098
1099
1100
1101
  // do not schedule UE if UL is not working
  if (UE_sched_ctl->ul_failure_timer>0)
    return(0);
  if (UE_sched_ctl->ul_out_of_sync>0)
    return(0);

1102
1103
  LOG_D(MAC,"[eNB %d][PUSCH] Checking UL requirements UE %d/%x\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id));

knopp's avatar
   
knopp committed
1104
1105
1106
1107
  if ((UE_template->bsr_info[LCGID0]>0) ||
      (UE_template->bsr_info[LCGID1]>0) ||
      (UE_template->bsr_info[LCGID2]>0) ||
      (UE_template->bsr_info[LCGID3]>0) ||
gauthier's avatar
gauthier committed
1108
      (UE_template->ul_SR>0) || // uplink scheduling request
1109
      ((UE_sched_ctl->ul_inactivity_timer>20)&&
1110
1111
1112
1113
1114
       (UE_sched_ctl->ul_scheduled==0))||  // every 2 frames when RRC_CONNECTED
      ((UE_sched_ctl->ul_inactivity_timer>10)&&
       (UE_sched_ctl->ul_scheduled==0)&&
       (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) // every Frame when not RRC_CONNECTED
    { 
1115

1116
    LOG_D(MAC,"[eNB %d][PUSCH] UE %d/%x should be scheduled\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id));
1117
    return(1);
1118
  } else {
1119
    return(0);
1120
  }
1121
1122
1123
}


1124
1125
1126
1127
1128
1129
1130
uint8_t get_tmode(module_id_t module_idP,int CC_idP,int UE_idP) {

  eNB_MAC_INST         *eNB                                = RC.mac[module_idP];
  COMMON_channels_t    *cc                                 = &eNB->common_channels[CC_idP];

  struct PhysicalConfigDedicated  *physicalConfigDedicated = eNB->UE_list.physicalConfigDedicated[CC_idP][UE_idP];

1131
  if (physicalConfigDedicated == NULL ) { // RRCConnectionSetup not received by UE yet
1132
1133
1134
    AssertFatal(cc->p_eNB<=2,"p_eNB is %d, should be <2\n",cc->p_eNB);
    return(cc->p_eNB);
  }
1135
1136
1137
1138
1139
1140
1141
1142
1143
1144
1145
1146
1147
1148
1149
1150
  else {
    AssertFatal(physicalConfigDedicated->antennaInfo!=NULL,
		"antennaInfo is null for CCId %d, UEid %d\n",CC_idP,UE_idP);
    
    AssertFatal(physicalConfigDedicated->antennaInfo->present != PhysicalConfigDedicated__antennaInfo_PR_NOTHING, 
		"antennaInfo (mod_id %d, CC_id %d) is set to NOTHING\n",module_idP,CC_idP);
    
    if (physicalConfigDedicated->antennaInfo->present == PhysicalConfigDedicated__antennaInfo_PR_explicitValue) {
      return(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
    }
    else if (physicalConfigDedicated->antennaInfo->present == PhysicalConfigDedicated__antennaInfo_PR_defaultValue) {
      AssertFatal(cc->p_eNB<=2,"p_eNB is %d, should be <2\n",cc->p_eNB);
      return(cc->p_eNB);
    }
    else AssertFatal(1==0,"Shouldn't be here\n");
  }
1151
1152
}

1153
int8_t get_ULharq(module_id_t module_idP,int CC_idP,uint16_t frameP,uint8_t subframeP) {
1154
1155
1156
1157
1158
1159
1160
1161
1162
1163
1164
1165
1166
1167
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177
1178
1179
1180
1181

  uint8_t           ret       = -1;
  eNB_MAC_INST      *eNB      = RC.mac[module_idP];
  COMMON_channels_t *cc       = &eNB->common_channels[CC_idP];

  if (cc->tdd_Config==NULL) { // FDD
    ret = (((frameP<<1)+subframeP)&7);
  } else {

    switch (cc->tdd_Config->subframeAssignment) {

    case 1:
      if ((subframeP==2) ||
          (subframeP==3) ||
          (subframeP==7) ||
          (subframeP==8))
        switch (subframeP) {
        case 2:
        case 3:
          ret = (subframeP-2);
          break;

        case 7:
        case 8:
          ret = (subframeP-5);
          break;

        default:
1182
          AssertFatal(1==0,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
1183
1184
1185
1186
1187
1188
          break;
        }

      break;

    case 2:
1189
1190
1191
      AssertFatal((subframeP==2) || (subframeP==7),
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
      ret = (subframeP/7);
1192
1193
1194
      break;

    case 3:
1195
1196
1197
      AssertFatal((subframeP>1) && (subframeP<5),
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
      ret = (subframeP-2);
1198
1199
1200
      break;

    case 4:
1201
1202
1203
      AssertFatal((subframeP>1) && (subframeP<4),
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
      ret = (subframeP-2);
1204
1205
1206
      break;

    case 5:
1207
1208
1209
      AssertFatal(subframeP==2,
		  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
      ret = (subframeP-2);
1210
1211
1212
      break;

    default:
1213
1214
      AssertFatal(1==0,"subframe2_harq_pid, Unsupported TDD mode %d\n",(int)cc->tdd_Config->subframeAssignment);
      break;
1215
1216
1217
1218
1219
1220
1221
1222
1223
1224
1225
1226
1227
1228
1229
1230
1231
1232
    }
  }

  AssertFatal(ret!=-1,
	      "invalid harq_pid(%d) at SFN/SF = %d/%d\n", (int8_t)ret, frameP, subframeP);
  return ret;
}


uint16_t getRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs)
{

  uint16_t RIV;

  if (Lcrbs<=(1+(N_RB_DL>>1)))
    RIV = (N_RB_DL*(Lcrbs-1)) + RBstart;
  else
    RIV = (N_RB_DL*(N_RB_DL+1-Lcrbs)) + (N_RB_DL-1-RBstart);
1233

1234
1235
  return(RIV);
}
1236

knopp's avatar
knopp committed
1237
uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, int N_RB_DL, uint32_t *rballoc)
1238
{
1239
1240
1241
1242
1243

  int i;
  uint32_t rballoc_dci=0;
  unsigned char nb_rb_alloc=0;

knopp's avatar
knopp committed
1244
  for (i=0; i<(N_RB_DL-2); i+=2) {
1245
1246
1247
1248
1249
1250
    if (((*rballoc>>i)&3)==0) {
      *rballoc |= (3<<i);
      rballoc_dci |= (1<<((12-i)>>1));
      nb_rb_alloc+=2;
    }

1251
    if (nb_rb_alloc==nb_rb) {
1252
      return(rballoc_dci);
1253
    }
1254
1255
  }

knopp's avatar
knopp committed
1256
1257
1258
1259
  if ((N_RB_DL&1)==1) {
    if ((*rballoc>>(N_RB_DL-1)&1)==0) {
      *rballoc |= (1<<(N_RB_DL-1));
      rballoc_dci |= 1;
1260
    }
1261
  }
1262

1263
1264
1265
  return(rballoc_dci);
}

1266
1267
1268
1269
int get_bw_index(module_id_t module_id, uint8_t CC_id)
{

  int bw_index=0;
knopp's avatar
knopp committed
1270
1271
 
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
1272

knopp's avatar
knopp committed
1273
  switch (N_RB_DL) {
1274
1275
1276
1277
1278
1279
1280
1281
1282
1283
1284
1285
1286
1287
1288
1289
1290
1291
  case 6: // 1.4 MHz
    bw_index=0;
    break;

  case 25: // 5HMz
    bw_index=1;
    break;

  case 50: // 10HMz
    bw_index=2;
    break;

  case 100: // 20HMz
    bw_index=3;
    break;

  default:
    bw_index=1;
knopp's avatar
knopp committed
1292
    LOG_W(MAC,"[eNB %d] N_RB_DL %d unknown for CC_id %d, setting bw_index to 1\n", module_id, N_RB_DL,CC_id);
1293
1294
1295
1296
1297
1298
    break;
  }

  return bw_index;
}

1299
1300
1301
int get_min_rb_unit(module_id_t module_id, uint8_t CC_id)
{

1302
  int min_rb_unit=0;
knopp's avatar
knopp committed
1303
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
1304

knopp's avatar
knopp committed
1305
  switch (N_RB_DL) {
1306
1307
1308
  case 6: // 1.4 MHz
    min_rb_unit=1;
    break;
1309

1310
1311
1312
  case 25: // 5HMz
    min_rb_unit=2;
    break;
1313

1314
1315
1316
  case 50: // 10HMz
    min_rb_unit=3;
    break;
1317

1318
1319
1320
  case 100: // 20HMz
    min_rb_unit=4;
    break;
1321

1322
1323
  default:
    min_rb_unit=2;
Cedric Roux's avatar
Cedric Roux committed
1324
    LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n",
knopp's avatar
knopp committed
1325
          module_id, N_RB_DL, CC_id);
1326
1327
    break;
  }
1328

1329
1330
  return min_rb_unit;
}
1331

knopp's avatar
knopp committed
1332
uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, uint8_t *rballoc)
1333
{
1334
1335
1336
1337
1338

  int check=0;//check1=0,check2=0;
  uint32_t rballoc_dci=0;
  //uint8_t number_of_subbands=13;

1339
  LOG_T(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n",
knopp's avatar
knopp committed
1340
        rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,N_RBG);
1341

knopp's avatar
knopp committed
1342
  while((nb_rb >0) && (check < N_RBG)) {
knopp's avatar
   
knopp committed
1343
    //printf("rballoc[%d] %d\n",check,rballoc[check]);
1344
    if(rballoc[check] == 1) {
knopp's avatar
knopp committed
1345
      rballoc_dci |= (1<<((N_RBG-1)-check));
1346

knopp's avatar
knopp committed
1347
      switch (N_RB_DL) {
1348
1349
1350
1351
1352
      case 6:
        nb_rb--;
        break;

      case 25:
knopp's avatar
knopp committed
1353
        if ((check == N_RBG-1)) {
1354
          nb_rb--;<