lte-ue.c 62.2 KB
Newer Older
1 2 3 4 5
/*
 * 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20
 * 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 62
#include "T.h"

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

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

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

76
void init_UE_threads(int);
77
void init_UE_threads_stub(int);
78
void *UE_thread(void *arg);
79
void init_UE(int nb_inst,int,int);
80
void init_UE_stub(int nb_inst,int,int);
81
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
82
//extern int tx_req_UE_MAC1();
83

84 85
int32_t **rxdata;
int32_t **txdata;
86

87 88 89 90
int timer_subframe;
int timer_frame;
SF_ticking *phy_stub_ticking;

91
#define KHz (1000UL)
92
#define MHz (1000*KHz)
93 94

typedef struct eutra_band_s {
laurent's avatar
laurent committed
95 96 97 98 99 100
    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;
101 102 103
} eutra_band_t;

typedef struct band_info_s {
laurent's avatar
laurent committed
104 105
    int nbands;
    eutra_band_t band_info[100];
106 107 108 109
} band_info_t;

band_info_t bands_to_scan;

110
static const eutra_band_t eutra_bands[] = {
laurent's avatar
laurent committed
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 136 137 138 139
    { 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},
140 141
};

142 143


144

145 146 147 148
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

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

knopp's avatar
knopp committed
151 152 153
PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag)
154 155 156

{

knopp's avatar
knopp committed
157 158
  PHY_VARS_UE* ue;

159
  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
160 161 162 163 164 165
    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];

166 167 168

  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
169 170 171 172

  // Panos: In phy_stub_UE (MAC-to-MAC) mode these init functions don't need to get called. Is this correct?
  if (nfapi_mode!=3)
  {
knopp's avatar
knopp committed
173 174 175 176
  // initialize all signal buffers
  init_lte_ue_signal(ue,1,abstraction_flag);
  // intialize transport
  init_lte_ue_transport(ue,abstraction_flag);
177
  }
knopp's avatar
knopp committed
178 179

  return(ue);
180 181
}

knopp's avatar
knopp committed
182

183 184
char uecap_xer[1024];

185 186


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

laurent's avatar
laurent committed
189 190 191 192 193 194 195 196 197
#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,
198
                    "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
199 200
        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
201
    }
laurent's avatar
laurent committed
202
#else
203
    if (CPU_COUNT(cpuset) > 0)
laurent's avatar
laurent committed
204 205 206 207 208
        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");
209 210 211 212 213 214 215 216
    /* 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);
217
    }
218
    CPU_FREE(cset);
219 220
#endif

laurent's avatar
laurent committed
221
}
222

223
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in) {
224

knopp's avatar
knopp committed
225
  PHY_VARS_UE *UE;
226 227
  int         inst;
  int         ret;
knopp's avatar
knopp committed
228

229
  LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");
230 231 232 233
    
  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
	     0,// cba_group_active
	     0); // HO flag
234
  
knopp's avatar
knopp committed
235
  for (inst=0;inst<nb_inst;inst++) {
236

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

240
    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
241 242
    init_UE_threads(inst);
    UE = PHY_vars_UE_g[inst][0];
knopp's avatar
knopp committed
243

244 245 246 247 248
    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
249
    }
250
    UE->rfdevice.host_type = RAU_HOST;
knopp's avatar
knopp committed
251
    //    UE->rfdevice.type      = NONE_DEV;
252 253 254 255 256
    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), "");
257 258
  }

259
  printf("UE threads created by %ld\n", gettid());
260 261
#if 0
#if defined(ENABLE_USE_MME)
262
  extern volatile int start_UE;
263 264 265 266
  while (start_UE == 0) {
    sleep(1);
  }
#endif
267
#endif
268 269
}

270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321

void init_UE_stub(int nb_inst,int eMBMS_active, int uecap_xer_in) {

  PHY_VARS_UE *UE;
  int         inst;
  //int         ret;

  LOG_I(PHY,"UE : Calling Layer 2 for initialization\n");

  l2_init_ue(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,
	     0,// cba_group_active
	     0); // HO flag

  for (inst=0;inst<nb_inst;inst++) {

    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);

    LOG_I(PHY,"Intializing UE Threads for instance %d (%p,%p)...\n",inst,PHY_vars_UE_g[inst],PHY_vars_UE_g[inst][0]);
    init_UE_threads_stub(inst);
    UE = PHY_vars_UE_g[inst][0];

    /*if (oaisim_flag == 0) {
      ret = openair0_device_load(&(UE->rfdevice), &openair0_cfg[0]);
      if (ret !=0){
	exit_fun("Error loading device library");
      }
    }*/
    //UE->rfdevice.host_type = RAU_HOST;
    //    UE->rfdevice.type      = NONE_DEV;

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

  printf("UE threads created \n");
