eNB_scheduler_primitives.c 140 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

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 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58
 * @ingroup _mac

 */

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

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

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

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

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

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

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

Cedric Roux's avatar
Cedric Roux committed
59 60
#include "T.h"

61 62 63
#define ENABLE_MAC_PAYLOAD_DEBUG
#define DEBUG_eNB_SCHEDULER 1

Cedric Roux's avatar
Cedric Roux committed
64 65
int choose(int n,int k)
{
66 67 68 69 70 71 72 73 74 75 76 77 78 79
  int res  = 1;
  int res2 = 1;
  int i;

  if (k>n) return(0);
  if (n==k) return(1);

  for (i=n;i>k;i--) res*=i;
  for (i=2;i<=(n-k);i++) res2*=i;

  return(res/res2);
}

// Patented algorithm from Yang et al, US Patent 2009, "Channel Quality Indexing and Reverse Indexing"
Cedric Roux's avatar
Cedric Roux committed
80 81
void reverse_index(int N,int M,int r,int *v)
{
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
  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;
  while (i>0 && r>0) {
    IncreaseValue = choose(N-M+1-sumV-v[i-1]+i-2,i-1);
    ThresholdValue = BaseValue+IncreaseValue;
    if (r>=ThresholdValue) {
      v[i-1]++;
      BaseValue=ThresholdValue;
    }
    else {
      r=r-BaseValue;
      sumV+=v[i-1];
      i--;
      BaseValue=0;
    }
  }
}
Cedric Roux's avatar
Cedric Roux committed
107 108 109

int to_prb(int dl_Bandwidth)
{
110
  int prbmap[6] = {6,15,25,50,75,100};
111

112 113 114 115
  AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n");
  return(prbmap[dl_Bandwidth]);
}

Cedric Roux's avatar
Cedric Roux committed
116 117
int to_rbg(int dl_Bandwidth)
{
118 119 120 121 122
  int rbgmap[6] = {6,8,13,17,19,25};

  AssertFatal(dl_Bandwidth < 6,"dl_Bandwidth is 0..5\n");
  return(rbgmap[dl_Bandwidth]);
}
123

