lte-ue.c 41.1 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

/*! \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
 */
32
#include "lte-softmodem.h"
33 34 35

#include "rt_wrapper.h"

knopp's avatar
 
knopp committed
36
#ifdef OPENAIR2
37 38
#include "LAYER2/MAC/defs.h"
#include "RRC/LITE/extern.h"
knopp's avatar
 
knopp committed
39
#endif
40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#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 "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"

Bilel's avatar
Bilel committed
57 58
#include "T.h"

Bilel's avatar
Bilel committed
59 60
extern double cpuf;

61 62
#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL
laurent's avatar
laurent committed
63
#define FIFO_PRIORITY   40
64 65

typedef enum {
laurent's avatar
laurent committed
66 67 68
    pss=0,
    pbch=1,
    si=2
69 70
} sync_mode_t;

71
void init_UE_threads(int);
72
void *UE_thread(void *arg);
73
void init_UE(int nb_inst,int,int);
74

75 76
int32_t **rxdata;
int32_t **txdata;
77 78

#define KHz (1000UL)
79
#define MHz (1000*KHz)
80 81

typedef struct eutra_band_s {
laurent's avatar
laurent committed
82 83 84 85 86 87
    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;
88 89 90
} eutra_band_t;

typedef struct band_info_s {
laurent's avatar
laurent committed
91 92
    int nbands;
    eutra_band_t band_info[100];
93 94 95 96
} band_info_t;

band_info_t bands_to_scan;

97
static const eutra_band_t eutra_bands[] = {
laurent's avatar
laurent committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    { 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},
    {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
    {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},
127 128
};

129 130


131

132 133 134 135
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

knopp's avatar
knopp committed
136
void phy_init_lte_ue_transport(PHY_VARS_UE *ue,int absraction_flag);
137

knopp's avatar
knopp committed
138 139 140
PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag)
141 142 143 144

{

  int i,j;
knopp's avatar
knopp committed
145 146
  PHY_VARS_UE* ue;

147
  if (frame_parms!=(LTE_DL_FRAME_PARMS *)NULL) { // if we want to give initial frame parms, allocate the PHY_VARS_UE structure and put them in
knopp's avatar
knopp committed
148 149 150 151 152 153
    ue = (PHY_VARS_UE *)malloc(sizeof(PHY_VARS_UE));
    memset(ue,0,sizeof(PHY_VARS_UE));
    memcpy(&(ue->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS));
  }					
  else ue = PHY_vars_UE_g[UE_id][0];

154 155 156

  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
knopp's avatar
knopp committed
157 158 159 160 161 162
  // initialize all signal buffers
  init_lte_ue_signal(ue,1,abstraction_flag);
  // intialize transport
  init_lte_ue_transport(ue,abstraction_flag);

  return(ue);
163 164
}

knopp's avatar
knopp committed
165

166 167
char uecap_xer[1024];

168 169


laurent's avatar
laurent committed
170
void init_thread(int sched_runtime, int sched_deadline, int sched_fifo, cpu_set_t *cpuset, char * name) {
171

laurent's avatar
laurent committed
172 173 174 175 176 177 178 179 180
#ifdef DEADLINE_SCHEDULER
    if (sched_runtime!=0) {
        struct sched_attr attr= {0};
        attr.size = sizeof(attr);
        attr.sched_policy = SCHED_DEADLINE;
        attr.sched_runtime  = sched_runtime;
        attr.sched_deadline = sched_deadline;
        attr.sched_period   = 0;
        AssertFatal(sched_setattr(0, &attr, 0) == 0,
181
                    "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
182 183
        LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
              name, (unsigned long)gettid(), sched_getcpu());
knopp's avatar
knopp committed
184
    }
laurent's avatar
laurent committed
185
#else
186
    if (CPU_COUNT(cpuset) > 0)
laurent's avatar
laurent committed
187 188 189 190 191
        AssertFatal( 0 == pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), cpuset), "");
    struct sched_param sp;
    sp.sched_priority = sched_fifo;
    AssertFatal(pthread_setschedparam(pthread_self(),SCHED_FIFO,&sp)==0,
                "Can't set thread priority, Are you root?\n");
