lte-ue.c 45.7 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
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 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56
#include "PHY_INTERFACE/extern.h"

#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all

#include "PHY/extern.h"
#include "SCHED/extern.h"
#include "LAYER2/MAC/extern.h"
#include "LAYER2/MAC/proto.h"

#include "UTIL/LOG/log_extern.h"
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
#include "UTIL/OPT/opt.h"

57 58
#include "T.h"

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

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

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

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

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

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

typedef struct eutra_band_s {
laurent's avatar
laurent committed
82 83 84 85 86 87
    int16_t band;
    uint32_t ul_min;
    uint32_t ul_max;
    uint32_t dl_min;
    uint32_t dl_max;
    lte_frame_type_t frame_type;
88 89 90
} eutra_band_t;

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

band_info_t bands_to_scan;

97
static const eutra_band_t eutra_bands[] = {
laurent's avatar
laurent committed
98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126
    { 1, 1920    * MHz, 1980    * MHz, 2110    * MHz, 2170    * MHz, FDD},
    { 2, 1850    * MHz, 1910    * MHz, 1930    * MHz, 1990    * MHz, FDD},
    { 3, 1710    * MHz, 1785    * MHz, 1805    * MHz, 1880    * MHz, FDD},
    { 4, 1710    * MHz, 1755    * MHz, 2110    * MHz, 2155    * MHz, FDD},
    { 5,  824    * MHz,  849    * MHz,  869    * MHz,  894    * MHz, FDD},
    { 6,  830    * MHz,  840    * MHz,  875    * MHz,  885    * MHz, FDD},
    { 7, 2500    * MHz, 2570    * MHz, 2620    * MHz, 2690    * MHz, FDD},
    { 8,  880    * MHz,  915    * MHz,  925    * MHz,  960    * MHz, FDD},
    { 9, 1749900 * KHz, 1784900 * KHz, 1844900 * KHz, 1879900 * KHz, FDD},
    {10, 1710    * MHz, 1770    * MHz, 2110    * MHz, 2170    * MHz, FDD},
    {11, 1427900 * KHz, 1452900 * KHz, 1475900 * KHz, 1500900 * KHz, FDD},
    {12,  698    * MHz,  716    * MHz,  728    * MHz,  746    * MHz, FDD},
    {13,  777    * MHz,  787    * MHz,  746    * MHz,  756    * MHz, FDD},
    {14,  788    * MHz,  798    * MHz,  758    * MHz,  768    * MHz, FDD},
    {17,  704    * MHz,  716    * MHz,  734    * MHz,  746    * MHz, FDD},
    {20,  832    * MHz,  862    * MHz,  791    * MHz,  821    * MHz, FDD},
    {22, 3510    * MHz, 3590    * MHz, 3410    * MHz, 3490    * MHz, FDD},
    {33, 1900    * MHz, 1920    * MHz, 1900    * MHz, 1920    * MHz, TDD},
    {34, 2010    * MHz, 2025    * MHz, 2010    * MHz, 2025    * MHz, TDD},
    {35, 1850    * MHz, 1910    * MHz, 1850    * MHz, 1910    * MHz, TDD},
    {36, 1930    * MHz, 1990    * MHz, 1930    * MHz, 1990    * MHz, TDD},
    {37, 1910    * MHz, 1930    * MHz, 1910    * MHz, 1930    * MHz, TDD},
    {38, 2570    * MHz, 2620    * MHz, 2570    * MHz, 2630    * MHz, TDD},
    {39, 1880    * MHz, 1920    * MHz, 1880    * MHz, 1920    * MHz, TDD},
    {40, 2300    * MHz, 2400    * MHz, 2300    * MHz, 2400    * MHz, TDD},
    {41, 2496    * MHz, 2690    * MHz, 2496    * MHz, 2690    * MHz, TDD},
    {42, 3400    * MHz, 3600    * MHz, 3400    * MHz, 3600    * MHz, TDD},
    {43, 3600    * MHz, 3800    * MHz, 3600    * MHz, 3800    * MHz, TDD},
    {44, 703    * MHz, 803    * MHz, 703    * MHz, 803    * MHz, TDD},
127 128
};

129 130


131

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

136
void phy_init_lte_ue_transport(PHY_VARS_UE *ue,int absraction_flag);
137

138 139 140
PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag)
141 142 143

{

144 145
  PHY_VARS_UE* ue;

146
  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
147 148 149 150 151 152
    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];

