lte-uesoftmodem.c 30.9 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"
frtabu's avatar
frtabu committed
71
#include "nfapi/oai_integration/vendor_ext.h"
72 73 74
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
75
#include "common/utils/LOG/vcd_signal_dumper.h"
76 77 78
#include "UTIL/OPT/opt.h"

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

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

#include "system.h"

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

94

95

96 97 98
/* temporary compilation wokaround (UE/eNB split */
uint16_t sf_ahead;
#ifdef XFORMS
99 100 101 102 103 104 105 106
  // 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
107 108
#endif //XFORMS

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

frtabu's avatar
frtabu committed
113

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


122 123 124 125 126 127 128 129 130 131
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
132
clock_source_t clock_source = internal;
133

134 135 136 137 138 139 140 141 142 143 144

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;
frtabu's avatar
frtabu committed
145

146
int snr_dB=25;
knopp's avatar
knopp committed
147

148 149 150 151 152 153 154 155
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}};
156
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0}};
157 158 159
#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}};
160
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0},{20,0,0,0}};
161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182
#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
183
  extern int                      otg_enabled;
184 185 186 187 188
#endif
//int                             number_of_cards =   1;


static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
189

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

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

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

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

int transmission_mode=1;


206 207
char *usrp_args=NULL;
char *usrp_clksrc=NULL;
208

209
THREAD_STRUCT thread_struct;
210 211 212 213 214 215 216 217 218 219 220
/* 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;
221

222 223 224 225 226 227 228 229 230 231 232 233 234 235 236 237

/* 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;
238

239 240 241 242 243 244 245
  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;
  }
246

247 248 249 250 251 252 253 254 255 256 257 258 259 260 261
  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);
262

263 264 265 266
  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;
  }
267

268 269 270 271
  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;
  }
272

273
#if 1
274

275
  if (changed) print_difftimes();
276

277 278 279 280 281 282 283 284 285 286 287 288
#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));
}

289 290


291 292 293 294 295 296 297 298 299 300 301 302
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 {
303 304 305
    char msg[64];
    sprintf(msg,"Received linux signal %s...\n",strsignal(sig));
    exit_function(__FILE__, __FUNCTION__, __LINE__,msg);
306 307 308 309
  }
}


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

  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
317
    if (PHY_vars_UE_g)
318
      if (PHY_vars_UE_g[0])
319 320 321 322
        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);
  }
323

324 325 326
  sleep(1); //allow lte-softmodem threads to exit first

  if(PHY_vars_UE_g != NULL )
327
    itti_terminate_tasks (TASK_UNKNOWN);
328

329
  exit(1);
330 331 332 333 334
}

#ifdef XFORMS


335
void reset_stats(FL_OBJECT *button, long arg) {
336 337 338 339 340 341
  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++) {
342 343 344
        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;
345 346 347 348 349 350 351 352 353 354 355 356 357 358 359 360 361 362 363 364 365 366 367 368 369 370
      }

      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) {
371
    //      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);
372 373 374 375 376 377 378 379 380
    //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);
  }
381 382 383

# ifdef ENABLE_XFORMS_WRITE_STATS

384 385 386 387 388
  if (UE_stats) {
    rewind (UE_stats);
    fwrite (stats_buffer, 1, len, UE_stats);
    fclose (UE_stats);
  }
389 390

# endif
391
  pthread_exit((void *)arg);
392 393 394 395 396
}
#endif



397
extern int16_t dlsch_demod_shift;
398

399
static void get_options(void) {
400
  int CC_id;
401
  int tddflag;
402 403
  char *loopfile=NULL;
  int dumpframe;
404
  int timingadv;
frtabu's avatar
frtabu committed
405 406
  uint8_t nfapi_mode;
  int simL1flag ;
407
  set_default_frame_parms(frame_parms);
408
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
409 410
  /* unknown parameters on command line will be checked in main
     after all init have been performed                         */
411 412
  get_common_options();
  get_uethreads_params();
413 414 415 416
  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);
frtabu's avatar
frtabu committed
417 418 419 420
  nfapi_setmode(nfapi_mode);

  if (simL1flag)
    set_softmodem_optmask(SOFTMODEM_SIML1_BIT);
421

422
  if (loopfile != NULL) {
423 424 425 426
    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");
427 428
  }

429
  get_softmodem_params()->hw_timing_advance = timingadv;
430

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

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

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

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

440
  if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr)
441 442 443 444 445
    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;

446
  if (dumpframe  > 0)  mode = rx_dump_frame;
447

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

452
  UE_scan=0;
frtabu's avatar
frtabu committed
453

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

  if (frame_parms[0]->N_RB_DL !=0) {
462 463 464 465
    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);
    }
466

467 468 469 470
    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);
    }
471

472 473 474 475
    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);
    }
476

477 478 479 480
    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);
    }
481

482 483 484 485 486 487 488 489 490 491 492 493
    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];