192 193 194 195 196 197 198 199
    /* Check the actual affinity mask assigned to the thread */
    cpu_set_t *cset=CPU_ALLOC(CPU_SETSIZE);
    if (0 == pthread_getaffinity_np(pthread_self(), CPU_ALLOC_SIZE(CPU_SETSIZE), cset)) {
      char txt[512]={0};
      for (int j = 0; j < CPU_SETSIZE; j++)
        if (CPU_ISSET(j, cset))
	  sprintf(txt+strlen(txt), " %d ", j);
      printf("CPU Affinity of thread %s is %s\n", name, txt);
Rohit Gupta's avatar
Rohit Gupta committed
200
    }
201
    CPU_FREE(cset);
202 203
#endif

laurent's avatar
laurent committed
204
}
205

206
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in) {
207

knopp's avatar
knopp committed
208
  PHY_VARS_UE *UE;
209 210
  int         inst;
  int         ret;
knopp's avatar
knopp committed
211

212
  LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
213 214 215 216
    
  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
	     0,// cba_group_active
	     0); // HO flag
217
  
knopp's avatar
knopp committed
218
  for (inst=0;inst<nb_inst;inst++) {
219

220
    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
knopp's avatar
knopp committed
221 222
    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);

223
    LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
knopp's avatar
knopp committed
224 225
    init_UE_threads(inst);
    UE = PHY_vars_UE_g[inst][0];
knopp's avatar
knopp committed
226

227 228 229 230 231
    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
232
    }
233
    UE->rfdevice.host_type = RAU_HOST;
knopp's avatar
knopp committed
234
    //    UE->rfdevice.type      = NONE_DEV;
235 236 237 238 239
    PHY_VARS_UE *UE = PHY_vars_UE_g[inst][0];
    AssertFatal(0 == pthread_create(&UE->proc.pthread_ue,
                                    &UE->proc.attr_ue,
                                    UE_thread,
                                    (void*)UE), "");
240 241
  }

242
  printf("UE threads created by %ld\n", gettid());
243 244
#if 0
#if defined(ENABLE_USE_MME)
245
  extern volatile int start_UE;
246 247 248 249
  while (start_UE == 0) {
    sleep(1);
  }
#endif
250
#endif
251 252
}

253 254
/*!
 * \brief This is the UE synchronize thread.
255
 * It performs band scanning and synchonization.
256 257 258
 * \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.
 */
laurent's avatar
laurent committed
259

260 261
static void *UE_thread_synch(void *arg)
{
262 263 264
  static int UE_thread_synch_retval;
  int i, hw_slot_offset;
  PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
265 266
  int current_band = 0;
  int current_offset = 0;
267
  sync_mode_t sync_mode = pbch;
268
  int CC_id = UE->CC_id;
269 270
  int ind;
  int found;
271
  int freq_offset=0;
272
  char threadname[128];
273 274 275

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

277
   cpu_set_t cpuset;
278
  CPU_ZERO(&cpuset);
279 280 281 282 283
  if ( threads.iq != -1 )
    CPU_SET(threads.iq, &cpuset);
  // this thread priority must be lower that the main acquisition thread
  sprintf(threadname, "sync UE %d\n", UE->Mod_id);
  init_thread(100000, 500000, FIFO_PRIORITY-1, &cpuset, threadname);
284
  
285
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
286 287
  ind = 0;
  found = 0;
288 289


290 291
  if (UE->UE_scan == 0) {
    do  {
292
      current_band = eutra_bands[ind].band;
knopp's avatar
 
knopp committed
293
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
294

295
      if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) {
296 297
	for (i=0; i<4; i++)
	  uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
298 299 300 301

        found = 1;
        break;
      }
302

303
      ind++;
304 305
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
  
306 307
    if (found == 0) {
      exit_fun("Can't find EUTRA band for frequency");
308
      return &UE_thread_synch_retval;
309
    }
310

311

312
    LOG_I( PHY, "[SCHED][UE] Check absolute frequency DL %"PRIu32", UL %"PRIu32" (oai_exit %d, rx_num_channels %d)\n", UE->frame_parms.dl_CarrierFreq, UE->frame_parms.ul_CarrierFreq,oai_exit, openair0_cfg[0].rx_num_channels);
313

314
    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
315 316
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = UE->frame_parms.dl_CarrierFreq;
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = UE->frame_parms.ul_CarrierFreq;
317 318 319
      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;
320
      else //FDD
321
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
322 323
    }

324
    sync_mode = pbch;
325

326
  } else if  (UE->UE_scan == 1) {
327
    current_band=0;
328

329 330
    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;
331 332
      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;
333
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
334 335
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
	downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
336
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
337 338
    }
  }
