lte-softmodem.c 41.7 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
#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

Raymond Knopp's avatar
 
Raymond 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]
Raymond Knopp's avatar
 
Raymond Knopp committed
128

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

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

Raymond Knopp's avatar
Raymond Knopp committed
138
static char              UE_flag=0;
139
unsigned int                    mmapped_dma=0;
140
int                             single_thread_flag=1;
141

142
static char                     threequarter_fs=0;
143

144
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
145
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
Lionel Gauthier's avatar
Lionel Gauthier committed
146

147

148

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

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

157 158
FILE *input_fd=NULL;

159

160 161
#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
162 163
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
164 165 166 167
#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
168
#endif
Raymond Knopp's avatar
 
Raymond Knopp committed
169

170
double rx_gain_off = 0.0;
171

Raymond Knopp's avatar
 
Raymond Knopp committed
172
double sample_rate=30.72e6;
173
double bw = 10.0e6;
174

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

177 178
char   rf_config_file[1024];

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

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

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

Raymond Knopp's avatar
 
Raymond Knopp committed
189 190 191
char ref[128] = "internal";
char channels[128] = "0";

192
int                      rx_input_level_dBm;
193

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

202 203

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

210

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

214 215 216 217 218 219
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);

220
int transmission_mode=1;
Raymond Knopp's avatar
 
Raymond Knopp committed
221

222

223

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

227 228 229 230
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

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

234
int oaisim_flag=0;
235
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
Raymond Knopp's avatar
 
Raymond Knopp committed
236

Cedric Roux's avatar
Cedric Roux committed
237 238 239 240
/* 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
241

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

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

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

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

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

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

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

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

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

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

321

Raymond Knopp's avatar
Raymond Knopp committed
322

323 324
void exit_fun(const char* s)
{
Raymond Knopp's avatar
Raymond Knopp committed
325
  int CC_id;
326
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
327

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

  oai_exit = 1;
333 334 335 336 337 338 339 340 341 342

  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
343
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
344 345 346 347

    oai_exit = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
348 349 350 351 352
      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
353
    }
354 355

#if defined(ENABLE_ITTI)
356 357
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
358
#endif
359

360
  }
361

362
}
363

364
#ifdef XFORMS
365

366

367 368
void reset_stats(FL_OBJECT *button, long arg)
{
369
  int i,j,k;
370
  PHY_VARS_eNB *phy_vars_eNB = RC.eNB[0][0];
371 372 373

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
374
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
375 376 377
	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;
378
      }
379

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


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

392
static void *scope_thread(void *arg) {
Raymond Knopp's avatar
 
Raymond Knopp committed
393
  char stats_buffer[16384];
394
# ifdef ENABLE_XFORMS_WRITE_STATS
Raymond Knopp's avatar
 
Raymond Knopp committed
395
  FILE *UE_stats, *eNB_stats;
396
# endif
Raymond Knopp's avatar
 
Raymond Knopp committed
397
  struct sched_param sched_param;
398
  int UE_id, CC_id;
399
  int ue_cnt=0;
400

401
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
Raymond Knopp's avatar
 
Raymond Knopp committed
402
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
403

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

406
# ifdef ENABLE_XFORMS_WRITE_STATS
407 408

  if (UE_flag==1)
Raymond Knopp's avatar
 
Raymond Knopp committed
409
    UE_stats  = fopen("UE_stats.txt", "w");
410
  else
Raymond Knopp's avatar
 
Raymond Knopp committed
411
    eNB_stats = fopen("eNB_stats.txt", "w");
412

413
#endif
414

Raymond Knopp's avatar
 
Raymond Knopp committed
415 416
  while (!oai_exit) {
    if (UE_flag==1) {
417
      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
418 419 420
      //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);
421

422
      phy_scope_UE(form_ue[0],
423 424 425 426
		   PHY_vars_UE_g[0][0],
		   0,
		   0,7);

427

Raymond Knopp's avatar
 
Raymond Knopp committed
428
    } else {
429
      /*
430
	if (RC.eNB[0][0]->mac_enabled==1) {
431 432 433 434
	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);
435 436
	}
	len = dump_eNB_stats (RC.eNB[0][0], stats_buffer, 0);
437

438 439
	if (MAX_NUM_CCs>1)
	len += dump_eNB_stats (RC.eNB[0][1], &stats_buffer[len], 0);
440

441 442 443
	//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);
444
      */
