lte-uesoftmodem.c 33.1 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22
/*! \file lte-uesoftmodem.c
23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 * \brief Top-level threads for eNodeB
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2012
 * \version 0.1
 * \company Eurecom
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
 * \note
 * \warning
 */


#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

#include "rt_wrapper.h"


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

#include "assertions.h"
#include "msc.h"

#include "PHY/types.h"

47
#include "PHY/defs_UE.h"
48 49 50 51 52 53 54 55 56 57 58
#include "common/ran_context.h"
#include "common/config/config_userapi.h"
#include "common/utils/load_module_shlib.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 "../../ARCH/COMMON/common_lib.h"
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"

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

59 60 61 62
#include "PHY/phy_vars_ue.h"
#include "PHY/LTE_TRANSPORT/transport_vars.h"
#include "SCHED/sched_common_vars.h"
#include "PHY/MODULATION/modulation_vars.h"
63

64 65 66 67 68
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_vars.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
69

70
#include "common/utils/LOG/log.h"
71 72 73
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
74
#include "common/utils/LOG/vcd_signal_dumper.h"
75 76 77
#include "UTIL/OPT/opt.h"

#ifndef OPENAIR2
78
  #include "UTIL/OTG/otg_vars.h"
79 80 81
#endif

#if defined(ENABLE_ITTI)
82
  #include "create_tasks.h"
83 84 85 86 87
#endif

#include "system.h"

#ifdef XFORMS
88 89
  #include "PHY/TOOLS/lte_phy_scope.h"
  #include "stats.h"
90 91 92
#endif
#include "lte-softmodem.h"

93

94

95 96 97
/* temporary compilation wokaround (UE/eNB split */
uint16_t sf_ahead;
#ifdef XFORMS
98 99 100 101 102 103 104 105
  // current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
  // at eNB 0, an UL scope for every UE
  FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
  FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
  FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
  char title[255];
  unsigned char                   scope_enb_num_ue = 2;
  static pthread_t                forms_thread; //xforms
106 107
#endif //XFORMS

108 109 110 111 112
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

uint8_t nfapi_mode = 0;
113 114 115 116 117
#ifdef PDCP_USE_NETLINK
#ifdef UESIM_EXPANSION
uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX];
#endif
#endif
118
uint16_t sf_ahead=2;
119
int tddflag;
120 121 122
char *emul_iface;


123 124 125 126 127 128 129 130 131 132
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
int config_sync_var=-1;

uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]

volatile int             oai_exit = 0;

Cedric Roux's avatar
Cedric Roux committed
133
clock_source_t clock_source = internal;
134

135 136 137 138 139 140 141 142 143 144 145

unsigned int                    mmapped_dma=0;


uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];



int UE_scan = 1;
int UE_scan_carrier = 0;
146
int simL1flag = 0;
147
int snr_dB=25;
knopp's avatar
knopp committed
148

149 150 151 152 153 154 155 156
runmode_t mode = normal_txrx;

FILE *input_fd=NULL;


#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
157
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0}};
158 159 160
#else
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
161
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0},{20,0,0,0}};
162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183
#endif

double rx_gain_off = 0.0;

double sample_rate=30.72e6;
double bw = 10.0e6;

static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;


uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;

char ref[128] = "internal";
char channels[128] = "0";

int                      rx_input_level_dBm;

#ifdef XFORMS
184
  extern int                      otg_enabled;
185 186 187 188 189
#endif
//int                             number_of_cards =   1;


static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
190

191 192 193
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots

194 195
/* prototypes from function implemented in lte-ue.c, probably should be elsewhere in a include
   file */
196
extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
197

198 199 200
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
                                 uint8_t UE_id,
                                 uint8_t abstraction_flag);
201

202
extern void get_uethreads_params(void);
203 204 205 206

int transmission_mode=1;


Wang Tsu-Han's avatar
Wang Tsu-Han committed
207

208 209
char *usrp_args=NULL;
char *usrp_clksrc=NULL;
210

211
THREAD_STRUCT thread_struct;
212 213 214 215 216 217 218 219 220 221 222
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

extern char uecap_xer[1024];
char uecap_xer_in=0;

