lte-softmodem.c 35.8 KB
Newer Older
1 2 3 4 5
/*
 * 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
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
 * 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 23
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
knopp committed
25 26 27
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
knopp's avatar
knopp committed
29 30 31
 * \note
 * \warning
 */
32

33

Cedric Roux's avatar
Cedric Roux committed
34 35 36
#define _GNU_SOURCE             /* See feature_test_macros(7) */
#include <sched.h>

37

38 39
#include "T.h"

40
#include "rt_wrapper.h"
41

42

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

45
#include "assertions.h"
46
#include "msc.h"
47 48

#include "PHY/types.h"
49

50
#include "PHY/defs.h"
51
#include "common/ran_context.h"
52
#include "common/config/config_userapi.h"
oai's avatar
oai committed
53
#include "common/utils/load_module_shlib.h"
54
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
knopp's avatar
knopp committed
55
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
56

knopp's avatar
knopp committed
57
#include "../../ARCH/COMMON/common_lib.h"
58
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
knopp's avatar
knopp committed
59

knopp's avatar
knopp committed
60
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
61 62 63 64 65 66 67 68 69

#include "PHY/vars.h"
#include "SCHED/vars.h"
#include "LAYER2/MAC/vars.h"

#include "../../SIMU/USER/init_lte.h"

#include "LAYER2/MAC/defs.h"
#include "LAYER2/MAC/vars.h"
70
#include "LAYER2/MAC/proto.h"
71 72 73 74 75 76 77 78
#include "RRC/LITE/vars.h"
#include "PHY_INTERFACE/vars.h"

#ifdef SMBV
#include "PHY/TOOLS/smbv.h"
unsigned short config_frames[4] = {2,9,11,13};
#endif
#include "UTIL/LOG/log_extern.h"
nikaeinn's avatar
nikaeinn committed
79
#include "UTIL/OTG/otg_tx.h"
80
#include "UTIL/OTG/otg_externs.h"
81 82
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
83
#include "UTIL/OPT/opt.h"
84
#include "enb_config.h"
nikaeinn's avatar
nikaeinn committed
85
//#include "PHY/TOOLS/time_meas.h"
86

Florian Kaltenberger's avatar
Florian Kaltenberger committed
87 88 89 90
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

91
#if defined(ENABLE_ITTI)
92 93
#include "intertask_interface_init.h"
#include "create_tasks.h"
94 95
#endif

96 97
#include "system.h"

98 99 100
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
101
#endif
102
#include "lte-softmodem.h"
oai's avatar
oai committed
103
#include "NB_IoT_interface.h"
104
#ifdef XFORMS
105
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
106
// at eNB 0, an UL scope for every UE
107
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
108
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
109
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
110
char title[255];
111
unsigned char                   scope_enb_num_ue = 2;
112
static pthread_t                forms_thread; //xforms
113 114
#endif //XFORMS

115 116 117 118 119 120
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

uint8_t nfapi_mode = 0; // Default to monolithic mode

knopp's avatar
knopp committed
121 122
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
123
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
124
int config_sync_var=-1;
125

126 127
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]
knopp's avatar
knopp committed
128

129
#if defined(ENABLE_ITTI)
130 131
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
132
#endif
knopp's avatar
knopp committed
133
volatile int             oai_exit = 0;
134

135
static clock_source_t clock_source = internal;
136
static int wait_for_sync = 0;
knopp's avatar
knopp committed
137

138
unsigned int                    mmapped_dma=0;
139
int                             single_thread_flag=1;
140

141
static int8_t                     threequarter_fs=0;
142

143
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
144
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
145

146

147

148
#if defined(ENABLE_ITTI)
149
static char                    *itti_dump_file = NULL;
knopp's avatar
knopp committed
150 151
#endif

152
int UE_scan = 1;
153
int UE_scan_carrier = 0;
154 155
runmode_t mode = normal_txrx;

