lte-ue.c 56.9 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */
21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47

/*! \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>
48
#include <sys/sysinfo.h>
49 50 51 52 53 54

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

#include "PHY/defs.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
55
#ifdef OPENAIR2
56 57
#include "LAYER2/MAC/defs.h"
#include "RRC/LITE/extern.h"
Raymond Knopp's avatar
 
Raymond Knopp committed
58
#endif
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86
#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;

Raymond Knopp's avatar
Raymond Knopp committed
87
void init_UE_threads(int nb_inst);
88
void *UE_thread(void *arg);
Raymond Knopp's avatar
Raymond Knopp committed
89
void init_UE(int nb_inst);
90 91 92 93 94

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

95

96 97
extern openair0_config_t openair0_cfg[MAX_CARDS];
extern uint32_t          downlink_frequency[MAX_NUM_CCs][4];
98
extern int32_t           uplink_frequency_offset[MAX_NUM_CCs][4];
99 100 101 102 103
extern int oai_exit;

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

104 105
//extern unsigned int tx_forward_nsamps;
//extern int tx_delay;
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

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;

132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148
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},
149
  {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
150 151 152 153 154 155 156 157 158 159 160 161 162 163
  {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},
};

164 165 166 167
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

Raymond Knopp's avatar
Raymond Knopp committed
168
void init_UE(int nb_inst) {
169 170

  int error_code;
Raymond Knopp's avatar
Raymond Knopp committed
171 172
  int inst;
  PHY_VARS_UE *UE;
Raymond Knopp's avatar
Raymond Knopp committed
173
  int ret;
Raymond Knopp's avatar
Raymond Knopp committed
174 175 176 177 178 179

  for (inst=0;inst<nb_inst;inst++) {
    printf("Intializing UE Threads for instance %d ...\n",inst);
    init_UE_threads(inst);
    sleep(1);
    UE = PHY_vars_UE_g[inst][0];
Raymond Knopp's avatar
Raymond Knopp committed
180 181

    ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]);
Rohit Gupta's avatar
Rohit Gupta committed
182 183 184
    if (ret !=0){
       exit_fun("Error loading device library");
    }
Raymond Knopp's avatar
Raymond Knopp committed
185
    UE->rfdevice.host_type = BBU_HOST;
Raymond Knopp's avatar
Raymond Knopp committed
186
    //    UE->rfdevice.type      = NONE_DEV;
Raymond Knopp's avatar
Raymond Knopp committed
187 188 189 190 191 192 193 194 195
    error_code = pthread_create(&UE->proc.pthread_ue, &UE->proc.attr_ue, 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( UE->proc.pthread_ue, "main UE" );
    }
196 197 198 199 200 201 202 203 204 205 206 207 208
  }

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

209 210
/*!
 * \brief This is the UE synchronize thread.
211
 * It performs band scanning and synchonization.
212 213 214
 * \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.
 */
215 216
static void *UE_thread_synch(void *arg)
{
217 218 219
  static int UE_thread_synch_retval;
  int i, hw_slot_offset;
  PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
220 221
  int current_band = 0;
  int current_offset = 0;
222
  sync_mode_t sync_mode = pbch;
223
  int CC_id = UE->CC_id;
224 225
  int ind;
  int found;
226
  int freq_offset=0;
227 228 229 230 231

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

laurent's avatar
laurent committed
232
#ifndef DEADLINE_SCHEDULER
233 234 235 236 237 238 239 240 241
  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);

242 243
  #ifdef CPU_AFFINITY
  if (get_nprocs() >2)
244
  {
245 246 247 248 249 250 251 252 253
    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");
    }
254
  }
