phy_procedures_lte_common.c 25.4 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
ghaddab's avatar
ghaddab committed
3
    Copyright(c) 1999 - 2014 Eurecom
4

ghaddab's avatar
ghaddab committed
5 6 7 8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9 10


ghaddab's avatar
ghaddab committed
11 12 13 14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

ghaddab's avatar
ghaddab committed
16
    You should have received a copy of the GNU General Public License
17 18
    along with OpenAirInterface.The full GNU General Public License is
   included in this distribution in the file called "COPYING". If not,
ghaddab's avatar
ghaddab committed
19
   see <http://www.gnu.org/licenses/>.
20 21

  Contact Information
ghaddab's avatar
ghaddab committed
22 23 24
  OpenAirInterface Admin: openair_admin@eurecom.fr
  OpenAirInterface Tech : openair_tech@eurecom.fr
  OpenAirInterface Dev  : openair4g-devel@eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
  Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

ghaddab's avatar
ghaddab committed
28
 *******************************************************************************/
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46

/*! \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
*/
#include "PHY/defs.h"
#include "PHY/extern.h"
#include "MAC_INTERFACE/defs.h"
#include "MAC_INTERFACE/extern.h"
#include "SCHED/defs.h"
#include "SCHED/extern.h"

47
#ifdef LOCALIZATION
48
#include <sys/time.h>
49
#endif
50 51

void get_Msg3_alloc(LTE_DL_FRAME_PARMS *frame_parms,
52 53 54 55 56
                    unsigned char current_subframe,
                    unsigned int current_frame,
                    unsigned int *frame,
                    unsigned char *subframe)
{
57 58 59 60 61

  // Fill in other TDD Configuration!!!!

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

63 64 65
    if (*subframe>9) {
      *subframe = *subframe-10;
      *frame = current_frame+1;
66
    } else {
67 68
      *frame=current_frame;
    }
69
  } else { // TDD
70 71
    if (frame_parms->tdd_config == 1) {
      switch (current_subframe) {
72

73
      case 0:
74 75 76 77
        *subframe = 7;
        *frame = current_frame;
        break;

78
      case 4:
79 80 81 82
        *subframe = 2;
        *frame = current_frame+1;
        break;

83
      case 5:
84 85 86 87
        *subframe = 2;
        *frame = current_frame+1;
        break;

88
      case 9:
89 90 91
        *subframe = 7;
        *frame = current_frame+1;
        break;
92
      }
93
    } else if (frame_parms->tdd_config == 3) {
94
      switch (current_subframe) {
95

96 97 98
      case 0:
      case 5:
      case 6:
99 100 101 102
        *subframe = 2;
        *frame = current_frame+1;
        break;

103
      case 7:
104 105 106 107
        *subframe = 3;
        *frame = current_frame+1;
        break;

108
      case 8:
109 110 111 112
        *subframe = 4;
        *frame = current_frame+1;
        break;

113
      case 9:
114 115 116
        *subframe = 2;
        *frame = current_frame+2;
        break;
117 118 119 120 121 122
      }
    }
  }
}

void get_Msg3_alloc_ret(LTE_DL_FRAME_PARMS *frame_parms,
123 124 125 126 127
                        unsigned char current_subframe,
                        unsigned int current_frame,
                        unsigned int *frame,
                        unsigned char *subframe)
{
Raymond Knopp's avatar
 
Raymond Knopp committed
128
  if (frame_parms->frame_type == FDD) {
129 130
    // always retransmit in n+8
    *subframe = current_subframe+8;
131

132 133 134
    if (*subframe>9) {
      *subframe = *subframe-10;
      *frame = current_frame+1;
135
    } else {
136 137
      *frame=current_frame;
    }
138
  } else {
139 140 141 142 143 144
    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
      *frame = current_frame+1;
145
    } else if (frame_parms->tdd_config == 3) {
146 147 148 149 150 151 152 153
      // 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;
    }
  }
}

