lte-ue.c 79.9 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 37
#include "LAYER2/MAC/mac.h"
#include "RRC/LTE/rrc_extern.h"
38
#include "PHY_INTERFACE/phy_stub_UE.h"
39
#include "PHY_INTERFACE/phy_interface_extern.h"
40 41 42
#include "PHY/INIT/phy_init.h"
#include "PHY/MODULATION/modulation_UE.h"
#include "PHY/LTE_ESTIMATION/lte_estimation.h"
43 44 45 46

#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

47 48 49
#include "PHY/phy_extern_ue.h"
#include "LAYER2/MAC/mac_extern.h"
#include "LAYER2/MAC/mac_proto.h"
50 51 52
#include "SCHED_UE/sched_UE.h"
#include "PHY/LTE_UE_TRANSPORT/transport_proto_ue.h"

53
#include <inttypes.h>
54

55
#include "common/utils/LOG/log.h"
56 57 58
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
59
#include "common/utils/LOG/vcd_signal_dumper.h"
60
#include "UTIL/OPT/opt.h"
61 62
#include "lte-softmodem.h"
#include "common/config/config_userapi.h"
63 64
#include "T.h"

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

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

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

78
void init_UE_threads(int);
79 80
void init_UE_threads_stub(int);
void init_UE_single_thread_stub(int);
81
void *UE_thread(void *arg);
82
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction, int phy_test, int UE_scan, int UE_scan_carrier, runmode_t mode,int rxgain,int txpowermax,LTE_DL_FRAME_PARMS *fp);
83 84 85 86 87 88 89 90 91 92 93 94 95
void init_UE_stub(int nb_inst,int,int,char*);
void init_UE_stub_single_thread(int nb_inst,int,int,char*);
int init_timer_thread(void);
extern void oai_subframe_ind(uint16_t sfn, uint16_t sf);
extern void multicast_link_start(void (*rx_handlerP) (unsigned int, char *),
                          unsigned char _multicast_group, char *multicast_ifname);
extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
extern int oai_nfapi_crc_indication(nfapi_crc_indication_t *crc_ind);
extern int oai_nfapi_harq_indication(nfapi_harq_indication_t *harq_ind);
extern int oai_nfapi_sr_indication(nfapi_sr_indication_t *ind);
extern int oai_nfapi_rx_ind(nfapi_rx_indication_t *ind);
extern int multicast_link_write_sock(int groupP, char *dataP, uint32_t sizeP);

96
extern int simL1flag;
97
extern uint16_t sf_ahead;
98 99 100
//extern int tx_req_UE_MAC1();

void ue_stub_rx_handler(unsigned int, char *);
101

102 103
int32_t **rxdata;
int32_t **txdata;
104

105 106 107 108 109
int timer_subframe = 0;
int timer_frame = 0;
SF_ticking *phy_stub_ticking = NULL;
int next_ra_frame = 0;
module_id_t next_Mod_id = 0;
110

111
#define KHz (1000UL)
112
#define MHz (1000*KHz)
113 114

typedef struct eutra_band_s {
115 116 117 118 119 120
  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;
121 122 123
} eutra_band_t;

typedef struct band_info_s {
124 125
  int nbands;
  eutra_band_t band_info[100];
126 127 128 129
} band_info_t;

band_info_t bands_to_scan;

130
static const eutra_band_t eutra_bands[] = {
131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159
  { 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},
160 161
};

162

163
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
164

165 166 167 168
pthread_t                       main_ue_thread;
pthread_attr_t                  attr_UE_thread;
struct sched_param              sched_param_UE_thread;

169 170 171 172 173 174 175 176 177

void get_uethreads_params(void) {
  paramdef_t cmdline_threadsparams[] =CMDLINE_UETHREADSPARAMS_DESC;


  config_process_cmdline( cmdline_threadsparams,sizeof(cmdline_threadsparams)/sizeof(paramdef_t),NULL);
}


178
void phy_init_lte_ue_transport(PHY_VARS_UE *ue,int absraction_flag);
179

180 181 182
PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag)
183 184 185

{

186 187
  PHY_VARS_UE* ue = (PHY_VARS_UE *)malloc(sizeof(PHY_VARS_UE));
  memset(ue,0,sizeof(PHY_VARS_UE));
188

189
  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
190
    memcpy(&(ue->frame_parms), frame_parms, sizeof(LTE_DL_FRAME_PARMS));
191
  }
192

193
  ue->hw_timing_advance=get_softmodem_params()->hw_timing_advance;
194 195
  ue->Mod_id      = UE_id;
  ue->mac_enabled = 1;
196

197
  // In phy_stub_UE (MAC-to-MAC) mode these init functions don't need to get called. Is this correct?
198 199 200 201 202 203 204
  if (nfapi_mode!=3)
    {
      // initialize all signal buffers
      init_lte_ue_signal(ue,1,abstraction_flag);
      // intialize transport
      init_lte_ue_transport(ue,abstraction_flag);
    }
205 206

  return(ue);
207 208
}

209

210 211
char uecap_xer[1024];

212 213


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

laurent's avatar
laurent committed
216
#ifdef DEADLINE_SCHEDULER
217 218 219 220 221 222 223 224 225 226 227 228
  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
229
#else
230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245
  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);
246 247
#endif

laurent's avatar
laurent committed
248
}
249