156 157
FILE *input_fd=NULL;

158

159 160
#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
161 162
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
163 164 165 166
#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}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
gauthier's avatar
gauthier committed
167
#endif
knopp's avatar
knopp committed
168

169
double rx_gain_off = 0.0;
170

knopp's avatar
knopp committed
171
double sample_rate=30.72e6;
172
double bw = 10.0e6;
173

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

176 177
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
178
int chain_offset=0;
179
int phy_test = 0;
180
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
181

182 183 184
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

185 186
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
187

knopp's avatar
knopp committed
188 189 190
char ref[128] = "internal";
char channels[128] = "0";

191
int                      rx_input_level_dBm;
192

193
#ifdef XFORMS
194
extern int                      otg_enabled;
195
static char                     do_forms=0;
196
#else
197
int                             otg_enabled;
198
#endif
knopp's avatar
knopp committed
199
//int                             number_of_cards =   1;
200

201 202

static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
Florian Kaltenberger's avatar
Florian Kaltenberger committed
203
uint32_t target_dl_mcs = 28; //maximum allowed mcs
204
uint32_t target_ul_mcs = 20;
205
uint32_t timing_advance = 0;
206 207
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
208

209

210 211
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
212

213 214 215 216 217 218
extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag);

extern void init_eNB_afterRU(void);

219
int transmission_mode=1;
knopp's avatar
knopp committed
220

221

222

223 224 225
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

226 227 228 229
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

230 231
extern char uecap_xer[1024];
char uecap_xer_in=0;
232

233
int oaisim_flag=0;
234
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
knopp's avatar
knopp committed
235

Cedric Roux's avatar
Cedric Roux committed
236 237 238 239
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;
knopp's avatar
knopp committed
240

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

244 245 246 247 248
/*---------------------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 };

249
struct timespec clock_difftime(struct timespec start, struct timespec end) {
250 251 252 253 254 255 256 257 258
  struct timespec temp;
  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;
  }
  return temp;
259 260
}

261
void print_difftimes(void) {
262
#ifdef DEBUG
263
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
264
#else
265
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
266 267 268
#endif
}

269
void update_difftimes(struct timespec start, struct timespec end) {
270 271 272
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
273 274 275 276 277 278 279 280
  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;
  }
  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;
  }
281
#if 1
282
  if (changed) print_difftimes();
283 284 285 286 287
#endif
}

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

288
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
knopp's avatar
knopp committed
289
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
290
}
291
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
knopp's avatar
knopp committed
292
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
293 294
}

295
#if !defined(ENABLE_ITTI)
296
void signal_handler(int sig) {
297 298 299 300 301 302
  void *array[10];
  size_t size;

  if (sig==SIGSEGV) {
    // get void*'s for all entries on the stack
    size = backtrace(array, 10);
303

304 305 306 307
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
308 309
  } else {
    printf("trying to exit gracefully...\n");
310
    oai_exit = 1;
311 312
  }
}
313
#endif
314 315 316 317 318 319
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

320

Raymond Knopp's avatar
Raymond Knopp committed
321

322 323
void exit_fun(const char* s)
{
324

325
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
326

327
  if (s != NULL) {
328
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
329 330 331
  }

  oai_exit = 1;
332

333 334 335

    if (RC.ru == NULL)
        exit(-1); // likely init not completed, prevent crash or hang, exit now...
336
    for (ru_id=0; ru_id<RC.nb_RU;ru_id++) {
337
      if (RC.ru[ru_id] && RC.ru[ru_id]->rfdevice.trx_end_func)
338
	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
339
      if (RC.ru[ru_id] && RC.ru[ru_id]->ifdevice.trx_end_func)
340 341
	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);  
    }
342

343 344

#if defined(ENABLE_ITTI)
345 346
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
347
#endif
348 349


350
}
351

352
#ifdef XFORMS
353

354

355 356
void reset_stats(FL_OBJECT *button, long arg)
{
357
  int i,j,k;
358
  PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];
359 360 361

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
362
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
363 364 365
	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;
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;
371 372


373 374 375
      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;
376 377 378 379
    }
  }
}

380
static void *scope_thread(void *arg) {
381
 
382
# ifdef ENABLE_XFORMS_WRITE_STATS
383
  FILE *eNB_stats;
384
# endif
knopp's avatar
knopp committed
385
  struct sched_param sched_param;
386
  int UE_id, CC_id;
387
  int ue_cnt=0;
388

389
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
knopp committed
390
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
391

knopp's avatar
knopp committed
392
  printf("Scope thread has priority %d\n",sched_param.sched_priority);
393

394
# ifdef ENABLE_XFORMS_WRITE_STATS
395

396
  eNB_stats = fopen("eNB_stats.txt", "w");
397

398
#endif
399

knopp's avatar
knopp committed
400
  while (!oai_exit) {
401

402 403
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
404
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
405
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
406
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
407
			  RC.eNB[0][CC_id],
408 409 410
			  UE_id);
	    ue_cnt++;
	  }
411
	}
412
      }	
Florian Kaltenberger's avatar
Florian Kaltenberger committed
413
    sleep(1);
knopp's avatar
knopp committed
414
  }
415

416
  //  printf("%s",stats_buffer);
417

418
# ifdef ENABLE_XFORMS_WRITE_STATS
419

420 421 422 423 424
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
425

426
# endif
427

knopp's avatar
knopp committed
428
  pthread_exit((void*)arg);
429 430 431
}
#endif

432

433

434

knopp's avatar
knopp committed
435
#if defined(ENABLE_ITTI)
436
void *l2l1_task(void *arg) {
knopp's avatar
knopp committed
437 438 439 440 441
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
442

knopp's avatar
knopp committed
443
    /* Wait for the initialize message */