445 446
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
447
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
448
	  //	  if ((RC.eNB[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
449
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
450
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
451
			  RC.eNB[0][CC_id],
452 453 454
			  UE_id);
	    ue_cnt++;
	  }
455
	}
Raymond Knopp's avatar
 
Raymond Knopp committed
456
      }
457

458
    }
459
	
Raymond Knopp's avatar
 
Raymond Knopp committed
460
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
461 462
    //usleep(100000); // 100 ms
    sleep(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
463
  }
464

465
  //  printf("%s",stats_buffer);
466

467
# ifdef ENABLE_XFORMS_WRITE_STATS
468

469 470 471 472 473 474
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
475
  } else {
476 477 478 479 480 481
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
482

483
# endif
484

Raymond Knopp's avatar
 
Raymond Knopp committed
485
  pthread_exit((void*)arg);
486 487 488
}
#endif

489

490

491

Raymond Knopp's avatar
 
Raymond Knopp committed
492
#if defined(ENABLE_ITTI)
493
void *l2l1_task(void *arg) {
Raymond Knopp's avatar
 
Raymond Knopp committed
494 495 496 497 498
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
499

Raymond Knopp's avatar
 
Raymond Knopp committed
500 501
  if (UE_flag == 0) {
    /* Wait for the initialize message */
502
    printf("Wait for the ITTI initialize message\n");
503
    do {
Raymond Knopp's avatar
 
Raymond Knopp committed
504
      if (message_p != NULL) {
505 506
	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
507
      }
508

509 510 511
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
Raymond Knopp's avatar
 
Raymond Knopp committed
512
      case INITIALIZE_MESSAGE:
513 514 515 516
	/* 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
517 518

      case TERMINATE_MESSAGE:
519 520 521 522
	printf("received terminate message\n");
	oai_exit=1;
	itti_exit_task ();
	break;
Raymond Knopp's avatar
 
Raymond Knopp committed
523 524

      default:
525 526
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
527
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
528
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
529

Raymond Knopp's avatar
 
Raymond Knopp committed
530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550
    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;
551

Raymond Knopp's avatar
 
Raymond Knopp committed
552 553 554 555 556 557 558 559 560 561 562
    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);
563
  } while(!oai_exit);
564

Raymond Knopp's avatar
 
Raymond Knopp committed
565
  return NULL;
566 567 568
}
#endif

569

570 571 572 573 574
static void get_options(void) {
  int CC_id;
  int tddflag;
  char *loopfile=NULL;
  int dumpframe;
575 576
  uint32_t online_log_messages;
  uint32_t glog_level, glog_verbosity;
oai's avatar
oai committed
577
  uint32_t start_telnetsrv;
578

579
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
580
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
581 582 583 584 585 586 587 588 589 590 591 592 593

  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");
  }
594 595 596 597 598 599 600 601

  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);
  }
602
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGVERBO_IDX)) {
603 604
      set_glog(-1, glog_verbosity);
  }
oai's avatar
oai committed
605
  if (start_telnetsrv) {
606
     load_module_shlib("telnetsrv",NULL,0);
oai's avatar
oai committed
607 608
  }

609
  
610
  if (UE_flag > 0) {
oai's avatar
oai committed
611
     uint8_t n_rb_dl;
612 613
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
oai's avatar
oai committed
614

Florian Kaltenberger's avatar
Florian Kaltenberger committed
615
     set_default_frame_parms(frame_parms);
oai's avatar
oai committed
616

617 618 619 620 621 622 623 624
     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
625

626 627 628
      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;
629 630
      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;
Guy De Souza's avatar
Guy De Souza committed
631 632
      if ( (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = calib_prach_tx;
      if ( (cmdline_uemodeparams[CMDLINE_DUMPMEMORY_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = rx_dump_frame;
633 634
      
      if ( downlink_frequency[0][0] > 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
635 636 637 638 639
	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;
640 641
      } 

oai's avatar
oai committed
642 643 644 645
      if (tddflag > 0) {
         for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	     frame_parms[CC_id]->frame_type = TDD;
      }
646

647
      if (n_rb_dl !=0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
648
	printf("NB_RB set to %d\n",n_rb_dl);
649 650 651 652 653 654 655 656 657 658 659 660 661 662 663 664 665 666 667 668 669
	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;
	}
670 671
      }

672 673 674 675
      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];
676 677
      }
  } /* UE_flag > 0 */
678

679 680 681 682 683
#if T_TRACER
  paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
  config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);   
#endif

684 685 686 687
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
    if (UE_flag == 0) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
688
      RCConfig();
689 690
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
691
      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
692
    }
693
  } else if (UE_flag == 1 && (!(CONFIG_ISFLAGSET(CONFIG_NOOOPT))) ) {
694 695
    // 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
696 697
    sprintf(uecap_xer,"%stargets/PROJECTS/GENERIC-LTE-EPC/CONF/UE_config.xml",getenv("OPENAIR_HOME"));
    printf("%s\n",uecap_xer);
698 699
    uecap_xer_in=1;
  } /* UE with config file  */