255 256
  #endif

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 299 300 301
  /* 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


302

303

304
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
305 306
  ind = 0;
  found = 0;
307 308


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

314
      if ((eutra_bands[ind].dl_min <= downlink_frequency[0][0]) && (eutra_bands[ind].dl_max >= downlink_frequency[0][0])) {
315 316
	for (i=0; i<4; i++)
	  uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
317 318 319 320

        found = 1;
        break;
      }
321

322
      ind++;
323 324
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
  
325 326
    if (found == 0) {
      exit_fun("Can't find EUTRA band for frequency");
327
      return &UE_thread_synch_retval;
328
    }
329

330 331


332

333 334


335
    LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", downlink_frequency[0][0], downlink_frequency[0][0]+uplink_frequency_offset[0][0],oai_exit, openair0_cfg[0].rx_num_channels);
336

337 338 339 340 341 342
    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
      openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
      if (uplink_frequency_offset[CC_id][i] != 0) // 
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
343
      else //FDD
344
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
345 346
    }

347
    sync_mode = pbch;
348

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

352 353 354 355 356 357 358
    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
      downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].dl_min;
      uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[CC_id].ul_min-bands_to_scan.band_info[CC_id].dl_min;
      
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
359 360
    }
  }
361

Raymond Knopp's avatar
Raymond Knopp committed
362

363 364 365 366 367 368 369 370 371
  pthread_mutex_lock(&sync_mutex);
  printf("Locked sync_mutex, waiting (UE_sync_thread)\n");

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

  pthread_mutex_unlock(&sync_mutex);
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");

Raymond Knopp's avatar
Raymond Knopp committed
372 373 374 375 376
  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { 
    LOG_E(HW,"Could not start the device\n");
    oai_exit=1;
  }

377
  while (oai_exit==0) {
378

379
    if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) {
380
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" );
381
      exit_fun("noting to add");
382 383
      return &UE_thread_synch_retval;
    }
384
    
385

386
    while (UE->proc.instance_cnt_synch < 0) {
387
      // the thread waits here most of the time
388
      pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
389
    }
390

391
    if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) {
392 393 394 395
      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for UE Initial Synch thread\n" );
      exit_fun("nothing to add");
      return &UE_thread_synch_retval;
    }
396

397
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 1 );
398 399

    switch (sync_mode) {
400
    case pss:
401 402
      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);
403 404 405 406 407 408 409
      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;
      }

410
      if (current_band==bands_to_scan.nbands) {
411 412
        current_band=0;
        oai_exit=1;
413
      }
414

415 416 417
      for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
	downlink_frequency[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].dl_min+current_offset;
	uplink_frequency_offset[UE->rf_map.card][UE->rf_map.chain+i] = bands_to_scan.band_info[current_band].ul_min-bands_to_scan.band_info[0].dl_min + current_offset;
418

419 420 421 422 423
	openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
	openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
	openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
	if (UE->UE_scan_carrier) {
	  openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
424
	}
425
	
426
      }
427

428 429
      break;
 
430
    case pbch:
431

Rohit Gupta's avatar
Rohit Gupta committed
432
      LOG_I(PHY,"[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
433
      if (initial_sync( UE, UE->mode ) == 0) {
434

435
        hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
436 437 438 439 440 441 442 443
        LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
          hw_slot_offset,
          freq_offset,
          UE->rx_total_gain_dB,
          downlink_frequency[0][0]+freq_offset,
          downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
          UE->UE_scan_carrier );

444 445 446 447
	if (UE->UE_scan_carrier == 1) {

	  UE->UE_scan_carrier = 0;
	  // rerun with new cell parameters and frequency-offset
448 449 450 451 452
	  for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
	    openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
	    openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= UE->common_vars.freq_offset;
	    openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =  openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
	    downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
453 454 455
	    freq_offset=0;	    
	  }

456
	  // reconfigure for potentially different bandwidth
457
	  switch(UE->frame_parms.N_RB_DL) {
458
	  case 6:
459 460 461
	    openair0_cfg[UE->rf_map.card].sample_rate =1.92e6;
	    openair0_cfg[UE->rf_map.card].rx_bw          =.96e6;
	    openair0_cfg[UE->rf_map.card].tx_bw          =.96e6;
462
	    //            openair0_cfg[0].rx_gain[0] -= 12;
463 464
	    break;
	  case 25:
465 466 467
	    openair0_cfg[UE->rf_map.card].sample_rate =7.68e6;
	    openair0_cfg[UE->rf_map.card].rx_bw          =2.5e6;
	    openair0_cfg[UE->rf_map.card].tx_bw          =2.5e6;
468
	    //            openair0_cfg[0].rx_gain[0] -= 6;
469 470
	    break;
	  case 50:
471 472 473
	    openair0_cfg[UE->rf_map.card].sample_rate =15.36e6;
	    openair0_cfg[UE->rf_map.card].rx_bw          =5.0e6;
	    openair0_cfg[UE->rf_map.card].tx_bw          =5.0e6;
474
	    //            openair0_cfg[0].rx_gain[0] -= 3;
475 476
	    break;
	  case 100:
477 478 479
	    openair0_cfg[UE->rf_map.card].sample_rate=30.72e6;
	    openair0_cfg[UE->rf_map.card].rx_bw=10.0e6;
	    openair0_cfg[UE->rf_map.card].tx_bw=10.0e6;
480
	    //            openair0_cfg[0].rx_gain[0] -= 0;
481 482
	    break;
	  }
483
	
Rohit Gupta's avatar
Rohit Gupta committed
484
	  UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
Raymond Knopp's avatar
Raymond Knopp committed
485 486
	  //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
	  UE->rfdevice.trx_stop_func(&UE->rfdevice);	  
487
	  sleep(1);
488
	  init_frame_parms(&UE->frame_parms,1);
Raymond Knopp's avatar
Raymond Knopp committed
489
	  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { 
490 491 492
	    LOG_E(HW,"Could not start the device\n");
	    oai_exit=1;
	  }
493 494 495
	}
	else {
	  UE->is_synchronized = 1;
496

497 498
	  if( UE->mode == rx_dump_frame ){
	    FILE *fd;
499
	    if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present 
500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
	      if ((fd = fopen("rxsig_frame0.dat","w")) != NULL) {
		fwrite((void*)&UE->common_vars.rxdata[0][0],
		       sizeof(int32_t),
		       10*UE->frame_parms.samples_per_tti,
		       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;
	    }
	  }
518
	}
519 520 521
      } else {
        // initial sync failed
        // calculate new offset and try again
522 523 524 525 526 527 528 529 530 531
	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" );
532
	    FILE *fd;
533
	    if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
534
	      fwrite((void*)&UE->common_vars.rxdata[0][0],
535
		     sizeof(int32_t),
536
		     10*UE->frame_parms.samples_per_tti,
537 538 539 540 541
		     fd);
	      LOG_I(PHY,"Dummping Frame ... bye bye \n");
	      fclose(fd);
	      exit(0);
	    }
542 543 544 545 546 547 548 549 550
	    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,
551
               UE->rx_total_gain_dB,
552 553
               downlink_frequency[0][0]+freq_offset,
               downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
554

555 556 557 558 559 560 561 562
	for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
	  openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
	  openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
	  
	  openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
	  
	  if (UE->UE_scan_carrier==1) {
	    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
563
	  }
564
	}
565

566 567
	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
	    
568
      }// initial_sync=0
569

570
      break;
571

572 573 574 575
    case si:
    default:
      break;
    }
576

577

578
    if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) {
579 580 581 582
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE synch\n" );
      exit_fun("noting to add");
      return &UE_thread_synch_retval;
    }
583

584
    // indicate readiness
585
    UE->proc.instance_cnt_synch--;
586

587
    if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) {
588 589 590
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE synch\n" );
      exit_fun("noting to add");
      return &UE_thread_synch_retval;
591
    }
592

593
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
594
  }  // while !oai_exit
595

596
  return &UE_thread_synch_retval;
597 598
}

599

600

601
/*!
602
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
603
 * This thread performs the phy_procedures_UE_RX() on every received slot.
604
 * then, if TX is enabled it performs TX for n+4. 
605 606 607
 * \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.
 */
608

609
static void *UE_thread_rxn_txnp4(void *arg)
610
{
Raymond Knopp's avatar
Raymond Knopp committed
611
  static int UE_thread_rxtx_retval;
612
  UE_rxtx_proc_t *proc = (UE_rxtx_proc_t *)arg;
613
  int ret;
614 615
  PHY_VARS_UE *UE=PHY_vars_UE_g[0][proc->CC_id];
  proc->instance_cnt_rxtx=-1;
616

617

laurent's avatar
laurent committed
618
#ifdef DEADLINE_SCHEDULER
619

620 621 622
  struct sched_attr attr;
  unsigned int flags = 0;

623 624 625
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
626
  attr.sched_priority = 0;
627

628
  // This creates a .5ms reservation every 1ms period
629 630 631 632
  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
633 634

  if (sched_setattr(0, &attr, flags) < 0 ) {
Raymond Knopp's avatar
Raymond Knopp committed
635 636
    perror("[SCHED] UE_thread_rxtx : sched_setattr failed\n");
    return &UE_thread_rxtx_retval;
637 638
  }

639
#else
640 641 642 643 644 645 646 647 648
  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);

