lte-uesoftmodem.c 25.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
 * \note
 * \warning
 */


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

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

#include "assertions.h"

#include "PHY/types.h"
42
#include "pdcp.h"
43

44
#include "PHY/defs_UE.h"
45 46 47 48 49 50
#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

francescomani's avatar
francescomani committed
51 52
#include "radio/COMMON/common_lib.h"
#include "radio/ETHERNET/USERSPACE/LIB/if_defs.h"
53 54 55

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

56 57
#include "PHY/phy_vars_ue.h"
#include "PHY/LTE_TRANSPORT/transport_vars.h"
58

59 60 61 62
#include "LAYER2/MAC/mac.h"
#include "LAYER2/MAC/mac_proto.h"
#include "RRC/LTE/rrc_vars.h"
#include "PHY_INTERFACE/phy_interface_vars.h"
Michael Cook's avatar
Michael Cook committed
63
#include "PHY_INTERFACE/phy_stub_UE.h"
64
#include "PHY/TOOLS/phy_scope_interface.h"
65
#include "common/utils/LOG/log.h"
frtabu's avatar
frtabu committed
66
#include "nfapi/oai_integration/vendor_ext.h"
67 68 69
#include "UTIL/OTG/otg_tx.h"
#include "UTIL/OTG/otg_externs.h"
#include "UTIL/MATH/oml.h"
70
#include "common/utils/LOG/vcd_signal_dumper.h"
71 72
#include "UTIL/OPT/opt.h"

73
#include "create_tasks.h"
74 75 76
#include "system.h"

#include "lte-softmodem.h"
77
#include "executables/softmodem-common.h"
78

79
/* temporary compilation wokaround (UE/eNB split */
80

81

82 83 84 85 86
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex


87
uint16_t sf_ahead=4;
Y_Tomita's avatar
Y_Tomita committed
88
int tddflag;
89 90 91
char *emul_iface;


92 93 94 95 96 97 98 99
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]

100
int oai_exit = 0;
101 102

unsigned int                    mmapped_dma=0;
laurent's avatar
laurent committed
103
UE_MAC_INST *UE_mac_inst = NULL;
104

Cedric Roux's avatar
Cedric Roux committed
105
uint64_t                 downlink_frequency[MAX_NUM_CCs][4];
106 107 108 109 110 111
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];



int UE_scan = 1;
int UE_scan_carrier = 0;
frtabu's avatar
frtabu committed
112

113 114 115
runmode_t mode = normal_txrx;

FILE *input_fd=NULL;
116
int otg_enabled=0;
117 118 119 120

#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}};
121
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0}};
122 123 124
#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}};
125
double rx_gain[MAX_NUM_CCs][4] = {{130,0,0,0},{20,0,0,0}};
126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149
#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];
150

151 152
uint64_t num_missed_slots=0; // counter for the number of missed slots

153
// prototypes from function implemented in lte-ue.c, probably should be elsewhere in a include file.
154
extern void init_UE_stub_single_thread(int nb_inst,int eMBMS_active, int uecap_xer_in, char *emul_iface);
155
extern PHY_VARS_UE *init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms, uint8_t UE_id, uint8_t abstraction_flag);
156 157 158

int transmission_mode=1;

159

160

161 162
char *usrp_args=NULL;
char *usrp_clksrc=NULL;
163

laurent's avatar
laurent committed
164
THREAD_STRUCT thread_struct;
165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181
/* 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;

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

Ricky S's avatar
Ricky S committed
182
bler_struct bler_data[NUM_MCS];
183 184
// needed for pdcp.c
RAN_CONTEXT_t RC;
185
instance_t CUuniqInstance=0;
186 187 188 189 190 191 192 193 194 195
/* 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;
196

197 198 199 200 201 202 203
  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;
  }
204

205 206 207 208 209 210 211 212 213 214 215 216 217 218 219
  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);
220

221 222 223 224
  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;
  }
225

226 227 228 229
  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;
  }
230

231
#if 1
232

233
  if (changed) print_difftimes();
234

235 236 237 238 239 240 241 242 243 244 245 246
#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));
}

247

248
void exit_function(const char *file, const char *function, const int line, const char *s, const int assert) {
249
  int CC_id;
250
  logClean();
251
  printf("%s:%d %s() Exiting OAI softmodem: %s\n",file,line, function, ((s==NULL)?"":s));
252 253 254
  oai_exit = 1;

  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
255
    if (PHY_vars_UE_g)
256
      if (PHY_vars_UE_g[0])
257 258 259 260
        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);
  }
261

262
  if(PHY_vars_UE_g != NULL )
263
    itti_terminate_tasks (TASK_UNKNOWN);
264

265 266 267 268 269 270
  if (assert) {
    abort();
  } else {
    sleep(1); // allow lte-softmodem threads to exit first
    exit(EXIT_SUCCESS);
  }
271 272
}

273
extern int16_t dlsch_demod_shift;
274
uint16_t node_number;
275
static void get_options(void) {
276 277 278 279
  int CC_id=0;
  int tddflag=0;
  int dumpframe=0;
  int timingadv=0;
Cedric Roux's avatar
Cedric Roux committed
280
  uint8_t nfapi_mode = NFAPI_MONOLITHIC;
281 282

  set_default_frame_parms(frame_parms);
283
  CONFIG_SETRTFLAG(CONFIG_NOEXITONHELP);
284 285
  /* unknown parameters on command line will be checked in main
     after all init have been performed                         */