700 701 702
}


703
#if T_TRACER
704
int T_nowait = 0;     /* by default we wait for the tracer */
705
int T_port = 2021;    /* default port to listen to to wait for the tracer */
706
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
707 708
#endif

709

710

711
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
Raymond Knopp's avatar
Raymond Knopp committed
712 713 714 715 716 717 718 719 720 721 722 723 724 725 726

  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;
727
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
Raymond Knopp's avatar
Raymond Knopp committed
728 729 730 731 732 733 734 735 736 737 738 739 740 741 742 743 744 745 746
    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;

747 748 749 750
//    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
751
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
752
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
Raymond Knopp's avatar
Raymond Knopp committed
753 754 755 756 757

  }

}

758 759
void init_openair0(void);

Raymond Knopp's avatar
Raymond Knopp committed
760 761 762 763 764 765 766 767 768 769 770 771 772
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;
773
	openair0_cfg[card].samples_per_frame = 230400;
Raymond Knopp's avatar
Raymond Knopp committed
774 775
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
776
      } else {
Raymond Knopp's avatar
Raymond Knopp committed
777
	openair0_cfg[card].sample_rate=30.72e6;
778
	openair0_cfg[card].samples_per_frame = 307200;
Raymond Knopp's avatar
Raymond Knopp committed
779 780 781 782 783 784 785 786 787 788 789 790 791 792 793 794 795 796 797 798 799 800 801 802 803 804 805 806 807
	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,
808 809
	   ((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
810 811 812
    openair0_cfg[card].Mod_id = 0;

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

814
    openair0_cfg[card].clock_source = clock_source;
815

816

817 818
    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));
819

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

Raymond Knopp's avatar
Raymond Knopp committed
822 823 824 825
      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;
826

Raymond Knopp's avatar
Raymond Knopp committed
827 828 829 830 831 832 833 834
      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) {
835
	openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;
Raymond Knopp's avatar
Raymond Knopp committed
836 837
      }
      else {
838
	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
839 840
      }

841
      openair0_cfg[card].configFilename = rf_config_file;
842
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
843 844 845 846
	     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]);
847
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
848
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
849
}
850

851

852
void wait_RUs(void) {
853

854
  LOG_I(PHY,"Waiting for RUs to be configured ... RC.ru_mask:%02lx\n", RC.ru_mask);
855 856 857 858 859 860 861 862

  // 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);
863
    printf("RC.ru_mask:%02lx\n", RC.ru_mask);
864 865 866 867 868
  }

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

