lte-softmodem.c 43.6 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
Raymond Knopp's avatar
 
Raymond 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
Raymond Knopp's avatar
 
Raymond 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
Raymond Knopp's avatar
 
Raymond 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

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

Raymond Knopp's avatar
 
Raymond 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"
Navid Nikaein's avatar
Navid Nikaein 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"
Navid Nikaein's avatar
Navid Nikaein 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"
103

104

105
#ifdef XFORMS
106
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
107
// at eNB 0, an UL scope for every UE
108
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
109
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
110
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
111
char title[255];
112
unsigned char                   scope_enb_num_ue = 2;
113
static pthread_t                forms_thread; //xforms
114 115
#endif //XFORMS

Raymond Knopp's avatar
 
Raymond Knopp committed
116 117
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
118
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
119

120 121
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]
Raymond Knopp's avatar
 
Raymond Knopp committed
122

123
#if defined(ENABLE_ITTI)
124 125
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
126
#endif
Raymond Knopp's avatar
Raymond Knopp committed
127
volatile int             oai_exit = 0;
128

129
static clock_source_t clock_source = internal;
130
static int wait_for_sync = 0;
Raymond Knopp's avatar
 
Raymond Knopp committed
131

Raymond Knopp's avatar
Raymond Knopp committed
132
static char              UE_flag=0;
133
unsigned int                    mmapped_dma=0;
134
int                             single_thread_flag=1;
135

136
static char                     threequarter_fs=0;
137

138
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
139
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
140

141

142

143
#if defined(ENABLE_ITTI)
144
static char                    *itti_dump_file = NULL;
Raymond Knopp's avatar
 
Raymond Knopp committed
145 146
#endif

147
int UE_scan = 1;
148
int UE_scan_carrier = 0;
149 150
runmode_t mode = normal_txrx;

151 152
FILE *input_fd=NULL;

153

154 155
#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
kortke's avatar
kortke committed
156 157
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
158 159 160 161
#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}};
Lionel Gauthier's avatar
Lionel Gauthier committed
162
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
163

164
double rx_gain_off = 0.0;
165

Raymond Knopp's avatar
 
Raymond Knopp committed
166
double sample_rate=30.72e6;
167
double bw = 10.0e6;
168

169
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
170

171 172
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
173
int chain_offset=0;
174
int phy_test = 0;
175
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
176

177 178 179
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

180 181
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
182

Raymond Knopp's avatar
 
Raymond Knopp committed
183 184 185
char ref[128] = "internal";
char channels[128] = "0";

186
int                      rx_input_level_dBm;
187

188
#ifdef XFORMS
189
extern int                      otg_enabled;
190
static char                     do_forms=0;
191
#else
192
int                             otg_enabled;
193
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
194
//int                             number_of_cards =   1;
195

196 197

static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
Florian Kaltenberger's avatar
Florian Kaltenberger committed
198
uint32_t target_dl_mcs = 28; //maximum allowed mcs
199
uint32_t target_ul_mcs = 20;
200
uint32_t timing_advance = 0;
201 202
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
203

204

205 206
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
207

208
int transmission_mode=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
209

210

211

212 213 214
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

215 216 217 218
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

219 220
extern char uecap_xer[1024];
char uecap_xer_in=0;
221

222
int oaisim_flag=0;
223
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
Raymond Knopp's avatar
 
Raymond Knopp committed
224

