lte-softmodem.c 59.7 KB
Newer Older
1
2
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
3
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
   
knopp committed
4
5
6
 * \date 2012
 * \version 0.1
 * \company Eurecom
7
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
knopp's avatar
   
knopp committed
8
9
10
 * \note
 * \warning
 */
knopp's avatar
   
knopp committed
11
#define _GNU_SOURCE
12
13
14
15
16
17
18
19
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <sys/ioctl.h>
#include <sys/types.h>
#include <sys/mman.h>
#include <sched.h>
20
#include <linux/sched.h>
21
22
23
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
24
#include <sys/sysinfo.h>
25

26
27
#include "T.h"

28
#include "rt_wrapper.h"
29

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

32
#include "assertions.h"
33
#include "msc.h"
34
35

#include "PHY/types.h"
36

37
#include "PHY/defs.h"
38
#undef MALLOC //there are two conflicting definitions, so we better make sure we don't use it at all
knopp's avatar
   
knopp committed
39
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
40

knopp's avatar
   
knopp committed
41
#include "../../ARCH/COMMON/common_lib.h"
42
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
knopp's avatar
   
knopp committed
43

knopp's avatar
   
knopp committed
44
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
45
46
47
48
49
50
51
52
53

#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"
54
#include "LAYER2/MAC/proto.h"
55
56
57
58
59
60
61
62
#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
63
#include "UTIL/OTG/otg_tx.h"
64
#include "UTIL/OTG/otg_externs.h"
65
66
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
67
#include "UTIL/OPT/opt.h"
68
#include "enb_config.h"
nikaeinn's avatar
nikaeinn committed
69
//#include "PHY/TOOLS/time_meas.h"
70

Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
71
72
73
74
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

75
76
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
77
# include "create_tasks.h"
78
79
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
80
#ifdef PDCP_USE_NETLINK
81
82
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
83
# endif
84
85
#endif

86
87
88
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
89
90
#endif

91
// In lte-enb.c
knopp's avatar
knopp committed
92
extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg);
knopp's avatar
knopp committed
93
extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int);
94
extern void stop_eNB(int);
95
extern void kill_eNB_proc(void);
knopp's avatar
   
knopp committed
96

97
// In lte-ue.c
knopp's avatar
knopp committed
98
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
99
extern void fill_ue_band_info(void);
knopp's avatar
knopp committed
100
extern void init_UE(int);
101

102
#ifdef XFORMS
103
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
gauthier's avatar
gauthier committed
104
// at eNB 0, an UL scope for every UE
105
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
106
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
107
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
108
char title[255];
109
unsigned char                   scope_enb_num_ue = 2;
110
111
#endif //XFORMS

112
113


114

115

knopp's avatar
   
knopp committed
116

knopp's avatar
   
knopp committed
117
118
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
119
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
120

121

122
123


124

125
#ifdef XFORMS
knopp's avatar
   
knopp committed
126
static pthread_t                forms_thread; //xforms
127
#endif
128

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

132

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



knopp's avatar
   
knopp committed
141

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

146
static char                     threequarter_fs=0;
147

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

151

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

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

161
162
FILE *input_fd=NULL;

163

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

174
175


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

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

181
182
char   rf_config_file[1024];

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

186

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

190
int                      rx_input_level_dBm;
191
static int                      online_log_messages=0;
192
#ifdef XFORMS
193
extern int                      otg_enabled;
194
static char                     do_forms=0;
195
#else
196
int                             otg_enabled;
197
#endif
knopp's avatar
   
knopp committed
198
//int                             number_of_cards =   1;
199

200

knopp's avatar
   
knopp committed
201
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
202
203
204
eNB_func_t node_function[MAX_NUM_CCs];
eNB_timing_t node_timing[MAX_NUM_CCs];
int16_t   node_synch_ref[MAX_NUM_CCs];
205

