lte-ue.c 72.6 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
#include <inttypes.h>
51 52
//#include "openair2/PHY_INTERFACE/phy_stub_UE.h"

53 54 55 56 57 58 59 60

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

61

62 63
#include "T.h"

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

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

typedef enum {
72 73 74
  pss=0,
  pbch=1,
  si=2
75 76
} sync_mode_t;

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

85 86
void ue_stub_rx_handler(unsigned int, char *);

87 88
int32_t **rxdata;
int32_t **txdata;
89

90 91 92 93
int timer_subframe;
int timer_frame;
SF_ticking *phy_stub_ticking;

94
#define KHz (1000UL)
95
#define MHz (1000*KHz)
96 97

typedef struct eutra_band_s {
98 99 100 101 102 103
  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;
104 105 106
} eutra_band_t;

typedef struct band_info_s {
107 108
  int nbands;
  eutra_band_t band_info[100];
109 110 111 112
} band_info_t;

band_info_t bands_to_scan;

113
static const eutra_band_t eutra_bands[] = {
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 140 141 142
  { 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},
143 144
};

145 146


147

148 149 150 151
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

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

knopp's avatar
knopp committed
154 155 156
PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag)
157 158 159

{

knopp's avatar
knopp committed
160 161
  PHY_VARS_UE* ue;

162
  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
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));
166
  }
knopp's avatar
knopp committed
167 168
  else ue = PHY_vars_UE_g[UE_id][0];

169 170 171

  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
172 173 174

  // 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)
175 176 177 178 179 180
    {
      // initialize all signal buffers
      init_lte_ue_signal(ue,1,abstraction_flag);
      // intialize transport
      init_lte_ue_transport(ue,abstraction_flag);
    }
knopp's avatar
knopp committed
181 182

  return(ue);
183 184
}

knopp's avatar
knopp committed
185

186 187
char uecap_xer[1024];

188 189


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

laurent's avatar
laurent committed
192
#ifdef DEADLINE_SCHEDULER
193 194 195 196 197 198 199 200 201 202 203 204
  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,
		"[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
    LOG_I(HW,"[SCHED][eNB] %s deadline thread %lu started on CPU %d\n",
	  name, (unsigned long)gettid(), sched_getcpu());
  }