649 650
  #ifdef CPU_AFFINITY
  if (get_nprocs() >2)
651
  {
652 653 654 655 656 657 658 659 660
    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");
    }
661
  }
662 663
  #endif

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
  /* 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);

706

707
#endif
708

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

712
  printf("waiting for sync (UE_thread_rxn_txnp4)\n");
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
713

714
  pthread_mutex_lock(&sync_mutex);
715
  printf("Locked sync_mutex, waiting (UE_thread_rxn_txnp4)\n");
716

717 718
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
719

720 721 722 723 724 725 726 727 728 729 730
#if 1 // 2016-11-23 wilson add pthread name to the logging
#define THREAD_NAME_LEN 16
  char threadname[THREAD_NAME_LEN];
  ret = pthread_getname_np(proc->pthread_rxtx, threadname, THREAD_NAME_LEN);
  if (ret != 0)
  {
   perror("pthread_getname_np : ");
   exit_fun("Error getting thread name");
  }
#endif

731
  pthread_mutex_unlock(&sync_mutex);
Raymond Knopp's avatar
Raymond Knopp committed
732
  printf("unlocked sync_mutex, waiting (UE_thread_rxtx)\n");
733

734
  printf("Starting UE RXN_TXNP4 thread (%s)\n", threadname);
735 736

  while (!oai_exit) {
737
    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
Raymond Knopp's avatar
Raymond Knopp committed
738
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
739
      exit_fun("nothing to add");
Raymond Knopp's avatar
Raymond Knopp committed
740
      return &UE_thread_rxtx_retval;
741
    }
742

743
    while (proc->instance_cnt_rxtx < 0) {
744
      // most of the time, the thread is waiting here
745
      pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
746 747
    }

748 749
    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
750
      exit_fun("nothing to add");
Raymond Knopp's avatar
Raymond Knopp committed
751
      return &UE_thread_rxtx_retval;
752 753
    }

754 755 756 757 758
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 1 );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_UE+(proc->subframe_rx&1), proc->subframe_rx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_UE+(proc->subframe_tx&1), proc->subframe_tx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE+(proc->subframe_rx&1), proc->frame_rx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE+(proc->subframe_tx&1), proc->frame_tx );
759

760 761 762 763
    lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
    if ((sf_type == SF_DL) ||
        (UE->frame_parms.frame_type == FDD) ||
        (sf_type == SF_S)) {
764
    
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780
      if (UE->frame_parms.frame_type == TDD) {
      LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
          threadname,
          UE->frame_parms.tdd_config,
          (sf_type==SF_DL? "SF_DL" :
          (sf_type==SF_UL? "SF_UL" :
          (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
      } else {
        LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
            threadname,
            (UE->frame_parms.frame_type==FDD? "FDD":
            (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
            (sf_type==SF_DL? "SF_DL" :
            (sf_type==SF_UL? "SF_UL" :
            (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
      }
781 782
      phy_procedures_UE_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL );
    }
783
    
784
    if (UE->mac_enabled==1) {
785

786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804
      ret = mac_xface->ue_scheduler(UE->Mod_id,
				    proc->frame_tx,
				    proc->subframe_rx,
				    subframe_select(&UE->frame_parms,proc->subframe_tx),
				    0,
				    0/*FIXME CC_id*/);
      
      if (ret == CONNECTION_LOST) {
	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, returning to PRACH\n",
	       UE->Mod_id, proc->frame_rx, proc->subframe_tx );
	UE->UE_mode[0] = PRACH;
      } else if (ret == PHY_RESYNCH) {
	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u RRC Connection lost, trying to resynch\n",
	       UE->Mod_id, proc->frame_rx, proc->subframe_tx );
	UE->UE_mode[0] = RESYNCH;
      } else if (ret == PHY_HO_PRACH) {
	LOG_I( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u, return to PRACH and perform a contention-free access\n",
	       UE->Mod_id, proc->frame_rx, proc->subframe_tx );
	UE->UE_mode[0] = PRACH;
805 806
      }
    }
807 808 809 810 811 812

    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
	(UE->frame_parms.frame_type == FDD) ||
	(subframe_select( &UE->frame_parms, proc->subframe_tx ) == SF_S)) {

      if (UE->mode != loop_through_memory) {
Rohit Gupta's avatar
Rohit Gupta committed
813
	phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
814 815 816
      }
    }

817 818
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->subframe_rx&1), 0 );

819 820
    
    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
Raymond Knopp's avatar
Raymond Knopp committed
821
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
822
      exit_fun("noting to add");
Raymond Knopp's avatar
Raymond Knopp committed
823
      return &UE_thread_rxtx_retval;
824
    }
825 826 827 828 829
    
    proc->instance_cnt_rxtx--;
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, proc->instance_cnt_rxtx);
    
    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
Raymond Knopp's avatar
Raymond Knopp committed
830
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
831
      exit_fun("noting to add");
Raymond Knopp's avatar
Raymond Knopp committed
832
      return &UE_thread_rxtx_retval;
833
    }
834
  }
835
  
836
  // thread finished
Raymond Knopp's avatar
Raymond Knopp committed
837
  return &UE_thread_rxtx_retval;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
838
}
839

840 841 842



843

844 845 846 847
#define RX_OFF_MAX 10
#define RX_OFF_MIN 5
#define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2)

848 849 850
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
851 852
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
853 854 855 856
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
857 858 859 860 861 862