Florian Kaltenberger's avatar
Florian Kaltenberger committed
206
uint32_t target_dl_mcs = 28; //maximum allowed mcs
207
uint32_t target_ul_mcs = 20;
208
uint32_t timing_advance = 0;
209
210
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
211

knopp's avatar
   
knopp committed
212

213
214
extern void reset_opp_meas(void);
extern void print_opp_meas(void);
215
//int transmission_mode=1;
knopp's avatar
   
knopp committed
216

217
int16_t           glog_level         = LOG_INFO;
gauthier's avatar
   
gauthier committed
218
int16_t           glog_verbosity     = LOG_MED;
219
int16_t           hw_log_level       = LOG_INFO;
gauthier's avatar
   
gauthier committed
220
int16_t           hw_log_verbosity   = LOG_MED;
221
int16_t           phy_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
222
int16_t           phy_log_verbosity  = LOG_MED;
223
int16_t           mac_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
224
int16_t           mac_log_verbosity  = LOG_MED;
225
int16_t           rlc_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
226
int16_t           rlc_log_verbosity  = LOG_MED;
227
int16_t           pdcp_log_level     = LOG_INFO;
gauthier's avatar
   
gauthier committed
228
int16_t           pdcp_log_verbosity = LOG_MED;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
229
int16_t           rrc_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
230
int16_t           rrc_log_verbosity  = LOG_MED;
231
232
233
int16_t           opt_log_level      = LOG_INFO;
int16_t           opt_log_verbosity  = LOG_MED;

gauthier's avatar
   
gauthier committed
234
235
236
237
238
239
# if defined(ENABLE_USE_MME)
int16_t           gtpu_log_level     = LOG_DEBUG;
int16_t           gtpu_log_verbosity = LOG_MED;
int16_t           udp_log_level      = LOG_DEBUG;
int16_t           udp_log_verbosity  = LOG_MED;
#endif
240
241
242
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
243
#endif
244

knopp's avatar
   
knopp committed
245

knopp's avatar
knopp committed
246

247
248
char *rrh_UE_ip = "127.0.0.1";
int rrh_UE_port = 51000;
knopp's avatar
knopp committed
249

250
251
252
253
254
255

/* flag set by eNB conf file to specify if the radio head is local or remote (default option is local) */
uint8_t local_remote_radio = BBU_LOCAL_RADIO_HEAD;
/* struct for ethernet specific parameters given in eNB conf file */
eth_params_t *eth_params;

256
257
258
259
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

knopp's avatar
   
knopp committed
260
char uecap_xer[1024],uecap_xer_in=0;
261
262


knopp's avatar
   
knopp committed
263