laurent's avatar
laurent committed
205
#else
206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221
  if (CPU_COUNT(cpuset) > 0)
    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");
  /* 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);
  }
  CPU_FREE(cset);
222 223
#endif

laurent's avatar
laurent committed
224
}
225

226
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction) {
227

knopp's avatar
knopp committed
228
  PHY_VARS_UE *UE;
229 230
  int         inst;
  int         ret;
knopp's avatar
knopp committed
231

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

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

knopp's avatar
knopp committed
238
  for (inst=0;inst<nb_inst;inst++) {
239

240
    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
knopp's avatar
knopp committed
241
    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
242 243
    // turn off timing control loop in UE
    PHY_vars_UE_g[inst][0]->no_timing_correction = timing_correction;
knopp's avatar
knopp committed
244

245
    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
246 247
    init_UE_threads(inst);
    UE = PHY_vars_UE_g[inst][0];
knopp's avatar
knopp committed
248

249 250 251 252 253
    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
254
    }
255
    UE->rfdevice.host_type = RAU_HOST;
knopp's avatar
knopp committed
256
    //    UE->rfdevice.type      = NONE_DEV;
257 258 259 260 261
    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), "");
262 263
  }

264
  printf("UE threads created by %ld\n", gettid());
265 266
#if 0
#if defined(ENABLE_USE_MME)
267
  extern volatile int start_UE;
268 269 270 271
  while (start_UE == 0) {
    sleep(1);
  }
#endif
272
#endif
273 274
}

275

276
void init_UE_stub(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface) {
277 278 279 280 281 282 283 284 285 286 287 288 289

  int         inst;

  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);
290 291 292 293
  }
  init_timer_thread();

  for (inst=0;inst<nb_inst;inst++) {
294 295 296 297 298 299

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

  printf("UE threads created \n");
300

301
  LOG_I(PHY,"Starting multicast link on %s\n",emul_iface);
302
  if(nfapi_mode !=3)
303
  multicast_link_start(ue_stub_rx_handler,0,emul_iface);
304 305


306

307 308 309 310 311
}




312 313
/*!
 * \brief This is the UE synchronize thread.
314
 * It performs band scanning and synchonization.
315 316 317
 * \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
318

319 320
static void *UE_thread_synch(void *arg)
{
321 322 323
  static int UE_thread_synch_retval;
  int i, hw_slot_offset;
  PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
324 325
  int current_band = 0;
  int current_offset = 0;
326
  sync_mode_t sync_mode = pbch;
327
  int CC_id = UE->CC_id;
328 329
  int ind;
  int found;
330
  int freq_offset=0;
331
  char threadname[128];
332 333 334

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

336
  cpu_set_t cpuset;
337
  CPU_ZERO(&cpuset);
338 339 340 341 342
  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);
343

344
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
345 346
  ind = 0;
  found = 0;
347 348


349 350
  if (UE->UE_scan == 0) {
    do  {
351
      current_band = eutra_bands[ind].band;
352
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
353

354
      if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) {
355 356
	for (i=0; i<4; i++)
	  uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
357 358 359 360

        found = 1;
        break;
      }
361

362
      ind++;
363
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
364

365
    if (found == 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
366
      LOG_E(PHY,"Can't find EUTRA band for frequency %d",UE->frame_parms.dl_CarrierFreq);
367
      exit_fun("Can't find EUTRA band for frequency");
368
      return &UE_thread_synch_retval;
369
    }
370

371

372
    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);
373

374
    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
375 376
      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;
377
      openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
378
      if (uplink_frequency_offset[CC_id][i] != 0) //
379
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
380
      else //FDD
381
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
382 383
    }

384
    sync_mode = pbch;
385

386
  } else if  (UE->UE_scan == 1) {
387
    current_band=0;
388

389 390
    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;
391 392
      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;
393
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
394 395
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
	downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
396
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
397 398
    }
  }
399

400 401 402
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
  pthread_mutex_unlock(&sync_mutex);
knopp's avatar
knopp committed
403

404
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");
405

406 407 408
  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
409 410
  }

411
  while (oai_exit==0) {
412 413
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    while (UE->proc.instance_cnt_synch < 0)
414
      // the thread waits here most of the time
415
      pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
416
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
417

418
    switch (sync_mode) {
419
    case pss:
420 421
      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);
422
      current_offset += 20000000; // increase by 20 MHz
423

424
      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
425
	current_band++;
426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444
	current_offset=0;
      }

      if (current_band==bands_to_scan.nbands) {
	current_band=0;
	oai_exit=1;
      }

      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;

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

446
      break;
447

448
    case pbch:
449

Cedric Roux's avatar
Cedric Roux committed
450
#if DISABLE_LOG_X
451
      printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
Cedric Roux's avatar
Cedric Roux committed
452
#else
453
      LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
Cedric Roux's avatar
Cedric Roux committed
454
#endif
455 456 457 458 459 460 461 462 463 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478
      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 );


	// rerun with new cell parameters and frequency-offset
	for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
	  openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
	  if (UE->UE_scan_carrier == 1) {
	    if (freq_offset >= 0)
	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
	    else
	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
	    openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
	      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i]+uplink_frequency_offset[CC_id][i];
	    downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
	    freq_offset=0;
479
	  }
480 481 482 483 484 485 486 487 488 489 490 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 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546
	}

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

	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
	//UE->rfdevice.trx_set_gains_func(&openair0,&openair0_cfg[0]);
	//UE->rfdevice.trx_stop_func(&UE->rfdevice);
	sleep(1);
	init_frame_parms(&UE->frame_parms,1);
	/*if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
	  LOG_E(HW,"Could not start the device\n");
	  oai_exit=1;
	  }*/

	if (UE->UE_scan_carrier == 1) {

	  UE->UE_scan_carrier = 0;
	} else {
	  AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
	  UE->is_synchronized = 1;
	  AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

	  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 {
	      AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
	      UE->is_synchronized = 0;
	      AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
547

548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574
	    }
	  }
	}
      } else {
	// initial sync failed
	// calculate new offset and try again
	if (UE->UE_scan_carrier == 1) {
	  if (freq_offset >= 0)
	    freq_offset += 100;
	  freq_offset *= -1;

	  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);
	    }
	    AssertFatal(1==0,"No cell synchronization found, abandoning");
	    return &UE_thread_synch_retval; // not reached
	  }
	}
