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

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
27
 * \version 1.0
28 29 30 31 32 33
 * @ingroup _mac

 */

#include "assertions.h"

34 35
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_extern.h"
36

37
#include "LAYER2/MAC/mac_proto.h"
38
#include "common/utils/LOG/log.h"
frtabu's avatar
frtabu committed
39
#include "nfapi/oai_integration/vendor_ext.h"
40
#include "common/utils/LOG/vcd_signal_dumper.h"
41 42 43 44
#include "UTIL/OPT/opt.h"
#include "OCG.h"
#include "OCG_extern.h"

45
#include "RRC/LTE/rrc_extern.h"
46 47 48 49 50
#include "RRC/L2_INTERFACE/openair_rrc_L2_interface.h"

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

51 52
#include "intertask_interface.h"
#include "executables/softmodem-common.h"
Cedric Roux's avatar
Cedric Roux committed
53 54
#include "T.h"

55 56
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1
57
extern uint16_t frame_cnt;
58

59
#include "common/ran_context.h"
60
#include "SCHED/sched_common.h"
61 62

extern RAN_CONTEXT_t RC;
frtabu's avatar
frtabu committed
63

64

65
//------------------------------------------------------------------------------
66 67 68
int
choose(int n,
       int k)
69
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
70
{
71 72 73
  int res = 1;
  int res2 = 1;
  int i;
74

75 76
  if (k > n)
    return (0);
77

78 79
  if (n == k)
    return (1);
80

81 82
  for (i = n; i > k; i--)
    res *= i;
83

84 85
  for (i = 2; i <= (n - k); i++)
    res2 *= i;
86

87
  return (res / res2);
88 89
}

90
//------------------------------------------------------------------------------
91
// Patented algorithm from Yang et al, US Patent 2009, "Channel Quality Indexing and Reverse Indexing"
92 93 94 95
void reverse_index(int N,
                   int M,
                   int r,
                   int *v)
96
//------------------------------------------------------------------------------
97
{
98 99 100 101 102 103 104 105
  int BaseValue = 0;
  int IncreaseValue, ThresholdValue;
  int sumV;
  int i;
  r = choose(N, M) - 1 - r;
  memset((void *) v, 0, M * sizeof(int));
  sumV = 0;
  i = M;
106

107
  while (i > 0 && r > 0) {
108
    IncreaseValue = choose(N - M + 1 - sumV - v[i - 1] + i - 2,
109
                           i - 1);
110
    ThresholdValue = BaseValue + IncreaseValue;
111

112 113 114 115
    if (r >= ThresholdValue) {
      v[i - 1]++;
      BaseValue = ThresholdValue;
    } else {
116 117
      r -= BaseValue;
      sumV += v[--i];
118
      BaseValue = 0;
119
    }
120
  }
121
}
Cedric Roux's avatar
Cedric Roux committed
122

123
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
124
int
125
to_prb(int dl_Bandwidth)
126
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
127
{
128 129 130
  int prbmap[6] = { 6, 15, 25, 50, 75, 100 };
  AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth is 0..5\n");
  return (prbmap[dl_Bandwidth]);
131 132
}

133
//------------------------------------------------------------------------------
134 135
int
to_rbg(int dl_Bandwidth)
136
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
137
{
138 139 140
  int rbgmap[6] = { 6, 8, 13, 17, 19, 25 };
  AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth is 0..5\n");
  return (rbgmap[dl_Bandwidth]);
141
}
142

143
//------------------------------------------------------------------------------
144 145
int
get_phich_resource_times6(COMMON_channels_t *cc)
146
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
147
{
148 149 150
  int phichmap[4] = { 1, 3, 6, 12 };
  AssertFatal(cc != NULL, "cc is null\n");
  AssertFatal(cc->mib != NULL, "cc->mib is null\n");
151 152 153 154
  int phich_Resource = (int) cc->mib->message.phich_Config.phich_Resource;
  AssertFatal(phich_Resource >= 0 && phich_Resource < 4, "phich_Resource %d not in 0..3\n",
              phich_Resource);
  return (phichmap[phich_Resource]);
155 156
}

157
//------------------------------------------------------------------------------
158 159 160 161
uint16_t
mac_computeRIV(uint16_t N_RB_DL,
               uint16_t RBstart,
               uint16_t Lcrbs)
162
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
163
{
164 165 166
  if (Lcrbs <= (1 + (N_RB_DL >> 1))) {
    return (N_RB_DL * (Lcrbs - 1)) + RBstart;
  }
frtabu's avatar
frtabu committed
167

168
  return (N_RB_DL * (N_RB_DL + 1 - Lcrbs)) + (N_RB_DL - 1 - RBstart);
169 170
}

171
//------------------------------------------------------------------------------
172 173
uint8_t
getQm(uint8_t mcs)
174
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
175
{
176 177
  if (mcs < 10)      return (2);
  else if (mcs < 17) return (4);
frtabu's avatar
frtabu committed
178

Stefan's avatar
Stefan committed
179
  return (6);
180 181
}

182
//------------------------------------------------------------------------------
183
void
184
get_Msg3alloc(COMMON_channels_t *cc,
185 186 187
              sub_frame_t       current_subframe,
              frame_t           current_frame,
              frame_t           *frame,
188
              sub_frame_t       *subframe)
189
//------------------------------------------------------------------------------
190
{
191
  // Fill in other TDD Configuration!!!!
192
  int subframeAssignment;
193

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

197 198 199 200 201 202
    if (*subframe > 9) {
      *subframe = *subframe - 10;
      *frame = (current_frame + 1) & 1023;
    } else {
      *frame = current_frame;
    }
203
  } else {      // TDD
204
    subframeAssignment = (int) cc->tdd_Config->subframeAssignment;
frtabu's avatar
frtabu committed
205

206
    if (subframeAssignment == 1) {
207
      switch (current_subframe) {
208 209 210 211
        case 0:
          *subframe = 7;
          *frame = current_frame;
          break;
212

213 214 215 216
        case 4:
          *subframe = 2;
          *frame = (current_frame + 1) & 1023;
          break;
217

218 219 220 221 222 223 224 225 226
        case 5:
          *subframe = 2;
          *frame = (current_frame + 1) & 1023;
          break;

        case 9:
          *subframe = 7;
          *frame = (current_frame + 1) & 1023;
          break;
227
      }
228
    } else if (subframeAssignment == 3) {
229
      switch (current_subframe) {
230 231 232 233 234 235
        case 0:
        case 5:
        case 6:
          *subframe = 2;
          *frame = (current_frame + 1) & 1023;
          break;
236

237 238 239 240
        case 7:
          *subframe = 3;
          *frame = (current_frame + 1) & 1023;
          break;
241

242 243 244 245
        case 8:
          *subframe = 4;
          *frame = (current_frame + 1) & 1023;
          break;
246

247 248 249 250
        case 9:
          *subframe = 2;
          *frame = (current_frame + 2) & 1023;
          break;
251
      }
252
    } else if (subframeAssignment == 4) {
253
      switch (current_subframe) {
254 255 256 257 258 259 260
        case 0:
        case 4:
        case 5:
        case 6:
          *subframe = 2;
          *frame = (current_frame + 1) & 1023;
          break;
261

262 263 264 265
        case 7:
          *subframe = 3;
          *frame = (current_frame + 1) & 1023;
          break;
266

267 268 269 270 271
        case 8:
        case 9:
          *subframe = 2;
          *frame = (current_frame + 2) & 1023;
          break;
272
      }
273
    } else if (subframeAssignment == 5) {
274
      switch (current_subframe) {
275 276 277 278 279 280 281
        case 0:
        case 4:
        case 5:
        case 6:
          *subframe = 2;
          *frame = (current_frame + 1) & 1023;
          break;
282

283 284 285 286 287 288
        case 7:
        case 8:
        case 9:
          *subframe = 2;
          *frame = (current_frame + 2) & 1023;
          break;
289
      }
Cedric Roux's avatar
Cedric Roux committed
290
    }
291
  }
frtabu's avatar
frtabu committed
292

293
  return;
294 295
}

296
//------------------------------------------------------------------------------
297
void
298 299 300
get_Msg3allocret(COMMON_channels_t *cc,
                 sub_frame_t current_subframe,
                 frame_t current_frame,
301 302
                 frame_t *frame,
                 sub_frame_t *subframe)
303
//------------------------------------------------------------------------------
304
{
305 306
  int subframeAssignment;

307
  if (cc->tdd_Config == NULL) { //FDD
308 309
    /* always retransmit in n+8 */
    *subframe = current_subframe + 8;
310

311 312 313
    if (*subframe > 9) {
      *subframe = *subframe - 10;
      *frame = (current_frame + 1) & 1023;
314
    } else {
315
      *frame = current_frame;
316
    }
317
  } else {
318
    subframeAssignment = (int) cc->tdd_Config->subframeAssignment;
frtabu's avatar
frtabu committed
319

320
    if (subframeAssignment == 1) {
321 322 323 324 325
      // 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;
326
    } else if (subframeAssignment == 3) {
327 328 329 330
      // 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;
331
    } else if (subframeAssignment == 4) {
332 333 334
      // 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;
335
    } else if (subframeAssignment == 5) {
336 337 338 339
      // original PUSCH in 2, PHICH in 8, ret in 2 next frame
      *frame = (current_frame + 1) & 1023;
    }
  }
frtabu's avatar
frtabu committed
340

341
  return;
342 343
}

344
//------------------------------------------------------------------------------
345
uint8_t
346
subframe2harqpid(COMMON_channels_t *cc,
347
                 frame_t frame,
348
                 sub_frame_t subframe)
349
//------------------------------------------------------------------------------
350
{
351
  AssertFatal(cc != NULL, "cc is null\n");
352 353
  uint8_t ret = 255;

354
  if (cc->tdd_Config == NULL) { // FDD
355
    ret = (((frame << 1) + subframe) & 7);
356
  } else {
357
    switch (cc->tdd_Config->subframeAssignment) {
358
      case 1:
359
        if (subframe == 2 || subframe == 3 || subframe == 7 || subframe == 8) {
Stefan's avatar
Stefan committed
360 361 362 363 364
          switch (subframe) {
            case 2:
            case 3:
              ret = (subframe - 2);
              break;
365

Stefan's avatar
Stefan committed
366 367 368 369
            case 7:
            case 8:
              ret = (subframe - 5);
              break;
370

Stefan's avatar
Stefan committed
371
            default:
372
              AssertFatal(1 == 0, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
Stefan's avatar
Stefan committed
373 374 375 376
                          subframe,
                          (int) cc->tdd_Config->subframeAssignment);
              break;
          }
Stefan's avatar
Stefan committed
377
        }
frtabu's avatar
frtabu committed
378

379
        break;
380

381
      case 2:
382
        AssertFatal(subframe == 2 || subframe == 7, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
Stefan's avatar
Stefan committed
383 384
                    subframe,
                    (int) cc->tdd_Config->subframeAssignment);
385 386
        ret = (subframe / 7);
        break;
387

388
      case 3:
389
        AssertFatal(subframe > 1 && subframe < 5, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
Stefan's avatar
Stefan committed
390 391
                    subframe,
                    (int) cc->tdd_Config->subframeAssignment);
392 393
        ret = (subframe - 2);
        break;
394

395
      case 4:
396
        AssertFatal(subframe > 1 && subframe < 4, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
Stefan's avatar
Stefan committed
397 398
                    subframe,
                    (int) cc->tdd_Config->subframeAssignment);
399 400
        ret = (subframe - 2);
        break;
401

402
      case 5:
403
        AssertFatal(subframe == 2, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
Stefan's avatar
Stefan committed
404 405
                    subframe,
                    (int) cc->tdd_Config->subframeAssignment);
406 407
        ret = (subframe - 2);
        break;
408

409
      default:
410
        AssertFatal(1 == 0, "subframe2_harq_pid, Unsupported TDD mode %d\n",
411 412
                    (int) cc->tdd_Config->subframeAssignment);
        break;
413
    }
414
  }
415

416
  return ret;
417
}
418

419
//------------------------------------------------------------------------------
420
uint8_t
421
get_Msg3harqpid(COMMON_channels_t *cc,
422 423
                frame_t frame,
                sub_frame_t current_subframe)
424
//------------------------------------------------------------------------------
425
{
426 427
  uint8_t ul_subframe = 0;
  uint32_t ul_frame = 0;
428

429
  if (cc->tdd_Config == NULL) { // FDD
430
    ul_subframe = (current_subframe > 3) ? (current_subframe - 4) : (current_subframe + 6);
431 432 433
    ul_frame = (current_subframe > 3) ? ((frame + 1) & 1023) : frame;
  } else {
    switch (cc->tdd_Config->subframeAssignment) {
434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488
      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;

489
      case 5:
490 491 492 493
        ul_subframe = 2;
        break;

      default:
494
        LOG_E(PHY, "get_Msg3_harq_pid: Unsupported TDD configuration %d\n",
495
              (int) cc->tdd_Config->subframeAssignment);
496
        AssertFatal(1 == 0, "get_Msg3_harq_pid: Unsupported TDD configuration");
497
        break;
498
    }
499
  }
Cedric Roux's avatar
Cedric Roux committed
500

501 502
  return (subframe2harqpid(cc,
                           ul_frame,
503
                           ul_subframe));
504
}
505

506
//------------------------------------------------------------------------------
507
uint32_t
508 509 510
pdcchalloc2ulframe(COMMON_channels_t *ccP,
                   uint32_t frame,
                   uint8_t n)
511
//------------------------------------------------------------------------------
512
{
513
  uint32_t ul_frame = (frame + (n >= 6 ? 1 : 0));
514

515 516 517 518 519 520 521 522 523 524 525 526 527
  if (ccP->tdd_Config) {
    if (ccP->tdd_Config->subframeAssignment == 1) {
      if (n == 1 || n == 6) {
        ul_frame = (frame + (n == 1 ? 0 : 1));
      }
    } else if (ccP->tdd_Config->subframeAssignment == 6) {
      if (n == 0 || n == 1 || n == 5 || n == 6) {
        ul_frame = (frame + (n >= 5 ? 1 : 0));
      } else if (n == 9) {
        ul_frame = (frame + 1);
      }
    }
  }
frtabu's avatar
frtabu committed
528

529 530
  LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n",
        frame,
531
        n,
532
        ul_frame);
533
  return ul_frame;
534
}
535

536
//------------------------------------------------------------------------------
537 538 539
uint8_t
pdcchalloc2ulsubframe(COMMON_channels_t *ccP,
                      uint8_t n)
540
//------------------------------------------------------------------------------
541
{
542
  uint8_t ul_subframe;
543

544
  if (ccP->tdd_Config && ccP->tdd_Config->subframeAssignment == 1 && (n == 1 || n == 6))  // tdd_config 0,1 SF 1,5
545
    ul_subframe = ((n + 6) % 10);
546
  else if (ccP->tdd_Config && ccP->tdd_Config->subframeAssignment == 6 && (n == 0 || n == 1 || n == 5 || n == 6))
547
    ul_subframe = ((n + 7) % 10);
548
  else if (ccP->tdd_Config && ccP->tdd_Config->subframeAssignment == 6 && n == 9) // tdd_config 6 SF 9
549 550 551
    ul_subframe = ((n + 5) % 10);
  else
    ul_subframe = ((n + 4) % 10);
552

553 554
  LOG_D(PHY, "subframe %d: PUSCH subframe = %d\n",
        n,
555
        ul_subframe);
556
  return ul_subframe;
557 558
}

559
//------------------------------------------------------------------------------
560 561 562
int
is_UL_sf(COMMON_channels_t *ccP,
         sub_frame_t subframeP)
563
//------------------------------------------------------------------------------
564
{
565 566
  // if FDD return dummy value
  if (ccP->tdd_Config == NULL)
567
    return 0;
568

569
  switch (ccP->tdd_Config->subframeAssignment) {
570 571 572 573 574 575
    case 1:
      switch (subframeP) {
        case 0:
        case 4:
        case 5:
        case 9:
576
          return 0;
577 578 579 580 581

        case 2:
        case 3:
        case 7:
        case 8:
582
          return 1;
583 584

        default:
585
          return 0;
586 587
      }

588
      break;
589

590
    case 3:
591 592
      if (subframeP <= 1 || subframeP >= 5)
        return 0;
593

594
      return 1;
595 596

    case 4:
597 598
      if (subframeP <= 1 || subframeP >= 4)
        return 0;
599

600
      return 1;
601 602

    case 5:
603 604
      if (subframeP <= 1 || subframeP >= 3)
        return 0;
605

606
      return 1;
607

608
    default:
609 610 611
      AssertFatal(1 == 0,  "subframe %d Unsupported TDD configuration %d\n",
                  subframeP,
                  (int) ccP->tdd_Config->subframeAssignment);
612 613
      break;
  }
frtabu's avatar
frtabu committed
614

615
  return 0;
616 617
}

618
//------------------------------------------------------------------------------
619 620 621
int
is_S_sf(COMMON_channels_t *ccP,
        sub_frame_t subframeP)
622
//------------------------------------------------------------------------------
623
{
624 625
  // if FDD return dummy value
  if (ccP->tdd_Config == NULL)
626
    return 0;
627

628
  switch (subframeP) {
629
    case 1:
630
      return 1;
631 632

    case 6:
633 634 635
      if (ccP->tdd_Config->subframeAssignment == 0 || ccP->tdd_Config->subframeAssignment == 1 ||
          ccP->tdd_Config->subframeAssignment == 2 || ccP->tdd_Config->subframeAssignment == 6)
        return 1;
636 637

      break;
638 639

    default:
640 641 642 643
      break;
  }

  return 0;
644 645
}

646
//------------------------------------------------------------------------------
647 648 649
uint8_t
ul_subframe2_k_phich(COMMON_channels_t *cc,
                     sub_frame_t ul_subframe)
650 651
//------------------------------------------------------------------------------
{
652 653 654 655
  if(cc->tdd_Config) { //TODO fill other tdd config
    switch(cc->tdd_Config->subframeAssignment) {
      case 0:
        break;
656

657 658 659 660 661
      case 1:
        if(ul_subframe == 2 || ul_subframe == 7)
          return 4;
        else if(ul_subframe == 3 || ul_subframe == 8)
          return 6;
frtabu's avatar
frtabu committed
662

663
        return 255;
664 665 666 667 668 669

      case 2:
      case 3:
      case 4:
      case 5:
        break;
670
    }
671 672 673
  }

  return 4; //idk  sf_ahead?
674 675
}

676
//------------------------------------------------------------------------------
677 678 679
uint16_t
get_pucch1_absSF(COMMON_channels_t *cc,
                 uint16_t dlsch_absSF)
680
//------------------------------------------------------------------------------
681
{
682
  uint16_t sf, f, nextf;
Stefan's avatar
Stefan committed
683
  LTE_TDD_Config_t *tdd_Config = cc->tdd_Config;
684

Stefan's avatar
Stefan committed
685 686
  if (tdd_Config == NULL) { //FDD n+4
    return (dlsch_absSF + 4) % 10240;
687
  }
688

Stefan's avatar
Stefan committed
689 690 691
  sf = dlsch_absSF % 10;
  f = dlsch_absSF / 10;
  nextf = (f + 1) & 1023;
692

Stefan's avatar
Stefan committed
693
  switch (tdd_Config->subframeAssignment) {
694
    case 0:
Stefan's avatar
Stefan committed
695 696
      if (sf == 0 || sf == 5)
        return ((10 * f) + sf + 4) % 10240; // ACK/NAK in SF 4,9 same frame
frtabu's avatar
frtabu committed
697

Stefan's avatar
Stefan committed
698 699
      if (sf == 6)
        return ((10 * nextf) + 2) % 10240;  // ACK/NAK in SF 2 next frame
frtabu's avatar
frtabu committed
700

Stefan's avatar
Stefan committed
701 702
      if (sf == 1)
        return ((10 * f) + 7) % 10240;      // ACK/NAK in SF 7 same frame
703

704
      break;
705

706
    case 1:
Stefan's avatar
Stefan committed
707 708
      if (sf == 5 || sf == 6)
        return ((10 * nextf) + 2) % 10240;  // ACK/NAK in SF 2 next frame
frtabu's avatar
frtabu committed
709

Stefan's avatar
Stefan committed
710 711
      if (sf == 9)
        return ((10 * nextf) + 3) % 10240;  // ACK/NAK in SF 3 next frame
frtabu's avatar
frtabu committed
712

Stefan's avatar
Stefan committed
713 714
      if ((sf == 0) || (sf == 1))
        return ((10 * f) + 7) % 10240;      // ACK/NAK in SF 7 same frame
frtabu's avatar
frtabu committed
715

Stefan's avatar
Stefan committed
716 717
      if (sf == 4)
        return ((10 * f) + 8) % 10240;      // ACK/NAK in SF 8 same frame
718

719
      break;
720

721
    case 2:
Stefan's avatar
Stefan committed
722 723
      if (sf == 4 || sf == 5 || sf == 6 || sf == 8)
        return ((10 * nextf) + 2) % 10240;  // ACK/NAK in SF 2 next frame
frtabu's avatar
frtabu committed
724

Stefan's avatar
Stefan committed
725 726
      if (sf == 9)
        return ((10 * nextf) + 7) % 10240;  // ACK/NAK in SF 7 next frame
frtabu's avatar
frtabu committed
727

Stefan's avatar
Stefan committed
728 729
      if (sf == 0 || sf == 1 || sf == 3)
        return ((10 * f) + 7)% 10240;       // ACK/NAK in SF 7 same frame
730

731
      break;
732

733
    case 3:
Stefan's avatar
Stefan committed
734 735
      if (sf == 5 || sf == 6 || sf == 7 || sf == 8 || sf == 9)
        return ((10 * nextf) + ((sf - 1) >> 1)) % 10240;  // ACK/NAK in 2,3,4 resp. next frame
frtabu's avatar
frtabu committed
736

Stefan's avatar
Stefan committed
737 738
      if (sf == 1)
        return ((10 * nextf) + 2) % 10240;                // ACK/NAK in 2 next frame
frtabu's avatar
frtabu committed
739

Stefan's avatar
Stefan committed
740 741
      if (sf == 0)
        return ((10 * f) + 4) % 10240;                    // ACK/NAK in 4 same frame
742

743
      break;
744

745
    case 4:
Stefan's avatar
Stefan committed
746 747 748 749
      if (sf == 6 || sf == 7 || sf == 8 || sf == 9)
        return ((10 * nextf) + 3) % 10240;  // ACK/NAK in SF 3 next frame
      else if (sf == 0 || sf == 1 || sf == 4 || sf == 5)
        return ((10 * nextf) + 2) % 10240;  // ACK/NAK in SF 2 next frame
750

751
      break;
752

753
    case 5:
Stefan's avatar
Stefan committed
754 755
      if (sf == 0 || sf == 1 || sf == 3 || sf == 4 || sf == 5 || sf == 6 || sf == 7 || sf == 8)
        return ((10 * nextf) + 2) % 10240;        // ACK/NAK in SF 3 next frame
frtabu's avatar
frtabu committed
756

Stefan's avatar
Stefan committed
757 758
      if (sf == 9)
        return ((10 * (1 + nextf)) + 2) % 10240;  // ACK/NAK in SF 2 next frame
759

760
      break;
761

762
    case 6:
Stefan's avatar
Stefan committed
763 764
      if (sf == 5 || sf == 6)
        return ((10 * f) + sf + 7) % 10240; // ACK/NAK in SF 2,3 next frame
frtabu's avatar
frtabu committed
765

Stefan's avatar
Stefan committed
766 767
      if (sf == 9)
        return ((10 * nextf) + 4) % 10240;  // ACK/NAK in SF 4 next frame
frtabu's avatar
frtabu committed
768

Stefan's avatar
Stefan committed
769 770
      if (sf == 1 || sf == 0)
        return ((10 * f) + sf + 7) % 10240; // ACK/NAK in SF 7 same frame
771

772
      break;
Stefan's avatar
Stefan committed
773

774
    default:
Stefan's avatar
Stefan committed
775 776 777
      AssertFatal(1 == 0, "Illegal TDD subframe Assigment %ld\n",
                  tdd_Config->subframeAssignment);
      return 0;
778
  }
779

780
  AssertFatal(1 == 0, "Shouldn't get here\n");
781 782
}

783
//------------------------------------------------------------------------------
784
void
785
get_srs_pos(COMMON_channels_t *cc,
786
            uint16_t isrs,
787 788
            uint16_t *psrsPeriodicity,
            uint16_t *psrsOffset)
789
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
790
{
791
  if (cc->tdd_Config) { // TDD
792
    AssertFatal(isrs >= 10, "2 ms SRS periodicity not supported");
793

794
    if (isrs > 9 && isrs < 15) {
795 796
      *psrsPeriodicity = 5;
      *psrsOffset = isrs - 10;
797
    } else if (isrs > 14 && isrs < 25) {
798 799
      *psrsPeriodicity = 10;
      *psrsOffset = isrs - 15;
800
    } else if (isrs > 24 && isrs < 45) {
801 802
      *psrsPeriodicity = 20;
      *psrsOffset = isrs - 25;
803
    } else if (isrs > 44 && isrs < 85) {
804 805
      *psrsPeriodicity = 40;
      *psrsOffset = isrs - 45;
806
    } else if (isrs > 84 && isrs < 165) {
807 808
      *psrsPeriodicity = 80;
      *psrsOffset = isrs - 85;
809
    } else if (isrs > 164 && isrs < 325) {
810 811
      *psrsPeriodicity = 160;
      *psrsOffset = isrs - 165;
812
    } else if (isrs > 324 && isrs < 645) {
813 814 815
      *psrsPeriodicity = 320;
      *psrsOffset = isrs - 325;
    }
816

817
    AssertFatal(isrs <= 644, "Isrs out of range %d>644\n", isrs);
818 819
  }       // TDD
  else {      // FDD
820 821 822
    if (isrs < 2) {
      *psrsPeriodicity = 2;
      *psrsOffset = isrs;
823
    } else if (isrs > 1 && isrs < 7) {
824 825
      *psrsPeriodicity = 5;
      *psrsOffset = isrs - 2;
826
    } else if (isrs > 6 && isrs < 17) {
827 828
      *psrsPeriodicity = 10;
      *psrsOffset = isrs - 7;
829
    } else if (isrs > 16 && isrs < 37) {
830 831
      *psrsPeriodicity = 20;
      *psrsOffset = isrs - 17;
832
    } else if (isrs > 36 && isrs < 77) {
833 834
      *psrsPeriodicity = 40;
      *psrsOffset = isrs - 37;
835
    } else if (isrs > 76 && isrs < 157) {
836 837
      *psrsPeriodicity = 80;
      *psrsOffset = isrs - 77;
838
    } else if (isrs > 156 && isrs < 317) {
839 840
      *psrsPeriodicity = 160;
      *psrsOffset = isrs - 157;
841
    } else if (isrs > 316 && isrs < 637) {
842 843 844
      *psrsPeriodicity = 320;
      *psrsOffset = isrs - 317;
    }
845

846 847
    AssertFatal(isrs <= 636, "Isrs out of range %d>636\n", isrs);
  }
frtabu's avatar
frtabu committed
848

849
  return;
850 851
}