Cedric Roux's avatar
Cedric Roux committed
124 125
int get_phich_resource_times6(COMMON_channels_t *cc)
{
126 127 128
  int phichmap[4] = {1,3,6,12};
  AssertFatal(cc!=NULL,"cc is null\n");
  AssertFatal(cc->mib!=NULL,"cc->mib is null\n");
Cedric Roux's avatar
Cedric Roux committed
129 130 131
  AssertFatal((cc->mib->message.phich_Config.phich_Resource>=0) &&
              (cc->mib->message.phich_Config.phich_Resource<4),
              "phich_Resource %d not in 0..3\n",(int)cc->mib->message.phich_Config.phich_Resource);
132 133 134 135

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

Cedric Roux's avatar
Cedric Roux committed
136 137
uint16_t mac_computeRIV(uint16_t N_RB_DL,uint16_t RBstart,uint16_t Lcrbs)
{
138 139 140 141 142 143 144 145 146 147
  uint16_t RIV;

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

  return(RIV);
}

Cedric Roux's avatar
Cedric Roux committed
148 149
uint8_t getQm(uint8_t mcs)
{
150 151 152 153 154
  if (mcs<10) return(2);
  else if (mcs<17) return(4);
  else return (6);
}

155
void get_Msg3alloc(COMMON_channels_t *cc,
156

Cedric Roux's avatar
Cedric Roux committed
157 158 159 160
                   sub_frame_t current_subframe,
                   frame_t current_frame,
                   frame_t *frame,
                   sub_frame_t *subframe)
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222
{
  // Fill in other TDD Configuration!!!!

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

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

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

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

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

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

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

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

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

      case 9:
        *subframe = 2;
        *frame = (current_frame+2) & 1023;
        break;
      }
    } else if (cc->tdd_Config->subframeAssignment == 4) {
Cedric Roux's avatar
Cedric Roux committed
223
      switch (current_subframe) {
224

Cedric Roux's avatar
Cedric Roux committed
225 226 227 228 229 230 231
      case 0:
      case 4:
      case 5:
      case 6:
        *subframe = 2;
        *frame = (current_frame+1) & 1023;
        break;
232

Cedric Roux's avatar
Cedric Roux committed
233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 260 261 262
      case 7:
        *subframe = 3;
        *frame = (current_frame+1) & 1023;
        break;

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

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

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

266 267


268
void get_Msg3allocret(COMMON_channels_t *cc,
Cedric Roux's avatar
Cedric Roux committed
269 270 271 272
                      sub_frame_t current_subframe,
                      frame_t current_frame,
                      frame_t *frame,
                      sub_frame_t *subframe)
273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
{
  if (cc->tdd_Config == NULL) { //FDD
    /* always retransmit in n+8 */
    *subframe = current_subframe + 8;

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

307
uint8_t subframe2harqpid(COMMON_channels_t *cc,frame_t frame,sub_frame_t subframe)
308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333
{
  uint8_t ret = 255;

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

  if (cc->tdd_Config == NULL) { // FDD
    ret = (((frame<<1)+subframe)&7);
  } else {
    switch (cc->tdd_Config->subframeAssignment) {
    case 1:
      if ((subframe==2) ||
          (subframe==3) ||
          (subframe==7) ||
          (subframe==8))
        switch (subframe) {
        case 2:
        case 3:
          ret = (subframe-2);
          break;

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

        default:
Cedric Roux's avatar
Cedric Roux committed
334
          AssertFatal(1==0,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
335 336 337 338 339 340 341
          break;
        }

      break;

    case 2:
      AssertFatal((subframe==2) || (subframe==7),
Cedric Roux's avatar
Cedric Roux committed
342 343
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);

344 345 346 347
      ret = (subframe/7);
      break;

    case 3:
Cedric Roux's avatar
Cedric Roux committed
348 349
      AssertFatal((subframe>1) && (subframe<5),
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
350 351 352 353 354
      ret = (subframe-2);
      break;

    case 4:
      AssertFatal((subframe>1) && (subframe<4),
Cedric Roux's avatar
Cedric Roux committed
355
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
356 357 358 359 360
      ret = (subframe-2);
      break;

    case 5:
      AssertFatal(subframe==2,
Cedric Roux's avatar
Cedric Roux committed
361
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframe,(int)cc->tdd_Config->subframeAssignment);
362 363 364 365 366 367 368 369 370 371 372
      ret = (subframe-2);
      break;

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

uint8_t get_Msg3harqpid(COMMON_channels_t *cc,
Cedric Roux's avatar
Cedric Roux committed
373 374
                        frame_t frame,
                        sub_frame_t current_subframe)
375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453
{
  uint8_t ul_subframe=0;
  uint32_t ul_frame=0;

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

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

      }

      break;

    case 3:
      switch (current_subframe) {
      case 0:
      case 5:
      case 6:
        ul_subframe = 2;
        break;

      case 7:
        ul_subframe = 3;
        break;

      case 8:
        ul_subframe = 4;
        break;

      case 9:
        ul_subframe = 2;
        break;
      }

      break;

    case 4:
      switch (current_subframe) {
      case 0:
      case 5:
      case 6:
      case 8:
      case 9:
        ul_subframe = 2;
        break;

      case 7:
        ul_subframe = 3;
        break;
      }

      break;

    case 5:
      ul_subframe =2;
      break;

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

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

454 455 456 457 458 459 460 461 462
uint32_t pdcchalloc2ulframe(COMMON_channels_t *ccP,uint32_t frame, uint8_t n)
{
  uint32_t ul_frame;

  if ((ccP->tdd_Config) &&
      (ccP->tdd_Config->subframeAssignment == 1) &&
      ((n==1)||(n==6))) // tdd_config 0,1 SF 1,5
    ul_frame = (frame + (n==1 ? 0 : 1));
  else if ((ccP->tdd_Config) &&
Cedric Roux's avatar
Cedric Roux committed
463 464
           (ccP->tdd_Config->subframeAssignment == 6) &&
           ((n==0)||(n==1)||(n==5)||(n==6)))
465 466
    ul_frame = (frame + (n>=5 ? 1 : 0));
  else if ((ccP->tdd_Config) &&
Cedric Roux's avatar
Cedric Roux committed
467
           (ccP->tdd_Config->subframeAssignment == 6) &&
468 469 470 471 472 473 474 475 476
           (n==9)) // tdd_config 6 SF 9
    ul_frame = (frame+1);
  else
    ul_frame = (frame+(n>=6 ? 1 : 0));

  LOG_D(PHY, "frame %d subframe %d: PUSCH frame = %d\n", frame, n, ul_frame);
  return ul_frame;
}

Cedric Roux's avatar
Cedric Roux committed
477 478
uint8_t pdcchalloc2ulsubframe(COMMON_channels_t *ccP,uint8_t n)
{
479 480 481 482 483 484 485
  uint8_t ul_subframe;

  if ((ccP->tdd_Config) &&
      (ccP->tdd_Config->subframeAssignment == 1) &&
      ((n==1)||(n==6))) // tdd_config 0,1 SF 1,5
    ul_subframe = ((n+6)%10);
  else if ((ccP->tdd_Config) &&
Cedric Roux's avatar
Cedric Roux committed
486
           (ccP->tdd_Config->subframeAssignment == 6) &&
487 488 489
           ((n==0)||(n==1)||(n==5)||(n==6)))
    ul_subframe = ((n+7)%10);
  else if ((ccP->tdd_Config) &&
Cedric Roux's avatar
Cedric Roux committed
490
           (ccP->tdd_Config->subframeAssignment == 6) &&
491 492 493 494 495 496 497 498 499
           (n==9)) // tdd_config 6 SF 9
    ul_subframe = ((n+5)%10);
  else
    ul_subframe = ((n+4)%10);

  LOG_D(PHY, "subframe %d: PUSCH subframe = %d\n", n, ul_subframe);
  return ul_subframe;
}

500
int is_UL_sf(COMMON_channels_t *ccP,sub_frame_t subframeP)
501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543
{
  // if FDD return dummy value
  if (ccP->tdd_Config == NULL)
    return(0);

  switch (ccP->tdd_Config->subframeAssignment) {
  case 1:
    switch (subframeP) {
    case 0:
    case 4:
    case 5:
    case 9:
      return(0);
      break;

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

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

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

  case 4:
    if  ((subframeP<=1) || (subframeP>=4))
      return(0);
    else if ((subframeP>1) && (subframeP < 4))
      return(1);
    else AssertFatal(1==0,"Unknown subframe number\n");
    break;
Cedric Roux's avatar
Cedric Roux committed
544

545 546 547 548 549 550 551 552 553 554
  case 5:
    if  ((subframeP<=1) || (subframeP>=3))
      return(0);
    else if ((subframeP>1) && (subframeP < 3))
      return(1);
    else AssertFatal(1==0,"Unknown subframe number\n");
    break;

  default:
    AssertFatal(1==0,"subframe %d Unsupported TDD configuration %d\n",
Cedric Roux's avatar
Cedric Roux committed
555
                subframeP,(int)ccP->tdd_Config->subframeAssignment);
556 557 558 559
    break;
  }
}

Cedric Roux's avatar
Cedric Roux committed
560 561
uint16_t get_pucch1_absSF(COMMON_channels_t *cc,uint16_t dlsch_absSF)
{
562
  uint16_t sf,f,nextf;
Cedric Roux's avatar
Cedric Roux committed
563

564 565 566 567 568 569 570 571 572 573 574 575 576 577 578 579 580 581 582 583 584 585 586 587 588
  if (cc->tdd_Config==NULL) { //FDD n+4
    return((dlsch_absSF + 4)%10240);
  }
  else {
    sf    = dlsch_absSF%10;
    f     = dlsch_absSF/10;
    nextf = (f+1)&1023;

    switch (cc->tdd_Config->subframeAssignment) {
    case 0:
      AssertFatal(1==0,"SFA 0 to be filled in now, :-)\n");
      break;
    case 1:
      if      ((sf==5) || (sf==6)) return((10*nextf) + 2);                                        // ACK/NAK in SF 2 next frame
      else if (sf==9)              return((10*nextf) + 3);                                        // ACK/NAK in SF 3 next frame
      else if ((sf==0) || (sf==1)) return((10*f) + 2);                                            // ACK/NAK in SF 7 same frame
      else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 3\n",sf);
      break;
    case 2:
      if      ((sf==4) || (sf==5) || (sf==6) || (sf==8)) return((10*nextf) + 2);                  // ACK/NAK in SF 2 next frame
      else if (sf==9)                                    return((10*nextf) + 7);                  // ACK/NAK in SF 7 next frame
      else if ((sf==0) || (sf==1) || (sf==3))            return((10*f) + 7);                      // ACK/NAK in SF 7 same frame
      else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 3\n",sf);
      break;
    case 3:
Cedric Roux's avatar
Cedric Roux committed
589 590 591
      if      ((sf==5) || (sf==6) || (sf==7) || (sf==8) || (sf==9)) return((10*nextf) + (sf>>1)); // ACK/NAK in 2,3,4 resp. next frame
      else if (sf==1)                                               return((10*nextf) + 2);       // ACK/NAK in 2 next frame
      else if (sf==0)                                               return((10*f) + 4);           // ACK/NAK in 4 same frame
592 593 594 595 596 597 598 599 600
      else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 3\n",sf);
      break;
    case 4:
      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
      else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 4\n",sf);
      break;
    case 5:
      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
Cedric Roux's avatar
Cedric Roux committed
601 602
      else if (sf==9)                                                                                return(((10*(1+nextf)) + 2)%10240); // ACK/NAK in SF 2 next frame
      else AssertFatal(1==0,"Impossible dlsch subframe %d for TDD configuration 5\n",sf);
603 604 605 606 607 608 609 610 611 612 613 614
      break;
    case 6:
      AssertFatal(1==0,"SFA 6 To be filled in now, :-)\n");
      break;
    default:
      AssertFatal(1==0,"Illegal TDD subframe Assigment %d\n",(int)cc->tdd_Config->subframeAssignment);
      break;
    }
  }
  AssertFatal(1==0,"Shouldn't get here\n");
}

Cedric Roux's avatar
Cedric Roux committed
615 616
void get_srs_pos(COMMON_channels_t *cc,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset)
{
617 618
  if(cc->tdd_Config) { // TDD
    AssertFatal(isrs>=10,"2 ms SRS periodicity not supported");
Cedric Roux's avatar
Cedric Roux committed
619

620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 637 638 639 640 641 642 643 644 645 646 647
    if ((isrs>9)&&(isrs<15)) {
      *psrsPeriodicity=5;
      *psrsOffset=isrs-10;
    }
    if ((isrs>14)&&(isrs<25)) {
      *psrsPeriodicity=10;
      *psrsOffset=isrs-15;
    }
    if ((isrs>24)&&(isrs<45)) {
      *psrsPeriodicity=20;
      *psrsOffset=isrs-25;
    }
    if ((isrs>44)&&(isrs<85)) {
      *psrsPeriodicity=40;
      *psrsOffset=isrs-45;
    }
    if ((isrs>84)&&(isrs<165)) {
      *psrsPeriodicity=80;
      *psrsOffset=isrs-85;
    }
    if ((isrs>164)&&(isrs<325)) {
      *psrsPeriodicity=160;
      *psrsOffset=isrs-165;
    }
    if ((isrs>324)&&(isrs<645)) {
      *psrsPeriodicity=320;
      *psrsOffset=isrs-325;
    }
Cedric Roux's avatar
Cedric Roux committed
648

649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687
    AssertFatal(isrs<=644,"Isrs out of range %d>644\n",isrs);
  } // TDD
  else { // FDD
    if (isrs<2) {
      *psrsPeriodicity=2;
      *psrsOffset=isrs;
    }
    if ((isrs>1)&&(isrs<7)) {
      *psrsPeriodicity=5;
      *psrsOffset=isrs-2;
    }
    if ((isrs>6)&&(isrs<17)) {
      *psrsPeriodicity=10;
      *psrsOffset=isrs-7;
    }
    if ((isrs>16)&&(isrs<37)) {
      *psrsPeriodicity=20;
      *psrsOffset=isrs-17;
    }
    if ((isrs>36)&&(isrs<77)) {
      *psrsPeriodicity=40;
      *psrsOffset=isrs-37;
    }
    if ((isrs>76)&&(isrs<157)) {
      *psrsPeriodicity=80;
      *psrsOffset=isrs-77;
    }
    if ((isrs>156)&&(isrs<317)) {
      *psrsPeriodicity=160;
      *psrsOffset=isrs-157;
    }
    if ((isrs>316)&&(isrs<637)) {
      *psrsPeriodicity=320;
      *psrsOffset=isrs-317;
    }
    AssertFatal(isrs<=636,"Isrs out of range %d>636\n",isrs);
  }
}

Cedric Roux's avatar
Cedric Roux committed
688 689
void get_csi_params(COMMON_channels_t *cc,struct CQI_ReportPeriodic *cqi_ReportPeriodic,uint16_t *Npd,uint16_t *N_OFFSET_CQI,int *H)
{
690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718
  uint16_t cqi_PMI_ConfigIndex = cqi_ReportPeriodic->choice.setup.cqi_pmi_ConfigIndex;
  uint8_t Jtab[6] = {0,2,2,3,4,4};

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

  if (cc->tdd_Config==NULL) { //FDD
    if (cqi_PMI_ConfigIndex <= 1) {        // 2 ms CQI_PMI period
      *Npd = 2;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex;
    } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
      *Npd = 5;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex-2;
    } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
      *Npd = 10;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex-7;
    } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
      *Npd = 20;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex-17;
    } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
      *Npd = 40;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex-37;
    } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
      *Npd = 80;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex-77;
    } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
      *Npd = 160;
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex-157;
    }
    else if (cqi_PMI_ConfigIndex > 317) {
Cedric Roux's avatar
Cedric Roux committed
719

720
      if (cqi_PMI_ConfigIndex <= 349) { // 32 ms CQI_PMI period
Cedric Roux's avatar
Cedric Roux committed
721
        *Npd = 32;
722 723 724
      *N_OFFSET_CQI = cqi_PMI_ConfigIndex-318;
      }
      else if (cqi_PMI_ConfigIndex <= 413) { // 64 ms CQI_PMI period
Cedric Roux's avatar
Cedric Roux committed
725 726
        *Npd = 64;
        *N_OFFSET_CQI = cqi_PMI_ConfigIndex-350;
727 728
      }
      else if (cqi_PMI_ConfigIndex <= 541) { // 128 ms CQI_PMI period
Cedric Roux's avatar
Cedric Roux committed
729 730 731
        *Npd = 128;
        *N_OFFSET_CQI = cqi_PMI_ConfigIndex-414;
      }
732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765
    }
  }
  else { // TDD
   if (cqi_PMI_ConfigIndex == 0) {        // all UL subframes
     *Npd = 1;
     *N_OFFSET_CQI = 0;
   } else if (cqi_PMI_ConfigIndex <= 6) { // 5 ms CQI_PMI period
     *Npd = 5;
     *N_OFFSET_CQI = cqi_PMI_ConfigIndex-1;
   } else if (cqi_PMI_ConfigIndex <=16) { // 10ms CQI_PMI period
     *Npd = 10;
     *N_OFFSET_CQI = cqi_PMI_ConfigIndex-6;
   } else if (cqi_PMI_ConfigIndex <= 36) { // 20 ms CQI_PMI period
     *Npd = 20;
     *N_OFFSET_CQI = cqi_PMI_ConfigIndex-16;
   } else if (cqi_PMI_ConfigIndex <= 76) { // 40 ms CQI_PMI period
     *Npd = 40;
     *N_OFFSET_CQI = cqi_PMI_ConfigIndex-36;
   } else if (cqi_PMI_ConfigIndex <= 156) { // 80 ms CQI_PMI period
     *Npd = 80;
     *N_OFFSET_CQI = cqi_PMI_ConfigIndex-76;
   } else if (cqi_PMI_ConfigIndex <= 316) { // 160 ms CQI_PMI period
     *Npd = 160;
     *N_OFFSET_CQI = cqi_PMI_ConfigIndex-156;
   }
  }

  // get H
  if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == 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
    *H=1;
}

Cedric Roux's avatar
Cedric Roux committed
766 767
uint8_t get_dl_cqi_pmi_size_pusch(COMMON_channels_t *cc,uint8_t tmode,uint8_t ri, CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic)
{
768
  int Ntab[6]       = {0,4,7,9,10,13};
769
  int N             = Ntab[cc->mib->message.dl_Bandwidth];
770
  int Ltab_uesel[6] = {0,6,9,13,15,18};
771
  int L             = Ltab_uesel[cc->mib->message.dl_Bandwidth];
772 773 774 775 776 777 778 779 780 781

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

  switch (*cqi_ReportModeAperiodic) {
  case CQI_ReportModeAperiodic_rm12:
    AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm12\n",tmode);
    AssertFatal(cc->p_eNB<=4,"only up to 4 antenna ports supported here\n");
    if (ri==1 && cc->p_eNB==2) return(4+(N<<1));
    else if (ri==2 && cc->p_eNB==2) return(8+N);
    else if (ri==1 && cc->p_eNB==4) return(4+(N<<2));
Cedric Roux's avatar
Cedric Roux committed
782
    else if (ri>1  && cc->p_eNB==4) return(8+(N<<2));
783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827 828 829
    break;
  case CQI_ReportModeAperiodic_rm20:
    // Table 5.2.2.6.3-1 (36.212)
    AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm20\n",tmode);
    AssertFatal(tmode!=9 && tmode!=10,"TM9/10 will be handled later for CQI_ReportModeAperiodic_rm20\n");
    return(4+2+L);
    break;
  case CQI_ReportModeAperiodic_rm22:
    // Table 5.2.2.6.3-2 (36.212)
    AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm22\n",tmode);
    AssertFatal(tmode!=9 && tmode!=10,"TM9/10 will be handled later for CQI_ReportModeAperiodic_rm22\n");
    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 CQI_ReportModeAperiodic_rm30:
    // Table 5.2.2.6.2-1 (36.212)
    AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm30\n",tmode);
    AssertFatal(tmode!=8 && tmode!=9 && tmode!=10,"TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm30\n");
    return(4+(N<<1));
    break;
  case CQI_ReportModeAperiodic_rm31:
    // Table 5.2.2.6.2-2 (36.212)
    AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm31\n",tmode);
    AssertFatal(tmode!=8 && tmode!=9 && tmode!=10,"TM8/9/10 will be handled later for CQI_ReportModeAperiodic_rm31\n");
    if (ri==1 && cc->p_eNB==2) return(4+(N<<1)+0+0+2);
    else if (ri==2 && cc->p_eNB==2) return(4+(N<<1)+4+(N<<1)+1);
    else if (ri==1 && cc->p_eNB==4) return(4+(N<<1)+0+0+4);
    else if (ri>=2 && cc->p_eNB==4) return(4+(N<<1)+4+(N<<1)+4);
    break;
  case CQI_ReportModeAperiodic_rm32_v1250:
    AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm32\n",tmode);
    AssertFatal(1==0,"CQI_ReportModeAperiodic_rm32_v1250 not supported yet\n");
    break;
  case CQI_ReportModeAperiodic_rm10_v1310:
    // Table 5.2.2.6.1-1F/G (36.212)
    if (ri==1) return(4); // F
    else return(7); // G
    break;
  case CQI_ReportModeAperiodic_rm11_v1310:
    // Table 5.2.2.6.1-1H (36.212)
    AssertFatal(tmode==4 || tmode==6 || tmode==8 || tmode==9 || tmode==10,"Illegal TM (%d) for CQI_ReportModeAperiodic_rm11\n",tmode);
    AssertFatal(cc->p_eNB<=4,"only up to 4 antenna ports supported here\n");
    if (ri==1 && cc->p_eNB==2) return(4+0+2);
    else if (ri==2 && cc->p_eNB==2) return(4+4+1);
    else if (ri==1 && cc->p_eNB==4) return(4+0+4);
Cedric Roux's avatar
Cedric Roux committed
830
    else if (ri>1  && cc->p_eNB==4) return(4+4+4);
831 832 833

    break;
  }
834 835
  AssertFatal(1==0,"Shouldn't get here\n");
  return(0);
836 837
}

Cedric Roux's avatar
Cedric Roux committed
838 839
uint8_t get_rel8_dl_cqi_pmi_size(UE_sched_ctrl *sched_ctl,int CC_idP,COMMON_channels_t *cc,uint8_t tmode, struct CQI_ReportPeriodic *cqi_ReportPeriodic)
{
840 841 842 843 844 845 846 847
  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];

  AssertFatal(cqi_ReportPeriodic != NULL,"cqi_ReportPeriodic is null!\n");
  AssertFatal(cqi_ReportPeriodic->present != CQI_ReportPeriodic_PR_NOTHING,
Cedric Roux's avatar
Cedric Roux committed
848
              "cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_NOTHING!\n");
849
  AssertFatal(cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present != CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING,
Cedric Roux's avatar
Cedric Roux committed
850
              "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n");
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875 876

  switch(tmode) {
  case 1:
  case 2:
  case 5:
  case 6:
  case 7:
    no_pmi=1;
    break;
  default:
    no_pmi=0;
  }

  if ((cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI) ||
      (sched_ctl->feedback_cnt[CC_idP] == 0)) {
    // send wideband report every opportunity if wideband reporting mode is selected, else every H opportunities
    if (no_pmi == 1)
      return(4);
    else if ((cc->p_eNB==2) && (ri==1)) return(6);
    else if ((cc->p_eNB==2) && (ri==2)) return(8);
    else if ((cc->p_eNB==4) && (ri==1)) return(8);
    else if ((cc->p_eNB==4) && (ri==2)) return(11);
    else AssertFatal(1==0,"illegal combination p %d, ri %d, no_pmi %d\n",cc->p_eNB,ri,no_pmi);
  }
  else if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_subbandCQI) {
    if ((no_pmi == 1)||ri==1) return(4+Ltab[cc->mib->message.dl_Bandwidth]);
Cedric Roux's avatar
Cedric Roux committed
877 878
    else
      return(7+Ltab[cc->mib->message.dl_Bandwidth]);
879 880 881 882 883
  }
  AssertFatal(1==0,"Shouldn't get here : cqi_ReportPeriodic->present %d\n",cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present);
}

void fill_nfapi_dl_dci_1A(nfapi_dl_config_request_pdu_t   *dl_config_pdu,
Cedric Roux's avatar
Cedric Roux committed
884 885 886 887 888 889 890 891 892 893 894
                          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,
                          uint8_t vrb_flag)
{
895
  memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
Cedric Roux's avatar
Cedric Roux committed
896
  dl_config_pdu->pdu_type                                                          = NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE;
897 898 899 900 901 902 903 904 905 906 907 908 909 910 911
  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.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;
  dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.transmission_power                     = 6000; // equal to RS power
  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; // no 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;
}

Cedric Roux's avatar
Cedric Roux committed
912 913
void program_dlsch_acknak(module_id_t module_idP, int CC_idP,int UE_idP, frame_t frameP, sub_frame_t subframeP,uint8_t cce_idx)
{
914 915 916 917 918 919 920 921 922 923
  eNB_MAC_INST                   *eNB      = RC.mac[module_idP];
  COMMON_channels_t              *cc       = eNB->common_channels;
  UE_list_t                      *UE_list  = &eNB->UE_list;
  rnti_t                         rnti      = UE_RNTI(module_idP,UE_idP);
  nfapi_ul_config_request_body_t *ul_req;
  nfapi_ul_config_request_pdu_t  *ul_config_pdu;

  int use_simultaneous_pucch_pusch=0;
  nfapi_ul_config_ulsch_harq_information *ulsch_harq_information = NULL;
  nfapi_ul_config_harq_information *harq_information = NULL;
Cedric Roux's avatar
Cedric Roux committed
924

925
#if defined(Rel10) || defined(Rel14)
Cedric Roux's avatar
Cedric Roux committed
926

927 928
  if ((UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2) &&
      (UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020) &&
Cedric Roux's avatar
Cedric Roux committed
929
      (UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020->simultaneousPUCCH_PUSCH_r10) &&
930 931 932
      (*UE_list->UE_template[CC_idP][UE_idP].physicalConfigDedicated->ext2->pucch_ConfigDedicated_v1020->simultaneousPUCCH_PUSCH_r10 ==
          PUCCH_ConfigDedicated_v1020__simultaneousPUCCH_PUSCH_r10_true))
    use_simultaneous_pucch_pusch=1;
933
#endif
Cedric Roux's avatar
Cedric Roux committed
934

935 936 937
  // 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
  int16_t ul_absSF = get_pucch1_absSF(&cc[CC_idP],subframeP+(10*frameP));
Cedric Roux's avatar
Cedric Roux committed
938

939
  if ((ul_config_pdu = has_ul_grant(module_idP,CC_idP,
Cedric Roux's avatar
Cedric Roux committed
940 941
                                    ul_absSF,
                                    rnti)) == NULL) {
942 943
    // no UL grant so
    // Program ACK/NAK alone Format 1a/b or 3
Cedric Roux's avatar
Cedric Roux committed
944

945
    ul_req        = &RC.mac[module_idP]->UL_req_tmp[CC_idP][ul_absSF%10].ul_config_request_body;
Cedric Roux's avatar
Cedric Roux committed
946
    ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
947 948
    // Do PUCCH
    fill_nfapi_uci_acknak(module_idP,
Cedric Roux's avatar
Cedric Roux committed
949 950 951 952
                          CC_idP,
                          rnti,
                          (frameP*10)+subframeP,
                          cce_idx);
953
  }
954 955 956 957
  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)
     */
958
    switch(ul_config_pdu->pdu_type) {
959 960 961

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

962 963
    case NFAPI_UL_CONFIG_ULSCH_PDU_TYPE:
      if (use_simultaneous_pucch_pusch==1) {
Cedric Roux's avatar
Cedric Roux committed
964 965 966 967
        // Convert it to an NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE
        harq_information = &ul_config_pdu->ulsch_uci_harq_pdu.harq_information;
        ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE;
        LOG_D(MAC,"Frame %d, Subframe %d: Switched UCI HARQ to ULSCH UCI HARQ\n",frameP,subframeP);
968 969
      }
      else {
Cedric Roux's avatar
Cedric Roux committed
970 971 972 973 974 975 976
        // Convert it to an NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE
        ulsch_harq_information = &ul_config_pdu->ulsch_harq_pdu.harq_information;
        ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE;
        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",frameP,subframeP);
977 978
      }
      break;
979 980 981 982 983 984 985 986 987 988 989
    case NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE:
      AssertFatal(use_simultaneous_pucch_pusch == 1,
                  "Cannot be NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE, simultaneous_pucch_pusch is active");
      break;
    case NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE:
      AssertFatal(use_simultaneous_pucch_pusch == 0,
                  "Cannot be NFAPI_UL_CONFIG_ULSCH_UCI_PDU_TYPE, simultaneous_pucch_pusch is inactive\n");
      break;

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

990
    case NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE:
991 992 993 994 995 996 997 998 999 1000 1001 1002 1003
      // Convert it to an NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE
      ulsch_harq_information = &ul_config_pdu->ulsch_cqi_harq_ri_pdu.harq_information;
      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.
       */
      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
      break;
1004
    case NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE:
1005 1006 1007
      AssertFatal(use_simultaneous_pucch_pusch == 0,
                  "Cannot be NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE, simultaneous_pucch_pusch is active\n");
      break;
Cedric Roux's avatar
Cedric Roux committed
1008

1009
    /* [ulsch + cqi on pucch] to [ulsch + cqi on pucch + harq on pucch] */
Cedric Roux's avatar
Cedric Roux committed
1010

1011 1012 1013 1014 1015 1016 1017 1018
    case NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE:
      // convert it to an NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE
      harq_information = &ul_config_pdu->ulsch_csi_uci_harq_pdu.harq_information;
      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:
      AssertFatal(use_simultaneous_pucch_pusch == 1,
                  "Cannot be NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE, simultaneous_pucch_pusch is inactive\n");
1019
      break;
Cedric Roux's avatar
Cedric Roux committed
1020

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

1023
    case NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE:
1024
      // convert to NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE
1025 1026 1027
      ul_config_pdu->pdu_type = NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE;
      harq_information = &ul_config_pdu->uci_sr_harq_pdu.harq_information;
      break;
1028 1029 1030 1031 1032 1033
    case NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE:
      /* nothing to do */
      break;

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

1034
    case NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE:
1035
      // convert to NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE
1036 1037 1038
      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;
1039 1040 1041 1042 1043
    case NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE:
      /* nothing to do */
      break;

    /* [cqi + sr] to [cqr + sr + harq] */
Cedric Roux's avatar
Cedric Roux committed
1044

1045
    case NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE:
1046
      // convert to NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE
1047 1048 1049
      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;
1050 1051 1052
    case NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE:
      /* nothing to do */
      break;
1053 1054
    }
  }
Cedric Roux's avatar
Cedric Roux committed
1055

1056
  if (ulsch_harq_information) fill_nfapi_ulsch_harq_information(module_idP,CC_idP,
Cedric Roux's avatar
Cedric Roux committed
1057 1058 1059
                                                                rnti,
                                                                ulsch_harq_information);

1060
  if (harq_information) fill_nfapi_harq_information(module_idP,CC_idP,
Cedric Roux's avatar
Cedric Roux committed
1061 1062 1063 1064
                                                    rnti,
                                                    (frameP*10)+subframeP,
                                                    harq_information,
                                                    cce_idx);
1065 1066
}

Cedric Roux's avatar
Cedric Roux committed
1067 1068
uint8_t get_V_UL_DAI(module_id_t module_idP,int CC_idP,uint16_t rntiP)
{
1069 1070 1071 1072 1073
  nfapi_hi_dci0_request_body_t        *HI_DCI0_req         = &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body;
  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++) {
    if ((hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
1074 1075
        (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti == rntiP))
        return(hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.dl_assignment_index);
1076 1077 1078 1079
  }
  return(4); // this is rule from Section 7.3 in 36.213
}

Cedric Roux's avatar
Cedric Roux committed
1080 1081 1082 1083 1084
void fill_nfapi_ulsch_harq_information(module_id_t module_idP,
                                       int CC_idP,
                                       uint16_t rntiP,
                                       nfapi_ul_config_ulsch_harq_information *harq_information)
{
1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109 1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120 1121 1122 1123 1124 1125
  eNB_MAC_INST                   *eNB      = RC.mac[module_idP];
  COMMON_channels_t              *cc       = &eNB->common_channels[CC_idP];
  UE_list_t                      *UE_list  = &eNB->UE_list;

  int UE_id                                = find_UE_id(module_idP,rntiP);

  PUSCH_ConfigDedicated_t              *puschConfigDedicated;
  //  PUSCH_ConfigDedicated_v1020_t        *puschConfigDedicated_v1020;
  //  PUSCH_ConfigDedicated_v1130_t        *puschConfigDedicated_v1130;
  //  PUSCH_ConfigDedicated_v1250_t        *puschConfigDedicated_v1250;

  AssertFatal(UE_id>=0,"UE_id cannot be found, impossible\n");
  AssertFatal(UE_list!=NULL,"UE_list is null\n");
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated for rnti %x is null\n",rntiP);
  AssertFatal((puschConfigDedicated = (PUSCH_ConfigDedicated_t *)UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pusch_ConfigDedicated)!=NULL,"physicalConfigDedicated->puschConfigDedicated for rnti %x is null\n",rntiP);
#if defined(Rel14) || defined(Rel14)
  /*  if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext2) puschConfigDedicated_v1020 =  UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext2->pusch_ConfigDedicated_v1020;
#endif
#ifdef Rel14
  if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext4) puschConfigDedicated_v1130 =  UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext4->pusch_ConfigDedicated_v1130;
  if (UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext5) puschConfigDedicated_v1250 =  UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->ext5->pusch_ConfigDedicated_v1250;
  */
#endif
  harq_information->harq_information_rel10.delta_offset_harq = puschConfigDedicated->betaOffset_ACK_Index;
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL,"pucch_ConfigDedicated is null!\n");
  if ((UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode!=NULL)&&
      (*UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode==PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing))
      harq_information->harq_information_rel10.ack_nack_mode = 1;  // multiplexing
  else
      harq_information->harq_information_rel10.ack_nack_mode = 0;  // bundling

  switch(get_tmode(module_idP,CC_idP,UE_id)) {
  case 1:
  case 2:
  case 5:
  case 6:
  case 7:
    if (cc->tdd_Config==NULL) // FDD
      harq_information->harq_information_rel10.harq_size = 1;
    else {
      if (harq_information->harq_information_rel10.ack_nack_mode == 1)
Cedric Roux's avatar
Cedric Roux committed
1126
        harq_information->harq_information_rel10.harq_size = get_V_UL_DAI(module_idP,CC_idP,rntiP);
1127
      else
Cedric Roux's avatar
Cedric Roux committed
1128
        harq_information->harq_information_rel10.harq_size = 1;
1129 1130
    }
    break;
Cedric Roux's avatar
Cedric Roux committed
1131
  default: // for any other TM we need 2 bits harq
1132
    if (cc->tdd_Config==NULL) {
Cedric Roux's avatar
Cedric Roux committed
1133
        harq_information->harq_information_rel10.harq_size     = 2;
1134 1135 1136
    }
    else {
      if (harq_information->harq_information_rel10.ack_nack_mode == 1)
Cedric Roux's avatar
Cedric Roux committed
1137
        harq_information->harq_information_rel10.harq_size     = get_V_UL_DAI(module_idP,CC_idP,rntiP);
1138
      else
Cedric Roux's avatar
Cedric Roux committed
1139
        harq_information->harq_information_rel10.harq_size     = 2;
1140 1141 1142 1143
    }
    break;
  } // get Tmode
}
Cedric Roux's avatar
Cedric Roux committed
1144

