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

55
56
#include "T.h"

57
#include "rt_wrapper.h"
58

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

61
#include "assertions.h"
62
#include "msc.h"
63
64

#include "PHY/types.h"
65

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

knopp's avatar
   
knopp committed
70
#include "../../ARCH/COMMON/common_lib.h"
71
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
knopp's avatar
   
knopp committed
72

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

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

Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
100
101
102
103
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

104
105
#if defined(ENABLE_ITTI)
# include "intertask_interface_init.h"
106
# include "create_tasks.h"
107
108
# if defined(ENABLE_USE_MME)
#   include "s1ap_eNB.h"
109
#ifdef PDCP_USE_NETLINK
110
111
#   include "SIMULATION/ETH_TRANSPORT/proto.h"
#endif
112
# endif
113
114
#endif

115
116
117
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
118
119
#endif

120
// In lte-enb.c
121
extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg, openair0_rf_map rf_map[MAX_NUM_CCs]);
122
extern void init_eNB(eNB_func_t);
123
extern void stop_eNB(void);
124
extern void kill_eNB_proc(void);
125

126
// In lte-ue.c
127
128
extern 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 fill_ue_band_info(void);
129
130
extern void init_UE(void);

131
#ifdef XFORMS
132
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
gauthier's avatar
gauthier committed
133
// at eNB 0, an UL scope for every UE
134
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
135
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
136
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
137
char title[255];
138
unsigned char                   scope_enb_num_ue = 2;
139
140
#endif //XFORMS

141

142

143
144


knopp's avatar
   
knopp committed
145

knopp's avatar
   
knopp committed
146
147
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
148
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
149

150

151
152


153

154
#ifdef XFORMS
knopp's avatar
   
knopp committed
155
static pthread_t                forms_thread; //xforms
156
#endif
157

158
159
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
160

161

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

168

169

knopp's avatar
   
knopp committed
170

171
static char                     UE_flag=0;
172
unsigned int                    mmapped_dma=0;
173
174
//static uint8_t                  eNB_id=0,UE_id=0;

175
static char                     threequarter_fs=0;
176

177
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
178
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
179

180
openair0_rf_map rf_map[MAX_NUM_CCs];
181

182
static char                    *conf_config_file_name = NULL;
183
#if defined(ENABLE_ITTI)
184
static char                    *itti_dump_file = NULL;
knopp's avatar
   
knopp committed
185
186
#endif

187
int UE_scan = 1;
188
int UE_scan_carrier = 0;
189
190
runmode_t mode = normal_txrx;

191
192
FILE *input_fd=NULL;

193

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

204
205


knopp's avatar
   
knopp committed
206
double sample_rate=30.72e6;
207
double bw = 10.0e6;
208

209
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
210

211
212
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
213
int chain_offset=0;
214
int phy_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
215

216

knopp's avatar
   
knopp committed
217
218
219
char ref[128] = "internal";
char channels[128] = "0";

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

230

knopp's avatar
   
knopp committed
231
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
232
eNB_func_t node_function=eNodeB_3GPP;
233

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

knopp's avatar
   
knopp committed
240

241
242
243

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

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

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

knopp's avatar
   
knopp committed
274
275
276

#ifdef ETHERNET
char *rrh_UE_ip = "127.0.0.1";
277
int rrh_UE_port = 51000;
knopp's avatar
   
knopp committed
278
279
#endif

