lte-ue.c 63.4 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"
55
#ifdef OPENAIR2
56 57
#include "LAYER2/MAC/defs.h"
#include "RRC/LITE/extern.h"
58
#endif
59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77
#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"

78 79
#include "T.h"

80 81 82 83 84 85 86 87 88
#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL

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

knopp's avatar
knopp committed
89
void init_UE_threads(int nb_inst);
90
void *UE_thread(void *arg);
knopp's avatar
knopp committed
91
void init_UE(int nb_inst);
92 93 94 95 96

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

97

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

103 104
int32_t **rxdata;
int32_t **txdata;
105

106 107
//extern unsigned int tx_forward_nsamps;
//extern int tx_delay;
108 109 110 111 112

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

113 114
extern int oaisim_flag;

115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
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;

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

168 169 170 171
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

knopp's avatar
knopp committed
172
void init_UE(int nb_inst) {
173 174

  int error_code;
knopp's avatar
knopp committed
175 176
  int inst;
  PHY_VARS_UE *UE;
knopp's avatar
knopp committed
177
  int ret;
knopp's avatar
knopp committed
178 179 180 181 182 183

  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];
knopp's avatar
knopp committed
184

185 186 187 188 189
    if (oaisim_flag == 0) {
      ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]);
      if (ret !=0){
	exit_fun("Error loading device library");
      }
Rohit Gupta's avatar
Rohit Gupta committed
190
    }
knopp's avatar
knopp committed
191
    UE->rfdevice.host_type = BBU_HOST;
knopp's avatar
knopp committed
192
    //    UE->rfdevice.type      = NONE_DEV;
knopp's avatar
knopp committed
193 194 195 196 197 198 199 200 201
    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" );
    }
202 203 204 205 206 207 208 209 210 211 212 213 214
  }

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

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

  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
238
#ifndef DEADLINE_SCHEDULER
239 240 241 242 243 244 245 246 247
  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);

248 249
  #ifdef CPU_AFFINITY
  if (get_nprocs() >2)
250
  {
251 252 253 254 255 256 257 258 259
    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");
    }
260
  }
