eNB_scheduler_primitives.c 185 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
  eNB_MAC_INST                           *eNB                         = RC.mac[module_idP];
  COMMON_channels_t                      *cc                          = eNB->common_channels;
1172
  UE_info_t                              *UE_info                     = &eNB->UE_info;
1173 1174 1175 1176 1177 1178
  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;
1179
  struct LTE_PhysicalConfigDedicated__ext2 *ext2 = UE_info->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
{
  eNB_MAC_INST *eNB     = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
1366
  UE_info_t *UE_info    = &eNB->UE_info;
1367
  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
  AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n");
1370 1371
  AssertFatal(UE_info != NULL, "UE_info is null\n");
  LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->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
  eNB_MAC_INST *eNB     = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
1471
  UE_info_t *UE_info    = &eNB->UE_info;
1472
  int UE_id = find_UE_id(module_idP,
1473
                         rntiP);
1474
  AssertFatal(UE_id >= 0, "UE_id cannot be found, impossible\n");
1475
  AssertFatal(UE_info != NULL, "UE_info is null\n");
1476 1477
  harq_information->harq_information_rel11.tl.tag        = NFAPI_UL_CONFIG_REQUEST_HARQ_INFORMATION_REL11_TAG;
  harq_information->harq_information_rel11.num_ant_ports = 1;
1478
  LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated;
Stefan's avatar
Stefan committed
1479
  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
    case 1:
    case 2:
    case 5:
    case 6:
    case 7:
      if (cc->tdd_Config != NULL) {
1492
        //      AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated != NULL,
1493
        //      "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
fill_nfapi_dlsch_config(nfapi_dl_config_request_pdu_t *dl_config_pdu,
1623 1624 1625 1626 1627 1628
                        uint16_t length,
                        int16_t pdu_index,
                        uint16_t rnti,
                        uint8_t resource_allocation_type,
                        uint8_t
                        virtual_resource_block_assignment_flag,
Robert Schmidt's avatar
Robert Schmidt committed
1629
                        uint32_t resource_block_coding,
1630 1631 1632 1633 1634 1635 1636
                        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
1637
                        // uint8_t codebook_index,
1638 1639 1640 1641 1642 1643 1644
                        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,
1645
                        uint8_t num_bf_vector)
1646
//------------------------------------------------------------------------------
1647
{
1648
  memset((void *) dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
1649 1650 1651 1652 1653 1654 1655 1656 1657 1658 1659 1660 1661 1662 1663 1664
  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
1665
  // dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = codebook_index;
1666 1667 1668 1669 1670 1671 1672 1673
  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;
1674
  return;
1675
}
1676

1677
//------------------------------------------------------------------------------
1678
uint16_t
1679
fill_nfapi_tx_req(nfapi_tx_request_body_t *tx_req_body,
1680 1681 1682
                  uint16_t                absSF,
                  uint16_t                pdu_length,
                  int16_t                 pdu_index,
1683
                  uint8_t                 *pdu)
1684
//------------------------------------------------------------------------------
1685
{
1686 1687
  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",
1688
        tx_req_body->number_of_pdus,
1689
        pdu_length);
1690 1691 1692 1693 1694 1695 1696 1697
  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));
1698
}
1699

1700
//------------------------------------------------------------------------------
1701
void
1702 1703 1704 1705 1706 1707 1708 1709 1710 1711 1712 1713 1714 1715 1716 1717 1718 1719 1720
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,
1721
                                     uint16_t                       size)
1722
//------------------------------------------------------------------------------
1723
{
1724 1725
  uint8_t ri_size = 0;
  memset((void *) ul_config_pdu, 0, sizeof(nfapi_ul_config_request_pdu_t));
1726 1727 1728 1729 1730 1731 1732
  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;
1733

1734 1735
  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;
1736 1737
  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;
1738

1739 1740 1741 1742 1743 1744 1745 1746 1747 1748 1749 1750 1751 1752 1753 1754 1755 1756
  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;
1757 1758
    LOG_D(MAC, "report_type %d\n",
          ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.report_type);
1759

1760 1761 1762
    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;
1763

frtabu's avatar
frtabu committed
1764
    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;
1765 1766 1767
    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");
1768 1769
    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
1770

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

1779 1780
    ri_information->delta_offset_cqi = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
    ri_information->delta_offset_ri = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
1781
  }
frtabu's avatar
frtabu committed
1782

1783
  return;
1784 1785
}

1786
//------------------------------------------------------------------------------
1787
void
1788
fill_nfapi_ulsch_config_request_emtc(nfapi_ul_config_request_pdu_t *ul_config_pdu,
1789 1790
                                     uint8_t ue_type,
                                     uint16_t total_number_of_repetitions,
1791
                                     uint16_t repetition_number,
1792
                                     uint16_t initial_transmission_sf_io)
1793
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1794
{
1795 1796 1797 1798 1799 1800
  // 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;
1801
  return;
1802
}
1803

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

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

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

1830
//------------------------------------------------------------------------------
1831
int
1832 1833
startSF_tdd_RA[7] = { 1, 2, 4, 5, 8, 10, 20 };
//------------------------------------------------------------------------------
1834

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

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

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

      break;

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

    case TYPEUESPEC:
1879
      epdcch_setconfig_r11 = eNB->UE_info.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0];
1880 1881
      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");
1882 1883

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

      break;

    default:
1891
      return 0;
1892
  }
1893

1894
  AssertFatal(T > 0, "T is 0!\n");
1895

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

1898
  return 0;
1899 1900
}

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

    case 3:     // 50 PRBs, N_NB=8, i_0=1
1912
      return (1 + (6 * nb_index));
1913 1914

    case 5:     // 100 PRBs, N_NB=16, i_0=2
1915
      return (2 + (6 * nb_index));
1916 1917 1918

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

1921
      return 0;
1922 1923 1924 1925

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

1927
      return ((6 * nb_index));
1928 1929 1930 1931

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

1933
      return (1 + (6 * nb_index));
1934 1935 1936 1937 1938

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

1941
  return 0;
1942
}
1943

1944
//------------------------------------------------------------------------------
1945
void
1946
init_ue_sched_info(void)
1947
//------------------------------------------------------------------------------
1948
{
1949 1950 1951 1952
  module_id_t i, j, k;

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

1967
  return;
1968 1969
}

1970
//------------------------------------------------------------------------------
1971 1972 1973
unsigned char
get_ue_weight(module_id_t module_idP,
              int CC_idP,
1974
              int ue_idP)
1975
//------------------------------------------------------------------------------
1976
{
1977
  return (eNB_dlsch_info[module_idP][CC_idP][ue_idP].weight);
1978 1979
}

1980
//------------------------------------------------------------------------------
1981 1982
int
find_UE_id(module_id_t mod_idP,
1983
           rnti_t rntiP)
1984
//------------------------------------------------------------------------------
1985
{
1986
  int UE_id;
1987
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
1988 1989
  if(!UE_info)
    return -1;
1990

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

2000
  return -1;
2001 2002
}

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

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

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

2024
  return -1;
2025 2026
}

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

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

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

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

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

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

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

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

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

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

2122
//------------------------------------------------------------------------------
2123
/*
2124
 * Dump the UE_list into LOG_T(MAC)
2125
 */
2126
void
2127 2128 2129 2130 2131
dump_ue_list(UE_list_t *listP) {
  for (int j = listP->head; j >= 0; j = listP->next[j])
    LOG_T(MAC, "DL list node %d => %d\n", j, listP->next[j]);
}

2132
//------------------------------------------------------------------------------
2133 2134 2135 2136
/*
 * Add a UE to UE_list listP
 */
inline void add_ue_list(UE_list_t *listP, int UE_id) {
2137 2138 2139 2140
  int *cur = &listP->head;
  while (*cur >= 0)
    cur = &listP->next[*cur];
  *cur = UE_id;
Raymond Knopp's avatar
 
Raymond Knopp committed
2141 2142
}

2143 2144
//------------------------------------------------------------------------------
/*
2145
 * Remove a UE from the UE_list listP
2146
 */
2147
inline int remove_ue_list(UE_list_t *listP, int UE_id) {
2148 2149 2150 2151 2152 2153 2154 2155 2156 2157
  int *cur = &listP->head;
  while (*cur != -1 && *cur != UE_id)
    cur = &listP->next[*cur];
  if (*cur == -1)
    return 0;
  int *next = &listP->next[*cur];
  *cur = listP->next[*cur];
  *next = -1;
  return 1;
}
2158

2159 2160 2161 2162 2163 2164 2165 2166
//------------------------------------------------------------------------------
/*
 * Initialize the UE_list listP
 */
inline void init_ue_list(UE_list_t *listP) {
  listP->head = -1;
  for (int i = 0; i < MAX_MOBILES_PER_ENB; ++i)
    listP->next[i] = -1;
2167 2168
}

2169
//------------------------------------------------------------------------------
2170 2171 2172 2173
int
add_new_ue(module_id_t mod_idP,
           int cc_idP,
           rnti_t rntiP,
2174 2175
           int harq_pidP,
           uint8_t rach_resource_type
frtabu's avatar
frtabu committed
2176
          )
2177
//------------------------------------------------------------------------------
2178
{
2179
  eNB_MAC_INST *eNB     = RC.mac[mod_idP];
2180 2181
  int UE_id;
  int i, j;
2182 2183
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
  LOG_D(MAC, "[eNB %d, CC_id %d] Adding UE with rnti %x (prev. num_UEs %d)\n",
2184 2185 2186
        mod_idP,
        cc_idP,
        rntiP,
2187
        UE_info->num_UEs);
2188

2189
  for (i = 0; i < MAX_MOBILES_PER_ENB; i++) {
2190
    if (UE_info->active[i] == TRUE)
2191
      continue;
2192

2193
    UE_id = i;
2194 2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205
    memset(&UE_info->UE_template[cc_idP][UE_id], 0, sizeof(UE_TEMPLATE));
    UE_info->UE_template[cc_idP][UE_id].rnti = rntiP;
    UE_info->UE_template[cc_idP][UE_id].configured = FALSE;
    UE_info->numactiveCCs[UE_id] = 1;
    UE_info->numactiveULCCs[UE_id] = 1;
    UE_info->pCC_id[UE_id] = cc_idP;
    UE_info->ordered_CCids[0][UE_id] = cc_idP;
    UE_info->ordered_ULCCids[0][UE_id] = cc_idP;
    UE_info->num_UEs++;
    UE_info->active[UE_id] = TRUE;
    add_ue_list(&UE_info->list, UE_id);
    dump_ue_list(&UE_info->list);
2206 2207 2208 2209 2210 2211
    pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl;
    if (dl->slices) // inform slice implementation about new UE
      dl->add_UE(dl->slices, UE_id);
    pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul;
    if (ul->slices) // inform slice implementation about new UE
      ul->add_UE(ul->slices, UE_id);
2212
    if (IS_SOFTMODEM_IQPLAYER)// not specific to record/playback ?
2213 2214 2215
      UE_info->UE_template[cc_idP][UE_id].pre_assigned_mcs_ul = 0;
    UE_info->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type;
    memset((void *) &UE_info->UE_sched_ctrl[UE_id],
2216
           0,
2217
           sizeof(UE_sched_ctrl_t));
2218
    memset((void *) &UE_info->eNB_UE_stats[cc_idP][UE_id],
2219
           0,
2220
           sizeof(eNB_UE_STATS));
2221
    UE_info->UE_sched_ctrl[UE_id].ue_reestablishment_reject_timer = 0;
2222
    UE_info->UE_sched_ctrl[UE_id].ta_update_f = 31.0;
2223
    UE_info->UE_sched_ctrl[UE_id].ta_update = 31;
2224
    UE_info->UE_sched_ctrl[UE_id].pusch_snr[cc_idP] = 0;
2225 2226 2227
    UE_info->UE_sched_ctrl[UE_id].pusch_cqi_f[cc_idP]     = (eNB->puSch10xSnr+640)/5;
    UE_info->UE_sched_ctrl[UE_id].pusch_cqi[cc_idP]     = (eNB->puSch10xSnr+640)/5;
    UE_info->UE_sched_ctrl[UE_id].pusch_snr_avg[cc_idP] = eNB->puSch10xSnr/10;
2228 2229 2230 2231 2232
    UE_info->UE_sched_ctrl[UE_id].pusch_rx_num[cc_idP] = 0;
    UE_info->UE_sched_ctrl[UE_id].pusch_rx_num_old[cc_idP] = 0;
    UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num[cc_idP] = 0;
    UE_info->UE_sched_ctrl[UE_id].pusch_rx_error_num_old[cc_idP] = 0;
    UE_info->UE_sched_ctrl[UE_id].pusch_bler[cc_idP] = 0;
masayuki.harada's avatar
masayuki.harada committed
2233 2234
    UE_info->UE_sched_ctrl[UE_id].ret_cnt[cc_idP] = 0;
    UE_info->UE_sched_ctrl[UE_id].first_cnt[cc_idP] = 0;
2235

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

2243 2244 2245
    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",
2246 2247 2248
          mod_idP,
          UE_id,
          cc_idP,
2249
          rntiP);
2250 2251 2252
    return (UE_id);
  }