#if 0
#if defined(ENABLE_USE_MME)
  extern volatile int start_UE;
  while (start_UE == 0) {
    sleep(1);
  }
#endif
#endif
}




322 323
/*!
 * \brief This is the UE synchronize thread.
324
 * It performs band scanning and synchonization.
325 326 327
 * \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
328

329 330
static void *UE_thread_synch(void *arg)
{
331 332 333
  static int UE_thread_synch_retval;
  int i, hw_slot_offset;
  PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
334 335
  int current_band = 0;
  int current_offset = 0;
336
  sync_mode_t sync_mode = pbch;
337
  int CC_id = UE->CC_id;
338 339
  int ind;
  int found;
340
  int freq_offset=0;
341
  char threadname[128];
342 343 344

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

346
   cpu_set_t cpuset;
347
  CPU_ZERO(&cpuset);
348 349 350 351 352
  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);
353
  
354
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
355 356
  ind = 0;
  found = 0;
357 358


359 360
  if (UE->UE_scan == 0) {
    do  {
361
      current_band = eutra_bands[ind].band;
362
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
363

364
      if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) {
365 366
	for (i=0; i<4; i++)
	  uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
367 368 369 370

        found = 1;
        break;
      }
371

372
      ind++;
373 374
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
  
375 376
    if (found == 0) {
      exit_fun("Can't find EUTRA band for frequency");
377
      return &UE_thread_synch_retval;
378
    }
379

380

381
    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);
382

383
    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
384 385
      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;
386 387 388
      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;
389
      else //FDD
390
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
391 392
    }

393
    sync_mode = pbch;
394

395
  } else if  (UE->UE_scan == 1) {
396
    current_band=0;
397

398 399
    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;
400 401
      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;
402
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
403 404
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
	downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
405
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
406 407
    }
  }
408

409 410 411
  while (sync_var<0)     
    pthread_cond_wait(&sync_cond, &sync_mutex);   
  pthread_mutex_unlock(&sync_mutex);   
knopp's avatar
knopp committed
412

413
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");   
414

415 416 417
  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
418 419
  }

420
  while (oai_exit==0) {
421 422
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    while (UE->proc.instance_cnt_synch < 0)
423
      // the thread waits here most of the time
424
      pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
425 426
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
    
427
    switch (sync_mode) {
428
    case pss:
429 430
      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);
431
      current_offset += 20000000; // increase by 20 MHz
432
      
433
      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
434
	current_band++;
laurent's avatar
laurent committed
435 436
                current_offset=0;
            }
437

laurent's avatar
laurent committed
438 439 440 441
            if (current_band==bands_to_scan.nbands) {
                current_band=0;
                oai_exit=1;
            }
442

laurent's avatar
laurent committed
443 444 445
            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;
446

laurent's avatar
laurent committed
447 448 449 450 451 452
                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;
                }
453
	    }
454

455
	    break;
456
 
457
    case pbch:
458

Cedric Roux's avatar
Cedric Roux committed
459
#if DISABLE_LOG_X
460
            printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
Cedric Roux's avatar
Cedric Roux committed
461 462 463
#else
            LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
#endif
laurent's avatar
laurent committed
464 465 466 467 468 469 470 471 472 473 474
            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 );

475

laurent's avatar
laurent committed
476 477 478
                    // 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;
479
			if (UE->UE_scan_carrier == 1) {
laurent's avatar
laurent committed
480
                        if (freq_offset >= 0)
481
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
482
                        else
483
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
484 485
                        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
486 487 488
                        downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
                        freq_offset=0;
                    }
489
	  }
490

laurent's avatar
laurent committed
491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 512 513 514 515 516 517
                    // 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;
                    }
518

laurent's avatar
laurent committed
519 520
                    UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
                    //UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
521
                    //UE->rfdevice.trx_stop_func(&UE->rfdevice);
laurent's avatar
laurent committed
522 523
                    sleep(1);
                    init_frame_parms(&UE->frame_parms,1);
524
                    /*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
laurent's avatar
laurent committed
525 526
                        LOG_E(HW,"Could not start the device\n");
                        oai_exit=1;
527
                    }*/
