lte-softmodem.c 59 KB
Newer Older
1
/*******************************************************************************
2
    OpenAirInterface
3
    Copyright(c) 1999 - 2014 Eurecom
4

5
6
7
8
    OpenAirInterface is free software: you can redistribute it and/or modify
    it under the terms of the GNU General Public License as published by
    the Free Software Foundation, either version 3 of the License, or
    (at your option) any later version.
9
10


11
12
13
14
    OpenAirInterface is distributed in the hope that it will be useful,
    but WITHOUT ANY WARRANTY; without even the implied warranty of
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
    GNU General Public License for more details.
15

16
    You should have received a copy of the GNU General Public License
17
18
    along with OpenAirInterface.The full GNU General Public License is
    included in this distribution in the file called "COPYING". If not,
19
    see <http://www.gnu.org/licenses/>.
20

21
22
23
   Contact Information
   OpenAirInterface Admin: openair_admin@eurecom.fr
   OpenAirInterface Tech : openair_tech@eurecom.fr
24
   OpenAirInterface Dev  : openair4g-devel@lists.eurecom.fr
25

ghaddab's avatar
ghaddab committed
26
   Address      : Eurecom, Campus SophiaTech, 450 Route des Chappes, CS 50193 - 06904 Biot Sophia Antipolis cedex, FRANCE
27

knopp's avatar
   
knopp committed
28
*******************************************************************************/
29

30
31
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
32
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
   
knopp committed
33
34
35
 * \date 2012
 * \version 0.1
 * \company Eurecom
36
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
knopp's avatar
   
knopp committed
37
38
39
 * \note
 * \warning
 */
knopp's avatar
   
knopp committed
40
#define _GNU_SOURCE
41
42
43
44
45
46
47
48
#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>
49
#include <linux/sched.h>
50
51
52
#include <signal.h>
#include <execinfo.h>
#include <getopt.h>
53
#include <sys/sysinfo.h>
54
#include "rt_wrapper.h"
55

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

58
#include "assertions.h"
59
#include "msc.h"
60
61

#include "PHY/types.h"
62

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

knopp's avatar
   
knopp committed
67
68
#include "../../ARCH/COMMON/common_lib.h"

knopp's avatar
   
knopp committed
69
//#undef FRAME_LENGTH_COMPLEX_SAMPLES //there are two conflicting definitions, so we better make sure we don't use it at all
70
71
72
73
74
75
76
77
78

#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"
79
#include "LAYER2/MAC/proto.h"
80
81
82
83
84
85
86
87
#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
88
#include "UTIL/OTG/otg_tx.h"
89
#include "UTIL/OTG/otg_externs.h"
90
91
#include "UTIL/MATH/oml.h"
#include "UTIL/LOG/vcd_signal_dumper.h"
92
#include "UTIL/OPT/opt.h"
93
#include "enb_config.h"
nikaeinn's avatar
nikaeinn committed
94
//#include "PHY/TOOLS/time_meas.h"
95

Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
96
97
98
99
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

100
101
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
102
# include "create_tasks.h"
103
104
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
105
#ifdef PDCP_USE_NETLINK
106
107
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
108
# endif
109
110
#endif

111
112
113
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
114
115
#endif

116
int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
117
118
119
int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
extern void init_eNB(void);
extern void stop_eNB(void);
120

121
void fill_ue_band_info(void);
122
#ifdef XFORMS
123
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
gauthier's avatar
gauthier committed
124
// at eNB 0, an UL scope for every UE
125
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
126
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
127
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
128
char title[255];
129
unsigned char                   scope_enb_num_ue = 2;
130
131
#endif //XFORMS

132

knopp's avatar
   
knopp committed
133
pthread_t                       main_ue_thread;
134

135
136
pthread_attr_t                  attr_UE_thread;

137
138


knopp's avatar
   
knopp committed
139

knopp's avatar
   
knopp committed
140
141
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
142
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
143

144

145
146


147
struct sched_param              sched_param_UE_thread;
148

149

150
#ifdef XFORMS
knopp's avatar
   
knopp committed
151
static pthread_t                forms_thread; //xforms
152
#endif
153

knopp's avatar
   
knopp committed
154
openair0_device openair0;
155

156
157
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
158

159

160
#if defined(ENABLE_ITTI)
161
162
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
163
#endif
164
165
volatile int                    oai_exit = 0;

166

167

knopp's avatar
   
knopp committed
168

169
static char                     UE_flag=0;
170
171
//static uint8_t                  eNB_id=0,UE_id=0;

172
static char                     threequarter_fs=0;
173

174
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
175
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
176