852
//------------------------------------------------------------------------------
853 854 855 856
/*
* Get some CSI (CQI/PMI/RI) parameters for SFN and subframe number calculation
* with periodic report.
*/
857
void
858 859
get_csi_params(COMMON_channels_t *cc,
               struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic,
860 861 862
               uint16_t *Npd,
               uint16_t *N_OFFSET_CQI,
               int *H)
863
//------------------------------------------------------------------------------
864
{
865
  AssertFatal(cqi_ReportPeriodic != NULL, "cqi_ReportPeriodic is null!\n");
866
  uint16_t cqi_PMI_ConfigIndex = cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex;
867 868
  uint8_t Jtab[6] = { 0, 2, 2, 3, 4, 4 };

869 870
  if (cc->tdd_Config == NULL) { //FDD
    if (cqi_PMI_ConfigIndex <= 1) { // 2 ms CQI_PMI period
871 872
      *Npd = 2;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex;
873
    } else if (cqi_PMI_ConfigIndex <= 6) {  // 5 ms CQI_PMI period
874 875
      *Npd = 5;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 2;
876
    } else if (cqi_PMI_ConfigIndex <= 16) { // 10ms CQI_PMI period
877 878
      *Npd = 10;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 7;
879
    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
880 881
      *Npd = 20;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 17;
882
    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
883 884
      *Npd = 40;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 37;
885
    } else if (cqi_PMI_ConfigIndex <= 156) {  // 80 ms CQI_PMI period
886 887
      *Npd = 80;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 77;
888
    } else if (cqi_PMI_ConfigIndex <= 316) {  // 160 ms CQI_PMI period
889 890 891
      *Npd = 160;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 157;
    } else if (cqi_PMI_ConfigIndex > 317) {
892 893 894 895 896 897 898 899 900
      if (cqi_PMI_ConfigIndex <= 349) {         // 32 ms CQI_PMI period
        *Npd = 32;
        *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 318;
      } else if (cqi_PMI_ConfigIndex <= 413) {  // 64 ms CQI_PMI period
        *Npd = 64;
        *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 350;
      } else if (cqi_PMI_ConfigIndex <= 541) {  // 128 ms CQI_PMI period
        *Npd = 128;
        *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 414;
901
      }
902
    }
903
  } else {  // TDD
904
    if (cqi_PMI_ConfigIndex == 0) { // all UL subframes
905 906
      *Npd = 1;
      *N_OFFSET_CQI = 0;
907
    } else if (cqi_PMI_ConfigIndex <= 6) {  // 5 ms CQI_PMI period
908 909
      *Npd = 5;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 1;
910
    } else if (cqi_PMI_ConfigIndex <= 16) { // 10ms CQI_PMI period
911 912
      *Npd = 10;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 6;
913
    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
914 915
      *Npd = 20;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 16;
916
    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
917 918
      *Npd = 40;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 36;
919
    } else if (cqi_PMI_ConfigIndex <= 156) {  // 80 ms CQI_PMI period
920 921
      *Npd = 80;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 76;
922
    } else if (cqi_PMI_ConfigIndex <= 316) {  // 160 ms CQI_PMI period
923 924
      *Npd = 160;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex - 156;
925
    }
926
  }
927

928
  // get H
929 930 931
  if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) {
    *H = 1 + (Jtab[cc->mib->message.dl_Bandwidth] * cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.choice.subbandCQI.k);
  } else {
932
    *H = 1;
933
  }
frtabu's avatar
frtabu committed
934

935
  return;
936 937
}

938
//------------------------------------------------------------------------------
939
uint8_t
940
get_dl_cqi_pmi_size_pusch(COMMON_channels_t *cc,
941
                          uint8_t tmode,
942
                          uint8_t ri,
943
                          LTE_CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic)
944
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
945
{
946 947 948 949
  int Ntab[6] = { 0, 4, 7, 9, 10, 13 };
  int N = Ntab[cc->mib->message.dl_Bandwidth];
  int Ltab_uesel[6] = { 0, 6, 9, 13, 15, 18 };
  int L = Ltab_uesel[cc->mib->message.dl_Bandwidth];
950
  AssertFatal(cqi_ReportModeAperiodic != NULL, "cqi_ReportPeriodic is null!\n");
951 952

  switch (*cqi_ReportModeAperiodic) {
953
    case LTE_CQI_ReportModeAperiodic_rm12:
954
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal TM (%d) for CQI_ReportModeAperiodic_rm12\n",
955
                  tmode);
956
      AssertFatal(cc->p_eNB <= 4, "only up to 4 antenna ports supported here\n");
957 958 959

      if (ri == 1 && cc->p_eNB == 2)
        return (4 + (N << 1));
frtabu's avatar
frtabu committed
960

961
      if (ri == 2 && cc->p_eNB == 2)
962
        return (8 + N);
frtabu's avatar
frtabu committed
963

964
      if (ri == 1 && cc->p_eNB == 4)
965
        return (4 + (N << 2));
frtabu's avatar
frtabu committed
966

967
      if (ri > 1 && cc->p_eNB == 4)
968 969 970 971 972 973
        return (8 + (N << 2));

      break;

    case LTE_CQI_ReportModeAperiodic_rm20:
      // Table 5.2.2.6.3-1 (36.212)
974
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7 || tmode == 9 || tmode == 10, "Illegal TM (%d) for CQI_ReportModeAperiodic_rm20\n",
975
                  tmode);
976
      AssertFatal(tmode != 9 && tmode != 10, "TM9/10 will be handled later for CQI_ReportModeAperiodic_rm20\n");
977 978 979 980
      return (4 + 2 + L);

    case LTE_CQI_ReportModeAperiodic_rm22:
      // Table 5.2.2.6.3-2 (36.212)
981
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal TM (%d) for CQI_ReportModeAperiodic_rm22\n",
982
                  tmode);
983
      AssertFatal(tmode != 9 && tmode != 10, "TM9/10 will be handled later for CQI_ReportModeAperiodic_rm22\n");
984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000

      if (ri == 1 && cc->p_eNB == 2)
        return (4 + 2 + 0 + 0 + L + 4);

      if (ri == 2 && cc->p_eNB == 2)
        return (4 + 2 + 4 + 2 + L + 2);

      if (ri == 1 && cc->p_eNB == 4)
        return (4 + 2 + 0 + 0 + L + 8);

      if (ri >= 2 && cc->p_eNB == 4)
        return (4 + 2 + 4 + 2 + L + 8);

      break;

    case LTE_CQI_ReportModeAperiodic_rm30:
      // Table 5.2.2.6.2-1 (36.212)
1001
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7 || tmode == 8 || tmode == 9 || tmode == 10,
1002 1003
                  "Illegal TM (%d) for CQI_ReportModeAperiodic_rm30\n",
                  tmode);
1004
      AssertFatal(tmode != 8 && tmode != 9 && tmode != 10, "TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm30\n");
1005
      return (4 + (N << 1));
1006 1007 1008

    case LTE_CQI_ReportModeAperiodic_rm31:
      // Table 5.2.2.6.2-2 (36.212)
1009
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal TM (%d) for CQI_ReportModeAperiodic_rm31\n",
1010
                  tmode);
1011
      AssertFatal(tmode != 8 && tmode != 9 && tmode != 10, "TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm31\n");
1012 1013 1014

      if (ri == 1 && cc->p_eNB == 2)
        return (4 + (N << 1) + 0 + 0 + 2);
frtabu's avatar
frtabu committed
1015

1016
      if (ri == 2 && cc->p_eNB == 2)
1017
        return (4 + (N << 1) + 4 + (N << 1) + 1);
frtabu's avatar
frtabu committed
1018

1019
      if (ri == 1 && cc->p_eNB == 4)
1020
        return (4 + (N << 1) + 0 + 0 + 4);
frtabu's avatar
frtabu committed
1021

1022
      if (ri >= 2 && cc->p_eNB == 4)
1023 1024 1025
        return (4 + (N << 1) + 4 + (N << 1) + 4);

      break;
frtabu's avatar
frtabu committed
1026

1027
    case LTE_CQI_ReportModeAperiodic_rm32_v1250:
1028
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal TM (%d) for CQI_ReportModeAperiodic_rm32\n",
1029
                  tmode);
1030
      AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm32_v1250 not supported yet\n");
1031 1032 1033 1034 1035 1036
      break;

    case LTE_CQI_ReportModeAperiodic_rm10_v1310:

      // Table 5.2.2.6.1-1F/G (36.212)
      if (ri == 1)
1037
        return 4;   // F
frtabu's avatar
frtabu committed
1038

1039
      return 7;   // G
1040 1041 1042

    case LTE_CQI_ReportModeAperiodic_rm11_v1310:
      // Table 5.2.2.6.1-1H (36.212)
1043
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10,  "Illegal TM (%d) for CQI_ReportModeAperiodic_rm11\n",
1044
                  tmode);
1045
      AssertFatal(cc->p_eNB <= 4, "only up to 4 antenna ports supported here\n");
1046 1047 1048

      if (ri == 1 && cc->p_eNB == 2)
        return (4 + 0 + 2);
frtabu's avatar
frtabu committed
1049

1050
      if (ri == 2 && cc->p_eNB == 2)
1051
        return (4 + 4 + 1);
frtabu's avatar
frtabu committed
1052

1053
      if (ri == 1 && cc->p_eNB == 4)
1054
        return (4 + 0 + 4);
frtabu's avatar
frtabu committed
1055

1056
      if (ri > 1 && cc->p_eNB == 4)
1057 1058 1059
        return (4 + 4 + 4);

      break;
1060
  }
1061

1062
  AssertFatal(1 == 0, "Shouldn't get here\n");
1063
  return 0;
1064
}
1065

1066
//------------------------------------------------------------------------------
1067
uint8_t
1068
get_rel8_dl_cqi_pmi_size(UE_sched_ctrl_t *sched_ctl,
1069
                         int CC_idP,
1070
                         COMMON_channels_t *cc,
1071
                         uint8_t tmode,
1072
                         struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic)
1073
//------------------------------------------------------------------------------
1074
{
1075 1076 1077 1078
  int no_pmi = 0;
  //    Ltab[6] = {0,log2(15/4/2),log2(25/4/2),log2(50/6/3),log2(75/8/4),log2(100/8/4)};
  uint8_t Ltab[6] = { 0, 1, 2, 2, 2, 2 };
  uint8_t ri = sched_ctl->periodic_ri_received[CC_idP];
1079 1080 1081
  AssertFatal(cqi_ReportPeriodic != NULL, "cqi_ReportPeriodic is null!\n");
  AssertFatal(cqi_ReportPeriodic->present != LTE_CQI_ReportPeriodic_PR_NOTHING, "cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_NOTHING!\n");
  AssertFatal(cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present != LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING,
1082
              "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n");
1083 1084

  switch (tmode) {
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094
    case 1:
    case 2:
    case 5:
    case 6:
    case 7:
      no_pmi = 1;
      break;

    default:
      no_pmi = 0;
1095
      break;
1096 1097
  }

1098
  if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI ||
1099
      sched_ctl->feedback_cnt[CC_idP] == 0) {
1100
    // send wideband report every opportunity if wideband reporting mode is selected, else every H opportunities
1101
    if (no_pmi == 1) return 4;
frtabu's avatar
frtabu committed
1102

1103
    if (cc->p_eNB == 2 && ri == 1) return 6;
frtabu's avatar
frtabu committed
1104

1105
    if (cc->p_eNB == 2 && ri == 2) return 8;
frtabu's avatar
frtabu committed
1106

1107
    if (cc->p_eNB == 4 && ri == 1) return 8;
frtabu's avatar
frtabu committed
1108

1109
    if (cc->p_eNB == 4 && ri == 2) return 11;
frtabu's avatar
frtabu committed
1110

1111
    AssertFatal(1 == 0, "illegal combination p %d, ri %d, no_pmi %d\n",
1112 1113
                cc->p_eNB,
                ri,
1114
                no_pmi);
1115
  } else if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) {
1116
    if (no_pmi == 1 || ri == 1) return (4 + Ltab[cc->mib->message.dl_Bandwidth]);
frtabu's avatar
frtabu committed
1117

1118
    return (7 + Ltab[cc->mib->message.dl_Bandwidth]);
1119 1120
  }

1121
  AssertFatal(1 == 0, "Shouldn't get here : cqi_ReportPeriodic->present %d\n",
1122
              cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present);
1123
  return 0;
1124 1125
}

1126
//------------------------------------------------------------------------------
1127
void
1128
fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t *dl_config_pdu,
1129 1130 1131 1132 1133 1134 1135 1136 1137
                     uint8_t                       aggregation_level,
                     uint16_t                      rnti,
                     uint8_t                       rnti_type,
                     uint8_t                       harq_process,
                     uint8_t                       tpc,
                     uint16_t                      resource_block_coding,
                     uint8_t                       mcs,
                     uint8_t                       ndi,
                     uint8_t                       rv,
1138
                     uint8_t                       vrb_flag)
1139
//------------------------------------------------------------------------------
1140
{
1141
  memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
1142 1143 1144 1145 1146 1147 1148
  dl_config_pdu->pdu_type                                                          = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
  dl_config_pdu->pdu_size                                                          = (uint8_t) (2 + sizeof(nfapi_dl_config_dci_dl_pdu));
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag                                 = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.dci_format                             = NFAPI_DL_DCI_FORMAT_1A;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level                      = aggregation_level;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti                                   = rnti;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type                              = rnti_type;
1149
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power                     = 6000;  // equal to RS power
1150 1151 1152 1153 1154 1155 1156
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.harq_process                           = harq_process;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tpc                                    = tpc;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.resource_block_coding                  = resource_block_coding;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.mcs_1                                  = mcs;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.new_data_indicator_1                   = ndi;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.redundancy_version_1                   = rv;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.virtual_resource_block_assignment_flag = vrb_flag;
1157
  return;
1158 1159
}

1160
//------------------------------------------------------------------------------
1161
void
1162 1163
program_dlsch_acknak(module_id_t module_idP,
                     int CC_idP,
Stefan's avatar
Stefan committed
1164
                     int UE_idP,
1165
                     frame_t frameP,
Stefan's avatar
Stefan committed
1166
                     sub_frame_t subframeP,
1167
                     uint8_t cce_idx)
1168
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1169
{
1170 1171 1172 1173 1174 1175 1176 1177 1178
  eNB_MAC_INST                           *eNB                         = RC.mac[module_idP];
  COMMON_channels_t                      *cc                          = eNB->common_channels;
  UE_list_t                              *UE_list                     = &eNB->UE_list;
  rnti_t                                 rnti                         = UE_RNTI(module_idP, UE_idP);
  nfapi_ul_config_request_body_t         *ul_req;
  nfapi_ul_config_request_pdu_t          *ul_config_pdu;
  int                                    use_simultaneous_pucch_pusch = 0;
  nfapi_ul_config_ulsch_harq_information *ulsch_harq_information      = NULL;
  nfapi_ul_config_harq_information       *harq_information            = NULL;
Stefan's avatar
Stefan committed
1179
  struct LTE_PhysicalConfigDedicated__ext2 *ext2 = UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2;
frtabu's avatar
frtabu committed
1180

1181 1182
  if (ext2 &&
      ext2->pucch_ConfigDedicated_v1020 &&
Stefan's avatar
Stefan committed
1183 1184
      ext2->pucch_ConfigDedicated_v1020->simultaneousPUCCH_PUSCH_r10 &&
      *ext2->pucch_ConfigDedicated_v1020->simultaneousPUCCH_PUSCH_r10 == LTE_PUCCH_ConfigDedicated_v1020__simultaneousPUCCH_PUSCH_r10_true)
1185
    use_simultaneous_pucch_pusch = 1;
Cedric Roux's avatar
Cedric Roux committed
1186

1187 1188
  // pucch1 and pusch feedback is similar, namely in n+k subframes from now
  // This is used in the following "if/else" condition to check if there isn't or is already an UL grant in n+k
1189
  int16_t ul_absSF = get_pucch1_absSF(&cc[CC_idP],
1190
                                      subframeP + (10 * frameP));
1191

1192 1193 1194
  if ((ul_config_pdu = has_ul_grant(module_idP,
                                    CC_idP,
                                    ul_absSF,
1195
                                    rnti)) == NULL) {
1196 1197
    // no UL grant so
    // Program ACK/NAK alone Format 1a/b or 3
Stefan's avatar
Stefan committed
1198
    ul_req = &eNB->UL_req_tmp[CC_idP][ul_absSF % 10].ul_config_request_body;
1199 1200 1201
    ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
    // Do PUCCH
    fill_nfapi_uci_acknak(module_idP,
1202
                          CC_idP,
1203 1204
                          rnti,
                          subframeP + (10 * frameP),
1205
                          cce_idx);
1206 1207 1208 1209 1210 1211
  } else {
    /* there is already an existing UL grant so update it if needed
     * on top of some other UL resource (PUSCH,combined SR/CQI/HARQ on PUCCH, etc)
     */
    switch (ul_config_pdu->pdu_type) {
      /* [ulsch] to [ulsch + harq] or [ulsch + harq on pucch] */
1212 1213 1214
      case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE:
        if (use_simultaneous_pucch_pusch == 1) {
          // Convert it to an NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE
Stefan's avatar
Stefan committed
1215
          harq_information = &ul_config_pdu->ulsch_uci_harq_pdu.harq_information;
1216
          ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE;
Stefan's avatar
Stefan committed
1217
          LOG_D(MAC, "Frame %d, Subframe %d: Switched UCI HARQ to ULSCH UCI HARQ\n",
1218
                frameP,
Stefan's avatar
Stefan committed
1219
                subframeP);
1220 1221
        } else {
          // Convert it to an NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE
Stefan's avatar
Stefan committed
1222
          ulsch_harq_information = &ul_config_pdu->ulsch_harq_pdu.harq_information;
1223
          ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE;
Stefan's avatar
Stefan committed
1224 1225 1226 1227 1228 1229
          ul_config_pdu->ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag
            = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG;
          ul_config_pdu->ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0; // last symbol not punctured
          ul_config_pdu->ulsch_harq_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks
            = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks;  // we don't change the number of resource blocks across retransmissions yet
          LOG_D(MAC,"Frame %d, Subframe %d: Switched UCI HARQ to ULSCH HARQ\n",
1230
                frameP,
Stefan's avatar
Stefan committed
1231
                subframeP);
1232 1233 1234 1235 1236
        }

        break;

      case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE:
Stefan's avatar
Stefan committed
1237
        AssertFatal(use_simultaneous_pucch_pusch == 0, "Cannot be NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE, simultaneous_pucch_pusch is active");
1238 1239 1240
        break;

      case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE:
Stefan's avatar
Stefan committed
1241
        AssertFatal(use_simultaneous_pucch_pusch == 1, "Cannot be NFAPI_UL_CONFIG_ULSCH_UCI_PDU_TYPE, simultaneous_pucch_pusch is inactive\n");
1242
        break;
1243 1244 1245

      /* [ulsch + cqi] to [ulsch + cqi + harq] */

1246 1247
      case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE:
        // Convert it to an NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE
Stefan's avatar
Stefan committed
1248
        ulsch_harq_information = &ul_config_pdu->ulsch_cqi_harq_ri_pdu.harq_information;
1249 1250 1251 1252 1253 1254 1255
        ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE;
        /* TODO: check this - when converting from nfapi_ul_config_ulsch_cqi_ri_pdu to
         * nfapi_ul_config_ulsch_cqi_harq_ri_pdu, shouldn't we copy initial_transmission_parameters
         * from the one to the other?
         * Those two types are not compatible. 'initial_transmission_parameters' is not at the
         * place in both.
         */
Stefan's avatar
Stefan committed
1256 1257 1258 1259 1260
        ul_config_pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.tl.tag
          = NFAPI_UL_CONFIG_REQUEST_INITIAL_TRANSMISSION_PARAMETERS_REL8_TAG;
        ul_config_pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.n_srs_initial = 0;  // last symbol not punctured
        ul_config_pdu->ulsch_cqi_harq_ri_pdu.initial_transmission_parameters.initial_transmission_parameters_rel8.initial_number_of_resource_blocks
          = ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks; // we don't change the number of resource blocks across retransmissions yet
1261 1262 1263
        break;

      case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE:
1264
        AssertFatal(use_simultaneous_pucch_pusch == 0, "Cannot be NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE, simultaneous_pucch_pusch is active\n");
1265
        break;
1266 1267 1268

      /* [ulsch + cqi on pucch] to [ulsch + cqi on pucch + harq on pucch] */

1269 1270
      case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE:
        // convert it to an NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE
Stefan's avatar
Stefan committed
1271
        harq_information = &ul_config_pdu->ulsch_csi_uci_harq_pdu.harq_information;
1272 1273 1274 1275
        ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE;
        break;

      case NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE:
1276
        AssertFatal(use_simultaneous_pucch_pusch == 1, "Cannot be NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE, simultaneous_pucch_pusch is inactive\n");
1277
        break;
1278 1279 1280

      /* [sr] to [sr + harq] */

1281 1282 1283
      case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE:
        // convert to NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE
        ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
Stefan's avatar
Stefan committed
1284
        harq_information = &ul_config_pdu->uci_sr_harq_pdu.harq_information;
1285 1286 1287 1288 1289 1290
        break;

      case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE:
        /* nothing to do */
        break;

1291
      /* [cqi] to [cqi + harq] */
1292 1293 1294 1295 1296 1297 1298 1299 1300 1301
      case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE:
        // convert to NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE
        ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE;
        harq_information = &ul_config_pdu->uci_cqi_harq_pdu.harq_information;
        break;

      case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE:
        /* nothing to do */
        break;

1302
      /* [cqi + sr] to [cqr + sr + harq] */
1303 1304 1305 1306 1307 1308 1309 1310 1311
      case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE:
        // convert to NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE
        ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE;
        harq_information = &ul_config_pdu->uci_cqi_sr_harq_pdu.harq_information;
        break;

      case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE:
        /* nothing to do */
        break;
1312
    }
1313
  }
Cedric Roux's avatar
Cedric Roux committed
1314

Stefan's avatar
Stefan committed
1315
  if (ulsch_harq_information) {
1316 1317 1318 1319
    fill_nfapi_ulsch_harq_information(module_idP,
                                      CC_idP,
                                      rnti,
                                      ulsch_harq_information,
1320
                                      subframeP);
Stefan's avatar
Stefan committed
1321
  }
frtabu's avatar
frtabu committed
1322

Stefan's avatar
Stefan committed
1323
  if (harq_information) {
1324 1325 1326 1327
    fill_nfapi_harq_information(module_idP,
                                CC_idP,
                                rnti,
                                harq_information,
1328
                                cce_idx);
Stefan's avatar
Stefan committed
1329
  }
frtabu's avatar
frtabu committed
1330

1331
  return;
1332 1333
}

1334
//------------------------------------------------------------------------------
1335 1336 1337
uint8_t
get_V_UL_DAI(module_id_t module_idP,
             int CC_idP,
1338
             uint16_t rntiP,
1339
             sub_frame_t subframeP)
1340
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1341
{
1342
  nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_idP]->HI_DCI0_req[CC_idP][subframeP].hi_dci0_request_body;
1343 1344 1345
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu  = &HI_DCI0_req->hi_dci0_pdu_list[0];

  for (int i = 0; i < HI_DCI0_req->number_of_dci; i++) {
1346 1347 1348 1349
    if (hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE &&
        hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP) {
      return hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.dl_assignment_index;
    }
1350
  }
1351

1352
  return 4;     // this is rule from Section 7.3 in 36.213
1353
}
1354

1355
//------------------------------------------------------------------------------
1356
void
1357
fill_nfapi_ulsch_harq_information(module_id_t                            module_idP,
1358 1359 1360
                                  int                                    CC_idP,
                                  uint16_t                               rntiP,
                                  nfapi_ul_config_ulsch_harq_information *harq_information,
1361
                                  sub_frame_t                            subframeP)