154
uint8_t get_Msg3_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,
155 156 157
                          uint32_t frame,
                          unsigned char current_subframe)
{
158

159
  uint8_t ul_subframe=0;
160
  uint32_t ul_frame=0;
161

Raymond Knopp's avatar
 
Raymond Knopp committed
162
  if (frame_parms->frame_type ==FDD) {
163
    ul_subframe = (current_subframe>3) ? (current_subframe-4) : (current_subframe+6);
164 165
    ul_frame    = (current_subframe>3) ? (frame+1) : frame;
  } else {
166 167 168 169 170 171
    switch (frame_parms->tdd_config) {
    case 1:
      switch (current_subframe) {

      case 9:
      case 0:
172 173 174
        ul_subframe = 7;
        break;

175 176
      case 5:
      case 7:
177 178
        ul_subframe = 2;
        break;
179 180

      }
181

182
      break;
183

184 185 186 187 188 189
    case 3:
      switch (current_subframe) {

      case 0:
      case 5:
      case 6:
190 191 192
        ul_subframe = 2;
        break;

193
      case 7:
194 195 196
        ul_subframe = 3;
        break;

197
      case 8:
198 199 200
        ul_subframe = 4;
        break;

201
      case 9:
202 203
        ul_subframe = 2;
        break;
204
      }
205

206
      break;
207

208 209 210 211 212 213 214 215
    case 4:
      switch (current_subframe) {

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

219
      case 7:
220 221
        ul_subframe = 3;
        break;
222
      }
223

224
      break;
225

226 227 228
    case 5:
      ul_subframe =2;
      break;
229

230 231
    default:
      LOG_E(PHY,"get_Msg3_harq_pid: Unsupported TDD configuration %d\n",frame_parms->tdd_config);
Lionel Gauthier's avatar
Lionel Gauthier committed
232
      mac_xface->macphy_exit("get_Msg3_harq_pid: Unsupported TDD configuration");
233 234 235
      break;
    }
  }
236

237 238 239 240
  return(subframe2harq_pid(frame_parms,ul_frame,ul_subframe));

}

241 242
unsigned char ul_ACK_subframe2_dl_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe,unsigned char ACK_index)
{
243

Raymond Knopp's avatar
 
Raymond Knopp committed
244
  if (frame_parms->frame_type == FDD) {
245
    return((subframe<4) ? subframe+6 : subframe-4);
246
  } else {
247 248 249
    switch (frame_parms->tdd_config) {
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
250 251 252 253 254 255 256 257 258 259 260 261
        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);
262
      }
263

264
      break;
265

266 267
    case 1:
      if (subframe == 2) {  // ACK subframes 5 and 6
268 269 270 271 272 273 274 275 276 277 278
        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);
279
      }
280

281 282 283
      break;
    }
  }
284

285 286 287
  return(0);
}

288 289
unsigned char ul_ACK_subframe2_M(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
290

Raymond Knopp's avatar
 
Raymond Knopp committed
291
  if (frame_parms->frame_type == FDD) {
292
    return(1);
293
  } else {
294 295 296
    switch (frame_parms->tdd_config) {
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
297 298 299 300 301 302 303 304 305
        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);
306
      }
307

308
      break;
309

310 311
    case 1:
      if (subframe == 2) {  // ACK subframes 5 and 6
312 313 314 315 316 317 318 319 320 321 322
        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);
323
      }
324

325 326 327
      break;
    }
  }
328

329 330 331 332
  return(0);
}

