lte-softmodem.c 60.6 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
knopp's avatar
knopp committed
121
extern int setup_eNB_buffers(PHY_VARS_eNB **phy_vars_eNB, openair0_config_t *openair0_cfg);
knopp's avatar
knopp committed
122
extern void init_eNB(eNB_func_t *, eNB_timing_t *,int,eth_params_t *,int);
123
extern void stop_eNB(int);
124
extern void kill_eNB_proc(void);
125

126
// In lte-ue.c
knopp's avatar
knopp committed
127
extern int setup_ue_buffers(PHY_VARS_UE **phy_vars_ue, openair0_config_t *openair0_cfg);
128
extern void fill_ue_band_info(void);
knopp's avatar
knopp committed
129
extern void init_UE(int);
130

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
knopp's avatar
knopp committed
166
volatile int             oai_exit = 0;
167

168

169

knopp's avatar
   
knopp committed
170

knopp's avatar
knopp committed
171
static char              UE_flag=0;
172
unsigned int                    mmapped_dma=0;
knopp's avatar
knopp committed
173
int                             single_thread_flag=0;
174

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

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

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

190
191
FILE *input_fd=NULL;

192

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

203
204


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

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

210
211
char   rf_config_file[1024];

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

215

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

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

229

knopp's avatar
   
knopp committed
230
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
231
232
233
eNB_func_t node_function[MAX_NUM_CCs];
eNB_timing_t node_timing[MAX_NUM_CCs];
int16_t   node_synch_ref[MAX_NUM_CCs];
234

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

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

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

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

knopp's avatar
   
knopp committed
273

knopp's avatar
knopp committed
274

knopp's avatar
   
knopp committed
275
char *rrh_UE_ip = "127.0.0.1";
276
int rrh_UE_port = 51000;
knopp's avatar
knopp committed
277

knopp's avatar
   
knopp committed
278

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

284
285
286
287
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

knopp's avatar
   
knopp committed
288
char uecap_xer[1024],uecap_xer_in=0;
289
290


knopp's avatar
   
knopp committed
291

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

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

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

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

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

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

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

415
416
void exit_fun(const char* s)
{
Raymond Knopp's avatar
Raymond Knopp committed
417
418
  int CC_id;

419
  if (s != NULL) {
420
    printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
421
422
423
  }

  oai_exit = 1;
Raymond Knopp's avatar
Raymond Knopp committed
424
425
426
427
428
429
430
  
  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);  
  }
431
432

#if defined(ENABLE_ITTI)
Florian Kaltenberger's avatar
Florian Kaltenberger committed
433
  sleep(1); //allow lte-softmodem threads to exit first
434
  itti_terminate_tasks (TASK_UNKNOWN);
435
#endif
436
437
438

}

439

440
#ifdef XFORMS
441

442
443
void reset_stats(FL_OBJECT *button, long arg)
{
444
445
  int i,j,k;
  PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];
446
447
448

  for (i=0; i<NUMBER_OF_UE_MAX; i++) {
    for (k=0; k<8; k++) { //harq_processes
449
450
451
452
      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;
453
      }
454

455
456
457
      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;
458

459
460
461
462
463
      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;
464
      }
465
    }
466

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