869
void wait_eNBs(void) {
870 871 872 873 874 875

  int i,j;
  int waiting=1;


  while (waiting==1) {
Cedric Roux's avatar
Cedric Roux committed
876 877
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(50*1000);
878
    waiting=0;
879 880 881 882 883
    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++) {
884 885 886
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
887 888 889
        } 
      }
    }
890 891 892
  }
  printf("eNB L1 are configured\n");
}
893

894 895 896 897 898 899 900 901 902 903 904 905 906
static inline void wait_nfapi_init(char *thread_name) {

  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
  
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
  
  pthread_mutex_unlock(&nfapi_sync_mutex);
  
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

907 908
int main( int argc, char **argv )
{
909
  int i;
910
#if defined (XFORMS)
Raymond Knopp's avatar
 
Raymond Knopp committed
911
  void *status;
912
#endif
913

Raymond Knopp's avatar
 
Raymond Knopp committed
914
  int CC_id;
915
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
916
  uint8_t  abstraction_flag=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
917
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
918

Raymond Knopp's avatar
 
Raymond Knopp committed
919
#if defined (XFORMS)
920 921
  int ret;
#endif
922

923
  start_background_system();
924 925 926 927
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
      
928 929 930 931 932
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

933 934 935
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

938
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
939

Raymond Knopp's avatar
 
Raymond Knopp committed
940
  set_latency_target();
941 942


Raymond Knopp's avatar
Raymond Knopp committed
943
  // set default parameters
Florian Kaltenberger's avatar
Florian Kaltenberger committed
944
  //if (UE_flag == 1) set_default_frame_parms(frame_parms);
945

946
  logInit();
Raymond Knopp's avatar
Raymond Knopp committed
947

948
  printf("Reading in command-line options\n");
949

950
  get_options (); 
951
  if (CONFIG_ISFLAGSET(CONFIG_ABORT) && UE_flag == 0) {
952 953
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
954
  }
Raymond Knopp's avatar
Raymond Knopp committed
955 956


957
#if T_TRACER
958
  T_init(T_port, 1-T_nowait, T_dont_fork);
959 960
#endif

961

Florian Kaltenberger's avatar
Florian Kaltenberger committed
962

963 964
  //randominit (0);
  set_taus_seed (0);
Raymond Knopp's avatar
 
Raymond Knopp committed
965

966 967
  if (UE_flag==1) {
    printf("configuring for UE\n");
968

969
    set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
Florian Kaltenberger's avatar
Florian Kaltenberger committed
970
    set_comp_log(PHY,     LOG_INFO,   LOG_HIGH, 1);
971
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
972
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH | FLAG_THREAD, 1);
973 974 975
    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);
976
#if defined(ENABLE_ITTI)
977
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
978
# if defined(ENABLE_USE_MME)
979
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
980 981
# endif
#endif
982

983
  } else {
984
    printf("configuring for RAU/RRU\n");
985

986
  }
987

Raymond Knopp's avatar
 
Raymond Knopp committed
988 989
  if (ouput_vcd) {
    if (UE_flag==1)
990
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
991
    else
992
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
Raymond Knopp's avatar
 
Raymond Knopp committed
993
  }
994

995
  if (opp_enabled ==1) {
996
    reset_opp_meas();
997 998
  }
  cpuf=get_cpu_freq_GHz();
999

1000
#if defined(ENABLE_ITTI)
1001

Raymond Knopp's avatar
 
Raymond Knopp committed
1002 1003
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
1004
  } else {
Raymond Knopp's avatar
 
Raymond Knopp committed
1005 1006
    log_set_instance_type (LOG_INSTANCE_ENB);
  }
1007