528 529 530 531

		if (UE->UE_scan_carrier == 1) {

		  UE->UE_scan_carrier = 0;
laurent's avatar
laurent committed
532
                } else {
laurent's avatar
laurent committed
533
                    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
534
                    UE->is_synchronized = 1;
laurent's avatar
laurent committed
535
                    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552

                    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
553
                            AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
554
                            UE->is_synchronized = 0;
laurent's avatar
laurent committed
555 556
                            AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

laurent's avatar
laurent committed
557 558 559 560 561 562 563
                        }
                    }
                }
            } else {
                // initial sync failed
                // calculate new offset and try again
                if (UE->UE_scan_carrier == 1) {
laurent's avatar
laurent committed
564
                    if (freq_offset >= 0)
laurent's avatar
laurent committed
565
                        freq_offset += 100;
laurent's avatar
laurent committed
566
                    freq_offset *= -1;
laurent's avatar
laurent committed
567 568 569 570 571 572 573 574 575 576 577 578 579

                    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);
                        }
580
                        AssertFatal(1==0,"No cell synchronization found, abandoning");
laurent's avatar
laurent committed
581 582 583
                        return &UE_thread_synch_retval; // not reached
                    }
                }
Cedric Roux's avatar
Cedric Roux committed
584
#if DISABLE_LOG_X
585
                printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
laurent's avatar
laurent committed
586 587 588 589
                       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
590 591 592 593 594 595 596
#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
597 598 599 600 601

                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
602
                    if (UE->UE_scan_carrier==1)
laurent's avatar
laurent committed
603 604 605 606 607 608 609 610 611
                        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;
        }
612

laurent's avatar
laurent committed
613
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
614 615
        // indicate readiness
        UE->proc.instance_cnt_synch--;
laurent's avatar
laurent committed
616
        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
617

laurent's avatar
laurent committed
618 619
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
    }  // while !oai_exit
620

laurent's avatar
laurent committed
621
    return &UE_thread_synch_retval;
622 623
}

624
/*!
625
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
626
 * This thread performs the phy_procedures_UE_RX() on every received slot.
laurent's avatar
laurent committed
627
 * then, if TX is enabled it performs TX for n+4.
628 629 630
 * \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.
 */
631

laurent's avatar
laurent committed
632 633
static void *UE_thread_rxn_txnp4(void *arg) {
    static __thread int UE_thread_rxtx_retval;
634 635 636
    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
637 638
    int ret;

639
    proc->instance_cnt_rxtx=-1;
laurent's avatar
laurent committed
640 641
    proc->subframe_rx=proc->sub_frame_start;

642 643
    char threadname[256];
    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
laurent's avatar
laurent committed
644 645
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
646

Bilel's avatar
Bilel committed
647 648 649 650 651
    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 )
652
        CPU_SET(threads.three, &cpuset);
Bilel's avatar
Bilel committed
653
            //CPU_SET(threads.three, &cpuset);
laurent's avatar
laurent committed
654
    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
655
                threadname);
laurent's avatar
laurent committed
656 657

    while (!oai_exit) {
658 659 660 661 662 663 664 665 666 667 668 669
        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
670

laurent's avatar
laurent committed
671 672 673 674
        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
675

676 677 678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704 705 706 707 708 709 710 711 712 713 714 715 716 717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746 747 748 749 750 751 752 753 754 755 756 757 758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791
        // 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",
                      threadname,
                      UE->frame_parms.tdd_config,
                      (sf_type==SF_DL? "SF_DL" :
                       (sf_type==SF_UL? "SF_UL" :
                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
            } else {
                LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
                      threadname,
                      (UE->frame_parms.frame_type==FDD? "FDD":
                       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
                      (sf_type==SF_DL? "SF_DL" :
                       (sf_type==SF_UL? "SF_UL" :
                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
            }
#ifdef UE_SLOT_PARALLELISATION
            phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#else
            phy_procedures_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#endif
        }

#if UE_TIMING_TRACE
        start_meas(&UE->generic_stat);
#endif
        if (UE->mac_enabled==1) {

            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*/);
            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 );
            }
        }
#if UE_TIMING_TRACE
        stop_meas(&UE->generic_stat);
#endif


        // Prepare the future Tx data

        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
	    (UE->frame_parms.frame_type == FDD) )
            if (UE->mode != loop_through_memory)
                phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);



        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);
        updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");

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

// thread finished
    free(arg);
    return &UE_thread_rxtx_retval;
}





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