2253
  LOG_E(MAC, "error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
2254
  dump_ue_list(&UE_info->list);
2255
  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_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
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_info->active[UE_id] = FALSE;
  UE_info->num_UEs--;
2285

2286
  remove_ue_list(&UE_info->list, UE_id);
2287 2288 2289 2290 2291 2292
  pp_impl_param_t* dl = &RC.mac[mod_idP]->pre_processor_dl;
  if (dl->slices) // inform slice implementation about new UE
    dl->remove_UE(dl->slices, UE_id);
  pp_impl_param_t* ul = &RC.mac[mod_idP]->pre_processor_ul;
  if (ul->slices) // inform slice implementation about new UE
    ul->remove_UE(ul->slices, UE_id);
2293 2294

  /* Clear all remaining pending transmissions */
2295 2296
  memset(&UE_info->UE_template[pCC_id][UE_id], 0, sizeof(UE_TEMPLATE));
  ue_stats = &UE_info->eNB_UE_stats[pCC_id][UE_id];
2297 2298
  ue_stats->total_rbs_used = 0;
  ue_stats->total_rbs_used_retx = 0;
2299

2300
  for (int j = 0; j < NB_RB_MAX; j++ ) {
2301 2302
    ue_stats->num_pdu_tx[j] = 0;
    ue_stats->num_bytes_tx[j] = 0;
2303
  }
2304

2305 2306 2307 2308 2309
  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;
2310

2311
  for (int j = 0; j < NB_RB_MAX; j++ ) {
2312 2313
    ue_stats->num_pdu_rx[j] = 0;
    ue_stats->num_bytes_rx[j] = 0;
2314
  }
2315

2316 2317 2318 2319
  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;
2320 2321
  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;
2322
  eNB_ulsch_info[mod_idP][pCC_id][UE_id].serving_num = 0;
2323 2324
  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;
2325
  eNB_dlsch_info[mod_idP][pCC_id][UE_id].serving_num = 0;
2326

2327
  // check if this has an RA process active
2328 2329
  if (find_RA_id(mod_idP,
                 pCC_id,
2330
                 rntiP) != -1) {
2331 2332 2333
    cancel_ra_proc(mod_idP,
                   pCC_id,
                   0,
2334
                   rntiP);
2335
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
2336

2337
  if(rrc_release_info.num_UEs > 0) {
2338 2339 2340
    while(pthread_mutex_trylock(&rrc_release_freelist)) {
      /* spin... */
    }
2341

2342
    uint16_t release_total = 0;
2343

2344 2345
    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) {
2346
        release_total++;
2347
      } else {
2348 2349
        continue;
      }
2350

2351
      if (rrc_release_info.RRC_release_ctrl[release_num].rnti == rntiP) {
2352 2353 2354 2355
        rrc_release_info.RRC_release_ctrl[release_num].flag = 0;
        rrc_release_info.num_UEs--;
        release_total--;
      }
2356

2357
      if (release_total >= rrc_release_info.num_UEs) {
2358
        break;
wujing's avatar
wujing committed
2359
      }
2360
    }
2361

2362
    pthread_mutex_unlock(&rrc_release_freelist);
2363
  }
2364

2365
  pthread_mutex_unlock(&rrc_release_freelist);
2366
  return 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
2367
}
2368

2369
//------------------------------------------------------------------------------
2370 2371 2372
/*
 * Returns the previous UE_id in the scheduling list in UL or DL
 */
2373 2374 2375
inline int prev(UE_list_t *listP, int nodeP) {
  if (nodeP == listP->head)
      return -1; /* there is no previous of the head */
2376

2377 2378 2379
  for (int j = listP->head; j >= 0; j = listP->next[j])
    if (listP->next[j] == nodeP)
      return j;
2380

2381 2382
  LOG_E(MAC, "%s(): could not find previous to %d in UE_list\n", __func__, nodeP);
  dump_ue_list(listP);
2383
  return -1;
2384
}
Raymond Knopp's avatar
 
Raymond Knopp committed
2385

2386
// This has to be updated to include BSR information
2387
//------------------------------------------------------------------------------
2388
uint8_t
2389 2390 2391
UE_is_to_be_scheduled(module_id_t module_idP,
                      int CC_id,
                      uint8_t UE_id)
2392
//------------------------------------------------------------------------------
2393
{
2394 2395
  UE_TEMPLATE *UE_template = &RC.mac[module_idP]->UE_info.UE_template[CC_id][UE_id];
  UE_sched_ctrl_t *UE_sched_ctl = &RC.mac[module_idP]->UE_info.UE_sched_ctrl[UE_id];
2396
  int rrc_status;
2397 2398

  // do not schedule UE if UL is not working
2399 2400
  if (UE_sched_ctl->ul_failure_timer > 0 || UE_sched_ctl->ul_out_of_sync > 0)
    return 0;
2401

2402
  rnti_t ue_rnti = UE_RNTI(module_idP, UE_id);
2403
  LOG_D(MAC, "[eNB %d][PUSCH] Checking UL requirements UE %d/%x\n",
2404 2405
        module_idP,
        UE_id,
2406 2407
        ue_rnti);

2408 2409
  rrc_status = mac_eNB_get_rrc_status(module_idP, ue_rnti);

2410 2411
  if (UE_template->scheduled_ul_bytes < UE_template->estimated_ul_buffer ||
      UE_template->ul_SR > 0 || // uplink scheduling request
2412
      (UE_sched_ctl->ul_inactivity_timer > 19 && UE_sched_ctl->ul_scheduled == 0) ||  // every 2 frames when RRC_CONNECTED
2413
      (UE_sched_ctl->ul_inactivity_timer > 10 &&
2414 2415
       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)
2416
    LOG_D(MAC, "[eNB %d][PUSCH] UE %d/%x should be scheduled (BSR0 estimated size %d, SR %d)\n",
2417 2418
          module_idP,
          UE_id,
2419
          ue_rnti,
2420 2421
          UE_template->ul_buffer_info[LCGID0],
          UE_template->ul_SR);
2422
    return 1;
2423
  }
frtabu's avatar
frtabu committed
2424

2425
  return 0;
2426 2427
}

2428
//------------------------------------------------------------------------------
2429 2430 2431 2432
uint8_t
get_tmode(module_id_t module_idP,
          int CC_idP,
          int UE_idP)
2433
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2434
{
2435 2436
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
2437
  struct LTE_PhysicalConfigDedicated *physicalConfigDedicated = eNB->UE_info.UE_template[CC_idP][UE_idP].physicalConfigDedicated;
2438

2439
  if (physicalConfigDedicated == NULL) {  // RRCConnectionSetup not received by UE yet
2440
    AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n",
Stefan's avatar
Stefan committed
2441
                cc->p_eNB);
2442
    return (cc->p_eNB);
2443
  }
2444 2445

  AssertFatal(physicalConfigDedicated->antennaInfo != NULL,
2446
              "antennaInfo (mod_id %d) is null for CCId %d, UEid %d, physicalConfigDedicated %p\n",
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
2447
              module_idP,
Stefan's avatar
Stefan committed
2448
              CC_idP,
frtabu's avatar
frtabu committed
2449
              UE_idP,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
2450
              physicalConfigDedicated);
2451
  AssertFatal(physicalConfigDedicated->antennaInfo->present != LTE_PhysicalConfigDedicated__antennaInfo_PR_NOTHING,
Stefan's avatar
Stefan committed
2452 2453 2454
              "antennaInfo (mod_id %d, CC_id %d) is set to NOTHING\n",
              module_idP,
              CC_idP);
2455

2456
  if (physicalConfigDedicated->antennaInfo->present == LTE_PhysicalConfigDedicated__antennaInfo_PR_explicitValue) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
2457
    return (1 + physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
2458
  }
2459

2460
  if (physicalConfigDedicated->antennaInfo->present == LTE_PhysicalConfigDedicated__antennaInfo_PR_defaultValue) {
2461
    AssertFatal(cc->p_eNB <= 2, "p_eNB is %d, should be <2\n",
Stefan's avatar
Stefan committed
2462
                cc->p_eNB);
2463 2464
    return (cc->p_eNB);
  }
2465 2466 2467

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

2470
//------------------------------------------------------------------------------
2471
int8_t
2472 2473
get_ULharq(module_id_t module_idP,
           int CC_idP,
2474
           uint16_t frameP,
2475
           uint8_t subframeP)
2476
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2477
{
2478
  int8_t ret = -1;
2479 2480
  eNB_MAC_INST *eNB = RC.mac[module_idP];
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
2481

2482
  if (cc->tdd_Config == NULL) { // FDD
2483 2484 2485
    ret = (((frameP << 1) + subframeP) & 7);
  } else {
    switch (cc->tdd_Config->subframeAssignment) {
2486
      case 1:
2487 2488 2489 2490 2491
        switch (subframeP) {
          case 2:
          case 3:
            ret = (subframeP - 2);
            break;
2492

2493 2494 2495 2496
          case 7:
          case 8:
            ret = (subframeP - 5);
            break;
2497

2498 2499 2500 2501 2502 2503
          default:
            AssertFatal(1 == 0, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
                        subframeP,
                        (int) cc->tdd_Config->subframeAssignment);
            break;
        }
2504

2505
        break;
2506

2507
      case 2:
2508
        AssertFatal((subframeP == 2) || (subframeP == 7), "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
2509 2510 2511 2512
                    subframeP,
                    (int) cc->tdd_Config->subframeAssignment);
        ret = (subframeP / 7);
        break;
2513

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

2521
      case 4:
2522
        AssertFatal((subframeP > 1) && (subframeP < 4), "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
2523 2524 2525 2526 2527 2528
                    subframeP,
                    (int) cc->tdd_Config->subframeAssignment);
        ret = (subframeP - 2);
        break;

      case 5:
2529
        AssertFatal(subframeP == 2, "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",
2530 2531 2532 2533 2534 2535
                    subframeP,
                    (int) cc->tdd_Config->subframeAssignment);
        ret = (subframeP - 2);
        break;

      default:
2536
        AssertFatal(1 == 0, "subframe2_harq_pid, Unsupported TDD mode %d\n",
2537 2538
                    (int) cc->tdd_Config->subframeAssignment);
        break;
2539
    }
2540
  }
2541

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

2548
//------------------------------------------------------------------------------
2549 2550 2551 2552
uint16_t
getRIV(uint16_t N_RB_DL,
       uint16_t RBstart,
       uint16_t Lcrbs)
2553
//------------------------------------------------------------------------------
2554
{
2555
  uint16_t RIV;
2556

2557 2558 2559 2560
  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);
2561

2562
  return RIV;
2563
}
2564

2565
//------------------------------------------------------------------------------
2566
uint32_t
2567 2568
allocate_prbs(int UE_id,
              unsigned char nb_rb,
2569
              int N_RB_DL,
2570
              uint32_t *rballoc)
2571
//------------------------------------------------------------------------------
2572
{
2573 2574 2575
  int i;
  uint32_t rballoc_dci = 0;
  unsigned char nb_rb_alloc = 0;
2576

2577 2578 2579 2580 2581
  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;
2582 2583
    }

2584 2585 2586 2587 2588 2589 2590 2591 2592
    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;
2593
    }
2594
  }
2595

2596
  return (rballoc_dci);
2597 2598
}

2599
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
2600 2601
int
get_bw_index(module_id_t module_id,
2602
             uint8_t CC_id)
2603
//------------------------------------------------------------------------------
2604
{
2605
  int bw_index = 0;
2606
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
2607

2608
  switch (N_RB_DL) {
2609 2610 2611
    case 6:     // 1.4 MHz
      bw_index = 0;
      break;
2612

2613 2614 2615
    case 25:      // 5HMz
      bw_index = 1;
      break;
2616

2617 2618 2619
    case 50:      // 10HMz
      bw_index = 2;
      break;
2620

2621 2622 2623
    case 100:     // 20HMz
      bw_index = 3;
      break;
2624

2625 2626
    default:
      bw_index = 1;
Stefan's avatar
Stefan committed
2627 2628 2629 2630
      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);
2631
      break;
2632
  }
2633

2634
  return bw_index;
2635 2636
}

2637
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
2638 2639
int
get_min_rb_unit(module_id_t module_id,
2640
                uint8_t CC_id)