264
265
266
267
268
269
270
/*---------------------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 };

struct timespec clock_difftime(struct timespec start, struct timespec end)
{
271
272
273
274
275
276
277
278
279
  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;
280
281
}

Cedric Roux's avatar
Cedric Roux committed
282
void print_difftimes(void)
283
284
{
#ifdef DEBUG
285
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
286
#else
287
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
288
289
290
291
292
#endif
}

void update_difftimes(struct timespec start, struct timespec end)
{
293
294
295
296
297
  struct timespec diff_time = { .tv_sec = 0, .tv_nsec = 0 };
  int             changed = 0;
  diff_time = clock_difftime(start, end);
  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; }
298
#if 1
299
  if (changed) print_difftimes();
300
301
302
303
304
#endif
}

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

305
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
306
{
knopp's avatar
   
knopp committed
307
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
308
309
310
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
knopp's avatar
   
knopp committed
311
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
312
313
}

314
#if !defined(ENABLE_ITTI)
315
316
317
318
319
320
321
322
void signal_handler(int sig)
{
  void *array[10];
  size_t size;

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

324
325
326
327
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
328
329
  } else {
    printf("trying to exit gracefully...\n");
330
    oai_exit = 1;
331
332
  }
}
333
#endif
nikaeinn's avatar
nikaeinn committed
334
335
336
337
338
339
340
341
342
343
344
#define KNRM  "\x1B[0m"
#define KRED  "\x1B[31m"
#define KGRN  "\x1B[32m"
#define KBLU  "\x1B[34m"
#define RESET "\033[0m"

void help (void) {
  printf (KGRN "Usage:\n");
  printf("  sudo -E lte-softmodem [options]\n");
  printf("  sudo -E ./lte-softmodem -O ../../../targets/PROJECTS/GENERIC-LTE-EPC/CONF/enb.band7.tm1.exmimo2.openEPC.conf -S -V -m 26 -t 16 -x 1 --ulsch-max-errors 100 -W\n\n");
  printf("Options:\n");
345
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
nikaeinn's avatar
nikaeinn committed
346
347
348
349
  printf("  --ulsch-max-errors set the max ULSCH erros\n");
  printf("  --calib-ue-rx set UE RX calibration\n");
  printf("  --calib-ue-rx-med \n");
  printf("  --calib-ue-rxbyp\n");
knopp's avatar
   
knopp committed
350
351
  printf("  --debug-ue-prach run normal prach power ramping, but don't continue random-access\n");
  printf("  --calib-prach-tx run normal prach with maximum power, but don't continue random-access\n");
nikaeinn's avatar
nikaeinn committed
352
  printf("  --no-L2-connect bypass L2 and upper layers\n");
353
354
355
356
  printf("  --ue-rxgain set UE RX gain\n");
  printf("  --ue-txgain set UE TX gain\n");
  printf("  --ue-scan_carrier set UE to scan around carrier\n");
  printf("  --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n");
357
358
  printf("  --mmapped-dma sets flag for improved EXMIMO UE performance\n");  
  printf("  --single-thread runs lte-softmodem in only one thread\n"); 
359
  printf("  -C Set the downlink frequency for all component carriers\n");
nikaeinn's avatar
nikaeinn committed
360
361
362
  printf("  -d Enable soft scope and L1 and L2 stats (Xforms)\n");
  printf("  -F Calibrate the EXMIMO borad, available files: exmimo2_2arxg.lime exmimo2_2brxg.lime \n");
  printf("  -g Set the global log level, valide options: (9:trace, 8/7:debug, 6:info, 4:warn, 3:error)\n");
363
  printf("  -G Set the global log verbosity \n");
nikaeinn's avatar
nikaeinn committed
364
365
366
367
368
  printf("  -h provides this help message!\n");
  printf("  -K Generate ITTI analyzser logs (similar to wireshark logs but with more details)\n");
  printf("  -m Set the maximum downlink MCS\n");
  printf("  -O eNB configuration file (located in targets/PROJECTS/GENERIC-LTE-EPC/CONF\n");
  printf("  -q Enable processing timing measurement of lte softmodem on per subframe basis \n");
kaltenbe's avatar
kaltenbe committed
369
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
nikaeinn's avatar
nikaeinn committed
370
371
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
372
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
nikaeinn's avatar
nikaeinn committed
373
374
375
  printf("  -U Set the lte softmodem as a UE\n");
  printf("  -W Enable L2 wireshark messages on localhost \n");
  printf("  -V Enable VCD (generated file will be located atopenair_dump_eNB.vcd, read it with target/RT/USER/eNB.gtkw\n");
376
  printf("  -x Set the transmission mode, valid options: 1 \n");
377
  printf("  -E Apply three-quarter of sampling frequency, 23.04 Msps to reduce the data rate on USB/PCIe transfers (only valid for 20 MHz)\n");
378
379
380
#if T_TRACER
  printf("  --T_port [port]    use given port\n");
  printf("  --T_nowait         don't wait for tracer, start immediately\n");
381
  printf("  --T_dont_fork      to ease debugging with gdb\n");
382
383
384
#endif
  printf(RESET);
  fflush(stdout);
nikaeinn's avatar
nikaeinn committed
385
}
386

387
388
void exit_fun(const char* s)
{
Raymond Knopp's avatar
Raymond Knopp committed
389
390
  int CC_id;

391
  if (s != NULL) {
392
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
393
394
395
  }

  oai_exit = 1;
Raymond Knopp's avatar
Raymond Knopp committed
396
397
  
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
knopp's avatar
knopp committed
398
399
400
401
402
403
404
405
406
407
    if (UE_flag == 0) {
      if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func)
	PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice);
      if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func)
	PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice);  
    }
    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);
    }
Raymond Knopp's avatar
Raymond Knopp committed
408
  }
409
410

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
411
  sleep(1); //allow lte-softmodem threads to exit first
412
  itti_terminate_tasks (TASK_UNKNOWN);
413
#endif
414
415
416

}

417

418
#ifdef XFORMS
419

420
421
void reset_stats(FL_OBJECT *button, long arg)
{
422
423
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
424
425
426

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
427
428
429
430
      for (j=0; j<phy_vars_eNB->dlsch[i][0]->Mlimit; j++) {
        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;
431
      }
432

433
434
435
      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;
436

437
438
439
440
441
      for (j=0; j<phy_vars_eNB->ulsch[i]->Mlimit; j++) {
        phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts[k][j]=0;
        phy_vars_eNB->UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
        phy_vars_eNB->UE_stats[i].ulsch_round_errors[k][j]=0;
        phy_vars_eNB->UE_stats[i].ulsch_round_fer[k][j]=0;
442
      }
443
    }
444

445
446
447
    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;
448
449
450
  }
}

451
452
static void *scope_thread(void *arg)
{
knopp's avatar
   
knopp committed
453
  char stats_buffer[16384];
454
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
   
knopp committed
455
  FILE *UE_stats, *eNB_stats;
456
# endif
Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
457
  int len = 0;
knopp's avatar
   
knopp committed
458
  struct sched_param sched_param;
459
  int UE_id, CC_id;
460
  int ue_cnt=0;
461

462
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
   
knopp committed
463
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
464

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

467
# ifdef ENABLE_XFORMS_WRITE_STATS
468
469

  if (UE_flag==1)
knopp's avatar
   
knopp committed
470
    UE_stats  = fopen("UE_stats.txt", "w");
471
  else
knopp's avatar
   
knopp committed
472
    eNB_stats = fopen("eNB_stats.txt", "w");
473

474
#endif
475

knopp's avatar
   
knopp committed
476
477
  while (!oai_exit) {
    if (UE_flag==1) {
478
      len = 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
479
480
481
      //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);
482

483
484
485
486
487
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

knopp's avatar
   
knopp committed
488
    } else {
489
490
491
492
493
494
      if (PHY_vars_eNB_g[0][0]->mac_enabled==1) {
	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);
      }
Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
495
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
496

Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
497
      if (MAX_NUM_CCs>1)
498
499
        len += dump_eNB_stats (PHY_vars_eNB_g[0][1], &stats_buffer[len], 0);

kaltenbe's avatar
kaltenbe committed
500
501
502
      //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);
503

504
505
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
506
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
507
508
	  //	  if ((PHY_vars_eNB_g[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
	  if ((ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
509
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
510
511
512
513
			  PHY_vars_eNB_g[0][CC_id],
			  UE_id);
	    ue_cnt++;
	  }
514
	}
knopp's avatar
   
knopp committed
515
      }
516

517
    }
518

knopp's avatar
   
knopp committed
519
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
520
521
    //usleep(100000); // 100 ms
    sleep(1);
knopp's avatar
   
knopp committed
522
  }
523

524
  //  printf("%s",stats_buffer);
525

526
# ifdef ENABLE_XFORMS_WRITE_STATS
527

528
529
530
531
532
533
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
534
  } else {
535
536
537
538
539
540
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
541

542
# endif
543

knopp's avatar
   
knopp committed
544
  pthread_exit((void*)arg);
545
546
547
}
#endif

548

549

550

knopp's avatar
   
knopp committed
551
#if defined(ENABLE_ITTI)
552
void *l2l1_task(void *arg)
553
{
knopp's avatar
   
knopp committed
554
555
556
557
558
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
559

knopp's avatar
   
knopp committed
560
561
  if (UE_flag == 0) {
    /* Wait for the initialize message */
