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

knopp's avatar
knopp committed
138
static char              UE_flag=0;
139
unsigned int                    mmapped_dma=0;
140
int                             single_thread_flag=1;
141

142
static char                     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
521
522
	printf("received terminate message\n");
	oai_exit=1;
	itti_exit_task ();
	break;
knopp's avatar
   
knopp committed
523
524

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

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

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

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

569

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

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

  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
594
595
596
597
598
599
600
601

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

oai's avatar
oai committed
609
  
610
  if (UE_flag > 0) {
oai's avatar
oai committed
611
     uint8_t n_rb_dl;
612
613
     paramdef_t cmdline_uemodeparams[] =CMDLINE_UEMODEPARAMS_DESC;
     paramdef_t cmdline_ueparams[] =CMDLINE_UEPARAMS_DESC;
oai's avatar
oai committed
614

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

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

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

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

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

Florian Kaltenberger's avatar
Florian Kaltenberger committed
672
673
674
675
      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];
676
677
      }
  } /* UE_flag > 0 */
Florian Kaltenberger's avatar
Florian Kaltenberger committed
678

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

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


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

709

710

knopp's avatar
knopp committed
711
void set_default_frame_parms(LTE_DL_FRAME_PARMS *frame_parms[MAX_NUM_CCs]) {
knopp's avatar
knopp committed
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726

  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;
727
    frame_parms[CC_id]->nb_antenna_ports_eNB  = 1;
knopp's avatar
knopp committed
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
    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;

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

knopp's avatar
knopp committed
754
755
756
757
  }

}

knopp's avatar
knopp committed
758
759
void init_openair0(void);

knopp's avatar
knopp committed
760
761
762
763
764
765
766
767
768
769
770
771
772
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;
773
	openair0_cfg[card].samples_per_frame = 230400;
knopp's avatar
knopp committed
774
775
	openair0_cfg[card].tx_bw = 10e6;
	openair0_cfg[card].rx_bw = 10e6;
776
      } else {
knopp's avatar
knopp committed
777
	openair0_cfg[card].sample_rate=30.72e6;
778
	openair0_cfg[card].samples_per_frame = 307200;
knopp's avatar
knopp committed
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
	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,
808
809
	   ((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
810
811
812
    openair0_cfg[card].Mod_id = 0;

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

814
    openair0_cfg[card].clock_source = clock_source;
815

816

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

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

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

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

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

851

852
void wait_RUs(void) {
853

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

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

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

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

  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);
877
    usleep(5000000);
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
895
896
897
898
899
900
901
902
903
904
905
906
static inline void wait_nfapi_init(char *thread_name) {

  printf( "waiting for NFAPI PNF connection and population of global structure (%s)\n",thread_name);
  pthread_mutex_lock( &nfapi_sync_mutex );
  
  while (nfapi_sync_var<0)
    pthread_cond_wait( &nfapi_sync_cond, &nfapi_sync_mutex );
  
  pthread_mutex_unlock(&nfapi_sync_mutex);
  
  printf( "NFAPI: got sync (%s)\n", thread_name);
}

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

knopp's avatar
   
knopp committed
914
  int CC_id;
915
  int ru_id;
knopp's avatar
knopp committed
916
  uint8_t  abstraction_flag=0;
knopp's avatar
   
knopp committed
917
  uint8_t beta_ACK=0,beta_RI=0,beta_CQI=2;
918

knopp's avatar
   
knopp committed
919
#if defined (XFORMS)
920
921
  int ret;
#endif
922

923
  start_background_system();
924
925
926
927
  if ( load_configmodule(argc,argv) == NULL) {
    exit_fun("[SOFTMODEM] Error, configuration module init failed\n");
  } 
      
928
929
930
931
932
#ifdef DEBUG_CONSOLE
  setvbuf(stdout, NULL, _IONBF, 0);
  setvbuf(stderr, NULL, _IONBF, 0);
#endif

933
934
935
  PHY_VARS_UE *UE[MAX_NUM_CCs];

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

938
  memset(tx_max_power,0,sizeof(int)*MAX_NUM_CCs);
939

knopp's avatar
   
knopp committed
940
  set_latency_target();
941
942


knopp's avatar
knopp committed
943
  // set default parameters
Florian Kaltenberger's avatar
Florian Kaltenberger committed
944
  //if (UE_flag == 1) set_default_frame_parms(frame_parms);
945

946
  logInit();
knopp's avatar
knopp committed
947

948
  printf("Reading in command-line options\n");
949

950
  get_options ();