2641
//------------------------------------------------------------------------------
2642
{
2643
  int min_rb_unit = 0;
2644
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
2645

2646
  switch (N_RB_DL) {
2647
    case 6:       // 1.4MHz
2648 2649
      min_rb_unit = 1;
      break;
2650

2651 2652
    case 15:      // 3MHz
    case 25:      // 5MHz
2653 2654
      min_rb_unit = 2;
      break;
2655

2656
    case 50:      // 10MHz
2657 2658
      min_rb_unit = 3;
      break;
2659

2660 2661
    case 75:      // 15MHz
    case 100:     // 20MHz
2662 2663
      min_rb_unit = 4;
      break;
2664

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

2674
  return min_rb_unit;
2675
}
2676

2677
//------------------------------------------------------------------------------
2678
uint32_t
2679 2680 2681
allocate_prbs_sub(int nb_rb,
                  int N_RB_DL,
                  int N_RBG,
Robert Schmidt's avatar
Robert Schmidt committed
2682
                  const uint8_t *rballoc)
2683
//------------------------------------------------------------------------------
2684
{
2685
  int check = 0;    //check1=0,check2=0;
2686 2687 2688
  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",
2689 2690 2691 2692 2693
        rballoc[3],
        rballoc[2],
        rballoc[1],
        rballoc[0],
        nb_rb,
2694 2695 2696
        N_RBG);

  while (nb_rb > 0 && check < N_RBG) {
2697 2698 2699 2700 2701
    //printf("rballoc[%d] %d\n",check,rballoc[check]);
    if (rballoc[check] == 1) {
      rballoc_dci |= (1 << ((N_RBG - 1) - check));

      switch (N_RB_DL) {
2702 2703 2704
        case 6:
          nb_rb--;
          break;
2705

2706 2707 2708 2709 2710 2711
        case 25:
          if ((check == N_RBG - 1)) {
            nb_rb--;
          } else {
            nb_rb -= 2;
          }
frtabu's avatar
frtabu committed
2712

2713
          break;
2714

2715 2716 2717 2718 2719 2720
        case 50:
          if ((check == N_RBG - 1)) {
            nb_rb -= 2;
          } else {
            nb_rb -= 3;
          }
frtabu's avatar
frtabu committed
2721

2722
          break;
2723

2724 2725 2726
        case 100:
          nb_rb -= 4;
          break;
2727
      }
2728
    }
2729

2730
    //      printf("rb_alloc %x\n",rballoc_dci);
2731
    check++;
2732 2733
    //    check1 = check1+2;
  }
2734

2735
  // rballoc_dci = (rballoc_dci)&(0x1fff);
2736
  LOG_T(MAC, "*********RBALLOC : %x\n",
2737
        rballoc_dci);
2738
  // exit(-1);
2739
  return rballoc_dci;
2740 2741
}

2742
//------------------------------------------------------------------------------
2743 2744
int
get_subbandsize(uint8_t dl_Bandwidth)
2745
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2746
{
2747 2748
  uint8_t ss[6] = { 6, 4, 4, 6, 8, 8 };
  AssertFatal(dl_Bandwidth < 6, "dl_Bandwidth %d is out of bounds\n",
2749
              dl_Bandwidth);
2750
  return (ss[dl_Bandwidth]);
2751
}
Cedric Roux's avatar
Cedric Roux committed
2752

2753
//------------------------------------------------------------------------------
2754 2755
int
get_nb_subband(int N_RB_DL)
2756
//------------------------------------------------------------------------------
2757
{
2758
  int nb_sb = 0;
2759

2760
  switch (N_RB_DL) {
2761 2762 2763
    case 6:
      nb_sb = 0;
      break;
2764

2765 2766
    case 15:
      nb_sb = 4;    // sb_size =4
2767
      break;
2768

2769 2770 2771
    case 25:
      nb_sb = 7;    // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs
      break;
2772

2773 2774 2775
    case 50:      // sb_size =6
      nb_sb = 9;
      break;
2776

2777 2778 2779
    case 75:      // sb_size =8
      nb_sb = 10;
      break;
2780

2781 2782 2783
    case 100:     // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs
      nb_sb = 13;
      break;
2784

2785 2786 2787
    default:
      nb_sb = 0;
      break;
2788
  }
2789

2790
  return nb_sb;
2791
}
2792 2793

//------------------------------------------------------------------------------
2794 2795
void
init_CCE_table(int *CCE_table)
2796
//------------------------------------------------------------------------------
2797
{
Stefan's avatar
Stefan committed
2798
  memset(CCE_table, 0, 800 * sizeof(int));
Cedric Roux's avatar
Cedric Roux committed
2799
}
2800

2801
//------------------------------------------------------------------------------
2802 2803
int
get_nCCE_offset(int *CCE_table,
2804 2805 2806
                const unsigned char L,
                const int nCCE,
                const int common_dci,
2807 2808
                const unsigned short rnti,
                const unsigned char subframe)