261 262
  #endif

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 302 303 304 305 306 307
  /* 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


308

309

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


315 316
  if (UE->UE_scan == 0) {
    do  {
317
      current_band = eutra_bands[ind].band;
318
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
319

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

        found = 1;
        break;
      }
327

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

336 337


338

339 340


341
    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);
342

343 344 345 346 347 348
    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;
349
      else //FDD
350
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
351 352
    }

353
    sync_mode = pbch;
354

355
  } else if  (UE->UE_scan == 1) {
356
    current_band=0;
357

358 359 360 361 362 363 364
    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;
365 366
    }
  }
367

knopp's avatar
knopp committed
368

369 370 371 372 373 374 375
  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);


knopp's avatar
knopp committed
376 377 378 379 380
  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { 
    LOG_E(HW,"Could not start the device\n");
    oai_exit=1;
  }

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

384
  while (oai_exit==0) {
385

386
    if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) {
387
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE initial synch thread\n" );
388
      exit_fun("noting to add");
389 390
      return &UE_thread_synch_retval;
    }
391
    
392

393
    while (UE->proc.instance_cnt_synch < 0) {
394
      // the thread waits here most of the time
395
      pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
396
    }
397

398
    if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) {
399 400 401 402
      LOG_E( PHY, "[SCHED][eNB] error unlocking mutex for UE Initial Synch thread\n" );
      exit_fun("nothing to add");
      return &UE_thread_synch_retval;
    }
403

404
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 1 );
405 406

    switch (sync_mode) {
407
    case pss:
408 409
      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);
410 411 412 413 414 415 416
      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;
      }

417
      if (current_band==bands_to_scan.nbands) {
418 419
        current_band=0;
        oai_exit=1;
420
      }
421

422 423 424
      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;
425

426 427 428 429 430
	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;
431
	}
432
	
433
      }
434

435 436
      break;
 
437
    case pbch:
438

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

442
        hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
443 444 445 446 447 448 449 450
        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 );

451 452 453 454
	if (UE->UE_scan_carrier == 1) {

	  UE->UE_scan_carrier = 0;
	  // rerun with new cell parameters and frequency-offset
455 456
	  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;
457 458 459 460 461 462 463 464
		if (freq_offset >= 0)
	    {
	        openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += UE->common_vars.freq_offset;
	    }
	    else
	    {
	        openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= UE->common_vars.freq_offset;
	    }
465 466
	    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];
467 468 469
	    freq_offset=0;	    
	  }

470
	  // reconfigure for potentially different bandwidth
471
	  switch(UE->frame_parms.N_RB_DL) {
472
	  case 6:
473 474 475
	    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;
476
	    //            openair0_cfg[0].rx_gain[0] -= 12;
477 478
	    break;
	  case 25:
479 480 481
	    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;
482
	    //            openair0_cfg[0].rx_gain[0] -= 6;
483 484
	    break;
	  case 50:
485 486 487
	    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;
488
	    //            openair0_cfg[0].rx_gain[0] -= 3;
489 490
	    break;
	  case 100:
491 492 493
	    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;
494
	    //            openair0_cfg[0].rx_gain[0] -= 0;
495 496
	    break;
	  }
497
	
Rohit Gupta's avatar
Rohit Gupta committed
498
	  UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
knopp's avatar
knopp committed
499
	  //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
500 501 502

	  //UE->rfdevice.trx_stop_func(&UE->rfdevice);	  
	  //	  sleep(1);
503
	  init_frame_parms(&UE->frame_parms,1);
504 505 506 507
	  //	  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) { 
	  //	    LOG_E(HW,"Could not start the device\n");
	  //	    oai_exit=1;
	  //	  }
508 509 510
	}
	else {
	  UE->is_synchronized = 1;
511

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

570 571 572 573 574 575 576 577
	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;
578
	  }
579
	}
580

581 582
	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
	    
583
      }// initial_sync=0
584

585
      break;
586

587 588 589 590
    case si:
    default:
      break;
    }
591

592

593
    if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) {
594 595 596 597
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE synch\n" );
      exit_fun("noting to add");
      return &UE_thread_synch_retval;
    }
598

599
    // indicate readiness
600
    UE->proc.instance_cnt_synch--;
601

602
    if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) {
603 604 605
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE synch\n" );
      exit_fun("noting to add");
      return &UE_thread_synch_retval;
606
    }
607

608
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
609
  }  // while !oai_exit
610

611
  return &UE_thread_synch_retval;
612 613
}

614

615

616
/*!
617
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
618
 * This thread performs the phy_procedures_UE_RX() on every received slot.
619
 * then, if TX is enabled it performs TX for n+4. 
620 621 622
 * \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.
 */
623

624
static void *UE_thread_rxn_txnp4(void *arg)
625
{
knopp's avatar
knopp committed
626
  static int UE_thread_rxtx_retval;
627
  UE_rxtx_proc_t *proc = (UE_rxtx_proc_t *)arg;
628
  int ret;
629 630
  PHY_VARS_UE *UE=PHY_vars_UE_g[0][proc->CC_id];
  proc->instance_cnt_rxtx=-1;
631

632

laurent's avatar
laurent committed
633
#ifdef DEADLINE_SCHEDULER
634

635 636 637
  struct sched_attr attr;
  unsigned int flags = 0;

638 639 640
  attr.size = sizeof(attr);
  attr.sched_flags = 0;
  attr.sched_nice = 0;
641
  attr.sched_priority = 0;
642

643
  // This creates a .5ms reservation every 1ms period
644 645 646 647
  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
648 649

  if (sched_setattr(0, &attr, flags) < 0 ) {
knopp's avatar
knopp committed
650 651
    perror("[SCHED] UE_thread_rxtx : sched_setattr failed\n");
    return &UE_thread_rxtx_retval;
652 653
  }

654
#else
655 656 657 658 659 660 661 662 663
  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);