153 154 155

  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
156 157 158 159 160 161
  // initialize all signal buffers
  init_lte_ue_signal(ue,1,abstraction_flag);
  // intialize transport
  init_lte_ue_transport(ue,abstraction_flag);

  return(ue);
162 163
}

164

165 166
char uecap_xer[1024];

167 168


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

laurent's avatar
laurent committed
171 172 173 174 175 176 177 178 179
#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,
180
                    "[SCHED] %s thread: sched_setattr failed %s \n", name, strerror(errno));
181 182
        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
183
    }
laurent's avatar
laurent committed
184
#else
185
    if (CPU_COUNT(cpuset) > 0)
laurent's avatar
laurent committed
186 187 188 189 190
        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");
191 192 193 194 195 196 197 198
    /* 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);
199
    }
200
    CPU_FREE(cset);
201 202
#endif

laurent's avatar
laurent committed
203
}
204

205
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction) {
206

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

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

219
    LOG_I(PHY,"Initializing memory for UE instance %d (%p)\n",inst,PHY_vars_UE_g[inst]);
220
    PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
221 222
    // turn off timing control loop in UE
    PHY_vars_UE_g[inst][0]->no_timing_correction = timing_correction;
223

224
    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
225 226
    init_UE_threads(inst);
    UE = PHY_vars_UE_g[inst][0];
knopp's avatar
knopp committed
227

228 229 230 231 232
    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
233
    }
234
    UE->rfdevice.host_type = RAU_HOST;
knopp's avatar
knopp committed
235
    //    UE->rfdevice.type      = NONE_DEV;
236 237 238 239 240
    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), "");
241 242
  }

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

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

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

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

278
   cpu_set_t cpuset;
279
  CPU_ZERO(&cpuset);
280 281 282 283 284
  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);
285
  
286
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
287 288
  ind = 0;
  found = 0;
289 290


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

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

        found = 1;
        break;
      }
303

304
      ind++;
305 306
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
  
307
    if (found == 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
308
      LOG_E(PHY,"Can't find EUTRA band for frequency %d",UE->frame_parms.dl_CarrierFreq);
309
      exit_fun("Can't find EUTRA band for frequency");
310
      return &UE_thread_synch_retval;
311
    }
312

313

314
    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);
315

316
    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
317 318
      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;
319 320 321
      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;
322
      else //FDD
323
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
324 325
    }

326
    sync_mode = pbch;
327

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

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

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

346
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");   
347

348 349 350
  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
351 352
  }

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

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

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

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

388
	    break;
389
 
390
    case pbch:
391

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

408

laurent's avatar
laurent committed
409 410 411
                    // rerun with new cell parameters and frequency-offset
                    for (i=0; i<openair0_cfg[UE->rf_map.card].rx_num_channels; i++) {
                        openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;//-USRP_GAIN_OFFSET;
412
			if (UE->UE_scan_carrier == 1) {
laurent's avatar
laurent committed
413
                        if (freq_offset >= 0)
414
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] += abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
415
                        else
416
                            openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] -= abs(UE->common_vars.freq_offset);
laurent's avatar
laurent committed
417 418
                        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
419 420 421
                        downlink_frequency[CC_id][i] = openair0_cfg[CC_id].rx_freq[i];
                        freq_offset=0;
                    }
422
	  }
423

laurent's avatar
laurent committed
424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449 450
                    // 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;
                    }
451

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

		if (UE->UE_scan_carrier == 1) {

		  UE->UE_scan_carrier = 0;
laurent's avatar
laurent committed
465
                } else {
laurent's avatar
laurent committed
466
                    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
467
                    UE->is_synchronized = 1;
laurent's avatar
laurent committed
468
                    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485

                    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
486
                            AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
487
                            UE->is_synchronized = 0;
laurent's avatar
laurent committed
488 489
                            AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");

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

                    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);
                        }
513
                        AssertFatal(1==0,"No cell synchronization found, abandoning");
laurent's avatar
laurent committed
514 515 516
                        return &UE_thread_synch_retval; // not reached
                    }
                }
Cedric Roux's avatar
Cedric Roux committed
517
#if DISABLE_LOG_X
518
                printf("[initial_sync] trying carrier off %d Hz, rxgain %d (DL %u, UL %u)\n",
laurent's avatar
laurent committed
519 520 521 522
                       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
523 524 525 526 527 528 529
#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
530 531 532 533 534

                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
535
                    if (UE->UE_scan_carrier==1)
laurent's avatar
laurent committed
536 537 538 539 540 541 542 543 544
                        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;
        }
545

laurent's avatar
laurent committed
546
        AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
547 548
        // indicate readiness
        UE->proc.instance_cnt_synch--;
laurent's avatar
laurent committed
549
        AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
550

laurent's avatar
laurent committed
551 552
        VCD_SIGNAL_DUMPER_DUMP_FUNCTION_BY_NAME( VCD_SIGNAL_DUMPER_FUNCTIONS_UE_THREAD_SYNCH, 0 );
    }  // while !oai_exit
553

laurent's avatar
laurent committed
554
    return &UE_thread_synch_retval;
555 556
}

557
/*!
558
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
559
 * This thread performs the phy_procedures_UE_RX() on every received slot.
laurent's avatar
laurent committed
560
 * then, if TX is enabled it performs TX for n+4.
561 562 563
 * \param arg is a pointer to a \ref PHY_VARS_UE structure.
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
564

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

572
    proc->instance_cnt_rxtx=-1;
laurent's avatar
laurent committed
573 574
    proc->subframe_rx=proc->sub_frame_start;

575 576
    char threadname[256];
    sprintf(threadname,"UE_%d_proc_%d", UE->Mod_id, proc->sub_frame_start);
laurent's avatar
laurent committed
577 578
    cpu_set_t cpuset;
    CPU_ZERO(&cpuset);
579

580 581 582 583 584
    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 )
585
        CPU_SET(threads.three, &cpuset);
586
            //CPU_SET(threads.three, &cpuset);
laurent's avatar
laurent committed
587
    init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
588
                threadname);
laurent's avatar
laurent committed
589 590

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

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

        // Process Rx data for one sub-frame
        lte_subframe_t sf_type = subframe_select( &UE->frame_parms, proc->subframe_rx);
        if ((sf_type == SF_DL) ||
                (UE->frame_parms.frame_type == FDD) ||
                (sf_type == SF_S)) {

            if (UE->frame_parms.frame_type == TDD) {
                LOG_D(PHY, "%s,TDD%d,%s: calling UE_RX\n",
617
                      threadname,
laurent's avatar
laurent committed
618 619 620 621 622 623
                      UE->frame_parms.tdd_config,
                      (sf_type==SF_DL? "SF_DL" :
                       (sf_type==SF_UL? "SF_UL" :
                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
            } else {
                LOG_D(PHY, "%s,%s,%s: calling UE_RX\n",
624
                      threadname,
laurent's avatar
laurent committed
625 626 627 628 629 630
                      (UE->frame_parms.frame_type==FDD? "FDD":
                       (UE->frame_parms.frame_type==TDD? "TDD":"UNKNOWN_DUPLEX_MODE")),
                      (sf_type==SF_DL? "SF_DL" :
                       (sf_type==SF_UL? "SF_UL" :
                        (sf_type==SF_S ? "SF_S"  : "UNKNOWN_SF_TYPE"))));
            }
631 632 633
#ifdef UE_SLOT_PARALLELISATION
            phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
#else
634
            phy_procedures_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
635
#endif
laurent's avatar
laurent committed
636
        }
Bilel's avatar
Bilel committed
637

Gabriel's avatar
Gabriel committed
638
#if UE_TIMING_TRACE
Bilel's avatar
Bilel committed
639
        start_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
640
#endif
laurent's avatar
laurent committed
641 642
        if (UE->mac_enabled==1) {

643 644 645 646 647 648 649 650
            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
651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
            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
670
#if UE_TIMING_TRACE
Bilel's avatar
Bilel committed
671
        stop_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
672
#endif
Bilel's avatar
Bilel committed
673

674

laurent's avatar
laurent committed
675
        // Prepare the future Tx data
676

laurent's avatar
laurent committed
677
        if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
678
	    (UE->frame_parms.frame_type == FDD) )
laurent's avatar
laurent committed
679 680
            if (UE->mode != loop_through_memory)
                phy_procedures_UE_TX(UE,proc,0,0,UE->mode,no_relay);
681 682


683

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

690 691 692 693 694 695 696 697 698
        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");
        }
699 700
    }

laurent's avatar
laurent committed
701
// thread finished
702
    free(arg);
laurent's avatar
laurent committed
703
    return &UE_thread_rxtx_retval;
704
}
705

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

void *UE_thread(void *arg) {


719
    PHY_VARS_UE *UE = (PHY_VARS_UE *) arg;
laurent's avatar
laurent committed
720 721 722 723 724 725
    //  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;
726
    int th_id;
727

728
    static uint8_t thread_idx = 0;
729

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

#ifdef NAS_UE
laurent's avatar
laurent committed
738 739
    MessageDef *message_p;
    message_p = itti_alloc_new_message(TASK_NAS_UE, INITIALIZE_MESSAGE);
740
    itti_send_msg_to_task (TASK_NAS_UE, UE->Mod_id + NB_eNB_INST, message_p);
741
#endif
742

laurent's avatar
laurent committed
743
    int sub_frame=-1;
744
    //int cumulated_shift=0;
745

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

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

                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
766
		AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
767 768 769 770 771 772 773
                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");
                }
774
		AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
laurent's avatar
laurent committed
775
            } else {
776
#if OAISIM
777
              (void)dummy_rx; /* avoid gcc warnings */
