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

36
#ifdef OPENAIR2
37 38
#include "LAYER2/MAC/defs.h"
#include "RRC/LITE/extern.h"
39
#endif
40
#include "PHY_INTERFACE/phy_stub_UE.h"
41 42 43 44 45 46 47 48 49
#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"
50 51
//#include "openair2/PHY_INTERFACE/phy_stub_UE.h"

52 53 54 55 56 57 58 59

#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"

60 61
#include "T.h"

Bilel's avatar
Bilel committed
62
extern double cpuf;
63
extern uint8_t  nfapi_mode;
Bilel's avatar
Bilel committed
64

65 66
#define FRAME_PERIOD    100000000ULL
#define DAQ_PERIOD      66667ULL
laurent's avatar
laurent committed
67
#define FIFO_PRIORITY   40
68 69

typedef enum {
laurent's avatar
laurent committed
70 71 72
    pss=0,
    pbch=1,
    si=2
73 74
} sync_mode_t;

75
void init_UE_threads(int);
76
void *UE_thread(void *arg);
77
void init_UE(int nb_inst,int,int);
78
//extern int tx_req_UE_MAC1();
79

80 81
int32_t **rxdata;
int32_t **txdata;
82

83 84 85 86
int timer_subframe;
int timer_frame;
SF_ticking *phy_stub_ticking;

87
#define KHz (1000UL)
88
#define MHz (1000*KHz)
89 90

typedef struct eutra_band_s {
laurent's avatar
laurent committed
91 92 93 94 95 96
    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;
97 98 99
} eutra_band_t;

typedef struct band_info_s {
laurent's avatar
laurent committed
100 101
    int nbands;
    eutra_band_t band_info[100];
102 103 104 105
} band_info_t;

band_info_t bands_to_scan;

106
static const eutra_band_t eutra_bands[] = {
laurent's avatar
laurent committed
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 132 133 134 135
    { 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},
136 137
};

138 139


140

141 142 143 144
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

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

knopp's avatar
knopp committed
147 148 149
PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag)
150 151 152

{

knopp's avatar
knopp committed
153 154
  PHY_VARS_UE* ue;

155
  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
156 157 158 159 160 161
    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];

162 163 164

  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
knopp's avatar
knopp committed
165 166 167 168 169 170
  // initialize all signal buffers
  init_lte_ue_signal(ue,1,abstraction_flag);
  // intialize transport
  init_lte_ue_transport(ue,abstraction_flag);

  return(ue);
171 172
}

knopp's avatar
knopp committed
173

174 175
char uecap_xer[1024];

176 177


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

laurent's avatar
laurent committed
180 181 182 183 184 185 186 187 188
#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,
189
                    "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
190 191
        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
192
    }
laurent's avatar
laurent committed
193
#else
194
    if (CPU_COUNT(cpuset) > 0)
laurent's avatar
laurent committed
195 196 197 198 199
        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");