1008
  printf("ITTI init\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1009
  itti_init(TASK_MAX, THREAD_MAX, MESSAGES_ID_MAX, tasks_info, messages_info, messages_definition_xml, itti_dump_file);
1010

1011 1012
  // initialize mscgen log after ITTI
  MSC_INIT(MSC_E_UTRAN, THREAD_MAX+TASK_MAX);
1013
#endif
1014

1015 1016
  if (opt_type != OPT_NONE) {
    radio_type_t radio_type;
1017

1018 1019
    if (frame_parms[0]->frame_type == FDD)
      radio_type = RADIO_TYPE_FDD;
1020
    else
1021
      radio_type = RADIO_TYPE_TDD;
1022

1023 1024 1025
    if (init_opt(in_path, in_ip, NULL, radio_type) == -1)
      LOG_E(OPT,"failed to run OPT \n");
  }
1026

1027
#ifdef PDCP_USE_NETLINK
1028
  printf("PDCP netlink\n");
Raymond Knopp's avatar
 
Raymond Knopp committed
1029
  netlink_init();
1030 1031 1032
#if defined(PDCP_USE_NETLINK_QUEUES)
  pdcp_netlink_init();
#endif
1033 1034
#endif

1035
#if !defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
1036 1037 1038
  // to make a graceful exit when ctrl-c is pressed
  signal(SIGSEGV, signal_handler);
  signal(SIGINT, signal_handler);
1039
#endif
1040

1041

Raymond Knopp's avatar
 
Raymond Knopp committed
1042 1043
  check_clock();

1044 1045 1046 1047 1048 1049
#ifndef PACKAGE_VERSION
#  define PACKAGE_VERSION "UNKNOWN-EXPERIMENTAL"
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1050
  // init the parameters
1051 1052
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {

Raymond Knopp's avatar
Raymond Knopp committed
1053
    if (UE_flag==1) {
1054 1055
      frame_parms[CC_id]->nb_antennas_tx     = nb_antenna_tx;
      frame_parms[CC_id]->nb_antennas_rx     = nb_antenna_rx;
1056
      frame_parms[CC_id]->nb_antenna_ports_eNB = 1; //initial value overwritten by initial sync later
1057
    }
Raymond Knopp's avatar
 
Raymond Knopp committed
1058 1059 1060
  }


Raymond Knopp's avatar
 
Raymond Knopp committed
1061

1062
  printf("Before CC \n");
1063

1064
  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
1065

1066

1067 1068 1069 1070 1071 1072 1073 1074
    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);
      
      
      
1075
      PHY_vars_UE_g[0][CC_id] = init_ue_vars(frame_parms[CC_id], 0,abstraction_flag);
1076 1077
      UE[CC_id] = PHY_vars_UE_g[0][CC_id];
      printf("PHY_vars_UE_g[0][%d] = %p\n",CC_id,UE[CC_id]);
1078
      
1079 1080 1081 1082
      if (phy_test==1)
	UE[CC_id]->mac_enabled = 0;
      else 
	UE[CC_id]->mac_enabled = 1;
1083
      
1084
      if (UE[CC_id]->mac_enabled == 0) {  //set default UL parameters for testing mode
1085 1086 1087 1088 1089 1090 1091 1092 1093
	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
1094
      }
1095
      
1096
      UE[CC_id]->UE_scan = UE_scan;
1097
      UE[CC_id]->UE_scan_carrier = UE_scan_carrier;
1098
      UE[CC_id]->mode    = mode;
Rohit Gupta's avatar
Rohit Gupta committed
1099
      printf("UE[%d]->mode = %d\n",CC_id,mode);
1100 1101 1102 1103 1104 1105 1106 1107
      
      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;
      }
1108
      UE[CC_id]->rx_total_gain_dB =  (int)rx_gain[CC_id][0] + rx_gain_off;
1109
      UE[CC_id]->tx_power_max_dBm = tx_max_power[CC_id];
1110 1111 1112 1113 1114 1115 1116 1117 1118 1119 1120
      
      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;
1121
      }
1122
    init_openair0();      
Raymond Knopp's avatar
 
Raymond Knopp committed
1123
    }
1124

Raymond Knopp's avatar
 
Raymond Knopp committed
1125
  }
1126

1127
  printf("Runtime table\n");
1128 1129
  fill_modeled_runtime_table(runtime_phy_rx,runtime_phy_tx);
  cpuf=get_cpu_freq_GHz();
