lte-uesoftmodem.c 26.3 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
 * \brief Top-level threads for eNodeB
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: {knopp, florian.kaltenberger, navid.nikaein}@eurecom.fr
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46
 * \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
#include "PHY/TOOLS/phy_scope_interface.h"
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
#endif

#include "system.h"

88

89 90
#include "lte-softmodem.h"

91

92 93
/* temporary compilation wokaround (UE/eNB split */
uint16_t sf_ahead;
94

95

96 97 98 99 100
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex


101
#ifdef UESIM_EXPANSION
102
  uint16_t inst_pdcp_list[NUMBER_OF_UE_MAX];
103
#endif
104
uint16_t sf_ahead=2;
Y_Tomita's avatar
Y_Tomita committed
105
int tddflag;
106 107 108
char *emul_iface;


109 110 111 112 113 114 115 116 117 118
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;

119

120
clock_source_t clock_source = internal,time_source=internal;
121

122 123 124 125 126 127 128 129 130 131 132

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
133

134 135 136
runmode_t mode = normal_txrx;

FILE *input_fd=NULL;
137
int otg_enabled=0;
138 139 140 141

#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}};
142
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0}};
143 144 145
#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}};
146
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0},{20,0,0,0}};
147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170
#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;



static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
171

172 173 174
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots

175
// prototypes from function implemented in lte-ue.c, probably should be elsewhere in a include file.
176
extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
177
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
178
extern void get_uethreads_params(void);
179 180 181 182

int transmission_mode=1;


183 184
char *usrp_args=NULL;
char *usrp_clksrc=NULL;
185

laurent's avatar
laurent committed
186
THREAD_STRUCT thread_struct;
187 188 189 190 191 192 193 194 195 196 197
/* 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;
198
//threads_t threads= {-1,-1,-1,-1,-1,-1,-1,-1};
199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214

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

216 217 218 219 220 221 222
  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;
  }
223

224 225 226 227 228 229 230 231 232 233 234 235 236 237 238
  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);
239

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

245 246 247 248
  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;
  }
249

250
#if 1
251

252
  if (changed) print_difftimes();
253

254 255 256 257 258 259 260 261 262 263 264 265
#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));
}

266 267


268 269 270 271 272 273 274 275 276 277 278 279
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 {
280 281 282
    char msg[64];
    sprintf(msg,"Received linux signal %s...\n",strsignal(sig));
    exit_function(__FILE__, __FUNCTION__, __LINE__,msg);
283 284 285 286
  }
}


287
void exit_function(const char *file, const char *function, const int line, const char *s) {
288
  int CC_id;
289
  logClean();
290
  printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, ((s==NULL)?"":s));
291 292 293
  oai_exit = 1;

  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
294
    if (PHY_vars_UE_g)
295
      if (PHY_vars_UE_g[0])
296 297 298 299
        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);
  }
300

301 302 303
  sleep(1); //allow lte-softmodem threads to exit first

  if(PHY_vars_UE_g != NULL )
304
    itti_terminate_tasks (TASK_UNKNOWN);
305

306
  exit(1);
307 308
}

309
extern int16_t dlsch_demod_shift;
310

311
static void get_options(void) {
312
  int CC_id;
Cedric Roux's avatar
Cedric Roux committed
313 314 315 316 317 318
  int tddflag = 0;
  char *loopfile = NULL;
  int dumpframe = 0;
  int timingadv = 0;
  uint8_t nfapi_mode = NFAPI_MONOLITHIC;
  int simL1flag = 0;
319 320

  set_default_frame_parms(frame_parms);
321
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
322 323
  /* unknown parameters on command line will be checked in main
     after all init have been performed                         */
324 325
  get_common_options();
  get_uethreads_params();
326 327 328 329
  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
330 331 332 333
  nfapi_setmode(nfapi_mode);

  if (simL1flag)
    set_softmodem_optmask(SOFTMODEM_SIML1_BIT);
334

335
  if (loopfile != NULL) {
336 337 338 339
    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");
340 341
  }

342
  get_softmodem_params()->hw_timing_advance = timingadv;
343

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

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

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

350
  if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr)
351 352
    if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;

353
  if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr)
354 355 356 357 358
    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;

359
  if (dumpframe  > 0)  mode = rx_dump_frame;
360

361 362 363
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
  }
364

365
  UE_scan=0;
frtabu's avatar
frtabu committed
366

367
  if (tddflag > 0) {
368
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
369
      frame_parms[CC_id]->frame_type = TDD;
370 371
      frame_parms[CC_id]->tdd_config = tddflag;
    }
372 373 374
  }

  if (frame_parms[0]->N_RB_DL !=0) {
375 376 377 378
    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);
    }
379

380 381 382 383
    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);
    }