562
    printf("Wait for the ITTI initialize message\n");
563
    do {
knopp's avatar
   
knopp committed
564
      if (message_p != NULL) {
565
566
        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
567
      }
568

569
570
571
      itti_receive_msg (TASK_L2L1, &message_p);

      switch (ITTI_MSG_ID(message_p)) {
knopp's avatar
   
knopp committed
572
      case INITIALIZE_MESSAGE:
573
574
575
576
        /* 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
577
578

      case TERMINATE_MESSAGE:
579
580
581
582
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
knopp's avatar
   
knopp committed
583
584

      default:
585
586
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
587
      }
knopp's avatar
   
knopp committed
588
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
589

knopp's avatar
   
knopp committed
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
    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;
611

knopp's avatar
   
knopp committed
612
613
614
615
616
617
618
619
620
621
622
    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
623
  } while(!oai_exit);
624

knopp's avatar
   
knopp committed
625
  return NULL;
626
627
628
}
#endif

knopp's avatar
   
knopp committed
629

630

knopp's avatar
   
knopp committed
631

632
static void get_options (int argc, char **argv)
633
{
634
635
636
  int c;
  //  char                          line[1000];
  //  int                           l;
637
  int k,i;//,j,k;
638
#if defined(OAI_USRP) || defined(CPRIGW)
639
  int clock_src;
knopp's avatar
   
knopp committed
640
#endif
641
  int CC_id;
knopp's avatar
   
knopp committed
642
643


644

645
  const Enb_properties_array_t *enb_properties;
646

647
648
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
649
    LONG_OPTION_RF_CONFIG_FILE,
650
651
652
653
654
    LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS,
    LONG_OPTION_CALIB_UE_RX,
    LONG_OPTION_CALIB_UE_RX_MED,
    LONG_OPTION_CALIB_UE_RX_BYP,
    LONG_OPTION_DEBUG_UE_PRACH,
655
    LONG_OPTION_NO_L2_CONNECT,
knopp's avatar
   
knopp committed
656
    LONG_OPTION_CALIB_PRACH_TX,
657
658
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
659
    LONG_OPTION_SCANCARRIER,
660
661
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
662
    LONG_OPTION_LOOPMEMORY,
663
    LONG_OPTION_PHYTEST,
Cedric Roux's avatar
Cedric Roux committed
664
    LONG_OPTION_MMAPPED_DMA,
knopp's avatar
knopp committed
665
    LONG_OPTION_SINGLE_THREAD,
666
667
668
#if T_TRACER
    LONG_OPTION_T_PORT,
    LONG_OPTION_T_NOWAIT,
Cedric Roux's avatar
Cedric Roux committed
669
    LONG_OPTION_T_DONT_FORK,
670
#endif
671
  };
672

673
  static const struct option long_options[] = {
674
    {"rf-config-file",required_argument,  NULL, LONG_OPTION_RF_CONFIG_FILE},
675
676
677
678
679
680
    {"ulsch-max-errors",required_argument,  NULL, LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS},
    {"calib-ue-rx",     required_argument,  NULL, LONG_OPTION_CALIB_UE_RX},
    {"calib-ue-rx-med", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_MED},
    {"calib-ue-rx-byp", required_argument,  NULL, LONG_OPTION_CALIB_UE_RX_BYP},
    {"debug-ue-prach",  no_argument,        NULL, LONG_OPTION_DEBUG_UE_PRACH},
    {"no-L2-connect",   no_argument,        NULL, LONG_OPTION_NO_L2_CONNECT},
knopp's avatar
   
knopp committed
681
682
683
684
    {"calib-prach-tx",   no_argument,        NULL, LONG_OPTION_CALIB_PRACH_TX},
    {"ue-rxgain",   required_argument,  NULL, LONG_OPTION_RXGAIN},
    {"ue-txgain",   required_argument,  NULL, LONG_OPTION_TXGAIN},
    {"ue-scan-carrier",   no_argument,  NULL, LONG_OPTION_SCANCARRIER},
685
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
686
687
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
688
    {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
689
    {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
knopp's avatar
knopp committed
690
    {"single-thread", no_argument, NULL, LONG_OPTION_SINGLE_THREAD},
691
692
693
#if T_TRACER
    {"T_port",                 required_argument, 0, LONG_OPTION_T_PORT},
    {"T_nowait",               no_argument,       0, LONG_OPTION_T_NOWAIT},
694
    {"T_dont_fork",            no_argument,       0, LONG_OPTION_T_DONT_FORK},
695
#endif
696
697
698
    {NULL, 0, NULL, 0}
  };

699
  while ((c = getopt_long (argc, argv, "A:a:C:dEK:g:F:G:hqO:m:SUVRM:r:P:Ws:t:Tx:",long_options,NULL)) != -1) {
700
    switch (c) {
701
    case LONG_OPTION_RF_CONFIG_FILE:
702
703
704
705
706
707
      if ((strcmp("null", optarg) == 0) || (strcmp("NULL", optarg) == 0)) {
	printf("no configuration filename is provided\n");
      }
      else if (strlen(optarg)<=1024){
	strcpy(rf_config_file,optarg);
      }else {
708
709
	printf("Configuration filename is too long\n");
	exit(-1);   
710
711
      }
      break;
712
713
714
715
    case LONG_OPTION_MAXPOWER:
      tx_max_power[0]=atoi(optarg);
      for (CC_id=1;CC_id<MAX_NUM_CCs;CC_id++)
	tx_max_power[CC_id]=tx_max_power[0];
716
      break;
717
718
719
720
    case LONG_OPTION_ULSCH_MAX_CONSECUTIVE_ERRORS:
      ULSCH_max_consecutive_errors = atoi(optarg);
      printf("Set ULSCH_max_consecutive_errors = %d\n",ULSCH_max_consecutive_errors);
      break;
721

722
723
724
725
726
    case LONG_OPTION_CALIB_UE_RX:
      mode = rx_calib_ue;
      rx_input_level_dBm = atoi(optarg);
      printf("Running with UE calibration on (LNA max), input level %d dBm\n",rx_input_level_dBm);
      break;
727

728
729
730
731
    case LONG_OPTION_CALIB_UE_RX_MED:
      mode = rx_calib_ue_med;
      rx_input_level_dBm = atoi(optarg);
      printf("Running with UE calibration on (LNA med), input level %d dBm\n",rx_input_level_dBm);
knopp's avatar
   
knopp committed
732
      break;
733

734
735
736
737
738
    case LONG_OPTION_CALIB_UE_RX_BYP:
      mode = rx_calib_ue_byp;
      rx_input_level_dBm = atoi(optarg);
      printf("Running with UE calibration on (LNA byp), input level %d dBm\n",rx_input_level_dBm);
      break;
739

740
741
742
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
743

744
745
746
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
747

knopp's avatar
   
knopp committed
748
749
750
751
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

752
    case LONG_OPTION_RXGAIN:
753
754
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
755

756
      break;
757

758
759
760
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
761

762
      break;
763

764
765
766
767
768
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

769
770
771
772
773
774
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

775
776
777
778
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
779
780
781
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
782

783
784
785
    case LONG_OPTION_MMAPPED_DMA:
      mmapped_dma = 1;
      break;
knopp's avatar
knopp committed
786
787
788
789

    case LONG_OPTION_SINGLE_THREAD:
      single_thread_flag = 1;
      break;
790
              
791
792
793
794
795
796
797
798
799
800
801
802
803
#if T_TRACER
    case LONG_OPTION_T_PORT: {
      extern int T_port;
      if (optarg == NULL) abort();  /* should not happen */
      T_port = atoi(optarg);
      break;
    }

    case LONG_OPTION_T_NOWAIT: {
      extern int T_wait;
      T_wait = 0;
      break;
    }
804
805
806
807
808
809

    case LONG_OPTION_T_DONT_FORK: {
      extern int T_dont_fork;
      T_dont_fork = 1;
      break;
    }
810
811
#endif

812
813
814
815
    case 'A':
      timing_advance = atoi (optarg);
      break;

816
    case 'C':
817
818
819
820
821
822
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        downlink_frequency[CC_id][0] = atof(optarg); // Use float to avoid issue with frequency over 2^31.
        downlink_frequency[CC_id][1] = downlink_frequency[CC_id][0];
        downlink_frequency[CC_id][2] = downlink_frequency[CC_id][0];
        downlink_frequency[CC_id][3] = downlink_frequency[CC_id][0];
        printf("Downlink for CC_id %d frequency set to %u\n", CC_id, downlink_frequency[CC_id][0]);
knopp's avatar
knopp committed
823
      }
