lte-uesoftmodem.c 33 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 818 819
  if (simL1flag==1) {
    RCConfig_sim();
  }
820

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

826 827 828 829 830 831 832 833 834
  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]);
835 836
  }

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

843 844 845 846 847 848 849
  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);
    }
850
  }
851
*/
852 853
  
  cpuf=get_cpu_freq_GHz();
854 855 856 857 858 859 860 861
#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
862

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

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

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

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

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

884
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
885

886 887 888 889 890 891 892
  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);
    }
  }
893

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

902 903 904 905 906 907
  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
908 909
  mlockall(MCL_CURRENT | MCL_FUTURE);
  rt_sleep_ns(10*100000000ULL);
910
  const char *nfapi_mode_str = "<UNKNOWN>";
911 912
  // start the main UE threads
  int eMBMS_active = 0;
913

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

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

923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938
    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;
  }
939

940
  printf("NFAPI MODE:%s\n", nfapi_mode_str);
941

942 943 944 945 946 947 948 949 950
  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
951
      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],
952 953 954 955
              frame_parms[0]);
  }


Raphael Defosseux's avatar
Raphael Defosseux committed
956
  if (get_softmodem_params()->phy_test==0) {
957 958 959 960 961 962 963 964 965
    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
966
              PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+(get_softmodem_params()->chain_offset);
967 968
      }
  }
969 970
  // connect the TX/RX buffers

971 972 973 974 975
  /*
  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);
976
    }
977 978
  }
  */
979

980 981 982 983 984 985 986 987
  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
988
  }
989

990 991 992 993 994 995
  //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;
  }
996

997 998 999 1000
#ifdef XFORMS
  int UE_id;
  printf("XFORMS\n");

1001
  if (get_softmodem_params()->do_forms==1) {
1002
    fl_initialize (&argc, argv, NULL, 0, 0);
1003 1004 1005 1006 1007 1008 1009 1010 1011 1012 1013 1014 1015 1016 1017 1018
    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");
1019
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
1020

1021 1022
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
1023

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

1027
#endif
1028
  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
1029
  printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
1030 1031 1032 1033
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
1034
  printf("sync sent\n");
1035 1036 1037 1038 1039
  /*
    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__);
  */
1040 1041 1042 1043 1044 1045 1046 1047 1048 1049 1050
  // 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

1051 1052
  while (oai_exit==0)
    rt_sleep_ns(100000000ULL);
1053

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

1060
  if (get_softmodem_params()->do_forms==1) {
1061 1062 1063 1064 1065 1066 1067 1068 1069 1070 1071 1072
    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);

1073
  //  pthread_mutex_destroy(&ue_pf_po_mutex);
1074 1075 1076 1077

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

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