664 665
  #ifdef CPU_AFFINITY
  if (get_nprocs() >2)
666
  {
667 668 669 670 671 672 673 674 675
    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");
    }
676
  }
677 678
  #endif

679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720
  /* 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);

721

722
#endif
723

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

727
  printf("waiting for sync (UE_thread_rxn_txnp4)\n");
728

729
  pthread_mutex_lock(&sync_mutex);
730
  printf("Locked sync_mutex, waiting (UE_thread_rxn_txnp4)\n");
731

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

735 736 737 738 739 740 741 742 743
#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");
  }

744
  pthread_mutex_unlock(&sync_mutex);
knopp's avatar
knopp committed
745
  printf("unlocked sync_mutex, waiting (UE_thread_rxtx)\n");
746

747
  printf("Starting UE RXN_TXNP4 thread (%s)\n", threadname);
748 749

  while (!oai_exit) {
Wilson's avatar
Wilson committed
750
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0+(proc->proc_id), 1 );
751
    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
knopp's avatar
knopp committed
752
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
753
      exit_fun("nothing to add");
knopp's avatar
knopp committed
754
      return &UE_thread_rxtx_retval;
755
    }
756

757
    while (proc->instance_cnt_rxtx < 0) {
Wilson's avatar
Wilson committed
758
      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0+(proc->proc_id), 1 );
759
      // most of the time, the thread is waiting here
760
      pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
761
    }
Wilson's avatar
Wilson committed
762
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_WAIT_COND_RXTX0+(proc->proc_id), 0 );
763

764 765
    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
766
      exit_fun("nothing to add");
knopp's avatar
knopp committed
767
      return &UE_thread_rxtx_retval;
768
    }
Wilson's avatar
Wilson committed
769
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_COND_WAIT0+(proc->proc_id), 0 );
770

Wilson's avatar
Wilson committed
771 772 773 774 775
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->proc_id), 1 );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_RX0_UE+(proc->proc_id), proc->subframe_rx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_SUBFRAME_NUMBER_TX0_UE+(proc->proc_id), proc->subframe_tx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_RX0_UE+(proc->proc_id), proc->frame_rx );
    VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_FRAME_NUMBER_TX0_UE+(proc->proc_id), proc->frame_tx );
776

777 778 779 780
    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)) {
781
    
782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797
      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"))));
      }
798 799
      phy_procedures_UE_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL );
    }
800
    
801
    if (UE->mac_enabled==1) {
802

803
      ret = mac_xface->ue_scheduler(UE->Mod_id,
804 805 806 807 808 809 810
          proc->frame_rx,
          proc->subframe_rx,
          proc->frame_tx,
          proc->subframe_tx,
          subframe_select(&UE->frame_parms,proc->subframe_tx),
          0,
          0/*FIXME CC_id*/);
811 812 813 814 815 816 817 818 819 820 821 822 823
      
      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;
824 825
      }
    }
826 827

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

      if (UE->mode != loop_through_memory) {
Rohit Gupta's avatar
Rohit Gupta committed
831
	phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
832 833 834
      }
    }

835 836 837 838 839 840 841 842
    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
  (UE->frame_parms.frame_type == TDD)) {

      if (UE->mode != loop_through_memory) {
  phy_procedures_UE_S_TX(UE,0,0,no_relay);
      }
    }

Wilson's avatar
Wilson committed
843
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_RXTX0+(proc->proc_id), 0 );
844

845
    
Wilson's avatar
Wilson committed
846
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0+(proc->proc_id), 1 );
847
    if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
knopp's avatar
knopp committed
848
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
849
      exit_fun("noting to add");
knopp's avatar
knopp committed
850
      return &UE_thread_rxtx_retval;
851
    }
852 853 854 855 856
    
    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) {
knopp's avatar
knopp committed
857
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
858
      exit_fun("noting to add");
knopp's avatar
knopp committed
859
      return &UE_thread_rxtx_retval;
860
    }
