lte-softmodem.c 46.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
#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
119
120
pthread_cond_t nfapi_sync_cond;
pthread_mutex_t nfapi_sync_mutex;
int nfapi_sync_var=-1; //!< protected by mutex \ref nfapi_sync_mutex

uint8_t nfapi_mode = 0; // Default to monolithic mode

knopp's avatar
   
knopp committed
121
122
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
123
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
124
int config_sync_var=-1;
125

126
127
uint16_t runtime_phy_rx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
uint16_t runtime_phy_tx[29][6]; // SISO [MCS 0-28][RBs 0-5 : 6, 15, 25, 50, 75, 100]
knopp's avatar
   
knopp committed
128

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

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

138
static int8_t              UE_flag=0;
139
unsigned int                    mmapped_dma=0;
140
int                             single_thread_flag=1;
141

142
static int8_t                     threequarter_fs=0;
143

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

147

oai's avatar
oai committed
148

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

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

157
158
FILE *input_fd=NULL;

159

160
161
#if MAX_NUM_CCs == 1
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain}};
kortke's avatar
kortke committed
162
163
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
164
165
166
167
#else
rx_gain_t                rx_gain_mode[MAX_NUM_CCs][4] = {{max_gain,max_gain,max_gain,max_gain},{max_gain,max_gain,max_gain,max_gain}};
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0},{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0},{20,0,0,0}};
gauthier's avatar
gauthier committed
168
#endif
knopp's avatar
   
knopp committed
169

fnabet's avatar
fnabet committed
170
double rx_gain_off = 0.0;
171

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

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

177
178
char   rf_config_file[1024];

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

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

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

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

192
int                      rx_input_level_dBm;
oai's avatar
oai committed
193

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

202
203

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

210

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

214
215
216
217
218
219
extern PHY_VARS_UE* init_ue_vars(LTE_DL_FRAME_PARMS *frame_parms,
			  uint8_t UE_id,
			  uint8_t abstraction_flag);

extern void init_eNB_afterRU(void);

220
int transmission_mode=1;
knopp's avatar
   
knopp committed
221

222

223

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

227
228
229
230
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

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

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

Cedric Roux's avatar
Cedric Roux committed
237
238
239
240
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;
knopp's avatar
   
knopp committed
241

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

245
246
247
248
249
/*---------------------BMC: timespec helpers -----------------------------*/

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

250
struct timespec clock_difftime(struct timespec start, struct timespec end) {
251
252
253
254
255
256
257
258
259
  struct timespec temp;
  if ((end.tv_nsec-start.tv_nsec)<0) {
    temp.tv_sec = end.tv_sec-start.tv_sec-1;
    temp.tv_nsec = 1000000000+end.tv_nsec-start.tv_nsec;
  } else {
    temp.tv_sec = end.tv_sec-start.tv_sec;
    temp.tv_nsec = end.tv_nsec-start.tv_nsec;
  }
  return temp;
260
261
}

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

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

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

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

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

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

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

321

Raymond Knopp's avatar
Raymond Knopp committed
322

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

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

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

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

Raymond Knopp's avatar
Raymond Knopp committed
343
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
344
345
346
347

    oai_exit = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
348
349
350
351
352
      if (UE_flag == 0) {
      } else {
	if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
	  PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
      }
knopp's avatar
knopp committed
353
    }
354
355

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

360
  }
361

362
}
363

364
#ifdef XFORMS
365

366

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

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
374
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
375
376
377
	phy_vars_eNB->UE_stats[i].dlsch_NAK[k][j]=0;
	phy_vars_eNB->UE_stats[i].dlsch_ACK[k][j]=0;
	phy_vars_eNB->UE_stats[i].dlsch_trials[k][j]=0;
378
      }
379

380
381
382
      phy_vars_eNB->UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->UE_stats[i].ulsch_consecutive_errors=0;
383
384


385
386
387
      phy_vars_eNB->UE_stats[i].dlsch_sliding_cnt=0;
      phy_vars_eNB->UE_stats[i].dlsch_NAK_round0=0;
      phy_vars_eNB->UE_stats[i].dlsch_mcs_offset=0;
388
389
390
391
    }
  }
}

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

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

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

406
# ifdef ENABLE_XFORMS_WRITE_STATS
407
408

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

413
#endif
414

knopp's avatar
   