2809
//------------------------------------------------------------------------------
2810
{
2811 2812
  int search_space_free, m, nb_candidates = 0, l, i;
  unsigned int Yk;
2813

2814 2815 2816 2817 2818 2819 2820 2821 2822 2823
  /*
    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);
2824

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

2827 2828
    for (m = nb_candidates - 1; m >= 0; m--) {
      search_space_free = 1;
Raymond Knopp's avatar
Raymond Knopp committed
2829

2830 2831 2832 2833 2834 2835
      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;
        }
2836
      }
2837

2838
      if (search_space_free == 1) {
2839
        //        printf("returning %d\n",m*L);
2840
        for (l = 0; l < L; l++) {
2841
          CCE_table[(m * L) + l] = 1;
2842
        }
frtabu's avatar
frtabu committed
2843

2844
        return (m * L);
2845 2846
      }
    }
2847

2848
    return -1;
2849
  }
frtabu's avatar
frtabu committed
2850

2851 2852 2853 2854
  // 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;
2855

2856 2857 2858
  for (i = 0; i <= subframe; i++) {
    Yk = (Yk * 39827) % 65537;
  }
frtabu's avatar
frtabu committed
2859

2860
  Yk = Yk % (nCCE / L);
2861

2862
  switch (L) {
2863 2864 2865 2866
    case 1:
    case 2:
      nb_candidates = 6;
      break;
2867

2868 2869 2870 2871
    case 4:
    case 8:
      nb_candidates = 2;
      break;
2872

2873
    default:
2874 2875
      DevParam(L,
               nCCE,
2876
               rnti);
2877
      break;
2878
  }
2879

2880
  LOG_D(MAC, "rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",
2881 2882 2883 2884
        rnti,
        Yk,
        nCCE,
        nCCE / L,
2885
        nb_candidates);
2886

2887 2888
  for (m = 0; m < nb_candidates; m++) {
    search_space_free = 1;
2889

2890 2891
    for (l = 0; l < L; l++) {
      int cce = (((Yk + m) % (nCCE / L)) * L) + l;
2892

2893 2894 2895
      if (cce >= nCCE || CCE_table[cce] == 1) {
        search_space_free = 0;
        break;
2896
      }
2897
    }
2898

2899 2900 2901
    if (search_space_free == 1) {
      for (l = 0; l < L; l++) {
        CCE_table[(((Yk + m) % (nCCE / L)) * L) + l] = 1;
2902
      }
frtabu's avatar
frtabu committed
2903

2904
      return (((Yk + m) % (nCCE / L)) * L);
2905
    }
2906
  }
2907 2908

  return -1;
2909 2910
}

2911
//------------------------------------------------------------------------------
2912
void
2913
dump_CCE_table(int *CCE_table,
2914
               const int nCCE,
2915 2916 2917
               const unsigned short rnti,
               const int subframe,
               int L)
2918
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
2919
{
2920 2921 2922
  int nb_candidates = 0, i;
  unsigned int Yk;
  printf("CCE 0: ");
2923

2924 2925
  for (i = 0; i < nCCE; i++) {
    printf("%1d.", CCE_table[i]);
2926

2927
    if ((i & 7) == 7)
2928
      printf("\n CCE %d: ",
2929
             i);
2930
  }
Cedric Roux's avatar
Cedric Roux committed
2931

2932
  Yk = (unsigned int) rnti;
Cedric Roux's avatar
Cedric Roux committed
2933

2934
  for (i = 0; i <= subframe; i++) {
2935
    Yk = (Yk * 39827) % 65537;
2936
  }
frtabu's avatar
frtabu committed
2937

2938
  Yk = Yk % (nCCE / L);
Cedric Roux's avatar
Cedric Roux committed
2939

2940
  switch (L) {
2941 2942 2943 2944 2945 2946 2947 2948 2949
    case 1:
    case 2:
      nb_candidates = 6;
      break;

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

2951 2952 2953
    default:
      DevParam(L, nCCE, rnti);
      break;
2954
  }
2955

2956
  LOG_I(PHY, "rnti %x, Yk*L = %u, nCCE %d (nCCE/L %d),nb_cand*L %d\n",
frtabu's avatar
frtabu committed
2957 2958 2959 2960 2961
        rnti,
        Yk * L,
        nCCE,
        nCCE / L,
        nb_candidates * L);
2962 2963
}

2964
//------------------------------------------------------------------------------
2965
uint16_t
2966 2967 2968
getnquad(COMMON_channels_t *cc,
         uint8_t num_pdcch_symbols,
         uint8_t mi)
2969
//------------------------------------------------------------------------------
2970
{
2971 2972 2973 2974 2975 2976
  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;
2977

2978
  if (((phich_resource * N_RB_DL) % 48) > 0) {
2979
    Ngroup_PHICH++;
2980
  }
frtabu's avatar
frtabu committed
2981

2982 2983 2984
  if (cc->Ncp == 1) {
    Ngroup_PHICH <<= 1;
  }
2985

2986
  Ngroup_PHICH *= mi;
2987

2988
  if (num_pdcch_symbols > 0 && num_pdcch_symbols < 4)
2989
    switch (N_RB_DL) {
2990 2991 2992
      case 6:
        Nreg = 12 + (num_pdcch_symbols - 1) * 18;
        break;
2993

2994 2995 2996
      case 25:
        Nreg = 50 + (num_pdcch_symbols - 1) * 75;
        break;
2997

2998 2999 3000
      case 50:
        Nreg = 100 + (num_pdcch_symbols - 1) * 150;
        break;
3001

3002 3003 3004
      case 100:
        Nreg = 200 + (num_pdcch_symbols - 1) * 300;
        break;
3005

3006
      default:
3007
        return 0;
3008
    }
3009

3010 3011
  //   printf("Nreg %d (%d)\n",Nreg,Nreg - 4 - (3*Ngroup_PHICH));
  return (Nreg - 4 - (3 * Ngroup_PHICH));
3012 3013
}

3014
//------------------------------------------------------------------------------
3015
uint16_t
3016 3017 3018
getnCCE(COMMON_channels_t *cc,
        uint8_t num_pdcch_symbols,
        uint8_t mi)
3019
//------------------------------------------------------------------------------
3020
{
3021
  AssertFatal(cc != NULL, "cc is null\n");
3022 3023
  return (getnquad(cc,
                   num_pdcch_symbols,
3024
                   mi) / 9);
3025 3026
}

3027
//------------------------------------------------------------------------------
3028 3029 3030
uint8_t
getmi(COMMON_channels_t *cc,
      int subframe)
3031
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
3032
{
3033
  AssertFatal(cc != NULL, "cc is null\n");
3034

3035
  // for FDD
3036
  if (cc->tdd_Config == NULL) // FDD
3037
    return 1;
3038

3039 3040
  // for TDD
  switch (cc->tdd_Config->subframeAssignment) {
3041
    case 0:
3042 3043 3044
      if (subframe == 0 || subframe == 5) {
        return 2;
      }
frtabu's avatar
frtabu committed
3045

3046
      return 1;
3047

3048
    case 1:
3049 3050 3051
      if (subframe == 0 || subframe == 5) {
        return 0;
      }
frtabu's avatar
frtabu committed
3052

3053
      return 1;
3054

3055
    case 2:
3056 3057 3058
      if (subframe == 3 || subframe == 8) {
        return 0;
      }
frtabu's avatar
frtabu committed
3059

3060
      return 1;
3061

3062
    case 3:
3063 3064 3065
      if (subframe == 0 || subframe == 8 || subframe == 9) {
        return 1;
      }
frtabu's avatar
frtabu committed
3066

3067
      return 0;
3068

3069
    case 4:
3070 3071 3072
      if (subframe == 8 || subframe == 9) {
        return 1;
      }
frtabu's avatar
frtabu committed
3073

3074
      return 0;
3075

3076
    case 5:
3077 3078 3079
      if (subframe == 8) {
        return 1;
      }
frtabu's avatar
frtabu committed
3080

3081
      return 0;
3082

3083
    case 6:
3084
      return 1;
3085

3086
    default:
3087
      break;
3088
  }
frtabu's avatar
frtabu committed
3089

3090
  return 0;
3091 3092
}

3093
//------------------------------------------------------------------------------
3094
uint16_t
3095 3096 3097
get_nCCE_max(COMMON_channels_t *cc,
             int num_pdcch_symbols,
             int subframe)
3098
//------------------------------------------------------------------------------
3099
{
3100
  AssertFatal(cc != NULL, "cc is null\n");
3101 3102 3103
  return (getnCCE(cc,
                  num_pdcch_symbols,
                  getmi(cc,
3104
                        subframe)));
3105
}
Cedric Roux's avatar
Cedric Roux committed
3106

3107
// Allocate the CCEs
3108
//------------------------------------------------------------------------------
3109
int
3110 3111 3112 3113 3114
allocate_CCEs(int module_idP,
              int CC_idP,
              frame_t frameP,
              sub_frame_t subframeP,
              int test_onlyP)
3115
//------------------------------------------------------------------------------
3116
{
Stefan's avatar
Stefan committed
3117 3118 3119 3120
  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;
3121 3122
  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
3123 3124
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
  int nCCE_max = get_nCCE_max(cc, 1, subframeP);
3125 3126 3127
  int fCCE;
  int i, j, idci;
  int nCCE = 0;
3128 3129
  int max_symbol;
  int ackNAK_absSF = get_pucch1_absSF(cc, (frameP*10+subframeP));
Stefan's avatar
Stefan committed
3130 3131
  nfapi_dl_config_request_pdu_t *dl_config_pduLoop;
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pduLoop;
3132

3133 3134 3135 3136 3137 3138
  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;
3139
  LOG_D(MAC, "Allocate CCEs subframe %d, test %d : (DL PDU %d, DL DCI %d, UL %d)\n",
3140 3141 3142
        subframeP,
        test_onlyP,
        DL_req->number_pdu,
Stefan's avatar
Stefan committed
3143
        DL_req->number_dci,
3144
        HI_DCI0_req->number_of_dci);
3145
  DL_req->number_pdcch_ofdm_symbols = 1;
3146
try_again:
Stefan's avatar
Stefan committed
3147
  init_CCE_table(CCE_table);
3148 3149 3150
  nCCE = 0;

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

3153
    // allocate DL common DCIs first
3154
    if (dl_config_pduLoop->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE &&
Stefan's avatar
Stefan committed
3155
        dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == 2) {
3156
      LOG_D(MAC, "Trying to allocate COMMON DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3157
            idci,
Stefan's avatar
Stefan committed
3158
            DL_req->number_dci + HI_DCI0_req->number_of_dci,
3159
            DL_req->number_dci,
Stefan's avatar
Stefan committed
3160 3161
            HI_DCI0_req->number_of_dci,
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3162 3163 3164
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
            nCCE,
            nCCE_max,
Stefan's avatar
Stefan committed
3165
            DL_req->number_pdcch_ofdm_symbols);
3166

Stefan's avatar
Stefan committed
3167
      if (nCCE + (dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) {
3168
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol)
3169
          return -1;
3170 3171 3172 3173

        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
3174
        nCCE_max = get_nCCE_max(cc, DL_req->number_pdcch_ofdm_symbols, subframeP);
3175
        goto try_again;
3176
      }
3177

3178 3179
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
3180 3181
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                             nCCE_max,
Stefan's avatar
Stefan committed
3182 3183
                             1,
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3184 3185
                             subframeP);

3186
      if (fCCE == -1) {
3187 3188
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol) {
          LOG_D(MAC, "subframe %d: Dropping Allocation for RNTI %x\n",
3189
                subframeP,
Stefan's avatar
Stefan committed
3190
                dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti);
3191 3192

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

Stefan's avatar
Stefan committed
3195
            if (dl_config_pduLoop->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
3196 3197 3198 3199 3200
              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
3201 3202
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.dci_format,
3203
                    dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
3204 3205
                    nCCE, nCCE_max, DL_req->number_pdcch_ofdm_symbols);
          }
frtabu's avatar
frtabu committed
3206

3207
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
3208
          return -1;
3209 3210
        }

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

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

3222
      if ((test_onlyP%2) == 0) {
Stefan's avatar
Stefan committed
3223
        dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE;
3224
        LOG_D(MAC, "Allocate COMMON DCI CCEs subframe %d, test %d => L %d fCCE %d\n",
3225 3226 3227
              subframeP,
              test_onlyP,
              dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
Stefan's avatar
Stefan committed
3228
              fCCE);
3229
      }
3230

3231 3232
      idci++;
    }
3233
  }       // for i = 0 ... num_DL_DCIs
3234

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

3239 3240
    // allocate UL DCIs
    if (hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) {
3241
      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",
3242
            idci,
Stefan's avatar
Stefan committed
3243
            DL_req->number_dci + HI_DCI0_req->number_of_dci,
3244
            DL_req->number_dci,
Stefan's avatar
Stefan committed
3245 3246 3247
            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,
3248
            nCCE, nCCE_max,
Stefan's avatar
Stefan committed
3249
            DL_req->number_pdcch_ofdm_symbols);
3250

Stefan's avatar
Stefan committed
3251
      if (nCCE + hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level > nCCE_max) {
3252
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol)
3253
          return -1;
3254

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

3262 3263
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
Stefan's avatar
Stefan committed
3264
                             hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level,
3265
                             nCCE_max,
Stefan's avatar
Stefan committed
3266
                             0,
3267
                             hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.rnti,
Stefan's avatar
Stefan committed
3268
                             subframeP);
3269

3270
      if (fCCE == -1) {
3271
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol) {
3272
          LOG_D(MAC, "subframe %d: Dropping Allocation for RNTI %x\n",
3273
                subframeP,
Stefan's avatar
Stefan committed
3274
                hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.rnti);
3275 3276

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

3279
            if (hi_dci0_pdu[j].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)
3280
              LOG_D(MAC, "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3281 3282 3283 3284
                    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
3285 3286
                    hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.rnti,
                    hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.dci_format,
3287
                    hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.aggregation_level,
3288 3289
                    nCCE, nCCE_max, DL_req->number_pdcch_ofdm_symbols);
          }
frtabu's avatar
frtabu committed
3290

3291
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
3292
          return -1;
3293 3294
        }

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

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

3307
      if ((test_onlyP%2) == 0) {
Stefan's avatar
Stefan committed
3308
        hi_dci0_pduLoop->dci_pdu.dci_pdu_rel8.cce_index = fCCE;
3309 3310
        LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n",
              subframeP,
Stefan's avatar
Stefan committed
3311
              test_onlyP);
3312
      }
3313

3314 3315
      idci++;
    }
3316
  }       // for i = 0 ... num_UL_DCIs
3317 3318

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

3321 3322
    // allocate DL UE specific DCIs
    if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
Stefan's avatar
Stefan committed
3323
        && (dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type == 1)) {
3324
      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",
3325
            idci,
Stefan's avatar
Stefan committed
3326
            DL_req->number_dci + HI_DCI0_req->number_of_dci,
3327
            DL_req->number_dci, HI_DCI0_req->number_of_dci,
Stefan's avatar
Stefan committed
3328
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3329 3330
            dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
            nCCE,
Stefan's avatar
Stefan committed
3331
            nCCE_max,
3332
            DL_req->number_pdcch_ofdm_symbols);
3333

Stefan's avatar
Stefan committed
3334
      if (nCCE + (dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) {
3335
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol)
3336
          return -1;
3337

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

3345 3346
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
3347 3348
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                             nCCE_max,
Stefan's avatar
Stefan committed
3349 3350
                             0,
                             dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
3351 3352
                             subframeP);

3353
      if (fCCE == -1) {
3354
        if (DL_req->number_pdcch_ofdm_symbols == max_symbol) {
3355
          LOG_D(MAC, "subframe %d: Dropping Allocation for RNTI %x\n",
3356
                subframeP,
Stefan's avatar
Stefan committed
3357
                dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.rnti);
3358 3359

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

Stefan's avatar
Stefan committed
3362
            if (dl_config_pduLoop->pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
3363
              LOG_D(MAC, "DCI %d/%d (%d,%d) : rnti %x dci format %d, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
3364 3365 3366 3367
                    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
3368 3369 3370
                    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,
3371 3372 3373 3374
                    nCCE,
                    nCCE_max,
                    DL_req->number_pdcch_ofdm_symbols);
          }
frtabu's avatar
frtabu committed
3375

3376
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
3377
          return -1;
3378 3379
        }

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

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

3392
      if ((test_onlyP%2) == 0) {
Stefan's avatar
Stefan committed
3393
        dl_config_pduLoop->dci_dl_pdu.dci_dl_pdu_rel8.cce_idx = fCCE;
3394 3395
        LOG_D(MAC, "Allocate CCEs subframe %d, test %d\n",
              subframeP,
Stefan's avatar
Stefan committed
3396
              test_onlyP);
3397
      }
3398

3399
      if ((test_onlyP/2) == 1) {
3400 3401 3402 3403 3404 3405 3406 3407 3408 3409 3410
        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) ;
          }
3411 3412
        }
      }
3413

3414 3415
      idci++;
    }
3416
  }       // for i = 0 ... num_DL_DCIs
frtabu's avatar
frtabu committed
3417

3418
  return 0;
3419 3420
}

3421
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3422 3423
nfapi_ul_config_request_pdu_t *
has_ul_grant(module_id_t module_idP,
3424 3425 3426
             int CC_idP,
             uint16_t absSFP,
             uint16_t rnti)
3427
//------------------------------------------------------------------------------
3428
{
Stefan's avatar
Stefan committed
3429 3430 3431 3432
  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",
3433 3434
        rnti,
        absSFP % 10,
Stefan's avatar
Stefan committed
3435 3436 3437 3438
        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;
3439
    LOG_D(MAC, "PDU %d : type %d,rnti %x\n",
Stefan's avatar
Stefan committed
3440
          i,
3441
          pdu_type,
Stefan's avatar
Stefan committed
3442 3443 3444 3445 3446 3447 3448 3449 3450 3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468 3469 3470 3471 3472 3473 3474 3475 3476 3477 3478 3479 3480 3481 3482 3483 3484
          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;
3485
  }
Cedric Roux's avatar
Cedric Roux committed
3486

3487
  return (NULL);    // no ul grant at all for this UE
3488
}
Cedric Roux's avatar
Cedric Roux committed
3489

3490
//------------------------------------------------------------------------------
3491 3492
boolean_t
CCE_allocation_infeasible(int module_idP,
3493 3494 3495 3496 3497
                          int CC_idP,
                          int format_flag,
                          int subframe,
                          int aggregation,
                          int rnti)
3498
//------------------------------------------------------------------------------
3499
{
3500 3501
  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];
3502
  nfapi_hi_dci0_request_body_t *HI_DCI0_req    = &RC.mac[module_idP]->HI_DCI0_req[CC_idP][subframe].hi_dci0_request_body;
3503
  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];
3504
  boolean_t res = TRUE;
3505

3506
  if (format_flag != 2) { // DL DCI
3507
    if (DL_req->number_pdu == MAX_NUM_DL_PDU) {
3508
      LOG_W(MAC, "Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", subframe, rnti);
3509 3510 3511 3512 3513 3514 3515
    } 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++;
3516
      LOG_D(MAC, "Subframe %d: Checking CCE feasibility format %d : (%x,%d) \n",
3517
            subframe, format_flag, rnti, aggregation);
3518

3519 3520
      if (allocate_CCEs(module_idP, CC_idP, 0, subframe, 0) != -1)
        res = FALSE;
frtabu's avatar
frtabu committed
3521

3522 3523
      DL_req->number_pdu--;
    }
3524
  } else { // ue-specific UL DCI
3525
    if (HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi == MAX_NUM_HI_DCI0_PDU) {
3526
      LOG_W(MAC, "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n", subframe, rnti);
3527 3528 3529 3530 3531 3532
    } 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++;
3533

3534 3535
      if (allocate_CCEs(module_idP, CC_idP, 0, subframe, 0) != -1)
        res = FALSE;
frtabu's avatar
frtabu committed
3536

3537
      HI_DCI0_req->number_of_dci--;
3538
    }
3539
  }
3540

3541
  return res;
3542
}
3543

3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554 3555 3556 3557 3558 3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570 3571 3572 3573 3574 3575 3576 3577 3578 3579 3580 3581 3582 3583 3584 3585 3586 3587 3588 3589 3590 3591 3592 3593 3594 3595 3596 3597 3598 3599 3600 3601 3602 3603 3604
int CCE_try_allocate_dlsch(int module_id,
                           int CC_id,
                           int subframe,
                           int UE_id,
                           uint8_t dl_cqi) {
  const rnti_t rnti = RC.mac[module_id]->UE_info.UE_template[CC_id][UE_id].rnti;
  nfapi_dl_config_request_body_t *DL_req       = &RC.mac[module_id]->DL_req[CC_id].dl_config_request_body;

  if (DL_req->number_pdu >= MAX_NUM_DL_PDU) {
    LOG_W(MAC, "Subframe %d: FAPI DL structure is full, skip scheduling UE %d\n", subframe, rnti);
    return -1;
  }

  int aggregation = 2;
  const uint8_t tm = get_tmode(module_id, CC_id, UE_id);
  switch (tm) {
    case 1:
    case 2:
    case 7:
      aggregation = get_aggregation(get_bw_index(module_id, CC_id),
                                    dl_cqi,
                                    format1);
      break;

    case 3:
      aggregation = get_aggregation(get_bw_index(module_id, CC_id),
                                    dl_cqi,
                                    format2A);
      break;

    default:
      AssertFatal(0, "Unsupported transmission mode %d\n", tm);
      break;
  }

  nfapi_dl_config_request_pdu_t *dl_config_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu];
  memset(dl_config_pdu, 0, sizeof(nfapi_dl_config_request_pdu_t));
  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         = 1;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level = aggregation;
  DL_req->number_pdu++;
  LOG_D(MAC, "Subframe %d: Checking CCE feasibility format 1: (%x,%d) \n",
        subframe, rnti, aggregation);

  if (allocate_CCEs(module_id, CC_id, 0, subframe, 0) < 0) {
    DL_req->number_pdu--;
    return -1;
  }

  DL_req->number_dci++;
  nfapi_dl_config_request_pdu_t *dl_dlsch_pdu = &DL_req->dl_config_pdu_list[DL_req->number_pdu];
  dl_dlsch_pdu->pdu_type = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
  dl_dlsch_pdu->dlsch_pdu.dlsch_pdu_rel8.tl.tag = NFAPI_DL_CONFIG_REQUEST_DLSCH_PDU_REL8_TAG;
  dl_dlsch_pdu->dlsch_pdu.dlsch_pdu_rel8.rnti = rnti;
  DL_req->number_pdu++;

  return DL_req->number_pdu - 2;
}

3605 3606 3607 3608 3609 3610 3611 3612 3613 3614 3615 3616 3617 3618 3619 3620 3621 3622 3623 3624 3625 3626 3627 3628 3629 3630 3631 3632 3633 3634 3635 3636 3637 3638 3639 3640 3641 3642 3643 3644 3645 3646 3647 3648 3649 3650 3651 3652 3653 3654 3655 3656 3657 3658
int CCE_try_allocate_ulsch(int module_id,
                           int CC_id,
                           int subframe,
                           int UE_id,
                           uint8_t dl_cqi) {
  const rnti_t rnti = RC.mac[module_id]->UE_info.UE_template[CC_id][UE_id].rnti;
  nfapi_hi_dci0_request_body_t *HI_DCI0_req = &RC.mac[module_id]->HI_DCI0_req[CC_id][subframe].hi_dci0_request_body;

  if (HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi >= MAX_NUM_HI_DCI0_PDU) {
    LOG_W(MAC, "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n", subframe, rnti);
    return -1;
  }

  int aggregation = 2;
  const uint8_t tm = get_tmode(module_id, CC_id, UE_id);
  switch (tm) {
    case 1:
    case 2:
    case 7:
      aggregation = get_aggregation(get_bw_index(module_id, CC_id),
                                    dl_cqi,
                                    format1);
      break;

    case 3:
      aggregation = get_aggregation(get_bw_index(module_id, CC_id),
                                    dl_cqi,
                                    format2A);
      break;

    default:
      AssertFatal(0, "Unsupported transmission mode %d\n", tm);
      break;
  }

  const int idx = HI_DCI0_req->number_of_dci + HI_DCI0_req->number_of_hi;
  nfapi_hi_dci0_request_pdu_t *hi_dci0_pdu = &HI_DCI0_req->hi_dci0_pdu_list[idx];
  memset(hi_dci0_pdu, 0, sizeof(nfapi_hi_dci0_request_pdu_t));
  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++;
  LOG_D(MAC, "%s() sf %d: Checking CCE feasibility format 2: RNTI %04x, agg %d\n",
        __func__, subframe, rnti, aggregation);

  if (allocate_CCEs(module_id, CC_id, 0, subframe, 0) < 0) {
    HI_DCI0_req->number_of_dci--;
    return -1;
  }

  return idx;
}

3659
//------------------------------------------------------------------------------
3660 3661
void
get_retransmission_timing(LTE_TDD_Config_t *tdd_Config,
3662
                          frame_t *frameP,
3663
                          sub_frame_t *subframeP)
3664 3665
//------------------------------------------------------------------------------
{
3666
  if (tdd_Config == NULL) {
3667
    if (*subframeP > 1) {
3668
      *frameP = (*frameP + 1) % 1024;
3669
    }
frtabu's avatar
frtabu committed
3670

3671 3672 3673 3674
    *subframeP = (*subframeP + 8) % 10;
  } else {
    switch (tdd_Config->subframeAssignment) { //TODO fill in other TDD configs
      default:
3675 3676
        printf("%s:%d: TODO\n",
               __FILE__,
3677
               __LINE__);
3678
        abort();
3679
        break;
3680 3681 3682 3683

      case 1:
        if (*subframeP == 0 || *subframeP == 5) {
          *subframeP  += 19;
3684
          *frameP = (*frameP + (*subframeP / 10)) % 1024;
3685 3686 3687
          *subframeP %= 10;
        } else if (*subframeP == 4 || *subframeP == 9) {
          *subframeP  += 16;
3688
          *frameP = (*frameP + (*subframeP / 10)) % 1024;
3689 3690
          *subframeP %= 10;
        } else {
3691
          AssertFatal(2 == 1, "Illegal dl subframe %d for tdd config %ld\n",
3692
                      *subframeP,
3693
                      tdd_Config->subframeAssignment);
3694
        }
frtabu's avatar
frtabu committed
3695

3696
        break;
3697
    }
3698
  }
frtabu's avatar
frtabu committed
3699

3700
  return;
3701 3702
}

3703
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3704 3705
uint8_t
get_dl_subframe_count(int tdd_config_sfa,
3706
                      sub_frame_t subframeP)
3707
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3708
{
3709
  uint8_t tdd1[10] = {1, -1, -1, -1, 2, 3, -1, -1, -1, 4}; // special subframes 1,6 are excluded
3710

Stefan's avatar
Stefan committed
3711 3712
  switch (tdd_config_sfa) {// TODO fill in other tdd configs
    case 1:
3713 3714
      return tdd1[subframeP];
  }
3715

3716
  return -1;
3717 3718
}

3719
//------------------------------------------------------------------------------
Stefan's avatar
Stefan committed
3720 3721 3722
uint8_t
frame_subframe2_dl_harq_pid(LTE_TDD_Config_t *tdd_Config,
                            int abs_frameP,
3723
                            sub_frame_t subframeP)
3724 3725
//------------------------------------------------------------------------------
{
3726
  int harq_pid;
Stefan's avatar
Stefan committed
3727
  uint8_t count;
3728

Stefan's avatar
Stefan committed
3729
  if (tdd_Config) {
3730 3731
    switch(tdd_Config->subframeAssignment) { //TODO fill in other tdd config
      case 1:
3732
        count = get_dl_subframe_count(tdd_Config->subframeAssignment,
3733
                                      subframeP);
Stefan's avatar
Stefan committed
3734
        harq_pid = (((frame_cnt * 1024 + abs_frameP) * 4) - 1 + count) % 7;//4 dl subframe in a frame
3735

Stefan's avatar
Stefan committed
3736
        if (harq_pid < 0) {
3737
          harq_pid += 7;
3738
        }
3739 3740

        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
3741 3742 3743 3744 3745 3746
              (abs_frameP + 1024) % 1024,
              subframeP,
              frame_cnt,
              abs_frameP,
              count,
              harq_pid);
3747
        return harq_pid;
3748
    }
3749
  } else {
Stefan's avatar
Stefan committed
3750
    return ((abs_frameP * 10) + subframeP) & 7;
3751
  }
3752

3753
  return -1;
3754 3755
}

3756
//------------------------------------------------------------------------------
3757
unsigned char
3758
ul_ACK_subframe2M(LTE_TDD_Config_t *tdd_Config,
3759
                  unsigned char subframe)
3760
//------------------------------------------------------------------------------
3761 3762
{
  if (tdd_Config == NULL) {
3763
    return 1;
3764
  }
frtabu's avatar
frtabu committed
3765

3766
  switch (tdd_Config->subframeAssignment) {
3767
    case 1:
3768
      return 1; // don't ACK special subframe for now
frtabu's avatar
frtabu committed
3769 3770 3771 3772 3773 3774 3775 3776 3777 3778 3779 3780 3781 3782 3783 3784

    /*
    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;
    */
3785 3786
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
3787
        return 2; // should be 3
3788
      }