Cedric Roux's avatar
Cedric Roux committed
575
#if DISABLE_LOG_X
576 577 578 579 580
	printf("[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 );
Cedric Roux's avatar
Cedric Roux committed
581
#else
582 583 584 585 586
	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 );
Cedric Roux's avatar
Cedric Roux committed
587
#endif
laurent's avatar
laurent committed
588

589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608 609 610 611 612
	for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
	  openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+freq_offset;
	  openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i]+freq_offset;
	  openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
	  if (UE->UE_scan_carrier==1)
	    openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
	}
	UE->rfdevice.trx_set_freq_func(&UE->rfdevice,&openair0_cfg[0],0);
      }// initial_sync=0
      break;
    case si:
    default:
      break;
    }

    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    // indicate readiness
    UE->proc.instance_cnt_synch--;
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

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

  return &UE_thread_synch_retval;
613 614
}

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

laurent's avatar
laurent committed
623
static void *UE_thread_rxn_txnp4(void *arg) {
624 625 626 627 628 629 630 631 632 633 634 635 636
  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;

  proc->instance_cnt_rxtx=-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);
laurent's avatar
laurent committed
637

638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676 677 678 679 680 681 682 683 684 685 686 687 688
  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);

  while (!oai_exit) {
    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");
    }

    initRefTimes(t2);
    initRefTimes(t3);
    pickTime(current);
    updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");

    // 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"))));
      }
689
#ifdef UE_SLOT_PARALLELISATION
690
      phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
691
#else
692
      phy_procedures_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
693
#endif
694
    }
695 696

#if UE_TIMING_TRACE
697
    start_meas(&UE->generic_stat);
698
#endif
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
    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 );
      }
    }
728
#if UE_TIMING_TRACE
729
    stop_meas(&UE->generic_stat);
730 731 732
#endif


733
    // Prepare the future Tx data
734

735 736 737 738
    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);
739 740 741



742 743 744 745 746
    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)");
747

748 749 750
    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");
751
    }
752 753 754 755 756 757
    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");
    }
  }
758

759 760 761
  // thread finished
  free(arg);
  return &UE_thread_rxtx_retval;
762 763 764 765
}



766
unsigned int emulator_absSF;
767