int oaisim_flag=0;
223

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239

/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;

/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

struct timespec clock_difftime(struct timespec start, struct timespec end) {
  struct timespec temp;
240

241 242 243 244 245 246 247
  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }
248

249 250 251 252 253 254 255 256 257 258 259 260 261 262 263
  return temp;
}

void print_difftimes(void) {
#ifdef DEBUG
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

void update_difftimes(struct timespec start, struct timespec end) {
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
264

265 266 267 268
  if ((min_diff_time.tv_nsec == 0) || (diff_time.tv_nsec < min_diff_time.tv_nsec)) {
    min_diff_time.tv_nsec = diff_time.tv_nsec;
    changed = 1;
  }
269

270 271 272 273
  if ((max_diff_time.tv_nsec == 0) || (diff_time.tv_nsec > max_diff_time.tv_nsec)) {
    max_diff_time.tv_nsec = diff_time.tv_nsec;
    changed = 1;
  }
274

275
#if 1
276

277
  if (changed) print_difftimes();
278

279 280 281 282 283 284 285 286 287 288 289 290
#endif
}

/*------------------------------------------------------------------------*/

unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
}

291 292


293 294 295 296 297 298 299 300 301 302 303 304
void signal_handler(int sig) {
  void *array[10];
  size_t size;

  if (sig==SIGSEGV) {
    // get void*'s for all entries on the stack
    size = backtrace(array, 10);
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
  } else {
305 306 307
    char msg[64];
    sprintf(msg,"Received linux signal %s...\n",strsignal(sig));
    exit_function(__FILE__, __FUNCTION__, __LINE__,msg);
308 309 310 311
  }
}


312
void exit_function(const char *file, const char *function, const int line, const char *s) {
313
  int CC_id;
314
  logClean();
315
  printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, ((s==NULL)?"":s));
316 317 318
  oai_exit = 1;

  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
319
    if (PHY_vars_UE_g)
320
      if (PHY_vars_UE_g[0])
321 322 323 324
        if (PHY_vars_UE_g[0][CC_id])
          if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
            PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
  }
325

326
  sleep(1); //allow lte-softmodem threads to exit first
327
#if defined(ENABLE_ITTI)
328 329

  if(PHY_vars_UE_g != NULL )
330
    itti_terminate_tasks (TASK_UNKNOWN);
331

332
#endif
333
  exit(1);
334 335 336 337 338
}

#ifdef XFORMS


339
void reset_stats(FL_OBJECT *button, long arg) {
340 341 342 343 344 345
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
346 347 348
        phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
        phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
        phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370 371 372 373 374
      }

      phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;
      phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
      phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
      phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
    }
  }
}

static void *scope_thread(void *arg) {
  char stats_buffer[16384];
# ifdef ENABLE_XFORMS_WRITE_STATS
  FILE *UE_stats, *eNB_stats;
# endif
  struct sched_param sched_param;
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
# ifdef ENABLE_XFORMS_WRITE_STATS
  UE_stats  = fopen("UE_stats.txt", "w");
#endif

  while (!oai_exit) {
375
    //      dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm);
376 377 378 379 380 381 382 383 384
    //fl_set_object_label(form_stats->stats_text, stats_buffer);
    fl_clear_browser(form_stats->stats_text);
    fl_add_browser_line(form_stats->stats_text, stats_buffer);
    phy_scope_UE(form_ue[0],
                 PHY_vars_UE_g[0][0],
                 0,
                 0,7);
    //  printf("%s",stats_buffer);
  }
385 386 387

# ifdef ENABLE_XFORMS_WRITE_STATS

388 389 390 391 392
  if (UE_stats) {
    rewind (UE_stats);
    fwrite (stats_buffer, 1, len, UE_stats);
    fclose (UE_stats);
  }
393 394

# endif
395
  pthread_exit((void *)arg);
396 397 398 399 400
}
#endif



401
extern int16_t dlsch_demod_shift;
402