250
void init_UE(int nb_inst,int eMBMS_active, int uecap_xer_in, int timing_correction, int phy_test, int UE_scan, int UE_scan_carrier, runmode_t mode,int rxgain,int txpowermax,LTE_DL_FRAME_PARMS *fp0) {
251

knopp's avatar
knopp committed
252
  PHY_VARS_UE *UE;
253 254
  int         inst;
  int         ret;
255
  LTE_DL_FRAME_PARMS *fp;
knopp's avatar
knopp committed
256

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

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

263 264
  if (PHY_vars_UE_g==NULL) PHY_vars_UE_g = (PHY_VARS_UE***)calloc(1+nb_inst,sizeof(PHY_VARS_UE**));
   
knopp's avatar
knopp committed
265
  for (inst=0;inst<nb_inst;inst++) {
266
    if (PHY_vars_UE_g[inst]==NULL) PHY_vars_UE_g[inst] = (PHY_VARS_UE**)calloc(1+MAX_NUM_CCs,sizeof(PHY_VARS_UE*));
267
    LOG_I(PHY,"Allocating UE context %d\n",inst);
knopp's avatar
knopp committed
268

269
    if (simL1flag == 0) PHY_vars_UE_g[inst][0] = init_ue_vars(fp0,inst,0);
knopp's avatar
knopp committed
270
    else {
271
      // needed for memcopy below. these are not used in the RU, but needed for UE
272 273
       RC.ru[0]->frame_parms.nb_antennas_rx = fp0->nb_antennas_rx;
       RC.ru[0]->frame_parms.nb_antennas_tx = fp0->nb_antennas_tx;
knopp's avatar
knopp committed
274 275
       PHY_vars_UE_g[inst][0]  = init_ue_vars(&RC.ru[0]->frame_parms,inst,0);
    }
276 277
    // turn off timing control loop in UE
    PHY_vars_UE_g[inst][0]->no_timing_correction = timing_correction;
278

279
    UE = PHY_vars_UE_g[inst][0];
280
    fp = &UE->frame_parms;
281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314
    printf("PHY_vars_UE_g[0][0] = %p\n",UE);

    if (phy_test==1)
      UE->mac_enabled = 0;
    else
      UE->mac_enabled = 1;

    if (UE->mac_enabled == 0) {  //set default UL parameters for testing mode
      for (int i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
        UE->pusch_config_dedicated[i].betaOffset_ACK_Index = 0;
        UE->pusch_config_dedicated[i].betaOffset_RI_Index  = 0;
        UE->pusch_config_dedicated[i].betaOffset_CQI_Index = 2;
        
        UE->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
        UE->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
        UE->scheduling_request_config[i].dsr_TransMax = sr_n4;
      }
    }

    UE->UE_scan = UE_scan;
    UE->UE_scan_carrier = UE_scan_carrier;
    UE->mode    = mode;
    printf("UE->mode = %d\n",mode);

    if (UE->mac_enabled == 1) {
      UE->pdcch_vars[0][0]->crnti = 0x1234;
      UE->pdcch_vars[1][0]->crnti = 0x1234;
    }else {
      UE->pdcch_vars[0][0]->crnti = 0x1235;
      UE->pdcch_vars[1][0]->crnti = 0x1235;
    }
    UE->rx_total_gain_dB =  rxgain;
    UE->tx_power_max_dBm = txpowermax;

315 316
    UE->frame_parms.nb_antennas_tx = fp0->nb_antennas_tx;
    UE->frame_parms.nb_antennas_rx = fp0->nb_antennas_rx; 
317

318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 333 334 335 336 337 338 339 340 341 342 343 344 345 346
    if (fp->frame_type == TDD) {
      switch (fp->N_RB_DL) {

      case 100:
	if (fp->threequarter_fs) UE->N_TA_offset = (624*3)/4;
	else                              UE->N_TA_offset = 624;
	break;
      case 75:
	UE->N_TA_offset = (624*3)/4;
	break;
      case 50:
	UE->N_TA_offset = 624/2;
	break;
      case 25:
	UE->N_TA_offset = 624/4;
	break;
      case 15:
	UE->N_TA_offset = 624/8;
	break;
      case 6:
	UE->N_TA_offset = 624/16;
	break;
      default:
	AssertFatal(1==0,"illegal N_RB_DL %d\n",fp->N_RB_DL);
	break;
      }
    }
    else UE->N_TA_offset = 0;

347 348 349 350 351 352 353
#if BASIC_SIMULATOR
    /* this is required for the basic simulator in TDD mode
     * TODO: find a proper cleaner solution
     */
    UE->N_TA_offset = 0;
#endif

354
    if (simL1flag == 1) init_ue_devices(UE);
355
    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
356
    init_UE_threads(inst);
knopp's avatar
knopp committed
357

358
    if (simL1flag == 0) {
359 360 361 362
      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
363
    }
364
    UE->rfdevice.host_type = RAU_HOST;
knopp's avatar
knopp committed
365
    //    UE->rfdevice.type      = NONE_DEV;
366

367 368 369 370
    AssertFatal(0 == pthread_create(&UE->proc.pthread_ue,
                                    &UE->proc.attr_ue,
                                    UE_thread,
                                    (void*)UE), "");
371 372
  }

373
  printf("UE threads created by %ld\n", gettid());
374 375
}

376
// Initiating all UEs within a single set of threads for PHY_STUB. Future extensions -> multiple
377 378 379 380 381 382 383 384 385 386 387 388 389 390
// set of threads for multiple UEs.
void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface) {

  int         inst;

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

  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]);
391
    // PHY_vars_UE_g[inst][0] = init_ue_vars(NULL,inst,0);
392 393 394 395 396 397 398 399 400 401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445
  }
  init_timer_thread();
  init_UE_single_thread_stub(nb_inst);


  printf("UE threads created \n");

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


}





void init_UE_stub(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface) {

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

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

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

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



}