frtabu's avatar
frtabu committed
3789

3790 3791
      if (subframe == 3) { // ACK subframes 7 and 8
        return 2;  // To be updated
3792
      }
frtabu's avatar
frtabu committed
3793

3794 3795
      if (subframe == 4) { // ACK subframes 9 and 0
        return 2;
3796
      }
frtabu's avatar
frtabu committed
3797

3798 3799 3800
      AssertFatal(1==0,"illegal subframe %d for tdd_config %ld\n",
                  subframe,
                  tdd_Config->subframeAssignment);
3801 3802 3803
      break;

    case 4:
3804 3805
      if (subframe == 2) {  // ACK subframes 0,4 and 5
        return 3; // should be 4
3806
      }
frtabu's avatar
frtabu committed
3807

3808 3809
      if (subframe == 3) { // ACK subframes 6,7,8 and 9
        return 4;
3810
      }
frtabu's avatar
frtabu committed
3811

3812 3813 3814 3815
      AssertFatal(1==0,"illegal subframe %d for tdd_config %ld\n",
                  subframe,
                  tdd_Config->subframeAssignment);
      break;
3816 3817

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

3822 3823 3824 3825
      AssertFatal(1==0,"illegal subframe %d for tdd_config %ld\n",
                  subframe,
                  tdd_Config->subframeAssignment);
      break;
3826 3827
  }

3828
  return 0;
3829 3830
}

3831
//------------------------------------------------------------------------------
3832
unsigned char
3833 3834
ul_ACK_subframe2dl_subframe(LTE_TDD_Config_t *tdd_Config,
                            unsigned char subframe,
3835
                            unsigned char ACK_index)
3836
//------------------------------------------------------------------------------
3837 3838
{
  if (tdd_Config == NULL) {
3839
    return ((subframe < 4) ? subframe + 6 : subframe - 4);
3840
  }
3841

3842
  switch (tdd_Config->subframeAssignment) {
3843 3844
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
3845
        if (ACK_index == 2) return 1;
frtabu's avatar
frtabu committed
3846

3847
        return (5 + ACK_index);
3848
      }
frtabu's avatar
frtabu committed
3849

3850 3851
      if (subframe == 3) { // ACK subframes 7 and 8
        return (7 + ACK_index);  // To be updated
3852
      }
frtabu's avatar
frtabu committed
3853

3854 3855
      if (subframe == 4) { // ACK subframes 9 and 0
        return ((9 + ACK_index) % 10);
3856
      }
frtabu's avatar
frtabu committed
3857

3858
      AssertFatal(1==0, "illegal subframe %d for tdd_config->subframeAssignment %ld\n",
3859 3860
                  subframe,
                  tdd_Config->subframeAssignment);
3861 3862 3863
      break;

    case 4:
3864 3865 3866 3867
      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
3868

3869
        return (4 + ACK_index);
3870
      }
frtabu's avatar
frtabu committed
3871

3872 3873
      if (subframe == 3) { // ACK subframes 6, 7 8 and 9
        return (6 + ACK_index);  // To be updated
3874
      }
frtabu's avatar
frtabu committed
3875

3876
      AssertFatal(1 == 0, "illegal subframe %d for tdd_config %ld\n",
3877 3878 3879
                  subframe,
                  tdd_Config->subframeAssignment);
      break;
3880 3881 3882

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

3886 3887 3888
      if (subframe == 3) { // ACK subframe 9
        return 9;  // To be updated
      }
frtabu's avatar
frtabu committed
3889

3890 3891 3892
      if (subframe == 7) { // ACK subframes 0 and 1
        return ACK_index;  // To be updated
      }
frtabu's avatar
frtabu committed
3893

3894 3895
      if (subframe == 8) { // ACK subframe 4
        return 4;  // To be updated
3896
      }
frtabu's avatar
frtabu committed
3897

3898
      AssertFatal(1 == 0, "illegal subframe %d for tdd_config %ld\n",
3899 3900
                  subframe,
                  tdd_Config->subframeAssignment);
3901 3902
      break;
  }
frtabu's avatar
frtabu committed
3903

3904
  return 0;
3905
}
3906