768 769 770 771 772
void ue_stub_rx_handler(unsigned int num_bytes, char *rx_buffer) {

  PHY_VARS_UE *UE;
  UE = PHY_vars_UE_g[0][0];

knopp's avatar
knopp committed
773 774
  UE_tport_t *pdu = (UE_tport_t*)rx_buffer;
  SLSCH_t *slsch = (SLSCH_t*)&pdu->slsch;
775
  SLDCH_t *sldch = (SLDCH_t*)&pdu->sldch;
776

777 778 779 780 781 782
  switch (((UE_tport_header_t*)rx_buffer)->packet_type) {
  case TTI_SYNC:
    emulator_absSF = ((UE_tport_header_t*)rx_buffer)->absSF;
    wakeup_thread(&UE->timer_mutex,&UE->timer_cond,&UE->instance_cnt_timer,"timer_thread");
    break;
  case SLSCH:
783 784


knopp's avatar
knopp committed
785 786 787 788 789 790 791
    LOG_I(PHY,"Emulator SFN.SF %d.%d, Got SLSCH packet\n",emulator_absSF/10,emulator_absSF%10);
    LOG_I(PHY,"Received %d bytes on UE-UE link for SFN.SF %d.%d, sending SLSCH payload (%d bytes) to MAC\n",num_bytes,
	  pdu->header.absSF/10,pdu->header.absSF%10,
	  slsch->payload_length);
    printf("SLSCH:");
    for (int i=0;i<sizeof(SLSCH_t);i++) printf("%x ",((uint8_t*)slsch)[i]);
    printf("\n");
792

knopp's avatar
knopp committed
793 794 795 796 797 798
    ue_send_sl_sdu(0,
		   0,
		   pdu->header.absSF/10,
		   pdu->header.absSF%10,
		   pdu->payload,
		   slsch->payload_length,
Tien-Thinh Nguyen's avatar
Tien-Thinh Nguyen committed
799 800
		   0,
		   SL_DISCOVERY_FLAG_NO);
801
    break;
802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817

  case SLDCH:


    LOG_I(PHY,"Emulator SFN.SF %d.%d, Got SLDCH packet\n",emulator_absSF/10,emulator_absSF%10);
    LOG_I(PHY,"Received %d bytes on UE-UE link for SFN.SF %d.%d, sending SLDCH payload (%d bytes) to MAC\n",num_bytes,
          pdu->header.absSF/10,pdu->header.absSF%10,
          sldch->payload_length);
    printf("SLDCH:");
    for (int i=0;i<sizeof(SLDCH_t);i++) printf("%x ",((uint8_t*)sldch)[i]);
    printf("\n");

    ue_send_sl_sdu(0,
                   0,
                   pdu->header.absSF/10,
                   pdu->header.absSF%10,
818
                   sldch->payload,
819 820 821 822 823
                   sldch->payload_length,
                   0,
                   SL_DISCOVERY_FLAG_YES);
    break;

824 825
  }
}
826 827 828 829 830 831 832 833 834 835

/*!
 * \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) {
matzakos's avatar
matzakos committed
836

837 838 839
	thread_top_init("UE_phy_stub_thread_rxn_txnp4",1,870000L,1000000L,1000000L);

	module_id_t Mod_id = 0;
840 841 842 843 844
  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;
845
  //  double t_diff;
846

847 848
  char threadname[256];
  sprintf(threadname,"UE_%d_proc", UE->Mod_id);
849

850 851 852
  // 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.
853

854
  //proc->instance_cnt_rxtx=-1;
855

856 857
  phy_stub_ticking->ticking_var = -1;
  proc->subframe_rx=proc->sub_frame_start;
858

859 860 861
  //PANOS: CAREFUL HERE!
  wait_sync("UE_phy_stub_thread_rxn_txnp4");

862
  while (!oai_exit) {
863

864
    if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
865
      LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
866 867 868 869
      exit_fun("nothing to add");
    }
    while (phy_stub_ticking->ticking_var < 0) {
      // most of the time, the thread is waiting here
870 871
      //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
      LOG_D(MAC,"Waiting for ticking_var\n",phy_stub_ticking->ticking_var);
872 873
      pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
    }
874
    phy_stub_ticking->ticking_var--;
875
    if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
876
      LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
877 878
      exit_fun("nothing to add");
    }
879 880
    LOG_D(MAC," Panos-D [UE_phy_stub_thread_rxn_txnp4 1] Frame: %d, Subframe: %d \n" "\n" "\n", timer_frame, timer_subframe);

881 882 883

    proc->subframe_rx=timer_subframe;
    proc->frame_rx = timer_frame;
884 885
    proc->subframe_tx=(timer_subframe+4)%10;
    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
886 887
    //oai_subframe_ind(proc->frame_rx, proc->subframe_rx);

888 889 890 891 892 893 894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911 912 913 914 915 916 917 918 919


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


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

920

921
      phy_procedures_UE_SL_RX(UE,proc);
922

923 924 925 926 927 928 929 930 931 932
      /*
	#ifdef UE_SLOT_PARALLELISATION
	phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
	#else
      */
      // 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.

      // Panos: is this the right place to call oai_subframe_indication to invoke p7 nfapi callbacks here?