200 201 202 203 204 205 206 207
    /* 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);
208
    }
209
    CPU_FREE(cset);
210 211
#endif

laurent's avatar
laurent committed
212
}
213

214
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in) {
215

knopp's avatar
knopp committed
216
  PHY_VARS_UE *UE;
217 218
  int         inst;
  int         ret;
knopp's avatar
knopp committed
219

220
  LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
221 222 223 224
    
  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
	     0,// cba_group_active
	     0); // HO flag
225
  
knopp's avatar
knopp committed
226
  for (inst=0;inst<nb_inst;inst++) {
227

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

231
    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
232 233
    init_UE_threads(inst);
    UE = PHY_vars_UE_g[inst][0];
knopp's avatar
knopp committed
234

235 236 237 238 239
    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
240
    }
241
    UE->rfdevice.host_type = RAU_HOST;
knopp's avatar
knopp committed
242
    //    UE->rfdevice.type      = NONE_DEV;
243 244 245 246 247
    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), "");
248 249
  }

250
  printf("UE threads created by %ld\n", gettid());
251 252
#if 0
#if defined(ENABLE_USE_MME)
253
  extern volatile int start_UE;
254 255 256 257
  while (start_UE == 0) {
    sleep(1);
  }
#endif
258
#endif
259 260
}

261 262
/*!
 * \brief This is the UE synchronize thread.
263
 * It performs band scanning and synchonization.
264 265 266
 * \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
267

268 269
static void *UE_thread_synch(void *arg)
{
270 271 272
  static int UE_thread_synch_retval;
  int i, hw_slot_offset;
  PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
273 274
  int current_band = 0;
  int current_offset = 0;
275
  sync_mode_t sync_mode = pbch;
276
  int CC_id = UE->CC_id;
277 278
  int ind;
  int found;
279
  int freq_offset=0;
280
  char threadname[128];
281 282 283

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

285
   cpu_set_t cpuset;
286
  CPU_ZERO(&cpuset);
287 288 289 290 291
  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);
292
  
293
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
294 295
  ind = 0;
  found = 0;
296 297


298 299
  if (UE->UE_scan == 0) {
    do  {
300
      current_band = eutra_bands[ind].band;
301
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
302

303
      if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) {
304 305
	for (i=0; i<4; i++)
	  uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
306 307 308 309

        found = 1;
        break;
      }
310

311
      ind++;
312 313
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
  
314 315
    if (found == 0) {
      exit_fun("Can't find EUTRA band for frequency");
316
      return &UE_thread_synch_retval;
317
    }
318

319

320
    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);
321

322
    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
323 324
      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;
325 326 327
      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;
328
      else //FDD
329
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
330 331
    }

332
    sync_mode = pbch;
333

334
  } else if  (UE->UE_scan == 1) {
335
    current_band=0;
336

337 338
    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;
339 340
      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;
341
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
342 343
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
	downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
344
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
345 346
    }
  }
347

348 349 350
  while (sync_var<0)     
    pthread_cond_wait(&sync_cond, &sync_mutex);   
  pthread_mutex_unlock(&sync_mutex);   
knopp's avatar
knopp committed
351

352
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");   
353

354 355 356
  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
357 358
  }

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

laurent's avatar
laurent committed
377 378 379 380
            if (current_band==bands_to_scan.nbands) {
                current_band=0;
                oai_exit=1;
            }
381

laurent's avatar
laurent committed
382 383 384
            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;
385

laurent's avatar
laurent committed
386 387 388 389 390 391
                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;
                }
392
	    }
393

394
	    break;
395
 
396
    case pbch:
397

Cedric Roux's avatar
Cedric Roux committed
398
#if DISABLE_LOG_X
399
            printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
Cedric Roux's avatar
Cedric Roux committed
400 401 402
#else
            LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
#endif
laurent's avatar
laurent committed
403 404 405 406 407 408 409 410 411 412 413
            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",
                       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 );

414

laurent's avatar
laurent committed
415 416 417
                    // 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;
418
			if (UE->UE_scan_carrier == 1) {
laurent's avatar
laurent committed
419
                        if (freq_offset >= 0)
420
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
421
                        else
422
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
423 424
                        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];
laurent's avatar
laurent committed
425 426 427
                        downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
                        freq_offset=0;
                    }
428
	  }
429

laurent's avatar
laurent committed
430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450 451 452 453 454 455 456
                    // 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;
                    }
457

laurent's avatar
laurent committed
458 459
                    UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
                    //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
460
                    //UE->rfdevice.trx_stop_func(&UE->rfdevice);
laurent's avatar
laurent committed
461 462
                    sleep(1);
                    init_frame_parms(&UE->frame_parms,1);
463
                    /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
laurent's avatar
laurent committed
464 465
                        LOG_E(HW,"Could not start the device\n");
                        oai_exit=1;
466
                    }*/