177
openair0_rf_map rf_map[MAX_NUM_CCs];
178

179
static char                    *conf_config_file_name = NULL;
180
#if defined(ENABLE_ITTI)
181
static char                    *itti_dump_file = NULL;
knopp's avatar
   
knopp committed
182
183
#endif

184
int UE_scan = 1;
185
int UE_scan_carrier = 0;
186
187
runmode_t mode = normal_txrx;

188
189
FILE *input_fd=NULL;

190

191
192
#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
193
194
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
195
196
197
198
#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
199
#endif
knopp's avatar
   
knopp committed
200

201
202


knopp's avatar
   
knopp committed
203
double sample_rate=30.72e6;
204
double bw = 10.0e6;
205

206
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
207

208
209
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
210
int chain_offset=0;
211
int phy_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
212

213

knopp's avatar
   
knopp committed
214
215
216
char ref[128] = "internal";
char channels[128] = "0";

217
int                      rx_input_level_dBm;
218
static int                      online_log_messages=0;
219
#ifdef XFORMS
220
extern int                      otg_enabled;
221
static char                     do_forms=0;
222
#else
223
int                             otg_enabled;
224
#endif
knopp's avatar
   
knopp committed
225
//int                             number_of_cards =   1;
226

227

knopp's avatar
   
knopp committed
228
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
229

230

Florian Kaltenberger's avatar
Florian Kaltenberger committed
231
uint32_t target_dl_mcs = 28; //maximum allowed mcs
232
uint32_t target_ul_mcs = 20;
233
uint32_t timing_advance = 0;
234
235
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
236

knopp's avatar
   
knopp committed
237

238
239
240

extern void reset_opp_meas(void);
extern void print_opp_meas(void);
241
int transmission_mode=1;
knopp's avatar
   
knopp committed
242

243
int16_t           glog_level         = LOG_INFO;
gauthier's avatar
   
gauthier committed
244
int16_t           glog_verbosity     = LOG_MED;
245
int16_t           hw_log_level       = LOG_INFO;
gauthier's avatar
   
gauthier committed
246
int16_t           hw_log_verbosity   = LOG_MED;
247
int16_t           phy_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
248
int16_t           phy_log_verbosity  = LOG_MED;
249
int16_t           mac_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
250
int16_t           mac_log_verbosity  = LOG_MED;
251
int16_t           rlc_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
252
int16_t           rlc_log_verbosity  = LOG_MED;
253
int16_t           pdcp_log_level     = LOG_INFO;
gauthier's avatar
   
gauthier committed
254
int16_t           pdcp_log_verbosity = LOG_MED;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
255
int16_t           rrc_log_level      = LOG_INFO;
gauthier's avatar
   
gauthier committed
256
int16_t           rrc_log_verbosity  = LOG_MED;
257
258
259
int16_t           opt_log_level      = LOG_INFO;
int16_t           opt_log_verbosity  = LOG_MED;

gauthier's avatar
   
gauthier committed
260
261
262
263
264
265
# 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
266
267
268
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
269
#endif
270

knopp's avatar
   
knopp committed
271
272
273

#ifdef ETHERNET
char *rrh_UE_ip = "127.0.0.1";
274
int rrh_UE_port = 51000;
knopp's avatar
   
knopp committed
275
276
#endif