Cedric Roux's avatar
Cedric Roux committed
225 226 227 228
/* 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;
Raymond Knopp's avatar
 
Raymond Knopp committed
229

230 231 232
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

233 234 235 236 237
/*---------------------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 };

238
struct timespec clock_difftime(struct timespec start, struct timespec end) {
239 240 241 242 243 244 245 246 247
  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;
248 249
}

250
void print_difftimes(void) {
251
#ifdef DEBUG
252
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
253
#else
254
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
255 256 257
#endif
}

258
void update_difftimes(struct timespec start, struct timespec end) {
259 260 261
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
262 263 264 265 266 267 268 269
  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;
  }
270
#if 1
271
  if (changed) print_difftimes();
272 273 274 275 276
#endif
}

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

277
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
Raymond Knopp's avatar
 
Raymond Knopp committed
278
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
279
}
280
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
Raymond Knopp's avatar
 
Raymond Knopp committed
281
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
282 283
}

284
#if !defined(ENABLE_ITTI)
285
void signal_handler(int sig) {
286 287 288 289 290 291
  void *array[10];
  size_t size;

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

293 294 295 296
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
297 298
  } else {
    printf("trying to exit gracefully...\n");
299
    oai_exit = 1;
300 301
  }
}
302
#endif
303 304 305 306 307 308
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

309

Raymond Knopp's avatar
Raymond Knopp committed
310

311 312
void exit_fun(const char* s)
{
Raymond Knopp's avatar
Raymond Knopp committed
313
  int CC_id;
314
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
315

316
  if (s != NULL) {
317
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
318 319 320
  }

  oai_exit = 1;
321 322 323 324 325 326 327 328 329 330

  if (UE_flag==0) {
    for (ru_id=0; ru_id<RC.nb_RU;ru_id++) {
      if (RC.ru[ru_id]->rfdevice.trx_end_func)
	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);
      if (RC.ru[ru_id]->ifdevice.trx_end_func)
	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);  
    }
  }

Raymond Knopp's avatar
Raymond Knopp committed
331
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
332 333 334 335

    oai_exit = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
336 337 338 339 340
      if (UE_flag == 0) {
      } else {
	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);
      }
Raymond Knopp's avatar
Raymond Knopp committed
341
    }
342 343

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

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) {
Raymond Knopp's avatar
 
Raymond Knopp committed
381
  char stats_buffer[16384];
382
# ifdef ENABLE_XFORMS_WRITE_STATS
Raymond Knopp's avatar
 
Raymond Knopp committed
383
  FILE *UE_stats, *eNB_stats;
384
# endif
Raymond Knopp's avatar
 
Raymond 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;
Raymond Knopp's avatar
 
Raymond Knopp committed
390
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
391

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

394
# ifdef ENABLE_XFORMS_WRITE_STATS
395 396

  if (UE_flag==1)
Raymond Knopp's avatar
 
Raymond Knopp committed
397
    UE_stats  = fopen("UE_stats.txt", "w");
398
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
399
    eNB_stats = fopen("eNB_stats.txt", "w");
400

401
#endif
402

Raymond Knopp's avatar
 
Raymond Knopp committed
403 404
  while (!oai_exit) {
    if (UE_flag==1) {
405
      dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
406 407 408
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
409

410
      phy_scope_UE(form_ue[0],
411 412 413 414
		   PHY_vars_UE_g[0][0],
		   0,
		   0,7);

415

Raymond Knopp's avatar
 
Raymond Knopp committed
416
    } else {
417
      /*
418
	if (RC.eNB[0][0]->mac_enabled==1) {
419 420 421 422
	len = dump_eNB_l2_stats (stats_buffer, 0);
	//fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
	fl_clear_browser(form_stats_l2->stats_text);
	fl_add_browser_line(form_stats_l2->stats_text, stats_buffer);
423 424
	}
	len = dump_eNB_stats (RC.eNB[0][0], stats_buffer, 0);
425

426 427
	if (MAX_NUM_CCs>1)
	len += dump_eNB_stats (RC.eNB[0][1], &stats_buffer[len], 0);
428

429 430 431
	//fl_set_object_label(form_stats->stats_text, stats_buffer);
	fl_clear_browser(form_stats->stats_text);
	fl_add_browser_line(form_stats->stats_text, stats_buffer);
432
      */
433 434
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
435
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
436
	  //	  if ((RC.eNB[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
437
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
438
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
439
			  RC.eNB[0][CC_id],
440 441 442
			  UE_id);
	    ue_cnt++;
	  }
443
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
444
      }
445

446
    }
447
	
Raymond Knopp's avatar
 
Raymond Knopp committed
448
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
449 450
    //usleep(100000); // 100 ms
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
451
  }
452

453
  //  printf("%s",stats_buffer);
454

455
# ifdef ENABLE_XFORMS_WRITE_STATS
456

457 458 459 460 461 462
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
463
  } else {
464 465 466 467 468 469
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
470

471
# endif
472

Raymond Knopp's avatar
 
Raymond Knopp committed
473
  pthread_exit((void*)arg);
474 475 476
}
#endif

477

478

479

Raymond Knopp's avatar
 
Raymond Knopp committed
480
#if defined(ENABLE_ITTI)
481
void *l2l1_task(void *arg) {
Raymond Knopp's avatar
 
Raymond Knopp committed
482 483 484 485 486
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
487

Raymond Knopp's avatar
 
Raymond Knopp committed
488 489
  if (UE_flag == 0) {
    /* Wait for the initialize message */
490
    printf("Wait for the ITTI initialize message\n");
491
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
492
      if (message_p != NULL) {
493 494
	result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
	AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
Raymond Knopp's avatar
 
Raymond Knopp committed
495
      }
496

497 498 499
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
500
      case INITIALIZE_MESSAGE:
501 502 503 504
	/* Start eNB thread */
	LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
	start_eNB = 1;
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
505 506

      case TERMINATE_MESSAGE:
507 508
	printf("received terminate message\n");
	oai_exit=1;
509
        start_eNB = 0;
510 511
	itti_exit_task ();
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
512 513

      default:
514 515
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
516
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
517
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
518

Raymond Knopp's avatar
 
Raymond Knopp committed
519 520 521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }

  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;
540

Raymond Knopp's avatar
 
Raymond Knopp committed
541 542 543 544 545 546 547 548 549 550 551
    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);
552
  } while(!oai_exit);
553

Raymond Knopp's avatar
 
Raymond Knopp committed
554
  return NULL;
555 556 557
}
#endif

558