1362
//------------------------------------------------------------------------------
1363 1364 1365 1366 1367
{
  eNB_MAC_INST *eNB     = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
  UE_list_t *UE_list    = &eNB->UE_list;
  int UE_id = find_UE_id(module_idP, rntiP);
frtabu's avatar
frtabu committed
1368
  nfapi_ul_config_ulsch_harq_information_rel10_t *harq_information_rel10 = &harq_information->harq_information_rel10;
1369 1370
  AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n");
  AssertFatal(UE_list != NULL, "UE_list is null\n");
Stefan's avatar
Stefan committed
1371
  LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated;
1372
  AssertFatal(physicalConfigDedicated != NULL, "physicalConfigDedicated for rnti %x is null\n",
1373
              rntiP);
1374
  struct LTE_PUSCH_ConfigDedicated *puschConfigDedicated = physicalConfigDedicated->pusch_ConfigDedicated;
Stefan's avatar
Stefan committed
1375 1376
  AssertFatal(puschConfigDedicated != NULL, "physicalConfigDedicated->puschConfigDedicated for rnti %x is null\n",
              rntiP);
1377 1378
  harq_information_rel10->delta_offset_harq = puschConfigDedicated->betaOffset_ACK_Index;
  harq_information_rel10->tl.tag = NFAPI_UL_CONFIG_REQUEST_ULSCH_HARQ_INFORMATION_REL10_TAG;
Stefan's avatar
Stefan committed
1379 1380 1381 1382 1383
  struct LTE_PUCCH_ConfigDedicated *pucch_ConfigDedicated = physicalConfigDedicated->pucch_ConfigDedicated;
  AssertFatal(pucch_ConfigDedicated != NULL, "pucch_ConfigDedicated is null!\n");

  if (pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL &&
      *pucch_ConfigDedicated->tdd_AckNackFeedbackMode == LTE_PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)
1384
    harq_information_rel10->ack_nack_mode = 1; // multiplexing
1385
  else
1386
    harq_information_rel10->ack_nack_mode = 0; // bundling
1387 1388

  switch (get_tmode(module_idP, CC_idP, UE_id)) {
1389 1390 1391 1392 1393 1394
    case 1:
    case 2:
    case 5:
    case 6:
    case 7:
      if (cc->tdd_Config == NULL) // FDD
1395
        harq_information_rel10->harq_size = 1;
1396
      else {
1397
        if (harq_information_rel10->ack_nack_mode == 1)
1398
          harq_information_rel10->harq_size = get_V_UL_DAI(module_idP,
frtabu's avatar
frtabu committed
1399 1400 1401
                                              CC_idP,
                                              rntiP,
                                              subframeP);
1402
        else
1403
          harq_information_rel10->harq_size = 1;
1404
      }
1405

1406 1407 1408 1409
      break;

    default:      // for any other TM we need 2 bits harq
      if (cc->tdd_Config == NULL) {
1410
        harq_information_rel10->harq_size = 2;
1411
      } else {
1412
        if (harq_information_rel10->ack_nack_mode == 1)
1413
          harq_information_rel10->harq_size = get_V_UL_DAI(module_idP,
frtabu's avatar
frtabu committed
1414 1415 1416
                                              CC_idP,
                                              rntiP,
                                              subframeP);
1417
        else
1418
          harq_information_rel10->harq_size = 2;
1419
      }
1420

1421 1422
      break;
  }       // get Tmode
frtabu's avatar
frtabu committed
1423

1424
  return;
1425 1426
}

1427
//------------------------------------------------------------------------------
1428
uint8_t
1429 1430 1431 1432 1433 1434 1435
Np[6][4] = {
  {0, 1, 3, 5},
  {0, 3, 8, 13},
  {0, 5, 13, 22},
  {0, 11, 27, 44},
  {0, 16, 41, 66},
  {0, 22, 55, 88}
1436
};
1437
//------------------------------------------------------------------------------
1438 1439

// This is part of the PUCCH allocation procedure (see Section 10.1 36.213)
1440
//------------------------------------------------------------------------------
1441
uint16_t
1442 1443
getNp(int dl_Bandwidth,
      uint8_t nCCE,
1444
      uint8_t plus1)
1445
//------------------------------------------------------------------------------
1446
{
1447
  AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth %d>5\n", dl_Bandwidth);
1448

1449
  if (nCCE >= Np[dl_Bandwidth][2]) {
frtabu's avatar
frtabu committed
1450
    return(Np[dl_Bandwidth][2+plus1]);
1451
  }
frtabu's avatar
frtabu committed
1452 1453

  if (nCCE >= Np[dl_Bandwidth][1]) {
1454
    return(Np[dl_Bandwidth][1+plus1]);
1455
  }
frtabu's avatar
frtabu committed
1456

1457
  return(Np[dl_Bandwidth][0+plus1]);
1458 1459
}

1460
//------------------------------------------------------------------------------
1461
void
1462
fill_nfapi_harq_information(module_id_t                      module_idP,
1463 1464 1465
                            int                              CC_idP,
                            uint16_t                         rntiP,
                            nfapi_ul_config_harq_information *harq_information,
1466
                            uint8_t                          cce_idxP)
1467
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1468
{
1469 1470 1471
  eNB_MAC_INST *eNB     = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
  UE_list_t *UE_list    = &eNB->UE_list;
1472
  int UE_id = find_UE_id(module_idP,
1473
                         rntiP);
1474 1475 1476 1477
  AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n");
  AssertFatal(UE_list != NULL, "UE_list is null\n");
  harq_information->harq_information_rel11.tl.tag        = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG;
  harq_information->harq_information_rel11.num_ant_ports = 1;
Stefan's avatar
Stefan committed
1478 1479
  LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated;
  struct LTE_PUCCH_ConfigDedicated *pucch_ConfigDedicated = NULL;
frtabu's avatar
frtabu committed
1480

Stefan's avatar
Stefan committed
1481
  if (physicalConfigDedicated != NULL) pucch_ConfigDedicated = physicalConfigDedicated->pucch_ConfigDedicated;
1482

1483 1484
  switch (get_tmode(module_idP,
                    CC_idP,
1485
                    UE_id)) {
1486 1487 1488 1489 1490 1491 1492 1493
    case 1:
    case 2:
    case 5:
    case 6:
    case 7:
      if (cc->tdd_Config != NULL) {
        //      AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated != NULL,
        //      "pucch_ConfigDedicated is null for TDD!\n");
Stefan's avatar
Stefan committed
1494 1495 1496
        if (physicalConfigDedicated != NULL && pucch_ConfigDedicated != NULL &&
            pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL &&
            *pucch_ConfigDedicated->tdd_AckNackFeedbackMode == LTE_PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing) {
1497 1498 1499 1500 1501 1502 1503 1504
          harq_information->harq_information_rel10_tdd.harq_size             = 2;        // 2-bit ACK/NAK
          harq_information->harq_information_rel10_tdd.ack_nack_mode         = 1;        // multiplexing
        } else {
          harq_information->harq_information_rel10_tdd.harq_size             = 1;        // 1-bit ACK/NAK
          harq_information->harq_information_rel10_tdd.ack_nack_mode         = 0;        // bundling
        }

        harq_information->harq_information_rel10_tdd.tl.tag                    = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG;
1505
        harq_information->harq_information_rel10_tdd.n_pucch_1_0
Stefan's avatar
Stefan committed
1506
          = getNp(cc->mib->message.dl_Bandwidth, cce_idxP, 0) + cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP;
1507
        harq_information->harq_information_rel10_tdd.number_of_pucch_resources = 1;
1508
      } else {
1509 1510 1511 1512
        harq_information->harq_information_rel9_fdd.tl.tag                     = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG;
        harq_information->harq_information_rel9_fdd.number_of_pucch_resources  = 1;
        harq_information->harq_information_rel9_fdd.harq_size                  = 1; // 1-bit ACK/NAK
        harq_information->harq_information_rel9_fdd.n_pucch_1_0                = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP;
1513
      }
1514 1515 1516 1517 1518

      break;

    default:      // for any other TM we need 2 bits harq
      if (cc->tdd_Config != NULL) {
Stefan's avatar
Stefan committed
1519
        AssertFatal(pucch_ConfigDedicated != NULL, "pucch_ConfigDedicated is null for TDD!\n");
1520

Stefan's avatar
Stefan committed
1521 1522
        if (pucch_ConfigDedicated->tdd_AckNackFeedbackMode != NULL &&
            *pucch_ConfigDedicated->tdd_AckNackFeedbackMode == LTE_PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing) {
1523 1524 1525 1526 1527 1528 1529 1530 1531
          harq_information->harq_information_rel10_tdd.ack_nack_mode            = 1;  // multiplexing
        } else {
          harq_information->harq_information_rel10_tdd.ack_nack_mode            = 0;  // bundling
        }

        harq_information->harq_information_rel10_tdd.tl.tag                     = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL10_TDD_TAG;
        harq_information->harq_information_rel10_tdd.harq_size                  = 2;
        harq_information->harq_information_rel10_tdd.n_pucch_1_0                = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP;
        harq_information->harq_information_rel10_tdd.number_of_pucch_resources  = 1;
1532
      } else {
1533 1534 1535 1536 1537
        harq_information->harq_information_rel9_fdd.tl.tag                      = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL9_FDD_TAG;
        harq_information->harq_information_rel9_fdd.number_of_pucch_resources   = 1;
        harq_information->harq_information_rel9_fdd.ack_nack_mode               = 0;  // 1a/b
        harq_information->harq_information_rel9_fdd.harq_size                   = 2;
        harq_information->harq_information_rel9_fdd.n_pucch_1_0                 = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP;
1538
      }
1539 1540 1541

      break;
  }       // get Tmode
frtabu's avatar
frtabu committed
1542

Stefan's avatar
Stefan committed
1543
  return;
1544
}
Cedric Roux's avatar
Cedric Roux committed
1545

1546
//------------------------------------------------------------------------------
1547 1548
uint16_t
fill_nfapi_uci_acknak(module_id_t module_idP,
1549 1550 1551
                      int         CC_idP,
                      uint16_t    rntiP,
                      uint16_t    absSFP,
1552
                      uint8_t     cce_idxP)
1553
//------------------------------------------------------------------------------
1554 1555 1556 1557 1558 1559 1560 1561 1562 1563 1564
{
  eNB_MAC_INST                   *eNB           = RC.mac[module_idP];
  COMMON_channels_t              *cc            = &eNB->common_channels[CC_idP];
  int                            ackNAK_absSF   = get_pucch1_absSF(cc, absSFP);
  nfapi_ul_config_request_t      *ul_req        = &eNB->UL_req_tmp[CC_idP][ackNAK_absSF % 10];
  nfapi_ul_config_request_body_t *ul_req_body   = &ul_req->ul_config_request_body;
  nfapi_ul_config_request_pdu_t  *ul_config_pdu = &ul_req_body->ul_config_pdu_list[ul_req_body->number_of_pdus];
  memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
  ul_config_pdu->pdu_type                                               = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE;
  ul_config_pdu->pdu_size                                               = (uint8_t) (2 + sizeof(nfapi_ul_config_uci_harq_pdu));
  ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.tl.tag = NFAPI_UL_CONFIG_REQUEST_UE_INFORMATION_REL8_TAG;
1565
  ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.handle = 0;  // don't know how to use this
1566
  ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti   = rntiP;
1567
  fill_nfapi_harq_information(module_idP,
Stefan's avatar
Stefan committed
1568
                              CC_idP,
1569
                              rntiP,
1570
                              &ul_config_pdu->uci_harq_pdu.harq_information,
Stefan's avatar
Stefan committed
1571
                              cce_idxP);
1572
  LOG_D(MAC, "Filled in UCI HARQ request for rnti %x SF %d.%d acknakSF %d.%d, cce_idxP %d-> n1_pucch %d\n",
1573 1574 1575
        rntiP,
        absSFP / 10,
        absSFP % 10,
Stefan's avatar
Stefan committed
1576
        ackNAK_absSF / 10,
1577
        ackNAK_absSF % 10,
Stefan's avatar
Stefan committed
1578
        cce_idxP,
Stefan's avatar
Stefan committed
1579
        ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel9_fdd.n_pucch_1_0);
1580 1581 1582 1583 1584
  ul_req_body->number_of_pdus++;
  ul_req_body->tl.tag       = NFAPI_UL_CONFIG_REQUEST_BODY_TAG;
  ul_req->header.message_id = NFAPI_UL_CONFIG_REQUEST;
  ul_req->sfn_sf            = (ackNAK_absSF/10) << 4 | ackNAK_absSF%10;
  return (((ackNAK_absSF / 10) << 4) + (ackNAK_absSF % 10));
1585
}
1586

1587 1588 1589 1590 1591 1592 1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605 1606 1607 1608 1609 1610 1611 1612 1613 1614 1615 1616 1617 1618 1619
//------------------------------------------------------------------------------

void
fill_nfapi_mch_config(nfapi_dl_config_request_body_t *dl_req,
                  uint16_t length,
                  uint16_t pdu_index,
                  uint16_t rnti,
                  uint8_t resource_allocation_type,
                  uint16_t resource_block_coding,
                  uint8_t modulation,
                  uint16_t transmission_power,
                  uint8_t mbsfn_area_id){
  nfapi_dl_config_request_pdu_t *dl_config_pdu =
    &dl_req->dl_config_pdu_list[dl_req->number_pdu];
  memset((void *) dl_config_pdu, 0,
         sizeof(nfapi_dl_config_request_pdu_t));
  dl_config_pdu->pdu_type                                                    = NFAPI_DL_CONFIG_MCH_PDU_TYPE;
  dl_config_pdu->pdu_size                                                    = (uint8_t) (2 + sizeof(nfapi_dl_config_mch_pdu));
  dl_config_pdu->mch_pdu.mch_pdu_rel8.tl.tag                                 = NFAPI_DL_CONFIG_REQUEST_MCH_PDU_REL8_TAG;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.length                                 = length;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.pdu_index                              = pdu_index;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.rnti                                   = rnti;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.resource_allocation_type               = resource_allocation_type;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.resource_block_coding                  = resource_block_coding;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.modulation                             = modulation;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.transmission_power                     = transmission_power;
  dl_config_pdu->mch_pdu.mch_pdu_rel8.mbsfn_area_id                          = mbsfn_area_id;
  dl_req->number_pdu++;
}

//------------------------------------------------------------------------------


1620
//------------------------------------------------------------------------------
1621
void
1622 1623 1624 1625 1626 1627 1628 1629 1630 1631 1632 1633 1634 1635 1636 1637
fill_nfapi_dlsch_config(eNB_MAC_INST *eNB,
                        nfapi_dl_config_request_body_t *dl_req,
                        uint16_t length,
                        int16_t pdu_index,
                        uint16_t rnti,
                        uint8_t resource_allocation_type,
                        uint8_t
                        virtual_resource_block_assignment_flag,
                        uint16_t resource_block_coding,
                        uint8_t modulation,
                        uint8_t redundancy_version,
                        uint8_t transport_blocks,
                        uint8_t transport_block_to_codeword_swap_flag,
                        uint8_t transmission_scheme,
                        uint8_t number_of_layers,
                        uint8_t number_of_subbands,
Stefan's avatar
Stefan committed
1638
                        // uint8_t codebook_index,
1639 1640 1641 1642 1643 1644 1645
                        uint8_t ue_category_capacity,
                        uint8_t pa,
                        uint8_t delta_power_offset_index,
                        uint8_t ngap,
                        uint8_t nprb,
                        uint8_t transmission_mode,
                        uint8_t num_bf_prb_per_subband,
1646
                        uint8_t num_bf_vector)
1647
//------------------------------------------------------------------------------
1648
{
Stefan's avatar
Stefan committed
1649
  nfapi_dl_config_request_pdu_t *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
1650
  memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664 1665 1666
  dl_config_pdu->pdu_type                                                        = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
  dl_config_pdu->pdu_size                                                        = (uint8_t) (2 + sizeof(nfapi_dl_config_dlsch_pdu));
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag                                 = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.length                                 = length;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pdu_index                              = pdu_index;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti                                   = rnti;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_allocation_type               = resource_allocation_type;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = virtual_resource_block_assignment_flag;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding                  = resource_block_coding;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation                             = modulation;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.redundancy_version                     = redundancy_version;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_blocks                       = transport_blocks;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transport_block_to_codeword_swap_flag  = transport_block_to_codeword_swap_flag;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_scheme                    = transmission_scheme;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_layers                       = number_of_layers;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.number_of_subbands                     = number_of_subbands;
Stefan's avatar
Stefan committed
1667
  // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = codebook_index;
1668 1669 1670 1671 1672 1673 1674 1675 1676
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity                   = ue_category_capacity;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa                                     = pa;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index               = delta_power_offset_index;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap                                   = ngap;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb                                   = nprb;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode                      = transmission_mode;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband                 = num_bf_prb_per_subband;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = num_bf_vector;
  dl_req->number_pdu++;
1677
  return;
1678
}
1679

1680
//------------------------------------------------------------------------------
1681
uint16_t
1682
fill_nfapi_tx_req(nfapi_tx_request_body_t *tx_req_body,
1683 1684 1685
                  uint16_t                absSF,
                  uint16_t                pdu_length,
                  int16_t                 pdu_index,
1686
                  uint8_t                 *pdu)
1687
//------------------------------------------------------------------------------
1688
{
1689 1690
  nfapi_tx_request_pdu_t *TX_req = &tx_req_body->tx_pdu_list[tx_req_body->number_of_pdus];
  LOG_D(MAC, "Filling TX_req %d for pdu length %d\n",
1691
        tx_req_body->number_of_pdus,
1692
        pdu_length);
1693 1694 1695 1696 1697 1698 1699 1700
  TX_req->pdu_length                 = pdu_length;
  TX_req->pdu_index                  = pdu_index;
  TX_req->num_segments               = 1;
  TX_req->segments[0].segment_length = pdu_length;
  TX_req->segments[0].segment_data   = pdu;
  tx_req_body->tl.tag                = NFAPI_TX_REQUEST_BODY_TAG;
  tx_req_body->number_of_pdus++;
  return (((absSF / 10) << 4) + (absSF % 10));
1701
}
1702

1703
//------------------------------------------------------------------------------
1704
void
1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720 1721 1722 1723
fill_nfapi_ulsch_config_request_rel8(nfapi_ul_config_request_pdu_t *ul_config_pdu,
                                     uint8_t                        cqi_req,
                                     COMMON_channels_t              *cc,
                                     struct LTE_PhysicalConfigDedicated *physicalConfigDedicated,
                                     uint8_t                        tmode,
                                     uint32_t                       handle,
                                     uint16_t                       rnti,
                                     uint8_t                        resource_block_start,
                                     uint8_t                        number_of_resource_blocks,
                                     uint8_t                        mcs,
                                     uint8_t                        cyclic_shift_2_for_drms,
                                     uint8_t                        frequency_hopping_enabled_flag,
                                     uint8_t                        frequency_hopping_bits,
                                     uint8_t                        new_data_indication,
                                     uint8_t                        redundancy_version,
                                     uint8_t                        harq_process_number,
                                     uint8_t                        ul_tx_mode,
                                     uint8_t                        current_tx_nb,
                                     uint8_t                        n_srs,
1724
                                     uint16_t                       size)
1725
//------------------------------------------------------------------------------
1726
{
1727 1728
  uint8_t ri_size = 0;
  memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
1729 1730 1731 1732 1733 1734 1735
  ul_config_pdu->pdu_type                                                    = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE;
  ul_config_pdu->pdu_size                                                    = (uint8_t) (2 + sizeof(nfapi_ul_config_ulsch_pdu));
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.tl.tag                             = NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL8_TAG;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.handle                             = handle;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti                               = rnti;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.resource_block_start               = resource_block_start;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.number_of_resource_blocks          = number_of_resource_blocks;
1736

1737 1738
  if (mcs < 11)      ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 2;
  else if (mcs < 21) ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 4;
1739 1740
  else if(mcs < 29)  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 6;
  else               ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type = 0;
1741

1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756 1757 1758 1759
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.cyclic_shift_2_for_drms            = cyclic_shift_2_for_drms;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_enabled_flag     = frequency_hopping_enabled_flag;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.frequency_hopping_bits             = frequency_hopping_bits;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.new_data_indication                = new_data_indication;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.redundancy_version                 = redundancy_version;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.harq_process_number                = harq_process_number;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.ul_tx_mode                         = ul_tx_mode;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.current_tx_nb                      = current_tx_nb;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.n_srs                              = n_srs;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.size                               = size;

  if (cqi_req == 1) {
    // Add CQI portion
    ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE;
    ul_config_pdu->pdu_size = (uint8_t) (2 + sizeof(nfapi_ul_config_ulsch_cqi_ri_pdu));
    ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.tl.tag = NFAPI_UL_CONFIG_REQUEST_CQI_RI_INFORMATION_REL9_TAG;
    ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.report_type = 1;
    ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.number_of_cc = 1;
1760 1761
    LOG_D(MAC, "report_type %d\n",
          ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.report_type);
1762

1763 1764 1765
    if (cc->p_eNB <= 2 && (tmode == 3 || tmode == 4 || tmode == 8 || tmode == 9 || tmode == 10)) ri_size = 1;
    else if (cc->p_eNB <= 2) ri_size = 0;
    else if (cc->p_eNB == 4) ri_size = 2;
1766

frtabu's avatar
frtabu committed
1767
    ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = ri_size;
1768 1769 1770
    AssertFatal(physicalConfigDedicated->cqi_ReportConfig != NULL,"physicalConfigDedicated->cqi_ReportConfig is null!\n");
    AssertFatal(physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic != NULL,"physicalConfigDedicated->cqi_ReportModeAperiodic is null!\n");
    AssertFatal(physicalConfigDedicated->pusch_ConfigDedicated != NULL,"physicalConfigDedicated->puschConfigDedicated is null!\n");
1771 1772
    nfapi_ul_config_cqi_ri_information_rel9_t *ri_information = &ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9;
    int max_ri = (1 << ri_information->aperiodic_cqi_pmi_ri_report.cc[0].ri_size);
frtabu's avatar
frtabu committed
1773

1774
    for (int ri = 0; ri < max_ri; ri++) {
1775
      ri_information->aperiodic_cqi_pmi_ri_report.cc[0].dl_cqi_pmi_size[ri]
1776 1777 1778 1779
        = get_dl_cqi_pmi_size_pusch(cc,
                                    tmode,
                                    1 + ri,
                                    physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic);
1780
    }
frtabu's avatar
frtabu committed
1781

1782 1783
    ri_information->delta_offset_cqi = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
    ri_information->delta_offset_ri = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
1784
  }
frtabu's avatar
frtabu committed
1785

1786
  return;
1787 1788
}

1789
//------------------------------------------------------------------------------
1790
void
1791
fill_nfapi_ulsch_config_request_emtc(nfapi_ul_config_request_pdu_t *ul_config_pdu,
1792 1793
                                     uint8_t ue_type,
                                     uint16_t total_number_of_repetitions,
1794
                                     uint16_t repetition_number,
1795
                                     uint16_t initial_transmission_sf_io)
1796
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1797
{
1798 1799 1800 1801 1802 1803
  // Re13 fields
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.tl.tag                      = NFAPI_UL_CONFIG_REQUEST_ULSCH_PDU_REL13_TAG;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.ue_type                     = ue_type;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.total_number_of_repetitions = total_number_of_repetitions;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.repetition_number           = repetition_number;
  ul_config_pdu->ulsch_pdu.ulsch_pdu_rel13.initial_transmission_sf_io  = initial_transmission_sf_io;
1804
  return;
1805
}
1806

1807
//------------------------------------------------------------------------------
1808 1809
int
get_numnarrowbands(long dl_Bandwidth)
1810
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1811
{
1812 1813 1814
  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]);
1815 1816
}

1817
//------------------------------------------------------------------------------
1818 1819
int
get_numnarrowbandbits(long dl_Bandwidth)
1820
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1821
{
1822 1823 1824
  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]);
1825 1826 1827
}

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

1833
//------------------------------------------------------------------------------
1834
int
1835 1836
startSF_tdd_RA[7] = { 1, 2, 4, 5, 8, 10, 20 };
//------------------------------------------------------------------------------
1837

1838
//------------------------------------------------------------------------------
1839
int
1840 1841
mpdcch_sf_condition(eNB_MAC_INST *eNB,
                    int CC_id,
1842
                    frame_t frameP,
1843
                    sub_frame_t subframeP,
1844
                    int rmax,
1845 1846
                    MPDCCH_TYPES_t mpdcch_type,
                    int UE_id)
1847 1848 1849
//------------------------------------------------------------------------------
{
  struct LTE_PRACH_ConfigSIB_v1310 *ext4_prach = eNB->common_channels[CC_id].radioResourceConfigCommon_BR-> ext4->prach_ConfigCommon_v1310;
1850
  int T;
1851
  LTE_EPDCCH_SetConfig_r11_t *epdcch_setconfig_r11;
1852

1853
  switch (mpdcch_type) {
1854 1855 1856 1857 1858 1859 1860 1861 1862 1863 1864 1865 1866
    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
1867
      AssertFatal(ext4_prach->mpdcch_startSF_CSS_RA_r13 != NULL, "mpdcch_startSF_CSS_RA_r13 is null\n");
1868 1869 1870
      AssertFatal(rmax > 0, "rmax is 0!\b");

      if (eNB->common_channels[CC_id].tdd_Config == NULL) //FDD
1871
        T = (rmax * startSF_fdd_RA_times2[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.fdd_r13]) >> 1;
1872
      else      //TDD
1873
        T = rmax * startSF_tdd_RA[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.tdd_r13];
1874 1875 1876 1877 1878 1879 1880 1881 1882 1883

      break;

    case TYPE2A:
      AssertFatal(1 == 0, "MPDCCH Type 2A not handled yet\n");
      break;

    case TYPEUESPEC:
      epdcch_setconfig_r11 =
        eNB->UE_list.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0];
1884 1885
      AssertFatal(epdcch_setconfig_r11 != NULL, " epdcch_setconfig_r11 is null for UE specific \n");
      AssertFatal(epdcch_setconfig_r11->ext2 != NULL, " ext2 doesn't exist in epdcch config ' \n");
1886 1887

      if (eNB->common_channels[CC_id].tdd_Config == NULL) //FDD
1888
        T = (rmax * startSF_fdd_RA_times2[epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_StartSF_UESS_r13.choice.fdd_r13]) >> 1;
1889
      else      //TDD
1890
        T = rmax * startSF_tdd_RA[epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_StartSF_UESS_r13.choice.tdd_r13];
1891 1892 1893 1894

      break;

    default:
1895
      return 0;
1896
  }
1897