933 934 935 936 937 938 939 940

      //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");
941 942 943 944 945 946
      //printf("Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind \n");
      /*if(UE_mac_inst[Mod_id].tx_req!= NULL){
	printf("Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind 2\n");
	tx_req_UE_MAC(UE_mac_inst[Mod_id].tx_req);
	}*/
      if(UE_mac_inst[Mod_id].dl_config_req!= NULL) {
947
	//LOG_I( MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind 3 \n");
948 949
	dl_config_req_UE_MAC(UE_mac_inst[Mod_id].dl_config_req);
      }
950 951 952 953 954 955 956 957 958 959
      //if(UE_mac_inst[Mod_id].hi_dci0_req!= NULL){
      if (UE_mac_inst[Mod_id].hi_dci0_req!=NULL && UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
    	  LOG_I( MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 after oai_subframe_ind 4 \n");
    	  hi_dci0_req_UE_MAC(UE_mac_inst[Mod_id].hi_dci0_req);
    	  //if(UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
    		  free(UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list);
    		  UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL;
    	  //}
    	  free(UE_mac_inst[Mod_id].hi_dci0_req);
    	  UE_mac_inst[Mod_id].hi_dci0_req = NULL;
960
      }
961 962 963 964 965

      else if(UE_mac_inst[Mod_id].hi_dci0_req!=NULL){
      		free(UE_mac_inst[Mod_id].hi_dci0_req);
      		UE_mac_inst[Mod_id].hi_dci0_req = NULL;
      	}
966 967 968
      //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);
969
      if (nfapi_mode != 3)
970 971 972
      phy_procedures_UE_SL_TX(UE,proc);
      //#endif
    }
Bilel's avatar
Bilel committed
973

974
//>>>>>>> Stashed changes
975

Gabriel's avatar
Gabriel committed
976
#if UE_TIMING_TRACE
977
    start_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
978
#endif
979 980 981 982 983 984 985 986 987 988 989 990 991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007
    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 );
      }
    }
Gabriel's avatar
Gabriel committed
1008
#if UE_TIMING_TRACE
1009
    stop_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
1010
#endif
Bilel's avatar
Bilel committed
1011

1012

1013
    // Prepare the future Tx data
1014

1015 1016 1017 1018 1019
    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
	(UE->frame_parms.frame_type == FDD) )
      if (UE->mode != loop_through_memory){

	if ((UE_mac_inst[Mod_id].UE_mode[0] == PRACH) ) {
1020
	  //LOG_D(MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 before RACH \n");
1021 1022 1023 1024

	  // check if we have PRACH opportunity

	  if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx)) {
1025
	    //LOG_I(MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 before RACH 2 \n");
1026 1027
	    PRACH_RESOURCES_t *prach_resources = ue_get_rach(Mod_id, 0, proc->frame_tx, 0, proc->subframe_tx);
	    if(prach_resources!=NULL) {
1028
	      //LOG_I(MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 before RACH 3 \n");
1029 1030 1031 1032
	      fill_rach_indication_UE_MAC(Mod_id, proc->frame_tx ,proc->subframe_tx, UL_INFO, prach_resources->ra_PreambleIndex, prach_resources->ra_RNTI);
	      Msg1_transmitted(Mod_id, 0, proc->frame_tx, 0);
	      UE_mac_inst[Mod_id].UE_mode[0] = RA_RESPONSE;
	    }
1033

1034 1035 1036 1037 1038
	    //ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
	  }
	} // mode is PRACH
	// 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).