// This function implements table 10.1-1 of 36-213, p. 69
333
uint8_t get_ack(LTE_DL_FRAME_PARMS *frame_parms,
334 335 336 337
                harq_status_t *harq_ack,
                unsigned char subframe,
                unsigned char *o_ACK)
{
338

Raymond Knopp's avatar
 
Raymond Knopp committed
339

340 341
  uint8_t status=0;
  uint8_t subframe_dl;
342

Raymond Knopp's avatar
 
Raymond Knopp committed
343
  //  printf("get_ack: SF %d\n",subframe);
344 345 346 347 348
  if (frame_parms->frame_type == FDD) {
    if (subframe < 4)
      subframe_dl = subframe + 6;
    else
      subframe_dl = subframe - 4;
349

350 351
    o_ACK[0] = harq_ack[subframe_dl].ack;
    status = harq_ack[subframe_dl].send_harq_status;
352
    //printf("get_ack: Getting ACK/NAK for PDSCH (subframe %d) => %d\n",subframe_dl,o_ACK[0]);
353
  } else {
354 355 356
    switch (frame_parms->tdd_config) {
    case 1:
      if (subframe == 2) {  // ACK subframes 5 (forget 6)
357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373
        o_ACK[0] = harq_ack[5].ack;
        status = harq_ack[5].send_harq_status;
      } else if (subframe == 3) { // ACK subframe 9
        o_ACK[0] = harq_ack[9].ack;
        status = harq_ack[9].send_harq_status;
      } else if (subframe == 4) { // nothing
        status = 0;
      } else if (subframe == 7) { // ACK subframes 0 (forget 1)
        o_ACK[0] = harq_ack[0].ack;
        status = harq_ack[0].send_harq_status;
      } else if (subframe == 8) { // ACK subframes 4
        o_ACK[0] = harq_ack[4].ack;
        status = harq_ack[4].send_harq_status;
      } else {
        LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
374
      }
375

376
      break;
377

378 379
    case 3:
      if (subframe == 2) {  // ACK subframes 5 and 6
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
        if (harq_ack[5].send_harq_status == 1) {
          o_ACK[0] = harq_ack[5].ack;

          if (harq_ack[6].send_harq_status == 1)
            o_ACK[1] = harq_ack[6].ack;
        } else if (harq_ack[6].send_harq_status == 1)
          o_ACK[0] = harq_ack[6].ack;

        status = harq_ack[5].send_harq_status + (harq_ack[6].send_harq_status<<1);
        //printf("Subframe 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 == 3) { // ACK subframes 7 and 8
        if (harq_ack[7].send_harq_status == 1) {
          o_ACK[0] = harq_ack[7].ack;

          if (harq_ack[8].send_harq_status == 1)
            o_ACK[1] = harq_ack[8].ack;
        } else if (harq_ack[8].send_harq_status == 1)
          o_ACK[0] = harq_ack[8].ack;

        status = harq_ack[7].send_harq_status + (harq_ack[8].send_harq_status<<1);
        //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 if (subframe == 4) { // ACK subframes 9 and 0
        if (harq_ack[9].send_harq_status == 1) {
          o_ACK[0] = harq_ack[9].ack;

          if (harq_ack[0].send_harq_status == 1)
            o_ACK[1] = harq_ack[0].ack;
        } else if (harq_ack[8].send_harq_status == 1)
          o_ACK[0] = harq_ack[8].ack;

        status = harq_ack[9].send_harq_status + (harq_ack[0].send_harq_status<<1);
        //printf("Subframe 4, TDD config 3: harq_ack[9] = %d,harq_ack[0] = %d\n",harq_ack[9].ack,harq_ack[0].ack);
      } else {
        LOG_E(PHY,"phy_procedures_lte.c: get_ack, illegal subframe %d for tdd_config %d\n",
              subframe,frame_parms->tdd_config);
        return(0);
417
      }
418

419
      break;
420

421 422
    }
  }
423

424 425 426 427 428
  //printf("status %d\n",status);

  return(status);
}

429 430 431 432 433 434
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};
435
// This is part of the PUCCH allocation procedure (see Section 10.1 36.213)
436 437
uint16_t get_Np(uint8_t N_RB_DL,uint8_t nCCE,uint8_t plus1)
{
438
  uint8_t *Np;
439

440
  switch (N_RB_DL) {
441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465 466 467 468 469
  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;
  }
470 471 472 473 474 475 476 477 478

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

479 480
lte_subframe_t subframe_select(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
481 482

  // if FDD return dummy value
Raymond Knopp's avatar
 
Raymond Knopp committed
483
  if (frame_parms->frame_type == FDD)
484 485 486 487 488 489 490 491 492 493 494 495
    return(SF_DL);

  switch (frame_parms->tdd_config) {

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

497 498 499 500 501 502
    case 2:
    case 3:
    case 7:
    case 8:
      return(SF_UL);
      break;
503

504 505 506 507
    default:
      return(SF_S);
      break;
    }
508

509
  case 3:
510
    if  ((subframe<1) || (subframe>=5))
511
      return(SF_DL);
512
    else if ((subframe>1) && (subframe < 5))
513 514 515 516 517 518 519
      return(SF_UL);
    else if (subframe==1)
      return (SF_S);
    else  {
      LOG_E(PHY,"[PHY_PROCEDURES_LTE] Unknown subframe number\n");
      return(255);
    }
520

521
    break;
522

523 524
  default:
    LOG_E(PHY,"subframe %d Unsupported TDD configuration %d\n",subframe,frame_parms->tdd_config);
Lionel Gauthier's avatar
Lionel Gauthier committed
525
    mac_xface->macphy_exit("subframe x Unsupported TDD configuration");
526
    return(255);
527

528 529 530
  }
}