494 495 496 497 498 499 500 501
  }
}


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++) {
502
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) malloc(sizeof(LTE_DL_FRAME_PARMS));
503 504 505 506 507 508 509 510 511 512 513 514 515 516 517 518 519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536
    /* 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];
  }
}

537
void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
538 539 540 541 542 543 544
  int card;
  int i;

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

545 546
    if(frame_parms->N_RB_DL == 100) {
      if (frame_parms->threequarter_fs) {
547 548 549 550
        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;
551
      } else {
552 553 554 555
        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;
556
      }
557
    } else if(frame_parms->N_RB_DL == 50) {
558 559 560 561
      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;
562
    } else if (frame_parms->N_RB_DL == 25) {
563 564 565 566
      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;
567
    } else if (frame_parms->N_RB_DL == 6) {
568 569 570 571 572 573
      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;
    }

574
    if (frame_parms->frame_type==TDD)
575 576 577 578 579
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    openair0_cfg[card].Mod_id = 0;
580
    openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL;
581
    openair0_cfg[card].clock_source = clock_source;
582 583
    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);
584 585 586

    for (i=0; i<4; i++) {
      if (i<openair0_cfg[card].tx_num_channels)
587
        openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
588
      else
589
        openair0_cfg[card].tx_freq[i]=0.0;
590 591

      if (i<openair0_cfg[card].rx_num_channels)
592
        openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
593
      else
594
        openair0_cfg[card].rx_freq[i]=0.0;
595 596 597

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
598
      openair0_cfg[card].rx_gain[i] = rxgain - rx_gain_off;
599
      openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
600
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
601 602 603 604
             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]);
605
    }
606 607

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

609 610
    if (usrp_clksrc) {
      if (strcmp(usrp_clksrc, "internal") == 0) {
611 612
        openair0_cfg[card].clock_source = internal;
        LOG_D(PHY, "USRP clock source set as internal\n");
613
      } else if (strcmp(usrp_clksrc, "external") == 0) {
614 615
        openair0_cfg[card].clock_source = external;
        LOG_D(PHY, "USRP clock source set as external\n");
616
      } else if (strcmp(usrp_clksrc, "gpsdo") == 0) {
617 618
        openair0_cfg[card].clock_source = gpsdo;
        LOG_D(PHY, "USRP clock source set as gpsdo\n");
619
      } else {
620 621
        openair0_cfg[card].clock_source = internal;
        LOG_I(PHY, "USRP clock source unknown ('%s'). defaulting to internal\n", usrp_clksrc);
622 623 624
      }
    } else {
      openair0_cfg[card].clock_source = internal;
625
      LOG_I(PHY, "USRP clock source not specified. defaulting to internal\n");
626
    }
627 628 629 630 631
  }
}



frtabu's avatar
frtabu committed
632
/* helper function to terminate a certain ITTI task
633
 */
634
void terminate_task(task_id_t task_id, module_id_t mod_id) {
635 636 637 638 639 640 641
  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);
}


642 643 644 645 646 647 648 649 650 651 652
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);
}

653 654
int stop_L1L2(module_id_t enb_id) {
  return 0;
655 656 657
}


658 659
int restart_L1L2(module_id_t enb_id) {
  return 0;
660 661
}

662 663 664 665 666 667 668 669 670 671 672
void init_pdcp(void) {
  uint32_t pdcp_initmask = (!IS_SOFTMODEM_NOS1) ? LINK_ENB_PDCP_TO_GTPV1U_BIT : (LINK_ENB_PDCP_TO_GTPV1U_BIT | PDCP_USE_NETLINK_BIT | LINK_ENB_PDCP_TO_IP_DRIVER_BIT);

  if (IS_SOFTMODEM_BASICSIM || IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
  }

  if (IS_SOFTMODEM_NOKRNMOD)
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;

  pdcp_module_init(pdcp_initmask);
673 674
  pdcp_set_rlc_data_req_func((send_rlc_data_req_func_t) rlc_data_req);
  pdcp_set_pdcp_data_ind_func((pdcp_data_ind_func_t) pdcp_data_ind);
675 676
}

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

  if (config_mod == NULL) {
698
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
699
  }
700 701 702 703 704 705 706

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

707
  for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
708

709
  get_options ();
710

711 712
  if (is_nos1exec(argv[0]) )
    set_softmodem_optmask(SOFTMODEM_NOS1_BIT);
713

714
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
715
  printf("Running with %d UE instances\n",NB_UE_INST);
716