280
281
282
283
284
/* 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;

285
286
openair0_config_t openair0_cfg[MAX_CARDS];

287
288
289
// Change to openair_global to handle UE
openair0_device openair0;

290
291
double cpuf;

knopp's avatar
   
knopp committed
292
char uecap_xer[1024],uecap_xer_in=0;
293
294


knopp's avatar
   
knopp committed
295

296
297
298
299
300
301
302
/*---------------------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)
{
303
304
305
306
307
308
309
310
311
  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;
312
313
}

Cedric Roux's avatar
Cedric Roux committed
314
void print_difftimes(void)
315
316
{
#ifdef DEBUG
317
  printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
318
#else
319
  LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
320
321
322
323
324
#endif
}

void update_difftimes(struct timespec start, struct timespec end)
{
325
326
327
328
329
  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; }
330
#if 1
331
  if (changed) print_difftimes();
332
333
334
335
336
#endif
}

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

337
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq)
338
{
knopp's avatar
   
knopp committed
339
  return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
340
341
342
}
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe)
{
knopp's avatar
   
knopp committed
343
  return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
344
345
}

346
#if !defined(ENABLE_ITTI)
347
348
349
350
351
352
353
354
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);
355

356
357
358
359
    // print out all the frames to stderr
    fprintf(stderr, "Error: signal %d:\n", sig);
    backtrace_symbols_fd(array, size, 2);
    exit(-1);
360
361
  } else {
    printf("trying to exit gracefully...\n");
362
    oai_exit = 1;
363
364
  }
}
365
#endif
nikaeinn's avatar
nikaeinn committed
366
367
368
369
370
371
372
373
374
375
376
#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");
377
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
nikaeinn's avatar
nikaeinn committed
378
379
380
381
  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
382
383
  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
384
  printf("  --no-L2-connect bypass L2 and upper layers\n");
385
386
387
388
  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");
389
  printf("  --mmapped-dma sets flag for improved EXMIMO UE performance\n");   
390
391
  printf("  --RCC run using NGFI RCC node function IF4 split\n");
  printf("  --RRU run using NGFI RRU node function  IF4 split\n");
392
  printf("  --eNB run using 3GPP eNB node function\n");   
393
  printf("  --BBU run using 3GPP eNB node function with IF5 split\n");   
394
  printf("  --RRH run using RRH node function with IF5 split\n");
395
  printf("  -C Set the downlink frequency for all component carriers\n");
nikaeinn's avatar
nikaeinn committed
396
397
398
  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");
399
  printf("  -G Set the global log verbosity \n");
nikaeinn's avatar
nikaeinn committed
400
401
402
403
404
  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
405
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
nikaeinn's avatar
nikaeinn committed
406
407
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
408
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
nikaeinn's avatar
nikaeinn committed
409
410
411
  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");
412
413
414
415
416
417
418
  printf("  -x Set the transmission mode, valid options: 1 \n");
#if T_TRACER
  printf("  --T_port [port]    use given port\n");
  printf("  --T_nowait         don't wait for tracer, start immediately\n");
#endif
  printf(RESET);
  fflush(stdout);
nikaeinn's avatar
nikaeinn committed
419
}
420

421
422
void exit_fun(const char* s)
{
Raymond Knopp's avatar
Raymond Knopp committed
423
424
  int CC_id;

425
  if (s != NULL) {
426
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
427
428
429
  }

  oai_exit = 1;
Raymond Knopp's avatar
Raymond Knopp committed
430
431
432
433
434
435
436
  
  for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
    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);  
  }
437
438

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
439
  sleep(1); //allow lte-softmodem threads to exit first
440
  itti_terminate_tasks (TASK_UNKNOWN);
441
#endif
442
443
444

}

445

446
#ifdef XFORMS
447

448
449
void reset_stats(FL_OBJECT *button, long arg)
{
450
451
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
452
453
454

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
455
456
457
458
      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;
459
      }
460

461
462
463
      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;
464

465
466
467
468
469
      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;
470
      }
471
    }
472

473
474
475
    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;
476
477
478
  }
}

479
480
static void *scope_thread(void *arg)
{
knopp's avatar
   
knopp committed
481
  char stats_buffer[16384];
482
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
   
knopp committed
483
  FILE *UE_stats, *eNB_stats;
484
# endif
Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
485
  int len = 0;
knopp's avatar
   
knopp committed
486
  struct sched_param sched_param;
487
  int UE_id, CC_id;
488
  int ue_cnt=0;
489

490
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
   
knopp committed
491
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
492

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

495
# ifdef ENABLE_XFORMS_WRITE_STATS
496
497

  if (UE_flag==1)
knopp's avatar
   
knopp committed
498
    UE_stats  = fopen("UE_stats.txt", "w");
499
  else
knopp's avatar
   
knopp committed
500
    eNB_stats = fopen("eNB_stats.txt", "w");
501

502
#endif
503

knopp's avatar
   
knopp committed
504
505
  while (!oai_exit) {
    if (UE_flag==1) {
506
      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
507
508
509
      //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);
510

511
512
513
514
515
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

knopp's avatar
   
knopp committed
516
    } else {
517
518
519
520
521
522
      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
523
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
524

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

kaltenbe's avatar
kaltenbe committed
528
529
530
      //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);
531

532
533
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
534
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
535
	  if ((PHY_vars_eNB_g[0][CC_id]->dlsch[UE_id][0]->rnti>0) && (ue_cnt<scope_enb_num_ue)) {
gauthier's avatar
gauthier committed
536
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
537
538
539
540
			  PHY_vars_eNB_g[0][CC_id],
			  UE_id);
	    ue_cnt++;
	  }
541
	}
knopp's avatar
   
knopp committed
542
      }
543

544
    }
545

knopp's avatar
   
knopp committed
546
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
547
548
    //usleep(100000); // 100 ms
    sleep(1);
knopp's avatar
   
knopp committed
549
  }
550

551
  //  printf("%s",stats_buffer);
552

553
# ifdef ENABLE_XFORMS_WRITE_STATS
554

555
556
557
558
559
560
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
561
  } else {
562
563
564
565
566
567
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
568

569
# endif
570

knopp's avatar
   
knopp committed
571
  pthread_exit((void*)arg);
572
573
574
}
#endif

575

576

577

knopp's avatar
   
knopp committed
578
#if defined(ENABLE_ITTI)
579
void *l2l1_task(void *arg)
580
{
knopp's avatar
   
knopp committed
581
582
583
584
585
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
586

knopp's avatar
   
knopp committed
587
588
  if (UE_flag == 0) {
    /* Wait for the initialize message */