403
static void get_options(void) {
404
  int CC_id;
405
  int tddflag;
406 407
  char *loopfile=NULL;
  int dumpframe;
408
  int timingadv;
409
  set_default_frame_parms(frame_parms);
410
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
411 412
  /* unknown parameters on command line will be checked in main
     after all init have been performed                         */
413 414
  get_common_options();
  get_uethreads_params();
415 416 417 418
  paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
  paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
  config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
  config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);
419

420
  if (loopfile != NULL) {
421 422 423 424
    printf("Input file for hardware emulation: %s",loopfile);
    mode=loop_through_memory;
    input_fd = fopen(loopfile,"r");
    AssertFatal(input_fd != NULL,"Please provide a valid input file\n");
425 426
  }

427
  get_softmodem_params()->hw_timing_advance = timingadv;
428

429
  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue;
430

431
  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med;
432

433
  if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp;
434

435
  if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr)
436 437
    if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;

438
  if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr)
439 440 441 442 443
    if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0)  mode = no_L2_connect;

  if (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr)
    if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx;

444
  if (dumpframe  > 0)  mode = rx_dump_frame;
445

446 447 448
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
  }
449

450 451
  UE_scan=0;
   
452
  if (tddflag > 0) {
453
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
454
      frame_parms[CC_id]->frame_type = TDD;
455 456
      frame_parms[CC_id]->tdd_config = tddflag;
    }
457 458 459
  }

  if (frame_parms[0]->N_RB_DL !=0) {
460 461 462 463
    if ( frame_parms[0]->N_RB_DL < 6 ) {
      frame_parms[0]->N_RB_DL = 6;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL);
    }
464

465 466 467 468
    if ( frame_parms[0]->N_RB_DL > 100 ) {
      frame_parms[0]->N_RB_DL = 100;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL);
    }
469

470 471 472 473
    if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) {
      frame_parms[0]->N_RB_DL = 50;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL);
    }
474

475 476 477 478
    if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) {
      frame_parms[0]->N_RB_DL = 25;
      printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL);
    }
479

480 481 482 483 484 485 486 487 488 489 490 491
    UE_scan = 0;
    frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;

    for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
      frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL;
      frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL;
    }
  }

  for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
    rx_gain[0][CC_id] = rx_gain[0][0];
    tx_gain[0][CC_id] = tx_gain[0][0];
492 493
  }

494
  /*
495 496 497 498 499
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT))  && (!(CONFIG_ISFLAGSET(CONFIG_NOOOPT))) ) {
    // Here the configuration file is the XER encoded UE capabilities
    // Read it in and store in asn1c data structures
    sprintf(uecap_xer,"%stargets/PROJECTS/GENERIC-LTE-EPC/CONF/UE_config.xml",getenv("OPENAIR_HOME"));
    printf("%s\n",uecap_xer);
500
    if(nfapi_mode!=3)
501 502
      uecap_xer_in=1;
  } *//* UE with config file  */
503 504 505 506 507 508 509
}


void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
510
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS));
511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544
    /* Set some default values that may be overwritten while reading options */
    frame_parms[CC_id]->frame_type          = FDD;
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
    frame_parms[CC_id]->Ncp                 = NORMAL;
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = 0;
    frame_parms[CC_id]->num_MBSFN_config    = 0;
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;
    frame_parms[CC_id]->nushift             = 0;
    frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
    frame_parms[CC_id]->phich_config_common.phich_duration = normal;
    // UL RS Config
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;
    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;
    downlink_frequency[CC_id][0] = DEFAULT_DLF; // Use float to avoid issue with frequency over 2^31.
    downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
    downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
    downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
  }
}