446 447
/*!
 * \brief This is the UE synchronize thread.
448
 * It performs band scanning and synchonization.
449 450 451
 * \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
452

453 454
static void *UE_thread_synch(void *arg)
{
455
  static int UE_thread_synch_retval;
456
  int i ;
457
  PHY_VARS_UE *UE = (PHY_VARS_UE*) arg;
458 459
  int current_band = 0;
  int current_offset = 0;
460
  sync_mode_t sync_mode = pbch;
461
  int CC_id = UE->CC_id;
462 463
  int ind;
  int found;
464
  int freq_offset=0;
465
  char threadname[128];
466 467

  printf("UE_thread_sync in with PHY_vars_UE %p\n",arg);
468

469
  cpu_set_t cpuset;
470
  CPU_ZERO(&cpuset);
471 472 473 474 475
  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);
476

477
  printf("starting UE synch thread (IC %d)\n",UE->proc.instance_cnt_synch);
478 479
  ind = 0;
  found = 0;
480 481


482 483
  if (UE->UE_scan == 0) {
    do  {
484
      current_band = eutra_bands[ind].band;
knopp's avatar
knopp committed
485
      printf( "Scanning band %d, dl_min %"PRIu32", ul_min %"PRIu32"\n", current_band, eutra_bands[ind].dl_min,eutra_bands[ind].ul_min);
486

487
      if ((eutra_bands[ind].dl_min <= UE->frame_parms.dl_CarrierFreq) && (eutra_bands[ind].dl_max >= UE->frame_parms.dl_CarrierFreq)) {
488 489
	for (i=0; i<4; i++)
	  uplink_frequency_offset[CC_id][i] = eutra_bands[ind].ul_min - eutra_bands[ind].dl_min;
490 491 492 493

        found = 1;
        break;
      }
494

495
      ind++;
496
    } while (ind < sizeof(eutra_bands) / sizeof(eutra_bands[0]));
497

498
    if (found == 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
499
      LOG_E(PHY,"Can't find EUTRA band for frequency %d",UE->frame_parms.dl_CarrierFreq);
500
      exit_fun("Can't find EUTRA band for frequency");
501
      return &UE_thread_synch_retval;
502
    }
503

504

505
    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);
506

507
    for (i=0;i<openair0_cfg[UE->rf_map.card].rx_num_channels;i++) {
508 509
      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;
510
      openair0_cfg[UE->rf_map.card].autocal[UE->rf_map.chain+i] = 1;
511
      if (uplink_frequency_offset[CC_id][i] != 0) //
512
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_FDD;
513
      else //FDD
514
	openair0_cfg[UE->rf_map.card].duplex_mode = duplex_mode_TDD;
515 516
    }

517
    sync_mode = pbch;
518

519
  } else if  (UE->UE_scan == 1) {
520
    current_band=0;
521

522 523
    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;
524 525
      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;
526
      openair0_cfg[UE->rf_map.card].rx_freq[UE->rf_map.chain+i] = downlink_frequency[CC_id][i];
527 528
      openair0_cfg[UE->rf_map.card].tx_freq[UE->rf_map.chain+i] =
	downlink_frequency[CC_id][i]+uplink_frequency_offset[CC_id][i];
529
      openair0_cfg[UE->rf_map.card].rx_gain[UE->rf_map.chain+i] = UE->rx_total_gain_dB;
530 531
    }
  }
532

533
/*
534 535 536
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
  pthread_mutex_unlock(&sync_mutex);
537 538
*/
  wait_sync("UE_thread_sync");
knopp's avatar
knopp committed
539

540
  printf("Started device, unlocked sync_mutex (UE_sync_thread)\n");
541

542
  while (oai_exit==0) {
543 544
    AssertFatal ( 0== pthread_mutex_lock(&UE->proc.mutex_synch), "");
    while (UE->proc.instance_cnt_synch < 0)
545
      // the thread waits here most of the time
546
      pthread_cond_wait( &UE->proc.cond_synch, &UE->proc.mutex_synch );
547
    AssertFatal ( 0== pthread_mutex_unlock(&UE->proc.mutex_synch), "");
548

549
    switch (sync_mode) {
550
    case pss:
551 552
      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);
553
      current_offset += 20000000; // increase by 20 MHz
554

555
      if (current_offset > bands_to_scan.band_info[current_band].dl_max-bands_to_scan.band_info[current_band].dl_min) {
556
	current_band++;
557 558 559 560 561 562 563 564 565 566 567 568 569 570 571 572 573 574 575 576 577
	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;
	}
      }

      break;
578

579
    case pbch:
580

Cedric Roux's avatar
Cedric Roux committed
581
#if DISABLE_LOG_X
582
      printf("[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
Cedric Roux's avatar
Cedric Roux committed
583
#else
584
      LOG_I(PHY, "[UE thread Synch] Running Initial Synch (mode %d)\n",UE->mode);
Cedric Roux's avatar
Cedric Roux committed
585
#endif
586 587 588
      if (initial_sync( UE, UE->mode ) == 0) {

	LOG_I( HW, "Got synch: hw_slot_offset %d, carrier off %d Hz, rxgain %d (DL %u, UL %u), UE_scan_carrier %d\n",
589
	       (UE->rx_offset<<1) / UE->frame_parms.samples_per_tti,
590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 607 608
	       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;
609
	  }
610 611 612 613 614 615 616 617 618 619 620 621 622 623 624 625 626 627 628 629 630 631 632 633 634 635 636 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
	}

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

678 679 680 681 682 683 684 685 686 687 688 689 690 691 692 693 694 695 696 697 698 699 700 701 702 703 704
	    }
	  }
	}
      } 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
705
#if DISABLE_LOG_X
706 707 708 709 710
	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
711
#else
712 713 714 715 716
	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
717
#endif
laurent's avatar
laurent committed
718

719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735 736 737 738 739 740 741 742
	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;
743 744
}

745
/*!
746
 * \brief This is the UE thread for RX subframe n and TX subframe n+4.
747
 * This thread performs the phy_procedures_UE_RX() on every received slot.
laurent's avatar
laurent committed
748
 * then, if TX is enabled it performs TX for n+4.
749 750 751
 * \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.
 */
752 753 754 755 756 757 758 759 760 761 762
const char * get_connectionloss_errstr(int errcode) {
        switch (errcode) {
        case CONNECTION_LOST:
          return "RRC Connection lost, returning to PRACH";
        case PHY_RESYNCH:
           return "RRC Connection lost, trying to resynch";
        case RESYNCH:
           return "return to PRACH and perform a contention-free access";
        };
  return "UNKNOWN RETURN CODE";
}
763

laurent's avatar
laurent committed
764
static void *UE_thread_rxn_txnp4(void *arg) {
765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807 808 809 810 811 812 813 814 815 816 817 818 819 820 821 822 823 824 825 826 827
  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;

  proc->subframe_rx=proc->sub_frame_start;

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

  if ( (proc->sub_frame_start+1)%RX_NB_TH == 0 && threads.one != -1 )
    CPU_SET(threads.one, &cpuset);
  if ( (proc->sub_frame_start+1)%RX_NB_TH == 1 && threads.two != -1 )
    CPU_SET(threads.two, &cpuset);
  if ( (proc->sub_frame_start+1)%RX_NB_TH == 2 && threads.three != -1 )
    CPU_SET(threads.three, &cpuset);
  //CPU_SET(threads.three, &cpuset);
  init_thread(900000,1000000 , FIFO_PRIORITY-1, &cpuset,
	      threadname);

  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"))));
      }