559 560 561 562 563
static void get_options(void) {
  int CC_id;
  int tddflag;
  char *loopfile=NULL;
  int dumpframe;
564 565
  uint32_t online_log_messages;
  uint32_t glog_level, glog_verbosity;
oai's avatar
oai committed
566
  uint32_t start_telnetsrv;
567

568
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
569
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
570 571 572 573 574 575 576 577 578 579 580 581 582

  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");
  }
583 584 585 586 587 588 589 590

  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);
  }
591
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGVERBO_IDX)) {
592 593
      set_glog(-1, glog_verbosity);
  }
oai's avatar
oai committed
594
  if (start_telnetsrv) {
595
     load_module_shlib("telnetsrv",NULL,0);
oai's avatar
oai committed
596 597
  }

598
  
599
  if (UE_flag > 0) {
oai's avatar
oai committed
600
     uint8_t n_rb_dl;
601 602
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
oai's avatar
oai committed
603

Florian Kaltenberger's avatar
Florian Kaltenberger committed
604
     set_default_frame_parms(frame_parms);
oai's avatar
oai committed
605

606 607 608 609 610 611 612 613
     config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
     config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);
      if (loopfile != NULL) {
  	  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");
      }
oai's avatar
oai committed
614

615 616 617
      if ( (cmdline_uemodeparams[CMDLINE_CALIBUERX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue;
      if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXMED_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_med;
      if ( (cmdline_uemodeparams[CMDLINE_CALIBUERXBYP_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_calib_ue_byp;
618 619 620
      if ( (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = debug_prach;
      if ( (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0)  mode = no_L2_connect;
      if ( (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = calib_prach_tx; 
621 622 623
      if (dumpframe  > 0)  mode = rx_dump_frame;
      
      if ( downlink_frequency[0][0] > 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
624 625 626 627 628
	printf("Downlink frequency set to %u\n", downlink_frequency[0][0]);
	for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  frame_parms[CC_id]->dl_CarrierFreq = downlink_frequency[0][0];
	}
	UE_scan=0;
629 630
      } 

oai's avatar
oai committed
631 632 633 634
      if (tddflag > 0) {
         for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	     frame_parms[CC_id]->frame_type = TDD;
      }
Florian Kaltenberger's avatar
Florian Kaltenberger committed
635

636
      if (n_rb_dl !=0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
637
	printf("NB_RB set to %d\n",n_rb_dl);
638 639 640 641 642 643 644 645 646 647 648 649 650 651 652 653 654 655 656 657 658
	if ( n_rb_dl < 6 ) {
	  n_rb_dl = 6;
	  printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",n_rb_dl);
	}
	if ( n_rb_dl > 100 ) {
	  n_rb_dl = 100;
	  printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",n_rb_dl);
	}
	if ( n_rb_dl > 50 && n_rb_dl < 100 ) {
	  n_rb_dl = 50;
	  printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",n_rb_dl);
	}
	if ( n_rb_dl > 25 && n_rb_dl < 50 ) {
	  n_rb_dl = 25;
	  printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",n_rb_dl);
	}
	UE_scan = 0;
	for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  frame_parms[CC_id]->N_RB_DL=n_rb_dl;
	  frame_parms[CC_id]->N_RB_UL=n_rb_dl;
	}
659 660
      }

661 662 663 664
      for (CC_id=0;CC_id<MAX_NUM_CCs;CC_id++) {
	tx_max_power[CC_id]=tx_max_power[0];
	rx_gain[0][CC_id] = rx_gain[0][0];
	tx_gain[0][CC_id] = tx_gain[0][0];
665 666
      }
  } /* UE_flag > 0 */
667

668 669 670 671 672
#if T_TRACER
  paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
  config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);   
#endif

673 674 675 676
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
    if (UE_flag == 0) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
677
      RCConfig();
678 679
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
680
      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
681
    }
682
  } else if (UE_flag == 1 && (!(CONFIG_ISFLAGSET(CONFIG_NOOOPT))) ) {
683 684
    // Here the configuration file is the XER encoded UE capabilities
    // Read it in and store in asn1c data structures
Florian Kaltenberger's avatar
Florian Kaltenberger committed
685 686
    sprintf(uecap_xer,"%stargets/PROJECTS/GENERIC-LTE-EPC/CONF/UE_config.xml",getenv("OPENAIR_HOME"));
    printf("%s\n",uecap_xer);
687 688
    uecap_xer_in=1;
  } /* UE with config file  */
689 690 691
}


692
#if T_TRACER
693
int T_nowait = 0;     /* by default we wait for the tracer */
694
int T_port = 2021;    /* default port to listen to to wait for the tracer */
695
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
696 697
#endif

698

699

700
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
701 702 703 704 705 706 707 708 709 710 711 712 713 714 715

  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;
716
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
717 718 719 720 721 722 723 724 725 726 727 728 729 730 731 732 733 734 735
    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;

736 737 738 739
//    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];
Raymond Knopp's avatar
Raymond Knopp committed
740
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
741
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
oai's avatar
oai committed
742

Raymond Knopp's avatar
Raymond Knopp committed
743 744 745 746
  }

}

747 748
void init_openair0(void);

Raymond Knopp's avatar
Raymond Knopp committed
749 750 751 752 753 754 755 756 757 758 759 760 761
void init_openair0() {

  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;
762
	openair0_cfg[card].samples_per_frame = 230400;
Raymond Knopp's avatar
Raymond Knopp committed
763 764
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
765
      } else {
Raymond Knopp's avatar
Raymond Knopp committed
766
	openair0_cfg[card].sample_rate=30.72e6;
767
	openair0_cfg[card].samples_per_frame = 307200;
Raymond Knopp's avatar
Raymond Knopp committed
768 769 770 771 772 773 774 775 776 777 778 779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796
	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,
797 798
	   ((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx),
	   ((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx));
Raymond Knopp's avatar
Raymond Knopp committed
799 800 801
    openair0_cfg[card].Mod_id = 0;

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

803
    openair0_cfg[card].clock_source = clock_source;
804

805

806 807
    openair0_cfg[card].tx_num_channels=min(2,((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx));
    openair0_cfg[card].rx_num_channels=min(2,((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx));
808

Raymond Knopp's avatar
Raymond Knopp committed
809
    for (i=0; i<4; i++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
810

Raymond Knopp's avatar
Raymond Knopp committed
811 812 813 814
      if (i<openair0_cfg[card].tx_num_channels)
	openair0_cfg[card].tx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] : downlink_frequency[0][i]+uplink_frequency_offset[0][i];
      else
	openair0_cfg[card].tx_freq[i]=0.0;
815

Raymond Knopp's avatar
Raymond Knopp committed
816 817 818 819 820 821 822 823
      if (i<openair0_cfg[card].rx_num_channels)
	openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
      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];
      if (UE_flag == 0) {
824
	openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;
Raymond Knopp's avatar
Raymond Knopp committed
825 826
      }
      else {
827
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
Raymond Knopp's avatar
Raymond Knopp committed
828 829
      }

830
      openair0_cfg[card].configFilename = rf_config_file;
831
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
832 833 834 835
	     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]);
836
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
837
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
838
}
839

840

841
void wait_RUs(void) {
842 843 844 845 846 847 848 849

  LOG_I(PHY,"Waiting for RUs to be configured ...\n");

  // 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);
  }
850
  pthread_mutex_unlock(&RC.ru_mutex);
851 852 853 854

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

855
void wait_eNBs(void) {
856 857 858 859 860 861 862 863 864 865 866 867 868 869 870 871 872 873

  int i,j;
  int waiting=1;


  while (waiting==1) {
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 500ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(500000);
    waiting=0;
    for (i=0;i<RC.nb_L1_inst;i++)
      for (j=0;j<RC.nb_L1_CC[i];j++)
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
	}
  }
  printf("eNB L1 are configured\n");
}
874

875 876 877
#if defined(ENABLE_ITTI) && defined(FLEXRAN_AGENT_SB_IF)
/*
 * helper function to terminate a certain ITTI task
878
 */
879
void terminate_task(task_id_t task_id, mid_t mod_id)
880
{
881 882 883 884 885 886
  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);
}