339

340 341 342
  while (sync_var<0)     
    pthread_cond_wait(&sync_cond, &sync_mutex);   
  pthread_mutex_unlock(&sync_mutex);   
knopp's avatar
knopp committed
343

344
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");   
345

346 347 348
  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {     
    LOG_E(HW,"Could not start the device\n");     
    oai_exit=1;   
knopp's avatar
knopp committed
349 350
  }

351
  while (oai_exit==0) {
352 353
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    while (UE->proc.instance_cnt_synch < 0)
354
      // the thread waits here most of the time
355
      pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
356 357
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
    
358
    switch (sync_mode) {
359
    case pss:
360 361
      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);
362
      current_offset += 20000000; // increase by 20 MHz
363
      
364
      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
365
	current_band++;
laurent's avatar
laurent committed
366 367
                current_offset=0;
            }
368

laurent's avatar
laurent committed
369 370 371 372
            if (current_band==bands_to_scan.nbands) {
                current_band=0;
                oai_exit=1;
            }
373

laurent's avatar
laurent committed
374 375 376
            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;
377

laurent's avatar
laurent committed
378 379 380 381 382 383
                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;
                }
384

385
	
386
	    }
387

388
	    break;
389
 
390
    case pbch:
391

Rohit Gupta's avatar
Rohit Gupta committed
392
      LOG_I(PHY,"[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
393 394


395 396 397 398 399
      LOG_I(PHY,"[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
      if (initial_sync( UE, UE->mode ) == 0) {
	
	hw_slot_offset = (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti;
	LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
400 401 402
	       hw_slot_offset,
	       freq_offset,
	       UE->rx_total_gain_dB,
403 404
	       downlink_frequency[0][0]+freq_offset,
	       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset,
405
	       UE->UE_scan_carrier );
406 407 408 409 410 411
	
	
	// rerun with new cell parameters and frequency-offset
	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;
	  if (UE->UE_scan_carrier == 1) {
412
	    if (freq_offset >= 0)
413
	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
414
	    else
415 416 417 418 419
	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(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];
	    freq_offset=0;
420
	  }
421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448
	  
	}	  
	// reconfigure for potentially different bandwidth
	switch(UE->frame_parms.N_RB_DL) {
	case 6:
	  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;
	  //            openair0_cfg[0].rx_gain[0] -= 12;
	  break;
	case 25:
	  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;
	  //            openair0_cfg[0].rx_gain[0] -= 6;
	  break;
	case 50:
	  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;
	  //            openair0_cfg[0].rx_gain[0] -= 3;
	  break;
	case 100:
	  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;
	  //            openair0_cfg[0].rx_gain[0] -= 0;
	  break;
449
	}
450 451 452 453 454 455 456 457 458 459 460 461 462 463 464 465
	
	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
	//UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
	//UE->rfdevice.trx_stop_func(&UE->rfdevice);
	sleep(1);
	init_frame_parms(&UE->frame_parms,1);
	/*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
	  LOG_E(HW,"Could not start the device\n");
	  oai_exit=1;
	  }*/
	
	if (UE->UE_scan_carrier == 1) {
	  
	  UE->UE_scan_carrier = 0;
	} else {
	  AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
466
	  UE->is_synchronized = 1;
467 468 469
	  AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
	  
	  if( UE->mode == rx_dump_frame ) {
470
	    FILE *fd;
471
	    if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present
472 473 474 475 476 477 478 479
	      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);
480
	      } else {
481 482 483
		LOG_E(PHY,"Cannot open file for writing\n");
		exit(0);
	      }
484 485
	    } else {
	      AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
486
	      UE->is_synchronized = 0;
487 488
	      AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
	      
489 490
	    }
	  }