531 532
lte_subframe_t get_subframe_direction(uint8_t Mod_id,uint8_t CC_id,uint8_t subframe)
{
533

Raymond Knopp's avatar
 
Raymond Knopp committed
534
  return(subframe_select(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms,subframe));
535 536 537

}

538 539
uint8_t phich_subframe_to_harq_pid(LTE_DL_FRAME_PARMS *frame_parms,uint32_t frame,uint8_t subframe)
{
540 541 542

  //LOG_D(PHY,"phich_subframe_to_harq_pid.c: frame %d, subframe %d\n",frame,subframe);
  return(subframe2harq_pid(frame_parms,
543 544
                           phich_frame2_pusch_frame(frame_parms,frame,subframe),
                           phich_subframe2_pusch_subframe(frame_parms,subframe)));
545 546
}

547 548
unsigned int is_phich_subframe(LTE_DL_FRAME_PARMS *frame_parms,unsigned char subframe)
{
549

Raymond Knopp's avatar
 
Raymond Knopp committed
550
  if (frame_parms->frame_type == FDD) {
551
    return(1);
552
  } else {
553 554 555
    switch (frame_parms->tdd_config) {
    case 1:
      if ((subframe == 1) || (subframe == 4) || (subframe == 6) || (subframe == 9))
556 557
        return(1);

558
      break;
559

560 561
    case 3:
      if ((subframe == 0) || (subframe == 8) || (subframe == 9))
562 563
        return(1);

564
      break;
565

566 567
    case 4:
      if ((subframe == 0) || (subframe == 8) )
568 569
        return(1);

570
      break;
571

572 573
    case 5:
      if (subframe == 0)
574 575
        return(1);

576
      break;
577

578 579 580 581 582
    default:
      return(0);
      break;
    }
  }
583

584 585 586 587
  return(0);
}


