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

22 23 24 25 26 27 28 29 30 31
/*! \file phy_procedures_lte_eNB.c
* \brief Implementation of common utilities for eNB/UE procedures from 36.213 LTE specifications
* \author R. Knopp, F. Kaltenberger
* \date 2011
* \version 0.1
* \company Eurecom
* \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr
* \note
* \warning
*/
32 33
#include "PHY/defs_eNB.h"
#include "PHY/defs_UE.h"
34
#include "SCHED/sched_common_extern.h"
35
#include "PHY/LTE_TRANSPORT/transport_common_proto.h"
36 37

void get_Msg3_alloc(LTE_DL_FRAME_PARMS *frame_parms,
38 39 40 41 42
                    unsigned char current_subframe,
                    unsigned int current_frame,
                    unsigned int *frame,
                    unsigned char *subframe)
{
43 44 45 46 47

  // Fill in other TDD Configuration!!!!

  if (frame_parms->frame_type == FDD) {
    *subframe = current_subframe+6;
48

49 50
    if (*subframe>9) {
      *subframe = *subframe-10;
51
      *frame = (current_frame+1) & 1023;
52
    } else {
53 54
      *frame=current_frame;
    }
55
  } else { // TDD
56 57
    if (frame_parms->tdd_config == 1) {
      switch (current_subframe) {
58

59
      case 0:
60 61 62 63
        *subframe = 7;
        *frame = current_frame;
        break;

64
      case 4:
65
        *subframe = 2;
66
        *frame = (current_frame+1) & 1023;
67 68
        break;

69
      case 5:
70
        *subframe = 2;
71
        *frame = (current_frame+1) & 1023;
72 73
        break;

74
      case 9:
75
        *subframe = 7;
76
        *frame = (current_frame+1) & 1023;
77
        break;
78
      }
79
    } else if (frame_parms->tdd_config == 3) {
80
      switch (current_subframe) {
81

82 83 84
      case 0:
      case 5:
      case 6:
85
        *subframe = 2;
86
        *frame = (current_frame+1) & 1023;
87 88
        break;

89
      case 7:
90
        *subframe = 3;
91
        *frame = (current_frame+1) & 1023;
92 93
        break;

94
      case 8:
95
        *subframe = 4;
96
        *frame = (current_frame+1) & 1023;
97 98
        break;

99
      case 9:
100
        *subframe = 2;
101
        *frame = (current_frame+2) & 1023;
102
        break;
103
      }
104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144
    } else if (frame_parms->tdd_config == 4) {
        switch (current_subframe) {

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

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

        case 8:
        case 9:
          *subframe = 2;
          *frame = (current_frame+2) & 1023;
          break;
        }
      } else if (frame_parms->tdd_config == 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;
          }
        }
145 146 147 148
  }
}

void get_Msg3_alloc_ret(LTE_DL_FRAME_PARMS *frame_parms,
149 150 151 152 153
                        unsigned char current_subframe,
                        unsigned int current_frame,
                        unsigned int *frame,
                        unsigned char *subframe)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
154
  if (frame_parms->frame_type == FDD) {
roux's avatar
roux committed
155 156
    /* always retransmit in n+8 */
    *subframe = current_subframe + 8;
157

roux's avatar
roux committed
158 159 160
    if (*subframe > 9) {
      *subframe = *subframe - 10;
      *frame = (current_frame + 1) & 1023;
161
    } else {
roux's avatar
roux committed
162
      *frame = current_frame;
163
    }
164
  } else {
165 166 167 168 169
    if (frame_parms->tdd_config == 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
170
      *frame = (current_frame+1) & 1023;
171
    } else if (frame_parms->tdd_config == 3) {
172 173 174
      // 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
175
      *frame=(current_frame+1) & 1023;
176 177 178 179 180 181 182
    } else if (frame_parms->tdd_config == 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 (frame_parms->tdd_config == 5) {
        // original PUSCH in 2, PHICH in 8, ret in 2 next frame
        *frame=(current_frame+1) & 1023;
183 184 185 186
    }
  }
}

187
uint8_t get_Msg3_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,
188 189 190
                          uint32_t frame,
                          unsigned char current_subframe)
{
191

192
  uint8_t ul_subframe=0;
193
  uint32_t ul_frame=0;
194

Raymond Knopp's avatar
 
Raymond Knopp committed
195
  if (frame_parms->frame_type ==FDD) {
196
    ul_subframe = (current_subframe>3) ? (current_subframe-4) : (current_subframe+6);
197
    ul_frame    = (current_subframe>3) ? ((frame+1)&1023) : frame;
198
  } else {
199 200 201 202 203 204
    switch (frame_parms->tdd_config) {
    case 1:
      switch (current_subframe) {

      case 9:
      case 0:
205 206 207
        ul_subframe = 7;
        break;

208 209
      case 5:
      case 7:
210 211
        ul_subframe = 2;
        break;
212 213

      }
214

215
      break;
216

217 218 219 220 221 222
    case 3:
      switch (current_subframe) {

      case 0:
      case 5:
      case 6:
223 224 225
        ul_subframe = 2;
        break;

226
      case 7:
227 228 229
        ul_subframe = 3;
        break;

230
      case 8:
231 232 233
        ul_subframe = 4;
        break;

234
      case 9:
235 236
        ul_subframe = 2;
        break;
237
      }
238

239
      break;
240

241 242 243 244 245 246 247 248
    case 4:
      switch (current_subframe) {

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

252
      case 7:
253 254
        ul_subframe = 3;
        break;
255
      }
256

257
      break;
258

259 260 261
    case 5:
      ul_subframe =2;
      break;
262

263 264
    default:
      LOG_E(PHY,"get_Msg3_harq_pid: Unsupported TDD configuration %d\n",frame_parms->tdd_config);
265
      AssertFatal(1==0,"get_Msg3_harq_pid: Unsupported TDD configuration");
266 267 268
      break;
    }
  }
269

270 271 272 273
  return(subframe2harq_pid(frame_parms,ul_frame,ul_subframe));

}