1039 1040
	// Generate UL_indications which correspond to UL traffic.
	if(UE_mac_inst[Mod_id].ul_config_req!= NULL && UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
1041
		//LOG_I(MAC, "Panos-D: UE_phy_stub_thread_rxn_txnp4 ul_config_req is not NULL \n");
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052 1053 1054
		ul_config_req_UE_MAC(UE_mac_inst[Mod_id].ul_config_req, timer_frame, timer_subframe);
		//ul_config_req_UE_MAC(UE_mac_inst[Mod_id].ul_config_req, proc->frame_tx, proc->subframe_tx);
		if(UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
			free(UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.ul_config_pdu_list);
			UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.ul_config_pdu_list = NULL;
		}
		free(UE_mac_inst[Mod_id].ul_config_req);
		UE_mac_inst[Mod_id].ul_config_req = NULL;
		//UL_indication(UL_INFO);
	}
	else if(UE_mac_inst[Mod_id].ul_config_req!=NULL){
		free(UE_mac_inst[Mod_id].ul_config_req);
		UE_mac_inst[Mod_id].ul_config_req = NULL;
1055 1056
	}
      }
1057

1058
    phy_procedures_UE_SL_RX(UE,proc);
1059

1060

1061 1062 1063 1064 1065
    /*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)");*/
1066

1067
    //if (pthread_mutex_lock(&proc->mutex_rxtx) != 0) {
1068
    /*if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
1069 1070 1071
      LOG_E( PHY, "[SCHED][UE] error locking mutex for UE RXTX\n" );
      exit_fun("noting to add");
    }
1072

1073
    //proc->instance_cnt_rxtx--;
1074

1075 1076 1077 1078
    //if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
    if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
      exit_fun("noting to add");
1079
    }*/
1080 1081 1082 1083
  }
  // thread finished
  free(arg);
  return &UE_thread_rxtx_retval;
1084
}
1085

1086 1087


1088 1089 1090
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
1091 1092
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
1093 1094 1095 1096
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
1097

1098 1099 1100
void *UE_thread(void *arg) {


1101 1102 1103 1104 1105 1106 1107 1108
  PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
  //  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;
  int th_id;
1109

1110
  static uint8_t thread_idx = 0;
1111

1112 1113 1114 1115 1116 1117
  cpu_set_t cpuset;
  CPU_ZERO(&cpuset);
  if ( threads.iq != -1 )
    CPU_SET(threads.iq, &cpuset);
  init_thread(100000, 500000, FIFO_PRIORITY, &cpuset,
	      "UHD Threads");
1118 1119

#ifdef NAS_UE
1120 1121 1122
  MessageDef *message_p;
  message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
  itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
1123
#endif
1124

1125 1126
  int sub_frame=-1;
  //int cumulated_shift=0;
1127

1128

1129 1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141 1142 1143 1144 1145 1146 1147 1148 1149 1150 1151 1152 1153 1154 1155 1156 1157
  while (!oai_exit) {
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    int instance_cnt_synch = UE->proc.instance_cnt_synch;
    int is_synchronized    = UE->is_synchronized;
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

    if (is_synchronized == 0) {
      if (instance_cnt_synch < 0) {  // we can invoke the synch
	// grab 10 ms of signal and wakeup synch thread
	for (int i=0; i<UE->frame_parms.nb_antennas_rx; i++)
	  rxp[i] = (void*)&UE->common_vars.rxdata[i][0];

	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), "");
	AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
	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");
	}
	AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
      } else {
Cedric Roux's avatar
Cedric Roux committed
1158
#if OAISIM
1159 1160
	(void)dummy_rx; /* avoid gcc warnings */
	usleep(500);
Cedric Roux's avatar
Cedric Roux committed
1161
#else
1162 1163 1164 1165 1166 1167 1168 1169 1170 1171 1172 1173
	// 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];
	  for (int sf=0; sf<10; sf++)
	    //	    printf("Reading dummy sf %d\n",sf);
	    UE->rfdevice.trx_read_func(&UE->rfdevice,
				       &timestamp,
				       rxp,
				       UE->frame_parms.samples_per_tti,
				       UE->frame_parms.nb_antennas_rx);
	}
Cedric Roux's avatar
Cedric Roux committed
1174
#endif
1175 1176
	}

laurent's avatar
laurent committed
1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
        } // 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,
1187
                                                               (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
1188 1189 1190 1191
                                                               UE->rx_offset,
                                                               UE->frame_parms.nb_antennas_rx),"");
                    }
                    UE->rx_offset=0;
1192 <