1145
void fill_nfapi_harq_information(module_id_t module_idP,
Cedric Roux's avatar
Cedric Roux committed
1146 1147 1148 1149 1150 1151
                                 int CC_idP,
                                 uint16_t rntiP,
                                 uint16_t absSFP,
                                 nfapi_ul_config_harq_information *harq_information,
                                 uint8_t cce_idxP)
{
1152 1153 1154 1155 1156 1157 1158 1159 1160 1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171
  eNB_MAC_INST                   *eNB      = RC.mac[module_idP];
  COMMON_channels_t              *cc       = &eNB->common_channels[CC_idP];
  UE_list_t                      *UE_list  = &eNB->UE_list;

  int UE_id                                = find_UE_id(module_idP,rntiP);

  AssertFatal(UE_id>=0,"UE_id cannot be found, impossible\n");
  AssertFatal(UE_list!=NULL,"UE_list is null\n");
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated!=NULL,"physicalConfigDedicated for rnti %x is null\n",rntiP);

  harq_information->harq_information_rel11.num_ant_ports = 1;

  switch(get_tmode(module_idP,CC_idP,UE_id)) {
  case 1:
  case 2:
  case 5:
  case 6:
  case 7:
    if (cc->tdd_Config!=NULL) {
      AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL,
Cedric Roux's avatar
Cedric Roux committed
1172
                  "pucch_ConfigDedicated is null for TDD!\n");
1173
      if ((UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode!=NULL)&&
Cedric Roux's avatar
Cedric Roux committed
1174 1175 1176
          (*UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode==PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) {
        harq_information->harq_information_rel10_tdd.harq_size     = 2;  // 2-bit ACK/NAK
        harq_information->harq_information_rel10_tdd.ack_nack_mode = 1;  // multiplexing
1177 1178
      }
      else {
Cedric Roux's avatar
Cedric Roux committed
1179 1180
        harq_information->harq_information_rel10_tdd.harq_size     = 1;  // 1-bit ACK/NAK
        harq_information->harq_information_rel10_tdd.ack_nack_mode = 0;  // bundling
1181 1182 1183 1184 1185 1186 1187 1188 1189
      }
      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;
    } else {
      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;
    }
    break;
Cedric Roux's avatar
Cedric Roux committed
1190
  default: // for any other TM we need 2 bits harq
1191 1192
    if (cc->tdd_Config!=NULL) {
      AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL,
Cedric Roux's avatar
Cedric Roux committed
1193
                  "pucch_ConfigDedicated is null for TDD!\n");
1194
      if ((UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode!=NULL)&&
Cedric Roux's avatar
Cedric Roux committed
1195 1196
          (*UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->pucch_ConfigDedicated->tdd_AckNackFeedbackMode==PUCCH_ConfigDedicated__tdd_AckNackFeedbackMode_multiplexing)) {
        harq_information->harq_information_rel10_tdd.ack_nack_mode = 1;  // multiplexing
1197 1198
      }
      else {
Cedric Roux's avatar
Cedric Roux committed
1199
        harq_information->harq_information_rel10_tdd.ack_nack_mode = 0;  // bundling
1200
      }
Cedric Roux's avatar
Cedric Roux committed
1201
      harq_information->harq_information_rel10_tdd.harq_size       = 2;
1202 1203 1204 1205 1206 1207 1208
      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;
    }
    else {
      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;
Cedric Roux's avatar
Cedric Roux committed
1209
      harq_information->harq_information_rel9_fdd.n_pucch_1_0      = cc->radioResourceConfigCommon->pucch_ConfigCommon.n1PUCCH_AN + cce_idxP;
1210 1211 1212 1213 1214 1215
    }
    break;
  } // get Tmode
}

uint16_t fill_nfapi_uci_acknak(module_id_t module_idP,
Cedric Roux's avatar
Cedric Roux committed
1216 1217 1218 1219 1220
                               int CC_idP,
                               uint16_t rntiP,
                               uint16_t absSFP,
                               uint8_t cce_idxP)
{
1221 1222
  eNB_MAC_INST                   *eNB          = RC.mac[module_idP];
  COMMON_channels_t              *cc           = &eNB->common_channels[CC_idP];
Cedric Roux's avatar
Cedric Roux committed
1223

1224 1225
  int ackNAK_absSF                             = get_pucch1_absSF(cc,absSFP);
  nfapi_ul_config_request_body_t *ul_req       = &eNB->UL_req_tmp[CC_idP][ackNAK_absSF%10].ul_config_request_body;
Cedric Roux's avatar
Cedric Roux committed
1226
  nfapi_ul_config_request_pdu_t *ul_config_pdu = &ul_req->ul_config_pdu_list[ul_req->number_of_pdus];
1227 1228

  memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t));
Cedric Roux's avatar
Cedric Roux committed
1229
  ul_config_pdu->pdu_type                                                              = NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE;
1230 1231 1232 1233 1234
  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.handle                = 0; // don't know how to use this
  ul_config_pdu->uci_harq_pdu.ue_information.ue_information_rel8.rnti                  = rntiP;

  fill_nfapi_harq_information(module_idP,CC_idP,
Cedric Roux's avatar
Cedric Roux committed
1235 1236 1237 1238
                              rntiP,
                              absSFP,
                              &ul_config_pdu->uci_harq_pdu.harq_information,
                              cce_idxP);
1239
  LOG_D(MAC,"Filled in UCI HARQ request for rnti %x SF %d.%d acknakSF %d.%d, cce_idxP %d-> n1_pucch %d\n",rntiP,
Cedric Roux's avatar
Cedric Roux committed
1240
        absSFP/10,absSFP%10,ackNAK_absSF/10,ackNAK_absSF%10,cce_idxP,ul_config_pdu->uci_harq_pdu.harq_information.harq_information_rel9_fdd.n_pucch_1_0);
1241 1242 1243 1244 1245 1246

  ul_req->number_of_pdus++;

  return(((ackNAK_absSF/10)<<4) + (ackNAK_absSF%10));
}

Cedric Roux's avatar
Cedric Roux committed
1247 1248 1249 1250 1251 1252 1253 1254 1255 1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273
void fill_nfapi_dlsch_config(eNB_MAC_INST *eNB,
                             nfapi_dl_config_request_body_t *dl_req,
                             uint16_t length,
                             uint16_t pdu_index,
                             uint16_t rnti,
                             uint8_t resource_allocation_type,
                             uint8_t virtual_resource_block_assignment_flag,
                             uint16_t resource_block_coding,
                             uint8_t modulation,
                             uint8_t redundancy_version,
                             uint8_t transport_blocks,
                             uint8_t transport_block_to_codeword_swap_flag,
                             uint8_t transmission_scheme,
                             uint8_t number_of_layers,
                             uint8_t number_of_subbands,
                             //                             uint8_t codebook_index,
                             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,
                             uint8_t num_bf_vector
                             )
{
  nfapi_dl_config_request_pdu_t   *dl_config_pdu = &dl_req->dl_config_pdu_list[dl_req->number_pdu];
1274
  memset((void*)dl_config_pdu,0,sizeof(nfapi_dl_config_request_pdu_t));
Cedric Roux's avatar
Cedric Roux committed
1275 1276

  dl_config_pdu->pdu_type                                                        = NFAPI_DL_CONFIG_DLSCH_PDU_TYPE;
1277 1278 1279 1280 1281
  dl_config_pdu->pdu_size                                                        = (uint8_t)(2+sizeof(nfapi_dl_config_dlsch_pdu));
  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;
Cedric Roux's avatar
Cedric Roux committed
1282
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.virtual_resource_block_assignment_flag = virtual_resource_block_assignment_flag;
1283
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.resource_block_coding                  = resource_block_coding;
Cedric Roux's avatar
Cedric Roux committed
1284
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.modulation                             = modulation;
1285 1286 1287 1288 1289 1290 1291 1292 1293 1294 1295 1296 1297 1298 1299 1300 1301 1302
  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;
  //  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.codebook_index                         = codebook_index;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ue_category_capacity                   = ue_category_capacity;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.pa                                     = pa;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.delta_power_offset_index               = delta_power_offset_index;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.ngap                                   = ngap;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.nprb                                   = nprb;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.transmission_mode                      = transmission_mode;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_prb_per_subband                 = num_bf_prb_per_subband;
  dl_config_pdu->dlsch_pdu.dlsch_pdu_rel8.num_bf_vector                          = num_bf_vector;
  dl_req->number_pdu++;
}

1303
uint16_t fill_nfapi_tx_req(nfapi_tx_request_body_t *tx_req_body,uint16_t absSF,uint16_t pdu_length, uint16_t pdu_index, uint8_t *pdu)
Cedric Roux's avatar
Cedric Roux committed
1304 1305
{
  nfapi_tx_request_pdu_t *TX_req        = &tx_req_body->tx_pdu_list[tx_req_body->number_of_pdus];
Raymond Knopp's avatar
Raymond Knopp committed
1306
  LOG_D(MAC,"Filling TX_req %d for pdu length %d\n",tx_req_body->number_of_pdus,pdu_length);
1307
  TX_req->pdu_length                    = pdu_length;
1308
  TX_req->pdu_index                     = pdu_index;
1309 1310 1311 1312 1313 1314 1315
  TX_req->num_segments                  = 1;
  TX_req->segments[0].segment_length    = pdu_length;
  TX_req->segments[0].segment_data      = pdu;
  tx_req_body->number_of_pdus++;

  return(((absSF/10)<<4) + (absSF%10));
}
1316 1317

void fill_nfapi_ulsch_config_request_rel8(nfapi_ul_config_request_pdu_t  *ul_config_pdu,
Cedric Roux's avatar
Cedric Roux committed
1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333 1334 1335 1336 1337 1338
                                          uint8_t                        cqi_req,
                                          COMMON_channels_t              *cc,
                                          struct 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,
                                          uint16_t                       size
                                          )
{
1339
  memset((void*)ul_config_pdu,0,sizeof(nfapi_ul_config_request_pdu_t));
1340 1341

  ul_config_pdu->pdu_type                                                        = NFAPI_UL_CONFIG_ULSCH_PDU_TYPE;
1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360
  ul_config_pdu->pdu_size                                                        = (uint8_t)(2+sizeof(nfapi_ul_config_ulsch_pdu));
  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;
  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;
  else             ul_config_pdu->ulsch_pdu.ulsch_pdu_rel8.modulation_type       = 6;
  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;

1361 1362 1363
  if (cqi_req == 1) {
    // Add CQI portion
    ul_config_pdu->pdu_type                                                           = NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE;
1364 1365 1366 1367
    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.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;
    LOG_D(MAC,"report_type %d\n",ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.report_type);
Cedric Roux's avatar
Cedric Roux committed
1368

1369 1370
    if (cc->p_eNB<=2 && (tmode==3||tmode==4||tmode==8||tmode==9||tmode==10))
      ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 1;
Cedric Roux's avatar
Cedric Roux committed
1371
    else if (cc->p_eNB<=2)
1372 1373 1374
      ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 0;
    else if (cc->p_eNB==4)
      ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size = 2;
Cedric Roux's avatar
Cedric Roux committed
1375

1376 1377 1378
    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");
Cedric Roux's avatar
Cedric Roux committed
1379

1380
    for (int ri=0;
Cedric Roux's avatar
Cedric Roux committed
1381 1382 1383 1384 1385 1386 1387 1388
         ri<(1<<ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].ri_size);
         ri++)
      ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.aperiodic_cqi_pmi_ri_report.cc[0].dl_cqi_pmi_size[ri] =
        get_dl_cqi_pmi_size_pusch(cc,
                                  tmode,
                                  1+ri,
                                  physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic);

1389
    ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.delta_offset_cqi        = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_CQI_Index;
Cedric Roux's avatar
Cedric Roux committed
1390
    ul_config_pdu->ulsch_cqi_ri_pdu.cqi_ri_information.cqi_ri_information_rel9.delta_offset_ri         = physicalConfigDedicated->pusch_ConfigDedicated->betaOffset_RI_Index;
1391 1392 1393
  }
}

1394
#ifdef Rel14
1395
void fill_nfapi_ulsch_config_request_emtc(nfapi_ul_config_request_pdu_t  *ul_config_pdu,
Cedric Roux's avatar
Cedric Roux committed
1396 1397 1398 1399 1400
                                          uint8_t ue_type,
                                          uint16_t total_number_of_repetitions,
                                          uint16_t repetition_number,
                                          uint16_t initial_transmission_sf_io)
{
1401
  // Re13 fields
Cedric Roux's avatar
Cedric Roux committed
1402

1403 1404 1405 1406 1407
  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;
}
1408

Cedric Roux's avatar
Cedric Roux committed
1409 1410
int get_numnarrowbands(long dl_Bandwidth)
{
1411 1412 1413 1414 1415 1416
  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]);
}

Cedric Roux's avatar
Cedric Roux committed
1417 1418
int get_numnarrowbandbits(long dl_Bandwidth)
{
1419 1420 1421 1422 1423 1424 1425 1426 1427 1428
  int nbbits_tab[6] = {0,1,2,3,4,4};

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

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

Cedric Roux's avatar
Cedric Roux committed
1429 1430
int mpdcch_sf_condition(eNB_MAC_INST *eNB,int CC_id, frame_t frameP,sub_frame_t subframeP,int rmax,MPDCCH_TYPES_t mpdcch_type,int UE_id)
{
1431
  struct PRACH_ConfigSIB_v1310 *ext4_prach = eNB->common_channels[CC_id].radioResourceConfigCommon_BR->ext4->prach_ConfigCommon_v1310;
1432

1433
  int T;
1434
  EPDCCH_SetConfig_r11_t *epdcch_setconfig_r11;
1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447

  switch (mpdcch_type) {
  case TYPE0:
    AssertFatal(1==0,"MPDCCH Type 0 not handled yet\n");
    break;
  case TYPE1:
    AssertFatal(1==0,"MPDCCH Type 1 not handled yet\n");
    break;
  case TYPE1A:
    AssertFatal(1==0,"MPDCCH Type 1A not handled yet\n");
    break;
  case TYPE2: // RAR
    AssertFatal(ext4_prach->mpdcch_startSF_CSS_RA_r13!=NULL,
Cedric Roux's avatar
Cedric Roux committed
1448
                "mpdcch_startSF_CSS_RA_r13 is null\n");
1449
    AssertFatal(rmax>0,"rmax is 0!\b");
1450 1451 1452 1453 1454 1455 1456 1457 1458
    if (eNB->common_channels[CC_id].tdd_Config==NULL) //FDD
      T = rmax*startSF_fdd_RA_times2[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.fdd_r13]>>1;
    else //TDD
      T = rmax*startSF_tdd_RA[ext4_prach->mpdcch_startSF_CSS_RA_r13->choice.tdd_r13];
    break;
  case TYPE2A:
    AssertFatal(1==0,"MPDCCH Type 2A not handled yet\n");
    break;
  case TYPEUESPEC:
1459
    epdcch_setconfig_r11= eNB->UE_list.UE_template[CC_id][UE_id].physicalConfigDedicated->ext4->epdcch_Config_r11->config_r11.choice.setup.setConfigToAddModList_r11->list.array[0] ;
Cedric Roux's avatar
Cedric Roux committed
1460

1461 1462
    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");
Cedric Roux's avatar
Cedric Roux committed
1463

1464 1465 1466 1467
    if (eNB->common_channels[CC_id].tdd_Config==NULL) //FDD
      T = rmax*startSF_fdd_RA_times2[epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_StartSF_UESS_r13.choice.fdd_r13]>>1;
    else //TDD
      T = rmax*startSF_tdd_RA[epdcch_setconfig_r11->ext2->mpdcch_config_r13->choice.setup.mpdcch_StartSF_UESS_r13.choice.tdd_r13];
Cedric Roux's avatar
Cedric Roux committed
1468

1469 1470 1471 1472 1473
    break;
  default:
    return(0);
  }

1474
  AssertFatal(T>0,"T is 0!\n");
1475 1476 1477 1478
  if (((10*frameP) + subframeP)%T == 0) return(1);
  else return(0);
}

Cedric Roux's avatar
Cedric Roux committed
1479 1480
int narrowband_to_first_rb(COMMON_channels_t *cc, int nb_index)
{
1481 1482 1483 1484 1485 1486 1487 1488 1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503
  switch (cc->mib->message.dl_Bandwidth) {
  case 0: // 6 PRBs, N_NB=1, i_0=0
    return(0);
    break;
  case 3: // 50 PRBs, N_NB=8, i_0=1
    return((int)(1+(6*nb_index)));
    break;
  case 5: // 100 PRBs, N_NB=16, i_0=2
    return((int)(2+(6*nb_index)));
    break;
  case 1: // 15 PRBs  N_NB=2, i_0=1
    if (nb_index>0) return(1);
    else            return(0);
    break;
  case 2: // 25 PRBs, N_NB=4, i_0=0
    if (nb_index>1) return(1+(6*nb_index));
    else            return((6*nb_index));
    break;
  case 4: // 75 PRBs, N_NB=12, i_0=1
    if (nb_index>5) return(2+(6*nb_index));
    else            return(1+(6*nb_index));
    break;
  default:
1504
    AssertFatal(1==0,"Impossible dl_Bandwidth %d\n",(int)cc->mib->message.dl_Bandwidth);
1505 1506 1507
    break;
  }
}
1508 1509
#endif

1510
//------------------------------------------------------------------------------
1511
void init_ue_sched_info(void)
1512
//------------------------------------------------------------------------------
1513
{
1514
  module_id_t i,j,k;
1515 1516

  for (i=0; i<NUMBER_OF_eNB_MAX; i++) {
Cedric Roux's avatar
Cedric Roux committed
1517
    for (k=0; k<MAX_NUM_CCs; k++) {
1518 1519 1520 1521 1522 1523 1524 1525 1526 1527
      for (j=0; j<NUMBER_OF_UE_MAX; j++) {
        // init DL
        eNB_dlsch_info[i][k][j].weight           = 0;
        eNB_dlsch_info[i][k][j].subframe         = 0;
        eNB_dlsch_info[i][k][j].serving_num      = 0;
        eNB_dlsch_info[i][k][j].status           = S_DL_NONE;
        // init UL
        eNB_ulsch_info[i][k][j].subframe         = 0;
        eNB_ulsch_info[i][k][j].serving_num      = 0;
        eNB_ulsch_info[i][k][j].status           = S_UL_NONE;
1528
      }
1529
    }
1530 1531 1532 1533 1534
  }
}



1535
//------------------------------------------------------------------------------
1536
unsigned char get_ue_weight(module_id_t module_idP, int CC_idP, int ue_idP)
1537
//------------------------------------------------------------------------------
1538
{
1539
  return(eNB_dlsch_info[module_idP][CC_idP][ue_idP].weight);
1540 1541
}

1542
//------------------------------------------------------------------------------
1543
int find_UE_id(module_id_t mod_idP, rnti_t rntiP)
1544
//------------------------------------------------------------------------------
1545
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1546
  int UE_id;
1547
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
1548

1549 1550
  for (UE_id = 0; UE_id < NUMBER_OF_UE_MAX; UE_id++) {
    if (UE_list->active[UE_id] != TRUE) continue;
Raymond Knopp's avatar
 
Raymond Knopp committed
1551 1552 1553
    if (UE_list->UE_template[UE_PCCID(mod_idP,UE_id)][UE_id].rnti==rntiP) {
      return(UE_id);
    }
1554
  }
1555

Raymond Knopp's avatar
 
Raymond Knopp committed
1556
  return(-1);
1557 1558
}