545
void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
546 547 548 549 550 551 552
  int card;
  int i;

  for (card=0; card<MAX_CARDS; card++) {
    openair0_cfg[card].mmapped_dma=mmapped_dma;
    openair0_cfg[card].configFilename = NULL;

553 554
    if(frame_parms->N_RB_DL == 100) {
      if (frame_parms->threequarter_fs) {
555 556 557 558
        openair0_cfg[card].sample_rate=23.04e6;
        openair0_cfg[card].samples_per_frame = 230400;
        openair0_cfg[card].tx_bw = 10e6;
        openair0_cfg[card].rx_bw = 10e6;
559
      } else {
560 561 562 563
        openair0_cfg[card].sample_rate=30.72e6;
        openair0_cfg[card].samples_per_frame = 307200;
        openair0_cfg[card].tx_bw = 10e6;
        openair0_cfg[card].rx_bw = 10e6;
564
      }
565
    } else if(frame_parms->N_RB_DL == 50) {
566 567 568 569
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
570
    } else if (frame_parms->N_RB_DL == 25) {
571 572 573 574
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
575
    } else if (frame_parms->N_RB_DL == 6) {
576 577 578 579 580 581
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }

582
    if (frame_parms->frame_type==TDD)
583 584 585 586 587
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    openair0_cfg[card].Mod_id = 0;
588
    openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL;
589
    openair0_cfg[card].clock_source = clock_source;
590 591
    openair0_cfg[card].tx_num_channels=min(2,frame_parms->nb_antennas_tx);
    openair0_cfg[card].rx_num_channels=min(2,frame_parms->nb_antennas_rx);
592 593 594

    for (i=0; i<4; i++) {
      if (i<openair0_cfg[card].tx_num_channels)
595
        openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
596
      else
597
        openair0_cfg[card].tx_freq[i]=0.0;
598 599

      if (i<openair0_cfg[card].rx_num_channels)
600
        openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
601
      else
602
        openair0_cfg[card].rx_freq[i]=0.0;
603 604 605

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
606
      openair0_cfg[card].rx_gain[i] = rxgain - rx_gain_off;
607
      openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
608
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
609 610 611 612
             card,i, openair0_cfg[card].tx_gain[i],
             openair0_cfg[card].rx_gain[i],
             openair0_cfg[card].tx_freq[i],
             openair0_cfg[card].rx_freq[i]);
613
    }
614 615

    if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
616

617 618
    if (usrp_clksrc) {
      if (strcmp(usrp_clksrc, "internal") == 0) {
619 620
        openair0_cfg[card].clock_source = internal;
        LOG_D(PHY, "USRP clock source set as internal\n");
621
      } else if (strcmp(usrp_clksrc, "external") == 0) {
622 623
        openair0_cfg[card].clock_source = external;
        LOG_D(PHY, "USRP clock source set as external\n");
624
      } else if (strcmp(usrp_clksrc, "gpsdo") == 0) {
625 626
        openair0_cfg[card].clock_source = gpsdo;
        LOG_D(PHY, "USRP clock source set as gpsdo\n");
627
      } else {
628 629
        openair0_cfg[card].clock_source = internal;
        LOG_I(PHY, "USRP clock source unknown ('%s'). defaulting to internal\n", usrp_clksrc);
630 631 632
      }
    } else {
      openair0_cfg[card].clock_source = internal;
633
      LOG_I(PHY, "USRP clock source not specified. defaulting to internal\n");
634
    }
635 636 637 638 639 640 641 642 643 644
  }
}




#if defined(ENABLE_ITTI)
/*
 * helper function to terminate a certain ITTI task
 */
645
void terminate_task(task_id_t task_id, module_id_t mod_id) {
646 647 648 649 650 651 652 653 654 655
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
  MessageDef *msg;
  msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
  itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}



#endif

656 657 658 659 660 661 662 663 664 665 666 667 668


static inline void wait_nfapi_init(char *thread_name) {
  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );

  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );

  pthread_mutex_unlock(&nfapi_sync_mutex);
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

669 670
int stop_L1L2(module_id_t enb_id) {
  return 0;
671 672 673
}


674 675
int restart_L1L2(module_id_t enb_id) {
  return 0;
676 677
}

678
int main( int argc, char **argv ) {
679 680 681 682 683
#if defined (XFORMS)
  void *status;
#endif
  int CC_id;
  uint8_t  abstraction_flag=0;
684 685 686 687 688
#ifdef PDCP_USE_NETLINK
#ifdef UESIM_EXPANSION
  memset(inst_pdcp_list, 0, sizeof(inst_pdcp_list));
#endif
#endif
689 690 691
  // Default value for the number of UEs. It will hold,
  // if not changed from the command line option --num-ues
  NB_UE_INST=1;
692
  NB_THREAD_INST=1;
693 694 695
#if defined (XFORMS)
  int ret;
#endif
696 697
  configmodule_interface_t *config_mod;

698 699
  start_background_system();

700 701 702
  config_mod = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);

  if (config_mod == NULL) {
703
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
704
  }
