lte-softmodem.c 38.9 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"
frtabu's avatar
frtabu committed
53
#include "common/utils/telnetsrv/load_telnet.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
562
  uint32_t online_log_messages;
  uint32_t glog_level, glog_verbosity;

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

  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
578
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);
  }
  
590
591
592
  if (UE_flag > 0) {
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
oai's avatar
oai committed
593
594
595



596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
     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
622
623
624
625
      if (tddflag > 0) {
         for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) 
	     frame_parms[CC_id]->frame_type = TDD;
      }
626
627
628
629
630
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

      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

664
665
666
667
  if ( !(CONFIG_ISFLAGSET(CONFIG_ABORT)) ) {
    if (UE_flag == 0) {
      memset((void*)&RC,0,sizeof(RC));
      /* Read RC configuration file */
668
      RCConfig();
669
670
671
      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);
672
    }
673
674
675
676
677
678
  } 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  */
679
680
681
}


682
  
683
684
685
#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 */
686
int T_dont_fork = 0;  /* default is to fork, see 'T_init' to understand */
687
688
#endif

689

knopp's avatar
knopp committed
690
691
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
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706

  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;
707
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
    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
737
738
void init_openair0(void);

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

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

793
    openair0_cfg[card].clock_source = clock_source;
794

795

796
797
    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));
798

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

knopp's avatar
knopp committed
801
802
803
804
      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;
805

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

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

830

831
void wait_RUs(void) {
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846

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

847
void wait_eNBs(void) {
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865

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

867
868
int main( int argc, char **argv )
{
869
  int i;
870
#if defined (XFORMS)
knopp's avatar
   
knopp committed
871
  void *status;
872
#endif
873

knopp's avatar
   
knopp committed
874
  int CC_id;
875
  int ru_id;
knopp's avatar
knopp committed
876
  uint8_t  abstraction_flag=0;
knopp's avatar
   
knopp committed
877
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
878

knopp's avatar
   
knopp committed
879
#if defined (XFORMS)
880
881
  int ret;
#endif
882

883
  start_background_system();
884
885
886
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
887

888
      
889
890
891
892
893
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

894
895
896
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

899
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
900

knopp's avatar
   
knopp committed
901
  set_latency_target();
902
903


knopp's avatar
knopp committed
904
  // set default parameters
905
  if (UE_flag == 1) set_default_frame_parms(frame_parms);
906

907
  logInit();
knopp's avatar
knopp committed
908

909
  printf("Reading in command-line options\n");
910

911
  get_options (); 
oai's avatar
oai committed
912
913
914
  if (CONFIG_ISFLAGSET(CONFIG_ABORT)) {
      fprintf(stderr,"Getting configuration failed\n");
      exit(-1);
915
  }
knopp's avatar
knopp committed
916
917
918



919
#if T_TRACER
920
  T_init(T_port, T_wait, T_dont_fork);
921
922
#endif

oai's avatar
oai committed
923

Florian Kaltenberger's avatar
Florian Kaltenberger committed
924

nikaeinn's avatar
nikaeinn committed
925
926
  //randominit (0);
  set_taus_seed (0);
knopp's avatar
   
knopp committed
927

928
929
  if (UE_flag==1) {
    printf("configuring for UE\n");
930

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

945
  } else {
946
    printf("configuring for RAU/RRU\n");
947

948
  }
949