286
  get_common_options(SOFTMODEM_4GUE_BIT );
287 288 289 290
  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
291 292
  nfapi_setmode(nfapi_mode);

293
  get_softmodem_params()->hw_timing_advance = timingadv;
294

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

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

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

301
  if (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr)
302 303
    if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;

304
  if (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr)
305 306 307 308 309
    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;

310
  if (dumpframe  > 0)  mode = rx_dump_frame;
311

312 313 314
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
  }
315

316
  UE_scan=0;
frtabu's avatar
frtabu committed
317

318
  if (tddflag > 0) {
319
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
320
      frame_parms[CC_id]->frame_type = TDD;
321 322
      frame_parms[CC_id]->tdd_config = tddflag;
    }
323 324 325
  }

  if (frame_parms[0]->N_RB_DL !=0) {
326 327 328 329
    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);
    }
330

331 332 333 334
    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);
    }
335

336 337 338 339
    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);
    }
340

341 342 343 344
    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);
    }
345

346 347
    UE_scan = 0;
    frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
348

349 350 351 352
    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;
    }
353 354
  }

355 356 357
  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];
358 359 360 361 362 363 364 365
  }
}


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++) {
366
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS *) calloc(1, sizeof(LTE_DL_FRAME_PARMS));
367 368 369 370 371 372 373 374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
    /* 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];
  }
}

401
void init_openair0(LTE_DL_FRAME_PARMS *frame_parms,int rxgain) {
402 403 404 405 406 407 408
  int card;
  int i;

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

409 410
    if(frame_parms->N_RB_DL == 100) {
      if (frame_parms->threequarter_fs) {
411 412 413 414
        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;
415
      } else {
416 417 418 419
        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;
420
      }
421
    } else if(frame_parms->N_RB_DL == 50) {
422 423 424 425
      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;
426
    } else if (frame_parms->N_RB_DL == 25) {
427 428 429 430
      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;
431
    } else if (frame_parms->N_RB_DL == 6) {
432 433 434 435 436 437
      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;
    }

438
    if (frame_parms->frame_type==TDD)
439 440 441 442 443
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    openair0_cfg[card].Mod_id = 0;
444
    openair0_cfg[card].num_rb_dl=frame_parms->N_RB_DL;
445 446
    openair0_cfg[card].clock_source = get_softmodem_params()->clock_source;
    openair0_cfg[card].time_source = get_softmodem_params()->timing_source;
447
    openair0_cfg[card].tune_offset = get_softmodem_params()->tune_offset;
448 449
    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);
450 451 452

    for (i=0; i<4; i++) {
      if (i<openair0_cfg[card].tx_num_channels)
453
        openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i]+uplink_frequency_offset[0][i];
454
      else
455
        openair0_cfg[card].tx_freq[i]=0.0;
456 457

      if (i<openair0_cfg[card].rx_num_channels)
458
        openair0_cfg[card].rx_freq[i] = downlink_frequency[0][i];
459
      else
460
        openair0_cfg[card].rx_freq[i]=0.0;
461 462 463

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
464
      openair0_cfg[card].rx_gain[i] = rxgain - rx_gain_off;
465
      openair0_cfg[card].configFilename = get_softmodem_params()->rf_config_file;
Robert Schmidt's avatar
Robert Schmidt committed
466
      printf("Card %d, channel %d, Setting tx_gain %.0f, rx_gain %.0f, tx_freq %.0f, rx_freq %.0f, tune_offset %.0f\n",
467 468 469
             card,i, openair0_cfg[card].tx_gain[i],
             openair0_cfg[card].rx_gain[i],
             openair0_cfg[card].tx_freq[i],
470 471
             openair0_cfg[card].rx_freq[i],
             openair0_cfg[card].tune_offset);
472
    }
473 474

    if (usrp_args) openair0_cfg[card].sdr_addrs = usrp_args;
475 476 477 478 479
  }
}



frtabu's avatar
frtabu committed
480
/* helper function to terminate a certain ITTI task
481
 */