1559 1560 1561 1562 1563 1564 1565
//------------------------------------------------------------------------------
int find_RA_id(module_id_t mod_idP, int CC_idP, rnti_t rntiP)
//------------------------------------------------------------------------------
{
  int RA_id;
  AssertFatal(RC.mac[mod_idP],"RC.mac[%d] is null\n",mod_idP);

Cedric Roux's avatar
Cedric Roux committed
1566
  RA_TEMPLATE *RA_template = (RA_TEMPLATE *)&RC.mac[mod_idP]->common_channels[CC_idP].RA_template[0];
1567

1568
  for (RA_id = 0; RA_id < NB_RA_PROC_MAX; RA_id++) {
Raymond Knopp's avatar
Raymond Knopp committed
1569
    LOG_D(MAC,"Checking RA_id %d for %x : RA_active %d, wait_ack_Msg4 %d\n",
Cedric Roux's avatar
Cedric Roux committed
1570 1571 1572 1573 1574
          RA_id,rntiP,
          RA_template[RA_id].RA_active,
          RA_template[RA_id].wait_ack_Msg4);

    if (RA_template[RA_id].RA_active==TRUE &&
1575
        RA_template[RA_id].wait_ack_Msg4 == 0 &&
Cedric Roux's avatar
Cedric Roux committed
1576
        RA_template[RA_id].rnti == rntiP) return(RA_id);
1577
  }
1578 1579 1580
  return(-1);
}

1581
//------------------------------------------------------------------------------
1582
int UE_num_active_CC(UE_list_t *listP,int ue_idP)
1583
//------------------------------------------------------------------------------
1584
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1585 1586
  return(listP->numactiveCCs[ue_idP]);
}
1587

1588
//------------------------------------------------------------------------------
1589
int UE_PCCID(module_id_t mod_idP,int ue_idP)
1590
//------------------------------------------------------------------------------
1591
{
1592
  return(RC.mac[mod_idP]->UE_list.pCC_id[ue_idP]);
Raymond Knopp's avatar
 
Raymond Knopp committed
1593
}
1594

1595
//------------------------------------------------------------------------------
1596
rnti_t UE_RNTI(module_id_t mod_idP, int ue_idP)
1597
//------------------------------------------------------------------------------
1598
{
1599
  rnti_t rnti = RC.mac[mod_idP]->UE_list.UE_template[UE_PCCID(mod_idP,ue_idP)][ue_idP].rnti;
1600

1601
  if (rnti>0) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1602
    return (rnti);
1603
  }
1604

1605
  LOG_D(MAC,"[eNB %d] Couldn't find RNTI for UE %d\n",mod_idP,ue_idP);
1606 1607
  //display_backtrace();
  return(NOT_A_RNTI);
1608
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1609

1610
//------------------------------------------------------------------------------
1611
boolean_t is_UE_active(module_id_t mod_idP, int ue_idP)
1612
//------------------------------------------------------------------------------
1613
{
1614
  return(RC.mac[mod_idP]->UE_list.active[ue_idP]);
1615
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1616 1617 1618

/*
uint8_t find_active_UEs(module_id_t module_idP,int CC_id){
1619 1620 1621 1622 1623 1624 1625

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1626
      if (((rnti=eNB_mac_inst[module_idP][CC_id].UE_template[ue_mod_id].rnti) !=0)&&(eNB_mac_inst[module_idP][CC_id].UE_template[ue_mod_id].ul_active==TRUE)){
1627 1628

          if (mac_xface->get_eNB_UE_stats(module_idP,rnti) != NULL){ // check at the phy enb_ue state for this rnti
1629
      nb_active_ue++;
1630 1631
          }
          else { // this ue is removed at the phy => remove it at the mac as well
1632
      mac_remove_ue(module_idP, CC_id, ue_mod_id);
1633 1634 1635 1636 1637
          }
      }
  }
  return(nb_active_ue);
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1638
*/
1639 1640


1641 1642
// get aggregation (L) form phy for a give UE
unsigned char get_aggregation (uint8_t bw_index, uint8_t cqi, uint8_t dci_fmt)
1643
{
1644
  unsigned char aggregation=3;
Cedric Roux's avatar
Cedric Roux committed
1645

1646 1647 1648 1649 1650 1651 1652 1653
  switch (dci_fmt){
  case format0:
    aggregation = cqi2fmt0_agg[bw_index][cqi];
    break;
  case format1:
  case format1A:
  case format1B:
  case format1D:
Cedric Roux's avatar
Cedric Roux committed
1654
    aggregation = cqi2fmt1x_agg[bw_index][cqi];
1655 1656 1657 1658 1659 1660
    break;
  case format2:
  case format2A:
  case format2B:
  case format2C:
  case format2D:
Cedric Roux's avatar
Cedric Roux committed
1661
    aggregation = cqi2fmt2x_agg[bw_index][cqi];
1662 1663 1664 1665 1666 1667 1668 1669 1670 1671
    break;
  case format1C:
  case format1E_2A_M10PRB:
  case format3:
  case format3A:
  case format4:
  default:
    LOG_W(MAC,"unsupported DCI format %d\n",dci_fmt);
  }

Cedric Roux's avatar
Cedric Roux committed
1672 1673 1674
  LOG_D(MAC,"Aggregation level %d (cqi %d, bw_index %d, format %d)\n",
        1<<aggregation, cqi,bw_index,dci_fmt);

1675
  return 1<<aggregation;
1676
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1677

1678 1679
void dump_ue_list(UE_list_t *listP, int ul_flag)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1680
  int j;
1681 1682 1683

  if ( ul_flag == 0 ) {
    for (j=listP->head; j>=0; j=listP->next[j]) {
1684 1685 1686
      LOG_T(MAC,"node %d => %d\n",j,listP->next[j]);
    }
  } else {
1687
    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
1688 1689
      LOG_T(MAC,"node %d => %d\n",j,listP->next_ul[j]);
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1690 1691 1692
  }
}

1693 1694 1695 1696 1697
int add_new_ue(module_id_t mod_idP, int cc_idP, rnti_t rntiP,int harq_pidP
               #ifdef Rel14
                 ,uint8_t rach_resource_type
               #endif
               )
1698
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1699
  int UE_id;
1700
  int i, j;
1701

1702
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
1703

Raymond Knopp's avatar
 
Raymond Knopp committed
1704
  LOG_D(MAC,"[eNB %d, CC_id %d] Adding UE with rnti %x (next avail %d, num_UEs %d)\n",mod_idP,cc_idP,rntiP,UE_list->avail,UE_list->num_UEs);
1705
  dump_ue_list(UE_list,0);
Raymond Knopp's avatar
 
Raymond Knopp committed
1706

1707 1708 1709
  for (i = 0; i < NUMBER_OF_UE_MAX; i++) {
    if (UE_list->active[i] == TRUE) continue;
    UE_id = i;
Raymond Knopp's avatar
 
Raymond Knopp committed
1710 1711 1712 1713 1714 1715 1716
    UE_list->UE_template[cc_idP][UE_id].rnti       = rntiP;
    UE_list->UE_template[cc_idP][UE_id].configured = FALSE;
    UE_list->numactiveCCs[UE_id]                   = 1;
    UE_list->numactiveULCCs[UE_id]                 = 1;
    UE_list->pCC_id[UE_id]                         = cc_idP;
    UE_list->ordered_CCids[0][UE_id]               = cc_idP;
    UE_list->ordered_ULCCids[0][UE_id]             = cc_idP;
Raymond Knopp's avatar
 
Raymond Knopp committed
1717
    UE_list->num_UEs++;
Raymond Knopp's avatar
 
Raymond Knopp committed
1718
    UE_list->active[UE_id]                         = TRUE;
1719 1720 1721 1722 1723

#ifdef Rel14
    UE_list->UE_template[cc_idP][UE_id].rach_resource_type = rach_resource_type ;
#endif

1724
    memset((void*)&UE_list->UE_sched_ctrl[UE_id],0,sizeof(UE_sched_ctrl));
1725
    memset((void*)&UE_list->eNB_UE_stats[cc_idP][UE_id],0,sizeof(eNB_UE_STATS));
Raymond Knopp's avatar
 
Raymond Knopp committed
1726

Cedric Roux's avatar
Cedric Roux committed
1727 1728
    UE_list->UE_sched_ctrl[UE_id].ta_update = 31;

1729 1730
    for (j=0; j<8; j++) {
      UE_list->UE_template[cc_idP][UE_id].oldNDI[j]    = (j==0)?1:0;   // 1 because first transmission is with format1A (Msg4) for harq_pid 0
Raymond Knopp's avatar
 
Raymond Knopp committed
1731
      UE_list->UE_template[cc_idP][UE_id].oldNDI_UL[j] = (j==harq_pidP)?0:1; // 1st transmission is with Msg3;
Cedric Roux's avatar
Cedric Roux committed
1732 1733
      UE_list->UE_sched_ctrl[UE_id].round[cc_idP][j]   = 8;
      UE_list->UE_sched_ctrl[UE_id].round_UL[cc_idP][j]   = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1734
    }
1735

1736
    eNB_ulsch_info[mod_idP][cc_idP][UE_id].status = S_UL_WAITING;
1737
    eNB_dlsch_info[mod_idP][cc_idP][UE_id].status = S_DL_WAITING;
Raymond Knopp's avatar
 
Raymond Knopp committed
1738
    LOG_D(MAC,"[eNB %d] Add UE_id %d on Primary CC_id %d: rnti %x\n",mod_idP,UE_id,cc_idP,rntiP);
1739
    dump_ue_list(UE_list,0);
Raymond Knopp's avatar
 
Raymond Knopp committed
1740
    return(UE_id);
1741
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1742

1743
  printf("MAC: cannot add new UE for rnti %x\n", rntiP);
Raymond Knopp's avatar
 
Raymond Knopp committed
1744
  LOG_E(MAC,"error in add_new_ue(), could not find space in UE_list, Dumping UE list\n");
1745
  dump_ue_list(UE_list,0);
1746 1747 1748
  return(-1);
}

1749
//------------------------------------------------------------------------------
Cedric Roux's avatar
Cedric Roux committed
1750
int rrc_mac_remove_ue(module_id_t mod_idP,rnti_t rntiP)
1751
//------------------------------------------------------------------------------
1752
{
1753
  int i;
1754
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
1755
  int UE_id = find_UE_id(mod_idP,rntiP);
1756
  int pCC_id;
1757

1758 1759 1760 1761 1762
  if (UE_id == -1) {
    LOG_W(MAC,"rrc_mac_remove_ue: UE %x not found\n", rntiP);
    return 0;
  }

1763 1764
  pCC_id = UE_PCCID(mod_idP,UE_id);

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

1768 1769 1770
  UE_list->active[UE_id] = FALSE;
  UE_list->num_UEs--;

1771 1772 1773 1774 1775
  if (UE_list->head == UE_id) UE_list->head=UE_list->next[UE_id];
  else UE_list->next[prev(UE_list,UE_id,0)]=UE_list->next[UE_id];
  if (UE_list->head_ul == UE_id) UE_list->head_ul=UE_list->next_ul[UE_id];
  else UE_list->next_ul[prev(UE_list,UE_id,0)]=UE_list->next_ul[UE_id];

1776
  // clear all remaining pending transmissions
1777 1778 1779 1780 1781 1782 1783 1784 1785 1786 1787 1788
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID0]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID1]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID2]  = 0;
  UE_list->UE_template[pCC_id][UE_id].bsr_info[LCGID3]  = 0;

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

1790 1791 1792
  // check if this has an RA process active
  RA_TEMPLATE *RA_template;
  for (i=0;i<NB_RA_PROC_MAX;i++) {
1793
    RA_template = (RA_TEMPLATE *)&RC.mac[mod_idP]->common_channels[pCC_id].RA_template[i];
1794
    if (RA_template->rnti == rntiP){
1795 1796 1797 1798 1799 1800 1801
      RA_template->RA_active=FALSE;
      RA_template->generate_rar=0;
      RA_template->generate_Msg4=0;
      RA_template->wait_ack_Msg4=0;
      RA_template->timing_offset=0;
      RA_template->RRC_timer=20;
      RA_template->rnti = 0;
1802
      //break;
1803 1804
    }
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1805

1806
  return 0;
1807 1808
}

1809 1810
int prev(UE_list_t *listP, int nodeP, int ul_flag)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1811
  int j;
1812