444
    printf("Wait for the ITTI initialize message\n");
445
    do {
knopp's avatar
knopp committed
446
      if (message_p != NULL) {
447 448
	result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
	AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
knopp's avatar
knopp committed
449
      }
450

451 452 453
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
knopp committed
454
      case INITIALIZE_MESSAGE:
455 456 457 458
	/* Start eNB thread */
	LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
	start_eNB = 1;
	break;
knopp's avatar
knopp committed
459 460

      case TERMINATE_MESSAGE:
461 462
	printf("received terminate message\n");
	oai_exit=1;
463
        start_eNB = 0;
464 465
	itti_exit_task ();
	break;
knopp's avatar
knopp committed
466 467

      default:
468 469
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
470
      }
knopp's avatar
knopp committed
471
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
472

knopp's avatar
knopp committed
473 474
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
475
/* ???? no else but seems to be UE only ??? 
knopp's avatar
knopp committed
476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492
  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);

    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;

    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;

    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
493

knopp's avatar
knopp committed
494 495 496 497 498 499 500 501 502 503 504
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;

    default:
      LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
      break;
    }

    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
505
  } while(!oai_exit);
506
*/
knopp's avatar
knopp committed
507
  return NULL;
508 509 510
}
#endif

511

512
static void get_options(void) {
513
 
514
  int tddflag, nonbiotflag;
515 516
 
  
517 518
  uint32_t online_log_messages;
  uint32_t glog_level, glog_verbosity;
oai's avatar
oai committed
519
  uint32_t start_telnetsrv;
520

521
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
522
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
523 524 525 526 527 528 529 530 531 532 533 534 535

  config_process_cmdline( cmdline_params,sizeof(cmdline_params)/sizeof(paramdef_t),NULL); 

  if (strlen(in_path) > 0) {
      opt_type = OPT_PCAP;
      opt_enabled=1;
      printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
  }
  if (strlen(in_ip) > 0) {
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      printf("Enabling OPT for wireshark for local interface");
  }
536 537 538 539 540 541 542 543

  config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
  if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
      set_glog_onlinelog(online_log_messages);
  }
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
      set_glog(glog_level, -1);
  }