482
void terminate_task(task_id_t task_id, module_id_t mod_id) {
483 484
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
  MessageDef *msg;
485
  msg = itti_alloc_new_message (ENB_APP, 0, TERMINATE_MESSAGE);
486 487 488 489
  itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}


490 491 492 493 494 495 496 497 498 499 500
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);
}

501
static void init_pdcp(int ue_id) {
502 503
  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);

Robert Schmidt's avatar
Robert Schmidt committed
504
  if (IS_SOFTMODEM_RFSIM || (nfapi_getmode()==NFAPI_UE_STUB_PNF)) {
505 506 507 508 509 510
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;
  }

  if (IS_SOFTMODEM_NOKRNMOD)
    pdcp_initmask = pdcp_initmask | UE_NAS_USE_TUN_BIT;

511
  pdcp_module_init(pdcp_initmask, ue_id);
512 513
  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);
514 515
}

516
// Stupid function addition because UE itti messages queues definition is common with eNB
517 518
void *rrc_enb_process_msg(void *notUsed) {
AssertFatal(false,"");
519 520 521
	return NULL;
}

laurent's avatar
laurent committed
522 523
int NB_UE_INST = 1;

524
int main( int argc, char **argv ) {
Michael Cook's avatar
Michael Cook committed
525

526 527
  int CC_id;
  uint8_t  abstraction_flag=0;
528 529
  // Default value for the number of UEs. It will hold,
  // if not changed from the command line option --num-ues
530
  configmodule_interface_t *config_mod;
531
  start_background_system();
532
  config_mod = load_configmodule(argc, argv, CONFIG_ENABLECMDLINEONLY);
533

534
  if (config_mod == NULL) {
535
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
536
  }
537

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

544
  for (int i=0; i<MAX_NUM_CCs; i++) tx_max_power[i]=23;
545

546
  get_options ();
547

548 549 550 551 552
  if (NFAPI_MODE == NFAPI_MODE_STANDALONE_PNF) {
    sf_ahead = 1;
  }
  printf("sf_ahead = %d\n", sf_ahead);

553
  EPC_MODE_ENABLED = !IS_SOFTMODEM_NOS1;
554
  printf("Running with %d UE instances\n",NB_UE_INST);
555

556
#if T_TRACER
557
  T_Config_Init();
558 559 560 561
#endif
  //randominit (0);
  set_taus_seed (0);
  cpuf=get_cpu_freq_GHz();
562 563 564
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);

565
  printf("ITTI init\n");
Laurent Thomas's avatar
Laurent Thomas committed
566
  itti_init(TASK_MAX, tasks_info);
567

568
  init_opt();
569 570
  ue_id_g = (node_number == 0) ? 0 : node_number-2; //ue_id_g = 0, 1, ...,
  if(node_number == 0)
571 572 573 574 575 576 577
  {
    init_pdcp(0);
  }
  else
  {
    init_pdcp(node_number-1);
  }
578

579
  //TTN for D2D
580 581 582 583
  printf ("RRC control socket\n");
  rrc_control_socket_init();
  printf ("PDCP PC5S socket\n");
  pdcp_pc5_socket_init();
584
  // to make a graceful exit when ctrl-c is pressed
585
  set_softmodem_sighandler();
586 587 588 589 590 591 592
#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++) {
593 594 595
    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
596 597
  }

Michael Cook's avatar
Michael Cook committed
598
  if(NFAPI_MODE==NFAPI_UE_STUB_PNF || NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) {
599
    PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE **)*NB_UE_INST);
600

601 602 603 604
    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);
605

606 607 608 609
        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;
610
      }
611 612
    }
  } else init_openair0(frame_parms[0],(int)rx_gain[0][0]);
613

614 615

  cpuf=get_cpu_freq_GHz();
616

617
  if (create_tasks_ue(NB_UE_INST) < 0) {
618 619 620
    printf("cannot create ITTI tasks\n");
    exit(-1); // need a softer mode
  }
621

622
  if (NFAPI_MODE==NFAPI_UE_STUB_PNF || NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) { // UE-STUB-PNF
623 624 625 626
    UE_config_stub_pnf();
  }

  printf("ITTI tasks created\n");
627 628
  mlockall(MCL_CURRENT | MCL_FUTURE);
  rt_sleep_ns(10*100000000ULL);
629
  int eMBMS_active = 0;
630

frtabu's avatar
frtabu committed
631 632 633 634 635 636
  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);
637
  } else if (NFAPI_MODE==NFAPI_MODE_STANDALONE_PNF) {
638
    init_queue(&dl_config_req_tx_req_queue);
639 640
    init_queue(&hi_dci0_req_queue);
    init_queue(&ul_config_req_queue);
641

Ricky S's avatar
Ricky S committed
642 643
    init_bler_table();

644
    config_sync_var=0;
645 646 647 648 649
    if (sem_init(&sfn_semaphore, 0, 0) != 0)
    {
      LOG_E(MAC, "sem_init() error\n");
      abort();
    }
650
    init_UE_stub_single_thread(NB_UE_INST,eMBMS_active,uecap_xer_in,emul_iface);
651
    init_UE_standalone_thread(ue_id_g);
652
  } else {
frtabu's avatar
frtabu committed
653 654
    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]);