knopp committed
415
416
  while (!oai_exit) {
    if (UE_flag==1) {
oai's avatar
oai committed
417
      dump_ue_stats (PHY_vars_UE_g[0][0], &PHY_vars_UE_g[0][0]->proc.proc_rxtx[0],stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
418
419
420
      //fl_set_object_label(form_stats->stats_text, stats_buffer);
      fl_clear_browser(form_stats->stats_text);
      fl_add_browser_line(form_stats->stats_text, stats_buffer);
421

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

427

knopp's avatar
   
knopp committed
428
    } else {
429
      /*
430
	if (RC.eNB[0][0]->mac_enabled==1) {
431
432
433
434
	len = dump_eNB_l2_stats (stats_buffer, 0);
	//fl_set_object_label(form_stats_l2->stats_text, stats_buffer);
	fl_clear_browser(form_stats_l2->stats_text);
	fl_add_browser_line(form_stats_l2->stats_text, stats_buffer);
435
436
	}
	len = dump_eNB_stats (RC.eNB[0][0], stats_buffer, 0);
437

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

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

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

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

467
# ifdef ENABLE_XFORMS_WRITE_STATS
468

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

483
# endif
484

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

489

490

491

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
499

knopp's avatar
   
knopp committed
500
501
  if (UE_flag == 0) {
    /* Wait for the initialize message */
502
    printf("Wait for the ITTI initialize message\n");
503
    do {
knopp's avatar
   
knopp committed
504
      if (message_p != NULL) {
505
506
	result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
	AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
knopp's avatar
   
knopp committed
507
      }
508

509
510
511
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
   
knopp committed
512
      case INITIALIZE_MESSAGE:
513
514
515
516
	/* Start eNB thread */
	LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
	start_eNB = 1;
	break;
knopp's avatar
   
knopp committed
517
518

      case TERMINATE_MESSAGE:
519
520
	printf("received terminate message\n");
	oai_exit=1;
521
        start_eNB = 0;
522
523
	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

570

571
572
static void get_options(void) {
  int CC_id;
573
  int tddflag, nonbiotflag;
574
575
  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;
oai's avatar
oai committed
579

580
  paramdef_t cmdline_params[] =CMDLINE_PARAMS_DESC ;
oai's avatar
oai committed
581
  paramdef_t cmdline_logparams[] =CMDLINE_LOGPARAMS_DESC ;
582
583
584
585
586
587
588
589
590
591
592
593
594

  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
595
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) {
oai's avatar
oai committed
612
     uint8_t n_rb_dl;
613
614
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
oai's avatar
oai committed
615

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

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

627
628
629
      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;
630
631
632
633
      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;
634
635
      
      if ( downlink_frequency[0][0] > 0) {
Florian Kaltenberger's avatar
Florian Kaltenberger committed
636
637
638
639
640
	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;
641
642
      } 

oai's avatar
oai committed
643
644
645
646
      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
647

648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
      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;
  	  }
671
672
      }

673
674
675
676
677

      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];
678
679
      }
  } /* UE_flag > 0 */
Florian Kaltenberger's avatar
Florian Kaltenberger committed
680

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

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

712

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

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

knopp's avatar
knopp committed
756
757
758
759
  }

}

knopp's avatar
knopp committed
760
761
void init_openair0(void);

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

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

816
    openair0_cfg[card].clock_source = clock_source;
817

818

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

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

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

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

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

853

854
void wait_RUs(void) {
855

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

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

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

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

  int i,j;
  int waiting=1;


  while (waiting==1) {
Cedric Roux's avatar
Cedric Roux committed
876
877
    printf("Waiting for eNB L1 instances to all get configured ... sleeping 50ms (nb_L1_inst %d)\n",RC.nb_L1_inst);
    usleep(50*1000);
878
    waiting=0;
879
880
881
882
883
    for (i=0;i<RC.nb_L1_inst;i++) {

      printf("RC.nb_L1_CC[%d]:%d\n", i, RC.nb_L1_CC[i]);

      for (j=0;j<RC.nb_L1_CC[i];j++) {
884
885
886
	if (RC.eNB[i][j]->configured==0) {
	  waiting=1;
	  break;
887
888
889
        } 
      }
    }
890
891
892
  }
  printf("eNB L1 are configured\n");
}
893

894
#if defined(ENABLE_ITTI)
895
896
/*
 * helper function to terminate a certain ITTI task
897
 */
898
void terminate_task(task_id_t task_id, module_id_t mod_id)
899
{
900
901
902
903
904
905
  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);
}

906
extern void  free_transport(PHY_VARS_eNB *);
907
908
extern void  phy_free_RU(RU_t*);

909
int stop_L1L2(module_id_t enb_id)
910
911
{
  LOG_W(ENB_APP, "stopping lte-softmodem\n");
912
  oai_exit = 1;
913

914
915
916
917
918
919
920
921
922
923
924
925
  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");
926
    }
927
928
929
930
931
    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");
932
    }
933
934
935
  } else {
    LOG_W(ENB_APP, "no RU found for index %d\n", enb_id);
    return -1;
936
937
938
939
940
  }

  /* these tasks need to pick up new configuration */
  terminate_task(TASK_RRC_ENB, enb_id);
  terminate_task(TASK_L2L1, enb_id);
941
  LOG_I(ENB_APP, "calling kill_eNB_proc() for instance %d\n", enb_id);
942
  kill_eNB_proc(enb_id);
943
944
  LOG_I(ENB_APP, "calling kill_RU_proc() for instance %d\n", enb_id);
  kill_RU_proc(enb_id);
945
  oai_exit = 0;
946
947
948
949
  for (int cc_id = 0; cc_id < RC.nb_CC[enb_id]; cc_id++) {
    free_transport(RC.eNB[enb_id][cc_id]);
    phy_free_lte_eNB(RC.eNB[enb_id][cc_id]);
  }
950
  phy_free_RU(RC.ru[enb_id]);