467 468 469 470

		if (UE->UE_scan_carrier == 1) {

		  UE->UE_scan_carrier = 0;
laurent's avatar
laurent committed
471
                } else {
laurent's avatar
laurent committed
472
                    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
473
                    UE->is_synchronized = 1;
laurent's avatar
laurent committed
474
                    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491

                    if( UE->mode == rx_dump_frame ) {
                        FILE *fd;
                        if ((UE->proc.proc_rxtx[0].frame_rx&1) == 0) {  // this guarantees SIB1 is present
                            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 {
laurent's avatar
laurent committed
492
                            AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
493
                            UE->is_synchronized = 0;
laurent's avatar
laurent committed
494 495
                            AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

laurent's avatar
laurent committed
496 497 498 499 500 501 502
                        }
                    }
                }
            } else {
                // initial sync failed
                // calculate new offset and try again
                if (UE->UE_scan_carrier == 1) {
laurent's avatar
laurent committed
503
                    if (freq_offset >= 0)
laurent's avatar
laurent committed
504
                        freq_offset += 100;
laurent's avatar
laurent committed
505
                    freq_offset *= -1;
laurent's avatar
laurent committed
506 507 508 509 510 511 512 513 514 515 516 517 518

                    if (abs(freq_offset) > 7500) {
                        LOG_I( PHY, "[initial_sync] No cell synchronization found, abandoning\n" );
                        FILE *fd;
                        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);
                        }
519
                        AssertFatal(1==0,"No cell synchronization found, abandoning");
laurent's avatar
laurent committed
520 521 522
                        return &UE_thread_synch_retval; // not reached
                    }
                }
Cedric Roux's avatar
Cedric Roux committed
523
#if DISABLE_LOG_X
524
                printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
laurent's avatar
laurent committed
525 526 527 528
                       freq_offset,
                       UE->rx_total_gain_dB,
                       downlink_frequency[0][0]+freq_offset,
                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
Cedric Roux's avatar
Cedric Roux committed
529 530 531 532 533 534 535
#else
                LOG_I(PHY, "[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
                       freq_offset,
                       UE->rx_total_gain_dB,
                       downlink_frequency[0][0]+freq_offset,
                       downlink_frequency[0][0]+uplink_frequency_offset[0][0]+freq_offset );
#endif
laurent's avatar
laurent committed
536 537 538 539 540

                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;
laurent's avatar
laurent committed
541
                    if (UE->UE_scan_carrier==1)
laurent's avatar
laurent committed
542 543 544 545 546 547 548 549 550
                        openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
                }
                UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
            }// initial_sync=0
            break;
        case si:
        default:
            break;
        }
551

laurent's avatar
laurent committed
552
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
553 554
        // indicate readiness
        UE->proc.instance_cnt_synch--;
laurent's avatar
laurent committed
555
        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
556

laurent's avatar
laurent committed
557 558
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
    }  // while !oai_exit
559

laurent's avatar
laurent committed
560
    return &UE_thread_synch_retval;
561 562
}

563
/*!
564
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
565
 * This thread performs the phy_procedures_UE_RX() on every received slot.
laurent's avatar
laurent committed
566
 * then, if TX is enabled it performs TX for n+4.
567 568 569
 * \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.
 */
570

laurent's avatar
laurent committed
571
static void *UE_thread_rxn_txnp4(void *arg) {
572
	module_id_t Mod_id = 0;
laurent's avatar
laurent committed
573
    static __thread int UE_thread_rxtx_retval;
574 575 576
    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
577 578
    int ret;

579 580 581 582
    // 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.

583
    proc->instance_cnt_rxtx=-1;
laurent's avatar
laurent committed
584 585
    proc->subframe_rx=proc->sub_frame_start;

586 587
    char threadname[256];
    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
laurent's avatar
laurent committed
588 589
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
590

Bilel's avatar
Bilel committed
591 592 593 594 595
    if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 )
        CPU_SET(threads.one, &cpuset);
    if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 )
        CPU_SET(threads.two, &cpuset);
    if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 )
596
        CPU_SET(threads.three, &cpuset);
Bilel's avatar
Bilel committed
597
            //CPU_SET(threads.three, &cpuset);
laurent's avatar
laurent committed
598
    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
599
                threadname);