1898
  AssertFatal(T > 0, "T is 0!\n");
1899

1900
  if (((10 * frameP) + subframeP) % T == 0) return 1;
frtabu's avatar
frtabu committed
1901

1902
  return 0;
1903 1904
}

1905
//------------------------------------------------------------------------------
1906 1907 1908
int
narrowband_to_first_rb(COMMON_channels_t *cc,
                       int nb_index)
1909
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1910
{
1911
  switch (cc->mib->message.dl_Bandwidth) {
1912
    case 0:     // 6 PRBs, N_NB=1, i_0=0
1913
      return 0;
1914 1915

    case 3:     // 50 PRBs, N_NB=8, i_0=1
1916
      return (1 + (6 * nb_index));
1917 1918

    case 5:     // 100 PRBs, N_NB=16, i_0=2
1919
      return (2 + (6 * nb_index));
1920 1921 1922

    case 1:     // 15 PRBs  N_NB=2, i_0=1
      if (nb_index > 0)
1923
        return 1;
frtabu's avatar
frtabu committed
1924

1925
      return 0;
1926 1927 1928 1929

    case 2:     // 25 PRBs, N_NB=4, i_0=0
      if (nb_index > 1)
        return (1 + (6 * nb_index));
frtabu's avatar
frtabu committed
1930

1931
      return ((6 * nb_index));
1932 1933 1934 1935

    case 4:     // 75 PRBs, N_NB=12, i_0=1
      if (nb_index > 5)
        return (2 + (6 * nb_index));
frtabu's avatar
frtabu committed
1936

1937
      return (1 + (6 * nb_index));
1938 1939 1940 1941 1942

    default:
      AssertFatal(1 == 0, "Impossible dl_Bandwidth %d\n",
                  (int) cc->mib->message.dl_Bandwidth);
      break;
1943
  }
frtabu's avatar
frtabu committed
1944

1945
  return 0;
1946
}
1947

1948
//------------------------------------------------------------------------------
1949
void
1950
init_ue_sched_info(void)
1951
//------------------------------------------------------------------------------
1952
{
1953 1954 1955 1956
  module_id_t i, j, k;

  for (i = 0; i < NUMBER_OF_eNB_MAX; i++) {
    for (k = 0; k < MAX_NUM_CCs; k++) {
1957
      for (j = 0; j < MAX_MOBILES_PER_ENB; j++) {
1958 1959 1960 1961 1962 1963 1964 1965 1966
        // 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;
1967
      }
1968
    }
1969
  }
frtabu's avatar
frtabu committed
1970

1971
  return;
1972 1973
}

1974
//------------------------------------------------------------------------------
1975 1976 1977
unsigned char
get_ue_weight(module_id_t module_idP,
              int CC_idP,
1978
              int ue_idP)
1979
//------------------------------------------------------------------------------
1980
{
1981
  return (eNB_dlsch_info[module_idP][CC_idP][ue_idP].weight);
1982 1983
}

1984
//------------------------------------------------------------------------------
1985 1986
int
find_UE_id(module_id_t mod_idP,
1987
           rnti_t rntiP)
1988
//------------------------------------------------------------------------------
1989
{
1990 1991 1992
  int UE_id;
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;

1993
  for (UE_id = 0; UE_id < MAX_MOBILES_PER_ENB; UE_id++) {
1994
    if (UE_list->active[UE_id] == TRUE) {
1995
      if (UE_list->UE_template[UE_PCCID(mod_idP, UE_id)][UE_id].rnti == rntiP) {
1996 1997
        return UE_id;
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1998
    }
1999
  }
2000

2001
  return -1;
2002 2003
}

2004
//------------------------------------------------------------------------------
2005 2006 2007
int
find_RA_id(module_id_t mod_idP,
           int CC_idP,
2008
           rnti_t rntiP)
2009 2010
//------------------------------------------------------------------------------
{
2011 2012
  int RA_id;
  AssertFatal(RC.mac[mod_idP], "RC.mac[%d] is null\n", mod_idP);
2013
  RA_t *ra = (RA_t *) &RC.mac[mod_idP]->common_channels[CC_idP].ra[0];
2014

2015
  for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) {
2016
    LOG_D(MAC, "Checking RA_id %d for %x : state %d\n",
2017 2018
          RA_id,
          rntiP,
2019
          ra[RA_id].state);
Cedric Roux's avatar
Cedric Roux committed
2020

2021 2022
    if (ra[RA_id].state != IDLE && ra[RA_id].rnti == rntiP)
      return RA_id;
2023
  }
2024

2025
  return -1;
2026 2027
}

2028
//------------------------------------------------------------------------------
2029 2030
int
UE_num_active_CC(UE_list_t *listP,
2031
                 int ue_idP)
2032
//------------------------------------------------------------------------------
2033
{
2034
  return (listP->numactiveCCs[ue_idP]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2035
}
2036

2037
//------------------------------------------------------------------------------
2038 2039
int
UE_PCCID(module_id_t mod_idP,
2040
         int ue_idP)
2041
//------------------------------------------------------------------------------
2042
{
2043
  return (RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]);
Raymond Knopp's avatar
 
Raymond Knopp committed
2044
}
2045

2046
//------------------------------------------------------------------------------
2047 2048
rnti_t
UE_RNTI(module_id_t mod_idP,
2049
        int ue_idP)
2050
//------------------------------------------------------------------------------
2051
{
2052
  if (!RC.mac || !RC.mac[mod_idP]) return 0;
Stefan's avatar
Stefan committed
2053

2054
  rnti_t rnti = RC.mac[mod_idP]->UE_list.UE_template[UE_PCCID(mod_idP,
frtabu's avatar
frtabu committed
2055
                ue_idP)][ue_idP].rnti;
2056

2057 2058
  if (rnti > 0) {
    return (rnti);
2059
  }
2060

Robert Schmidt's avatar
Robert Schmidt committed
2061
  //LOG_D(MAC, "[eNB %d] Couldn't find RNTI for UE %d\n", mod_idP, ue_idP);
2062 2063
  //display_backtrace();
  return (NOT_A_RNTI);
2064
}
Raymond Knopp's avatar
 
Raymond Knopp committed
2065

2066
//------------------------------------------------------------------------------
2067 2068
boolean_t
is_UE_active(module_id_t mod_idP,
2069
             int ue_idP)
2070
//------------------------------------------------------------------------------
2071
{
2072
  return (RC.mac[mod_idP]->UE_list.active[ue_idP]);
2073
}
Raymond Knopp's avatar
 
Raymond Knopp committed
2074

2075
//------------------------------------------------------------------------------
2076
unsigned char
Stefan's avatar
Stefan committed
2077 2078
get_aggregation(uint8_t bw_index,
                uint8_t cqi,
2079
                uint8_t dci_fmt)
2080
//------------------------------------------------------------------------------
2081
{
2082
  unsigned char aggregation = 3;
2083

2084
  switch (dci_fmt) {
2085 2086 2087 2088 2089 2090 2091 2092 2093 2094 2095 2096 2097 2098 2099 2100 2101 2102 2103 2104 2105 2106 2107 2108 2109
    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:
Stefan's avatar
Stefan committed
2110 2111 2112
      LOG_W(MAC, "unsupported DCI format %d\n",
            dci_fmt);
      break;
2113
  }
Cedric Roux's avatar
Cedric Roux committed
2114

Stefan's avatar
Stefan committed
2115 2116 2117 2118 2119
  LOG_D(MAC, "Aggregation level %d (cqi %d, bw_index %d, format %d)\n",
        1 << aggregation,
        cqi,
        bw_index,
        dci_fmt);
2120
  return 1 << aggregation;
2121
}
Raymond Knopp's avatar
 
Raymond Knopp committed
2122

2123
//------------------------------------------------------------------------------
2124 2125 2126
/*
 * Dump the UL or DL UE_list into LOG_T(MAC)
 */
2127 2128 2129
void
dump_ue_list(UE_list_t *listP,
             int ul_flag)
2130
//------------------------------------------------------------------------------
2131
{
2132
  if (ul_flag == 0) {
2133 2134
    for (int j = listP->head; j >= 0; j = listP->next[j]) {
      LOG_T(MAC, "DL list node %d => %d\n",
2135
            j,
2136
            listP->next[j]);
2137
    }
2138
  } else {
2139 2140
    for (int j = listP->head_ul; j >= 0; j = listP->next_ul[j]) {
      LOG_T(MAC, "UL list node %d => %d\n",
2141
            j,
2142
            listP->next_ul[j]);
2143
    }
2144
  }
frtabu's avatar
frtabu committed
2145

2146
  return;
Raymond Knopp's avatar
 
Raymond Knopp committed
2147 2148
}

2149 2150 2151 2152 2153 2154 2155 2156 2157 2158 2159 2160 2161 2162 2163 2164 2165 2166 2167 2168 2169 2170 2171 2172 2173 2174 2175 2176 2177 2178 2179
//------------------------------------------------------------------------------
/*
 * Add a UE to the UL or DL UE_list listP
 */
void
add_ue_list(UE_list_t *listP, int UE_id, int ul_flag) {
  if (ul_flag == 0) {
    if (listP->head == -1) {
      listP->head = UE_id;
      listP->next[UE_id] = -1;
    } else {
      int i = listP->head;
      while (listP->next[i] >= 0)
        i = listP->next[i];
      listP->next[i] = UE_id;
      listP->next[UE_id] = -1;
    }
  } else {
    if (listP->head_ul == -1) {
      listP->head_ul = UE_id;
      listP->next_ul[UE_id] = -1;
    } else {
      int i = listP->head;
      while (listP->next_ul[i] >= 0)
        i = listP->next[i];
      listP->next_ul[i] = UE_id;
      listP->next_ul[UE_id] = -1;
    }
  }
}

2180
//------------------------------------------------------------------------------
2181 2182 2183 2184
int
add_new_ue(module_id_t mod_idP,
           int cc_idP,
           rnti_t rntiP,
2185 2186
           int harq_pidP,
           uint8_t rach_resource_type
frtabu's avatar
frtabu committed
2187
          )
2188
//------------------------------------------------------------------------------
2189 2190 2191 2192
{
  int UE_id;
  int i, j;
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
2193
  LOG_D(MAC, "[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n",
2194 2195 2196 2197
        mod_idP,
        cc_idP,
        rntiP,
        UE_list->avail,
2198
        UE_list->num_UEs);
2199

2200
  for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
2201 2202
    if (UE_list->active[i] == TRUE)
      continue;
2203

2204
    UE_id = i;
2205
    memset(&UE_list->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE));
2206 2207 2208 2209 2210 2211 2212 2213 2214
    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;
    UE_list->num_UEs++;
    UE_list->active[UE_id] = TRUE;
2215 2216 2217 2218
    add_ue_list(UE_list, UE_id, 0);
    dump_ue_list(UE_list, 0);
    add_ue_list(UE_list, UE_id, 1);
    dump_ue_list(UE_list, 1);
2219 2220
    if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ?
      UE_list->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0;
2221
    UE_list->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type;
2222
    memset((void *) &UE_list->UE_sched_ctrl[UE_id],
2223
           0,
2224
           sizeof(UE_sched_ctrl_t));
2225
    memset((void *) &UE_list->eNB_UE_stats[cc_idP][UE_id],
2226
           0,
2227
           sizeof(eNB_UE_STATS));
2228
    UE_list->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0;
2229
    /* default slice in case there was something different */
2230 2231
    UE_list->assoc_dl_slice_idx[UE_id] = 0;
    UE_list->assoc_ul_slice_idx[UE_id] = 0;
2232
    UE_list->UE_sched_ctrl[UE_id].ta_update = 31;
2233

2234
    for (j = 0; j < 8; j++) {
2235 2236
      UE_list->UE_template[cc_idP][UE_id].oldNDI[j] = 0;
      UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = 0;
2237 2238
      UE_list->UE_sched_ctrl[UE_id].round[cc_idP][j] = 8;
      UE_list->UE_sched_ctrl[UE_id].round_UL[cc_idP][j] = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2239
    }
2240

2241 2242 2243
    eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING;
    eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING;
    LOG_D(MAC, "[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",
2244 2245 2246
          mod_idP,
          UE_id,
          cc_idP,
2247
          rntiP);
2248 2249 2250
    return (UE_id);
  }

2251 2252
  // printf("MAC: cannot add new UE for rnti %x\n", rntiP);
  LOG_E(MAC, "error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
2253
  dump_ue_list(UE_list,
2254 2255
               0);
  return -1;
2256 2257
}

2258
//------------------------------------------------------------------------------
2259 2260 2261
/*
 * Remove MAC context of UE
 */
2262 2263
int
rrc_mac_remove_ue(module_id_t mod_idP,
2264
                  rnti_t rntiP)
2265
//------------------------------------------------------------------------------
2266
{
2267
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
2268 2269 2270
  int UE_id = find_UE_id(mod_idP, rntiP);
  eNB_UE_STATS *ue_stats = NULL;
  int pCC_id = -1;
2271

2272
  if (UE_id == -1) {
2273
    LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n",
2274
          rntiP);
2275
    return 0;
2276
  }
2277

2278
  pCC_id = UE_PCCID(mod_idP, UE_id);
2279 2280
  LOG_I(MAC,"Removing UE %d from Primary CC_id %d (rnti %x)\n",
        UE_id,
2281
        pCC_id,
2282
        rntiP);
2283 2284
  UE_list->active[UE_id] = FALSE;
  UE_list->num_UEs--;
2285

2286 2287
  UE_list->next[UE_id] = -1;
  UE_list->next_ul[UE_id] = -1;
2288 2289 2290 2291 2292 2293 2294 2295 2296 2297 2298 2299 2300 2301 2302 2303 2304 2305 2306 2307 2308 2309 2310 2311
  /* If present, remove UE from DL list */
  if (UE_list->head == UE_id) {
    UE_list->head = UE_list->next[UE_id];
  } else {
    int previous = prev(UE_list, UE_id, 0);

    if (previous != -1) {
      UE_list->next[previous] = UE_list->next[UE_id];
    }
  }

  /* If present, remove UE from UL list */
  if (UE_list->head_ul == UE_id) {
    UE_list->head_ul = UE_list->next_ul[UE_id];
  } else {
    int previous = prev(UE_list, UE_id, 1);

    if (previous != -1) {
      UE_list->next_ul[previous] = UE_list->next_ul[UE_id];
    }
  }

  /* Clear all remaining pending transmissions */
  memset(&UE_list->UE_template[pCC_id][UE_id],
2312 2313
         0,
         sizeof(UE_TEMPLATE));
2314 2315 2316
  ue_stats = &UE_list->eNB_UE_stats[pCC_id][UE_id];
  ue_stats->total_rbs_used = 0;
  ue_stats->total_rbs_used_retx = 0;
2317

2318
  for (int j = 0; j < NB_RB_MAX; j++ ) {
2319 2320
    ue_stats->num_pdu_tx[j] = 0;
    ue_stats->num_bytes_tx[j] = 0;
2321
  }
2322

2323 2324 2325 2326 2327
  ue_stats->num_retransmission = 0;
  ue_stats->total_sdu_bytes = 0;
  ue_stats->total_pdu_bytes = 0;
  ue_stats->total_num_pdus = 0;
  ue_stats->total_rbs_used_rx = 0;
2328

2329
  for (int j = 0; j < NB_RB_MAX; j++ ) {
2330 2331
    ue_stats->num_pdu_rx[j] = 0;
    ue_stats->num_bytes_rx[j] = 0;
2332
  }
2333

2334 2335 2336 2337
  ue_stats->num_errors_rx = 0;
  ue_stats->total_pdu_bytes_rx = 0;
  ue_stats->total_num_pdus_rx = 0;
  ue_stats->total_num_errors_rx = 0;
2338 2339
  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;
2340
  eNB_ulsch_info[mod_idP][pCC_id][UE_id].serving_num = 0;
2341 2342
  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;
2343
  eNB_dlsch_info[mod_idP][pCC_id][UE_id].serving_num = 0;
2344

2345
  // check if this has an RA process active
2346 2347
  if (find_RA_id(mod_idP,
                 pCC_id,
2348
                 rntiP) != -1) {
2349 2350 2351
    cancel_ra_proc(mod_idP,
                   pCC_id,
                   0,
2352
                   rntiP);
2353
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2354

2355
  if(rrc_release_info.num_UEs > 0) {
2356 2357 2358
    while(pthread_mutex_trylock(&rrc_release_freelist)) {
      /* spin... */
    }
2359

2360
    uint16_t release_total = 0;
2361

2362 2363
    for (uint16_t release_num = 0; release_num < NUMBER_OF_UE_MAX; release_num++) {
      if (rrc_release_info.RRC_release_ctrl[release_num].flag > 0) {
2364
        release_total++;
2365
      } else {
2366 2367
        continue;
      }
2368

2369
      if (rrc_release_info.RRC_release_ctrl[release_num].rnti == rntiP) {
2370 2371 2372 2373
        rrc_release_info.RRC_release_ctrl[release_num].flag = 0;
        rrc_release_info.num_UEs--;
        release_total--;
      }
2374

2375
      if (release_total >= rrc_release_info.num_UEs) {
2376
        break;
wujing's avatar
wujing committed
2377
      }
2378
    }
2379

2380
    pthread_mutex_unlock(&rrc_release_freelist);
2381
  }
2382

2383
  pthread_mutex_unlock(&rrc_release_freelist);
2384
  return 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2385
}
2386

2387
//------------------------------------------------------------------------------
2388 2389 2390
/*
 * Returns the previous UE_id in the scheduling list in UL or DL
 */
2391 2392 2393 2394
int
prev(UE_list_t *listP,
     int nodeP,
     int ul_flag)
2395
//------------------------------------------------------------------------------
2396
{
2397 2398
  if (ul_flag == 0) {
    if (nodeP == listP->head) {
2399
      return nodeP;
2400
    }
2401

2402
    for (int j = listP->head; j >= 0; j = listP->next[j]) {
2403
      if (listP->next[j] == nodeP) {
2404
        return j;
2405 2406 2407 2408
      }
    }
  } else {
    if (nodeP == listP->head_ul) {
2409
      return nodeP;
2410
    }
2411

2412
    for (int j = listP->head_ul; j >= 0; j = listP->next_ul[j]) {
2413
      if (listP->next_ul[j] == nodeP) {
2414
        return j;
2415
      }
2416
    }
2417
  }
2418

2419
  LOG_E(MAC, "error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n",
2420
        nodeP,
2421
        (ul_flag == 0) ? "DL" : "UL");
2422
  dump_ue_list(listP,
2423 2424
               ul_flag);
  return -1;
2425
}
Raymond Knopp's avatar
 
Raymond Knopp committed
2426

2427
// This has to be updated to include BSR information
2428
//------------------------------------------------------------------------------
2429
uint8_t
2430 2431 2432
UE_is_to_be_scheduled(module_id_t module_idP,
                      int CC_id,
                      uint8_t UE_id)
2433
//------------------------------------------------------------------------------
2434
{
2435
  UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id];
2436
  UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id];
2437
  int rrc_status;
2438 2439

  // do not schedule UE if UL is not working
2440 2441
  if (UE_sched_ctl->ul_failure_timer > 0 || UE_sched_ctl->ul_out_of_sync > 0)
    return 0;
2442

2443
  rnti_t ue_rnti = UE_RNTI(module_idP, UE_id);
2444
  LOG_D(MAC, "[eNB %d][PUSCH] Checking UL requirements UE %d/%x\n",
2445 2446
        module_idP,
        UE_id,
2447 2448
        ue_rnti);

2449 2450
  rrc_status = mac_eNB_get_rrc_status(module_idP, ue_rnti);

2451 2452
  if (UE_template->scheduled_ul_bytes < UE_template->estimated_ul_buffer ||
      UE_template->ul_SR > 0 || // uplink scheduling request
2453
      (UE_sched_ctl->ul_inactivity_timer > 19 && UE_sched_ctl->ul_scheduled == 0) ||  // every 2 frames when RRC_CONNECTED
2454
      (UE_sched_ctl->ul_inactivity_timer > 10 &&
2455 2456
       UE_sched_ctl->ul_scheduled == 0 && rrc_status < RRC_CONNECTED) || // every Frame when not RRC_CONNECTED
      (UE_sched_ctl->cqi_req_timer > 300 && rrc_status >= RRC_CONNECTED)) { // cqi req timer expired long ago (do not put too low value)
2457
    LOG_D(MAC, "[eNB %d][PUSCH] UE %d/%x should be scheduled (BSR0 estimated size %d, SR %d)\n",
2458 2459
          module_idP,
          UE_id,
2460
          ue_rnti,
2461 2462
          UE_template->ul_buffer_info[LCGID0],
          UE_template->ul_SR);
2463
    return 1;
2464
  }
frtabu's avatar
frtabu committed
2465

2466
  return 0;
2467 2468
}

2469
//------------------------------------------------------------------------------
2470 2471 2472 2473
uint8_t
get_tmode(module_id_t module_idP,
          int CC_idP,
          int UE_idP)
2474
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2475
{
2476 2477
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
2478
  struct LTE_PhysicalConfigDedicated *physicalConfigDedicated = eNB->UE_list.UE_template[CC_idP][UE_idP].physicalConfigDedicated;
2479

2480
  if (physicalConfigDedicated == NULL) {  // RRCConnectionSetup not received by UE yet
2481
    AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n",
Stefan's avatar
Stefan committed
2482
                cc->p_eNB);
2483
    return (cc->p_eNB);
2484
  }
2485 2486

  AssertFatal(physicalConfigDedicated->antennaInfo != NULL,
2487
              "antennaInfo (mod_id %d) is null for CCId %d, UEid %d, physicalConfigDedicated %p\n",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
2488
              module_idP,
Stefan's avatar
Stefan committed
2489
              CC_idP,
frtabu's avatar
frtabu committed
2490
              UE_idP,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
2491
              physicalConfigDedicated);
2492
  AssertFatal(physicalConfigDedicated->antennaInfo->present != LTE_PhysicalConfigDedicated__antennaInfo_PR_NOTHING,
Stefan's avatar
Stefan committed
2493 2494 2495
              "antennaInfo (mod_id %d, CC_id %d) is set to NOTHING\n",
              module_idP,
              CC_idP);
2496

2497
  if (physicalConfigDedicated->antennaInfo->present == LTE_PhysicalConfigDedicated__antennaInfo_PR_explicitValue) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
2498
    return (1 + physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
2499
  }
2500

2501
  if (physicalConfigDedicated->antennaInfo->present == LTE_PhysicalConfigDedicated__antennaInfo_PR_defaultValue) {
2502
    AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n",
Stefan's avatar
Stefan committed
2503
                cc->p_eNB);
2504 2505
    return (cc->p_eNB);
  }
2506 2507 2508

  AssertFatal(1 == 0, "Shouldn't be here\n");
  return 0;
2509 2510
}

2511
//------------------------------------------------------------------------------
2512
int8_t
2513 2514
get_ULharq(module_id_t module_idP,
           int CC_idP,
2515
           uint16_t frameP,
2516
           uint8_t subframeP)
2517
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2518
{
2519
  int8_t ret = -1;
2520 2521
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
2522

2523
  if (cc->tdd_Config == NULL) { // FDD
2524 2525 2526
    ret = (((frameP << 1) + subframeP) & 7);
  } else {
    switch (cc->tdd_Config->subframeAssignment) {
2527
      case 1:
2528 2529 2530 2531 2532
        switch (subframeP) {
          case 2:
          case 3:
            ret = (subframeP - 2);
            break;
2533

2534 2535 2536 2537
          case 7:
          case 8:
            ret = (subframeP - 5);
            break;
2538

2539 2540 2541 2542 2543 2544
          default:
            AssertFatal(1 == 0, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
                        subframeP,
                        (int) cc->tdd_Config->subframeAssignment);
            break;
        }
2545

2546
        break;
2547

2548
      case 2:
2549
        AssertFatal((subframeP == 2) || (subframeP == 7), "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
2550 2551 2552 2553
                    subframeP,
                    (int) cc->tdd_Config->subframeAssignment);
        ret = (subframeP / 7);
        break;
2554

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

2562
      case 4:
2563
        AssertFatal((subframeP > 1) && (subframeP < 4), "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
2564 2565 2566 2567 2568 2569
                    subframeP,
                    (int) cc->tdd_Config->subframeAssignment);
        ret = (subframeP - 2);
        break;

      case 5:
2570
        AssertFatal(subframeP == 2, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
2571 2572 2573 2574 2575 2576
                    subframeP,
                    (int) cc->tdd_Config->subframeAssignment);
        ret = (subframeP - 2);
        break;

      default:
2577
        AssertFatal(1 == 0, "subframe2_harq_pid, Unsupported TDD mode %d\n",
2578 2579
                    (int) cc->tdd_Config->subframeAssignment);
        break;
2580
    }
2581
  }
2582

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

2589
//------------------------------------------------------------------------------
2590 2591 2592 2593
uint16_t
getRIV(uint16_t N_RB_DL,
       uint16_t RBstart,
       uint16_t Lcrbs)
2594
//------------------------------------------------------------------------------
2595
{
2596
  uint16_t RIV;
2597

2598 2599 2600 2601
  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);
2602

2603
  return RIV;
2604
}
2605

2606
//------------------------------------------------------------------------------
2607
uint32_t
2608 2609
allocate_prbs(int UE_id,
              unsigned char nb_rb,
2610
              int N_RB_DL,
2611
              uint32_t *rballoc)
2612
//------------------------------------------------------------------------------
2613
{
2614 2615 2616
  int i;
  uint32_t rballoc_dci = 0;
  unsigned char nb_rb_alloc = 0;
2617

2618 2619 2620 2621 2622
  for (i = 0; i < (N_RB_DL - 2); i += 2) {
    if (((*rballoc >> i) & 3) == 0) {
      *rballoc |= (3 << i);
      rballoc_dci |= (1 << ((12 - i) >> 1));
      nb_rb_alloc += 2;
2623 2624
    }

2625 2626 2627 2628 2629 2630 2631 2632 2633
    if (nb_rb_alloc == nb_rb) {
      return (rballoc_dci);
    }
  }

  if ((N_RB_DL & 1) == 1) {
    if ((*rballoc >> (N_RB_DL - 1) & 1) == 0) {
      *rballoc |= (1 << (N_RB_DL - 1));
      rballoc_dci |= 1;
2634
    }
2635
  }
2636

2637
  return (rballoc_dci);
2638 2639
}