491
	}
492
      } else {
493 494
	// initial sync failed
	// calculate new offset and try again
495
	if (UE->UE_scan_carrier == 1) {
496
	  if (freq_offset >= 0)
497
	    freq_offset += 100;
498 499
	  freq_offset *= -1;
	  
500 501
	  if (abs(freq_offset) > 7500) {
	    LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
502
	    FILE *fd;
503
	    if ((fd = fopen("rxsig_frame0.dat","w"))!=NULL) {
504
	      fwrite((void*)&UE->common_vars.rxdata[0][0],
505
		     sizeof(int32_t),
506
		     10*UE->frame_parms.samples_per_tti,
507 508 509 510 511
		     fd);
	      LOG_I(PHY,"Dummping Frame ... bye bye \n");
	      fclose(fd);
	      exit(0);
	    }
512
	    exit_fun("No cell synchronization found, abandoning");
513 514 515
	    return &UE_thread_synch_retval; // not reached
	  }
	}
516
	LOG_I( PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
517
	       freq_offset,
518 519 520 521
	       UE->rx_total_gain_dB,
	       downlink_frequency[0][0]+freq_offset,
	       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
	
522
	for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
523 524
	  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;
525
	  openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
526
	  if (UE->UE_scan_carrier==1)
527
	    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
528
	}
529
	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
530
      }// initial_sync=0
531 532 533 534 535
      break;
    case si:
    default:
      break;
    }
536 537
    
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
538
    // indicate readiness
539
    UE->proc.instance_cnt_synch--;
540 541
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
    
542
    VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
543
  }  // while !oai_exit
544
  
545
  return &UE_thread_synch_retval;
546 547
}

548

549 550 551 552 553 554 555
/* this structure is used to pass both UE phy vars and
 * proc to the function UE_thread_rxn_txnp4
 */
struct rx_tx_thread_data {
  PHY_VARS_UE    *UE;
  UE_rxtx_proc_t *proc;
};
556

557
/*!
558
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
559
 * This thread performs the phy_procedures_UE_RX() on every received slot.
laurent's avatar
laurent committed
560
 * then, if TX is enabled it performs TX for n+4.
561 562 563
 * \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.
 */
564

laurent's avatar
laurent committed
565 566
static void *UE_thread_rxn_txnp4(void *arg) {
    static __thread int UE_thread_rxtx_retval;
567 568 569
    struct rx_tx_thread_data *rtd = arg;
    UE_rxtx_proc_t *proc = rtd->proc;
    PHY_VARS_UE    *UE   = rtd->UE;
laurent's avatar
laurent committed
570 571
    int ret;

572 573 574 575
    // Panos: Call (Sched_Rsp_t) get_nfapi_sched_response(UE->Mod_ID) to get all
    //sched_response config messages which concern the specific UE. Inside this
    //function we should somehow make the translation of rnti to Mod_ID.

576
    proc->instance_cnt_rxtx=-1;
laurent's avatar
laurent committed
577 578
    proc->subframe_rx=proc->sub_frame_start;

579 580
    char threadname[256];
    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
laurent's avatar
laurent committed
581 582
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
583 584 585 586
    if ( (proc->sub_frame_start+1)%2 == 0 && threads.even != -1 )
        CPU_SET(threads.even, &cpuset);
    if ( (proc->sub_frame_start+1)%2 == 1 && threads.odd != -1 )
        CPU_SET(threads.odd, &cpuset);
laurent's avatar
laurent committed
587
    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
588
                threadname);