frtabu's avatar
frtabu committed
717
  if (NB_UE_INST > 1 && (!IS_SOFTMODEM_SIML1)  && NFAPI_MODE!=NFAPI_UE_STUB_PNF) {
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
  // Checking option of nums_ue_thread.
723
  if(NB_THREAD_INST < 1) {
724 725 726
    printf("Running with 0 UE rxtx thread, exiting.\n");
    abort();
  }
727

728
  // Checking option's relation between nums_ue_thread and num-ues
729
  if(NB_UE_INST <NB_THREAD_INST ) {
730 731 732
    printf("Number of UEs < number of UE rxtx threads, exiting.\n");
    abort();
  }
733

734
#if T_TRACER
735
  T_Config_Init();
736 737 738 739
#endif
  //randominit (0);
  set_taus_seed (0);
  cpuf=get_cpu_freq_GHz();
740 741
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
742
  printf("ITTI init\n");
Cedric Roux's avatar
Cedric Roux committed
743
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
744 745

  // initialize mscgen log after ITTI
746
  if (get_softmodem_params()->start_msc) {
747
    load_module_shlib("msc",NULL,0,&msc_interface);
748
  }
749

750
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
751
  init_opt();
752

753
  init_pdcp();
754

755
  //TTN for D2D
756 757 758 759
  printf ("RRC control socket\n");
  rrc_control_socket_init();
  printf ("PDCP PC5S socket\n");
  pdcp_pc5_socket_init();
760 761 762
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
763 764
  signal(SIGTERM, signal_handler);
  signal(SIGABRT, signal_handler);
765 766 767 768 769 770 771 772
  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++) {
773 774 775
    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
776 777
  }

778
  NB_INST=1;
779

frtabu's avatar
frtabu committed
780
  if(NFAPI_MODE==NFAPI_UE_STUB_PNF) {
781
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE **)*NB_UE_INST);
782

783 784 785 786
    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);
787

788 789 790 791 792 793 794
        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]);
795

frtabu's avatar
frtabu committed
796
  if (IS_SOFTMODEM_SIML1 ) {
797 798
    RCConfig_sim();
  }
799

800
  cpuf=get_cpu_freq_GHz();
801 802 803 804 805 806 807 808
#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
809

810 811 812
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
813

814 815 816 817
    if (s != 0) {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
818

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

822 823 824
#endif
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
825

826 827 828 829
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
830

831
  memset(cpu_affinity, 0, sizeof(cpu_affinity));
832

833 834 835 836 837 838 839
  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);
    }
  }
840

841 842
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
#endif
843

844
  if (create_tasks_ue(NB_UE_INST) < 0) {
845 846 847
    printf("cannot create ITTI tasks\n");
    exit(-1); // need a softer mode
  }
848

frtabu's avatar
frtabu committed
849
  if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { // UE-STUB-PNF
850 851 852 853
    UE_config_stub_pnf();
  }

  printf("ITTI tasks created\n");
854 855
  mlockall(MCL_CURRENT | MCL_FUTURE);
  rt_sleep_ns(10*100000000ULL);
856
  int eMBMS_active = 0;
857

frtabu's avatar
frtabu committed
858 859 860 861 862 863
  if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { // 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);
864
  } else {
frtabu's avatar
frtabu committed
865 866
    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]);
867 868
  }

Raphael Defosseux's avatar
Raphael Defosseux committed
869
  if (get_softmodem_params()->phy_test==0) {
870 871 872 873
    printf("Filling UE band info\n");
    fill_ue_band_info();
    dl_phy_sync_success (0, 0, 0, 1);
  }
874

frtabu's avatar
frtabu committed
875 876
  if (NFAPI_MODE != NFAPI_UE_STUB_PNF) {
    number_of_cards = 1;
877

frtabu's avatar
frtabu committed
878 879 880
    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);
881
    }
882
  }
883

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

894 895
  //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;

frtabu's avatar
frtabu committed
896
  if (IS_SOFTMODEM_SIML1 )  {
897 898 899
    init_ocm((double)snr_dB,0);
    PHY_vars_UE_g[0][0]->no_timing_correction = 1;
  }
900

901 902 903 904
#ifdef XFORMS
  int UE_id;
  printf("XFORMS\n");

905
  if (get_softmodem_params()->do_forms==1) {
906
    fl_initialize (&argc, argv, NULL, 0, 0);
907 908 909 910 911 912 913 914 915 916 917 918 919 920 921 922
    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");
923
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
924

925 926
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
927

928 929
    printf("Scope thread created, ret=%d\n",ret);
  }
930

931
#endif
932
  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
933
  printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
934 935 936 937
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
938
  printf("sync sent\n");
939 940 941 942 943
  /*
    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__);
  */
944 945 946 947 948 949 950 951 952 953 954
  // 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

955 956
  while (oai_exit==0)
    rt_sleep_ns(100000000ULL);
957

958
  printf("Terminating application - oai_exit=%d\n",oai_exit);
959 960 961 962 963
#endif
  // stop threads
#ifdef XFORMS
  printf("waiting for XFORMS thread\n");

964
  if (get_softmodem_params()->do_forms==1) {
965 966 967 968 969 970 971 972 973 974 975 976
    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);

977
  //  pthread_mutex_destroy(&ue_pf_po_mutex);
978 979 980 981 982

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

983
  terminate_opt();
984
  logClean();
985 986 987
  printf("Bye.\n");
  return 0;
}