655
  }
656

Raphael Defosseux's avatar
Raphael Defosseux committed
657
  if (get_softmodem_params()->phy_test==0) {
658 659 660 661
    printf("Filling UE band info\n");
    fill_ue_band_info();
    dl_phy_sync_success (0, 0, 0, 1);
  }
662

frtabu's avatar
frtabu committed
663 664
  if (NFAPI_MODE != NFAPI_UE_STUB_PNF) {
    number_of_cards = 1;
665

frtabu's avatar
frtabu committed
666 667 668
    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);
669
    }
670
  }
671

672 673
  if (input_fd) {
    printf("Reading in from file to antenna buffer %d\n",0);
674

675 676 677 678 679
    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");
680
  }
681

682
  if(IS_SOFTMODEM_DOSCOPE)
683
    load_softscope("ue",NULL);
684

685
  config_check_unknown_cmdlineopt(CONFIG_CHECKALLSECTIONS);
686
  printf("Sending sync to all threads (%p,%p,%p)\n",&sync_var,&sync_cond,&sync_mutex);
687 688 689 690
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
691
  printf("sync sent\n");
692 693
  /*
    printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
694
    We have to set properly PARAMFLAG_NOFREE
695 696 697
    end_configmodule();
    printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
  */
698 699 700 701
  // wait for end of program
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
  printf("Entering ITTI signals handler\n");
702
  itti_wait_tasks_end(NULL);
703 704 705
  printf("Returned from ITTI signal handler\n");
  oai_exit=1;
  printf("oai_exit=%d\n",oai_exit);
706

707
  // stop threads
708
  if(IS_SOFTMODEM_DOSCOPE)
709
    end_forms();
710 711 712 713 714

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

715
  //  pthread_mutex_destroy(&ue_pf_po_mutex);
716 717 718 719 720

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

Michael Cook's avatar
Michael Cook committed
721
  pdcp_module_cleanup();
722
  terminate_opt();
723
  logClean();
724 725 726
  printf("Bye.\n");
  return 0;
}
Ricky S's avatar
Ricky S committed
727 728 729 730 731


// Read in each MCS file and build BLER-SINR-TB table
void init_bler_table(void)
{
732
  size_t bufSize = 1024;
Ricky S's avatar
Ricky S committed
733 734 735
  char * line = NULL;
  char * token;
  char * temp = NULL;
736
  const char *openair_dir = getenv("OPENAIR_DIR");
737 738 739 740 741
  if (!openair_dir)
  {
    LOG_E(MAC, "No $OPENAIR_DIR\n");
    abort();
  }
Ricky S's avatar
Ricky S committed
742 743 744 745 746 747

  // Maybe not needed... and may not work.
  memset(bler_data, 0, sizeof(bler_data));

  for (unsigned int i = 0; i < NUM_MCS; i++)
  {
748
    char fName[1024];
749
    snprintf(fName, sizeof(fName), "%s/openair1/SIMULATION/LTE_PHY/BLER_SIMULATIONS/AWGN/AWGN_results/bler_tx1_chan18_nrx1_mcs%d.csv", openair_dir, i);
750 751
    FILE *pFile = fopen(fName, "r");
    if (!pFile)
Ricky S's avatar
Ricky S committed
752 753 754 755 756
    {
      LOG_E(MAC, "Bler File ERROR! - fopen(), file: %s\n", fName);
      abort();
    }
    int nlines = 0;
757
    while (getline(&line, &bufSize, pFile) > 0)
Ricky S's avatar
Ricky S committed
758 759 760 761 762 763 764 765 766 767 768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784
    {
      if (!strncmp(line,"SNR",3))
      {
        continue;
      }

      if (nlines > NUM_SINR)
      {
        LOG_E(MAC, "BLER FILE ERROR - num lines greater than expected - file: %s\n", fName);
        abort();
      }

      token = strtok_r(line, ";", &temp);
      int ncols = 0;
      while (token != NULL)
      {
        if (ncols > NUM_BLER_COL)
        {
          LOG_E(MAC, "BLER FILE ERROR - num of cols greater than expected\n");
          abort();
        }

        bler_data[i].bler_table[nlines][ncols] = strtof(token, NULL);
        ncols++;

        token = strtok_r(NULL, ";", &temp);
      }
785
      nlines++;
Ricky S's avatar
Ricky S committed
786 787 788 789 790
    }
    bler_data[i].length = nlines;
    fclose(pFile);
  }
}