2640
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
2641 2642
int
get_bw_index(module_id_t module_id,
2643
             uint8_t CC_id)
2644
//------------------------------------------------------------------------------
2645
{
2646
  int bw_index = 0;
2647
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
2648

2649
  switch (N_RB_DL) {
2650 2651 2652
    case 6:     // 1.4 MHz
      bw_index = 0;
      break;
2653

2654 2655 2656
    case 25:      // 5HMz
      bw_index = 1;
      break;
2657

2658 2659 2660
    case 50:      // 10HMz
      bw_index = 2;
      break;
2661

2662 2663 2664
    case 100:     // 20HMz
      bw_index = 3;
      break;
2665

2666 2667
    default:
      bw_index = 1;
Stefan's avatar
Stefan committed
2668 2669 2670 2671
      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);
2672
      break;
2673
  }
2674

2675
  return bw_index;
2676 2677
}

2678
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
2679 2680
int
get_min_rb_unit(module_id_t module_id,
2681
                uint8_t CC_id)
2682
//------------------------------------------------------------------------------
2683
{
2684
  int min_rb_unit = 0;
2685
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
2686

2687
  switch (N_RB_DL) {
2688
    case 6:       // 1.4MHz
2689 2690
      min_rb_unit = 1;
      break;
2691

2692 2693
    case 15:      // 3MHz
    case 25:      // 5MHz
2694 2695
      min_rb_unit = 2;
      break;
2696

2697
    case 50:      // 10MHz
2698 2699
      min_rb_unit = 3;
      break;
2700

2701 2702
    case 75:      // 15MHz
    case 100:     // 20MHz
2703 2704
      min_rb_unit = 4;
      break;
2705

2706 2707
    default:
      min_rb_unit = 2;
Stefan's avatar
Stefan committed
2708 2709 2710 2711
      LOG_W(MAC, "[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n",
            module_id,
            N_RB_DL,
            CC_id);
2712
      break;
2713
  }
2714

2715
  return min_rb_unit;
2716
}
2717

2718
//------------------------------------------------------------------------------
2719
uint32_t
2720 2721 2722 2723
allocate_prbs_sub(int nb_rb,
                  int N_RB_DL,
                  int N_RBG,
                  uint8_t *rballoc)
2724
//------------------------------------------------------------------------------
2725
{
2726
  int check = 0;    //check1=0,check2=0;
2727 2728 2729
  uint32_t rballoc_dci = 0;
  //uint8_t number_of_subbands=13;
  LOG_T(MAC, "*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n",
2730 2731 2732 2733 2734
        rballoc[3],
        rballoc[2],
        rballoc[1],
        rballoc[0],
        nb_rb,
2735 2736 2737
        N_RBG);

  while (nb_rb > 0 && check < N_RBG) {
2738 2739 2740 2741 2742
    //printf("rballoc[%d] %d\n",check,rballoc[check]);
    if (rballoc[check] == 1) {
      rballoc_dci |= (1 << ((N_RBG - 1) - check));

      switch (N_RB_DL) {
2743 2744 2745
        case 6:
          nb_rb--;
          break;
2746

2747 2748 2749 2750 2751 2752
        case 25:
          if ((check == N_RBG - 1)) {
            nb_rb--;
          } else {
            nb_rb -= 2;
          }
frtabu's avatar
frtabu committed
2753

2754
          break;
2755

2756 2757 2758 2759 2760 2761
        case 50:
          if ((check == N_RBG - 1)) {
            nb_rb -= 2;
          } else {
            nb_rb -= 3;
          }
frtabu's avatar
frtabu committed
2762

2763
          break;
2764

2765 2766 2767
        case 100:
          nb_rb -= 4;
          break;
2768
      }
2769
    }
2770

2771
    //      printf("rb_alloc %x\n",rballoc_dci);
2772
    check++;
2773 2774
    //    check1 = check1+2;
  }
2775

2776
  // rballoc_dci = (rballoc_dci)&(0x1fff);
2777
  LOG_T(MAC, "*********RBALLOC : %x\n",
2778
        rballoc_dci);
2779
  // exit(-1);
2780
  return rballoc_dci;
2781 2782
}

2783
//------------------------------------------------------------------------------
2784 2785
int
get_subbandsize(uint8_t dl_Bandwidth)
2786
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2787
{
2788 2789
  uint8_t ss[6] = { 6, 4, 4, 6, 8, 8 };
  AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth %d is out of bounds\n",
2790
              dl_Bandwidth);
2791
  return (ss[dl_Bandwidth]);
2792
}
Cedric Roux's avatar
Cedric Roux committed
2793

2794
//------------------------------------------------------------------------------
2795 2796
int
get_nb_subband(int N_RB_DL)
2797
//------------------------------------------------------------------------------
2798
{
2799
  int nb_sb = 0;
2800

2801
  switch (N_RB_DL) {
2802 2803 2804
    case 6:
      nb_sb = 0;
      break;
2805

2806 2807
    case 15:
      nb_sb = 4;    // sb_size =4
2808
      break;
2809

2810 2811 2812
    case 25:
      nb_sb = 7;    // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs
      break;
2813

2814 2815 2816
    case 50:      // sb_size =6
      nb_sb = 9;
      break;
2817

2818 2819 2820
    case 75:      // sb_size =8
      nb_sb = 10;
      break;
2821

2822 2823 2824
    case 100:     // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs
      nb_sb = 13;
      break;
2825

2826 2827 2828
    default:
      nb_sb = 0;
      break;
2829
  }
2830

2831
  return nb_sb;
2832
}
2833 2834

//------------------------------------------------------------------------------
2835 2836
void
init_CCE_table(int *CCE_table)
2837
//------------------------------------------------------------------------------
2838
{
Stefan's avatar
Stefan committed
2839
  memset(CCE_table, 0, 800 * sizeof(int));
Cedric Roux's avatar
Cedric Roux committed
2840
}
2841

2842
//------------------------------------------------------------------------------
2843 2844
int
get_nCCE_offset(int *CCE_table,
2845 2846 2847
                const unsigned char L,
                const int nCCE,
                const int common_dci,
2848 2849
                const unsigned short rnti,
                const unsigned char subframe)
2850
//------------------------------------------------------------------------------
2851
{
2852 2853
  int search_space_free, m, nb_candidates = 0, l, i;
  unsigned int Yk;
2854

2855 2856 2857 2858 2859 2860 2861 2862 2863 2864
  /*
    printf("CCE Allocation: ");
    for (i=0;i<nCCE;i++)
    printf("%d.",CCE_table[i]);
    printf("\n");
  */
  if (common_dci == 1) {
    // check CCE(0 ... L-1)
    nb_candidates = (L == 4) ? 4 : 2;
    nb_candidates = min(nb_candidates, nCCE / L);
2865

2866
    //    printf("Common DCI nb_candidates %d, L %d\n",nb_candidates,L);
Raymond Knopp's avatar
Raymond Knopp committed
2867

2868 2869
    for (m = nb_candidates - 1; m >= 0; m--) {
      search_space_free = 1;
Raymond Knopp's avatar
Raymond Knopp committed
2870

2871 2872 2873 2874 2875 2876
      for (l = 0; l < L; l++) {
        //        printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]);
        if (CCE_table[(m * L) + l] == 1) {
          search_space_free = 0;
          break;
        }
2877
      }
2878

2879
      if (search_space_free == 1) {
2880
        //        printf("returning %d\n",m*L);
2881
        for (l = 0; l < L; l++) {
2882
          CCE_table[(m * L) + l] = 1;
2883
        }
frtabu's avatar
frtabu committed
2884

2885
        return (m * L);
2886 2887
      }
    }
2888

2889
    return -1;
2890
  }
frtabu's avatar
frtabu committed
2891

2892 2893 2894 2895
  // Find first available in ue specific search space
  // according to procedure in Section 9.1.1 of 36.213 (v. 8.6)
  // compute Yk
  Yk = (unsigned int) rnti;
2896

2897 2898 2899
  for (i = 0; i <= subframe; i++) {
    Yk = (Yk * 39827) % 65537;
  }
frtabu's avatar
frtabu committed
2900

2901
  Yk = Yk % (nCCE / L);
2902

2903
  switch (L) {
2904 2905 2906 2907
    case 1:
    case 2:
      nb_candidates = 6;
      break;
2908

2909 2910 2911 2912
    case 4:
    case 8:
      nb_candidates = 2;
      break;
2913

2914
    default:
2915 2916
      DevParam(L,
               nCCE,
2917
               rnti);
2918
      break;
2919
  }
2920

2921
  LOG_D(MAC, "rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",
2922 2923 2924 2925
        rnti,
        Yk,
        nCCE,
        nCCE / L,
2926
        nb_candidates);
2927

2928 2929
  for (m = 0; m < nb_candidates; m++) {
    search_space_free = 1;
2930

2931 2932
    for (l = 0; l < L; l++) {
      int cce = (((Yk + m) % (nCCE / L)) * L) + l;
2933

2934 2935 2936
      if (cce >= nCCE || CCE_table[cce] == 1) {
        search_space_free = 0;
        break;
2937
      }
2938
    }
2939

2940 2941 2942
    if (search_space_free == 1) {
      for (l = 0; l < L; l++) {
        CCE_table[(((Yk + m) % (nCCE / L)) * L) + l] = 1;
2943
      }
frtabu's avatar
frtabu committed
2944

2945
      return (((Yk + m) % (nCCE / L)) * L);
2946
    }
2947
  }
2948 2949

  return -1;
2950 2951
}

2952
//------------------------------------------------------------------------------
2953
void
2954
dump_CCE_table(int *CCE_table,
2955
               const int nCCE,
2956 2957 2958
               const unsigned short rnti,
               const int subframe,
               int L)
2959
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2960
{
2961 2962 2963
  int nb_candidates = 0, i;
  unsigned int Yk;
  printf("CCE 0: ");
2964

2965 2966
  for (i = 0; i < nCCE; i++) {
    printf("%1d.", CCE_table[i]);
2967

2968
    if ((i & 7) == 7)
2969
      printf("\n CCE %d: ",
2970
             i);
2971
  }
Cedric Roux's avatar
Cedric Roux committed
2972

2973
  Yk = (unsigned int) rnti;
Cedric Roux's avatar
Cedric Roux committed
2974

2975
  for (i = 0; i <= subframe; i++) {
2976
    Yk = (Yk * 39827) % 65537;
2977
  }
frtabu's avatar
frtabu committed
2978

2979
  Yk = Yk % (nCCE / L);
Cedric Roux's avatar
Cedric Roux committed
2980

2981
  switch (L) {
2982 2983 2984 2985 2986 2987 2988 2989 2990
    case 1:
    case 2:
      nb_candidates = 6;
      break;

    case 4:
    case 8:
      nb_candidates = 2;
      break;
Cedric Roux's avatar
Cedric Roux committed
2991

2992 2993 2994
    default:
      DevParam(L, nCCE, rnti);
      break;
2995
  }
2996

2997
  LOG_I(PHY, "rnti %x, Yk*L = %u, nCCE %d (nCCE/L %d),nb_cand*L %d\n",
frtabu's avatar
frtabu committed
2998 2999 3000 3001 3002
        rnti,
        Yk * L,
        nCCE,
        nCCE / L,
        nb_candidates * L);
3003 3004
}

3005
//------------------------------------------------------------------------------
3006
uint16_t
3007 3008 3009
getnquad(COMMON_channels_t *cc,
         uint8_t num_pdcch_symbols,
         uint8_t mi)
3010
//------------------------------------------------------------------------------
3011
{
3012 3013 3014 3015 3016 3017
  uint16_t Nreg = 0;
  AssertFatal(cc != NULL, "cc is null\n");
  AssertFatal(cc->mib != NULL, "cc->mib is null\n");
  int N_RB_DL = to_prb(cc->mib->message.dl_Bandwidth);
  int phich_resource = get_phich_resource_times6(cc);
  uint8_t Ngroup_PHICH = (phich_resource * N_RB_DL) / 48;
3018

3019
  if (((phich_resource * N_RB_DL) % 48) > 0) {
3020
    Ngroup_PHICH++;
3021
  }
frtabu's avatar
frtabu committed
3022

3023 3024 3025
  if (cc->Ncp == 1) {
    Ngroup_PHICH <<= 1;
  }
3026

3027
  Ngroup_PHICH *= mi;
3028

3029
  if (num_pdcch_symbols > 0 && num_pdcch_symbols < 4)
3030
    switch (N_RB_DL) {
3031 3032 3033
      case 6:
        Nreg = 12 + (num_pdcch_symbols - 1) * 18;
        break;
3034

3035 3036 3037
      case 25:
        Nreg = 50 + (num_pdcch_symbols - 1) * 75;
        break;
3038

3039 3040 3041
      case 50:
        Nreg = 100 + (num_pdcch_symbols - 1) * 150;
        break;
3042

3043 3044 3045
      case 100:
        Nreg = 200 + (num_pdcch_symbols - 1) * 300;
        break;
3046

3047
      default:
3048
        return 0;
3049
    }
3050

3051 3052
  //   printf("Nreg %d (%d)\n",Nreg,Nreg - 4 - (3*Ngroup_PHICH));
  return (Nreg - 4 - (3 * Ngroup_PHICH));
3053 3054
}

3055
//------------------------------------------------------------------------------
3056
uint16_t
3057 3058 3059
getnCCE(COMMON_channels_t *cc,
        uint8_t num_pdcch_symbols,
        uint8_t mi)
3060
//------------------------------------------------------------------------------
3061
{
3062
  AssertFatal(cc != NULL, "cc is null\n");
3063 3064
  return (getnquad(cc,
                   num_pdcch_symbols,
3065
                   mi) / 9);
3066 3067
}

3068
//------------------------------------------------------------------------------
3069 3070 3071
uint8_t
getmi(COMMON_channels_t *cc,
      int subframe)
3072
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
3073
{
3074
  AssertFatal(cc != NULL, "cc is null\n");
3075

3076
  // for FDD
3077
  if (cc->tdd_Config == NULL) // FDD
3078
    return 1;
3079

3080 3081
  // for TDD
  switch (cc->tdd_Config->subframeAssignment) {
3082
    case 0:
3083 3084 3085
      if (subframe == 0 || subframe == 5) {
        return 2;
      }
frtabu's avatar
frtabu committed
3086

3087
      return 1;
3088

3089
    case 1:
3090 3091 3092
      if (subframe == 0 || subframe == 5) {
        return 0;
      }
frtabu's avatar
frtabu committed
3093

3094
      return 1;
3095

3096
    case 2:
3097 3098 3099
      if (subframe == 3 || subframe == 8) {
        return 0;
      }
frtabu's avatar
frtabu committed
3100

3101
      return 1;
3102

3103
    case 3:
3104 3105 3106
      if (subframe == 0 || subframe == 8 || subframe == 9) {
        return 1;
      }
frtabu's avatar
frtabu committed
3107

3108
      return 0;
3109

3110
    case 4:
3111 3112 3113
      if (subframe == 8 || subframe == 9) {
        return 1;
      }
frtabu's avatar
frtabu committed
3114

3115
      return 0;
3116

3117
    case 5:
3118 3119 3120
      if (subframe == 8) {
        return 1;
      }
frtabu's avatar
frtabu committed
3121

3122
      return 0;
3123

3124
    case 6:
3125
      return 1;
3126

3127
    default:
3128
      break;
3129
  }
frtabu's avatar
frtabu committed
3130

3131
  return 0;
3132 3133
}

3134
//------------------------------------------------------------------------------
3135
uint16_t
3136 3137 3138
get_nCCE_max(COMMON_channels_t *cc,
             int num_pdcch_symbols,
             int subframe)
3139
//------------------------------------------------------------------------------
3140
{
3141
  AssertFatal(cc != NULL, "cc is null\n");
3142 3143 3144
  return (getnCCE(cc,
                  num_pdcch_symbols,
                  getmi(cc,
3145
                        subframe)));
3146
}
Cedric Roux's avatar
Cedric Roux committed
3147

3148
// Allocate the CCEs
3149
//------------------------------------------------------------------------------
3150
int
3151 3152 3153 3154 3155
allocate_CCEs(int module_idP,
              int CC_idP,
              frame_t frameP,
              sub_frame_t subframeP,
              int test_onlyP)
3156
//------------------------------------------------------------------------------
3157
{
Stefan's avatar
Stefan committed
3158 3159 3160 3161
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  int *CCE_table = eNB->CCE_table[CC_idP];
  nfapi_dl_config_request_body_t *DL_req = &eNB->DL_req[CC_idP].dl_config_request_body;
  nfapi_hi_dci0_request_body_t *HI_DCI0_req = &eNB->HI_DCI0_req[CC_idP][subframeP].hi_dci0_request_body;
3162 3163
  nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[0];
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[0];
Stefan's avatar
Stefan committed
3164 3165
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
  int nCCE_max = get_nCCE_max(cc, 1, subframeP);
3166 3167 3168
  int fCCE;
  int i, j, idci;
  int nCCE = 0;
3169 3170
  int max_symbol;
  int ackNAK_absSF = get_pucch1_absSF(cc, (frameP*10+subframeP));
Stefan's avatar
Stefan committed
3171 3172
  nfapi_dl_config_request_pdu_t *dl_config_pduLoop;
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pduLoop;
3173

3174 3175 3176 3177 3178 3179
  if (cc->tdd_Config!=NULL && is_S_sf(cc,subframeP) > 0)
    max_symbol = 2;
  else
    max_symbol = 3;

  nfapi_ul_config_request_body_t *ul_req = &eNB->UL_req_tmp[CC_idP][ackNAK_absSF % 10].ul_config_request_body;
3180
  LOG_D(MAC, "Allocate CCEs subframe %d, test %d : (DL PDU %d, DL DCI %d, UL %d)\n",
3181 3182 3183
        subframeP,
        test_onlyP,
        DL_req->number_pdu,
Stefan's avatar
Stefan committed
3184
        DL_req->number_dci,
3185
        HI_DCI0_req->number_of_dci);
3186
  DL_req->number_pdcch_ofdm_symbols = 1;
3187
try_again:
Stefan's avatar
Stefan committed
3188
  init_CCE_table(CCE_table);
3189 3190 3191
  nCCE = 0;

  for (i = 0, idci = 0; i < DL_req->number_pdu; i++) {
Stefan's avatar
Stefan committed
3192
    dl_config_pduLoop = &dl_config_pdu[i];
frtabu's avatar
frtabu committed
3193

3194
    // allocate DL common DCIs first
3195
    if (dl_config_pduLoop->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE &&
Stefan's avatar
Stefan committed
3196
        dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == 2) {
3197
      LOG_D(MAC, "Trying to allocate COMMON DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3198
            idci,
Stefan's avatar
Stefan committed
3199
            DL_req->number_dci + HI_DCI0_req->number_of_dci,
3200
            DL_req->number_dci,
Stefan's avatar
Stefan committed
3201 3202
            HI_DCI0_req->number_of_dci,
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3203 3204 3205
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
            nCCE,
            nCCE_max,
Stefan's avatar
Stefan committed
3206
            DL_req->number_pdcch_ofdm_symbols);
3207

Stefan's avatar
Stefan committed
3208
      if (nCCE + (dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) {
3209
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol)
3210
          return -1;
3211 3212 3213 3214

        LOG_D(MAC, "Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",
              DL_req->number_pdcch_ofdm_symbols);
        DL_req->number_pdcch_ofdm_symbols++;
Stefan's avatar
Stefan committed
3215
        nCCE_max = get_nCCE_max(cc, DL_req->number_pdcch_ofdm_symbols, subframeP);
3216
        goto try_again;
3217
      }
3218

3219 3220
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
3221 3222
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                             nCCE_max,
Stefan's avatar
Stefan committed
3223 3224
                             1,
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3225 3226
                             subframeP);

3227
      if (fCCE == -1) {
3228 3229
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol) {
          LOG_D(MAC, "subframe %d: Dropping Allocation for RNTI %x\n",
3230
                subframeP,
Stefan's avatar
Stefan committed
3231
                dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti);
3232 3233

          for (j = 0; j <= i; j++) {
Stefan's avatar
Stefan committed
3234
            dl_config_pduLoop = &dl_config_pdu[j];
frtabu's avatar
frtabu committed
3235

Stefan's avatar
Stefan committed
3236
            if (dl_config_pduLoop->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
3237 3238 3239 3240 3241
              LOG_D(MAC, "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
                    j,
                    DL_req->number_dci + HI_DCI0_req->number_of_dci,
                    DL_req->number_dci,
                    HI_DCI0_req->number_of_dci,
Stefan's avatar
Stefan committed
3242 3243
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.dci_format,
3244
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
3245 3246
                    nCCE, nCCE_max, DL_req->number_pdcch_ofdm_symbols);
          }
frtabu's avatar
frtabu committed
3247

3248
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
3249
          return -1;
3250 3251
        }

Stefan's avatar
Stefan committed
3252
        LOG_D(MAC, "Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",
3253 3254
              DL_req->number_pdcch_ofdm_symbols);
        DL_req->number_pdcch_ofdm_symbols++;
Stefan's avatar
Stefan committed
3255
        nCCE_max = get_nCCE_max(cc, DL_req->number_pdcch_ofdm_symbols, subframeP);
3256 3257
        goto try_again;
      }     // fCCE==-1
3258 3259

      // the allocation is feasible, rnti rule passes
Stefan's avatar
Stefan committed
3260
      nCCE += dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level;
3261
      LOG_D(MAC, "Allocating at nCCE %d\n", fCCE);
3262

3263
      if ((test_onlyP%2) == 0) {
Stefan's avatar
Stefan committed
3264
        dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE;
3265
        LOG_D(MAC, "Allocate COMMON DCI CCEs subframe %d, test %d => L %d fCCE %d\n",
3266 3267 3268
              subframeP,
              test_onlyP,
              dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
Stefan's avatar
Stefan committed
3269
              fCCE);
3270
      }
3271

3272 3273
      idci++;
    }
3274
  }       // for i = 0 ... num_DL_DCIs
3275

3276
  // now try to allocate UL DCIs
3277
  for (i = 0; i < HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi; i++) {
Stefan's avatar
Stefan committed
3278
    hi_dci0_pduLoop = &hi_dci0_pdu[i];
frtabu's avatar
frtabu committed
3279

3280 3281
    // allocate UL DCIs
    if (hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) {
3282
      LOG_D(MAC, "Trying to allocate format 0 DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3283
            idci,
Stefan's avatar
Stefan committed
3284
            DL_req->number_dci + HI_DCI0_req->number_of_dci,
3285
            DL_req->number_dci,
Stefan's avatar
Stefan committed
3286 3287 3288
            HI_DCI0_req->number_of_dci,
            hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.rnti,
            hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level,
3289
            nCCE, nCCE_max,
Stefan's avatar
Stefan committed
3290
            DL_req->number_pdcch_ofdm_symbols);
3291

Stefan's avatar
Stefan committed
3292
      if (nCCE + hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level > nCCE_max) {
3293
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol)
3294
          return -1;
3295

3296
        LOG_D(MAC, "Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",
3297 3298
              DL_req->number_pdcch_ofdm_symbols);
        DL_req->number_pdcch_ofdm_symbols++;
Stefan's avatar
Stefan committed
3299
        nCCE_max = get_nCCE_max(cc, DL_req->number_pdcch_ofdm_symbols, subframeP);
3300
        goto try_again;
3301
      }
3302

3303 3304
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
Stefan's avatar
Stefan committed
3305
                             hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level,
3306
                             nCCE_max,
Stefan's avatar
Stefan committed
3307
                             0,
3308
                             hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.rnti,
Stefan's avatar
Stefan committed
3309
                             subframeP);
3310

3311
      if (fCCE == -1) {
3312
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol) {
3313
          LOG_D(MAC, "subframe %d: Dropping Allocation for RNTI %x\n",
3314
                subframeP,
Stefan's avatar
Stefan committed
3315
                hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.rnti);
3316 3317

          for (j = 0; j <= i; j++) {
Stefan's avatar
Stefan committed
3318
            hi_dci0_pduLoop = &hi_dci0_pdu[j];
frtabu's avatar
frtabu committed
3319

3320
            if (hi_dci0_pdu[j].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)
3321
              LOG_D(MAC, "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3322 3323 3324 3325
                    j,
                    DL_req->number_dci + HI_DCI0_req->number_of_dci,
                    DL_req->number_dci,
                    HI_DCI0_req->number_of_dci,
Stefan's avatar
Stefan committed
3326 3327
                    hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.rnti,
                    hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.dci_format,
3328
                    hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level,
3329 3330
                    nCCE, nCCE_max, DL_req->number_pdcch_ofdm_symbols);
          }
frtabu's avatar
frtabu committed
3331

3332
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
3333
          return -1;
3334 3335
        }

3336
        LOG_D(MAC, "Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",
3337 3338
              DL_req->number_pdcch_ofdm_symbols);
        DL_req->number_pdcch_ofdm_symbols++;
Stefan's avatar
Stefan committed
3339
        nCCE_max = get_nCCE_max(cc, DL_req->number_pdcch_ofdm_symbols, subframeP);
3340 3341
        goto try_again;
      }     // fCCE==-1
3342 3343

      // the allocation is feasible, rnti rule passes
Stefan's avatar
Stefan committed
3344
      nCCE += hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level;
3345
      LOG_D(MAC, "Allocating at nCCE %d\n",
Stefan's avatar
Stefan committed
3346
            fCCE);
3347