274 275
unsigned char ul_ACK_subframe2_dl_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe,unsigned char ACK_index)
{
276

Raymond Knopp's avatar
 
Raymond Knopp committed
277
  if (frame_parms->frame_type == FDD) {
278
    return((subframe<4) ? subframe+6 : subframe-4);
279
  } else {
280 281 282
    switch (frame_parms->tdd_config) {
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
283 284 285 286 287 288 289 290 291 292 293 294
        if (ACK_index==2)
          return(1);

        return(5+ACK_index);
      } else if (subframe == 3) { // ACK subframes 7 and 8
        return(7+ACK_index);  // To be updated
      } else if (subframe == 4) { // ACK subframes 9 and 0
        return((9+ACK_index)%10);
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
295
      }
296

297
      break;
298

299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316
    case 4:
          if (subframe == 2) {  // ACK subframes 0, 4 and 5
            //if (ACK_index==2)
            //  return(1); TBC
            if (ACK_index==2)
            return(0);

            return(4+ACK_index);
          } else if (subframe == 3) { // ACK subframes 6, 7 8 and 9
            return(6+ACK_index);  // To be updated
          } else {
            LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
                  subframe,frame_parms->tdd_config);
            return(0);
          }

          break;

317 318
    case 1:
      if (subframe == 2) {  // ACK subframes 5 and 6
319 320 321 322 323 324 325 326 327 328 329
        return(5+ACK_index);
      } else if (subframe == 3) { // ACK subframe 9
        return(9);  // To be updated
      } else if (subframe == 7) { // ACK subframes 0 and 1
        return(ACK_index);  // To be updated
      } else if (subframe == 8) { // ACK subframe 4
        return(4);  // To be updated
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/ul_ACK_subframe2_dl_subframe: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
330
      }
331

332 333 334
      break;
    }
  }
335

336 337 338
  return(0);
}

339
int ul_ACK_subframe2_dl_frame(LTE_DL_FRAME_PARMS *frame_parms,int frame, unsigned char subframe,unsigned char subframe_tx)
340 341 342 343 344 345
{

  if (frame_parms->frame_type == FDD) {
    return (((subframe_tx > subframe ) ? frame-1 : frame)+1024)%1024;
  } else {
    switch (frame_parms->tdd_config) {
346 347 348
    case 1:
      return(((subframe_tx > subframe ) ? frame-1 : frame)+1024)%1024;
      break;
349 350 351 352 353 354 355 356 357 358 359 360 361
    case 3:
        //TODO
      break;
    case 4:
        //TODO
      break;
    }
  }

  return(0);
}


362 363
unsigned char ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
364

Raymond Knopp's avatar
 
Raymond Knopp committed
365
  if (frame_parms->frame_type == FDD) {
366
    return(1);
367
  } else {
368
    switch (frame_parms->tdd_config) {
369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385
    case 1:
        return 1; // don't ACK special subframe for now
      if (subframe == 2) {  // ACK subframes 5 and 6
        return(2);
      } else if (subframe == 3) { // ACK subframe 9
        return(1);  // To be updated
      } else if (subframe == 7) { // ACK subframes 0 and 1
        return(2);  // To be updated
      } else if (subframe == 8) { // ACK subframe 4
        return(1);  // To be updated
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
      }

      break;
386 387
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
388 389 390 391 392 393 394 395 396
        return(2); // should be 3
      } else if (subframe == 3) { // ACK subframes 7 and 8
        return(2);  // To be updated
      } else if (subframe == 4) { // ACK subframes 9 and 0
        return(2);
      } else {
        LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
397
      }
398

399
      break;
400

401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
    case 4:
          if (subframe == 2) {  // ACK subframes 0,4 and 5
            return(3); // should be 4
          } else if (subframe == 3) { // ACK subframes 6,7,8 and 9
            return(4);
          } else {
            LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
                  subframe,frame_parms->tdd_config);
            return(0);
          }

          break;

    case 5:
              if (subframe == 2) {  // ACK subframes 0,3,4,5,6,7,8 and 9
                return(8); // should be 3
              } else {
                LOG_E(PHY,"phy_procedures_lte_common.c/subframe2_dl_harq_pid: illegal subframe %d for tdd_config %d\n",
                      subframe,frame_parms->tdd_config);
                return(0);
              }

              break;
424 425
    }
  }
426

427 428 429 430
  return(0);
}

// This function implements table 10.1-1 of 36-213, p. 69
431 432
// return the number 'Nbundled'
uint8_t get_reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
433
                harq_status_t *harq_ack,
hbilel's avatar
hbilel committed
434 435
                unsigned char subframe_tx,
                unsigned char subframe_rx,
436
                unsigned char *o_ACK,