778 779
              usleep(500);
#else
laurent's avatar
laurent committed
780 781 782 783
                // 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
784
                    for (int sf=0; sf<10; sf++)
laurent's avatar
laurent committed
785
                        //	    printf("Reading dummy sf %d\n",sf);
786
                          UE->rfdevice.trx_read_func(&UE->rfdevice,
laurent's avatar
laurent committed
787 788 789
                                              &timestamp,
                                              rxp,
                                              UE->frame_parms.samples_per_tti,
790
                                              UE->frame_parms.nb_antennas_rx);
laurent's avatar
laurent committed
791
                }
792
#endif
793
            }
794

laurent's avatar
laurent committed
795 796 797 798 799 800 801 802 803 804
        } // 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,
805
                                                               (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
806 807 808 809
                                                               UE->rx_offset,
                                                               UE->frame_parms.nb_antennas_rx),"");
                    }
                    UE->rx_offset=0;
810
                    UE->time_sync_cell=0;
811 812 813 814 815
                    //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
816 817 818 819 820

                    // 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,
821 822
                                                            (void**)UE->common_vars.rxdata,
                                                            UE->frame_parms.ofdm_symbol_size+UE->frame_parms.nb_prefix_samples0,
laurent's avatar
laurent committed
823 824 825 826 827 828 829 830 831
                                                            UE->frame_parms.nb_antennas_rx),"");
                    slot_fep(UE,0, 0, 0, 0, 0);
                } //UE->mode != loop_through_memory
                else
                    rt_sleep_ns(1000*1000);

            } else {
                sub_frame++;
                sub_frame%=10;
832 833 834 835 836 837 838 839 840 841
                UE_rxtx_proc_t *proc = &UE->proc.proc_rxtx[thread_idx];
                // update thread index for received subframe
                UE->current_thread_id[sub_frame] = thread_idx;

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

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

laurent's avatar
laurent committed
842 843 844

                if (UE->mode != loop_through_memory) {
                    for (i=0; i<UE->frame_parms.nb_antennas_rx; i++)
Thomas Laurent's avatar
Thomas Laurent committed
845
                        rxp[i] = (void*)&UE->common_vars.rxdata[i][UE->frame_parms.ofdm_symbol_size+
846 847
                                 UE->frame_parms.nb_prefix_samples0+
                                 sub_frame*UE->frame_parms.samples_per_tti];
laurent's avatar
laurent committed
848 849 850 851 852 853 854 855
                    for (i=0; i<UE->frame_parms.nb_antennas_tx; i++)
                        txp[i] = (void*)&UE->common_vars.txdata[i][((sub_frame+2)%10)*UE->frame_parms.samples_per_tti];

                    int readBlockSize, writeBlockSize;
                    if (sub_frame<9) {
                        readBlockSize=UE->frame_parms.samples_per_tti;
                        writeBlockSize=UE->frame_parms.samples_per_tti;
                    } else {
856
                        // set TO compensation to zero
857

858
                        UE->rx_offset_diff = 0;
859

860
                        // compute TO compensation that should be applied for this frame
861 862 863 864

			if (UE->no_timing_correction == 0) {
			  if ( UE->rx_offset < 5*UE->frame_parms.samples_per_tti  &&
			       UE->rx_offset > 0 )
laurent's avatar
laurent committed
865
                            UE->rx_offset_diff = -1 ;
866 867
			  if ( UE->rx_offset > 5*UE->frame_parms.samples_per_tti &&
			       UE->rx_offset < 10*UE->frame_parms.samples_per_tti )
laurent's avatar
laurent committed
868
                            UE->rx_offset_diff = 1;
869
			}
laurent's avatar
laurent committed
870

871
                        LOG_D(PHY,"AbsSubframe %d.%d SET rx_off_diff to %d rx_offset %d \n",proc->frame_rx,sub_frame,UE->rx_offset_diff,UE->rx_offset);
laurent's avatar
laurent committed
872 873 874 875 876 877
                        readBlockSize=UE->frame_parms.samples_per_tti -
                                      UE->frame_parms.ofdm_symbol_size -
                                      UE->frame_parms.nb_prefix_samples0 -
                                      UE->rx_offset_diff;
                        writeBlockSize=UE->frame_parms.samples_per_tti -
                                       UE->rx_offset_diff;
laurent's avatar
laurent committed
878 879 880 881 882 883 884 885 886 887 888 889 890 891 892 893 894 895 896 897 898 899 900 901 902
                    }

                    AssertFatal(readBlockSize ==
                                UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                           &timestamp,
                                                           rxp,
                                                           readBlockSize,
                                                           UE->frame_parms.nb_antennas_rx),"");
                    AssertFatal( writeBlockSize ==
                                 UE->rfdevice.trx_write_func(&UE->rfdevice,
                                         timestamp+
                                         (2*UE->frame_parms.samples_per_tti) -
                                         UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0 -
                                         openair0_cfg[0].tx_sample_advance,
                                         txp,
                                         writeBlockSize,
                                         UE->frame_parms.nb_antennas_tx,
                                         1),"");
                    if( sub_frame==9) {
                        // read in first symbol of next frame and adjust for timing drift
                        int first_symbols=writeBlockSize-readBlockSize;
                        if ( first_symbols > 0 )
                            AssertFatal(first_symbols ==
                                        UE->rfdevice.trx_read_func(&UE->rfdevice,
                                                                   &timestamp1,
Thomas Laurent's avatar
Thomas Laurent committed
903
                                                                   (void**)UE->common_vars.rxdata,
laurent's avatar
laurent committed
904 905 906 907 908
                                                                   first_symbols,
                                                                   UE->frame_parms.nb_antennas_rx),"");
                        if ( first_symbols <0 )
                            LOG_E(PHY,"can't compensate: diff =%d\n", first_symbols);
                    }
909
                    pickTime(gotIQs);
laurent's avatar
laurent committed
910 911 912
                    // operate on thread sf mod 2
                    AssertFatal(pthread_mutex_lock(&proc->mutex_rxtx) ==0,"");
                    if(sub_frame == 0) {
913 914 915 916 917 918 919 920 921 922
                        //UE->proc.proc_rxtx[0].frame_rx++;
                        //UE->proc.proc_rxtx[1].frame_rx++;
                        for (th_id=0; th_id < RX_NB_TH; th_id++) {
                            UE->proc.proc_rxtx[th_id].frame_rx++;
                        }
                    }
                    //UE->proc.proc_rxtx[0].gotIQs=readTime(gotIQs);
                    //UE->proc.proc_rxtx[1].gotIQs=readTime(gotIQs);
                    for (th_id=0; th_id < RX_NB_TH; th_id++) {
                        UE->proc.proc_rxtx[th_id].gotIQs=readTime(gotIQs);
laurent's avatar
laurent committed
923 924 925 926 927 928 929 930
                    }
                    proc->subframe_rx=sub_frame;
                    proc->subframe_tx=(sub_frame+4)%10;
                    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>5?1:0);
                    proc->timestamp_tx = timestamp+
                                         (4*UE->frame_parms.samples_per_tti)-
                                         UE->frame_parms.ofdm_symbol_size-UE->frame_parms.nb_prefix_samples0;

