lte-softmodem.c 77.7 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21
/*
 * Licensed to the OpenAirInterface (OAI) Software Alliance under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The OpenAirInterface Software Alliance licenses this file to You under
 * the OAI Public License, Version 1.0  (the "License"); you may not use this file
 * except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.openairinterface.org/?page_id=698
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *-------------------------------------------------------------------------------
 * For more information about the OpenAirInterface (OAI) Software Alliance:
 *      contact@openairinterface.org
 */

22 23
/*! \file lte-enb.c
 * \brief Top-level threads for eNodeB
24
 * \author R. Knopp, F. Kaltenberger, Navid Nikaein
knopp's avatar
 
knopp committed
25 26 27
 * \date 2012
 * \version 0.1
 * \company Eurecom
28
 * \email: knopp@eurecom.fr,florian.kaltenberger@eurecom.fr, navid.nikaein@eurecom.fr
knopp's avatar
 
knopp committed
29 30 31
 * \note
 * \warning
 */
32 33

#include "lte-softmodem.h"
34

35 36
#include "T.h"

37
#include "rt_wrapper.h"
38

39
#include "../../ARCH/ETHERNET/USERSPACE/LIB/if_defs.h"
knopp's avatar
 
knopp committed
40

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

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

Florian Kaltenberger's avatar
 
Florian Kaltenberger committed
68 69 70 71
#ifndef OPENAIR2
#include "UTIL/OTG/otg_vars.h"
#endif

72
#if defined(ENABLE_ITTI)
73 74
#include "intertask_interface_init.h"
#include "create_tasks.h"
75 76
#endif

77 78
#include "system.h"

79 80 81 82
#ifdef XFORMS
#include "PHY/TOOLS/lte_phy_scope.h"
#include "stats.h"
// current status is that every UE has a DL scope for a SINGLE eNB (eNB_id=0)
gauthier's avatar
gauthier committed
83
// at eNB 0, an UL scope for every UE
84
FD_lte_phy_scope_ue  *form_ue[NUMBER_OF_UE_MAX];
85
FD_lte_phy_scope_enb *form_enb[MAX_NUM_CCs][NUMBER_OF_UE_MAX];
86
FD_stats_form                  *form_stats=NULL,*form_stats_l2=NULL;
87
char title[255];
88
unsigned char                   scope_enb_num_ue = 2;
89
static pthread_t                forms_thread; //xforms
90 91
#endif //XFORMS

knopp's avatar
 
knopp committed
92 93
pthread_cond_t sync_cond;
pthread_mutex_t sync_mutex;
94
int sync_var=-1; //!< protected by mutex \ref sync_mutex.
95

96 97
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
98

99
#if defined(ENABLE_ITTI)
100 101
volatile int             start_eNB = 0;
volatile int             start_UE = 0;
102
#endif
knopp's avatar
knopp committed
103
volatile int             oai_exit = 0;
104

105
static clock_source_t clock_source = internal;
106
static int wait_for_sync = 0;
knopp's avatar
 
knopp committed
107

knopp's avatar
knopp committed
108
static char              UE_flag=0;
109
unsigned int                    mmapped_dma=0;
110
int                             single_thread_flag=1;
111

112
static char                     threequarter_fs=0;
113

114
uint32_t                 downlink_frequency[MAX_NUM_CCs][4];
115
int32_t                  uplink_frequency_offset[MAX_NUM_CCs][4];
gauthier's avatar
gauthier committed
116

117

118
static char                    *conf_config_file_name = NULL;
119
#if defined(ENABLE_ITTI)
120
static char                    *itti_dump_file = NULL;
knopp's avatar
 
knopp committed
121 122
#endif

123
int UE_scan = 1;
124
int UE_scan_carrier = 0;
125 126
runmode_t mode = normal_txrx;

127 128
FILE *input_fd=NULL;

129