384

385 386 387 388
    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);
    }
389

390 391 392 393
    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);
    }
394

395 396
    UE_scan = 0;
    frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
397

398 399 400 401
    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;
    }
402 403
  }

404 405 406
  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];
407 408 409 410 411 412 413 414
  }
}


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++) {
415
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) calloc(1, sizeof(LTE_DL_FRAME_PARMS));
416 417 418 419 420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439 440 441 442 443 444 445 446 447 448 449
    /* 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];
  }
}

450
void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
451 452 453 454 455 456 457
  int card;
  int i;

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

458 459
    if(frame_parms->N_RB_DL == 100) {
      if (frame_parms->threequarter_fs) {
460 461 462 463
        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;
464
      } else {
465 466 467 468
        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;
469
      }
470
    } else if(frame_parms->N_RB_DL == 50) {
471 472 473 474
      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;
475
    } else if (frame_parms->N_RB_DL == 25) {
476 477 478 479
      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;
480
    } else if (frame_parms->N_RB_DL == 6) {
481 482 483 484 485 486
      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;
    }

487
    if (frame_parms->frame_type==TDD)
488 489 490 491 492
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    openair0_cfg[card].Mod_id = 0;
493
    openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL;
494
    openair0_cfg[card].clock_source = clock_source;
495 496
    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);
497 498 499

    for (i=0; i<4; i++) {
      if (i<openair0_cfg[card].tx_num_channels)
500
        openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
501
      else
502
        openair0_cfg[card].tx_freq[i]=0.0;
503 504

      if (i<openair0_cfg[card].rx_num_channels)
505
        openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
506
      else
507
        openair0_cfg[card].rx_freq[i]=0.0;
508 509 510

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
511
      openair0_cfg[card].rx_gain[i] = rxgain - rx_gain_off;
512
      openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
513
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
514 515 516 517
             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]);
518
    }
519 520

    if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
521 522 523 524 525
  }
}



frtabu's avatar
frtabu committed
526
/* helper function to terminate a certain ITTI task
527
 */
528
void terminate_task(task_id_t task_id, module_id_t mod_id) {
529 530 531 532 533 534 535
  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);
}


536 537 538 539 540 541 542 543 544 545 546
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);
}

547 548
int stop_L1L2(module_id_t enb_id) {
  return 0;
549 550 551
}


552 553
int restart_L1L2(module_id_t enb_id) {
  return 0;
554 555
}

556 557 558 559 560 561 562 563 564 565 566
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);
567 568
  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);
569 570
}

571
int main( int argc, char **argv ) {
572 573
  int CC_id;
  uint8_t  abstraction_flag=0;
574 575 576
#ifdef UESIM_EXPANSION
  memset(inst_pdcp_list, 0, sizeof(inst_pdcp_list));
#endif
577 578 579
  // Default value for the number of UEs. It will hold,
  // if not changed from the command line option --num-ues
  NB_UE_INST=1;
580
  NB_THREAD_INST=1;
581
  configmodule_interface_t *config_mod;
582
  start_background_system();
583
  config_mod = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);
584

585
  if (config_mod == NULL) {
586
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
587
  }
588

589 590 591 592 593 594
  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");

595
  for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
596

597
  get_options ();
598

599 600
  if (is_nos1exec(argv[0]) )
    set_softmodem_optmask(SOFTMODEM_NOS1_BIT);
601

602
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
603
  printf("Running with %d UE instances\n",NB_UE_INST);
604

frtabu's avatar
frtabu committed
605
  if (NB_UE_INST > 1 && (!IS_SOFTMODEM_SIML1)  && NFAPI_MODE!=NFAPI_UE_STUB_PNF) {
606 607 608
    printf("Running with more than 1 UE instance and simL1 is not active, this will result in undefined behaviour for now, exiting.\n");
    abort();
  }
609

610
  // Checking option of nums_ue_thread.
611
  if(NB_THREAD_INST < 1) {
612 613 614
    printf("Running with 0 UE rxtx thread, exiting.\n");
    abort();
  }
615

616
  // Checking option's relation between nums_ue_thread and num-ues
617
  if(NB_UE_INST <NB_THREAD_INST ) {
618 619 620
    printf("Number of UEs < number of UE rxtx threads, exiting.\n");
    abort();
  }
621 622

#if T_TRACER
623
  T_Config_Init();
624 625 626 627
#endif
  //randominit (0);
  set_taus_seed (0);
  cpuf=get_cpu_freq_GHz();
628 629 630
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);

631
  printf("ITTI init\n");
Cedric Roux's avatar
Cedric Roux committed
632
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info);
633 634

  // initialize mscgen log after ITTI