void *UE_thread(void *arg) {

  static int UE_thread_retval;
  PHY_VARS_UE *UE = PHY_vars_UE_g[0][0];
  //  int tx_enabled = 0;
Rohit Gupta's avatar
Rohit Gupta committed
863
  unsigned int rxs,txs;
864 865
  int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
  openair0_timestamp timestamp,timestamp1;
Rohit Gupta's avatar
Rohit Gupta committed
866
  void* rxp[2], *txp[2];
867 868 869 870 871

#ifdef NAS_UE
  MessageDef *message_p;
#endif

872
  int start_rx_stream = 0;
873 874
  int rx_off_diff = 0;
  int rx_correction_timer = 0;
Rohit Gupta's avatar
Rohit Gupta committed
875
  int i;
876

877 878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930
#ifdef DEADLINE_SCHEDULER

  struct sched_attr attr;
  unsigned int flags = 0;

  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
  attr.sched_priority = 0;//sched_get_priority_max(SCHED_DEADLINE);

  // This creates a .5 ms  reservation
  attr.sched_policy = SCHED_DEADLINE;
  attr.sched_runtime  = 100000;
  attr.sched_deadline = 500000;
  attr.sched_period   = 500000;

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

#else
  struct sched_param sp;
  sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp);
#endif

  // Lock memory from swapping. This is a process wide call (not constraint to this thread).
  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");

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

  pthread_mutex_unlock(&sync_mutex);
  printf("unlocked sync_mutex, waiting (UE_thread)\n");

  printf("starting UE thread\n");

#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 

  while (!oai_exit) {
    
    if (UE->is_synchronized == 0) {
      
931
      if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) {
932 933 934 935 936
	LOG_E( PHY, "[SCHED][UE] verror locking mutex for UE initial synch thread\n" );
	exit_fun("nothing to add");
	return &UE_thread_retval;
      }
      
937
      int instance_cnt_synch = UE->proc.instance_cnt_synch;
938
      
939
      if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) {
940 941 942 943 944 945 946 947 948 949 950
	LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE initial synch thread\n" );
	exit_fun("nothing to add");
	return &UE_thread_retval;
      }
      
      if (instance_cnt_synch < 0) {  // we can invoke the synch
	// grab 10 ms of signal and wakeup synch thread
	for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
	  rxp[i] = (void*)&rxdata[i][0];
      
	if (UE->mode != loop_through_memory) {
Raymond Knopp's avatar
Raymond Knopp committed
951 952 953 954 955
	  rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					   &timestamp,
					   rxp,
					   UE->frame_parms.samples_per_tti*10,
					   UE->frame_parms.nb_antennas_rx);
Raymond Knopp's avatar
Raymond Knopp committed
956 957 958 959 960 961

	  
	  if (rxs!=UE->frame_parms.samples_per_tti*10) {
	    exit_fun("problem in rx");
	    return &UE_thread_retval;
	  }
962
	}
Raymond Knopp's avatar
Raymond Knopp committed
963

964
	instance_cnt_synch = ++UE->proc.instance_cnt_synch;
965
	if (instance_cnt_synch == 0) {
966
	  if (pthread_cond_signal(&UE->proc.cond_synch) != 0) {
967 968 969 970 971 972 973 974 975 976 977 978 979 980 981 982
	    LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE sync thread\n" );
	    exit_fun("nothing to add");
	    return &UE_thread_retval;
	  }
	} else {
	  LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
	  exit_fun("nothing to add");
	  return &UE_thread_retval;
	}
      } // 
      else {
	// grab 10 ms of signal into dummy buffer

	if (UE->mode != loop_through_memory) {
	  for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
	    rxp[i] = (void*)&dummy_rx[i][0];
983
	  for (int sf=0;sf<10;sf++) {
984
	    //	    printf("Reading dummy sf %d\n",sf);
Raymond Knopp's avatar
Raymond Knopp committed
985 986 987 988 989
	    rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					     &timestamp,
					     rxp,
					     UE->frame_parms.samples_per_tti,
					     UE->frame_parms.nb_antennas_rx);
Raymond Knopp's avatar
Raymond Knopp committed
990 991 992 993 994 995

	    if (rxs!=UE->frame_parms.samples_per_tti){
	      exit_fun("problem in rx");
	      return &UE_thread_retval;
	    }

996
	  }
997 998 999
	}
      }
      
1000
    } // UE->is_synchronized==0
1001
    else {
1002 1003 1004
      if (start_rx_stream==0) {
	start_rx_stream=1;
	if (UE->mode != loop_through_memory) {
1005 1006

	  if (UE->no_timing_correction==0) {
Rohit Gupta's avatar
Rohit Gupta committed
1007
	    LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
1008 1009 1010 1011 1012 1013 1014 1015 1016
	    rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					     &timestamp,
					     (void**)rxdata,
					     UE->rx_offset,
					     UE->frame_parms.nb_antennas_rx);
	    if (rxs != UE->rx_offset) {
	      exit_fun("problem in rx");
	      return &UE_thread_retval;
	    }
1017 1018
	  }
	  UE->rx_offset=0;
1019 1020 1021 1022
	  UE->proc.proc_rxtx[0].frame_rx++;
	  UE->proc.proc_rxtx[1].frame_rx++;

	  // read in first symbol
Raymond Knopp's avatar
Raymond Knopp committed
1023 1024 1025 1026 1027
	  rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					   &timestamp,
					   (void**)rxdata,
					   UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
					   UE->frame_parms.nb_antennas_rx);
1028 1029 1030 1031 1032 1033 1034 1035 1036 1037
	  slot_fep(UE,
		   0,
		   0,
		   0,
		   0,
		   0);
	  if (rxs != UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0) {
	    exit_fun("problem in rx");
	    return &UE_thread_retval;
	  }
1038 1039 1040
	} //UE->mode != loop_through_memory
	else
	  rt_sleep_ns(1000000);
1041

1042
      }// start_rx_stream==0