277
278
279
280
281
/* 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;

282
283
284
285
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

knopp's avatar
   
knopp committed
286
char uecap_xer[1024],uecap_xer_in=0;
287
288
extern void *UE_thread(void *arg);
extern void init_UE_threads(void);
289
extern void kill_eNB_proc(void);
knopp's avatar
   
knopp committed
290

291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
/*---------------------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)
{
    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;
}

Cedric Roux's avatar
Cedric Roux committed
309
void print_difftimes(void)
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
{
#ifdef DEBUG
    printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#else
    LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
#endif
}

void update_difftimes(struct timespec start, struct timespec end)
{
    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; }
#if 1
    if (changed) print_difftimes();
#endif
}

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

332
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
333
{
knopp's avatar
   
knopp committed
334
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
335
336
337
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
knopp's avatar
   
knopp committed
338
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
339
340
}

341
#if !defined(ENABLE_ITTI)
342
343
344
345
346
347
348
349
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);
350

351
352
353
354
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
355
356
  } else {
    printf("trying to exit gracefully...\n");
357
    oai_exit = 1;
358
359
  }
}
360
#endif
nikaeinn's avatar
nikaeinn committed
361
362
363
364
365
366
367
368
369
370
371
#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");
372
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
nikaeinn's avatar
nikaeinn committed
373
374
375
376
  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
377
378
  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
379
  printf("  --no-L2-connect bypass L2 and upper layers\n");
380
381
382
383
  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");
384
  printf("  -C Set the downlink frequency for all component carriers\n");
nikaeinn's avatar
nikaeinn committed
385
386
387
  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");
388
  printf("  -G Set the global log verbosity \n");
nikaeinn's avatar
nikaeinn committed
389
390
391
392
393
  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
394
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
nikaeinn's avatar
nikaeinn committed
395
396
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
397
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
nikaeinn's avatar
nikaeinn committed
398
399
400
401
  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");
  printf("  -x Set the transmission mode, valid options: 1 \n"RESET);    
402

nikaeinn's avatar
nikaeinn committed
403
}
404

405
406
void exit_fun(const char* s)
{
407
  if (s != NULL) {
408
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
409
410
411
412
413
  }

  oai_exit = 1;

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

}

420

421
#ifdef XFORMS
422

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

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
430
      for (j=0; j<phy_vars_eNB->dlsch_eNB[i][0]->Mlimit; j++) {
431
432
433
        phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_ACK[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].dlsch_trials[k][j]=0;
434
      }
435

436
437
438
      phy_vars_eNB->eNB_UE_stats[i].dlsch_l2_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_errors[k]=0;
      phy_vars_eNB->eNB_UE_stats[i].ulsch_consecutive_errors=0;
439

440
      for (j=0; j<phy_vars_eNB->ulsch_eNB[i]->Mlimit; j++) {
441
442
443
444
        phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_decoding_attempts_last[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_round_errors[k][j]=0;
        phy_vars_eNB->eNB_UE_stats[i].ulsch_round_fer[k][j]=0;
445
      }
446
    }
447

448
449
450
    phy_vars_eNB->eNB_UE_stats[i].dlsch_sliding_cnt=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_NAK_round0=0;
    phy_vars_eNB->eNB_UE_stats[i].dlsch_mcs_offset=0;
451
452
453
  }
}

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

465
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
   
knopp committed
466
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
467

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

470
# ifdef ENABLE_XFORMS_WRITE_STATS
471
472

  if (UE_flag==1)
knopp's avatar
   
knopp committed
473
    UE_stats  = fopen("UE_stats.txt", "w");
474
  else
knopp's avatar
   
knopp committed
475
    eNB_stats = fopen("eNB_stats.txt", "w");
476

477
#endif
478

knopp's avatar
   
knopp committed
479
480
  while (!oai_exit) {
    if (UE_flag==1) {
Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
481
      len = dump_ue_stats (PHY_vars_UE_g[0][0], stats_buffer, 0, mode,rx_input_level_dBm);
knopp's avatar
knopp committed
482
483
484
      //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);
485

486
487
488
489
490
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

knopp's avatar
   
knopp committed
491
    } else {
492
493
494
495
496
497
      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
498
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
499

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

kaltenbe's avatar
kaltenbe committed
503
504
505
      //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);
506

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

519
    }
520

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

526
  //  printf("%s",stats_buffer);
527

528
# ifdef ENABLE_XFORMS_WRITE_STATS
529

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

544
# endif
545

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

550

551

552

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

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
561

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

571
      itti_receive_msg (TASK_L2L1, &message_p);
572

573
574
575
576
577
578
      switch (ITTI_MSG_ID(message_p)) {
      case INITIALIZE_MESSAGE:
        /* Start eNB thread */
        LOG_D(EMU, "L2L1 TASK received %s\n", ITTI_MSG_NAME(message_p));
        start_eNB = 1;
        break;
579

580
581
582
583
584
      case TERMINATE_MESSAGE:
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
585

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

592
593
594
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }
595

596
597
598
  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);
599

600
601
602
603
604
    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;
knopp's avatar
   
knopp committed
605

606
607
608
    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;
609

610
611
612
    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
613

614
615
616
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;
617

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

623
624
625
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  } while(!oai_exit);
626

627
628
  return NULL;
}
knopp's avatar
   
knopp committed
629
#endif
630

631

632

633
634


635

636

knopp's avatar
   
knopp committed
637

Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
638

639
640
static void get_options (int argc, char **argv)
{
641
642
643
  int c;
  //  char                          line[1000];
  //  int                           l;
644
  int k,i;//,j,k;
645
#if defined(OAI_USRP) || defined(CPRIGW)
646
  int clock_src;
knopp's avatar
knopp committed
647
#endif
648
  int CC_id;
649
650


651
652

  const Enb_properties_array_t *enb_properties;
653

654
655
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
656
    LONG_OPTION_RF_CONFIG_FILE,
657
658
659
660
661
    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,
662
    LONG_OPTION_NO_L2_CONNECT,
knopp's avatar
   
knopp committed
663
    LONG_OPTION_CALIB_PRACH_TX,
664
665
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
666
    LONG_OPTION_SCANCARRIER,
667
668
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
669
670
    LONG_OPTION_LOOPMEMORY,
    LONG_OPTION_PHYTEST
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
690
691
    {NULL, 0, NULL, 0}
  };