824

825
      UE_scan=0;
826

827
      break;
828

Florian Kaltenberger's avatar
Florian Kaltenberger committed
829
830
831
832
    case 'a':
      chain_offset = atoi(optarg);
      break;

833
834
835
836
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
knopp's avatar
   
knopp committed
837
#endif
838
      break;
839
840
841
842
      
    case 'E':
      threequarter_fs=1;
      break;
843

844
845
846
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
847
#else
848
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
knopp's avatar
   
knopp committed
849
#endif
850
      break;
851

852
853
854
    case 'O':
      conf_config_file_name = optarg;
      break;
855

856
857
858
    case 'U':
      UE_flag = 1;
      break;
859

860
861
862
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
863

864
865
866
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
867

868
869
870
871
872
873
874
    case 'W':
      opt_enabled=1;
      opt_type = OPT_WIRESHARK;
      strncpy(in_ip, "127.0.0.1", sizeof(in_ip));
      in_ip[sizeof(in_ip) - 1] = 0; // terminate string
      printf("Enabling OPT for wireshark for local interface");
      /*
875
876
877
878
879
880
881
882
	if (optarg == NULL){
	in_ip[0] =NULL;
	printf("Enabling OPT for wireshark for local interface");
	} else {
	strncpy(in_ip, optarg, sizeof(in_ip));
	in_ip[sizeof(in_ip) - 1] = 0; // terminate string
	printf("Enabling OPT for wireshark with %s \n",in_ip);
	}
883
884
      */
      break;
885

886
    case 'P':
887
888
      opt_type = OPT_PCAP;
      opt_enabled=1;
889
890
891
892
893

      if (optarg == NULL) {
        strncpy(in_path, "/tmp/oai_opt.pcap", sizeof(in_path));
        in_path[sizeof(in_path) - 1] = 0; // terminate string
        printf("Enabling OPT for PCAP with the following path /tmp/oai_opt.pcap");
894
      } else {
895
896
897
        strncpy(in_path, optarg, sizeof(in_path));
        in_path[sizeof(in_path) - 1] = 0; // terminate string
        printf("Enabling OPT for PCAP  with the following file %s \n",in_path);
898
      }
899
900
901

      break;

knopp's avatar
   
knopp committed
902
903
904
    case 'V':
      ouput_vcd = 1;
      break;
905

knopp's avatar
   
knopp committed
906
    case  'q':
knopp's avatar
   
knopp committed
907
908
      opp_enabled = 1;
      break;
909

knopp's avatar
   
knopp committed