544
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGVERBO_IDX)) {
545 546
      set_glog(-1, glog_verbosity);
  }
oai's avatar
oai committed
547
  if (start_telnetsrv) {
548
     load_module_shlib("telnetsrv",NULL,0);
oai's avatar
oai committed
549 550
  }

551 552 553 554 555
#if T_TRACER
  paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
  config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);   
#endif

556 557 558
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
559
      RCConfig();
560 561
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
562
      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
oai's avatar
oai committed
563 564 565 566 567 568 569 570
      if (nonbiotflag <= 0) {
         load_NB_IoT();
         printf("               nb_nbiot_rrc_inst %d, nb_nbiot_L1_inst %d, nb_nbiot_macrlc_inst %d\n",
                RC.nb_nb_iot_rrc_inst, RC.nb_nb_iot_L1_inst, RC.nb_nb_iot_macrlc_inst);
      } else {
         printf("All Nb-IoT instances disabled\n");
         RC.nb_nb_iot_rrc_inst=RC.nb_nb_iot_L1_inst=RC.nb_nb_iot_macrlc_inst=0;
      }
571
   }
572 573 574
}


575
#if T_TRACER
576
int T_nowait = 0;     /* by default we wait for the tracer */
577
int T_port = 2021;    /* default port to listen to to wait for the tracer */
578
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
579 580
#endif

581

582

knopp's avatar
knopp committed
583
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
knopp's avatar
knopp committed
584 585 586 587 588 589 590 591 592 593 594 595 596 597 598

  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
    /* 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;
599
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
600 601 602 603 604 605 606 607 608 609 610 611 612 613 614 615 616 617 618
    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;

619 620 621 622
//    downlink_frequency[CC_id][0] = 2680000000; // 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];
knopp's avatar
knopp committed
623
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
624
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
oai's avatar
oai committed
625

knopp's avatar
knopp committed
626 627 628 629
  }

}

knopp's avatar
knopp committed
630

631
void init_openair0(void) {
knopp's avatar
knopp committed
632 633 634 635 636 637 638 639 640 641 642 643

  int card;
  int i;

  for (card=0; card<MAX_CARDS; card++) {

    openair0_cfg[card].mmapped_dma=mmapped_dma;
    openair0_cfg[card].configFilename = NULL;

    if(frame_parms[0]->N_RB_DL == 100) {
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
644
	openair0_cfg[card].samples_per_frame = 230400;
knopp's avatar
knopp committed
645 646
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
647
      } else {
knopp's avatar
knopp committed
648
	openair0_cfg[card].sample_rate=30.72e6;
649
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
knopp committed
650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669 670 671 672 673 674 675 676
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
    } else if(frame_parms[0]->N_RB_DL == 50) {
      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;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      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;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      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;
    }


    if (frame_parms[0]->frame_type==TDD)
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
677 678
	   RC.eNB[0][0]->frame_parms.nb_antennas_tx ,
	   RC.eNB[0][0]->frame_parms.nb_antennas_rx );
knopp's avatar
knopp committed
679 680 681
    openair0_cfg[card].Mod_id = 0;

    openair0_cfg[card].num_rb_dl=frame_parms[0]->N_RB_DL;
682

683
    openair0_cfg[card].clock_source = clock_source;
684

685

686 687
    openair0_cfg[card].tx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_tx );
    openair0_cfg[card].rx_num_channels=min(2,RC.eNB[0][0]->frame_parms.nb_antennas_rx );
688

knopp's avatar
knopp committed
689
    for (i=0; i<4; i++) {
690

knopp's avatar
knopp committed
691
      if (i<openair0_cfg[card].tx_num_channels)
692
	openair0_cfg[card].tx_freq[i] = downlink_frequency[0][i] ;
knopp's avatar
knopp committed
693 694
      else
	openair0_cfg[card].tx_freq[i]=0.0;
695

knopp's avatar
knopp committed
696
      if (i<openair0_cfg[card].rx_num_channels)
697
	openair0_cfg[card].rx_freq[i] =downlink_frequency[0][i] + uplink_frequency_offset[0][i] ;
knopp's avatar
knopp committed
698 699 700 701 702
      else
	openair0_cfg[card].rx_freq[i]=0.0;

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
703 704
      openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;

knopp's avatar
knopp committed
705

706
      openair0_cfg[card].configFilename = rf_config_file;
707
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
708 709 710 711
	     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]);
712
    }
713
  } /* for loop on cards */