130 131
#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
132 133
double tx_gain[MAX_NUM_CCs][4] = {{20,0,0,0}};
double rx_gain[MAX_NUM_CCs][4] = {{110,0,0,0}};
134 135 136 137
#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
138
#endif
knopp's avatar
 
knopp committed
139

fnabet's avatar
fnabet committed
140
double rx_gain_off = 0.0;
141

knopp's avatar
 
knopp committed
142
double sample_rate=30.72e6;
143
double bw = 10.0e6;
144

145
static int                      tx_max_power[MAX_NUM_CCs]; /* =  {0,0}*/;
146

147 148
char   rf_config_file[1024];

Florian Kaltenberger's avatar
Florian Kaltenberger committed
149
int chain_offset=0;
150
int phy_test = 0;
151
uint8_t usim_test = 0;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
152

153 154 155
uint8_t dci_Format = 0;
uint8_t agregation_Level =0xFF;

156 157
uint8_t nb_antenna_tx = 1;
uint8_t nb_antenna_rx = 1;
158

knopp's avatar
 
knopp committed
159 160 161
char ref[128] = "internal";
char channels[128] = "0";

162
int                      rx_input_level_dBm;
163
static int                      online_log_messages=0;
164
#ifdef XFORMS
165
extern int                      otg_enabled;
166
static char                     do_forms=0;
167
#else
168
int                             otg_enabled;
169
#endif
knopp's avatar
 
knopp committed
170
//int                             number_of_cards =   1;
171

knopp's avatar
 
knopp committed
172
static LTE_DL_FRAME_PARMS      *frame_parms[MAX_NUM_CCs];
173 174 175
eNB_func_t node_function[MAX_NUM_CCs];
eNB_timing_t node_timing[MAX_NUM_CCs];
int16_t   node_synch_ref[MAX_NUM_CCs];
176

Florian Kaltenberger's avatar
Florian Kaltenberger committed
177
uint32_t target_dl_mcs = 28; //maximum allowed mcs
178
uint32_t target_ul_mcs = 20;
179
uint32_t timing_advance = 0;
180 181
uint8_t exit_missed_slots=1;
uint64_t num_missed_slots=0; // counter for the number of missed slots
182

183
int transmission_mode=1;
knopp's avatar
 
knopp committed
184

185
int16_t           glog_level         = LOG_INFO;
gauthier's avatar
 
gauthier committed
186
int16_t           glog_verbosity     = LOG_MED;
187
int16_t           hw_log_level       = LOG_INFO;
gauthier's avatar
 
gauthier committed
188
int16_t           hw_log_verbosity   = LOG_MED;
189
int16_t           phy_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
190
int16_t           phy_log_verbosity  = LOG_MED;
191
int16_t           mac_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
192
int16_t           mac_log_verbosity  = LOG_MED;
193
int16_t           rlc_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
194
int16_t           rlc_log_verbosity  = LOG_MED;
195
int16_t           pdcp_log_level     = LOG_INFO;
gauthier's avatar
 
gauthier committed
196
int16_t           pdcp_log_verbosity = LOG_MED;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
197
int16_t           rrc_log_level      = LOG_INFO;
gauthier's avatar
 
gauthier committed
198
int16_t           rrc_log_verbosity  = LOG_MED;
199 200 201
int16_t           opt_log_level      = LOG_INFO;
int16_t           opt_log_verbosity  = LOG_MED;

gauthier's avatar
 
gauthier committed
202 203 204 205 206 207
# 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
208 209 210
#if defined (ENABLE_SECURITY)
int16_t           osa_log_level      = LOG_INFO;
int16_t           osa_log_verbosity  = LOG_MED;
211
#endif
212

213 214
char *rrh_UE_ip = "127.0.0.1";
int rrh_UE_port = 51000;
knopp's avatar
knopp committed
215