705 706 707 708 709 710 711

  mode = normal_txrx;
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
  set_latency_target();
  logInit();
  printf("Reading in command-line options\n");

712
  for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
713

714
  get_options ();
715
  printf("Running with %d UE instances\n",NB_UE_INST);
716

717
  if (NB_UE_INST > 1 && simL1flag != 1 && nfapi_mode != 3) {
718 719 720
    printf("Running with more than 1 UE instance and simL1 is not active, this will result in undefined behaviour for now, exiting.\n");
    abort();
  }
721

722 723
  printf("NFAPI_MODE value: %d \n", nfapi_mode);

724 725 726 727 728 729 730 731 732 733
  // Checking option of nums_ue_thread.
  if(NB_THREAD_INST < 1){
    printf("Running with 0 UE rxtx thread, exiting.\n");
    abort();
  }
  // Checking option's relation between nums_ue_thread and num-ues
  if(NB_UE_INST <NB_THREAD_INST ){
    printf("Number of UEs < number of UE rxtx threads, exiting.\n");
    abort();
  }
734
  // Not sure if the following is needed here
735 736 737 738 739 740 741 742 743 744
  /*if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
      if (UE_flag == 0) {
        fprintf(stderr,"Getting configuration failed\n");
        exit(-1);
      }
      else {
        printf("Setting nfapi mode to UE_STUB_OFFNET\n");
        nfapi_mode = 4;
      }
    }*/
745 746 747


#if T_TRACER
748
  T_Config_Init();
749 750 751 752
#endif
  //randominit (0);
  set_taus_seed (0);
  cpuf=get_cpu_freq_GHz();
753 754
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
755 756
#if defined(ENABLE_ITTI)
  printf("ITTI init\n");
Cedric Roux's avatar
Cedric Roux committed
757
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
758 759

  // initialize mscgen log after ITTI
760
  if (get_softmodem_params()->start_msc) {
761
    load_module_shlib("msc",NULL,0,&msc_interface);
762
  }
763

764 765
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
#endif
766
  init_opt();
767 768 769 770 771 772 773
#ifdef PDCP_USE_NETLINK
  printf("PDCP netlink\n");
  netlink_init();
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
#endif
774
  //TTN for D2D
775
#if (LTE_RRC_VERSION >= MAKE_VERSION(14, 0, 0))
776 777 778 779 780
  printf ("RRC control socket\n");
  rrc_control_socket_init();
  printf ("PDCP PC5S socket\n");
  pdcp_pc5_socket_init();
#endif
781 782 783
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
784 785
  signal(SIGTERM, signal_handler);
  signal(SIGABRT, signal_handler);
786 787 788 789 790 791 792 793
  check_clock();
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif
  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);

  // init the parameters
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
794 795 796
    frame_parms[CC_id]->nb_antennas_tx     = nb_antenna_tx;
    frame_parms[CC_id]->nb_antennas_rx     = nb_antenna_rx;
    frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
797 798
  }

799
  NB_INST=1;
800

801 802
  if(nfapi_mode == 3) {
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE **)*NB_UE_INST);
803

804 805 806 807
    for (int i=0; i<NB_UE_INST; i++) {
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        PHY_vars_UE_g[i] = malloc(sizeof(PHY_VARS_UE *)*MAX_NUM_CCs);
        PHY_vars_UE_g[i][CC_id] = init_ue_vars(frame_parms[CC_id], i,abstraction_flag);
808

809 810 811 812 813 814 815
        if (get_softmodem_params()->phy_test==1)
          PHY_vars_UE_g[i][CC_id]->mac_enabled = 0;
        else
          PHY_vars_UE_g[i][CC_id]->mac_enabled = 1;
      }
    }
  } else init_openair0(frame_parms[0],(int)rx_gain[0][0]);
816

817
  if (simL1flag==1) {
818
    AssertFatal(NULL!=config_mod,
819 820 821
                "[SOFTMODEM] Error, configuration module init failed\n");
    RCConfig_sim();
  }