knopp's avatar
knopp committed
714
}
715

716

717
void wait_RUs(void) {
718

719
  LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
720 721 722 723 724

  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
725
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
726
  }
727
  pthread_mutex_unlock(&RC.ru_mutex);
728 729 730 731

  LOG_I(PHY,"RUs configured\n");
}

732
void wait_eNBs(void) {
733 734 735 736 737 738

  int i,j;
  int waiting=1;


  while (waiting==1) {
Cedric Roux's avatar
Cedric Roux committed
739 740
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(50*1000);
741
    waiting=0;
742 743 744 745 746
    for (i=0;i<RC.nb_L1_inst;i++) {

      printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);

      for (j=0;j<RC.nb_L1_CC[i];j++) {
747 748 749
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
750 751 752
        } 
      }
    }
753 754 755
  }
  printf("eNB L1 are configured\n");
}
756

757
#if defined(ENABLE_ITTI)
758 759
/*
 * helper function to terminate a certain ITTI task
760
 */
761
void terminate_task(task_id_t task_id, module_id_t mod_id)
762
{
763 764 765 766 767 768
  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);
}

769
extern void  free_transport(PHY_VARS_eNB *);
770 771
extern void  phy_free_RU(RU_t*);

772
int stop_L1L2(module_id_t enb_id)
773 774
{
  LOG_W(ENB_APP, "stopping lte-softmodem\n");
775
  oai_exit = 1;
776

777 778 779 780 781 782 783 784 785 786 787 788
  if (!RC.ru) {
    LOG_F(ENB_APP, "no RU configured\n");
    return -1;
  }

  /* stop trx devices, multiple carrier currently not supported by RU */
  if (RC.ru[enb_id]) {
    if (RC.ru[enb_id]->rfdevice.trx_stop_func) {
      RC.ru[enb_id]->rfdevice.trx_stop_func(&RC.ru[enb_id]->rfdevice);
      LOG_I(ENB_APP, "turned off RU rfdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off rfdevice due to missing trx_stop_func callback, proceding anyway!\n");
789
    }
790 791 792 793 794
    if (RC.ru[enb_id]->ifdevice.trx_stop_func) {
      RC.ru[enb_id]->ifdevice.trx_stop_func(&RC.ru[enb_id]->ifdevice);
      LOG_I(ENB_APP, "turned off RU ifdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off ifdevice due to missing trx_stop_func callback, proceding anyway!\n");
795
    }
796 797 798
  } else {
    LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
    return -1;
799 800 801 802 803
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, enb_id);
  terminate_task(TASK_L2L1, enb_id);
804
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
805
  kill_eNB_proc(enb_id);
806 807
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
  kill_RU_proc(enb_id);
808
  oai_exit = 0;
809 810 811 812
  for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) {
    free_transport(RC.eNB[enb_id][cc_id]);
    phy_free_lte_eNB(RC.eNB[enb_id][cc_id]);
  }
813
  phy_free_RU(RC.ru[enb_id]);
814
  free_lte_top();
815 816 817 818
  return 0;
}

/*
819
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
820
 */
821
int restart_L1L2(module_id_t enb_id)
822
{
823 824 825
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
826 827 828 829 830 831

  LOG_W(ENB_APP, "restarting lte-softmodem\n");

  /* block threads */
  sync_var = -1;

832 833
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
834 835
  }

