lte-softmodem.c 39 KB
Newer Older
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22
23
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
   
knopp committed
25
26
27
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
knopp's avatar
   
knopp committed
29
30
31
 * \note
 * \warning
 */
32

33

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

37

38
39
#include "T.h"

40
#include "rt_wrapper.h"
41

42

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

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

#include "PHY/types.h"
49

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

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

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

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

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

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

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

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

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

96
97
#include "system.h"

98
99
100
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
101
#endif
102
#include "lte-softmodem.h"
103

104

105
#ifdef XFORMS
106
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
gauthier's avatar
gauthier committed
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

knopp's avatar
   
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]
knopp's avatar
   
knopp committed
122

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

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

knopp's avatar
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];
gauthier's avatar
gauthier committed
140

141

oai's avatar
oai committed
142

143
#if defined(ENABLE_ITTI)
144
static char                    *itti_dump_file = NULL;
knopp's avatar
   
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}};
gauthier's avatar
gauthier committed
162
#endif
knopp's avatar
   
knopp committed
163

fnabet's avatar
fnabet committed
164
double rx_gain_off = 0.0;
165

knopp's avatar
   
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

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

186
int                      rx_input_level_dBm;
oai's avatar
oai committed
187

188
#ifdef XFORMS
189
extern int                      otg_enabled;
190
static char                     do_forms=0;
191
#else
192
int                             otg_enabled;
193
#endif
knopp's avatar
   
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;
knopp's avatar
   
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};
knopp's avatar
   
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;
knopp's avatar
   
knopp committed
229

230
231
232
233
234
/*---------------------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 };

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

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

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

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

274
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
knopp's avatar
   
knopp committed
275
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
276
}
277
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
knopp's avatar
   
knopp committed
278
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
279
280
}

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

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

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

306

Raymond Knopp's avatar
Raymond Knopp committed
307

308
309
void exit_fun(const char* s)
{
Raymond Knopp's avatar
Raymond Knopp committed
310
  int CC_id;
311
  int ru_id;
Raymond Knopp's avatar
Raymond Knopp committed
312

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

  oai_exit = 1;
318
319
320
321
322
323
324
325
326
327

  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
328
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
329
330
331
332

    oai_exit = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
333
334
335
336
337
      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);
      }
knopp's avatar
knopp committed
338
    }
339
340

#if defined(ENABLE_ITTI)
341
342
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
343
#endif
344

345
  }
346

347
}
348

349
#ifdef XFORMS
350

351

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

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

365
366
367
      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;
368
369


370
371
372
      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;
373
374
375
376
    }
  }
}

377
static void *scope_thread(void *arg) {
knopp's avatar
   
knopp committed
378
  char stats_buffer[16384];
379
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
   
knopp committed
380
  FILE *UE_stats, *eNB_stats;
381
# endif
knopp's avatar
   
knopp committed
382
  struct sched_param sched_param;
383
  int UE_id, CC_id;
384
  int ue_cnt=0;
385

386
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
   
knopp committed
387
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
388

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

391
# ifdef ENABLE_XFORMS_WRITE_STATS
392
393

  if (UE_flag==1)
knopp's avatar
   
knopp committed
394
    UE_stats  = fopen("UE_stats.txt", "w");
395
  else
knopp's avatar
   
knopp committed
396
    eNB_stats = fopen("eNB_stats.txt", "w");
397

398
#endif
399

knopp's avatar
   
knopp committed
400
401
  while (!oai_exit) {
    if (UE_flag==1) {
oai's avatar
oai committed
402
      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
403
404
405
      //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);
406

407
      phy_scope_UE(form_ue[0],
408
409
410
411
		   PHY_vars_UE_g[0][0],
		   0,
		   0,7);

412

knopp's avatar
   
knopp committed
413
    } else {
414
      /*
415
	if (RC.eNB[0][0]->mac_enabled==1) {
416
417
418
419
	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);
420
421
	}
	len = dump_eNB_stats (RC.eNB[0][0], stats_buffer, 0);
422

423
424
	if (MAX_NUM_CCs>1)
	len += dump_eNB_stats (RC.eNB[0][1], &stats_buffer[len], 0);
425

426
427
428
	//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);
429
      */