3348
      if ((test_onlyP%2) == 0) {
Stefan's avatar
Stefan committed
3349
        hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.cce_index = fCCE;
3350 3351
        LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n",
              subframeP,
Stefan's avatar
Stefan committed
3352
              test_onlyP);
3353
      }
3354

3355 3356
      idci++;
    }
3357
  }       // for i = 0 ... num_UL_DCIs
3358 3359

  for (i = 0; i < DL_req->number_pdu; i++) {
Stefan's avatar
Stefan committed
3360
    dl_config_pduLoop = &dl_config_pdu[i];
frtabu's avatar
frtabu committed
3361

3362 3363
    // allocate DL UE specific DCIs
    if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
Stefan's avatar
Stefan committed
3364
        && (dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == 1)) {
3365
      LOG_D(MAC, "Trying to allocate DL UE-SPECIFIC DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3366
            idci,
Stefan's avatar
Stefan committed
3367
            DL_req->number_dci + HI_DCI0_req->number_of_dci,
3368
            DL_req->number_dci, HI_DCI0_req->number_of_dci,
Stefan's avatar
Stefan committed
3369
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3370 3371
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
            nCCE,
Stefan's avatar
Stefan committed
3372
            nCCE_max,
3373
            DL_req->number_pdcch_ofdm_symbols);
3374

Stefan's avatar
Stefan committed
3375
      if (nCCE + (dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) {
3376
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol)
3377
          return -1;
3378

3379
        LOG_D(MAC, "Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",
Stefan's avatar
Stefan committed
3380
              DL_req->number_pdcch_ofdm_symbols);
3381
        DL_req->number_pdcch_ofdm_symbols++;
Stefan's avatar
Stefan committed
3382
        nCCE_max = get_nCCE_max(cc, DL_req->number_pdcch_ofdm_symbols, subframeP);
3383
        goto try_again;
3384
      }
3385

3386 3387
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
3388 3389
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                             nCCE_max,
Stefan's avatar
Stefan committed
3390 3391
                             0,
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3392 3393
                             subframeP);

3394
      if (fCCE == -1) {
3395
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol) {
3396
          LOG_I(MAC, "subframe %d: Dropping Allocation for RNTI %x\n",
3397
                subframeP,
Stefan's avatar
Stefan committed
3398
                dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti);
3399 3400

          for (j = 0; j <= i; j++) {
Stefan's avatar
Stefan committed
3401
            dl_config_pduLoop = &dl_config_pdu[j];
frtabu's avatar
frtabu committed
3402

Stefan's avatar
Stefan committed
3403
            if (dl_config_pduLoop->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
3404
              LOG_D(MAC, "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3405 3406 3407 3408
                    j,
                    DL_req->number_dci + HI_DCI0_req->number_of_dci,
                    DL_req->number_dci,
                    HI_DCI0_req->number_of_dci,
Stefan's avatar
Stefan committed
3409 3410 3411
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.dci_format,
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
3412 3413 3414 3415
                    nCCE,
                    nCCE_max,
                    DL_req->number_pdcch_ofdm_symbols);
          }
frtabu's avatar
frtabu committed
3416

3417
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
3418
          return -1;
3419 3420
        }

3421
        LOG_D(MAC, "Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",
3422 3423
              DL_req->number_pdcch_ofdm_symbols);
        DL_req->number_pdcch_ofdm_symbols++;
Stefan's avatar
Stefan committed
3424
        nCCE_max = get_nCCE_max(cc, DL_req->number_pdcch_ofdm_symbols, subframeP);
3425 3426
        goto try_again;
      }     // fCCE==-1
3427 3428

      // the allocation is feasible, rnti rule passes
Stefan's avatar
Stefan committed
3429
      nCCE += dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level;
3430
      LOG_D(MAC, "Allocating at nCCE %d\n",
Stefan's avatar
Stefan committed
3431
            fCCE);
3432

3433
      if ((test_onlyP%2) == 0) {
Stefan's avatar
Stefan committed
3434
        dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE;
3435 3436
        LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n",
              subframeP,
Stefan's avatar
Stefan committed
3437
              test_onlyP);
3438
      }
3439

3440
      if ((test_onlyP/2) == 1) {
3441 3442 3443 3444 3445 3446 3447 3448 3449 3450 3451
        for(int ack_int = 0; ack_int < ul_req->number_of_pdus; ack_int++) {
          if(((ul_req->ul_config_pdu_list[ack_int].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE) ||
              (ul_req->ul_config_pdu_list[ack_int].pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE)) &&
              (ul_req->ul_config_pdu_list[ack_int].uci_harq_pdu.ue_information.ue_information_rel8.rnti == dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti)) {
            if (cc->tdd_Config==NULL)
              ul_req->ul_config_pdu_list[ack_int].uci_harq_pdu.harq_information.harq_information_rel9_fdd.n_pucch_1_0 =
                cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + fCCE;
            else
              ul_req->ul_config_pdu_list[ack_int].uci_harq_pdu.harq_information.harq_information_rel10_tdd.n_pucch_1_0 =
                cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + fCCE + getNp(cc->mib->message.dl_Bandwidth,fCCE,0) ;
          }
3452 3453
        }
      }
3454

3455 3456
      idci++;
    }
3457
  }       // for i = 0 ... num_DL_DCIs
frtabu's avatar
frtabu committed
3458

3459
  return 0;
3460 3461
}

3462
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3463 3464
nfapi_ul_config_request_pdu_t *
has_ul_grant(module_id_t module_idP,
3465 3466 3467
             int CC_idP,
             uint16_t absSFP,
             uint16_t rnti)
3468
//------------------------------------------------------------------------------
3469
{
Stefan's avatar
Stefan committed
3470 3471 3472 3473
  nfapi_ul_config_request_body_t *ul_req = &RC.mac[module_idP]->UL_req_tmp[CC_idP][absSFP % 10].ul_config_request_body;
  nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[0];
  uint8_t pdu_type;
  LOG_D(MAC, "Checking for rnti %x UL grant in subframeP %d (num pdu %d)\n",
3474 3475
        rnti,
        absSFP % 10,
Stefan's avatar
Stefan committed
3476 3477 3478 3479
        ul_req->number_of_pdus);

  for (int i = 0; i < ul_req->number_of_pdus; i++, ul_config_pdu++) {
    pdu_type = ul_config_pdu->pdu_type;
3480
    LOG_D(MAC, "PDU %d : type %d,rnti %x\n",
Stefan's avatar
Stefan committed
3481
          i,
3482
          pdu_type,
Stefan's avatar
Stefan committed
3483 3484 3485 3486 3487 3488 3489 3490 3491 3492 3493 3494 3495 3496 3497 3498 3499 3500 3501 3502 3503 3504 3505 3506 3507 3508 3509 3510 3511 3512 3513 3514 3515 3516 3517 3518 3519 3520 3521 3522 3523 3524 3525
          rnti);

    if (pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE && ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE && ul_config_pdu->ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE && ul_config_pdu->ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE && ul_config_pdu->ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE && ul_config_pdu->uci_cqi_pdu.ue_information.ue_information_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE && ul_config_pdu->uci_sr_pdu.ue_information.ue_information_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE && ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE && ul_config_pdu->uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE && ul_config_pdu->uci_cqi_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE && ul_config_pdu->uci_cqi_sr_pdu.ue_information.ue_information_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE && ul_config_pdu->uci_cqi_sr_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE && ul_config_pdu->ulsch_uci_csi_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE && ul_config_pdu->ulsch_uci_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)
      return ul_config_pdu;

    if (pdu_type == NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE && ul_config_pdu->ulsch_csi_uci_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)
      return ul_config_pdu;
3526
  }
Cedric Roux's avatar
Cedric Roux committed
3527

3528
  return (NULL);    // no ul grant at all for this UE
3529
}
Cedric Roux's avatar
Cedric Roux committed
3530

3531
//------------------------------------------------------------------------------
3532 3533
boolean_t
CCE_allocation_infeasible(int module_idP,
3534 3535 3536 3537 3538
                          int CC_idP,
                          int format_flag,
                          int subframe,
                          int aggregation,
                          int rnti)
3539
//------------------------------------------------------------------------------
3540
{
3541 3542
  nfapi_dl_config_request_body_t *DL_req       = &RC.mac[module_idP]->DL_req[CC_idP].dl_config_request_body;
  nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu];
3543
  nfapi_hi_dci0_request_body_t *HI_DCI0_req    = &RC.mac[module_idP]->HI_DCI0_req[CC_idP][subframe].hi_dci0_request_body;
3544
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu     = &HI_DCI0_req->hi_dci0_pdu_list[HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi];
3545
  boolean_t res = TRUE;
3546

3547
  if (format_flag != 2) { // DL DCI
3548
    if (DL_req->number_pdu == MAX_NUM_DL_PDU) {
3549
      LOG_W(MAC, "Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", subframe, rnti);
3550 3551 3552 3553 3554 3555 3556
    } else {
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.tl.tag            = NFAPI_DL_CONFIG_REQUEST_DCI_DL_PDU_REL8_TAG;
      dl_config_pdu->pdu_type                                     = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti              = rnti;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type         = (format_flag == 0) ? 2 : 1;
      dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation;
      DL_req->number_pdu++;
3557
      LOG_D(MAC, "Subframe %d: Checking CCE feasibility format %d : (%x,%d) \n",
3558
            subframe, format_flag, rnti, aggregation);
3559

3560 3561
      if (allocate_CCEs(module_idP, CC_idP, 0, subframe, 0) != -1)
        res = FALSE;
frtabu's avatar
frtabu committed
3562

3563 3564
      DL_req->number_pdu--;
    }
3565
  } else { // ue-specific UL DCI
3566
    if (HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi == MAX_NUM_HI_DCI0_PDU) {
3567
      LOG_W(MAC, "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n", subframe, rnti);
3568 3569 3570 3571 3572 3573
    } else {
      hi_dci0_pdu->pdu_type                               = NFAPI_HI_DCI0_DCI_PDU_TYPE;
      hi_dci0_pdu->dci_pdu.dci_pdu_rel8.tl.tag            = NFAPI_HI_DCI0_REQUEST_DCI_PDU_REL8_TAG;
      hi_dci0_pdu->dci_pdu.dci_pdu_rel8.rnti              = rnti;
      hi_dci0_pdu->dci_pdu.dci_pdu_rel8.aggregation_level = aggregation;
      HI_DCI0_req->number_of_dci++;
3574

3575 3576
      if (allocate_CCEs(module_idP, CC_idP, 0, subframe, 0) != -1)
        res = FALSE;
frtabu's avatar
frtabu committed
3577

3578
      HI_DCI0_req->number_of_dci--;
3579
    }
3580
  }
3581

3582
  return res;
3583
}
3584

3585
//------------------------------------------------------------------------------
3586 3587
void
get_retransmission_timing(LTE_TDD_Config_t *tdd_Config,
3588
                          frame_t *frameP,
3589
                          sub_frame_t *subframeP)
3590 3591
//------------------------------------------------------------------------------
{
3592
  if (tdd_Config == NULL) {
3593
    if (*subframeP > 1) {
3594
      *frameP = (*frameP + 1) % 1024;
3595
    }
frtabu's avatar
frtabu committed
3596

3597 3598 3599 3600
    *subframeP = (*subframeP + 8) % 10;
  } else {
    switch (tdd_Config->subframeAssignment) { //TODO fill in other TDD configs
      default:
3601 3602
        printf("%s:%d: TODO\n",
               __FILE__,
3603
               __LINE__);
3604
        abort();
3605
        break;
3606 3607 3608 3609

      case 1:
        if (*subframeP == 0 || *subframeP == 5) {
          *subframeP  += 19;
3610
          *frameP = (*frameP + (*subframeP / 10)) % 1024;
3611 3612 3613
          *subframeP %= 10;
        } else if (*subframeP == 4 || *subframeP == 9) {
          *subframeP  += 16;
3614
          *frameP = (*frameP + (*subframeP / 10)) % 1024;
3615 3616
          *subframeP %= 10;
        } else {
3617
          AssertFatal(2 == 1, "Illegal dl subframe %d for tdd config %ld\n",
3618
                      *subframeP,
3619
                      tdd_Config->subframeAssignment);
3620
        }
frtabu's avatar
frtabu committed
3621

3622
        break;
3623
    }
3624
  }
frtabu's avatar
frtabu committed
3625

3626
  return;
3627 3628
}

3629
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3630 3631
uint8_t
get_dl_subframe_count(int tdd_config_sfa,
3632
                      sub_frame_t subframeP)
3633
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3634
{
3635
  uint8_t tdd1[10] = {1, -1, -1, -1, 2, 3, -1, -1, -1, 4}; // special subframes 1,6 are excluded
3636

Stefan's avatar
Stefan committed
3637 3638
  switch (tdd_config_sfa) {// TODO fill in other tdd configs
    case 1:
3639 3640
      return tdd1[subframeP];
  }
3641

3642
  return -1;
3643 3644
}

3645
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3646 3647 3648
uint8_t
frame_subframe2_dl_harq_pid(LTE_TDD_Config_t *tdd_Config,
                            int abs_frameP,
3649
                            sub_frame_t subframeP)
3650 3651
//------------------------------------------------------------------------------
{
3652
  int harq_pid;
Stefan's avatar
Stefan committed
3653
  uint8_t count;
3654

Stefan's avatar
Stefan committed
3655
  if (tdd_Config) {
3656 3657
    switch(tdd_Config->subframeAssignment) { //TODO fill in other tdd config
      case 1:
3658
        count = get_dl_subframe_count(tdd_Config->subframeAssignment,
3659
                                      subframeP);
Stefan's avatar
Stefan committed
3660
        harq_pid = (((frame_cnt * 1024 + abs_frameP) * 4) - 1 + count) % 7;//4 dl subframe in a frame
3661

Stefan's avatar
Stefan committed
3662
        if (harq_pid < 0) {
3663
          harq_pid += 7;
3664
        }
3665 3666

        LOG_D(MAC,"[frame_subframe2_dl_harq_pid] (%d,%d) calculate harq_pid ((( %d * 1024 + %d) *4) - 1 + %d) = %d \n",
Stefan's avatar
Stefan committed
3667 3668 3669 3670 3671 3672
              (abs_frameP + 1024) % 1024,
              subframeP,
              frame_cnt,
              abs_frameP,
              count,
              harq_pid);
3673
        return harq_pid;
3674
    }
3675
  } else {
Stefan's avatar
Stefan committed
3676
    return ((abs_frameP * 10) + subframeP) & 7;
3677
  }
3678

3679
  return -1;
3680 3681
}

3682
//------------------------------------------------------------------------------
3683
unsigned char
3684
ul_ACK_subframe2M(LTE_TDD_Config_t *tdd_Config,
3685
                  unsigned char subframe)
3686
//------------------------------------------------------------------------------
3687 3688
{
  if (tdd_Config == NULL) {
3689
    return 1;
3690
  }
frtabu's avatar
frtabu committed
3691

3692
  switch (tdd_Config->subframeAssignment) {
3693
    case 1:
3694
      return 1; // don't ACK special subframe for now
frtabu's avatar
frtabu committed
3695 3696 3697 3698 3699 3700 3701 3702 3703 3704 3705 3706 3707 3708 3709 3710

    /*
    if (subframe == 2) {  // ACK subframes 5 and 6
      return(2);
    } else if (subframe == 3) { // ACK subframe 9
      return(1);  // To be updated
    } else if (subframe == 7) { // ACK subframes 0 and 1
      return(2);  // To be updated
    } else if (subframe == 8) { // ACK subframe 4
      return(1);  // To be updated
    } else {
      AssertFatal(1==0,"illegal subframe %d for tdd_config %ld\n",
                  subframe,tdd_Config->subframeAssignment);
    }
    break;
    */
3711 3712
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
3713
        return 2; // should be 3
3714
      }
frtabu's avatar
frtabu committed
3715

3716 3717
      if (subframe == 3) { // ACK subframes 7 and 8
        return 2;  // To be updated
3718
      }
frtabu's avatar
frtabu committed
3719

3720 3721
      if (subframe == 4) { // ACK subframes 9 and 0
        return 2;
3722
      }
frtabu's avatar
frtabu committed
3723

3724 3725 3726
      AssertFatal(1==0,"illegal subframe %d for tdd_config %ld\n",
                  subframe,
                  tdd_Config->subframeAssignment);
3727 3728 3729
      break;

    case 4:
3730 3731
      if (subframe == 2) {  // ACK subframes 0,4 and 5
        return 3; // should be 4
3732
      }
frtabu's avatar
frtabu committed
3733

3734 3735
      if (subframe == 3) { // ACK subframes 6,7,8 and 9
        return 4;
3736
      }
frtabu's avatar
frtabu committed
3737

3738 3739 3740 3741
      AssertFatal(1==0,"illegal subframe %d for tdd_config %ld\n",
                  subframe,
                  tdd_Config->subframeAssignment);
      break;
3742 3743

    case 5:
3744 3745
      if (subframe == 2) {  // ACK subframes 0,3,4,5,6,7,8 and 9
        return 8; // should be 3
3746
      }
frtabu's avatar
frtabu committed
3747

3748 3749 3750 3751
      AssertFatal(1==0,"illegal subframe %d for tdd_config %ld\n",
                  subframe,
                  tdd_Config->subframeAssignment);
      break;
3752 3753
  }

3754
  return 0;
3755 3756
}

3757
//------------------------------------------------------------------------------
3758
unsigned char
3759 3760
ul_ACK_subframe2dl_subframe(LTE_TDD_Config_t *tdd_Config,
                            unsigned char subframe,
3761
                            unsigned char ACK_index)
3762
//------------------------------------------------------------------------------
3763 3764
{
  if (tdd_Config == NULL) {
3765
    return ((subframe < 4) ? subframe + 6 : subframe - 4);
3766
  }
3767

3768
  switch (tdd_Config->subframeAssignment) {
3769 3770
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
3771
        if (ACK_index == 2) return 1;
frtabu's avatar
frtabu committed
3772

3773
        return (5 + ACK_index);
3774
      }
frtabu's avatar
frtabu committed
3775

3776 3777
      if (subframe == 3) { // ACK subframes 7 and 8
        return (7 + ACK_index);  // To be updated
3778
      }
frtabu's avatar
frtabu committed
3779

3780 3781
      if (subframe == 4) { // ACK subframes 9 and 0
        return ((9 + ACK_index) % 10);
3782
      }
frtabu's avatar
frtabu committed
3783

3784
      AssertFatal(1==0, "illegal subframe %d for tdd_config->subframeAssignment %ld\n",
3785 3786
                  subframe,
                  tdd_Config->subframeAssignment);
3787 3788 3789
      break;

    case 4:
3790 3791 3792 3793
      if (subframe == 2) {  // ACK subframes 0, 4 and 5
        //if (ACK_index==2)
        //  return(1); TBC
        if (ACK_index == 2) return 0;
frtabu's avatar
frtabu committed
3794

3795
        return (4 + ACK_index);
3796
      }
frtabu's avatar
frtabu committed
3797

3798 3799
      if (subframe == 3) { // ACK subframes 6, 7 8 and 9
        return (6 + ACK_index);  // To be updated
3800
      }
frtabu's avatar
frtabu committed
3801

3802
      AssertFatal(1 == 0, "illegal subframe %d for tdd_config %ld\n",
3803 3804 3805
                  subframe,
                  tdd_Config->subframeAssignment);
      break;
3806 3807 3808

    case 1:
      if (subframe == 2) {  // ACK subframes 5 and 6
3809
        return (5 + ACK_index);
3810
      }
frtabu's avatar
frtabu committed
3811

3812 3813 3814
      if (subframe == 3) { // ACK subframe 9
        return 9;  // To be updated
      }
frtabu's avatar
frtabu committed
3815

3816 3817 3818
      if (subframe == 7) { // ACK subframes 0 and 1
        return ACK_index;  // To be updated
      }
frtabu's avatar
frtabu committed
3819

3820 3821
      if (subframe == 8) { // ACK subframe 4
        return 4;  // To be updated
3822
      }
frtabu's avatar
frtabu committed
3823

3824
      AssertFatal(1 == 0, "illegal subframe %d for tdd_config %ld\n",
3825 3826
                  subframe,
                  tdd_Config->subframeAssignment);
3827 3828
      break;
  }
frtabu's avatar
frtabu committed
3829

3830
  return 0;
3831
}
3832

3833
//------------------------------------------------------------------------------
3834
void
3835 3836
extract_harq(module_id_t mod_idP,
             int CC_idP,
3837
             int UE_id,
3838
             frame_t frameP,
3839
             sub_frame_t subframeP,
3840 3841
             void *harq_indication,
             int format)
3842
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
3843
{
3844 3845
  eNB_MAC_INST *eNB = RC.mac[mod_idP];
  UE_list_t *UE_list = &eNB->UE_list;
3846
  UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
3847
  rnti_t rnti = UE_RNTI(mod_idP, UE_id);
3848
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
3849 3850 3851 3852 3853 3854 3855
  nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd;
  nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd;
  uint16_t num_ack_nak;
  int numCC = UE_list->numactiveCCs[UE_id];
  int pCCid = UE_list->pCC_id[UE_id];
  int spatial_bundling = 0;
  int tmode[5];
3856
  int i, j, m;
3857
  uint8_t *pdu;
3858 3859 3860
  sub_frame_t subframe_tx;
  int frame_tx;
  uint8_t harq_pid;
3861
  LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated;
frtabu's avatar
frtabu committed
3862

3863 3864
  if (physicalConfigDedicated != NULL && physicalConfigDedicated->pucch_ConfigDedicated != NULL &&
      physicalConfigDedicated->ext7 != NULL && physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13 != NULL &&
3865 3866
      ((physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUCCH_r13 && format == 0) ||
       (physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUSCH_r13 && format == 1))) {
3867
    spatial_bundling = 1;
3868
  }
frtabu's avatar
frtabu committed
3869

3870
  for (i = 0; i < numCC; i++) {
3871 3872
    tmode[i] = get_tmode(mod_idP,
                         i,
3873 3874
                         UE_id);
  }
frtabu's avatar
frtabu committed
3875

3876 3877 3878 3879
  if (cc->tdd_Config) {
    harq_indication_tdd = (nfapi_harq_indication_tdd_rel13_t *) harq_indication;
    //    pdu = &harq_indication_tdd->harq_tb_n[0];
    num_ack_nak = harq_indication_tdd->number_of_ack_nack;
3880

3881
    switch (harq_indication_tdd->mode) {
3882
      case 0:   // Format 1a/b bundling
3883
        AssertFatal(numCC == 1, "numCC %d > 1, should not be using Format1a/b\n",
3884 3885 3886
                    numCC);
        int M = ul_ACK_subframe2M(cc->tdd_Config,
                                  subframeP);
3887

3888 3889
        for (m=0; m<M; m++) {
          subframe_tx = ul_ACK_subframe2dl_subframe(cc->tdd_Config,
frtabu's avatar
frtabu committed
3890 3891
                        subframeP,
                        m);
3892

3893 3894
          if (frameP==1023&&subframeP>5) frame_tx=-1;
          else frame_tx = subframeP < 4 ? frameP -1 : frameP;
3895

3896 3897 3898 3899
          harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,
                                                 frame_tx,
                                                 subframe_tx);
          RA_t *ra = &eNB->common_channels[CC_idP].ra[0];
3900

3901 3902
          if(num_ack_nak == 1) {
            if (harq_indication_tdd->harq_data[0].bundling.value_0 == 1) { //ack
3903 3904
              sched_ctl->round[CC_idP][harq_pid] = 8; // release HARQ process
              sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
3905 3906 3907 3908 3909 3910 3911
              LOG_D(MAC, "frame %d subframe %d Acking (%d,%d) harq_pid %d round %d\n",
                    frameP,
                    subframeP,
                    frame_tx,
                    subframe_tx,
                    harq_pid,
                    sched_ctl->round[CC_idP][harq_pid]);
3912
            } else { //nack
3913
              if (sched_ctl->round[CC_idP][harq_pid] < 8) sched_ctl->round[CC_idP][harq_pid]++;
3914 3915 3916 3917 3918 3919

              if (sched_ctl->round[CC_idP][harq_pid] == 4) {
                sched_ctl->round[CC_idP][harq_pid] = 8;     // release HARQ process
                sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
              }

3920 3921 3922 3923 3924 3925 3926
              LOG_D(MAC,"frame %d subframe %d Nacking (%d,%d) harq_pid %d round %d\n",
                    frameP,
                    subframeP,
                    frame_tx,
                    subframe_tx,
                    harq_pid,
                    sched_ctl->round[CC_idP][harq_pid]);
3927

3928
              if (sched_ctl->round[CC_idP][harq_pid] == 8) {
3929
                for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
3930
                  if (ra[ra_i].rnti == rnti && ra[ra_i].state == WAITMSG4ACK) {
3931 3932
                    //Msg NACK num to MAC ,remove UE
                    // add UE info to freeList
3933
                    LOG_I(RRC, "put UE %x into freeList\n",
3934
                          rnti);
3935
                    put_UE_in_freelist(mod_idP,
frtabu's avatar
frtabu committed
3936 3937
                                       rnti,
                                       1);
3938 3939 3940 3941 3942 3943 3944
                  }
                }
              }
            }
          }

          for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
3945 3946 3947 3948 3949 3950 3951
            if (ra[ra_i].rnti == rnti && ra[ra_i].state == MSGCRNTI_ACK && ra[ra_i].crnti_harq_pid == harq_pid) {
              LOG_D(MAC,"CRNTI Reconfiguration: ACK %d rnti %x round %d frame %d subframe %d \n",
                    harq_indication_tdd->harq_data[0].bundling.value_0,
                    rnti,
                    sched_ctl->round[CC_idP][harq_pid],
                    frameP,
                    subframeP);
Stefan's avatar
Stefan committed
3952

3953
              if (num_ack_nak == 1 && harq_indication_tdd->harq_data[0].bundling.value_0 == 1) {
3954 3955 3956
                cancel_ra_proc(mod_idP,
                               CC_idP,
                               frameP,
3957
                               ra[ra_i].rnti);
3958 3959
              } else {
                if(sched_ctl->round[CC_idP][harq_pid] == 7) {
3960 3961 3962
                  cancel_ra_proc(mod_idP,
                                 CC_idP,
                                 frameP,
3963
                                 ra[ra_i].rnti);
3964 3965
                }
              }
frtabu's avatar
frtabu committed
3966

3967 3968
              break;
            }
3969 3970
          }
        }