828
#ifdef UE_SLOT_PARALLELISATION
829
      phy_procedures_slot_parallelization_UE_RX( UE, proc, 0, 0, 1, UE->mode, no_relay, NULL );
830
#else
831
      phy_procedures_UE_RX(UE, proc, 0, 0, 1, UE->mode);
832
#endif
833
    }
Bilel's avatar
Bilel committed
834

Gabriel's avatar
Gabriel committed
835
#if UE_TIMING_TRACE
836
    start_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
837
#endif
838 839
    if (UE->mac_enabled==1) {

840
      int ret = ue_scheduler(UE->Mod_id,
841 842 843 844 845 846 847 848 849
			 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) {
	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
850
	       UE->Mod_id, proc->frame_rx, proc->subframe_tx,get_connectionloss_errstr(ret) );
851 852
      }
    }
Gabriel's avatar
Gabriel committed
853
#if UE_TIMING_TRACE
854
    stop_meas(&UE->generic_stat);
Gabriel's avatar
Gabriel committed
855
#endif
Bilel's avatar
Bilel committed
856

857

858 859 860 861 862
    // Prepare the future Tx data

    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_UL) ||
	(UE->frame_parms.frame_type == FDD) )
      if (UE->mode != loop_through_memory)
863
	phy_procedures_UE_TX(UE,proc,0,0,UE->mode);
864 865 866 867 868 869



    if ((subframe_select( &UE->frame_parms, proc->subframe_tx) == SF_S) &&
	(UE->frame_parms.frame_type == TDD))
      if (UE->mode != loop_through_memory)
870
	phy_procedures_UE_S_TX(UE,0,0);
871
    updateTimes(current, &t3, 10000, "Delay to process sub-frame (case 3)");
872

873 874 875 876 877
    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--;
878
#if BASIC_SIMULATOR
879 880
    if (pthread_cond_signal(&proc->cond_rxtx) != 0) abort();
#endif
881 882 883 884 885 886 887 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 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966 967
    if (pthread_mutex_unlock(&proc->mutex_rxtx) != 0) {
      LOG_E( PHY, "[SCHED][UE] error unlocking mutex for UE RXTX\n" );
      exit_fun("noting to add");
    }
  }

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



unsigned int emulator_absSF;

void ue_stub_rx_handler(unsigned int num_bytes, char *rx_buffer) {

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

  UE_tport_t *pdu = (UE_tport_t*)rx_buffer;
  SLSCH_t *slsch = (SLSCH_t*)&pdu->slsch;
  SLDCH_t *sldch = (SLDCH_t*)&pdu->sldch;

  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:


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

    ue_send_sl_sdu(0,
		   0,
		   pdu->header.absSF/10,
		   pdu->header.absSF%10,
		   pdu->payload,
		   slsch->payload_length,
		   0,
		   SL_DISCOVERY_FLAG_NO);
    break;

  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,
                   sldch->payload,
                   sldch->payload_length,
                   0,
                   SL_DISCOVERY_FLAG_YES);
    break;

  }
}


/*!
 * \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_single_thread_rxn_txnp4(void *arg) {

	thread_top_init("UE_phy_stub_thread_rxn_txnp4",1,870000L,1000000L,1000000L);

968 969 970
	// for multipule UE's L2-emulator
	//module_id_t Mod_id = 0;

971 972 973 974 975
	//int init_ra_UE = -1; // This counter is used to initiate the RA of each UE in different SFrames
  static __thread int UE_thread_rxtx_retval;
  struct rx_tx_thread_data *rtd = arg;
  UE_rxtx_proc_t *proc = rtd->proc;

976 977 978 979 980
  // settings for nfapi-L2-emulator mode
  module_id_t ue_thread_id = rtd->ue_thread_id;
  uint16_t     ue_index = 0;
  uint16_t     ue_num = NB_UE_INST/NB_THREAD_INST+((NB_UE_INST%NB_THREAD_INST > ue_thread_id) ? 1 :0);
  module_id_t ue_Mod_id;
981
  PHY_VARS_UE    *UE = NULL;
982
  int ret;
983 984 985 986
  uint8_t   end_flag;
  proc = &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0];
  phy_stub_ticking->num_single_thread[ue_thread_id] = -1;

987 988 989 990
  if (rtd != NULL) {
    UE = rtd->UE;
  }

991 992 993 994 995 996 997 998 999 1000 1001 1002 1003 1004 1005 1006 1007 1008
  if(ue_thread_id == 0){
    phy_stub_ticking->ticking_var = -1;
    proc->subframe_rx=proc->sub_frame_start;
    // Initializations for nfapi-L2-emulator mode
    dl_config_req = NULL;
    ul_config_req = NULL;
    hi_dci0_req        = NULL;
    tx_request_pdu_list = NULL;

    // waiting for all UE's threads set phy_stub_ticking->num_single_thread[ue_thread_id] = -1.
    do{
      end_flag = 1;
      for(uint16_t i = 0;i< NB_THREAD_INST;i++){
        if(phy_stub_ticking->num_single_thread[i] == 0){
          end_flag = 0;
        }
      }
   }while(end_flag == 0);
1009

1010 1011
    sync_var=0;
  }
1012 1013 1014 1015 1016 1017


  //PANOS: CAREFUL HERE!
  wait_sync("UE_phy_stub_single_thread_rxn_txnp4");

  while (!oai_exit) {
1018
    if(ue_thread_id == 0){
1019 1020 1021 1022 1023 1024 1025 1026 1027 1028 1029 1030 1031 1032 1033 1034 1035 1036
    if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
      LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
      exit_fun("nothing to add");
    }
    while (phy_stub_ticking->ticking_var < 0) {
      // most of the time, the thread is waiting here
      //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
      LOG_D(MAC,"Waiting for ticking_var\n");
      pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
    }
    phy_stub_ticking->ticking_var--;
    if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
      LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
      exit_fun("nothing to add");
    }

    proc->subframe_rx=timer_subframe;
    proc->frame_rx = timer_frame;
1037 1038
    
    // FDD and TDD tx timing settings.
INOUE Yoshio's avatar
INOUE Yoshio committed
1039 1040
    // XXX:It is the result of timing adjustment in debug.
    // It is necessary to investigate why this will work in the future.
1041 1042
    proc->subframe_tx=(timer_subframe+sf_ahead)%10;
    proc->frame_tx = proc->frame_rx + (proc->subframe_rx>(9-sf_ahead)?1:0);
1043 1044
    //oai_subframe_ind(proc->frame_rx, proc->subframe_rx);

1045 1046 1047 1048 1049 1050 1051 1052 1053
    if (UE != NULL) {
      if (UE->frame_parms.frame_type == FDD) {
        oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
      } else {
        oai_subframe_ind(proc->frame_tx, proc->subframe_tx);
      }
    } else {
      // Default will be FDD
      oai_subframe_ind(proc->frame_rx, proc->subframe_rx);
1054
    }
1055

1056
    //Guessing that the next 4 lines are not needed for the phy_stub mode.
1057 1058 1059 1060 1061 1062
    /*initRefTimes(t2);
      initRefTimes(t3);
      pickTime(current);
      updateTimes(proc->gotIQs, &t2, 10000, "Delay to wake up UE_Thread_Rx (case 2)");*/