1813
  if (ul_flag == 0 ) {
1814
    if (nodeP==listP->head) {
1815
      return(nodeP);
1816
    }
1817 1818

    for (j=listP->head; j>=0; j=listP->next[j]) {
1819
      if (listP->next[j]==nodeP) {
1820
        return(j);
1821
    }
1822
    }
1823
  } else {
1824
    if (nodeP==listP->head_ul) {
1825
      return(nodeP);
1826
    }
1827 1828

    for (j=listP->head_ul; j>=0; j=listP->next_ul[j]) {
1829
      if (listP->next_ul[j]==nodeP) {
1830
        return(j);
1831
      }
1832
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1833
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1834

1835
  LOG_E(MAC,"error in prev(), could not find previous to %d in UE_list %s, should never happen, Dumping UE list\n",
1836
        nodeP, (ul_flag == 0)? "DL" : "UL");
1837
  dump_ue_list(listP, ul_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
1838

Raymond Knopp's avatar
 
Raymond Knopp committed
1839 1840
  return(-1);
}
1841

1842 1843
void swap_UEs(UE_list_t *listP,int nodeiP, int nodejP, int ul_flag)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
1844 1845
  int prev_i,prev_j,next_i,next_j;

1846 1847
  LOG_T(MAC,"Swapping UE %d,%d\n",nodeiP,nodejP);
  dump_ue_list(listP,ul_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
1848

1849 1850
  prev_i = prev(listP,nodeiP,ul_flag);
  prev_j = prev(listP,nodejP,ul_flag);
1851

1852
  AssertFatal((prev_i>=0) && (prev_j>=0),
Cedric Roux's avatar
Cedric Roux committed
1853
              "swap_UEs: problem");
Raymond Knopp's avatar
 
Raymond Knopp committed
1854

1855
  if (ul_flag == 0) {
1856 1857 1858 1859 1860
    next_i = listP->next[nodeiP];
    next_j = listP->next[nodejP];
  } else {
    next_i = listP->next_ul[nodeiP];
    next_j = listP->next_ul[nodejP];
Raymond Knopp's avatar
 
Raymond Knopp committed
1861
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1862

1863
  LOG_T(MAC,"[%s] next_i %d, next_i, next_j %d, head %d \n",
1864 1865
        (ul_flag == 0)? "DL" : "UL",
        next_i,next_j,listP->head);
1866 1867

  if (ul_flag == 0 ) {
Raymond Knopp's avatar
 
Raymond Knopp committed
1868

1869 1870
    if (next_i == nodejP) {   // case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...
      LOG_T(MAC,"Case ... p(i) i j n(j) ... => ... p(j) j i n(i) ...\n");
1871

1872 1873
      listP->next[nodeiP] = next_j;
      listP->next[nodejP] = nodeiP;
1874

1875
      if (nodeiP==listP->head) { // case i j n(j)
1876
        listP->head = nodejP;
1877
      } else {
1878
        listP->next[prev_i] = nodejP;
1879
      }
1880
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
1881 1882 1883
      LOG_T(MAC,"Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n");
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = nodejP;
1884

1885
      if (nodejP==listP->head) { // case j i n(i)
1886
        listP->head = nodeiP;
1887
      } else {
1888
        listP->next[prev_j] = nodeiP;
1889
      }
1890
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...
1891 1892
      listP->next[nodejP] = next_i;
      listP->next[nodeiP] = next_j;
1893

1894
      if (nodeiP==listP->head) {
1895 1896 1897 1898 1899 1900 1901 1902 1903 1904
        LOG_T(MAC,"changing head to %d\n",nodejP);
        listP->head=nodejP;
        listP->next[prev_j] = nodeiP;
      } else if (nodejP==listP->head) {
        LOG_D(MAC,"changing head to %d\n",nodeiP);
        listP->head=nodeiP;
        listP->next[prev_i] = nodejP;
      } else {
        listP->next[prev_i] = nodejP;
        listP->next[prev_j] = nodeiP;
1905 1906 1907 1908 1909 1910
      }
    }
  } else { // ul_flag

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

1912 1913
      listP->next_ul[nodeiP] = next_j;
      listP->next_ul[nodejP] = nodeiP;
1914

1915
      if (nodeiP==listP->head_ul) { // case i j n(j)
1916
        listP->head_ul = nodejP;
1917
      } else {
1918
        listP->next_ul[prev_i] = nodejP;
1919
      }
1920
    } else if (next_j == nodeiP) {  // case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...
1921 1922 1923
      LOG_T(MAC,"[UL]Case ... p(j) j i n(i) ... => ... p(i) i j n(j) ...\n");
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = nodejP;
1924

1925
      if (nodejP==listP->head_ul) { // case j i n(i)
1926
        listP->head_ul = nodeiP;
1927
      } else {
1928
        listP->next_ul[prev_j] = nodeiP;
1929
      }
1930 1931
    } else {  // case ...  p(i) i n(i) ... p(j) j n(j) ...

1932 1933
      listP->next_ul[nodejP] = next_i;
      listP->next_ul[nodeiP] = next_j;
1934

1935
      if (nodeiP==listP->head_ul) {
1936 1937 1938 1939 1940 1941 1942 1943 1944 1945
        LOG_T(MAC,"[UL]changing head to %d\n",nodejP);
        listP->head_ul=nodejP;
        listP->next_ul[prev_j] = nodeiP;
      } else if (nodejP==listP->head_ul) {
        LOG_T(MAC,"[UL]changing head to %d\n",nodeiP);
        listP->head_ul=nodeiP;
        listP->next_ul[prev_i] = nodejP;
      } else {
        listP->next_ul[prev_i] = nodejP;
        listP->next_ul[prev_j] = nodeiP;
1946
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1947 1948
    }
  }
1949

1950 1951
  LOG_T(MAC,"After swap\n");
  dump_ue_list(listP,ul_flag);
Raymond Knopp's avatar
 
Raymond Knopp committed
1952 1953
}

1954
/*
Cedric Roux's avatar
Cedric Roux committed
1955
  #if defined(Rel10) || defined(Rel14)
1956 1957 1958 1959 1960 1961 1962 1963 1964 1965 1966 1967 1968 1969 1970 1971 1972 1973 1974 1975 1976 1977 1978 1979 1980 1981 1982 1983 1984 1985 1986 1987 1988 1989 1990 1991 1992 1993 1994 1995 1996 1997 1998 1999 2000 2001 2002 2003 2004 2005 2006 2007 2008 2009 2010 2011 2012 2013 2014 2015 2016 2017 2018 2019 2020 2021 2022 2023 2024 2025 2026 2027 2028 2029 2030 2031 2032 2033 2034 2035 2036 2037 2038 2039 2040 2041 2042 2043 2044 2045 2046 2047 2048 2049 2050 2051 2052 2053 2054 2055 2056 2057 2058 2059 2060 2061 2062 2063 2064 2065 2066 2067
  unsigned char generate_mch_header( unsigned char *mac_header,
  unsigned char num_sdus,
  unsigned short *sdu_lengths,
  unsigned char *sdu_lcids,
  unsigned char msi,
  unsigned char short_padding,
  unsigned short post_padding) {

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

  ce_ptr = &mac_header_control_elements[0];

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

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

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

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

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

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

// This has to be updated to include BSR information
2068 2069
uint8_t UE_is_to_be_scheduled(module_id_t module_idP,int CC_id,uint8_t UE_id)
{
2070 2071
  UE_TEMPLATE *UE_template    = &RC.mac[module_idP]->UE_list.UE_template[CC_id][UE_id];
  UE_sched_ctrl *UE_sched_ctl = &RC.mac[module_idP]->UE_list.UE_sched_ctrl[UE_id];
2072

kaltenbe's avatar
kaltenbe committed
2073 2074 2075 2076 2077 2078
  // do not schedule UE if UL is not working
  if (UE_sched_ctl->ul_failure_timer>0)
    return(0);
  if (UE_sched_ctl->ul_out_of_sync>0)
    return(0);

Raymond Knopp's avatar
Raymond Knopp committed
2079
  LOG_D(MAC,"[eNB %d][PUSCH] Checking UL requirements UE %d/%x\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id));
2080

Raymond Knopp's avatar
 
Raymond Knopp committed
2081 2082 2083 2084
  if ((UE_template->bsr_info[LCGID0]>0) ||
      (UE_template->bsr_info[LCGID1]>0) ||
      (UE_template->bsr_info[LCGID2]>0) ||
      (UE_template->bsr_info[LCGID3]>0) ||
gauthier's avatar
gauthier committed
2085
      (UE_template->ul_SR>0) || // uplink scheduling request
2086
      ((UE_sched_ctl->ul_inactivity_timer>20)&&
2087 2088 2089 2090
       (UE_sched_ctl->ul_scheduled==0))||  // every 2 frames when RRC_CONNECTED
      ((UE_sched_ctl->ul_inactivity_timer>10)&&
       (UE_sched_ctl->ul_scheduled==0)&&
       (mac_eNB_get_rrc_status(module_idP,UE_RNTI(module_idP,UE_id)) < RRC_CONNECTED))) // every Frame when not RRC_CONNECTED
Cedric Roux's avatar
Cedric Roux committed
2091 2092 2093 2094
  {
    LOG_D(MAC,"[eNB %d][PUSCH] UE %d/%x should be scheduled (BSR0 %d,SR %d)\n",module_idP,UE_id,UE_RNTI(module_idP,UE_id),
          UE_template->bsr_info[LCGID0],
          UE_template->ul_SR);
2095
    return(1);
2096
  } else {
2097
    return(0);
2098
  }
2099 2100
}

Cedric Roux's avatar
Cedric Roux committed
2101 2102
uint8_t get_tmode(module_id_t module_idP,int CC_idP,int UE_idP)
{
2103 2104 2105 2106 2107
  eNB_MAC_INST         *eNB                                = RC.mac[module_idP];
  COMMON_channels_t    *cc                                 = &eNB->common_channels[CC_idP];

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

2108
  if (physicalConfigDedicated == NULL ) { // RRCConnectionSetup not received by UE yet
2109 2110 2111
    AssertFatal(cc->p_eNB<=2,"p_eNB is %d, should be <2\n",cc->p_eNB);
    return(cc->p_eNB);
  }
2112 2113
  else {
    AssertFatal(physicalConfigDedicated->antennaInfo!=NULL,
Cedric Roux's avatar
Cedric Roux committed
2114 2115 2116 2117 2118
                "antennaInfo is null for CCId %d, UEid %d\n",CC_idP,UE_idP);

    AssertFatal(physicalConfigDedicated->antennaInfo->present != PhysicalConfigDedicated__antennaInfo_PR_NOTHING,
                "antennaInfo (mod_id %d, CC_id %d) is set to NOTHING\n",module_idP,CC_idP);

2119 2120 2121 2122 2123 2124 2125 2126 2127
    if (physicalConfigDedicated->antennaInfo->present == PhysicalConfigDedicated__antennaInfo_PR_explicitValue) {
      return(physicalConfigDedicated->antennaInfo->choice.explicitValue.transmissionMode);
    }
    else if (physicalConfigDedicated->antennaInfo->present == PhysicalConfigDedicated__antennaInfo_PR_defaultValue) {
      AssertFatal(cc->p_eNB<=2,"p_eNB is %d, should be <2\n",cc->p_eNB);
      return(cc->p_eNB);
    }
    else AssertFatal(1==0,"Shouldn't be here\n");
  }
2128 2129
}

Cedric Roux's avatar
Cedric Roux committed
2130 2131
int8_t get_ULharq(module_id_t module_idP,int CC_idP,uint16_t frameP,uint8_t subframeP)
{
2132 2133 2134 2135 2136 2137 2138 2139 2140 2141 2142 2143 2144 2145 2146 2147 2148 2149 2150 2151 2152 2153 2154 2155 2156
  uint8_t           ret       = -1;
  eNB_MAC_INST      *eNB      = RC.mac[module_idP];
  COMMON_channels_t *cc       = &eNB->common_channels[CC_idP];

  if (cc->tdd_Config==NULL) { // FDD
    ret = (((frameP<<1)+subframeP)&7);
  } else {
    switch (cc->tdd_Config->subframeAssignment) {
    case 1:
      if ((subframeP==2) ||
          (subframeP==3) ||
          (subframeP==7) ||
          (subframeP==8))
        switch (subframeP) {
        case 2:
        case 3:
          ret = (subframeP-2);
          break;

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

        default:
2157
          AssertFatal(1==0,"subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
2158 2159 2160 2161 2162 2163
          break;
        }

      break;

    case 2:
2164
      AssertFatal((subframeP==2) || (subframeP==7),
Cedric Roux's avatar
Cedric Roux committed
2165
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
2166
      ret = (subframeP/7);
2167 2168 2169
      break;

    case 3:
2170
      AssertFatal((subframeP>1) && (subframeP<5),
Cedric Roux's avatar
Cedric Roux committed
2171
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
2172
      ret = (subframeP-2);
2173 2174 2175
      break;

    case 4:
2176
      AssertFatal((subframeP>1) && (subframeP<4),
Cedric Roux's avatar
Cedric Roux committed
2177
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
2178
      ret = (subframeP-2);
2179 2180 2181
      break;

    case 5:
2182
      AssertFatal(subframeP==2,
Cedric Roux's avatar
Cedric Roux committed
2183
                  "subframe2_harq_pid, Illegal subframe %d for TDD mode %d\n",subframeP,(int)cc->tdd_Config->subframeAssignment);
2184
      ret = (subframeP-2);
2185 2186 2187
      break;

    default:
2188 2189
      AssertFatal(1==0,"subframe2_harq_pid, Unsupported TDD mode %d\n",(int)cc->tdd_Config->subframeAssignment);
      break;
2190 2191 2192 2193
    }
  }

  AssertFatal(ret!=-1,
Cedric Roux's avatar
Cedric Roux committed
2194
              "invalid harq_pid(%d) at SFN/SF = %d/%d\n", (int8_t)ret, frameP, subframeP);
2195 2196 2197 2198 2199 2200 2201 2202 2203 2204 2205 2206
  return ret;
}


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

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

2208 2209
  return(RIV);
}
2210

2211
uint32_t allocate_prbs(int UE_id,unsigned char nb_rb, int N_RB_DL, uint32_t *rballoc)
2212
{
2213 2214 2215 2216
  int i;
  uint32_t rballoc_dci=0;
  unsigned char nb_rb_alloc=0;

2217
  for (i=0; i<(N_RB_DL-2); i+=2) {
2218 2219 2220 2221 2222 2223
    if (((*rballoc>>i)&3)==0) {
      *rballoc |= (3<<i);
      rballoc_dci |= (1<<((12-i)>>1));
      nb_rb_alloc+=2;
    }

2224
    if (nb_rb_alloc==nb_rb) {
2225
      return(rballoc_dci);
2226
    }
2227 2228
  }

2229 2230 2231 2232
  if ((N_RB_DL&1)==1) {
    if ((*rballoc>>(N_RB_DL-1)&1)==0) {
      *rballoc |= (1<<(N_RB_DL-1));
      rballoc_dci |= 1;
2233
    }
2234
  }
2235

2236 2237 2238
  return(rballoc_dci);
}

2239 2240 2241
int get_bw_index(module_id_t module_id, uint8_t CC_id)
{
  int bw_index=0;
Cedric Roux's avatar
Cedric Roux committed
2242

2243
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
2244

2245
  switch (N_RB_DL) {
2246 2247 2248 2249 2250 2251 2252 2253 2254 2255 2256 2257 2258 2259 2260 2261 2262 2263
  case 6: // 1.4 MHz
    bw_index=0;
    break;

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

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

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

  default:
    bw_index=1;
2264
    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);
2265 2266 2267 2268 2269 2270
    break;
  }

  return bw_index;
}

2271 2272
int get_min_rb_unit(module_id_t module_id, uint8_t CC_id)
{
2273
  int min_rb_unit=0;
2274
  int N_RB_DL = to_prb(RC.mac[module_id]->common_channels[CC_id].mib->message.dl_Bandwidth);
2275

2276
  switch (N_RB_DL) {
2277 2278 2279
  case 6: // 1.4 MHz
    min_rb_unit=1;
    break;
2280

2281 2282 2283
  case 25: // 5HMz
    min_rb_unit=2;
    break;
2284

2285 2286 2287
  case 50: // 10HMz
    min_rb_unit=3;
    break;
2288

2289 2290 2291
  case 100: // 20HMz
    min_rb_unit=4;
    break;
2292

2293 2294
  default:
    min_rb_unit=2;
Cedric Roux's avatar
Cedric Roux committed
2295
    LOG_W(MAC,"[eNB %d] N_DL_RB %d unknown for CC_id %d, setting min_rb_unit to 2\n",
2296
          module_id, N_RB_DL, CC_id);
2297 2298
    break;
  }
2299

2300 2301
  return min_rb_unit;
}
2302

2303
uint32_t allocate_prbs_sub(int nb_rb, int N_RB_DL, int N_RBG, uint8_t *rballoc)
2304
{
2305 2306 2307 2308
  int check=0;//check1=0,check2=0;
  uint32_t rballoc_dci=0;
  //uint8_t number_of_subbands=13;

2309
  LOG_T(MAC,"*****Check1RBALLOC****: %d%d%d%d (nb_rb %d,N_RBG %d)\n",
2310
        rballoc[3],rballoc[2],rballoc[1],rballoc[0],nb_rb,N_RBG);
2311

2312
  while((nb_rb >0) && (check < N_RBG)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
2313
    //printf("rballoc[%d] %d\n",check,rballoc[check]);
2314
    if(rballoc[check] == 1) {
2315
      rballoc_dci |= (1<<((N_RBG-1)-check));
2316

2317
      switch (N_RB_DL) {
2318 2319 2320 2321 2322
      case 6:
        nb_rb--;
        break;

      case 25:
2323
        if ((check == N_RBG-1)) {
2324
          nb_rb--;
2325
        } else {
2326
          nb_rb-=2;
2327
        }
2328 2329 2330 2331

        break;

      case 50:
2332
        if ((check == N_RBG-1)) {
2333
          nb_rb-=2;
2334
        } else {
2335
          nb_rb-=3;
2336
        }
2337 2338 2339 2340 2341 2342

        break;

      case 100:
        nb_rb-=4;
        break;
2343
      }
2344 2345 2346 2347 2348
    }

    //      printf("rb_alloc %x\n",rballoc_dci);
    check = check+1;
    //    check1 = check1+2;
2349
  }
2350

2351 2352 2353 2354 2355 2356
  // rballoc_dci = (rballoc_dci)&(0x1fff);
  LOG_T(MAC,"*********RBALLOC : %x\n",rballoc_dci);
  // exit(-1);
  return (rballoc_dci);
}

Cedric Roux's avatar
Cedric Roux committed
2357 2358
int get_subbandsize(uint8_t dl_Bandwidth)
{
2359 2360 2361
  uint8_t ss[6] = {6,4,4,6,8,8};

  AssertFatal(dl_Bandwidth<6,"dl_Bandwidth %d is out of bounds\n",dl_Bandwidth);
2362

2363 2364
  return(ss[dl_Bandwidth]);
}
Cedric Roux's avatar
Cedric Roux committed
2365

2366
int get_nb_subband(int N_RB_DL)
2367
{
2368 2369
  int nb_sb=0;

2370
  switch (N_RB_DL) {
2371
  case 6:
2372
    nb_sb=0;
2373
    break;
2374

2375 2376
  case 15:
    nb_sb = 4;  // sb_size =4
2377 2378

  case 25:
2379 2380
    nb_sb = 7; // sb_size =4, 1 sb with 1PRB, 6 with 2 RBG, each has 2 PRBs
    break;
2381

2382 2383 2384
  case 50:    // sb_size =6
    nb_sb = 9;
    break;
2385

2386 2387 2388
  case 75:  // sb_size =8
    nb_sb = 10;
    break;
2389

2390 2391 2392
  case 100: // sb_size =8 , 1 sb with 1 RBG + 12 sb with 2RBG, each RBG has 4 PRBs
    nb_sb = 13;
    break;
2393

2394 2395 2396 2397
  default:
    nb_sb=0;
    break;
  }
2398

2399
  return nb_sb;
2400
}
2401 2402 2403

void init_CCE_table(int module_idP,int CC_idP)
{
2404
  memset(RC.mac[module_idP]->CCE_table[CC_idP],0,800*sizeof(int));
Cedric Roux's avatar
Cedric Roux committed
2405
}
2406 2407 2408


int get_nCCE_offset(int *CCE_table,
Cedric Roux's avatar
Cedric Roux committed
2409 2410 2411 2412 2413
                    const unsigned char L,
                    const int nCCE,
                    const int common_dci,
                    const unsigned short rnti,
                    const unsigned char subframe)
2414 2415 2416 2417 2418 2419 2420 2421 2422 2423 2424 2425 2426
{
  int search_space_free,m,nb_candidates = 0,l,i;
  unsigned int Yk;
   /*
    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);
Raymond Knopp's avatar
Raymond Knopp committed
2427

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

2430 2431 2432 2433
    for (m = nb_candidates-1 ; m >=0 ; m--) {

      search_space_free = 1;
      for (l=0; l<L; l++) {
Raymond Knopp's avatar
Raymond Knopp committed
2434

Cedric Roux's avatar
Cedric Roux committed
2435
        //        printf("CCE_table[%d] %d\n",(m*L)+l,CCE_table[(m*L)+l]);
2436 2437 2438 2439 2440
        if (CCE_table[(m*L) + l] == 1) {
          search_space_free = 0;
          break;
        }
      }
Cedric Roux's avatar
Cedric Roux committed
2441

2442
      if (search_space_free == 1) {
Raymond Knopp's avatar
Raymond Knopp committed
2443

Cedric Roux's avatar
Cedric Roux committed
2444
        //        printf("returning %d\n",m*L);
Raymond Knopp's avatar
Raymond Knopp committed
2445

2446 2447 2448 2449 2450 2451 2452 2453 2454 2455 2456 2457 2458 2459 2460 2461 2462 2463 2464 2465 2466 2467 2468 2469 2470 2471 2472 2473 2474 2475 2476 2477 2478 2479
        for (l=0; l<L; l++)
          CCE_table[(m*L)+l]=1;
        return(m*L);
      }
    }

    return(-1);

  } else { // 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;

    for (i=0; i<=subframe; i++)
      Yk = (Yk*39827)%65537;

    Yk = Yk % (nCCE/L);

    switch (L) {
    case 1:
    case 2:
      nb_candidates = 6;
      break;

    case 4:
    case 8:
      nb_candidates = 2;
      break;

    default:
      DevParam(L, nCCE, rnti);
      break;
    }

2480
    LOG_D(MAC,"rnti %x, Yk = %d, nCCE %d (nCCE/L %d),nb_cand %d\n",rnti,Yk,nCCE,nCCE/L,nb_candidates);
2481 2482 2483 2484 2485

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

      for (l=0; l<L; l++) {
Cedric Roux's avatar
Cedric Roux committed
2486 2487
        int cce = (((Yk+m)%(nCCE/L))*L) + l;
        if (cce >= nCCE || CCE_table[cce] == 1) {
2488 2489 2490 2491 2492 2493 2494 2495 2496 2497 2498 2499 2500 2501 2502 2503 2504
          search_space_free = 0;
          break;
        }
      }

      if (search_space_free == 1) {
        for (l=0; l<L; l++)
          CCE_table[(((Yk+m)%(nCCE/L))*L)+l]=1;

        return(((Yk+m)%(nCCE/L))*L);
      }
    }

    return(-1);
  }
}

Cedric Roux's avatar
Cedric Roux committed
2505 2506
void dump_CCE_table(int *CCE_table,const int nCCE,const unsigned short rnti,const int subframe,int L)
{
2507 2508
  int nb_candidates = 0,i;
  unsigned int Yk;
Cedric Roux's avatar
Cedric Roux committed
2509

2510
  printf("CCE 0: ");
2511 2512
  for (i=0;i<nCCE;i++) {
    printf("%1d.",CCE_table[i]);
2513
    if ((i&7) == 7)
Raymond Knopp's avatar
Raymond Knopp committed
2514
      printf("\n CCE %d: ",i);
2515 2516 2517
  }

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

2519 2520
  for (i=0; i<=subframe; i++)
    Yk = (Yk*39827)%65537;
Cedric Roux's avatar
Cedric Roux committed
2521

2522
  Yk = Yk % (nCCE/L);
Cedric Roux's avatar
Cedric Roux committed
2523

2524 2525 2526 2527 2528
  switch (L) {
  case 1:
  case 2:
    nb_candidates = 6;
    break;
Cedric Roux's avatar
Cedric Roux committed
2529

2530 2531 2532 2533
  case 4:
  case 8:
    nb_candidates = 2;
    break;
Cedric Roux's avatar
Cedric Roux committed
2534

2535 2536 2537 2538 2539
  default:
    DevParam(L, nCCE, rnti);
    break;
  }

Cedric Roux's avatar
Cedric Roux committed
2540
  printf("rnti %x, Yk*L = %d, nCCE %d (nCCE/L %d),nb_cand*L %d\n",rnti,Yk*L,nCCE,nCCE/L,nb_candidates*L);
2541 2542
}

2543 2544 2545 2546 2547 2548 2549 2550
uint16_t getnquad(COMMON_channels_t *cc, uint8_t num_pdcch_symbols,uint8_t mi)
{
  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);
Cedric Roux's avatar
Cedric Roux committed
2551
  int phich_resource = get_phich_resource_times6(cc);
2552 2553 2554 2555 2556 2557 2558 2559 2560 2561 2562 2563 2564 2565 2566 2567 2568 2569 2570 2571 2572 2573 2574 2575 2576 2577 2578 2579 2580 2581 2582 2583 2584 2585 2586 2587 2588 2589 2590 2591 2592 2593 2594 2595

  uint8_t Ngroup_PHICH = (phich_resource*N_RB_DL)/48;

  if (((phich_resource*N_RB_DL)%48) > 0)
    Ngroup_PHICH++;

  if (cc->Ncp == 1) {
    Ngroup_PHICH<<=1;
  }

  Ngroup_PHICH*=mi;

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

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

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

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

    default:
      return(0);
    }

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

uint16_t getnCCE(COMMON_channels_t *cc, uint8_t num_pdcch_symbols, uint8_t mi)
{
  AssertFatal(cc!=NULL,"cc is null\n");
  return(getnquad(cc,num_pdcch_symbols,mi)/9);
}

Cedric Roux's avatar
Cedric Roux committed
2596 2597
uint8_t getmi(COMMON_channels_t *cc,int subframe)
{
2598 2599 2600 2601 2602 2603 2604 2605 2606 2607 2608 2609 2610 2611 2612 2613 2614 2615 2616 2617 2618 2619 2620 2621 2622 2623 2624 2625 2626 2627 2628 2629 2630 2631 2632 2633 2634 2635 2636 2637 2638 2639 2640 2641 2642 2643 2644 2645 2646 2647 2648 2649 2650 2651 2652 2653 2654 2655 2656 2657 2658 2659 2660
  AssertFatal(cc!=NULL,"cc is null\n");

  // for FDD
  if (cc->tdd_Config==NULL) // FDD
    return 1;

  // for TDD
  switch (cc->tdd_Config->subframeAssignment) {
  case 0:
    if ((subframe==0) || (subframe==5))
      return(2);
    else return(1);

    break;

  case 1:
    if ((subframe==0) || (subframe==5))
      return(0);
    else return(1);

    break;

  case 2:
    if ((subframe==3) || (subframe==8))
      return(1);
    else return(0);

    break;

  case 3:
    if ((subframe==0) || (subframe==8) || (subframe==9))
      return(1);
    else return(0);

    break;

  case 4:
    if ((subframe==8) || (subframe==9))
      return(1);
    else return(0);

    break;

  case 5:
    if (subframe==8)
      return(1);
    else return(0);

    break;

  case 6:
    return(1);
    break;

  default:
    return(0);
  }
}

uint16_t get_nCCE_max(COMMON_channels_t *cc, int num_pdcch_symbols,int subframe)
{
  AssertFatal(cc!=NULL,"cc is null\n");
  return(getnCCE(cc,num_pdcch_symbols,
Cedric Roux's avatar
Cedric Roux committed
2661
                 getmi(cc,subframe)));
2662
}
Cedric Roux's avatar
Cedric Roux committed
2663

2664 2665
// Allocate the CCEs
int allocate_CCEs(int module_idP,
Cedric Roux's avatar
Cedric Roux committed
2666 2667 2668 2669
                  int CC_idP,
                  int subframeP,
                  int test_onlyP)
{
2670
  int                                 *CCE_table           = RC.mac[module_idP]->CCE_table[CC_idP];
2671 2672
  nfapi_dl_config_request_body_t      *DL_req              = &RC.mac[module_idP]->DL_req[CC_idP].dl_config_request_body;
  nfapi_hi_dci0_request_body_t        *HI_DCI0_req         = &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body;
2673 2674 2675
  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];
  int                                 nCCE_max             = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],1,subframeP);
2676
  int fCCE;
2677
  int i,j,idci;
Raymond Knopp's avatar
Raymond Knopp committed
2678
  int nCCE=0;
2679

Raymond Knopp's avatar
Raymond Knopp committed
2680
  LOG_D(MAC,"Allocate CCEs subframe %d, test %d : (DL PDU %d, DL DCI %d, UL %d)\n",subframeP,test_onlyP,DL_req->number_pdu,DL_req->number_dci,HI_DCI0_req->number_of_dci);
2681
  DL_req->number_pdcch_ofdm_symbols=1;
Raymond Knopp's avatar
Raymond Knopp committed
2682

2683 2684 2685 2686
try_again:
  init_CCE_table(module_idP,CC_idP);
  nCCE=0;

2687 2688 2689
  for (i=0,idci=0;i<DL_req->number_pdu;i++) {
    // allocate DL common DCIs first
    if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2690 2691
        (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type==2)
        ) {
2692
      LOG_D(MAC,"Trying to allocate COMMON DCI %d/%d (%d,%d) : rnti %x, aggreg %d nCCE %d / %d (num_pdcch_symbols %d)\n",
Cedric Roux's avatar
Cedric Roux committed
2693 2694 2695 2696 2697 2698
            idci,DL_req->number_dci+HI_DCI0_req->number_of_dci,
            DL_req->number_dci,HI_DCI0_req->number_of_dci,
            dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti,
            dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
            nCCE,nCCE_max, DL_req->number_pdcch_ofdm_symbols);

2699
      if (nCCE + (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) {
Cedric Roux's avatar
Cedric Roux committed
2700 2701 2702 2703 2704 2705
        if (DL_req->number_pdcch_ofdm_symbols == 3)
          goto failed;
        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++;
        nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP);
        goto try_again;
2706
      }
Cedric Roux's avatar
Cedric Roux committed
2707

2708 2709
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
Cedric Roux's avatar
Cedric Roux committed
2710 2711 2712 2713 2714
                             dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                             nCCE_max,
                             1,
                             dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti,
                             subframeP);
2715
      if (fCCE == -1) {
Cedric Roux's avatar
Cedric Roux committed
2716 2717 2718 2719 2720 2721 2722 2723 2724 2725 2726 2727 2728 2729 2730 2731 2732 2733 2734 2735 2736
        if (DL_req->number_pdcch_ofdm_symbols == 3) {
          LOG_D(MAC,"subframe %d: Dropping Allocation for RNTI %x\n",
                subframeP,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti);
          for (j=0;j<=i;j++){
            if (dl_config_pdu[j].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
              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,
                    dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.rnti,
                    dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.dci_format,
                    dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                    nCCE,nCCE_max,DL_req->number_pdcch_ofdm_symbols);
          }
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
          goto failed;
        }
        LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",DL_req->number_pdcch_ofdm_symbols);

        DL_req->number_pdcch_ofdm_symbols++;
        nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP);
        goto try_again;
2737
      } // fCCE==-1
Cedric Roux's avatar
Cedric Roux committed
2738

2739 2740 2741 2742
      // the allocation is feasible, rnti rule passes
      nCCE += dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level;
      LOG_D(MAC,"Allocating at nCCE %d\n",fCCE);
      if (test_onlyP == 0) {
Cedric Roux's avatar
Cedric Roux committed
2743 2744
        dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx=fCCE;
        LOG_D(MAC,"Allocate COMMON DCI CCEs subframe %d, test %d => L %d fCCE %d\n",subframeP,test_onlyP,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,fCCE);
2745 2746
      }
      idci++;
2747
    }
2748
  } // for i = 0 ... num_DL_DCIs
2749

2750 2751 2752
  // no try to allocate UL DCIs
  for (i=0;i<HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi;i++) {

Cedric Roux's avatar
Cedric Roux committed
2753
    // allocate UL DCIs
2754 2755 2756
    if (hi_dci0_pdu[i].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE) {

      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",
Cedric Roux's avatar
Cedric Roux committed
2757 2758 2759 2760 2761
            idci,DL_req->number_dci+HI_DCI0_req->number_of_dci,
            DL_req->number_dci,HI_DCI0_req->number_of_dci,
            hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti,hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level,
            nCCE,nCCE_max, DL_req->number_pdcch_ofdm_symbols);

2762
      if (nCCE + (hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level) > nCCE_max) {
Cedric Roux's avatar
Cedric Roux committed
2763 2764 2765
        if (DL_req->number_pdcch_ofdm_symbols == 3)
          goto failed;
        LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",DL_req->number_pdcch_ofdm_symbols);
2766

Cedric Roux's avatar
Cedric Roux committed
2767 2768 2769
        DL_req->number_pdcch_ofdm_symbols++;
        nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP);
        goto try_again;
2770
      }
Cedric Roux's avatar
Cedric Roux committed
2771

2772 2773
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
Cedric Roux's avatar
Cedric Roux committed
2774 2775 2776 2777 2778
                             hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level,
                             nCCE_max,
                             0,
                             hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti,
                             subframeP);
2779
      if (fCCE == -1) {
Cedric Roux's avatar
Cedric Roux committed
2780 2781 2782 2783 2784 2785 2786 2787 2788 2789 2790 2791 2792 2793 2794 2795 2796 2797 2798 2799 2800
        if (DL_req->number_pdcch_ofdm_symbols == 3) {
          LOG_D(MAC,"subframe %d: Dropping Allocation for RNTI %x\n",
                subframeP,hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.rnti);
          for (j=0;j<=i;j++){
            if (hi_dci0_pdu[j].pdu_type == NFAPI_HI_DCI0_DCI_PDU_TYPE)
              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,
                    hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8.rnti,
                    hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8.dci_format,
                    hi_dci0_pdu[j].dci_pdu.dci_pdu_rel8.aggregation_level,
                    nCCE,nCCE_max,DL_req->number_pdcch_ofdm_symbols);
          }
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
          goto failed;
        }
        LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",DL_req->number_pdcch_ofdm_symbols);

        DL_req->number_pdcch_ofdm_symbols++;
        nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP);
        goto try_again;
2801
      } // fCCE==-1
Cedric Roux's avatar
Cedric Roux committed
2802

2803 2804 2805 2806
      // the allocation is feasible, rnti rule passes
      nCCE += hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.aggregation_level;
      LOG_D(MAC,"Allocating at nCCE %d\n",fCCE);
      if (test_onlyP == 0) {
Cedric Roux's avatar
Cedric Roux committed
2807 2808
        hi_dci0_pdu[i].dci_pdu.dci_pdu_rel8.cce_index=fCCE;
        LOG_D(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP);
2809 2810 2811 2812 2813 2814
      }
      idci++;
    }
  } // for i = 0 ... num_UL_DCIs

  for (i=0;i<DL_req->number_pdu;i++) {
Cedric Roux's avatar
Cedric Roux committed
2815
    // allocate DL UE specific DCIs
2816
    if ((dl_config_pdu[i].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2817
        (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti_type==1)) {
2818
      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",
Cedric Roux's avatar
Cedric Roux committed
2819 2820 2821 2822 2823
            idci,DL_req->number_dci+HI_DCI0_req->number_of_dci,
            DL_req->number_dci,HI_DCI0_req->number_of_dci,
            dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
            nCCE,nCCE_max, DL_req->number_pdcch_ofdm_symbols);

2824
      if (nCCE + (dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level) > nCCE_max) {
Cedric Roux's avatar
Cedric Roux committed
2825 2826 2827
        if (DL_req->number_pdcch_ofdm_symbols == 3)
          goto failed;
        LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols, increasing by 1\n",DL_req->number_pdcch_ofdm_symbols);
2828

Cedric Roux's avatar
Cedric Roux committed
2829 2830 2831
        DL_req->number_pdcch_ofdm_symbols++;
        nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP);
        goto try_again;
2832
      }
Cedric Roux's avatar
Cedric Roux committed
2833

2834 2835
      // number of CCEs left can potentially hold this allocation
      fCCE = get_nCCE_offset(CCE_table,
Cedric Roux's avatar
Cedric Roux committed
2836 2837 2838 2839 2840
                             dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                             nCCE_max,
                             0,
                             dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti,
                             subframeP);
2841
      if (fCCE == -1) {
Cedric Roux's avatar
Cedric Roux committed
2842 2843 2844 2845 2846 2847 2848 2849 2850 2851 2852 2853 2854 2855 2856 2857 2858 2859 2860 2861 2862
        if (DL_req->number_pdcch_ofdm_symbols == 3) {
          LOG_I(MAC,"subframe %d: Dropping Allocation for RNTI %x\n",
                subframeP,dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.rnti);
          for (j=0;j<=i;j++){
            if (dl_config_pdu[j].pdu_type == NFAPI_DL_CONFIG_DCI_DL_PDU_TYPE)
              LOG_I(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,
                    dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.rnti,
                    dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.dci_format,
                    dl_config_pdu[j].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
                    nCCE,nCCE_max,DL_req->number_pdcch_ofdm_symbols);
          }
          //dump_CCE_table(CCE_table,nCCE_max,subframeP,dci_alloc->rnti,1<<dci_alloc->L);
          goto failed;
        }
        LOG_D(MAC,"Can't fit DCI allocations with %d PDCCH symbols (rnti condition), increasing by 1\n",DL_req->number_pdcch_ofdm_symbols);

        DL_req->number_pdcch_ofdm_symbols++;
        nCCE_max = get_nCCE_max(&RC.mac[module_idP]->common_channels[CC_idP],DL_req->number_pdcch_ofdm_symbols,subframeP);
        goto try_again;
2863
      } // fCCE==-1
Cedric Roux's avatar
Cedric Roux committed
2864

2865 2866 2867 2868
      // the allocation is feasible, rnti rule passes
      nCCE += dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level;
      LOG_D(MAC,"Allocating at nCCE %d\n",fCCE);
      if (test_onlyP == 0) {
Cedric Roux's avatar
Cedric Roux committed
2869 2870
        dl_config_pdu[i].dci_dl_pdu.dci_dl_pdu_rel8.cce_idx=fCCE;
        LOG_D(MAC,"Allocate CCEs subframe %d, test %d\n",subframeP,test_onlyP);
2871
      }
2872
      idci++;
2873
    }
2874
  } // for i = 0 ... num_DL_DCIs
2875

2876
  return 0;
2877

Cedric Roux's avatar
Cedric Roux committed
2878
failed:
2879
  return -1;
2880 2881
}

2882
/*
Cedric Roux's avatar
Cedric Roux committed
2883 2884 2885
uint8_t get_ul_req_index(module_id_t module_idP, int CC_idP, sub_frame_t subframeP)
{
  if (RC.mac[module_idP]->common_channels[CC_idP].tdd_Config == NULL)
2886
    return(0);
Cedric Roux's avatar
Cedric Roux committed
2887

2888 2889 2890 2891 2892 2893 2894 2895 2896 2897 2898 2899 2900 2901 2902 2903 2904 2905 2906 2907 2908 2909 2910 2911 2912 2913 2914 2915 2916 2917 2918
  switch (RC.mac[module_idP]->common_channels[CC_idP].tdd_Config->subframeAssignment) {
  case 0:
  case 1:
  case 2:
  case 6:
    return(0);
  case 3:
    // 1,5,6 -> 2, prog. 8, buffer 0
    // 7,8   -> 3, prog. 9, buffer 1
    // 9,0   -> 4, prog. 0, buffer 0
    if ((subframeP == 7) || (subframeP == 8)) return(1);
    else                                      return(0);
  case 4:
    // 0,1,4,5 -> 2, prog. 8, buffer 0
    // 6,7,8,9 -> 3, prog. 9, buffer 1
    if (subframeP<6) return(0);
    else             return(1);
    return(1);
    break;
  case 5:
    // 9(-1),0,1,3,4,5,6,7,8,9 -> 2, prog 8, buffer 0
    return(0);
    break;
  default:
    AssertFatal(1==0,"Should not get here, why is tdd_Config->subframeAssignment = %d\n",(int)RC.mac[module_idP]->common_channels[CC_idP].tdd_Config->subframeAssignment);
    break;
  }
  return(0);
}
*/

Cedric Roux's avatar
Cedric Roux committed
2919 2920 2921 2922 2923
nfapi_ul_config_request_pdu_t* has_ul_grant(module_id_t module_idP,int CC_idP,uint16_t absSFP,uint16_t rnti)
{
  nfapi_ul_config_request_body_t *ul_req;
  nfapi_ul_config_request_pdu_t *ul_config_pdu;

2924
  ul_req        = &RC.mac[module_idP]->UL_req_tmp[CC_idP][absSFP%10].ul_config_request_body;
2925
  ul_config_pdu = &ul_req->ul_config_pdu_list[0];
2926
  LOG_D(MAC,"Checking for rnti %x UL grant in subframeP %d (num pdu %d)\n",rnti,absSFP%10,ul_req->number_of_pdus);
2927 2928

  for (int i=0; i<ul_req->number_of_pdus;i++){
2929
    LOG_D(MAC,"PDU %d : type %d,rnti %x\n",i,ul_config_pdu[i].pdu_type,rnti);
2930
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2931
        (ul_config_pdu[i].ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2932
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_RI_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2933
        (ul_config_pdu[i].ulsch_cqi_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2934
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_HARQ_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2935
        (ul_config_pdu[i].ulsch_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2936
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CQI_HARQ_RI_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2937
        (ul_config_pdu[i].ulsch_cqi_harq_ri_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2938 2939

    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2940
        (ul_config_pdu[i].uci_cqi_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2941
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2942
        (ul_config_pdu[i].uci_sr_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2943
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_HARQ_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2944
        (ul_config_pdu[i].uci_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2945
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_SR_HARQ_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2946
        (ul_config_pdu[i].uci_sr_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2947
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_HARQ_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2948
        (ul_config_pdu[i].uci_cqi_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2949
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2950
        (ul_config_pdu[i].uci_cqi_sr_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2951
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_UCI_CQI_SR_HARQ_PDU_TYPE) &&
Cedric Roux's avatar
Cedric Roux committed
2952
        (ul_config_pdu[i].uci_cqi_sr_harq_pdu.ue_information.ue_information_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2953 2954

    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_UCI_CSI_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2955
        (ul_config_pdu[i].ulsch_uci_csi_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2956
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_UCI_HARQ_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2957
        (ul_config_pdu[i].ulsch_uci_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2958
    if ((ul_config_pdu[i].pdu_type == NFAPI_UL_CONFIG_ULSCH_CSI_UCI_HARQ_PDU_TYPE)&&
Cedric Roux's avatar
Cedric Roux committed
2959
        (ul_config_pdu[i].ulsch_csi_uci_harq_pdu.ulsch_pdu.ulsch_pdu_rel8.rnti == rnti)) return(&ul_config_pdu[i]);
2960
  }
Cedric Roux's avatar
Cedric Roux committed
2961

2962 2963
  return(NULL); // no ul grant at all for this UE
}
Cedric Roux's avatar
Cedric Roux committed
2964

2965
boolean_t CCE_allocation_infeasible(int module_idP,
Cedric Roux's avatar
Cedric Roux committed
2966 2967 2968 2969 2970
                                    int CC_idP,
                                    int format_flag,
                                    int subframe,
                                    int aggregation,
                                    int rnti)
2971 2972 2973 2974
{
  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];
  nfapi_hi_dci0_request_body_t   *HI_DCI0_req   = &RC.mac[module_idP]->HI_DCI0_req[CC_idP].hi_dci0_request_body;
Cedric Roux's avatar
Cedric Roux committed
2975
  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];
2976
  int ret;
2977
  boolean_t res = FALSE;
2978

2979 2980 2981 2982 2983 2984 2985 2986 2987 2988 2989
  if (format_flag != 2) { // DL DCI
    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);
    } else {
      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++;
      LOG_D(MAC,"Subframe %d: Checking CCE feasibility format %d : (%x,%d) (%x,%d,%d)\n",
Cedric Roux's avatar
Cedric Roux committed
2990 2991 2992 2993
        subframe,format_flag,rnti,aggregation,
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti,
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.aggregation_level,
          dl_config_pdu->dci_dl_pdu.dci_dl_pdu_rel8.rnti_type);
2994 2995 2996 2997 2998 2999 3000 3001
      ret = allocate_CCEs(module_idP,CC_idP,subframe,0);
      if (ret==-1)
        res = TRUE;
      DL_req->number_pdu--;
    }
  }
  else { // ue-specific UL DCI
    if (HI_DCI0_req->number_of_dci+HI_DCI0_req->number_of_hi == MAX_NUM_HI_DCI0_PDU) {
Cedric Roux's avatar
Cedric Roux committed
3002 3003
      LOG_W(MAC, "Subframe %d: FAPI UL structure is full, skip scheduling UE %d\n",
            subframe, rnti);
3004 3005 3006 3007 3008 3009 3010 3011 3012 3013 3014
    } else {
      hi_dci0_pdu->pdu_type                               = NFAPI_HI_DCI0_DCI_PDU_TYPE;
      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++;
      ret = allocate_CCEs(module_idP,CC_idP,subframe,0);
      if (ret==-1)
        res = TRUE;
      HI_DCI0_req->number_of_dci--;
    }
  }
3015

3016
  return res;
3017 3018
}

Cedric Roux's avatar
Cedric Roux committed
3019 3020
void extract_harq(module_id_t mod_idP,int CC_idP,int UE_id,frame_t frameP,sub_frame_t subframeP,void *harq_indication,int format)
{
3021 3022 3023 3024 3025 3026 3027 3028 3029 3030 3031 3032 3033 3034 3035 3036 3037 3038
  UE_list_t *UE_list       = &RC.mac[mod_idP]->UE_list;
  UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
  rnti_t rnti              = UE_RNTI(mod_idP,UE_id);
  COMMON_channels_t *cc    = &RC.mac[mod_idP]->common_channels[CC_idP];
  nfapi_harq_indication_fdd_rel13_t *harq_indication_fdd;
  nfapi_harq_indication_tdd_rel13_t *harq_indication_tdd;
  uint16_t num_ack_nak;
  int numCC = UE_list->numactiveCCs[UE_id];
  int pCCid = UE_list->pCC_id[UE_id];
  int spatial_bundling = 0;
  int tmode[5];
  int i,j;
  uint8_t *pdu;

#ifdef Rel14
  AssertFatal(UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->pucch_ConfigDedicated!=NULL,"pucch_ConfigDedicated is null!\n");
  if ((UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7) &&
      (UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13) &&
Cedric Roux's avatar
Cedric Roux committed
3039 3040 3041 3042
      (((UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUCCH_r13) &&
        (format==0)) ||
       ((UE_list->UE_template[pCCid][UE_id].physicalConfigDedicated->ext7->pucch_ConfigDedicated_r13->spatialBundlingPUSCH_r13) &&
        (format==1))))
3043 3044 3045 3046
    spatial_bundling = 1;
#endif

  for (i=0;i<numCC;i++) tmode[i] = get_tmode(mod_idP,i,UE_id);
Cedric Roux's avatar
Cedric Roux committed
3047 3048

  if (cc->tdd_Config) {
3049 3050 3051 3052 3053 3054 3055
    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;

    switch (harq_indication_tdd->mode) {
      case 0: // Format 1a/b
Cedric Roux's avatar
Cedric Roux committed
3056 3057
        AssertFatal(numCC==1,"numCC %d > 1, should not be using Format1a/b\n",numCC);
        break;
3058
      case 1: // Channel Selection
Cedric Roux's avatar
Cedric Roux committed
3059
        break;
3060
      case 2: // Format 3
Cedric Roux's avatar
Cedric Roux committed
3061
        break;
3062
      case 3: // Format 4
Cedric Roux's avatar
Cedric Roux committed
3063
        break;
3064
      case 4: // Format 5
Cedric Roux's avatar
Cedric Roux committed
3065
        break;
3066 3067 3068 3069 3070 3071 3072 3073 3074 3075 3076
    }
  }
  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];

    uint8_t harq_pid = ((10*frameP) + subframeP + 10236)&7;

    switch (harq_indication_fdd->mode) {
      case 0: // Format 1a/b (10.1.2.1)
Cedric Roux's avatar
Cedric Roux committed
3077 3078 3079 3080 3081 3082
        AssertFatal(numCC==1,"numCC %d > 1, should not be using Format1a/b\n",numCC);
        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
          // single ACK/NAK bit
          AssertFatal(num_ack_nak==1,"num_ack_nak %d > 1 for 1 CC and single-layer transmission\n",num_ack_nak);
          AssertFatal(sched_ctl->round[CC_idP][harq_pid]<8,"Got ACK/NAK for inactive harq_pid %d for UE %d/%x\n",harq_pid,UE_id,rnti);
          AssertFatal(pdu[0] == 1 || pdu[0] == 2 || pdu[0] == 4,
Cedric Roux's avatar
Cedric Roux committed
3083
                      "Received ACK/NAK %d which is not 1 or 2 for harq_pid %d from UE %d/%x\n",pdu[0],harq_pid,UE_id,rnti);
Cedric Roux's avatar
Cedric Roux committed
3084 3085 3086 3087 3088 3089 3090 3091 3092 3093 3094 3095 3096 3097 3098 3099 3100 3101 3102 3103 3104 3105 3106 3107 3108 3109 3110 3111 3112 3113
          LOG_D(MAC,"Received %d for harq_pid %d\n",pdu[0],harq_pid);

          if (pdu[0] == 1) { // ACK
            sched_ctl->round[CC_idP][harq_pid]=8; // release HARQ process
            sched_ctl->tbcnt[CC_idP][harq_pid]=0;
          }
          else if (pdu[0] == 2 || pdu[0] == 4) // NAK (treat DTX as NAK)
            sched_ctl->round[CC_idP][harq_pid]++; // increment round
        }
        else {
          // one or two ACK/NAK bits
          AssertFatal(num_ack_nak>2,"num_ack_nak %d > 2 for 1 CC and TM3/4/8/9/10\n",num_ack_nak);
          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)) {
            sched_ctl->round[CC_idP][harq_pid]=8;
            sched_ctl->tbcnt[CC_idP][harq_pid]=0;
          }
          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]++;
          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;
          }
          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]++;
          else AssertFatal(1==0,"Illegal ACK/NAK/round combination (%d,%d,%d,%d,%d) for harq_pid %d, UE %d/%x\n",
                           num_ack_nak,sched_ctl->round[CC_idP][harq_pid],sched_ctl->round[CC_idP][harq_pid],pdu[0],pdu[1], harq_pid,UE_id,
                           rnti);
        }
        break;
3114
      case 1: // FDD Channel Selection (10.1.2.2.1), must be received for 2 serving cells
Cedric Roux's avatar
Cedric Roux committed
3115 3116 3117 3118 3119 3120 3121 3122 3123 3124 3125 3126 3127 3128 3129 3130 3131 3132 3133 3134 3135 3136 3137 3138 3139 3140 3141 3142 3143 3144 3145 3146 3147 3148 3149 3150 3151 3152 3153 3154 3155 3156 3157 3158 3159 3160 3161 3162 3163 3164 3165 3166 3167
        AssertFatal(numCC==2,"Should not receive harq indication with channel selection with %d active CCs\n",
                    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 (pdu[1] == 1) sched_ctl->round[1-pCCid][harq_pid]=8;
          else             sched_ctl->round[1-pCCid][harq_pid]++;
        } // 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]);
          AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 2,"sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",pCCid,harq_pid,UE_id,rnti);
          AssertFatal(sched_ctl->tbcnt[1-pCCid][harq_pid] == 1,"sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",1-pCCid,harq_pid,UE_id,rnti);
          if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK
              sched_ctl->round[pCCid][harq_pid]=8;
              sched_ctl->tbcnt[pCCid][harq_pid]=0;
          }
          else if (((pdu[0] == 2) && (pdu[1] == 1))||
                   ((pdu[0] == 1) && (pdu[1] == 2))){
            sched_ctl->round[pCCid][harq_pid]++;
            sched_ctl->tbcnt[pCCid][harq_pid]=1;
          }
          else
             sched_ctl->round[pCCid][harq_pid]++;

          if (pdu[2] == 1) sched_ctl->round[1-pCCid][harq_pid]=8;
          else             sched_ctl->round[1-pCCid][harq_pid]++;
        } // 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]);
          AssertFatal(sched_ctl->tbcnt[1-pCCid][harq_pid] == 2,"sched_ctl->tbcnt[%d][%d] != 2 for UE %d/%x\n",1-pCCid,harq_pid,UE_id,rnti);
          AssertFatal(sched_ctl->tbcnt[pCCid][harq_pid] == 1,"sched_ctl->tbcnt[%d][%d] != 1 for UE %d/%x\n",pCCid,harq_pid,UE_id,rnti);
          if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK
              sched_ctl->round[1-pCCid][harq_pid]=8;
              sched_ctl->tbcnt[1-pCCid][harq_pid]=0;
          }
          else if (((pdu[0] >= 2) && (pdu[1] == 1))||
                   ((pdu[0] == 1) && (pdu[1] >= 2))){ // one ACK
            sched_ctl->round[1-pCCid][harq_pid]++;
            sched_ctl->tbcnt[1-pCCid][harq_pid]=1;
          }
          else  // both NAK/DTX
             sched_ctl->round[1-pCCid][harq_pid]++;

          if (pdu[2] == 1) sched_ctl->round[pCCid][harq_pid]=8;
          else             sched_ctl->round[pCCid][harq_pid]++;
        } // A=3 secondary cell has 2 TBs
3168
#if MAX_NUM_CCs>1
Cedric Roux's avatar
Cedric Roux committed
3169 3170 3171 3172 3173 3174 3175 3176 3177 3178 3179 3180 3181 3182 3183 3184 3185 3186 3187 3188 3189 3190 3191 3192 3193 3194 3195 3196 3197 3198 3199
        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]);
          AssertFatal(sched_ctl->tbcnt[0][harq_pid] == 2,"sched_ctl->tbcnt[0][%d] != 2 for UE %d/%x\n",harq_pid,UE_id,rnti);
          AssertFatal(sched_ctl->tbcnt[1][harq_pid] == 2,"sched_ctl->tbcnt[1][%d] != 2 for UE %d/%x\n",harq_pid,UE_id,rnti);
          if ((pdu[0] == 1) && (pdu[1] == 1)) { // both ACK
              sched_ctl->round[0][harq_pid]=8;
              sched_ctl->tbcnt[0][harq_pid]=0;
          }
          else if (((pdu[0] >= 2) && (pdu[1] == 1))||
                   ((pdu[0] == 1) && (pdu[1] >= 2))){ // one ACK
            sched_ctl->round[0][harq_pid]++;
            sched_ctl->tbcnt[0][harq_pid]=1;
          }
          else  // both NAK/DTX
             sched_ctl->round[0][harq_pid]++;

          if ((pdu[2] == 1) && (pdu[3] == 1)) { // both ACK
              sched_ctl->round[1][harq_pid]=8;
              sched_ctl->tbcnt[1][harq_pid]=0;
          }
          else if (((pdu[2] >= 2) && (pdu[3] == 1))||
                   ((pdu[2] == 1) && (pdu[3] >= 2))){ // one ACK
            sched_ctl->round[1][harq_pid]++;
            sched_ctl->tbcnt[1][harq_pid]=1;
          }
          else  // both NAK/DTX
             sched_ctl->round[1][harq_pid]++;
        } // A=4 both serving cells have 2 TBs