822

823 824
// source code written in below moved to later to avoid keeping waiting for nfapi_sync_cond in wait_nfapi_init.
/*
825 826
  // start the main UE threads
  int eMBMS_active = 0;
827

828 829 830 831 832 833 834 835 836
  if (nfapi_mode==3) { // UE-STUB-PNF
    config_sync_var=0;
    wait_nfapi_init("main?");
    //Panos: Temporarily we will be using single set of threads for multiple UEs.
    //init_UE_stub(1,eMBMS_active,uecap_xer_in,emul_iface);
    init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
  } else {
    init_UE(NB_UE_INST,eMBMS_active,uecap_xer_in,0,get_softmodem_params()->phy_test,UE_scan,UE_scan_carrier,mode,(int)rx_gain[0][0],tx_max_power[0],
            frame_parms[0]);
837 838
  }

839
  if (get_softmodem_params()->phy_test==0) {
840 841 842
    printf("Filling UE band info\n");
    fill_ue_band_info();
    dl_phy_sync_success (0, 0, 0, 1);
843
  }
844

845 846 847 848 849 850 851
  if (nfapi_mode!=3) {
    number_of_cards = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
      PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
    }
852
  }
853
*/
854 855
  
  cpuf=get_cpu_freq_GHz();
856 857 858 859 860 861 862 863
#ifndef DEADLINE_SCHEDULER
  printf("NO deadline scheduler\n");
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
#ifdef CPU_AFFINITY
864

865 866 867
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
868

869 870 871 872
    if (s != 0) {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
873

874 875
    LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
  }
876

877 878 879
#endif
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
880

881 882 883 884
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
885

886
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
887

888 889 890 891 892 893 894
  for (int j = 0; j < CPU_SETSIZE; j++) {
    if (CPU_ISSET(j, &cpuset)) {
      char temp[1024];
      sprintf(temp, " CPU_%d ", j);
      strcat(cpu_affinity, temp);
    }
  }
895

896 897 898
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
#endif
#if defined(ENABLE_ITTI)
899
  if (create_tasks_ue(NB_UE_INST) < 0) {
900 901 902
    printf("cannot create ITTI tasks\n");
    exit(-1); // need a softer mode
  }
903

904 905 906 907 908 909
  if(nfapi_mode==3) { // Here we should add another nfapi_mode for the case of Supervised LTE-D2D
    UE_config_stub_pnf();
  }

  printf("ITTI tasks created\n");
#endif
910 911
  mlockall(MCL_CURRENT | MCL_FUTURE);
  rt_sleep_ns(10*100000000ULL);
912
  const char *nfapi_mode_str = "<UNKNOWN>";
913 914
  // start the main UE threads
  int eMBMS_active = 0;
915

916 917 918 919 920 921 922 923
  switch(nfapi_mode) {
    case 0:
      nfapi_mode_str = "MONOLITHIC";
      break;

    case 1:
      nfapi_mode_str = "PNF";
      break;
924

925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940
    case 2:
      nfapi_mode_str = "VNF";
      break;

    case 3:
      nfapi_mode_str = "UE_STUB_PNF";
      break;

    case 4:
      nfapi_mode_str = "UE_STUB_OFFNET";
      break;

    default:
      nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
      break;
  }
941

942
  printf("NFAPI MODE:%s\n", nfapi_mode_str);
943

944 945 946 947 948 949 950 951 952
  if (nfapi_mode==3) // UE-STUB-PNF
  {
      config_sync_var=0;
      wait_nfapi_init("main?");
      //Panos: Temporarily we will be using single set of threads for multiple UEs.
      //init_UE_stub(1,eMBMS_active,uecap_xer_in,emul_iface);
      init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
  }
  else {
Raphael Defosseux's avatar
Raphael Defosseux committed
953
      init_UE(NB_UE_INST,eMBMS_active,uecap_xer_in,0,get_softmodem_params()->phy_test,UE_scan,UE_scan_carrier,mode,(int)rx_gain[0][0],tx_max_power[0],
954 955 956 957
              frame_parms[0]);
  }