3971

3972 3973 3974 3975 3976 3977 3978
        break;

      case 1:   // Channel Selection
      case 2:   // Format 3
      case 3:   // Format 4
      case 4:   // Format 5
        break;
3979 3980 3981 3982 3983
    }
  } else {
    harq_indication_fdd = (nfapi_harq_indication_fdd_rel13_t *) harq_indication;
    num_ack_nak         = harq_indication_fdd->number_of_ack_nack;
    pdu                 = &harq_indication_fdd->harq_tb_n[0];
3984
    harq_pid = ((10 * frameP) + subframeP + 10236) & 7;
3985 3986 3987 3988 3989 3990 3991 3992
    LOG_D(MAC, "frame %d subframe %d harq_pid %d mode %d tmode[0] %d num_ack_nak %d round %d\n",
          frameP,
          subframeP,
          harq_pid,
          harq_indication_fdd->mode,
          tmode[0],
          num_ack_nak,
          sched_ctl->round[CC_idP][harq_pid]);
3993

3994 3995
    // use 1 HARQ proces of BL/CE UE for now
    if (UE_list->UE_template[pCCid][UE_id].rach_resource_type > 0) harq_pid = 0;
3996 3997

    switch (harq_indication_fdd->mode) {
Stefan's avatar
Stefan committed
3998
      case 0:   // Format 1a/b (10.1.2.1)
3999
        AssertFatal(numCC == 1, "numCC %d > 1, should not be using Format1a/b\n",
4000
                    numCC);
Stefan's avatar
Stefan committed
4001 4002

        if (tmode[0] == 1 || tmode[0] == 2 || tmode[0] == 5 || tmode[0] == 6 || tmode[0] == 7) {  // NOTE: have to handle the case of TM9-10 with 1 antenna port
4003
          // single ACK/NAK bit
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4004 4005 4006 4007
          AssertFatal(num_ack_nak == 1, "num_ack_nak %d > 1 for 1 CC and single-layer transmission frame:%d subframe:%d\n",
                      num_ack_nak,
                      frameP,
                      subframeP);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4008 4009

          // In case of nFAPI, sometimes timing of eNB and UE become different.
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4010
          // So if nfapi_mode == 2(VNF), this function don't check assertion to avoid process exit.
frtabu's avatar
frtabu committed
4011
          if (NFAPI_MODE != NFAPI_MODE_VNF) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4012
            AssertFatal(sched_ctl->round[CC_idP][harq_pid] < 8, "Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",
4013 4014
                        harq_pid,
                        UE_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4015
                        rnti);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4016 4017
          } else {
            if (sched_ctl->round[CC_idP][harq_pid] == 8) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4018
              LOG_E(MAC,"Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",
4019 4020
                    harq_pid,
                    UE_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4021
                    rnti);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4022 4023
              return;
            }
4024
          }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4025 4026

          AssertFatal(pdu[0] == 1 || pdu[0] == 2 || pdu[0] == 4, "Received ACK/NAK %d which is not 1 or 2 for harq_pid %d from UE %d/%x\n",
4027 4028 4029
                      pdu[0],
                      harq_pid,
                      UE_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4030
                      rnti);
4031 4032
          LOG_D(MAC, "Received %d for harq_pid %d\n",
                pdu[0],
4033 4034
                harq_pid);
          RA_t *ra = &eNB->common_channels[CC_idP].ra[0];
4035 4036

          for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
4037
            if (ra[ra_i].rnti == rnti && ra[ra_i].state == MSGCRNTI_ACK && ra[ra_i].crnti_harq_pid == harq_pid) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4038 4039 4040 4041
              LOG_D(MAC,"CRNTI Reconfiguration: ACK %d rnti %x round %d frame %d subframe %d \n",
                    pdu[0],
                    rnti,
                    sched_ctl->round[CC_idP][harq_pid],
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4042 4043
                    frameP,
                    subframeP);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4044 4045

              if (pdu[0] == 1) {
4046 4047 4048
                cancel_ra_proc(mod_idP,
                               CC_idP,
                               frameP,
4049
                               ra[ra_i].rnti);
4050
              } else {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4051
                if (sched_ctl->round[CC_idP][harq_pid] == 7) {
4052 4053 4054
                  cancel_ra_proc(mod_idP,
                                 CC_idP,
                                 frameP,
4055
                                 ra[ra_i].rnti);
4056 4057
                }
              }
frtabu's avatar
frtabu committed
4058

4059
              break;
Xu Bo's avatar
Xu Bo committed
4060
            }
4061
          }
4062

nepes's avatar
nepes committed
4063
          LOG_D(MAC, "In extract_harq(): pdu[0] = %d for harq_pid = %d\n", pdu[0], harq_pid);
4064

4065 4066
          if (pdu[0] == 1) {  // ACK
            sched_ctl->round[CC_idP][harq_pid] = 8; // release HARQ process
4067
            sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
4068 4069
            /* CDRX: PUCCH gives an ACK, so reset corresponding HARQ RTT */
            sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4070 4071 4072 4073 4074 4075
          } else if (pdu[0] == 2 || pdu[0] == 4) {  // NAK (treat DTX as NAK)
            sched_ctl->round[CC_idP][harq_pid]++; // increment round

            if (sched_ctl->round[CC_idP][harq_pid] == 4) {
              sched_ctl->round[CC_idP][harq_pid] = 8; // release HARQ process
              sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
4076 4077
              /* CDRX: PUCCH gives an NACK and max number of repetitions reached so reset corresponding HARQ RTT */
              sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4078 4079 4080 4081 4082
            }

            if (sched_ctl->round[CC_idP][harq_pid] == 8) {
              for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
                if((ra[ra_i].rnti == rnti) && (ra[ra_i].state == WAITMSG4ACK)) {
4083
                  // Msg NACK num to MAC ,remove UE
4084
                  // add UE info to freeList
4085
                  LOG_I(RRC, "put UE %x into freeList\n",
4086
                        rnti);
4087 4088
                  put_UE_in_freelist(mod_idP,
                                     rnti,
4089
                                     1);
4090 4091 4092
                }
              }
            }
4093
          }
4094 4095
        } else {
          // one or two ACK/NAK bits
4096
          AssertFatal(num_ack_nak <= 2, "num_ack_nak %d > 2 for 1 CC and TM3/4/8/9/10\n",
4097 4098
                      num_ack_nak);

4099
          if (num_ack_nak == 2 && sched_ctl->round[CC_idP][harq_pid] < 8 && sched_ctl->tbcnt[CC_idP][harq_pid] == 1 && pdu[0] == 1 && pdu[1] == 1) {
4100
            sched_ctl->round[CC_idP][harq_pid] = 8;
4101
            sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
4102 4103
            /* CDRX: PUCCH gives an ACK, so reset corresponding HARQ RTT */
            sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4104
          }
4105 4106 4107 4108 4109 4110 4111 4112 4113 4114

          if ((num_ack_nak == 2)
              && (sched_ctl->round[CC_idP][harq_pid] < 8)
              && (sched_ctl->tbcnt[CC_idP][harq_pid] == 1)
              && (pdu[0] == 2) && (pdu[1] == 2)) {
            sched_ctl->round[CC_idP][harq_pid]++;

            if (sched_ctl->round[CC_idP][harq_pid] == 4) {
              sched_ctl->round[CC_idP][harq_pid] = 8;     // release HARQ process
              sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
4115 4116
              /* CDRX: PUCCH gives an NACK and max number of repetitions reached so reset corresponding HARQ RTT */
              sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4117 4118 4119 4120 4121 4122 4123 4124 4125 4126 4127 4128 4129 4130 4131
            }
          } else if (((num_ack_nak == 2)
                      && (sched_ctl->round[CC_idP][harq_pid] < 8)
                      && (sched_ctl->tbcnt[0][harq_pid] == 2)
                      && (pdu[0] == 1) && (pdu[1] == 2))
                     || ((num_ack_nak == 2)
                         && (sched_ctl->round[CC_idP][harq_pid] < 8)
                         && (sched_ctl->tbcnt[CC_idP][harq_pid] == 2)
                         && (pdu[0] == 2) && (pdu[1] == 1))) {
            sched_ctl->round[CC_idP][harq_pid]++;
            sched_ctl->tbcnt[CC_idP][harq_pid] = 1;

            if (sched_ctl->round[CC_idP][harq_pid] == 4) {
              sched_ctl->round[CC_idP][harq_pid] = 8;     // release HARQ process
              sched_ctl->tbcnt[CC_idP][harq_pid] = 0;  /* TODO: do we have to set it to 0? */
4132 4133
              /* CDRX: PUCCH gives an NACK and max number of repetitions reached so reset corresponding HARQ RTT */
              sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4134 4135 4136 4137 4138 4139 4140 4141 4142 4143
            }
          } else if ((num_ack_nak == 2)
                     && (sched_ctl->round[CC_idP][harq_pid] < 8)
                     && (sched_ctl->tbcnt[CC_idP][harq_pid] == 2)
                     && (pdu[0] == 2) && (pdu[1] == 2)) {
            sched_ctl->round[CC_idP][harq_pid]++;

            if (sched_ctl->round[CC_idP][harq_pid] == 4) {
              sched_ctl->round[CC_idP][harq_pid] = 8;     // release HARQ process
              sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
4144 4145
              /* CDRX: PUCCH gives an NACK and max number of repetitions reached so reset corresponding HARQ RTT */
              sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4146 4147
            }
          } else
4148
            AssertFatal(1 == 0, "Illegal ACK/NAK/round combination (%d,%d,%d,%d,%d) for harq_pid %d, UE %d/%x\n",
4149 4150
                        num_ack_nak,
                        sched_ctl->round[CC_idP][harq_pid],
4151
                        sched_ctl->round[CC_idP][harq_pid],
4152
                        pdu[0],
4153 4154 4155
                        pdu[1],
                        harq_pid,
                        UE_id,
4156
                        rnti);
4157
        }
4158 4159 4160 4161

        break;

      case 1:   // FDD Channel Selection (10.1.2.2.1), must be received for 2 serving cells
4162
        AssertFatal(numCC == 2, "Should not receive harq indication with channel selection with %d active CCs\n",
4163 4164 4165 4166 4167 4168 4169 4170 4171 4172 4173 4174 4175 4176 4177 4178 4179 4180 4181
                    numCC);

        if ((num_ack_nak == 2)
            && (sched_ctl->round[pCCid][harq_pid] < 8)
            && (sched_ctl->round[1 - pCCid][harq_pid] < 8)
            && (sched_ctl->tbcnt[pCCid][harq_pid] == 1)
            && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 1)) {
          AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n",
                      pdu[0]);
          AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n",
                      pdu[1]);

          if (pdu[0] == 1)
            sched_ctl->round[pCCid][harq_pid] = 8;
          else {
            sched_ctl->round[pCCid][harq_pid]++;

            if (sched_ctl->round[pCCid][harq_pid] == 4)
              sched_ctl->round[pCCid][harq_pid] = 8;
4182
          }
4183 4184 4185 4186 4187 4188 4189 4190

          if (pdu[1] == 1)
            sched_ctl->round[1 - pCCid][harq_pid] = 8;
          else {
            sched_ctl->round[1 - pCCid][harq_pid]++;

            if (sched_ctl->round[1 - pCCid][harq_pid] == 4)
              sched_ctl->round[1 - pCCid][harq_pid] = 8;
4191
          }
4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203
        }     // A=2
        else if ((num_ack_nak == 3)
                 && (sched_ctl->round[pCCid][harq_pid] < 8)
                 && (sched_ctl->tbcnt[pCCid][harq_pid] == 2)
                 && (sched_ctl->round[1 - pCCid][harq_pid] < 8)
                 && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 1)) {
          AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n",
                      pdu[0]);
          AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n",
                      pdu[1]);
          AssertFatal(pdu[2] <= 3, "pdu[2] %d is not ACK/NAK/DTX\n",
                      pdu[2]);
4204
          AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 2, "sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",
4205 4206 4207
                      pCCid,
                      harq_pid,
                      UE_id,
4208 4209
                      rnti);
          AssertFatal(sched_ctl->tbcnt[1 - pCCid][harq_pid] == 1, "sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",
4210 4211 4212
                      1 - pCCid,
                      harq_pid,
                      UE_id,
4213 4214 4215
                      rnti);

          if (pdu[0] == 1 && pdu[1] == 1) { // both ACK
4216 4217
            sched_ctl->round[pCCid][harq_pid] = 8;
            sched_ctl->tbcnt[pCCid][harq_pid] = 0;
4218
          } else if ((pdu[0] == 2 && pdu[1] == 1) || (pdu[0] == 1 && pdu[1] == 2)) {
4219 4220 4221 4222 4223 4224 4225 4226 4227
            sched_ctl->round[pCCid][harq_pid]++;
            sched_ctl->tbcnt[pCCid][harq_pid] = 1;

            if (sched_ctl->round[pCCid][harq_pid] == 4) {
              sched_ctl->round[pCCid][harq_pid] = 8;
              sched_ctl->tbcnt[pCCid][harq_pid] = 0; /* TODO: do we have to set it to 0? */
            }
          } else {
            sched_ctl->round[pCCid][harq_pid]++;
4228

4229 4230 4231 4232
            if (sched_ctl->round[pCCid][harq_pid] == 4) {
              sched_ctl->round[pCCid][harq_pid] = 8;
              sched_ctl->tbcnt[pCCid][harq_pid] = 0;
            }
4233
          }
4234

4235
          if (pdu[2] == 1) sched_ctl->round[1 - pCCid][harq_pid] = 8;
4236 4237 4238 4239 4240 4241
          else {
            sched_ctl->round[1 - pCCid][harq_pid]++;

            if (sched_ctl->round[1 - pCCid][harq_pid] == 4) {
              sched_ctl->round[1 - pCCid][harq_pid] = 8;
            }
4242
          }
4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254
        }     // A=3 primary cell has 2 TBs
        else if ((num_ack_nak == 3)
                 && (sched_ctl->round[1 - pCCid][harq_pid] < 8)
                 && (sched_ctl->round[pCCid][harq_pid] < 8)
                 && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 2)
                 && (sched_ctl->tbcnt[pCCid][harq_pid] == 1)) {
          AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n",
                      pdu[0]);
          AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n",
                      pdu[1]);
          AssertFatal(pdu[2] <= 3, "pdu[2] %d is not ACK/NAK/DTX\n",
                      pdu[2]);
4255
          AssertFatal(sched_ctl->tbcnt[1 - pCCid][harq_pid] == 2, "sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",
4256 4257 4258
                      1 - pCCid,
                      harq_pid,
                      UE_id,
4259 4260
                      rnti);
          AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 1, "sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",
4261 4262 4263
                      pCCid,
                      harq_pid,
                      UE_id,
4264 4265 4266
                      rnti);

          if (pdu[0] == 1 && pdu[1] == 1) { // both ACK
4267 4268
            sched_ctl->round[1 - pCCid][harq_pid] = 8;
            sched_ctl->tbcnt[1 - pCCid][harq_pid] = 0;
4269
          } else if ((pdu[0] >= 2 && pdu[1] == 1) || (pdu[0] == 1 && pdu[1] >= 2)) { // one ACK
4270 4271 4272 4273 4274 4275 4276 4277 4278 4279 4280 4281 4282 4283
            sched_ctl->round[1 - pCCid][harq_pid]++;
            sched_ctl->tbcnt[1 - pCCid][harq_pid] = 1;

            if (sched_ctl->round[1 - pCCid][harq_pid] == 4) {
              sched_ctl->round[1 - pCCid][harq_pid] = 8;
              sched_ctl->tbcnt[1 - pCCid][harq_pid] = 0;
            }
          } else {    // both NAK/DTX
            sched_ctl->round[1 - pCCid][harq_pid]++;

            if (sched_ctl->round[1 - pCCid][harq_pid] == 4) {
              sched_ctl->round[1 - pCCid][harq_pid] = 8;
              sched_ctl->tbcnt[1 - pCCid][harq_pid] = 0;
            }
4284
          }
4285

4286
          if (pdu[2] == 1) sched_ctl->round[pCCid][harq_pid] = 8;
4287 4288 4289 4290 4291 4292
          else {
            sched_ctl->round[pCCid][harq_pid]++;

            if (sched_ctl->round[pCCid][harq_pid] == 4) {
              sched_ctl->round[pCCid][harq_pid] = 8;
            }
4293
          }
4294 4295
        }     // A=3 secondary cell has 2 TBs

4296
#if MAX_NUM_CCs>1
4297 4298 4299 4300 4301 4302 4303 4304 4305 4306 4307 4308 4309
        else if ((num_ack_nak == 4)
                 && (sched_ctl->round[0][harq_pid] < 8)
                 && (sched_ctl->round[1][harq_pid] < 8)
                 && (sched_ctl->tbcnt[1 - pCCid][harq_pid] == 2)
                 && (sched_ctl->tbcnt[pCCid][harq_pid] == 2)) {
          AssertFatal(pdu[0] <= 3, "pdu[0] %d is not ACK/NAK/DTX\n",
                      pdu[0]);
          AssertFatal(pdu[1] <= 3, "pdu[1] %d is not ACK/NAK/DTX\n",
                      pdu[1]);
          AssertFatal(pdu[2] <= 3, "pdu[2] %d is not ACK/NAK/DTX\n",
                      pdu[2]);
          AssertFatal(pdu[3] <= 3, "pdu[3] %d is not ACK/NAK/DTX\n",
                      pdu[3]);
4310
          AssertFatal(sched_ctl->tbcnt[0][harq_pid] == 2, "sched_ctl->tbcnt[0][%d] != 2 for UE %d/%x\n",
4311 4312
                      harq_pid,
                      UE_id,
4313 4314
                      rnti);
          AssertFatal(sched_ctl->tbcnt[1][harq_pid] == 2, "sched_ctl->tbcnt[1][%d] != 2 for UE %d/%x\n",
4315 4316
                      harq_pid,
                      UE_id,
4317 4318 4319
                      rnti);

          if (pdu[0] == 1 && pdu[1] == 1) { // both ACK
4320 4321
            sched_ctl->round[0][harq_pid] = 8;
            sched_ctl->tbcnt[0][harq_pid] = 0;
4322
          } else if ((pdu[0] >= 2 && pdu[1] == 1) || (pdu[0] == 1 && pdu[1] >= 2)) { // one ACK
4323 4324 4325 4326 4327 4328 4329 4330 4331
            sched_ctl->round[0][harq_pid]++;
            sched_ctl->tbcnt[0][harq_pid] = 1;

            if (sched_ctl->round[0][harq_pid] == 4) {
              sched_ctl->round[0][harq_pid] = 8;
              sched_ctl->tbcnt[0][harq_pid] = 0;
            }
          } else {    // both NAK/DTX
            sched_ctl->round[0][harq_pid]++;
4332

4333 4334 4335 4336
            if (sched_ctl->round[0][harq_pid] == 4) {
              sched_ctl->round[0][harq_pid] = 8;
              sched_ctl->tbcnt[0][harq_pid] = 0;
            }
4337
          }
4338

4339
          if (pdu[2] == 1 && pdu[3] == 1) { // both ACK
4340 4341
            sched_ctl->round[1][harq_pid] = 8;
            sched_ctl->tbcnt[1][harq_pid] = 0;
4342
          } else if ((pdu[2] >= 2 && pdu[3] == 1) || (pdu[2] == 1 && pdu[3] >= 2)) { // one ACK
4343 4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356
            sched_ctl->round[1][harq_pid]++;
            sched_ctl->tbcnt[1][harq_pid] = 1;

            if (sched_ctl->round[1][harq_pid] == 4) {
              sched_ctl->round[1][harq_pid] = 8;
              sched_ctl->tbcnt[1][harq_pid] = 0;
            }
          } else {    // both NAK/DTX
            sched_ctl->round[1][harq_pid]++;

            if (sched_ctl->round[1][harq_pid] == 4) {
              sched_ctl->round[1][harq_pid] = 8;
              sched_ctl->tbcnt[1][harq_pid] = 0;
            }
4357
          }
4358 4359
        }     // A=4 both serving cells have 2 TBs

4360
#endif
4361 4362 4363
        break;

      case 2:   // Format 3
4364
        AssertFatal(numCC > 2, "Should not receive harq indication with FDD format 3 with %d < 3 active CCs\n",
4365 4366 4367
                    numCC);

        for (i = 0, j = 0; i < numCC; i++) {
4368 4369
          if (sched_ctl->round[i][harq_pid] < 8) {
            if (tmode[i] == 1 || tmode[i] == 2 || tmode[0] == 5 || tmode[0] == 6 || tmode[0] == 7) {
4370 4371 4372 4373 4374 4375 4376 4377 4378 4379 4380
              if (pdu[j] == 1) {
                sched_ctl->round[i][harq_pid] = 8;
                sched_ctl->tbcnt[i][harq_pid] = 0;
              } else if (pdu[j] == 2) {
                sched_ctl->round[i][harq_pid]++;

                if (sched_ctl->round[i][harq_pid] == 4) {
                  sched_ctl->round[i][harq_pid] = 8;
                  sched_ctl->tbcnt[i][harq_pid] = 0;
                }
              } else
4381
                AssertFatal(1 == 0, "Illegal harq_ack value for CC %d harq_pid %d (%d) UE %d/%x\n",
4382 4383 4384 4385
                            i,
                            harq_pid,
                            pdu[j],
                            UE_id,
4386
                            rnti);
4387 4388 4389

              j++;
            } else if (spatial_bundling == 0) {
4390
              if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 1 && pdu[j + 1] == 1) {
4391 4392
                sched_ctl->round[i][harq_pid] = 8;
                sched_ctl->tbcnt[i][harq_pid] = 0;
4393
              } else if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 1 && pdu[j + 1] == 2) {
4394 4395 4396 4397 4398 4399 4400
                sched_ctl->round[i][harq_pid]++;
                sched_ctl->tbcnt[i][harq_pid] = 1;

                if (sched_ctl->round[i][harq_pid] == 4) {
                  sched_ctl->round[i][harq_pid] = 8;
                  sched_ctl->tbcnt[i][harq_pid] = 0;
                }
4401
              } else if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 2 && pdu[j + 1] == 1) {
4402 4403 4404 4405 4406 4407 4408
                sched_ctl->round[i][harq_pid]++;
                sched_ctl->tbcnt[i][harq_pid] = 1;

                if (sched_ctl->round[i][harq_pid] == 4) {
                  sched_ctl->round[i][harq_pid] = 8;
                  sched_ctl->tbcnt[i][harq_pid] = 0;
                }
4409
              } else if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 2 && pdu[j + 1] == 2) {
4410 4411 4412 4413 4414 4415 4416
                sched_ctl->round[i][harq_pid]++;

                if (sched_ctl->round[i][harq_pid] == 4) {
                  sched_ctl->round[i][harq_pid] = 8;
                  sched_ctl->tbcnt[i][harq_pid] = 0;
                }
              } else
4417
                AssertFatal(1 == 0, "Illegal combination for CC %d harq_pid %d (%d,%d,%d) UE %d/%x\n",
4418
                            i,
4419
                            harq_pid,
4420
                            sched_ctl->tbcnt[i][harq_pid],
4421 4422 4423
                            pdu[j],
                            pdu[j + 1],
                            UE_id,
4424
                            rnti);
4425 4426 4427 4428 4429 4430 4431 4432 4433 4434 4435 4436 4437

              j += 2;
            } else if (spatial_bundling == 1) {
              if (pdu[j] == 1) {
                sched_ctl->round[i][harq_pid] = 8;
                sched_ctl->tbcnt[i][harq_pid] = 0;
              } else if (pdu[j] == 2) {
                sched_ctl->round[i][harq_pid]++;

                if (sched_ctl->round[i][harq_pid] == 4) {
                  sched_ctl->round[i][harq_pid] = 8;
                  sched_ctl->tbcnt[i][harq_pid] = 0;
                }
4438 4439
              } else {
                AssertFatal(1 == 0, "Illegal hack_nak value %d for CC %d harq_pid %d UE %d/%x\n",
4440 4441 4442 4443
                            pdu[j],
                            i,
                            harq_pid,
                            UE_id,
4444
                            rnti);
4445
              }
frtabu's avatar
frtabu committed
4446

4447
              j++;
4448 4449
            } else {
              AssertFatal(1 == 0, "Illegal value for spatial_bundling %d\n",
4450
                          spatial_bundling);
4451 4452 4453
            }
          }
        }
4454 4455 4456 4457

        break;

      case 3:   // Format 4
4458
        AssertFatal(1 == 0, "Should not receive harq indication with Format 4\n");
4459 4460 4461
        break;

      case 4:   // Format 5
4462
        AssertFatal(1 == 0, "Should not receive harq indication with Format 5\n");
4463
        break;
4464
    }
4465
  }
frtabu's avatar
frtabu committed
4466

4467
  return;
4468 4469
}

4470
//------------------------------------------------------------------------------
4471
void
4472 4473
extract_pucch_csi(module_id_t mod_idP,
                  int CC_idP,
4474
                  int UE_id,
4475
                  frame_t frameP,
4476
                  sub_frame_t subframeP,
4477 4478
                  uint8_t *pdu,
                  uint8_t length)
4479
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
4480
{
4481
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
4482
  UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
4483 4484 4485 4486 4487
  COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
  int no_pmi;
  uint8_t Ltab[6] = { 0, 2, 4, 4, 4, 4 };
  uint8_t Jtab[6] = { 0, 2, 2, 3, 4, 4 };
  int feedback_cnt;
4488
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",
4489
              UE_id);