laurent's avatar
laurent committed
589 590

    while (!oai_exit) {
591 592 593 594 595 596 597 598 599 600 601 602
        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
          exit_fun("nothing to add");
        }
        while (proc->instance_cnt_rxtx < 0) {
          // most of the time, the thread is waiting here
          pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
        }
        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
          exit_fun("nothing to add");
        }
laurent's avatar
laurent committed
603

laurent's avatar
laurent committed
604 605 606 607
        initRefTimes(t2);
        initRefTimes(t3);
        pickTime(current);
        updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");
laurent's avatar
laurent committed
608 609 610 611 612 613 614 615 616

        // Process Rx data for one sub-frame
        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)) {

            if (UE->frame_parms.frame_type == TDD) {
                LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
617
                      threadname,
laurent's avatar
laurent committed
618 619 620 621 622 623
                      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",
624
                      threadname,
laurent's avatar
laurent committed
625 626 627 628 629 630
                      (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"))));
            }
631
            // Panos: Substitute with call to handle_nfapi_UE_Rx(Sched_Resp).
laurent's avatar
laurent committed
632 633
            phy_procedures_UE_RX( UE, proc, 0, 0, UE->mode, no_relay, NULL );
        }
Bilel's avatar
Bilel committed
634 635 636

        start_meas(&UE->generic_stat);

laurent's avatar
laurent committed
637 638
        if (UE->mac_enabled==1) {

639 640 641 642 643 644 645 646
            ret = ue_scheduler(UE->Mod_id,
			       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*/);
laurent's avatar
laurent committed
647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665
            if ( ret != CONNECTION_OK) {
                char *txt;
                switch (ret) {
                case CONNECTION_LOST:
                    txt="RRC Connection lost, returning to PRACH";
                    break;
                case PHY_RESYNCH:
                    txt="RRC Connection lost, trying to resynch";
                    break;
                case RESYNCH:
                    txt="return to PRACH and perform a contention-free access";
                    break;
                default:
                    txt="UNKNOWN RETURN CODE";
                };
                LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
                       UE->Mod_id, proc->frame_rx, proc->subframe_tx,txt );
            }
        }
Bilel's avatar
Bilel committed
666 667 668

        stop_meas(&UE->generic_stat);

669

laurent's avatar
laurent committed
670
        // Prepare the future Tx data
671

laurent's avatar
laurent committed
672
        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
673
	    (UE->frame_parms.frame_type == FDD) )
674 675 676 677 678
            if (UE->mode != loop_through_memory){
            	// Panos: Substitute with call to generate_nfapi_UL_indications and then send_nfapi_UL_indications()
            	phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
            }

679 680


681

laurent's avatar
laurent committed
682 683 684 685
        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);
laurent's avatar
laurent committed
686
        updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
687

688 689 690 691 692 693 694 695 696
        if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
          exit_fun("noting to add");
        }
        proc->instance_cnt_rxtx--;
        if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
          exit_fun("noting to add");
        }
697 698
    }

laurent's avatar
laurent committed
699
// thread finished
700
    free(arg);
laurent's avatar
laurent committed
701
    return &UE_thread_rxtx_retval;
Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
702
}
703

704 705 706
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
707 708
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
709 710 711 712
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
713 714 715 716

void *UE_thread(void *arg) {


717
    PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
laurent's avatar
laurent committed
718 719 720 721 722 723
    //  int tx_enabled = 0;
    int dummy_rx[UE->frame_parms.nb_antennas_rx][UE->frame_parms.samples_per_tti] __attribute__((aligned(32)));
    openair0_timestamp timestamp,timestamp1;
    void* rxp[NB_ANTENNAS_RX], *txp[NB_ANTENNAS_TX];
    int start_rx_stream = 0;
    int i;
724
    char threadname[128];
725

laurent's avatar
laurent committed
726 727
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
728 729
    if ( threads.iq != -1 )
        CPU_SET(threads.iq, &cpuset);
laurent's avatar
laurent committed
730
    init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
731
                "UHD Threads");
732 733

#ifdef NAS_UE
laurent's avatar
laurent committed
734 735
    MessageDef *message_p;
    message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