216 217 218 219 220
/* 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;

221 222 223 224
openair0_config_t openair0_cfg[MAX_CARDS];

double cpuf;

knopp's avatar
 
knopp committed
225
char uecap_xer[1024],uecap_xer_in=0;
226

227
int oaisim_flag=0;
228
threads_t threads= {-1,-1,-1,-1,-1,-1,-1};
knopp's avatar
 
knopp committed
229

Cedric Roux's avatar
Cedric Roux committed
230 231 232 233
/* see file openair2/LAYER2/MAC/main.c for why abstraction_flag is needed
 * this is very hackish - find a proper solution
 */
uint8_t abstraction_flag=0;
knopp's avatar
 
knopp committed
234

235
/* override the enb configuration parameters */
236 237 238
static void reconfigure_enb_params(int enb_id);


239 240 241 242 243
/*---------------------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 };

244 245 246 247 248 249 250 251 252 253
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;
254 255
}

256
void print_difftimes(void) {
257
#ifdef DEBUG
258
    printf("difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
259
#else
260
    LOG_I(HW,"difftimes min = %lu ns ; max = %lu ns\n", min_diff_time.tv_nsec, max_diff_time.tv_nsec);
261 262 263
#endif
}

264 265 266 267 268 269 270 271 272 273 274 275
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;
    }
276
#if 1
277
    if (changed) print_difftimes();
278 279 280 281 282
#endif
}

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

283 284
unsigned int build_rflocal(int txi, int txq, int rxi, int rxq) {
    return (txi + (txq<<6) + (rxi<<12) + (rxq<<18));
285
}
286 287
unsigned int build_rfdc(int dcoff_i_rxfe, int dcoff_q_rxfe) {
    return (dcoff_i_rxfe + (dcoff_q_rxfe<<8));
288 289
}

290
#if !defined(ENABLE_ITTI)
291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306
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);

        // print out all the frames to stderr
        fprintf(stderr, "Error: signal %d:\n", sig);
        backtrace_symbols_fd(array, size, 2);
        exit(-1);
    } else {
        printf("trying to exit gracefully...\n");
        oai_exit = 1;
    }
307
}
308
#endif
nikaeinn's avatar
nikaeinn committed
309 310 311 312 313 314 315 316 317 318 319
#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");
320
  printf("  --rf-config-file Configuration file for front-end (e.g. LMS7002M)\n");
nikaeinn's avatar
nikaeinn committed
321 322 323 324
  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
325 326
  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
327
  printf("  --no-L2-connect bypass L2 and upper layers\n");
328
  printf("  --ue-rxgain set UE RX gain\n");
fnabet's avatar
fnabet committed
329
  printf("  --ue-rxgain-off external UE amplifier offset\n");
330
  printf("  --ue-txgain set UE TX gain\n");
Cedric Roux's avatar
Cedric Roux committed
331 332
  printf("  --ue-nb-ant-rx  set UE number of rx antennas\n");
  printf("  --ue-scan-carrier set UE to scan around carrier\n");
333
  printf("  --dlsch-demod-shift dynamic shift for LLR compuation for TM3/4 (default 0)\n");
334
  printf("  --loop-memory get softmodem (UE) to loop through memory instead of acquiring from HW\n");
335
  printf("  --mmapped-dma sets flag for improved EXMIMO UE performance\n");  
336
  printf("  --external-clock tells hardware to use an external clock reference\n");
337
  printf("  --usim-test use XOR autentication algo in case of test usim mode\n"); 
338
  printf("  --single-thread-disable. Disables single-thread mode in lte-softmodem\n"); 
339
  printf("  --AgregationLevel Choose the agregation level used by tghe eNB for the OAI use 1, it will save some time of processing the pdcch\n");
340
  printf("  --DCIformat choose the DCI format, be careful when using this option(for the moment only valid for SISO DCI format 1)\n");
341
  printf("  -A Set timing_advance\n");
342
  printf("  -C Set the downlink frequency for all component carriers\n");
nikaeinn's avatar
nikaeinn committed
343 344 345
  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");
346
  printf("  -G Set the global log verbosity \n");
nikaeinn's avatar
nikaeinn committed
347 348 349 350 351
  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
352
  printf("  -r Set the PRB, valid values: 6, 25, 50, 100  \n");    
nikaeinn's avatar
nikaeinn committed
353 354
  printf("  -S Skip the missed slots/subframes \n");    
  printf("  -t Set the maximum uplink MCS\n");
355
  printf("  -T Set hardware to TDD mode (default: FDD). Used only with -U (otherwise set in config file).\n");
nikaeinn's avatar
nikaeinn committed
356 357 358
  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");
359
  printf("  -x Set the transmission mode, valid options: 1 \n");
360
  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");
361
#if T_TRACER
362 363 364
    printf("  --T_port [port]    use given port\n");
    printf("  --T_nowait         don't wait for tracer, start immediately\n");
    printf("  --T_dont_fork      to ease debugging with gdb\n");
365
#endif
366 367
    printf(RESET);
    fflush(stdout);
nikaeinn's avatar
nikaeinn committed
368
}
369

370 371
void exit_fun(const char* s) {
    int CC_id;
Raymond Knopp's avatar
Raymond Knopp committed
372

373 374
    if (s != NULL) {
        printf("%s %s() Exiting OAI softmodem: %s\n",__FILE__, __FUNCTION__, s);
knopp's avatar
knopp committed
375
    }
376 377 378 379 380 381 382 383 384 385 386 387 388

    oai_exit = 1;

    for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
        if (UE_flag == 0) {
            if (PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func)
                PHY_vars_eNB_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->rfdevice);
            if (PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func)
                PHY_vars_eNB_g[0][CC_id]->ifdevice.trx_end_func(&PHY_vars_eNB_g[0][CC_id]->ifdevice);
        } else {
            if (PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func)
                PHY_vars_UE_g[0][CC_id]->rfdevice.trx_end_func(&PHY_vars_UE_g[0][CC_id]->rfdevice);
        }
knopp's avatar
knopp committed
389
    }
390 391

#if defined(ENABLE_ITTI)
392 393
    sleep(1); //allow lte-softmodem threads to exit first
    itti_terminate_tasks (TASK_UNKNOWN);
394
#endif
395 396 397

}

398

399
#ifdef XFORMS
400

401 402 403 404 405 406 407 408 409 410 411 412 413 414 415 416 417 418 419 420 421 422 423
void reset_stats(FL_OBJECT *button, long arg) {
    int i,j,k;
    PHY_VARS_eNB *phy_vars_eNB = PHY_vars_eNB_g[0][0];

    for (i=0; i<NUMBER_OF_UE_MAX; i++) {
        for (k=0; k<8; k++) { //harq_processes
            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;
            }

            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;

            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;
            }
        }
424

425 426 427
        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;
428 429 430
    }
}

431 432
static void *scope_thread(void *arg) {
    char stats_buffer[16384];
433
# ifdef ENABLE_XFORMS_WRITE_STATS
434
    FILE *UE_stats, *eNB_stats;
435
# endif
436 437 438 439
    int len = 0;
    struct sched_param sched_param;
    int UE_id, CC_id;
    int ue_cnt=0;
440

441 442
    sched_param.sched_priority = sched_get_priority_min(SCHED_FIFO)+1;
    sched_setscheduler(0, SCHED_FIFO,&sched_param);
443

444
    printf("Scope thread has priority %d\n",sched_param.sched_priority);
445

446
# ifdef ENABLE_XFORMS_WRITE_STATS
447

448 449 450 451
    if (UE_flag==1)
        UE_stats  = fopen("UE_stats.txt", "w");
    else
        eNB_stats = fopen("eNB_stats.txt", "w");
452

453
#endif
454

455 456 457 458 459 460
    while (!oai_exit) {
        if (UE_flag==1) {
            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);
            //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);
461

462 463 464 465
            phy_scope_UE(form_ue[0],
                         PHY_vars_UE_g[0][0],
                         0,
                         0,7);
466

467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494
        } else {
            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);
            }
            len = dump_eNB_stats (PHY_vars_eNB_g[0][0], stats_buffer, 0);

            if (MAX_NUM_CCs>1)
                len += dump_eNB_stats (PHY_vars_eNB_g[0][1], &stats_buffer[len], 0);

            //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);

            ue_cnt=0;
            for(UE_id=0; UE_id<NUMBER_OF_UE_MAX; UE_id++) {
                for(CC_id=0; CC_id<MAX_NUM_CCs; CC_id++) {
                    //	  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)) {
                        phy_scope_eNB(form_enb[CC_id][ue_cnt],
                                      PHY_vars_eNB_g[0][CC_id],
                                      UE_id);
                        ue_cnt++;
                    }
                }
            }
495

496
        }
497

498 499 500 501
        //printf("doing forms\n");
        //usleep(100000); // 100 ms
        sleep(1);
    }
502

503
    //  printf("%s",stats_buffer);
504

505
# ifdef ENABLE_XFORMS_WRITE_STATS
506

507 508 509 510 511 512 513 514 515 516 517 518
    if (UE_flag==1) {
        if (UE_stats) {
            rewind (UE_stats);
            fwrite (stats_buffer, 1, len, UE_stats);
            fclose (UE_stats);
        }
    } else {
        if (eNB_stats) {
            rewind (eNB_stats);
            fwrite (stats_buffer, 1, len, eNB_stats);
            fclose (eNB_stats);
        }
519
    }
520

521
# endif
522

523
    pthread_exit((void*)arg);
524 525 526
}
#endif

527

528

529

knopp's avatar
 
knopp committed
530
#if defined(ENABLE_ITTI)
531 532 533
void *l2l1_task(void *arg) {
    MessageDef *message_p = NULL;
    int         result;
knopp's avatar
 
knopp committed
534

535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 550 551 552 553 554 555 556
    itti_set_task_real_time(TASK_L2L1);
    itti_mark_task_ready(TASK_L2L1);

    if (UE_flag == 0) {
        /* Wait for the initialize message */
        printf("Wait for the ITTI initialize message\n");
        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);
            }

            itti_receive_msg (TASK_L2L1, &message_p);

            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;

            case TERMINATE_MESSAGE:
557
                LOG_W(TASK_L2L1, " *** Exiting L2L1 thread\n");
558 559 560 561 562 563 564 565 566
                oai_exit=1;
                itti_exit_task ();
                break;

            default:
                LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
                break;
            }
        } while (ITTI_MSG_ID(message_p) != INITIALIZE_MESSAGE);
567

568 569
        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
    }

572 573 574
    do {
        // Wait for a message
        itti_receive_msg (TASK_L2L1, &message_p);
knopp's avatar
 
knopp committed
575

576 577
        switch (ITTI_MSG_ID(message_p)) {
        case TERMINATE_MESSAGE:
578
            LOG_W(TASK_L2L1, " *** Exiting L2L1 thread\n");
579 580 581
            oai_exit=1;
            itti_exit_task ();
            break;
knopp's avatar
 
knopp committed
582

583 584 585
        case ACTIVATE_MESSAGE:
            start_UE = 1;
            break;
knopp's avatar
 
knopp committed
586

587 588 589
        case DEACTIVATE_MESSAGE:
            start_UE = 0;
            break;
590

591 592 593
        case MESSAGE_TEST:
            LOG_I(EMU, "Received %s\n", ITTI_MSG_NAME(message_p));
            break;
knopp's avatar
 
knopp committed
594

595 596 597 598
        default:
            LOG_E(EMU, "Received unexpected message %s\n", ITTI_MSG_NAME(message_p));
            break;
        }
knopp's avatar
 
knopp committed
599

600 601 602
        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);