1130 1131 1132
  
  
  
laurent's avatar
laurent committed
1133
#ifndef DEADLINE_SCHEDULER
1134
  
1135
  printf("NO deadline scheduler\n");
1136
  /* Currently we set affinity for UHD to CPU 0 for eNB/UE and only if number of CPUS >2 */
1137 1138 1139 1140 1141
  
  cpu_set_t cpuset;
  int s;
  char cpu_affinity[1024];
  CPU_ZERO(&cpuset);
1142
#ifdef CPU_AFFINITY
1143 1144 1145
  if (get_nprocs() > 2) {
    CPU_SET(0, &cpuset);
    s = pthread_setaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1146
    if (s != 0) {
1147 1148
      perror( "pthread_setaffinity_np");
      exit_fun("Error setting processor affinity");
1149
    }
1150 1151
    LOG_I(HW, "Setting the affinity of main function to CPU 0, for device library to use CPU 0 only!\n");
  }
1152
#endif
1153
  
1154 1155
  /* Check the actual affinity mask assigned to the thread */
  s = pthread_getaffinity_np(pthread_self(), sizeof(cpu_set_t), &cpuset);
1156 1157 1158 1159
  if (s != 0) {
    perror( "pthread_getaffinity_np");
    exit_fun("Error getting processor affinity ");
  }
1160
  memset(cpu_affinity, 0 , sizeof(cpu_affinity));
1161 1162 1163 1164 1165
  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);
1166
    }
1167
  }
1168
  LOG_I(HW, "CPU Affinity of main() function is... %s\n", cpu_affinity);
1169
#endif
1170
  
1171

1172
  
1173
  
winckel's avatar
winckel committed
1174
#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
Raymond Knopp committed
1175
  if ((UE_flag == 1)||
1176
      (RC.nb_inst > 0))  {
1177
    
Raymond Knopp's avatar
Raymond Knopp committed
1178 1179 1180 1181 1182
    // 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
    }
1183
    
1184 1185 1186
    printf("ITTI tasks created\n");
  }
  else {
1187 1188
    printf("No ITTI, Initializing L1\n");
    RCconfig_L1();
1189
  }
winckel's avatar
winckel committed
1190
#endif
1191 1192
  
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1193
  mlockall(MCL_CURRENT | MCL_FUTURE);
1194
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1195 1196
  pthread_cond_init(&sync_cond,NULL);
  pthread_mutex_init(&sync_mutex, NULL);
1197
  
1198
#ifdef XFORMS
1199
  int UE_id;
1200
  
1201 1202
  printf("XFORMS\n");

Raymond Knopp's avatar
 
Raymond Knopp committed
1203 1204
  if (do_forms==1) {
    fl_initialize (&argc, argv, NULL, 0, 0);
1205
    
1206
    if (UE_flag==0) {
1207
      form_stats_l2 = create_form_stats_form();
1208 1209 1210
      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");
1211
      
1212
      for(UE_id=0; UE_id<scope_enb_num_ue; UE_id++) {
1213 1214 1215 1216
	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);
1217
	  
1218 1219 1220 1221 1222 1223 1224
	  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");
	  }
1225 1226
	} // CC_id
      } // UE_id
1227
    } else {
1228 1229 1230 1231 1232 1233
      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);
1234
      
1235
      /*
1236
	if (openair_daq_vars.use_ia_receiver) {
1237 1238
	fl_set_button(form_ue[UE_id]->button_0,1);
	fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver ON");
1239
	} else {
1240 1241
	fl_set_button(form_ue[UE_id]->button_0,0);
	fl_set_object_label(form_ue[UE_id]->button_0, "IA Receiver OFF");
1242
	}*/
1243 1244
      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
1245
    }
1246
    
Raymond Knopp's avatar
 
Raymond Knopp committed
1247
    ret = pthread_create(&forms_thread, NULL, scope_thread, NULL);
1248
    
