lte-ue.c 52 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
3 4 5 6 7 8 9 10 11 12 13 14 15 16
    Copyright(c) 1999 - 2014 Eurecom

    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.


    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.

    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,
19 20 21 22 23
    see <http://www.gnu.org/licenses/>.

   Contact Information
   OpenAirInterface Admin: openair_admin@eurecom.fr
   OpenAirInterface Tech : openair_tech@eurecom.fr
24
   OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

26 27 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
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE

*******************************************************************************/

/*! \file lte-ue.c
 * \brief threads and support functions for real-time LTE UE target
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2015
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */
#define _GNU_SOURCE
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <sched.h>
#include <linux/sched.h>
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
#include <syscall.h>
56
#include <sys/sysinfo.h>
57 58 59 60 61 62

#include "rt_wrapper.h"
#include "assertions.h"
#include "PHY/types.h"

#include "PHY/defs.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
63
#ifdef OPENAIR2
64 65
#include "LAYER2/MAC/defs.h"
#include "RRC/LITE/extern.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
66
#endif
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94
#include "PHY_INTERFACE/extern.h"

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "../../ARCH/COMMON/common_lib.h"

#include "PHY/extern.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"

#include "UTIL/LOG/log_extern.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"

#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

typedef enum {
  pss=0,
  pbch=1,
  si=2
} sync_mode_t;

95 96 97
void init_UE_threads(void);
void *UE_thread(void *arg);
void init_UE(void);
98 99 100 101 102 103 104

extern pthread_cond_t sync_cond;
extern pthread_mutex_t sync_mutex;
extern int sync_var;

extern openair0_config_t openair0_cfg[MAX_CARDS];
extern uint32_t          downlink_frequency[MAX_NUM_CCs][4];
105
extern int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];
106 107 108 109 110 111 112 113
extern openair0_rf_map rf_map[MAX_NUM_CCs];

extern openair0_device openair0;
extern int oai_exit;

extern int32_t **rxdata;
extern int32_t **txdata;

114 115
//extern unsigned int tx_forward_nsamps;
//extern int tx_delay;
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

extern int rx_input_level_dBm;
extern uint8_t exit_missed_slots;
extern uint64_t num_missed_slots; // counter for the number of missed slots

extern void exit_fun(const char* s);

#define KHz (1000UL)
#define MHz (1000 * KHz)

typedef struct eutra_band_s {
  int16_t band;
  uint32_t ul_min;
  uint32_t ul_max;
  uint32_t dl_min;
  uint32_t dl_max;
  lte_frame_type_t frame_type;
} eutra_band_t;

typedef struct band_info_s {
  int nbands;
  eutra_band_t band_info[100];
} band_info_t;

band_info_t bands_to_scan;