hbilel's avatar
hbilel committed
437
                uint8_t *pN_bundled,
438
                uint8_t cw_idx,
439
                uint8_t do_reset) // 1 to reset ACK/NACK status : 0 otherwise
440
{
441
  uint8_t status=0;
442
  uint8_t subframe_ul=0xff, subframe_dl0=0xff, subframe_dl1=0xff,subframe_dl2=0xff, subframe_dl3=0xff;
443

Raymond Knopp's avatar
 
Raymond Knopp committed
444
  //  printf("get_ack: SF %d\n",subframe);
445
  if (frame_parms->frame_type == FDD) {
hbilel's avatar
hbilel committed
446 447
    if (subframe_tx < 4)
      subframe_dl0 = subframe_tx + 6;
448
    else
hbilel's avatar
hbilel committed
449
      subframe_dl0 = subframe_tx - 4;
450

451
    o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;
452
    status = harq_ack[subframe_dl0].send_harq_status;
453

454
    LOG_D(PHY,"dl subframe %d send_harq_status %d cw_idx %d, reset %d\n",subframe_dl0, status, cw_idx, do_reset);
455 456
    if(do_reset)
    	harq_ack[subframe_dl0].send_harq_status = 0;
457
    //printf("get_ack: Getting ACK/NAK for PDSCH (subframe %d) => %d\n",subframe_dl,o_ACK[0]);
458
  } else {
459 460
    switch (frame_parms->tdd_config) {
    case 1:
hbilel's avatar
hbilel committed
461
      if (subframe_tx == 2) {  // ACK subframes 5,6
462 463 464
        subframe_ul  = 6;
        subframe_dl0 = 5;
        subframe_dl1 = 6;
hbilel's avatar
hbilel committed
465
      } else if (subframe_tx == 3) { // ACK subframe 9
466 467 468
        subframe_ul  = 9;
        subframe_dl0 = 9;
        subframe_dl1 = 0xff;
hbilel's avatar
hbilel committed
469
      } else if (subframe_tx == 4) { // nothing
470 471 472
        subframe_ul  = 0xff;
        subframe_dl0 = 0xff; // invalid subframe number indicates ACK/NACK is not needed
        subframe_dl1 = 0xff;
hbilel's avatar
hbilel committed
473
      } else if (subframe_tx == 7) { // ACK subframes 0,1
474 475 476
        subframe_ul  = 1;
        subframe_dl0 = 0;
        subframe_dl1 = 1;
hbilel's avatar
hbilel committed
477
      } else if (subframe_tx == 8) { // ACK subframes 4
478 479 480
        subframe_ul  = 4;
        subframe_dl0 = 4;
        subframe_dl1 = 0xff;
481
      } else {
hbilel's avatar
hbilel committed
482 483
        LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
              subframe_tx,frame_parms->tdd_config);
484
        return(0);
485
      }
486

487
      // report ACK/NACK status
488
      o_ACK[cw_idx] = 1;
489 490
      status = 0;
      if ((subframe_dl0 < 10) && (harq_ack[subframe_dl0].send_harq_status)) {
491
        o_ACK[cw_idx] &= harq_ack[subframe_dl0].ack;
492 493 494
        status = harq_ack[subframe_dl0].send_harq_status;
      }
      if ((subframe_dl1 < 10) && (harq_ack[subframe_dl1].send_harq_status)) {
495
        o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;
496 497 498 499
        status = harq_ack[subframe_dl1].send_harq_status;
      }
      // report status = Nbundled
      if (!status) {
500
        o_ACK[cw_idx] = 0;
501 502 503 504 505 506 507 508 509
      } else {
        if (harq_ack[subframe_ul].vDAI_UL < 0xff) {
          status = harq_ack[subframe_ul].vDAI_UL;
        }
      }

      if (!do_reset && (subframe_ul < 10)) {
        if ((subframe_dl0 < 10) && (subframe_dl1 < 10)) {
          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, dlsf#%d ACK=%d harq_status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
hbilel's avatar
hbilel committed
510
              subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
511 512
              subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL,
              subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL,
513
              o_ACK[cw_idx], status);
514 515
        } else if (subframe_dl0 < 10) {
          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
hbilel's avatar
hbilel committed
516
              subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
517
              subframe_dl0, harq_ack[subframe_dl0].ack, harq_ack[subframe_dl0].send_harq_status, harq_ack[subframe_dl0].vDAI_DL,
518
              o_ACK[cw_idx], status);
519 520
        }else if (subframe_dl1 < 10) {
          LOG_D(PHY,"ul-sf#%d vDAI_UL[sf#%d]=%d Nbundled=%d: dlsf#%d ACK=%d status=%d vDAI_DL=%d, o_ACK[0]=%d status=%d\n",
hbilel's avatar
hbilel committed
521
              subframe_tx, subframe_ul, harq_ack[subframe_ul].vDAI_UL, status,
522
              subframe_dl1, harq_ack[subframe_dl1].ack, harq_ack[subframe_dl1].send_harq_status, harq_ack[subframe_dl1].vDAI_DL,
523
              o_ACK[cw_idx], status);
524 525 526 527 528
        }
      }

      // reset ACK/NACK status
      if (do_reset) {
hbilel's avatar
hbilel committed
529
        LOG_D(PHY,"ul-sf#%d ACK/NACK status resetting @ dci0-sf#%d, dci1x/2x-sf#%d, dci1x/2x-sf#%d\n", subframe_tx, subframe_ul, subframe_dl0, subframe_dl1);
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
        if (subframe_ul < 10) {
          harq_ack[subframe_ul].vDAI_UL = 0xff;
        }
        if (subframe_dl0 < 10) {
          harq_ack[subframe_dl0].vDAI_DL = 0xff;
          harq_ack[subframe_dl0].ack = 2;
          harq_ack[subframe_dl0].send_harq_status = 0;
        }
        if (subframe_dl1 < 10) {
          harq_ack[subframe_dl1].vDAI_DL = 0xff;
          harq_ack[subframe_dl1].ack = 2;
          harq_ack[subframe_dl1].send_harq_status = 0;
        }
      }