603

604
    return NULL;
605 606 607
}
#endif

knopp's avatar
 
knopp committed
608 609


610 611 612 613 614 615

static void get_options (int argc, char **argv) {
    int c;
    //  char                          line[1000];
    //  int                           l;
    int k,i;//,j,k;
616
#if defined(OAI_USRP) || defined(CPRIGW)
617
    int clock_src;
knopp's avatar
 
knopp committed
618
#endif
619
    int CC_id;
knopp's avatar
 
knopp committed
620

621

622
  const Enb_properties_array_t *enb_properties;
623

624 625 626 627 628 629 630 631 632 633 634 635 636
    enum long_option_e {
        LONG_OPTION_START = 0x100, /* Start after regular single char options */
        LONG_OPTION_RF_CONFIG_FILE,
        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,
        LONG_OPTION_NO_L2_CONNECT,
        LONG_OPTION_CALIB_PRACH_TX,
        LONG_OPTION_RXGAIN,
        LONG_OPTION_RXGAINOFF,
        LONG_OPTION_TXGAIN,
637 638
	LONG_OPTION_NBRXANT,
	LONG_OPTION_NBTXANT,
639 640 641 642 643 644 645 646 647 648 649
        LONG_OPTION_SCANCARRIER,
        LONG_OPTION_MAXPOWER,
        LONG_OPTION_DUMP_FRAME,
        LONG_OPTION_LOOPMEMORY,
        LONG_OPTION_PHYTEST,
        LONG_OPTION_USIMTEST,
        LONG_OPTION_MMAPPED_DMA,
        LONG_OPTION_EXTERNAL_CLOCK,
        LONG_OPTION_WAIT_FOR_SYNC,
        LONG_OPTION_SINGLE_THREAD_DISABLE,
        LONG_OPTION_THREADIQ,
Bilel's avatar
Bilel committed
650 651 652
        LONG_OPTION_THREADONESUBFRAME,
        LONG_OPTION_THREADTWOSUBFRAME,
        LONG_OPTION_THREADTHREESUBFRAME,
653 654 655
        LONG_OPTION_THREADSLOT1PROCONE,
        LONG_OPTION_THREADSLOT1PROCTWO,
        LONG_OPTION_THREADSLOT1PROCTHREE,
656 657
        LONG_OPTION_DCIFORMAT,
        LONG_OPTION_AGREGATIONLEVEL,
658
        LONG_OPTION_DEMOD_SHIFT,
659
#if T_TRACER
660 661 662
        LONG_OPTION_T_PORT,
        LONG_OPTION_T_NOWAIT,
        LONG_OPTION_T_DONT_FORK,
663
#endif
664

665 666 667 668 669 670 671 672 673 674 675 676 677 678
    };

    static const struct option long_options[] = {
        {"rf-config-file",required_argument,  NULL, LONG_OPTION_RF_CONFIG_FILE},
        {"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},
        {"calib-prach-tx",   no_argument,        NULL, LONG_OPTION_CALIB_PRACH_TX},
        {"ue-rxgain",   required_argument,  NULL, LONG_OPTION_RXGAIN},
        {"ue-rxgain-off",   required_argument,  NULL, LONG_OPTION_RXGAINOFF},
        {"ue-txgain",   required_argument,  NULL, LONG_OPTION_TXGAIN},
679 680
     	{"ue-nb-ant-rx", required_argument,  NULL, LONG_OPTION_NBRXANT},
	    {"ue-nb-ant-tx", required_argument,  NULL, LONG_OPTION_NBTXANT},
681 682 683 684 685 686 687 688 689 690 691
        {"ue-scan-carrier",   no_argument,  NULL, LONG_OPTION_SCANCARRIER},
        {"ue-max-power",   required_argument,  NULL, LONG_OPTION_MAXPOWER},
        {"ue-dump-frame", no_argument, NULL, LONG_OPTION_DUMP_FRAME},
        {"loop-memory", required_argument, NULL, LONG_OPTION_LOOPMEMORY},
        {"phy-test", no_argument, NULL, LONG_OPTION_PHYTEST},
        {"usim-test", no_argument, NULL, LONG_OPTION_USIMTEST},
        {"mmapped-dma", no_argument, NULL, LONG_OPTION_MMAPPED_DMA},
        {"external-clock", no_argument, NULL, LONG_OPTION_EXTERNAL_CLOCK},
        {"wait-for-sync", no_argument, NULL, LONG_OPTION_WAIT_FOR_SYNC},
        {"single-thread-disable", no_argument, NULL, LONG_OPTION_SINGLE_THREAD_DISABLE},
        {"threadIQ",  required_argument, NULL, LONG_OPTION_THREADIQ},
Bilel's avatar
Bilel committed
692 693 694
        {"threadOneSubframe",  required_argument, NULL, LONG_OPTION_THREADONESUBFRAME},
        {"threadTwoSubframe",  required_argument, NULL, LONG_OPTION_THREADTWOSUBFRAME},
        {"threadThreeSubframe",  required_argument, NULL, LONG_OPTION_THREADTHREESUBFRAME},
695 696 697
        {"threadSlot1ProcOne",  required_argument, NULL, LONG_OPTION_THREADSLOT1PROCONE},
        {"threadSlot1ProcTwo",  required_argument, NULL, LONG_OPTION_THREADSLOT1PROCTWO},
        {"threadSlot1ProcThree",  required_argument, NULL, LONG_OPTION_THREADSLOT1PROCTHREE},
698 699
        {"DCIformat",  required_argument, NULL, LONG_OPTION_DCIFORMAT},
        {"AgregationLevel",  required_argument, NULL, LONG_OPTION_AGREGATIONLEVEL},
700
        {"dlsch-demod-shift", required_argument,  NULL, LONG_OPTION_DEMOD_SHIFT},
701
#if T_TRACER
702 703 704
        {"T_port",                 required_argument, 0, LONG_OPTION_T_PORT},
        {"T_nowait",               no_argument,       0, LONG_OPTION_T_NOWAIT},
        {"T_dont_fork",            no_argument,       0, LONG_OPTION_T_DONT_FORK},
705
#endif
706 707 708
    {NULL, 0, NULL, 0}
  };

709
  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) {
710
    switch (c) {
711
    case LONG_OPTION_RF_CONFIG_FILE:
712 713 714 715 716 717
      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 {
718 719
	printf("Configuration filename is too long\n");
	exit(-1);   
720 721
      }
      break;
722 723 724 725
    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];
726
      break;
727 728 729 730
    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;
731

732 733 734 735 736
    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;
737

738 739 740 741
    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
742
      break;
743

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

750 751 752
    case LONG_OPTION_DEBUG_UE_PRACH:
      mode = debug_prach;
      break;
753

754 755 756
    case LONG_OPTION_NO_L2_CONNECT:
      mode = no_L2_connect;
      break;
757

knopp's avatar
 
knopp committed
758 759
    case LONG_OPTION_CALIB_PRACH_TX:
      mode = calib_prach_tx;
Rohit Gupta's avatar
Rohit Gupta committed
760
      printf("Setting mode to calib_prach_tx (%d)\n",mode);
knopp's avatar
 
knopp committed
761 762
      break;

763
    case LONG_OPTION_RXGAIN:
764 765
      for (i=0; i<4; i++)
        rx_gain[0][i] = atof(optarg);
766

767
      break;
768

fnabet's avatar
fnabet committed
769 770 771 772
    case LONG_OPTION_RXGAINOFF:
      rx_gain_off = atof(optarg);
      break;

773 774 775
    case LONG_OPTION_TXGAIN:
      for (i=0; i<4; i++)
        tx_gain[0][i] = atof(optarg);
776

777
      break;
778 779 780 781 782 783
    case LONG_OPTION_NBRXANT:
    	nb_antenna_rx = atof(optarg);
    	break;
    case LONG_OPTION_NBTXANT:
    	nb_antenna_tx = atof(optarg);
    	break;
784 785 786 787 788
    case LONG_OPTION_SCANCARRIER:
      UE_scan_carrier=1;

      break;

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

795 796 797 798
    case LONG_OPTION_DUMP_FRAME:
      mode = rx_dump_frame;
      break;
      
799 800 801
    case LONG_OPTION_PHYTEST:
      phy_test = 1;
      break;
802

803 804 805
    case LONG_OPTION_USIMTEST:
        usim_test = 1;
      break;
806 807 808
    case LONG_OPTION_MMAPPED_DMA:
      mmapped_dma = 1;
      break;
knopp's avatar
knopp committed
809

810 811
    case LONG_OPTION_SINGLE_THREAD_DISABLE:
      single_thread_flag = 0;
knopp's avatar
knopp committed
812
      break;
813 814 815 816 817

    case LONG_OPTION_EXTERNAL_CLOCK:
      clock_source = external;
      break;

818 819 820 821
    case LONG_OPTION_WAIT_FOR_SYNC:
      wait_for_sync = 1;
      break;

822 823 824
    case LONG_OPTION_THREADIQ:
       threads.iq=atoi(optarg);
       break;
Bilel's avatar
Bilel committed
825 826
    case LONG_OPTION_THREADONESUBFRAME:
       threads.one=atoi(optarg);
827
       break;
Bilel's avatar
Bilel committed
828 829
    case LONG_OPTION_THREADTWOSUBFRAME:
       threads.two=atoi(optarg);
830
       break;
Bilel's avatar
Bilel committed
831 832 833
    case LONG_OPTION_THREADTHREESUBFRAME:
       threads.three=atoi(optarg);
    break;
834 835 836 837 838 839 840 841 842
    case LONG_OPTION_THREADSLOT1PROCONE:
       threads.slot1_proc_one=atoi(optarg);
       break;
    case LONG_OPTION_THREADSLOT1PROCTWO:
       threads.slot1_proc_two=atoi(optarg);
       break;
    case LONG_OPTION_THREADSLOT1PROCTHREE:
       threads.slot1_proc_three=atoi(optarg);
       break;
843 844 845 846 847 848
    case LONG_OPTION_DCIFORMAT:
        dci_Format = atoi(optarg);
       break;
    case LONG_OPTION_AGREGATIONLEVEL:
        agregation_Level = atoi(optarg);
        break;
849 850
    case LONG_OPTION_DEMOD_SHIFT: {
        extern int16_t dlsch_demod_shift;
851 852
        dlsch_demod_shift = atof(optarg);
        break;
853
    }
854
#if T_TRACER
855 856 857 858 859 860
        case LONG_OPTION_T_PORT: {
            extern int T_port;
            if (optarg == NULL) abort();  /* should not happen */
            T_port = atoi(optarg);
            break;
        }
861

862 863 864 865 866
        case LONG_OPTION_T_NOWAIT: {
            extern int T_wait;
            T_wait = 0;
            break;
        }
867

868 869 870 871 872
        case LONG_OPTION_T_DONT_FORK: {
            extern int T_dont_fork;
            T_dont_fork = 1;
            break;
        }
873 874
#endif

875 876 877
        case 'A':
            timing_advance = atoi (optarg);
            break;
878

879 880 881 882 883 884 885 886
        case 'C':
            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]);
            }
887

888
            UE_scan=0;
889

890
            break;
891

892 893 894
        case 'a':
            chain_offset = atoi(optarg);
            break;
Florian Kaltenberger's avatar
Florian Kaltenberger committed
895

896
        case 'd':
897
#ifdef XFORMS
898 899
            do_forms=1;
            printf("Running with XFORMS!\n");
knopp's avatar
 
knopp committed
900
#endif
901
            break;
902

903 904 905
        case 'E':
            threequarter_fs=1;
            break;
906

907
        case 'K':
908
#if defined(ENABLE_ITTI)
909
            itti_dump_file = strdup(optarg);
910
#else
911
            printf("-K option is disabled when ENABLE_ITTI is not defined\n");
knopp's avatar
 
knopp committed
912
#endif
913