736
    itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
Bilel's avatar
Bilel committed
737
#endif
738

laurent's avatar
laurent committed
739
    int sub_frame=-1;
740
    //int cumulated_shift=0;
741

742
    
laurent's avatar
laurent committed
743
    while (!oai_exit) {
laurent's avatar
laurent committed
744 745 746 747
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
        int instance_cnt_synch = UE->proc.instance_cnt_synch;
        int is_synchronized    = UE->is_synchronized;
        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
748

laurent's avatar
laurent committed
749
        if (is_synchronized == 0) {
laurent's avatar
laurent committed
750 751 752
            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++)
753
                    rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
laurent's avatar
laurent committed
754 755 756 757 758 759 760 761

                if (UE->mode != loop_through_memory)
                    AssertFatal( UE->frame_parms.samples_per_tti*10 ==
                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                            &timestamp,
                                                            rxp,
                                                            UE->frame_parms.samples_per_tti*10,
                                                            UE->frame_parms.nb_antennas_rx), "");
laurent's avatar
laurent committed
762
		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
763 764 765 766 767 768 769
                instance_cnt_synch = ++UE->proc.instance_cnt_synch;
                if (instance_cnt_synch == 0) {
                    AssertFatal( 0 == pthread_cond_signal(&UE->proc.cond_synch), "");
                } else {
                    LOG_E( PHY, "[SCHED][UE] UE sync thread busy!!\n" );
                    exit_fun("nothing to add");
                }
770
		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
771
            } else {
laurent's avatar
laurent committed
772 773 774 775
                // 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];
laurent's avatar
laurent committed
776
                    for (int sf=0; sf<10; sf++)
laurent's avatar
laurent committed
777
                        //	    printf("Reading dummy sf %d\n",sf);
778
                          UE->rfdevice.trx_read_func(&UE->rfdevice,
laurent's avatar
laurent committed
779 780 781
                                              &timestamp,
                                              rxp,
                                              UE->frame_parms.samples_per_tti,
782
                                              UE->frame_parms.nb_antennas_rx);
laurent's avatar
laurent committed
783
                }
784
            }
785