1063
    	// Not sure whether we should put the memory allocation here and not sure how much memory
1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074 1075 1076
        //we should allocate for each subframe cycle.
    	UL_INFO = (UL_IND_t*)malloc(sizeof(UL_IND_t));

    	UL_INFO->rx_ind.rx_indication_body.rx_pdu_list = (nfapi_rx_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_rx_indication_pdu_t));
    	UL_INFO->rx_ind.rx_indication_body.number_of_pdus = 0;


    	UL_INFO->crc_ind.crc_indication_body.crc_pdu_list = (nfapi_crc_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_crc_indication_pdu_t));
    	UL_INFO->crc_ind.crc_indication_body.number_of_crcs = 0;

    	UL_INFO->harq_ind.harq_indication_body.harq_pdu_list = (nfapi_harq_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_harq_indication_pdu_t));
    	UL_INFO->harq_ind.harq_indication_body.number_of_harqs = 0;

1077 1078 1079 1080 1081 1082 1083 1084 1085 1086 1087 1088 1089 1090 1091 1092 1093 1094 1095 1096 1097 1098 1099 1100 1101 1102 1103 1104 1105 1106 1107 1108 1109
    	UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = (nfapi_sr_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_sr_indication_pdu_t));
     	UL_INFO->sr_ind.sr_indication_body.number_of_srs = 0;

        UL_INFO->cqi_ind.cqi_pdu_list =  (nfapi_cqi_indication_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_cqi_indication_pdu_t));
        UL_INFO->cqi_ind.cqi_raw_pdu_list = (nfapi_cqi_indication_raw_pdu_t*)malloc(NB_UE_INST*sizeof(nfapi_cqi_indication_raw_pdu_t));
        UL_INFO->cqi_ind.number_of_cqis = 0;

        if (pthread_mutex_lock(&phy_stub_ticking->mutex_single_thread) != 0) {
          LOG_E( MAC, "[SCHED][UE] error locking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
          exit_fun("nothing to add");
        }
        memset(&phy_stub_ticking->num_single_thread[0],0,sizeof(int)*NB_THREAD_INST);
        pthread_cond_broadcast(&phy_stub_ticking->cond_single_thread);

        if (pthread_mutex_unlock(&phy_stub_ticking->mutex_single_thread) != 0) {
          LOG_E( MAC, "[SCHED][UE] error unlocking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
          exit_fun("nothing to add");
        }
    }else{
        if (pthread_mutex_lock(&phy_stub_ticking->mutex_single_thread) != 0) {
          LOG_E( MAC, "[SCHED][UE] error locking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
           exit_fun("nothing to add");
        }
        while (phy_stub_ticking->num_single_thread[ue_thread_id] < 0) {
          // most of the time, the thread is waiting here
          LOG_D(MAC,"Waiting for single_thread (ue_thread_id %d)\n",ue_thread_id);
          pthread_cond_wait( &phy_stub_ticking->cond_single_thread, &phy_stub_ticking->mutex_single_thread);
        }
        if (pthread_mutex_unlock(&phy_stub_ticking->mutex_single_thread) != 0) {
          LOG_E( MAC, "[SCHED][UE] error unlocking mutex for ue_thread_id %d (mutex_single_thread)\n",ue_thread_id);
          exit_fun("nothing to add");
        }
    }
1110

1111 1112 1113 1114 1115 1116
    //for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++) {
    for (ue_index=0; ue_index < ue_num; ue_index++) {
    ue_Mod_id = ue_thread_id + NB_THREAD_INST*ue_index;
    UE = PHY_vars_UE_g[ue_Mod_id][0];
    //LOG_D(MAC, "UE_phy_stub_single_thread_rxn_txnp4, NB_UE_INST:%d, Mod_id:%d \n", NB_UE_INST, Mod_id);
    //UE = PHY_vars_UE_g[Mod_id][0];
1117 1118 1119 1120 1121 1122
    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) {
1123
	LOG_D(PHY, "TDD%d,%s: calling UE_RX\n",
1124 1125 1126 1127 1128
	      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 {
1129
	LOG_D(PHY, "%s,%s: calling UE_RX\n",
1130 1131 1132 1133 1134 1135 1136 1137 1138 1139 1140 1141
	      (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"))));
      }


      phy_procedures_UE_SL_RX(UE,proc);

      if (dl_config_req!=NULL && tx_request_pdu_list!=NULL){
    	  //if(dl_config_req!= NULL) {
1142
    	  dl_config_req_UE_MAC(dl_config_req, ue_Mod_id);
1143

1144 1145 1146
      }

      if (hi_dci0_req!=NULL && hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
1147
    	  hi_dci0_req_UE_MAC(hi_dci0_req, ue_Mod_id);
1148 1149 1150 1151
      }

      if(nfapi_mode!=3)
      phy_procedures_UE_SL_TX(UE,proc);
1152

1153
    }
1154

1155 1156 1157
#if UE_TIMING_TRACE
    start_meas(&UE->generic_stat);
#endif
1158

1159 1160
    if (UE->mac_enabled==1) {

1161
      ret = ue_scheduler(ue_Mod_id,
1162 1163 1164 1165 1166 1167 1168 1169 1170
			 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) {
	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
1171
	       UE->Mod_id, proc->frame_rx, proc->subframe_tx,get_connectionloss_errstr(ret) );
1172
      }
1173
    }
1174 1175 1176 1177 1178 1179 1180 1181 1182 1183 1184 1185 1186
#if UE_TIMING_TRACE
    stop_meas(&UE->generic_stat);
#endif


    // Prepare the future Tx data

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

    // We make the start of RA between consecutive UEs differ by 20 frames
	//if ((UE_mac_inst[Mod_id].UE_mode[0] == PRACH  && Mod_id == 0) || (UE_mac_inst[Mod_id].UE_mode[0] == PRACH && Mod_id>0 && proc->frame_rx >= UE_mac_inst[Mod_id-1].ra_frame + 20) ) {
1187 1188 1189
	if (UE_mac_inst[ue_Mod_id].UE_mode[0] == PRACH  && ue_Mod_id == next_Mod_id) {
          next_ra_frame++;
          if(next_ra_frame > 200){
1190
	  // check if we have PRACH opportunity
1191

1192
	  if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx) &&  UE_mac_inst[ue_Mod_id].SI_Decoded == 1) {
1193 1194 1195 1196

	  // The one working strangely...
      //if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx && Mod_id == (module_id_t) init_ra_UE) ) {

1197
	    PRACH_RESOURCES_t *prach_resources = ue_get_rach(ue_Mod_id, 0, proc->frame_tx, 0, proc->subframe_tx);
1198
	    if(prach_resources!=NULL ) {
1199 1200 1201 1202 1203 1204 1205 1206
	    	UE_mac_inst[ue_Mod_id].ra_frame = proc->frame_rx;
	      LOG_D(MAC, "UE_phy_stub_thread_rxn_txnp4 before RACH, Mod_id: %d frame %d subframe %d\n", ue_Mod_id ,proc->frame_tx, proc->subframe_tx);
	      fill_rach_indication_UE_MAC(ue_Mod_id, proc->frame_tx ,proc->subframe_tx, UL_INFO, prach_resources->ra_PreambleIndex, prach_resources->ra_RNTI);
	      Msg1_transmitted(ue_Mod_id, 0, proc->frame_tx, 0);
	      UE_mac_inst[ue_Mod_id].UE_mode[0] = RA_RESPONSE;
	      next_Mod_id = ue_Mod_id + 1;
	      //next_ra_frame = (proc->frame_rx + 20)%1000;
              next_ra_frame = 0;
1207 1208 1209 1210
	    }

	    //ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
	  }
1211
          }
1212
	} // mode is PRACH
1213
	// Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
1214 1215 1216
	// UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
	// Generate UL_indications which correspond to UL traffic.
	if(ul_config_req!=NULL){ //&& UE_mac_inst[Mod_id].ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
1217
		ul_config_req_UE_MAC(ul_config_req, timer_frame, timer_subframe, ue_Mod_id);
1218 1219 1220 1221 1222 1223 1224 1225
	}
      }

    phy_procedures_UE_SL_RX(UE,proc);


    } //for (Mod_id=0; Mod_id<NB_UE_INST; Mod_id++)