3907
//------------------------------------------------------------------------------
3908
void
3909 3910
extract_harq(module_id_t mod_idP,
             int CC_idP,
3911
             int UE_id,
3912
             frame_t frameP,
3913
             sub_frame_t subframeP,
3914 3915
             void *harq_indication,
             int format)
3916
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
3917
{
3918
  eNB_MAC_INST *eNB = RC.mac[mod_idP];
3919 3920
  UE_info_t *UE_info = &eNB->UE_info;
  UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
3921
  rnti_t rnti = UE_RNTI(mod_idP, UE_id);
3922
  COMMON_channels_t *cc = &eNB->common_channels[CC_idP];
3923 3924 3925
  nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd;
  nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd;
  uint16_t num_ack_nak;
3926 3927
  int numCC = UE_info->numactiveCCs[UE_id];
  int pCCid = UE_info->pCC_id[UE_id];
3928 3929
  int spatial_bundling = 0;
  int tmode[5];
3930
  int i, j, m;
3931
  uint8_t *pdu;
3932 3933 3934
  sub_frame_t subframe_tx;
  int frame_tx;
  uint8_t harq_pid;
3935
  LTE_PhysicalConfigDedicated_t *physicalConfigDedicated = UE_info->UE_template[pCCid][UE_id].physicalConfigDedicated;
frtabu's avatar
frtabu committed
3936

3937 3938
  if (physicalConfigDedicated != NULL && physicalConfigDedicated->pucch_ConfigDedicated != NULL &&
      physicalConfigDedicated->ext7 != NULL && physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13 != NULL &&
3939 3940
      ((physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUCCH_r13 && format == 0) ||
       (physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUSCH_r13 && format == 1))) {
3941
    spatial_bundling = 1;
3942
  }
frtabu's avatar
frtabu committed
3943

3944
  for (i = 0; i < numCC; i++) {
3945 3946
    tmode[i] = get_tmode(mod_idP,
                         i,
3947 3948
                         UE_id);
  }
frtabu's avatar
frtabu committed
3949

3950 3951 3952 3953
  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;
3954

3955
    switch (harq_indication_tdd->mode) {
3956
      case 0:   // Format 1a/b bundling
3957
        AssertFatal(numCC == 1, "numCC %d > 1, should not be using Format1a/b\n",
3958 3959 3960
                    numCC);
        int M = ul_ACK_subframe2M(cc->tdd_Config,
                                  subframeP);
3961

3962 3963
        for (m=0; m<M; m++) {
          subframe_tx = ul_ACK_subframe2dl_subframe(cc->tdd_Config,
frtabu's avatar
frtabu committed
3964 3965
                        subframeP,
                        m);
3966

3967 3968
          if (frameP==1023&&subframeP>5) frame_tx=-1;
          else frame_tx = subframeP < 4 ? frameP -1 : frameP;
3969

3970 3971 3972 3973
          harq_pid = frame_subframe2_dl_harq_pid(cc->tdd_Config,
                                                 frame_tx,
                                                 subframe_tx);
          RA_t *ra = &eNB->common_channels[CC_idP].ra[0];
3974

3975 3976
          if(num_ack_nak == 1) {
            if (harq_indication_tdd->harq_data[0].bundling.value_0 == 1) { //ack
3977 3978
              sched_ctl->round[CC_idP][harq_pid] = 8; // release HARQ process
              sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
3979 3980 3981 3982 3983 3984 3985
              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]);
3986
            } else { //nack
3987
              if (sched_ctl->round[CC_idP][harq_pid] < 8) sched_ctl->round[CC_idP][harq_pid]++;
3988 3989 3990 3991 3992 3993

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

3994 3995 3996 3997 3998 3999 4000
              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]);
4001

4002
              if (sched_ctl->round[CC_idP][harq_pid] == 8) {
4003
                for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
4004
                  if (ra[ra_i].rnti == rnti && ra[ra_i].state == WAITMSG4ACK) {
4005 4006
                    //Msg NACK num to MAC ,remove UE
                    // add UE info to freeList
4007
                    LOG_I(RRC, "put UE %x into freeList\n",
4008
                          rnti);
4009
                    put_UE_in_freelist(mod_idP,
frtabu's avatar
frtabu committed
4010 4011
                                       rnti,
                                       1);
4012 4013 4014 4015 4016 4017 4018
                  }
                }
              }
            }
          }

          for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
4019 4020 4021 4022 4023 4024 4025
            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
4026

4027
              if (num_ack_nak == 1 && harq_indication_tdd->harq_data[0].bundling.value_0 == 1) {
4028 4029 4030
                cancel_ra_proc(mod_idP,
                               CC_idP,
                               frameP,
4031
                               ra[ra_i].rnti);
4032 4033
              } else {
                if(sched_ctl->round[CC_idP][harq_pid] == 7) {
4034 4035 4036
                  cancel_ra_proc(mod_idP,
                                 CC_idP,
                                 frameP,
4037
                                 ra[ra_i].rnti);
4038 4039
                }
              }
frtabu's avatar
frtabu committed
4040

4041 4042
              break;
            }
4043 4044
          }
        }
4045

4046 4047 4048 4049 4050 4051 4052
        break;

      case 1:   // Channel Selection
      case 2:   // Format 3
      case 3:   // Format 4
      case 4:   // Format 5
        break;
4053 4054 4055 4056 4057
    }
  } 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];
4058
    harq_pid = ((10 * frameP) + subframeP + 10236) & 7;
4059 4060 4061 4062 4063 4064 4065 4066
    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]);
4067

4068
    // use 1 HARQ proces of BL/CE UE for now
4069
    if (UE_info->UE_template[pCCid][UE_id].rach_resource_type > 0) harq_pid = 0;
4070 4071

    switch (harq_indication_fdd->mode) {
Stefan's avatar
Stefan committed
4072
      case 0:   // Format 1a/b (10.1.2.1)
4073
        AssertFatal(numCC == 1, "numCC %d > 1, should not be using Format1a/b\n",
4074
                    numCC);
Stefan's avatar
Stefan committed
4075 4076

        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
4077
          // single ACK/NAK bit
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4078 4079 4080 4081
          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
4082 4083

          // In case of nFAPI, sometimes timing of eNB and UE become different.
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4084
          // So if nfapi_mode == 2(VNF), this function don't check assertion to avoid process exit.
frtabu's avatar
frtabu committed
4085
          if (NFAPI_MODE != NFAPI_MODE_VNF) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4086
            AssertFatal(sched_ctl->round[CC_idP][harq_pid] < 8, "Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",
4087 4088
                        harq_pid,
                        UE_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4089
                        rnti);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4090 4091
          } else {
            if (sched_ctl->round[CC_idP][harq_pid] == 8) {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4092
              LOG_E(MAC,"Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",
4093 4094
                    harq_pid,
                    UE_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4095
                    rnti);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4096 4097
              return;
            }
4098
          }
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4099 4100

          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",
4101 4102 4103
                      pdu[0],
                      harq_pid,
                      UE_id,
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4104
                      rnti);
4105 4106
          LOG_D(MAC, "Received %d for harq_pid %d\n",
                pdu[0],
4107 4108
                harq_pid);
          RA_t *ra = &eNB->common_channels[CC_idP].ra[0];
4109 4110

          for (uint8_t ra_i = 0; ra_i < NB_RA_PROC_MAX; ra_i++) {
4111
            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
4112 4113 4114 4115
              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
4116 4117
                    frameP,
                    subframeP);
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4118 4119

              if (pdu[0] == 1) {
4120 4121 4122
                cancel_ra_proc(mod_idP,
                               CC_idP,
                               frameP,
4123
                               ra[ra_i].rnti);
4124
              } else {
Louis Adrien Dufrene's avatar
Louis Adrien Dufrene committed
4125
                if (sched_ctl->round[CC_idP][harq_pid] == 7) {
4126 4127 4128
                  cancel_ra_proc(mod_idP,
                                 CC_idP,
                                 frameP,
4129
                                 ra[ra_i].rnti);
4130 4131
                }
              }
frtabu's avatar
frtabu committed
4132

4133
              break;
Xu Bo's avatar
Xu Bo committed
4134
            }
4135
          }
4136

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

4139 4140
          if (pdu[0] == 1) {  // ACK
            sched_ctl->round[CC_idP][harq_pid] = 8; // release HARQ process
4141
            sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
4142 4143
            /* CDRX: PUCCH gives an ACK, so reset corresponding HARQ RTT */
            sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4144 4145 4146 4147 4148 4149
          } 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;
4150 4151
              /* 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;
4152 4153 4154 4155 4156
            }

            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)) {
4157
                  // Msg NACK num to MAC ,remove UE
4158
                  // add UE info to freeList
4159
                  LOG_I(RRC, "put UE %x into freeList\n",
4160
                        rnti);
4161 4162
                  put_UE_in_freelist(mod_idP,
                                     rnti,
4163
                                     1);
4164 4165 4166
                }
              }
            }
4167
          }
4168 4169
        } else {
          // one or two ACK/NAK bits
4170
          AssertFatal(num_ack_nak <= 2, "num_ack_nak %d > 2 for 1 CC and TM3/4/8/9/10\n",
4171 4172
                      num_ack_nak);

4173
          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) {
4174
            sched_ctl->round[CC_idP][harq_pid] = 8;
4175
            sched_ctl->tbcnt[CC_idP][harq_pid] = 0;
4176 4177
            /* CDRX: PUCCH gives an ACK, so reset corresponding HARQ RTT */
            sched_ctl->harq_rtt_timer[CC_idP][harq_pid] = 0;
4178
          }
4179 4180 4181 4182 4183 4184 4185 4186 4187 4188

          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;
4189 4190
              /* 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;
4191 4192 4193 4194 4195 4196 4197 4198 4199 4200 4201 4202 4203 4204 4205
            }
          } 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? */