1043
      else {
fnabet's avatar
fnabet committed
1044 1045
	//UE->proc.proc_rxtx[0].frame_rx++;
	//UE->proc.proc_rxtx[1].frame_rx++;
Rohit Gupta's avatar
Rohit Gupta committed
1046
	
1047
	for (int sf=0;sf<10;sf++) {
Rohit Gupta's avatar
Rohit Gupta committed
1048
	  for (i=0; i<UE->frame_parms.nb_antennas_rx; i++) 
1049 1050
	    rxp[i] = (void*)&rxdata[i][UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti)];
	  // grab signal for subframe
1051
	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
1052 1053
	  if (UE->mode != loop_through_memory) {
	    if (sf<9) {
Raymond Knopp's avatar
Raymond Knopp committed
1054 1055 1056 1057 1058
	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					       &timestamp,
					       rxp,
					       UE->frame_parms.samples_per_tti,
					       UE->frame_parms.nb_antennas_rx);
Rohit Gupta's avatar
Rohit Gupta committed
1059 1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073
	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
	      // prepare tx buffer pointers
	      
	      for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
		txp[i] = (void*)&UE->common_vars.txdata[i][((sf+2)%10)*UE->frame_parms.samples_per_tti];
	      
	      txs = UE->rfdevice.trx_write_func(&UE->rfdevice,
						timestamp+
						(2*UE->frame_parms.samples_per_tti) -
						UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
						openair0_cfg[0].tx_sample_advance,
						txp,
						UE->frame_parms.samples_per_tti,
						UE->frame_parms.nb_antennas_tx,
						1);
Rohit Gupta's avatar
Rohit Gupta committed
1074 1075 1076 1077 1078
              if (txs !=  UE->frame_parms.samples_per_tti) {
                 LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, UE->frame_parms.samples_per_tti);
                 exit_fun( "problem transmitting samples" );
              }

Rohit Gupta's avatar
Rohit Gupta committed
1079 1080
	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );

1081
	    }
Rohit Gupta's avatar
Rohit Gupta committed
1082
	    
1083
	    else {
Raymond Knopp's avatar
Raymond Knopp committed
1084 1085 1086 1087 1088
	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					       &timestamp,
					       rxp,
					       UE->frame_parms.samples_per_tti-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0,
					       UE->frame_parms.nb_antennas_rx);
Rohit Gupta's avatar
Rohit Gupta committed
1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103
	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
	      // prepare tx buffer pointers
	      
	      for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
		txp[i] = (void*)&UE->common_vars.txdata[i][((sf+2)%10)*UE->frame_parms.samples_per_tti];
	      
	      txs = UE->rfdevice.trx_write_func(&UE->rfdevice,
						timestamp+
						(2*UE->frame_parms.samples_per_tti) -
						UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
						openair0_cfg[0].tx_sample_advance,
						txp,
						UE->frame_parms.samples_per_tti - rx_off_diff,
						UE->frame_parms.nb_antennas_tx,
						1);
Rohit Gupta's avatar
Rohit Gupta committed
1104 1105 1106 1107
              if (txs !=  UE->frame_parms.samples_per_tti - rx_off_diff) {
                 LOG_E(PHY,"TX : Timeout (sent %d/%d)\n",txs, UE->frame_parms.samples_per_tti-rx_off_diff);
                 exit_fun( "problem transmitting samples" );
              }
Rohit Gupta's avatar
Rohit Gupta committed
1108 1109
	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );

1110
	      // read in first symbol of next frame and adjust for timing drift
Raymond Knopp's avatar
Raymond Knopp committed
1111
	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
Rohit Gupta's avatar
Rohit Gupta committed
1112 1113 1114 1115
					       &timestamp1,
					       (void**)rxdata,
					       UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 - rx_off_diff,
					       UE->frame_parms.nb_antennas_rx);
1116 1117 1118
	      rx_off_diff = 0;
	    }
	  }
1119
	  VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1120 1121 1122 1123 1124 1125 1126 1127 1128 1129 1130
	  // operate on thread sf mod 2
	  UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[sf&1];

	  // lock mutex
	  if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
	    LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX\n" );
	    exit_fun("nothing to add");
	    return &UE_thread_retval;
	  }
	  // increment instance count and change proc subframe/frame variables
	  int instance_cnt_rxtx = ++proc->instance_cnt_rxtx;
fnabet's avatar
fnabet committed
1131 1132 1133 1134 1135
	  if(sf == 0)
	  {
	     UE->proc.proc_rxtx[0].frame_rx++;
	     UE->proc.proc_rxtx[1].frame_rx++;
	  }
1136 1137
	  proc->subframe_rx=sf;
	  proc->subframe_tx=(sf+4)%10;
1138
	  proc->frame_tx = proc->frame_rx + ((proc->subframe_rx>5)?1:0);
1139 1140
	  proc->timestamp_tx = timestamp+(4*UE->frame_parms.samples_per_tti)-UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;

Raymond Knopp's avatar
Raymond Knopp committed
1141
	  /*
1142 1143 1144 1145
	  if (sf != (timestamp/UE->frame_parms.samples_per_tti)%10) {
	    LOG_E(PHY,"steady-state UE_thread error : frame_rx %d, subframe_rx %d, frame_tx %d, subframe_tx %d, rx subframe %d\n",proc->frame_rx,proc->subframe_rx,proc->frame_tx,proc->subframe_tx,(timestamp/UE->frame_parms.samples_per_tti)%10);
	    exit(-1);
	  }
Raymond Knopp's avatar
Raymond Knopp committed
1146
	  */
1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157 1158 1159
	  if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
	    LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RX\n" );
	    exit_fun("nothing to add");
	    return &UE_thread_retval;
	  }


	  if (instance_cnt_rxtx == 0) {
	    if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
	      LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n" );
	      exit_fun("nothing to add");
	      return &UE_thread_retval;
	    }
1160
	    LOG_D(PHY, "firing up rxtx_thread[%d] at subframe %d\n", sf&1, sf);
1161 1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173 1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186 1187
	  } else {
	    LOG_E( PHY, "[SCHED][UE] UE RX thread busy (IC %d)!!\n", instance_cnt_rxtx);
	    if (instance_cnt_rxtx > 2) {
	      sleep(1);
	      exit_fun("instance_cnt_rxtx > 2");
	      return &UE_thread_retval;
	    }
	  }
	  if (UE->mode == loop_through_memory) {
	    printf("Processing subframe %d",proc->subframe_rx);
	    getchar();
	  }
	}// for sf=0..10
	if ((UE->rx_offset<(5*UE->frame_parms.samples_per_tti)) &&
	    (UE->rx_offset > RX_OFF_MIN) && 
	    (rx_correction_timer == 0)) {
	  rx_off_diff = -UE->rx_offset + RX_OFF_MIN;
	  LOG_D(PHY,"UE->rx_offset %d > %d, diff %d\n",UE->rx_offset,RX_OFF_MIN,rx_off_diff);
	  rx_correction_timer = 5;
	} else if ((UE->rx_offset>(5*UE->frame_parms.samples_per_tti)) && 
		   (UE->rx_offset < ((10*UE->frame_parms.samples_per_tti)-RX_OFF_MIN)) &&
		   (rx_correction_timer == 0)) {   // moving to the left so drop rx_off_diff samples
	  rx_off_diff = 10*UE->frame_parms.samples_per_tti - RX_OFF_MIN - UE->rx_offset;
	  LOG_D(PHY,"UE->rx_offset %d < %d, diff %d\n",UE->rx_offset,10*UE->frame_parms.samples_per_tti-RX_OFF_MIN,rx_off_diff);
	  
	  rx_correction_timer = 5;
	}