545
      break;
546

547
    case 3:
hbilel's avatar
hbilel committed
548
      if (subframe_tx == 2) {  // ACK subframes 5 and 6
549 550
        subframe_dl0 = 5;
        subframe_dl1 = 6;
hbilel's avatar
hbilel committed
551 552 553
        subframe_ul  = 2;
        //printf("subframe_tx 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status);
      } else if (subframe_tx == 3) { // ACK subframes 7 and 8
554 555
        subframe_dl0 = 7;
        subframe_dl1 = 8;
hbilel's avatar
hbilel committed
556
        subframe_ul  = 3;
557 558
        //printf("Subframe 3, TDD config 3: harq_ack[7] = %d,harq_ack[8] = %d\n",harq_ack[7].ack,harq_ack[8].ack);
        //printf("status %d : o_ACK (%d,%d)\n", status,o_ACK[0],o_ACK[1]);
hbilel's avatar
hbilel committed
559
      } else if (subframe_tx == 4) { // ACK subframes 9 and 0
560 561
        subframe_dl0 = 9;
        subframe_dl1 = 0;
hbilel's avatar
hbilel committed
562
        subframe_ul  = 4;
563 564
        //printf("Subframe 4, TDD config 3: harq_ack[9] = %d,harq_ack[0] = %d\n",harq_ack[9].ack,harq_ack[0].ack);
      } else {
hbilel's avatar
hbilel committed
565 566
        LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
              subframe_tx,frame_parms->tdd_config);
567
        return(0);
568
      }
569

570
      // report ACK/NACK status
hbilel's avatar
hbilel committed
571
      o_ACK[cw_idx] = 0;
572
      if (harq_ack[subframe_dl0].send_harq_status == 1) {
gabrielC's avatar
gabrielC committed
573
        o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;
574 575

        if (harq_ack[subframe_dl1].send_harq_status == 1)
gabrielC's avatar
gabrielC committed
576
          o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;
577
      } else if (harq_ack[subframe_dl1].send_harq_status == 1)
gabrielC's avatar
gabrielC committed
578
        o_ACK[cw_idx] = harq_ack[subframe_dl1].ack;
579

hbilel's avatar
hbilel committed
580
      pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL;
hbilel's avatar
hbilel committed
581
      status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status;
582

583 584 585
      //LOG_D(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d subframe_rx %d N_bundled %d \n",
      //	  subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack,
      //    subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack, subframe_rx, pN_bundled[0]);
586 587 588 589 590 591 592 593
      if (do_reset) {
        // reset ACK/NACK status
        harq_ack[subframe_dl0].ack = 2;
        harq_ack[subframe_dl1].ack = 2;
        harq_ack[subframe_dl0].send_harq_status = 0;
        harq_ack[subframe_dl1].send_harq_status = 0;
      }

594
      break;
595

596 597
    case 4:
          if (subframe_tx == 2) {  // ACK subframes 4, 5 and 0
hbilel's avatar
hbilel committed
598 599 600
            subframe_dl0 = 0;
            subframe_dl1 = 4;
            subframe_dl2 = 5;
601 602 603
            subframe_ul  = 2;
            //printf("subframe_tx 2, TDD config 3: harq_ack[5] = %d (%d),harq_ack[6] = %d (%d)\n",harq_ack[5].ack,harq_ack[5].send_harq_status,harq_ack[6].ack,harq_ack[6].send_harq_status);
          } else if (subframe_tx == 3) { // ACK subframes 6, 7 8 and 9
hbilel's avatar
hbilel committed
604 605 606 607
            subframe_dl0 = 7;
            subframe_dl1 = 8;
            subframe_dl2 = 9;
            subframe_dl3 = 6;
608 609 610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633
            subframe_ul  = 3;
            //printf("Subframe 3, TDD config 3: harq_ack[7] = %d,harq_ack[8] = %d\n",harq_ack[7].ack,harq_ack[8].ack);
            //printf("status %d : o_ACK (%d,%d)\n", status,o_ACK[0],o_ACK[1]);
          } else {
            LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe_tx %d for tdd_config %d\n",
                  subframe_tx,frame_parms->tdd_config);
            return(0);
          }

          // report ACK/NACK status
          o_ACK[cw_idx] = 0;
          if (harq_ack[subframe_dl0].send_harq_status == 1)
            o_ACK[cw_idx] = harq_ack[subframe_dl0].ack;

          if (harq_ack[subframe_dl1].send_harq_status == 1)
            o_ACK[cw_idx] &= harq_ack[subframe_dl1].ack;

          if (harq_ack[subframe_dl2].send_harq_status == 1)
            o_ACK[cw_idx] &= harq_ack[subframe_dl2].ack;

          if (harq_ack[subframe_dl3].send_harq_status == 1)
            o_ACK[cw_idx] &= harq_ack[subframe_dl3].ack;

          pN_bundled[0] = harq_ack[subframe_rx].vDAI_UL;
          status = harq_ack[subframe_dl0].send_harq_status + harq_ack[subframe_dl1].send_harq_status + harq_ack[subframe_dl2].send_harq_status + harq_ack[subframe_dl3].send_harq_status;