473
474
static void *scope_thread(void *arg)
{
knopp's avatar
   
knopp committed
475
  char stats_buffer[16384];
476
# ifdef ENABLE_XFORMS_WRITE_STATS
knopp's avatar
   
knopp committed
477
  FILE *UE_stats, *eNB_stats;
478
# endif
Florian Kaltenberger's avatar
   
Florian Kaltenberger committed
479
  int len = 0;
knopp's avatar
   
knopp committed
480
  struct sched_param sched_param;
481
  int UE_id, CC_id;
482
  int ue_cnt=0;
483

484
  sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
knopp's avatar
   
knopp committed
485
  sched_setscheduler(0, SCHED_FIFO,&sched_param);
486

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

489
# ifdef ENABLE_XFORMS_WRITE_STATS
490
491

  if (UE_flag==1)
knopp's avatar
   
knopp committed
492
    UE_stats  = fopen("UE_stats.txt", "w");
493
  else
knopp's avatar
   
knopp committed
494
    eNB_stats = fopen("eNB_stats.txt", "w");
495

496
#endif
497

knopp's avatar
   
knopp committed
498
499
  while (!oai_exit) {
    if (UE_flag==1) {
500
      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
501
502
503
      //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);
504

505
506
507
508
509
      phy_scope_UE(form_ue[0],
                   PHY_vars_UE_g[0][0],
                   0,
                   0,7);

knopp's avatar
   
knopp committed
510
    } else {
511
512
513
514
515
516
      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
517
      len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);
518

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

kaltenbe's avatar
kaltenbe committed
522
523
524
      //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);
525

526
527
      ue_cnt=0;
      for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
528
	for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
529
530
	  //	  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
531
	    phy_scope_eNB(form_enb[CC_id][ue_cnt],
532
533
534
535
			  PHY_vars_eNB_g[0][CC_id],
			  UE_id);
	    ue_cnt++;
	  }
536
	}
knopp's avatar
   
knopp committed
537
      }
538

539
    }
540

knopp's avatar
   
knopp committed
541
    //printf("doing forms\n");
Florian Kaltenberger's avatar
Florian Kaltenberger committed
542
543
    //usleep(100000); // 100 ms
    sleep(1);
knopp's avatar
   
knopp committed
544
  }
545

546
  //  printf("%s",stats_buffer);
547

548
# ifdef ENABLE_XFORMS_WRITE_STATS
549

550
551
552
553
554
555
  if (UE_flag==1) {
    if (UE_stats) {
      rewind (UE_stats);
      fwrite (stats_buffer, 1, len, UE_stats);
      fclose (UE_stats);
    }
556
  } else {
557
558
559
560
561
562
    if (eNB_stats) {
      rewind (eNB_stats);
      fwrite (stats_buffer, 1, len, eNB_stats);
      fclose (eNB_stats);
    }
  }
563

564
# endif
565

knopp's avatar
   
knopp committed
566
  pthread_exit((void*)arg);
567
568
569
}
#endif

570

571

572

knopp's avatar
   
knopp committed
573
#if defined(ENABLE_ITTI)
574
void *l2l1_task(void *arg)
575
{
knopp's avatar
   
knopp committed
576
577
578
579
580
  MessageDef *message_p = NULL;
  int         result;

  itti_set_task_real_time(TASK_L2L1);
  itti_mark_task_ready(TASK_L2L1);
581

knopp's avatar
   
knopp committed
582
583
  if (UE_flag == 0) {
    /* Wait for the initialize message */
584
    printf("Wait for the ITTI initialize message\n");
585
586
587
588
589
    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
590

591
      itti_receive_msg (TASK_L2L1, &message_p);
592

593
594
595
596
597
598
      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;
599

600
601
602
603
604
      case TERMINATE_MESSAGE:
        printf("received terminate message\n");
        oai_exit=1;
        itti_exit_task ();
        break;
605

606
607
608
609
610
      default:
        LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
        break;
      }
    } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
611

612
613
614
    result = itti_free (ITTI_MSG_ORIGIN_ID(message_p), message_p);
    AssertFatal (result == EXIT_SUCCESS, "Failed to free memory (%d)!\n", result);
  }
615

616
617
618
  do {
    // Wait for a message
    itti_receive_msg (TASK_L2L1, &message_p);
619

620
621
622
623
624
    switch (ITTI_MSG_ID(message_p)) {
    case TERMINATE_MESSAGE:
      oai_exit=1;
      itti_exit_task ();
      break;
knopp's avatar
   
knopp committed
625

626
627
628
    case ACTIVATE_MESSAGE:
      start_UE = 1;
      break;
629

630
631
632
    case DEACTIVATE_MESSAGE:
      start_UE = 0;
      break;
633

634
635
636
    case MESSAGE_TEST:
      LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
      break;
637

638
639
640
    default:
      LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
      break;
641
    }
642

643
644
645
    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);
646

647
648
  return NULL;
}
knopp's avatar
   