1188
	
1189 1190 1191
	if (rx_correction_timer>0)
	  rx_correction_timer--;
      } // start_rx_stream==1
1192 1193
    } // UE->is_synchronized==1
      
1194
  } // while !oai_exit
Rohit Gupta's avatar
Rohit Gupta committed
1195
 return NULL;
1196 1197 1198 1199
} // UE_thread

/*
void *UE_thread_old(void *arg)
1200
{
1201 1202 1203
  UNUSED(arg)
  static int UE_thread_retval;
  PHY_VARS_UE *UE = PHY_vars_UE_g[0][0];
1204
  int spp = openair0_cfg[0].samples_per_packet;
1205
  int slot=1, frame=0, hw_subframe=0, rxpos=0, txpos=openair0_cfg[0].tx_scheduling_advance;
1206 1207 1208 1209 1210
#ifdef __AVX2__
  int dummy[2][spp] __attribute__((aligned(32)));
#else
  int dummy[2][spp] __attribute__((aligned(16)));
#endif
1211
  int dummy_dump = 0;
1212 1213
  int tx_enabled = 0;
  int start_rx_stream = 0;
1214 1215
  int rx_off_diff = 0;
  int rx_correction_timer = 0;
1216
  int first_rx = 0;
1217
  RTIME T0;
1218
  unsigned int rxs;
1219
  void* rxp[2];
1220 1221 1222

  openair0_timestamp timestamp;

1223 1224 1225 1226
#ifdef NAS_UE
  MessageDef *message_p;
#endif

laurent's avatar
laurent committed
1227
#ifdef DEADLINE_SCHEDULER
1228

1229 1230 1231
  struct sched_attr attr;
  unsigned int flags = 0;

1232 1233 1234
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
1235
  attr.sched_priority = 0;//sched_get_priority_max(SCHED_DEADLINE);
1236

1237 1238
  // This creates a .5 ms  reservation
  attr.sched_policy = SCHED_DEADLINE;
1239 1240 1241
  attr.sched_runtime  = 100000;
  attr.sched_deadline = 500000;
  attr.sched_period   = 500000;
1242 1243

  if (sched_setattr(0, &attr, flags) < 0 ) {
1244 1245
    perror("[SCHED] main eNB thread: sched_setattr failed\n");
    exit_fun("Nothing to add");
1246
    return &UE_thread_retval;
1247
  }
1248 1249 1250
  LOG_I(HW,"[SCHED][eNB] eNB main deadline thread %lu started on CPU %d\n",
        (unsigned long)gettid(), sched_getcpu());

1251 1252 1253 1254
#else
  struct sched_param sp;
  sp.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp);
1255 1256
#endif

1257
  // Lock memory from swapping. This is a process wide call (not constraint to this thread).
1258 1259 1260 1261 1262
  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");
1263

1264 1265
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
1266

1267 1268 1269 1270 1271
  pthread_mutex_unlock(&sync_mutex);
  printf("unlocked sync_mutex, waiting (UE_thread)\n");

  printf("starting UE thread\n");

1272 1273 1274 1275 1276
#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

1277 1278
  T0 = rt_get_time_ns();
  first_rx = 1;
1279
  rxpos=0;
1280

1281
  while (!oai_exit) {
1282 1283
    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 );
1284
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_DUMMY_DUMP, dummy_dump );
1285

1286

1287
    while (rxpos < (1+hw_subframe)*UE->frame_parms.samples_per_tti) {
1288
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
1289

1290 1291
#ifndef USRP_DEBUG

1292
      DevAssert( UE->frame_parms.nb_antennas_rx <= 2 );
1293
      void* rxp[2];
1294

1295
      for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
1296
        rxp[i] = (dummy_dump==0) ? (void*)&rxdata[i][rxpos] : (void*)dummy[i];
1297
      
1298
    
1299
      if (UE->mode != loop_through_memory) {
Raymond Knopp's avatar
Raymond Knopp committed
1300
	rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
1301 1302 1303
				     &timestamp,
				     rxp,
				     spp - ((first_rx==1) ? rx_off_diff : 0),
1304
				     UE->frame_parms.nb_antennas_rx);
1305 1306

	if (rxs != (spp- ((first_rx==1) ? rx_off_diff : 0))) {
1307 1308 1309 1310 1311
	  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;
	  }
1312
	}
1313
      }
1314

1315
      if (rx_off_diff !=0)
1316
	LOG_D(PHY,"frame %d, rx_offset %d, rx_off_diff %d\n",UE->frame_rx,UE->rx_offset,rx_off_diff);
1317

1318
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
1319

1320
      // Transmit TX buffer based on timestamp from RX
1321
      if ((tx_enabled==1) && (UE->mode!=loop_through_memory)) {
1322
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
1323

1324
        DevAssert( UE->frame_parms.nb_antennas_tx <= 2 );
1325
        void* txp[2];
1326

1327
        for (int i=0; i<UE->frame_parms.nb_antennas_tx; i++)
1328 1329
          txp[i] = (void*)&txdata[i][txpos];

Raymond Knopp's avatar
Raymond Knopp committed
1330
        UE->rfdevice.trx_write_func(&openair0,
Raymond Knopp's avatar
Raymond Knopp committed
1331
                                (timestamp+openair0_cfg[0].tx_scheduling_advance-openair0_cfg[0].tx_sample_advance),
1332
                                txp,
1333
				spp - ((first_rx==1) ? rx_off_diff : 0),
1334
                                UE->frame_parms.nb_antennas_tx,
1335 1336
                                1);

1337
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 0 );
1338
      }
1339 1340
      else if (UE->mode == loop_through_memory)
	rt_sleep_ns(1000000);
1341
#else
1342
      // define USRP_DEBUG is active
1343 1344
      rt_sleep_ns(1000000);
#endif
1345

1346 1347 1348
      rx_off_diff = 0;
      first_rx = 0;

1349 1350 1351
      rxpos += spp;
      txpos += spp;

1352 1353
      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;
1354
    }
1355

1356 1357
    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;
1358

1359 1360
    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 );
1361

1362
      if (start_rx_stream == 1) {
1363
	LOG_D(PHY,"Locking mutex_rx (IC %d)\n",UE->instance_cnt_rx);
1364
        if (pthread_mutex_lock(&UE->mutex_rx) != 0) {
1365
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RX thread\n" );
1366
          exit_fun("nothing to add");
1367 1368
          return &UE_thread_retval;
        }
1369

1370
        int instance_cnt_rx = ++UE->instance_cnt_rx;
1371

1372
	LOG_D(PHY,"Unlocking mutex_rx (IC %d)\n",instance_cnt_rx);
1373 1374 1375 1376 1377
        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;
        }
1378

1379 1380 1381
	VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_RX, instance_cnt_rx);


1382
        if (instance_cnt_rx == 0) {
1383
	  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 );
1384
          if (pthread_cond_signal(&UE->proc.cond_rx) != 0) {
1385 1386 1387 1388
            LOG_E( PHY, "[SCHED][UE] ERROR pthread_cond_signal for UE RX thread\n" );
            exit_fun("nothing to add");
            return &UE_thread_retval;
          }
1389
	  
1390
	  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 );
1391 1392 1393 1394
	  if (UE->mode == loop_through_memory) {
	    printf("Processing subframe %d",UE->slot_rx>>1);
	    getchar();
	  }
1395

1396 1397 1398
          if (UE->mode == rx_calib_ue) {
            if (frame == 10) {
              LOG_D(PHY,
1399
                    "[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",
1400 1401 1402 1403 1404 1405 1406 1407
                    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,
1408 1409
                    UE->rx_total_gain_dB,
                    openair0_cfg[0].rx_gain[0]
1410
                   );
1411 1412
              exit_fun("[HW][UE] UE in RX calibration mode, exiting");
              return &UE_thread_retval;
1413 1414
            }
          }
1415
        } else {
1416
          LOG_E( PHY, "[SCHED][UE] UE RX thread busy (IC %d)!!\n", instance_cnt_rx);
1417
	  if (instance_cnt_rx > 2) {
1418 1419 1420
	    exit_fun("instance_cnt_rx > 1");
	    return &UE_thread_retval;
	  }
1421 1422
        }

1423 1424
       
        if ((tx_enabled==1)&&(UE->mode != loop_through_memory)) {
1425 1426 1427 1428 1429 1430 1431

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

1432

1433 1434 1435 1436 1437 1438 1439
          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;
          }
1440 1441
	  VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME(VCD_SIGNAL_DUMPER_VARIABLES_UE_INST_CNT_TX, instance_cnt_tx);

1442 1443 1444 1445

          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" );
1446
              exit_fun("nothing to add");
1447
              return &UE_thread_retval;
1448
            }
1449
	    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 );
1450

1451
          } else {
1452
            LOG_E( PHY, "[SCHED][UE] UE TX thread busy (IC %d)!!\n" );
1453
	    if (instance_cnt_tx>2) {
1454 1455 1456
	      exit_fun("instance_cnt_tx > 1");
	      return &UE_thread_retval;
	    }
1457 1458
          }
        }
1459

1460
      }
1461 1462 1463
    } else {
      // we are not yet synchronized
      if ((hw_subframe == 9) && (dummy_dump == 0)) {
1464 1465
        // Wake up initial synch thread
        if (pthread_mutex_lock(&UE->mutex_synch) != 0) {
1466
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" );
1467
          exit_fun("nothing to add");
1468 1469
          return &UE_thread_retval;
        }
1470

1471
        int instance_cnt_synch = ++UE->instance_cnt_synch;
1472

1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483
        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" );
1484
            exit_fun("nothing to add");
1485
            return &UE_thread_retval;
1486
          }
1487 1488 1489 1490
        } else {
          LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
          exit_fun("nothing to add");
          return &UE_thread_retval;
1491
        }
1492 1493
      }
    }
1494

1495 1496
    hw_subframe++;
    slot+=2;
1497

1498
    if (hw_subframe==10) {
1499 1500 1501 1502
      hw_subframe = 0;
      first_rx = 1;
      frame++;
      slot = 1;
1503

1504 1505 1506
      int fail = pthread_mutex_lock(&UE->mutex_synch);
      int instance_cnt_synch = UE->instance_cnt_synch;
      fail = fail || pthread_mutex_unlock(&UE->mutex_synch);
1507

1508 1509 1510 1511 1512 1513 1514 1515
      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
1516 1517
        if (UE->is_synchronized == 1) {
          rx_off_diff = 0;
1518
          LTE_DL_FRAME_PARMS *frame_parms = &UE->frame_parms; // for macro FRAME_LENGTH_COMPLEX_SAMPLES
1519

1520
	  //	  LOG_I(PHY,"UE->rx_offset %d\n",UE->rx_offset);
1521
          if ((UE->rx_offset > RX_OFF_MAX) && (start_rx_stream == 0)) {
1522 1523 1524
            start_rx_stream=1;
            frame=0;
            // dump ahead in time to start of frame
1525 1526

#ifndef USRP_DEBUG
1527
	    if (UE->mode != loop_through_memory) {
1528
	      LOG_I(PHY,"Resynchronizing RX by %d samples\n",UE->rx_offset);
Raymond Knopp's avatar
Raymond Knopp committed
1529
	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
1530 1531 1532
					   &timestamp,
					   (void**)rxdata,
					   UE->rx_offset,
1533
					   UE->frame_parms.nb_antennas_rx);
1534 1535 1536 1537 1538 1539
	      if (rxs != UE->rx_offset) {
		exit_fun("problem in rx");
		return &UE_thread_retval;
	      }
	      UE->rx_offset=0;
	      tx_enabled = 1;
1540
	    }
1541 1542
	    else
	      rt_sleep_ns(1000000);
1543
#else
1544
            rt_sleep_ns(10000000);
1545
#endif
1546

1547 1548 1549 1550
          } else if ((UE->rx_offset<(FRAME_LENGTH_COMPLEX_SAMPLES/2)) &&
		     (UE->rx_offset > RX_OFF_MIN) && 
		     (start_rx_stream==1) && 
		     (rx_correction_timer == 0)) {
1551
            rx_off_diff = -UE->rx_offset + RX_OFF_MIN;
1552
	    LOG_D(PHY,"UE->rx_offset %d > %d, diff %d\n",UE->rx_offset,RX_OFF_MIN,rx_off_diff);
1553
            rx_correction_timer = 5;
1554 1555 1556 1557 1558
          } 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;
1559
	    LOG_D(PHY,"UE->rx_offset %d < %d, diff %d\n",UE->rx_offset,FRAME_LENGTH_COMPLEX_SAMPLES-RX_OFF_MIN,rx_off_diff);
1560

1561 1562 1563 1564 1565 1566 1567 1568
            rx_correction_timer = 5;
          }

          if (rx_correction_timer>0)
            rx_correction_timer--;
        }

        dummy_dump=0;
1569 1570
      }
    }
1571

1572 1573 1574 1575
#if defined(ENABLE_ITTI)
    itti_update_lte_time(frame, slot);
#endif
  }
1576

1577
  return &UE_thread_retval;
1578 1579
}

1580
*/
1581