887
#if 0
888 889 890 891 892
int stop_L1L2(int enb_id)
{
  int CC_id;

  LOG_W(ENB_APP, "stopping lte-softmodem\n");
893
  oai_exit = 1;
894 895 896 897 898 899 900 901 902 903 904 905 906 907 908 909 910 911

  /* stop trx devices */
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_stop_func) {
        LOG_I(ENB_APP, "stopping PHY_vars_eNB_g[0][%d]->rfdevice (via trx_stop_func())\n", CC_id);
        PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_stop_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice);
    }
    if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_stop_func) {
        LOG_I(ENB_APP, "stopping PHY_vars_eNB_g[0][%d]->ifdevice (via trx_stop_func())\n", CC_id);
        PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_stop_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice);
    }
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, enb_id);
  terminate_task(TASK_L2L1, enb_id);
  LOG_W(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
  kill_eNB_proc(enb_id);
912
  oai_exit = 0;
913 914 915 916 917 918 919 920 921 922 923 924 925 926 927 928 929 930 931 932 933 934 935 936 937 938 939 940 941 942 943 944 945 946 947 948 949 950 951 952 953 954 955 956 957 958 959 960 961 962 963 964 965 966
  return 0;
}

/*
 * Restart the lte-softmodem.
 * This function checks whether we are in ENB_NORMAL_OPERATION (defined by
 * FlexRAN). If yes, first stop L1/L2/L3, then resume.
 */
