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

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
/* forward declarations */
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]);

233
234
235
236
237
/*---------------------BMC: timespec helpers -----------------------------*/

struct timespec min_diff_time = { .tv_sec = 0, .tv_nsec = 0 };
struct timespec max_diff_time = { .tv_sec = 0, .tv_nsec = 0 };

238
struct timespec clock_difftime(struct timespec start, struct timespec end) {
239
240
241
242
243
244
245
246
247
  struct timespec temp;
  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }
  return temp;
248
249
}

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

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

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

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

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

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

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

309

Raymond Knopp's avatar
Raymond Knopp committed
310

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

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

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

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

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

    oai_exit = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
336
337
338
339
340
      if (UE_flag == 0) {
      } else {
	if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
	  PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
      }
knopp's avatar
knopp committed
341
    }
342
343

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

348
  }
349

350
}
351

352
#ifdef XFORMS
353

354

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

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
362
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
363
364
365
	phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
	phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
	phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
366
      }
367

368
369
370
      phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;
371
372


373
374
375
      phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
      phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
      phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
376
377
378
379
    }
  }
}

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

389
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
   
knopp committed
390
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
391

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

394
# ifdef ENABLE_XFORMS_WRITE_STATS
395
396

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

401
#endif
402

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

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

415

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

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

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

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

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

455
# ifdef ENABLE_XFORMS_WRITE_STATS
456

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

471
# endif
472

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

477

478

479

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
487

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

497
498
499
      itti_receive_msg (TASK_L2L1, &message_p);

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

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

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

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

  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);

    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;

    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;

    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
540

knopp's avatar
   
knopp committed
541
542
543
544
545
546
547
548
549
550
551
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;

    default:
      LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
      break;
    }

    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
thomasl's avatar
thomasl committed
552
  } while(!oai_exit);
553

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

558

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

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

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

  if (strlen(in_path) > 0) {
      opt_type = OPT_PCAP;
      opt_enabled=1;
      printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
  }
  if (strlen(in_ip) > 0) {
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      printf("Enabling OPT for wireshark for local interface");
  }
oai's avatar
oai committed
583
584
585
586
587
588
589
590

  config_process_cmdline( cmdline_logparams,sizeof(cmdline_logparams)/sizeof(paramdef_t),NULL);
  if(config_isparamset(cmdline_logparams,CMDLINE_ONLINELOG_IDX)) {
      set_glog_onlinelog(online_log_messages);
  }
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGLEVEL_IDX)) {
      set_glog(glog_level, -1);
  }
591
  if(config_isparamset(cmdline_logparams,CMDLINE_GLOGVERBO_IDX)) {
oai's avatar
oai committed
592
593
      set_glog(-1, glog_verbosity);
  }
oai's avatar
oai committed
594
  if (start_telnetsrv) {
595
     load_module_shlib("telnetsrv",NULL,0);
oai's avatar
oai committed
596
597
  }

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

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

606
607
608
609
610
611
612
613
     config_process_cmdline( cmdline_uemodeparams,sizeof(cmdline_uemodeparams)/sizeof(paramdef_t),NULL);
     config_process_cmdline( cmdline_ueparams,sizeof(cmdline_ueparams)/sizeof(paramdef_t),NULL);
      if (loopfile != NULL) {
  	  printf("Input file for hardware emulation: %s",loopfile);
  	  mode=loop_through_memory;
  	  input_fd = fopen(loopfile,"r");
  	  AssertFatal(input_fd != NULL,"Please provide a valid input file\n");
      }
oai's avatar
oai committed
614

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

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

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

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

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

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


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

698

699

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

  int CC_id;

  for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    frame_parms[CC_id] = (LTE_DL_FRAME_PARMS*) malloc(sizeof(LTE_DL_FRAME_PARMS));
    /* Set some default values that may be overwritten while reading options */
    frame_parms[CC_id]->frame_type          = FDD;
    frame_parms[CC_id]->tdd_config          = 3;
    frame_parms[CC_id]->tdd_config_S        = 0;
    frame_parms[CC_id]->N_RB_DL             = 100;
    frame_parms[CC_id]->N_RB_UL             = 100;
    frame_parms[CC_id]->Ncp                 = NORMAL;
    frame_parms[CC_id]->Ncp_UL              = NORMAL;
    frame_parms[CC_id]->Nid_cell            = 0;
    frame_parms[CC_id]->num_MBSFN_config    = 0;