1582 1583 1584
/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
1585 1586
 * - UE_thread_rxtx0
 * - UE_thread_rxtx1
1587 1588 1589
 * - UE_thread_synch
 * and the locking between them.
 */
Raymond Knopp's avatar
Raymond Knopp committed
1590
void init_UE_threads(int inst)
1591
{
Raymond Knopp's avatar
Raymond Knopp committed
1592 1593 1594
  PHY_VARS_UE *UE;
 
  UE = PHY_vars_UE_g[inst][0];
1595

Raymond Knopp's avatar
Raymond Knopp committed
1596 1597 1598
  pthread_attr_init (&UE->proc.attr_ue);
  pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
  
1599
#ifndef LOWLATENCY
Raymond Knopp's avatar
Raymond Knopp committed
1600 1601
  UE->proc.sched_param_ue.sched_priority = sched_get_priority_max(SCHED_FIFO);
  pthread_attr_setschedparam(&UE->proc.attr_ue,&sched_param_UE_thread);
1602 1603
#endif

1604
  // the threads are not yet active, therefore access is allowed without locking
1605 1606 1607 1608 1609 1610 1611 1612 1613
  UE->proc.proc_rxtx[0].instance_cnt_rxtx = -1;
  UE->proc.proc_rxtx[1].instance_cnt_rxtx = -1;
  UE->proc.instance_cnt_synch = -1;
  pthread_mutex_init(&UE->proc.proc_rxtx[0].mutex_rxtx,NULL);
  pthread_mutex_init(&UE->proc.proc_rxtx[1].mutex_rxtx,NULL);
  pthread_mutex_init(&UE->proc.mutex_synch,NULL);
  pthread_cond_init(&UE->proc.proc_rxtx[0].cond_rxtx,NULL);
  pthread_cond_init(&UE->proc.proc_rxtx[1].cond_rxtx,NULL);
  pthread_cond_init(&UE->proc.cond_synch,NULL);
1614 1615 1616 1617 1618 1619
  pthread_create(&UE->proc.proc_rxtx[0].pthread_rxtx,NULL,UE_thread_rxn_txnp4,(void*)&UE->proc.proc_rxtx[0]);
  pthread_setname_np( UE->proc.proc_rxtx[0].pthread_rxtx, "UE_thread_rxn_txnp4_even" );
  pthread_create(&UE->proc.proc_rxtx[1].pthread_rxtx,NULL,UE_thread_rxn_txnp4,(void*)&UE->proc.proc_rxtx[1]);
  pthread_setname_np( UE->proc.proc_rxtx[1].pthread_rxtx, "UE_thread_rxn_txnp4_odd" );
  pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
  pthread_setname_np( UE->proc.pthread_synch, "UE_thread_synch" );
1620 1621 1622
}