int restart_L1L2(int enb_id)
{
  int i, aa, CC_id;
  /* needed for fill_PHY_vars_eNB_g(), defined locally in main();
   * abstraction flag is needed too, but defined both globally and in main () */
  uint8_t beta_ACK = 0, beta_RI = 0, beta_CQI = 2;
  /* needed for macphy_init() */
  int eMBMS_active = 0;

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

  /* block threads */
  sync_var = -1;

  reconfigure_enb_params(enb_id);     /* set frame parameters from configuration */

  /* PHY_vars_eNB_g will be filled by init_lte_eNB(), so free and
   * let the data structure be filled again */
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    free(PHY_vars_eNB_g[0][CC_id]);
    fill_PHY_vars_eNB_g(abstraction_flag, beta_ACK, beta_RI, beta_CQI);
  }

  dump_frame_parms(frame_parms[0]);
  init_openair0();

  /* give MAC interface current cell information, the rest is the same.
   * For more info, check l2_init(). Then, initialize it (cf. line 1904). */
  mac_xface->frame_parms = frame_parms[0];
  mac_xface->macphy_init(eMBMS_active,(uecap_xer_in==1)?uecap_xer:NULL,0,0);

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

  /* TODO XForms here */
967

968 969 970 971 972
  printf("Initializing eNB threads\n");
  init_eNB(node_function, node_timing, 1, eth_params, single_thread_flag, wait_for_sync);
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      PHY_vars_eNB_g[0][CC_id]->rf_map.card=0;
      PHY_vars_eNB_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
973
  }
974 975 976 977 978 979 980 981 982 983 984 985 986 987 988 989 990 991 992 993

  mlockall(MCL_CURRENT | MCL_FUTURE);

  printf("Setting eNB buffer to all-RX\n");
  // Set LSBs for antenna switch (ExpressMIMO)
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    PHY_vars_eNB_g[0][CC_id]->hw_timing_advance = 0;
    for (i=0; i<frame_parms[CC_id]->samples_per_tti*10; i++)
      for (aa=0; aa<frame_parms[CC_id]->nb_antennas_tx; aa++)
        PHY_vars_eNB_g[0][CC_id]->common_vars.txdata[0][aa][i] = 0x00010001;
  }

  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;
994
}
995
#endif
996
#endif
997

998 999
int main( int argc, char **argv )
{
1000
  int i;
1001
#if defined (XFORMS)
Raymond Knopp's avatar
 
Raymond Knopp committed
1002
  void *status;
1003
#endif
1004

Raymond Knopp's avatar
 
Raymond Knopp committed
1005
  int CC_id;
1006
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
1007
  uint8_t  abstraction_flag=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1008
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
1009

Raymond Knopp's avatar
 
Raymond Knopp committed
1010
#if defined (XFORMS)
1011 1012
  int ret;
#endif
1013

1014
  start_background_system();
1015 1016 1017 1018
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
      
1019 1020 1021 1022 1023
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

1024 1025 1026
  PHY_VARS_UE *UE[MAX_NUM_CCs];

  mode = normal_txrx;
1027
  memset(&openair0_cfg[0],0,sizeof(openair0_config_t)*MAX_CARDS);
1028

1029
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
1030

Raymond Knopp's avatar
 
Raymond Knopp committed
1031
  set_latency_target();
1032 1033


Raymond Knopp's avatar
Raymond Knopp committed
1034
  // set default parameters
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1035
  //if (UE_flag == 1) set_default_frame_parms(frame_parms);
1036

1037
  logInit();
Raymond Knopp's avatar
Raymond Knopp committed
1038

1039
  printf("Reading in command-line options\n");
1040

1041
  get_options (); 
1042
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) && UE_flag == 0) {
1043 1044
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
1045
  }
Raymond Knopp's avatar
Raymond Knopp committed
1046 1047


1048
#if T_TRACER
1049
  T_init(T_port, 1-T_nowait, T_dont_fork);
1050 1051
#endif

1052

Florian Kaltenberger's avatar
Florian Kaltenberger committed
1053

1054 1055
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
1056

1057 1058
  if (UE_flag==1) {
    printf("configuring for UE\n");
1059

1060
    set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
1061
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
1062
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
1063
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH | FLAG_THREAD, 1);
1064 1065 1066
    set_comp_log(PDCP,    LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(OTG,     LOG_INFO,   LOG_HIGH, 1);
    set_comp_log(RRC,     LOG_INFO,   LOG_HIGH, 1);
1067
#if defined(ENABLE_ITTI)
1068
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
1069
# if defined(ENABLE_USE_MME)
1070
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
1071 1072
# endif
#endif
1073

1074
  } else {
1075
    printf("configuring for RAU/RRU\n");
1076

1077
  }
1078

Raymond Knopp's avatar
 
Raymond Knopp committed
1079 1080
  if (ouput_vcd) {
    if (UE_flag==1)
1081
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
1082
    else
1083
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
1084
  }
1085

1086
  if (opp_enabled ==1) {
1087
    reset_opp_meas();
1088 1089
  }
  cpuf=get_cpu_freq_GHz();
1090

1091
#if defined(ENABLE_ITTI)
1092

Raymond Knopp's avatar
 
Raymond Knopp committed
1093 1094
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
1095
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
1096 1097
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
1098

Raymond Knopp's avatar
 
Raymond Knopp committed
1099
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
1100

1101 1102
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
1103
#endif
1104

1105 1106
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
1107

1108 1109
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
1110
    else