4490
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n",
4491
              UE_id);
4492 4493
  struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic;
  AssertFatal(cqi_ReportPeriodic != NULL, "cqi_ReportPeriodic is null for UE %d\n",
4494
              UE_id);
4495
  // determine feedback mode
4496
  AssertFatal(cqi_ReportPeriodic->present != LTE_CQI_ReportPeriodic_PR_NOTHING, "cqi_ReportPeriodic->present == LTE_CQI_ReportPeriodic_PR_NOTHING!\n");
4497
  AssertFatal(cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present != LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING,
4498
              "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n");
4499 4500 4501
  uint16_t Npd, N_OFFSET_CQI;
  int H, K, bandwidth_part, L, Lmask;
  int ri = sched_ctl->periodic_ri_received[CC_idP];
4502 4503 4504 4505
  get_csi_params(cc,
                 cqi_ReportPeriodic,
                 &Npd,
                 &N_OFFSET_CQI,
4506
                 &H);
4507 4508 4509 4510 4511
  K = (H - 1) / Jtab[cc->mib->message.dl_Bandwidth];
  L = Ltab[cc->mib->message.dl_Bandwidth];
  Lmask = L - 1;
  feedback_cnt = (((frameP * 10) + subframeP) / Npd) % H;

4512 4513
  if (feedback_cnt > 0) bandwidth_part = (feedback_cnt - 1) % K;
  else bandwidth_part = 0;
4514

4515 4516
  switch (get_tmode(mod_idP,
                    CC_idP,
4517
                    UE_id)) {
4518 4519 4520 4521 4522 4523 4524 4525 4526 4527 4528 4529
    case 1:
    case 2:
    case 3:
    case 7:
      no_pmi = 1;
      break;

    case 4:
    case 5:
    case 6:
      no_pmi = 0;
      break;
4530

4531 4532 4533
    default:
      // note: need to check TM8-10 without PMI/RI or with 1 antenna port (see Section 5.2.3.3.1 from 36.213)
      no_pmi = 0;
4534
      break;
frtabu's avatar
frtabu committed
4535
  }
4536

4537
  if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI ||
4538
      feedback_cnt == 0) {
4539
    // Note: This implements only Tables: 5.3.3.1-1,5.3.3.1-1A and 5.3.3.1-2 from 36.213 (1,2,4 antenna ports Wideband CQI/PMI)
4540
    if (no_pmi == 1) {  // get spatial_diffcqi if needed
4541
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4542 4543
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0] >> 4) & 7;
    } else if (cc->p_eNB == 2 && ri == 1) {
4544 4545 4546
      // p=2 Rank 1 wideband CQI/PMI 6 bits
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
      sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 4) & 3;
4547
    } else if (cc->p_eNB == 2 && ri > 1) {
4548 4549
      // p=2 Rank 2 wideband CQI/PMI 8 bits
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4550
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0] >> 4) & 7;
4551
      sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 7) & 1;
4552
    } else if (cc->p_eNB == 4 && ri == 1) {
4553 4554
      // p=4 Rank 1 wideband CQI/PMI 8 bits
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4555 4556
      sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 4) & 0x0F;
    } else if (cc->p_eNB == 4 && ri > 1) {
4557 4558
      // p=4 Rank 2 wideband CQI/PMI 11 bits
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4559
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0] >> 4) & 7;
4560 4561
      sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 7) & 0xF;
    } else
4562
      AssertFatal(1 == 0, "illegal combination p %d, ri %d, no_pmi %d\n",
4563 4564
                  cc->p_eNB,
                  ri,
4565
                  no_pmi);
4566 4567 4568 4569 4570 4571 4572 4573
  } else if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) {
    // This is Table 5.2.3.3.2-2 for 36.213
    if (ri == 1) {
      //4+Ltab[cc->mib->message.dl_Bandwidth] bits
      sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part * L) +((pdu[0] >> 4) & Lmask)] = pdu[0] & 0xF;
    } else if (ri > 1) {
      //7+Ltab[cc->mib->message.dl_Bandwidth] bits;
      sched_ctl->periodic_subband_spatial_diffcqi[CC_idP][(bandwidth_part * L) + ((pdu[0] >> 7) & Lmask)] = (pdu[0] >> 4) & 7;
4574
      sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part * L) + ((pdu[0] >> 7) & Lmask)] = pdu[0] & 0xF;
4575
    }
4576
  }
frtabu's avatar
frtabu committed
4577

4578
  return;
4579 4580
}

4581
//------------------------------------------------------------------------------
4582
void
4583 4584
extract_pusch_csi(module_id_t mod_idP,
                  int CC_idP,
4585
                  int UE_id,
4586
                  frame_t frameP,
4587
                  sub_frame_t subframeP,
4588 4589
                  uint8_t *pdu,
                  uint8_t length)
4590
//------------------------------------------------------------------------------
4591
{
4592 4593
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
  COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
4594
  UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
4595 4596 4597 4598 4599 4600 4601 4602
  int Ntab[6] = { 0, 4, 7, 9, 10, 13 };
  int Ntab_uesel[6] = { 0, 8, 13, 17, 19, 25 };
  int Ltab_uesel[6] = { 0, 6, 9, 13, 15, 18 };
  int Mtab_uesel[6] = { 0, 1, 3, 5, 6, 6 };
  int v[6];
  int i;
  uint64_t p = *(uint64_t *) pdu;
  int curbyte, curbit;
4603
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",
4604
              UE_id);
4605
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n",
4606
              UE_id);
4607
  LTE_CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic
4608
    = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
4609
  AssertFatal(cqi_ReportModeAperiodic  != NULL, "cqi_ReportModeAperiodic is null for UE %d\n",
4610
              UE_id);
4611 4612 4613 4614 4615 4616 4617 4618
  int N = Ntab[cc->mib->message.dl_Bandwidth];
  int tmode = get_tmode(mod_idP, CC_idP, UE_id);
  int ri = sched_ctl->aperiodic_ri_received[CC_idP];
  int r, diffcqi0 = 0, diffcqi1 = 0, pmi_uesel = 0;
  int bw = cc->mib->message.dl_Bandwidth;
  int m;

  switch (*cqi_ReportModeAperiodic) {
4619 4620 4621
    case LTE_CQI_ReportModeAperiodic_rm12:
      AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n");
      // wideband multiple PMI (TM4/6), Table 5.2.2.6.1-1 (for TM4/6)
4622
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm12\n",
4623 4624 4625
                  tmode);

      if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213
4626 4627
        if (ri == 1 && cc->p_eNB == 2) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4628 4629 4630 4631 4632 4633 4634 4635
          p >>= 4;

          for (i = 0; i < N; i++) {
            sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x03);
            p >>= 2;
          }
        }

4636 4637
        if (ri == 2 && cc->p_eNB == 2) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4638
          p >>= 4;
4639
          sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4640 4641 4642 4643 4644 4645 4646 4647
          p >>= 4;

          for (i = 0; i < N; i++) {
            sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x01);
            p >>= 1;
          }
        }

4648 4649
        if (ri == 1 && cc->p_eNB == 4) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4650 4651 4652 4653 4654 4655 4656 4657
          p >>= 4;

          for (i = 0; i < N; i++) {
            sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x03);
            p >>= 4;
          }
        }

4658 4659
        if (ri == 2 && cc->p_eNB == 4) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4660
          p >>= 4;
4661
          sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4662 4663 4664 4665 4666 4667 4668 4669 4670 4671
          p >>= 4;

          for (i = 0; i < N; i++) {
            sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x01);
            p >>= 4;
          }
        }
      }     // if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213
      else {
        AssertFatal(1 == 0, "support for TM 8-10 to be done\n");
4672
      }
4673

4674 4675 4676 4677 4678
      break;

    case LTE_CQI_ReportModeAperiodic_rm20:
      AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n");
      // UE-selected subband CQI no PMI (TM1/2/3/7) , Table 5.2.2.6.3-1 from 36.213
4679
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm20\n",
4680 4681
                  tmode);
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4682
      p >>= 4;
4683
      diffcqi0 = (uint8_t) (p & 0x03);
4684
      p >>= 2;
4685
      r = (uint8_t) (p & ((1 >> Ltab_uesel[bw]) - 1));
4686 4687 4688
      reverse_index(Ntab_uesel[bw],
                    Mtab_uesel[bw],
                    r,
4689
                    v);
4690

4691
      for (m = 0; m < Mtab_uesel[bw]; m++) {
4692
        sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0;
4693
      }
4694 4695 4696 4697 4698 4699

      break;

    case LTE_CQI_ReportModeAperiodic_rm22:
      AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n");
      // UE-selected subband CQI multiple PMI (TM4/6) Table 5.2.2.6.3-2 from 36.213
4700
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm22\n",
4701 4702
                  tmode);
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4703
      p >>= 4;
4704 4705 4706 4707 4708 4709 4710 4711 4712
      diffcqi0 = (uint8_t) (p & 0x03);
      p >>= 2;

      if (ri > 1) {
        sched_ctl->aperiodic_wideband_cqi1[CC_idP] =
          (uint8_t) (p & 0x0F);
        p >>= 4;
        diffcqi1 = (uint8_t) (p & 0x03);
        p >>= 2;
4713
      }
4714 4715 4716

      r = (uint8_t) (p & ((1 >> Ltab_uesel[bw]) - 1));
      p >>= Ltab_uesel[bw];
4717 4718 4719
      reverse_index(Ntab_uesel[bw],
                    Mtab_uesel[bw],
                    r,
4720
                    v);
4721

4722
      if (ri == 1 && cc->p_eNB == 2) {
4723 4724 4725
        pmi_uesel = p & 0x3;
        p >>= 2;
        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x3;
4726
      } else if (ri == 2 && cc->p_eNB == 2) {
4727 4728 4729 4730 4731 4732 4733
        pmi_uesel = p & 0x1;
        p >>= 1;
        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x1;
      } else if (cc->p_eNB == 4) {
        pmi_uesel = p & 0x0F;
        p >>= 4;
        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x0F;
4734
      }
4735 4736 4737 4738

      for (m = 0; m < Mtab_uesel[bw]; m++) {
        sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0;

4739
        if (ri > 1) sched_ctl->aperiodic_subband_diffcqi1[CC_idP][v[m]] = diffcqi1;
4740 4741

        sched_ctl->aperiodic_subband_pmi[CC_idP][v[m]] = pmi_uesel;
4742
      }
4743 4744 4745 4746 4747

      break;

    case LTE_CQI_ReportModeAperiodic_rm30:
      //subband CQI no PMI (TM1/2/3/7)
4748
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm30\n",
4749 4750 4751 4752 4753
                  tmode);
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = pdu[0] >> 4;
      curbyte = 0;
      curbit = 3;

4754
      for (i = 0; i < N; i++) {
4755 4756 4757 4758 4759 4760 4761 4762
        sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] =
          (pdu[curbyte] >> (curbit - 1)) & 0x03;
        curbit -= 2;

        if (curbit < 0) {
          curbit = 7;
          curbyte++;
        }
4763
      }
4764

4765
      sched_ctl->dl_cqi[CC_idP] = sched_ctl->aperiodic_wideband_cqi0[CC_idP];
4766 4767 4768 4769 4770
      break;

    case LTE_CQI_ReportModeAperiodic_rm31:
      AssertFatal(0 == 1, "to be fixed, don't use p but pdu directly\n");
      //subband CQI single PMI (TM4/5/6)
4771
      AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10,
4772 4773 4774
                  "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm31\n",
                  tmode);

4775 4776
      if (ri == 1 && cc->p_eNB == 2) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4777 4778 4779
        p >>= 4;

        for (i = 0; i < N; i++) {
4780
          sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t) (p & 0x03);
4781 4782 4783 4784
          p >>= 2;
        }

        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x03;
4785
      }
4786

4787 4788
      if (ri == 2 && cc->p_eNB == 2) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4789 4790 4791
        p >>= 4;

        for (i = 0; i < N; i++) {
4792
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x01);
4793 4794 4795
          p >>= 1;
        }

4796
        sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4797 4798 4799
        p >>= 4;

        for (i = 0; i < N; i++) {
4800
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x01);
4801 4802 4803 4804
          p >>= 1;
        }

        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x01;
4805
      }
4806

4807 4808
      if (ri == 1 && cc->p_eNB == 4) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4809 4810 4811
        p >>= 4;

        for (i = 0; i < N; i++) {
4812
          sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t) (p & 0x03);
4813 4814 4815 4816
          p >>= 2;
        }

        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x0F;
4817 4818
      }

4819 4820
      if (ri > 1 && cc->p_eNB == 4) { // Note : 64 bits for 20 MHz
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4821 4822 4823
        p >>= 4;

        for (i = 0; i < N; i++) {
4824
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x01);
4825 4826 4827
          p >>= 1;
        }

4828
        sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4829 4830 4831
        p >>= 4;

        for (i = 0; i < N; i++) {
4832
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x01);
4833 4834 4835 4836 4837 4838 4839
          p >>= 2;
        }

        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x0F;
      }

      break;
frtabu's avatar
frtabu committed
4840

4841
    case LTE_CQI_ReportModeAperiodic_rm32_v1250:
4842
      AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10,
4843 4844 4845 4846
                  "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm32\n",
                  tmode);
      AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm32 to be done\n");
      break;
frtabu's avatar
frtabu committed
4847

4848
    case LTE_CQI_ReportModeAperiodic_rm10_v1310:
4849
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm10\n",
4850 4851 4852 4853 4854
                  tmode);
      AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm10 to be done\n");
      break;

    case LTE_CQI_ReportModeAperiodic_rm11_v1310:
4855
      AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10,
4856 4857 4858 4859
                  "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm11\n",
                  tmode);
      AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm11 to be done\n");
      break;
4860
  }
frtabu's avatar
frtabu committed
4861

4862
  return;
4863 4864
}

4865
//------------------------------------------------------------------------------
4866
void
4867 4868
cqi_indication(module_id_t mod_idP,
               int CC_idP,
4869
               frame_t frameP,
4870
               sub_frame_t subframeP,
4871
               rnti_t rntiP,
4872
               nfapi_cqi_indication_rel9_t *rel9,
4873
               uint8_t *pdu,
4874
               nfapi_ul_cqi_information_t *ul_cqi_information)
4875
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
4876
{
4877 4878
  int UE_id = find_UE_id(mod_idP, rntiP);
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
4879

4880 4881 4882 4883
  if (UE_id == -1) {
    LOG_W(MAC, "cqi_indication: UE %x not found\n", rntiP);
    return;
  }
4884

4885
  UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
4886

4887
  if (UE_id >= 0) {
4888 4889 4890 4891
    LOG_D(MAC,"%s() UE_id:%d channel:%d cqi:%d\n",
          __FUNCTION__,
          UE_id,
          ul_cqi_information->channel,
4892
          ul_cqi_information->ul_cqi);
4893

4894
    if (ul_cqi_information->channel == 0) { // PUCCH
4895
      // extract pucch csi information before changing RI information
4896 4897 4898 4899
      extract_pucch_csi(mod_idP,
                        CC_idP,
                        UE_id,
                        frameP,
4900
                        subframeP,
4901
                        pdu, rel9->length);
4902
      memcpy((void *) sched_ctl->periodic_ri_received,
4903
             (void *) rel9->ri,
4904
             rel9->number_of_cc_reported);
4905 4906
      // SNR for PUCCH2
      sched_ctl->pucch2_snr[CC_idP] = ul_cqi_information->ul_cqi;
4907
    } else {    //PUSCH
4908
      memcpy((void *) sched_ctl->aperiodic_ri_received,
4909
             (void *) rel9->ri,
4910
             rel9->number_of_cc_reported);
4911 4912 4913 4914
      extract_pusch_csi(mod_idP,
                        CC_idP,
                        UE_id,
                        frameP,
4915
                        subframeP,
4916
                        pdu,
4917 4918 4919 4920 4921
                        rel9->length);
      LOG_D(MAC,"Frame %d Subframe %d update CQI:%d\n",
            frameP,
            subframeP,
            sched_ctl->dl_cqi[CC_idP]);
4922 4923
      sched_ctl->cqi_req_flag &= (~(1 << subframeP));
      sched_ctl->cqi_received = 1;
4924
    }
4925 4926 4927 4928 4929

    // timing advance
    sched_ctl->timing_advance = rel9->timing_advance;
    sched_ctl->timing_advance_r9 = rel9->timing_advance_r9;
  }
frtabu's avatar
frtabu committed
4930

4931
  return;
4932 4933
}

4934
//------------------------------------------------------------------------------
4935
void
4936 4937
SR_indication(module_id_t mod_idP,
              int cc_idP,
4938
              frame_t frameP,
4939 4940 4941
              sub_frame_t subframeP,
              rnti_t rntiP,
              uint8_t ul_cqi)
4942
//------------------------------------------------------------------------------
4943
{
4944 4945
  T(T_ENB_MAC_SCHEDULING_REQUEST,
    T_INT(mod_idP),
4946
    T_INT(cc_idP),
4947 4948
    T_INT(frameP),
    T_INT(subframeP),
4949
    T_INT(rntiP));
4950 4951
  int UE_id = find_UE_id(mod_idP, rntiP);
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
4952
  UE_sched_ctrl_t *UE_scheduling_ctrl = NULL;
Cedric Roux's avatar
Cedric Roux committed
4953

4954
  if (UE_id != -1) {
4955 4956
    UE_scheduling_ctrl = &(UE_list->UE_sched_ctrl[UE_id]);

4957
    if ((UE_scheduling_ctrl->cdrx_configured == TRUE) &&
4958
        (UE_scheduling_ctrl->dci0_ongoing_timer > 0)  &&
4959
        (UE_scheduling_ctrl->dci0_ongoing_timer < 8)) {
4960 4961
      LOG_D(MAC, "[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d on CC_id %d.  \
                  The SR is not set do to ongoing DCI0 with CDRX activated\n",
4962 4963 4964 4965 4966
            mod_idP,
            rntiP,
            frameP,
            subframeP,
            UE_id,
4967
            cc_idP);
4968 4969 4970 4971 4972 4973 4974 4975 4976 4977
    } else {
      if (mac_eNB_get_rrc_status(mod_idP, UE_RNTI(mod_idP, UE_id)) <  RRC_CONNECTED) {
        LOG_D(MAC, "[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d on CC_id %d\n",
              mod_idP,
              rntiP,
              frameP,
              subframeP,
              UE_id,
              cc_idP);
      }
4978

4979 4980 4981 4982
      UE_list->UE_template[cc_idP][UE_id].ul_SR = 1;
      UE_list->UE_template[cc_idP][UE_id].ul_active = TRUE;
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 1);
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME(VCD_SIGNAL_DUMPER_FUNCTIONS_SR_INDICATION, 0);
4983
    }
4984
  } else {
4985
    LOG_D(MAC, "[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d (unknown UE_id) on CC_id %d\n",
4986 4987 4988 4989 4990
          mod_idP,
          rntiP,
          frameP,
          subframeP,
          UE_id,
4991
          cc_idP);
4992
  }
4993

4994
  return;
4995 4996
}

4997
//------------------------------------------------------------------------------
4998
void
4999 5000
UL_failure_indication(module_id_t mod_idP,
                      int cc_idP,
5001
                      frame_t frameP,
5002 5003
                      rnti_t rntiP,
                      sub_frame_t subframeP)
5004
//------------------------------------------------------------------------------
5005
{
5006 5007
  int UE_id = find_UE_id(mod_idP, rntiP);
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
5008

5009
  if (UE_id != -1) {
5010
    LOG_D(MAC, "[eNB %d][UE %d/%x] Frame %d subframeP %d Signaling UL Failure for UE %d on CC_id %d (timer %d)\n",
5011 5012 5013 5014 5015 5016
          mod_idP,
          UE_id,
          rntiP,
          frameP,
          subframeP,
          UE_id,
5017
          cc_idP,
5018 5019
          UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);

5020
    if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0) UE_list->UE_sched_ctrl[UE_id].ul_failure_timer = 1;
5021 5022 5023
  } else {
    //     AssertFatal(0, "find_UE_id(%u,rnti %d) not found", enb_mod_idP, rntiP);
    //    AssertError(0, 0, "Frame %d: find_UE_id(%u,rnti %d) not found\n", frameP, enb_mod_idP, rntiP);
5024
    LOG_W(MAC, "[eNB %d][SR %x] Frame %d subframeP %d Signaling UL Failure for UE %d (unknown UEid) on CC_id %d\n",
5025 5026 5027 5028 5029
          mod_idP,
          rntiP,
          frameP,
          subframeP,
          UE_id,
5030
          cc_idP);
5031
  }
5032
}
5033

5034
//------------------------------------------------------------------------------
5035
static int
5036
nack_or_dtx_reported(COMMON_channels_t *cc,
5037
                     nfapi_harq_indication_pdu_t *harq_pdu)
5038
//------------------------------------------------------------------------------
5039 5040 5041 5042
{
  int i;

  if (cc->tdd_Config) {
Raymond Knopp's avatar
Raymond Knopp committed
5043
    nfapi_harq_indication_tdd_rel13_t *hi = &harq_pdu->harq_indication_tdd_rel13;
5044

5045 5046
    for (i = 0; i < hi->number_of_ack_nack; i++) {
      if (hi->harq_data[i].bundling.value_0 != 1) //only bundling is used for tdd for now
Raymond Knopp's avatar
Raymond Knopp committed
5047
        return 1;
5048
    }
frtabu's avatar
frtabu committed
5049

Raymond Knopp's avatar
Raymond Knopp committed
5050
    return 0;
5051
  }
5052

5053
  nfapi_harq_indication_fdd_rel13_t *hi = &harq_pdu->harq_indication_fdd_rel13;
frtabu's avatar
frtabu committed
5054

5055
  for (i = 0; i < hi->number_of_ack_nack; i++) {
5056 5057
    if (hi->harq_tb_n[i] != 1)
      return 1;
5058
  }
frtabu's avatar
frtabu committed
5059

5060
  return 0;
5061
}
5062

5063
//------------------------------------------------------------------------------
5064
void
5065 5066
harq_indication(module_id_t mod_idP,
                int CC_idP,
5067
                frame_t frameP,
5068
                sub_frame_t subframeP,
5069
                nfapi_harq_indication_pdu_t *harq_pdu)
5070
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
5071
{
5072 5073 5074 5075
  rnti_t rnti = harq_pdu->rx_ue_information.rnti;
  uint8_t ul_cqi = harq_pdu->ul_cqi_information.ul_cqi;
  uint8_t channel = harq_pdu->ul_cqi_information.channel;
  int UE_id = find_UE_id(mod_idP, rnti);
5076

5077
  if (UE_id == -1) {
5078
    LOG_W(MAC, "harq_indication: UE %x not found\n",
5079
          rnti);
5080 5081
    return;
  }
5082

5083
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
5084
  UE_sched_ctrl_t *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
5085 5086
  COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
  // extract HARQ Information
5087

5088
  if (cc->tdd_Config) {
5089 5090 5091 5092
    extract_harq(mod_idP,
                 CC_idP,
                 UE_id,
                 frameP,
5093
                 subframeP,
5094 5095
                 (void *) &harq_pdu->harq_indication_tdd_rel13,
                 channel);
frtabu's avatar
frtabu committed
5096
  } else {
5097 5098 5099 5100
    extract_harq(mod_idP,
                 CC_idP,
                 UE_id,
                 frameP,
5101
                 subframeP,
5102 5103
                 (void *) &harq_pdu->harq_indication_fdd_rel13,
                 channel);
5104
  }
5105

5106
  /* don't care about cqi reporting if NACK/DTX is there */
5107
  if (channel == 0 && !nack_or_dtx_reported(cc,
frtabu's avatar
frtabu committed
5108
      harq_pdu)) {
5109 5110 5111
    sched_ctl->pucch1_snr[CC_idP] = ul_cqi;
    sched_ctl->pucch1_cqi_update[CC_idP] = 1;
  }
frtabu's avatar
frtabu committed
5112

5113
  return;
5114
}
5115 5116

// Flexran Slicing functions
5117
//------------------------------------------------------------------------------
5118 5119 5120
uint16_t
nb_rbs_allowed_slice(float rb_percentage,
                     int total_rbs)
5121
//------------------------------------------------------------------------------
5122
{
5123
  return (uint16_t) floor(rb_percentage * total_rbs);
5124 5125
}

5126
//------------------------------------------------------------------------------
5127 5128 5129 5130
int
ue_dl_slice_membership(module_id_t mod_id,
                       int UE_id,
                       int slice_idx)
5131
//------------------------------------------------------------------------------
5132
{
5133 5134 5135
  eNB_MAC_INST *eNB = RC.mac[mod_id];

  if (slice_idx < 0 || slice_idx >= eNB->slice_info.n_dl) {
5136
    LOG_W(MAC, "out of range slice index %d (slice ID %d)\n",
5137
          slice_idx,
5138
          eNB->slice_info.dl[slice_idx].id);
5139 5140
    return 0;
  }
5141

5142
  return eNB->UE_list.active[UE_id] == TRUE && eNB->UE_list.assoc_dl_slice_idx[UE_id] == slice_idx;
5143
}
5144

5145
//------------------------------------------------------------------------------
5146 5147 5148 5149
int
ue_ul_slice_membership(module_id_t mod_id,
                       int UE_id,
                       int slice_idx)
5150
//------------------------------------------------------------------------------
5151
{
5152 5153 5154
  eNB_MAC_INST *eNB = RC.mac[mod_id];

  if (slice_idx < 0 || slice_idx >= eNB->slice_info.n_ul) {
5155
    LOG_W(MAC, "out of range slice index %d (slice ID %d)\n",
5156
          slice_idx,
5157
          eNB->slice_info.dl[slice_idx].id);
5158
    return 0;
5159
  }
5160

5161
  return eNB->UE_list.active[UE_id] == TRUE && eNB->UE_list.assoc_ul_slice_idx[UE_id] == slice_idx;
5162
}