634
          LOG_D(PHY,"TDD Config3 UL Sfn %d, dl Sfn0 %d status %d o_Ack %d, dl Sfn1 %d status %d o_Ack %d dl Sfn2 %d status %d o_Ack %d dl Sfn3 %d status %d o_Ack %d subframe_rx %d N_bundled %d status %d\n",
635 636 637 638 639 640 641 642 643 644 645 646 647 648 649 650 651 652
                subframe_tx, subframe_dl0, harq_ack[subframe_dl0].send_harq_status,harq_ack[subframe_dl0].ack,
              subframe_dl1, harq_ack[subframe_dl1].send_harq_status,harq_ack[subframe_dl1].ack,
              subframe_dl2, harq_ack[subframe_dl2].send_harq_status,harq_ack[subframe_dl2].ack,
              subframe_dl3, harq_ack[subframe_dl3].send_harq_status,harq_ack[subframe_dl3].ack,subframe_rx, pN_bundled[0], status);
          if (do_reset) {
            // reset ACK/NACK status
            harq_ack[subframe_dl0].ack = 2;
            harq_ack[subframe_dl1].ack = 2;
            harq_ack[subframe_dl2].ack = 2;
            harq_ack[subframe_dl3].ack = 2;
            harq_ack[subframe_dl0].send_harq_status = 0;
            harq_ack[subframe_dl1].send_harq_status = 0;
            harq_ack[subframe_dl2].send_harq_status = 0;
            harq_ack[subframe_dl3].send_harq_status = 0;
          }

          break;

653 654
    }
  }
655

656 657 658 659 660
  //printf("status %d\n",status);

  return(status);
}

661 662
uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
                harq_status_t *harq_ack,
hbilel's avatar
hbilel committed
663 664
                unsigned char subframe_tx,
                unsigned char subframe_rx,
665 666
                unsigned char *o_ACK,
                uint8_t cw_idx)
667
{
hbilel's avatar
hbilel committed
668 669
    uint8_t N_bundled = 0;
  return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, &N_bundled, cw_idx, 0);
670 671 672 673
}

uint8_t reset_ack(LTE_DL_FRAME_PARMS *frame_parms,
                harq_status_t *harq_ack,
hbilel's avatar
hbilel committed
674 675
                unsigned char subframe_tx,
                unsigned char subframe_rx,
676
                unsigned char *o_ACK,
hbilel's avatar
hbilel committed
677
                uint8_t *pN_bundled,
678
                uint8_t cw_idx)
679
{
hbilel's avatar
hbilel committed
680
  return get_reset_ack(frame_parms, harq_ack, subframe_tx, subframe_rx, o_ACK, pN_bundled, cw_idx, 1);
681 682 683 684
}



685 686 687 688 689 690
uint8_t Np6[4]= {0,1,3,5};
uint8_t Np15[4]= {0,3,8,13};
uint8_t Np25[4]= {0,5,13,22};
uint8_t Np50[4]= {0,11,27,44};
uint8_t Np75[4]= {0,16,41,66};
uint8_t Np100[4]= {0,22,55,88};
691
// This is part of the PUCCH allocation procedure (see Section 10.1 36.213)
692 693
uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1)
{
694
  uint8_t *Np;
695

696
  switch (N_RB_DL) {
697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725
  case 6:
    Np=Np6;
    break;

  case 15:
    Np=Np15;
    break;

  case 25:
    Np=Np25;
    break;

  case 50:
    Np=Np50;
    break;

  case 75:
    Np=Np75;
    break;

  case 100:
    Np=Np100;
    break;

  default:
    LOG_E(PHY,"get_Np() FATAL: unsupported N_RB_DL %d\n",N_RB_DL);
    return(0);
    break;
  }
726 727 728 729 730 731 732 733 734

  if (nCCE>=Np[2])
    return(Np[2+plus1]);
  else if (nCCE>=Np[1])
    return(Np[1+plus1]);
  else
    return(Np[0+plus1]);
}

735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754
int subframe_num(LTE_DL_FRAME_PARMS *frame_parms){
    if (frame_parms->frame_type == FDD)
        return 10;

    switch (frame_parms->tdd_config) {
    case 1:
        return 6;
    case 3:
        return 7;
    case 4:
        return 8;
    case 5:
        return 9;
    default:
      LOG_E(PHY,"Unsupported TDD configuration %d\n",frame_parms->tdd_config);
      AssertFatal(frame_parms->tdd_config==1 || frame_parms->tdd_config==3 || frame_parms->tdd_config==4 || frame_parms->tdd_config==5,"subframe x Unsupported TDD configuration");
      return(255);
    }
}

755 756
lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,
		                       unsigned char subframe)