Wilson's avatar
Wilson committed
861
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_LOCK_MUTEX_RXTX_FOR_CNT_DECREMENT0+(proc->proc_id), 0 );
gauthier's avatar
gauthier committed
862
  }
863
  
gauthier's avatar
gauthier committed
864
  // thread finished
knopp's avatar
knopp committed
865
  return &UE_thread_rxtx_retval;
866
}
867

868 869 870



871

872 873
#define RX_OFF_MAX 23
#define RX_OFF_MIN 0
874 875
#define RX_OFF_MID ((RX_OFF_MAX+RX_OFF_MIN)/2)

876 877 878
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
879 880
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
881 882 883 884
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
885 886 887 888 889 890

void *UE_thread(void *arg) {

  static int UE_thread_retval;
  PHY_VARS_UE *UE = PHY_vars_UE_g[0][0];
  //  int tx_enabled = 0;
891
  uint32_t rxs=0,txs=0;
892 893
  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
894
  void* rxp[2], *txp[2];
895 896 897 898 899

#ifdef NAS_UE
  MessageDef *message_p;
#endif

900
  int start_rx_stream = 0;
901 902
  int rx_off_diff = 0;
  int rx_correction_timer = 0;
Rohit Gupta's avatar
Rohit Gupta committed
903
  int i;
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 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954
#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 

955 956 957
  while (UE->rfdevice.trx_started==0)
    usleep(500);
  
958 959 960 961
  while (!oai_exit) {
    
    if (UE->is_synchronized == 0) {
      
962
      if (pthread_mutex_lock(&UE->proc.mutex_synch) != 0) {
963 964 965 966 967
	LOG_E( PHY, "[SCHED][UE] verror locking mutex for UE initial synch thread\n" );
	exit_fun("nothing to add");
	return &UE_thread_retval;
      }
      
968
      int instance_cnt_synch = UE->proc.instance_cnt_synch;
969
      
970
      if (pthread_mutex_unlock(&UE->proc.mutex_synch) != 0) {
971 972 973 974 975 976 977 978
	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++)
979
	  rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
980 981
      
	if (UE->mode != loop_through_memory) {
knopp's avatar
knopp committed
982 983 984 985 986
	  rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					   &timestamp,
					   rxp,
					   UE->frame_parms.samples_per_tti*10,
					   UE->frame_parms.nb_antennas_rx);
987
	  
knopp's avatar
knopp committed
988 989
	  
	  if (rxs!=UE->frame_parms.samples_per_tti*10) {
990
	    LOG_E(PHY, "problem in rx 1! expect #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti*10, rxs);
991
	    exit_fun("problem in rx 1");
knopp's avatar
knopp committed
992 993
	    return &UE_thread_retval;
	  }
994
	}
knopp's avatar
knopp committed
995

996
	instance_cnt_synch = ++UE->proc.instance_cnt_synch;
997
	if (instance_cnt_synch == 0) {
998
	  if (pthread_cond_signal(&UE->proc.cond_synch) != 0) {
999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014
	    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];
1015
	  for (int sf=0;sf<10;sf++) {
1016
	    //	    printf("Reading dummy sf %d\n",sf);
knopp's avatar
knopp committed
1017 1018 1019 1020 1021
	    rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					     &timestamp,
					     rxp,
					     UE->frame_parms.samples_per_tti,
					     UE->frame_parms.nb_antennas_rx);
knopp's avatar
knopp committed
1022 1023

	    if (rxs!=UE->frame_parms.samples_per_tti){
1024
	      LOG_E(PHY, "problem in rx 2! expect #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti, rxs);
1025
	      exit_fun("problem in rx 2");
knopp's avatar
knopp committed
1026 1027 1028
	      return &UE_thread_retval;
	    }

1029
	  }
1030 1031 1032
	}
      }
      
1033
    } // UE->is_synchronized==0
1034
    else {
1035 1036 1037
      if (start_rx_stream==0) {
	start_rx_stream=1;
	if (UE->mode != loop_through_memory) {
1038 1039

	  if (UE->no_timing_correction==0) {
Rohit Gupta's avatar
Rohit Gupta committed
1040
	    LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
1041 1042
	    rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					     &timestamp,
1043
					     (void**)UE->common_vars.rxdata,
1044 1045 1046
					     UE->rx_offset,
					     UE->frame_parms.nb_antennas_rx);
	    if (rxs != UE->rx_offset) {
1047
	      LOG_E(PHY, "problem in rx 3! expect #samples=%d but got only %d!\n", UE->rx_offset, rxs);
1048
	      exit_fun("problem in rx 3!");
1049 1050
	      return &UE_thread_retval;
	    }
1051
	  }
1052
	  LOG_D(PHY,"Set rx_offset to 0 \n");
1053
	  UE->rx_offset=0;
1054 1055 1056 1057
	  UE->proc.proc_rxtx[0].frame_rx++;
	  UE->proc.proc_rxtx[1].frame_rx++;

	  // read in first symbol
knopp's avatar
knopp committed
1058 1059
	  rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					   &timestamp,
1060
					   (void**)UE->common_vars.rxdata,
knopp's avatar
knopp committed
1061 1062
					   UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
					   UE->frame_parms.nb_antennas_rx);
1063
    if (rxs != (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0)) {
1064
      LOG_E(PHY, "problem in rx 4! expect #samples=%d but got only %d!\n", UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0, rxs);
1065 1066 1067
      exit_fun("problem in rx 4!");
      return &UE_thread_retval;
    }
1068 1069 1070 1071 1072 1073 1074 1075 1076 1077
	  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;
	  }
1078 1079 1080
	} //UE->mode != loop_through_memory
	else
	  rt_sleep_ns(1000000);