716
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
    frame_parms[CC_id]->nb_antennas_tx      = 1;
    frame_parms[CC_id]->nb_antennas_rx      = 1;

    frame_parms[CC_id]->nushift             = 0;

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

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

736
737
738
739
//    downlink_frequency[CC_id][0] = 2680000000; // Use float to avoid issue with frequency over 2^31.
//    downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
//    downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
//    downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
knopp's avatar
knopp committed
740
    //printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
741
    frame_parms[CC_id]->dl_CarrierFreq=downlink_frequency[CC_id][0];
oai's avatar
oai committed
742

knopp's avatar
knopp committed
743
744
745
746
  }

}

knopp's avatar
knopp committed
747
748
void init_openair0(void);

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

  int card;
  int i;

  for (card=0; card<MAX_CARDS; card++) {

    openair0_cfg[card].mmapped_dma=mmapped_dma;
    openair0_cfg[card].configFilename = NULL;

    if(frame_parms[0]->N_RB_DL == 100) {
      if (frame_parms[0]->threequarter_fs) {
	openair0_cfg[card].sample_rate=23.04e6;
762
	openair0_cfg[card].samples_per_frame = 230400;
knopp's avatar
knopp committed
763
764
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
765
      } else {
knopp's avatar
knopp committed
766
	openair0_cfg[card].sample_rate=30.72e6;
767
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
knopp committed
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
      }
    } else if(frame_parms[0]->N_RB_DL == 50) {
      openair0_cfg[card].sample_rate=15.36e6;
      openair0_cfg[card].samples_per_frame = 153600;
      openair0_cfg[card].tx_bw = 5e6;
      openair0_cfg[card].rx_bw = 5e6;
    } else if (frame_parms[0]->N_RB_DL == 25) {
      openair0_cfg[card].sample_rate=7.68e6;
      openair0_cfg[card].samples_per_frame = 76800;
      openair0_cfg[card].tx_bw = 2.5e6;
      openair0_cfg[card].rx_bw = 2.5e6;
    } else if (frame_parms[0]->N_RB_DL == 6) {
      openair0_cfg[card].sample_rate=1.92e6;
      openair0_cfg[card].samples_per_frame = 19200;
      openair0_cfg[card].tx_bw = 1.5e6;
      openair0_cfg[card].rx_bw = 1.5e6;
    }




    if (frame_parms[0]->frame_type==TDD)
      openair0_cfg[card].duplex_mode = duplex_mode_TDD;
    else //FDD
      openair0_cfg[card].duplex_mode = duplex_mode_FDD;

    printf("HW: Configuring card %d, nb_antennas_tx/rx %d/%d\n",card,
797
798
	   ((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_tx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_tx),
	   ((UE_flag==0) ? RC.eNB[0][0]->frame_parms.nb_antennas_rx : PHY_vars_UE_g[0][0]->frame_parms.nb_antennas_rx));
knopp's avatar
knopp committed
799
800
801
    openair0_cfg[card].Mod_id = 0;

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

803
    openair0_cfg[card].clock_source = clock_source;
804

805

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

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

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

knopp's avatar
knopp committed
816
817
818
819
820
821
822
823
      if (i<openair0_cfg[card].rx_num_channels)
	openair0_cfg[card].rx_freq[i] = (UE_flag==0) ? downlink_frequency[0][i] + uplink_frequency_offset[0][i] : downlink_frequency[0][i];
      else
	openair0_cfg[card].rx_freq[i]=0.0;

      openair0_cfg[card].autocal[i] = 1;
      openair0_cfg[card].tx_gain[i] = tx_gain[0][i];
      if (UE_flag == 0) {
824
	openair0_cfg[card].rx_gain[i] = RC.eNB[0][0]->rx_total_gain_dB;
knopp's avatar
knopp committed
825
826
      }
      else {
fnabet's avatar
fnabet committed
827
	openair0_cfg[card].rx_gain[i] = PHY_vars_UE_g[0][0]->rx_total_gain_dB - rx_gain_off;
knopp's avatar
knopp committed
828
829
      }

830
      openair0_cfg[card].configFilename = rf_config_file;
831
      printf("Card %d, channel %d, Setting tx_gain %f, rx_gain %f, tx_freq %f, rx_freq %f\n",
832
833
834
835
	     card,i, openair0_cfg[card].tx_gain[i],
	     openair0_cfg[card].rx_gain[i],
	     openair0_cfg[card].tx_freq[i],
	     openair0_cfg[card].rx_freq[i]);
836
    }
knopp's avatar
   
knopp committed
837
  }
knopp's avatar
   
knopp committed
838
}
839