757
{
758
  // if FDD return dummy value
Raymond Knopp's avatar
 
Raymond Knopp committed
759
  if (frame_parms->frame_type == FDD)
760 761 762 763 764 765 766 767 768 769 770 771
    return(SF_DL);

  switch (frame_parms->tdd_config) {

  case 1:
    switch (subframe) {
    case 0:
    case 4:
    case 5:
    case 9:
      return(SF_DL);
      break;
772

773 774 775 776 777 778
    case 2:
    case 3:
    case 7:
    case 8:
      return(SF_UL);
      break;
779

780 781 782 783
    default:
      return(SF_S);
      break;
    }
784

785
  case 3:
786
    if  ((subframe<1) || (subframe>=5))
787
      return(SF_DL);
788
    else if ((subframe>1) && (subframe < 5))
789 790 791 792 793 794 795
      return(SF_UL);
    else if (subframe==1)
      return (SF_S);
    else  {
      LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
      return(255);
    }
796

797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819
  case 4:
      if  ((subframe<1) || (subframe>=4))
        return(SF_DL);
      else if ((subframe>1) && (subframe < 4))
        return(SF_UL);
      else if (subframe==1)
        return (SF_S);
      else  {
        LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
        return(255);
      }

  case 5:
        if  ((subframe<1) || (subframe>=3))
          return(SF_DL);
        else if ((subframe>1) && (subframe < 3))
          return(SF_UL);
        else if (subframe==1)
          return (SF_S);
        else  {
          LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
          return(255);
        }
820
    break;
821

822
  default:
823

824
    AssertFatal(1==0,"subframe %d Unsupported TDD configuration %d\n",subframe,frame_parms->tdd_config);
825
    return(255);
826

827 828 829
  }
}

830 831 832 833 834 835 836 837 838 839 840 841 842 843 844 845 846 847 848 849 850 851 852 853 854 855 856 857
dci_detect_mode_t dci_detect_mode_select(LTE_DL_FRAME_PARMS *frame_parms,uint8_t subframe)
{
  dci_detect_mode_t ret = 0;

  static dci_detect_mode_t Table_8_2_3gpp_36_213[][10] = {
     //subf0    , subf1     , subf2 , subf3         , subf4     , subf5     , subf6     , subf7 , subf8     , subf9
      {UL_DL_DCI, UL_DL_DCI , NO_DCI    , NO_DCI    , NO_DCI    , UL_DL_DCI , UL_DL_DCI , NO_DCI, NO_DCI    , NO_DCI    },  // tdd0
      {DL_DCI   , UL_DL_DCI , NO_DCI    , NO_DCI    , UL_DL_DCI , DL_DCI    , UL_DL_DCI , NO_DCI, NO_DCI    , UL_DL_DCI },  // tdd1
      {DL_DCI   , DL_DCI    , NO_DCI    , UL_DL_DCI , DL_DCI    , DL_DCI    , DL_DCI    , NO_DCI, UL_DL_DCI , DL_DCI    },  // tdd2
      {UL_DL_DCI, DL_DCI    , NO_DCI    , NO_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , UL_DL_DCI },  // tdd3
      {DL_DCI   , DL_DCI    , NO_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , UL_DL_DCI },  // tdd4
      {DL_DCI   , DL_DCI    , NO_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI    , DL_DCI, UL_DL_DCI , DL_DCI    },  // tdd5
      {UL_DL_DCI, UL_DL_DCI , NO_DCI    , NO_DCI    , NO_DCI    , UL_DL_DCI , UL_DL_DCI , NO_DCI, NO_DCI    , UL_DL_DCI }}; // tdd6


  DevAssert(subframe>=0 && subframe<=9);
  DevAssert((frame_parms->tdd_config)>=0 && (frame_parms->tdd_config)<=6);

  if (frame_parms->frame_type == FDD) {
    ret = UL_DL_DCI;
  } else {
    ret = Table_8_2_3gpp_36_213[frame_parms->tdd_config][subframe];
  }

  LOG_D(PHY, "subframe %d: detect UL_DCI=%d, detect DL_DCI=%d\n", subframe, (ret & UL_DCI)>0, (ret & DL_DCI)>0);
  return ret;
}

858 859


860 861
uint8_t phich_subframe_to_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe)
{
862

Raymond Knopp's avatar
Raymond Knopp committed
863
  LOG_D(PHY,"phich_subframe_to_harq_pid.c: frame %d, subframe %d\n",frame,subframe);
864
  return(subframe2harq_pid(frame_parms,
865 866
                           phich_frame2_pusch_frame(frame_parms,frame,subframe),
                           phich_subframe2_pusch_subframe(frame_parms,subframe)));
867 868
}

869 870
unsigned int is_phich_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
871

Raymond Knopp's avatar
 
Raymond Knopp committed
872
  if (frame_parms->frame_type == FDD) {
873
    return(1);
874
  } else {
875 876 877
    switch (frame_parms->tdd_config) {
    case 1:
      if ((subframe == 1) || (subframe == 4) || (subframe == 6) || (subframe == 9))
878 879
        return(1);

880
      break;
881

882 883
    case 3:
      if ((subframe == 0) || (subframe == 8) || (subframe == 9))
884 885
        return(1);

886
      break;
887

888
    case 4:
889
      if ((subframe == 8) || (subframe == 9) )
890 891
        return(1);

892
      break;
893

894
    case 5:
895
      if (subframe == 8)
896 897
        return(1);

898
      break;
899

900 901 902 903 904
    default:
      return(0);
      break;
    }
  }
905

906 907 908 909
  return(0);
}