635
  if (get_softmodem_params()->start_msc) {
636
    load_module_shlib("msc",NULL,0,&msc_interface);
637
  }
638 639

  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
640
  init_opt();
641
  init_pdcp();
642
  //TTN for D2D
643 644 645 646
  printf ("RRC control socket\n");
  rrc_control_socket_init();
  printf ("PDCP PC5S socket\n");
  pdcp_pc5_socket_init();
647 648 649
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
650 651
  signal(SIGTERM, signal_handler);
  signal(SIGABRT, signal_handler);
652 653 654 655 656 657 658 659
  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++) {
660 661 662
    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
663 664
  }

665 666
  NB_INST=1;

frtabu's avatar
frtabu committed
667
  if(NFAPI_MODE==NFAPI_UE_STUB_PNF) {
668
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE **)*NB_UE_INST);
669

670 671 672 673
    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);
674

675 676 677 678
        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;
679
      }
680 681
    }
  } else init_openair0(frame_parms[0],(int)rx_gain[0][0]);
682

frtabu's avatar
frtabu committed
683
  if (IS_SOFTMODEM_SIML1 ) {
684
    RCConfig_sim();
685
  }
686 687

  cpuf=get_cpu_freq_GHz();
688 689
  
  
laurent's avatar
laurent committed
690
#if 0 // #ifndef DEADLINE_SCHEDULER
691 692 693 694 695 696 697 698
  
  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
Florian Kaltenberger's avatar
Florian Kaltenberger committed
699
  int j;
700
  if (get_nprocs() > 2) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
701 702 703
    for (j = 2; j < get_nprocs(); j++)
      CPU_SET(j, &cpuset);
    
704
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
705

706 707 708 709
    if (s != 0) {
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
    }
Florian Kaltenberger's avatar
Florian Kaltenberger committed
710
    LOG_I(HW, "Setting the affinity of main function to all CPUs, for device library to use CPU 0 only!\n");
711
  }
712

713 714 715
#endif
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
716

717 718 719 720
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
721

722
  memset(cpu_affinity, 0, sizeof(cpu_affinity));
723

724 725 726 727 728 729 730
  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);
    }
  }
731

732 733 734
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
#endif

735
  if (create_tasks_ue(NB_UE_INST) < 0) {
736 737 738
    printf("cannot create ITTI tasks\n");
    exit(-1); // need a softer mode
  }
739

frtabu's avatar
frtabu committed
740
  if (NFAPI_MODE==NFAPI_UE_STUB_PNF) { // UE-STUB-PNF
741 742 743 744
    UE_config_stub_pnf();
  }

  printf("ITTI tasks created\n");
745 746
  mlockall(MCL_CURRENT | MCL_FUTURE);
  rt_sleep_ns(10*100000000ULL);
747
  int eMBMS_active = 0;
748

frtabu's avatar
frtabu committed
749 750 751 752 753 754
  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);
755
  } else {
frtabu's avatar
frtabu committed
756 757
    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]);
758
  }
759

Raphael Defosseux's avatar
Raphael Defosseux committed
760
  if (get_softmodem_params()->phy_test==0) {
761 762 763 764
    printf("Filling UE band info\n");
    fill_ue_band_info();
    dl_phy_sync_success (0, 0, 0, 1);
  }
765

frtabu's avatar
frtabu committed
766 767
  if (NFAPI_MODE != NFAPI_UE_STUB_PNF) {
    number_of_cards = 1;
768

frtabu's avatar
frtabu committed
769 770 771
    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);
772
    }
773
  }
774

775 776
  if (input_fd) {
    printf("Reading in from file to antenna buffer %d\n",0);
777

778 779 780 781 782
    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");
783
  }
784

785 786
  //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;

frtabu's avatar
frtabu committed
787
  if (IS_SOFTMODEM_SIML1 )  {
788
    init_ocm();
789 790
    PHY_vars_UE_g[0][0]->no_timing_correction = 1;
  }
791

792 793
  if(IS_SOFTMODEM_DOFORMS)
    load_softscope("ue");
794

795
  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
796
  printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
797 798 799 800
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
801
  printf("sync sent\n");
802 803 804 805 806
  /*
    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__);
  */
807 808 809 810 811 812 813 814 815 816 817
  // 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

818 819
  while (oai_exit==0)
    rt_sleep_ns(100000000ULL);
820

821
  printf("Terminating application - oai_exit=%d\n",oai_exit);
822
#endif
823

824
  // stop threads
825 826
  if(IS_SOFTMODEM_DOFORMS)
    end_forms();
827 828 829 830 831

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

832
  //  pthread_mutex_destroy(&ue_pf_po_mutex);
833 834 835 836 837

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

838
  terminate_opt();
839
  logClean();
840 841 842
  printf("Bye.\n");
  return 0;
}