589
    printf("Wait for the ITTI initialize message\n");
590
591
592
593
594
    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
595

596
      itti_receive_msg (TASK_L2L1, &message_p);
597

598
599
600
601
602
603
      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;
604

605
606
607
608
609
      case TERMINATE_MESSAGE:
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
610

611
612
613
614
615
      default:
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
      }
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
616

617
618
619
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }
620

621
622
623
  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);
624

625
626
627
628
629
    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;
knopp's avatar
   
knopp committed
630

631
632
633
    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;
634

635
636
637
    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
638

639
640
641
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;
642

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

648
649
650
    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);
651

652
653
  return NULL;
}
knopp's avatar
   
knopp committed
654
#endif
655

656

657

658

659
660
static void get_options (int argc, char **argv)
{
661
662
663
  int c;
  //  char                          line[1000];
  //  int                           l;
664
  int k,i;//,j,k;
665
#if defined(OAI_USRP) || defined(CPRIGW)
666
  int clock_src;
knopp's avatar
knopp committed
667
#endif
668
  int CC_id;
669
670


671
672

  const Enb_properties_array_t *enb_properties;
673

674
675
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
676
    LONG_OPTION_RF_CONFIG_FILE,
677
678
679
680
681
    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,
682
    LONG_OPTION_NO_L2_CONNECT,
knopp's avatar
   
knopp committed
683
    LONG_OPTION_CALIB_PRACH_TX,
684
685
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
686
    LONG_OPTION_SCANCARRIER,
687
688
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
689
    LONG_OPTION_LOOPMEMORY,
690
    LONG_OPTION_PHYTEST,
691
    LONG_OPTION_MMAPPED_DMA,
692
693
    LONG_OPTION_RCC,
    LONG_OPTION_RRU,
694
    LONG_OPTION_ENB,
695
696
    LONG_OPTION_ENB_BBU,
    LONG_OPTION_RRH
697
#if T_TRACER
698
    ,
699
700
701
    LONG_OPTION_T_PORT,
    LONG_OPTION_T_NOWAIT,
#endif
702
  };
703

704
  static const struct option long_options[] = {
705
    {"rf-config-file",required_argument,  NULL, LONG_OPTION_RF_CONFIG_FILE},
706
707
708
709
710
711
    {"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
712
713
714
715
    {"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},
716
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
717
718
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
719
    {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
720
    {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
721
722
723
    {"RCC", no_argument, NULL, LONG_OPTION_RCC},
    {"RRU", no_argument, NULL, LONG_OPTION_RRU},
    {"eNB", no_argument, NULL, LONG_OPTION_ENB},
724
    {"BBU", no_argument, NULL, LONG_OPTION_ENB_BBU},
725
    {"RRH", no_argument, NULL, LONG_OPTION_RRH},
726
727
728
729
#if T_TRACER
    {"T_port",                 required_argument, 0, LONG_OPTION_T_PORT},
    {"T_nowait",               no_argument,       0, LONG_OPTION_T_NOWAIT},
#endif
730
731
732
    {NULL, 0, NULL, 0}
  };

733
  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) {
734
    switch (c) {
735
    case LONG_OPTION_RF_CONFIG_FILE:
736
737
738
739
740
741
      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 {
742
743
	printf("Configuration filename is too long\n");
	exit(-1);   
744
745
      }
      break;
746
747
748
749
    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];
750
      break;
751
752
753
754
    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;
755

756
757
758
759
760
    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;
761

762
763
764
765
    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
766
      break;
767

768
769
770
771
772
    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;
773

774
775
776
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
777

778
779
780
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
781

knopp's avatar
   
knopp committed
782
783
784
785
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

786
    case LONG_OPTION_RXGAIN:
787
788
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
789

790
      break;
791

792
793
794
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
795

796
      break;
797

798
799
800
801
802
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

803
804
805
806
807
808
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

809
810
811
812
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
813
814
815
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
816

817
818
819
820
    case LONG_OPTION_MMAPPED_DMA:
      mmapped_dma = 1;
      break;

821
822
823
824
825
826
827
828
829
830
831
    case LONG_OPTION_RCC:
      node_function = NGFI_RCC_IF4;
      break;

    case LONG_OPTION_RRU:
      node_function = NGFI_RRU_IF4;
      break;

    case LONG_OPTION_ENB:
      node_function = eNodeB_3GPP;
      break;
832
833
834
835

    case LONG_OPTION_ENB_BBU:
      node_function = eNodeB_3GPP_BBU;
      break;
836
837
838
839

    case LONG_OPTION_RRH:
      node_function = NGFI_RRU_IF5;
      break;
840
              
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
#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;
    }
#endif

856
857
858
859
    case 'A':
      timing_advance = atoi (optarg);
      break;

860
    case 'C':
861
862
863
864
865
866
      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
867
      }
868

869