1249 1250
    if (ret == 0)
      pthread_setname_np( forms_thread, "xforms" );
1251
    
Raymond Knopp's avatar
 
Raymond Knopp committed
1252 1253
    printf("Scope thread created, ret=%d\n",ret);
  }
1254
  
1255
#endif
1256
  
1257
  rt_sleep_ns(10*100000000ULL);
Cedric Roux's avatar
Cedric Roux committed
1258

1259 1260 1261 1262 1263 1264
  if (nfapi_mode) {

    printf("NFAPI*** - mutex and cond created - will block shortly for completion of PNF connection\n");
    pthread_cond_init(&sync_cond,NULL);
    pthread_mutex_init(&sync_mutex, NULL);
  }
1265
  
1266 1267 1268 1269 1270 1271 1272 1273 1274 1275 1276 1277 1278 1279 1280 1281 1282 1283 1284 1285 1286 1287
  const char *nfapi_mode_str = "<UNKNOWN>";

  switch(nfapi_mode) {
    case 0:
      nfapi_mode_str = "MONOLITHIC";
      break;
    case 1:
      nfapi_mode_str = "PNF";
      break;
    case 2:
      nfapi_mode_str = "VNF";
      break;
    default:
      nfapi_mode_str = "<UNKNOWN NFAPI MODE>";
      break;
  }
  printf("NFAPI MODE:%s\n", nfapi_mode_str);

  if (nfapi_mode==2) // VNF
    wait_nfapi_init("main?");

  printf("START MAIN THREADS\n");
1288
  
1289
  // start the main threads
Raymond Knopp's avatar
 
Raymond Knopp committed
1290
  if (UE_flag == 1) {
1291
    int eMBMS_active = 0;
1292
    init_UE(1,eMBMS_active,uecap_xer_in,0);
1293 1294 1295 1296 1297 1298 1299

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

1300 1301 1302 1303
    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
1304
    }
1305
  }
Raymond Knopp's avatar
Raymond Knopp committed
1306
  else { 
1307
    number_of_cards = 1;    
1308
    printf("RC.nb_L1_inst:%d\n", RC.nb_L1_inst);
1309
    if (RC.nb_L1_inst > 0) {
1310
      printf("Initializing eNB threads single_thread_flag:%d wait_for_sync:%d\n", single_thread_flag,wait_for_sync);
1311
      init_eNB(single_thread_flag,wait_for_sync);
1312 1313
      //      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
1314
    }
1315

1316
    printf("wait_eNBs()\n");
1317 1318
    wait_eNBs();

1319
    printf("About to Init RU threads RC.nb_RU:%d\n", RC.nb_RU);
1320 1321 1322 1323 1324 1325 1326 1327
    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;
      }
    }
1328

1329 1330 1331 1332 1333 1334 1335
    config_sync_var=0;

    if (nfapi_mode==1) { // PNF
      wait_nfapi_init("main?");
    }

    printf("wait RUs\n");
1336
    wait_RUs();
1337 1338
    printf("ALL RUs READY!\n");
    printf("RC.nb_RU:%d\n", RC.nb_RU);
1339
    // once all RUs are ready intiailize the rest of the eNBs ((dependence on final RU parameters after configuration)
1340 1341 1342 1343 1344 1345 1346 1347 1348 1349 1350
    printf("ALL RUs ready - init eNBs\n");

    if (nfapi_mode != 1 && nfapi_mode != 2)
    {
      printf("Not NFAPI mode - call init_eNB_afterRU()\n");
      init_eNB_afterRU();
    }
    else
    {
      printf("NFAPI mode - DO NOT call init_eNB_afterRU()\n");
    }
1351
    
1352
    printf("ALL RUs ready - ALL eNBs ready\n");
1353
  }
1354 1355
  
  
1356 1357 1358
  // connect the TX/RX buffers
  if (UE_flag==1) {
    
1359 1360 1361
    for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
      
      
1362 1363 1364 1365
#ifdef OAI_USRP
      UE[CC_id]->hw_timing_advance = timing_advance;
#else
      UE[CC_id]->hw_timing_advance = 160;
1366
#endif
1367 1368 1369 1370
    }
    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