142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158
static const eutra_band_t eutra_bands[] = {
  { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
  { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
  { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
  { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
  { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
  { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
  { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
  { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
  { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
  {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
  {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
  {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
  {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
  {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
  {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
  {20,  832    * MHz,  862    * MHz,  791    * MHz,  821    * MHz, FDD},
159
  {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
160 161 162 163 164 165 166 167 168 169 170 171 172 173
  {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
  {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
  {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
  {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
  {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
  {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
  {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
  {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
  {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
  {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
  {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
  {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
};

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
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

void init_UE() {

  int error_code;
  
  printf("Intializing UE Threads ...\n");
  init_UE_threads();
  sleep(1);
  error_code = pthread_create(&main_ue_thread, &attr_UE_thread, UE_thread, NULL);
  
  if (error_code!= 0) {
    LOG_D(HW,"[lte-softmodem.c] Could not allocate UE_thread, error %d\n",error_code);
    return;
  } else {
    LOG_D( HW, "[lte-softmodem.c] Allocate UE_thread successful\n" );
    pthread_setname_np( main_ue_thread, "main UE" );
  }

  printf("UE threads created\n");
#ifdef USE_MME
  
  while (start_UE == 0) {
    sleep(1);
  }
  
#endif
  
}

206 207
/*!
 * \brief This is the UE synchronize thread.
208
 * It performs band scanning and synchonization.
209 210 211
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
212 213
static void *UE_thread_synch(void *arg)
{
214 215 216
  static int UE_thread_synch_retval;
  int i, hw_slot_offset;
  PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
217 218
  int current_band = 0;
  int current_offset = 0;
219
  sync_mode_t sync_mode = pbch;
220
  int card;
221 222
  int ind;
  int found;
223
  int freq_offset=0;
224 225 226 227 228

  UE->is_synchronized = 0;
  printf("UE_thread_sync in with PHY_vars_UE %p\n",arg);
  printf("waiting for sync (UE_thread_synch) \n");

229 230 231 232 233 234 235 236 237 238
#ifndef LOWLATENCY
  int policy, s, j;
  struct sched_param sparam;
  char cpu_affinity[1024];
  cpu_set_t cpuset;

  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
  /* CPU 0 is reserved for UHD threads */
  CPU_ZERO(&cpuset);

239 240
  #ifdef CPU_AFFINITY
  if (get_nprocs() >2)
241
  {
242 243 244 245 246 247 248 249 250
    for (j = 1; j < get_nprocs(); j++)
      CPU_SET(j, &cpuset);

    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
    if (s != 0)
    {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
251
  }
252 253
  #endif

254 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 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
  /* Check the actual affinity mask assigned to the thread */

  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
  if (s != 0)
  {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
  for (j = 0; j < CPU_SETSIZE; j++)
  if (CPU_ISSET(j, &cpuset))
  {  
     char temp[1024];
     sprintf(temp, " CPU_%d ", j);    
     strcat(cpu_affinity, temp);
  }

  memset(&sparam, 0 , sizeof (sparam));
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
  policy = SCHED_FIFO ; 
  
  s = pthread_setschedparam(pthread_self(), policy, &sparam);
  if (s != 0)
     {
     perror("pthread_setschedparam : ");
     exit_fun("Error setting thread priority");
     }
  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
  if (s != 0)
   {
     perror("pthread_getschedparam : ");
     exit_fun("Error getting thread priority");

   }

  LOG_I( HW, "[SCHED][UE] Started UE synch thread on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(),
                   (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
                   (policy == SCHED_RR)    ? "SCHED_RR" :
                   (policy == SCHED_OTHER) ? "SCHED_OTHER" :
                   "???",
                   (int) sparam.sched_priority, cpu_affinity);

#endif


299 300
  pthread_mutex_lock(&sync_mutex);
  printf("Locked sync_mutex, waiting (UE_sync_thread)\n");
301

302 303
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
304

305 306 307
  pthread_mutex_unlock(&sync_mutex);
  printf("unlocked sync_mutex (UE_sync_thread)\n");

308
  printf("starting UE synch thread (IC %d)\n",UE->instance_cnt_synch);
309 310
  ind = 0;
  found = 0;
311 312


313 314
  if (UE->UE_scan == 0) {
    do  {
315
      current_band = eutra_bands[ind].band;
Raymond Knopp's avatar
 
Raymond Knopp committed
316
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
317

318
      if ((eutra_bands[ind].dl_min <= downlink_frequency[0][0]) && (eutra_bands[ind].dl_max >= downlink_frequency[0][0])) {
319 320 321 322 323 324 325
        for (card=0; card<MAX_NUM_CCs; card++)
          for (i=0; i<4; i++)
            uplink_frequency_offset[card][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;

        found = 1;
        break;
      }
326

327
      ind++;
328 329
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
  
330 331
    if (found == 0) {
      exit_fun("Can't find EUTRA band for frequency");
332
      return &UE_thread_synch_retval;
333
    }
334

335 336


337

338 339


Raymond Knopp's avatar
 
Raymond Knopp committed
340
    LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d)\n", downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],oai_exit );
341 342 343 344 345 346 347

    for (i=0;i<openair0_cfg[0].rx_num_channels;i++) {
      openair0_cfg[0].rx_freq[i] = downlink_frequency[0][i];
      openair0_cfg[0].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
      openair0_cfg[0].autocal[i] = 1;
    }

348
    sync_mode = pbch;
349

350
  } else if  (UE->UE_scan == 1) {
351
    current_band=0;
352

353
    for (card=0; card<MAX_CARDS; card++) {
354
      for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
355 356 357 358 359
        downlink_frequency[card][i] = bands_to_scan.band_info[0].dl_min;
        uplink_frequency_offset[card][i] = bands_to_scan.band_info[0].ul_min-bands_to_scan.band_info[0].dl_min;

        openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i];
        openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i];
360
#ifdef OAI_USRP
361
        openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
362

363
#if 0 // UHD 3.8	
364
        switch(UE->frame_parms.N_RB_DL) {
365 366 367 368 369 370 371 372 373 374 375 376
        case 6:
          openair0_cfg[card].rx_gain[i] -= 12;
          break;

        case 25:
          openair0_cfg[card].rx_gain[i] -= 6;
          break;

        case 50:
          openair0_cfg[card].rx_gain[i] -= 3;
          break;

377 378 379 380
        case 100:
          openair0_cfg[card].rx_gain[i] -= 0;
          break;

381
        default:
382
          printf( "Unknown number of RBs %d\n", UE->frame_parms.N_RB_DL );
383 384
          break;
        }
385
#endif
386
        printf( "UE synch: setting RX gain (%d,%d) to %f\n", card, i, openair0_cfg[card].rx_gain[i] );
387 388
#endif
      }
389 390 391
    }

  }
392 393

  while (oai_exit==0) {
394

395
    if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
396
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" );
397
      exit_fun("noting to add");
398 399
      return &UE_thread_synch_retval;
    }
400
    
401

402
    while (UE->instance_cnt_synch < 0) {
403
      // the thread waits here most of the time
404 405
      pthread_cond_wait( &UE->cond_synch, &UE->mutex_synch );
    }
406

407 408 409 410 411
    if (pthread_mutex_unlock(&UE->mutex_synch) != 0) {
      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for UE Initial Synch thread\n" );
      exit_fun("nothing to add");
      return &UE_thread_synch_retval;
    }
412

413
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH, 1 );
414 415

    switch (sync_mode) {
416
    case pss:
417 418
      LOG_I(PHY,"[SCHED][UE] Scanning band %d (%d), freq %u\n",bands_to_scan.band_info[current_band].band, current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
      lte_sync_timefreq(UE,current_band,bands_to_scan.band_info[current_band].dl_min+current_offset);
419 420 421 422 423 424 425
      current_offset += 20000000; // increase by 20 MHz

      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
        current_band++;
        current_offset=0;
      }

426
      if (current_band==bands_to_scan.nbands) {
427 428
        current_band=0;
        oai_exit=1;
429
      }
430 431 432 433 434 435 436

      for (card=0; card<MAX_CARDS; card++) {
        for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
          downlink_frequency[card][i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
          uplink_frequency_offset[card][i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;


437 438
          openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i];
          openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i];
439
#ifdef OAI_USRP
440
          openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;  // 65 calibrated for USRP B210 @ 2.6 GHz
441 442

#if 0 // UHD 3.8	  
443
          switch(UE->frame_parms.N_RB_DL) {
444 445 446 447 448 449 450 451 452 453 454 455
          case 6:
            openair0_cfg[card].rx_gain[i] -= 12;
            break;

          case 25:
            openair0_cfg[card].rx_gain[i] -= 6;
            break;

          case 50:
            openair0_cfg[card].rx_gain[i] -= 3;
            break;

456 457 458 459
          case 100:
            openair0_cfg[card].rx_gain[i] -= 0;
            break;

460
          default:
461
            printf("Unknown number of RBs %d\n",UE->frame_parms.N_RB_DL);
462 463
            break;
          }
464
#endif	  
465 466

          printf("UE synch: setting RX gain (%d,%d) to %f\n",card,i,openair0_cfg[card].rx_gain[i]);
467
#endif
468

469
        }
470 471 472

      }

473
      if (UE->UE_scan_carrier) {
474

475 476 477 478
	for (i=0;i<openair0_cfg[0].rx_num_channels;i++)
	  openair0_cfg[0].autocal[i] = 1;

      }
479

480 481 482

      break;
 
483
    case pbch:
484

485
      LOG_I(PHY,"[UE thread Synch] Running Initial Synch\n");
486
      if (initial_sync( UE, UE->mode ) == 0) {
487

488
        hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
489 490 491 492 493 494
        LOG_I( HW, "Got synch: hw_slot_offset %d\n", hw_slot_offset );
	if (UE->UE_scan_carrier == 1) {

	  UE->UE_scan_carrier = 0;
	  // rerun with new cell parameters and frequency-offset
	  for (i=0;i<openair0_cfg[0].rx_num_channels;i++) {
495
	    openair0_cfg[0].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
496
	    openair0_cfg[0].rx_freq[i] -= UE->common_vars.freq_offset;
497 498 499 500 501
	    openair0_cfg[0].tx_freq[i] =  openair0_cfg[0].rx_freq[i]+uplink_frequency_offset[0][i];
	    downlink_frequency[0][i] = openair0_cfg[0].rx_freq[i];
	    freq_offset=0;	    
	  }

502
	  // reconfigure for potentially different bandwidth
503
	  switch(UE->frame_parms.N_RB_DL) {
504 505
	  case 6:
	    openair0_cfg[0].sample_rate =1.92e6;
506 507
	    openair0_cfg[0].rx_bw          =.96e6;
	    openair0_cfg[0].tx_bw          =.96e6;
508
	    //            openair0_cfg[0].rx_gain[0] -= 12;
509 510
	    break;
	  case 25:
511 512 513
	    openair0_cfg[0].sample_rate =7.68e6;
	    openair0_cfg[0].rx_bw          =2.5e6;
	    openair0_cfg[0].tx_bw          =2.5e6;
514
	    //            openair0_cfg[0].rx_gain[0] -= 6;
515 516
	    break;
	  case 50:
517 518 519
	    openair0_cfg[0].sample_rate =15.36e6;
	    openair0_cfg[0].rx_bw          =5.0e6;
	    openair0_cfg[0].tx_bw          =5.0e6;
520
	    //            openair0_cfg[0].rx_gain[0] -= 3;
521 522 523
	    break;
	  case 100:
	    openair0_cfg[0].sample_rate=30.72e6;
524 525
	    openair0_cfg[0].rx_bw=10.0e6;
	    openair0_cfg[0].tx_bw=10.0e6;
526
	    //            openair0_cfg[0].rx_gain[0] -= 0;
527 528
	    break;
	  }
529

530
	  openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0);
531 532
	  //openair0.trx_set_gains_func(&openair0,&openair0_cfg[0]);
	  //openair0.trx_stop_func(0);	  
533
	  sleep(1);
534
	  init_frame_parms(&UE->frame_parms,1);
535 536 537
	}
	else {
	  UE->is_synchronized = 1;
538 539

	 if( UE->mode == rx_dump_frame ){
540 541
	   FILE *fd;
	   if ((UE->frame_rx&1) == 0) {  // this guarantees SIB1 is present 
Cedric Roux's avatar
Cedric Roux committed
542
	     if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
543
	       fwrite((void*)&UE->common_vars.rxdata[0][0],
544
		      sizeof(int32_t),
545
		      10*UE->frame_parms.samples_per_tti,
546 547 548 549 550 551 552 553 554 555 556 557 558
		      fd);
	       LOG_I(PHY,"Dummping Frame ... bye bye \n");
	       fclose(fd);
	       exit(0);
	     }
	     else {
	       LOG_E(PHY,"Cannot open file for writing\n");
	       exit(0);
	     }
	   }
	   else {
	     UE->is_synchronized = 0;
	   }
559
	 }
560
	 
561

562

563 564 565
	  UE->slot_rx = 0;
	  UE->slot_tx = 4;
	}
566 567 568
      } else {
        // initial sync failed
        // calculate new offset and try again
569 570 571 572 573 574 575 576 577 578
	if (UE->UE_scan_carrier == 1) {
	  if (freq_offset >= 0) {
	    freq_offset += 100;
	    freq_offset *= -1;
	  } else {
	    freq_offset *= -1;
	  }
	
	  if (abs(freq_offset) > 7500) {
	    LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
579
	    FILE *fd;
580
	    if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
581
	      fwrite((void*)&UE->common_vars.rxdata[0][0],
582
		     sizeof(int32_t),
583
		     10*UE->frame_parms.samples_per_tti,
584 585 586 587 588
		     fd);
	      LOG_I(PHY,"Dummping Frame ... bye bye \n");
	      fclose(fd);
	      exit(0);
	    }
589 590 591 592 593 594 595 596 597
	    mac_xface->macphy_exit("No cell synchronization found, abandoning");
	    return &UE_thread_synch_retval; // not reached
	  }
	}
	else {
	  
	}
        LOG_I( PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n", 
	       freq_offset,
598
               UE->rx_total_gain_dB,
599 600
               downlink_frequency[0][0]+freq_offset,
               downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
601 602 603

        for (card=0; card<MAX_CARDS; card++) {
          for (i=0; i<openair0_cfg[card].rx_num_channels; i++) {
604 605
            openair0_cfg[card].rx_freq[i] = downlink_frequency[card][i]+freq_offset;
            openair0_cfg[card].tx_freq[i] = downlink_frequency[card][i]+uplink_frequency_offset[card][i]+freq_offset;
606

607 608
	    openair0.trx_set_freq_func(&openair0,&openair0_cfg[0],0);
	    
609 610 611 612

            openair0_cfg[card].rx_gain[i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
	    
	    
613 614
          }
        }
615 616 617 618 619 620
	if (UE->UE_scan_carrier==1) {
	  for (i=0;i<openair0_cfg[0].rx_num_channels;i++)
	    openair0_cfg[0].autocal[i] = 1;
	  
	}
      }// initial_sync=0
621

622
      break;
623

624 625 626 627
    case si:
    default:
      break;
    }
628

629
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH, 0 );
Raymond Knopp's avatar
 
Raymond Knopp committed
630

631 632


633
    if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
634 635 636 637
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE synch\n" );
      exit_fun("noting to add");
      return &UE_thread_synch_retval;
    }
638

639
    // indicate readiness
640 641 642 643 644 645
    UE->instance_cnt_synch--;

    if (pthread_mutex_unlock(&UE->mutex_synch) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE synch\n" );
      exit_fun("noting to add");
      return &UE_thread_synch_retval;
646
    }
647

648
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_SYNCH, 0 );
649
  }  // while !oai_exit
650

651
  return &UE_thread_synch_retval;
652 653
}

654 655 656 657 658 659
/*!
 * \brief This is the UE transmit thread.
 * This thread performs the phy_procedures_UE_TX() on every transmit slot.
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
660 661
static void *UE_thread_tx(void *arg)
{
662
  static int UE_thread_tx_retval;
663
  //int ret;
664 665 666 667 668 669

  PHY_VARS_UE *UE = (PHY_VARS_UE*)arg;

  UE->instance_cnt_tx=-1;

#ifdef LOWLATENCY
670 671 672
  struct sched_attr attr;
  unsigned int flags = 0;

673 674 675
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
676
  attr.sched_priority = 0;
677

678
  /* This creates a 1ms reservation every 10ms period*/
679 680 681 682
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = 900000;  // each tx thread requires .5ms to finish its job
  attr.sched_deadline = 1000000; // each tx thread will finish within 1ms
  attr.sched_period   = 1000000; // each tx thread has a period of 1ms from the starting point
683

684 685

  if (sched_setattr(0, &attr, flags) < 0 ) {
knopp's avatar
knopp committed
686
    perror("[SCHED] UE_thread_tx thread: sched_setattr failed\n");
687
    return &UE_thread_tx_retval;
688
  }
689

690
#else
691 692 693 694 695 696 697 698 699
  int policy, s, j;
  struct sched_param sparam;
  char cpu_affinity[1024];
  cpu_set_t cpuset;

  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
  /* CPU 0 is reserved for UHD threads */
  CPU_ZERO(&cpuset);

700 701
  #ifdef CPU_AFFINITY
  if (get_nprocs() >2)
702
  {
703 704 705 706 707 708 709 710 711
    for (j = 1; j < get_nprocs(); j++)
      CPU_SET(j, &cpuset);

    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
    if (s != 0)
    {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
712
  }
713
#endif
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 745 746 747 748 749 750 751 752 753 754 755 756
  /* Check the actual affinity mask assigned to the thread */

  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
  if (s != 0)
  {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
  for (j = 0; j < CPU_SETSIZE; j++)
  if (CPU_ISSET(j, &cpuset))
  {  
     char temp[1024];
     sprintf(temp, " CPU_%d ", j);    
     strcat(cpu_affinity, temp);
  }

  memset(&sparam, 0 , sizeof (sparam));
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
  policy = SCHED_FIFO ; 
  
  s = pthread_setschedparam(pthread_self(), policy, &sparam);
  if (s != 0)
     {
     perror("pthread_setschedparam : ");
     exit_fun("Error setting thread priority");
     }
  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
  if (s != 0)
   {
     perror("pthread_getschedparam : ");
     exit_fun("Error getting thread priority");

   }

  LOG_I( HW, "[SCHED][UE] Started UE thread TX on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(),
                   (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
                   (policy == SCHED_RR)    ? "SCHED_RR" :
                   (policy == SCHED_OTHER) ? "SCHED_OTHER" :
                   "???",
                   (int) sparam.sched_priority, cpu_affinity);

757

758
#endif
759

760 761 762 763
  printf("waiting for sync (UE_thread_tx)\n");

  pthread_mutex_lock(&sync_mutex);
  printf("Locked sync_mutex, waiting (UE_thread_tx)\n");
764

765 766
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
767

768 769 770 771 772
  pthread_mutex_unlock(&sync_mutex);
  printf("unlocked sync_mutex, waiting (UE_thread_tx)\n");

  printf("Starting UE TX thread\n");

773
  // Lock memory from swapping. This is a process wide call (not constraint to this thread).
774 775 776 777 778
  mlockall(MCL_CURRENT | MCL_FUTURE);

  while (!oai_exit) {

    if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
779
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE TX\n" );
780
      exit_fun("nothing to add");
781 782
      return &UE_thread_tx_retval;
    }
783

784 785 786
    while (UE->instance_cnt_tx < 0) {
      // most of the time, the thread is waiting here
      pthread_cond_wait( &UE->cond_tx, &UE->mutex_tx );
787
    }
788

789 790 791 792 793
    if (pthread_mutex_unlock(&UE->mutex_tx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE TX\n" );
      exit_fun("nothing to add");
      return &UE_thread_tx_retval;
    }
794
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX, 1 );
795

796 797
    if ((subframe_select( &UE->frame_parms, UE->slot_tx>>1 ) == SF_UL) ||
        (UE->frame_parms.frame_type == FDD)) {
798
      phy_procedures_UE_TX( UE, 0, 0, UE->mode, no_relay );
799
    }
800

801
    if ((subframe_select( &UE->frame_parms, UE->slot_tx>>1 ) == SF_S) &&
802 803
        ((UE->slot_tx&1) == 1)) {
      phy_procedures_UE_S_TX( UE, 0, 0, no_relay );
804
    }
805

806 807 808 809 810 811 812 813 814 815 816
    UE->slot_tx += 2;

    if (UE->slot_tx >= 20) {
      UE->slot_tx -= 20;
      UE->frame_tx++;
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX_UE, UE->frame_tx );
    }

    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX_UE, UE->slot_tx>>1 );

    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_TX, 0 );
817

818
    if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
819 820 821 822
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE TX thread\n" );
      exit_fun("nothing to add");
      return &UE_thread_tx_retval;
    }
823

824
    UE->instance_cnt_tx--;
825
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX, UE->instance_cnt_tx);
826 827 828 829 830

    if (pthread_mutex_unlock(&UE->mutex_tx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE TX thread\n" );
      exit_fun("nothing to add");
      return &UE_thread_tx_retval;
831
    }
832

833
  }
834

835
  return &UE_thread_tx_retval;
836 837
}

838 839 840 841 842 843
/*!
 * \brief This is the UE receive thread.
 * This thread performs the phy_procedures_UE_RX() on every received slot.
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
844

845
/*
846 847 848 849 850 851 852 853 854 855 856 857 858 859 860 861 862 863 864
#ifdef OAI_USRP
void rescale(int16_t *input,int length)
{
#if defined(__x86_64__) || defined(__i386__)
  __m128i *input128 = (__m128i *)input;
#elif defined(__arm__)
  int16x8_t *input128 = (int16x8_t *)input;
#endif
  int i;

  for (i=0; i<length>>2; i++) {
#if defined(__x86_64__) || defined(__i386__)
    input128[i] = _mm_srai_epi16(input128[i],4);
#elif defined(__arm__)
    input128[i] = vshrq_n_s16(input128[i],4);
#endif
  }
}
#endif
865
*/
866

867 868
static void *UE_thread_rx(void *arg)
{
869
  static int UE_thread_rx_retval;
870 871 872
  PHY_VARS_UE *UE = (PHY_VARS_UE*)arg;
  int i;
  int ret;
873

874 875 876
  UE->instance_cnt_rx=-1;

#ifdef LOWLATENCY
877 878 879
  struct sched_attr attr;
  unsigned int flags = 0;

880 881 882
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
883
  attr.sched_priority = 0;
884

885
  // This creates a .5ms reservation every 1ms period
886 887 888 889
  attr.sched_policy   = SCHED_DEADLINE;
  attr.sched_runtime  = 900000;  // each rx thread requires 1ms to finish its job
  attr.sched_deadline = 1000000; // each rx thread will finish within 1ms
  attr.sched_period   = 1000000; // each rx thread has a period of 1ms from the starting point
890 891

  if (sched_setattr(0, &attr, flags) < 0 ) {
knopp's avatar
knopp committed
892
    perror("[SCHED] UE_thread_rx : sched_setattr failed\n");
893
    return &UE_thread_rx_retval;
894 895
  }

896
#else
897 898 899 900 901 902 903 904 905
  int policy, s, j;
  struct sched_param sparam;
  char cpu_affinity[1024];
  cpu_set_t cpuset;

  /* Set affinity mask to include CPUs 1 to MAX_CPUS */
  /* CPU 0 is reserved for UHD threads */
  CPU_ZERO(&cpuset);

906 907
  #ifdef CPU_AFFINITY
  if (get_nprocs() >2)
908
  {
909 910 911 912 913 914 915 916 917
    for (j = 1; j < get_nprocs(); j++)
      CPU_SET(j, &cpuset);

    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
    if (s != 0)
    {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
918
  }
919 920
  #endif

921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962
  /* Check the actual affinity mask assigned to the thread */

  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
  if (s != 0)
  {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
  for (j = 0; j < CPU_SETSIZE; j++)
  if (CPU_ISSET(j, &cpuset))
  {  
     char temp[1024];
     sprintf(temp, " CPU_%d ", j);    
     strcat(cpu_affinity, temp);
  }

  memset(&sparam, 0 , sizeof (sparam));
  sparam.sched_priority = sched_get_priority_max(SCHED_FIFO)-1;
  policy = SCHED_FIFO ; 
  
  s = pthread_setschedparam(pthread_self(), policy, &sparam);
  if (s != 0)
     {
     perror("pthread_setschedparam : ");
     exit_fun("Error setting thread priority");
     }
  s = pthread_getschedparam(pthread_self(), &policy, &sparam);
  if (s != 0)
   {
     perror("pthread_getschedparam : ");
     exit_fun("Error getting thread priority");

   }

  LOG_I( HW, "[SCHED][UE] Started UE RX thread on CPU %d TID %ld , sched_policy = %s, priority = %d, CPU Affinity = %s \n", (int)sched_getcpu(), gettid(),
                   (policy == SCHED_FIFO)  ? "SCHED_FIFO" :
                   (policy == SCHED_RR)    ? "SCHED_RR" :
                   (policy == SCHED_OTHER) ? "SCHED_OTHER" :
                   "???",
                   (int) sparam.sched_priority, cpu_affinity);

963

964
#endif
965

966
  // Lock memory from swapping. This is a process wide call (not constraint to this thread).
967
  mlockall(MCL_CURRENT | MCL_FUTURE);
968

969
  printf("waiting for sync (UE_thread_rx)\n");
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
970

971 972
  pthread_mutex_lock(&sync_mutex);
  printf("Locked sync_mutex, waiting (UE_thread_rx)\n");
973

974 975
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
976

977 978
  pthread_mutex_unlock(&sync_mutex);
  printf("unlocked sync_mutex, waiting (UE_thread_rx)\n");
979

980
  printf("Starting UE RX thread\n");
981 982

  while (!oai_exit) {
983
    if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
984
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" );
985
      exit_fun("nothing to add");
986
      return &UE_thread_rx_retval;
987
    }
988 989

    while (UE->instance_cnt_rx < 0) {
990 991
      // most of the time, the thread is waiting here
      pthread_cond_wait( &UE->cond_rx, &UE->mutex_rx );
992 993 994
    }

    if (pthread_mutex_unlock(&UE->mutex_rx) != 0) {
995
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" );
996
      exit_fun("nothing to add");
997
      return &UE_thread_rx_retval;
998 999
    }

1000
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, 1 );
1001
    for (i=0; i<2; i++) {
1002 1003
      if ((subframe_select( &UE->frame_parms, UE->slot_rx>>1 ) == SF_DL) ||
          (UE->frame_parms.frame_type == FDD)) {
1004
	/*
1005 1006
#ifdef OAI_USRP
	// this does the adjustments of RX signal amplitude to bring into least 12 significant bits
1007
	int slot_length = UE->frame_parms.samples_per_tti>>1;
1008
	int rx_offset = (UE->slot_rx)*slot_length + UE->rx_offset;
1009
	int frame_length = UE->frame_parms.samples_per_tti*10;
1010 1011 1012 1013 1014 1015 1016
	int aa;
	if (rx_offset > frame_length)
	  rx_offset-=frame_length;


	if (rx_offset >= 0) {
	  if (rx_offset + slot_length < frame_length)
1017 1018
	    for (aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++)
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)],
1019 1020 1021
		      slot_length);
	  else {
	    int diff = rx_offset + slot_length - frame_length;
1022 1023
	    for (aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++){
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)],
1024
		      slot_length-diff);
1025
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][0],
1026 1027 1028 1029 1030
		      diff);
	    }
	  }
	}
	else {
1031 1032
	    for (aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++){
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)],
1033
		      -rx_offset);
1034
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][0],
1035 1036 1037 1038
		      slot_length+rx_offset);
	    }
	}
#endif
1039
	*/
1040
        phy_procedures_UE_RX( UE, 0, 0, UE->mode, no_relay, NULL );
1041
      }
1042

1043
      if ((subframe_select( &UE->frame_parms, UE->slot_rx>>1 ) == SF_S) &&
1044
          ((UE->slot_rx&1) == 0)) {
1045
	/*
1046 1047
#ifdef OAI_USRP
	// this does the adjustments of RX signal amplitude to bring into least 12 significant bits
1048
	int slot_length = UE->frame_parms.samples_per_tti>>1;
1049
	int rx_offset = (UE->slot_rx)*slot_length + UE->rx_offset;
1050
	int frame_length = UE->frame_parms.samples_per_tti*10;
1051 1052 1053 1054 1055 1056
	if (rx_offset > frame_length)
	  rx_offset-=frame_length;
	int aa;

	if (rx_offset >= 0) {
	  if (rx_offset + slot_length < frame_length)
1057 1058
	    for (aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++)
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)],
1059 1060 1061
		      slot_length);
	  else {
	    int diff = rx_offset + slot_length - frame_length;
1062 1063
	    for (aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++){
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][rx_offset&(~0x3)],
1064
		      slot_length-diff);
1065
	      rescale((int16_t*)&UE->common_vars.rxdata[aa][0],
1066 1067 1068 1069 1070
		      diff);
	    }
	  }
	}
	else {
1071 1072
	  for (aa=0;aa<UE->frame_parms.nb_antennas_rx;aa++){
	    rescale((int16_t*)&UE->common_vars.rxdata[aa][(frame_length+rx_offset)&(~0x3)],
1073
		    -rx_offset);
1074
	    rescale((int16_t*)&UE->common_vars.rxdata[aa][0],
1075 1076 1077 1078
		    slot_length+rx_offset);
	  }
	}
#endif
1079
	*/
1080
        phy_procedures_UE_RX( UE, 0, 0, UE->mode, no_relay, NULL );
1081 1082
      }

1083
      if ((UE->mac_enabled==1) && (i==0)) {
1084 1085 1086
        ret = mac_xface->ue_scheduler(UE->Mod_id,
                                      UE->frame_tx,
                                      UE->slot_rx>>1,
1087
                                      subframe_select(&UE->frame_parms,UE->slot_tx>>1),
1088 1089 1090 1091
                                      0,
                                      0/*FIXME CC_id*/);

        if (ret == CONNECTION_LOST) {
1092
          LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, returning to PRACH\n",
1093
                 UE->Mod_id, UE->frame_rx, UE->slot_tx>>1 );
1094 1095
          UE->UE_mode[0] = PRACH;
        } else if (ret == PHY_RESYNCH) {
1096
          LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, trying to resynch\n",
1097
                 UE->Mod_id, UE->frame_rx, UE->slot_tx>>1 );
1098 1099
          UE->UE_mode[0] = RESYNCH;
        } else if (ret == PHY_HO_PRACH) {
1100
          LOG_I( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u, return to PRACH and perform a contention-free access\n",
1101
                 UE->Mod_id, UE->frame_rx, UE->slot_tx>>1 );
1102 1103
          UE->UE_mode[0] = PRACH;
        }
1104
      }
1105 1106 1107

      UE->slot_rx++;

1108 1109
      if (UE->slot_rx == 20) {
        UE->slot_rx = 0;
1110
        UE->frame_rx++;
1111
        VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX_UE, UE->frame_rx );
1112 1113
      }

1114
      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX_UE, UE->slot_rx>>1 );
1115
    }
1116 1117
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RX, 0 );

1118
    if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
1119 1120 1121
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" );
      exit_fun("noting to add");
      return &UE_thread_rx_retval;
1122 1123
    }

1124
    UE->instance_cnt_rx--;
1125
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, UE->instance_cnt_rx);
1126 1127 1128 1129 1130 1131

    if (pthread_mutex_unlock(&UE->mutex_rx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" );
      exit_fun("noting to add");
      return &UE_thread_rx_retval;
    }
1132 1133 1134
  }

  // thread finished
1135
  return &UE_thread_rx_retval;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
1136
}
1137

1138 1139 1140



1141

1142 1143 1144 1145
#define RX_OFF_MAX 10
#define RX_OFF_MIN 5
#define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2)

1146 1147 1148 1149 1150 1151 1152 1153 1154
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
 * - UE_thread_rx
 * - UE_thread_tx
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
1155 1156
void *UE_thread(void *arg)
{
1157 1158 1159
  UNUSED(arg)
  static int UE_thread_retval;
  PHY_VARS_UE *UE = PHY_vars_UE_g[0][0];
1160
  int spp = openair0_cfg[0].samples_per_packet;
1161
  int slot=1, frame=0, hw_subframe=0, rxpos=0, txpos=openair0_cfg[0].tx_scheduling_advance;
1162 1163 1164 1165 1166
#ifdef __AVX2__
  int dummy[2][spp] __attribute__((aligned(32)));
#else
  int dummy[2][spp] __attribute__((aligned(16)));
#endif
1167
  int dummy_dump = 0;
1168 1169
  int tx_enabled = 0;
  int start_rx_stream = 0;
1170 1171
  int rx_off_diff = 0;
  int rx_correction_timer = 0;
1172
  int first_rx = 0;
1173
  RTIME T0;
1174
  unsigned int rxs;
1175 1176 1177

  openair0_timestamp timestamp;

1178 1179 1180 1181
#ifdef NAS_UE
  MessageDef *message_p;
#endif

1182
#ifdef LOWLATENCY
1183 1184 1185
  struct sched_attr attr;
  unsigned int flags = 0;

1186 1187 1188
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
1189
  attr.sched_priority = 0;//sched_get_priority_max(SCHED_DEADLINE);
1190

1191 1192
  // This creates a .5 ms  reservation
  attr.sched_policy = SCHED_DEADLINE;
1193 1194 1195
  attr.sched_runtime  = 100000;
  attr.sched_deadline = 500000;
  attr.sched_period   = 500000;
1196 1197

  if (sched_setattr(0, &attr, flags) < 0 ) {
1198 1199
    perror("[SCHED] main eNB thread: sched_setattr failed\n");
    exit_fun("Nothing to add");
1200
    return &UE_thread_retval;
1201
  }
1202 1203 1204
  LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %lu started on CPU %d\n",
        (unsigned long)gettid(), sched_getcpu());

1205 1206 1207 1208
#else
  struct sched_param sp;
  sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp);
1209 1210
#endif

1211
  // Lock memory from swapping. This is a process wide call (not constraint to this thread).
1212 1213 1214 1215 1216
  mlockall(MCL_CURRENT | MCL_FUTURE);

  printf("waiting for sync (UE_thread)\n");
  pthread_mutex_lock(&sync_mutex);
  printf("Locked sync_mutex, waiting (UE_thread)\n");
1217

1218 1219
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
1220

1221 1222 1223 1224 1225
  pthread_mutex_unlock(&sync_mutex);
  printf("unlocked sync_mutex, waiting (UE_thread)\n");

  printf("starting UE thread\n");

1226 1227 1228 1229 1230
#ifdef NAS_UE
  message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
  itti_send_msg_to_task (TASK_NAS_UE, INSTANCE_DEFAULT, message_p);
#endif

1231 1232
  T0 = rt_get_time_ns();
  first_rx = 1;
1233
  rxpos=0;
1234

1235
  while (!oai_exit) {
1236 1237
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_SUBFRAME, hw_subframe );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_HW_FRAME, frame );
1238
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP, dummy_dump );
1239

1240

1241
    while (rxpos < (1+hw_subframe)*UE->frame_parms.samples_per_tti) {
1242
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
1243

1244 1245
#ifndef USRP_DEBUG

1246
      DevAssert( UE->frame_parms.nb_antennas_rx <= 2 );
1247
      void* rxp[2];
1248

1249
      for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
1250
        rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rxpos] : (void*)dummy[i];
1251 1252 1253 1254
      
      /*      if (dummy_dump == 0)
	      printf("writing %d samples to %d (first_rx %d)\n",spp - ((first_rx==1) ? rx_off_diff : 0),rxpos,first_rx);*/
      
1255 1256 1257 1258 1259
      if (UE->mode != loop_through_memory) {
	rxs = openair0.trx_read_func(&openair0,
				     &timestamp,
				     rxp,
				     spp - ((first_rx==1) ? rx_off_diff : 0),
1260
				     UE->frame_parms.nb_antennas_rx);
1261 1262

	if (rxs != (spp- ((first_rx==1) ? rx_off_diff : 0))) {
1263 1264 1265 1266 1267
	  printf("rx error: asked %d got %d ",spp - ((first_rx==1) ? rx_off_diff : 0),rxs);
	  if (UE->is_synchronized == 1) {
	    exit_fun("problem in rx");
	    return &UE_thread_retval;
	  }
1268
	}
1269
      }
1270

1271
      if (rx_off_diff !=0)
1272
	LOG_D(PHY,"frame %d, rx_offset %d, rx_off_diff %d\n",UE->frame_rx,UE->rx_offset,rx_off_diff);
1273

1274
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1275

1276
      // Transmit TX buffer based on timestamp from RX
1277
      if ((tx_enabled==1) && (UE->mode!=loop_through_memory)) {
1278
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
1279

1280
        DevAssert( UE->frame_parms.nb_antennas_tx <= 2 );
1281
        void* txp[2];
1282

1283
        for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
1284 1285 1286
          txp[i] = (void*)&txdata[i][txpos];

        openair0.trx_write_func(&openair0,
Raymond Knopp's avatar
Raymond Knopp committed
1287
                                (timestamp+openair0_cfg[0].tx_scheduling_advance-openair0_cfg[0].tx_sample_advance),
1288
                                txp,
1289
				spp - ((first_rx==1) ? rx_off_diff : 0),
1290
                                UE->frame_parms.nb_antennas_tx,
1291 1292
                                1);

1293
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
1294
      }
1295 1296
      else if (UE->mode == loop_through_memory)
	rt_sleep_ns(1000000);
1297
#else
1298
      // define USRP_DEBUG is active
1299 1300
      rt_sleep_ns(1000000);
#endif
1301

1302 1303 1304
      rx_off_diff = 0;
      first_rx = 0;

1305 1306 1307
      rxpos += spp;
      txpos += spp;

1308 1309
      if (txpos >= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti)
        txpos -= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti;
1310
    }
1311

1312 1313
    if (rxpos >= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti)
      rxpos -= 10*PHY_vars_UE_g[0][0]->frame_parms.samples_per_tti;
1314

1315 1316
    if (UE->is_synchronized == 1)  {
      LOG_D( HW, "UE_thread: hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 );
1317

1318
      if (start_rx_stream == 1) {
1319
	LOG_D(PHY,"Locking mutex_rx (IC %d)\n",UE->instance_cnt_rx);
1320
        if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
1321
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX thread\n" );
1322
          exit_fun("nothing to add");
1323 1324
          return &UE_thread_retval;
        }
1325

1326
        int instance_cnt_rx = ++UE->instance_cnt_rx;
1327

1328
	LOG_D(PHY,"Unlocking mutex_rx (IC %d)\n",instance_cnt_rx);
1329 1330 1331 1332 1333
        if (pthread_mutex_unlock(&UE->mutex_rx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX thread\n" );
          exit_fun("nothing to add");
          return &UE_thread_retval;
        }
1334

1335 1336 1337
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, instance_cnt_rx);


1338
        if (instance_cnt_rx == 0) {
1339
	  LOG_D(HW,"signalling rx thread to wake up, hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 );
1340 1341 1342 1343 1344
          if (pthread_cond_signal(&UE->cond_rx) != 0) {
            LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n" );
            exit_fun("nothing to add");
            return &UE_thread_retval;
          }
1345
	  
1346
	  LOG_D(HW,"signalled rx thread to wake up, hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 );
1347 1348 1349 1350
	  if (UE->mode == loop_through_memory) {
	    printf("Processing subframe %d",UE->slot_rx>>1);
	    getchar();
	  }
1351

1352 1353 1354
          if (UE->mode == rx_calib_ue) {
            if (frame == 10) {
              LOG_D(PHY,
1355
                    "[SCHED][UE] Found cell with N_RB_DL %"PRIu8", PHICH CONFIG (%d,%d), Nid_cell %"PRIu16", NB_ANTENNAS_TX %"PRIu8", frequency offset "PRIi32" Hz, RSSI (digital) %hu dB, measured Gain %d dB, total_rx_gain %"PRIu32" dB, USRP rx gain %f dB\n",
1356 1357 1358 1359 1360 1361 1362 1363
                    UE->frame_parms.N_RB_DL,
                    UE->frame_parms.phich_config_common.phich_duration,
                    UE->frame_parms.phich_config_common.phich_resource,
                    UE->frame_parms.Nid_cell,
                    UE->frame_parms.nb_antennas_tx_eNB,
                    UE->common_vars.freq_offset,
                    UE->measurements.rx_power_avg_dB[0],
                    UE->measurements.rx_power_avg_dB[0] - rx_input_level_dBm,
1364 1365
                    UE->rx_total_gain_dB,
                    openair0_cfg[0].rx_gain[0]
1366
                   );
1367 1368
              exit_fun("[HW][UE] UE in RX calibration mode, exiting");
              return &UE_thread_retval;
1369 1370
            }
          }
1371
        } else {
1372
          LOG_E( PHY, "[SCHED][UE] UE RX thread busy (IC %d)!!\n", instance_cnt_rx);
1373
	  if (instance_cnt_rx > 2) {
1374 1375 1376
	    exit_fun("instance_cnt_rx > 1");
	    return &UE_thread_retval;
	  }
1377 1378
        }

1379 1380
       
        if ((tx_enabled==1)&&(UE->mode != loop_through_memory)) {
1381 1382 1383 1384 1385 1386 1387

	  if (pthread_mutex_lock(&UE->mutex_tx) != 0) {
	    LOG_E( PHY, "[SCHED][UE] error locking mutex for UE TX thread\n" );
	    exit_fun("nothing to add");
	    return &UE_thread_retval;
	  }

1388

1389 1390 1391 1392 1393 1394 1395
          int instance_cnt_tx = ++UE->instance_cnt_tx;

          if (pthread_mutex_unlock(&UE->mutex_tx) != 0) {
            LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE TX thread\n" );
            exit_fun("nothing to add");
            return &UE_thread_retval;
          }
1396 1397
	  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX, instance_cnt_tx);

1398 1399 1400 1401

          if (instance_cnt_tx == 0) {
            if (pthread_cond_signal(&UE->cond_tx) != 0) {
              LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE TX thread\n" );
1402
              exit_fun("nothing to add");
1403
              return &UE_thread_retval;
1404
            }
1405
	    LOG_D(HW,"signalled tx thread to wake up, hw_frame %d, hw_subframe %d (time %lli)\n", frame, hw_subframe, rt_get_time_ns()-T0 );
1406

1407
          } else {
1408
            LOG_E( PHY, "[SCHED][UE] UE TX thread busy (IC %d)!!\n" );
1409
	    if (instance_cnt_tx>2) {
1410 1411 1412
	      exit_fun("instance_cnt_tx > 1");
	      return &UE_thread_retval;
	    }
1413 1414
          }
        }
1415

1416
      }
1417 1418 1419
    } else {
      // we are not yet synchronized
      if ((hw_subframe == 9) && (dummy_dump == 0)) {
1420 1421
        // Wake up initial synch thread
        if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
1422
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" );
1423
          exit_fun("nothing to add");
1424 1425
          return &UE_thread_retval;
        }
1426

1427
        int instance_cnt_synch = ++UE->instance_cnt_synch;
1428

1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439
        if (pthread_mutex_unlock(&UE->mutex_synch) != 0) {
          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE initial synch thread\n" );
          exit_fun("nothing to add");
          return &UE_thread_retval;
        }

        dummy_dump = 1;

        if (instance_cnt_synch == 0) {
          if (pthread_cond_signal(&UE->cond_synch) != 0) {
            LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n" );
1440
            exit_fun("nothing to add");
1441
            return &UE_thread_retval;
1442
          }
1443 1444 1445 1446
        } else {
          LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
          exit_fun("nothing to add");
          return &UE_thread_retval;
1447
        }
1448 1449
      }
    }
1450

1451 1452
    hw_subframe++;
    slot+=2;
1453

1454
    if (hw_subframe==10) {
1455 1456 1457 1458
      hw_subframe = 0;
      first_rx = 1;
      frame++;
      slot = 1;
1459

1460 1461 1462
      int fail = pthread_mutex_lock(&UE->mutex_synch);
      int instance_cnt_synch = UE->instance_cnt_synch;
      fail = fail || pthread_mutex_unlock(&UE->mutex_synch);
1463

1464 1465 1466 1467 1468 1469 1470 1471
      if (fail) {
        LOG_E( PHY, "[SCHED][UE] error (un-)locking mutex for UE synch\n" );
        exit_fun("noting to add");
        return &UE_thread_retval;
      }

      if (instance_cnt_synch < 0) {
        // the UE_thread_synch is ready
1472 1473
        if (UE->is_synchronized == 1) {
          rx_off_diff = 0;
1474
          LTE_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; // for macro FRAME_LENGTH_COMPLEX_SAMPLES
1475

1476
	  //	  LOG_I(PHY,"UE->rx_offset %d\n",UE->rx_offset);
1477
          if ((UE->rx_offset > RX_OFF_MAX) && (start_rx_stream == 0)) {
1478 1479 1480
            start_rx_stream=1;
            frame=0;
            // dump ahead in time to start of frame
1481 1482

#ifndef USRP_DEBUG
1483
	    if (UE->mode != loop_through_memory) {
1484
	      LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
1485 1486 1487 1488
	      rxs = openair0.trx_read_func(&openair0,
					   &timestamp,
					   (void**)rxdata,
					   UE->rx_offset,
1489
					   UE->frame_parms.nb_antennas_rx);
1490 1491 1492 1493 1494 1495
	      if (rxs != UE->rx_offset) {
		exit_fun("problem in rx");
		return &UE_thread_retval;
	      }
	      UE->rx_offset=0;
	      tx_enabled = 1;
1496
	    }
1497 1498
	    else
	      rt_sleep_ns(1000000);
1499
#else
1500
            rt_sleep_ns(10000000);
1501
#endif
1502

1503 1504 1505 1506
          } else if ((UE->rx_offset<(FRAME_LENGTH_COMPLEX_SAMPLES/2)) &&
		     (UE->rx_offset > RX_OFF_MIN) && 
		     (start_rx_stream==1) && 
		     (rx_correction_timer == 0)) {
1507
            rx_off_diff = -UE->rx_offset + RX_OFF_MIN;
1508
	    LOG_D(PHY,"UE->rx_offset %d > %d, diff %d\n",UE->rx_offset,RX_OFF_MIN,rx_off_diff);
1509
            rx_correction_timer = 5;
1510 1511 1512 1513 1514
          } else if ((UE->rx_offset>(FRAME_LENGTH_COMPLEX_SAMPLES/2)) && 
		     (UE->rx_offset < (FRAME_LENGTH_COMPLEX_SAMPLES-RX_OFF_MIN)) &&
		     (start_rx_stream==1) && 
		     (rx_correction_timer == 0)) {   // moving to the left so drop rx_off_diff samples
            rx_off_diff = FRAME_LENGTH_COMPLEX_SAMPLES - RX_OFF_MIN - UE->rx_offset;
1515
	    LOG_D(PHY,"UE->rx_offset %d < %d, diff %d\n",UE->rx_offset,FRAME_LENGTH_COMPLEX_SAMPLES-RX_OFF_MIN,rx_off_diff);
1516

1517 1518 1519 1520 1521 1522 1523 1524
            rx_correction_timer = 5;
          }

          if (rx_correction_timer>0)
            rx_correction_timer--;
        }

        dummy_dump=0;
1525 1526
      }
    }
1527

1528 1529 1530 1531
#if defined(ENABLE_ITTI)
    itti_update_lte_time(frame, slot);
#endif
  }
1532

1533
  return &UE_thread_retval;
1534 1535 1536 1537 1538
}




1539 1540 1541 1542 1543 1544 1545 1546
/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
 * - UE_thread_tx
 * - UE_thread_rx
 * - UE_thread_synch
 * and the locking between them.
 */
1547 1548
void init_UE_threads(void)
{
1549
  PHY_VARS_UE *UE = PHY_vars_UE_g[0][0];
1550

1551 1552 1553 1554 1555 1556 1557 1558
  pthread_attr_init (&attr_UE_thread);
  pthread_attr_setstacksize(&attr_UE_thread,8192);//5*PTHREAD_STACK_MIN);

#ifndef LOWLATENCY
  sched_param_UE_thread.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&attr_UE_thread,&sched_param_UE_thread);
#endif

1559 1560 1561 1562
  // the threads are not yet active, therefore access is allowed without locking
  UE->instance_cnt_tx = -1;
  UE->instance_cnt_rx = -1;
  UE->instance_cnt_synch = -1;
1563 1564 1565 1566 1567 1568 1569
  pthread_mutex_init(&UE->mutex_tx,NULL);
  pthread_mutex_init(&UE->mutex_rx,NULL);
  pthread_mutex_init(&UE->mutex_synch,NULL);
  pthread_cond_init(&UE->cond_tx,NULL);
  pthread_cond_init(&UE->cond_rx,NULL);
  pthread_cond_init(&UE->cond_synch,NULL);
  pthread_create(&UE->thread_tx,NULL,UE_thread_tx,(void*)UE);
1570
  pthread_setname_np( UE->thread_tx, "UE_thread_tx" );
1571
  pthread_create(&UE->thread_rx,NULL,UE_thread_rx,(void*)UE);
1572 1573 1574
  pthread_setname_np( UE->thread_rx, "UE_thread_rx" );
  pthread_create(&UE->thread_synch,NULL,UE_thread_synch,(void*)UE);
  pthread_setname_np( UE->thread_synch, "UE_thread_synch" );
1575 1576 1577 1578 1579
  UE->frame_tx = 0;
  UE->frame_rx = 0;
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1580
#ifdef OPENAIR2
1581 1582
void fill_ue_band_info(void)
{
1583 1584 1585 1586 1587 1588

  UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
  int i,j;

  bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;

1589 1590 1591
  for (i=0; i<bands_to_scan.nbands; i++) {

    for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
1592
      if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
1593 1594 1595 1596 1597 1598 1599 1600 1601 1602 1603 1604 1605
        memcpy(&bands_to_scan.band_info[i],
               &eutra_bands[j],
               sizeof(eutra_band_t));

        printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
               bands_to_scan.band_info[i].band,
               UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
               bands_to_scan.band_info[i].dl_min,
               bands_to_scan.band_info[i].dl_max,
               bands_to_scan.band_info[i].ul_min,
               bands_to_scan.band_info[i].ul_max,
               (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
        break;
1606 1607 1608
      }
  }
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1609
#endif
1610 1611 1612 1613 1614 1615

int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs])
{

  int i, CC_id;
  LTE_DL_FRAME_PARMS *frame_parms;
1616
  
1617
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1618
  if (phy_vars_ue[CC_id]) {
1619
  frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
1620 1621 1622 1623
  } else {
    printf("phy_vars_UE[%d] not initialized\n", CC_id);
    return(-1);
  }
1624

1625
  /*
1626 1627 1628 1629 1630 1631 1632 1633
  if (frame_parms->frame_type == TDD) {
    if (frame_parms->N_RB_DL == 100)
      N_TA_offset = 624;
    else if (frame_parms->N_RB_DL == 50)
      N_TA_offset = 624/2;
    else if (frame_parms->N_RB_DL == 25)
      N_TA_offset = 624/4;
  }
1634
  */
1635

1636
    // replace RX signal buffers with mmaped HW versions
1637 1638 1639 1640 1641
  rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
  txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );

  for (i=0; i<frame_parms->nb_antennas_rx; i++) {
    printf( "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i );
1642
    free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
1643
    rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
1644
    phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
1645 1646 1647 1648
  }
  
  for (i=0; i<frame_parms->nb_antennas_tx; i++) {
    printf( "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n", CC_id, i, downlink_frequency[CC_id][i], rf_map[CC_id].card, rf_map[CC_id].chain+i );
1649
    free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
1650
    txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
1651
    phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
1652 1653
  }
  
1654 1655
  // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x]
  // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x]
1656 1657
  // be careful when releasing memory!
  // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
1658

1659
  }
1660

1661
  return 0;
1662
}