1226 1227 1228 1229 1230 1231 1232 1233 1234 1235 1236 1237 1238
    phy_stub_ticking->num_single_thread[ue_thread_id] = -1;

    // waiting for all UE's threads set phy_stub_ticking->num_single_thread[ue_thread_id] = -1.
    if(ue_thread_id == 0){
      do{
        end_flag = 1;
        for(uint16_t i = 0;i< NB_THREAD_INST;i++){
          if(phy_stub_ticking->num_single_thread[i] == 0){
             end_flag = 0;
          }
        }
      }while(end_flag == 0);

1239 1240 1241 1242 1243 1244 1245 1246 1247 1248 1249 1250 1251 1252

    if (UL_INFO->crc_ind.crc_indication_body.number_of_crcs>0)
      {
    	  //LOG_D(PHY,"UL_info->crc_ind.crc_indication_body.number_of_crcs:%d CRC_IND:SFN/SF:%d\n", UL_info->crc_ind.crc_indication_body.number_of_crcs, NFAPI_SFNSF2DEC(UL_info->crc_ind.sfn_sf));
    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.2, SFN/SF of PNF counter:%d.%d, number_of_crcs: %d \n", timer_frame, timer_subframe, UL_INFO->crc_ind.crc_indication_body.number_of_crcs);
    	  oai_nfapi_crc_indication(&UL_INFO->crc_ind);
    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.21 \n");
    	  UL_INFO->crc_ind.crc_indication_body.number_of_crcs = 0;
      }
      if (UL_INFO->rx_ind.rx_indication_body.number_of_pdus>0)
      {
    	  //LOG_D(PHY,"UL_info->rx_ind.number_of_pdus:%d RX_IND:SFN/SF:%d\n", UL_info->rx_ind.rx_indication_body.number_of_pdus, NFAPI_SFNSF2DEC(UL_info->rx_ind.sfn_sf));
    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.3, SFN/SF of PNF counter:%d.%d, number_of_pdus: %d \n", timer_frame, timer_subframe, UL_INFO->rx_ind.rx_indication_body.number_of_pdus);
    	  oai_nfapi_rx_ind(&UL_INFO->rx_ind);
1253 1254 1255
          for(uint8_t num_pdu = 0;num_pdu < UL_INFO->rx_ind.rx_indication_body.number_of_pdus;num_pdu++){
            free(UL_INFO->rx_ind.rx_indication_body.rx_pdu_list[num_pdu].data);
          }
1256 1257 1258 1259 1260 1261 1262 1263 1264 1265 1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287 1288 1289 1290 1291
    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.31 \n");
    	  UL_INFO->rx_ind.rx_indication_body.number_of_pdus = 0;
      }
      if(UL_INFO->harq_ind.harq_indication_body.number_of_harqs>0)
      {
    	  //LOG_D(MAC, "ul_config_req_UE_MAC 2.4, SFN/SF of PNF counter:%d.%d, number_of_harqs: %d \n", timer_frame, timer_subframe, UL_INFO->harq_ind.harq_indication_body.number_of_harqs);
    	  oai_nfapi_harq_indication(&UL_INFO->harq_ind);
    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.41 \n");
    	  UL_INFO->harq_ind.harq_indication_body.number_of_harqs =0;

      }
      if(UL_INFO->sr_ind.sr_indication_body.number_of_srs>0)
      {
    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.5, SFN/SF of PNF counter:%d.%d, number_of_srs: %d \n", timer_frame, timer_subframe, UL_INFO->sr_ind.sr_indication_body.number_of_srs);
    	  oai_nfapi_sr_indication(&UL_INFO->sr_ind);
    	  //LOG_I(MAC, "ul_config_req_UE_MAC 2.51 \n");
    	  UL_INFO->sr_ind.sr_indication_body.number_of_srs = 0;
      }

      // Free UL_INFO messages
      //if(UL_INFO->crc_ind.crc_indication_body.crc_pdu_list != NULL){
    	  free(UL_INFO->crc_ind.crc_indication_body.crc_pdu_list);
    	  UL_INFO->crc_ind.crc_indication_body.crc_pdu_list = NULL;
      //}
      //if(UL_INFO->rx_ind.rx_indication_body.rx_pdu_list != NULL){
    	  free(UL_INFO->rx_ind.rx_indication_body.rx_pdu_list);
    	  UL_INFO->rx_ind.rx_indication_body.rx_pdu_list = NULL;
      //}
      //if(UL_INFO->harq_ind.harq_indication_body.harq_pdu_list !=NULL){
    	  free(UL_INFO->harq_ind.harq_indication_body.harq_pdu_list);
    	  UL_INFO->harq_ind.harq_indication_body.harq_pdu_list = NULL;
      //}
      //if(UL_INFO->sr_ind.sr_indication_body.sr_pdu_list!=NULL){
    	  free(UL_INFO->sr_ind.sr_indication_body.sr_pdu_list);
    	  UL_INFO->sr_ind.sr_indication_body.sr_pdu_list = NULL;
      //}
1292 1293 1294 1295
      free(UL_INFO->cqi_ind.cqi_pdu_list);
      UL_INFO->cqi_ind.cqi_pdu_list = NULL;
      free(UL_INFO->cqi_ind.cqi_raw_pdu_list);
      UL_INFO->cqi_ind.cqi_raw_pdu_list = NULL;
1296 1297 1298 1299 1300
      free(UL_INFO);
      UL_INFO = NULL;

      // De-allocate memory of nfapi requests copies before next subframe round
      if(dl_config_req!=NULL){
1301 1302 1303 1304
    	  if(dl_config_req->vendor_extension!=NULL){
            free(dl_config_req->vendor_extension);
            dl_config_req->vendor_extension = NULL;
          }
1305 1306 1307 1308 1309 1310 1311 1312 1313 1314 1315 1316 1317 1318 1319 1320 1321 1322 1323 1324 1325 1326 1327 1328 1329 1330 1331 1332 1333
    	  if(dl_config_req->dl_config_request_body.dl_config_pdu_list!=NULL){
    		  free(dl_config_req->dl_config_request_body.dl_config_pdu_list);
    		  dl_config_req->dl_config_request_body.dl_config_pdu_list = NULL;
    	  }
    	  free(dl_config_req);
    	  dl_config_req = NULL;
      }
      if(tx_request_pdu_list!=NULL){
    	  free(tx_request_pdu_list);
    	  tx_request_pdu_list = NULL;
      }
      if(ul_config_req!=NULL){
    	  if(ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
    		  free(ul_config_req->ul_config_request_body.ul_config_pdu_list);
    		  ul_config_req->ul_config_request_body.ul_config_pdu_list = NULL;
    	  }
    	  free(ul_config_req);
    	  ul_config_req = NULL;
      }

      if(hi_dci0_req!=NULL){
    	  if(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
    		  free(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list);
    		  hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL;
    	  }
    	  free(hi_dci0_req);
    	  hi_dci0_req = NULL;
      }

1334
    }