3200
#endif
Cedric Roux's avatar
Cedric Roux committed
3201
        break;
3202
      case 2: // Format 3
Cedric Roux's avatar
Cedric Roux committed
3203 3204 3205 3206 3207 3208 3209 3210 3211 3212 3213 3214 3215 3216 3217 3218 3219 3220 3221 3222 3223 3224 3225 3226 3227 3228 3229 3230 3231 3232 3233 3234 3235 3236 3237 3238 3239 3240 3241 3242 3243 3244 3245 3246 3247 3248 3249 3250 3251 3252
        AssertFatal(numCC>2,"Should not receive harq indication with FDD format 3 with %d < 3 active CCs\n",
                    numCC);
        for (i=0,j=0;i<numCC;i++) {
          if ((sched_ctl->round[i][harq_pid]<8)) {
            if (tmode[i]==1 || tmode[i]==2 || tmode[0]==5 || tmode[0]==6 || tmode[0]==7) {
              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]++;
              else AssertFatal(1==0,"Illegal harq_ack value for CC %d harq_pid %d (%d) UE %d/%x\n",
                               i,harq_pid,pdu[j],UE_id,rnti);
              j++;
            }
            else if (spatial_bundling == 0) {
              if      ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 1) && (pdu[j+1]==1)) {
                sched_ctl->round[i][harq_pid]=8;
                sched_ctl->tbcnt[i][harq_pid]=0;
              }
              else if ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 1) && (pdu[j+1]==2)) {
                sched_ctl->round[i][harq_pid]++;
                sched_ctl->tbcnt[i][harq_pid]=1;
              }
              else if ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 2) && (pdu[j+1]==1)) {
                sched_ctl->round[i][harq_pid]++;
                sched_ctl->tbcnt[i][harq_pid]=1;
              }
              else if ((sched_ctl->tbcnt[i][harq_pid]==2) && (pdu[j] == 2) && (pdu[j+1]==2)) {
                sched_ctl->round[i][harq_pid]++;
              }
              else AssertFatal(1==0,"Illegal combination for CC %d harq_pid %d (%d,%d,%d) UE %d/%x\n",
                               i,harq_pid,sched_ctl->tbcnt[i][harq_pid],pdu[j],pdu[j+1],UE_id,rnti);
              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]++;
              }
              else AssertFatal(1==0,"Illegal hack_nak value %d for CC %d harq_pid %d UE %d/%x\n",
                               pdu[j],i,harq_pid,UE_id,rnti);
              j++;
            }
            else AssertFatal(1==0,"Illegal value for spatial_bundling %d\n",spatial_bundling);
          }
        }
        break;