430
431
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
432
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
433
	  //	  if ((RC.eNB[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
434
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
435
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
436
			  RC.eNB[0][CC_id],
437
438
439
			  UE_id);
	    ue_cnt++;
	  }
440
	}
knopp's avatar
   
knopp committed
441
      }
442

443
    }
444
	
knopp's avatar
   
knopp committed
445
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
446
447
    //usleep(100000); // 100 ms
    sleep(1);
knopp's avatar
   
knopp committed
448
  }
449

450
  //  printf("%s",stats_buffer);
451

452
# ifdef ENABLE_XFORMS_WRITE_STATS
453

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

468
# endif
469

knopp's avatar
   
knopp committed
470
  pthread_exit((void*)arg);
471
472
473
}
#endif

474

475

476

knopp's avatar
   
knopp committed
477
#if defined(ENABLE_ITTI)
478
void *l2l1_task(void *arg) {
knopp's avatar
   
knopp committed
479
480
481
482
483
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
484

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

494
495
496
      itti_receive_msg (TASK_L2L1, &message_p);

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

      case TERMINATE_MESSAGE:
504
505
506
507
	printf("received terminate message\n");
	oai_exit=1;
	itti_exit_task ();
	break;
knopp's avatar
   
knopp committed
508
509

      default:
510
511
	LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
	break;
512
      }
knopp's avatar
   
knopp committed
513
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
514

knopp's avatar
   
knopp committed
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
    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;
536

knopp's avatar
   
knopp committed
537
538
539
540
541
542
543
544
545
546
547
    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);
thomasl's avatar
thomasl committed
548
  } while(!oai_exit);
549

knopp's avatar
   
knopp committed
550
  return NULL;
551
552
553
}
#endif

554

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

564
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
oai's avatar
oai committed
565
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
566
567
568
569
570
571
572
573
574
575
576
577
578

  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");
  }
oai's avatar
oai committed
579
580
581
582
583
584
585
586
587
588
589

  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);
  }
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
      set_glog(-1, glog_verbosity);
  }
oai's avatar
oai committed
590
591
592
593
  if (start_telnetsrv) {
     load_module_shlib("telnetsrv");
  }

oai's avatar
oai committed
594
  
595
596
597
  if (UE_flag > 0) {
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
oai's avatar
oai committed
598
599
600



601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
     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");
      }
      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;
      if ( *(cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].uptr) > 0) mode = debug_prach;
      if ( *(cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].uptr) > 0)  mode = no_L2_connect;
      if ( *(cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].uptr) > 0) mode = calib_prach_tx; 
      if (dumpframe  > 0)  mode = rx_dump_frame;
      
      if ( downlink_frequency[0][0] > 0) {
  	  for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
  	    downlink_frequency[CC_id][1] = downlink_frequency[0][0];
  	    downlink_frequency[CC_id][2] = downlink_frequency[0][0];
  	    downlink_frequency[CC_id][3] = downlink_frequency[0][0];
  	    printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
  	  }
      UE_scan=0;
      } 