laurent's avatar
laurent committed
600 601

    while (!oai_exit) {
602 603 604 605 606 607 608 609 610 611 612 613
        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
614

laurent's avatar
laurent committed
615 616 617 618
        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
619 620 621 622 623 624 625 626 627

        // 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",
628
                      threadname,
laurent's avatar
laurent committed
629 630 631 632 633 634
                      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",
635
                      threadname,
laurent's avatar
laurent committed
636 637 638 639 640 641
                      (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"))));
            }
matzakos's avatar
matzakos committed
642

643 644 645
#ifdef UE_SLOT_PARALLELISATION
            phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#else
646 647 648 649
			// Panos: Substitute call to phy_procedures Rx with call to phy_stub functions in order to trigger
            // UE Rx procedures directly at the MAC layer, based on the received nfapi requests from the vnf (eNB).
            // Hardcode Mod_id for now. Will be changed later.

650
            if(nfapi_mode == 3){
651 652
            	// Panos: is this the right place to call oai_subframe_indication to invoke p7 nfapi callbacks here?
            	//oai_subframe_insdication()
653 654 655 656 657 658 659 660 661 662
            	if(UE_mac_inst[Mod_id].tx_req)
            		tx_req_UE_MAC(UE_mac_inst[Mod_id].tx_req);
            	if(UE_mac_inst[Mod_id].dl_config_req)
            		dl_config_req_UE_MAC(UE_mac_inst[Mod_id].dl_config_req);
            	if(UE_mac_inst[Mod_id].hi_dci0_req)
            		hi_dci0_req_UE_MAC(UE_mac_inst[Mod_id].hi_dci0_req);
            }
            else{
            phy_procedures_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
            }
663
#endif
laurent's avatar
laurent committed
664
        }
Bilel's avatar
Bilel committed
665

Gabriel's avatar
Gabriel committed
666
#if UE_TIMING_TRACE
Bilel's avatar
Bilel committed
667
        start_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
668
#endif
laurent's avatar
laurent committed
669 670
        if (UE->mac_enabled==1) {

671 672 673 674 675 676 677 678
            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
679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697
            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 );
            }
        }
Gabriel's avatar
Gabriel committed
698
#if UE_TIMING_TRACE
Bilel's avatar
Bilel committed
699
        stop_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
700
#endif
Bilel's avatar
Bilel committed
701

702

laurent's avatar
laurent committed
703
        // Prepare the future Tx data
704

laurent's avatar
laurent committed
705
        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
706
	    (UE->frame_parms.frame_type == FDD) )
707
            if (UE->mode != loop_through_memory){
708 709 710
            	// Panos: Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
                // UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
            	// Generate UL_indications which corresponf to UL traffic.
711
            	if(nfapi_mode == 3 && UE_mac_inst[Mod_id].ul_config_req){
712 713 714
            		ul_config_req_UE_MAC(UE_mac_inst[Mod_id].ul_config_req);
            		UL_indication(UL_INFO);
            	}
715 716 717
            	else{
            	phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
            	}
718 719
            }

720 721


722

laurent's avatar
laurent committed
723 724 725 726
        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
727
        updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
728

729 730 731 732 733 734 735 736 737
        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");
        }
738 739
    }

laurent's avatar
laurent committed
740
// thread finished
741
    free(arg);
laurent's avatar
laurent committed
742
    return &UE_thread_rxtx_retval;
743
}
744

745 746 747
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
748 749
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
750 751 752 753
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
754
// Panos: Modified function to support nfapi_mode=3 (phy_stub mode).
755 756 757
void *UE_thread(void *arg) {


758
    PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
laurent's avatar
laurent committed
759 760 761 762 763 764
    //  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;
Bilel's avatar
Bilel committed
765
    int th_id;
766

767
    static uint8_t thread_idx = 0;
768

laurent's avatar
laurent committed
769 770
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
771 772
    if ( threads.iq != -1 )
        CPU_SET(threads.iq, &cpuset);
laurent's avatar
laurent committed
773
    init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
774
                "UHD Threads");
775 776

#ifdef NAS_UE
laurent's avatar
laurent committed
777 778
    MessageDef *message_p;
    message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
779
    itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
780
#endif
781

laurent's avatar
laurent committed
782
    int sub_frame=-1;
783 784 785 786
    if(nfapi_mode==3) {
    	phy_stub_ticking->ticking_var = -1;
    }

787
    //int cumulated_shift=0;
788

789