1335 1336 1337 1338 1339

  }
  // thread finished
  free(arg);
  return &UE_thread_rxtx_retval;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1340
}
1341

1342 1343 1344 1345 1346 1347 1348 1349 1350 1351 1352 1353 1354 1355 1356 1357 1358 1359 1360 1361 1362 1363 1364 1365



/*!
 * \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) {

	thread_top_init("UE_phy_stub_thread_rxn_txnp4",1,870000L,1000000L,1000000L);

	module_id_t Mod_id = 0;
  static __thread int UE_thread_rxtx_retval;
  struct rx_tx_thread_data *rtd = arg;
  UE_rxtx_proc_t *proc = rtd->proc;
  PHY_VARS_UE    *UE   = rtd->UE;

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

1366
  // CAREFUL HERE!
1367 1368 1369 1370 1371 1372 1373 1374 1375 1376 1377 1378 1379 1380 1381 1382 1383 1384 1385 1386 1387 1388 1389 1390 1391 1392 1393 1394 1395 1396 1397 1398 1399
  wait_sync("UE_phy_stub_thread_rxn_txnp4");

  while (!oai_exit) {

    if (pthread_mutex_lock(&phy_stub_ticking->mutex_ticking) != 0) {
      LOG_E( MAC, "[SCHED][UE] error locking mutex for UE RXTX\n" );
      exit_fun("nothing to add");
    }
    while (phy_stub_ticking->ticking_var < 0) {
      // most of the time, the thread is waiting here
      //pthread_cond_wait( &proc->cond_rxtx, &proc->mutex_rxtx )
      LOG_D(MAC,"Waiting for ticking_var\n");
      pthread_cond_wait( &phy_stub_ticking->cond_ticking, &phy_stub_ticking->mutex_ticking);
    }
    phy_stub_ticking->ticking_var--;
    if (pthread_mutex_unlock(&phy_stub_ticking->mutex_ticking) != 0) {
      LOG_E( MAC, "[SCHED][UE] error unlocking mutex for UE RXn_TXnp4\n" );
      exit_fun("nothing to add");
    }

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


    // 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) {
1400
	LOG_D(PHY, "TDD%d,%s: calling UE_RX\n",
1401 1402 1403 1404 1405
	      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 {
1406
	LOG_D(PHY, "%s,%s: calling UE_RX\n",
1407 1408 1409 1410 1411 1412 1413 1414 1415 1416 1417 1418 1419 1420 1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434 1435 1436 1437 1438 1439 1440 1441 1442 1443 1444 1445 1446 1447 1448 1449
	      (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"))));
      }


      phy_procedures_UE_SL_RX(UE,proc);

       oai_subframe_ind(timer_frame, timer_subframe);

      if(dl_config_req!= NULL) {

	dl_config_req_UE_MAC(dl_config_req, Mod_id);

      }
      //if(UE_mac_inst[Mod_id].hi_dci0_req!= NULL){
      if (hi_dci0_req!=NULL && hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
    	  hi_dci0_req_UE_MAC(hi_dci0_req, Mod_id);
    	  //if(UE_mac_inst[Mod_id].hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list!=NULL){
    		  free(hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list);
    		  hi_dci0_req->hi_dci0_request_body.hi_dci0_pdu_list = NULL;
    	  //}
    	  free(hi_dci0_req);
    	  hi_dci0_req = NULL;
      }

      else if(hi_dci0_req!=NULL){
      		free(hi_dci0_req);
      		hi_dci0_req = NULL;
      	}

      if (nfapi_mode != 3)
        phy_procedures_UE_SL_TX(UE,proc);

    }

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

1450
      int ret = ue_scheduler(UE->Mod_id,
1451 1452 1453 1454 1455 1456 1457
			 proc->frame_rx,
			 proc->subframe_rx,
			 proc->frame_tx,
			 proc->subframe_tx,
			 subframe_select(&UE->frame_parms,proc->subframe_tx),
			 0,
			 0);
1458
      if (ret != CONNECTION_OK)
1459
	LOG_E( PHY, "[UE %"PRIu8"] Frame %"PRIu32", subframe %u %s\n",
1460
	       UE->Mod_id, proc->frame_rx, proc->subframe_tx,get_connectionloss_errstr(ret) );
1461 1462 1463 1464 1465 1466 1467 1468 1469 1470 1471 1472 1473 1474 1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487
    }
#if UE_TIMING_TRACE
    stop_meas(&UE->generic_stat);
#endif


    // Prepare the future Tx data

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

	if ((UE_mac_inst[Mod_id].UE_mode[0] == PRACH) ) {

	  // check if we have PRACH opportunity

	  if (is_prach_subframe(&UE->frame_parms,proc->frame_tx, proc->subframe_tx)) {
	    PRACH_RESOURCES_t *prach_resources = ue_get_rach(Mod_id, 0, proc->frame_tx, 0, proc->subframe_tx);
	    if(prach_resources!=NULL) {
	      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;
	    }

	    //ue_prach_procedures(ue,proc,eNB_id,abstraction_flag,mode);
	  }
	} // mode is PRACH
1488
	// Substitute call to phy_procedures Tx with call to phy_stub functions in order to trigger
1489 1490 1491 1492 1493 1494 1495 1496 1497 1498 1499 1500 1501 1502 1503 1504 1505 1506 1507 1508 1509 1510 1511 1512 1513 1514 1515 1516
	// UE Tx procedures directly at the MAC layer, based on the received ul_config requests from the vnf (eNB).
	// Generate UL_indications which correspond to UL traffic.
	if(ul_config_req!= NULL && ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
		//LOG_I(MAC, "UE_phy_stub_thread_rxn_txnp4 ul_config_req is not NULL \n");
		ul_config_req_UE_MAC(ul_config_req, timer_frame, timer_subframe, Mod_id);
		if(ul_config_req->ul_config_request_body.ul_config_pdu_list != NULL){
			free(ul_config_req->ul_config_request_body.ul_config_pdu_list);
			ul_config_req->ul_config_request_body.ul_config_pdu_list = NULL;
		}
		free(ul_config_req);
		ul_config_req = NULL;
	}
	else if(ul_config_req!=NULL){
		free(ul_config_req);
		ul_config_req = NULL;
	}
      }

    phy_procedures_UE_SL_RX(UE,proc);

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



1517 1518 1519
/*!
 * \brief This is the main UE thread.
 * This thread controls the other three UE threads:
1520 1521
 * - UE_thread_rxn_txnp4 (even subframes)
 * - UE_thread_rxn_txnp4 (odd subframes)
1522 1523 1524 1525
 * - UE_thread_synch
 * \param arg unused
 * \returns a pointer to an int. The storage is not on the heap and must not be freed.
 */
1526 1527 1528 1529

void *UE_thread(void *arg) {


1530 1531 1532 1533 1534 1535 1536 1537
  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;
1538

1539
  static uint8_t thread_idx = 0;
1540

1541 1542 1543 1544 1545 1546
  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");
1547

1548 1549 1550 1551 1552 1553
  /*
  while (sync_var<0)
    pthread_cond_wait(&sync_cond, &sync_mutex);
  pthread_mutex_unlock(&sync_mutex);
  */

knopp's avatar
knopp committed
1554
  wait_sync("UE thread");
1555
#ifdef NAS_UE
1556 1557 1558
  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);
1559
#endif
1560

1561 1562
  int sub_frame=-1;
  //int cumulated_shift=0;
1563

1564 1565 1566 1567
  if (UE->rfdevice.trx_start_func(&UE->rfdevice) != 0 ) {
    LOG_E(HW,"Could not start the de