931
                    proc->instance_cnt_rxtx++;
932
                    LOG_D( PHY, "[SCHED][UE %d] UE RX instance_cnt_rxtx %d subframe %d !!\n", UE->Mod_id, proc->instance_cnt_rxtx,proc->subframe_rx);
933 934 935 936 937 938 939 940 941 942 943
                    if (proc->instance_cnt_rxtx == 0) {
                      if (pthread_cond_signal(&proc->cond_rxtx) != 0) {
                        LOG_E( PHY, "[SCHED][UE %d] ERROR pthread_cond_signal for UE RX thread\n", UE->Mod_id);
                        exit_fun("nothing to add");
                      }
                    } else {
                      LOG_E( PHY, "[SCHED][UE %d] UE RX thread busy (IC %d)!!\n", UE->Mod_id, proc->instance_cnt_rxtx);
                      if (proc->instance_cnt_rxtx > 2)
                        exit_fun("instance_cnt_rxtx > 2");
                    }

laurent's avatar
laurent committed
944 945
                    AssertFatal (pthread_cond_signal(&proc->cond_rxtx) ==0 ,"");
                    AssertFatal(pthread_mutex_unlock(&proc->mutex_rxtx) ==0,"");
946 947 948 949
                    initRefTimes(t1);
                    initStaticTime(lastTime);
                    updateTimes(lastTime, &t1, 20000, "Delay between two IQ acquisitions (case 1)");
                    pickStaticTime(lastTime);