692
  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) {
693
    switch (c) {
694
    case LONG_OPTION_RF_CONFIG_FILE:
695
696
697
698
699
700
      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 {
701
702
703
704
         printf("Configuration filename is too long\n");
         exit(-1);   
      }
      break;
705
706
707
708
    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];
709
      break;
710
711
712
713
    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;
714

715
716
717
718
719
    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;
720

721
722
723
724
    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
725
      break;
726

727
728
729
730
731
    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;
732

733
734
735
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
736

737
738
739
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
740

knopp's avatar
   
knopp committed
741
742
743
744
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

745
    case LONG_OPTION_RXGAIN:
746
747
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
748

749
      break;
750

751
752
753
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
754

755
      break;
756

757
758
759
760
761
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

762
763
764
765
766
767
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

768
769
770
771
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
772
773
774
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
775
      
776
777
778
779
    case 'A':
      timing_advance = atoi (optarg);
      break;

780
    case 'C':
781
782
783
784
785
786
      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
787
      }
788

789
      UE_scan=0;
790

791
      break;
792

Florian Kaltenberger's avatar
Florian Kaltenberger committed
793
794
795
796
    case 'a':
      chain_offset = atoi(optarg);
      break;

797
798
799
800
    case 'd':
#ifdef XFORMS
      do_forms=1;
      printf("Running with XFORMS!\n");
knopp's avatar
   
knopp committed
801
#endif
802
      break;
803
804
805
806
      
    case 'E':
      threequarter_fs=1;
      break;
807

808
809
810
    case 'K':
#if defined(ENABLE_ITTI)
      itti_dump_file = strdup(optarg);
811
#else
812
      printf("-K option is disabled when ENABLE_ITTI is not defined\n");
knopp's avatar
   
knopp committed
813
#endif
814
      break;
815

816
817
818
    case 'O':
      conf_config_file_name = optarg;
      break;
819

820
821
822
    case 'U':
      UE_flag = 1;
      break;
823

824
825
826
    case 'm':
      target_dl_mcs = atoi (optarg);
      break;
827

828
829
830
    case 't':
      target_ul_mcs = atoi (optarg);
      break;
831

832
833
834
835
836
837
838
    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");
      /*
839
840
841
      if (optarg == NULL){
      in_ip[0] =NULL;
      printf("Enabling OPT for wireshark for local interface");
842
      } else {
843
844
845
      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);
846
847
848
      }
      */
      break;
849

850
    case 'P':
851
852
      opt_type = OPT_PCAP;
      opt_enabled=1;
853
854
855
856
857

      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");
858
      } else {
859
860
861
        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);
862
      }
863
864
865

      break;

knopp's avatar
   
knopp committed
866
867
868
    case 'V':
      ouput_vcd = 1;
      break;
869

knopp's avatar
   
knopp committed
870
    case  'q':
knopp's avatar
   
knopp committed
871
872
      opp_enabled = 1;
      break;
873

knopp's avatar
   
knopp committed
874
875
876
    case  'R' :
      online_log_messages =1;
      break;
877

knopp's avatar
   
knopp committed
878
    case 'r':
879
      UE_scan = 0;
880

881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
      for (CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        switch(atoi(optarg)) {
        case 6:
          frame_parms[CC_id]->N_RB_DL=6;
          frame_parms[CC_id]->N_RB_UL=6;
          break;

        case 25:
          frame_parms[CC_id]->N_RB_DL=25;
          frame_parms[CC_id]->N_RB_UL=25;
          break;

        case 50:
          frame_parms[CC_id]->N_RB_DL=50;
          frame_parms[CC_id]->N_RB_UL=50;
          break;

        case 100:
          frame_parms[CC_id]->N_RB_DL=100;
          frame_parms[CC_id]->N_RB_UL=100;
          break;

        default:
          printf("Unknown N_RB_DL %d, switching to 25\n",atoi(optarg));
          break;
        }
knopp's avatar
   
knopp committed
907
      }
908

909
      break;
910

knopp's avatar
   
knopp committed
911
    case 's':
912
#if defined(OAI_USRP) || defined(CPRIGW)
knopp's avatar
   
knopp committed
913
914