1371
    }
1372 1373 1374
    
    
    
1375 1376 1377
    if (input_fd) {
      printf("Reading in from file to antenna buffer %d\n",0);
      if (fread(UE[0]->common_vars.rxdata[0],
1378 1379 1380 1381
		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");
1382 1383 1384
    }
    //p_exmimo_config->framing.tdd_config = TXRXSWITCH_TESTRX;
  } else {
1385
    
1386
    printf("eNB mode\n");
1387
    
1388
  }
1389
  
1390
  printf("Sending sync to all threads\n");
1391
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1392
  pthread_mutex_lock(&sync_mutex);
1393
  sync_var=0;
Raymond Knopp's avatar
 
Raymond Knopp committed
1394 1395
  pthread_cond_broadcast(&sync_cond);
  pthread_mutex_unlock(&sync_mutex);
1396
  printf("About to call end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
1397
  end_configmodule();
1398
  printf("Called end_configmodule() from %s() %s:%d\n", __FUNCTION__, __FILE__, __LINE__);
1399

1400
  // wait for end of program
Raymond Knopp's avatar
 
Raymond Knopp committed
1401 1402
  printf("TYPE <CTRL-C> TO TERMINATE\n");
  //getchar();
1403 1404

#if defined(ENABLE_ITTI)
Raymond Knopp's avatar
 
Raymond Knopp committed
1405 1406
  printf("Entering ITTI signals handler\n");
  itti_wait_tasks_end();
1407
  printf("Returned from ITTI signal handler\n");
1408
  oai_exit=1;
1409
  printf("oai_exit=%d\n",oai_exit);
1410
#else
1411

Raymond Knopp's avatar
 
Raymond Knopp committed
1412
  while (oai_exit==0)
1413
    rt_sleep_ns(100000000ULL);
1414
  printf("Terminating application - oai_exit=%d\n",oai_exit);
1415

1416
#endif
1417

Raymond Knopp's avatar
 
Raymond Knopp committed
1418
  // stop threads
1419
#ifdef XFORMS
Raymond Knopp's avatar
 
Raymond Knopp committed
1420
  printf("waiting for XFORMS thread\n");
1421 1422 1423 1424 1425 1426 1427 1428 1429 1430 1431 1432 1433 1434

  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++) {
1435 1436 1437 1438
	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
1439
      }
Raymond Knopp's avatar
 
Raymond Knopp committed
1440
    }
1441 1442
  }

1443 1444
#endif

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

Raymond Knopp's avatar
 
Raymond Knopp committed
1447 1448
  // cleanup
  if (UE_flag == 1) {
1449
  } else {
1450
    stop_eNB(1);
Raymond Knopp's avatar
 
Raymond Knopp committed
1451
  }
1452

1453

Raymond Knopp's avatar
 
Raymond Knopp committed
1454 1455
  pthread_cond_destroy(&sync_cond);
  pthread_mutex_destroy(&sync_mutex);
1456

1457 1458 1459
  pthread_cond_destroy(&nfapi_sync_cond);
  pthread_mutex_destroy(&nfapi_sync_mutex);

1460

1461

Raymond Knopp's avatar
Raymond Knopp committed
1462
  // *** Handle per CC_id openair0
Raymond Knopp's avatar
Raymond Knopp committed
1463 1464 1465 1466 1467
  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 {
1468 1469 1470 1471 1472
    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);  
1473

Raymond Knopp's avatar
Raymond Knopp committed
1474
    }
1475
  }
Raymond Knopp's avatar
 
Raymond Knopp committed
1476
  if (ouput_vcd)
1477
    VCD_SIGNAL_DUMPER_CLOSE();
1478
  
1479
  if (opt_enabled == 1)
1480
    terminate_opt();
1481
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1482
  logClean();
1483
  
Raymond Knopp's avatar
 
Raymond Knopp committed
1484 1485
  return 0;
}