static void *UE_phy_stub_thread_rxn_txnp4(void *arg) {
	module_id_t Mod_id = 0;
    static __thread int UE_thread_rxtx_retval;
    struct rx_tx_thread_data *rtd = arg;
    UE_rxtx_proc_t *proc = rtd->proc;
    PHY_VARS_UE    *UE   = rtd->UE;
    int ret;
792
    double t_diff;
793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816

    // 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.

    //proc->instance_cnt_rxtx=-1;

    phy_stub_ticking->ticking_var = -1;
    proc->subframe_rx=proc->sub_frame_start;

    char threadname[256];
    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);

    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 )
        CPU_SET(threads.three, &cpuset);
            //CPU_SET(threads.three, &cpuset);
    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
                threadname);
817
    wait_sync("UE_phy_stub_thread_rxn_txnp4");
818 819

    while (!oai_exit) {
820

821
        if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
822
          LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
823 824 825 826 827 828 829
          exit_fun("nothing to add");
        }
        while (phy_stub_ticking->ticking_var < 0) {
          // most of the time, the thread is waiting here
          //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx );
          pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
        }
830
        phy_stub_ticking->ticking_var--;
831
        if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
832
          LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
833 834
          exit_fun("nothing to add");
        }
835 836
        LOG_I(MAC," Panos-D [UE_phy_stub_thread_rxn_txnp4 1] Frame: %d, Subframe: %d \n" "\n" "\n", timer_frame, timer_subframe);

837 838 839

        proc->subframe_rx=timer_subframe;
        proc->frame_rx = timer_frame;
840
        proc->subframe_tx=(timer_subframe+2)%10;
841 842 843
        proc->frame_tx = proc->frame_rx + (proc->subframe_rx>7?1:0);
        //oai_subframe_ind(proc->frame_rx, proc->subframe_rx);

844 845 846 847 848 849 850 851 852


        // Panos: Guessing that the next 4 lines are not needed for the phy_stub mode.
        /*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
853 854 855 856 857 858 859 860
        // 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",
861
                      threadname,
laurent's avatar
laurent committed
862 863 864 865 866 867
                      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",
868
                      threadname,
laurent's avatar
laurent committed
869 870 871 872 873 874
                      (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
875

876 877


878
/*
879 880 881
#ifdef UE_SLOT_PARALLELISATION
            phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#else
882
*/
883 884 885 886
			// 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.

887
            // Panos: is this the right place to call oai_subframe_indication to invoke p7 nfapi callbacks here?
888 889 890 891 892 893 894 895

            //oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
            //oai_subframe_ind(timer_frame, timer_subframe);

            //start_meas(&UE->timer_stats);
            //oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
            oai_subframe_ind(timer_frame, timer_subframe);
            //LOG_I( MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind \n");
896 897
            //printf("Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind \n");
            /*if(UE_mac_inst[Mod_id].tx_req!= NULL){
898
            	printf("Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind 2\n");
899
            	tx_req_UE_MAC(UE_mac_inst[Mod_id].tx_req);
900
            }*/
901
            if(UE_mac_inst[Mod_id].dl_config_req!= NULL) {
902
            	LOG_I( MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind 3 \n");
903
            	dl_config_req_UE_MAC(UE_mac_inst[Mod_id].dl_config_req);
904 905
            }
            if(UE_mac_inst[Mod_id].hi_dci0_req!= NULL){
906
            	LOG_I( MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind 4 \n");
907
            	hi_dci0_req_UE_MAC(UE_mac_inst[Mod_id].hi_dci0_req);
908
            }
909 910 911
            //stop_meas(&UE->timer_stats);
            //t_diff = get_time_meas_us(&UE->timer_stats);
            //LOG_E(MAC," Panos-D Absolute time: %f\n", t_diff);
912 913

//#endif
laurent's avatar
laurent committed
914
        }
Bilel's avatar
Bilel committed
915

Gabriel's avatar
Gabriel committed
916
#if UE_TIMING_TRACE
Bilel's avatar
Bilel committed
917
        start_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
918
#endif
laurent's avatar
laurent committed
919 920
        if (UE->mac_enabled==1) {

921 922 923 924 925 926 927 928
            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
929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947
            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
948
#if UE_TIMING_TRACE
Bilel's avatar
Bilel committed
949
        stop_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
950
#endif
Bilel's avatar
Bilel committed
951

952

laurent's avatar
laurent committed
953
        // Prepare the future Tx data
954

laurent's avatar
laurent committed
955
        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
956
	    (UE->frame_parms.frame_type == FDD) )
957
            if (UE->mode != loop_through_memory){
958 959 960
            	// 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.
961
            	if(UE_mac_inst[Mod_id].ul_config_req!= NULL){
962 963 964
            		ul_config_req_UE_MAC(UE_mac_inst[Mod_id].ul_config_req);
            		UL_indication(UL_INFO);
            	}
965 966
            }

967 968


969

970
        /*if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
laurent's avatar
laurent committed
971 972 973
                (UE->frame_parms.frame_type == TDD))
            if (UE->mode != loop_through_memory)
                phy_procedures_UE_S_TX(UE,0,0,no_relay);
974
        updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");*/
975

976 977
        //if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
        if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
978 979 980
          LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
          exit_fun("noting to add");
        }