laurent's avatar
laurent committed
950 951 952 953 954 955 956 957 958 959

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

    } // while !oai_exit
    return NULL;
960 961
}

962 963 964
/*!
 * \brief Initialize the UE theads.
 * Creates the UE threads:
965 966
 * - UE_thread_rxtx0
 * - UE_thread_rxtx1
967
 * - UE_thread_synch
968 969 970 971
 * - UE_thread_fep_slot0
 * - UE_thread_fep_slot1
 * - UE_thread_dlsch_proc_slot0
 * - UE_thread_dlsch_proc_slot1
972 973
 * and the locking between them.
 */
974
void init_UE_threads(int inst) {
975
    struct rx_tx_thread_data *rtd;
976
    PHY_VARS_UE *UE;
977

978 979 980 981
    AssertFatal(PHY_vars_UE_g!=NULL,"PHY_vars_UE_g is NULL\n");
    AssertFatal(PHY_vars_UE_g[inst]!=NULL,"PHY_vars_UE_g[inst] is NULL\n");
    AssertFatal(PHY_vars_UE_g[inst][0]!=NULL,"PHY_vars_UE_g[inst][0] is NULL\n");
    UE = PHY_vars_UE_g[inst][0];
982

laurent's avatar
laurent committed
983 984
    pthread_attr_init (&UE->proc.attr_ue);
    pthread_attr_setstacksize(&UE->proc.attr_ue,8192);//5*PTHREAD_STACK_MIN);
985

986 987
    pthread_mutex_init(&UE->proc.mutex_synch,NULL);
    pthread_cond_init(&UE->proc.cond_synch,NULL);
988

laurent's avatar
laurent committed
989
    // the threads are not yet active, therefore access is allowed without locking
990
    int nb_threads=RX_NB_TH;
laurent's avatar
laurent committed
991
    for (int i=0; i<nb_threads; i++) {
992 993 994 995
        rtd = calloc(1, sizeof(struct rx_tx_thread_data));
        if (rtd == NULL) abort();
        rtd->UE = UE;
        rtd->proc = &UE->proc.proc_rxtx[i];
996

laurent's avatar
laurent committed
997 998 999 1000
        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_rxtx,NULL);
        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_rxtx,NULL);
        UE->proc.proc_rxtx[i].sub_frame_start=i;
        UE->proc.proc_rxtx[i].sub_frame_step=nb_threads;