4206 4207
              /* 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;
4208 4209 4210 4211 4212 4213 4214 4215 4216 4217
            }
          } 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;
4218 4219
              /* 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;
4220 4221
            }
          } else
4222
            AssertFatal(1 == 0, "Illegal ACK/NAK/round combination (%d,%d,%d,%d,%d) for harq_pid %d, UE %d/%x\n",
4223 4224
                        num_ack_nak,
                        sched_ctl->round[CC_idP][harq_pid],
4225
                        sched_ctl->round[CC_idP][harq_pid],
4226
                        pdu[0],
4227 4228 4229
                        pdu[1],
                        harq_pid,
                        UE_id,
4230
                        rnti);
4231
        }
4232 4233 4234 4235

        break;

      case 1:   // FDD Channel Selection (10.1.2.2.1), must be received for 2 serving cells
4236
        AssertFatal(numCC == 2, "Should not receive harq indication with channel selection with %d active CCs\n",
4237 4238 4239 4240 4241 4242 4243 4244 4245 4246 4247 4248 4249 4250 4251 4252 4253 4254 4255
                    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;
4256
          }
4257 4258 4259 4260 4261 4262 4263 4264

          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;
4265
          }
4266 4267 4268 4269 4270 4271 4272 4273 4274 4275 4276 4277
        }     // 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]);
4278
          AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 2, "sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",
4279 4280 4281
                      pCCid,
                      harq_pid,
                      UE_id,
4282 4283
                      rnti);
          AssertFatal(sched_ctl->tbcnt[1 - pCCid][harq_pid] == 1, "sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",
4284 4285 4286
                      1 - pCCid,
                      harq_pid,
                      UE_id,
4287 4288 4289
                      rnti);

          if (pdu[0] == 1 && pdu[1] == 1) { // both ACK
4290 4291
            sched_ctl->round[pCCid][harq_pid] = 8;
            sched_ctl->tbcnt[pCCid][harq_pid] = 0;
4292
          } else if ((pdu[0] == 2 && pdu[1] == 1) || (pdu[0] == 1 && pdu[1] == 2)) {
4293 4294 4295 4296 4297 4298 4299 4300 4301
            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]++;
4302

4303 4304 4305 4306
            if (sched_ctl->round[pCCid][harq_pid] == 4) {
              sched_ctl->round[pCCid][harq_pid] = 8;
              sched_ctl->tbcnt[pCCid][harq_pid] = 0;
            }
4307
          }
4308

4309
          if (pdu[2] == 1) sched_ctl->round[1 - pCCid][harq_pid] = 8;
4310 4311 4312 4313 4314 4315
          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;
            }
4316
          }
4317 4318 4319 4320 4321 4322 4323 4324 4325 4326 4327 4328
        }     // 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]);
4329
          AssertFatal(sched_ctl->tbcnt[1 - pCCid][harq_pid] == 2, "sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",
4330 4331 4332
                      1 - pCCid,
                      harq_pid,
                      UE_id,
4333 4334
                      rnti);
          AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 1, "sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",
4335 4336 4337
                      pCCid,
                      harq_pid,
                      UE_id,
4338 4339 4340
                      rnti);

          if (pdu[0] == 1 && pdu[1] == 1) { // both ACK
4341 4342
            sched_ctl->round[1 - pCCid][harq_pid] = 8;
            sched_ctl->tbcnt[1 - pCCid][harq_pid] = 0;
4343
          } else if ((pdu[0] >= 2 && pdu[1] == 1) || (pdu[0] == 1 && pdu[1] >= 2)) { // one ACK
4344 4345 4346 4347 4348 4349 4350 4351 4352 4353 4354 4355 4356 4357
            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;
            }
4358
          }
4359

4360
          if (pdu[2] == 1) sched_ctl->round[pCCid][harq_pid] = 8;
4361 4362 4363 4364 4365 4366
          else {
            sched_ctl->round[pCCid][harq_pid]++;

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

4370
#if MAX_NUM_CCs>1
4371 4372 4373 4374 4375 4376 4377 4378 4379 4380 4381 4382 4383
        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]);
4384
          AssertFatal(sched_ctl->tbcnt[0][harq_pid] == 2, "sched_ctl->tbcnt[0][%d] != 2 for UE %d/%x\n",
4385 4386
                      harq_pid,
                      UE_id,
4387 4388
                      rnti);
          AssertFatal(sched_ctl->tbcnt[1][harq_pid] == 2, "sched_ctl->tbcnt[1][%d] != 2 for UE %d/%x\n",
4389 4390
                      harq_pid,
                      UE_id,
4391 4392 4393
                      rnti);

          if (pdu[0] == 1 && pdu[1] == 1) { // both ACK
4394 4395
            sched_ctl->round[0][harq_pid] = 8;
            sched_ctl->tbcnt[0][harq_pid] = 0;
4396
          } else if ((pdu[0] >= 2 && pdu[1] == 1) || (pdu[0] == 1 && pdu[1] >= 2)) { // one ACK
4397 4398 4399 4400 4401 4402 4403 4404 4405
            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]++;
4406

4407 4408 4409 4410
            if (sched_ctl->round[0][harq_pid] == 4) {
              sched_ctl->round[0][harq_pid] = 8;
              sched_ctl->tbcnt[0][harq_pid] = 0;
            }
4411
          }
4412

4413
          if (pdu[2] == 1 && pdu[3] == 1) { // both ACK
4414 4415
            sched_ctl->round[1][harq_pid] = 8;
            sched_ctl->tbcnt[1][harq_pid] = 0;
4416
          } else if ((pdu[2] >= 2 && pdu[3] == 1) || (pdu[2] == 1 && pdu[3] >= 2)) { // one ACK
4417 4418 4419 4420 4421 4422 4423 4424 4425 4426 4427 4428 4429 4430
            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;
            }
4431
          }
4432 4433
        }     // A=4 both serving cells have 2 TBs

4434
#endif
4435 4436 4437
        break;

      case 2:   // Format 3
4438
        AssertFatal(numCC > 2, "Should not receive harq indication with FDD format 3 with %d < 3 active CCs\n",
4439 4440 4441
                    numCC);

        for (i = 0, j = 0; i < numCC; i++) {
4442 4443
          if (sched_ctl->round[i][harq_pid] < 8) {
            if (tmode[i] == 1 || tmode[i] == 2 || tmode[0] == 5 || tmode[0] == 6 || tmode[0] == 7) {
4444 4445 4446 4447 4448 4449 4450 4451 4452 4453 4454
              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
4455
                AssertFatal(1 == 0, "Illegal harq_ack value for CC %d harq_pid %d (%d) UE %d/%x\n",
4456 4457 4458 4459
                            i,
                            harq_pid,
                            pdu[j],
                            UE_id,
4460
                            rnti);
4461 4462 4463

              j++;
            } else if (spatial_bundling == 0) {
4464
              if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 1 && pdu[j + 1] == 1) {
4465 4466
                sched_ctl->round[i][harq_pid] = 8;
                sched_ctl->tbcnt[i][harq_pid] = 0;
4467
              } else if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 1 && pdu[j + 1] == 2) {
4468 4469 4470 4471 4472 4473 4474
                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;
                }
4475
              } else if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 2 && pdu[j + 1] == 1) {
4476 4477 4478 4479 4480 4481 4482
                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;
                }
4483
              } else if (sched_ctl->tbcnt[i][harq_pid] == 2 && pdu[j] == 2 && pdu[j + 1] == 2) {
4484 4485 4486 4487 4488 4489 4490
                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
4491
                AssertFatal(1 == 0, "Illegal combination for CC %d harq_pid %d (%d,%d,%d) UE %d/%x\n",
4492
                            i,
4493
                            harq_pid,
4494
                            sched_ctl->tbcnt[i][harq_pid],
4495 4496 4497
                            pdu[j],
                            pdu[j + 1],
                            UE_id,
4498
                            rnti);
4499 4500 4501 4502 4503 4504 4505 4506 4507 4508 4509 4510 4511

              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;
                }
4512 4513
              } else {
                AssertFatal(1 == 0, "Illegal hack_nak value %d for CC %d harq_pid %d UE %d/%x\n",
4514 4515 4516 4517
                            pdu[j],
                            i,
                            harq_pid,
                            UE_id,
4518
                            rnti);
4519
              }
frtabu's avatar
frtabu committed
4520

4521
              j++;
4522 4523
            } else {
              AssertFatal(1 == 0, "Illegal value for spatial_bundling %d\n",
4524
                          spatial_bundling);
4525 4526 4527
            }
          }
        }
4528 4529 4530 4531

        break;

      case 3:   // Format 4
4532
        AssertFatal(1 == 0, "Should not receive harq indication with Format 4\n");
4533 4534 4535
        break;

      case 4:   // Format 5
4536
        AssertFatal(1 == 0, "Should not receive harq indication with Format 5\n");
4537
        break;
4538
    }
4539
  }
frtabu's avatar
frtabu committed
4540

4541
  return;
4542 4543
}

4544
//------------------------------------------------------------------------------
4545
void
4546 4547
extract_pucch_csi(module_id_t mod_idP,
                  int CC_idP,
4548
                  int UE_id,
4549
                  frame_t frameP,
4550
                  sub_frame_t subframeP,
4551 4552
                  uint8_t *pdu,
                  uint8_t length)
4553
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
4554
{
4555 4556
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
  UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
4557 4558 4559 4560 4561
  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;
4562
  AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",
4563
              UE_id);
4564
  AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n",
4565
              UE_id);
4566
  struct LTE_CQI_ReportPeriodic *cqi_ReportPeriodic = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic;
4567
  AssertFatal(cqi_ReportPeriodic != NULL, "cqi_ReportPeriodic is null for UE %d\n",
4568
              UE_id);
4569
  // determine feedback mode
4570
  AssertFatal(cqi_ReportPeriodic->present != LTE_CQI_ReportPeriodic_PR_NOTHING, "cqi_ReportPeriodic->present == LTE_CQI_ReportPeriodic_PR_NOTHING!\n");
4571
  AssertFatal(cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present != LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING,
4572
              "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n");
4573 4574 4575
  uint16_t Npd, N_OFFSET_CQI;
  int H, K, bandwidth_part, L, Lmask;
  int ri = sched_ctl->periodic_ri_received[CC_idP];
4576 4577 4578 4579
  get_csi_params(cc,
                 cqi_ReportPeriodic,
                 &Npd,
                 &N_OFFSET_CQI,
4580
                 &H);
4581 4582 4583 4584 4585
  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;

4586 4587
  if (feedback_cnt > 0) bandwidth_part = (feedback_cnt - 1) % K;
  else bandwidth_part = 0;
4588

4589 4590
  switch (get_tmode(mod_idP,
                    CC_idP,
4591
                    UE_id)) {
4592 4593 4594 4595 4596 4597 4598 4599 4600 4601 4602 4603
    case 1:
    case 2:
    case 3:
    case 7:
      no_pmi = 1;
      break;

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

4605 4606 4607
    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;
4608
      break;
frtabu's avatar
frtabu committed
4609
  }
4610

4611
  if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == LTE_CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI ||
4612
      feedback_cnt == 0) {
4613
    // 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)
4614
    if (no_pmi == 1) {  // get spatial_diffcqi if needed
4615
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4616 4617
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0] >> 4) & 7;
    } else if (cc->p_eNB == 2 && ri == 1) {
4618 4619 4620
      // 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;
4621
    } else if (cc->p_eNB == 2 && ri > 1) {
4622 4623
      // p=2 Rank 2 wideband CQI/PMI 8 bits
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4624
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0] >> 4) & 7;
4625
      sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 7) & 1;
4626
    } else if (cc->p_eNB == 4 && ri == 1) {
4627 4628
      // p=4 Rank 1 wideband CQI/PMI 8 bits
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4629 4630
      sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 4) & 0x0F;
    } else if (cc->p_eNB == 4 && ri > 1) {
4631 4632
      // p=4 Rank 2 wideband CQI/PMI 11 bits
      sched_ctl->periodic_wideband_cqi[CC_idP] = pdu[0] & 0xF;
4633
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0] >> 4) & 7;
4634 4635
      sched_ctl->periodic_wideband_pmi[CC_idP] = (pdu[0] >> 7) & 0xF;
    } else
4636
      AssertFatal(1 == 0, "illegal combination p %d, ri %d, no_pmi %d\n",
4637 4638
                  cc->p_eNB,
                  ri,
4639
                  no_pmi);
4640 4641 4642 4643 4644 4645 4646 4647
  } 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;
4648
      sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part * L) + ((pdu[0] >> 7) & Lmask)] = pdu[0] & 0xF;
4649
    }
4650
  }
frtabu's avatar
frtabu committed
4651

4652
  return;
4653 4654
}

4655
//------------------------------------------------------------------------------
4656
void
4657 4658
extract_pusch_csi(module_id_t mod_idP,
                  int CC_idP,
4659
                  int UE_id,
4660
                  frame_t frameP,
4661
                  sub_frame_t subframeP,
4662 4663
                  uint8_t *pdu,
                  uint8_t length)
4664
//------------------------------------------------------------------------------
4665
{
4666
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
4667
  COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
4668
  UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
4669 4670 4671 4672 4673 4674 4675 4676
  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;
4677
  AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",
4678
              UE_id);
4679
  AssertFatal(UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL, "cqi_ReportConfig is null for UE %d\n",
4680
              UE_id);
4681
  LTE_CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic
4682
    = UE_info->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic;
4683
  AssertFatal(cqi_ReportModeAperiodic  != NULL, "cqi_ReportModeAperiodic is null for UE %d\n",
4684
              UE_id);
4685 4686 4687 4688 4689 4690 4691 4692
  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) {
4693 4694 4695
    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)
4696
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm12\n",
4697 4698 4699
                  tmode);

      if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213
4700 4701
        if (ri == 1 && cc->p_eNB == 2) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4702 4703 4704 4705 4706 4707 4708 4709
          p >>= 4;

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

4710 4711
        if (ri == 2 && cc->p_eNB == 2) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4712
          p >>= 4;
4713
          sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4714 4715 4716 4717 4718 4719 4720 4721
          p >>= 4;

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

4722 4723
        if (ri == 1 && cc->p_eNB == 4) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4724 4725 4726 4727 4728 4729 4730 4731
          p >>= 4;

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

4732 4733
        if (ri == 2 && cc->p_eNB == 4) {
          sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4734
          p >>= 4;
4735
          sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4736 4737 4738 4739 4740 4741 4742 4743 4744 4745
          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");
4746
      }
4747

4748 4749 4750 4751 4752
      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
4753
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm20\n",
4754 4755
                  tmode);
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4756
      p >>= 4;
4757
      diffcqi0 = (uint8_t) (p & 0x03);
4758
      p >>= 2;
4759
      r = (uint8_t) (p & ((1 >> Ltab_uesel[bw]) - 1));
4760 4761 4762
      reverse_index(Ntab_uesel[bw],
                    Mtab_uesel[bw],
                    r,
4763
                    v);
4764

4765
      for (m = 0; m < Mtab_uesel[bw]; m++) {
4766
        sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0;
4767
      }
4768 4769 4770 4771 4772 4773

      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
4774
      AssertFatal(tmode == 4 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm22\n",
4775 4776
                  tmode);
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4777
      p >>= 4;
4778 4779 4780 4781 4782 4783 4784 4785 4786
      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;
4787
      }
4788 4789 4790

      r = (uint8_t) (p & ((1 >> Ltab_uesel[bw]) - 1));
      p >>= Ltab_uesel[bw];
4791 4792 4793
      reverse_index(Ntab_uesel[bw],
                    Mtab_uesel[bw],
                    r,
4794
                    v);
4795

4796
      if (ri == 1 && cc->p_eNB == 2) {
4797 4798 4799
        pmi_uesel = p & 0x3;
        p >>= 2;
        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x3;
4800
      } else if (ri == 2 && cc->p_eNB == 2) {
4801 4802 4803 4804 4805 4806 4807
        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;
4808
      }
4809 4810 4811 4812

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

4813
        if (ri > 1) sched_ctl->aperiodic_subband_diffcqi1[CC_idP][v[m]] = diffcqi1;
4814 4815

        sched_ctl->aperiodic_subband_pmi[CC_idP][v[m]] = pmi_uesel;
4816
      }
4817 4818 4819 4820 4821

      break;

    case LTE_CQI_ReportModeAperiodic_rm30:
      //subband CQI no PMI (TM1/2/3/7)
4822
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm30\n",
4823 4824 4825 4826 4827
                  tmode);
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = pdu[0] >> 4;
      curbyte = 0;
      curbit = 3;

4828
      for (i = 0; i < N; i++) {
4829 4830 4831 4832 4833 4834 4835 4836
        sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] =
          (pdu[curbyte] >> (curbit - 1)) & 0x03;
        curbit -= 2;

        if (curbit < 0) {
          curbit = 7;
          curbyte++;
        }
4837
      }
4838

4839
      sched_ctl->dl_cqi[CC_idP] = sched_ctl->aperiodic_wideband_cqi0[CC_idP];
4840 4841 4842 4843 4844
      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)
4845
      AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10,
4846 4847 4848
                  "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm31\n",
                  tmode);

4849 4850
      if (ri == 1 && cc->p_eNB == 2) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4851 4852 4853
        p >>= 4;

        for (i = 0; i < N; i++) {
4854
          sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t) (p & 0x03);
4855 4856 4857 4858
          p >>= 2;
        }

        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x03;
4859
      }
4860

4861 4862
      if (ri == 2 && cc->p_eNB == 2) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4863 4864 4865
        p >>= 4;

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

4870
        sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4871 4872 4873
        p >>= 4;

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

        sched_ctl->aperiodic_wideband_pmi[CC_idP] = p & 0x01;
4879
      }
4880

4881 4882
      if (ri == 1 && cc->p_eNB == 4) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4883 4884 4885
        p >>= 4;

        for (i = 0; i < N; i++) {
4886
          sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t) (p & 0x03);
4887 4888 4889 4890
          p >>= 2;
        }

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

4893 4894
      if (ri > 1 && cc->p_eNB == 4) { // Note : 64 bits for 20 MHz
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t) (p & 0x0F);
4895 4896 4897
        p >>= 4;

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

4902
        sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t) (p & 0x0F);
4903 4904 4905
        p >>= 4;

        for (i = 0; i < N; i++) {
4906
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t) (p & 0x01);
4907 4908 4909 4910 4911 4912 4913
          p >>= 2;
        }

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

      break;
frtabu's avatar
frtabu committed
4914

4915
    case LTE_CQI_ReportModeAperiodic_rm32_v1250:
4916
      AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10,
4917 4918 4919 4920
                  "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
4921

4922
    case LTE_CQI_ReportModeAperiodic_rm10_v1310:
4923
      AssertFatal(tmode == 1 || tmode == 2 || tmode == 3 || tmode == 7, "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm10\n",
4924 4925 4926 4927 4928
                  tmode);
      AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm10 to be done\n");
      break;

    case LTE_CQI_ReportModeAperiodic_rm11_v1310:
4929
      AssertFatal(tmode == 4 || tmode == 5 || tmode == 6 || tmode == 8 || tmode == 9 || tmode == 10,
4930 4931 4932 4933
                  "Illegal transmission mode %d for CQI_ReportModeAperiodic_rm11\n",
                  tmode);
      AssertFatal(1 == 0, "CQI_ReportModeAperiodic_rm11 to be done\n");
      break;
4934
  }
frtabu's avatar
frtabu committed
4935

4936
  return;
4937 4938
}

4939
//------------------------------------------------------------------------------
4940
void
4941 4942
cqi_indication(module_id_t mod_idP,
               int CC_idP,
4943
               frame_t frameP,
4944
               sub_frame_t subframeP,
4945
               rnti_t rntiP,
4946
               nfapi_cqi_indication_rel9_t *rel9,
4947
               uint8_t *pdu,
4948
               nfapi_ul_cqi_information_t *ul_cqi_information)
4949
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
4950
{
4951
  int UE_id = find_UE_id(mod_idP, rntiP);
4952
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
Haruki NAOI's avatar
Haruki NAOI committed
4953
  uint64_t pdu_val = *(uint64_t *) pdu;
4954

4955 4956 4957 4958
  if (UE_id == -1) {
    LOG_W(MAC, "cqi_indication: UE %x not found\n", rntiP);
    return;
  }
4959

4960
  UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
4961

4962
  if (UE_id >= 0) {
4963 4964 4965 4966
    LOG_D(MAC,"%s() UE_id:%d channel:%d cqi:%d\n",
          __FUNCTION__,
          UE_id,
          ul_cqi_information->channel,
4967
          ul_cqi_information->ul_cqi);
4968

4969
    if (ul_cqi_information->channel == 0) { // PUCCH
4970
      // extract pucch csi information before changing RI information
4971 4972 4973 4974
      extract_pucch_csi(mod_idP,
                        CC_idP,
                        UE_id,
                        frameP,
4975
                        subframeP,
4976
                        pdu, rel9->length);
4977
      memcpy((void *) sched_ctl->periodic_ri_received,
4978
             (void *) rel9->ri,
4979
             rel9->number_of_cc_reported);
4980 4981
      // SNR for PUCCH2
      sched_ctl->pucch2_snr[CC_idP] = ul_cqi_information->ul_cqi;
4982
    } else {    //PUSCH
4983
      memcpy((void *) sched_ctl->aperiodic_ri_received,
4984
             (void *) rel9->ri,
4985
             rel9->number_of_cc_reported);
4986 4987 4988 4989
      extract_pusch_csi(mod_idP,
                        CC_idP,
                        UE_id,
                        frameP,
4990
                        subframeP,
4991
                        pdu,
4992
                        rel9->length);
Haruki NAOI's avatar
Haruki NAOI committed
4993
      LOG_D(MAC,"Frame %d Subframe %d update CQI:%d pdu 0x%016"PRIx64"\n",
4994 4995
            frameP,
            subframeP,
Haruki NAOI's avatar
Haruki NAOI committed
4996
            sched_ctl->dl_cqi[CC_idP],pdu_val);
4997 4998
      sched_ctl->cqi_req_flag &= (~(1 << subframeP));
      sched_ctl->cqi_received = 1;
4999
    }
5000 5001 5002 5003 5004

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

5006
  return;
5007 5008
}

5009
//------------------------------------------------------------------------------
5010
void
5011 5012
SR_indication(module_id_t mod_idP,
              int cc_idP,
5013
              frame_t frameP,
5014 5015 5016
              sub_frame_t subframeP,
              rnti_t rntiP,
              uint8_t ul_cqi)
5017
//------------------------------------------------------------------------------
5018
{
5019 5020
  T(T_ENB_MAC_SCHEDULING_REQUEST,
    T_INT(mod_idP),
5021
    T_INT(cc_idP),
5022 5023
    T_INT(frameP),
    T_INT(subframeP),
5024
    T_INT(rntiP));
5025
  int UE_id = find_UE_id(mod_idP, rntiP);
5026
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
5027
  UE_sched_ctrl_t *UE_scheduling_ctrl = NULL;
Cedric Roux's avatar
Cedric Roux committed
5028

5029
  if (UE_id != -1) {
5030
    UE_scheduling_ctrl = &(UE_info->UE_sched_ctrl[UE_id]);
5031

5032
    if ((UE_scheduling_ctrl->cdrx_configured == TRUE) &&
5033
        (UE_scheduling_ctrl->dci0_ongoing_timer > 0)  &&
5034
        (UE_scheduling_ctrl->dci0_ongoing_timer < 8)) {
5035 5036
      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",
5037 5038 5039 5040 5041
            mod_idP,
            rntiP,
            frameP,
            subframeP,
            UE_id,
5042
            cc_idP);
5043 5044 5045 5046 5047 5048 5049 5050 5051 5052
    } 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);
      }
5053

5054 5055
      UE_info->UE_template[cc_idP][UE_id].ul_SR = 1;
      UE_info->UE_template[cc_idP][UE_id].ul_active = TRUE;
5056 5057
      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);
5058
    }
5059
  } else {
5060
    LOG_D(MAC, "[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d (unknown UE_id) on CC_id %d\n",
5061 5062 5063 5064 5065
          mod_idP,
          rntiP,
          frameP,
          subframeP,
          UE_id,
5066
          cc_idP);
5067
  }
5068

5069
  return;
5070 5071
}

5072
//------------------------------------------------------------------------------
5073
void
5074 5075
UL_failure_indication(module_id_t mod_idP,
                      int cc_idP,
5076
                      frame_t frameP,
5077 5078
                      rnti_t rntiP,
                      sub_frame_t subframeP)
5079
//------------------------------------------------------------------------------
5080
{
5081
  int UE_id = find_UE_id(mod_idP, rntiP);
5082
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
5083

5084
  if (UE_id != -1) {
5085
    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",
5086 5087 5088 5089 5090 5091
          mod_idP,
          UE_id,
          rntiP,
          frameP,
          subframeP,
          UE_id,
5092
          cc_idP,
5093
          UE_info->UE_sched_ctrl[UE_id].ul_failure_timer);
5094

5095
    if (UE_info->UE_sched_ctrl[UE_id].ul_failure_timer == 0) UE_info->UE_sched_ctrl[UE_id].ul_failure_timer = 1;
5096 5097 5098
  } 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);
5099
    LOG_W(MAC, "[eNB %d][SR %x] Frame %d subframeP %d Signaling UL Failure for UE %d (unknown UEid) on CC_id %d\n",
5100 5101 5102 5103 5104
          mod_idP,
          rntiP,
          frameP,
          subframeP,
          UE_id,
5105
          cc_idP);
5106
  }
5107
}
5108

5109
//------------------------------------------------------------------------------
5110
static int
5111
nack_or_dtx_reported(COMMON_channels_t *cc,
5112
                     nfapi_harq_indication_pdu_t *harq_pdu)
5113
//------------------------------------------------------------------------------
5114 5115 5116 5117
{
  int i;

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

5120 5121
    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
5122
        return 1;
5123
    }
frtabu's avatar
frtabu committed
5124

Raymond Knopp's avatar
Raymond Knopp committed
5125
    return 0;
5126
  }
5127

5128
  nfapi_harq_indication_fdd_rel13_t *hi = &harq_pdu->harq_indication_fdd_rel13;
frtabu's avatar
frtabu committed
5129

5130
  for (i = 0; i < hi->number_of_ack_nack; i++) {
5131 5132
    if (hi->harq_tb_n[i] != 1)
      return 1;
5133
  }
frtabu's avatar
frtabu committed
5134

5135
  return 0;
5136
}
5137

5138
//------------------------------------------------------------------------------
5139
void
5140 5141
harq_indication(module_id_t mod_idP,
                int CC_idP,
5142
                frame_t frameP,
5143
                sub_frame_t subframeP,
5144
                nfapi_harq_indication_pdu_t *harq_pdu)
5145
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
5146
{
5147 5148 5149 5150
  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);
5151

5152
  if (UE_id == -1) {
5153
    LOG_W(MAC, "harq_indication: UE %x not found\n",
5154
          rnti);
5155 5156
    return;
  }
5157

5158 5159
  UE_info_t *UE_info = &RC.mac[mod_idP]->UE_info;
  UE_sched_ctrl_t *sched_ctl = &UE_info->UE_sched_ctrl[UE_id];
5160 5161
  COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
  // extract HARQ Information
5162

5163
  if (cc->tdd_Config) {
5164 5165 5166 5167
    extract_harq(mod_idP,
                 CC_idP,
                 UE_id,
                 frameP,
5168
                 subframeP,
5169 5170
                 (void *) &harq_pdu->harq_indication_tdd_rel13,
                 channel);
frtabu's avatar
frtabu committed
5171
  } else {
5172 5173 5174 5175
    extract_harq(mod_idP,
                 CC_idP,
                 UE_id,
                 frameP,
5176
                 subframeP,
5177 5178
                 (void *) &harq_pdu->harq_indication_fdd_rel13,
                 channel);
5179
  }
5180

5181
  /* don't care about cqi reporting if NACK/DTX is there */
5182
  if (channel == 0 && !nack_or_dtx_reported(cc,
frtabu's avatar
frtabu committed
5183
      harq_pdu)) {
5184
    sched_ctl->pucch1_snr[CC_idP] = (5 * ul_cqi - 640) / 10;
5185 5186
    sched_ctl->pucch1_cqi_update[CC_idP] = 1;
  }
frtabu's avatar
frtabu committed
5187

5188
  return;
5189
}