910

911
/*
912
LTE_eNB_UE_stats* get_UE_stats(uint8_t Mod_id, uint8_t  CC_id,uint16_t rnti)
913
{
914
  int8_t UE_id;
915

916
  if ((RC.eNB == NULL) || (Mod_id > RC.nb_inst) || (CC_id > RC.nb_CC[Mod_id])) {
917
    LOG_E(PHY,"get_UE_stats: No eNB found (or not allocated) for Mod_id %d,CC_id %d\n",Mod_id,CC_id);
918 919
    return NULL;
  }
920

921
  UE_id = find_ue(rnti, RC.eNB[Mod_id][CC_id]);
922

923
  if (UE_id == -1) {
924
    //    LOG_E(PHY,"get_UE_stats: UE with rnti %x not found\n",rnti);
925 926
    return NULL;
  }
927

928
  return(&RC.eNB[Mod_id][CC_id]->UE_stats[(uint32_t)UE_id]);
929
}
930
*/
931

932
/*
933 934
LTE_DL_FRAME_PARMS* get_lte_frame_parms(module_id_t Mod_id, uint8_t  CC_id)
{
935

936
  return(&RC.eNB[Mod_id][CC_id]->frame_parms);
937 938 939

}

940 941
MU_MIMO_mode *get_mu_mimo_mode (module_id_t Mod_id, uint8_t  CC_id, rnti_t rnti)
{
942
  int8_t UE_id = find_ue( rnti, RC.eNB[Mod_id][CC_id] );
943

944
  if (UE_id == -1)
945 946
    return 0;

947
  return &RC.eNB[Mod_id][CC_id]->mu_mimo_mode[UE_id];
948
}
949
*/
950 951 952 953 954 955 956 957 958 959

int is_srs_occasion_common(LTE_DL_FRAME_PARMS *frame_parms,int frame_tx,int subframe_tx)
{
  uint8_t isSubframeSRS   = 0; // SRS Cell Occasion

  //ue->ulsch[eNB_id]->srs_active   = 0;
  //ue->ulsch[eNB_id]->Nsymb_pusch  = 12-(frame_parms->Ncp<<1)- ue->ulsch[eNB_id]->srs_active;
  if(frame_parms->soundingrs_ul_config_common.enabled_flag)
  {

960
    //LOG_D(PHY," SRS SUBFRAMECONFIG: %d\n", frame_parms->soundingrs_ul_config_common.srs_SubframeConfig);
961 962 963 964 965 966 967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992

      uint8_t  TSFC;
      uint16_t deltaTSFC; // bitmap
      uint8_t  srs_SubframeConfig;

      // table resuming TSFC (Period) and deltaSFC (offset)
      const uint16_t deltaTSFCTabType1[15][2] = { {1,1},{1,2},{2,2},{1,5},{2,5},{4,5},{8,5},{3,5},{12,5},{1,10},{2,10},{4,10},{8,10},{351,10},{383,10} };      // Table 5.5.3.3-2 3GPP 36.211 FDD
      const uint16_t deltaTSFCTabType2[14][2] = { {2,5},{6,5},{10,5},{18,5},{14,5},{22,5},{26,5},{30,5},{70,10},{74,10},{194,10},{326,10},{586,10},{210,10} }; // Table 5.5.3.3-2 3GPP 36.211 TDD

      srs_SubframeConfig = frame_parms->soundingrs_ul_config_common.srs_SubframeConfig;
      if (FDD == frame_parms->frame_type)
      {
          // srs_SubframeConfig =< 14
          deltaTSFC = deltaTSFCTabType1[srs_SubframeConfig][0];
          TSFC      = deltaTSFCTabType1[srs_SubframeConfig][1];
      }
      else
      {
          // srs_SubframeConfig =< 13
          deltaTSFC = deltaTSFCTabType2[srs_SubframeConfig][0];
          TSFC      = deltaTSFCTabType2[srs_SubframeConfig][1];
      }

      // Sounding reference signal subframes are the subframes satisfying ns/2 mod TSFC (- deltaTSFC
      uint16_t tmp = (subframe_tx %  TSFC);
      if((1<<tmp) & deltaTSFC)
      {
          // This is a Sounding reference signal subframes
          isSubframeSRS = 1;
      }
      LOG_D(PHY," ISTDD: %d, TSFC: %d, deltaTSFC: %d, AbsSubframeTX: %d.%d\n", frame_parms->frame_type, TSFC, deltaTSFC, frame_tx, subframe_tx);
  }
993
  //LOG_D(PHY," isSubframeSRS %d\n", isSubframeSRS);
994 995 996 997 998 999 1000
  return(isSubframeSRS);
}

