lte-softmodem.c 41.5 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
Cedric Roux's avatar
Cedric Roux committed
6
 * the OAI Public License, Version 1.1  (the "License"); you may not use this file
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

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

33

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

37

38
39
#include "T.h"

40
#include "rt_wrapper.h"
41

42

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

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

#include "PHY/types.h"
49

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

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

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

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

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

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

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

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

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

96
97
#include "system.h"

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

104
#ifdef XFORMS
105
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
gauthier's avatar
gauthier committed
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
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

119
uint8_t nfapi_mode = 2;
120

121
122
uint16_t sf_ahead=4;

123
124
char emul_iface[100];

knopp's avatar
   
knopp committed
125
126
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
127
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
128
int config_sync_var=-1;
129

130
131
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
132

133
#if defined(ENABLE_ITTI)
134
135
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
136
#endif
knopp's avatar
knopp committed
137
volatile int             oai_exit = 0;
138

139
static clock_source_t clock_source = internal;
140
static int wait_for_sync = 0;
knopp's avatar
   
knopp committed
141

knopp's avatar
knopp committed
142
static char              UE_flag=0;
143
unsigned int                    mmapped_dma=0;
144
int                             single_thread_flag=1;
145

146
static char                     threequarter_fs=0;
147

148
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
149
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
150

151

oai's avatar
oai committed
152

153
#if defined(ENABLE_ITTI)
154
static char                    *itti_dump_file = NULL;
knopp's avatar
   
knopp committed
155
156
#endif

157
int UE_scan = 1;
158
int UE_scan_carrier = 0;
159
160
runmode_t mode = normal_txrx;

161
162
FILE *input_fd=NULL;

163

164
165
#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
166
167
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
168
169
170
171
#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
172
#endif
knopp's avatar
   
knopp committed
173

fnabet's avatar
fnabet committed
174
double rx_gain_off = 0.0;
175

knopp's avatar
   
knopp committed
176
double sample_rate=30.72e6;
177
double bw = 10.0e6;
178

179
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
180

181
182
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
183
int chain_offset=0;
184
int phy_test = 0;
185
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
186

187
188
189
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

190
191
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
192

knopp's avatar
   
knopp committed
193
194
195
char ref[128] = "internal";
char channels[128] = "0";

196
int                      rx_input_level_dBm;
oai's avatar
oai committed
197

198
#ifdef XFORMS
199
extern int                      otg_enabled;
200
static char                     do_forms=0;
201
#else
202
int                             otg_enabled;
203
#endif
knopp's avatar
   
knopp committed
204
//int                             number_of_cards =   1;
205

206
207

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

214

215
216
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
217

218
219
220
221
222
223
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);

224
int transmission_mode=1;
knopp's avatar
   
knopp committed
225

226

227

228
229
230
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

231
232
233
234
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

235
236
extern char uecap_xer[1024];
char uecap_xer_in=0;
237

238
int oaisim_flag=0;
239
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
knopp's avatar
   
knopp committed
240

Cedric Roux's avatar
Cedric Roux committed
241
242
243
244
/* 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
245

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

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

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

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

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

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

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

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

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

322

Raymond Knopp's avatar
Raymond Knopp committed
323

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

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

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

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

    oai_exit = 1;

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

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

361
  }
362

363
}
364

365
#ifdef XFORMS
366

367

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

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

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


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

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

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

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

407
# ifdef ENABLE_XFORMS_WRITE_STATS
408
409

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

414
#endif
415

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

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

428

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

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

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

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

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

468
# ifdef ENABLE_XFORMS_WRITE_STATS
469

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

484
# endif
485

knopp's avatar
   
knopp committed
486
  pthread_exit((void*)arg);
487
488
489
}
#endif

490

491

492

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
500

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

510
511
512
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

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

knopp's avatar
   
knopp committed
566
  return NULL;
567
568
569
}
#endif

knopp's avatar
   
knopp committed
570

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

580
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
oai's avatar
oai committed
581
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
knopp's avatar
   
knopp committed
582

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

585
586
587
588
589
590
  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) {
591
592
593
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      printf("Enabling OPT for wireshark for local interface");
594
  }
595

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

oai's avatar
oai committed
610
  
611
  if (UE_flag > 0) {
612
613
     uint8_t n_rb_dl;
     nfapi_mode=0;
614

615
616
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
617

618
     set_default_frame_parms(frame_parms);
619
620


621
622
623
624
625
626
627
     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");
knopp's avatar
   
knopp committed
628
      }
629
630
631
      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;
632
633
634
      if ( (cmdline_uemodeparams[CMDLINE_DEBUGUEPRACH_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = debug_prach;
      if ( (cmdline_uemodeparams[CMDLINE_NOL2CONNECT_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0)  mode = no_L2_connect;
      if ( (cmdline_uemodeparams[CMDLINE_CALIBPRACHTX_IDX].paramflags &  PARAMFLAG_PARAMSET) != 0) mode = calib_prach_tx; 
635
636
637
      if (dumpframe  > 0)  mode = rx_dump_frame;
      
      if ( downlink_frequency[0][0] > 0) {
638
639
640
641
642
        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;
643
      } 
644

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

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

675

676
677
678
679
      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];
knopp's avatar
   
knopp committed
680
      }
681
682
683
684
  } /* 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);   
knopp's avatar
   
knopp committed
685
#endif
686

687
688
689
690
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
    if (UE_flag == 0) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
691
      RCConfig();
692
693
      NB_eNB_INST = RC.nb_inst;
      NB_RU	  = RC.nb_RU;
694
      printf("Configuration: nb_rrc_inst %d, nb_L1_inst %d, nb_ru %d\n",NB_eNB_INST,RC.nb_L1_inst,NB_RU);
695
    }
696
697
698
699
  } 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);
700
    //    uecap_xer_in=1;
701
  } /* UE with config file  */
702
}
703
704


705
#if T_TRACER
Cedric Roux's avatar
Cedric Roux committed
706
int T_nowait = 0;     /* by default we wait for the tracer */
707
int T_port = 2021;    /* default port to listen to to wait for the tracer */
708
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
709
710
#endif

711

knopp's avatar
knopp committed
712
713
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
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728

  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;
729
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
    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
759
760
void init_openair0(void);

knopp's avatar
knopp committed
761
762
763
764
765
766
767
768
769
770
771
772
773
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;
774
	openair0_cfg[card].samples_per_frame = 230400;
knopp's avatar
knopp committed
775
776
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
777
      } else {
knopp's avatar
knopp committed
778
	openair0_cfg[card].sample_rate=30.72e6;
779
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
knopp committed
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
808
	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,
809
810
	   ((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
811
812
813
    openair0_cfg[card].Mod_id = 0;

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

815
    openair0_cfg[card].clock_source = clock_source;
816

817

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

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

knopp's avatar
knopp committed
823
824
825
826
      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;
827

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

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

852

853
void wait_RUs(void) {
854

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

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

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

870
void wait_eNBs(void) {
871
872
873
874
875
876
877

  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);
878
    usleep(5000000);
879
    waiting=0;
880
881
882
883
884
    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++) {
885
886
887
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
888
889
890
        } 
      }
    }
891
892
893
  }
  printf("eNB L1 are configured\n");
}
894

895
896
897
898
899
900
901
902
903
904
905
906
907
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);
}

908
909
int main( int argc, char **argv )
{
910
  int i;
911
#if defined (XFORMS)
knopp's avatar
   
knopp committed