knopp committed
649
#endif
650

651

652

653

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


666
667

  const Enb_properties_array_t *enb_properties;
668

669
670
  enum long_option_e {
    LONG_OPTION_START = 0x100, /* Start after regular single char options */
671
    LONG_OPTION_RF_CONFIG_FILE,
672
673
674
675
676
    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,
677
    LONG_OPTION_NO_L2_CONNECT,
knopp's avatar
   
knopp committed
678
    LONG_OPTION_CALIB_PRACH_TX,
679
680
    LONG_OPTION_RXGAIN,
    LONG_OPTION_TXGAIN,
681
    LONG_OPTION_SCANCARRIER,
682
683
    LONG_OPTION_MAXPOWER,
    LONG_OPTION_DUMP_FRAME,
684
    LONG_OPTION_LOOPMEMORY,
685
    LONG_OPTION_PHYTEST,
Cedric Roux's avatar
Cedric Roux committed
686
    LONG_OPTION_MMAPPED_DMA,
knopp's avatar
knopp committed
687
    LONG_OPTION_SINGLE_THREAD,
688
689
690
#if T_TRACER
    LONG_OPTION_T_PORT,
    LONG_OPTION_T_NOWAIT,
Cedric Roux's avatar
Cedric Roux committed
691
    LONG_OPTION_T_DONT_FORK,
692
#endif
693
  };
694

695
  static const struct option long_options[] = {
696
    {"rf-config-file",required_argument,  NULL, LONG_OPTION_RF_CONFIG_FILE},
697
698
699
700
701
702
    {"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
703
704
705
706
    {"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},
707
    {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
708
709
    {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
    {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
710
    {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
711
    {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
knopp's avatar
knopp committed
712
    {"single-thread", no_argument, NULL, LONG_OPTION_SINGLE_THREAD},
713
714
715
#if T_TRACER
    {"T_port",                 required_argument, 0, LONG_OPTION_T_PORT},
    {"T_nowait",               no_argument,       0, LONG_OPTION_T_NOWAIT},
Cedric Roux's avatar
Cedric Roux committed
716
    {"T_dont_fork",            no_argument,       0, LONG_OPTION_T_DONT_FORK},
717
#endif
718
719
720
    {NULL, 0, NULL, 0}
  };

721
  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) {
722
    switch (c) {
723
    case LONG_OPTION_RF_CONFIG_FILE:
724
725
726
727
728
729
      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 {
730
731
	printf("Configuration filename is too long\n");
	exit(-1);   
732
733
      }
      break;
734
735
736
737
    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];
738
      break;
739
740
741
742
    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;
743

744
745
746
747
748
    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;
749

knopp's avatar
   
knopp committed
750

751
752
753
754
    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
755
      break;
756

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

763
764
765
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
766

767
768
769
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
770

knopp's avatar
   
knopp committed
771
772
773
774
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
      break;

775
    case LONG_OPTION_RXGAIN:
776
777
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
778

779
      break;
780

781
782
783
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
784

785
      break;
786

787
788
789
790
791
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

792
793
794
795
796
797
    case LONG_OPTION_LOOPMEMORY:
      mode=loop_through_memory;
      input_fd = fopen(optarg,"r");
      AssertFatal(input_fd != NULL,"Please provide an input file\n");
      break;

798
799
800
801
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
802
803
804
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
805

806
807
808
    case LONG_OPTION_MMAPPED_DMA:
      mmapped_dma = 1;
      break;
knopp's avatar
knopp committed
809
810
811
812

    case LONG_OPTION_SINGLE_THREAD:
      single_thread_flag = 1;
      break;
813
              
814
815
816
817
818
819
820
821
822
823
824
825
826
#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;
    }
827
828
829
830
831
832

    case LONG_OPTION_T_DONT_FORK: {
      extern int T_dont_fork;
      T_dont_fork = 1;
      break;
    }
833
834
#endif

835
836
837
838
    case 'A':
      timing_advance = atoi (optarg);
      break;

839
    case 'C':
840
841
842
843
844
845
      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
846
      }
847

848
      UE_scan=0;
849

850
      break;