1111
      radio_type = RADIO_TYPE_TDD;
1112

1113 1114 1115
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
1116

1117
#ifdef PDCP_USE_NETLINK
Raymond Knopp's avatar
 
Raymond Knopp committed
1118
  netlink_init();
1119 1120 1121
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
1122 1123
#endif

1124
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
1125 1126 1127
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
1128
#endif
1129

1130

Raymond Knopp's avatar
 
Raymond Knopp committed
1131 1132
  check_clock();

1133 1134 1135 1136 1137 1138
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1139
  // init the parameters
1140 1141
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {

Raymond Knopp's avatar
Raymond Knopp committed
1142
    if (UE_flag==1) {
1143 1144
      frame_parms[CC_id]->nb_antennas_tx     = nb_antenna_tx;
      frame_parms[CC_id]->nb_antennas_rx     = nb_antenna_rx;
1145
      frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
1146
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1147 1148 1149
  }


Raymond Knopp's avatar
 
Raymond Knopp committed
1150

1151

1152
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1153

1154
#ifdef FLEXRAN_AGENT_SB_IF
1155 1156 1157
    pthread_mutex_init(&mutex_node_ctrl, NULL);
    pthread_cond_init(&cond_node_ctrl, NULL);

1158 1159 1160
    /* create RC.flexran data structure */
    RCconfig_flexran();
    for (i = 0; i < RC.nb_L1_inst; i++) {
1161
      flexran_agent_start(i);
1162 1163
    }

1164 1165 1166 1167 1168 1169 1170 1171
    /* TODO handle restart/initial blocking */
    //LOG_I(ENB_APP, " * Waiting for FlexRAN RTController command *\n");
    //pthread_mutex_lock(&mutex_node_ctrl);
    //while (ENB_NORMAL_OPERATION != node_control_state)
    //  pthread_cond_wait(&cond_node_ctrl, &mutex_node_ctrl);
    //pthread_mutex_unlock(&mutex_node_ctrl);

    /* TODO do eNB reconfiguration (handled implicitly?) */
1172
#endif
1173

1174 1175 1176 1177 1178 1179 1180 1181
    if (UE_flag==1) {     
      NB_UE_INST=1;     
      NB_INST=1;     
      PHY_vars_UE_g = malloc(sizeof(PHY_VARS_UE**));     
      PHY_vars_UE_g[0] = malloc(sizeof(PHY_VARS_UE*)*MAX_NUM_CCs);
      
      
      
1182
      PHY_vars_UE_g[0][CC_id] = init_ue_vars(frame_parms[CC_id], 0,abstraction_flag);
1183 1184
      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
1185
      
1186 1187 1188 1189
      if (phy_test==1)
	UE[CC_id]->mac_enabled = 0;
      else 
	UE[CC_id]->mac_enabled = 1;
1190
      
1191
      if (UE[CC_id]->mac_enabled == 0) {  //set default UL parameters for testing mode
1192 1193 1194 1195 1196 1197 1198 1199 1200
	for (i=0; i<NUMBER_OF_CONNECTED_eNB_MAX; i++) {
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_ACK_Index = beta_ACK;
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_RI_Index  = beta_RI;
	  UE[CC_id]->pusch_config_dedicated[i].betaOffset_CQI_Index = beta_CQI;
	  
	  UE[CC_id]->scheduling_request_config[i].sr_PUCCH_ResourceIndex = 0;
	  UE[CC_id]->scheduling_request_config[i].sr_ConfigIndex = 7+(0%3);
	  UE[CC_id]->scheduling_request_config[i].dsr_TransMax = sr_n4;
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
1201
      }
1202
      
1203
      UE[CC_id]->UE_scan = UE_scan;
1204
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
1205
      UE[CC_id]->mode    = mode;
Rohit Gupta's avatar
Rohit Gupta committed
1206
      printf("UE[%d]->mode = %d\n",CC_id,mode);
1207 1208 1209 1210 1211 1212 1213 1214
      
      if (UE[CC_id]->mac_enabled == 1) { 
	UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1234;
	UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1234;
      }else {
	UE[CC_id]->pdcch_vars[0][0]->crnti = 0x1235;
	UE[CC_id]->pdcch_vars[1][0]->crnti = 0x1235;
      }
1215
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0] + rx_gain_off;
1216
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
1217 1218 1219 1220 1221 1222 1223 1224 1225 1226 1227
      
      if (frame_parms[CC_id]->frame_type==FDD) {
	UE[CC_id]->N_TA_offset = 0;
      }
      else {
	if (frame_parms[CC_id]->N_RB_DL == 100)
	  UE[CC_id]->N_TA_offset = 624;
	else if (frame_parms[CC_id]->N_RB_DL == 50)
	  UE[CC_id]->N_TA_offset = 624/2;
	else if (frame_parms[CC_id]->N_RB_DL == 25)
	  UE[CC_id]->N_TA_offset = 624/4;
1228
      }
1229
    init_openair0();      
Raymond Knopp's avatar
 
Raymond Knopp committed
1230
    }
1231

Raymond Knopp's avatar
 
Raymond Knopp committed
1232
  }