3253
      case 3: // Format 4
Cedric Roux's avatar
Cedric Roux committed
3254 3255
        AssertFatal(1==0,"Should not receive harq indication with Format 4\n");
        break;
3256
      case 4: // Format 5
Cedric Roux's avatar
Cedric Roux committed
3257 3258
        AssertFatal(1==0,"Should not receive harq indication with Format 5\n");
        break;
3259 3260 3261 3262
    }
  }
}

Cedric Roux's avatar
Cedric Roux committed
3263 3264
void extract_pucch_csi(module_id_t mod_idP,int CC_idP,int UE_id, frame_t frameP,sub_frame_t subframeP,uint8_t *pdu, uint8_t length)
{
3265 3266 3267 3268 3269 3270 3271 3272 3273 3274 3275 3276
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
  UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
  COMMON_channels_t *cc=&RC.mac[mod_idP]->common_channels[CC_idP];
  struct CQI_ReportPeriodic *cqi_ReportPeriodic;
  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;

  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id);
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL,"cqi_ReportConfig is null for UE %d\n",UE_id);
  AssertFatal((cqi_ReportPeriodic = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportPeriodic)!=NULL,
Cedric Roux's avatar
Cedric Roux committed
3277 3278
              "cqi_ReportPeriodic is null for UE %d\n",UE_id);

3279 3280
  // determine feedback mode
  AssertFatal(cqi_ReportPeriodic->present != CQI_ReportPeriodic_PR_NOTHING,
Cedric Roux's avatar
Cedric Roux committed
3281
              "cqi_ReportPeriodic->present == CQI_ReportPeriodic_PR_NOTHING!\n");
3282
  AssertFatal(cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present != CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING,
Cedric Roux's avatar
Cedric Roux committed
3283
              "cqi_ReportPeriodic->cqi_FormatIndicatorPeriodic.choice.setup.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_NOTHING!\n");
3284 3285 3286 3287

  uint16_t Npd,N_OFFSET_CQI;
  int H,K,bandwidth_part,L,Lmask;
  int ri    = sched_ctl->periodic_ri_received[CC_idP];
Cedric Roux's avatar
Cedric Roux committed
3288

3289 3290 3291 3292 3293 3294 3295 3296 3297 3298 3299 3300 3301 3302 3303 3304 3305 3306 3307 3308 3309 3310 3311 3312 3313
  get_csi_params(cc,cqi_ReportPeriodic,&Npd,&N_OFFSET_CQI,&H);
  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;

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

  switch(get_tmode(mod_idP,CC_idP,UE_id)) {
  case 1:
  case 2:
  case 3:
  case 7:
    no_pmi=1;
    break;
  case 4:
  case 5:
  case 6:
    no_pmi=0;
    break;
  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;
  }