laurent's avatar
laurent committed
790
    while (!oai_exit) {
791 792
    	if(nfapi_mode!=3) {
    	AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
793 794 795
        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
796

laurent's avatar
laurent committed
797
        if (is_synchronized == 0) {
laurent's avatar
laurent committed
798 799 800
            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++)
801
                    rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
laurent's avatar
laurent committed
802 803 804 805 806 807 808 809

                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
810
		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
811 812 813 814 815 816 817
                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");
                }
818
		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
819
            } else {
Cedric Roux's avatar
Cedric Roux committed
820
#if OAISIM
821
              (void)dummy_rx; /* avoid gcc warnings */
Cedric Roux's avatar
Cedric Roux committed
822 823
              usleep(500);
#else
laurent's avatar
laurent committed
824 825 826 827
                // 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
828
                    for (int sf=0; sf<10; sf++)
laurent's avatar
laurent committed
829
                        //	    printf("Reading dummy sf %d\n",sf);
830
                          UE->rfdevice.trx_read_func(&UE->rfdevice,
laurent's avatar
laurent committed
831 832 833
                                              &timestamp,
                                              rxp,
                                              UE->frame_parms.samples_per_tti,
834
                                              UE->frame_parms.nb_antennas_rx);
laurent's avatar
laurent committed
835
                }
Cedric Roux's avatar
Cedric Roux committed
836
#endif
837
            }
838

laurent's avatar
laurent committed
839 840 841 842 843 844 845 846 847 848
        } // 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,
849
                                                               (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
850 851 852 853
                                                               UE->rx_offset,
                                                               UE->frame_parms.nb_antennas_rx),"");
                    }
                    UE->rx_offset=0;
854
                    UE->time_sync_cell=0;
Bilel's avatar
Bilel committed
855 856 857 858 859
                    //UE->proc.proc_rxtx[0].frame_rx++;
                    //UE->proc.proc_rxtx[1].frame_rx++;
                    for (th_id=0; th_id < RX_NB_TH; th_id++) {
                        UE->proc.proc_rxtx[th_id].frame_rx++;
                    }
laurent's avatar
laurent committed
860 861 862 863 864

                    // 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,
865 866
                                                            (void**)UE->common_vars.rxdata,
                                                            UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
laurent's avatar
laurent committed
867 868 869 870 871 872 873 874 875
                                                            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;
876 877 878 879 880 881 882 883 884 885
                UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[thread_idx];
                // update thread index for received subframe
                UE->current_thread_id[sub_frame] = thread_idx;

                LOG_D(PHY,"Process Subframe %d thread Idx %d \n", sub_frame, UE->current_thread_id[sub_frame]);

                thread_idx++;
                if(thread_idx>=RX_NB_TH)
                    thread_idx = 0;

laurent's avatar
laurent committed
886 887 888

                if (UE->mode != loop_through_memory) {
                    for (i=0; i<UE->frame_parms.nb_antennas_rx; i++)
Thomas Laurent's avatar
Thomas Laurent committed
889
                        rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
890 891
                                 UE->frame_parms.nb_prefix_samples0+
                                 sub_frame*UE->frame_parms.samples_per_tti];
laurent's avatar
laurent committed
892 893 894 895 896 897 898 899
                    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 {
900 901 902
                        // 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
903 904 905 906 907 908 909
                        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;

910
                        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
911 912 913 914 915 916
                        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
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
                    }

                    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
942
                                                                   (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
943 944 945 946 947
                                                                   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
948
                    pickTime(gotIQs);
laurent's avatar
laurent committed
949 950
                    // operate on thread sf mod 2
                    AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,"");
951

laurent's avatar
laurent committed
952
                    if(sub_frame == 0) {
Bilel's avatar
Bilel committed
953 954 955 956 957 958 959 960 961 962
                        //UE->proc.proc_rxtx[0].frame_rx++;
                        //UE->proc.proc_rxtx[1].frame_rx++;
                        for (th_id=0; th_id < RX_NB_TH; th_id++) {
                            UE->proc.proc_rxtx[th_id].frame_rx++;
                        }
                    }
                    //UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs);
                    //UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs);
                    for (th_id=0; th_id < RX_NB_TH; th_id++) {
                        UE->proc.proc_rxtx[th_id].gotIQs=readTime(gotIQs);
laurent's avatar
laurent committed
963 964 965 966 967 968 969 970
                    }
                    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;