1001
        printf("Init_UE_threads rtd %d proc %d nb_threads %d i %d\n",rtd->proc->sub_frame_start, UE->proc.proc_rxtx[i].sub_frame_start,nb_threads, i);
1002
        pthread_create(&UE->proc.proc_rxtx[i].pthread_rxtx, NULL, UE_thread_rxn_txnp4, rtd);
1003

fnabet's avatar
fnabet committed
1004
#ifdef UE_SLOT_PARALLELISATION
1005 1006 1007 1008 1009 1010 1011
        //pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot0_dl_processing,NULL);
        //pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot0_dl_processing,NULL);
        //pthread_create(&UE->proc.proc_rxtx[i].pthread_slot0_dl_processing,NULL,UE_thread_slot0_dl_processing, rtd);

        pthread_mutex_init(&UE->proc.proc_rxtx[i].mutex_slot1_dl_processing,NULL);
        pthread_cond_init(&UE->proc.proc_rxtx[i].cond_slot1_dl_processing,NULL);
        pthread_create(&UE->proc.proc_rxtx[i].pthread_slot1_dl_processing,NULL,UE_thread_slot1_dl_processing, rtd);
fnabet's avatar
fnabet committed
1012 1013
#endif

1014
    }
laurent's avatar
laurent committed
1015
    pthread_create(&UE->proc.pthread_synch,NULL,UE_thread_synch,(void*)UE);