Cedric Roux's avatar
Cedric Roux committed
3314 3315

  if ((cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == CQI_ReportPeriodic__setup__cqi_FormatIndicatorPeriodic_PR_widebandCQI) ||
3316 3317 3318 3319 3320 3321 3322 3323 3324 3325 3326 3327 3328 3329 3330 3331 3332 3333 3334 3335 3336 3337 3338 3339 3340 3341 3342 3343 3344 3345 3346 3347 3348 3349 3350 3351 3352 3353 3354
      (feedback_cnt==0)){
      // 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)

    if (no_pmi == 1) { // get spatial_diffcqi if needed
      sched_ctl->periodic_wideband_cqi[CC_idP]             = pdu[0]&0xF;
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0]>>4)&7;
    }
    else if ((cc->p_eNB==2) && (ri==1))  {
      // 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;
    }
    else if ((cc->p_eNB==2) && (ri>1)) {
      // p=2 Rank 2 wideband CQI/PMI 8 bits
      sched_ctl->periodic_wideband_cqi[CC_idP]             = pdu[0]&0xF;
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0]>>4)&7;
      sched_ctl->periodic_wideband_pmi[CC_idP]             = (pdu[0]>>7)&1;
    }
    else if ((cc->p_eNB==4) && (ri==1)) {
      // p=4 Rank 1 wideband CQI/PMI 8 bits
      sched_ctl->periodic_wideband_cqi[CC_idP]             = pdu[0]&0xF;
      sched_ctl->periodic_wideband_pmi[CC_idP]             = (pdu[0]>>4)&0x0F;

    }
    else if ((cc->p_eNB==4) && (ri>1)) {
      // p=4 Rank 2 wideband CQI/PMI 11 bits
      sched_ctl->periodic_wideband_cqi[CC_idP]             = pdu[0]&0xF;
      sched_ctl->periodic_wideband_spatial_diffcqi[CC_idP] = (pdu[0]>>4)&7;
      sched_ctl->periodic_wideband_pmi[CC_idP]             = (pdu[0]>>7)&0xF;
    }
    else AssertFatal(1==0,"illegal combination p %d, ri %d, no_pmi %d\n",cc->p_eNB,ri,no_pmi);
  }
  else if (cqi_ReportPeriodic->choice.setup.cqi_FormatIndicatorPeriodic.present == 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) {
Cedric Roux's avatar
Cedric Roux committed
3355
      //7+Ltab[cc->mib->message.dl_Bandwidth] bits;
3356 3357 3358 3359 3360 3361
      sched_ctl->periodic_subband_spatial_diffcqi[CC_idP][(bandwidth_part*L)+((pdu[0]>>7)&Lmask)]  = (pdu[0]>>4)&7;
      sched_ctl->periodic_subband_cqi[CC_idP][(bandwidth_part*L)+((pdu[0]>>7)&Lmask)]              = pdu[0]&0xF;
    }
  }
}

Cedric Roux's avatar
Cedric Roux committed
3362 3363
void extract_pusch_csi(module_id_t mod_idP,int CC_idP,int UE_id, frame_t frameP,sub_frame_t subframeP,uint8_t *pdu, uint8_t length)
{
3364
  UE_list_t *UE_list    = &RC.mac[mod_idP]->UE_list;
Cedric Roux's avatar
Cedric Roux committed
3365
  COMMON_channels_t *cc = &RC.mac[mod_idP]->common_channels[CC_idP];
3366 3367 3368 3369 3370 3371 3372 3373
  UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
  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;
Cedric Roux's avatar
Cedric Roux committed
3374
  int curbyte, curbit;
3375 3376 3377 3378 3379
  CQI_ReportModeAperiodic_t *cqi_ReportModeAperiodic;

  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated != NULL, "physicalConfigDedicated is null for UE %d\n",UE_id);
  AssertFatal(UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig != NULL,"cqi_ReportConfig is null for UE %d\n",UE_id);
  AssertFatal((cqi_ReportModeAperiodic = UE_list->UE_template[CC_idP][UE_id].physicalConfigDedicated->cqi_ReportConfig->cqi_ReportModeAperiodic)!=NULL,
Cedric Roux's avatar
Cedric Roux committed
3380
              "cqi_ReportModeAperiodic is null for UE %d\n",UE_id);
3381

3382
  int N     = Ntab[cc->mib->message.dl_Bandwidth];
3383 3384 3385 3386 3387 3388 3389 3390
  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) {
  case CQI_ReportModeAperiodic_rm12:
Cedric Roux's avatar
Cedric Roux committed
3391
    AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n");
3392 3393 3394
    // wideband multiple PMI (TM4/6), Table 5.2.2.6.1-1 (for TM4/6)
    AssertFatal(tmode==4 || tmode==6 || tmode==8|| tmode==9 || tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm12\n",tmode);
    if (tmode <= 6) { //Table 5.2.2.6.1-1 36.213
Cedric Roux's avatar
Cedric Roux committed
3395 3396 3397 3398 3399 3400
      if ((ri==1) && (cc->p_eNB==2)) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
        for (i=0;i<N;i++) {
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x03);
          p>>=2;
        }
3401
      }
Cedric Roux's avatar
Cedric Roux committed
3402 3403 3404 3405 3406 3407 3408
      if ((ri==2) && (cc->p_eNB==2)) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
        sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
        for (i=0;i<N;i++) {
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01);
          p>>=1;
        }
3409
      }
Cedric Roux's avatar
Cedric Roux committed
3410 3411 3412 3413 3414 3415
      if ((ri==1) && (cc->p_eNB==4)) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
        for (i=0;i<N;i++) {
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x03);
          p>>=4;
        }
3416
      }
Cedric Roux's avatar
Cedric Roux committed
3417 3418 3419 3420 3421 3422 3423
      if ((ri==2) && (cc->p_eNB==4)) {
        sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
        sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
        for (i=0;i<N;i++) {
          sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01);
          p>>=4;
        }
3424 3425 3426 3427 3428 3429 3430 3431
      }
    } // 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");
    }

   break;
  case CQI_ReportModeAperiodic_rm20:
Cedric Roux's avatar
Cedric Roux committed
3432
    AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n");
Cedric Roux's avatar
Cedric Roux committed
3433
    // UE-selected subband CQI no PMI (TM1/2/3/7) , Table 5.2.2.6.3-1 from 36.213
3434 3435 3436 3437 3438 3439 3440 3441 3442
    AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm20\n",tmode);

    sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
    diffcqi0 = (uint8_t)(p&0x03); p>>=2;
    r = (uint8_t)(p&((1>>Ltab_uesel[bw])-1));
    reverse_index(Ntab_uesel[bw],Mtab_uesel[bw],r,v);
    for (m=0;m<Mtab_uesel[bw];m++) sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0;
    break;
  case CQI_ReportModeAperiodic_rm22:
Cedric Roux's avatar
Cedric Roux committed
3443
    AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n");
3444 3445 3446 3447 3448 3449
    // UE-selected subband CQI multiple PMI (TM4/6) Table 5.2.2.6.3-2 from 36.213

    AssertFatal(tmode==4 || tmode==6 || tmode==8|| tmode==9 || tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm22\n",tmode);

    sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
    diffcqi0 = (uint8_t)(p&0x03); p>>=2;
Cedric Roux's avatar
Cedric Roux committed
3450

3451 3452 3453 3454 3455 3456 3457 3458 3459 3460 3461 3462 3463 3464 3465 3466 3467 3468
    if (ri>1) {
      sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
      diffcqi1 = (uint8_t)(p&0x03); p>>=2;
    }
    r = (uint8_t)(p&((1>>Ltab_uesel[bw])-1)); p>>=Ltab_uesel[bw];
    reverse_index(Ntab_uesel[bw],Mtab_uesel[bw],r,v);
    if ((ri==1)&&(cc->p_eNB==2)) {
      pmi_uesel                                  = p&0x3; p>>=2;
      sched_ctl->aperiodic_wideband_pmi[CC_idP]  = p&0x3;
    }
    else if ((ri==2)&&(cc->p_eNB==2)) {
      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;
    }
Cedric Roux's avatar
Cedric Roux committed
3469
    for (m=0;m<Mtab_uesel[bw];m++) {
3470 3471 3472 3473 3474 3475 3476 3477
      sched_ctl->aperiodic_subband_diffcqi0[CC_idP][v[m]] = diffcqi0;
      if (ri>1) sched_ctl->aperiodic_subband_diffcqi1[CC_idP][v[m]] = diffcqi1;
      sched_ctl->aperiodic_subband_pmi[CC_idP][v[m]]      = pmi_uesel;
    }
    break;
  case CQI_ReportModeAperiodic_rm30:
    //subband CQI no PMI (TM1/2/3/7)
    AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm30\n",tmode);
Cedric Roux's avatar
Cedric Roux committed
3478 3479 3480
    sched_ctl->aperiodic_wideband_cqi0[CC_idP] = pdu[0]>>4;
    curbyte = 0;
    curbit = 3;
3481
    for (i=0;i<N;i++) {
Cedric Roux's avatar
Cedric Roux committed
3482 3483 3484 3485 3486 3487
      sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (pdu[curbyte] >> (curbit-1)) & 0x03;
      curbit -= 2;
      if (curbit < 0) {
        curbit = 7;
        curbyte++;
      }
3488
    }
Cedric Roux's avatar
Cedric Roux committed
3489
    sched_ctl->dl_cqi[CC_idP] = sched_ctl->aperiodic_wideband_cqi0[CC_idP];
3490 3491
    break;
  case CQI_ReportModeAperiodic_rm31:
Cedric Roux's avatar
Cedric Roux committed
3492
    AssertFatal(0==1, "to be fixed, don't use p but pdu directly\n");
3493 3494 3495
    //subband CQI single PMI (TM4/5/6)
    AssertFatal(tmode==4 || tmode==5 || tmode==6 || tmode==8|| tmode==9|| tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm31\n",tmode);

Cedric Roux's avatar
Cedric Roux committed
3496
    if ((ri==1) && (cc->p_eNB==2)) {
3497 3498
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
      for (i=0;i<N;i++) {
Cedric Roux's avatar
Cedric Roux committed
3499 3500
        sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t)(p&0x03);
        p>>=2;
3501 3502 3503
      }
      sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x03;
    }
Cedric Roux's avatar
Cedric Roux committed
3504
    if ((ri==2) && (cc->p_eNB==2)) {
3505 3506
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
      for (i=0;i<N;i++) {
Cedric Roux's avatar
Cedric Roux committed
3507 3508
        sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01);
        p>>=1;
3509 3510 3511
      }
      sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
      for (i=0;i<N;i++) {
Cedric Roux's avatar
Cedric Roux committed
3512 3513
        sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01);
        p>>=1;
3514 3515 3516
      }
      sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x01;
    }
Cedric Roux's avatar
Cedric Roux committed
3517
    if ((ri==1) && (cc->p_eNB==4)) {
3518 3519
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
      for (i=0;i<N;i++) {
Cedric Roux's avatar
Cedric Roux committed
3520 3521
        sched_ctl->aperiodic_subband_diffcqi0[CC_idP][i] = (uint8_t)(p&0x03);
        p>>=2;
3522 3523 3524 3525 3526 3527
      }
      sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x0F;
    }
    if ((ri>1) && (cc->p_eNB==4)) { // Note : 64 bits for 20 MHz
      sched_ctl->aperiodic_wideband_cqi0[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
      for (i=0;i<N;i++) {
Cedric Roux's avatar
Cedric Roux committed
3528 3529
        sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01);
        p>>=1;
3530 3531 3532
      }
      sched_ctl->aperiodic_wideband_cqi1[CC_idP] = (uint8_t)(p&0x0F); p>>=4;
      for (i=0;i<N;i++) {
Cedric Roux's avatar
Cedric Roux committed
3533 3534
        sched_ctl->aperiodic_subband_pmi[CC_idP][i] = (uint8_t)(p&0x01);
        p>>=2;
3535 3536 3537
      }
      sched_ctl->aperiodic_wideband_pmi[CC_idP] = p&0x0F;
    }
Cedric Roux's avatar
Cedric Roux committed
3538

3539 3540 3541 3542 3543 3544 3545 3546 3547 3548 3549 3550 3551 3552 3553 3554
    break;
  case CQI_ReportModeAperiodic_rm32_v1250:
    AssertFatal(tmode==4 || tmode==5 || tmode==6 || tmode==8|| tmode==9|| tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm32\n",tmode);
    AssertFatal(1==0,"CQI_ReportModeAperiodic_rm32 to be done\n");
    break;
  case CQI_ReportModeAperiodic_rm10_v1310:
    AssertFatal(tmode==1 || tmode==2 || tmode==3 || tmode==7,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm10\n",tmode);
    AssertFatal(1==0,"CQI_ReportModeAperiodic_rm10 to be done\n");
    break;
  case CQI_ReportModeAperiodic_rm11_v1310:
    AssertFatal(tmode==4 || tmode==5 || tmode==6 || tmode==8|| tmode==9|| tmode==10,"Illegal transmission mode %d for CQI_ReportModeAperiodic_rm11\n",tmode);
    AssertFatal(1==0,"CQI_ReportModeAperiodic_rm11 to be done\n");
    break;
  }
}

Cedric Roux's avatar
Cedric Roux committed
3555 3556 3557 3558
void cqi_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, sub_frame_t subframeP, rnti_t rntiP,
                    nfapi_cqi_indication_rel9_t *rel9,uint8_t *pdu,
                    nfapi_ul_cqi_information_t *ul_cqi_information)
{
3559 3560 3561 3562 3563 3564 3565 3566 3567 3568 3569 3570
  int UE_id = find_UE_id(mod_idP, rntiP);
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
  UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];

  if (UE_id  >= 0) {

    if (ul_cqi_information->channel == 0) { // PUCCH

      // extract pucch csi information before changing RI information
      extract_pucch_csi(mod_idP,CC_idP,UE_id,frameP,subframeP,pdu,rel9->length);

      memcpy((void*)sched_ctl->periodic_ri_received,
Cedric Roux's avatar
Cedric Roux committed
3571 3572
             (void*)rel9->ri,
             rel9->number_of_cc_reported);
3573 3574 3575 3576 3577 3578

      // SNR for PUCCH2
      sched_ctl->pucch2_snr[CC_idP] = ul_cqi_information->ul_cqi;
    }
    else { //PUSCH
      memcpy((void*)sched_ctl->aperiodic_ri_received,
Cedric Roux's avatar
Cedric Roux committed
3579 3580
             (void*)rel9->ri,
             rel9->number_of_cc_reported);
3581 3582

      extract_pusch_csi(mod_idP,CC_idP,UE_id,frameP,subframeP,pdu,rel9->length);
Cedric Roux's avatar
Cedric Roux committed
3583

3584 3585 3586 3587
    }

    // timing advance
    sched_ctl->timing_advance    = rel9->timing_advance;
Cedric Roux's avatar
Cedric Roux committed
3588
    sched_ctl->timing_advance_r9 = rel9->timing_advance_r9;
3589 3590 3591 3592
  }
}

void SR_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, sub_frame_t subframeP, rnti_t rntiP, uint8_t ul_cqi)
3593
{
Cedric Roux's avatar
Cedric Roux committed
3594
  T(T_ENB_MAC_SCHEDULING_REQUEST, T_INT(mod_idP), T_INT(cc_idP), T_INT(frameP), T_INT(subframeP), T_INT(rntiP));
Cedric Roux's avatar
Cedric Roux committed
3595

3596
  int UE_id = find_UE_id(mod_idP, rntiP);
3597
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
Cedric Roux's avatar
Cedric Roux committed
3598

3599
  if (UE_id  != -1) {
3600
    if (mac_eNB_get_rrc_status(mod_idP,UE_RNTI(mod_idP,UE_id)) < RRC_CONNECTED)
3601
      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);
3602 3603 3604 3605 3606 3607

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

    sched_ctl->pucch1_snr[cc_idP]        = ul_cqi;
    sched_ctl->pucch1_cqi_update[cc_idP] = 1;

3608 3609
    UE_list->UE_template[cc_idP][UE_id].ul_SR = 1;
    UE_list->UE_template[cc_idP][UE_id].ul_active = TRUE;
3610 3611
    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);
3612 3613 3614 3615 3616 3617 3618 3619 3620 3621
  } 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);
    LOG_D(MAC,"[eNB %d][SR %x] Frame %d subframeP %d Signaling SR for UE %d (unknown UEid) on CC_id %d\n",mod_idP,rntiP,frameP,subframeP, UE_id,cc_idP);
  }
}

void UL_failure_indication(module_id_t mod_idP, int cc_idP, frame_t frameP, rnti_t rntiP, sub_frame_t subframeP)
{
  int UE_id = find_UE_id(mod_idP, rntiP);
3622
  UE_list_t *UE_list = &RC.mac[mod_idP]->UE_list;
3623 3624

  if (UE_id  != -1) {
Raymond Knopp's avatar
Raymond Knopp committed
3625
    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",
Cedric Roux's avatar
Cedric Roux committed
3626 3627
          mod_idP,UE_id,rntiP,frameP,subframeP, UE_id,cc_idP,
          UE_list->UE_sched_ctrl[UE_id].ul_failure_timer);
kaltenbe's avatar
kaltenbe committed
3628 3629
    if (UE_list->UE_sched_ctrl[UE_id].ul_failure_timer == 0)
      UE_list->UE_sched_ctrl[UE_id].ul_failure_timer=1;
3630 3631 3632 3633 3634 3635
  } 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);
    LOG_W(MAC,"[eNB %d][SR %x] Frame %d subframeP %d Signaling UL Failure for UE %d (unknown UEid) on CC_id %d\n",mod_idP,rntiP,frameP,subframeP, UE_id,cc_idP);
  }
}
3636

Cedric Roux's avatar
Cedric Roux committed
3637 3638
void harq_indication(module_id_t mod_idP, int CC_idP, frame_t frameP, sub_frame_t subframeP, nfapi_harq_indication_pdu_t *harq_pdu)
{
3639 3640 3641 3642 3643 3644 3645 3646
  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);
  UE_list_t *UE_list       = &RC.mac[mod_idP]->UE_list;
  UE_sched_ctrl *sched_ctl = &UE_list->UE_sched_ctrl[UE_id];
  COMMON_channels_t *cc    = &RC.mac[mod_idP]->common_channels[CC_idP];
    // extract HARQ Information
3647
  LOG_D(MAC,"Frame %d, subframe %d: Received harq indication (%d) from UE %d/%x, ul_cqi %d\n",frameP,subframeP,channel,UE_id,rnti,ul_cqi);
3648 3649
  if (cc->tdd_Config) extract_harq(mod_idP,CC_idP,UE_id,frameP,subframeP,(void*)&harq_pdu->harq_indication_tdd_rel13,channel);
  else                extract_harq(mod_idP,CC_idP,UE_id,frameP,subframeP,(void*)&harq_pdu->harq_indication_fdd_rel13,channel);
3650 3651 3652 3653
  if (channel == 0) {
    sched_ctl->pucch1_snr[CC_idP]       = ul_cqi;
    sched_ctl->pucch1_cqi_update[CC_idP] = 1;
  }
3654
}