588
#ifdef LOCALIZATION
589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 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 634 635 636 637 638 639 640 641 642 643 644 645 646 647 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 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711
double aggregate_eNB_UE_localization_stats(PHY_VARS_eNB *phy_vars_eNB, int8_t UE_id, frame_t frame, sub_frame_t subframe, int32_t UE_tx_power_dB)
{
  // parameters declaration
  int8_t Mod_id, CC_id;
  //    int32_t harq_pid;
  int32_t avg_power, avg_rssi, median_power, median_rssi, median_subcarrier_rss, median_TA, median_TA_update, ref_timestamp_ms, current_timestamp_ms;
  char cqis[100], sub_powers[2048];
  int len = 0, i;
  struct timeval ts;
  double sys_bw = 0;
  uint8_t N_RB_DL;
  LTE_DL_FRAME_PARMS *frame_parms = &phy_vars_eNB->lte_frame_parms;

  Mod_id = phy_vars_eNB->Mod_id;
  CC_id = phy_vars_eNB->CC_id;
  ref_timestamp_ms = phy_vars_eNB->ulsch_eNB[UE_id+1]->reference_timestamp_ms;

  for (i=0; i<13; i++) {
    len += sprintf(&cqis[len]," %d ", phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].DL_subband_cqi[0][i]);
  }

  len = 0;

  for (i=0; i<phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) {
    len += sprintf(&sub_powers[len]," %d ", phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]);
  }

  gettimeofday(&ts, NULL);
  current_timestamp_ms = ts.tv_sec * 1000 + ts.tv_usec / 1000;


  LOG_D(LOCALIZE, " PHY: [UE %x/%d -> eNB %d], timestamp %d, "
        "frame %d, subframe %d"
        "UE Tx power %d dBm, "
        "RSSI ant1 %d dBm, "
        "RSSI ant2 %d dBm, "
        "pwr ant1 %d dBm, "
        "pwr ant2 %d dBm, "
        "Rx gain %d dB, "
        "TA %d, "
        "TA update %d, "
        "DL_CQI (%d,%d), "
        "Wideband CQI (%d,%d), "
        "DL Subband CQI[13] %s \n",
        //          "timestamp %d, (%d active subcarrier) %s \n"
        phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms,
        frame,subframe,
        UE_tx_power_dB,
        phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[0],
        phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[1],
        dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]),
        dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]),
        phy_vars_eNB->rx_total_gain_eNB_dB,
        phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset, // raw timing advance 1/sampling rate
        phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update,
        phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].DL_cqi[0],phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].DL_cqi[1],
        phy_vars_eNB->PHY_measurements_eNB[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][0],
        phy_vars_eNB->PHY_measurements_eNB[Mod_id].wideband_cqi_dB[(uint32_t)UE_id][1],
        cqis);
  LOG_D(LOCALIZE, " PHY: timestamp %d, (%d active subcarrier) %s \n",
        current_timestamp_ms,
        phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier,
        sub_powers);

  N_RB_DL = frame_parms->N_RB_DL;

  switch (N_RB_DL) {
  case 6:
    sys_bw = 1.92;
    break;

  case 25:
    sys_bw = 7.68;
    break;

  case 50:
    sys_bw = 15.36;
    break;

  case 100:
    sys_bw = 30.72;
    break;
  }

  if ((current_timestamp_ms - ref_timestamp_ms > phy_vars_eNB->ulsch_eNB[UE_id+1]->aggregation_period_ms)) {
    // check the size of one list to be sure there was a message transmitted during the defined aggregation period

    // make the reference timestamp == current timestamp
    phy_vars_eNB->ulsch_eNB[UE_id+1]->reference_timestamp_ms = current_timestamp_ms;
    int i;

    for (i=0; i<10; i++) {
      median_power = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[i]);
      del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[i]);
      median_rssi = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[i]);
      del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[i]);
      median_subcarrier_rss = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[i]);
      del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[i]);
      median_TA = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[i]);
      del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[i]);
      median_TA_update = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[i]);
      del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[i]);

      if (median_power != 0)
        push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list,median_power);

      if (median_rssi != 0)
        push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list,median_rssi);

      if (median_subcarrier_rss != 0)
        push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list,median_subcarrier_rss);

      if (median_TA != 0)
        push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list,median_TA);

      if (median_TA_update != 0)
        push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list,median_TA_update);

      initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[i]);
      initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[i]);
      initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[i]);
      initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[i]);
      initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[i]);
712
    }
713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744

    median_power = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list);
    del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list);
    median_rssi = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list);
    del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list);
    median_subcarrier_rss = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list);
    del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list);
    median_TA = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list);
    del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list);
    median_TA_update = calculate_median(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list);
    del(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list);

    initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rss_list);
    initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_subcarrier_rss_list);
    initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_rssi_list);
    initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_advance_list);
    initialize(&phy_vars_eNB->ulsch_eNB[UE_id+1]->tot_loc_timing_update_list);

    double alpha = 2, power_distance, time_distance;
    // distance = 10^((Ptx - Prx - A)/10alpha), A is a constance experimentally evaluated
    // A includes the rx gain (phy_vars_eNB->rx_total_gain_eNB_dB) and hardware calibration
    power_distance = pow(10, ((UE_tx_power_dB - median_power - phy_vars_eNB->rx_total_gain_eNB_dB + 133)/(10.0*alpha)));
    /* current measurements shows constant UE_timing_offset = 18
       and timing_advance_update = 11 at 1m. at 5m, timing_advance_update = 12*/
    //time_distance = (double) 299792458*(phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update)/(sys_bw*1000000);
    time_distance = (double) abs(phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update - 11) * 4.89;//  (3 x 108 x 1 / (15000 x 2048)) / 2 = 4.89 m

    phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].distance.time_based = time_distance;
    phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].distance.power_based = power_distance;

    LOG_D(LOCALIZE, " PHY agg [UE %x/%d -> eNB %d], timestamp %d, "
          "frame %d, subframe %d "
745
          "UE Tx power %d dBm, "
746 747
          "median RSSI %d dBm, "
          "median Power %d dBm, "
748
          "Rx gain %d dB, "
749 750 751 752 753
          "power estimated r = %0.3f, "
          " TA %d, update %d "
          "TA estimated r = %0.3f\n"
          ,phy_vars_eNB->dlsch_eNB[(uint32_t)UE_id][0]->rnti, UE_id, Mod_id, current_timestamp_ms,
          frame, subframe,
754
          UE_tx_power_dB,
755 756
          median_rssi,
          median_power,
757
          phy_vars_eNB->rx_total_gain_eNB_dB,
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777
          power_distance,
          phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset, median_TA_update,
          time_distance);

    return 0;
  } else {
    avg_power = (dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[0]) + dB_fixed(phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->ulsch_power[1]))/2;
    avg_rssi = (phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[0] + phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UL_rssi[1])/2;

    push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rss_list[subframe],avg_power);
    push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_rssi_list[subframe],avg_rssi);

    for (i=0; i<phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->active_subcarrier; i++) {
      push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_subcarrier_rss_list[subframe], phy_vars_eNB->lte_eNB_pusch_vars[(uint32_t)UE_id]->subcarrier_power[i]);
    }

    push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_advance_list[subframe], phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].UE_timing_offset);
    push_front(&phy_vars_eNB->ulsch_eNB[UE_id+1]->loc_timing_update_list[subframe], phy_vars_eNB->eNB_UE_stats[(uint32_t)UE_id].timing_advance_update);
    return -1;
  }