971
                    proc->instance_cnt_rxtx++;
972
                    LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx);
973 974 975 976 977 978 979 980 981 982 983
                    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
984 985
                    AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,"");
                    AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");
laurent's avatar
laurent committed
986 987 988 989
                    initRefTimes(t1);
                    initStaticTime(lastTime);
                    updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)");
                    pickStaticTime(lastTime);
laurent's avatar
laurent committed
990 991 992 993 994 995 996 997

                } else {
                    printf("Processing subframe %d",proc->subframe_rx);
                    getchar();
                }
            } // start_rx_stream==1
        } // UE->is_synchronized==1

998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054 1055 1056 1057 1058 1059 1060 1061 1062 1063
    } // nfapi_mode!=3
    	else { // nfapi_mode==3

    		//AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_ticking), "");
    		AssertFatal ( 0== pthread_mutex_lock(&phy_stub_ticking->mutex_ticking), "");
    		while (phy_stub_ticking->ticking_var<0)
    			pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
    		AssertFatal ( 0== pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking), "");

    		UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[thread_idx];
    		// update thread index for received subframe
    		UE->current_thread_id[sub_frame] = thread_idx;
    		LOG_D(PHY,"Process Subframe %d thread Idx %d \n", sub_frame, UE->current_thread_id[sub_frame]);
    		thread_idx++;
    		if(thread_idx>=RX_NB_TH)
    			thread_idx = 0;

    		// Panos: timer_subframe/timer_frame (phy_stub mode SFN/SF counter) acquired from thread_timer.
    		if(timer_subframe == 0) {
    			//UE->proc.proc_rxtx[0].frame_rx++;
    			//UE->proc.proc_rxtx[1].frame_rx++;
    			for (th_id=0; th_id < RX_NB_TH; th_id++) {
    				//UE->proc.proc_rxtx[th_id].frame_rx++;
    				UE->proc.proc_rxtx[th_id].frame_rx = timer_frame;
    			}
    		}
    		//UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs);
    		//UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs);

    		// Panos: Remove for phy_stub
    		/*for (th_id=0; th_id < RX_NB_TH; th_id++) {
    			UE->proc.proc_rxtx[th_id].gotIQs=readTime(gotIQs);
    		}*/

    		proc->subframe_rx=timer_subframe;
    		proc->subframe_tx=(sub_frame+4)%10;
    		proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);

    		// Panos: Do we need the timestamp_tx indication for phy_stub mode?
    		proc->timestamp_tx = timestamp+
    				(4*UE->frame_parms.samples_per_tti)-
    				UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;
    		proc->instance_cnt_rxtx++;

    		LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx);
    		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");
    		}
    		AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,"");
    		AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");

    		// Panos: Do we need these function calls for the phy_stub?
    		/*initRefTimes(t1);
    		initStaticTime(lastTime);
    		updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)");
    		pickStaticTime(lastTime);*/
    		phy_stub_ticking->ticking_var--;
    		}

laurent's avatar
laurent committed
1064 1065
    } // while !oai_exit
    return NULL;
1066 1067
}

1068

1069 1070 1071
/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
1072 1073
 * - UE_thread_rxtx0
 * - UE_thread_rxtx1
1074
 * - UE_thread_synch
1075 1076 1077 1078
 * - UE_thread_fep_slot0
 * - UE_thread_fep_slot1
 * - UE_thread_dlsch_proc_slot0
 * - UE_thread_dlsch_proc_slot1
1079 1080
 * and the locking between them.
 */
1081
void init_UE_threads(int inst) {
1082
    struct rx_tx_thread_data *rtd;
1083
    PHY_VARS_UE *UE;
1084

1085 1086 1087 1088
    AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
    AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
    AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
    UE = PHY_vars_UE_g[inst][0];
1089

laurent's avatar
laurent committed
1090 1091
    pthread_attr_init (&UE->proc.attr_ue);
    pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
1092

1093 1094
    pthread_mutex_init(&UE->proc.mutex_synch,NULL);
    pthread_cond_init(&UE->proc.cond_synch,NULL);