Raymond Knopp's avatar
 
Raymond Knopp committed
1623
#ifdef OPENAIR2
1624 1625
void fill_ue_band_info(void)
{
1626 1627 1628 1629 1630 1631

  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;

1632 1633 1634
  for (i=0; i<bands_to_scan.nbands; i++) {

    for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
1635
      if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
1636 1637 1638 1639 1640 1641 1642 1643 1644 1645 1646 1647 1648
        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;
1649 1650 1651
      }
  }
}
Raymond Knopp's avatar
 
Raymond Knopp committed
1652
#endif
1653

1654
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg)
1655 1656 1657 1658
{

  int i, CC_id;
  LTE_DL_FRAME_PARMS *frame_parms;
1659
  openair0_rf_map *rf_map;
1660

1661 1662 1663 1664 1665 1666 1667 1668 1669 1670 1671 1672 1673
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    rf_map = &phy_vars_ue[CC_id]->rf_map;
    
    if (phy_vars_ue[CC_id]) {
      frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
    } else {
      printf("phy_vars_UE[%d] not initialized\n", CC_id);
      return(-1);
    }
    
    /*
      if (frame_parms->frame_type == TDD) {
      if (frame_parms->N_RB_DL == 100)
1674 1675
      N_TA_offset = 624;
    else if (frame_parms->N_RB_DL == 50)
1676
    N_TA_offset = 624/2;
1677
    else if (frame_parms->N_RB_DL == 25)
1678 1679 1680 1681
    N_TA_offset = 624/4;
    }
    */
    
1682
    // replace RX signal buffers with mmaped HW versions
1683 1684 1685 1686 1687 1688
    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->card, rf_map->chain+i );
      free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
1689
    rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
1690
    phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
1691
    printf("rxdata[%d] : %p\n",i,rxdata[i]);
1692 1693 1694 1695 1696 1697 1698 1699 1700 1701 1702 1703 1704 1705 1706
    }
    
    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->card, rf_map->chain+i );
      free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
      txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
      phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
      printf("txdata[%d] : %p\n",i,txdata[i]);
    }
    
    // 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]
    // be careful when releasing memory!
    // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
    
1707
  }
1708

1709
  return 0;
1710
}