778 779
}
#endif
780 781
LTE_eNB_UE_stats* get_eNB_UE_stats(uint8_t Mod_id, uint8_t  CC_id,uint16_t rnti)
{
782
  int8_t UE_id;
783

Raymond Knopp's avatar
 
Raymond Knopp committed
784 785
  if ((PHY_vars_eNB_g == NULL) || (PHY_vars_eNB_g[Mod_id] == NULL) || (PHY_vars_eNB_g[Mod_id][CC_id]==NULL)) {
    LOG_E(PHY,"get_eNB_UE_stats: No phy_vars_eNB found (or not allocated) for Mod_id %d,CC_id %d\n",Mod_id,CC_id);
786 787
    return NULL;
  }
788

Raymond Knopp's avatar
 
Raymond Knopp committed
789
  UE_id = find_ue(rnti, PHY_vars_eNB_g[Mod_id][CC_id]);
790

791
  if (UE_id == -1) {
Raymond Knopp's avatar
 
Raymond Knopp committed
792
    //    LOG_E(PHY,"get_eNB_UE_stats: UE with rnti %x not found\n",rnti);
793 794
    return NULL;
  }
795

Raymond Knopp's avatar
 
Raymond Knopp committed
796
  return(&PHY_vars_eNB_g[Mod_id][CC_id]->eNB_UE_stats[(uint32_t)UE_id]);
797 798
}

799 800
int8_t find_ue(uint16_t rnti, PHY_VARS_eNB *phy_vars_eNB)
{
801
  uint8_t i;
802

803 804 805 806
  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    if ((phy_vars_eNB->dlsch_eNB[i]) &&
        (phy_vars_eNB->dlsch_eNB[i][0]) &&
        (phy_vars_eNB->dlsch_eNB[i][0]->rnti==rnti)) {
807 808 809
      return(i);
    }
  }
810 811 812 813

#ifdef CBA

  for (i=0; i<NUM_MAX_CBA_GROUP; i++) {
814
    if ((phy_vars_eNB->ulsch_eNB[i]) && // ue J is the representative of group j
815 816
        (phy_vars_eNB->ulsch_eNB[i]->num_active_cba_groups) &&
        (phy_vars_eNB->ulsch_eNB[i]->cba_rnti[i]== rnti))
817 818
      return(i);
  }
819 820 821

#endif

822 823 824
  return(-1);
}

825 826
LTE_DL_FRAME_PARMS* get_lte_frame_parms(module_id_t Mod_id, uint8_t  CC_id)
{
827 828 829 830 831

  return(&PHY_vars_eNB_g[Mod_id][CC_id]->lte_frame_parms);

}

832 833 834
MU_MIMO_mode *get_mu_mimo_mode (module_id_t Mod_id, uint8_t  CC_id, rnti_t rnti)
{
  int8_t UE_id = find_ue( rnti, PHY_vars_eNB_g[Mod_id][CC_id] );
835

836
  if (UE_id == -1)
837 838
    return 0;

839
  return &PHY_vars_eNB_g[Mod_id][CC_id]->mu_mimo_mode[UE_id];
840
}