840

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

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

  // wait for all RUs to be configured over fronthaul
  pthread_mutex_lock(&RC.ru_mutex);
  while (RC.ru_mask>0) {
    pthread_cond_wait(&RC.ru_cond,&RC.ru_mutex);
  }
850
  pthread_mutex_unlock(&RC.ru_mutex);
851
852
853
854

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

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

  int i,j;
  int waiting=1;


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

875
#if defined(ENABLE_ITTI)
876
877
/*
 * helper function to terminate a certain ITTI task
878
 */
879
void terminate_task(task_id_t task_id, module_id_t mod_id)
880
{
881
882
883
884
885
886
  LOG_I(ENB_APP, "sending TERMINATE_MESSAGE to task %s (%d)\n", itti_get_task_name(task_id), task_id);
  MessageDef *msg;
  msg = itti_alloc_new_message (ENB_APP, TERMINATE_MESSAGE);
  itti_send_msg_to_task (task_id, ENB_MODULE_ID_TO_INSTANCE(mod_id), msg);
}

887
888
extern void  phy_free_RU(RU_t*);

889
int stop_L1L2(module_id_t enb_id)
890
891
{
  LOG_W(ENB_APP, "stopping lte-softmodem\n");
892
  oai_exit = 1;
893

894
895
896
897
898
899
900
901
902
903
904
905
  if (!RC.ru) {
    LOG_F(ENB_APP, "no RU configured\n");
    return -1;
  }

  /* stop trx devices, multiple carrier currently not supported by RU */
  if (RC.ru[enb_id]) {
    if (RC.ru[enb_id]->rfdevice.trx_stop_func) {
      RC.ru[enb_id]->rfdevice.trx_stop_func(&RC.ru[enb_id]->rfdevice);
      LOG_I(ENB_APP, "turned off RU rfdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off rfdevice due to missing trx_stop_func callback, proceding anyway!\n");
906
    }
907
908
909
910
911
    if (RC.ru[enb_id]->ifdevice.trx_stop_func) {
      RC.ru[enb_id]->ifdevice.trx_stop_func(&RC.ru[enb_id]->ifdevice);
      LOG_I(ENB_APP, "turned off RU ifdevice\n");
    } else {
      LOG_W(ENB_APP, "can not turn off ifdevice due to missing trx_stop_func callback, proceding anyway!\n");
912
    }
913
914
915
  } else {
    LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
    return -1;
916
917
918
919
920
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, enb_id);
  terminate_task(TASK_L2L1, enb_id);
921
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
922
  kill_eNB_proc(enb_id);
923
924
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
  kill_RU_proc(enb_id);
925
  oai_exit = 0;
926
927
  for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) phy_free_lte_eNB(RC.eNB[enb_id][cc_id]);
  phy_free_RU(RC.ru[enb_id]);
928
929
930
931
  return 0;
}

/*
932
 * Restart the lte-softmodem after it has been soft-stopped with stop_L1L2()
933
 */
934
int restart_L1L2(module_id_t enb_id)
935
{
936
937
938
  RU_t *ru = RC.ru[enb_id];
  int cc_id;
  MessageDef *msg_p = NULL;
939
940
941
942
943
944

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

  /* block threads */
  sync_var = -1;

945
946
  for (cc_id = 0; cc_id < RC.nb_L1_CC[enb_id]; cc_id++) {
    RC.eNB[enb_id][cc_id]->configured = 0;
947
948
949
  }


950
951
952
953
954
955
  /* TODO undo malloc_IF4p5_buffer() */
  RC.ru_mask |= (1 << ru->idx);
  /* copy the changed frame parameters to the RU */
  /* TODO this should be done for all RUs associated to this eNB */
  memcpy(&ru->frame_parms, &RC.eNB[enb_id][0]->frame_parms, sizeof(LTE_DL_FRAME_PARMS));
  set_function_spec_param(RC.ru[enb_id]);
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970

  LOG_I(ENB_APP, "attempting to create ITTI tasks\n");
  if (itti_create_task (TASK_RRC_ENB, rrc_enb_task, NULL) < 0) {
    LOG_E(RRC, "Create task for RRC eNB failed\n");
    return -1;
  } else {
    LOG_I(RRC, "Re-created task for RRC eNB successfully\n");
  }
  if (itti_create_task (TASK_L2L1, l2l1_task, NULL) < 0) {
    LOG_E(PDCP, "Create task for L2L1 failed\n");
    return -1;
  } else {
    LOG_I(PDCP, "Re-created task for L2L1 successfully\n");
  }