836 837 838 839 840
  RC.ru_mask |= (1 << ru->idx);
  /* copy the changed frame parameters to the RU */
  /* TODO this should be done for all RUs associated to this eNB */
  memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS));
  set_function_spec_param(RC.ru[enb_id]);
841 842 843 844 845 846 847 848 849 850 851 852 853 854 855

  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
  if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
    LOG_E(RRC, "Create task for RRC eNB failed\n");
    return -1;
  } else {
    LOG_I(RRC, "Re-created task for RRC eNB successfully\n");
  }
  if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
    LOG_E(PDCP, "Create task for L2L1 failed\n");
    return -1;
  } else {
    LOG_I(PDCP, "Re-created task for L2L1 successfully\n");
  }

856 857 858 859 860
  /* pass a reconfiguration request which will configure everything down to
   * RC.eNB[i][j]->frame_parms, too */
  msg_p = itti_alloc_new_message(TASK_ENB_APP, RRC_CONFIGURATION_REQ);
  RRC_CONFIGURATION_REQ(msg_p) = RC.rrc[enb_id]->configuration;
  itti_send_msg_to_task(TASK_RRC_ENB, ENB_MODULE_ID_TO_INSTANCE(enb_id), msg_p);
861 862
  /* TODO XForms might need to be restarted, but it is currently (09/02/18)
   * broken, so we cannot test it */
863

864 865 866 867 868 869
  wait_eNBs();
  init_RU_proc(ru);
  ru->rf_map.card = 0;
  ru->rf_map.chain = 0; /* CC_id + chain_offset;*/
  wait_RUs();
  init_eNB_afterRU();
870 871 872 873 874 875 876 877

  printf("Sending sync to all threads\n");
  pthread_mutex_lock(&sync_mutex);
  sync_var=0;
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);

  return 0;
878
}
879
#endif
880

881
static  void wait_nfapi_init(char *thread_name) {
882 883 884 885 886 887 888 889 890 891 892 893

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

894 895
int main( int argc, char **argv )
{
896
  int i;
897
#if defined (XFORMS)
knopp's avatar
knopp committed
898
  void *status;
899
#endif
900

knopp's avatar
knopp committed
901
  int CC_id;
902
  int ru_id;
knopp's avatar
knopp committed
903
#if defined (XFORMS)
904 905
  int ret;
#endif
906

907 908 909 910
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
      
911 912 913 914 915
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

916
  mode = normal_txrx;
917
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
918

919
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
920

knopp's avatar
knopp committed
921
  set_latency_target();
922

923
  logInit();
knopp's avatar
knopp committed
924

925
  printf("Reading in command-line options\n");
926

927
  get_options (); 
928
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) ) {
929 930
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
931
  }
knopp's avatar
knopp committed
932 933


934
#if T_TRACER
935
  T_init(T_port, 1-T_nowait, T_dont_fork);
936 937
#endif

938

939

940 941
  //randominit (0);
  set_taus_seed (0);
knopp's avatar
knopp committed
942

943
  printf("configuring for RAU/RRU\n");
944

945

knopp's avatar
knopp committed
946
  if (ouput_vcd) {
gauthier's avatar
gauthier committed
947
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
knopp's avatar
knopp committed
948
  }
949

950
  if (opp_enabled ==1) {
951
    reset_opp_meas();
952 953
  }
  cpuf=get_cpu_freq_GHz();
954

955
#if defined(ENABLE_ITTI)
956
  log_set_instance_type (LOG_INSTANCE_ENB);
957

958
  printf("ITTI init\n");
knopp's avatar
knopp committed
959
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
960

961 962
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
963
#endif
964

965 966
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
967

968 969
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
970
    else
971
      radio_type = RADIO_TYPE_TDD;
972

973 974 975
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
976