oai's avatar
oai committed
627
628
629
630
      if (tddflag > 0) {
         for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	     frame_parms[CC_id]->frame_type = TDD;
      }
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668

      if (frame_parms[0]->N_RB_DL !=0) {
  	  if ( frame_parms[0]->N_RB_DL < 6 ) {
  	     frame_parms[0]->N_RB_DL = 6;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 6\n",frame_parms[0]->N_RB_DL);
  	  }
  	  if ( frame_parms[0]->N_RB_DL > 100 ) {
  	     frame_parms[0]->N_RB_DL = 100;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 100\n",frame_parms[0]->N_RB_DL);
  	  }
  	  if ( frame_parms[0]->N_RB_DL > 50 && frame_parms[0]->N_RB_DL < 100 ) {
  	     frame_parms[0]->N_RB_DL = 50;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 50\n",frame_parms[0]->N_RB_DL);
  	  }
  	  if ( frame_parms[0]->N_RB_DL > 25 && frame_parms[0]->N_RB_DL < 50 ) {
  	     frame_parms[0]->N_RB_DL = 25;
  	     printf ( "%i: Invalid number of ressource blocks, adjusted to 25\n",frame_parms[0]->N_RB_DL);
  	  }
  	  UE_scan = 0;
  	  frame_parms[0]->N_RB_UL=frame_parms[0]->N_RB_DL;
  	  for (CC_id=1; CC_id<MAX_NUM_CCs; CC_id++) {
  	      frame_parms[CC_id]->N_RB_DL=frame_parms[0]->N_RB_DL;
  	      frame_parms[CC_id]->N_RB_UL=frame_parms[0]->N_RB_UL;
  	  }
      }


      for (CC_id=1;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];
      }
  } /* UE_flag > 0 */
#if T_TRACER
  paramdef_t cmdline_ttraceparams[] =CMDLINE_TTRACEPARAMS_DESC ;
  config_process_cmdline( cmdline_ttraceparams,sizeof(cmdline_ttraceparams)/sizeof(paramdef_t),NULL);   
#endif

669
670
671
672
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
    if (UE_flag == 0) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
673
      RCConfig();
674
675
676
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
      printf("Configuration: nb_inst %d, nb_ru %d\n",NB_eNB_INST,NB_RU);
677
    }
678
679
680
681
682
683
  } else if (UE_flag == 1 && (CONFIG_GETCONFFILE != NULL)) {
    // Here the configuration file is the XER encoded UE capabilities
    // Read it in and store in asn1c data structures
    strcpy(uecap_xer,CONFIG_GETCONFFILE);
    uecap_xer_in=1;
  } /* UE with config file  */
684
685
686
}


687
  
688
689
690
#if T_TRACER
int T_wait = 1;       /* by default we wait for the tracer */
int T_port = 2021;    /* default port to listen to to wait for the tracer */
691
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
692
693
#endif

694

knopp's avatar
knopp committed
695
696
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
knopp's avatar
knopp committed
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711

  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;
712
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;

    frame_parms[CC_id]->nushift             = 0;

    frame_parms[CC_id]->phich_config_common.phich_resource = oneSixth;
    frame_parms[CC_id]->phich_config_common.phich_duration = normal;
    // UL RS Config
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.cyclicShift = 0;//n_DMRS1 set to 0
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.sequenceHoppingEnabled = 0;
    frame_parms[CC_id]->pusch_config_common.ul_ReferenceSignalsPUSCH.groupAssignmentPUSCH = 0;

    frame_parms[CC_id]->prach_config_common.rootSequenceIndex=22;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.zeroCorrelationZoneConfig=1;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_ConfigIndex=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.highSpeedFlag=0;
    frame_parms[CC_id]->prach_config_common.prach_ConfigInfo.prach_FreqOffset=0;

    downlink_frequency[CC_id][0] = 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];
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);

  }

}

knopp's avatar
knopp committed
742
743
void init_openair0(void);

knopp's avatar
knopp committed
744
745
746
747
748
749
750
751
752
753
754
755
756
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;
757
	openair0_cfg[card].samples_per_frame = 230400;
knopp's avatar
knopp committed
758
759
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
760
      } else {
knopp's avatar
knopp committed
761
	openair0_cfg[card].sample_rate=30.72e6;
762
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
knopp committed
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
	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,
792
793
	   ((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));
knopp's avatar
knopp committed
794
795
796
    openair0_cfg[card].Mod_id = 0;

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

798
    openair0_cfg[card].clock_source = clock_source;
799

800

801
802
    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));
803

knopp's avatar
knopp committed
804
    for (i=0; i<4; i++) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
805