1233

1234 1235
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
1236 1237 1238
  
  
  
laurent's avatar
laurent committed
1239
#ifndef DEADLINE_SCHEDULER
1240
  
1241
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
1242 1243 1244 1245 1246
  
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
1247
#ifdef CPU_AFFINITY
1248 1249 1250
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1251
    if (s != 0) {
1252 1253
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
1254
    }
1255 1256
    LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
  }
1257
#endif
1258
  
1259 1260
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1261 1262 1263 1264
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
1265
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
1266 1267 1268 1269 1270
  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);
1271
    }
1272
  }
1273
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
1274
#endif
1275
  
1276

1277
  
1278
  
winckel's avatar
winckel committed
1279
#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
Raymond Knopp committed
1280
  if ((UE_flag == 1)||
1281
      (RC.nb_inst > 0))  {
1282
    
Raymond Knopp's avatar
Raymond Knopp committed
1283 1284 1285 1286 1287
    // don't create if node doesn't connect to RRC/S1/GTP
    if (create_tasks(UE_flag ? 0 : 1, UE_flag ? 1 : 0) < 0) {
      printf("cannot create ITTI tasks\n");
      exit(-1); // need a softer mode
    }
1288
    
1289 1290 1291
    printf("ITTI tasks created\n");
  }
  else {
1292 1293
    printf("No ITTI, Initializing L1\n");
    RCconfig_L1();
1294
  }
winckel's avatar
winckel committed
1295
#endif
1296 1297
  
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1298
  mlockall(MCL_CURRENT | MCL_FUTURE);
1299
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1300 1301
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
1302
  
1303
#ifdef XFORMS
1304
  int UE_id;
1305
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1306 1307
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
1308
    
1309
    if (UE_flag==0) {
1310
      form_stats_l2 = create_form_stats_form();
1311 1312 1313
      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");
1314
      
1315
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1316 1317 1318 1319
	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);
1320
	  
1321 1322 1323 1324 1325 1326 1327
	  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");
	  }
1328 1329
	} // CC_id
      } // UE_id
1330
    } else {
1331 1332 1333 1334 1335 1336
      form_stats = create_form_stats_form();
      fl_show_form (form_stats->stats_form, FL_PLACE_HOTSPOT, FL_FULLBORDER, "stats");
      UE_id = 0;
      form_ue[UE_id] = create_lte_phy_scope_ue();
      sprintf (title, "LTE DL SCOPE UE");
      fl_show_form (form_ue[UE_id]->lte_phy_scope_ue, FL_PLACE_HOTSPOT, FL_FULLBORDER, title);
1337
      
1338
      /*
1339
	if (openair_daq_vars.use_ia_receiver) {
1340 1341
	fl_set_button(form_ue[UE_id]->button_0,1);
	fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON");
1342
	} else {
1343 1344
	fl_set_button(form_ue[UE_id]->button_0,0);
	fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
1345
	}*/
1346 1347
      fl_set_button(form_ue[UE_id]->button_0,0);
      fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
Raymond Knopp's avatar
 
Raymond Knopp committed
1348
    }
1349
    
Raymond Knopp's avatar
 
Raymond Knopp committed
1350
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
1351
    
1352 1353
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
1354
    
Raymond Knopp's avatar
 
Raymond Knopp committed
1355 1356
    printf("Scope thread created, ret=%d\n",ret);
  }
1357
  
1358
#endif
1359
  
1360
  rt_sleep_ns(10*100000000ULL);
1361 1362
  
  
1363
  // start the main threads
Raymond Knopp's avatar
 
Raymond Knopp committed
1364
  if (UE_flag == 1) {
1365 1366
    int eMBMS_active = 0;
    init_UE(1,eMBMS_active,uecap_xer_in);
1367 1368 1369 1370 1371 1372 1373

    if (phy_test==0) {
      printf("Filling UE band info\n");
      fill_ue_band_info();
      dl_phy_sync_success (0, 0, 0, 1);
    }

1374 1375 1376 1377
    number_of_cards = 1;
    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      PHY_vars_UE_g[0][CC_id]->rf_map.card=0;
      PHY_vars_UE_g[0][CC_id]->rf_map.chain=CC_id+chain_offset;
Raymond Knopp's avatar
 
Raymond Knopp committed
1378
    }
1379
  }
Raymond Knopp's avatar
Raymond Knopp committed
1380
  else { 
1381
    number_of_cards = 1;    
1382
    if (RC.nb_L1_inst > 0) {
1383 1384
      printf("Initializing eNB threads\n");
      init_eNB(single_thread_flag,wait_for_sync);
1385 1386
      //      for (inst=0;inst<RC.nb_L1_inst;inst++)
      //	for (CC_id=0;CC_id<RC.nb_L1_CC[inst];CC_id++) phy_init_lte_eNB(RC.eNB[inst][CC_id],0,0);
Raymond Knopp's avatar
 
Raymond Knopp committed
1387
    }
1388 1389 1390

    wait_eNBs();

1391 1392 1393 1394 1395 1396 1397 1398
    if (RC.nb_RU >0) {
      printf("Initializing RU threads\n");
      init_RU(rf_config_file);
      for (ru_id=0;ru_id<RC.nb_RU;ru_id++) {
	RC.ru[ru_id]->rf_map.card=0;
	RC.ru[ru_id]->rf_map.chain=CC_id+chain_offset;
      }
    }
1399

1400
    wait_RUs();
1401
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
1402
    init_eNB_afterRU();
1403
    
1404
  }