1016 1017 1018
}


1019
#ifdef OPENAIR2
laurent's avatar
laurent committed
1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036 1037 1038 1039 1040 1041 1042 1043
void fill_ue_band_info(void) {

    UE_EUTRA_Capability_t *UE_EUTRA_Capability = UE_rrc_inst[0].UECap->UE_EUTRA_Capability;
    int i,j;

    bands_to_scan.nbands = UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.count;

    for (i=0; i<bands_to_scan.nbands; i++) {

        for (j=0; j<sizeof (eutra_bands) / sizeof (eutra_bands[0]); j++)
            if (eutra_bands[j].band == UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA) {
                memcpy(&bands_to_scan.band_info[i],
                       &eutra_bands[j],
                       sizeof(eutra_band_t));

                printf("Band %d (%lu) : DL %u..%u Hz, UL %u..%u Hz, Duplex %s \n",
                       bands_to_scan.band_info[i].band,
                       UE_EUTRA_Capability->rf_Parameters.supportedBandListEUTRA.list.array[i]->bandEUTRA,
                       bands_to_scan.band_info[i].dl_min,
                       bands_to_scan.band_info[i].dl_max,
                       bands_to_scan.band_info[i].ul_min,
                       bands_to_scan.band_info[i].ul_max,
                       (bands_to_scan.band_info[i].frame_type==FDD) ? "FDD" : "TDD");
                break;
1044
            }
1045 1046
    }
}
1047
#endif
1048

laurent's avatar
laurent committed
1049
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg) {
1050

laurent's avatar
laurent committed
1051 1052 1053
    int i, CC_id;
    LTE_DL_FRAME_PARMS *frame_parms;
    openair0_rf_map *rf_map;
1054

laurent's avatar
laurent committed
1055
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1056 1057 1058
      rf_map = &phy_vars_ue[CC_id]->rf_map;
      
      AssertFatal( phy_vars_ue[CC_id] !=0, "");
1059
      frame_parms = &(phy_vars_ue[CC_id]->frame_parms);
1060 1061 1062 1063 1064 1065 1066 1067 1068 1069 1070
      
      // replace RX signal buffers with mmaped HW versions
      rxdata = (int32_t**)malloc16( frame_parms->nb_antennas_rx*sizeof(int32_t*) );
      txdata = (int32_t**)malloc16( frame_parms->nb_antennas_tx*sizeof(int32_t*) );
      
      for (i=0; i<frame_parms->nb_antennas_rx; i++) {
	LOG_I(PHY, "Mapping UE CC_id %d, rx_ant %d, freq %u on card %d, chain %d\n",
	      CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
	free( phy_vars_ue[CC_id]->common_vars.rxdata[i] );
	rxdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
	phy_vars_ue[CC_id]->common_vars.rxdata[i] = rxdata[i]; // what about the "-N_TA_offset" ? // N_TA offset for TDD
1071
      }
1072 1073 1074 1075 1076 1077 1078 1079 1080 1081 1082 1083 1084
		
      for (i=0; i<frame_parms->nb_antennas_tx; i++) {
	LOG_I(PHY, "Mapping UE CC_id %d, tx_ant %d, freq %u on card %d, chain %d\n",
	      CC_id, i, downlink_frequency[CC_id][i], rf_map->card, rf_map->chain+i );
	free( phy_vars_ue[CC_id]->common_vars.txdata[i] );
	txdata[i] = (int32_t*)malloc16_clear( 307200*sizeof(int32_t) );
	phy_vars_ue[CC_id]->common_vars.txdata[i] = txdata[i];
      }
      
      // rxdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.rxdata[x]
      // txdata[x] points now to the same memory region as phy_vars_ue[CC_id]->common_vars.txdata[x]
      // be careful when releasing memory!
      // because no "release_ue_buffers"-function is available, at least rxdata and txdata memory will leak (only some bytes)
1085
    }
laurent's avatar
laurent committed
1086
    return 0;
1087
}
1088