knopp's avatar
knopp committed
806
807
808
809
      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;
810

knopp's avatar
knopp committed
811
812
813
814
815
816
817
818
      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) {
819
	openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;
knopp's avatar
knopp committed
820
821
      }
      else {
fnabet's avatar
fnabet committed
822
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
knopp's avatar
knopp committed
823
824
      }

825
      openair0_cfg[card].configFilename = rf_config_file;
826
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
827
828
829
830
	     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]);
831
    }
knopp's avatar
   
knopp committed
832
  }
knopp's avatar
   
knopp committed
833
}
834

835

836
void wait_RUs(void) {
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851

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

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

852
void wait_eNBs(void) {
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870

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

872
873
int main( int argc, char **argv )
{
874
  int i;
875
#if defined (XFORMS)
knopp's avatar
   
knopp committed
876
  void *status;
877
#endif
878

knopp's avatar
   
knopp committed
879
  int CC_id;
880
  int ru_id;
knopp's avatar
knopp committed
881
  uint8_t  abstraction_flag=0;
knopp's avatar
   
knopp committed
882
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
883

knopp's avatar
   
knopp committed
884
#if defined (XFORMS)
885
886
  int ret;
#endif
887

888
  start_background_system();
889
890
891
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
892

893
      
894
895
896
897
898
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

899
900
901
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

904
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
905

knopp's avatar
   
knopp committed
906
  set_latency_target();
907
908


knopp's avatar
knopp committed
909
  // set default parameters
910
  if (UE_flag == 1) set_default_frame_parms(frame_parms);
911

912
  logInit();
knopp's avatar
knopp committed
913

914
  printf("Reading in command-line options\n");
915

916
  get_options (); 
oai's avatar
oai committed
917
918
919
  if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
920
  }
knopp's avatar
knopp committed
921
922
923



924
#if T_TRACER
925
  T_init(T_port, T_wait, T_dont_fork);
926
927
#endif

oai's avatar
oai committed
928

Florian Kaltenberger's avatar
Florian Kaltenberger committed
929

nikaeinn's avatar
nikaeinn committed
930
931
  //randominit (0);
  set_taus_seed (0);
knopp's avatar
   
knopp committed
932

933
934
  if (UE_flag==1) {
    printf("configuring for UE\n");
935

936
937
    set_comp_log(HW,      LOG_DEBUG,  LOG_HIGH, 1);
    set_comp_log(PHY,     LOG_DEBUG,   LOG_HIGH, 1);
938
    set_comp_log(MAC,     LOG_INFO,   LOG_HIGH, 1);
939
    set_comp_log(RLC,     LOG_INFO,   LOG_HIGH | FLAG_THREAD, 1);
940
941
942
    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);
943
#if defined(ENABLE_ITTI)
944
    set_comp_log(EMU,     LOG_INFO,   LOG_MED, 1);
945
# if defined(ENABLE_USE_MME)
946
    set_comp_log(NAS,     LOG_INFO,   LOG_HIGH, 1);
947
948
# endif
#endif
949

950
  } else {
951
    printf("configuring for RAU/RRU\n");
952

953
  }
954

knopp's avatar
   
knopp committed
955
956
  if (ouput_vcd) {
    if (UE_flag==1)
gauthier's avatar
gauthier committed
957
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_UE.vcd");
knopp's avatar
   
knopp committed
958
    else
gauthier's avatar
gauthier committed
959
      VCD_SIGNAL_DUMPER_INIT("/tmp/openair_dump_eNB.vcd");
knopp's avatar
   
knopp committed
960
  }
961

962
  if (opp_enabled ==1) {
963
    reset_opp_meas();
964
965
  }
  cpuf=get_cpu_freq_GHz();
966

967
#if defined(ENABLE_ITTI)
968

knopp's avatar
   
knopp committed
969
970
  if (UE_flag == 1) {
    log_set_instance_type (LOG_INSTANCE_UE);
971
  } else {
knopp's avatar