laurent's avatar
laurent committed
786 787 788 789 790 791 792 793 794 795
        } // UE->is_synchronized==0
        else {
            if (start_rx_stream==0) {
                start_rx_stream=1;
                if (UE->mode != loop_through_memory) {
                    if (UE->no_timing_correction==0) {
                        LOG_I(PHY,"Resynchronizing RX by %d samples (mode = %d)\n",UE->rx_offset,UE->mode);
                        AssertFatal(UE->rx_offset ==
                                    UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                               &timestamp,
796
                                                               (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
797 798 799 800 801 802 803 804 805 806 807
                                                               UE->rx_offset,
                                                               UE->frame_parms.nb_antennas_rx),"");
                    }
                    UE->rx_offset=0;
                    UE->proc.proc_rxtx[0].frame_rx++;
                    UE->proc.proc_rxtx[1].frame_rx++;

                    // read in first symbol
                    AssertFatal (UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0 ==
                                 UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                            &timestamp,
808 809
                                                            (void**)UE->common_vars.rxdata,
                                                            UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
laurent's avatar
laurent committed
810 811 812 813 814 815 816 817 818 819 820 821 822
                                                            UE->frame_parms.nb_antennas_rx),"");
                    slot_fep(UE,0, 0, 0, 0, 0);
                } //UE->mode != loop_through_memory
                else
                    rt_sleep_ns(1000*1000);

            } else {
                sub_frame++;
                sub_frame%=10;
                UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[sub_frame&1];

                if (UE->mode != loop_through_memory) {
                    for (i=0; i<UE->frame_parms.nb_antennas_rx; i++)
Thomas Laurent's avatar
Thomas Laurent committed
823
                        rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
824 825
                                 UE->frame_parms.nb_prefix_samples0+
                                 sub_frame*UE->frame_parms.samples_per_tti];
laurent's avatar
laurent committed
826 827 828 829 830 831 832 833
                    for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
                        txp[i] = (void*)&UE->common_vars.txdata[i][((sub_frame+2)%10)*UE->frame_parms.samples_per_tti];

                    int readBlockSize, writeBlockSize;
                    if (sub_frame<9) {
                        readBlockSize=UE->frame_parms.samples_per_tti;
                        writeBlockSize=UE->frame_parms.samples_per_tti;
                    } else {
834 835 836
                        // set TO compensation to zero
                        UE->rx_offset_diff = 0;
                        // compute TO compensation that should be applied for this frame
laurent's avatar
laurent committed
837 838 839 840 841 842 843
                        if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti  &&
                                UE->rx_offset > 0 )
                            UE->rx_offset_diff = -1 ;
                        if ( UE->rx_offset > 5*UE->frame_parms.samples_per_tti &&
                                UE->rx_offset < 10*UE->frame_parms.samples_per_tti )
                            UE->rx_offset_diff = 1;

844
                        LOG_D(PHY,"AbsSubframe %d.%d SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,sub_frame,UE->rx_offset_diff,UE->rx_offset);
laurent's avatar
laurent committed
845 846 847 848 849 850
                        readBlockSize=UE->frame_parms.samples_per_tti -
                                      UE->frame_parms.ofdm_symbol_size -
                                      UE->frame_parms.nb_prefix_samples0 -
                                      UE->rx_offset_diff;
                        writeBlockSize=UE->frame_parms.samples_per_tti -
                                       UE->rx_offset_diff;
laurent's avatar
laurent committed
851 852 853 854 855 856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873 874 875
                    }

                    AssertFatal(readBlockSize ==
                                UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                           &timestamp,
                                                           rxp,
                                                           readBlockSize,
                                                           UE->frame_parms.nb_antennas_rx),"");
                    AssertFatal( writeBlockSize ==
                                 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,
                                         writeBlockSize,
                                         UE->frame_parms.nb_antennas_tx,
                                         1),"");
                    if( sub_frame==9) {
                        // read in first symbol of next frame and adjust for timing drift
                        int first_symbols=writeBlockSize-readBlockSize;
                        if ( first_symbols > 0 )
                            AssertFatal(first_symbols ==
                                        UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                                   &timestamp1,
Thomas Laurent's avatar
Thomas Laurent committed
876
                                                                   (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
877 878 879 880 881
                                                                   first_symbols,
                                                                   UE->frame_parms.nb_antennas_rx),"");
                        if ( first_symbols <0 )
                            LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
                    }
laurent's avatar
laurent committed
882
                    pickTime(gotIQs);
laurent's avatar
laurent committed
883 884 885 886 887 888
                    // operate on thread sf mod 2
                    AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,"");
                    if(sub_frame == 0) {
                        UE->proc.proc_rxtx[0].frame_rx++;
                        UE->proc.proc_rxtx[1].frame_rx++;
                    }
laurent's avatar
laurent committed
889 890
                    UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs);
                    UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs);
laurent's avatar
laurent committed
891 892 893 894 895 896 897
                    proc->subframe_rx=sub_frame;
                    proc->subframe_tx=(sub_frame+4)%10;
                    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
                    proc->timestamp_tx = timestamp+
                                         (4*UE->frame_parms.samples_per_tti)-
                                         UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;

898 899 900 901 902 903 904 905 906 907 908 909
                    proc->instance_cnt_rxtx++;
                    if (proc->instance_cnt_rxtx == 0) {
                      if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
                        LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
                        exit_fun("nothing to add");
                      }
                    } else {
                      LOG_E( PHY, "[SCHED][UE %d] UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx);
                      if (proc->instance_cnt_rxtx > 2)
                        exit_fun("instance_cnt_rxtx > 2");
                    }

laurent's avatar
laurent committed
910 911
                    AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,"");
                    AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");
laurent's avatar
laurent committed
912 913 914 915
                    initRefTimes(t1);
                    initStaticTime(lastTime);
                    updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)");
                    pickStaticTime(lastTime);
laurent's avatar
laurent committed
916 917 918 919 920 921