977
#ifdef PDCP_USE_NETLINK
978
  printf("PDCP netlink\n");
knopp's avatar
knopp committed
979
  netlink_init();
980 981 982
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
983 984
#endif

985
#if !defined(ENABLE_ITTI)
knopp's avatar
knopp committed
986 987 988
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
989
#endif
990

991

knopp's avatar
knopp committed
992 993
  check_clock();

994 995 996 997 998 999
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif

  LOG_I(HW, "Version: %s\n", PACKAGE_VERSION);

knopp's avatar
knopp committed
1000 1001


knopp's avatar
knopp committed
1002

1003
  printf("Before CC \n");
1004

1005
  printf("Runtime table\n");
1006
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
1007 1008


laurent's avatar
laurent committed
1009
#ifndef DEADLINE_SCHEDULER
1010
  
1011
  printf("NO deadline scheduler\n");
1012
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
1013 1014 1015 1016 1017
  
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
1018
#ifdef CPU_AFFINITY
1019 1020 1021
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1022
    if (s != 0) {
1023 1024
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
1025
    }
1026 1027
    LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
  }
1028
#endif
1029
  
1030 1031
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1032 1033 1034 1035
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
1036
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
1037 1038 1039 1040 1041
  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);
1042
    }
1043
  }
1044
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
1045
#endif
1046
  
1047

1048
  
1049
  
1050
#if defined(ENABLE_ITTI)
1051
  if (RC.nb_inst > 0)  {
1052
    
knopp's avatar
knopp committed
1053
    // don't create if node doesn't connect to RRC/S1/GTP
1054 1055 1056 1057
      if (create_tasks(1) < 0) {
        printf("cannot create ITTI tasks\n");
        exit(-1); // need a softer mode
      }
1058 1059 1060
    printf("ITTI tasks created\n");
  }
  else {
1061 1062
    printf("No ITTI, Initializing L1\n");
    RCconfig_L1();
1063
  }
1064
#endif
1065

1066
  /* Start the agent. If it is turned off in the configuration, it won't start */
1067 1068 1069 1070 1071 1072 1073 1074
  RCconfig_flexran();
  for (i = 0; i < RC.nb_L1_inst; i++) {
    flexran_agent_start(i);
  }

  // init UE_PF_PO and mutex lock
  pthread_mutex_init(&ue_pf_po_mutex, NULL);
  memset (&UE_PF_PO[0][0], 0, sizeof(UE_PF_PO_t)*NUMBER_OF_UE_MAX*MAX_NUM_CCs);
1075
  
knopp's avatar
knopp committed
1076
  mlockall(MCL_CURRENT | MCL_FUTURE);
1077
  
knopp's avatar
knopp committed
1078 1079
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
1080
  
1081
#ifdef XFORMS
1082
  int UE_id;
1083
  
1084 1085
  printf("XFORMS\n");

knopp's avatar
knopp committed
1086 1087
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
1088
    
1089
      form_stats_l2 = create_form_stats_form();
1090 1091 1092
      fl_show_form (form_stats_l2->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "l2 stats");
      form_stats = create_form_stats_form();
      fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
1093
      
1094
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1095 1096 1097 1098
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  form_enb[CC_id][UE_id] = create_lte_phy_scope_enb();
	  sprintf (title, "LTE UL SCOPE eNB for CC_id %d, UE %d",CC_id,UE_id);
	  fl_show_form (form_enb[CC_id][UE_id]->lte_phy_scope_enb, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
1099
	  
1100 1101 1102 1103 1104 1105 1106
	  if (otg_enabled) {
	    fl_set_button(form_enb[CC_id][UE_id]->button_0,1);
	    fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic ON");
	  } else {
	    fl_set_button(form_enb[CC_id][UE_id]->button_0,0);
	    fl_set_object_label(form_enb[CC_id][UE_id]->button_0,"DL Traffic OFF");
	  }
1107 1108
	} // CC_id
      } // UE_id