1405 1406
  
  
1407 1408 1409
  // connect the TX/RX buffers
  if (UE_flag==1) {
    
1410 1411 1412
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      
      
1413 1414 1415 1416
#ifdef OAI_USRP
      UE[CC_id]->hw_timing_advance = timing_advance;
#else
      UE[CC_id]->hw_timing_advance = 160;
1417
#endif
1418 1419 1420 1421
    }
    if (setup_ue_buffers(UE,&openair0_cfg[0])!=0) {
      printf("Error setting up eNB buffer\n");
      exit(-1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1422
    }
1423 1424 1425
    
    
    
1426 1427 1428
    if (input_fd) {
      printf("Reading in from file to antenna buffer %d\n",0);
      if (fread(UE[0]->common_vars.rxdata[0],
1429 1430 1431 1432
		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");
1433 1434 1435
    }
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
  } else {
1436 1437 1438 1439 1440
    
    
    
    
    
1441
  }
1442 1443 1444 1445
  
  
  
  
1446
  printf("Sending sync to all threads\n");
1447 1448 1449
  
  
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1450
  pthread_mutex_lock(&sync_mutex);
1451
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1452 1453
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
1454
  end_configmodule();
1455

1456
  // wait for end of program
Raymond Knopp's avatar
 
Raymond Knopp committed
1457 1458
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
1459 1460 1461


#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
1462 1463
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
1464
  oai_exit=1;
1465
#else
1466

Raymond Knopp's avatar
 
Raymond Knopp committed
1467
  while (oai_exit==0)
1468
    rt_sleep_ns(100000000ULL);
1469

1470
#endif
1471

Raymond Knopp's avatar
 
Raymond Knopp committed
1472
  // stop threads
1473
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
1474
  printf("waiting for XFORMS thread\n");
1475 1476 1477 1478 1479 1480 1481 1482 1483 1484 1485 1486 1487 1488

  if (do_forms==1) {
    pthread_join(forms_thread,&status);
    fl_hide_form(form_stats->stats_form);
    fl_free_form(form_stats->stats_form);

    if (UE_flag==1) {
      fl_hide_form(form_ue[0]->lte_phy_scope_ue);
      fl_free_form(form_ue[0]->lte_phy_scope_ue);
    } else {
      fl_hide_form(form_stats_l2->stats_form);
      fl_free_form(form_stats_l2->stats_form);

      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1489 1490 1491 1492
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
	  fl_hide_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
	  fl_free_form(form_enb[CC_id][UE_id]->lte_phy_scope_enb);
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
1493
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1494
    }
1495
  }
1496

1497 1498
#endif

Raymond Knopp's avatar
 
Raymond Knopp committed
1499
  printf("stopping MODEM threads\n");
1500

Raymond Knopp's avatar
 
Raymond Knopp committed
1501 1502
  // cleanup
  if (UE_flag == 1) {
1503
  } else {
1504
    stop_eNB(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1505
  }
1506

1507

Raymond Knopp's avatar
 
Raymond Knopp committed
1508 1509
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
1510

1511 1512 1513 1514
#ifdef FLEXRAN_AGENT_SB_IF
    pthread_cond_destroy(&cond_node_ctrl);
    pthread_mutex_destroy(&mutex_node_ctrl);
#endif
1515

Raymond Knopp's avatar
Raymond Knopp committed
1516
  // *** Handle per CC_id openair0
Raymond Knopp's avatar
Raymond Knopp committed
1517 1518 1519 1520 1521
  if (UE_flag==1) {
    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);
  }
  else {
1522 1523 1524 1525 1526
    for(ru_id=0; ru_id<NB_RU; ru_id++) {
      if (RC.ru[ru_id]->rfdevice.trx_end_func)
	RC.ru[ru_id]->rfdevice.trx_end_func(&RC.ru[ru_id]->rfdevice);  
      if (RC.ru[ru_id]->ifdevice.trx_end_func)
	RC.ru[ru_id]->ifdevice.trx_end_func(&RC.ru[ru_id]->ifdevice);  
1527

Raymond Knopp's avatar
Raymond Knopp committed
1528
    }
1529
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1530
  if (ouput_vcd)
1531
    VCD_SIGNAL_DUMPER_CLOSE();
1532
  
1533
  if (opt_enabled == 1)
1534
    terminate_opt();
1535
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1536
  logClean();
1537

1538
  printf("Bye.\n");
1539
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1540 1541
  return 0;
}