Raphael Defosseux's avatar
Raphael Defosseux committed
958
  if (get_softmodem_params()->phy_test==0) {
959 960 961 962 963 964 965 966 967
    printf("Filling UE band info\n");
    fill_ue_band_info();
    dl_phy_sync_success (0, 0, 0, 1);
  }

  if (nfapi_mode!=3){
      number_of_cards = 1;
      for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
              PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
Raphael Defosseux's avatar
Raphael Defosseux committed
968
              PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
969 970
      }
  }
971 972
  // connect the TX/RX buffers

973 974 975 976 977
  /*
  if(nfapi_mode!=3) {
    if (setup_ue_buffers(PHY_vars_UE_g[0],&openair0_cfg[0])!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
978
    }
979 980
  }
  */
981

982 983 984 985 986 987 988 989
  if (input_fd) {
    printf("Reading in from file to antenna buffer %d\n",0);

    if (fread(PHY_vars_UE_g[0][0]->common_vars.rxdata[0],
              sizeof(int32_t),
              frame_parms[0]->samples_per_tti*10,
              input_fd) != frame_parms[0]->samples_per_tti*10)
      printf("error reading from file\n");
knopp's avatar
knopp committed
990
  }
991

992 993 994 995 996 997
  //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;

  if (simL1flag==1)  {
    init_ocm((double)snr_dB,0);
    PHY_vars_UE_g[0][0]->no_timing_correction = 1;
  }
998

999 1000 1001 1002
#ifdef XFORMS
  int UE_id;
  printf("XFORMS\n");

1003
  if (get_softmodem_params()->do_forms==1) {
1004
    fl_initialize (&argc, argv, NULL, 0, 0);
1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018 1019 1020
    form_stats = create_form_stats_form();
    fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
    UE_id = 0;
    form_ue[UE_id] = create_lte_phy_scope_ue();
    sprintf (title, "LTE DL SCOPE UE");
    fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
    /*
    if (openair_daq_vars.use_ia_receiver) {
    fl_set_button(form_ue[UE_id]->button_0,1);
    fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON");
    } else {
    fl_set_button(form_ue[UE_id]->button_0,0);
    fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
    }*/
    fl_set_button(form_ue[UE_id]->button_0,0);
    fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
1021
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
1022

1023 1024
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
1025

1026 1027
    printf("Scope thread created, ret=%d\n",ret);
  }
1028

1029
#endif
1030
  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
1031
  printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
1032 1033 1034 1035
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
1036
  printf("sync sent\n");
1037 1038 1039 1040 1041
  /*
    printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
    end_configmodule();
    printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
  */
1042 1043 1044 1045 1046 1047 1048 1049 1050 1051 1052
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
#if defined(ENABLE_ITTI)
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
  printf("Returned from ITTI signal handler\n");
  oai_exit=1;
  printf("oai_exit=%d\n",oai_exit);
#else

1053 1054
  while (oai_exit==0)
    rt_sleep_ns(100000000ULL);
1055

1056
  printf("Terminating application - oai_exit=%d\n",oai_exit);
1057 1058 1059 1060 1061
#endif
  // stop threads
#ifdef XFORMS
  printf("waiting for XFORMS thread\n");

1062
  if (get_softmodem_params()->do_forms==1) {
1063 1064 1065 1066 1067 1068 1069 1070 1071 1072 1073 1074
    pthread_join(forms_thread,&status);
    fl_hide_form(form_stats->stats_form);
    fl_free_form(form_stats->stats_form);
    fl_hide_form(form_ue[0]->lte_phy_scope_ue);
    fl_free_form(form_ue[0]->lte_phy_scope_ue);
  }

#endif
  printf("stopping MODEM threads\n");
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);

1075
  //  pthread_mutex_destroy(&ue_pf_po_mutex);
1076 1077 1078 1079

  // *** Handle per CC_id openair0
  if (PHY_vars_UE_g[0][0]->rfdevice.trx_end_func)
    PHY_vars_UE_g[0][0]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][0]->rfdevice);
1080

1081
  terminate_opt();
1082
  logClean();
1083 1084 1085
  printf("Bye.\n");
  return 0;
}