void compute_srs_pos(lte_frame_type_t frameType,uint16_t isrs,uint16_t *psrsPeriodicity,uint16_t *psrsOffset)
{
    if(TDD == frameType)
    {
1001
      AssertFatal(isrs>=10,"2 ms SRS periodicity not supported");
1002

1003
      if((isrs>9)&&(isrs<15))
1004
        {
1005 1006
	  *psrsPeriodicity=5;
	  *psrsOffset=isrs-10;
1007
        }
1008
      if((isrs>14)&&(isrs<25))
1009
        {
1010 1011
	  *psrsPeriodicity=10;
	  *psrsOffset=isrs-15;
1012
        }
1013
      if((isrs>24)&&(isrs<45))
1014
        {
1015 1016
	  *psrsPeriodicity=20;
	  *psrsOffset=isrs-25;
1017
        }
1018
      if((isrs>44)&&(isrs<85))
1019
        {
1020 1021
	  *psrsPeriodicity=40;
	  *psrsOffset=isrs-45;
1022
        }
1023
      if((isrs>84)&&(isrs<165))
1024
        {
1025 1026
	  *psrsPeriodicity=80;
	  *psrsOffset=isrs-85;
1027
        }
1028
      if((isrs>164)&&(isrs<325))
1029
        {
1030 1031
	  *psrsPeriodicity=160;
	  *psrsOffset=isrs-165;
1032
        }
1033
      if((isrs>324)&&(isrs<645))
1034
        {
1035 1036
	  *psrsPeriodicity=320;
	  *psrsOffset=isrs-325;
1037
        }
1038 1039 1040
      
      AssertFatal(isrs<=644,"Isrs out of range %d>644\n",isrs);
      
1041 1042
    }
    else
1043
      {
1044
        if(isrs<2)
1045
	  {
1046 1047
            *psrsPeriodicity=2;
            *psrsOffset=isrs;
1048
	  }
1049
        if((isrs>1)&&(isrs<7))
1050
	  {
1051 1052 1053 1054
            *psrsPeriodicity=5;
            *psrsOffset=isrs-2;
        }
        if((isrs>6)&&(isrs<17))
1055
	  {
1056 1057
            *psrsPeriodicity=10;
            *psrsOffset=isrs-7;
1058
	  }
1059
        if((isrs>16)&&(isrs<37))
1060
	  {
1061 1062
            *psrsPeriodicity=20;
            *psrsOffset=isrs-17;
1063
	  }
1064
        if((isrs>36)&&(isrs<77))
1065
	  {
1066 1067
            *psrsPeriodicity=40;
            *psrsOffset=isrs-37;
1068
	  }
1069
        if((isrs>76)&&(isrs<157))
1070
	  {
1071 1072
            *psrsPeriodicity=80;
            *psrsOffset=isrs-77;
1073
	  }
1074
        if((isrs>156)&&(isrs<317))
1075
	  {
1076 1077 1078 1079
            *psrsPeriodicity=160;
            *psrsOffset=isrs-157;
        }
        if((isrs>316)&&(isrs<637))
1080
	  {
1081 1082
            *psrsPeriodicity=320;
            *psrsOffset=isrs-317;
1083 1084 1085 1086
	  }
	AssertFatal(isrs<=636,"Isrs out of range %d>636\n",isrs);
	
      }
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 1126 1127 1128 1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148

// uint8_t eNB_id,uint8_t harq_pid, uint8_t UE_id,
int16_t estimate_ue_tx_power(uint32_t tbs, uint32_t nb_rb, uint8_t control_only, lte_prefix_type_t ncp, uint8_t use_srs)
{

  /// The payload + CRC size in bits, "B"
  uint32_t B;
  /// Number of code segments
  uint32_t C;
  /// Number of "small" code segments
  uint32_t Cminus;
  /// Number of "large" code segments
  uint32_t Cplus;
  /// Number of bits in "small" code segments (<6144)
  uint32_t Kminus;
  /// Number of bits in "large" code segments (<6144)
  uint32_t Kplus;
  /// Total number of bits across all segments
  uint32_t sumKr;
  /// Number of "Filler" bits
  uint32_t F;
  // num resource elements
  uint32_t num_re=0.0;
  // num symbols
  uint32_t num_symb=0.0;
  /// effective spectral efficiency of the PUSCH
  uint32_t MPR_x100=0;
  /// beta_offset
  uint16_t beta_offset_pusch_x8=8;
  /// delta mcs
  float delta_mcs=0.0;
  /// bandwidth factor
  float bw_factor=0.0;

  B= tbs+24;
  lte_segmentation(NULL,
                   NULL,
                   B,
                   &C,
                   &Cplus,
                   &Cminus,
                   &Kplus,
                   &Kminus,
                   &F);


  sumKr = Cminus*Kminus + Cplus*Kplus;
  num_symb = 12-(ncp<<1)-(use_srs==0?0:1);
  num_re = num_symb * nb_rb * 12;

  if (num_re == 0)
    return(0);

  MPR_x100 = 100*sumKr/num_re;

  if (control_only == 1 )
    beta_offset_pusch_x8=8; // fixme

  //(beta_offset_pusch_x8=ue->ulsch[eNB_id]->harq_processes[harq_pid]->control_only == 1) ? ue->ulsch[eNB_id]->beta_offset_cqi_times8:8;

  // if deltamcs_enabledm
1149
  delta_mcs = ((hundred_times_delta_TF[MPR_x100/6]+10*dB_fixed_x10((beta_offset_pusch_x8)>>3))/100.0);
1150 1151 1152 1153 1154 1155 1156 1157
  bw_factor = (hundred_times_log10_NPRB[nb_rb-1]/100.0);
#ifdef DEBUG_SEGMENTATION
  printf("estimated ue tx power %d (num_re %d, sumKr %d, mpr_x100 %d, delta_mcs %f, bw_factor %f)\n",
         (int16_t)ceil(delta_mcs + bw_factor), num_re, sumKr, MPR_x100, delta_mcs, bw_factor);
#endif
  return (int16_t)ceil(delta_mcs + bw_factor);

}