981 982

        //proc->instance_cnt_rxtx--;
983

984 985
        //if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
        if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
986 987 988
          LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
          exit_fun("noting to add");
        }
989 990
    }

laurent's avatar
laurent committed
991
// thread finished
992
    free(arg);
laurent's avatar
laurent committed
993
    return &UE_thread_rxtx_retval;
994
}
995

996 997


998 999 1000
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
1001 1002
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
1003 1004 1005 1006
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
1007

1008 1009 1010
void *UE_thread(void *arg) {


1011
    PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
laurent's avatar
laurent committed
1012 1013 1014 1015 1016 1017
    //  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
1018
    int th_id;
1019

1020
    static uint8_t thread_idx = 0;
1021

laurent's avatar
laurent committed
1022 1023
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
1024 1025
    if ( threads.iq != -1 )
        CPU_SET(threads.iq, &cpuset);
laurent's avatar
laurent committed
1026
    init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
1027
                "UHD Threads");
1028 1029

#ifdef NAS_UE
laurent's avatar
laurent committed
1030 1031
    MessageDef *message_p;
    message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
1032
    itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
1033
#endif
1034

laurent's avatar
laurent committed
1035
    int sub_frame=-1;
1036
    //int cumulated_shift=0;
1037

1038

laurent's avatar
laurent committed
1039
    while (!oai_exit) {
1040
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
1041 1042 1043
        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
1044

laurent's avatar
laurent committed
1045
        if (is_synchronized == 0) {
laurent's avatar
laurent committed
1046 1047 1048
            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++)
1049
                    rxp[i] = (void*)&UE->common_vars.rxdata[i][0];
laurent's avatar
laurent committed
1050 1051 1052 1053 1054 1055 1056 1057

                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
1058
		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
1059 1060 1061 1062 1063 1064 1065
                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");
                }
1066
		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
1067
            } else {
Cedric Roux's avatar
Cedric Roux committed
1068
#if OAISIM
1069
              (void)dummy_rx; /* avoid gcc warnings */
Cedric Roux's avatar
Cedric Roux committed
1070 1071
              usleep(500);
#else
laurent's avatar
laurent committed
1072 1073 1074 1075
                // 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
1076
                    for (int sf=0; sf<10; sf++)
laurent's avatar
laurent committed
1077
                        //	    printf("Reading dummy sf %d\n",sf);
1078
                          UE->rfdevice.trx_read_func(&UE->rfdevice,
laurent's avatar
laurent committed
1079 1080 1081
                                              &timestamp,
                                              rxp,
                                              UE->frame_parms.samples_per_tti,
1082
                                              UE->frame_parms.nb_antennas_rx);
laurent's avatar
laurent committed
1083
                }
Cedric Roux's avatar
Cedric Roux committed
1084
#endif
1085
            }
1086

laurent's avatar
laurent committed
1087 1088 1089 1090 1091 1092 1093 1094 1095 1096
        } // 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,
1097
                                                               (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
1098 1099 1100 1101
                                                               UE->rx_offset,
                                                               UE->frame_parms.nb_antennas_rx),"");
                    }
                    UE->rx_offset=0;
1102
                    UE->time_sync_cell=0;
Bilel's avatar
Bilel committed
1103 1104 1105 1106 1107
                    //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
1108 1109 1110 1111 1112

                    // 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,
1113 1114
                                                            (void**)UE->common_vars.rxdata,
                                                            UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
laurent's avatar
laurent committed
1115 1116 1117 1118 1119 1120 1121 1122 1123
                                                            UE->frame_parms.nb_antennas_rx),"");
                    slot_fep(UE,0, 0, 0, 0, 0);
                } //UE->mode != loop_through_memory
                else
                    rt_sleep_ns