1081

1082
      }// start_rx_stream==0
1083
      else {
fnabet's avatar
fnabet committed
1084 1085
	//UE->proc.proc_rxtx[0].frame_rx++;
	//UE->proc.proc_rxtx[1].frame_rx++;
Rohit Gupta's avatar
Rohit Gupta committed
1086
	
1087
	for (int sf=0;sf<10;sf++) {
Rohit Gupta's avatar
Rohit Gupta committed
1088
	  for (i=0; i<UE->frame_parms.nb_antennas_rx; i++) 
1089
	    rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti)];
1090 1091 1092
	  // grab signal for subframe
	  if (UE->mode != loop_through_memory) {
	    if (sf<9) {
1093
	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 1 );
knopp's avatar
knopp committed
1094 1095 1096 1097 1098
	      rxs = UE->rfdevice.trx_read_func(&UE->rfdevice,
					       &timestamp,
					       rxp,
					       UE->frame_parms.samples_per_tti,
					       UE->frame_parms.nb_antennas_rx);
1099 1100
	      LOG_D(PHY,"grab signal for subframe %d offset %d Nbsamples %d \n", sf, UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0+(sf*UE->frame_parms.samples_per_tti),
	    		  UE->frame_parms.samples_per_tti);
1101 1102
	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_READ, 0 );
	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS, rxs );
1103
	      VCD_SIGNAL_DUMPER_DUMP_VARIABLE_BY_NAME( VCD_SIGNAL_DUMPER_VARIABLES_UE0_TRX_READ_NS_MISSING, UE->frame_parms.samples_per_tti - rxs);
1104
	      if (rxs != UE->frame_parms.samples_per_tti) {
1105
	        LOG_E(PHY, "problem in rx 5! expect #samples=%d but got only %d!\n", UE->frame_parms.samples_per_tti, rxs);
1106 1107 1108
	        exit_fun("problem in rx 5!");
	        return &UE_thread_retval;
	      }
Rohit Gupta's avatar
Rohit Gupta committed
1109
	      
1110
	      // prepare tx buffer pointers
Rohit Gupta's avatar
Rohit Gupta committed
1111 1112 1113
	      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];
	      
1114
	      VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_TRX_WRITE, 1 );
Rohit Gupta's avatar
Rohit Gupta committed